diff options
-rw-r--r-- | bfd/ChangeLog | 107 | ||||
-rw-r--r-- | bfd/aix386-core.c | 8 | ||||
-rw-r--r-- | bfd/aout-target.h | 129 | ||||
-rw-r--r-- | bfd/aoutf1.h | 17 | ||||
-rw-r--r-- | bfd/aoutx.h | 2118 | ||||
-rw-r--r-- | bfd/bfd-in.h | 151 | ||||
-rw-r--r-- | bfd/bfd-in2.h | 227 | ||||
-rw-r--r-- | bfd/coff-a29k.c | 39 | ||||
-rw-r--r-- | bfd/coffgen.c | 44 | ||||
-rw-r--r-- | bfd/ecoff.c | 132 | ||||
-rw-r--r-- | bfd/elf.c | 4 | ||||
-rw-r--r-- | bfd/elf32-target.h | 13 | ||||
-rw-r--r-- | bfd/elf64-target.h | 11 | ||||
-rw-r--r-- | bfd/hosts/std-host.h | 2 | ||||
-rw-r--r-- | bfd/hppabsd-core.c | 334 | ||||
-rw-r--r-- | bfd/hpux-core.c | 318 | ||||
-rw-r--r-- | bfd/irix-core.c | 292 | ||||
-rw-r--r-- | bfd/libaout.h | 71 | ||||
-rw-r--r-- | bfd/libbfd-in.h | 74 | ||||
-rw-r--r-- | bfd/libbfd.c | 6 | ||||
-rw-r--r-- | bfd/libbfd.h | 75 | ||||
-rw-r--r-- | bfd/libelf.h | 3 | ||||
-rw-r--r-- | bfd/osf-core.c | 298 | ||||
-rw-r--r-- | bfd/ptrace-core.c | 303 | ||||
-rw-r--r-- | bfd/reloc.c | 427 | ||||
-rw-r--r-- | bfd/section.c | 24 | ||||
-rw-r--r-- | bfd/srec.c | 128 | ||||
-rw-r--r-- | bfd/targets.c | 28 | ||||
-rw-r--r-- | bfd/trad-core.c | 28 |
29 files changed, 4752 insertions, 659 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index a0d0f0b..182f3c5 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,110 @@ +Thu Dec 30 13:37:24 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + Extensive changes to move the bulk of the linker into BFD so that + more efficient backend code can be written for specific object + files. Only existing efficient backend is a.out. + * seclet.c, seclet.h: Removed. + * hash.c, linker.c, genlink.h: New files. + * bfd-in.h: Removed bfd_error_vector. Declared hash table + structures and functions. + (JUMP_TABLE): Removed bfd_seclet_link, added + bfd_link_hash_table_create, bfd_link_add_symbols and + bfd_final_link. + * All backends: Changed accordingly. + * bfd-in2.h: Rebuilt. + * bfd.c (struct _bfd): Added link_next and archive_pass fields. + Removed ld_symbols field. + (bfd_nonrepresentable_section, bfd_undefined_symbol, + bfd_reloc_value_truncated, bfd_reloc_is_dangerous, + bfd_error_vector): Removed. + (bfd_default_error_trap, bfd_error_trap, + bfd_error_nonrepresentabltrap): Removed. + (bfd_get_relocated_section_contents): Pass link_info. Pass + link_order instead of seclet. Pass symbols. + (bfd_relax_section): Pass link_info. + (bfd_seclet_link): Removed. + (bfd_link_hash_table_create, bfd_link_add_symbols, + bfd_final_link): New macros. + * libbfd-in.h: If __GNUC__ is defined and alloca is not, define + alloca as __builtin_alloca. Declare internal linking functions. + * libbfd.h: Rebuilt. + * libbfd.c (bfd_seek): Comment out fseek assertion. It's worked + for months. + * reloc.c (reloc_howto_type): Added error_message argument to + special_function field. Changed all callers and all definitions. + (bfd_get_reloc_size): Make argument a const pointer. + (bfd_perform_relocation): Add error_message argument to hold + string set if return value if bfd_reloc_dangerous. Changed all + callers. + (_bfd_final_link_relocate, _bfd_relocate_contents): New functions. + * section.c (asection): Renamed seclets_head and seclets_tail to + link_order_head and link_order_tail. + * targets.c (bfd_target): Replaced seclet argument with link_info + and link_order and symbols arguments in + bfd_get_relocated_section_contents. Added symbols argument to + bfd_relax_section. Removed bfd_seclet_link. Added + bfd_link_hash_table_create, bfd_link_add_symbols and + bfd_final_link. + * libaout.h (struct aoutdata): Added external_syms, + external_sym_count, external_strings, sym_hashes fields. + (obj_aout_external_syms, obj_aout_external_sym_count, + obj_aout_external_strings, obj_aout_sym_hashes): New accessor + macros. + (WRITE_HEADERS): Only output symbols if outsymbols is not NULL. + * aoutx.h: Wrote new back end linker routines. + (translate_to_native_sym_flags): Return boolean value. Don't use + bfd_error_vector. + (NAME(aout,write_syms)): Return boolean value. Check return value + of translate_to_native_sym_flags and bfd_write. + * aout-target.h (final_link_callback): New function. + (MY_bfd_final_link): New function. + * aout-adobe.c (aout_adobe_write_object_contents): Check return + value of aout_32_write_syms. + * hp300hpux.c (MY(write_object_contents)): Likewise. + * i386lynx.c (WRITE_HEADERS): Likewise. + * libaout.h (WRITE_HEADERS): Likewise. + * bout.c: Changed functions to use link_info->callbacks rather + than bfd_error_vector, and link_orders rather than seclets. + * coff-alpha.c: Likewise. + * coff-h8300.c: Likewise. + * coff-h8500.c: Likewise. + * coff-sh.c: Likewise. + * coff-z8k.c: Likewise. + * elf32-hppa.c: Likewise. + * reloc16.c: Likewise. + * coff-alpha.c (alpha_ecoff_get_relocated_section_contents): Look + up _gp in the hash table rather than in outsymbols. + * coff-a29k.c (a29k_reloc): Pass errors back in new error_message + argument rather than printing them. + * coffcode.h (bfd_coff_reloc16_extra_cases): Take link_info and + link_order arguments rather than seclet. Changed all uses and + definitions. + (bfd_coff_reloc16_estimate): Pass link_info arguments. Changed + all uses and definitions. + * libcoff.h: Rebuilt. + * ecoff.c (ecoff_get_extr): If symbol is defined by linker, but + not by ECOFF, make it scAbs. + (ecoff_bfd_final_link): Renamed from ecoff_bfd_seclet_link and + rewritten. + * elf32-mips.c (mips_elf_final_link): Renamed from + mips_elf_seclet_link and rewritten. + * elf32-hppa.c (elf32_hppa_stub_description): Added link_info + field. + (new_stub, add_stub_by_name, hppa_elf_build_arg_reloc_stub, + hppa_elf_build_long_branch_stub, hppa_look_for_stubs_in_section): + Added link_info arguments. Changed all callers. + * elfcode.h (elf_slurp_symbol_table): Don't quit if outsymbols is + not NULL. + * oasys.c (oasys_write_sections): Return boolean value rather than + using bfd_error_vector. + (oasys_write_object_contents): Check return value of + oasys_write_sections. + * hosts/std-host.h: Don't declare qsort or strtol. + * Makefile.in: Rebuild dependencies. + (BFD_LIBS): Removed seclet.o. Added hash.o and linker.o. + (CFILES): Removed seclet.c. Added hash.c and linker.c. + (HFILES): Removed seclet.h. Added genlink.h. + Thu Dec 30 07:41:36 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) * section.c (bfd_get_section_contents): Return zero filled buffer diff --git a/bfd/aix386-core.c b/bfd/aix386-core.c index 3701367..ac0bba6 100644 --- a/bfd/aix386-core.c +++ b/bfd/aix386-core.c @@ -290,12 +290,16 @@ DEFUN(aix386_core_file_matches_executable_p, (core_bfd, exec_bfd), (bfd *, struct sec *))) bfd_void #define aix386_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents #define aix386_bfd_relax_section bfd_generic_relax_section -#define aix386_bfd_seclet_link \ - ((boolean (*) PARAMS ((bfd *, PTR, boolean))) bfd_false) #define aix386_bfd_reloc_type_lookup \ ((CONST struct reloc_howto_struct *(*) PARAMS ((bfd *, bfd_reloc_code_real_type))) bfd_nullvoidptr) #define aix386_bfd_make_debug_symbol \ ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr) +#define aix386_bfd_link_hash_table_create \ + ((struct bfd_link_hash_table *(*) PARAMS ((bfd *))) bfd_nullvoidptr) +#define aix386_bfd_link_add_symbols \ + ((boolean (*) PARAMS ((bfd *, struct bfd_link_info *))) bfd_false) +#define aix386_bfd_final_link \ + ((boolean (*) PARAMS ((bfd *, struct bfd_link_info *))) bfd_false) /* If somebody calls any byte-swapping routines, shoot them. */ void diff --git a/bfd/aout-target.h b/bfd/aout-target.h index 8cf7429..70835c5 100644 --- a/bfd/aout-target.h +++ b/bfd/aout-target.h @@ -1,5 +1,5 @@ /* Define a target vector and some small routines for a variant of a.out. - Copyright (C) 1990-1991 Free Software Foundation, Inc. + Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -93,9 +93,16 @@ DEFUN(MY(object_p),(abfd), return 0; } +#ifdef NO_SWAP_MAGIC + memcpy (&exec.a_info, exec_bytes.e_info, sizeof(exec.a_info)); +#else exec.a_info = bfd_h_get_32 (abfd, exec_bytes.e_info); +#endif /* NO_SWAP_MAGIC */ if (N_BADMAG (exec)) return 0; +#ifdef MACHTYPE_OK + if (!(MACHTYPE_OK (N_MACHTYPE (exec)))) return 0; +#endif NAME(aout,swap_exec_header_in)(abfd, &exec_bytes, &exec); target = NAME(aout,some_aout_object_p) (abfd, &exec, MY(callback)); @@ -199,6 +206,38 @@ static CONST struct aout_backend_data MY(backend_data) = { #define MY_backend_data &MY(backend_data) #endif +#ifndef MY_bfd_final_link + +/* Final link routine. We need to use a call back to get the correct + offsets in the output file. */ + +static void final_link_callback + PARAMS ((bfd *, file_ptr *, file_ptr *, file_ptr *)); + +static void +final_link_callback (abfd, ptreloff, pdreloff, psymoff) + bfd *abfd; + file_ptr *ptreloff; + file_ptr *pdreloff; + file_ptr *psymoff; +{ + struct internal_exec *execp = exec_hdr (abfd); + + *ptreloff = N_TRELOFF (*execp); + *pdreloff = N_DRELOFF (*execp); + *psymoff = N_SYMOFF (*execp); +} + +static boolean +MY_bfd_final_link (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + return NAME(aout,final_link) (abfd, info, final_link_callback); +} + +#endif + /* We assume BFD generic archive files. */ #ifndef MY_openr_next_archived_file #define MY_openr_next_archived_file bfd_generic_openr_next_archived_file @@ -296,6 +335,9 @@ static CONST struct aout_backend_data MY(backend_data) = { #ifndef MY_print_symbol #define MY_print_symbol NAME(aout,print_symbol) #endif +#ifndef MY_get_symbol_info +#define MY_get_symbol_info NAME(aout,get_symbol_info) +#endif #ifndef MY_get_lineno #define MY_get_lineno NAME(aout,get_lineno) #endif @@ -314,20 +356,24 @@ static CONST struct aout_backend_data MY(backend_data) = { #ifndef MY_sizeof_headers #define MY_sizeof_headers NAME(aout,sizeof_headers) #endif -#ifndef MY_bfd_debug_info_start -#define MY_bfd_debug_info_start NAME(aout,bfd_debug_info_start) +#ifndef MY_bfd_get_relocated_section_contents +#define MY_bfd_get_relocated_section_contents \ + bfd_generic_get_relocated_section_contents #endif -#ifndef MY_bfd_debug_info_end -#define MY_bfd_debug_info_end NAME(aout,bfd_debug_info_end) +#ifndef MY_bfd_relax_section +#define MY_bfd_relax_section bfd_generic_relax_section +#endif +#ifndef MY_bfd_reloc_type_lookup +#define MY_bfd_reloc_type_lookup NAME(aout,reloc_type_lookup) #endif -#ifndef MY_bfd_debug_info_accumulat -#define MY_bfd_debug_info_accumulat NAME(aout,bfd_debug_info_accumulat) +#ifndef MY_bfd_make_debug_symbol +#define MY_bfd_make_debug_symbol 0 #endif -#ifndef MY_reloc_howto_type_lookup -#define MY_reloc_howto_type_lookup NAME(aout,reloc_type_lookup) +#ifndef MY_bfd_link_hash_table_create +#define MY_bfd_link_hash_table_create NAME(aout,link_hash_table_create) #endif -#ifndef MY_make_debug_symbol -#define MY_make_debug_symbol 0 +#ifndef MY_bfd_link_add_symbols +#define MY_bfd_link_add_symbols NAME(aout,link_add_symbols) #endif /* Aout symbols normally have leading underscores */ @@ -335,6 +381,12 @@ static CONST struct aout_backend_data MY(backend_data) = { #define MY_symbol_leading_char '_' #endif +/* Aout archives normally use spaces for padding */ +#ifndef AR_PAD_CHAR +#define AR_PAD_CHAR ' ' +#endif + +#ifndef MY_BFD_TARGET bfd_target MY(vec) = { TARGETNAME, /* name */ @@ -348,18 +400,26 @@ bfd_target MY(vec) = #endif (HAS_RELOC | EXEC_P | /* object flags */ HAS_LINENO | HAS_DEBUG | - HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED), + HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ MY_symbol_leading_char, - ' ', /* ar_pad_char */ + AR_PAD_CHAR, /* ar_pad_char */ 15, /* ar_max_namelen */ - 1, /* minimum alignment */ + 3, /* minimum alignment */ #ifdef TARGET_IS_BIG_ENDIAN_P - _do_getb64, _do_putb64, _do_getb32, _do_putb32, _do_getb16, _do_putb16, /* data */ - _do_getb64, _do_putb64, _do_getb32, _do_putb32, _do_getb16, _do_putb16, /* hdrs */ + bfd_getb64, bfd_getb_signed_64, bfd_putb64, + bfd_getb32, bfd_getb_signed_32, bfd_putb32, + bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */ + bfd_getb64, bfd_getb_signed_64, bfd_putb64, + bfd_getb32, bfd_getb_signed_32, bfd_putb32, + bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */ #else - _do_getl64, _do_putl64, _do_getl32, _do_putl32, _do_getl16, _do_putl16, /* data */ - _do_getl64, _do_putl64, _do_getl32, _do_putl32, _do_getl16, _do_putl16, /* hdrs */ + bfd_getl64, bfd_getl_signed_64, bfd_putl64, + bfd_getl32, bfd_getl_signed_32, bfd_putl32, + bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */ + bfd_getl64, bfd_getl_signed_64, bfd_putl64, + bfd_getl32, bfd_getl_signed_32, bfd_putl32, + bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */ #endif {_bfd_dummy_target, MY_object_p, /* bfd_check_format */ bfd_generic_archive_p, MY_core_file_p}, @@ -368,36 +428,7 @@ bfd_target MY(vec) = {bfd_false, MY_write_object_contents, /* bfd_write_contents */ _bfd_write_archive_contents, bfd_false}, - MY_core_file_failing_command, - MY_core_file_failing_signal, - MY_core_file_matches_executable_p, - MY_slurp_armap, - MY_slurp_extended_name_table, - MY_truncate_arname, - MY_write_armap, - MY_close_and_cleanup, - MY_set_section_contents, - MY_get_section_contents, - MY_new_section_hook, - MY_get_symtab_upper_bound, - MY_get_symtab, - MY_get_reloc_upper_bound, - MY_canonicalize_reloc, - MY_make_empty_symbol, - MY_print_symbol, - MY_get_lineno, - MY_set_arch_mach, - MY_openr_next_archived_file, - MY_find_nearest_line, - MY_generic_stat_arch_elt, - MY_sizeof_headers, - MY_bfd_debug_info_start, - MY_bfd_debug_info_end, - MY_bfd_debug_info_accumulate, - bfd_generic_get_relocated_section_contents, - bfd_generic_relax_section, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* COFF stuff?! */ - MY_reloc_howto_type_lookup, - MY_make_debug_symbol, + JUMP_TABLE (MY), (PTR) MY_backend_data, }; +#endif /* MY_BFD_TARGET */ diff --git a/bfd/aoutf1.h b/bfd/aoutf1.h index 076b0f2..2f4b728 100644 --- a/bfd/aoutf1.h +++ b/bfd/aoutf1.h @@ -1,5 +1,5 @@ /* A.out "format 1" file handling code for BFD. - Copyright 1990, 1991, 1992 Free Software Foundation, Inc. + Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -30,8 +30,12 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "aout/ar.h" /* This is needed to reject a NewsOS file, e.g. in - gdb/testsuite/gdb.t10/crossload.exp. */ -#define MACHTYPE_OK(mtype) ((mtype) == M_68010 || (mtype) == M_68020 \ + gdb/testsuite/gdb.t10/crossload.exp. <kingdon@cygnus.com> + I needed to add M_UNKNOWN to recognize a 68000 object, so this will + probably no longer reject a NewsOS object. <ian@cygnus.com>. */ +#define MACHTYPE_OK(mtype) ((mtype) == M_UNKNOWN \ + || (mtype) == M_68010 \ + || (mtype) == M_68020 \ || (mtype) == M_SPARC) /* @@ -56,8 +60,6 @@ The name put into the target vector. */ -void (*bfd_error_trap)(); - /*SUPPRESS558*/ /*SUPPRESS529*/ @@ -72,9 +74,9 @@ DEFUN(NAME(sunos,set_arch_mach), (abfd, machtype), case M_UNKNOWN: /* Some Sun3s make magic numbers without cpu types in them, so - we'll default to the 68020. */ + we'll default to the 68000. */ arch = bfd_arch_m68k; - machine = 68020; + machine = 68000; break; case M_68010: @@ -95,6 +97,7 @@ DEFUN(NAME(sunos,set_arch_mach), (abfd, machtype), break; case M_386: + case M_386_DYNIX: arch = bfd_arch_i386; machine = 0; break; diff --git a/bfd/aoutx.h b/bfd/aoutx.h index 1b096b2..57eeaa6 100644 --- a/bfd/aoutx.h +++ b/bfd/aoutx.h @@ -93,17 +93,18 @@ DESCRIPTION | HOST_TEXT_START_ADDR | HOST_STACK_END_ADDR - in the file <<../include/sys/h-XXX.h>> (for your host). These - values, plus the structures and macros defined in <<a.out.h>> on + in the file @file{../include/sys/h-@var{XXX}.h} (for your host). These + values, plus the structures and macros defined in @file{a.out.h} on your host system, will produce a BFD target that will access ordinary a.out files on your host. To configure a new machine - to use <<host-aout.c>., specify: + to use @file{host-aout.c}, specify: | TDEFAULTS = -DDEFAULT_VECTOR=host_aout_big_vec | TDEPFILES= host-aout.o trad-core.o - in the <<config/mt-XXX>> file, and modify @file{configure.in} to use the - <<mt-XXX>> file (by setting "<<bfd_target=XXX>>") when your + in the @file{config/@var{XXX}.mt} file, and modify @file{configure.in} + to use the + @file{@var{XXX}.mt} file (by setting "<<bfd_target=XXX>>") when your configuration is selected. */ @@ -125,6 +126,7 @@ DESCRIPTION #include "bfd.h" #include <sysdep.h> #include <ansidecl.h> +#include "bfdlink.h" struct external_exec; #include "libaout.h" @@ -133,11 +135,9 @@ struct external_exec; #include "aout/stab_gnu.h" #include "aout/ar.h" -extern void (*bfd_error_trap)(); - /* SUBSECTION - relocations + Relocations DESCRIPTION The file @file{aoutx.h} provides for both the @emph{standard} @@ -156,7 +156,7 @@ DESCRIPTION reloc_howto_type howto_table_ext[] = { - /* type rs size bsz pcrel bitpos ovrf sf name part_inpl readmask setmask pcdone */ + /* type rs size bsz pcrel bitpos ovrf sf name part_inpl readmask setmask pcdone */ HOWTO(RELOC_8, 0, 0, 8, false, 0, complain_overflow_bitfield,0,"8", false, 0,0x000000ff, false), HOWTO(RELOC_16, 0, 1, 16, false, 0, complain_overflow_bitfield,0,"16", false, 0,0x0000ffff, false), HOWTO(RELOC_32, 0, 2, 32, false, 0, complain_overflow_bitfield,0,"32", false, 0,0xffffffff, false), @@ -186,7 +186,7 @@ reloc_howto_type howto_table_ext[] = /* Convert standard reloc records to "arelent" format (incl byte swap). */ reloc_howto_type howto_table_std[] = { - /* type rs size bsz pcrel bitpos ovrf sf name part_inpl readmask setmask pcdone */ + /* type rs size bsz pcrel bitpos ovrf sf name part_inpl readmask setmask pcdone */ HOWTO( 0, 0, 0, 8, false, 0, complain_overflow_bitfield,0,"8", true, 0x000000ff,0x000000ff, false), HOWTO( 1, 0, 1, 16, false, 0, complain_overflow_bitfield,0,"16", true, 0x0000ffff,0x0000ffff, false), HOWTO( 2, 0, 2, 32, false, 0, complain_overflow_bitfield,0,"32", true, 0xffffffff,0xffffffff, false), @@ -242,11 +242,9 @@ DEFUN(NAME(aout,reloc_type_lookup),(abfd,code), } } -extern bfd_error_vector_type bfd_error_vector; - /* SUBSECTION - Internal Entry Points + Internal entry points DESCRIPTION @file{aoutx.h} exports several routines for accessing the @@ -681,29 +679,199 @@ DEFUN(NAME(aout,set_arch_mach),(abfd, arch, machine), return (*aout_backend_info(abfd)->set_sizes) (abfd); } +static void +adjust_o_magic (abfd, execp) + bfd *abfd; + struct internal_exec *execp; +{ + file_ptr pos = adata (abfd).exec_bytes_size; + bfd_vma vma = 0; + int pad = 0; + + /* Text. */ + obj_textsec(abfd)->filepos = pos; + pos += obj_textsec(abfd)->_raw_size; + vma += obj_textsec(abfd)->_raw_size; + + /* Data. */ + if (!obj_datasec(abfd)->user_set_vma) + { +#if 0 /* ?? Does alignment in the file image really matter? */ + pad = align_power (vma, obj_datasec(abfd)->alignment_power) - vma; +#endif + obj_textsec(abfd)->_raw_size += pad; + pos += pad; + vma += pad; + obj_datasec(abfd)->vma = vma; + } + obj_datasec(abfd)->filepos = pos; + pos += obj_datasec(abfd)->_raw_size; + vma += obj_datasec(abfd)->_raw_size; + + /* BSS. */ + if (!obj_bsssec(abfd)->user_set_vma) + { +#if 0 + pad = align_power (vma, obj_bsssec(abfd)->alignment_power) - vma; +#endif + obj_datasec(abfd)->_raw_size += pad; + pos += pad; + vma += pad; + obj_bsssec(abfd)->vma = vma; + } + obj_bsssec(abfd)->filepos = pos; + + /* Fix up the exec header. */ + execp->a_text = obj_textsec(abfd)->_raw_size; + execp->a_data = obj_datasec(abfd)->_raw_size; + execp->a_bss = obj_bsssec(abfd)->_raw_size; + N_SET_MAGIC (*execp, OMAGIC); +} + +static void +adjust_z_magic (abfd, execp) + bfd *abfd; + struct internal_exec *execp; +{ + bfd_size_type data_pad, text_pad; + file_ptr text_end; + CONST struct aout_backend_data *abdp; + int ztih; /* Nonzero if text includes exec header. */ + bfd_vma data_vma; + + abdp = aout_backend_info (abfd); + + /* Text. */ + ztih = abdp && abdp->text_includes_header; + obj_textsec(abfd)->filepos = (ztih + ? adata(abfd).exec_bytes_size + : adata(abfd).page_size); + if (! obj_textsec(abfd)->user_set_vma) + /* ?? Do we really need to check for relocs here? */ + obj_textsec(abfd)->vma = ((abfd->flags & HAS_RELOC) + ? 0 + : (ztih + ? (abdp->default_text_vma + + adata(abfd).exec_bytes_size) + : abdp->default_text_vma)); + /* Could take strange alignment of text section into account here? */ + + /* Find start of data. */ + text_end = obj_textsec(abfd)->filepos + obj_textsec(abfd)->_raw_size; + text_pad = BFD_ALIGN (text_end, adata(abfd).page_size) - text_end; + obj_textsec(abfd)->_raw_size += text_pad; + text_end += text_pad; + + /* Data. */ + if (!obj_datasec(abfd)->user_set_vma) + { + bfd_vma vma; + vma = obj_textsec(abfd)->vma + obj_textsec(abfd)->_raw_size; + obj_datasec(abfd)->vma = BFD_ALIGN (vma, adata(abfd).segment_size); + } + data_vma = obj_datasec(abfd)->vma; + if (abdp && abdp->zmagic_mapped_contiguous) + { + text_pad = (obj_datasec(abfd)->vma + - obj_textsec(abfd)->vma + - obj_textsec(abfd)->_raw_size); + obj_textsec(abfd)->_raw_size += text_pad; + } + obj_datasec(abfd)->filepos = (obj_textsec(abfd)->filepos + + obj_textsec(abfd)->_raw_size); + + /* Fix up exec header while we're at it. */ + execp->a_text = obj_textsec(abfd)->_raw_size; + if (ztih && (!abdp || (abdp && !abdp->exec_header_not_counted))) + execp->a_text += adata(abfd).exec_bytes_size; + N_SET_MAGIC (*execp, ZMAGIC); + /* Spec says data section should be rounded up to page boundary. */ + /* If extra space in page is left after data section, fudge data + in the header so that the bss section looks smaller by that + amount. We'll start the bss section there, and lie to the OS. */ + obj_datasec(abfd)->_raw_size + = align_power (obj_datasec(abfd)->_raw_size, + obj_bsssec(abfd)->alignment_power); + execp->a_data = BFD_ALIGN (obj_datasec(abfd)->_raw_size, + adata(abfd).page_size); + data_pad = execp->a_data - obj_datasec(abfd)->_raw_size; + + /* BSS. */ + if (!obj_bsssec(abfd)->user_set_vma) + obj_bsssec(abfd)->vma = (obj_datasec(abfd)->vma + + obj_datasec(abfd)->_raw_size); + execp->a_bss = (data_pad > obj_bsssec(abfd)->_raw_size) ? 0 : + obj_bsssec(abfd)->_raw_size - data_pad; +} + +static void +adjust_n_magic (abfd, execp) + bfd *abfd; + struct internal_exec *execp; +{ + file_ptr pos = adata(abfd).exec_bytes_size; + bfd_vma vma = 0; + int pad; + + /* Text. */ + obj_textsec(abfd)->filepos = pos; + if (!obj_textsec(abfd)->user_set_vma) + obj_textsec(abfd)->vma = vma; + else + vma = obj_textsec(abfd)->vma; + pos += obj_textsec(abfd)->_raw_size; + vma += obj_textsec(abfd)->_raw_size; + + /* Data. */ + obj_datasec(abfd)->filepos = pos; + if (!obj_datasec(abfd)->user_set_vma) + obj_datasec(abfd)->vma = BFD_ALIGN (vma, adata(abfd).segment_size); + vma = obj_datasec(abfd)->vma; + + /* Since BSS follows data immediately, see if it needs alignment. */ + vma += obj_datasec(abfd)->_raw_size; + pad = align_power (vma, obj_bsssec(abfd)->alignment_power) - vma; + obj_datasec(abfd)->_raw_size += pad; + pos += obj_datasec(abfd)->_raw_size; + + /* BSS. */ + if (!obj_bsssec(abfd)->user_set_vma) + obj_bsssec(abfd)->vma = vma; + else + vma = obj_bsssec(abfd)->vma; + + /* Fix up exec header. */ + execp->a_text = obj_textsec(abfd)->_raw_size; + execp->a_data = obj_datasec(abfd)->_raw_size; + execp->a_bss = obj_bsssec(abfd)->_raw_size; + N_SET_MAGIC (*execp, NMAGIC); +} + boolean -DEFUN (NAME (aout,adjust_sizes_and_vmas), (abfd, text_size, text_end), +DEFUN (NAME(aout,adjust_sizes_and_vmas), (abfd, text_size, text_end), bfd *abfd AND bfd_size_type *text_size AND file_ptr *text_end) { struct internal_exec *execp = exec_hdr (abfd); + if ((obj_textsec (abfd) == NULL) || (obj_datasec (abfd) == NULL)) { bfd_error = invalid_operation; return false; } if (adata(abfd).magic != undecided_magic) return true; + obj_textsec(abfd)->_raw_size = align_power(obj_textsec(abfd)->_raw_size, obj_textsec(abfd)->alignment_power); *text_size = obj_textsec (abfd)->_raw_size; /* Rule (heuristic) for when to pad to a new page. Note that there - * are (at least) two ways demand-paged (ZMAGIC) files have been - * handled. Most Berkeley-based systems start the text segment at - * (PAGE_SIZE). However, newer versions of SUNOS start the text - * segment right after the exec header; the latter is counted in the - * text segment size, and is paged in by the kernel with the rest of - * the text. */ + are (at least) two ways demand-paged (ZMAGIC) files have been + handled. Most Berkeley-based systems start the text segment at + (PAGE_SIZE). However, newer versions of SUNOS start the text + segment right after the exec header; the latter is counted in the + text segment size, and is paged in by the kernel with the rest of + the text. */ /* This perhaps isn't the right way to do this, but made it simpler for me to understand enough to implement it. Better would probably be to go @@ -712,17 +880,15 @@ DEFUN (NAME (aout,adjust_sizes_and_vmas), (abfd, text_size, text_end), other magic, that it was a little hard for me to understand. I think I understand it better now, but I haven't time to do the cleanup this minute. */ - if (adata(abfd).magic == undecided_magic) - { - if (abfd->flags & D_PAGED) - /* Whether or not WP_TEXT is set -- let D_PAGED override. */ - /* @@ What about QMAGIC? */ - adata(abfd).magic = z_magic; - else if (abfd->flags & WP_TEXT) - adata(abfd).magic = n_magic; - else - adata(abfd).magic = o_magic; - } + + if (abfd->flags & D_PAGED) + /* Whether or not WP_TEXT is set -- let D_PAGED override. */ + /* @@ What about QMAGIC? */ + adata(abfd).magic = z_magic; + else if (abfd->flags & WP_TEXT) + adata(abfd).magic = n_magic; + else + adata(abfd).magic = o_magic; #ifdef BFD_AOUT_DEBUG /* requires gcc2 */ #if __GNUC__ >= 2 @@ -736,167 +902,39 @@ DEFUN (NAME (aout,adjust_sizes_and_vmas), (abfd, text_size, text_end), } str; }), - obj_textsec(abfd)->vma, obj_textsec(abfd)->_raw_size, obj_textsec(abfd)->alignment_power, - obj_datasec(abfd)->vma, obj_datasec(abfd)->_raw_size, obj_datasec(abfd)->alignment_power, - obj_bsssec(abfd)->vma, obj_bsssec(abfd)->_raw_size, obj_bsssec(abfd)->alignment_power); + obj_textsec(abfd)->vma, obj_textsec(abfd)->_raw_size, + obj_textsec(abfd)->alignment_power, + obj_datasec(abfd)->vma, obj_datasec(abfd)->_raw_size, + obj_datasec(abfd)->alignment_power, + obj_bsssec(abfd)->vma, obj_bsssec(abfd)->_raw_size, + obj_bsssec(abfd)->alignment_power); #endif #endif switch (adata(abfd).magic) { case o_magic: - { - file_ptr pos = adata (abfd).exec_bytes_size; - bfd_vma vma = 0; - int pad = 0; - - obj_textsec(abfd)->filepos = pos; - pos += obj_textsec(abfd)->_raw_size; - vma += obj_textsec(abfd)->_raw_size; - if (!obj_datasec(abfd)->user_set_vma) - { -#if 0 /* ?? Does alignment in the file image really matter? */ - pad = align_power (vma, obj_datasec(abfd)->alignment_power) - vma; -#endif - obj_textsec(abfd)->_raw_size += pad; - pos += pad; - vma += pad; - obj_datasec(abfd)->vma = vma; - } - obj_datasec(abfd)->filepos = pos; - pos += obj_datasec(abfd)->_raw_size; - vma += obj_datasec(abfd)->_raw_size; - if (!obj_bsssec(abfd)->user_set_vma) - { -#if 0 - pad = align_power (vma, obj_bsssec(abfd)->alignment_power) - vma; -#endif - obj_datasec(abfd)->_raw_size += pad; - pos += pad; - vma += pad; - obj_bsssec(abfd)->vma = vma; - } - obj_bsssec(abfd)->filepos = pos; - execp->a_text = obj_textsec(abfd)->_raw_size; - execp->a_data = obj_datasec(abfd)->_raw_size; - execp->a_bss = obj_bsssec(abfd)->_raw_size; - N_SET_MAGIC (*execp, OMAGIC); - } + adjust_o_magic (abfd, execp); break; case z_magic: - { - bfd_size_type data_pad, text_pad; - file_ptr text_end; - CONST struct aout_backend_data *abdp; - int ztih; - bfd_vma data_vma; - - abdp = aout_backend_info (abfd); - ztih = abdp && abdp->text_includes_header; - obj_textsec(abfd)->filepos = (ztih - ? adata(abfd).exec_bytes_size - : adata(abfd).page_size); - if (! obj_textsec(abfd)->user_set_vma) - /* ?? Do we really need to check for relocs here? */ - obj_textsec(abfd)->vma = ((abfd->flags & HAS_RELOC) - ? 0 - : (ztih - ? (abdp->default_text_vma - + adata(abfd).exec_bytes_size) - : abdp->default_text_vma)); - /* Could take strange alignment of text section into account here? */ - - /* Find start of data. */ - text_end = obj_textsec(abfd)->filepos + obj_textsec(abfd)->_raw_size; - text_pad = BFD_ALIGN (text_end, adata(abfd).page_size) - text_end; - obj_textsec(abfd)->_raw_size += text_pad; - text_end += text_pad; - - if (!obj_datasec(abfd)->user_set_vma) - { - bfd_vma vma; - vma = obj_textsec(abfd)->vma + obj_textsec(abfd)->_raw_size; - obj_datasec(abfd)->vma = BFD_ALIGN (vma, adata(abfd).segment_size); - } - data_vma = obj_datasec(abfd)->vma; - if (abdp && abdp->zmagic_mapped_contiguous) - { - text_pad = (obj_datasec(abfd)->vma - - obj_textsec(abfd)->vma - - obj_textsec(abfd)->_raw_size); - obj_textsec(abfd)->_raw_size += text_pad; - } - obj_datasec(abfd)->filepos = (obj_textsec(abfd)->filepos - + obj_textsec(abfd)->_raw_size); - - /* Fix up exec header while we're at it. */ - execp->a_text = obj_textsec(abfd)->_raw_size; - if (ztih && (!abdp || (abdp && !abdp->exec_header_not_counted))) - execp->a_text += adata(abfd).exec_bytes_size; - N_SET_MAGIC (*execp, ZMAGIC); - /* Spec says data section should be rounded up to page boundary. */ - /* If extra space in page is left after data section, fudge data - in the header so that the bss section looks smaller by that - amount. We'll start the bss section there, and lie to the OS. */ - obj_datasec(abfd)->_raw_size - = align_power (obj_datasec(abfd)->_raw_size, - obj_bsssec(abfd)->alignment_power); - execp->a_data = BFD_ALIGN (obj_datasec(abfd)->_raw_size, - adata(abfd).page_size); - data_pad = execp->a_data - obj_datasec(abfd)->_raw_size; - - if (!obj_bsssec(abfd)->user_set_vma) - obj_bsssec(abfd)->vma = (obj_datasec(abfd)->vma - + obj_datasec(abfd)->_raw_size); - if (data_pad > obj_bsssec(abfd)->_raw_size) - execp->a_bss = 0; - else - execp->a_bss = obj_bsssec(abfd)->_raw_size - data_pad; - } + adjust_z_magic (abfd, execp); break; case n_magic: - { - file_ptr pos = adata(abfd).exec_bytes_size; - bfd_vma vma = 0; - int pad; - - obj_textsec(abfd)->filepos = pos; - if (!obj_textsec(abfd)->user_set_vma) - obj_textsec(abfd)->vma = vma; - else - vma = obj_textsec(abfd)->vma; - pos += obj_textsec(abfd)->_raw_size; - vma += obj_textsec(abfd)->_raw_size; - obj_datasec(abfd)->filepos = pos; - if (!obj_datasec(abfd)->user_set_vma) - obj_datasec(abfd)->vma = BFD_ALIGN (vma, adata(abfd).segment_size); - vma = obj_datasec(abfd)->vma; - - /* Since BSS follows data immediately, see if it needs alignment. */ - vma += obj_datasec(abfd)->_raw_size; - pad = align_power (vma, obj_bsssec(abfd)->alignment_power) - vma; - obj_datasec(abfd)->_raw_size += pad; - pos += obj_datasec(abfd)->_raw_size; - - if (!obj_bsssec(abfd)->user_set_vma) - obj_bsssec(abfd)->vma = vma; - else - vma = obj_bsssec(abfd)->vma; - } - execp->a_text = obj_textsec(abfd)->_raw_size; - execp->a_data = obj_datasec(abfd)->_raw_size; - execp->a_bss = obj_bsssec(abfd)->_raw_size; - N_SET_MAGIC (*execp, NMAGIC); + adjust_n_magic (abfd, execp); break; default: abort (); } + #ifdef BFD_AOUT_DEBUG fprintf (stderr, " text=<%x,%x,%x> data=<%x,%x,%x> bss=<%x,%x>\n", - obj_textsec(abfd)->vma, obj_textsec(abfd)->_raw_size, obj_textsec(abfd)->filepos, - obj_datasec(abfd)->vma, obj_datasec(abfd)->_raw_size, obj_datasec(abfd)->filepos, + obj_textsec(abfd)->vma, obj_textsec(abfd)->_raw_size, + obj_textsec(abfd)->filepos, + obj_datasec(abfd)->vma, obj_datasec(abfd)->_raw_size, + obj_datasec(abfd)->filepos, obj_bsssec(abfd)->vma, obj_bsssec(abfd)->_raw_size); #endif + return true; } @@ -1163,7 +1201,6 @@ DEFUN (translate_from_native_sym_flags, (sym_pointer, cache_ptr, abfd), break; default: case N_ABS: - cache_ptr->symbol.section = &bfd_abs_section; break; } @@ -1231,7 +1268,7 @@ DEFUN (translate_from_native_sym_flags, (sym_pointer, cache_ptr, abfd), -static void +static boolean DEFUN(translate_to_native_sym_flags,(sym_pointer, cache_ptr, abfd), struct external_nlist *sym_pointer AND asymbol *cache_ptr AND @@ -1270,19 +1307,8 @@ DEFUN(translate_to_native_sym_flags,(sym_pointer, cache_ptr, abfd), sym_pointer->e_type[0] = (N_UNDF | N_EXT); } else { - if (cache_ptr->section->output_section) - { - - bfd_error_vector.nonrepresentable_section(abfd, - bfd_get_output_section(cache_ptr)->name); - } - else - { - bfd_error_vector.nonrepresentable_section(abfd, - cache_ptr->section->name); - - } - + bfd_error = bfd_error_nonrepresentable_section; + return false; } /* Turn the symbol from section relative to absolute again */ @@ -1312,6 +1338,8 @@ DEFUN(translate_to_native_sym_flags,(sym_pointer, cache_ptr, abfd), } PUT_WORD(abfd, value, sym_pointer->e_value); + + return true; } /* Native-level interface to symbols. */ @@ -1804,7 +1832,7 @@ emit_strtab (abfd, tab) } */ } -void +boolean DEFUN(NAME(aout,write_syms),(abfd), bfd *abfd) { @@ -1838,9 +1866,12 @@ DEFUN(NAME(aout,write_syms),(abfd), bfd_h_put_8(abfd, 0, nsp.e_type); } - translate_to_native_sym_flags (&nsp, g, abfd); + if (! translate_to_native_sym_flags (&nsp, g, abfd)) + return false; - bfd_write((PTR)&nsp,1,EXTERNAL_NLIST_SIZE, abfd); + if (bfd_write((PTR)&nsp,1,EXTERNAL_NLIST_SIZE, abfd) + != EXTERNAL_NLIST_SIZE) + return false; /* NB: `KEEPIT' currently overlays `flags', so set this only here, at the end. */ @@ -1848,6 +1879,8 @@ DEFUN(NAME(aout,write_syms),(abfd), } emit_strtab (abfd, &strtab); + + return true; } @@ -2562,3 +2595,1704 @@ DEFUN(NAME(aout,sizeof_headers),(abfd, execable), { return adata(abfd).exec_bytes_size; } + +/* a.out link code. */ + +/* a.out linker hash table entries. */ + +struct aout_link_hash_entry +{ + struct bfd_link_hash_entry root; + /* Symbol index in output file. */ + int indx; +}; + +/* a.out linker hash table. */ + +struct aout_link_hash_table +{ + struct bfd_link_hash_table root; +}; + +static struct bfd_hash_entry *aout_link_hash_newfunc + PARAMS ((struct bfd_hash_entry *entry, + struct bfd_hash_table *table, + const char *string)); +static boolean aout_link_add_object_symbols + PARAMS ((bfd *, struct bfd_link_info *)); +static boolean aout_link_check_archive_element + PARAMS ((bfd *, struct bfd_link_info *, boolean *)); +static boolean aout_link_get_symbols PARAMS ((bfd *)); +static boolean aout_link_free_symbols PARAMS ((bfd *)); +static boolean aout_link_check_ar_symbols + PARAMS ((bfd *, struct bfd_link_info *, boolean *pneeded)); +static boolean aout_link_add_symbols + PARAMS ((bfd *, struct bfd_link_info *)); + +/* Routine to create an entry in an a.out link hash table. */ + +static struct bfd_hash_entry * +aout_link_hash_newfunc (entry, table, string) + struct bfd_hash_entry *entry; + struct bfd_hash_table *table; + const char *string; +{ + struct aout_link_hash_entry *ret = (struct aout_link_hash_entry *) entry; + + /* Allocate the structure if it has not already been allocated by a + subclass. */ + if (ret == (struct aout_link_hash_entry *) NULL) + ret = ((struct aout_link_hash_entry *) + bfd_hash_allocate (table, sizeof (struct aout_link_hash_entry))); + + /* Call the allocation method of the superclass. */ + ret = ((struct aout_link_hash_entry *) + _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret, + table, string)); + + /* Set local fields. */ + ret->indx = -1; + + return (struct bfd_hash_entry *) ret; +} + +/* Create an a.out link hash table. */ + +struct bfd_link_hash_table * +NAME(aout,link_hash_table_create) (abfd) + bfd *abfd; +{ + struct aout_link_hash_table *ret; + + ret = ((struct aout_link_hash_table *) + bfd_xmalloc (sizeof (struct aout_link_hash_table))); + if (! _bfd_link_hash_table_init (&ret->root, abfd, + aout_link_hash_newfunc)) + { + free (ret); + return (struct bfd_link_hash_table *) NULL; + } + return &ret->root; +} + +/* Look up an entry in an a.out link hash table. */ + +#define aout_link_hash_lookup(table, string, create, copy, follow) \ + ((struct aout_link_hash_entry *) \ + bfd_link_hash_lookup (&(table)->root, (string), (create), (copy), (follow))) + +/* Traverse an a.out link hash table. */ + +#define aout_link_hash_traverse(table, func, info) \ + (bfd_link_hash_traverse \ + (&(table)->root, \ + (boolean (*) PARAMS ((struct bfd_link_hash_entry *, PTR))) (func), \ + (info))) + +/* Get the a.out link hash table from the info structure. This is + just a cast. */ + +#define aout_hash_table(p) ((struct aout_link_hash_table *) ((p)->hash)) + +/* Given an a.out BFD, add symbols to the global hash table as + appropriate. */ + +boolean +NAME(aout,link_add_symbols) (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + switch (bfd_get_format (abfd)) + { + case bfd_object: + return aout_link_add_object_symbols (abfd, info); + case bfd_archive: + return _bfd_generic_link_add_archive_symbols + (abfd, info, aout_link_check_archive_element); + default: + bfd_error = wrong_format; + return false; + } +} + +/* Add symbols from an a.out object file. */ + +static boolean +aout_link_add_object_symbols (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + if (! aout_link_get_symbols (abfd)) + return false; + if (! aout_link_add_symbols (abfd, info)) + return false; + if (! info->keep_memory) + { + if (! aout_link_free_symbols (abfd)) + return false; + } + return true; +} + +/* Check a single archive element to see if we need to include it in + the link. *PNEEDED is set according to whether this element is + needed in the link or not. This is called from + _bfd_generic_link_add_archive_symbols. */ + +static boolean +aout_link_check_archive_element (abfd, info, pneeded) + bfd *abfd; + struct bfd_link_info *info; + boolean *pneeded; +{ + if (! aout_link_get_symbols (abfd)) + return false; + + if (! aout_link_check_ar_symbols (abfd, info, pneeded)) + return false; + + if (*pneeded) + { + if (! aout_link_add_symbols (abfd, info)) + return false; + } + + /* We keep around the symbols even if we aren't going to use this + object file, because we may want to reread it. This doesn't + waste too much memory, because it isn't all that common to read + an archive element but not need it. */ + if (! info->keep_memory) + { + if (! aout_link_free_symbols (abfd)) + return false; + } + + return true; +} + +/* Read the internal symbols from an a.out file. */ + +static boolean +aout_link_get_symbols (abfd) + bfd *abfd; +{ + bfd_size_type count; + struct external_nlist *syms; + unsigned char string_chars[BYTES_IN_WORD]; + bfd_size_type stringsize; + char *strings; + + if (obj_aout_external_syms (abfd) != (struct external_nlist *) NULL) + { + /* We already have them. */ + return true; + } + + count = exec_hdr (abfd)->a_syms / EXTERNAL_NLIST_SIZE; + + /* We allocate using bfd_xmalloc to make the values easy to free + later on. If we put them on the obstack it might not be possible + to free them. */ + syms = ((struct external_nlist *) + bfd_xmalloc ((size_t) count * EXTERNAL_NLIST_SIZE)); + + if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0 + || (bfd_read ((PTR) syms, 1, exec_hdr (abfd)->a_syms, abfd) + != exec_hdr (abfd)->a_syms)) + return false; + + /* Get the size of the strings. */ + if (bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET) != 0 + || (bfd_read ((PTR) string_chars, BYTES_IN_WORD, 1, abfd) + != BYTES_IN_WORD)) + return false; + stringsize = GET_WORD (abfd, string_chars); + strings = (char *) bfd_xmalloc ((size_t) stringsize); + + /* Skip space for the string count in the buffer for convenience + when using indexes. */ + if (bfd_read (strings + BYTES_IN_WORD, 1, stringsize - BYTES_IN_WORD, abfd) + != stringsize - BYTES_IN_WORD) + return false; + + /* Save the data. */ + obj_aout_external_syms (abfd) = syms; + obj_aout_external_sym_count (abfd) = count; + obj_aout_external_strings (abfd) = strings; + + return true; +} + +/* Free up the internal symbols read from an a.out file. */ + +static boolean +aout_link_free_symbols (abfd) + bfd *abfd; +{ + if (obj_aout_external_syms (abfd) != (struct external_nlist *) NULL) + { + free ((PTR) obj_aout_external_syms (abfd)); + obj_aout_external_syms (abfd) = (struct external_nlist *) NULL; + } + if (obj_aout_external_strings (abfd) != (char *) NULL) + { + free ((PTR) obj_aout_external_strings (abfd)); + obj_aout_external_strings (abfd) = (char *) NULL; + } + return true; +} + +/* Look through the internal symbols to see if this object file should + be included in the link. We should include this object file if it + defines any symbols which are currently undefined. If this object + file defines a common symbol, then we may adjust the size of the + known symbol but we do not include the object file in the link + (unless there is some other reason to include it). */ + +static boolean +aout_link_check_ar_symbols (abfd, info, pneeded) + bfd *abfd; + struct bfd_link_info *info; + boolean *pneeded; +{ + register struct external_nlist *p; + struct external_nlist *pend; + char *strings; + + *pneeded = false; + + /* Look through all the symbols. */ + p = obj_aout_external_syms (abfd); + pend = p + obj_aout_external_sym_count (abfd); + strings = obj_aout_external_strings (abfd); + for (; p < pend; p++) + { + int type = bfd_h_get_8 (abfd, p->e_type); + const char *name; + struct bfd_link_hash_entry *h; + + /* Ignore symbols that are not externally visible. */ + if ((type & N_EXT) == 0) + continue; + + name = strings + GET_WORD (abfd, p->e_strx); + h = bfd_link_hash_lookup (info->hash, name, false, false, true); + + /* We are only interested in symbols that are currently + undefined or common. */ + if (h == (struct bfd_link_hash_entry *) NULL + || (h->type != bfd_link_hash_undefined + && h->type != bfd_link_hash_common)) + continue; + + if ((type & (N_TEXT | N_DATA | N_BSS)) != 0) + { + /* This object file defines this symbol. We must link it + in. This is true regardless of whether the current + definition of the symbol is undefined or common. If the + current definition is common, we have a case in which we + have already seen an object file including + int a; + and this object file from the archive includes + int a = 5; + In such a case we must include this object file. */ + if (! (*info->callbacks->add_archive_element) (info, abfd, name)) + return false; + *pneeded = true; + return true; + } + + if (type == (N_EXT | N_UNDF)) + { + bfd_vma value; + + value = GET_WORD (abfd, p->e_value); + if (value != 0) + { + /* This symbol is common in the object from the archive + file. */ + if (h->type == bfd_link_hash_undefined) + { + bfd *symbfd; + + symbfd = h->u.undef.abfd; + if (symbfd == (bfd *) NULL) + { + /* This symbol was created as undefined from + outside BFD. We assume that we should link + in the object file. This is done for the -u + option in the linker. */ + if (! (*info->callbacks->add_archive_element) (info, + abfd, + name)) + return false; + *pneeded = true; + return true; + } + /* Turn the current link symbol into a common + symbol. It is already on the undefs list. */ + h->type = bfd_link_hash_common; + h->u.c.size = value; + h->u.c.section = bfd_make_section_old_way (symbfd, + "COMMON"); + } + else + { + /* Adjust the size of the common symbol if + necessary. */ + if (value > h->u.c.size) + h->u.c.size = value; + } + } + } + } + + /* We do not need this object file. */ + return true; +} + +/* Add all symbols from an object file to the hash table. */ + +static boolean +aout_link_add_symbols (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + bfd_size_type sym_count; + char *strings; + boolean copy; + struct aout_link_hash_entry **sym_hash; + register struct external_nlist *p; + struct external_nlist *pend; + + sym_count = obj_aout_external_sym_count (abfd); + strings = obj_aout_external_strings (abfd); + if (info->keep_memory) + copy = false; + else + copy = true; + + + /* We keep a list of the linker hash table entries that correspond + to particular symbols. We could just look them up in the hash + table, but keeping the list is more efficient. Perhaps this + should be conditional on info->keep_memory. */ + sym_hash = ((struct aout_link_hash_entry **) + bfd_alloc (abfd, + ((size_t) sym_count + * sizeof (struct aout_link_hash_entry *)))); + obj_aout_sym_hashes (abfd) = sym_hash; + + p = obj_aout_external_syms (abfd); + pend = p + sym_count; + for (; p < pend; p++, sym_hash++) + { + int type; + const char *name; + bfd_vma value; + asection *section; + flagword flags; + const char *string; + + *sym_hash = NULL; + + type = bfd_h_get_8 (abfd, p->e_type); + + /* Ignore debugging symbols. */ + if ((type & N_STAB) != 0) + continue; + + /* Ignore symbols that are not external. */ + if ((type & N_EXT) == 0 + && type != N_WARNING + && type != N_SETA + && type != N_SETT + && type != N_SETD + && type != N_SETB) + { + /* If this is an N_INDR symbol we must skip the next entry, + which is the symbol to indirect to (actually, an N_INDR + symbol without N_EXT set is pretty useless). */ + if (type == N_INDR) + ++p; + continue; + } + + /* Ignore N_FN symbols (these appear to have N_EXT set). */ + if (type == N_FN) + continue; + + name = strings + GET_WORD (abfd, p->e_strx); + value = GET_WORD (abfd, p->e_value); + flags = BSF_GLOBAL; + string = NULL; + switch (type) + { + default: + abort (); + case N_UNDF | N_EXT: + if (value != 0) + section = &bfd_com_section; + else + section = &bfd_und_section; + break; + case N_ABS | N_EXT: + section = &bfd_abs_section; + break; + case N_TEXT | N_EXT: + section = obj_textsec (abfd); + value -= bfd_get_section_vma (abfd, section); + break; + case N_DATA | N_EXT: + section = obj_datasec (abfd); + value -= bfd_get_section_vma (abfd, section); + break; + case N_BSS | N_EXT: + section = obj_bsssec (abfd); + value -= bfd_get_section_vma (abfd, section); + break; + case N_INDR | N_EXT: + /* An indirect symbol. The next symbol is the symbol + which this one really is. */ + BFD_ASSERT (p + 1 < pend); + ++p; + string = strings + GET_WORD (abfd, p->e_strx); + section = &bfd_ind_section; + flags |= BSF_INDIRECT; + break; + case N_COMM | N_EXT: + section = &bfd_com_section; + break; + case N_SETA: + section = &bfd_abs_section; + flags |= BSF_CONSTRUCTOR; + break; + case N_SETT: + section = obj_textsec (abfd); + flags |= BSF_CONSTRUCTOR; + value -= bfd_get_section_vma (abfd, section); + break; + case N_SETD: + section = obj_datasec (abfd); + flags |= BSF_CONSTRUCTOR; + value -= bfd_get_section_vma (abfd, section); + break; + case N_SETB: + section = obj_bsssec (abfd); + flags |= BSF_CONSTRUCTOR; + value -= bfd_get_section_vma (abfd, section); + break; + case N_WARNING: + /* A warning symbol. The next symbol is the one to warn + about. */ + BFD_ASSERT (p + 1 < pend); + ++p; + string = name; + name = strings + GET_WORD (abfd, p->e_strx); + section = &bfd_und_section; + flags |= BSF_WARNING; + break; + } + + if (! (_bfd_generic_link_add_one_symbol + (info, abfd, name, flags, section, value, string, copy, + (struct bfd_link_hash_entry **) sym_hash))) + return false; + } + + return true; +} + +/* During the final link step we need to pass around a bunch of + information, so we do it in an instance of this structure. */ + +struct aout_final_link_info +{ + /* General link information. */ + struct bfd_link_info *info; + /* Output bfd. */ + bfd *output_bfd; + /* Reloc file positions. */ + file_ptr treloff, dreloff; + /* File position of symbols. */ + file_ptr symoff; + /* String table. */ + struct stringtab_data strtab; +}; + +static boolean aout_link_input_bfd + PARAMS ((struct aout_final_link_info *, bfd *input_bfd)); +static boolean aout_link_write_symbols + PARAMS ((struct aout_final_link_info *, bfd *input_bfd, int *symbol_map)); +static boolean aout_link_write_other_symbol + PARAMS ((struct aout_link_hash_entry *, PTR)); +static boolean aout_link_input_section + PARAMS ((struct aout_final_link_info *, bfd *input_bfd, + asection *input_section, file_ptr *reloff_ptr, + bfd_size_type rel_size, int *symbol_map)); +static boolean aout_link_input_section_std + PARAMS ((struct aout_final_link_info *, bfd *input_bfd, + asection *input_section, struct reloc_std_external *, + bfd_size_type rel_size, bfd_byte *contents, int *symbol_map)); +static boolean aout_link_input_section_ext + PARAMS ((struct aout_final_link_info *, bfd *input_bfd, + asection *input_section, struct reloc_ext_external *, + bfd_size_type rel_size, bfd_byte *contents, int *symbol_map)); +static INLINE asection *aout_reloc_index_to_section + PARAMS ((bfd *, int)); + +/* Do the final link step. This is called on the output BFD. The + INFO structure should point to a list of BFDs linked through the + link_next field which can be used to find each BFD which takes part + in the output. Also, each section in ABFD should point to a list + of bfd_link_order structures which list all the input sections for + the output section. */ + +boolean +NAME(aout,final_link) (abfd, info, callback) + bfd *abfd; + struct bfd_link_info *info; + void (*callback) PARAMS ((bfd *, file_ptr *, file_ptr *, file_ptr *)); +{ + struct aout_final_link_info aout_info; + register bfd *sub; + bfd_size_type text_size; + file_ptr text_end; + register struct bfd_link_order *p; + asection *o; + + aout_info.info = info; + aout_info.output_bfd = abfd; + + if (! info->relocateable) + { + exec_hdr (abfd)->a_trsize = 0; + exec_hdr (abfd)->a_drsize = 0; + } + else + { + bfd_size_type trsize, drsize; + + /* Count up the relocation sizes. */ + trsize = 0; + drsize = 0; + for (sub = info->input_bfds; sub != (bfd *) NULL; sub = sub->link_next) + { + if (bfd_get_flavour (abfd) == bfd_target_aout_flavour) + { + trsize += exec_hdr (sub)->a_trsize; + drsize += exec_hdr (sub)->a_drsize; + } + else + { + /* FIXME: We need to identify the .text and .data sections + and call get_reloc_upper_bound and canonicalize_reloc to + work out the number of relocs needed, and then multiply + by the reloc size. */ + abort (); + } + } + exec_hdr (abfd)->a_trsize = trsize; + exec_hdr (abfd)->a_drsize = drsize; + } + + /* Adjust the section sizes and vmas according to the magic number. + This sets a_text, a_data and a_bss in the exec_hdr and sets the + filepos for each section. */ + if (! NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end)) + return false; + + /* The relocation and symbol file positions differ among a.out + targets. We are passed a callback routine from the backend + specific code to handle this. + FIXME: At this point we do not know how much space the symbol + table will require. This will not work for any (nonstandard) + a.out target that needs to know the symbol table size before it + can compute the relocation file positions. This may or may not + be the case for the hp300hpux target, for example. */ + (*callback) (abfd, &aout_info.treloff, &aout_info.dreloff, + &aout_info.symoff); + obj_textsec (abfd)->rel_filepos = aout_info.treloff; + obj_datasec (abfd)->rel_filepos = aout_info.dreloff; + obj_sym_filepos (abfd) = aout_info.symoff; + + /* We keep a count of the symbols as we output them. */ + obj_aout_external_sym_count (abfd) = 0; + + /* We accumulate the string table as we write out the symbols. */ + stringtab_init (&aout_info.strtab); + + /* The most time efficient way to do the link would be to read all + the input object files into memory and then sort out the + information into the output file. Unfortunately, that will + probably use too much memory. Another method would be to step + through everything that composes the text section and write it + out, and then everything that composes the data section and write + it out, and then write out the relocs, and then write out the + symbols. Unfortunately, that requires reading stuff from each + input file several times, and we will not be able to keep all the + input files open simultaneously, and reopening them will be slow. + + What we do is basically process one input file at a time. We do + everything we need to do with an input file once--copy over the + section contents, handle the relocation information, and write + out the symbols--and then we throw away the information we read + from it. This approach requires a lot of lseeks of the output + file, which is unfortunate but still faster than reopening a lot + of files. + + We use the output_has_begun field of the input BFDs to see + whether we have already handled it. */ + for (sub = info->input_bfds; sub != (bfd *) NULL; sub = sub->link_next) + sub->output_has_begun = false; + + for (o = abfd->sections; o != (asection *) NULL; o = o->next) + { + bfd *input_bfd; + + for (p = o->link_order_head; + p != (struct bfd_link_order *) NULL; + p = p->next) + { + /* If we might be using the C based alloca function, we need + to dump the memory allocated by aout_link_input_bfd. */ +#ifndef __GNUC__ +#ifndef alloca + (void) alloca (0); +#endif +#endif + switch (p->type) + { + case bfd_indirect_link_order: + input_bfd = p->u.indirect.section->owner; + if (bfd_get_flavour (input_bfd) == bfd_target_aout_flavour) + { + if (! input_bfd->output_has_begun) + { + if (! aout_link_input_bfd (&aout_info, input_bfd)) + return false; + input_bfd->output_has_begun = true; + } + } + else + { + /* FIXME. */ + abort (); + } + break; + default: + if (! _bfd_default_link_order (abfd, info, o, p)) + return false; + } + } + } + + /* Write out any symbols that we have not already written out. */ + aout_link_hash_traverse (aout_hash_table (info), + aout_link_write_other_symbol, + (PTR) &aout_info); + + /* Update the header information. */ + abfd->symcount = obj_aout_external_sym_count (abfd); + exec_hdr (abfd)->a_syms = abfd->symcount * EXTERNAL_NLIST_SIZE; + obj_str_filepos (abfd) = obj_sym_filepos (abfd) + exec_hdr (abfd)->a_syms; + obj_textsec (abfd)->reloc_count = + exec_hdr (abfd)->a_trsize / obj_reloc_entry_size (abfd); + obj_datasec (abfd)->reloc_count = + exec_hdr (abfd)->a_drsize / obj_reloc_entry_size (abfd); + + /* Write out the string table. */ + if (bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET) != 0) + return false; + emit_strtab (abfd, &aout_info.strtab); + + return true; +} + +/* Link an a.out input BFD into the output file. */ + +static boolean +aout_link_input_bfd (finfo, input_bfd) + struct aout_final_link_info *finfo; + bfd *input_bfd; +{ + bfd_size_type sym_count; + int *symbol_map; + + BFD_ASSERT (bfd_get_format (input_bfd) == bfd_object); + + /* Get the symbols. We probably have them already, unless + finfo->info->keep_memory is false. */ + if (! aout_link_get_symbols (input_bfd)) + return false; + + sym_count = obj_aout_external_sym_count (input_bfd); + symbol_map = (int *) alloca ((size_t) sym_count * sizeof (int)); + + /* Write out the symbols and get a map of the new indices. */ + if (! aout_link_write_symbols (finfo, input_bfd, symbol_map)) + return false; + + /* Relocate and write out the sections. */ + if (! aout_link_input_section (finfo, input_bfd, + obj_textsec (input_bfd), + &finfo->treloff, + exec_hdr (input_bfd)->a_trsize, + symbol_map) + || ! aout_link_input_section (finfo, input_bfd, + obj_datasec (input_bfd), + &finfo->dreloff, + exec_hdr (input_bfd)->a_drsize, + symbol_map)) + return false; + + /* If we are not keeping memory, we don't need the symbols any + longer. We still need them if we are keeping memory, because the + strings in the hash table point into them. */ + if (! finfo->info->keep_memory) + { + if (! aout_link_free_symbols (input_bfd)) + return false; + } + + return true; +} + +/* Adjust and write out the symbols for an a.out file. Set the new + symbol indices into a symbol_map. */ + +static boolean +aout_link_write_symbols (finfo, input_bfd, symbol_map) + struct aout_final_link_info *finfo; + bfd *input_bfd; + int *symbol_map; +{ + bfd *output_bfd; + bfd_size_type sym_count; + char *strings; + enum bfd_link_strip strip; + enum bfd_link_discard discard; + struct external_nlist *output_syms; + struct external_nlist *outsym; + register struct external_nlist *sym; + struct external_nlist *sym_end; + struct aout_link_hash_entry **sym_hash; + boolean pass; + + output_bfd = finfo->output_bfd; + sym_count = obj_aout_external_sym_count (input_bfd); + strings = obj_aout_external_strings (input_bfd); + strip = finfo->info->strip; + discard = finfo->info->discard; + output_syms = ((struct external_nlist *) + alloca ((size_t) (sym_count + 1) * EXTERNAL_NLIST_SIZE)); + outsym = output_syms; + + /* First write out a symbol for this object file, unless we are + discarding such symbols. */ + if (strip != strip_all + && (strip != strip_some + || bfd_hash_lookup (finfo->info->keep_hash, input_bfd->filename, + false, false) != NULL) + && discard != discard_all) + { + bfd_h_put_8 (output_bfd, N_TEXT, outsym->e_type); + bfd_h_put_8 (output_bfd, 0, outsym->e_other); + bfd_h_put_16 (output_bfd, (bfd_vma) 0, outsym->e_desc); + PUT_WORD (output_bfd, + add_to_stringtab (output_bfd, input_bfd->filename, + &finfo->strtab), + outsym->e_strx); + PUT_WORD (output_bfd, + bfd_get_section_vma (input_bfd, obj_textsec (input_bfd)), + outsym->e_value); + ++obj_aout_external_sym_count (output_bfd); + ++outsym; + } + + pass = false; + sym = obj_aout_external_syms (input_bfd); + sym_end = sym + sym_count; + sym_hash = obj_aout_sym_hashes (input_bfd); + for (; sym < sym_end; sym++, sym_hash++, symbol_map++) + { + const char *name; + int type; + boolean skip; + asection *symsec; + bfd_vma val = 0; + + *symbol_map = -1; + + type = bfd_h_get_8 (input_bfd, sym->e_type); + name = strings + GET_WORD (input_bfd, sym->e_strx); + + if (pass) + { + /* Pass this symbol through. */ + val = GET_WORD (input_bfd, sym->e_value); + pass = false; + } + else + { + struct aout_link_hash_entry *h; + + /* We have saved the hash table entry for this symbol, if + there is one. Note that we could just look it up again + in the hash table, provided we first check that it is an + external symbol. */ + h = *sym_hash; + + /* If the symbol has already been written out, skip it. */ + if (h != (struct aout_link_hash_entry *) NULL + && h->root.written) + { + *symbol_map = h->indx; + continue; + } + + /* See if we are stripping this symbol. */ + skip = false; + switch (strip) + { + case strip_none: + break; + case strip_debugger: + if ((type & N_STAB) != 0) + skip = true; + break; + case strip_some: + if (bfd_hash_lookup (finfo->info->keep_hash, name, false, false) + == NULL) + skip = true; + break; + case strip_all: + skip = true; + break; + } + if (skip) + { + if (h != (struct aout_link_hash_entry *) NULL) + h->root.written = true; + continue; + } + + /* Get the value of the symbol. */ + if ((type & N_TYPE) == N_TEXT) + symsec = obj_textsec (input_bfd); + else if ((type & N_TYPE) == N_DATA) + symsec = obj_datasec (input_bfd); + else if ((type & N_TYPE) == N_BSS) + symsec = obj_bsssec (input_bfd); + else if ((type & N_TYPE) == N_ABS) + symsec = &bfd_abs_section; + else if ((type & N_TYPE) == N_INDR + || type == N_WARNING) + { + /* Pass the next symbol through unchanged. */ + pass = true; + val = GET_WORD (input_bfd, sym->e_value); + symsec = NULL; + } + else if ((type & N_STAB) != 0) + { + val = GET_WORD (input_bfd, sym->e_value); + symsec = NULL; + } + else + { + if (h == (struct aout_link_hash_entry *) NULL) + val = 0; + else if (h->root.type == bfd_link_hash_defined) + { + asection *output_section; + + /* This case means a common symbol which was turned + into a defined symbol. */ + output_section = h->root.u.def.section->output_section; + BFD_ASSERT (output_section == &bfd_abs_section + || output_section->owner == output_bfd); + val = (h->root.u.def.value + + bfd_get_section_vma (output_bfd, output_section) + + h->root.u.def.section->output_offset); + + /* Get the correct type based on the section. If + this is a constructed set, force it to be + globally visible. */ + if (type == N_SETT + || type == N_SETD + || type == N_SETB + || type == N_SETA) + type |= N_EXT; + + type &=~ N_TYPE; + + if (output_section == obj_textsec (output_bfd)) + type |= N_TEXT; + else if (output_section == obj_datasec (output_bfd)) + type |= N_DATA; + else if (output_section == obj_bsssec (output_bfd)) + type |= N_BSS; + else + type |= N_ABS; + } + else if (h->root.type == bfd_link_hash_common) + val = h->root.u.c.size; + else + val = 0; + + symsec = NULL; + } + if (symsec != (asection *) NULL) + val = (symsec->output_section->vma + + symsec->output_offset + + (GET_WORD (input_bfd, sym->e_value) + - symsec->vma)); + + /* If this is a global symbol set the written flag, and if + it is a local symbol see if we should discard it. */ + if (h != (struct aout_link_hash_entry *) NULL) + { + h->root.written = true; + h->indx = obj_aout_external_sym_count (output_bfd); + } + else + { + switch (discard) + { + case discard_none: + break; + case discard_l: + if (*name == *finfo->info->lprefix + && (finfo->info->lprefix_len == 1 + || strncmp (name, finfo->info->lprefix, + finfo->info->lprefix_len) == 0)) + skip = true; + break; + case discard_all: + skip = true; + break; + } + if (skip) + { + pass = false; + continue; + } + } + } + + /* Copy this symbol into the list of symbols we are going to + write out. */ + bfd_h_put_8 (output_bfd, type, outsym->e_type); + bfd_h_put_8 (output_bfd, bfd_h_get_8 (input_bfd, sym->e_other), + outsym->e_other); + bfd_h_put_16 (output_bfd, bfd_h_get_16 (input_bfd, sym->e_desc), + outsym->e_desc); + PUT_WORD (output_bfd, + add_to_stringtab (output_bfd, name, &finfo->strtab), + outsym->e_strx); + PUT_WORD (output_bfd, val, outsym->e_value); + *symbol_map = obj_aout_external_sym_count (output_bfd); + ++obj_aout_external_sym_count (output_bfd); + ++outsym; + } + + /* Write out the output symbols we have just constructed. */ + if (outsym > output_syms) + { + bfd_size_type outsym_count; + + if (bfd_seek (output_bfd, finfo->symoff, SEEK_SET) != 0) + return false; + outsym_count = outsym - output_syms; + if (bfd_write ((PTR) output_syms, (bfd_size_type) EXTERNAL_NLIST_SIZE, + (bfd_size_type) outsym_count, output_bfd) + != outsym_count * EXTERNAL_NLIST_SIZE) + return false; + finfo->symoff += outsym_count * EXTERNAL_NLIST_SIZE; + } + + return true; +} + +/* Write out a symbol that was not associated with an a.out input + object. */ + +static boolean +aout_link_write_other_symbol (h, data) + struct aout_link_hash_entry *h; + PTR data; +{ + struct aout_final_link_info *finfo = (struct aout_final_link_info *) data; + bfd *output_bfd; + int type; + bfd_vma val; + struct external_nlist outsym; + + if (h->root.written) + return true; + + output_bfd = finfo->output_bfd; + + switch (h->root.type) + { + default: + case bfd_link_hash_new: + abort (); + /* Avoid variable not initialized warnings. */ + return true; + case bfd_link_hash_undefined: + type = N_UNDF | N_EXT; + val = 0; + break; + case bfd_link_hash_defined: + { + asection *sec; + + sec = h->root.u.def.section; + BFD_ASSERT (sec == &bfd_abs_section + || sec->owner == output_bfd); + if (sec == obj_textsec (output_bfd)) + type = N_TEXT | N_EXT; + else if (sec == obj_datasec (output_bfd)) + type = N_DATA | N_EXT; + else if (sec == obj_bsssec (output_bfd)) + type = N_BSS | N_EXT; + else + type = N_ABS | N_EXT; + val = (h->root.u.def.value + + sec->output_section->vma + + sec->output_offset); + } + break; + case bfd_link_hash_common: + type = N_UNDF | N_EXT; + val = h->root.u.c.size; + break; + case bfd_link_hash_indirect: + case bfd_link_hash_warning: + /* FIXME: Ignore these for now. The circumstances under which + they should be written out are not clear to me. */ + return true; + } + + bfd_h_put_8 (output_bfd, type, outsym.e_type); + bfd_h_put_8 (output_bfd, 0, outsym.e_other); + bfd_h_put_16 (output_bfd, 0, outsym.e_desc); + PUT_WORD (output_bfd, + add_to_stringtab (output_bfd, h->root.root.string, &finfo->strtab), + outsym.e_strx); + PUT_WORD (output_bfd, val, outsym.e_value); + + if (bfd_seek (output_bfd, finfo->symoff, SEEK_SET) != 0 + || bfd_write ((PTR) &outsym, (bfd_size_type) EXTERNAL_NLIST_SIZE, + (bfd_size_type) 1, output_bfd) != EXTERNAL_NLIST_SIZE) + { + /* FIXME: No way to handle errors. */ + abort (); + } + + finfo->symoff += EXTERNAL_NLIST_SIZE; + h->indx = obj_aout_external_sym_count (output_bfd); + ++obj_aout_external_sym_count (output_bfd); + + return true; +} + +/* Link an a.out section into the output file. */ + +static boolean +aout_link_input_section (finfo, input_bfd, input_section, reloff_ptr, + rel_size, symbol_map) + struct aout_final_link_info *finfo; + bfd *input_bfd; + asection *input_section; + file_ptr *reloff_ptr; + bfd_size_type rel_size; + int *symbol_map; +{ + bfd_size_type input_size; + bfd_byte *contents; + PTR relocs; + + /* Get the section contents. */ + input_size = bfd_section_size (input_bfd, input_section); + contents = (bfd_byte *) alloca (input_size); + if (! bfd_get_section_contents (input_bfd, input_section, contents, + (file_ptr) 0, input_size)) + return false; + + /* Read in the relocs. */ + relocs = (PTR) alloca (rel_size); + if (bfd_seek (input_bfd, input_section->rel_filepos, SEEK_SET) != 0 + || bfd_read (relocs, 1, rel_size, input_bfd) != rel_size) + return false; + + /* Relocate the section contents. */ + if (obj_reloc_entry_size (input_bfd) == RELOC_STD_SIZE) + { + if (! aout_link_input_section_std (finfo, input_bfd, input_section, + (struct reloc_std_external *) relocs, + rel_size, contents, symbol_map)) + return false; + } + else + { + if (! aout_link_input_section_ext (finfo, input_bfd, input_section, + (struct reloc_ext_external *) relocs, + rel_size, contents, symbol_map)) + return false; + } + + /* Write out the section contents. */ + if (! bfd_set_section_contents (finfo->output_bfd, + input_section->output_section, + contents, input_section->output_offset, + input_size)) + return false; + + /* If we are producing relocateable output, the relocs were + modified, and we now write them out. */ + if (finfo->info->relocateable) + { + if (bfd_seek (finfo->output_bfd, *reloff_ptr, SEEK_SET) != 0) + return false; + if (bfd_write (relocs, (bfd_size_type) 1, rel_size, finfo->output_bfd) + != rel_size) + return false; + *reloff_ptr += rel_size; + + /* Assert that the relocs have not run into the symbols, and + that if these are the text relocs they have not run into the + data relocs. */ + BFD_ASSERT (*reloff_ptr <= obj_sym_filepos (finfo->output_bfd) + && (reloff_ptr != &finfo->treloff + || (*reloff_ptr + <= obj_datasec (finfo->output_bfd)->rel_filepos))); + } + + return true; +} + +/* Get the section corresponding to a reloc index. */ + +static INLINE asection * +aout_reloc_index_to_section (abfd, indx) + bfd *abfd; + int indx; +{ + switch (indx & N_TYPE) + { + case N_TEXT: + return obj_textsec (abfd); + case N_DATA: + return obj_datasec (abfd); + case N_BSS: + return obj_bsssec (abfd); + case N_ABS: + return &bfd_abs_section; + default: + abort (); + } +} + +/* Relocate an a.out section using standard a.out relocs. */ + +static boolean +aout_link_input_section_std (finfo, input_bfd, input_section, relocs, + rel_size, contents, symbol_map) + struct aout_final_link_info *finfo; + bfd *input_bfd; + asection *input_section; + struct reloc_std_external *relocs; + bfd_size_type rel_size; + bfd_byte *contents; + int *symbol_map; +{ + bfd *output_bfd; + boolean relocateable; + struct external_nlist *syms; + char *strings; + struct aout_link_hash_entry **sym_hashes; + bfd_size_type reloc_count; + register struct reloc_std_external *rel; + struct reloc_std_external *rel_end; + + output_bfd = finfo->output_bfd; + + BFD_ASSERT (obj_reloc_entry_size (input_bfd) == RELOC_STD_SIZE); + BFD_ASSERT (input_bfd->xvec->header_byteorder_big_p + == output_bfd->xvec->header_byteorder_big_p); + + relocateable = finfo->info->relocateable; + syms = obj_aout_external_syms (input_bfd); + strings = obj_aout_external_strings (input_bfd); + sym_hashes = obj_aout_sym_hashes (input_bfd); + + reloc_count = rel_size / RELOC_STD_SIZE; + rel = relocs; + rel_end = rel + reloc_count; + for (; rel < rel_end; rel++) + { + bfd_vma r_addr; + int r_index; + int r_extern; + int r_pcrel; + int r_baserel; + int r_jmptable; + int r_relative; + int r_length; + int howto_idx; + bfd_vma relocation; + bfd_reloc_status_type r; + + r_addr = GET_SWORD (input_bfd, rel->r_address); + + if (input_bfd->xvec->header_byteorder_big_p) + { + r_index = ((rel->r_index[0] << 16) + | (rel->r_index[1] << 8) + | rel->r_index[2]); + r_extern = (0 != (rel->r_type[0] & RELOC_STD_BITS_EXTERN_BIG)); + r_pcrel = (0 != (rel->r_type[0] & RELOC_STD_BITS_PCREL_BIG)); + r_baserel = (0 != (rel->r_type[0] & RELOC_STD_BITS_BASEREL_BIG)); + r_jmptable= (0 != (rel->r_type[0] & RELOC_STD_BITS_JMPTABLE_BIG)); + r_relative= (0 != (rel->r_type[0] & RELOC_STD_BITS_RELATIVE_BIG)); + r_length = ((rel->r_type[0] & RELOC_STD_BITS_LENGTH_BIG) + >> RELOC_STD_BITS_LENGTH_SH_BIG); + } + else + { + r_index = ((rel->r_index[2] << 16) + | (rel->r_index[1] << 8) + | rel->r_index[0]); + r_extern = (0 != (rel->r_type[0] & RELOC_STD_BITS_EXTERN_LITTLE)); + r_pcrel = (0 != (rel->r_type[0] & RELOC_STD_BITS_PCREL_LITTLE)); + r_baserel = (0 != (rel->r_type[0] & RELOC_STD_BITS_BASEREL_LITTLE)); + r_jmptable= (0 != (rel->r_type[0] & RELOC_STD_BITS_JMPTABLE_LITTLE)); + r_relative= (0 != (rel->r_type[0] & RELOC_STD_BITS_RELATIVE_LITTLE)); + r_length = ((rel->r_type[0] & RELOC_STD_BITS_LENGTH_LITTLE) + >> RELOC_STD_BITS_LENGTH_SH_LITTLE); + } + + howto_idx = r_length + 4 * r_pcrel + 8 * r_baserel; + BFD_ASSERT (howto_idx < TABLE_SIZE (howto_table_std)); + BFD_ASSERT (r_jmptable == 0); + BFD_ASSERT (r_relative == 0); + + if (relocateable) + { + /* We are generating a relocateable output file, and must + modify the reloc accordingly. */ + if (r_extern) + { + struct aout_link_hash_entry *h; + + /* If we know the symbol this relocation is against, + convert it into a relocation against a section. This + is what the native linker does. */ + h = sym_hashes[r_index]; + if (h != (struct aout_link_hash_entry *) NULL + && h->root.type == bfd_link_hash_defined) + { + asection *output_section; + + /* Change the r_extern value. */ + if (output_bfd->xvec->header_byteorder_big_p) + rel->r_type[0] &=~ RELOC_STD_BITS_EXTERN_BIG; + else + rel->r_type[0] &=~ RELOC_STD_BITS_EXTERN_LITTLE; + + /* Compute a new r_index. */ + output_section = h->root.u.def.section->output_section; + if (output_section == obj_textsec (output_bfd)) + r_index = N_TEXT; + else if (output_section == obj_datasec (output_bfd)) + r_index = N_DATA; + else if (output_section == obj_bsssec (output_bfd)) + r_index = N_BSS; + else + r_index = N_ABS; + + /* Add the symbol value and the section VMA to the + addend stored in the contents. */ + relocation = (h->root.u.def.value + + output_section->vma + + h->root.u.def.section->output_offset); + } + else + { + /* We must change r_index according to the symbol + map. */ + r_index = symbol_map[r_index]; + + if (r_index == -1) + { + const char *name; + + name = strings + GET_WORD (input_bfd, + syms[r_index].e_strx); + if (! ((*finfo->info->callbacks->unattached_reloc) + (finfo->info, name, input_bfd, input_section, + r_addr))) + return false; + r_index = 0; + } + + relocation = 0; + } + + /* Write out the new r_index value. */ + if (output_bfd->xvec->header_byteorder_big_p) + { + rel->r_index[0] = r_index >> 16; + rel->r_index[1] = r_index >> 8; + rel->r_index[2] = r_index; + } + else + { + rel->r_index[2] = r_index >> 16; + rel->r_index[1] = r_index >> 8; + rel->r_index[0] = r_index; + } + } + else + { + asection *section; + + /* This is a relocation against a section. We must + adjust by the amount that the section moved. */ + section = aout_reloc_index_to_section (input_bfd, r_index); + relocation = (section->output_section->vma + + section->output_offset + - section->vma); + } + + /* Change the address of the relocation. */ + PUT_WORD (output_bfd, + r_addr + input_section->output_offset, + rel->r_address); + + /* Adjust a PC relative relocation by removing the reference + to the original address in the section and then including + the reference to the new address. */ + if (r_pcrel) + { + relocation += input_section->vma; + relocation -= (input_section->output_section->vma + + input_section->output_offset); + } + + if (relocation == 0) + r = bfd_reloc_ok; + else + r = _bfd_relocate_contents (howto_table_std + howto_idx, + input_bfd, relocation, + contents + r_addr); + } + else + { + /* We are generating an executable, and must do a full + relocation. */ + if (r_extern) + { + struct aout_link_hash_entry *h; + + h = sym_hashes[r_index]; + if (h != (struct aout_link_hash_entry *) NULL + && h->root.type == bfd_link_hash_defined) + { + relocation = (h->root.u.def.value + + h->root.u.def.section->output_section->vma + + h->root.u.def.section->output_offset); + } + else + { + const char *name; + + name = strings + GET_WORD (input_bfd, syms[r_index].e_strx); + if (! ((*finfo->info->callbacks->undefined_symbol) + (finfo->info, name, input_bfd, input_section, + r_addr))) + return false; + relocation = 0; + } + } + else + { + asection *section; + + section = aout_reloc_index_to_section (input_bfd, r_index); + relocation = (section->output_section->vma + + section->output_offset + - section->vma); + } + + + r = _bfd_final_link_relocate (howto_table_std + howto_idx, + input_bfd, input_section, + contents, r_addr, relocation, + (bfd_vma) 0); + } + + if (r != bfd_reloc_ok) + { + switch (r) + { + default: + case bfd_reloc_outofrange: + abort (); + case bfd_reloc_overflow: + if (! ((*finfo->info->callbacks->reloc_overflow) + (finfo->info, input_bfd, input_section, r_addr))) + return false; + break; + } + } + } + + return true; +} + +/* Relocate an a.out section using extended a.out relocs. */ + +static boolean +aout_link_input_section_ext (finfo, input_bfd, input_section, relocs, + rel_size, contents, symbol_map) + struct aout_final_link_info *finfo; + bfd *input_bfd; + asection *input_section; + struct reloc_ext_external *relocs; + bfd_size_type rel_size; + bfd_byte *contents; + int *symbol_map; +{ + bfd *output_bfd; + boolean relocateable; + struct external_nlist *syms; + char *strings; + struct aout_link_hash_entry **sym_hashes; + bfd_size_type reloc_count; + register struct reloc_ext_external *rel; + struct reloc_ext_external *rel_end; + + output_bfd = finfo->output_bfd; + + BFD_ASSERT (obj_reloc_entry_size (input_bfd) == RELOC_EXT_SIZE); + BFD_ASSERT (input_bfd->xvec->header_byteorder_big_p + == output_bfd->xvec->header_byteorder_big_p); + + relocateable = finfo->info->relocateable; + syms = obj_aout_external_syms (input_bfd); + strings = obj_aout_external_strings (input_bfd); + sym_hashes = obj_aout_sym_hashes (input_bfd); + + reloc_count = rel_size / RELOC_EXT_SIZE; + rel = relocs; + rel_end = rel + reloc_count; + for (; rel < rel_end; rel++) + { + bfd_vma r_addr; + int r_index; + int r_extern; + int r_type; + bfd_vma r_addend; + bfd_vma relocation; + + r_addr = GET_SWORD (input_bfd, rel->r_address); + + if (input_bfd->xvec->header_byteorder_big_p) + { + r_index = ((rel->r_index[0] << 16) + | (rel->r_index[1] << 8) + | rel->r_index[2]); + r_extern = (0 != (rel->r_type[0] & RELOC_EXT_BITS_EXTERN_BIG)); + r_type = ((rel->r_type[0] & RELOC_EXT_BITS_TYPE_BIG) + >> RELOC_EXT_BITS_TYPE_SH_BIG); + } + else + { + r_index = ((rel->r_index[2] << 16) + | (rel->r_index[1] << 8) + | rel->r_index[0]); + r_extern = (0 != (rel->r_type[0] & RELOC_EXT_BITS_EXTERN_LITTLE)); + r_type = ((rel->r_type[0] & RELOC_EXT_BITS_TYPE_LITTLE) + >> RELOC_EXT_BITS_TYPE_SH_LITTLE); + } + + r_addend = GET_SWORD (input_bfd, rel->r_addend); + + if (relocateable) + { + /* We are generating a relocateable output file, and must + modify the reloc accordingly. */ + if (r_extern) + { + struct aout_link_hash_entry *h; + + /* If we know the symbol this relocation is against, + convert it into a relocation against a section. This + is what the native linker does. */ + h = sym_hashes[r_index]; + if (h != (struct aout_link_hash_entry *) NULL + && h->root.type == bfd_link_hash_defined) + { + asection *output_section; + + /* Change the r_extern value. */ + if (output_bfd->xvec->header_byteorder_big_p) + rel->r_type[0] &=~ RELOC_EXT_BITS_EXTERN_BIG; + else + rel->r_type[0] &=~ RELOC_EXT_BITS_EXTERN_LITTLE; + + /* Compute a new r_index. */ + output_section = h->root.u.def.section->output_section; + if (output_section == obj_textsec (output_bfd)) + r_index = N_TEXT; + else if (output_section == obj_datasec (output_bfd)) + r_index = N_DATA; + else if (output_section == obj_bsssec (output_bfd)) + r_index = N_BSS; + else + r_index = N_ABS; + + /* Add the symbol value and the section VMA to the + addend. */ + relocation = (h->root.u.def.value + + output_section->vma + + h->root.u.def.section->output_offset); + } + else + { + /* We must change r_index according to the symbol + map. */ + r_index = symbol_map[r_index]; + + if (r_index == -1) + { + const char *name; + + name = (strings + + GET_WORD (input_bfd, syms[r_index].e_strx)); + if (! ((*finfo->info->callbacks->unattached_reloc) + (finfo->info, name, input_bfd, input_section, + r_addr))) + return false; + r_index = 0; + } + + relocation = 0; + } + + /* Write out the new r_index value. */ + if (output_bfd->xvec->header_byteorder_big_p) + { + rel->r_index[0] = r_index >> 16; + rel->r_index[1] = r_index >> 8; + rel->r_index[2] = r_index; + } + else + { + rel->r_index[2] = r_index >> 16; + rel->r_index[1] = r_index >> 8; + rel->r_index[0] = r_index; + } + } + else + { + asection *section; + + /* This is a relocation against a section. We must + adjust by the amount that the section moved. */ + section = aout_reloc_index_to_section (input_bfd, r_index); + relocation = (section->output_section->vma + + section->output_offset + - section->vma); + } + + /* Adjust a PC relative relocation by removing the reference + to the original address in the section and then including + the reference to the new address. */ + if (howto_table_ext[r_type].pc_relative + && ! howto_table_ext[r_type].pcrel_offset) + { + relocation += input_section->vma; + relocation -= (input_section->output_section->vma + + input_section->output_offset); + } + + /* Change the addend if necessary. */ + if (relocation != 0) + PUT_WORD (output_bfd, r_addend + relocation, rel->r_addend); + + /* Change the address of the relocation. */ + PUT_WORD (output_bfd, + r_addr + input_section->output_offset, + rel->r_address); + } + else + { + bfd_reloc_status_type r; + + /* We are generating an executable, and must do a full + relocation. */ + if (r_extern) + { + struct aout_link_hash_entry *h; + + h = sym_hashes[r_index]; + if (h != (struct aout_link_hash_entry *) NULL + && h->root.type == bfd_link_hash_defined) + { + relocation = (h->root.u.def.value + + h->root.u.def.section->output_section->vma + + h->root.u.def.section->output_offset); + } + else + { + const char *name; + + name = strings + GET_WORD (input_bfd, syms[r_index].e_strx); + if (! ((*finfo->info->callbacks->undefined_symbol) + (finfo->info, name, input_bfd, input_section, + r_addr))) + return false; + relocation = 0; + } + } + else + { + asection *section; + + section = aout_reloc_index_to_section (input_bfd, r_index); + relocation = (section->output_section->vma + + section->output_offset + - section->vma); + } + + BFD_ASSERT (r_type >= 0 + && r_type < TABLE_SIZE (howto_table_ext)); + + r = _bfd_final_link_relocate (howto_table_ext + r_type, + input_bfd, input_section, + contents, r_addr, relocation, + r_addend); + if (r != bfd_reloc_ok) + { + switch (r) + { + default: + case bfd_reloc_outofrange: + abort (); + case bfd_reloc_overflow: + if (! ((*finfo->info->callbacks->reloc_overflow) + (finfo->info, input_bfd, input_section, r_addr))) + return false; + break; + } + } + } + } + + return true; +} diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h index 1b44503..810e803 100644 --- a/bfd/bfd-in.h +++ b/bfd/bfd-in.h @@ -114,8 +114,8 @@ typedef unsigned HOST_64_BIT uint64_type; #if !defined (uint64_type) && defined (__GNUC__) #define uint64_type unsigned long long #define int64_type long long -#define uint64_typeLOW(x) (unsigned long)(((x) & 0xffffffff)) -#define uint64_typeHIGH(x) (unsigned long)(((x) >> 32) & 0xffffffff) +#define uint64_typeLOW(x) ((unsigned long)(((x) & 0xffffffff))) +#define uint64_typeHIGH(x) ((unsigned long)(((x) >> 32) & 0xffffffff)) #endif typedef unsigned HOST_64_BIT bfd_vma; @@ -123,9 +123,9 @@ typedef HOST_64_BIT bfd_signed_vma; typedef unsigned HOST_64_BIT bfd_size_type; typedef unsigned HOST_64_BIT symvalue; #define fprintf_vma(s,x) \ - fprintf(s,"%08x%08x", uint64_typeHIGH(x), uint64_typeLOW(x)) + fprintf(s,"%08lx%08lx", uint64_typeHIGH(x), uint64_typeLOW(x)) #define sprintf_vma(s,x) \ - sprintf(s,"%08x%08x", uint64_typeHIGH(x), uint64_typeLOW(x)) + sprintf(s,"%08lx%08lx", uint64_typeHIGH(x), uint64_typeLOW(x)) #else /* not BFD64 */ /* Represent a target address. Also used as a generic unsigned type @@ -286,41 +286,32 @@ typedef struct sec *sec_ptr; typedef struct stat stat_type; -/** Error handling */ - -typedef enum bfd_error { - no_error = 0, system_call_error, invalid_target, - wrong_format, invalid_operation, no_memory, - no_symbols, no_relocation_info, - no_more_archived_files, malformed_archive, - symbol_not_found, file_not_recognized, - file_ambiguously_recognized, no_contents, - bfd_error_nonrepresentable_section, - no_debug_section, bad_value, - - /* An input file is shorter than expected. */ - file_truncated, - - invalid_error_code} bfd_ec; +/* Error handling */ -extern bfd_ec bfd_error; -struct reloc_cache_entry; -struct bfd_seclet; - - -typedef struct bfd_error_vector { - void (* nonrepresentable_section ) PARAMS ((CONST bfd *CONST abfd, - CONST char *CONST name)); - void (* undefined_symbol) PARAMS ((CONST struct reloc_cache_entry *rel, - CONST struct bfd_seclet *sec)); - void (* reloc_value_truncated) PARAMS ((CONST struct - reloc_cache_entry *rel, - struct bfd_seclet *sec)); +typedef enum bfd_error +{ + no_error = 0, + system_call_error, + invalid_target, + wrong_format, + invalid_operation, + no_memory, + no_symbols, + no_relocation_info, + no_more_archived_files, + malformed_archive, + symbol_not_found, + file_not_recognized, + file_ambiguously_recognized, + no_contents, + bfd_error_nonrepresentable_section, + no_debug_section, + bad_value, + file_truncated, + invalid_error_code +} bfd_ec; - void (* reloc_dangerous) PARAMS ((CONST struct reloc_cache_entry *rel, - CONST struct bfd_seclet *sec)); - -} bfd_error_vector_type; +extern bfd_ec bfd_error; CONST char *bfd_errmsg PARAMS ((bfd_ec error_tag)); void bfd_perror PARAMS ((CONST char *message)); @@ -346,6 +337,86 @@ typedef struct _symbol_info CONST char *stab_name; } symbol_info; +/* Hash table routines. There is no way to free up a hash table. */ + +/* An element in the hash table. Most uses will actually use a larger + structure, and an instance of this will be the first field. */ + +struct bfd_hash_entry +{ + /* Next entry for this hash code. */ + struct bfd_hash_entry *next; + /* String being hashed. */ + const char *string; + /* Hash code. This is the full hash code, not the index into the + table. */ + unsigned long hash; +}; + +/* A hash table. */ + +struct bfd_hash_table +{ + /* The hash array. */ + struct bfd_hash_entry **table; + /* The number of slots in the hash table. */ + unsigned int size; + /* A function used to create new elements in the hash table. The + first entry is itself a pointer to an element. When this + function is first invoked, this pointer will be NULL. However, + having the pointer permits a hierarchy of method functions to be + built each of which calls the function in the superclass. Thus + each function should be written to allocate a new block of memory + only if the argument is NULL. */ + struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *, + struct bfd_hash_table *, + const char *)); + /* An obstack for this hash table. */ + struct obstack memory; +}; + +/* Initialize a hash table. */ +extern boolean bfd_hash_table_init + PARAMS ((struct bfd_hash_table *, + struct bfd_hash_entry *(*) (struct bfd_hash_entry *, + struct bfd_hash_table *, + const char *))); + +/* Initialize a hash table specifying a size. */ +extern boolean bfd_hash_table_init_n + PARAMS ((struct bfd_hash_table *, + struct bfd_hash_entry *(*) (struct bfd_hash_entry *, + struct bfd_hash_table *, + const char *), + unsigned int size)); + +/* Free up a hash table. */ +extern void bfd_hash_table_free PARAMS ((struct bfd_hash_table *)); + +/* Look up a string in a hash table. If CREATE is true, a new entry + will be created for this string if one does not already exist. The + COPY argument must be true if this routine should copy the string + into newly allocated memory when adding an entry. */ +extern struct bfd_hash_entry *bfd_hash_lookup + PARAMS ((struct bfd_hash_table *, const char *, boolean create, + boolean copy)); + +/* Base method for creating a hash table entry. */ +extern struct bfd_hash_entry *bfd_hash_newfunc + PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, + const char *)); + +/* Grab some space for a hash table entry. */ +extern PTR bfd_hash_allocate PARAMS ((struct bfd_hash_table *, size_t)); + +/* Traverse a hash table in a random order, calling a function on each + element. If the function returns false, the traversal stops. The + INFO argument is passed to the function. */ +extern void bfd_hash_traverse PARAMS ((struct bfd_hash_table *, + boolean (*) (struct bfd_hash_entry *, + PTR), + PTR info)); + /* The code that implements targets can initialize a jump table with this macro. It must name all its routines the same way (a prefix plus the standard routine suffix), or it must #define the routines that @@ -406,9 +477,11 @@ CAT(NAME,_bfd_debug_info_end),\ CAT(NAME,_bfd_debug_info_accumulate),\ CAT(NAME,_bfd_get_relocated_section_contents),\ CAT(NAME,_bfd_relax_section),\ -CAT(NAME,_bfd_seclet_link),\ CAT(NAME,_bfd_reloc_type_lookup),\ -CAT(NAME,_bfd_make_debug_symbol) +CAT(NAME,_bfd_make_debug_symbol),\ +CAT(NAME,_bfd_link_hash_table_create),\ +CAT(NAME,_bfd_link_add_symbols),\ +CAT(NAME,_bfd_final_link) #define COFF_SWAP_TABLE (PTR) &bfd_coff_std_swap_table diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 52a29b1..c5905a9 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -286,41 +286,32 @@ typedef struct sec *sec_ptr; typedef struct stat stat_type; -/** Error handling */ - -typedef enum bfd_error { - no_error = 0, system_call_error, invalid_target, - wrong_format, invalid_operation, no_memory, - no_symbols, no_relocation_info, - no_more_archived_files, malformed_archive, - symbol_not_found, file_not_recognized, - file_ambiguously_recognized, no_contents, - bfd_error_nonrepresentable_section, - no_debug_section, bad_value, - - /* An input file is shorter than expected. */ - file_truncated, - - invalid_error_code} bfd_ec; +/* Error handling */ -extern bfd_ec bfd_error; -struct reloc_cache_entry; -struct bfd_seclet; - - -typedef struct bfd_error_vector { - void (* nonrepresentable_section ) PARAMS ((CONST bfd *CONST abfd, - CONST char *CONST name)); - void (* undefined_symbol) PARAMS ((CONST struct reloc_cache_entry *rel, - CONST struct bfd_seclet *sec)); - void (* reloc_value_truncated) PARAMS ((CONST struct - reloc_cache_entry *rel, - struct bfd_seclet *sec)); +typedef enum bfd_error +{ + no_error = 0, + system_call_error, + invalid_target, + wrong_format, + invalid_operation, + no_memory, + no_symbols, + no_relocation_info, + no_more_archived_files, + malformed_archive, + symbol_not_found, + file_not_recognized, + file_ambiguously_recognized, + no_contents, + bfd_error_nonrepresentable_section, + no_debug_section, + bad_value, + file_truncated, + invalid_error_code +} bfd_ec; - void (* reloc_dangerous) PARAMS ((CONST struct reloc_cache_entry *rel, - CONST struct bfd_seclet *sec)); - -} bfd_error_vector_type; +extern bfd_ec bfd_error; CONST char *bfd_errmsg PARAMS ((bfd_ec error_tag)); void bfd_perror PARAMS ((CONST char *message)); @@ -346,6 +337,86 @@ typedef struct _symbol_info CONST char *stab_name; } symbol_info; +/* Hash table routines. There is no way to free up a hash table. */ + +/* An element in the hash table. Most uses will actually use a larger + structure, and an instance of this will be the first field. */ + +struct bfd_hash_entry +{ + /* Next entry for this hash code. */ + struct bfd_hash_entry *next; + /* String being hashed. */ + const char *string; + /* Hash code. This is the full hash code, not the index into the + table. */ + unsigned long hash; +}; + +/* A hash table. */ + +struct bfd_hash_table +{ + /* The hash array. */ + struct bfd_hash_entry **table; + /* The number of slots in the hash table. */ + unsigned int size; + /* A function used to create new elements in the hash table. The + first entry is itself a pointer to an element. When this + function is first invoked, this pointer will be NULL. However, + having the pointer permits a hierarchy of method functions to be + built each of which calls the function in the superclass. Thus + each function should be written to allocate a new block of memory + only if the argument is NULL. */ + struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *, + struct bfd_hash_table *, + const char *)); + /* An obstack for this hash table. */ + struct obstack memory; +}; + +/* Initialize a hash table. */ +extern boolean bfd_hash_table_init + PARAMS ((struct bfd_hash_table *, + struct bfd_hash_entry *(*) (struct bfd_hash_entry *, + struct bfd_hash_table *, + const char *))); + +/* Initialize a hash table specifying a size. */ +extern boolean bfd_hash_table_init_n + PARAMS ((struct bfd_hash_table *, + struct bfd_hash_entry *(*) (struct bfd_hash_entry *, + struct bfd_hash_table *, + const char *), + unsigned int size)); + +/* Free up a hash table. */ +extern void bfd_hash_table_free PARAMS ((struct bfd_hash_table *)); + +/* Look up a string in a hash table. If CREATE is true, a new entry + will be created for this string if one does not already exist. The + COPY argument must be true if this routine should copy the string + into newly allocated memory when adding an entry. */ +extern struct bfd_hash_entry *bfd_hash_lookup + PARAMS ((struct bfd_hash_table *, const char *, boolean create, + boolean copy)); + +/* Base method for creating a hash table entry. */ +extern struct bfd_hash_entry *bfd_hash_newfunc + PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, + const char *)); + +/* Grab some space for a hash table entry. */ +extern PTR bfd_hash_allocate PARAMS ((struct bfd_hash_table *, size_t)); + +/* Traverse a hash table in a random order, calling a function on each + element. If the function returns false, the traversal stops. The + INFO argument is passed to the function. */ +extern void bfd_hash_traverse PARAMS ((struct bfd_hash_table *, + boolean (*) (struct bfd_hash_entry *, + PTR), + PTR info)); + /* The code that implements targets can initialize a jump table with this macro. It must name all its routines the same way (a prefix plus the standard routine suffix), or it must #define the routines that @@ -406,9 +477,11 @@ CAT(NAME,_bfd_debug_info_end),\ CAT(NAME,_bfd_debug_info_accumulate),\ CAT(NAME,_bfd_get_relocated_section_contents),\ CAT(NAME,_bfd_relax_section),\ -CAT(NAME,_bfd_seclet_link),\ CAT(NAME,_bfd_reloc_type_lookup),\ -CAT(NAME,_bfd_make_debug_symbol) +CAT(NAME,_bfd_make_debug_symbol),\ +CAT(NAME,_bfd_link_hash_table_create),\ +CAT(NAME,_bfd_link_add_symbols),\ +CAT(NAME,_bfd_final_link) #define COFF_SWAP_TABLE (PTR) &bfd_coff_std_swap_table @@ -807,8 +880,8 @@ typedef struct sec struct symbol_cache_entry *symbol; struct symbol_cache_entry **symbol_ptr_ptr; - struct bfd_seclet *seclets_head; - struct bfd_seclet *seclets_tail; + struct bfd_link_order *link_order_head; + struct bfd_link_order *link_order_tail; } asection ; @@ -1014,7 +1087,8 @@ typedef enum bfd_reloc_status /* The relocation was performed, but may not be ok - presently generated only when linking i960 coff files with i960 b.out - symbols. */ + symbols. If this type is returned, the error_message argument + to bfd_perform_relocation will be set. */ bfd_reloc_dangerous } bfd_reloc_status_type; @@ -1068,16 +1142,8 @@ typedef struct reloc_howto_struct unsigned int rightshift; /* The size of the item to be relocated. This is *not* a - power-of-two measure. - 0 : one byte - 1 : two bytes - 2 : four bytes - 3 : nothing done (unless special_function is nonzero) - 4 : eight bytes - -2 : two bytes, result should be subtracted from the - data instead of added - There is currently no trivial way to extract a "number of - bytes" from a howto pointer. */ + power-of-two measure. To get the number of bytes operated + on by a type of relocation, use bfd_get_reloc_size. */ int size; /* The number of bits in the item to be relocated. This is used @@ -1108,7 +1174,8 @@ typedef struct reloc_howto_struct struct symbol_cache_entry *symbol, PTR data, asection *input_section, - bfd *output_bfd)); + bfd *output_bfd, + char **error_message)); /* The textual name of the relocation type. */ char *name; @@ -1156,6 +1223,9 @@ typedef struct reloc_howto_struct } \ } \ } +int +bfd_get_reloc_size PARAMS ((const reloc_howto_type *)); + typedef unsigned char bfd_byte; typedef struct relent_chain { @@ -1169,7 +1239,8 @@ bfd_perform_relocation arelent *reloc_entry, PTR data, asection *input_section, - bfd *output_bfd)); + bfd *output_bfd, + char **error_message)); typedef enum bfd_reloc_code_real { @@ -1625,6 +1696,13 @@ struct _bfd struct _bfd *archive_head; /* The first BFD in the archive. */ boolean has_armap; + /* A chain of BFD structures involved in a link. */ + struct _bfd *link_next; + + /* A field used by _bfd_generic_link_add_archive_symbols. This will + be used only for archive elements. */ + int archive_pass; + /* Used by the back end to hold private data. */ union @@ -1658,9 +1736,6 @@ struct _bfd /* Where all the allocated stuff under this BFD goes */ struct obstack memory; - - /* Is this really needed in addition to usrdata? */ - asymbol **ld_symbols; }; unsigned int @@ -1723,14 +1798,23 @@ bfd_scan_vma PARAMS ((CONST char *string, CONST char **end, int base)); #define bfd_set_arch_mach(abfd, arch, mach)\ BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach)) -#define bfd_get_relocated_section_contents(abfd, seclet, data, relocateable) \ - BFD_SEND (abfd, _bfd_get_relocated_section_contents, (abfd, seclet, data, relocateable)) +#define bfd_get_relocated_section_contents(abfd, link_info, link_order, data, relocateable, symbols) \ + BFD_SEND (abfd, _bfd_get_relocated_section_contents, \ + (abfd, link_info, link_order, data, relocateable, symbols)) -#define bfd_relax_section(abfd, section, symbols) \ - BFD_SEND (abfd, _bfd_relax_section, (abfd, section, symbols)) +#define bfd_relax_section(abfd, section, link_info, symbols) \ + BFD_SEND (abfd, _bfd_relax_section, \ + (abfd, section, link_info, symbols)) + +#define bfd_link_hash_table_create(abfd) \ + BFD_SEND (abfd, _bfd_link_hash_table_create, (abfd)) + +#define bfd_link_add_symbols(abfd, info) \ + BFD_SEND (abfd, _bfd_link_add_symbols, (abfd, info)) + +#define bfd_final_link(abfd, info) \ + BFD_SEND (abfd, _bfd_final_link, (abfd, info)) -#define bfd_seclet_link(abfd, data, relocateable) \ - BFD_SEND (abfd, _bfd_seclet_link, (abfd, data, relocateable)) symindex bfd_get_next_mapent PARAMS ((bfd *abfd, symindex previous, carsym **sym)); @@ -1769,6 +1853,10 @@ enum bfd_flavour { bfd_target_tekhex_flavour, bfd_target_srec_flavour, bfd_target_som_flavour}; + + /* Forward declaration. */ +typedef struct bfd_link_info _bfd_link_info; + typedef struct bfd_target { char *name; @@ -1856,14 +1944,13 @@ typedef struct bfd_target void (*_bfd_debug_info_accumulate) PARAMS ((bfd *, struct sec *)); bfd_byte * (*_bfd_get_relocated_section_contents) PARAMS ((bfd *, - struct bfd_seclet *, bfd_byte *data, - boolean relocateable)); + struct bfd_link_info *, struct bfd_link_order *, + bfd_byte *data, boolean relocateable, + struct symbol_cache_entry **)); boolean (*_bfd_relax_section) PARAMS ((bfd *, struct sec *, - struct symbol_cache_entry **)); + struct bfd_link_info *, struct symbol_cache_entry **)); - boolean (*_bfd_seclet_link) PARAMS ((bfd *, PTR data, - boolean relocateable)); /* See documentation on reloc types. */ CONST struct reloc_howto_struct * (*reloc_type_lookup) PARAMS ((bfd *abfd, @@ -1876,6 +1963,18 @@ typedef struct bfd_target bfd *abfd, void *ptr, unsigned long size)); + + /* Create a hash table for the linker. Different backends store + different information in this table. */ + struct bfd_link_hash_table *(*_bfd_link_hash_table_create) PARAMS ((bfd *)); + + /* Add symbols from this object file into the hash table. */ + boolean (*_bfd_link_add_symbols) PARAMS ((bfd *, struct bfd_link_info *)); + + /* Do a link based on the link_order structures attached to each + section of the BFD. */ + boolean (*_bfd_final_link) PARAMS ((bfd *, struct bfd_link_info *)); + PTR backend_data; } bfd_target; bfd_target * diff --git a/bfd/coff-a29k.c b/bfd/coff-a29k.c index ef41bdb..7161d40 100644 --- a/bfd/coff-a29k.c +++ b/bfd/coff-a29k.c @@ -28,6 +28,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "coff/internal.h" #include "libcoff.h" +static long get_symbol_value PARAMS ((asymbol *)); +static bfd_reloc_status_type a29k_reloc + PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); + #define INSERT_HWORD(WORD,HWORD) \ (((WORD) & 0xff00ff00) | (((HWORD) & 0xff00) << 8) | ((HWORD)& 0xff)) #define EXTRACT_HWORD(WORD) \ @@ -36,9 +40,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ ((HWORD) & 0x8000 ? (HWORD)|0xffff0000 : (HWORD)) /* Provided the symbol, returns the value reffed */ -static long -get_symbol_value(symbol) -asymbol *symbol; +static long +get_symbol_value (symbol) + asymbol *symbol; { long relocation = 0; @@ -59,13 +63,15 @@ asymbol *symbol; /* this function is in charge of performing all the 29k relocations */ static bfd_reloc_status_type -DEFUN(a29k_reloc,(abfd, reloc_entry, symbol_in, data, input_section, output_bfd), - bfd *abfd AND - arelent *reloc_entry AND - asymbol *symbol_in AND - PTR data AND - asection *input_section AND - bfd *output_bfd) +a29k_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd, + error_message) + bfd *abfd; + arelent *reloc_entry; + asymbol *symbol_in; + PTR data; + asection *input_section; + bfd *output_bfd; + char **error_message; { /* the consth relocation comes in two parts, we have to remember the state between calls, in these variables */ @@ -103,9 +109,8 @@ DEFUN(a29k_reloc,(abfd, reloc_entry, symbol_in, data, input_section, output_bfd) if ((part1_consth_active) && (r_type != R_IHCONST)) { - fprintf(stderr,"Relocation problem : "); - fprintf(stderr,"Missing IHCONST in module %s\n",abfd->filename); part1_consth_active = false; + *error_message = (char *) "Missing IHCONST"; return(bfd_reloc_dangerous); } @@ -133,7 +138,7 @@ DEFUN(a29k_reloc,(abfd, reloc_entry, symbol_in, data, input_section, output_bfd) signed_value -= (input_section->output_section->vma + input_section->output_offset); if (signed_value>0x1ffff || signed_value<-0x20000) - return(bfd_reloc_outofrange); + return(bfd_reloc_overflow); } signed_value >>= 2; insn = INSERT_HWORD(insn, signed_value); @@ -159,9 +164,7 @@ DEFUN(a29k_reloc,(abfd, reloc_entry, symbol_in, data, input_section, output_bfd) /* consth, part 2 Now relocate the reference */ if (part1_consth_active == false) { - fprintf(stderr,"Relocation problem : "); - fprintf(stderr,"IHIHALF missing in module %s\n", - abfd->filename); + *error_message = (char *) "Missing IHIHALF"; return(bfd_reloc_dangerous); } /* sym_ptr_ptr = r_symndx, in coff_slurp_reloc_table() */ @@ -202,9 +205,7 @@ DEFUN(a29k_reloc,(abfd, reloc_entry, symbol_in, data, input_section, output_bfd) bfd_put_32(abfd, insn, hit_data); break; default: - fprintf(stderr,"Relocation problem : "); - fprintf(stderr,"Unrecognized reloc type %d, in module %s\n", - r_type,abfd->filename); + *error_message = "Unrecognized reloc"; return (bfd_reloc_dangerous); } diff --git a/bfd/coffgen.c b/bfd/coffgen.c index dcdf9e9..ebc596f 100644 --- a/bfd/coffgen.c +++ b/bfd/coffgen.c @@ -39,7 +39,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "sysdep.h" #include "libbfd.h" #include "coff/internal.h" -#include "seclet.h" #include "libcoff.h" static asection bfd_debug_section = { "*DEBUG*" }; @@ -67,6 +66,13 @@ DEFUN(make_a_section_from_file,(abfd, hdr, target_index), return_section = bfd_make_section(abfd, name); if (return_section == NULL) return_section = bfd_coff_make_section_hook (abfd, name); + + /* Handle several sections of the same name. For example, if an executable + has two .bss sections, GDB better be able to find both of them + (PR 3562). */ + if (return_section == NULL) + return_section = bfd_make_section_anyway (abfd, name); + if (return_section == NULL) return false; @@ -904,10 +910,7 @@ coff_section_symbol (abfd, name) combined_entry_type *csym; sym = sec->symbol; - if (coff_symbol_from (abfd, sym)) - csym = coff_symbol_from (abfd, sym)->native; - else - csym = 0; + csym = coff_symbol_from (abfd, sym)->native; /* Make sure back-end COFF stuff is there. */ if (csym == 0) { @@ -924,18 +927,16 @@ coff_section_symbol (abfd, name) csym[0].u.syment.n_sclass = C_STAT; csym[0].u.syment.n_numaux = 1; /* SF_SET_STATICS (sym); @@ ??? */ - if (sec) - { - csym[1].u.auxent.x_scn.x_scnlen = sec->_raw_size; - csym[1].u.auxent.x_scn.x_nreloc = sec->reloc_count; - csym[1].u.auxent.x_scn.x_nlinno = sec->lineno_count; - } - else + csym[1].u.auxent.x_scn.x_scnlen = sec->_raw_size; + csym[1].u.auxent.x_scn.x_nreloc = sec->reloc_count; + csym[1].u.auxent.x_scn.x_nlinno = sec->lineno_count; + + if (sec->output_section == NULL) { - csym[1].u.auxent.x_scn.x_scnlen = 0; - csym[1].u.auxent.x_scn.x_nreloc = 0; - csym[1].u.auxent.x_scn.x_nlinno = 0; + sec->output_section = sec; + sec->output_offset = 0; } + return sym; } @@ -1326,13 +1327,13 @@ coff_print_symbol (abfd, filep, symbol, how) fprintf (file,"[%3d]", combined - root); fprintf (file, - "(sc %2d)(fl 0x%02x)(ty %3x)(sc %3d) (nx %d) 0x%08x %s", + "(sc %2d)(fl 0x%02x)(ty %3x)(sc %3d) (nx %d) 0x%08lx %s", combined->u.syment.n_scnum, combined->u.syment.n_flags, combined->u.syment.n_type, combined->u.syment.n_sclass, combined->u.syment.n_numaux, - combined->u.syment.n_value, + (unsigned long) combined->u.syment.n_value, symbol->name); for (aux = 0; aux < combined->u.syment.n_numaux; aux++) @@ -1353,7 +1354,7 @@ coff_print_symbol (abfd, filep, symbol, how) break; default: - fprintf (file, "AUX lnno %d size 0x%x tagndx %d", + fprintf (file, "AUX lnno %d size 0x%x tagndx %ld", auxp->u.auxent.x_sym.x_misc.x_lnsz.x_lnno, auxp->u.auxent.x_sym.x_misc.x_lnsz.x_size, tagndx); @@ -1367,9 +1368,10 @@ coff_print_symbol (abfd, filep, symbol, how) l++; while (l->line_number) { - fprintf (file, "\n%4d : 0x%x", - l->line_number, - l->u.offset); + fprintf (file, "\n%4d : 0x%lx", + l->line_number, + ((unsigned long) + (l->u.offset + symbol->section->vma))); l++; } } diff --git a/bfd/ecoff.c b/bfd/ecoff.c index 840d425..101adbd 100644 --- a/bfd/ecoff.c +++ b/bfd/ecoff.c @@ -21,8 +21,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "bfd.h" #include "sysdep.h" +#include "bfdlink.h" #include "libbfd.h" -#include "seclet.h" #include "aout/ar.h" #include "aout/ranlib.h" @@ -111,6 +111,8 @@ ecoff_mkobject_hook (abfd, filehdr, aouthdr) regsec = bfd_make_section (abfd, REGINFO); if (regsec == NULL) return NULL; + /* Tell the linker to leave this section completely alone. */ + regsec->flags = SEC_SHARED_LIBRARY; if (internal_a != (struct internal_aouthdr *) NULL) { @@ -1322,7 +1324,7 @@ ecoff_type_to_string (abfd, aux_ptr, indx, bigendian) case btStruct: /* Structure (Record) */ ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx); ecoff_emit_aggregate (abfd, p1, &rndx, - AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]), + (long) AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]), "struct"); indx++; /* skip aux words */ break; @@ -1334,7 +1336,7 @@ ecoff_type_to_string (abfd, aux_ptr, indx, bigendian) case btUnion: /* Union */ ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx); ecoff_emit_aggregate (abfd, p1, &rndx, - AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]), + (long) AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]), "union"); indx++; /* skip aux words */ break; @@ -1346,7 +1348,7 @@ ecoff_type_to_string (abfd, aux_ptr, indx, bigendian) case btEnum: /* Enumeration */ ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx); ecoff_emit_aggregate (abfd, p1, &rndx, - AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]), + (long) AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]), "enum"); indx++; /* skip aux words */ break; @@ -2040,8 +2042,9 @@ ecoff_find_nearest_line (abfd, /* We can't use the generic linking routines for ECOFF, because we have to handle all the debugging information. The generic link routine just works out the section contents and attaches a list of - symbols. We find each input BFD by looping over all the seclets. - We accumulate the debugging information for each input BFD. */ + symbols. We find each input BFD by looping over all the link_order + information. We accumulate the debugging information for each + input BFD. */ /* Get ECOFF EXTR information for an external symbol. This function is passed to bfd_ecoff_debug_externals. */ @@ -2084,6 +2087,14 @@ ecoff_get_extr (sym, esym) (*(ecoff_backend (input_bfd)->debug_swap.swap_ext_in)) (input_bfd, ecoff_sym_ptr->native, esym); + /* If the symbol was defined by the linker, then esym will be + undefined but sym will not be. Get a better class for such a + symbol. */ + if ((esym->asym.sc == scUndefined + || esym->asym.sc == scSUndefined) + && bfd_get_section (sym) != &bfd_und_section) + esym->asym.sc = scAbs; + /* Adjust the FDR index for the symbol by that used for the input BFD. */ esym->ifd += ecoff_data (input_bfd)->debug_info.ifdbase; @@ -2107,16 +2118,15 @@ ecoff_set_index (sym, indx) link. */ boolean -ecoff_bfd_seclet_link (abfd, data, relocateable) +ecoff_bfd_final_link (abfd, info) bfd *abfd; - PTR data; - boolean relocateable; + struct bfd_link_info *info; { const struct ecoff_backend_data * const backend = ecoff_backend (abfd); struct ecoff_debug_info * const debug = &ecoff_data (abfd)->debug_info; HDRR *symhdr; - register asection *o; - register bfd_seclet_type *p; + register bfd *input_bfd; + asection *o; /* We accumulate the debugging information counts in the symbolic header. */ @@ -2147,69 +2157,49 @@ ecoff_bfd_seclet_link (abfd, data, relocateable) debug->external_fdr = debug->external_fdr_end = NULL; debug->external_rfd = debug->external_rfd_end = NULL; - /* We need to accumulate the debugging symbols from each input BFD. - We do this by looking through all the seclets to gather all the - input BFD's. We use the output_has_begun field to avoid - including a particular input BFD more than once. */ - - /* Clear the output_has_begun fields. */ - for (o = abfd->sections; o != (asection *) NULL; o = o->next) - for (p = o->seclets_head; - p != (bfd_seclet_type *) NULL; - p = p->next) - if (p->type == bfd_indirect_seclet) - p->u.indirect.section->owner->output_has_begun = false; - - /* Add in each input BFD. */ - for (o = abfd->sections; o != (asection *) NULL; o = o->next) + /* We accumulate the debugging symbols from each input BFD. */ + for (input_bfd = info->input_bfds; + input_bfd != (bfd *) NULL; + input_bfd = input_bfd->link_next) { - for (p = o->seclets_head; - p != (bfd_seclet_type *) NULL; - p = p->next) - { - bfd *input_bfd; - boolean ret; + boolean ret; - if (p->type != bfd_indirect_seclet) - continue; + if (bfd_get_flavour (input_bfd) == bfd_target_ecoff_flavour) + ret = (bfd_ecoff_debug_accumulate + (abfd, debug, &backend->debug_swap, + input_bfd, &ecoff_data (input_bfd)->debug_info, + &ecoff_backend (input_bfd)->debug_swap, info->relocateable)); + else + ret = bfd_ecoff_debug_link_other (abfd, + debug, + &backend->debug_swap, + input_bfd); - input_bfd = p->u.indirect.section->owner; - if (input_bfd->output_has_begun) - continue; + if (! ret) + return false; - if (bfd_get_flavour (input_bfd) == bfd_target_ecoff_flavour) - ret = (bfd_ecoff_debug_accumulate - (abfd, debug, &backend->debug_swap, - input_bfd, &ecoff_data (input_bfd)->debug_info, - &ecoff_backend (input_bfd)->debug_swap, relocateable)); - else - ret = bfd_ecoff_debug_link_other (abfd, - debug, - &backend->debug_swap, - input_bfd); - - if (ret == false) - return false; - - /* Combine the register masks. */ - ecoff_data (abfd)->gprmask |= ecoff_data (input_bfd)->gprmask; - ecoff_data (abfd)->fprmask |= ecoff_data (input_bfd)->fprmask; - ecoff_data (abfd)->cprmask[0] |= ecoff_data (input_bfd)->cprmask[0]; - ecoff_data (abfd)->cprmask[1] |= ecoff_data (input_bfd)->cprmask[1]; - ecoff_data (abfd)->cprmask[2] |= ecoff_data (input_bfd)->cprmask[2]; - ecoff_data (abfd)->cprmask[3] |= ecoff_data (input_bfd)->cprmask[3]; - - input_bfd->output_has_begun = true; - } + /* Combine the register masks. */ + ecoff_data (abfd)->gprmask |= ecoff_data (input_bfd)->gprmask; + ecoff_data (abfd)->fprmask |= ecoff_data (input_bfd)->fprmask; + ecoff_data (abfd)->cprmask[0] |= ecoff_data (input_bfd)->cprmask[0]; + ecoff_data (abfd)->cprmask[1] |= ecoff_data (input_bfd)->cprmask[1]; + ecoff_data (abfd)->cprmask[2] |= ecoff_data (input_bfd)->cprmask[2]; + ecoff_data (abfd)->cprmask[3] |= ecoff_data (input_bfd)->cprmask[3]; + } - /* Don't bother to do any linking of .reginfo sections. */ + /* Don't let the generic routine link the .reginfo sections. */ + for (o = abfd->sections; o != (asection *) NULL; o = o->next) + { if (strcmp (o->name, REGINFO) == 0) - o->seclets_head = (bfd_seclet_type *) NULL; + { + o->link_order_head = (struct bfd_link_order *) NULL; + break; + } } /* Let the generic link routine handle writing out the section contents. */ - return bfd_generic_seclet_link (abfd, data, relocateable); + return _bfd_generic_final_link (abfd, info); } /* Set the architecture. The supported architecture is stored in the @@ -2279,7 +2269,7 @@ ecoff_get_section_contents (abfd, section, location, offset, count) size is reasonable. We don't have to worry about swapping or any such thing; the .reginfo section is defined such that the contents are an ecoff_reginfo structure as seen on the host. */ - memcpy (location, ((char *) &s) + offset, count); + memcpy (location, ((char *) &s) + offset, (size_t) count); return true; } @@ -2382,7 +2372,7 @@ ecoff_set_section_contents (abfd, section, location, offset, count) swapping or any such thing; the .reginfo section is defined such that the contents are an ecoff_reginfo structure as seen on the host. */ - memcpy (((char *) &s) + offset, location, count); + memcpy (((char *) &s) + offset, location, (size_t) count); tdata->gp = s.gp_value; tdata->gprmask = s.gprmask; @@ -3134,7 +3124,7 @@ ecoff_write_armap (abfd, elength, map, orl_count, stridx) != sizeof (struct ar_hdr)) return false; - bfd_h_put_32 (abfd, hashsize, temp); + bfd_h_put_32 (abfd, (bfd_vma) hashsize, temp); if (bfd_write (temp, 1, 4, abfd) != 4) return false; @@ -3178,8 +3168,10 @@ ecoff_write_armap (abfd, elength, map, orl_count, stridx) hash = srch; } - bfd_h_put_32 (abfd, map[i].namidx, (PTR) (hashtable + hash * 8)); - bfd_h_put_32 (abfd, firstreal, (PTR) (hashtable + hash * 8 + 4)); + bfd_h_put_32 (abfd, (bfd_vma) map[i].namidx, + (PTR) (hashtable + hash * 8)); + bfd_h_put_32 (abfd, (bfd_vma) firstreal, + (PTR) (hashtable + hash * 8 + 4)); } if (bfd_write (hashtable, 1, symdefsize, abfd) != symdefsize) @@ -3188,7 +3180,7 @@ ecoff_write_armap (abfd, elength, map, orl_count, stridx) bfd_release (abfd, hashtable); /* Now write the strings. */ - bfd_h_put_32 (abfd, stringsize, temp); + bfd_h_put_32 (abfd, (bfd_vma) stringsize, temp); if (bfd_write (temp, 1, 4, abfd) != 4) return false; for (i = 0; i < orl_count; i++) @@ -216,13 +216,15 @@ bfd_elf_generic_reloc (abfd, symbol, data, input_section, - output_bfd) + output_bfd, + error_message) bfd *abfd; arelent *reloc_entry; asymbol *symbol; PTR data; asection *input_section; bfd *output_bfd; + char **error_message; { if (output_bfd != (bfd *) NULL && (symbol->flags & BSF_SECTION_SYM) == 0 diff --git a/bfd/elf32-target.h b/bfd/elf32-target.h index ed1f417..bdbb4a5 100644 --- a/bfd/elf32-target.h +++ b/bfd/elf32-target.h @@ -47,11 +47,18 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define bfd_elf32_bfd_get_relocated_section_contents \ bfd_generic_get_relocated_section_contents #define bfd_elf32_bfd_relax_section bfd_generic_relax_section -#ifndef bfd_elf32_bfd_seclet_link -#define bfd_elf32_bfd_seclet_link bfd_generic_seclet_link -#endif #define bfd_elf32_bfd_make_debug_symbol \ ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr) +#ifndef bfd_elf32_bfd_link_hash_table_create +#define bfd_elf32_bfd_link_hash_table_create \ + _bfd_generic_link_hash_table_create +#endif +#ifndef bfd_elf32_bfd_link_add_symbols +#define bfd_elf32_bfd_link_add_symbols _bfd_generic_link_add_symbols +#endif +#ifndef bfd_elf32_bfd_final_link +#define bfd_elf32_bfd_final_link _bfd_generic_final_link +#endif #ifndef elf_info_to_howto_rel #define elf_info_to_howto_rel 0 diff --git a/bfd/elf64-target.h b/bfd/elf64-target.h index 8450179..7fdfa26 100644 --- a/bfd/elf64-target.h +++ b/bfd/elf64-target.h @@ -47,9 +47,18 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define bfd_elf64_bfd_get_relocated_section_contents \ bfd_generic_get_relocated_section_contents #define bfd_elf64_bfd_relax_section bfd_generic_relax_section -#define bfd_elf64_bfd_seclet_link bfd_generic_seclet_link #define bfd_elf64_bfd_make_debug_symbol \ ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr) +#ifndef bfd_elf64_bfd_link_hash_table_create +#define bfd_elf64_bfd_link_hash_table_create \ + _bfd_generic_link_hash_table_create +#endif +#ifndef bfd_elf64_bfd_link_add_symbols +#define bfd_elf64_bfd_link_add_symbols _bfd_generic_link_add_symbols +#endif +#ifndef bfd_elf64_bfd_final_link +#define bfd_elf64_bfd_final_link _bfd_generic_final_link +#endif #ifndef elf_info_to_howto_rel #define elf_info_to_howto_rel 0 diff --git a/bfd/hosts/std-host.h b/bfd/hosts/std-host.h index dc16af0..a0db98c 100644 --- a/bfd/hosts/std-host.h +++ b/bfd/hosts/std-host.h @@ -26,7 +26,6 @@ extern int fflush (); extern int write (); extern void abort (); extern int close (); -extern int qsort (); extern void exit (); extern int fseek (); extern int fclose (); @@ -70,7 +69,6 @@ extern char *strrchr(); extern int chmod(); extern int fstat(); extern int stat(); -extern int strtol(); extern char *strrchr(); extern char *ctime(); diff --git a/bfd/hppabsd-core.c b/bfd/hppabsd-core.c new file mode 100644 index 0000000..b6ecc30 --- /dev/null +++ b/bfd/hppabsd-core.c @@ -0,0 +1,334 @@ +/* BFD back-end for HPPA BSD core files. + Copyright 1993 Free Software Foundation, Inc. + + This file is part of BFD, the Binary File Descriptor library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + Written by the Center for Software Science at the University of Utah + and by Cygnus Support. + + The core file structure for the Utah 4.3BSD and OSF1 ports on the + PA is a mix between traditional cores and hpux cores -- just + different enough that supporting this format would tend to add + gross hacks to trad-core.c or hpux-core.c. So instead we keep any + gross hacks isolated to this file. */ + + +/* This file can only be compiled on systems which use HPPA-BSD style + core files. In the config/XXXXXX.mh file for such a system add + HDEFINES=-DHPPABSD_CORE + HDEPFILES=hppabsd-core.o + + I would not expect this to be of use to any other host/target, but + you never know. */ + +#include "bfd.h" +#include "sysdep.h" +#include "libbfd.h" + +#if defined (HOST_HPPABSD) + +#include "machine/vmparam.h" + +#include <stdio.h> +#include <sys/types.h> +#include <sys/param.h> +#include <sys/dir.h> +#include <signal.h> +#include <machine/reg.h> +#include <sys/user.h> /* After a.out.h */ +#include <sys/file.h> +#include <errno.h> + +static asection *make_bfd_asection PARAMS ((bfd *, CONST char *, + flagword, bfd_size_type, + bfd_vma, unsigned int)); +static asymbol *hppabsd_core_make_empty_symbol PARAMS ((bfd *)); +static bfd_target *hppabsd_core_core_file_p PARAMS ((bfd *)); +static char *hppabsd_core_core_file_failing_command PARAMS ((bfd *)); +static int hppabsd_core_core_file_failing_signal PARAMS ((bfd *)); +static boolean hppabsd_core_core_file_matches_executable_p + PARAMS ((bfd *, bfd *)); +static void swap_abort PARAMS ((void)); + +/* These are stored in the bfd's tdata. */ + +struct hppabsd_core_struct + { + int sig; + char cmd[MAXCOMLEN + 1]; + asection *data_section; + asection *stack_section; + asection *reg_section; + }; + +#define core_hdr(bfd) ((bfd)->tdata.hppabsd_core_data) +#define core_signal(bfd) (core_hdr(bfd)->sig) +#define core_command(bfd) (core_hdr(bfd)->cmd) +#define core_datasec(bfd) (core_hdr(bfd)->data_section) +#define core_stacksec(bfd) (core_hdr(bfd)->stack_section) +#define core_regsec(bfd) (core_hdr(bfd)->reg_section) + +static asection * +make_bfd_asection (abfd, name, flags, _raw_size, vma, alignment_power) + bfd *abfd; + CONST char *name; + flagword flags; + bfd_size_type _raw_size; + bfd_vma vma; + unsigned int alignment_power; +{ + asection *asect; + + asect = bfd_make_section (abfd, name); + if (!asect) + return NULL; + + asect->flags = flags; + asect->_raw_size = _raw_size; + asect->vma = vma; + asect->filepos = bfd_tell (abfd); + asect->alignment_power = alignment_power; + + return asect; +} + +static asymbol * +hppabsd_core_make_empty_symbol (abfd) + bfd *abfd; +{ + asymbol *new = (asymbol *) bfd_zalloc (abfd, sizeof (asymbol)); + new->the_bfd = abfd; + return new; +} + +static bfd_target * +hppabsd_core_core_file_p (abfd) + bfd *abfd; +{ + int val; + struct user u; + struct hppabsd_core_struct *coredata; + int clicksz; + + /* Try to read in the u-area. We will need information from this + to know how to grok the rest of the core structures. */ + val = bfd_read ((void *) &u, 1, sizeof u, abfd); + if (val != sizeof u) + { + bfd_error = wrong_format; + return NULL; + } + + /* Get the page size out of the u structure. This will be different + for PA 1.0 machines and PA 1.1 machines. Yuk! */ + clicksz = u.u_pcb.pcb_pgsz; + + /* Sanity checks. Make sure the size of the core file matches the + the size computed from information within the core itself. */ + { + FILE *stream = bfd_cache_lookup (abfd); + struct stat statbuf; + if (stream == NULL || fstat (fileno (stream), &statbuf) < 0) + { + bfd_error = system_call_error; + return NULL; + } + if (NBPG * (UPAGES + u.u_dsize + u.u_ssize) > statbuf.st_size) + { + bfd_error = file_truncated; + return NULL; + } + if (clicksz * (UPAGES + u.u_dsize + u.u_ssize) < statbuf.st_size) + { + /* The file is too big. Maybe it's not a core file + or we otherwise have bad values for u_dsize and u_ssize). */ + bfd_error = wrong_format; + return NULL; + } + } + + /* OK, we believe you. You're a core file (sure, sure). */ + + coredata = (struct hppabsd_core_struct *) + bfd_zalloc (abfd, sizeof (struct hppabsd_core_struct)); + + /* Make the core data and available via the tdata part of the BFD. */ + abfd->tdata.hppabsd_core_data = coredata; + + /* Create the sections. */ + core_stacksec (abfd) = make_bfd_asection (abfd, ".stack", + SEC_ALLOC + SEC_HAS_CONTENTS, + clicksz * u.u_ssize, + NBPG * (USIZE + KSTAKSIZE) + + clicksz * u.u_dsize, 2); + core_stacksec (abfd)->vma = USRSTACK; + + core_datasec (abfd) = make_bfd_asection (abfd, ".data", + SEC_ALLOC + SEC_LOAD + + SEC_HAS_CONTENTS, + clicksz * u.u_dsize, + NBPG * (USIZE + KSTAKSIZE), 2); + core_datasec (abfd)->vma = UDATASEG; + + core_regsec (abfd) = make_bfd_asection (abfd, ".reg", + SEC_ALLOC + SEC_HAS_CONTENTS, + KSTAKSIZE * NBPG, + NBPG * USIZE, 2); + core_regsec (abfd)->vma = 0; + + strncpy (core_command (abfd), u.u_comm, MAXCOMLEN + 1); + core_signal (abfd) = u.u_code; + return abfd->xvec; +} + +static char * +hppabsd_core_core_file_failing_command (abfd) + bfd *abfd; +{ + return core_command (abfd); +} + +/* ARGSUSED */ +static int +hppabsd_core_core_file_failing_signal (abfd) + bfd *abfd; +{ + return core_signal (abfd); +} + +/* ARGSUSED */ +static boolean +hppabsd_core_core_file_matches_executable_p (core_bfd, exec_bfd) + bfd *core_bfd, *exec_bfd; +{ + /* There's no way to know this... */ + return true; +} + + +/* No archive file support via this BFD */ +#define hppabsd_core_openr_next_archived_file \ + bfd_generic_openr_next_archived_file +#define hppabsd_core_generic_stat_arch_elt bfd_generic_stat_arch_elt +#define hppabsd_core_slurp_armap bfd_false +#define hppabsd_core_slurp_extended_name_table bfd_true +#define hppabsd_core_write_armap (boolean (*) PARAMS \ + ((bfd *arch, unsigned int elength, struct orl *map, \ + unsigned int orl_count, int stridx))) bfd_false +#define hppabsd_core_truncate_arname bfd_dont_truncate_arname + +#define hppabsd_core_close_and_cleanup bfd_generic_close_and_cleanup +#define hppabsd_core_set_section_contents (boolean (*) PARAMS \ + ((bfd *abfd, asection *section, PTR data, file_ptr offset, \ + bfd_size_type count))) bfd_false +#define hppabsd_core_get_section_contents \ + bfd_generic_get_section_contents +#define hppabsd_core_new_section_hook (boolean (*) PARAMS \ + ((bfd *, sec_ptr))) bfd_true +#define hppabsd_core_get_symtab_upper_bound bfd_0u +#define hppabsd_core_get_symtab (unsigned int (*) PARAMS \ + ((bfd *, struct symbol_cache_entry **))) bfd_0u +#define hppabsd_core_get_reloc_upper_bound (unsigned int (*) PARAMS \ + ((bfd *, sec_ptr))) bfd_0u +#define hppabsd_core_canonicalize_reloc (unsigned int (*) PARAMS \ + ((bfd *, sec_ptr, arelent **, struct symbol_cache_entry**))) bfd_0u +#define hppabsd_core_print_symbol (void (*) PARAMS \ + ((bfd *, PTR, struct symbol_cache_entry *, \ + bfd_print_symbol_type))) bfd_false +#define hppabsd_core_get_symbol_info (void (*) PARAMS \ + ((bfd *, struct symbol_cache_entry *, \ + symbol_info *))) bfd_false +#define hppabsd_core_get_lineno (alent * (*) PARAMS \ + ((bfd *, struct symbol_cache_entry *))) bfd_nullvoidptr +#define hppabsd_core_set_arch_mach (boolean (*) PARAMS \ + ((bfd *, enum bfd_architecture, unsigned long))) bfd_false +#define hppabsd_core_find_nearest_line (boolean (*) PARAMS \ + ((bfd *abfd, struct sec *section, \ + struct symbol_cache_entry **symbols,bfd_vma offset, \ + CONST char **file, CONST char **func, unsigned int *line))) bfd_false +#define hppabsd_core_sizeof_headers (int (*) PARAMS \ + ((bfd *, boolean))) bfd_0 + +#define hppabsd_core_bfd_debug_info_start bfd_void +#define hppabsd_core_bfd_debug_info_end bfd_void +#define hppabsd_core_bfd_debug_info_accumulate (void (*) PARAMS \ + ((bfd *, struct sec *))) bfd_void +#define hppabsd_core_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents +#define hppabsd_core_bfd_relax_section bfd_generic_relax_section +#define hppabsd_core_bfd_reloc_type_lookup \ + ((CONST struct reloc_howto_struct *(*) PARAMS ((bfd *, bfd_reloc_code_real_type))) bfd_nullvoidptr) +#define hppabsd_core_bfd_make_debug_symbol \ + ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr) +#define hppabsd_core_bfd_link_hash_table_create \ + ((struct bfd_link_hash_table *(*) PARAMS ((bfd *))) bfd_nullvoidptr) +#define hppabsd_core_bfd_link_add_symbols \ + ((boolean (*) PARAMS ((bfd *, struct bfd_link_info *))) bfd_false) +#define hppabsd_core_bfd_final_link \ + ((boolean (*) PARAMS ((bfd *, struct bfd_link_info *))) bfd_false) + +/* If somebody calls any byte-swapping routines, shoot them. */ +static void +swap_abort () +{ + /* This way doesn't require any declaration for ANSI to fuck up. */ + abort (); +} + +#define NO_GET ((bfd_vma (*) PARAMS (( bfd_byte *))) swap_abort ) +#define NO_PUT ((void (*) PARAMS ((bfd_vma, bfd_byte *))) swap_abort ) +#define NO_SIGNED_GET ((bfd_signed_vma (*) PARAMS ((bfd_byte *))) swap_abort ) + +bfd_target hppabsd_core_vec = + { + "hppabsd-core", + bfd_target_unknown_flavour, + true, /* target byte order */ + true, /* target headers byte order */ + (HAS_RELOC | EXEC_P | /* object flags */ + HAS_LINENO | HAS_DEBUG | + HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED), + (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ + 0, /* symbol prefix */ + ' ', /* ar_pad_char */ + 16, /* ar_max_namelen */ + 3, /* minimum alignment power */ + NO_GET, NO_SIGNED_GET, NO_PUT, /* 64 bit data */ + NO_GET, NO_SIGNED_GET, NO_PUT, /* 32 bit data */ + NO_GET, NO_SIGNED_GET, NO_PUT, /* 16 bit data */ + NO_GET, NO_SIGNED_GET, NO_PUT, /* 64 bit hdrs */ + NO_GET, NO_SIGNED_GET, NO_PUT, /* 32 bit hdrs */ + NO_GET, NO_SIGNED_GET, NO_PUT, /* 16 bit hdrs */ + + { /* bfd_check_format */ + _bfd_dummy_target, /* unknown format */ + _bfd_dummy_target, /* object file */ + _bfd_dummy_target, /* archive */ + hppabsd_core_core_file_p /* a core file */ + }, + { /* bfd_set_format */ + bfd_false, bfd_false, + bfd_false, bfd_false + }, + { /* bfd_write_contents */ + bfd_false, bfd_false, + bfd_false, bfd_false + }, + + JUMP_TABLE(hppabsd_core), + (PTR) 0 /* backend_data */ +}; +#endif diff --git a/bfd/hpux-core.c b/bfd/hpux-core.c new file mode 100644 index 0000000..afda813 --- /dev/null +++ b/bfd/hpux-core.c @@ -0,0 +1,318 @@ +/* BFD back-end for HP/UX core files. + Copyright 1993 Free Software Foundation, Inc. + Written by Stu Grossman, Cygnus Support. + Converted to back-end form by Ian Lance Taylor, Cygnus SUpport + +This file is part of BFD, the Binary File Descriptor library. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* This file can only be compiled on systems which use HP/UX style + core files. In the config/XXXXXX.mh file for such a system add + HDEFINES=-DHPUX_CORE + HDEPFILES=hpux-core.o + */ + +#include "bfd.h" +#include "sysdep.h" +#include "libbfd.h" + +#if defined (HOST_HPPAHPUX) || defined (HOST_HP300HPUX) + +/* FIXME: sys/core.h doesn't exist for HPUX version 7. HPUX version + 5, 6, and 7 core files seem to be standard trad-core.c type core + files; can we just use trad-core.c in addition to this file? */ + +#include <sys/core.h> +#include <sys/utsname.h> + +#endif /* HOST_HPPAHPUX */ + +#ifdef HOST_HPPABSD + +/* Not a very swift place to put it, but that's where the BSD port + puts them. */ +#include "/hpux/usr/include/sys/core.h" + +#endif /* HOST_HPPABSD */ + +#include <stdio.h> +#include <sys/types.h> +#include <sys/param.h> +#include <sys/dir.h> +#include <signal.h> +#include <machine/reg.h> +#include <sys/user.h> /* After a.out.h */ +#include <sys/file.h> +#include <errno.h> + +/* These are stored in the bfd's tdata */ + +struct hpux_core_struct +{ + int sig; + char cmd[MAXCOMLEN + 1]; + asection *data_section; + asection *stack_section; + asection *reg_section; +}; + +#define core_hdr(bfd) ((bfd)->tdata.hpux_core_data) +#define core_signal(bfd) (core_hdr(bfd)->sig) +#define core_command(bfd) (core_hdr(bfd)->cmd) +#define core_datasec(bfd) (core_hdr(bfd)->data_section) +#define core_stacksec(bfd) (core_hdr(bfd)->stack_section) +#define core_regsec(bfd) (core_hdr(bfd)->reg_section) + +static asection * +make_bfd_asection (abfd, name, flags, _raw_size, vma, alignment_power) + bfd *abfd; + CONST char *name; + flagword flags; + bfd_size_type _raw_size; + bfd_vma vma; + unsigned int alignment_power; +{ + asection *asect; + + asect = bfd_make_section (abfd, name); + if (!asect) + return NULL; + + asect->flags = flags; + asect->_raw_size = _raw_size; + asect->vma = vma; + asect->filepos = bfd_tell (abfd); + asect->alignment_power = alignment_power; + + return asect; +} + +static asymbol * +hpux_core_make_empty_symbol (abfd) + bfd *abfd; +{ + asymbol *new = (asymbol *) bfd_zalloc (abfd, sizeof (asymbol)); + new->the_bfd = abfd; + return new; +} + +static bfd_target * +hpux_core_core_file_p (abfd) + bfd *abfd; +{ + core_hdr (abfd) = (struct hpux_core_struct *) + bfd_zalloc (abfd, sizeof (struct hpux_core_struct)); + if (!core_hdr (abfd)) + return NULL; + + while (1) + { + int val; + struct corehead core_header; + + val = bfd_read ((void *) &core_header, 1, sizeof core_header, abfd); + if (val <= 0) + break; + switch (core_header.type) + { + case CORE_KERNEL: + case CORE_FORMAT: + bfd_seek (abfd, core_header.len, SEEK_CUR); /* Just skip this */ + break; + case CORE_EXEC: + { + struct proc_exec proc_exec; + bfd_read ((void *) &proc_exec, 1, core_header.len, abfd); + strncpy (core_command (abfd), proc_exec.cmd, MAXCOMLEN + 1); + } + break; + case CORE_PROC: + { + struct proc_info proc_info; + core_regsec (abfd) = make_bfd_asection (abfd, ".reg", + SEC_ALLOC + SEC_HAS_CONTENTS, + core_header.len, + (int) &proc_info - (int) &proc_info.hw_regs, + 2); + bfd_read (&proc_info, 1, core_header.len, abfd); + core_signal (abfd) = proc_info.sig; + } + if (!core_regsec (abfd)) + return NULL; + break; + case CORE_DATA: + core_datasec (abfd) = make_bfd_asection (abfd, ".data", + SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS, + core_header.len, + core_header.addr, + 2); + if (!core_datasec (abfd)) + return NULL; + bfd_seek (abfd, core_header.len, SEEK_CUR); + break; + case CORE_STACK: + core_stacksec (abfd) = make_bfd_asection (abfd, ".stack", + SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS, + core_header.len, + core_header.addr, + 2); + if (!core_stacksec (abfd)) + return NULL; + bfd_seek (abfd, core_header.len, SEEK_CUR); + break; + default: + /* Falling into here is an error and should prevent this + target from matching. That way systems which use hpux + cores along with other formats can still work. */ + return 0; + } + } + + /* OK, we believe you. You're a core file (sure, sure). */ + + return abfd->xvec; +} + +static char * +hpux_core_core_file_failing_command (abfd) + bfd *abfd; +{ + return core_command (abfd); +} + +/* ARGSUSED */ +static int +hpux_core_core_file_failing_signal (abfd) + bfd *abfd; +{ + return core_signal (abfd); +} + +/* ARGSUSED */ +static boolean +hpux_core_core_file_matches_executable_p (core_bfd, exec_bfd) + bfd *core_bfd, *exec_bfd; +{ + return true; /* FIXME, We have no way of telling at this point */ +} + +/* No archive file support via this BFD */ +#define hpux_core_openr_next_archived_file bfd_generic_openr_next_archived_file +#define hpux_core_generic_stat_arch_elt bfd_generic_stat_arch_elt +#define hpux_core_slurp_armap bfd_false +#define hpux_core_slurp_extended_name_table bfd_true +#define hpux_core_write_armap (boolean (*) PARAMS \ + ((bfd *arch, unsigned int elength, struct orl *map, \ + unsigned int orl_count, int stridx))) bfd_false +#define hpux_core_truncate_arname bfd_dont_truncate_arname + +#define hpux_core_close_and_cleanup bfd_generic_close_and_cleanup +#define hpux_core_set_section_contents (boolean (*) PARAMS \ + ((bfd *abfd, asection *section, PTR data, file_ptr offset, \ + bfd_size_type count))) bfd_false +#define hpux_core_get_section_contents bfd_generic_get_section_contents +#define hpux_core_new_section_hook (boolean (*) PARAMS \ + ((bfd *, sec_ptr))) bfd_true +#define hpux_core_get_symtab_upper_bound bfd_0u +#define hpux_core_get_symtab (unsigned int (*) PARAMS \ + ((bfd *, struct symbol_cache_entry **))) bfd_0u +#define hpux_core_get_reloc_upper_bound (unsigned int (*) PARAMS \ + ((bfd *, sec_ptr))) bfd_0u +#define hpux_core_canonicalize_reloc (unsigned int (*) PARAMS \ + ((bfd *, sec_ptr, arelent **, struct symbol_cache_entry**))) bfd_0u +#define hpux_core_print_symbol (void (*) PARAMS \ + ((bfd *, PTR, struct symbol_cache_entry *, \ + bfd_print_symbol_type))) bfd_false +#define hpux_core_get_symbol_info (void (*) PARAMS \ + ((bfd *, struct symbol_cache_entry *, \ + symbol_info *))) bfd_false +#define hpux_core_get_lineno (alent * (*) PARAMS \ + ((bfd *, struct symbol_cache_entry *))) bfd_nullvoidptr +#define hpux_core_set_arch_mach (boolean (*) PARAMS \ + ((bfd *, enum bfd_architecture, unsigned long))) bfd_false +#define hpux_core_find_nearest_line (boolean (*) PARAMS \ + ((bfd *abfd, struct sec *section, \ + struct symbol_cache_entry **symbols,bfd_vma offset, \ + CONST char **file, CONST char **func, unsigned int *line))) bfd_false +#define hpux_core_sizeof_headers (int (*) PARAMS \ + ((bfd *, boolean))) bfd_0 + +#define hpux_core_bfd_debug_info_start bfd_void +#define hpux_core_bfd_debug_info_end bfd_void +#define hpux_core_bfd_debug_info_accumulate (void (*) PARAMS \ + ((bfd *, struct sec *))) bfd_void +#define hpux_core_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents +#define hpux_core_bfd_relax_section bfd_generic_relax_section +#define hpux_core_bfd_reloc_type_lookup \ + ((CONST struct reloc_howto_struct *(*) PARAMS ((bfd *, bfd_reloc_code_real_type))) bfd_nullvoidptr) +#define hpux_core_bfd_make_debug_symbol \ + ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr) +#define hpux_core_bfd_link_hash_table_create \ + ((struct bfd_link_hash_table *(*) PARAMS ((bfd *))) bfd_nullvoidptr) +#define hpux_core_bfd_link_add_symbols \ + ((boolean (*) PARAMS ((bfd *, struct bfd_link_info *))) bfd_false) +#define hpux_core_bfd_final_link \ + ((boolean (*) PARAMS ((bfd *, struct bfd_link_info *))) bfd_false) + +/* If somebody calls any byte-swapping routines, shoot them. */ +void +swap_abort() +{ + abort(); /* This way doesn't require any declaration for ANSI to fuck up */ +} +#define NO_GET ((bfd_vma (*) PARAMS (( bfd_byte *))) swap_abort ) +#define NO_PUT ((void (*) PARAMS ((bfd_vma, bfd_byte *))) swap_abort ) +#define NO_SIGNED_GET ((bfd_signed_vma (*) PARAMS ((bfd_byte *))) swap_abort ) + +bfd_target hpux_core_vec = + { + "hpux-core", + bfd_target_unknown_flavour, + true, /* target byte order */ + true, /* target headers byte order */ + (HAS_RELOC | EXEC_P | /* object flags */ + HAS_LINENO | HAS_DEBUG | + HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), + (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ + 0, /* symbol prefix */ + ' ', /* ar_pad_char */ + 16, /* ar_max_namelen */ + 3, /* minimum alignment power */ + NO_GET, NO_SIGNED_GET, NO_PUT, /* 64 bit data */ + NO_GET, NO_SIGNED_GET, NO_PUT, /* 32 bit data */ + NO_GET, NO_SIGNED_GET, NO_PUT, /* 16 bit data */ + NO_GET, NO_SIGNED_GET, NO_PUT, /* 64 bit hdrs */ + NO_GET, NO_SIGNED_GET, NO_PUT, /* 32 bit hdrs */ + NO_GET, NO_SIGNED_GET, NO_PUT, /* 16 bit hdrs */ + + { /* bfd_check_format */ + _bfd_dummy_target, /* unknown format */ + _bfd_dummy_target, /* object file */ + _bfd_dummy_target, /* archive */ + hpux_core_core_file_p /* a core file */ + }, + { /* bfd_set_format */ + bfd_false, bfd_false, + bfd_false, bfd_false + }, + { /* bfd_write_contents */ + bfd_false, bfd_false, + bfd_false, bfd_false + }, + + JUMP_TABLE(hpux_core), + (PTR) 0 /* backend_data */ +}; diff --git a/bfd/irix-core.c b/bfd/irix-core.c new file mode 100644 index 0000000..b0482a4 --- /dev/null +++ b/bfd/irix-core.c @@ -0,0 +1,292 @@ +/* BFD back-end for Irix core files. + Copyright 1993 Free Software Foundation, Inc. + Written by Stu Grossman, Cygnus Support. + Converted to back-end form by Ian Lance Taylor, Cygnus Support + +This file is part of BFD, the Binary File Descriptor library. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* This file can only be compiled on systems which use Irix style core + files (namely, Irix 4 and Irix 5, so far). In the config/XXXXXX.mh + file for such a system add + HDEFINES=-DIRIX_CORE + HDEPFILES=irix-core.o + */ + +#include "bfd.h" +#include "sysdep.h" +#include "libbfd.h" + +#ifdef IRIX_CORE + +#include <core.out.h> + +struct sgi_core_struct +{ + int sig; + char cmd[CORE_NAMESIZE]; +}; + +#define core_hdr(bfd) ((bfd)->tdata.sgi_core_data) +#define core_signal(bfd) (core_hdr(bfd)->sig) +#define core_command(bfd) (core_hdr(bfd)->cmd) + +static asection * +make_bfd_asection (abfd, name, flags, _raw_size, vma, filepos) + bfd *abfd; + CONST char *name; + flagword flags; + bfd_size_type _raw_size; + bfd_vma vma; + file_ptr filepos; +{ + asection *asect; + + asect = bfd_make_section_anyway (abfd, name); + if (!asect) + return NULL; + + asect->flags = flags; + asect->_raw_size = _raw_size; + asect->vma = vma; + asect->filepos = filepos; + asect->alignment_power = 4; + + return asect; +} + +static bfd_target * +irix_core_core_file_p (abfd) + bfd *abfd; +{ + int val; + int i; + char *secname; + struct coreout coreout; + struct idesc *idg, *idf, *ids; + + val = bfd_read ((PTR)&coreout, 1, sizeof coreout, abfd); + if (val != sizeof coreout) + return 0; + + if (coreout.c_magic != CORE_MAGIC + || coreout.c_version != CORE_VERSION1) + return 0; + + core_hdr (abfd) = (struct sgi_core_struct *) bfd_zalloc (abfd, sizeof (struct sgi_core_struct)); + if (!core_hdr (abfd)) + return NULL; + + strncpy (core_command (abfd), coreout.c_name, CORE_NAMESIZE); + core_signal (abfd) = coreout.c_sigcause; + + bfd_seek (abfd, coreout.c_vmapoffset, SEEK_SET); + + for (i = 0; i < coreout.c_nvmap; i++) + { + struct vmap vmap; + + val = bfd_read ((PTR)&vmap, 1, sizeof vmap, abfd); + if (val != sizeof vmap) + break; + + switch (vmap.v_type) + { + case VDATA: + secname = ".data"; + break; + case VSTACK: + secname = ".stack"; + break; +#ifdef VMAPFILE + case VMAPFILE: + secname = ".mapfile"; + break; +#endif + default: + continue; + } + + if (!make_bfd_asection (abfd, secname, + SEC_ALLOC+SEC_LOAD+SEC_HAS_CONTENTS, + vmap.v_len, + vmap.v_vaddr, + vmap.v_offset, + 2)) + return NULL; + } + + /* Make sure that the regs are contiguous within the core file. */ + + idg = &coreout.c_idesc[I_GPREGS]; + idf = &coreout.c_idesc[I_FPREGS]; + ids = &coreout.c_idesc[I_SPECREGS]; + + if (idg->i_offset + idg->i_len != idf->i_offset + || idf->i_offset + idf->i_len != ids->i_offset) + return 0; /* Can't deal with non-contig regs */ + + bfd_seek (abfd, idg->i_offset, SEEK_SET); + + make_bfd_asection (abfd, ".reg", + SEC_ALLOC+SEC_HAS_CONTENTS, + idg->i_len + idf->i_len + ids->i_len, + 0, + idg->i_offset); + + /* OK, we believe you. You're a core file (sure, sure). */ + + return abfd->xvec; +} + +static char * +irix_core_core_file_failing_command (abfd) + bfd *abfd; +{ + return core_command (abfd); +} + +static int +irix_core_core_file_failing_signal (abfd) + bfd *abfd; +{ + return core_signal (abfd); +} + +static boolean +irix_core_core_file_matches_executable_p (core_bfd, exec_bfd) + bfd *core_bfd, *exec_bfd; +{ + return true; /* XXX - FIXME */ +} + +static asymbol * +irix_core_make_empty_symbol (abfd) + bfd *abfd; +{ + asymbol *new = (asymbol *) bfd_zalloc (abfd, sizeof (asymbol)); + new->the_bfd = abfd; + return new; +} + +#define irix_core_openr_next_archived_file bfd_generic_openr_next_archived_file +#define irix_core_generic_stat_arch_elt bfd_generic_stat_arch_elt +#define irix_core_slurp_armap bfd_false +#define irix_core_slurp_extended_name_table bfd_true +#define irix_core_write_armap (boolean (*) PARAMS \ + ((bfd *arch, unsigned int elength, struct orl *map, \ + unsigned int orl_count, int stridx))) bfd_false +#define irix_core_truncate_arname bfd_dont_truncate_arname + +#define irix_core_close_and_cleanup bfd_generic_close_and_cleanup +#define irix_core_set_section_contents (boolean (*) PARAMS \ + ((bfd *abfd, asection *section, PTR data, file_ptr offset, \ + bfd_size_type count))) bfd_false +#define irix_core_get_section_contents bfd_generic_get_section_contents +#define irix_core_new_section_hook (boolean (*) PARAMS \ + ((bfd *, sec_ptr))) bfd_true +#define irix_core_get_symtab_upper_bound bfd_0u +#define irix_core_get_symtab (unsigned int (*) PARAMS \ + ((bfd *, struct symbol_cache_entry **))) bfd_0u +#define irix_core_get_reloc_upper_bound (unsigned int (*) PARAMS \ + ((bfd *, sec_ptr))) bfd_0u +#define irix_core_canonicalize_reloc (unsigned int (*) PARAMS \ + ((bfd *, sec_ptr, arelent **, struct symbol_cache_entry**))) bfd_0u +#define irix_core_print_symbol (void (*) PARAMS \ + ((bfd *, PTR, struct symbol_cache_entry *, \ + bfd_print_symbol_type))) bfd_false +#define irix_core_get_symbol_info (void (*) PARAMS \ + ((bfd *, struct symbol_cache_entry *, \ + symbol_info *))) bfd_false +#define irix_core_get_lineno (alent * (*) PARAMS \ + ((bfd *, struct symbol_cache_entry *))) bfd_nullvoidptr +#define irix_core_set_arch_mach (boolean (*) PARAMS \ + ((bfd *, enum bfd_architecture, unsigned long))) bfd_false +#define irix_core_find_nearest_line (boolean (*) PARAMS \ + ((bfd *abfd, struct sec *section, \ + struct symbol_cache_entry **symbols,bfd_vma offset, \ + CONST char **file, CONST char **func, unsigned int *line))) bfd_false +#define irix_core_sizeof_headers (int (*) PARAMS \ + ((bfd *, boolean))) bfd_0 + +#define irix_core_bfd_debug_info_start bfd_void +#define irix_core_bfd_debug_info_end bfd_void +#define irix_core_bfd_debug_info_accumulate (void (*) PARAMS \ + ((bfd *, struct sec *))) bfd_void +#define irix_core_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents +#define irix_core_bfd_relax_section bfd_generic_relax_section +#define irix_core_bfd_reloc_type_lookup \ + ((CONST struct reloc_howto_struct *(*) PARAMS ((bfd *, bfd_reloc_code_real_type))) bfd_nullvoidptr) +#define irix_core_bfd_make_debug_symbol \ + ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr) +#define irix_core_bfd_link_hash_table_create \ + ((struct bfd_link_hash_table *(*) PARAMS ((bfd *))) bfd_nullvoidptr) +#define irix_core_bfd_link_add_symbols \ + ((boolean (*) PARAMS ((bfd *, struct bfd_link_info *))) bfd_false) +#define irix_core_bfd_final_link \ + ((boolean (*) PARAMS ((bfd *, struct bfd_link_info *))) bfd_false) + +/* If somebody calls any byte-swapping routines, shoot them. */ +void +swap_abort() +{ + abort(); /* This way doesn't require any declaration for ANSI to fuck up */ +} +#define NO_GET ((bfd_vma (*) PARAMS (( bfd_byte *))) swap_abort ) +#define NO_PUT ((void (*) PARAMS ((bfd_vma, bfd_byte *))) swap_abort ) +#define NO_SIGNED_GET ((bfd_signed_vma (*) PARAMS ((bfd_byte *))) swap_abort ) + +bfd_target irix_core_vec = + { + "irix-core", + bfd_target_unknown_flavour, + true, /* target byte order */ + true, /* target headers byte order */ + (HAS_RELOC | EXEC_P | /* object flags */ + HAS_LINENO | HAS_DEBUG | + HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), + (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ + 0, /* symbol prefix */ + ' ', /* ar_pad_char */ + 16, /* ar_max_namelen */ + 3, /* minimum alignment power */ + NO_GET, NO_SIGNED_GET, NO_PUT, /* 64 bit data */ + NO_GET, NO_SIGNED_GET, NO_PUT, /* 32 bit data */ + NO_GET, NO_SIGNED_GET, NO_PUT, /* 16 bit data */ + NO_GET, NO_SIGNED_GET, NO_PUT, /* 64 bit hdrs */ + NO_GET, NO_SIGNED_GET, NO_PUT, /* 32 bit hdrs */ + NO_GET, NO_SIGNED_GET, NO_PUT, /* 16 bit hdrs */ + + { /* bfd_check_format */ + _bfd_dummy_target, /* unknown format */ + _bfd_dummy_target, /* object file */ + _bfd_dummy_target, /* archive */ + irix_core_core_file_p /* a core file */ + }, + { /* bfd_set_format */ + bfd_false, bfd_false, + bfd_false, bfd_false + }, + { /* bfd_write_contents */ + bfd_false, bfd_false, + bfd_false, bfd_false + }, + + JUMP_TABLE(irix_core), + (PTR) 0 /* backend_data */ +}; + +#endif /* IRIX_CORE */ diff --git a/bfd/libaout.h b/bfd/libaout.h index f063817..1f89385 100644 --- a/bfd/libaout.h +++ b/bfd/libaout.h @@ -26,7 +26,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ for a 32-bit architecture or a 64-bit architecture. */ #if ARCH_SIZE==64 #define GET_WORD bfd_h_get_64 -#define GET_SWORD (int64_type)GET_WORD +#define GET_SWORD bfd_h_get_signed_64 #define PUT_WORD bfd_h_put_64 #ifndef NAME #define NAME(x,y) CAT3(x,_64_,y) @@ -35,7 +35,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define BYTES_IN_WORD 8 #else /* ARCH_SIZE == 32 */ #define GET_WORD bfd_h_get_32 -#define GET_SWORD (int32_type)GET_WORD +#define GET_SWORD bfd_h_get_signed_32 #define PUT_WORD bfd_h_put_32 #ifndef NAME #define NAME(x,y) CAT3(x,_32_,y) @@ -111,6 +111,12 @@ struct internal_exec 3130292827262524232221201918171615141312111009080706050403020100 < FLAGS >< MACHINE TYPE >< MAGIC NUMBER > */ +/* Magic number for NetBSD is +<MSB > +3130292827262524232221201918171615141312111009080706050403020100 +< FLAGS >< >< MAGIC NUMBER > +*/ + enum machine_type { M_UNKNOWN = 0, M_68010 = 1, @@ -119,6 +125,8 @@ enum machine_type { /* skip a bunch so we don't run into any of suns numbers */ M_386 = 100, M_29K = 101, /* AMD 29000 */ + M_386_DYNIX = 102, /* Sequent running dynix */ + M_386_NETBSD = 134, /* NetBSD/386 binary */ M_MIPS1 = 151, /* MIPS R2000/R3000 binary */ M_MIPS2 = 152, /* MIPS R4000/R6000 binary */ M_HP200 = 200, /* HP 200 (68010) BSD binary */ @@ -128,24 +136,41 @@ enum machine_type { #define N_DYNAMIC(exec) ((exec).a_info & 0x8000000) -#define N_MAGIC(exec) ((exec).a_info & 0xffff) -#define N_MACHTYPE(exec) ((enum machine_type)(((exec).a_info >> 16) & 0xff)) -#define N_FLAGS(exec) (((exec).a_info >> 24) & 0xff) -#define N_SET_INFO(exec, magic, type, flags) \ +#ifndef N_MAGIC +# define N_MAGIC(exec) ((exec).a_info & 0xffff) +#endif + +#ifndef N_MACHTYPE +# define N_MACHTYPE(exec) ((enum machine_type)(((exec).a_info >> 16) & 0xff)) +#endif + +#ifndef N_FLAGS +# define N_FLAGS(exec) (((exec).a_info >> 24) & 0xff) +#endif + +#ifndef N_SET_INFO +# define N_SET_INFO(exec, magic, type, flags) \ ((exec).a_info = ((magic) & 0xffff) \ | (((int)(type) & 0xff) << 16) \ | (((flags) & 0xff) << 24)) +#endif -#define N_SET_MAGIC(exec, magic) \ +#ifndef N_SET_MAGIC +# define N_SET_MAGIC(exec, magic) \ ((exec).a_info = (((exec).a_info & 0xffff0000) | ((magic) & 0xffff))) +#endif -#define N_SET_MACHTYPE(exec, machtype) \ +#ifndef N_SET_MACHTYPE +# define N_SET_MACHTYPE(exec, machtype) \ ((exec).a_info = \ ((exec).a_info&0xff00ffff) | ((((int)(machtype))&0xff) << 16)) +#endif -#define N_SET_FLAGS(exec, flags) \ +#ifndef N_SET_FLAGS +# define N_SET_FLAGS(exec, flags) \ ((exec).a_info = \ ((exec).a_info&0x00ffffff) | (((flags) & 0xff) << 24)) +#endif typedef struct aout_symbol { asymbol symbol; @@ -197,6 +222,12 @@ struct aoutdata { z_magic, o_magic, n_magic } magic; + + /* The external symbol information. */ + struct external_nlist *external_syms; + bfd_size_type external_sym_count; + char *external_strings; + struct aout_link_hash_entry **sym_hashes; }; struct aout_data_struct { @@ -215,6 +246,10 @@ struct aout_data_struct { #define obj_reloc_entry_size(bfd) (adata(bfd).reloc_entry_size) #define obj_symbol_entry_size(bfd) (adata(bfd).symbol_entry_size) #define obj_aout_subformat(bfd) (adata(bfd).subformat) +#define obj_aout_external_syms(bfd) (adata(bfd).external_syms) +#define obj_aout_external_sym_count(bfd) (adata(bfd).external_sym_count) +#define obj_aout_external_strings(bfd) (adata(bfd).external_strings) +#define obj_aout_sym_hashes(bfd) (adata(bfd).sym_hashes) /* We take the address of the first element of an asymbol to ensure that the macro is only ever applied to an asymbol */ @@ -254,7 +289,7 @@ NAME(aout,make_empty_symbol) PARAMS ((bfd *abfd)); boolean NAME(aout,slurp_symbol_table) PARAMS ((bfd *abfd)); -void +boolean NAME(aout,write_syms) PARAMS ((bfd *abfd)); void @@ -314,6 +349,17 @@ void NAME(aout,swap_exec_header_out) PARAMS ((bfd *abfd, struct internal_exec *execp, struct external_exec *raw_bytes)); +struct bfd_link_hash_table * +NAME(aout,link_hash_table_create) PARAMS ((bfd *)); + +boolean +NAME(aout,link_add_symbols) PARAMS ((bfd *, struct bfd_link_info *)); + +boolean +NAME(aout,final_link) PARAMS ((bfd *, struct bfd_link_info *, + void (*) (bfd *, file_ptr *, file_ptr *, + file_ptr *))); + /* Prototypes for functions in stab-syms.c. */ CONST char * @@ -351,11 +397,12 @@ aout_stab_name PARAMS ((int code)); bfd_write ((PTR) &exec_bytes, 1, EXEC_BYTES_SIZE, abfd); \ /* Now write out reloc info, followed by syms and strings */ \ \ - if (bfd_get_symcount (abfd) != 0) \ + if (bfd_get_outsymbols (abfd) != (asymbol **) NULL \ + && bfd_get_symcount (abfd) != 0) \ { \ bfd_seek (abfd, (file_ptr)(N_SYMOFF(*execp)), SEEK_SET); \ \ - NAME(aout,write_syms)(abfd); \ + if (! NAME(aout,write_syms)(abfd)) return false; \ \ bfd_seek (abfd, (file_ptr)(N_TRELOFF(*execp)), SEEK_SET); \ \ diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h index 0f9a2cd..5ba73fe 100644 --- a/bfd/libbfd-in.h +++ b/bfd/libbfd-in.h @@ -19,6 +19,12 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* Use builtin alloca for gcc. */ +#ifdef __GNUC__ +#ifndef alloca +#define alloca __builtin_alloca +#endif +#endif /* Align an address upward to a boundary, expressed as a number of bytes. E.g. align to an 8-byte boundary with argument of 8. */ @@ -44,7 +50,8 @@ struct artdata { carsym *symdefs; /* the symdef entries */ symindex symdef_count; /* how many there are */ char *extended_names; /* clever intel extension */ - time_t armap_timestamp; /* Timestamp value written into armap. + /* when more compilers are standard C, this can be a time_t */ + long armap_timestamp; /* Timestamp value written into armap. This is used for BSD archives to check that the timestamp is recent enough for the BSD linker to not complain, @@ -88,6 +95,9 @@ int bfd_seek PARAMS ((bfd* CONST abfd, CONST file_ptr fp, CONST int direction)); long bfd_tell PARAMS ((bfd *abfd)); +int bfd_flush PARAMS ((bfd *abfd)); +int bfd_stat PARAMS ((bfd *abfd, struct stat *)); + bfd * _bfd_create_empty_archive_element_shell PARAMS ((bfd *obfd)); bfd * look_for_bfd_in_cache PARAMS ((bfd *arch_bfd, file_ptr index)); boolean _bfd_generic_mkarchive PARAMS ((bfd *abfd)); @@ -99,7 +109,7 @@ boolean bfd_slurp_bsd_armap_f2 PARAMS ((bfd *abfd)); #define bfd_slurp_coff_armap bfd_slurp_armap boolean _bfd_slurp_extended_name_table PARAMS ((bfd *abfd)); boolean _bfd_write_archive_contents PARAMS ((bfd *abfd)); -bfd * new_bfd PARAMS (()); +bfd * new_bfd PARAMS ((void)); #define DEFAULT_STRING_SPACE_SIZE 0x2000 boolean bfd_add_to_string_table PARAMS ((char **table, char *new_string, @@ -146,7 +156,60 @@ boolean bfd_generic_get_section_contents PARAMS ((bfd *abfd, sec_ptr section, boolean bfd_generic_set_section_contents PARAMS ((bfd *abfd, sec_ptr section, PTR location, file_ptr offset, bfd_size_type count)); - + +/* A routine to create entries for a bfd_link_hash_table. */ +extern struct bfd_hash_entry *_bfd_link_hash_newfunc + PARAMS ((struct bfd_hash_entry *entry, + struct bfd_hash_table *table, + const char *string)); + +/* Initialize a bfd_link_hash_table. */ +extern boolean _bfd_link_hash_table_init + PARAMS ((struct bfd_link_hash_table *, bfd *, + struct bfd_hash_entry *(*) (struct bfd_hash_entry *, + struct bfd_hash_table *, + const char *))); + +/* Generic link hash table creation routine. */ +extern struct bfd_link_hash_table *_bfd_generic_link_hash_table_create + PARAMS ((bfd *)); + +/* Generic add symbol routine. */ +extern boolean _bfd_generic_link_add_symbols + PARAMS ((bfd *, struct bfd_link_info *)); + +/* Generic archive add symbol routine. */ +extern boolean _bfd_generic_link_add_archive_symbols + PARAMS ((bfd *, struct bfd_link_info *, + boolean (*checkfn) (bfd *, struct bfd_link_info *, boolean *))); + +/* Forward declaration to avoid prototype errors. */ +typedef struct bfd_link_hash_entry _bfd_link_hash_entry; + +/* Generic routine to add a single symbol. */ +extern boolean _bfd_generic_link_add_one_symbol + PARAMS ((struct bfd_link_info *, bfd *, const char *name, flagword, + asection *, bfd_vma, const char *, boolean copy, + struct bfd_link_hash_entry **)); + +/* Generic link routine. */ +extern boolean _bfd_generic_final_link + PARAMS ((bfd *, struct bfd_link_info *)); + +/* Default link order processing routine. */ +extern boolean _bfd_default_link_order + PARAMS ((bfd *, struct bfd_link_info *, asection *, + struct bfd_link_order *)); + +/* Final link relocation routine. */ +extern bfd_reloc_status_type _bfd_final_link_relocate + PARAMS ((const reloc_howto_type *, bfd *, asection *, bfd_byte *, + bfd_vma address, bfd_vma value, bfd_vma addend)); + +/* Relocate a particular location by a howto and a value. */ +extern bfd_reloc_status_type _bfd_relocate_contents + PARAMS ((const reloc_howto_type *, bfd *, bfd_vma, bfd_byte *)); + /* Macros to tell if bfds are read or write enabled. Note that bfds open for read may be scribbled into if the fd passed @@ -183,5 +246,10 @@ extern bfd *bfd_last_cache; /* Generic routine for close_and_cleanup is really just bfd_true. */ #define bfd_generic_close_and_cleanup bfd_true +/* List of supported target vectors, and the default vector (if + default_vector[0] is NULL, there is no default). */ +extern bfd_target *target_vector[]; +extern bfd_target *default_vector[]; + /* And more follows */ diff --git a/bfd/libbfd.c b/bfd/libbfd.c index 74a28af..10e9a9d 100644 --- a/bfd/libbfd.c +++ b/bfd/libbfd.c @@ -1,5 +1,5 @@ /* Assorted BFD support routines, only used internally. - Copyright 1990, 1991, 1992 Free Software Foundation, Inc. + Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -310,7 +310,7 @@ DEFUN(bfd_seek,(abfd, position, direction), #ifdef FILE_OFFSET_IS_CHAR_INDEX if (abfd->format != bfd_archive && abfd->my_archive == 0) { -#ifndef NDEBUG +#if 0 /* Explanation for this code: I'm only about 95+% sure that the above conditions are sufficient and that all i/o calls are properly adjusting the `where' field. So this is sort of an `assert' @@ -461,7 +461,7 @@ DESCRIPTION .{* Byte swapping macros for user section data. *} . .#define bfd_put_8(abfd, val, ptr) \ -. (*((unsigned char *)(ptr)) = (unsigned char)val) +. (*((unsigned char *)(ptr)) = (unsigned char)(val)) .#define bfd_put_signed_8 \ . bfd_put_8 .#define bfd_get_8(abfd, ptr) \ diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 34f1968..e9b0560 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -19,6 +19,12 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* Use builtin alloca for gcc. */ +#ifdef __GNUC__ +#ifndef alloca +#define alloca __builtin_alloca +#endif +#endif /* Align an address upward to a boundary, expressed as a number of bytes. E.g. align to an 8-byte boundary with argument of 8. */ @@ -103,7 +109,7 @@ boolean bfd_slurp_bsd_armap_f2 PARAMS ((bfd *abfd)); #define bfd_slurp_coff_armap bfd_slurp_armap boolean _bfd_slurp_extended_name_table PARAMS ((bfd *abfd)); boolean _bfd_write_archive_contents PARAMS ((bfd *abfd)); -bfd * new_bfd PARAMS (()); +bfd * new_bfd PARAMS ((void)); #define DEFAULT_STRING_SPACE_SIZE 0x2000 boolean bfd_add_to_string_table PARAMS ((char **table, char *new_string, @@ -150,7 +156,60 @@ boolean bfd_generic_get_section_contents PARAMS ((bfd *abfd, sec_ptr section, boolean bfd_generic_set_section_contents PARAMS ((bfd *abfd, sec_ptr section, PTR location, file_ptr offset, bfd_size_type count)); - + +/* A routine to create entries for a bfd_link_hash_table. */ +extern struct bfd_hash_entry *_bfd_link_hash_newfunc + PARAMS ((struct bfd_hash_entry *entry, + struct bfd_hash_table *table, + const char *string)); + +/* Initialize a bfd_link_hash_table. */ +extern boolean _bfd_link_hash_table_init + PARAMS ((struct bfd_link_hash_table *, bfd *, + struct bfd_hash_entry *(*) (struct bfd_hash_entry *, + struct bfd_hash_table *, + const char *))); + +/* Generic link hash table creation routine. */ +extern struct bfd_link_hash_table *_bfd_generic_link_hash_table_create + PARAMS ((bfd *)); + +/* Generic add symbol routine. */ +extern boolean _bfd_generic_link_add_symbols + PARAMS ((bfd *, struct bfd_link_info *)); + +/* Generic archive add symbol routine. */ +extern boolean _bfd_generic_link_add_archive_symbols + PARAMS ((bfd *, struct bfd_link_info *, + boolean (*checkfn) (bfd *, struct bfd_link_info *, boolean *))); + +/* Forward declaration to avoid prototype errors. */ +typedef struct bfd_link_hash_entry _bfd_link_hash_entry; + +/* Generic routine to add a single symbol. */ +extern boolean _bfd_generic_link_add_one_symbol + PARAMS ((struct bfd_link_info *, bfd *, const char *name, flagword, + asection *, bfd_vma, const char *, boolean copy, + struct bfd_link_hash_entry **)); + +/* Generic link routine. */ +extern boolean _bfd_generic_final_link + PARAMS ((bfd *, struct bfd_link_info *)); + +/* Default link order processing routine. */ +extern boolean _bfd_default_link_order + PARAMS ((bfd *, struct bfd_link_info *, asection *, + struct bfd_link_order *)); + +/* Final link relocation routine. */ +extern bfd_reloc_status_type _bfd_final_link_relocate + PARAMS ((const reloc_howto_type *, bfd *, asection *, bfd_byte *, + bfd_vma address, bfd_vma value, bfd_vma addend)); + +/* Relocate a particular location by a howto and a value. */ +extern bfd_reloc_status_type _bfd_relocate_contents + PARAMS ((const reloc_howto_type *, bfd *, bfd_vma, bfd_byte *)); + /* Macros to tell if bfds are read or write enabled. Note that bfds open for read may be scribbled into if the fd passed @@ -187,6 +246,11 @@ extern bfd *bfd_last_cache; /* Generic routine for close_and_cleanup is really just bfd_true. */ #define bfd_generic_close_and_cleanup bfd_true +/* List of supported target vectors, and the default vector (if + default_vector[0] is NULL, there is no default). */ +extern bfd_target *target_vector[]; +extern bfd_target *default_vector[]; + /* And more follows */ void @@ -234,14 +298,17 @@ boolean bfd_generic_relax_section PARAMS ((bfd *abfd, asection *section, + struct bfd_link_info *, asymbol **symbols)); bfd_byte * bfd_generic_get_relocated_section_contents PARAMS ((bfd *abfd, - struct bfd_seclet *seclet, + struct bfd_link_info *link_info, + struct bfd_link_order *link_order, bfd_byte *data, - boolean relocateable)); + boolean relocateable, + asymbol **symbols)); boolean bfd_generic_seclet_link diff --git a/bfd/libelf.h b/bfd/libelf.h index 838df6c..311bb1f 100644 --- a/bfd/libelf.h +++ b/bfd/libelf.h @@ -241,7 +241,8 @@ extern bfd_reloc_status_type bfd_elf_generic_reloc PARAMS ((bfd *, asymbol *, PTR, asection *, - bfd *)); + bfd *, + char **)); extern boolean bfd_elf_mkobject PARAMS ((bfd *)); extern Elf_Internal_Shdr *bfd_elf_find_section PARAMS ((bfd *, char *)); diff --git a/bfd/osf-core.c b/bfd/osf-core.c new file mode 100644 index 0000000..c8c988c --- /dev/null +++ b/bfd/osf-core.c @@ -0,0 +1,298 @@ +/* BFD back-end for OSF/1 core files. + Copyright 1993 Free Software Foundation, Inc. + +This file is part of BFD, the Binary File Descriptor library. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* This file can only be compiled on systems which use OSF/1 style + core files. In the config/XXXXXX.mh file for such a system add + HDEFINES=-DOSF_CORE + HDEPFILES=osf-core.o + */ + +#include "bfd.h" +#include "sysdep.h" +#include "libbfd.h" + +#include <stdio.h> +#include <string.h> +#include <sys/user.h> +#include <sys/core.h> + +/* forward declarations */ + +static asection * +make_bfd_asection PARAMS ((bfd *, CONST char *, flagword, bfd_size_type, + bfd_vma, file_ptr)); +static asymbol * +osf_core_make_empty_symbol PARAMS ((bfd *)); +static bfd_target * +osf_core_core_file_p PARAMS ((bfd *)); +static char * +osf_core_core_file_failing_command PARAMS ((bfd *)); +static int +osf_core_core_file_failing_signal PARAMS ((bfd *)); +static boolean +osf_core_core_file_matches_executable_p PARAMS ((bfd *, bfd *)); +static void +swap_abort PARAMS ((void)); + +/* These are stored in the bfd's tdata */ + +struct osf_core_struct +{ + int sig; + char cmd[MAXCOMLEN + 1]; +}; + +#define core_hdr(bfd) ((bfd)->tdata.osf_core_data) +#define core_signal(bfd) (core_hdr(bfd)->sig) +#define core_command(bfd) (core_hdr(bfd)->cmd) + +static asection * +make_bfd_asection (abfd, name, flags, _raw_size, vma, filepos) + bfd *abfd; + CONST char *name; + flagword flags; + bfd_size_type _raw_size; + bfd_vma vma; + file_ptr filepos; +{ + asection *asect; + + asect = bfd_make_section (abfd, name); + if (!asect) + return NULL; + + asect->flags = flags; + asect->_raw_size = _raw_size; + asect->vma = vma; + asect->filepos = filepos; + asect->alignment_power = 8; + + return asect; +} + +static asymbol * +osf_core_make_empty_symbol (abfd) + bfd *abfd; +{ + asymbol *new = (asymbol *) bfd_zalloc (abfd, sizeof (asymbol)); + new->the_bfd = abfd; + return new; +} + +static bfd_target * +osf_core_core_file_p (abfd) + bfd *abfd; +{ + int val; + int i; + char *secname; + struct core_filehdr core_header; + int dseccnt = 0; + + val = bfd_read ((PTR)&core_header, 1, sizeof core_header, abfd); + if (val != sizeof core_header) + return NULL; + + if (strncmp (core_header.magic, "Core", 4) != 0) + return NULL; + + core_hdr (abfd) = (struct osf_core_struct *) + bfd_zalloc (abfd, sizeof (struct osf_core_struct)); + if (!core_hdr (abfd)) + return NULL; + + strncpy (core_command (abfd), core_header.name, MAXCOMLEN + 1); + core_signal (abfd) = core_header.signo; + + for (i = 0; i < core_header.nscns; i++) + { + struct core_scnhdr core_scnhdr; + + val = bfd_read ((PTR)&core_scnhdr, 1, sizeof core_scnhdr, abfd); + if (val != sizeof core_scnhdr) + break; + + /* Skip empty sections. */ + if (core_scnhdr.size == 0 || core_scnhdr.scnptr == 0) + continue; + + switch (core_scnhdr.scntype) + { + case SCNRGN: + /* OSF/1 has multiple data sections (data, bss and data/bss sections + for shared libraries), but bfd doesn't permit data sections with + the same name. Construct a unique section name. */ + secname = bfd_alloc (abfd, 40); + sprintf (secname, ".data%d", dseccnt++); + break; + case SCNSTACK: + secname = ".stack"; + break; + case SCNREGS: + secname = ".reg"; + break; + default: + fprintf (stderr, "Unhandled OSF/1 core file section type %d\n", + core_scnhdr.scntype); + continue; + } + + if (!make_bfd_asection (abfd, secname, + SEC_ALLOC+SEC_LOAD+SEC_HAS_CONTENTS, + (bfd_size_type) core_scnhdr.size, + (bfd_vma) core_scnhdr.vaddr, + (file_ptr) core_scnhdr.scnptr)) + return NULL; + } + + /* OK, we believe you. You're a core file (sure, sure). */ + + return abfd->xvec; +} + +static char * +osf_core_core_file_failing_command (abfd) + bfd *abfd; +{ + return core_command (abfd); +} + +/* ARGSUSED */ +static int +osf_core_core_file_failing_signal (abfd) + bfd *abfd; +{ + return core_signal (abfd); +} + +/* ARGSUSED */ +static boolean +osf_core_core_file_matches_executable_p (core_bfd, exec_bfd) + bfd *core_bfd, *exec_bfd; +{ + return true; /* FIXME, We have no way of telling at this point */ +} + +/* No archive file support via this BFD */ +#define osf_core_openr_next_archived_file bfd_generic_openr_next_archived_file +#define osf_core_generic_stat_arch_elt bfd_generic_stat_arch_elt +#define osf_core_slurp_armap bfd_false +#define osf_core_slurp_extended_name_table bfd_true +#define osf_core_write_armap (boolean (*) PARAMS \ + ((bfd *arch, unsigned int elength, struct orl *map, \ + unsigned int orl_count, int stridx))) bfd_false +#define osf_core_truncate_arname bfd_dont_truncate_arname + +#define osf_core_close_and_cleanup bfd_generic_close_and_cleanup +#define osf_core_set_section_contents (boolean (*) PARAMS \ + ((bfd *abfd, asection *section, PTR data, file_ptr offset, \ + bfd_size_type count))) bfd_false +#define osf_core_get_section_contents bfd_generic_get_section_contents +#define osf_core_new_section_hook (boolean (*) PARAMS \ + ((bfd *, sec_ptr))) bfd_true +#define osf_core_get_symtab_upper_bound bfd_0u +#define osf_core_get_symtab (unsigned int (*) PARAMS \ + ((bfd *, struct symbol_cache_entry **))) bfd_0u +#define osf_core_get_reloc_upper_bound (unsigned int (*) PARAMS \ + ((bfd *, sec_ptr))) bfd_0u +#define osf_core_canonicalize_reloc (unsigned int (*) PARAMS \ + ((bfd *, sec_ptr, arelent **, struct symbol_cache_entry**))) bfd_0u +#define osf_core_print_symbol (void (*) PARAMS \ + ((bfd *, PTR, struct symbol_cache_entry *, \ + bfd_print_symbol_type))) bfd_false +#define osf_core_get_symbol_info (void (*) PARAMS \ + ((bfd *, struct symbol_cache_entry *, \ + symbol_info *))) bfd_false +#define osf_core_get_lineno (alent * (*) PARAMS \ + ((bfd *, struct symbol_cache_entry *))) bfd_nullvoidptr +#define osf_core_set_arch_mach (boolean (*) PARAMS \ + ((bfd *, enum bfd_architecture, unsigned long))) bfd_false +#define osf_core_find_nearest_line (boolean (*) PARAMS \ + ((bfd *abfd, struct sec *section, \ + struct symbol_cache_entry **symbols,bfd_vma offset, \ + CONST char **file, CONST char **func, unsigned int *line))) bfd_false +#define osf_core_sizeof_headers (int (*) PARAMS \ + ((bfd *, boolean))) bfd_0 + +#define osf_core_bfd_debug_info_start bfd_void +#define osf_core_bfd_debug_info_end bfd_void +#define osf_core_bfd_debug_info_accumulate (void (*) PARAMS \ + ((bfd *, struct sec *))) bfd_void +#define osf_core_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents +#define osf_core_bfd_relax_section bfd_generic_relax_section +#define osf_core_bfd_reloc_type_lookup \ + ((CONST struct reloc_howto_struct *(*) PARAMS ((bfd *, bfd_reloc_code_real_type))) bfd_nullvoidptr) +#define osf_core_bfd_make_debug_symbol \ + ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr) +#define osf_core_bfd_link_hash_table_create \ + ((struct bfd_link_hash_table *(*) PARAMS ((bfd *))) bfd_nullvoidptr) +#define osf_core_bfd_link_add_symbols \ + ((boolean (*) PARAMS ((bfd *, struct bfd_link_info *))) bfd_false) +#define osf_core_bfd_final_link \ + ((boolean (*) PARAMS ((bfd *, struct bfd_link_info *))) bfd_false) + +/* If somebody calls any byte-swapping routines, shoot them. */ +static void +swap_abort() +{ + abort(); /* This way doesn't require any declaration for ANSI to fuck up */ +} +#define NO_GET ((bfd_vma (*) PARAMS (( bfd_byte *))) swap_abort ) +#define NO_PUT ((void (*) PARAMS ((bfd_vma, bfd_byte *))) swap_abort ) +#define NO_SIGNED_GET ((bfd_signed_vma (*) PARAMS ((bfd_byte *))) swap_abort ) + +bfd_target osf_core_vec = + { + "osf-core", + bfd_target_unknown_flavour, + true, /* target byte order */ + true, /* target headers byte order */ + (HAS_RELOC | EXEC_P | /* object flags */ + HAS_LINENO | HAS_DEBUG | + HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), + (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ + 0, /* symbol prefix */ + ' ', /* ar_pad_char */ + 16, /* ar_max_namelen */ + 3, /* minimum alignment power */ + NO_GET, NO_SIGNED_GET, NO_PUT, /* 64 bit data */ + NO_GET, NO_SIGNED_GET, NO_PUT, /* 32 bit data */ + NO_GET, NO_SIGNED_GET, NO_PUT, /* 16 bit data */ + NO_GET, NO_SIGNED_GET, NO_PUT, /* 64 bit hdrs */ + NO_GET, NO_SIGNED_GET, NO_PUT, /* 32 bit hdrs */ + NO_GET, NO_SIGNED_GET, NO_PUT, /* 16 bit hdrs */ + + { /* bfd_check_format */ + _bfd_dummy_target, /* unknown format */ + _bfd_dummy_target, /* object file */ + _bfd_dummy_target, /* archive */ + osf_core_core_file_p /* a core file */ + }, + { /* bfd_set_format */ + bfd_false, bfd_false, + bfd_false, bfd_false + }, + { /* bfd_write_contents */ + bfd_false, bfd_false, + bfd_false, bfd_false + }, + + JUMP_TABLE(osf_core), + (PTR) 0 /* backend_data */ +}; diff --git a/bfd/ptrace-core.c b/bfd/ptrace-core.c new file mode 100644 index 0000000..5b07ea1 --- /dev/null +++ b/bfd/ptrace-core.c @@ -0,0 +1,303 @@ +/* BFD backend for core files which use the ptrace_user structure + Copyright 1993 Free Software Foundation, Inc. + The structure of this file is based on trad-core.c written by John Gilmore + of Cygnus Support. + Modified to work with the ptrace_user structure by Kevin A. Buettner. + (Longterm it may be better to merge this file with trad-core.c) + +This file is part of BFD, the Binary File Descriptor library. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + To use this file on a particular host, configure the host with these + parameters in the config/h-HOST file: + + HDEFINES=-DPTRACE_CORE + HDEPFILES=ptrace-core.o + +*/ + +#ifdef PTRACE_CORE + +#include "bfd.h" +#include "sysdep.h" +#include "libbfd.h" + +#include <stdio.h> +#include <sys/types.h> +#include <sys/param.h> +#include <sys/dir.h> +#include <signal.h> +#include <errno.h> +#include <unistd.h> +#include <sys/ptrace.h> + + +struct trad_core_struct + { + asection *data_section; + asection *stack_section; + asection *reg_section; + struct ptrace_user u; + } *rawptr; + +#define core_upage(bfd) (&((bfd)->tdata.trad_core_data->u)) +#define core_datasec(bfd) ((bfd)->tdata.trad_core_data->data_section) +#define core_stacksec(bfd) ((bfd)->tdata.trad_core_data->stack_section) +#define core_regsec(bfd) ((bfd)->tdata.trad_core_data->reg_section) + +/* forward declarations */ + +bfd_target * ptrace_unix_core_file_p PARAMS ((bfd *abfd)); +char * ptrace_unix_core_file_failing_command PARAMS ((bfd *abfd)); +int ptrace_unix_core_file_failing_signal PARAMS ((bfd *abfd)); +boolean ptrace_unix_core_file_matches_executable_p + PARAMS ((bfd *core_bfd, bfd *exec_bfd)); + +/* ARGSUSED */ +bfd_target * +ptrace_unix_core_file_p (abfd) + bfd *abfd; + +{ + int val; + struct ptrace_user u; + + val = bfd_read ((void *)&u, 1, sizeof u, abfd); + if (val != sizeof u || u.pt_magic != _BCS_PTRACE_MAGIC + || u.pt_rev != _BCS_PTRACE_REV) + { + /* Too small to be a core file */ + bfd_error = wrong_format; + return 0; + } + + /* OK, we believe you. You're a core file (sure, sure). */ + + /* Allocate both the upage and the struct core_data at once, so + a single free() will free them both. */ + rawptr = (struct trad_core_struct *) + bfd_zalloc (abfd, sizeof (struct trad_core_struct)); + + if (rawptr == NULL) { + bfd_error = no_memory; + return 0; + } + + abfd->tdata.trad_core_data = rawptr; + + rawptr->u = u; /*Copy the uarea into the tdata part of the bfd */ + + /* Create the sections. This is raunchy, but bfd_close wants to free + them separately. */ + + core_stacksec(abfd) = (asection *) zalloc (sizeof (asection)); + if (core_stacksec (abfd) == NULL) { + loser: + bfd_error = no_memory; + free ((void *)rawptr); + return 0; + } + core_datasec (abfd) = (asection *) zalloc (sizeof (asection)); + if (core_datasec (abfd) == NULL) { + loser1: + free ((void *)core_stacksec (abfd)); + goto loser; + } + core_regsec (abfd) = (asection *) zalloc (sizeof (asection)); + if (core_regsec (abfd) == NULL) { + free ((void *)core_datasec (abfd)); + goto loser1; + } + + core_stacksec (abfd)->name = ".stack"; + core_datasec (abfd)->name = ".data"; + core_regsec (abfd)->name = ".reg"; + + /* FIXME: Need to worry about shared memory, library data, and library + text. I don't think that any of these things are supported on the + system on which I am developing this for though. */ + + + core_stacksec (abfd)->flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS; + core_datasec (abfd)->flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS; + core_regsec (abfd)->flags = SEC_ALLOC + SEC_HAS_CONTENTS; + + core_datasec (abfd)->_raw_size = u.pt_dsize; + core_stacksec (abfd)->_raw_size = u.pt_ssize; + core_regsec (abfd)->_raw_size = sizeof(u); + + core_datasec (abfd)->vma = u.pt_o_data_start; + core_stacksec (abfd)->vma = USRSTACK - u.pt_ssize; + core_regsec (abfd)->vma = 0 - sizeof(u); /* see trad-core.c */ + + core_datasec (abfd)->filepos = (int) u.pt_dataptr; + core_stacksec (abfd)->filepos = (int) (u.pt_dataptr + u.pt_dsize); + core_regsec (abfd)->filepos = 0; /* Register segment is ptrace_user */ + + /* Align to word at least */ + core_stacksec (abfd)->alignment_power = 2; + core_datasec (abfd)->alignment_power = 2; + core_regsec (abfd)->alignment_power = 2; + + abfd->sections = core_stacksec (abfd); + core_stacksec (abfd)->next = core_datasec (abfd); + core_datasec (abfd)->next = core_regsec (abfd); + abfd->section_count = 3; + + return abfd->xvec; +} + +char * +ptrace_unix_core_file_failing_command (abfd) + bfd *abfd; +{ + char *com = abfd->tdata.trad_core_data->u.pt_comm; + if (*com) + return com; + else + return 0; +} + +/* ARGSUSED */ +int +ptrace_unix_core_file_failing_signal (abfd) + bfd *abfd; +{ + return abfd->tdata.trad_core_data->u.pt_sigframe.sig_num; +} + +/* ARGSUSED */ +boolean +ptrace_unix_core_file_matches_executable_p (core_bfd, exec_bfd) + bfd *core_bfd, *exec_bfd; +{ + /* FIXME: Use pt_timdat field of the ptrace_user structure to match + the date of the executable */ + return true; +} + +/* No archive file support via this BFD */ +#define ptrace_unix_openr_next_archived_file bfd_generic_openr_next_archived_file +#define ptrace_unix_generic_stat_arch_elt bfd_generic_stat_arch_elt +#define ptrace_unix_slurp_armap bfd_false +#define ptrace_unix_slurp_extended_name_table bfd_true +#define ptrace_unix_write_armap (boolean (*) PARAMS \ + ((bfd *arch, unsigned int elength, struct orl *map, \ + unsigned int orl_count, int stridx))) bfd_false +#define ptrace_unix_truncate_arname bfd_dont_truncate_arname +#define aout_32_openr_next_archived_file bfd_generic_openr_next_archived_file + +#define ptrace_unix_close_and_cleanup bfd_generic_close_and_cleanup +#define ptrace_unix_set_section_contents (boolean (*) PARAMS \ + ((bfd *abfd, asection *section, PTR data, file_ptr offset, \ + bfd_size_type count))) bfd_false +#define ptrace_unix_get_section_contents bfd_generic_get_section_contents +#define ptrace_unix_new_section_hook (boolean (*) PARAMS \ + ((bfd *, sec_ptr))) bfd_true +#define ptrace_unix_get_symtab_upper_bound bfd_0u +#define ptrace_unix_get_symtab (unsigned int (*) PARAMS \ + ((bfd *, struct symbol_cache_entry **))) bfd_0u +#define ptrace_unix_get_reloc_upper_bound (unsigned int (*) PARAMS \ + ((bfd *, sec_ptr))) bfd_0u +#define ptrace_unix_canonicalize_reloc (unsigned int (*) PARAMS \ + ((bfd *, sec_ptr, arelent **, struct symbol_cache_entry**))) bfd_0u +#define ptrace_unix_make_empty_symbol (struct symbol_cache_entry * \ + (*) PARAMS ((bfd *))) bfd_false +#define ptrace_unix_print_symbol (void (*) PARAMS \ + ((bfd *, PTR, struct symbol_cache_entry *, \ + bfd_print_symbol_type))) bfd_false +#define ptrace_unix_get_symbol_info (void (*) PARAMS \ + ((bfd *, struct symbol_cache_entry *, \ + symbol_info *))) bfd_false +#define ptrace_unix_get_lineno (alent * (*) PARAMS \ + ((bfd *, struct symbol_cache_entry *))) bfd_nullvoidptr +#define ptrace_unix_set_arch_mach (boolean (*) PARAMS \ + ((bfd *, enum bfd_architecture, unsigned long))) bfd_false +#define ptrace_unix_find_nearest_line (boolean (*) PARAMS \ + ((bfd *abfd, struct sec *section, \ + struct symbol_cache_entry **symbols,bfd_vma offset, \ + CONST char **file, CONST char **func, unsigned int *line))) bfd_false +#define ptrace_unix_sizeof_headers (int (*) PARAMS \ + ((bfd *, boolean))) bfd_0 + +#define ptrace_unix_bfd_debug_info_start bfd_void +#define ptrace_unix_bfd_debug_info_end bfd_void +#define ptrace_unix_bfd_debug_info_accumulate (void (*) PARAMS \ + ((bfd *, struct sec *))) bfd_void +#define ptrace_unix_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents +#define ptrace_unix_bfd_relax_section bfd_generic_relax_section +#define ptrace_unix_bfd_reloc_type_lookup \ + ((CONST struct reloc_howto_struct *(*) PARAMS ((bfd *, bfd_reloc_code_real_type))) bfd_nullvoidptr) +#define ptrace_unix_bfd_make_debug_symbol \ + ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr) +#define ptrace_unix_bfd_link_hash_table_create \ + ((struct bfd_link_hash_table *(*) PARAMS ((bfd *))) bfd_nullvoidptr) +#define ptrace_unix_bfd_link_add_symbols \ + ((boolean (*) PARAMS ((bfd *, struct bfd_link_info *))) bfd_false) +#define ptrace_unix_bfd_final_link \ + ((boolean (*) PARAMS ((bfd *, struct bfd_link_info *))) bfd_false) + +/* If somebody calls any byte-swapping routines, shoot them. */ +void +swap_abort() +{ + abort(); /* This way doesn't require any declaration for ANSI to fuck up */ +} +#define NO_GET ((bfd_vma (*) PARAMS (( bfd_byte *))) swap_abort ) +#define NO_PUT ((void (*) PARAMS ((bfd_vma, bfd_byte *))) swap_abort ) +#define NO_SIGNED_GET ((bfd_signed_vma (*) PARAMS ((bfd_byte *))) swap_abort ) + +bfd_target ptrace_core_vec = + { + "trad-core", + bfd_target_unknown_flavour, + true, /* target byte order */ + true, /* target headers byte order */ + (HAS_RELOC | EXEC_P | /* object flags */ + HAS_LINENO | HAS_DEBUG | + HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), + (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ + 0, /* symbol prefix */ + ' ', /* ar_pad_char */ + 16, /* ar_max_namelen */ + 3, /* minimum alignment power */ + NO_GET, NO_SIGNED_GET, NO_PUT, /* 64 bit data */ + NO_GET, NO_SIGNED_GET, NO_PUT, /* 32 bit data */ + NO_GET, NO_SIGNED_GET, NO_PUT, /* 16 bit data */ + NO_GET, NO_SIGNED_GET, NO_PUT, /* 64 bit hdrs */ + NO_GET, NO_SIGNED_GET, NO_PUT, /* 32 bit hdrs */ + NO_GET, NO_SIGNED_GET, NO_PUT, /* 16 bit hdrs */ + + { /* bfd_check_format */ + _bfd_dummy_target, /* unknown format */ + _bfd_dummy_target, /* object file */ + _bfd_dummy_target, /* archive */ + ptrace_unix_core_file_p /* a core file */ + }, + { /* bfd_set_format */ + bfd_false, bfd_false, + bfd_false, bfd_false + }, + { /* bfd_write_contents */ + bfd_false, bfd_false, + bfd_false, bfd_false + }, + + JUMP_TABLE(ptrace_unix), + (PTR) 0 /* backend_data */ +}; + +#endif /* PTRACE_CORE */ diff --git a/bfd/reloc.c b/bfd/reloc.c index 0f05cbe..20dd050 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -43,8 +43,8 @@ SECTION */ #include "bfd.h" #include "sysdep.h" +#include "bfdlink.h" #include "libbfd.h" -#include "seclet.h" /* DOCDD INODE @@ -82,7 +82,8 @@ CODE_FRAGMENT . . {* The relocation was performed, but may not be ok - presently . generated only when linking i960 coff files with i960 b.out -. symbols. *} +. symbols. If this type is returned, the error_message argument +. to bfd_perform_relocation will be set. *} . bfd_reloc_dangerous . } . bfd_reloc_status_type; @@ -100,7 +101,7 @@ CODE_FRAGMENT . bfd_vma addend; . . {* Pointer to how to perform the required relocation *} -. CONST struct reloc_howto_struct *howto; +. const struct reloc_howto_struct *howto; . .} arelent; @@ -189,7 +190,7 @@ DESCRIPTION |offset type value |00000002 HVRT16 _foo+0x12340000 |00000006 LVRT16 _foo+0x12340000 - +| |00000000 5da05678 ; or.u r13,r0,0x5678 |00000004 1c4d5678 ; ld.b r2,r13,0x5678 |00000008 f400c001 ; jmp r1 @@ -214,7 +215,7 @@ DESCRIPTION | ret | restore - Both relocs contains a pointer to <<foo>>, and the offsets + Both relocs contain a pointer to <<foo>>, and the offsets contain junk. @@ -222,7 +223,7 @@ DESCRIPTION |offset type value |00000004 HI22 _foo+0x12345678 |00000008 LO10 _foo+0x12345678 - +| |00000000 9de3bf90 ; save %sp,-112,%sp |00000004 05000000 ; sethi %hi(_foo+0),%g2 |00000008 f048a000 ; ldsb [%g2+%lo(_foo+0)],%i0 @@ -296,16 +297,8 @@ CODE_FRAGMENT . unsigned int rightshift; . . {* The size of the item to be relocated. This is *not* a -. power-of-two measure. -. 0 : one byte -. 1 : two bytes -. 2 : four bytes -. 3 : nothing done (unless special_function is nonzero) -. 4 : eight bytes -. -2 : two bytes, result should be subtracted from the -. data instead of added -. There is currently no trivial way to extract a "number of -. bytes" from a howto pointer. *} +. power-of-two measure. To get the number of bytes operated +. on by a type of relocation, use bfd_get_reloc_size. *} . int size; . . {* The number of bits in the item to be relocated. This is used @@ -336,7 +329,8 @@ CODE_FRAGMENT . struct symbol_cache_entry *symbol, . PTR data, . asection *input_section, -. bfd *output_bfd)); +. bfd *output_bfd, +. char **error_message)); . . {* The textual name of the relocation type. *} . char *name; @@ -408,6 +402,33 @@ DESCRIPTION */ /* +FUNCTION + bfd_get_reloc_size + +SYNOPSIS + int bfd_get_reloc_size (const reloc_howto_type *); + +DESCRIPTION + For a reloc_howto_type that operates on a fixed number of bytes, + this returns the number of bytes operated on. + */ + +int +bfd_get_reloc_size (howto) + const reloc_howto_type *howto; +{ + switch (howto->size) { + case 0: return 1; + case 1: return 2; + case 2: return 4; + case 3: return 0; + case 4: return 8; + case -2: return 2; + default: abort (); + } +} + +/* TYPEDEF arelent_chain @@ -434,50 +455,50 @@ SYNOPSIS bfd_reloc_status_type bfd_perform_relocation (bfd *abfd, - arelent *reloc_entry, - PTR data, - asection *input_section, - bfd *output_bfd); + arelent *reloc_entry, + PTR data, + asection *input_section, + bfd *output_bfd, + char **error_message); DESCRIPTION - If @var{output_bfd} is supplied to this function, the generated - image will be relocatable; the relocations are copied to the - output file after they have been changed to reflect the new - state of the world. There are two ways of reflecting the - results of partial linkage in an output file: by modifying the - output data in place, and by modifying the relocation record. - Some native formats (e.g., basic a.out and basic coff) have no - way of specifying an addend in the relocation type, so the - addend has to go in the output data. This is no big deal - since in these formats the output data slot will always be big - enough for the addend. Complex reloc types with addends were - invented to solve just this problem. + If @var{output_bfd} is supplied to this function, the + generated image will be relocatable; the relocations are + copied to the output file after they have been changed to + reflect the new state of the world. There are two ways of + reflecting the results of partial linkage in an output file: + by modifying the output data in place, and by modifying the + relocation record. Some native formats (e.g., basic a.out and + basic coff) have no way of specifying an addend in the + relocation type, so the addend has to go in the output data. + This is no big deal since in these formats the output data + slot will always be big enough for the addend. Complex reloc + types with addends were invented to solve just this problem. + The @var{error_message} argument is set to an error message if + this return @code{bfd_reloc_dangerous}. */ bfd_reloc_status_type -DEFUN(bfd_perform_relocation,(abfd, - reloc_entry, - data, - input_section, - output_bfd), - bfd *abfd AND - arelent *reloc_entry AND - PTR data AND - asection *input_section AND - bfd *output_bfd) +bfd_perform_relocation (abfd, reloc_entry, data, input_section, output_bfd, + error_message) + bfd *abfd; + arelent *reloc_entry; + PTR data; + asection *input_section; + bfd *output_bfd; + char **error_message; { bfd_vma relocation; bfd_reloc_status_type flag = bfd_reloc_ok; bfd_size_type addr = reloc_entry->address ; bfd_vma output_base = 0; - reloc_howto_type *howto = reloc_entry->howto; - asection *reloc_target_output_section ; - + const reloc_howto_type *howto = reloc_entry->howto; + asection *reloc_target_output_section; asymbol *symbol; - symbol = *( reloc_entry->sym_ptr_ptr); + symbol = *(reloc_entry->sym_ptr_ptr); if ((symbol->section == &bfd_abs_section) && output_bfd != (bfd *)NULL) { @@ -500,7 +521,8 @@ DEFUN(bfd_perform_relocation,(abfd, { bfd_reloc_status_type cont; cont = howto->special_function (abfd, reloc_entry, symbol, data, - input_section, output_bfd); + input_section, output_bfd, + error_message); if (cont != bfd_reloc_continue) return cont; } @@ -891,7 +913,240 @@ space consuming. For each target: return flag; } +/* This relocation routine is used by some of the backend linkers. + They do not construct asymbol or arelent structures, so there is no + reason for them to use bfd_perform_relocation. Also, + bfd_perform_relocation is so hacked up it is easier to write a new + function than to try to deal with it. + + This routine does a final relocation. It should not be used when + generating relocateable output. + + FIXME: This routine ignores any special_function in the HOWTO, + since the existing special_function values have been written for + bfd_perform_relocation. + + HOWTO is the reloc howto information. + INPUT_BFD is the BFD which the reloc applies to. + INPUT_SECTION is the section which the reloc applies to. + CONTENTS is the contents of the section. + ADDRESS is the address of the reloc within INPUT_SECTION. + VALUE is the value of the symbol the reloc refers to. + ADDEND is the addend of the reloc. */ + +bfd_reloc_status_type +_bfd_final_link_relocate (howto, input_bfd, input_section, contents, address, + value, addend) + const reloc_howto_type *howto; + bfd *input_bfd; + asection *input_section; + bfd_byte *contents; + bfd_vma address; + bfd_vma value; + bfd_vma addend; +{ + bfd_vma relocation; + /* Sanity check the address. */ + if (address > input_section->_cooked_size) + return bfd_reloc_outofrange; + + /* This function assumes that we are dealing with a basic relocation + against a symbol. We want to compute the value of the symbol to + relocate to. This is just VALUE, the value of the symbol, plus + ADDEND, any addend associated with the reloc. */ + relocation = value + addend; + + /* If the relocation is PC relative, we want to set RELOCATION to + the distance between the symbol (currently in RELOCATION) and the + location we are relocating. Some targets (e.g., i386-aout) + arrange for the contents of the section to be the negative of the + offset of the location within the section; for such targets + pcrel_offset is false. Other targets (e.g., m88kbcs or ELF) + simply leave the contents of the section as zero; for such + targets pcrel_offset is true. If pcrel_offset is false we do not + need to subtract out the offset of the location within the + section (which is just ADDRESS). */ + if (howto->pc_relative) + { + relocation -= (input_section->output_section->vma + + input_section->output_offset); + if (howto->pcrel_offset) + relocation -= address; + } + + return _bfd_relocate_contents (howto, input_bfd, relocation, + contents + address); +} + +/* Relocate a given location using a given value and howto. */ + +bfd_reloc_status_type +_bfd_relocate_contents (howto, input_bfd, relocation, location) + const reloc_howto_type *howto; + bfd *input_bfd; + bfd_vma relocation; + bfd_byte *location; +{ + int size; + bfd_vma x; + boolean overflow; + + /* If the size is negative, negate RELOCATION. This isn't very + general. */ + if (howto->size < 0) + relocation = - relocation; + + /* Get the value we are going to relocate. */ + size = bfd_get_reloc_size (howto); + switch (size) + { + default: + case 0: + abort (); + case 1: + x = bfd_get_8 (input_bfd, location); + break; + case 2: + x = bfd_get_16 (input_bfd, location); + break; + case 4: + x = bfd_get_32 (input_bfd, location); + break; + case 8: +#ifdef BFD64 + x = bfd_get_64 (input_bfd, location); +#else + abort (); +#endif + break; + } + + /* Check for overflow. FIXME: We may drop bits during the addition + which we don't check for. We must either check at every single + operation, which would be tedious, or we must do the computations + in a type larger than bfd_vma, which would be inefficient. */ + overflow = false; + if (howto->complain_on_overflow != complain_overflow_dont) + { + bfd_vma check; + bfd_signed_vma signed_check; + bfd_vma add; + + if (howto->rightshift == 0) + { + check = relocation; + signed_check = (bfd_signed_vma) relocation; + } + else + { + /* Drop unwanted bits from the value we are relocating to. */ + check = relocation >> howto->rightshift; + + /* If this is a signed value, the rightshift just dropped + leading 1 bits (assuming twos complement). */ + if ((bfd_signed_vma) relocation >= 0) + signed_check = check; + else + signed_check = (check + | ((bfd_vma) -1 + &~ ((bfd_vma) -1 >> howto->rightshift))); + } + + /* Add in the value from the object file, shifted down so that + it is a straight number. */ + add = x & howto->src_mask; + if (howto->bitpos == 0) + { + check += add; + signed_check += add; + } + else + { + add >>= howto->bitpos; + check += add; + signed_check += (add + | ((bfd_vma) -1 + &~ ((bfd_vma) -1 >> howto->bitpos))); + } + + switch (howto->complain_on_overflow) + { + case complain_overflow_signed: + { + /* Assumes two's complement. */ + bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1; + bfd_signed_vma reloc_signed_min = ~ reloc_signed_max; + + if (signed_check > reloc_signed_max + || signed_check < reloc_signed_min) + overflow = true; + } + break; + case complain_overflow_unsigned: + { + /* Assumes two's complement. This expression avoids + overflow if howto->bitsize is the number of bits in + bfd_vma. */ + bfd_vma reloc_unsigned_max = + (((1 << (howto->bitsize - 1)) - 1) << 1) | 1; + + if (check > reloc_unsigned_max) + overflow = true; + } + break; + case complain_overflow_bitfield: + { + /* Assumes two's complement. This expression avoids + overflow if howto->bitsize is the number of bits in + bfd_vma. */ + bfd_vma reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1; + + if ((check &~ reloc_bits) != 0 + && (((bfd_vma) signed_check &~ reloc_bits) + != (-1 &~ reloc_bits))) + overflow = true; + } + break; + default: + abort (); + } + } + + /* Put RELOCATION in the right bits. */ + relocation >>= (bfd_vma) howto->rightshift; + relocation <<= (bfd_vma) howto->bitpos; + + /* Add RELOCATION to the right bits of X. */ + x = ((x &~ howto->dst_mask) + | (((x & howto->src_mask) + relocation) & howto->dst_mask)); + + /* Put the relocated value back in the object file. */ + switch (size) + { + default: + case 0: + abort (); + case 1: + bfd_put_8 (input_bfd, x, location); + break; + case 2: + bfd_put_16 (input_bfd, x, location); + break; + case 4: + bfd_put_32 (input_bfd, x, location); + break; + case 8: +#ifdef BFD64 + bfd_put_64 (input_bfd, x, location); +#else + abort (); +#endif + break; + } + + return overflow ? bfd_reloc_overflow : bfd_reloc_ok; +} /* DOCDD @@ -1147,18 +1402,18 @@ FUNCTION bfd_reloc_type_lookup SYNOPSIS - CONST struct reloc_howto_struct * + const struct reloc_howto_struct * bfd_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code); DESCRIPTION - Return a pointer to a howto struct which, when + Return a pointer to a howto structure which, when invoked, will perform the relocation @var{code} on data from the architecture noted. */ -CONST struct reloc_howto_struct * +const struct reloc_howto_struct * DEFUN(bfd_reloc_type_lookup,(abfd, code), bfd *abfd AND bfd_reloc_code_real_type code) @@ -1175,7 +1430,7 @@ INTERNAL_FUNCTION bfd_default_reloc_type_lookup SYNOPSIS - CONST struct reloc_howto_struct *bfd_default_reloc_type_lookup + const struct reloc_howto_struct *bfd_default_reloc_type_lookup (bfd *abfd AND bfd_reloc_code_real_type code); @@ -1185,7 +1440,7 @@ DESCRIPTION */ -CONST struct reloc_howto_struct * +const struct reloc_howto_struct * DEFUN(bfd_default_reloc_type_lookup, (abfd, code), bfd *abfd AND bfd_reloc_code_real_type code) @@ -1208,7 +1463,7 @@ DEFUN(bfd_default_reloc_type_lookup, (abfd, code), default: BFD_FAIL(); } - return (CONST struct reloc_howto_struct *)NULL; + return (const struct reloc_howto_struct *)NULL; } @@ -1220,6 +1475,7 @@ SYNOPSIS boolean bfd_generic_relax_section (bfd *abfd, asection *section, + struct bfd_link_info *, asymbol **symbols); DESCRIPTION @@ -1228,16 +1484,14 @@ DESCRIPTION */ boolean -DEFUN(bfd_generic_relax_section,(abfd, section, symbols), - bfd *abfd AND - asection *section AND - asymbol **symbols) +bfd_generic_relax_section (abfd, section, link_info, symbols) + bfd *abfd; + asection *section; + struct bfd_link_info *link_info; + asymbol **symbols; { - return false; - } - /* INTERNAL_FUNCTION @@ -1246,9 +1500,11 @@ INTERNAL_FUNCTION SYNOPSIS bfd_byte * bfd_generic_get_relocated_section_contents (bfd *abfd, - struct bfd_seclet *seclet, + struct bfd_link_info *link_info, + struct bfd_link_order *link_order, bfd_byte *data, - boolean relocateable); + boolean relocateable, + asymbol **symbols); DESCRIPTION Provides default handling of relocation effort for back ends @@ -1257,20 +1513,18 @@ DESCRIPTION */ bfd_byte * -DEFUN(bfd_generic_get_relocated_section_contents,(abfd, - seclet, - data, - relocateable), - bfd *abfd AND - struct bfd_seclet *seclet AND - bfd_byte *data AND - boolean relocateable) +bfd_generic_get_relocated_section_contents (abfd, link_info, link_order, data, + relocateable, symbols) + bfd *abfd; + struct bfd_link_info *link_info; + struct bfd_link_order *link_order; + bfd_byte *data; + boolean relocateable; + asymbol **symbols; { - extern bfd_error_vector_type bfd_error_vector; - /* Get enough memory to hold the stuff */ - bfd *input_bfd = seclet->u.indirect.section->owner; - asection *input_section = seclet->u.indirect.section; + bfd *input_bfd = link_order->u.indirect.section->owner; + asection *input_section = link_order->u.indirect.section; @@ -1292,18 +1546,20 @@ DEFUN(bfd_generic_get_relocated_section_contents,(abfd, if (bfd_canonicalize_reloc(input_bfd, input_section, reloc_vector, - seclet->u.indirect.symbols) ) + symbols) ) { arelent **parent; for (parent = reloc_vector; * parent != (arelent *)NULL; parent++) { + char *error_message = (char *) NULL; bfd_reloc_status_type r= bfd_perform_relocation(input_bfd, *parent, data, input_section, - relocateable ? abfd : (bfd *) NULL); + relocateable ? abfd : (bfd *) NULL, + &error_message); if (relocateable) { @@ -1319,15 +1575,24 @@ DEFUN(bfd_generic_get_relocated_section_contents,(abfd, switch (r) { case bfd_reloc_undefined: - bfd_error_vector.undefined_symbol(*parent, seclet); + if (! ((*link_info->callbacks->undefined_symbol) + (link_info, bfd_asymbol_name (*(*parent)->sym_ptr_ptr), + input_bfd, input_section, (*parent)->address))) + return NULL; break; case bfd_reloc_dangerous: - bfd_error_vector.reloc_dangerous(*parent, seclet); + BFD_ASSERT (error_message != (char *) NULL); + if (! ((*link_info->callbacks->reloc_dangerous) + (link_info, error_message, input_bfd, input_section, + (*parent)->address))) + return NULL; break; - case bfd_reloc_outofrange: case bfd_reloc_overflow: - bfd_error_vector.reloc_value_truncated(*parent, seclet); + if (! ((*link_info->callbacks->reloc_overflow) + (link_info, input_bfd, input_section, (*parent)->address))) + return NULL; break; + case bfd_reloc_outofrange: default: abort(); break; diff --git a/bfd/section.c b/bfd/section.c index daccf2eb..374e2fa 100644 --- a/bfd/section.c +++ b/bfd/section.c @@ -112,23 +112,23 @@ SUBSECTION SUBSECTION - Seclets + Link orders - The data within a section is stored in a @dfn{seclet}. These - are much like the fixups in <<gas>>. The seclet abstraction - allows a section to grow and shrink within itself. + The data within a section is stored in a @dfn{link_order}. + These are much like the fixups in <<gas>>. The link_order + abstraction allows a section to grow and shrink within itself. - A seclet knows how big it is, and which is the next seclet and - where the raw data for it is; it also points to a list of - relocations which apply to it. + A link_order knows how big it is, and which is the next + link_order and where the raw data for it is; it also points to + a list of relocations which apply to it. - The seclet is used by the linker to perform relaxing on final - code. The compiler creates code which is as big as + The link_order is used by the linker to perform relaxing on + final code. The compiler creates code which is as big as necessary to make it work without relaxing, and the user can select whether to relax. Sometimes relaxing takes a lot of time. The linker runs around the relocations to see if any are attached to data which can be shrunk, if so it does it on - a seclet by seclet basis. + a link_order by link_order basis. */ @@ -361,8 +361,8 @@ CODE_FRAGMENT . struct symbol_cache_entry *symbol; . struct symbol_cache_entry **symbol_ptr_ptr; . -. struct bfd_seclet *seclets_head; -. struct bfd_seclet *seclets_tail; +. struct bfd_link_order *link_order_head; +. struct bfd_link_order *link_order_tail; .} asection ; . . @@ -279,7 +279,7 @@ unsigned int length) static int white(x) char x; { -return (x== ' ' || x == '\t' || x == '\n' || x == '\r'); + return (x== ' ' || x == '\t' || x == '\n' || x == '\r'); } static int skipwhite(src,abfd) @@ -309,12 +309,11 @@ DEFUN(srec_mkobject, (abfd), } -static void -DEFUN(pass_over,(abfd, func, symbolfunc, section), - bfd *abfd AND - void (*func)() AND - void (*symbolfunc)() AND - asection *section) +static void pass_over(abfd, func, symbolfunc, section) + bfd *abfd; + void (*func)(); + void (*symbolfunc)(); + asection *section; { unsigned int bytes_on_line; boolean eof = false; @@ -348,45 +347,46 @@ DEFUN(pass_over,(abfd, func, symbolfunc, section), case ' ': /* spaces - maybe just before a symbol */ - while (*src != '\n' && white(*src)) { - eof = skipwhite(src, abfd); - -{ - int val = 0; - int slen = 0; - char symbol[MAXCHUNK]; - - /* get the symbol part */ - while (!eof && !white(*src) && slen < MAXCHUNK) - { - symbol[slen++] = *src; - eof = (boolean)(bfd_read(src, 1, 1, abfd) != 1); - } - symbol[slen] = 0; - eof = skipwhite(src, abfd); - /* skip the $ for the hex value */ - if (*src == '$') - { - eof = (boolean)(bfd_read(src, 1, 1, abfd) != 1); - } - - /* Scan off the hex number */ - while (isxdigit(*src )) + while (*src != '\n' && *src != '\r' && white(*src)) { - val *= 16; - if (isdigit(*src)) - val += *src - '0'; - else if (isupper(*src)) { - val += *src - 'A' + 10; + eof = skipwhite(src, abfd); + + { + int val = 0; + int slen = 0; + char symbol[MAXCHUNK]; + + /* get the symbol part */ + while (!eof && !white(*src) && slen < MAXCHUNK) + { + symbol[slen++] = *src; + eof = (boolean)(bfd_read(src, 1, 1, abfd) != 1); + } + symbol[slen] = 0; + eof = skipwhite(src, abfd); + /* skip the $ for the hex value */ + if (*src == '$') + { + eof = (boolean)(bfd_read(src, 1, 1, abfd) != 1); + } + + /* Scan off the hex number */ + while (isxdigit(*src )) + { + val *= 16; + if (isdigit(*src)) + val += *src - '0'; + else if (isupper(*src)) { + val += *src - 'A' + 10; + } + else { + val += *src - 'a' + 10; + } + eof = (boolean)(bfd_read(src, 1, 1, abfd) != 1); + } + symbolfunc(abfd, symbol, slen, val); } - else { - val += *src - 'a' + 10; - } - eof = (boolean)(bfd_read(src, 1, 1, abfd) != 1); } - symbolfunc(abfd, symbol, slen, val); - } -} break; case 'S': src++; @@ -733,7 +733,7 @@ srec_write_symbols(abfd) if (len > 3 && s->name[len-2] == '.') { int l; - sprintf(buffer, "$$ %s\n\r", s->name); + sprintf(buffer, "$$ %s\r\n", s->name); l = strlen(buffer); bfd_write(buffer, l, 1, abfd); } @@ -749,13 +749,13 @@ srec_write_symbols(abfd) int l; char buf2[40], *p; - sprintf (buffer," %s $", s->name); - sprintf_vma (buf2, s->value + s->section->lma); + sprintf_vma (buf2, + s->value + s->section->output_section->lma + + s->section->output_offset); p = buf2; while (p[0] == '0' && p[1] != 0) p++; - strcat (buffer, p); - strcat (buffer, "\n\r"); + sprintf (buffer, " %s $%s\r\n", s->name, p); l = strlen(buffer); bfd_write(buffer, l, 1,abfd); } @@ -906,11 +906,13 @@ DEFUN(srec_print_symbol,(ignore_abfd, afile, symbol, how), #define srec_bfd_debug_info_accumulate (FOO(void, (*), (bfd *, asection *))) bfd_void #define srec_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents #define srec_bfd_relax_section bfd_generic_relax_section -#define srec_bfd_seclet_link bfd_generic_seclet_link #define srec_bfd_reloc_type_lookup \ ((CONST struct reloc_howto_struct *(*) PARAMS ((bfd *, bfd_reloc_code_real_type))) bfd_nullvoidptr) #define srec_bfd_make_debug_symbol \ ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr) +#define srec_bfd_link_hash_table_create _bfd_generic_link_hash_table_create +#define srec_bfd_link_add_symbols _bfd_generic_link_add_symbols +#define srec_bfd_final_link _bfd_generic_final_link bfd_target srec_vec = { @@ -920,19 +922,19 @@ bfd_target srec_vec = true, /* target headers byte order */ (HAS_RELOC | EXEC_P | /* object flags */ HAS_LINENO | HAS_DEBUG | - HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED), + HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), (SEC_CODE|SEC_DATA|SEC_ROM|SEC_HAS_CONTENTS |SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ 0, /* leading underscore */ ' ', /* ar_pad_char */ 16, /* ar_max_namelen */ 1, /* minimum alignment */ - _do_getb64, _do_getb_signed_64, _do_putb64, - _do_getb32, _do_getb_signed_32, _do_putb32, - _do_getb16, _do_getb_signed_16, _do_putb16, /* data */ - _do_getb64, _do_getb_signed_64, _do_putb64, - _do_getb32, _do_getb_signed_32, _do_putb32, - _do_getb16, _do_getb_signed_16, _do_putb16, /* hdrs */ + bfd_getb64, bfd_getb_signed_64, bfd_putb64, + bfd_getb32, bfd_getb_signed_32, bfd_putb32, + bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */ + bfd_getb64, bfd_getb_signed_64, bfd_putb64, + bfd_getb32, bfd_getb_signed_32, bfd_putb32, + bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */ { _bfd_dummy_target, @@ -965,19 +967,19 @@ bfd_target symbolsrec_vec = true, /* target headers byte order */ (HAS_RELOC | EXEC_P | /* object flags */ HAS_LINENO | HAS_DEBUG | - HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED), + HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), (SEC_CODE|SEC_DATA|SEC_ROM|SEC_HAS_CONTENTS |SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ 0, /* leading underscore */ ' ', /* ar_pad_char */ 16, /* ar_max_namelen */ 1, /* minimum alignment */ - _do_getb64, _do_getb_signed_64, _do_putb64, - _do_getb32, _do_getb_signed_32, _do_putb32, - _do_getb16, _do_getb_signed_16, _do_putb16, /* data */ - _do_getb64, _do_getb_signed_64, _do_putb64, - _do_getb32, _do_getb_signed_32, _do_putb32, - _do_getb16, _do_getb_signed_16, _do_putb16, /* hdrs */ + bfd_getb64, bfd_getb_signed_64, bfd_putb64, + bfd_getb32, bfd_getb_signed_32, bfd_putb32, + bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */ + bfd_getb64, bfd_getb_signed_64, bfd_putb64, + bfd_getb32, bfd_getb_signed_32, bfd_putb32, + bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */ { _bfd_dummy_target, diff --git a/bfd/targets.c b/bfd/targets.c index adfc530..8f10ef3 100644 --- a/bfd/targets.c +++ b/bfd/targets.c @@ -130,7 +130,10 @@ DESCRIPTION . bfd_target_tekhex_flavour, . bfd_target_srec_flavour, . bfd_target_som_flavour}; - +. +.{* Forward declaration. *} +.typedef struct bfd_link_info _bfd_link_info; +. .typedef struct bfd_target .{ @@ -290,15 +293,13 @@ Symbols and relocations. . void (*_bfd_debug_info_accumulate) PARAMS ((bfd *, struct sec *)); . . bfd_byte * (*_bfd_get_relocated_section_contents) PARAMS ((bfd *, -. struct bfd_seclet *, bfd_byte *data, -. boolean relocateable)); +. struct bfd_link_info *, struct bfd_link_order *, +. bfd_byte *data, boolean relocateable, +. struct symbol_cache_entry **)); . . boolean (*_bfd_relax_section) PARAMS ((bfd *, struct sec *, -. struct symbol_cache_entry **)); +. struct bfd_link_info *, struct symbol_cache_entry **)); . -. boolean (*_bfd_seclet_link) PARAMS ((bfd *, PTR data, -. boolean relocateable)); - . {* See documentation on reloc types. *} . CONST struct reloc_howto_struct * . (*reloc_type_lookup) PARAMS ((bfd *abfd, @@ -311,6 +312,18 @@ Symbols and relocations. . bfd *abfd, . void *ptr, . unsigned long size)); +. +. {* Create a hash table for the linker. Different backends store +. different information in this table. *} +. struct bfd_link_hash_table *(*_bfd_link_hash_table_create) PARAMS ((bfd *)); +. +. {* Add symbols from this object file into the hash table. *} +. boolean (*_bfd_link_add_symbols) PARAMS ((bfd *, struct bfd_link_info *)); +. +. {* Do a link based on the link_order structures attached to each +. section of the BFD. *} +. boolean (*_bfd_final_link) PARAMS ((bfd *, struct bfd_link_info *)); +. Data for use by back-end routines, which isn't generic enough to belong in this structure. @@ -376,6 +389,7 @@ extern bfd_target newsos3_vec; extern bfd_target nlm32_big_generic_vec; extern bfd_target nlm32_i386_vec; extern bfd_target nlm32_sparc_vec; +extern bfd_target nlm32_alpha_vec; extern bfd_target nlm32_little_generic_vec; extern bfd_target nlm64_big_generic_vec; extern bfd_target nlm64_little_generic_vec; diff --git a/bfd/trad-core.c b/bfd/trad-core.c index d3e5fdd..f059a88 100644 --- a/bfd/trad-core.c +++ b/bfd/trad-core.c @@ -80,6 +80,12 @@ trad_unix_core_file_p (abfd) int val; struct user u; +#ifdef TRAD_CORE_USER_OFFSET + /* If defined, this macro is the file position of the user struct. */ + if (bfd_seek (abfd, TRAD_CORE_USER_OFFSET, SEEK_SET) == 0) + return 0; +#endif + val = bfd_read ((void *)&u, 1, sizeof u, abfd); if (val != sizeof u) { @@ -116,6 +122,7 @@ trad_unix_core_file_p (abfd) bfd_error = file_truncated; return 0; } +#ifndef TRAD_CORE_ALLOW_ANY_EXTRA_SIZE if (NBPG * (UPAGES + u.u_dsize + u.u_ssize) #ifdef TRAD_CORE_EXTRA_SIZE_ALLOWED /* Some systems write the file too big. */ @@ -128,6 +135,7 @@ trad_unix_core_file_p (abfd) bfd_error = wrong_format; return 0; } +#endif } /* OK, we believe you. You're a core file (sure, sure). */ @@ -186,7 +194,13 @@ trad_unix_core_file_p (abfd) #else core_datasec (abfd)->vma = HOST_TEXT_START_ADDR + (NBPG * u.u_tsize); #endif + +#ifdef HOST_STACK_START_ADDR + core_stacksec (abfd)->vma = HOST_STACK_START_ADDR; +#else core_stacksec (abfd)->vma = HOST_STACK_END_ADDR - (NBPG * u.u_ssize); +#endif + /* This is tricky. As the "register section", we give them the entire upage and stack. u.u_ar0 points to where "register 0" is stored. There are two tricks with this, though. One is that the rest of the @@ -204,7 +218,11 @@ trad_unix_core_file_p (abfd) core_regsec (abfd)->vma = 0 - (int) u.u_ar0; core_datasec (abfd)->filepos = NBPG * UPAGES; +#ifdef TRAD_CORE_STACK_FILEPOS + core_stacksec (abfd)->filepos = TRAD_CORE_STACK_FILEPOS; +#else core_stacksec (abfd)->filepos = (NBPG * UPAGES) + NBPG * u.u_dsize; +#endif core_regsec (abfd)->filepos = 0; /* Register segment is the upage */ /* Align to word at least */ @@ -303,12 +321,16 @@ trad_unix_core_file_matches_executable_p (core_bfd, exec_bfd) ((bfd *, struct sec *))) bfd_void #define trad_unix_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents #define trad_unix_bfd_relax_section bfd_generic_relax_section -#define trad_unix_bfd_seclet_link \ - ((boolean (*) PARAMS ((bfd *, PTR, boolean))) bfd_false) #define trad_unix_bfd_reloc_type_lookup \ ((CONST struct reloc_howto_struct *(*) PARAMS ((bfd *, bfd_reloc_code_real_type))) bfd_nullvoidptr) #define trad_unix_bfd_make_debug_symbol \ ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr) +#define trad_unix_bfd_link_hash_table_create \ + ((struct bfd_link_hash_table *(*) PARAMS ((bfd *))) bfd_nullvoidptr) +#define trad_unix_bfd_link_add_symbols \ + ((boolean (*) PARAMS ((bfd *, struct bfd_link_info *))) bfd_false) +#define trad_unix_bfd_final_link \ + ((boolean (*) PARAMS ((bfd *, struct bfd_link_info *))) bfd_false) /* If somebody calls any byte-swapping routines, shoot them. */ void @@ -328,7 +350,7 @@ bfd_target trad_core_vec = true, /* target headers byte order */ (HAS_RELOC | EXEC_P | /* object flags */ HAS_LINENO | HAS_DEBUG | - HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED), + HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ 0, /* symbol prefix */ ' ', /* ar_pad_char */ |