Home | History | Annotate | Download | only in bfd
      1 /* Support for 32-bit SPARC NLM (NetWare Loadable Module)
      2    Copyright (C) 1993-2016 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
     19    MA 02110-1301, USA.  */
     20 
     21 #include "sysdep.h"
     22 #include "bfd.h"
     23 #include "libbfd.h"
     24 
     25 #define ARCH_SIZE 32
     26 
     27 #include "nlm/sparc32-ext.h"
     28 #define Nlm_External_Fixed_Header	Nlm32_sparc_External_Fixed_Header
     29 
     30 #include "libnlm.h"
     31 
     32 enum reloc_type
     33 {
     34   R_SPARC_NONE = 0,
     35   R_SPARC_8,		R_SPARC_16,		R_SPARC_32,
     36   R_SPARC_DISP8,	R_SPARC_DISP16,		R_SPARC_DISP32,
     37   R_SPARC_WDISP30,	R_SPARC_WDISP22,
     38   R_SPARC_HI22,		R_SPARC_22,
     39   R_SPARC_13,		R_SPARC_LO10,
     40   R_SPARC_GOT10,	R_SPARC_GOT13,		R_SPARC_GOT22,
     41   R_SPARC_PC10,		R_SPARC_PC22,
     42   R_SPARC_WPLT30,
     43   R_SPARC_COPY,
     44   R_SPARC_GLOB_DAT,	R_SPARC_JMP_SLOT,
     45   R_SPARC_RELATIVE,
     46   R_SPARC_UA32,
     47   R_SPARC_max
     48 };
     49 
     50 static reloc_howto_type nlm32_sparc_howto_table[] =
     51 {
     52   HOWTO (R_SPARC_NONE,    0,3, 0,FALSE,0,complain_overflow_dont,    0,"R_SPARC_NONE",    FALSE,0,0x00000000,TRUE),
     53   HOWTO (R_SPARC_8,       0,0, 8,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_8",       FALSE,0,0x000000ff,TRUE),
     54   HOWTO (R_SPARC_16,      0,1,16,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_16",      FALSE,0,0x0000ffff,TRUE),
     55   HOWTO (R_SPARC_32,      0,2,32,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_32",      FALSE,0,0xffffffff,TRUE),
     56   HOWTO (R_SPARC_DISP8,   0,0, 8,TRUE, 0,complain_overflow_signed,  0,"R_SPARC_DISP8",   FALSE,0,0x000000ff,TRUE),
     57   HOWTO (R_SPARC_DISP16,  0,1,16,TRUE, 0,complain_overflow_signed,  0,"R_SPARC_DISP16",  FALSE,0,0x0000ffff,TRUE),
     58   HOWTO (R_SPARC_DISP32,  0,2,32,TRUE, 0,complain_overflow_signed,  0,"R_SPARC_DISP32",  FALSE,0,0x00ffffff,TRUE),
     59   HOWTO (R_SPARC_WDISP30, 2,2,30,TRUE, 0,complain_overflow_signed,  0,"R_SPARC_WDISP30", FALSE,0,0x3fffffff,TRUE),
     60   HOWTO (R_SPARC_WDISP22, 2,2,22,TRUE, 0,complain_overflow_signed,  0,"R_SPARC_WDISP22", FALSE,0,0x003fffff,TRUE),
     61   HOWTO (R_SPARC_HI22,   10,2,22,FALSE,0,complain_overflow_dont,    0,"R_SPARC_HI22",    FALSE,0,0x003fffff,TRUE),
     62   HOWTO (R_SPARC_22,      0,2,22,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_22",      FALSE,0,0x003fffff,TRUE),
     63   HOWTO (R_SPARC_13,      0,2,13,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_13",      FALSE,0,0x00001fff,TRUE),
     64   HOWTO (R_SPARC_LO10,    0,2,10,FALSE,0,complain_overflow_dont,    0,"R_SPARC_LO10",    FALSE,0,0x000003ff,TRUE),
     65   HOWTO (R_SPARC_GOT10,   0,2,10,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_GOT10",   FALSE,0,0x000003ff,TRUE),
     66   HOWTO (R_SPARC_GOT13,   0,2,13,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_GOT13",   FALSE,0,0x00001fff,TRUE),
     67   HOWTO (R_SPARC_GOT22,  10,2,22,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_GOT22",   FALSE,0,0x003fffff,TRUE),
     68   HOWTO (R_SPARC_PC10,    0,2,10,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_PC10",    FALSE,0,0x000003ff,TRUE),
     69   HOWTO (R_SPARC_PC22,    0,2,22,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_PC22",    FALSE,0,0x003fffff,TRUE),
     70   HOWTO (R_SPARC_WPLT30,  0,0,00,FALSE,0,complain_overflow_dont,    0,"R_SPARC_WPLT30",  FALSE,0,0x00000000,TRUE),
     71   HOWTO (R_SPARC_COPY,    0,0,00,FALSE,0,complain_overflow_dont,    0,"R_SPARC_COPY",    FALSE,0,0x00000000,TRUE),
     72   HOWTO (R_SPARC_GLOB_DAT,0,0,00,FALSE,0,complain_overflow_dont,    0,"R_SPARC_GLOB_DAT",FALSE,0,0x00000000,TRUE),
     73   HOWTO (R_SPARC_JMP_SLOT,0,0,00,FALSE,0,complain_overflow_dont,    0,"R_SPARC_JMP_SLOT",FALSE,0,0x00000000,TRUE),
     74   HOWTO (R_SPARC_RELATIVE,0,0,00,FALSE,0,complain_overflow_dont,    0,"R_SPARC_RELATIVE",FALSE,0,0x00000000,TRUE),
     75   HOWTO (R_SPARC_UA32,    0,0,00,FALSE,0,complain_overflow_dont,    0,"R_SPARC_UA32",    FALSE,0,0x00000000,TRUE),
     76 };
     77 
     78 /* Read a NetWare sparc reloc.  */
     79 
     80 struct nlm32_sparc_reloc_ext
     81 {
     82   unsigned char offset[4];
     83   unsigned char addend[4];
     84   unsigned char type[1];
     85   unsigned char pad1[3];
     86 };
     87 
     88 static bfd_boolean
     89 nlm_sparc_read_reloc (bfd *abfd,
     90 		      nlmNAME (symbol_type) *sym ATTRIBUTE_UNUSED,
     91 		      asection **secp,
     92 		      arelent *rel)
     93 {
     94   bfd_vma val, addend;
     95   unsigned int howto_index;
     96   unsigned int type;
     97   struct nlm32_sparc_reloc_ext tmp_reloc;
     98   asection *code_sec;
     99 
    100   if (bfd_bread (&tmp_reloc, (bfd_size_type) 12, abfd) != 12)
    101     return FALSE;
    102 
    103   code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
    104   *secp = code_sec;
    105 
    106   val = bfd_get_32 (abfd, tmp_reloc.offset);
    107   addend = bfd_get_32 (abfd, tmp_reloc.addend);
    108   type = bfd_get_8 (abfd, tmp_reloc.type);
    109 
    110   rel->address = val;
    111   rel->addend = addend;
    112   rel->howto = NULL;
    113 
    114   for (howto_index = 0;
    115        howto_index < sizeof (nlm32_sparc_howto_table) / sizeof (reloc_howto_type);
    116        howto_index++)
    117     if (nlm32_sparc_howto_table[howto_index].type == type)
    118       {
    119 	rel->howto = &nlm32_sparc_howto_table[howto_index];
    120 	break;
    121       }
    122 
    123 #ifdef DEBUG
    124   fprintf (stderr, "%s:  address = %08lx, addend = %08lx, type = %u, howto = %p\n",
    125 	   __FUNCTION__, (unsigned long) rel->address,
    126 	   (unsigned long) rel->addend, type, rel->howto);
    127 #endif
    128   return TRUE;
    129 
    130 }
    131 
    132 /* Write a NetWare sparc reloc.  */
    133 
    134 static bfd_boolean
    135 nlm_sparc_write_reloc (bfd * abfd, asection * sec, arelent * rel)
    136 {
    137   bfd_vma val;
    138   struct nlm32_sparc_reloc_ext tmp_reloc;
    139   unsigned int howto_index;
    140   int type = -1;
    141   reloc_howto_type *tmp;
    142 
    143   for (howto_index = 0;
    144        howto_index < sizeof (nlm32_sparc_howto_table) / sizeof (reloc_howto_type);
    145        howto_index++)
    146     {
    147       tmp = &nlm32_sparc_howto_table[howto_index];
    148 
    149       if (tmp->rightshift == rel->howto->rightshift
    150 	  && tmp->size == rel->howto->size
    151 	  && tmp->bitsize == rel->howto->bitsize
    152 	  && tmp->pc_relative == rel->howto->pc_relative
    153 	  && tmp->bitpos == rel->howto->bitpos
    154 	  && tmp->src_mask == rel->howto->src_mask
    155 	  && tmp->dst_mask == rel->howto->dst_mask)
    156 	{
    157 	  type = tmp->type;
    158 	  break;
    159 	}
    160     }
    161   if (type == -1)
    162     abort ();
    163 
    164   /* Netware wants a list of relocs for each address.
    165      Format is:
    166     	long	offset
    167     	long	addend
    168     	char	type
    169      That should be it.  */
    170 
    171   /* The value we write out is the offset into the appropriate
    172      segment.  This offset is the section vma, adjusted by the vma of
    173      the lowest section in that segment, plus the address of the
    174      relocation.  */
    175   val = bfd_get_section_vma (abfd, sec) + rel->address;
    176 
    177 #ifdef DEBUG
    178   fprintf (stderr, "%s:  val = %08lx, addend = %08lx, type = %u\n",
    179 	   __FUNCTION__, (unsigned long) val, (unsigned long) rel->addend,
    180 	   rel->howto->type);
    181 #endif
    182   bfd_put_32 (abfd, val, tmp_reloc.offset);
    183   bfd_put_32 (abfd, rel->addend, tmp_reloc.addend);
    184   bfd_put_8 (abfd, (short) (rel->howto->type), tmp_reloc.type);
    185 
    186   if (bfd_bwrite (&tmp_reloc, (bfd_size_type) 12, abfd) != 12)
    187     return FALSE;
    188 
    189   return TRUE;
    190 }
    191 
    192 /* Mangle relocs for SPARC NetWare.  We can just use the standard
    193    SPARC relocs.  */
    194 
    195 static bfd_boolean
    196 nlm_sparc_mangle_relocs (bfd *abfd ATTRIBUTE_UNUSED,
    197 			 asection *sec ATTRIBUTE_UNUSED,
    198 			 const void * data ATTRIBUTE_UNUSED,
    199 			 bfd_vma offset ATTRIBUTE_UNUSED,
    200 			 bfd_size_type count ATTRIBUTE_UNUSED)
    201 {
    202   return TRUE;
    203 }
    204 
    205 /* Read a NetWare sparc import record.  */
    206 
    207 static bfd_boolean
    208 nlm_sparc_read_import (bfd *abfd, nlmNAME (symbol_type) *sym)
    209 {
    210   struct nlm_relent *nlm_relocs;	/* Relocation records for symbol.  */
    211   bfd_size_type rcount;			/* Number of relocs.  */
    212   bfd_byte temp[NLM_TARGET_LONG_SIZE];	/* Temporary 32-bit value.  */
    213   unsigned char symlength;		/* Length of symbol name.  */
    214   char *name;
    215 
    216   /* First, read in the number of relocation
    217      entries for this symbol.  */
    218   if (bfd_bread (temp, (bfd_size_type) 4, abfd) != 4)
    219     return FALSE;
    220 
    221   rcount = bfd_get_32 (abfd, temp);
    222 
    223   /* Next, read in the length of the symbol.  */
    224   if (bfd_bread (& symlength, (bfd_size_type) sizeof (symlength), abfd)
    225       != sizeof (symlength))
    226     return FALSE;
    227   sym -> symbol.the_bfd = abfd;
    228   name = bfd_alloc (abfd, (bfd_size_type) symlength + 1);
    229   if (name == NULL)
    230     return FALSE;
    231 
    232   /* Then read in the symbol.  */
    233   if (bfd_bread (name, (bfd_size_type) symlength, abfd) != symlength)
    234     return FALSE;
    235   name[symlength] = '\0';
    236   sym -> symbol.name = name;
    237   sym -> symbol.flags = 0;
    238   sym -> symbol.value = 0;
    239   sym -> symbol.section = bfd_und_section_ptr;
    240 
    241   /* Next, start reading in the relocs.  */
    242   nlm_relocs = bfd_alloc (abfd, rcount * sizeof (struct nlm_relent));
    243   if (!nlm_relocs)
    244     return FALSE;
    245   sym -> relocs = nlm_relocs;
    246   sym -> rcnt = 0;
    247   while (sym -> rcnt < rcount)
    248     {
    249       asection *section;
    250 
    251       if (! nlm_sparc_read_reloc (abfd, sym, &section, &nlm_relocs -> reloc))
    252 	return FALSE;
    253       nlm_relocs -> section = section;
    254       nlm_relocs++;
    255       sym -> rcnt++;
    256     }
    257 
    258   return TRUE;
    259 }
    260 
    261 static bfd_boolean
    262 nlm_sparc_write_import (bfd * abfd, asection * sec, arelent * rel)
    263 {
    264   char temp[4];
    265   asection *code, *data, *bss, *symsec;
    266   bfd_vma base;
    267 
    268   code = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
    269   data = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
    270   bss = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
    271   symsec = (*rel->sym_ptr_ptr)->section;
    272 
    273   if (symsec == code)
    274     base = 0;
    275   else if (symsec == data)
    276     base = code->size;
    277   else if (symsec == bss)
    278     base = code->size + data->size;
    279   else
    280     base = 0;
    281 
    282 #ifdef DEBUG
    283   fprintf (stderr, "%s:  <%lx, 1>\n\t",
    284 	   __FUNCTION__, (unsigned long) (base + (*rel->sym_ptr_ptr)->value));
    285 #endif
    286   bfd_put_32 (abfd, base + (*rel->sym_ptr_ptr)->value, temp);
    287   if (bfd_bwrite (temp, (bfd_size_type) 4, abfd) != 4)
    288     return FALSE;
    289   bfd_put_32 (abfd, (bfd_vma) 1, temp);
    290   if (bfd_bwrite (temp, (bfd_size_type) 4, abfd) != 4)
    291     return FALSE;
    292   if (! nlm_sparc_write_reloc (abfd, sec, rel))
    293     return FALSE;
    294   return TRUE;
    295 }
    296 
    297 /* Write out an external reference.  */
    298 
    299 static bfd_boolean
    300 nlm_sparc_write_external (bfd *abfd,
    301 			  bfd_size_type count,
    302 			  asymbol *sym,
    303 			  struct reloc_and_sec *relocs)
    304 {
    305   unsigned int i;
    306   bfd_byte len;
    307   unsigned char temp[NLM_TARGET_LONG_SIZE];
    308 
    309   bfd_put_32 (abfd, count, temp);
    310   if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp))
    311     return FALSE;
    312 
    313   len = strlen (sym->name);
    314   if ((bfd_bwrite (&len, (bfd_size_type) sizeof (bfd_byte), abfd)
    315        != sizeof (bfd_byte))
    316       || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len)
    317     return FALSE;
    318 
    319   for (i = 0; i < count; i++)
    320     if (! nlm_sparc_write_reloc (abfd, relocs[i].sec, relocs[i].rel))
    321       return FALSE;
    322 
    323   return TRUE;
    324 }
    325 
    326 static bfd_boolean
    327 nlm_sparc_write_export (bfd * abfd, asymbol * sym, bfd_vma value)
    328 {
    329   bfd_byte len;
    330   bfd_byte temp[4];
    331 
    332 #ifdef DEBUG
    333   fprintf (stderr, "%s: <%lx, %u, %s>\n",
    334 	   __FUNCTION__, (unsigned long) value, strlen (sym->name), sym->name);
    335 #endif
    336   bfd_put_32 (abfd, value, temp);
    337   len = strlen (sym->name);
    338 
    339   if (bfd_bwrite (temp, (bfd_size_type) 4, abfd) != 4
    340       || bfd_bwrite (&len, (bfd_size_type) 1, abfd) != 1
    341       || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len)
    342     return FALSE;
    343 
    344   return TRUE;
    345 }
    346 
    347 #undef nlm_swap_fixed_header_in
    348 #undef nlm_swap_fixed_header_out
    349 
    350 #include "nlmswap.h"
    351 
    352 static const struct nlm_backend_data nlm32_sparc_backend =
    353 {
    354   "NetWare SPARC Module   \032",
    355   sizeof (Nlm32_sparc_External_Fixed_Header),
    356   0,	/* Optional_prefix_size.  */
    357   bfd_arch_sparc,
    358   0,
    359   FALSE,
    360   0,	/* Backend_object_p.  */
    361   0,	/* Write_prefix_func.  */
    362   nlm_sparc_read_reloc,
    363   nlm_sparc_mangle_relocs,
    364   nlm_sparc_read_import,
    365   nlm_sparc_write_import,
    366   0,	/* Set_public_section.  */
    367   0,	/* Get_public_offset.  */
    368   nlm_swap_fixed_header_in,
    369   nlm_swap_fixed_header_out,
    370   nlm_sparc_write_external,
    371   nlm_sparc_write_export
    372 };
    373 
    374 #define TARGET_BIG_NAME		"nlm32-sparc"
    375 #define TARGET_BIG_SYM		sparc_nlm32_vec
    376 #define TARGET_BACKEND_DATA	& nlm32_sparc_backend
    377 
    378 #include "nlm-target.h"
    379