home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / gdb-4.16-base.tgz / gdb-4.16-base.tar / fsf / gdb / bfd / nlm32-ppc.c < prev    next >
C/C++ Source or Header  |  1995-11-29  |  37KB  |  1,046 lines

  1. /* Support for 32-bit PowerPC NLM (NetWare Loadable Module)
  2.    Copyright (C) 1994, 1995 Free Software Foundation, Inc.
  3.  
  4. This file is part of BFD, the Binary File Descriptor library.
  5.  
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
  19.  
  20. #include "bfd.h"
  21. #include "sysdep.h"
  22. #include "libbfd.h"
  23.  
  24. /* The format of a PowerPC NLM changed.  Define OLDFORMAT to get the
  25.    old format.  */
  26.  
  27. #define ARCH_SIZE 32
  28.  
  29. #include "nlm/ppc-ext.h"
  30. #define Nlm_External_Fixed_Header    Nlm32_powerpc_External_Fixed_Header
  31.  
  32. #include "libnlm.h"
  33.  
  34. #ifdef OLDFORMAT
  35. static boolean nlm_powerpc_backend_object_p
  36.   PARAMS ((bfd *));
  37. static boolean nlm_powerpc_write_prefix
  38.   PARAMS ((bfd *));
  39. #endif
  40.  
  41. static boolean nlm_powerpc_read_reloc
  42.   PARAMS ((bfd *, nlmNAME(symbol_type) *, asection **, arelent *));
  43. static boolean nlm_powerpc_mangle_relocs
  44.   PARAMS ((bfd *, asection *, PTR, bfd_vma, bfd_size_type));
  45. static boolean nlm_powerpc_read_import
  46.   PARAMS ((bfd *, nlmNAME(symbol_type) *));
  47.  
  48. #ifdef OLDFORMAT
  49. static boolean nlm_powerpc_write_reloc
  50.   PARAMS ((bfd *, asection *, arelent *, int));
  51. #endif
  52.  
  53. static boolean nlm_powerpc_write_import
  54.   PARAMS ((bfd *, asection *, arelent *));
  55. static boolean nlm_powerpc_write_external
  56.   PARAMS ((bfd *, bfd_size_type, asymbol *, struct reloc_and_sec *));
  57.  
  58. #ifndef OLDFORMAT
  59. static boolean nlm_powerpc_set_public_section
  60.   PARAMS ((bfd *, nlmNAME(symbol_type) *));
  61. static bfd_vma nlm_powerpc_get_public_offset
  62.   PARAMS ((bfd *, asymbol *));
  63. #endif
  64.  
  65. #ifdef OLDFORMAT
  66.  
  67. /* The prefix header is only used in the old format.  */
  68.  
  69. /* PowerPC NLM's have a prefix header before the standard NLM.  This
  70.    function reads it in, verifies the version, and seeks the bfd to
  71.    the location before the regular NLM header.  */
  72.  
  73. static boolean
  74. nlm_powerpc_backend_object_p (abfd)
  75.      bfd *abfd;
  76. {
  77.   struct nlm32_powerpc_external_prefix_header s;
  78.  
  79.   if (bfd_read ((PTR) &s, sizeof s, 1, abfd) != sizeof s)
  80.     return false;
  81.  
  82.   if (memcmp (s.signature, NLM32_POWERPC_SIGNATURE, sizeof s.signature) != 0
  83.       || bfd_h_get_32 (abfd, s.headerVersion) != NLM32_POWERPC_HEADER_VERSION)
  84.     return false;
  85.  
  86.   return true;
  87. }
  88.  
  89. /* Write out the prefix.  */
  90.  
  91. static boolean
  92. nlm_powerpc_write_prefix (abfd)
  93.      bfd *abfd;
  94. {
  95.   struct nlm32_powerpc_external_prefix_header s;
  96.  
  97.   memset (&s, 0, sizeof s);
  98.   memcpy (s.signature, NLM32_POWERPC_SIGNATURE, sizeof s.signature);
  99.   bfd_h_put_32 (abfd, (bfd_vma) NLM32_POWERPC_HEADER_VERSION, s.headerVersion);
  100.   bfd_h_put_32 (abfd, (bfd_vma) 0, s.origins);
  101.  
  102.   /* FIXME: What should we do about the date?  */
  103.  
  104.   if (bfd_write ((PTR) &s, sizeof s, 1, abfd) != sizeof s)
  105.     return false;
  106.  
  107.   return true;
  108. }
  109.  
  110. #endif /* OLDFORMAT */
  111.  
  112. #ifndef OLDFORMAT
  113.  
  114. /* There is only one type of reloc in a PowerPC NLM.  */
  115.  
  116. static reloc_howto_type nlm_powerpc_howto =
  117.   HOWTO (0,            /* type */
  118.      0,            /* rightshift */
  119.      2,            /* size (0 = byte, 1 = short, 2 = long) */
  120.      32,            /* bitsize */
  121.      false,            /* pc_relative */
  122.      0,            /* bitpos */
  123.      complain_overflow_bitfield, /* complain_on_overflow */
  124.      0,            /* special_function */
  125.      "32",            /* name */
  126.      true,            /* partial_inplace */
  127.      0xffffffff,        /* src_mask */
  128.      0xffffffff,        /* dst_mask */
  129.      false);        /* pcrel_offset */
  130.  
  131. /* Read a PowerPC NLM reloc.  */
  132.  
  133. static boolean
  134. nlm_powerpc_read_reloc (abfd, sym, secp, rel)
  135.      bfd *abfd;
  136.      nlmNAME(symbol_type) *sym;
  137.      asection **secp;
  138.      arelent *rel;
  139. {
  140.   bfd_byte temp[4];
  141.   bfd_vma val;
  142.   const char *name;
  143.  
  144.   if (bfd_read (temp, sizeof (temp), 1, abfd) != sizeof (temp))
  145.     return false;
  146.  
  147.   val = bfd_get_32 (abfd, temp);
  148.  
  149.   /* The value is a word offset into either the code or data segment.
  150.      This is the location which needs to be adjusted.
  151.  
  152.      The high bit is 0 if the value is an offset into the data
  153.      segment, or 1 if the value is an offset into the text segment.
  154.  
  155.      If this is a relocation fixup rather than an imported symbol (the
  156.      sym argument is NULL), then the second most significant bit is 0
  157.      if the address of the data segment should be added to the
  158.      location addressed by the value, or 1 if the address of the text
  159.      segment should be added.
  160.  
  161.      If this is an imported symbol, the second most significant bit is
  162.      not used and must be 0.  */
  163.  
  164.   if ((val & NLM_HIBIT) == 0)
  165.     name = NLM_INITIALIZED_DATA_NAME;
  166.   else
  167.     {
  168.       name = NLM_CODE_NAME;
  169.       val &=~ NLM_HIBIT;
  170.     }
  171.   *secp = bfd_get_section_by_name (abfd, name);
  172.  
  173.   if (sym == NULL)
  174.     {
  175.       if ((val & (NLM_HIBIT >> 1)) == 0)
  176.     name = NLM_INITIALIZED_DATA_NAME;
  177.       else
  178.     {
  179.       name = NLM_CODE_NAME;
  180.       val &=~ (NLM_HIBIT >> 1);
  181.     }
  182.       rel->sym_ptr_ptr = bfd_get_section_by_name (abfd, name)->symbol_ptr_ptr;
  183.     }
  184.  
  185.   rel->howto = &nlm_powerpc_howto;
  186.  
  187.   rel->address = val << 2;
  188.   rel->addend = 0;
  189.  
  190.   return true;
  191. }
  192.  
  193. #else /* OLDFORMAT */
  194.  
  195. /* This reloc handling is only applicable to the old format.  */
  196.  
  197. /* How to process the various reloc types.  PowerPC NLMs use XCOFF
  198.    reloc types, and I have just copied the XCOFF reloc table here.  */
  199.  
  200. static reloc_howto_type nlm_powerpc_howto_table[] =
  201. {
  202.   /* Standard 32 bit relocation.  */
  203.   HOWTO (0,                    /* type */                                 
  204.      0,                    /* rightshift */                           
  205.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  206.      32,                    /* bitsize */                   
  207.      false,                    /* pc_relative */                          
  208.      0,                    /* bitpos */                               
  209.      complain_overflow_bitfield, /* complain_on_overflow */
  210.      0,                /* special_function */                     
  211.      "R_POS",               /* name */                                 
  212.      true,                    /* partial_inplace */                      
  213.      0xffffffff,            /* src_mask */                             
  214.      0xffffffff,            /* dst_mask */                             
  215.      false),                /* pcrel_offset */
  216.  
  217.   /* 32 bit relocation, but store negative value.  */
  218.   HOWTO (1,                    /* type */                                 
  219.      0,                    /* rightshift */                           
  220.      -2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  221.      32,                    /* bitsize */                   
  222.      false,                    /* pc_relative */                          
  223.      0,                    /* bitpos */                               
  224.      complain_overflow_bitfield, /* complain_on_overflow */
  225.      0,                /* special_function */                     
  226.      "R_NEG",               /* name */                                 
  227.      true,                    /* partial_inplace */                      
  228.      0xffffffff,            /* src_mask */                             
  229.      0xffffffff,            /* dst_mask */                             
  230.      false),                /* pcrel_offset */
  231.  
  232.   /* 32 bit PC relative relocation.  */
  233.   HOWTO (2,                    /* type */                                 
  234.      0,                    /* rightshift */                           
  235.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  236.      32,                    /* bitsize */                   
  237.      true,                    /* pc_relative */                          
  238.      0,                    /* bitpos */                               
  239.      complain_overflow_signed, /* complain_on_overflow */
  240.      0,                /* special_function */                     
  241.      "R_REL",               /* name */                                 
  242.      true,                    /* partial_inplace */                      
  243.      0xffffffff,            /* src_mask */                             
  244.      0xffffffff,            /* dst_mask */                             
  245.      false),                /* pcrel_offset */
  246.   
  247.   /* 16 bit TOC relative relocation.  */
  248.   HOWTO (3,                    /* type */                                 
  249.      0,                    /* rightshift */                           
  250.      1,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  251.      16,                    /* bitsize */                   
  252.      false,                    /* pc_relative */                          
  253.      0,                    /* bitpos */                               
  254.      complain_overflow_signed, /* complain_on_overflow */
  255.      0,                /* special_function */                     
  256.      "R_TOC",               /* name */                                 
  257.      true,                    /* partial_inplace */                      
  258.      0xffff,            /* src_mask */                             
  259.      0xffff,            /* dst_mask */                             
  260.      false),                /* pcrel_offset */
  261.   
  262.   /* I don't really know what this is.  */
  263.   HOWTO (4,                    /* type */                                 
  264.      1,                    /* rightshift */                           
  265.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  266.      32,                    /* bitsize */                   
  267.      false,                    /* pc_relative */                          
  268.      0,                    /* bitpos */                               
  269.      complain_overflow_bitfield, /* complain_on_overflow */
  270.      0,                /* special_function */                     
  271.      "R_RTB",               /* name */                                 
  272.      true,                    /* partial_inplace */                      
  273.      0xffffffff,            /* src_mask */                             
  274.      0xffffffff,            /* dst_mask */                             
  275.      false),                /* pcrel_offset */
  276.   
  277.   /* External TOC relative symbol.  */
  278.   HOWTO (5,                    /* type */                                 
  279.      0,                    /* rightshift */                           
  280.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  281.      16,                    /* bitsize */                   
  282.      false,                    /* pc_relative */                          
  283.      0,                    /* bitpos */                               
  284.      complain_overflow_bitfield, /* complain_on_overflow */
  285.      0,                /* special_function */                     
  286.      "R_GL",                /* name */                                 
  287.      true,                    /* partial_inplace */                      
  288.      0xffff,            /* src_mask */                             
  289.      0xffff,            /* dst_mask */                             
  290.      false),                /* pcrel_offset */
  291.   
  292.   /* Local TOC relative symbol.  */
  293.   HOWTO (6,                    /* type */                                 
  294.      0,                    /* rightshift */                           
  295.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  296.      16,                    /* bitsize */                   
  297.      false,                    /* pc_relative */                          
  298.      0,                    /* bitpos */                               
  299.      complain_overflow_bitfield, /* complain_on_overflow */
  300.      0,                /* special_function */                     
  301.      "R_TCL",               /* name */                                 
  302.      true,                    /* partial_inplace */                      
  303.      0xffff,            /* src_mask */                             
  304.      0xffff,            /* dst_mask */                             
  305.      false),                /* pcrel_offset */
  306.   
  307.   { 7 },
  308.   
  309.   /* Non modifiable absolute branch.  */
  310.   HOWTO (8,                    /* type */                                 
  311.      0,                    /* rightshift */                           
  312.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  313.      26,                    /* bitsize */                   
  314.      false,                    /* pc_relative */                          
  315.      0,                    /* bitpos */                               
  316.      complain_overflow_bitfield, /* complain_on_overflow */
  317.      0,                /* special_function */                     
  318.      "R_BA",                /* name */                                 
  319.      true,                    /* partial_inplace */                      
  320.      0x3fffffc,            /* src_mask */                             
  321.      0x3fffffc,            /* dst_mask */                             
  322.      false),                /* pcrel_offset */
  323.   
  324.   { 9 },
  325.  
  326.   /* Non modifiable relative branch.  */
  327.   HOWTO (0xa,                    /* type */                                 
  328.      0,                    /* rightshift */                           
  329.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  330.      26,                    /* bitsize */                   
  331.      true,                    /* pc_relative */                          
  332.      0,                    /* bitpos */                               
  333.      complain_overflow_signed, /* complain_on_overflow */
  334.      0,                /* special_function */                     
  335.      "R_BR",                /* name */                                 
  336.      true,                    /* partial_inplace */                      
  337.      0x3fffffc,            /* src_mask */                             
  338.      0x3fffffc,            /* dst_mask */                             
  339.      false),                /* pcrel_offset */
  340.   
  341.   { 0xb },
  342.  
  343.   /* Indirect load.  */
  344.   HOWTO (0xc,                    /* type */                                 
  345.      0,                    /* rightshift */                           
  346.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  347.      16,                    /* bitsize */                   
  348.      false,                    /* pc_relative */                          
  349.      0,                    /* bitpos */                               
  350.      complain_overflow_bitfield, /* complain_on_overflow */
  351.      0,                /* special_function */                     
  352.      "R_RL",                /* name */                                 
  353.      true,                    /* partial_inplace */                      
  354.      0xffff,            /* src_mask */                             
  355.      0xffff,            /* dst_mask */                             
  356.      false),                /* pcrel_offset */
  357.   
  358.   /* Load address.  */
  359.   HOWTO (0xd,                    /* type */                                 
  360.      0,                    /* rightshift */                           
  361.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  362.      16,                    /* bitsize */                   
  363.      false,                    /* pc_relative */                          
  364.      0,                    /* bitpos */                               
  365.      complain_overflow_bitfield, /* complain_on_overflow */
  366.      0,                /* special_function */                     
  367.      "R_RLA",               /* name */                                 
  368.      true,                    /* partial_inplace */                      
  369.      0xffff,            /* src_mask */                             
  370.      0xffff,            /* dst_mask */                             
  371.      false),                /* pcrel_offset */
  372.   
  373.   { 0xe },
  374.   
  375.   /* Non-relocating reference.  */
  376.   HOWTO (0xf,                    /* type */                                 
  377.      0,                    /* rightshift */                           
  378.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  379.      32,                    /* bitsize */                   
  380.      false,                    /* pc_relative */                          
  381.      0,                    /* bitpos */                               
  382.      complain_overflow_bitfield, /* complain_on_overflow */
  383.      0,                /* special_function */                     
  384.      "R_REF",               /* name */                                 
  385.      false,                    /* partial_inplace */                      
  386.      0,                /* src_mask */                             
  387.      0,                /* dst_mask */                             
  388.      false),                /* pcrel_offset */
  389.   
  390.   { 0x10 },
  391.   { 0x11 },
  392.   
  393.   /* TOC relative indirect load.  */
  394.   HOWTO (0x12,                    /* type */                                 
  395.      0,                    /* rightshift */                           
  396.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  397.      16,                    /* bitsize */                   
  398.      false,                    /* pc_relative */                          
  399.      0,                    /* bitpos */                               
  400.      complain_overflow_bitfield, /* complain_on_overflow */
  401.      0,                /* special_function */                     
  402.      "R_TRL",               /* name */                                 
  403.      true,                    /* partial_inplace */                      
  404.      0xffff,            /* src_mask */                             
  405.      0xffff,            /* dst_mask */                             
  406.      false),                /* pcrel_offset */
  407.   
  408.   /* TOC relative load address.  */
  409.   HOWTO (0x13,                    /* type */                                 
  410.      0,                    /* rightshift */                           
  411.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  412.      16,                    /* bitsize */                   
  413.      false,                    /* pc_relative */                          
  414.      0,                    /* bitpos */                               
  415.      complain_overflow_bitfield, /* complain_on_overflow */
  416.      0,                /* special_function */                     
  417.      "R_TRLA",              /* name */                                 
  418.      true,                    /* partial_inplace */                      
  419.      0xffff,            /* src_mask */                             
  420.      0xffff,            /* dst_mask */                             
  421.      false),                /* pcrel_offset */
  422.   
  423.   /* Modifiable relative branch.  */
  424.   HOWTO (0x14,                    /* type */                                 
  425.      1,                    /* rightshift */                           
  426.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  427.      32,                    /* bitsize */                   
  428.      false,                    /* pc_relative */                          
  429.      0,                    /* bitpos */                               
  430.      complain_overflow_bitfield, /* complain_on_overflow */
  431.      0,                /* special_function */                     
  432.      "R_RRTBI",             /* name */                                 
  433.      true,                    /* partial_inplace */                      
  434.      0xffffffff,            /* src_mask */                             
  435.      0xffffffff,            /* dst_mask */                             
  436.      false),                /* pcrel_offset */
  437.   
  438.   /* Modifiable absolute branch.  */
  439.   HOWTO (0x15,                    /* type */                                 
  440.      1,                    /* rightshift */                           
  441.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  442.      32,                    /* bitsize */                   
  443.      false,                    /* pc_relative */                          
  444.      0,                    /* bitpos */                               
  445.      complain_overflow_bitfield, /* complain_on_overflow */
  446.      0,                /* special_function */                     
  447.      "R_RRTBA",             /* name */                                 
  448.      true,                    /* partial_inplace */                      
  449.      0xffffffff,            /* src_mask */                             
  450.      0xffffffff,            /* dst_mask */                             
  451.      false),                /* pcrel_offset */
  452.   
  453.   /* Modifiable call absolute indirect.  */
  454.   HOWTO (0x16,                    /* type */                                 
  455.      0,                    /* rightshift */                           
  456.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  457.      16,                    /* bitsize */                   
  458.      false,                    /* pc_relative */                          
  459.      0,                    /* bitpos */                               
  460.      complain_overflow_bitfield, /* complain_on_overflow */
  461.      0,                /* special_function */                     
  462.      "R_CAI",               /* name */                                 
  463.      true,                    /* partial_inplace */                      
  464.      0xffff,            /* src_mask */                             
  465.      0xffff,            /* dst_mask */                             
  466.      false),                /* pcrel_offset */
  467.   
  468.   /* Modifiable call relative.  */
  469.   HOWTO (0x17,                    /* type */                                 
  470.      0,                    /* rightshift */                           
  471.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  472.      16,                    /* bitsize */                   
  473.      false,                    /* pc_relative */                          
  474.      0,                    /* bitpos */                               
  475.      complain_overflow_bitfield, /* complain_on_overflow */
  476.      0,                /* special_function */                     
  477.      "R_REL",               /* name */                                 
  478.      true,                    /* partial_inplace */                      
  479.      0xffff,            /* src_mask */                             
  480.      0xffff,            /* dst_mask */                             
  481.      false),                /* pcrel_offset */
  482.   
  483.   /* Modifiable branch absolute.  */
  484.   HOWTO (0x18,                    /* type */                                 
  485.      0,                    /* rightshift */                           
  486.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  487.      16,                    /* bitsize */                   
  488.      false,                    /* pc_relative */                          
  489.      0,                    /* bitpos */                               
  490.      complain_overflow_bitfield, /* complain_on_overflow */
  491.      0,                /* special_function */                     
  492.      "R_RBA",               /* name */                                 
  493.      true,                    /* partial_inplace */                      
  494.      0xffff,            /* src_mask */                             
  495.      0xffff,            /* dst_mask */                             
  496.      false),                /* pcrel_offset */
  497.   
  498.   /* Modifiable branch absolute.  */
  499.   HOWTO (0x19,                    /* type */                                 
  500.      0,                    /* rightshift */                           
  501.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  502.      16,                    /* bitsize */                   
  503.      false,                    /* pc_relative */                          
  504.      0,                    /* bitpos */                               
  505.      complain_overflow_bitfield, /* complain_on_overflow */
  506.      0,                /* special_function */                     
  507.      "R_RBAC",              /* name */                                 
  508.      true,                    /* partial_inplace */                      
  509.      0xffff,            /* src_mask */                             
  510.      0xffff,            /* dst_mask */                             
  511.      false),                /* pcrel_offset */
  512.   
  513.   /* Modifiable branch relative.  */
  514.   HOWTO (0x1a,                    /* type */                                 
  515.      0,                    /* rightshift */                           
  516.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  517.      26,                    /* bitsize */                   
  518.      false,                    /* pc_relative */                          
  519.      0,                    /* bitpos */                               
  520.      complain_overflow_signed, /* complain_on_overflow */
  521.      0,                /* special_function */                     
  522.      "R_REL",               /* name */                                 
  523.      true,                    /* partial_inplace */                      
  524.      0xffff,            /* src_mask */                             
  525.      0xffff,            /* dst_mask */                             
  526.      false),                /* pcrel_offset */
  527.   
  528.   /* Modifiable branch absolute.  */
  529.   HOWTO (0x1b,                    /* type */                                 
  530.      0,                    /* rightshift */                           
  531.      2,                    /* size (0 = byte, 1 = short, 2 = long) */ 
  532.      16,                    /* bitsize */                   
  533.      false,                    /* pc_relative */                          
  534.      0,                    /* bitpos */                               
  535.      complain_overflow_bitfield, /* complain_on_overflow */
  536.      0,                /* special_function */                     
  537.      "R_REL",               /* name */                                 
  538.      true,                    /* partial_inplace */                      
  539.      0xffff,            /* src_mask */                             
  540.      0xffff,            /* dst_mask */                             
  541.      false)                 /* pcrel_offset */
  542. };
  543.  
  544. #define HOWTO_COUNT (sizeof nlm_powerpc_howto_table        \
  545.              / sizeof nlm_powerpc_howto_table[0])
  546.  
  547. /* Read a PowerPC NLM reloc.  */
  548.  
  549. static boolean
  550. nlm_powerpc_read_reloc (abfd, sym, secp, rel)
  551.      bfd *abfd;
  552.      nlmNAME(symbol_type) *sym;
  553.      asection **secp;
  554.      arelent *rel;
  555. {
  556.   struct nlm32_powerpc_external_reloc ext;
  557.   bfd_vma l_vaddr;
  558.   unsigned long l_symndx;
  559.   int l_rtype;
  560.   int l_rsecnm;
  561.   asection *code_sec, *data_sec, *bss_sec;
  562.  
  563.   /* Read the reloc from the file.  */
  564.   if (bfd_read (&ext, sizeof ext, 1, abfd) != sizeof ext)
  565.     return false;
  566.  
  567.   /* Swap in the fields.  */
  568.   l_vaddr = bfd_h_get_32 (abfd, ext.l_vaddr);
  569.   l_symndx = bfd_h_get_32 (abfd, ext.l_symndx);
  570.   l_rtype = bfd_h_get_16 (abfd, ext.l_rtype);
  571.   l_rsecnm = bfd_h_get_16 (abfd, ext.l_rsecnm);
  572.  
  573.   /* Get the sections now, for convenience.  */
  574.   code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
  575.   data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
  576.   bss_sec = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
  577.  
  578.   /* Work out the arelent fields.  */
  579.   if (sym != NULL)
  580.     {
  581.       /* This is an import.  sym_ptr_ptr is filled in by
  582.      nlm_canonicalize_reloc.  */
  583.       rel->sym_ptr_ptr = NULL;
  584.     }
  585.   else
  586.     {
  587.       asection *sec;
  588.  
  589.       if (l_symndx == 0)
  590.     sec = code_sec;
  591.       else if (l_symndx == 1)
  592.     sec = data_sec;
  593.       else if (l_symndx == 2)
  594.     sec = bss_sec;
  595.       else
  596.     {
  597.       bfd_set_error (bfd_error_bad_value);
  598.       return false;
  599.     }
  600.  
  601.       rel->sym_ptr_ptr = sec->symbol_ptr_ptr;
  602.     }
  603.  
  604.   rel->addend = 0;
  605.  
  606.   BFD_ASSERT ((l_rtype & 0xff) < HOWTO_COUNT);
  607.  
  608.   rel->howto = nlm_powerpc_howto_table + (l_rtype & 0xff);
  609.  
  610.   BFD_ASSERT (rel->howto->name != NULL
  611.           && ((l_rtype & 0x8000) != 0
  612.           ? (rel->howto->complain_on_overflow
  613.              == complain_overflow_signed)
  614.           : (rel->howto->complain_on_overflow
  615.              == complain_overflow_bitfield))
  616.           && ((l_rtype >> 8) & 0x1f) == rel->howto->bitsize - 1);
  617.  
  618.   if (l_rsecnm == 0)
  619.     *secp = code_sec;
  620.   else if (l_rsecnm == 1)
  621.     {
  622.       *secp = data_sec;
  623.       l_vaddr -= bfd_section_size (abfd, code_sec);
  624.     }
  625.   else
  626.     {
  627.       bfd_set_error (bfd_error_bad_value);
  628.       return false;
  629.     }
  630.  
  631.   rel->address = l_vaddr;
  632.  
  633.   return true;
  634. }
  635.  
  636. #endif /* OLDFORMAT */
  637.  
  638. /* Mangle PowerPC NLM relocs for output.  */
  639.  
  640. static boolean
  641. nlm_powerpc_mangle_relocs (abfd, sec, data, offset, count)
  642.      bfd *abfd;
  643.      asection *sec;
  644.      PTR data;
  645.      bfd_vma offset;
  646.      bfd_size_type count;
  647. {
  648.   return true;
  649. }
  650.  
  651. /* Read a PowerPC NLM import record */
  652.  
  653. static boolean
  654. nlm_powerpc_read_import (abfd, sym)
  655.      bfd *abfd;
  656.      nlmNAME(symbol_type) *sym;
  657. {
  658.   struct nlm_relent *nlm_relocs;    /* relocation records for symbol */
  659.   bfd_size_type rcount;            /* number of relocs */
  660.   bfd_byte temp[NLM_TARGET_LONG_SIZE];    /* temporary 32-bit value */
  661.   unsigned char symlength;        /* length of symbol name */
  662.   char *name;
  663.  
  664.   if (bfd_read ((PTR) &symlength, sizeof (symlength), 1, abfd)
  665.       != sizeof (symlength))
  666.     return (false);
  667.   sym -> symbol.the_bfd = abfd;
  668.   name = bfd_alloc (abfd, symlength + 1);
  669.   if (name == NULL)
  670.     return false;
  671.   if (bfd_read (name, symlength, 1, abfd) != symlength)
  672.     return (false);
  673.   name[symlength] = '\0';
  674.   sym -> symbol.name = name;
  675.   sym -> symbol.flags = 0;
  676.   sym -> symbol.value = 0;
  677.   sym -> symbol.section = bfd_und_section_ptr;
  678.   if (bfd_read ((PTR) temp, sizeof (temp), 1, abfd) != sizeof (temp))
  679.     return (false);
  680.   rcount = bfd_h_get_32 (abfd, temp);
  681.   nlm_relocs = ((struct nlm_relent *)
  682.         bfd_alloc (abfd, rcount * sizeof (struct nlm_relent)));
  683.   if (nlm_relocs == (struct nlm_relent *) NULL)
  684.     return false;
  685.   sym -> relocs = nlm_relocs;
  686.   sym -> rcnt = 0;
  687.   while (sym -> rcnt < rcount)
  688.     {
  689.       asection *section;
  690.       
  691.       if (nlm_powerpc_read_reloc (abfd, sym, §ion,
  692.                   &nlm_relocs -> reloc)
  693.       == false)
  694.     return false;
  695.       nlm_relocs -> section = section;
  696.       nlm_relocs++;
  697.       sym -> rcnt++;
  698.     }
  699.   return true;
  700. }
  701.  
  702. #ifndef OLDFORMAT
  703.  
  704. /* Write a PowerPC NLM reloc.  */
  705.  
  706. static boolean
  707. nlm_powerpc_write_import (abfd, sec, rel)
  708.      bfd *abfd;
  709.      asection *sec;
  710.      arelent *rel;
  711. {
  712.   asymbol *sym;
  713.   bfd_vma val;
  714.   bfd_byte temp[4];
  715.  
  716.   /* PowerPC NetWare only supports one kind of reloc.  */
  717.   if (rel->addend != 0
  718.       || rel->howto == NULL
  719.       || rel->howto->rightshift != 0
  720.       || rel->howto->size != 2
  721.       || rel->howto->bitsize != 32
  722.       || rel->howto->bitpos != 0
  723.       || rel->howto->pc_relative
  724.       || (rel->howto->src_mask != 0xffffffff && rel->addend != 0)
  725.       || rel->howto->dst_mask != 0xffffffff)
  726.     {
  727.       bfd_set_error (bfd_error_invalid_operation);
  728.       return false;
  729.     }
  730.  
  731.   sym = *rel->sym_ptr_ptr;
  732.  
  733.   /* The value we write out is the offset into the appropriate
  734.      segment, rightshifted by two.  This offset is the section vma,
  735.      adjusted by the vma of the lowest section in that segment, plus
  736.      the address of the relocation.  */
  737.   val = bfd_get_section_vma (abfd, sec) + rel->address;
  738.   if ((val & 3) != 0)
  739.     {
  740.       bfd_set_error (bfd_error_bad_value);
  741.       return false;
  742.     }
  743.   val >>= 2;
  744.  
  745.   /* The high bit is 0 if the reloc is in the data section, or 1 if
  746.      the reloc is in the code section.  */
  747.   if (bfd_get_section_flags (abfd, sec) & SEC_DATA)
  748.     val -= nlm_get_data_low (abfd);
  749.   else
  750.     {
  751.       val -= nlm_get_text_low (abfd);
  752.       val |= NLM_HIBIT;
  753.     }
  754.     
  755.   if (! bfd_is_und_section (bfd_get_section (sym)))
  756.     {
  757.       /* This is an internal relocation fixup.  The second most
  758.      significant bit is 0 if this is a reloc against the data
  759.      segment, or 1 if it is a reloc against the text segment.  */
  760.       if (bfd_get_section_flags (abfd, bfd_get_section (sym)) & SEC_CODE)
  761.     val |= NLM_HIBIT >> 1;
  762.     }
  763.  
  764.   bfd_put_32 (abfd, val, temp);
  765.   if (bfd_write (temp, sizeof (temp), 1, abfd) != sizeof (temp))
  766.     return false;
  767.  
  768.   return true;
  769. }
  770.  
  771. #else /* OLDFORMAT */
  772.  
  773. /* This is used for the reloc handling in the old format.  */
  774.  
  775. /* Write a PowerPC NLM reloc.  */
  776.  
  777. static boolean
  778. nlm_powerpc_write_reloc (abfd, sec, rel, indx)
  779.      bfd *abfd;
  780.      asection *sec;
  781.      arelent *rel;
  782.      int indx;
  783. {
  784.   struct nlm32_powerpc_external_reloc ext;
  785.   asection *code_sec, *data_sec, *bss_sec;
  786.   asymbol *sym;
  787.   asection *symsec;
  788.   unsigned long l_symndx;
  789.   int l_rtype;
  790.   int l_rsecnm;
  791.   reloc_howto_type *howto;
  792.   bfd_size_type address;
  793.  
  794.   /* Get the sections now, for convenience.  */
  795.   code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
  796.   data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
  797.   bss_sec = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
  798.  
  799.   sym = *rel->sym_ptr_ptr;
  800.   symsec = bfd_get_section (sym);
  801.   if (indx != -1)
  802.     {
  803.       BFD_ASSERT (bfd_is_und_section (symsec));
  804.       l_symndx = indx + 3;
  805.     }
  806.   else
  807.     {
  808.       if (symsec == code_sec)
  809.     l_symndx = 0;
  810.       else if (symsec == data_sec)
  811.     l_symndx = 1;
  812.       else if (symsec == bss_sec)
  813.     l_symndx = 2;
  814.       else
  815.     {
  816.       bfd_set_error (bfd_error_bad_value);
  817.       return false;
  818.     }
  819.     }
  820.  
  821.   bfd_h_put_32 (abfd, (bfd_vma) l_symndx, ext.l_symndx);
  822.  
  823.   for (howto = nlm_powerpc_howto_table;
  824.        howto < nlm_powerpc_howto_table + HOWTO_COUNT;
  825.        howto++)
  826.     {
  827.       if (howto->rightshift == rel->howto->rightshift
  828.       && howto->size == rel->howto->size
  829.       && howto->bitsize == rel->howto->bitsize
  830.       && howto->pc_relative == rel->howto->pc_relative
  831.       && howto->bitpos == rel->howto->bitpos
  832.       && (howto->partial_inplace == rel->howto->partial_inplace
  833.           || (! rel->howto->partial_inplace
  834.           && rel->addend == 0))
  835.       && (howto->src_mask == rel->howto->src_mask
  836.           || (rel->howto->src_mask == 0
  837.           && rel->addend == 0))
  838.       && howto->dst_mask == rel->howto->dst_mask
  839.       && howto->pcrel_offset == rel->howto->pcrel_offset)
  840.     break;
  841.     }
  842.   if (howto >= nlm_powerpc_howto_table + HOWTO_COUNT)
  843.     {
  844.       bfd_set_error (bfd_error_bad_value);
  845.       return false;
  846.     }
  847.  
  848.   l_rtype = howto->type;
  849.   if (howto->complain_on_overflow == complain_overflow_signed)
  850.     l_rtype |= 0x8000;
  851.   l_rtype |= (howto->bitsize - 1) << 8;
  852.   bfd_h_put_16 (abfd, (bfd_vma) l_rtype, ext.l_rtype);
  853.  
  854.   address = rel->address;
  855.  
  856.   if (sec == code_sec)
  857.     l_rsecnm = 0;
  858.   else if (sec == data_sec)
  859.     {
  860.       l_rsecnm = 1;
  861.       address += bfd_section_size (abfd, code_sec);
  862.     }
  863.   else
  864.     {
  865.       bfd_set_error (bfd_error_bad_value);
  866.       return false;
  867.     }
  868.  
  869.   bfd_h_put_16 (abfd, (bfd_vma) l_rsecnm, ext.l_rsecnm);
  870.   bfd_h_put_32 (abfd, (bfd_vma) address, ext.l_vaddr);
  871.  
  872.   if (bfd_write (&ext, sizeof ext, 1, abfd) != sizeof ext)
  873.     return false;
  874.  
  875.   return true;
  876. }
  877.  
  878. /* Write a PowerPC NLM import.  */
  879.  
  880. static boolean
  881. nlm_powerpc_write_import (abfd, sec, rel)
  882.      bfd *abfd;
  883.      asection *sec;
  884.      arelent *rel;
  885. {
  886.   return nlm_powerpc_write_reloc (abfd, sec, rel, -1);
  887. }
  888.  
  889. #endif /* OLDFORMAT */
  890.  
  891. /* Write a PowerPC NLM external symbol.  This routine keeps a static
  892.    count of the symbol index.  FIXME: I don't know if this is
  893.    necessary, and the index never gets reset.  */
  894.  
  895. static boolean
  896. nlm_powerpc_write_external (abfd, count, sym, relocs)
  897.      bfd *abfd;
  898.      bfd_size_type count;
  899.      asymbol *sym;
  900.      struct reloc_and_sec *relocs;
  901. {
  902.   unsigned int i;
  903.   bfd_byte len;
  904.   unsigned char temp[NLM_TARGET_LONG_SIZE];
  905. #ifdef OLDFORMAT
  906.   static int indx;
  907. #endif
  908.  
  909.   len = strlen (sym->name);
  910.   if ((bfd_write (&len, sizeof (bfd_byte), 1, abfd) != sizeof(bfd_byte))
  911.       || bfd_write (sym->name, len, 1, abfd) != len)
  912.     return false;
  913.  
  914.   bfd_put_32 (abfd, count, temp);
  915.   if (bfd_write (temp, sizeof(temp), 1, abfd) != sizeof (temp))
  916.     return false;
  917.  
  918.   for (i = 0; i < count; i++)
  919.     {
  920. #ifndef OLDFORMAT
  921.       if (! nlm_powerpc_write_import (abfd, relocs[i].sec, relocs[i].rel))
  922.     return false;
  923. #else
  924.       if (! nlm_powerpc_write_reloc (abfd, relocs[i].sec,
  925.                      relocs[i].rel, indx))
  926.     return false;
  927. #endif
  928.     }
  929.  
  930. #ifdef OLDFORMAT
  931.   ++indx;
  932. #endif
  933.  
  934.   return true;
  935. }
  936.  
  937. #ifndef OLDFORMAT
  938.  
  939. /* PowerPC Netware uses a word offset, not a byte offset, for public
  940.    symbols.  */
  941.  
  942. /* Set the section for a public symbol.  */
  943.  
  944. static boolean
  945. nlm_powerpc_set_public_section (abfd, sym)
  946.      bfd *abfd;
  947.      nlmNAME(symbol_type) *sym;
  948. {
  949.   if (sym->symbol.value & NLM_HIBIT)
  950.     {
  951.       sym->symbol.value &= ~NLM_HIBIT;
  952.       sym->symbol.flags |= BSF_FUNCTION;
  953.       sym->symbol.section =
  954.     bfd_get_section_by_name (abfd, NLM_CODE_NAME);
  955.     }
  956.   else
  957.     {
  958.       sym->symbol.section =
  959.     bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
  960.     }
  961.  
  962.   sym->symbol.value <<= 2;
  963.  
  964.   return true;
  965. }
  966.  
  967. /* Get the offset to write out for a public symbol.  */
  968.  
  969. static bfd_vma
  970. nlm_powerpc_get_public_offset (abfd, sym)
  971.      bfd *abfd;
  972.      asymbol *sym;
  973. {
  974.   bfd_vma offset;
  975.   asection *sec;
  976.  
  977.   offset = bfd_asymbol_value (sym);
  978.   sec = bfd_get_section (sym);
  979.   if (sec->flags & SEC_CODE)
  980.     {
  981.       offset -= nlm_get_text_low (abfd);
  982.       offset |= NLM_HIBIT;
  983.     }
  984.   else if (sec->flags & (SEC_DATA | SEC_ALLOC))
  985.     {
  986.       /* SEC_ALLOC is for the .bss section.  */
  987.       offset -= nlm_get_data_low (abfd);
  988.     }
  989.   else
  990.     {
  991.       /* We can't handle an exported symbol that is not in the code or
  992.      data segment.  */
  993.       bfd_set_error (bfd_error_invalid_operation);
  994.       /* FIXME: No way to return error.  */
  995.       abort ();
  996.     }
  997.  
  998.   return offset;
  999. }
  1000.  
  1001. #endif /* ! defined (OLDFORMAT) */
  1002.  
  1003. #include "nlmswap.h"
  1004.  
  1005. static const struct nlm_backend_data nlm32_powerpc_backend =
  1006. {
  1007.   "NetWare PowerPC Module \032",
  1008.   sizeof (Nlm32_powerpc_External_Fixed_Header),
  1009. #ifndef OLDFORMAT
  1010.   0,    /* optional_prefix_size */
  1011. #else
  1012.   sizeof (struct nlm32_powerpc_external_prefix_header),
  1013. #endif
  1014.   bfd_arch_powerpc,
  1015.   0,
  1016.   false,
  1017. #ifndef OLDFORMAT
  1018.   0,    /* backend_object_p */
  1019.   0,    /* write_prefix */
  1020. #else
  1021.   nlm_powerpc_backend_object_p,
  1022.   nlm_powerpc_write_prefix,
  1023. #endif
  1024.   nlm_powerpc_read_reloc,
  1025.   nlm_powerpc_mangle_relocs,
  1026.   nlm_powerpc_read_import,
  1027.   nlm_powerpc_write_import,
  1028. #ifndef OLDFORMAT
  1029.   nlm_powerpc_set_public_section,
  1030.   nlm_powerpc_get_public_offset,
  1031. #else
  1032.   0,    /* set_public_section */
  1033.   0,    /* get_public_offset */
  1034. #endif
  1035.   nlm_swap_fixed_header_in,
  1036.   nlm_swap_fixed_header_out,
  1037.   nlm_powerpc_write_external,
  1038.   0,    /* write_export */
  1039. };
  1040.  
  1041. #define TARGET_BIG_NAME            "nlm32-powerpc"
  1042. #define TARGET_BIG_SYM            nlmNAME(powerpc_vec)
  1043. #define TARGET_BACKEND_DATA        &nlm32_powerpc_backend
  1044.  
  1045. #include "nlm-target.h"
  1046.