From: Ian Lance Taylor Date: Thu, 30 Dec 1993 19:56:50 +0000 (+0000) Subject: Extensive changes to move the bulk of the linker into BFD so that X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=4c3721d5147489f4ba880871de0eafb025a4543f;p=binutils-gdb.git 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. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index a0d0f0b1ad9..182f3c51d66 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 3701367d560..ac0bba6f809 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 8cf7429b57f..70835c5b2f0 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 076b0f23044..2f4b7286ddb 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. + I needed to add M_UNKNOWN to recognize a 68000 object, so this will + probably no longer reject a NewsOS object. . */ +#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 1b096b2ac34..57eeaa61426 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 <> 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 <., specify: + to use @file{host-aout.c}, specify: | TDEFAULTS = -DDEFAULT_VECTOR=host_aout_big_vec | TDEPFILES= host-aout.o trad-core.o - in the <> file, and modify @file{configure.in} to use the - <> file (by setting "<>") 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 "<>") when your configuration is selected. */ @@ -125,6 +126,7 @@ DESCRIPTION #include "bfd.h" #include #include +#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 1b445031193..810e80308b6 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 52a29b1e701..c5905a91423 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 ef41bdbe725..7161d4065d7 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 dcdf9e90122..ebc596f5a48 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 840d4256197..101adbd0bea 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++) diff --git a/bfd/elf.c b/bfd/elf.c index 02b3b33bc79..bfb3898dfab 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -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 ed1f417cd0b..bdbb4a51e10 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 84501796f54..7fdfa26daca 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 dc16af0388b..a0db98c3ac4 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 00000000000..b6ecc30fbef --- /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 +#include +#include +#include +#include +#include +#include /* After a.out.h */ +#include +#include + +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 00000000000..afda81389ad --- /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 +#include + +#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 +#include +#include +#include +#include +#include +#include /* After a.out.h */ +#include +#include + +/* 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 00000000000..b0482a4ae4e --- /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 + +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 f063817b896..1f89385b45a 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 + +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 0f9a2cdba3f..5ba73fe79cc 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 74a28afdb20..10e9a9de9ba 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 34f196827f7..e9b0560676d 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 838df6c0a91..311bb1fdca0 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 00000000000..c8c988c6de2 --- /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 +#include +#include +#include + +/* 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 00000000000..5b07ea12d3c --- /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 +#include +#include +#include +#include +#include +#include +#include + + +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 0f05cbe1484..20dd0506bf6 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 <>, and the offsets + Both relocs contain a pointer to <>, 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; @@ -407,6 +401,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 daccf2eb0cf..374e2faf05f 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 <>. 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 <>. 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 ; . . diff --git a/bfd/srec.c b/bfd/srec.c index b37d2070aed..02a49fbd239 100644 --- a/bfd/srec.c +++ b/bfd/srec.c @@ -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 adfc530d3cb..8f10ef3a336 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 d3e5fdd7d0a..f059a8874a4 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 */