Back to index

cell-binutils  2.17cvs20070401
nlm32-sparc.c
Go to the documentation of this file.
00001 /* Support for 32-bit SPARC NLM (NetWare Loadable Module)
00002    Copyright 1993, 1994, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
00003    Free Software Foundation, Inc.
00004 
00005    This file is part of BFD, the Binary File Descriptor library.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program; if not, write to the Free Software
00019    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00020 
00021 #include "bfd.h"
00022 #include "sysdep.h"
00023 #include "libbfd.h"
00024 
00025 #define ARCH_SIZE 32
00026 
00027 #include "nlm/sparc32-ext.h"
00028 #define Nlm_External_Fixed_Header  Nlm32_sparc_External_Fixed_Header
00029 
00030 #include "libnlm.h"
00031 
00032 enum reloc_type
00033 {
00034   R_SPARC_NONE = 0,
00035   R_SPARC_8,         R_SPARC_16,          R_SPARC_32,
00036   R_SPARC_DISP8,     R_SPARC_DISP16,             R_SPARC_DISP32,
00037   R_SPARC_WDISP30,   R_SPARC_WDISP22,
00038   R_SPARC_HI22,             R_SPARC_22,
00039   R_SPARC_13,        R_SPARC_LO10,
00040   R_SPARC_GOT10,     R_SPARC_GOT13,              R_SPARC_GOT22,
00041   R_SPARC_PC10,             R_SPARC_PC22,
00042   R_SPARC_WPLT30,
00043   R_SPARC_COPY,
00044   R_SPARC_GLOB_DAT,  R_SPARC_JMP_SLOT,
00045   R_SPARC_RELATIVE,
00046   R_SPARC_UA32,
00047   R_SPARC_max
00048 };
00049 
00050 static reloc_howto_type nlm32_sparc_howto_table[] =
00051 {
00052   HOWTO (R_SPARC_NONE,    0,0, 0,FALSE,0,complain_overflow_dont,    0,"R_SPARC_NONE",    FALSE,0,0x00000000,TRUE),
00053   HOWTO (R_SPARC_8,       0,0, 8,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_8",       FALSE,0,0x000000ff,TRUE),
00054   HOWTO (R_SPARC_16,      0,1,16,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_16",      FALSE,0,0x0000ffff,TRUE),
00055   HOWTO (R_SPARC_32,      0,2,32,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_32",      FALSE,0,0xffffffff,TRUE),
00056   HOWTO (R_SPARC_DISP8,   0,0, 8,TRUE, 0,complain_overflow_signed,  0,"R_SPARC_DISP8",   FALSE,0,0x000000ff,TRUE),
00057   HOWTO (R_SPARC_DISP16,  0,1,16,TRUE, 0,complain_overflow_signed,  0,"R_SPARC_DISP16",  FALSE,0,0x0000ffff,TRUE),
00058   HOWTO (R_SPARC_DISP32,  0,2,32,TRUE, 0,complain_overflow_signed,  0,"R_SPARC_DISP32",  FALSE,0,0x00ffffff,TRUE),
00059   HOWTO (R_SPARC_WDISP30, 2,2,30,TRUE, 0,complain_overflow_signed,  0,"R_SPARC_WDISP30", FALSE,0,0x3fffffff,TRUE),
00060   HOWTO (R_SPARC_WDISP22, 2,2,22,TRUE, 0,complain_overflow_signed,  0,"R_SPARC_WDISP22", FALSE,0,0x003fffff,TRUE),
00061   HOWTO (R_SPARC_HI22,   10,2,22,FALSE,0,complain_overflow_dont,    0,"R_SPARC_HI22",    FALSE,0,0x003fffff,TRUE),
00062   HOWTO (R_SPARC_22,      0,2,22,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_22",      FALSE,0,0x003fffff,TRUE),
00063   HOWTO (R_SPARC_13,      0,2,13,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_13",      FALSE,0,0x00001fff,TRUE),
00064   HOWTO (R_SPARC_LO10,    0,2,10,FALSE,0,complain_overflow_dont,    0,"R_SPARC_LO10",    FALSE,0,0x000003ff,TRUE),
00065   HOWTO (R_SPARC_GOT10,   0,2,10,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_GOT10",   FALSE,0,0x000003ff,TRUE),
00066   HOWTO (R_SPARC_GOT13,   0,2,13,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_GOT13",   FALSE,0,0x00001fff,TRUE),
00067   HOWTO (R_SPARC_GOT22,  10,2,22,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_GOT22",   FALSE,0,0x003fffff,TRUE),
00068   HOWTO (R_SPARC_PC10,    0,2,10,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_PC10",    FALSE,0,0x000003ff,TRUE),
00069   HOWTO (R_SPARC_PC22,    0,2,22,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_PC22",    FALSE,0,0x003fffff,TRUE),
00070   HOWTO (R_SPARC_WPLT30,  0,0,00,FALSE,0,complain_overflow_dont,    0,"R_SPARC_WPLT30",  FALSE,0,0x00000000,TRUE),
00071   HOWTO (R_SPARC_COPY,    0,0,00,FALSE,0,complain_overflow_dont,    0,"R_SPARC_COPY",    FALSE,0,0x00000000,TRUE),
00072   HOWTO (R_SPARC_GLOB_DAT,0,0,00,FALSE,0,complain_overflow_dont,    0,"R_SPARC_GLOB_DAT",FALSE,0,0x00000000,TRUE),
00073   HOWTO (R_SPARC_JMP_SLOT,0,0,00,FALSE,0,complain_overflow_dont,    0,"R_SPARC_JMP_SLOT",FALSE,0,0x00000000,TRUE),
00074   HOWTO (R_SPARC_RELATIVE,0,0,00,FALSE,0,complain_overflow_dont,    0,"R_SPARC_RELATIVE",FALSE,0,0x00000000,TRUE),
00075   HOWTO (R_SPARC_UA32,    0,0,00,FALSE,0,complain_overflow_dont,    0,"R_SPARC_UA32",    FALSE,0,0x00000000,TRUE),
00076 };
00077 
00078 /* Read a NetWare sparc reloc.  */
00079 
00080 struct nlm32_sparc_reloc_ext
00081 {
00082   unsigned char offset[4];
00083   unsigned char addend[4];
00084   unsigned char type[1];
00085   unsigned char pad1[3];
00086 };
00087 
00088 static bfd_boolean
00089 nlm_sparc_read_reloc (bfd *abfd,
00090                     nlmNAME (symbol_type) *sym ATTRIBUTE_UNUSED,
00091                     asection **secp,
00092                     arelent *rel)
00093 {
00094   bfd_vma val, addend;
00095   unsigned int index;
00096   unsigned int type;
00097   struct nlm32_sparc_reloc_ext tmp_reloc;
00098   asection *code_sec, *data_sec;
00099 
00100   if (bfd_bread (&tmp_reloc, (bfd_size_type) 12, abfd) != 12)
00101     return FALSE;
00102 
00103   code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
00104   data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
00105 
00106   *secp = code_sec;
00107 
00108   val = bfd_get_32 (abfd, tmp_reloc.offset);
00109   addend = bfd_get_32 (abfd, tmp_reloc.addend);
00110   type = bfd_get_8 (abfd, tmp_reloc.type);
00111 
00112   rel->address = val;
00113   rel->addend = addend;
00114   rel->howto = NULL;
00115 
00116   for (index = 0;
00117        index < sizeof (nlm32_sparc_howto_table) / sizeof (reloc_howto_type);
00118        index++)
00119     if (nlm32_sparc_howto_table[index].type == type)
00120       {
00121        rel->howto = &nlm32_sparc_howto_table[index];
00122        break;
00123       }
00124 
00125 #ifdef DEBUG
00126   fprintf (stderr, "%s:  address = %08lx, addend = %08lx, type = %u, howto = %p\n",
00127           __FUNCTION__, (unsigned long) rel->address,
00128           (unsigned long) rel->addend, type, rel->howto);
00129 #endif
00130   return TRUE;
00131 
00132 }
00133 
00134 /* Write a NetWare sparc reloc.  */
00135 
00136 static bfd_boolean
00137 nlm_sparc_write_reloc (bfd * abfd, asection * sec, arelent * rel)
00138 {
00139   bfd_vma val;
00140   struct nlm32_sparc_reloc_ext tmp_reloc;
00141   unsigned int index;
00142   int type = -1;
00143   reloc_howto_type *tmp;
00144 
00145   for (index = 0;
00146        index < sizeof (nlm32_sparc_howto_table) / sizeof (reloc_howto_type);
00147        index++)
00148     {
00149       tmp = &nlm32_sparc_howto_table[index];
00150 
00151       if (tmp->rightshift == rel->howto->rightshift
00152          && tmp->size == rel->howto->size
00153          && tmp->bitsize == rel->howto->bitsize
00154          && tmp->pc_relative == rel->howto->pc_relative
00155          && tmp->bitpos == rel->howto->bitpos
00156          && tmp->src_mask == rel->howto->src_mask
00157          && tmp->dst_mask == rel->howto->dst_mask)
00158        {
00159          type = tmp->type;
00160          break;
00161        }
00162     }
00163   if (type == -1)
00164     abort ();
00165 
00166   /* Netware wants a list of relocs for each address.
00167      Format is:
00168        long   offset
00169        long   addend
00170        char   type
00171      That should be it.  */
00172 
00173   /* The value we write out is the offset into the appropriate
00174      segment.  This offset is the section vma, adjusted by the vma of
00175      the lowest section in that segment, plus the address of the
00176      relocation.  */
00177   val = bfd_get_section_vma (abfd, sec) + rel->address;
00178 
00179 #ifdef DEBUG
00180   fprintf (stderr, "%s:  val = %08lx, addend = %08lx, type = %u\n",
00181           __FUNCTION__, (unsigned long) val, (unsigned long) rel->addend,
00182           rel->howto->type);
00183 #endif
00184   bfd_put_32 (abfd, val, tmp_reloc.offset);
00185   bfd_put_32 (abfd, rel->addend, tmp_reloc.addend);
00186   bfd_put_8 (abfd, (short) (rel->howto->type), tmp_reloc.type);
00187 
00188   if (bfd_bwrite (&tmp_reloc, (bfd_size_type) 12, abfd) != 12)
00189     return FALSE;
00190 
00191   return TRUE;
00192 }
00193 
00194 /* Mangle relocs for SPARC NetWare.  We can just use the standard
00195    SPARC relocs.  */
00196 
00197 static bfd_boolean
00198 nlm_sparc_mangle_relocs (bfd *abfd ATTRIBUTE_UNUSED,
00199                       asection *sec ATTRIBUTE_UNUSED,
00200                       const void * data ATTRIBUTE_UNUSED,
00201                       bfd_vma offset ATTRIBUTE_UNUSED,
00202                       bfd_size_type count ATTRIBUTE_UNUSED)
00203 {
00204   return TRUE;
00205 }
00206 
00207 /* Read a NetWare sparc import record.  */
00208 
00209 static bfd_boolean
00210 nlm_sparc_read_import (bfd *abfd, nlmNAME (symbol_type) *sym)
00211 {
00212   struct nlm_relent *nlm_relocs;   /* Relocation records for symbol.  */
00213   bfd_size_type rcount;                   /* Number of relocs.  */
00214   bfd_byte temp[NLM_TARGET_LONG_SIZE];    /* Temporary 32-bit value.  */
00215   unsigned char symlength;         /* Length of symbol name.  */
00216   char *name;
00217 
00218   /* First, read in the number of relocation
00219      entries for this symbol.  */
00220   if (bfd_bread (temp, (bfd_size_type) 4, abfd) != 4)
00221     return FALSE;
00222 
00223   rcount = bfd_get_32 (abfd, temp);
00224 
00225   /* Next, read in the length of the symbol.  */
00226   if (bfd_bread (& symlength, (bfd_size_type) sizeof (symlength), abfd)
00227       != sizeof (symlength))
00228     return FALSE;
00229   sym -> symbol.the_bfd = abfd;
00230   name = bfd_alloc (abfd, (bfd_size_type) symlength + 1);
00231   if (name == NULL)
00232     return FALSE;
00233 
00234   /* Then read in the symbol.  */
00235   if (bfd_bread (name, (bfd_size_type) symlength, abfd) != symlength)
00236     return FALSE;
00237   name[symlength] = '\0';
00238   sym -> symbol.name = name;
00239   sym -> symbol.flags = 0;
00240   sym -> symbol.value = 0;
00241   sym -> symbol.section = bfd_und_section_ptr;
00242 
00243   /* Next, start reading in the relocs.  */
00244   nlm_relocs = bfd_alloc (abfd, rcount * sizeof (struct nlm_relent));
00245   if (!nlm_relocs)
00246     return FALSE;
00247   sym -> relocs = nlm_relocs;
00248   sym -> rcnt = 0;
00249   while (sym -> rcnt < rcount)
00250     {
00251       asection *section;
00252 
00253       if (! nlm_sparc_read_reloc (abfd, sym, &section, &nlm_relocs -> reloc))
00254        return FALSE;
00255       nlm_relocs -> section = section;
00256       nlm_relocs++;
00257       sym -> rcnt++;
00258     }
00259 
00260   return TRUE;
00261 }
00262 
00263 static bfd_boolean
00264 nlm_sparc_write_import (bfd * abfd, asection * sec, arelent * rel)
00265 {
00266   char temp[4];
00267   asection *code, *data, *bss, *symsec;
00268   bfd_vma base;
00269 
00270   code = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
00271   data = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
00272   bss = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
00273   symsec = (*rel->sym_ptr_ptr)->section;
00274 
00275   if (symsec == code)
00276     base = 0;
00277   else if (symsec == data)
00278     base = code->size;
00279   else if (symsec == bss)
00280     base = code->size + data->size;
00281   else
00282     base = 0;
00283 
00284 #ifdef DEBUG
00285   fprintf (stderr, "%s:  <%lx, 1>\n\t",
00286           __FUNCTION__, (unsigned long) (base + (*rel->sym_ptr_ptr)->value));
00287 #endif
00288   bfd_put_32 (abfd, base + (*rel->sym_ptr_ptr)->value, temp);
00289   if (bfd_bwrite (temp, (bfd_size_type) 4, abfd) != 4)
00290     return FALSE;
00291   bfd_put_32 (abfd, (bfd_vma) 1, temp);
00292   if (bfd_bwrite (temp, (bfd_size_type) 4, abfd) != 4)
00293     return FALSE;
00294   if (! nlm_sparc_write_reloc (abfd, sec, rel))
00295     return FALSE;
00296   return TRUE;
00297 }
00298 
00299 /* Write out an external reference.  */
00300 
00301 static bfd_boolean
00302 nlm_sparc_write_external (bfd *abfd,
00303                        bfd_size_type count,
00304                        asymbol *sym,
00305                        struct reloc_and_sec *relocs)
00306 {
00307   unsigned int i;
00308   bfd_byte len;
00309   unsigned char temp[NLM_TARGET_LONG_SIZE];
00310 
00311   bfd_put_32 (abfd, count, temp);
00312   if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp))
00313     return FALSE;
00314 
00315   len = strlen (sym->name);
00316   if ((bfd_bwrite (&len, (bfd_size_type) sizeof (bfd_byte), abfd)
00317        != sizeof (bfd_byte))
00318       || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len)
00319     return FALSE;
00320 
00321   for (i = 0; i < count; i++)
00322     if (! nlm_sparc_write_reloc (abfd, relocs[i].sec, relocs[i].rel))
00323       return FALSE;
00324 
00325   return TRUE;
00326 }
00327 
00328 static bfd_boolean
00329 nlm_sparc_write_export (bfd * abfd, asymbol * sym, bfd_vma value)
00330 {
00331   bfd_byte len;
00332   bfd_byte temp[4];
00333 
00334 #ifdef DEBUG
00335   fprintf (stderr, "%s: <%lx, %u, %s>\n",
00336           __FUNCTION__, (unsigned long) value, strlen (sym->name), sym->name);
00337 #endif
00338   bfd_put_32 (abfd, value, temp);
00339   len = strlen (sym->name);
00340 
00341   if (bfd_bwrite (temp, (bfd_size_type) 4, abfd) != 4
00342       || bfd_bwrite (&len, (bfd_size_type) 1, abfd) != 1
00343       || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len)
00344     return FALSE;
00345 
00346   return TRUE;
00347 }
00348 
00349 #undef nlm_swap_fixed_header_in
00350 #undef nlm_swap_fixed_header_out
00351 
00352 #include "nlmswap.h"
00353 
00354 static const struct nlm_backend_data nlm32_sparc_backend =
00355 {
00356   "NetWare SPARC Module   \032",
00357   sizeof (Nlm32_sparc_External_Fixed_Header),
00358   0,   /* Optional_prefix_size.  */
00359   bfd_arch_sparc,
00360   0,
00361   FALSE,
00362   0,   /* Backend_object_p.  */
00363   0,   /* Write_prefix_func.  */
00364   nlm_sparc_read_reloc,
00365   nlm_sparc_mangle_relocs,
00366   nlm_sparc_read_import,
00367   nlm_sparc_write_import,
00368   0,   /* Set_public_section.  */
00369   0,   /* Get_public_offset.  */
00370   nlm_swap_fixed_header_in,
00371   nlm_swap_fixed_header_out,
00372   nlm_sparc_write_external,
00373   nlm_sparc_write_export
00374 };
00375 
00376 #define TARGET_BIG_NAME            "nlm32-sparc"
00377 #define TARGET_BIG_SYM             nlmNAME (sparc_vec)
00378 #define TARGET_BACKEND_DATA & nlm32_sparc_backend
00379 
00380 #include "nlm-target.h"