aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog537
-rw-r--r--bfd/Makefile.am29
-rw-r--r--bfd/Makefile.in31
-rw-r--r--bfd/aoutx.h19
-rw-r--r--bfd/archures.c30
-rw-r--r--bfd/bfd-in.h7
-rw-r--r--bfd/bfd-in2.h53
-rw-r--r--bfd/bfd.c3
-rw-r--r--bfd/coff-arm.c8
-rw-r--r--bfd/coff-h8300.c20
-rw-r--r--bfd/coff-ppc.c26
-rw-r--r--bfd/cofflink.c10
-rw-r--r--bfd/config.bfd13
-rwxr-xr-xbfd/configure41
-rw-r--r--bfd/configure.in41
-rw-r--r--bfd/cpu-arm.c7
-rw-r--r--bfd/cpu-m68k.c100
-rw-r--r--bfd/dwarf2.c402
-rw-r--r--bfd/ecoff.c7
-rw-r--r--bfd/ecofflink.c9
-rw-r--r--bfd/elf-bfd.h3
-rw-r--r--bfd/elf-m10300.c14
-rw-r--r--bfd/elf-strtab.c5
-rw-r--r--bfd/elf.c8
-rw-r--r--bfd/elf32-arm.c695
-rw-r--r--bfd/elf32-bfin.c4441
-rw-r--r--bfd/elf32-cris.c7
-rw-r--r--bfd/elf32-frv.c7
-rw-r--r--bfd/elf32-hppa.c6
-rw-r--r--bfd/elf32-i386.c3
-rw-r--r--bfd/elf32-m32r.c5
-rw-r--r--bfd/elf32-m68hc1x.c10
-rw-r--r--bfd/elf32-m68k.c131
-rw-r--r--bfd/elf32-mips.c149
-rw-r--r--bfd/elf32-ppc.c20
-rw-r--r--bfd/elf32-s390.c3
-rw-r--r--bfd/elf32-sh.c5
-rw-r--r--bfd/elf32-vax.c7
-rw-r--r--bfd/elf32-xtensa.c1
-rw-r--r--bfd/elf64-alpha.c9
-rw-r--r--bfd/elf64-hppa.c26
-rw-r--r--bfd/elf64-ppc.c9
-rw-r--r--bfd/elf64-s390.c3
-rw-r--r--bfd/elf64-sh64.c7
-rw-r--r--bfd/elf64-x86-64.c122
-rw-r--r--bfd/elflink.c373
-rw-r--r--bfd/elfxx-ia64.c13
-rw-r--r--bfd/elfxx-mips.c1568
-rw-r--r--bfd/elfxx-mips.h7
-rw-r--r--bfd/elfxx-sparc.c3
-rw-r--r--bfd/hash.c15
-rw-r--r--bfd/i386linux.c7
-rw-r--r--bfd/ieee.c24
-rw-r--r--bfd/libaout.h5
-rw-r--r--bfd/libbfd-in.h11
-rw-r--r--bfd/libbfd.h33
-rw-r--r--bfd/libcoff-in.h8
-rw-r--r--bfd/libcoff.h8
-rw-r--r--bfd/linker.c22
-rw-r--r--bfd/m68klinux.c7
-rw-r--r--bfd/merge.c5
-rw-r--r--bfd/opncls.c4
-rw-r--r--bfd/pdp11.c18
-rw-r--r--bfd/reloc.c48
-rw-r--r--bfd/section.c8
-rw-r--r--bfd/sparclinux.c7
-rw-r--r--bfd/stabs.c7
-rw-r--r--bfd/sunos.c7
-rw-r--r--bfd/targets.c6
-rw-r--r--bfd/version.h2
-rw-r--r--bfd/vms.c7
-rw-r--r--bfd/xcofflink.c7
72 files changed, 7294 insertions, 2025 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index e52fdfb..51157c0 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,540 @@
+2006-03-30 Ben Elliston <bje@au.ibm.com>
+
+ PR ld/2267
+ * elflink.c (elf_fixup_link_order): Ensure `elfsec' is not a
+ special section number that exceeds the number of ELF sections
+ (eg. SHN_MIPS_SCOMMON).
+
+2006-03-27 Richard Sandiford <richard@codesourcery.com>
+
+ * elfxx-mips.c (mips_got_entry): Add more commentary.
+ (mips_elf_local_got_index): Use the hash table entry to record
+ the GOT index of forced-local symbols.
+ (mips_elf_initialize_tls_index): Rearrange code. Store the index
+ in either the hash table entry or the mips_got_entry, not both.
+ Add more commentary.
+ (mips_elf_multi_got): Make sure the g->next is nonnull when calling
+ mips_elf_initialize_tls_index.
+
+2006-03-25 Bernd Schmidt <bernd.schmidt@analog.com>
+
+ * elf32-bfin.c (bfd_const_reloc, bfd_oper_reloc, bfin_push_reloc,
+ RELOC_STACK_SIZE, reloc_stack, reloc_stack_tos, is_reloc_stack_empty,
+ reloc_stack_push, reloc_stack_pop, reloc_stack_operate,
+ bfin_areloc_howto_table): Delete. All
+ uses deleted as well.
+ (bfin_reloc_map): Delete all stack relocs.
+ (bfin_info_to_howto, bfin_bfd_reloc_type_lookup,
+ bfin_reloc_type_lookup): Don't support them.
+ (bfin_relocate_section): Don't try to handle them.
+
+ * config.bfd (bfin-*-*): Add bfd_elf32_bfinfdpic_vec.
+ * configure.in: Likewise.
+ * configure: Regenerate.
+ * elf32-bfin.c: Include "elf/dwarf2.h" and "hashtab.h".
+ (BFIN_RELOC_MAX): Now 0x21.
+ (bfin_howto_table, bfin_reloc_map): Add FD-PIC relocs.
+ (bfd_elf32_bfinfdpic_vec): Declare.
+ (IS_FDPIC): New macro.
+ (struct bfinfdpic_elf_link_hash_table): New struct.
+ (bfinfdpic_hash_table, bfinfdpic_got_section,
+ bfinfdpic_gotrel_section, bfinfdpic_gotfixup_section,
+ bfinfdpic_plt_setion, bfinfdpic_pltrel_section,
+ bfinfdpic_relocs_info, bfinfdpic_got_initial_offset,
+ bfinfdpic_plt_initial_offset): Accessor macros for it.
+ (BFINFDPIC_SYM_LOCAL, BFINFDPIC_FUNCDESC_LOCAL): New macros.
+ (struct bfinfdpic_relocs_info): New struct.
+ (LZPLT_RESOLVER_EXTRA, LZPLT_NORMAL_SIZE, LZPLT_ENTRIES,
+ BFINFDPIC_LZPLT_BLOCK_SIZE, BFINFDPIC_LZPLT_RESOLV_LOC,
+ DEFAULT_STACK_SIZE): New macros.
+ (bfinfdpic_elf_link_hash_table_create, bfinfdpic_relocs_info_hash,
+ bfinfdpic_relocs_info_eq, bfinfdpics_relocs_info_find,
+ bfinfdpic_relocs_info_for_global, bfinfdpic_relocs_info_for_local,
+ bfinfdpic_pic_merge_early_relocs_info, _bfinfdpic_add_dyn_reloc,
+ _bfinfdpic_add_rofixup, _bfinfdpic_osec_to_segment,
+ _bfinfdpic_osec_readonly_p, bfinfdpic_relocate_section,
+ bfinfdpic_check_relocs, bfinfdpic_gc_sweep_hook,
+ _bfinfdpic_link_omit_section_dynsym, _bfin_create_got_section,
+ elf32_bfinfdpic_create_dynamic_sections, _bfinfdpic_get_fd_entry,
+ _bfinfdpic_compute_got_alloc_data, _bfinfdpic_get_got_entry,
+ _bfinfdpic_assign_got_entries, _bfinfdpic_assign_plt_entries,
+ _bfinfdpic_resolve_final_relocs_info,
+ elf32_bfinfdpic_size_dynamic_sections,
+ elf32_bfinfdpic_always_size_sections,
+ elf32_bfinfdpic_modify_segment_map,
+ _bfinfdpic_count_got_plt_entries,
+ elf32_bfinfdpic_finish_dynamic_sections,
+ elf32_bfinfdpic_adjust_dynamic_symbol,
+ elf32_bfinfdpic_finish_dynamic_symbol,
+ elf32_bfinfdpic_elf_use_relative_eh_frame,
+ elf32_bfinfdpic_elf_encode_eh_address,
+ elf32_bfin_object_p, bfin_elf_copy_private_bfd_data,
+ elf32_bfinfdpic_copy_private_bfd_data,
+ (struct _bfinfdpic_dynamic_got_info,
+ struct _bfinfdpic_dynamic_got_plt_info): New structs.
+ (elf32_bfin_print_private_bfd_data): Print PIC flags.
+ (elf32_bfin_merge_private_bfd_data): Extend to support FD-PIC.
+ (TARGET_LITTLE_SYM, TARGET_LITTLE_NAME, elf32_bed,
+ elf_backend_got_header_size, bfd_elf32_bfd_link_hash_table_create,
+ elf_backend_always_size_sectinos, elf_backend_modify_segment_map,
+ bfd_elf32_bfd_copy_private_bfd_data,
+ elf_backend_create_dynamic_sections, elf_backend_adjust_dynamic_symbol,
+ elf_backend_size_dynamic_sections, elf_backend_finish_dynamic_symbol,
+ elf_backend_finish_dynamic_sections, elf_backend_relocate_section,
+ elf_backend_can_make_relative_eh_frame, elf_backend_check_relocs,
+ elf_backend_can_make_ldsa_relative_eh_frame, elf_backend_may_use_rel_p,
+ elf_backend_may_use_rela_p, elf_backend_default_use_rela_p,
+ elf_backend_omit_section_dynsym): Redefine these macros and include
+ "elf32-target.h" again to create the elf32-bfinfdpic target.
+ * reloc.c (BFD_RELOC_BFIN_GOT17M4, BFD_RELOC_BFIN_GOTHI,
+ BFD_RELOC_BFIN_GOTLO, BFD_RELOC_BFIN_FUNCDESC,
+ BFD_RELOC_BFIN_FUNCDESC_GOT17M4, BFD_RELOC_BFIN_FUNCDESC_GOTHI,
+ BFD_RELOC_BFIN_FUNCDESC_GOTLO, BFD_RELOC_BFIN_FUNCDESC_VALUE,
+ BFD_RELOC_BFIN_FUNCDESC_GOTOFF17M4, BFD_RELOC_BFIN_FUNCDESC_GOTOFFHI,
+ BFD_RELOC_BFIN_FUNCDESC_GOTOFFLO, BFD_RELOC_BFIN_GOTOFFHI,
+ BFD_RELOC_BFIN_GOTOFFLO): New.
+ * targets.c (bfd_elf32_bfinfdpic_vec): New bfd_target.
+ (_bfd_target_vector): Add it.
+ * bfd-in2.h: Regenerate.
+ * libbfd.h: Regenerate.
+
+2006-03-25 Richard Sandiford <richard@codesourcery.com>
+
+ * cpu-m68k.c (bfd_m68k_compatible): Treat ISA A+ and ISA B code as
+ incompatible. Likewise MAC and EMAC code.
+ * elf32-m68k.c (elf32_m68k_merge_private_bfd_data): Use
+ bfd_get_compatible to set the new bfd architecture. Rely on it
+ to detect incompatibilities.
+
+2006-03-22 Bob Wilson <bob.wilson@acm.org>
+
+ * elf32-xtensa.c (xtensa_read_table_entries): Remove assertion that
+ rel->r_addend is zero.
+
+2006-03-22 Richard Sandiford <richard@codesourcery.com>
+
+ * elfxx-mips.c (_bfd_mips_vxworks_finish_dynamic_symbol): Fix type
+ of "loc".
+
+2006-03-22 Richard Sandiford <richard@codesourcery.com>
+ Daniel Jacobowitz <dan@codesourcery.com>
+ Phil Edwards <phil@codesourcery.com>
+ Zack Weinberg <zack@codesourcery.com>
+ Mark Mitchell <mark@codesourcery.com>
+ Nathan Sidwell <nathan@codesourcery.com>
+
+ * bfd-in2.h: Regenerate.
+ * config.bfd (mips*-*-vxworks*, mips*el-*-vxworks*): New stanzas.
+ * configure.in (bfd_elf32_bigmips_vxworks_vec): New stanza.
+ (bfd_elf32_littlemips_vxworks_vec): Likewise.
+ (bfd_elf32_bigmips_vec): Add elf-vxworks.lo.
+ (bfd_elf32_littlemips_vec): Likewise.
+ (bfd_elf32_nbigmips_vec): Likewise.
+ (bfd_elf32_nlittlemips_vec): Likewise.
+ (bfd_elf32_ntradbigmips_vec): Likewise.
+ (bfd_elf32_ntradlittlemips_vec): Likewise.
+ (bfd_elf32_tradbigmips_vec): Likewise.
+ (bfd_elf32_tradlittlemips_vec): Likewise.
+ (bfd_elf64_bigmips_vec): Likewise.
+ (bfd_elf64_littlemips_vec): Likewise.
+ (bfd_elf64_tradbigmips_vec): Likewise.
+ (bfd_elf64_tradlittlemips_vec): Likewise.
+ * elf32-mips.c: Include elf-vxworks.h.
+ (mips_info_to_howto_rel): Use elf_backend_mips_rtype_to_howto
+ instead of calling mips_elf32_rtype_to_howto directly.
+ (mips_vxworks_copy_howto_rela): New reloc howto.
+ (mips_vxworks_jump_slot_howto_rela): Likewise.
+ (mips_vxworks_bfd_reloc_type_lookup): New function.
+ (mips_vxworks_rtype_to_howto): Likewise.
+ (mips_vxworks_final_write_processing): Likewise.
+ (TARGET_LITTLE_SYM, TARGET_LITTLE_NAME): Override for VxWorks.
+ (TARGET_BIG_SYM, TARGET_BIG_NAME, elf_bed, ELF_MAXPAGESIZE): Likewise.
+ (elf_backend_want_got_plt): Likewise.
+ (elf_backend_want_plt_sym): Likewise.
+ (elf_backend_got_symbol_offset): Likewise.
+ (elf_backend_want_dynbss): Likewise.
+ (elf_backend_may_use_rel_p): Likewise.
+ (elf_backend_may_use_rela_p): Likewise.
+ (elf_backend_default_use_rela_p): Likewise.
+ (elf_backend_got_header_size: Likewise.
+ (elf_backend_plt_readonly): Likewise.
+ (bfd_elf32_bfd_reloc_type_lookup): Likewise.
+ (elf_backend_mips_rtype_to_howto): Likewise.
+ (elf_backend_adjust_dynamic_symbol): Likewise.
+ (elf_backend_finish_dynamic_symbol): Likewise.
+ (bfd_elf32_bfd_link_hash_table_create): Likewise.
+ (elf_backend_add_symbol_hook): Likewise.
+ (elf_backend_link_output_symbol_hook): Likewise.
+ (elf_backend_emit_relocs): Likewise.
+ (elf_backend_final_write_processing: Likewise.
+ (elf_backend_additional_program_headers): Likewise.
+ (elf_backend_modify_segment_map): Likewise.
+ (elf_backend_symbol_processing): Likewise.
+ * elfxx-mips.c: Include elf-vxworks.h.
+ (mips_elf_link_hash_entry): Add is_relocation_target and
+ is_branch_target fields.
+ (mips_elf_link_hash_table): Add is_vxworks, srelbss, sdynbss, srelplt,
+ srelplt2, sgotplt, splt, plt_header_size and plt_entry_size fields.
+ (MIPS_ELF_RELA_SIZE, MIPS_ELF_REL_DYN_NAME): New macros.
+ (MIPS_RESERVED_GOTNO): Take a mips_elf_link_hash_table argument.
+ Return 3 for VxWorks.
+ (ELF_MIPS_GP_OFFSET): Change the argument from a bfd to a
+ mips_elf_link_hash_table. Return 0 for VxWorks.
+ (MIPS_ELF_GOT_MAX_SIZE): Change the argument from a bfd to a
+ mips_elf_link_hash_table. Update the call to ELF_MIPS_GP_OFFSET.
+ (mips_vxworks_exec_plt0_entry): New variable.
+ (mips_vxworks_exec_plt_entry): Likewise.
+ (mips_vxworks_shared_plt0_entry): Likewise.
+ (mips_vxworks_shared_plt_entry): Likewise.
+ (mips_elf_link_hash_newfunc): Initialize the new hash_entry fields.
+ (mips_elf_rel_dyn_section): Change the bfd argument to a
+ mips_elf_link_hash_table. Use MIPS_ELF_REL_DYN_NAME to get
+ the name of the section.
+ (mips_elf_initialize_tls_slots): Update the call to
+ mips_elf_rel_dyn_section.
+ (mips_elf_gotplt_index): New function.
+ (mips_elf_local_got_index): Add an input_section argument.
+ Update the call to mips_elf_create_local_got_entry.
+ (mips_elf_got_page): Likewise.
+ (mips_elf_got16_entry): Likewise.
+ (mips_elf_create_local_got_entry): Add bfd_link_info and input_section
+ arguments. Create dynamic relocations for each entry on VxWorks.
+ (mips_elf_merge_gots): Update the use of MIPS_ELF_GOT_MAX_SIZE.
+ (mips_elf_multi_got): Update the uses of MIPS_ELF_GOT_MAX_SIZE
+ and MIPS_RESERVED_GOTNO.
+ (mips_elf_create_got_section): Update the uses of
+ MIPS_ELF_GOT_MAX_SIZE. Create .got.plt on VxWorks.
+ (is_gott_symbol): New function.
+ (mips_elf_calculate_relocation): Use a dynobj local variable.
+ Update the calls to mips_elf_local_got_index, mips_elf_got16_entry and
+ mips_elf_got_page_entry. Set G to the .got.plt entry when calculating
+ VxWorks R_MIPS_CALL* relocations. Calculate and use G for all GOT
+ relocations on VxWorks. Add dynamic relocations for references
+ to the VxWorks __GOTT_BASE__ and __GOTT_INDEX__ symbols. Don't
+ create dynamic relocations for R_MIPS_32, R_MIPS_REL32 or R_MIPS_64
+ in VxWorks executables.
+ (mips_elf_allocate_dynamic_relocations): Add a bfd_link_info argument.
+ Use MIPS_ELF_RELA_SIZE to calculate the size of a VxWorks entry.
+ Don't allocate a null entry on VxWorks.
+ (mips_elf_create_dynamic_relocation): Update the call to
+ mips_elf_rel_dyn_section. Use absolute rather than relative
+ relocations for VxWorks, and make them RELA rather than REL.
+ (_bfd_mips_elf_create_dynamic_sections): Don't make .dynamic
+ read-only on VxWorks. Update the call to mips_elf_rel_dyn_section.
+ Create the .plt, .rela.plt, .dynbss and .rela.bss sections on
+ VxWorks. Likewise create the _PROCEDURE_LINKAGE_TABLE symbol.
+ Call elf_vxworks_create_dynamic_sections for VxWorks and
+ initialize the plt_header_size and plt_entry_size fields.
+ (_bfd_mips_elf_check_relocs): Don't allow GOT relocations to be
+ used in VxWorks executables. Don't allocate dynamic relocations
+ for R_MIPS_32, R_MIPS_REL32 or R_MIPS_64 in VxWorks executables.
+ Set is_relocation_target for each symbol referenced by a relocation.
+ Allocate .rela.dyn entries for relocations against the special
+ VxWorks __GOTT_BASE__ and __GOTT_INDEX__ symbols. Create GOT
+ entries for all VxWorks R_MIPS_GOT16 relocations. Don't allocate
+ a global GOT entry for symbols mentioned in VxWorks R_MIPS_CALL*,
+ R_MIPS_32, R_MIPS_REL32 or R_MIPS_64 relocations. Update the calls
+ to mips_elf_rel_dyn_section and mips_elf_allocate_dynamic_relocations.
+ Set is_branch_target for symbols mentioned in R_MIPS_PC16 or R_MIPS_26
+ relocations. Don't set no_fn_stub on VxWorks.
+ (_bfd_mips_elf_adjust_dynamic_symbol): Update the call to
+ mips_elf_allocate_dynamic_relocations.
+ (_bfd_mips_vxworks_adjust_dynamic_symbol): New function.
+ (_bfd_mips_elf_always_size_sections): Do not allocate GOT page
+ entries for VxWorks, and do not create multiple GOTs.
+ (_bfd_mips_elf_size_dynamic_sections): Use MIPS_ELF_REL_DYN_NAME.
+ Handle .got specially for VxWorks. Update the uses of
+ MIPS_RESERVED_GOTNO and mips_elf_allocate_dynamic_relocations.
+ Check for sgotplt and splt. Allocate the .rel(a).dyn contents last,
+ once its final size is known. Set DF_TEXTREL for VxWorks. Add
+ DT_RELA, DT_RELASZ, DT_RELAENT, DT_PLTREL, DT_PLTRELSZ and DT_JMPREL
+ tags on VxWorks. Do not add the MIPS-specific tags for VxWorks.
+ (_bfd_mips_vxworks_finish_dynamic_symbol): New function.
+ (mips_vxworks_finish_exec_plt): Likewise.
+ (mips_vxworks_finish_shared_plt): Likewise.
+ (_bfd_mips_elf_finish_dynamic_sections): Remove an unncessary call
+ to mips_elf_rel_dyn_section. Use a VxWorks-specific value of
+ DT_PLTGOT. Handle DT_RELA, DT_RELASZ, DT_RELAENT, DT_PLTREL,
+ DT_PLTRELSZ and DT_JMPREL. Update the uses of MIPS_RESERVED_GOTNO
+ and mips_elf_rel_dyn_section. Use a different GOT header for
+ VxWorks. Don't sort .rela.dyn on VxWorks. Finish the PLT on VxWorks.
+ (_bfd_mips_elf_link_hash_table_create): Initialize the new
+ mips_elf_link_hash_table fields.
+ (_bfd_mips_vxworks_link_hash_table_create): New function.
+ (_bfd_mips_elf_final_link): Set the GP value to _GLOBAL_OFFSET_TABLE_
+ on VxWorks. Update the call to ELF_MIPS_GP_OFFSET.
+ * elfxx-mips.h (_bfd_mips_vxworks_adjust_dynamic_symbol): Declare.
+ (_bfd_mips_vxworks_finish_dynamic_symbol): Likewise.
+ (_bfd_mips_vxworks_link_hash_table_create): Likewise.
+ * libbfd.h: Regenerate.
+ * Makefile.am (elfxx-mips.lo): Depend on elf-vxworks.h.
+ (elf32-mips.lo): Likewise.
+ * Makefile.in: Regenerate.
+ * reloc.c (BFD_RELOC_MIPS_COPY, BFD_RELOC_MIPS_JUMP_SLOT): Declare.
+ * targets.c (bfd_elf32_bigmips_vxworks_vec): Declare.
+ (bfd_elf32_littlemips_vxworks_vec): Likewise.
+ (_bfd_target_vector): Add entries for them.
+
+2006-03-19 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
+
+ * elf64-hppa.c (elf64_hppa_special_sections): Change flags for .tbss
+ section from SHF_PARISC_WEAKORDER to SHF_HP_TLS.
+ (elf_backend_special_sections): Remove #undef.
+
+2006-03-18 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
+
+ * elf64-hppa.c (allocate_global_data_opd): Don't create an OPD entry
+ for undefined weak symbols.
+
+2006-03-17 Daniel Jacobowitz <dan@codesourcery.com>
+
+ PR ld/2462
+ * elflink.c (bfd_elf_final_link): Remove
+ bed->elf_backend_emit_relocs from emit_relocs.
+
+2006-03-17 Alexandre Oliva <aoliva@redhat.com>
+
+ * elf32-ppc.c (ppc_elf_relocate_section): Copy addend from
+ first relocation to the second when relaxing TLS GD to LE;
+ zero it out when relaxing to IE.
+
+2006-03-17 Alan Modra <amodra@bigpond.net.au>
+
+ PR 2434
+ * elflink.c (elf_link_add_object_symbols): Save and restore
+ warning sym's linked sym.
+
+2006-03-16 Alan Modra <amodra@bigpond.net.au>
+
+ PR 2434
+ * elflink.c (struct elf_smash_syms_data, elf_smash_syms): Delete.
+ (elf_link_add_object_symbols): Delete unnecessary locals. Rename
+ hash_table -> htab. Formatting. Save entire symbol table
+ before loading as-needed syms, and restore afterwards if lib not
+ needed. Use bfd_hash_allocate rather than bfd_alloc for sym
+ name. Free some buffers earlier.
+ * bfd-in.h (struct bfd_hash_table): Add entsize.
+ (bfd_hash_table_init, bfd_hash_table_init_n): Adjust prototype.
+ * elf-bfd.h (_bfd_elf_link_hash_table_init): Likewise
+ * hash.c (bfd_hash_table_init_n): Add entsize param, save to
+ hash table.
+ (bfd_hash_table_init): Add param, adjust calls.
+ * aoutx.h: Adjust all hash_table_init functions and calls.
+ * bfd.c: Likewise.
+ * coff-arm.c: Likewise.
+ * coff-h8300.c: Likewise.
+ * coff-ppc.c: Likewise.
+ * cofflink.c: Likewise.
+ * ecoff.c: Likewise.
+ * ecofflink.c: Likewise.
+ * elf-m10300.c: Likewise.
+ * elf-strtab.c: Likewise.
+ * elf.c: Likewise.
+ * elf32-arm.c: Likewise.
+ * elf32-bfin.c: Likewise.
+ * elf32-cris.c: Likewise.
+ * elf32-frv.c: Likewise.
+ * elf32-hppa.c: Likewise.
+ * elf32-i386.c: Likewise.
+ * elf32-m32r.c: Likewise.
+ * elf32-m68hc1x.c: Likewise.
+ * elf32-m68k.c: Likewise.
+ * elf32-ppc.c: Likewise.
+ * elf32-s390.c: Likewise.
+ * elf32-sh.c: Likewise.
+ * elf32-vax.c: Likewise.
+ * elf64-alpha.c: Likewise.
+ * elf64-hppa.c: Likewise.
+ * elf64-ppc.c: Likewise.
+ * elf64-s390.c: Likewise.
+ * elf64-sh64.c: Likewise.
+ * elf64-x86-64.c: Likewise.
+ * elfxx-ia64.c: Likewise.
+ * elfxx-mips.c: Likewise.
+ * elfxx-sparc.c: Likewise.
+ * i386linux.c: Likewise.
+ * libaout.h: Likewise.
+ * libbfd-in.h: Likewise.
+ * libcoff-in.h: Likewise.
+ * linker.c: Likewise.
+ * m68klinux.c: Likewise.
+ * merge.c: Likewise.
+ * opncls.c: Likewise.
+ * pdp11.c: Likewise.
+ * sparclinux.c: Likewise.
+ * stabs.c: Likewise.
+ * sunos.c: Likewise.
+ * vms.c: Likewise.
+ * xcofflink.c: Likewise.
+ * section.c (struct section_hash_entry): Move to..
+ * libbfd-in.h: ..here.
+ * Makefile.am: Run "make dep-am"
+ * Makefile.in: Regenerate.
+ * bfd-in2.h: Regenerate.
+ * libbfd.h: Regenerate.
+ * libcoff.h: Regenerate.
+
+2006-03-16 Alan Modra <amodra@bigpond.net.au>
+
+ * elf32-ppc.c (ppc_elf_check_relocs): REL24 and REL14 relocs
+ against __GLOBAL_OFFSET_TABLE__ need never be dynamic. Tweak
+ last change to REL32 relocs so that they are counted as
+ possibly dynamic as per REL24 and REL14.
+
+2006-03-16 Alan Modra <amodra@bigpond.net.au>
+
+ * elf32-ppc.c (ppc_elf_check_relocs): Don't fall into REL24
+ checks from REL32.
+
+2006-03-15 Ben Elliston <bje@au.ibm.com>
+
+ * elf32-arm.c (elf32_arm_merge_eabi_attributes): Iterate over all
+ in_list elements, not just the first.
+
+2006-03-14 Richard Sandiford <richard@codesourcery.com>
+
+ * elf32-mips.c (mips_elf_adjust_addend): New function, mostly split
+ out from...
+ (_bfd_mips_elf_relocate_section): ...here. Use it to adjust r_addend
+ for final links too.
+
+2006-03-13 Richard Sandiford <richard@codesourcery.com>
+
+ * elfxx-mips.c (mips_elf_create_got_section): Initialize hgot.
+
+2006-03-11 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ld/2443
+ * dwarf2.c (concat_filename): Don't issue an error if file is
+ 0.
+
+2006-03-10 Paul Brook <paul@codesourcery.com>
+
+ * elf32-arm.c (INTERWORK_FLAG): Handle EABIv5.
+ (elf32_arm_print_private_bfd_data): Ditto.
+
+2006-03-09 Paul Brook <paul@codesourcery.com>
+
+ * cpu-arm.c (bfd_is_arm_mapping_symbol_name): Recognise additional
+ mapping symbols.
+
+2006-03-09 Khem Raj <khem@mvista.com>
+
+ * elf32-arm.c(elf32_arm_finish_dynamic_sections): Use unsigned
+ char type.
+
+2006-03-08 H.J. Lu <hongjiu.lu@intel.com>
+
+ * elfxx-ia64.c (elfNN_ia64_choose_gp): Properly choose gp.
+
+2006-03-07 Richard Sandiford <richard@codesourcery.com>
+ Daniel Jacobowitz <dan@codesourcery.com>
+ Zack Weinberg <zack@codesourcery.com>
+ Nathan Sidwell <nathan@codesourcery.com>
+ Paul Brook <paul@codesourcery.com>
+ Ricardo Anguiano <anguiano@codesourcery.com>
+ Phil Edwards <phil@codesourcery.com>
+
+ * configure.in (bfd_elf32_bigarm_vec): Include elf-vxworks.lo.
+ (bfd_elf32_bigarm_symbian_vec): Likewise.
+ (bfd_elf32_bigarm_vxworks_vec): Likewise.
+ (bfd_elf32_littlearm_vec): Likewise.
+ (bfd_elf32_littlearm_symbian_vec): Likewise.
+ (bfd_elf32_littlearm_vxworks_vec): Likewise.
+ * configure: Regenerate.
+ * elf32-arm.c: Include libiberty.h and elf-vxworks.h.
+ (RELOC_SECTION, RELOC_SIZE, SWAP_RELOC_IN, SWAP_RELOC_OUT): New macros.
+ (elf32_arm_vxworks_bed): Add forward declaration.
+ (elf32_arm_howto_table_1): Fix the masks for R_ASM_ABS12.
+ (elf32_arm_vxworks_exec_plt0_entry): New table.
+ (elf32_arm_vxworks_exec_plt_entry): Likewise.
+ (elf32_arm_vxworks_shared_plt_entry): Likewise.
+ (elf32_arm_link_hash_table): Add vxworks_p and srelplt2 fields.
+ (reloc_section_p): New function.
+ (create_got_section): Use RELOC_SECTION.
+ (elf32_arm_create_dynamic_sections): Likewise. Call
+ elf_vxworks_create_dynamic_sections for VxWorks targets.
+ Choose between the two possible values of plt_header_size
+ and plt_entry_size.
+ (elf32_arm_link_hash_table_create): Initialize vxworks_p and srelplt2.
+ (elf32_arm_abs12_reloc): New function.
+ (elf32_arm_final_link_relocate): Call it. Allow the creation of
+ dynamic R_ARM_ABS12 relocs on VxWorks. Use reloc_section_p,
+ RELOC_SIZE, SWAP_RELOC_OUT and RELOC_SECTION. Initialize the
+ r_addend fields of relocs. On rela targets, skip any code that
+ adjusts in-place addends. When using _bfd_link_final_relocate
+ to perform a final relocation, pass rel->r_addend as the addend
+ argument.
+ (elf32_arm_merge_private_bfd_data): If one of the bfds is a VxWorks
+ object, ignore flags that are not standard on VxWorks.
+ (elf32_arm_check_relocs): Allow the creation of dynamic R_ARM_ABS12
+ relocs on VxWorks. Use reloc_section_p.
+ (elf32_arm_adjust_dynamic_symbol): Use RELOC_SECTION and RELOC_SIZE.
+ (allocate_dynrelocs): Use RELOC_SIZE. Account for the size of
+ .rela.plt.unloaded relocs on VxWorks targets.
+ (elf32_arm_size_dynamic_sections): Use RELOC_SIZE. Check for
+ .rela.plt.unloaded as well as .rel(a).plt. Add DT_RELA* tags
+ instead of DT_REL* tags on RELA targets.
+ (elf32_arm_finish_dynamic_symbol): Use RELOC_SECTION, RELOC_SIZE
+ and SWAP_RELOC_OUT. Initialize r_addend fields. Handle VxWorks
+ PLT entries. Do not make _GLOBAL_OFFSET_TABLE_ absolute on VxWorks.
+ (elf32_arm_finish_dynamic_sections): Use RELOC_SECTION, RELOC_SIZE
+ and SWAP_RELOC_OUT. Initialize r_addend fields. Handle DT_RELASZ
+ like DT_RELSZ. Handle the VxWorks form of initial PLT entry.
+ Correct the .rela.plt.unreloaded symbol indexes.
+ (elf32_arm_output_symbol_hook): Call the VxWorks version of this
+ hook on VxWorks targets.
+ (elf32_arm_vxworks_link_hash_table_create): Set vxworks_p to true.
+ Minor formatting tweak.
+ (elf32_arm_vxworks_final_write_processing): New function.
+ (elf_backend_add_symbol_hook): Override for VxWorks and reset
+ for Symbian.
+ (elf_backend_final_write_processing): Likewise.
+ (elf_backend_emit_relocs): Likewise.
+ (elf_backend_want_plt_sym): Likewise.
+ (ELF_MAXPAGESIZE): Likewise.
+ (elf_backend_may_use_rel_p): Minor formatting tweak.
+ (elf_backend_may_use_rela_p): Likewise.
+ (elf_backend_default_use_rela_p): Likewise.
+ (elf_backend_rela_normal): Likewise.
+ * Makefile.in (elf32-arm.lo): Depend on elf-vxworks.h.
+
+2006-03-06 Nathan Sidwell <nathan@codesourcery.com>
+
+ * archures.c (bfd_mach_mcf_isa_a_nodiv, bfd_mach_mcf_isa_b_nousp):
+ New. Adjust other variants.
+ (bfd_default_scan): Update.
+ * bfd-in2.h: Rebuilt.
+ * cpu-m68k.c: Adjust.
+ (bfd_m68k_compatible): New. Use it for architectures.
+ * elf32-m68k.c (elf32_m68k_object_p): Adjust.
+ (elf32_m68k_merge_private_bfd_data): Adjust. Correct isa-a/b
+ mismatch.
+ (elf32_m68k_print_private_bfd_data): Adjust.
+ * ieee.c (ieee_write_processor): Adjust.
+
+2006-03-06 Alan Modra <amodra@bigpond.net.au>
+
+ * dwarf2.c: Formatting.
+ (add_line_info): Remove outer loop.
+
+2006-03-05 H.J. Lu <hongjiu.lu@intel.com>
+ Alan Modra <amodra@bigpond.net.au>
+
+ PR binutils/2338
+ * dwarf2.c (loadable_section): New struct.
+ (dwarf2_debug): Add loadable_section_count and
+ loadable_sections.
+ (new_line_sorts_after): New.
+ (add_line_info): Use new_line_sorts_after to compare line
+ addresses.
+ (check_function_name): Removed.
+ (unset_sections): New.
+ (place_sections): New.
+ (_bfd_dwarf2_find_nearest_line): Updated. Call place_sections
+ and unset_sections on relocatable files.
+ (_bfd_dwarf2_find_line): Likewise.
+
2006-03-03 Nick Clifton <nickc@redhat.com>
* cpu-avr.c: Update to ISO-C90 formatting.
diff --git a/bfd/Makefile.am b/bfd/Makefile.am
index f793c9a..a0d5edf 100644
--- a/bfd/Makefile.am
+++ b/bfd/Makefile.am
@@ -1000,7 +1000,8 @@ cpu-m68hc11.lo: cpu-m68hc11.c $(INCDIR)/filenames.h \
$(INCDIR)/hashtab.h
cpu-m68hc12.lo: cpu-m68hc12.c $(INCDIR)/filenames.h \
$(INCDIR)/hashtab.h
-cpu-m68k.lo: cpu-m68k.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
+cpu-m68k.lo: cpu-m68k.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
+ $(INCDIR)/opcode/m68k.h
cpu-m88k.lo: cpu-m88k.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
cpu-m10200.lo: cpu-m10200.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
cpu-m10300.lo: cpu-m10300.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
@@ -1218,10 +1219,11 @@ elf32-arc.lo: elf32-arc.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
$(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(INCDIR)/elf/arc.h \
$(INCDIR)/elf/reloc-macros.h $(INCDIR)/libiberty.h \
elf32-target.h
-elf32-arm.lo: elf32-arm.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
- elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
- $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(INCDIR)/elf/arm.h \
- $(INCDIR)/elf/reloc-macros.h elf32-target.h
+elf32-arm.lo: elf32-arm.c $(INCDIR)/filenames.h $(INCDIR)/libiberty.h \
+ $(INCDIR)/hashtab.h elf-bfd.h $(INCDIR)/elf/common.h \
+ $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h \
+ elf-vxworks.h $(INCDIR)/elf/arm.h $(INCDIR)/elf/reloc-macros.h \
+ elf32-target.h
elf32-avr.lo: elf32-avr.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
$(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(INCDIR)/elf/avr.h \
@@ -1312,7 +1314,8 @@ elf32-m32r.lo: elf32-m32r.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
elf32-m68k.lo: elf32-m68k.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \
$(INCDIR)/hashtab.h elf-bfd.h $(INCDIR)/elf/common.h \
$(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/elf/m68k.h \
- $(INCDIR)/elf/reloc-macros.h elf32-target.h
+ $(INCDIR)/elf/reloc-macros.h $(INCDIR)/opcode/m68k.h \
+ elf32-target.h
elf32-m68hc11.lo: elf32-m68hc11.c $(INCDIR)/filenames.h \
$(INCDIR)/bfdlink.h $(INCDIR)/hashtab.h elf-bfd.h $(INCDIR)/elf/common.h \
$(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h elf32-m68hc1x.h \
@@ -1347,14 +1350,14 @@ elfxx-mips.lo: elfxx-mips.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
$(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h \
elfxx-mips.h $(INCDIR)/elf/mips.h $(INCDIR)/elf/reloc-macros.h \
$(INCDIR)/coff/sym.h $(INCDIR)/coff/symconst.h $(INCDIR)/coff/ecoff.h \
- $(INCDIR)/coff/mips.h $(INCDIR)/coff/external.h
+ $(INCDIR)/coff/mips.h $(INCDIR)/coff/external.h elf-vxworks.h
elf32-mips.lo: elf32-mips.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
$(INCDIR)/bfdlink.h genlink.h elf-bfd.h $(INCDIR)/elf/common.h \
$(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h elfxx-mips.h \
$(INCDIR)/elf/mips.h $(INCDIR)/elf/reloc-macros.h $(INCDIR)/coff/sym.h \
$(INCDIR)/coff/symconst.h $(INCDIR)/coff/internal.h \
$(INCDIR)/coff/ecoff.h $(INCDIR)/coff/mips.h $(INCDIR)/coff/external.h \
- ecoffswap.h elf32-target.h
+ ecoffswap.h elf32-target.h elf-vxworks.h
elf32-mt.lo: elf32-mt.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
$(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(INCDIR)/elf/mt.h \
@@ -1439,17 +1442,17 @@ elf32-xtensa.lo: elf32-xtensa.c $(INCDIR)/filenames.h \
$(INCDIR)/elf/reloc-macros.h $(INCDIR)/xtensa-isa.h \
$(INCDIR)/xtensa-config.h elf32-target.h
elf32-xc16x.lo: elf32-xc16x.c $(INCDIR)/filenames.h \
- elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
- $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(INCDIR)/elf/xc16x.h \
- $(INCDIR)/elf/reloc-macros.h $(INCDIR)/libiberty.h \
- elf32-target.h
+ $(INCDIR)/hashtab.h elf-bfd.h $(INCDIR)/elf/common.h \
+ $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/elf/xc16x.h $(INCDIR)/elf/reloc-macros.h \
+ $(INCDIR)/elf/dwarf2.h $(INCDIR)/libiberty.h elf32-target.h
elf32.lo: elf32.c elfcode.h $(INCDIR)/filenames.h $(INCDIR)/libiberty.h \
$(INCDIR)/bfdlink.h $(INCDIR)/hashtab.h elf-bfd.h $(INCDIR)/elf/common.h \
$(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h elfcore.h
elflink.lo: elflink.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \
$(INCDIR)/hashtab.h elf-bfd.h $(INCDIR)/elf/common.h \
$(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/safe-ctype.h \
- $(INCDIR)/libiberty.h
+ $(INCDIR)/libiberty.h $(INCDIR)/objalloc.h
elf-strtab.lo: elf-strtab.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
$(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(INCDIR)/libiberty.h
diff --git a/bfd/Makefile.in b/bfd/Makefile.in
index bd496aa..6b78333 100644
--- a/bfd/Makefile.in
+++ b/bfd/Makefile.in
@@ -2,7 +2,7 @@
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005 Free Software Foundation, Inc.
+# 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -1567,7 +1567,8 @@ cpu-m68hc11.lo: cpu-m68hc11.c $(INCDIR)/filenames.h \
$(INCDIR)/hashtab.h
cpu-m68hc12.lo: cpu-m68hc12.c $(INCDIR)/filenames.h \
$(INCDIR)/hashtab.h
-cpu-m68k.lo: cpu-m68k.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
+cpu-m68k.lo: cpu-m68k.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
+ $(INCDIR)/opcode/m68k.h
cpu-m88k.lo: cpu-m88k.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
cpu-m10200.lo: cpu-m10200.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
cpu-m10300.lo: cpu-m10300.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
@@ -1785,10 +1786,11 @@ elf32-arc.lo: elf32-arc.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
$(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(INCDIR)/elf/arc.h \
$(INCDIR)/elf/reloc-macros.h $(INCDIR)/libiberty.h \
elf32-target.h
-elf32-arm.lo: elf32-arm.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
- elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
- $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(INCDIR)/elf/arm.h \
- $(INCDIR)/elf/reloc-macros.h elf32-target.h
+elf32-arm.lo: elf32-arm.c $(INCDIR)/filenames.h $(INCDIR)/libiberty.h \
+ $(INCDIR)/hashtab.h elf-bfd.h $(INCDIR)/elf/common.h \
+ $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h \
+ elf-vxworks.h $(INCDIR)/elf/arm.h $(INCDIR)/elf/reloc-macros.h \
+ elf32-target.h
elf32-avr.lo: elf32-avr.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
$(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(INCDIR)/elf/avr.h \
@@ -1879,7 +1881,8 @@ elf32-m32r.lo: elf32-m32r.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
elf32-m68k.lo: elf32-m68k.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \
$(INCDIR)/hashtab.h elf-bfd.h $(INCDIR)/elf/common.h \
$(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/elf/m68k.h \
- $(INCDIR)/elf/reloc-macros.h elf32-target.h
+ $(INCDIR)/elf/reloc-macros.h $(INCDIR)/opcode/m68k.h \
+ elf32-target.h
elf32-m68hc11.lo: elf32-m68hc11.c $(INCDIR)/filenames.h \
$(INCDIR)/bfdlink.h $(INCDIR)/hashtab.h elf-bfd.h $(INCDIR)/elf/common.h \
$(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h elf32-m68hc1x.h \
@@ -1914,14 +1917,14 @@ elfxx-mips.lo: elfxx-mips.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
$(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h \
elfxx-mips.h $(INCDIR)/elf/mips.h $(INCDIR)/elf/reloc-macros.h \
$(INCDIR)/coff/sym.h $(INCDIR)/coff/symconst.h $(INCDIR)/coff/ecoff.h \
- $(INCDIR)/coff/mips.h $(INCDIR)/coff/external.h
+ $(INCDIR)/coff/mips.h $(INCDIR)/coff/external.h elf-vxworks.h
elf32-mips.lo: elf32-mips.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
$(INCDIR)/bfdlink.h genlink.h elf-bfd.h $(INCDIR)/elf/common.h \
$(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h elfxx-mips.h \
$(INCDIR)/elf/mips.h $(INCDIR)/elf/reloc-macros.h $(INCDIR)/coff/sym.h \
$(INCDIR)/coff/symconst.h $(INCDIR)/coff/internal.h \
$(INCDIR)/coff/ecoff.h $(INCDIR)/coff/mips.h $(INCDIR)/coff/external.h \
- ecoffswap.h elf32-target.h
+ ecoffswap.h elf32-target.h elf-vxworks.h
elf32-mt.lo: elf32-mt.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
$(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(INCDIR)/elf/mt.h \
@@ -2006,17 +2009,17 @@ elf32-xtensa.lo: elf32-xtensa.c $(INCDIR)/filenames.h \
$(INCDIR)/elf/reloc-macros.h $(INCDIR)/xtensa-isa.h \
$(INCDIR)/xtensa-config.h elf32-target.h
elf32-xc16x.lo: elf32-xc16x.c $(INCDIR)/filenames.h \
- elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
- $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(INCDIR)/elf/xc16x.h \
- $(INCDIR)/elf/reloc-macros.h $(INCDIR)/libiberty.h \
- elf32-target.h
+ $(INCDIR)/hashtab.h elf-bfd.h $(INCDIR)/elf/common.h \
+ $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/elf/xc16x.h $(INCDIR)/elf/reloc-macros.h \
+ $(INCDIR)/elf/dwarf2.h $(INCDIR)/libiberty.h elf32-target.h
elf32.lo: elf32.c elfcode.h $(INCDIR)/filenames.h $(INCDIR)/libiberty.h \
$(INCDIR)/bfdlink.h $(INCDIR)/hashtab.h elf-bfd.h $(INCDIR)/elf/common.h \
$(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h elfcore.h
elflink.lo: elflink.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \
$(INCDIR)/hashtab.h elf-bfd.h $(INCDIR)/elf/common.h \
$(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/safe-ctype.h \
- $(INCDIR)/libiberty.h
+ $(INCDIR)/libiberty.h $(INCDIR)/objalloc.h
elf-strtab.lo: elf-strtab.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
$(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(INCDIR)/libiberty.h
diff --git a/bfd/aoutx.h b/bfd/aoutx.h
index 9c44605..7dce072 100644
--- a/bfd/aoutx.h
+++ b/bfd/aoutx.h
@@ -1,6 +1,6 @@
/* BFD semi-generic back-end for a.out binaries.
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004, 2005
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
Written by Cygnus Support.
@@ -2859,9 +2859,10 @@ NAME (aout, link_hash_table_init) (struct aout_link_hash_table *table,
bfd *abfd,
struct bfd_hash_entry *(*newfunc)
(struct bfd_hash_entry *, struct bfd_hash_table *,
- const char *))
+ const char *),
+ unsigned int entsize)
{
- return _bfd_link_hash_table_init (&table->root, abfd, newfunc);
+ return _bfd_link_hash_table_init (&table->root, abfd, newfunc, entsize);
}
/* Create an a.out link hash table. */
@@ -2876,8 +2877,9 @@ NAME (aout, link_hash_table_create) (bfd *abfd)
if (ret == NULL)
return NULL;
- if (! NAME (aout, link_hash_table_init) (ret, abfd,
- NAME (aout, link_hash_newfunc)))
+ if (!NAME (aout, link_hash_table_init) (ret, abfd,
+ NAME (aout, link_hash_newfunc),
+ sizeof (struct aout_link_hash_entry)))
{
free (ret);
return NULL;
@@ -5252,9 +5254,10 @@ NAME (aout, final_link) (bfd *abfd,
aout_info.symbol_map = NULL;
aout_info.output_syms = NULL;
- if (! bfd_hash_table_init_n (&aout_info.includes.root,
- aout_link_includes_newfunc,
- 251))
+ if (!bfd_hash_table_init_n (&aout_info.includes.root,
+ aout_link_includes_newfunc,
+ sizeof (struct aout_link_includes_entry),
+ 251))
goto error_return;
includes_hash_initialized = TRUE;
diff --git a/bfd/archures.c b/bfd/archures.c
index fc2f85b..f4080a6 100644
--- a/bfd/archures.c
+++ b/bfd/archures.c
@@ -80,22 +80,22 @@ DESCRIPTION
.#define bfd_mach_m68040 6
.#define bfd_mach_m68060 7
.#define bfd_mach_cpu32 8
-.#define bfd_mach_mcf_isa_a 9
-.#define bfd_mach_mcf_isa_a_div 10
-.#define bfd_mach_mcf_isa_a_div_mac 11
-.#define bfd_mach_mcf_isa_a_div_emac 12
+.#define bfd_mach_mcf_isa_a_nodiv 9
+.#define bfd_mach_mcf_isa_a 10
+.#define bfd_mach_mcf_isa_a_mac 11
+.#define bfd_mach_mcf_isa_a_emac 12
.#define bfd_mach_mcf_isa_aplus 13
.#define bfd_mach_mcf_isa_aplus_mac 14
.#define bfd_mach_mcf_isa_aplus_emac 15
-.#define bfd_mach_mcf_isa_aplus_usp 16
-.#define bfd_mach_mcf_isa_aplus_usp_mac 17
-.#define bfd_mach_mcf_isa_aplus_usp_emac 18
+.#define bfd_mach_mcf_isa_b_nousp 16
+.#define bfd_mach_mcf_isa_b_nousp_mac 17
+.#define bfd_mach_mcf_isa_b_nousp_emac 18
.#define bfd_mach_mcf_isa_b 19
.#define bfd_mach_mcf_isa_b_mac 20
.#define bfd_mach_mcf_isa_b_emac 21
-.#define bfd_mach_mcf_isa_b_usp_float 22
-.#define bfd_mach_mcf_isa_b_usp_float_mac 23
-.#define bfd_mach_mcf_isa_b_usp_float_emac 24
+.#define bfd_mach_mcf_isa_b_float 22
+.#define bfd_mach_mcf_isa_b_float_mac 23
+.#define bfd_mach_mcf_isa_b_float_emac 24
. bfd_arch_vax, {* DEC Vax *}
. bfd_arch_i960, {* Intel 960 *}
. {* The order of the following is important.
@@ -1016,23 +1016,23 @@ bfd_default_scan (const bfd_arch_info_type *info, const char *string)
break;
case 5200:
arch = bfd_arch_m68k;
- number = bfd_mach_mcf_isa_a;
+ number = bfd_mach_mcf_isa_a_nodiv;
break;
case 5206:
arch = bfd_arch_m68k;
- number = bfd_mach_mcf_isa_a_div_mac;
+ number = bfd_mach_mcf_isa_a_mac;
break;
case 5307:
arch = bfd_arch_m68k;
- number = bfd_mach_mcf_isa_a_div_mac;
+ number = bfd_mach_mcf_isa_a_mac;
break;
case 5407:
arch = bfd_arch_m68k;
- number = bfd_mach_mcf_isa_b_mac;
+ number = bfd_mach_mcf_isa_b_nousp_mac;
break;
case 5282:
arch = bfd_arch_m68k;
- number = bfd_mach_mcf_isa_b_usp_float_emac;
+ number = bfd_mach_mcf_isa_aplus_emac;
break;
case 32000:
diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h
index 25ae6a4..9daa578 100644
--- a/bfd/bfd-in.h
+++ b/bfd/bfd-in.h
@@ -376,6 +376,8 @@ struct bfd_hash_table
struct bfd_hash_entry **table;
/* The number of slots in the hash table. */
unsigned int size;
+ /* The size of elements. */
+ unsigned int entsize;
/* A function used to create new elements in the hash table. The
first entry is itself a pointer to an element. When this
function is first invoked, this pointer will be NULL. However,
@@ -395,7 +397,8 @@ extern bfd_boolean bfd_hash_table_init
(struct bfd_hash_table *,
struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
struct bfd_hash_table *,
- const char *));
+ const char *),
+ unsigned int);
/* Initialize a hash table specifying a size. */
extern bfd_boolean bfd_hash_table_init_n
@@ -403,7 +406,7 @@ extern bfd_boolean bfd_hash_table_init_n
struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
struct bfd_hash_table *,
const char *),
- unsigned int size);
+ unsigned int, unsigned int);
/* Free up a hash table. */
extern void bfd_hash_table_free
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index cc9eb24..63fb521 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -383,6 +383,8 @@ struct bfd_hash_table
struct bfd_hash_entry **table;
/* The number of slots in the hash table. */
unsigned int size;
+ /* The size of elements. */
+ unsigned int entsize;
/* A function used to create new elements in the hash table. The
first entry is itself a pointer to an element. When this
function is first invoked, this pointer will be NULL. However,
@@ -402,7 +404,8 @@ extern bfd_boolean bfd_hash_table_init
(struct bfd_hash_table *,
struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
struct bfd_hash_table *,
- const char *));
+ const char *),
+ unsigned int);
/* Initialize a hash table specifying a size. */
extern bfd_boolean bfd_hash_table_init_n
@@ -410,7 +413,7 @@ extern bfd_boolean bfd_hash_table_init_n
struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
struct bfd_hash_table *,
const char *),
- unsigned int size);
+ unsigned int, unsigned int);
/* Free up a hash table. */
extern void bfd_hash_table_free
@@ -1674,22 +1677,22 @@ enum bfd_architecture
#define bfd_mach_m68040 6
#define bfd_mach_m68060 7
#define bfd_mach_cpu32 8
-#define bfd_mach_mcf_isa_a 9
-#define bfd_mach_mcf_isa_a_div 10
-#define bfd_mach_mcf_isa_a_div_mac 11
-#define bfd_mach_mcf_isa_a_div_emac 12
+#define bfd_mach_mcf_isa_a_nodiv 9
+#define bfd_mach_mcf_isa_a 10
+#define bfd_mach_mcf_isa_a_mac 11
+#define bfd_mach_mcf_isa_a_emac 12
#define bfd_mach_mcf_isa_aplus 13
#define bfd_mach_mcf_isa_aplus_mac 14
#define bfd_mach_mcf_isa_aplus_emac 15
-#define bfd_mach_mcf_isa_aplus_usp 16
-#define bfd_mach_mcf_isa_aplus_usp_mac 17
-#define bfd_mach_mcf_isa_aplus_usp_emac 18
+#define bfd_mach_mcf_isa_b_nousp 16
+#define bfd_mach_mcf_isa_b_nousp_mac 17
+#define bfd_mach_mcf_isa_b_nousp_emac 18
#define bfd_mach_mcf_isa_b 19
#define bfd_mach_mcf_isa_b_mac 20
#define bfd_mach_mcf_isa_b_emac 21
-#define bfd_mach_mcf_isa_b_usp_float 22
-#define bfd_mach_mcf_isa_b_usp_float_mac 23
-#define bfd_mach_mcf_isa_b_usp_float_emac 24
+#define bfd_mach_mcf_isa_b_float 22
+#define bfd_mach_mcf_isa_b_float_mac 23
+#define bfd_mach_mcf_isa_b_float_emac 24
bfd_arch_vax, /* DEC Vax */
bfd_arch_i960, /* Intel 960 */
/* The order of the following is important.
@@ -2585,6 +2588,11 @@ to compensate for the borrow when the low bits are added. */
BFD_RELOC_MIPS_TLS_TPREL_LO16,
+/* MIPS ELF relocations (VxWorks extensions). */
+ BFD_RELOC_MIPS_COPY,
+ BFD_RELOC_MIPS_JUMP_SLOT,
+
+
/* Fujitsu Frv Relocations. */
BFD_RELOC_FRV_LABEL16,
BFD_RELOC_FRV_LABEL24,
@@ -2699,6 +2707,11 @@ in the instruction. */
BFD_RELOC_X86_64_TPOFF32,
BFD_RELOC_X86_64_GOTOFF64,
BFD_RELOC_X86_64_GOTPC32,
+ BFD_RELOC_X86_64_GOT64,
+ BFD_RELOC_X86_64_GOTPCREL64,
+ BFD_RELOC_X86_64_GOTPC64,
+ BFD_RELOC_X86_64_GOTPLT64,
+ BFD_RELOC_X86_64_PLTOFF64,
BFD_RELOC_X86_64_GOTPC32_TLSDESC,
BFD_RELOC_X86_64_TLSDESC_CALL,
BFD_RELOC_X86_64_TLSDESC,
@@ -3072,6 +3085,22 @@ through 0. */
/* ADI Blackfin Long Jump pcrel. */
BFD_RELOC_BFIN_24_PCREL_JUMP_L,
+/* ADI Blackfin FD-PIC relocations. */
+ BFD_RELOC_BFIN_GOT17M4,
+ BFD_RELOC_BFIN_GOTHI,
+ BFD_RELOC_BFIN_GOTLO,
+ BFD_RELOC_BFIN_FUNCDESC,
+ BFD_RELOC_BFIN_FUNCDESC_GOT17M4,
+ BFD_RELOC_BFIN_FUNCDESC_GOTHI,
+ BFD_RELOC_BFIN_FUNCDESC_GOTLO,
+ BFD_RELOC_BFIN_FUNCDESC_VALUE,
+ BFD_RELOC_BFIN_FUNCDESC_GOTOFF17M4,
+ BFD_RELOC_BFIN_FUNCDESC_GOTOFFHI,
+ BFD_RELOC_BFIN_FUNCDESC_GOTOFFLO,
+ BFD_RELOC_BFIN_GOTOFF17M4,
+ BFD_RELOC_BFIN_GOTOFFHI,
+ BFD_RELOC_BFIN_GOTOFFLO,
+
/* ADI Blackfin GOT relocation. */
BFD_RELOC_BFIN_GOT,
diff --git a/bfd/bfd.c b/bfd/bfd.c
index c4b18e9..733f6ee 100644
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -1440,7 +1440,8 @@ bfd_preserve_save (bfd *abfd, struct bfd_preserve *preserve)
preserve->section_count = abfd->section_count;
preserve->section_htab = abfd->section_htab;
- if (! bfd_hash_table_init (&abfd->section_htab, bfd_section_hash_newfunc))
+ if (! bfd_hash_table_init (&abfd->section_htab, bfd_section_hash_newfunc,
+ sizeof (struct section_hash_entry)))
return FALSE;
abfd->tdata.any = NULL;
diff --git a/bfd/coff-arm.c b/bfd/coff-arm.c
index 4ae195c..6b83dc7 100644
--- a/bfd/coff-arm.c
+++ b/bfd/coff-arm.c
@@ -1,6 +1,6 @@
/* BFD back-end for ARM COFF files.
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004, 2005
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
Written by Cygnus Support.
@@ -879,8 +879,10 @@ coff_arm_link_hash_table_create (bfd * abfd)
if (ret == NULL)
return NULL;
- if (! _bfd_coff_link_hash_table_init
- (& ret->root, abfd, _bfd_coff_link_hash_newfunc))
+ if (!_bfd_coff_link_hash_table_init (&ret->root,
+ abfd,
+ _bfd_coff_link_hash_newfunc,
+ sizeof (struct coff_link_hash_entry)))
{
free (ret);
return NULL;
diff --git a/bfd/coff-h8300.c b/bfd/coff-h8300.c
index ef29664..9c858e1 100644
--- a/bfd/coff-h8300.c
+++ b/bfd/coff-h8300.c
@@ -1,6 +1,6 @@
/* BFD back-end for Renesas H8/300 COFF binaries.
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004, 2005
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
Written by Steve Chamberlain, <sac@cygnus.com>.
@@ -63,13 +63,6 @@ static struct bfd_hash_entry *
funcvec_hash_newfunc
(struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
-static bfd_boolean
-funcvec_hash_table_init
- (struct funcvec_hash_table *, bfd *,
- struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
- struct bfd_hash_table *,
- const char *));
-
static bfd_reloc_status_type special
(bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **);
static int select_reloc
@@ -181,13 +174,14 @@ funcvec_hash_table_init (struct funcvec_hash_table *table,
struct bfd_hash_entry *(*newfunc)
(struct bfd_hash_entry *,
struct bfd_hash_table *,
- const char *))
+ const char *),
+ unsigned int entsize)
{
/* Initialize our local fields, then call the generic initialization
routine. */
table->offset = 0;
table->abfd = abfd;
- return (bfd_hash_table_init (&table->root, newfunc));
+ return (bfd_hash_table_init (&table->root, newfunc, entsize));
}
/* Create the derived linker hash table. We use a derived hash table
@@ -204,7 +198,8 @@ h8300_coff_link_hash_table_create (bfd *abfd)
if (ret == NULL)
return NULL;
if (!_bfd_link_hash_table_init (&ret->root.root, abfd,
- _bfd_generic_link_hash_newfunc))
+ _bfd_generic_link_hash_newfunc,
+ sizeof (struct generic_link_hash_entry)))
{
free (ret);
return NULL;
@@ -1298,7 +1293,8 @@ h8300_bfd_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
/* And initialize the funcvec hash table. */
if (!funcvec_hash_table_init (funcvec_hash_table, abfd,
- funcvec_hash_newfunc))
+ funcvec_hash_newfunc,
+ sizeof (struct funcvec_hash_entry)))
{
bfd_release (abfd, funcvec_hash_table);
return FALSE;
diff --git a/bfd/coff-ppc.c b/bfd/coff-ppc.c
index 55f5f62..b442793 100644
--- a/bfd/coff-ppc.c
+++ b/bfd/coff-ppc.c
@@ -1,6 +1,6 @@
/* BFD back-end for PowerPC Microsoft Portable Executable files.
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004, 2005
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
Original version pieced together by Kim Knuttila (krk@cygnus.com)
@@ -127,11 +127,6 @@ struct ppc_coff_link_hash_table
static struct bfd_hash_entry *ppc_coff_link_hash_newfunc
PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *,
const char *));
-static bfd_boolean ppc_coff_link_hash_table_init
- PARAMS ((struct ppc_coff_link_hash_table *, bfd *,
- struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
- struct bfd_hash_table *,
- const char *)));
static struct bfd_link_hash_table *ppc_coff_link_hash_table_create
PARAMS ((bfd *));
static bfd_boolean coff_ppc_relocate_section
@@ -184,14 +179,14 @@ ppc_coff_link_hash_newfunc (entry, table, string)
/* Initialize a PE linker hash table. */
static bfd_boolean
-ppc_coff_link_hash_table_init (table, abfd, newfunc)
- struct ppc_coff_link_hash_table *table;
- bfd *abfd;
- struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
- struct bfd_hash_table *,
- const char *));
+ppc_coff_link_hash_table_init (struct ppc_coff_link_hash_table *table,
+ bfd *abfd,
+ struct bfd_hash_entry *(*newfunc) (struct bfd_hash_entry *,
+ struct bfd_hash_table *,
+ const char *),
+ unsigned int entsize)
{
- return _bfd_coff_link_hash_table_init (&table->root, abfd, newfunc);
+ return _bfd_coff_link_hash_table_init (&table->root, abfd, newfunc, entsize);
}
/* Create a PE linker hash table. */
@@ -206,8 +201,9 @@ ppc_coff_link_hash_table_create (abfd)
ret = (struct ppc_coff_link_hash_table *) bfd_malloc (amt);
if (ret == NULL)
return NULL;
- if (! ppc_coff_link_hash_table_init (ret, abfd,
- ppc_coff_link_hash_newfunc))
+ if (!ppc_coff_link_hash_table_init (ret, abfd,
+ ppc_coff_link_hash_newfunc,
+ sizeof (struct ppc_coff_link_hash_entry)))
{
free (ret);
return (struct bfd_link_hash_table *) NULL;
diff --git a/bfd/cofflink.c b/bfd/cofflink.c
index 151b1ff..a1f6684 100644
--- a/bfd/cofflink.c
+++ b/bfd/cofflink.c
@@ -1,6 +1,6 @@
/* COFF specific linker code.
Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
- 2004, 2005 Free Software Foundation, Inc.
+ 2004, 2005, 2006 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support.
This file is part of BFD, the Binary File Descriptor library.
@@ -94,10 +94,11 @@ _bfd_coff_link_hash_table_init (struct coff_link_hash_table *table,
bfd *abfd,
struct bfd_hash_entry *(*newfunc) (struct bfd_hash_entry *,
struct bfd_hash_table *,
- const char *))
+ const char *),
+ unsigned int entsize)
{
memset (&table->stab_info, 0, sizeof (table->stab_info));
- return _bfd_link_hash_table_init (&table->root, abfd, newfunc);
+ return _bfd_link_hash_table_init (&table->root, abfd, newfunc, entsize);
}
/* Create a COFF linker hash table. */
@@ -113,7 +114,8 @@ _bfd_coff_link_hash_table_create (bfd *abfd)
return NULL;
if (! _bfd_coff_link_hash_table_init (ret, abfd,
- _bfd_coff_link_hash_newfunc))
+ _bfd_coff_link_hash_newfunc,
+ sizeof (struct coff_link_hash_entry)))
{
free (ret);
return (struct bfd_link_hash_table *) NULL;
diff --git a/bfd/config.bfd b/bfd/config.bfd
index 37dd03c..ccd0de8 100644
--- a/bfd/config.bfd
+++ b/bfd/config.bfd
@@ -313,7 +313,8 @@ case "${targ}" in
bfin-*-*)
targ_defvec=bfd_elf32_bfin_vec
- tar_underscore=yes
+ targ_selvecs=bfd_elf32_bfinfdpic_vec
+ targ_underscore=yes
;;
c30-*-*aout* | tic30-*-*aout*)
@@ -868,6 +869,16 @@ case "${targ}" in
targ_defvec=ecoff_big_vec
targ_selvecs=ecoff_little_vec
;;
+#ifdef BFD64
+ mips*el-*-vxworks*)
+ targ_defvec=bfd_elf32_littlemips_vxworks_vec
+ targ_selvecs="bfd_elf32_littlemips_vec bfd_elf32_bigmips_vxworks_vec bfd_elf32_bigmips_vec bfd_elf64_bigmips_vec bfd_elf64_littlemips_vec"
+ ;;
+ mips*-*-vxworks*)
+ targ_defvec=bfd_elf32_bigmips_vxworks_vec
+ targ_selvecs="bfd_elf32_bigmips_vec bfd_elf32_littlemips_vxworks_vec bfd_elf32_bigmips_vec bfd_elf64_bigmips_vec bfd_elf64_littlemips_vec"
+ ;;
+#endif
mips*el-*-elf* | mips*el-*-vxworks* | mips*-*-chorus*)
targ_defvec=bfd_elf32_littlemips_vec
targ_selvecs="bfd_elf32_bigmips_vec bfd_elf64_bigmips_vec bfd_elf64_littlemips_vec"
diff --git a/bfd/configure b/bfd/configure
index b79f0da..5ad2bc4 100755
--- a/bfd/configure
+++ b/bfd/configure
@@ -13071,14 +13071,17 @@ do
bfd_elf32_am33lin_vec) tb="$tb elf32-am33lin.lo elf32.lo $elf" ;;
bfd_elf32_avr_vec) tb="$tb elf32-avr.lo elf32.lo $elf" ;;
bfd_elf32_bfin_vec) tb="$tb elf32-bfin.lo elf32.lo $elf" ;;
+ bfd_elf32_bfinfdpic_vec) tb="$tb elf32-bfin.lo elf32.lo $elf" ;;
bfd_elf32_big_generic_vec) tb="$tb elf32-gen.lo elf32.lo $elf" ;;
bfd_elf32_bigarc_vec) tb="$tb elf32-arc.lo elf32.lo $elf" ;;
- bfd_elf32_bigarm_vec) tb="$tb elf32-arm.lo elf32.lo $elf" ;;
+ bfd_elf32_bigarm_vec) tb="$tb elf32-arm.lo elf32.lo elf-vxworks.lo $elf" ;;
bfd_elf32_bigarm_symbian_vec)
- tb="$tb elf32-arm.lo elf32.lo $elf" ;;
+ tb="$tb elf32-arm.lo elf32.lo elf-vxworks.lo $elf" ;;
bfd_elf32_bigarm_vxworks_vec)
- tb="$tb elf32-arm.lo elf32.lo $elf" ;;
- bfd_elf32_bigmips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo" ;;
+ tb="$tb elf32-arm.lo elf32.lo elf-vxworks.lo $elf" ;;
+ bfd_elf32_bigmips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo" ;;
+ bfd_elf32_bigmips_vxworks_vec)
+ tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.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_crx_vec) tb="$tb elf32-crx.lo elf32.lo $elf" ;;
@@ -13106,11 +13109,13 @@ do
bfd_elf32_little_generic_vec) tb="$tb elf32-gen.lo elf32.lo $elf" ;;
bfd_elf32_littlearc_vec) tb="$tb elf32-arc.lo elf32.lo $elf" ;;
bfd_elf32_littlearm_symbian_vec)
- tb="$tb elf32-arm.lo elf32.lo $elf" ;;
+ tb="$tb elf32-arm.lo elf32.lo elf-vxworks.lo $elf" ;;
bfd_elf32_littlearm_vxworks_vec)
- tb="$tb elf32-arm.lo elf32.lo $elf" ;;
- bfd_elf32_littlearm_vec) tb="$tb elf32-arm.lo elf32.lo $elf" ;;
- bfd_elf32_littlemips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo" ;;
+ tb="$tb elf32-arm.lo elf32.lo elf-vxworks.lo $elf" ;;
+ bfd_elf32_littlearm_vec) tb="$tb elf32-arm.lo elf32.lo elf-vxworks.lo $elf" ;;
+ bfd_elf32_littlemips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo" ;;
+ bfd_elf32_littlemips_vxworks_vec)
+ tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo" ;;
bfd_elf32_m32c_vec) tb="$tb elf32-m32c.lo elf32.lo $elf" ;;
bfd_elf32_m32r_vec) tb="$tb elf32-m32r.lo elf32.lo $elf" ;;
bfd_elf32_m32rle_vec) tb="$tb elf32-m32r.lo elf32.lo $elf" ;;
@@ -13126,10 +13131,10 @@ do
bfd_elf32_mn10300_vec) tb="$tb elf-m10300.lo elf32.lo $elf" ;;
bfd_elf32_mt_vec) tb="$tb elf32-mt.lo elf32.lo $elf" ;;
bfd_elf32_msp430_vec) tb="$tb elf32-msp430.lo elf32.lo $elf" ;;
- bfd_elf32_nbigmips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
- bfd_elf32_nlittlemips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
- bfd_elf32_ntradbigmips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
- bfd_elf32_ntradlittlemips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
+ bfd_elf32_nbigmips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
+ bfd_elf32_nlittlemips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
+ bfd_elf32_ntradbigmips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
+ bfd_elf32_ntradlittlemips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
bfd_elf32_openrisc_vec) tb="$tb elf32-openrisc.lo elf32.lo $elf" ;;
bfd_elf32_or32_big_vec) tb="$tb elf32-or32.lo elf32.lo $elf" ;;
bfd_elf32_pj_vec) tb="$tb elf32-pj.lo elf32.lo $elf";;
@@ -13155,8 +13160,8 @@ do
bfd_elf32_shlnbsd_vec) tb="$tb elf32-sh.lo elf32.lo $elf coff-sh.lo cofflink.lo" ;;
bfd_elf32_shnbsd_vec) tb="$tb elf32-sh.lo elf32.lo $elf coff-sh.lo cofflink.lo" ;;
bfd_elf32_sparc_vec) tb="$tb elf32-sparc.lo elfxx-sparc.lo elf32.lo $elf" ;;
- bfd_elf32_tradbigmips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo" ;;
- bfd_elf32_tradlittlemips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo" ;;
+ bfd_elf32_tradbigmips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo" ;;
+ bfd_elf32_tradlittlemips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo" ;;
bfd_elf32_us_cris_vec) tb="$tb elf32-cris.lo elf32.lo $elf" ;;
bfd_elf32_v850_vec) tb="$tb elf32-v850.lo elf32.lo $elf" ;;
bfd_elf32_vax_vec) tb="$tb elf32-vax.lo elf32.lo $elf" ;;
@@ -13167,14 +13172,14 @@ do
bfd_elf64_alpha_freebsd_vec) tb="$tb elf64-alpha.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_alpha_vec) tb="$tb elf64-alpha.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_big_generic_vec) tb="$tb elf64-gen.lo elf64.lo $elf"; target_size=64 ;;
- bfd_elf64_bigmips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
+ bfd_elf64_bigmips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
bfd_elf64_hppa_linux_vec) tb="$tb elf64-hppa.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_hppa_vec) tb="$tb elf64-hppa.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_ia64_big_vec) tb="$tb elf64-ia64.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_ia64_hpux_big_vec) tb="$tb elf64-ia64.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_ia64_little_vec) tb="$tb elf64-ia64.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_little_generic_vec) tb="$tb elf64-gen.lo elf64.lo $elf"; target_size=64 ;;
- bfd_elf64_littlemips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
+ bfd_elf64_littlemips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
bfd_elf64_mmix_vec) tb="$tb elf64-mmix.lo elf64.lo $elf" target_size=64 ;;
bfd_elf64_powerpc_vec) tb="$tb elf64-ppc.lo elf64-gen.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_powerpcle_vec) tb="$tb elf64-ppc.lo elf64-gen.lo elf64.lo $elf" target_size=64 ;;
@@ -13186,8 +13191,8 @@ do
bfd_elf64_sh64lnbsd_vec) tb="$tb elf64-sh64.lo elf64.lo $elf" target_size=64 ;;
bfd_elf64_sh64nbsd_vec) tb="$tb elf64-sh64.lo elf64.lo $elf" target_size=64 ;;
bfd_elf64_sparc_vec) tb="$tb elf64-sparc.lo elfxx-sparc.lo elf64.lo $elf"; target_size=64 ;;
- bfd_elf64_tradbigmips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
- bfd_elf64_tradlittlemips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
+ bfd_elf64_tradbigmips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
+ bfd_elf64_tradlittlemips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
bfd_elf64_x86_64_vec) tb="$tb elf64-x86-64.lo elf64.lo $elf"; target_size=64 ;;
bfd_mmo_vec) tb="$tb mmo.lo" target_size=64 ;;
bfd_powerpc_pe_vec) tb="$tb pe-ppc.lo peigen.lo cofflink.lo" ;;
diff --git a/bfd/configure.in b/bfd/configure.in
index b90e1fa..bc8dabb 100644
--- a/bfd/configure.in
+++ b/bfd/configure.in
@@ -584,14 +584,17 @@ do
bfd_elf32_am33lin_vec) tb="$tb elf32-am33lin.lo elf32.lo $elf" ;;
bfd_elf32_avr_vec) tb="$tb elf32-avr.lo elf32.lo $elf" ;;
bfd_elf32_bfin_vec) tb="$tb elf32-bfin.lo elf32.lo $elf" ;;
+ bfd_elf32_bfinfdpic_vec) tb="$tb elf32-bfin.lo elf32.lo $elf" ;;
bfd_elf32_big_generic_vec) tb="$tb elf32-gen.lo elf32.lo $elf" ;;
bfd_elf32_bigarc_vec) tb="$tb elf32-arc.lo elf32.lo $elf" ;;
- bfd_elf32_bigarm_vec) tb="$tb elf32-arm.lo elf32.lo $elf" ;;
+ bfd_elf32_bigarm_vec) tb="$tb elf32-arm.lo elf32.lo elf-vxworks.lo $elf" ;;
bfd_elf32_bigarm_symbian_vec)
- tb="$tb elf32-arm.lo elf32.lo $elf" ;;
+ tb="$tb elf32-arm.lo elf32.lo elf-vxworks.lo $elf" ;;
bfd_elf32_bigarm_vxworks_vec)
- tb="$tb elf32-arm.lo elf32.lo $elf" ;;
- bfd_elf32_bigmips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo" ;;
+ tb="$tb elf32-arm.lo elf32.lo elf-vxworks.lo $elf" ;;
+ bfd_elf32_bigmips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo" ;;
+ bfd_elf32_bigmips_vxworks_vec)
+ tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.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_crx_vec) tb="$tb elf32-crx.lo elf32.lo $elf" ;;
@@ -619,11 +622,13 @@ do
bfd_elf32_little_generic_vec) tb="$tb elf32-gen.lo elf32.lo $elf" ;;
bfd_elf32_littlearc_vec) tb="$tb elf32-arc.lo elf32.lo $elf" ;;
bfd_elf32_littlearm_symbian_vec)
- tb="$tb elf32-arm.lo elf32.lo $elf" ;;
+ tb="$tb elf32-arm.lo elf32.lo elf-vxworks.lo $elf" ;;
bfd_elf32_littlearm_vxworks_vec)
- tb="$tb elf32-arm.lo elf32.lo $elf" ;;
- bfd_elf32_littlearm_vec) tb="$tb elf32-arm.lo elf32.lo $elf" ;;
- bfd_elf32_littlemips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo" ;;
+ tb="$tb elf32-arm.lo elf32.lo elf-vxworks.lo $elf" ;;
+ bfd_elf32_littlearm_vec) tb="$tb elf32-arm.lo elf32.lo elf-vxworks.lo $elf" ;;
+ bfd_elf32_littlemips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo" ;;
+ bfd_elf32_littlemips_vxworks_vec)
+ tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo" ;;
bfd_elf32_m32c_vec) tb="$tb elf32-m32c.lo elf32.lo $elf" ;;
bfd_elf32_m32r_vec) tb="$tb elf32-m32r.lo elf32.lo $elf" ;;
bfd_elf32_m32rle_vec) tb="$tb elf32-m32r.lo elf32.lo $elf" ;;
@@ -639,10 +644,10 @@ do
bfd_elf32_mn10300_vec) tb="$tb elf-m10300.lo elf32.lo $elf" ;;
bfd_elf32_mt_vec) tb="$tb elf32-mt.lo elf32.lo $elf" ;;
bfd_elf32_msp430_vec) tb="$tb elf32-msp430.lo elf32.lo $elf" ;;
- bfd_elf32_nbigmips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
- bfd_elf32_nlittlemips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
- bfd_elf32_ntradbigmips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
- bfd_elf32_ntradlittlemips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
+ bfd_elf32_nbigmips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
+ bfd_elf32_nlittlemips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
+ bfd_elf32_ntradbigmips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
+ bfd_elf32_ntradlittlemips_vec) tb="$tb elfn32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
bfd_elf32_openrisc_vec) tb="$tb elf32-openrisc.lo elf32.lo $elf" ;;
bfd_elf32_or32_big_vec) tb="$tb elf32-or32.lo elf32.lo $elf" ;;
bfd_elf32_pj_vec) tb="$tb elf32-pj.lo elf32.lo $elf";;
@@ -668,8 +673,8 @@ do
bfd_elf32_shlnbsd_vec) tb="$tb elf32-sh.lo elf32.lo $elf coff-sh.lo cofflink.lo" ;;
bfd_elf32_shnbsd_vec) tb="$tb elf32-sh.lo elf32.lo $elf coff-sh.lo cofflink.lo" ;;
bfd_elf32_sparc_vec) tb="$tb elf32-sparc.lo elfxx-sparc.lo elf32.lo $elf" ;;
- bfd_elf32_tradbigmips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo" ;;
- bfd_elf32_tradlittlemips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo" ;;
+ bfd_elf32_tradbigmips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo" ;;
+ bfd_elf32_tradlittlemips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo" ;;
bfd_elf32_us_cris_vec) tb="$tb elf32-cris.lo elf32.lo $elf" ;;
bfd_elf32_v850_vec) tb="$tb elf32-v850.lo elf32.lo $elf" ;;
bfd_elf32_vax_vec) tb="$tb elf32-vax.lo elf32.lo $elf" ;;
@@ -680,14 +685,14 @@ do
bfd_elf64_alpha_freebsd_vec) tb="$tb elf64-alpha.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_alpha_vec) tb="$tb elf64-alpha.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_big_generic_vec) tb="$tb elf64-gen.lo elf64.lo $elf"; target_size=64 ;;
- bfd_elf64_bigmips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
+ bfd_elf64_bigmips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
bfd_elf64_hppa_linux_vec) tb="$tb elf64-hppa.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_hppa_vec) tb="$tb elf64-hppa.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_ia64_big_vec) tb="$tb elf64-ia64.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_ia64_hpux_big_vec) tb="$tb elf64-ia64.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_ia64_little_vec) tb="$tb elf64-ia64.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_little_generic_vec) tb="$tb elf64-gen.lo elf64.lo $elf"; target_size=64 ;;
- bfd_elf64_littlemips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
+ bfd_elf64_littlemips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
bfd_elf64_mmix_vec) tb="$tb elf64-mmix.lo elf64.lo $elf" target_size=64 ;;
bfd_elf64_powerpc_vec) tb="$tb elf64-ppc.lo elf64-gen.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_powerpcle_vec) tb="$tb elf64-ppc.lo elf64-gen.lo elf64.lo $elf" target_size=64 ;;
@@ -699,8 +704,8 @@ do
bfd_elf64_sh64lnbsd_vec) tb="$tb elf64-sh64.lo elf64.lo $elf" target_size=64 ;;
bfd_elf64_sh64nbsd_vec) tb="$tb elf64-sh64.lo elf64.lo $elf" target_size=64 ;;
bfd_elf64_sparc_vec) tb="$tb elf64-sparc.lo elfxx-sparc.lo elf64.lo $elf"; target_size=64 ;;
- bfd_elf64_tradbigmips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
- bfd_elf64_tradlittlemips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
+ bfd_elf64_tradbigmips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
+ bfd_elf64_tradlittlemips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
bfd_elf64_x86_64_vec) tb="$tb elf64-x86-64.lo elf64.lo $elf"; target_size=64 ;;
bfd_mmo_vec) tb="$tb mmo.lo" target_size=64 ;;
bfd_powerpc_pe_vec) tb="$tb pe-ppc.lo peigen.lo cofflink.lo" ;;
diff --git a/bfd/cpu-arm.c b/bfd/cpu-arm.c
index 3f56e8f..a28a1f9 100644
--- a/bfd/cpu-arm.c
+++ b/bfd/cpu-arm.c
@@ -404,9 +404,12 @@ bfd_arm_get_mach_from_notes (bfd *abfd, const char *note_section)
bfd_boolean
bfd_is_arm_mapping_symbol_name (const char * name)
{
+ /* The ARM compiler outputs several obsolete forms. Recognize them
+ in addition to the standard $a, $t and $d. */
return (name != NULL)
&& (name[0] == '$')
- && ((name[1] == 'a') || (name[1] == 't') || (name[1] == 'd'))
- && (name[2] == 0);
+ && ((name[1] == 'a') || (name[1] == 't') || (name[1] == 'd')
+ || (name[1] == 'm') || (name[1] == 'f') || (name[1] == 'p'))
+ && (name[2] == 0 || name[2] == '.');
}
diff --git a/bfd/cpu-m68k.c b/bfd/cpu-m68k.c
index 93b60f9..3662789 100644
--- a/bfd/cpu-m68k.c
+++ b/bfd/cpu-m68k.c
@@ -24,8 +24,12 @@
#include "libbfd.h"
#include "opcode/m68k.h"
+static const bfd_arch_info_type *
+bfd_m68k_compatible (const bfd_arch_info_type *a,
+ const bfd_arch_info_type *b);
+
#define N(name, print,d,next) \
-{ 32, 32, 8, bfd_arch_m68k, name, "m68k",print,2,d,bfd_default_compatible,bfd_default_scan, next, }
+{ 32, 32, 8, bfd_arch_m68k, name, "m68k",print,2,d,bfd_m68k_compatible,bfd_default_scan, next, }
static const bfd_arch_info_type arch_info_struct[] =
{
@@ -39,25 +43,25 @@ static const bfd_arch_info_type arch_info_struct[] =
N(bfd_mach_cpu32, "m68k:cpu32", FALSE, &arch_info_struct[8]),
/* Various combinations of CF architecture features */
- N(bfd_mach_mcf_isa_a, "m68k:isa-a",
+ N(bfd_mach_mcf_isa_a_nodiv, "m68k:isa-a:nodiv",
FALSE, &arch_info_struct[9]),
- N(bfd_mach_mcf_isa_a_div, "m68k:isa-a:div",
+ N(bfd_mach_mcf_isa_a, "m68k:isa-a",
FALSE, &arch_info_struct[10]),
- N(bfd_mach_mcf_isa_a_div_mac, "m68k:isa-a:div:mac",
+ N(bfd_mach_mcf_isa_a_mac, "m68k:isa-a:mac",
FALSE, &arch_info_struct[11]),
- N(bfd_mach_mcf_isa_a_div_emac, "m68k:isa-a:div:emac",
+ N(bfd_mach_mcf_isa_a_emac, "m68k:isa-a:emac",
FALSE, &arch_info_struct[12]),
- N(bfd_mach_mcf_isa_aplus, "m68k:isa-a+",
+ N(bfd_mach_mcf_isa_aplus, "m68k:isa-aplus",
FALSE, &arch_info_struct[13]),
- N(bfd_mach_mcf_isa_aplus_mac, "m68k:isa-a+:mac",
+ N(bfd_mach_mcf_isa_aplus_mac, "m68k:isa-aplus:mac",
FALSE, &arch_info_struct[14]),
- N(bfd_mach_mcf_isa_aplus_emac, "m68k:isa-a+:emac",
+ N(bfd_mach_mcf_isa_aplus_emac, "m68k:isa-aplus:emac",
FALSE, &arch_info_struct[15]),
- N(bfd_mach_mcf_isa_aplus_usp, "m68k:isa-a+:usp",
+ N(bfd_mach_mcf_isa_b_nousp, "m68k:isa-b:nousp",
FALSE, &arch_info_struct[16]),
- N(bfd_mach_mcf_isa_aplus_usp_mac, "m68k:isa-a+:usp:mac",
+ N(bfd_mach_mcf_isa_b_nousp_mac, "m68k:isa-b:nousp:mac",
FALSE, &arch_info_struct[17]),
- N(bfd_mach_mcf_isa_aplus_usp_emac, "m68k:isa-a+:usp:emac",
+ N(bfd_mach_mcf_isa_b_nousp_emac, "m68k:isa-b:nousp:emac",
FALSE, &arch_info_struct[18]),
N(bfd_mach_mcf_isa_b, "m68k:isa-b",
FALSE, &arch_info_struct[19]),
@@ -65,28 +69,26 @@ static const bfd_arch_info_type arch_info_struct[] =
FALSE, &arch_info_struct[20]),
N(bfd_mach_mcf_isa_b_emac, "m68k:isa-b:emac",
FALSE, &arch_info_struct[21]),
- N(bfd_mach_mcf_isa_b_usp_float, "m68k:isa-b:usp:float",
+ N(bfd_mach_mcf_isa_b_float, "m68k:isa-b:float",
FALSE, &arch_info_struct[22]),
- N(bfd_mach_mcf_isa_b_usp_float_mac, "m68k:isa-b:usp:float:mac",
+ N(bfd_mach_mcf_isa_b_float_mac, "m68k:isa-b:float:mac",
FALSE, &arch_info_struct[23]),
- N(bfd_mach_mcf_isa_b_usp_float_emac, "m68k:isa-b:usp:float:emac",
+ N(bfd_mach_mcf_isa_b_float_emac, "m68k:isa-b:float:emac",
FALSE, &arch_info_struct[24]),
/* Legacy names for CF architectures */
- N(bfd_mach_mcf_isa_a, "m68k:5200", FALSE, &arch_info_struct[25]),
- N(bfd_mach_mcf_isa_a_div_mac,"m68k:5206e", FALSE, &arch_info_struct[26]),
- N(bfd_mach_mcf_isa_a_div_mac, "m68k:5307", FALSE, &arch_info_struct[27]),
- N(bfd_mach_mcf_isa_b_mac, "m68k:5407", FALSE, &arch_info_struct[28]),
- N(bfd_mach_mcf_isa_aplus_usp_emac, "m68k:528x",
- FALSE, &arch_info_struct[29]),
- N(bfd_mach_mcf_isa_aplus_usp_emac, "m68k:521x",
- FALSE, &arch_info_struct[30]),
- N(bfd_mach_mcf_isa_a_div_emac, "m68k:5249", FALSE, &arch_info_struct[31]),
- N(bfd_mach_mcf_isa_b_usp_float_emac, "m68k:547x",
+ N(bfd_mach_mcf_isa_a_nodiv, "m68k:5200", FALSE, &arch_info_struct[25]),
+ N(bfd_mach_mcf_isa_a_mac,"m68k:5206e", FALSE, &arch_info_struct[26]),
+ N(bfd_mach_mcf_isa_a_mac, "m68k:5307", FALSE, &arch_info_struct[27]),
+ N(bfd_mach_mcf_isa_b_nousp_mac, "m68k:5407", FALSE, &arch_info_struct[28]),
+ N(bfd_mach_mcf_isa_aplus_emac, "m68k:528x", FALSE, &arch_info_struct[29]),
+ N(bfd_mach_mcf_isa_aplus_emac, "m68k:521x", FALSE, &arch_info_struct[30]),
+ N(bfd_mach_mcf_isa_a_emac, "m68k:5249", FALSE, &arch_info_struct[31]),
+ N(bfd_mach_mcf_isa_b_float_emac, "m68k:547x",
FALSE, &arch_info_struct[32]),
- N(bfd_mach_mcf_isa_b_usp_float_emac, "m68k:548x",
+ N(bfd_mach_mcf_isa_b_float_emac, "m68k:548x",
FALSE, &arch_info_struct[33]),
- N(bfd_mach_mcf_isa_b_usp_float_emac, "m68k:cfv4e", FALSE, 0),
+ N(bfd_mach_mcf_isa_b_float_emac, "m68k:cfv4e", FALSE, 0),
};
const bfd_arch_info_type bfd_m68k_arch =
@@ -109,15 +111,15 @@ static const unsigned m68k_arch_features[] =
mcfisa_a|mcfhwdiv,
mcfisa_a|mcfhwdiv|mcfmac,
mcfisa_a|mcfhwdiv|mcfemac,
- mcfisa_a|mcfisa_aa|mcfhwdiv,
- mcfisa_a|mcfisa_aa|mcfhwdiv|mcfmac,
- mcfisa_a|mcfisa_aa|mcfhwdiv|mcfemac,
mcfisa_a|mcfisa_aa|mcfhwdiv|mcfusp,
mcfisa_a|mcfisa_aa|mcfhwdiv|mcfusp|mcfmac,
mcfisa_a|mcfisa_aa|mcfhwdiv|mcfusp|mcfemac,
mcfisa_a|mcfhwdiv|mcfisa_b,
mcfisa_a|mcfhwdiv|mcfisa_b|mcfmac,
mcfisa_a|mcfhwdiv|mcfisa_b|mcfemac,
+ mcfisa_a|mcfhwdiv|mcfisa_b|mcfusp,
+ mcfisa_a|mcfhwdiv|mcfisa_b|mcfusp|mcfmac,
+ mcfisa_a|mcfhwdiv|mcfisa_b|mcfusp|mcfemac,
mcfisa_a|mcfhwdiv|mcfisa_b|mcfusp|cfloat,
mcfisa_a|mcfhwdiv|mcfisa_b|mcfusp|cfloat|mcfmac,
mcfisa_a|mcfhwdiv|mcfisa_b|mcfusp|cfloat|mcfemac,
@@ -181,3 +183,43 @@ int bfd_m68k_features_to_mach (unsigned features)
}
return superset ? superset : subset;
}
+
+static const bfd_arch_info_type *
+bfd_m68k_compatible (const bfd_arch_info_type *a,
+ const bfd_arch_info_type *b)
+{
+ if (a->arch != b->arch)
+ return NULL;
+
+ if (a->bits_per_word != b->bits_per_word)
+ return NULL;
+
+ if (!a->mach)
+ return b;
+ if (!b->mach)
+ return a;
+
+ if (a->mach <= bfd_mach_m68060 && b->mach <= bfd_mach_m68060)
+ /* Merge m68k machine. */
+ return a->mach > b->mach ? a : b;
+ else if (a->mach >= bfd_mach_mcf_isa_a_nodiv
+ && b->mach >= bfd_mach_mcf_isa_a_nodiv)
+ {
+ /* Merge cf machine. */
+ unsigned features = (bfd_m68k_mach_to_features (a->mach)
+ | bfd_m68k_mach_to_features (b->mach));
+
+ /* ISA A+ and ISA B are incompatible. */
+ if ((~features & (mcfisa_aa | mcfisa_b)) == 0)
+ return NULL;
+
+ /* MAC and EMAC code cannot be merged. */
+ if ((~features & (mcfmac | mcfemac)) == 0)
+ return NULL;
+
+ return bfd_lookup_arch (a->arch, bfd_m68k_features_to_mach (features));
+ }
+ else
+ /* They are incompatible. */
+ return NULL;
+}
diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c
index f9cff9b..ae68d18 100644
--- a/bfd/dwarf2.c
+++ b/bfd/dwarf2.c
@@ -1,6 +1,6 @@
/* DWARF 2 support.
Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
- 2004, 2005 Free Software Foundation, Inc.
+ 2004, 2005, 2006 Free Software Foundation, Inc.
Adapted from gdb/dwarf2read.c by Gavin Koch of Cygnus Solutions
(gavin@cygnus.com).
@@ -74,6 +74,12 @@ struct dwarf_block
bfd_byte *data;
};
+struct loadable_section
+{
+ asection *section;
+ bfd_vma adj_vma;
+};
+
struct dwarf2_debug
{
/* A list of all previously read comp_units. */
@@ -124,6 +130,12 @@ struct dwarf2_debug
calling chain for subsequent calls to bfd_find_inliner_info to
use. */
struct funcinfo *inliner_chain;
+
+ /* Number of loadable sections. */
+ unsigned int loadable_section_count;
+
+ /* Array of loadable sections. */
+ struct loadable_section *loadable_sections;
};
struct arange
@@ -481,21 +493,21 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash)
amt *= sizeof (struct attr_abbrev);
tmp = bfd_realloc (cur_abbrev->attrs, amt);
if (tmp == NULL)
- {
- size_t i;
-
- for (i = 0; i < ABBREV_HASH_SIZE; i++)
- {
- struct abbrev_info *abbrev = abbrevs[i];
-
- while (abbrev)
- {
- free (abbrev->attrs);
- abbrev = abbrev->next;
- }
- }
- return NULL;
- }
+ {
+ size_t i;
+
+ for (i = 0; i < ABBREV_HASH_SIZE; i++)
+ {
+ struct abbrev_info *abbrev = abbrevs[i];
+
+ while (abbrev)
+ {
+ free (abbrev->attrs);
+ abbrev = abbrev->next;
+ }
+ }
+ return NULL;
+ }
cur_abbrev->attrs = tmp;
}
@@ -521,7 +533,7 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash)
for the next compile unit) or if the end of the abbreviation
table is reached. */
if ((unsigned int) (abbrev_ptr - stash->dwarf_abbrev_buffer)
- >= stash->dwarf_abbrev_size)
+ >= stash->dwarf_abbrev_size)
break;
abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
abbrev_ptr += bytes_read;
@@ -744,6 +756,17 @@ struct varinfo
unsigned int stack: 1;
};
+/* Return TRUE if NEW_LINE should sort after LINE. */
+
+static inline bfd_boolean
+new_line_sorts_after (struct line_info *new_line, struct line_info *line)
+{
+ return (new_line->address > line->address
+ || (new_line->address == line->address
+ && new_line->end_sequence < line->end_sequence));
+}
+
+
/* Adds a new entry to the line_info list in the line_info_table, ensuring
that the list is sorted. Note that the line_info list is sorted from
highest to lowest VMA (with possible duplicates); that is,
@@ -760,6 +783,21 @@ add_line_info (struct line_info_table *table,
bfd_size_type amt = sizeof (struct line_info);
struct line_info* info = bfd_alloc (table->abfd, amt);
+ /* Set member data of 'info'. */
+ info->address = address;
+ info->line = line;
+ info->column = column;
+ info->end_sequence = end_sequence;
+
+ if (filename && filename[0])
+ {
+ info->filename = bfd_alloc (table->abfd, strlen (filename) + 1);
+ if (info->filename)
+ strcpy (info->filename, filename);
+ }
+ else
+ info->filename = NULL;
+
/* Find the correct location for 'info'. Normally we will receive
new line_info data 1) in order and 2) with increasing VMAs.
However some compilers break the rules (cf. decode_line_info) and
@@ -775,70 +813,45 @@ add_line_info (struct line_info_table *table,
Note: we may receive duplicate entries from 'decode_line_info'. */
- while (1)
- if (!table->last_line
- || address >= table->last_line->address)
- {
- /* Normal case: add 'info' to the beginning of the list */
- info->prev_line = table->last_line;
- table->last_line = info;
-
- /* lcl_head: initialize to head a *possible* sequence at the end. */
- if (!table->lcl_head)
- table->lcl_head = info;
- break;
- }
- else if (!table->lcl_head->prev_line
- && table->lcl_head->address > address)
- {
- /* Abnormal but easy: lcl_head is 1) at the *end* of the line
- list and 2) the head of 'info'. */
- info->prev_line = NULL;
- table->lcl_head->prev_line = info;
- break;
- }
- else if (table->lcl_head->prev_line
- && table->lcl_head->address > address
- && address >= table->lcl_head->prev_line->address)
- {
- /* Abnormal but easy: lcl_head is 1) in the *middle* of the line
- list and 2) the head of 'info'. */
- info->prev_line = table->lcl_head->prev_line;
- table->lcl_head->prev_line = info;
- break;
- }
- else
- {
- /* Abnormal and hard: Neither 'last_line' nor 'lcl_head' are valid
- heads for 'info'. Reset 'lcl_head' and repeat. */
- struct line_info* li2 = table->last_line; /* always non-NULL */
- struct line_info* li1 = li2->prev_line;
-
- while (li1)
- {
- if (li2->address > address && address >= li1->address)
- break;
-
- li2 = li1; /* always non-NULL */
- li1 = li1->prev_line;
- }
- table->lcl_head = li2;
- }
-
- /* Set member data of 'info'. */
- info->address = address;
- info->line = line;
- info->column = column;
- info->end_sequence = end_sequence;
+ if (!table->last_line
+ || new_line_sorts_after (info, table->last_line))
+ {
+ /* Normal case: add 'info' to the beginning of the list */
+ info->prev_line = table->last_line;
+ table->last_line = info;
- if (filename && filename[0])
+ /* lcl_head: initialize to head a *possible* sequence at the end. */
+ if (!table->lcl_head)
+ table->lcl_head = info;
+ }
+ else if (!new_line_sorts_after (info, table->lcl_head)
+ && (!table->lcl_head->prev_line
+ || new_line_sorts_after (info, table->lcl_head->prev_line)))
{
- info->filename = bfd_alloc (table->abfd, strlen (filename) + 1);
- if (info->filename)
- strcpy (info->filename, filename);
+ /* Abnormal but easy: lcl_head is the head of 'info'. */
+ info->prev_line = table->lcl_head->prev_line;
+ table->lcl_head->prev_line = info;
}
else
- info->filename = NULL;
+ {
+ /* Abnormal and hard: Neither 'last_line' nor 'lcl_head' are valid
+ heads for 'info'. Reset 'lcl_head'. */
+ struct line_info* li2 = table->last_line; /* always non-NULL */
+ struct line_info* li1 = li2->prev_line;
+
+ while (li1)
+ {
+ if (!new_line_sorts_after (info, li2)
+ && new_line_sorts_after (info, li1))
+ break;
+
+ li2 = li1; /* always non-NULL */
+ li1 = li1->prev_line;
+ }
+ table->lcl_head = li2;
+ info->prev_line = table->lcl_head->prev_line;
+ table->lcl_head->prev_line = info;
+ }
}
/* Extract a fully qualified filename from a line info table.
@@ -852,8 +865,10 @@ concat_filename (struct line_info_table *table, unsigned int file)
if (file - 1 >= table->num_files)
{
- (*_bfd_error_handler)
- (_("Dwarf Error: mangled line number section (bad file number)."));
+ /* FILE == 0 means unknown. */
+ if (file)
+ (*_bfd_error_handler)
+ (_("Dwarf Error: mangled line number section (bad file number)."));
return strdup ("<unknown>");
}
@@ -1168,12 +1183,12 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
amt *= sizeof (struct fileinfo);
tmp = bfd_realloc (table->files, amt);
if (tmp == NULL)
- {
+ {
free (table->files);
free (table->dirs);
free (filename);
return NULL;
- }
+ }
table->files = tmp;
}
table->files[table->num_files].name = cur_file;
@@ -1585,7 +1600,7 @@ read_rangelist (struct comp_unit *unit, struct arange *arange, bfd_uint64_t offs
return;
}
ranges_ptr = unit->stash->dwarf_ranges_buffer + offset;
-
+
for (;;)
{
bfd_vma low_pc;
@@ -1802,7 +1817,7 @@ scan_unit_for_symbols (struct comp_unit *unit)
attr.u.blk->data + 1);
}
break;
-
+
default:
break;
}
@@ -2179,28 +2194,91 @@ find_debug_info (bfd *abfd, asection *after_sec)
return NULL;
}
-/* Return TRUE if there is no mismatch bewteen function FUNC and
- section SECTION from symbol table SYMBOLS in ABFD. */
+/* Unset vmas for loadable sections in STASH. */
+
+static void
+unset_sections (struct dwarf2_debug *stash)
+{
+ unsigned int i;
+ struct loadable_section *p;
+
+ i = stash->loadable_section_count;
+ p = stash->loadable_sections;
+ for (; i > 0; i--, p++)
+ p->section->vma = 0;
+}
+
+/* Set unique vmas for loadable sections in ABFD and save vmas in
+ STASH for unset_sections. */
static bfd_boolean
-check_function_name (bfd *abfd, asection *section, asymbol **symbols,
- const char *func)
+place_sections (bfd *abfd, struct dwarf2_debug *stash)
{
- /* Mismatch can only happen when we have 2 functions with the same
- address. It can only occur in a relocatable file. */
- if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0
- && func != NULL
- && section != NULL
- && symbols != NULL)
+ struct loadable_section *p;
+ unsigned int i;
+
+ if (stash->loadable_section_count != 0)
{
- asymbol **p;
+ i = stash->loadable_section_count;
+ p = stash->loadable_sections;
+ for (; i > 0; i--, p++)
+ p->section->vma = p->adj_vma;
+ }
+ else
+ {
+ asection *sect;
+ bfd_vma last_vma = 0;
+ bfd_size_type amt;
+ struct loadable_section *p;
- for (p = symbols; *p != NULL; p++)
+ i = 0;
+ for (sect = abfd->sections; sect != NULL; sect = sect->next)
{
- if (((*p)->flags & BSF_FUNCTION) != 0
- && (*p)->name != NULL
- && strcmp ((*p)->name, func) == 0)
- return (*p)->section == section;
+ bfd_size_type sz;
+
+ if (sect->vma != 0 || (sect->flags & SEC_LOAD) == 0)
+ continue;
+
+ sz = sect->rawsize ? sect->rawsize : sect->size;
+ if (sz == 0)
+ continue;
+
+ i++;
+ }
+
+ amt = i * sizeof (struct loadable_section);
+ p = (struct loadable_section *) bfd_zalloc (abfd, amt);
+ if (! p)
+ return FALSE;
+
+ stash->loadable_sections = p;
+ stash->loadable_section_count = i;
+
+ for (sect = abfd->sections; sect != NULL; sect = sect->next)
+ {
+ bfd_size_type sz;
+
+ if (sect->vma != 0 || (sect->flags & SEC_LOAD) == 0)
+ continue;
+
+ sz = sect->rawsize ? sect->rawsize : sect->size;
+ if (sz == 0)
+ continue;
+
+ p->section = sect;
+ if (last_vma != 0)
+ {
+ /* Align the new address to the current section
+ alignment. */
+ last_vma = ((last_vma
+ + ~((bfd_vma) -1 << sect->alignment_power))
+ & ((bfd_vma) -1 << sect->alignment_power));
+ sect->vma = last_vma;
+ }
+ p->adj_vma = sect->vma;
+ last_vma += sect->vma + sz;
+
+ p++;
}
}
@@ -2239,7 +2317,27 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
struct comp_unit* each;
+ bfd_vma found = FALSE;
+
stash = *pinfo;
+
+ if (! stash)
+ {
+ bfd_size_type amt = sizeof (struct dwarf2_debug);
+
+ stash = bfd_zalloc (abfd, amt);
+ if (! stash)
+ return FALSE;
+ }
+
+ /* In a relocatable file, 2 functions may have the same address.
+ We change the section vma so that they won't overlap. */
+ if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
+ {
+ if (! place_sections (abfd, stash))
+ return FALSE;
+ }
+
addr = offset;
if (section->output_section)
addr += section->output_section->vma + section->output_offset;
@@ -2256,15 +2354,10 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
addr_size = 4;
BFD_ASSERT (addr_size == 4 || addr_size == 8);
- if (! stash)
+ if (! *pinfo)
{
bfd_size_type total_size;
asection *msec;
- bfd_size_type amt = sizeof (struct dwarf2_debug);
-
- stash = bfd_zalloc (abfd, amt);
- if (! stash)
- return FALSE;
*pinfo = stash;
@@ -2273,7 +2366,7 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
/* No dwarf2 info. Note that at this point the stash
has been allocated, but contains zeros, this lets
future calls to this function fail quicker. */
- return FALSE;
+ goto done;
/* There can be more than one DWARF2 info section in a BFD these days.
Read them all in and produce one large stash. We do this in two
@@ -2285,7 +2378,7 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
stash->info_ptr = bfd_alloc (abfd, total_size);
if (stash->info_ptr == NULL)
- return FALSE;
+ goto done;
stash->info_ptr_end = stash->info_ptr;
@@ -2319,7 +2412,7 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
/* A null info_ptr indicates that there is no dwarf2 info
(or that an error occured while setting up the stash). */
if (! stash->info_ptr)
- return FALSE;
+ goto done;
stash->inliner_chain = NULL;
@@ -2328,10 +2421,11 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
if (comp_unit_contains_address (each, addr)
&& comp_unit_find_nearest_line (each, addr, filename_ptr,
functionname_ptr,
- linenumber_ptr, stash)
- && check_function_name (abfd, section, symbols,
- *functionname_ptr))
- return TRUE;
+ linenumber_ptr, stash))
+ {
+ found = TRUE;
+ goto done;
+ }
/* Read each remaining comp. units checking each as they are read. */
while (stash->info_ptr < stash->info_ptr_end)
@@ -2398,15 +2492,20 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
filename_ptr,
functionname_ptr,
linenumber_ptr,
- stash)
- && check_function_name (abfd, section, symbols,
- *functionname_ptr))
- return TRUE;
+ stash))
+ {
+ found = TRUE;
+ goto done;
+ }
}
}
}
- return FALSE;
+done:
+ if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
+ unset_sections (stash);
+
+ return found;
}
/* The DWARF2 version of find_line. Return TRUE if the line is found
@@ -2438,10 +2537,29 @@ _bfd_dwarf2_find_line (bfd *abfd,
asection *section;
- bfd_boolean found;
+ bfd_boolean found = FALSE;
section = bfd_get_section (symbol);
+ stash = *pinfo;
+
+ if (! stash)
+ {
+ bfd_size_type amt = sizeof (struct dwarf2_debug);
+
+ stash = bfd_zalloc (abfd, amt);
+ if (! stash)
+ return FALSE;
+ }
+
+ /* In a relocatable file, 2 functions may have the same address.
+ We change the section vma so that they won't overlap. */
+ if (!stash && (abfd->flags & (EXEC_P | DYNAMIC)) == 0)
+ {
+ if (! place_sections (abfd, stash))
+ return FALSE;
+ }
+
addr = symbol->value;
if (section->output_section)
addr += section->output_section->vma + section->output_offset;
@@ -2449,19 +2567,13 @@ _bfd_dwarf2_find_line (bfd *abfd,
addr += section->vma;
*filename_ptr = NULL;
- stash = *pinfo;
*filename_ptr = NULL;
*linenumber_ptr = 0;
- if (! stash)
+ if (! *pinfo)
{
bfd_size_type total_size;
asection *msec;
- bfd_size_type amt = sizeof (struct dwarf2_debug);
-
- stash = bfd_zalloc (abfd, amt);
- if (! stash)
- return FALSE;
*pinfo = stash;
@@ -2470,7 +2582,7 @@ _bfd_dwarf2_find_line (bfd *abfd,
/* No dwarf2 info. Note that at this point the stash
has been allocated, but contains zeros, this lets
future calls to this function fail quicker. */
- return FALSE;
+ goto done;
/* There can be more than one DWARF2 info section in a BFD these days.
Read them all in and produce one large stash. We do this in two
@@ -2482,7 +2594,7 @@ _bfd_dwarf2_find_line (bfd *abfd,
stash->info_ptr = bfd_alloc (abfd, total_size);
if (stash->info_ptr == NULL)
- return FALSE;
+ goto done;
stash->info_ptr_end = stash->info_ptr;
@@ -2516,7 +2628,7 @@ _bfd_dwarf2_find_line (bfd *abfd,
/* A null info_ptr indicates that there is no dwarf2 info
(or that an error occured while setting up the stash). */
if (! stash->info_ptr)
- return FALSE;
+ goto done;
stash->inliner_chain = NULL;
@@ -2528,7 +2640,7 @@ _bfd_dwarf2_find_line (bfd *abfd,
found = comp_unit_find_line (each, symbol, addr, filename_ptr,
linenumber_ptr, stash);
if (found)
- return found;
+ goto done;
}
/* The DWARF2 spec says that the initial length field, and the
@@ -2605,12 +2717,16 @@ _bfd_dwarf2_find_line (bfd *abfd,
linenumber_ptr,
stash));
if (found)
- return TRUE;
+ goto done;
}
}
}
- return FALSE;
+done:
+ if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
+ unset_sections (stash);
+
+ return found;
}
bfd_boolean
@@ -2659,21 +2775,21 @@ _bfd_dwarf2_cleanup_debug_info (bfd *abfd)
size_t i;
for (i = 0; i < ABBREV_HASH_SIZE; i++)
- {
- struct abbrev_info *abbrev = abbrevs[i];
+ {
+ struct abbrev_info *abbrev = abbrevs[i];
- while (abbrev)
- {
- free (abbrev->attrs);
- abbrev = abbrev->next;
- }
- }
+ while (abbrev)
+ {
+ free (abbrev->attrs);
+ abbrev = abbrev->next;
+ }
+ }
if (each->line_table)
- {
- free (each->line_table->dirs);
- free (each->line_table->files);
- }
+ {
+ free (each->line_table->dirs);
+ free (each->line_table->files);
+ }
}
free (stash->dwarf_abbrev_buffer);
diff --git a/bfd/ecoff.c b/bfd/ecoff.c
index 8c855b3..75e1cc2 100644
--- a/bfd/ecoff.c
+++ b/bfd/ecoff.c
@@ -1,6 +1,6 @@
/* Generic ECOFF (Extended-COFF) routines.
Copyright 1990, 1991, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
- 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
Original version by Per Bothner.
Full support added by Ian Lance Taylor, ian@cygnus.com.
@@ -3285,8 +3285,9 @@ _bfd_ecoff_bfd_link_hash_table_create (bfd *abfd)
ret = bfd_malloc (amt);
if (ret == NULL)
return NULL;
- if (! _bfd_link_hash_table_init (&ret->root, abfd,
- ecoff_link_hash_newfunc))
+ if (!_bfd_link_hash_table_init (&ret->root, abfd,
+ ecoff_link_hash_newfunc,
+ sizeof (struct ecoff_link_hash_entry)))
{
free (ret);
return NULL;
diff --git a/bfd/ecofflink.c b/bfd/ecofflink.c
index d7bb817..4246e94 100644
--- a/bfd/ecofflink.c
+++ b/bfd/ecofflink.c
@@ -1,6 +1,6 @@
/* Routines to link ECOFF debugging information.
Copyright 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003,
- 2004, 2005 Free Software Foundation, Inc.
+ 2004, 2005, 2006 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support, <ian@cygnus.com>.
This file is part of BFD, the Binary File Descriptor library.
@@ -501,8 +501,8 @@ bfd_ecoff_debug_init (output_bfd, output_debug, output_swap, info)
ainfo = (struct accumulate *) bfd_malloc (amt);
if (!ainfo)
return NULL;
- if (! bfd_hash_table_init_n (&ainfo->fdr_hash.table, string_hash_newfunc,
- 1021))
+ if (!bfd_hash_table_init_n (&ainfo->fdr_hash.table, string_hash_newfunc,
+ sizeof (struct string_hash_entry), 1021))
return NULL;
ainfo->line = NULL;
@@ -528,7 +528,8 @@ bfd_ecoff_debug_init (output_bfd, output_debug, output_swap, info)
if (! info->relocatable)
{
- if (! bfd_hash_table_init (&ainfo->str_hash.table, string_hash_newfunc))
+ if (!bfd_hash_table_init (&ainfo->str_hash.table, string_hash_newfunc,
+ sizeof (struct string_hash_entry)))
return NULL;
/* The first entry in the string table is the empty string. */
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 76be811..3fba1c2 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -1489,7 +1489,8 @@ extern bfd_boolean _bfd_elf_link_hash_fixup_symbol
extern bfd_boolean _bfd_elf_link_hash_table_init
(struct elf_link_hash_table *, bfd *,
struct bfd_hash_entry *(*)
- (struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
+ (struct bfd_hash_entry *, struct bfd_hash_table *, const char *),
+ unsigned int);
extern bfd_boolean _bfd_elf_slurp_version_tables
(bfd *, bfd_boolean);
extern bfd_boolean _bfd_elf_merge_sections
diff --git a/bfd/elf-m10300.c b/bfd/elf-m10300.c
index 81c5db0..509f2a1 100644
--- a/bfd/elf-m10300.c
+++ b/bfd/elf-m10300.c
@@ -1,6 +1,6 @@
/* Matsushita 10300 specific support for 32-bit ELF
- Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
- Free Software Foundation, Inc.
+ Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+ 2006 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
@@ -3695,8 +3695,9 @@ elf32_mn10300_link_hash_table_create (abfd)
if (ret == (struct elf32_mn10300_link_hash_table *) NULL)
return NULL;
- if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
- elf32_mn10300_link_hash_newfunc))
+ if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
+ elf32_mn10300_link_hash_newfunc,
+ sizeof (struct elf32_mn10300_link_hash_entry)))
{
free (ret);
return NULL;
@@ -3712,8 +3713,9 @@ elf32_mn10300_link_hash_table_create (abfd)
return NULL;
}
- if (! _bfd_elf_link_hash_table_init (&ret->static_hash_table->root, abfd,
- elf32_mn10300_link_hash_newfunc))
+ if (!_bfd_elf_link_hash_table_init (&ret->static_hash_table->root, abfd,
+ elf32_mn10300_link_hash_newfunc,
+ sizeof (struct elf32_mn10300_link_hash_entry)))
{
free (ret->static_hash_table);
free (ret);
diff --git a/bfd/elf-strtab.c b/bfd/elf-strtab.c
index ac17b15..a0ce1d7 100644
--- a/bfd/elf-strtab.c
+++ b/bfd/elf-strtab.c
@@ -1,5 +1,5 @@
/* ELF strtab with GC and suffix merging support.
- Copyright 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+ Copyright 2001, 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
Written by Jakub Jelinek <jakub@redhat.com>.
This file is part of BFD, the Binary File Descriptor library.
@@ -99,7 +99,8 @@ _bfd_elf_strtab_init (void)
if (table == NULL)
return NULL;
- if (! bfd_hash_table_init (&table->table, elf_strtab_hash_newfunc))
+ if (!bfd_hash_table_init (&table->table, elf_strtab_hash_newfunc,
+ sizeof (struct elf_strtab_hash_entry)))
{
free (table);
return NULL;
diff --git a/bfd/elf.c b/bfd/elf.c
index 365c3a0..9e48f66 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1561,7 +1561,8 @@ _bfd_elf_link_hash_table_init
bfd *abfd,
struct bfd_hash_entry *(*newfunc) (struct bfd_hash_entry *,
struct bfd_hash_table *,
- const char *))
+ const char *),
+ unsigned int entsize)
{
bfd_boolean ret;
int can_refcount = get_elf_backend_data (abfd)->can_refcount;
@@ -1588,7 +1589,7 @@ _bfd_elf_link_hash_table_init
table->loaded = NULL;
table->is_relocatable_executable = FALSE;
- ret = _bfd_link_hash_table_init (&table->root, abfd, newfunc);
+ ret = _bfd_link_hash_table_init (&table->root, abfd, newfunc, entsize);
table->root.type = bfd_link_elf_hash_table;
return ret;
@@ -1606,7 +1607,8 @@ _bfd_elf_link_hash_table_create (bfd *abfd)
if (ret == NULL)
return NULL;
- if (! _bfd_elf_link_hash_table_init (ret, abfd, _bfd_elf_link_hash_newfunc))
+ if (! _bfd_elf_link_hash_table_init (ret, abfd, _bfd_elf_link_hash_newfunc,
+ sizeof (struct elf_link_hash_entry)))
{
free (ret);
return NULL;
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index ef19e6e..ca33121 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -20,20 +20,50 @@
#include "bfd.h"
#include "sysdep.h"
+#include "libiberty.h"
#include "libbfd.h"
#include "elf-bfd.h"
+#include "elf-vxworks.h"
#include "elf/arm.h"
#ifndef NUM_ELEM
#define NUM_ELEM(a) (sizeof (a) / (sizeof (a)[0]))
#endif
+/* Return the relocation section associated with NAME. HTAB is the
+ bfd's elf32_arm_link_hash_entry. */
+#define RELOC_SECTION(HTAB, NAME) \
+ ((HTAB)->use_rel ? ".rel" NAME : ".rela" NAME)
+
+/* Return size of a relocation entry. HTAB is the bfd's
+ elf32_arm_link_hash_entry. */
+#define RELOC_SIZE(HTAB) \
+ ((HTAB)->use_rel \
+ ? sizeof (Elf32_External_Rel) \
+ : sizeof (Elf32_External_Rela))
+
+/* Return function to swap relocations in. HTAB is the bfd's
+ elf32_arm_link_hash_entry. */
+#define SWAP_RELOC_IN(HTAB) \
+ ((HTAB)->use_rel \
+ ? bfd_elf32_swap_reloc_in \
+ : bfd_elf32_swap_reloca_in)
+
+/* Return function to swap relocations out. HTAB is the bfd's
+ elf32_arm_link_hash_entry. */
+#define SWAP_RELOC_OUT(HTAB) \
+ ((HTAB)->use_rel \
+ ? bfd_elf32_swap_reloc_out \
+ : bfd_elf32_swap_reloca_out)
+
#define elf_info_to_howto 0
#define elf_info_to_howto_rel elf32_arm_info_to_howto
#define ARM_ELF_ABI_VERSION 0
#define ARM_ELF_OS_ABI_VERSION ELFOSABI_ARM
+static const struct elf_backend_data elf32_arm_vxworks_bed;
+
/* Note: code such as elf32_arm_reloc_type_lookup expect to use e.g.
R_ARM_PC24 as an index into this, and find the R_ARM_PC24 HOWTO
in that slot. */
@@ -140,8 +170,8 @@ static reloc_howto_type elf32_arm_howto_table_1[] =
bfd_elf_generic_reloc, /* special_function */
"R_ARM_ABS12", /* name */
FALSE, /* partial_inplace */
- 0x000008ff, /* src_mask */
- 0x000008ff, /* dst_mask */
+ 0x00000fff, /* src_mask */
+ 0x00000fff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_THM_ABS5, /* type */
@@ -1422,9 +1452,10 @@ elf32_arm_nabi_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
typedef unsigned long int insn32;
typedef unsigned short int insn16;
-/* In lieu of proper flags, assume all EABIv4 objects are interworkable. */
+/* In lieu of proper flags, assume all EABIv4 or later objects are
+ interworkable. */
#define INTERWORK_FLAG(abfd) \
- (EF_ARM_EABI_VERSION (elf_elfheader (abfd)->e_flags) == EF_ARM_EABI_VER4 \
+ (EF_ARM_EABI_VERSION (elf_elfheader (abfd)->e_flags) >= EF_ARM_EABI_VER4 \
|| (elf_elfheader (abfd)->e_flags & EF_ARM_INTERWORK))
/* The linker script knows the section names for placement.
@@ -1491,6 +1522,38 @@ static const bfd_vma elf32_arm_plt_entry [] =
#endif
+/* The format of the first entry in the procedure linkage table
+ for a VxWorks executable. */
+static const bfd_vma elf32_arm_vxworks_exec_plt0_entry[] =
+ {
+ 0xe52dc008, /* str ip,[sp,#-8]! */
+ 0xe59fc000, /* ldr ip,[pc] */
+ 0xe59cf008, /* ldr pc,[ip,#8] */
+ 0x00000000, /* .long _GLOBAL_OFFSET_TABLE_ */
+ };
+
+/* The format of subsequent entries in a VxWorks executable. */
+static const bfd_vma elf32_arm_vxworks_exec_plt_entry[] =
+ {
+ 0xe59fc000, /* ldr ip,[pc] */
+ 0xe59cf000, /* ldr pc,[ip] */
+ 0x00000000, /* .long @got */
+ 0xe59fc000, /* ldr ip,[pc] */
+ 0xea000000, /* b _PLT */
+ 0x00000000, /* .long @pltindex*sizeof(Elf32_Rela) */
+ };
+
+/* The format of entries in a VxWorks shared library. */
+static const bfd_vma elf32_arm_vxworks_shared_plt_entry[] =
+ {
+ 0xe59fc000, /* ldr ip,[pc] */
+ 0xe79cf009, /* ldr pc,[ip,r9] */
+ 0x00000000, /* .long @got */
+ 0xe59fc000, /* ldr ip,[pc] */
+ 0xe599f008, /* ldr pc,[r9,#8] */
+ 0x00000000, /* .long @pltindex*sizeof(Elf32_Rela) */
+ };
+
/* An initial stub used if the PLT entry is referenced from Thumb code. */
#define PLT_THUMB_STUB_SIZE 4
static const bfd_vma elf32_arm_plt_thumb_stub [] =
@@ -1668,6 +1731,9 @@ struct elf32_arm_link_hash_table
/* The number of bytes in the subsequent PLT etries. */
bfd_size_type plt_entry_size;
+ /* True if the target system is VxWorks. */
+ int vxworks_p;
+
/* True if the target system is Symbian OS. */
int symbian_p;
@@ -1683,6 +1749,9 @@ struct elf32_arm_link_hash_table
asection *sdynbss;
asection *srelbss;
+ /* The (unloaded but important) VxWorks .rela.plt.unloaded section. */
+ asection *srelplt2;
+
/* Data for R_ARM_TLS_LDM32 relocations. */
union {
bfd_signed_vma refcount;
@@ -1728,7 +1797,20 @@ elf32_arm_link_hash_newfunc (struct bfd_hash_entry * entry,
return (struct bfd_hash_entry *) ret;
}
-/* Create .got, .gotplt, and .rel.got sections in DYNOBJ, and set up
+/* Return true if NAME is the name of the relocation section associated
+ with S. */
+
+static bfd_boolean
+reloc_section_p (struct elf32_arm_link_hash_table *htab,
+ const char *name, asection *s)
+{
+ if (htab->use_rel)
+ return strncmp (name, ".rel", 4) == 0 && strcmp (s->name, name + 4) == 0;
+ else
+ return strncmp (name, ".rela", 5) == 0 && strcmp (s->name, name + 5) == 0;
+}
+
+/* Create .got, .gotplt, and .rel(a).got sections in DYNOBJ, and set up
shortcuts to them in our hash table. */
static bfd_boolean
@@ -1749,7 +1831,8 @@ create_got_section (bfd *dynobj, struct bfd_link_info *info)
if (!htab->sgot || !htab->sgotplt)
abort ();
- htab->srelgot = bfd_make_section_with_flags (dynobj, ".rel.got",
+ htab->srelgot = bfd_make_section_with_flags (dynobj,
+ RELOC_SECTION (htab, ".got"),
(SEC_ALLOC | SEC_LOAD
| SEC_HAS_CONTENTS
| SEC_IN_MEMORY
@@ -1761,8 +1844,8 @@ create_got_section (bfd *dynobj, struct bfd_link_info *info)
return TRUE;
}
-/* Create .plt, .rel.plt, .got, .got.plt, .rel.got, .dynbss, and
- .rel.bss sections in DYNOBJ, and set up shortcuts to them in our
+/* Create .plt, .rel(a).plt, .got, .got.plt, .rel(a).got, .dynbss, and
+ .rel(a).bss sections in DYNOBJ, and set up shortcuts to them in our
hash table. */
static bfd_boolean
@@ -1778,10 +1861,32 @@ elf32_arm_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
return FALSE;
htab->splt = bfd_get_section_by_name (dynobj, ".plt");
- htab->srelplt = bfd_get_section_by_name (dynobj, ".rel.plt");
+ htab->srelplt = bfd_get_section_by_name (dynobj,
+ RELOC_SECTION (htab, ".plt"));
htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss");
if (!info->shared)
- htab->srelbss = bfd_get_section_by_name (dynobj, ".rel.bss");
+ htab->srelbss = bfd_get_section_by_name (dynobj,
+ RELOC_SECTION (htab, ".bss"));
+
+ if (htab->vxworks_p)
+ {
+ if (!elf_vxworks_create_dynamic_sections (dynobj, info, &htab->srelplt2))
+ return FALSE;
+
+ if (info->shared)
+ {
+ htab->plt_header_size = 0;
+ htab->plt_entry_size
+ = 4 * ARRAY_SIZE (elf32_arm_vxworks_shared_plt_entry);
+ }
+ else
+ {
+ htab->plt_header_size
+ = 4 * ARRAY_SIZE (elf32_arm_vxworks_exec_plt0_entry);
+ htab->plt_entry_size
+ = 4 * ARRAY_SIZE (elf32_arm_vxworks_exec_plt_entry);
+ }
+ }
if (!htab->splt
|| !htab->srelplt
@@ -1862,7 +1967,8 @@ elf32_arm_link_hash_table_create (bfd *abfd)
return NULL;
if (!_bfd_elf_link_hash_table_init (& ret->root, abfd,
- elf32_arm_link_hash_newfunc))
+ elf32_arm_link_hash_newfunc,
+ sizeof (struct elf32_arm_link_hash_entry)))
{
free (ret);
return NULL;
@@ -1875,6 +1981,7 @@ elf32_arm_link_hash_table_create (bfd *abfd)
ret->srelplt = NULL;
ret->sdynbss = NULL;
ret->srelbss = NULL;
+ ret->srelplt2 = NULL;
ret->thumb_glue_size = 0;
ret->arm_glue_size = 0;
ret->bfd_of_glue_owner = NULL;
@@ -1890,6 +1997,7 @@ elf32_arm_link_hash_table_create (bfd *abfd)
#endif
ret->fix_v4bx = 0;
ret->use_blx = 0;
+ ret->vxworks_p = 0;
ret->symbian_p = 0;
ret->use_rel = 1;
ret->sym_sec.abfd = NULL;
@@ -2805,6 +2913,20 @@ tpoff (struct bfd_link_info *info, bfd_vma address)
return address - htab->tls_sec->vma + base;
}
+/* Perform an R_ARM_ABS12 relocation on the field pointed to by DATA.
+ VALUE is the relocation value. */
+
+static bfd_reloc_status_type
+elf32_arm_abs12_reloc (bfd *abfd, void *data, bfd_vma value)
+{
+ if (value > 0xfff)
+ return bfd_reloc_overflow;
+
+ value |= bfd_get_32 (abfd, data) & 0xfffff000;
+ bfd_put_32 (abfd, value, data);
+ return bfd_reloc_ok;
+}
+
/* Perform a relocation as part of a final link. */
static bfd_reloc_status_type
@@ -2891,6 +3013,10 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
*unresolved_reloc_p = FALSE;
return bfd_reloc_ok;
+ case R_ARM_ABS12:
+ if (!globals->vxworks_p)
+ return elf32_arm_abs12_reloc (input_bfd, hit_data, value + addend);
+
case R_ARM_PC24:
case R_ARM_ABS32:
case R_ARM_REL32:
@@ -2925,7 +3051,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
*unresolved_reloc_p = FALSE;
return _bfd_final_link_relocate (howto, input_bfd, input_section,
contents, rel->r_offset, value,
- (bfd_vma) 0);
+ rel->r_addend);
}
/* When generating a shared object or relocatable executable, these
@@ -2961,10 +3087,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
if (name == NULL)
return bfd_reloc_notsupported;
- BFD_ASSERT (strncmp (name, ".rel", 4) == 0
- && strcmp (bfd_get_section_name (input_bfd,
- input_section),
- name + 4) == 0);
+ BFD_ASSERT (reloc_section_p (globals, name, input_section));
sreloc = bfd_get_section_by_name (dynobj, name);
BFD_ASSERT (sreloc != NULL);
@@ -2973,6 +3096,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
skip = FALSE;
relocate = FALSE;
+ outrel.r_addend = addend;
outrel.r_offset =
_bfd_elf_section_offset (output_bfd, info, input_section,
rel->r_offset);
@@ -2996,7 +3120,6 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
int symbol;
/* This symbol is local, or marked to become local. */
- relocate = TRUE;
if (sym_flags == STT_ARM_TFUNC)
value |= 1;
if (globals->symbian_p)
@@ -3021,11 +3144,15 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
so the symbol does not matter. */
symbol = 0;
outrel.r_info = ELF32_R_INFO (symbol, R_ARM_RELATIVE);
+ if (globals->use_rel)
+ relocate = TRUE;
+ else
+ outrel.r_addend += value;
}
loc = sreloc->contents;
- loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rel);
- bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
+ loc += sreloc->reloc_count++ * RELOC_SIZE (globals);
+ SWAP_RELOC_OUT (globals) (output_bfd, &outrel, loc);
/* If this reloc is against an external symbol, we do not want to
fiddle with the addend. Otherwise, we need to include the symbol
@@ -3039,6 +3166,9 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
}
else switch (r_type)
{
+ case R_ARM_ABS12:
+ return elf32_arm_abs12_reloc (input_bfd, hit_data, value + addend);
+
case R_ARM_XPC25: /* Arm BLX instruction. */
case R_ARM_CALL:
case R_ARM_JUMP24:
@@ -3186,18 +3316,6 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
bfd_put_16 (input_bfd, value, hit_data);
return bfd_reloc_ok;
- case R_ARM_ABS12:
- /* Support ldr and str instruction for the arm */
- /* Also thumb b (unconditional branch). ??? Really? */
- value += addend;
-
- if ((long) value > 0x7ff || (long) value < -0x800)
- return bfd_reloc_overflow;
-
- value |= (bfd_get_32 (input_bfd, hit_data) & 0xfffff000);
- bfd_put_32 (input_bfd, value, hit_data);
- return bfd_reloc_ok;
-
case R_ARM_THM_ABS5:
/* Support ldr and str instructions for the thumb. */
if (globals->use_rel)
@@ -3589,7 +3707,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
value -= sgot->output_section->vma;
return _bfd_final_link_relocate (howto, input_bfd, input_section,
contents, rel->r_offset, value,
- (bfd_vma) 0);
+ rel->r_addend);
case R_ARM_GOTPC:
/* Use global offset table as symbol value. */
@@ -3602,7 +3720,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
value = sgot->output_section->vma;
return _bfd_final_link_relocate (howto, input_bfd, input_section,
contents, rel->r_offset, value,
- (bfd_vma) 0);
+ rel->r_addend);
case R_ARM_GOT32:
case R_ARM_GOT_PREL:
@@ -3632,7 +3750,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
always be a multiple of 4, we use the least significant bit
to record whether we have initialized it already.
- When doing a dynamic link, we create a .rel.got relocation
+ When doing a dynamic link, we create a .rel(a).got relocation
entry to initialize the value. This is done in the
finish_dynamic_symbol routine. */
if ((off & 1) != 0)
@@ -3678,7 +3796,8 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
if (sym_flags == STT_ARM_TFUNC)
value |= 1;
- bfd_put_32 (output_bfd, value, sgot->contents + off);
+ if (globals->use_rel)
+ bfd_put_32 (output_bfd, value, sgot->contents + off);
if (info->shared)
{
@@ -3686,16 +3805,18 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
Elf_Internal_Rela outrel;
bfd_byte *loc;
- srelgot = bfd_get_section_by_name (dynobj, ".rel.got");
+ srelgot = (bfd_get_section_by_name
+ (dynobj, RELOC_SECTION (globals, ".got")));
BFD_ASSERT (srelgot != NULL);
+ outrel.r_addend = addend + value;
outrel.r_offset = (sgot->output_section->vma
+ sgot->output_offset
+ off);
outrel.r_info = ELF32_R_INFO (0, R_ARM_RELATIVE);
loc = srelgot->contents;
- loc += srelgot->reloc_count++ * sizeof (Elf32_External_Rel);
- bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
+ loc += srelgot->reloc_count++ * RELOC_SIZE (globals);
+ SWAP_RELOC_OUT (globals) (output_bfd, &outrel, loc);
}
local_got_offsets[r_symndx] |= 1;
@@ -3708,13 +3829,14 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
return _bfd_final_link_relocate (howto, input_bfd, input_section,
contents, rel->r_offset, value,
- (bfd_vma) 0);
+ rel->r_addend);
case R_ARM_TLS_LDO32:
value = value - dtpoff_base (info);
return _bfd_final_link_relocate (howto, input_bfd, input_section,
- contents, rel->r_offset, value, (bfd_vma) 0);
+ contents, rel->r_offset, value,
+ rel->r_addend);
case R_ARM_TLS_LDM32:
{
@@ -3739,15 +3861,18 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
if (globals->srelgot == NULL)
abort ();
+ outrel.r_addend = 0;
outrel.r_offset = (globals->sgot->output_section->vma
+ globals->sgot->output_offset + off);
outrel.r_info = ELF32_R_INFO (0, R_ARM_TLS_DTPMOD32);
- bfd_put_32 (output_bfd, 0, globals->sgot->contents + off);
+ if (globals->use_rel)
+ bfd_put_32 (output_bfd, outrel.r_addend,
+ globals->sgot->contents + off);
loc = globals->srelgot->contents;
- loc += globals->srelgot->reloc_count++ * sizeof (Elf32_External_Rel);
- bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
+ loc += globals->srelgot->reloc_count++ * RELOC_SIZE (globals);
+ SWAP_RELOC_OUT (globals) (output_bfd, &outrel, loc);
}
else
bfd_put_32 (output_bfd, 1, globals->sgot->contents + off);
@@ -3760,7 +3885,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
return _bfd_final_link_relocate (howto, input_bfd, input_section,
contents, rel->r_offset, value,
- (bfd_vma) 0);
+ rel->r_addend);
}
case R_ARM_TLS_GD32:
@@ -3821,36 +3946,45 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
if (globals->srelgot == NULL)
abort ();
loc = globals->srelgot->contents;
- loc += globals->srelgot->reloc_count * sizeof (Elf32_External_Rel);
+ loc += globals->srelgot->reloc_count * RELOC_SIZE (globals);
}
if (tls_type & GOT_TLS_GD)
{
if (need_relocs)
{
+ outrel.r_addend = 0;
outrel.r_offset = (globals->sgot->output_section->vma
- + globals->sgot->output_offset + cur_off);
+ + globals->sgot->output_offset
+ + cur_off);
outrel.r_info = ELF32_R_INFO (indx, R_ARM_TLS_DTPMOD32);
- bfd_put_32 (output_bfd, 0, globals->sgot->contents + cur_off);
- bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
+ if (globals->use_rel)
+ bfd_put_32 (output_bfd, outrel.r_addend,
+ globals->sgot->contents + cur_off);
+
+ SWAP_RELOC_OUT (globals) (output_bfd, &outrel, loc);
globals->srelgot->reloc_count++;
- loc += sizeof (Elf32_External_Rel);
+ loc += RELOC_SIZE (globals);
if (indx == 0)
bfd_put_32 (output_bfd, value - dtpoff_base (info),
globals->sgot->contents + cur_off + 4);
else
{
- bfd_put_32 (output_bfd, 0,
- globals->sgot->contents + cur_off + 4);
-
+ outrel.r_addend = 0;
outrel.r_info = ELF32_R_INFO (indx,
R_ARM_TLS_DTPOFF32);
outrel.r_offset += 4;
- bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
+
+ if (globals->use_rel)
+ bfd_put_32 (output_bfd, outrel.r_addend,
+ globals->sgot->contents + cur_off + 4);
+
+
+ SWAP_RELOC_OUT (globals) (output_bfd, &outrel, loc);
globals->srelgot->reloc_count++;
- loc += sizeof (Elf32_External_Rel);
+ loc += RELOC_SIZE (globals);
}
}
else
@@ -3873,21 +4007,22 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
{
if (need_relocs)
{
+ if (indx == 0)
+ outrel.r_addend = value - dtpoff_base (info);
+ else
+ outrel.r_addend = 0;
outrel.r_offset = (globals->sgot->output_section->vma
+ globals->sgot->output_offset
+ cur_off);
outrel.r_info = ELF32_R_INFO (indx, R_ARM_TLS_TPOFF32);
- if (indx == 0)
- bfd_put_32 (output_bfd, value - dtpoff_base (info),
- globals->sgot->contents + cur_off);
- else
- bfd_put_32 (output_bfd, 0,
+ if (globals->use_rel)
+ bfd_put_32 (output_bfd, outrel.r_addend,
globals->sgot->contents + cur_off);
- bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
+ SWAP_RELOC_OUT (globals) (output_bfd, &outrel, loc);
globals->srelgot->reloc_count++;
- loc += sizeof (Elf32_External_Rel);
+ loc += RELOC_SIZE (globals);
}
else
bfd_put_32 (output_bfd, tpoff (info, value),
@@ -3908,7 +4043,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
return _bfd_final_link_relocate (howto, input_bfd, input_section,
contents, rel->r_offset, value,
- (bfd_vma) 0);
+ rel->r_addend);
}
case R_ARM_TLS_LE32:
@@ -3924,7 +4059,8 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
value = tpoff (info, value);
return _bfd_final_link_relocate (howto, input_bfd, input_section,
- contents, rel->r_offset, value, (bfd_vma) 0);
+ contents, rel->r_offset, value,
+ rel->r_addend);
case R_ARM_V4BX:
if (globals->fix_v4bx)
@@ -5011,14 +5147,31 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd)
for (; in_list; in_list = in_list->next)
{
if ((in_list->tag & 128) < 64)
- _bfd_error_handler
- (_("Warning: %B: Unknown EABI object attribute %d"),
- ibfd, in_list->tag);
- break;
+ {
+ _bfd_error_handler
+ (_("Warning: %B: Unknown EABI object attribute %d"),
+ ibfd, in_list->tag);
+ break;
+ }
}
return TRUE;
}
+
+/* Return TRUE if the two EABI versions are incompatible. */
+
+static bfd_boolean
+elf32_arm_versions_compatible (unsigned iver, unsigned over)
+{
+ /* v4 and v5 are the same spec before and after it was released,
+ so allow mixing them. */
+ if ((iver == EF_ARM_EABI_VER4 && over == EF_ARM_EABI_VER5)
+ || (iver == EF_ARM_EABI_VER5 && over == EF_ARM_EABI_VER4))
+ return TRUE;
+
+ return (iver == over);
+}
+
/* Merge backend specific data from an object file to the output
object file when linking. */
@@ -5117,7 +5270,8 @@ elf32_arm_merge_private_bfd_data (bfd * ibfd, bfd * obfd)
}
/* Complain about various flag mismatches. */
- if (EF_ARM_EABI_VERSION (in_flags) != EF_ARM_EABI_VERSION (out_flags))
+ if (!elf32_arm_versions_compatible (EF_ARM_EABI_VERSION (in_flags),
+ EF_ARM_EABI_VERSION (out_flags)))
{
_bfd_error_handler
(_("ERROR: Source object %B has EABI version %d, but target %B has EABI version %d"),
@@ -5128,7 +5282,10 @@ elf32_arm_merge_private_bfd_data (bfd * ibfd, bfd * obfd)
}
/* Not sure what needs to be checked for EABI versions >= 1. */
- if (EF_ARM_EABI_VERSION (in_flags) == EF_ARM_EABI_UNKNOWN)
+ /* VxWorks libraries do not use these flags. */
+ if (get_elf_backend_data (obfd) != &elf32_arm_vxworks_bed
+ && get_elf_backend_data (ibfd) != &elf32_arm_vxworks_bed
+ && EF_ARM_EABI_VERSION (in_flags) == EF_ARM_EABI_UNKNOWN)
{
if ((in_flags & EF_ARM_APCS_26) != (out_flags & EF_ARM_APCS_26))
{
@@ -5325,7 +5482,11 @@ elf32_arm_print_private_bfd_data (bfd *abfd, void * ptr)
case EF_ARM_EABI_VER4:
fprintf (file, _(" [Version4 EABI]"));
+ goto eabi;
+ case EF_ARM_EABI_VER5:
+ fprintf (file, _(" [Version5 EABI]"));
+ eabi:
if (flags & EF_ARM_BE8)
fprintf (file, _(" [BE8]"));
@@ -5683,6 +5844,13 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
}
break;
+ case R_ARM_ABS12:
+ /* VxWorks uses dynamic R_ARM_ABS12 relocations for
+ ldr __GOTT_INDEX__ offsets. */
+ if (!htab->vxworks_p)
+ break;
+ /* Fall through */
+
case R_ARM_ABS32:
case R_ARM_REL32:
case R_ARM_PC24:
@@ -5757,9 +5925,7 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
if (name == NULL)
return FALSE;
- BFD_ASSERT (strncmp (name, ".rel", 4) == 0
- && strcmp (bfd_get_section_name (abfd, sec),
- name + 4) == 0);
+ BFD_ASSERT (reloc_section_p (htab, name, sec));
sreloc = bfd_get_section_by_name (dynobj, name);
if (sreloc == NULL)
@@ -6094,14 +6260,14 @@ elf32_arm_adjust_dynamic_symbol (struct bfd_link_info * info,
/* We must generate a R_ARM_COPY reloc to tell the dynamic linker to
copy the initial value out of the dynamic object and into the
runtime process image. We need to remember the offset into the
- .rel.bss section we are going to use. */
+ .rel(a).bss section we are going to use. */
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
{
asection *srel;
- srel = bfd_get_section_by_name (dynobj, ".rel.bss");
+ srel = bfd_get_section_by_name (dynobj, RELOC_SECTION (globals, ".bss"));
BFD_ASSERT (srel != NULL);
- srel->size += sizeof (Elf32_External_Rel);
+ srel->size += RELOC_SIZE (globals);
h->needs_copy = 1;
}
@@ -6215,8 +6381,24 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
htab->sgotplt->size += 4;
}
- /* We also need to make an entry in the .rel.plt section. */
- htab->srelplt->size += sizeof (Elf32_External_Rel);
+ /* We also need to make an entry in the .rel(a).plt section. */
+ htab->srelplt->size += RELOC_SIZE (htab);
+
+ /* VxWorks executables have a second set of relocations for
+ each PLT entry. They go in a separate relocation section,
+ which is processed by the kernel loader. */
+ if (htab->vxworks_p && !info->shared)
+ {
+ /* There is a relocation for the initial PLT entry:
+ an R_ARM_32 relocation for _GLOBAL_OFFSET_TABLE_. */
+ if (h->plt.offset == htab->plt_header_size)
+ htab->srelplt2->size += RELOC_SIZE (htab);
+
+ /* There are two extra relocations for each subsequent
+ PLT entry: an R_ARM_32 relocation for the GOT entry,
+ and an R_ARM_32 relocation for the PLT entry. */
+ htab->srelplt2->size += RELOC_SIZE (htab) * 2;
+ }
}
else
{
@@ -6281,19 +6463,19 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
|| h->root.type != bfd_link_hash_undefweak))
{
if (tls_type & GOT_TLS_IE)
- htab->srelgot->size += sizeof (Elf32_External_Rel);
+ htab->srelgot->size += RELOC_SIZE (htab);
if (tls_type & GOT_TLS_GD)
- htab->srelgot->size += sizeof (Elf32_External_Rel);
+ htab->srelgot->size += RELOC_SIZE (htab);
if ((tls_type & GOT_TLS_GD) && indx != 0)
- htab->srelgot->size += sizeof (Elf32_External_Rel);
+ htab->srelgot->size += RELOC_SIZE (htab);
}
else if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|| h->root.type != bfd_link_hash_undefweak)
&& (info->shared
|| WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)))
- htab->srelgot->size += sizeof (Elf32_External_Rel);
+ htab->srelgot->size += RELOC_SIZE (htab);
}
}
else
@@ -6397,7 +6579,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
for (p = eh->relocs_copied; p != NULL; p = p->next)
{
asection *sreloc = elf_section_data (p->section)->sreloc;
- sreloc->size += p->count * sizeof (Elf32_External_Rel);
+ sreloc->size += p->count * RELOC_SIZE (htab);
}
return TRUE;
@@ -6493,7 +6675,7 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
else if (p->count != 0)
{
srel = elf_section_data (p->section)->sreloc;
- srel->size += p->count * sizeof (Elf32_External_Rel);
+ srel->size += p->count * RELOC_SIZE (htab);
if ((p->section->output_section->flags & SEC_READONLY) != 0)
info->flags |= DF_TEXTREL;
}
@@ -6524,7 +6706,7 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
s->size += 4;
if (info->shared || *local_tls_type == GOT_TLS_GD)
- srel->size += sizeof (Elf32_External_Rel);
+ srel->size += RELOC_SIZE (htab);
}
else
*local_got = (bfd_vma) -1;
@@ -6538,7 +6720,7 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
htab->tls_ldm_got.offset = htab->sgot->size;
htab->sgot->size += 8;
if (info->shared)
- htab->srelgot->size += sizeof (Elf32_External_Rel);
+ htab->srelgot->size += RELOC_SIZE (htab);
}
else
htab->tls_ldm_got.offset = -1;
@@ -6573,8 +6755,8 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
if (s->size != 0)
{
/* Remember whether there are any reloc sections other
- than .rel.plt. */
- if (strcmp (name, ".rel.plt") != 0)
+ than .rel(a).plt and .rela.plt.unloaded. */
+ if (s != htab->srelplt && s != htab->srelplt2)
relocs = TRUE;
/* We use the reloc_count field as a counter if we need
@@ -6592,8 +6774,8 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
if (s->size == 0)
{
/* If we don't need this section, strip it from the
- output file. This is mostly to handle .rel.bss and
- .rel.plt. We must create both sections in
+ output file. This is mostly to handle .rel(a).bss and
+ .rel(a).plt. We must create both sections in
create_dynamic_sections, because they must be created
before the linker maps input sections to output
sections. The linker does that before
@@ -6633,17 +6815,28 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
{
if ( !add_dynamic_entry (DT_PLTGOT, 0)
|| !add_dynamic_entry (DT_PLTRELSZ, 0)
- || !add_dynamic_entry (DT_PLTREL, DT_REL)
+ || !add_dynamic_entry (DT_PLTREL,
+ htab->use_rel ? DT_REL : DT_RELA)
|| !add_dynamic_entry (DT_JMPREL, 0))
return FALSE;
}
if (relocs)
{
- if ( !add_dynamic_entry (DT_REL, 0)
- || !add_dynamic_entry (DT_RELSZ, 0)
- || !add_dynamic_entry (DT_RELENT, sizeof (Elf32_External_Rel)))
- return FALSE;
+ if (htab->use_rel)
+ {
+ if (!add_dynamic_entry (DT_REL, 0)
+ || !add_dynamic_entry (DT_RELSZ, 0)
+ || !add_dynamic_entry (DT_RELENT, RELOC_SIZE (htab)))
+ return FALSE;
+ }
+ else
+ {
+ if (!add_dynamic_entry (DT_RELA, 0)
+ || !add_dynamic_entry (DT_RELASZ, 0)
+ || !add_dynamic_entry (DT_RELAENT, RELOC_SIZE (htab)))
+ return FALSE;
+ }
}
/* If any dynamic relocs apply to a read-only section,
@@ -6692,7 +6885,7 @@ elf32_arm_finish_dynamic_symbol (bfd * output_bfd, struct bfd_link_info * info,
BFD_ASSERT (h->dynindx != -1);
splt = bfd_get_section_by_name (dynobj, ".plt");
- srel = bfd_get_section_by_name (dynobj, ".rel.plt");
+ srel = bfd_get_section_by_name (dynobj, RELOC_SECTION (htab, ".plt"));
BFD_ASSERT (splt != NULL && srel != NULL);
/* Fill in the entry in the procedure linkage table. */
@@ -6719,7 +6912,7 @@ elf32_arm_finish_dynamic_symbol (bfd * output_bfd, struct bfd_link_info * info,
}
else
{
- bfd_vma got_offset;
+ bfd_vma got_offset, got_address, plt_address;
bfd_vma got_displacement;
asection * sgot;
@@ -6737,38 +6930,103 @@ elf32_arm_finish_dynamic_symbol (bfd * output_bfd, struct bfd_link_info * info,
symbols appear in the same order as in .plt. */
plt_index = (got_offset - 12) / 4;
- /* Calculate the displacement between the PLT slot and the
- entry in the GOT. The eight-byte offset accounts for the
- value produced by adding to pc in the first instruction
- of the PLT stub. */
- got_displacement = (sgot->output_section->vma
- + sgot->output_offset
- + got_offset
- - splt->output_section->vma
- - splt->output_offset
- - h->plt.offset
- - 8);
+ /* Calculate the address of the GOT entry. */
+ got_address = (sgot->output_section->vma
+ + sgot->output_offset
+ + got_offset);
- BFD_ASSERT ((got_displacement & 0xf0000000) == 0);
+ /* ...and the address of the PLT entry. */
+ plt_address = (splt->output_section->vma
+ + splt->output_offset
+ + h->plt.offset);
- if (!htab->use_blx && eh->plt_thumb_refcount > 0)
+ if (htab->vxworks_p && info->shared)
{
- bfd_put_16 (output_bfd, elf32_arm_plt_thumb_stub[0],
- splt->contents + h->plt.offset - 4);
- bfd_put_16 (output_bfd, elf32_arm_plt_thumb_stub[1],
- splt->contents + h->plt.offset - 2);
+ unsigned int i;
+ bfd_vma val;
+
+ for (i = 0; i != htab->plt_entry_size / 4; i++)
+ {
+ val = elf32_arm_vxworks_shared_plt_entry[i];
+ if (i == 2)
+ val |= got_address - sgot->output_section->vma;
+ if (i == 5)
+ val |= plt_index * RELOC_SIZE (htab);
+ bfd_put_32 (output_bfd, val,
+ htab->splt->contents + h->plt.offset + i * 4);
+ }
}
+ else if (htab->vxworks_p)
+ {
+ unsigned int i;
+ bfd_vma val;
- bfd_put_32 (output_bfd, elf32_arm_plt_entry[0] | ((got_displacement & 0x0ff00000) >> 20),
- splt->contents + h->plt.offset + 0);
- bfd_put_32 (output_bfd, elf32_arm_plt_entry[1] | ((got_displacement & 0x000ff000) >> 12),
- splt->contents + h->plt.offset + 4);
- bfd_put_32 (output_bfd, elf32_arm_plt_entry[2] | (got_displacement & 0x00000fff),
- splt->contents + h->plt.offset + 8);
+ for (i = 0; i != htab->plt_entry_size / 4; i++)
+ {
+ val = elf32_arm_vxworks_exec_plt_entry[i];
+ if (i == 2)
+ val |= got_address;
+ if (i == 4)
+ val |= 0xffffff & -((h->plt.offset + i * 4 + 8) >> 2);
+ if (i == 5)
+ val |= plt_index * RELOC_SIZE (htab);
+ bfd_put_32 (output_bfd, val,
+ htab->splt->contents + h->plt.offset + i * 4);
+ }
+
+ loc = (htab->srelplt2->contents
+ + (plt_index * 2 + 1) * RELOC_SIZE (htab));
+
+ /* Create the .rela.plt.unloaded R_ARM_ABS32 relocation
+ referencing the GOT for this PLT entry. */
+ rel.r_offset = plt_address + 8;
+ rel.r_info = ELF32_R_INFO (htab->root.hgot->indx, R_ARM_ABS32);
+ rel.r_addend = got_offset;
+ SWAP_RELOC_OUT (htab) (output_bfd, &rel, loc);
+ loc += RELOC_SIZE (htab);
+
+ /* Create the R_ARM_ABS32 relocation referencing the
+ beginning of the PLT for this GOT entry. */
+ rel.r_offset = got_address;
+ rel.r_info = ELF32_R_INFO (htab->root.hplt->indx, R_ARM_ABS32);
+ rel.r_addend = 0;
+ SWAP_RELOC_OUT (htab) (output_bfd, &rel, loc);
+ }
+ else
+ {
+ /* Calculate the displacement between the PLT slot and the
+ entry in the GOT. The eight-byte offset accounts for the
+ value produced by adding to pc in the first instruction
+ of the PLT stub. */
+ got_displacement = got_address - (plt_address + 8);
+
+ BFD_ASSERT ((got_displacement & 0xf0000000) == 0);
+
+ if (!htab->use_blx && eh->plt_thumb_refcount > 0)
+ {
+ bfd_put_16 (output_bfd, elf32_arm_plt_thumb_stub[0],
+ splt->contents + h->plt.offset - 4);
+ bfd_put_16 (output_bfd, elf32_arm_plt_thumb_stub[1],
+ splt->contents + h->plt.offset - 2);
+ }
+
+ bfd_put_32 (output_bfd,
+ elf32_arm_plt_entry[0]
+ | ((got_displacement & 0x0ff00000) >> 20),
+ splt->contents + h->plt.offset + 0);
+ bfd_put_32 (output_bfd,
+ elf32_arm_plt_entry[1]
+ | ((got_displacement & 0x000ff000) >> 12),
+ splt->contents + h->plt.offset + 4);
+ bfd_put_32 (output_bfd,
+ elf32_arm_plt_entry[2]
+ | (got_displacement & 0x00000fff),
+ splt->contents + h->plt.offset + 8);
#ifdef FOUR_WORD_PLT
- bfd_put_32 (output_bfd, elf32_arm_plt_entry[3],
- splt->contents + h->plt.offset + 12);
+ bfd_put_32 (output_bfd, elf32_arm_plt_entry[3],
+ splt->contents + h->plt.offset + 12);
#endif
+ }
/* Fill in the entry in the global offset table. */
bfd_put_32 (output_bfd,
@@ -6776,15 +7034,14 @@ elf32_arm_finish_dynamic_symbol (bfd * output_bfd, struct bfd_link_info * info,
+ splt->output_offset),
sgot->contents + got_offset);
- /* Fill in the entry in the .rel.plt section. */
- rel.r_offset = (sgot->output_section->vma
- + sgot->output_offset
- + got_offset);
+ /* Fill in the entry in the .rel(a).plt section. */
+ rel.r_addend = 0;
+ rel.r_offset = got_address;
rel.r_info = ELF32_R_INFO (h->dynindx, R_ARM_JUMP_SLOT);
}
- loc = srel->contents + plt_index * sizeof (Elf32_External_Rel);
- bfd_elf32_swap_reloc_out (output_bfd, &rel, loc);
+ loc = srel->contents + plt_index * RELOC_SIZE (htab);
+ SWAP_RELOC_OUT (htab) (output_bfd, &rel, loc);
if (!h->def_regular)
{
@@ -6808,16 +7065,19 @@ elf32_arm_finish_dynamic_symbol (bfd * output_bfd, struct bfd_link_info * info,
asection * srel;
Elf_Internal_Rela rel;
bfd_byte *loc;
+ bfd_vma offset;
/* This symbol has an entry in the global offset table. Set it
up. */
sgot = bfd_get_section_by_name (dynobj, ".got");
- srel = bfd_get_section_by_name (dynobj, ".rel.got");
+ srel = bfd_get_section_by_name (dynobj, RELOC_SECTION (htab, ".got"));
BFD_ASSERT (sgot != NULL && srel != NULL);
+ offset = (h->got.offset & ~(bfd_vma) 1);
+ rel.r_addend = 0;
rel.r_offset = (sgot->output_section->vma
+ sgot->output_offset
- + (h->got.offset &~ (bfd_vma) 1));
+ + offset);
/* If this is a static link, or it is a -Bsymbolic link and the
symbol is defined locally or was forced to be local because
@@ -6829,16 +7089,21 @@ elf32_arm_finish_dynamic_symbol (bfd * output_bfd, struct bfd_link_info * info,
{
BFD_ASSERT((h->got.offset & 1) != 0);
rel.r_info = ELF32_R_INFO (0, R_ARM_RELATIVE);
+ if (!htab->use_rel)
+ {
+ rel.r_addend = bfd_get_32 (output_bfd, sgot->contents + offset);
+ bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + offset);
+ }
}
else
{
BFD_ASSERT((h->got.offset & 1) == 0);
- bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got.offset);
+ bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + offset);
rel.r_info = ELF32_R_INFO (h->dynindx, R_ARM_GLOB_DAT);
}
- loc = srel->contents + srel->reloc_count++ * sizeof (Elf32_External_Rel);
- bfd_elf32_swap_reloc_out (output_bfd, &rel, loc);
+ loc = srel->contents + srel->reloc_count++ * RELOC_SIZE (htab);
+ SWAP_RELOC_OUT (htab) (output_bfd, &rel, loc);
}
if (h->needs_copy)
@@ -6853,20 +7118,23 @@ elf32_arm_finish_dynamic_symbol (bfd * output_bfd, struct bfd_link_info * info,
|| h->root.type == bfd_link_hash_defweak));
s = bfd_get_section_by_name (h->root.u.def.section->owner,
- ".rel.bss");
+ RELOC_SECTION (htab, ".bss"));
BFD_ASSERT (s != NULL);
+ rel.r_addend = 0;
rel.r_offset = (h->root.u.def.value
+ h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset);
rel.r_info = ELF32_R_INFO (h->dynindx, R_ARM_COPY);
- loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rel);
- bfd_elf32_swap_reloc_out (output_bfd, &rel, loc);
+ loc = s->contents + s->reloc_count++ * RELOC_SIZE (htab);
+ SWAP_RELOC_OUT (htab) (output_bfd, &rel, loc);
}
- /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. */
+ /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. On VxWorks,
+ the _GLOBAL_OFFSET_TABLE_ symbol is not absolute: it is relative
+ to the ".got" section. */
if (strcmp (h->root.root.string, "_DYNAMIC") == 0
- || h == htab->root.hgot)
+ || (!htab->vxworks_p && h == htab->root.hgot))
sym->st_shndx = SHN_ABS;
return TRUE;
@@ -6938,7 +7206,7 @@ elf32_arm_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info * info
name = ".got";
goto get_vma;
case DT_JMPREL:
- name = ".rel.plt";
+ name = RELOC_SECTION (htab, ".plt");
get_vma:
s = bfd_get_section_by_name (output_bfd, name);
BFD_ASSERT (s != NULL);
@@ -6958,13 +7226,15 @@ elf32_arm_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info * info
break;
case DT_PLTRELSZ:
- s = bfd_get_section_by_name (output_bfd, ".rel.plt");
+ s = bfd_get_section_by_name (output_bfd,
+ RELOC_SECTION (htab, ".plt"));
BFD_ASSERT (s != NULL);
dyn.d_un.d_val = s->size;
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
break;
case DT_RELSZ:
+ case DT_RELASZ:
if (!htab->symbian_p)
{
/* My reading of the SVR4 ABI indicates that the
@@ -6973,10 +7243,11 @@ elf32_arm_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info * info
what Solaris does. However, UnixWare can not handle
that case. Therefore, we override the DT_RELSZ entry
here to make it not include the JMPREL relocs. Since
- the linker script arranges for .rel.plt to follow all
+ the linker script arranges for .rel(a).plt to follow all
other relocation sections, we don't have to worry
about changing the DT_REL entry. */
- s = bfd_get_section_by_name (output_bfd, ".rel.plt");
+ s = bfd_get_section_by_name (output_bfd,
+ RELOC_SECTION (htab, ".plt"));
if (s != NULL)
dyn.d_un.d_val -= s->size;
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
@@ -6986,7 +7257,6 @@ elf32_arm_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info * info
case DT_REL:
case DT_RELA:
- case DT_RELASZ:
/* In the BPABI, the DT_REL tag must point at the file
offset, not the VMA, of the first relocation
section. So, we use code similar to that in
@@ -7049,31 +7319,83 @@ elf32_arm_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info * info
/* Fill in the first entry in the procedure linkage table. */
if (splt->size > 0 && elf32_arm_hash_table (info)->plt_header_size)
{
- bfd_vma got_displacement;
+ const bfd_vma *plt0_entry;
+ bfd_vma got_address, plt_address, got_displacement;
+
+ /* Calculate the addresses of the GOT and PLT. */
+ got_address = sgot->output_section->vma + sgot->output_offset;
+ plt_address = splt->output_section->vma + splt->output_offset;
+
+ if (htab->vxworks_p)
+ {
+ /* The VxWorks GOT is relocated by the dynamic linker.
+ Therefore, we must emit relocations rather than simply
+ computing the values now. */
+ Elf_Internal_Rela rel;
+
+ plt0_entry = elf32_arm_vxworks_exec_plt0_entry;
+ bfd_put_32 (output_bfd, plt0_entry[0], splt->contents + 0);
+ bfd_put_32 (output_bfd, plt0_entry[1], splt->contents + 4);
+ bfd_put_32 (output_bfd, plt0_entry[2], splt->contents + 8);
+ bfd_put_32 (output_bfd, got_address, splt->contents + 12);
+
+ /* Generate a relocation for _GLOBAL_OFFSET_TABLE_. */
+ rel.r_offset = plt_address + 12;
+ rel.r_info = ELF32_R_INFO (htab->root.hgot->indx, R_ARM_ABS32);
+ rel.r_addend = 0;
+ SWAP_RELOC_OUT (htab) (output_bfd, &rel,
+ htab->srelplt2->contents);
+ }
+ else
+ {
+ got_displacement = got_address - (plt_address + 16);
+
+ plt0_entry = elf32_arm_plt0_entry;
+ bfd_put_32 (output_bfd, plt0_entry[0], splt->contents + 0);
+ bfd_put_32 (output_bfd, plt0_entry[1], splt->contents + 4);
+ bfd_put_32 (output_bfd, plt0_entry[2], splt->contents + 8);
+ bfd_put_32 (output_bfd, plt0_entry[3], splt->contents + 12);
- /* Calculate the displacement between the PLT slot and &GOT[0]. */
- got_displacement = (sgot->output_section->vma
- + sgot->output_offset
- - splt->output_section->vma
- - splt->output_offset
- - 16);
-
- bfd_put_32 (output_bfd, elf32_arm_plt0_entry[0], splt->contents + 0);
- bfd_put_32 (output_bfd, elf32_arm_plt0_entry[1], splt->contents + 4);
- bfd_put_32 (output_bfd, elf32_arm_plt0_entry[2], splt->contents + 8);
- bfd_put_32 (output_bfd, elf32_arm_plt0_entry[3], splt->contents + 12);
#ifdef FOUR_WORD_PLT
- /* The displacement value goes in the otherwise-unused last word of
- the second entry. */
- bfd_put_32 (output_bfd, got_displacement, splt->contents + 28);
+ /* The displacement value goes in the otherwise-unused
+ last word of the second entry. */
+ bfd_put_32 (output_bfd, got_displacement, splt->contents + 28);
#else
- bfd_put_32 (output_bfd, got_displacement, splt->contents + 16);
+ bfd_put_32 (output_bfd, got_displacement, splt->contents + 16);
#endif
+ }
}
/* UnixWare sets the entsize of .plt to 4, although that doesn't
really seem like the right value. */
elf_section_data (splt->output_section)->this_hdr.sh_entsize = 4;
+
+ if (htab->vxworks_p && !info->shared && htab->splt->size > 0)
+ {
+ /* Correct the .rel(a).plt.unloaded relocations. They will have
+ incorrect symbol indexes. */
+ int num_plts;
+ unsigned char *p;
+
+ num_plts = ((htab->splt->size - htab->plt_header_size)
+ / htab->plt_entry_size);
+ p = htab->srelplt2->contents + RELOC_SIZE (htab);
+
+ for (; num_plts; num_plts--)
+ {
+ Elf_Internal_Rela rel;
+
+ SWAP_RELOC_IN (htab) (output_bfd, p, &rel);
+ rel.r_info = ELF32_R_INFO (htab->root.hgot->indx, R_ARM_ABS32);
+ SWAP_RELOC_OUT (htab) (output_bfd, &rel, p);
+ p += RELOC_SIZE (htab);
+
+ SWAP_RELOC_IN (htab) (output_bfd, p, &rel);
+ rel.r_info = ELF32_R_INFO (htab->root.hplt->indx, R_ARM_ABS32);
+ SWAP_RELOC_OUT (htab) (output_bfd, &rel, p);
+ p += RELOC_SIZE (htab);
+ }
+ }
}
/* Fill in the first three entries in the global offset table. */
@@ -7443,7 +7765,7 @@ 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)
+ struct elf_link_hash_entry *h)
{
int mapcount;
elf32_arm_section_map *map;
@@ -7451,12 +7773,17 @@ elf32_arm_output_symbol_hook (struct bfd_link_info *info,
_arm_elf_section_data *arm_data;
struct elf32_arm_link_hash_table *globals;
+ globals = elf32_arm_hash_table (info);
+ if (globals->vxworks_p
+ && !elf_vxworks_link_output_symbol_hook (info, name, elfsym,
+ input_sec, h))
+ return FALSE;
+
/* 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;
@@ -7837,27 +8164,48 @@ elf32_arm_vxworks_link_hash_table_create (bfd *abfd)
if (ret)
{
struct elf32_arm_link_hash_table *htab
- = (struct elf32_arm_link_hash_table *)ret;
+ = (struct elf32_arm_link_hash_table *) ret;
htab->use_rel = 0;
+ htab->vxworks_p = 1;
}
return ret;
}
+static void
+elf32_arm_vxworks_final_write_processing (bfd *abfd, bfd_boolean linker)
+{
+ elf32_arm_final_write_processing (abfd, linker);
+ elf_vxworks_final_write_processing (abfd, linker);
+}
+
#undef elf32_bed
#define elf32_bed elf32_arm_vxworks_bed
#undef bfd_elf32_bfd_link_hash_table_create
#define bfd_elf32_bfd_link_hash_table_create \
elf32_arm_vxworks_link_hash_table_create
+#undef elf_backend_add_symbol_hook
+#define elf_backend_add_symbol_hook \
+ elf_vxworks_add_symbol_hook
+#undef elf_backend_final_write_processing
+#define elf_backend_final_write_processing \
+ elf32_arm_vxworks_final_write_processing
+#undef elf_backend_emit_relocs
+#define elf_backend_emit_relocs \
+ elf_vxworks_emit_relocs
#undef elf_backend_may_use_rel_p
-#define elf_backend_may_use_rel_p 0
+#define elf_backend_may_use_rel_p 0
#undef elf_backend_may_use_rela_p
-#define elf_backend_may_use_rela_p 1
+#define elf_backend_may_use_rela_p 1
#undef elf_backend_default_use_rela_p
-#define elf_backend_default_use_rela_p 1
+#define elf_backend_default_use_rela_p 1
#undef elf_backend_rela_normal
-#define elf_backend_rela_normal 1
+#define elf_backend_rela_normal 1
+#undef elf_backend_want_plt_sym
+#define elf_backend_want_plt_sym 1
+#undef ELF_MAXPAGESIZE
+#define ELF_MAXPAGESIZE 0x1000
#include "elf32-target.h"
@@ -7969,6 +8317,7 @@ elf32_arm_symbian_modify_segment_map (bfd *abfd,
#undef bfd_elf32_bfd_link_hash_table_create
#define bfd_elf32_bfd_link_hash_table_create \
elf32_arm_symbian_link_hash_table_create
+#undef elf_backend_add_symbol_hook
#undef elf_backend_special_sections
#define elf_backend_special_sections elf32_arm_symbian_special_sections
@@ -7976,6 +8325,10 @@ elf32_arm_symbian_modify_segment_map (bfd *abfd,
#undef elf_backend_begin_write_processing
#define elf_backend_begin_write_processing \
elf32_arm_symbian_begin_write_processing
+#undef elf_backend_final_write_processing
+#define elf_backend_final_write_processing \
+ elf32_arm_final_write_processing
+#undef elf_backend_emit_relocs
#undef elf_backend_modify_segment_map
#define elf_backend_modify_segment_map elf32_arm_symbian_modify_segment_map
@@ -7989,12 +8342,16 @@ elf32_arm_symbian_modify_segment_map (bfd *abfd,
#define elf_backend_want_got_plt 0
#undef elf_backend_may_use_rel_p
-#define elf_backend_may_use_rel_p 1
+#define elf_backend_may_use_rel_p 1
#undef elf_backend_may_use_rela_p
-#define elf_backend_may_use_rela_p 0
+#define elf_backend_may_use_rela_p 0
#undef elf_backend_default_use_rela_p
-#define elf_backend_default_use_rela_p 0
+#define elf_backend_default_use_rela_p 0
#undef elf_backend_rela_normal
-#define elf_backend_rela_normal 0
+#define elf_backend_rela_normal 0
+#undef elf_backend_want_plt_sym
+#define elf_backend_want_plt_sym 0
+#undef ELF_MAXPAGESIZE
+#define ELF_MAXPAGESIZE 0x8000
#include "elf32-target.h"
diff --git a/bfd/elf32-bfin.c b/bfd/elf32-bfin.c
index c97cbb2..219a834 100644
--- a/bfd/elf32-bfin.c
+++ b/bfd/elf32-bfin.c
@@ -1,5 +1,5 @@
-/* ADI Blackfin BFD support for 32-bit ELF.
- Copyright 2005 Free Software Foundation, Inc.
+/* ADI Blackfin BFD support for 32-bit ELF.
+ Copyright 2005, 2006 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
@@ -23,167 +23,8 @@
#include "libbfd.h"
#include "elf-bfd.h"
#include "elf/bfin.h"
-
-/* Handling expression relocations for blackfin. Blackfin
- will generate relocations in an expression form with a stack.
- A relocation such as P1.H = _typenames-4000000;
- will generate the following relocs at offset 4:
-00000004 R_expst_push _typenames
-00000004 R_expst_const .__constant
-00000004 R_expst_sub .__operator
-00000006 R_huimm16 .__operator
-
- The .__constant and .__operator symbol names are fake.
- Special case is a single relocation
- P1.L = _typenames; generates
-00000002 R_luimm16 _typenames
-
- Thus, if you get a R_luimm16, R_huimm16, R_imm16,
- if the stack is not empty, pop the stack and
- put the value, else do the normal thing
- We will currently assume that the max the stack
- would grow to is 100. . */
-
-#define RELOC_STACK_SIZE 100
-static bfd_vma reloc_stack[RELOC_STACK_SIZE];
-static unsigned int reloc_stack_tos = 0;
-
-#define is_reloc_stack_empty() ((reloc_stack_tos > 0) ? 0 : 1)
-
-static void
-reloc_stack_push (bfd_vma value)
-{
- reloc_stack[reloc_stack_tos++] = value;
-}
-
-static bfd_vma
-reloc_stack_pop (void)
-{
- return reloc_stack[--reloc_stack_tos];
-}
-
-static bfd_vma
-reloc_stack_operate (unsigned int oper)
-{
- bfd_vma value;
- switch (oper)
- {
- case R_add:
- {
- value =
- reloc_stack[reloc_stack_tos - 2] + reloc_stack[reloc_stack_tos - 1];
- reloc_stack_tos -= 2;
- break;
- }
- case R_sub:
- {
- value =
- reloc_stack[reloc_stack_tos - 2] - reloc_stack[reloc_stack_tos - 1];
- reloc_stack_tos -= 2;
- break;
- }
- case R_mult:
- {
- value =
- reloc_stack[reloc_stack_tos - 2] * reloc_stack[reloc_stack_tos - 1];
- reloc_stack_tos -= 2;
- break;
- }
- case R_div:
- {
- if (reloc_stack[reloc_stack_tos - 1] == 0)
- {
- _bfd_abort (__FILE__, __LINE__, _("Division by zero. "));
- }
- else
- {
- value =
- reloc_stack[reloc_stack_tos - 2] / reloc_stack[reloc_stack_tos - 1];
- reloc_stack_tos -= 2;
- }
- break;
- }
- case R_mod:
- {
- value =
- reloc_stack[reloc_stack_tos - 2] % reloc_stack[reloc_stack_tos - 1];
- reloc_stack_tos -= 2;
- break;
- }
- case R_lshift:
- {
- value =
- reloc_stack[reloc_stack_tos - 2] << reloc_stack[reloc_stack_tos -
- 1];
- reloc_stack_tos -= 2;
- break;
- }
- case R_rshift:
- {
- value =
- reloc_stack[reloc_stack_tos - 2] >> reloc_stack[reloc_stack_tos -
- 1];
- reloc_stack_tos -= 2;
- break;
- }
- case R_and:
- {
- value =
- reloc_stack[reloc_stack_tos - 2] & reloc_stack[reloc_stack_tos - 1];
- reloc_stack_tos -= 2;
- break;
- }
- case R_or:
- {
- value =
- reloc_stack[reloc_stack_tos - 2] | reloc_stack[reloc_stack_tos - 1];
- reloc_stack_tos -= 2;
- break;
- }
- case R_xor:
- {
- value =
- reloc_stack[reloc_stack_tos - 2] ^ reloc_stack[reloc_stack_tos - 1];
- reloc_stack_tos -= 2;
- break;
- }
- case R_land:
- {
- value = reloc_stack[reloc_stack_tos - 2]
- && reloc_stack[reloc_stack_tos - 1];
- reloc_stack_tos -= 2;
- break;
- }
- case R_lor:
- {
- value = reloc_stack[reloc_stack_tos - 2]
- || reloc_stack[reloc_stack_tos - 1];
- reloc_stack_tos -= 2;
- break;
- }
- case R_neg:
- {
- value = -reloc_stack[reloc_stack_tos - 1];
- reloc_stack_tos--;
- break;
- }
- case R_comp:
- {
- value = ~reloc_stack[reloc_stack_tos - 1];
- reloc_stack_tos -= 1;
- break;
- }
- default:
- {
- fprintf (stderr, "bfin relocation : Internal bug\n");
- return 0;
- }
- }
-
- reloc_stack_push (value);
-
- return value;
-}
+#include "elf/dwarf2.h"
+#include "hashtab.h"
/* FUNCTION : bfin_pltpc_reloc
ABSTRACT : TODO : figure out how to handle pltpc relocs. */
@@ -195,10 +36,10 @@ bfin_pltpc_reloc (
PTR data ATTRIBUTE_UNUSED,
asection *input_section ATTRIBUTE_UNUSED,
bfd *output_bfd ATTRIBUTE_UNUSED,
- char **error_message ATTRIBUTE_UNUSED)
+ char **error_message ATTRIBUTE_UNUSED)
{
bfd_reloc_status_type flag = bfd_reloc_ok;
- return flag;
+ return flag;
}
@@ -221,49 +62,44 @@ bfin_pcrel24_reloc (bfd *abfd,
if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
return bfd_reloc_outofrange;
- if (!is_reloc_stack_empty ())
- relocation = reloc_stack_pop();
+ if (bfd_is_und_section (symbol->section)
+ && (symbol->flags & BSF_WEAK) == 0
+ && !relocatable)
+ return bfd_reloc_undefined;
+
+ if (bfd_is_com_section (symbol->section))
+ relocation = 0;
else
- {
- if (bfd_is_und_section (symbol->section)
- && (symbol->flags & BSF_WEAK) == 0
- && !relocatable)
- return bfd_reloc_undefined;
+ relocation = symbol->value;
- if (bfd_is_com_section (symbol->section))
- relocation = 0;
- else
- relocation = symbol->value;
+ output_section = symbol->section->output_section;
+
+ if (relocatable)
+ output_base = 0;
+ else
+ output_base = output_section->vma;
- output_section = symbol->section->output_section;
+ if (!relocatable || !strcmp (symbol->name, symbol->section->name))
+ relocation += output_base + symbol->section->output_offset;
+
+ if (!relocatable && !strcmp (symbol->name, symbol->section->name))
+ relocation += reloc_entry->addend;
- if (relocatable)
- output_base = 0;
- else
- output_base = output_section->vma;
-
- if (!relocatable || !strcmp (symbol->name, symbol->section->name))
- relocation += output_base + symbol->section->output_offset;
-
- if (!relocatable && !strcmp (symbol->name, symbol->section->name))
- relocation += reloc_entry->addend;
- }
-
relocation -= input_section->output_section->vma + input_section->output_offset;
relocation -= reloc_entry->address;
if (howto->complain_on_overflow != complain_overflow_dont)
{
bfd_reloc_status_type status;
- status= bfd_check_overflow (howto->complain_on_overflow,
- howto->bitsize,
- howto->rightshift,
- bfd_arch_bits_per_address(abfd),
- relocation);
+ status = bfd_check_overflow (howto->complain_on_overflow,
+ howto->bitsize,
+ howto->rightshift,
+ bfd_arch_bits_per_address(abfd),
+ relocation);
if (status != bfd_reloc_ok)
return status;
}
-
+
/* if rightshift is 1 and the number odd, return error. */
if (howto->rightshift && (relocation & 0x01))
{
@@ -286,11 +122,11 @@ bfin_pcrel24_reloc (bfd *abfd,
short x;
/* We are getting reloc_entry->address 2 byte off from
- the start of instruction. Assuming absolute postion
- of the reloc data. But, following code had been written assuming
- reloc address is starting at begining of instruction.
- To compensate that I have increased the value of
- relocation by 1 (effectively 2) and used the addr -2 instead of addr. */
+ the start of instruction. Assuming absolute postion
+ of the reloc data. But, following code had been written assuming
+ reloc address is starting at begining of instruction.
+ To compensate that I have increased the value of
+ relocation by 1 (effectively 2) and used the addr -2 instead of addr. */
relocation += 1;
x = bfd_get_16 (abfd, (bfd_byte *) data + addr - 2);
@@ -305,30 +141,32 @@ bfin_pcrel24_reloc (bfd *abfd,
}
static bfd_reloc_status_type
-bfin_push_reloc (bfd *abfd ATTRIBUTE_UNUSED,
- arelent *reloc_entry,
- asymbol *symbol,
- PTR data ATTRIBUTE_UNUSED,
- asection *input_section,
- bfd *output_bfd,
- char **error_message ATTRIBUTE_UNUSED)
+bfin_imm16_reloc (bfd *abfd,
+ arelent *reloc_entry,
+ asymbol *symbol,
+ PTR data,
+ asection *input_section,
+ bfd *output_bfd,
+ char **error_message ATTRIBUTE_UNUSED)
{
- bfd_vma relocation;
+ bfd_vma relocation, x;
+ bfd_size_type reloc_addr = reloc_entry->address;
bfd_vma output_base = 0;
+ reloc_howto_type *howto = reloc_entry->howto;
asection *output_section;
bfd_boolean relocatable = (output_bfd != NULL);
+ /* Is the address of the relocation really within the section? */
+ if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
+ return bfd_reloc_outofrange;
+
if (bfd_is_und_section (symbol->section)
&& (symbol->flags & BSF_WEAK) == 0
&& !relocatable)
return bfd_reloc_undefined;
- /* Is the address of the relocation really within the section? */
- if (reloc_entry->address > bfd_get_section_limit(abfd, input_section))
- return bfd_reloc_outofrange;
-
output_section = symbol->section->output_section;
- relocation = symbol->value;
+ relocation = symbol->value;
/* Convert input-section-relative symbol value to absolute. */
if (relocatable)
@@ -336,7 +174,7 @@ bfin_push_reloc (bfd *abfd ATTRIBUTE_UNUSED,
else
output_base = output_section->vma;
- if (!relocatable || !strcmp(symbol->name, symbol->section->name))
+ if (!relocatable || !strcmp (symbol->name, symbol->section->name))
relocation += output_base + symbol->section->output_offset;
/* Add in supplied addend. */
@@ -347,105 +185,6 @@ bfin_push_reloc (bfd *abfd ATTRIBUTE_UNUSED,
reloc_entry->address += input_section->output_offset;
reloc_entry->addend += symbol->section->output_offset;
}
-
- /* Now that we have the value, push it. */
- reloc_stack_push (relocation);
-
- return bfd_reloc_ok;
-}
-
-static bfd_reloc_status_type
-bfin_oper_reloc (bfd *abfd ATTRIBUTE_UNUSED,
- arelent *reloc_entry,
- asymbol *symbol ATTRIBUTE_UNUSED,
- PTR data ATTRIBUTE_UNUSED,
- asection *input_section,
- bfd *output_bfd,
- char **error_message ATTRIBUTE_UNUSED)
-{
- bfd_boolean relocatable = (output_bfd != NULL);
-
- /* Just call the operation based on the reloc_type. */
- reloc_stack_operate (reloc_entry->howto->type);
-
- if (relocatable)
- reloc_entry->address += input_section->output_offset;
-
- return bfd_reloc_ok;
-}
-
-static bfd_reloc_status_type
-bfin_const_reloc (bfd *abfd ATTRIBUTE_UNUSED,
- arelent *reloc_entry,
- asymbol *symbol ATTRIBUTE_UNUSED,
- PTR data ATTRIBUTE_UNUSED,
- asection *input_section,
- bfd *output_bfd,
- char **error_message ATTRIBUTE_UNUSED)
-{
- bfd_boolean relocatable = (output_bfd != NULL);
-
- /* Push the addend portion of the relocation. */
- reloc_stack_push (reloc_entry->addend);
-
- if (relocatable)
- reloc_entry->address += input_section->output_offset;
-
- return bfd_reloc_ok;
-}
-
-static bfd_reloc_status_type
-bfin_imm16_reloc (bfd *abfd,
- arelent *reloc_entry,
- asymbol *symbol,
- PTR data,
- asection *input_section,
- bfd *output_bfd,
- char **error_message ATTRIBUTE_UNUSED)
-{
- bfd_vma relocation, x;
- bfd_size_type reloc_addr = reloc_entry->address;
- bfd_vma output_base = 0;
- reloc_howto_type *howto = reloc_entry->howto;
- asection *output_section;
- bfd_boolean relocatable = (output_bfd != NULL);
-
- /* Is the address of the relocation really within the section? */
- if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
- return bfd_reloc_outofrange;
-
- if (is_reloc_stack_empty ())
- {
- if (bfd_is_und_section (symbol->section)
- && (symbol->flags & BSF_WEAK) == 0
- && !relocatable)
- return bfd_reloc_undefined;
-
- output_section = symbol->section->output_section;
- relocation = symbol->value;
-
- /* Convert input-section-relative symbol value to absolute. */
- if (relocatable)
- output_base = 0;
- else
- output_base = output_section->vma;
-
- if (!relocatable || !strcmp (symbol->name, symbol->section->name))
- relocation += output_base + symbol->section->output_offset;
-
- /* Add in supplied addend. */
- relocation += reloc_entry->addend;
- }
- else
- {
- relocation = reloc_stack_pop ();
- }
-
- if (relocatable)
- {
- reloc_entry->address += input_section->output_offset;
- reloc_entry->addend += symbol->section->output_offset;
- }
else
{
reloc_entry->addend = 0;
@@ -455,15 +194,14 @@ bfin_imm16_reloc (bfd *abfd,
{
bfd_reloc_status_type flag;
flag = bfd_check_overflow (howto->complain_on_overflow,
- howto->bitsize,
- howto->rightshift,
- bfd_arch_bits_per_address(abfd),
- relocation);
+ howto->bitsize,
+ howto->rightshift,
+ bfd_arch_bits_per_address(abfd),
+ relocation);
if (flag != bfd_reloc_ok)
- return flag;
+ return flag;
}
-
/* Here the variable relocation holds the final address of the
symbol we are relocating against, plus any addend. */
@@ -481,7 +219,7 @@ bfin_byte4_reloc (bfd *abfd,
PTR data,
asection *input_section,
bfd *output_bfd,
- char **error_message ATTRIBUTE_UNUSED)
+ char **error_message ATTRIBUTE_UNUSED)
{
bfd_vma relocation, x;
bfd_size_type addr = reloc_entry->address;
@@ -493,39 +231,31 @@ bfin_byte4_reloc (bfd *abfd,
if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
return bfd_reloc_outofrange;
- if (is_reloc_stack_empty ())
- {
- if (bfd_is_und_section (symbol->section)
- && (symbol->flags & BSF_WEAK) == 0
- && !relocatable)
- return bfd_reloc_undefined;
-
- output_section = symbol->section->output_section;
- relocation = symbol->value;
- /* Convert input-section-relative symbol value to absolute. */
- if (relocatable)
- output_base = 0;
- else
- output_base = output_section->vma;
-
- if ((symbol->name
- && symbol->section->name
- && !strcmp (symbol->name, symbol->section->name))
- || !relocatable)
- {
- relocation += output_base + symbol->section->output_offset;
- }
+ if (bfd_is_und_section (symbol->section)
+ && (symbol->flags & BSF_WEAK) == 0
+ && !relocatable)
+ return bfd_reloc_undefined;
- relocation += reloc_entry->addend;
- }
+ output_section = symbol->section->output_section;
+ relocation = symbol->value;
+ /* Convert input-section-relative symbol value to absolute. */
+ if (relocatable)
+ output_base = 0;
else
+ output_base = output_section->vma;
+
+ if ((symbol->name
+ && symbol->section->name
+ && !strcmp (symbol->name, symbol->section->name))
+ || !relocatable)
{
- relocation = reloc_stack_pop();
- relocation += reloc_entry->addend;
+ relocation += output_base + symbol->section->output_offset;
}
+ relocation += reloc_entry->addend;
+
if (relocatable)
- {
+ {
/* This output will be relocatable ... like ld -r. */
reloc_entry->address += input_section->output_offset;
reloc_entry->addend += symbol->section->output_offset;
@@ -540,7 +270,7 @@ bfin_byte4_reloc (bfd *abfd,
x = relocation & 0xFFFF0000;
x >>=16;
bfd_put_16 (abfd, x, (unsigned char *) data + addr + 2);
-
+
x = relocation & 0x0000FFFF;
bfd_put_16 (abfd, x, (unsigned char *) data + addr);
return bfd_reloc_ok;
@@ -568,42 +298,34 @@ bfin_bfd_reloc (bfd *abfd,
if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
return bfd_reloc_outofrange;
- if (is_reloc_stack_empty())
- {
- if (bfd_is_und_section (symbol->section)
- && (symbol->flags & BSF_WEAK) == 0
- && !relocatable)
- return bfd_reloc_undefined;
+ if (bfd_is_und_section (symbol->section)
+ && (symbol->flags & BSF_WEAK) == 0
+ && !relocatable)
+ return bfd_reloc_undefined;
- /* Get symbol value. (Common symbols are special.) */
- if (bfd_is_com_section (symbol->section))
- relocation = 0;
- else
- relocation = symbol->value;
-
- output_section = symbol->section->output_section;
-
- /* Convert input-section-relative symbol value to absolute. */
- if (relocatable)
- output_base = 0;
- else
- output_base = output_section->vma;
-
- if (!relocatable || !strcmp (symbol->name, symbol->section->name))
- relocation += output_base + symbol->section->output_offset;
-
- if (!relocatable && !strcmp (symbol->name, symbol->section->name))
- {
- /* Add in supplied addend. */
- relocation += reloc_entry->addend;
- }
-
- }
+ /* Get symbol value. (Common symbols are special.) */
+ if (bfd_is_com_section (symbol->section))
+ relocation = 0;
else
+ relocation = symbol->value;
+
+ output_section = symbol->section->output_section;
+
+ /* Convert input-section-relative symbol value to absolute. */
+ if (relocatable)
+ output_base = 0;
+ else
+ output_base = output_section->vma;
+
+ if (!relocatable || !strcmp (symbol->name, symbol->section->name))
+ relocation += output_base + symbol->section->output_offset;
+
+ if (!relocatable && !strcmp (symbol->name, symbol->section->name))
{
- relocation = reloc_stack_pop();
+ /* Add in supplied addend. */
+ relocation += reloc_entry->addend;
}
-
+
/* Here the variable relocation holds the final address of the
symbol we are relocating against, plus any addend. */
@@ -625,15 +347,15 @@ bfin_bfd_reloc (bfd *abfd,
{
bfd_reloc_status_type status;
- status = bfd_check_overflow (howto->complain_on_overflow,
+ status = bfd_check_overflow (howto->complain_on_overflow,
howto->bitsize,
- howto->rightshift,
+ howto->rightshift,
bfd_arch_bits_per_address(abfd),
relocation);
if (status != bfd_reloc_ok)
return status;
}
-
+
/* If rightshift is 1 and the number odd, return error. */
if (howto->rightshift && (relocation & 0x01))
{
@@ -647,7 +369,7 @@ bfin_bfd_reloc (bfd *abfd,
relocation <<= (bfd_vma) howto->bitpos;
-#define DOIT(x) \
+#define DOIT(x) \
x = ( (x & ~howto->dst_mask) | (relocation & howto->dst_mask))
/* handle 8 and 16 bit relocations here. */
@@ -673,41 +395,9 @@ bfin_bfd_reloc (bfd *abfd,
return bfd_reloc_other;
}
- return bfd_reloc_ok;
+ return bfd_reloc_ok;
}
-#if 0
-static bfd_reloc_status_type bfin_bfd_reloc
- PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-
-static bfd_reloc_status_type bfin_imm16_reloc
- PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-
-static bfd_reloc_status_type bfin_pcrel24_reloc
- PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-
-static bfd_reloc_status_type bfin_pltpc_reloc
- PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-
-static bfd_reloc_status_type bfin_const_reloc
- PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-
-static bfd_reloc_status_type bfin_oper_reloc
- PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-
-static bfd_reloc_status_type bfin_byte4_reloc
- PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-
-static bfd_reloc_status_type bfin_push_reloc
- PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-
-static bfd_boolean bfin_is_local_label_name
- PARAMS ((bfd *, const char *));
-#endif
-bfd_boolean bfd_bfin_elf32_create_embedded_relocs
- PARAMS ((bfd *, struct bfd_link_info *, asection *, asection *, char **));
-
-
/* HOWTO Table for blackfin.
Blackfin relocations are fairly complicated.
Some of the salient features are
@@ -722,7 +412,7 @@ bfd_boolean bfd_bfin_elf32_create_embedded_relocs
the relocation stack. . */
#define BFIN_RELOC_MIN 0
-#define BFIN_RELOC_MAX 0x13
+#define BFIN_RELOC_MAX 0x21
#define BFIN_GNUEXT_RELOC_MIN 0x40
#define BFIN_GNUEXT_RELOC_MAX 0x43
#define BFIN_ARELOC_MIN 0xE0
@@ -786,7 +476,7 @@ static reloc_howto_type bfin_howto_table [] =
0, /* src_mask. */
0x000003FF, /* dst_mask. */
TRUE), /* pcrel_offset. */
-
+
HOWTO (R_pcrel12_jump, /* type. */
1, /* rightshift. */
/* the offset is actually 13 bit
@@ -832,7 +522,7 @@ static reloc_howto_type bfin_howto_table [] =
0, /* src_mask. */
0x0000FFFF, /* dst_mask. */
TRUE), /* pcrel_offset. */
-
+
HOWTO (R_huimm16, /* type. */
16, /* rightshift. */
1, /* size (0 = byte, 1 = short, 2 = long). */
@@ -1014,289 +704,229 @@ static reloc_howto_type bfin_howto_table [] =
0, /* src_mask. */
0x000003FF, /* dst_mask. */
FALSE), /* pcrel_offset. */
-};
-
-static reloc_howto_type bfin_areloc_howto_table [] =
-{
- HOWTO (R_push,
- 0,
- 2,
- 0,
- FALSE,
- 0,
- complain_overflow_dont,
- bfin_push_reloc,
- "R_expst_push",
- FALSE,
- 0,
- 0,
- FALSE),
-
- HOWTO (R_const,
- 0,
- 2,
- 0,
- FALSE,
- 0,
- complain_overflow_dont,
- bfin_const_reloc,
- "R_expst_const",
- FALSE,
- 0,
- 0,
- FALSE),
-
- HOWTO (R_add,
- 0,
- 0,
- 0,
- FALSE,
- 0,
- complain_overflow_dont,
- bfin_oper_reloc,
- "R_expst_add",
- FALSE,
- 0,
- 0,
- FALSE),
-
- HOWTO (R_sub,
- 0,
- 0,
- 0,
- FALSE,
- 0,
- complain_overflow_dont,
- bfin_oper_reloc,
- "R_expst_sub",
- FALSE,
- 0,
- 0,
- FALSE),
-
- HOWTO (R_mult,
- 0,
- 0,
- 0,
- FALSE,
- 0,
- complain_overflow_dont,
- bfin_oper_reloc,
- "R_expst_mult",
- FALSE,
- 0,
- 0,
- FALSE),
-
- HOWTO (R_div, /* type. */
- 0, /* rightshift. */
- 0, /* size (0 = byte, 1 = short, 2 = long). */
- 0, /* bitsize. */
- FALSE, /* pc_relative. */
- 0, /* bitpos. */
- complain_overflow_dont, /* complain_on_overflow. */
- bfin_oper_reloc, /* special_function. */
- "R_expst_div", /* name. */
- FALSE, /* partial_inplace. */
- 0, /* src_mask. */
- 0, /* dst_mask. */
- FALSE), /* pcrel_offset. */
-
- HOWTO (R_mod, /* type. */
- 0, /* rightshift. */
- 0, /* size (0 = byte, 1 = short, 2 = long). */
- 0, /* bitsize. */
- FALSE, /* pc_relative. */
- 0, /* bitpos. */
- complain_overflow_dont, /* complain_on_overflow. */
- bfin_oper_reloc, /* special_function. */
- "R_expst_mod", /* name. */
- FALSE, /* partial_inplace. */
- 0, /* src_mask. */
- 0, /* dst_mask. */
- FALSE), /* pcrel_offset. */
-
- HOWTO (R_lshift, /* type. */
- 0, /* rightshift. */
- 0, /* size (0 = byte, 1 = short, 2 = long). */
- 0, /* bitsize. */
- FALSE, /* pc_relative. */
- 0, /* bitpos. */
- complain_overflow_dont, /* complain_on_overflow. */
- bfin_oper_reloc, /* special_function. */
- "R_expst_lshift", /* name. */
- FALSE, /* partial_inplace. */
- 0, /* src_mask. */
- 0, /* dst_mask. */
- FALSE), /* pcrel_offset. */
-
- HOWTO (R_rshift, /* type. */
- 0, /* rightshift. */
- 0, /* size (0 = byte, 1 = short, 2 = long). */
- 0, /* bitsize. */
- FALSE, /* pc_relative. */
- 0, /* bitpos. */
- complain_overflow_dont, /* complain_on_overflow. */
- bfin_oper_reloc, /* special_function. */
- "R_expst_rshift", /* name. */
- FALSE, /* partial_inplace. */
- 0, /* src_mask. */
- 0, /* dst_mask. */
- FALSE), /* pcrel_offset. */
-
- HOWTO (R_and, /* type. */
- 0, /* rightshift. */
- 0, /* size (0 = byte, 1 = short, 2 = long). */
- 0, /* bitsize. */
- FALSE, /* pc_relative. */
- 0, /* bitpos. */
- complain_overflow_dont, /* complain_on_overflow. */
- bfin_oper_reloc, /* special_function. */
- "R_expst_and", /* name. */
- FALSE, /* partial_inplace. */
- 0, /* src_mask. */
- 0, /* dst_mask. */
- FALSE), /* pcrel_offset. */
-
- HOWTO (R_or, /* type. */
- 0, /* rightshift. */
- 0, /* size (0 = byte, 1 = short, 2 = long). */
- 0, /* bitsize. */
- FALSE, /* pc_relative. */
- 0, /* bitpos. */
- complain_overflow_dont, /* complain_on_overflow. */
- bfin_oper_reloc, /* special_function. */
- "R_expst_or", /* name. */
- FALSE, /* partial_inplace. */
- 0, /* src_mask. */
- 0, /* dst_mask. */
- FALSE), /* pcrel_offset. */
-
- HOWTO (R_xor, /* type. */
- 0, /* rightshift. */
- 0, /* size (0 = byte, 1 = short, 2 = long). */
- 0, /* bitsize. */
- FALSE, /* pc_relative. */
- 0, /* bitpos. */
- complain_overflow_dont, /* complain_on_overflow. */
- bfin_oper_reloc, /* special_function. */
- "R_expst_xor", /* name. */
- FALSE, /* partial_inplace. */
- 0, /* src_mask. */
- 0, /* dst_mask. */
- FALSE), /* pcrel_offset. */
-
- HOWTO (R_land, /* type. */
- 0, /* rightshift. */
- 0, /* size (0 = byte, 1 = short, 2 = long). */
- 0, /* bitsize. */
- FALSE, /* pc_relative. */
- 0, /* bitpos. */
- complain_overflow_dont, /* complain_on_overflow. */
- bfin_oper_reloc, /* special_function. */
- "R_expst_land", /* name. */
- FALSE, /* partial_inplace. */
- 0, /* src_mask. */
- 0, /* dst_mask. */
- FALSE), /* pcrel_offset. */
-
- HOWTO (R_lor, /* type. */
- 0, /* rightshift. */
- 0, /* size (0 = byte, 1 = short, 2 = long). */
- 0, /* bitsize. */
- FALSE, /* pc_relative. */
- 0, /* bitpos. */
- complain_overflow_dont, /* complain_on_overflow. */
- bfin_oper_reloc, /* special_function. */
- "R_expst_lor", /* name. */
- FALSE, /* partial_inplace. */
- 0, /* src_mask. */
- 0, /* dst_mask. */
- FALSE), /* pcrel_offset. */
- HOWTO (R_len, /* type. */
- 0, /* rightshift. */
- 0, /* size (0 = byte, 1 = short, 2 = long). */
- 0, /* bitsize. */
- FALSE, /* pc_relative. */
- 0, /* bitpos. */
- complain_overflow_dont, /* complain_on_overflow. */
- bfin_oper_reloc, /* special_function. */
- "R_expst_len", /* name. */
- FALSE, /* partial_inplace. */
- 0, /* src_mask. */
- 0, /* dst_mask. */
- FALSE), /* pcrel_offset. */
- HOWTO (R_neg, /* type. */
- 0, /* rightshift. */
- 0, /* size (0 = byte, 1 = short, 2 = long). */
- 0, /* bitsize. */
- FALSE, /* pc_relative. */
- 0, /* bitpos. */
- complain_overflow_dont, /* complain_on_overflow. */
- bfin_oper_reloc, /* special_function. */
- "R_expst_neg", /* name. */
- FALSE, /* partial_inplace. */
- 0, /* src_mask. */
- 0, /* dst_mask. */
- FALSE), /* pcrel_offset. */
-
- HOWTO (R_comp, /* type. */
- 0, /* rightshift. */
- 0, /* size (0 = byte, 1 = short, 2 = long). */
- 0, /* bitsize. */
- FALSE, /* pc_relative. */
- 0, /* bitpos. */
- complain_overflow_dont, /* complain_on_overflow. */
- bfin_oper_reloc, /* special_function. */
- "R_expst_comp", /* name. */
- FALSE, /* partial_inplace. */
- 0, /* src_mask. */
- 0, /* dst_mask. */
- FALSE), /* pcrel_offset. */
-
- HOWTO (R_page, /* type. */
- 0, /* rightshift. */
- 0, /* size (0 = byte, 1 = short, 2 = long). */
- 0, /* bitsize. */
- FALSE, /* pc_relative. */
- 0, /* bitpos. */
- complain_overflow_dont, /* complain_on_overflow. */
- bfin_oper_reloc, /* special_function. */
- "R_expst_page", /* name. */
- FALSE, /* partial_inplace. */
- 0, /* src_mask. */
- 0, /* dst_mask. */
- FALSE), /* pcrel_offset. */
-
- HOWTO (R_hwpage, /* type. */
- 0, /* rightshift. */
- 0, /* size (0 = byte, 1 = short, 2 = long). */
- 0, /* bitsize. */
- FALSE, /* pc_relative. */
- 0, /* bitpos. */
- complain_overflow_dont, /* complain_on_overflow. */
- bfin_oper_reloc, /* special_function. */
- "R_expst_hwpage", /* name. */
- FALSE, /* partial_inplace. */
- 0, /* src_mask. */
- 0, /* dst_mask. */
- FALSE), /* pcrel_offset. */
-
- HOWTO (R_addr, /* type. */
- 0, /* rightshift. */
- 0, /* size (0 = byte, 1 = short, 2 = long). */
- 0, /* bitsize. */
- FALSE, /* pc_relative. */
- 0, /* bitpos. */
- complain_overflow_dont, /* complain_on_overflow. */
- bfin_oper_reloc, /* special_function. */
- "R_expst_addr", /* name. */
- FALSE, /* partial_inplace. */
- 0, /* src_mask. */
- 0, /* dst_mask. */
- FALSE), /* pcrel_offset. */
+ /* A 18-bit signed operand with the GOT offset for the address of
+ the symbol. */
+ HOWTO (R_BFIN_GOT17M4, /* type */
+ 2, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_BFIN_GOT12", /* name */
+ FALSE, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* The upper 16 bits of the GOT offset for the address of the
+ symbol. */
+ HOWTO (R_BFIN_GOTHI, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_BFIN_GOTHI", /* name */
+ FALSE, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* The lower 16 bits of the GOT offset for the address of the
+ symbol. */
+ HOWTO (R_BFIN_GOTLO, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_BFIN_GOTLO", /* name */
+ FALSE, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* The 32-bit address of the canonical descriptor of a function. */
+ HOWTO (R_BFIN_FUNCDESC, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_BFIN_FUNCDESC", /* name */
+ FALSE, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* A 12-bit signed operand with the GOT offset for the address of
+ canonical descriptor of a function. */
+ HOWTO (R_BFIN_FUNCDESC_GOT17M4, /* type */
+ 2, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_BFIN_FUNCDESC_GOT17M4", /* name */
+ FALSE, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* The upper 16 bits of the GOT offset for the address of the
+ canonical descriptor of a function. */
+ HOWTO (R_BFIN_FUNCDESC_GOTHI, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_BFIN_FUNCDESC_GOTHI", /* name */
+ FALSE, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* The lower 16 bits of the GOT offset for the address of the
+ canonical descriptor of a function. */
+ HOWTO (R_BFIN_FUNCDESC_GOTLO, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_BFIN_FUNCDESC_GOTLO", /* name */
+ FALSE, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* The 32-bit address of the canonical descriptor of a function. */
+ HOWTO (R_BFIN_FUNCDESC_VALUE, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 64, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_BFIN_FUNCDESC_VALUE", /* name */
+ FALSE, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* A 12-bit signed operand with the GOT offset for the address of
+ canonical descriptor of a function. */
+ HOWTO (R_BFIN_FUNCDESC_GOTOFF17M4, /* type */
+ 2, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_BFIN_FUNCDESC_GOTOFF17M4", /* name */
+ FALSE, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* The upper 16 bits of the GOT offset for the address of the
+ canonical descriptor of a function. */
+ HOWTO (R_BFIN_FUNCDESC_GOTOFFHI, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_BFIN_FUNCDESC_GOTOFFHI", /* name */
+ FALSE, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* The lower 16 bits of the GOT offset for the address of the
+ canonical descriptor of a function. */
+ HOWTO (R_BFIN_FUNCDESC_GOTOFFLO, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_BFIN_FUNCDESC_GOTOFFLO", /* name */
+ FALSE, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* A 12-bit signed operand with the GOT offset for the address of
+ the symbol. */
+ HOWTO (R_BFIN_GOTOFF17M4, /* type */
+ 2, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_BFIN_GOTOFF17M4", /* name */
+ FALSE, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* The upper 16 bits of the GOT offset for the address of the
+ symbol. */
+ HOWTO (R_BFIN_GOTOFFHI, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_BFIN_GOTOFFHI", /* name */
+ FALSE, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* The lower 16 bits of the GOT offset for the address of the
+ symbol. */
+ HOWTO (R_BFIN_GOTOFFLO, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_BFIN_GOTOFFLO", /* name */
+ FALSE, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
};
static reloc_howto_type bfin_gnuext_howto_table [] =
@@ -1389,29 +1019,24 @@ static const struct bfin_reloc_map bfin_reloc_map [] =
{ BFD_RELOC_BFIN_11_PCREL, R_pcrel11 },
{ BFD_RELOC_BFIN_GOT, R_got },
{ BFD_RELOC_BFIN_PLTPC, R_pltpc },
+
+ { BFD_RELOC_BFIN_GOT17M4, R_BFIN_GOT17M4 },
+ { BFD_RELOC_BFIN_GOTHI, R_BFIN_GOTHI },
+ { BFD_RELOC_BFIN_GOTLO, R_BFIN_GOTLO },
+ { BFD_RELOC_BFIN_FUNCDESC, R_BFIN_FUNCDESC },
+ { BFD_RELOC_BFIN_FUNCDESC_GOT17M4, R_BFIN_FUNCDESC_GOT17M4 },
+ { BFD_RELOC_BFIN_FUNCDESC_GOTHI, R_BFIN_FUNCDESC_GOTHI },
+ { BFD_RELOC_BFIN_FUNCDESC_GOTLO, R_BFIN_FUNCDESC_GOTLO },
+ { BFD_RELOC_BFIN_FUNCDESC_VALUE, R_BFIN_FUNCDESC_VALUE },
+ { BFD_RELOC_BFIN_FUNCDESC_GOTOFF17M4, R_BFIN_FUNCDESC_GOTOFF17M4 },
+ { BFD_RELOC_BFIN_FUNCDESC_GOTOFFHI, R_BFIN_FUNCDESC_GOTOFFHI },
+ { BFD_RELOC_BFIN_FUNCDESC_GOTOFFLO, R_BFIN_FUNCDESC_GOTOFFLO },
+ { BFD_RELOC_BFIN_GOTOFF17M4, R_BFIN_GOTOFF17M4 },
+ { BFD_RELOC_BFIN_GOTOFFHI, R_BFIN_GOTOFFHI },
+ { BFD_RELOC_BFIN_GOTOFFLO, R_BFIN_GOTOFFLO },
+
{ BFD_RELOC_VTABLE_INHERIT, R_BFIN_GNU_VTINHERIT },
{ BFD_RELOC_VTABLE_ENTRY, R_BFIN_GNU_VTENTRY },
- { BFD_ARELOC_BFIN_PUSH, R_push },
- { BFD_ARELOC_BFIN_CONST, R_const },
- { BFD_ARELOC_BFIN_ADD, R_add },
- { BFD_ARELOC_BFIN_SUB, R_sub },
- { BFD_ARELOC_BFIN_MULT, R_mult },
- { BFD_ARELOC_BFIN_DIV, R_div },
- { BFD_ARELOC_BFIN_MOD, R_mod },
- { BFD_ARELOC_BFIN_LSHIFT, R_lshift },
- { BFD_ARELOC_BFIN_RSHIFT, R_rshift },
- { BFD_ARELOC_BFIN_AND, R_and },
- { BFD_ARELOC_BFIN_OR, R_or },
- { BFD_ARELOC_BFIN_XOR, R_xor },
- { BFD_ARELOC_BFIN_LAND, R_land },
- { BFD_ARELOC_BFIN_LOR, R_lor },
- { BFD_ARELOC_BFIN_LEN, R_len },
- { BFD_ARELOC_BFIN_NEG, R_neg },
- { BFD_ARELOC_BFIN_COMP, R_comp },
- { BFD_ARELOC_BFIN_PAGE, R_page },
- { BFD_ARELOC_BFIN_HWPAGE, R_hwpage },
- { BFD_ARELOC_BFIN_ADDR, R_addr }
-
};
@@ -1427,9 +1052,6 @@ bfin_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
if (r_type <= BFIN_RELOC_MAX)
cache_ptr->howto = &bfin_howto_table [r_type];
- else if (r_type >= BFIN_ARELOC_MIN && r_type <= BFIN_ARELOC_MAX)
- cache_ptr->howto = &bfin_areloc_howto_table [r_type - BFIN_ARELOC_MIN];
-
else if (r_type >= BFIN_GNUEXT_RELOC_MIN && r_type <= BFIN_GNUEXT_RELOC_MAX)
cache_ptr->howto = &bfin_gnuext_howto_table [r_type - BFIN_GNUEXT_RELOC_MIN];
@@ -1452,9 +1074,6 @@ bfin_bfd_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
if (r_type <= BFIN_RELOC_MAX && r_type > BFIN_RELOC_MIN)
return &bfin_howto_table [r_type];
- else if (r_type >= BFIN_ARELOC_MIN && r_type <= BFIN_ARELOC_MAX)
- return &bfin_areloc_howto_table [r_type - BFIN_ARELOC_MIN];
-
else if (r_type >= BFIN_GNUEXT_RELOC_MIN && r_type <= BFIN_GNUEXT_RELOC_MAX)
return &bfin_gnuext_howto_table [r_type - BFIN_GNUEXT_RELOC_MIN];
@@ -1469,9 +1088,6 @@ bfin_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
if (r_type <= BFIN_RELOC_MAX)
return &bfin_howto_table [r_type];
- else if (r_type >= BFIN_ARELOC_MIN && r_type <= BFIN_ARELOC_MAX)
- return &bfin_areloc_howto_table [r_type - BFIN_ARELOC_MIN];
-
else if (r_type >= BFIN_GNUEXT_RELOC_MIN && r_type <= BFIN_GNUEXT_RELOC_MAX)
return &bfin_gnuext_howto_table [r_type - BFIN_GNUEXT_RELOC_MIN];
@@ -1492,6 +1108,797 @@ bfin_is_local_label_name (
return _bfd_elf_is_local_label_name (abfd, label);
}
+extern const bfd_target bfd_elf32_bfinfdpic_vec;
+#define IS_FDPIC(bfd) ((bfd)->xvec == &bfd_elf32_bfinfdpic_vec)
+
+/* An extension of the elf hash table data structure, containing some
+ additional Blackfin-specific data. */
+struct bfinfdpic_elf_link_hash_table
+{
+ struct elf_link_hash_table elf;
+
+ /* A pointer to the .got section. */
+ asection *sgot;
+ /* A pointer to the .rel.got section. */
+ asection *sgotrel;
+ /* A pointer to the .rofixup section. */
+ asection *sgotfixup;
+ /* A pointer to the .plt section. */
+ asection *splt;
+ /* A pointer to the .rel.plt section. */
+ asection *spltrel;
+ /* GOT base offset. */
+ bfd_vma got0;
+ /* Location of the first non-lazy PLT entry, i.e., the number of
+ bytes taken by lazy PLT entries. */
+ bfd_vma plt0;
+ /* A hash table holding information about which symbols were
+ referenced with which PIC-related relocations. */
+ struct htab *relocs_info;
+};
+
+/* Get the Blackfin ELF linker hash table from a link_info structure. */
+
+#define bfinfdpic_hash_table(info) \
+ ((struct bfinfdpic_elf_link_hash_table *) ((info)->hash))
+
+#define bfinfdpic_got_section(info) \
+ (bfinfdpic_hash_table (info)->sgot)
+#define bfinfdpic_gotrel_section(info) \
+ (bfinfdpic_hash_table (info)->sgotrel)
+#define bfinfdpic_gotfixup_section(info) \
+ (bfinfdpic_hash_table (info)->sgotfixup)
+#define bfinfdpic_plt_section(info) \
+ (bfinfdpic_hash_table (info)->splt)
+#define bfinfdpic_pltrel_section(info) \
+ (bfinfdpic_hash_table (info)->spltrel)
+#define bfinfdpic_relocs_info(info) \
+ (bfinfdpic_hash_table (info)->relocs_info)
+#define bfinfdpic_got_initial_offset(info) \
+ (bfinfdpic_hash_table (info)->got0)
+#define bfinfdpic_plt_initial_offset(info) \
+ (bfinfdpic_hash_table (info)->plt0)
+
+/* Create a Blackfin ELF linker hash table. */
+
+static struct bfd_link_hash_table *
+bfinfdpic_elf_link_hash_table_create (bfd *abfd)
+{
+ struct bfinfdpic_elf_link_hash_table *ret;
+ bfd_size_type amt = sizeof (struct bfinfdpic_elf_link_hash_table);
+
+ ret = bfd_zalloc (abfd, amt);
+ if (ret == NULL)
+ return NULL;
+
+ if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd,
+ _bfd_elf_link_hash_newfunc,
+ sizeof (struct elf_link_hash_entry)))
+ {
+ free (ret);
+ return NULL;
+ }
+
+ return &ret->elf.root;
+}
+
+/* Decide whether a reference to a symbol can be resolved locally or
+ not. If the symbol is protected, we want the local address, but
+ its function descriptor must be assigned by the dynamic linker. */
+#define BFINFDPIC_SYM_LOCAL(INFO, H) \
+ (_bfd_elf_symbol_refs_local_p ((H), (INFO), 1) \
+ || ! elf_hash_table (INFO)->dynamic_sections_created)
+#define BFINFDPIC_FUNCDESC_LOCAL(INFO, H) \
+ ((H)->dynindx == -1 || ! elf_hash_table (INFO)->dynamic_sections_created)
+
+/* This structure collects information on what kind of GOT, PLT or
+ function descriptors are required by relocations that reference a
+ certain symbol. */
+struct bfinfdpic_relocs_info
+{
+ /* The index of the symbol, as stored in the relocation r_info, if
+ we have a local symbol; -1 otherwise. */
+ long symndx;
+ union
+ {
+ /* The input bfd in which the symbol is defined, if it's a local
+ symbol. */
+ bfd *abfd;
+ /* If symndx == -1, the hash table entry corresponding to a global
+ symbol (even if it turns out to bind locally, in which case it
+ should ideally be replaced with section's symndx + addend). */
+ struct elf_link_hash_entry *h;
+ } d;
+ /* The addend of the relocation that references the symbol. */
+ bfd_vma addend;
+
+ /* The fields above are used to identify an entry. The fields below
+ contain information on how an entry is used and, later on, which
+ locations it was assigned. */
+ /* The following 2 fields record whether the symbol+addend above was
+ ever referenced with a GOT relocation. The 17M4 suffix indicates a
+ GOT17M4 relocation; hilo is used for GOTLO/GOTHI pairs. */
+ unsigned got17m4:1;
+ unsigned gothilo:1;
+ /* Whether a FUNCDESC relocation references symbol+addend. */
+ unsigned fd:1;
+ /* Whether a FUNCDESC_GOT relocation references symbol+addend. */
+ unsigned fdgot17m4:1;
+ unsigned fdgothilo:1;
+ /* Whether a FUNCDESC_GOTOFF relocation references symbol+addend. */
+ unsigned fdgoff17m4:1;
+ unsigned fdgoffhilo:1;
+ /* Whether symbol+addend is referenced with GOTOFF17M4, GOTOFFLO or
+ GOTOFFHI relocations. The addend doesn't really matter, since we
+ envision that this will only be used to check whether the symbol
+ is mapped to the same segment as the got. */
+ unsigned gotoff:1;
+ /* Whether symbol+addend is referenced by a LABEL24 relocation. */
+ unsigned call:1;
+ /* Whether symbol+addend is referenced by a 32 or FUNCDESC_VALUE
+ relocation. */
+ unsigned sym:1;
+ /* Whether we need a PLT entry for a symbol. Should be implied by
+ something like:
+ (call && symndx == -1 && ! BFINFDPIC_SYM_LOCAL (info, d.h)) */
+ unsigned plt:1;
+ /* Whether a function descriptor should be created in this link unit
+ for symbol+addend. Should be implied by something like:
+ (plt || fdgotoff17m4 || fdgotofflohi
+ || ((fd || fdgot17m4 || fdgothilo)
+ && (symndx != -1 || BFINFDPIC_FUNCDESC_LOCAL (info, d.h)))) */
+ unsigned privfd:1;
+ /* Whether a lazy PLT entry is needed for this symbol+addend.
+ Should be implied by something like:
+ (privfd && symndx == -1 && ! BFINFDPIC_SYM_LOCAL (info, d.h)
+ && ! (info->flags & DF_BIND_NOW)) */
+ unsigned lazyplt:1;
+ /* Whether we've already emitted GOT relocations and PLT entries as
+ needed for this symbol. */
+ unsigned done:1;
+
+ /* The number of R_byte4_data, R_BFIN_FUNCDESC and R_BFIN_FUNCDESC_VALUE
+ relocations referencing the symbol. */
+ unsigned relocs32, relocsfd, relocsfdv;
+
+ /* The number of .rofixups entries and dynamic relocations allocated
+ for this symbol, minus any that might have already been used. */
+ unsigned fixups, dynrelocs;
+
+ /* The offsets of the GOT entries assigned to symbol+addend, to the
+ function descriptor's address, and to a function descriptor,
+ respectively. Should be zero if unassigned. The offsets are
+ counted from the value that will be assigned to the PIC register,
+ not from the beginning of the .got section. */
+ bfd_signed_vma got_entry, fdgot_entry, fd_entry;
+ /* The offsets of the PLT entries assigned to symbol+addend,
+ non-lazy and lazy, respectively. If unassigned, should be
+ (bfd_vma)-1. */
+ bfd_vma plt_entry, lzplt_entry;
+};
+
+/* Compute a hash with the key fields of an bfinfdpic_relocs_info entry. */
+static hashval_t
+bfinfdpic_relocs_info_hash (const void *entry_)
+{
+ const struct bfinfdpic_relocs_info *entry = entry_;
+
+ return (entry->symndx == -1
+ ? entry->d.h->root.root.hash
+ : entry->symndx + entry->d.abfd->id * 257) + entry->addend;
+}
+
+/* Test whether the key fields of two bfinfdpic_relocs_info entries are
+ identical. */
+static int
+bfinfdpic_relocs_info_eq (const void *entry1, const void *entry2)
+{
+ const struct bfinfdpic_relocs_info *e1 = entry1;
+ const struct bfinfdpic_relocs_info *e2 = entry2;
+
+ return e1->symndx == e2->symndx && e1->addend == e2->addend
+ && (e1->symndx == -1 ? e1->d.h == e2->d.h : e1->d.abfd == e2->d.abfd);
+}
+
+/* Find or create an entry in a hash table HT that matches the key
+ fields of the given ENTRY. If it's not found, memory for a new
+ entry is allocated in ABFD's obstack. */
+static struct bfinfdpic_relocs_info *
+bfinfdpic_relocs_info_find (struct htab *ht,
+ bfd *abfd,
+ const struct bfinfdpic_relocs_info *entry,
+ enum insert_option insert)
+{
+ struct bfinfdpic_relocs_info **loc =
+ (struct bfinfdpic_relocs_info **) htab_find_slot (ht, entry, insert);
+
+ if (! loc)
+ return NULL;
+
+ if (*loc)
+ return *loc;
+
+ *loc = bfd_zalloc (abfd, sizeof (**loc));
+
+ if (! *loc)
+ return *loc;
+
+ (*loc)->symndx = entry->symndx;
+ (*loc)->d = entry->d;
+ (*loc)->addend = entry->addend;
+ (*loc)->plt_entry = (bfd_vma)-1;
+ (*loc)->lzplt_entry = (bfd_vma)-1;
+
+ return *loc;
+}
+
+/* Obtain the address of the entry in HT associated with H's symbol +
+ addend, creating a new entry if none existed. ABFD is only used
+ for memory allocation purposes. */
+inline static struct bfinfdpic_relocs_info *
+bfinfdpic_relocs_info_for_global (struct htab *ht,
+ bfd *abfd,
+ struct elf_link_hash_entry *h,
+ bfd_vma addend,
+ enum insert_option insert)
+{
+ struct bfinfdpic_relocs_info entry;
+
+ entry.symndx = -1;
+ entry.d.h = h;
+ entry.addend = addend;
+
+ return bfinfdpic_relocs_info_find (ht, abfd, &entry, insert);
+}
+
+/* Obtain the address of the entry in HT associated with the SYMNDXth
+ local symbol of the input bfd ABFD, plus the addend, creating a new
+ entry if none existed. */
+inline static struct bfinfdpic_relocs_info *
+bfinfdpic_relocs_info_for_local (struct htab *ht,
+ bfd *abfd,
+ long symndx,
+ bfd_vma addend,
+ enum insert_option insert)
+{
+ struct bfinfdpic_relocs_info entry;
+
+ entry.symndx = symndx;
+ entry.d.abfd = abfd;
+ entry.addend = addend;
+
+ return bfinfdpic_relocs_info_find (ht, abfd, &entry, insert);
+}
+
+/* Merge fields set by check_relocs() of two entries that end up being
+ mapped to the same (presumably global) symbol. */
+
+inline static void
+bfinfdpic_pic_merge_early_relocs_info (struct bfinfdpic_relocs_info *e2,
+ struct bfinfdpic_relocs_info const *e1)
+{
+ e2->got17m4 |= e1->got17m4;
+ e2->gothilo |= e1->gothilo;
+ e2->fd |= e1->fd;
+ e2->fdgot17m4 |= e1->fdgot17m4;
+ e2->fdgothilo |= e1->fdgothilo;
+ e2->fdgoff17m4 |= e1->fdgoff17m4;
+ e2->fdgoffhilo |= e1->fdgoffhilo;
+ e2->gotoff |= e1->gotoff;
+ e2->call |= e1->call;
+ e2->sym |= e1->sym;
+}
+
+/* Every block of 65535 lazy PLT entries shares a single call to the
+ resolver, inserted in the 32768th lazy PLT entry (i.e., entry #
+ 32767, counting from 0). All other lazy PLT entries branch to it
+ in a single instruction. */
+
+#define LZPLT_RESOLVER_EXTRA 10
+#define LZPLT_NORMAL_SIZE 6
+#define LZPLT_ENTRIES 1362
+
+#define BFINFDPIC_LZPLT_BLOCK_SIZE ((bfd_vma) LZPLT_NORMAL_SIZE * LZPLT_ENTRIES + LZPLT_RESOLVER_EXTRA)
+#define BFINFDPIC_LZPLT_RESOLV_LOC (LZPLT_NORMAL_SIZE * LZPLT_ENTRIES / 2)
+
+/* Add a dynamic relocation to the SRELOC section. */
+
+inline static bfd_vma
+_bfinfdpic_add_dyn_reloc (bfd *output_bfd, asection *sreloc, bfd_vma offset,
+ int reloc_type, long dynindx, bfd_vma addend,
+ struct bfinfdpic_relocs_info *entry)
+{
+ Elf_Internal_Rela outrel;
+ bfd_vma reloc_offset;
+
+ outrel.r_offset = offset;
+ outrel.r_info = ELF32_R_INFO (dynindx, reloc_type);
+ outrel.r_addend = addend;
+
+ reloc_offset = sreloc->reloc_count * sizeof (Elf32_External_Rel);
+ BFD_ASSERT (reloc_offset < sreloc->size);
+ bfd_elf32_swap_reloc_out (output_bfd, &outrel,
+ sreloc->contents + reloc_offset);
+ sreloc->reloc_count++;
+
+ /* If the entry's index is zero, this relocation was probably to a
+ linkonce section that got discarded. We reserved a dynamic
+ relocation, but it was for another entry than the one we got at
+ the time of emitting the relocation. Unfortunately there's no
+ simple way for us to catch this situation, since the relocation
+ is cleared right before calling relocate_section, at which point
+ we no longer know what the relocation used to point to. */
+ if (entry->symndx)
+ {
+ BFD_ASSERT (entry->dynrelocs > 0);
+ entry->dynrelocs--;
+ }
+
+ return reloc_offset;
+}
+
+/* Add a fixup to the ROFIXUP section. */
+
+static bfd_vma
+_bfinfdpic_add_rofixup (bfd *output_bfd, asection *rofixup, bfd_vma offset,
+ struct bfinfdpic_relocs_info *entry)
+{
+ bfd_vma fixup_offset;
+
+ if (rofixup->flags & SEC_EXCLUDE)
+ return -1;
+
+ fixup_offset = rofixup->reloc_count * 4;
+ if (rofixup->contents)
+ {
+ BFD_ASSERT (fixup_offset < rofixup->size);
+ bfd_put_32 (output_bfd, offset, rofixup->contents + fixup_offset);
+ }
+ rofixup->reloc_count++;
+
+ if (entry && entry->symndx)
+ {
+ /* See discussion about symndx == 0 in _bfinfdpic_add_dyn_reloc
+ above. */
+ BFD_ASSERT (entry->fixups > 0);
+ entry->fixups--;
+ }
+
+ return fixup_offset;
+}
+
+/* Find the segment number in which OSEC, and output section, is
+ located. */
+
+static unsigned
+_bfinfdpic_osec_to_segment (bfd *output_bfd, asection *osec)
+{
+ struct elf_segment_map *m;
+ Elf_Internal_Phdr *p;
+
+ /* Find the segment that contains the output_section. */
+ for (m = elf_tdata (output_bfd)->segment_map,
+ p = elf_tdata (output_bfd)->phdr;
+ m != NULL;
+ m = m->next, p++)
+ {
+ int i;
+
+ for (i = m->count - 1; i >= 0; i--)
+ if (m->sections[i] == osec)
+ break;
+
+ if (i >= 0)
+ break;
+ }
+
+ return p - elf_tdata (output_bfd)->phdr;
+}
+
+inline static bfd_boolean
+_bfinfdpic_osec_readonly_p (bfd *output_bfd, asection *osec)
+{
+ unsigned seg = _bfinfdpic_osec_to_segment (output_bfd, osec);
+
+ return ! (elf_tdata (output_bfd)->phdr[seg].p_flags & PF_W);
+}
+
+/* Generate relocations for GOT entries, function descriptors, and
+ code for PLT and lazy PLT entries. */
+
+inline static bfd_boolean
+_bfinfdpic_emit_got_relocs_plt_entries (struct bfinfdpic_relocs_info *entry,
+ bfd *output_bfd,
+ struct bfd_link_info *info,
+ asection *sec,
+ Elf_Internal_Sym *sym,
+ bfd_vma addend)
+
+{
+ bfd_vma fd_lazy_rel_offset = (bfd_vma)-1;
+ int dynindx = -1;
+
+ if (entry->done)
+ return TRUE;
+ entry->done = 1;
+
+ if (entry->got_entry || entry->fdgot_entry || entry->fd_entry)
+ {
+ /* If the symbol is dynamic, consider it for dynamic
+ relocations, otherwise decay to section + offset. */
+ if (entry->symndx == -1 && entry->d.h->dynindx != -1)
+ dynindx = entry->d.h->dynindx;
+ else
+ {
+ if (sec->output_section
+ && ! bfd_is_abs_section (sec->output_section)
+ && ! bfd_is_und_section (sec->output_section))
+ dynindx = elf_section_data (sec->output_section)->dynindx;
+ else
+ dynindx = 0;
+ }
+ }
+
+ /* Generate relocation for GOT entry pointing to the symbol. */
+ if (entry->got_entry)
+ {
+ int idx = dynindx;
+ bfd_vma ad = addend;
+
+ /* If the symbol is dynamic but binds locally, use
+ section+offset. */
+ if (sec && (entry->symndx != -1
+ || BFINFDPIC_SYM_LOCAL (info, entry->d.h)))
+ {
+ if (entry->symndx == -1)
+ ad += entry->d.h->root.u.def.value;
+ else
+ ad += sym->st_value;
+ ad += sec->output_offset;
+ if (sec->output_section && elf_section_data (sec->output_section))
+ idx = elf_section_data (sec->output_section)->dynindx;
+ else
+ idx = 0;
+ }
+
+ /* If we're linking an executable at a fixed address, we can
+ omit the dynamic relocation as long as the symbol is local to
+ this module. */
+ if (info->executable && !info->pie
+ && (entry->symndx != -1
+ || BFINFDPIC_SYM_LOCAL (info, entry->d.h)))
+ {
+ if (sec)
+ ad += sec->output_section->vma;
+ if (entry->symndx != -1
+ || entry->d.h->root.type != bfd_link_hash_undefweak)
+ _bfinfdpic_add_rofixup (output_bfd,
+ bfinfdpic_gotfixup_section (info),
+ bfinfdpic_got_section (info)->output_section
+ ->vma
+ + bfinfdpic_got_section (info)->output_offset
+ + bfinfdpic_got_initial_offset (info)
+ + entry->got_entry, entry);
+ }
+ else
+ _bfinfdpic_add_dyn_reloc (output_bfd, bfinfdpic_gotrel_section (info),
+ _bfd_elf_section_offset
+ (output_bfd, info,
+ bfinfdpic_got_section (info),
+ bfinfdpic_got_initial_offset (info)
+ + entry->got_entry)
+ + bfinfdpic_got_section (info)
+ ->output_section->vma
+ + bfinfdpic_got_section (info)->output_offset,
+ R_byte4_data, idx, ad, entry);
+
+ bfd_put_32 (output_bfd, ad,
+ bfinfdpic_got_section (info)->contents
+ + bfinfdpic_got_initial_offset (info)
+ + entry->got_entry);
+ }
+
+ /* Generate relocation for GOT entry pointing to a canonical
+ function descriptor. */
+ if (entry->fdgot_entry)
+ {
+ int reloc, idx;
+ bfd_vma ad = 0;
+
+ if (! (entry->symndx == -1
+ && entry->d.h->root.type == bfd_link_hash_undefweak
+ && BFINFDPIC_SYM_LOCAL (info, entry->d.h)))
+ {
+ /* If the symbol is dynamic and there may be dynamic symbol
+ resolution because we are, or are linked with, a shared
+ library, emit a FUNCDESC relocation such that the dynamic
+ linker will allocate the function descriptor. If the
+ symbol needs a non-local function descriptor but binds
+ locally (e.g., its visibility is protected, emit a
+ dynamic relocation decayed to section+offset. */
+ if (entry->symndx == -1
+ && ! BFINFDPIC_FUNCDESC_LOCAL (info, entry->d.h)
+ && BFINFDPIC_SYM_LOCAL (info, entry->d.h)
+ && !(info->executable && !info->pie))
+ {
+ reloc = R_BFIN_FUNCDESC;
+ idx = elf_section_data (entry->d.h->root.u.def.section
+ ->output_section)->dynindx;
+ ad = entry->d.h->root.u.def.section->output_offset
+ + entry->d.h->root.u.def.value;
+ }
+ else if (entry->symndx == -1
+ && ! BFINFDPIC_FUNCDESC_LOCAL (info, entry->d.h))
+ {
+ reloc = R_BFIN_FUNCDESC;
+ idx = dynindx;
+ ad = addend;
+ if (ad)
+ return FALSE;
+ }
+ else
+ {
+ /* Otherwise, we know we have a private function descriptor,
+ so reference it directly. */
+ if (elf_hash_table (info)->dynamic_sections_created)
+ BFD_ASSERT (entry->privfd);
+ reloc = R_byte4_data;
+ idx = elf_section_data (bfinfdpic_got_section (info)
+ ->output_section)->dynindx;
+ ad = bfinfdpic_got_section (info)->output_offset
+ + bfinfdpic_got_initial_offset (info) + entry->fd_entry;
+ }
+
+ /* If there is room for dynamic symbol resolution, emit the
+ dynamic relocation. However, if we're linking an
+ executable at a fixed location, we won't have emitted a
+ dynamic symbol entry for the got section, so idx will be
+ zero, which means we can and should compute the address
+ of the private descriptor ourselves. */
+ if (info->executable && !info->pie
+ && (entry->symndx != -1
+ || BFINFDPIC_FUNCDESC_LOCAL (info, entry->d.h)))
+ {
+ ad += bfinfdpic_got_section (info)->output_section->vma;
+ _bfinfdpic_add_rofixup (output_bfd,
+ bfinfdpic_gotfixup_section (info),
+ bfinfdpic_got_section (info)
+ ->output_section->vma
+ + bfinfdpic_got_section (info)
+ ->output_offset
+ + bfinfdpic_got_initial_offset (info)
+ + entry->fdgot_entry, entry);
+ }
+ else
+ _bfinfdpic_add_dyn_reloc (output_bfd,
+ bfinfdpic_gotrel_section (info),
+ _bfd_elf_section_offset
+ (output_bfd, info,
+ bfinfdpic_got_section (info),
+ bfinfdpic_got_initial_offset (info)
+ + entry->fdgot_entry)
+ + bfinfdpic_got_section (info)
+ ->output_section->vma
+ + bfinfdpic_got_section (info)
+ ->output_offset,
+ reloc, idx, ad, entry);
+ }
+
+ bfd_put_32 (output_bfd, ad,
+ bfinfdpic_got_section (info)->contents
+ + bfinfdpic_got_initial_offset (info)
+ + entry->fdgot_entry);
+ }
+
+ /* Generate relocation to fill in a private function descriptor in
+ the GOT. */
+ if (entry->fd_entry)
+ {
+ int idx = dynindx;
+ bfd_vma ad = addend;
+ bfd_vma ofst;
+ long lowword, highword;
+
+ /* If the symbol is dynamic but binds locally, use
+ section+offset. */
+ if (sec && (entry->symndx != -1
+ || BFINFDPIC_SYM_LOCAL (info, entry->d.h)))
+ {
+ if (entry->symndx == -1)
+ ad += entry->d.h->root.u.def.value;
+ else
+ ad += sym->st_value;
+ ad += sec->output_offset;
+ if (sec->output_section && elf_section_data (sec->output_section))
+ idx = elf_section_data (sec->output_section)->dynindx;
+ else
+ idx = 0;
+ }
+
+ /* If we're linking an executable at a fixed address, we can
+ omit the dynamic relocation as long as the symbol is local to
+ this module. */
+ if (info->executable && !info->pie
+ && (entry->symndx != -1 || BFINFDPIC_SYM_LOCAL (info, entry->d.h)))
+ {
+ if (sec)
+ ad += sec->output_section->vma;
+ ofst = 0;
+ if (entry->symndx != -1
+ || entry->d.h->root.type != bfd_link_hash_undefweak)
+ {
+ _bfinfdpic_add_rofixup (output_bfd,
+ bfinfdpic_gotfixup_section (info),
+ bfinfdpic_got_section (info)
+ ->output_section->vma
+ + bfinfdpic_got_section (info)
+ ->output_offset
+ + bfinfdpic_got_initial_offset (info)
+ + entry->fd_entry, entry);
+ _bfinfdpic_add_rofixup (output_bfd,
+ bfinfdpic_gotfixup_section (info),
+ bfinfdpic_got_section (info)
+ ->output_section->vma
+ + bfinfdpic_got_section (info)
+ ->output_offset
+ + bfinfdpic_got_initial_offset (info)
+ + entry->fd_entry + 4, entry);
+ }
+ }
+ else
+ {
+ ofst
+ = _bfinfdpic_add_dyn_reloc (output_bfd,
+ entry->lazyplt
+ ? bfinfdpic_pltrel_section (info)
+ : bfinfdpic_gotrel_section (info),
+ _bfd_elf_section_offset
+ (output_bfd, info,
+ bfinfdpic_got_section (info),
+ bfinfdpic_got_initial_offset (info)
+ + entry->fd_entry)
+ + bfinfdpic_got_section (info)
+ ->output_section->vma
+ + bfinfdpic_got_section (info)
+ ->output_offset,
+ R_BFIN_FUNCDESC_VALUE, idx, ad, entry);
+ }
+
+ /* If we've omitted the dynamic relocation, just emit the fixed
+ addresses of the symbol and of the local GOT base offset. */
+ if (info->executable && !info->pie && sec && sec->output_section)
+ {
+ lowword = ad;
+ highword = bfinfdpic_got_section (info)->output_section->vma
+ + bfinfdpic_got_section (info)->output_offset
+ + bfinfdpic_got_initial_offset (info);
+ }
+ else if (entry->lazyplt)
+ {
+ if (ad)
+ return FALSE;
+
+ fd_lazy_rel_offset = ofst;
+
+ /* A function descriptor used for lazy or local resolving is
+ initialized such that its high word contains the output
+ section index in which the PLT entries are located, and
+ the low word contains the address of the lazy PLT entry
+ entry point, that must be within the memory region
+ assigned to that section. */
+ lowword = entry->lzplt_entry + 4
+ + bfinfdpic_plt_section (info)->output_offset
+ + bfinfdpic_plt_section (info)->output_section->vma;
+ highword = _bfinfdpic_osec_to_segment
+ (output_bfd, bfinfdpic_plt_section (info)->output_section);
+ }
+ else
+ {
+ /* A function descriptor for a local function gets the index
+ of the section. For a non-local function, it's
+ disregarded. */
+ lowword = ad;
+ if (entry->symndx == -1 && entry->d.h->dynindx != -1
+ && entry->d.h->dynindx == idx)
+ highword = 0;
+ else
+ highword = _bfinfdpic_osec_to_segment
+ (output_bfd, sec->output_section);
+ }
+
+ bfd_put_32 (output_bfd, lowword,
+ bfinfdpic_got_section (info)->contents
+ + bfinfdpic_got_initial_offset (info)
+ + entry->fd_entry);
+ bfd_put_32 (output_bfd, highword,
+ bfinfdpic_got_section (info)->contents
+ + bfinfdpic_got_initial_offset (info)
+ + entry->fd_entry + 4);
+ }
+
+ /* Generate code for the PLT entry. */
+ if (entry->plt_entry != (bfd_vma) -1)
+ {
+ bfd_byte *plt_code = bfinfdpic_plt_section (info)->contents
+ + entry->plt_entry;
+
+ BFD_ASSERT (entry->fd_entry);
+
+ /* Figure out what kind of PLT entry we need, depending on the
+ location of the function descriptor within the GOT. */
+ if (entry->fd_entry >= -(1 << (18 - 1))
+ && entry->fd_entry + 4 < (1 << (18 - 1)))
+ {
+ /* P1 = [P3 + fd_entry]; P3 = [P3 + fd_entry + 4] */
+ bfd_put_32 (output_bfd,
+ 0xe519 | ((entry->fd_entry << 14) & 0xFFFF0000),
+ plt_code);
+ bfd_put_32 (output_bfd,
+ 0xe51b | (((entry->fd_entry + 4) << 14) & 0xFFFF0000),
+ plt_code + 4);
+ plt_code += 8;
+ }
+ else
+ {
+ /* P1.L = fd_entry; P1.H = fd_entry;
+ P3 = P3 + P1;
+ P1 = [P3];
+ P3 = [P3 + 4]; */
+ bfd_put_32 (output_bfd,
+ 0xe109 | (entry->fd_entry << 16),
+ plt_code);
+ bfd_put_32 (output_bfd,
+ 0xe149 | (entry->fd_entry & 0xFFFF0000),
+ plt_code + 4);
+ bfd_put_16 (output_bfd, 0x5ad9, plt_code + 8);
+ bfd_put_16 (output_bfd, 0x9159, plt_code + 10);
+ bfd_put_16 (output_bfd, 0xac5b, plt_code + 12);
+ plt_code += 14;
+ }
+ /* JUMP (P1) */
+ bfd_put_16 (output_bfd, 0x0051, plt_code);
+ }
+
+ /* Generate code for the lazy PLT entry. */
+ if (entry->lzplt_entry != (bfd_vma) -1)
+ {
+ bfd_byte *lzplt_code = bfinfdpic_plt_section (info)->contents
+ + entry->lzplt_entry;
+ bfd_vma resolverStub_addr;
+
+ bfd_put_32 (output_bfd, fd_lazy_rel_offset, lzplt_code);
+ lzplt_code += 4;
+
+ resolverStub_addr = entry->lzplt_entry / BFINFDPIC_LZPLT_BLOCK_SIZE
+ * BFINFDPIC_LZPLT_BLOCK_SIZE + BFINFDPIC_LZPLT_RESOLV_LOC;
+ if (resolverStub_addr >= bfinfdpic_plt_initial_offset (info))
+ resolverStub_addr = bfinfdpic_plt_initial_offset (info) - LZPLT_NORMAL_SIZE - LZPLT_RESOLVER_EXTRA;
+
+ if (entry->lzplt_entry == resolverStub_addr)
+ {
+ /* This is a lazy PLT entry that includes a resolver call.
+ P2 = [P3];
+ R3 = [P3 + 4];
+ JUMP (P2); */
+ bfd_put_32 (output_bfd,
+ 0xa05b915a,
+ lzplt_code);
+ bfd_put_16 (output_bfd, 0x0052, lzplt_code + 4);
+ }
+ else
+ {
+ /* JUMP.S resolverStub */
+ bfd_put_16 (output_bfd,
+ 0x2000
+ | (((resolverStub_addr - entry->lzplt_entry)
+ / 2) & (((bfd_vma)1 << 12) - 1)),
+ lzplt_code);
+ }
+ }
+
+ return TRUE;
+}
+
/* Look through the relocs for a section during the first phase, and
allocate space in the global offset table or procedure linkage
@@ -1656,6 +2063,746 @@ elf32_bfin_reloc_type_class (const Elf_Internal_Rela * rela)
return reloc_class_normal;
}
}
+
+/* Relocate an Blackfin ELF section.
+
+ The RELOCATE_SECTION function is called by the new ELF backend linker
+ to handle the relocations for a section.
+
+ The relocs are always passed as Rela structures; if the section
+ actually uses Rel structures, the r_addend field will always be
+ zero.
+
+ This function 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.
+
+ This function does not have to worry about setting the reloc
+ address or the reloc symbol index.
+
+ LOCAL_SYMS is a pointer to the swapped in local symbols.
+
+ LOCAL_SECTIONS is an array giving the section in the input file
+ corresponding to the st_shndx field of each local symbol.
+
+ The global hash table entry for the global symbols can be found
+ via elf_sym_hashes (input_bfd).
+
+ When generating relocatable output, this function must handle
+ STB_LOCAL/STT_SECTION symbols specially. The output symbol is
+ going to be the section symbol corresponding to the output
+ section, which means that the addend must be adjusted
+ accordingly. */
+
+static bfd_boolean
+bfinfdpic_relocate_section (bfd * output_bfd,
+ struct bfd_link_info *info,
+ bfd * input_bfd,
+ asection * input_section,
+ bfd_byte * contents,
+ Elf_Internal_Rela * relocs,
+ Elf_Internal_Sym * local_syms,
+ asection ** local_sections)
+{
+ Elf_Internal_Shdr *symtab_hdr;
+ struct elf_link_hash_entry **sym_hashes;
+ Elf_Internal_Rela *rel;
+ Elf_Internal_Rela *relend;
+ unsigned isec_segment, got_segment, plt_segment,
+ check_segment[2];
+ int silence_segment_error = !(info->shared || info->pie);
+
+ if (info->relocatable)
+ return TRUE;
+
+ symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
+ sym_hashes = elf_sym_hashes (input_bfd);
+ relend = relocs + input_section->reloc_count;
+
+ isec_segment = _bfinfdpic_osec_to_segment (output_bfd,
+ input_section->output_section);
+ if (IS_FDPIC (output_bfd) && bfinfdpic_got_section (info))
+ got_segment = _bfinfdpic_osec_to_segment (output_bfd,
+ bfinfdpic_got_section (info)
+ ->output_section);
+ else
+ got_segment = -1;
+ if (IS_FDPIC (output_bfd) && elf_hash_table (info)->dynamic_sections_created)
+ plt_segment = _bfinfdpic_osec_to_segment (output_bfd,
+ bfinfdpic_plt_section (info)
+ ->output_section);
+ else
+ plt_segment = -1;
+
+ for (rel = relocs; rel < relend; rel ++)
+ {
+ reloc_howto_type *howto;
+ unsigned long r_symndx;
+ Elf_Internal_Sym *sym;
+ asection *sec;
+ struct elf_link_hash_entry *h;
+ bfd_vma relocation;
+ bfd_reloc_status_type r;
+ const char * name = NULL;
+ int r_type;
+ asection *osec;
+ struct bfinfdpic_relocs_info *picrel;
+ bfd_vma orig_addend = rel->r_addend;
+
+ r_type = ELF32_R_TYPE (rel->r_info);
+
+ if (r_type == R_BFIN_GNU_VTINHERIT
+ || r_type == R_BFIN_GNU_VTENTRY)
+ continue;
+
+ /* This is a final link. */
+ r_symndx = ELF32_R_SYM (rel->r_info);
+ howto = bfin_reloc_type_lookup (input_bfd, r_type);
+ if (howto == NULL)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
+
+ h = NULL;
+ sym = NULL;
+ sec = NULL;
+
+ if (r_symndx < symtab_hdr->sh_info)
+ {
+ sym = local_syms + r_symndx;
+ osec = 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;
+ }
+ else
+ {
+ 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;
+
+ name = h->root.root.string;
+
+ if ((h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && ! BFINFDPIC_SYM_LOCAL (info, h))
+ {
+ sec = NULL;
+ relocation = 0;
+ }
+ else
+ 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->unresolved_syms_in_objects == RM_IGNORE
+ && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
+ relocation = 0;
+ else
+ {
+ if (! ((*info->callbacks->undefined_symbol)
+ (info, h->root.root.string, input_bfd,
+ input_section, rel->r_offset,
+ (info->unresolved_syms_in_objects == RM_GENERATE_ERROR
+ || ELF_ST_VISIBILITY (h->other)))))
+ return FALSE;
+ relocation = 0;
+ }
+ osec = sec;
+ }
+
+ switch (r_type)
+ {
+ case R_pcrel24:
+ case R_pcrel24_jump_l:
+ case R_byte4_data:
+ if (! IS_FDPIC (output_bfd))
+ goto non_fdpic;
+
+ case R_BFIN_GOT17M4:
+ case R_BFIN_GOTHI:
+ case R_BFIN_GOTLO:
+ case R_BFIN_FUNCDESC_GOT17M4:
+ case R_BFIN_FUNCDESC_GOTHI:
+ case R_BFIN_FUNCDESC_GOTLO:
+ case R_BFIN_GOTOFF17M4:
+ case R_BFIN_GOTOFFHI:
+ case R_BFIN_GOTOFFLO:
+ case R_BFIN_FUNCDESC_GOTOFF17M4:
+ case R_BFIN_FUNCDESC_GOTOFFHI:
+ case R_BFIN_FUNCDESC_GOTOFFLO:
+ case R_BFIN_FUNCDESC:
+ case R_BFIN_FUNCDESC_VALUE:
+ if (h != NULL)
+ picrel = bfinfdpic_relocs_info_for_global (bfinfdpic_relocs_info
+ (info), input_bfd, h,
+ orig_addend, INSERT);
+ else
+ /* In order to find the entry we created before, we must
+ use the original addend, not the one that may have been
+ modified by _bfd_elf_rela_local_sym(). */
+ picrel = bfinfdpic_relocs_info_for_local (bfinfdpic_relocs_info
+ (info), input_bfd, r_symndx,
+ orig_addend, INSERT);
+ if (! picrel)
+ return FALSE;
+
+ if (!_bfinfdpic_emit_got_relocs_plt_entries (picrel, output_bfd, info,
+ osec, sym,
+ rel->r_addend))
+ {
+ (*_bfd_error_handler)
+ (_("%B: relocation at `%A+0x%x' references symbol `%s' with nonzero addend"),
+ input_bfd, input_section, rel->r_offset, name);
+ return FALSE;
+
+ }
+
+ break;
+
+ default:
+ non_fdpic:
+ picrel = NULL;
+ if (h && ! BFINFDPIC_SYM_LOCAL (info, h))
+ {
+ info->callbacks->warning
+ (info, _("relocation references symbol not defined in the module"),
+ name, input_bfd, input_section, rel->r_offset);
+ return FALSE;
+ }
+ break;
+ }
+
+ switch (r_type)
+ {
+ case R_pcrel24:
+ case R_pcrel24_jump_l:
+ check_segment[0] = isec_segment;
+ if (! IS_FDPIC (output_bfd))
+ check_segment[1] = isec_segment;
+ else if (picrel->plt)
+ {
+ relocation = bfinfdpic_plt_section (info)->output_section->vma
+ + bfinfdpic_plt_section (info)->output_offset
+ + picrel->plt_entry;
+ check_segment[1] = plt_segment;
+ }
+ /* We don't want to warn on calls to undefined weak symbols,
+ as calls to them must be protected by non-NULL tests
+ anyway, and unprotected calls would invoke undefined
+ behavior. */
+ else if (picrel->symndx == -1
+ && picrel->d.h->root.type == bfd_link_hash_undefweak)
+ check_segment[1] = check_segment[0];
+ else
+ check_segment[1] = sec
+ ? _bfinfdpic_osec_to_segment (output_bfd, sec->output_section)
+ : (unsigned)-1;
+ break;
+
+ case R_BFIN_GOT17M4:
+ case R_BFIN_GOTHI:
+ case R_BFIN_GOTLO:
+ relocation = picrel->got_entry;
+ check_segment[0] = check_segment[1] = got_segment;
+ break;
+
+ case R_BFIN_FUNCDESC_GOT17M4:
+ case R_BFIN_FUNCDESC_GOTHI:
+ case R_BFIN_FUNCDESC_GOTLO:
+ relocation = picrel->fdgot_entry;
+ check_segment[0] = check_segment[1] = got_segment;
+ break;
+
+ case R_BFIN_GOTOFFHI:
+ case R_BFIN_GOTOFF17M4:
+ case R_BFIN_GOTOFFLO:
+ relocation -= bfinfdpic_got_section (info)->output_section->vma
+ + bfinfdpic_got_section (info)->output_offset
+ + bfinfdpic_got_initial_offset (info);
+ check_segment[0] = got_segment;
+ check_segment[1] = sec
+ ? _bfinfdpic_osec_to_segment (output_bfd, sec->output_section)
+ : (unsigned)-1;
+ break;
+
+ case R_BFIN_FUNCDESC_GOTOFF17M4:
+ case R_BFIN_FUNCDESC_GOTOFFHI:
+ case R_BFIN_FUNCDESC_GOTOFFLO:
+ relocation = picrel->fd_entry;
+ check_segment[0] = check_segment[1] = got_segment;
+ break;
+
+ case R_BFIN_FUNCDESC:
+ {
+ int dynindx;
+ bfd_vma addend = rel->r_addend;
+
+ if (! (h && h->root.type == bfd_link_hash_undefweak
+ && BFINFDPIC_SYM_LOCAL (info, h)))
+ {
+ /* If the symbol is dynamic and there may be dynamic
+ symbol resolution because we are or are linked with a
+ shared library, emit a FUNCDESC relocation such that
+ the dynamic linker will allocate the function
+ descriptor. If the symbol needs a non-local function
+ descriptor but binds locally (e.g., its visibility is
+ protected, emit a dynamic relocation decayed to
+ section+offset. */
+ if (h && ! BFINFDPIC_FUNCDESC_LOCAL (info, h)
+ && BFINFDPIC_SYM_LOCAL (info, h)
+ && !(info->executable && !info->pie))
+ {
+ dynindx = elf_section_data (h->root.u.def.section
+ ->output_section)->dynindx;
+ addend += h->root.u.def.section->output_offset
+ + h->root.u.def.value;
+ }
+ else if (h && ! BFINFDPIC_FUNCDESC_LOCAL (info, h))
+ {
+ if (addend)
+ {
+ info->callbacks->warning
+ (info, _("R_BFIN_FUNCDESC references dynamic symbol with nonzero addend"),
+ name, input_bfd, input_section, rel->r_offset);
+ return FALSE;
+ }
+ dynindx = h->dynindx;
+ }
+ else
+ {
+ /* Otherwise, we know we have a private function
+ descriptor, so reference it directly. */
+ BFD_ASSERT (picrel->privfd);
+ r_type = R_byte4_data;
+ dynindx = elf_section_data (bfinfdpic_got_section (info)
+ ->output_section)->dynindx;
+ addend = bfinfdpic_got_section (info)->output_offset
+ + bfinfdpic_got_initial_offset (info)
+ + picrel->fd_entry;
+ }
+
+ /* If there is room for dynamic symbol resolution, emit
+ the dynamic relocation. However, if we're linking an
+ executable at a fixed location, we won't have emitted a
+ dynamic symbol entry for the got section, so idx will
+ be zero, which means we can and should compute the
+ address of the private descriptor ourselves. */
+ if (info->executable && !info->pie
+ && (!h || BFINFDPIC_FUNCDESC_LOCAL (info, h)))
+ {
+ addend += bfinfdpic_got_section (info)->output_section->vma;
+ if ((bfd_get_section_flags (output_bfd,
+ input_section->output_section)
+ & (SEC_ALLOC | SEC_LOAD)) == (SEC_ALLOC | SEC_LOAD))
+ {
+ if (_bfinfdpic_osec_readonly_p (output_bfd,
+ input_section
+ ->output_section))
+ {
+ info->callbacks->warning
+ (info,
+ _("cannot emit fixups in read-only section"),
+ name, input_bfd, input_section, rel->r_offset);
+ return FALSE;
+ }
+ _bfinfdpic_add_rofixup (output_bfd,
+ bfinfdpic_gotfixup_section
+ (info),
+ _bfd_elf_section_offset
+ (output_bfd, info,
+ input_section, rel->r_offset)
+ + input_section
+ ->output_section->vma
+ + input_section->output_offset,
+ picrel);
+ }
+ }
+ else if ((bfd_get_section_flags (output_bfd,
+ input_section->output_section)
+ & (SEC_ALLOC | SEC_LOAD)) == (SEC_ALLOC | SEC_LOAD))
+ {
+ if (_bfinfdpic_osec_readonly_p (output_bfd,
+ input_section
+ ->output_section))
+ {
+ info->callbacks->warning
+ (info,
+ _("cannot emit dynamic relocations in read-only section"),
+ name, input_bfd, input_section, rel->r_offset);
+ return FALSE;
+ }
+ _bfinfdpic_add_dyn_reloc (output_bfd,
+ bfinfdpic_gotrel_section (info),
+ _bfd_elf_section_offset
+ (output_bfd, info,
+ input_section, rel->r_offset)
+ + input_section
+ ->output_section->vma
+ + input_section->output_offset,
+ r_type, dynindx, addend, picrel);
+ }
+ else
+ addend += bfinfdpic_got_section (info)->output_section->vma;
+ }
+
+ /* We want the addend in-place because dynamic
+ relocations are REL. Setting relocation to it should
+ arrange for it to be installed. */
+ relocation = addend - rel->r_addend;
+ }
+ check_segment[0] = check_segment[1] = got_segment;
+ break;
+
+ case R_byte4_data:
+ if (! IS_FDPIC (output_bfd))
+ {
+ check_segment[0] = check_segment[1] = -1;
+ break;
+ }
+ /* Fall through. */
+ case R_BFIN_FUNCDESC_VALUE:
+ {
+ int dynindx;
+ bfd_vma addend = rel->r_addend;
+
+ /* If the symbol is dynamic but binds locally, use
+ section+offset. */
+ if (h && ! BFINFDPIC_SYM_LOCAL (info, h))
+ {
+ if (addend && r_type == R_BFIN_FUNCDESC_VALUE)
+ {
+ info->callbacks->warning
+ (info, _("R_BFIN_FUNCDESC_VALUE references dynamic symbol with nonzero addend"),
+ name, input_bfd, input_section, rel->r_offset);
+ return FALSE;
+ }
+ dynindx = h->dynindx;
+ }
+ else
+ {
+ if (h)
+ addend += h->root.u.def.value;
+ else
+ addend += sym->st_value;
+ if (osec)
+ addend += osec->output_offset;
+ if (osec && osec->output_section
+ && ! bfd_is_abs_section (osec->output_section)
+ && ! bfd_is_und_section (osec->output_section))
+ dynindx = elf_section_data (osec->output_section)->dynindx;
+ else
+ dynindx = 0;
+ }
+
+ /* If we're linking an executable at a fixed address, we
+ can omit the dynamic relocation as long as the symbol
+ is defined in the current link unit (which is implied
+ by its output section not being NULL). */
+ if (info->executable && !info->pie
+ && (!h || BFINFDPIC_SYM_LOCAL (info, h)))
+ {
+ if (osec)
+ addend += osec->output_section->vma;
+ if (IS_FDPIC (input_bfd)
+ && (bfd_get_section_flags (output_bfd,
+ input_section->output_section)
+ & (SEC_ALLOC | SEC_LOAD)) == (SEC_ALLOC | SEC_LOAD))
+ {
+ if (_bfinfdpic_osec_readonly_p (output_bfd,
+ input_section
+ ->output_section))
+ {
+ info->callbacks->warning
+ (info,
+ _("cannot emit fixups in read-only section"),
+ name, input_bfd, input_section, rel->r_offset);
+ return FALSE;
+ }
+ if (!h || h->root.type != bfd_link_hash_undefweak)
+ {
+ _bfinfdpic_add_rofixup (output_bfd,
+ bfinfdpic_gotfixup_section
+ (info),
+ _bfd_elf_section_offset
+ (output_bfd, info,
+ input_section, rel->r_offset)
+ + input_section
+ ->output_section->vma
+ + input_section->output_offset,
+ picrel);
+ if (r_type == R_BFIN_FUNCDESC_VALUE)
+ _bfinfdpic_add_rofixup
+ (output_bfd,
+ bfinfdpic_gotfixup_section (info),
+ _bfd_elf_section_offset
+ (output_bfd, info,
+ input_section, rel->r_offset)
+ + input_section->output_section->vma
+ + input_section->output_offset + 4, picrel);
+ }
+ }
+ }
+ else
+ {
+ if ((bfd_get_section_flags (output_bfd,
+ input_section->output_section)
+ & (SEC_ALLOC | SEC_LOAD)) == (SEC_ALLOC | SEC_LOAD))
+ {
+ if (_bfinfdpic_osec_readonly_p (output_bfd,
+ input_section
+ ->output_section))
+ {
+ info->callbacks->warning
+ (info,
+ _("cannot emit dynamic relocations in read-only section"),
+ name, input_bfd, input_section, rel->r_offset);
+ return FALSE;
+ }
+ _bfinfdpic_add_dyn_reloc (output_bfd,
+ bfinfdpic_gotrel_section (info),
+ _bfd_elf_section_offset
+ (output_bfd, info,
+ input_section, rel->r_offset)
+ + input_section
+ ->output_section->vma
+ + input_section->output_offset,
+ r_type, dynindx, addend, picrel);
+ }
+ else if (osec)
+ addend += osec->output_section->vma;
+ /* We want the addend in-place because dynamic
+ relocations are REL. Setting relocation to it
+ should arrange for it to be installed. */
+ relocation = addend - rel->r_addend;
+ }
+
+ if (r_type == R_BFIN_FUNCDESC_VALUE)
+ {
+ /* If we've omitted the dynamic relocation, just emit
+ the fixed addresses of the symbol and of the local
+ GOT base offset. */
+ if (info->executable && !info->pie
+ && (!h || BFINFDPIC_SYM_LOCAL (info, h)))
+ bfd_put_32 (output_bfd,
+ bfinfdpic_got_section (info)->output_section->vma
+ + bfinfdpic_got_section (info)->output_offset
+ + bfinfdpic_got_initial_offset (info),
+ contents + rel->r_offset + 4);
+ else
+ /* A function descriptor used for lazy or local
+ resolving is initialized such that its high word
+ contains the output section index in which the
+ PLT entries are located, and the low word
+ contains the offset of the lazy PLT entry entry
+ point into that section. */
+ bfd_put_32 (output_bfd,
+ h && ! BFINFDPIC_SYM_LOCAL (info, h)
+ ? 0
+ : _bfinfdpic_osec_to_segment (output_bfd,
+ sec
+ ->output_section),
+ contents + rel->r_offset + 4);
+ }
+ }
+ check_segment[0] = check_segment[1] = got_segment;
+ break;
+
+ default:
+ check_segment[0] = isec_segment;
+ check_segment[1] = sec
+ ? _bfinfdpic_osec_to_segment (output_bfd, sec->output_section)
+ : (unsigned)-1;
+ break;
+ }
+
+ if (check_segment[0] != check_segment[1] && IS_FDPIC (output_bfd))
+ {
+#if 1 /* If you take this out, remove the #error from fdpic-static-6.d
+ in the ld testsuite. */
+ /* This helps catch problems in GCC while we can't do more
+ than static linking. The idea is to test whether the
+ input file basename is crt0.o only once. */
+ if (silence_segment_error == 1)
+ silence_segment_error =
+ (strlen (input_bfd->filename) == 6
+ && strcmp (input_bfd->filename, "crt0.o") == 0)
+ || (strlen (input_bfd->filename) > 6
+ && strcmp (input_bfd->filename
+ + strlen (input_bfd->filename) - 7,
+ "/crt0.o") == 0)
+ ? -1 : 0;
+#endif
+ if (!silence_segment_error
+ /* We don't want duplicate errors for undefined
+ symbols. */
+ && !(picrel && picrel->symndx == -1
+ && picrel->d.h->root.type == bfd_link_hash_undefined))
+ info->callbacks->warning
+ (info,
+ (info->shared || info->pie)
+ ? _("relocations between different segments are not supported")
+ : _("warning: relocation references a different segment"),
+ name, input_bfd, input_section, rel->r_offset);
+ if (!silence_segment_error && (info->shared || info->pie))
+ return FALSE;
+ elf_elfheader (output_bfd)->e_flags |= EF_BFIN_PIC;
+ }
+
+ switch (r_type)
+ {
+ case R_BFIN_GOTOFFHI:
+ /* We need the addend to be applied before we shift the
+ value right. */
+ relocation += rel->r_addend;
+ /* Fall through. */
+ case R_BFIN_GOTHI:
+ case R_BFIN_FUNCDESC_GOTHI:
+ case R_BFIN_FUNCDESC_GOTOFFHI:
+ relocation >>= 16;
+ /* Fall through. */
+
+ case R_BFIN_GOTLO:
+ case R_BFIN_FUNCDESC_GOTLO:
+ case R_BFIN_GOTOFFLO:
+ case R_BFIN_FUNCDESC_GOTOFFLO:
+ relocation &= 0xffff;
+ break;
+
+ default:
+ break;
+ }
+
+ switch (r_type)
+ {
+ case R_pcrel24:
+ case R_pcrel24_jump_l:
+ if (! IS_FDPIC (output_bfd) || ! picrel->plt)
+ break;
+ /* Fall through. */
+
+ /* When referencing a GOT entry, a function descriptor or a
+ PLT, we don't want the addend to apply to the reference,
+ but rather to the referenced symbol. The actual entry
+ will have already been created taking the addend into
+ account, so cancel it out here. */
+ case R_BFIN_GOT17M4:
+ case R_BFIN_GOTHI:
+ case R_BFIN_GOTLO:
+ case R_BFIN_FUNCDESC_GOT17M4:
+ case R_BFIN_FUNCDESC_GOTHI:
+ case R_BFIN_FUNCDESC_GOTLO:
+ case R_BFIN_FUNCDESC_GOTOFF17M4:
+ case R_BFIN_FUNCDESC_GOTOFFHI:
+ case R_BFIN_FUNCDESC_GOTOFFLO:
+ /* Note that we only want GOTOFFHI, not GOTOFFLO or GOTOFF17M4
+ here, since we do want to apply the addend to the others.
+ Note that we've applied the addend to GOTOFFHI before we
+ shifted it right. */
+ case R_BFIN_GOTOFFHI:
+ relocation -= rel->r_addend;
+ break;
+
+ default:
+ break;
+ }
+
+ if (r_type == R_pcrel24
+ || r_type == R_pcrel24_jump_l)
+ {
+ bfd_vma x;
+ bfd_vma address = rel->r_offset;
+
+ relocation += rel->r_addend;
+
+ /* Perform usual pc-relative correction. */
+ relocation -= input_section->output_section->vma + input_section->output_offset;
+ relocation -= address;
+
+ /* We are getting reloc_entry->address 2 byte off from
+ the start of instruction. Assuming absolute postion
+ of the reloc data. But, following code had been written assuming
+ reloc address is starting at begining of instruction.
+ To compensate that I have increased the value of
+ relocation by 1 (effectively 2) and used the addr -2 instead of addr. */
+
+ relocation += 2;
+ address -= 2;
+
+ relocation >>= 1;
+
+ x = bfd_get_16 (input_bfd, contents + address);
+ x = (x & 0xff00) | ((relocation >> 16) & 0xff);
+ bfd_put_16 (input_bfd, x, contents + address);
+
+ x = bfd_get_16 (input_bfd, contents + address + 2);
+ x = relocation & 0xFFFF;
+ bfd_put_16 (input_bfd, x, contents + address + 2);
+ r = bfd_reloc_ok;
+ }
+ else
+ r = _bfd_final_link_relocate (howto, input_bfd, input_section,
+ contents, rel->r_offset,
+ relocation, rel->r_addend);
+
+ if (r != bfd_reloc_ok)
+ {
+ const char * msg = (const char *) NULL;
+
+ switch (r)
+ {
+ case bfd_reloc_overflow:
+ r = info->callbacks->reloc_overflow
+ (info, (h ? &h->root : NULL), name, howto->name,
+ (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
+ break;
+
+ case bfd_reloc_undefined:
+ r = info->callbacks->undefined_symbol
+ (info, name, input_bfd, input_section, rel->r_offset, TRUE);
+ break;
+
+ case bfd_reloc_outofrange:
+ msg = _("internal error: out of range error");
+ break;
+
+ case bfd_reloc_notsupported:
+ msg = _("internal error: unsupported relocation error");
+ break;
+
+ case bfd_reloc_dangerous:
+ msg = _("internal error: dangerous relocation");
+ break;
+
+ default:
+ msg = _("internal error: unknown error");
+ break;
+ }
+
+ if (msg)
+ r = info->callbacks->warning
+ (info, msg, name, input_bfd, input_section, rel->r_offset);
+
+ if (! r)
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
static bfd_boolean
bfin_relocate_section (bfd * output_bfd,
@@ -1735,63 +2882,15 @@ bfin_relocate_section (bfd * output_bfd,
}
else
{
- 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 (!
- (!strcmp (h->root.root.string, ".__constant")
- || !strcmp (h->root.root.string, ".__operator")))
- {
- bfd_boolean warned;
- h = NULL;
- RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
- r_symndx, symtab_hdr, sym_hashes,
- h, sec, relocation,
- unresolved_reloc, warned);
-
- }
+ bfd_boolean warned;
+ h = NULL;
+ RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
+ r_symndx, symtab_hdr, sym_hashes,
+ h, sec, relocation,
+ unresolved_reloc, warned);
}
address = rel->r_offset;
- /* First, get stack relocs out of the way. */
- switch (r_type)
- {
- case R_push:
- reloc_stack_push (relocation + rel->r_addend);
- r = bfd_reloc_ok;
- goto done_reloc;
- case R_const:
- reloc_stack_push (rel->r_addend);
- r = bfd_reloc_ok;
- goto done_reloc;
- case R_add:
- case R_sub:
- case R_mult:
- case R_div:
- case R_mod:
- case R_lshift:
- case R_rshift:
- case R_neg:
- case R_and:
- case R_or:
- case R_xor:
- case R_land:
- case R_lor:
- case R_comp:
- case R_page:
- case R_hwpage:
- reloc_stack_operate (r_type);
- r = bfd_reloc_ok;
- goto done_reloc;
-
- default:
- if (!is_reloc_stack_empty())
- relocation = reloc_stack_pop ();
- break;
- }
/* Then, process normally. */
switch (r_type)
@@ -1917,10 +3016,10 @@ bfin_relocate_section (bfd * output_bfd,
/* We are getting reloc_entry->address 2 byte off from
the start of instruction. Assuming absolute postion
- of the reloc data. But, following code had been written assuming
+ of the reloc data. But, following code had been written assuming
reloc address is starting at begining of instruction.
- To compensate that I have increased the value of
- relocation by 1 (effectively 2) and used the addr -2 instead of addr. */
+ To compensate that I have increased the value of
+ relocation by 1 (effectively 2) and used the addr -2 instead of addr. */
relocation += 2;
address -= 2;
@@ -1947,7 +3046,6 @@ bfin_relocate_section (bfd * output_bfd,
break;
}
- done_reloc:
/* Dynamic relocs are not propagated for SEC_DEBUGGING sections
because such sections are not SEC_ALLOC and thus ld.so will
not process them. */
@@ -2040,6 +3138,17 @@ bfin_gc_mark_hook (asection * sec,
/* Update the got entry reference counts for the section being removed. */
static bfd_boolean
+bfinfdpic_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ asection *sec ATTRIBUTE_UNUSED,
+ const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED)
+{
+ return TRUE;
+}
+
+/* Update the got entry reference counts for the section being removed. */
+
+static bfd_boolean
bfin_gc_sweep_hook (bfd * abfd,
struct bfd_link_info *info,
asection * sec,
@@ -2107,35 +3216,1527 @@ bfin_gc_sweep_hook (bfd * abfd,
break;
}
}
+ return TRUE;
+}
+
+/* We need dynamic symbols for every section, since segments can
+ relocate independently. */
+static bfd_boolean
+_bfinfdpic_link_omit_section_dynsym (bfd *output_bfd ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info
+ ATTRIBUTE_UNUSED,
+ asection *p ATTRIBUTE_UNUSED)
+{
+ switch (elf_section_data (p)->this_hdr.sh_type)
+ {
+ case SHT_PROGBITS:
+ case SHT_NOBITS:
+ /* If sh_type is yet undecided, assume it could be
+ SHT_PROGBITS/SHT_NOBITS. */
+ case SHT_NULL:
+ return FALSE;
+
+ /* There shouldn't be section relative relocations
+ against any other section. */
+ default:
+ return TRUE;
+ }
+}
+
+/* Create a .got section, as well as its additional info field. This
+ is almost entirely copied from
+ elflink.c:_bfd_elf_create_got_section(). */
+
+static bfd_boolean
+_bfin_create_got_section (bfd *abfd, struct bfd_link_info *info)
+{
+ flagword flags, pltflags;
+ asection *s;
+ struct elf_link_hash_entry *h;
+ struct bfd_link_hash_entry *bh;
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ int ptralign;
+ int offset;
+
+ /* This function may be called more than once. */
+ s = bfd_get_section_by_name (abfd, ".got");
+ if (s != NULL && (s->flags & SEC_LINKER_CREATED) != 0)
+ return TRUE;
+
+ /* Machine specific: although pointers are 32-bits wide, we want the
+ GOT to be aligned to a 64-bit boundary, such that function
+ descriptors in it can be accessed with 64-bit loads and
+ stores. */
+ ptralign = 3;
+
+ flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
+ | SEC_LINKER_CREATED);
+ pltflags = flags;
+
+ s = bfd_make_section_with_flags (abfd, ".got", flags);
+ if (s == NULL
+ || !bfd_set_section_alignment (abfd, s, ptralign))
+ return FALSE;
+
+ if (bed->want_got_plt)
+ {
+ s = bfd_make_section_with_flags (abfd, ".got.plt", flags);
+ if (s == NULL
+ || !bfd_set_section_alignment (abfd, s, ptralign))
+ return FALSE;
+ }
+
+ if (bed->want_got_sym)
+ {
+ /* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the .got
+ (or .got.plt) section. We don't do this in the linker script
+ because we don't want to define the symbol if we are not creating
+ a global offset table. */
+ h = _bfd_elf_define_linkage_sym (abfd, info, s, "_GLOBAL_OFFSET_TABLE_");
+ elf_hash_table (info)->hgot = h;
+ if (h == NULL)
+ return FALSE;
+
+ /* Machine-specific: we want the symbol for executables as
+ well. */
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
+ return FALSE;
+ }
+
+ /* The first bit of the global offset table is the header. */
+ s->size += bed->got_header_size;
+
+ /* This is the machine-specific part. Create and initialize section
+ data for the got. */
+ if (IS_FDPIC (abfd))
+ {
+ bfinfdpic_got_section (info) = s;
+ bfinfdpic_relocs_info (info) = htab_try_create (1,
+ bfinfdpic_relocs_info_hash,
+ bfinfdpic_relocs_info_eq,
+ (htab_del) NULL);
+ if (! bfinfdpic_relocs_info (info))
+ return FALSE;
+
+ s = bfd_make_section_with_flags (abfd, ".rel.got",
+ (flags | SEC_READONLY));
+ if (s == NULL
+ || ! bfd_set_section_alignment (abfd, s, 2))
+ return FALSE;
+
+ bfinfdpic_gotrel_section (info) = s;
+
+ /* Machine-specific. */
+ s = bfd_make_section_with_flags (abfd, ".rofixup",
+ (flags | SEC_READONLY));
+ if (s == NULL
+ || ! bfd_set_section_alignment (abfd, s, 2))
+ return FALSE;
+
+ bfinfdpic_gotfixup_section (info) = s;
+ offset = -2048;
+ flags = BSF_GLOBAL;
+ }
+ else
+ {
+ offset = 2048;
+ flags = BSF_GLOBAL | BSF_WEAK;
+ }
+
+ /* Define _gp in .rofixup, for FDPIC, or .got otherwise. If it
+ turns out that we're linking with a different linker script, the
+ linker script will override it. */
+ bh = NULL;
+ if (!(_bfd_generic_link_add_one_symbol
+ (info, abfd, "_gp", flags, s, offset, (const char *) NULL, FALSE,
+ bed->collect, &bh)))
+ return FALSE;
+ h = (struct elf_link_hash_entry *) bh;
+ h->def_regular = 1;
+ h->type = STT_OBJECT;
+ /* h->other = STV_HIDDEN; */ /* Should we? */
+
+ /* Machine-specific: we want the symbol for executables as well. */
+ if (IS_FDPIC (abfd) && ! bfd_elf_link_record_dynamic_symbol (info, h))
+ return FALSE;
return TRUE;
}
+/* Make sure the got and plt sections exist, and that our pointers in
+ the link hash table point to them. */
-/* Merge backend specific data from an object file to the output
- object file when linking. */
static bfd_boolean
-elf32_bfin_merge_private_bfd_data (bfd * ibfd, bfd * obfd)
+elf32_bfinfdpic_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
{
- flagword out_flags;
- flagword in_flags;
+ /* This is mostly copied from
+ elflink.c:_bfd_elf_create_dynamic_sections(). */
+ flagword flags, pltflags;
+ asection *s;
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+
+ /* We need to create .plt, .rel[a].plt, .got, .got.plt, .dynbss, and
+ .rel[a].bss sections. */
+
+ flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
+ | SEC_LINKER_CREATED);
+
+ pltflags = flags;
+ pltflags |= SEC_CODE;
+ if (bed->plt_not_loaded)
+ pltflags &= ~ (SEC_CODE | SEC_LOAD | SEC_HAS_CONTENTS);
+ if (bed->plt_readonly)
+ pltflags |= SEC_READONLY;
+
+ s = bfd_make_section (abfd, ".plt");
+ if (s == NULL
+ || ! bfd_set_section_flags (abfd, s, pltflags)
+ || ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
+ return FALSE;
+ /* Blackfin-specific: remember it. */
+ bfinfdpic_plt_section (info) = s;
+
+ if (bed->want_plt_sym)
+ {
+ /* Define the symbol _PROCEDURE_LINKAGE_TABLE_ at the start of the
+ .plt section. */
+ struct elf_link_hash_entry *h;
+ struct bfd_link_hash_entry *bh = NULL;
- if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
- || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+ if (! (_bfd_generic_link_add_one_symbol
+ (info, abfd, "_PROCEDURE_LINKAGE_TABLE_", BSF_GLOBAL, s, 0, NULL,
+ FALSE, get_elf_backend_data (abfd)->collect, &bh)))
+ return FALSE;
+ h = (struct elf_link_hash_entry *) bh;
+ h->def_regular = 1;
+ h->type = STT_OBJECT;
+
+ if (! info->executable
+ && ! bfd_elf_link_record_dynamic_symbol (info, h))
+ return FALSE;
+ }
+
+ /* Blackfin-specific: we want rel relocations for the plt. */
+ s = bfd_make_section (abfd, ".rel.plt");
+ if (s == NULL
+ || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
+ || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
+ return FALSE;
+ /* Blackfin-specific: remember it. */
+ bfinfdpic_pltrel_section (info) = s;
+
+ /* Blackfin-specific: we want to create the GOT in the Blackfin way. */
+ if (! _bfin_create_got_section (abfd, info))
+ return FALSE;
+
+ /* Blackfin-specific: make sure we created everything we wanted. */
+ BFD_ASSERT (bfinfdpic_got_section (info) && bfinfdpic_gotrel_section (info)
+ /* && bfinfdpic_gotfixup_section (info) */
+ && bfinfdpic_plt_section (info)
+ && bfinfdpic_pltrel_section (info));
+
+ if (bed->want_dynbss)
+ {
+ /* The .dynbss section is a place to put symbols which are defined
+ by dynamic objects, are referenced by regular objects, and are
+ not functions. We must allocate space for them in the process
+ image and use a R_*_COPY reloc to tell the dynamic linker to
+ initialize them at run time. The linker script puts the .dynbss
+ section into the .bss section of the final image. */
+ s = bfd_make_section (abfd, ".dynbss");
+ if (s == NULL
+ || ! bfd_set_section_flags (abfd, s, SEC_ALLOC | SEC_LINKER_CREATED))
+ return FALSE;
+
+ /* The .rel[a].bss section holds copy relocs. This section is not
+ normally needed. We need to create it here, though, so that the
+ linker will map it to an output section. We can't just create it
+ only if we need it, because we will not know whether we need it
+ until we have seen all the input files, and the first time the
+ main linker code calls BFD after examining all the input files
+ (size_dynamic_sections) the input sections have already been
+ mapped to the output sections. If the section turns out not to
+ be needed, we can discard it later. We will never need this
+ section when generating a shared object, since they do not use
+ copy relocs. */
+ if (! info->shared)
+ {
+ s = bfd_make_section (abfd,
+ (bed->default_use_rela_p
+ ? ".rela.bss" : ".rel.bss"));
+ if (s == NULL
+ || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
+ || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/* The name of the dynamic interpreter. This is put in the .interp
+ section. */
+
+#define ELF_DYNAMIC_INTERPRETER "/lib/ld.so.1"
+
+#define DEFAULT_STACK_SIZE 0x20000
+
+/* This structure is used to collect the number of entries present in
+ each addressable range of the got. */
+struct _bfinfdpic_dynamic_got_info
+{
+ /* Several bits of information about the current link. */
+ struct bfd_link_info *info;
+ /* Total size needed for GOT entries within the 18- or 32-bit
+ ranges. */
+ bfd_vma got17m4, gothilo;
+ /* Total size needed for function descriptor entries within the 18-
+ or 32-bit ranges. */
+ bfd_vma fd17m4, fdhilo;
+ /* Total size needed function descriptor entries referenced in PLT
+ entries, that would be profitable to place in offsets close to
+ the PIC register. */
+ bfd_vma fdplt;
+ /* Total size needed by lazy PLT entries. */
+ bfd_vma lzplt;
+ /* Number of relocations carried over from input object files. */
+ unsigned long relocs;
+ /* Number of fixups introduced by relocations in input object files. */
+ unsigned long fixups;
+};
+
+/* Compute the total GOT size required by each symbol in each range.
+ Symbols may require up to 4 words in the GOT: an entry pointing to
+ the symbol, an entry pointing to its function descriptor, and a
+ private function descriptors taking two words. */
+
+static int
+_bfinfdpic_count_got_plt_entries (void **entryp, void *dinfo_)
+{
+ struct bfinfdpic_relocs_info *entry = *entryp;
+ struct _bfinfdpic_dynamic_got_info *dinfo = dinfo_;
+ unsigned relocs = 0, fixups = 0;
+
+ /* Allocate space for a GOT entry pointing to the symbol. */
+ if (entry->got17m4)
+ dinfo->got17m4 += 4;
+ else if (entry->gothilo)
+ dinfo->gothilo += 4;
+ else
+ entry->relocs32--;
+ entry->relocs32++;
+
+ /* Allocate space for a GOT entry pointing to the function
+ descriptor. */
+ if (entry->fdgot17m4)
+ dinfo->got17m4 += 4;
+ else if (entry->fdgothilo)
+ dinfo->gothilo += 4;
+ else
+ entry->relocsfd--;
+ entry->relocsfd++;
+
+ /* Decide whether we need a PLT entry, a function descriptor in the
+ GOT, and a lazy PLT entry for this symbol. */
+ entry->plt = entry->call
+ && entry->symndx == -1 && ! BFINFDPIC_SYM_LOCAL (dinfo->info, entry->d.h)
+ && elf_hash_table (dinfo->info)->dynamic_sections_created;
+ entry->privfd = entry->plt
+ || entry->fdgoff17m4 || entry->fdgoffhilo
+ || ((entry->fd || entry->fdgot17m4 || entry->fdgothilo)
+ && (entry->symndx != -1
+ || BFINFDPIC_FUNCDESC_LOCAL (dinfo->info, entry->d.h)));
+ entry->lazyplt = entry->privfd
+ && entry->symndx == -1 && ! BFINFDPIC_SYM_LOCAL (dinfo->info, entry->d.h)
+ && ! (dinfo->info->flags & DF_BIND_NOW)
+ && elf_hash_table (dinfo->info)->dynamic_sections_created;
+
+ /* Allocate space for a function descriptor. */
+ if (entry->fdgoff17m4)
+ dinfo->fd17m4 += 8;
+ else if (entry->privfd && entry->plt)
+ dinfo->fdplt += 8;
+ else if (entry->privfd)
+ dinfo->fdhilo += 8;
+ else
+ entry->relocsfdv--;
+ entry->relocsfdv++;
+
+ if (entry->lazyplt)
+ dinfo->lzplt += LZPLT_NORMAL_SIZE;
+
+ if (!dinfo->info->executable || dinfo->info->pie)
+ relocs = entry->relocs32 + entry->relocsfd + entry->relocsfdv;
+ else
+ {
+ if (entry->symndx != -1 || BFINFDPIC_SYM_LOCAL (dinfo->info, entry->d.h))
+ {
+ if (entry->symndx != -1
+ || entry->d.h->root.type != bfd_link_hash_undefweak)
+ fixups += entry->relocs32 + 2 * entry->relocsfdv;
+ }
+ else
+ relocs += entry->relocs32 + entry->relocsfdv;
+
+ if (entry->symndx != -1
+ || BFINFDPIC_FUNCDESC_LOCAL (dinfo->info, entry->d.h))
+ {
+ if (entry->symndx != -1
+ || entry->d.h->root.type != bfd_link_hash_undefweak)
+ fixups += entry->relocsfd;
+ }
+ else
+ relocs += entry->relocsfd;
+ }
+
+ entry->dynrelocs += relocs;
+ entry->fixups += fixups;
+ dinfo->relocs += relocs;
+ dinfo->fixups += fixups;
+
+ return 1;
+}
+
+/* This structure is used to assign offsets to got entries, function
+ descriptors, plt entries and lazy plt entries. */
+
+struct _bfinfdpic_dynamic_got_plt_info
+{
+ /* Summary information collected with _bfinfdpic_count_got_plt_entries. */
+ struct _bfinfdpic_dynamic_got_info g;
+
+ /* For each addressable range, we record a MAX (positive) and MIN
+ (negative) value. CUR is used to assign got entries, and it's
+ incremented from an initial positive value to MAX, then from MIN
+ to FDCUR (unless FDCUR wraps around first). FDCUR is used to
+ assign function descriptors, and it's decreased from an initial
+ non-positive value to MIN, then from MAX down to CUR (unless CUR
+ wraps around first). All of MIN, MAX, CUR and FDCUR always point
+ to even words. ODD, if non-zero, indicates an odd word to be
+ used for the next got entry, otherwise CUR is used and
+ incremented by a pair of words, wrapping around when it reaches
+ MAX. FDCUR is decremented (and wrapped) before the next function
+ descriptor is chosen. FDPLT indicates the number of remaining
+ slots that can be used for function descriptors used only by PLT
+ entries. */
+ struct _bfinfdpic_dynamic_got_alloc_data
+ {
+ bfd_signed_vma max, cur, odd, fdcur, min;
+ bfd_vma fdplt;
+ } got17m4, gothilo;
+};
+
+/* Determine the positive and negative ranges to be used by each
+ offset range in the GOT. FDCUR and CUR, that must be aligned to a
+ double-word boundary, are the minimum (negative) and maximum
+ (positive) GOT offsets already used by previous ranges, except for
+ an ODD entry that may have been left behind. GOT and FD indicate
+ the size of GOT entries and function descriptors that must be
+ placed within the range from -WRAP to WRAP. If there's room left,
+ up to FDPLT bytes should be reserved for additional function
+ descriptors. */
+
+inline static bfd_signed_vma
+_bfinfdpic_compute_got_alloc_data (struct _bfinfdpic_dynamic_got_alloc_data *gad,
+ bfd_signed_vma fdcur,
+ bfd_signed_vma odd,
+ bfd_signed_vma cur,
+ bfd_vma got,
+ bfd_vma fd,
+ bfd_vma fdplt,
+ bfd_vma wrap)
+{
+ bfd_signed_vma wrapmin = -wrap;
+
+ /* Start at the given initial points. */
+ gad->fdcur = fdcur;
+ gad->cur = cur;
+
+ /* If we had an incoming odd word and we have any got entries that
+ are going to use it, consume it, otherwise leave gad->odd at
+ zero. We might force gad->odd to zero and return the incoming
+ odd such that it is used by the next range, but then GOT entries
+ might appear to be out of order and we wouldn't be able to
+ shorten the GOT by one word if it turns out to end with an
+ unpaired GOT entry. */
+ if (odd && got)
+ {
+ gad->odd = odd;
+ got -= 4;
+ odd = 0;
+ }
+ else
+ gad->odd = 0;
+
+ /* If we're left with an unpaired GOT entry, compute its location
+ such that we can return it. Otherwise, if got doesn't require an
+ odd number of words here, either odd was already zero in the
+ block above, or it was set to zero because got was non-zero, or
+ got was already zero. In the latter case, we want the value of
+ odd to carry over to the return statement, so we don't want to
+ reset odd unless the condition below is true. */
+ if (got & 4)
+ {
+ odd = cur + got;
+ got += 4;
+ }
+
+ /* Compute the tentative boundaries of this range. */
+ gad->max = cur + got;
+ gad->min = fdcur - fd;
+ gad->fdplt = 0;
+
+ /* If function descriptors took too much space, wrap some of them
+ around. */
+ if (gad->min < wrapmin)
+ {
+ gad->max += wrapmin - gad->min;
+ gad->min = wrapmin;
+ }
+ /* If there is space left and we have function descriptors
+ referenced in PLT entries that could take advantage of shorter
+ offsets, place them here. */
+ else if (fdplt && gad->min > wrapmin)
+ {
+ bfd_vma fds;
+ if ((bfd_vma) (gad->min - wrapmin) < fdplt)
+ fds = gad->min - wrapmin;
+ else
+ fds = fdplt;
+
+ fdplt -= fds;
+ gad->min -= fds;
+ gad->fdplt += fds;
+ }
+
+ /* If GOT entries took too much space, wrap some of them around.
+ This may well cause gad->min to become lower than wrapmin. This
+ will cause a relocation overflow later on, so we don't have to
+ report it here . */
+ if ((bfd_vma) gad->max > wrap)
+ {
+ gad->min -= gad->max - wrap;
+ gad->max = wrap;
+ }
+ /* If there is more space left, try to place some more function
+ descriptors for PLT entries. */
+ else if (fdplt && (bfd_vma) gad->max < wrap)
+ {
+ bfd_vma fds;
+ if ((bfd_vma) (wrap - gad->max) < fdplt)
+ fds = wrap - gad->max;
+ else
+ fds = fdplt;
+
+ fdplt -= fds;
+ gad->max += fds;
+ gad->fdplt += fds;
+ }
+
+ /* If odd was initially computed as an offset past the wrap point,
+ wrap it around. */
+ if (odd > gad->max)
+ odd = gad->min + odd - gad->max;
+
+ /* _bfinfdpic_get_got_entry() below will always wrap gad->cur if needed
+ before returning, so do it here too. This guarantees that,
+ should cur and fdcur meet at the wrap point, they'll both be
+ equal to min. */
+ if (gad->cur == gad->max)
+ gad->cur = gad->min;
+
+ return odd;
+}
+
+/* Compute the location of the next GOT entry, given the allocation
+ data for a range. */
+
+inline static bfd_signed_vma
+_bfinfdpic_get_got_entry (struct _bfinfdpic_dynamic_got_alloc_data *gad)
+{
+ bfd_signed_vma ret;
+
+ if (gad->odd)
+ {
+ /* If there was an odd word left behind, use it. */
+ ret = gad->odd;
+ gad->odd = 0;
+ }
+ else
+ {
+ /* Otherwise, use the word pointed to by cur, reserve the next
+ as an odd word, and skip to the next pair of words, possibly
+ wrapping around. */
+ ret = gad->cur;
+ gad->odd = gad->cur + 4;
+ gad->cur += 8;
+ if (gad->cur == gad->max)
+ gad->cur = gad->min;
+ }
+
+ return ret;
+}
+
+/* Compute the location of the next function descriptor entry in the
+ GOT, given the allocation data for a range. */
+
+inline static bfd_signed_vma
+_bfinfdpic_get_fd_entry (struct _bfinfdpic_dynamic_got_alloc_data *gad)
+{
+ /* If we're at the bottom, wrap around, and only then allocate the
+ next pair of words. */
+ if (gad->fdcur == gad->min)
+ gad->fdcur = gad->max;
+ return gad->fdcur -= 8;
+}
+
+/* Assign GOT offsets for every GOT entry and function descriptor.
+ Doing everything in a single pass is tricky. */
+
+static int
+_bfinfdpic_assign_got_entries (void **entryp, void *info_)
+{
+ struct bfinfdpic_relocs_info *entry = *entryp;
+ struct _bfinfdpic_dynamic_got_plt_info *dinfo = info_;
+
+ if (entry->got17m4)
+ entry->got_entry = _bfinfdpic_get_got_entry (&dinfo->got17m4);
+ else if (entry->gothilo)
+ entry->got_entry = _bfinfdpic_get_got_entry (&dinfo->gothilo);
+
+ if (entry->fdgot17m4)
+ entry->fdgot_entry = _bfinfdpic_get_got_entry (&dinfo->got17m4);
+ else if (entry->fdgothilo)
+ entry->fdgot_entry = _bfinfdpic_get_got_entry (&dinfo->gothilo);
+
+ if (entry->fdgoff17m4)
+ entry->fd_entry = _bfinfdpic_get_fd_entry (&dinfo->got17m4);
+ else if (entry->plt && dinfo->got17m4.fdplt)
+ {
+ dinfo->got17m4.fdplt -= 8;
+ entry->fd_entry = _bfinfdpic_get_fd_entry (&dinfo->got17m4);
+ }
+ else if (entry->plt)
+ {
+ dinfo->gothilo.fdplt -= 8;
+ entry->fd_entry = _bfinfdpic_get_fd_entry (&dinfo->gothilo);
+ }
+ else if (entry->privfd)
+ entry->fd_entry = _bfinfdpic_get_fd_entry (&dinfo->gothilo);
+
+ return 1;
+}
+
+/* Assign GOT offsets to private function descriptors used by PLT
+ entries (or referenced by 32-bit offsets), as well as PLT entries
+ and lazy PLT entries. */
+
+static int
+_bfinfdpic_assign_plt_entries (void **entryp, void *info_)
+{
+ struct bfinfdpic_relocs_info *entry = *entryp;
+ struct _bfinfdpic_dynamic_got_plt_info *dinfo = info_;
+
+ /* If this symbol requires a local function descriptor, allocate
+ one. */
+ if (entry->privfd && entry->fd_entry == 0)
+ {
+ if (dinfo->got17m4.fdplt)
+ {
+ entry->fd_entry = _bfinfdpic_get_fd_entry (&dinfo->got17m4);
+ dinfo->got17m4.fdplt -= 8;
+ }
+ else
+ {
+ BFD_ASSERT (dinfo->gothilo.fdplt);
+ entry->fd_entry = _bfinfdpic_get_fd_entry (&dinfo->gothilo);
+ dinfo->gothilo.fdplt -= 8;
+ }
+ }
+
+ if (entry->plt)
+ {
+ int size;
+
+ /* We use the section's raw size to mark the location of the
+ next PLT entry. */
+ entry->plt_entry = bfinfdpic_plt_section (dinfo->g.info)->size;
+
+ /* Figure out the length of this PLT entry based on the
+ addressing mode we need to reach the function descriptor. */
+ BFD_ASSERT (entry->fd_entry);
+ if (entry->fd_entry >= -(1 << (18 - 1))
+ && entry->fd_entry + 4 < (1 << (18 - 1)))
+ size = 10;
+ else
+ size = 16;
+
+ bfinfdpic_plt_section (dinfo->g.info)->size += size;
+ }
+
+ if (entry->lazyplt)
+ {
+ entry->lzplt_entry = dinfo->g.lzplt;
+ dinfo->g.lzplt += LZPLT_NORMAL_SIZE;
+ /* If this entry is the one that gets the resolver stub, account
+ for the additional instruction. */
+ if (entry->lzplt_entry % BFINFDPIC_LZPLT_BLOCK_SIZE
+ == BFINFDPIC_LZPLT_RESOLV_LOC)
+ dinfo->g.lzplt += LZPLT_RESOLVER_EXTRA;
+ }
+
+ return 1;
+}
+
+/* Follow indirect and warning hash entries so that each got entry
+ points to the final symbol definition. P must point to a pointer
+ to the hash table we're traversing. Since this traversal may
+ modify the hash table, we set this pointer to NULL to indicate
+ we've made a potentially-destructive change to the hash table, so
+ the traversal must be restarted. */
+static int
+_bfinfdpic_resolve_final_relocs_info (void **entryp, void *p)
+{
+ struct bfinfdpic_relocs_info *entry = *entryp;
+ htab_t *htab = p;
+
+ if (entry->symndx == -1)
+ {
+ struct elf_link_hash_entry *h = entry->d.h;
+ struct bfinfdpic_relocs_info *oentry;
+
+ 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 (entry->d.h == h)
+ return 1;
+
+ oentry = bfinfdpic_relocs_info_for_global (*htab, 0, h, entry->addend,
+ NO_INSERT);
+
+ if (oentry)
+ {
+ /* Merge the two entries. */
+ bfinfdpic_pic_merge_early_relocs_info (oentry, entry);
+ htab_clear_slot (*htab, entryp);
+ return 1;
+ }
+
+ entry->d.h = h;
+
+ /* If we can't find this entry with the new bfd hash, re-insert
+ it, and get the traversal restarted. */
+ if (! htab_find (*htab, entry))
+ {
+ htab_clear_slot (*htab, entryp);
+ entryp = htab_find_slot (*htab, entry, INSERT);
+ if (! *entryp)
+ *entryp = entry;
+ /* Abort the traversal, since the whole table may have
+ moved, and leave it up to the parent to restart the
+ process. */
+ *(htab_t *)p = NULL;
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+/* Set the sizes of the dynamic sections. */
+
+static bfd_boolean
+elf32_bfinfdpic_size_dynamic_sections (bfd *output_bfd,
+ struct bfd_link_info *info)
+{
+ bfd *dynobj;
+ asection *s;
+ struct _bfinfdpic_dynamic_got_plt_info gpinfo;
+ bfd_signed_vma odd;
+ bfd_vma limit;
+
+ dynobj = elf_hash_table (info)->dynobj;
+ BFD_ASSERT (dynobj != NULL);
+
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ /* Set the contents of the .interp section to the interpreter. */
+ if (info->executable)
+ {
+ s = bfd_get_section_by_name (dynobj, ".interp");
+ BFD_ASSERT (s != NULL);
+ s->size = sizeof ELF_DYNAMIC_INTERPRETER;
+ s->contents = (bfd_byte *) ELF_DYNAMIC_INTERPRETER;
+ }
+ }
+
+ memset (&gpinfo, 0, sizeof (gpinfo));
+ gpinfo.g.info = info;
+
+ for (;;)
+ {
+ htab_t relocs = bfinfdpic_relocs_info (info);
+
+ htab_traverse (relocs, _bfinfdpic_resolve_final_relocs_info, &relocs);
+
+ if (relocs == bfinfdpic_relocs_info (info))
+ break;
+ }
+
+ htab_traverse (bfinfdpic_relocs_info (info), _bfinfdpic_count_got_plt_entries,
+ &gpinfo.g);
+
+ odd = 12;
+ /* Compute the total size taken by entries in the 18-bit range,
+ to tell how many PLT function descriptors we can bring into it
+ without causing it to overflow. */
+ limit = odd + gpinfo.g.got17m4 + gpinfo.g.fd17m4;
+ if (limit < (bfd_vma)1 << 18)
+ limit = ((bfd_vma)1 << 18) - limit;
+ else
+ limit = 0;
+ if (gpinfo.g.fdplt < limit)
+ limit = gpinfo.g.fdplt;
+
+ /* Determine the ranges of GOT offsets that we can use for each
+ range of addressing modes. */
+ odd = _bfinfdpic_compute_got_alloc_data (&gpinfo.got17m4,
+ 0,
+ odd,
+ 16,
+ gpinfo.g.got17m4,
+ gpinfo.g.fd17m4,
+ limit,
+ (bfd_vma)1 << (18-1));
+ odd = _bfinfdpic_compute_got_alloc_data (&gpinfo.gothilo,
+ gpinfo.got17m4.min,
+ odd,
+ gpinfo.got17m4.max,
+ gpinfo.g.gothilo,
+ gpinfo.g.fdhilo,
+ gpinfo.g.fdplt - gpinfo.got17m4.fdplt,
+ (bfd_vma)1 << (32-1));
+
+ /* Now assign (most) GOT offsets. */
+ htab_traverse (bfinfdpic_relocs_info (info), _bfinfdpic_assign_got_entries,
+ &gpinfo);
+
+ bfinfdpic_got_section (info)->size = gpinfo.gothilo.max
+ - gpinfo.gothilo.min
+ /* If an odd word is the last word of the GOT, we don't need this
+ word to be part of the GOT. */
+ - (odd + 4 == gpinfo.gothilo.max ? 4 : 0);
+ if (bfinfdpic_got_section (info)->size == 0)
+ bfinfdpic_got_section (info)->flags |= SEC_EXCLUDE;
+ else if (bfinfdpic_got_section (info)->size == 12
+ && ! elf_hash_table (info)->dynamic_sections_created)
+ {
+ bfinfdpic_got_section (info)->flags |= SEC_EXCLUDE;
+ bfinfdpic_got_section (info)->size = 0;
+ }
+ else
+ {
+ bfinfdpic_got_section (info)->contents =
+ (bfd_byte *) bfd_zalloc (dynobj,
+ bfinfdpic_got_section (info)->size);
+ if (bfinfdpic_got_section (info)->contents == NULL)
+ return FALSE;
+ }
+
+ if (elf_hash_table (info)->dynamic_sections_created)
+ /* Subtract the number of lzplt entries, since those will generate
+ relocations in the pltrel section. */
+ bfinfdpic_gotrel_section (info)->size =
+ (gpinfo.g.relocs - gpinfo.g.lzplt / LZPLT_NORMAL_SIZE)
+ * get_elf_backend_data (output_bfd)->s->sizeof_rel;
+ else
+ BFD_ASSERT (gpinfo.g.relocs == 0);
+ if (bfinfdpic_gotrel_section (info)->size == 0)
+ bfinfdpic_gotrel_section (info)->flags |= SEC_EXCLUDE;
+ else
+ {
+ bfinfdpic_gotrel_section (info)->contents =
+ (bfd_byte *) bfd_zalloc (dynobj,
+ bfinfdpic_gotrel_section (info)->size);
+ if (bfinfdpic_gotrel_section (info)->contents == NULL)
+ return FALSE;
+ }
+
+ bfinfdpic_gotfixup_section (info)->size = (gpinfo.g.fixups + 1) * 4;
+ if (bfinfdpic_gotfixup_section (info)->size == 0)
+ bfinfdpic_gotfixup_section (info)->flags |= SEC_EXCLUDE;
+ else
+ {
+ bfinfdpic_gotfixup_section (info)->contents =
+ (bfd_byte *) bfd_zalloc (dynobj,
+ bfinfdpic_gotfixup_section (info)->size);
+ if (bfinfdpic_gotfixup_section (info)->contents == NULL)
+ return FALSE;
+ }
+
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ bfinfdpic_pltrel_section (info)->size =
+ gpinfo.g.lzplt / LZPLT_NORMAL_SIZE * get_elf_backend_data (output_bfd)->s->sizeof_rel;
+ if (bfinfdpic_pltrel_section (info)->size == 0)
+ bfinfdpic_pltrel_section (info)->flags |= SEC_EXCLUDE;
+ else
+ {
+ bfinfdpic_pltrel_section (info)->contents =
+ (bfd_byte *) bfd_zalloc (dynobj,
+ bfinfdpic_pltrel_section (info)->size);
+ if (bfinfdpic_pltrel_section (info)->contents == NULL)
+ return FALSE;
+ }
+ }
+
+ /* Add 4 bytes for every block of at most 65535 lazy PLT entries,
+ such that there's room for the additional instruction needed to
+ call the resolver. Since _bfinfdpic_assign_got_entries didn't
+ account for them, our block size is 4 bytes smaller than the real
+ block size. */
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ bfinfdpic_plt_section (info)->size = gpinfo.g.lzplt
+ + ((gpinfo.g.lzplt + (BFINFDPIC_LZPLT_BLOCK_SIZE - 4) - LZPLT_NORMAL_SIZE)
+ / (BFINFDPIC_LZPLT_BLOCK_SIZE - 4) * LZPLT_RESOLVER_EXTRA);
+ }
+
+ /* Reset it, such that _bfinfdpic_assign_plt_entries() can use it to
+ actually assign lazy PLT entries addresses. */
+ gpinfo.g.lzplt = 0;
+
+ /* Save information that we're going to need to generate GOT and PLT
+ entries. */
+ bfinfdpic_got_initial_offset (info) = -gpinfo.gothilo.min;
+
+ if (get_elf_backend_data (output_bfd)->want_got_sym)
+ elf_hash_table (info)->hgot->root.u.def.value
+ += bfinfdpic_got_initial_offset (info);
+
+ if (elf_hash_table (info)->dynamic_sections_created)
+ bfinfdpic_plt_initial_offset (info) =
+ bfinfdpic_plt_section (info)->size;
+
+ htab_traverse (bfinfdpic_relocs_info (info), _bfinfdpic_assign_plt_entries,
+ &gpinfo);
+
+ /* Allocate the PLT section contents only after
+ _bfinfdpic_assign_plt_entries has a chance to add the size of the
+ non-lazy PLT entries. */
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ if (bfinfdpic_plt_section (info)->size == 0)
+ bfinfdpic_plt_section (info)->flags |= SEC_EXCLUDE;
+ else
+ {
+ bfinfdpic_plt_section (info)->contents =
+ (bfd_byte *) bfd_zalloc (dynobj,
+ bfinfdpic_plt_section (info)->size);
+ if (bfinfdpic_plt_section (info)->contents == NULL)
+ return FALSE;
+ }
+ }
+
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ if (bfinfdpic_got_section (info)->size)
+ if (!_bfd_elf_add_dynamic_entry (info, DT_PLTGOT, 0))
+ return FALSE;
+
+ if (bfinfdpic_pltrel_section (info)->size)
+ if (!_bfd_elf_add_dynamic_entry (info, DT_PLTRELSZ, 0)
+ || !_bfd_elf_add_dynamic_entry (info, DT_PLTREL, DT_REL)
+ || !_bfd_elf_add_dynamic_entry (info, DT_JMPREL, 0))
+ return FALSE;
+
+ if (bfinfdpic_gotrel_section (info)->size)
+ if (!_bfd_elf_add_dynamic_entry (info, DT_REL, 0)
+ || !_bfd_elf_add_dynamic_entry (info, DT_RELSZ, 0)
+ || !_bfd_elf_add_dynamic_entry (info, DT_RELENT,
+ sizeof (Elf32_External_Rel)))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static bfd_boolean
+elf32_bfinfdpic_always_size_sections (bfd *output_bfd,
+ struct bfd_link_info *info)
+{
+ if (!info->relocatable)
+ {
+ struct elf_link_hash_entry *h;
+ asection *sec;
+
+ /* Force a PT_GNU_STACK segment to be created. */
+ if (! elf_tdata (output_bfd)->stack_flags)
+ elf_tdata (output_bfd)->stack_flags = PF_R | PF_W | PF_X;
+
+ /* Define __stacksize if it's not defined yet. */
+ h = elf_link_hash_lookup (elf_hash_table (info), "__stacksize",
+ FALSE, FALSE, FALSE);
+ if (! h || h->root.type != bfd_link_hash_defined
+ || h->type != STT_OBJECT
+ || !h->def_regular)
+ {
+ struct bfd_link_hash_entry *bh = NULL;
+
+ if (!(_bfd_generic_link_add_one_symbol
+ (info, output_bfd, "__stacksize",
+ BSF_GLOBAL, bfd_abs_section_ptr, DEFAULT_STACK_SIZE,
+ (const char *) NULL, FALSE,
+ get_elf_backend_data (output_bfd)->collect, &bh)))
+ return FALSE;
+
+ h = (struct elf_link_hash_entry *) bh;
+ h->def_regular = 1;
+ h->type = STT_OBJECT;
+ }
+
+ /* Create a stack section, and set its alignment. */
+ sec = bfd_make_section (output_bfd, ".stack");
+
+ if (sec == NULL
+ || ! bfd_set_section_alignment (output_bfd, sec, 3))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static bfd_boolean
+elf32_bfinfdpic_modify_segment_map (bfd *output_bfd,
+ struct bfd_link_info *info)
+{
+ struct elf_segment_map *m;
+
+ /* objcopy and strip preserve what's already there using
+ elf32_bfinfdpic_copy_private_bfd_data (). */
+ if (! info)
return TRUE;
- in_flags = elf_elfheader (ibfd)->e_flags;
- out_flags = elf_elfheader (obfd)->e_flags;
+ for (m = elf_tdata (output_bfd)->segment_map; m != NULL; m = m->next)
+ if (m->p_type == PT_GNU_STACK)
+ break;
- if (!elf_flags_init (obfd))
+ if (m)
{
- elf_flags_init (obfd) = TRUE;
- elf_elfheader (obfd)->e_flags = in_flags;
+ asection *sec = bfd_get_section_by_name (output_bfd, ".stack");
+ struct elf_link_hash_entry *h;
+
+ if (sec)
+ {
+ /* Obtain the pointer to the __stacksize symbol. */
+ h = elf_link_hash_lookup (elf_hash_table (info), "__stacksize",
+ FALSE, FALSE, FALSE);
+ 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;
+ BFD_ASSERT (h->root.type == bfd_link_hash_defined);
+
+ /* Set the section size from the symbol value. We
+ intentionally ignore the symbol section. */
+ if (h->root.type == bfd_link_hash_defined)
+ sec->size = h->root.u.def.value;
+ else
+ sec->size = DEFAULT_STACK_SIZE;
+
+ /* Add the stack section to the PT_GNU_STACK segment,
+ such that its size and alignment requirements make it
+ to the segment. */
+ m->sections[m->count] = sec;
+ m->count++;
+ }
+ }
+
+ return TRUE;
+}
+
+static bfd_boolean
+elf32_bfinfdpic_finish_dynamic_sections (bfd *output_bfd,
+ struct bfd_link_info *info)
+{
+ bfd *dynobj;
+ asection *sdyn;
+
+ dynobj = elf_hash_table (info)->dynobj;
+
+ if (bfinfdpic_got_section (info))
+ {
+ BFD_ASSERT (bfinfdpic_gotrel_section (info)->size
+ == (bfinfdpic_gotrel_section (info)->reloc_count
+ * sizeof (Elf32_External_Rel)));
+
+ if (bfinfdpic_gotfixup_section (info))
+ {
+ struct elf_link_hash_entry *hgot = elf_hash_table (info)->hgot;
+ bfd_vma got_value = hgot->root.u.def.value
+ + hgot->root.u.def.section->output_section->vma
+ + hgot->root.u.def.section->output_offset;
+
+ _bfinfdpic_add_rofixup (output_bfd, bfinfdpic_gotfixup_section (info),
+ got_value, 0);
+
+ if (bfinfdpic_gotfixup_section (info)->size
+ != (bfinfdpic_gotfixup_section (info)->reloc_count * 4))
+ {
+ (*_bfd_error_handler)
+ ("LINKER BUG: .rofixup section size mismatch");
+ return FALSE;
+ }
+ }
+ }
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ BFD_ASSERT (bfinfdpic_pltrel_section (info)->size
+ == (bfinfdpic_pltrel_section (info)->reloc_count
+ * sizeof (Elf32_External_Rel)));
+ }
+
+ sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ Elf32_External_Dyn * dyncon;
+ Elf32_External_Dyn * dynconend;
+
+ BFD_ASSERT (sdyn != NULL);
+
+ dyncon = (Elf32_External_Dyn *) sdyn->contents;
+ dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size);
+
+ for (; dyncon < dynconend; dyncon++)
+ {
+ Elf_Internal_Dyn dyn;
+
+ bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
+
+ switch (dyn.d_tag)
+ {
+ default:
+ break;
+
+ case DT_PLTGOT:
+ dyn.d_un.d_ptr = bfinfdpic_got_section (info)->output_section->vma
+ + bfinfdpic_got_section (info)->output_offset
+ + bfinfdpic_got_initial_offset (info);
+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+ break;
+
+ case DT_JMPREL:
+ dyn.d_un.d_ptr = bfinfdpic_pltrel_section (info)
+ ->output_section->vma
+ + bfinfdpic_pltrel_section (info)->output_offset;
+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+ break;
+
+ case DT_PLTRELSZ:
+ dyn.d_un.d_val = bfinfdpic_pltrel_section (info)->size;
+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+ break;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+/* Adjust a symbol defined by a dynamic object and referenced by a
+ regular object. */
+
+static bfd_boolean
+elf32_bfinfdpic_adjust_dynamic_symbol
+(struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ struct elf_link_hash_entry *h ATTRIBUTE_UNUSED)
+{
+ bfd * dynobj;
+
+ dynobj = elf_hash_table (info)->dynobj;
+
+ /* Make sure we know what is going on here. */
+ BFD_ASSERT (dynobj != NULL
+ && (h->u.weakdef != NULL
+ || (h->def_dynamic
+ && h->ref_regular
+ && !h->def_regular)));
+
+ /* If this is a weak symbol, and there is a real definition, the
+ processor independent code will have arranged for us to see the
+ real definition first, and we can just use the same value. */
+ if (h->u.weakdef != NULL)
+ {
+ BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
+ || h->u.weakdef->root.type == bfd_link_hash_defweak);
+ h->root.u.def.section = h->u.weakdef->root.u.def.section;
+ h->root.u.def.value = h->u.weakdef->root.u.def.value;
+ }
+
+ return TRUE;
+}
+
+/* Perform any actions needed for dynamic symbols. */
+
+static bfd_boolean
+elf32_bfinfdpic_finish_dynamic_symbol
+(bfd *output_bfd ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ struct elf_link_hash_entry *h ATTRIBUTE_UNUSED,
+ Elf_Internal_Sym *sym ATTRIBUTE_UNUSED)
+{
+ return TRUE;
+}
+
+/* Decide whether to attempt to turn absptr or lsda encodings in
+ shared libraries into pcrel within the given input section. */
+
+static bfd_boolean
+bfinfdpic_elf_use_relative_eh_frame
+(bfd *input_bfd ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ asection *eh_frame_section ATTRIBUTE_UNUSED)
+{
+ /* We can't use PC-relative encodings in FDPIC binaries, in general. */
+ return FALSE;
+}
+
+/* Adjust the contents of an eh_frame_hdr section before they're output. */
+
+static bfd_byte
+bfinfdpic_elf_encode_eh_address (bfd *abfd,
+ struct bfd_link_info *info,
+ asection *osec, bfd_vma offset,
+ asection *loc_sec, bfd_vma loc_offset,
+ bfd_vma *encoded)
+{
+ struct elf_link_hash_entry *h;
+
+ h = elf_hash_table (info)->hgot;
+ BFD_ASSERT (h && h->root.type == bfd_link_hash_defined);
+
+ if (! h || (_bfinfdpic_osec_to_segment (abfd, osec)
+ == _bfinfdpic_osec_to_segment (abfd, loc_sec->output_section)))
+ return _bfd_elf_encode_eh_address (abfd, info, osec, offset,
+ loc_sec, loc_offset, encoded);
+
+ BFD_ASSERT (_bfinfdpic_osec_to_segment (abfd, osec)
+ == (_bfinfdpic_osec_to_segment
+ (abfd, h->root.u.def.section->output_section)));
+
+ *encoded = osec->vma + offset
+ - (h->root.u.def.value
+ + h->root.u.def.section->output_section->vma
+ + h->root.u.def.section->output_offset);
+
+ return DW_EH_PE_datarel | DW_EH_PE_sdata4;
+}
+
+
+
+/* Look through the relocs for a section during the first phase.
+
+ Besides handling virtual table relocs for gc, we have to deal with
+ all sorts of PIC-related relocations. We describe below the
+ general plan on how to handle such relocations, even though we only
+ collect information at this point, storing them in hash tables for
+ perusal of later passes.
+
+ 32 relocations are propagated to the linker output when creating
+ position-independent output. LO16 and HI16 relocations are not
+ supposed to be encountered in this case.
+
+ LABEL16 should always be resolvable by the linker, since it's only
+ used by branches.
+
+ LABEL24, on the other hand, is used by calls. If it turns out that
+ the target of a call is a dynamic symbol, a PLT entry must be
+ created for it, which triggers the creation of a private function
+ descriptor and, unless lazy binding is disabled, a lazy PLT entry.
+
+ GPREL relocations require the referenced symbol to be in the same
+ segment as _gp, but this can only be checked later.
+
+ All GOT, GOTOFF and FUNCDESC relocations require a .got section to
+ exist. LABEL24 might as well, since it may require a PLT entry,
+ that will require a got.
+
+ Non-FUNCDESC GOT relocations require a GOT entry to be created
+ regardless of whether the symbol is dynamic. However, since a
+ global symbol that turns out to not be exported may have the same
+ address of a non-dynamic symbol, we don't assign GOT entries at
+ this point, such that we can share them in this case. A relocation
+ for the GOT entry always has to be created, be it to offset a
+ private symbol by the section load address, be it to get the symbol
+ resolved dynamically.
+
+ FUNCDESC GOT relocations require a GOT entry to be created, and
+ handled as if a FUNCDESC relocation was applied to the GOT entry in
+ an object file.
+
+ FUNCDESC relocations referencing a symbol that turns out to NOT be
+ dynamic cause a private function descriptor to be created. The
+ FUNCDESC relocation then decays to a 32 relocation that points at
+ the private descriptor. If the symbol is dynamic, the FUNCDESC
+ relocation is propagated to the linker output, such that the
+ dynamic linker creates the canonical descriptor, pointing to the
+ dynamically-resolved definition of the function.
+
+ Non-FUNCDESC GOTOFF relocations must always refer to non-dynamic
+ symbols that are assigned to the same segment as the GOT, but we
+ can only check this later, after we know the complete set of
+ symbols defined and/or exported.
+
+ FUNCDESC GOTOFF relocations require a function descriptor to be
+ created and, unless lazy binding is disabled or the symbol is not
+ dynamic, a lazy PLT entry. Since we can't tell at this point
+ whether a symbol is going to be dynamic, we have to decide later
+ whether to create a lazy PLT entry or bind the descriptor directly
+ to the private function.
+
+ FUNCDESC_VALUE relocations are not supposed to be present in object
+ files, but they may very well be simply propagated to the linker
+ output, since they have no side effect.
+
+
+ A function descriptor always requires a FUNCDESC_VALUE relocation.
+ Whether it's in .plt.rel or not depends on whether lazy binding is
+ enabled and on whether the referenced symbol is dynamic.
+
+ The existence of a lazy PLT requires the resolverStub lazy PLT
+ entry to be present.
+
+
+ As for assignment of GOT, PLT and lazy PLT entries, and private
+ descriptors, we might do them all sequentially, but we can do
+ better than that. For example, we can place GOT entries and
+ private function descriptors referenced using 12-bit operands
+ closer to the PIC register value, such that these relocations don't
+ overflow. Those that are only referenced with LO16 relocations
+ could come next, but we may as well place PLT-required function
+ descriptors in the 12-bit range to make them shorter. Symbols
+ referenced with LO16/HI16 may come next, but we may place
+ additional function descriptors in the 16-bit range if we can
+ reliably tell that we've already placed entries that are ever
+ referenced with only LO16. PLT entries are therefore generated as
+ small as possible, while not introducing relocation overflows in
+ GOT or FUNCDESC_GOTOFF relocations. Lazy PLT entries could be
+ generated before or after PLT entries, but not intermingled with
+ them, such that we can have more lazy PLT entries in range for a
+ branch to the resolverStub. The resolverStub should be emitted at
+ the most distant location from the first lazy PLT entry such that
+ it's still in range for a branch, or closer, if there isn't a need
+ for so many lazy PLT entries. Additional lazy PLT entries may be
+ emitted after the resolverStub, as long as branches are still in
+ range. If the branch goes out of range, longer lazy PLT entries
+ are emitted.
+
+ We could further optimize PLT and lazy PLT entries by giving them
+ priority in assignment to closer-to-gr17 locations depending on the
+ number of occurrences of references to them (assuming a function
+ that's called more often is more important for performance, so its
+ PLT entry should be faster), or taking hints from the compiler.
+ Given infinite time and money... :-) */
+
+static bfd_boolean
+bfinfdpic_check_relocs (bfd *abfd, struct bfd_link_info *info,
+ asection *sec, const Elf_Internal_Rela *relocs)
+{
+ Elf_Internal_Shdr *symtab_hdr;
+ struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
+ const Elf_Internal_Rela *rel;
+ const Elf_Internal_Rela *rel_end;
+ bfd *dynobj;
+ struct bfinfdpic_relocs_info *picrel;
+
+ if (info->relocatable)
+ return TRUE;
+
+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+ sym_hashes = elf_sym_hashes (abfd);
+ sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof(Elf32_External_Sym);
+ if (!elf_bad_symtab (abfd))
+ sym_hashes_end -= symtab_hdr->sh_info;
+
+ dynobj = elf_hash_table (info)->dynobj;
+ rel_end = relocs + sec->reloc_count;
+ for (rel = relocs; rel < rel_end; rel++)
+ {
+ struct elf_link_hash_entry *h;
+ unsigned long r_symndx;
+
+ r_symndx = ELF32_R_SYM (rel->r_info);
+ if (r_symndx < symtab_hdr->sh_info)
+ h = NULL;
+ else
+ h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+
+ switch (ELF32_R_TYPE (rel->r_info))
+ {
+ case R_BFIN_GOT17M4:
+ case R_BFIN_GOTHI:
+ case R_BFIN_GOTLO:
+ case R_BFIN_FUNCDESC_GOT17M4:
+ case R_BFIN_FUNCDESC_GOTHI:
+ case R_BFIN_FUNCDESC_GOTLO:
+ case R_BFIN_GOTOFF17M4:
+ case R_BFIN_GOTOFFHI:
+ case R_BFIN_GOTOFFLO:
+ case R_BFIN_FUNCDESC_GOTOFF17M4:
+ case R_BFIN_FUNCDESC_GOTOFFHI:
+ case R_BFIN_FUNCDESC_GOTOFFLO:
+ case R_BFIN_FUNCDESC:
+ case R_BFIN_FUNCDESC_VALUE:
+ if (! IS_FDPIC (abfd))
+ goto bad_reloc;
+ /* Fall through. */
+ case R_pcrel24:
+ case R_pcrel24_jump_l:
+ case R_byte4_data:
+ if (IS_FDPIC (abfd) && ! dynobj)
+ {
+ elf_hash_table (info)->dynobj = dynobj = abfd;
+ if (! _bfin_create_got_section (abfd, info))
+ return FALSE;
+ }
+ if (! IS_FDPIC (abfd))
+ {
+ picrel = NULL;
+ break;
+ }
+ if (h != NULL)
+ {
+ if (h->dynindx == -1)
+ switch (ELF_ST_VISIBILITY (h->other))
+ {
+ case STV_INTERNAL:
+ case STV_HIDDEN:
+ break;
+ default:
+ bfd_elf_link_record_dynamic_symbol (info, h);
+ break;
+ }
+ picrel
+ = bfinfdpic_relocs_info_for_global (bfinfdpic_relocs_info (info),
+ abfd, h,
+ rel->r_addend, INSERT);
+ }
+ else
+ picrel = bfinfdpic_relocs_info_for_local (bfinfdpic_relocs_info
+ (info), abfd, r_symndx,
+ rel->r_addend, INSERT);
+ if (! picrel)
+ return FALSE;
+ break;
+
+ default:
+ picrel = NULL;
+ break;
+ }
+
+ switch (ELF32_R_TYPE (rel->r_info))
+ {
+ case R_pcrel24:
+ case R_pcrel24_jump_l:
+ if (IS_FDPIC (abfd))
+ picrel->call = 1;
+ break;
+
+ case R_BFIN_FUNCDESC_VALUE:
+ picrel->relocsfdv++;
+ if (bfd_get_section_flags (abfd, sec) & SEC_ALLOC)
+ picrel->relocs32--;
+ /* Fall through. */
+
+ case R_byte4_data:
+ if (! IS_FDPIC (abfd))
+ break;
+
+ picrel->sym = 1;
+ if (bfd_get_section_flags (abfd, sec) & SEC_ALLOC)
+ picrel->relocs32++;
+ break;
+
+ case R_BFIN_GOT17M4:
+ picrel->got17m4 = 1;
+ break;
+
+ case R_BFIN_GOTHI:
+ case R_BFIN_GOTLO:
+ picrel->gothilo = 1;
+ break;
+
+ case R_BFIN_FUNCDESC_GOT17M4:
+ picrel->fdgot17m4 = 1;
+ break;
+
+ case R_BFIN_FUNCDESC_GOTHI:
+ case R_BFIN_FUNCDESC_GOTLO:
+ picrel->fdgothilo = 1;
+ break;
+
+ case R_BFIN_GOTOFF17M4:
+ case R_BFIN_GOTOFFHI:
+ case R_BFIN_GOTOFFLO:
+ picrel->gotoff = 1;
+ break;
+
+ case R_BFIN_FUNCDESC_GOTOFF17M4:
+ picrel->fdgoff17m4 = 1;
+ break;
+
+ case R_BFIN_FUNCDESC_GOTOFFHI:
+ case R_BFIN_FUNCDESC_GOTOFFLO:
+ picrel->fdgoffhilo = 1;
+ break;
+
+ case R_BFIN_FUNCDESC:
+ picrel->fd = 1;
+ picrel->relocsfd++;
+ break;
+
+ /* This relocation describes the C++ object vtable hierarchy.
+ Reconstruct it for later use during GC. */
+ case R_BFIN_GNU_VTINHERIT:
+ 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_BFIN_GNU_VTENTRY:
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+ return FALSE;
+ break;
+
+ case R_huimm16:
+ case R_luimm16:
+ case R_pcrel12_jump_s:
+ case R_pcrel10:
+ break;
+
+ default:
+ bad_reloc:
+ (*_bfd_error_handler)
+ (_("%B: unsupported relocation type %i"),
+ abfd, ELF32_R_TYPE (rel->r_info));
+ return FALSE;
+ }
}
return TRUE;
}
+/* Set the right machine number for a Blackfin ELF file. */
+
+static bfd_boolean
+elf32_bfin_object_p (bfd *abfd)
+{
+ bfd_default_set_arch_mach (abfd, bfd_arch_bfin, 0);
+ return (((elf_elfheader (abfd)->e_flags & EF_BFIN_FDPIC) != 0)
+ == (IS_FDPIC (abfd)));
+}
static bfd_boolean
elf32_bfin_set_private_flags (bfd * abfd, flagword flags)
@@ -2145,29 +4746,170 @@ elf32_bfin_set_private_flags (bfd * abfd, flagword flags)
return TRUE;
}
+/* Copy backend specific data from one object module to another. */
+
+static bfd_boolean
+bfin_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
+{
+ if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
+ || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+ return TRUE;
+
+ BFD_ASSERT (!elf_flags_init (obfd)
+ || elf_elfheader (obfd)->e_flags == elf_elfheader (ibfd)->e_flags);
+
+ elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
+ elf_flags_init (obfd) = TRUE;
+ return TRUE;
+}
+
+static bfd_boolean
+elf32_bfinfdpic_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
+{
+ unsigned i;
+
+ if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
+ || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+ return TRUE;
+
+ if (! bfin_elf_copy_private_bfd_data (ibfd, obfd))
+ return FALSE;
+
+ if (! elf_tdata (ibfd) || ! elf_tdata (ibfd)->phdr
+ || ! elf_tdata (obfd) || ! elf_tdata (obfd)->phdr)
+ return TRUE;
+
+ /* Copy the stack size. */
+ for (i = 0; i < elf_elfheader (ibfd)->e_phnum; i++)
+ if (elf_tdata (ibfd)->phdr[i].p_type == PT_GNU_STACK)
+ {
+ Elf_Internal_Phdr *iphdr = &elf_tdata (ibfd)->phdr[i];
+
+ for (i = 0; i < elf_elfheader (obfd)->e_phnum; i++)
+ if (elf_tdata (obfd)->phdr[i].p_type == PT_GNU_STACK)
+ {
+ memcpy (&elf_tdata (obfd)->phdr[i], iphdr, sizeof (*iphdr));
+
+ /* Rewrite the phdrs, since we're only called after they
+ were first written. */
+ if (bfd_seek (obfd, (bfd_signed_vma) get_elf_backend_data (obfd)
+ ->s->sizeof_ehdr, SEEK_SET) != 0
+ || get_elf_backend_data (obfd)->s
+ ->write_out_phdrs (obfd, elf_tdata (obfd)->phdr,
+ elf_elfheader (obfd)->e_phnum) != 0)
+ return FALSE;
+ break;
+ }
+
+ break;
+ }
+
+ return TRUE;
+}
+
/* Display the flags field. */
static bfd_boolean
elf32_bfin_print_private_bfd_data (bfd * abfd, PTR ptr)
{
FILE *file = (FILE *) ptr;
+ flagword flags;
BFD_ASSERT (abfd != NULL && ptr != NULL);
/* Print normal ELF private data. */
_bfd_elf_print_private_bfd_data (abfd, ptr);
- /* Ignore init flag - it may not be set, despite the flags field
- containing valid data. */
+ flags = elf_elfheader (abfd)->e_flags;
/* xgettext:c-format */
fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
+ if (flags & EF_BFIN_PIC)
+ fprintf (file, " -fpic");
+
+ if (flags & EF_BFIN_FDPIC)
+ fprintf (file, " -mfdpic");
+
fputc ('\n', file);
return TRUE;
}
+/* Merge backend specific data from an object file to the output
+ object file when linking. */
+
+static bfd_boolean
+elf32_bfin_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
+{
+ flagword old_flags, old_partial;
+ flagword new_flags, new_partial;
+ bfd_boolean error = FALSE;
+
+ new_flags = elf_elfheader (ibfd)->e_flags;
+ old_flags = elf_elfheader (obfd)->e_flags;
+
+ if (new_flags & EF_BFIN_FDPIC)
+ new_flags &= ~EF_BFIN_PIC;
+
+#ifdef DEBUG
+ (*_bfd_error_handler) ("old_flags = 0x%.8lx, new_flags = 0x%.8lx, init = %s, filename = %s",
+ old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no",
+ bfd_get_filename (ibfd));
+#endif
+
+ if (!elf_flags_init (obfd)) /* First call, no flags set. */
+ {
+ elf_flags_init (obfd) = TRUE;
+ old_flags = new_flags;
+ }
+
+ else if (new_flags == old_flags) /* Compatible flags are ok. */
+ ;
+
+ else /* Possibly incompatible flags. */
+ {
+ /* We don't have to do anything if the pic flags are the same, or the new
+ module(s) were compiled with -mlibrary-pic. */
+ new_partial = (new_flags & EF_BFIN_PIC_FLAGS);
+ old_partial = (old_flags & EF_BFIN_PIC_FLAGS);
+ if (new_partial == old_partial)
+ ;
+
+ /* If we have mixtures of -fpic and -fPIC, or in both bits. */
+ else if (new_partial != 0 && old_partial != 0)
+ old_flags |= new_partial;
+
+ /* One module was compiled for pic and the other was not, see if we have
+ had any relocations that are not pic-safe. */
+ else
+ old_flags |= new_partial;
+
+ }
+
+ /* Update the old flags now with changes made above. */
+ elf_elfheader (obfd)->e_flags = old_flags;
+
+ if (((new_flags & EF_BFIN_FDPIC) == 0)
+ != (! IS_FDPIC (ibfd)))
+ {
+ error = TRUE;
+ if (IS_FDPIC (obfd))
+ (*_bfd_error_handler)
+ (_("%s: cannot link non-fdpic object file into fdpic executable"),
+ bfd_get_filename (ibfd));
+ else
+ (*_bfd_error_handler)
+ (_("%s: cannot link fdpic object file into non-fdpic executable"),
+ bfd_get_filename (ibfd));
+ }
+
+ if (error)
+ bfd_set_error (bfd_error_bad_value);
+
+ return !error;
+}
+
/* bfin ELF linker hash entry. */
struct bfin_link_hash_entry
@@ -2192,7 +4934,7 @@ struct bfin_link_hash_table
static struct bfd_hash_entry *
bfin_link_hash_newfunc (struct bfd_hash_entry *entry,
- struct bfd_hash_table *table, const char *string)
+ struct bfd_hash_table *table, const char *string)
{
struct bfd_hash_entry *ret = entry;
@@ -2219,12 +4961,13 @@ bfin_link_hash_table_create (bfd * abfd)
struct bfin_link_hash_table *ret;
bfd_size_type amt = sizeof (struct bfin_link_hash_table);
- ret = (struct bfin_link_hash_table *) bfd_malloc (amt);
- if (ret == (struct bfin_link_hash_table *) NULL)
+ ret = bfd_zalloc (abfd, amt);
+ if (ret == NULL)
return NULL;
if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
- bfin_link_hash_newfunc))
+ bfin_link_hash_newfunc,
+ sizeof (struct elf_link_hash_entry)))
{
free (ret);
return NULL;
@@ -2511,9 +5254,6 @@ bfin_discard_copies (struct elf_link_hash_entry *h, PTR inf)
return TRUE;
}
-/* Set the sizes of the dynamic sections. */
-#define ELF_DYNAMIC_INTERPRETER "/usr/lib/libc.so.1"
-
static bfd_boolean
bfin_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
struct bfd_link_info *info)
@@ -2659,7 +5399,7 @@ bfin_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
return TRUE;
}
-
+
/* Given a .data section and a .emreloc in-memory section, store
relocation information into the .emreloc section which can be
used at runtime to relocate the section. This is called by the
@@ -2667,6 +5407,9 @@ bfin_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
after the add_symbols entry point has been called for all the
objects, and before the final_link entry point is called. */
+bfd_boolean bfd_bfin_elf32_create_embedded_relocs
+ PARAMS ((bfd *, struct bfd_link_info *, asection *, asection *, char **));
+
bfd_boolean
bfd_bfin_elf32_create_embedded_relocs (
bfd *abfd,
@@ -2782,17 +5525,18 @@ error_return:
free (internal_relocs);
return FALSE;
}
-
+
#define TARGET_LITTLE_SYM bfd_elf32_bfin_vec
#define TARGET_LITTLE_NAME "elf32-bfin"
#define ELF_ARCH bfd_arch_bfin
-#define ELF_MACHINE_CODE EM_BLACKFIN
+#define ELF_MACHINE_CODE EM_BLACKFIN
#define ELF_MAXPAGESIZE 0x1000
#define elf_symbol_leading_char '_'
#define bfd_elf32_bfd_reloc_type_lookup bfin_bfd_reloc_type_lookup
#define elf_info_to_howto bfin_info_to_howto
#define elf_info_to_howto_rel 0
+#define elf_backend_object_p elf32_bfin_object_p
#define bfd_elf32_bfd_is_local_label_name \
bfin_is_local_label_name
@@ -2807,7 +5551,7 @@ error_return:
bfin_link_hash_table_create
#define bfd_elf32_bfd_final_link bfd_elf_gc_common_final_link
-#define elf_backend_check_relocs bfin_check_relocs
+#define elf_backend_check_relocs bfin_check_relocs
#define elf_backend_adjust_dynamic_symbol \
bfin_adjust_dynamic_symbol
#define elf_backend_size_dynamic_sections \
@@ -2834,5 +5578,74 @@ error_return:
#define elf_backend_got_header_size 12
#define elf_backend_rela_normal 1
+#include "elf32-target.h"
+
+#undef TARGET_LITTLE_SYM
+#define TARGET_LITTLE_SYM bfd_elf32_bfinfdpic_vec
+#undef TARGET_LITTLE_NAME
+#define TARGET_LITTLE_NAME "elf32-bfinfdpic"
+#undef elf32_bed
+#define elf32_bed elf32_bfinfdpic_bed
+
+#undef elf_backend_gc_sweep_hook
+#define elf_backend_gc_sweep_hook bfinfdpic_gc_sweep_hook
+
+#undef elf_backend_got_header_size
+#define elf_backend_got_header_size 0
+
+#undef elf_backend_relocate_section
+#define elf_backend_relocate_section bfinfdpic_relocate_section
+#undef elf_backend_check_relocs
+#define elf_backend_check_relocs bfinfdpic_check_relocs
+
+#undef bfd_elf32_bfd_link_hash_table_create
+#define bfd_elf32_bfd_link_hash_table_create \
+ bfinfdpic_elf_link_hash_table_create
+#undef elf_backend_always_size_sections
+#define elf_backend_always_size_sections \
+ elf32_bfinfdpic_always_size_sections
+#undef elf_backend_modify_segment_map
+#define elf_backend_modify_segment_map \
+ elf32_bfinfdpic_modify_segment_map
+#undef bfd_elf32_bfd_copy_private_bfd_data
+#define bfd_elf32_bfd_copy_private_bfd_data \
+ elf32_bfinfdpic_copy_private_bfd_data
+
+#undef elf_backend_create_dynamic_sections
+#define elf_backend_create_dynamic_sections \
+ elf32_bfinfdpic_create_dynamic_sections
+#undef elf_backend_adjust_dynamic_symbol
+#define elf_backend_adjust_dynamic_symbol \
+ elf32_bfinfdpic_adjust_dynamic_symbol
+#undef elf_backend_size_dynamic_sections
+#define elf_backend_size_dynamic_sections \
+ elf32_bfinfdpic_size_dynamic_sections
+#undef elf_backend_finish_dynamic_symbol
+#define elf_backend_finish_dynamic_symbol \
+ elf32_bfinfdpic_finish_dynamic_symbol
+#undef elf_backend_finish_dynamic_sections
+#define elf_backend_finish_dynamic_sections \
+ elf32_bfinfdpic_finish_dynamic_sections
+
+#undef elf_backend_can_make_relative_eh_frame
+#define elf_backend_can_make_relative_eh_frame \
+ bfinfdpic_elf_use_relative_eh_frame
+#undef elf_backend_can_make_lsda_relative_eh_frame
+#define elf_backend_can_make_lsda_relative_eh_frame \
+ bfinfdpic_elf_use_relative_eh_frame
+#undef elf_backend_encode_eh_address
+#define elf_backend_encode_eh_address \
+ bfinfdpic_elf_encode_eh_address
+
+#undef elf_backend_may_use_rel_p
+#define elf_backend_may_use_rel_p 1
+#undef elf_backend_may_use_rela_p
+#define elf_backend_may_use_rela_p 1
+/* We use REL for dynamic relocations only. */
+#undef elf_backend_default_use_rela_p
+#define elf_backend_default_use_rela_p 1
+
+#undef elf_backend_omit_section_dynsym
+#define elf_backend_omit_section_dynsym _bfinfdpic_link_omit_section_dynsym
#include "elf32-target.h"
diff --git a/bfd/elf32-cris.c b/bfd/elf32-cris.c
index 3edabc7..4019e34 100644
--- a/bfd/elf32-cris.c
+++ b/bfd/elf32-cris.c
@@ -1,5 +1,5 @@
/* CRIS-specific support for 32-bit ELF.
- Copyright 2000, 2001, 2002, 2003, 2004, 2005
+ Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
Contributed by Axis Communications AB.
Written by Hans-Peter Nilsson, based on elf32-fr30.c
@@ -849,8 +849,9 @@ elf_cris_link_hash_table_create (abfd)
if (ret == (struct elf_cris_link_hash_table *) NULL)
return NULL;
- if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
- elf_cris_link_hash_newfunc))
+ if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
+ elf_cris_link_hash_newfunc,
+ sizeof (struct elf_cris_link_hash_entry)))
{
free (ret);
return NULL;
diff --git a/bfd/elf32-frv.c b/bfd/elf32-frv.c
index 7126ed4..1758e27 100644
--- a/bfd/elf32-frv.c
+++ b/bfd/elf32-frv.c
@@ -1,5 +1,5 @@
/* FRV-specific support for 32-bit ELF.
- Copyright 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
@@ -1008,8 +1008,9 @@ frvfdpic_elf_link_hash_table_create (bfd *abfd)
if (ret == NULL)
return NULL;
- if (! _bfd_elf_link_hash_table_init (&ret->elf, abfd,
- _bfd_elf_link_hash_newfunc))
+ if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd,
+ _bfd_elf_link_hash_newfunc,
+ sizeof (struct elf_link_hash_entry)))
{
free (ret);
return NULL;
diff --git a/bfd/elf32-hppa.c b/bfd/elf32-hppa.c
index b5d6714..51c210e 100644
--- a/bfd/elf32-hppa.c
+++ b/bfd/elf32-hppa.c
@@ -394,14 +394,16 @@ elf32_hppa_link_hash_table_create (bfd *abfd)
if (htab == NULL)
return NULL;
- if (!_bfd_elf_link_hash_table_init (&htab->etab, abfd, hppa_link_hash_newfunc))
+ if (!_bfd_elf_link_hash_table_init (&htab->etab, abfd, hppa_link_hash_newfunc,
+ sizeof (struct elf32_hppa_link_hash_entry)))
{
free (htab);
return NULL;
}
/* Init the stub hash table too. */
- if (!bfd_hash_table_init (&htab->bstab, stub_hash_newfunc))
+ if (!bfd_hash_table_init (&htab->bstab, stub_hash_newfunc,
+ sizeof (struct elf32_hppa_stub_hash_entry)))
return NULL;
htab->stub_bfd = NULL;
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index c14fc3b..bc44cba 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -721,7 +721,8 @@ elf_i386_link_hash_table_create (bfd *abfd)
if (ret == NULL)
return NULL;
- if (! _bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc))
+ if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc,
+ sizeof (struct elf_i386_link_hash_entry)))
{
free (ret);
return NULL;
diff --git a/bfd/elf32-m32r.c b/bfd/elf32-m32r.c
index aecf0fe..6c42c2f 100644
--- a/bfd/elf32-m32r.c
+++ b/bfd/elf32-m32r.c
@@ -1572,8 +1572,9 @@ m32r_elf_link_hash_table_create (bfd *abfd)
if (ret == NULL)
return NULL;
- if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
- m32r_elf_link_hash_newfunc))
+ if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
+ m32r_elf_link_hash_newfunc,
+ sizeof (struct elf_m32r_link_hash_entry)))
{
free (ret);
return NULL;
diff --git a/bfd/elf32-m68hc1x.c b/bfd/elf32-m68hc1x.c
index bf34694..e7fb944 100644
--- a/bfd/elf32-m68hc1x.c
+++ b/bfd/elf32-m68hc1x.c
@@ -1,5 +1,5 @@
/* Motorola 68HC11/HC12-specific support for 32-bit ELF
- Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005
+ Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
Contributed by Stephane Carrez (stcarrez@nerim.fr)
@@ -70,8 +70,9 @@ m68hc11_elf_hash_table_create (bfd *abfd)
return NULL;
memset (ret, 0, amt);
- if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
- _bfd_elf_link_hash_newfunc))
+ if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
+ _bfd_elf_link_hash_newfunc,
+ sizeof (struct elf_link_hash_entry)))
{
free (ret);
return NULL;
@@ -85,7 +86,8 @@ m68hc11_elf_hash_table_create (bfd *abfd)
free (ret);
return NULL;
}
- if (!bfd_hash_table_init (ret->stub_hash_table, stub_hash_newfunc))
+ if (!bfd_hash_table_init (ret->stub_hash_table, stub_hash_newfunc,
+ sizeof (struct elf32_m68hc11_stub_hash_entry)))
return NULL;
ret->stub_bfd = NULL;
diff --git a/bfd/elf32-m68k.c b/bfd/elf32-m68k.c
index 98b0b12..df988a8 100644
--- a/bfd/elf32-m68k.c
+++ b/bfd/elf32-m68k.c
@@ -361,8 +361,9 @@ elf_m68k_link_hash_table_create (abfd)
if (ret == (struct elf_m68k_link_hash_table *) NULL)
return NULL;
- if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
- elf_m68k_link_hash_newfunc))
+ if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
+ elf_m68k_link_hash_newfunc,
+ sizeof (struct elf_m68k_link_hash_entry)))
{
free (ret);
return NULL;
@@ -390,18 +391,22 @@ elf32_m68k_object_p (bfd *abfd)
{
switch (eflags & EF_M68K_ISA_MASK)
{
- case EF_M68K_ISA_B:
- features |= mcfisa_b;
- /* FALLTHROUGH */
- case EF_M68K_ISA_A_PLUS:
- features |= mcfisa_aa;
- /* FALLTHROUGH */
- case EF_M68K_ISA_A:
+ case EF_M68K_ISA_A_NODIV:
features |= mcfisa_a;
break;
+ case EF_M68K_ISA_A:
+ features |= mcfisa_a|mcfhwdiv;
+ break;
+ case EF_M68K_ISA_A_PLUS:
+ features |= mcfisa_a|mcfisa_aa|mcfhwdiv|mcfusp;
+ break;
+ case EF_M68K_ISA_B_NOUSP:
+ features |= mcfisa_a|mcfisa_b|mcfhwdiv;
+ break;
+ case EF_M68K_ISA_B:
+ features |= mcfisa_a|mcfisa_b|mcfhwdiv|mcfusp;
+ break;
}
- if (eflags & EF_M68K_HW_DIV)
- features |= mcfhwdiv;
switch (eflags & EF_M68K_MAC_MASK)
{
case EF_M68K_MAC:
@@ -411,8 +416,6 @@ elf32_m68k_object_p (bfd *abfd)
features |= mcfemac;
break;
}
- if (eflags & EF_M68K_USP)
- features |= mcfusp;
if (eflags & EF_M68K_FLOAT)
features |= cfloat;
}
@@ -443,39 +446,24 @@ elf32_m68k_merge_private_bfd_data (ibfd, obfd)
{
flagword out_flags;
flagword in_flags;
- unsigned in_mach, out_mach;
+ flagword out_isa;
+ flagword in_isa;
+ const bfd_arch_info_type *arch_info;
if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour
|| bfd_get_flavour (obfd) != bfd_target_elf_flavour)
return FALSE;
- in_mach = bfd_get_mach (ibfd);
- out_mach = bfd_get_mach (obfd);
- if (!out_mach || !in_mach)
- /* One is unknown, copy the input machine. */
- out_mach = in_mach;
- else if (in_mach != out_mach)
- {
- if (in_mach <= bfd_mach_m68060 && out_mach <= bfd_mach_m68060)
- {
- /* Merge m68k machine. */
- if (in_mach > out_mach)
- out_mach = in_mach;
- }
- else if (in_mach >= bfd_mach_mcf_isa_a && out_mach >= bfd_mach_mcf_isa_a)
- /* Merge cf machine. */
- out_mach = bfd_m68k_features_to_mach
- (bfd_m68k_mach_to_features (in_mach)
- | bfd_m68k_mach_to_features (out_mach));
- else
- /* They are incompatible. */
- return FALSE;
- }
- bfd_set_arch_mach (obfd, bfd_arch_m68k, out_mach);
-
- in_flags = elf_elfheader (ibfd)->e_flags;
- out_flags = elf_elfheader (obfd)->e_flags;
+ /* Get the merged machine. This checks for incompatibility between
+ Coldfire & non-Coldfire flags, incompability between different
+ Coldfire ISAs, and incompability between different MAC types. */
+ arch_info = bfd_arch_get_compatible (ibfd, obfd, FALSE);
+ if (!arch_info)
+ return FALSE;
+ bfd_set_arch_mach (obfd, bfd_arch_m68k, arch_info->mach);
+
+ in_flags = elf_elfheader (ibfd)->e_flags;
if (!elf_flags_init (obfd))
{
elf_flags_init (obfd) = TRUE;
@@ -483,44 +471,12 @@ elf32_m68k_merge_private_bfd_data (ibfd, obfd)
}
else
{
- /* Copy legacy flags. */
- out_flags |= in_flags & (EF_M68K_CPU32 | EF_M68K_M68000 | EF_M68K_CFV4E);
-
- if (((in_flags | out_flags) & EF_M68K_ISA_MASK)
- && ((in_flags | out_flags) & (EF_M68K_CPU32 | EF_M68K_M68000)))
- /* Mixing m68k and cf is not allowed */
- return FALSE;
-
- if (in_flags & EF_M68K_ISA_MASK)
- {
- if (out_flags & EF_M68K_ISA_MASK)
- {
- /* Merge cf specific flags */
- if ((in_flags & EF_M68K_ISA_MASK)
- > (out_flags & EF_M68K_ISA_MASK))
- {
- out_flags ^= out_flags & EF_M68K_ISA_MASK;
- out_flags |= in_flags & EF_M68K_ISA_MASK;
- }
- out_flags |= in_flags
- & (EF_M68K_HW_DIV | EF_M68K_USP | EF_M68K_FLOAT);
- if (in_flags & EF_M68K_MAC_MASK)
- {
- if (!(out_flags & EF_M68K_MAC_MASK))
- out_flags |= in_flags & EF_M68K_MAC_MASK;
- else if ((out_flags & EF_M68K_MAC_MASK)
- != (in_flags & EF_M68K_MAC_MASK))
- /* Cannot mix MACs */
- return FALSE;
- }
- }
- else
- {
- /* Copy the coldfire bits. */
- out_flags &= ~EF_M68K_CF_MASK;
- out_flags |= in_flags & EF_M68K_CF_MASK;
- }
- }
+ out_flags = elf_elfheader (obfd)->e_flags;
+ in_isa = (in_flags & EF_M68K_ISA_MASK);
+ out_isa = (out_flags & EF_M68K_ISA_MASK);
+ if (in_isa > out_isa)
+ out_flags ^= in_isa ^ out_isa;
+ out_flags |= in_flags ^ in_isa;
}
elf_elfheader (obfd)->e_flags = out_flags;
@@ -559,22 +515,31 @@ elf32_m68k_print_private_bfd_data (abfd, ptr)
{
char const *isa = _("unknown");
char const *mac = _("unknown");
+ char const *additional = "";
switch (eflags & EF_M68K_ISA_MASK)
{
+ case EF_M68K_ISA_A_NODIV:
+ isa = "A";
+ additional = " [nodiv]";
+ break;
case EF_M68K_ISA_A:
isa = "A";
break;
case EF_M68K_ISA_A_PLUS:
isa = "A+";
break;
+ case EF_M68K_ISA_B_NOUSP:
+ isa = "B";
+ additional = " [nousp]";
+ break;
case EF_M68K_ISA_B:
isa = "B";
break;
}
- fprintf (file, " [isa %s]", isa);
- if (eflags & EF_M68K_HW_DIV)
- fprintf (file, " [hwdiv]");
+ fprintf (file, " [isa %s]%s", isa, additional);
+ if (eflags & EF_M68K_FLOAT)
+ fprintf (file, " [float]");
switch (eflags & EF_M68K_MAC_MASK)
{
case 0:
@@ -589,10 +554,6 @@ elf32_m68k_print_private_bfd_data (abfd, ptr)
}
if (mac)
fprintf (file, " [%s]", mac);
- if (eflags & EF_M68K_USP)
- fprintf (file, " [usp");
- if (eflags & EF_M68K_FLOAT)
- fprintf (file, " [float]");
}
fputc ('\n', file);
diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c
index 3cdaeee..6ed4ad3 100644
--- a/bfd/elf32-mips.c
+++ b/bfd/elf32-mips.c
@@ -37,6 +37,7 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
#include "elf-bfd.h"
#include "elfxx-mips.h"
#include "elf/mips.h"
+#include "elf-vxworks.h"
/* Get the ECOFF swapping routines. */
#include "coff/sym.h"
@@ -1319,10 +1320,12 @@ mips_elf32_rtype_to_howto (unsigned int r_type,
static void
mips_info_to_howto_rel (bfd *abfd, arelent *cache_ptr, Elf_Internal_Rela *dst)
{
+ const struct elf_backend_data *bed;
unsigned int r_type;
r_type = ELF32_R_TYPE (dst->r_info);
- cache_ptr->howto = mips_elf32_rtype_to_howto (r_type, FALSE);
+ bed = get_elf_backend_data (abfd);
+ cache_ptr->howto = bed->elf_backend_mips_rtype_to_howto (r_type, FALSE);
/* The addend for a GPREL16 or LITERAL relocation comes from the GP
value for the object file. We get the addend now, rather than
@@ -1619,3 +1622,147 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap = {
/* Include the target file again for this target. */
#include "elf32-target.h"
+
+
+/* Specific to VxWorks. */
+static reloc_howto_type mips_vxworks_copy_howto_rela =
+ HOWTO (R_MIPS_COPY, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_COPY", /* name */
+ FALSE, /* partial_inplace */
+ 0x0, /* src_mask */
+ 0x0, /* dst_mask */
+ FALSE); /* pcrel_offset */
+
+/* Specific to VxWorks. */
+static reloc_howto_type mips_vxworks_jump_slot_howto_rela =
+ HOWTO (R_MIPS_JUMP_SLOT, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_JUMP_SLOT", /* name */
+ FALSE, /* partial_inplace */
+ 0x0, /* src_mask */
+ 0x0, /* dst_mask */
+ FALSE); /* pcrel_offset */
+
+/* Implement elf_backend_bfd_reloc_type_lookup for VxWorks. */
+
+static reloc_howto_type *
+mips_vxworks_bfd_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code)
+{
+ switch (code)
+ {
+ case BFD_RELOC_MIPS_COPY:
+ return &mips_vxworks_copy_howto_rela;
+ case BFD_RELOC_MIPS_JUMP_SLOT:
+ return &mips_vxworks_jump_slot_howto_rela;
+ default:
+ return bfd_elf32_bfd_reloc_type_lookup (abfd, code);
+ }
+}
+
+/* Implement elf_backend_mips_rtype_to_lookup for VxWorks. */
+
+static reloc_howto_type *
+mips_vxworks_rtype_to_howto (unsigned int r_type, bfd_boolean rela_p)
+{
+ switch (r_type)
+ {
+ case R_MIPS_COPY:
+ return &mips_vxworks_copy_howto_rela;
+ case R_MIPS_JUMP_SLOT:
+ return &mips_vxworks_jump_slot_howto_rela;
+ default:
+ return mips_elf32_rtype_to_howto (r_type, rela_p);
+ }
+}
+
+/* Implement elf_backend_final_write_processing for VxWorks. */
+
+static void
+mips_vxworks_final_write_processing (bfd *abfd, bfd_boolean linker)
+{
+ _bfd_mips_elf_final_write_processing (abfd, linker);
+ elf_vxworks_final_write_processing (abfd, linker);
+}
+
+#undef TARGET_LITTLE_SYM
+#undef TARGET_LITTLE_NAME
+#undef TARGET_BIG_SYM
+#undef TARGET_BIG_NAME
+
+#define TARGET_LITTLE_SYM bfd_elf32_littlemips_vxworks_vec
+#define TARGET_LITTLE_NAME "elf32-littlemips-vxworks"
+#define TARGET_BIG_SYM bfd_elf32_bigmips_vxworks_vec
+#define TARGET_BIG_NAME "elf32-bigmips-vxworks"
+
+#undef elf32_bed
+#define elf32_bed elf32_mips_vxworks_bed
+
+#undef ELF_MAXPAGESIZE
+#define ELF_MAXPAGESIZE 0x1000
+
+#undef elf_backend_want_got_plt
+#define elf_backend_want_got_plt 1
+#undef elf_backend_want_plt_sym
+#define elf_backend_want_plt_sym 1
+#undef elf_backend_got_symbol_offset
+#define elf_backend_got_symbol_offset 0
+#undef elf_backend_want_dynbss
+#define elf_backend_want_dynbss 1
+#undef elf_backend_may_use_rel_p
+#define elf_backend_may_use_rel_p 0
+#undef elf_backend_may_use_rela_p
+#define elf_backend_may_use_rela_p 1
+#undef elf_backend_default_use_rela_p
+#define elf_backend_default_use_rela_p 1
+#undef elf_backend_got_header_size
+#define elf_backend_got_header_size (4 * 3)
+#undef elf_backend_plt_readonly
+#define elf_backend_plt_readonly 1
+
+#undef bfd_elf32_bfd_reloc_type_lookup
+#define bfd_elf32_bfd_reloc_type_lookup \
+ mips_vxworks_bfd_reloc_type_lookup
+#undef elf_backend_mips_rtype_to_howto
+#define elf_backend_mips_rtype_to_howto \
+ mips_vxworks_rtype_to_howto
+#undef elf_backend_adjust_dynamic_symbol
+#define elf_backend_adjust_dynamic_symbol \
+ _bfd_mips_vxworks_adjust_dynamic_symbol
+#undef elf_backend_finish_dynamic_symbol
+#define elf_backend_finish_dynamic_symbol \
+ _bfd_mips_vxworks_finish_dynamic_symbol
+#undef bfd_elf32_bfd_link_hash_table_create
+#define bfd_elf32_bfd_link_hash_table_create \
+ _bfd_mips_vxworks_link_hash_table_create
+#undef elf_backend_add_symbol_hook
+#define elf_backend_add_symbol_hook \
+ elf_vxworks_add_symbol_hook
+#undef elf_backend_link_output_symbol_hook
+#define elf_backend_link_output_symbol_hook \
+ elf_vxworks_link_output_symbol_hook
+#undef elf_backend_emit_relocs
+#define elf_backend_emit_relocs \
+ elf_vxworks_emit_relocs
+#undef elf_backend_final_write_processing
+#define elf_backend_final_write_processing \
+ mips_vxworks_final_write_processing
+
+#undef elf_backend_additional_program_headers
+#undef elf_backend_modify_segment_map
+#undef elf_backend_symbol_processing
+/* NOTE: elf_backend_rela_normal is not defined for MIPS. */
+
+#include "elf32-target.h"
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index b3d8308..6a2d517 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -1,6 +1,6 @@
/* PowerPC-specific support for 32-bit ELF
Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
- 2004, 2005 Free Software Foundation, Inc.
+ 2004, 2005, 2006 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support.
This file is part of BFD, the Binary File Descriptor library.
@@ -2430,8 +2430,9 @@ ppc_elf_link_hash_table_create (bfd *abfd)
if (ret == NULL)
return NULL;
- if (! _bfd_elf_link_hash_table_init (&ret->elf, abfd,
- ppc_elf_link_hash_newfunc))
+ if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd,
+ ppc_elf_link_hash_newfunc,
+ sizeof (struct ppc_elf_link_hash_entry)))
{
free (ret);
return NULL;
@@ -3335,7 +3336,9 @@ ppc_elf_check_relocs (bfd *abfd,
if (s == got2)
htab->plt_type = PLT_OLD;
}
- /* fall through */
+ if (h == NULL || h == htab->elf.hgot)
+ break;
+ goto dodyn1;
case R_PPC_REL24:
case R_PPC_REL14:
@@ -3343,9 +3346,10 @@ ppc_elf_check_relocs (bfd *abfd,
case R_PPC_REL14_BRNTAKEN:
if (h == NULL)
break;
- if (h == htab->elf.hgot && htab->plt_type == PLT_UNSET)
+ if (h == htab->elf.hgot)
{
- htab->plt_type = PLT_OLD;
+ if (htab->plt_type == PLT_UNSET)
+ htab->plt_type = PLT_OLD;
break;
}
/* fall through */
@@ -3361,6 +3365,7 @@ ppc_elf_check_relocs (bfd *abfd,
case R_PPC_ADDR14_BRNTAKEN:
case R_PPC_UADDR32:
case R_PPC_UADDR16:
+ dodyn1:
if (h != NULL && !info->shared)
{
/* We may need a plt entry if the symbol turns out to be
@@ -5763,6 +5768,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
insn1 |= 32 << 26; /* lwz */
insn2 = 0x7c631214; /* add 3,3,2 */
rel[1].r_info = ELF32_R_INFO (r_symndx2, R_PPC_NONE);
+ rel[1].r_addend = 0;
r_type = (((r_type - (R_PPC_GOT_TLSGD16 & 3)) & 3)
+ R_PPC_GOT_TPREL16);
rel->r_info = ELF32_R_INFO (r_symndx, r_type);
@@ -5777,13 +5783,13 @@ ppc_elf_relocate_section (bfd *output_bfd,
/* Was an LD reloc. */
r_symndx = 0;
rel->r_addend = htab->elf.tls_sec->vma + DTP_OFFSET;
- rel[1].r_addend = htab->elf.tls_sec->vma + DTP_OFFSET;
}
r_type = R_PPC_TPREL16_HA;
rel->r_info = ELF32_R_INFO (r_symndx, r_type);
rel[1].r_info = ELF32_R_INFO (r_symndx,
R_PPC_TPREL16_LO);
rel[1].r_offset += 2;
+ rel[1].r_addend = rel->r_addend;
}
bfd_put_32 (output_bfd, insn1, contents + rel->r_offset - 2);
bfd_put_32 (output_bfd, insn2, contents + offset);
diff --git a/bfd/elf32-s390.c b/bfd/elf32-s390.c
index 1c52755..eb8e172 100644
--- a/bfd/elf32-s390.c
+++ b/bfd/elf32-s390.c
@@ -771,7 +771,8 @@ elf_s390_link_hash_table_create (abfd)
if (ret == NULL)
return NULL;
- if (! _bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc))
+ if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc,
+ sizeof (struct elf_s390_link_hash_entry)))
{
free (ret);
return NULL;
diff --git a/bfd/elf32-sh.c b/bfd/elf32-sh.c
index d03f60b..118690d 100644
--- a/bfd/elf32-sh.c
+++ b/bfd/elf32-sh.c
@@ -3612,8 +3612,9 @@ sh_elf_link_hash_table_create (bfd *abfd)
if (ret == (struct elf_sh_link_hash_table *) NULL)
return NULL;
- if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
- sh_elf_link_hash_newfunc))
+ if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
+ sh_elf_link_hash_newfunc,
+ sizeof (struct elf_sh_link_hash_entry)))
{
free (ret);
return NULL;
diff --git a/bfd/elf32-vax.c b/bfd/elf32-vax.c
index e0d059c..bf481e4 100644
--- a/bfd/elf32-vax.c
+++ b/bfd/elf32-vax.c
@@ -1,6 +1,6 @@
/* VAX series support for 32-bit ELF
Copyright 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
- 2004, 2005 Free Software Foundation, Inc.
+ 2004, 2005, 2006 Free Software Foundation, Inc.
Contributed by Matt Thomas <matt@3am-software.com>.
This file is part of BFD, the Binary File Descriptor library.
@@ -468,8 +468,9 @@ elf_vax_link_hash_table_create (bfd *abfd)
if (ret == NULL)
return NULL;
- if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
- elf_vax_link_hash_newfunc))
+ if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
+ elf_vax_link_hash_newfunc,
+ sizeof (struct elf_vax_link_hash_entry)))
{
free (ret);
return NULL;
diff --git a/bfd/elf32-xtensa.c b/bfd/elf32-xtensa.c
index 18610c7..4dce0ea 100644
--- a/bfd/elf32-xtensa.c
+++ b/bfd/elf32-xtensa.c
@@ -640,7 +640,6 @@ xtensa_read_table_entries (bfd *abfd,
{
bfd_vma sym_off = get_elf_r_symndx_offset (abfd, r_symndx);
BFD_ASSERT (sym_off == 0);
- BFD_ASSERT (rel->r_addend == 0);
blocks[block_count].address =
(section_addr + sym_off + rel->r_addend
+ bfd_get_32 (abfd, table_data + rel->r_offset));
diff --git a/bfd/elf64-alpha.c b/bfd/elf64-alpha.c
index 60deadb..76d0661 100644
--- a/bfd/elf64-alpha.c
+++ b/bfd/elf64-alpha.c
@@ -1,6 +1,6 @@
/* Alpha specific support for 64-bit ELF
- Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
- Free Software Foundation, Inc.
+ Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+ 2006 Free Software Foundation, Inc.
Contributed by Richard Henderson <rth@tamu.edu>.
This file is part of BFD, the Binary File Descriptor library.
@@ -273,8 +273,9 @@ elf64_alpha_bfd_link_hash_table_create (bfd *abfd)
if (ret == (struct alpha_elf_link_hash_table *) NULL)
return NULL;
- if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
- elf64_alpha_link_hash_newfunc))
+ if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
+ elf64_alpha_link_hash_newfunc,
+ sizeof (struct alpha_elf_link_hash_entry)))
{
free (ret);
return NULL;
diff --git a/bfd/elf64-hppa.c b/bfd/elf64-hppa.c
index fbd6458..4e0b83c 100644
--- a/bfd/elf64-hppa.c
+++ b/bfd/elf64-hppa.c
@@ -1,5 +1,5 @@
/* Support for HPPA 64-bit ELF
- Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005
+ Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
@@ -157,9 +157,6 @@ struct elf64_hppa_link_hash_table
typedef struct bfd_hash_entry *(*new_hash_entry_func)
PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
-static bfd_boolean elf64_hppa_dyn_hash_table_init
- PARAMS ((struct elf64_hppa_dyn_hash_table *ht, bfd *abfd,
- new_hash_entry_func new));
static struct bfd_hash_entry *elf64_hppa_new_dyn_hash_entry
PARAMS ((struct bfd_hash_entry *entry, struct bfd_hash_table *table,
const char *string));
@@ -276,13 +273,13 @@ static int elf64_hppa_elf_get_symbol_type
PARAMS ((Elf_Internal_Sym *, int));
static bfd_boolean
-elf64_hppa_dyn_hash_table_init (ht, abfd, new)
- struct elf64_hppa_dyn_hash_table *ht;
- bfd *abfd ATTRIBUTE_UNUSED;
- new_hash_entry_func new;
+elf64_hppa_dyn_hash_table_init (struct elf64_hppa_dyn_hash_table *ht,
+ bfd *abfd ATTRIBUTE_UNUSED,
+ new_hash_entry_func new,
+ unsigned int entsize)
{
memset (ht, 0, sizeof (*ht));
- return bfd_hash_table_init (&ht->root, new);
+ return bfd_hash_table_init (&ht->root, new, entsize);
}
static struct bfd_hash_entry*
@@ -328,14 +325,16 @@ elf64_hppa_hash_table_create (abfd)
if (!ret)
return 0;
if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
- _bfd_elf_link_hash_newfunc))
+ _bfd_elf_link_hash_newfunc,
+ sizeof (struct elf_link_hash_entry)))
{
bfd_release (abfd, ret);
return 0;
}
if (!elf64_hppa_dyn_hash_table_init (&ret->dyn_hash_table, abfd,
- elf64_hppa_new_dyn_hash_entry))
+ elf64_hppa_new_dyn_hash_entry,
+ sizeof (struct elf64_hppa_dyn_hash_entry)))
return 0;
return &ret->root.root;
}
@@ -1130,6 +1129,7 @@ allocate_global_data_opd (dyn_h, data)
/* We never need an opd entry for a symbol which is not
defined by this output file. */
if (h && (h->root.type == bfd_link_hash_undefined
+ || h->root.type == bfd_link_hash_undefweak
|| h->root.u.def.section->output_section == NULL))
dyn_h->want_opd = 0;
@@ -2703,7 +2703,7 @@ static const struct bfd_elf_special_section elf64_hppa_special_sections[] =
{ ".dlt", 4, 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_PARISC_SHORT },
{ ".sdata", 6, 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_PARISC_SHORT },
{ ".sbss", 5, 0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_PARISC_SHORT },
- { ".tbss", 5, 0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_PARISC_WEAKORDER },
+ { ".tbss", 5, 0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_HP_TLS },
{ NULL, 0, 0, 0, 0 }
};
@@ -2814,7 +2814,5 @@ const struct elf_size_info hppa64_elf_size_info =
#undef TARGET_BIG_NAME
#define TARGET_BIG_NAME "elf64-hppa-linux"
-#undef elf_backend_special_sections
-
#define INCLUDED_TARGET_FILE 1
#include "elf64-target.h"
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index 1cfac82..fc8c182 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -3464,18 +3464,21 @@ ppc64_elf_link_hash_table_create (bfd *abfd)
if (htab == NULL)
return NULL;
- if (! _bfd_elf_link_hash_table_init (&htab->elf, abfd, link_hash_newfunc))
+ if (!_bfd_elf_link_hash_table_init (&htab->elf, abfd, link_hash_newfunc,
+ sizeof (struct ppc_link_hash_entry)))
{
free (htab);
return NULL;
}
/* Init the stub hash table too. */
- if (!bfd_hash_table_init (&htab->stub_hash_table, stub_hash_newfunc))
+ if (!bfd_hash_table_init (&htab->stub_hash_table, stub_hash_newfunc,
+ sizeof (struct ppc_stub_hash_entry)))
return NULL;
/* And the branch hash table. */
- if (!bfd_hash_table_init (&htab->branch_hash_table, branch_hash_newfunc))
+ if (!bfd_hash_table_init (&htab->branch_hash_table, branch_hash_newfunc,
+ sizeof (struct ppc_branch_hash_entry)))
return NULL;
/* Initializing two fields of the union is just cosmetic. We really
diff --git a/bfd/elf64-s390.c b/bfd/elf64-s390.c
index 7beda9d..1fe0c6c 100644
--- a/bfd/elf64-s390.c
+++ b/bfd/elf64-s390.c
@@ -724,7 +724,8 @@ elf_s390_link_hash_table_create (abfd)
if (ret == NULL)
return NULL;
- if (! _bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc))
+ if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc,
+ sizeof (struct elf_s390_link_hash_entry)))
{
free (ret);
return NULL;
diff --git a/bfd/elf64-sh64.c b/bfd/elf64-sh64.c
index f76e916..4d6d8d5 100644
--- a/bfd/elf64-sh64.c
+++ b/bfd/elf64-sh64.c
@@ -1,5 +1,5 @@
/* SuperH SH64-specific support for 64-bit ELF
- Copyright 2000, 2001, 2002, 2003, 2004, 2005
+ Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
@@ -3138,8 +3138,9 @@ sh64_elf64_link_hash_table_create (bfd *abfd)
if (ret == (struct elf_sh64_link_hash_table *) NULL)
return NULL;
- if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
- sh64_elf64_link_hash_newfunc))
+ if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
+ sh64_elf64_link_hash_newfunc,
+ sizeof (struct elf_sh64_link_hash_entry)))
{
free (ret);
return NULL;
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 8c1a712..9befd69 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -31,8 +31,8 @@
#define MINUS_ONE (~ (bfd_vma) 0)
/* The relocation "howto" table. Order of fields:
- type, size, bitsize, pc_relative, complain_on_overflow,
- special_function, name, partial_inplace, src_mask, dst_pack, pcrel_offset. */
+ type, rightshift, size, bitsize, pc_relative, bitpos, complain_on_overflow,
+ special_function, name, partial_inplace, src_mask, dst_mask, pcrel_offset. */
static reloc_howto_type x86_64_elf_howto_table[] =
{
HOWTO(R_X86_64_NONE, 0, 0, 0, FALSE, 0, complain_overflow_dont,
@@ -112,11 +112,21 @@ static reloc_howto_type x86_64_elf_howto_table[] =
HOWTO(R_X86_64_GOTPC32, 0, 2, 32, TRUE, 0, complain_overflow_signed,
bfd_elf_generic_reloc, "R_X86_64_GOTPC32",
FALSE, 0xffffffff, 0xffffffff, TRUE),
- EMPTY_HOWTO (27),
- EMPTY_HOWTO (28),
- EMPTY_HOWTO (29),
- EMPTY_HOWTO (30),
- EMPTY_HOWTO (31),
+ HOWTO(R_X86_64_GOT64, 0, 4, 64, FALSE, 0, complain_overflow_signed,
+ bfd_elf_generic_reloc, "R_X86_64_GOT64", FALSE, MINUS_ONE, MINUS_ONE,
+ FALSE),
+ HOWTO(R_X86_64_GOTPCREL64, 0, 4, 64, TRUE, 0, complain_overflow_signed,
+ bfd_elf_generic_reloc, "R_X86_64_GOTPCREL64", FALSE, MINUS_ONE,
+ MINUS_ONE, TRUE),
+ HOWTO(R_X86_64_GOTPC64, 0, 4, 64, TRUE, 0, complain_overflow_signed,
+ bfd_elf_generic_reloc, "R_X86_64_GOTPC64",
+ FALSE, MINUS_ONE, MINUS_ONE, TRUE),
+ HOWTO(R_X86_64_GOTPLT64, 0, 4, 64, FALSE, 0, complain_overflow_signed,
+ bfd_elf_generic_reloc, "R_X86_64_GOTPLT64", FALSE, MINUS_ONE,
+ MINUS_ONE, FALSE),
+ HOWTO(R_X86_64_PLTOFF64, 0, 4, 64, FALSE, 0, complain_overflow_signed,
+ bfd_elf_generic_reloc, "R_X86_64_PLTOFF64", FALSE, MINUS_ONE,
+ MINUS_ONE, FALSE),
EMPTY_HOWTO (32),
EMPTY_HOWTO (33),
HOWTO(R_X86_64_GOTPC32_TLSDESC, 0, 2, 32, TRUE, 0,
@@ -185,6 +195,11 @@ static const struct elf_reloc_map x86_64_reloc_map[] =
{ BFD_RELOC_64_PCREL, R_X86_64_PC64, },
{ BFD_RELOC_X86_64_GOTOFF64, R_X86_64_GOTOFF64, },
{ BFD_RELOC_X86_64_GOTPC32, R_X86_64_GOTPC32, },
+ { BFD_RELOC_X86_64_GOT64, R_X86_64_GOT64, },
+ { BFD_RELOC_X86_64_GOTPCREL64,R_X86_64_GOTPCREL64, },
+ { BFD_RELOC_X86_64_GOTPC64, R_X86_64_GOTPC64, },
+ { BFD_RELOC_X86_64_GOTPLT64, R_X86_64_GOTPLT64, },
+ { BFD_RELOC_X86_64_PLTOFF64, R_X86_64_PLTOFF64, },
{ BFD_RELOC_X86_64_GOTPC32_TLSDESC, R_X86_64_GOTPC32_TLSDESC, },
{ BFD_RELOC_X86_64_TLSDESC_CALL, R_X86_64_TLSDESC_CALL, },
{ BFD_RELOC_X86_64_TLSDESC, R_X86_64_TLSDESC, },
@@ -510,7 +525,8 @@ elf64_x86_64_link_hash_table_create (bfd *abfd)
if (ret == NULL)
return NULL;
- if (! _bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc))
+ if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc,
+ sizeof (struct elf64_x86_64_link_hash_entry)))
{
free (ret);
return NULL;
@@ -776,6 +792,9 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec,
case R_X86_64_GOT32:
case R_X86_64_GOTPCREL:
case R_X86_64_TLSGD:
+ case R_X86_64_GOT64:
+ case R_X86_64_GOTPCREL64:
+ case R_X86_64_GOTPLT64:
case R_X86_64_GOTPC32_TLSDESC:
case R_X86_64_TLSDESC_CALL:
/* This symbol requires a global offset table entry. */
@@ -794,6 +813,14 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec,
if (h != NULL)
{
+ if (r_type == R_X86_64_GOTPLT64)
+ {
+ /* This relocation indicates that we also need
+ a PLT entry, as this is a function. We don't need
+ a PLT entry for local symbols. */
+ h->needs_plt = 1;
+ h->plt.refcount += 1;
+ }
h->got.refcount += 1;
old_tls_type = elf64_x86_64_hash_entry (h)->tls_type;
}
@@ -857,6 +884,7 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec,
case R_X86_64_GOTOFF64:
case R_X86_64_GOTPC32:
+ case R_X86_64_GOTPC64:
create_got:
if (htab->sgot == NULL)
{
@@ -884,6 +912,16 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec,
h->plt.refcount += 1;
break;
+ case R_X86_64_PLTOFF64:
+ /* This tries to form the 'address' of a function relative
+ to GOT. For global symbols we need a PLT entry. */
+ if (h != NULL)
+ {
+ h->needs_plt = 1;
+ h->plt.refcount += 1;
+ }
+ goto create_got;
+
case R_X86_64_8:
case R_X86_64_16:
case R_X86_64_32:
@@ -1188,8 +1226,13 @@ elf64_x86_64_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
case R_X86_64_GOTTPOFF:
case R_X86_64_GOT32:
case R_X86_64_GOTPCREL:
+ case R_X86_64_GOT64:
+ case R_X86_64_GOTPCREL64:
+ case R_X86_64_GOTPLT64:
if (h != NULL)
{
+ if (r_type == R_X86_64_GOTPLT64 && h->plt.refcount > 0)
+ h->plt.refcount -= 1;
if (h->got.refcount > 0)
h->got.refcount -= 1;
}
@@ -1214,6 +1257,7 @@ elf64_x86_64_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
/* Fall thru */
case R_X86_64_PLT32:
+ case R_X86_64_PLTOFF64:
if (h != NULL)
{
if (h->plt.refcount > 0)
@@ -2095,11 +2139,23 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
copied into the output file to be resolved at run time. */
switch (r_type)
{
+ asection *base_got;
case R_X86_64_GOT32:
+ case R_X86_64_GOT64:
/* Relocation is to the entry for this symbol in the global
offset table. */
case R_X86_64_GOTPCREL:
- /* Use global offset table as symbol value. */
+ case R_X86_64_GOTPCREL64:
+ /* Use global offset table entry as symbol value. */
+ case R_X86_64_GOTPLT64:
+ /* This is the same as GOT64 for relocation purposes, but
+ indicates the existence of a PLT entry. The difficulty is,
+ that we must calculate the GOT slot offset from the PLT
+ offset, if this symbol got a PLT entry (it was global).
+ Additionally if it's computed from the PLT entry, then that
+ GOT offset is relative to .got.plt, not to .got. */
+ base_got = htab->sgot;
+
if (htab->sgot == NULL)
abort ();
@@ -2108,6 +2164,19 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
bfd_boolean dyn;
off = h->got.offset;
+ if (h->needs_plt
+ && h->plt.offset != (bfd_vma)-1
+ && off == (bfd_vma)-1)
+ {
+ /* We can't use h->got.offset here to save
+ state, or even just remember the offset, as
+ finish_dynamic_symbol would use that as offset into
+ .got. */
+ bfd_vma plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1;
+ off = (plt_index + 3) * GOT_ENTRY_SIZE;
+ base_got = htab->sgotplt;
+ }
+
dyn = htab->elf.dynamic_sections_created;
if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
@@ -2132,7 +2201,9 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
else
{
bfd_put_64 (output_bfd, relocation,
- htab->sgot->contents + off);
+ base_got->contents + off);
+ /* Note that this is harmless for the GOTPLT64 case,
+ as -1 | 1 still is -1. */
h->got.offset |= 1;
}
}
@@ -2154,7 +2225,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
else
{
bfd_put_64 (output_bfd, relocation,
- htab->sgot->contents + off);
+ base_got->contents + off);
if (info->shared)
{
@@ -2168,8 +2239,8 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
if (s == NULL)
abort ();
- outrel.r_offset = (htab->sgot->output_section->vma
- + htab->sgot->output_offset
+ outrel.r_offset = (base_got->output_section->vma
+ + base_got->output_offset
+ off);
outrel.r_info = ELF64_R_INFO (0, R_X86_64_RELATIVE);
outrel.r_addend = relocation;
@@ -2185,9 +2256,9 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
if (off >= (bfd_vma) -2)
abort ();
- relocation = htab->sgot->output_section->vma
- + htab->sgot->output_offset + off;
- if (r_type != R_X86_64_GOTPCREL)
+ relocation = base_got->output_section->vma
+ + base_got->output_offset + off;
+ if (r_type != R_X86_64_GOTPCREL && r_type != R_X86_64_GOTPCREL64)
relocation -= htab->sgotplt->output_section->vma
- htab->sgotplt->output_offset;
@@ -2223,12 +2294,31 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
break;
case R_X86_64_GOTPC32:
+ case R_X86_64_GOTPC64:
/* Use global offset table as symbol value. */
relocation = htab->sgotplt->output_section->vma
+ htab->sgotplt->output_offset;
unresolved_reloc = FALSE;
break;
+ case R_X86_64_PLTOFF64:
+ /* Relocation is PLT entry relative to GOT. For local
+ symbols it's the symbol itself relative to GOT. */
+ if (h != NULL
+ /* See PLT32 handling. */
+ && h->plt.offset != (bfd_vma) -1
+ && htab->splt != NULL)
+ {
+ relocation = (htab->splt->output_section->vma
+ + htab->splt->output_offset
+ + h->plt.offset);
+ unresolved_reloc = FALSE;
+ }
+
+ relocation -= htab->sgotplt->output_section->vma
+ + htab->sgotplt->output_offset;
+ break;
+
case R_X86_64_PLT32:
/* Relocation is to the entry for this symbol in the
procedure linkage table. */
diff --git a/bfd/elflink.c b/bfd/elflink.c
index a95ac44..88e56da 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -26,6 +26,7 @@
#include "elf-bfd.h"
#include "safe-ctype.h"
#include "libiberty.h"
+#include "objalloc.h"
/* Define a symbol in a dynamic linkage section. */
@@ -2875,98 +2876,6 @@ elf_add_dt_needed_tag (bfd *abfd,
return 0;
}
-/* Called via elf_link_hash_traverse, elf_smash_syms sets all symbols
- belonging to NOT_NEEDED to bfd_link_hash_new. We know there are no
- references from regular objects to these symbols.
-
- ??? Should we do something about references from other dynamic
- obects? If not, we potentially lose some warnings about undefined
- symbols. But how can we recover the initial undefined / undefweak
- state? */
-
-struct elf_smash_syms_data
-{
- bfd *not_needed;
- struct elf_link_hash_table *htab;
- bfd_boolean twiddled;
-};
-
-static bfd_boolean
-elf_smash_syms (struct elf_link_hash_entry *h, void *data)
-{
- struct elf_smash_syms_data *inf = (struct elf_smash_syms_data *) data;
- struct bfd_link_hash_entry *bh;
-
- switch (h->root.type)
- {
- default:
- case bfd_link_hash_new:
- return TRUE;
-
- case bfd_link_hash_undefined:
- if (h->root.u.undef.abfd != inf->not_needed)
- return TRUE;
- if (h->root.u.undef.weak != NULL
- && h->root.u.undef.weak != inf->not_needed)
- {
- /* Symbol was undefweak in u.undef.weak bfd, and has become
- undefined in as-needed lib. Restore weak. */
- h->root.type = bfd_link_hash_undefweak;
- h->root.u.undef.abfd = h->root.u.undef.weak;
- if (h->root.u.undef.next != NULL
- || inf->htab->root.undefs_tail == &h->root)
- inf->twiddled = TRUE;
- return TRUE;
- }
- break;
-
- case bfd_link_hash_undefweak:
- if (h->root.u.undef.abfd != inf->not_needed)
- return TRUE;
- break;
-
- case bfd_link_hash_defined:
- case bfd_link_hash_defweak:
- if (h->root.u.def.section->owner != inf->not_needed)
- return TRUE;
- break;
-
- case bfd_link_hash_common:
- if (h->root.u.c.p->section->owner != inf->not_needed)
- return TRUE;
- break;
-
- case bfd_link_hash_warning:
- case bfd_link_hash_indirect:
- elf_smash_syms ((struct elf_link_hash_entry *) h->root.u.i.link, data);
- if (h->root.u.i.link->type != bfd_link_hash_new)
- return TRUE;
- if (h->root.u.i.link->u.undef.abfd != inf->not_needed)
- return TRUE;
- break;
- }
-
- /* There is no way we can undo symbol table state from defined or
- defweak back to undefined. */
- if (h->ref_regular)
- abort ();
-
- /* Set sym back to newly created state, but keep undef.next if it is
- being used as a list pointer. */
- bh = h->root.u.undef.next;
- if (bh == &h->root)
- bh = NULL;
- if (bh != NULL || inf->htab->root.undefs_tail == &h->root)
- inf->twiddled = TRUE;
- (*inf->htab->root.table.newfunc) (&h->root.root,
- &inf->htab->root.table,
- h->root.root.string);
- h->root.u.undef.next = bh;
- h->root.u.undef.abfd = inf->not_needed;
- h->non_elf = 0;
- return TRUE;
-}
-
/* Sort symbol by value and section. */
static int
elf_sort_symbol (const void *arg1, const void *arg2)
@@ -3136,14 +3045,6 @@ elf_finalize_dynstr (bfd *output_bfd, struct bfd_link_info *info)
static bfd_boolean
elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
{
- bfd_boolean (*add_symbol_hook)
- (bfd *, struct bfd_link_info *, Elf_Internal_Sym *,
- const char **, flagword *, asection **, bfd_vma *);
- bfd_boolean (*check_relocs)
- (bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *);
- bfd_boolean (*check_directives)
- (bfd *, struct bfd_link_info *);
- bfd_boolean collect;
Elf_Internal_Shdr *hdr;
bfd_size_type symcount;
bfd_size_type extsymcount;
@@ -3160,14 +3061,20 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
Elf_Internal_Sym *isymend;
const struct elf_backend_data *bed;
bfd_boolean add_needed;
- struct elf_link_hash_table * hash_table;
+ struct elf_link_hash_table *htab;
bfd_size_type amt;
+ void *alloc_mark = NULL;
+ void *old_tab = NULL;
+ void *old_hash;
+ void *old_ent;
+ struct bfd_link_hash_entry *old_undefs = NULL;
+ struct bfd_link_hash_entry *old_undefs_tail = NULL;
+ long old_dynsymcount = 0;
+ size_t tabsize = 0;
+ size_t hashsize = 0;
- hash_table = elf_hash_table (info);
-
+ htab = elf_hash_table (info);
bed = get_elf_backend_data (abfd);
- add_symbol_hook = bed->elf_add_symbol_hook;
- collect = bed->collect;
if ((abfd->flags & DYNAMIC) == 0)
dynamic = FALSE;
@@ -3179,8 +3086,8 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
hope of using a dynamic object which does not exactly match
the format of the output file. */
if (info->relocatable
- || !is_elf_hash_table (hash_table)
- || hash_table->root.creator != abfd->xvec)
+ || !is_elf_hash_table (htab)
+ || htab->root.creator != abfd->xvec)
{
if (info->relocatable)
bfd_set_error (bfd_error_invalid_operation);
@@ -3223,8 +3130,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
{
struct elf_link_hash_entry *h;
- h = elf_link_hash_lookup (hash_table, name,
- FALSE, FALSE, TRUE);
+ h = elf_link_hash_lookup (htab, name, FALSE, FALSE, TRUE);
/* FIXME: What about bfd_link_hash_common? */
if (h != NULL
@@ -3251,7 +3157,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
if (! (_bfd_generic_link_add_one_symbol
(info, abfd, name, BSF_WARNING, s, 0, msg,
- FALSE, collect, NULL)))
+ FALSE, bed->collect, NULL)))
goto error_return;
if (! info->relocatable)
@@ -3277,15 +3183,15 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
format. FIXME: If there are no input BFD's of the same
format as the output, we can't make a shared library. */
if (info->shared
- && is_elf_hash_table (hash_table)
- && hash_table->root.creator == abfd->xvec
- && ! hash_table->dynamic_sections_created)
+ && is_elf_hash_table (htab)
+ && htab->root.creator == abfd->xvec
+ && !htab->dynamic_sections_created)
{
if (! _bfd_elf_link_create_dynamic_sections (abfd, info))
goto error_return;
}
}
- else if (!is_elf_hash_table (hash_table))
+ else if (!is_elf_hash_table (htab))
goto error_return;
else
{
@@ -3360,9 +3266,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
n->name = anm;
n->by = abfd;
n->next = NULL;
- for (pn = & hash_table->needed;
- *pn != NULL;
- pn = &(*pn)->next)
+ for (pn = &htab->needed; *pn != NULL; pn = &(*pn)->next)
;
*pn = n;
}
@@ -3434,9 +3338,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
if (rpath)
{
struct bfd_link_needed_list **pn;
- for (pn = & hash_table->runpath;
- *pn != NULL;
- pn = &(*pn)->next)
+ for (pn = &htab->runpath; *pn != NULL; pn = &(*pn)->next)
;
*pn = rpath;
}
@@ -3544,8 +3446,70 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
}
}
- weaks = NULL;
+ /* If we are loading an as-needed shared lib, save the symbol table
+ state before we start adding symbols. If the lib turns out
+ to be unneeded, restore the state. */
+ if ((elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0)
+ {
+ unsigned int i;
+ size_t entsize;
+
+ for (entsize = 0, i = 0; i < htab->root.table.size; i++)
+ {
+ struct bfd_hash_entry *p;
+ struct elf_link_hash_entry *h;
+
+ for (p = htab->root.table.table[i]; p != NULL; p = p->next)
+ {
+ h = (struct elf_link_hash_entry *) p;
+ entsize += htab->root.table.entsize;
+ if (h->root.type == bfd_link_hash_warning)
+ entsize += htab->root.table.entsize;
+ }
+ }
+
+ tabsize = htab->root.table.size * sizeof (struct bfd_hash_entry *);
+ hashsize = extsymcount * sizeof (struct elf_link_hash_entry *);
+ old_tab = bfd_malloc (tabsize + entsize + hashsize);
+ if (old_tab == NULL)
+ goto error_free_vers;
+
+ /* Remember the current objalloc pointer, so that all mem for
+ symbols added can later be reclaimed. */
+ alloc_mark = bfd_hash_allocate (&htab->root.table, 1);
+ if (alloc_mark == NULL)
+ goto error_free_vers;
+
+ /* Clone the symbol table and sym hashes. Remember some
+ pointers into the symbol table, and dynamic symbol count. */
+ old_hash = (char *) old_tab + tabsize;
+ old_ent = (char *) old_hash + hashsize;
+ memcpy (old_tab, htab->root.table.table, tabsize);
+ memcpy (old_hash, sym_hash, hashsize);
+ old_undefs = htab->root.undefs;
+ old_undefs_tail = htab->root.undefs_tail;
+ old_dynsymcount = htab->dynsymcount;
+
+ for (i = 0; i < htab->root.table.size; i++)
+ {
+ struct bfd_hash_entry *p;
+ struct elf_link_hash_entry *h;
+
+ for (p = htab->root.table.table[i]; p != NULL; p = p->next)
+ {
+ memcpy (old_ent, p, htab->root.table.entsize);
+ old_ent = (char *) old_ent + htab->root.table.entsize;
+ h = (struct elf_link_hash_entry *) p;
+ if (h->root.type == bfd_link_hash_warning)
+ {
+ memcpy (old_ent, h->root.u.i.link, htab->root.table.entsize);
+ old_ent = (char *) old_ent + htab->root.table.entsize;
+ }
+ }
+ }
+ }
+ weaks = NULL;
ever = extversym != NULL ? extversym + extsymoff : NULL;
for (isym = isymbuf, isymend = isymbuf + extsymcount;
isym < isymend;
@@ -3597,7 +3561,8 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
if (isym->st_shndx == SHN_UNDEF)
sec = bfd_und_section_ptr;
- else if (isym->st_shndx < SHN_LORESERVE || isym->st_shndx > SHN_HIRESERVE)
+ else if (isym->st_shndx < SHN_LORESERVE
+ || isym->st_shndx > SHN_HIRESERVE)
{
sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
if (sec == NULL)
@@ -3608,8 +3573,8 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
default visibility. */
sec = bfd_und_section_ptr;
isym->st_shndx = SHN_UNDEF;
- isym->st_other = STV_DEFAULT
- | (isym->st_other & ~ ELF_ST_VISIBILITY(-1));
+ isym->st_other = (STV_DEFAULT
+ | (isym->st_other & ~ ELF_ST_VISIBILITY (-1)));
}
else if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
value -= sec->vma;
@@ -3650,10 +3615,10 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
}
sec = tcomm;
}
- else if (add_symbol_hook)
+ else if (bed->elf_add_symbol_hook)
{
- if (! (*add_symbol_hook) (abfd, info, isym, &name, &flags, &sec,
- &value))
+ if (! (*bed->elf_add_symbol_hook) (abfd, info, isym, &name, &flags,
+ &sec, &value))
goto error_free_vers;
/* The hook function sets the name to NULL if this symbol
@@ -3676,12 +3641,12 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
definition = TRUE;
size_change_ok = FALSE;
- type_change_ok = get_elf_backend_data (abfd)->type_change_ok;
+ type_change_ok = bed->type_change_ok;
old_alignment = 0;
old_bfd = NULL;
new_sec = sec;
- if (is_elf_hash_table (hash_table))
+ if (is_elf_hash_table (htab))
{
Elf_Internal_Versym iver;
unsigned int vernum = 0;
@@ -3776,7 +3741,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
&& isym->st_shndx != SHN_UNDEF)
++newlen;
- newname = bfd_alloc (abfd, newlen);
+ newname = bfd_hash_allocate (&htab->root.table, newlen);
if (newname == NULL)
goto error_free_vers;
memcpy (newname, name, namelen);
@@ -3840,7 +3805,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
}
if (! (_bfd_generic_link_add_one_symbol
- (info, abfd, name, flags, sec, value, NULL, FALSE, collect,
+ (info, abfd, name, flags, sec, value, NULL, FALSE, bed->collect,
(struct bfd_link_hash_entry **) sym_hash)))
goto error_free_vers;
@@ -3855,7 +3820,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
&& definition
&& (flags & BSF_WEAK) != 0
&& ELF_ST_TYPE (isym->st_info) != STT_FUNC
- && is_elf_hash_table (hash_table)
+ && is_elf_hash_table (htab)
&& h->u.weakdef == NULL)
{
/* Keep a list of all weak defined non function symbols from
@@ -3898,7 +3863,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
h->root.u.c.p->alignment_power = old_alignment;
}
- if (is_elf_hash_table (hash_table))
+ if (is_elf_hash_table (htab))
{
bfd_boolean dynsym;
@@ -3998,7 +3963,8 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
&& (abfd->no_export
|| (abfd->my_archive && abfd->my_archive->no_export))
&& ELF_ST_VISIBILITY (isym->st_other) != STV_INTERNAL)
- isym->st_other = STV_HIDDEN | (isym->st_other & ~ ELF_ST_VISIBILITY (-1));
+ isym->st_other = (STV_HIDDEN
+ | (isym->st_other & ~ELF_ST_VISIBILITY (-1)));
if (isym->st_other != 0 && !dynamic)
{
@@ -4071,13 +4037,13 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
{
/* Queue non-default versions so that .symver x, x@FOO
aliases can be checked. */
- if (! nondeflt_vers)
+ if (!nondeflt_vers)
{
- amt = (isymend - isym + 1)
- * sizeof (struct elf_link_hash_entry *);
+ amt = ((isymend - isym + 1)
+ * sizeof (struct elf_link_hash_entry *));
nondeflt_vers = bfd_malloc (amt);
}
- nondeflt_vers [nondeflt_vers_cnt++] = h;
+ nondeflt_vers[nondeflt_vers_cnt++] = h;
}
}
@@ -4089,7 +4055,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
&& ! new_weakdef
&& h->u.weakdef->dynindx == -1)
{
- if (! bfd_elf_link_record_dynamic_symbol (info, h->u.weakdef))
+ if (!bfd_elf_link_record_dynamic_symbol (info, h->u.weakdef))
goto error_free_vers;
}
}
@@ -4139,6 +4105,68 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
}
}
+ if (extversym != NULL)
+ {
+ free (extversym);
+ extversym = NULL;
+ }
+
+ if (isymbuf != NULL)
+ {
+ free (isymbuf);
+ isymbuf = NULL;
+ }
+
+ if ((elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0)
+ {
+ unsigned int i;
+
+ /* Restore the symbol table. */
+ old_hash = (char *) old_tab + tabsize;
+ old_ent = (char *) old_hash + hashsize;
+ sym_hash = elf_sym_hashes (abfd);
+ memcpy (htab->root.table.table, old_tab, tabsize);
+ memcpy (sym_hash, old_hash, hashsize);
+ htab->root.undefs = old_undefs;
+ htab->root.undefs_tail = old_undefs_tail;
+ for (i = 0; i < htab->root.table.size; i++)
+ {
+ struct bfd_hash_entry *p;
+ struct elf_link_hash_entry *h;
+
+ for (p = htab->root.table.table[i]; p != NULL; p = p->next)
+ {
+ h = (struct elf_link_hash_entry *) p;
+ if (h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+ if (h->dynindx >= old_dynsymcount)
+ _bfd_elf_strtab_delref (htab->dynstr, h->dynstr_index);
+
+ memcpy (p, old_ent, htab->root.table.entsize);
+ old_ent = (char *) old_ent + htab->root.table.entsize;
+ h = (struct elf_link_hash_entry *) p;
+ if (h->root.type == bfd_link_hash_warning)
+ {
+ memcpy (h->root.u.i.link, old_ent, htab->root.table.entsize);
+ old_ent = (char *) old_ent + htab->root.table.entsize;
+ }
+ }
+ }
+
+ free (old_tab);
+ objalloc_free_block ((struct objalloc *) htab->root.table.memory,
+ alloc_mark);
+ if (nondeflt_vers != NULL)
+ free (nondeflt_vers);
+ return TRUE;
+ }
+
+ if (old_tab != NULL)
+ {
+ free (old_tab);
+ old_tab = NULL;
+ }
+
/* Now that all the symbols from this input file are created, handle
.symver foo, foo@BAR such that any relocs against foo become foo@BAR. */
if (nondeflt_vers != NULL)
@@ -4162,7 +4190,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
shortname[amt] = '\0';
hi = (struct elf_link_hash_entry *)
- bfd_link_hash_lookup (&hash_table->root, shortname,
+ bfd_link_hash_lookup (&htab->root, shortname,
FALSE, FALSE, FALSE);
if (hi != NULL
&& hi->root.type == h->root.type
@@ -4188,31 +4216,6 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
nondeflt_vers = NULL;
}
- if (extversym != NULL)
- {
- free (extversym);
- extversym = NULL;
- }
-
- if (isymbuf != NULL)
- free (isymbuf);
- isymbuf = NULL;
-
- if (!add_needed
- && (elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0)
- {
- /* Remove symbols defined in an as-needed shared lib that wasn't
- needed. */
- struct elf_smash_syms_data inf;
- inf.not_needed = abfd;
- inf.htab = hash_table;
- inf.twiddled = FALSE;
- elf_link_hash_traverse (hash_table, elf_smash_syms, &inf);
- if (inf.twiddled)
- bfd_link_repair_undef_list (&hash_table->root);
- weaks = NULL;
- }
-
/* Now set the weakdefs field correctly for all the weak defined
symbols we found. The only way to do this is to search all the
symbols. Since we only need the information for non functions in
@@ -4352,9 +4355,8 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
free (sorted_sym_hash);
}
- check_directives = get_elf_backend_data (abfd)->check_directives;
- if (check_directives)
- check_directives (abfd, info);
+ if (bed->check_directives)
+ (*bed->check_directives) (abfd, info);
/* If this object is the same format as the output object, and it is
not a shared library, then let the backend look through the
@@ -4373,11 +4375,10 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
I have no idea how to handle linking PIC code into a file of a
different format. It probably can't be done. */
- check_relocs = get_elf_backend_data (abfd)->check_relocs;
if (! dynamic
- && is_elf_hash_table (hash_table)
- && hash_table->root.creator == abfd->xvec
- && check_relocs != NULL)
+ && is_elf_hash_table (htab)
+ && htab->root.creator == abfd->xvec
+ && bed->check_relocs != NULL)
{
asection *o;
@@ -4398,7 +4399,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
if (internal_relocs == NULL)
goto error_return;
- ok = (*check_relocs) (abfd, info, o, internal_relocs);
+ ok = (*bed->check_relocs) (abfd, info, o, internal_relocs);
if (elf_section_data (o)->relocs != internal_relocs)
free (internal_relocs);
@@ -4412,7 +4413,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
of the .stab/.stabstr sections. */
if (! dynamic
&& ! info->traditional_format
- && is_elf_hash_table (hash_table)
+ && is_elf_hash_table (htab)
&& (info->strip != strip_all && info->strip != strip_debugger))
{
asection *stabstr;
@@ -4433,10 +4434,8 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
struct bfd_elf_section_data *secdata;
secdata = elf_section_data (stab);
- if (! _bfd_link_section_stabs (abfd,
- &hash_table->stab_info,
- stab, stabstr,
- &secdata->sec_info,
+ if (! _bfd_link_section_stabs (abfd, &htab->stab_info, stab,
+ stabstr, &secdata->sec_info,
&string_offset))
goto error_return;
if (secdata->sec_info)
@@ -4445,7 +4444,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
}
}
- if (is_elf_hash_table (hash_table) && add_needed)
+ if (is_elf_hash_table (htab) && add_needed)
{
/* Add this bfd to the loaded list. */
struct elf_link_loaded_list *n;
@@ -4454,13 +4453,15 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
if (n == NULL)
goto error_return;
n->abfd = abfd;
- n->next = hash_table->loaded;
- hash_table->loaded = n;
+ n->next = htab->loaded;
+ htab->loaded = n;
}
return TRUE;
error_free_vers:
+ if (old_tab != NULL)
+ free (old_tab);
if (nondeflt_vers != NULL)
free (nondeflt_vers);
if (extversym != NULL)
@@ -7664,7 +7665,7 @@ elf_fixup_link_order (bfd *abfd, asection *o)
struct bfd_link_order *p;
bfd *sub;
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
- int elfsec;
+ unsigned elfsec;
struct bfd_link_order **sections;
asection *s, *other_sec, *linkorder_sec;
bfd_vma offset;
@@ -7681,7 +7682,8 @@ elf_fixup_link_order (bfd *abfd, asection *o)
sub = s->owner;
if (bfd_get_flavour (sub) == bfd_target_elf_flavour
&& elf_elfheader (sub)->e_ident[EI_CLASS] == bed->s->elfclass
- && (elfsec = _bfd_elf_section_from_bfd_section (sub, s)) != -1
+ && (elfsec = _bfd_elf_section_from_bfd_section (sub, s))
+ && elfsec < elf_numsections (sub)
&& elf_elfsections (sub)[elfsec]->sh_flags & SHF_LINK_ORDER)
{
seen_linkorder++;
@@ -7781,8 +7783,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
dynobj = elf_hash_table (info)->dynobj;
emit_relocs = (info->relocatable
- || info->emitrelocations
- || bed->elf_backend_emit_relocs);
+ || info->emitrelocations);
finfo.info = info;
finfo.output_bfd = abfd;
@@ -9170,7 +9171,7 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
/* Keep .gcc_except_table.* if the associated .text.* is
marked. This isn't very nice, but the proper solution,
- splitting .eh_frame up and using comdat doesn't pan out
+ splitting .eh_frame up and using comdat doesn't pan out
easily due to needing special relocs to handle the
difference of two symbols in separate sections.
Don't keep code sections referenced by .eh_frame. */
diff --git a/bfd/elfxx-ia64.c b/bfd/elfxx-ia64.c
index 7a0cc90..f0bb0fa 100644
--- a/bfd/elfxx-ia64.c
+++ b/bfd/elfxx-ia64.c
@@ -1,5 +1,5 @@
/* IA-64 support for 64-bit ELF
- Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+ Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
@@ -1918,7 +1918,8 @@ elfNN_ia64_hash_table_create (abfd)
return 0;
if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
- elfNN_ia64_new_elf_hash_entry))
+ elfNN_ia64_new_elf_hash_entry,
+ sizeof (struct elfNN_ia64_link_hash_entry)))
{
free (ret);
return 0;
@@ -3928,14 +3929,16 @@ elfNN_ia64_choose_gp (abfd, info)
gp_val = got_sec->output_section->vma;
else if (max_short_vma != 0)
gp_val = min_short_vma;
- else
+ else if (max_vma - min_vma < 0x200000)
gp_val = min_vma;
+ else
+ gp_val = max_vma - 0x200000 + 8;
/* If it is possible to address the entire image, but we
don't with the choice above, adjust. */
if (max_vma - min_vma < 0x400000
- && max_vma - gp_val <= 0x200000
- && gp_val - min_vma > 0x200000)
+ && (max_vma - gp_val >= 0x200000
+ || gp_val - min_vma > 0x200000))
gp_val = min_vma + 0x200000;
else if (max_short_vma != 0)
{
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index 89acbc5..4e27a53 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -1,6 +1,6 @@
/* MIPS-specific support for ELF
Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
- 2003, 2004, 2005 Free Software Foundation, Inc.
+ 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
Most of the information added by Ian Lance Taylor, Cygnus Support,
<ian@cygnus.com>.
@@ -34,6 +34,7 @@
#include "elf-bfd.h"
#include "elfxx-mips.h"
#include "elf/mips.h"
+#include "elf-vxworks.h"
/* Get the ECOFF swapping routines. */
#include "coff/sym.h"
@@ -43,8 +44,39 @@
#include "hashtab.h"
-/* This structure is used to hold .got entries while estimating got
- sizes. */
+/* This structure is used to hold information about one GOT entry.
+ There are three types of entry:
+
+ (1) absolute addresses
+ (abfd == NULL)
+ (2) SYMBOL + OFFSET addresses, where SYMBOL is local to an input bfd
+ (abfd != NULL, symndx >= 0)
+ (3) global and forced-local symbols
+ (abfd != NULL, symndx == -1)
+
+ Type (3) entries are treated differently for different types of GOT.
+ In the "master" GOT -- i.e. the one that describes every GOT
+ reference needed in the link -- the mips_got_entry is keyed on both
+ the symbol and the input bfd that references it. If it turns out
+ that we need multiple GOTs, we can then use this information to
+ create separate GOTs for each input bfd.
+
+ However, we want each of these separate GOTs to have at most one
+ entry for a given symbol, so their type (3) entries are keyed only
+ on the symbol. The input bfd given by the "abfd" field is somewhat
+ arbitrary in this case.
+
+ This means that when there are multiple GOTs, each GOT has a unique
+ mips_got_entry for every symbol within it. We can therefore use the
+ mips_got_entry fields (tls_type and gotidx) to track the symbol's
+ GOT index.
+
+ However, if it turns out that we need only a single GOT, we continue
+ to use the master GOT to describe it. There may therefore be several
+ mips_got_entries for the same symbol, each with a different input bfd.
+ We want to make sure that each symbol gets a unique GOT entry, so when
+ there's a single GOT, we use the symbol's hash entry, not the
+ mips_got_entry fields, to track a symbol's GOT index. */
struct mips_got_entry
{
/* The input bfd in which the symbol is defined. */
@@ -246,6 +278,12 @@ struct mips_elf_link_hash_entry
the initial global GOT entry to a local GOT entry. */
bfd_boolean forced_local;
+ /* Are we referenced by some kind of relocation? */
+ bfd_boolean is_relocation_target;
+
+ /* Are we referenced by branch relocations? */
+ bfd_boolean is_branch_target;
+
#define GOT_NORMAL 0
#define GOT_TLS_GD 1
#define GOT_TLS_LDM 2
@@ -283,6 +321,20 @@ struct mips_elf_link_hash_table
bfd_vma rld_value;
/* This is set if we see any mips16 stub sections. */
bfd_boolean mips16_stubs_seen;
+ /* True if we're generating code for VxWorks. */
+ bfd_boolean is_vxworks;
+ /* Shortcuts to some dynamic sections, or NULL if they are not
+ being used. */
+ asection *srelbss;
+ asection *sdynbss;
+ asection *srelplt;
+ asection *srelplt2;
+ asection *sgotplt;
+ asection *splt;
+ /* The size of the PLT header in bytes (VxWorks only). */
+ bfd_vma plt_header_size;
+ /* The size of a PLT entry in bytes (VxWorks only). */
+ bfd_vma plt_entry_size;
};
#define TLS_RELOC_P(r_type) \
@@ -433,8 +485,8 @@ typedef struct runtime_pdr {
#define rpdNil ((pRPDR) 0)
static struct mips_got_entry *mips_elf_create_local_got_entry
- (bfd *, bfd *, struct mips_got_info *, asection *, bfd_vma, unsigned long,
- struct mips_elf_link_hash_entry *, int);
+ (bfd *, struct bfd_link_info *, bfd *, struct mips_got_info *, asection *,
+ asection *, bfd_vma, unsigned long, struct mips_elf_link_hash_entry *, int);
static bfd_boolean mips_elf_sort_hash_table_f
(struct mips_elf_link_hash_entry *, void *);
static bfd_vma mips_elf_high
@@ -490,6 +542,10 @@ static bfd *reldyn_sorting_bfd;
#define MIPS_ELF_REL_SIZE(abfd) \
(get_elf_backend_data (abfd)->s->sizeof_rel)
+/* The size of an external RELA relocation. */
+#define MIPS_ELF_RELA_SIZE(abfd) \
+ (get_elf_backend_data (abfd)->s->sizeof_rela)
+
/* The size of an external dynamic table entry. */
#define MIPS_ELF_DYN_SIZE(abfd) \
(get_elf_backend_data (abfd)->s->sizeof_dyn)
@@ -540,20 +596,26 @@ static bfd *reldyn_sorting_bfd;
== (ABI_64_P (abfd) ? sizeof (Elf64_External_Rela) \
: sizeof (Elf32_External_Rela))))
+/* The name of the dynamic relocation section. */
+#define MIPS_ELF_REL_DYN_NAME(INFO) \
+ (mips_elf_hash_table (INFO)->is_vxworks ? ".rela.dyn" : ".rel.dyn")
+
/* In case we're on a 32-bit machine, construct a 64-bit "-1" value
from smaller values. Start with zero, widen, *then* decrement. */
#define MINUS_ONE (((bfd_vma)0) - 1)
#define MINUS_TWO (((bfd_vma)0) - 2)
/* The number of local .got entries we reserve. */
-#define MIPS_RESERVED_GOTNO (2)
+#define MIPS_RESERVED_GOTNO(INFO) \
+ (mips_elf_hash_table (INFO)->is_vxworks ? 3 : 2)
/* The offset of $gp from the beginning of the .got section. */
-#define ELF_MIPS_GP_OFFSET(abfd) (0x7ff0)
+#define ELF_MIPS_GP_OFFSET(INFO) \
+ (mips_elf_hash_table (INFO)->is_vxworks ? 0x0 : 0x7ff0)
/* The maximum size of the GOT for it to be addressable using 16-bit
offsets from $gp. */
-#define MIPS_ELF_GOT_MAX_SIZE(abfd) (ELF_MIPS_GP_OFFSET(abfd) + 0x7fff)
+#define MIPS_ELF_GOT_MAX_SIZE(INFO) (ELF_MIPS_GP_OFFSET (INFO) + 0x7fff)
/* Instructions which appear in a stub. */
#define STUB_LW(abfd) \
@@ -636,6 +698,44 @@ static bfd *reldyn_sorting_bfd;
#define CALL_STUB ".mips16.call."
#define CALL_FP_STUB ".mips16.call.fp."
+/* The format of the first PLT entry in a VxWorks executable. */
+static const bfd_vma mips_vxworks_exec_plt0_entry[] = {
+ 0x3c190000, /* lui t9, %hi(_GLOBAL_OFFSET_TABLE_) */
+ 0x27390000, /* addiu t9, t9, %lo(_GLOBAL_OFFSET_TABLE_) */
+ 0x8f390008, /* lw t9, 8(t9) */
+ 0x00000000, /* nop */
+ 0x03200008, /* jr t9 */
+ 0x00000000 /* nop */
+};
+
+/* The format of subsequent PLT entries. */
+static const bfd_vma mips_vxworks_exec_plt_entry[] = {
+ 0x10000000, /* b .PLT_resolver */
+ 0x24180000, /* li t8, <pltindex> */
+ 0x3c190000, /* lui t9, %hi(<.got.plt slot>) */
+ 0x27390000, /* addiu t9, t9, %lo(<.got.plt slot>) */
+ 0x8f390000, /* lw t9, 0(t9) */
+ 0x00000000, /* nop */
+ 0x03200008, /* jr t9 */
+ 0x00000000 /* nop */
+};
+
+/* The format of the first PLT entry in a VxWorks shared object. */
+static const bfd_vma mips_vxworks_shared_plt0_entry[] = {
+ 0x8f990008, /* lw t9, 8(gp) */
+ 0x00000000, /* nop */
+ 0x03200008, /* jr t9 */
+ 0x00000000, /* nop */
+ 0x00000000, /* nop */
+ 0x00000000 /* nop */
+};
+
+/* The format of subsequent PLT entries. */
+static const bfd_vma mips_vxworks_shared_plt_entry[] = {
+ 0x10000000, /* b .PLT_resolver */
+ 0x24180000 /* li t8, <pltindex> */
+};
+
/* Look up an entry in a MIPS ELF linker hash table. */
#define mips_elf_link_hash_lookup(table, string, create, copy, follow) \
@@ -715,6 +815,8 @@ mips_elf_link_hash_newfunc (struct bfd_hash_entry *entry,
ret->call_stub = NULL;
ret->call_fp_stub = NULL;
ret->forced_local = FALSE;
+ ret->is_branch_target = FALSE;
+ ret->is_relocation_target = FALSE;
ret->tls_type = GOT_NORMAL;
}
@@ -1896,14 +1998,19 @@ mips_elf_multi_got_entry_eq (const void *entry1, const void *entry2)
: e1->d.h == e2->d.h);
}
-/* Returns the dynamic relocation section for DYNOBJ. */
+/* Return the dynamic relocation section. If it doesn't exist, try to
+ create a new it if CREATE_P, otherwise return NULL. Also return NULL
+ if creation fails. */
static asection *
-mips_elf_rel_dyn_section (bfd *dynobj, bfd_boolean create_p)
+mips_elf_rel_dyn_section (struct bfd_link_info *info, bfd_boolean create_p)
{
- static const char dname[] = ".rel.dyn";
+ const char *dname;
asection *sreloc;
+ bfd *dynobj;
+ dname = MIPS_ELF_REL_DYN_NAME (info);
+ dynobj = elf_hash_table (info)->dynobj;
sreloc = bfd_get_section_by_name (dynobj, dname);
if (sreloc == NULL && create_p)
{
@@ -2121,7 +2228,7 @@ mips_elf_initialize_tls_slots (bfd *abfd, bfd_vma got_offset,
|| h->root.root.type == bfd_link_hash_undefweak);
/* Emit necessary relocations. */
- sreloc = mips_elf_rel_dyn_section (dynobj, FALSE);
+ sreloc = mips_elf_rel_dyn_section (info, FALSE);
/* General Dynamic. */
if (*tls_type_p & GOT_TLS_GD)
@@ -2240,14 +2347,46 @@ mips_tls_got_index (bfd *abfd, bfd_vma got_index, unsigned char *tls_type,
return got_index;
}
-/* Returns the GOT offset at which the indicated address can be found.
- If there is not yet a GOT entry for this value, create one. If
- R_SYMNDX refers to a TLS symbol, create a TLS GOT entry instead.
- Returns -1 if no satisfactory GOT offset can be found. */
+/* Return the offset from _GLOBAL_OFFSET_TABLE_ of the .got.plt entry
+ for global symbol H. .got.plt comes before the GOT, so the offset
+ will be negative. */
+
+static bfd_vma
+mips_elf_gotplt_index (struct bfd_link_info *info,
+ struct elf_link_hash_entry *h)
+{
+ bfd_vma plt_index, got_address, got_value;
+ struct mips_elf_link_hash_table *htab;
+
+ htab = mips_elf_hash_table (info);
+ BFD_ASSERT (h->plt.offset != (bfd_vma) -1);
+
+ /* Calculate the index of the symbol's PLT entry. */
+ plt_index = (h->plt.offset - htab->plt_header_size) / htab->plt_entry_size;
+
+ /* Calculate the address of the associated .got.plt entry. */
+ got_address = (htab->sgotplt->output_section->vma
+ + htab->sgotplt->output_offset
+ + plt_index * 4);
+
+ /* Calculate the value of _GLOBAL_OFFSET_TABLE_. */
+ got_value = (htab->root.hgot->root.u.def.section->output_section->vma
+ + htab->root.hgot->root.u.def.section->output_offset
+ + htab->root.hgot->root.u.def.value);
+
+ return got_address - got_value;
+}
+
+/* Return the GOT offset for address VALUE, which was derived from
+ a symbol belonging to INPUT_SECTION. If there is not yet a GOT
+ entry for this value, create one. If R_SYMNDX refers to a TLS symbol,
+ create a TLS GOT entry instead. Return -1 if no satisfactory GOT
+ offset can be found. */
static bfd_vma
mips_elf_local_got_index (bfd *abfd, bfd *ibfd, struct bfd_link_info *info,
- bfd_vma value, unsigned long r_symndx,
+ asection *input_section, bfd_vma value,
+ unsigned long r_symndx,
struct mips_elf_link_hash_entry *h, int r_type)
{
asection *sgot;
@@ -2256,14 +2395,23 @@ mips_elf_local_got_index (bfd *abfd, bfd *ibfd, struct bfd_link_info *info,
g = mips_elf_got_info (elf_hash_table (info)->dynobj, &sgot);
- entry = mips_elf_create_local_got_entry (abfd, ibfd, g, sgot, value,
+ entry = mips_elf_create_local_got_entry (abfd, info, ibfd, g, sgot,
+ input_section, value,
r_symndx, h, r_type);
if (!entry)
return MINUS_ONE;
if (TLS_RELOC_P (r_type))
- return mips_tls_got_index (abfd, entry->gotidx, &entry->tls_type, r_type,
- info, h, value);
+ {
+ if (entry->symndx == -1 && g->next == NULL)
+ /* A type (3) entry in the single-GOT case. We use the symbol's
+ hash table entry to track the index. */
+ return mips_tls_got_index (abfd, h->tls_got_offset, &h->tls_type,
+ r_type, info, h, value);
+ else
+ return mips_tls_got_index (abfd, entry->gotidx, &entry->tls_type,
+ r_type, info, h, value);
+ }
else
return entry->gotidx;
}
@@ -2350,26 +2498,27 @@ mips_elf_global_got_index (bfd *abfd, bfd *ibfd, struct elf_link_hash_entry *h,
return index;
}
-/* Find a GOT entry that is within 32KB of the VALUE. These entries
- are supposed to be placed at small offsets in the GOT, i.e.,
- within 32KB of GP. Return the index into the GOT for this page,
- and store the offset from this entry to the desired address in
- OFFSETP, if it is non-NULL. */
+/* Find a GOT page entry that points to within 32KB of VALUE, which was
+ calculated from a symbol belonging to INPUT_SECTION. These entries
+ are supposed to be placed at small offsets in the GOT, i.e., within
+ 32KB of GP. Return the index of the GOT entry, or -1 if no entry
+ could be created. If OFFSETP is nonnull, use it to return the
+ offset of the GOT entry from VALUE. */
static bfd_vma
mips_elf_got_page (bfd *abfd, bfd *ibfd, struct bfd_link_info *info,
- bfd_vma value, bfd_vma *offsetp)
+ asection *input_section, bfd_vma value, bfd_vma *offsetp)
{
asection *sgot;
struct mips_got_info *g;
- bfd_vma index;
+ bfd_vma page, index;
struct mips_got_entry *entry;
g = mips_elf_got_info (elf_hash_table (info)->dynobj, &sgot);
- entry = mips_elf_create_local_got_entry (abfd, ibfd, g, sgot,
- (value + 0x8000)
- & (~(bfd_vma)0xffff), 0,
+ page = (value + 0x8000) & ~(bfd_vma) 0xffff;
+ entry = mips_elf_create_local_got_entry (abfd, info, ibfd, g, sgot,
+ input_section, page, 0,
NULL, R_MIPS_GOT_PAGE);
if (!entry)
@@ -2383,30 +2532,32 @@ mips_elf_got_page (bfd *abfd, bfd *ibfd, struct bfd_link_info *info,
return index;
}
-/* Find a GOT entry whose higher-order 16 bits are the same as those
- for value. Return the index into the GOT for this entry. */
+/* Find a local GOT entry for an R_MIPS_GOT16 relocation against VALUE,
+ which was calculated from a symbol belonging to INPUT_SECTION.
+ EXTERNAL is true if the relocation was against a global symbol
+ that has been forced local. */
static bfd_vma
mips_elf_got16_entry (bfd *abfd, bfd *ibfd, struct bfd_link_info *info,
- bfd_vma value, bfd_boolean external)
+ asection *input_section, bfd_vma value,
+ bfd_boolean external)
{
asection *sgot;
struct mips_got_info *g;
struct mips_got_entry *entry;
+ /* GOT16 relocations against local symbols are followed by a LO16
+ relocation; those against global symbols are not. Thus if the
+ symbol was originally local, the GOT16 relocation should load the
+ equivalent of %hi(VALUE), otherwise it should load VALUE itself. */
if (! external)
- {
- /* Although the ABI says that it is "the high-order 16 bits" that we
- want, it is really the %high value. The complete value is
- calculated with a `addiu' of a LO16 relocation, just as with a
- HI16/LO16 pair. */
- value = mips_elf_high (value) << 16;
- }
+ value = mips_elf_high (value) << 16;
g = mips_elf_got_info (elf_hash_table (info)->dynobj, &sgot);
- entry = mips_elf_create_local_got_entry (abfd, ibfd, g, sgot, value, 0, NULL,
- R_MIPS_GOT16);
+ entry = mips_elf_create_local_got_entry (abfd, info, ibfd, g, sgot,
+ input_section, value, 0,
+ NULL, R_MIPS_GOT16);
if (entry)
return entry->gotidx;
else
@@ -2431,20 +2582,24 @@ mips_elf_got_offset_from_index (bfd *dynobj, bfd *output_bfd,
return sgot->output_section->vma + sgot->output_offset + index - gp;
}
-/* Create a local GOT entry for VALUE. Return the index of the entry,
- or -1 if it could not be created. If R_SYMNDX refers to a TLS symbol,
- create a TLS entry instead. */
+/* Create and return a local GOT entry for VALUE, which was calculated
+ from a symbol belonging to INPUT_SECTON. Return NULL if it could not
+ be created. If R_SYMNDX refers to a TLS symbol, create a TLS entry
+ instead. */
static struct mips_got_entry *
-mips_elf_create_local_got_entry (bfd *abfd, bfd *ibfd,
- struct mips_got_info *gg,
- asection *sgot, bfd_vma value,
- unsigned long r_symndx,
+mips_elf_create_local_got_entry (bfd *abfd, struct bfd_link_info *info,
+ bfd *ibfd, struct mips_got_info *gg,
+ asection *sgot, asection *input_section,
+ bfd_vma value, unsigned long r_symndx,
struct mips_elf_link_hash_entry *h,
int r_type)
{
struct mips_got_entry entry, **loc;
struct mips_got_info *g;
+ struct mips_elf_link_hash_table *htab;
+
+ htab = mips_elf_hash_table (info);
entry.abfd = NULL;
entry.symndx = -1;
@@ -2517,6 +2672,33 @@ mips_elf_create_local_got_entry (bfd *abfd, bfd *ibfd,
MIPS_ELF_PUT_WORD (abfd, value,
(sgot->contents + entry.gotidx));
+ /* These GOT entries need a dynamic relocation on VxWorks. Because
+ the offset between segments is not fixed, the relocation must be
+ against a symbol in the same segment as the original symbol.
+ The easiest way to do this is to take INPUT_SECTION's output
+ section and emit a relocation against its section symbol. */
+ if (htab->is_vxworks)
+ {
+ Elf_Internal_Rela outrel;
+ asection *s, *output_section;
+ bfd_byte *loc;
+ bfd_vma got_address;
+ int dynindx;
+
+ s = mips_elf_rel_dyn_section (info, FALSE);
+ output_section = input_section->output_section;
+ dynindx = elf_section_data (output_section)->dynindx;
+ got_address = (sgot->output_section->vma
+ + sgot->output_offset
+ + entry.gotidx);
+
+ loc = s->contents + (s->reloc_count++ * sizeof (Elf32_External_Rela));
+ outrel.r_offset = got_address;
+ outrel.r_info = ELF32_R_INFO (dynindx, R_MIPS_32);
+ outrel.r_addend = value - output_section->vma;
+ bfd_elf32_swap_reloca_out (abfd, &outrel, loc);
+ }
+
return *loc;
}
@@ -2892,7 +3074,7 @@ mips_elf_merge_gots (void **bfd2got_, void *p)
{
unsigned int primary_total = lcount + tcount + arg->global_count;
if (primary_total * MIPS_ELF_GOT_SIZE (bfd2got->bfd)
- >= MIPS_ELF_GOT_MAX_SIZE (bfd2got->bfd))
+ >= MIPS_ELF_GOT_MAX_SIZE (arg->info))
too_many_for_tls = TRUE;
}
@@ -2975,55 +3157,54 @@ mips_elf_merge_gots (void **bfd2got_, void *p)
return 1;
}
-/* Set the TLS GOT index for the GOT entry in ENTRYP. */
+/* Set the TLS GOT index for the GOT entry in ENTRYP. ENTRYP's NEXT field
+ is null iff there is just a single GOT. */
static int
mips_elf_initialize_tls_index (void **entryp, void *p)
{
struct mips_got_entry *entry = (struct mips_got_entry *)*entryp;
struct mips_got_info *g = p;
+ bfd_vma next_index;
/* We're only interested in TLS symbols. */
if (entry->tls_type == 0)
return 1;
- if (entry->symndx == -1)
+ next_index = MIPS_ELF_GOT_SIZE (entry->abfd) * (long) g->tls_assigned_gotno;
+
+ if (entry->symndx == -1 && g->next == NULL)
{
- /* There may be multiple mips_got_entry structs for a global variable
- if there is just one GOT. Just do this once. */
- if (g->next == NULL)
+ /* A type (3) got entry in the single-GOT case. We use the symbol's
+ hash table entry to track its index. */
+ if (entry->d.h->tls_type & GOT_TLS_OFFSET_DONE)
+ return 1;
+ entry->d.h->tls_type |= GOT_TLS_OFFSET_DONE;
+ entry->d.h->tls_got_offset = next_index;
+ }
+ else
+ {
+ if (entry->tls_type & GOT_TLS_LDM)
{
- if (entry->d.h->tls_type & GOT_TLS_OFFSET_DONE)
+ /* There are separate mips_got_entry objects for each input bfd
+ that requires an LDM entry. Make sure that all LDM entries in
+ a GOT resolve to the same index. */
+ if (g->tls_ldm_offset != MINUS_TWO && g->tls_ldm_offset != MINUS_ONE)
{
- entry->gotidx = entry->d.h->tls_got_offset;
+ entry->gotidx = g->tls_ldm_offset;
return 1;
}
- entry->d.h->tls_type |= GOT_TLS_OFFSET_DONE;
- }
- }
- else if (entry->tls_type & GOT_TLS_LDM)
- {
- /* Similarly, there may be multiple structs for the LDM entry. */
- if (g->tls_ldm_offset != MINUS_TWO && g->tls_ldm_offset != MINUS_ONE)
- {
- entry->gotidx = g->tls_ldm_offset;
- return 1;
+ g->tls_ldm_offset = next_index;
}
+ entry->gotidx = next_index;
}
- /* Initialize the GOT offset. */
- entry->gotidx = MIPS_ELF_GOT_SIZE (entry->abfd) * (long) g->tls_assigned_gotno;
- if (g->next == NULL && entry->symndx == -1)
- entry->d.h->tls_got_offset = entry->gotidx;
-
+ /* Account for the entries we've just allocated. */
if (entry->tls_type & (GOT_TLS_GD | GOT_TLS_LDM))
g->tls_assigned_gotno += 2;
if (entry->tls_type & GOT_TLS_IE)
g->tls_assigned_gotno += 1;
- if (entry->tls_type & GOT_TLS_LDM)
- g->tls_ldm_offset = entry->gotidx;
-
return 1;
}
@@ -3207,9 +3388,9 @@ mips_elf_multi_got (bfd *abfd, struct bfd_link_info *info,
/* Taking out PAGES entries is a worst-case estimate. We could
compute the maximum number of pages that each separate input bfd
uses, but it's probably not worth it. */
- got_per_bfd_arg.max_count = ((MIPS_ELF_GOT_MAX_SIZE (abfd)
+ got_per_bfd_arg.max_count = ((MIPS_ELF_GOT_MAX_SIZE (info)
/ MIPS_ELF_GOT_SIZE (abfd))
- - MIPS_RESERVED_GOTNO - pages);
+ - MIPS_RESERVED_GOTNO (info) - pages);
/* The number of globals that will be included in the primary GOT.
See the calls to mips_elf_set_global_got_offset below for more
information. */
@@ -3344,21 +3525,24 @@ mips_elf_multi_got (bfd *abfd, struct bfd_link_info *info,
{
struct mips_got_info *gn;
- assign += MIPS_RESERVED_GOTNO;
+ assign += MIPS_RESERVED_GOTNO (info);
g->assigned_gotno = assign;
g->local_gotno += assign + pages;
assign = g->local_gotno + g->global_gotno + g->tls_gotno;
+ /* Take g out of the direct list, and push it onto the reversed
+ list that gg points to. g->next is guaranteed to be nonnull after
+ this operation, as required by mips_elf_initialize_tls_index. */
+ gn = g->next;
+ g->next = gg->next;
+ gg->next = g;
+
/* Set up any TLS entries. We always place the TLS entries after
all non-TLS entries. */
g->tls_assigned_gotno = g->local_gotno + g->global_gotno;
htab_traverse (g->got_entries, mips_elf_initialize_tls_index, g);
- /* Take g out of the direct list, and push it onto the reversed
- list that gg points to. */
- gn = g->next;
- g->next = gg->next;
- gg->next = g;
+ /* Move onto the next GOT. It will be a secondary GOT if nonull. */
g = gn;
/* Mark global symbols in every non-primary GOT as ineligible for
@@ -3540,6 +3724,9 @@ mips_elf_create_got_section (bfd *abfd, struct bfd_link_info *info,
struct bfd_link_hash_entry *bh;
struct mips_got_info *g;
bfd_size_type amt;
+ struct mips_elf_link_hash_table *htab;
+
+ htab = mips_elf_hash_table (info);
/* This function may be called more than once. */
s = mips_elf_got_section (abfd, TRUE);
@@ -3576,6 +3763,7 @@ mips_elf_create_got_section (bfd *abfd, struct bfd_link_info *info,
h->non_elf = 0;
h->def_regular = 1;
h->type = STT_OBJECT;
+ elf_hash_table (info)->hgot = h;
if (info->shared
&& ! bfd_elf_link_record_dynamic_symbol (info, h))
@@ -3588,8 +3776,8 @@ mips_elf_create_got_section (bfd *abfd, struct bfd_link_info *info,
g->global_gotsym = NULL;
g->global_gotno = 0;
g->tls_gotno = 0;
- g->local_gotno = MIPS_RESERVED_GOTNO;
- g->assigned_gotno = MIPS_RESERVED_GOTNO;
+ g->local_gotno = MIPS_RESERVED_GOTNO (info);
+ g->assigned_gotno = MIPS_RESERVED_GOTNO (info);
g->bfd2got = NULL;
g->next = NULL;
g->tls_ldm_offset = MINUS_ONE;
@@ -3601,9 +3789,33 @@ mips_elf_create_got_section (bfd *abfd, struct bfd_link_info *info,
mips_elf_section_data (s)->elf.this_hdr.sh_flags
|= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL;
+ /* VxWorks also needs a .got.plt section. */
+ if (htab->is_vxworks)
+ {
+ s = bfd_make_section_with_flags (abfd, ".got.plt",
+ SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY | SEC_LINKER_CREATED);
+ if (s == NULL || !bfd_set_section_alignment (abfd, s, 4))
+ return FALSE;
+
+ htab->sgotplt = s;
+ }
return TRUE;
}
+/* Return true if H refers to the special VxWorks __GOTT_BASE__ or
+ __GOTT_INDEX__ symbols. These symbols are only special for
+ shared objects; they are not used in executables. */
+
+static bfd_boolean
+is_gott_symbol (struct bfd_link_info *info, struct elf_link_hash_entry *h)
+{
+ return (mips_elf_hash_table (info)->is_vxworks
+ && info->shared
+ && (strcmp (h->root.root.string, "__GOTT_BASE__") == 0
+ || strcmp (h->root.root.string, "__GOTT_INDEX__") == 0));
+}
+
/* Calculate the value produced by the RELOCATION (which comes from
the INPUT_BFD). The ADDEND is the addend to use for this
RELOCATION; RELOCATION->R_ADDEND is ignored.
@@ -3666,6 +3878,11 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
bfd_boolean overflowed_p;
/* TRUE if this relocation refers to a MIPS16 function. */
bfd_boolean target_is_16_bit_code_p = FALSE;
+ struct mips_elf_link_hash_table *htab;
+ bfd *dynobj;
+
+ dynobj = elf_hash_table (info)->dynobj;
+ htab = mips_elf_hash_table (info);
/* Parse the relocation. */
r_symndx = ELF_R_SYM (input_bfd, relocation->r_info);
@@ -3915,52 +4132,61 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
/* Find the index into the GOT where this value is located. */
if (r_type == R_MIPS_TLS_LDM)
{
- g = mips_elf_local_got_index (abfd, input_bfd, info, 0, 0, NULL,
- r_type);
+ g = mips_elf_local_got_index (abfd, input_bfd, info,
+ sec, 0, 0, NULL, r_type);
if (g == MINUS_ONE)
return bfd_reloc_outofrange;
}
else if (!local_p)
{
- /* GOT_PAGE may take a non-zero addend, that is ignored in a
- GOT_PAGE relocation that decays to GOT_DISP because the
- symbol turns out to be global. The addend is then added
- as GOT_OFST. */
- BFD_ASSERT (addend == 0 || r_type == R_MIPS_GOT_PAGE);
- g = mips_elf_global_got_index (elf_hash_table (info)->dynobj,
- input_bfd,
- (struct elf_link_hash_entry *) h,
- r_type, info);
- if (h->tls_type == GOT_NORMAL
- && (! elf_hash_table(info)->dynamic_sections_created
- || (info->shared
- && (info->symbolic || h->root.forced_local)
- && h->root.def_regular)))
+ /* On VxWorks, CALL relocations should refer to the .got.plt
+ entry, which is initialized to point at the PLT stub. */
+ if (htab->is_vxworks
+ && (r_type == R_MIPS_CALL_HI16
+ || r_type == R_MIPS_CALL_LO16
+ || r_type == R_MIPS_CALL16))
{
- /* This is a static link or a -Bsymbolic link. The
- symbol is defined locally, or was forced to be local.
- We must initialize this entry in the GOT. */
- bfd *tmpbfd = elf_hash_table (info)->dynobj;
- asection *sgot = mips_elf_got_section (tmpbfd, FALSE);
- MIPS_ELF_PUT_WORD (tmpbfd, symbol, sgot->contents + g);
+ BFD_ASSERT (addend == 0);
+ BFD_ASSERT (h->root.needs_plt);
+ g = mips_elf_gotplt_index (info, &h->root);
+ }
+ else
+ {
+ /* GOT_PAGE may take a non-zero addend, that is ignored in a
+ GOT_PAGE relocation that decays to GOT_DISP because the
+ symbol turns out to be global. The addend is then added
+ as GOT_OFST. */
+ BFD_ASSERT (addend == 0 || r_type == R_MIPS_GOT_PAGE);
+ g = mips_elf_global_got_index (dynobj, input_bfd,
+ &h->root, r_type, info);
+ if (h->tls_type == GOT_NORMAL
+ && (! elf_hash_table(info)->dynamic_sections_created
+ || (info->shared
+ && (info->symbolic || h->root.forced_local)
+ && h->root.def_regular)))
+ {
+ /* This is a static link or a -Bsymbolic link. The
+ symbol is defined locally, or was forced to be local.
+ We must initialize this entry in the GOT. */
+ asection *sgot = mips_elf_got_section (dynobj, FALSE);
+ MIPS_ELF_PUT_WORD (dynobj, symbol, sgot->contents + g);
+ }
}
}
- else if (r_type == R_MIPS_GOT16 || r_type == R_MIPS_CALL16)
- /* There's no need to create a local GOT entry here; the
- calculation for a local GOT16 entry does not involve G. */
+ else if (!htab->is_vxworks
+ && (r_type == R_MIPS_CALL16 || (r_type == R_MIPS_GOT16)))
+ /* The calculation below does not involve "g". */
break;
else
{
- g = mips_elf_local_got_index (abfd, input_bfd,
- info, symbol + addend, r_symndx, h,
- r_type);
+ g = mips_elf_local_got_index (abfd, input_bfd, info, sec,
+ symbol + addend, r_symndx, h, r_type);
if (g == MINUS_ONE)
return bfd_reloc_outofrange;
}
/* Convert GOT indices to actual offsets. */
- g = mips_elf_got_offset_from_index (elf_hash_table (info)->dynobj,
- abfd, input_bfd, g);
+ g = mips_elf_got_offset_from_index (dynobj, abfd, input_bfd, g);
break;
case R_MIPS_HI16:
@@ -3973,10 +4199,8 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
case R_MIPS16_GPREL:
gp0 = _bfd_get_gp_value (input_bfd);
gp = _bfd_get_gp_value (abfd);
- if (elf_hash_table (info)->dynobj)
- gp += mips_elf_adjust_gp (abfd,
- mips_elf_got_info
- (elf_hash_table (info)->dynobj, NULL),
+ if (dynobj)
+ gp += mips_elf_adjust_gp (abfd, mips_elf_got_info (dynobj, NULL),
input_bfd);
break;
@@ -3987,6 +4211,27 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
if (gnu_local_gp_p)
symbol = gp;
+ /* Relocations against the VxWorks __GOTT_BASE__ and __GOTT_INDEX__
+ symbols are resolved by the loader. Add them to .rela.dyn. */
+ if (h != NULL && is_gott_symbol (info, &h->root))
+ {
+ Elf_Internal_Rela outrel;
+ bfd_byte *loc;
+ asection *s;
+
+ s = mips_elf_rel_dyn_section (info, FALSE);
+ loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela);
+
+ outrel.r_offset = (input_section->output_section->vma
+ + input_section->output_offset
+ + relocation->r_offset);
+ outrel.r_info = ELF32_R_INFO (h->root.dynindx, r_type);
+ outrel.r_addend = addend;
+ bfd_elf32_swap_reloca_out (abfd, &outrel, loc);
+ *valuep = 0;
+ return bfd_reloc_ok;
+ }
+
/* Figure out what kind of relocation is being performed. */
switch (r_type)
{
@@ -4002,7 +4247,8 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
case R_MIPS_REL32:
case R_MIPS_64:
if ((info->shared
- || (elf_hash_table (info)->dynamic_sections_created
+ || (!htab->is_vxworks
+ && htab->root.dynamic_sections_created
&& h != NULL
&& h->root.def_dynamic
&& !h->root.def_regular))
@@ -4013,7 +4259,11 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
against a symbol in a shared library, then we can't know
where the symbol will end up. So, we create a relocation
record in the output, and leave the job up to the dynamic
- linker. */
+ linker.
+
+ In VxWorks executables, references to external symbols
+ are handled using copy relocs or PLT stubs, so there's
+ no need to add a dynamic relocation here. */
value = addend;
if (!mips_elf_create_dynamic_relocation (abfd,
info,
@@ -4165,22 +4415,20 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
case R_MIPS_GOT16:
case R_MIPS_CALL16:
- if (local_p)
+ /* VxWorks does not have separate local and global semantics for
+ R_MIPS_GOT16; every relocation evaluates to "G". */
+ if (!htab->is_vxworks && local_p)
{
bfd_boolean forced;
- /* The special case is when the symbol is forced to be local. We
- need the full address in the GOT since no R_MIPS_LO16 relocation
- follows. */
forced = ! mips_elf_local_relocation_p (input_bfd, relocation,
local_sections, FALSE);
- value = mips_elf_got16_entry (abfd, input_bfd, info,
+ value = mips_elf_got16_entry (abfd, input_bfd, info, sec,
symbol + addend, forced);
if (value == MINUS_ONE)
return bfd_reloc_outofrange;
value
- = mips_elf_got_offset_from_index (elf_hash_table (info)->dynobj,
- abfd, input_bfd, value);
+ = mips_elf_got_offset_from_index (dynobj, abfd, input_bfd, value);
overflowed_p = mips_elf_overflow_p (value, 16);
break;
}
@@ -4230,17 +4478,18 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
0. */
if (! local_p)
goto got_disp;
- value = mips_elf_got_page (abfd, input_bfd, info, symbol + addend, NULL);
+ value = mips_elf_got_page (abfd, input_bfd, info, sec,
+ symbol + addend, NULL);
if (value == MINUS_ONE)
return bfd_reloc_outofrange;
- value = mips_elf_got_offset_from_index (elf_hash_table (info)->dynobj,
- abfd, input_bfd, value);
+ value = mips_elf_got_offset_from_index (dynobj, abfd, input_bfd, value);
overflowed_p = mips_elf_overflow_p (value, 16);
break;
case R_MIPS_GOT_OFST:
if (local_p)
- mips_elf_got_page (abfd, input_bfd, info, symbol + addend, &value);
+ mips_elf_got_page (abfd, input_bfd, info, sec,
+ symbol + addend, &value);
else
value = addend;
overflowed_p = mips_elf_overflow_p (value, 16);
@@ -4425,23 +4674,31 @@ mips_elf_stub_section_p (bfd *abfd ATTRIBUTE_UNUSED, asection *section)
|| strncmp (name, CALL_FP_STUB, sizeof CALL_FP_STUB - 1) == 0);
}
-/* Add room for N relocations to the .rel.dyn section in ABFD. */
+/* Add room for N relocations to the .rel(a).dyn section in ABFD. */
static void
-mips_elf_allocate_dynamic_relocations (bfd *abfd, unsigned int n)
+mips_elf_allocate_dynamic_relocations (bfd *abfd, struct bfd_link_info *info,
+ unsigned int n)
{
asection *s;
+ struct mips_elf_link_hash_table *htab;
- s = mips_elf_rel_dyn_section (abfd, FALSE);
+ htab = mips_elf_hash_table (info);
+ s = mips_elf_rel_dyn_section (info, FALSE);
BFD_ASSERT (s != NULL);
- if (s->size == 0)
+ if (htab->is_vxworks)
+ s->size += n * MIPS_ELF_RELA_SIZE (abfd);
+ else
{
- /* Make room for a null element. */
- s->size += MIPS_ELF_REL_SIZE (abfd);
- ++s->reloc_count;
+ if (s->size == 0)
+ {
+ /* Make room for a null element. */
+ s->size += MIPS_ELF_REL_SIZE (abfd);
+ ++s->reloc_count;
+ }
+ s->size += n * MIPS_ELF_REL_SIZE (abfd);
}
- s->size += n * MIPS_ELF_REL_SIZE (abfd);
}
/* Create a rel.dyn relocation for the dynamic linker to resolve. REL
@@ -4463,10 +4720,12 @@ mips_elf_create_dynamic_relocation (bfd *output_bfd,
int r_type;
long indx;
bfd_boolean defined_p;
+ struct mips_elf_link_hash_table *htab;
+ htab = mips_elf_hash_table (info);
r_type = ELF_R_TYPE (output_bfd, rel->r_info);
dynobj = elf_hash_table (info)->dynobj;
- sreloc = mips_elf_rel_dyn_section (dynobj, FALSE);
+ sreloc = mips_elf_rel_dyn_section (info, FALSE);
BFD_ASSERT (sreloc != NULL);
BFD_ASSERT (sreloc->contents != NULL);
BFD_ASSERT (sreloc->reloc_count * MIPS_ELF_REL_SIZE (output_bfd)
@@ -4551,10 +4810,15 @@ mips_elf_create_dynamic_relocation (bfd *output_bfd,
if (defined_p && r_type != R_MIPS_REL32)
*addendp += symbol;
- /* The relocation is always an REL32 relocation because we don't
- know where the shared library will wind up at load-time. */
- outrel[0].r_info = ELF_R_INFO (output_bfd, (unsigned long) indx,
- R_MIPS_REL32);
+ if (htab->is_vxworks)
+ /* VxWorks uses non-relative relocations for this. */
+ outrel[0].r_info = ELF32_R_INFO (indx, R_MIPS_32);
+ else
+ /* The relocation is always an REL32 relocation because we don't
+ know where the shared library will wind up at load-time. */
+ outrel[0].r_info = ELF_R_INFO (output_bfd, (unsigned long) indx,
+ R_MIPS_REL32);
+
/* For strict adherence to the ABI specification, we should
generate a R_MIPS_64 relocation record by itself before the
_REL32/_64 record as well, such that the addend is read in as
@@ -4592,6 +4856,15 @@ mips_elf_create_dynamic_relocation (bfd *output_bfd,
(sreloc->contents
+ sreloc->reloc_count * sizeof (Elf64_Mips_External_Rel)));
}
+ else if (htab->is_vxworks)
+ {
+ /* VxWorks uses RELA rather than REL dynamic relocations. */
+ outrel[0].r_addend = *addendp;
+ bfd_elf32_swap_reloca_out
+ (output_bfd, &outrel[0],
+ (sreloc->contents
+ + sreloc->reloc_count * sizeof (Elf32_External_Rela)));
+ }
else
bfd_elf32_swap_reloc_out
(output_bfd, &outrel[0],
@@ -5608,23 +5881,29 @@ _bfd_mips_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
flagword flags;
register asection *s;
const char * const *namep;
+ struct mips_elf_link_hash_table *htab;
+ htab = mips_elf_hash_table (info);
flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
| SEC_LINKER_CREATED | SEC_READONLY);
- /* Mips ABI requests the .dynamic section to be read only. */
- s = bfd_get_section_by_name (abfd, ".dynamic");
- if (s != NULL)
+ /* The psABI requires a read-only .dynamic section, but the VxWorks
+ EABI doesn't. */
+ if (!htab->is_vxworks)
{
- if (! bfd_set_section_flags (abfd, s, flags))
- return FALSE;
+ s = bfd_get_section_by_name (abfd, ".dynamic");
+ if (s != NULL)
+ {
+ if (! bfd_set_section_flags (abfd, s, flags))
+ return FALSE;
+ }
}
/* We need to create .got section. */
if (! mips_elf_create_got_section (abfd, info, FALSE))
return FALSE;
- if (! mips_elf_rel_dyn_section (elf_hash_table (info)->dynobj, TRUE))
+ if (! mips_elf_rel_dyn_section (info, TRUE))
return FALSE;
/* Create .stub section. */
@@ -5745,6 +6024,45 @@ _bfd_mips_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
}
}
+ if (htab->is_vxworks)
+ {
+ /* Create the .plt, .rela.plt, .dynbss and .rela.bss sections.
+ Also create the _PROCEDURE_LINKAGE_TABLE symbol. */
+ if (!_bfd_elf_create_dynamic_sections (abfd, info))
+ return FALSE;
+
+ /* Cache the sections created above. */
+ htab->sdynbss = bfd_get_section_by_name (abfd, ".dynbss");
+ htab->srelbss = bfd_get_section_by_name (abfd, ".rela.bss");
+ htab->srelplt = bfd_get_section_by_name (abfd, ".rela.plt");
+ htab->splt = bfd_get_section_by_name (abfd, ".plt");
+ if (!htab->sdynbss
+ || (!htab->srelbss && !info->shared)
+ || !htab->srelplt
+ || !htab->splt)
+ abort ();
+
+ /* Do the usual VxWorks handling. */
+ if (!elf_vxworks_create_dynamic_sections (abfd, info, &htab->srelplt2))
+ return FALSE;
+
+ /* Work out the PLT sizes. */
+ if (info->shared)
+ {
+ htab->plt_header_size
+ = 4 * ARRAY_SIZE (mips_vxworks_shared_plt0_entry);
+ htab->plt_entry_size
+ = 4 * ARRAY_SIZE (mips_vxworks_shared_plt_entry);
+ }
+ else
+ {
+ htab->plt_header_size
+ = 4 * ARRAY_SIZE (mips_vxworks_exec_plt0_entry);
+ htab->plt_entry_size
+ = 4 * ARRAY_SIZE (mips_vxworks_exec_plt_entry);
+ }
+ }
+
return TRUE;
}
@@ -5766,10 +6084,12 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
asection *sgot;
asection *sreloc;
const struct elf_backend_data *bed;
+ struct mips_elf_link_hash_table *htab;
if (info->relocatable)
return TRUE;
+ htab = mips_elf_hash_table (info);
dynobj = elf_hash_table (info)->dynobj;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (abfd);
@@ -6011,13 +6331,24 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
if (! mips_elf_create_got_section (dynobj, info, FALSE))
return FALSE;
g = mips_elf_got_info (dynobj, &sgot);
+ if (htab->is_vxworks && !info->shared)
+ {
+ (*_bfd_error_handler)
+ (_("%B: GOT reloc at 0x%lx not expected in executables"),
+ abfd, (unsigned long) rel->r_offset);
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
break;
case R_MIPS_32:
case R_MIPS_REL32:
case R_MIPS_64:
+ /* In VxWorks executables, references to external symbols
+ are handled using copy relocs or PLT stubs, so there's
+ no need to add a dynamic relocation here. */
if (dynobj == NULL
- && (info->shared || h != NULL)
+ && (info->shared || (h != NULL && !htab->is_vxworks))
&& (sec->flags & SEC_ALLOC) != 0)
elf_hash_table (info)->dynobj = dynobj = abfd;
break;
@@ -6027,15 +6358,35 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
}
}
- if (!h && (r_type == R_MIPS_CALL_LO16
- || r_type == R_MIPS_GOT_LO16
- || r_type == R_MIPS_GOT_DISP))
+ if (h)
+ {
+ ((struct mips_elf_link_hash_entry *) h)->is_relocation_target = TRUE;
+
+ /* Relocations against the special VxWorks __GOTT_BASE__ and
+ __GOTT_INDEX__ symbols must be left to the loader. Allocate
+ room for them in .rela.dyn. */
+ if (is_gott_symbol (info, h))
+ {
+ if (sreloc == NULL)
+ {
+ sreloc = mips_elf_rel_dyn_section (info, TRUE);
+ if (sreloc == NULL)
+ return FALSE;
+ }
+ mips_elf_allocate_dynamic_relocations (dynobj, info, 1);
+ }
+ }
+ else if (r_type == R_MIPS_CALL_LO16
+ || r_type == R_MIPS_GOT_LO16
+ || r_type == R_MIPS_GOT_DISP
+ || (r_type == R_MIPS_GOT16 && htab->is_vxworks))
{
/* We may need a local GOT entry for this relocation. We
don't count R_MIPS_GOT_PAGE because we can estimate the
maximum number of pages needed by looking at the size of
the segment. Similar comments apply to R_MIPS_GOT16 and
- R_MIPS_CALL16. We don't count R_MIPS_GOT_HI16, or
+ R_MIPS_CALL16, except on VxWorks, where GOT relocations
+ always evaluate to "G". We don't count R_MIPS_GOT_HI16, or
R_MIPS_CALL_HI16 because these are always followed by an
R_MIPS_GOT_LO16 or R_MIPS_CALL_LO16. */
if (! mips_elf_record_local_got_symbol (abfd, r_symndx,
@@ -6060,8 +6411,11 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
case R_MIPS_CALL_LO16:
if (h != NULL)
{
- /* This symbol requires a global offset table entry. */
- if (! mips_elf_record_global_got_symbol (h, abfd, info, g, 0))
+ /* VxWorks call relocations point the function's .got.plt
+ entry, which will be allocated by adjust_dynamic_symbol.
+ Otherwise, this symbol requires a global GOT entry. */
+ if (!htab->is_vxworks
+ && !mips_elf_record_global_got_symbol (h, abfd, info, g, 0))
return FALSE;
/* We need a stub, not a plt entry for the undefined
@@ -6147,12 +6501,15 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
case R_MIPS_32:
case R_MIPS_REL32:
case R_MIPS_64:
- if ((info->shared || h != NULL)
+ /* In VxWorks executables, references to external symbols
+ are handled using copy relocs or PLT stubs, so there's
+ no need to add a .rela.dyn entry for this relocation. */
+ if ((info->shared || (h != NULL && !htab->is_vxworks))
&& (sec->flags & SEC_ALLOC) != 0)
{
if (sreloc == NULL)
{
- sreloc = mips_elf_rel_dyn_section (dynobj, TRUE);
+ sreloc = mips_elf_rel_dyn_section (info, TRUE);
if (sreloc == NULL)
return FALSE;
}
@@ -6161,9 +6518,8 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
{
/* When creating a shared object, we must copy these
reloc types into the output file as R_MIPS_REL32
- relocs. We make room for this reloc in the
- .rel.dyn reloc section. */
- mips_elf_allocate_dynamic_relocations (dynobj, 1);
+ relocs. Make room for this reloc in .rel(a).dyn. */
+ mips_elf_allocate_dynamic_relocations (dynobj, info, 1);
if ((sec->flags & MIPS_READONLY_SECTION)
== MIPS_READONLY_SECTION)
/* We tell the dynamic linker that there are
@@ -6188,8 +6544,10 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
/* Even though we don't directly need a GOT entry for
this symbol, a symbol must have a dynamic symbol
table index greater that DT_MIPS_GOTSYM if there are
- dynamic relocations against it. */
- if (h != NULL)
+ dynamic relocations against it. This does not apply
+ to VxWorks, which does not have the usual coupling
+ between global GOT entries and .dynsym entries. */
+ if (h != NULL && !htab->is_vxworks)
{
if (dynobj == NULL)
elf_hash_table (info)->dynobj = dynobj = abfd;
@@ -6206,7 +6564,16 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
sizeof (Elf32_External_crinfo);
break;
+ case R_MIPS_PC16:
+ if (h)
+ ((struct mips_elf_link_hash_entry *) h)->is_branch_target = TRUE;
+ break;
+
case R_MIPS_26:
+ if (h)
+ ((struct mips_elf_link_hash_entry *) h)->is_branch_target = TRUE;
+ /* Fall through. */
+
case R_MIPS_GPREL16:
case R_MIPS_LITERAL:
case R_MIPS_GPREL32:
@@ -6234,24 +6601,21 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
}
/* We must not create a stub for a symbol that has relocations
- related to taking the function's address. */
- switch (r_type)
- {
- default:
- if (h != NULL)
- {
- struct mips_elf_link_hash_entry *mh;
-
- mh = (struct mips_elf_link_hash_entry *) h;
- mh->no_fn_stub = TRUE;
- }
- break;
- case R_MIPS_CALL16:
- case R_MIPS_CALL_HI16:
- case R_MIPS_CALL_LO16:
- case R_MIPS_JALR:
- break;
- }
+ related to taking the function's address. This doesn't apply to
+ VxWorks, where CALL relocs refer to a .got.plt entry instead of
+ a normal .got entry. */
+ if (!htab->is_vxworks && h != NULL)
+ switch (r_type)
+ {
+ default:
+ ((struct mips_elf_link_hash_entry *) h)->no_fn_stub = TRUE;
+ break;
+ case R_MIPS_CALL16:
+ case R_MIPS_CALL_HI16:
+ case R_MIPS_CALL_LO16:
+ case R_MIPS_JALR:
+ break;
+ }
/* If this reloc is not a 16 bit call, and it has a global
symbol, then we will need the fn_stub if there is one.
@@ -6478,8 +6842,8 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
&& (h->root.type == bfd_link_hash_defweak
|| !h->def_regular))
{
- mips_elf_allocate_dynamic_relocations (dynobj,
- hmips->possibly_dynamic_relocs);
+ mips_elf_allocate_dynamic_relocations
+ (dynobj, info, hmips->possibly_dynamic_relocs);
if (hmips->readonly_reloc)
/* We tell the dynamic linker that there are relocations
against the text segment. */
@@ -6544,6 +6908,160 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
return TRUE;
}
+
+/* Likewise, for VxWorks. */
+
+bfd_boolean
+_bfd_mips_vxworks_adjust_dynamic_symbol (struct bfd_link_info *info,
+ struct elf_link_hash_entry *h)
+{
+ bfd *dynobj;
+ struct mips_elf_link_hash_entry *hmips;
+ struct mips_elf_link_hash_table *htab;
+ unsigned int power_of_two;
+
+ htab = mips_elf_hash_table (info);
+ dynobj = elf_hash_table (info)->dynobj;
+ hmips = (struct mips_elf_link_hash_entry *) h;
+
+ /* Make sure we know what is going on here. */
+ BFD_ASSERT (dynobj != NULL
+ && (h->needs_plt
+ || h->needs_copy
+ || h->u.weakdef != NULL
+ || (h->def_dynamic
+ && h->ref_regular
+ && !h->def_regular)));
+
+ /* If the symbol is defined by a dynamic object, we need a PLT stub if
+ either (a) we want to branch to the symbol or (b) we're linking an
+ executable that needs a canonical function address. In the latter
+ case, the canonical address will be the address of the executable's
+ load stub. */
+ if ((hmips->is_branch_target
+ || (!info->shared
+ && h->type == STT_FUNC
+ && hmips->is_relocation_target))
+ && h->def_dynamic
+ && h->ref_regular
+ && !h->def_regular
+ && !h->forced_local)
+ h->needs_plt = 1;
+
+ /* Locally-binding symbols do not need a PLT stub; we can refer to
+ the functions directly. */
+ else if (h->needs_plt
+ && (SYMBOL_CALLS_LOCAL (info, h)
+ || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+ && h->root.type == bfd_link_hash_undefweak)))
+ {
+ h->needs_plt = 0;
+ return TRUE;
+ }
+
+ if (h->needs_plt)
+ {
+ /* If this is the first symbol to need a PLT entry, allocate room
+ for the header, and for the header's .rela.plt.unloaded entries. */
+ if (htab->splt->size == 0)
+ {
+ htab->splt->size += htab->plt_header_size;
+ if (!info->shared)
+ htab->srelplt2->size += 2 * sizeof (Elf32_External_Rela);
+ }
+
+ /* Assign the next .plt entry to this symbol. */
+ h->plt.offset = htab->splt->size;
+ htab->splt->size += htab->plt_entry_size;
+
+ /* If the output file has no definition of the symbol, set the
+ symbol's value to the address of the stub. For executables,
+ point at the PLT load stub rather than the lazy resolution stub;
+ this stub will become the canonical function address. */
+ if (!h->def_regular)
+ {
+ h->root.u.def.section = htab->splt;
+ h->root.u.def.value = h->plt.offset;
+ if (!info->shared)
+ h->root.u.def.value += 8;
+ }
+
+ /* Make room for the .got.plt entry and the R_JUMP_SLOT relocation. */
+ htab->sgotplt->size += 4;
+ htab->srelplt->size += sizeof (Elf32_External_Rela);
+
+ /* Make room for the .rela.plt.unloaded relocations. */
+ if (!info->shared)
+ htab->srelplt2->size += 3 * sizeof (Elf32_External_Rela);
+
+ return TRUE;
+ }
+
+ /* If a function symbol is defined by a dynamic object, and we do not
+ need a PLT stub for it, the symbol's value should be zero. */
+ if (h->type == STT_FUNC
+ && h->def_dynamic
+ && h->ref_regular
+ && !h->def_regular)
+ {
+ h->root.u.def.value = 0;
+ return TRUE;
+ }
+
+ /* If this is a weak symbol, and there is a real definition, the
+ processor independent code will have arranged for us to see the
+ real definition first, and we can just use the same value. */
+ if (h->u.weakdef != NULL)
+ {
+ BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
+ || h->u.weakdef->root.type == bfd_link_hash_defweak);
+ h->root.u.def.section = h->u.weakdef->root.u.def.section;
+ h->root.u.def.value = h->u.weakdef->root.u.def.value;
+ return TRUE;
+ }
+
+ /* This is a reference to a symbol defined by a dynamic object which
+ is not a function. */
+ if (info->shared)
+ return TRUE;
+
+ /* We must allocate the symbol in our .dynbss section, which will
+ become part of the .bss section of the executable. There will be
+ an entry for this symbol in the .dynsym section. The dynamic
+ object will contain position independent code, so all references
+ from the dynamic object to this symbol will go through the global
+ offset table. The dynamic linker will use the .dynsym entry to
+ determine the address it must put in the global offset table, so
+ both the dynamic object and the regular object will refer to the
+ same memory location for the variable. */
+
+ if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
+ {
+ htab->srelbss->size += sizeof (Elf32_External_Rela);
+ h->needs_copy = 1;
+ }
+
+ /* We need to figure out the alignment required for this symbol. */
+ power_of_two = bfd_log2 (h->size);
+ if (power_of_two > 4)
+ power_of_two = 4;
+
+ /* Apply the required alignment. */
+ htab->sdynbss->size = BFD_ALIGN (htab->sdynbss->size,
+ (bfd_size_type) 1 << power_of_two);
+ if (power_of_two > bfd_get_section_alignment (dynobj, htab->sdynbss)
+ && !bfd_set_section_alignment (dynobj, htab->sdynbss, power_of_two))
+ return FALSE;
+
+ /* Define the symbol as being at this point in the section. */
+ h->root.u.def.section = htab->sdynbss;
+ h->root.u.def.value = htab->sdynbss->size;
+
+ /* Increment the section size to make room for the symbol. */
+ htab->sdynbss->size += h->size;
+
+ return TRUE;
+}
/* This function is called after all the input files have been read,
and the input sections have been assigned to output sections. We
@@ -6563,6 +7081,9 @@ _bfd_mips_elf_always_size_sections (bfd *output_bfd,
bfd_size_type local_gotno;
bfd *sub;
struct mips_elf_count_tls_arg count_tls_arg;
+ struct mips_elf_link_hash_table *htab;
+
+ htab = mips_elf_hash_table (info);
/* The .reginfo section has a fixed size. */
ri = bfd_get_section_by_name (output_bfd, ".reginfo");
@@ -6621,9 +7142,15 @@ _bfd_mips_elf_always_size_sections (bfd *output_bfd,
rld. */
loadable_size += MIPS_FUNCTION_STUB_SIZE * (i + 1);
- /* Assume there are two loadable segments consisting of
- contiguous sections. Is 5 enough? */
- local_gotno = (loadable_size >> 16) + 5;
+ if (htab->is_vxworks)
+ /* There's no need to allocate page entries for VxWorks; R_MIPS_GOT16
+ relocations against local symbols evaluate to "G", and the EABI does
+ not include R_MIPS_GOT_PAGE. */
+ local_gotno = 0;
+ else
+ /* Assume there are two loadable segments consisting of contiguous
+ sections. Is 5 enough? */
+ local_gotno = (loadable_size >> 16) + 5;
g->local_gotno += local_gotno;
s->size += g->local_gotno * MIPS_ELF_GOT_SIZE (output_bfd);
@@ -6644,7 +7171,10 @@ _bfd_mips_elf_always_size_sections (bfd *output_bfd,
mips_elf_resolve_final_got_entries (g);
- if (s->size > MIPS_ELF_GOT_MAX_SIZE (output_bfd))
+ /* VxWorks does not support multiple GOTs. It initializes $gp to
+ __GOTT_BASE__[__GOTT_INDEX__], the value of which is set by the
+ dynamic loader. */
+ if (!htab->is_vxworks && s->size > MIPS_ELF_GOT_MAX_SIZE (info))
{
if (! mips_elf_multi_got (output_bfd, info, g, s, local_gotno))
return FALSE;
@@ -6666,9 +7196,11 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
struct bfd_link_info *info)
{
bfd *dynobj;
- asection *s;
+ asection *s, *sreldyn;
bfd_boolean reltext;
+ struct mips_elf_link_hash_table *htab;
+ htab = mips_elf_hash_table (info);
dynobj = elf_hash_table (info)->dynobj;
BFD_ASSERT (dynobj != NULL);
@@ -6690,6 +7222,7 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
determined the sizes of the various dynamic sections. Allocate
memory for them. */
reltext = FALSE;
+ sreldyn = NULL;
for (s = dynobj->sections; s != NULL; s = s->next)
{
const char *name;
@@ -6710,7 +7243,7 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
/* If this relocation section applies to a read only
section, then we probably need a DT_TEXTREL entry.
- If the relocation section is .rel.dyn, we always
+ If the relocation section is .rel(a).dyn, we always
assert a DT_TEXTREL entry rather than testing whether
there exists a relocation to a read only section or
not. */
@@ -6720,12 +7253,12 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
if ((target != NULL
&& (target->flags & SEC_READONLY) != 0
&& (target->flags & SEC_ALLOC) != 0)
- || strcmp (outname, ".rel.dyn") == 0)
+ || strcmp (outname, MIPS_ELF_REL_DYN_NAME (info)) == 0)
reltext = TRUE;
/* We use the reloc_count field as a counter if we need
to copy relocs into the output file. */
- if (strcmp (name, ".rel.dyn") != 0)
+ if (strcmp (name, MIPS_ELF_REL_DYN_NAME (info)) != 0)
s->reloc_count = 0;
/* If combreloc is enabled, elf_link_sort_relocs() will
@@ -6737,7 +7270,23 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
info->combreloc = 0;
}
}
- else if (strncmp (name, ".got", 4) == 0)
+ else if (htab->is_vxworks && strcmp (name, ".got") == 0)
+ {
+ /* Executables do not need a GOT. */
+ if (info->shared)
+ {
+ /* Allocate relocations for all but the reserved entries. */
+ struct mips_got_info *g;
+ unsigned int count;
+
+ g = mips_elf_got_info (dynobj, NULL);
+ count = (g->global_gotno
+ + g->local_gotno
+ - MIPS_RESERVED_GOTNO (info));
+ mips_elf_allocate_dynamic_relocations (dynobj, info, count);
+ }
+ }
+ else if (!htab->is_vxworks && strncmp (name, ".got", 4) == 0)
{
/* _bfd_mips_elf_always_size_sections() has already done
most of the work, but some symbols may have been mapped
@@ -6782,7 +7331,7 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
BFD_ASSERT (g->assigned_gotno == g->next->local_gotno
+ g->next->global_gotno
+ g->next->tls_gotno
- + MIPS_RESERVED_GOTNO);
+ + MIPS_RESERVED_GOTNO (info));
}
}
}
@@ -6802,7 +7351,8 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
}
if (needed_relocs)
- mips_elf_allocate_dynamic_relocations (dynobj, needed_relocs);
+ mips_elf_allocate_dynamic_relocations (dynobj, info,
+ needed_relocs);
}
else if (strcmp (name, MIPS_ELF_STUB_SECTION_NAME (output_bfd)) == 0)
{
@@ -6821,7 +7371,9 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
else if (SGI_COMPAT (output_bfd)
&& strncmp (name, ".compact_rel", 12) == 0)
s->size += mips_elf_hash_table (info)->compact_rel_size;
- else if (strncmp (name, ".init", 5) != 0)
+ else if (strncmp (name, ".init", 5) != 0
+ && s != htab->sgotplt
+ && s != htab->splt)
{
/* It's not one of our sections, so don't allocate space. */
continue;
@@ -6836,6 +7388,14 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
if ((s->flags & SEC_HAS_CONTENTS) == 0)
continue;
+ /* Allocate memory for this section last, since we may increase its
+ size above. */
+ if (strcmp (name, MIPS_ELF_REL_DYN_NAME (info)) == 0)
+ {
+ sreldyn = s;
+ continue;
+ }
+
/* Allocate memory for the section contents. */
s->contents = bfd_zalloc (dynobj, s->size);
if (s->contents == NULL)
@@ -6845,6 +7405,17 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
}
}
+ /* Allocate memory for the .rel(a).dyn section. */
+ if (sreldyn != NULL)
+ {
+ sreldyn->contents = bfd_zalloc (dynobj, sreldyn->size);
+ if (sreldyn->contents == NULL)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return FALSE;
+ }
+ }
+
if (elf_hash_table (info)->dynamic_sections_created)
{
/* Add some entries to the .dynamic section. We fill in the
@@ -6874,7 +7445,7 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
}
}
- if (reltext && SGI_COMPAT (output_bfd))
+ if (reltext && (SGI_COMPAT (output_bfd) || htab->is_vxworks))
info->flags |= DF_TEXTREL;
if ((info->flags & DF_TEXTREL) != 0)
@@ -6886,53 +7457,125 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_PLTGOT, 0))
return FALSE;
- if (mips_elf_rel_dyn_section (dynobj, FALSE))
+ if (htab->is_vxworks)
{
- if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_REL, 0))
- return FALSE;
+ /* VxWorks uses .rela.dyn instead of .rel.dyn. It does not
+ use any of the DT_MIPS_* tags. */
+ if (mips_elf_rel_dyn_section (info, FALSE))
+ {
+ if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELA, 0))
+ return FALSE;
- if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELSZ, 0))
- return FALSE;
+ if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELASZ, 0))
+ return FALSE;
- if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELENT, 0))
- return FALSE;
+ if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELAENT, 0))
+ return FALSE;
+ }
+ if (htab->splt->size > 0)
+ {
+ if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_PLTREL, 0))
+ return FALSE;
+
+ if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_JMPREL, 0))
+ return FALSE;
+
+ if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_PLTRELSZ, 0))
+ return FALSE;
+ }
}
+ else
+ {
+ if (mips_elf_rel_dyn_section (info, FALSE))
+ {
+ if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_REL, 0))
+ return FALSE;
- if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_RLD_VERSION, 0))
- return FALSE;
+ if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELSZ, 0))
+ return FALSE;
- if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_FLAGS, 0))
- return FALSE;
+ if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELENT, 0))
+ return FALSE;
+ }
- if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_BASE_ADDRESS, 0))
- return FALSE;
+ if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_RLD_VERSION, 0))
+ return FALSE;
- if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_LOCAL_GOTNO, 0))
- return FALSE;
+ if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_FLAGS, 0))
+ return FALSE;
- if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_SYMTABNO, 0))
- return FALSE;
+ if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_BASE_ADDRESS, 0))
+ return FALSE;
- if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_UNREFEXTNO, 0))
- return FALSE;
+ if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_LOCAL_GOTNO, 0))
+ return FALSE;
- if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_GOTSYM, 0))
- return FALSE;
+ if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_SYMTABNO, 0))
+ return FALSE;
- if (IRIX_COMPAT (dynobj) == ict_irix5
- && ! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_HIPAGENO, 0))
- return FALSE;
+ if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_UNREFEXTNO, 0))
+ return FALSE;
- if (IRIX_COMPAT (dynobj) == ict_irix6
- && (bfd_get_section_by_name
- (dynobj, MIPS_ELF_OPTIONS_SECTION_NAME (dynobj)))
- && !MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_OPTIONS, 0))
- return FALSE;
+ if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_GOTSYM, 0))
+ return FALSE;
+
+ if (IRIX_COMPAT (dynobj) == ict_irix5
+ && ! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_HIPAGENO, 0))
+ return FALSE;
+
+ if (IRIX_COMPAT (dynobj) == ict_irix6
+ && (bfd_get_section_by_name
+ (dynobj, MIPS_ELF_OPTIONS_SECTION_NAME (dynobj)))
+ && !MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_OPTIONS, 0))
+ return FALSE;
+ }
}
return TRUE;
}
+/* REL is a relocation in INPUT_BFD that is being copied to OUTPUT_BFD.
+ Adjust its R_ADDEND field so that it is correct for the output file.
+ LOCAL_SYMS and LOCAL_SECTIONS are arrays of INPUT_BFD's local symbols
+ and sections respectively; both use symbol indexes. */
+
+static void
+mips_elf_adjust_addend (bfd *output_bfd, struct bfd_link_info *info,
+ bfd *input_bfd, Elf_Internal_Sym *local_syms,
+ asection **local_sections, Elf_Internal_Rela *rel)
+{
+ unsigned int r_type, r_symndx;
+ Elf_Internal_Sym *sym;
+ asection *sec;
+
+ if (mips_elf_local_relocation_p (input_bfd, rel, local_sections, FALSE))
+ {
+ r_type = ELF_R_TYPE (output_bfd, rel->r_info);
+ if (r_type == R_MIPS16_GPREL
+ || r_type == R_MIPS_GPREL16
+ || r_type == R_MIPS_GPREL32
+ || r_type == R_MIPS_LITERAL)
+ {
+ rel->r_addend += _bfd_get_gp_value (input_bfd);
+ rel->r_addend -= _bfd_get_gp_value (output_bfd);
+ }
+
+ r_symndx = ELF_R_SYM (output_bfd, rel->r_info);
+ sym = local_syms + r_symndx;
+
+ /* Adjust REL's addend to account for section merging. */
+ if (!info->relocatable)
+ {
+ sec = local_sections[r_symndx];
+ _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
+ }
+
+ /* This would normally be done by the rela_normal code in elflink.c. */
+ if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
+ rel->r_addend += local_sections[r_symndx]->output_offset;
+ }
+}
+
/* Relocate a MIPS ELF section. */
bfd_boolean
@@ -7083,47 +7726,19 @@ _bfd_mips_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
}
else
addend = rel->r_addend;
+ mips_elf_adjust_addend (output_bfd, info, input_bfd,
+ local_syms, local_sections, rel);
}
if (info->relocatable)
{
- Elf_Internal_Sym *sym;
- unsigned long r_symndx;
-
if (r_type == R_MIPS_64 && ! NEWABI_P (output_bfd)
&& bfd_big_endian (input_bfd))
rel->r_offset -= 4;
- /* Since we're just relocating, all we need to do is copy
- the relocations back out to the object file, unless
- they're against a section symbol, in which case we need
- to adjust by the section offset, or unless they're GP
- relative in which case we need to adjust by the amount
- that we're adjusting GP in this relocatable object. */
-
- if (! mips_elf_local_relocation_p (input_bfd, rel, local_sections,
- FALSE))
- /* There's nothing to do for non-local relocations. */
- continue;
-
- if (r_type == R_MIPS16_GPREL
- || r_type == R_MIPS_GPREL16
- || r_type == R_MIPS_GPREL32
- || r_type == R_MIPS_LITERAL)
- addend -= (_bfd_get_gp_value (output_bfd)
- - _bfd_get_gp_value (input_bfd));
-
- r_symndx = ELF_R_SYM (output_bfd, rel->r_info);
- sym = local_syms + r_symndx;
- if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
- /* Adjust the addend appropriately. */
- addend += local_sections[r_symndx]->output_offset;
-
- if (rela_relocation_p)
- /* If this is a RELA relocation, just update the addend. */
- rel->r_addend = addend;
- else
+ if (!rela_relocation_p && rel->r_addend)
{
+ addend += rel->r_addend;
if (r_type == R_MIPS_HI16
|| r_type == R_MIPS_GOT16)
addend = mips_elf_high (addend);
@@ -7569,6 +8184,268 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
return TRUE;
}
+/* Likewise, for VxWorks. */
+
+bfd_boolean
+_bfd_mips_vxworks_finish_dynamic_symbol (bfd *output_bfd,
+ struct bfd_link_info *info,
+ struct elf_link_hash_entry *h,
+ Elf_Internal_Sym *sym)
+{
+ bfd *dynobj;
+ asection *sgot;
+ struct mips_got_info *g;
+ struct mips_elf_link_hash_table *htab;
+
+ htab = mips_elf_hash_table (info);
+ dynobj = elf_hash_table (info)->dynobj;
+
+ if (h->plt.offset != (bfd_vma) -1)
+ {
+ bfd_byte *loc;
+ bfd_vma plt_address, plt_index, got_address, got_offset, branch_offset;
+ Elf_Internal_Rela rel;
+ static const bfd_vma *plt_entry;
+
+ BFD_ASSERT (h->dynindx != -1);
+ BFD_ASSERT (htab->splt != NULL);
+ BFD_ASSERT (h->plt.offset <= htab->splt->size);
+
+ /* Calculate the address of the .plt entry. */
+ plt_address = (htab->splt->output_section->vma
+ + htab->splt->output_offset
+ + h->plt.offset);
+
+ /* Calculate the index of the entry. */
+ plt_index = ((h->plt.offset - htab->plt_header_size)
+ / htab->plt_entry_size);
+
+ /* Calculate the address of the .got.plt entry. */
+ got_address = (htab->sgotplt->output_section->vma
+ + htab->sgotplt->output_offset
+ + plt_index * 4);
+
+ /* Calculate the offset of the .got.plt entry from
+ _GLOBAL_OFFSET_TABLE_. */
+ got_offset = mips_elf_gotplt_index (info, h);
+
+ /* Calculate the offset for the branch at the start of the PLT
+ entry. The branch jumps to the beginning of .plt. */
+ branch_offset = -(h->plt.offset / 4 + 1) & 0xffff;
+
+ /* Fill in the initial value of the .got.plt entry. */
+ bfd_put_32 (output_bfd, plt_address,
+ htab->sgotplt->contents + plt_index * 4);
+
+ /* Find out where the .plt entry should go. */
+ loc = htab->splt->contents + h->plt.offset;
+
+ if (info->shared)
+ {
+ plt_entry = mips_vxworks_shared_plt_entry;
+ bfd_put_32 (output_bfd, plt_entry[0] | branch_offset, loc);
+ bfd_put_32 (output_bfd, plt_entry[1] | plt_index, loc + 4);
+ }
+ else
+ {
+ bfd_vma got_address_high, got_address_low;
+
+ plt_entry = mips_vxworks_exec_plt_entry;
+ got_address_high = ((got_address + 0x8000) >> 16) & 0xffff;
+ got_address_low = got_address & 0xffff;
+
+ bfd_put_32 (output_bfd, plt_entry[0] | branch_offset, loc);
+ bfd_put_32 (output_bfd, plt_entry[1] | plt_index, loc + 4);
+ bfd_put_32 (output_bfd, plt_entry[2] | got_address_high, loc + 8);
+ bfd_put_32 (output_bfd, plt_entry[3] | got_address_low, loc + 12);
+ bfd_put_32 (output_bfd, plt_entry[4], loc + 16);
+ bfd_put_32 (output_bfd, plt_entry[5], loc + 20);
+ bfd_put_32 (output_bfd, plt_entry[6], loc + 24);
+ bfd_put_32 (output_bfd, plt_entry[7], loc + 28);
+
+ loc = (htab->srelplt2->contents
+ + (plt_index * 3 + 2) * sizeof (Elf32_External_Rela));
+
+ /* Emit a relocation for the .got.plt entry. */
+ rel.r_offset = got_address;
+ rel.r_info = ELF32_R_INFO (htab->root.hplt->indx, R_MIPS_32);
+ rel.r_addend = h->plt.offset;
+ bfd_elf32_swap_reloca_out (output_bfd, &rel, loc);
+
+ /* Emit a relocation for the lui of %hi(<.got.plt slot>). */
+ loc += sizeof (Elf32_External_Rela);
+ rel.r_offset = plt_address + 8;
+ rel.r_info = ELF32_R_INFO (htab->root.hgot->indx, R_MIPS_HI16);
+ rel.r_addend = got_offset;
+ bfd_elf32_swap_reloca_out (output_bfd, &rel, loc);
+
+ /* Emit a relocation for the addiu of %lo(<.got.plt slot>). */
+ loc += sizeof (Elf32_External_Rela);
+ rel.r_offset += 4;
+ rel.r_info = ELF32_R_INFO (htab->root.hgot->indx, R_MIPS_LO16);
+ bfd_elf32_swap_reloca_out (output_bfd, &rel, loc);
+ }
+
+ /* Emit an R_MIPS_JUMP_SLOT relocation against the .got.plt entry. */
+ loc = htab->srelplt->contents + plt_index * sizeof (Elf32_External_Rela);
+ rel.r_offset = got_address;
+ rel.r_info = ELF32_R_INFO (h->dynindx, R_MIPS_JUMP_SLOT);
+ rel.r_addend = 0;
+ bfd_elf32_swap_reloca_out (output_bfd, &rel, loc);
+
+ if (!h->def_regular)
+ sym->st_shndx = SHN_UNDEF;
+ }
+
+ BFD_ASSERT (h->dynindx != -1 || h->forced_local);
+
+ sgot = mips_elf_got_section (dynobj, FALSE);
+ BFD_ASSERT (sgot != NULL);
+ BFD_ASSERT (mips_elf_section_data (sgot) != NULL);
+ g = mips_elf_section_data (sgot)->u.got_info;
+ BFD_ASSERT (g != NULL);
+
+ /* See if this symbol has an entry in the GOT. */
+ if (g->global_gotsym != NULL
+ && h->dynindx >= g->global_gotsym->dynindx)
+ {
+ bfd_vma offset;
+ Elf_Internal_Rela outrel;
+ bfd_byte *loc;
+ asection *s;
+
+ /* Install the symbol value in the GOT. */
+ offset = mips_elf_global_got_index (dynobj, output_bfd, h,
+ R_MIPS_GOT16, info);
+ MIPS_ELF_PUT_WORD (output_bfd, sym->st_value, sgot->contents + offset);
+
+ /* Add a dynamic relocation for it. */
+ s = mips_elf_rel_dyn_section (info, FALSE);
+ loc = s->contents + (s->reloc_count++ * sizeof (Elf32_External_Rela));
+ outrel.r_offset = (sgot->output_section->vma
+ + sgot->output_offset
+ + offset);
+ outrel.r_info = ELF32_R_INFO (h->dynindx, R_MIPS_32);
+ outrel.r_addend = 0;
+ bfd_elf32_swap_reloca_out (dynobj, &outrel, loc);
+ }
+
+ /* Emit a copy reloc, if needed. */
+ if (h->needs_copy)
+ {
+ Elf_Internal_Rela rel;
+
+ BFD_ASSERT (h->dynindx != -1);
+
+ rel.r_offset = (h->root.u.def.section->output_section->vma
+ + h->root.u.def.section->output_offset
+ + h->root.u.def.value);
+ rel.r_info = ELF32_R_INFO (h->dynindx, R_MIPS_COPY);
+ rel.r_addend = 0;
+ bfd_elf32_swap_reloca_out (output_bfd, &rel,
+ htab->srelbss->contents
+ + (htab->srelbss->reloc_count
+ * sizeof (Elf32_External_Rela)));
+ ++htab->srelbss->reloc_count;
+ }
+
+ /* If this is a mips16 symbol, force the value to be even. */
+ if (sym->st_other == STO_MIPS16)
+ sym->st_value &= ~1;
+
+ return TRUE;
+}
+
+/* Install the PLT header for a VxWorks executable and finalize the
+ contents of .rela.plt.unloaded. */
+
+static void
+mips_vxworks_finish_exec_plt (bfd *output_bfd, struct bfd_link_info *info)
+{
+ Elf_Internal_Rela rela;
+ bfd_byte *loc;
+ bfd_vma got_value, got_value_high, got_value_low, plt_address;
+ static const bfd_vma *plt_entry;
+ struct mips_elf_link_hash_table *htab;
+
+ htab = mips_elf_hash_table (info);
+ plt_entry = mips_vxworks_exec_plt0_entry;
+
+ /* Calculate the value of _GLOBAL_OFFSET_TABLE_. */
+ got_value = (htab->root.hgot->root.u.def.section->output_section->vma
+ + htab->root.hgot->root.u.def.section->output_offset
+ + htab->root.hgot->root.u.def.value);
+
+ got_value_high = ((got_value + 0x8000) >> 16) & 0xffff;
+ got_value_low = got_value & 0xffff;
+
+ /* Calculate the address of the PLT header. */
+ plt_address = htab->splt->output_section->vma + htab->splt->output_offset;
+
+ /* Install the PLT header. */
+ loc = htab->splt->contents;
+ bfd_put_32 (output_bfd, plt_entry[0] | got_value_high, loc);
+ bfd_put_32 (output_bfd, plt_entry[1] | got_value_low, loc + 4);
+ bfd_put_32 (output_bfd, plt_entry[2], loc + 8);
+ bfd_put_32 (output_bfd, plt_entry[3], loc + 12);
+ bfd_put_32 (output_bfd, plt_entry[4], loc + 16);
+ bfd_put_32 (output_bfd, plt_entry[5], loc + 20);
+
+ /* Output the relocation for the lui of %hi(_GLOBAL_OFFSET_TABLE_). */
+ loc = htab->srelplt2->contents;
+ rela.r_offset = plt_address;
+ rela.r_info = ELF32_R_INFO (htab->root.hgot->indx, R_MIPS_HI16);
+ rela.r_addend = 0;
+ bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
+ loc += sizeof (Elf32_External_Rela);
+
+ /* Output the relocation for the following addiu of
+ %lo(_GLOBAL_OFFSET_TABLE_). */
+ rela.r_offset += 4;
+ rela.r_info = ELF32_R_INFO (htab->root.hgot->indx, R_MIPS_LO16);
+ bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
+ loc += sizeof (Elf32_External_Rela);
+
+ /* Fix up the remaining relocations. They may have the wrong
+ symbol index for _G_O_T_ or _P_L_T_ depending on the order
+ in which symbols were output. */
+ while (loc < htab->srelplt2->contents + htab->srelplt2->size)
+ {
+ Elf_Internal_Rela rel;
+
+ bfd_elf32_swap_reloca_in (output_bfd, loc, &rel);
+ rel.r_info = ELF32_R_INFO (htab->root.hplt->indx, R_MIPS_32);
+ bfd_elf32_swap_reloca_out (output_bfd, &rel, loc);
+ loc += sizeof (Elf32_External_Rela);
+
+ bfd_elf32_swap_reloca_in (output_bfd, loc, &rel);
+ rel.r_info = ELF32_R_INFO (htab->root.hgot->indx, R_MIPS_HI16);
+ bfd_elf32_swap_reloca_out (output_bfd, &rel, loc);
+ loc += sizeof (Elf32_External_Rela);
+
+ bfd_elf32_swap_reloca_in (output_bfd, loc, &rel);
+ rel.r_info = ELF32_R_INFO (htab->root.hgot->indx, R_MIPS_LO16);
+ bfd_elf32_swap_reloca_out (output_bfd, &rel, loc);
+ loc += sizeof (Elf32_External_Rela);
+ }
+}
+
+/* Install the PLT header for a VxWorks shared library. */
+
+static void
+mips_vxworks_finish_shared_plt (bfd *output_bfd, struct bfd_link_info *info)
+{
+ unsigned int i;
+ struct mips_elf_link_hash_table *htab;
+
+ htab = mips_elf_hash_table (info);
+
+ /* We just need to copy the entry byte-by-byte. */
+ for (i = 0; i < ARRAY_SIZE (mips_vxworks_shared_plt0_entry); i++)
+ bfd_put_32 (output_bfd, mips_vxworks_shared_plt0_entry[i],
+ htab->splt->contents + i * 4);
+}
+
/* Finish up the dynamic sections. */
bfd_boolean
@@ -7579,7 +8456,9 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd,
asection *sdyn;
asection *sgot;
struct mips_got_info *gg, *g;
+ struct mips_elf_link_hash_table *htab;
+ htab = mips_elf_hash_table (info);
dynobj = elf_hash_table (info)->dynobj;
sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
@@ -7622,11 +8501,14 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd,
switch (dyn.d_tag)
{
case DT_RELENT:
- s = mips_elf_rel_dyn_section (dynobj, FALSE);
- BFD_ASSERT (s != NULL);
dyn.d_un.d_val = MIPS_ELF_REL_SIZE (dynobj);
break;
+ case DT_RELAENT:
+ BFD_ASSERT (htab->is_vxworks);
+ dyn.d_un.d_val = MIPS_ELF_RELA_SIZE (dynobj);
+ break;
+
case DT_STRSZ:
/* Rewrite DT_STRSZ. */
dyn.d_un.d_val =
@@ -7635,9 +8517,20 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd,
case DT_PLTGOT:
name = ".got";
- s = bfd_get_section_by_name (output_bfd, name);
- BFD_ASSERT (s != NULL);
- dyn.d_un.d_ptr = s->vma;
+ if (htab->is_vxworks)
+ {
+ /* _GLOBAL_OFFSET_TABLE_ is defined to be the beginning
+ of the ".got" section in DYNOBJ. */
+ s = bfd_get_section_by_name (dynobj, name);
+ BFD_ASSERT (s != NULL);
+ dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
+ }
+ else
+ {
+ s = bfd_get_section_by_name (output_bfd, name);
+ BFD_ASSERT (s != NULL);
+ dyn.d_un.d_ptr = s->vma;
+ }
break;
case DT_MIPS_RLD_VERSION:
@@ -7703,7 +8596,7 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd,
break;
case DT_MIPS_HIPAGENO:
- dyn.d_un.d_val = g->local_gotno - MIPS_RESERVED_GOTNO;
+ dyn.d_un.d_val = g->local_gotno - MIPS_RESERVED_GOTNO (info);
break;
case DT_MIPS_RLD_MAP:
@@ -7716,6 +8609,29 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd,
dyn.d_un.d_ptr = s->vma;
break;
+ case DT_RELASZ:
+ BFD_ASSERT (htab->is_vxworks);
+ /* The count does not include the JUMP_SLOT relocations. */
+ if (htab->srelplt)
+ dyn.d_un.d_val -= htab->srelplt->size;
+ break;
+
+ case DT_PLTREL:
+ BFD_ASSERT (htab->is_vxworks);
+ dyn.d_un.d_val = DT_RELA;
+ break;
+
+ case DT_PLTRELSZ:
+ BFD_ASSERT (htab->is_vxworks);
+ dyn.d_un.d_val = htab->srelplt->size;
+ break;
+
+ case DT_JMPREL:
+ BFD_ASSERT (htab->is_vxworks);
+ dyn.d_un.d_val = (htab->srelplt->output_section->vma
+ + htab->srelplt->output_offset);
+ break;
+
default:
swap_out_p = FALSE;
break;
@@ -7727,14 +8643,33 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd,
}
}
- /* The first entry of the global offset table will be filled at
- runtime. The second entry will be used by some runtime loaders.
- This isn't the case of IRIX rld. */
if (sgot != NULL && sgot->size > 0)
{
- MIPS_ELF_PUT_WORD (output_bfd, 0, sgot->contents);
- MIPS_ELF_PUT_WORD (output_bfd, 0x80000000,
- sgot->contents + MIPS_ELF_GOT_SIZE (output_bfd));
+ if (htab->is_vxworks)
+ {
+ /* The first entry of the global offset table points to the
+ ".dynamic" section. The second is initialized by the
+ loader and contains the shared library identifier.
+ The third is also initialized by the loader and points
+ to the lazy resolution stub. */
+ MIPS_ELF_PUT_WORD (output_bfd,
+ sdyn->output_offset + sdyn->output_section->vma,
+ sgot->contents);
+ MIPS_ELF_PUT_WORD (output_bfd, 0,
+ sgot->contents + MIPS_ELF_GOT_SIZE (output_bfd));
+ MIPS_ELF_PUT_WORD (output_bfd, 0,
+ sgot->contents
+ + 2 * MIPS_ELF_GOT_SIZE (output_bfd));
+ }
+ else
+ {
+ /* The first entry of the global offset table will be filled at
+ runtime. The second entry will be used by some runtime loaders.
+ This isn't the case of IRIX rld. */
+ MIPS_ELF_PUT_WORD (output_bfd, (bfd_vma) 0, sgot->contents);
+ MIPS_ELF_PUT_WORD (output_bfd, (bfd_vma) 0x80000000,
+ sgot->contents + MIPS_ELF_GOT_SIZE (output_bfd));
+ }
}
if (sgot != NULL)
@@ -7808,7 +8743,7 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd,
decided not to make. This is for the n64 irix rld,
which doesn't seem to apply any relocations if there
are trailing null entries. */
- s = mips_elf_rel_dyn_section (dynobj, FALSE);
+ s = mips_elf_rel_dyn_section (info, FALSE);
dyn.d_un.d_val = (s->reloc_count
* (ABI_64_P (output_bfd)
? sizeof (Elf64_Mips_External_Rel)
@@ -7862,24 +8797,37 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd,
}
}
- /* We need to sort the entries of the dynamic relocation section. */
-
- s = mips_elf_rel_dyn_section (dynobj, FALSE);
-
- if (s != NULL
- && s->size > (bfd_vma)2 * MIPS_ELF_REL_SIZE (output_bfd))
+ /* The psABI says that the dynamic relocations must be sorted in
+ increasing order of r_symndx. The VxWorks EABI doesn't require
+ this, and because the code below handles REL rather than RELA
+ relocations, using it for VxWorks would be outright harmful. */
+ if (!htab->is_vxworks)
{
- reldyn_sorting_bfd = output_bfd;
+ s = mips_elf_rel_dyn_section (info, FALSE);
+ if (s != NULL
+ && s->size > (bfd_vma)2 * MIPS_ELF_REL_SIZE (output_bfd))
+ {
+ reldyn_sorting_bfd = output_bfd;
- if (ABI_64_P (output_bfd))
- qsort ((Elf64_External_Rel *) s->contents + 1, s->reloc_count - 1,
- sizeof (Elf64_Mips_External_Rel), sort_dynamic_relocs_64);
- else
- qsort ((Elf32_External_Rel *) s->contents + 1, s->reloc_count - 1,
- sizeof (Elf32_External_Rel), sort_dynamic_relocs);
+ if (ABI_64_P (output_bfd))
+ qsort ((Elf64_External_Rel *) s->contents + 1,
+ s->reloc_count - 1, sizeof (Elf64_Mips_External_Rel),
+ sort_dynamic_relocs_64);
+ else
+ qsort ((Elf32_External_Rel *) s->contents + 1,
+ s->reloc_count - 1, sizeof (Elf32_External_Rel),
+ sort_dynamic_relocs);
+ }
}
}
+ if (htab->is_vxworks && htab->splt->size > 0)
+ {
+ if (info->shared)
+ mips_vxworks_finish_shared_plt (output_bfd, info);
+ else
+ mips_vxworks_finish_exec_plt (output_bfd, info);
+ }
return TRUE;
}
@@ -8929,8 +9877,9 @@ _bfd_mips_elf_link_hash_table_create (bfd *abfd)
if (ret == NULL)
return NULL;
- if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
- mips_elf_link_hash_newfunc))
+ if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
+ mips_elf_link_hash_newfunc,
+ sizeof (struct mips_elf_link_hash_entry)))
{
free (ret);
return NULL;
@@ -8946,9 +9895,36 @@ _bfd_mips_elf_link_hash_table_create (bfd *abfd)
ret->use_rld_obj_head = FALSE;
ret->rld_value = 0;
ret->mips16_stubs_seen = FALSE;
+ ret->is_vxworks = FALSE;
+ ret->srelbss = NULL;
+ ret->sdynbss = NULL;
+ ret->srelplt = NULL;
+ ret->srelplt2 = NULL;
+ ret->sgotplt = NULL;
+ ret->splt = NULL;
+ ret->plt_header_size = 0;
+ ret->plt_entry_size = 0;
return &ret->root.root;
}
+
+/* Likewise, but indicate that the target is VxWorks. */
+
+struct bfd_link_hash_table *
+_bfd_mips_vxworks_link_hash_table_create (bfd *abfd)
+{
+ struct bfd_link_hash_table *ret;
+
+ ret = _bfd_mips_elf_link_hash_table_create (abfd);
+ if (ret)
+ {
+ struct mips_elf_link_hash_table *htab;
+
+ htab = (struct mips_elf_link_hash_table *) ret;
+ htab->is_vxworks = 1;
+ }
+ return ret;
+}
/* We need to use a special link routine to handle the .reginfo and
the .mdebug sections. We need to merge all instances of these
@@ -8971,6 +9947,7 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info)
EXTR esym;
unsigned int i;
bfd_size_type amt;
+ struct mips_elf_link_hash_table *htab;
static const char * const secname[] =
{
@@ -8987,6 +9964,7 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info)
generic size_dynamic_sections renumbered them out from under us.
Rather than trying somehow to prevent the renumbering, just do
the sort again. */
+ htab = mips_elf_hash_table (info);
if (elf_hash_table (info)->dynamic_sections_created)
{
bfd *dynobj;
@@ -9037,6 +10015,14 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info)
elf_gp (abfd) = (h->u.def.value
+ h->u.def.section->output_section->vma
+ h->u.def.section->output_offset);
+ else if (htab->is_vxworks
+ && (h = bfd_link_hash_lookup (info->hash,
+ "_GLOBAL_OFFSET_TABLE_",
+ FALSE, FALSE, TRUE))
+ && h->type == bfd_link_hash_defined)
+ elf_gp (abfd) = (h->u.def.section->output_section->vma
+ + h->u.def.section->output_offset
+ + h->u.def.value);
else if (info->relocatable)
{
bfd_vma lo = MINUS_ONE;
@@ -9048,7 +10034,7 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info)
lo = o->vma;
/* And calculate GP relative to that. */
- elf_gp (abfd) = lo + ELF_MIPS_GP_OFFSET (abfd);
+ elf_gp (abfd) = lo + ELF_MIPS_GP_OFFSET (info);
}
else
{
@@ -9780,6 +10766,12 @@ _bfd_mips_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
new_flags &= ~EF_MIPS_UCODE;
old_flags &= ~EF_MIPS_UCODE;
+ /* Don't care about the PIC flags from dynamic objects; they are
+ PIC by design. */
+ if ((new_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) != 0
+ && (ibfd->flags & DYNAMIC) != 0)
+ new_flags &= ~ (EF_MIPS_PIC | EF_MIPS_CPIC);
+
if (new_flags == old_flags)
return TRUE;
diff --git a/bfd/elfxx-mips.h b/bfd/elfxx-mips.h
index 07e661d..6c3c9a3 100644
--- a/bfd/elfxx-mips.h
+++ b/bfd/elfxx-mips.h
@@ -48,6 +48,8 @@ extern bfd_boolean _bfd_mips_elf_check_relocs
(bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *);
extern bfd_boolean _bfd_mips_elf_adjust_dynamic_symbol
(struct bfd_link_info *, struct elf_link_hash_entry *);
+extern bfd_boolean _bfd_mips_vxworks_adjust_dynamic_symbol
+ (struct bfd_link_info *, struct elf_link_hash_entry *);
extern bfd_boolean _bfd_mips_elf_always_size_sections
(bfd *, struct bfd_link_info *);
extern bfd_boolean _bfd_mips_elf_size_dynamic_sections
@@ -58,6 +60,9 @@ extern bfd_boolean _bfd_mips_elf_relocate_section
extern bfd_boolean _bfd_mips_elf_finish_dynamic_symbol
(bfd *, struct bfd_link_info *, struct elf_link_hash_entry *,
Elf_Internal_Sym *);
+extern bfd_boolean _bfd_mips_vxworks_finish_dynamic_symbol
+ (bfd *, struct bfd_link_info *, struct elf_link_hash_entry *,
+ Elf_Internal_Sym *);
extern bfd_boolean _bfd_mips_elf_finish_dynamic_sections
(bfd *, struct bfd_link_info *);
extern void _bfd_mips_elf_final_write_processing
@@ -90,6 +95,8 @@ extern bfd_byte *_bfd_elf_mips_get_relocated_section_contents
bfd_byte *, bfd_boolean, asymbol **);
extern struct bfd_link_hash_table *_bfd_mips_elf_link_hash_table_create
(bfd *);
+extern struct bfd_link_hash_table *_bfd_mips_vxworks_link_hash_table_create
+ (bfd *);
extern bfd_boolean _bfd_mips_elf_final_link
(bfd *, struct bfd_link_info *);
extern bfd_boolean _bfd_mips_elf_merge_private_bfd_data
diff --git a/bfd/elfxx-sparc.c b/bfd/elfxx-sparc.c
index cdf8c83..cb5f7cb 100644
--- a/bfd/elfxx-sparc.c
+++ b/bfd/elfxx-sparc.c
@@ -810,7 +810,8 @@ _bfd_sparc_elf_link_hash_table_create (bfd *abfd)
ret->dynamic_interpreter_size = sizeof ELF32_DYNAMIC_INTERPRETER;
}
- if (! _bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc))
+ if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc,
+ sizeof (struct _bfd_sparc_elf_link_hash_entry)))
{
free (ret);
return NULL;
diff --git a/bfd/hash.c b/bfd/hash.c
index e53eda1..ce9ba5c 100644
--- a/bfd/hash.c
+++ b/bfd/hash.c
@@ -1,6 +1,6 @@
/* hash.c -- hash table routines for BFD
- Copyright 1993, 1994, 1995, 1997, 1999, 2001, 2002, 2003, 2004, 2005
- Free Software Foundation, Inc.
+ Copyright 1993, 1994, 1995, 1997, 1999, 2001, 2002, 2003, 2004, 2005,
+ 2006 Free Software Foundation, Inc.
Written by Steve Chamberlain <sac@cygnus.com>
This file is part of BFD, the Binary File Descriptor library.
@@ -308,6 +308,7 @@ bfd_hash_table_init_n (struct bfd_hash_table *table,
struct bfd_hash_entry *(*newfunc) (struct bfd_hash_entry *,
struct bfd_hash_table *,
const char *),
+ unsigned int entsize,
unsigned int size)
{
unsigned int alloc;
@@ -328,6 +329,7 @@ bfd_hash_table_init_n (struct bfd_hash_table *table,
}
memset ((void *) table->table, 0, alloc);
table->size = size;
+ table->entsize = entsize;
table->newfunc = newfunc;
return TRUE;
}
@@ -338,9 +340,11 @@ bfd_boolean
bfd_hash_table_init (struct bfd_hash_table *table,
struct bfd_hash_entry *(*newfunc) (struct bfd_hash_entry *,
struct bfd_hash_table *,
- const char *))
+ const char *),
+ unsigned int entsize)
{
- return bfd_hash_table_init_n (table, newfunc, bfd_default_hash_table_size);
+ return bfd_hash_table_init_n (table, newfunc, entsize,
+ bfd_default_hash_table_size);
}
/* Free a hash table. */
@@ -591,7 +595,8 @@ _bfd_stringtab_init (void)
if (table == NULL)
return NULL;
- if (! bfd_hash_table_init (& table->table, strtab_hash_newfunc))
+ if (!bfd_hash_table_init (&table->table, strtab_hash_newfunc,
+ sizeof (struct strtab_hash_entry)))
{
free (table);
return NULL;
diff --git a/bfd/i386linux.c b/bfd/i386linux.c
index 8b55b35..17c6180 100644
--- a/bfd/i386linux.c
+++ b/bfd/i386linux.c
@@ -1,6 +1,6 @@
/* BFD back-end for linux flavored i386 a.out binaries.
Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2001, 2002, 2003,
- 2004 Free Software Foundation, Inc.
+ 2004, 2006 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
@@ -231,8 +231,9 @@ linux_link_hash_table_create (abfd)
ret = (struct linux_link_hash_table *) bfd_alloc (abfd, amt);
if (ret == (struct linux_link_hash_table *) NULL)
return (struct bfd_link_hash_table *) NULL;
- if (! NAME(aout,link_hash_table_init) (&ret->root, abfd,
- linux_link_hash_newfunc))
+ if (!NAME(aout,link_hash_table_init) (&ret->root, abfd,
+ linux_link_hash_newfunc,
+ sizeof (struct linux_link_hash_entry)))
{
free (ret);
return (struct bfd_link_hash_table *) NULL;
diff --git a/bfd/ieee.c b/bfd/ieee.c
index 248551f..be8455c 100644
--- a/bfd/ieee.c
+++ b/bfd/ieee.c
@@ -3466,22 +3466,22 @@ ieee_write_processor (bfd *abfd)
case bfd_mach_m68040: id = "68040"; break;
case bfd_mach_m68060: id = "68060"; break;
case bfd_mach_cpu32: id = "cpu32"; break;
+ case bfd_mach_mcf_isa_a_nodiv: id = "isa-a:nodiv"; break;
case bfd_mach_mcf_isa_a: id = "isa-a"; break;
- case bfd_mach_mcf_isa_a_div: id = "isa-a:div"; break;
- case bfd_mach_mcf_isa_a_div_mac: id = "isa-a:div:mac"; break;
- case bfd_mach_mcf_isa_a_div_emac: id = "isa-a:div:emac"; break;
- case bfd_mach_mcf_isa_aplus: id = "isa-a+"; break;
- case bfd_mach_mcf_isa_aplus_mac: id = "isa-a+:mac"; break;
- case bfd_mach_mcf_isa_aplus_emac: id = "isa-a+:mac"; break;
- case bfd_mach_mcf_isa_aplus_usp: id = "isa-a+:usp"; break;
- case bfd_mach_mcf_isa_aplus_usp_mac: id = "isa-a+:usp:mac"; break;
- case bfd_mach_mcf_isa_aplus_usp_emac: id = "isa-a+:usp:emac"; break;
+ case bfd_mach_mcf_isa_a_mac: id = "isa-a:mac"; break;
+ case bfd_mach_mcf_isa_a_emac: id = "isa-a:emac"; break;
+ case bfd_mach_mcf_isa_aplus: id = "isa-aplus"; break;
+ case bfd_mach_mcf_isa_aplus_mac: id = "isa-aplus:mac"; break;
+ case bfd_mach_mcf_isa_aplus_emac: id = "isa-aplus:mac"; break;
+ case bfd_mach_mcf_isa_b_nousp: id = "isa-b:nousp"; break;
+ case bfd_mach_mcf_isa_b_nousp_mac: id = "isa-b:nousp:mac"; break;
+ case bfd_mach_mcf_isa_b_nousp_emac: id = "isa-b:nousp:emac"; break;
case bfd_mach_mcf_isa_b: id = "isa-b"; break;
case bfd_mach_mcf_isa_b_mac: id = "isa-b:mac"; break;
case bfd_mach_mcf_isa_b_emac: id = "isa-b:emac"; break;
- case bfd_mach_mcf_isa_b_usp_float: id = "isa-b:usp:float"; break;
- case bfd_mach_mcf_isa_b_usp_float_mac: id = "isa-b:usp:float:mac"; break;
- case bfd_mach_mcf_isa_b_usp_float_emac: id = "isa-b:usp:float:emac"; break;
+ case bfd_mach_mcf_isa_b_float: id = "isa-b:float"; break;
+ case bfd_mach_mcf_isa_b_float_mac: id = "isa-b:float:mac"; break;
+ case bfd_mach_mcf_isa_b_float_emac: id = "isa-b:float:emac"; break;
}
if (! ieee_write_id (abfd, id))
diff --git a/bfd/libaout.h b/bfd/libaout.h
index 79f5402..bb3ee80 100644
--- a/bfd/libaout.h
+++ b/bfd/libaout.h
@@ -1,6 +1,6 @@
/* BFD back-end data structures for a.out (and similar) files.
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004, 2005
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
Written by Cygnus Support.
@@ -575,7 +575,8 @@ extern bfd_boolean NAME (aout, link_hash_table_init)
(struct aout_link_hash_table *, bfd *,
struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
struct bfd_hash_table *,
- const char *));
+ const char *),
+ unsigned int);
extern struct bfd_link_hash_table * NAME (aout, link_hash_table_create)
(bfd *);
diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h
index e3468c1..ee2484f 100644
--- a/bfd/libbfd-in.h
+++ b/bfd/libbfd-in.h
@@ -2,7 +2,7 @@
(This include file is not for users of the library.)
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
Written by Cygnus Support.
@@ -53,6 +53,12 @@ struct bfd_in_memory
bfd_byte *buffer;
};
+struct section_hash_entry
+{
+ struct bfd_hash_entry root;
+ asection section;
+};
+
/* tdata for an archive. For an input archive, cache
needs to be free()'d. For an output archive, symdefs do. */
@@ -468,7 +474,8 @@ extern bfd_boolean _bfd_link_hash_table_init
(struct bfd_link_hash_table *, bfd *,
struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
struct bfd_hash_table *,
- const char *));
+ const char *),
+ unsigned int);
/* Generic link hash table creation routine. */
extern struct bfd_link_hash_table *_bfd_generic_link_hash_table_create
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 03e2fa5..2a590a3 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -7,7 +7,7 @@
(This include file is not for users of the library.)
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
Written by Cygnus Support.
@@ -58,6 +58,12 @@ struct bfd_in_memory
bfd_byte *buffer;
};
+struct section_hash_entry
+{
+ struct bfd_hash_entry root;
+ asection section;
+};
+
/* tdata for an archive. For an input archive, cache
needs to be free()'d. For an output archive, symdefs do. */
@@ -473,7 +479,8 @@ extern bfd_boolean _bfd_link_hash_table_init
(struct bfd_link_hash_table *, bfd *,
struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
struct bfd_hash_table *,
- const char *));
+ const char *),
+ unsigned int);
/* Generic link hash table creation routine. */
extern struct bfd_link_hash_table *_bfd_generic_link_hash_table_create
@@ -965,6 +972,9 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_MIPS_TLS_TPREL_HI16",
"BFD_RELOC_MIPS_TLS_TPREL_LO16",
+ "BFD_RELOC_MIPS_COPY",
+ "BFD_RELOC_MIPS_JUMP_SLOT",
+
"BFD_RELOC_FRV_LABEL16",
"BFD_RELOC_FRV_LABEL24",
"BFD_RELOC_FRV_LO16",
@@ -1055,6 +1065,11 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_X86_64_TPOFF32",
"BFD_RELOC_X86_64_GOTOFF64",
"BFD_RELOC_X86_64_GOTPC32",
+ "BFD_RELOC_X86_64_GOT64",
+ "BFD_RELOC_X86_64_GOTPCREL64",
+ "BFD_RELOC_X86_64_GOTPC64",
+ "BFD_RELOC_X86_64_GOTPLT64",
+ "BFD_RELOC_X86_64_PLTOFF64",
"BFD_RELOC_X86_64_GOTPC32_TLSDESC",
"BFD_RELOC_X86_64_TLSDESC_CALL",
"BFD_RELOC_X86_64_TLSDESC",
@@ -1333,6 +1348,20 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_BFIN_12_PCREL_JUMP_S",
"BFD_RELOC_BFIN_24_PCREL_CALL_X",
"BFD_RELOC_BFIN_24_PCREL_JUMP_L",
+ "BFD_RELOC_BFIN_GOT17M4",
+ "BFD_RELOC_BFIN_GOTHI",
+ "BFD_RELOC_BFIN_GOTLO",
+ "BFD_RELOC_BFIN_FUNCDESC",
+ "BFD_RELOC_BFIN_FUNCDESC_GOT17M4",
+ "BFD_RELOC_BFIN_FUNCDESC_GOTHI",
+ "BFD_RELOC_BFIN_FUNCDESC_GOTLO",
+ "BFD_RELOC_BFIN_FUNCDESC_VALUE",
+ "BFD_RELOC_BFIN_FUNCDESC_GOTOFF17M4",
+ "BFD_RELOC_BFIN_FUNCDESC_GOTOFFHI",
+ "BFD_RELOC_BFIN_FUNCDESC_GOTOFFLO",
+ "BFD_RELOC_BFIN_GOTOFF17M4",
+ "BFD_RELOC_BFIN_GOTOFFHI",
+ "BFD_RELOC_BFIN_GOTOFFLO",
"BFD_RELOC_BFIN_GOT",
"BFD_RELOC_BFIN_PLTPC",
"BFD_ARELOC_BFIN_PUSH",
diff --git a/bfd/libcoff-in.h b/bfd/libcoff-in.h
index 490f2a8..f2bc264 100644
--- a/bfd/libcoff-in.h
+++ b/bfd/libcoff-in.h
@@ -1,6 +1,6 @@
/* BFD COFF object file private structure.
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004, 2005
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
Written by Cygnus Support.
@@ -421,7 +421,8 @@ struct coff_debug_merge_hash_table
/* Initialize a COFF debug merge hash table. */
#define coff_debug_merge_hash_table_init(table) \
- (bfd_hash_table_init (&(table)->root, _bfd_coff_debug_merge_hash_newfunc))
+ (bfd_hash_table_init (&(table)->root, _bfd_coff_debug_merge_hash_newfunc, \
+ sizeof (struct coff_debug_merge_hash_entry)))
/* Free a COFF debug merge hash table. */
@@ -537,7 +538,8 @@ extern bfd_boolean _bfd_coff_link_hash_table_init
(struct coff_link_hash_table *, bfd *,
struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
struct bfd_hash_table *,
- const char *));
+ const char *),
+ unsigned int);
extern struct bfd_link_hash_table *_bfd_coff_link_hash_table_create
(bfd *);
extern const char *_bfd_coff_internal_syment_name
diff --git a/bfd/libcoff.h b/bfd/libcoff.h
index 67ff404..f756f30 100644
--- a/bfd/libcoff.h
+++ b/bfd/libcoff.h
@@ -4,7 +4,7 @@
/* BFD COFF object file private structure.
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004, 2005
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
Written by Cygnus Support.
@@ -425,7 +425,8 @@ struct coff_debug_merge_hash_table
/* Initialize a COFF debug merge hash table. */
#define coff_debug_merge_hash_table_init(table) \
- (bfd_hash_table_init (&(table)->root, _bfd_coff_debug_merge_hash_newfunc))
+ (bfd_hash_table_init (&(table)->root, _bfd_coff_debug_merge_hash_newfunc, \
+ sizeof (struct coff_debug_merge_hash_entry)))
/* Free a COFF debug merge hash table. */
@@ -541,7 +542,8 @@ extern bfd_boolean _bfd_coff_link_hash_table_init
(struct coff_link_hash_table *, bfd *,
struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
struct bfd_hash_table *,
- const char *));
+ const char *),
+ unsigned int);
extern struct bfd_link_hash_table *_bfd_coff_link_hash_table_create
(bfd *);
extern const char *_bfd_coff_internal_syment_name
diff --git a/bfd/linker.c b/bfd/linker.c
index 67fe804..14eeae4 100644
--- a/bfd/linker.c
+++ b/bfd/linker.c
@@ -1,6 +1,6 @@
/* linker.c -- BFD linker routines
Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
- 2003, 2004, 2005 Free Software Foundation, Inc.
+ 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
Written by Steve Chamberlain and Ian Lance Taylor, Cygnus Support
This file is part of BFD, the Binary File Descriptor library.
@@ -472,14 +472,15 @@ _bfd_link_hash_table_init
bfd *abfd,
struct bfd_hash_entry *(*newfunc) (struct bfd_hash_entry *,
struct bfd_hash_table *,
- const char *))
+ const char *),
+ unsigned int entsize)
{
table->creator = abfd->xvec;
table->undefs = NULL;
table->undefs_tail = NULL;
table->type = bfd_link_generic_hash_table;
- return bfd_hash_table_init (&table->table, newfunc);
+ return bfd_hash_table_init (&table->table, newfunc, entsize);
}
/* Look up a symbol in a link hash table. If follow is TRUE, we
@@ -709,7 +710,8 @@ _bfd_generic_link_hash_table_create (bfd *abfd)
if (ret == NULL)
return NULL;
if (! _bfd_link_hash_table_init (&ret->root, abfd,
- _bfd_generic_link_hash_newfunc))
+ _bfd_generic_link_hash_newfunc,
+ sizeof (struct generic_link_hash_entry)))
{
free (ret);
return NULL;
@@ -901,9 +903,10 @@ archive_hash_table_init
(struct archive_hash_table *table,
struct bfd_hash_entry *(*newfunc) (struct bfd_hash_entry *,
struct bfd_hash_table *,
- const char *))
+ const char *),
+ unsigned int entsize)
{
- return bfd_hash_table_init (&table->table, newfunc);
+ return bfd_hash_table_init (&table->table, newfunc, entsize);
}
/* Look up an entry in an archive hash table. */
@@ -981,7 +984,8 @@ _bfd_generic_link_add_archive_symbols
/* In order to quickly determine whether an symbol is defined in
this archive, we build a hash table of the symbols. */
- if (! archive_hash_table_init (&arsym_hash, archive_hash_newfunc))
+ if (! archive_hash_table_init (&arsym_hash, archive_hash_newfunc,
+ sizeof (struct archive_hash_entry)))
return FALSE;
for (arsym = arsyms, indx = 0; arsym < arsym_end; arsym++, indx++)
{
@@ -2952,7 +2956,9 @@ bfd_boolean
bfd_section_already_linked_table_init (void)
{
return bfd_hash_table_init_n (&_bfd_section_already_linked_table,
- already_linked_newfunc, 42);
+ already_linked_newfunc,
+ sizeof (struct bfd_section_already_linked_hash_entry),
+ 42);
}
void
diff --git a/bfd/m68klinux.c b/bfd/m68klinux.c
index e55fd54..2c12a7c 100644
--- a/bfd/m68klinux.c
+++ b/bfd/m68klinux.c
@@ -1,6 +1,6 @@
/* BFD back-end for linux flavored m68k a.out binaries.
Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002,
- 2003, 2004 Free Software Foundation, Inc.
+ 2003, 2004, 2006 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
@@ -235,8 +235,9 @@ linux_link_hash_table_create (abfd)
bfd_set_error (bfd_error_no_memory);
return (struct bfd_link_hash_table *) NULL;
}
- if (! NAME(aout,link_hash_table_init) (&ret->root, abfd,
- linux_link_hash_newfunc))
+ if (!NAME(aout,link_hash_table_init) (&ret->root, abfd,
+ linux_link_hash_newfunc,
+ sizeof (struct linux_link_hash_entry)))
{
free (ret);
return (struct bfd_link_hash_table *) NULL;
diff --git a/bfd/merge.c b/bfd/merge.c
index 0c34821..c1795d2 100644
--- a/bfd/merge.c
+++ b/bfd/merge.c
@@ -1,5 +1,6 @@
/* SEC_MERGE support.
- Copyright 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
Written by Jakub Jelinek <jakub@redhat.com>.
This file is part of BFD, the Binary File Descriptor library.
@@ -242,7 +243,7 @@ sec_merge_init (unsigned int entsize, bfd_boolean strings)
return NULL;
if (! bfd_hash_table_init_n (&table->table, sec_merge_hash_newfunc,
- 16699))
+ sizeof (struct sec_merge_hash_entry), 16699))
{
free (table);
return NULL;
diff --git a/bfd/opncls.c b/bfd/opncls.c
index 63f7b74..b02b137 100644
--- a/bfd/opncls.c
+++ b/bfd/opncls.c
@@ -1,6 +1,6 @@
/* opncls.c -- open and close a BFD.
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000,
- 2001, 2002, 2003, 2004, 2005
+ 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
Written by Cygnus Support.
@@ -71,7 +71,7 @@ _bfd_new_bfd (void)
nbfd->iostream = NULL;
nbfd->where = 0;
if (!bfd_hash_table_init_n (& nbfd->section_htab, bfd_section_hash_newfunc,
- 251))
+ sizeof (struct section_hash_entry), 251))
{
free (nbfd);
return NULL;
diff --git a/bfd/pdp11.c b/bfd/pdp11.c
index 83029c4..37f960f 100644
--- a/bfd/pdp11.c
+++ b/bfd/pdp11.c
@@ -1,5 +1,6 @@
/* BFD back-end for PDP-11 a.out binaries.
- Copyright 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
@@ -2446,9 +2447,10 @@ NAME (aout, link_hash_table_init) (struct aout_link_hash_table *table,
bfd *abfd,
struct bfd_hash_entry *(*newfunc) (struct bfd_hash_entry *,
struct bfd_hash_table *,
- const char *))
+ const char *),
+ unsigned int entsize)
{
- return _bfd_link_hash_table_init (&table->root, abfd, newfunc);
+ return _bfd_link_hash_table_init (&table->root, abfd, newfunc, entsize);
}
/* Create an a.out link hash table. */
@@ -2463,7 +2465,8 @@ NAME (aout, link_hash_table_create) (bfd *abfd)
if (ret == NULL)
return NULL;
if (! NAME (aout, link_hash_table_init) (ret, abfd,
- NAME (aout, link_hash_newfunc)))
+ NAME (aout, link_hash_newfunc),
+ sizeof (struct aout_link_hash_entry)))
{
free (ret);
return NULL;
@@ -3657,9 +3660,10 @@ NAME (aout, final_link) (bfd *abfd,
aout_info.symbol_map = NULL;
aout_info.output_syms = NULL;
- if (! bfd_hash_table_init_n (&aout_info.includes.root,
- aout_link_includes_newfunc,
- 251))
+ if (!bfd_hash_table_init_n (&aout_info.includes.root,
+ aout_link_includes_newfunc,
+ sizeof (struct aout_link_includes_entry),
+ 251))
goto error_return;
includes_hash_initialized = TRUE;
diff --git a/bfd/reloc.c b/bfd/reloc.c
index 31314e7..f1d09a5 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -2140,6 +2140,14 @@ ENUMDOC
COMMENT
ENUM
+ BFD_RELOC_MIPS_COPY
+ENUMX
+ BFD_RELOC_MIPS_JUMP_SLOT
+ENUMDOC
+ MIPS ELF relocations (VxWorks extensions).
+COMMENT
+
+ENUM
BFD_RELOC_FRV_LABEL16
ENUMX
BFD_RELOC_FRV_LABEL24
@@ -2344,6 +2352,16 @@ ENUMX
ENUMX
BFD_RELOC_X86_64_GOTPC32
ENUMX
+ BFD_RELOC_X86_64_GOT64
+ENUMX
+ BFD_RELOC_X86_64_GOTPCREL64
+ENUMX
+ BFD_RELOC_X86_64_GOTPC64
+ENUMX
+ BFD_RELOC_X86_64_GOTPLT64
+ENUMX
+ BFD_RELOC_X86_64_PLTOFF64
+ENUMX
BFD_RELOC_X86_64_GOTPC32_TLSDESC
ENUMX
BFD_RELOC_X86_64_TLSDESC_CALL
@@ -3014,6 +3032,36 @@ ENUM
ENUMDOC
ADI Blackfin Long Jump pcrel.
ENUM
+ BFD_RELOC_BFIN_GOT17M4
+ENUMX
+ BFD_RELOC_BFIN_GOTHI
+ENUMX
+ BFD_RELOC_BFIN_GOTLO
+ENUMX
+ BFD_RELOC_BFIN_FUNCDESC
+ENUMX
+ BFD_RELOC_BFIN_FUNCDESC_GOT17M4
+ENUMX
+ BFD_RELOC_BFIN_FUNCDESC_GOTHI
+ENUMX
+ BFD_RELOC_BFIN_FUNCDESC_GOTLO
+ENUMX
+ BFD_RELOC_BFIN_FUNCDESC_VALUE
+ENUMX
+ BFD_RELOC_BFIN_FUNCDESC_GOTOFF17M4
+ENUMX
+ BFD_RELOC_BFIN_FUNCDESC_GOTOFFHI
+ENUMX
+ BFD_RELOC_BFIN_FUNCDESC_GOTOFFLO
+ENUMX
+ BFD_RELOC_BFIN_GOTOFF17M4
+ENUMX
+ BFD_RELOC_BFIN_GOTOFFHI
+ENUMX
+ BFD_RELOC_BFIN_GOTOFFLO
+ENUMDOC
+ ADI Blackfin FD-PIC relocations.
+ENUM
BFD_RELOC_BFIN_GOT
ENUMDOC
ADI Blackfin GOT relocation.
diff --git a/bfd/section.c b/bfd/section.c
index 42554b9..f870e6b 100644
--- a/bfd/section.c
+++ b/bfd/section.c
@@ -1,6 +1,6 @@
/* Object file "section" support for the BFD library.
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004, 2005
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
Written by Cygnus Support.
@@ -713,12 +713,6 @@ STD_SECTION (bfd_abs_section, 0, bfd_abs_symbol, BFD_ABS_SECTION_NAME, 2);
STD_SECTION (bfd_ind_section, 0, bfd_ind_symbol, BFD_IND_SECTION_NAME, 3);
#undef STD_SECTION
-struct section_hash_entry
-{
- struct bfd_hash_entry root;
- asection section;
-};
-
/* Initialize an entry in the section hash table. */
struct bfd_hash_entry *
diff --git a/bfd/sparclinux.c b/bfd/sparclinux.c
index 27e5f2f..d8659ee 100644
--- a/bfd/sparclinux.c
+++ b/bfd/sparclinux.c
@@ -1,6 +1,6 @@
/* BFD back-end for linux flavored sparc a.out binaries.
Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002,
- 2003, 2004 Free Software Foundation, Inc.
+ 2003, 2004, 2006 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
@@ -232,8 +232,9 @@ linux_link_hash_table_create (abfd)
ret = (struct linux_link_hash_table *) bfd_malloc (amt);
if (ret == (struct linux_link_hash_table *) NULL)
return (struct bfd_link_hash_table *) NULL;
- if (! NAME(aout,link_hash_table_init) (&ret->root, abfd,
- linux_link_hash_newfunc))
+ if (!NAME(aout,link_hash_table_init) (&ret->root, abfd,
+ linux_link_hash_newfunc,
+ sizeof (struct linux_link_hash_entry)))
{
free (ret);
return (struct bfd_link_hash_table *) NULL;
diff --git a/bfd/stabs.c b/bfd/stabs.c
index 25fae29..ba3f934 100644
--- a/bfd/stabs.c
+++ b/bfd/stabs.c
@@ -1,6 +1,6 @@
/* Stabs in sections linking support.
- Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
- Free Software Foundation, Inc.
+ Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+ 2006 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support.
This file is part of BFD, the Binary File Descriptor library.
@@ -195,7 +195,8 @@ _bfd_link_section_stabs (bfd *abfd,
/* Make sure the first byte is zero. */
(void) _bfd_stringtab_add (sinfo->strings, "", TRUE, TRUE);
if (! bfd_hash_table_init (&sinfo->includes,
- stab_link_includes_newfunc))
+ stab_link_includes_newfunc,
+ sizeof (struct stab_link_includes_entry)))
goto error_return;
sinfo->stabstr = bfd_make_section_anyway (abfd, ".stabstr");
if (sinfo->stabstr == NULL)
diff --git a/bfd/sunos.c b/bfd/sunos.c
index 03d386a..024320f 100644
--- a/bfd/sunos.c
+++ b/bfd/sunos.c
@@ -1,6 +1,6 @@
/* BFD backend for SunOS binaries.
Copyright 1990, 1991, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
Written by Cygnus Support.
This file is part of BFD, the Binary File Descriptor library.
@@ -679,8 +679,9 @@ sunos_link_hash_table_create (bfd *abfd)
ret = bfd_malloc (amt);
if (ret == NULL)
return NULL;
- if (! NAME (aout, link_hash_table_init) (&ret->root, abfd,
- sunos_link_hash_newfunc))
+ if (!NAME (aout, link_hash_table_init) (&ret->root, abfd,
+ sunos_link_hash_newfunc,
+ sizeof (struct sunos_link_hash_entry)))
{
free (ret);
return NULL;
diff --git a/bfd/targets.c b/bfd/targets.c
index 99f3006..0649179 100644
--- a/bfd/targets.c
+++ b/bfd/targets.c
@@ -554,12 +554,14 @@ extern const bfd_target bfd_efi_app_ia32_vec;
extern const bfd_target bfd_efi_app_ia64_vec;
extern const bfd_target bfd_elf32_avr_vec;
extern const bfd_target bfd_elf32_bfin_vec;
+extern const bfd_target bfd_elf32_bfinfdpic_vec;
extern const bfd_target bfd_elf32_big_generic_vec;
extern const bfd_target bfd_elf32_bigarc_vec;
extern const bfd_target bfd_elf32_bigarm_vec;
extern const bfd_target bfd_elf32_bigarm_symbian_vec;
extern const bfd_target bfd_elf32_bigarm_vxworks_vec;
extern const bfd_target bfd_elf32_bigmips_vec;
+extern const bfd_target bfd_elf32_bigmips_vxworks_vec;
extern const bfd_target bfd_elf32_cr16c_vec;
extern const bfd_target bfd_elf32_cris_vec;
extern const bfd_target bfd_elf32_crx_vec;
@@ -590,6 +592,7 @@ extern const bfd_target bfd_elf32_littlearm_vec;
extern const bfd_target bfd_elf32_littlearm_symbian_vec;
extern const bfd_target bfd_elf32_littlearm_vxworks_vec;
extern const bfd_target bfd_elf32_littlemips_vec;
+extern const bfd_target bfd_elf32_littlemips_vxworks_vec;
extern const bfd_target bfd_elf32_m32c_vec;
extern const bfd_target bfd_elf32_m32r_vec;
extern const bfd_target bfd_elf32_m32rle_vec;
@@ -852,6 +855,7 @@ static const bfd_target * const _bfd_target_vector[] = {
#endif
&bfd_elf32_avr_vec,
&bfd_elf32_bfin_vec,
+ &bfd_elf32_bfinfdpic_vec,
/* This, and other vectors, may not be used in any *.mt configuration.
But that does not mean they are unnecessary. If configured with
@@ -863,6 +867,7 @@ static const bfd_target * const _bfd_target_vector[] = {
&bfd_elf32_bigarm_symbian_vec,
&bfd_elf32_bigarm_vxworks_vec,
&bfd_elf32_bigmips_vec,
+ &bfd_elf32_bigmips_vxworks_vec,
&bfd_elf32_cr16c_vec,
&bfd_elf32_cris_vec,
&bfd_elf32_crx_vec,
@@ -897,6 +902,7 @@ static const bfd_target * const _bfd_target_vector[] = {
&bfd_elf32_littlearm_symbian_vec,
&bfd_elf32_littlearm_vxworks_vec,
&bfd_elf32_littlemips_vec,
+ &bfd_elf32_littlemips_vxworks_vec,
&bfd_elf32_m32c_vec,
&bfd_elf32_m32r_vec,
&bfd_elf32_m32rle_vec,
diff --git a/bfd/version.h b/bfd/version.h
index bdc58dc..6166019 100644
--- a/bfd/version.h
+++ b/bfd/version.h
@@ -1,3 +1,3 @@
-#define BFD_VERSION_DATE 20060303
+#define BFD_VERSION_DATE 20060330
#define BFD_VERSION @bfd_version@
#define BFD_VERSION_STRING @bfd_version_string@
diff --git a/bfd/vms.c b/bfd/vms.c
index cdac381..e6ee98a 100644
--- a/bfd/vms.c
+++ b/bfd/vms.c
@@ -1,7 +1,7 @@
/* vms.c -- BFD back-end for VAX (openVMS/VAX) and
EVAX (openVMS/Alpha) files.
- Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
- Free Software Foundation, Inc.
+ Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+ 2006 Free Software Foundation, Inc.
Written by Klaus K"ampf (kkaempf@rmi.de)
@@ -77,7 +77,8 @@ vms_initialize (bfd * abfd)
if (PRIV (vms_symbol_table) == NULL)
goto error_ret1;
- if (!bfd_hash_table_init (PRIV (vms_symbol_table), _bfd_vms_hash_newfunc))
+ if (!bfd_hash_table_init (PRIV (vms_symbol_table), _bfd_vms_hash_newfunc,
+ sizeof (vms_symbol_entry)))
goto error_ret1;
amt = sizeof (struct location_struct) * LOCATION_SAVE_SIZE;
diff --git a/bfd/xcofflink.c b/bfd/xcofflink.c
index b1cac27..47c330b 100644
--- a/bfd/xcofflink.c
+++ b/bfd/xcofflink.c
@@ -1,6 +1,6 @@
/* POWER/PowerPC XCOFF linker support.
- Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
- Free Software Foundation, Inc.
+ Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+ 2005, 2006 Free Software Foundation, Inc.
Written by Ian Lance Taylor <ian@cygnus.com>, Cygnus Support.
This file is part of BFD, the Binary File Descriptor library.
@@ -444,7 +444,8 @@ _bfd_xcoff_bfd_link_hash_table_create (bfd *abfd)
ret = bfd_malloc (amt);
if (ret == NULL)
return NULL;
- if (! _bfd_link_hash_table_init (&ret->root, abfd, xcoff_link_hash_newfunc))
+ if (!_bfd_link_hash_table_init (&ret->root, abfd, xcoff_link_hash_newfunc,
+ sizeof (struct xcoff_link_hash_entry)))
{
free (ret);
return NULL;