Back to index

cell-binutils  2.17cvs20070401
i386lynx.c
Go to the documentation of this file.
00001 /* BFD back-end for i386 a.out binaries under LynxOS.
00002    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1999, 2001, 2002,
00003    2003 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 #define N_SHARED_LIB(x) 0
00022 
00023 #define TEXT_START_ADDR 0
00024 #define TARGET_PAGE_SIZE 4096
00025 #define SEGMENT_SIZE TARGET_PAGE_SIZE
00026 #define DEFAULT_ARCH bfd_arch_i386
00027 
00028 /* Do not "beautify" the CONCAT* macro args.  Traditional C will not
00029    remove whitespace added here, and thus will fail to concatenate
00030    the tokens.  */
00031 #define MY(OP) CONCAT2 (i386lynx_aout_,OP)
00032 #define TARGETNAME "a.out-i386-lynx"
00033 
00034 #include "bfd.h"
00035 #include "sysdep.h"
00036 #include "libbfd.h"
00037 
00038 #ifndef WRITE_HEADERS
00039 #define WRITE_HEADERS(abfd, execp)                                   \
00040       {                                                                     \
00041        bfd_size_type text_size; /* dummy vars */                     \
00042        file_ptr text_end;                                            \
00043        if (adata(abfd).magic == undecided_magic)                     \
00044          NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end);     \
00045                                                                      \
00046        execp->a_syms = bfd_get_symcount (abfd) * EXTERNAL_NLIST_SIZE;       \
00047        execp->a_entry = bfd_get_start_address (abfd);                       \
00048                                                                      \
00049        execp->a_trsize = ((obj_textsec (abfd)->reloc_count) *               \
00050                         obj_reloc_entry_size (abfd));                \
00051        execp->a_drsize = ((obj_datasec (abfd)->reloc_count) *               \
00052                         obj_reloc_entry_size (abfd));                \
00053        NAME(aout,swap_exec_header_out) (abfd, execp, &exec_bytes);          \
00054                                                                      \
00055        if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0              \
00056            || bfd_bwrite ((PTR) &exec_bytes, (bfd_size_type) EXEC_BYTES_SIZE, \
00057                        abfd) != EXEC_BYTES_SIZE)                     \
00058          return FALSE;                                                      \
00059        /* Now write out reloc info, followed by syms and strings */         \
00060                                                                      \
00061        if (bfd_get_symcount (abfd) != 0)                             \
00062            {                                                         \
00063              if (bfd_seek (abfd, (file_ptr) (N_SYMOFF(*execp)), SEEK_SET)    \
00064                 != 0)                                                       \
00065                return FALSE;                                                \
00066                                                                      \
00067              if (! NAME(aout,write_syms) (abfd)) return FALSE;              \
00068                                                                      \
00069              if (bfd_seek (abfd, (file_ptr) (N_TRELOFF(*execp)), SEEK_SET)   \
00070                 != 0)                                                       \
00071                return FALSE;                                                \
00072                                                                      \
00073              if (!NAME(lynx,squirt_out_relocs) (abfd, obj_textsec (abfd)))   \
00074               return FALSE;                                          \
00075              if (bfd_seek (abfd, (file_ptr) (N_DRELOFF(*execp)), SEEK_SET)   \
00076                 != 0)                                                       \
00077                return 0;                                             \
00078                                                                      \
00079              if (!NAME(lynx,squirt_out_relocs) (abfd, obj_datasec (abfd)))   \
00080               return FALSE;                                          \
00081            }                                                         \
00082       }
00083 #endif
00084 
00085 #include "libaout.h"
00086 #include "aout/aout64.h"
00087 
00088 void NAME (lynx,swap_std_reloc_out)
00089   PARAMS ((bfd *, arelent *, struct reloc_std_external *));
00090 void NAME (lynx,swap_ext_reloc_out)
00091   PARAMS ((bfd *, arelent *, struct reloc_ext_external *));
00092 void NAME (lynx,swap_ext_reloc_in)
00093   PARAMS ((bfd *, struct reloc_ext_external *, arelent *, asymbol **,
00094           bfd_size_type));
00095 void NAME (lynx,swap_std_reloc_in)
00096   PARAMS ((bfd *, struct reloc_std_external *, arelent *, asymbol **,
00097           bfd_size_type));
00098 bfd_boolean NAME (lynx,slurp_reloc_table)
00099   PARAMS ((bfd *, sec_ptr, asymbol **));
00100 bfd_boolean NAME (lynx,squirt_out_relocs)
00101   PARAMS ((bfd *, asection *));
00102 long NAME (lynx,canonicalize_reloc)
00103   PARAMS ((bfd *, sec_ptr, arelent **, asymbol **));
00104 
00105 #ifdef LYNX_CORE
00106 
00107 char *lynx_core_file_failing_command ();
00108 int lynx_core_file_failing_signal ();
00109 bfd_boolean lynx_core_file_matches_executable_p ();
00110 const bfd_target *lynx_core_file_p ();
00111 
00112 #define       MY_core_file_failing_command lynx_core_file_failing_command
00113 #define       MY_core_file_failing_signal lynx_core_file_failing_signal
00114 #define       MY_core_file_matches_executable_p lynx_core_file_matches_executable_p
00115 #define       MY_core_file_p lynx_core_file_p
00116 
00117 #endif /* LYNX_CORE */
00118 
00119 
00120 #define KEEPIT udata.i
00121 
00122 extern reloc_howto_type aout_32_ext_howto_table[];
00123 extern reloc_howto_type aout_32_std_howto_table[];
00124 
00125 /* Standard reloc stuff */
00126 /* Output standard relocation information to a file in target byte order. */
00127 
00128 void
00129 NAME(lynx,swap_std_reloc_out) (abfd, g, natptr)
00130      bfd *abfd;
00131      arelent *g;
00132      struct reloc_std_external *natptr;
00133 {
00134   int r_index;
00135   asymbol *sym = *(g->sym_ptr_ptr);
00136   int r_extern;
00137   unsigned int r_length;
00138   int r_pcrel;
00139   int r_baserel, r_jmptable, r_relative;
00140   unsigned int r_addend;
00141   asection *output_section = sym->section->output_section;
00142 
00143   PUT_WORD (abfd, g->address, natptr->r_address);
00144 
00145   r_length = g->howto->size;       /* Size as a power of two */
00146   r_pcrel = (int) g->howto->pc_relative;  /* Relative to PC? */
00147   /* r_baserel, r_jmptable, r_relative???  FIXME-soon */
00148   r_baserel = 0;
00149   r_jmptable = 0;
00150   r_relative = 0;
00151 
00152   r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
00153 
00154   /* name was clobbered by aout_write_syms to be symbol index */
00155 
00156   /* If this relocation is relative to a symbol then set the
00157      r_index to the symbols index, and the r_extern bit.
00158 
00159      Absolute symbols can come in in two ways, either as an offset
00160      from the abs section, or as a symbol which has an abs value.
00161      check for that here
00162   */
00163 
00164 
00165   if (bfd_is_com_section (output_section)
00166       || bfd_is_abs_section (output_section)
00167       || bfd_is_und_section (output_section))
00168     {
00169       if (bfd_abs_section_ptr->symbol == sym)
00170        {
00171          /* Whoops, looked like an abs symbol, but is really an offset
00172             from the abs section */
00173          r_index = 0;
00174          r_extern = 0;
00175        }
00176       else
00177        {
00178          /* Fill in symbol */
00179          r_extern = 1;
00180          r_index = (*g->sym_ptr_ptr)->KEEPIT;
00181        }
00182     }
00183   else
00184     {
00185       /* Just an ordinary section */
00186       r_extern = 0;
00187       r_index = output_section->target_index;
00188     }
00189 
00190   /* now the fun stuff */
00191   if (bfd_header_big_endian (abfd))
00192     {
00193       natptr->r_index[0] = r_index >> 16;
00194       natptr->r_index[1] = r_index >> 8;
00195       natptr->r_index[2] = r_index;
00196       natptr->r_type[0] =
00197        (r_extern ? RELOC_STD_BITS_EXTERN_BIG : 0)
00198        | (r_pcrel ? RELOC_STD_BITS_PCREL_BIG : 0)
00199        | (r_baserel ? RELOC_STD_BITS_BASEREL_BIG : 0)
00200        | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0)
00201        | (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0)
00202        | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG);
00203     }
00204   else
00205     {
00206       natptr->r_index[2] = r_index >> 16;
00207       natptr->r_index[1] = r_index >> 8;
00208       natptr->r_index[0] = r_index;
00209       natptr->r_type[0] =
00210        (r_extern ? RELOC_STD_BITS_EXTERN_LITTLE : 0)
00211        | (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE : 0)
00212        | (r_baserel ? RELOC_STD_BITS_BASEREL_LITTLE : 0)
00213        | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_LITTLE : 0)
00214        | (r_relative ? RELOC_STD_BITS_RELATIVE_LITTLE : 0)
00215        | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE);
00216     }
00217 }
00218 
00219 
00220 /* Extended stuff */
00221 /* Output extended relocation information to a file in target byte order. */
00222 
00223 void
00224 NAME(lynx,swap_ext_reloc_out) (abfd, g, natptr)
00225      bfd *abfd;
00226      arelent *g;
00227      register struct reloc_ext_external *natptr;
00228 {
00229   int r_index;
00230   int r_extern;
00231   unsigned int r_type;
00232   unsigned int r_addend;
00233   asymbol *sym = *(g->sym_ptr_ptr);
00234   asection *output_section = sym->section->output_section;
00235 
00236   PUT_WORD (abfd, g->address, natptr->r_address);
00237 
00238   r_type = (unsigned int) g->howto->type;
00239 
00240   r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
00241 
00242 
00243   /* If this relocation is relative to a symbol then set the
00244      r_index to the symbols index, and the r_extern bit.
00245 
00246      Absolute symbols can come in in two ways, either as an offset
00247      from the abs section, or as a symbol which has an abs value.
00248      check for that here
00249      */
00250 
00251   if (bfd_is_com_section (output_section)
00252       || bfd_is_abs_section (output_section)
00253       || bfd_is_und_section (output_section))
00254     {
00255       if (bfd_abs_section_ptr->symbol == sym)
00256        {
00257          /* Whoops, looked like an abs symbol, but is really an offset
00258         from the abs section */
00259          r_index = 0;
00260          r_extern = 0;
00261        }
00262       else
00263        {
00264          r_extern = 1;
00265          r_index = (*g->sym_ptr_ptr)->KEEPIT;
00266        }
00267     }
00268   else
00269     {
00270       /* Just an ordinary section */
00271       r_extern = 0;
00272       r_index = output_section->target_index;
00273     }
00274 
00275 
00276   /* now the fun stuff */
00277   if (bfd_header_big_endian (abfd))
00278     {
00279       natptr->r_index[0] = r_index >> 16;
00280       natptr->r_index[1] = r_index >> 8;
00281       natptr->r_index[2] = r_index;
00282       natptr->r_type[0] =
00283        (r_extern ? RELOC_EXT_BITS_EXTERN_BIG : 0)
00284        | (r_type << RELOC_EXT_BITS_TYPE_SH_BIG);
00285     }
00286   else
00287     {
00288       natptr->r_index[2] = r_index >> 16;
00289       natptr->r_index[1] = r_index >> 8;
00290       natptr->r_index[0] = r_index;
00291       natptr->r_type[0] =
00292        (r_extern ? RELOC_EXT_BITS_EXTERN_LITTLE : 0)
00293        | (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
00294     }
00295 
00296   PUT_WORD (abfd, r_addend, natptr->r_addend);
00297 }
00298 
00299 /* BFD deals internally with all things based from the section they're
00300    in. so, something in 10 bytes into a text section  with a base of
00301    50 would have a symbol (.text+10) and know .text vma was 50.
00302 
00303    Aout keeps all it's symbols based from zero, so the symbol would
00304    contain 60. This macro subs the base of each section from the value
00305    to give the true offset from the section */
00306 
00307 
00308 #define MOVE_ADDRESS(ad)                                              \
00309   if (r_extern) {                                              \
00310    /* undefined symbol */                                      \
00311      cache_ptr->sym_ptr_ptr = symbols + r_index;               \
00312      cache_ptr->addend = ad;                                          \
00313      } else {                                                  \
00314     /* defined, section relative. replace symbol with pointer to      \
00315        symbol which points to section  */                      \
00316     switch (r_index) {                                                \
00317     case N_TEXT:                                               \
00318     case N_TEXT | N_EXT:                                       \
00319       cache_ptr->sym_ptr_ptr  = obj_textsec(abfd)->symbol_ptr_ptr;    \
00320       cache_ptr->addend = ad  - su->textsec->vma;                     \
00321       break;                                                   \
00322     case N_DATA:                                               \
00323     case N_DATA | N_EXT:                                       \
00324       cache_ptr->sym_ptr_ptr  = obj_datasec(abfd)->symbol_ptr_ptr;    \
00325       cache_ptr->addend = ad - su->datasec->vma;               \
00326       break;                                                   \
00327     case N_BSS:                                                       \
00328     case N_BSS | N_EXT:                                               \
00329       cache_ptr->sym_ptr_ptr  = obj_bsssec(abfd)->symbol_ptr_ptr;     \
00330       cache_ptr->addend = ad - su->bsssec->vma;                       \
00331       break;                                                   \
00332     default:                                                   \
00333     case N_ABS:                                                       \
00334     case N_ABS | N_EXT:                                               \
00335      cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;    \
00336       cache_ptr->addend = ad;                                         \
00337       break;                                                   \
00338     }                                                          \
00339   }                                                            \
00340 
00341 void
00342 NAME(lynx,swap_ext_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount)
00343      bfd *abfd;
00344      struct reloc_ext_external *bytes;
00345      arelent *cache_ptr;
00346      asymbol **symbols;
00347      bfd_size_type symcount ATTRIBUTE_UNUSED;
00348 {
00349   int r_index;
00350   int r_extern;
00351   unsigned int r_type;
00352   struct aoutdata *su = &(abfd->tdata.aout_data->a);
00353 
00354   cache_ptr->address = (GET_SWORD (abfd, bytes->r_address));
00355 
00356   r_index = bytes->r_index[1];
00357   r_extern = (0 != (bytes->r_index[0] & RELOC_EXT_BITS_EXTERN_BIG));
00358   r_type = (bytes->r_index[0] & RELOC_EXT_BITS_TYPE_BIG)
00359     >> RELOC_EXT_BITS_TYPE_SH_BIG;
00360 
00361   cache_ptr->howto = aout_32_ext_howto_table + r_type;
00362   MOVE_ADDRESS (GET_SWORD (abfd, bytes->r_addend));
00363 }
00364 
00365 void
00366 NAME(lynx,swap_std_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount)
00367      bfd *abfd;
00368      struct reloc_std_external *bytes;
00369      arelent *cache_ptr;
00370      asymbol **symbols;
00371      bfd_size_type symcount ATTRIBUTE_UNUSED;
00372 {
00373   int r_index;
00374   int r_extern;
00375   unsigned int r_length;
00376   int r_pcrel;
00377   int r_baserel, r_jmptable, r_relative;
00378   struct aoutdata *su = &(abfd->tdata.aout_data->a);
00379 
00380   cache_ptr->address = H_GET_32 (abfd, bytes->r_address);
00381 
00382   r_index = bytes->r_index[1];
00383   r_extern = (0 != (bytes->r_index[0] & RELOC_STD_BITS_EXTERN_BIG));
00384   r_pcrel = (0 != (bytes->r_index[0] & RELOC_STD_BITS_PCREL_BIG));
00385   r_baserel = (0 != (bytes->r_index[0] & RELOC_STD_BITS_BASEREL_BIG));
00386   r_jmptable = (0 != (bytes->r_index[0] & RELOC_STD_BITS_JMPTABLE_BIG));
00387   r_relative = (0 != (bytes->r_index[0] & RELOC_STD_BITS_RELATIVE_BIG));
00388   r_length = (bytes->r_index[0] & RELOC_STD_BITS_LENGTH_BIG)
00389     >> RELOC_STD_BITS_LENGTH_SH_BIG;
00390 
00391   cache_ptr->howto = aout_32_std_howto_table + r_length + 4 * r_pcrel;
00392   /* FIXME-soon:  Roll baserel, jmptable, relative bits into howto setting */
00393 
00394   MOVE_ADDRESS (0);
00395 }
00396 
00397 /* Reloc hackery */
00398 
00399 bfd_boolean
00400 NAME(lynx,slurp_reloc_table) (abfd, asect, symbols)
00401      bfd *abfd;
00402      sec_ptr asect;
00403      asymbol **symbols;
00404 {
00405   bfd_size_type count;
00406   bfd_size_type reloc_size;
00407   PTR relocs;
00408   arelent *reloc_cache;
00409   size_t each_size;
00410 
00411   if (asect->relocation)
00412     return TRUE;
00413 
00414   if (asect->flags & SEC_CONSTRUCTOR)
00415     return TRUE;
00416 
00417   if (asect == obj_datasec (abfd))
00418     {
00419       reloc_size = exec_hdr (abfd)->a_drsize;
00420       goto doit;
00421     }
00422 
00423   if (asect == obj_textsec (abfd))
00424     {
00425       reloc_size = exec_hdr (abfd)->a_trsize;
00426       goto doit;
00427     }
00428 
00429   bfd_set_error (bfd_error_invalid_operation);
00430   return FALSE;
00431 
00432 doit:
00433   if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
00434     return FALSE;
00435   each_size = obj_reloc_entry_size (abfd);
00436 
00437   count = reloc_size / each_size;
00438 
00439 
00440   reloc_cache = (arelent *) bfd_zmalloc (count * sizeof (arelent));
00441   if (!reloc_cache && count != 0)
00442     return FALSE;
00443 
00444   relocs = (PTR) bfd_alloc (abfd, reloc_size);
00445   if (!relocs && reloc_size != 0)
00446     {
00447       free (reloc_cache);
00448       return FALSE;
00449     }
00450 
00451   if (bfd_bread (relocs, reloc_size, abfd) != reloc_size)
00452     {
00453       bfd_release (abfd, relocs);
00454       free (reloc_cache);
00455       return FALSE;
00456     }
00457 
00458   if (each_size == RELOC_EXT_SIZE)
00459     {
00460       register struct reloc_ext_external *rptr = (struct reloc_ext_external *) relocs;
00461       unsigned int counter = 0;
00462       arelent *cache_ptr = reloc_cache;
00463 
00464       for (; counter < count; counter++, rptr++, cache_ptr++)
00465        {
00466          NAME(lynx,swap_ext_reloc_in) (abfd, rptr, cache_ptr, symbols,
00467                                    (bfd_size_type) bfd_get_symcount (abfd));
00468        }
00469     }
00470   else
00471     {
00472       register struct reloc_std_external *rptr = (struct reloc_std_external *) relocs;
00473       unsigned int counter = 0;
00474       arelent *cache_ptr = reloc_cache;
00475 
00476       for (; counter < count; counter++, rptr++, cache_ptr++)
00477        {
00478          NAME(lynx,swap_std_reloc_in) (abfd, rptr, cache_ptr, symbols,
00479                                    (bfd_size_type) bfd_get_symcount (abfd));
00480        }
00481 
00482     }
00483 
00484   bfd_release (abfd, relocs);
00485   asect->relocation = reloc_cache;
00486   asect->reloc_count = count;
00487   return TRUE;
00488 }
00489 
00490 
00491 
00492 /* Write out a relocation section into an object file.  */
00493 
00494 bfd_boolean
00495 NAME(lynx,squirt_out_relocs) (abfd, section)
00496      bfd *abfd;
00497      asection *section;
00498 {
00499   arelent **generic;
00500   unsigned char *native, *natptr;
00501   size_t each_size;
00502 
00503   unsigned int count = section->reloc_count;
00504   bfd_size_type natsize;
00505 
00506   if (count == 0)
00507     return TRUE;
00508 
00509   each_size = obj_reloc_entry_size (abfd);
00510   natsize = count;
00511   natsize *= each_size;
00512   native = (unsigned char *) bfd_zalloc (abfd, natsize);
00513   if (!native)
00514     return FALSE;
00515 
00516   generic = section->orelocation;
00517 
00518   if (each_size == RELOC_EXT_SIZE)
00519     {
00520       for (natptr = native;
00521           count != 0;
00522           --count, natptr += each_size, ++generic)
00523        NAME(lynx,swap_ext_reloc_out) (abfd, *generic, (struct reloc_ext_external *) natptr);
00524     }
00525   else
00526     {
00527       for (natptr = native;
00528           count != 0;
00529           --count, natptr += each_size, ++generic)
00530        NAME(lynx,swap_std_reloc_out) (abfd, *generic, (struct reloc_std_external *) natptr);
00531     }
00532 
00533   if (bfd_bwrite ((PTR) native, natsize, abfd) != natsize)
00534     {
00535       bfd_release (abfd, native);
00536       return FALSE;
00537     }
00538   bfd_release (abfd, native);
00539 
00540   return TRUE;
00541 }
00542 
00543 /* This is stupid.  This function should be a boolean predicate */
00544 long
00545 NAME(lynx,canonicalize_reloc) (abfd, section, relptr, symbols)
00546      bfd *abfd;
00547      sec_ptr section;
00548      arelent **relptr;
00549      asymbol **symbols;
00550 {
00551   arelent *tblptr = section->relocation;
00552   unsigned int count;
00553 
00554   if (!(tblptr || NAME(lynx,slurp_reloc_table) (abfd, section, symbols)))
00555     return -1;
00556 
00557   if (section->flags & SEC_CONSTRUCTOR)
00558     {
00559       arelent_chain *chain = section->constructor_chain;
00560       for (count = 0; count < section->reloc_count; count++)
00561        {
00562          *relptr++ = &chain->relent;
00563          chain = chain->next;
00564        }
00565     }
00566   else
00567     {
00568       tblptr = section->relocation;
00569 
00570       for (count = 0; count++ < section->reloc_count;)
00571        {
00572          *relptr++ = tblptr++;
00573        }
00574     }
00575   *relptr = 0;
00576 
00577   return section->reloc_count;
00578 }
00579 
00580 #define MY_canonicalize_reloc NAME(lynx,canonicalize_reloc)
00581 
00582 #include "aout-target.h"