Back to index

cell-binutils  2.17cvs20070401
hp300hpux.c
Go to the documentation of this file.
00001 /* BFD backend for hp-ux 9000/300
00002    Copyright 1990, 1991, 1993, 1994, 1995, 1997, 1999, 2000, 2001, 2002,
00003    2003, 2004 Free Software Foundation, Inc.
00004    Written by Glenn Engel.
00005 
00006 This file is part of BFD, the Binary File Descriptor library.
00007 
00008 This program is free software; you can redistribute it and/or modify
00009 it under the terms of the GNU General Public License as published by
00010 the Free Software Foundation; either version 2 of the License, or
00011 (at your option) any later version.
00012 
00013 This program is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 GNU General Public License for more details.
00017 
00018 You should have received a copy of the GNU General Public License
00019 along with this program; if not, write to the Free Software
00020 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00021 
00022 /*
00023     hpux native  ------------> |               |
00024                                | hp300hpux bfd | ----------> hpux w/gnu ext
00025     hpux w/gnu extension ----> |               |
00026 
00027     Support for the 9000/[34]00 has several limitations.
00028       1. Shared libraries are not supported.
00029       2. The output format from this bfd is not usable by native tools.
00030 
00031     The primary motivation for writing this bfd was to allow use of
00032     gdb and gcc for host based debugging and not to mimic the hp-ux tools
00033     in every detail.  This leads to a significant simplification of the
00034     code and a leap in performance.  The decision to not output hp native
00035     compatible objects was further strengthened by the fact that the richness
00036     of the gcc compiled objects could not be represented without loss of
00037     information.  For example, while the hp format supports the concept of
00038     secondary symbols, it does not support indirect symbols.  Another
00039     reason is to maintain backwards compatibility with older implementations
00040     of gcc on hpux which used 'hpxt' to translate .a and .o files into a
00041     format which could be readily understood by the gnu linker and gdb.
00042     This allows reading hp secondary symbols and converting them into
00043     indirect symbols but the reverse it not always possible.
00044 
00045     Another example of differences is that the hp format stores symbol offsets
00046     in the object code while the gnu utilities use a field in the
00047     relocation record for this.  To support the hp native format, the object
00048     code would need to be patched with the offsets when producing .o files.
00049 
00050     The basic technique taken in this implementation is to #include the code
00051     from aoutx.h and aout-target.h with appropriate #defines to override
00052     code where a unique implementation is needed:
00053 
00054     {
00055         #define a bunch of stuff
00056         #include <aoutx.h>
00057 
00058         implement a bunch of functions
00059 
00060         #include "aout-target.h"
00061     }
00062 
00063     The hp symbol table is a bit different than other a.out targets.  Instead
00064     of having an array of nlist items and an array of strings, hp's format
00065     has them mixed together in one structure.  In addition, the strings are
00066     not null terminated.  It looks something like this:
00067 
00068     nlist element 1
00069     string1
00070     nlist element 2
00071     string2
00072     ...
00073 
00074     The whole symbol table is read as one chunk and then we march thru it
00075     and convert it to canonical form.  As we march thru the table, we copy
00076     the nlist data into the internal form and we compact the strings and null
00077     terminate them, using storage from the already allocated symbol table:
00078 
00079     string1
00080     null
00081     string2
00082     null
00083  */
00084 
00085 /* @@ Is this really so different from normal a.out that it needs to include
00086    aoutx.h?  We should go through this file sometime and see what can be made
00087    more dependent on aout32.o and what might need to be broken off and accessed
00088    through the backend_data field.  Or, maybe we really do need such a
00089    completely separate implementation.  I don't have time to investigate this
00090    much further right now.  [raeburn:19930428.2124EST] */
00091 /* @@ Also, note that there wind up being two versions of some routines, with
00092    different names, only one of which actually gets used.  For example:
00093        slurp_symbol_table
00094        swap_std_reloc_in
00095        slurp_reloc_table
00096        canonicalize_symtab
00097        get_symtab_upper_bound
00098        canonicalize_reloc
00099        mkobject
00100    This should also be fixed.  */
00101 
00102 #define TARGETNAME "a.out-hp300hpux"
00103 
00104 /* Do not "beautify" the CONCAT* macro args.  Traditional C will not
00105    remove whitespace added here, and thus will fail to concatenate
00106    the tokens.  */
00107 #define MY(OP) CONCAT2 (hp300hpux_,OP)
00108 
00109 #define external_exec hp300hpux_exec_bytes
00110 #define external_nlist hp300hpux_nlist_bytes
00111 
00112 #include "aout/hp300hpux.h"
00113 
00114 /* define these so we can compile unused routines in aoutx.h */
00115 #define e_strx  e_shlib
00116 #define e_other e_length
00117 #define e_desc  e_almod
00118 
00119 #define AR_PAD_CHAR '/'
00120 #define TARGET_IS_BIG_ENDIAN_P
00121 #define DEFAULT_ARCH bfd_arch_m68k
00122 
00123 #define MY_get_section_contents aout_32_get_section_contents
00124 #define MY_slurp_armap bfd_slurp_bsd_armap_f2
00125 
00126 /***********************************************/
00127 /* provide overrides for routines in this file */
00128 /***********************************************/
00129 /* these don't use MY because that causes problems within JUMP_TABLE
00130    (CONCAT2 winds up being expanded recursively, which ANSI C compilers
00131    will not do).  */
00132 #define MY_canonicalize_symtab hp300hpux_canonicalize_symtab
00133 #define MY_get_symtab_upper_bound hp300hpux_get_symtab_upper_bound
00134 #define MY_canonicalize_reloc hp300hpux_canonicalize_reloc
00135 #define MY_write_object_contents hp300hpux_write_object_contents
00136 
00137 #define MY_read_minisymbols _bfd_generic_read_minisymbols
00138 #define MY_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
00139 
00140 #define MY_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
00141 #define MY_bfd_link_add_symbols _bfd_generic_link_add_symbols
00142 #define MY_final_link_callback unused
00143 #define MY_bfd_final_link _bfd_generic_final_link
00144 
00145 /* Until and unless we convert the slurp_reloc and slurp_symtab
00146    routines in this file, we can not use the default aout
00147    free_cached_info routine which assumes that the relocs and symtabs
00148    were allocated using malloc.  */
00149 #define MY_bfd_free_cached_info bfd_true
00150 
00151 #define hp300hpux_write_syms aout_32_write_syms
00152 
00153 #define MY_callback MY(callback)
00154 
00155 #define MY_exec_hdr_flags 0x2
00156 
00157 #define NAME_swap_exec_header_in NAME(hp300hpux_32_,swap_exec_header_in)
00158 
00159 #define HP_SYMTYPE_UNDEFINED       0x00
00160 #define HP_SYMTYPE_ABSOLUTE 0x01
00161 #define HP_SYMTYPE_TEXT            0x02
00162 #define HP_SYMTYPE_DATA            0x03
00163 #define HP_SYMTYPE_BSS             0x04
00164 #define HP_SYMTYPE_COMMON   0x05
00165 
00166 #define HP_SYMTYPE_TYPE            0x0F
00167 #define HP_SYMTYPE_FILENAME 0x1F
00168 
00169 #define HP_SYMTYPE_ALIGN    0x10
00170 #define HP_SYMTYPE_EXTERNAL 0x20
00171 #define HP_SECONDARY_SYMBOL     0x40
00172 
00173 /* RELOCATION DEFINITIONS */
00174 #define HP_RSEGMENT_TEXT    0x00
00175 #define HP_RSEGMENT_DATA    0x01
00176 #define HP_RSEGMENT_BSS            0x02
00177 #define HP_RSEGMENT_EXTERNAL       0x03
00178 #define HP_RSEGMENT_PCREL       0x04
00179 #define HP_RSEGMENT_RDLT        0x05
00180 #define HP_RSEGMENT_RPLT        0x06
00181 #define HP_RSEGMENT_NOOP    0x3F
00182 
00183 #define HP_RLENGTH_BYTE            0x00
00184 #define HP_RLENGTH_WORD            0x01
00185 #define HP_RLENGTH_LONG            0x02
00186 #define HP_RLENGTH_ALIGN    0x03
00187 
00188 #define NAME(x,y) CONCAT3 (hp300hpux,_32_,y)
00189 #define ARCH_SIZE 32
00190 
00191 /* aoutx.h requires definitions for BMAGIC and QMAGIC.  */
00192 #define BMAGIC HPUX_DOT_O_MAGIC
00193 #define QMAGIC 0314
00194 
00195 #include "aoutx.h"
00196 
00197 static const bfd_target * MY (callback)
00198   PARAMS ((bfd *));
00199 static bfd_boolean MY (write_object_contents)
00200   PARAMS ((bfd *));
00201 static void convert_sym_type
00202   PARAMS ((struct external_nlist *, aout_symbol_type *, bfd *));
00203 
00204 bfd_boolean MY (slurp_symbol_table)
00205   PARAMS ((bfd *));
00206 void MY (swap_std_reloc_in)
00207   PARAMS ((bfd *, struct hp300hpux_reloc *, arelent *, asymbol **,
00208           bfd_size_type));
00209 bfd_boolean MY (slurp_reloc_table)
00210   PARAMS ((bfd *, sec_ptr, asymbol **));
00211 long MY (canonicalize_symtab)
00212   PARAMS ((bfd *, asymbol **));
00213 long MY (get_symtab_upper_bound)
00214   PARAMS ((bfd *));
00215 long MY (canonicalize_reloc)
00216   PARAMS ((bfd *, sec_ptr, arelent **, asymbol **));
00217 
00218 /* Since the hpux symbol table has nlist elements interspersed with
00219    strings and we need to insert som strings for secondary symbols, we
00220    give ourselves a little extra padding up front to account for
00221    this.  Note that for each non-secondary symbol we process, we gain
00222    9 bytes of space for the discarded nlist element (one byte used for
00223    null).  SYM_EXTRA_BYTES is the extra space.  */
00224 #define SYM_EXTRA_BYTES   1024
00225 
00226 /* Set parameters about this a.out file that are machine-dependent.
00227    This routine is called from some_aout_object_p just before it returns.  */
00228 static const bfd_target *
00229 MY (callback) (abfd)
00230      bfd *abfd;
00231 {
00232   struct internal_exec *execp = exec_hdr (abfd);
00233 
00234   /* Calculate the file positions of the parts of a newly read aout header */
00235   obj_textsec (abfd)->size = N_TXTSIZE (*execp);
00236 
00237   /* The virtual memory addresses of the sections */
00238   obj_textsec (abfd)->vma = N_TXTADDR (*execp);
00239   obj_datasec (abfd)->vma = N_DATADDR (*execp);
00240   obj_bsssec (abfd)->vma = N_BSSADDR (*execp);
00241 
00242   obj_textsec (abfd)->lma = obj_textsec (abfd)->vma;
00243   obj_datasec (abfd)->lma = obj_datasec (abfd)->vma;
00244   obj_bsssec (abfd)->lma = obj_bsssec (abfd)->vma;
00245 
00246   /* The file offsets of the sections */
00247   obj_textsec (abfd)->filepos = N_TXTOFF (*execp);
00248   obj_datasec (abfd)->filepos = N_DATOFF (*execp);
00249 
00250   /* The file offsets of the relocation info */
00251   obj_textsec (abfd)->rel_filepos = N_TRELOFF (*execp);
00252   obj_datasec (abfd)->rel_filepos = N_DRELOFF (*execp);
00253 
00254   /* The file offsets of the string table and symbol table.  */
00255   obj_sym_filepos (abfd) = N_SYMOFF (*execp);
00256   obj_str_filepos (abfd) = N_STROFF (*execp);
00257 
00258   /* Determine the architecture and machine type of the object file.  */
00259 #ifdef SET_ARCH_MACH
00260   SET_ARCH_MACH (abfd, *execp);
00261 #else
00262   bfd_default_set_arch_mach (abfd, DEFAULT_ARCH, 0);
00263 #endif
00264 
00265   if (obj_aout_subformat (abfd) == gnu_encap_format)
00266     {
00267       /* The file offsets of the relocation info */
00268       obj_textsec (abfd)->rel_filepos = N_GNU_TRELOFF (*execp);
00269       obj_datasec (abfd)->rel_filepos = N_GNU_DRELOFF (*execp);
00270 
00271       /* The file offsets of the string table and symbol table.  */
00272       obj_sym_filepos (abfd) = N_GNU_SYMOFF (*execp);
00273       obj_str_filepos (abfd) = (obj_sym_filepos (abfd) + execp->a_syms);
00274 
00275       abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
00276       bfd_get_symcount (abfd) = execp->a_syms / 12;
00277       obj_symbol_entry_size (abfd) = 12;
00278       obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
00279     }
00280 
00281   return abfd->xvec;
00282 }
00283 
00284 extern bfd_boolean aout_32_write_syms
00285   PARAMS ((bfd * abfd));
00286 
00287 static bfd_boolean
00288 MY (write_object_contents) (abfd)
00289      bfd *abfd;
00290 {
00291   struct external_exec exec_bytes;
00292   struct internal_exec *execp = exec_hdr (abfd);
00293   bfd_size_type text_size;  /* dummy vars */
00294   file_ptr text_end;
00295 
00296   memset (&exec_bytes, 0, sizeof (exec_bytes));
00297 
00298   obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
00299 
00300   if (adata (abfd).magic == undecided_magic)
00301     NAME (aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end);
00302   execp->a_syms = 0;
00303 
00304   execp->a_entry = bfd_get_start_address (abfd);
00305 
00306   execp->a_trsize = ((obj_textsec (abfd)->reloc_count) *
00307                    obj_reloc_entry_size (abfd));
00308   execp->a_drsize = ((obj_datasec (abfd)->reloc_count) *
00309                    obj_reloc_entry_size (abfd));
00310 
00311   N_SET_MACHTYPE (*execp, 0xc);
00312   N_SET_FLAGS (*execp, aout_backend_info (abfd)->exec_hdr_flags);
00313 
00314   NAME (aout,swap_exec_header_out) (abfd, execp, &exec_bytes);
00315 
00316   /* update fields not covered by default swap_exec_header_out */
00317 
00318   /* this is really the sym table size but we store it in drelocs */
00319   H_PUT_32 (abfd, (bfd_get_symcount (abfd) * 12), exec_bytes.e_drelocs);
00320 
00321   if (bfd_seek (abfd, (file_ptr) 0, FALSE) != 0
00322       || (bfd_bwrite ((PTR) &exec_bytes, (bfd_size_type) EXEC_BYTES_SIZE, abfd)
00323          != EXEC_BYTES_SIZE))
00324     return FALSE;
00325 
00326   /* Write out the symbols, and then the relocs.  We must write out
00327        the symbols first so that we know the symbol indices.  */
00328 
00329   if (bfd_get_symcount (abfd) != 0)
00330     {
00331       /* Skip the relocs to where we want to put the symbols.  */
00332       if (bfd_seek (abfd, (file_ptr) (N_DRELOFF (*execp) + execp->a_drsize),
00333                   SEEK_SET) != 0)
00334        return FALSE;
00335     }
00336 
00337   if (!MY (write_syms) (abfd))
00338     return FALSE;
00339 
00340   if (bfd_get_symcount (abfd) != 0)
00341     {
00342       if (bfd_seek (abfd, (file_ptr) N_TRELOFF (*execp), SEEK_CUR) != 0)
00343        return FALSE;
00344       if (!NAME (aout,squirt_out_relocs) (abfd, obj_textsec (abfd)))
00345        return FALSE;
00346       if (bfd_seek (abfd, (file_ptr) N_DRELOFF (*execp), SEEK_CUR) != 0)
00347        return FALSE;
00348       if (!NAME (aout,squirt_out_relocs) (abfd, obj_datasec (abfd)))
00349        return FALSE;
00350     }
00351 
00352   return TRUE;
00353 }
00354 
00355 /* convert the hp symbol type to be the same as aout64.h usage so we */
00356 /* can piggyback routines in aoutx.h.                                */
00357 
00358 static void
00359 convert_sym_type (sym_pointer, cache_ptr, abfd)
00360      struct external_nlist *sym_pointer ATTRIBUTE_UNUSED;
00361      aout_symbol_type *cache_ptr;
00362      bfd *abfd ATTRIBUTE_UNUSED;
00363 {
00364   int name_type;
00365   int new_type;
00366 
00367   name_type = (cache_ptr->type);
00368   new_type = 0;
00369 
00370   if ((name_type & HP_SYMTYPE_ALIGN) != 0)
00371     {
00372       /* iou_error ("aligned symbol encountered: %s", name);*/
00373       name_type = 0;
00374     }
00375 
00376   if (name_type == HP_SYMTYPE_FILENAME)
00377     new_type = N_FN;
00378   else
00379     {
00380       switch (name_type & HP_SYMTYPE_TYPE)
00381        {
00382        case HP_SYMTYPE_UNDEFINED:
00383          new_type = N_UNDF;
00384          break;
00385 
00386        case HP_SYMTYPE_ABSOLUTE:
00387          new_type = N_ABS;
00388          break;
00389 
00390        case HP_SYMTYPE_TEXT:
00391          new_type = N_TEXT;
00392          break;
00393 
00394        case HP_SYMTYPE_DATA:
00395          new_type = N_DATA;
00396          break;
00397 
00398        case HP_SYMTYPE_BSS:
00399          new_type = N_BSS;
00400          break;
00401 
00402        case HP_SYMTYPE_COMMON:
00403          new_type = N_COMM;
00404          break;
00405 
00406        default:
00407          abort ();
00408          break;
00409        }
00410       if (name_type & HP_SYMTYPE_EXTERNAL)
00411        new_type |= N_EXT;
00412 
00413       if (name_type & HP_SECONDARY_SYMBOL)
00414        {
00415          switch (new_type)
00416            {
00417            default:
00418              abort ();
00419            case N_UNDF | N_EXT:
00420              /* If the value is nonzero, then just treat this as a
00421                  common symbol.  I don't know if this is correct in
00422                  all cases, but it is more correct than treating it as
00423                  a weak undefined symbol.  */
00424              if (cache_ptr->symbol.value == 0)
00425               new_type = N_WEAKU;
00426              break;
00427            case N_ABS | N_EXT:
00428              new_type = N_WEAKA;
00429              break;
00430            case N_TEXT | N_EXT:
00431              new_type = N_WEAKT;
00432              break;
00433            case N_DATA | N_EXT:
00434              new_type = N_WEAKD;
00435              break;
00436            case N_BSS | N_EXT:
00437              new_type = N_WEAKB;
00438              break;
00439            }
00440        }
00441     }
00442   cache_ptr->type = new_type;
00443 
00444 }
00445 
00446 /*
00447 DESCRIPTION
00448         Swaps the information in an executable header taken from a raw
00449         byte stream memory image, into the internal exec_header
00450         structure.
00451 */
00452 
00453 void
00454 NAME (aout,swap_exec_header_in) (abfd, raw_bytes, execp)
00455      bfd *abfd;
00456      struct external_exec *raw_bytes;
00457      struct internal_exec *execp;
00458 {
00459   struct external_exec *bytes = (struct external_exec *) raw_bytes;
00460 
00461   /* The internal_exec structure has some fields that are unused in this
00462      configuration (IE for i960), so ensure that all such uninitialized
00463      fields are zero'd out.  There are places where two of these structs
00464      are memcmp'd, and thus the contents do matter. */
00465   memset (execp, 0, sizeof (struct internal_exec));
00466   /* Now fill in fields in the execp, from the bytes in the raw data.  */
00467   execp->a_info = H_GET_32 (abfd, bytes->e_info);
00468   execp->a_text = GET_WORD (abfd, bytes->e_text);
00469   execp->a_data = GET_WORD (abfd, bytes->e_data);
00470   execp->a_bss = GET_WORD (abfd, bytes->e_bss);
00471   execp->a_syms = GET_WORD (abfd, bytes->e_syms);
00472   execp->a_entry = GET_WORD (abfd, bytes->e_entry);
00473   execp->a_trsize = GET_WORD (abfd, bytes->e_trsize);
00474   execp->a_drsize = GET_WORD (abfd, bytes->e_drsize);
00475 
00476   /***************************************************************/
00477   /* check the header to see if it was generated by a bfd output */
00478   /* this is detected rather bizarrely by requiring a bunch of   */
00479   /* header fields to be zero and an old unused field (now used) */
00480   /* to be set.                                                  */
00481   /***************************************************************/
00482   do
00483     {
00484       long syms;
00485       struct aout_data_struct *rawptr;
00486       bfd_size_type amt;
00487 
00488       if (H_GET_32 (abfd, bytes->e_passize) != 0)
00489        break;
00490       if (H_GET_32 (abfd, bytes->e_syms) != 0)
00491        break;
00492       if (H_GET_32 (abfd, bytes->e_supsize) != 0)
00493        break;
00494 
00495       syms = H_GET_32 (abfd, bytes->e_drelocs);
00496       if (syms == 0)
00497        break;
00498 
00499       /* OK, we've passed the test as best as we can determine */
00500       execp->a_syms = syms;
00501 
00502       /* allocate storage for where we will store this result */
00503       amt = sizeof (*rawptr);
00504       rawptr = (struct aout_data_struct *) bfd_zalloc (abfd, amt);
00505 
00506       if (rawptr == NULL)
00507        return;
00508       abfd->tdata.aout_data = rawptr;
00509       obj_aout_subformat (abfd) = gnu_encap_format;
00510     }
00511   while (0);
00512 }
00513 
00514 /* The hp symbol table is a bit different than other a.out targets.  Instead
00515    of having an array of nlist items and an array of strings, hp's format
00516    has them mixed together in one structure.  In addition, the strings are
00517    not null terminated.  It looks something like this:
00518 
00519    nlist element 1
00520    string1
00521    nlist element 2
00522    string2
00523    ...
00524 
00525    The whole symbol table is read as one chunk and then we march thru it
00526    and convert it to canonical form.  As we march thru the table, we copy
00527    the nlist data into the internal form and we compact the strings and null
00528    terminate them, using storage from the already allocated symbol table:
00529 
00530    string1
00531    null
00532    string2
00533    null
00534    ...
00535 */
00536 
00537 bfd_boolean
00538 MY (slurp_symbol_table) (abfd)
00539      bfd *abfd;
00540 {
00541   bfd_size_type symbol_bytes;
00542   struct external_nlist *syms;
00543   struct external_nlist *sym_pointer;
00544   struct external_nlist *sym_end;
00545   char *strings;
00546   aout_symbol_type *cached;
00547   unsigned num_syms = 0;
00548   bfd_size_type amt;
00549 
00550   /* If there's no work to be done, don't do any */
00551   if (obj_aout_symbols (abfd) != (aout_symbol_type *) NULL)
00552     return TRUE;
00553   symbol_bytes = exec_hdr (abfd)->a_syms;
00554 
00555   amt = symbol_bytes + SYM_EXTRA_BYTES;
00556   strings = (char *) bfd_alloc (abfd, amt);
00557   if (!strings)
00558     return FALSE;
00559   syms = (struct external_nlist *) (strings + SYM_EXTRA_BYTES);
00560   if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0
00561       || bfd_bread ((PTR) syms, symbol_bytes, abfd) != symbol_bytes)
00562     {
00563       bfd_release (abfd, syms);
00564       return FALSE;
00565     }
00566 
00567   sym_end = (struct external_nlist *) (((char *) syms) + symbol_bytes);
00568 
00569   /* first, march thru the table and figure out how many symbols there are */
00570   for (sym_pointer = syms; sym_pointer < sym_end; sym_pointer++, num_syms++)
00571     {
00572       /* skip over the embedded symbol. */
00573       sym_pointer = (struct external_nlist *) (((char *) sym_pointer) +
00574                                           sym_pointer->e_length[0]);
00575     }
00576 
00577   /* now that we know the symbol count, update the bfd header */
00578   bfd_get_symcount (abfd) = num_syms;
00579 
00580   amt = num_syms;
00581   amt *= sizeof (aout_symbol_type);
00582   cached = (aout_symbol_type *) bfd_zalloc (abfd, amt);
00583   if (cached == NULL && num_syms != 0)
00584     return FALSE;
00585 
00586   /* as we march thru the hp symbol table, convert it into a list of
00587      null terminated strings to hold the symbol names.  Make sure any
00588      assignment to the strings pointer is done after we're thru using
00589      the nlist so we don't overwrite anything important. */
00590 
00591   /* OK, now walk the new symtable, caching symbol properties */
00592   {
00593     aout_symbol_type *cache_ptr = cached;
00594     aout_symbol_type cache_save;
00595     /* Run through table and copy values */
00596     for (sym_pointer = syms, cache_ptr = cached;
00597         sym_pointer < sym_end; sym_pointer++, cache_ptr++)
00598       {
00599        unsigned int length;
00600        cache_ptr->symbol.the_bfd = abfd;
00601        cache_ptr->symbol.value = GET_SWORD (abfd, sym_pointer->e_value);
00602        cache_ptr->desc = bfd_get_16 (abfd, sym_pointer->e_almod);
00603        cache_ptr->type = bfd_get_8 (abfd, sym_pointer->e_type);
00604        cache_ptr->symbol.udata.p = NULL;
00605        length = bfd_get_8 (abfd, sym_pointer->e_length);
00606        cache_ptr->other = length;  /* other not used, save length here */
00607 
00608        cache_save = *cache_ptr;
00609        convert_sym_type (sym_pointer, cache_ptr, abfd);
00610        if (!translate_from_native_sym_flags (abfd, cache_ptr))
00611          return FALSE;
00612 
00613        /********************************************************/
00614        /* for hpux, the 'length' value indicates the length of */
00615        /* the symbol name which follows the nlist entry.       */
00616        /********************************************************/
00617        if (length)
00618          {
00619            /**************************************************************/
00620            /* the hp string is not null terminated so we create a new one*/
00621            /* by copying the string to overlap the just vacated nlist    */
00622            /* structure before it in memory.                             */
00623            /**************************************************************/
00624            cache_ptr->symbol.name = strings;
00625            memcpy (strings, sym_pointer + 1, length);
00626            strings[length] = '\0';
00627            strings += length + 1;
00628          }
00629        else
00630          cache_ptr->symbol.name = (char *) NULL;
00631 
00632        /* skip over the embedded symbol. */
00633        sym_pointer = (struct external_nlist *) (((char *) sym_pointer) +
00634                                            length);
00635       }
00636   }
00637 
00638   obj_aout_symbols (abfd) = cached;
00639 
00640   return TRUE;
00641 }
00642 
00643 void
00644 MY (swap_std_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount)
00645      bfd *abfd;
00646      struct hp300hpux_reloc *bytes;
00647      arelent *cache_ptr;
00648      asymbol **symbols;
00649      bfd_size_type symcount ATTRIBUTE_UNUSED;
00650 {
00651   int r_index;
00652   int r_extern = 0;
00653   unsigned int r_length;
00654   int r_pcrel = 0;
00655   struct aoutdata *su = &(abfd->tdata.aout_data->a);
00656 
00657   cache_ptr->address = H_GET_32 (abfd, bytes->r_address);
00658   r_index = H_GET_16 (abfd, bytes->r_index);
00659 
00660   switch (bytes->r_type[0])
00661     {
00662     case HP_RSEGMENT_TEXT:
00663       r_index = N_TEXT;
00664       break;
00665     case HP_RSEGMENT_DATA:
00666       r_index = N_DATA;
00667       break;
00668     case HP_RSEGMENT_BSS:
00669       r_index = N_BSS;
00670       break;
00671     case HP_RSEGMENT_EXTERNAL:
00672       r_extern = 1;
00673       break;
00674     case HP_RSEGMENT_PCREL:
00675       r_extern = 1;
00676       r_pcrel = 1;
00677       break;
00678     case HP_RSEGMENT_RDLT:
00679       break;
00680     case HP_RSEGMENT_RPLT:
00681       break;
00682     case HP_RSEGMENT_NOOP:
00683       break;
00684     default:
00685       abort ();
00686       break;
00687     }
00688 
00689   switch (bytes->r_length[0])
00690     {
00691     case HP_RLENGTH_BYTE:
00692       r_length = 0;
00693       break;
00694     case HP_RLENGTH_WORD:
00695       r_length = 1;
00696       break;
00697     case HP_RLENGTH_LONG:
00698       r_length = 2;
00699       break;
00700     default:
00701       abort ();
00702       break;
00703     }
00704 
00705   cache_ptr->howto = howto_table_std + r_length + 4 * r_pcrel;
00706   /* FIXME-soon:  Roll baserel, jmptable, relative bits into howto setting */
00707 
00708   /* This macro uses the r_index value computed above */
00709   if (r_pcrel && r_extern)
00710     {
00711       /* The GNU linker assumes any offset from beginning of section */
00712       /* is already incorporated into the image while the HP linker  */
00713       /* adds this in later.  Add it in now...                       */
00714       MOVE_ADDRESS (-cache_ptr->address);
00715     }
00716   else
00717     {
00718       MOVE_ADDRESS (0);
00719     }
00720 }
00721 
00722 bfd_boolean
00723 MY (slurp_reloc_table) (abfd, asect, symbols)
00724      bfd *abfd;
00725      sec_ptr asect;
00726      asymbol **symbols;
00727 {
00728   bfd_size_type count;
00729   bfd_size_type reloc_size;
00730   PTR relocs;
00731   arelent *reloc_cache;
00732   size_t each_size;
00733   struct hp300hpux_reloc *rptr;
00734   unsigned int counter;
00735   arelent *cache_ptr;
00736 
00737   if (asect->relocation)
00738     return TRUE;
00739 
00740   if (asect->flags & SEC_CONSTRUCTOR)
00741     return TRUE;
00742 
00743   if (asect == obj_datasec (abfd))
00744     {
00745       reloc_size = exec_hdr (abfd)->a_drsize;
00746       goto doit;
00747     }
00748 
00749   if (asect == obj_textsec (abfd))
00750     {
00751       reloc_size = exec_hdr (abfd)->a_trsize;
00752       goto doit;
00753     }
00754 
00755   bfd_set_error (bfd_error_invalid_operation);
00756   return FALSE;
00757 
00758 doit:
00759   if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
00760     return FALSE;
00761   each_size = obj_reloc_entry_size (abfd);
00762 
00763   count = reloc_size / each_size;
00764 
00765   reloc_cache = (arelent *) bfd_zalloc (abfd, count * sizeof (arelent));
00766   if (!reloc_cache && count != 0)
00767     return FALSE;
00768 
00769   relocs = (PTR) bfd_alloc (abfd, reloc_size);
00770   if (!relocs && reloc_size != 0)
00771     {
00772       bfd_release (abfd, reloc_cache);
00773       return FALSE;
00774     }
00775 
00776   if (bfd_bread (relocs, reloc_size, abfd) != reloc_size)
00777     {
00778       bfd_release (abfd, relocs);
00779       bfd_release (abfd, reloc_cache);
00780       return FALSE;
00781     }
00782 
00783   rptr = (struct hp300hpux_reloc *) relocs;
00784   counter = 0;
00785   cache_ptr = reloc_cache;
00786 
00787   for (; counter < count; counter++, rptr++, cache_ptr++)
00788     {
00789       MY (swap_std_reloc_in) (abfd, rptr, cache_ptr, symbols,
00790                            (bfd_size_type) bfd_get_symcount (abfd));
00791     }
00792 
00793   bfd_release (abfd, relocs);
00794   asect->relocation = reloc_cache;
00795   asect->reloc_count = count;
00796   return TRUE;
00797 }
00798 
00799 /************************************************************************/
00800 /* The following functions are identical to functions in aoutx.h except */
00801 /* they refer to MY(func) rather than NAME(aout,func) and they also     */
00802 /* call aout_32 versions if the input file was generated by gcc         */
00803 /************************************************************************/
00804 
00805 long aout_32_canonicalize_symtab
00806   PARAMS ((bfd * abfd, asymbol ** location));
00807 long aout_32_get_symtab_upper_bound
00808   PARAMS ((bfd * abfd));
00809 long aout_32_canonicalize_reloc
00810   PARAMS ((bfd * abfd, sec_ptr section, arelent ** relptr,
00811           asymbol ** symbols));
00812 
00813 long
00814 MY (canonicalize_symtab) (abfd, location)
00815      bfd *abfd;
00816      asymbol **location;
00817 {
00818   unsigned int counter = 0;
00819   aout_symbol_type *symbase;
00820 
00821   if (obj_aout_subformat (abfd) == gnu_encap_format)
00822     return aout_32_canonicalize_symtab (abfd, location);
00823 
00824   if (!MY (slurp_symbol_table) (abfd))
00825     return -1;
00826 
00827   for (symbase = obj_aout_symbols (abfd); counter++ < bfd_get_symcount (abfd);)
00828     *(location++) = (asymbol *) (symbase++);
00829   *location++ = 0;
00830   return bfd_get_symcount (abfd);
00831 }
00832 
00833 long
00834 MY (get_symtab_upper_bound) (abfd)
00835      bfd *abfd;
00836 {
00837   if (obj_aout_subformat (abfd) == gnu_encap_format)
00838     return aout_32_get_symtab_upper_bound (abfd);
00839   if (!MY (slurp_symbol_table) (abfd))
00840     return -1;
00841 
00842   return (bfd_get_symcount (abfd) + 1) * (sizeof (aout_symbol_type *));
00843 }
00844 
00845 long
00846 MY (canonicalize_reloc) (abfd, section, relptr, symbols)
00847      bfd *abfd;
00848      sec_ptr section;
00849      arelent **relptr;
00850      asymbol **symbols;
00851 {
00852   arelent *tblptr = section->relocation;
00853   unsigned int count;
00854   if (obj_aout_subformat (abfd) == gnu_encap_format)
00855     return aout_32_canonicalize_reloc (abfd, section, relptr, symbols);
00856 
00857   if (!(tblptr || MY (slurp_reloc_table) (abfd, section, symbols)))
00858     return -1;
00859 
00860   if (section->flags & SEC_CONSTRUCTOR)
00861     {
00862       arelent_chain *chain = section->constructor_chain;
00863       for (count = 0; count < section->reloc_count; count++)
00864        {
00865          *relptr++ = &chain->relent;
00866          chain = chain->next;
00867        }
00868     }
00869   else
00870     {
00871       tblptr = section->relocation;
00872 
00873       for (count = 0; count++ < section->reloc_count;)
00874        {
00875          *relptr++ = tblptr++;
00876        }
00877     }
00878   *relptr = 0;
00879 
00880   return section->reloc_count;
00881 }
00882 
00883 #include "aout-target.h"