+2004-04-01 Paul Brook <paul@codesourcery.com>
+
+ * bfd-in.h (bfd_elf32_arm_process_before_allocation): Update.
+ * elf32-arm.h (struct elf32_elf_section_map): New.
+ (struct _arm_elf_section_data): New.
+ (elf32_arm_section_data): Define.
+ (struct elf32_arm_link_hash_table): Add byteswap_code.
+ (elf32_arm_link_hash_table_create): Initialize byteswap_code.
+ (bfd_elf32_arm_process_before_allocation): Add byteswap_code.
+ (elf32_arm_post_process_headers): Set EF_ARM_BE8.
+ (elf32_arm_output_symbol_hook, elf32_arm_new_section_hook,
+ elf32_arm_compare_mapping, elf32_arm_write_section): New functions.
+ (bfd_elf32_new_section_hook, elf_backend_write_section,
+ elf_backend_link_output_symbol_hook): Define.
+
+2004-04-01 Andy Chittenden <achittenden@bluearc.com>
+
+ * stabs.c (struct stab_link_includes_totals): Add field 'symb'
+ that keeps the characters in a B_INCL..B_EINCL range.
+ (_bfd_link_section_stabs): When computing the sum of the
+ characters in a B_INCL..B_EINCL range also keep a copy of those
+ characters. Use this information to distinguish between
+ include sections that have the same sum and the same length
+ but which are nevertheless unique.
+
+2004-03-31 Paul Brook <paul@codesourcery.com>
+
+ * elf32-arm.h (elf32_arm_final_link_relocate): Add R_ARM_ALU*.
+ * elfarm-nabi.c (elf32_arm_howto_table): Ditto.
+
+2004-03-31 Andy Chittenden <achittenden@bluearc.com>
+
+ * stabs.c (struct stab_link_includes_totals): Rename field 'total'
+ to 'sum_chars' and add field 'num_chars'.
+ (_bfd_link_section_stabs): When computing the sum of the
+ characters in a B_INCL..B_EINCL range also keep a count of the
+ number of characters. Use this information to help distinguish
+ between include sections when have the same sum but which
+ nevertheless are still unique.
+
+2004-03-31 Mattias Engdegård <mattias@virtutech.se>
+
+ * stabs.c (_bfd_link_section_stabs): Do not skip N_EXCL stabs.
+
+2004-03-30 Galit Heller <Galit.Heller@nsc.com>
+ Tomer Levi <Tomer.Levi@nsc.com>
+
+ * Makefile.am (ALL_MACHINES): Add cpu-cr16c.lo.
+ (ALL_MACHINES_CFILES): Add cpu-cr16c.c.
+ (BFD32_BACKENDS): Add elf32-cr16c.lo.
+ (BFD32_BACKENDS_CFILES): Add elf32-cr16c.c.
+ (cpu-cr16c.lo): New target.
+ (elf32-cr16c.lo): Likewise.
+ * Makefile.in: Regenerate.
+ * archures.c (bfd_architecture): Add bfd_{arch,mach}_cr16c.
+ (bfd_archures_list): Add bfd_cr16c_arch.
+ * config.bfd: Handle cr16c-*-elf*.
+ * configure.in: Handle bfd_elf32_cr16c_vec.
+ * configure: Regenerate.
+ * reloc.c: Add BFD_RELOC_16C_NUM08, BFD_RELOC_16C_NUM08_C,
+ BFD_RELOC_16C_NUM16, BFD_RELOC_16C_NUM16_C,
+ BFD_RELOC_16C_NUM32, BFD_RELOC_16C_NUM32_C,
+ BFD_RELOC_16C_DISP04, BFD_RELOC_16C_DISP04_C,
+ BFD_RELOC_16C_DISP08, BFD_RELOC_16C_DISP08_C,
+ BFD_RELOC_16C_DISP16, BFD_RELOC_16C_DISP16_C,
+ BFD_RELOC_16C_DISP24, BFD_RELOC_16C_DISP24_C,
+ BFD_RELOC_16C_DISP24a, BFD_RELOC_16C_DISP24a_C,
+ BFD_RELOC_16C_REG04, BFD_RELOC_16C_REG04_C,
+ BFD_RELOC_16C_REG04a, BFD_RELOC_16C_REG04a_C,
+ BFD_RELOC_16C_REG14, BFD_RELOC_16C_REG14_C,
+ BFD_RELOC_16C_REG16, BFD_RELOC_16C_REG16_C,
+ BFD_RELOC_16C_REG20, BFD_RELOC_16C_REG20_C,
+ BFD_RELOC_16C_ABS20, BFD_RELOC_16C_ABS20_C,
+ BFD_RELOC_16C_ABS24, BFD_RELOC_16C_ABS24_C,
+ BFD_RELOC_16C_IMM04, BFD_RELOC_16C_IMM04_C,
+ BFD_RELOC_16C_IMM16, BFD_RELOC_16C_IMM16_C,
+ BFD_RELOC_16C_IMM20, BFD_RELOC_16C_IMM20_C,
+ BFD_RELOC_16C_IMM24, BFD_RELOC_16C_IMM24_C,
+ BFD_RELOC_16C_IMM32, BFD_RELOC_16C_IMM32_C.
+ * targets.c (bfd_elf32_cr16c_vec): Declare.
+ (bfd_target_vector): Add bfd_elf32_cr16c_vec.
+ * cpu-cr16c.c: New file.
+ * elf32-cr16c.c: Likewise.
+ * libbfd.h: Regenerate.
+ * bfd-in2.h: Likewise.
+
+2004-03-30 Jakub Jelinek <jakub@redhat.com>
+
+ * elf.c (map_sections_to_segments): Fix handling of .tbss.
+
+2004-03-27 Alan Modra <amodra@bigpond.net.au>
+
+ * Makefile.am: Remove all mention of elflink.h.
+ * Makefile.in: Regenerate.
+ * bfd-in.h (bfd_elf_discard_info): Declare.
+ (bfd_elf32_discard_info, bfd_elf64_discard_info): Delete.
+ * bfd-in2.h: Regenerate.
+ * elf-bfd.h (bfd_elf32_print_symbol, bfd_elf64_print_symbol,
+ bfd_elf32_link_record_dynamic_symbol,
+ bfd_elf64_link_record_dynamic_symbol,
+ _bfd_elf_link_record_dynamic_symbol, bfd_elf32_bfd_final_link,
+ bfd_elf64_bfd_final_link, elf_link_record_local_dynamic_symbol,
+ _bfd_elf32_link_record_local_dynamic_symbol,
+ _bfd_elf64_link_record_local_dynamic_symbol,
+ _bfd_elf32_gc_sections, _bfd_elf32_gc_common_finalize_got_offsets,
+ _bfd_elf32_gc_common_final_link, _bfd_elf64_gc_common_final_link,
+ _bfd_elf32_gc_record_vtinherit, _bfd_elf32_gc_record_vtentry,
+ _bfd_elf64_gc_sections, _bfd_elf64_gc_common_finalize_got_offsets,
+ _bfd_elf64_gc_record_vtinherit, _bfd_elf64_gc_record_vtentry,
+ _bfd_elf32_reloc_symbol_deleted_p,
+ _bfd_elf64_reloc_symbol_deleted_p): Delete.
+ (bfd_elf_link_record_dynamic_symbol,
+ bfd_elf_link_record_local_dynamic_symbol,
+ bfd_elf_final_link, bfd_elf_gc_sections,
+ bfd_elf_gc_record_vtinherit, bfd_elf_gc_record_vtentry,
+ bfd_elf_gc_common_finalize_got_offsets, bfd_elf_gc_common_final_link,
+ bfd_elf_reloc_symbol_deleted_p): Declare.
+ (WILL_CALL_FINISH_DYNAMIC_SYMBOL): Define.
+ * elf32-arm.h: Update for changed function names. Remove local
+ WILL_CALL_FINISH_DYNAMIC_SECTION define.
+ * elf-hppa.h, elf-m10300.c, elf32-cris.c, elf32-d10v.c, elf32-dlx.c,
+ * elf32-fr30.c, elf32-frv.c, elf32-h8300.c, elf32-hppa.c, elf32-i386.c,
+ * elf32-iq2000.c, elf32-m32r.c, elf32-m68hc1x.c, elf32-m68k.c,
+ * elf32-mcore.c, elf32-openrisc.c, elf32-ppc.c, elf32-s390.c,
+ * elf32-sh.c, elf32-sparc.c, elf32-v850.c, elf32-vax.c,
+ * elf32-xstormy16.c, elf32-xtensa.c, elf64-alpha.c, elf64-hppa.c,
+ * elf64-mmix.c, elf64-ppc.c, elf64-s390.c, elf64-sh64.c, elf64-sparc.c,
+ * elf64-x86-64.c, elfxx-ia64.c, elfxx-mips.c, elfxx-target.h: Likewise.
+ * elfxx-target.h (bfd_elfNN_bfd_final_link): Define.
+ (bfd_elfNN_print_symbol): Define.
+ * elfcode.h: Don't include elflink.h.
+ (elf_bfd_discard_info, elf_reloc_symbol_deleted_p,
+ elf_link_record_dynamic_symbol, elf_bfd_final_link, elf_gc_sections,
+ elf_gc_common_finalize_got_offsets, elf_gc_common_final_link,
+ elf_gc_record_vtinherit, elf_gc_record_vtentry,
+ elf_link_record_local_dynamic_symbol): Don't define.
+ * elflink.c: Update for changed function names. Move elflink.h
+ code here.
+ * elflink.h: Delete file.
+ * po/SRC-POTFILES.in: Regenerate.
+ * po/bfd.pot: Regenerate.
+
+2004-03-27 Alan Modra <amodra@bigpond.net.au>
+
+ * elf64-mmix.c (mmix_elf_relocate_section): Restore code setting
+ "name" for global syms accidentally removed in 2004-03-20 change.
+
+2004-03-27 Alan Modra <amodra@bigpond.net.au>
+
+ * elf-bfd.h (struct elf_reloc_cookie): Add r_sym_shift field.
+ * elflink.h: Replace all occurrences of sizeof (Elf_External_*)
+ where Elf_External_* is different for 64 and 32 bit, with
+ corresponding elf_size_info field.
+ (struct elf_final_link_info): Use "bfd_byte *" instead
+ of "Elf_External_Sym *" for external_syms and symbuf.
+ (elf_link_adjust_relocs): Set up r_type_mask and r_sym_shift local
+ vars and use instead of ELF_R_INFO and ELF_R_TYPE macros.
+ (struct elf_link_sort_rela): Add "sym_mask" alias for "offset".
+ (elf_link_sort_cmp1): Use sym_mask field instead of ELF_R_SYM.
+ (elf_link_sort_cmp2): Adjust.
+ (elf_link_sort_relocs): Set up r_sym_mask local var instead of
+ using ELF_R_SYM macro. Set u.sym_mask.
+ (elf_bfd_final_link): Call _bfd_elf_stringtab_init instead of macro
+ version, elf_stringtab_init. Ditto for bfd_section_from_elf_index
+ vs. section_from_elf_index. Adjust Elf_External_Sym pointer
+ arithmetic. Pass bed to elf_link_flush_output_syms. Adjust
+ Elf_External_Dyn pointer arithmentic. Use bed swap_dyn_in and
+ swap_syn_out functions. Rearrange dyn swap in/out switch.
+ (elf_link_output_sym): Adjust Elf_External_Sym pointer arithmentic.
+ Pass bed to elf_link_flush_output_syms. Use bed swap_symbol_out.
+ (elf_link_flush_output_syms): Add elf_backend_data arg.
+ (elf_link_check_versioned_symbol): Likewise.
+ (elf_link_output_extsym): Pass bed to elf_link_check_versioned_symbol.
+ Adjust Elf_External_Sym pointer arithmetic. Use bed swap_symbol_out.
+ (elf_link_input_bfd): Use bfd_section_from_elf_index. Set up
+ r_type_mask and r_sym_shift local vars and use instead of ELF_R_SYM,
+ ELF_R_TYPE and ELF_R_INFO macros.
+ (elf_reloc_link_order): Select ELF32_R_INFO or ELF64_R_INFO invocation
+ based on size rather than using ELF_R_INFO.
+ (elf_gc_mark): Set up r_sym_shift local var and use instead of
+ ELF_R_SYM macro.
+ (struct alloc_got_off_arg): New.
+ (elf_gc_common_finalize_got_offsets): Use elf_size_info instead of
+ ARCH_SIZE. Pass get entry size down to elf_gc_allocate_got_offsets.
+ (elf_gc_allocate_got_offsets): Adjust.
+ (elf_reloc_symbol_deleted_p): Usee cookie.r_sym_shift instead of
+ ELF_R_SYM. Use bfd_section_from_elf_index.
+ (elf_bfd_discard_info): Set cookie.r_sym_shift.
+ * elfcode.h (elf_stringtab_init, section_from_elf_index): Delete.
+ (elf_slurp_symbol_table): Use bfd_section_from_elf_index.
+
+2004-03-26 Stan Shebs <shebs@apple.com>
+
+ Remove MPW support, no longer used.
+ * config.bfd (powerpc-*-mpw*): Remove configuration.
+ * mpw-config.in, mpw-make.sed: Remove files.
+ * ecoffswap.h [MPW_C]: Remove MPW-C-friendly version of code.
+
2004-03-26 Alan Modra <amodra@bigpond.net.au>
* elf64-ppc.c (elf_backend_add_symbol_hook): Define.
* elflink.h (elf_link_add_object_symbols): Add DT_NEEDED for as-needed
and chained shared libs only if dynsym. Clear dynsym on forced-local.
-
+
* elf-bfd.h (_bfd_elf_add_dynamic_entry): Declare.
(bfd_elf32_add_dynamic_entry, bfd_elf64_add_dynamic_entry): Delete.
(_bfd_elf_add_dt_needed_tag): Declare.
(elf_xtensa_size_dynamic_sections): Don't add DT_TEXTREL entry.
(elf_xtensa_relocate_section): Read literal tables and check for
dynamic relocations in read-only sections and not in literal pools.
-
+
2004-03-23 Alan Modra <amodra@bigpond.net.au>
PR 51.
cpu-arc.lo \
cpu-arm.lo \
cpu-avr.lo \
+ cpu-cr16c.lo \
cpu-cris.lo \
cpu-d10v.lo \
cpu-d30v.lo \
cpu-arm.c \
cpu-avr.c \
cpu-cris.c \
+ cpu-cr16c.c \
cpu-d10v.c \
cpu-d30v.c \
cpu-dlx.c \
elfarm-oabi.lo \
elfarm-nabi.lo \
elf32-avr.lo \
+ elf32-cr16c.lo \
elf32-cris.lo \
elf32-d10v.lo \
elf32-d30v.lo \
elfarm-oabi.c \
elfarm-nabi.c \
elf32-avr.c \
+ elf32-cr16c.c \
elf32-cris.c \
elf32-d10v.c \
elf32-d30v.c \
SOURCE_HFILES = \
aout-target.h aoutf1.h aoutx.h coffcode.h coffswap.h ecoffswap.h \
elf-bfd.h elf-hppa.h elf32-arm.h elf32-hppa.h \
- elf64-hppa.h elfcode.h elfcore.h elflink.h \
+ elf64-hppa.h elfcode.h elfcore.h \
freebsd.h genlink.h go32stub.h \
libaout.h libbfd.h libcoff.h libecoff.h libhppa.h libieee.h \
libnlm.h liboasys.h libpei.h libxcoff.h mach-o.h \
cpu-arc.lo: cpu-arc.c $(INCDIR)/filenames.h
cpu-arm.lo: cpu-arm.c $(INCDIR)/filenames.h $(INCDIR)/libiberty.h
cpu-avr.lo: cpu-avr.c $(INCDIR)/filenames.h
+cpu-cr16c.lo: cpu-cr16c.c $(INCDIR)/filenames.h
cpu-cris.lo: cpu-cris.c $(INCDIR)/filenames.h
cpu-d10v.lo: cpu-d10v.c $(INCDIR)/filenames.h
cpu-d30v.lo: cpu-d30v.c $(INCDIR)/filenames.h
$(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
$(INCDIR)/bfdlink.h $(INCDIR)/elf/avr.h $(INCDIR)/elf/reloc-macros.h \
elf32-target.h
+elf32-cr16c.lo: elf32-cr16c.c $(INCDIR)/filenames.h elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/elf/cr16c.h $(INCDIR)/elf/reloc-macros.h \
+ elf32-target.h
elf32-cris.lo: elf32-cris.c $(INCDIR)/filenames.h elf-bfd.h \
$(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
$(INCDIR)/bfdlink.h $(INCDIR)/elf/cris.h $(INCDIR)/elf/reloc-macros.h \
elf32.lo: elf32.c elfcode.h $(INCDIR)/filenames.h $(INCDIR)/libiberty.h \
$(INCDIR)/bfdlink.h elf-bfd.h $(INCDIR)/elf/common.h \
$(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h elfcore.h \
- elflink.h $(INCDIR)/safe-ctype.h
+ $(INCDIR)/safe-ctype.h
elflink.lo: elflink.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \
elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
$(INCDIR)/elf/external.h
elf64.lo: elf64.c elfcode.h $(INCDIR)/filenames.h $(INCDIR)/libiberty.h \
$(INCDIR)/bfdlink.h elf-bfd.h $(INCDIR)/elf/common.h \
$(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h elfcore.h \
- elflink.h $(INCDIR)/safe-ctype.h
+ $(INCDIR)/safe-ctype.h
mmo.lo: mmo.c $(INCDIR)/filenames.h $(INCDIR)/libiberty.h \
$(INCDIR)/elf/mmix.h $(INCDIR)/elf/reloc-macros.h $(INCDIR)/opcode/mmix.h
nlm32-alpha.lo: nlm32-alpha.c $(INCDIR)/filenames.h \
-# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
+# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
cpu-arc.lo \
cpu-arm.lo \
cpu-avr.lo \
+ cpu-cr16c.lo \
cpu-cris.lo \
cpu-d10v.lo \
cpu-d30v.lo \
cpu-arm.c \
cpu-avr.c \
cpu-cris.c \
+ cpu-cr16c.c \
cpu-d10v.c \
cpu-d30v.c \
cpu-dlx.c \
elfarm-oabi.lo \
elfarm-nabi.lo \
elf32-avr.lo \
+ elf32-cr16c.lo \
elf32-cris.lo \
elf32-d10v.lo \
elf32-d30v.lo \
elfarm-oabi.c \
elfarm-nabi.c \
elf32-avr.c \
+ elf32-cr16c.c \
elf32-cris.c \
elf32-d10v.c \
elf32-d30v.c \
SOURCE_HFILES = \
aout-target.h aoutf1.h aoutx.h coffcode.h coffswap.h ecoffswap.h \
elf-bfd.h elf-hppa.h elf32-arm.h elf32-hppa.h \
- elf64-hppa.h elfcode.h elfcore.h elflink.h \
+ elf64-hppa.h elfcode.h elfcore.h \
freebsd.h genlink.h go32stub.h \
libaout.h libbfd.h libcoff.h libecoff.h libhppa.h libieee.h \
libnlm.h liboasys.h libpei.h libxcoff.h mach-o.h \
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
-TAR = tar
+TAR = gtar
GZIP_ENV = --best
SOURCES = $(libbfd_a_SOURCES) $(libbfd_la_SOURCES)
OBJECTS = $(libbfd_a_OBJECTS) $(libbfd_la_OBJECTS)
cpu-arc.lo: cpu-arc.c $(INCDIR)/filenames.h
cpu-arm.lo: cpu-arm.c $(INCDIR)/filenames.h $(INCDIR)/libiberty.h
cpu-avr.lo: cpu-avr.c $(INCDIR)/filenames.h
+cpu-cr16c.lo: cpu-cr16c.c $(INCDIR)/filenames.h
cpu-cris.lo: cpu-cris.c $(INCDIR)/filenames.h
cpu-d10v.lo: cpu-d10v.c $(INCDIR)/filenames.h
cpu-d30v.lo: cpu-d30v.c $(INCDIR)/filenames.h
$(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
$(INCDIR)/bfdlink.h $(INCDIR)/elf/avr.h $(INCDIR)/elf/reloc-macros.h \
elf32-target.h
+elf32-cr16c.lo: elf32-cr16c.c $(INCDIR)/filenames.h elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/elf/cr16c.h $(INCDIR)/elf/reloc-macros.h \
+ elf32-target.h
elf32-cris.lo: elf32-cris.c $(INCDIR)/filenames.h elf-bfd.h \
$(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
$(INCDIR)/bfdlink.h $(INCDIR)/elf/cris.h $(INCDIR)/elf/reloc-macros.h \
elf32.lo: elf32.c elfcode.h $(INCDIR)/filenames.h $(INCDIR)/libiberty.h \
$(INCDIR)/bfdlink.h elf-bfd.h $(INCDIR)/elf/common.h \
$(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h elfcore.h \
- elflink.h $(INCDIR)/safe-ctype.h
+ $(INCDIR)/safe-ctype.h
elflink.lo: elflink.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \
elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
$(INCDIR)/elf/external.h
elf64.lo: elf64.c elfcode.h $(INCDIR)/filenames.h $(INCDIR)/libiberty.h \
$(INCDIR)/bfdlink.h elf-bfd.h $(INCDIR)/elf/common.h \
$(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h elfcore.h \
- elflink.h $(INCDIR)/safe-ctype.h
+ $(INCDIR)/safe-ctype.h
mmo.lo: mmo.c $(INCDIR)/filenames.h $(INCDIR)/libiberty.h \
$(INCDIR)/elf/mmix.h $(INCDIR)/elf/reloc-macros.h $(INCDIR)/opcode/mmix.h
nlm32-alpha.lo: nlm32-alpha.c $(INCDIR)/filenames.h \
.#define bfd_mach_avr3 3
.#define bfd_mach_avr4 4
.#define bfd_mach_avr5 5
+. bfd_arch_cr16c, {* National Semiconductor CompactRISC. *}
+.#define bfd_mach_cr16c 1
. bfd_arch_cris, {* Axis CRIS *}
. bfd_arch_s390, {* IBM s390 *}
.#define bfd_mach_s390_31 31
extern const bfd_arch_info_type bfd_arc_arch;
extern const bfd_arch_info_type bfd_arm_arch;
extern const bfd_arch_info_type bfd_avr_arch;
+extern const bfd_arch_info_type bfd_cr16c_arch;
extern const bfd_arch_info_type bfd_cris_arch;
extern const bfd_arch_info_type bfd_d10v_arch;
extern const bfd_arch_info_type bfd_d30v_arch;
&bfd_arc_arch,
&bfd_arm_arch,
&bfd_avr_arch,
+ &bfd_cr16c_arch,
&bfd_cris_arch,
&bfd_d10v_arch,
&bfd_d30v_arch,
(bfd *, int);
extern struct bfd_link_needed_list *bfd_elf_get_runpath_list
(bfd *, struct bfd_link_info *);
-extern bfd_boolean bfd_elf32_discard_info
- (bfd *, struct bfd_link_info *);
-extern bfd_boolean bfd_elf64_discard_info
+extern bfd_boolean bfd_elf_discard_info
(bfd *, struct bfd_link_info *);
/* Return an upper bound on the number of bytes required to store a
(struct bfd_link_info *);
extern bfd_boolean bfd_elf32_arm_process_before_allocation
- (bfd *, struct bfd_link_info *, int);
+ (bfd *, struct bfd_link_info *, int, int);
extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
(bfd *, struct bfd_link_info *);
(bfd *, int);
extern struct bfd_link_needed_list *bfd_elf_get_runpath_list
(bfd *, struct bfd_link_info *);
-extern bfd_boolean bfd_elf32_discard_info
- (bfd *, struct bfd_link_info *);
-extern bfd_boolean bfd_elf64_discard_info
+extern bfd_boolean bfd_elf_discard_info
(bfd *, struct bfd_link_info *);
/* Return an upper bound on the number of bytes required to store a
(struct bfd_link_info *);
extern bfd_boolean bfd_elf32_arm_process_before_allocation
- (bfd *, struct bfd_link_info *, int);
+ (bfd *, struct bfd_link_info *, int, int);
extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
(bfd *, struct bfd_link_info *);
#define bfd_mach_avr3 3
#define bfd_mach_avr4 4
#define bfd_mach_avr5 5
+ bfd_arch_cr16c, /* National Semiconductor CompactRISC. */
+#define bfd_mach_cr16c 1
bfd_arch_cris, /* Axis CRIS */
bfd_arch_s390, /* IBM s390 */
#define bfd_mach_s390_31 31
This is the 5 bits of a value. */
BFD_RELOC_M68HC12_5B,
+/* NS CR16C Relocations. */
+ BFD_RELOC_16C_NUM08,
+ BFD_RELOC_16C_NUM08_C,
+ BFD_RELOC_16C_NUM16,
+ BFD_RELOC_16C_NUM16_C,
+ BFD_RELOC_16C_NUM32,
+ BFD_RELOC_16C_NUM32_C,
+ BFD_RELOC_16C_DISP04,
+ BFD_RELOC_16C_DISP04_C,
+ BFD_RELOC_16C_DISP08,
+ BFD_RELOC_16C_DISP08_C,
+ BFD_RELOC_16C_DISP16,
+ BFD_RELOC_16C_DISP16_C,
+ BFD_RELOC_16C_DISP24,
+ BFD_RELOC_16C_DISP24_C,
+ BFD_RELOC_16C_DISP24a,
+ BFD_RELOC_16C_DISP24a_C,
+ BFD_RELOC_16C_REG04,
+ BFD_RELOC_16C_REG04_C,
+ BFD_RELOC_16C_REG04a,
+ BFD_RELOC_16C_REG04a_C,
+ BFD_RELOC_16C_REG14,
+ BFD_RELOC_16C_REG14_C,
+ BFD_RELOC_16C_REG16,
+ BFD_RELOC_16C_REG16_C,
+ BFD_RELOC_16C_REG20,
+ BFD_RELOC_16C_REG20_C,
+ BFD_RELOC_16C_ABS20,
+ BFD_RELOC_16C_ABS20_C,
+ BFD_RELOC_16C_ABS24,
+ BFD_RELOC_16C_ABS24_C,
+ BFD_RELOC_16C_IMM04,
+ BFD_RELOC_16C_IMM04_C,
+ BFD_RELOC_16C_IMM16,
+ BFD_RELOC_16C_IMM16_C,
+ BFD_RELOC_16C_IMM20,
+ BFD_RELOC_16C_IMM20_C,
+ BFD_RELOC_16C_IMM24,
+ BFD_RELOC_16C_IMM24_C,
+ BFD_RELOC_16C_IMM32,
+ BFD_RELOC_16C_IMM32_C,
+
/* These relocs are only used within the CRIS assembler. They are not
(at present) written to any object files. */
BFD_RELOC_CRIS_BDISP8,
targ_underscore=yes
;;
+ cr16c-*-elf*)
+ targ_defvec=bfd_elf32_cr16c_vec
+ targ_underscore=yes
+ ;;
+
cris-*-*)
targ_defvec=cris_aout_vec
targ_selvecs="bfd_elf32_us_cris_vec bfd_elf32_cris_vec ieee_vec"
targ_selvecs="mach_o_be_vec mach_o_le_vec mach_o_fat_vec pef_vec pef_xlib_vec sym_vec"
targ_archs="bfd_powerpc_arch bfd_rs6000_arch bfd_i386_arch"
;;
- powerpc-*-macos* | powerpc-*-mpw*)
+ powerpc-*-macos*)
targ_defvec=pmac_xcoff_vec
;;
powerpc-*-netware*)
bfd_elf32_bigarm_oabi_vec) tb="$tb elfarm-oabi.lo elf32.lo $elf" ;;
bfd_elf32_bigarm_vec) tb="$tb elfarm-nabi.lo elf32.lo $elf" ;;
bfd_elf32_bigmips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo" ;;
+ bfd_elf32_cr16c_vec) tb="$tb elf32-cr16c.lo elf32.lo $elf" ;;
bfd_elf32_cris_vec) tb="$tb elf32-cris.lo elf32.lo $elf" ;;
bfd_elf32_d10v_vec) tb="$tb elf32-d10v.lo elf32.lo $elf" ;;
bfd_elf32_d30v_vec) tb="$tb elf32-d30v.lo elf32.lo $elf" ;;
if test -n "$GCC" ; then
bad_64bit_gcc=no;
echo $ac_n "checking for gcc version with buggy 64-bit support""... $ac_c" 1>&6
-echo "configure:6590: checking for gcc version with buggy 64-bit support" >&5
+echo "configure:6591: checking for gcc version with buggy 64-bit support" >&5
# Add more tests for gcc versions with non-working 64-bit support here.
cat > conftest.$ac_ext <<EOF
-#line 6593 "configure"
+#line 6594 "configure"
#include "confdefs.h"
:__GNUC__:__GNUC_MINOR__:__i386__:
EOF
for ac_func in ftello ftello64 fseeko fseeko64
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:6635: checking for $ac_func" >&5
+echo "configure:6636: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 6640 "configure"
+#line 6641 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
; return 0; }
EOF
-if { (eval echo configure:6663: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6664: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
if test x"$ac_cv_func_ftello" = xyes -a x"$ac_cv_func_fseeko" = xyes; then
echo $ac_n "checking size of off_t""... $ac_c" 1>&6
-echo "configure:6689: checking size of off_t" >&5
+echo "configure:6690: checking size of off_t" >&5
if eval "test \"`echo '$''{'ac_cv_sizeof_off_t'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
for ac_size in 4 8 1 2 16 12 ; do # List sizes in rough order of prevalence.
cat > conftest.$ac_ext <<EOF
-#line 6695 "configure"
+#line 6696 "configure"
#include "confdefs.h"
#include "confdefs.h"
#include <sys/types.h>
switch (0) case 0: case (sizeof (off_t) == $ac_size):;
; return 0; }
EOF
-if { (eval echo configure:6705: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:6706: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_sizeof_off_t=$ac_size
else
fi
echo $ac_n "checking file_ptr type""... $ac_c" 1>&6
-echo "configure:6729: checking file_ptr type" >&5
+echo "configure:6730: checking file_ptr type" >&5
bfd_file_ptr="long"
bfd_ufile_ptr="unsigned long"
if test x"$ac_cv_func_ftello64" = xyes -a x"$ac_cv_func_fseeko64" = xyes \
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:6754: checking for $ac_hdr" >&5
+echo "configure:6755: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 6759 "configure"
+#line 6760 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:6764: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:6765: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
for ac_func in getpagesize
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:6793: checking for $ac_func" >&5
+echo "configure:6794: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 6798 "configure"
+#line 6799 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
; return 0; }
EOF
-if { (eval echo configure:6821: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6822: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
done
echo $ac_n "checking for working mmap""... $ac_c" 1>&6
-echo "configure:6846: checking for working mmap" >&5
+echo "configure:6847: checking for working mmap" >&5
if eval "test \"`echo '$''{'ac_cv_func_mmap_fixed_mapped'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_cv_func_mmap_fixed_mapped=no
else
cat > conftest.$ac_ext <<EOF
-#line 6854 "configure"
+#line 6855 "configure"
#include "confdefs.h"
/* Thanks to Mike Haertel and Jim Avera for this test.
}
EOF
-if { (eval echo configure:7007: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:7008: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_func_mmap_fixed_mapped=yes
else
for ac_func in madvise mprotect
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:7032: checking for $ac_func" >&5
+echo "configure:7033: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 7037 "configure"
+#line 7038 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
; return 0; }
EOF
-if { (eval echo configure:7060: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7061: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
bfd_elf32_bigarm_oabi_vec) tb="$tb elfarm-oabi.lo elf32.lo $elf" ;;
bfd_elf32_bigarm_vec) tb="$tb elfarm-nabi.lo elf32.lo $elf" ;;
bfd_elf32_bigmips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo" ;;
+ bfd_elf32_cr16c_vec) tb="$tb elf32-cr16c.lo elf32.lo $elf" ;;
bfd_elf32_cris_vec) tb="$tb elf32-cris.lo elf32.lo $elf" ;;
bfd_elf32_d10v_vec) tb="$tb elf32-d10v.lo elf32.lo $elf" ;;
bfd_elf32_d30v_vec) tb="$tb elf32-d30v.lo elf32.lo $elf" ;;
+2004-03-27 Alan Modra <amodra@bigpond.net.au>
+
+ * bfdint.texi: Remove all mention of elflink.h.
+
2004-03-19 Alan Modra <amodra@bigpond.net.au>
* Makefile.in: Regenerate.
-# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
+# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
-TAR = tar
+TAR = gtar
GZIP_ENV = --best
all: all-redirect
.SUFFIXES:
Like @file{elfcode.h}, but for functions that are specific to ELF core
files. This is included only by @file{elfcode.h}.
-@item elflink.h
-@cindex @file{elflink.h}
-Like @file{elfcode.h}, but for functions used by the ELF linker. This
-is included only by @file{elfcode.h}.
-
@item elfxx-target.h
@cindex @file{elfxx-target.h}
This file is the source for the generated files @file{elf32-target.h}
@file{elfcode.h} includes functions to swap the ELF structures in and
out of external form, as well as a few more complex functions.
-Linker support is found in @file{elflink.c} and @file{elflink.h}. The
-latter file is compiled twice, for both 32 and 64 bit support. The
+Linker support is found in @file{elflink.c}. The
linker support is only used if the processor specific file defines
@samp{elf_backend_relocate_section}, which is required to relocate the
section contents. If that macro is not defined, the generic linker code
#endif
}
-#ifndef MPW_C
-
/* Swap in the procedure descriptor record. */
static void
#endif
}
-#else /* MPW_C */
-/* Same routines, but with ECOFF_64 code removed, so ^&%$#&! MPW C doesn't
- corrupt itself and then freak out. */
-/* Swap in the procedure descriptor record. */
-
-static void
-ecoff_swap_pdr_in (abfd, ext_copy, intern)
- bfd *abfd;
- PTR ext_copy;
- PDR *intern;
-{
- struct pdr_ext ext[1];
-
- *ext = *(struct pdr_ext *) ext_copy;
-
- intern->adr = ECOFF_GET_OFF (abfd, ext->p_adr);
- intern->isym = H_GET_32 (abfd, ext->p_isym);
- intern->iline = H_GET_32 (abfd, ext->p_iline);
- intern->regmask = H_GET_32 (abfd, ext->p_regmask);
- intern->regoffset = H_GET_S32 (abfd, ext->p_regoffset);
- intern->iopt = H_GET_S32 (abfd, ext->p_iopt);
- intern->fregmask = H_GET_32 (abfd, ext->p_fregmask);
- intern->fregoffset = H_GET_S32 (abfd, ext->p_fregoffset);
- intern->frameoffset = H_GET_S32 (abfd, ext->p_frameoffset);
- intern->framereg = H_GET_16 (abfd, ext->p_framereg);
- intern->pcreg = H_GET_16 (abfd, ext->p_pcreg);
- intern->lnLow = H_GET_32 (abfd, ext->p_lnLow);
- intern->lnHigh = H_GET_32 (abfd, ext->p_lnHigh);
- intern->cbLineOffset = ECOFF_GET_OFF (abfd, ext->p_cbLineOffset);
-
-#ifdef TEST
- if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
- abort ();
-#endif
-}
-
-/* Swap out the procedure descriptor record. */
-
-static void
-ecoff_swap_pdr_out (abfd, intern_copy, ext_ptr)
- bfd *abfd;
- const PDR *intern_copy;
- PTR ext_ptr;
-{
- struct pdr_ext *ext = (struct pdr_ext *) ext_ptr;
- PDR intern[1];
-
- /* Make it reasonable to do in-place. */
- *intern = *intern_copy;
-
- ECOFF_PUT_OFF (abfd, intern->adr, ext->p_adr);
- H_PUT_32 (abfd, intern->isym, ext->p_isym);
- H_PUT_32 (abfd, intern->iline, ext->p_iline);
- H_PUT_32 (abfd, intern->regmask, ext->p_regmask);
- H_PUT_32 (abfd, intern->regoffset, ext->p_regoffset);
- H_PUT_32 (abfd, intern->iopt, ext->p_iopt);
- H_PUT_32 (abfd, intern->fregmask, ext->p_fregmask);
- H_PUT_32 (abfd, intern->fregoffset, ext->p_fregoffset);
- H_PUT_32 (abfd, intern->frameoffset, ext->p_frameoffset);
- H_PUT_16 (abfd, intern->framereg, ext->p_framereg);
- H_PUT_16 (abfd, intern->pcreg, ext->p_pcreg);
- H_PUT_32 (abfd, intern->lnLow, ext->p_lnLow);
- H_PUT_32 (abfd, intern->lnHigh, ext->p_lnHigh);
- ECOFF_PUT_OFF (abfd, intern->cbLineOffset, ext->p_cbLineOffset);
-
-#ifdef TEST
- if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
- abort ();
-#endif
-}
-#endif /* MPW_C */
-
/* Swap in a symbol record. */
static void
size_t locsymcount;
size_t extsymoff;
struct elf_link_hash_entry **sym_hashes;
+ int r_sym_shift;
bfd_boolean bad_symtab;
};
bfd_elf_string_from_elf_section (abfd, elf_elfheader(abfd)->e_shstrndx, \
strindex)
-#define bfd_elf32_print_symbol bfd_elf_print_symbol
-#define bfd_elf64_print_symbol bfd_elf_print_symbol
-
extern void _bfd_elf_sprintf_vma
(bfd *, char *, bfd_vma);
extern void _bfd_elf_fprintf_vma
extern bfd_boolean _bfd_elf_link_assign_sym_version
(struct elf_link_hash_entry *, void *);
-extern bfd_boolean _bfd_elf_link_record_dynamic_symbol
- (struct bfd_link_info *, struct elf_link_hash_entry *);
extern long _bfd_elf_link_lookup_local_dynindx
(struct bfd_link_info *, bfd *, long);
extern bfd_boolean _bfd_elf_compute_section_file_positions
extern bfd_boolean bfd_elf32_core_file_matches_executable_p
(bfd *, bfd *);
-extern bfd_boolean bfd_elf32_bfd_final_link
- (bfd *, struct bfd_link_info *);
-
extern void bfd_elf32_swap_symbol_in
(bfd *, const void *, const void *, Elf_Internal_Sym *);
extern void bfd_elf32_swap_symbol_out
(bfd *);
extern bfd_boolean bfd_elf64_core_file_matches_executable_p
(bfd *, bfd *);
-extern bfd_boolean bfd_elf64_bfd_final_link
- (bfd *, struct bfd_link_info *);
extern void bfd_elf64_swap_symbol_in
(bfd *, const void *, const void *, Elf_Internal_Sym *);
extern bfd_boolean _bfd_elf_add_dynamic_entry
(struct bfd_link_info *, bfd_vma, bfd_vma);
-#define bfd_elf32_link_record_dynamic_symbol \
- _bfd_elf_link_record_dynamic_symbol
-#define bfd_elf64_link_record_dynamic_symbol \
- _bfd_elf_link_record_dynamic_symbol
+extern bfd_boolean bfd_elf_link_record_dynamic_symbol
+ (struct bfd_link_info *, struct elf_link_hash_entry *);
-extern int elf_link_record_local_dynamic_symbol
+extern int bfd_elf_link_record_local_dynamic_symbol
(struct bfd_link_info *, bfd *, long);
-#define _bfd_elf32_link_record_local_dynamic_symbol \
- elf_link_record_local_dynamic_symbol
-#define _bfd_elf64_link_record_local_dynamic_symbol \
- elf_link_record_local_dynamic_symbol
extern bfd_boolean _bfd_elf_close_and_cleanup
(bfd *);
(bfd *, arelent *, struct bfd_symbol *, void *,
asection *, bfd *, char **);
-extern bfd_boolean _bfd_elf32_gc_sections
+extern bfd_boolean bfd_elf_final_link
(bfd *, struct bfd_link_info *);
-extern bfd_boolean _bfd_elf32_gc_common_finalize_got_offsets
- (bfd *, struct bfd_link_info *);
-extern bfd_boolean _bfd_elf32_gc_common_final_link
+
+extern bfd_boolean bfd_elf_gc_sections
(bfd *, struct bfd_link_info *);
-extern bfd_boolean _bfd_elf32_gc_record_vtinherit
+
+extern bfd_boolean bfd_elf_gc_record_vtinherit
(bfd *, asection *, struct elf_link_hash_entry *, bfd_vma);
-extern bfd_boolean _bfd_elf32_gc_record_vtentry
+
+extern bfd_boolean bfd_elf_gc_record_vtentry
(bfd *, asection *, struct elf_link_hash_entry *, bfd_vma);
-extern bfd_boolean _bfd_elf64_gc_sections
+extern bfd_boolean bfd_elf_gc_common_finalize_got_offsets
(bfd *, struct bfd_link_info *);
-extern bfd_boolean _bfd_elf64_gc_common_finalize_got_offsets
- (bfd *, struct bfd_link_info *);
-extern bfd_boolean _bfd_elf64_gc_common_final_link
+
+extern bfd_boolean bfd_elf_gc_common_final_link
(bfd *, struct bfd_link_info *);
-extern bfd_boolean _bfd_elf64_gc_record_vtinherit
- (bfd *, asection *, struct elf_link_hash_entry *, bfd_vma);
-extern bfd_boolean _bfd_elf64_gc_record_vtentry
- (bfd *, asection *, struct elf_link_hash_entry *, bfd_vma);
-extern bfd_boolean _bfd_elf32_reloc_symbol_deleted_p
- (bfd_vma, void *);
-extern bfd_boolean _bfd_elf64_reloc_symbol_deleted_p
+extern bfd_boolean bfd_elf_reloc_symbol_deleted_p
(bfd_vma, void *);
/* Exported interface for writing elf corefile notes. */
extern bfd_boolean _sh_elf_set_mach_from_flags
(bfd *);
+/* This is the condition under which finish_dynamic_symbol will be called.
+ If our finish_dynamic_symbol isn't called, we'll need to do something
+ about initializing any .plt and .got entries in relocate_section. */
+#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, SHARED, H) \
+ ((DYN) \
+ && ((SHARED) \
+ || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \
+ && ((H)->dynindx != -1 \
+ || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
+
/* This macro is to avoid lots of duplicated code in the body
of xxx_relocate_section() in the various elfxx-xxxx.c files. */
#define RELOC_FOR_GLOBAL_SYMBOL(info, input_bfd, input_section, rel, \
#define elf_hppa_reloc_final_type elf64_hppa_reloc_final_type
#define _bfd_elf_hppa_gen_reloc_type _bfd_elf64_hppa_gen_reloc_type
#define elf_hppa_relocate_section elf64_hppa_relocate_section
-#define bfd_elf_bfd_final_link bfd_elf64_bfd_final_link
#define elf_hppa_final_link elf64_hppa_final_link
#endif
#if ARCH_SIZE == 32
#define elf_hppa_reloc_final_type elf32_hppa_reloc_final_type
#define _bfd_elf_hppa_gen_reloc_type _bfd_elf32_hppa_gen_reloc_type
#define elf_hppa_relocate_section elf32_hppa_relocate_section
-#define bfd_elf_bfd_final_link bfd_elf32_bfd_final_link
#define elf_hppa_final_link elf32_hppa_final_link
#endif
info);
/* Invoke the regular ELF backend linker to do all the work. */
- retval = bfd_elf_bfd_final_link (abfd, info);
+ retval = bfd_elf_final_link (abfd, info);
elf_link_hash_traverse (elf_hash_table (info),
elf_hppa_remark_useless_dynamic_symbols,
h->type = STT_OBJECT;
if (info->shared
- && ! _bfd_elf_link_record_dynamic_symbol (info, h))
+ && ! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
h->type = STT_OBJECT;
if (info->shared
- && ! _bfd_elf_link_record_dynamic_symbol (info, h))
+ && ! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
elf_hash_table (info)->hgot = h;
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_MN10300_GNU_VTINHERIT:
- if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
return FALSE;
break;
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
case R_MN10300_GNU_VTENTRY:
- if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
return FALSE;
break;
case R_MN10300_GOT32:
/* Make sure this symbol is output as a dynamic symbol. */
if (h->dynindx == -1)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
/* Make sure this symbol is output as a dynamic symbol. */
if (h->dynindx == -1)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
struct elf_segment_map **pm;
struct elf_segment_map *m;
asection *last_hdr;
+ bfd_vma last_size;
unsigned int phdr_index;
bfd_vma maxpagesize;
asection **hdrpp;
segment when the start of the second section can be placed within
a few bytes of the end of the first section. */
last_hdr = NULL;
+ last_size = 0;
phdr_index = 0;
maxpagesize = get_elf_backend_data (abfd)->maxpagesize;
writable = FALSE;
segment. */
new_segment = TRUE;
}
- else if (BFD_ALIGN (last_hdr->lma + last_hdr->_raw_size, maxpagesize)
+ else if (BFD_ALIGN (last_hdr->lma + last_size, maxpagesize)
< BFD_ALIGN (hdr->lma, maxpagesize))
{
/* If putting this section in this segment would force us to
skip a page in the segment, then we need a new segment. */
new_segment = TRUE;
}
- else if ((last_hdr->flags & SEC_LOAD) == 0
- && (hdr->flags & SEC_LOAD) != 0)
+ else if ((last_hdr->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) == 0
+ && (hdr->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) != 0)
{
/* We don't want to put a loadable section after a
- nonloadable section in the same segment. */
+ nonloadable section in the same segment.
+ Consider .tbss sections as loadable for this purpose. */
new_segment = TRUE;
}
else if ((abfd->flags & D_PAGED) == 0)
}
else if (! writable
&& (hdr->flags & SEC_READONLY) == 0
- && (((last_hdr->lma + last_hdr->_raw_size - 1)
+ && (((last_hdr->lma + last_size - 1)
& ~(maxpagesize - 1))
!= (hdr->lma & ~(maxpagesize - 1))))
{
{
if ((hdr->flags & SEC_READONLY) == 0)
writable = TRUE;
- /* Ignore .tbss section for segment layout purposes. */
+ last_hdr = hdr;
+ /* .tbss sections effectively have zero size. */
if ((hdr->flags & (SEC_THREAD_LOCAL | SEC_LOAD)) != SEC_THREAD_LOCAL)
- last_hdr = hdr;
+ last_size = hdr->_raw_size;
+ else
+ last_size = 0;
continue;
}
writable = FALSE;
last_hdr = hdr;
+ /* .tbss sections effectively have zero size. */
+ if ((hdr->flags & (SEC_THREAD_LOCAL | SEC_LOAD)) != SEC_THREAD_LOCAL)
+ last_size = hdr->_raw_size;
+ else
+ last_size = 0;
phdr_index = i;
phdr_in_segment = FALSE;
}
bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
PARAMS ((bfd *, struct bfd_link_info *));
bfd_boolean bfd_elf32_arm_process_before_allocation
- PARAMS ((bfd *, struct bfd_link_info *, int));
+ PARAMS ((bfd *, struct bfd_link_info *, int, int));
#endif
#endif
+/* Used to build a map of a section. This is required for mixed-endian
+ code/data. */
+
+typedef struct elf32_elf_section_map
+{
+ bfd_vma vma;
+ char type;
+}
+elf32_arm_section_map;
+
+struct _arm_elf_section_data
+{
+ struct bfd_elf_section_data elf;
+ int mapcount;
+ elf32_arm_section_map *map;
+};
+
+#define elf32_arm_section_data(sec) \
+ ((struct _arm_elf_section_data *) elf_section_data (sec))
+
/* The ARM linker needs to keep track of the number of relocs that it
decides to copy in check_relocs for each symbol. This is so that
it can discard PC relative relocs if it doesn't need them when
length should be applied by the linker. */
int no_pipeline_knowledge;
+ /* Nonzero to output a BE8 image. */
+ int byteswap_code;
+
/* Short-cuts to get to dynamic linker sections. */
asection *sgot;
asection *sgotplt;
ret->arm_glue_size = 0;
ret->bfd_of_glue_owner = NULL;
ret->no_pipeline_knowledge = 0;
+ ret->byteswap_code = 0;
ret->sym_sec.abfd = NULL;
return &ret->root.root;
}
bfd_boolean
-bfd_elf32_arm_process_before_allocation (abfd, link_info, no_pipeline_knowledge)
+bfd_elf32_arm_process_before_allocation (abfd, link_info,
+ no_pipeline_knowledge,
+ byteswap_code)
bfd *abfd;
struct bfd_link_info *link_info;
int no_pipeline_knowledge;
+ int byteswap_code;
{
Elf_Internal_Shdr *symtab_hdr;
Elf_Internal_Rela *internal_relocs = NULL;
BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
globals->no_pipeline_knowledge = no_pipeline_knowledge;
+ if (byteswap_code && !bfd_big_endian (abfd))
+ {
+ _bfd_error_handler (
+ _("%s: BE8 images only valid in big-endian mode."),
+ bfd_archive_filename (abfd));
+ return FALSE;
+ }
+ globals->byteswap_code = byteswap_code;
/* Rummage around all the relocs and map the glue vectors. */
sec = abfd->sections;
return TRUE;
}
-/* This is the condition under which elf32_arm_finish_dynamic_symbol
- will be called from elflink.h. If elflink.h doesn't call our
- finish_dynamic_symbol routine, we'll need to do something about
- initializing any .plt and .got entries in elf32_arm_relocate_section
- and elf32_arm_final_link_relocate. */
-#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, SHARED, H) \
- ((DYN) \
- && ((SHARED) \
- || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \
- && ((H)->dynindx != -1 \
- || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
-
/* Perform a relocation as part of a final link. */
static bfd_reloc_status_type
return bfd_reloc_ok;
}
+ case R_ARM_ALU_PCREL7_0:
+ case R_ARM_ALU_PCREL15_8:
+ case R_ARM_ALU_PCREL23_15:
+ {
+ bfd_vma insn;
+ bfd_vma relocation;
+
+ insn = bfd_get_32 (input_bfd, hit_data);
+#if USE_REL
+ /* Extract the addend. */
+ addend = (insn & 0xff) << ((insn & 0xf00) >> 7);
+ signed_addend = addend;
+#endif
+ relocation = value + signed_addend;
+
+ relocation -= (input_section->output_section->vma
+ + input_section->output_offset
+ + rel->r_offset);
+ insn = (insn & ~0xfff)
+ | ((howto->bitpos << 7) & 0xf00)
+ | ((relocation >> howto->bitpos) & 0xff);
+ bfd_put_32 (input_bfd, value, hit_data);
+ }
+ return bfd_reloc_ok;
+
case R_ARM_GNU_VTINHERIT:
case R_ARM_GNU_VTENTRY:
return bfd_reloc_ok;
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_ARM_GNU_VTINHERIT:
- if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
return FALSE;
break;
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
case R_ARM_GNU_VTENTRY:
- if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
return FALSE;
break;
}
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
struct bfd_link_info * link_info ATTRIBUTE_UNUSED;
{
Elf_Internal_Ehdr * i_ehdrp; /* ELF file header, internal form. */
+ struct elf32_arm_link_hash_table *globals;
i_ehdrp = elf_elfheader (abfd);
i_ehdrp->e_ident[EI_OSABI] = ARM_ELF_OS_ABI_VERSION;
i_ehdrp->e_ident[EI_ABIVERSION] = ARM_ELF_ABI_VERSION;
+
+ if (link_info)
+ {
+ globals = elf32_arm_hash_table (link_info);
+ if (globals->byteswap_code)
+ i_ehdrp->e_flags |= EF_ARM_BE8;
+ }
}
static enum elf_reloc_type_class
return TRUE;
}
-void
+static void
elf32_arm_final_write_processing (abfd, linker)
bfd *abfd;
bfd_boolean linker ATTRIBUTE_UNUSED;
bfd_arm_update_notes (abfd, ARM_NOTE_SECTION);
}
+
+/* Called for each symbol. Builds a section map based on mapping symbols.
+ Does not alter any of the symbols. */
+
+static bfd_boolean
+elf32_arm_output_symbol_hook (struct bfd_link_info *info,
+ const char *name,
+ Elf_Internal_Sym *elfsym,
+ asection *input_sec,
+ struct elf_link_hash_entry *h ATTRIBUTE_UNUSED)
+{
+ int mapcount;
+ elf32_arm_section_map *map;
+ struct elf32_arm_link_hash_table *globals;
+
+ /* Only do this on final link. */
+ if (info->relocatable)
+ return TRUE;
+
+ /* Only build a map if we need to byteswap code. */
+ globals = elf32_arm_hash_table (info);
+ if (!globals->byteswap_code)
+ return TRUE;
+
+ /* We only want mapping symbols. */
+ if (name == NULL
+ || name[0] != '$'
+ || (name[1] != 'a'
+ && name[1] != 't'
+ && name[1] != 'd'))
+ return TRUE;
+
+ mapcount = ++(elf32_arm_section_data (input_sec)->mapcount);
+ map = elf32_arm_section_data (input_sec)->map;
+ /* TODO: This may be inefficient, but we probably don't usually have many
+ mapping symbols per section. */
+ map = bfd_realloc (map, mapcount * sizeof (elf32_arm_section_map));
+ elf32_arm_section_data (input_sec)->map = map;
+
+ map[mapcount - 1].vma = elfsym->st_value;
+ map[mapcount - 1].type = name[1];
+ return TRUE;
+}
+
+
+/* Allocate target specific section data. */
+
+static bfd_boolean
+elf32_arm_new_section_hook (bfd *abfd, asection *sec)
+{
+ struct _arm_elf_section_data *sdata;
+ bfd_size_type amt = sizeof (*sdata);
+
+ sdata = bfd_zalloc (abfd, amt);
+ if (sdata == NULL)
+ return FALSE;
+ sec->used_by_bfd = sdata;
+
+ return _bfd_elf_new_section_hook (abfd, sec);
+}
+
+
+/* Used to order a list of mapping symbols by address. */
+
+static int
+elf32_arm_compare_mapping (const void * a, const void * b)
+{
+ return ((const elf32_arm_section_map *) a)->vma
+ > ((const elf32_arm_section_map *) b)->vma;
+}
+
+
+/* Do code byteswapping. Return FALSE afterwards so that the section is
+ written out as normal. */
+
+static bfd_boolean
+elf32_arm_write_section (bfd *output_bfd ATTRIBUTE_UNUSED, asection *sec,
+ bfd_byte *contents)
+{
+ int mapcount;
+ elf32_arm_section_map *map;
+ bfd_vma ptr;
+ bfd_vma end;
+ bfd_vma offset;
+ bfd_byte tmp;
+ int i;
+
+ mapcount = elf32_arm_section_data (sec)->mapcount;
+ map = elf32_arm_section_data (sec)->map;
+
+ if (mapcount == 0)
+ return FALSE;
+
+ qsort (map, mapcount, sizeof (elf32_arm_section_map),
+ elf32_arm_compare_mapping);
+
+ offset = sec->output_section->vma + sec->output_offset;
+ ptr = map[0].vma - offset;
+ for (i = 0; i < mapcount; i++)
+ {
+ if (i == mapcount - 1)
+ end = bfd_section_size (output_bfd, sec);
+ else
+ end = map[i + 1].vma - offset;
+
+ switch (map[i].type)
+ {
+ case 'a':
+ /* Byte swap code words. */
+ while (ptr + 3 < end)
+ {
+ tmp = contents[ptr];
+ contents[ptr] = contents[ptr + 3];
+ contents[ptr + 3] = tmp;
+ tmp = contents[ptr + 1];
+ contents[ptr + 1] = contents[ptr + 2];
+ contents[ptr + 2] = tmp;
+ ptr += 4;
+ }
+ break;
+
+ case 't':
+ /* Byte swap code halfwords. */
+ while (ptr + 1 < end)
+ {
+ tmp = contents[ptr];
+ contents[ptr] = contents[ptr + 1];
+ contents[ptr + 1] = tmp;
+ ptr += 2;
+ }
+ break;
+
+ case 'd':
+ /* Leave data alone. */
+ break;
+ }
+ ptr = end;
+ }
+ free (map);
+ return FALSE;
+}
+
#define ELF_ARCH bfd_arch_arm
#define ELF_MACHINE_CODE EM_ARM
#ifdef __QNXTARGET__
#define bfd_elf32_bfd_link_hash_table_create elf32_arm_link_hash_table_create
#define bfd_elf32_bfd_reloc_type_lookup elf32_arm_reloc_type_lookup
#define bfd_elf32_find_nearest_line elf32_arm_find_nearest_line
+#define bfd_elf32_new_section_hook elf32_arm_new_section_hook
#define elf_backend_get_symbol_type elf32_arm_get_symbol_type
#define elf_backend_gc_mark_hook elf32_arm_gc_mark_hook
#define elf_backend_gc_sweep_hook elf32_arm_gc_sweep_hook
#define elf_backend_check_relocs elf32_arm_check_relocs
#define elf_backend_relocate_section elf32_arm_relocate_section
+#define elf_backend_write_section elf32_arm_write_section
#define elf_backend_adjust_dynamic_symbol elf32_arm_adjust_dynamic_symbol
#define elf_backend_create_dynamic_sections elf32_arm_create_dynamic_sections
#define elf_backend_finish_dynamic_symbol elf32_arm_finish_dynamic_symbol
#define elf_backend_finish_dynamic_sections elf32_arm_finish_dynamic_sections
+#define elf_backend_link_output_symbol_hook elf32_arm_output_symbol_hook
#define elf_backend_size_dynamic_sections elf32_arm_size_dynamic_sections
#define elf_backend_post_process_headers elf32_arm_post_process_headers
#define elf_backend_reloc_type_class elf32_arm_reloc_type_class
}
else
{
- bfd_boolean unresolved_reloc, warned;
-
- RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
- r_symndx, symtab_hdr, sym_hashes,
- h, sec, relocation,
- unresolved_reloc, warned);
+ h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+ while (h->root.type == bfd_link_hash_indirect
+ || h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+ if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ {
+ sec = h->root.u.def.section;
+ relocation = (h->root.u.def.value
+ + sec->output_section->vma + sec->output_offset);
+ }
+ else if (h->root.type == bfd_link_hash_undefweak)
+ relocation = 0;
+ else
+ {
+ if (!((*info->callbacks->undefined_symbol)
+ (info, h->root.root.string, input_bfd,
+ input_section, rel->r_offset, TRUE)))
+ return FALSE;
+ relocation = 0;
+ }
}
r = cr16c_elf_final_link_relocate (howto, input_bfd, output_bfd,
static bfd_boolean
elf32_cr16c_add_symbol_hook (bfd *abfd,
struct bfd_link_info *info ATTRIBUTE_UNUSED,
- Elf_Internal_Sym *sym,
+ const Elf_Internal_Sym *sym,
const char **namep ATTRIBUTE_UNUSED,
flagword *flagsp ATTRIBUTE_UNUSED,
asection **secp,
to this function. Note that we embed knowledge that "incoming"
.got goes after .got.plt in the output without padding (pointer
aligned). However, that knowledge is present in several other
- places too, here and in elflink.h at least. */
+ places too. */
bfd_vma got_offset
= (has_gotplt
? gotplt_offset
/* Make sure this symbol is output as a dynamic symbol. */
if (h->dynindx == -1)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
/* Make sure this symbol is output as a dynamic symbol. */
if (h->dynindx == -1)
{
- if (!bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (!bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_CRIS_GNU_VTINHERIT:
- if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
return FALSE;
break;
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
case R_CRIS_GNU_VTENTRY:
- if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
return FALSE;
break;
#define elf_backend_create_dynamic_sections \
_bfd_elf_create_dynamic_sections
#define bfd_elf32_bfd_final_link \
- _bfd_elf32_gc_common_final_link
+ bfd_elf_gc_common_final_link
#define elf_backend_hide_symbol elf_cris_hide_symbol
#define elf_backend_reloc_type_class elf_cris_reloc_type_class
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_D10V_GNU_VTINHERIT:
- if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
return FALSE;
break;
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
case R_D10V_GNU_VTENTRY:
- if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
return FALSE;
break;
}
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_DLX_GNU_VTINHERIT:
- if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
return FALSE;
break;
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
case R_DLX_GNU_VTENTRY:
- if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
return FALSE;
break;
}
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_FR30_GNU_VTINHERIT:
- if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
return FALSE;
break;
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
case R_FR30_GNU_VTENTRY:
- if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
return FALSE;
break;
}
/* Machine-specific: we want the symbol for executables as
well. */
- if (! _bfd_elf_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
elf_hash_table (info)->hgot = h;
h->type = STT_OBJECT;
/* Machine-specific: we want the symbol for executables as well. */
- if (! _bfd_elf_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
return TRUE;
h->type = STT_OBJECT;
if (! info->executable
- && ! _bfd_elf_link_record_dynamic_symbol (info, h))
+ && ! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
case STV_HIDDEN:
break;
default:
- bfd_elf32_link_record_dynamic_symbol (info, h);
+ bfd_elf_link_record_dynamic_symbol (info, h);
break;
}
picrel
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_FRV_GNU_VTINHERIT:
- if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
return FALSE;
break;
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
case R_FRV_GNU_VTENTRY:
- if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
return FALSE;
break;
}
/* ??? when elf_backend_relocate_section is not defined, elf32-target.h
defaults to using _bfd_generic_link_hash_table_create, but
- elflink.h:bfd_elf32_size_dynamic_sections uses
+ bfd_elf_size_dynamic_sections uses
dynobj = elf_hash_table (info)->dynobj;
and thus requires an elf hash table. */
#define bfd_elf32_bfd_link_hash_table_create _bfd_elf_link_hash_table_create
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_PARISC_GNU_VTINHERIT:
- if (!_bfd_elf32_gc_record_vtinherit (abfd, sec,
- &h->elf, rel->r_offset))
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, &h->elf, rel->r_offset))
return FALSE;
continue;
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
case R_PARISC_GNU_VTENTRY:
- if (!_bfd_elf32_gc_record_vtentry (abfd, sec,
- &h->elf, rel->r_addend))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, &h->elf, rel->r_addend))
return FALSE;
continue;
}
}
-/* This is the condition under which elf32_hppa_finish_dynamic_symbol
- will be called from elflink.h. If elflink.h doesn't call our
- finish_dynamic_symbol routine, we'll need to do something about
- initializing any .plt and .got entries in elf32_hppa_relocate_section. */
-#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, INFO, H) \
- ((DYN) \
- && ((INFO)->shared \
- || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \
- && ((H)->dynindx != -1 \
- || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
-
/* Adjust a symbol defined by a dynamic object and referenced by a
regular object. The current definition is in some section of the
dynamic object, but we're not including those sections. We have to
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0
&& h->type != STT_PARISC_MILLI)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
- if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, h))
+ if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info->shared, h))
{
/* Allocate these later. From this point on, h->plabel
means that the plt entry is only used by a plabel.
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0
&& h->type != STT_PARISC_MILLI)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0
&& h->type != STT_PARISC_MILLI)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
elf32_hppa_final_link (bfd *abfd, struct bfd_link_info *info)
{
/* Invoke the regular ELF linker to do all the work. */
- if (!bfd_elf32_bfd_final_link (abfd, info))
+ if (!bfd_elf_final_link (abfd, info))
return FALSE;
/* If we're producing a final executable, sort the contents of the
off = h->elf.got.offset;
dyn = htab->elf.dynamic_sections_created;
- if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, &h->elf))
+ if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared,
+ &h->elf))
{
/* If we aren't going to call finish_dynamic_symbol,
then we need to handle initialisation of the .got
if (h != NULL)
{
off = h->elf.plt.offset;
- if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, &h->elf))
+ if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info->shared,
+ &h->elf))
{
/* In a non-shared link, adjust_dynamic_symbols
isn't called for symbols forced local. We
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_386_GNU_VTINHERIT:
- if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
return FALSE;
break;
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
case R_386_GNU_VTENTRY:
- if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
return FALSE;
break;
return TRUE;
}
-/* This is the condition under which elf_i386_finish_dynamic_symbol
- will be called from elflink.h. If elflink.h doesn't call our
- finish_dynamic_symbol routine, we'll need to do something about
- initializing any .plt and .got entries in elf_i386_relocate_section. */
-#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, SHARED, H) \
- ((DYN) \
- && ((SHARED) \
- || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \
- && ((H)->dynindx != -1 \
- || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
-
/* Allocate space in .plt, .got and associated reloc sections for
dynamic relocs. */
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_IQ2000_GNU_VTINHERIT:
- if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
return FALSE;
break;
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
case R_IQ2000_GNU_VTENTRY:
- if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
return FALSE;
break;
h->type = STT_OBJECT;
if (info->shared
- && ! _bfd_elf_link_record_dynamic_symbol (info, h))
+ && ! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
return TRUE;
}
-/* This is the condition under which finish_dynamic_symbol will be called
- from elflink.h. If elflink.h doesn't call our finish_dynamic_symbol
- routine, we'll need to do something about initializing any .plt and .got
- entries in relocate_section. */
-#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, INFO, H) \
- ((DYN) \
- && ((INFO)->shared \
- || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \
- && ((H)->dynindx != -1 \
- || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
-
/* Allocate space in .plt, .got and associated reloc sections for
dynamic relocs. */
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
- if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, h))
+ if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info->shared, h))
{
asection *s = htab->splt;
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
h->got.offset = s->_raw_size;
s->_raw_size += 4;
dyn = htab->root.dynamic_sections_created;
- if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h))
+ if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h))
htab->srelgot->_raw_size += sizeof (Elf32_External_Rela);
}
else
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
|| r_type == R_M32R_GOT16_HI_ULO
|| r_type == R_M32R_GOT16_HI_SLO
|| r_type == R_M32R_GOT16_LO)
- && WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h)
+ && WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn,
+ info->shared, h)
&& (! info->shared
|| (! info->symbolic && h->dynindx != -1)
|| (h->elf_link_hash_flags
BFD_ASSERT (off != (bfd_vma) -1);
dyn = htab->root.dynamic_sections_created;
- if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h)
+ if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
|| (info->shared
&& (info->symbolic
|| h->dynindx == -1
Reconstruct it for later use during GC. */
case R_M32R_RELA_GNU_VTINHERIT:
case R_M32R_GNU_VTINHERIT:
- if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
return FALSE;
break;
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
case R_M32R_GNU_VTENTRY:
- if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
return FALSE;
break;
case R_M32R_RELA_GNU_VTENTRY:
- if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
return FALSE;
break;
}
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_M68HC11_GNU_VTINHERIT:
- if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
return FALSE;
break;
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
case R_M68HC11_GNU_VTENTRY:
- if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
return FALSE;
break;
}
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (!bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (!bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (!bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (!bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_68K_GNU_VTINHERIT:
- if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
return FALSE;
break;
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
case R_68K_GNU_VTENTRY:
- if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
return FALSE;
break;
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
return TRUE;
}
-/* This is the condition under which elf_m68k_finish_dynamic_symbol
- will be called from elflink.h. If elflink.h doesn't call our
- finish_dynamic_symbol routine, we'll need to do something about
- initializing any .plt and .got entries in elf_m68k_relocate_section. */
-#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, SHARED, H) \
- ((DYN) \
- && ((SHARED) \
- || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \
- && ((H)->dynindx != -1 \
- || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
-
/* Set the sizes of the dynamic sections. */
static bfd_boolean
_bfd_elf_create_dynamic_sections
#define bfd_elf32_bfd_link_hash_table_create \
elf_m68k_link_hash_table_create
-#define bfd_elf32_bfd_final_link _bfd_elf32_gc_common_final_link
+#define bfd_elf32_bfd_final_link bfd_elf_gc_common_final_link
#define elf_backend_check_relocs elf_m68k_check_relocs
#define elf_backend_adjust_dynamic_symbol \
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_MCORE_GNU_VTINHERIT:
- if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
return FALSE;
break;
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
case R_MCORE_GNU_VTENTRY:
- if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
return FALSE;
break;
}
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_OPENRISC_GNU_VTINHERIT:
- if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
return FALSE;
break;
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
case R_OPENRISC_GNU_VTENTRY:
- if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
return FALSE;
break;
}
/* Make sure this symbol is output as a dynamic symbol. */
if (h->dynindx == -1)
{
- if (! _bfd_elf_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
lsect->sym_hash = h;
if (info->shared
- && ! _bfd_elf_link_record_dynamic_symbol (info, h))
+ && ! bfd_elf_link_record_dynamic_symbol (info, h))
return NULL;
}
return TRUE;
}
\f
-/* This is the condition under which finish_dynamic_symbol will be
- called from elflink.h. If elflink.h doesn't call our
- finish_dynamic_symbol routine, we'll need to do something about
- initializing any .plt and .got entries in relocate_section. */
-#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, SHARED, H) \
- ((DYN) \
- && ((SHARED) \
- || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \
- && ((H)->dynindx != -1 \
- || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
-
/* Of those relocs that might be copied as dynamic relocs, this macro
selects those that must be copied when linking a shared library,
even when the symbol is local. */
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
if (eh->elf.dynindx == -1
&& (eh->elf.elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (!bfd_elf32_link_record_dynamic_symbol (info, &eh->elf))
+ if (!bfd_elf_link_record_dynamic_symbol (info, &eh->elf))
return FALSE;
}
&& h->root.type == bfd_link_hash_undefweak
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
}
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf64_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_PPC_GNU_VTINHERIT:
- if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
return FALSE;
break;
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
case R_PPC_GNU_VTENTRY:
- if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
return FALSE;
break;
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_390_GNU_VTINHERIT:
- if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
return FALSE;
break;
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
case R_390_GNU_VTENTRY:
- if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
return FALSE;
break;
return TRUE;
}
-/* This is the condition under which elf_s390_finish_dynamic_symbol
- will be called from elflink.h. If elflink.h doesn't call our
- finish_dynamic_symbol routine, we'll need to do something about
- initializing any .plt and .got entries in elf_s390_relocate_section. */
-#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, SHARED, H) \
- ((DYN) \
- && ((SHARED) \
- || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \
- && ((H)->dynindx != -1 \
- || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
-
/* Allocate space in .plt, .got and associated reloc sections for
dynamic relocs. */
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
h->type = STT_OBJECT;
if (info->shared
- && ! _bfd_elf_link_record_dynamic_symbol (info, h))
+ && ! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
return TRUE;
}
-/* This is the condition under which sh_elf_finish_dynamic_symbol
- will be called from elflink.h. If elflink.h doesn't call our
- finish_dynamic_symbol routine, we'll need to do something about
- initializing any .plt and .got entries in sh_elf_relocate_section. */
-#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, SHARED, H) \
- ((DYN) \
- && ((SHARED) \
- || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \
- && ((H)->dynindx != -1 \
- || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
-
/* Allocate space in .plt, .got and associated reloc sections for
dynamic relocs. */
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_SH_GNU_VTINHERIT:
- if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
return FALSE;
break;
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
case R_SH_GNU_VTENTRY:
- if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
return FALSE;
break;
break;
case R_SPARC_GNU_VTINHERIT:
- if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
return FALSE;
break;
case R_SPARC_GNU_VTENTRY:
- if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
return FALSE;
break;
return TRUE;
}
-/* This is the condition under which finish_dynamic_symbol will be called
- from elflink.h. If elflink.h doesn't call our finish_dynamic_symbol
- routine, we'll need to do something about initializing any .plt and .got
- entries in relocate_section. */
-#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, INFO, H) \
- ((DYN) \
- && ((INFO)->shared \
- || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \
- && ((H)->dynindx != -1 \
- || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
-
/* Allocate space in .plt, .got and associated reloc sections for
dynamic relocs. */
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
- if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, h))
+ if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info->shared, h))
{
asection *s = htab->splt;
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
htab->srelgot->_raw_size += sizeof (Elf32_External_Rela);
else if (tls_type == GOT_TLS_GD)
htab->srelgot->_raw_size += 2 * sizeof (Elf32_External_Rela);
- else if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h))
+ else if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h))
htab->srelgot->_raw_size += sizeof (Elf32_External_Rela);
}
else
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
BFD_ASSERT (off != (bfd_vma) -1);
dyn = elf_hash_table (info)->dynamic_sections_created;
- if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h)
+ if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
|| (info->shared
&& (info->symbolic
|| h->dynindx == -1
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_V850_GNU_VTINHERIT:
- if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
return FALSE;
break;
/* This relocation describes which C++ vtable entries
are actually used. Record for later use during GC. */
case R_V850_GNU_VTENTRY:
- if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
return FALSE;
break;
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_VAX_GNU_VTINHERIT:
- if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
return FALSE;
break;
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
case R_VAX_GNU_VTENTRY:
- if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
return FALSE;
break;
/* Make sure this symbol is output as a dynamic symbol. */
if (h->dynindx == -1)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
/* Make sure this symbol is output as a dynamic symbol. */
if (h->dynindx == -1)
{
- if (!bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (!bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
_bfd_elf_create_dynamic_sections
#define bfd_elf32_bfd_link_hash_table_create \
elf_vax_link_hash_table_create
-#define bfd_elf32_bfd_final_link _bfd_elf32_gc_common_final_link
+#define bfd_elf32_bfd_final_link bfd_elf_gc_common_final_link
#define elf_backend_check_relocs elf_vax_check_relocs
#define elf_backend_adjust_dynamic_symbol \
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_XSTORMY16_GNU_VTINHERIT:
- if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
return FALSE;
break;
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
case R_XSTORMY16_GNU_VTENTRY:
- if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
return FALSE;
break;
}
case R_XTENSA_GNU_VTINHERIT:
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
- if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
return FALSE;
break;
case R_XTENSA_GNU_VTENTRY:
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
- if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
return FALSE;
break;
while (cookie->rel < cookie->relend
&& cookie->rel->r_offset == offset)
{
- if (_bfd_elf32_reloc_symbol_deleted_p (offset, cookie))
+ if (bfd_elf_reloc_symbol_deleted_p (offset, cookie))
{
/* Remove the table entry. (If the reloc type is NONE, then
the entry has already been merged with another and deleted
#define elf_info_to_howto elf_xtensa_info_to_howto_rela
-#define bfd_elf32_bfd_final_link bfd_elf32_bfd_final_link
#define bfd_elf32_bfd_merge_private_bfd_data elf_xtensa_merge_private_bfd_data
#define bfd_elf32_new_section_hook elf_xtensa_new_section_hook
#define bfd_elf32_bfd_print_private_bfd_data elf_xtensa_print_private_bfd_data
h->type = STT_OBJECT;
if (info->shared
- && ! _bfd_elf_link_record_dynamic_symbol (info, h))
+ && ! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
s = bfd_make_section (abfd, ".rela.plt");
h->type = STT_OBJECT;
if (info->shared
- && ! _bfd_elf_link_record_dynamic_symbol (info, h))
+ && ! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
elf_hash_table (info)->hgot = h;
}
/* Invoke the regular ELF backend linker to do all the work. */
- if (! bfd_elf64_bfd_final_link (abfd, info))
+ if (! bfd_elf_final_link (abfd, info))
return FALSE;
/* Now write out the computed sections. */
section symbol for this section ends up in the dynamic
symbol table. */
if (info->shared && dynrel_type == R_PARISC_FPTR64
- && ! (_bfd_elf64_link_record_local_dynamic_symbol
+ && ! (bfd_elf_link_record_local_dynamic_symbol
(info, abfd, sec_symndx)))
return FALSE;
}
bfd *owner;
owner = (h ? h->root.u.def.section->owner : dyn_h->owner);
- if (! (_bfd_elf64_link_record_local_dynamic_symbol
+ if (! (bfd_elf_link_record_local_dynamic_symbol
(x->info, owner, dyn_h->sym_indx)))
return FALSE;
}
bfd *owner;
owner = (h ? h->root.u.def.section->owner : dyn_h->owner);
- if (!_bfd_elf64_link_record_local_dynamic_symbol
+ if (!bfd_elf_link_record_local_dynamic_symbol
(x->info, owner, dyn_h->sym_indx))
return FALSE;
}
nh->root.u.def.value = h->root.u.def.value;
nh->root.u.def.section = h->root.u.def.section;
- if (! bfd_elf64_link_record_dynamic_symbol (x->info, nh))
+ if (! bfd_elf_link_record_dynamic_symbol (x->info, nh))
return FALSE;
}
the symbol need only be added once. */
if (dyn_h->h == 0
|| (dyn_h->h->dynindx == -1 && dyn_h->h->type != STT_PARISC_MILLI))
- if (!_bfd_elf64_link_record_local_dynamic_symbol
+ if (!bfd_elf_link_record_local_dynamic_symbol
(x->info, rent->sec->owner, dyn_h->sym_indx))
return FALSE;
}
sec = local_sections [r_symndx];
relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
- name = bfd_elf_string_from_elf_section
- (input_bfd, symtab_hdr->sh_link, sym->st_name);
- name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
+ name = bfd_elf_string_from_elf_section (input_bfd,
+ symtab_hdr->sh_link,
+ sym->st_name);
+ if (name == NULL)
+ name = bfd_section_name (input_bfd, sec);
}
else
{
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
unresolved_reloc, undefined_signalled);
+ name = h->root.root.string;
}
r = mmix_final_link_relocate (howto, input_section,
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_MMIX_GNU_VTINHERIT:
- if (!_bfd_elf64_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
return FALSE;
break;
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
case R_MMIX_GNU_VTENTRY:
- if (!_bfd_elf64_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
return FALSE;
break;
}
--abfd->section_count;
}
- if (! bfd_elf64_bfd_final_link (abfd, info))
+ if (! bfd_elf_final_link (abfd, info))
return FALSE;
/* Since this section is marked SEC_LINKER_CREATED, it isn't output by
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_PPC64_GNU_VTINHERIT:
- if (!_bfd_elf64_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
return FALSE;
break;
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
case R_PPC64_GNU_VTENTRY:
- if (!_bfd_elf64_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
return FALSE;
break;
&& ELF_ST_VISIBILITY (fdh->elf.other) == STV_DEFAULT)))
{
if (fdh->elf.dynindx == -1)
- if (! bfd_elf64_link_record_dynamic_symbol (info, &fdh->elf))
+ if (! bfd_elf_link_record_dynamic_symbol (info, &fdh->elf))
return FALSE;
fdh->elf.elf_link_hash_flags
|= (fh->elf.elf_link_hash_flags & (ELF_LINK_HASH_REF_REGULAR
return TRUE;
}
-/* This is the condition under which ppc64_elf_finish_dynamic_symbol
- will be called from elflink.h. If elflink.h doesn't call our
- finish_dynamic_symbol routine, we'll need to do something about
- initializing any .plt and .got entries in ppc64_elf_relocate_section. */
-#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, SHARED, H) \
- ((DYN) \
- && ((SHARED) \
- || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \
- && ((H)->dynindx != -1 \
- || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
-
/* Allocate space in .plt, .got and associated reloc sections for
dynamic relocs. */
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf64_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf64_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_390_GNU_VTINHERIT:
- if (!_bfd_elf64_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
return FALSE;
break;
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
case R_390_GNU_VTENTRY:
- if (!_bfd_elf64_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
return FALSE;
break;
return TRUE;
}
-/* This is the condition under which elf_s390_finish_dynamic_symbol
- will be called from elflink.h. If elflink.h doesn't call our
- finish_dynamic_symbol routine, we'll need to do something about
- initializing any .plt and .got entries in elf_s390_relocate_section. */
-#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, SHARED, H) \
- ((DYN) \
- && ((SHARED) \
- || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \
- && ((H)->dynindx != -1 \
- || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
-
/* Allocate space in .plt, .got and associated reloc sections for
dynamic relocs. */
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf64_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf64_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf64_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_SH_GNU_VTINHERIT:
- if (!_bfd_elf64_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
return FALSE;
break;
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
case R_SH_GNU_VTENTRY:
- if (!_bfd_elf64_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
return FALSE;
break;
/* Make sure this symbol is output as a dynamic symbol. */
if (h->dynindx == -1)
{
- if (! bfd_elf64_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
/* Make sure this symbol is output as a dynamic symbol. */
if (h->dynindx == -1)
{
- if (! bfd_elf64_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
h->type = STT_OBJECT;
if (info->shared
- && ! _bfd_elf_link_record_dynamic_symbol (info, h))
+ && ! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
/* Make sure this symbol is output as a dynamic symbol. */
if (h->dynindx == -1)
{
- if (! bfd_elf64_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
/* Make sure this symbol is output as a dynamic symbol. */
if (h->dynindx == -1)
{
- if (! bfd_elf64_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
/* Make sure this symbol is output as a dynamic symbol. */
if (h->dynindx == -1)
{
- if (! bfd_elf64_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
return TRUE;
}
\f
-/* This is the condition under which finish_dynamic_symbol will be called
- from elflink.h. If elflink.h doesn't call our finish_dynamic_symbol
- routine, we'll need to do something about initializing any .plt and
- .got entries in relocate_section. */
-#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, INFO, H) \
- ((DYN) \
- && ((INFO)->shared \
- || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \
- && ((H)->dynindx != -1 \
- || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
-
/* Relocate a SPARC64 ELF section. */
static bfd_boolean
BFD_ASSERT (off != (bfd_vma) -1);
dyn = elf_hash_table (info)->dynamic_sections_created;
- if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h)
+ if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
|| (info->shared
&& (info->symbolic
|| h->dynindx == -1
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_X86_64_GNU_VTINHERIT:
- if (!_bfd_elf64_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
return FALSE;
break;
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
case R_X86_64_GNU_VTENTRY:
- if (!_bfd_elf64_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
return FALSE;
break;
return TRUE;
}
-/* This is the condition under which elf64_x86_64_finish_dynamic_symbol
- will be called from elflink.h. If elflink.h doesn't call our
- finish_dynamic_symbol routine, we'll need to do something about
- initializing any .plt and .got entries in elf64_x86_64_relocate_section. */
-#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, SHARED, H) \
- ((DYN) \
- && ((SHARED) \
- || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \
- && ((H)->dynindx != -1 \
- || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
-
/* Allocate space in .plt, .got and associated reloc sections for
dynamic relocs. */
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf64_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf64_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf64_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
0, /* dst_mask */
FALSE), /* pcrel_offset */
+ HOWTO (R_ARM_ALU_PCREL7_0, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 12, /* bitsize */
+ TRUE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont,/* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_ARM_ALU_PCREL_7_0", /* name */
+ FALSE, /* partial_inplace */
+ 0x00000fff, /* src_mask */
+ 0x00000fff, /* dst_mask */
+ TRUE), /* pcrel_offset */
+
+ HOWTO (R_ARM_ALU_PCREL15_8, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 12, /* bitsize */
+ TRUE, /* pc_relative */
+ 8, /* bitpos */
+ complain_overflow_dont,/* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_ARM_ALU_PCREL_15_8",/* name */
+ FALSE, /* partial_inplace */
+ 0x00000fff, /* src_mask */
+ 0x00000fff, /* dst_mask */
+ TRUE), /* pcrel_offset */
+
+ HOWTO (R_ARM_ALU_PCREL23_15, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 12, /* bitsize */
+ TRUE, /* pc_relative */
+ 16, /* bitpos */
+ complain_overflow_dont,/* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_ARM_ALU_PCREL_23_15",/* name */
+ FALSE, /* partial_inplace */
+ 0x00000fff, /* src_mask */
+ 0x00000fff, /* dst_mask */
+ TRUE), /* pcrel_offset */
};
/* GNU extension to record C++ vtable hierarchy */
#define elf_write_out_phdrs NAME(bfd_elf,write_out_phdrs)
#define elf_write_relocs NAME(bfd_elf,write_relocs)
#define elf_slurp_reloc_table NAME(bfd_elf,slurp_reloc_table)
-#define elf_bfd_discard_info NAME(bfd_elf,discard_info)
-#define elf_reloc_symbol_deleted_p NAME(_bfd_elf,reloc_symbol_deleted_p)
-#define elf_link_record_dynamic_symbol _bfd_elf_link_record_dynamic_symbol
-#define elf_bfd_final_link NAME(bfd_elf,bfd_final_link)
-#define elf_gc_sections NAME(_bfd_elf,gc_sections)
-#define elf_gc_common_finalize_got_offsets \
- NAME(_bfd_elf,gc_common_finalize_got_offsets)
-#define elf_gc_common_final_link NAME(_bfd_elf,gc_common_final_link)
-#define elf_gc_record_vtinherit NAME(_bfd_elf,gc_record_vtinherit)
-#define elf_gc_record_vtentry NAME(_bfd_elf,gc_record_vtentry)
-#define elf_link_record_local_dynamic_symbol \
- NAME(_bfd_elf,link_record_local_dynamic_symbol)
#if ARCH_SIZE == 64
#define ELF_R_INFO(X,Y) ELF64_R_INFO(X,Y)
#define LOG_FILE_ALIGN 2
#endif
-#define elf_stringtab_init _bfd_elf_stringtab_init
-
-#define section_from_elf_index bfd_section_from_elf_index
-
#ifdef DEBUG
static void elf_debug_section (int, Elf_Internal_Shdr *);
static void elf_debug_file (Elf_Internal_Ehdr *);
else if (isym->st_shndx < SHN_LORESERVE
|| isym->st_shndx > SHN_HIRESERVE)
{
- sym->symbol.section = section_from_elf_index (abfd,
- isym->st_shndx);
+ sym->symbol.section = bfd_section_from_elf_index (abfd,
+ isym->st_shndx);
if (sym->symbol.section == NULL)
{
/* This symbol is in a section for which we did not
}
\f
#include "elfcore.h"
-#include "elflink.h"
\f
/* Size-dependent data and functions. */
const struct elf_size_info NAME(_bfd_elf,size_info) = {
h->type = STT_OBJECT;
if (! info->executable
- && ! _bfd_elf_link_record_dynamic_symbol (info, h))
+ && ! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
elf_hash_table (info)->hgot = h;
h->type = STT_OBJECT;
if (! info->executable
- && ! _bfd_elf_link_record_dynamic_symbol (info, h))
+ && ! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
s = bfd_make_section (abfd, ".hash");
h->type = STT_OBJECT;
if (! info->executable
- && ! _bfd_elf_link_record_dynamic_symbol (info, h))
+ && ! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
one. */
bfd_boolean
-_bfd_elf_link_record_dynamic_symbol (struct bfd_link_info *info,
- struct elf_link_hash_entry *h)
+bfd_elf_link_record_dynamic_symbol (struct bfd_link_info *info,
+ struct elf_link_hash_entry *h)
{
if (h->dynindx == -1)
{
|| info->shared)
&& h->dynindx == -1)
{
- if (! _bfd_elf_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
/* If this is a weak defined symbol, and we know a corresponding
if (h->weakdef != NULL
&& h->weakdef->dynindx == -1)
{
- if (! _bfd_elf_link_record_dynamic_symbol (info, h->weakdef))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h->weakdef))
return FALSE;
}
}
in a discarded section, eg. a discarded link-once section symbol. */
int
-elf_link_record_local_dynamic_symbol (struct bfd_link_info *info,
- bfd *input_bfd,
- long input_indx)
+bfd_elf_link_record_local_dynamic_symbol (struct bfd_link_info *info,
+ bfd *input_bfd,
+ long input_indx)
{
bfd_size_type amt;
struct elf_link_local_dynamic_entry *entry;
FIXME: Should we check type and size for protected symbol? */
if (ELF_ST_VISIBILITY (h->other) == STV_PROTECTED)
- return _bfd_elf_link_record_dynamic_symbol (info, h);
+ return bfd_elf_link_record_dynamic_symbol (info, h);
else
return TRUE;
}
& (ELF_LINK_HASH_REF_REGULAR
| ELF_LINK_HASH_DEF_REGULAR))
{
- if (! _bfd_elf_link_record_dynamic_symbol (info, hi))
+ if (! bfd_elf_link_record_dynamic_symbol (info, hi))
return FALSE;
}
}
if (!eif->verdefs)
{
doit:
- if (! _bfd_elf_link_record_dynamic_symbol (eif->info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (eif->info, h))
{
eif->failed = TRUE;
return FALSE;
&& ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
|| (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0))
{
- if (! _bfd_elf_link_record_dynamic_symbol (eif->info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (eif->info, h))
{
eif->failed = TRUE;
return FALSE;
if (dynsym && h->dynindx == -1)
{
- if (! _bfd_elf_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
goto error_free_vers;
if (h->weakdef != NULL
&& ! new_weakdef
&& h->weakdef->dynindx == -1)
{
- if (! _bfd_elf_link_record_dynamic_symbol (info, h->weakdef))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h->weakdef))
goto error_free_vers;
}
}
there as well. */
if (hlook->dynindx != -1 && h->dynindx == -1)
{
- if (! _bfd_elf_link_record_dynamic_symbol (info,
- h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
goto error_return;
}
real definition and the weak definition. */
if (h->dynindx != -1 && hlook->dynindx == -1)
{
- if (! _bfd_elf_link_record_dynamic_symbol (info,
- hlook))
+ if (! bfd_elf_link_record_dynamic_symbol (info, hlook))
goto error_return;
}
break;
h->type = STT_OBJECT;
h->verinfo.vertree = t;
- if (! _bfd_elf_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
def.vd_version = VER_DEF_CURRENT;
return TRUE;
}
+
+/* Final phase of ELF linker. */
+
+/* A structure we use to avoid passing large numbers of arguments. */
+
+struct elf_final_link_info
+{
+ /* General link information. */
+ struct bfd_link_info *info;
+ /* Output BFD. */
+ bfd *output_bfd;
+ /* Symbol string table. */
+ struct bfd_strtab_hash *symstrtab;
+ /* .dynsym section. */
+ asection *dynsym_sec;
+ /* .hash section. */
+ asection *hash_sec;
+ /* symbol version section (.gnu.version). */
+ asection *symver_sec;
+ /* Buffer large enough to hold contents of any section. */
+ bfd_byte *contents;
+ /* Buffer large enough to hold external relocs of any section. */
+ void *external_relocs;
+ /* Buffer large enough to hold internal relocs of any section. */
+ Elf_Internal_Rela *internal_relocs;
+ /* Buffer large enough to hold external local symbols of any input
+ BFD. */
+ bfd_byte *external_syms;
+ /* And a buffer for symbol section indices. */
+ Elf_External_Sym_Shndx *locsym_shndx;
+ /* Buffer large enough to hold internal local symbols of any input
+ BFD. */
+ Elf_Internal_Sym *internal_syms;
+ /* Array large enough to hold a symbol index for each local symbol
+ of any input BFD. */
+ long *indices;
+ /* Array large enough to hold a section pointer for each local
+ symbol of any input BFD. */
+ asection **sections;
+ /* Buffer to hold swapped out symbols. */
+ bfd_byte *symbuf;
+ /* And one for symbol section indices. */
+ Elf_External_Sym_Shndx *symshndxbuf;
+ /* Number of swapped out symbols in buffer. */
+ size_t symbuf_count;
+ /* Number of symbols which fit in symbuf. */
+ size_t symbuf_size;
+ /* And same for symshndxbuf. */
+ size_t shndxbuf_size;
+};
+
+/* This struct is used to pass information to elf_link_output_extsym. */
+
+struct elf_outext_info
+{
+ bfd_boolean failed;
+ bfd_boolean localsyms;
+ struct elf_final_link_info *finfo;
+};
+
+/* When performing a relocatable link, the input relocations are
+ preserved. But, if they reference global symbols, the indices
+ referenced must be updated. Update all the relocations in
+ REL_HDR (there are COUNT of them), using the data in REL_HASH. */
+
+static void
+elf_link_adjust_relocs (bfd *abfd,
+ Elf_Internal_Shdr *rel_hdr,
+ unsigned int count,
+ struct elf_link_hash_entry **rel_hash)
+{
+ unsigned int i;
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ bfd_byte *erela;
+ void (*swap_in) (bfd *, const bfd_byte *, Elf_Internal_Rela *);
+ void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *);
+ bfd_vma r_type_mask;
+ int r_sym_shift;
+
+ if (rel_hdr->sh_entsize == bed->s->sizeof_rel)
+ {
+ swap_in = bed->s->swap_reloc_in;
+ swap_out = bed->s->swap_reloc_out;
+ }
+ else if (rel_hdr->sh_entsize == bed->s->sizeof_rela)
+ {
+ swap_in = bed->s->swap_reloca_in;
+ swap_out = bed->s->swap_reloca_out;
+ }
+ else
+ abort ();
+
+ if (bed->s->int_rels_per_ext_rel > MAX_INT_RELS_PER_EXT_REL)
+ abort ();
+
+ if (bed->s->arch_size == 32)
+ {
+ r_type_mask = 0xff;
+ r_sym_shift = 8;
+ }
+ else
+ {
+ r_type_mask = 0xffffffff;
+ r_sym_shift = 32;
+ }
+
+ erela = rel_hdr->contents;
+ for (i = 0; i < count; i++, rel_hash++, erela += rel_hdr->sh_entsize)
+ {
+ Elf_Internal_Rela irela[MAX_INT_RELS_PER_EXT_REL];
+ unsigned int j;
+
+ if (*rel_hash == NULL)
+ continue;
+
+ BFD_ASSERT ((*rel_hash)->indx >= 0);
+
+ (*swap_in) (abfd, erela, irela);
+ for (j = 0; j < bed->s->int_rels_per_ext_rel; j++)
+ irela[j].r_info = ((bfd_vma) (*rel_hash)->indx << r_sym_shift
+ | (irela[j].r_info & r_type_mask));
+ (*swap_out) (abfd, irela, erela);
+ }
+}
+
+struct elf_link_sort_rela
+{
+ union {
+ bfd_vma offset;
+ bfd_vma sym_mask;
+ } u;
+ enum elf_reloc_type_class type;
+ /* We use this as an array of size int_rels_per_ext_rel. */
+ Elf_Internal_Rela rela[1];
+};
+
+static int
+elf_link_sort_cmp1 (const void *A, const void *B)
+{
+ const struct elf_link_sort_rela *a = A;
+ const struct elf_link_sort_rela *b = B;
+ int relativea, relativeb;
+
+ relativea = a->type == reloc_class_relative;
+ relativeb = b->type == reloc_class_relative;
+
+ if (relativea < relativeb)
+ return 1;
+ if (relativea > relativeb)
+ return -1;
+ if ((a->rela->r_info & a->u.sym_mask) < (b->rela->r_info & b->u.sym_mask))
+ return -1;
+ if ((a->rela->r_info & a->u.sym_mask) > (b->rela->r_info & b->u.sym_mask))
+ return 1;
+ if (a->rela->r_offset < b->rela->r_offset)
+ return -1;
+ if (a->rela->r_offset > b->rela->r_offset)
+ return 1;
+ return 0;
+}
+
+static int
+elf_link_sort_cmp2 (const void *A, const void *B)
+{
+ const struct elf_link_sort_rela *a = A;
+ const struct elf_link_sort_rela *b = B;
+ int copya, copyb;
+
+ if (a->u.offset < b->u.offset)
+ return -1;
+ if (a->u.offset > b->u.offset)
+ return 1;
+ copya = (a->type == reloc_class_copy) * 2 + (a->type == reloc_class_plt);
+ copyb = (b->type == reloc_class_copy) * 2 + (b->type == reloc_class_plt);
+ if (copya < copyb)
+ return -1;
+ if (copya > copyb)
+ return 1;
+ if (a->rela->r_offset < b->rela->r_offset)
+ return -1;
+ if (a->rela->r_offset > b->rela->r_offset)
+ return 1;
+ return 0;
+}
+
+static size_t
+elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
+{
+ asection *reldyn;
+ bfd_size_type count, size;
+ size_t i, ret, sort_elt, ext_size;
+ bfd_byte *sort, *s_non_relative, *p;
+ struct elf_link_sort_rela *sq;
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ int i2e = bed->s->int_rels_per_ext_rel;
+ void (*swap_in) (bfd *, const bfd_byte *, Elf_Internal_Rela *);
+ void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *);
+ struct bfd_link_order *lo;
+ bfd_vma r_sym_mask;
+
+ reldyn = bfd_get_section_by_name (abfd, ".rela.dyn");
+ if (reldyn == NULL || reldyn->_raw_size == 0)
+ {
+ reldyn = bfd_get_section_by_name (abfd, ".rel.dyn");
+ if (reldyn == NULL || reldyn->_raw_size == 0)
+ return 0;
+ ext_size = bed->s->sizeof_rel;
+ swap_in = bed->s->swap_reloc_in;
+ swap_out = bed->s->swap_reloc_out;
+ }
+ else
+ {
+ ext_size = bed->s->sizeof_rela;
+ swap_in = bed->s->swap_reloca_in;
+ swap_out = bed->s->swap_reloca_out;
+ }
+ count = reldyn->_raw_size / ext_size;
+
+ size = 0;
+ for (lo = reldyn->link_order_head; lo != NULL; lo = lo->next)
+ if (lo->type == bfd_indirect_link_order)
+ {
+ asection *o = lo->u.indirect.section;
+ size += o->_raw_size;
+ }
+
+ if (size != reldyn->_raw_size)
+ return 0;
+
+ sort_elt = (sizeof (struct elf_link_sort_rela)
+ + (i2e - 1) * sizeof (Elf_Internal_Rela));
+ sort = bfd_zmalloc (sort_elt * count);
+ if (sort == NULL)
+ {
+ (*info->callbacks->warning)
+ (info, _("Not enough memory to sort relocations"), 0, abfd, 0, 0);
+ return 0;
+ }
+
+ if (bed->s->arch_size == 32)
+ r_sym_mask = ~(bfd_vma) 0xff;
+ else
+ r_sym_mask = ~(bfd_vma) 0xffffffff;
+
+ for (lo = reldyn->link_order_head; lo != NULL; lo = lo->next)
+ if (lo->type == bfd_indirect_link_order)
+ {
+ bfd_byte *erel, *erelend;
+ asection *o = lo->u.indirect.section;
+
+ erel = o->contents;
+ erelend = o->contents + o->_raw_size;
+ p = sort + o->output_offset / ext_size * sort_elt;
+ while (erel < erelend)
+ {
+ struct elf_link_sort_rela *s = (struct elf_link_sort_rela *) p;
+ (*swap_in) (abfd, erel, s->rela);
+ s->type = (*bed->elf_backend_reloc_type_class) (s->rela);
+ s->u.sym_mask = r_sym_mask;
+ p += sort_elt;
+ erel += ext_size;
+ }
+ }
+
+ qsort (sort, count, sort_elt, elf_link_sort_cmp1);
+
+ for (i = 0, p = sort; i < count; i++, p += sort_elt)
+ {
+ struct elf_link_sort_rela *s = (struct elf_link_sort_rela *) p;
+ if (s->type != reloc_class_relative)
+ break;
+ }
+ ret = i;
+ s_non_relative = p;
+
+ sq = (struct elf_link_sort_rela *) s_non_relative;
+ for (; i < count; i++, p += sort_elt)
+ {
+ struct elf_link_sort_rela *sp = (struct elf_link_sort_rela *) p;
+ if (((sp->rela->r_info ^ sq->rela->r_info) & r_sym_mask) != 0)
+ sq = sp;
+ sp->u.offset = sq->rela->r_offset;
+ }
+
+ qsort (s_non_relative, count - ret, sort_elt, elf_link_sort_cmp2);
+
+ for (lo = reldyn->link_order_head; lo != NULL; lo = lo->next)
+ if (lo->type == bfd_indirect_link_order)
+ {
+ bfd_byte *erel, *erelend;
+ asection *o = lo->u.indirect.section;
+
+ erel = o->contents;
+ erelend = o->contents + o->_raw_size;
+ p = sort + o->output_offset / ext_size * sort_elt;
+ while (erel < erelend)
+ {
+ struct elf_link_sort_rela *s = (struct elf_link_sort_rela *) p;
+ (*swap_out) (abfd, s->rela, erel);
+ p += sort_elt;
+ erel += ext_size;
+ }
+ }
+
+ free (sort);
+ *psec = reldyn;
+ return ret;
+}
+
+/* Flush the output symbols to the file. */
+
+static bfd_boolean
+elf_link_flush_output_syms (struct elf_final_link_info *finfo,
+ const struct elf_backend_data *bed)
+{
+ if (finfo->symbuf_count > 0)
+ {
+ Elf_Internal_Shdr *hdr;
+ file_ptr pos;
+ bfd_size_type amt;
+
+ hdr = &elf_tdata (finfo->output_bfd)->symtab_hdr;
+ pos = hdr->sh_offset + hdr->sh_size;
+ amt = finfo->symbuf_count * bed->s->sizeof_sym;
+ if (bfd_seek (finfo->output_bfd, pos, SEEK_SET) != 0
+ || bfd_bwrite (finfo->symbuf, amt, finfo->output_bfd) != amt)
+ return FALSE;
+
+ hdr->sh_size += amt;
+ finfo->symbuf_count = 0;
+ }
+
+ return TRUE;
+}
+
+/* Add a symbol to the output symbol table. */
+
+static bfd_boolean
+elf_link_output_sym (struct elf_final_link_info *finfo,
+ const char *name,
+ Elf_Internal_Sym *elfsym,
+ asection *input_sec,
+ struct elf_link_hash_entry *h)
+{
+ bfd_byte *dest;
+ Elf_External_Sym_Shndx *destshndx;
+ bfd_boolean (*output_symbol_hook)
+ (struct bfd_link_info *, const char *, Elf_Internal_Sym *, asection *,
+ struct elf_link_hash_entry *);
+ const struct elf_backend_data *bed;
+
+ bed = get_elf_backend_data (finfo->output_bfd);
+ output_symbol_hook = bed->elf_backend_link_output_symbol_hook;
+ if (output_symbol_hook != NULL)
+ {
+ if (! (*output_symbol_hook) (finfo->info, name, elfsym, input_sec, h))
+ return FALSE;
+ }
+
+ if (name == NULL || *name == '\0')
+ elfsym->st_name = 0;
+ else if (input_sec->flags & SEC_EXCLUDE)
+ elfsym->st_name = 0;
+ else
+ {
+ elfsym->st_name = (unsigned long) _bfd_stringtab_add (finfo->symstrtab,
+ name, TRUE, FALSE);
+ if (elfsym->st_name == (unsigned long) -1)
+ return FALSE;
+ }
+
+ if (finfo->symbuf_count >= finfo->symbuf_size)
+ {
+ if (! elf_link_flush_output_syms (finfo, bed))
+ return FALSE;
+ }
+
+ dest = finfo->symbuf + finfo->symbuf_count * bed->s->sizeof_sym;
+ destshndx = finfo->symshndxbuf;
+ if (destshndx != NULL)
+ {
+ if (bfd_get_symcount (finfo->output_bfd) >= finfo->shndxbuf_size)
+ {
+ bfd_size_type amt;
+
+ amt = finfo->shndxbuf_size * sizeof (Elf_External_Sym_Shndx);
+ finfo->symshndxbuf = destshndx = bfd_realloc (destshndx, amt * 2);
+ if (destshndx == NULL)
+ return FALSE;
+ memset ((char *) destshndx + amt, 0, amt);
+ finfo->shndxbuf_size *= 2;
+ }
+ destshndx += bfd_get_symcount (finfo->output_bfd);
+ }
+
+ bed->s->swap_symbol_out (finfo->output_bfd, elfsym, dest, destshndx);
+ finfo->symbuf_count += 1;
+ bfd_get_symcount (finfo->output_bfd) += 1;
+
+ return TRUE;
+}
+
+/* For DSOs loaded in via a DT_NEEDED entry, emulate ld.so in
+ allowing an unsatisfied unversioned symbol in the DSO to match a
+ versioned symbol that would normally require an explicit version.
+ We also handle the case that a DSO references a hidden symbol
+ which may be satisfied by a versioned symbol in another DSO. */
+
+static bfd_boolean
+elf_link_check_versioned_symbol (struct bfd_link_info *info,
+ const struct elf_backend_data *bed,
+ struct elf_link_hash_entry *h)
+{
+ bfd *abfd;
+ struct elf_link_loaded_list *loaded;
+
+ if (!is_elf_hash_table (info->hash))
+ return FALSE;
+
+ switch (h->root.type)
+ {
+ default:
+ abfd = NULL;
+ break;
+
+ case bfd_link_hash_undefined:
+ case bfd_link_hash_undefweak:
+ abfd = h->root.u.undef.abfd;
+ if ((abfd->flags & DYNAMIC) == 0
+ || elf_dyn_lib_class (abfd) != DYN_DT_NEEDED)
+ return FALSE;
+ break;
+
+ case bfd_link_hash_defined:
+ case bfd_link_hash_defweak:
+ abfd = h->root.u.def.section->owner;
+ break;
+
+ case bfd_link_hash_common:
+ abfd = h->root.u.c.p->section->owner;
+ break;
+ }
+ BFD_ASSERT (abfd != NULL);
+
+ for (loaded = elf_hash_table (info)->loaded;
+ loaded != NULL;
+ loaded = loaded->next)
+ {
+ bfd *input;
+ Elf_Internal_Shdr *hdr;
+ bfd_size_type symcount;
+ bfd_size_type extsymcount;
+ bfd_size_type extsymoff;
+ Elf_Internal_Shdr *versymhdr;
+ Elf_Internal_Sym *isym;
+ Elf_Internal_Sym *isymend;
+ Elf_Internal_Sym *isymbuf;
+ Elf_External_Versym *ever;
+ Elf_External_Versym *extversym;
+
+ input = loaded->abfd;
+
+ /* We check each DSO for a possible hidden versioned definition. */
+ if (input == abfd
+ || (input->flags & DYNAMIC) == 0
+ || elf_dynversym (input) == 0)
+ continue;
+
+ hdr = &elf_tdata (input)->dynsymtab_hdr;
+
+ symcount = hdr->sh_size / bed->s->sizeof_sym;
+ if (elf_bad_symtab (input))
+ {
+ extsymcount = symcount;
+ extsymoff = 0;
+ }
+ else
+ {
+ extsymcount = symcount - hdr->sh_info;
+ extsymoff = hdr->sh_info;
+ }
+
+ if (extsymcount == 0)
+ continue;
+
+ isymbuf = bfd_elf_get_elf_syms (input, hdr, extsymcount, extsymoff,
+ NULL, NULL, NULL);
+ if (isymbuf == NULL)
+ return FALSE;
+
+ /* Read in any version definitions. */
+ versymhdr = &elf_tdata (input)->dynversym_hdr;
+ extversym = bfd_malloc (versymhdr->sh_size);
+ if (extversym == NULL)
+ goto error_ret;
+
+ if (bfd_seek (input, versymhdr->sh_offset, SEEK_SET) != 0
+ || (bfd_bread (extversym, versymhdr->sh_size, input)
+ != versymhdr->sh_size))
+ {
+ free (extversym);
+ error_ret:
+ free (isymbuf);
+ return FALSE;
+ }
+
+ ever = extversym + extsymoff;
+ isymend = isymbuf + extsymcount;
+ for (isym = isymbuf; isym < isymend; isym++, ever++)
+ {
+ const char *name;
+ Elf_Internal_Versym iver;
+ unsigned short version_index;
+
+ if (ELF_ST_BIND (isym->st_info) == STB_LOCAL
+ || isym->st_shndx == SHN_UNDEF)
+ continue;
+
+ name = bfd_elf_string_from_elf_section (input,
+ hdr->sh_link,
+ isym->st_name);
+ if (strcmp (name, h->root.root.string) != 0)
+ continue;
+
+ _bfd_elf_swap_versym_in (input, ever, &iver);
+
+ if ((iver.vs_vers & VERSYM_HIDDEN) == 0)
+ {
+ /* If we have a non-hidden versioned sym, then it should
+ have provided a definition for the undefined sym. */
+ abort ();
+ }
+
+ version_index = iver.vs_vers & VERSYM_VERSION;
+ if (version_index == 1 || version_index == 2)
+ {
+ /* This is the base or first version. We can use it. */
+ free (extversym);
+ free (isymbuf);
+ return TRUE;
+ }
+ }
+
+ free (extversym);
+ free (isymbuf);
+ }
+
+ return FALSE;
+}
+
+/* Add an external symbol to the symbol table. This is called from
+ the hash table traversal routine. When generating a shared object,
+ we go through the symbol table twice. The first time we output
+ anything that might have been forced to local scope in a version
+ script. The second time we output the symbols that are still
+ global symbols. */
+
+static bfd_boolean
+elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
+{
+ struct elf_outext_info *eoinfo = data;
+ struct elf_final_link_info *finfo = eoinfo->finfo;
+ bfd_boolean strip;
+ Elf_Internal_Sym sym;
+ asection *input_sec;
+ const struct elf_backend_data *bed;
+
+ if (h->root.type == bfd_link_hash_warning)
+ {
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+ if (h->root.type == bfd_link_hash_new)
+ return TRUE;
+ }
+
+ /* Decide whether to output this symbol in this pass. */
+ if (eoinfo->localsyms)
+ {
+ if ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
+ return TRUE;
+ }
+ else
+ {
+ if ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)
+ return TRUE;
+ }
+
+ bed = get_elf_backend_data (finfo->output_bfd);
+
+ /* If we have an undefined symbol reference here then it must have
+ come from a shared library that is being linked in. (Undefined
+ references in regular files have already been handled). If we
+ are reporting errors for this situation then do so now. */
+ if (h->root.type == bfd_link_hash_undefined
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0
+ && ! elf_link_check_versioned_symbol (finfo->info, bed, h)
+ && finfo->info->unresolved_syms_in_shared_libs != RM_IGNORE)
+ {
+ if (! ((*finfo->info->callbacks->undefined_symbol)
+ (finfo->info, h->root.root.string, h->root.u.undef.abfd,
+ NULL, 0, finfo->info->unresolved_syms_in_shared_libs == RM_GENERATE_ERROR)))
+ {
+ eoinfo->failed = TRUE;
+ return FALSE;
+ }
+ }
+
+ /* We should also warn if a forced local symbol is referenced from
+ shared libraries. */
+ if (! finfo->info->relocatable
+ && (! finfo->info->shared)
+ && (h->elf_link_hash_flags
+ & (ELF_LINK_FORCED_LOCAL | ELF_LINK_HASH_REF_DYNAMIC | ELF_LINK_DYNAMIC_DEF | ELF_LINK_DYNAMIC_WEAK))
+ == (ELF_LINK_FORCED_LOCAL | ELF_LINK_HASH_REF_DYNAMIC)
+ && ! elf_link_check_versioned_symbol (finfo->info, bed, h))
+ {
+ (*_bfd_error_handler)
+ (_("%s: %s symbol `%s' in %s is referenced by DSO"),
+ bfd_get_filename (finfo->output_bfd),
+ ELF_ST_VISIBILITY (h->other) == STV_INTERNAL
+ ? "internal"
+ : ELF_ST_VISIBILITY (h->other) == STV_HIDDEN
+ ? "hidden" : "local",
+ h->root.root.string,
+ bfd_archive_filename (h->root.u.def.section->owner));
+ eoinfo->failed = TRUE;
+ return FALSE;
+ }
+
+ /* We don't want to output symbols that have never been mentioned by
+ a regular file, or that we have been told to strip. However, if
+ h->indx is set to -2, the symbol is used by a reloc and we must
+ output it. */
+ if (h->indx == -2)
+ strip = FALSE;
+ else if (((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
+ || (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0)
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0)
+ strip = TRUE;
+ else if (finfo->info->strip == strip_all)
+ strip = TRUE;
+ else if (finfo->info->strip == strip_some
+ && bfd_hash_lookup (finfo->info->keep_hash,
+ h->root.root.string, FALSE, FALSE) == NULL)
+ strip = TRUE;
+ else if (finfo->info->strip_discarded
+ && (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && elf_discarded_section (h->root.u.def.section))
+ strip = TRUE;
+ else
+ strip = FALSE;
+
+ /* If we're stripping it, and it's not a dynamic symbol, there's
+ nothing else to do unless it is a forced local symbol. */
+ if (strip
+ && h->dynindx == -1
+ && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
+ return TRUE;
+
+ sym.st_value = 0;
+ sym.st_size = h->size;
+ sym.st_other = h->other;
+ if ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)
+ sym.st_info = ELF_ST_INFO (STB_LOCAL, h->type);
+ else if (h->root.type == bfd_link_hash_undefweak
+ || h->root.type == bfd_link_hash_defweak)
+ sym.st_info = ELF_ST_INFO (STB_WEAK, h->type);
+ else
+ sym.st_info = ELF_ST_INFO (STB_GLOBAL, h->type);
+
+ switch (h->root.type)
+ {
+ default:
+ case bfd_link_hash_new:
+ case bfd_link_hash_warning:
+ abort ();
+ return FALSE;
+
+ case bfd_link_hash_undefined:
+ case bfd_link_hash_undefweak:
+ input_sec = bfd_und_section_ptr;
+ sym.st_shndx = SHN_UNDEF;
+ break;
+
+ case bfd_link_hash_defined:
+ case bfd_link_hash_defweak:
+ {
+ input_sec = h->root.u.def.section;
+ if (input_sec->output_section != NULL)
+ {
+ sym.st_shndx =
+ _bfd_elf_section_from_bfd_section (finfo->output_bfd,
+ input_sec->output_section);
+ if (sym.st_shndx == SHN_BAD)
+ {
+ (*_bfd_error_handler)
+ (_("%s: could not find output section %s for input section %s"),
+ bfd_get_filename (finfo->output_bfd),
+ input_sec->output_section->name,
+ input_sec->name);
+ eoinfo->failed = TRUE;
+ return FALSE;
+ }
+
+ /* ELF symbols in relocatable files are section relative,
+ but in nonrelocatable files they are virtual
+ addresses. */
+ sym.st_value = h->root.u.def.value + input_sec->output_offset;
+ if (! finfo->info->relocatable)
+ {
+ sym.st_value += input_sec->output_section->vma;
+ if (h->type == STT_TLS)
+ {
+ /* STT_TLS symbols are relative to PT_TLS segment
+ base. */
+ BFD_ASSERT (elf_hash_table (finfo->info)->tls_sec != NULL);
+ sym.st_value -= elf_hash_table (finfo->info)->tls_sec->vma;
+ }
+ }
+ }
+ else
+ {
+ BFD_ASSERT (input_sec->owner == NULL
+ || (input_sec->owner->flags & DYNAMIC) != 0);
+ sym.st_shndx = SHN_UNDEF;
+ input_sec = bfd_und_section_ptr;
+ }
+ }
+ break;
+
+ case bfd_link_hash_common:
+ input_sec = h->root.u.c.p->section;
+ sym.st_shndx = SHN_COMMON;
+ sym.st_value = 1 << h->root.u.c.p->alignment_power;
+ break;
+
+ case bfd_link_hash_indirect:
+ /* These symbols are created by symbol versioning. They point
+ to the decorated version of the name. For example, if the
+ symbol foo@@GNU_1.2 is the default, which should be used when
+ foo is used with no version, then we add an indirect symbol
+ foo which points to foo@@GNU_1.2. We ignore these symbols,
+ since the indirected symbol is already in the hash table. */
+ return TRUE;
+ }
+
+ /* Give the processor backend a chance to tweak the symbol value,
+ and also to finish up anything that needs to be done for this
+ symbol. FIXME: Not calling elf_backend_finish_dynamic_symbol for
+ forced local syms when non-shared is due to a historical quirk. */
+ if ((h->dynindx != -1
+ || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)
+ && ((finfo->info->shared
+ && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+ || h->root.type != bfd_link_hash_undefweak))
+ || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
+ && elf_hash_table (finfo->info)->dynamic_sections_created)
+ {
+ if (! ((*bed->elf_backend_finish_dynamic_symbol)
+ (finfo->output_bfd, finfo->info, h, &sym)))
+ {
+ eoinfo->failed = TRUE;
+ return FALSE;
+ }
+ }
+
+ /* If we are marking the symbol as undefined, and there are no
+ non-weak references to this symbol from a regular object, then
+ mark the symbol as weak undefined; if there are non-weak
+ references, mark the symbol as strong. We can't do this earlier,
+ because it might not be marked as undefined until the
+ finish_dynamic_symbol routine gets through with it. */
+ if (sym.st_shndx == SHN_UNDEF
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) != 0
+ && (ELF_ST_BIND (sym.st_info) == STB_GLOBAL
+ || ELF_ST_BIND (sym.st_info) == STB_WEAK))
+ {
+ int bindtype;
+
+ if ((h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR_NONWEAK) != 0)
+ bindtype = STB_GLOBAL;
+ else
+ bindtype = STB_WEAK;
+ sym.st_info = ELF_ST_INFO (bindtype, ELF_ST_TYPE (sym.st_info));
+ }
+
+ /* If a non-weak symbol with non-default visibility is not defined
+ locally, it is a fatal error. */
+ if (! finfo->info->relocatable
+ && ELF_ST_VISIBILITY (sym.st_other) != STV_DEFAULT
+ && ELF_ST_BIND (sym.st_info) != STB_WEAK
+ && h->root.type == bfd_link_hash_undefined
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+ {
+ (*_bfd_error_handler)
+ (_("%s: %s symbol `%s' isn't defined"),
+ bfd_get_filename (finfo->output_bfd),
+ ELF_ST_VISIBILITY (sym.st_other) == STV_PROTECTED
+ ? "protected"
+ : ELF_ST_VISIBILITY (sym.st_other) == STV_INTERNAL
+ ? "internal" : "hidden",
+ h->root.root.string);
+ eoinfo->failed = TRUE;
+ return FALSE;
+ }
+
+ /* If this symbol should be put in the .dynsym section, then put it
+ there now. We already know the symbol index. We also fill in
+ the entry in the .hash section. */
+ if (h->dynindx != -1
+ && elf_hash_table (finfo->info)->dynamic_sections_created)
+ {
+ size_t bucketcount;
+ size_t bucket;
+ size_t hash_entry_size;
+ bfd_byte *bucketpos;
+ bfd_vma chain;
+ bfd_byte *esym;
+
+ sym.st_name = h->dynstr_index;
+ esym = finfo->dynsym_sec->contents + h->dynindx * bed->s->sizeof_sym;
+ bed->s->swap_symbol_out (finfo->output_bfd, &sym, esym, 0);
+
+ bucketcount = elf_hash_table (finfo->info)->bucketcount;
+ bucket = h->elf_hash_value % bucketcount;
+ hash_entry_size
+ = elf_section_data (finfo->hash_sec)->this_hdr.sh_entsize;
+ bucketpos = ((bfd_byte *) finfo->hash_sec->contents
+ + (bucket + 2) * hash_entry_size);
+ chain = bfd_get (8 * hash_entry_size, finfo->output_bfd, bucketpos);
+ bfd_put (8 * hash_entry_size, finfo->output_bfd, h->dynindx, bucketpos);
+ bfd_put (8 * hash_entry_size, finfo->output_bfd, chain,
+ ((bfd_byte *) finfo->hash_sec->contents
+ + (bucketcount + 2 + h->dynindx) * hash_entry_size));
+
+ if (finfo->symver_sec != NULL && finfo->symver_sec->contents != NULL)
+ {
+ Elf_Internal_Versym iversym;
+ Elf_External_Versym *eversym;
+
+ if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+ {
+ if (h->verinfo.verdef == NULL)
+ iversym.vs_vers = 0;
+ else
+ iversym.vs_vers = h->verinfo.verdef->vd_exp_refno + 1;
+ }
+ else
+ {
+ if (h->verinfo.vertree == NULL)
+ iversym.vs_vers = 1;
+ else
+ iversym.vs_vers = h->verinfo.vertree->vernum + 1;
+ }
+
+ if ((h->elf_link_hash_flags & ELF_LINK_HIDDEN) != 0)
+ iversym.vs_vers |= VERSYM_HIDDEN;
+
+ eversym = (Elf_External_Versym *) finfo->symver_sec->contents;
+ eversym += h->dynindx;
+ _bfd_elf_swap_versym_out (finfo->output_bfd, &iversym, eversym);
+ }
+ }
+
+ /* If we're stripping it, then it was just a dynamic symbol, and
+ there's nothing else to do. */
+ if (strip || (input_sec->flags & SEC_EXCLUDE) != 0)
+ return TRUE;
+
+ h->indx = bfd_get_symcount (finfo->output_bfd);
+
+ if (! elf_link_output_sym (finfo, h->root.root.string, &sym, input_sec, h))
+ {
+ eoinfo->failed = TRUE;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static bfd_boolean
+elf_section_ignore_discarded_relocs (asection *sec)
+{
+ const struct elf_backend_data *bed;
+
+ switch (sec->sec_info_type)
+ {
+ case ELF_INFO_TYPE_STABS:
+ case ELF_INFO_TYPE_EH_FRAME:
+ return TRUE;
+ default:
+ break;
+ }
+
+ bed = get_elf_backend_data (sec->owner);
+ if (bed->elf_backend_ignore_discarded_relocs != NULL
+ && (*bed->elf_backend_ignore_discarded_relocs) (sec))
+ return TRUE;
+
+ return FALSE;
+}
+
+/* Link an input file into the linker output file. This function
+ handles all the sections and relocations of the input file at once.
+ This is so that we only have to read the local symbols once, and
+ don't have to keep them in memory. */
+
+static bfd_boolean
+elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
+{
+ bfd_boolean (*relocate_section)
+ (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
+ Elf_Internal_Rela *, Elf_Internal_Sym *, asection **);
+ bfd *output_bfd;
+ Elf_Internal_Shdr *symtab_hdr;
+ size_t locsymcount;
+ size_t extsymoff;
+ Elf_Internal_Sym *isymbuf;
+ Elf_Internal_Sym *isym;
+ Elf_Internal_Sym *isymend;
+ long *pindex;
+ asection **ppsection;
+ asection *o;
+ const struct elf_backend_data *bed;
+ bfd_boolean emit_relocs;
+ struct elf_link_hash_entry **sym_hashes;
+
+ output_bfd = finfo->output_bfd;
+ bed = get_elf_backend_data (output_bfd);
+ relocate_section = bed->elf_backend_relocate_section;
+
+ /* If this is a dynamic object, we don't want to do anything here:
+ we don't want the local symbols, and we don't want the section
+ contents. */
+ if ((input_bfd->flags & DYNAMIC) != 0)
+ return TRUE;
+
+ emit_relocs = (finfo->info->relocatable
+ || finfo->info->emitrelocations
+ || bed->elf_backend_emit_relocs);
+
+ symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
+ if (elf_bad_symtab (input_bfd))
+ {
+ locsymcount = symtab_hdr->sh_size / bed->s->sizeof_sym;
+ extsymoff = 0;
+ }
+ else
+ {
+ locsymcount = symtab_hdr->sh_info;
+ extsymoff = symtab_hdr->sh_info;
+ }
+
+ /* Read the local symbols. */
+ isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+ if (isymbuf == NULL && locsymcount != 0)
+ {
+ isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, locsymcount, 0,
+ finfo->internal_syms,
+ finfo->external_syms,
+ finfo->locsym_shndx);
+ if (isymbuf == NULL)
+ return FALSE;
+ }
+
+ /* Find local symbol sections and adjust values of symbols in
+ SEC_MERGE sections. Write out those local symbols we know are
+ going into the output file. */
+ isymend = isymbuf + locsymcount;
+ for (isym = isymbuf, pindex = finfo->indices, ppsection = finfo->sections;
+ isym < isymend;
+ isym++, pindex++, ppsection++)
+ {
+ asection *isec;
+ const char *name;
+ Elf_Internal_Sym osym;
+
+ *pindex = -1;
+
+ if (elf_bad_symtab (input_bfd))
+ {
+ if (ELF_ST_BIND (isym->st_info) != STB_LOCAL)
+ {
+ *ppsection = NULL;
+ continue;
+ }
+ }
+
+ if (isym->st_shndx == SHN_UNDEF)
+ isec = bfd_und_section_ptr;
+ else if (isym->st_shndx < SHN_LORESERVE
+ || isym->st_shndx > SHN_HIRESERVE)
+ {
+ isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx);
+ if (isec
+ && isec->sec_info_type == ELF_INFO_TYPE_MERGE
+ && ELF_ST_TYPE (isym->st_info) != STT_SECTION)
+ isym->st_value =
+ _bfd_merged_section_offset (output_bfd, &isec,
+ elf_section_data (isec)->sec_info,
+ isym->st_value, 0);
+ }
+ else if (isym->st_shndx == SHN_ABS)
+ isec = bfd_abs_section_ptr;
+ else if (isym->st_shndx == SHN_COMMON)
+ isec = bfd_com_section_ptr;
+ else
+ {
+ /* Who knows? */
+ isec = NULL;
+ }
+
+ *ppsection = isec;
+
+ /* Don't output the first, undefined, symbol. */
+ if (ppsection == finfo->sections)
+ continue;
+
+ if (ELF_ST_TYPE (isym->st_info) == STT_SECTION)
+ {
+ /* We never output section symbols. Instead, we use the
+ section symbol of the corresponding section in the output
+ file. */
+ continue;
+ }
+
+ /* If we are stripping all symbols, we don't want to output this
+ one. */
+ if (finfo->info->strip == strip_all)
+ continue;
+
+ /* If we are discarding all local symbols, we don't want to
+ output this one. If we are generating a relocatable output
+ file, then some of the local symbols may be required by
+ relocs; we output them below as we discover that they are
+ needed. */
+ if (finfo->info->discard == discard_all)
+ continue;
+
+ /* If this symbol is defined in a section which we are
+ discarding, we don't need to keep it, but note that
+ linker_mark is only reliable for sections that have contents.
+ For the benefit of the MIPS ELF linker, we check SEC_EXCLUDE
+ as well as linker_mark. */
+ if ((isym->st_shndx < SHN_LORESERVE || isym->st_shndx > SHN_HIRESERVE)
+ && isec != NULL
+ && ((! isec->linker_mark && (isec->flags & SEC_HAS_CONTENTS) != 0)
+ || (! finfo->info->relocatable
+ && (isec->flags & SEC_EXCLUDE) != 0)))
+ continue;
+
+ /* Get the name of the symbol. */
+ name = bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link,
+ isym->st_name);
+ if (name == NULL)
+ return FALSE;
+
+ /* See if we are discarding symbols with this name. */
+ if ((finfo->info->strip == strip_some
+ && (bfd_hash_lookup (finfo->info->keep_hash, name, FALSE, FALSE)
+ == NULL))
+ || (((finfo->info->discard == discard_sec_merge
+ && (isec->flags & SEC_MERGE) && ! finfo->info->relocatable)
+ || finfo->info->discard == discard_l)
+ && bfd_is_local_label_name (input_bfd, name)))
+ continue;
+
+ /* If we get here, we are going to output this symbol. */
+
+ osym = *isym;
+
+ /* Adjust the section index for the output file. */
+ osym.st_shndx = _bfd_elf_section_from_bfd_section (output_bfd,
+ isec->output_section);
+ if (osym.st_shndx == SHN_BAD)
+ return FALSE;
+
+ *pindex = bfd_get_symcount (output_bfd);
+
+ /* ELF symbols in relocatable files are section relative, but
+ in executable files they are virtual addresses. Note that
+ this code assumes that all ELF sections have an associated
+ BFD section with a reasonable value for output_offset; below
+ we assume that they also have a reasonable value for
+ output_section. Any special sections must be set up to meet
+ these requirements. */
+ osym.st_value += isec->output_offset;
+ if (! finfo->info->relocatable)
+ {
+ osym.st_value += isec->output_section->vma;
+ if (ELF_ST_TYPE (osym.st_info) == STT_TLS)
+ {
+ /* STT_TLS symbols are relative to PT_TLS segment base. */
+ BFD_ASSERT (elf_hash_table (finfo->info)->tls_sec != NULL);
+ osym.st_value -= elf_hash_table (finfo->info)->tls_sec->vma;
+ }
+ }
+
+ if (! elf_link_output_sym (finfo, name, &osym, isec, NULL))
+ return FALSE;
+ }
+
+ /* Relocate the contents of each section. */
+ sym_hashes = elf_sym_hashes (input_bfd);
+ for (o = input_bfd->sections; o != NULL; o = o->next)
+ {
+ bfd_byte *contents;
+
+ if (! o->linker_mark)
+ {
+ /* This section was omitted from the link. */
+ continue;
+ }
+
+ if ((o->flags & SEC_HAS_CONTENTS) == 0
+ || (o->_raw_size == 0 && (o->flags & SEC_RELOC) == 0))
+ continue;
+
+ if ((o->flags & SEC_LINKER_CREATED) != 0)
+ {
+ /* Section was created by _bfd_elf_link_create_dynamic_sections
+ or somesuch. */
+ continue;
+ }
+
+ /* Get the contents of the section. They have been cached by a
+ relaxation routine. Note that o is a section in an input
+ file, so the contents field will not have been set by any of
+ the routines which work on output files. */
+ if (elf_section_data (o)->this_hdr.contents != NULL)
+ contents = elf_section_data (o)->this_hdr.contents;
+ else
+ {
+ contents = finfo->contents;
+ if (! bfd_get_section_contents (input_bfd, o, contents, 0,
+ o->_raw_size))
+ return FALSE;
+ }
+
+ if ((o->flags & SEC_RELOC) != 0)
+ {
+ Elf_Internal_Rela *internal_relocs;
+ bfd_vma r_type_mask;
+ int r_sym_shift;
+
+ /* Get the swapped relocs. */
+ internal_relocs
+ = _bfd_elf_link_read_relocs (input_bfd, o, finfo->external_relocs,
+ finfo->internal_relocs, FALSE);
+ if (internal_relocs == NULL
+ && o->reloc_count > 0)
+ return FALSE;
+
+ if (bed->s->arch_size == 32)
+ {
+ r_type_mask = 0xff;
+ r_sym_shift = 8;
+ }
+ else
+ {
+ r_type_mask = 0xffffffff;
+ r_sym_shift = 32;
+ }
+
+ /* Run through the relocs looking for any against symbols
+ from discarded sections and section symbols from
+ removed link-once sections. Complain about relocs
+ against discarded sections. Zero relocs against removed
+ link-once sections. Preserve debug information as much
+ as we can. */
+ if (!elf_section_ignore_discarded_relocs (o))
+ {
+ Elf_Internal_Rela *rel, *relend;
+
+ rel = internal_relocs;
+ relend = rel + o->reloc_count * bed->s->int_rels_per_ext_rel;
+ for ( ; rel < relend; rel++)
+ {
+ unsigned long r_symndx = rel->r_info >> r_sym_shift;
+ asection *sec;
+
+ if (r_symndx >= locsymcount
+ || (elf_bad_symtab (input_bfd)
+ && finfo->sections[r_symndx] == NULL))
+ {
+ struct elf_link_hash_entry *h;
+
+ h = sym_hashes[r_symndx - extsymoff];
+ while (h->root.type == bfd_link_hash_indirect
+ || h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+ /* Complain if the definition comes from a
+ discarded section. */
+ sec = h->root.u.def.section;
+ if ((h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && elf_discarded_section (sec))
+ {
+ if ((o->flags & SEC_DEBUGGING) != 0)
+ {
+ BFD_ASSERT (r_symndx != 0);
+ /* Try to preserve debug information. */
+ if ((o->flags & SEC_DEBUGGING) != 0
+ && sec->kept_section != NULL
+ && sec->_raw_size == sec->kept_section->_raw_size)
+ h->root.u.def.section
+ = sec->kept_section;
+ else
+ memset (rel, 0, sizeof (*rel));
+ }
+ else
+ finfo->info->callbacks->error_handler
+ (LD_DEFINITION_IN_DISCARDED_SECTION,
+ _("%T: discarded in section `%s' from %s\n"),
+ h->root.root.string,
+ h->root.root.string,
+ h->root.u.def.section->name,
+ bfd_archive_filename (h->root.u.def.section->owner));
+ }
+ }
+ else
+ {
+ sec = finfo->sections[r_symndx];
+
+ if (sec != NULL && elf_discarded_section (sec))
+ {
+ if ((o->flags & SEC_DEBUGGING) != 0
+ || (sec->flags & SEC_LINK_ONCE) != 0)
+ {
+ BFD_ASSERT (r_symndx != 0);
+ /* Try to preserve debug information. */
+ if ((o->flags & SEC_DEBUGGING) != 0
+ && sec->kept_section != NULL
+ && sec->_raw_size == sec->kept_section->_raw_size)
+ finfo->sections[r_symndx]
+ = sec->kept_section;
+ else
+ {
+ rel->r_info &= r_type_mask;
+ rel->r_addend = 0;
+ }
+ }
+ else
+ {
+ static int count;
+ int ok;
+ char *buf;
+
+ ok = asprintf (&buf, "local symbol %d",
+ count++);
+ if (ok <= 0)
+ buf = (char *) "local symbol";
+ finfo->info->callbacks->error_handler
+ (LD_DEFINITION_IN_DISCARDED_SECTION,
+ _("%T: discarded in section `%s' from %s\n"),
+ buf, buf, sec->name,
+ bfd_archive_filename (input_bfd));
+ if (ok != -1)
+ free (buf);
+ }
+ }
+ }
+ }
+ }
+
+ /* Relocate the section by invoking a back end routine.
+
+ The back end routine is responsible for adjusting the
+ section contents as necessary, and (if using Rela relocs
+ and generating a relocatable output file) adjusting the
+ reloc addend as necessary.
+
+ The back end routine does not have to worry about setting
+ the reloc address or the reloc symbol index.
+
+ The back end routine is given a pointer to the swapped in
+ internal symbols, and can access the hash table entries
+ for the external symbols via elf_sym_hashes (input_bfd).
+
+ When generating relocatable output, the back end routine
+ must handle STB_LOCAL/STT_SECTION symbols specially. The
+ output symbol is going to be a section symbol
+ corresponding to the output section, which will require
+ the addend to be adjusted. */
+
+ if (! (*relocate_section) (output_bfd, finfo->info,
+ input_bfd, o, contents,
+ internal_relocs,
+ isymbuf,
+ finfo->sections))
+ return FALSE;
+
+ if (emit_relocs)
+ {
+ Elf_Internal_Rela *irela;
+ Elf_Internal_Rela *irelaend;
+ bfd_vma last_offset;
+ struct elf_link_hash_entry **rel_hash;
+ Elf_Internal_Shdr *input_rel_hdr, *input_rel_hdr2;
+ unsigned int next_erel;
+ bfd_boolean (*reloc_emitter)
+ (bfd *, asection *, Elf_Internal_Shdr *, Elf_Internal_Rela *);
+ bfd_boolean rela_normal;
+
+ input_rel_hdr = &elf_section_data (o)->rel_hdr;
+ rela_normal = (bed->rela_normal
+ && (input_rel_hdr->sh_entsize
+ == bed->s->sizeof_rela));
+
+ /* Adjust the reloc addresses and symbol indices. */
+
+ irela = internal_relocs;
+ irelaend = irela + o->reloc_count * bed->s->int_rels_per_ext_rel;
+ rel_hash = (elf_section_data (o->output_section)->rel_hashes
+ + elf_section_data (o->output_section)->rel_count
+ + elf_section_data (o->output_section)->rel_count2);
+ last_offset = o->output_offset;
+ if (!finfo->info->relocatable)
+ last_offset += o->output_section->vma;
+ for (next_erel = 0; irela < irelaend; irela++, next_erel++)
+ {
+ unsigned long r_symndx;
+ asection *sec;
+ Elf_Internal_Sym sym;
+
+ if (next_erel == bed->s->int_rels_per_ext_rel)
+ {
+ rel_hash++;
+ next_erel = 0;
+ }
+
+ irela->r_offset = _bfd_elf_section_offset (output_bfd,
+ finfo->info, o,
+ irela->r_offset);
+ if (irela->r_offset >= (bfd_vma) -2)
+ {
+ /* This is a reloc for a deleted entry or somesuch.
+ Turn it into an R_*_NONE reloc, at the same
+ offset as the last reloc. elf_eh_frame.c and
+ elf_bfd_discard_info rely on reloc offsets
+ being ordered. */
+ irela->r_offset = last_offset;
+ irela->r_info = 0;
+ irela->r_addend = 0;
+ continue;
+ }
+
+ irela->r_offset += o->output_offset;
+
+ /* Relocs in an executable have to be virtual addresses. */
+ if (!finfo->info->relocatable)
+ irela->r_offset += o->output_section->vma;
+
+ last_offset = irela->r_offset;
+
+ r_symndx = irela->r_info >> r_sym_shift;
+ if (r_symndx == STN_UNDEF)
+ continue;
+
+ if (r_symndx >= locsymcount
+ || (elf_bad_symtab (input_bfd)
+ && finfo->sections[r_symndx] == NULL))
+ {
+ struct elf_link_hash_entry *rh;
+ unsigned long indx;
+
+ /* This is a reloc against a global symbol. We
+ have not yet output all the local symbols, so
+ we do not know the symbol index of any global
+ symbol. We set the rel_hash entry for this
+ reloc to point to the global hash table entry
+ for this symbol. The symbol index is then
+ set at the end of elf_bfd_final_link. */
+ indx = r_symndx - extsymoff;
+ rh = elf_sym_hashes (input_bfd)[indx];
+ while (rh->root.type == bfd_link_hash_indirect
+ || rh->root.type == bfd_link_hash_warning)
+ rh = (struct elf_link_hash_entry *) rh->root.u.i.link;
+
+ /* Setting the index to -2 tells
+ elf_link_output_extsym that this symbol is
+ used by a reloc. */
+ BFD_ASSERT (rh->indx < 0);
+ rh->indx = -2;
+
+ *rel_hash = rh;
+
+ continue;
+ }
+
+ /* This is a reloc against a local symbol. */
+
+ *rel_hash = NULL;
+ sym = isymbuf[r_symndx];
+ sec = finfo->sections[r_symndx];
+ if (ELF_ST_TYPE (sym.st_info) == STT_SECTION)
+ {
+ /* I suppose the backend ought to fill in the
+ section of any STT_SECTION symbol against a
+ processor specific section. If we have
+ discarded a section, the output_section will
+ be the absolute section. */
+ if (bfd_is_abs_section (sec)
+ || (sec != NULL
+ && bfd_is_abs_section (sec->output_section)))
+ r_symndx = 0;
+ else if (sec == NULL || sec->owner == NULL)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
+ else
+ {
+ r_symndx = sec->output_section->target_index;
+ BFD_ASSERT (r_symndx != 0);
+ }
+
+ /* Adjust the addend according to where the
+ section winds up in the output section. */
+ if (rela_normal)
+ irela->r_addend += sec->output_offset;
+ }
+ else
+ {
+ if (finfo->indices[r_symndx] == -1)
+ {
+ unsigned long shlink;
+ const char *name;
+ asection *osec;
+
+ if (finfo->info->strip == strip_all)
+ {
+ /* You can't do ld -r -s. */
+ bfd_set_error (bfd_error_invalid_operation);
+ return FALSE;
+ }
+
+ /* This symbol was skipped earlier, but
+ since it is needed by a reloc, we
+ must output it now. */
+ shlink = symtab_hdr->sh_link;
+ name = (bfd_elf_string_from_elf_section
+ (input_bfd, shlink, sym.st_name));
+ if (name == NULL)
+ return FALSE;
+
+ osec = sec->output_section;
+ sym.st_shndx =
+ _bfd_elf_section_from_bfd_section (output_bfd,
+ osec);
+ if (sym.st_shndx == SHN_BAD)
+ return FALSE;
+
+ sym.st_value += sec->output_offset;
+ if (! finfo->info->relocatable)
+ {
+ sym.st_value += osec->vma;
+ if (ELF_ST_TYPE (sym.st_info) == STT_TLS)
+ {
+ /* STT_TLS symbols are relative to PT_TLS
+ segment base. */
+ BFD_ASSERT (elf_hash_table (finfo->info)
+ ->tls_sec != NULL);
+ sym.st_value -= (elf_hash_table (finfo->info)
+ ->tls_sec->vma);
+ }
+ }
+
+ finfo->indices[r_symndx]
+ = bfd_get_symcount (output_bfd);
+
+ if (! elf_link_output_sym (finfo, name, &sym, sec,
+ NULL))
+ return FALSE;
+ }
+
+ r_symndx = finfo->indices[r_symndx];
+ }
+
+ irela->r_info = ((bfd_vma) r_symndx << r_sym_shift
+ | (irela->r_info & r_type_mask));
+ }
+
+ /* Swap out the relocs. */
+ if (bed->elf_backend_emit_relocs
+ && !(finfo->info->relocatable
+ || finfo->info->emitrelocations))
+ reloc_emitter = bed->elf_backend_emit_relocs;
+ else
+ reloc_emitter = _bfd_elf_link_output_relocs;
+
+ if (input_rel_hdr->sh_size != 0
+ && ! (*reloc_emitter) (output_bfd, o, input_rel_hdr,
+ internal_relocs))
+ return FALSE;
+
+ input_rel_hdr2 = elf_section_data (o)->rel_hdr2;
+ if (input_rel_hdr2 && input_rel_hdr2->sh_size != 0)
+ {
+ internal_relocs += (NUM_SHDR_ENTRIES (input_rel_hdr)
+ * bed->s->int_rels_per_ext_rel);
+ if (! (*reloc_emitter) (output_bfd, o, input_rel_hdr2,
+ internal_relocs))
+ return FALSE;
+ }
+ }
+ }
+
+ /* Write out the modified section contents. */
+ if (bed->elf_backend_write_section
+ && (*bed->elf_backend_write_section) (output_bfd, o, contents))
+ {
+ /* Section written out. */
+ }
+ else switch (o->sec_info_type)
+ {
+ case ELF_INFO_TYPE_STABS:
+ if (! (_bfd_write_section_stabs
+ (output_bfd,
+ &elf_hash_table (finfo->info)->stab_info,
+ o, &elf_section_data (o)->sec_info, contents)))
+ return FALSE;
+ break;
+ case ELF_INFO_TYPE_MERGE:
+ if (! _bfd_write_merged_section (output_bfd, o,
+ elf_section_data (o)->sec_info))
+ return FALSE;
+ break;
+ case ELF_INFO_TYPE_EH_FRAME:
+ {
+ if (! _bfd_elf_write_section_eh_frame (output_bfd, finfo->info,
+ o, contents))
+ return FALSE;
+ }
+ break;
+ default:
+ {
+ bfd_size_type sec_size;
+
+ sec_size = (o->_cooked_size != 0 ? o->_cooked_size : o->_raw_size);
+ if (! (o->flags & SEC_EXCLUDE)
+ && ! bfd_set_section_contents (output_bfd, o->output_section,
+ contents,
+ (file_ptr) o->output_offset,
+ sec_size))
+ return FALSE;
+ }
+ break;
+ }
+ }
+
+ return TRUE;
+}
+
+/* Generate a reloc when linking an ELF file. This is a reloc
+ requested by the linker, and does come from any input file. This
+ is used to build constructor and destructor tables when linking
+ with -Ur. */
+
+static bfd_boolean
+elf_reloc_link_order (bfd *output_bfd,
+ struct bfd_link_info *info,
+ asection *output_section,
+ struct bfd_link_order *link_order)
+{
+ reloc_howto_type *howto;
+ long indx;
+ bfd_vma offset;
+ bfd_vma addend;
+ struct elf_link_hash_entry **rel_hash_ptr;
+ Elf_Internal_Shdr *rel_hdr;
+ const struct elf_backend_data *bed = get_elf_backend_data (output_bfd);
+ Elf_Internal_Rela irel[MAX_INT_RELS_PER_EXT_REL];
+ bfd_byte *erel;
+ unsigned int i;
+
+ howto = bfd_reloc_type_lookup (output_bfd, link_order->u.reloc.p->reloc);
+ if (howto == NULL)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
+
+ addend = link_order->u.reloc.p->addend;
+
+ /* Figure out the symbol index. */
+ rel_hash_ptr = (elf_section_data (output_section)->rel_hashes
+ + elf_section_data (output_section)->rel_count
+ + elf_section_data (output_section)->rel_count2);
+ if (link_order->type == bfd_section_reloc_link_order)
+ {
+ indx = link_order->u.reloc.p->u.section->target_index;
+ BFD_ASSERT (indx != 0);
+ *rel_hash_ptr = NULL;
+ }
+ else
+ {
+ struct elf_link_hash_entry *h;
+
+ /* Treat a reloc against a defined symbol as though it were
+ actually against the section. */
+ h = ((struct elf_link_hash_entry *)
+ bfd_wrapped_link_hash_lookup (output_bfd, info,
+ link_order->u.reloc.p->u.name,
+ FALSE, FALSE, TRUE));
+ if (h != NULL
+ && (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak))
+ {
+ asection *section;
+
+ section = h->root.u.def.section;
+ indx = section->output_section->target_index;
+ *rel_hash_ptr = NULL;
+ /* It seems that we ought to add the symbol value to the
+ addend here, but in practice it has already been added
+ because it was passed to constructor_callback. */
+ addend += section->output_section->vma + section->output_offset;
+ }
+ else if (h != NULL)
+ {
+ /* Setting the index to -2 tells elf_link_output_extsym that
+ this symbol is used by a reloc. */
+ h->indx = -2;
+ *rel_hash_ptr = h;
+ indx = 0;
+ }
+ else
+ {
+ if (! ((*info->callbacks->unattached_reloc)
+ (info, link_order->u.reloc.p->u.name, NULL, NULL, 0)))
+ return FALSE;
+ indx = 0;
+ }
+ }
+
+ /* If this is an inplace reloc, we must write the addend into the
+ object file. */
+ if (howto->partial_inplace && addend != 0)
+ {
+ bfd_size_type size;
+ bfd_reloc_status_type rstat;
+ bfd_byte *buf;
+ bfd_boolean ok;
+ const char *sym_name;
+
+ size = bfd_get_reloc_size (howto);
+ buf = bfd_zmalloc (size);
+ if (buf == NULL)
+ return FALSE;
+ rstat = _bfd_relocate_contents (howto, output_bfd, addend, buf);
+ switch (rstat)
+ {
+ case bfd_reloc_ok:
+ break;
+
+ default:
+ case bfd_reloc_outofrange:
+ abort ();
+
+ case bfd_reloc_overflow:
+ if (link_order->type == bfd_section_reloc_link_order)
+ sym_name = bfd_section_name (output_bfd,
+ link_order->u.reloc.p->u.section);
+ else
+ sym_name = link_order->u.reloc.p->u.name;
+ if (! ((*info->callbacks->reloc_overflow)
+ (info, sym_name, howto->name, addend, NULL, NULL, 0)))
+ {
+ free (buf);
+ return FALSE;
+ }
+ break;
+ }
+ ok = bfd_set_section_contents (output_bfd, output_section, buf,
+ link_order->offset, size);
+ free (buf);
+ if (! ok)
+ return FALSE;
+ }
+
+ /* The address of a reloc is relative to the section in a
+ relocatable file, and is a virtual address in an executable
+ file. */
+ offset = link_order->offset;
+ if (! info->relocatable)
+ offset += output_section->vma;
+
+ for (i = 0; i < bed->s->int_rels_per_ext_rel; i++)
+ {
+ irel[i].r_offset = offset;
+ irel[i].r_info = 0;
+ irel[i].r_addend = 0;
+ }
+ if (bed->s->arch_size == 32)
+ irel[0].r_info = ELF32_R_INFO (indx, howto->type);
+ else
+ irel[0].r_info = ELF64_R_INFO (indx, howto->type);
+
+ rel_hdr = &elf_section_data (output_section)->rel_hdr;
+ erel = rel_hdr->contents;
+ if (rel_hdr->sh_type == SHT_REL)
+ {
+ erel += (elf_section_data (output_section)->rel_count
+ * bed->s->sizeof_rel);
+ (*bed->s->swap_reloc_out) (output_bfd, irel, erel);
+ }
+ else
+ {
+ irel[0].r_addend = addend;
+ erel += (elf_section_data (output_section)->rel_count
+ * bed->s->sizeof_rela);
+ (*bed->s->swap_reloca_out) (output_bfd, irel, erel);
+ }
+
+ ++elf_section_data (output_section)->rel_count;
+
+ return TRUE;
+}
+
+/* Do the final step of an ELF link. */
+
+bfd_boolean
+bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
+{
+ bfd_boolean dynamic;
+ bfd_boolean emit_relocs;
+ bfd *dynobj;
+ struct elf_final_link_info finfo;
+ register asection *o;
+ register struct bfd_link_order *p;
+ register bfd *sub;
+ bfd_size_type max_contents_size;
+ bfd_size_type max_external_reloc_size;
+ bfd_size_type max_internal_reloc_count;
+ bfd_size_type max_sym_count;
+ bfd_size_type max_sym_shndx_count;
+ file_ptr off;
+ Elf_Internal_Sym elfsym;
+ unsigned int i;
+ Elf_Internal_Shdr *symtab_hdr;
+ Elf_Internal_Shdr *symtab_shndx_hdr;
+ Elf_Internal_Shdr *symstrtab_hdr;
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ struct elf_outext_info eoinfo;
+ bfd_boolean merged;
+ size_t relativecount = 0;
+ asection *reldyn = 0;
+ bfd_size_type amt;
+
+ if (! is_elf_hash_table (info->hash))
+ return FALSE;
+
+ if (info->shared)
+ abfd->flags |= DYNAMIC;
+
+ dynamic = elf_hash_table (info)->dynamic_sections_created;
+ dynobj = elf_hash_table (info)->dynobj;
+
+ emit_relocs = (info->relocatable
+ || info->emitrelocations
+ || bed->elf_backend_emit_relocs);
+
+ finfo.info = info;
+ finfo.output_bfd = abfd;
+ finfo.symstrtab = _bfd_elf_stringtab_init ();
+ if (finfo.symstrtab == NULL)
+ return FALSE;
+
+ if (! dynamic)
+ {
+ finfo.dynsym_sec = NULL;
+ finfo.hash_sec = NULL;
+ finfo.symver_sec = NULL;
+ }
+ else
+ {
+ finfo.dynsym_sec = bfd_get_section_by_name (dynobj, ".dynsym");
+ finfo.hash_sec = bfd_get_section_by_name (dynobj, ".hash");
+ BFD_ASSERT (finfo.dynsym_sec != NULL && finfo.hash_sec != NULL);
+ finfo.symver_sec = bfd_get_section_by_name (dynobj, ".gnu.version");
+ /* Note that it is OK if symver_sec is NULL. */
+ }
+
+ finfo.contents = NULL;
+ finfo.external_relocs = NULL;
+ finfo.internal_relocs = NULL;
+ finfo.external_syms = NULL;
+ finfo.locsym_shndx = NULL;
+ finfo.internal_syms = NULL;
+ finfo.indices = NULL;
+ finfo.sections = NULL;
+ finfo.symbuf = NULL;
+ finfo.symshndxbuf = NULL;
+ finfo.symbuf_count = 0;
+ finfo.shndxbuf_size = 0;
+
+ /* Count up the number of relocations we will output for each output
+ section, so that we know the sizes of the reloc sections. We
+ also figure out some maximum sizes. */
+ max_contents_size = 0;
+ max_external_reloc_size = 0;
+ max_internal_reloc_count = 0;
+ max_sym_count = 0;
+ max_sym_shndx_count = 0;
+ merged = FALSE;
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ struct bfd_elf_section_data *esdo = elf_section_data (o);
+ o->reloc_count = 0;
+
+ for (p = o->link_order_head; p != NULL; p = p->next)
+ {
+ unsigned int reloc_count = 0;
+ struct bfd_elf_section_data *esdi = NULL;
+ unsigned int *rel_count1;
+
+ if (p->type == bfd_section_reloc_link_order
+ || p->type == bfd_symbol_reloc_link_order)
+ reloc_count = 1;
+ else if (p->type == bfd_indirect_link_order)
+ {
+ asection *sec;
+
+ sec = p->u.indirect.section;
+ esdi = elf_section_data (sec);
+
+ /* Mark all sections which are to be included in the
+ link. This will normally be every section. We need
+ to do this so that we can identify any sections which
+ the linker has decided to not include. */
+ sec->linker_mark = TRUE;
+
+ if (sec->flags & SEC_MERGE)
+ merged = TRUE;
+
+ if (info->relocatable || info->emitrelocations)
+ reloc_count = sec->reloc_count;
+ else if (bed->elf_backend_count_relocs)
+ {
+ Elf_Internal_Rela * relocs;
+
+ relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
+ info->keep_memory);
+
+ reloc_count = (*bed->elf_backend_count_relocs) (sec, relocs);
+
+ if (elf_section_data (o)->relocs != relocs)
+ free (relocs);
+ }
+
+ if (sec->_raw_size > max_contents_size)
+ max_contents_size = sec->_raw_size;
+ if (sec->_cooked_size > max_contents_size)
+ max_contents_size = sec->_cooked_size;
+
+ /* We are interested in just local symbols, not all
+ symbols. */
+ if (bfd_get_flavour (sec->owner) == bfd_target_elf_flavour
+ && (sec->owner->flags & DYNAMIC) == 0)
+ {
+ size_t sym_count;
+
+ if (elf_bad_symtab (sec->owner))
+ sym_count = (elf_tdata (sec->owner)->symtab_hdr.sh_size
+ / bed->s->sizeof_sym);
+ else
+ sym_count = elf_tdata (sec->owner)->symtab_hdr.sh_info;
+
+ if (sym_count > max_sym_count)
+ max_sym_count = sym_count;
+
+ if (sym_count > max_sym_shndx_count
+ && elf_symtab_shndx (sec->owner) != 0)
+ max_sym_shndx_count = sym_count;
+
+ if ((sec->flags & SEC_RELOC) != 0)
+ {
+ size_t ext_size;
+
+ ext_size = elf_section_data (sec)->rel_hdr.sh_size;
+ if (ext_size > max_external_reloc_size)
+ max_external_reloc_size = ext_size;
+ if (sec->reloc_count > max_internal_reloc_count)
+ max_internal_reloc_count = sec->reloc_count;
+ }
+ }
+ }
+
+ if (reloc_count == 0)
+ continue;
+
+ o->reloc_count += reloc_count;
+
+ /* MIPS may have a mix of REL and RELA relocs on sections.
+ To support this curious ABI we keep reloc counts in
+ elf_section_data too. We must be careful to add the
+ relocations from the input section to the right output
+ count. FIXME: Get rid of one count. We have
+ o->reloc_count == esdo->rel_count + esdo->rel_count2. */
+ rel_count1 = &esdo->rel_count;
+ if (esdi != NULL)
+ {
+ bfd_boolean same_size;
+ bfd_size_type entsize1;
+
+ entsize1 = esdi->rel_hdr.sh_entsize;
+ BFD_ASSERT (entsize1 == bed->s->sizeof_rel
+ || entsize1 == bed->s->sizeof_rela);
+ same_size = !o->use_rela_p == (entsize1 == bed->s->sizeof_rel);
+
+ if (!same_size)
+ rel_count1 = &esdo->rel_count2;
+
+ if (esdi->rel_hdr2 != NULL)
+ {
+ bfd_size_type entsize2 = esdi->rel_hdr2->sh_entsize;
+ unsigned int alt_count;
+ unsigned int *rel_count2;
+
+ BFD_ASSERT (entsize2 != entsize1
+ && (entsize2 == bed->s->sizeof_rel
+ || entsize2 == bed->s->sizeof_rela));
+
+ rel_count2 = &esdo->rel_count2;
+ if (!same_size)
+ rel_count2 = &esdo->rel_count;
+
+ /* The following is probably too simplistic if the
+ backend counts output relocs unusually. */
+ BFD_ASSERT (bed->elf_backend_count_relocs == NULL);
+ alt_count = NUM_SHDR_ENTRIES (esdi->rel_hdr2);
+ *rel_count2 += alt_count;
+ reloc_count -= alt_count;
+ }
+ }
+ *rel_count1 += reloc_count;
+ }
+
+ if (o->reloc_count > 0)
+ o->flags |= SEC_RELOC;
+ else
+ {
+ /* Explicitly clear the SEC_RELOC flag. The linker tends to
+ set it (this is probably a bug) and if it is set
+ assign_section_numbers will create a reloc section. */
+ o->flags &=~ SEC_RELOC;
+ }
+
+ /* If the SEC_ALLOC flag is not set, force the section VMA to
+ zero. This is done in elf_fake_sections as well, but forcing
+ the VMA to 0 here will ensure that relocs against these
+ sections are handled correctly. */
+ if ((o->flags & SEC_ALLOC) == 0
+ && ! o->user_set_vma)
+ o->vma = 0;
+ }
+
+ if (! info->relocatable && merged)
+ elf_link_hash_traverse (elf_hash_table (info),
+ _bfd_elf_link_sec_merge_syms, abfd);
+
+ /* Figure out the file positions for everything but the symbol table
+ and the relocs. We set symcount to force assign_section_numbers
+ to create a symbol table. */
+ bfd_get_symcount (abfd) = info->strip == strip_all ? 0 : 1;
+ BFD_ASSERT (! abfd->output_has_begun);
+ if (! _bfd_elf_compute_section_file_positions (abfd, info))
+ goto error_return;
+
+ /* That created the reloc sections. Set their sizes, and assign
+ them file positions, and allocate some buffers. */
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ if ((o->flags & SEC_RELOC) != 0)
+ {
+ if (!(_bfd_elf_link_size_reloc_section
+ (abfd, &elf_section_data (o)->rel_hdr, o)))
+ goto error_return;
+
+ if (elf_section_data (o)->rel_hdr2
+ && !(_bfd_elf_link_size_reloc_section
+ (abfd, elf_section_data (o)->rel_hdr2, o)))
+ goto error_return;
+ }
+
+ /* Now, reset REL_COUNT and REL_COUNT2 so that we can use them
+ to count upwards while actually outputting the relocations. */
+ elf_section_data (o)->rel_count = 0;
+ elf_section_data (o)->rel_count2 = 0;
+ }
+
+ _bfd_elf_assign_file_positions_for_relocs (abfd);
+
+ /* We have now assigned file positions for all the sections except
+ .symtab and .strtab. We start the .symtab section at the current
+ file position, and write directly to it. We build the .strtab
+ section in memory. */
+ bfd_get_symcount (abfd) = 0;
+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+ /* sh_name is set in prep_headers. */
+ symtab_hdr->sh_type = SHT_SYMTAB;
+ /* sh_flags, sh_addr and sh_size all start off zero. */
+ symtab_hdr->sh_entsize = bed->s->sizeof_sym;
+ /* sh_link is set in assign_section_numbers. */
+ /* sh_info is set below. */
+ /* sh_offset is set just below. */
+ symtab_hdr->sh_addralign = 1 << bed->s->log_file_align;
+
+ off = elf_tdata (abfd)->next_file_pos;
+ off = _bfd_elf_assign_file_position_for_section (symtab_hdr, off, TRUE);
+
+ /* Note that at this point elf_tdata (abfd)->next_file_pos is
+ incorrect. We do not yet know the size of the .symtab section.
+ We correct next_file_pos below, after we do know the size. */
+
+ /* Allocate a buffer to hold swapped out symbols. This is to avoid
+ continuously seeking to the right position in the file. */
+ if (! info->keep_memory || max_sym_count < 20)
+ finfo.symbuf_size = 20;
+ else
+ finfo.symbuf_size = max_sym_count;
+ amt = finfo.symbuf_size;
+ amt *= bed->s->sizeof_sym;
+ finfo.symbuf = bfd_malloc (amt);
+ if (finfo.symbuf == NULL)
+ goto error_return;
+ if (elf_numsections (abfd) > SHN_LORESERVE)
+ {
+ /* Wild guess at number of output symbols. realloc'd as needed. */
+ amt = 2 * max_sym_count + elf_numsections (abfd) + 1000;
+ finfo.shndxbuf_size = amt;
+ amt *= sizeof (Elf_External_Sym_Shndx);
+ finfo.symshndxbuf = bfd_zmalloc (amt);
+ if (finfo.symshndxbuf == NULL)
+ goto error_return;
+ }
+
+ /* Start writing out the symbol table. The first symbol is always a
+ dummy symbol. */
+ if (info->strip != strip_all
+ || emit_relocs)
+ {
+ elfsym.st_value = 0;
+ elfsym.st_size = 0;
+ elfsym.st_info = 0;
+ elfsym.st_other = 0;
+ elfsym.st_shndx = SHN_UNDEF;
+ if (! elf_link_output_sym (&finfo, NULL, &elfsym, bfd_und_section_ptr,
+ NULL))
+ goto error_return;
+ }
+
+#if 0
+ /* Some standard ELF linkers do this, but we don't because it causes
+ bootstrap comparison failures. */
+ /* Output a file symbol for the output file as the second symbol.
+ We output this even if we are discarding local symbols, although
+ I'm not sure if this is correct. */
+ elfsym.st_value = 0;
+ elfsym.st_size = 0;
+ elfsym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FILE);
+ elfsym.st_other = 0;
+ elfsym.st_shndx = SHN_ABS;
+ if (! elf_link_output_sym (&finfo, bfd_get_filename (abfd),
+ &elfsym, bfd_abs_section_ptr, NULL))
+ goto error_return;
+#endif
+
+ /* Output a symbol for each section. We output these even if we are
+ discarding local symbols, since they are used for relocs. These
+ symbols have no names. We store the index of each one in the
+ index field of the section, so that we can find it again when
+ outputting relocs. */
+ if (info->strip != strip_all
+ || emit_relocs)
+ {
+ elfsym.st_size = 0;
+ elfsym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
+ elfsym.st_other = 0;
+ for (i = 1; i < elf_numsections (abfd); i++)
+ {
+ o = bfd_section_from_elf_index (abfd, i);
+ if (o != NULL)
+ o->target_index = bfd_get_symcount (abfd);
+ elfsym.st_shndx = i;
+ if (info->relocatable || o == NULL)
+ elfsym.st_value = 0;
+ else
+ elfsym.st_value = o->vma;
+ if (! elf_link_output_sym (&finfo, NULL, &elfsym, o, NULL))
+ goto error_return;
+ if (i == SHN_LORESERVE - 1)
+ i += SHN_HIRESERVE + 1 - SHN_LORESERVE;
+ }
+ }
+
+ /* Allocate some memory to hold information read in from the input
+ files. */
+ if (max_contents_size != 0)
+ {
+ finfo.contents = bfd_malloc (max_contents_size);
+ if (finfo.contents == NULL)
+ goto error_return;
+ }
+
+ if (max_external_reloc_size != 0)
+ {
+ finfo.external_relocs = bfd_malloc (max_external_reloc_size);
+ if (finfo.external_relocs == NULL)
+ goto error_return;
+ }
+
+ if (max_internal_reloc_count != 0)
+ {
+ amt = max_internal_reloc_count * bed->s->int_rels_per_ext_rel;
+ amt *= sizeof (Elf_Internal_Rela);
+ finfo.internal_relocs = bfd_malloc (amt);
+ if (finfo.internal_relocs == NULL)
+ goto error_return;
+ }
+
+ if (max_sym_count != 0)
+ {
+ amt = max_sym_count * bed->s->sizeof_sym;
+ finfo.external_syms = bfd_malloc (amt);
+ if (finfo.external_syms == NULL)
+ goto error_return;
+
+ amt = max_sym_count * sizeof (Elf_Internal_Sym);
+ finfo.internal_syms = bfd_malloc (amt);
+ if (finfo.internal_syms == NULL)
+ goto error_return;
+
+ amt = max_sym_count * sizeof (long);
+ finfo.indices = bfd_malloc (amt);
+ if (finfo.indices == NULL)
+ goto error_return;
+
+ amt = max_sym_count * sizeof (asection *);
+ finfo.sections = bfd_malloc (amt);
+ if (finfo.sections == NULL)
+ goto error_return;
+ }
+
+ if (max_sym_shndx_count != 0)
+ {
+ amt = max_sym_shndx_count * sizeof (Elf_External_Sym_Shndx);
+ finfo.locsym_shndx = bfd_malloc (amt);
+ if (finfo.locsym_shndx == NULL)
+ goto error_return;
+ }
+
+ if (elf_hash_table (info)->tls_sec)
+ {
+ bfd_vma base, end = 0;
+ asection *sec;
+
+ for (sec = elf_hash_table (info)->tls_sec;
+ sec && (sec->flags & SEC_THREAD_LOCAL);
+ sec = sec->next)
+ {
+ bfd_vma size = sec->_raw_size;
+
+ if (size == 0 && (sec->flags & SEC_HAS_CONTENTS) == 0)
+ {
+ struct bfd_link_order *o;
+
+ for (o = sec->link_order_head; o != NULL; o = o->next)
+ if (size < o->offset + o->size)
+ size = o->offset + o->size;
+ }
+ end = sec->vma + size;
+ }
+ base = elf_hash_table (info)->tls_sec->vma;
+ end = align_power (end, elf_hash_table (info)->tls_sec->alignment_power);
+ elf_hash_table (info)->tls_size = end - base;
+ }
+
+ /* Since ELF permits relocations to be against local symbols, we
+ must have the local symbols available when we do the relocations.
+ Since we would rather only read the local symbols once, and we
+ would rather not keep them in memory, we handle all the
+ relocations for a single input file at the same time.
+
+ Unfortunately, there is no way to know the total number of local
+ symbols until we have seen all of them, and the local symbol
+ indices precede the global symbol indices. This means that when
+ we are generating relocatable output, and we see a reloc against
+ a global symbol, we can not know the symbol index until we have
+ finished examining all the local symbols to see which ones we are
+ going to output. To deal with this, we keep the relocations in
+ memory, and don't output them until the end of the link. This is
+ an unfortunate waste of memory, but I don't see a good way around
+ it. Fortunately, it only happens when performing a relocatable
+ link, which is not the common case. FIXME: If keep_memory is set
+ we could write the relocs out and then read them again; I don't
+ know how bad the memory loss will be. */
+
+ for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+ sub->output_has_begun = FALSE;
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ for (p = o->link_order_head; p != NULL; p = p->next)
+ {
+ if (p->type == bfd_indirect_link_order
+ && (bfd_get_flavour ((sub = p->u.indirect.section->owner))
+ == bfd_target_elf_flavour)
+ && elf_elfheader (sub)->e_ident[EI_CLASS] == bed->s->elfclass)
+ {
+ if (! sub->output_has_begun)
+ {
+ if (! elf_link_input_bfd (&finfo, sub))
+ goto error_return;
+ sub->output_has_begun = TRUE;
+ }
+ }
+ else if (p->type == bfd_section_reloc_link_order
+ || p->type == bfd_symbol_reloc_link_order)
+ {
+ if (! elf_reloc_link_order (abfd, info, o, p))
+ goto error_return;
+ }
+ else
+ {
+ if (! _bfd_default_link_order (abfd, info, o, p))
+ goto error_return;
+ }
+ }
+ }
+
+ /* Output any global symbols that got converted to local in a
+ version script or due to symbol visibility. We do this in a
+ separate step since ELF requires all local symbols to appear
+ prior to any global symbols. FIXME: We should only do this if
+ some global symbols were, in fact, converted to become local.
+ FIXME: Will this work correctly with the Irix 5 linker? */
+ eoinfo.failed = FALSE;
+ eoinfo.finfo = &finfo;
+ eoinfo.localsyms = TRUE;
+ elf_link_hash_traverse (elf_hash_table (info), elf_link_output_extsym,
+ &eoinfo);
+ if (eoinfo.failed)
+ return FALSE;
+
+ /* That wrote out all the local symbols. Finish up the symbol table
+ with the global symbols. Even if we want to strip everything we
+ can, we still need to deal with those global symbols that got
+ converted to local in a version script. */
+
+ /* The sh_info field records the index of the first non local symbol. */
+ symtab_hdr->sh_info = bfd_get_symcount (abfd);
+
+ if (dynamic
+ && finfo.dynsym_sec->output_section != bfd_abs_section_ptr)
+ {
+ Elf_Internal_Sym sym;
+ bfd_byte *dynsym = finfo.dynsym_sec->contents;
+ long last_local = 0;
+
+ /* Write out the section symbols for the output sections. */
+ if (info->shared)
+ {
+ asection *s;
+
+ sym.st_size = 0;
+ sym.st_name = 0;
+ sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
+ sym.st_other = 0;
+
+ for (s = abfd->sections; s != NULL; s = s->next)
+ {
+ int indx;
+ bfd_byte *dest;
+ long dynindx;
+
+ indx = elf_section_data (s)->this_idx;
+ dynindx = elf_section_data (s)->dynindx;
+ BFD_ASSERT (indx > 0);
+ sym.st_shndx = indx;
+ sym.st_value = s->vma;
+ dest = dynsym + dynindx * bed->s->sizeof_sym;
+ bed->s->swap_symbol_out (abfd, &sym, dest, 0);
+ }
+
+ last_local = bfd_count_sections (abfd);
+ }
+
+ /* Write out the local dynsyms. */
+ if (elf_hash_table (info)->dynlocal)
+ {
+ struct elf_link_local_dynamic_entry *e;
+ for (e = elf_hash_table (info)->dynlocal; e ; e = e->next)
+ {
+ asection *s;
+ bfd_byte *dest;
+
+ sym.st_size = e->isym.st_size;
+ sym.st_other = e->isym.st_other;
+
+ /* Copy the internal symbol as is.
+ Note that we saved a word of storage and overwrote
+ the original st_name with the dynstr_index. */
+ sym = e->isym;
+
+ if (e->isym.st_shndx != SHN_UNDEF
+ && (e->isym.st_shndx < SHN_LORESERVE
+ || e->isym.st_shndx > SHN_HIRESERVE))
+ {
+ s = bfd_section_from_elf_index (e->input_bfd,
+ e->isym.st_shndx);
+
+ sym.st_shndx =
+ elf_section_data (s->output_section)->this_idx;
+ sym.st_value = (s->output_section->vma
+ + s->output_offset
+ + e->isym.st_value);
+ }
+
+ if (last_local < e->dynindx)
+ last_local = e->dynindx;
+
+ dest = dynsym + e->dynindx * bed->s->sizeof_sym;
+ bed->s->swap_symbol_out (abfd, &sym, dest, 0);
+ }
+ }
+
+ elf_section_data (finfo.dynsym_sec->output_section)->this_hdr.sh_info =
+ last_local + 1;
+ }
+
+ /* We get the global symbols from the hash table. */
+ eoinfo.failed = FALSE;
+ eoinfo.localsyms = FALSE;
+ eoinfo.finfo = &finfo;
+ elf_link_hash_traverse (elf_hash_table (info), elf_link_output_extsym,
+ &eoinfo);
+ if (eoinfo.failed)
+ return FALSE;
+
+ /* If backend needs to output some symbols not present in the hash
+ table, do it now. */
+ if (bed->elf_backend_output_arch_syms)
+ {
+ typedef bfd_boolean (*out_sym_func)
+ (void *, const char *, Elf_Internal_Sym *, asection *,
+ struct elf_link_hash_entry *);
+
+ if (! ((*bed->elf_backend_output_arch_syms)
+ (abfd, info, &finfo, (out_sym_func) elf_link_output_sym)))
+ return FALSE;
+ }
+
+ /* Flush all symbols to the file. */
+ if (! elf_link_flush_output_syms (&finfo, bed))
+ return FALSE;
+
+ /* Now we know the size of the symtab section. */
+ off += symtab_hdr->sh_size;
+
+ symtab_shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
+ if (symtab_shndx_hdr->sh_name != 0)
+ {
+ symtab_shndx_hdr->sh_type = SHT_SYMTAB_SHNDX;
+ symtab_shndx_hdr->sh_entsize = sizeof (Elf_External_Sym_Shndx);
+ symtab_shndx_hdr->sh_addralign = sizeof (Elf_External_Sym_Shndx);
+ amt = bfd_get_symcount (abfd) * sizeof (Elf_External_Sym_Shndx);
+ symtab_shndx_hdr->sh_size = amt;
+
+ off = _bfd_elf_assign_file_position_for_section (symtab_shndx_hdr,
+ off, TRUE);
+
+ if (bfd_seek (abfd, symtab_shndx_hdr->sh_offset, SEEK_SET) != 0
+ || (bfd_bwrite (finfo.symshndxbuf, amt, abfd) != amt))
+ return FALSE;
+ }
+
+
+ /* Finish up and write out the symbol string table (.strtab)
+ section. */
+ symstrtab_hdr = &elf_tdata (abfd)->strtab_hdr;
+ /* sh_name was set in prep_headers. */
+ symstrtab_hdr->sh_type = SHT_STRTAB;
+ symstrtab_hdr->sh_flags = 0;
+ symstrtab_hdr->sh_addr = 0;
+ symstrtab_hdr->sh_size = _bfd_stringtab_size (finfo.symstrtab);
+ symstrtab_hdr->sh_entsize = 0;
+ symstrtab_hdr->sh_link = 0;
+ symstrtab_hdr->sh_info = 0;
+ /* sh_offset is set just below. */
+ symstrtab_hdr->sh_addralign = 1;
+
+ off = _bfd_elf_assign_file_position_for_section (symstrtab_hdr, off, TRUE);
+ elf_tdata (abfd)->next_file_pos = off;
+
+ if (bfd_get_symcount (abfd) > 0)
+ {
+ if (bfd_seek (abfd, symstrtab_hdr->sh_offset, SEEK_SET) != 0
+ || ! _bfd_stringtab_emit (abfd, finfo.symstrtab))
+ return FALSE;
+ }
+
+ /* Adjust the relocs to have the correct symbol indices. */
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ if ((o->flags & SEC_RELOC) == 0)
+ continue;
+
+ elf_link_adjust_relocs (abfd, &elf_section_data (o)->rel_hdr,
+ elf_section_data (o)->rel_count,
+ elf_section_data (o)->rel_hashes);
+ if (elf_section_data (o)->rel_hdr2 != NULL)
+ elf_link_adjust_relocs (abfd, elf_section_data (o)->rel_hdr2,
+ elf_section_data (o)->rel_count2,
+ (elf_section_data (o)->rel_hashes
+ + elf_section_data (o)->rel_count));
+
+ /* Set the reloc_count field to 0 to prevent write_relocs from
+ trying to swap the relocs out itself. */
+ o->reloc_count = 0;
+ }
+
+ if (dynamic && info->combreloc && dynobj != NULL)
+ relativecount = elf_link_sort_relocs (abfd, info, &reldyn);
+
+ /* If we are linking against a dynamic object, or generating a
+ shared library, finish up the dynamic linking information. */
+ if (dynamic)
+ {
+ bfd_byte *dyncon, *dynconend;
+
+ /* Fix up .dynamic entries. */
+ o = bfd_get_section_by_name (dynobj, ".dynamic");
+ BFD_ASSERT (o != NULL);
+
+ dyncon = o->contents;
+ dynconend = o->contents + o->_raw_size;
+ for (; dyncon < dynconend; dyncon += bed->s->sizeof_dyn)
+ {
+ Elf_Internal_Dyn dyn;
+ const char *name;
+ unsigned int type;
+
+ bed->s->swap_dyn_in (dynobj, dyncon, &dyn);
+
+ switch (dyn.d_tag)
+ {
+ default:
+ continue;
+ case DT_NULL:
+ if (relativecount > 0 && dyncon + bed->s->sizeof_dyn < dynconend)
+ {
+ switch (elf_section_data (reldyn)->this_hdr.sh_type)
+ {
+ case SHT_REL: dyn.d_tag = DT_RELCOUNT; break;
+ case SHT_RELA: dyn.d_tag = DT_RELACOUNT; break;
+ default: continue;
+ }
+ dyn.d_un.d_val = relativecount;
+ relativecount = 0;
+ break;
+ }
+ continue;
+
+ case DT_INIT:
+ name = info->init_function;
+ goto get_sym;
+ case DT_FINI:
+ name = info->fini_function;
+ get_sym:
+ {
+ struct elf_link_hash_entry *h;
+
+ h = elf_link_hash_lookup (elf_hash_table (info), name,
+ FALSE, FALSE, TRUE);
+ if (h != NULL
+ && (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak))
+ {
+ dyn.d_un.d_val = h->root.u.def.value;
+ o = h->root.u.def.section;
+ if (o->output_section != NULL)
+ dyn.d_un.d_val += (o->output_section->vma
+ + o->output_offset);
+ else
+ {
+ /* The symbol is imported from another shared
+ library and does not apply to this one. */
+ dyn.d_un.d_val = 0;
+ }
+ break;
+ }
+ }
+ continue;
+
+ case DT_PREINIT_ARRAYSZ:
+ name = ".preinit_array";
+ goto get_size;
+ case DT_INIT_ARRAYSZ:
+ name = ".init_array";
+ goto get_size;
+ case DT_FINI_ARRAYSZ:
+ name = ".fini_array";
+ get_size:
+ o = bfd_get_section_by_name (abfd, name);
+ if (o == NULL)
+ {
+ (*_bfd_error_handler)
+ (_("%s: could not find output section %s"),
+ bfd_get_filename (abfd), name);
+ goto error_return;
+ }
+ if (o->_raw_size == 0)
+ (*_bfd_error_handler)
+ (_("warning: %s section has zero size"), name);
+ dyn.d_un.d_val = o->_raw_size;
+ break;
+
+ case DT_PREINIT_ARRAY:
+ name = ".preinit_array";
+ goto get_vma;
+ case DT_INIT_ARRAY:
+ name = ".init_array";
+ goto get_vma;
+ case DT_FINI_ARRAY:
+ name = ".fini_array";
+ goto get_vma;
+
+ case DT_HASH:
+ name = ".hash";
+ goto get_vma;
+ case DT_STRTAB:
+ name = ".dynstr";
+ goto get_vma;
+ case DT_SYMTAB:
+ name = ".dynsym";
+ goto get_vma;
+ case DT_VERDEF:
+ name = ".gnu.version_d";
+ goto get_vma;
+ case DT_VERNEED:
+ name = ".gnu.version_r";
+ goto get_vma;
+ case DT_VERSYM:
+ name = ".gnu.version";
+ get_vma:
+ o = bfd_get_section_by_name (abfd, name);
+ if (o == NULL)
+ {
+ (*_bfd_error_handler)
+ (_("%s: could not find output section %s"),
+ bfd_get_filename (abfd), name);
+ goto error_return;
+ }
+ dyn.d_un.d_ptr = o->vma;
+ break;
+
+ case DT_REL:
+ case DT_RELA:
+ case DT_RELSZ:
+ case DT_RELASZ:
+ if (dyn.d_tag == DT_REL || dyn.d_tag == DT_RELSZ)
+ type = SHT_REL;
+ else
+ type = SHT_RELA;
+ dyn.d_un.d_val = 0;
+ for (i = 1; i < elf_numsections (abfd); i++)
+ {
+ Elf_Internal_Shdr *hdr;
+
+ hdr = elf_elfsections (abfd)[i];
+ if (hdr->sh_type == type
+ && (hdr->sh_flags & SHF_ALLOC) != 0)
+ {
+ if (dyn.d_tag == DT_RELSZ || dyn.d_tag == DT_RELASZ)
+ dyn.d_un.d_val += hdr->sh_size;
+ else
+ {
+ if (dyn.d_un.d_val == 0
+ || hdr->sh_addr < dyn.d_un.d_val)
+ dyn.d_un.d_val = hdr->sh_addr;
+ }
+ }
+ }
+ break;
+ }
+ bed->s->swap_dyn_out (dynobj, &dyn, dyncon);
+ }
+ }
+
+ /* If we have created any dynamic sections, then output them. */
+ if (dynobj != NULL)
+ {
+ if (! (*bed->elf_backend_finish_dynamic_sections) (abfd, info))
+ goto error_return;
+
+ for (o = dynobj->sections; o != NULL; o = o->next)
+ {
+ if ((o->flags & SEC_HAS_CONTENTS) == 0
+ || o->_raw_size == 0
+ || o->output_section == bfd_abs_section_ptr)
+ continue;
+ if ((o->flags & SEC_LINKER_CREATED) == 0)
+ {
+ /* At this point, we are only interested in sections
+ created by _bfd_elf_link_create_dynamic_sections. */
+ continue;
+ }
+ if ((elf_section_data (o->output_section)->this_hdr.sh_type
+ != SHT_STRTAB)
+ || strcmp (bfd_get_section_name (abfd, o), ".dynstr") != 0)
+ {
+ if (! bfd_set_section_contents (abfd, o->output_section,
+ o->contents,
+ (file_ptr) o->output_offset,
+ o->_raw_size))
+ goto error_return;
+ }
+ else
+ {
+ /* The contents of the .dynstr section are actually in a
+ stringtab. */
+ off = elf_section_data (o->output_section)->this_hdr.sh_offset;
+ if (bfd_seek (abfd, off, SEEK_SET) != 0
+ || ! _bfd_elf_strtab_emit (abfd,
+ elf_hash_table (info)->dynstr))
+ goto error_return;
+ }
+ }
+ }
+
+ if (info->relocatable)
+ {
+ bfd_boolean failed = FALSE;
+
+ bfd_map_over_sections (abfd, bfd_elf_set_group_contents, &failed);
+ if (failed)
+ goto error_return;
+ }
+
+ /* If we have optimized stabs strings, output them. */
+ if (elf_hash_table (info)->stab_info != NULL)
+ {
+ if (! _bfd_write_stab_strings (abfd, &elf_hash_table (info)->stab_info))
+ goto error_return;
+ }
+
+ if (info->eh_frame_hdr)
+ {
+ if (! _bfd_elf_write_section_eh_frame_hdr (abfd, info))
+ goto error_return;
+ }
+
+ if (finfo.symstrtab != NULL)
+ _bfd_stringtab_free (finfo.symstrtab);
+ if (finfo.contents != NULL)
+ free (finfo.contents);
+ if (finfo.external_relocs != NULL)
+ free (finfo.external_relocs);
+ if (finfo.internal_relocs != NULL)
+ free (finfo.internal_relocs);
+ if (finfo.external_syms != NULL)
+ free (finfo.external_syms);
+ if (finfo.locsym_shndx != NULL)
+ free (finfo.locsym_shndx);
+ if (finfo.internal_syms != NULL)
+ free (finfo.internal_syms);
+ if (finfo.indices != NULL)
+ free (finfo.indices);
+ if (finfo.sections != NULL)
+ free (finfo.sections);
+ if (finfo.symbuf != NULL)
+ free (finfo.symbuf);
+ if (finfo.symshndxbuf != NULL)
+ free (finfo.symshndxbuf);
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ if ((o->flags & SEC_RELOC) != 0
+ && elf_section_data (o)->rel_hashes != NULL)
+ free (elf_section_data (o)->rel_hashes);
+ }
+
+ elf_tdata (abfd)->linker = TRUE;
+
+ return TRUE;
+
+ error_return:
+ if (finfo.symstrtab != NULL)
+ _bfd_stringtab_free (finfo.symstrtab);
+ if (finfo.contents != NULL)
+ free (finfo.contents);
+ if (finfo.external_relocs != NULL)
+ free (finfo.external_relocs);
+ if (finfo.internal_relocs != NULL)
+ free (finfo.internal_relocs);
+ if (finfo.external_syms != NULL)
+ free (finfo.external_syms);
+ if (finfo.locsym_shndx != NULL)
+ free (finfo.locsym_shndx);
+ if (finfo.internal_syms != NULL)
+ free (finfo.internal_syms);
+ if (finfo.indices != NULL)
+ free (finfo.indices);
+ if (finfo.sections != NULL)
+ free (finfo.sections);
+ if (finfo.symbuf != NULL)
+ free (finfo.symbuf);
+ if (finfo.symshndxbuf != NULL)
+ free (finfo.symshndxbuf);
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ if ((o->flags & SEC_RELOC) != 0
+ && elf_section_data (o)->rel_hashes != NULL)
+ free (elf_section_data (o)->rel_hashes);
+ }
+
+ return FALSE;
+}
+\f
+/* Garbage collect unused sections. */
+
+/* The mark phase of garbage collection. For a given section, mark
+ it and any sections in this section's group, and all the sections
+ which define symbols to which it refers. */
+
+typedef asection * (*gc_mark_hook_fn)
+ (asection *, struct bfd_link_info *, Elf_Internal_Rela *,
+ struct elf_link_hash_entry *, Elf_Internal_Sym *);
+
+static bfd_boolean
+elf_gc_mark (struct bfd_link_info *info,
+ asection *sec,
+ gc_mark_hook_fn gc_mark_hook)
+{
+ bfd_boolean ret;
+ asection *group_sec;
+
+ sec->gc_mark = 1;
+
+ /* Mark all the sections in the group. */
+ group_sec = elf_section_data (sec)->next_in_group;
+ if (group_sec && !group_sec->gc_mark)
+ if (!elf_gc_mark (info, group_sec, gc_mark_hook))
+ return FALSE;
+
+ /* Look through the section relocs. */
+ ret = TRUE;
+ if ((sec->flags & SEC_RELOC) != 0 && sec->reloc_count > 0)
+ {
+ Elf_Internal_Rela *relstart, *rel, *relend;
+ Elf_Internal_Shdr *symtab_hdr;
+ struct elf_link_hash_entry **sym_hashes;
+ size_t nlocsyms;
+ size_t extsymoff;
+ bfd *input_bfd = sec->owner;
+ const struct elf_backend_data *bed = get_elf_backend_data (input_bfd);
+ Elf_Internal_Sym *isym = NULL;
+ int r_sym_shift;
+
+ symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
+ sym_hashes = elf_sym_hashes (input_bfd);
+
+ /* Read the local symbols. */
+ if (elf_bad_symtab (input_bfd))
+ {
+ nlocsyms = symtab_hdr->sh_size / bed->s->sizeof_sym;
+ extsymoff = 0;
+ }
+ else
+ extsymoff = nlocsyms = symtab_hdr->sh_info;
+
+ isym = (Elf_Internal_Sym *) symtab_hdr->contents;
+ if (isym == NULL && nlocsyms != 0)
+ {
+ isym = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, nlocsyms, 0,
+ NULL, NULL, NULL);
+ if (isym == NULL)
+ return FALSE;
+ }
+
+ /* Read the relocations. */
+ relstart = _bfd_elf_link_read_relocs (input_bfd, sec, NULL, NULL,
+ info->keep_memory);
+ if (relstart == NULL)
+ {
+ ret = FALSE;
+ goto out1;
+ }
+ relend = relstart + sec->reloc_count * bed->s->int_rels_per_ext_rel;
+
+ if (bed->s->arch_size == 32)
+ r_sym_shift = 8;
+ else
+ r_sym_shift = 32;
+
+ for (rel = relstart; rel < relend; rel++)
+ {
+ unsigned long r_symndx;
+ asection *rsec;
+ struct elf_link_hash_entry *h;
+
+ r_symndx = rel->r_info >> r_sym_shift;
+ if (r_symndx == 0)
+ continue;
+
+ if (r_symndx >= nlocsyms
+ || ELF_ST_BIND (isym[r_symndx].st_info) != STB_LOCAL)
+ {
+ h = sym_hashes[r_symndx - extsymoff];
+ rsec = (*gc_mark_hook) (sec, info, rel, h, NULL);
+ }
+ else
+ {
+ rsec = (*gc_mark_hook) (sec, info, rel, NULL, &isym[r_symndx]);
+ }
+
+ if (rsec && !rsec->gc_mark)
+ {
+ if (bfd_get_flavour (rsec->owner) != bfd_target_elf_flavour)
+ rsec->gc_mark = 1;
+ else if (!elf_gc_mark (info, rsec, gc_mark_hook))
+ {
+ ret = FALSE;
+ goto out2;
+ }
+ }
+ }
+
+ out2:
+ if (elf_section_data (sec)->relocs != relstart)
+ free (relstart);
+ out1:
+ if (isym != NULL && symtab_hdr->contents != (unsigned char *) isym)
+ {
+ if (! info->keep_memory)
+ free (isym);
+ else
+ symtab_hdr->contents = (unsigned char *) isym;
+ }
+ }
+
+ return ret;
+}
+
+/* Sweep symbols in swept sections. Called via elf_link_hash_traverse. */
+
+static bfd_boolean
+elf_gc_sweep_symbol (struct elf_link_hash_entry *h, void *idxptr)
+{
+ int *idx = idxptr;
+
+ if (h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+ if (h->dynindx != -1
+ && ((h->root.type != bfd_link_hash_defined
+ && h->root.type != bfd_link_hash_defweak)
+ || h->root.u.def.section->gc_mark))
+ h->dynindx = (*idx)++;
+
+ return TRUE;
+}
+
+/* The sweep phase of garbage collection. Remove all garbage sections. */
+
+typedef bfd_boolean (*gc_sweep_hook_fn)
+ (bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *);
+
+static bfd_boolean
+elf_gc_sweep (struct bfd_link_info *info, gc_sweep_hook_fn gc_sweep_hook)
+{
+ bfd *sub;
+
+ for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+ {
+ asection *o;
+
+ if (bfd_get_flavour (sub) != bfd_target_elf_flavour)
+ continue;
+
+ for (o = sub->sections; o != NULL; o = o->next)
+ {
+ /* Keep special sections. Keep .debug sections. */
+ if ((o->flags & SEC_LINKER_CREATED)
+ || (o->flags & SEC_DEBUGGING))
+ o->gc_mark = 1;
+
+ if (o->gc_mark)
+ continue;
+
+ /* Skip sweeping sections already excluded. */
+ if (o->flags & SEC_EXCLUDE)
+ continue;
+
+ /* Since this is early in the link process, it is simple
+ to remove a section from the output. */
+ o->flags |= SEC_EXCLUDE;
+
+ /* But we also have to update some of the relocation
+ info we collected before. */
+ if (gc_sweep_hook
+ && (o->flags & SEC_RELOC) && o->reloc_count > 0)
+ {
+ Elf_Internal_Rela *internal_relocs;
+ bfd_boolean r;
+
+ internal_relocs
+ = _bfd_elf_link_read_relocs (o->owner, o, NULL, NULL,
+ info->keep_memory);
+ if (internal_relocs == NULL)
+ return FALSE;
+
+ r = (*gc_sweep_hook) (o->owner, info, o, internal_relocs);
+
+ if (elf_section_data (o)->relocs != internal_relocs)
+ free (internal_relocs);
+
+ if (!r)
+ return FALSE;
+ }
+ }
+ }
+
+ /* Remove the symbols that were in the swept sections from the dynamic
+ symbol table. GCFIXME: Anyone know how to get them out of the
+ static symbol table as well? */
+ {
+ int i = 0;
+
+ elf_link_hash_traverse (elf_hash_table (info), elf_gc_sweep_symbol, &i);
+
+ elf_hash_table (info)->dynsymcount = i;
+ }
+
+ return TRUE;
+}
+
+/* Propagate collected vtable information. This is called through
+ elf_link_hash_traverse. */
+
+static bfd_boolean
+elf_gc_propagate_vtable_entries_used (struct elf_link_hash_entry *h, void *okp)
+{
+ if (h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+ /* Those that are not vtables. */
+ if (h->vtable_parent == NULL)
+ return TRUE;
+
+ /* Those vtables that do not have parents, we cannot merge. */
+ if (h->vtable_parent == (struct elf_link_hash_entry *) -1)
+ return TRUE;
+
+ /* If we've already been done, exit. */
+ if (h->vtable_entries_used && h->vtable_entries_used[-1])
+ return TRUE;
+
+ /* Make sure the parent's table is up to date. */
+ elf_gc_propagate_vtable_entries_used (h->vtable_parent, okp);
+
+ if (h->vtable_entries_used == NULL)
+ {
+ /* None of this table's entries were referenced. Re-use the
+ parent's table. */
+ h->vtable_entries_used = h->vtable_parent->vtable_entries_used;
+ h->vtable_entries_size = h->vtable_parent->vtable_entries_size;
+ }
+ else
+ {
+ size_t n;
+ bfd_boolean *cu, *pu;
+
+ /* Or the parent's entries into ours. */
+ cu = h->vtable_entries_used;
+ cu[-1] = TRUE;
+ pu = h->vtable_parent->vtable_entries_used;
+ if (pu != NULL)
+ {
+ const struct elf_backend_data *bed;
+ unsigned int log_file_align;
+
+ bed = get_elf_backend_data (h->root.u.def.section->owner);
+ log_file_align = bed->s->log_file_align;
+ n = h->vtable_parent->vtable_entries_size >> log_file_align;
+ while (n--)
+ {
+ if (*pu)
+ *cu = TRUE;
+ pu++;
+ cu++;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+static bfd_boolean
+elf_gc_smash_unused_vtentry_relocs (struct elf_link_hash_entry *h, void *okp)
+{
+ asection *sec;
+ bfd_vma hstart, hend;
+ Elf_Internal_Rela *relstart, *relend, *rel;
+ const struct elf_backend_data *bed;
+ unsigned int log_file_align;
+
+ if (h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+ /* Take care of both those symbols that do not describe vtables as
+ well as those that are not loaded. */
+ if (h->vtable_parent == NULL)
+ return TRUE;
+
+ BFD_ASSERT (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak);
+
+ sec = h->root.u.def.section;
+ hstart = h->root.u.def.value;
+ hend = hstart + h->size;
+
+ relstart = _bfd_elf_link_read_relocs (sec->owner, sec, NULL, NULL, TRUE);
+ if (!relstart)
+ return *(bfd_boolean *) okp = FALSE;
+ bed = get_elf_backend_data (sec->owner);
+ log_file_align = bed->s->log_file_align;
+
+ relend = relstart + sec->reloc_count * bed->s->int_rels_per_ext_rel;
+
+ for (rel = relstart; rel < relend; ++rel)
+ if (rel->r_offset >= hstart && rel->r_offset < hend)
+ {
+ /* If the entry is in use, do nothing. */
+ if (h->vtable_entries_used
+ && (rel->r_offset - hstart) < h->vtable_entries_size)
+ {
+ bfd_vma entry = (rel->r_offset - hstart) >> log_file_align;
+ if (h->vtable_entries_used[entry])
+ continue;
+ }
+ /* Otherwise, kill it. */
+ rel->r_offset = rel->r_info = rel->r_addend = 0;
+ }
+
+ return TRUE;
+}
+
+/* Do mark and sweep of unused sections. */
+
+bfd_boolean
+bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
+{
+ bfd_boolean ok = TRUE;
+ bfd *sub;
+ asection * (*gc_mark_hook)
+ (asection *, struct bfd_link_info *, Elf_Internal_Rela *,
+ struct elf_link_hash_entry *h, Elf_Internal_Sym *);
+
+ if (!get_elf_backend_data (abfd)->can_gc_sections
+ || info->relocatable
+ || info->emitrelocations
+ || !is_elf_hash_table (info->hash)
+ || elf_hash_table (info)->dynamic_sections_created)
+ {
+ (*_bfd_error_handler)(_("Warning: gc-sections option ignored"));
+ return TRUE;
+ }
+
+ /* Apply transitive closure to the vtable entry usage info. */
+ elf_link_hash_traverse (elf_hash_table (info),
+ elf_gc_propagate_vtable_entries_used,
+ &ok);
+ if (!ok)
+ return FALSE;
+
+ /* Kill the vtable relocations that were not used. */
+ elf_link_hash_traverse (elf_hash_table (info),
+ elf_gc_smash_unused_vtentry_relocs,
+ &ok);
+ if (!ok)
+ return FALSE;
+
+ /* Grovel through relocs to find out who stays ... */
+
+ gc_mark_hook = get_elf_backend_data (abfd)->gc_mark_hook;
+ for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+ {
+ asection *o;
+
+ if (bfd_get_flavour (sub) != bfd_target_elf_flavour)
+ continue;
+
+ for (o = sub->sections; o != NULL; o = o->next)
+ {
+ if (o->flags & SEC_KEEP)
+ if (!elf_gc_mark (info, o, gc_mark_hook))
+ return FALSE;
+ }
+ }
+
+ /* ... and mark SEC_EXCLUDE for those that go. */
+ if (!elf_gc_sweep (info, get_elf_backend_data (abfd)->gc_sweep_hook))
+ return FALSE;
+
+ return TRUE;
+}
+\f
+/* Called from check_relocs to record the existence of a VTINHERIT reloc. */
+
+bfd_boolean
+bfd_elf_gc_record_vtinherit (bfd *abfd,
+ asection *sec,
+ struct elf_link_hash_entry *h,
+ bfd_vma offset)
+{
+ struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
+ struct elf_link_hash_entry **search, *child;
+ bfd_size_type extsymcount;
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+
+ /* The sh_info field of the symtab header tells us where the
+ external symbols start. We don't care about the local symbols at
+ this point. */
+ extsymcount = elf_tdata (abfd)->symtab_hdr.sh_size / bed->s->sizeof_sym;
+ if (!elf_bad_symtab (abfd))
+ extsymcount -= elf_tdata (abfd)->symtab_hdr.sh_info;
+
+ sym_hashes = elf_sym_hashes (abfd);
+ sym_hashes_end = sym_hashes + extsymcount;
+
+ /* Hunt down the child symbol, which is in this section at the same
+ offset as the relocation. */
+ for (search = sym_hashes; search != sym_hashes_end; ++search)
+ {
+ if ((child = *search) != NULL
+ && (child->root.type == bfd_link_hash_defined
+ || child->root.type == bfd_link_hash_defweak)
+ && child->root.u.def.section == sec
+ && child->root.u.def.value == offset)
+ goto win;
+ }
+
+ (*_bfd_error_handler) ("%s: %s+%lu: No symbol found for INHERIT",
+ bfd_archive_filename (abfd), sec->name,
+ (unsigned long) offset);
+ bfd_set_error (bfd_error_invalid_operation);
+ return FALSE;
+
+ win:
+ if (!h)
+ {
+ /* This *should* only be the absolute section. It could potentially
+ be that someone has defined a non-global vtable though, which
+ would be bad. It isn't worth paging in the local symbols to be
+ sure though; that case should simply be handled by the assembler. */
+
+ child->vtable_parent = (struct elf_link_hash_entry *) -1;
+ }
+ else
+ child->vtable_parent = h;
+
+ return TRUE;
+}
+
+/* Called from check_relocs to record the existence of a VTENTRY reloc. */
+
+bfd_boolean
+bfd_elf_gc_record_vtentry (bfd *abfd ATTRIBUTE_UNUSED,
+ asection *sec ATTRIBUTE_UNUSED,
+ struct elf_link_hash_entry *h,
+ bfd_vma addend)
+{
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ unsigned int log_file_align = bed->s->log_file_align;
+
+ if (addend >= h->vtable_entries_size)
+ {
+ size_t size, bytes, file_align;
+ bfd_boolean *ptr = h->vtable_entries_used;
+
+ /* While the symbol is undefined, we have to be prepared to handle
+ a zero size. */
+ file_align = 1 << log_file_align;
+ if (h->root.type == bfd_link_hash_undefined)
+ size = addend + file_align;
+ else
+ {
+ size = h->size;
+ if (addend >= size)
+ {
+ /* Oops! We've got a reference past the defined end of
+ the table. This is probably a bug -- shall we warn? */
+ size = addend + file_align;
+ }
+ }
+ size = (size + file_align - 1) & -file_align;
+
+ /* Allocate one extra entry for use as a "done" flag for the
+ consolidation pass. */
+ bytes = ((size >> log_file_align) + 1) * sizeof (bfd_boolean);
+
+ if (ptr)
+ {
+ ptr = bfd_realloc (ptr - 1, bytes);
+
+ if (ptr != NULL)
+ {
+ size_t oldbytes;
+
+ oldbytes = (((h->vtable_entries_size >> log_file_align) + 1)
+ * sizeof (bfd_boolean));
+ memset (((char *) ptr) + oldbytes, 0, bytes - oldbytes);
+ }
+ }
+ else
+ ptr = bfd_zmalloc (bytes);
+
+ if (ptr == NULL)
+ return FALSE;
+
+ /* And arrange for that done flag to be at index -1. */
+ h->vtable_entries_used = ptr + 1;
+ h->vtable_entries_size = size;
+ }
+
+ h->vtable_entries_used[addend >> log_file_align] = TRUE;
+
+ return TRUE;
+}
+
+struct alloc_got_off_arg {
+ bfd_vma gotoff;
+ unsigned int got_elt_size;
+};
+
+/* We need a special top-level link routine to convert got reference counts
+ to real got offsets. */
+
+static bfd_boolean
+elf_gc_allocate_got_offsets (struct elf_link_hash_entry *h, void *arg)
+{
+ struct alloc_got_off_arg *gofarg = arg;
+
+ if (h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+ if (h->got.refcount > 0)
+ {
+ h->got.offset = gofarg->gotoff;
+ gofarg->gotoff += gofarg->got_elt_size;
+ }
+ else
+ h->got.offset = (bfd_vma) -1;
+
+ return TRUE;
+}
+
+/* And an accompanying bit to work out final got entry offsets once
+ we're done. Should be called from final_link. */
+
+bfd_boolean
+bfd_elf_gc_common_finalize_got_offsets (bfd *abfd,
+ struct bfd_link_info *info)
+{
+ bfd *i;
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ bfd_vma gotoff;
+ unsigned int got_elt_size = bed->s->arch_size / 8;
+ struct alloc_got_off_arg gofarg;
+
+ if (! is_elf_hash_table (info->hash))
+ return FALSE;
+
+ /* The GOT offset is relative to the .got section, but the GOT header is
+ put into the .got.plt section, if the backend uses it. */
+ if (bed->want_got_plt)
+ gotoff = 0;
+ else
+ gotoff = bed->got_header_size;
+
+ /* Do the local .got entries first. */
+ for (i = info->input_bfds; i; i = i->link_next)
+ {
+ bfd_signed_vma *local_got;
+ bfd_size_type j, locsymcount;
+ Elf_Internal_Shdr *symtab_hdr;
+
+ if (bfd_get_flavour (i) != bfd_target_elf_flavour)
+ continue;
+
+ local_got = elf_local_got_refcounts (i);
+ if (!local_got)
+ continue;
+
+ symtab_hdr = &elf_tdata (i)->symtab_hdr;
+ if (elf_bad_symtab (i))
+ locsymcount = symtab_hdr->sh_size / bed->s->sizeof_sym;
+ else
+ locsymcount = symtab_hdr->sh_info;
+
+ for (j = 0; j < locsymcount; ++j)
+ {
+ if (local_got[j] > 0)
+ {
+ local_got[j] = gotoff;
+ gotoff += got_elt_size;
+ }
+ else
+ local_got[j] = (bfd_vma) -1;
+ }
+ }
+
+ /* Then the global .got entries. .plt refcounts are handled by
+ adjust_dynamic_symbol */
+ gofarg.gotoff = gotoff;
+ gofarg.got_elt_size = got_elt_size;
+ elf_link_hash_traverse (elf_hash_table (info),
+ elf_gc_allocate_got_offsets,
+ &gofarg);
+ return TRUE;
+}
+
+/* Many folk need no more in the way of final link than this, once
+ got entry reference counting is enabled. */
+
+bfd_boolean
+bfd_elf_gc_common_final_link (bfd *abfd, struct bfd_link_info *info)
+{
+ if (!bfd_elf_gc_common_finalize_got_offsets (abfd, info))
+ return FALSE;
+
+ /* Invoke the regular ELF backend linker to do all the work. */
+ return bfd_elf_final_link (abfd, info);
+}
+
+bfd_boolean
+bfd_elf_reloc_symbol_deleted_p (bfd_vma offset, void *cookie)
+{
+ struct elf_reloc_cookie *rcookie = cookie;
+
+ if (rcookie->bad_symtab)
+ rcookie->rel = rcookie->rels;
+
+ for (; rcookie->rel < rcookie->relend; rcookie->rel++)
+ {
+ unsigned long r_symndx;
+
+ if (! rcookie->bad_symtab)
+ if (rcookie->rel->r_offset > offset)
+ return FALSE;
+ if (rcookie->rel->r_offset != offset)
+ continue;
+
+ r_symndx = rcookie->rel->r_info >> rcookie->r_sym_shift;
+ if (r_symndx == SHN_UNDEF)
+ return TRUE;
+
+ if (r_symndx >= rcookie->locsymcount
+ || ELF_ST_BIND (rcookie->locsyms[r_symndx].st_info) != STB_LOCAL)
+ {
+ struct elf_link_hash_entry *h;
+
+ h = rcookie->sym_hashes[r_symndx - rcookie->extsymoff];
+
+ while (h->root.type == bfd_link_hash_indirect
+ || h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+ if ((h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && elf_discarded_section (h->root.u.def.section))
+ return TRUE;
+ else
+ return FALSE;
+ }
+ else
+ {
+ /* It's not a relocation against a global symbol,
+ but it could be a relocation against a local
+ symbol for a discarded section. */
+ asection *isec;
+ Elf_Internal_Sym *isym;
+
+ /* Need to: get the symbol; get the section. */
+ isym = &rcookie->locsyms[r_symndx];
+ if (isym->st_shndx < SHN_LORESERVE || isym->st_shndx > SHN_HIRESERVE)
+ {
+ isec = bfd_section_from_elf_index (rcookie->abfd, isym->st_shndx);
+ if (isec != NULL && elf_discarded_section (isec))
+ return TRUE;
+ }
+ }
+ return FALSE;
+ }
+ return FALSE;
+}
+
+/* Discard unneeded references to discarded sections.
+ Returns TRUE if any section's size was changed. */
+/* This function assumes that the relocations are in sorted order,
+ which is true for all known assemblers. */
+
+bfd_boolean
+bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
+{
+ struct elf_reloc_cookie cookie;
+ asection *stab, *eh;
+ Elf_Internal_Shdr *symtab_hdr;
+ const struct elf_backend_data *bed;
+ bfd *abfd;
+ unsigned int count;
+ bfd_boolean ret = FALSE;
+
+ if (info->traditional_format
+ || !is_elf_hash_table (info->hash))
+ return FALSE;
+
+ for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link_next)
+ {
+ if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
+ continue;
+
+ bed = get_elf_backend_data (abfd);
+
+ if ((abfd->flags & DYNAMIC) != 0)
+ continue;
+
+ eh = bfd_get_section_by_name (abfd, ".eh_frame");
+ if (info->relocatable
+ || (eh != NULL
+ && (eh->_raw_size == 0
+ || bfd_is_abs_section (eh->output_section))))
+ eh = NULL;
+
+ stab = bfd_get_section_by_name (abfd, ".stab");
+ if (stab != NULL
+ && (stab->_raw_size == 0
+ || bfd_is_abs_section (stab->output_section)
+ || stab->sec_info_type != ELF_INFO_TYPE_STABS))
+ stab = NULL;
+
+ if (stab == NULL
+ && eh == NULL
+ && bed->elf_backend_discard_info == NULL)
+ continue;
+
+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+ cookie.abfd = abfd;
+ cookie.sym_hashes = elf_sym_hashes (abfd);
+ cookie.bad_symtab = elf_bad_symtab (abfd);
+ if (cookie.bad_symtab)
+ {
+ cookie.locsymcount = symtab_hdr->sh_size / bed->s->sizeof_sym;
+ cookie.extsymoff = 0;
+ }
+ else
+ {
+ cookie.locsymcount = symtab_hdr->sh_info;
+ cookie.extsymoff = symtab_hdr->sh_info;
+ }
+
+ if (bed->s->arch_size == 32)
+ cookie.r_sym_shift = 8;
+ else
+ cookie.r_sym_shift = 32;
+
+ cookie.locsyms = (Elf_Internal_Sym *) symtab_hdr->contents;
+ if (cookie.locsyms == NULL && cookie.locsymcount != 0)
+ {
+ cookie.locsyms = bfd_elf_get_elf_syms (abfd, symtab_hdr,
+ cookie.locsymcount, 0,
+ NULL, NULL, NULL);
+ if (cookie.locsyms == NULL)
+ return FALSE;
+ }
+
+ if (stab != NULL)
+ {
+ cookie.rels = NULL;
+ count = stab->reloc_count;
+ if (count != 0)
+ cookie.rels = _bfd_elf_link_read_relocs (abfd, stab, NULL, NULL,
+ info->keep_memory);
+ if (cookie.rels != NULL)
+ {
+ cookie.rel = cookie.rels;
+ cookie.relend = cookie.rels;
+ cookie.relend += count * bed->s->int_rels_per_ext_rel;
+ if (_bfd_discard_section_stabs (abfd, stab,
+ elf_section_data (stab)->sec_info,
+ bfd_elf_reloc_symbol_deleted_p,
+ &cookie))
+ ret = TRUE;
+ if (elf_section_data (stab)->relocs != cookie.rels)
+ free (cookie.rels);
+ }
+ }
+
+ if (eh != NULL)
+ {
+ cookie.rels = NULL;
+ count = eh->reloc_count;
+ if (count != 0)
+ cookie.rels = _bfd_elf_link_read_relocs (abfd, eh, NULL, NULL,
+ info->keep_memory);
+ cookie.rel = cookie.rels;
+ cookie.relend = cookie.rels;
+ if (cookie.rels != NULL)
+ cookie.relend += count * bed->s->int_rels_per_ext_rel;
+
+ if (_bfd_elf_discard_section_eh_frame (abfd, info, eh,
+ bfd_elf_reloc_symbol_deleted_p,
+ &cookie))
+ ret = TRUE;
+
+ if (cookie.rels != NULL
+ && elf_section_data (eh)->relocs != cookie.rels)
+ free (cookie.rels);
+ }
+
+ if (bed->elf_backend_discard_info != NULL
+ && (*bed->elf_backend_discard_info) (abfd, &cookie, info))
+ ret = TRUE;
+
+ if (cookie.locsyms != NULL
+ && symtab_hdr->contents != (unsigned char *) cookie.locsyms)
+ {
+ if (! info->keep_memory)
+ free (cookie.locsyms);
+ else
+ symtab_hdr->contents = (unsigned char *) cookie.locsyms;
+ }
+ }
+
+ if (info->eh_frame_hdr
+ && !info->relocatable
+ && _bfd_elf_discard_section_eh_frame_hdr (output_bfd, info))
+ ret = TRUE;
+
+ return ret;
+}
+++ /dev/null
-/* ELF linker support.
- Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
- 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-/* ELF linker code. */
-
-static bfd_boolean elf_section_ignore_discarded_relocs (asection *);
-
-/* Final phase of ELF linker. */
-
-/* A structure we use to avoid passing large numbers of arguments. */
-
-struct elf_final_link_info
-{
- /* General link information. */
- struct bfd_link_info *info;
- /* Output BFD. */
- bfd *output_bfd;
- /* Symbol string table. */
- struct bfd_strtab_hash *symstrtab;
- /* .dynsym section. */
- asection *dynsym_sec;
- /* .hash section. */
- asection *hash_sec;
- /* symbol version section (.gnu.version). */
- asection *symver_sec;
- /* Buffer large enough to hold contents of any section. */
- bfd_byte *contents;
- /* Buffer large enough to hold external relocs of any section. */
- void *external_relocs;
- /* Buffer large enough to hold internal relocs of any section. */
- Elf_Internal_Rela *internal_relocs;
- /* Buffer large enough to hold external local symbols of any input
- BFD. */
- Elf_External_Sym *external_syms;
- /* And a buffer for symbol section indices. */
- Elf_External_Sym_Shndx *locsym_shndx;
- /* Buffer large enough to hold internal local symbols of any input
- BFD. */
- Elf_Internal_Sym *internal_syms;
- /* Array large enough to hold a symbol index for each local symbol
- of any input BFD. */
- long *indices;
- /* Array large enough to hold a section pointer for each local
- symbol of any input BFD. */
- asection **sections;
- /* Buffer to hold swapped out symbols. */
- Elf_External_Sym *symbuf;
- /* And one for symbol section indices. */
- Elf_External_Sym_Shndx *symshndxbuf;
- /* Number of swapped out symbols in buffer. */
- size_t symbuf_count;
- /* Number of symbols which fit in symbuf. */
- size_t symbuf_size;
- /* And same for symshndxbuf. */
- size_t shndxbuf_size;
-};
-
-static bfd_boolean elf_link_output_sym
- (struct elf_final_link_info *, const char *, Elf_Internal_Sym *, asection *,
- struct elf_link_hash_entry *);
-static bfd_boolean elf_link_flush_output_syms
- (struct elf_final_link_info *);
-static bfd_boolean elf_link_output_extsym
- (struct elf_link_hash_entry *, void *);
-static bfd_boolean elf_link_input_bfd
- (struct elf_final_link_info *, bfd *);
-static bfd_boolean elf_reloc_link_order
- (bfd *, struct bfd_link_info *, asection *, struct bfd_link_order *);
-
-/* This struct is used to pass information to elf_link_output_extsym. */
-
-struct elf_outext_info
-{
- bfd_boolean failed;
- bfd_boolean localsyms;
- struct elf_final_link_info *finfo;
-};
-
-/* When performing a relocatable link, the input relocations are
- preserved. But, if they reference global symbols, the indices
- referenced must be updated. Update all the relocations in
- REL_HDR (there are COUNT of them), using the data in REL_HASH. */
-
-static void
-elf_link_adjust_relocs (bfd *abfd,
- Elf_Internal_Shdr *rel_hdr,
- unsigned int count,
- struct elf_link_hash_entry **rel_hash)
-{
- unsigned int i;
- const struct elf_backend_data *bed = get_elf_backend_data (abfd);
- bfd_byte *erela;
- void (*swap_in) (bfd *, const bfd_byte *, Elf_Internal_Rela *);
- void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *);
-
- if (rel_hdr->sh_entsize == sizeof (Elf_External_Rel))
- {
- swap_in = bed->s->swap_reloc_in;
- swap_out = bed->s->swap_reloc_out;
- }
- else if (rel_hdr->sh_entsize == sizeof (Elf_External_Rela))
- {
- swap_in = bed->s->swap_reloca_in;
- swap_out = bed->s->swap_reloca_out;
- }
- else
- abort ();
-
- if (bed->s->int_rels_per_ext_rel > MAX_INT_RELS_PER_EXT_REL)
- abort ();
-
- erela = rel_hdr->contents;
- for (i = 0; i < count; i++, rel_hash++, erela += rel_hdr->sh_entsize)
- {
- Elf_Internal_Rela irela[MAX_INT_RELS_PER_EXT_REL];
- unsigned int j;
-
- if (*rel_hash == NULL)
- continue;
-
- BFD_ASSERT ((*rel_hash)->indx >= 0);
-
- (*swap_in) (abfd, erela, irela);
- for (j = 0; j < bed->s->int_rels_per_ext_rel; j++)
- irela[j].r_info = ELF_R_INFO ((*rel_hash)->indx,
- ELF_R_TYPE (irela[j].r_info));
- (*swap_out) (abfd, irela, erela);
- }
-}
-
-struct elf_link_sort_rela
-{
- bfd_vma offset;
- enum elf_reloc_type_class type;
- /* We use this as an array of size int_rels_per_ext_rel. */
- Elf_Internal_Rela rela[1];
-};
-
-static int
-elf_link_sort_cmp1 (const void *A, const void *B)
-{
- const struct elf_link_sort_rela *a = A;
- const struct elf_link_sort_rela *b = B;
- int relativea, relativeb;
-
- relativea = a->type == reloc_class_relative;
- relativeb = b->type == reloc_class_relative;
-
- if (relativea < relativeb)
- return 1;
- if (relativea > relativeb)
- return -1;
- if (ELF_R_SYM (a->rela->r_info) < ELF_R_SYM (b->rela->r_info))
- return -1;
- if (ELF_R_SYM (a->rela->r_info) > ELF_R_SYM (b->rela->r_info))
- return 1;
- if (a->rela->r_offset < b->rela->r_offset)
- return -1;
- if (a->rela->r_offset > b->rela->r_offset)
- return 1;
- return 0;
-}
-
-static int
-elf_link_sort_cmp2 (const void *A, const void *B)
-{
- const struct elf_link_sort_rela *a = A;
- const struct elf_link_sort_rela *b = B;
- int copya, copyb;
-
- if (a->offset < b->offset)
- return -1;
- if (a->offset > b->offset)
- return 1;
- copya = (a->type == reloc_class_copy) * 2 + (a->type == reloc_class_plt);
- copyb = (b->type == reloc_class_copy) * 2 + (b->type == reloc_class_plt);
- if (copya < copyb)
- return -1;
- if (copya > copyb)
- return 1;
- if (a->rela->r_offset < b->rela->r_offset)
- return -1;
- if (a->rela->r_offset > b->rela->r_offset)
- return 1;
- return 0;
-}
-
-static size_t
-elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
-{
- asection *reldyn;
- bfd_size_type count, size;
- size_t i, ret, sort_elt, ext_size;
- bfd_byte *sort, *s_non_relative, *p;
- struct elf_link_sort_rela *sq;
- const struct elf_backend_data *bed = get_elf_backend_data (abfd);
- int i2e = bed->s->int_rels_per_ext_rel;
- void (*swap_in) (bfd *, const bfd_byte *, Elf_Internal_Rela *);
- void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *);
- struct bfd_link_order *lo;
-
- reldyn = bfd_get_section_by_name (abfd, ".rela.dyn");
- if (reldyn == NULL || reldyn->_raw_size == 0)
- {
- reldyn = bfd_get_section_by_name (abfd, ".rel.dyn");
- if (reldyn == NULL || reldyn->_raw_size == 0)
- return 0;
- ext_size = sizeof (Elf_External_Rel);
- swap_in = bed->s->swap_reloc_in;
- swap_out = bed->s->swap_reloc_out;
- }
- else
- {
- ext_size = sizeof (Elf_External_Rela);
- swap_in = bed->s->swap_reloca_in;
- swap_out = bed->s->swap_reloca_out;
- }
- count = reldyn->_raw_size / ext_size;
-
- size = 0;
- for (lo = reldyn->link_order_head; lo != NULL; lo = lo->next)
- if (lo->type == bfd_indirect_link_order)
- {
- asection *o = lo->u.indirect.section;
- size += o->_raw_size;
- }
-
- if (size != reldyn->_raw_size)
- return 0;
-
- sort_elt = (sizeof (struct elf_link_sort_rela)
- + (i2e - 1) * sizeof (Elf_Internal_Rela));
- sort = bfd_zmalloc (sort_elt * count);
- if (sort == NULL)
- {
- (*info->callbacks->warning)
- (info, _("Not enough memory to sort relocations"), 0, abfd, 0, 0);
- return 0;
- }
-
- for (lo = reldyn->link_order_head; lo != NULL; lo = lo->next)
- if (lo->type == bfd_indirect_link_order)
- {
- bfd_byte *erel, *erelend;
- asection *o = lo->u.indirect.section;
-
- erel = o->contents;
- erelend = o->contents + o->_raw_size;
- p = sort + o->output_offset / ext_size * sort_elt;
- while (erel < erelend)
- {
- struct elf_link_sort_rela *s = (struct elf_link_sort_rela *) p;
- (*swap_in) (abfd, erel, s->rela);
- s->type = (*bed->elf_backend_reloc_type_class) (s->rela);
- p += sort_elt;
- erel += ext_size;
- }
- }
-
- qsort (sort, count, sort_elt, elf_link_sort_cmp1);
-
- for (i = 0, p = sort; i < count; i++, p += sort_elt)
- {
- struct elf_link_sort_rela *s = (struct elf_link_sort_rela *) p;
- if (s->type != reloc_class_relative)
- break;
- }
- ret = i;
- s_non_relative = p;
-
- sq = (struct elf_link_sort_rela *) s_non_relative;
- for (; i < count; i++, p += sort_elt)
- {
- struct elf_link_sort_rela *sp = (struct elf_link_sort_rela *) p;
- if (ELF_R_SYM (sp->rela->r_info) != ELF_R_SYM (sq->rela->r_info))
- sq = sp;
- sp->offset = sq->rela->r_offset;
- }
-
- qsort (s_non_relative, count - ret, sort_elt, elf_link_sort_cmp2);
-
- for (lo = reldyn->link_order_head; lo != NULL; lo = lo->next)
- if (lo->type == bfd_indirect_link_order)
- {
- bfd_byte *erel, *erelend;
- asection *o = lo->u.indirect.section;
-
- erel = o->contents;
- erelend = o->contents + o->_raw_size;
- p = sort + o->output_offset / ext_size * sort_elt;
- while (erel < erelend)
- {
- struct elf_link_sort_rela *s = (struct elf_link_sort_rela *) p;
- (*swap_out) (abfd, s->rela, erel);
- p += sort_elt;
- erel += ext_size;
- }
- }
-
- free (sort);
- *psec = reldyn;
- return ret;
-}
-
-/* Do the final step of an ELF link. */
-
-bfd_boolean
-elf_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
-{
- bfd_boolean dynamic;
- bfd_boolean emit_relocs;
- bfd *dynobj;
- struct elf_final_link_info finfo;
- register asection *o;
- register struct bfd_link_order *p;
- register bfd *sub;
- bfd_size_type max_contents_size;
- bfd_size_type max_external_reloc_size;
- bfd_size_type max_internal_reloc_count;
- bfd_size_type max_sym_count;
- bfd_size_type max_sym_shndx_count;
- file_ptr off;
- Elf_Internal_Sym elfsym;
- unsigned int i;
- Elf_Internal_Shdr *symtab_hdr;
- Elf_Internal_Shdr *symtab_shndx_hdr;
- Elf_Internal_Shdr *symstrtab_hdr;
- const struct elf_backend_data *bed = get_elf_backend_data (abfd);
- struct elf_outext_info eoinfo;
- bfd_boolean merged;
- size_t relativecount = 0;
- asection *reldyn = 0;
- bfd_size_type amt;
-
- if (! is_elf_hash_table (info->hash))
- return FALSE;
-
- if (info->shared)
- abfd->flags |= DYNAMIC;
-
- dynamic = elf_hash_table (info)->dynamic_sections_created;
- dynobj = elf_hash_table (info)->dynobj;
-
- emit_relocs = (info->relocatable
- || info->emitrelocations
- || bed->elf_backend_emit_relocs);
-
- finfo.info = info;
- finfo.output_bfd = abfd;
- finfo.symstrtab = elf_stringtab_init ();
- if (finfo.symstrtab == NULL)
- return FALSE;
-
- if (! dynamic)
- {
- finfo.dynsym_sec = NULL;
- finfo.hash_sec = NULL;
- finfo.symver_sec = NULL;
- }
- else
- {
- finfo.dynsym_sec = bfd_get_section_by_name (dynobj, ".dynsym");
- finfo.hash_sec = bfd_get_section_by_name (dynobj, ".hash");
- BFD_ASSERT (finfo.dynsym_sec != NULL && finfo.hash_sec != NULL);
- finfo.symver_sec = bfd_get_section_by_name (dynobj, ".gnu.version");
- /* Note that it is OK if symver_sec is NULL. */
- }
-
- finfo.contents = NULL;
- finfo.external_relocs = NULL;
- finfo.internal_relocs = NULL;
- finfo.external_syms = NULL;
- finfo.locsym_shndx = NULL;
- finfo.internal_syms = NULL;
- finfo.indices = NULL;
- finfo.sections = NULL;
- finfo.symbuf = NULL;
- finfo.symshndxbuf = NULL;
- finfo.symbuf_count = 0;
- finfo.shndxbuf_size = 0;
-
- /* Count up the number of relocations we will output for each output
- section, so that we know the sizes of the reloc sections. We
- also figure out some maximum sizes. */
- max_contents_size = 0;
- max_external_reloc_size = 0;
- max_internal_reloc_count = 0;
- max_sym_count = 0;
- max_sym_shndx_count = 0;
- merged = FALSE;
- for (o = abfd->sections; o != NULL; o = o->next)
- {
- struct bfd_elf_section_data *esdo = elf_section_data (o);
- o->reloc_count = 0;
-
- for (p = o->link_order_head; p != NULL; p = p->next)
- {
- unsigned int reloc_count = 0;
- struct bfd_elf_section_data *esdi = NULL;
- unsigned int *rel_count1;
-
- if (p->type == bfd_section_reloc_link_order
- || p->type == bfd_symbol_reloc_link_order)
- reloc_count = 1;
- else if (p->type == bfd_indirect_link_order)
- {
- asection *sec;
-
- sec = p->u.indirect.section;
- esdi = elf_section_data (sec);
-
- /* Mark all sections which are to be included in the
- link. This will normally be every section. We need
- to do this so that we can identify any sections which
- the linker has decided to not include. */
- sec->linker_mark = TRUE;
-
- if (sec->flags & SEC_MERGE)
- merged = TRUE;
-
- if (info->relocatable || info->emitrelocations)
- reloc_count = sec->reloc_count;
- else if (bed->elf_backend_count_relocs)
- {
- Elf_Internal_Rela * relocs;
-
- relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
- info->keep_memory);
-
- reloc_count = (*bed->elf_backend_count_relocs) (sec, relocs);
-
- if (elf_section_data (o)->relocs != relocs)
- free (relocs);
- }
-
- if (sec->_raw_size > max_contents_size)
- max_contents_size = sec->_raw_size;
- if (sec->_cooked_size > max_contents_size)
- max_contents_size = sec->_cooked_size;
-
- /* We are interested in just local symbols, not all
- symbols. */
- if (bfd_get_flavour (sec->owner) == bfd_target_elf_flavour
- && (sec->owner->flags & DYNAMIC) == 0)
- {
- size_t sym_count;
-
- if (elf_bad_symtab (sec->owner))
- sym_count = (elf_tdata (sec->owner)->symtab_hdr.sh_size
- / sizeof (Elf_External_Sym));
- else
- sym_count = elf_tdata (sec->owner)->symtab_hdr.sh_info;
-
- if (sym_count > max_sym_count)
- max_sym_count = sym_count;
-
- if (sym_count > max_sym_shndx_count
- && elf_symtab_shndx (sec->owner) != 0)
- max_sym_shndx_count = sym_count;
-
- if ((sec->flags & SEC_RELOC) != 0)
- {
- size_t ext_size;
-
- ext_size = elf_section_data (sec)->rel_hdr.sh_size;
- if (ext_size > max_external_reloc_size)
- max_external_reloc_size = ext_size;
- if (sec->reloc_count > max_internal_reloc_count)
- max_internal_reloc_count = sec->reloc_count;
- }
- }
- }
-
- if (reloc_count == 0)
- continue;
-
- o->reloc_count += reloc_count;
-
- /* MIPS may have a mix of REL and RELA relocs on sections.
- To support this curious ABI we keep reloc counts in
- elf_section_data too. We must be careful to add the
- relocations from the input section to the right output
- count. FIXME: Get rid of one count. We have
- o->reloc_count == esdo->rel_count + esdo->rel_count2. */
- rel_count1 = &esdo->rel_count;
- if (esdi != NULL)
- {
- bfd_boolean same_size;
- bfd_size_type entsize1;
-
- entsize1 = esdi->rel_hdr.sh_entsize;
- BFD_ASSERT (entsize1 == sizeof (Elf_External_Rel)
- || entsize1 == sizeof (Elf_External_Rela));
- same_size = (!o->use_rela_p
- == (entsize1 == sizeof (Elf_External_Rel)));
-
- if (!same_size)
- rel_count1 = &esdo->rel_count2;
-
- if (esdi->rel_hdr2 != NULL)
- {
- bfd_size_type entsize2 = esdi->rel_hdr2->sh_entsize;
- unsigned int alt_count;
- unsigned int *rel_count2;
-
- BFD_ASSERT (entsize2 != entsize1
- && (entsize2 == sizeof (Elf_External_Rel)
- || entsize2 == sizeof (Elf_External_Rela)));
-
- rel_count2 = &esdo->rel_count2;
- if (!same_size)
- rel_count2 = &esdo->rel_count;
-
- /* The following is probably too simplistic if the
- backend counts output relocs unusually. */
- BFD_ASSERT (bed->elf_backend_count_relocs == NULL);
- alt_count = NUM_SHDR_ENTRIES (esdi->rel_hdr2);
- *rel_count2 += alt_count;
- reloc_count -= alt_count;
- }
- }
- *rel_count1 += reloc_count;
- }
-
- if (o->reloc_count > 0)
- o->flags |= SEC_RELOC;
- else
- {
- /* Explicitly clear the SEC_RELOC flag. The linker tends to
- set it (this is probably a bug) and if it is set
- assign_section_numbers will create a reloc section. */
- o->flags &=~ SEC_RELOC;
- }
-
- /* If the SEC_ALLOC flag is not set, force the section VMA to
- zero. This is done in elf_fake_sections as well, but forcing
- the VMA to 0 here will ensure that relocs against these
- sections are handled correctly. */
- if ((o->flags & SEC_ALLOC) == 0
- && ! o->user_set_vma)
- o->vma = 0;
- }
-
- if (! info->relocatable && merged)
- elf_link_hash_traverse (elf_hash_table (info),
- _bfd_elf_link_sec_merge_syms, abfd);
-
- /* Figure out the file positions for everything but the symbol table
- and the relocs. We set symcount to force assign_section_numbers
- to create a symbol table. */
- bfd_get_symcount (abfd) = info->strip == strip_all ? 0 : 1;
- BFD_ASSERT (! abfd->output_has_begun);
- if (! _bfd_elf_compute_section_file_positions (abfd, info))
- goto error_return;
-
- /* That created the reloc sections. Set their sizes, and assign
- them file positions, and allocate some buffers. */
- for (o = abfd->sections; o != NULL; o = o->next)
- {
- if ((o->flags & SEC_RELOC) != 0)
- {
- if (!(_bfd_elf_link_size_reloc_section
- (abfd, &elf_section_data (o)->rel_hdr, o)))
- goto error_return;
-
- if (elf_section_data (o)->rel_hdr2
- && !(_bfd_elf_link_size_reloc_section
- (abfd, elf_section_data (o)->rel_hdr2, o)))
- goto error_return;
- }
-
- /* Now, reset REL_COUNT and REL_COUNT2 so that we can use them
- to count upwards while actually outputting the relocations. */
- elf_section_data (o)->rel_count = 0;
- elf_section_data (o)->rel_count2 = 0;
- }
-
- _bfd_elf_assign_file_positions_for_relocs (abfd);
-
- /* We have now assigned file positions for all the sections except
- .symtab and .strtab. We start the .symtab section at the current
- file position, and write directly to it. We build the .strtab
- section in memory. */
- bfd_get_symcount (abfd) = 0;
- symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
- /* sh_name is set in prep_headers. */
- symtab_hdr->sh_type = SHT_SYMTAB;
- /* sh_flags, sh_addr and sh_size all start off zero. */
- symtab_hdr->sh_entsize = sizeof (Elf_External_Sym);
- /* sh_link is set in assign_section_numbers. */
- /* sh_info is set below. */
- /* sh_offset is set just below. */
- symtab_hdr->sh_addralign = 1 << bed->s->log_file_align;
-
- off = elf_tdata (abfd)->next_file_pos;
- off = _bfd_elf_assign_file_position_for_section (symtab_hdr, off, TRUE);
-
- /* Note that at this point elf_tdata (abfd)->next_file_pos is
- incorrect. We do not yet know the size of the .symtab section.
- We correct next_file_pos below, after we do know the size. */
-
- /* Allocate a buffer to hold swapped out symbols. This is to avoid
- continuously seeking to the right position in the file. */
- if (! info->keep_memory || max_sym_count < 20)
- finfo.symbuf_size = 20;
- else
- finfo.symbuf_size = max_sym_count;
- amt = finfo.symbuf_size;
- amt *= sizeof (Elf_External_Sym);
- finfo.symbuf = bfd_malloc (amt);
- if (finfo.symbuf == NULL)
- goto error_return;
- if (elf_numsections (abfd) > SHN_LORESERVE)
- {
- /* Wild guess at number of output symbols. realloc'd as needed. */
- amt = 2 * max_sym_count + elf_numsections (abfd) + 1000;
- finfo.shndxbuf_size = amt;
- amt *= sizeof (Elf_External_Sym_Shndx);
- finfo.symshndxbuf = bfd_zmalloc (amt);
- if (finfo.symshndxbuf == NULL)
- goto error_return;
- }
-
- /* Start writing out the symbol table. The first symbol is always a
- dummy symbol. */
- if (info->strip != strip_all
- || emit_relocs)
- {
- elfsym.st_value = 0;
- elfsym.st_size = 0;
- elfsym.st_info = 0;
- elfsym.st_other = 0;
- elfsym.st_shndx = SHN_UNDEF;
- if (! elf_link_output_sym (&finfo, NULL, &elfsym, bfd_und_section_ptr,
- NULL))
- goto error_return;
- }
-
-#if 0
- /* Some standard ELF linkers do this, but we don't because it causes
- bootstrap comparison failures. */
- /* Output a file symbol for the output file as the second symbol.
- We output this even if we are discarding local symbols, although
- I'm not sure if this is correct. */
- elfsym.st_value = 0;
- elfsym.st_size = 0;
- elfsym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FILE);
- elfsym.st_other = 0;
- elfsym.st_shndx = SHN_ABS;
- if (! elf_link_output_sym (&finfo, bfd_get_filename (abfd),
- &elfsym, bfd_abs_section_ptr, NULL))
- goto error_return;
-#endif
-
- /* Output a symbol for each section. We output these even if we are
- discarding local symbols, since they are used for relocs. These
- symbols have no names. We store the index of each one in the
- index field of the section, so that we can find it again when
- outputting relocs. */
- if (info->strip != strip_all
- || emit_relocs)
- {
- elfsym.st_size = 0;
- elfsym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
- elfsym.st_other = 0;
- for (i = 1; i < elf_numsections (abfd); i++)
- {
- o = section_from_elf_index (abfd, i);
- if (o != NULL)
- o->target_index = bfd_get_symcount (abfd);
- elfsym.st_shndx = i;
- if (info->relocatable || o == NULL)
- elfsym.st_value = 0;
- else
- elfsym.st_value = o->vma;
- if (! elf_link_output_sym (&finfo, NULL, &elfsym, o, NULL))
- goto error_return;
- if (i == SHN_LORESERVE - 1)
- i += SHN_HIRESERVE + 1 - SHN_LORESERVE;
- }
- }
-
- /* Allocate some memory to hold information read in from the input
- files. */
- if (max_contents_size != 0)
- {
- finfo.contents = bfd_malloc (max_contents_size);
- if (finfo.contents == NULL)
- goto error_return;
- }
-
- if (max_external_reloc_size != 0)
- {
- finfo.external_relocs = bfd_malloc (max_external_reloc_size);
- if (finfo.external_relocs == NULL)
- goto error_return;
- }
-
- if (max_internal_reloc_count != 0)
- {
- amt = max_internal_reloc_count * bed->s->int_rels_per_ext_rel;
- amt *= sizeof (Elf_Internal_Rela);
- finfo.internal_relocs = bfd_malloc (amt);
- if (finfo.internal_relocs == NULL)
- goto error_return;
- }
-
- if (max_sym_count != 0)
- {
- amt = max_sym_count * sizeof (Elf_External_Sym);
- finfo.external_syms = bfd_malloc (amt);
- if (finfo.external_syms == NULL)
- goto error_return;
-
- amt = max_sym_count * sizeof (Elf_Internal_Sym);
- finfo.internal_syms = bfd_malloc (amt);
- if (finfo.internal_syms == NULL)
- goto error_return;
-
- amt = max_sym_count * sizeof (long);
- finfo.indices = bfd_malloc (amt);
- if (finfo.indices == NULL)
- goto error_return;
-
- amt = max_sym_count * sizeof (asection *);
- finfo.sections = bfd_malloc (amt);
- if (finfo.sections == NULL)
- goto error_return;
- }
-
- if (max_sym_shndx_count != 0)
- {
- amt = max_sym_shndx_count * sizeof (Elf_External_Sym_Shndx);
- finfo.locsym_shndx = bfd_malloc (amt);
- if (finfo.locsym_shndx == NULL)
- goto error_return;
- }
-
- if (elf_hash_table (info)->tls_sec)
- {
- bfd_vma base, end = 0;
- asection *sec;
-
- for (sec = elf_hash_table (info)->tls_sec;
- sec && (sec->flags & SEC_THREAD_LOCAL);
- sec = sec->next)
- {
- bfd_vma size = sec->_raw_size;
-
- if (size == 0 && (sec->flags & SEC_HAS_CONTENTS) == 0)
- {
- struct bfd_link_order *o;
-
- for (o = sec->link_order_head; o != NULL; o = o->next)
- if (size < o->offset + o->size)
- size = o->offset + o->size;
- }
- end = sec->vma + size;
- }
- base = elf_hash_table (info)->tls_sec->vma;
- end = align_power (end, elf_hash_table (info)->tls_sec->alignment_power);
- elf_hash_table (info)->tls_size = end - base;
- }
-
- /* Since ELF permits relocations to be against local symbols, we
- must have the local symbols available when we do the relocations.
- Since we would rather only read the local symbols once, and we
- would rather not keep them in memory, we handle all the
- relocations for a single input file at the same time.
-
- Unfortunately, there is no way to know the total number of local
- symbols until we have seen all of them, and the local symbol
- indices precede the global symbol indices. This means that when
- we are generating relocatable output, and we see a reloc against
- a global symbol, we can not know the symbol index until we have
- finished examining all the local symbols to see which ones we are
- going to output. To deal with this, we keep the relocations in
- memory, and don't output them until the end of the link. This is
- an unfortunate waste of memory, but I don't see a good way around
- it. Fortunately, it only happens when performing a relocatable
- link, which is not the common case. FIXME: If keep_memory is set
- we could write the relocs out and then read them again; I don't
- know how bad the memory loss will be. */
-
- for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
- sub->output_has_begun = FALSE;
- for (o = abfd->sections; o != NULL; o = o->next)
- {
- for (p = o->link_order_head; p != NULL; p = p->next)
- {
- if (p->type == bfd_indirect_link_order
- && (bfd_get_flavour ((sub = p->u.indirect.section->owner))
- == bfd_target_elf_flavour)
- && elf_elfheader (sub)->e_ident[EI_CLASS] == bed->s->elfclass)
- {
- if (! sub->output_has_begun)
- {
- if (! elf_link_input_bfd (&finfo, sub))
- goto error_return;
- sub->output_has_begun = TRUE;
- }
- }
- else if (p->type == bfd_section_reloc_link_order
- || p->type == bfd_symbol_reloc_link_order)
- {
- if (! elf_reloc_link_order (abfd, info, o, p))
- goto error_return;
- }
- else
- {
- if (! _bfd_default_link_order (abfd, info, o, p))
- goto error_return;
- }
- }
- }
-
- /* Output any global symbols that got converted to local in a
- version script or due to symbol visibility. We do this in a
- separate step since ELF requires all local symbols to appear
- prior to any global symbols. FIXME: We should only do this if
- some global symbols were, in fact, converted to become local.
- FIXME: Will this work correctly with the Irix 5 linker? */
- eoinfo.failed = FALSE;
- eoinfo.finfo = &finfo;
- eoinfo.localsyms = TRUE;
- elf_link_hash_traverse (elf_hash_table (info), elf_link_output_extsym,
- &eoinfo);
- if (eoinfo.failed)
- return FALSE;
-
- /* That wrote out all the local symbols. Finish up the symbol table
- with the global symbols. Even if we want to strip everything we
- can, we still need to deal with those global symbols that got
- converted to local in a version script. */
-
- /* The sh_info field records the index of the first non local symbol. */
- symtab_hdr->sh_info = bfd_get_symcount (abfd);
-
- if (dynamic
- && finfo.dynsym_sec->output_section != bfd_abs_section_ptr)
- {
- Elf_Internal_Sym sym;
- Elf_External_Sym *dynsym =
- (Elf_External_Sym *) finfo.dynsym_sec->contents;
- long last_local = 0;
-
- /* Write out the section symbols for the output sections. */
- if (info->shared)
- {
- asection *s;
-
- sym.st_size = 0;
- sym.st_name = 0;
- sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
- sym.st_other = 0;
-
- for (s = abfd->sections; s != NULL; s = s->next)
- {
- int indx;
- Elf_External_Sym *dest;
-
- indx = elf_section_data (s)->this_idx;
- BFD_ASSERT (indx > 0);
- sym.st_shndx = indx;
- sym.st_value = s->vma;
- dest = dynsym + elf_section_data (s)->dynindx;
- elf_swap_symbol_out (abfd, &sym, dest, 0);
- }
-
- last_local = bfd_count_sections (abfd);
- }
-
- /* Write out the local dynsyms. */
- if (elf_hash_table (info)->dynlocal)
- {
- struct elf_link_local_dynamic_entry *e;
- for (e = elf_hash_table (info)->dynlocal; e ; e = e->next)
- {
- asection *s;
- Elf_External_Sym *dest;
-
- sym.st_size = e->isym.st_size;
- sym.st_other = e->isym.st_other;
-
- /* Copy the internal symbol as is.
- Note that we saved a word of storage and overwrote
- the original st_name with the dynstr_index. */
- sym = e->isym;
-
- if (e->isym.st_shndx != SHN_UNDEF
- && (e->isym.st_shndx < SHN_LORESERVE
- || e->isym.st_shndx > SHN_HIRESERVE))
- {
- s = bfd_section_from_elf_index (e->input_bfd,
- e->isym.st_shndx);
-
- sym.st_shndx =
- elf_section_data (s->output_section)->this_idx;
- sym.st_value = (s->output_section->vma
- + s->output_offset
- + e->isym.st_value);
- }
-
- if (last_local < e->dynindx)
- last_local = e->dynindx;
-
- dest = dynsym + e->dynindx;
- elf_swap_symbol_out (abfd, &sym, dest, 0);
- }
- }
-
- elf_section_data (finfo.dynsym_sec->output_section)->this_hdr.sh_info =
- last_local + 1;
- }
-
- /* We get the global symbols from the hash table. */
- eoinfo.failed = FALSE;
- eoinfo.localsyms = FALSE;
- eoinfo.finfo = &finfo;
- elf_link_hash_traverse (elf_hash_table (info), elf_link_output_extsym,
- &eoinfo);
- if (eoinfo.failed)
- return FALSE;
-
- /* If backend needs to output some symbols not present in the hash
- table, do it now. */
- if (bed->elf_backend_output_arch_syms)
- {
- typedef bfd_boolean (*out_sym_func)
- (void *, const char *, Elf_Internal_Sym *, asection *,
- struct elf_link_hash_entry *);
-
- if (! ((*bed->elf_backend_output_arch_syms)
- (abfd, info, &finfo, (out_sym_func) elf_link_output_sym)))
- return FALSE;
- }
-
- /* Flush all symbols to the file. */
- if (! elf_link_flush_output_syms (&finfo))
- return FALSE;
-
- /* Now we know the size of the symtab section. */
- off += symtab_hdr->sh_size;
-
- symtab_shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
- if (symtab_shndx_hdr->sh_name != 0)
- {
- symtab_shndx_hdr->sh_type = SHT_SYMTAB_SHNDX;
- symtab_shndx_hdr->sh_entsize = sizeof (Elf_External_Sym_Shndx);
- symtab_shndx_hdr->sh_addralign = sizeof (Elf_External_Sym_Shndx);
- amt = bfd_get_symcount (abfd) * sizeof (Elf_External_Sym_Shndx);
- symtab_shndx_hdr->sh_size = amt;
-
- off = _bfd_elf_assign_file_position_for_section (symtab_shndx_hdr,
- off, TRUE);
-
- if (bfd_seek (abfd, symtab_shndx_hdr->sh_offset, SEEK_SET) != 0
- || (bfd_bwrite (finfo.symshndxbuf, amt, abfd) != amt))
- return FALSE;
- }
-
-
- /* Finish up and write out the symbol string table (.strtab)
- section. */
- symstrtab_hdr = &elf_tdata (abfd)->strtab_hdr;
- /* sh_name was set in prep_headers. */
- symstrtab_hdr->sh_type = SHT_STRTAB;
- symstrtab_hdr->sh_flags = 0;
- symstrtab_hdr->sh_addr = 0;
- symstrtab_hdr->sh_size = _bfd_stringtab_size (finfo.symstrtab);
- symstrtab_hdr->sh_entsize = 0;
- symstrtab_hdr->sh_link = 0;
- symstrtab_hdr->sh_info = 0;
- /* sh_offset is set just below. */
- symstrtab_hdr->sh_addralign = 1;
-
- off = _bfd_elf_assign_file_position_for_section (symstrtab_hdr, off, TRUE);
- elf_tdata (abfd)->next_file_pos = off;
-
- if (bfd_get_symcount (abfd) > 0)
- {
- if (bfd_seek (abfd, symstrtab_hdr->sh_offset, SEEK_SET) != 0
- || ! _bfd_stringtab_emit (abfd, finfo.symstrtab))
- return FALSE;
- }
-
- /* Adjust the relocs to have the correct symbol indices. */
- for (o = abfd->sections; o != NULL; o = o->next)
- {
- if ((o->flags & SEC_RELOC) == 0)
- continue;
-
- elf_link_adjust_relocs (abfd, &elf_section_data (o)->rel_hdr,
- elf_section_data (o)->rel_count,
- elf_section_data (o)->rel_hashes);
- if (elf_section_data (o)->rel_hdr2 != NULL)
- elf_link_adjust_relocs (abfd, elf_section_data (o)->rel_hdr2,
- elf_section_data (o)->rel_count2,
- (elf_section_data (o)->rel_hashes
- + elf_section_data (o)->rel_count));
-
- /* Set the reloc_count field to 0 to prevent write_relocs from
- trying to swap the relocs out itself. */
- o->reloc_count = 0;
- }
-
- if (dynamic && info->combreloc && dynobj != NULL)
- relativecount = elf_link_sort_relocs (abfd, info, &reldyn);
-
- /* If we are linking against a dynamic object, or generating a
- shared library, finish up the dynamic linking information. */
- if (dynamic)
- {
- Elf_External_Dyn *dyncon, *dynconend;
-
- /* Fix up .dynamic entries. */
- o = bfd_get_section_by_name (dynobj, ".dynamic");
- BFD_ASSERT (o != NULL);
-
- dyncon = (Elf_External_Dyn *) o->contents;
- dynconend = (Elf_External_Dyn *) (o->contents + o->_raw_size);
- for (; dyncon < dynconend; dyncon++)
- {
- Elf_Internal_Dyn dyn;
- const char *name;
- unsigned int type;
-
- elf_swap_dyn_in (dynobj, dyncon, &dyn);
-
- switch (dyn.d_tag)
- {
- default:
- break;
- case DT_NULL:
- if (relativecount > 0 && dyncon + 1 < dynconend)
- {
- switch (elf_section_data (reldyn)->this_hdr.sh_type)
- {
- case SHT_REL: dyn.d_tag = DT_RELCOUNT; break;
- case SHT_RELA: dyn.d_tag = DT_RELACOUNT; break;
- default: break;
- }
- if (dyn.d_tag != DT_NULL)
- {
- dyn.d_un.d_val = relativecount;
- elf_swap_dyn_out (dynobj, &dyn, dyncon);
- relativecount = 0;
- }
- }
- break;
- case DT_INIT:
- name = info->init_function;
- goto get_sym;
- case DT_FINI:
- name = info->fini_function;
- get_sym:
- {
- struct elf_link_hash_entry *h;
-
- h = elf_link_hash_lookup (elf_hash_table (info), name,
- FALSE, FALSE, TRUE);
- if (h != NULL
- && (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak))
- {
- dyn.d_un.d_val = h->root.u.def.value;
- o = h->root.u.def.section;
- if (o->output_section != NULL)
- dyn.d_un.d_val += (o->output_section->vma
- + o->output_offset);
- else
- {
- /* The symbol is imported from another shared
- library and does not apply to this one. */
- dyn.d_un.d_val = 0;
- }
-
- elf_swap_dyn_out (dynobj, &dyn, dyncon);
- }
- }
- break;
-
- case DT_PREINIT_ARRAYSZ:
- name = ".preinit_array";
- goto get_size;
- case DT_INIT_ARRAYSZ:
- name = ".init_array";
- goto get_size;
- case DT_FINI_ARRAYSZ:
- name = ".fini_array";
- get_size:
- o = bfd_get_section_by_name (abfd, name);
- if (o == NULL)
- {
- (*_bfd_error_handler)
- (_("%s: could not find output section %s"),
- bfd_get_filename (abfd), name);
- goto error_return;
- }
- if (o->_raw_size == 0)
- (*_bfd_error_handler)
- (_("warning: %s section has zero size"), name);
- dyn.d_un.d_val = o->_raw_size;
- elf_swap_dyn_out (dynobj, &dyn, dyncon);
- break;
-
- case DT_PREINIT_ARRAY:
- name = ".preinit_array";
- goto get_vma;
- case DT_INIT_ARRAY:
- name = ".init_array";
- goto get_vma;
- case DT_FINI_ARRAY:
- name = ".fini_array";
- goto get_vma;
-
- case DT_HASH:
- name = ".hash";
- goto get_vma;
- case DT_STRTAB:
- name = ".dynstr";
- goto get_vma;
- case DT_SYMTAB:
- name = ".dynsym";
- goto get_vma;
- case DT_VERDEF:
- name = ".gnu.version_d";
- goto get_vma;
- case DT_VERNEED:
- name = ".gnu.version_r";
- goto get_vma;
- case DT_VERSYM:
- name = ".gnu.version";
- get_vma:
- o = bfd_get_section_by_name (abfd, name);
- if (o == NULL)
- {
- (*_bfd_error_handler)
- (_("%s: could not find output section %s"),
- bfd_get_filename (abfd), name);
- goto error_return;
- }
- dyn.d_un.d_ptr = o->vma;
- elf_swap_dyn_out (dynobj, &dyn, dyncon);
- break;
-
- case DT_REL:
- case DT_RELA:
- case DT_RELSZ:
- case DT_RELASZ:
- if (dyn.d_tag == DT_REL || dyn.d_tag == DT_RELSZ)
- type = SHT_REL;
- else
- type = SHT_RELA;
- dyn.d_un.d_val = 0;
- for (i = 1; i < elf_numsections (abfd); i++)
- {
- Elf_Internal_Shdr *hdr;
-
- hdr = elf_elfsections (abfd)[i];
- if (hdr->sh_type == type
- && (hdr->sh_flags & SHF_ALLOC) != 0)
- {
- if (dyn.d_tag == DT_RELSZ || dyn.d_tag == DT_RELASZ)
- dyn.d_un.d_val += hdr->sh_size;
- else
- {
- if (dyn.d_un.d_val == 0
- || hdr->sh_addr < dyn.d_un.d_val)
- dyn.d_un.d_val = hdr->sh_addr;
- }
- }
- }
- elf_swap_dyn_out (dynobj, &dyn, dyncon);
- break;
- }
- }
- }
-
- /* If we have created any dynamic sections, then output them. */
- if (dynobj != NULL)
- {
- if (! (*bed->elf_backend_finish_dynamic_sections) (abfd, info))
- goto error_return;
-
- for (o = dynobj->sections; o != NULL; o = o->next)
- {
- if ((o->flags & SEC_HAS_CONTENTS) == 0
- || o->_raw_size == 0
- || o->output_section == bfd_abs_section_ptr)
- continue;
- if ((o->flags & SEC_LINKER_CREATED) == 0)
- {
- /* At this point, we are only interested in sections
- created by _bfd_elf_link_create_dynamic_sections. */
- continue;
- }
- if ((elf_section_data (o->output_section)->this_hdr.sh_type
- != SHT_STRTAB)
- || strcmp (bfd_get_section_name (abfd, o), ".dynstr") != 0)
- {
- if (! bfd_set_section_contents (abfd, o->output_section,
- o->contents,
- (file_ptr) o->output_offset,
- o->_raw_size))
- goto error_return;
- }
- else
- {
- /* The contents of the .dynstr section are actually in a
- stringtab. */
- off = elf_section_data (o->output_section)->this_hdr.sh_offset;
- if (bfd_seek (abfd, off, SEEK_SET) != 0
- || ! _bfd_elf_strtab_emit (abfd,
- elf_hash_table (info)->dynstr))
- goto error_return;
- }
- }
- }
-
- if (info->relocatable)
- {
- bfd_boolean failed = FALSE;
-
- bfd_map_over_sections (abfd, bfd_elf_set_group_contents, &failed);
- if (failed)
- goto error_return;
- }
-
- /* If we have optimized stabs strings, output them. */
- if (elf_hash_table (info)->stab_info != NULL)
- {
- if (! _bfd_write_stab_strings (abfd, &elf_hash_table (info)->stab_info))
- goto error_return;
- }
-
- if (info->eh_frame_hdr)
- {
- if (! _bfd_elf_write_section_eh_frame_hdr (abfd, info))
- goto error_return;
- }
-
- if (finfo.symstrtab != NULL)
- _bfd_stringtab_free (finfo.symstrtab);
- if (finfo.contents != NULL)
- free (finfo.contents);
- if (finfo.external_relocs != NULL)
- free (finfo.external_relocs);
- if (finfo.internal_relocs != NULL)
- free (finfo.internal_relocs);
- if (finfo.external_syms != NULL)
- free (finfo.external_syms);
- if (finfo.locsym_shndx != NULL)
- free (finfo.locsym_shndx);
- if (finfo.internal_syms != NULL)
- free (finfo.internal_syms);
- if (finfo.indices != NULL)
- free (finfo.indices);
- if (finfo.sections != NULL)
- free (finfo.sections);
- if (finfo.symbuf != NULL)
- free (finfo.symbuf);
- if (finfo.symshndxbuf != NULL)
- free (finfo.symshndxbuf);
- for (o = abfd->sections; o != NULL; o = o->next)
- {
- if ((o->flags & SEC_RELOC) != 0
- && elf_section_data (o)->rel_hashes != NULL)
- free (elf_section_data (o)->rel_hashes);
- }
-
- elf_tdata (abfd)->linker = TRUE;
-
- return TRUE;
-
- error_return:
- if (finfo.symstrtab != NULL)
- _bfd_stringtab_free (finfo.symstrtab);
- if (finfo.contents != NULL)
- free (finfo.contents);
- if (finfo.external_relocs != NULL)
- free (finfo.external_relocs);
- if (finfo.internal_relocs != NULL)
- free (finfo.internal_relocs);
- if (finfo.external_syms != NULL)
- free (finfo.external_syms);
- if (finfo.locsym_shndx != NULL)
- free (finfo.locsym_shndx);
- if (finfo.internal_syms != NULL)
- free (finfo.internal_syms);
- if (finfo.indices != NULL)
- free (finfo.indices);
- if (finfo.sections != NULL)
- free (finfo.sections);
- if (finfo.symbuf != NULL)
- free (finfo.symbuf);
- if (finfo.symshndxbuf != NULL)
- free (finfo.symshndxbuf);
- for (o = abfd->sections; o != NULL; o = o->next)
- {
- if ((o->flags & SEC_RELOC) != 0
- && elf_section_data (o)->rel_hashes != NULL)
- free (elf_section_data (o)->rel_hashes);
- }
-
- return FALSE;
-}
-
-/* Add a symbol to the output symbol table. */
-
-static bfd_boolean
-elf_link_output_sym (struct elf_final_link_info *finfo,
- const char *name,
- Elf_Internal_Sym *elfsym,
- asection *input_sec,
- struct elf_link_hash_entry *h)
-{
- Elf_External_Sym *dest;
- Elf_External_Sym_Shndx *destshndx;
- bfd_boolean (*output_symbol_hook)
- (struct bfd_link_info *, const char *, Elf_Internal_Sym *, asection *,
- struct elf_link_hash_entry *);
-
- output_symbol_hook = get_elf_backend_data (finfo->output_bfd)->
- elf_backend_link_output_symbol_hook;
- if (output_symbol_hook != NULL)
- {
- if (! (*output_symbol_hook) (finfo->info, name, elfsym, input_sec, h))
- return FALSE;
- }
-
- if (name == NULL || *name == '\0')
- elfsym->st_name = 0;
- else if (input_sec->flags & SEC_EXCLUDE)
- elfsym->st_name = 0;
- else
- {
- elfsym->st_name = (unsigned long) _bfd_stringtab_add (finfo->symstrtab,
- name, TRUE, FALSE);
- if (elfsym->st_name == (unsigned long) -1)
- return FALSE;
- }
-
- if (finfo->symbuf_count >= finfo->symbuf_size)
- {
- if (! elf_link_flush_output_syms (finfo))
- return FALSE;
- }
-
- dest = finfo->symbuf + finfo->symbuf_count;
- destshndx = finfo->symshndxbuf;
- if (destshndx != NULL)
- {
- if (bfd_get_symcount (finfo->output_bfd) >= finfo->shndxbuf_size)
- {
- bfd_size_type amt;
-
- amt = finfo->shndxbuf_size * sizeof (Elf_External_Sym_Shndx);
- finfo->symshndxbuf = destshndx = bfd_realloc (destshndx, amt * 2);
- if (destshndx == NULL)
- return FALSE;
- memset ((char *) destshndx + amt, 0, amt);
- finfo->shndxbuf_size *= 2;
- }
- destshndx += bfd_get_symcount (finfo->output_bfd);
- }
-
- elf_swap_symbol_out (finfo->output_bfd, elfsym, dest, destshndx);
- finfo->symbuf_count += 1;
- bfd_get_symcount (finfo->output_bfd) += 1;
-
- return TRUE;
-}
-
-/* Flush the output symbols to the file. */
-
-static bfd_boolean
-elf_link_flush_output_syms (struct elf_final_link_info *finfo)
-{
- if (finfo->symbuf_count > 0)
- {
- Elf_Internal_Shdr *hdr;
- file_ptr pos;
- bfd_size_type amt;
-
- hdr = &elf_tdata (finfo->output_bfd)->symtab_hdr;
- pos = hdr->sh_offset + hdr->sh_size;
- amt = finfo->symbuf_count * sizeof (Elf_External_Sym);
- if (bfd_seek (finfo->output_bfd, pos, SEEK_SET) != 0
- || bfd_bwrite (finfo->symbuf, amt, finfo->output_bfd) != amt)
- return FALSE;
-
- hdr->sh_size += amt;
- finfo->symbuf_count = 0;
- }
-
- return TRUE;
-}
-
-/* For DSOs loaded in via a DT_NEEDED entry, emulate ld.so in
- allowing an unsatisfied unversioned symbol in the DSO to match a
- versioned symbol that would normally require an explicit version.
- We also handle the case that a DSO references a hidden symbol
- which may be satisfied by a versioned symbol in another DSO. */
-
-static bfd_boolean
-elf_link_check_versioned_symbol (struct bfd_link_info *info,
- struct elf_link_hash_entry *h)
-{
- bfd *abfd;
- struct elf_link_loaded_list *loaded;
-
- if (!is_elf_hash_table (info->hash))
- return FALSE;
-
- switch (h->root.type)
- {
- default:
- abfd = NULL;
- break;
-
- case bfd_link_hash_undefined:
- case bfd_link_hash_undefweak:
- abfd = h->root.u.undef.abfd;
- if ((abfd->flags & DYNAMIC) == 0
- || elf_dyn_lib_class (abfd) != DYN_DT_NEEDED)
- return FALSE;
- break;
-
- case bfd_link_hash_defined:
- case bfd_link_hash_defweak:
- abfd = h->root.u.def.section->owner;
- break;
-
- case bfd_link_hash_common:
- abfd = h->root.u.c.p->section->owner;
- break;
- }
- BFD_ASSERT (abfd != NULL);
-
- for (loaded = elf_hash_table (info)->loaded;
- loaded != NULL;
- loaded = loaded->next)
- {
- bfd *input;
- Elf_Internal_Shdr *hdr;
- bfd_size_type symcount;
- bfd_size_type extsymcount;
- bfd_size_type extsymoff;
- Elf_Internal_Shdr *versymhdr;
- Elf_Internal_Sym *isym;
- Elf_Internal_Sym *isymend;
- Elf_Internal_Sym *isymbuf;
- Elf_External_Versym *ever;
- Elf_External_Versym *extversym;
-
- input = loaded->abfd;
-
- /* We check each DSO for a possible hidden versioned definition. */
- if (input == abfd
- || (input->flags & DYNAMIC) == 0
- || elf_dynversym (input) == 0)
- continue;
-
- hdr = &elf_tdata (input)->dynsymtab_hdr;
-
- symcount = hdr->sh_size / sizeof (Elf_External_Sym);
- if (elf_bad_symtab (input))
- {
- extsymcount = symcount;
- extsymoff = 0;
- }
- else
- {
- extsymcount = symcount - hdr->sh_info;
- extsymoff = hdr->sh_info;
- }
-
- if (extsymcount == 0)
- continue;
-
- isymbuf = bfd_elf_get_elf_syms (input, hdr, extsymcount, extsymoff,
- NULL, NULL, NULL);
- if (isymbuf == NULL)
- return FALSE;
-
- /* Read in any version definitions. */
- versymhdr = &elf_tdata (input)->dynversym_hdr;
- extversym = bfd_malloc (versymhdr->sh_size);
- if (extversym == NULL)
- goto error_ret;
-
- if (bfd_seek (input, versymhdr->sh_offset, SEEK_SET) != 0
- || (bfd_bread (extversym, versymhdr->sh_size, input)
- != versymhdr->sh_size))
- {
- free (extversym);
- error_ret:
- free (isymbuf);
- return FALSE;
- }
-
- ever = extversym + extsymoff;
- isymend = isymbuf + extsymcount;
- for (isym = isymbuf; isym < isymend; isym++, ever++)
- {
- const char *name;
- Elf_Internal_Versym iver;
- unsigned short version_index;
-
- if (ELF_ST_BIND (isym->st_info) == STB_LOCAL
- || isym->st_shndx == SHN_UNDEF)
- continue;
-
- name = bfd_elf_string_from_elf_section (input,
- hdr->sh_link,
- isym->st_name);
- if (strcmp (name, h->root.root.string) != 0)
- continue;
-
- _bfd_elf_swap_versym_in (input, ever, &iver);
-
- if ((iver.vs_vers & VERSYM_HIDDEN) == 0)
- {
- /* If we have a non-hidden versioned sym, then it should
- have provided a definition for the undefined sym. */
- abort ();
- }
-
- version_index = iver.vs_vers & VERSYM_VERSION;
- if (version_index == 1 || version_index == 2)
- {
- /* This is the base or first version. We can use it. */
- free (extversym);
- free (isymbuf);
- return TRUE;
- }
- }
-
- free (extversym);
- free (isymbuf);
- }
-
- return FALSE;
-}
-
-/* Add an external symbol to the symbol table. This is called from
- the hash table traversal routine. When generating a shared object,
- we go through the symbol table twice. The first time we output
- anything that might have been forced to local scope in a version
- script. The second time we output the symbols that are still
- global symbols. */
-
-static bfd_boolean
-elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
-{
- struct elf_outext_info *eoinfo = data;
- struct elf_final_link_info *finfo = eoinfo->finfo;
- bfd_boolean strip;
- Elf_Internal_Sym sym;
- asection *input_sec;
-
- if (h->root.type == bfd_link_hash_warning)
- {
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
- if (h->root.type == bfd_link_hash_new)
- return TRUE;
- }
-
- /* Decide whether to output this symbol in this pass. */
- if (eoinfo->localsyms)
- {
- if ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
- return TRUE;
- }
- else
- {
- if ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)
- return TRUE;
- }
-
- /* If we have an undefined symbol reference here then it must have
- come from a shared library that is being linked in. (Undefined
- references in regular files have already been handled). If we
- are reporting errors for this situation then do so now. */
- if (h->root.type == bfd_link_hash_undefined
- && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0
- && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0
- && ! elf_link_check_versioned_symbol (finfo->info, h)
- && finfo->info->unresolved_syms_in_shared_libs != RM_IGNORE)
- {
- if (! ((*finfo->info->callbacks->undefined_symbol)
- (finfo->info, h->root.root.string, h->root.u.undef.abfd,
- NULL, 0, finfo->info->unresolved_syms_in_shared_libs == RM_GENERATE_ERROR)))
- {
- eoinfo->failed = TRUE;
- return FALSE;
- }
- }
-
- /* We should also warn if a forced local symbol is referenced from
- shared libraries. */
- if (! finfo->info->relocatable
- && (! finfo->info->shared)
- && (h->elf_link_hash_flags
- & (ELF_LINK_FORCED_LOCAL | ELF_LINK_HASH_REF_DYNAMIC | ELF_LINK_DYNAMIC_DEF | ELF_LINK_DYNAMIC_WEAK))
- == (ELF_LINK_FORCED_LOCAL | ELF_LINK_HASH_REF_DYNAMIC)
- && ! elf_link_check_versioned_symbol (finfo->info, h))
- {
- (*_bfd_error_handler)
- (_("%s: %s symbol `%s' in %s is referenced by DSO"),
- bfd_get_filename (finfo->output_bfd),
- ELF_ST_VISIBILITY (h->other) == STV_INTERNAL
- ? "internal"
- : ELF_ST_VISIBILITY (h->other) == STV_HIDDEN
- ? "hidden" : "local",
- h->root.root.string,
- bfd_archive_filename (h->root.u.def.section->owner));
- eoinfo->failed = TRUE;
- return FALSE;
- }
-
- /* We don't want to output symbols that have never been mentioned by
- a regular file, or that we have been told to strip. However, if
- h->indx is set to -2, the symbol is used by a reloc and we must
- output it. */
- if (h->indx == -2)
- strip = FALSE;
- else if (((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
- || (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0)
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0
- && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0)
- strip = TRUE;
- else if (finfo->info->strip == strip_all)
- strip = TRUE;
- else if (finfo->info->strip == strip_some
- && bfd_hash_lookup (finfo->info->keep_hash,
- h->root.root.string, FALSE, FALSE) == NULL)
- strip = TRUE;
- else if (finfo->info->strip_discarded
- && (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
- && elf_discarded_section (h->root.u.def.section))
- strip = TRUE;
- else
- strip = FALSE;
-
- /* If we're stripping it, and it's not a dynamic symbol, there's
- nothing else to do unless it is a forced local symbol. */
- if (strip
- && h->dynindx == -1
- && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
- return TRUE;
-
- sym.st_value = 0;
- sym.st_size = h->size;
- sym.st_other = h->other;
- if ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)
- sym.st_info = ELF_ST_INFO (STB_LOCAL, h->type);
- else if (h->root.type == bfd_link_hash_undefweak
- || h->root.type == bfd_link_hash_defweak)
- sym.st_info = ELF_ST_INFO (STB_WEAK, h->type);
- else
- sym.st_info = ELF_ST_INFO (STB_GLOBAL, h->type);
-
- switch (h->root.type)
- {
- default:
- case bfd_link_hash_new:
- case bfd_link_hash_warning:
- abort ();
- return FALSE;
-
- case bfd_link_hash_undefined:
- case bfd_link_hash_undefweak:
- input_sec = bfd_und_section_ptr;
- sym.st_shndx = SHN_UNDEF;
- break;
-
- case bfd_link_hash_defined:
- case bfd_link_hash_defweak:
- {
- input_sec = h->root.u.def.section;
- if (input_sec->output_section != NULL)
- {
- sym.st_shndx =
- _bfd_elf_section_from_bfd_section (finfo->output_bfd,
- input_sec->output_section);
- if (sym.st_shndx == SHN_BAD)
- {
- (*_bfd_error_handler)
- (_("%s: could not find output section %s for input section %s"),
- bfd_get_filename (finfo->output_bfd),
- input_sec->output_section->name,
- input_sec->name);
- eoinfo->failed = TRUE;
- return FALSE;
- }
-
- /* ELF symbols in relocatable files are section relative,
- but in nonrelocatable files they are virtual
- addresses. */
- sym.st_value = h->root.u.def.value + input_sec->output_offset;
- if (! finfo->info->relocatable)
- {
- sym.st_value += input_sec->output_section->vma;
- if (h->type == STT_TLS)
- {
- /* STT_TLS symbols are relative to PT_TLS segment
- base. */
- BFD_ASSERT (elf_hash_table (finfo->info)->tls_sec != NULL);
- sym.st_value -= elf_hash_table (finfo->info)->tls_sec->vma;
- }
- }
- }
- else
- {
- BFD_ASSERT (input_sec->owner == NULL
- || (input_sec->owner->flags & DYNAMIC) != 0);
- sym.st_shndx = SHN_UNDEF;
- input_sec = bfd_und_section_ptr;
- }
- }
- break;
-
- case bfd_link_hash_common:
- input_sec = h->root.u.c.p->section;
- sym.st_shndx = SHN_COMMON;
- sym.st_value = 1 << h->root.u.c.p->alignment_power;
- break;
-
- case bfd_link_hash_indirect:
- /* These symbols are created by symbol versioning. They point
- to the decorated version of the name. For example, if the
- symbol foo@@GNU_1.2 is the default, which should be used when
- foo is used with no version, then we add an indirect symbol
- foo which points to foo@@GNU_1.2. We ignore these symbols,
- since the indirected symbol is already in the hash table. */
- return TRUE;
- }
-
- /* Give the processor backend a chance to tweak the symbol value,
- and also to finish up anything that needs to be done for this
- symbol. FIXME: Not calling elf_backend_finish_dynamic_symbol for
- forced local syms when non-shared is due to a historical quirk. */
- if ((h->dynindx != -1
- || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)
- && ((finfo->info->shared
- && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
- || h->root.type != bfd_link_hash_undefweak))
- || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
- && elf_hash_table (finfo->info)->dynamic_sections_created)
- {
- const struct elf_backend_data *bed;
-
- bed = get_elf_backend_data (finfo->output_bfd);
- if (! ((*bed->elf_backend_finish_dynamic_symbol)
- (finfo->output_bfd, finfo->info, h, &sym)))
- {
- eoinfo->failed = TRUE;
- return FALSE;
- }
- }
-
- /* If we are marking the symbol as undefined, and there are no
- non-weak references to this symbol from a regular object, then
- mark the symbol as weak undefined; if there are non-weak
- references, mark the symbol as strong. We can't do this earlier,
- because it might not be marked as undefined until the
- finish_dynamic_symbol routine gets through with it. */
- if (sym.st_shndx == SHN_UNDEF
- && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) != 0
- && (ELF_ST_BIND (sym.st_info) == STB_GLOBAL
- || ELF_ST_BIND (sym.st_info) == STB_WEAK))
- {
- int bindtype;
-
- if ((h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR_NONWEAK) != 0)
- bindtype = STB_GLOBAL;
- else
- bindtype = STB_WEAK;
- sym.st_info = ELF_ST_INFO (bindtype, ELF_ST_TYPE (sym.st_info));
- }
-
- /* If a non-weak symbol with non-default visibility is not defined
- locally, it is a fatal error. */
- if (! finfo->info->relocatable
- && ELF_ST_VISIBILITY (sym.st_other) != STV_DEFAULT
- && ELF_ST_BIND (sym.st_info) != STB_WEAK
- && h->root.type == bfd_link_hash_undefined
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
- {
- (*_bfd_error_handler)
- (_("%s: %s symbol `%s' isn't defined"),
- bfd_get_filename (finfo->output_bfd),
- ELF_ST_VISIBILITY (sym.st_other) == STV_PROTECTED
- ? "protected"
- : ELF_ST_VISIBILITY (sym.st_other) == STV_INTERNAL
- ? "internal" : "hidden",
- h->root.root.string);
- eoinfo->failed = TRUE;
- return FALSE;
- }
-
- /* If this symbol should be put in the .dynsym section, then put it
- there now. We already know the symbol index. We also fill in
- the entry in the .hash section. */
- if (h->dynindx != -1
- && elf_hash_table (finfo->info)->dynamic_sections_created)
- {
- size_t bucketcount;
- size_t bucket;
- size_t hash_entry_size;
- bfd_byte *bucketpos;
- bfd_vma chain;
- Elf_External_Sym *esym;
-
- sym.st_name = h->dynstr_index;
- esym = (Elf_External_Sym *) finfo->dynsym_sec->contents + h->dynindx;
- elf_swap_symbol_out (finfo->output_bfd, &sym, esym, 0);
-
- bucketcount = elf_hash_table (finfo->info)->bucketcount;
- bucket = h->elf_hash_value % bucketcount;
- hash_entry_size
- = elf_section_data (finfo->hash_sec)->this_hdr.sh_entsize;
- bucketpos = ((bfd_byte *) finfo->hash_sec->contents
- + (bucket + 2) * hash_entry_size);
- chain = bfd_get (8 * hash_entry_size, finfo->output_bfd, bucketpos);
- bfd_put (8 * hash_entry_size, finfo->output_bfd, h->dynindx, bucketpos);
- bfd_put (8 * hash_entry_size, finfo->output_bfd, chain,
- ((bfd_byte *) finfo->hash_sec->contents
- + (bucketcount + 2 + h->dynindx) * hash_entry_size));
-
- if (finfo->symver_sec != NULL && finfo->symver_sec->contents != NULL)
- {
- Elf_Internal_Versym iversym;
- Elf_External_Versym *eversym;
-
- if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
- {
- if (h->verinfo.verdef == NULL)
- iversym.vs_vers = 0;
- else
- iversym.vs_vers = h->verinfo.verdef->vd_exp_refno + 1;
- }
- else
- {
- if (h->verinfo.vertree == NULL)
- iversym.vs_vers = 1;
- else
- iversym.vs_vers = h->verinfo.vertree->vernum + 1;
- }
-
- if ((h->elf_link_hash_flags & ELF_LINK_HIDDEN) != 0)
- iversym.vs_vers |= VERSYM_HIDDEN;
-
- eversym = (Elf_External_Versym *) finfo->symver_sec->contents;
- eversym += h->dynindx;
- _bfd_elf_swap_versym_out (finfo->output_bfd, &iversym, eversym);
- }
- }
-
- /* If we're stripping it, then it was just a dynamic symbol, and
- there's nothing else to do. */
- if (strip || (input_sec->flags & SEC_EXCLUDE) != 0)
- return TRUE;
-
- h->indx = bfd_get_symcount (finfo->output_bfd);
-
- if (! elf_link_output_sym (finfo, h->root.root.string, &sym, input_sec, h))
- {
- eoinfo->failed = TRUE;
- return FALSE;
- }
-
- return TRUE;
-}
-
-/* Link an input file into the linker output file. This function
- handles all the sections and relocations of the input file at once.
- This is so that we only have to read the local symbols once, and
- don't have to keep them in memory. */
-
-static bfd_boolean
-elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
-{
- bfd_boolean (*relocate_section)
- (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
- Elf_Internal_Rela *, Elf_Internal_Sym *, asection **);
- bfd *output_bfd;
- Elf_Internal_Shdr *symtab_hdr;
- size_t locsymcount;
- size_t extsymoff;
- Elf_Internal_Sym *isymbuf;
- Elf_Internal_Sym *isym;
- Elf_Internal_Sym *isymend;
- long *pindex;
- asection **ppsection;
- asection *o;
- const struct elf_backend_data *bed;
- bfd_boolean emit_relocs;
- struct elf_link_hash_entry **sym_hashes;
-
- output_bfd = finfo->output_bfd;
- bed = get_elf_backend_data (output_bfd);
- relocate_section = bed->elf_backend_relocate_section;
-
- /* If this is a dynamic object, we don't want to do anything here:
- we don't want the local symbols, and we don't want the section
- contents. */
- if ((input_bfd->flags & DYNAMIC) != 0)
- return TRUE;
-
- emit_relocs = (finfo->info->relocatable
- || finfo->info->emitrelocations
- || bed->elf_backend_emit_relocs);
-
- symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
- if (elf_bad_symtab (input_bfd))
- {
- locsymcount = symtab_hdr->sh_size / sizeof (Elf_External_Sym);
- extsymoff = 0;
- }
- else
- {
- locsymcount = symtab_hdr->sh_info;
- extsymoff = symtab_hdr->sh_info;
- }
-
- /* Read the local symbols. */
- isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
- if (isymbuf == NULL && locsymcount != 0)
- {
- isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, locsymcount, 0,
- finfo->internal_syms,
- finfo->external_syms,
- finfo->locsym_shndx);
- if (isymbuf == NULL)
- return FALSE;
- }
-
- /* Find local symbol sections and adjust values of symbols in
- SEC_MERGE sections. Write out those local symbols we know are
- going into the output file. */
- isymend = isymbuf + locsymcount;
- for (isym = isymbuf, pindex = finfo->indices, ppsection = finfo->sections;
- isym < isymend;
- isym++, pindex++, ppsection++)
- {
- asection *isec;
- const char *name;
- Elf_Internal_Sym osym;
-
- *pindex = -1;
-
- if (elf_bad_symtab (input_bfd))
- {
- if (ELF_ST_BIND (isym->st_info) != STB_LOCAL)
- {
- *ppsection = NULL;
- continue;
- }
- }
-
- if (isym->st_shndx == SHN_UNDEF)
- isec = bfd_und_section_ptr;
- else if (isym->st_shndx < SHN_LORESERVE
- || isym->st_shndx > SHN_HIRESERVE)
- {
- isec = section_from_elf_index (input_bfd, isym->st_shndx);
- if (isec
- && isec->sec_info_type == ELF_INFO_TYPE_MERGE
- && ELF_ST_TYPE (isym->st_info) != STT_SECTION)
- isym->st_value =
- _bfd_merged_section_offset (output_bfd, &isec,
- elf_section_data (isec)->sec_info,
- isym->st_value, 0);
- }
- else if (isym->st_shndx == SHN_ABS)
- isec = bfd_abs_section_ptr;
- else if (isym->st_shndx == SHN_COMMON)
- isec = bfd_com_section_ptr;
- else
- {
- /* Who knows? */
- isec = NULL;
- }
-
- *ppsection = isec;
-
- /* Don't output the first, undefined, symbol. */
- if (ppsection == finfo->sections)
- continue;
-
- if (ELF_ST_TYPE (isym->st_info) == STT_SECTION)
- {
- /* We never output section symbols. Instead, we use the
- section symbol of the corresponding section in the output
- file. */
- continue;
- }
-
- /* If we are stripping all symbols, we don't want to output this
- one. */
- if (finfo->info->strip == strip_all)
- continue;
-
- /* If we are discarding all local symbols, we don't want to
- output this one. If we are generating a relocatable output
- file, then some of the local symbols may be required by
- relocs; we output them below as we discover that they are
- needed. */
- if (finfo->info->discard == discard_all)
- continue;
-
- /* If this symbol is defined in a section which we are
- discarding, we don't need to keep it, but note that
- linker_mark is only reliable for sections that have contents.
- For the benefit of the MIPS ELF linker, we check SEC_EXCLUDE
- as well as linker_mark. */
- if ((isym->st_shndx < SHN_LORESERVE || isym->st_shndx > SHN_HIRESERVE)
- && isec != NULL
- && ((! isec->linker_mark && (isec->flags & SEC_HAS_CONTENTS) != 0)
- || (! finfo->info->relocatable
- && (isec->flags & SEC_EXCLUDE) != 0)))
- continue;
-
- /* Get the name of the symbol. */
- name = bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link,
- isym->st_name);
- if (name == NULL)
- return FALSE;
-
- /* See if we are discarding symbols with this name. */
- if ((finfo->info->strip == strip_some
- && (bfd_hash_lookup (finfo->info->keep_hash, name, FALSE, FALSE)
- == NULL))
- || (((finfo->info->discard == discard_sec_merge
- && (isec->flags & SEC_MERGE) && ! finfo->info->relocatable)
- || finfo->info->discard == discard_l)
- && bfd_is_local_label_name (input_bfd, name)))
- continue;
-
- /* If we get here, we are going to output this symbol. */
-
- osym = *isym;
-
- /* Adjust the section index for the output file. */
- osym.st_shndx = _bfd_elf_section_from_bfd_section (output_bfd,
- isec->output_section);
- if (osym.st_shndx == SHN_BAD)
- return FALSE;
-
- *pindex = bfd_get_symcount (output_bfd);
-
- /* ELF symbols in relocatable files are section relative, but
- in executable files they are virtual addresses. Note that
- this code assumes that all ELF sections have an associated
- BFD section with a reasonable value for output_offset; below
- we assume that they also have a reasonable value for
- output_section. Any special sections must be set up to meet
- these requirements. */
- osym.st_value += isec->output_offset;
- if (! finfo->info->relocatable)
- {
- osym.st_value += isec->output_section->vma;
- if (ELF_ST_TYPE (osym.st_info) == STT_TLS)
- {
- /* STT_TLS symbols are relative to PT_TLS segment base. */
- BFD_ASSERT (elf_hash_table (finfo->info)->tls_sec != NULL);
- osym.st_value -= elf_hash_table (finfo->info)->tls_sec->vma;
- }
- }
-
- if (! elf_link_output_sym (finfo, name, &osym, isec, NULL))
- return FALSE;
- }
-
- /* Relocate the contents of each section. */
- sym_hashes = elf_sym_hashes (input_bfd);
- for (o = input_bfd->sections; o != NULL; o = o->next)
- {
- bfd_byte *contents;
-
- if (! o->linker_mark)
- {
- /* This section was omitted from the link. */
- continue;
- }
-
- if ((o->flags & SEC_HAS_CONTENTS) == 0
- || (o->_raw_size == 0 && (o->flags & SEC_RELOC) == 0))
- continue;
-
- if ((o->flags & SEC_LINKER_CREATED) != 0)
- {
- /* Section was created by _bfd_elf_link_create_dynamic_sections
- or somesuch. */
- continue;
- }
-
- /* Get the contents of the section. They have been cached by a
- relaxation routine. Note that o is a section in an input
- file, so the contents field will not have been set by any of
- the routines which work on output files. */
- if (elf_section_data (o)->this_hdr.contents != NULL)
- contents = elf_section_data (o)->this_hdr.contents;
- else
- {
- contents = finfo->contents;
- if (! bfd_get_section_contents (input_bfd, o, contents, 0,
- o->_raw_size))
- return FALSE;
- }
-
- if ((o->flags & SEC_RELOC) != 0)
- {
- Elf_Internal_Rela *internal_relocs;
-
- /* Get the swapped relocs. */
- internal_relocs
- = _bfd_elf_link_read_relocs (input_bfd, o, finfo->external_relocs,
- finfo->internal_relocs, FALSE);
- if (internal_relocs == NULL
- && o->reloc_count > 0)
- return FALSE;
-
- /* Run through the relocs looking for any against symbols
- from discarded sections and section symbols from
- removed link-once sections. Complain about relocs
- against discarded sections. Zero relocs against removed
- link-once sections. Preserve debug information as much
- as we can. */
- if (!elf_section_ignore_discarded_relocs (o))
- {
- Elf_Internal_Rela *rel, *relend;
-
- rel = internal_relocs;
- relend = rel + o->reloc_count * bed->s->int_rels_per_ext_rel;
- for ( ; rel < relend; rel++)
- {
- unsigned long r_symndx = ELF_R_SYM (rel->r_info);
- asection *sec;
-
- if (r_symndx >= locsymcount
- || (elf_bad_symtab (input_bfd)
- && finfo->sections[r_symndx] == NULL))
- {
- struct elf_link_hash_entry *h;
-
- h = sym_hashes[r_symndx - extsymoff];
- while (h->root.type == bfd_link_hash_indirect
- || h->root.type == bfd_link_hash_warning)
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
- /* Complain if the definition comes from a
- discarded section. */
- sec = h->root.u.def.section;
- if ((h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
- && elf_discarded_section (sec))
- {
- if ((o->flags & SEC_DEBUGGING) != 0)
- {
- BFD_ASSERT (r_symndx != 0);
- /* Try to preserve debug information. */
- if ((o->flags & SEC_DEBUGGING) != 0
- && sec->kept_section != NULL
- && sec->_raw_size == sec->kept_section->_raw_size)
- h->root.u.def.section
- = sec->kept_section;
- else
- memset (rel, 0, sizeof (*rel));
- }
- else
- finfo->info->callbacks->error_handler
- (LD_DEFINITION_IN_DISCARDED_SECTION,
- _("%T: discarded in section `%s' from %s\n"),
- h->root.root.string,
- h->root.root.string,
- h->root.u.def.section->name,
- bfd_archive_filename (h->root.u.def.section->owner));
- }
- }
- else
- {
- sec = finfo->sections[r_symndx];
-
- if (sec != NULL && elf_discarded_section (sec))
- {
- if ((o->flags & SEC_DEBUGGING) != 0
- || (sec->flags & SEC_LINK_ONCE) != 0)
- {
- BFD_ASSERT (r_symndx != 0);
- /* Try to preserve debug information. */
- if ((o->flags & SEC_DEBUGGING) != 0
- && sec->kept_section != NULL
- && sec->_raw_size == sec->kept_section->_raw_size)
- finfo->sections[r_symndx]
- = sec->kept_section;
- else
- {
- rel->r_info
- = ELF_R_INFO (0, ELF_R_TYPE (rel->r_info));
- rel->r_addend = 0;
- }
- }
- else
- {
- static int count;
- int ok;
- char *buf;
-
- ok = asprintf (&buf, "local symbol %d",
- count++);
- if (ok <= 0)
- buf = (char *) "local symbol";
- finfo->info->callbacks->error_handler
- (LD_DEFINITION_IN_DISCARDED_SECTION,
- _("%T: discarded in section `%s' from %s\n"),
- buf, buf, sec->name,
- bfd_archive_filename (input_bfd));
- if (ok != -1)
- free (buf);
- }
- }
- }
- }
- }
-
- /* Relocate the section by invoking a back end routine.
-
- The back end routine is responsible for adjusting the
- section contents as necessary, and (if using Rela relocs
- and generating a relocatable output file) adjusting the
- reloc addend as necessary.
-
- The back end routine does not have to worry about setting
- the reloc address or the reloc symbol index.
-
- The back end routine is given a pointer to the swapped in
- internal symbols, and can access the hash table entries
- for the external symbols via elf_sym_hashes (input_bfd).
-
- When generating relocatable output, the back end routine
- must handle STB_LOCAL/STT_SECTION symbols specially. The
- output symbol is going to be a section symbol
- corresponding to the output section, which will require
- the addend to be adjusted. */
-
- if (! (*relocate_section) (output_bfd, finfo->info,
- input_bfd, o, contents,
- internal_relocs,
- isymbuf,
- finfo->sections))
- return FALSE;
-
- if (emit_relocs)
- {
- Elf_Internal_Rela *irela;
- Elf_Internal_Rela *irelaend;
- bfd_vma last_offset;
- struct elf_link_hash_entry **rel_hash;
- Elf_Internal_Shdr *input_rel_hdr, *input_rel_hdr2;
- unsigned int next_erel;
- bfd_boolean (*reloc_emitter)
- (bfd *, asection *, Elf_Internal_Shdr *, Elf_Internal_Rela *);
- bfd_boolean rela_normal;
-
- input_rel_hdr = &elf_section_data (o)->rel_hdr;
- rela_normal = (bed->rela_normal
- && (input_rel_hdr->sh_entsize
- == sizeof (Elf_External_Rela)));
-
- /* Adjust the reloc addresses and symbol indices. */
-
- irela = internal_relocs;
- irelaend = irela + o->reloc_count * bed->s->int_rels_per_ext_rel;
- rel_hash = (elf_section_data (o->output_section)->rel_hashes
- + elf_section_data (o->output_section)->rel_count
- + elf_section_data (o->output_section)->rel_count2);
- last_offset = o->output_offset;
- if (!finfo->info->relocatable)
- last_offset += o->output_section->vma;
- for (next_erel = 0; irela < irelaend; irela++, next_erel++)
- {
- unsigned long r_symndx;
- asection *sec;
- Elf_Internal_Sym sym;
-
- if (next_erel == bed->s->int_rels_per_ext_rel)
- {
- rel_hash++;
- next_erel = 0;
- }
-
- irela->r_offset = _bfd_elf_section_offset (output_bfd,
- finfo->info, o,
- irela->r_offset);
- if (irela->r_offset >= (bfd_vma) -2)
- {
- /* This is a reloc for a deleted entry or somesuch.
- Turn it into an R_*_NONE reloc, at the same
- offset as the last reloc. elf_eh_frame.c and
- elf_bfd_discard_info rely on reloc offsets
- being ordered. */
- irela->r_offset = last_offset;
- irela->r_info = 0;
- irela->r_addend = 0;
- continue;
- }
-
- irela->r_offset += o->output_offset;
-
- /* Relocs in an executable have to be virtual addresses. */
- if (!finfo->info->relocatable)
- irela->r_offset += o->output_section->vma;
-
- last_offset = irela->r_offset;
-
- r_symndx = ELF_R_SYM (irela->r_info);
- if (r_symndx == STN_UNDEF)
- continue;
-
- if (r_symndx >= locsymcount
- || (elf_bad_symtab (input_bfd)
- && finfo->sections[r_symndx] == NULL))
- {
- struct elf_link_hash_entry *rh;
- unsigned long indx;
-
- /* This is a reloc against a global symbol. We
- have not yet output all the local symbols, so
- we do not know the symbol index of any global
- symbol. We set the rel_hash entry for this
- reloc to point to the global hash table entry
- for this symbol. The symbol index is then
- set at the end of elf_bfd_final_link. */
- indx = r_symndx - extsymoff;
- rh = elf_sym_hashes (input_bfd)[indx];
- while (rh->root.type == bfd_link_hash_indirect
- || rh->root.type == bfd_link_hash_warning)
- rh = (struct elf_link_hash_entry *) rh->root.u.i.link;
-
- /* Setting the index to -2 tells
- elf_link_output_extsym that this symbol is
- used by a reloc. */
- BFD_ASSERT (rh->indx < 0);
- rh->indx = -2;
-
- *rel_hash = rh;
-
- continue;
- }
-
- /* This is a reloc against a local symbol. */
-
- *rel_hash = NULL;
- sym = isymbuf[r_symndx];
- sec = finfo->sections[r_symndx];
- if (ELF_ST_TYPE (sym.st_info) == STT_SECTION)
- {
- /* I suppose the backend ought to fill in the
- section of any STT_SECTION symbol against a
- processor specific section. If we have
- discarded a section, the output_section will
- be the absolute section. */
- if (bfd_is_abs_section (sec)
- || (sec != NULL
- && bfd_is_abs_section (sec->output_section)))
- r_symndx = 0;
- else if (sec == NULL || sec->owner == NULL)
- {
- bfd_set_error (bfd_error_bad_value);
- return FALSE;
- }
- else
- {
- r_symndx = sec->output_section->target_index;
- BFD_ASSERT (r_symndx != 0);
- }
-
- /* Adjust the addend according to where the
- section winds up in the output section. */
- if (rela_normal)
- irela->r_addend += sec->output_offset;
- }
- else
- {
- if (finfo->indices[r_symndx] == -1)
- {
- unsigned long shlink;
- const char *name;
- asection *osec;
-
- if (finfo->info->strip == strip_all)
- {
- /* You can't do ld -r -s. */
- bfd_set_error (bfd_error_invalid_operation);
- return FALSE;
- }
-
- /* This symbol was skipped earlier, but
- since it is needed by a reloc, we
- must output it now. */
- shlink = symtab_hdr->sh_link;
- name = (bfd_elf_string_from_elf_section
- (input_bfd, shlink, sym.st_name));
- if (name == NULL)
- return FALSE;
-
- osec = sec->output_section;
- sym.st_shndx =
- _bfd_elf_section_from_bfd_section (output_bfd,
- osec);
- if (sym.st_shndx == SHN_BAD)
- return FALSE;
-
- sym.st_value += sec->output_offset;
- if (! finfo->info->relocatable)
- {
- sym.st_value += osec->vma;
- if (ELF_ST_TYPE (sym.st_info) == STT_TLS)
- {
- /* STT_TLS symbols are relative to PT_TLS
- segment base. */
- BFD_ASSERT (elf_hash_table (finfo->info)
- ->tls_sec != NULL);
- sym.st_value -= (elf_hash_table (finfo->info)
- ->tls_sec->vma);
- }
- }
-
- finfo->indices[r_symndx]
- = bfd_get_symcount (output_bfd);
-
- if (! elf_link_output_sym (finfo, name, &sym, sec,
- NULL))
- return FALSE;
- }
-
- r_symndx = finfo->indices[r_symndx];
- }
-
- irela->r_info = ELF_R_INFO (r_symndx,
- ELF_R_TYPE (irela->r_info));
- }
-
- /* Swap out the relocs. */
- if (bed->elf_backend_emit_relocs
- && !(finfo->info->relocatable
- || finfo->info->emitrelocations))
- reloc_emitter = bed->elf_backend_emit_relocs;
- else
- reloc_emitter = _bfd_elf_link_output_relocs;
-
- if (input_rel_hdr->sh_size != 0
- && ! (*reloc_emitter) (output_bfd, o, input_rel_hdr,
- internal_relocs))
- return FALSE;
-
- input_rel_hdr2 = elf_section_data (o)->rel_hdr2;
- if (input_rel_hdr2 && input_rel_hdr2->sh_size != 0)
- {
- internal_relocs += (NUM_SHDR_ENTRIES (input_rel_hdr)
- * bed->s->int_rels_per_ext_rel);
- if (! (*reloc_emitter) (output_bfd, o, input_rel_hdr2,
- internal_relocs))
- return FALSE;
- }
- }
- }
-
- /* Write out the modified section contents. */
- if (bed->elf_backend_write_section
- && (*bed->elf_backend_write_section) (output_bfd, o, contents))
- {
- /* Section written out. */
- }
- else switch (o->sec_info_type)
- {
- case ELF_INFO_TYPE_STABS:
- if (! (_bfd_write_section_stabs
- (output_bfd,
- &elf_hash_table (finfo->info)->stab_info,
- o, &elf_section_data (o)->sec_info, contents)))
- return FALSE;
- break;
- case ELF_INFO_TYPE_MERGE:
- if (! _bfd_write_merged_section (output_bfd, o,
- elf_section_data (o)->sec_info))
- return FALSE;
- break;
- case ELF_INFO_TYPE_EH_FRAME:
- {
- if (! _bfd_elf_write_section_eh_frame (output_bfd, finfo->info,
- o, contents))
- return FALSE;
- }
- break;
- default:
- {
- bfd_size_type sec_size;
-
- sec_size = (o->_cooked_size != 0 ? o->_cooked_size : o->_raw_size);
- if (! (o->flags & SEC_EXCLUDE)
- && ! bfd_set_section_contents (output_bfd, o->output_section,
- contents,
- (file_ptr) o->output_offset,
- sec_size))
- return FALSE;
- }
- break;
- }
- }
-
- return TRUE;
-}
-
-/* Generate a reloc when linking an ELF file. This is a reloc
- requested by the linker, and does come from any input file. This
- is used to build constructor and destructor tables when linking
- with -Ur. */
-
-static bfd_boolean
-elf_reloc_link_order (bfd *output_bfd,
- struct bfd_link_info *info,
- asection *output_section,
- struct bfd_link_order *link_order)
-{
- reloc_howto_type *howto;
- long indx;
- bfd_vma offset;
- bfd_vma addend;
- struct elf_link_hash_entry **rel_hash_ptr;
- Elf_Internal_Shdr *rel_hdr;
- const struct elf_backend_data *bed = get_elf_backend_data (output_bfd);
- Elf_Internal_Rela irel[MAX_INT_RELS_PER_EXT_REL];
- bfd_byte *erel;
- unsigned int i;
-
- howto = bfd_reloc_type_lookup (output_bfd, link_order->u.reloc.p->reloc);
- if (howto == NULL)
- {
- bfd_set_error (bfd_error_bad_value);
- return FALSE;
- }
-
- addend = link_order->u.reloc.p->addend;
-
- /* Figure out the symbol index. */
- rel_hash_ptr = (elf_section_data (output_section)->rel_hashes
- + elf_section_data (output_section)->rel_count
- + elf_section_data (output_section)->rel_count2);
- if (link_order->type == bfd_section_reloc_link_order)
- {
- indx = link_order->u.reloc.p->u.section->target_index;
- BFD_ASSERT (indx != 0);
- *rel_hash_ptr = NULL;
- }
- else
- {
- struct elf_link_hash_entry *h;
-
- /* Treat a reloc against a defined symbol as though it were
- actually against the section. */
- h = ((struct elf_link_hash_entry *)
- bfd_wrapped_link_hash_lookup (output_bfd, info,
- link_order->u.reloc.p->u.name,
- FALSE, FALSE, TRUE));
- if (h != NULL
- && (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak))
- {
- asection *section;
-
- section = h->root.u.def.section;
- indx = section->output_section->target_index;
- *rel_hash_ptr = NULL;
- /* It seems that we ought to add the symbol value to the
- addend here, but in practice it has already been added
- because it was passed to constructor_callback. */
- addend += section->output_section->vma + section->output_offset;
- }
- else if (h != NULL)
- {
- /* Setting the index to -2 tells elf_link_output_extsym that
- this symbol is used by a reloc. */
- h->indx = -2;
- *rel_hash_ptr = h;
- indx = 0;
- }
- else
- {
- if (! ((*info->callbacks->unattached_reloc)
- (info, link_order->u.reloc.p->u.name, NULL, NULL, 0)))
- return FALSE;
- indx = 0;
- }
- }
-
- /* If this is an inplace reloc, we must write the addend into the
- object file. */
- if (howto->partial_inplace && addend != 0)
- {
- bfd_size_type size;
- bfd_reloc_status_type rstat;
- bfd_byte *buf;
- bfd_boolean ok;
- const char *sym_name;
-
- size = bfd_get_reloc_size (howto);
- buf = bfd_zmalloc (size);
- if (buf == NULL)
- return FALSE;
- rstat = _bfd_relocate_contents (howto, output_bfd, addend, buf);
- switch (rstat)
- {
- case bfd_reloc_ok:
- break;
-
- default:
- case bfd_reloc_outofrange:
- abort ();
-
- case bfd_reloc_overflow:
- if (link_order->type == bfd_section_reloc_link_order)
- sym_name = bfd_section_name (output_bfd,
- link_order->u.reloc.p->u.section);
- else
- sym_name = link_order->u.reloc.p->u.name;
- if (! ((*info->callbacks->reloc_overflow)
- (info, sym_name, howto->name, addend, NULL, NULL, 0)))
- {
- free (buf);
- return FALSE;
- }
- break;
- }
- ok = bfd_set_section_contents (output_bfd, output_section, buf,
- link_order->offset, size);
- free (buf);
- if (! ok)
- return FALSE;
- }
-
- /* The address of a reloc is relative to the section in a
- relocatable file, and is a virtual address in an executable
- file. */
- offset = link_order->offset;
- if (! info->relocatable)
- offset += output_section->vma;
-
- for (i = 0; i < bed->s->int_rels_per_ext_rel; i++)
- {
- irel[i].r_offset = offset;
- irel[i].r_info = 0;
- irel[i].r_addend = 0;
- }
- irel[0].r_info = ELF_R_INFO (indx, howto->type);
-
- rel_hdr = &elf_section_data (output_section)->rel_hdr;
- erel = rel_hdr->contents;
- if (rel_hdr->sh_type == SHT_REL)
- {
- erel += (elf_section_data (output_section)->rel_count
- * sizeof (Elf_External_Rel));
- (*bed->s->swap_reloc_out) (output_bfd, irel, erel);
- }
- else
- {
- irel[0].r_addend = addend;
- erel += (elf_section_data (output_section)->rel_count
- * sizeof (Elf_External_Rela));
- (*bed->s->swap_reloca_out) (output_bfd, irel, erel);
- }
-
- ++elf_section_data (output_section)->rel_count;
-
- return TRUE;
-}
-\f
-/* Garbage collect unused sections. */
-
-static bfd_boolean elf_gc_sweep_symbol
- (struct elf_link_hash_entry *, void *);
-
-static bfd_boolean elf_gc_allocate_got_offsets
- (struct elf_link_hash_entry *, void *);
-
-/* The mark phase of garbage collection. For a given section, mark
- it and any sections in this section's group, and all the sections
- which define symbols to which it refers. */
-
-typedef asection * (*gc_mark_hook_fn)
- (asection *, struct bfd_link_info *, Elf_Internal_Rela *,
- struct elf_link_hash_entry *, Elf_Internal_Sym *);
-
-static bfd_boolean
-elf_gc_mark (struct bfd_link_info *info,
- asection *sec,
- gc_mark_hook_fn gc_mark_hook)
-{
- bfd_boolean ret;
- asection *group_sec;
-
- sec->gc_mark = 1;
-
- /* Mark all the sections in the group. */
- group_sec = elf_section_data (sec)->next_in_group;
- if (group_sec && !group_sec->gc_mark)
- if (!elf_gc_mark (info, group_sec, gc_mark_hook))
- return FALSE;
-
- /* Look through the section relocs. */
- ret = TRUE;
- if ((sec->flags & SEC_RELOC) != 0 && sec->reloc_count > 0)
- {
- Elf_Internal_Rela *relstart, *rel, *relend;
- Elf_Internal_Shdr *symtab_hdr;
- struct elf_link_hash_entry **sym_hashes;
- size_t nlocsyms;
- size_t extsymoff;
- bfd *input_bfd = sec->owner;
- const struct elf_backend_data *bed = get_elf_backend_data (input_bfd);
- Elf_Internal_Sym *isym = NULL;
-
- symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
- sym_hashes = elf_sym_hashes (input_bfd);
-
- /* Read the local symbols. */
- if (elf_bad_symtab (input_bfd))
- {
- nlocsyms = symtab_hdr->sh_size / sizeof (Elf_External_Sym);
- extsymoff = 0;
- }
- else
- extsymoff = nlocsyms = symtab_hdr->sh_info;
-
- isym = (Elf_Internal_Sym *) symtab_hdr->contents;
- if (isym == NULL && nlocsyms != 0)
- {
- isym = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, nlocsyms, 0,
- NULL, NULL, NULL);
- if (isym == NULL)
- return FALSE;
- }
-
- /* Read the relocations. */
- relstart = _bfd_elf_link_read_relocs (input_bfd, sec, NULL, NULL,
- info->keep_memory);
- if (relstart == NULL)
- {
- ret = FALSE;
- goto out1;
- }
- relend = relstart + sec->reloc_count * bed->s->int_rels_per_ext_rel;
-
- for (rel = relstart; rel < relend; rel++)
- {
- unsigned long r_symndx;
- asection *rsec;
- struct elf_link_hash_entry *h;
-
- r_symndx = ELF_R_SYM (rel->r_info);
- if (r_symndx == 0)
- continue;
-
- if (r_symndx >= nlocsyms
- || ELF_ST_BIND (isym[r_symndx].st_info) != STB_LOCAL)
- {
- h = sym_hashes[r_symndx - extsymoff];
- rsec = (*gc_mark_hook) (sec, info, rel, h, NULL);
- }
- else
- {
- rsec = (*gc_mark_hook) (sec, info, rel, NULL, &isym[r_symndx]);
- }
-
- if (rsec && !rsec->gc_mark)
- {
- if (bfd_get_flavour (rsec->owner) != bfd_target_elf_flavour)
- rsec->gc_mark = 1;
- else if (!elf_gc_mark (info, rsec, gc_mark_hook))
- {
- ret = FALSE;
- goto out2;
- }
- }
- }
-
- out2:
- if (elf_section_data (sec)->relocs != relstart)
- free (relstart);
- out1:
- if (isym != NULL && symtab_hdr->contents != (unsigned char *) isym)
- {
- if (! info->keep_memory)
- free (isym);
- else
- symtab_hdr->contents = (unsigned char *) isym;
- }
- }
-
- return ret;
-}
-
-/* The sweep phase of garbage collection. Remove all garbage sections. */
-
-typedef bfd_boolean (*gc_sweep_hook_fn)
- (bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *);
-
-static bfd_boolean
-elf_gc_sweep (struct bfd_link_info *info, gc_sweep_hook_fn gc_sweep_hook)
-{
- bfd *sub;
-
- for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
- {
- asection *o;
-
- if (bfd_get_flavour (sub) != bfd_target_elf_flavour)
- continue;
-
- for (o = sub->sections; o != NULL; o = o->next)
- {
- /* Keep special sections. Keep .debug sections. */
- if ((o->flags & SEC_LINKER_CREATED)
- || (o->flags & SEC_DEBUGGING))
- o->gc_mark = 1;
-
- if (o->gc_mark)
- continue;
-
- /* Skip sweeping sections already excluded. */
- if (o->flags & SEC_EXCLUDE)
- continue;
-
- /* Since this is early in the link process, it is simple
- to remove a section from the output. */
- o->flags |= SEC_EXCLUDE;
-
- /* But we also have to update some of the relocation
- info we collected before. */
- if (gc_sweep_hook
- && (o->flags & SEC_RELOC) && o->reloc_count > 0)
- {
- Elf_Internal_Rela *internal_relocs;
- bfd_boolean r;
-
- internal_relocs
- = _bfd_elf_link_read_relocs (o->owner, o, NULL, NULL,
- info->keep_memory);
- if (internal_relocs == NULL)
- return FALSE;
-
- r = (*gc_sweep_hook) (o->owner, info, o, internal_relocs);
-
- if (elf_section_data (o)->relocs != internal_relocs)
- free (internal_relocs);
-
- if (!r)
- return FALSE;
- }
- }
- }
-
- /* Remove the symbols that were in the swept sections from the dynamic
- symbol table. GCFIXME: Anyone know how to get them out of the
- static symbol table as well? */
- {
- int i = 0;
-
- elf_link_hash_traverse (elf_hash_table (info), elf_gc_sweep_symbol, &i);
-
- elf_hash_table (info)->dynsymcount = i;
- }
-
- return TRUE;
-}
-
-/* Sweep symbols in swept sections. Called via elf_link_hash_traverse. */
-
-static bfd_boolean
-elf_gc_sweep_symbol (struct elf_link_hash_entry *h, void *idxptr)
-{
- int *idx = idxptr;
-
- if (h->root.type == bfd_link_hash_warning)
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
- if (h->dynindx != -1
- && ((h->root.type != bfd_link_hash_defined
- && h->root.type != bfd_link_hash_defweak)
- || h->root.u.def.section->gc_mark))
- h->dynindx = (*idx)++;
-
- return TRUE;
-}
-
-/* Propagate collected vtable information. This is called through
- elf_link_hash_traverse. */
-
-static bfd_boolean
-elf_gc_propagate_vtable_entries_used (struct elf_link_hash_entry *h, void *okp)
-{
- if (h->root.type == bfd_link_hash_warning)
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
- /* Those that are not vtables. */
- if (h->vtable_parent == NULL)
- return TRUE;
-
- /* Those vtables that do not have parents, we cannot merge. */
- if (h->vtable_parent == (struct elf_link_hash_entry *) -1)
- return TRUE;
-
- /* If we've already been done, exit. */
- if (h->vtable_entries_used && h->vtable_entries_used[-1])
- return TRUE;
-
- /* Make sure the parent's table is up to date. */
- elf_gc_propagate_vtable_entries_used (h->vtable_parent, okp);
-
- if (h->vtable_entries_used == NULL)
- {
- /* None of this table's entries were referenced. Re-use the
- parent's table. */
- h->vtable_entries_used = h->vtable_parent->vtable_entries_used;
- h->vtable_entries_size = h->vtable_parent->vtable_entries_size;
- }
- else
- {
- size_t n;
- bfd_boolean *cu, *pu;
-
- /* Or the parent's entries into ours. */
- cu = h->vtable_entries_used;
- cu[-1] = TRUE;
- pu = h->vtable_parent->vtable_entries_used;
- if (pu != NULL)
- {
- const struct elf_backend_data *bed;
- unsigned int log_file_align;
-
- bed = get_elf_backend_data (h->root.u.def.section->owner);
- log_file_align = bed->s->log_file_align;
- n = h->vtable_parent->vtable_entries_size >> log_file_align;
- while (n--)
- {
- if (*pu)
- *cu = TRUE;
- pu++;
- cu++;
- }
- }
- }
-
- return TRUE;
-}
-
-static bfd_boolean
-elf_gc_smash_unused_vtentry_relocs (struct elf_link_hash_entry *h, void *okp)
-{
- asection *sec;
- bfd_vma hstart, hend;
- Elf_Internal_Rela *relstart, *relend, *rel;
- const struct elf_backend_data *bed;
- unsigned int log_file_align;
-
- if (h->root.type == bfd_link_hash_warning)
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
- /* Take care of both those symbols that do not describe vtables as
- well as those that are not loaded. */
- if (h->vtable_parent == NULL)
- return TRUE;
-
- BFD_ASSERT (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak);
-
- sec = h->root.u.def.section;
- hstart = h->root.u.def.value;
- hend = hstart + h->size;
-
- relstart = _bfd_elf_link_read_relocs (sec->owner, sec, NULL, NULL, TRUE);
- if (!relstart)
- return *(bfd_boolean *) okp = FALSE;
- bed = get_elf_backend_data (sec->owner);
- log_file_align = bed->s->log_file_align;
-
- relend = relstart + sec->reloc_count * bed->s->int_rels_per_ext_rel;
-
- for (rel = relstart; rel < relend; ++rel)
- if (rel->r_offset >= hstart && rel->r_offset < hend)
- {
- /* If the entry is in use, do nothing. */
- if (h->vtable_entries_used
- && (rel->r_offset - hstart) < h->vtable_entries_size)
- {
- bfd_vma entry = (rel->r_offset - hstart) >> log_file_align;
- if (h->vtable_entries_used[entry])
- continue;
- }
- /* Otherwise, kill it. */
- rel->r_offset = rel->r_info = rel->r_addend = 0;
- }
-
- return TRUE;
-}
-
-/* Do mark and sweep of unused sections. */
-
-bfd_boolean
-elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
-{
- bfd_boolean ok = TRUE;
- bfd *sub;
- asection * (*gc_mark_hook)
- (asection *, struct bfd_link_info *, Elf_Internal_Rela *,
- struct elf_link_hash_entry *h, Elf_Internal_Sym *);
-
- if (!get_elf_backend_data (abfd)->can_gc_sections
- || info->relocatable
- || info->emitrelocations
- || !is_elf_hash_table (info->hash)
- || elf_hash_table (info)->dynamic_sections_created)
- {
- (*_bfd_error_handler)(_("Warning: gc-sections option ignored"));
- return TRUE;
- }
-
- /* Apply transitive closure to the vtable entry usage info. */
- elf_link_hash_traverse (elf_hash_table (info),
- elf_gc_propagate_vtable_entries_used,
- &ok);
- if (!ok)
- return FALSE;
-
- /* Kill the vtable relocations that were not used. */
- elf_link_hash_traverse (elf_hash_table (info),
- elf_gc_smash_unused_vtentry_relocs,
- &ok);
- if (!ok)
- return FALSE;
-
- /* Grovel through relocs to find out who stays ... */
-
- gc_mark_hook = get_elf_backend_data (abfd)->gc_mark_hook;
- for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
- {
- asection *o;
-
- if (bfd_get_flavour (sub) != bfd_target_elf_flavour)
- continue;
-
- for (o = sub->sections; o != NULL; o = o->next)
- {
- if (o->flags & SEC_KEEP)
- if (!elf_gc_mark (info, o, gc_mark_hook))
- return FALSE;
- }
- }
-
- /* ... and mark SEC_EXCLUDE for those that go. */
- if (!elf_gc_sweep (info, get_elf_backend_data (abfd)->gc_sweep_hook))
- return FALSE;
-
- return TRUE;
-}
-\f
-/* Called from check_relocs to record the existence of a VTINHERIT reloc. */
-
-bfd_boolean
-elf_gc_record_vtinherit (bfd *abfd,
- asection *sec,
- struct elf_link_hash_entry *h,
- bfd_vma offset)
-{
- struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
- struct elf_link_hash_entry **search, *child;
- bfd_size_type extsymcount;
-
- /* The sh_info field of the symtab header tells us where the
- external symbols start. We don't care about the local symbols at
- this point. */
- extsymcount = elf_tdata (abfd)->symtab_hdr.sh_size/sizeof (Elf_External_Sym);
- if (!elf_bad_symtab (abfd))
- extsymcount -= elf_tdata (abfd)->symtab_hdr.sh_info;
-
- sym_hashes = elf_sym_hashes (abfd);
- sym_hashes_end = sym_hashes + extsymcount;
-
- /* Hunt down the child symbol, which is in this section at the same
- offset as the relocation. */
- for (search = sym_hashes; search != sym_hashes_end; ++search)
- {
- if ((child = *search) != NULL
- && (child->root.type == bfd_link_hash_defined
- || child->root.type == bfd_link_hash_defweak)
- && child->root.u.def.section == sec
- && child->root.u.def.value == offset)
- goto win;
- }
-
- (*_bfd_error_handler) ("%s: %s+%lu: No symbol found for INHERIT",
- bfd_archive_filename (abfd), sec->name,
- (unsigned long) offset);
- bfd_set_error (bfd_error_invalid_operation);
- return FALSE;
-
- win:
- if (!h)
- {
- /* This *should* only be the absolute section. It could potentially
- be that someone has defined a non-global vtable though, which
- would be bad. It isn't worth paging in the local symbols to be
- sure though; that case should simply be handled by the assembler. */
-
- child->vtable_parent = (struct elf_link_hash_entry *) -1;
- }
- else
- child->vtable_parent = h;
-
- return TRUE;
-}
-
-/* Called from check_relocs to record the existence of a VTENTRY reloc. */
-
-bfd_boolean
-elf_gc_record_vtentry (bfd *abfd ATTRIBUTE_UNUSED,
- asection *sec ATTRIBUTE_UNUSED,
- struct elf_link_hash_entry *h,
- bfd_vma addend)
-{
- const struct elf_backend_data *bed = get_elf_backend_data (abfd);
- unsigned int log_file_align = bed->s->log_file_align;
-
- if (addend >= h->vtable_entries_size)
- {
- size_t size, bytes, file_align;
- bfd_boolean *ptr = h->vtable_entries_used;
-
- /* While the symbol is undefined, we have to be prepared to handle
- a zero size. */
- file_align = 1 << log_file_align;
- if (h->root.type == bfd_link_hash_undefined)
- size = addend + file_align;
- else
- {
- size = h->size;
- if (addend >= size)
- {
- /* Oops! We've got a reference past the defined end of
- the table. This is probably a bug -- shall we warn? */
- size = addend + file_align;
- }
- }
- size = (size + file_align - 1) & -file_align;
-
- /* Allocate one extra entry for use as a "done" flag for the
- consolidation pass. */
- bytes = ((size >> log_file_align) + 1) * sizeof (bfd_boolean);
-
- if (ptr)
- {
- ptr = bfd_realloc (ptr - 1, bytes);
-
- if (ptr != NULL)
- {
- size_t oldbytes;
-
- oldbytes = (((h->vtable_entries_size >> log_file_align) + 1)
- * sizeof (bfd_boolean));
- memset (((char *) ptr) + oldbytes, 0, bytes - oldbytes);
- }
- }
- else
- ptr = bfd_zmalloc (bytes);
-
- if (ptr == NULL)
- return FALSE;
-
- /* And arrange for that done flag to be at index -1. */
- h->vtable_entries_used = ptr + 1;
- h->vtable_entries_size = size;
- }
-
- h->vtable_entries_used[addend >> log_file_align] = TRUE;
-
- return TRUE;
-}
-
-/* And an accompanying bit to work out final got entry offsets once
- we're done. Should be called from final_link. */
-
-bfd_boolean
-elf_gc_common_finalize_got_offsets (bfd *abfd,
- struct bfd_link_info *info)
-{
- bfd *i;
- const struct elf_backend_data *bed = get_elf_backend_data (abfd);
- bfd_vma gotoff;
-
- if (! is_elf_hash_table (info->hash))
- return FALSE;
-
- /* The GOT offset is relative to the .got section, but the GOT header is
- put into the .got.plt section, if the backend uses it. */
- if (bed->want_got_plt)
- gotoff = 0;
- else
- gotoff = bed->got_header_size;
-
- /* Do the local .got entries first. */
- for (i = info->input_bfds; i; i = i->link_next)
- {
- bfd_signed_vma *local_got;
- bfd_size_type j, locsymcount;
- Elf_Internal_Shdr *symtab_hdr;
-
- if (bfd_get_flavour (i) != bfd_target_elf_flavour)
- continue;
-
- local_got = elf_local_got_refcounts (i);
- if (!local_got)
- continue;
-
- symtab_hdr = &elf_tdata (i)->symtab_hdr;
- if (elf_bad_symtab (i))
- locsymcount = symtab_hdr->sh_size / sizeof (Elf_External_Sym);
- else
- locsymcount = symtab_hdr->sh_info;
-
- for (j = 0; j < locsymcount; ++j)
- {
- if (local_got[j] > 0)
- {
- local_got[j] = gotoff;
- gotoff += ARCH_SIZE / 8;
- }
- else
- local_got[j] = (bfd_vma) -1;
- }
- }
-
- /* Then the global .got entries. .plt refcounts are handled by
- adjust_dynamic_symbol */
- elf_link_hash_traverse (elf_hash_table (info),
- elf_gc_allocate_got_offsets,
- &gotoff);
- return TRUE;
-}
-
-/* We need a special top-level link routine to convert got reference counts
- to real got offsets. */
-
-static bfd_boolean
-elf_gc_allocate_got_offsets (struct elf_link_hash_entry *h, void *offarg)
-{
- bfd_vma *off = offarg;
-
- if (h->root.type == bfd_link_hash_warning)
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
- if (h->got.refcount > 0)
- {
- h->got.offset = off[0];
- off[0] += ARCH_SIZE / 8;
- }
- else
- h->got.offset = (bfd_vma) -1;
-
- return TRUE;
-}
-
-/* Many folk need no more in the way of final link than this, once
- got entry reference counting is enabled. */
-
-bfd_boolean
-elf_gc_common_final_link (bfd *abfd, struct bfd_link_info *info)
-{
- if (!elf_gc_common_finalize_got_offsets (abfd, info))
- return FALSE;
-
- /* Invoke the regular ELF backend linker to do all the work. */
- return elf_bfd_final_link (abfd, info);
-}
-
-bfd_boolean
-elf_reloc_symbol_deleted_p (bfd_vma offset, void *cookie)
-{
- struct elf_reloc_cookie *rcookie = cookie;
-
- if (rcookie->bad_symtab)
- rcookie->rel = rcookie->rels;
-
- for (; rcookie->rel < rcookie->relend; rcookie->rel++)
- {
- unsigned long r_symndx;
-
- if (! rcookie->bad_symtab)
- if (rcookie->rel->r_offset > offset)
- return FALSE;
- if (rcookie->rel->r_offset != offset)
- continue;
-
- r_symndx = ELF_R_SYM (rcookie->rel->r_info);
- if (r_symndx == SHN_UNDEF)
- return TRUE;
-
- if (r_symndx >= rcookie->locsymcount
- || ELF_ST_BIND (rcookie->locsyms[r_symndx].st_info) != STB_LOCAL)
- {
- struct elf_link_hash_entry *h;
-
- h = rcookie->sym_hashes[r_symndx - rcookie->extsymoff];
-
- while (h->root.type == bfd_link_hash_indirect
- || h->root.type == bfd_link_hash_warning)
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
- if ((h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
- && elf_discarded_section (h->root.u.def.section))
- return TRUE;
- else
- return FALSE;
- }
- else
- {
- /* It's not a relocation against a global symbol,
- but it could be a relocation against a local
- symbol for a discarded section. */
- asection *isec;
- Elf_Internal_Sym *isym;
-
- /* Need to: get the symbol; get the section. */
- isym = &rcookie->locsyms[r_symndx];
- if (isym->st_shndx < SHN_LORESERVE || isym->st_shndx > SHN_HIRESERVE)
- {
- isec = section_from_elf_index (rcookie->abfd, isym->st_shndx);
- if (isec != NULL && elf_discarded_section (isec))
- return TRUE;
- }
- }
- return FALSE;
- }
- return FALSE;
-}
-
-/* Discard unneeded references to discarded sections.
- Returns TRUE if any section's size was changed. */
-/* This function assumes that the relocations are in sorted order,
- which is true for all known assemblers. */
-
-bfd_boolean
-elf_bfd_discard_info (bfd *output_bfd, struct bfd_link_info *info)
-{
- struct elf_reloc_cookie cookie;
- asection *stab, *eh;
- Elf_Internal_Shdr *symtab_hdr;
- const struct elf_backend_data *bed;
- bfd *abfd;
- unsigned int count;
- bfd_boolean ret = FALSE;
-
- if (info->traditional_format
- || !is_elf_hash_table (info->hash))
- return FALSE;
-
- for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link_next)
- {
- if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
- continue;
-
- bed = get_elf_backend_data (abfd);
-
- if ((abfd->flags & DYNAMIC) != 0)
- continue;
-
- eh = bfd_get_section_by_name (abfd, ".eh_frame");
- if (info->relocatable
- || (eh != NULL
- && (eh->_raw_size == 0
- || bfd_is_abs_section (eh->output_section))))
- eh = NULL;
-
- stab = bfd_get_section_by_name (abfd, ".stab");
- if (stab != NULL
- && (stab->_raw_size == 0
- || bfd_is_abs_section (stab->output_section)
- || stab->sec_info_type != ELF_INFO_TYPE_STABS))
- stab = NULL;
-
- if (stab == NULL
- && eh == NULL
- && bed->elf_backend_discard_info == NULL)
- continue;
-
- symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
- cookie.abfd = abfd;
- cookie.sym_hashes = elf_sym_hashes (abfd);
- cookie.bad_symtab = elf_bad_symtab (abfd);
- if (cookie.bad_symtab)
- {
- cookie.locsymcount = symtab_hdr->sh_size / sizeof (Elf_External_Sym);
- cookie.extsymoff = 0;
- }
- else
- {
- cookie.locsymcount = symtab_hdr->sh_info;
- cookie.extsymoff = symtab_hdr->sh_info;
- }
-
- cookie.locsyms = (Elf_Internal_Sym *) symtab_hdr->contents;
- if (cookie.locsyms == NULL && cookie.locsymcount != 0)
- {
- cookie.locsyms = bfd_elf_get_elf_syms (abfd, symtab_hdr,
- cookie.locsymcount, 0,
- NULL, NULL, NULL);
- if (cookie.locsyms == NULL)
- return FALSE;
- }
-
- if (stab != NULL)
- {
- cookie.rels = NULL;
- count = stab->reloc_count;
- if (count != 0)
- cookie.rels = _bfd_elf_link_read_relocs (abfd, stab, NULL, NULL,
- info->keep_memory);
- if (cookie.rels != NULL)
- {
- cookie.rel = cookie.rels;
- cookie.relend = cookie.rels;
- cookie.relend += count * bed->s->int_rels_per_ext_rel;
- if (_bfd_discard_section_stabs (abfd, stab,
- elf_section_data (stab)->sec_info,
- elf_reloc_symbol_deleted_p,
- &cookie))
- ret = TRUE;
- if (elf_section_data (stab)->relocs != cookie.rels)
- free (cookie.rels);
- }
- }
-
- if (eh != NULL)
- {
- cookie.rels = NULL;
- count = eh->reloc_count;
- if (count != 0)
- cookie.rels = _bfd_elf_link_read_relocs (abfd, eh, NULL, NULL,
- info->keep_memory);
- cookie.rel = cookie.rels;
- cookie.relend = cookie.rels;
- if (cookie.rels != NULL)
- cookie.relend += count * bed->s->int_rels_per_ext_rel;
-
- if (_bfd_elf_discard_section_eh_frame (abfd, info, eh,
- elf_reloc_symbol_deleted_p,
- &cookie))
- ret = TRUE;
-
- if (cookie.rels != NULL
- && elf_section_data (eh)->relocs != cookie.rels)
- free (cookie.rels);
- }
-
- if (bed->elf_backend_discard_info != NULL
- && (*bed->elf_backend_discard_info) (abfd, &cookie, info))
- ret = TRUE;
-
- if (cookie.locsyms != NULL
- && symtab_hdr->contents != (unsigned char *) cookie.locsyms)
- {
- if (! info->keep_memory)
- free (cookie.locsyms);
- else
- symtab_hdr->contents = (unsigned char *) cookie.locsyms;
- }
- }
-
- if (info->eh_frame_hdr
- && !info->relocatable
- && _bfd_elf_discard_section_eh_frame_hdr (output_bfd, info))
- ret = TRUE;
-
- return ret;
-}
-
-static bfd_boolean
-elf_section_ignore_discarded_relocs (asection *sec)
-{
- const struct elf_backend_data *bed;
-
- switch (sec->sec_info_type)
- {
- case ELF_INFO_TYPE_STABS:
- case ELF_INFO_TYPE_EH_FRAME:
- return TRUE;
- default:
- break;
- }
-
- bed = get_elf_backend_data (sec->owner);
- if (bed->elf_backend_ignore_discarded_relocs != NULL
- && (*bed->elf_backend_ignore_discarded_relocs) (sec))
- return TRUE;
-
- return FALSE;
-}
dynamic symbol table. */
if (!h && info->shared)
{
- if (! (_bfd_elfNN_link_record_local_dynamic_symbol
+ if (! (bfd_elf_link_record_local_dynamic_symbol
(info, abfd, (long) r_symndx)))
return FALSE;
}
BFD_ASSERT ((h->root.type == bfd_link_hash_defined)
|| (h->root.type == bfd_link_hash_defweak));
- if (!_bfd_elfNN_link_record_local_dynamic_symbol
+ if (!bfd_elf_link_record_local_dynamic_symbol
(x->info, h->root.u.def.section->owner,
global_sym_index (h)))
return FALSE;
}
/* Invoke the regular ELF backend linker to do all the work. */
- if (!bfd_elfNN_bfd_final_link (abfd, info))
+ if (!bfd_elf_final_link (abfd, info))
return FALSE;
if (unwind_output_sec)
/* Mark the symbol as undefined, rather than as defined in the
plt section. Leave the value alone. */
/* ??? We didn't redefine it in adjust_dynamic_symbol in the
- first place. But perhaps elflink.h did some for us. */
+ first place. But perhaps elflink.c did some for us. */
if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
sym->st_shndx = SHN_UNDEF;
}
_bfd_mips_elf_hide_symbol (info, h, TRUE);
break;
}
- if (!bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (!bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
h->type = STT_OBJECT;
if (info->shared
- && ! bfd_elf32_link_record_dynamic_symbol (info, h))
+ && ! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
amt = sizeof (struct mips_got_info);
h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
h->type = STT_OBJECT;
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
mips_elf_hash_table (info)->use_rld_obj_head = TRUE;
h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
h->type = STT_SECTION;
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
h->type = STT_SECTION;
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
if (! mips_elf_hash_table (info)->use_rld_obj_head)
h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
h->type = STT_OBJECT;
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
}
/* We need a stub, not a plt entry for the undefined
function. But we record it as if it needs plt. See
- elf_adjust_dynamic_symbol in elflink.h. */
+ _bfd_elf_adjust_dynamic_symbol. */
h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
h->type = STT_FUNC;
}
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_MIPS_GNU_VTINHERIT:
- if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
return FALSE;
break;
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
case R_MIPS_GNU_VTENTRY:
- if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
return FALSE;
break;
for (i = 0, skip = 0; i < o->_raw_size / PDR_SIZE; i ++)
{
- if (MNAME(abfd,_bfd_elf,reloc_symbol_deleted_p) (i * PDR_SIZE, cookie))
+ if (bfd_elf_reloc_symbol_deleted_p (i * PDR_SIZE, cookie))
{
tdata[i] = 1;
skip ++;
}
/* Invoke the regular ELF backend linker to do all the work. */
- if (!MNAME(abfd,bfd_elf,bfd_final_link) (abfd, info))
+ if (!bfd_elf_final_link (abfd, info))
return FALSE;
/* Now write out the computed sections. */
#define elf_backend_gc_sweep_hook NULL
#endif
#ifndef bfd_elfNN_bfd_gc_sections
-#define bfd_elfNN_bfd_gc_sections _bfd_elfNN_gc_sections
+#define bfd_elfNN_bfd_gc_sections bfd_elf_gc_sections
#endif
#ifndef bfd_elfNN_bfd_merge_sections
#ifndef bfd_elfNN_bfd_link_add_symbols
#define bfd_elfNN_bfd_link_add_symbols bfd_elf_link_add_symbols
#endif
+#ifndef bfd_elfNN_bfd_final_link
+#define bfd_elfNN_bfd_final_link bfd_elf_final_link
+#endif
#else /* ! defined (elf_backend_relocate_section) */
/* If no backend relocate_section routine, use the generic linker.
Note - this will prevent the port from being able to use some of
#define bfd_elfNN_mkarchive _bfd_generic_mkarchive
#endif
+#ifndef bfd_elfNN_print_symbol
+#define bfd_elfNN_print_symbol bfd_elf_print_symbol
+#endif
+
#ifndef elf_symbol_leading_char
#define elf_symbol_leading_char 0
#endif
"BFD_RELOC_M68HC11_PAGE",
"BFD_RELOC_M68HC11_24",
"BFD_RELOC_M68HC12_5B",
+ "BFD_RELOC_16C_NUM08",
+ "BFD_RELOC_16C_NUM08_C",
+ "BFD_RELOC_16C_NUM16",
+ "BFD_RELOC_16C_NUM16_C",
+ "BFD_RELOC_16C_NUM32",
+ "BFD_RELOC_16C_NUM32_C",
+ "BFD_RELOC_16C_DISP04",
+ "BFD_RELOC_16C_DISP04_C",
+ "BFD_RELOC_16C_DISP08",
+ "BFD_RELOC_16C_DISP08_C",
+ "BFD_RELOC_16C_DISP16",
+ "BFD_RELOC_16C_DISP16_C",
+ "BFD_RELOC_16C_DISP24",
+ "BFD_RELOC_16C_DISP24_C",
+ "BFD_RELOC_16C_DISP24a",
+ "BFD_RELOC_16C_DISP24a_C",
+ "BFD_RELOC_16C_REG04",
+ "BFD_RELOC_16C_REG04_C",
+ "BFD_RELOC_16C_REG04a",
+ "BFD_RELOC_16C_REG04a_C",
+ "BFD_RELOC_16C_REG14",
+ "BFD_RELOC_16C_REG14_C",
+ "BFD_RELOC_16C_REG16",
+ "BFD_RELOC_16C_REG16_C",
+ "BFD_RELOC_16C_REG20",
+ "BFD_RELOC_16C_REG20_C",
+ "BFD_RELOC_16C_ABS20",
+ "BFD_RELOC_16C_ABS20_C",
+ "BFD_RELOC_16C_ABS24",
+ "BFD_RELOC_16C_ABS24_C",
+ "BFD_RELOC_16C_IMM04",
+ "BFD_RELOC_16C_IMM04_C",
+ "BFD_RELOC_16C_IMM16",
+ "BFD_RELOC_16C_IMM16_C",
+ "BFD_RELOC_16C_IMM20",
+ "BFD_RELOC_16C_IMM20_C",
+ "BFD_RELOC_16C_IMM24",
+ "BFD_RELOC_16C_IMM24_C",
+ "BFD_RELOC_16C_IMM32",
+ "BFD_RELOC_16C_IMM32_C",
"BFD_RELOC_CRIS_BDISP8",
"BFD_RELOC_CRIS_UNSIGNED_5",
"BFD_RELOC_CRIS_SIGNED_6",
elf-eh-frame.c
elf-hppa.h
elflink.c
-elflink.h
elf-m10200.c
elf-m10300.c
elfn32-mips.c
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2004-03-19 14:59+1030\n"
+"POT-Creation-Date: 2004-03-27 15:34+1030\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
msgid "ERROR: %s is compiled for APCS-%d, whereas %s is compiled for APCS-%d"
msgstr ""
-#: coff-arm.c:2289 elf32-arm.h:2494
+#: coff-arm.c:2289 elf32-arm.h:2482
#, c-format
msgid ""
"ERROR: %s passes floats in float registers, whereas %s passes them in "
"integer registers"
msgstr ""
-#: coff-arm.c:2292 elf32-arm.h:2499
+#: coff-arm.c:2292 elf32-arm.h:2487
#, c-format
msgid ""
"ERROR: %s passes floats in integer registers, whereas %s passes them in "
"position independent"
msgstr ""
-#: coff-arm.c:2339 elf32-arm.h:2571
+#: coff-arm.c:2339 elf32-arm.h:2559
#, c-format
msgid "Warning: %s supports interworking, whereas %s does not"
msgstr ""
-#: coff-arm.c:2342 elf32-arm.h:2578
+#: coff-arm.c:2342 elf32-arm.h:2566
#, c-format
msgid "Warning: %s does not support interworking, whereas %s does"
msgstr ""
msgid "private flags = %x:"
msgstr ""
-#: coff-arm.c:2377 elf32-arm.h:2633
+#: coff-arm.c:2377 elf32-arm.h:2621
#, c-format
msgid " [floats passed in float registers]"
msgstr ""
msgid " [floats passed in integer registers]"
msgstr ""
-#: coff-arm.c:2382 elf32-arm.h:2636
+#: coff-arm.c:2382 elf32-arm.h:2624
#, c-format
msgid " [position independent]"
msgstr ""
msgid " [interworking not supported]"
msgstr ""
-#: coff-arm.c:2440 elf32-arm.h:2298
+#: coff-arm.c:2440 elf32-arm.h:2286
#, c-format
msgid ""
"Warning: Not setting interworking flag of %s since it has already been "
"specified as non-interworking"
msgstr ""
-#: coff-arm.c:2444 elf32-arm.h:2302
+#: coff-arm.c:2444 elf32-arm.h:2290
#, c-format
msgid "Warning: Clearing the interworking flag of %s due to outside request"
msgstr ""
msgid "uncertain calling convention for non-COFF symbol"
msgstr ""
-#: cofflink.c:506 elflink.h:945
+#: cofflink.c:506 elflink.c:3665
#, c-format
msgid "Warning: type of symbol `%s' changed from %d to %d in %s"
msgstr ""
msgid "%s: warning: %s: line number overflow: 0x%lx > 0xffff"
msgstr ""
-#: coff-m68k.c:482 coff-mips.c:2394 elf32-m68k.c:2153 elf32-mips.c:1405
+#: coff-m68k.c:482 coff-mips.c:2394 elf32-m68k.c:2145 elf32-mips.c:1405
msgid "unsupported reloc type"
msgstr ""
" Type: %s"
msgstr ""
-#: elf32-arm.h:1428
+#: elf32-arm.h:1416
#, c-format
msgid "%s: Warning: Arm BLX instruction targets Arm function '%s'."
msgstr ""
-#: elf32-arm.h:1624
+#: elf32-arm.h:1612
#, c-format
msgid "%s: Warning: Thumb BLX instruction targets thumb function '%s'."
msgstr ""
-#: elf32-arm.h:2092 elf32-sh.c:4819 elf64-sh64.c:1596
+#: elf32-arm.h:2080 elf32-sh.c:4808 elf64-sh64.c:1596
#, c-format
msgid "%s(%s+0x%lx): %s relocation against SEC_MERGE section"
msgstr ""
-#: elf32-arm.h:2184
+#: elf32-arm.h:2172
#, c-format
msgid ""
"%s: warning: unresolvable relocation %d against symbol `%s' from %s section"
msgstr ""
-#: elf32-arm.h:2236 elf32-avr.c:812 elf32-cris.c:1352 elf32-d10v.c:579
-#: elf32-fr30.c:634 elf32-frv.c:2499 elf32-h8300.c:509 elf32-i860.c:1218
-#: elf32-ip2k.c:1565 elf32-iq2000.c:665 elf32-m32r.c:3202 elf32-m68hc1x.c:1214
-#: elf32-msp430.c:510 elf32-openrisc.c:436 elf32-v850.c:1777
-#: elf32-xstormy16.c:976 elf64-mmix.c:1545 elf-m10200.c:442 elf-m10300.c:1677
+#: elf32-arm.h:2224 elf32-avr.c:791 elf32-cris.c:1376 elf32-d10v.c:563
+#: elf32-fr30.c:599 elf32-frv.c:2499 elf32-h8300.c:493 elf32-i860.c:1196
+#: elf32-ip2k.c:1568 elf32-iq2000.c:666 elf32-m32r.c:3191 elf32-m68hc1x.c:1190
+#: elf32-msp430.c:489 elf32-openrisc.c:415 elf32-v850.c:1746
+#: elf32-xstormy16.c:954 elf64-mmix.c:1518 elf-m10200.c:426 elf-m10300.c:1676
msgid "internal error: out of range error"
msgstr ""
-#: elf32-arm.h:2240 elf32-avr.c:816 elf32-cris.c:1356 elf32-d10v.c:583
-#: elf32-fr30.c:638 elf32-frv.c:2503 elf32-h8300.c:513 elf32-i860.c:1222
-#: elf32-iq2000.c:669 elf32-m32r.c:3206 elf32-m68hc1x.c:1218
-#: elf32-msp430.c:514 elf32-openrisc.c:440 elf32-v850.c:1781
-#: elf32-xstormy16.c:980 elf64-mmix.c:1549 elf-m10200.c:446 elf-m10300.c:1681
-#: elfxx-mips.c:6470
+#: elf32-arm.h:2228 elf32-avr.c:795 elf32-cris.c:1380 elf32-d10v.c:567
+#: elf32-fr30.c:603 elf32-frv.c:2503 elf32-h8300.c:497 elf32-i860.c:1200
+#: elf32-iq2000.c:670 elf32-m32r.c:3195 elf32-m68hc1x.c:1194
+#: elf32-msp430.c:493 elf32-openrisc.c:419 elf32-v850.c:1750
+#: elf32-xstormy16.c:958 elf64-mmix.c:1522 elf-m10200.c:430 elf-m10300.c:1680
+#: elfxx-mips.c:6459
msgid "internal error: unsupported relocation error"
msgstr ""
-#: elf32-arm.h:2244 elf32-d10v.c:587 elf32-h8300.c:517 elf32-m32r.c:3210
-#: elf32-m68hc1x.c:1222 elf-m10200.c:450 elf-m10300.c:1685
+#: elf32-arm.h:2232 elf32-d10v.c:571 elf32-h8300.c:501 elf32-m32r.c:3199
+#: elf32-m68hc1x.c:1198 elf-m10200.c:434 elf-m10300.c:1684
msgid "internal error: dangerous error"
msgstr ""
-#: elf32-arm.h:2248 elf32-avr.c:824 elf32-cris.c:1364 elf32-d10v.c:591
-#: elf32-fr30.c:646 elf32-frv.c:2511 elf32-h8300.c:521 elf32-i860.c:1230
-#: elf32-ip2k.c:1580 elf32-iq2000.c:677 elf32-m32r.c:3214 elf32-m68hc1x.c:1226
-#: elf32-msp430.c:522 elf32-openrisc.c:448 elf32-v850.c:1801
-#: elf32-xstormy16.c:988 elf64-mmix.c:1557 elf-m10200.c:454 elf-m10300.c:1689
+#: elf32-arm.h:2236 elf32-avr.c:803 elf32-cris.c:1388 elf32-d10v.c:575
+#: elf32-fr30.c:611 elf32-frv.c:2511 elf32-h8300.c:505 elf32-i860.c:1208
+#: elf32-ip2k.c:1583 elf32-iq2000.c:678 elf32-m32r.c:3203 elf32-m68hc1x.c:1202
+#: elf32-msp430.c:501 elf32-openrisc.c:427 elf32-v850.c:1770
+#: elf32-xstormy16.c:966 elf64-mmix.c:1530 elf-m10200.c:438 elf-m10300.c:1688
msgid "internal error: unknown error"
msgstr ""
-#: elf32-arm.h:2350
+#: elf32-arm.h:2338
#, c-format
msgid ""
"Warning: Clearing the interworking flag of %s because non-interworking code "
"in %s has been linked with it"
msgstr ""
-#: elf32-arm.h:2468
+#: elf32-arm.h:2456
#, c-format
msgid ""
"ERROR: %s is compiled for EABI version %d, whereas %s is compiled for "
"version %d"
msgstr ""
-#: elf32-arm.h:2482
+#: elf32-arm.h:2470
#, c-format
msgid "ERROR: %s is compiled for APCS-%d, whereas target %s uses APCS-%d"
msgstr ""
-#: elf32-arm.h:2510
+#: elf32-arm.h:2498
#, c-format
msgid "ERROR: %s uses VFP instructions, whereas %s does not"
msgstr ""
-#: elf32-arm.h:2515
+#: elf32-arm.h:2503
#, c-format
msgid "ERROR: %s uses FPA instructions, whereas %s does not"
msgstr ""
-#: elf32-arm.h:2526
+#: elf32-arm.h:2514
#, c-format
msgid "ERROR: %s uses Maverick instructions, whereas %s does not"
msgstr ""
-#: elf32-arm.h:2531
+#: elf32-arm.h:2519
#, c-format
msgid "ERROR: %s does not use Maverick instructions, whereas %s does"
msgstr ""
-#: elf32-arm.h:2551
+#: elf32-arm.h:2539
#, c-format
msgid "ERROR: %s uses software FP, whereas %s uses hardware FP"
msgstr ""
-#: elf32-arm.h:2556
+#: elf32-arm.h:2544
#, c-format
msgid "ERROR: %s uses hardware FP, whereas %s uses software FP"
msgstr ""
#. Ignore init flag - it may not be set, despite the flags field
#. containing valid data.
#. Ignore init flag - it may not be set, despite the flags field containing valid data.
-#: elf32-arm.h:2609 elf32-cris.c:2938 elf32-m68hc1x.c:1362 elf32-m68k.c:397
-#: elf32-vax.c:546 elfxx-mips.c:9179
+#: elf32-arm.h:2597 elf32-cris.c:2980 elf32-m68hc1x.c:1338 elf32-m68k.c:397
+#: elf32-vax.c:546 elfxx-mips.c:9168
#, c-format
msgid "private flags = %lx:"
msgstr ""
-#: elf32-arm.h:2618
+#: elf32-arm.h:2606
#, c-format
msgid " [interworking enabled]"
msgstr ""
-#: elf32-arm.h:2626
+#: elf32-arm.h:2614
#, c-format
msgid " [VFP float format]"
msgstr ""
-#: elf32-arm.h:2628
+#: elf32-arm.h:2616
#, c-format
msgid " [Maverick float format]"
msgstr ""
-#: elf32-arm.h:2630
+#: elf32-arm.h:2618
#, c-format
msgid " [FPA float format]"
msgstr ""
-#: elf32-arm.h:2639
+#: elf32-arm.h:2627
#, c-format
msgid " [new ABI]"
msgstr ""
-#: elf32-arm.h:2642
+#: elf32-arm.h:2630
#, c-format
msgid " [old ABI]"
msgstr ""
-#: elf32-arm.h:2645
+#: elf32-arm.h:2633
#, c-format
msgid " [software FP]"
msgstr ""
-#: elf32-arm.h:2654
+#: elf32-arm.h:2642
#, c-format
msgid " [Version1 EABI]"
msgstr ""
-#: elf32-arm.h:2657 elf32-arm.h:2668
+#: elf32-arm.h:2645 elf32-arm.h:2656
#, c-format
msgid " [sorted symbol table]"
msgstr ""
-#: elf32-arm.h:2659 elf32-arm.h:2670
+#: elf32-arm.h:2647 elf32-arm.h:2658
#, c-format
msgid " [unsorted symbol table]"
msgstr ""
-#: elf32-arm.h:2665
+#: elf32-arm.h:2653
#, c-format
msgid " [Version2 EABI]"
msgstr ""
-#: elf32-arm.h:2673
+#: elf32-arm.h:2661
#, c-format
msgid " [dynamic symbols use segment index]"
msgstr ""
-#: elf32-arm.h:2676
+#: elf32-arm.h:2664
#, c-format
msgid " [mapping symbols precede others]"
msgstr ""
+#: elf32-arm.h:2671
+#, c-format
+msgid " [Version3 EABI]"
+msgstr ""
+
+#: elf32-arm.h:2674
+#, c-format
+msgid " [BE8]"
+msgstr ""
+
+#: elf32-arm.h:2677
+#, c-format
+msgid " [LE8]"
+msgstr ""
+
#: elf32-arm.h:2683
#, c-format
msgid " <EABI version unrecognised>"
msgid "<Unrecognised flag bits set>"
msgstr ""
-#: elf32-avr.c:820 elf32-cris.c:1360 elf32-fr30.c:642 elf32-frv.c:2507
-#: elf32-i860.c:1226 elf32-ip2k.c:1576 elf32-iq2000.c:673 elf32-msp430.c:518
-#: elf32-openrisc.c:444 elf32-v850.c:1785 elf32-xstormy16.c:984
-#: elf64-mmix.c:1553
+#: elf32-avr.c:799 elf32-cris.c:1384 elf32-fr30.c:607 elf32-frv.c:2507
+#: elf32-i860.c:1204 elf32-ip2k.c:1579 elf32-iq2000.c:674 elf32-msp430.c:497
+#: elf32-openrisc.c:423 elf32-v850.c:1754 elf32-xstormy16.c:962
+#: elf64-mmix.c:1526
msgid "internal error: dangerous relocation"
msgstr ""
-#: elf32-cris.c:918
+#: elf32-cris.c:921
#, c-format
msgid "%s: unresolvable relocation %s against symbol `%s' from %s section"
msgstr ""
-#: elf32-cris.c:964
+#: elf32-cris.c:978
#, c-format
msgid ""
"%s: No PLT nor GOT for relocation %s against symbol `%s' from %s section"
msgstr ""
-#: elf32-cris.c:967 elf32-cris.c:1093
+#: elf32-cris.c:980
+#, c-format
+msgid "%s: No PLT for relocation %s against symbol `%s' from %s section"
+msgstr ""
+
+#: elf32-cris.c:984 elf32-cris.c:1117
msgid "[whose name is lost]"
msgstr ""
-#: elf32-cris.c:1082
+#: elf32-cris.c:1106
#, c-format
msgid ""
"%s: relocation %s with non-zero addend %d against local symbol from %s "
"section"
msgstr ""
-#: elf32-cris.c:1089
+#: elf32-cris.c:1113
#, c-format
msgid ""
"%s: relocation %s with non-zero addend %d against symbol `%s' from %s section"
msgstr ""
-#: elf32-cris.c:1114
+#: elf32-cris.c:1138
#, c-format
msgid ""
"%s: relocation %s is not allowed for global symbol: `%s' from %s section"
msgstr ""
-#: elf32-cris.c:1129
+#: elf32-cris.c:1153
#, c-format
msgid "%s: relocation %s in section %s with no GOT created"
msgstr ""
-#: elf32-cris.c:1248
+#: elf32-cris.c:1272
#, c-format
msgid "%s: Internal inconsistency; no relocation section %s"
msgstr ""
-#: elf32-cris.c:2463
+#: elf32-cris.c:2502
#, c-format
msgid ""
"%s, section %s:\n"
" relocation %s should not be used in a shared object; recompile with -fPIC"
msgstr ""
-#: elf32-cris.c:2941
+#: elf32-cris.c:2983
#, c-format
msgid " [symbols have a _ prefix]"
msgstr ""
-#: elf32-cris.c:2980
+#: elf32-cris.c:3022
#, c-format
msgid "%s: uses _-prefixed symbols, but writing file with non-prefixed symbols"
msgstr ""
-#: elf32-cris.c:2981
+#: elf32-cris.c:3023
#, c-format
msgid "%s: uses non-prefixed symbols, but writing file with _-prefixed symbols"
msgstr ""
"%s: compiled with %s and linked with modules that use non-pic relocations"
msgstr ""
-#: elf32-frv.c:4443 elf32-iq2000.c:861
+#: elf32-frv.c:4443 elf32-iq2000.c:862
#, c-format
msgid "%s: compiled with %s and linked with modules compiled with %s"
msgstr ""
"lx)"
msgstr ""
-#: elf32-frv.c:4491 elf32-iq2000.c:899
+#: elf32-frv.c:4491 elf32-iq2000.c:900
#, c-format
msgid "private flags = 0x%lx:"
msgstr ""
-#: elf32-gen.c:83 elf64-gen.c:82
+#: elf32-gen.c:83 elf64-gen.c:83
#, c-format
msgid "%s: Relocations in generic ELF (EM: %d)"
msgstr ""
-#: elf32-hppa.c:542 elf32-m68hc1x.c:170 elf64-ppc.c:3186
+#: elf32-hppa.c:542 elf32-m68hc1x.c:161 elf64-ppc.c:3188
#, c-format
msgid "%s: cannot create stub entry %s"
msgstr ""
-#: elf32-hppa.c:795 elf32-hppa.c:3326
+#: elf32-hppa.c:795 elf32-hppa.c:3315
#, c-format
msgid "%s(%s+0x%lx): cannot reach %s, recompile with -ffunction-sections"
msgstr ""
-#: elf32-hppa.c:1166 elf64-x86-64.c:665 elf64-x86-64.c:790
+#: elf32-hppa.c:1167 elf64-x86-64.c:665 elf64-x86-64.c:790
#, c-format
msgid ""
"%s: relocation %s can not be used when making a shared object; recompile "
"with -fPIC"
msgstr ""
-#: elf32-hppa.c:1186
+#: elf32-hppa.c:1187
#, c-format
msgid ""
"%s: relocation %s should not be used when making a shared object; recompile "
"with -fPIC"
msgstr ""
-#: elf32-hppa.c:1378
+#: elf32-hppa.c:1377
#, c-format
msgid "Could not find relocation section for %s"
msgstr ""
-#: elf32-hppa.c:2584
+#: elf32-hppa.c:2572
#, c-format
msgid "%s: duplicate export stub %s"
msgstr ""
-#: elf32-hppa.c:3174
+#: elf32-hppa.c:3162
#, c-format
msgid ""
"%s(%s+0x%lx): %s fixup for insn 0x%x is not supported in a non-shared link"
msgstr ""
-#: elf32-hppa.c:3204
+#: elf32-hppa.c:3192
#, c-format
msgid "%s(%s+0x%lx): fixing %s"
msgstr ""
-#: elf32-hppa.c:3820
+#: elf32-hppa.c:3810
#, c-format
msgid "%s(%s+0x%lx): cannot handle %s for %s"
msgstr ""
-#: elf32-hppa.c:4113
+#: elf32-hppa.c:4103
msgid ".got section not immediately after .plt section"
msgstr ""
msgid "%s: invalid relocation type %d"
msgstr ""
-#: elf32-i386.c:864 elf32-s390.c:983 elf32-sparc.c:916 elf32-xtensa.c:648
+#: elf32-i386.c:864 elf32-s390.c:983 elf32-sparc.c:916 elf32-xtensa.c:641
#: elf64-s390.c:936 elf64-x86-64.c:643
#, c-format
msgid "%s: bad symbol index: %d"
msgstr ""
-#: elf32-i386.c:972 elf32-s390.c:1161 elf32-sh.c:6603 elf32-sparc.c:1040
+#: elf32-i386.c:972 elf32-s390.c:1161 elf32-sh.c:6590 elf32-sparc.c:1040
#: elf64-s390.c:1122
#, c-format
msgid "%s: `%s' accessed both as normal and thread local symbol"
msgstr ""
-#: elf32-i386.c:1089 elf32-s390.c:1272 elf64-ppc.c:4018 elf64-s390.c:1236
+#: elf32-i386.c:1089 elf32-s390.c:1272 elf64-ppc.c:4036 elf64-s390.c:1236
#: elf64-x86-64.c:879
#, c-format
msgid "%s: bad relocation section name `%s'"
msgstr ""
-#: elf32-i386.c:2897 elf32-m68k.c:1717 elf32-s390.c:3007 elf32-sparc.c:2868
-#: elf32-xtensa.c:2119 elf64-s390.c:3003 elf64-sparc.c:2631
-#: elf64-x86-64.c:2400
+#: elf32-i386.c:2889 elf32-m68k.c:1709 elf32-s390.c:2996 elf32-sparc.c:2857
+#: elf32-xtensa.c:2106 elf64-s390.c:2992 elf64-sparc.c:2620
+#: elf64-x86-64.c:2389
#, c-format
msgid "%s(%s+0x%lx): unresolvable relocation against symbol `%s'"
msgstr ""
-#: elf32-i386.c:2936 elf32-m68k.c:1756 elf32-s390.c:3057 elf64-s390.c:3053
-#: elf64-x86-64.c:2438
+#: elf32-i386.c:2928 elf32-m68k.c:1748 elf32-s390.c:3046 elf64-s390.c:3042
+#: elf64-x86-64.c:2427
#, c-format
msgid "%s(%s+0x%lx): reloc against `%s': error %d"
msgstr ""
msgstr ""
#. Only if it's not an unresolved symbol.
-#: elf32-ip2k.c:1572
+#: elf32-ip2k.c:1575
msgid "unsupported relocation between data/insn address spaces"
msgstr ""
-#: elf32-iq2000.c:873 elf32-m68hc1x.c:1336 elf32-ppc.c:2293 elf64-sparc.c:3039
-#: elfxx-mips.c:9140
+#: elf32-iq2000.c:874 elf32-m68hc1x.c:1312 elf32-ppc.c:2293 elf64-sparc.c:3028
+#: elfxx-mips.c:9129
#, c-format
msgid "%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"
msgstr ""
msgid "SDA relocation when _SDA_BASE_ not defined"
msgstr ""
-#: elf32-m32r.c:2575 elf64-alpha.c:4199 elf64-alpha.c:4325 elf32-ia64.c:3920
-#: elf64-ia64.c:3920
+#: elf32-m32r.c:2564 elf64-alpha.c:4199 elf64-alpha.c:4325 elf32-ia64.c:3921
+#: elf64-ia64.c:3921
#, c-format
msgid "%s: unknown relocation type %d"
msgstr ""
-#: elf32-m32r.c:2763 elf64-sh64.c:1689 elf-hppa.h:1387 elf-hppa.h:1421
-#: elf-hppa.h:1437 elf-m10300.c:1632
+#: elf32-m32r.c:2753 elf64-sh64.c:1689 elf-hppa.h:1406 elf-hppa.h:1433
+#: elf-hppa.h:1449 elf-m10300.c:1631
#, c-format
msgid ""
"%s: warning: unresolvable relocation against symbol `%s' from %s section"
msgstr ""
-#: elf32-m32r.c:3139
+#: elf32-m32r.c:3128
#, c-format
msgid "%s: The target (%s) of an %s relocation is in the wrong section (%s)"
msgstr ""
-#: elf32-m32r.c:4222
+#: elf32-m32r.c:4211
#, c-format
msgid "%s: Instruction set mismatch with previous modules"
msgstr ""
-#: elf32-m32r.c:4245
+#: elf32-m32r.c:4234
#, c-format
msgid "private flags = %lx"
msgstr ""
-#: elf32-m32r.c:4250
+#: elf32-m32r.c:4239
#, c-format
msgid ": m32r instructions"
msgstr ""
-#: elf32-m32r.c:4251
+#: elf32-m32r.c:4240
#, c-format
msgid ": m32rx instructions"
msgstr ""
-#: elf32-m32r.c:4252
+#: elf32-m32r.c:4241
#, c-format
msgid ": m32r2 instructions"
msgstr ""
-#: elf32-m68hc1x.c:1126
+#: elf32-m68hc1x.c:1102
#, c-format
msgid ""
"Reference to the far symbol `%s' using a wrong relocation may result in "
"incorrect execution"
msgstr ""
-#: elf32-m68hc1x.c:1149
+#: elf32-m68hc1x.c:1125
#, c-format
msgid ""
"banked address [%lx:%04lx] (%lx) is not in the same bank as current banked "
"address [%lx:%04lx] (%lx)"
msgstr ""
-#: elf32-m68hc1x.c:1168
+#: elf32-m68hc1x.c:1144
#, c-format
msgid ""
"reference to a banked address [%lx:%04lx] in the normal address space at %"
"04lx"
msgstr ""
-#: elf32-m68hc1x.c:1301
+#: elf32-m68hc1x.c:1277
#, c-format
msgid ""
"%s: linking files compiled for 16-bit integers (-mshort) and others for 32-"
"bit integers"
msgstr ""
-#: elf32-m68hc1x.c:1309
+#: elf32-m68hc1x.c:1285
#, c-format
msgid ""
"%s: linking files compiled for 32-bit double (-fshort-double) and others for "
"64-bit double"
msgstr ""
-#: elf32-m68hc1x.c:1319
+#: elf32-m68hc1x.c:1295
#, c-format
msgid "%s: linking files compiled for HCS12 with others compiled for HC12"
msgstr ""
-#: elf32-m68hc1x.c:1365
+#: elf32-m68hc1x.c:1341
#, c-format
msgid "[abi=32-bit int, "
msgstr ""
-#: elf32-m68hc1x.c:1367
+#: elf32-m68hc1x.c:1343
#, c-format
msgid "[abi=16-bit int, "
msgstr ""
-#: elf32-m68hc1x.c:1370
+#: elf32-m68hc1x.c:1346
#, c-format
msgid "64-bit double, "
msgstr ""
-#: elf32-m68hc1x.c:1372
+#: elf32-m68hc1x.c:1348
#, c-format
msgid "32-bit double, "
msgstr ""
-#: elf32-m68hc1x.c:1375
+#: elf32-m68hc1x.c:1351
#, c-format
msgid "cpu=HC11]"
msgstr ""
-#: elf32-m68hc1x.c:1377
+#: elf32-m68hc1x.c:1353
#, c-format
msgid "cpu=HCS12]"
msgstr ""
-#: elf32-m68hc1x.c:1379
+#: elf32-m68hc1x.c:1355
#, c-format
msgid "cpu=HC12]"
msgstr ""
-#: elf32-m68hc1x.c:1382
+#: elf32-m68hc1x.c:1358
#, c-format
msgid " [memory=bank-model]"
msgstr ""
-#: elf32-m68hc1x.c:1384
+#: elf32-m68hc1x.c:1360
#, c-format
msgid " [memory=flat]"
msgstr ""
"%s: compiled normally and linked with modules compiled with -mrelocatable"
msgstr ""
-#: elf32-ppc.c:3545
+#: elf32-ppc.c:3534
#, c-format
msgid "%s: relocation %s cannot be used when making a shared object"
msgstr ""
-#: elf32-ppc.c:3751
+#: elf32-ppc.c:3740
#, c-format
msgid "%s(%s+0x%lx): %s reloc against local symbol"
msgstr ""
-#: elf32-ppc.c:4956 elf64-ppc.c:8015
+#: elf32-ppc.c:4945 elf64-ppc.c:8022
#, c-format
msgid "%s: unknown relocation type %d for symbol %s"
msgstr ""
-#: elf32-ppc.c:5207
+#: elf32-ppc.c:5196
#, c-format
msgid "%s(%s+0x%lx): non-zero addend on %s reloc against `%s'"
msgstr ""
-#: elf32-ppc.c:5518 elf32-ppc.c:5544 elf32-ppc.c:5603
+#: elf32-ppc.c:5507 elf32-ppc.c:5533 elf32-ppc.c:5592
#, c-format
msgid ""
"%s: the target (%s) of a %s relocation is in the wrong output section (%s)"
msgstr ""
-#: elf32-ppc.c:5658
+#: elf32-ppc.c:5647
#, c-format
msgid "%s: relocation %s is not yet supported for symbol %s."
msgstr ""
-#: elf32-ppc.c:5713 elf64-ppc.c:8687
+#: elf32-ppc.c:5702 elf64-ppc.c:8694
#, c-format
msgid "%s(%s+0x%lx): unresolvable %s relocation against symbol `%s'"
msgstr ""
-#: elf32-ppc.c:5763 elf64-ppc.c:8733
+#: elf32-ppc.c:5752 elf64-ppc.c:8740
#, c-format
msgid "%s(%s+0x%lx): %s reloc against `%s': error %d"
msgstr ""
-#: elf32-ppc.c:6007
+#: elf32-ppc.c:5996
#, c-format
msgid "corrupt or empty %s section in %s"
msgstr ""
-#: elf32-ppc.c:6014
+#: elf32-ppc.c:6003
#, c-format
msgid "unable to read in %s section from %s"
msgstr ""
-#: elf32-ppc.c:6020
+#: elf32-ppc.c:6009
#, c-format
msgid "corrupt %s section in %s"
msgstr ""
-#: elf32-ppc.c:6063
+#: elf32-ppc.c:6052
#, c-format
msgid "warning: unable to set size of %s section in %s"
msgstr ""
-#: elf32-ppc.c:6113
+#: elf32-ppc.c:6102
msgid "failed to allocate space for new APUinfo section."
msgstr ""
-#: elf32-ppc.c:6132
+#: elf32-ppc.c:6121
msgid "failed to compute new APUinfo section."
msgstr ""
-#: elf32-ppc.c:6135
+#: elf32-ppc.c:6124
msgid "failed to install new APUinfo section."
msgstr ""
-#: elf32-s390.c:2245 elf64-s390.c:2215
+#: elf32-s390.c:2234 elf64-s390.c:2204
#, c-format
msgid "%s(%s+0x%lx): invalid instruction for TLS relocation %s"
msgstr ""
-#: elf32-sh64.c:215 elf64-sh64.c:2382
+#: elf32-sh64.c:215 elf64-sh64.c:2383
#, c-format
msgid "%s: compiled as 32-bit object and %s is 64-bit"
msgstr ""
-#: elf32-sh64.c:218 elf64-sh64.c:2385
+#: elf32-sh64.c:218 elf64-sh64.c:2386
#, c-format
msgid "%s: compiled as 64-bit object and %s is 32-bit"
msgstr ""
-#: elf32-sh64.c:220 elf64-sh64.c:2387
+#: elf32-sh64.c:220 elf64-sh64.c:2388
#, c-format
msgid "%s: object size does not match that of target %s"
msgstr ""
-#: elf32-sh64.c:442 elf64-sh64.c:2954
+#: elf32-sh64.c:442 elf64-sh64.c:2955
#, c-format
msgid "%s: encountered datalabel symbol in input"
msgstr ""
msgid "%s: GAS error: unexpected PTB insn with R_SH_PT_16"
msgstr ""
-#: elf32-sh64.c:589 elf64-sh64.c:1735
+#: elf32-sh64.c:589 elf64-sh64.c:1736
#, c-format
msgid "%s: error: unaligned relocation type %d at %08x reloc %08x\n"
msgstr ""
msgid "%s: 0x%lx: fatal: reloc overflow while relaxing"
msgstr ""
-#: elf32-sh.c:4767 elf64-sh64.c:1568
+#: elf32-sh.c:4756 elf64-sh64.c:1568
msgid "Unexpected STO_SH5_ISA32 on local symbol is not handled"
msgstr ""
-#: elf32-sh.c:4924
+#: elf32-sh.c:4913
#, c-format
msgid "%s: unresolvable relocation against symbol `%s' from %s section"
msgstr ""
-#: elf32-sh.c:4997
+#: elf32-sh.c:4984
#, c-format
msgid "%s: 0x%lx: fatal: unaligned branch target for relax-support relocation"
msgstr ""
-#: elf32-sh.c:5030 elf32-sh.c:5045
+#: elf32-sh.c:5017 elf32-sh.c:5032
#, c-format
msgid "%s: 0x%lx: fatal: unaligned %s relocation 0x%lx"
msgstr ""
-#: elf32-sh.c:5059
+#: elf32-sh.c:5046
#, c-format
msgid "%s: 0x%lx: fatal: R_SH_PSHA relocation %d not in range -32..32"
msgstr ""
-#: elf32-sh.c:5073
+#: elf32-sh.c:5060
#, c-format
msgid "%s: 0x%lx: fatal: R_SH_PSHL relocation %d not in range -32..32"
msgstr ""
-#: elf32-sh.c:6815 elf64-alpha.c:4744
+#: elf32-sh.c:6802 elf64-alpha.c:4744
#, c-format
msgid "%s: TLS local exec code cannot be linked into shared objects"
msgstr ""
-#: elf32-sparc.c:2510 elf64-sparc.c:2281
+#: elf32-sparc.c:2499 elf64-sparc.c:2270
#, c-format
msgid "%s: probably compiled without -fPIC?"
msgstr ""
-#: elf32-sparc.c:3336
+#: elf32-sparc.c:3325
#, c-format
msgid "%s: compiled for a 64 bit system and target is 32 bit"
msgstr ""
-#: elf32-sparc.c:3350
+#: elf32-sparc.c:3339
#, c-format
msgid "%s: linking little endian files with big endian files"
msgstr ""
msgid "FAILED to find previous HI16 reloc\n"
msgstr ""
-#: elf32-v850.c:1789
+#: elf32-v850.c:1758
msgid "could not locate special linker symbol __gp"
msgstr ""
-#: elf32-v850.c:1793
+#: elf32-v850.c:1762
msgid "could not locate special linker symbol __ep"
msgstr ""
-#: elf32-v850.c:1797
+#: elf32-v850.c:1766
msgid "could not locate special linker symbol __ctbp"
msgstr ""
-#: elf32-v850.c:1982
+#: elf32-v850.c:1951
#, c-format
msgid "%s: Architecture mismatch with previous modules"
msgstr ""
-#: elf32-v850.c:2003
+#: elf32-v850.c:1972
#, c-format
msgid "private flags = %lx: "
msgstr ""
-#: elf32-v850.c:2008
+#: elf32-v850.c:1977
#, c-format
msgid "v850 architecture"
msgstr ""
-#: elf32-v850.c:2009
+#: elf32-v850.c:1978
#, c-format
msgid "v850e architecture"
msgstr ""
-#: elf32-v850.c:2010
+#: elf32-v850.c:1979
#, c-format
msgid "v850e1 architecture"
msgstr ""
msgid "%s: warning: %s relocation to 0x%x from %s section"
msgstr ""
-#: elf32-xstormy16.c:462 elf32-ia64.c:2417 elf64-ia64.c:2417
+#: elf32-xstormy16.c:462 elf32-ia64.c:2418 elf64-ia64.c:2418
msgid "non-zero addend in @fptr reloc"
msgstr ""
+#: elf32-xtensa.c:2051
+msgid "dynamic relocation in read-only section"
+msgstr ""
+
#: elf64-alpha.c:1067
msgid "GPDISP relocation did not find ldah and lda instructions"
msgstr ""
msgid "%s: tp-relative relocation against dynamic symbol %s"
msgstr ""
-#: elf64-hppa.c:2082
+#: elf64-hppa.c:2083
#, c-format
msgid "stub entry for %s cannot load .plt, dp offset = %ld"
msgstr ""
"08lx\n"
msgstr ""
-#: elf64-mmix.c:1630
+#: elf64-mmix.c:1603
#, c-format
msgid ""
"%s: base-plus-offset relocation against register symbol: (unknown) in %s"
msgstr ""
-#: elf64-mmix.c:1635
+#: elf64-mmix.c:1608
#, c-format
msgid "%s: base-plus-offset relocation against register symbol: %s in %s"
msgstr ""
-#: elf64-mmix.c:1679
+#: elf64-mmix.c:1652
#, c-format
msgid "%s: register relocation against non-register symbol: (unknown) in %s"
msgstr ""
-#: elf64-mmix.c:1684
+#: elf64-mmix.c:1657
#, c-format
msgid "%s: register relocation against non-register symbol: %s in %s"
msgstr ""
-#: elf64-mmix.c:1721
+#: elf64-mmix.c:1694
#, c-format
msgid "%s: directive LOCAL valid only with a register or absolute value"
msgstr ""
-#: elf64-mmix.c:1749
+#: elf64-mmix.c:1722
#, c-format
msgid ""
"%s: LOCAL directive: Register $%ld is not a local register. First global "
"register is $%ld."
msgstr ""
-#: elf64-mmix.c:2229
+#: elf64-mmix.c:2202
#, c-format
msgid ""
"%s: Error: multiple definition of `%s'; start of %s is set in a earlier "
"linked file\n"
msgstr ""
-#: elf64-mmix.c:2288
+#: elf64-mmix.c:2261
msgid "Register section has contents\n"
msgstr ""
-#: elf64-mmix.c:2494
+#: elf64-mmix.c:2467
#, c-format
msgid ""
"Internal inconsistency: remaining %u != max %u.\n"
" Please report this bug."
msgstr ""
-#: elf64-ppc.c:2431 libbfd.c:821
+#: elf64-ppc.c:2433 libbfd.c:821
#, c-format
msgid "%s: compiled for a big endian system and target is little endian"
msgstr ""
-#: elf64-ppc.c:2434 libbfd.c:823
+#: elf64-ppc.c:2436 libbfd.c:823
#, c-format
msgid "%s: compiled for a little endian system and target is big endian"
msgstr ""
-#: elf64-ppc.c:4638
+#: elf64-ppc.c:4656
#, c-format
msgid ""
"copy reloc against `%s' requires lazy plt linking; avoid setting "
"LD_BIND_NOW=1 or upgrade gcc"
msgstr ""
-#: elf64-ppc.c:5009
+#: elf64-ppc.c:5027
#, c-format
msgid "%s: .opd is not a regular array of opd entries"
msgstr ""
-#: elf64-ppc.c:5019
+#: elf64-ppc.c:5037
#, c-format
msgid "%s: unexpected reloc type %u in .opd section"
msgstr ""
-#: elf64-ppc.c:5039
+#: elf64-ppc.c:5057
#, c-format
msgid "%s: undefined sym `%s' in .opd section"
msgstr ""
-#: elf64-ppc.c:6265
+#: elf64-ppc.c:6272
#, c-format
msgid "can't find branch stub `%s'"
msgstr ""
-#: elf64-ppc.c:6304 elf64-ppc.c:6379
+#: elf64-ppc.c:6311 elf64-ppc.c:6386
#, c-format
msgid "linkage table error against `%s'"
msgstr ""
-#: elf64-ppc.c:6496
+#: elf64-ppc.c:6503
#, c-format
msgid "can't build branch stub `%s'"
msgstr ""
-#: elf64-ppc.c:7215
+#: elf64-ppc.c:7222
msgid ".glink and .plt too far apart"
msgstr ""
-#: elf64-ppc.c:7327
+#: elf64-ppc.c:7334
msgid "stubs don't match calculated size"
msgstr ""
-#: elf64-ppc.c:7339
+#: elf64-ppc.c:7346
#, c-format
msgid ""
"linker stubs in %u groups\n"
" plt call %lu"
msgstr ""
-#: elf64-ppc.c:7537
+#: elf64-ppc.c:7544
#, c-format
msgid "%s(%s+0x%lx): %s used with TLS symbol %s"
msgstr ""
-#: elf64-ppc.c:7538
+#: elf64-ppc.c:7545
#, c-format
msgid "%s(%s+0x%lx): %s used with non-TLS symbol %s"
msgstr ""
-#: elf64-ppc.c:7949
+#: elf64-ppc.c:7956
#, c-format
msgid ""
"%s(%s+0x%lx): automatic multiple TOCs not supported using your crt files; "
"recompile with -mminimal-toc or upgrade gcc"
msgstr ""
-#: elf64-ppc.c:7957
+#: elf64-ppc.c:7964
#, c-format
msgid ""
"%s(%s+0x%lx): sibling call optimization to `%s' does not allow automatic "
"or make `%s' extern"
msgstr ""
-#: elf64-ppc.c:8555
+#: elf64-ppc.c:8562
#, c-format
msgid "%s: relocation %s is not supported for symbol %s."
msgstr ""
-#: elf64-ppc.c:8634
+#: elf64-ppc.c:8641
#, c-format
msgid "%s: error: relocation %s not a multiple of %d"
msgstr ""
msgid "Symbol `%s' has differing types: %s in %s, previously REGISTER in %s"
msgstr ""
-#: elf64-sparc.c:3020
+#: elf64-sparc.c:3009
#, c-format
msgid "%s: linking UltraSPARC specific with HAL specific code"
msgstr ""
msgid "%s: unsupported relocation type %s"
msgstr ""
-#: elfcode.h:1068
+#: elfcode.h:1050
#, c-format
msgid "%s: version count (%ld) does not match symbol count (%ld)"
msgstr ""
-#: elfcode.h:1294
+#: elfcode.h:1276
#, c-format
msgid "%s(%s): relocation %d has invalid symbol index %ld"
msgstr ""
-#: elflink.c:1349
+#: elflink.c:1350
#, c-format
msgid "%s: warning: unexpected redefinition of indirect versioned symbol `%s'"
msgstr ""
-#: elflink.c:1668
+#: elflink.c:1669
#, c-format
msgid "%s: undefined versioned symbol name %s"
msgstr ""
-#: elflink.c:1817
+#: elflink.c:1818
#, c-format
msgid ""
"%s: bad reloc symbol index (0x%lx >= 0x%lx) for offset 0x%lx in section `%s'"
msgstr ""
-#: elflink.c:2006
+#: elflink.c:2007
#, c-format
msgid "%s: relocation size mismatch in %s section %s"
msgstr ""
-#: elflink.c:2295
+#: elflink.c:2296
#, c-format
msgid "warning: type and size of dynamic symbol `%s' are not defined"
msgstr ""
-#: elflink.h:196
+#: elflink.c:2917
msgid "warning: "
msgstr ""
-#: elflink.h:691
+#: elflink.c:3411
#, c-format
msgid "%s: %s: invalid version %u (max %d)"
msgstr ""
-#: elflink.h:732
+#: elflink.c:3452
#, c-format
msgid "%s: %s: invalid needed version %d"
msgstr ""
-#: elflink.h:907
+#: elflink.c:3627
#, c-format
msgid "Warning: alignment %u of symbol `%s' in %s is smaller than %u in %s"
msgstr ""
-#: elflink.h:921
+#: elflink.c:3641
#, c-format
msgid "Warning: size of symbol `%s' changed from %lu in %s to %lu in %s"
msgstr ""
-#: elflink.h:1858
+#: elflink.c:4837
#, c-format
msgid "%s: undefined version: %s"
msgstr ""
-#: elflink.h:1924
+#: elflink.c:4903
#, c-format
msgid "%s: .preinit_array section is not allowed in DSO"
msgstr ""
-#: elflink.h:2750
+#: elflink.c:5594
msgid "Not enough memory to sort relocations"
msgstr ""
-#: elflink.h:3609 elflink.h:3652
+#: elflink.c:5976
#, c-format
-msgid "%s: could not find output section %s"
+msgid "%s: %s symbol `%s' in %s is referenced by DSO"
msgstr ""
-#: elflink.h:3615
+#: elflink.c:6057
#, c-format
-msgid "warning: %s section has zero size"
+msgid "%s: could not find output section %s for input section %s"
msgstr ""
-#: elflink.h:4124
+#: elflink.c:6156
#, c-format
-msgid "%s: %s symbol `%s' in %s is referenced by DSO"
+msgid "%s: %s symbol `%s' isn't defined"
msgstr ""
-#: elflink.h:4205
-#, c-format
-msgid "%s: could not find output section %s for input section %s"
+#: elflink.c:6575 elflink.c:6616
+msgid "%T: discarded in section `%s' from %s\n"
msgstr ""
-#: elflink.h:4307
+#: elflink.c:7870 elflink.c:7912
#, c-format
-msgid "%s: %s symbol `%s' isn't defined"
+msgid "%s: could not find output section %s"
msgstr ""
-#: elflink.h:4691 elflink.h:4733
-msgid "%T: discarded in section `%s' from %s\n"
+#: elflink.c:7876
+#, c-format
+msgid "warning: %s section has zero size"
msgstr ""
-#: elflink.h:5542
+#: elflink.c:8427
msgid "Warning: gc-sections option ignored"
msgstr ""
-#: elfxx-mips.c:899
+#: elfxx-mips.c:890
msgid "static procedure (no name)"
msgstr ""
-#: elfxx-mips.c:2037
+#: elfxx-mips.c:2028
msgid "not enough GOT space for local GOT entries"
msgstr ""
-#: elfxx-mips.c:3786
+#: elfxx-mips.c:3775
#, c-format
msgid "%s: %s+0x%lx: jump to stub routine which is not jal"
msgstr ""
-#: elfxx-mips.c:5271
+#: elfxx-mips.c:5260
#, c-format
msgid "%s: Malformed reloc detected for section %s"
msgstr ""
-#: elfxx-mips.c:5345
+#: elfxx-mips.c:5334
#, c-format
msgid "%s: CALL16 reloc at 0x%lx not against global symbol"
msgstr ""
-#: elfxx-mips.c:8642
+#: elfxx-mips.c:8631
#, c-format
msgid "%s: illegal section name `%s'"
msgstr ""
-#: elfxx-mips.c:8965
+#: elfxx-mips.c:8954
#, c-format
msgid "%s: endianness incompatible with that of the selected emulation"
msgstr ""
-#: elfxx-mips.c:8977
+#: elfxx-mips.c:8966
#, c-format
msgid "%s: ABI is incompatible with that of the selected emulation"
msgstr ""
-#: elfxx-mips.c:9049
+#: elfxx-mips.c:9038
#, c-format
msgid "%s: warning: linking PIC files with non-PIC files"
msgstr ""
-#: elfxx-mips.c:9066
+#: elfxx-mips.c:9055
#, c-format
msgid "%s: linking 32-bit code with 64-bit code"
msgstr ""
-#: elfxx-mips.c:9094
+#: elfxx-mips.c:9083
#, c-format
msgid "%s: linking %s module with previous %s modules"
msgstr ""
-#: elfxx-mips.c:9117
+#: elfxx-mips.c:9106
#, c-format
msgid "%s: ABI mismatch: linking %s module with previous %s modules"
msgstr ""
-#: elfxx-mips.c:9182
+#: elfxx-mips.c:9171
#, c-format
msgid " [abi=O32]"
msgstr ""
-#: elfxx-mips.c:9184
+#: elfxx-mips.c:9173
#, c-format
msgid " [abi=O64]"
msgstr ""
-#: elfxx-mips.c:9186
+#: elfxx-mips.c:9175
#, c-format
msgid " [abi=EABI32]"
msgstr ""
-#: elfxx-mips.c:9188
+#: elfxx-mips.c:9177
#, c-format
msgid " [abi=EABI64]"
msgstr ""
-#: elfxx-mips.c:9190
+#: elfxx-mips.c:9179
#, c-format
msgid " [abi unknown]"
msgstr ""
-#: elfxx-mips.c:9192
+#: elfxx-mips.c:9181
#, c-format
msgid " [abi=N32]"
msgstr ""
-#: elfxx-mips.c:9194
+#: elfxx-mips.c:9183
#, c-format
msgid " [abi=64]"
msgstr ""
-#: elfxx-mips.c:9196
+#: elfxx-mips.c:9185
#, c-format
msgid " [no abi set]"
msgstr ""
-#: elfxx-mips.c:9199
+#: elfxx-mips.c:9188
#, c-format
msgid " [mips1]"
msgstr ""
-#: elfxx-mips.c:9201
+#: elfxx-mips.c:9190
#, c-format
msgid " [mips2]"
msgstr ""
-#: elfxx-mips.c:9203
+#: elfxx-mips.c:9192
#, c-format
msgid " [mips3]"
msgstr ""
-#: elfxx-mips.c:9205
+#: elfxx-mips.c:9194
#, c-format
msgid " [mips4]"
msgstr ""
-#: elfxx-mips.c:9207
+#: elfxx-mips.c:9196
#, c-format
msgid " [mips5]"
msgstr ""
-#: elfxx-mips.c:9209
+#: elfxx-mips.c:9198
#, c-format
msgid " [mips32]"
msgstr ""
-#: elfxx-mips.c:9211
+#: elfxx-mips.c:9200
#, c-format
msgid " [mips64]"
msgstr ""
-#: elfxx-mips.c:9213
+#: elfxx-mips.c:9202
#, c-format
msgid " [mips32r2]"
msgstr ""
-#: elfxx-mips.c:9215
+#: elfxx-mips.c:9204
#, c-format
msgid " [mips64r2]"
msgstr ""
-#: elfxx-mips.c:9217
+#: elfxx-mips.c:9206
#, c-format
msgid " [unknown ISA]"
msgstr ""
-#: elfxx-mips.c:9220
+#: elfxx-mips.c:9209
#, c-format
msgid " [mdmx]"
msgstr ""
-#: elfxx-mips.c:9223
+#: elfxx-mips.c:9212
#, c-format
msgid " [mips16]"
msgstr ""
-#: elfxx-mips.c:9226
+#: elfxx-mips.c:9215
#, c-format
msgid " [32bitmode]"
msgstr ""
-#: elfxx-mips.c:9228
+#: elfxx-mips.c:9217
#, c-format
msgid " [not 32bitmode]"
msgstr ""
msgid "Deprecated %s called\n"
msgstr ""
-#: linker.c:1829
+#: linker.c:1831
#, c-format
msgid "%s: indirect symbol `%s' to `%s' is a loop"
msgstr ""
-#: linker.c:2697
+#: linker.c:2699
#, c-format
msgid "Attempt to do relocatable link with %s input and %s output"
msgstr ""
msgid "%s: loader reloc in read-only section %s"
msgstr ""
-#: elf32-ia64.c:2362 elf64-ia64.c:2362
+#: elf32-ia64.c:2363 elf64-ia64.c:2363
msgid "@pltoff reloc against local symbol"
msgstr ""
-#: elf32-ia64.c:3767 elf64-ia64.c:3767
+#: elf32-ia64.c:3768 elf64-ia64.c:3768
#, c-format
msgid "%s: short data segment overflowed (0x%lx >= 0x400000)"
msgstr ""
-#: elf32-ia64.c:3778 elf64-ia64.c:3778
+#: elf32-ia64.c:3779 elf64-ia64.c:3779
#, c-format
msgid "%s: __gp does not cover short data segment"
msgstr ""
-#: elf32-ia64.c:4026 elf64-ia64.c:4026
+#: elf32-ia64.c:4027 elf64-ia64.c:4027
#, c-format
msgid "%s: non-pic code with imm relocation against dynamic symbol `%s'"
msgstr ""
-#: elf32-ia64.c:4091 elf64-ia64.c:4091
+#: elf32-ia64.c:4092 elf64-ia64.c:4092
#, c-format
msgid "%s: @gprel relocation against dynamic symbol %s"
msgstr ""
-#: elf32-ia64.c:4151 elf64-ia64.c:4151
+#: elf32-ia64.c:4152 elf64-ia64.c:4152
#, c-format
msgid "%s: linking non-pic code in a position independent executable"
msgstr ""
-#: elf32-ia64.c:4288 elf64-ia64.c:4288
+#: elf32-ia64.c:4289 elf64-ia64.c:4289
#, c-format
msgid "%s: @internal branch to dynamic symbol %s"
msgstr ""
-#: elf32-ia64.c:4290 elf64-ia64.c:4290
+#: elf32-ia64.c:4291 elf64-ia64.c:4291
#, c-format
msgid "%s: speculation fixup to dynamic symbol %s"
msgstr ""
-#: elf32-ia64.c:4292 elf64-ia64.c:4292
+#: elf32-ia64.c:4293 elf64-ia64.c:4293
#, c-format
msgid "%s: @pcrel relocation against dynamic symbol %s"
msgstr ""
-#: elf32-ia64.c:4504 elf64-ia64.c:4504
+#: elf32-ia64.c:4505 elf64-ia64.c:4505
msgid "unsupported reloc"
msgstr ""
-#: elf32-ia64.c:4783 elf64-ia64.c:4783
+#: elf32-ia64.c:4784 elf64-ia64.c:4784
#, c-format
msgid "%s: linking trap-on-NULL-dereference with non-trapping files"
msgstr ""
-#: elf32-ia64.c:4792 elf64-ia64.c:4792
+#: elf32-ia64.c:4793 elf64-ia64.c:4793
#, c-format
msgid "%s: linking big-endian files with little-endian files"
msgstr ""
-#: elf32-ia64.c:4801 elf64-ia64.c:4801
+#: elf32-ia64.c:4802 elf64-ia64.c:4802
#, c-format
msgid "%s: linking 64-bit files with 32-bit files"
msgstr ""
-#: elf32-ia64.c:4810 elf64-ia64.c:4810
+#: elf32-ia64.c:4811 elf64-ia64.c:4811
#, c-format
msgid "%s: linking constant-gp files with non-constant-gp files"
msgstr ""
-#: elf32-ia64.c:4820 elf64-ia64.c:4820
+#: elf32-ia64.c:4821 elf64-ia64.c:4821
#, c-format
msgid "%s: linking auto-pic files with non-auto-pic files"
msgstr ""
Motorola 68HC12 reloc.
This is the 5 bits of a value.
+ENUM
+ BFD_RELOC_16C_NUM08
+ENUMX
+ BFD_RELOC_16C_NUM08_C
+ENUMX
+ BFD_RELOC_16C_NUM16
+ENUMX
+ BFD_RELOC_16C_NUM16_C
+ENUMX
+ BFD_RELOC_16C_NUM32
+ENUMX
+ BFD_RELOC_16C_NUM32_C
+ENUMX
+ BFD_RELOC_16C_DISP04
+ENUMX
+ BFD_RELOC_16C_DISP04_C
+ENUMX
+ BFD_RELOC_16C_DISP08
+ENUMX
+ BFD_RELOC_16C_DISP08_C
+ENUMX
+ BFD_RELOC_16C_DISP16
+ENUMX
+ BFD_RELOC_16C_DISP16_C
+ENUMX
+ BFD_RELOC_16C_DISP24
+ENUMX
+ BFD_RELOC_16C_DISP24_C
+ENUMX
+ BFD_RELOC_16C_DISP24a
+ENUMX
+ BFD_RELOC_16C_DISP24a_C
+ENUMX
+ BFD_RELOC_16C_REG04
+ENUMX
+ BFD_RELOC_16C_REG04_C
+ENUMX
+ BFD_RELOC_16C_REG04a
+ENUMX
+ BFD_RELOC_16C_REG04a_C
+ENUMX
+ BFD_RELOC_16C_REG14
+ENUMX
+ BFD_RELOC_16C_REG14_C
+ENUMX
+ BFD_RELOC_16C_REG16
+ENUMX
+ BFD_RELOC_16C_REG16_C
+ENUMX
+ BFD_RELOC_16C_REG20
+ENUMX
+ BFD_RELOC_16C_REG20_C
+ENUMX
+ BFD_RELOC_16C_ABS20
+ENUMX
+ BFD_RELOC_16C_ABS20_C
+ENUMX
+ BFD_RELOC_16C_ABS24
+ENUMX
+ BFD_RELOC_16C_ABS24_C
+ENUMX
+ BFD_RELOC_16C_IMM04
+ENUMX
+ BFD_RELOC_16C_IMM04_C
+ENUMX
+ BFD_RELOC_16C_IMM16
+ENUMX
+ BFD_RELOC_16C_IMM16_C
+ENUMX
+ BFD_RELOC_16C_IMM20
+ENUMX
+ BFD_RELOC_16C_IMM20_C
+ENUMX
+ BFD_RELOC_16C_IMM24
+ENUMX
+ BFD_RELOC_16C_IMM24_C
+ENUMX
+ BFD_RELOC_16C_IMM32
+ENUMX
+ BFD_RELOC_16C_IMM32_C
+ENUMDOC
+ NS CR16C Relocations.
+
ENUM
BFD_RELOC_CRIS_BDISP8
ENUMX
/* Stabs in sections linking support.
- Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+ Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support.
};
/* A linked list of totals that we have found for a particular header
- file. */
+ file. A total is a unique identifier for a particular BINCL...EINCL
+ sequence of STABs that can be used to identify duplicate sequences.
+ It consists of three fields, 'sum_chars' which is the sum of all the
+ STABS characters; 'num_chars' which is the number of these charactes
+ and 'symb' which is a buffer of all the symbols in the sequence. This
+ buffer is only checked as a last resort. */
struct stab_link_includes_totals
{
struct stab_link_includes_totals *next;
- bfd_vma total;
+ bfd_vma sum_chars; /* Accumulated sum of STABS characters. */
+ bfd_vma num_chars; /* Number of STABS characters. */
+ const char* symb; /* The STABS characters themselves. */
};
/* An entry in the header file hash table. */
first number after an open parenthesis). */
if (type == (int) N_BINCL)
{
- bfd_vma val;
+ bfd_vma sum_chars;
+ bfd_vma num_chars;
+ bfd_vma buf_len = 0;
+ char * symb;
+ char * symb_rover;
int nest;
- bfd_byte *incl_sym;
- struct stab_link_includes_entry *incl_entry;
- struct stab_link_includes_totals *t;
- struct stab_excl_list *ne;
+ bfd_byte * incl_sym;
+ struct stab_link_includes_entry * incl_entry;
+ struct stab_link_includes_totals * t;
+ struct stab_excl_list * ne;
- val = 0;
+ symb = symb_rover = NULL;
+ sum_chars = num_chars = 0;
nest = 0;
+
for (incl_sym = sym + STABSIZE;
incl_sym < symend;
incl_sym += STABSIZE)
+ bfd_get_32 (abfd, incl_sym + STRDXOFF));
for (; *str != '\0'; str++)
{
- val += *str;
+ if (num_chars >= buf_len)
+ {
+ buf_len += 32 * 1024;
+ symb = bfd_realloc (symb, buf_len);
+ if (symb == NULL)
+ goto error_return;
+ symb_rover = symb + num_chars;
+ }
+ * symb_rover ++ = * str;
+ sum_chars += *str;
+ num_chars ++;
if (*str == '(')
{
/* Skip the file number. */
}
}
+ BFD_ASSERT (num_chars == (bfd_vma) (symb_rover - symb));
+
/* If we have already included a header file with the same
value, then replaced this one with an N_EXCL symbol. */
incl_entry = stab_link_includes_lookup (&sinfo->includes, string,
goto error_return;
for (t = incl_entry->totals; t != NULL; t = t->next)
- if (t->total == val)
+ if (t->sum_chars == sum_chars
+ && t->num_chars == num_chars
+ && memcmp (t->symb, symb, num_chars) == 0)
break;
/* Record this symbol, so that we can set the value
if (ne == NULL)
goto error_return;
ne->offset = sym - stabbuf;
- ne->val = val;
+ ne->val = sum_chars;
ne->type = (int) N_BINCL;
ne->next = secinfo->excls;
secinfo->excls = ne;
bfd_hash_allocate (&sinfo->includes.root, sizeof *t));
if (t == NULL)
goto error_return;
- t->total = val;
+ t->sum_chars = sum_chars;
+ t->num_chars = num_chars;
+ t->symb = bfd_realloc (symb, num_chars); /* Trim data down. */
t->next = incl_entry->totals;
incl_entry->totals = t;
}
pass to change the type to N_EXCL. */
ne->type = (int) N_EXCL;
+ /* Free off superfluous symbols. */
+ free (symb);
+
/* Mark the skipped symbols. */
nest = 0;
}
else if (incl_type == (int) N_BINCL)
++nest;
+ else if (incl_type == (int) N_EXCL)
+ /* Keep existing exclusion marks. */
+ continue;
else if (nest == 0)
{
*incl_pstridx = (bfd_size_type) -1;
extern const bfd_target bfd_elf32_bigarm_oabi_vec;
extern const bfd_target bfd_elf32_bigarm_vec;
extern const bfd_target bfd_elf32_bigmips_vec;
+extern const bfd_target bfd_elf32_cr16c_vec;
extern const bfd_target bfd_elf32_cris_vec;
extern const bfd_target bfd_elf32_d10v_vec;
extern const bfd_target bfd_elf32_d30v_vec;
&bfd_elf32_bigarm_oabi_vec,
&bfd_elf32_bigarm_vec,
&bfd_elf32_bigmips_vec,
+ &bfd_elf32_cr16c_vec,
&bfd_elf32_cris_vec,
&bfd_elf32_d10v_vec,
&bfd_elf32_d30v_vec,
-#define BFD_VERSION_DATE 20040327
+#define BFD_VERSION_DATE 20040402
#define BFD_VERSION @bfd_version@
#define BFD_VERSION_STRING @bfd_version_string@
+2004-03-30 Kazuhiro Inaoka <inaoka.kazuhiro@renesas.com>
+
+ * m32r.opc (parse_hi16): Fixed shigh(0xffff8000) bug.
+
2004-03-01 Richard Sandiford <rsandifo@redhat.com>
* frv.cpu (define-arch frv): Add fr450 mach.
/* M32R opcode support. -*- C -*-
- Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright 1998, 1999, 2000, 2001, 2004 Free Software Foundation, Inc.
Contributed by Red Hat Inc; developed under contract from
Mitsubishi Electric Corporation.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* This file is an addendum to m32r.cpu. Heavy use of C code isn't
appropriate in .cpu files, so it resides here. This especially applies
<arch>-opc.c additions use: "-- opc.c"
<arch>-asm.c additions use: "-- asm.c"
<arch>-dis.c additions use: "-- dis.c"
- <arch>-ibd.h additions use: "-- ibd.h"
-*/
+ <arch>-ibd.h additions use: "-- ibd.h" */
\f
/* -- opc.h */
++*strp;
if (errmsg == NULL
&& result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- value = (value >> 16) + (value & 0x8000 ? 1 : 0);
+ {
+ value = value + (value & 0x8000 ? 0x10000 : 0);
+ value >>= 16;
+ }
*valuep = value;
return errmsg;
}
+2004-04-01 Daniel Jacobowitz <drow@mvista.com>
+
+ * dwarf2read.c (dwarf2_objfile_data_key): New.
+ (struct dwarf2_per_objfile, dwarf2_per_objfile): New.
+ (dwarf_info_size, dwarf_abbrev_size, dwarf_line_size)
+ (dwarf_pubnames_size, dwarf_aranges_size, dwarf_loc_size)
+ (dwarf_macinfo_size, dwarf_str_size, dwarf_ranges_size)
+ (dwarf_frame_size, dwarf_eh_frame_size, dwarf_info_buffer)
+ (dwarf_abbrev_buffer, dwarf_line_buffer, dwarf_str_buffer)
+ (dwarf_macinfo_buffer, dwarf_ranges_buffer, dwarf_loc_buffer):
+ Remove variables.
+ (struct dwarf2_pinfo): Remove per-objfile members. Update comments.
+ (DWARF_ABBREV_SIZE, DWARF_LINE_SIZE)
+ (DWARF_LOC_SIZE, DWARF_MACINFO_SIZE, DWARF_STR_SIZE)
+ (DWARF_RANGES_SIZE, DWARF_INFO_BUFFER)
+ (DWARF_ABBREV_BUFFER, DWARF_LINE_BUFFER, DWARF_STR_BUFFER)
+ (DWARF_MACINFO_BUFFER, DWARF_RANGES_BUFFER, DWARF_LOC_BUFFER):
+ Remove macros.
+ (dwarf2_has_info): Take an objfile argument. Allocate per-objfile
+ data.
+ (dwarf2_locate_sections, dwarf2_build_psymtabs)
+ (dwarf2_build_psymtabs_easy, dwarf2_build_psymtabs_hard)
+ (skip_one_die, dwarf2_get_pc_bounds, dwarf2_read_abbrevs)
+ (read_partial_die, read_full_die, read_indirect_string)
+ (dwarf_decode_line_header, dwarf_decode_macros)
+ (dwarf2_symbol_mark_computed): Remove use of removed macros.
+ Update uses of removed variables.
+ (psymtab_to_symtab_1): Restore per-objfile data pointer. Remove use
+ of removed macros.
+ (_initialize_dwarf2_read): New function.
+ * symfile.h (dwarf2_has_info): Update prototype.
+ * coffread.c (coff_symfile_read): Update call to dwarf2_has_info.
+ * elfread.c (elf_symfile_read): Likewise.
+
+2004-04-01 Jim Blandy <jimb@redhat.com>
+
+ * rs6000-tdep.c (rs6000_dwarf2_stab_reg_to_regnum): New, unified
+ function for register numbers on all the rs6000-derived targets.
+ (rs6000_gdbarch_init): Don't register a separate
+ gdbarch_dwarf2_reg_to_regnum function for the E500. Use
+ rs6000_dwarf2_stab_reg_to_regnum for both Dwarf 2 and stabs on all
+ variants.
+
+ * i386-tdep.c: Add FIXME regarding STABS vs. Dwarf 2 register
+ numbering.
+
+2004-04-01 Paul N. Hilfinger <Hilfinger@gnat.com>
+
+ * valarith.c: Update copyright notice.
+ (value_add): Handle range types.
+ (value_sub): Ditto.
+ (value_equal): Ditto.
+ (value_less): Ditto.
+ (value_neg): Ditto.
+ (value_complement): Ditto.
+ (value_binop): Simplify slightly by using is_integral_type and
+ eliminiating unnecessary COERCE_ENUMs.
+
+2004-03-31 Andrew Cagney <cagney@redhat.com>
+
+ * frame.h (frame_unwind_id): Declare.
+ * frame.c (frame_unwind_id): New function.
+ (get_prev_frame_1): New function.
+ (frame_debug_got_null_frame): New function.
+ (get_prev_frame): Use frame_debug_got_null_frame. Move unwind
+ code proper to prev_frame, update description.
+ * infrun.c (step_over_function): Use frame_unwind_id.
+
+2004-04-31 J. Brobecker <brobecker@gnat.com>
+
+ * hppa-tdep.c (hppa32_push_dummy_call): Set the Stack Pointer.
+ (hppa64_push_dummy_call): Likewise.
+
+2004-03-30 Jim Blandy <jimb@redhat.com>
+
+ From Ulrich Weigand:
+ * utils.c (query): Do not use a va_list variable multiple times.
+
+2004-03-29 Daniel Jacobowitz <drow@mvista.com>
+
+ * Makefile.in (linux_nat_h): Update dependencies.
+ * configure.in: Check for <gnu/libc-version.h>.
+ * configure: Regenerate.
+ * config.in: Regenerate.
+ * linux-nat.h: Include "target.h". Add waitstatus field to
+ struct lwp_info.
+ * lin-lwp.c (add_lwp): Initialize waitstatus.kind.
+ (lin_lwp_attach_lwp): Don't attach to LWPs we have already attached
+ to.
+ (lin_lwp_handle_extended): New function. Handle clone events.
+ (wait_lwp): Use lin_lwp_handle_extended. Update comment about
+ thread exit events.
+ (child_wait): Handle clone events.
+ (lin_lwp_wait: Use lin_lwp_handle_extended and handle clone events.
+ * linux-nat.c (linux_enable_event_reporting): Turn on
+ PTRACE_O_TRACECLONE.
+ (linux_handle_extended_wait): Handle clone events.
+ * thread-db.c: Include <gnu/libc-version.h>.
+ (struct private_thread_info): Add dying flag.
+ (enable_thread_event_reporting): Enable TD_DEATH for glibc 2.2 and
+ higher.
+ (attach_thread): Update comments. Handle dying threads.
+ (detach_thread): Set the dying flag.
+ (check_event): Always call attach_thread.
+
+2004-03-29 Daniel Jacobowitz <drow@mvista.com>
+
+ * mips-tdep.c (mips_pdr_data): New.
+ (non_heuristic_proc_desc): Use objfile_data and set_objfile_data.
+ (_initialize_mips_tdep): Initialize mips_pdr_data.
+
+2004-03-29 Corinna Vinschen <vinschen@redhat.com>
+
+ * minsyms.c (install_minimal_symbols): Move dropping leading
+ char from linkage name from here...
+ (prim_record_minimal_symbol_and_info): ...to here. Simplify
+ test for "__gnu_compiled*" symbols.
+
+2004-03-28 Jim Blandy <jimb@redhat.com>
+
+ * rs6000-tdep.c (skip_prologue): Recognize moves from argument
+ registers to temp register r0 and byte stores as prologue
+ instructions.
+
+2004-03-28 Andrew Cagney <cagney@redhat.com>
+
+ * PROBLEMS (Stack backtraces): Rewrite. Remove reference to
+ arm*-*-*.
+
+2004-03-28 Stephane Carrez <stcarrez@nerim.fr>
+
+ * tui/tui-regs.c (tui_show_registers): Make sure the TUI is active
+ and switch the layout to force a display of register window.
+
2004-02-26 J. Brobecker <brobecker@gnat.com>
* amd64-tdep.c (amd64_classify): make RANGE_TYPE objects be part
(determine_prefix): Look at TYPE_TAG_NAME and call
determine_class_name when appropriate.
(determine_prefix_aux, class_name): Delete.
+ (read_namespace): Set die->type.
2004-03-15 Kevin Buettner <kevinb@redhat.com>
language_h = language.h
libunwind_frame_h = libunwind-frame.h $(libunwind_h)
linespec_h = linespec.h
-linux_nat_h = linux-nat.h
+linux_nat_h = linux-nat.h $(target_h)
m2_lang_h = m2-lang.h
m68k_tdep_h = m68k-tdep.h
macroexp_h = macroexp.h
*** Stack backtraces
+GDB's core code base has been updated to use a new backtrace
+mechanism. This mechanism makes it possible to support new features
+such DWARF 2 Call Frame Information (which in turn makes possible
+backtraces through optimized code).
+
+Since this code is new, it is known to still have a few problems:
+
gdb/1505: [regression] gdb prints a bad backtrace for a thread
-When backtracing a thread, gdb doesn't stop until it hits garbage.
-This is sensitive to the operating system and thread library.
+When backtracing a thread, gdb does not stop when it reaches the
+outermost frame, instead continuing until it hits garbage. This is
+sensitive to the operating system and thread library.
+hppa*-*-*
mips*-*-*
-powerpc*-*-*
-sparc*-*-*
-GDB's SPARC, MIPS and PowerPC targets, in 6.0, have not been updated
-to use the new frame mechanism.
+The MIPS and HPPA backtrace code has only very recently been updated
+to use GDB's new frame mechanism. At present there are still a few
+problems, in particular backtraces through signal handlers do not
+work.
-People encountering problems with these targets should consult GDB's
-web pages and mailing lists (http://www.gnu.org/software/gdb/) to see
-if there is an update.
+People encountering problems with these architectures should consult
+GDB's web pages and mailing lists (http://www.gnu.org/software/gdb/)
+to see if there are updates.
-arm-*-*
+powerpc*-*-*
-GDB's ARM target, in 6.0, has not been updated to use the new frame
-mechanism.
+PowerPC architecture support, in 6.1, does not use the new frame code.
-Fortunately the ARM target, in the GDB's mainline sources, has been
-updated so people encountering problems should consider downloading a
-more current GDB (http://www.gnu.org/software/gdb/current).
+Fortunately, PowerPC architecture support, in GDB's mainline sources,
+have been updated. People encountering problems should consider
+downloading a more current snapshot of GDB
+(http://www.gnu.org/software/gdb/current/).
/* Define if you have the <dirent.h> header file. */
#undef HAVE_DIRENT_H
+/* Define if you have the <gnu/libc-version.h> header file. */
+#undef HAVE_GNU_LIBC_VERSION_H
+
/* Define if you have the <libunwind-ia64.h> header file. */
#undef HAVE_LIBUNWIND_IA64_H
fi
done
-for ac_hdr in proc_service.h thread_db.h
+for ac_hdr in proc_service.h thread_db.h gnu/libc-version.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
AC_CHECK_HEADERS(machine/reg.h)
AC_CHECK_HEADERS(nlist.h)
AC_CHECK_HEADERS(poll.h sys/poll.h)
-AC_CHECK_HEADERS(proc_service.h thread_db.h)
+AC_CHECK_HEADERS(proc_service.h thread_db.h gnu/libc-version.h)
AC_CHECK_HEADERS(stddef.h)
AC_CHECK_HEADERS(stdlib.h)
AC_CHECK_HEADERS(stdint.h)
+2004-03-28 Stephane Carrez <stcarrez@nerim.fr>
+
+ * gdb.texinfo (TUI Commands): Document tui reg commands.
+
2004-03-26 Andrew Cagney <cagney@redhat.com>
* gdb.texinfo (TUI): Delete reference to --enable-tui. Mention
@item register
This window shows the processor registers. It detects when
a register is changed and when this is the case, registers that have
-changed are highlighted.
+changed are highlighted.
@end table
@kindex refresh
Refresh the screen. This is similar to using @key{C-L} key.
+@item tui reg float
+@kindex tui reg
+Show the floating point registers in the register window.
+
+@item tui reg general
+Show the general registers in the register window.
+
+@item tui reg next
+Show the next register group. The list of register groups as well as
+their order is target specific. The predefined register groups are the
+following: @code{general}, @code{float}, @code{system}, @code{vector},
+@code{all}, @code{save}, @code{restore}.
+
+@item tui reg system
+Show the system registers in the register window.
+
@item update
@kindex update
Update the source window and the current execution point.
}
_STATEMENT_PROLOGUE;
-static const struct objfile_data *dwarf2_per_objfile_data;
+static const struct objfile_data *dwarf2_objfile_data_key;
-struct dwarf2_per_objfile_data
+struct dwarf2_per_objfile
{
/* Sizes of debugging sections. */
- unsigned int dwarf_info_size;
- unsigned int dwarf_abbrev_size;
- unsigned int dwarf_line_size;
- unsigned int dwarf_pubnames_size;
- unsigned int dwarf_aranges_size;
- unsigned int dwarf_loc_size;
- unsigned int dwarf_macinfo_size;
- unsigned int dwarf_str_size;
- unsigned int dwarf_ranges_size;
- unsigned int dwarf_frame_size;
- unsigned int dwarf_eh_frame_size;
+ unsigned int info_size;
+ unsigned int abbrev_size;
+ unsigned int line_size;
+ unsigned int pubnames_size;
+ unsigned int aranges_size;
+ unsigned int loc_size;
+ unsigned int macinfo_size;
+ unsigned int str_size;
+ unsigned int ranges_size;
+ unsigned int frame_size;
+ unsigned int eh_frame_size;
/* Loaded data from the sections. */
- char *dwarf_info_buffer;
- char *dwarf_abbrev_buffer;
- char *dwarf_line_buffer;
- char *dwarf_str_buffer;
- char *dwarf_macinfo_buffer;
- char *dwarf_ranges_buffer;
- char *dwarf_loc_buffer;
+ char *info_buffer;
+ char *abbrev_buffer;
+ char *line_buffer;
+ char *str_buffer;
+ char *macinfo_buffer;
+ char *ranges_buffer;
+ char *loc_buffer;
/* A tree of all the compilation units. Each member is a pointer
to a struct dwarf2_cu. This will be set if and only if we have
struct dwarf2_per_cu_data *read_in_chain;
};
-#define dwarf_info_size dwarf2_per_objfile->dwarf_info_size
-#define dwarf_abbrev_size dwarf2_per_objfile->dwarf_abbrev_size
-#define dwarf_line_size dwarf2_per_objfile->dwarf_line_size
-#define dwarf_pubnames_size dwarf2_per_objfile->dwarf_pubnames_size
-#define dwarf_aranges_size dwarf2_per_objfile->dwarf_aranges_size
-#define dwarf_loc_size dwarf2_per_objfile->dwarf_loc_size
-#define dwarf_macinfo_size dwarf2_per_objfile->dwarf_macinfo_size
-#define dwarf_str_size dwarf2_per_objfile->dwarf_str_size
-#define dwarf_ranges_size dwarf2_per_objfile->dwarf_ranges_size
-#define dwarf_frame_size dwarf2_per_objfile->dwarf_frame_size
-#define dwarf_eh_frame_size dwarf2_per_objfile->dwarf_eh_frame_size
-
-#define dwarf_info_buffer dwarf2_per_objfile->dwarf_info_buffer
-#define dwarf_abbrev_buffer dwarf2_per_objfile->dwarf_abbrev_buffer
-#define dwarf_line_buffer dwarf2_per_objfile->dwarf_line_buffer
-#define dwarf_loc_buffer dwarf2_per_objfile->dwarf_loc_buffer
-#define dwarf_macinfo_buffer dwarf2_per_objfile->dwarf_macinfo_buffer
-#define dwarf_str_buffer dwarf2_per_objfile->dwarf_str_buffer
-#define dwarf_ranges_buffer dwarf2_per_objfile->dwarf_ranges_buffer
-
-static struct dwarf2_per_objfile_data *dwarf2_per_objfile;
+static struct dwarf2_per_objfile *dwarf2_per_objfile;
static asection *dwarf_info_section;
static asection *dwarf_abbrev_section;
} *file_names;
/* The start and end of the statement program following this
- header. These point into dwarf_line_buffer. */
+ header. These point into dwarf2_per_objfile->line_buffer. */
char *statement_program_start, *statement_program_end;
};
the register number. */
/* We put a pointer to this structure in the read_symtab_private field
- of the psymtab.
-
- Most of the information in this structure is related to an entire
- object file and could be passed via the sym_private field of the
- objfile. It is possible to have both dwarf2 and some other form
- of debug symbols in one object file. */
+ of the psymtab. */
struct dwarf2_pinfo
{
+ /* Offset in .debug_info for this compilation unit. */
+
+ unsigned long dwarf_info_offset;
+
/* If this partial symbol table has been read in, a map of DIE
offsets to types. */
- htab_t type_hash;
- /* Offset in dwarf_info_buffer for this compilation unit. */
-
- unsigned long dwarf_info_offset;
+ htab_t type_hash;
};
#define PST_PRIVATE(p) ((struct dwarf2_pinfo *)(p)->read_symtab_private)
int
dwarf2_has_info (struct objfile *objfile)
{
- struct dwarf2_per_objfile_data *data;
+ struct dwarf2_per_objfile *data;
/* Initialize per-objfile state. */
data = obstack_alloc (&objfile->objfile_obstack, sizeof (*data));
memset (data, 0, sizeof (*data));
- set_objfile_data (objfile, dwarf2_per_objfile_data, data);
+ set_objfile_data (objfile, dwarf2_objfile_data_key, data);
dwarf2_per_objfile = data;
dwarf_info_section = 0;
{
if (strcmp (sectp->name, INFO_SECTION) == 0)
{
- dwarf_info_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf2_per_objfile->info_size = bfd_get_section_size_before_reloc (sectp);
dwarf_info_section = sectp;
}
else if (strcmp (sectp->name, ABBREV_SECTION) == 0)
{
- dwarf_abbrev_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf2_per_objfile->abbrev_size = bfd_get_section_size_before_reloc (sectp);
dwarf_abbrev_section = sectp;
}
else if (strcmp (sectp->name, LINE_SECTION) == 0)
{
- dwarf_line_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf2_per_objfile->line_size = bfd_get_section_size_before_reloc (sectp);
dwarf_line_section = sectp;
}
else if (strcmp (sectp->name, PUBNAMES_SECTION) == 0)
{
- dwarf_pubnames_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf2_per_objfile->pubnames_size = bfd_get_section_size_before_reloc (sectp);
dwarf_pubnames_section = sectp;
}
else if (strcmp (sectp->name, ARANGES_SECTION) == 0)
{
- dwarf_aranges_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf2_per_objfile->aranges_size = bfd_get_section_size_before_reloc (sectp);
dwarf_aranges_section = sectp;
}
else if (strcmp (sectp->name, LOC_SECTION) == 0)
{
- dwarf_loc_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf2_per_objfile->loc_size = bfd_get_section_size_before_reloc (sectp);
dwarf_loc_section = sectp;
}
else if (strcmp (sectp->name, MACINFO_SECTION) == 0)
{
- dwarf_macinfo_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf2_per_objfile->macinfo_size = bfd_get_section_size_before_reloc (sectp);
dwarf_macinfo_section = sectp;
}
else if (strcmp (sectp->name, STR_SECTION) == 0)
{
- dwarf_str_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf2_per_objfile->str_size = bfd_get_section_size_before_reloc (sectp);
dwarf_str_section = sectp;
}
else if (strcmp (sectp->name, FRAME_SECTION) == 0)
{
- dwarf_frame_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf2_per_objfile->frame_size = bfd_get_section_size_before_reloc (sectp);
dwarf_frame_section = sectp;
}
else if (strcmp (sectp->name, EH_FRAME_SECTION) == 0)
flagword aflag = bfd_get_section_flags (ignore_abfd, sectp);
if (aflag & SEC_HAS_CONTENTS)
{
- dwarf_eh_frame_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf2_per_objfile->eh_frame_size = bfd_get_section_size_before_reloc (sectp);
dwarf_eh_frame_section = sectp;
}
}
else if (strcmp (sectp->name, RANGES_SECTION) == 0)
{
- dwarf_ranges_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf2_per_objfile->ranges_size = bfd_get_section_size_before_reloc (sectp);
dwarf_ranges_section = sectp;
}
}
{
/* We definitely need the .debug_info and .debug_abbrev sections */
- dwarf_info_buffer = dwarf2_read_section (objfile, dwarf_info_section);
- dwarf_abbrev_buffer = dwarf2_read_section (objfile, dwarf_abbrev_section);
+ dwarf2_per_objfile->info_buffer = dwarf2_read_section (objfile, dwarf_info_section);
+ dwarf2_per_objfile->abbrev_buffer = dwarf2_read_section (objfile, dwarf_abbrev_section);
if (dwarf_line_section)
- dwarf_line_buffer = dwarf2_read_section (objfile, dwarf_line_section);
+ dwarf2_per_objfile->line_buffer = dwarf2_read_section (objfile, dwarf_line_section);
else
- dwarf_line_buffer = NULL;
+ dwarf2_per_objfile->line_buffer = NULL;
if (dwarf_str_section)
- dwarf_str_buffer = dwarf2_read_section (objfile, dwarf_str_section);
+ dwarf2_per_objfile->str_buffer = dwarf2_read_section (objfile, dwarf_str_section);
else
- dwarf_str_buffer = NULL;
+ dwarf2_per_objfile->str_buffer = NULL;
if (dwarf_macinfo_section)
- dwarf_macinfo_buffer = dwarf2_read_section (objfile,
+ dwarf2_per_objfile->macinfo_buffer = dwarf2_read_section (objfile,
dwarf_macinfo_section);
else
- dwarf_macinfo_buffer = NULL;
+ dwarf2_per_objfile->macinfo_buffer = NULL;
if (dwarf_ranges_section)
- dwarf_ranges_buffer = dwarf2_read_section (objfile, dwarf_ranges_section);
+ dwarf2_per_objfile->ranges_buffer = dwarf2_read_section (objfile, dwarf_ranges_section);
else
- dwarf_ranges_buffer = NULL;
+ dwarf2_per_objfile->ranges_buffer = NULL;
if (dwarf_loc_section)
- dwarf_loc_buffer = dwarf2_read_section (objfile, dwarf_loc_section);
+ dwarf2_per_objfile->loc_buffer = dwarf2_read_section (objfile, dwarf_loc_section);
else
- dwarf_loc_buffer = NULL;
+ dwarf2_per_objfile->loc_buffer = NULL;
if (mainline
|| (objfile->global_psymbols.size == 0
pubnames_buffer = dwarf2_read_section (objfile,
dwarf_pubnames_section);
pubnames_ptr = pubnames_buffer;
- while ((pubnames_ptr - pubnames_buffer) < dwarf_pubnames_size)
+ while ((pubnames_ptr - pubnames_buffer) < dwarf2_per_objfile->pubnames_size)
{
struct comp_unit_head cu_header;
int bytes_read;
"(is %d, should be %d) [in module %s]", header->version,
2, bfd_get_filename (abfd));
- if (header->abbrev_offset >= dwarf_abbrev_size)
+ if (header->abbrev_offset >= dwarf2_per_objfile->abbrev_size)
error ("Dwarf Error: bad offset (0x%lx) in compilation unit header "
"(offset 0x%lx + 6) [in module %s]",
(long) header->abbrev_offset,
- (long) (beg_of_comp_unit - dwarf_info_buffer),
+ (long) (beg_of_comp_unit - dwarf2_per_objfile->info_buffer),
bfd_get_filename (abfd));
if (beg_of_comp_unit + header->length + header->initial_length_size
- > dwarf_info_buffer + dwarf_info_size)
+ > dwarf2_per_objfile->info_buffer + dwarf2_per_objfile->info_size)
error ("Dwarf Error: bad length (0x%lx) in compilation unit header "
"(offset 0x%lx + 0) [in module %s]",
(long) header->length,
- (long) (beg_of_comp_unit - dwarf_info_buffer),
+ (long) (beg_of_comp_unit - dwarf2_per_objfile->info_buffer),
bfd_get_filename (abfd));
return info_ptr;
CORE_ADDR lowpc, highpc, baseaddr;
splay_tree cu_tree = NULL;
- info_ptr = dwarf_info_buffer;
+ info_ptr = dwarf2_per_objfile->info_buffer;
/* We use dwarf2_tmp_obstack for objects that don't need to survive
the partial symbol scan, like attribute values.
2) 30% of the attributes used the form DW_FORM_string. For
DW_FORM_string, read_attribute simply hands back a pointer to
- the null-terminated string in dwarf_info_buffer, so no dynamic
+ the null-terminated string in info_buffer, so no dynamic
allocation is needed there either.
3) The remaining 1% of the attributes all used DW_FORM_block1.
read_in_chain. Make sure to free them when we're done. */
make_cleanup (free_cached_comp_units, NULL);
- /* Since the objects we're extracting from dwarf_info_buffer vary in
+ /* Since the objects we're extracting from .debug_info vary in
length, only the individual functions to extract them (like
read_comp_unit_head and load_partial_die) can really know whether
the buffer is large enough to hold another complete object.
- At the moment, they don't actually check that. If
- dwarf_info_buffer holds just one extra byte after the last
- compilation unit's dies, then read_comp_unit_head will happily
- read off the end of the buffer. load_partial_die is similarly
- casual. Those functions should be fixed.
+ At the moment, they don't actually check that. If .debug_info
+ holds just one extra byte after the last compilation unit's dies,
+ then read_comp_unit_head will happily read off the end of the
+ buffer. read_partial_die is similarly casual. Those functions
+ should be fixed.
For this loop condition, simply checking whether there's any data
left at all should be sufficient. */
- while (info_ptr < dwarf_info_buffer + dwarf_info_size)
+ while (info_ptr < (dwarf2_per_objfile->info_buffer
+ + dwarf2_per_objfile->info_size))
{
struct cleanup *back_to_inner;
struct dwarf2_cu cu;
info_ptr = partial_read_comp_unit_head (&cu.header, info_ptr, abfd);
/* Complete the cu_header */
- cu.header.offset = beg_of_comp_unit - dwarf_info_buffer;
+ cu.header.offset = beg_of_comp_unit - dwarf2_per_objfile->info_buffer;
cu.header.first_die_ptr = info_ptr;
cu.header.cu_head_ptr = beg_of_comp_unit;
pst->read_symtab_private = (char *)
obstack_alloc (&objfile->objfile_obstack, sizeof (struct dwarf2_pinfo));
- DWARF_INFO_OFFSET (pst) = beg_of_comp_unit - dwarf_info_buffer;
+ DWARF_INFO_OFFSET (pst) = beg_of_comp_unit - dwarf2_per_objfile->info_buffer;
PST_PRIVATE (pst)->type_hash = NULL;
baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
unsigned int bytes_read;
struct cleanup *back_to;
- info_ptr = dwarf_info_buffer + this_cu->offset;
+ info_ptr = dwarf2_per_objfile->info_buffer + this_cu->offset;
beg_of_comp_unit = info_ptr;
cu = xmalloc (sizeof (struct dwarf2_cu));
info_ptr = partial_read_comp_unit_head (&cu->header, info_ptr, abfd);
/* Complete the cu_header */
- cu->header.offset = beg_of_comp_unit - dwarf_info_buffer;
+ cu->header.offset = beg_of_comp_unit - dwarf2_per_objfile->info_buffer;
cu->header.first_die_ptr = info_ptr;
cu->header.cu_head_ptr = beg_of_comp_unit;
create_comp_unit_tree (struct objfile *objfile)
{
splay_tree cu_tree;
- char *info_ptr = dwarf_info_buffer;
+ char *info_ptr = dwarf2_per_objfile->info_buffer;
/* Initialize the compilation unit tree. */
cu_tree = splay_tree_new_with_allocator (splay_tree_compare_ints,
&objfile->objfile_obstack);
dwarf2_per_objfile->cu_tree = cu_tree;
- while (info_ptr < dwarf_info_buffer + dwarf_info_size)
+ while (info_ptr < dwarf2_per_objfile->info_buffer + dwarf2_per_objfile->info_size)
{
struct comp_unit_head cu_header;
char *beg_of_comp_unit;
unsigned long offset;
beg_of_comp_unit = info_ptr;
- offset = beg_of_comp_unit - dwarf_info_buffer;
+ offset = beg_of_comp_unit - dwarf2_per_objfile->info_buffer;
/* FIXME: Can I read less data here? All we really need is the length
and the initial length size. */
if (attr.form == DW_FORM_ref_addr)
complaint (&symfile_complaints, "ignoring absolute DW_AT_sibling");
else
- return dwarf_info_buffer + dwarf2_get_ref_die_offset (&attr, cu);
+ return dwarf2_per_objfile->info_buffer
+ + dwarf2_get_ref_die_offset (&attr, cu);
}
/* If it isn't DW_AT_sibling, skip this attribute. */
}
dwarf2_per_objfile = objfile_data (pst->objfile,
- dwarf2_per_objfile_data);
+ dwarf2_objfile_data_key);
psymtab_to_symtab_1 (pst);
/* Finish up the debug error message. */
struct cleanup *back_to, *free_cu_cleanup;
struct attribute *attr;
+ dwarf2_per_objfile = objfile_data (pst->objfile, dwarf2_objfile_data_key);
+
/* Set local variables from the partial symbol table info. */
offset = DWARF_INFO_OFFSET (pst);
- info_ptr = dwarf_info_buffer + offset;
+ info_ptr = dwarf2_per_objfile->info_buffer + offset;
cu = xmalloc (sizeof (struct dwarf2_cu));
memset (cu, 0, sizeof (struct dwarf2_cu));
found_base = cu_header->base_known;
base = cu_header->base_address;
- if (offset >= dwarf_ranges_size)
+ if (offset >= dwarf2_per_objfile->ranges_size)
{
complaint (&symfile_complaints,
"Offset %d out of bounds for DW_AT_ranges attribute",
offset);
return 0;
}
- buffer = dwarf_ranges_buffer + offset;
+ buffer = dwarf2_per_objfile->ranges_buffer + offset;
/* Read in the largest possible address. */
marker = read_address (obfd, buffer, cu, &dummy);
memset (cu->dwarf2_abbrevs, 0,
ABBREV_HASH_SIZE * sizeof (struct abbrev_info *));
- abbrev_ptr = dwarf_abbrev_buffer + cu_header->abbrev_offset;
+ abbrev_ptr = dwarf2_per_objfile->abbrev_buffer + cu_header->abbrev_offset;
abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
abbrev_ptr += bytes_read;
already read (which means we are about to read the abbreviations
for the next compile unit) or if the end of the abbreviation
table is reached. */
- if ((unsigned int) (abbrev_ptr - dwarf_abbrev_buffer)
- >= dwarf_abbrev_size)
+ if ((unsigned int) (abbrev_ptr - dwarf2_per_objfile->abbrev_buffer)
+ >= dwarf2_per_objfile->abbrev_size)
break;
abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
abbrev_ptr += bytes_read;
continue;
}
- // fprintf_unfiltered (gdb_stderr, "Loading DIE %x\n", info_ptr - dwarf_info_buffer);
+ // fprintf_unfiltered (gdb_stderr, "Loading DIE %x\n", info_ptr - dwarf2_per_objfile->info_buffer);
info_ptr = load_partial_die (part_die, abbrev, bytes_read,
abfd, info_ptr, cu);
memset (part_die, 0, sizeof (struct partial_die_info));
- part_die->offset = info_ptr - dwarf_info_buffer;
+ part_die->offset = info_ptr - dwarf2_per_objfile->info_buffer;
info_ptr += abbrev_len;
if (attr.form == DW_FORM_ref_addr)
complaint (&symfile_complaints, "ignoring absolute DW_AT_sibling");
else
- part_die->sibling =
- dwarf_info_buffer + dwarf2_get_ref_die_offset (&attr, cu);
+ part_die->sibling = dwarf2_per_objfile->info_buffer
+ + dwarf2_get_ref_die_offset (&attr, cu);
break;
default:
break;
struct abbrev_info *abbrev;
struct die_info *die;
- offset = info_ptr - dwarf_info_buffer;
+ offset = info_ptr - dwarf2_per_objfile->info_buffer;
abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
info_ptr += bytes_read;
if (!abbrev_number)
LONGEST str_offset = read_offset (abfd, buf, cu_header,
(int *) bytes_read_ptr);
- if (dwarf_str_buffer == NULL)
+ if (dwarf2_per_objfile->str_buffer == NULL)
{
error ("DW_FORM_strp used without .debug_str section [in module %s]",
bfd_get_filename (abfd));
return NULL;
}
- if (str_offset >= dwarf_str_size)
+ if (str_offset >= dwarf2_per_objfile->str_size)
{
error ("DW_FORM_strp pointing outside of .debug_str section [in module %s]",
bfd_get_filename (abfd));
return NULL;
}
gdb_assert (HOST_CHAR_BIT == 8);
- if (dwarf_str_buffer[str_offset] == '\0')
+ if (dwarf2_per_objfile->str_buffer[str_offset] == '\0')
return NULL;
- return dwarf_str_buffer + str_offset;
+ return dwarf2_per_objfile->str_buffer + str_offset;
}
static unsigned long
/* Read the statement program header starting at OFFSET in
- dwarf_line_buffer, according to the endianness of ABFD. Return a
- pointer to a struct line_header, allocated using xmalloc.
+ .debug_line, according to the endianness of ABFD. Return a pointer
+ to a struct line_header, allocated using xmalloc.
NOTE: the strings in the include directory and file name tables of
the returned object point into debug_line_buffer, and must not be
int i;
char *cur_dir, *cur_file;
- if (dwarf_line_buffer == NULL)
+ if (dwarf2_per_objfile->line_buffer == NULL)
{
complaint (&symfile_complaints, "missing .debug_line section");
return 0;
/* Make sure that at least there's room for the total_length field. That
could be 12 bytes long, but we're just going to fudge that. */
- if (offset + 4 >= dwarf_line_size)
+ if (offset + 4 >= dwarf2_per_objfile->line_size)
{
dwarf2_statement_list_fits_in_line_number_section_complaint ();
return 0;
back_to = make_cleanup ((make_cleanup_ftype *) free_line_header,
(void *) lh);
- line_ptr = dwarf_line_buffer + offset;
+ line_ptr = dwarf2_per_objfile->line_buffer + offset;
/* read in the header */
lh->total_length = read_initial_length (abfd, line_ptr, NULL, &bytes_read);
line_ptr += bytes_read;
- if (line_ptr + lh->total_length > dwarf_line_buffer + dwarf_line_size)
+ if (line_ptr + lh->total_length > (dwarf2_per_objfile->line_buffer
+ + dwarf2_per_objfile->line_size))
{
dwarf2_statement_list_fits_in_line_number_section_complaint ();
return 0;
line_ptr += bytes_read;
lh->statement_program_start = line_ptr;
- if (line_ptr > dwarf_line_buffer + dwarf_line_size)
+ if (line_ptr > (dwarf2_per_objfile->line_buffer
+ + dwarf2_per_objfile->line_size))
complaint (&symfile_complaints,
"line number info header doesn't fit in `.debug_line' section");
char *mac_ptr, *mac_end;
struct macro_source_file *current_file = 0;
- if (dwarf_macinfo_buffer == NULL)
+ if (dwarf2_per_objfile->macinfo_buffer == NULL)
{
complaint (&symfile_complaints, "missing .debug_macinfo section");
return;
}
- mac_ptr = dwarf_macinfo_buffer + offset;
- mac_end = dwarf_macinfo_buffer + dwarf_macinfo_size;
+ mac_ptr = dwarf2_per_objfile->macinfo_buffer + offset;
+ mac_end = dwarf2_per_objfile->macinfo_buffer
+ + dwarf2_per_objfile->macinfo_size;
for (;;)
{
/* We don't know how long the location list is, but make sure we
don't run off the edge of the section. */
- baton->size = dwarf_loc_size - DW_UNSND (attr);
- baton->data = dwarf_loc_buffer + DW_UNSND (attr);
+ baton->size = dwarf2_per_objfile->loc_size - DW_UNSND (attr);
+ baton->data = dwarf2_per_objfile->loc_buffer + DW_UNSND (attr);
baton->base_address = cu->header.base_address;
if (cu->header.base_known == 0)
complaint (&symfile_complaints,
{
/* Note that we're just copying the block's data pointer
here, not the actual data. We're still pointing into the
- dwarf_info_buffer for SYM's objfile; right now we never
- release that buffer, but when we do clean up properly
- this may need to change. */
+ info_buffer for SYM's objfile; right now we never release
+ that buffer, but when we do clean up properly this may
+ need to change. */
baton->size = DW_BLOCK (attr)->size;
baton->data = DW_BLOCK (attr)->data;
}
void
_initialize_dwarf2_read (void)
{
- dwarf2_per_objfile_data = register_objfile_data ();
+ dwarf2_objfile_data_key = register_objfile_data ();
}
#include "command.h"
#include "gdbcmd.h"
+static struct frame_info *get_prev_frame_1 (struct frame_info *this_frame);
+
/* We keep a cache of stack frames, each of which is a "struct
frame_info". The innermost one gets allocated (in
wait_for_inferior) each time the inferior stops; current_frame
return fi->this_id.value;
}
+struct frame_id
+frame_unwind_id (struct frame_info *next_frame)
+{
+ /* Use prev_frame, and not get_prev_frame. The latter will truncate
+ the frame chain, leading to this function unintentionally
+ returning a null_frame_id (e.g., when a caller requests the frame
+ ID of "main()"s caller. */
+ return get_frame_id (get_prev_frame_1 (next_frame));
+}
+
const struct frame_id null_frame_id; /* All zeros. */
struct frame_id
return prev;
}
-/* Return a structure containing various interesting information
- about the frame that called THIS_FRAME. Returns NULL
- if there is no such frame.
+/* Return a "struct frame_info" corresponding to the frame that called
+ THIS_FRAME. Returns NULL if there is no such frame.
- This function tests some target-independent conditions that should
- terminate the frame chain, such as unwinding past main(). It
- should not contain any target-dependent tests, such as checking
- whether the program-counter is zero. */
+ Unlike get_prev_frame, this function always tries to unwind the
+ frame. */
-struct frame_info *
-get_prev_frame (struct frame_info *this_frame)
+static struct frame_info *
+get_prev_frame_1 (struct frame_info *this_frame)
{
struct frame_info *prev_frame;
+ gdb_assert (this_frame != NULL);
+
if (frame_debug)
{
- fprintf_unfiltered (gdb_stdlog, "{ get_prev_frame (this_frame=");
+ fprintf_unfiltered (gdb_stdlog, "{ get_prev_frame_1 (this_frame=");
if (this_frame != NULL)
fprintf_unfiltered (gdb_stdlog, "%d", this_frame->level);
else
fprintf_unfiltered (gdb_stdlog, ") ");
}
+ /* Only try to do the unwind once. */
+ if (this_frame->prev_p)
+ {
+ if (frame_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "-> ");
+ fprint_frame (gdb_stdlog, this_frame->prev);
+ fprintf_unfiltered (gdb_stdlog, " // cached \n");
+ }
+ return this_frame->prev;
+ }
+ this_frame->prev_p = 1;
+
+ /* If any of the old frame initialization methods are around, use
+ the legacy get_prev_frame method. */
+ if (legacy_frame_p (current_gdbarch))
+ {
+ prev_frame = legacy_get_prev_frame (this_frame);
+ return prev_frame;
+ }
+
+ /* Check that this frame's ID was valid. If it wasn't, don't try to
+ unwind to the prev frame. Be careful to not apply this test to
+ the sentinel frame. */
+ if (this_frame->level >= 0 && !frame_id_p (get_frame_id (this_frame)))
+ {
+ if (frame_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "-> ");
+ fprint_frame (gdb_stdlog, NULL);
+ fprintf_unfiltered (gdb_stdlog, " // this ID is NULL }\n");
+ }
+ return NULL;
+ }
+
+ /* Check that this frame's ID isn't inner to (younger, below, next)
+ the next frame. This happens when a frame unwind goes backwards.
+ Since the sentinel frame doesn't really exist, don't compare the
+ inner-most against that sentinel. */
+ if (this_frame->level > 0
+ && frame_id_inner (get_frame_id (this_frame),
+ get_frame_id (this_frame->next)))
+ error ("Previous frame inner to this frame (corrupt stack?)");
+
+ /* Check that this and the next frame are not identical. If they
+ are, there is most likely a stack cycle. As with the inner-than
+ test above, avoid comparing the inner-most and sentinel frames. */
+ if (this_frame->level > 0
+ && frame_id_eq (get_frame_id (this_frame),
+ get_frame_id (this_frame->next)))
+ error ("Previous frame identical to this frame (corrupt stack?)");
+
+ /* Allocate the new frame but do not wire it in to the frame chain.
+ Some (bad) code in INIT_FRAME_EXTRA_INFO tries to look along
+ frame->next to pull some fancy tricks (of course such code is, by
+ definition, recursive). Try to prevent it.
+
+ There is no reason to worry about memory leaks, should the
+ remainder of the function fail. The allocated memory will be
+ quickly reclaimed when the frame cache is flushed, and the `we've
+ been here before' check above will stop repeated memory
+ allocation calls. */
+ prev_frame = FRAME_OBSTACK_ZALLOC (struct frame_info);
+ prev_frame->level = this_frame->level + 1;
+
+ /* Don't yet compute ->unwind (and hence ->type). It is computed
+ on-demand in get_frame_type, frame_register_unwind, and
+ get_frame_id. */
+
+ /* Don't yet compute the frame's ID. It is computed on-demand by
+ get_frame_id(). */
+
+ /* The unwound frame ID is validate at the start of this function,
+ as part of the logic to decide if that frame should be further
+ unwound, and not here while the prev frame is being created.
+ Doing this makes it possible for the user to examine a frame that
+ has an invalid frame ID.
+
+ Some very old VAX code noted: [...] For the sake of argument,
+ suppose that the stack is somewhat trashed (which is one reason
+ that "info frame" exists). So, return 0 (indicating we don't
+ know the address of the arglist) if we don't know what frame this
+ frame calls. */
+
+ /* Link it in. */
+ this_frame->prev = prev_frame;
+ prev_frame->next = this_frame;
+
+ if (frame_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "-> ");
+ fprint_frame (gdb_stdlog, prev_frame);
+ fprintf_unfiltered (gdb_stdlog, " }\n");
+ }
+
+ return prev_frame;
+}
+
+/* Debug routine to print a NULL frame being returned. */
+
+static void
+frame_debug_got_null_frame (struct ui_file *file,
+ struct frame_info *this_frame,
+ const char *reason)
+{
+ if (frame_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "{ get_prev_frame (this_frame=");
+ if (this_frame != NULL)
+ fprintf_unfiltered (gdb_stdlog, "%d", this_frame->level);
+ else
+ fprintf_unfiltered (gdb_stdlog, "<NULL>");
+ fprintf_unfiltered (gdb_stdlog, ") -> // %s}\n", reason);
+ }
+}
+
+/* Return a structure containing various interesting information about
+ the frame that called THIS_FRAME. Returns NULL if there is entier
+ no such frame or the frame fails any of a set of target-independent
+ condition that should terminate the frame chain (e.g., as unwinding
+ past main()).
+
+ This function should not contain target-dependent tests, such as
+ checking whether the program-counter is zero. */
+
+struct frame_info *
+get_prev_frame (struct frame_info *this_frame)
+{
+ struct frame_info *prev_frame;
+
/* Return the inner-most frame, when the caller passes in NULL. */
/* NOTE: cagney/2002-11-09: Not sure how this would happen. The
caller should have previously obtained a valid frame using
Per the above, this code shouldn't even be called with a NULL
THIS_FRAME. */
+ frame_debug_got_null_frame (gdb_stdlog, this_frame, "this_frame NULL");
return current_frame;
}
previously unwound. That way if the user later decides to
allow unwinds past main(), that just happens. */
{
- if (frame_debug)
- fprintf_unfiltered (gdb_stdlog, "-> NULL // inside main func }\n");
+ frame_debug_got_null_frame (gdb_stdlog, this_frame, "inside main func");
return NULL;
}
&& this_frame->type != DUMMY_FRAME && this_frame->level >= 0
&& inside_entry_func (this_frame))
{
- if (frame_debug)
- {
- fprintf_unfiltered (gdb_stdlog, "-> ");
- fprint_frame (gdb_stdlog, NULL);
- fprintf_unfiltered (gdb_stdlog, "// inside entry func }\n");
- }
+ frame_debug_got_null_frame (gdb_stdlog, this_frame, "inside entry func");
return NULL;
}
- /* Only try to do the unwind once. */
- if (this_frame->prev_p)
- {
- if (frame_debug)
- {
- fprintf_unfiltered (gdb_stdlog, "-> ");
- fprint_frame (gdb_stdlog, this_frame->prev);
- fprintf_unfiltered (gdb_stdlog, " // cached \n");
- }
- return this_frame->prev;
- }
- this_frame->prev_p = 1;
-
/* If we're inside the entry file, it isn't valid. Don't apply this
test to a dummy frame - dummy frame PC's typically land in the
entry file. Don't apply this test to the sentinel frame.
&& this_frame->type != DUMMY_FRAME && this_frame->level >= 0
&& deprecated_inside_entry_file (get_frame_pc (this_frame)))
{
- if (frame_debug)
- {
- fprintf_unfiltered (gdb_stdlog, "-> ");
- fprint_frame (gdb_stdlog, NULL);
- fprintf_unfiltered (gdb_stdlog, " // inside entry file }\n");
- }
+ frame_debug_got_null_frame (gdb_stdlog, this_frame, "inside entry file");
return NULL;
}
- /* If any of the old frame initialization methods are around, use
- the legacy get_prev_frame method. */
- if (legacy_frame_p (current_gdbarch))
- {
- prev_frame = legacy_get_prev_frame (this_frame);
- return prev_frame;
- }
-
- /* Check that this frame's ID was valid. If it wasn't, don't try to
- unwind to the prev frame. Be careful to not apply this test to
- the sentinel frame. */
- if (this_frame->level >= 0 && !frame_id_p (get_frame_id (this_frame)))
- {
- if (frame_debug)
- {
- fprintf_unfiltered (gdb_stdlog, "-> ");
- fprint_frame (gdb_stdlog, NULL);
- fprintf_unfiltered (gdb_stdlog, " // this ID is NULL }\n");
- }
- return NULL;
- }
-
- /* Check that this frame's ID isn't inner to (younger, below, next)
- the next frame. This happens when a frame unwind goes backwards.
- Since the sentinel frame doesn't really exist, don't compare the
- inner-most against that sentinel. */
- if (this_frame->level > 0
- && frame_id_inner (get_frame_id (this_frame),
- get_frame_id (this_frame->next)))
- error ("Previous frame inner to this frame (corrupt stack?)");
-
- /* Check that this and the next frame are not identical. If they
- are, there is most likely a stack cycle. As with the inner-than
- test above, avoid comparing the inner-most and sentinel frames. */
- if (this_frame->level > 0
- && frame_id_eq (get_frame_id (this_frame),
- get_frame_id (this_frame->next)))
- error ("Previous frame identical to this frame (corrupt stack?)");
-
- /* Allocate the new frame but do not wire it in to the frame chain.
- Some (bad) code in INIT_FRAME_EXTRA_INFO tries to look along
- frame->next to pull some fancy tricks (of course such code is, by
- definition, recursive). Try to prevent it.
-
- There is no reason to worry about memory leaks, should the
- remainder of the function fail. The allocated memory will be
- quickly reclaimed when the frame cache is flushed, and the `we've
- been here before' check above will stop repeated memory
- allocation calls. */
- prev_frame = FRAME_OBSTACK_ZALLOC (struct frame_info);
- prev_frame->level = this_frame->level + 1;
-
- /* Don't yet compute ->unwind (and hence ->type). It is computed
- on-demand in get_frame_type, frame_register_unwind, and
- get_frame_id. */
-
- /* Don't yet compute the frame's ID. It is computed on-demand by
- get_frame_id(). */
-
- /* The unwound frame ID is validate at the start of this function,
- as part of the logic to decide if that frame should be further
- unwound, and not here while the prev frame is being created.
- Doing this makes it possible for the user to examine a frame that
- has an invalid frame ID.
-
- Some very old VAX code noted: [...] For the sake of argument,
- suppose that the stack is somewhat trashed (which is one reason
- that "info frame" exists). So, return 0 (indicating we don't
- know the address of the arglist) if we don't know what frame this
- frame calls. */
-
- /* Link it in. */
- this_frame->prev = prev_frame;
- prev_frame->next = this_frame;
-
- if (frame_debug)
- {
- fprintf_unfiltered (gdb_stdlog, "-> ");
- fprint_frame (gdb_stdlog, prev_frame);
- fprintf_unfiltered (gdb_stdlog, " }\n");
- }
-
- return prev_frame;
+ return get_prev_frame_1 (this_frame);
}
CORE_ADDR
frame after a frame cache flush (and other similar operations). If
FI is NULL, return the null_frame_id. */
extern struct frame_id get_frame_id (struct frame_info *fi);
+extern struct frame_id frame_unwind_id (struct frame_info *next_frame);
/* Assuming that a frame is `normal', return its base-address, or 0 if
the information isn't available. NOTE: This address is really only
/* Set the return address. */
regcache_cooked_write_unsigned (regcache, RP_REGNUM, bp_addr);
+ /* Update the Stack Pointer. */
+ regcache_cooked_write_unsigned (regcache, SP_REGNUM, param_end + 32);
+
/* The stack will have 32 bytes of additional space for a frame marker. */
return param_end + 32;
}
/* Set the return address. */
regcache_cooked_write_unsigned (regcache, RP_REGNUM, bp_addr);
+ /* Update the Stack Pointer. */
+ regcache_cooked_write_unsigned (regcache, SP_REGNUM, param_end + 64);
+
/* The stack will have 32 bytes of additional space for a frame marker. */
return param_end + 64;
}
return NULL;
}
+
+/* FIXME: jimb/2004-04-01: I don't think these functions are right.
+ For a given platform, GCC always uses the same register numbering
+ in both STABS and Dwarf2: gcc/dbxout.c and gcc/dwarf2out.c both use
+ the DBX_REGISTER_NUMBER macro, as defined by the config headers.
+ If you compile a program so that its variables are allocated to
+ floating-point registers, first with STABS and again with Dwarf 2,
+ you'll see that the variable's register numbers are the same in
+ each case.
+
+ GCC does use (at least) two different register numberings on the
+ i386; they differ in how they number %ebp, %esp, %eflags, and the
+ floating-point registers. And it has a third numbering for "64bit
+ mode", which I assume is x86_64. But it always uses a given
+ numbering in both STABS and Dwarf.
+
+ This does not match the arrangement we have below, which presumes
+ that STABS and Dwarf numberings are different, and does some
+ strange mixing and matching (e.g., registering the Dwarf 2 function
+ as the STABS function for "Generic i386 ELF") to get close enough
+ to the right effect on the platforms we care about.
+
+ If we wanted to match GCC, we should have two separate register
+ number translation functions (we handle x86_64 in a separate tdep
+ file altogether), one corresponding to each of GCC's i386 register
+ maps. And for a given platform, we would register one of them as
+ both the STABS and Dwarf 2 functions.
+
+ However, we don't aspire to match GCC; we aspire to match the
+ native system's tools. I don't have access to lots of different
+ native compilers and debuggers to verify that GCC is matching their
+ behavior in this regard. Is it sufficient to argue that we at
+ least want to match GNU's compiler, and say we'll fix bugs relative
+ to native tools as they're reported? */
+
+
/* Convert stabs register number REG to the appropriate register
number used by GDB. */
sr_id = get_frame_id (get_current_frame ());
}
else
- sr_id = get_frame_id (get_prev_frame (get_current_frame ()));
+ sr_id = frame_unwind_id (get_current_frame ());
step_resume_breakpoint = set_momentary_breakpoint (sr_sal, sr_id, bp_step_resume);
/* Multi-threaded debugging support for GNU/Linux (LWP layer).
- Copyright 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ Copyright 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
This file is part of GDB.
memset (lp, 0, sizeof (struct lwp_info));
+ lp->waitstatus.kind = TARGET_WAITKIND_IGNORE;
+
lp->ptid = ptid;
lp->next = lwp_list;
void
lin_lwp_attach_lwp (ptid_t ptid, int verbose)
{
- struct lwp_info *lp;
+ struct lwp_info *lp, *found_lp;
gdb_assert (is_lwp (ptid));
if (verbose)
printf_filtered ("[New %s]\n", target_pid_to_str (ptid));
- lp = find_lwp_pid (ptid);
+ found_lp = lp = find_lwp_pid (ptid);
if (lp == NULL)
lp = add_lwp (ptid);
- /* We assume that we're already attached to any LWP that has an
- id equal to the overall process id. */
- if (GET_LWP (ptid) != GET_PID (ptid))
+ /* We assume that we're already attached to any LWP that has an id
+ equal to the overall process id, and to any LWP that is already
+ in our list of LWPs. If we're not seeing exit events from threads
+ and we've had PID wraparound since we last tried to stop all threads,
+ this assumption might be wrong; fortunately, this is very unlikely
+ to happen. */
+ if (GET_LWP (ptid) != GET_PID (ptid) && found_lp == NULL)
{
pid_t pid;
int status;
return kill (lwpid, signo);
}
+/* Handle a GNU/Linux extended wait response. Most of the work we
+ just pass off to linux_handle_extended_wait, but if it reports a
+ clone event we need to add the new LWP to our list (and not report
+ the trap to higher layers). This function returns non-zero if
+ the event should be ignored and we should wait again. */
+
+static int
+lin_lwp_handle_extended (struct lwp_info *lp, int status)
+{
+ linux_handle_extended_wait (GET_LWP (lp->ptid), status,
+ &lp->waitstatus);
+
+ /* TARGET_WAITKIND_SPURIOUS is used to indicate clone events. */
+ if (lp->waitstatus.kind == TARGET_WAITKIND_SPURIOUS)
+ {
+ struct lwp_info *new_lp;
+ new_lp = add_lwp (BUILD_LWP (lp->waitstatus.value.related_pid,
+ GET_PID (inferior_ptid)));
+ new_lp->cloned = 1;
+ new_lp->stopped = 1;
+
+ lp->waitstatus.kind = TARGET_WAITKIND_IGNORE;
+
+ if (debug_lin_lwp)
+ fprintf_unfiltered (gdb_stdlog,
+ "LLHE: Got clone event from LWP %ld, resuming\n",
+ GET_LWP (lp->ptid));
+ ptrace (PTRACE_CONT, GET_LWP (lp->ptid), 0, 0);
+
+ return 1;
+ }
+
+ return 0;
+}
+
/* Wait for LP to stop. Returns the wait status, or 0 if the LWP has
exited. */
pid = waitpid (GET_LWP (lp->ptid), &status, __WCLONE);
if (pid == -1 && errno == ECHILD)
{
- /* The thread has previously exited. We need to delete it now
- because in the case of NPTL threads, there won't be an
- exit event unless it is the main thread. */
+ /* The thread has previously exited. We need to delete it
+ now because, for some vendor 2.4 kernels with NPTL
+ support backported, there won't be an exit event unless
+ it is the main thread. 2.6 kernels will report an exit
+ event for each thread that exits, as expected. */
thread_dead = 1;
if (debug_lin_lwp)
fprintf_unfiltered (gdb_stdlog, "WL: %s vanished.\n",
gdb_assert (WIFSTOPPED (status));
+ /* Handle GNU/Linux's extended waitstatus for trace events. */
+ if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP && status >> 16 != 0)
+ {
+ if (debug_lin_lwp)
+ fprintf_unfiltered (gdb_stdlog,
+ "WL: Handling extended status 0x%06x\n",
+ status);
+ if (lin_lwp_handle_extended (lp, status))
+ return wait_lwp (lp);
+ }
+
return status;
}
int status;
pid_t pid;
+ ourstatus->kind = TARGET_WAITKIND_IGNORE;
+
do
{
set_sigint_trap (); /* Causes SIGINT to be passed on to the
save_errno = EINTR;
}
+ /* Handle GNU/Linux's extended waitstatus for trace events. */
+ if (pid != -1 && WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP
+ && status >> 16 != 0)
+ {
+ linux_handle_extended_wait (pid, status, ourstatus);
+
+ /* If we see a clone event, detach the child, and don't
+ report the event. It would be nice to offer some way to
+ switch into a non-thread-db based threaded mode at this
+ point. */
+ if (ourstatus->kind == TARGET_WAITKIND_SPURIOUS)
+ {
+ ptrace (PTRACE_DETACH, ourstatus->value.related_pid, 0, 0);
+ ourstatus->kind = TARGET_WAITKIND_IGNORE;
+ pid = -1;
+ save_errno = EINTR;
+ }
+ }
+
clear_sigio_trap ();
clear_sigint_trap ();
}
return minus_one_ptid;
}
- /* Handle GNU/Linux's extended waitstatus for trace events. */
- if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP && status >> 16 != 0)
- return linux_handle_extended_wait (pid, status, ourstatus);
+ if (ourstatus->kind == TARGET_WAITKIND_IGNORE)
+ store_waitstatus (ourstatus, status);
- store_waitstatus (ourstatus, status);
return pid_to_ptid (pid);
}
}
}
+ /* Handle GNU/Linux's extended waitstatus for trace events. */
+ if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP && status >> 16 != 0)
+ {
+ if (debug_lin_lwp)
+ fprintf_unfiltered (gdb_stdlog,
+ "LLW: Handling extended status 0x%06x\n",
+ status);
+ if (lin_lwp_handle_extended (lp, status))
+ {
+ status = 0;
+ continue;
+ }
+ }
+
/* Check if the thread has exited. */
if ((WIFEXITED (status) || WIFSIGNALED (status)) && num_lwps > 1)
{
else
trap_ptid = null_ptid;
- /* Handle GNU/Linux's extended waitstatus for trace events. */
- if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP && status >> 16 != 0)
+ if (lp->waitstatus.kind != TARGET_WAITKIND_IGNORE)
{
- linux_handle_extended_wait (GET_LWP (lp->ptid), status, ourstatus);
- return trap_ptid;
+ *ourstatus = lp->waitstatus;
+ lp->waitstatus.kind = TARGET_WAITKIND_IGNORE;
}
+ else
+ store_waitstatus (ourstatus, status);
- store_waitstatus (ourstatus, status);
return (threaded ? lp->ptid : pid_to_ptid (GET_LWP (lp->ptid)));
}
/* GNU/Linux native-dependent code common to multiple platforms.
- Copyright (C) 2003 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
This file is part of GDB.
if (! linux_supports_tracefork ())
return;
- options = PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACEEXEC;
+ options = PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACEEXEC
+ | PTRACE_O_TRACECLONE;
if (linux_supports_tracevforkdone ())
options |= PTRACE_O_TRACEVFORKDONE;
{
int event = status >> 16;
- if (event == PTRACE_EVENT_CLONE)
- internal_error (__FILE__, __LINE__,
- "unexpected clone event");
-
- if (event == PTRACE_EVENT_FORK || event == PTRACE_EVENT_VFORK)
+ if (event == PTRACE_EVENT_FORK || event == PTRACE_EVENT_VFORK
+ || event == PTRACE_EVENT_CLONE)
{
unsigned long new_pid;
int ret;
if (! pull_pid_from_list (&stopped_pids, new_pid))
{
/* The new child has a pending SIGSTOP. We can't affect it until it
- hits the SIGSTOP, but we're already attached.
-
- It won't be a clone (we didn't ask for clones in the event mask)
- so we can just call waitpid and wait for the SIGSTOP. */
+ hits the SIGSTOP, but we're already attached. */
do {
- ret = waitpid (new_pid, &status, 0);
+ ret = waitpid (new_pid, &status,
+ (event == PTRACE_EVENT_CLONE) ? __WCLONE : 0);
} while (ret == -1 && errno == EINTR);
if (ret == -1)
perror_with_name ("waiting for new child");
"wait returned unexpected status 0x%x", status);
}
- ourstatus->kind = (event == PTRACE_EVENT_FORK)
- ? TARGET_WAITKIND_FORKED : TARGET_WAITKIND_VFORKED;
+ if (event == PTRACE_EVENT_FORK)
+ ourstatus->kind = TARGET_WAITKIND_FORKED;
+ else if (event == PTRACE_EVENT_VFORK)
+ ourstatus->kind = TARGET_WAITKIND_VFORKED;
+ else
+ ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
+
ourstatus->value.related_pid = new_pid;
return inferior_ptid;
}
/* Native debugging support for GNU/Linux (LWP layer).
- Copyright 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ Copyright 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
This file is part of GDB.
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+#include "target.h"
+
/* Structure describing an LWP. */
struct lwp_info
/* Non-zero if we were stepping this LWP. */
int step;
+ /* If WAITSTATUS->KIND != TARGET_WAITKIND_SPURIOUS, the waitstatus
+ for this LWP's last event. This may correspond to STATUS above,
+ or to a local variable in lin_lwp_wait. */
+ struct target_waitstatus waitstatus;
+
/* Next LWP in list. */
struct lwp_info *next;
};
system". */
struct mem_attrib;
struct target_ops;
-struct target_waitstatus;
extern int linux_proc_xfer_memory (CORE_ADDR addr, char *myaddr, int len,
int write, struct mem_attrib *attrib,
struct msym_bunch *new;
struct minimal_symbol *msymbol;
- if (ms_type == mst_file_text)
- {
- /* Don't put gcc_compiled, __gnu_compiled_cplus, and friends into
- the minimal symbols, because if there is also another symbol
- at the same address (e.g. the first function of the file),
- lookup_minimal_symbol_by_pc would have no way of getting the
- right one. */
- if (name[0] == 'g'
- && (strcmp (name, GCC_COMPILED_FLAG_SYMBOL) == 0
- || strcmp (name, GCC2_COMPILED_FLAG_SYMBOL) == 0))
- return (NULL);
-
- {
- const char *tempstring = name;
- if (tempstring[0] == get_symbol_leading_char (objfile->obfd))
- ++tempstring;
- if (strncmp (tempstring, "__gnu_compiled", 14) == 0)
- return (NULL);
- }
- }
+ /* Don't put gcc_compiled, __gnu_compiled_cplus, and friends into
+ the minimal symbols, because if there is also another symbol
+ at the same address (e.g. the first function of the file),
+ lookup_minimal_symbol_by_pc would have no way of getting the
+ right one. */
+ if (ms_type == mst_file_text && name[0] == 'g'
+ && (strcmp (name, GCC_COMPILED_FLAG_SYMBOL) == 0
+ || strcmp (name, GCC2_COMPILED_FLAG_SYMBOL) == 0))
+ return (NULL);
+
+ /* It's safe to strip the leading char here once, since the name
+ is also stored stripped in the minimal symbol table. */
+ if (name[0] == get_symbol_leading_char (objfile->obfd))
+ ++name;
+
+ if (ms_type == mst_file_text && strncmp (name, "__gnu_compiled", 14) == 0)
+ return (NULL);
if (msym_bunch_index == BUNCH_SIZE)
{
struct msym_bunch *bunch;
struct minimal_symbol *msymbols;
int alloc_count;
- char leading_char;
if (msym_count > 0)
{
each bunch is full. */
mcount = objfile->minimal_symbol_count;
- leading_char = get_symbol_leading_char (objfile->obfd);
for (bunch = msym_bunch; bunch != NULL; bunch = bunch->next)
{
for (bindex = 0; bindex < msym_bunch_index; bindex++, mcount++)
- {
- msymbols[mcount] = bunch->contents[bindex];
- if (SYMBOL_LINKAGE_NAME (&msymbols[mcount])[0] == leading_char)
- {
- SYMBOL_LINKAGE_NAME (&msymbols[mcount])++;
- }
- }
+ msymbols[mcount] = bunch->contents[bindex];
msym_bunch_index = BUNCH_SIZE;
}
#include "frame-base.h"
#include "trad-frame.h"
+static const struct objfile_data *mips_pdr_data;
+
static void set_reg_offset (CORE_ADDR *saved_regs, int regnum, CORE_ADDR off);
static struct type *mips_register_type (struct gdbarch *gdbarch, int regnum);
sec = find_pc_section (pc);
if (sec != NULL)
{
- priv = (struct mips_objfile_private *) sec->objfile->obj_private;
+ priv = (struct mips_objfile_private *) objfile_data (sec->objfile, mips_pdr_data);
/* Search the ".pdr" section generated by GAS. This includes most of
the information normally found in ECOFF PDRs. */
priv = obstack_alloc (&sec->objfile->objfile_obstack,
sizeof (struct mips_objfile_private));
priv->size = 0;
- sec->objfile->obj_private = priv;
+ set_objfile_data (sec->objfile, mips_pdr_data, priv);
}
else if (priv == NULL)
{
else
priv->size = 0;
- sec->objfile->obj_private = priv;
+ set_objfile_data (sec->objfile, mips_pdr_data, priv);
}
the_bfd = NULL;
gdbarch_register (bfd_arch_mips, mips_gdbarch_init, mips_dump_tdep);
+ mips_pdr_data = register_objfile_data ();
+
/* Add root prefix command for all "set mips"/"show mips" commands */
add_prefix_cmd ("mips", no_class, set_mips_command,
"Various MIPS specific commands.",
/* store parameters in stack */
}
+ /* Move parameters from argument registers to temporary register. */
+ else if ((op & 0xfc0007fe) == 0x7c000378 && /* mr(.) Rx,Ry */
+ (((op >> 21) & 31) >= 3) && /* R3 >= Ry >= R10 */
+ (((op >> 21) & 31) <= 10) &&
+ (((op >> 16) & 31) == 0)) /* Rx: scratch register r0 */
+ {
+ continue;
+ }
else if ((op & 0xfc1f0003) == 0xf8010000 || /* std rx,NUM(r1) */
(op & 0xfc1f0000) == 0xd8010000 || /* stfd Rx,NUM(r1) */
(op & 0xfc1f0000) == 0xfc010000) /* frsp, fp?,NUM(r1) */
/* store parameters in stack via frame pointer */
}
else if (framep &&
- ((op & 0xfc1f0000) == 0x901f0000 || /* st rx,NUM(r1) */
- (op & 0xfc1f0000) == 0xd81f0000 || /* stfd Rx,NUM(r1) */
- (op & 0xfc1f0000) == 0xfc1f0000))
- { /* frsp, fp?,NUM(r1) */
+ ((op & 0xfc1f0000) == 0x901f0000 || /* st rx,NUM(r31) */
+ (op & 0xfc1f0000) == 0x981f0000 || /* stb Rx,NUM(r31) */
+ (op & 0xfc1f0000) == 0xd81f0000 || /* stfd Rx,NUM(r31) */
+ (op & 0xfc1f0000) == 0xfc1f0000)) /* frsp, fp?,NUM(r31) */
+ {
continue;
/* Set up frame pointer */
}
}
-/* Convert a dwarf2 register number to a gdb REGNUM. */
+/* Convert a dbx stab or Dwarf 2 register number (from `r'
+ declaration) to a gdb REGNUM. */
static int
-e500_dwarf2_reg_to_regnum (int num)
+rs6000_dwarf2_stab_reg_to_regnum (int num)
{
- int regnum;
- if (0 <= num && num <= 31)
- return num + gdbarch_tdep (current_gdbarch)->ppc_gp0_regnum;
- else
- return num;
-}
+ struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
-/* Convert a dbx stab register number (from `r' declaration) to a gdb
- REGNUM. */
-static int
-rs6000_stab_reg_to_regnum (int num)
-{
- int regnum;
- switch (num)
- {
- case 64:
- regnum = gdbarch_tdep (current_gdbarch)->ppc_mq_regnum;
- break;
- case 65:
- regnum = gdbarch_tdep (current_gdbarch)->ppc_lr_regnum;
- break;
- case 66:
- regnum = gdbarch_tdep (current_gdbarch)->ppc_ctr_regnum;
- break;
- case 76:
- regnum = gdbarch_tdep (current_gdbarch)->ppc_xer_regnum;
- break;
- default:
- regnum = num;
- break;
- }
- return regnum;
+ if (0 <= num && num <= 31)
+ return tdep->ppc_gp0_regnum + num;
+ else if (32 <= num && num <= 63)
+ return FP0_REGNUM + (num - 32);
+ else if (1200 <= num && num < 1200 + 32)
+ return tdep->ppc_ev0_regnum + (num - 1200);
+ else
+ switch (num)
+ {
+ case 64:
+ return tdep->ppc_mq_regnum;
+ case 65:
+ return tdep->ppc_lr_regnum;
+ case 66:
+ return tdep->ppc_ctr_regnum;
+ case 76:
+ return tdep->ppc_xer_regnum;
+ case 109:
+ return tdep->ppc_vrsave_regnum;
+ default:
+ return num;
+ }
+
+ /* FIXME: jimb/2004-03-28: Doesn't something need to be done here
+ for the Altivec registers, too?
+
+ Looking at GCC, the headers in config/rs6000 never define a
+ DBX_REGISTER_NUMBER macro, so the debug info uses the same
+ numbers GCC does internally. Then, looking at the REGISTER_NAMES
+ macro defined in config/rs6000/rs6000.h, it seems that GCC gives
+ v0 -- v31 the numbers 77 -- 108. But we number them 119 -- 150.
+
+ I don't have a way to test this ready to hand, but I noticed it
+ and thought I should include a note. */
}
static void
set_gdbarch_pc_regnum (gdbarch, 0);
set_gdbarch_sp_regnum (gdbarch, tdep->ppc_gp0_regnum + 1);
set_gdbarch_deprecated_fp_regnum (gdbarch, tdep->ppc_gp0_regnum + 1);
- set_gdbarch_dwarf2_reg_to_regnum (gdbarch, e500_dwarf2_reg_to_regnum);
set_gdbarch_pseudo_register_read (gdbarch, e500_pseudo_register_read);
set_gdbarch_pseudo_register_write (gdbarch, e500_pseudo_register_write);
break;
set_gdbarch_deprecated_register_convertible (gdbarch, rs6000_register_convertible);
set_gdbarch_deprecated_register_convert_to_virtual (gdbarch, rs6000_register_convert_to_virtual);
set_gdbarch_deprecated_register_convert_to_raw (gdbarch, rs6000_register_convert_to_raw);
- set_gdbarch_stab_reg_to_regnum (gdbarch, rs6000_stab_reg_to_regnum);
+ set_gdbarch_stab_reg_to_regnum (gdbarch, rs6000_dwarf2_stab_reg_to_regnum);
+ set_gdbarch_dwarf2_reg_to_regnum (gdbarch, rs6000_dwarf2_stab_reg_to_regnum);
/* Note: kevinb/2002-04-12: I'm not convinced that rs6000_push_arguments()
is correct for the SysV ABI when the wordsize is 8, but I'm also
fairly certain that ppc_sysv_abi_push_arguments() will give even
+2004-04-01 Joel Brobecker <brobecker@gnat.com>
+
+ * lib/ada.exp: Add copyright notice.
+ * bar.ads: Likewise.
+ * bar.adb: Likewise.
+ * null_record.adb: Likewise.
+ * null_record.exp: Likewise.
+ * gnat_ada.gpr.in: Likewise. Fix typo in a comment, clarify another.
+
+2004-04-01 Joel Brobecker <brobecker@gnat.com>
+
+ * configure.in: Generate gdb.ada/Makefile and gdb.ada/gnat_ada.gpr.
+ * configure: Regenerate.
+
+2004-04-01 Joel Brobecker <brobecker@gnat.com>
+
+ * lib/ada.exp (gdb_compile_ada): Emit UNSUPPORTED if we failed
+ to build the application. Remove the message printed when in
+ verbose mode, redundant with the UNSUPPORTED message above.
+
+2004-03-31 Joel Brobecker <brobecker@gnat.com>
+
+ * gdb.ada (bar.ads, bar.adb, null_record.adb): New files.
+ * gdb.ada (null_record.exp): New testcase.
+
+2004-03-31 Joel Brobecker <brobecker@gnat.com>
+
+ * Makefile.in (ALL_SUBDIRS) Add gdb.ada.
+
+2004-03-31 Joel Brobecker <brobecker@gnat.com>
+
+ * gdb.ada: New subdirectory.
+ * gdb.ada/Makefile.in: New file.
+ * gdb.ada/gnat_ada.gpr.in: New file.
+
+2004-03-31 Joel Brobecker <brobecker@gnat.com>
+
+ * lib/ada.exp: New file.
+
2004-03-24 Daniel Jacobowitz <drow@mvista.com>
* gdb.base/gdb1250.exp: Use runto {allow-pending}.
EXEEXT = @EXEEXT@
SUBDIRS = @subdirs@
RPATH_ENVVAR = @RPATH_ENVVAR@
-ALL_SUBDIRS = gdb.arch gdb.asm gdb.base gdb.cp gdb.disasm gdb.java gdb.mi \
- gdb.objc gdb.threads gdb.trace $(SUBDIRS)
+ALL_SUBDIRS = gdb.ada gdb.arch gdb.asm gdb.base gdb.cp gdb.disasm \
+ gdb.java gdb.mi gdb.objc gdb.threads gdb.trace $(SUBDIRS)
EXPECT = `if [ -f $${rootme}/../../expect/expect ] ; then \
echo $${rootme}/../../expect/expect ; \
if { (eval echo configure:918: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
for file in conftest.*; do
case $file in
- *.c | *.C | *.o | *.obj | *.ilk | *.pdb) ;;
+ *.c | *.o | *.obj | *.ilk | *.pdb) ;;
*) ac_cv_exeext=`echo $file | sed -e s/conftest//` ;;
esac
done
ac_given_srcdir=$srcdir
-trap 'rm -fr `echo "Makefile gdb.arch/Makefile gdb.asm/Makefile gdb.base/Makefile \
+trap 'rm -fr `echo "Makefile gdb.ada/Makefile gdb.ada/gnat_ada.gpr \
+ gdb.arch/Makefile gdb.asm/Makefile gdb.base/Makefile \
gdb.cp/Makefile gdb.disasm/Makefile gdb.java/Makefile gdb.mi/Makefile \
gdb.objc/Makefile gdb.threads/Makefile gdb.trace/Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
EOF
cat >> $CONFIG_STATUS <<EOF
-CONFIG_FILES=\${CONFIG_FILES-"Makefile gdb.arch/Makefile gdb.asm/Makefile gdb.base/Makefile \
+CONFIG_FILES=\${CONFIG_FILES-"Makefile gdb.ada/Makefile gdb.ada/gnat_ada.gpr \
+ gdb.arch/Makefile gdb.asm/Makefile gdb.base/Makefile \
gdb.cp/Makefile gdb.disasm/Makefile gdb.java/Makefile gdb.mi/Makefile \
gdb.objc/Makefile gdb.threads/Makefile gdb.trace/Makefile"}
EOF
AC_EXEEXT
AC_CONFIG_SUBDIRS($configdirs)
-AC_OUTPUT([Makefile gdb.arch/Makefile gdb.asm/Makefile gdb.base/Makefile \
+AC_OUTPUT([Makefile gdb.ada/Makefile gdb.ada/gnat_ada.gpr \
+ gdb.arch/Makefile gdb.asm/Makefile gdb.base/Makefile \
gdb.cp/Makefile gdb.disasm/Makefile gdb.java/Makefile gdb.mi/Makefile \
gdb.objc/Makefile gdb.threads/Makefile gdb.trace/Makefile])
/* libthread_db assisted debugging support, generic parts.
- Copyright 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
+ Copyright 1999, 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
This file is part of GDB.
#include "regcache.h"
#include "solib-svr4.h"
+#ifdef HAVE_GNU_LIBC_VERSION_H
+#include <gnu/libc-version.h>
+#endif
+
#ifndef LIBTHREAD_DB_SO
#define LIBTHREAD_DB_SO "libthread_db.so.1"
#endif
static void thread_db_find_new_threads (void);
static void attach_thread (ptid_t ptid, const td_thrhandle_t *th_p,
const td_thrinfo_t *ti_p, int verbose);
+static void detach_thread (ptid_t ptid, int verbose);
\f
/* Building process ids. */
struct private_thread_info
{
+ /* Flag set when we see a TD_DEATH event for this thread. */
+ unsigned int dying:1;
+
/* Cached thread state. */
unsigned int th_valid:1;
unsigned int ti_valid:1;
td_thr_events_t events;
td_notify_t notify;
td_err_e err;
+#ifdef HAVE_GNU_LIBC_VERSION_H
+ const char *libc_version;
+ int libc_major, libc_minor;
+#endif
/* We cannot use the thread event reporting facility if these
functions aren't available. */
/* Set the process wide mask saying which events we're interested in. */
td_event_emptyset (&events);
td_event_addset (&events, TD_CREATE);
-#if 0
+
+#ifdef HAVE_GNU_LIBC_VERSION_H
/* FIXME: kettenis/2000-04-23: The event reporting facility is
broken for TD_DEATH events in glibc 2.1.3, so don't enable it for
now. */
- td_event_addset (&events, TD_DEATH);
+ libc_version = gnu_get_libc_version ();
+ if (sscanf (libc_version, "%d.%d", &libc_major, &libc_minor) == 2
+ && (libc_major > 2 || (libc_major == 2 && libc_minor > 1)))
#endif
+ td_event_addset (&events, TD_DEATH);
err = td_ta_set_event_p (thread_agent, &events);
if (err != TD_OK)
target_new_objfile_chain (objfile);
}
+/* Attach to a new thread. This function is called when we receive a
+ TD_CREATE event or when we iterate over all threads and find one
+ that wasn't already in our list. */
+
static void
attach_thread (ptid_t ptid, const td_thrhandle_t *th_p,
const td_thrinfo_t *ti_p, int verbose)
struct thread_info *tp;
td_err_e err;
+ /* If we're being called after a TD_CREATE event, we may already
+ know about this thread. There are two ways this can happen. We
+ may have iterated over all threads between the thread creation
+ and the TD_CREATE event, for instance when the user has issued
+ the `info threads' command before the SIGTRAP for hitting the
+ thread creation breakpoint was reported. Alternatively, the
+ thread may have exited and a new one been created with the same
+ thread ID. In the first case we don't need to do anything; in
+ the second case we should discard information about the dead
+ thread and attach to the new one. */
+ if (in_thread_list (ptid))
+ {
+ tp = find_thread_pid (ptid);
+ gdb_assert (tp != NULL);
+
+ if (!tp->private->dying)
+ return;
+
+ delete_thread (ptid);
+ }
+
check_thread_signals ();
/* Add the thread to GDB's thread list. */
static void
detach_thread (ptid_t ptid, int verbose)
{
+ struct thread_info *thread_info;
+
if (verbose)
printf_unfiltered ("[%s exited]\n", target_pid_to_str (ptid));
+
+ /* Don't delete the thread now, because it still reports as active
+ until it has executed a few instructions after the event
+ breakpoint - if we deleted it now, "info threads" would cause us
+ to re-attach to it. Just mark it as having had a TD_DEATH
+ event. This means that we won't delete it from our thread list
+ until we notice that it's dead (via prune_threads), or until
+ something re-uses its thread ID. */
+ thread_info = find_thread_pid (ptid);
+ gdb_assert (thread_info != NULL);
+ thread_info->private->dying = 1;
}
static void
switch (msg.event)
{
case TD_CREATE:
-
- /* We may already know about this thread, for instance when the
- user has issued the `info threads' command before the SIGTRAP
- for hitting the thread creation breakpoint was reported. */
- if (!in_thread_list (ptid))
- attach_thread (ptid, msg.th_p, &ti, 1);
+ /* Call attach_thread whether or not we already know about a
+ thread with this thread ID. */
+ attach_thread (ptid, msg.th_p, &ti, 1);
break;
tui_show_registers (struct reggroup *group)
{
enum tui_status ret = TUI_FAILURE;
- struct tui_data_info *display_info = &TUI_DATA_WIN->detail.data_display_info;
+ struct tui_data_info *display_info;
+
+ /* Make sure the curses mode is enabled. */
+ tui_enable ();
+
+ /* Make sure the register window is visible. If not, select an
+ appropriate layout. */
+ if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->generic.is_visible)
+ tui_set_layout_for_display_command (DATA_NAME);
+ display_info = &TUI_DATA_WIN->detail.data_display_info;
if (group == 0)
group = general_reggroup;
int ans2;
int retval;
- va_start (args, ctlstr);
-
if (query_hook)
{
+ va_start (args, ctlstr);
return query_hook (ctlstr, args);
}
if (annotation_level > 1)
printf_filtered ("\n\032\032pre-query\n");
+ va_start (args, ctlstr);
vfprintf_filtered (gdb_stdout, ctlstr, args);
+ va_end (args);
printf_filtered ("(y or n) ");
if (annotation_level > 1)
/* Perform arithmetic and other operations on values, for GDB.
Copyright 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
- 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software
+ 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
Foundation, Inc.
This file is part of GDB.
LONGEST sz;
struct type *type1, *type2, *valptrtype;
- COERCE_NUMBER (arg1);
- COERCE_NUMBER (arg2);
+ COERCE_ARRAY (arg1);
+ COERCE_ARRAY (arg2);
type1 = check_typedef (VALUE_TYPE (arg1));
type2 = check_typedef (VALUE_TYPE (arg2));
if ((TYPE_CODE (type1) == TYPE_CODE_PTR
|| TYPE_CODE (type2) == TYPE_CODE_PTR)
&&
- (TYPE_CODE (type1) == TYPE_CODE_INT
- || TYPE_CODE (type2) == TYPE_CODE_INT))
+ (is_integral_type (type1) || is_integral_type (type2)))
/* Exactly one argument is a pointer, and one is an integer. */
{
struct value *retval;
value_sub (struct value *arg1, struct value *arg2)
{
struct type *type1, *type2;
- COERCE_NUMBER (arg1);
- COERCE_NUMBER (arg2);
+ COERCE_ARRAY (arg1);
+ COERCE_ARRAY (arg2);
type1 = check_typedef (VALUE_TYPE (arg1));
type2 = check_typedef (VALUE_TYPE (arg2));
if (TYPE_CODE (type1) == TYPE_CODE_PTR)
{
- if (TYPE_CODE (type2) == TYPE_CODE_INT)
+ if (is_integral_type (type2))
{
/* pointer - integer. */
LONGEST sz = find_size_for_pointer_math (type1);
COERCE_REF (arg1);
COERCE_REF (arg2);
- COERCE_ENUM (arg1);
- COERCE_ENUM (arg2);
type1 = check_typedef (VALUE_TYPE (arg1));
type2 = check_typedef (VALUE_TYPE (arg2));
- if ((TYPE_CODE (type1) != TYPE_CODE_FLT
- && TYPE_CODE (type1) != TYPE_CODE_CHAR
- && TYPE_CODE (type1) != TYPE_CODE_INT
- && TYPE_CODE (type1) != TYPE_CODE_BOOL
- && TYPE_CODE (type1) != TYPE_CODE_RANGE)
+ if ((TYPE_CODE (type1) != TYPE_CODE_FLT && !is_integral_type (type1))
||
- (TYPE_CODE (type2) != TYPE_CODE_FLT
- && TYPE_CODE (type2) != TYPE_CODE_CHAR
- && TYPE_CODE (type2) != TYPE_CODE_INT
- && TYPE_CODE (type2) != TYPE_CODE_BOOL
- && TYPE_CODE (type2) != TYPE_CODE_RANGE))
+ (TYPE_CODE (type2) != TYPE_CODE_FLT && !is_integral_type (type2)))
error ("Argument to arithmetic operation not a number or boolean.");
if (TYPE_CODE (type1) == TYPE_CODE_FLT
struct type *type1, *type2;
enum type_code code1;
enum type_code code2;
+ int is_int1, is_int2;
- COERCE_NUMBER (arg1);
- COERCE_NUMBER (arg2);
+ COERCE_ARRAY (arg1);
+ COERCE_ARRAY (arg2);
type1 = check_typedef (VALUE_TYPE (arg1));
type2 = check_typedef (VALUE_TYPE (arg2));
code1 = TYPE_CODE (type1);
code2 = TYPE_CODE (type2);
+ is_int1 = is_integral_type (type1);
+ is_int2 = is_integral_type (type2);
- if ((code1 == TYPE_CODE_INT || code1 == TYPE_CODE_BOOL) &&
- (code2 == TYPE_CODE_INT || code2 == TYPE_CODE_BOOL))
+ if (is_int1 && is_int2)
return longest_to_int (value_as_long (value_binop (arg1, arg2,
BINOP_EQUAL)));
- else if ((code1 == TYPE_CODE_FLT || code1 == TYPE_CODE_INT || code1 == TYPE_CODE_BOOL)
- && (code2 == TYPE_CODE_FLT || code2 == TYPE_CODE_INT || code2 == TYPE_CODE_BOOL))
+ else if ((code1 == TYPE_CODE_FLT || is_int1)
+ && (code2 == TYPE_CODE_FLT || is_int2))
return value_as_double (arg1) == value_as_double (arg2);
/* FIXME: Need to promote to either CORE_ADDR or LONGEST, whichever
is bigger. */
- else if (code1 == TYPE_CODE_PTR && (code2 == TYPE_CODE_INT || code2 == TYPE_CODE_BOOL))
+ else if (code1 == TYPE_CODE_PTR && is_int2)
return value_as_address (arg1) == (CORE_ADDR) value_as_long (arg2);
- else if (code2 == TYPE_CODE_PTR && (code1 == TYPE_CODE_INT || code1 == TYPE_CODE_BOOL))
+ else if (code2 == TYPE_CODE_PTR && is_int1)
return (CORE_ADDR) value_as_long (arg1) == value_as_address (arg2);
else if (code1 == code2
enum type_code code1;
enum type_code code2;
struct type *type1, *type2;
+ int is_int1, is_int2;
- COERCE_NUMBER (arg1);
- COERCE_NUMBER (arg2);
+ COERCE_ARRAY (arg1);
+ COERCE_ARRAY (arg2);
type1 = check_typedef (VALUE_TYPE (arg1));
type2 = check_typedef (VALUE_TYPE (arg2));
code1 = TYPE_CODE (type1);
code2 = TYPE_CODE (type2);
+ is_int1 = is_integral_type (type1);
+ is_int2 = is_integral_type (type2);
- if ((code1 == TYPE_CODE_INT || code1 == TYPE_CODE_BOOL) &&
- (code2 == TYPE_CODE_INT || code2 == TYPE_CODE_BOOL))
+ if (is_int1 && is_int2)
return longest_to_int (value_as_long (value_binop (arg1, arg2,
BINOP_LESS)));
- else if ((code1 == TYPE_CODE_FLT || code1 == TYPE_CODE_INT || code1 == TYPE_CODE_BOOL)
- && (code2 == TYPE_CODE_FLT || code2 == TYPE_CODE_INT || code2 == TYPE_CODE_BOOL))
+ else if ((code1 == TYPE_CODE_FLT || is_int1)
+ && (code2 == TYPE_CODE_FLT || is_int2))
return value_as_double (arg1) < value_as_double (arg2);
else if (code1 == TYPE_CODE_PTR && code2 == TYPE_CODE_PTR)
return value_as_address (arg1) < value_as_address (arg2);
/* FIXME: Need to promote to either CORE_ADDR or LONGEST, whichever
is bigger. */
- else if (code1 == TYPE_CODE_PTR && (code2 == TYPE_CODE_INT || code2 == TYPE_CODE_BOOL))
+ else if (code1 == TYPE_CODE_PTR && is_int2)
return value_as_address (arg1) < (CORE_ADDR) value_as_long (arg2);
- else if (code2 == TYPE_CODE_PTR && (code1 == TYPE_CODE_INT || code1 == TYPE_CODE_BOOL))
+ else if (code2 == TYPE_CODE_PTR && is_int1)
return (CORE_ADDR) value_as_long (arg1) < value_as_address (arg2);
else if (code1 == TYPE_CODE_STRING && code2 == TYPE_CODE_STRING)
return value_strcmp (arg1, arg2) < 0;
struct type *result_type = VALUE_TYPE (arg1);
COERCE_REF (arg1);
- COERCE_ENUM (arg1);
type = check_typedef (VALUE_TYPE (arg1));
if (TYPE_CODE (type) == TYPE_CODE_FLT)
return value_from_double (result_type, -value_as_double (arg1));
- else if (TYPE_CODE (type) == TYPE_CODE_INT || TYPE_CODE (type) == TYPE_CODE_BOOL)
+ else if (is_integral_type (type))
{
/* Perform integral promotion for ANSI C/C++. FIXME: What about
FORTRAN and (the deleted) chill ? */
{
struct type *type;
struct type *result_type = VALUE_TYPE (arg1);
- int typecode;
COERCE_REF (arg1);
- COERCE_ENUM (arg1);
type = check_typedef (VALUE_TYPE (arg1));
- typecode = TYPE_CODE (type);
- if ((typecode != TYPE_CODE_INT) && (typecode != TYPE_CODE_BOOL))
+ if (!is_integral_type (type))
error ("Argument to complement operation not an integer or boolean.");
/* Perform integral promotion for ANSI C/C++.
-2004-03-26-cvs
+2004-04-02-cvs
+2004-03-30 Zack Weinberg <zack@codesourcery.com>
+
+ * hashtab.h, splay-tree.h: Use new shorter form of GTY markers.
+
2004-03-25 Stan Shebs <shebs@apple.com>
* mpw/: Remove subdirectory and everything in it.
+2004-30-30 Galit Heller <Galit.Heller@nsc.com>
+ Tomer Levi <Tomer.Levi@nsc.com>
+
+ * common.h (EM_CR): Define.
+ * cr16c.h: New file.
+
2004-03-23 Paul Brook <paul@codesourcery.com>
* arm.h (EF_ERM_BE8, EF_ARM_LE8, EF_ARM_EABI_VER3): Add.
#define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */
#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */
#define EM_IP2K 101 /* Ubicom IP2022 micro controller */
+#define EM_CR 103 /* National Semiconductor CompactRISC */
#define EM_MSP430 105 /* TI msp430 micro controller */
/* If it is necessary to assign new unofficial EM_* values, please pick large
htab_del del_f;
/* Table itself. */
- PTR * GTY ((use_param (""), length ("%h.size"))) entries;
+ PTR * GTY ((use_param, length ("%h.size"))) entries;
/* Current size (in entries) of the hash table */
size_t size;
htab_free free_f;
/* Alternate allocate/free functions, which take an extra argument. */
- PTR GTY((skip (""))) alloc_arg;
+ PTR GTY((skip)) alloc_arg;
htab_alloc_with_arg alloc_with_arg_f;
htab_free_with_arg free_with_arg_f;
};
struct splay_tree_node_s GTY(())
{
/* The key. */
- splay_tree_key GTY ((use_param1 (""))) key;
+ splay_tree_key GTY ((use_param1)) key;
/* The value. */
- splay_tree_value GTY ((use_param2 (""))) value;
+ splay_tree_value GTY ((use_param2)) value;
/* The left and right children, respectively. */
- splay_tree_node GTY ((use_params (""))) left;
- splay_tree_node GTY ((use_params (""))) right;
+ splay_tree_node GTY ((use_params)) left;
+ splay_tree_node GTY ((use_params)) right;
};
/* The splay tree itself. */
struct splay_tree_s GTY(())
{
/* The root of the tree. */
- splay_tree_node GTY ((use_params (""))) root;
+ splay_tree_node GTY ((use_params)) root;
/* The comparision function. */
splay_tree_compare_fn comp;
/* Allocate/free functions, and a data pointer to pass to them. */
splay_tree_allocate_fn allocate;
splay_tree_deallocate_fn deallocate;
- PTR GTY((skip (""))) allocate_data;
+ PTR GTY((skip)) allocate_data;
};
typedef struct splay_tree_s *splay_tree;
+2004-03-31 Richard Henderson <rth@redhat.com>
+
+ * hashtab.c (htab_size): Move to top of file; mark inline.
+ (htab_elements): Likewise.
+ (htab_mod, htab_mod_m2): New.
+ (htab_delete): Refactor htab->size and htab->entries.
+ (htab_empty): Likewise.
+ (find_empty_slot_for_expand): Use htab_size, htab_mod, htab_mod_m2.
+ (htab_find_with_hash, htab_find_slot_with_hash): Likewise.
+ (htab_clear_slot): Use htab_size, htab_elements.
+ (htab_traverse_noresize, htab_traverse): Likewise.
+
2004-03-17 Ian Lance Taylor <ian@wasabisystems.com>
* pex-unix.c (pexecute): Use vfork instead of fork, with
return p1 == p2;
}
+/* Return the current size of given hash table. */
+
+inline size_t
+htab_size (htab)
+ htab_t htab;
+{
+ return htab->size;
+}
+
+/* Return the current number of elements in given hash table. */
+
+inline size_t
+htab_elements (htab)
+ htab_t htab;
+{
+ return htab->n_elements - htab->n_deleted;
+}
+
+/* Compute the primary hash for HASH given HTAB's current size. */
+
+static inline hashval_t
+htab_mod (hash, htab)
+ hashval_t hash;
+ htab_t htab;
+{
+ return hash % htab_size (htab);
+}
+
+/* Compute the secondary hash for HASH given HTAB's current size. */
+
+static inline hashval_t
+htab_mod_m2 (hash, htab)
+ hashval_t hash;
+ htab_t htab;
+{
+ return 1 + hash % (htab_size (htab) - 2);
+}
+
/* This function creates table with length slightly longer than given
source length. Created hash table is initiated as empty (all the
hash table entries are EMPTY_ENTRY). The function returns the
htab_delete (htab)
htab_t htab;
{
+ size_t size = htab_size (htab);
+ PTR *entries = htab->entries;
int i;
if (htab->del_f)
- for (i = htab->size - 1; i >= 0; i--)
- if (htab->entries[i] != EMPTY_ENTRY
- && htab->entries[i] != DELETED_ENTRY)
- (*htab->del_f) (htab->entries[i]);
+ for (i = size - 1; i >= 0; i--)
+ if (entries[i] != EMPTY_ENTRY && entries[i] != DELETED_ENTRY)
+ (*htab->del_f) (entries[i]);
if (htab->free_f != NULL)
{
- (*htab->free_f) (htab->entries);
+ (*htab->free_f) (entries);
(*htab->free_f) (htab);
}
else if (htab->free_with_arg_f != NULL)
{
- (*htab->free_with_arg_f) (htab->alloc_arg, htab->entries);
+ (*htab->free_with_arg_f) (htab->alloc_arg, entries);
(*htab->free_with_arg_f) (htab->alloc_arg, htab);
}
}
htab_empty (htab)
htab_t htab;
{
+ size_t size = htab_size (htab);
+ PTR *entries = htab->entries;
int i;
if (htab->del_f)
- for (i = htab->size - 1; i >= 0; i--)
- if (htab->entries[i] != EMPTY_ENTRY
- && htab->entries[i] != DELETED_ENTRY)
- (*htab->del_f) (htab->entries[i]);
+ for (i = size - 1; i >= 0; i--)
+ if (entries[i] != EMPTY_ENTRY && entries[i] != DELETED_ENTRY)
+ (*htab->del_f) (entries[i]);
- memset (htab->entries, 0, htab->size * sizeof (PTR));
+ memset (entries, 0, size * sizeof (PTR));
}
/* Similar to htab_find_slot, but without several unwanted side effects:
htab_t htab;
hashval_t hash;
{
- size_t size = htab->size;
- unsigned int index = hash % size;
+ hashval_t index = htab_mod (hash, htab);
+ size_t size = htab_size (htab);
PTR *slot = htab->entries + index;
hashval_t hash2;
else if (*slot == DELETED_ENTRY)
abort ();
- hash2 = 1 + hash % (size - 2);
+ hash2 = htab_mod_m2 (hash, htab);
for (;;)
{
index += hash2;
const PTR element;
hashval_t hash;
{
- unsigned int index;
- hashval_t hash2;
+ hashval_t index, hash2;
size_t size;
PTR entry;
htab->searches++;
- size = htab->size;
- index = hash % size;
+ size = htab_size (htab);
+ index = htab_mod (hash, htab);
entry = htab->entries[index];
if (entry == EMPTY_ENTRY
|| (entry != DELETED_ENTRY && (*htab->eq_f) (entry, element)))
return entry;
- hash2 = 1 + hash % (size - 2);
-
+ hash2 = htab_mod_m2 (hash, htab);
for (;;)
{
htab->collisions++;
enum insert_option insert;
{
PTR *first_deleted_slot;
- unsigned int index;
- hashval_t hash2;
+ hashval_t index, hash2;
size_t size;
PTR entry;
- if (insert == INSERT && htab->size * 3 <= htab->n_elements * 4
- && htab_expand (htab) == 0)
- return NULL;
+ size = htab_size (htab);
+ if (insert == INSERT && size * 3 <= htab->n_elements * 4)
+ {
+ if (htab_expand (htab) == 0)
+ return NULL;
+ size = htab_size (htab);
+ }
- size = htab->size;
- index = hash % size;
+ index = htab_mod (hash, htab);
htab->searches++;
first_deleted_slot = NULL;
else if ((*htab->eq_f) (entry, element))
return &htab->entries[index];
- hash2 = 1 + hash % (size - 2);
+ hash2 = htab_mod_m2 (hash, htab);
for (;;)
{
htab->collisions++;
htab_t htab;
PTR *slot;
{
- if (slot < htab->entries || slot >= htab->entries + htab->size
+ if (slot < htab->entries || slot >= htab->entries + htab_size (htab)
|| *slot == EMPTY_ENTRY || *slot == DELETED_ENTRY)
abort ();
PTR *limit;
slot = htab->entries;
- limit = slot + htab->size;
+ limit = slot + htab_size (htab);
do
{
htab_trav callback;
PTR info;
{
- if ((htab->n_elements - htab->n_deleted) * 8 < htab->size)
+ if (htab_elements (htab) * 8 < htab_size (htab))
htab_expand (htab);
htab_traverse_noresize (htab, callback, info);
}
-/* Return the current size of given hash table. */
-
-size_t
-htab_size (htab)
- htab_t htab;
-{
- return htab->size;
-}
-
-/* Return the current number of elements in given hash table. */
-
-size_t
-htab_elements (htab)
- htab_t htab;
-{
- return htab->n_elements - htab->n_deleted;
-}
-
/* Return the fraction of fixed collisions during all work with given
hash table. */
+2004-03-30 Kazuhiro Inaoka <inaoka.kazuhiro@renesas.com>
+
+ * m32r-asm.c: Regenerate.
+
+2004-03-29 Stan Shebs <shebs@apple.com>
+
+ * mpw-config.in, mpw-make.sed: Remove MPW support files, no longer
+ used.
+
2004-03-19 Alan Modra <amodra@bigpond.net.au>
* aclocal.m4: Regenerate.
THIS FILE IS MACHINE GENERATED WITH CGEN.
- the resultant file is machine generated, cgen-asm.in isn't
-Copyright 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2004 Free Software Foundation, Inc.
This file is part of the GNU Binutils and GDB, the GNU debugger.
++*strp;
if (errmsg == NULL
&& result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- value = (value >> 16) + (value & 0x8000 ? 1 : 0);
+ {
+ value = value + (value & 0x8000 ? 0x10000 : 0);
+ value >>= 16;
+ }
*valuep = value;
return errmsg;
}
+++ /dev/null
-# Configuration fragment for opcodes.
-
-Set target_arch `echo {target_canonical} | sed -e 's/-.*-.*//'`
-
-Set archname ARCH_{target_arch}
-
-If "{target_arch}" =~ /m68k/
- Set BFD_MACHINES '"{o}"m68k-dis.c.o "{o}"m68k-opc.c.o'
-Else If "{target_arch}" =~ /powerpc/
- Set BFD_MACHINES '"{o}"ppc-dis.c.o "{o}"ppc-opc.c.o'
-Else If "{target_arch}" =~ /i386/
- Set BFD_MACHINES '"{o}"i386-dis.c.o'
-Else If "{target_arch}" =~ /mips/
- Set BFD_MACHINES '"{o}"mips-dis.c.o "{o}"mips-opc.c.o'
-Else If "{target_arch}" =~ /sh/
- Set BFD_MACHINES '"{o}"sh-dis.c.o'
-End If
-
-Echo '# Start from mpw-config.in' > "{o}"mk.tmp
-Echo "BFD_MACHINES = " {BFD_MACHINES} >> "{o}"mk.tmp
-Echo "ARCHDEFS = -d" {archname} >> "{o}"mk.tmp
-Echo '# End from mpw-config.in' >> "{o}"mk.tmp
-
-Echo '/* config.h. Generated by mpw-configure. */' > "{o}"config.new
-Echo '#include "mpw.h"' >> "{o}"config.new
-
-MoveIfChange "{o}"config.new "{o}"config.h
+++ /dev/null
-# Sed commands to finish translating the opcodes Makefile.in into MPW syntax.
-
-# Empty HDEFINES.
-/HDEFINES/s/@HDEFINES@//
-
-# Fix pathnames to include directories.
-/^INCDIR = /s/^INCDIR = .*$/INCDIR = "{topsrcdir}"include/
-/^CSEARCH = /s/$/ -i "{INCDIR}":mpw: -i ::extra-include:/
-
-/BFD_MACHINES/s/@BFD_MACHINES@/{BFD_MACHINES}/
-/archdefs/s/@archdefs@/{ARCHDEFS}/
-
-# No PIC foolery in this environment.
-/@ALLLIBS@/s/@ALLLIBS@/{TARGETLIB}/
-/@PICLIST@/s/@PICLIST@//
-/@PICFLAG@/s/@PICFLAG@//
-/^{OFILES} \\Option-f stamp-picdir/,/^$/d
-
-# Remove the pic trickery from the default build rule.
-/^\.c\.o \\Option-f /,/End If/c\
-.c.o \\Option-f .c
-
-# Remove pic trickery from other rules - aimed at the rule
-# for disassemble.o in particular.
-/-n "{PICFLAG}"/,/End If/d
+2004-03-29 Chris Demetriou <cgd@broadcom.com>
+ Richard Sandiford <rsandifo@redhat.com>
+
+ * sim-main.h (MIPS_MACH_HAS_MT_HILO_HAZARD)
+ (MIPS_MACH_HAS_MULT_HILO_HAZARD, MIPS_MACH_HAS_DIV_HILO_HAZARD): New.
+ * mips.igen (check_mt_hilo, check_mult_hilo, check_div_hilo): Provide
+ separate implementations for mipsIV and mipsV. Use new macros to
+ determine whether the restrictions apply.
+
2004-01-19 Chris Demetriou <cgd@broadcom.com>
* mips.igen (check_mf_cycles, check_mt_hilo, check_mf_hilo)
// On the r3900, restriction (2) is not present, and restriction (3) is not
// present for multiplication.
//
-// For now this code is paranoid. Historically the simulator
-// enforced restrictions (2) and (3) for more ISAs and CPU types than
-// necessary. Unfortunately, at least some MIPS IV and later parts'
-// documentation describes them as having these hazards (e.g. vr5000),
-// so they can't be removed for at leats MIPS IV. MIPS V hasn't been
-// checked (since there are no known hardware implementations).
-//
+// Unfortunately, there seems to be some confusion about whether the last
+// two restrictions should apply to "MIPS IV" as well. One edition of
+// the MIPS IV ISA says they do, but references in later ISA documents
+// suggest they don't.
+//
+// In reality, some MIPS IV parts, such as the VR5000 and VR5400, do have
+// these restrictions, while others, like the VR5500, don't. To accomodate
+// such differences, the MIPS IV and MIPS V version of these helper functions
+// use auxillary routines to determine whether the restriction applies.
// check_mf_cycles:
//
*mipsI:
*mipsII:
*mipsIII:
-*mipsIV:
-*mipsV:
*vr4100:
*vr5000:
{
return ok;
}
+:function:::int:check_mt_hilo:hilo_history *history
+*mipsIV:
+*mipsV:
+{
+ signed64 time = sim_events_time (SD);
+ int ok = (! MIPS_MACH_HAS_MT_HILO_HAZARD (SD)
+ || check_mf_cycles (SD_, history, time, "MT"));
+ history->mt.timestamp = time;
+ history->mt.cia = CIA;
+ return ok;
+}
+
:function:::int:check_mt_hilo:hilo_history *history
*mips32:
*mips64:
*mipsI:
*mipsII:
*mipsIII:
-*mipsIV:
-*mipsV:
*vr4100:
*vr5000:
{
return ok;
}
+:function:::int:check_mult_hilo:hilo_history *hi, hilo_history *lo
+*mipsIV:
+*mipsV:
+{
+ signed64 time = sim_events_time (SD);
+ int ok = (! MIPS_MACH_HAS_MULT_HILO_HAZARD (SD)
+ || (check_mf_cycles (SD_, hi, time, "OP")
+ && check_mf_cycles (SD_, lo, time, "OP")));
+ hi->op.timestamp = time;
+ lo->op.timestamp = time;
+ hi->op.cia = CIA;
+ lo->op.cia = CIA;
+ return ok;
+}
+
:function:::int:check_mult_hilo:hilo_history *hi, hilo_history *lo
*mips32:
*mips64:
*mipsI:
*mipsII:
*mipsIII:
-*mipsIV:
-*mipsV:
*vr4100:
*vr5000:
*r3900:
return ok;
}
+:function:::int:check_div_hilo:hilo_history *hi, hilo_history *lo
+*mipsIV:
+*mipsV:
+{
+ signed64 time = sim_events_time (SD);
+ int ok = (! MIPS_MACH_HAS_DIV_HILO_HAZARD (SD)
+ || (check_mf_cycles (SD_, hi, time, "OP")
+ && check_mf_cycles (SD_, lo, time, "OP")));
+ hi->op.timestamp = time;
+ lo->op.timestamp = time;
+ hi->op.cia = CIA;
+ lo->op.cia = CIA;
+ return ok;
+}
+
:function:::int:check_div_hilo:hilo_history *hi, hilo_history *lo
*mips32:
*mips64:
#define MIPS_MACH(SD) MIPS_MACH_DEFAULT
#endif
+/* Macros for determining whether a MIPS IV or MIPS V part is subject
+ to the hi/lo restrictions described in mips.igen. */
+
+#define MIPS_MACH_HAS_MT_HILO_HAZARD(SD) \
+ (MIPS_MACH (SD) != bfd_mach_mips5500)
+
+#define MIPS_MACH_HAS_MULT_HILO_HAZARD(SD) \
+ (MIPS_MACH (SD) != bfd_mach_mips5500)
+
+#define MIPS_MACH_HAS_DIV_HILO_HAZARD(SD) \
+ (MIPS_MACH (SD) != bfd_mach_mips5500)
+
#if H_REVEALS_MODULE_P (SIM_MAIN_INLINE)
#include "sim-main.c"
#endif
+2004-03-29 Richard Sandiford <rsandifo@redhat.com>
+
+ * sim/mips/hilo-hazard-[123].s: New files.
+ * sim/mips/basic.exp (run_hilo_test): New procedure.
+ (models): Only list models that are included in the configuration.
+ (submodels): New variable, set to submodels of the above.
+ (mips64vr-*-elf, mips64vrel-*-elf): New configuration stanza.
+ Run hilo-hazard-[123].s.
+
2004-03-01 Richard Sandiford <rsandifo@redhat.com>
* sim/frv/allinsn.exp (all_machs): Add fr405 and fr450.
# than the compiler) can't necessarily find.
unset_currtarget_info ldscript
+# Do "run_sim_test TESTFILE MODELS" for each combination of the
+# mf{lo,hi} -> mult/div/mt{lo,hi} hazard described in mips.igen.
+# Insert NOPS nops after the mflo or mfhi.
+proc run_hilo_test {testfile models nops} {
+ foreach reg {lo hi} {
+ foreach insn "{mult\t\$4,\$4} {div\t\$0,\$4,\$4} {mt$reg\t\$4}" {
+ set contents ""
+ append contents "\t.macro hilo\n"
+ append contents "\tmf$reg\t\$4\n"
+ append contents "\t.rept\t$nops\n"
+ append contents "\tnop\n"
+ append contents "\t.endr\n"
+ append contents "\t$insn\n"
+ append contents "\t.endm"
+
+ verbose -log "HILO test:\n$contents"
+ set file [open hilo-hazard.inc w]
+ puts $file $contents
+ close $file
+
+ run_sim_test $testfile $models
+ }
+ }
+}
+
+
# Only test mips*-elf (e.g., no mips-linux), and only test if the target
# board really is a simulator (sim tests don't work on real HW).
if {[istarget mips*-elf] && [board_info target exists is_simulator]} {
if {[istarget mipsisa64*-elf]} {
- set models "mips1 mips2 mips3 mips4 mips32 mips64"
+ set models "mips32 mips64"
+ set submodels "mips1 mips2 mips3 mips4"
} elseif {[istarget mipsisa32*-elf]} {
- set models "mips1 mips2 mips32"
+ set models "mips32"
+ set submodels "mips1 mips2"
+ } elseif {[istarget mips64vr-*-elf] || [istarget mips64vrel-*-elf]} {
+ set models "vr4100 vr4111 vr4120 vr5000 vr5400 vr5500"
+ set submodels "mips1 mips2 mips3 mips4"
} elseif {[istarget mips64*-elf]} {
- set models "mips1 mips2 mips3"
+ set models "mips3"
+ set submodels "mips1 mips2"
} else {
# fall back to just testing mips1 code.
set models "mips1"
+ set submodels ""
}
+ append submodels " " $models
set cpu_option -march
- run_sim_test sanity.s $models
+ run_sim_test sanity.s $submodels
+ foreach nops {0 1} {
+ run_hilo_test hilo-hazard-1.s $models $nops
+ run_hilo_test hilo-hazard-2.s $models $nops
+ }
+ run_hilo_test hilo-hazard-3.s $models 2
}