12159047fSniklas /* BFD backend for hp-ux 9000/300
2*007c2a45Smiod Copyright 1990, 1991, 1993, 1994, 1995, 1997, 2000, 2001, 2002, 2003
3b55d4692Sfgsch Free Software Foundation, Inc.
42159047fSniklas Written by Glenn Engel.
52159047fSniklas
62159047fSniklas This file is part of BFD, the Binary File Descriptor library.
72159047fSniklas
82159047fSniklas This program is free software; you can redistribute it and/or modify
92159047fSniklas it under the terms of the GNU General Public License as published by
102159047fSniklas the Free Software Foundation; either version 2 of the License, or
112159047fSniklas (at your option) any later version.
122159047fSniklas
132159047fSniklas This program is distributed in the hope that it will be useful,
142159047fSniklas but WITHOUT ANY WARRANTY; without even the implied warranty of
152159047fSniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
162159047fSniklas GNU General Public License for more details.
172159047fSniklas
182159047fSniklas You should have received a copy of the GNU General Public License
192159047fSniklas along with this program; if not, write to the Free Software
202159047fSniklas Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
212159047fSniklas
222159047fSniklas /*
232159047fSniklas hpux native ------------> | |
242159047fSniklas | hp300hpux bfd | ----------> hpux w/gnu ext
252159047fSniklas hpux w/gnu extension ----> | |
262159047fSniklas
272159047fSniklas Support for the 9000/[34]00 has several limitations.
282159047fSniklas 1. Shared libraries are not supported.
292159047fSniklas 2. The output format from this bfd is not usable by native tools.
302159047fSniklas
312159047fSniklas The primary motivation for writing this bfd was to allow use of
322159047fSniklas gdb and gcc for host based debugging and not to mimic the hp-ux tools
332159047fSniklas in every detail. This leads to a significant simplification of the
342159047fSniklas code and a leap in performance. The decision to not output hp native
352159047fSniklas compatible objects was further strengthened by the fact that the richness
362159047fSniklas of the gcc compiled objects could not be represented without loss of
372159047fSniklas information. For example, while the hp format supports the concept of
382159047fSniklas secondary symbols, it does not support indirect symbols. Another
392159047fSniklas reason is to maintain backwards compatibility with older implementations
402159047fSniklas of gcc on hpux which used 'hpxt' to translate .a and .o files into a
412159047fSniklas format which could be readily understood by the gnu linker and gdb.
422159047fSniklas This allows reading hp secondary symbols and converting them into
432159047fSniklas indirect symbols but the reverse it not always possible.
442159047fSniklas
452159047fSniklas Another example of differences is that the hp format stores symbol offsets
462159047fSniklas in the object code while the gnu utilities use a field in the
472159047fSniklas relocation record for this. To support the hp native format, the object
482159047fSniklas code would need to be patched with the offsets when producing .o files.
492159047fSniklas
502159047fSniklas The basic technique taken in this implementation is to #include the code
512159047fSniklas from aoutx.h and aout-target.h with appropriate #defines to override
522159047fSniklas code where a unique implementation is needed:
532159047fSniklas
542159047fSniklas {
552159047fSniklas #define a bunch of stuff
562159047fSniklas #include <aoutx.h>
572159047fSniklas
582159047fSniklas implement a bunch of functions
592159047fSniklas
602159047fSniklas #include "aout-target.h"
612159047fSniklas }
622159047fSniklas
632159047fSniklas The hp symbol table is a bit different than other a.out targets. Instead
642159047fSniklas of having an array of nlist items and an array of strings, hp's format
652159047fSniklas has them mixed together in one structure. In addition, the strings are
662159047fSniklas not null terminated. It looks something like this:
672159047fSniklas
682159047fSniklas nlist element 1
692159047fSniklas string1
702159047fSniklas nlist element 2
712159047fSniklas string2
722159047fSniklas ...
732159047fSniklas
742159047fSniklas The whole symbol table is read as one chunk and then we march thru it
752159047fSniklas and convert it to canonical form. As we march thru the table, we copy
762159047fSniklas the nlist data into the internal form and we compact the strings and null
772159047fSniklas terminate them, using storage from the already allocated symbol table:
782159047fSniklas
792159047fSniklas string1
802159047fSniklas null
812159047fSniklas string2
822159047fSniklas null
832159047fSniklas */
842159047fSniklas
852159047fSniklas /* @@ Is this really so different from normal a.out that it needs to include
862159047fSniklas aoutx.h? We should go through this file sometime and see what can be made
872159047fSniklas more dependent on aout32.o and what might need to be broken off and accessed
882159047fSniklas through the backend_data field. Or, maybe we really do need such a
892159047fSniklas completely separate implementation. I don't have time to investigate this
902159047fSniklas much further right now. [raeburn:19930428.2124EST] */
912159047fSniklas /* @@ Also, note that there wind up being two versions of some routines, with
922159047fSniklas different names, only one of which actually gets used. For example:
932159047fSniklas slurp_symbol_table
942159047fSniklas swap_std_reloc_in
952159047fSniklas slurp_reloc_table
96*007c2a45Smiod canonicalize_symtab
972159047fSniklas get_symtab_upper_bound
982159047fSniklas canonicalize_reloc
992159047fSniklas mkobject
1002159047fSniklas This should also be fixed. */
1012159047fSniklas
1022159047fSniklas #define TARGETNAME "a.out-hp300hpux"
103c074d1c9Sdrahn
104c074d1c9Sdrahn /* Do not "beautify" the CONCAT* macro args. Traditional C will not
105c074d1c9Sdrahn remove whitespace added here, and thus will fail to concatenate
106c074d1c9Sdrahn the tokens. */
107c074d1c9Sdrahn #define MY(OP) CONCAT2 (hp300hpux_,OP)
1082159047fSniklas
1092159047fSniklas #define external_exec hp300hpux_exec_bytes
1102159047fSniklas #define external_nlist hp300hpux_nlist_bytes
1112159047fSniklas
1122159047fSniklas #include "aout/hp300hpux.h"
1132159047fSniklas
1142159047fSniklas /* define these so we can compile unused routines in aoutx.h */
1152159047fSniklas #define e_strx e_shlib
1162159047fSniklas #define e_other e_length
1172159047fSniklas #define e_desc e_almod
1182159047fSniklas
1192159047fSniklas #define AR_PAD_CHAR '/'
1202159047fSniklas #define TARGET_IS_BIG_ENDIAN_P
1212159047fSniklas #define DEFAULT_ARCH bfd_arch_m68k
1222159047fSniklas
1232159047fSniklas #define MY_get_section_contents aout_32_get_section_contents
1242159047fSniklas #define MY_slurp_armap bfd_slurp_bsd_armap_f2
1252159047fSniklas
1262159047fSniklas /***********************************************/
1272159047fSniklas /* provide overrides for routines in this file */
1282159047fSniklas /***********************************************/
1292159047fSniklas /* these don't use MY because that causes problems within JUMP_TABLE
130c074d1c9Sdrahn (CONCAT2 winds up being expanded recursively, which ANSI C compilers
1312159047fSniklas will not do). */
132*007c2a45Smiod #define MY_canonicalize_symtab hp300hpux_canonicalize_symtab
1332159047fSniklas #define MY_get_symtab_upper_bound hp300hpux_get_symtab_upper_bound
1342159047fSniklas #define MY_canonicalize_reloc hp300hpux_canonicalize_reloc
1352159047fSniklas #define MY_write_object_contents hp300hpux_write_object_contents
1362159047fSniklas
1372159047fSniklas #define MY_read_minisymbols _bfd_generic_read_minisymbols
1382159047fSniklas #define MY_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
1392159047fSniklas
1402159047fSniklas #define MY_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
1412159047fSniklas #define MY_bfd_link_add_symbols _bfd_generic_link_add_symbols
1422159047fSniklas #define MY_final_link_callback unused
1432159047fSniklas #define MY_bfd_final_link _bfd_generic_final_link
1442159047fSniklas
1452159047fSniklas /* Until and unless we convert the slurp_reloc and slurp_symtab
1462159047fSniklas routines in this file, we can not use the default aout
1472159047fSniklas free_cached_info routine which assumes that the relocs and symtabs
1482159047fSniklas were allocated using malloc. */
1492159047fSniklas #define MY_bfd_free_cached_info bfd_true
1502159047fSniklas
1512159047fSniklas #define hp300hpux_write_syms aout_32_write_syms
1522159047fSniklas
1532159047fSniklas #define MY_callback MY(callback)
1542159047fSniklas
1552159047fSniklas #define MY_exec_hdr_flags 0x2
1562159047fSniklas
1572159047fSniklas #define NAME_swap_exec_header_in NAME(hp300hpux_32_,swap_exec_header_in)
1582159047fSniklas
1592159047fSniklas #define HP_SYMTYPE_UNDEFINED 0x00
1602159047fSniklas #define HP_SYMTYPE_ABSOLUTE 0x01
1612159047fSniklas #define HP_SYMTYPE_TEXT 0x02
1622159047fSniklas #define HP_SYMTYPE_DATA 0x03
1632159047fSniklas #define HP_SYMTYPE_BSS 0x04
1642159047fSniklas #define HP_SYMTYPE_COMMON 0x05
1652159047fSniklas
1662159047fSniklas #define HP_SYMTYPE_TYPE 0x0F
1672159047fSniklas #define HP_SYMTYPE_FILENAME 0x1F
1682159047fSniklas
1692159047fSniklas #define HP_SYMTYPE_ALIGN 0x10
1702159047fSniklas #define HP_SYMTYPE_EXTERNAL 0x20
1712159047fSniklas #define HP_SECONDARY_SYMBOL 0x40
1722159047fSniklas
1732159047fSniklas /* RELOCATION DEFINITIONS */
1742159047fSniklas #define HP_RSEGMENT_TEXT 0x00
1752159047fSniklas #define HP_RSEGMENT_DATA 0x01
1762159047fSniklas #define HP_RSEGMENT_BSS 0x02
1772159047fSniklas #define HP_RSEGMENT_EXTERNAL 0x03
1782159047fSniklas #define HP_RSEGMENT_PCREL 0x04
1792159047fSniklas #define HP_RSEGMENT_RDLT 0x05
1802159047fSniklas #define HP_RSEGMENT_RPLT 0x06
1812159047fSniklas #define HP_RSEGMENT_NOOP 0x3F
1822159047fSniklas
1832159047fSniklas #define HP_RLENGTH_BYTE 0x00
1842159047fSniklas #define HP_RLENGTH_WORD 0x01
1852159047fSniklas #define HP_RLENGTH_LONG 0x02
1862159047fSniklas #define HP_RLENGTH_ALIGN 0x03
1872159047fSniklas
188c074d1c9Sdrahn #define NAME(x,y) CONCAT3 (hp300hpux,_32_,y)
1892159047fSniklas #define ARCH_SIZE 32
1902159047fSniklas
1912159047fSniklas /* aoutx.h requires definitions for BMAGIC and QMAGIC. */
1922159047fSniklas #define BMAGIC HPUX_DOT_O_MAGIC
1932159047fSniklas #define QMAGIC 0314
1942159047fSniklas
1952159047fSniklas #include "aoutx.h"
1962159047fSniklas
197c074d1c9Sdrahn static const bfd_target * MY (callback)
198c074d1c9Sdrahn PARAMS ((bfd *));
199c074d1c9Sdrahn static bfd_boolean MY (write_object_contents)
200c074d1c9Sdrahn PARAMS ((bfd *));
201c074d1c9Sdrahn static void convert_sym_type
202c074d1c9Sdrahn PARAMS ((struct external_nlist *, aout_symbol_type *, bfd *));
203c074d1c9Sdrahn
204c074d1c9Sdrahn bfd_boolean MY (slurp_symbol_table)
205c074d1c9Sdrahn PARAMS ((bfd *));
206c074d1c9Sdrahn void MY (swap_std_reloc_in)
207c074d1c9Sdrahn PARAMS ((bfd *, struct hp300hpux_reloc *, arelent *, asymbol **,
208c074d1c9Sdrahn bfd_size_type));
209c074d1c9Sdrahn bfd_boolean MY (slurp_reloc_table)
210c074d1c9Sdrahn PARAMS ((bfd *, sec_ptr, asymbol **));
211*007c2a45Smiod long MY (canonicalize_symtab)
212c074d1c9Sdrahn PARAMS ((bfd *, asymbol **));
213c074d1c9Sdrahn long MY (get_symtab_upper_bound)
214c074d1c9Sdrahn PARAMS ((bfd *));
215c074d1c9Sdrahn long MY (canonicalize_reloc)
216c074d1c9Sdrahn PARAMS ((bfd *, sec_ptr, arelent **, asymbol **));
217c074d1c9Sdrahn
2182159047fSniklas /* Since the hpux symbol table has nlist elements interspersed with
2192159047fSniklas strings and we need to insert som strings for secondary symbols, we
2202159047fSniklas give ourselves a little extra padding up front to account for
2212159047fSniklas this. Note that for each non-secondary symbol we process, we gain
2222159047fSniklas 9 bytes of space for the discarded nlist element (one byte used for
2232159047fSniklas null). SYM_EXTRA_BYTES is the extra space. */
2242159047fSniklas #define SYM_EXTRA_BYTES 1024
2252159047fSniklas
2262159047fSniklas /* Set parameters about this a.out file that are machine-dependent.
2272159047fSniklas This routine is called from some_aout_object_p just before it returns. */
2282159047fSniklas static const bfd_target *
2292159047fSniklas MY (callback) (abfd)
2302159047fSniklas bfd *abfd;
2312159047fSniklas {
2322159047fSniklas struct internal_exec *execp = exec_hdr (abfd);
2332159047fSniklas
2342159047fSniklas /* Calculate the file positions of the parts of a newly read aout header */
2352159047fSniklas obj_textsec (abfd)->_raw_size = N_TXTSIZE (*execp);
2362159047fSniklas
2372159047fSniklas /* The virtual memory addresses of the sections */
2382159047fSniklas obj_textsec (abfd)->vma = N_TXTADDR (*execp);
2392159047fSniklas obj_datasec (abfd)->vma = N_DATADDR (*execp);
2402159047fSniklas obj_bsssec (abfd)->vma = N_BSSADDR (*execp);
2412159047fSniklas
242c88b1d6cSniklas obj_textsec (abfd)->lma = obj_textsec (abfd)->vma;
243c88b1d6cSniklas obj_datasec (abfd)->lma = obj_datasec (abfd)->vma;
244c88b1d6cSniklas obj_bsssec (abfd)->lma = obj_bsssec (abfd)->vma;
245c88b1d6cSniklas
2462159047fSniklas /* The file offsets of the sections */
2472159047fSniklas obj_textsec (abfd)->filepos = N_TXTOFF (*execp);
2482159047fSniklas obj_datasec (abfd)->filepos = N_DATOFF (*execp);
2492159047fSniklas
2502159047fSniklas /* The file offsets of the relocation info */
2512159047fSniklas obj_textsec (abfd)->rel_filepos = N_TRELOFF (*execp);
2522159047fSniklas obj_datasec (abfd)->rel_filepos = N_DRELOFF (*execp);
2532159047fSniklas
2542159047fSniklas /* The file offsets of the string table and symbol table. */
2552159047fSniklas obj_sym_filepos (abfd) = N_SYMOFF (*execp);
2562159047fSniklas obj_str_filepos (abfd) = N_STROFF (*execp);
2572159047fSniklas
2582159047fSniklas /* Determine the architecture and machine type of the object file. */
2592159047fSniklas #ifdef SET_ARCH_MACH
2602159047fSniklas SET_ARCH_MACH (abfd, *execp);
2612159047fSniklas #else
2622159047fSniklas bfd_default_set_arch_mach (abfd, DEFAULT_ARCH, 0);
2632159047fSniklas #endif
2642159047fSniklas
2652159047fSniklas if (obj_aout_subformat (abfd) == gnu_encap_format)
2662159047fSniklas {
2672159047fSniklas /* The file offsets of the relocation info */
2682159047fSniklas obj_textsec (abfd)->rel_filepos = N_GNU_TRELOFF (*execp);
2692159047fSniklas obj_datasec (abfd)->rel_filepos = N_GNU_DRELOFF (*execp);
2702159047fSniklas
2712159047fSniklas /* The file offsets of the string table and symbol table. */
2722159047fSniklas obj_sym_filepos (abfd) = N_GNU_SYMOFF (*execp);
2732159047fSniklas obj_str_filepos (abfd) = (obj_sym_filepos (abfd) + execp->a_syms);
2742159047fSniklas
2752159047fSniklas abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
2762159047fSniklas bfd_get_symcount (abfd) = execp->a_syms / 12;
2772159047fSniklas obj_symbol_entry_size (abfd) = 12;
2782159047fSniklas obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
2792159047fSniklas }
2802159047fSniklas
2812159047fSniklas return abfd->xvec;
2822159047fSniklas }
2832159047fSniklas
284c074d1c9Sdrahn extern bfd_boolean aout_32_write_syms
285c074d1c9Sdrahn PARAMS ((bfd * abfd));
2862159047fSniklas
287c074d1c9Sdrahn static bfd_boolean
2882159047fSniklas MY (write_object_contents) (abfd)
2892159047fSniklas bfd *abfd;
2902159047fSniklas {
2912159047fSniklas struct external_exec exec_bytes;
2922159047fSniklas struct internal_exec *execp = exec_hdr (abfd);
2932159047fSniklas bfd_size_type text_size; /* dummy vars */
2942159047fSniklas file_ptr text_end;
2952159047fSniklas
2962159047fSniklas memset (&exec_bytes, 0, sizeof (exec_bytes));
297b305b0f1Sespie
2982159047fSniklas obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
2992159047fSniklas
3002159047fSniklas if (adata (abfd).magic == undecided_magic)
3012159047fSniklas NAME (aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end);
3022159047fSniklas execp->a_syms = 0;
3032159047fSniklas
3042159047fSniklas execp->a_entry = bfd_get_start_address (abfd);
3052159047fSniklas
3062159047fSniklas execp->a_trsize = ((obj_textsec (abfd)->reloc_count) *
3072159047fSniklas obj_reloc_entry_size (abfd));
3082159047fSniklas execp->a_drsize = ((obj_datasec (abfd)->reloc_count) *
3092159047fSniklas obj_reloc_entry_size (abfd));
3102159047fSniklas
3112159047fSniklas N_SET_MACHTYPE (*execp, 0xc);
3122159047fSniklas N_SET_FLAGS (*execp, aout_backend_info (abfd)->exec_hdr_flags);
3132159047fSniklas
3142159047fSniklas NAME (aout,swap_exec_header_out) (abfd, execp, &exec_bytes);
3152159047fSniklas
3162159047fSniklas /* update fields not covered by default swap_exec_header_out */
3172159047fSniklas
3182159047fSniklas /* this is really the sym table size but we store it in drelocs */
319c074d1c9Sdrahn H_PUT_32 (abfd, (bfd_get_symcount (abfd) * 12), exec_bytes.e_drelocs);
3202159047fSniklas
321c074d1c9Sdrahn if (bfd_seek (abfd, (file_ptr) 0, FALSE) != 0
322c074d1c9Sdrahn || (bfd_bwrite ((PTR) &exec_bytes, (bfd_size_type) EXEC_BYTES_SIZE, abfd)
3232159047fSniklas != EXEC_BYTES_SIZE))
324c074d1c9Sdrahn return FALSE;
3252159047fSniklas
3262159047fSniklas /* Write out the symbols, and then the relocs. We must write out
3272159047fSniklas the symbols first so that we know the symbol indices. */
3282159047fSniklas
3292159047fSniklas if (bfd_get_symcount (abfd) != 0)
3302159047fSniklas {
3312159047fSniklas /* Skip the relocs to where we want to put the symbols. */
332c074d1c9Sdrahn if (bfd_seek (abfd, (file_ptr) (N_DRELOFF (*execp) + execp->a_drsize),
3332159047fSniklas SEEK_SET) != 0)
334c074d1c9Sdrahn return FALSE;
3352159047fSniklas }
3362159047fSniklas
3372159047fSniklas if (!MY (write_syms) (abfd))
338c074d1c9Sdrahn return FALSE;
3392159047fSniklas
3402159047fSniklas if (bfd_get_symcount (abfd) != 0)
3412159047fSniklas {
342c074d1c9Sdrahn if (bfd_seek (abfd, (file_ptr) N_TRELOFF (*execp), SEEK_CUR) != 0)
343c074d1c9Sdrahn return FALSE;
3442159047fSniklas if (!NAME (aout,squirt_out_relocs) (abfd, obj_textsec (abfd)))
345c074d1c9Sdrahn return FALSE;
346c074d1c9Sdrahn if (bfd_seek (abfd, (file_ptr) N_DRELOFF (*execp), SEEK_CUR) != 0)
347c074d1c9Sdrahn return FALSE;
3482159047fSniklas if (!NAME (aout,squirt_out_relocs) (abfd, obj_datasec (abfd)))
349c074d1c9Sdrahn return FALSE;
3502159047fSniklas }
3512159047fSniklas
352c074d1c9Sdrahn return TRUE;
3532159047fSniklas }
3542159047fSniklas
3552159047fSniklas /* convert the hp symbol type to be the same as aout64.h usage so we */
3562159047fSniklas /* can piggyback routines in aoutx.h. */
3572159047fSniklas
3582159047fSniklas static void
convert_sym_type(sym_pointer,cache_ptr,abfd)3592159047fSniklas convert_sym_type (sym_pointer, cache_ptr, abfd)
360b305b0f1Sespie struct external_nlist *sym_pointer ATTRIBUTE_UNUSED;
3612159047fSniklas aout_symbol_type *cache_ptr;
362b305b0f1Sespie bfd *abfd ATTRIBUTE_UNUSED;
3632159047fSniklas {
3642159047fSniklas int name_type;
3652159047fSniklas int new_type;
3662159047fSniklas
3672159047fSniklas name_type = (cache_ptr->type);
3682159047fSniklas new_type = 0;
3692159047fSniklas
3702159047fSniklas if ((name_type & HP_SYMTYPE_ALIGN) != 0)
3712159047fSniklas {
3722159047fSniklas /* iou_error ("aligned symbol encountered: %s", name);*/
3732159047fSniklas name_type = 0;
3742159047fSniklas }
3752159047fSniklas
3762159047fSniklas if (name_type == HP_SYMTYPE_FILENAME)
3772159047fSniklas new_type = N_FN;
3782159047fSniklas else
3792159047fSniklas {
3802159047fSniklas switch (name_type & HP_SYMTYPE_TYPE)
3812159047fSniklas {
3822159047fSniklas case HP_SYMTYPE_UNDEFINED:
3832159047fSniklas new_type = N_UNDF;
3842159047fSniklas break;
3852159047fSniklas
3862159047fSniklas case HP_SYMTYPE_ABSOLUTE:
3872159047fSniklas new_type = N_ABS;
3882159047fSniklas break;
3892159047fSniklas
3902159047fSniklas case HP_SYMTYPE_TEXT:
3912159047fSniklas new_type = N_TEXT;
3922159047fSniklas break;
3932159047fSniklas
3942159047fSniklas case HP_SYMTYPE_DATA:
3952159047fSniklas new_type = N_DATA;
3962159047fSniklas break;
3972159047fSniklas
3982159047fSniklas case HP_SYMTYPE_BSS:
3992159047fSniklas new_type = N_BSS;
4002159047fSniklas break;
4012159047fSniklas
4022159047fSniklas case HP_SYMTYPE_COMMON:
4032159047fSniklas new_type = N_COMM;
4042159047fSniklas break;
4052159047fSniklas
4062159047fSniklas default:
4072159047fSniklas abort ();
4082159047fSniklas break;
4092159047fSniklas }
4102159047fSniklas if (name_type & HP_SYMTYPE_EXTERNAL)
4112159047fSniklas new_type |= N_EXT;
4122159047fSniklas
4132159047fSniklas if (name_type & HP_SECONDARY_SYMBOL)
4142159047fSniklas {
4152159047fSniklas switch (new_type)
4162159047fSniklas {
4172159047fSniklas default:
4182159047fSniklas abort ();
4192159047fSniklas case N_UNDF | N_EXT:
4206a4c786fSespie /* If the value is nonzero, then just treat this as a
4216a4c786fSespie common symbol. I don't know if this is correct in
4226a4c786fSespie all cases, but it is more correct than treating it as
4236a4c786fSespie a weak undefined symbol. */
4246a4c786fSespie if (cache_ptr->symbol.value == 0)
4252159047fSniklas new_type = N_WEAKU;
4262159047fSniklas break;
4272159047fSniklas case N_ABS | N_EXT:
4282159047fSniklas new_type = N_WEAKA;
4292159047fSniklas break;
4302159047fSniklas case N_TEXT | N_EXT:
4312159047fSniklas new_type = N_WEAKT;
4322159047fSniklas break;
4332159047fSniklas case N_DATA | N_EXT:
4342159047fSniklas new_type = N_WEAKD;
4352159047fSniklas break;
4362159047fSniklas case N_BSS | N_EXT:
4372159047fSniklas new_type = N_WEAKB;
4382159047fSniklas break;
4392159047fSniklas }
4402159047fSniklas }
4412159047fSniklas }
4422159047fSniklas cache_ptr->type = new_type;
4432159047fSniklas
4442159047fSniklas }
4452159047fSniklas
4462159047fSniklas /*
4472159047fSniklas DESCRIPTION
4482159047fSniklas Swaps the information in an executable header taken from a raw
4492159047fSniklas byte stream memory image, into the internal exec_header
4502159047fSniklas structure.
4512159047fSniklas */
4522159047fSniklas
4532159047fSniklas void
4542159047fSniklas NAME (aout,swap_exec_header_in) (abfd, raw_bytes, execp)
4552159047fSniklas bfd *abfd;
4562159047fSniklas struct external_exec *raw_bytes;
4572159047fSniklas struct internal_exec *execp;
4582159047fSniklas {
4592159047fSniklas struct external_exec *bytes = (struct external_exec *) raw_bytes;
4602159047fSniklas
4612159047fSniklas /* The internal_exec structure has some fields that are unused in this
4622159047fSniklas configuration (IE for i960), so ensure that all such uninitialized
4632159047fSniklas fields are zero'd out. There are places where two of these structs
4642159047fSniklas are memcmp'd, and thus the contents do matter. */
4652159047fSniklas memset (execp, 0, sizeof (struct internal_exec));
4662159047fSniklas /* Now fill in fields in the execp, from the bytes in the raw data. */
467c074d1c9Sdrahn execp->a_info = H_GET_32 (abfd, bytes->e_info);
4682159047fSniklas execp->a_text = GET_WORD (abfd, bytes->e_text);
4692159047fSniklas execp->a_data = GET_WORD (abfd, bytes->e_data);
4702159047fSniklas execp->a_bss = GET_WORD (abfd, bytes->e_bss);
4712159047fSniklas execp->a_syms = GET_WORD (abfd, bytes->e_syms);
4722159047fSniklas execp->a_entry = GET_WORD (abfd, bytes->e_entry);
4732159047fSniklas execp->a_trsize = GET_WORD (abfd, bytes->e_trsize);
4742159047fSniklas execp->a_drsize = GET_WORD (abfd, bytes->e_drsize);
4752159047fSniklas
4762159047fSniklas /***************************************************************/
4772159047fSniklas /* check the header to see if it was generated by a bfd output */
478*007c2a45Smiod /* this is detected rather bizarrely by requiring a bunch of */
4792159047fSniklas /* header fields to be zero and an old unused field (now used) */
4802159047fSniklas /* to be set. */
4812159047fSniklas /***************************************************************/
4822159047fSniklas do
4832159047fSniklas {
4842159047fSniklas long syms;
4852159047fSniklas struct aout_data_struct *rawptr;
486c074d1c9Sdrahn bfd_size_type amt;
487c074d1c9Sdrahn
488c074d1c9Sdrahn if (H_GET_32 (abfd, bytes->e_passize) != 0)
4892159047fSniklas break;
490c074d1c9Sdrahn if (H_GET_32 (abfd, bytes->e_syms) != 0)
4912159047fSniklas break;
492c074d1c9Sdrahn if (H_GET_32 (abfd, bytes->e_supsize) != 0)
4932159047fSniklas break;
4942159047fSniklas
495c074d1c9Sdrahn syms = H_GET_32 (abfd, bytes->e_drelocs);
4962159047fSniklas if (syms == 0)
4972159047fSniklas break;
4982159047fSniklas
4992159047fSniklas /* OK, we've passed the test as best as we can determine */
5002159047fSniklas execp->a_syms = syms;
5012159047fSniklas
5022159047fSniklas /* allocate storage for where we will store this result */
503c074d1c9Sdrahn amt = sizeof (*rawptr);
504c074d1c9Sdrahn rawptr = (struct aout_data_struct *) bfd_zalloc (abfd, amt);
5052159047fSniklas
5062159047fSniklas if (rawptr == NULL)
5072159047fSniklas return;
5082159047fSniklas abfd->tdata.aout_data = rawptr;
5092159047fSniklas obj_aout_subformat (abfd) = gnu_encap_format;
5102159047fSniklas }
5112159047fSniklas while (0);
5122159047fSniklas }
5132159047fSniklas
5142159047fSniklas /* The hp symbol table is a bit different than other a.out targets. Instead
5152159047fSniklas of having an array of nlist items and an array of strings, hp's format
5162159047fSniklas has them mixed together in one structure. In addition, the strings are
5172159047fSniklas not null terminated. It looks something like this:
5182159047fSniklas
5192159047fSniklas nlist element 1
5202159047fSniklas string1
5212159047fSniklas nlist element 2
5222159047fSniklas string2
5232159047fSniklas ...
5242159047fSniklas
5252159047fSniklas The whole symbol table is read as one chunk and then we march thru it
5262159047fSniklas and convert it to canonical form. As we march thru the table, we copy
5272159047fSniklas the nlist data into the internal form and we compact the strings and null
5282159047fSniklas terminate them, using storage from the already allocated symbol table:
5292159047fSniklas
5302159047fSniklas string1
5312159047fSniklas null
5322159047fSniklas string2
5332159047fSniklas null
5342159047fSniklas ...
5352159047fSniklas */
5362159047fSniklas
537c074d1c9Sdrahn bfd_boolean
5382159047fSniklas MY (slurp_symbol_table) (abfd)
5392159047fSniklas bfd *abfd;
5402159047fSniklas {
5412159047fSniklas bfd_size_type symbol_bytes;
5422159047fSniklas struct external_nlist *syms;
5432159047fSniklas struct external_nlist *sym_pointer;
5442159047fSniklas struct external_nlist *sym_end;
5452159047fSniklas char *strings;
5462159047fSniklas aout_symbol_type *cached;
5472159047fSniklas unsigned num_syms = 0;
548c074d1c9Sdrahn bfd_size_type amt;
5492159047fSniklas
5502159047fSniklas /* If there's no work to be done, don't do any */
5512159047fSniklas if (obj_aout_symbols (abfd) != (aout_symbol_type *) NULL)
552c074d1c9Sdrahn return TRUE;
5532159047fSniklas symbol_bytes = exec_hdr (abfd)->a_syms;
5542159047fSniklas
555c074d1c9Sdrahn amt = symbol_bytes + SYM_EXTRA_BYTES;
556c074d1c9Sdrahn strings = (char *) bfd_alloc (abfd, amt);
5572159047fSniklas if (!strings)
558c074d1c9Sdrahn return FALSE;
5592159047fSniklas syms = (struct external_nlist *) (strings + SYM_EXTRA_BYTES);
5602159047fSniklas if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0
561c074d1c9Sdrahn || bfd_bread ((PTR) syms, symbol_bytes, abfd) != symbol_bytes)
5622159047fSniklas {
5632159047fSniklas bfd_release (abfd, syms);
564c074d1c9Sdrahn return FALSE;
5652159047fSniklas }
5662159047fSniklas
5672159047fSniklas sym_end = (struct external_nlist *) (((char *) syms) + symbol_bytes);
5682159047fSniklas
5692159047fSniklas /* first, march thru the table and figure out how many symbols there are */
5702159047fSniklas for (sym_pointer = syms; sym_pointer < sym_end; sym_pointer++, num_syms++)
5712159047fSniklas {
5722159047fSniklas /* skip over the embedded symbol. */
5732159047fSniklas sym_pointer = (struct external_nlist *) (((char *) sym_pointer) +
5742159047fSniklas sym_pointer->e_length[0]);
5752159047fSniklas }
5762159047fSniklas
5772159047fSniklas /* now that we know the symbol count, update the bfd header */
5782159047fSniklas bfd_get_symcount (abfd) = num_syms;
5792159047fSniklas
580c074d1c9Sdrahn amt = num_syms;
581c074d1c9Sdrahn amt *= sizeof (aout_symbol_type);
582c074d1c9Sdrahn cached = (aout_symbol_type *) bfd_zalloc (abfd, amt);
583c074d1c9Sdrahn if (cached == NULL && num_syms != 0)
584c074d1c9Sdrahn return FALSE;
5852159047fSniklas
5862159047fSniklas /* as we march thru the hp symbol table, convert it into a list of
5872159047fSniklas null terminated strings to hold the symbol names. Make sure any
5882159047fSniklas assignment to the strings pointer is done after we're thru using
5892159047fSniklas the nlist so we don't overwrite anything important. */
5902159047fSniklas
591*007c2a45Smiod /* OK, now walk the new symtable, caching symbol properties */
5922159047fSniklas {
5932159047fSniklas aout_symbol_type *cache_ptr = cached;
5942159047fSniklas aout_symbol_type cache_save;
5952159047fSniklas /* Run through table and copy values */
5962159047fSniklas for (sym_pointer = syms, cache_ptr = cached;
5972159047fSniklas sym_pointer < sym_end; sym_pointer++, cache_ptr++)
5982159047fSniklas {
5992159047fSniklas unsigned int length;
6002159047fSniklas cache_ptr->symbol.the_bfd = abfd;
6012159047fSniklas cache_ptr->symbol.value = GET_SWORD (abfd, sym_pointer->e_value);
6022159047fSniklas cache_ptr->desc = bfd_get_16 (abfd, sym_pointer->e_almod);
6032159047fSniklas cache_ptr->type = bfd_get_8 (abfd, sym_pointer->e_type);
6042159047fSniklas cache_ptr->symbol.udata.p = NULL;
6052159047fSniklas length = bfd_get_8 (abfd, sym_pointer->e_length);
6062159047fSniklas cache_ptr->other = length; /* other not used, save length here */
6072159047fSniklas
6082159047fSniklas cache_save = *cache_ptr;
6092159047fSniklas convert_sym_type (sym_pointer, cache_ptr, abfd);
6102159047fSniklas if (!translate_from_native_sym_flags (abfd, cache_ptr))
611c074d1c9Sdrahn return FALSE;
6122159047fSniklas
6132159047fSniklas /********************************************************/
614*007c2a45Smiod /* for hpux, the 'length' value indicates the length of */
6152159047fSniklas /* the symbol name which follows the nlist entry. */
6162159047fSniklas /********************************************************/
6172159047fSniklas if (length)
6182159047fSniklas {
6192159047fSniklas /**************************************************************/
6202159047fSniklas /* the hp string is not null terminated so we create a new one*/
6212159047fSniklas /* by copying the string to overlap the just vacated nlist */
6222159047fSniklas /* structure before it in memory. */
6232159047fSniklas /**************************************************************/
6242159047fSniklas cache_ptr->symbol.name = strings;
6252159047fSniklas memcpy (strings, sym_pointer + 1, length);
6262159047fSniklas strings[length] = '\0';
6272159047fSniklas strings += length + 1;
6282159047fSniklas }
6292159047fSniklas else
6302159047fSniklas cache_ptr->symbol.name = (char *) NULL;
6312159047fSniklas
6322159047fSniklas /* skip over the embedded symbol. */
6332159047fSniklas sym_pointer = (struct external_nlist *) (((char *) sym_pointer) +
6342159047fSniklas length);
6352159047fSniklas }
6362159047fSniklas }
6372159047fSniklas
6382159047fSniklas obj_aout_symbols (abfd) = cached;
6392159047fSniklas
640c074d1c9Sdrahn return TRUE;
6412159047fSniklas }
6422159047fSniklas
6432159047fSniklas void
6442159047fSniklas MY (swap_std_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount)
6452159047fSniklas bfd *abfd;
6462159047fSniklas struct hp300hpux_reloc *bytes;
6472159047fSniklas arelent *cache_ptr;
6482159047fSniklas asymbol **symbols;
649b305b0f1Sespie bfd_size_type symcount ATTRIBUTE_UNUSED;
6502159047fSniklas {
6512159047fSniklas int r_index;
6522159047fSniklas int r_extern = 0;
6532159047fSniklas unsigned int r_length;
6542159047fSniklas int r_pcrel = 0;
6552159047fSniklas struct aoutdata *su = &(abfd->tdata.aout_data->a);
6562159047fSniklas
657c074d1c9Sdrahn cache_ptr->address = H_GET_32 (abfd, bytes->r_address);
658c074d1c9Sdrahn r_index = H_GET_16 (abfd, bytes->r_index);
6592159047fSniklas
6602159047fSniklas switch (bytes->r_type[0])
6612159047fSniklas {
6622159047fSniklas case HP_RSEGMENT_TEXT:
6632159047fSniklas r_index = N_TEXT;
6642159047fSniklas break;
6652159047fSniklas case HP_RSEGMENT_DATA:
6662159047fSniklas r_index = N_DATA;
6672159047fSniklas break;
6682159047fSniklas case HP_RSEGMENT_BSS:
6692159047fSniklas r_index = N_BSS;
6702159047fSniklas break;
6712159047fSniklas case HP_RSEGMENT_EXTERNAL:
6722159047fSniklas r_extern = 1;
6732159047fSniklas break;
6742159047fSniklas case HP_RSEGMENT_PCREL:
6752159047fSniklas r_extern = 1;
6762159047fSniklas r_pcrel = 1;
6772159047fSniklas break;
6782159047fSniklas case HP_RSEGMENT_RDLT:
6792159047fSniklas break;
6802159047fSniklas case HP_RSEGMENT_RPLT:
6812159047fSniklas break;
6822159047fSniklas case HP_RSEGMENT_NOOP:
6832159047fSniklas break;
6842159047fSniklas default:
6852159047fSniklas abort ();
6862159047fSniklas break;
6872159047fSniklas }
6882159047fSniklas
6892159047fSniklas switch (bytes->r_length[0])
6902159047fSniklas {
6912159047fSniklas case HP_RLENGTH_BYTE:
6922159047fSniklas r_length = 0;
6932159047fSniklas break;
6942159047fSniklas case HP_RLENGTH_WORD:
6952159047fSniklas r_length = 1;
6962159047fSniklas break;
6972159047fSniklas case HP_RLENGTH_LONG:
6982159047fSniklas r_length = 2;
6992159047fSniklas break;
7002159047fSniklas default:
7012159047fSniklas abort ();
7022159047fSniklas break;
7032159047fSniklas }
7042159047fSniklas
7052159047fSniklas cache_ptr->howto = howto_table_std + r_length + 4 * r_pcrel;
7062159047fSniklas /* FIXME-soon: Roll baserel, jmptable, relative bits into howto setting */
7072159047fSniklas
7082159047fSniklas /* This macro uses the r_index value computed above */
7092159047fSniklas if (r_pcrel && r_extern)
7102159047fSniklas {
7112159047fSniklas /* The GNU linker assumes any offset from beginning of section */
7122159047fSniklas /* is already incorporated into the image while the HP linker */
7132159047fSniklas /* adds this in later. Add it in now... */
7142159047fSniklas MOVE_ADDRESS (-cache_ptr->address);
7152159047fSniklas }
7162159047fSniklas else
7172159047fSniklas {
7182159047fSniklas MOVE_ADDRESS (0);
7192159047fSniklas }
7202159047fSniklas }
7212159047fSniklas
722c074d1c9Sdrahn bfd_boolean
7232159047fSniklas MY (slurp_reloc_table) (abfd, asect, symbols)
7242159047fSniklas bfd *abfd;
7252159047fSniklas sec_ptr asect;
7262159047fSniklas asymbol **symbols;
7272159047fSniklas {
728c074d1c9Sdrahn bfd_size_type count;
7292159047fSniklas bfd_size_type reloc_size;
7302159047fSniklas PTR relocs;
7312159047fSniklas arelent *reloc_cache;
7322159047fSniklas size_t each_size;
7332159047fSniklas struct hp300hpux_reloc *rptr;
7342159047fSniklas unsigned int counter;
7352159047fSniklas arelent *cache_ptr;
7362159047fSniklas
7372159047fSniklas if (asect->relocation)
738c074d1c9Sdrahn return TRUE;
7392159047fSniklas
7402159047fSniklas if (asect->flags & SEC_CONSTRUCTOR)
741c074d1c9Sdrahn return TRUE;
7422159047fSniklas
7432159047fSniklas if (asect == obj_datasec (abfd))
7442159047fSniklas {
7452159047fSniklas reloc_size = exec_hdr (abfd)->a_drsize;
7462159047fSniklas goto doit;
7472159047fSniklas }
7482159047fSniklas
7492159047fSniklas if (asect == obj_textsec (abfd))
7502159047fSniklas {
7512159047fSniklas reloc_size = exec_hdr (abfd)->a_trsize;
7522159047fSniklas goto doit;
7532159047fSniklas }
7542159047fSniklas
7552159047fSniklas bfd_set_error (bfd_error_invalid_operation);
756c074d1c9Sdrahn return FALSE;
7572159047fSniklas
7582159047fSniklas doit:
7592159047fSniklas if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
760c074d1c9Sdrahn return FALSE;
7612159047fSniklas each_size = obj_reloc_entry_size (abfd);
7622159047fSniklas
7632159047fSniklas count = reloc_size / each_size;
7642159047fSniklas
765c074d1c9Sdrahn reloc_cache = (arelent *) bfd_zalloc (abfd, count * sizeof (arelent));
7662159047fSniklas if (!reloc_cache && count != 0)
767c074d1c9Sdrahn return FALSE;
7682159047fSniklas
7692159047fSniklas relocs = (PTR) bfd_alloc (abfd, reloc_size);
7702159047fSniklas if (!relocs && reloc_size != 0)
7712159047fSniklas {
7722159047fSniklas bfd_release (abfd, reloc_cache);
773c074d1c9Sdrahn return FALSE;
7742159047fSniklas }
7752159047fSniklas
776c074d1c9Sdrahn if (bfd_bread (relocs, reloc_size, abfd) != reloc_size)
7772159047fSniklas {
7782159047fSniklas bfd_release (abfd, relocs);
7792159047fSniklas bfd_release (abfd, reloc_cache);
780c074d1c9Sdrahn return FALSE;
7812159047fSniklas }
7822159047fSniklas
7832159047fSniklas rptr = (struct hp300hpux_reloc *) relocs;
7842159047fSniklas counter = 0;
7852159047fSniklas cache_ptr = reloc_cache;
7862159047fSniklas
7872159047fSniklas for (; counter < count; counter++, rptr++, cache_ptr++)
7882159047fSniklas {
7892159047fSniklas MY (swap_std_reloc_in) (abfd, rptr, cache_ptr, symbols,
790c074d1c9Sdrahn (bfd_size_type) bfd_get_symcount (abfd));
7912159047fSniklas }
7922159047fSniklas
7932159047fSniklas bfd_release (abfd, relocs);
7942159047fSniklas asect->relocation = reloc_cache;
7952159047fSniklas asect->reloc_count = count;
796c074d1c9Sdrahn return TRUE;
7972159047fSniklas }
7982159047fSniklas
7992159047fSniklas /************************************************************************/
8002159047fSniklas /* The following functions are identical to functions in aoutx.h except */
8012159047fSniklas /* they refer to MY(func) rather than NAME(aout,func) and they also */
8022159047fSniklas /* call aout_32 versions if the input file was generated by gcc */
8032159047fSniklas /************************************************************************/
8042159047fSniklas
805*007c2a45Smiod long aout_32_canonicalize_symtab
806c074d1c9Sdrahn PARAMS ((bfd * abfd, asymbol ** location));
807c074d1c9Sdrahn long aout_32_get_symtab_upper_bound
808c074d1c9Sdrahn PARAMS ((bfd * abfd));
809c074d1c9Sdrahn long aout_32_canonicalize_reloc
810c074d1c9Sdrahn PARAMS ((bfd * abfd, sec_ptr section, arelent ** relptr,
8112159047fSniklas asymbol ** symbols));
8122159047fSniklas
8132159047fSniklas long
814*007c2a45Smiod MY (canonicalize_symtab) (abfd, location)
8152159047fSniklas bfd *abfd;
8162159047fSniklas asymbol **location;
8172159047fSniklas {
8182159047fSniklas unsigned int counter = 0;
8192159047fSniklas aout_symbol_type *symbase;
8202159047fSniklas
8212159047fSniklas if (obj_aout_subformat (abfd) == gnu_encap_format)
822*007c2a45Smiod return aout_32_canonicalize_symtab (abfd, location);
8232159047fSniklas
8242159047fSniklas if (!MY (slurp_symbol_table) (abfd))
8252159047fSniklas return -1;
8262159047fSniklas
8272159047fSniklas for (symbase = obj_aout_symbols (abfd); counter++ < bfd_get_symcount (abfd);)
8282159047fSniklas *(location++) = (asymbol *) (symbase++);
8292159047fSniklas *location++ = 0;
8302159047fSniklas return bfd_get_symcount (abfd);
8312159047fSniklas }
8322159047fSniklas
8332159047fSniklas long
8342159047fSniklas MY (get_symtab_upper_bound) (abfd)
8352159047fSniklas bfd *abfd;
8362159047fSniklas {
8372159047fSniklas if (obj_aout_subformat (abfd) == gnu_encap_format)
8382159047fSniklas return aout_32_get_symtab_upper_bound (abfd);
8392159047fSniklas if (!MY (slurp_symbol_table) (abfd))
8402159047fSniklas return -1;
8412159047fSniklas
8422159047fSniklas return (bfd_get_symcount (abfd) + 1) * (sizeof (aout_symbol_type *));
8432159047fSniklas }
8442159047fSniklas
8452159047fSniklas long
8462159047fSniklas MY (canonicalize_reloc) (abfd, section, relptr, symbols)
8472159047fSniklas bfd *abfd;
8482159047fSniklas sec_ptr section;
8492159047fSniklas arelent **relptr;
8502159047fSniklas asymbol **symbols;
8512159047fSniklas {
8522159047fSniklas arelent *tblptr = section->relocation;
8532159047fSniklas unsigned int count;
8542159047fSniklas if (obj_aout_subformat (abfd) == gnu_encap_format)
8552159047fSniklas return aout_32_canonicalize_reloc (abfd, section, relptr, symbols);
8562159047fSniklas
8572159047fSniklas if (!(tblptr || MY (slurp_reloc_table) (abfd, section, symbols)))
8582159047fSniklas return -1;
8592159047fSniklas
8602159047fSniklas if (section->flags & SEC_CONSTRUCTOR)
8612159047fSniklas {
8622159047fSniklas arelent_chain *chain = section->constructor_chain;
8632159047fSniklas for (count = 0; count < section->reloc_count; count++)
8642159047fSniklas {
8652159047fSniklas *relptr++ = &chain->relent;
8662159047fSniklas chain = chain->next;
8672159047fSniklas }
8682159047fSniklas }
8692159047fSniklas else
8702159047fSniklas {
8712159047fSniklas tblptr = section->relocation;
8722159047fSniklas
8732159047fSniklas for (count = 0; count++ < section->reloc_count;)
8742159047fSniklas {
8752159047fSniklas *relptr++ = tblptr++;
8762159047fSniklas }
8772159047fSniklas }
8782159047fSniklas *relptr = 0;
8792159047fSniklas
8802159047fSniklas return section->reloc_count;
8812159047fSniklas }
8822159047fSniklas
8832159047fSniklas #include "aout-target.h"
884