Index: head/contrib/binutils/bfd/ChangeLog =================================================================== --- head/contrib/binutils/bfd/ChangeLog (revision 275717) +++ head/contrib/binutils/bfd/ChangeLog (revision 275718) @@ -1,1792 +1,1838 @@ +2009-02-15 Alan Modra + + * elf64-ppc.c (struct _ppc64_elf_section_data): Delete t_symndx, + add toc.symndx and toc.add. + (ppc64_elf_check_relocs): Don't set htab->tls_get_addr here. + Set up toc.add. + (get_tls_mask): Add toc_addend param, set from toc.add. Adjust all + callers. + (ppc64_elf_tls_setup): Set htab->tls_get_addr and tls_get_addr_fd. + (branch_reloc_hash_match): New function, extracted from.. + (ppc64_elf_tls_optimize): ..here. + (ppc64_elf_relocate_section): Properly set addends when optimizing + tls sequences. Avoid unnecessary reading and writing of insns. + Only redo reloc when symbol changed. Bypass symbol checks when + using tlsld_got. + * elf32-ppc.c (ppc_elf_tls_setup): Correct comment. + (branch_reloc_hash_match): New function, extracted from.. + (ppc_elf_tls_optimize): ..here. + (ppc_elf_relocate_section): Avoid unnecessary reading of insns. + Don't clear addend on zapped __tls_get_addr reloc. + +2008-08-11 Alan Modra + + * elf64-ppc.c (toc_adjusting_stub_needed): Any call via the plt + needs r2 valid, not just those to external syms. + +2007-11-06 Alan Modra + + * elf32-ppc.c (ppc_elf_check_relocs): Don't refcount tlsld_got here.. + (ppc_elf_gc_sweep_hook): ..or here.. + (ppc_elf_tls_optimize): ..or here. Make two passes through the + relocs, ensuring that tls_get_addr calls follow gd and ld relocs. + (allocate_dynrelocs): Refcount tlsld_got here. + (ppc_elf_size_dynamic_sections): Call allocate_dynrelocs before + allocating tlsld_got. + (ppc_elf_relocate_section): Remove check that a tls_get_addr + call follows gd and ld relocs. + +2007-08-13 Alan Modra + + * elf64-ppc.c (ADDI_R12_R12, LD_R11_0R2, LD_R2_0R2): Define. + Update stub comments. + (build_plt_stub): Build two variants, one without "addis". + (ppc_build_one_stub): Build stubs without "addis" if possible. + (ppc_size_one_stub): Size new stubs. + 2007-07-02 Joseph Myers * elfxx-mips.c (mips_elf_calculate_relocation): Handle R_MIPS_TLS_DTPREL32 and R_MIPS_TLS_DTPREL64. * elf64-mips.c (mips_elf64_howto_table_rela): Support R_MIPS_TLS_DTPREL64. 2007-07-02 Alan Modra * Makefile.am: Run "make dep-am". * Makefile.in: Regenerate. * aclocal.m4: Regenerate. * config.in: Regenerate. * po/SRC-POTFILES.in: Regenerate. * po/bfd.pot: Regenerate. 2007-07-02 Alan Modra * elf-eh-frame.c (_bfd_elf_discard_section_eh_frame): Tidy symsec != NULL tests. 2007-07-02 Alan Modra PR 4712 * elf.c (assign_file_positions_for_load_sections): Adjust lma by p_vaddr_offset. 2007-06-30 H.J. Lu * aclocal.m4: Regenerated. * Makefile.in: Likewise. 2007-06-29 Joseph Myers * elf32-ppc.c (ppc_elf_merge_obj_attributes): New. (ppc_elf_merge_private_bfd_data): Call it. 2007-06-29 Joseph Myers * elfxx-mips.c (mips_elf_merge_obj_attributes): New. (_bfd_mips_elf_merge_private_bfd_data): Call it. 2007-06-29 Joseph Myers * elf-attrs.c: New. * Makefile.am (BFD32_BACKENDS): Add elf-attrs.lo. (BFD32_BACKENDS_CFILES): Add elf-attrs.c. (elf-attrs.lo): Generate dependencies. * Makefile.in: Regenerate. * configure.in (elf): Add elf-attrs.lo. * configure: Regenerate. * elf-bfd.h (struct elf_backend_data): Add entries for object attributes. (NUM_KNOWN_OBJ_ATTRIBUTES, obj_attribute, obj_attribute_list, OBJ_ATTR_PROC, OBJ_ATTR_GNU, OBJ_ATTR_FIRST, OBJ_ATTR_LAST, Tag_NULL, Tag_File, Tag_Section, Tag_Symbol, Tag_compatibility): New. (struct elf_obj_tdata): Add entries for object attributes. (elf_known_obj_attributes, elf_other_obj_attributes, elf_known_obj_attributes_proc, elf_other_obj_attributes_proc): New. (bfd_elf_obj_attr_size, bfd_elf_set_obj_attr_contents, bfd_elf_get_obj_attr_int, bfd_elf_add_obj_attr_int, bfd_elf_add_proc_attr_int, bfd_elf_add_obj_attr_string, bfd_elf_add_proc_attr_string, bfd_elf_add_obj_attr_compat, bfd_elf_add_proc_attr_compat, _bfd_elf_attr_strdup, _bfd_elf_copy_obj_attributes, _bfd_elf_obj_attrs_arg_type, _bfd_elf_parse_attributes, _bfd_elf_merge_object_attributes): New. * elf.c (_bfd_elf_copy_private_bfd_data): Copy object attributes. (bfd_section_from_shdr): Handle attributes sections. * elflink.c (bfd_elf_final_link): Handle attributes sections. * elfxx-target.h (elf_backend_obj_attrs_vendor, elf_backend_obj_attrs_section, elf_backend_obj_attrs_arg_type, elf_backend_obj_attrs_section_type): New. (elfNN_bed): Update. * elf32-arm.c (NUM_KNOWN_ATTRIBUTES, aeabi_attribute, aeabi_attribute_list): Remove. (struct elf32_arm_obj_tdata): Remove object attributes fields. (check_use_blx, bfd_elf32_arm_set_vfp11_fix, using_thumb2, elf32_arm_copy_private_bfd_data, elf32_arm_merge_eabi_attributes): Update for new object attributes interfaces. (uleb128_size, is_default_attr, eabi_attr_size, elf32_arm_eabi_attr_size, write_uleb128, write_eabi_attribute, elf32_arm_set_eabi_attr_contents, elf32_arm_bfd_final_link, elf32_arm_new_eabi_attr, elf32_arm_get_eabi_attr_int, elf32_arm_add_eabi_attr_int, attr_strdup, elf32_arm_add_eabi_attr_string, elf32_arm_add_eabi_attr_compat, copy_eabi_attributes, elf32_arm_parse_attributes): Remove. Moved to generic code in elf-attrs.c. (elf32_arm_obj_attrs_arg_type): New. (elf32_arm_fake_sections): Do not handle .ARM.attributes. (elf32_arm_section_from_shdr): Do not handle SHT_ARM_ATTRIBUTES. (bfd_elf32_bfd_final_link): Remove. (elf_backend_obj_attrs_vendor, elf_backend_obj_attrs_section, elf_backend_obj_attrs_arg_type, elf_backend_obj_attrs_section_type): New. * elf32-bfin.c (bfin_elf_copy_private_bfd_data): Copy object attributes. * elf32-frv.c (frv_elf_copy_private_bfd_data): Likewise. * elf32-iq2000.c (iq2000_elf_copy_private_bfd_data): Likewise. * elf32-mep.c (mep_elf_copy_private_bfd_data): Likewise. * elf32-mt.c (mt_elf_copy_private_bfd_data): Likewise. * elf32-sh.c (sh_elf_copy_private_data): Likewise. * elf64-sh64.c (sh_elf64_copy_private_data_internal): Likewise. 2007-06-29 Paul Brook * elf32-arm.c (bfd_elf32_arm_process_before_allocation): Suppress call veneers for call relocations against undefined symbols. (elf32_arm_final_link_relocate): Turn call to undefined symbol into a jump to the next instruction. 2007-06-29 Michael Snyder * bfd.c (bfd_demangle): Plug memory leak (Coverity). 2007-06-29 M R Swami Reddy * Makefile.am: Add cr16 related entry * Makefile.in: Regenerate * archures.c: Add bfd_cr16_arch * bfd-in2.h: Regenerate * config.bfd: Add cr16-elf * configure.in: Add bfd_elf32_cr16_vec * configure: Regenerate. * targets.c: Added cr16 related information * cpu-cr16.c: New file. * elf32-cr16.c: New file. * reloc.c: Added cr16 relocs. 2007-06-29 Alan Modra * elflink.c (_bfd_elf_link_assign_sym_version): Improve error message for undefined version nodes. (elf_gc_sweep): Don't warn when zero size sections are removed. 2007-06-29 Nathan Froyd * elf32-ppc.c (ppc_elf_info_to_howto): Check for invalid relocation types. 2007-06-29 Alan Modra * elf32-spu.c (spu_elf_fake_sections): New function. (elf_backend_fake_sections): Define. 2007-06-29 Alan Modra * elf.c (assign_file_positions_for_load_sections): Use elf section header sh_size rather than bfd section size, simplifying .tbss handling. 2007-06-29 Alan Modra PR ld/4701 * elf.c (assign_file_positions_for_load_sections): Ensure bss segments meet gABI alignment requirements. Don't allocate file space for bss sections in a segment also containing file or program headers. 2007-06-27 Alan Modra * bfd.c (struct bfd): Rename "next" to "archive_next". * archive.c: Rename uses throughout file. * archive64.c: Likewise. * coff-rs6000.c: Likewise. * ecoff.c: Likewise. * som.c: Likewise. * bfd-in2.h: Regenerate. * elf32-ppc.c (ppc_elf_select_plt_layout): Properly iterate over input bfds. * elf32-spu.c (spu_elf_create_sections): Likewise. 2007-06-26 H.J. Lu * dwarf2.c (find_line): New. Contains the duplicated code from: (_bfd_dwarf2_find_nearest_line): Use it. (_bfd_dwarf2_find_line): Use it. 2007-06-26 Joseph Myers * elf32-arm.c (copy_eabi_attributes): Copy type of attributes. 2007-06-25 Richard Sandiford * elfxx-mips.c (mips_elf_calculate_relocation): Allow local stubs to be used for calls from MIPS16 code. 2007-06-23 Andreas Schwab * configure.in (--with-separate-debug-dir): New option. * configure: Regenerate. * Makefile.am (dwarf2.lo): Add rule to pass DEBUGDIR. * Makefile.in: Regenerate. * dwarf2.c (_bfd_dwarf2_find_nearest_line): Pass DEBUGDIR to bfd_follow_gnu_debuglink. (_bfd_dwarf2_find_line): Likewise. 2007-06-22 Nick Clifton * dwarf2.c: Add support for reading in debug information via a .gnu_debuglink section: (struct dwarf2_debug): Add bfd field to record the bfd containing the debug info. (parse_comp_unit): Remove ABFD parameter. Instead use the bfd field in the dwarf2_debug structure. (_bfd_dwarf2_find_nearest_line): If a debug info section could not be found in the current bfd call bfd_follow_gnu_debuglink to see if another file contains the debug information. If it does, open it and continue. (_bfd_dwarf2_find_line): Likewise. 2007-06-19 H.J. Lu PR ld/4590 * elfxx-ia64.c (sort_dyn_sym_info): Keep the valid got_offset when removing duplicated entries. (get_dyn_sym_info): Initialize the got_offset field to -1. Update call to sort_dyn_sym_info. (elfNN_ia64_relocate_section): Call sort_dyn_sym_info to sort array of addend and remove duplicates. 2007-06-18 H.J. Lu * libpei.h (_bfd_XXi_final_link_postscript): Remove duplication. (bfd_target_pei_p): New. (bfd_target_pei_arch): New (bfd_target_efi_p): Likewise. (bfd_target_efi_arch): New (bfd_pe_executable_p): Use bfd_target_pei_p and bfd_target_efi_p. * peicode.h (arch_type): New enum. (pe_arch): New function. (pe_bfd_object_p): Don't match PE/EFI target with EFI/PE file if there is an EFI/PE target. 2007-06-14 H.J. Lu * Makefile.am (ACLOCAL_AMFLAGS): Add -I . -I ../config. * acinclude.m4: Don't include m4 files. Remove libtool kludge. * Makefile.in: Regenerated. * aclocal.m4: Likewise. * configure: Likewise. 2007-06-11 Sterling Augustine Bob Wilson * elf32-xtensa.c (extend_ebb_bounds_forward): Use renamed XTENSA_PROP_NO_TRANSFORM flag instead of XTENSA_PROP_INSN_NO_TRANSFORM. (extend_ebb_bounds_backward, compute_text_actions): Likewise. (compute_ebb_proposed_actions, coalesce_shared_literal): Likewise. (xtensa_get_property_predef_flags): Likewise. (compute_removed_literals): Pass new arguments to is_removable_literal. (is_removable_literal): Add sec, prop_table and ptblsize arguments. Do not remove literal if the NO_TRANSFORM property flag is set. 2007-05-31 Richard Sandiford * elfxx-mips.c (mips_elf_initialize_tls_index): When processing a type (3) single-GOT entry, read tls_type from the hash table entry rather than the GOT entry. 2007-06-01 Alan Modra * simple.c (bfd_simple_get_relocated_section_contents): Init input_bfds_tail. 2007-05-30 Alan Modra * elf.c (elf_fake_sections): Adjust test for SHT_NOBITS sections created by objcopy --only-keep-debug. (_bfd_elf_init_private_section_data): Only change elf_section_type if it is SHT_NULL. * elf.c (assign_file_positions_for_load_sections): Correct sh_type to SHT_NOBITS earlier. Base actions in rest of function on sh_type and sh_flags instead of bfd section flags. Delete voff and code keeping nobits segments aligned. 2007-05-25 Eric Christopher * elf-eh-frame.c (_bfd_elf_discard_section_eh_frame): Check that sym_sec isn't NULL before accessing. 2007-05-24 Steve Ellcey * Makefile.in: Regnerate. * configure: Regenerate. * aclocal.m4: Regenerate. * doc/Makefile.in: Regenerate. 2007-05-22 Paul Brook * elf32-arm.c (output_arch_syminfo): Replace plt_shndx and plt_offset with sec and sec_shndx. (elf32_arm_ouput_plt_map_sym): Use them. (elf32_arm_output_arch_local_syms): Output mapping symbols for interworking glue. 2007-05-18 Paul Brook * elf32-arm.c (ARM2THUMB_V5_STATIC_GLUE_SIZE): Define. (a2t1v5_ldr_insn, a2t1v5_ldr_insn): New. (record_arm_to_thumb_glue): Add v5t non-pic glue. (elf32_arm_create_thumb_stub): Ditto. 2007-05-16 H.J. Lu Alan Modra * elflink.c (_bfd_elf_adjust_dynamic_copy): Align dynamic bss section to the minimum alignment. 2007-05-15 H.J. Lu Alan Modra PR ld/4504 * elf-bfd.h (_bfd_elf_adjust_dynamic_copy): New. * elflink.c (_bfd_elf_adjust_dynamic_copy): New. * elf-m10300.c (_bfd_mn10300_elf_adjust_dynamic_symbol): Call _bfd_elf_adjust_dynamic_copy to adjust for the copy in dynamic bss section. * elf32-arm.c (elf32_arm_adjust_dynamic_symbol): Likewise. * elf32-cris.c (elf_cris_adjust_dynamic_symbol): Likewise. * elf32-hppa.c (elf32_hppa_adjust_dynamic_symbol): Likewise. * elf32-i370.c (i370_elf_adjust_dynamic_symbol): Likewise. * elf32-i386.c (elf_i386_adjust_dynamic_symbol): Likewise. * elf32-m32r.c (m32r_elf_adjust_dynamic_symbol): Likewise. * elf32-m68k.c (elf_m68k_adjust_dynamic_symbol): Likewise. * elf32-ppc.c (ppc_elf_adjust_dynamic_symbol): Likewise. * elf32-s390.c (elf_s390_adjust_dynamic_symbol): Likewise. * elf32-sh.c (sh_elf_adjust_dynamic_symbol): Likewise. * elf32-vax.c (elf_vax_adjust_dynamic_symbol): Likewise. * elf64-ppc.c (ppc64_elf_adjust_dynamic_symbol): Likewise. * elf64-s390.c (elf_s390_adjust_dynamic_symbol): Likewise. * elf64-sh64.c (sh64_elf64_adjust_dynamic_symbol): Likewise. * elf64-x86-64.c (elf64_x86_64_adjust_dynamic_symbol): Likewise. * elfxx-mips.c (_bfd_mips_vxworks_adjust_dynamic_symbol): Likewise. * elfxx-sparc.c (_bfd_sparc_elf_adjust_dynamic_symbol): Likewise. 2007-05-15 Richard Sandiford * elfxx-mips.c (mips_elf_create_local_got_entry): Remove input_section argument. Create .rela.dyn relocations against symbol 0 rather than the section symbol. (mips_elf_local_got_index): Remove input_section argument. Update call to mips_elf_create_local_got_entry. (mips_elf_got_page, mips_elf_got16_entry): Likewise. (mips_elf_calculate_relocation): Update calls to mips_elf_local_got_index, mips_elf_got16_entry and mips_elf_got_page. 2007-05-15 Mark Shinwell * elf32-arm.c (elf32_arm_final_link_relocate): Correctly handle the Thumb-2 JUMP19 relocation. 2007-05-15 Alan Modra PR 4479 * elf.c (elf_fake_sections): Don't allow backend to change SHT_NOBITS if called for strip/objcopy --only-keep-debug. * elfxx-mips.c (_bfd_mips_elf_fake_sections): Remove similar fix from here. 2007-05-14 Alan Modra * elf.c (bfd_elf_string_from_elf_section): Return NULL on invalid shstrndx. (bfd_elf_get_str_section): Likewise. 2007-05-12 Alan Modra PR 4497 * elf-eh-frame.c (struct cie): Add "local_personality". Make "personality" a union. (cie_eq): Compare local_personality too. Adjust personality comparison. (_bfd_elf_discard_section_eh_frame): Check binding on personality reloc sym to allow for bad symtab. Use stashed local syms rather than reading personality local sym. Handle discarded sections. 2007-05-12 Alan Modra * elf32-spu.c (elf_howto_table): Add howto for R_SPU_ADDR16X. 2007-05-11 Alan Modra * elf32-ppc.h (ppc_elf_select_plt_layout): Update prototype. (enum ppc_elf_plt_type): Move from.. * elf32-ppc.c: ..here. (struct ppc_elf_obj_tdata): Add makes_plt_call and has_rel16. (struct ppc_elf_link_hash_table): Reorder. Add old_bfd. Delete can_use_new_plt. Make is_vxworks a bitfield. (ppc_elf_link_hash_table_create): Don't clear is_vxworks (again). (ppc_elf_check_relocs): Update setting of reloc flags. Set old_bfd. (ppc_elf_select_plt_layout): Modify parameters. Use bfd reloc flags to better detect object files needing old bss-style plt. Allow secure plt to be used without rel16 relocs being detected. Warn if secure plt request cannot be allowed. 2007-05-11 Alan Modra * reloc.c (BFD_RELOC_SPU_PPU32, BFD_RELOC_SPU_PPU64): Define. * elf-bfd.h (struct elf_backend_data): Change return type of elf_backend_relocate_section to int. * elf32-spu.c (elf_howto_table): Add howtos for R_SPU_PPU32 and R_SPU_PPU64. (spu_elf_bfd_to_reloc_type): Convert new relocs. (spu_elf_count_relocs): New function. (elf_backend_count_relocs): Define. (spu_elf_relocate_section): Arrange to emit R_SPU_PPU32 and R_SPU_PPU64 relocs. * elflink.c (elf_link_input_bfd): Emit relocs if relocate_section returns 2. * bfd-in2.h: Regenerate. * libbfd.h: Regenerate. 2007-05-10 Richard Sandiford * elf32-arm.c (elf32_arm_check_relocs): Don't create PLT entries for R_ARM_ABS12 relocs. (elf32_arm_finish_dynamic_symbol): Fix the loop that creates non-shared VxWorks PLT entries. 2007-05-11 Alan Modra PR 4454 * elf-eh-frame.c (struct cie): Make "personality" a bfd_vma. (_bfd_elf_discard_section_eh_frame): Handle local syms on personality relocation. 2007-05-10 Richard Sandiford * elf.c (assign_file_positions_for_load_sections): Use p_memsz rather than p_filesz to calculate the LMA of the end of a segment. 2007-05-10 Jakub Jelinek * elf64-ppc.c (ppc64_elf_adjust_dynamic_symbol): Don't do copyreloc processing if symbol is defined in the executable. 2007-05-10 Alexandre Oliva * elf32-frv.c (_frvfdpic_check_discarded_relocs): New. (frvfdpic_elf_discard_info): New. (elf_backend_discard_info): Define for FDPIC. 2007-05-09 Mark Shinwell * elf32-arm.c (bfd_elf32_arm_vfp11_erratum_scan): Don't attempt to scan if the bfd doesn't correspond to an ELF image. (bfd_elf32_arm_vfp11_fix_veneer_locations): Likewise. 2007-05-08 Alexandre Oliva * elf32-frv.c (elf32_frv_relocate_section): Discard dynamic relocs for which _bfd_elf_section_offset returns -1. 2007-05-08 Alan Modra * elf32-spu.c (spu_elf_size_stubs): Use "void *" for psyms. (mark_functions_via_relocs): Likewise. 2007-05-07 Alan Modra * elflink.c (bfd_elf_final_link): Correct reloc handling for elf_backend_count_relocs. (bfd_elf_discard_info): Print an error if we can't read syms. 2007-05-07 Alan Modra * elf32-spu.c (spu_elf_reloc_type_lookup): Return NULL on invalid reloc code. (spu_elf_gc_mark_hook, spu_elf_section_processing): Delete functions. (elf_backend_gc_mark_hook, elf_backend_section_processing): Don't define. 2007-05-07 Alan Modra * elf.c (assign_file_positions_for_load_sections): Don't check core segment. 2007-05-04 H.J. Lu * elflink.c (elf_link_sort_relocs): Return if both .rela.dyn and .rel.dyn aren't present. 2007-05-04 Nick Clifton * elflink.c (elf_link_sort_relocs): If both .rela.dyn and .rel.dyn sections are present examine the indirect sections in an attempt to compute the correct relocation size. If there is any ambiguity, produce an error and refuse to sort. 2007-05-03 Sandra Loosemore * elf32-arm.c (allocate_dynrelocs): Fix typo in comment. 2007-05-03 Vincent Riviere Nick Clifton PR gas/3041 * aoutx.h (swap_std_reloc_out): Treat relocs against weak symbols in the same way as relocs against external symbols. 2007-05-02 Alan Modra * elf.c (assign_file_positions_for_load_sections): Set sh_offset here. Set sh_type to SHT_NOBITS if we won't be allocating file space. Don't bump p_memsz for non-alloc sections. Adjust section-in-segment check. (assign_file_positions_for_non_load_sections): Don't set sh_offset here for sections that have already been handled above. 2007-04-30 Alan Modra * elf32-spu.c (struct spu_link_hash_table): Add stack_analysis and emit_stack_syms bitfields. (get_sym_h): Read all symbols if stack analysis will be done. (spu_elf_create_sections): Add stack_analysis and emit_stack_syms params, and stash in hash table. (is_hint): Split off from.. (is_branch): ..here. Adjust callers. (spu_elf_size_stubs): Add stack_analysis param. Arrange to read and keep all syms. (write_one_stub): Fix mem leak. (find_function_stack_adjust): New function. (sort_syms_syms, sort_syms_psecs): New vars. (sort_syms): New function. (struct call_info, struct function_info): New. (struct spu_elf_stack_info): New. (alloc_stack_info, maybe_insert_function, func_name): New functions. (is_nop, insns_at_end, check_function_ranges): Likewise. (find_function, insert_callee, mark_functions_via_relocs): Likewise. (pasted_function, interesting_section, discover_functions): Likewise. (mark_non_root, call_graph_traverse, build_call_tree): Likewise. (sum_stack, spu_elf_stack_analysis, spu_elf_final_link): Likewise. (bfd_elf32_bfd_final_link): Define. * elf32-spu.h (struct _spu_elf_section_data): Add stack_info field. (spu_elf_create_sections, spu_elf_size_stubs): Update prototypes. 2007-04-28 Sergey Rogozhkin * elfxx-mips.c (mips_elf_create_dynamic_relocation): Don't access memory which we might not own. 2007-04-27 Bob Wilson * elf32-xtensa.c (elf_xtensa_make_sym_local): Restore deleted function. (elf_xtensa_hide_symbol, elf_backend_hide_symbol): Likewise. (elf_xtensa_allocate_dynrelocs): Use elf_xtensa_make_sym_local. 2007-04-27 Bob Wilson * elf32-xtensa.c (xtensa_read_table_entries): Step through table contents and relocs in parallel. 2007-04-27 Bob Wilson * elf32-xtensa.c (relax_property_section): Remove extra irel increment. 2007-04-27 Alan Modra * cpu-rs6000.c: Write Mimi's name in ASCII. * coff-rs6000.c: Likewise. * rs6000-core.c: Likewise. 2007-04-27 Alan Modra * sysdep.h: Include config.h first. Many files: Include sysdep.h before bfd.h. * Makefile.am: Run "make dep-am". * Makefile.in: Regenerate. 2007-04-25 Alan Modra * sysdep.h: Revert last change. 2007-04-24 Nick Clifton * coffcode.h (coff_slurp_reloc_table): Initialise dst.r_offset. * coff-m68k.c (m68kcoff_rtype_to_howto): Initialize relent.howto. 2007-04-24 Alan Modra * elf-eh-frame.c (_bfd_elf_discard_section_eh_frame): Warn if eh_frame_hdr table won't be created. 2007-04-24 Alan Modra * acinclude.m4: Include config/stdint.m4. * configure.in: Invoke GCC_HEADER_STDINT. * sysdep.h: Don't include ansidecl.h here. * configure: Regenerate. * config.in: Regenerate. * Makefile.in: Regenerate. 2007-04-23 Nathan Sidwell * archures.c (bfd_mach_mcf_isa_c, bfd_mach_mcf_isa_c_mac, bfd_mach_mcf_isa_c_emac): New. * elf32-m68k.c (ISAC_PLT_ENTRY_SIZE, elf_isac_plt0_entry, elf_isac_plt_entry, elf_isac_plt_info): New. (elf32_m68k_object_p): Add ISA_C. (elf32_m68k_print_private_bfd_data): Print ISA_C. (elf32_m68k_get_plt_info): Detect ISA_C. * cpu-m68k.c (arch_info): Add ISAC. (m68k_arch_features): Likewise, (bfd_m68k_compatible): ISAs B & C are not compatible. 2007-04-21 Nick Clifton * ecoff.c (_bfd_ecoff_write_armap): Initialise rehash. (ecoff_link_add_archive_symbols): Likewise. * coff-m68k.c (m68kcoff_common_addend_rtype_to_howto): Initialise relent.howto. * ieee.c (parse_int): Initialise x. (must_parse_int): Initialise result. (ieee_slurp_external_symbols): Initialise value. 2007-04-21 Alan Modra * config.bfd (spu-*-elf): Delete targ_selvecs. 2007-04-19 Nick Clifton * coffcode.h (coff_rtype_to_howto): Initialise genrel.howto. 2007-04-19 Alan Modra * bfd.c (bfd_demangle): New function. * Makefile.am: Run "make dep-am". * Makefile.in: Regenerate. * bfd-in2.h: Regenerate. 2007-04-18 Matthias Klose * Makefile.am (libbfd_la_LDFLAGS): Use bfd soversion. (bfdver.h): Use the date in non-release builds for the soversion. * Makefile.in: Regenerate. 2007-04-17 Paul Brook * elf.c (_bfd_elf_is_function_type): New function. * elflink.c (_bfd_elf_merge_symbol): Use bed->is_function_type. (_bfd_elf_dynamic_symbol_p, _bfd_elf_symbol_refs_local_p, is_global_data_symbol_definition, elf_link_add_object_symbols): Ditto. * elf-bfd.h (elf_backend_data): Add is_function_type. (_bfd_elf_is_function_type): Add prototype. * elfxx-target.h (elf_backend_is_function_type): Add default definition. (elfNN_bed): Add elf_backend_is_function_type. * elf32-arm.c (elf32_arm_is_function_type): New function. (elf_backend_is_function_type): Define. 2007-04-17 Daniel Jacobowitz * elfxx-mips.c (_bfd_mips_elf_size_dynamic_sections): Put DT_MIPS_RLD_MAP before DT_DEBUG again. 2007-04-14 Steve Ellcey * Makefile.am: Add ACLOCAL_AMFLAGS. * configure.in: Change macro call order. * Makefile.in: Regnerate. * doc/Makefile.in: Regenerate. * configure: Regenerate. 2007-04-14 Jakub Jelinek * elflink.c (bfd_elf_final_link): Don't free symbuf for non-elf input bfds. (bfd_elf_size_dynamic_sections): Don't access elf_section_data for non-elf input bfds. 2007-04-12 Richard Sandiford * elfxx-mips.c (_bfd_mips_elf_size_dynamic_sections): Don't add DT_MIPS_RTLD_MAP for PIEs. 2007-04-12 Richard Sandiford * elfxx-mips.c (mips_elf_calculate_relocation): Set DT_TEXTREL when creating a __GOTT_BASE__ or __GOTT_INDEX__ relocation in a read-only section. (_bfd_mips_elf_check_relocs): Likewise. 2007-04-12 Bob Wilson * elf32-xtensa.c (xtensa_is_insntable_section): New. (xtensa_is_proptable_section): New. (elf_xtensa_discard_info_for_section): Handle "full" .xt.prop property tables with 12-byte entries, as well as tables with 8-byte entries. Sort the relocations before examining them. (relax_property_section): Use xtensa_is_proptable_section and xtensa_is_littable_section. Rewrite code for combining table entries to be more robust in case of unexpected relocations. Do not set offset of unused relocations to less than zero. (xtensa_is_property_section): Use other functions instead of duplicating section name comparisons. (xtensa_is_littable_section): Use CONST_STRNEQ for ".gnu.linkonce.p.". (xtensa_get_property_predef_flags): Use xtensa_is_insntable_section. 2007-04-12 Bob Wilson * elf32-xtensa.c (elf_xtensa_gc_mark_hook): Don't follow references from Xtensa property sections. 2007-04-12 Alan Modra * elf32-spu.c (needs_ovl_stub): Test that spu_elf_section_data is non-NULL before dereferencing. 2007-04-11 Nathan Sidwell * elf-vxworks.c (elf_vxworks_emit_relocs): Remap weakdef PLT slot relocs too. 2007-04-10 Richard Henderson * elf64-alpha.c (struct alpha_elf_link_hash_table): Add relax_trip. (elf64_alpha_size_got_sections): Remove unused something_changed local. (elf64_alpha_size_plt_section): Return void. (elf64_alpha_size_rela_got_section): Likewise. (elf64_alpha_relax_section): Only regenerate got+plt if the relax_trip counter has changed. 2007-04-09 Daniel Jacobowitz * Makefile.am (bfdver.h): Do not generate doc/bfdver.texi. * doc/Makefile.am (DOCFILES): Add bfdver.texi. (bfdver.texi): New rule. * Makefile.in, doc/Makefile.in: Regenerated. 2007-04-03 Matt Thomas * elf32-vax.c (elf_vax_relocate_section): Do not emit a PCREL reloc in a shared object if it is not in a CODE section or if it is against a section symbol. This allows DWARF2 to use pcrel format. 2007-04-05 H.J. Lu PR ld/4304 * elflink.c (bfd_elf_final_link): Call einfo callback in bfd_link_info instead of _bfd_error_handler for DT_TEXTREL warning. 2007-04-05 Alan Modra * elf32-spu.c (spu_elf_output_symbol_hook): New function. (elf_backend_link_output_symbol_hook): Define. 2007-04-02 Nick Clifton PR binutils/4292 * bfd.c (bfd_fprintf_vma): Do not print addresses of 32-bit targets as 64-bit values, even if running on a 64-bit host. * coffgen.c (coff_print_symbol): Likewise. 2007-03-29 Nick Clifton PR binutils/4110 * elf.c (IS_VALID_GROUP_SECTION_HEADER): New macro. (setup_group): Use it. Report corrupt group section headers. (bfd_section_from_shdr): Use new macro. Replace constant 4 with GRP_ENTRY_SIZE. Cope with NULLs in the group section table. (elf_fake_section): Replace constant 4 with GRP_ENTRY_SIZE. 2007-03-29 Alan Modra PR ld/4267 * elflink.c (evaluate_complex_relocation_symbols): Use bfd_vma for rel->r_info values. (bfd_elf_perform_complex_relocation): Likewise. * elf32-ppc.c (allocate_dynrelocs): Set plt.offset to -1 for unused entries. Don't clear plt.plist in loop. 2007-03-28 Richard Sandiford * elfxx-sparc.h (_bfd_sparc_elf_link_hash_table): Remove append_rela. * elfxx-sparc.c (sparc_elf_append_rela_64, sparc_elf_append_rela_32): Merge into... (sparc_elf_append_rela): ...this new function. (SPARC_ELF_APPEND_RELA): Delete. (_bfd_sparc_elf_link_hash_table_create): Don't initialize the deleted append_rela field. (_bfd_sparc_elf_relocate_section): Use sparc_elf_append_rela instead of SPARC_ELF_APPEND_RELA. (_bfd_sparc_elf_finish_dynamic_symbol): Likewise. Use the elf_size_info structure to find the size of a RELA entry and the associated swap-out function. (sparc64_finish_dyn, sparc64_finish_dyn): Merge into... (sparc_finish_dyn): ...this new function. (_bfd_sparc_elf_finish_dynamic_sections): Update calls accordingly. 2007-03-28 Richard Sandiford Phil Edwards * doc/bfd.texinfo: Put the contents after the title page rather than at the end of the document. 2007-03-27 Andreas Schwab * elfxx-ia64.c (elf_backend_default_execstack): Define to 0. 2007-03-26 H.J. Lu * configure: Regenerated. 2007-03-26 Alan Modra * elf32-spu.c (struct stubarr): Add stub_hash_table and err fields. (allocate_spuear_stubs): New function. (spu_elf_size_stubs): Call allocate_spuear_stubs. 2007-03-26 Alan Modra * aout-adobe.c (aout_32_bfd_reloc_name_lookup): Define. * aout-arm.c (MY_bfd_reloc_name_lookup): Define. (MY (bfd_reloc_name_lookup)): New function. * aout-ns32k.c (MY (bfd_reloc_name_lookup)): New function. * aout-target.h (NAME (aout, reloc_name_lookup)): Declare. (MY_bfd_reloc_name_lookup): Define. * aout-tic30.c (tic30_aout_reloc_name_lookup): New function. (MY_bfd_reloc_name_lookup): Define. * aoutx.h (NAME (aout, reloc_type_lookup)): Don't declare. (NAME (aout, reloc_name_lookup)): New function. * bout.c (b_out_bfd_reloc_name_lookup): New function. * coff-alpha.c (alpha_bfd_reloc_name_lookup): New function. (_bfd_ecoff_bfd_reloc_name_lookup): Define. * coff-arm.c (coff_arm_reloc_name_lookup): New function. (coff_bfd_reloc_name_lookup): Define. * coff-i386.c (coff_bfd_reloc_name_lookup): Define. (coff_i386_reloc_name_lookup): New function. * coff-i860.c (coff_i860_reloc_name_lookup): New function. (coff_bfd_reloc_name_lookup): Define. * coff-i960.c (coff_i960_reloc_name_lookup): New function. (coff_bfd_reloc_name_lookup): Define. * coff-m68k.c (m68k_reloc_name_lookup): New function. (coff_bfd_reloc_name_lookup): Define. * coff-maxq.c (maxq_reloc_name_lookup): New function. (coff_bfd_reloc_name_lookup): Define. * coff-mcore.c (mcore_coff_reloc_name_lookup): New function. (coff_bfd_reloc_name_lookup): Define. * coff-mips.c (mips_bfd_reloc_name_lookup): New function. (_bfd_ecoff_bfd_reloc_name_lookup): Define. * coff-ppc.c (ppc_coff_reloc_name_lookup): New function. (coff_bfd_reloc_name_lookup): Define. * coff-rs6000.c (coff_bfd_reloc_name_lookup): Define. (_bfd_xcoff_reloc_name_lookup): New function. (rs6000coff_vec, pmac_xcoff_vec): Init new field. * coff-sh.c (coff_bfd_reloc_name_lookup): Define. (sh_coff_reloc_name_lookup): New function. * coff-sparc.c (coff_sparc_reloc_name_lookup): New function. (coff_bfd_reloc_name_lookup): Define. * coff-tic30.c (coff_bfd_reloc_name_lookup): Define. (tic30_coff_reloc_name_lookup): New function. * coff-tic4x.c (coff_bfd_reloc_name_lookup): Define. (tic4x_coff_reloc_name_lookup): New function. * coff-tic54x.c (coff_bfd_reloc_name_lookup): Define. (tic54x_coff_reloc_name_lookup): New function. * coff-x86_64.c (coff_bfd_reloc_name_lookup): Define. (coff_amd64_reloc_name_lookup): New function. * coff-z80.c (coff_z80_reloc_name_lookup): New function. (coff_bfd_reloc_name_lookup): Define. * coff-z8k.c (coff_z8k_reloc_name_lookup): New function. (coff_bfd_reloc_name_lookup): Define. * coff64-rs6000.c (coff_bfd_reloc_name_lookup): Define. (xcoff64_reloc_name_lookup): New function. (rs6000coff64_vec, aix5coff64_vec): Init new field. * coffcode.h (coff_bfd_reloc_name_lookup): Define. * elf-hppa.h (elf_hppa_reloc_name_lookup): New function. * elf-m10200.c (bfd_elf32_bfd_reloc_name_lookup): New function. * elf-m10300.c (bfd_elf32_bfd_reloc_name_lookup): New function. * elf32-arc.c (bfd_elf32_bfd_reloc_name_lookup): New function. * elf32-arm.c (elf32_arm_reloc_name_lookup): New function. (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-avr.c (bfd_elf32_bfd_reloc_name_lookup): New function. * elf32-bfin.c (bfin_bfd_reloc_name_lookup): New function. (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-cr16c.c (elf_cr16c_reloc_name_lookup): New function. (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-cris.c (cris_reloc_name_lookup): New function. (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-crx.c (elf_crx_reloc_name_lookup): New function. (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-d10v.c (bfd_elf32_bfd_reloc_name_lookup): New function. * elf32-d30v.c (bfd_elf32_bfd_reloc_name_lookup): New function. * elf32-dlx.c (elf32_dlx_reloc_name_lookup): New function. (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-fr30.c (fr30_reloc_name_lookup): New function. (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-frv.c (frv_reloc_name_lookup): New function. (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-gen.c (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-h8300.c (elf32_h8_reloc_name_lookup): New function. (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-hppa.c (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-i370.c (i370_elf_reloc_name_lookup): New function. (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-i386.c (elf_i386_reloc_name_lookup): New function. (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-i860.c (elf32_i860_reloc_name_lookup): New function. (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-i960.c (elf32_i960_reloc_name_lookup): New function. (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-ip2k.c (ip2k_reloc_name_lookup): New function. (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-iq2000.c (iq2000_reloc_name_lookup): New function. (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-m32c.c (m32c_reloc_name_lookup): New function. (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-m32r.c (bfd_elf32_bfd_reloc_name_lookup): New function. * elf32-m68hc11.c (bfd_elf32_bfd_reloc_name_lookup): New function. * elf32-m68hc12.c (bfd_elf32_bfd_reloc_name_lookup): New function. * elf32-m68k.c (reloc_name_lookup): New function. (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-m88k.c (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-mcore.c (mcore_elf_reloc_name_lookup): New function. (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-mep.c (mep_reloc_name_lookup): New function. (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-mips.c (bfd_elf32_bfd_reloc_name_lookup): New function. (mips_vxworks_bfd_reloc_name_lookup): Likewise. (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-msp430.c (bfd_elf32_bfd_reloc_name_lookup): New function. * elf32-mt.c (mt_reloc_name_lookup): New function. (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-openrisc.c (openrisc_reloc_name_lookup): New function. (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-or32.c (bfd_elf32_bfd_reloc_name_lookup): New function. * elf32-pj.c (pj_elf_reloc_name_lookup): New function. (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-ppc.c (ppc_elf_reloc_name_lookup): New function. (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-s390.c (elf_s390_reloc_name_lookup): New function. (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-score.c (elf32_score_reloc_name_lookup): New function. (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-sh.c (sh_elf_reloc_name_lookup): New function. (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-sparc.c (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-spu.c (spu_elf_reloc_name_lookup): New function. (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-v850.c (v850_elf_reloc_name_lookup): New function. (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-vax.c (reloc_name_lookup): New function. (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-xc16x.c (xc16x_reloc_name_lookup): New function. (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-xstormy16.c (xstormy16_reloc_name_lookup): New function. (bfd_elf32_bfd_reloc_name_lookup): Define. * elf32-xtensa.c (elf_xtensa_reloc_name_lookup): New function. (bfd_elf32_bfd_reloc_name_lookup): Define. * elf64-alpha.c (elf64_alpha_bfd_reloc_name_lookup): New function. (bfd_elf64_bfd_reloc_name_lookup): Define. * elf64-gen.c (bfd_elf64_bfd_reloc_name_lookup): Define. * elf64-hppa.c (bfd_elf64_bfd_reloc_name_lookup): Define. * elf64-mips.c (bfd_elf64_bfd_reloc_name_lookup): New function. * elf64-mmix.c (bfd_elf64_bfd_reloc_name_lookup): New function. * elf64-ppc.c (ppc64_elf_reloc_name_lookup): New function. (bfd_elf64_bfd_reloc_name_lookup): Define. * elf64-s390.c (elf_s390_reloc_name_lookup): New function. (bfd_elf64_bfd_reloc_name_lookup): Define. * elf64-sh64.c (sh_elf64_reloc_name_lookup): New function. (bfd_elf64_bfd_reloc_name_lookup): Define. * elf64-sparc.c (bfd_elf64_bfd_reloc_name_lookup): Define. * elf64-x86-64.c (elf64_x86_64_reloc_name_lookup): New function. (bfd_elf64_bfd_reloc_name_lookup): Define. * elfn32-mips.c (bfd_elf32_bfd_reloc_name_lookup): New function. * elfxx-ia64.c (elfNN_ia64_reloc_name_lookup): New function. (bfd_elfNN_bfd_reloc_name_lookup): Define. * elfxx-sparc.c (_bfd_sparc_elf_reloc_name_lookup): New function. * elfxx-sparc.h (_bfd_sparc_elf_reloc_name_lookup): Declare. * i386msdos.c (msdos_bfd_reloc_name_lookup): Define. * i386os9k.c (aout_32_bfd_reloc_name_lookup): Define. * ieee.c (ieee_bfd_reloc_name_lookup): Define. * libaout.h (NAME (aout, reloc_name_lookup)): Declare. * libbfd-in.h (_bfd_norelocs_bfd_reloc_name_lookup): Declare. * mipsbsd.c (MY_bfd_reloc_name_lookup): Define. (MY(reloc_type_lookup)): Rename from MY(reloc_howto_type_lookup). (MY(reloc_name_lookup)): New function. * nlm-target.h (nlm_bfd_reloc_name_lookup): Define. * oasys.c (oasys_bfd_reloc_name_lookup): Define. * pdp11.c (NAME (aout, reloc_name_lookup)): New function. * pe-mips.c (coff_mips_reloc_name_lookup): New function. (coff_bfd_reloc_name_lookup): Define. * reloc.c (bfd_reloc_name_lookup): New function. * riscix.c (riscix_reloc_name_lookup): New function. (MY_bfd_reloc_name_lookup): Define. * som.c (som_bfd_reloc_name_lookup): New function. * targets.c (struct bfd_target): Add reloc_name_lookup. (BFD_JUMP_TABLE_RELOCS): Add NAME##_bfd_reloc_name_lookup. * versados.c (versados_bfd_reloc_name_lookup): Define. * vms.c (vms_bfd_reloc_name_lookup): New function. * bfd-in2.h: Regenerate. * libbfd.h: Regenerate. 2007-03-26 Thiemo Seufer PR ld/4208 * elfxx-mips.c (mips_elf_next_relocation): Don't signal an error if no matching relocation is found. (_bfd_mips_elf_relocate_section): Only warn about missing relocations. 2007-03-23 H.J. Lu * configure: Regenerated. 2007-03-23 Joseph Myers * configure.in: Use ACX_PKGVERSION and ACX_BUGURL. * configure: Regenerate. 2007-03-23 Alan Modra * elf32-spu.c (spu_stub_name): Don't put input section in stub name. Remove input_sec param. Adjust all calls. (write_one_stub): Adjust stub symbol. (needs_ovl_stub): New function, extracted from.. (spu_elf_size_stubs): ..here. (spu_elf_relocate_section): Use needs_ovl_stub. 2007-03-22 Joseph Myers * Makefile.am (bfdver.h): Only set VERSION_PACKAGE in bfdver.texi if nonempty. * configure.in (REPORT_BUGS_TO): Do not use "URL:" prefix. * Makefile.in, configure, doc/Makefile.in: Regenerate. 2007-03-22 H.J. Lu PR ld/4210 * peXXigen.c (_bfd_XXi_swap_aouthdr_out): Use the virtual address and virtual size of the last section for the image size. 2007-03-22 H.J. Lu PR ld/4007 * elf.c (assign_file_positions_for_load_sections): Check if all sections are in the segment. 2007-03-20 H.J. Lu PR ld/4208 * elfxx-mips.c (_bfd_mips_elf_relocate_section): Report missing matching LO16 relocation for HI16 relocation. 2007-03-20 Paul Brook * bfd-in.h (bfd_elf32_arm_set_target_relocs): Update prototype. * bfd-in2.h: Regenerate. * elf32-arm.c (elf32_arm_link_hash_table): Add pic_veneer. (record_arm_to_thumb_glue): Use globals->pic_veneer. (elf32_arm_create_thumb_stub): Ditto. (bfd_elf32_arm_set_target_relocs): Set globals->pic_veneer. 2007-03-18 Mark Shinwell * bfd-in.h (bfd_elf32_arm_set_target_relocs): Add "bfd *" argument and extra last argument. * bfd-in2.h: Regenerate. * elf32-arm.c (elf32_arm_obj_tdata): Add no_enum_size_warning member. (bfd_elf32_arm_set_target_relocs): Add "bfd *" argument and extra last argument. Set no_enum_size_warning appropriately. (elf32_arm_merge_eabi_attributes): Improve enum sizes diagnostic, suppressing it when no_enum_size_warning dictates. 2007-03-20 Nick Clifton PR binutils/3535 * elf.c (copy_private_bfd_data): Widen the scope of Solaris specific conditions that need the program headers to be rewritten. 2007-03-19 H.J. Lu * peXXigen.c (_bfd_XXi_swap_aouthdr_in): Store Magic, MajorLinkerVersion, MinorLinkerVersion, SizeOfCode, SizeOfInitializedData, SizeOfUninitializedData, AddressOfEntryPoint, BaseOfCode and BaseOfData in internal extra PE a.out header. (IMAGE_NT_OPTIONAL_HDR_MAGIC): Defined as 0x10b if not defined. (IMAGE_NT_OPTIONAL_HDR64_MAGIC): Defined as 0x20b if not defined. (IMAGE_NT_OPTIONAL_HDRROM_MAGIC): Defined as 0x107 if not defined. (_bfd_XX_print_private_bfd_data_common): Also print Magic, MajorLinkerVersion, MinorLinkerVersion, SizeOfCode, SizeOfInitializedData, SizeOfUninitializedData, AddressOfEntryPoint, BaseOfCode and BaseOfData from internal extra PE a.out header. 2007-03-18 H.J. Lu * targets.c (_bfd_target_vector): Add bfd_efi_app_x86_64_vec only if BFD64 is defined. 2007-03-17 Alan Modra * elf32-spu.c (spu_elf_size_stubs): Always use an overlay stub on setjmp calls. 2007-03-15 H.J. Lu * doc/Makefile.in: Regenerated. 2007-03-15 H.J. Lu * Makefile.am (bfdver.h): Substitute report_bugs_to. Also create doc/bfdver.texi. * Makefile.in: Regenerated. * configure.in (--with-bugurl): New option. * configure: Regenerated. * version.h (REPORT_BUGS_TO): New. 2007-03-13 H.J. Lu PR binutils/3826 * elf-bfd.h (elf_backend_data): Add elf_osabi. (_bfd_elf_set_osabi): New. * elf.c (_bfd_elf_set_osabi): New. * elf32-hppa.c (elf32_hppa_post_process_headers): Removed. (elf_backend_post_process_headers): Defined with _bfd_elf_set_osabi. (ELF_OSABI): Properly defined for each target. * elf32-i370.c (i370_elf_post_process_headers): Removed. (ELF_OSABI): Defined. (elf_backend_post_process_headers): Defined with _bfd_elf_set_osabi. * elf32-i386.c (ELF_OSABI): Defined to ELFOSABI_FREEBSD for freebsd. (elf_i386_post_process_headers): Set EI_OSABI with elf_osabi. * elf32-msp430.c (elf32_msp430_post_process_headers): Removed. (ELF_OSABI): Defined. (elf_backend_post_process_headers): Defined with _bfd_elf_set_osabi. * elf64-alpha.c (ELF_OSABI): Defined to ELFOSABI_FREEBSD for freebsd. (elf64_alpha_fbsd_post_process_headers): Set EI_OSABI with elf_osabi. * elf64-hppa.c (elf64_hppa_post_process_headers): Set EI_OSABI with elf_osabi. (ELF_OSABI): Properly defined for each target. (elf_backend_post_process_headers): Defined with _bfd_elf_set_osabi for Linux. * elf64-sparc.c (elf64_sparc_fbsd_post_process_headers): Removed. (ELF_OSABI): Defined to ELFOSABI_FREEBSD for freebsd. (elf_backend_post_process_headers): Defined with _bfd_elf_set_osabi. * elf64-x86-64.c (elf64_x86_64_fbsd_post_process_headers): Removed. (ELF_OSABI): Defined to ELFOSABI_FREEBSD for freebsd. (elf_backend_post_process_headers): Defined with _bfd_elf_set_osabi. * elfcode.h (elf_object_p): Match the ELFOSABI_NONE ELF target with any ELF target of the compatible machine for which we do not have a specific backend. * elfxx-ia64.c (elfNN_hpux_post_process_headers): Set EI_OSABI with elf_osabi. * elfxx-target.h (ELF_OSABI): Default to ELFOSABI_NONE. (elfNN_bed): Initialize elf_osabi with ELF_OSABI. 2007-03-08 Alan Modra * elf32-v850.c (v850_elf_link_output_symbol_hook): Clean out V850_OTHER_* bits. 2007-03-08 Alan Modra * Makefile.am (BFD64_BACKENDS): Add efi-app-x86_64.lo. (BFD64_BACKENDS_CFILES): Add efi-app-x86_64.c. Run "make dep-am". * Makefile.in: Regenerate. * po/SRC-POTFILES.in: Regenerate. 2007-03-07 H.J. Lu * config.bfd (x86_64-*-freebsd*): Add bfd_efi_app_x86_64_vec. (x86_64-*-kfreebsd*-gnu): Likewise. (x86_64-*-netbsd*): Likewise. (x86_64-*-openbsd*): Likewise. (x86_64-*-linux-*): Likewise. * configure.in: Support bfd_efi_app_x86_64_vec. * configure: Regenerated. * efi-app-x86_64.c: New file. * targets.c (bfd_efi_app_x86_64_vec): New. (_bfd_target_vector): Add bfd_efi_app_x86_64_vec. 2007-03-07 Kai Tietz * reloc.c (bfd_generic_get_relocated_section_contents): Remove const for type reloc_howto_type. 2007-03-07 Alan Modra PR 3958 * elf-bfd.h (RELOC_FOR_GLOBAL_SYMBOL): No error on relocatable link. (elf_discarded_section): Move.. * bfd-in.h: ..to here. * bfd-in2.h: Regenerate. * elflink.c (elf_link_input_bfd): Don't zap relocs against symbols from discarded sections before relocate_section has done its job. * reloc.c (bfd_generic_get_relocated_section_contents): Handle relocs against symbols from discarded sections. * elf-hppa.h (elf_hppa_howto_table): Set size. Set dst_mask on SECREL32. (elf_hppa_relocate_section): Handle relocatable link after setting sec, sym, h etc. for final link. Squash error messages for relocatable link. Clear section contents for relocs against symbols in discarded sections, and zero reloc. Remove existing zero r_symndx code. * elf-m10200.c (mn10200_elf_relocate_section): Likewise. * elf-m10300.c (mn10300_elf_relocate_section): Likewise. * elf32-arm.c (elf32_arm_relocate_section): Likewise. * elf32-avr.c (elf32_avr_relocate_section): Likewise. * elf32-bfin.c (bfinfdpic_relocate_section): Likewise. (bfin_relocate_section): Likewise. * elf32-cr16c.c (elf32_cr16c_relocate_section): Likewise. * elf32-cris.c (cris_elf_relocate_section): Likewise. * elf32-crx.c (elf32_crx_relocate_section): Likewise. * elf32-d10v.c (elf32_d10v_relocate_section): Likewise. * elf32-fr30.c (fr30_elf_relocate_section): Likewise. * elf32-frv.c (elf32_frv_relocate_section): Likewise. * elf32-h8300.c (elf32_h8_relocate_section): Likewise. * elf32-hppa.c (elf32_hppa_relocate_section): Likewise. * elf32-i370.c (i370_elf_relocate_section): Likewise. * elf32-i386.c (elf_i386_relocate_section): Likewise. * elf32-i860.c (elf32_i860_relocate_section): Likewise. * elf32-ip2k.c (ip2k_elf_relocate_section): Likewise. * elf32-iq2000.c (iq2000_elf_relocate_section): Likewise. * elf32-m32c.c (m32c_elf_relocate_section): Likewise. * elf32-m32r.c (m32r_elf_relocate_section): Likewise. * elf32-m68hc1x.c (elf32_m68hc11_check_relocs): Likewise. * elf32-m68k.c (elf_m68k_relocate_section): Likewise. * elf32-mcore.c (mcore_elf_relocate_section): Likewise. * elf32-mep.c (mep_elf_relocate_section): Likewise. * elf32-msp430.c (elf32_msp430_relocate_section): Likewise. * elf32-mt.c (mt_elf_relocate_section): Likewise. * elf32-openrisc.c (openrisc_elf_relocate_section): Likewise. * elf32-ppc.c (ppc_elf_relocate_section): Likewise. * elf32-s390.c (elf_s390_relocate_section): Likewise. * elf32-score.c (_bfd_score_elf_relocate_section): Likewise. * elf32-sh.c (sh_elf_relocate_section): Likewise. * elf32-spu.c (spu_elf_relocate_section): Likewise. * elf32-v850.c (v850_elf_relocate_section): Likewise. * elf32-vax.c (elf_vax_relocate_section): Likewise. * elf32-xc16x.c (elf32_xc16x_relocate_section): Likewise. * elf32-xstormy16.c (xstormy16_elf_relocate_section): Likewise. * elf32-xtensa.c (elf_xtensa_relocate_section): Likewise. * elf64-alpha.c (elf64_alpha_relocate_section_r): Likewise. (elf64_alpha_relocate_section): Likewise. * elf64-mmix.c (mmix_elf_relocate_section): Likewise. * elf64-ppc.c (ppc64_elf_relocate_section): Likewise. * elf64-s390.c (elf_s390_relocate_section): Likewise. * elf64-sh64.c (sh_elf64_relocate_section): Likewise. * elf64-x86-64.c (elf64_x86_64_relocate_section): Likewise. * elfxx-ia64.c (elfNN_ia64_relocate_section): Likewise. * elfxx-mips.c (_bfd_mips_elf_relocate_section): Likewise. * elfxx-sparc.c (_bfd_sparc_elf_relocate_section): Likewise. * elf32-arm.c (elf32_arm_relocate_section): Always adjust section symbols for relocatable link. Don't use always-zero st_value. (elf_backend_rela_normal): Don't define. * elf32-bfin.c (bfinfdpic_relocate_section): Use RELOC_FOR_GLOBAL_SYMBOL. * elf32-frv.c (elf32_frv_relocate_section): Likewise. * elf32-d10v.c (elf32_d10v_relocate_section): Combine SEC_MERGE section symbol adjustments with same for relocatable link. * elf32-i386.c (elf_i386_relocate_section): Likewise. * elf32-m68hc1x.c (m68hc11_get_relocation_value): Move.. (elf32_m68hc11_check_relocs): ..to here. * elf32-score.c (score_elf_final_link_relocate): Remove zero r_symndx code. * elfxx-mips.c (mips_elf_calculate_relocation): Likewise. 2007-03-07 Alan Modra PR 4144 * elf.c (assign_file_positions_for_load_sections): Don't adjust p_memsz for !SEC_LOAD section vma modulo page size. Instead, use the same lma based adjustment for SEC_LOAD sections. 2007-03-01 Bob Wilson * elf32-xtensa.c (analyze_relocations): Zero src_count if not relaxing. (find_relaxable_sections): Do not increment src_count for unknown opcodes. Decode only once instead of calling is_l32r_relocation. (compute_text_actions): Remove unused no_insn_move flag. Assert that src_next matches src_count in relax_info. 2007-03-01 Joseph Myers * Makefile.am (bfdver.h): Use "." not " " between version number and date. * Makefile.in: Regenerate. * configure.in (PKGVERSION): Default to "(GNU Binutils) ". * configure: Regenerate. 2007-02-28 Nathan Sidwell * config.bfd (sh-*-uclinux, sh[12]-*-uclinux): New stanza. 2007-02-27 Alan Modra * elf32-spu.h (struct _ovl_stream): Make "start" and "end" const. * elf32-spu.c (ovl_mgr_pread): Add const to casts. 2007-02-23 Carlos O'Donell * dwarf2.c (_bfd_dwarf2_find_nearest_line): Assume 32-bit DWARF even with 64-bit addresses. (_bfd_dwarf2_find_nearest_line): Likewise. 2007-02-23 Nick Clifton PR binutils/3535 * elf.c (copy_private_bfd_data): Always rewrite the program headers when a Solaris interpreter segment is involved. 2007-02-22 Paul Brook * elflink.c (gc_mark_hook_fn): Remove. (_bfd_elf_gc_mark): Rename gc_mark_hook_fn to elf_gc_mark_hook_fn. (bfd_elf_gc_sections): Ditto. Call gc_mark_extra_sections. * elf-bfd.h (elf_gc_mark_hook_fn): Define. (elf_backend_data): Add gc_mark_extra_sections. * elfxx-target.h (elf_backend_gc_mark_extra_sections): Provide default definition. (elfNN_bed): Add elf_backend_gc_mark_extra_sections. * elf32-arm.c (elf32_arm_gc_mark_extra_sections): New function. (elf_backend_gc_mark_extra_sections): Define. 2007-02-21 Nick Clifton * elf.c (_bfd_elf_map_sections_to_segments): If the override_segment_assignment callback is defined then call it. 2007-02-21 Alan Modra * elf32-spu.c (spu_elf_size_stubs): Correct order of warning args. 2007-02-19 Thiemo Seufer * elfxx-mips.c (_bfd_mips_elf_print_private_bfd_data): Remove translation marker from untranslatable strings. 2007-02-19 Alan Modra * elf-bfd.h (struct elf_backend_data): Add default_execstack. * elflink.c (bfd_elf_size_dynamic_sections): Heed default_execstack. * elfxx-target.h (elf_backend_default_execstack): Define to 1. (elfNN_bed): Init new field. * elf64-ppc.c (elf_backend_default_execstack): Define to 0. 2007-02-17 Mark Mitchell Nathan Sidwell Vladimir Prus * configure.in (--with-pkgversion): New option. * configure: Regenerate. * Makefile.am (bfdver.h): Substitute for @bfd_version_package@. * Makefile.in: Regenerate. * version.h (BFD_VERSION_STRING): Define using @bfd_version_package@. 2007-02-16 Carlos O'Donell * elfxx-mips.c (_bfd_mips_elf_print_private_bfd_data): Print EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_XGOT and EF_MIPS_UCODE. 2007-02-15 Alan Modra * libbfd-in.h (_bfd_norelocs_get_reloc_upper_bound): Don't define, declare. (_bfd_norelocs_canonicalize_reloc): Likewise. * libbfd.h: Regenerate. * libbfd.c (_bfd_norelocs_get_reloc_upper_bound): New function. (_bfd_norelocs_canonicalize_reloc): Likewise. * binary.c (binary_bfd_reloc_type_lookup): Don't define. (binary_get_reloc_upper_bound, binary_canonicalize_reloc): Likewise. (binary_vec): Use _bfd_norelocs in BFD_JUMP_TABLE_RELOCS. * ihex.c: Similarly. * mach-o-target.c: Similarly. * mach-o.c: Similarly. * mmo.c: Similarly. * pef.c: Similarly. * ppcboot.c: Similarly. * srec.c: Similarly. * xsym.c: Similarly. 2007-02-14 H.J. Lu PR ld/3953 * elflink.c (_bfd_elf_add_default_symbol): Check warning symbol when adding default symbol. 2007-02-13 Alan Modra * elf64-ppc.c (create_linkage_sections): Use section ".branch_lt" for branch lookup table. 2007-02-12 Alan Modra * elf64-ppc.c (create_linkage_sections): Don't create .rela.rodata.brlt for --emit-relocs. (ppc_build_one_stub): Create relocs for brlt --emit-relocs here. (ppc_size_one_stub): Count them. Simplify test of stub type when counting stub relocs. Set SEC_RELOC too. (ppc64_elf_size_stubs): Clear reloc_count and SEC_RELOC. (ppc64_elf_finish_dynamic_sections): Output brlt relocs. 2007-02-12 Alan Modra * elflink.c (evaluate_complex_relocation_symbols): Ignore relocs with a zero symbol index. 2007-02-12 Alan Modra * elflink.c (bfd_elf_discard_info): Tidy setting of "eh". 2007-02-05 Dave Brolley Stan Cox PR ld/3972 * elflink.c (elf_link_input_bfd): Always setup finfo->internal_syms. 2007-02-05 Dave Brolley Richard Sandiford Stan Cox Nick Clifton DJ Delorie Frank Ch. Eigler Ben Elliston Richard Henderson * Makefile.am (ALL_MACHINES): Add cpu-mep.lo. (ALL_MACHINES_CFILES): Add CPU_MEP.c. (BFD32_BACKENDS): Add elf32-mep.lo. (BFD32_BACKENDS_CFILES): Add elf32-mep.c. (cpu-mep.lo,elf32-mep.lo): New targets. * archures.c (bfd_arch_mep): New enumerator. (bfd_mach_mep, bfd_mach_mep_h1): New macros. (bfd_mep_arch): New external variable. (bfd_archures_list): Add bfd_mep_arch. * config.bfd: Support mep-*-elf. * configure.in: Support bfd_elf32_mep_vec and bfd_elf32_mep_little_vec. * reloc.c (BFD_RELOC_MEP_*): New relocation numbers. * targets.c (bfd_elf32_mep_vec,bfd_elf32_mep_little_vec): New extern declarations. (_bfd_target_vector): Add bfd_elf32_mep_vec and bfd_elf32_mep_little_vec. * mep-relocs.pl: New file. * cpu-mep.c: New file. * elf32-mep.c: New file. * bfd-in2.h: Regenerate. * po/POTFILES.in: Regenerate. * libbfd.h: Regenerate. * Makefile.in: Regenerate. * configure: Regenerate. 2007-02-05 Dave Brolley * elflink.c (evaluate_complex_relocation_symbols): Check for STT_SRELC for global symbols. (perform_complex_relocations): Renamed to perform_complex_relocation and now examines only one relocation. (elf_link_input_bfd): Don't call perform_complex_relocations. * elf-bfd.h (bfd_elf_perform_complex_relocation_: New prototype. * elf32-mep.c (mep_elf_howto_table): Add R_RELC. (OD,OS,OU): #undefs corrected to N, S and U repectively. (mep_reloc_type_lookup): Handle BFD_RELOC_RELC. (complex_reloc_installation_howto): Removed. (mep_info_to_howto_rela): Remove special case for r_type==0xff. (mep_elf_relocate_section): Call bfd_elf_perform_complex_relocation. 2007-02-05 Dave Brolley Richard Sandiford DJ Delorie Graydon Hoare Nick Clifton Jeff Holcomb Frank Ch. Eigler * elf-bfd.h (bfd_elf_perform_complex_relocations): New prototype. * elf.c (swap_out_syms): Handle BSF_RELC and BSF_SRELC. * elfcode.h (elf_slurp_symbol_table): Handle STT_RELC and STT_SRELC. * elflink.c (set_symbolValue): New static function. (resolve_symbol): Likewise. (resolve_section): Likewise. (undefined_reference): Likewise. (eval_symbol): Likewise. (evaluate_complex_relocation_symbols): Likewise. (put_value): Likewise. (get_value): Likewise. (decode_complex_addend): (bfd_elf_perform_complex_relocation): New function. (elf_link_input_bfd): Call evaluate_complex_relocation_symbols. * reloc.c (BFD_RELOC_RELC): New relocation number. * syms.c (BSF_RELC,BSF_SRELC): New macros. 2007-02-05 Bob Wilson * elf32-xtensa.c (elf_xtensa_make_sym_local): Delete. (elf_xtensa_hide_symbol, elf_backend_hide_symbol): Delete. (elf_xtensa_fix_refcounts, elf_xtensa_allocate_plt_size) (elf_xtensa_allocate_got_size): Replace these with... (elf_xtensa_allocate_dynrelocs): ...this new function. (elf_xtensa_size_dynamic_sections): Use it. 2007-02-05 Bob Wilson * elf32-xtensa.c (elf_howto_table) : Set src_mask to zero. : Likewise. Also fix dst_mask. : Set pcrel_offset to TRUE. 2007-02-02 Bob Wilson * elf32-xtensa.c (xtensa_elf_dynamic_symbol_p): Renamed to... (elf_xtensa_dynamic_symbol_p): ...this. 2007-02-02 Bob Wilson * elf32-xtensa.c (plt_reloc_count): Move into link hash table. (struct elf_xtensa_link_hash_table): New. (elf_xtensa_hash_table): New. (elf_xtensa_link_hash_table_create): New. (elf_xtensa_check_relocs): Update plt_reloc_count references. Update arguments to add_extra_plt_sections. (elf_xtensa_create_dynamic_sections): Record new sections in the hash table. Update for plt_reloc_count and add_extra_plt_sections. (add_extra_plt_sections, elf_xtensa_create_plt_entry): Replace dynobj argument with link info. Update calls to elf_xtensa_get_plt_section and elf_xtensa_get_gotplt_section. (elf_xtensa_allocate_local_got_size, elf_xtensa_size_dynamic_sections) (elf_xtensa_relocate_section, elf_xtensa_finish_dynamic_sections) (elf_xtensa_discard_info_for_section, shrink_dynamic_reloc_sections) (relax_property_section): Get sections from the hash table and update function calls. (elf_xtensa_get_plt_section, elf_xtensa_get_gotplt_section): Replace dynobj argument with link info. Get sections for first plt chunk from the hash table. (bfd_elf32_bfd_link_hash_table_create): Define. 2007-02-02 Jakub Jelinek * elf-bfd.h (struct elf_obj_tdata): Change symbuf type to void *. * elf.c (struct elf_symbuf_symbol, struct elf_symbuf_head): New types. (struct elf_symbol): Change first member into union. (elf_sort_elf_symbol): Compare pointers to internal syms rather than internal syms. Only compare st_shndx fields. (elf_create_symbuf): New function. (bfd_elf_match_symbols_in_sections): Use it. If symbufs are available for bfds, use a binary search, otherwise don't qsort symbols unnecessarily only to select which symbols are for the particular shndx. 2007-02-01 Nick Clifton PR ld/3852 * elf.c (_bfd_elf_link_hash_table_init): Initialize all the fields in the elf_link_hash_table structure. 2007-02-01 Alan Modra * elf-bfd.h (struct elf_backend_data): Add elf_backend_write_core_note. * elfxx-target.h (elf_backend_write_core_note): Define and use. * elf.c (elfcore_write_prpsinfo): Call the above. Add support for 32-bit core note on 64-bit target. (elfcore_write_prstatus): Likewise. (elfcore_write_lwpstatus): Make note_name const. (elfcore_write_prfpreg): Likewise. (elfcore_write_pstatus): Add support for 32-bit core note on 64-bit target. * elf32-ppc.c (ppc_elf_write_core_note): New function. (elf_backend_write_core_note): Define. * elf64-ppc.c (ppc64_elf_write_core_note): New function. (elf_backend_write_core_note): Define. 2007-01-31 H.J. Lu * elf32-cris.c (INCLUDED_TARGET_FILE): Removed. (elf32_bed): Defined for elf32-us-cris. * elf64-sh64.c (elf64_bed): Defined for Linux. (INCLUDED_TARGET_FILE): Removed. * elfxx-target.h (elfNN_bed): Always define. Don't check INCLUDED_TARGET_FILE. 2007-01-31 DJ Delorie * elf-m10300.c (mn10300_elf_relocate_section): Clarify the warning message for dangerous relocs, special case the common user error. 2007-01-30 H.J. Lu * elf.c (copy_elf_program_header): Start from the first section in a segment and stop when all sections in a segment are accounted for. 2007-01-29 Julian Brown * bfd-in2.h: Regenerate. * bfd-in.h (bfd_arm_vfp11_fix): New enum. Specify how VFP11 instruction scanning should be done. (bfd_elf32_arm_init_maps, bfd_elf32_arm_vfp11_erratum_scan) (bfd_elf32_arm_vfp11_fix_veneer_locations): Add prototypes. (bfd_elf32_arm_set_target_relocs): Add vfp11 fix type argument to prototype. * elf-bfd.h (elf_backend_write_section): Add struct bfd_link_info argument. * elf32-arm.c (VFP11_ERRATUM_VENEER_SECTION_NAME) (VFP11_ERRATUM_VENEER_ENTRY_NAME): Define macros. (elf32_vfp11_erratum_type): New enum. (elf32_vfp11_erratum_list): New struct. List of veneers or jumps to veneers. (_arm_elf_section_data): Add mapsize, erratumcount, erratumlist. (elf32_arm_link_hash_table): Add vfp11_erratum_glue_size, vfp11_fix and num_vfp11_fixes fields. (elf32_arm_link_hash_table_create): Initialise vfp11_fix, vfp11_erratum_glue_size, num_vfp11_fixes fields. (VFP11_ERRATUM_VENEER_SIZE): Define. Size of an (ARM) veneer. (bfd_elf32_arm_allocate_interworking_sections): Initialise erratum glue section. (elf32_arm_section_map_add): Add an code/data mapping symbol entry to a section's map. (record_vfp11_erratum_veneer): Create a single veneer, and its associated symbols. (bfd_elf32_arm_add_glue_sections_to_bfd): Add vfp11 erratum glue. (bfd_elf32_arm_init_maps): Initialise mapping symbol table for input BFDs. (bfd_elf32_arm_set_vfp11_fix): Set the type of erratum workaround required. (bfd_arm_vfp11_pipe): Define VFP11 instruction pipes. (bfd_arm_vfp11_regno): Recode a register number from a VFP11 insn. (bfd_arm_vfp11_write_mask): Update write mask according to coded register number. (bfd_arm_vfp11_antidependency): New function. (bfd_arm_vfp11_insn_decode): Decode a VFP11 insn. (elf32_arm_compare_mapping): Declare. (bfd_elf32_arm_vfp11_erratum_scan): Scan the sections of an input BFD for potential erratum-triggering insns. Record results. (bfd_elf32_arm_vfp11_fix_veneer_locations): Find out where veneers and branches to veneers have been placed in virtual memory after layout. (bfd_elf32_arm_set_target_relocs): Set vfp11_fix field in global hash table. (elf32_arm_output_symbol_hook): Remove. (elf32_arm_write_section): Output veneers, and branches to veneers. Use maps from input sections, not output sections, for code byte-swapping. * elf32-ppc.c (ppc_elf_write_section): Add dummy link_info argument. * elf32-score.c (_bfd_score_elf_write_section): Likewise. * elfxx-mips.c (_bfd_mips_elf_write_section): Likewise. * elfxx-mips.h (_bfd_mips_elf_write_section): Likewise. 2007-01-27 H.J. Lu * elf64-hppa.c (elf64_bed): Defined for HPUX and Linux. (INCLUDED_TARGET_FILE): Removed. 2007-01-27 Mike Frysinger * elf32-hppa.c (elf32_bed): Define for hpux, linux and netbsd. (INCLUDED_TARGET_FILE): Remove. 2007-01-25 DJ Delorie * elf32-m32c.c (m32c_elf_howto_table): Don't complain about R_M32C_16 or R_M32C_24 relocs. 2007-01-25 Nick Clifton PR binutils/3874 * elf32-avr.c (avr_link_hash_table): Check to make sure that the hash table was created by elf32_avr_link_hash_table_create before using it. (elf32_avr_link_hash_newfunc): New function. Just pass the call through to _bfd_elf_link_hash_newfunc. (elf32_avr_link_hash_table_create): Use elf32_avr_link_hash_newfunc instead of _bfd_elf_link_hash_newfunc. (elf32_avr_relocate_section): Check for the hash table pointer being NULL. (elf32_avr_relax_section, avr_build_one_stub, elf32_avr_setup_params, get_local_syms, elf32_avr_size_stubs, elf32_avr_build_stubs): Likewise. 2007-01-16 H.J. Lu PR ld/3831 * elf-bfd.h (bfd_elf_link_mark_dynamic_symbol): Add an argument, Elf_Internal_Sym *. * elflink.c (bfd_elf_link_mark_dynamic_symbol): Mark a data symbol dynamic if info->dynamic_data is TRUE. (bfd_elf_record_link_assignment): Updated call to bfd_elf_record_link_assignment. (_bfd_elf_merge_symbol): Likewise. Always call bfd_elf_link_mark_dynamic_symbol. 2007-01-12 H.J. Lu * Makefile.am (BFD_LIBS): Removed. * Makefile.in: Regenerated. 2007-01-11 H.J. Lu PR binutils/3631 * Makefile.am (OFILES): Add @bfd64_libs@. (libbfd_la_SOURCES): Remove $(BFD64_LIBS_CFILES). * Makefile.in: Regenerated. * configure.in (bfd_libs): Replaced by ... (bfd64_libs): This. * configure: Regenerated. 2007-01-11 Nathan Sidwell * elf.c (assign_file_positions_for_load_sections): We can require fewer phdrs than expected. 2007-01-08 Kazu Hirata * archures.c (bfd_mach_cpu32_fido): Rename to bfd_mach_fido. * bfd-in2.h: Regenerate. * cpu-m68k.c (arch_info_struct): Use bfd_mach_fido instead of bfd_mach_cpu32_fido. (m68k_arch_features): Use fido_a instead of cpu32. (bfd_m68k_compatible): Reject the combination of Fido and ColdFire. Accept the combination of CPU32 and Fido with a warning. * elf32-m68k.c (elf32_m68k_object_p, elf32_m68k_merge_private_bfd_data, elf32_m68k_print_private_bfd_data): Treat Fido as an architecture by itself. 2007-01-08 Kai Tietz * config.bfd: Renamed target x86_64-*-mingw64 to x86_64-*-mingw*. 2007-01-05 Jakub Jelinek * texhex.c (first_phase): Don't fall through into the default case. (pass_over): Replace abort () calls with return FALSE. Fix buffer overflow. 2007-01-04 Jie Zhang * elf-eh-frame.c (_bfd_elf_discard_section_eh_frame): Don't set SEC_EXCLUDE on zero size .eh_frame. For older changes see ChangeLog-2006 Local Variables: mode: change-log left-margin: 8 fill-column: 74 version-control: never End: Index: head/contrib/binutils/bfd/bfd-in2.h =================================================================== --- head/contrib/binutils/bfd/bfd-in2.h (revision 275717) +++ head/contrib/binutils/bfd/bfd-in2.h (revision 275718) @@ -1,5398 +1,5403 @@ /* DO NOT EDIT! -*- buffer-read-only: t -*- This file is automatically generated from "bfd-in.h", "init.c", "opncls.c", "libbfd.c", "bfdio.c", "bfdwin.c", "section.c", "archures.c", "reloc.c", "syms.c", "bfd.c", "archive.c", "corefile.c", "targets.c", "format.c", "linker.c" and "simple.c". Run "make headers" in your build bfd/ to regenerate. */ /* Main header file for the bfd library -- portable access to object files. Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. Contributed by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __BFD_H_SEEN__ #define __BFD_H_SEEN__ #ifdef __cplusplus extern "C" { #endif #include "ansidecl.h" #include "symcat.h" #if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE) #ifndef SABER /* This hack is to avoid a problem with some strict ANSI C preprocessors. The problem is, "32_" is not a valid preprocessing token, and we don't want extra underscores (e.g., "nlm_32_"). The XCONCAT2 macro will cause the inner CONCAT2 macros to be evaluated first, producing still-valid pp-tokens. Then the final concatenation can be done. */ #undef CONCAT4 #define CONCAT4(a,b,c,d) XCONCAT2(CONCAT2(a,b),CONCAT2(c,d)) #endif #endif /* This is a utility macro to handle the situation where the code wants to place a constant string into the code, followed by a comma and then the length of the string. Doing this by hand is error prone, so using this macro is safer. The macro will also safely handle the case where a NULL is passed as the arg. */ #define STRING_COMMA_LEN(STR) (STR), ((STR) ? sizeof (STR) - 1 : 0) /* Unfortunately it is not possible to use the STRING_COMMA_LEN macro to create the arguments to another macro, since the preprocessor will mis-count the number of arguments to the outer macro (by not evaluating STRING_COMMA_LEN and so missing the comma). This is a problem for example when trying to use STRING_COMMA_LEN to build the arguments to the strncmp() macro. Hence this alternative definition of strncmp is provided here. Note - these macros do NOT work if STR2 is not a constant string. */ #define CONST_STRNEQ(STR1,STR2) (strncmp ((STR1), (STR2), sizeof (STR2) - 1) == 0) /* strcpy() can have a similar problem, but since we know we are copying a constant string, we can use memcpy which will be faster since there is no need to check for a NUL byte inside STR. We can also save time if we do not need to copy the terminating NUL. */ #define LITMEMCPY(DEST,STR2) memcpy ((DEST), (STR2), sizeof (STR2) - 1) #define LITSTRCPY(DEST,STR2) memcpy ((DEST), (STR2), sizeof (STR2)) /* The word size used by BFD on the host. This may be 64 with a 32 bit target if the host is 64 bit, or if other 64 bit targets have been selected with --enable-targets, or if --enable-64-bit-bfd. */ #define BFD_ARCH_SIZE @wordsize@ /* The word size of the default bfd target. */ #define BFD_DEFAULT_TARGET_SIZE @bfd_default_target_size@ #define BFD_HOST_64BIT_LONG @BFD_HOST_64BIT_LONG@ #define BFD_HOST_LONG_LONG @BFD_HOST_LONG_LONG@ #if @BFD_HOST_64_BIT_DEFINED@ #define BFD_HOST_64_BIT @BFD_HOST_64_BIT@ #define BFD_HOST_U_64_BIT @BFD_HOST_U_64_BIT@ typedef BFD_HOST_64_BIT bfd_int64_t; typedef BFD_HOST_U_64_BIT bfd_uint64_t; #endif #if BFD_ARCH_SIZE >= 64 #define BFD64 #endif #ifndef INLINE #if __GNUC__ >= 2 #define INLINE __inline__ #else #define INLINE #endif #endif /* Forward declaration. */ typedef struct bfd bfd; /* Boolean type used in bfd. Too many systems define their own versions of "boolean" for us to safely typedef a "boolean" of our own. Using an enum for "bfd_boolean" has its own set of problems, with strange looking casts required to avoid warnings on some older compilers. Thus we just use an int. General rule: Functions which are bfd_boolean return TRUE on success and FALSE on failure (unless they're a predicate). */ typedef int bfd_boolean; #undef FALSE #undef TRUE #define FALSE 0 #define TRUE 1 #ifdef BFD64 #ifndef BFD_HOST_64_BIT #error No 64 bit integer type available #endif /* ! defined (BFD_HOST_64_BIT) */ typedef BFD_HOST_U_64_BIT bfd_vma; typedef BFD_HOST_64_BIT bfd_signed_vma; typedef BFD_HOST_U_64_BIT bfd_size_type; typedef BFD_HOST_U_64_BIT symvalue; #ifndef fprintf_vma #if BFD_HOST_64BIT_LONG #define sprintf_vma(s,x) sprintf (s, "%016lx", x) #define fprintf_vma(f,x) fprintf (f, "%016lx", x) #else #define _bfd_int64_low(x) ((unsigned long) (((x) & 0xffffffff))) #define _bfd_int64_high(x) ((unsigned long) (((x) >> 32) & 0xffffffff)) #define fprintf_vma(s,x) \ fprintf ((s), "%08lx%08lx", _bfd_int64_high (x), _bfd_int64_low (x)) #define sprintf_vma(s,x) \ sprintf ((s), "%08lx%08lx", _bfd_int64_high (x), _bfd_int64_low (x)) #endif #endif #else /* not BFD64 */ /* Represent a target address. Also used as a generic unsigned type which is guaranteed to be big enough to hold any arithmetic types we need to deal with. */ typedef unsigned long bfd_vma; /* A generic signed type which is guaranteed to be big enough to hold any arithmetic types we need to deal with. Can be assumed to be compatible with bfd_vma in the same way that signed and unsigned ints are compatible (as parameters, in assignment, etc). */ typedef long bfd_signed_vma; typedef unsigned long symvalue; typedef unsigned long bfd_size_type; /* Print a bfd_vma x on stream s. */ #define fprintf_vma(s,x) fprintf (s, "%08lx", x) #define sprintf_vma(s,x) sprintf (s, "%08lx", x) #endif /* not BFD64 */ #define HALF_BFD_SIZE_TYPE \ (((bfd_size_type) 1) << (8 * sizeof (bfd_size_type) / 2)) #ifndef BFD_HOST_64_BIT /* Fall back on a 32 bit type. The idea is to make these types always available for function return types, but in the case that BFD_HOST_64_BIT is undefined such a function should abort or otherwise signal an error. */ typedef bfd_signed_vma bfd_int64_t; typedef bfd_vma bfd_uint64_t; #endif /* An offset into a file. BFD always uses the largest possible offset based on the build time availability of fseek, fseeko, or fseeko64. */ typedef @bfd_file_ptr@ file_ptr; typedef unsigned @bfd_file_ptr@ ufile_ptr; extern void bfd_sprintf_vma (bfd *, char *, bfd_vma); extern void bfd_fprintf_vma (bfd *, void *, bfd_vma); #define printf_vma(x) fprintf_vma(stdout,x) #define bfd_printf_vma(abfd,x) bfd_fprintf_vma (abfd,stdout,x) typedef unsigned int flagword; /* 32 bits of flags */ typedef unsigned char bfd_byte; /* File formats. */ typedef enum bfd_format { bfd_unknown = 0, /* File format is unknown. */ bfd_object, /* Linker/assembler/compiler output. */ bfd_archive, /* Object archive file. */ bfd_core, /* Core dump. */ bfd_type_end /* Marks the end; don't use it! */ } bfd_format; /* Values that may appear in the flags field of a BFD. These also appear in the object_flags field of the bfd_target structure, where they indicate the set of flags used by that backend (not all flags are meaningful for all object file formats) (FIXME: at the moment, the object_flags values have mostly just been copied from backend to another, and are not necessarily correct). */ /* No flags. */ #define BFD_NO_FLAGS 0x00 /* BFD contains relocation entries. */ #define HAS_RELOC 0x01 /* BFD is directly executable. */ #define EXEC_P 0x02 /* BFD has line number information (basically used for F_LNNO in a COFF header). */ #define HAS_LINENO 0x04 /* BFD has debugging information. */ #define HAS_DEBUG 0x08 /* BFD has symbols. */ #define HAS_SYMS 0x10 /* BFD has local symbols (basically used for F_LSYMS in a COFF header). */ #define HAS_LOCALS 0x20 /* BFD is a dynamic object. */ #define DYNAMIC 0x40 /* Text section is write protected (if D_PAGED is not set, this is like an a.out NMAGIC file) (the linker sets this by default, but clears it for -r or -N). */ #define WP_TEXT 0x80 /* BFD is dynamically paged (this is like an a.out ZMAGIC file) (the linker sets this by default, but clears it for -r or -n or -N). */ #define D_PAGED 0x100 /* BFD is relaxable (this means that bfd_relax_section may be able to do something) (sometimes bfd_relax_section can do something even if this is not set). */ #define BFD_IS_RELAXABLE 0x200 /* This may be set before writing out a BFD to request using a traditional format. For example, this is used to request that when writing out an a.out object the symbols not be hashed to eliminate duplicates. */ #define BFD_TRADITIONAL_FORMAT 0x400 /* This flag indicates that the BFD contents are actually cached in memory. If this is set, iostream points to a bfd_in_memory struct. */ #define BFD_IN_MEMORY 0x800 /* The sections in this BFD specify a memory page. */ #define HAS_LOAD_PAGE 0x1000 /* This BFD has been created by the linker and doesn't correspond to any input file. */ #define BFD_LINKER_CREATED 0x2000 /* Symbols and relocation. */ /* A count of carsyms (canonical archive symbols). */ typedef unsigned long symindex; /* How to perform a relocation. */ typedef const struct reloc_howto_struct reloc_howto_type; #define BFD_NO_MORE_SYMBOLS ((symindex) ~0) /* General purpose part of a symbol X; target specific parts are in libcoff.h, libaout.h, etc. */ #define bfd_get_section(x) ((x)->section) #define bfd_get_output_section(x) ((x)->section->output_section) #define bfd_set_section(x,y) ((x)->section) = (y) #define bfd_asymbol_base(x) ((x)->section->vma) #define bfd_asymbol_value(x) (bfd_asymbol_base(x) + (x)->value) #define bfd_asymbol_name(x) ((x)->name) /*Perhaps future: #define bfd_asymbol_bfd(x) ((x)->section->owner)*/ #define bfd_asymbol_bfd(x) ((x)->the_bfd) #define bfd_asymbol_flavour(x) (bfd_asymbol_bfd(x)->xvec->flavour) /* A canonical archive symbol. */ /* This is a type pun with struct ranlib on purpose! */ typedef struct carsym { char *name; file_ptr file_offset; /* Look here to find the file. */ } carsym; /* To make these you call a carsymogen. */ /* Used in generating armaps (archive tables of contents). Perhaps just a forward definition would do? */ struct orl /* Output ranlib. */ { char **name; /* Symbol name. */ union { file_ptr pos; bfd *abfd; } u; /* bfd* or file position. */ int namidx; /* Index into string table. */ }; /* Linenumber stuff. */ typedef struct lineno_cache_entry { unsigned int line_number; /* Linenumber from start of function. */ union { struct bfd_symbol *sym; /* Function name. */ bfd_vma offset; /* Offset into section. */ } u; } alent; /* Object and core file sections. */ #define align_power(addr, align) \ (((addr) + ((bfd_vma) 1 << (align)) - 1) & ((bfd_vma) -1 << (align))) typedef struct bfd_section *sec_ptr; #define bfd_get_section_name(bfd, ptr) ((ptr)->name + 0) #define bfd_get_section_vma(bfd, ptr) ((ptr)->vma + 0) #define bfd_get_section_lma(bfd, ptr) ((ptr)->lma + 0) #define bfd_get_section_alignment(bfd, ptr) ((ptr)->alignment_power + 0) #define bfd_section_name(bfd, ptr) ((ptr)->name) #define bfd_section_size(bfd, ptr) ((ptr)->size) #define bfd_get_section_size(ptr) ((ptr)->size) #define bfd_section_vma(bfd, ptr) ((ptr)->vma) #define bfd_section_lma(bfd, ptr) ((ptr)->lma) #define bfd_section_alignment(bfd, ptr) ((ptr)->alignment_power) #define bfd_get_section_flags(bfd, ptr) ((ptr)->flags + 0) #define bfd_get_section_userdata(bfd, ptr) ((ptr)->userdata) #define bfd_is_com_section(ptr) (((ptr)->flags & SEC_IS_COMMON) != 0) #define bfd_set_section_vma(bfd, ptr, val) (((ptr)->vma = (ptr)->lma = (val)), ((ptr)->user_set_vma = TRUE), TRUE) #define bfd_set_section_alignment(bfd, ptr, val) (((ptr)->alignment_power = (val)),TRUE) #define bfd_set_section_userdata(bfd, ptr, val) (((ptr)->userdata = (val)),TRUE) /* Find the address one past the end of SEC. */ #define bfd_get_section_limit(bfd, sec) \ (((sec)->rawsize ? (sec)->rawsize : (sec)->size) \ / bfd_octets_per_byte (bfd)) /* Return TRUE if section has been discarded. */ #define elf_discarded_section(sec) \ (!bfd_is_abs_section (sec) \ && bfd_is_abs_section ((sec)->output_section) \ && (sec)->sec_info_type != ELF_INFO_TYPE_MERGE \ && (sec)->sec_info_type != ELF_INFO_TYPE_JUST_SYMS) /* Forward define. */ struct stat; typedef enum bfd_print_symbol { bfd_print_symbol_name, bfd_print_symbol_more, bfd_print_symbol_all } bfd_print_symbol_type; /* Information about a symbol that nm needs. */ typedef struct _symbol_info { symvalue value; char type; const char *name; /* Symbol name. */ unsigned char stab_type; /* Stab type. */ char stab_other; /* Stab other. */ short stab_desc; /* Stab desc. */ const char *stab_name; /* String for stab type. */ } symbol_info; /* Get the name of a stabs type code. */ extern const char *bfd_get_stab_name (int); /* Hash table routines. There is no way to free up a hash table. */ /* An element in the hash table. Most uses will actually use a larger structure, and an instance of this will be the first field. */ struct bfd_hash_entry { /* Next entry for this hash code. */ struct bfd_hash_entry *next; /* String being hashed. */ const char *string; /* Hash code. This is the full hash code, not the index into the table. */ unsigned long hash; }; /* A hash table. */ struct bfd_hash_table { /* The hash array. */ struct bfd_hash_entry **table; /* A function used to create new elements in the hash table. The first entry is itself a pointer to an element. When this function is first invoked, this pointer will be NULL. However, having the pointer permits a hierarchy of method functions to be built each of which calls the function in the superclass. Thus each function should be written to allocate a new block of memory only if the argument is NULL. */ struct bfd_hash_entry *(*newfunc) (struct bfd_hash_entry *, struct bfd_hash_table *, const char *); /* An objalloc for this hash table. This is a struct objalloc *, but we use void * to avoid requiring the inclusion of objalloc.h. */ void *memory; /* The number of slots in the hash table. */ unsigned int size; /* The number of entries in the hash table. */ unsigned int count; /* The size of elements. */ unsigned int entsize; /* If non-zero, don't grow the hash table. */ unsigned int frozen:1; }; /* Initialize a hash table. */ 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 *), unsigned int); /* Initialize a hash table specifying a size. */ extern bfd_boolean bfd_hash_table_init_n (struct bfd_hash_table *, struct bfd_hash_entry *(*) (struct bfd_hash_entry *, struct bfd_hash_table *, const char *), unsigned int, unsigned int); /* Free up a hash table. */ extern void bfd_hash_table_free (struct bfd_hash_table *); /* Look up a string in a hash table. If CREATE is TRUE, a new entry will be created for this string if one does not already exist. The COPY argument must be TRUE if this routine should copy the string into newly allocated memory when adding an entry. */ extern struct bfd_hash_entry *bfd_hash_lookup (struct bfd_hash_table *, const char *, bfd_boolean create, bfd_boolean copy); /* Replace an entry in a hash table. */ extern void bfd_hash_replace (struct bfd_hash_table *, struct bfd_hash_entry *old, struct bfd_hash_entry *nw); /* Base method for creating a hash table entry. */ extern struct bfd_hash_entry *bfd_hash_newfunc (struct bfd_hash_entry *, struct bfd_hash_table *, const char *); /* Grab some space for a hash table entry. */ extern void *bfd_hash_allocate (struct bfd_hash_table *, unsigned int); /* Traverse a hash table in a random order, calling a function on each element. If the function returns FALSE, the traversal stops. The INFO argument is passed to the function. */ extern void bfd_hash_traverse (struct bfd_hash_table *, bfd_boolean (*) (struct bfd_hash_entry *, void *), void *info); /* Allows the default size of a hash table to be configured. New hash tables allocated using bfd_hash_table_init will be created with this size. */ extern void bfd_hash_set_default_size (bfd_size_type); /* This structure is used to keep track of stabs in sections information while linking. */ struct stab_info { /* A hash table used to hold stabs strings. */ struct bfd_strtab_hash *strings; /* The header file hash table. */ struct bfd_hash_table includes; /* The first .stabstr section. */ struct bfd_section *stabstr; }; #define COFF_SWAP_TABLE (void *) &bfd_coff_std_swap_table /* User program access to BFD facilities. */ /* Direct I/O routines, for programs which know more about the object file than BFD does. Use higher level routines if possible. */ extern bfd_size_type bfd_bread (void *, bfd_size_type, bfd *); extern bfd_size_type bfd_bwrite (const void *, bfd_size_type, bfd *); extern int bfd_seek (bfd *, file_ptr, int); extern file_ptr bfd_tell (bfd *); extern int bfd_flush (bfd *); extern int bfd_stat (bfd *, struct stat *); /* Deprecated old routines. */ #if __GNUC__ #define bfd_read(BUF, ELTSIZE, NITEMS, ABFD) \ (warn_deprecated ("bfd_read", __FILE__, __LINE__, __FUNCTION__), \ bfd_bread ((BUF), (ELTSIZE) * (NITEMS), (ABFD))) #define bfd_write(BUF, ELTSIZE, NITEMS, ABFD) \ (warn_deprecated ("bfd_write", __FILE__, __LINE__, __FUNCTION__), \ bfd_bwrite ((BUF), (ELTSIZE) * (NITEMS), (ABFD))) #else #define bfd_read(BUF, ELTSIZE, NITEMS, ABFD) \ (warn_deprecated ("bfd_read", (const char *) 0, 0, (const char *) 0), \ bfd_bread ((BUF), (ELTSIZE) * (NITEMS), (ABFD))) #define bfd_write(BUF, ELTSIZE, NITEMS, ABFD) \ (warn_deprecated ("bfd_write", (const char *) 0, 0, (const char *) 0),\ bfd_bwrite ((BUF), (ELTSIZE) * (NITEMS), (ABFD))) #endif extern void warn_deprecated (const char *, const char *, int, const char *); /* Cast from const char * to char * so that caller can assign to a char * without a warning. */ #define bfd_get_filename(abfd) ((char *) (abfd)->filename) #define bfd_get_cacheable(abfd) ((abfd)->cacheable) #define bfd_get_format(abfd) ((abfd)->format) #define bfd_get_target(abfd) ((abfd)->xvec->name) #define bfd_get_flavour(abfd) ((abfd)->xvec->flavour) #define bfd_family_coff(abfd) \ (bfd_get_flavour (abfd) == bfd_target_coff_flavour || \ bfd_get_flavour (abfd) == bfd_target_xcoff_flavour) #define bfd_big_endian(abfd) ((abfd)->xvec->byteorder == BFD_ENDIAN_BIG) #define bfd_little_endian(abfd) ((abfd)->xvec->byteorder == BFD_ENDIAN_LITTLE) #define bfd_header_big_endian(abfd) \ ((abfd)->xvec->header_byteorder == BFD_ENDIAN_BIG) #define bfd_header_little_endian(abfd) \ ((abfd)->xvec->header_byteorder == BFD_ENDIAN_LITTLE) #define bfd_get_file_flags(abfd) ((abfd)->flags) #define bfd_applicable_file_flags(abfd) ((abfd)->xvec->object_flags) #define bfd_applicable_section_flags(abfd) ((abfd)->xvec->section_flags) #define bfd_my_archive(abfd) ((abfd)->my_archive) #define bfd_has_map(abfd) ((abfd)->has_armap) #define bfd_valid_reloc_types(abfd) ((abfd)->xvec->valid_reloc_types) #define bfd_usrdata(abfd) ((abfd)->usrdata) #define bfd_get_start_address(abfd) ((abfd)->start_address) #define bfd_get_symcount(abfd) ((abfd)->symcount) #define bfd_get_outsymbols(abfd) ((abfd)->outsymbols) #define bfd_count_sections(abfd) ((abfd)->section_count) #define bfd_get_dynamic_symcount(abfd) ((abfd)->dynsymcount) #define bfd_get_symbol_leading_char(abfd) ((abfd)->xvec->symbol_leading_char) #define bfd_set_cacheable(abfd,bool) (((abfd)->cacheable = bool), TRUE) extern bfd_boolean bfd_cache_close (bfd *abfd); /* NB: This declaration should match the autogenerated one in libbfd.h. */ extern bfd_boolean bfd_cache_close_all (void); extern bfd_boolean bfd_record_phdr (bfd *, unsigned long, bfd_boolean, flagword, bfd_boolean, bfd_vma, bfd_boolean, bfd_boolean, unsigned int, struct bfd_section **); /* Byte swapping routines. */ bfd_uint64_t bfd_getb64 (const void *); bfd_uint64_t bfd_getl64 (const void *); bfd_int64_t bfd_getb_signed_64 (const void *); bfd_int64_t bfd_getl_signed_64 (const void *); bfd_vma bfd_getb32 (const void *); bfd_vma bfd_getl32 (const void *); bfd_signed_vma bfd_getb_signed_32 (const void *); bfd_signed_vma bfd_getl_signed_32 (const void *); bfd_vma bfd_getb16 (const void *); bfd_vma bfd_getl16 (const void *); bfd_signed_vma bfd_getb_signed_16 (const void *); bfd_signed_vma bfd_getl_signed_16 (const void *); void bfd_putb64 (bfd_uint64_t, void *); void bfd_putl64 (bfd_uint64_t, void *); void bfd_putb32 (bfd_vma, void *); void bfd_putl32 (bfd_vma, void *); void bfd_putb16 (bfd_vma, void *); void bfd_putl16 (bfd_vma, void *); /* Byte swapping routines which take size and endiannes as arguments. */ bfd_uint64_t bfd_get_bits (const void *, int, bfd_boolean); void bfd_put_bits (bfd_uint64_t, void *, int, bfd_boolean); extern bfd_boolean bfd_section_already_linked_table_init (void); extern void bfd_section_already_linked_table_free (void); /* Externally visible ECOFF routines. */ #if defined(__STDC__) || defined(ALMOST_STDC) struct ecoff_debug_info; struct ecoff_debug_swap; struct ecoff_extr; struct bfd_symbol; struct bfd_link_info; struct bfd_link_hash_entry; struct bfd_elf_version_tree; #endif extern bfd_vma bfd_ecoff_get_gp_value (bfd * abfd); extern bfd_boolean bfd_ecoff_set_gp_value (bfd *abfd, bfd_vma gp_value); extern bfd_boolean bfd_ecoff_set_regmasks (bfd *abfd, unsigned long gprmask, unsigned long fprmask, unsigned long *cprmask); extern void *bfd_ecoff_debug_init (bfd *output_bfd, struct ecoff_debug_info *output_debug, const struct ecoff_debug_swap *output_swap, struct bfd_link_info *); extern void bfd_ecoff_debug_free (void *handle, bfd *output_bfd, struct ecoff_debug_info *output_debug, const struct ecoff_debug_swap *output_swap, struct bfd_link_info *); extern bfd_boolean bfd_ecoff_debug_accumulate (void *handle, bfd *output_bfd, struct ecoff_debug_info *output_debug, const struct ecoff_debug_swap *output_swap, bfd *input_bfd, struct ecoff_debug_info *input_debug, const struct ecoff_debug_swap *input_swap, struct bfd_link_info *); extern bfd_boolean bfd_ecoff_debug_accumulate_other (void *handle, bfd *output_bfd, struct ecoff_debug_info *output_debug, const struct ecoff_debug_swap *output_swap, bfd *input_bfd, struct bfd_link_info *); extern bfd_boolean bfd_ecoff_debug_externals (bfd *abfd, struct ecoff_debug_info *debug, const struct ecoff_debug_swap *swap, bfd_boolean relocatable, bfd_boolean (*get_extr) (struct bfd_symbol *, struct ecoff_extr *), void (*set_index) (struct bfd_symbol *, bfd_size_type)); extern bfd_boolean bfd_ecoff_debug_one_external (bfd *abfd, struct ecoff_debug_info *debug, const struct ecoff_debug_swap *swap, const char *name, struct ecoff_extr *esym); extern bfd_size_type bfd_ecoff_debug_size (bfd *abfd, struct ecoff_debug_info *debug, const struct ecoff_debug_swap *swap); extern bfd_boolean bfd_ecoff_write_debug (bfd *abfd, struct ecoff_debug_info *debug, const struct ecoff_debug_swap *swap, file_ptr where); extern bfd_boolean bfd_ecoff_write_accumulated_debug (void *handle, bfd *abfd, struct ecoff_debug_info *debug, const struct ecoff_debug_swap *swap, struct bfd_link_info *info, file_ptr where); /* Externally visible ELF routines. */ struct bfd_link_needed_list { struct bfd_link_needed_list *next; bfd *by; const char *name; }; enum dynamic_lib_link_class { DYN_NORMAL = 0, DYN_AS_NEEDED = 1, DYN_DT_NEEDED = 2, DYN_NO_ADD_NEEDED = 4, DYN_NO_NEEDED = 8 }; enum notice_asneeded_action { notice_as_needed, notice_not_needed, notice_needed }; extern bfd_boolean bfd_elf_record_link_assignment (bfd *, struct bfd_link_info *, const char *, bfd_boolean, bfd_boolean); extern struct bfd_link_needed_list *bfd_elf_get_needed_list (bfd *, struct bfd_link_info *); extern bfd_boolean bfd_elf_get_bfd_needed_list (bfd *, struct bfd_link_needed_list **); extern bfd_boolean bfd_elf_size_dynamic_sections (bfd *, const char *, const char *, const char *, const char * const *, struct bfd_link_info *, struct bfd_section **, struct bfd_elf_version_tree *); extern bfd_boolean bfd_elf_size_dynsym_hash_dynstr (bfd *, struct bfd_link_info *); extern void bfd_elf_set_dt_needed_name (bfd *, const char *); extern const char *bfd_elf_get_dt_soname (bfd *); extern void bfd_elf_set_dyn_lib_class (bfd *, enum dynamic_lib_link_class); extern int bfd_elf_get_dyn_lib_class (bfd *); extern struct bfd_link_needed_list *bfd_elf_get_runpath_list (bfd *, struct bfd_link_info *); extern bfd_boolean bfd_elf_discard_info (bfd *, struct bfd_link_info *); extern unsigned int _bfd_elf_default_action_discarded (struct bfd_section *); /* Return an upper bound on the number of bytes required to store a copy of ABFD's program header table entries. Return -1 if an error occurs; bfd_get_error will return an appropriate code. */ extern long bfd_get_elf_phdr_upper_bound (bfd *abfd); /* Copy ABFD's program header table entries to *PHDRS. The entries will be stored as an array of Elf_Internal_Phdr structures, as defined in include/elf/internal.h. To find out how large the buffer needs to be, call bfd_get_elf_phdr_upper_bound. Return the number of program header table entries read, or -1 if an error occurs; bfd_get_error will return an appropriate code. */ extern int bfd_get_elf_phdrs (bfd *abfd, void *phdrs); /* Create a new BFD as if by bfd_openr. Rather than opening a file, reconstruct an ELF file by reading the segments out of remote memory based on the ELF file header at EHDR_VMA and the ELF program headers it points to. If not null, *LOADBASEP is filled in with the difference between the VMAs from which the segments were read, and the VMAs the file headers (and hence BFD's idea of each section's VMA) put them at. The function TARGET_READ_MEMORY is called to copy LEN bytes from the remote memory at target address VMA into the local buffer at MYADDR; it should return zero on success or an `errno' code on failure. TEMPL must be a BFD for an ELF target with the word size and byte order found in the remote memory. */ extern bfd *bfd_elf_bfd_from_remote_memory (bfd *templ, bfd_vma ehdr_vma, bfd_vma *loadbasep, int (*target_read_memory) (bfd_vma vma, bfd_byte *myaddr, int len)); /* Return the arch_size field of an elf bfd, or -1 if not elf. */ extern int bfd_get_arch_size (bfd *); /* Return TRUE if address "naturally" sign extends, or -1 if not elf. */ extern int bfd_get_sign_extend_vma (bfd *); extern struct bfd_section *_bfd_elf_tls_setup (bfd *, struct bfd_link_info *); extern void _bfd_fix_excluded_sec_syms (bfd *, struct bfd_link_info *); extern unsigned bfd_m68k_mach_to_features (int); extern int bfd_m68k_features_to_mach (unsigned); extern bfd_boolean bfd_m68k_elf32_create_embedded_relocs (bfd *, struct bfd_link_info *, struct bfd_section *, struct bfd_section *, char **); extern bfd_boolean bfd_bfin_elf32_create_embedded_relocs (bfd *, struct bfd_link_info *, struct bfd_section *, struct bfd_section *, char **); /* SunOS shared library support routines for the linker. */ extern struct bfd_link_needed_list *bfd_sunos_get_needed_list (bfd *, struct bfd_link_info *); extern bfd_boolean bfd_sunos_record_link_assignment (bfd *, struct bfd_link_info *, const char *); extern bfd_boolean bfd_sunos_size_dynamic_sections (bfd *, struct bfd_link_info *, struct bfd_section **, struct bfd_section **, struct bfd_section **); /* Linux shared library support routines for the linker. */ extern bfd_boolean bfd_i386linux_size_dynamic_sections (bfd *, struct bfd_link_info *); extern bfd_boolean bfd_m68klinux_size_dynamic_sections (bfd *, struct bfd_link_info *); extern bfd_boolean bfd_sparclinux_size_dynamic_sections (bfd *, struct bfd_link_info *); /* mmap hacks */ struct _bfd_window_internal; typedef struct _bfd_window_internal bfd_window_internal; typedef struct _bfd_window { /* What the user asked for. */ void *data; bfd_size_type size; /* The actual window used by BFD. Small user-requested read-only regions sharing a page may share a single window into the object file. Read-write versions shouldn't until I've fixed things to keep track of which portions have been claimed by the application; don't want to give the same region back when the application wants two writable copies! */ struct _bfd_window_internal *i; } bfd_window; extern void bfd_init_window (bfd_window *); extern void bfd_free_window (bfd_window *); extern bfd_boolean bfd_get_file_window (bfd *, file_ptr, bfd_size_type, bfd_window *, bfd_boolean); /* XCOFF support routines for the linker. */ extern bfd_boolean bfd_xcoff_link_record_set (bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *, bfd_size_type); extern bfd_boolean bfd_xcoff_import_symbol (bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *, bfd_vma, const char *, const char *, const char *, unsigned int); extern bfd_boolean bfd_xcoff_export_symbol (bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *); extern bfd_boolean bfd_xcoff_link_count_reloc (bfd *, struct bfd_link_info *, const char *); extern bfd_boolean bfd_xcoff_record_link_assignment (bfd *, struct bfd_link_info *, const char *); extern bfd_boolean bfd_xcoff_size_dynamic_sections (bfd *, struct bfd_link_info *, const char *, const char *, unsigned long, unsigned long, unsigned long, bfd_boolean, int, bfd_boolean, bfd_boolean, struct bfd_section **, bfd_boolean); extern bfd_boolean bfd_xcoff_link_generate_rtinit (bfd *, const char *, const char *, bfd_boolean); /* XCOFF support routines for ar. */ extern bfd_boolean bfd_xcoff_ar_archive_set_magic (bfd *, char *); /* Externally visible COFF routines. */ #if defined(__STDC__) || defined(ALMOST_STDC) struct internal_syment; union internal_auxent; #endif extern bfd_boolean bfd_coff_get_syment (bfd *, struct bfd_symbol *, struct internal_syment *); extern bfd_boolean bfd_coff_get_auxent (bfd *, struct bfd_symbol *, int, union internal_auxent *); extern bfd_boolean bfd_coff_set_symbol_class (bfd *, struct bfd_symbol *, unsigned int); extern bfd_boolean bfd_m68k_coff_create_embedded_relocs (bfd *, struct bfd_link_info *, struct bfd_section *, struct bfd_section *, char **); /* ARM VFP11 erratum workaround support. */ typedef enum { BFD_ARM_VFP11_FIX_DEFAULT, BFD_ARM_VFP11_FIX_NONE, BFD_ARM_VFP11_FIX_SCALAR, BFD_ARM_VFP11_FIX_VECTOR } bfd_arm_vfp11_fix; extern void bfd_elf32_arm_init_maps (bfd *); extern void bfd_elf32_arm_set_vfp11_fix (bfd *, struct bfd_link_info *); extern bfd_boolean bfd_elf32_arm_vfp11_erratum_scan (bfd *, struct bfd_link_info *); extern void bfd_elf32_arm_vfp11_fix_veneer_locations (bfd *, struct bfd_link_info *); /* ARM Interworking support. Called from linker. */ extern bfd_boolean bfd_arm_allocate_interworking_sections (struct bfd_link_info *); extern bfd_boolean bfd_arm_process_before_allocation (bfd *, struct bfd_link_info *, int); extern bfd_boolean bfd_arm_get_bfd_for_interworking (bfd *, struct bfd_link_info *); /* PE ARM Interworking support. Called from linker. */ extern bfd_boolean bfd_arm_pe_allocate_interworking_sections (struct bfd_link_info *); extern bfd_boolean bfd_arm_pe_process_before_allocation (bfd *, struct bfd_link_info *, int); extern bfd_boolean bfd_arm_pe_get_bfd_for_interworking (bfd *, struct bfd_link_info *); /* ELF ARM Interworking support. Called from linker. */ extern bfd_boolean bfd_elf32_arm_allocate_interworking_sections (struct bfd_link_info *); extern bfd_boolean bfd_elf32_arm_process_before_allocation (bfd *, struct bfd_link_info *); void bfd_elf32_arm_set_target_relocs (bfd *, struct bfd_link_info *, int, char *, int, int, bfd_arm_vfp11_fix, int, int); extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking (bfd *, struct bfd_link_info *); extern bfd_boolean bfd_elf32_arm_add_glue_sections_to_bfd (bfd *, struct bfd_link_info *); /* ELF ARM mapping symbol support */ #define BFD_ARM_SPECIAL_SYM_TYPE_MAP (1 << 0) #define BFD_ARM_SPECIAL_SYM_TYPE_TAG (1 << 1) #define BFD_ARM_SPECIAL_SYM_TYPE_OTHER (1 << 2) #define BFD_ARM_SPECIAL_SYM_TYPE_ANY (~0) extern bfd_boolean bfd_is_arm_special_symbol_name (const char * name, int type); extern void bfd_elf32_arm_set_byteswap_code (struct bfd_link_info *, int); /* ARM Note section processing. */ extern bfd_boolean bfd_arm_merge_machines (bfd *, bfd *); extern bfd_boolean bfd_arm_update_notes (bfd *, const char *); extern unsigned int bfd_arm_get_mach_from_notes (bfd *, const char *); /* TI COFF load page support. */ extern void bfd_ticoff_set_section_load_page (struct bfd_section *, int); extern int bfd_ticoff_get_section_load_page (struct bfd_section *); /* H8/300 functions. */ extern bfd_vma bfd_h8300_pad_address (bfd *, bfd_vma); /* IA64 Itanium code generation. Called from linker. */ extern void bfd_elf32_ia64_after_parse (int); extern void bfd_elf64_ia64_after_parse (int); /* This structure is used for a comdat section, as in PE. A comdat section is associated with a particular symbol. When the linker sees a comdat section, it keeps only one of the sections with a given name and associated with a given symbol. */ struct coff_comdat_info { /* The name of the symbol associated with a comdat section. */ const char *name; /* The local symbol table index of the symbol associated with a comdat section. This is only meaningful to the object file format specific code; it is not an index into the list returned by bfd_canonicalize_symtab. */ long symbol; }; extern struct coff_comdat_info *bfd_coff_get_comdat_section (bfd *, struct bfd_section *); /* Extracted from init.c. */ void bfd_init (void); /* Extracted from opncls.c. */ bfd *bfd_fopen (const char *filename, const char *target, const char *mode, int fd); bfd *bfd_openr (const char *filename, const char *target); bfd *bfd_fdopenr (const char *filename, const char *target, int fd); bfd *bfd_openstreamr (const char *, const char *, void *); bfd *bfd_openr_iovec (const char *filename, const char *target, void *(*open) (struct bfd *nbfd, void *open_closure), void *open_closure, file_ptr (*pread) (struct bfd *nbfd, void *stream, void *buf, file_ptr nbytes, file_ptr offset), int (*close) (struct bfd *nbfd, void *stream), int (*stat) (struct bfd *abfd, void *stream, struct stat *sb)); bfd *bfd_openw (const char *filename, const char *target); bfd_boolean bfd_close (bfd *abfd); bfd_boolean bfd_close_all_done (bfd *); bfd *bfd_create (const char *filename, bfd *templ); bfd_boolean bfd_make_writable (bfd *abfd); bfd_boolean bfd_make_readable (bfd *abfd); unsigned long bfd_calc_gnu_debuglink_crc32 (unsigned long crc, const unsigned char *buf, bfd_size_type len); char *bfd_follow_gnu_debuglink (bfd *abfd, const char *dir); struct bfd_section *bfd_create_gnu_debuglink_section (bfd *abfd, const char *filename); bfd_boolean bfd_fill_in_gnu_debuglink_section (bfd *abfd, struct bfd_section *sect, const char *filename); /* Extracted from libbfd.c. */ /* Byte swapping macros for user section data. */ #define bfd_put_8(abfd, val, ptr) \ ((void) (*((unsigned char *) (ptr)) = (val) & 0xff)) #define bfd_put_signed_8 \ bfd_put_8 #define bfd_get_8(abfd, ptr) \ (*(unsigned char *) (ptr) & 0xff) #define bfd_get_signed_8(abfd, ptr) \ (((*(unsigned char *) (ptr) & 0xff) ^ 0x80) - 0x80) #define bfd_put_16(abfd, val, ptr) \ BFD_SEND (abfd, bfd_putx16, ((val),(ptr))) #define bfd_put_signed_16 \ bfd_put_16 #define bfd_get_16(abfd, ptr) \ BFD_SEND (abfd, bfd_getx16, (ptr)) #define bfd_get_signed_16(abfd, ptr) \ BFD_SEND (abfd, bfd_getx_signed_16, (ptr)) #define bfd_put_32(abfd, val, ptr) \ BFD_SEND (abfd, bfd_putx32, ((val),(ptr))) #define bfd_put_signed_32 \ bfd_put_32 #define bfd_get_32(abfd, ptr) \ BFD_SEND (abfd, bfd_getx32, (ptr)) #define bfd_get_signed_32(abfd, ptr) \ BFD_SEND (abfd, bfd_getx_signed_32, (ptr)) #define bfd_put_64(abfd, val, ptr) \ BFD_SEND (abfd, bfd_putx64, ((val), (ptr))) #define bfd_put_signed_64 \ bfd_put_64 #define bfd_get_64(abfd, ptr) \ BFD_SEND (abfd, bfd_getx64, (ptr)) #define bfd_get_signed_64(abfd, ptr) \ BFD_SEND (abfd, bfd_getx_signed_64, (ptr)) #define bfd_get(bits, abfd, ptr) \ ((bits) == 8 ? (bfd_vma) bfd_get_8 (abfd, ptr) \ : (bits) == 16 ? bfd_get_16 (abfd, ptr) \ : (bits) == 32 ? bfd_get_32 (abfd, ptr) \ : (bits) == 64 ? bfd_get_64 (abfd, ptr) \ : (abort (), (bfd_vma) - 1)) #define bfd_put(bits, abfd, val, ptr) \ ((bits) == 8 ? bfd_put_8 (abfd, val, ptr) \ : (bits) == 16 ? bfd_put_16 (abfd, val, ptr) \ : (bits) == 32 ? bfd_put_32 (abfd, val, ptr) \ : (bits) == 64 ? bfd_put_64 (abfd, val, ptr) \ : (abort (), (void) 0)) /* Byte swapping macros for file header data. */ #define bfd_h_put_8(abfd, val, ptr) \ bfd_put_8 (abfd, val, ptr) #define bfd_h_put_signed_8(abfd, val, ptr) \ bfd_put_8 (abfd, val, ptr) #define bfd_h_get_8(abfd, ptr) \ bfd_get_8 (abfd, ptr) #define bfd_h_get_signed_8(abfd, ptr) \ bfd_get_signed_8 (abfd, ptr) #define bfd_h_put_16(abfd, val, ptr) \ BFD_SEND (abfd, bfd_h_putx16, (val, ptr)) #define bfd_h_put_signed_16 \ bfd_h_put_16 #define bfd_h_get_16(abfd, ptr) \ BFD_SEND (abfd, bfd_h_getx16, (ptr)) #define bfd_h_get_signed_16(abfd, ptr) \ BFD_SEND (abfd, bfd_h_getx_signed_16, (ptr)) #define bfd_h_put_32(abfd, val, ptr) \ BFD_SEND (abfd, bfd_h_putx32, (val, ptr)) #define bfd_h_put_signed_32 \ bfd_h_put_32 #define bfd_h_get_32(abfd, ptr) \ BFD_SEND (abfd, bfd_h_getx32, (ptr)) #define bfd_h_get_signed_32(abfd, ptr) \ BFD_SEND (abfd, bfd_h_getx_signed_32, (ptr)) #define bfd_h_put_64(abfd, val, ptr) \ BFD_SEND (abfd, bfd_h_putx64, (val, ptr)) #define bfd_h_put_signed_64 \ bfd_h_put_64 #define bfd_h_get_64(abfd, ptr) \ BFD_SEND (abfd, bfd_h_getx64, (ptr)) #define bfd_h_get_signed_64(abfd, ptr) \ BFD_SEND (abfd, bfd_h_getx_signed_64, (ptr)) /* Aliases for the above, which should eventually go away. */ #define H_PUT_64 bfd_h_put_64 #define H_PUT_32 bfd_h_put_32 #define H_PUT_16 bfd_h_put_16 #define H_PUT_8 bfd_h_put_8 #define H_PUT_S64 bfd_h_put_signed_64 #define H_PUT_S32 bfd_h_put_signed_32 #define H_PUT_S16 bfd_h_put_signed_16 #define H_PUT_S8 bfd_h_put_signed_8 #define H_GET_64 bfd_h_get_64 #define H_GET_32 bfd_h_get_32 #define H_GET_16 bfd_h_get_16 #define H_GET_8 bfd_h_get_8 #define H_GET_S64 bfd_h_get_signed_64 #define H_GET_S32 bfd_h_get_signed_32 #define H_GET_S16 bfd_h_get_signed_16 #define H_GET_S8 bfd_h_get_signed_8 /* Extracted from bfdio.c. */ long bfd_get_mtime (bfd *abfd); file_ptr bfd_get_size (bfd *abfd); /* Extracted from bfdwin.c. */ /* Extracted from section.c. */ typedef struct bfd_section { /* The name of the section; the name isn't a copy, the pointer is the same as that passed to bfd_make_section. */ const char *name; /* A unique sequence number. */ int id; /* Which section in the bfd; 0..n-1 as sections are created in a bfd. */ int index; /* The next section in the list belonging to the BFD, or NULL. */ struct bfd_section *next; /* The previous section in the list belonging to the BFD, or NULL. */ struct bfd_section *prev; /* The field flags contains attributes of the section. Some flags are read in from the object file, and some are synthesized from other information. */ flagword flags; #define SEC_NO_FLAGS 0x000 /* Tells the OS to allocate space for this section when loading. This is clear for a section containing debug information only. */ #define SEC_ALLOC 0x001 /* Tells the OS to load the section from the file when loading. This is clear for a .bss section. */ #define SEC_LOAD 0x002 /* The section contains data still to be relocated, so there is some relocation information too. */ #define SEC_RELOC 0x004 /* A signal to the OS that the section contains read only data. */ #define SEC_READONLY 0x008 /* The section contains code only. */ #define SEC_CODE 0x010 /* The section contains data only. */ #define SEC_DATA 0x020 /* The section will reside in ROM. */ #define SEC_ROM 0x040 /* The section contains constructor information. This section type is used by the linker to create lists of constructors and destructors used by <>. When a back end sees a symbol which should be used in a constructor list, it creates a new section for the type of name (e.g., <<__CTOR_LIST__>>), attaches the symbol to it, and builds a relocation. To build the lists of constructors, all the linker has to do is catenate all the sections called <<__CTOR_LIST__>> and relocate the data contained within - exactly the operations it would peform on standard data. */ #define SEC_CONSTRUCTOR 0x080 /* The section has contents - a data section could be <> | <>; a debug section could be <> */ #define SEC_HAS_CONTENTS 0x100 /* An instruction to the linker to not output the section even if it has information which would normally be written. */ #define SEC_NEVER_LOAD 0x200 /* The section contains thread local data. */ #define SEC_THREAD_LOCAL 0x400 /* The section has GOT references. This flag is only for the linker, and is currently only used by the elf32-hppa back end. It will be set if global offset table references were detected in this section, which indicate to the linker that the section contains PIC code, and must be handled specially when doing a static link. */ #define SEC_HAS_GOT_REF 0x800 /* The section contains common symbols (symbols may be defined multiple times, the value of a symbol is the amount of space it requires, and the largest symbol value is the one used). Most targets have exactly one of these (which we translate to bfd_com_section_ptr), but ECOFF has two. */ #define SEC_IS_COMMON 0x1000 /* The section contains only debugging information. For example, this is set for ELF .debug and .stab sections. strip tests this flag to see if a section can be discarded. */ #define SEC_DEBUGGING 0x2000 /* The contents of this section are held in memory pointed to by the contents field. This is checked by bfd_get_section_contents, and the data is retrieved from memory if appropriate. */ #define SEC_IN_MEMORY 0x4000 /* The contents of this section are to be excluded by the linker for executable and shared objects unless those objects are to be further relocated. */ #define SEC_EXCLUDE 0x8000 /* The contents of this section are to be sorted based on the sum of the symbol and addend values specified by the associated relocation entries. Entries without associated relocation entries will be appended to the end of the section in an unspecified order. */ #define SEC_SORT_ENTRIES 0x10000 /* When linking, duplicate sections of the same name should be discarded, rather than being combined into a single section as is usually done. This is similar to how common symbols are handled. See SEC_LINK_DUPLICATES below. */ #define SEC_LINK_ONCE 0x20000 /* If SEC_LINK_ONCE is set, this bitfield describes how the linker should handle duplicate sections. */ #define SEC_LINK_DUPLICATES 0x40000 /* This value for SEC_LINK_DUPLICATES means that duplicate sections with the same name should simply be discarded. */ #define SEC_LINK_DUPLICATES_DISCARD 0x0 /* This value for SEC_LINK_DUPLICATES means that the linker should warn if there are any duplicate sections, although it should still only link one copy. */ #define SEC_LINK_DUPLICATES_ONE_ONLY 0x80000 /* This value for SEC_LINK_DUPLICATES means that the linker should warn if any duplicate sections are a different size. */ #define SEC_LINK_DUPLICATES_SAME_SIZE 0x100000 /* This value for SEC_LINK_DUPLICATES means that the linker should warn if any duplicate sections contain different contents. */ #define SEC_LINK_DUPLICATES_SAME_CONTENTS \ (SEC_LINK_DUPLICATES_ONE_ONLY | SEC_LINK_DUPLICATES_SAME_SIZE) /* This section was created by the linker as part of dynamic relocation or other arcane processing. It is skipped when going through the first-pass output, trusting that someone else up the line will take care of it later. */ #define SEC_LINKER_CREATED 0x200000 /* This section should not be subject to garbage collection. Also set to inform the linker that this section should not be listed in the link map as discarded. */ #define SEC_KEEP 0x400000 /* This section contains "short" data, and should be placed "near" the GP. */ #define SEC_SMALL_DATA 0x800000 /* Attempt to merge identical entities in the section. Entity size is given in the entsize field. */ #define SEC_MERGE 0x1000000 /* If given with SEC_MERGE, entities to merge are zero terminated strings where entsize specifies character size instead of fixed size entries. */ #define SEC_STRINGS 0x2000000 /* This section contains data about section groups. */ #define SEC_GROUP 0x4000000 /* The section is a COFF shared library section. This flag is only for the linker. If this type of section appears in the input file, the linker must copy it to the output file without changing the vma or size. FIXME: Although this was originally intended to be general, it really is COFF specific (and the flag was renamed to indicate this). It might be cleaner to have some more general mechanism to allow the back end to control what the linker does with sections. */ #define SEC_COFF_SHARED_LIBRARY 0x10000000 /* This section contains data which may be shared with other executables or shared objects. This is for COFF only. */ #define SEC_COFF_SHARED 0x20000000 /* When a section with this flag is being linked, then if the size of the input section is less than a page, it should not cross a page boundary. If the size of the input section is one page or more, it should be aligned on a page boundary. This is for TI TMS320C54X only. */ #define SEC_TIC54X_BLOCK 0x40000000 /* Conditionally link this section; do not link if there are no references found to any symbol in the section. This is for TI TMS320C54X only. */ #define SEC_TIC54X_CLINK 0x80000000 /* End of section flags. */ /* Some internal packed boolean fields. */ /* See the vma field. */ unsigned int user_set_vma : 1; /* A mark flag used by some of the linker backends. */ unsigned int linker_mark : 1; /* Another mark flag used by some of the linker backends. Set for output sections that have an input section. */ unsigned int linker_has_input : 1; /* Mark flags used by some linker backends for garbage collection. */ unsigned int gc_mark : 1; unsigned int gc_mark_from_eh : 1; /* The following flags are used by the ELF linker. */ /* Mark sections which have been allocated to segments. */ unsigned int segment_mark : 1; /* Type of sec_info information. */ unsigned int sec_info_type:3; #define ELF_INFO_TYPE_NONE 0 #define ELF_INFO_TYPE_STABS 1 #define ELF_INFO_TYPE_MERGE 2 #define ELF_INFO_TYPE_EH_FRAME 3 #define ELF_INFO_TYPE_JUST_SYMS 4 /* Nonzero if this section uses RELA relocations, rather than REL. */ unsigned int use_rela_p:1; /* Bits used by various backends. The generic code doesn't touch these fields. */ /* Nonzero if this section has TLS related relocations. */ unsigned int has_tls_reloc:1; + /* Nonzero if this section has a call to __tls_get_addr. */ + unsigned int has_tls_get_addr_call:1; + /* Nonzero if this section has a gp reloc. */ unsigned int has_gp_reloc:1; /* Nonzero if this section needs the relax finalize pass. */ unsigned int need_finalize_relax:1; /* Whether relocations have been processed. */ unsigned int reloc_done : 1; /* End of internal packed boolean fields. */ /* The virtual memory address of the section - where it will be at run time. The symbols are relocated against this. The user_set_vma flag is maintained by bfd; if it's not set, the backend can assign addresses (for example, in <>, where the default address for <<.data>> is dependent on the specific target and various flags). */ bfd_vma vma; /* The load address of the section - where it would be in a rom image; really only used for writing section header information. */ bfd_vma lma; /* The size of the section in octets, as it will be output. Contains a value even if the section has no contents (e.g., the size of <<.bss>>). */ bfd_size_type size; /* For input sections, the original size on disk of the section, in octets. This field is used by the linker relaxation code. It is currently only set for sections where the linker relaxation scheme doesn't cache altered section and reloc contents (stabs, eh_frame, SEC_MERGE, some coff relaxing targets), and thus the original size needs to be kept to read the section multiple times. For output sections, rawsize holds the section size calculated on a previous linker relaxation pass. */ bfd_size_type rawsize; /* If this section is going to be output, then this value is the offset in *bytes* into the output section of the first byte in the input section (byte ==> smallest addressable unit on the target). In most cases, if this was going to start at the 100th octet (8-bit quantity) in the output section, this value would be 100. However, if the target byte size is 16 bits (bfd_octets_per_byte is "2"), this value would be 50. */ bfd_vma output_offset; /* The output section through which to map on output. */ struct bfd_section *output_section; /* The alignment requirement of the section, as an exponent of 2 - e.g., 3 aligns to 2^3 (or 8). */ unsigned int alignment_power; /* If an input section, a pointer to a vector of relocation records for the data in this section. */ struct reloc_cache_entry *relocation; /* If an output section, a pointer to a vector of pointers to relocation records for the data in this section. */ struct reloc_cache_entry **orelocation; /* The number of relocation records in one of the above. */ unsigned reloc_count; /* Information below is back end specific - and not always used or updated. */ /* File position of section data. */ file_ptr filepos; /* File position of relocation info. */ file_ptr rel_filepos; /* File position of line data. */ file_ptr line_filepos; /* Pointer to data for applications. */ void *userdata; /* If the SEC_IN_MEMORY flag is set, this points to the actual contents. */ unsigned char *contents; /* Attached line number information. */ alent *lineno; /* Number of line number records. */ unsigned int lineno_count; /* Entity size for merging purposes. */ unsigned int entsize; /* Points to the kept section if this section is a link-once section, and is discarded. */ struct bfd_section *kept_section; /* When a section is being output, this value changes as more linenumbers are written out. */ file_ptr moving_line_filepos; /* What the section number is in the target world. */ int target_index; void *used_by_bfd; /* If this is a constructor section then here is a list of the relocations created to relocate items within it. */ struct relent_chain *constructor_chain; /* The BFD which owns the section. */ bfd *owner; /* A symbol which points at this section only. */ struct bfd_symbol *symbol; struct bfd_symbol **symbol_ptr_ptr; /* Early in the link process, map_head and map_tail are used to build a list of input sections attached to an output section. Later, output sections use these fields for a list of bfd_link_order structs. */ union { struct bfd_link_order *link_order; struct bfd_section *s; } map_head, map_tail; } asection; /* These sections are global, and are managed by BFD. The application and target back end are not permitted to change the values in these sections. New code should use the section_ptr macros rather than referring directly to the const sections. The const sections may eventually vanish. */ #define BFD_ABS_SECTION_NAME "*ABS*" #define BFD_UND_SECTION_NAME "*UND*" #define BFD_COM_SECTION_NAME "*COM*" #define BFD_IND_SECTION_NAME "*IND*" /* The absolute section. */ extern asection bfd_abs_section; #define bfd_abs_section_ptr ((asection *) &bfd_abs_section) #define bfd_is_abs_section(sec) ((sec) == bfd_abs_section_ptr) /* Pointer to the undefined section. */ extern asection bfd_und_section; #define bfd_und_section_ptr ((asection *) &bfd_und_section) #define bfd_is_und_section(sec) ((sec) == bfd_und_section_ptr) /* Pointer to the common section. */ extern asection bfd_com_section; #define bfd_com_section_ptr ((asection *) &bfd_com_section) /* Pointer to the indirect section. */ extern asection bfd_ind_section; #define bfd_ind_section_ptr ((asection *) &bfd_ind_section) #define bfd_is_ind_section(sec) ((sec) == bfd_ind_section_ptr) #define bfd_is_const_section(SEC) \ ( ((SEC) == bfd_abs_section_ptr) \ || ((SEC) == bfd_und_section_ptr) \ || ((SEC) == bfd_com_section_ptr) \ || ((SEC) == bfd_ind_section_ptr)) /* Macros to handle insertion and deletion of a bfd's sections. These only handle the list pointers, ie. do not adjust section_count, target_index etc. */ #define bfd_section_list_remove(ABFD, S) \ do \ { \ asection *_s = S; \ asection *_next = _s->next; \ asection *_prev = _s->prev; \ if (_prev) \ _prev->next = _next; \ else \ (ABFD)->sections = _next; \ if (_next) \ _next->prev = _prev; \ else \ (ABFD)->section_last = _prev; \ } \ while (0) #define bfd_section_list_append(ABFD, S) \ do \ { \ asection *_s = S; \ bfd *_abfd = ABFD; \ _s->next = NULL; \ if (_abfd->section_last) \ { \ _s->prev = _abfd->section_last; \ _abfd->section_last->next = _s; \ } \ else \ { \ _s->prev = NULL; \ _abfd->sections = _s; \ } \ _abfd->section_last = _s; \ } \ while (0) #define bfd_section_list_prepend(ABFD, S) \ do \ { \ asection *_s = S; \ bfd *_abfd = ABFD; \ _s->prev = NULL; \ if (_abfd->sections) \ { \ _s->next = _abfd->sections; \ _abfd->sections->prev = _s; \ } \ else \ { \ _s->next = NULL; \ _abfd->section_last = _s; \ } \ _abfd->sections = _s; \ } \ while (0) #define bfd_section_list_insert_after(ABFD, A, S) \ do \ { \ asection *_a = A; \ asection *_s = S; \ asection *_next = _a->next; \ _s->next = _next; \ _s->prev = _a; \ _a->next = _s; \ if (_next) \ _next->prev = _s; \ else \ (ABFD)->section_last = _s; \ } \ while (0) #define bfd_section_list_insert_before(ABFD, B, S) \ do \ { \ asection *_b = B; \ asection *_s = S; \ asection *_prev = _b->prev; \ _s->prev = _prev; \ _s->next = _b; \ _b->prev = _s; \ if (_prev) \ _prev->next = _s; \ else \ (ABFD)->sections = _s; \ } \ while (0) #define bfd_section_removed_from_list(ABFD, S) \ ((S)->next == NULL ? (ABFD)->section_last != (S) : (S)->next->prev != (S)) #define BFD_FAKE_SECTION(SEC, FLAGS, SYM, NAME, IDX) \ /* name, id, index, next, prev, flags, user_set_vma, */ \ { NAME, IDX, 0, NULL, NULL, FLAGS, 0, \ \ /* linker_mark, linker_has_input, gc_mark, gc_mark_from_eh, */ \ 0, 0, 1, 0, \ \ /* segment_mark, sec_info_type, use_rela_p, has_tls_reloc, */ \ 0, 0, 0, 0, \ \ - /* has_gp_reloc, need_finalize_relax, reloc_done, */ \ - 0, 0, 0, \ + /* has_tls_get_addr_call, has_gp_reloc, need_finalize_relax, */ \ + 0, 0, 0, \ \ - /* vma, lma, size, rawsize */ \ - 0, 0, 0, 0, \ + /* reloc_done, vma, lma, size, rawsize */ \ + 0, 0, 0, 0, 0, \ \ /* output_offset, output_section, alignment_power, */ \ 0, (struct bfd_section *) &SEC, 0, \ \ /* relocation, orelocation, reloc_count, filepos, rel_filepos, */ \ NULL, NULL, 0, 0, 0, \ \ /* line_filepos, userdata, contents, lineno, lineno_count, */ \ 0, NULL, NULL, NULL, 0, \ \ /* entsize, kept_section, moving_line_filepos, */ \ 0, NULL, 0, \ \ /* target_index, used_by_bfd, constructor_chain, owner, */ \ 0, NULL, NULL, NULL, \ \ /* symbol, symbol_ptr_ptr, */ \ (struct bfd_symbol *) SYM, &SEC.symbol, \ \ /* map_head, map_tail */ \ { NULL }, { NULL } \ } void bfd_section_list_clear (bfd *); asection *bfd_get_section_by_name (bfd *abfd, const char *name); asection *bfd_get_section_by_name_if (bfd *abfd, const char *name, bfd_boolean (*func) (bfd *abfd, asection *sect, void *obj), void *obj); char *bfd_get_unique_section_name (bfd *abfd, const char *templat, int *count); asection *bfd_make_section_old_way (bfd *abfd, const char *name); asection *bfd_make_section_anyway_with_flags (bfd *abfd, const char *name, flagword flags); asection *bfd_make_section_anyway (bfd *abfd, const char *name); asection *bfd_make_section_with_flags (bfd *, const char *name, flagword flags); asection *bfd_make_section (bfd *, const char *name); bfd_boolean bfd_set_section_flags (bfd *abfd, asection *sec, flagword flags); void bfd_map_over_sections (bfd *abfd, void (*func) (bfd *abfd, asection *sect, void *obj), void *obj); asection *bfd_sections_find_if (bfd *abfd, bfd_boolean (*operation) (bfd *abfd, asection *sect, void *obj), void *obj); bfd_boolean bfd_set_section_size (bfd *abfd, asection *sec, bfd_size_type val); bfd_boolean bfd_set_section_contents (bfd *abfd, asection *section, const void *data, file_ptr offset, bfd_size_type count); bfd_boolean bfd_get_section_contents (bfd *abfd, asection *section, void *location, file_ptr offset, bfd_size_type count); bfd_boolean bfd_malloc_and_get_section (bfd *abfd, asection *section, bfd_byte **buf); bfd_boolean bfd_copy_private_section_data (bfd *ibfd, asection *isec, bfd *obfd, asection *osec); #define bfd_copy_private_section_data(ibfd, isection, obfd, osection) \ BFD_SEND (obfd, _bfd_copy_private_section_data, \ (ibfd, isection, obfd, osection)) bfd_boolean bfd_generic_is_group_section (bfd *, const asection *sec); bfd_boolean bfd_generic_discard_group (bfd *abfd, asection *group); /* Extracted from archures.c. */ enum bfd_architecture { bfd_arch_unknown, /* File arch not known. */ bfd_arch_obscure, /* Arch known, not one of these. */ bfd_arch_m68k, /* Motorola 68xxx */ #define bfd_mach_m68000 1 #define bfd_mach_m68008 2 #define bfd_mach_m68010 3 #define bfd_mach_m68020 4 #define bfd_mach_m68030 5 #define bfd_mach_m68040 6 #define bfd_mach_m68060 7 #define bfd_mach_cpu32 8 #define bfd_mach_fido 9 #define bfd_mach_mcf_isa_a_nodiv 10 #define bfd_mach_mcf_isa_a 11 #define bfd_mach_mcf_isa_a_mac 12 #define bfd_mach_mcf_isa_a_emac 13 #define bfd_mach_mcf_isa_aplus 14 #define bfd_mach_mcf_isa_aplus_mac 15 #define bfd_mach_mcf_isa_aplus_emac 16 #define bfd_mach_mcf_isa_b_nousp 17 #define bfd_mach_mcf_isa_b_nousp_mac 18 #define bfd_mach_mcf_isa_b_nousp_emac 19 #define bfd_mach_mcf_isa_b 20 #define bfd_mach_mcf_isa_b_mac 21 #define bfd_mach_mcf_isa_b_emac 22 #define bfd_mach_mcf_isa_b_float 23 #define bfd_mach_mcf_isa_b_float_mac 24 #define bfd_mach_mcf_isa_b_float_emac 25 #define bfd_mach_mcf_isa_c 26 #define bfd_mach_mcf_isa_c_mac 27 #define bfd_mach_mcf_isa_c_emac 28 bfd_arch_vax, /* DEC Vax */ bfd_arch_i960, /* Intel 960 */ /* The order of the following is important. lower number indicates a machine type that only accepts a subset of the instructions available to machines with higher numbers. The exception is the "ca", which is incompatible with all other machines except "core". */ #define bfd_mach_i960_core 1 #define bfd_mach_i960_ka_sa 2 #define bfd_mach_i960_kb_sb 3 #define bfd_mach_i960_mc 4 #define bfd_mach_i960_xa 5 #define bfd_mach_i960_ca 6 #define bfd_mach_i960_jx 7 #define bfd_mach_i960_hx 8 bfd_arch_or32, /* OpenRISC 32 */ bfd_arch_sparc, /* SPARC */ #define bfd_mach_sparc 1 /* The difference between v8plus and v9 is that v9 is a true 64 bit env. */ #define bfd_mach_sparc_sparclet 2 #define bfd_mach_sparc_sparclite 3 #define bfd_mach_sparc_v8plus 4 #define bfd_mach_sparc_v8plusa 5 /* with ultrasparc add'ns. */ #define bfd_mach_sparc_sparclite_le 6 #define bfd_mach_sparc_v9 7 #define bfd_mach_sparc_v9a 8 /* with ultrasparc add'ns. */ #define bfd_mach_sparc_v8plusb 9 /* with cheetah add'ns. */ #define bfd_mach_sparc_v9b 10 /* with cheetah add'ns. */ /* Nonzero if MACH has the v9 instruction set. */ #define bfd_mach_sparc_v9_p(mach) \ ((mach) >= bfd_mach_sparc_v8plus && (mach) <= bfd_mach_sparc_v9b \ && (mach) != bfd_mach_sparc_sparclite_le) /* Nonzero if MACH is a 64 bit sparc architecture. */ #define bfd_mach_sparc_64bit_p(mach) \ ((mach) >= bfd_mach_sparc_v9 && (mach) != bfd_mach_sparc_v8plusb) bfd_arch_spu, /* PowerPC SPU */ #define bfd_mach_spu 256 bfd_arch_mips, /* MIPS Rxxxx */ #define bfd_mach_mips3000 3000 #define bfd_mach_mips3900 3900 #define bfd_mach_mips4000 4000 #define bfd_mach_mips4010 4010 #define bfd_mach_mips4100 4100 #define bfd_mach_mips4111 4111 #define bfd_mach_mips4120 4120 #define bfd_mach_mips4300 4300 #define bfd_mach_mips4400 4400 #define bfd_mach_mips4600 4600 #define bfd_mach_mips4650 4650 #define bfd_mach_mips5000 5000 #define bfd_mach_mips5400 5400 #define bfd_mach_mips5500 5500 #define bfd_mach_mips6000 6000 #define bfd_mach_mips7000 7000 #define bfd_mach_mips8000 8000 #define bfd_mach_mips9000 9000 #define bfd_mach_mips10000 10000 #define bfd_mach_mips12000 12000 #define bfd_mach_mips16 16 #define bfd_mach_mips5 5 #define bfd_mach_mips_sb1 12310201 /* octal 'SB', 01 */ #define bfd_mach_mipsisa32 32 #define bfd_mach_mipsisa32r2 33 #define bfd_mach_mipsisa64 64 #define bfd_mach_mipsisa64r2 65 bfd_arch_i386, /* Intel 386 */ #define bfd_mach_i386_i386 1 #define bfd_mach_i386_i8086 2 #define bfd_mach_i386_i386_intel_syntax 3 #define bfd_mach_x86_64 64 #define bfd_mach_x86_64_intel_syntax 65 bfd_arch_we32k, /* AT&T WE32xxx */ bfd_arch_tahoe, /* CCI/Harris Tahoe */ bfd_arch_i860, /* Intel 860 */ bfd_arch_i370, /* IBM 360/370 Mainframes */ bfd_arch_romp, /* IBM ROMP PC/RT */ bfd_arch_convex, /* Convex */ bfd_arch_m88k, /* Motorola 88xxx */ bfd_arch_m98k, /* Motorola 98xxx */ bfd_arch_pyramid, /* Pyramid Technology */ bfd_arch_h8300, /* Renesas H8/300 (formerly Hitachi H8/300) */ #define bfd_mach_h8300 1 #define bfd_mach_h8300h 2 #define bfd_mach_h8300s 3 #define bfd_mach_h8300hn 4 #define bfd_mach_h8300sn 5 #define bfd_mach_h8300sx 6 #define bfd_mach_h8300sxn 7 bfd_arch_pdp11, /* DEC PDP-11 */ bfd_arch_powerpc, /* PowerPC */ #define bfd_mach_ppc 32 #define bfd_mach_ppc64 64 #define bfd_mach_ppc_403 403 #define bfd_mach_ppc_403gc 4030 #define bfd_mach_ppc_505 505 #define bfd_mach_ppc_601 601 #define bfd_mach_ppc_602 602 #define bfd_mach_ppc_603 603 #define bfd_mach_ppc_ec603e 6031 #define bfd_mach_ppc_604 604 #define bfd_mach_ppc_620 620 #define bfd_mach_ppc_630 630 #define bfd_mach_ppc_750 750 #define bfd_mach_ppc_860 860 #define bfd_mach_ppc_a35 35 #define bfd_mach_ppc_rs64ii 642 #define bfd_mach_ppc_rs64iii 643 #define bfd_mach_ppc_7400 7400 #define bfd_mach_ppc_e500 500 bfd_arch_rs6000, /* IBM RS/6000 */ #define bfd_mach_rs6k 6000 #define bfd_mach_rs6k_rs1 6001 #define bfd_mach_rs6k_rsc 6003 #define bfd_mach_rs6k_rs2 6002 bfd_arch_hppa, /* HP PA RISC */ #define bfd_mach_hppa10 10 #define bfd_mach_hppa11 11 #define bfd_mach_hppa20 20 #define bfd_mach_hppa20w 25 bfd_arch_d10v, /* Mitsubishi D10V */ #define bfd_mach_d10v 1 #define bfd_mach_d10v_ts2 2 #define bfd_mach_d10v_ts3 3 bfd_arch_d30v, /* Mitsubishi D30V */ bfd_arch_dlx, /* DLX */ bfd_arch_m68hc11, /* Motorola 68HC11 */ bfd_arch_m68hc12, /* Motorola 68HC12 */ #define bfd_mach_m6812_default 0 #define bfd_mach_m6812 1 #define bfd_mach_m6812s 2 bfd_arch_z8k, /* Zilog Z8000 */ #define bfd_mach_z8001 1 #define bfd_mach_z8002 2 bfd_arch_h8500, /* Renesas H8/500 (formerly Hitachi H8/500) */ bfd_arch_sh, /* Renesas / SuperH SH (formerly Hitachi SH) */ #define bfd_mach_sh 1 #define bfd_mach_sh2 0x20 #define bfd_mach_sh_dsp 0x2d #define bfd_mach_sh2a 0x2a #define bfd_mach_sh2a_nofpu 0x2b #define bfd_mach_sh2a_nofpu_or_sh4_nommu_nofpu 0x2a1 #define bfd_mach_sh2a_nofpu_or_sh3_nommu 0x2a2 #define bfd_mach_sh2a_or_sh4 0x2a3 #define bfd_mach_sh2a_or_sh3e 0x2a4 #define bfd_mach_sh2e 0x2e #define bfd_mach_sh3 0x30 #define bfd_mach_sh3_nommu 0x31 #define bfd_mach_sh3_dsp 0x3d #define bfd_mach_sh3e 0x3e #define bfd_mach_sh4 0x40 #define bfd_mach_sh4_nofpu 0x41 #define bfd_mach_sh4_nommu_nofpu 0x42 #define bfd_mach_sh4a 0x4a #define bfd_mach_sh4a_nofpu 0x4b #define bfd_mach_sh4al_dsp 0x4d #define bfd_mach_sh5 0x50 bfd_arch_alpha, /* Dec Alpha */ #define bfd_mach_alpha_ev4 0x10 #define bfd_mach_alpha_ev5 0x20 #define bfd_mach_alpha_ev6 0x30 bfd_arch_arm, /* Advanced Risc Machines ARM. */ #define bfd_mach_arm_unknown 0 #define bfd_mach_arm_2 1 #define bfd_mach_arm_2a 2 #define bfd_mach_arm_3 3 #define bfd_mach_arm_3M 4 #define bfd_mach_arm_4 5 #define bfd_mach_arm_4T 6 #define bfd_mach_arm_5 7 #define bfd_mach_arm_5T 8 #define bfd_mach_arm_5TE 9 #define bfd_mach_arm_XScale 10 #define bfd_mach_arm_ep9312 11 #define bfd_mach_arm_iWMMXt 12 #define bfd_mach_arm_iWMMXt2 13 bfd_arch_ns32k, /* National Semiconductors ns32000 */ bfd_arch_w65, /* WDC 65816 */ bfd_arch_tic30, /* Texas Instruments TMS320C30 */ bfd_arch_tic4x, /* Texas Instruments TMS320C3X/4X */ #define bfd_mach_tic3x 30 #define bfd_mach_tic4x 40 bfd_arch_tic54x, /* Texas Instruments TMS320C54X */ bfd_arch_tic80, /* TI TMS320c80 (MVP) */ bfd_arch_v850, /* NEC V850 */ #define bfd_mach_v850 1 #define bfd_mach_v850e 'E' #define bfd_mach_v850e1 '1' bfd_arch_arc, /* ARC Cores */ #define bfd_mach_arc_5 5 #define bfd_mach_arc_6 6 #define bfd_mach_arc_7 7 #define bfd_mach_arc_8 8 bfd_arch_m32c, /* Renesas M16C/M32C. */ #define bfd_mach_m16c 0x75 #define bfd_mach_m32c 0x78 bfd_arch_m32r, /* Renesas M32R (formerly Mitsubishi M32R/D) */ #define bfd_mach_m32r 1 /* For backwards compatibility. */ #define bfd_mach_m32rx 'x' #define bfd_mach_m32r2 '2' bfd_arch_mn10200, /* Matsushita MN10200 */ bfd_arch_mn10300, /* Matsushita MN10300 */ #define bfd_mach_mn10300 300 #define bfd_mach_am33 330 #define bfd_mach_am33_2 332 bfd_arch_fr30, #define bfd_mach_fr30 0x46523330 bfd_arch_frv, #define bfd_mach_frv 1 #define bfd_mach_frvsimple 2 #define bfd_mach_fr300 300 #define bfd_mach_fr400 400 #define bfd_mach_fr450 450 #define bfd_mach_frvtomcat 499 /* fr500 prototype */ #define bfd_mach_fr500 500 #define bfd_mach_fr550 550 bfd_arch_mcore, bfd_arch_mep, #define bfd_mach_mep 1 #define bfd_mach_mep_h1 0x6831 bfd_arch_ia64, /* HP/Intel ia64 */ #define bfd_mach_ia64_elf64 64 #define bfd_mach_ia64_elf32 32 bfd_arch_ip2k, /* Ubicom IP2K microcontrollers. */ #define bfd_mach_ip2022 1 #define bfd_mach_ip2022ext 2 bfd_arch_iq2000, /* Vitesse IQ2000. */ #define bfd_mach_iq2000 1 #define bfd_mach_iq10 2 bfd_arch_mt, #define bfd_mach_ms1 1 #define bfd_mach_mrisc2 2 #define bfd_mach_ms2 3 bfd_arch_pj, bfd_arch_avr, /* Atmel AVR microcontrollers. */ #define bfd_mach_avr1 1 #define bfd_mach_avr2 2 #define bfd_mach_avr3 3 #define bfd_mach_avr4 4 #define bfd_mach_avr5 5 #define bfd_mach_avr6 6 bfd_arch_bfin, /* ADI Blackfin */ #define bfd_mach_bfin 1 bfd_arch_cr16, /* National Semiconductor CompactRISC (ie CR16). */ #define bfd_mach_cr16 1 bfd_arch_cr16c, /* National Semiconductor CompactRISC. */ #define bfd_mach_cr16c 1 bfd_arch_crx, /* National Semiconductor CRX. */ #define bfd_mach_crx 1 bfd_arch_cris, /* Axis CRIS */ #define bfd_mach_cris_v0_v10 255 #define bfd_mach_cris_v32 32 #define bfd_mach_cris_v10_v32 1032 bfd_arch_s390, /* IBM s390 */ #define bfd_mach_s390_31 31 #define bfd_mach_s390_64 64 bfd_arch_score, /* Sunplus score */ bfd_arch_openrisc, /* OpenRISC */ bfd_arch_mmix, /* Donald Knuth's educational processor. */ bfd_arch_xstormy16, #define bfd_mach_xstormy16 1 bfd_arch_msp430, /* Texas Instruments MSP430 architecture. */ #define bfd_mach_msp11 11 #define bfd_mach_msp110 110 #define bfd_mach_msp12 12 #define bfd_mach_msp13 13 #define bfd_mach_msp14 14 #define bfd_mach_msp15 15 #define bfd_mach_msp16 16 #define bfd_mach_msp21 21 #define bfd_mach_msp31 31 #define bfd_mach_msp32 32 #define bfd_mach_msp33 33 #define bfd_mach_msp41 41 #define bfd_mach_msp42 42 #define bfd_mach_msp43 43 #define bfd_mach_msp44 44 bfd_arch_xc16x, /* Infineon's XC16X Series. */ #define bfd_mach_xc16x 1 #define bfd_mach_xc16xl 2 #define bfd_mach_xc16xs 3 bfd_arch_xtensa, /* Tensilica's Xtensa cores. */ #define bfd_mach_xtensa 1 bfd_arch_maxq, /* Dallas MAXQ 10/20 */ #define bfd_mach_maxq10 10 #define bfd_mach_maxq20 20 bfd_arch_z80, #define bfd_mach_z80strict 1 /* No undocumented opcodes. */ #define bfd_mach_z80 3 /* With ixl, ixh, iyl, and iyh. */ #define bfd_mach_z80full 7 /* All undocumented instructions. */ #define bfd_mach_r800 11 /* R800: successor with multiplication. */ bfd_arch_last }; typedef struct bfd_arch_info { int bits_per_word; int bits_per_address; int bits_per_byte; enum bfd_architecture arch; unsigned long mach; const char *arch_name; const char *printable_name; unsigned int section_align_power; /* TRUE if this is the default machine for the architecture. The default arch should be the first entry for an arch so that all the entries for that arch can be accessed via <>. */ bfd_boolean the_default; const struct bfd_arch_info * (*compatible) (const struct bfd_arch_info *a, const struct bfd_arch_info *b); bfd_boolean (*scan) (const struct bfd_arch_info *, const char *); const struct bfd_arch_info *next; } bfd_arch_info_type; const char *bfd_printable_name (bfd *abfd); const bfd_arch_info_type *bfd_scan_arch (const char *string); const char **bfd_arch_list (void); const bfd_arch_info_type *bfd_arch_get_compatible (const bfd *abfd, const bfd *bbfd, bfd_boolean accept_unknowns); void bfd_set_arch_info (bfd *abfd, const bfd_arch_info_type *arg); enum bfd_architecture bfd_get_arch (bfd *abfd); unsigned long bfd_get_mach (bfd *abfd); unsigned int bfd_arch_bits_per_byte (bfd *abfd); unsigned int bfd_arch_bits_per_address (bfd *abfd); const bfd_arch_info_type *bfd_get_arch_info (bfd *abfd); const bfd_arch_info_type *bfd_lookup_arch (enum bfd_architecture arch, unsigned long machine); const char *bfd_printable_arch_mach (enum bfd_architecture arch, unsigned long machine); unsigned int bfd_octets_per_byte (bfd *abfd); unsigned int bfd_arch_mach_octets_per_byte (enum bfd_architecture arch, unsigned long machine); /* Extracted from reloc.c. */ typedef enum bfd_reloc_status { /* No errors detected. */ bfd_reloc_ok, /* The relocation was performed, but there was an overflow. */ bfd_reloc_overflow, /* The address to relocate was not within the section supplied. */ bfd_reloc_outofrange, /* Used by special functions. */ bfd_reloc_continue, /* Unsupported relocation size requested. */ bfd_reloc_notsupported, /* Unused. */ bfd_reloc_other, /* The symbol to relocate against was undefined. */ bfd_reloc_undefined, /* The relocation was performed, but may not be ok - presently generated only when linking i960 coff files with i960 b.out symbols. If this type is returned, the error_message argument to bfd_perform_relocation will be set. */ bfd_reloc_dangerous } bfd_reloc_status_type; typedef struct reloc_cache_entry { /* A pointer into the canonical table of pointers. */ struct bfd_symbol **sym_ptr_ptr; /* offset in section. */ bfd_size_type address; /* addend for relocation value. */ bfd_vma addend; /* Pointer to how to perform the required relocation. */ reloc_howto_type *howto; } arelent; enum complain_overflow { /* Do not complain on overflow. */ complain_overflow_dont, /* Complain if the value overflows when considered as a signed number one bit larger than the field. ie. A bitfield of N bits is allowed to represent -2**n to 2**n-1. */ complain_overflow_bitfield, /* Complain if the value overflows when considered as a signed number. */ complain_overflow_signed, /* Complain if the value overflows when considered as an unsigned number. */ complain_overflow_unsigned }; struct reloc_howto_struct { /* The type field has mainly a documentary use - the back end can do what it wants with it, though normally the back end's external idea of what a reloc number is stored in this field. For example, a PC relative word relocation in a coff environment has the type 023 - because that's what the outside world calls a R_PCRWORD reloc. */ unsigned int type; /* The value the final relocation is shifted right by. This drops unwanted data from the relocation. */ unsigned int rightshift; /* The size of the item to be relocated. This is *not* a power-of-two measure. To get the number of bytes operated on by a type of relocation, use bfd_get_reloc_size. */ int size; /* The number of bits in the item to be relocated. This is used when doing overflow checking. */ unsigned int bitsize; /* Notes that the relocation is relative to the location in the data section of the addend. The relocation function will subtract from the relocation value the address of the location being relocated. */ bfd_boolean pc_relative; /* The bit position of the reloc value in the destination. The relocated value is left shifted by this amount. */ unsigned int bitpos; /* What type of overflow error should be checked for when relocating. */ enum complain_overflow complain_on_overflow; /* If this field is non null, then the supplied function is called rather than the normal function. This allows really strange relocation methods to be accommodated (e.g., i960 callj instructions). */ bfd_reloc_status_type (*special_function) (bfd *, arelent *, struct bfd_symbol *, void *, asection *, bfd *, char **); /* The textual name of the relocation type. */ char *name; /* Some formats record a relocation addend in the section contents rather than with the relocation. For ELF formats this is the distinction between USE_REL and USE_RELA (though the code checks for USE_REL == 1/0). The value of this field is TRUE if the addend is recorded with the section contents; when performing a partial link (ld -r) the section contents (the data) will be modified. The value of this field is FALSE if addends are recorded with the relocation (in arelent.addend); when performing a partial link the relocation will be modified. All relocations for all ELF USE_RELA targets should set this field to FALSE (values of TRUE should be looked on with suspicion). However, the converse is not true: not all relocations of all ELF USE_REL targets set this field to TRUE. Why this is so is peculiar to each particular target. For relocs that aren't used in partial links (e.g. GOT stuff) it doesn't matter what this is set to. */ bfd_boolean partial_inplace; /* src_mask selects the part of the instruction (or data) to be used in the relocation sum. If the target relocations don't have an addend in the reloc, eg. ELF USE_REL, src_mask will normally equal dst_mask to extract the addend from the section contents. If relocations do have an addend in the reloc, eg. ELF USE_RELA, this field should be zero. Non-zero values for ELF USE_RELA targets are bogus as in those cases the value in the dst_mask part of the section contents should be treated as garbage. */ bfd_vma src_mask; /* dst_mask selects which parts of the instruction (or data) are replaced with a relocated value. */ bfd_vma dst_mask; /* When some formats create PC relative instructions, they leave the value of the pc of the place being relocated in the offset slot of the instruction, so that a PC relative relocation can be made just by adding in an ordinary offset (e.g., sun3 a.out). Some formats leave the displacement part of an instruction empty (e.g., m88k bcs); this flag signals the fact. */ bfd_boolean pcrel_offset; }; #define HOWTO(C, R, S, B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC) \ { (unsigned) C, R, S, B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC } #define NEWHOWTO(FUNCTION, NAME, SIZE, REL, IN) \ HOWTO (0, 0, SIZE, 0, REL, 0, complain_overflow_dont, FUNCTION, \ NAME, FALSE, 0, 0, IN) #define EMPTY_HOWTO(C) \ HOWTO ((C), 0, 0, 0, FALSE, 0, complain_overflow_dont, NULL, \ NULL, FALSE, 0, 0, FALSE) #define HOWTO_PREPARE(relocation, symbol) \ { \ if (symbol != NULL) \ { \ if (bfd_is_com_section (symbol->section)) \ { \ relocation = 0; \ } \ else \ { \ relocation = symbol->value; \ } \ } \ } unsigned int bfd_get_reloc_size (reloc_howto_type *); typedef struct relent_chain { arelent relent; struct relent_chain *next; } arelent_chain; bfd_reloc_status_type bfd_check_overflow (enum complain_overflow how, unsigned int bitsize, unsigned int rightshift, unsigned int addrsize, bfd_vma relocation); bfd_reloc_status_type bfd_perform_relocation (bfd *abfd, arelent *reloc_entry, void *data, asection *input_section, bfd *output_bfd, char **error_message); bfd_reloc_status_type bfd_install_relocation (bfd *abfd, arelent *reloc_entry, void *data, bfd_vma data_start, asection *input_section, char **error_message); enum bfd_reloc_code_real { _dummy_first_bfd_reloc_code_real, /* Basic absolute relocations of N bits. */ BFD_RELOC_64, BFD_RELOC_32, BFD_RELOC_26, BFD_RELOC_24, BFD_RELOC_16, BFD_RELOC_14, BFD_RELOC_8, /* PC-relative relocations. Sometimes these are relative to the address of the relocation itself; sometimes they are relative to the start of the section containing the relocation. It depends on the specific target. The 24-bit relocation is used in some Intel 960 configurations. */ BFD_RELOC_64_PCREL, BFD_RELOC_32_PCREL, BFD_RELOC_24_PCREL, BFD_RELOC_16_PCREL, BFD_RELOC_12_PCREL, BFD_RELOC_8_PCREL, /* Section relative relocations. Some targets need this for DWARF2. */ BFD_RELOC_32_SECREL, /* For ELF. */ BFD_RELOC_32_GOT_PCREL, BFD_RELOC_16_GOT_PCREL, BFD_RELOC_8_GOT_PCREL, BFD_RELOC_32_GOTOFF, BFD_RELOC_16_GOTOFF, BFD_RELOC_LO16_GOTOFF, BFD_RELOC_HI16_GOTOFF, BFD_RELOC_HI16_S_GOTOFF, BFD_RELOC_8_GOTOFF, BFD_RELOC_64_PLT_PCREL, BFD_RELOC_32_PLT_PCREL, BFD_RELOC_24_PLT_PCREL, BFD_RELOC_16_PLT_PCREL, BFD_RELOC_8_PLT_PCREL, BFD_RELOC_64_PLTOFF, BFD_RELOC_32_PLTOFF, BFD_RELOC_16_PLTOFF, BFD_RELOC_LO16_PLTOFF, BFD_RELOC_HI16_PLTOFF, BFD_RELOC_HI16_S_PLTOFF, BFD_RELOC_8_PLTOFF, /* Relocations used by 68K ELF. */ BFD_RELOC_68K_GLOB_DAT, BFD_RELOC_68K_JMP_SLOT, BFD_RELOC_68K_RELATIVE, /* Linkage-table relative. */ BFD_RELOC_32_BASEREL, BFD_RELOC_16_BASEREL, BFD_RELOC_LO16_BASEREL, BFD_RELOC_HI16_BASEREL, BFD_RELOC_HI16_S_BASEREL, BFD_RELOC_8_BASEREL, BFD_RELOC_RVA, /* Absolute 8-bit relocation, but used to form an address like 0xFFnn. */ BFD_RELOC_8_FFnn, /* These PC-relative relocations are stored as word displacements -- i.e., byte displacements shifted right two bits. The 30-bit word displacement (<<32_PCREL_S2>> -- 32 bits, shifted 2) is used on the SPARC. (SPARC tools generally refer to this as <>.) The signed 16-bit displacement is used on the MIPS, and the 23-bit displacement is used on the Alpha. */ BFD_RELOC_32_PCREL_S2, BFD_RELOC_16_PCREL_S2, BFD_RELOC_23_PCREL_S2, /* High 22 bits and low 10 bits of 32-bit value, placed into lower bits of the target word. These are used on the SPARC. */ BFD_RELOC_HI22, BFD_RELOC_LO10, /* For systems that allocate a Global Pointer register, these are displacements off that register. These relocation types are handled specially, because the value the register will have is decided relatively late. */ BFD_RELOC_GPREL16, BFD_RELOC_GPREL32, /* Reloc types used for i960/b.out. */ BFD_RELOC_I960_CALLJ, /* SPARC ELF relocations. There is probably some overlap with other relocation types already defined. */ BFD_RELOC_NONE, BFD_RELOC_SPARC_WDISP22, BFD_RELOC_SPARC22, BFD_RELOC_SPARC13, BFD_RELOC_SPARC_GOT10, BFD_RELOC_SPARC_GOT13, BFD_RELOC_SPARC_GOT22, BFD_RELOC_SPARC_PC10, BFD_RELOC_SPARC_PC22, BFD_RELOC_SPARC_WPLT30, BFD_RELOC_SPARC_COPY, BFD_RELOC_SPARC_GLOB_DAT, BFD_RELOC_SPARC_JMP_SLOT, BFD_RELOC_SPARC_RELATIVE, BFD_RELOC_SPARC_UA16, BFD_RELOC_SPARC_UA32, BFD_RELOC_SPARC_UA64, /* I think these are specific to SPARC a.out (e.g., Sun 4). */ BFD_RELOC_SPARC_BASE13, BFD_RELOC_SPARC_BASE22, /* SPARC64 relocations */ #define BFD_RELOC_SPARC_64 BFD_RELOC_64 BFD_RELOC_SPARC_10, BFD_RELOC_SPARC_11, BFD_RELOC_SPARC_OLO10, BFD_RELOC_SPARC_HH22, BFD_RELOC_SPARC_HM10, BFD_RELOC_SPARC_LM22, BFD_RELOC_SPARC_PC_HH22, BFD_RELOC_SPARC_PC_HM10, BFD_RELOC_SPARC_PC_LM22, BFD_RELOC_SPARC_WDISP16, BFD_RELOC_SPARC_WDISP19, BFD_RELOC_SPARC_7, BFD_RELOC_SPARC_6, BFD_RELOC_SPARC_5, #define BFD_RELOC_SPARC_DISP64 BFD_RELOC_64_PCREL BFD_RELOC_SPARC_PLT32, BFD_RELOC_SPARC_PLT64, BFD_RELOC_SPARC_HIX22, BFD_RELOC_SPARC_LOX10, BFD_RELOC_SPARC_H44, BFD_RELOC_SPARC_M44, BFD_RELOC_SPARC_L44, BFD_RELOC_SPARC_REGISTER, /* SPARC little endian relocation */ BFD_RELOC_SPARC_REV32, /* SPARC TLS relocations */ BFD_RELOC_SPARC_TLS_GD_HI22, BFD_RELOC_SPARC_TLS_GD_LO10, BFD_RELOC_SPARC_TLS_GD_ADD, BFD_RELOC_SPARC_TLS_GD_CALL, BFD_RELOC_SPARC_TLS_LDM_HI22, BFD_RELOC_SPARC_TLS_LDM_LO10, BFD_RELOC_SPARC_TLS_LDM_ADD, BFD_RELOC_SPARC_TLS_LDM_CALL, BFD_RELOC_SPARC_TLS_LDO_HIX22, BFD_RELOC_SPARC_TLS_LDO_LOX10, BFD_RELOC_SPARC_TLS_LDO_ADD, BFD_RELOC_SPARC_TLS_IE_HI22, BFD_RELOC_SPARC_TLS_IE_LO10, BFD_RELOC_SPARC_TLS_IE_LD, BFD_RELOC_SPARC_TLS_IE_LDX, BFD_RELOC_SPARC_TLS_IE_ADD, BFD_RELOC_SPARC_TLS_LE_HIX22, BFD_RELOC_SPARC_TLS_LE_LOX10, BFD_RELOC_SPARC_TLS_DTPMOD32, BFD_RELOC_SPARC_TLS_DTPMOD64, BFD_RELOC_SPARC_TLS_DTPOFF32, BFD_RELOC_SPARC_TLS_DTPOFF64, BFD_RELOC_SPARC_TLS_TPOFF32, BFD_RELOC_SPARC_TLS_TPOFF64, /* SPU Relocations. */ BFD_RELOC_SPU_IMM7, BFD_RELOC_SPU_IMM8, BFD_RELOC_SPU_IMM10, BFD_RELOC_SPU_IMM10W, BFD_RELOC_SPU_IMM16, BFD_RELOC_SPU_IMM16W, BFD_RELOC_SPU_IMM18, BFD_RELOC_SPU_PCREL9a, BFD_RELOC_SPU_PCREL9b, BFD_RELOC_SPU_PCREL16, BFD_RELOC_SPU_LO16, BFD_RELOC_SPU_HI16, BFD_RELOC_SPU_PPU32, BFD_RELOC_SPU_PPU64, /* Alpha ECOFF and ELF relocations. Some of these treat the symbol or "addend" in some special way. For GPDISP_HI16 ("gpdisp") relocations, the symbol is ignored when writing; when reading, it will be the absolute section symbol. The addend is the displacement in bytes of the "lda" instruction from the "ldah" instruction (which is at the address of this reloc). */ BFD_RELOC_ALPHA_GPDISP_HI16, /* For GPDISP_LO16 ("ignore") relocations, the symbol is handled as with GPDISP_HI16 relocs. The addend is ignored when writing the relocations out, and is filled in with the file's GP value on reading, for convenience. */ BFD_RELOC_ALPHA_GPDISP_LO16, /* The ELF GPDISP relocation is exactly the same as the GPDISP_HI16 relocation except that there is no accompanying GPDISP_LO16 relocation. */ BFD_RELOC_ALPHA_GPDISP, /* The Alpha LITERAL/LITUSE relocs are produced by a symbol reference; the assembler turns it into a LDQ instruction to load the address of the symbol, and then fills in a register in the real instruction. The LITERAL reloc, at the LDQ instruction, refers to the .lita section symbol. The addend is ignored when writing, but is filled in with the file's GP value on reading, for convenience, as with the GPDISP_LO16 reloc. The ELF_LITERAL reloc is somewhere between 16_GOTOFF and GPDISP_LO16. It should refer to the symbol to be referenced, as with 16_GOTOFF, but it generates output not based on the position within the .got section, but relative to the GP value chosen for the file during the final link stage. The LITUSE reloc, on the instruction using the loaded address, gives information to the linker that it might be able to use to optimize away some literal section references. The symbol is ignored (read as the absolute section symbol), and the "addend" indicates the type of instruction using the register: 1 - "memory" fmt insn 2 - byte-manipulation (byte offset reg) 3 - jsr (target of branch) */ BFD_RELOC_ALPHA_LITERAL, BFD_RELOC_ALPHA_ELF_LITERAL, BFD_RELOC_ALPHA_LITUSE, /* The HINT relocation indicates a value that should be filled into the "hint" field of a jmp/jsr/ret instruction, for possible branch- prediction logic which may be provided on some processors. */ BFD_RELOC_ALPHA_HINT, /* The LINKAGE relocation outputs a linkage pair in the object file, which is filled by the linker. */ BFD_RELOC_ALPHA_LINKAGE, /* The CODEADDR relocation outputs a STO_CA in the object file, which is filled by the linker. */ BFD_RELOC_ALPHA_CODEADDR, /* The GPREL_HI/LO relocations together form a 32-bit offset from the GP register. */ BFD_RELOC_ALPHA_GPREL_HI16, BFD_RELOC_ALPHA_GPREL_LO16, /* Like BFD_RELOC_23_PCREL_S2, except that the source and target must share a common GP, and the target address is adjusted for STO_ALPHA_STD_GPLOAD. */ BFD_RELOC_ALPHA_BRSGP, /* Alpha thread-local storage relocations. */ BFD_RELOC_ALPHA_TLSGD, BFD_RELOC_ALPHA_TLSLDM, BFD_RELOC_ALPHA_DTPMOD64, BFD_RELOC_ALPHA_GOTDTPREL16, BFD_RELOC_ALPHA_DTPREL64, BFD_RELOC_ALPHA_DTPREL_HI16, BFD_RELOC_ALPHA_DTPREL_LO16, BFD_RELOC_ALPHA_DTPREL16, BFD_RELOC_ALPHA_GOTTPREL16, BFD_RELOC_ALPHA_TPREL64, BFD_RELOC_ALPHA_TPREL_HI16, BFD_RELOC_ALPHA_TPREL_LO16, BFD_RELOC_ALPHA_TPREL16, /* Bits 27..2 of the relocation address shifted right 2 bits; simple reloc otherwise. */ BFD_RELOC_MIPS_JMP, /* The MIPS16 jump instruction. */ BFD_RELOC_MIPS16_JMP, /* MIPS16 GP relative reloc. */ BFD_RELOC_MIPS16_GPREL, /* High 16 bits of 32-bit value; simple reloc. */ BFD_RELOC_HI16, /* High 16 bits of 32-bit value but the low 16 bits will be sign extended and added to form the final result. If the low 16 bits form a negative number, we need to add one to the high value to compensate for the borrow when the low bits are added. */ BFD_RELOC_HI16_S, /* Low 16 bits. */ BFD_RELOC_LO16, /* High 16 bits of 32-bit pc-relative value */ BFD_RELOC_HI16_PCREL, /* High 16 bits of 32-bit pc-relative value, adjusted */ BFD_RELOC_HI16_S_PCREL, /* Low 16 bits of pc-relative value */ BFD_RELOC_LO16_PCREL, /* MIPS16 high 16 bits of 32-bit value. */ BFD_RELOC_MIPS16_HI16, /* MIPS16 high 16 bits of 32-bit value but the low 16 bits will be sign extended and added to form the final result. If the low 16 bits form a negative number, we need to add one to the high value to compensate for the borrow when the low bits are added. */ BFD_RELOC_MIPS16_HI16_S, /* MIPS16 low 16 bits. */ BFD_RELOC_MIPS16_LO16, /* Relocation against a MIPS literal section. */ BFD_RELOC_MIPS_LITERAL, /* MIPS ELF relocations. */ BFD_RELOC_MIPS_GOT16, BFD_RELOC_MIPS_CALL16, BFD_RELOC_MIPS_GOT_HI16, BFD_RELOC_MIPS_GOT_LO16, BFD_RELOC_MIPS_CALL_HI16, BFD_RELOC_MIPS_CALL_LO16, BFD_RELOC_MIPS_SUB, BFD_RELOC_MIPS_GOT_PAGE, BFD_RELOC_MIPS_GOT_OFST, BFD_RELOC_MIPS_GOT_DISP, BFD_RELOC_MIPS_SHIFT5, BFD_RELOC_MIPS_SHIFT6, BFD_RELOC_MIPS_INSERT_A, BFD_RELOC_MIPS_INSERT_B, BFD_RELOC_MIPS_DELETE, BFD_RELOC_MIPS_HIGHEST, BFD_RELOC_MIPS_HIGHER, BFD_RELOC_MIPS_SCN_DISP, BFD_RELOC_MIPS_REL16, BFD_RELOC_MIPS_RELGOT, BFD_RELOC_MIPS_JALR, BFD_RELOC_MIPS_TLS_DTPMOD32, BFD_RELOC_MIPS_TLS_DTPREL32, BFD_RELOC_MIPS_TLS_DTPMOD64, BFD_RELOC_MIPS_TLS_DTPREL64, BFD_RELOC_MIPS_TLS_GD, BFD_RELOC_MIPS_TLS_LDM, BFD_RELOC_MIPS_TLS_DTPREL_HI16, BFD_RELOC_MIPS_TLS_DTPREL_LO16, BFD_RELOC_MIPS_TLS_GOTTPREL, BFD_RELOC_MIPS_TLS_TPREL32, BFD_RELOC_MIPS_TLS_TPREL64, BFD_RELOC_MIPS_TLS_TPREL_HI16, 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, BFD_RELOC_FRV_LO16, BFD_RELOC_FRV_HI16, BFD_RELOC_FRV_GPREL12, BFD_RELOC_FRV_GPRELU12, BFD_RELOC_FRV_GPREL32, BFD_RELOC_FRV_GPRELHI, BFD_RELOC_FRV_GPRELLO, BFD_RELOC_FRV_GOT12, BFD_RELOC_FRV_GOTHI, BFD_RELOC_FRV_GOTLO, BFD_RELOC_FRV_FUNCDESC, BFD_RELOC_FRV_FUNCDESC_GOT12, BFD_RELOC_FRV_FUNCDESC_GOTHI, BFD_RELOC_FRV_FUNCDESC_GOTLO, BFD_RELOC_FRV_FUNCDESC_VALUE, BFD_RELOC_FRV_FUNCDESC_GOTOFF12, BFD_RELOC_FRV_FUNCDESC_GOTOFFHI, BFD_RELOC_FRV_FUNCDESC_GOTOFFLO, BFD_RELOC_FRV_GOTOFF12, BFD_RELOC_FRV_GOTOFFHI, BFD_RELOC_FRV_GOTOFFLO, BFD_RELOC_FRV_GETTLSOFF, BFD_RELOC_FRV_TLSDESC_VALUE, BFD_RELOC_FRV_GOTTLSDESC12, BFD_RELOC_FRV_GOTTLSDESCHI, BFD_RELOC_FRV_GOTTLSDESCLO, BFD_RELOC_FRV_TLSMOFF12, BFD_RELOC_FRV_TLSMOFFHI, BFD_RELOC_FRV_TLSMOFFLO, BFD_RELOC_FRV_GOTTLSOFF12, BFD_RELOC_FRV_GOTTLSOFFHI, BFD_RELOC_FRV_GOTTLSOFFLO, BFD_RELOC_FRV_TLSOFF, BFD_RELOC_FRV_TLSDESC_RELAX, BFD_RELOC_FRV_GETTLSOFF_RELAX, BFD_RELOC_FRV_TLSOFF_RELAX, BFD_RELOC_FRV_TLSMOFF, /* This is a 24bit GOT-relative reloc for the mn10300. */ BFD_RELOC_MN10300_GOTOFF24, /* This is a 32bit GOT-relative reloc for the mn10300, offset by two bytes in the instruction. */ BFD_RELOC_MN10300_GOT32, /* This is a 24bit GOT-relative reloc for the mn10300, offset by two bytes in the instruction. */ BFD_RELOC_MN10300_GOT24, /* This is a 16bit GOT-relative reloc for the mn10300, offset by two bytes in the instruction. */ BFD_RELOC_MN10300_GOT16, /* Copy symbol at runtime. */ BFD_RELOC_MN10300_COPY, /* Create GOT entry. */ BFD_RELOC_MN10300_GLOB_DAT, /* Create PLT entry. */ BFD_RELOC_MN10300_JMP_SLOT, /* Adjust by program base. */ BFD_RELOC_MN10300_RELATIVE, /* i386/elf relocations */ BFD_RELOC_386_GOT32, BFD_RELOC_386_PLT32, BFD_RELOC_386_COPY, BFD_RELOC_386_GLOB_DAT, BFD_RELOC_386_JUMP_SLOT, BFD_RELOC_386_RELATIVE, BFD_RELOC_386_GOTOFF, BFD_RELOC_386_GOTPC, BFD_RELOC_386_TLS_TPOFF, BFD_RELOC_386_TLS_IE, BFD_RELOC_386_TLS_GOTIE, BFD_RELOC_386_TLS_LE, BFD_RELOC_386_TLS_GD, BFD_RELOC_386_TLS_LDM, BFD_RELOC_386_TLS_LDO_32, BFD_RELOC_386_TLS_IE_32, BFD_RELOC_386_TLS_LE_32, BFD_RELOC_386_TLS_DTPMOD32, BFD_RELOC_386_TLS_DTPOFF32, BFD_RELOC_386_TLS_TPOFF32, BFD_RELOC_386_TLS_GOTDESC, BFD_RELOC_386_TLS_DESC_CALL, BFD_RELOC_386_TLS_DESC, /* x86-64/elf relocations */ BFD_RELOC_X86_64_GOT32, BFD_RELOC_X86_64_PLT32, BFD_RELOC_X86_64_COPY, BFD_RELOC_X86_64_GLOB_DAT, BFD_RELOC_X86_64_JUMP_SLOT, BFD_RELOC_X86_64_RELATIVE, BFD_RELOC_X86_64_GOTPCREL, BFD_RELOC_X86_64_32S, BFD_RELOC_X86_64_DTPMOD64, BFD_RELOC_X86_64_DTPOFF64, BFD_RELOC_X86_64_TPOFF64, BFD_RELOC_X86_64_TLSGD, BFD_RELOC_X86_64_TLSLD, BFD_RELOC_X86_64_DTPOFF32, BFD_RELOC_X86_64_GOTTPOFF, 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, /* ns32k relocations */ BFD_RELOC_NS32K_IMM_8, BFD_RELOC_NS32K_IMM_16, BFD_RELOC_NS32K_IMM_32, BFD_RELOC_NS32K_IMM_8_PCREL, BFD_RELOC_NS32K_IMM_16_PCREL, BFD_RELOC_NS32K_IMM_32_PCREL, BFD_RELOC_NS32K_DISP_8, BFD_RELOC_NS32K_DISP_16, BFD_RELOC_NS32K_DISP_32, BFD_RELOC_NS32K_DISP_8_PCREL, BFD_RELOC_NS32K_DISP_16_PCREL, BFD_RELOC_NS32K_DISP_32_PCREL, /* PDP11 relocations */ BFD_RELOC_PDP11_DISP_8_PCREL, BFD_RELOC_PDP11_DISP_6_PCREL, /* Picojava relocs. Not all of these appear in object files. */ BFD_RELOC_PJ_CODE_HI16, BFD_RELOC_PJ_CODE_LO16, BFD_RELOC_PJ_CODE_DIR16, BFD_RELOC_PJ_CODE_DIR32, BFD_RELOC_PJ_CODE_REL16, BFD_RELOC_PJ_CODE_REL32, /* Power(rs6000) and PowerPC relocations. */ BFD_RELOC_PPC_B26, BFD_RELOC_PPC_BA26, BFD_RELOC_PPC_TOC16, BFD_RELOC_PPC_B16, BFD_RELOC_PPC_B16_BRTAKEN, BFD_RELOC_PPC_B16_BRNTAKEN, BFD_RELOC_PPC_BA16, BFD_RELOC_PPC_BA16_BRTAKEN, BFD_RELOC_PPC_BA16_BRNTAKEN, BFD_RELOC_PPC_COPY, BFD_RELOC_PPC_GLOB_DAT, BFD_RELOC_PPC_JMP_SLOT, BFD_RELOC_PPC_RELATIVE, BFD_RELOC_PPC_LOCAL24PC, BFD_RELOC_PPC_EMB_NADDR32, BFD_RELOC_PPC_EMB_NADDR16, BFD_RELOC_PPC_EMB_NADDR16_LO, BFD_RELOC_PPC_EMB_NADDR16_HI, BFD_RELOC_PPC_EMB_NADDR16_HA, BFD_RELOC_PPC_EMB_SDAI16, BFD_RELOC_PPC_EMB_SDA2I16, BFD_RELOC_PPC_EMB_SDA2REL, BFD_RELOC_PPC_EMB_SDA21, BFD_RELOC_PPC_EMB_MRKREF, BFD_RELOC_PPC_EMB_RELSEC16, BFD_RELOC_PPC_EMB_RELST_LO, BFD_RELOC_PPC_EMB_RELST_HI, BFD_RELOC_PPC_EMB_RELST_HA, BFD_RELOC_PPC_EMB_BIT_FLD, BFD_RELOC_PPC_EMB_RELSDA, BFD_RELOC_PPC64_HIGHER, BFD_RELOC_PPC64_HIGHER_S, BFD_RELOC_PPC64_HIGHEST, BFD_RELOC_PPC64_HIGHEST_S, BFD_RELOC_PPC64_TOC16_LO, BFD_RELOC_PPC64_TOC16_HI, BFD_RELOC_PPC64_TOC16_HA, BFD_RELOC_PPC64_TOC, BFD_RELOC_PPC64_PLTGOT16, BFD_RELOC_PPC64_PLTGOT16_LO, BFD_RELOC_PPC64_PLTGOT16_HI, BFD_RELOC_PPC64_PLTGOT16_HA, BFD_RELOC_PPC64_ADDR16_DS, BFD_RELOC_PPC64_ADDR16_LO_DS, BFD_RELOC_PPC64_GOT16_DS, BFD_RELOC_PPC64_GOT16_LO_DS, BFD_RELOC_PPC64_PLT16_LO_DS, BFD_RELOC_PPC64_SECTOFF_DS, BFD_RELOC_PPC64_SECTOFF_LO_DS, BFD_RELOC_PPC64_TOC16_DS, BFD_RELOC_PPC64_TOC16_LO_DS, BFD_RELOC_PPC64_PLTGOT16_DS, BFD_RELOC_PPC64_PLTGOT16_LO_DS, /* PowerPC and PowerPC64 thread-local storage relocations. */ BFD_RELOC_PPC_TLS, + BFD_RELOC_PPC_TLSGD, + BFD_RELOC_PPC_TLSLD, BFD_RELOC_PPC_DTPMOD, BFD_RELOC_PPC_TPREL16, BFD_RELOC_PPC_TPREL16_LO, BFD_RELOC_PPC_TPREL16_HI, BFD_RELOC_PPC_TPREL16_HA, BFD_RELOC_PPC_TPREL, BFD_RELOC_PPC_DTPREL16, BFD_RELOC_PPC_DTPREL16_LO, BFD_RELOC_PPC_DTPREL16_HI, BFD_RELOC_PPC_DTPREL16_HA, BFD_RELOC_PPC_DTPREL, BFD_RELOC_PPC_GOT_TLSGD16, BFD_RELOC_PPC_GOT_TLSGD16_LO, BFD_RELOC_PPC_GOT_TLSGD16_HI, BFD_RELOC_PPC_GOT_TLSGD16_HA, BFD_RELOC_PPC_GOT_TLSLD16, BFD_RELOC_PPC_GOT_TLSLD16_LO, BFD_RELOC_PPC_GOT_TLSLD16_HI, BFD_RELOC_PPC_GOT_TLSLD16_HA, BFD_RELOC_PPC_GOT_TPREL16, BFD_RELOC_PPC_GOT_TPREL16_LO, BFD_RELOC_PPC_GOT_TPREL16_HI, BFD_RELOC_PPC_GOT_TPREL16_HA, BFD_RELOC_PPC_GOT_DTPREL16, BFD_RELOC_PPC_GOT_DTPREL16_LO, BFD_RELOC_PPC_GOT_DTPREL16_HI, BFD_RELOC_PPC_GOT_DTPREL16_HA, BFD_RELOC_PPC64_TPREL16_DS, BFD_RELOC_PPC64_TPREL16_LO_DS, BFD_RELOC_PPC64_TPREL16_HIGHER, BFD_RELOC_PPC64_TPREL16_HIGHERA, BFD_RELOC_PPC64_TPREL16_HIGHEST, BFD_RELOC_PPC64_TPREL16_HIGHESTA, BFD_RELOC_PPC64_DTPREL16_DS, BFD_RELOC_PPC64_DTPREL16_LO_DS, BFD_RELOC_PPC64_DTPREL16_HIGHER, BFD_RELOC_PPC64_DTPREL16_HIGHERA, BFD_RELOC_PPC64_DTPREL16_HIGHEST, BFD_RELOC_PPC64_DTPREL16_HIGHESTA, /* IBM 370/390 relocations */ BFD_RELOC_I370_D12, /* The type of reloc used to build a constructor table - at the moment probably a 32 bit wide absolute relocation, but the target can choose. It generally does map to one of the other relocation types. */ BFD_RELOC_CTOR, /* ARM 26 bit pc-relative branch. The lowest two bits must be zero and are not stored in the instruction. */ BFD_RELOC_ARM_PCREL_BRANCH, /* ARM 26 bit pc-relative branch. The lowest bit must be zero and is not stored in the instruction. The 2nd lowest bit comes from a 1 bit field in the instruction. */ BFD_RELOC_ARM_PCREL_BLX, /* Thumb 22 bit pc-relative branch. The lowest bit must be zero and is not stored in the instruction. The 2nd lowest bit comes from a 1 bit field in the instruction. */ BFD_RELOC_THUMB_PCREL_BLX, /* ARM 26-bit pc-relative branch for an unconditional BL or BLX instruction. */ BFD_RELOC_ARM_PCREL_CALL, /* ARM 26-bit pc-relative branch for B or conditional BL instruction. */ BFD_RELOC_ARM_PCREL_JUMP, /* Thumb 7-, 9-, 12-, 20-, 23-, and 25-bit pc-relative branches. The lowest bit must be zero and is not stored in the instruction. Note that the corresponding ELF R_ARM_THM_JUMPnn constant has an "nn" one smaller in all cases. Note further that BRANCH23 corresponds to R_ARM_THM_CALL. */ BFD_RELOC_THUMB_PCREL_BRANCH7, BFD_RELOC_THUMB_PCREL_BRANCH9, BFD_RELOC_THUMB_PCREL_BRANCH12, BFD_RELOC_THUMB_PCREL_BRANCH20, BFD_RELOC_THUMB_PCREL_BRANCH23, BFD_RELOC_THUMB_PCREL_BRANCH25, /* 12-bit immediate offset, used in ARM-format ldr and str instructions. */ BFD_RELOC_ARM_OFFSET_IMM, /* 5-bit immediate offset, used in Thumb-format ldr and str instructions. */ BFD_RELOC_ARM_THUMB_OFFSET, /* Pc-relative or absolute relocation depending on target. Used for entries in .init_array sections. */ BFD_RELOC_ARM_TARGET1, /* Read-only segment base relative address. */ BFD_RELOC_ARM_ROSEGREL32, /* Data segment base relative address. */ BFD_RELOC_ARM_SBREL32, /* This reloc is used for references to RTTI data from exception handling tables. The actual definition depends on the target. It may be a pc-relative or some form of GOT-indirect relocation. */ BFD_RELOC_ARM_TARGET2, /* 31-bit PC relative address. */ BFD_RELOC_ARM_PREL31, /* Low and High halfword relocations for MOVW and MOVT instructions. */ BFD_RELOC_ARM_MOVW, BFD_RELOC_ARM_MOVT, BFD_RELOC_ARM_MOVW_PCREL, BFD_RELOC_ARM_MOVT_PCREL, BFD_RELOC_ARM_THUMB_MOVW, BFD_RELOC_ARM_THUMB_MOVT, BFD_RELOC_ARM_THUMB_MOVW_PCREL, BFD_RELOC_ARM_THUMB_MOVT_PCREL, /* Relocations for setting up GOTs and PLTs for shared libraries. */ BFD_RELOC_ARM_JUMP_SLOT, BFD_RELOC_ARM_GLOB_DAT, BFD_RELOC_ARM_GOT32, BFD_RELOC_ARM_PLT32, BFD_RELOC_ARM_RELATIVE, BFD_RELOC_ARM_GOTOFF, BFD_RELOC_ARM_GOTPC, /* ARM thread-local storage relocations. */ BFD_RELOC_ARM_TLS_GD32, BFD_RELOC_ARM_TLS_LDO32, BFD_RELOC_ARM_TLS_LDM32, BFD_RELOC_ARM_TLS_DTPOFF32, BFD_RELOC_ARM_TLS_DTPMOD32, BFD_RELOC_ARM_TLS_TPOFF32, BFD_RELOC_ARM_TLS_IE32, BFD_RELOC_ARM_TLS_LE32, /* ARM group relocations. */ BFD_RELOC_ARM_ALU_PC_G0_NC, BFD_RELOC_ARM_ALU_PC_G0, BFD_RELOC_ARM_ALU_PC_G1_NC, BFD_RELOC_ARM_ALU_PC_G1, BFD_RELOC_ARM_ALU_PC_G2, BFD_RELOC_ARM_LDR_PC_G0, BFD_RELOC_ARM_LDR_PC_G1, BFD_RELOC_ARM_LDR_PC_G2, BFD_RELOC_ARM_LDRS_PC_G0, BFD_RELOC_ARM_LDRS_PC_G1, BFD_RELOC_ARM_LDRS_PC_G2, BFD_RELOC_ARM_LDC_PC_G0, BFD_RELOC_ARM_LDC_PC_G1, BFD_RELOC_ARM_LDC_PC_G2, BFD_RELOC_ARM_ALU_SB_G0_NC, BFD_RELOC_ARM_ALU_SB_G0, BFD_RELOC_ARM_ALU_SB_G1_NC, BFD_RELOC_ARM_ALU_SB_G1, BFD_RELOC_ARM_ALU_SB_G2, BFD_RELOC_ARM_LDR_SB_G0, BFD_RELOC_ARM_LDR_SB_G1, BFD_RELOC_ARM_LDR_SB_G2, BFD_RELOC_ARM_LDRS_SB_G0, BFD_RELOC_ARM_LDRS_SB_G1, BFD_RELOC_ARM_LDRS_SB_G2, BFD_RELOC_ARM_LDC_SB_G0, BFD_RELOC_ARM_LDC_SB_G1, BFD_RELOC_ARM_LDC_SB_G2, /* These relocs are only used within the ARM assembler. They are not (at present) written to any object files. */ BFD_RELOC_ARM_IMMEDIATE, BFD_RELOC_ARM_ADRL_IMMEDIATE, BFD_RELOC_ARM_T32_IMMEDIATE, BFD_RELOC_ARM_T32_ADD_IMM, BFD_RELOC_ARM_T32_IMM12, BFD_RELOC_ARM_T32_ADD_PC12, BFD_RELOC_ARM_SHIFT_IMM, BFD_RELOC_ARM_SMC, BFD_RELOC_ARM_SWI, BFD_RELOC_ARM_MULTI, BFD_RELOC_ARM_CP_OFF_IMM, BFD_RELOC_ARM_CP_OFF_IMM_S2, BFD_RELOC_ARM_T32_CP_OFF_IMM, BFD_RELOC_ARM_T32_CP_OFF_IMM_S2, BFD_RELOC_ARM_ADR_IMM, BFD_RELOC_ARM_LDR_IMM, BFD_RELOC_ARM_LITERAL, BFD_RELOC_ARM_IN_POOL, BFD_RELOC_ARM_OFFSET_IMM8, BFD_RELOC_ARM_T32_OFFSET_U8, BFD_RELOC_ARM_T32_OFFSET_IMM, BFD_RELOC_ARM_HWLITERAL, BFD_RELOC_ARM_THUMB_ADD, BFD_RELOC_ARM_THUMB_IMM, BFD_RELOC_ARM_THUMB_SHIFT, /* Renesas / SuperH SH relocs. Not all of these appear in object files. */ BFD_RELOC_SH_PCDISP8BY2, BFD_RELOC_SH_PCDISP12BY2, BFD_RELOC_SH_IMM3, BFD_RELOC_SH_IMM3U, BFD_RELOC_SH_DISP12, BFD_RELOC_SH_DISP12BY2, BFD_RELOC_SH_DISP12BY4, BFD_RELOC_SH_DISP12BY8, BFD_RELOC_SH_DISP20, BFD_RELOC_SH_DISP20BY8, BFD_RELOC_SH_IMM4, BFD_RELOC_SH_IMM4BY2, BFD_RELOC_SH_IMM4BY4, BFD_RELOC_SH_IMM8, BFD_RELOC_SH_IMM8BY2, BFD_RELOC_SH_IMM8BY4, BFD_RELOC_SH_PCRELIMM8BY2, BFD_RELOC_SH_PCRELIMM8BY4, BFD_RELOC_SH_SWITCH16, BFD_RELOC_SH_SWITCH32, BFD_RELOC_SH_USES, BFD_RELOC_SH_COUNT, BFD_RELOC_SH_ALIGN, BFD_RELOC_SH_CODE, BFD_RELOC_SH_DATA, BFD_RELOC_SH_LABEL, BFD_RELOC_SH_LOOP_START, BFD_RELOC_SH_LOOP_END, BFD_RELOC_SH_COPY, BFD_RELOC_SH_GLOB_DAT, BFD_RELOC_SH_JMP_SLOT, BFD_RELOC_SH_RELATIVE, BFD_RELOC_SH_GOTPC, BFD_RELOC_SH_GOT_LOW16, BFD_RELOC_SH_GOT_MEDLOW16, BFD_RELOC_SH_GOT_MEDHI16, BFD_RELOC_SH_GOT_HI16, BFD_RELOC_SH_GOTPLT_LOW16, BFD_RELOC_SH_GOTPLT_MEDLOW16, BFD_RELOC_SH_GOTPLT_MEDHI16, BFD_RELOC_SH_GOTPLT_HI16, BFD_RELOC_SH_PLT_LOW16, BFD_RELOC_SH_PLT_MEDLOW16, BFD_RELOC_SH_PLT_MEDHI16, BFD_RELOC_SH_PLT_HI16, BFD_RELOC_SH_GOTOFF_LOW16, BFD_RELOC_SH_GOTOFF_MEDLOW16, BFD_RELOC_SH_GOTOFF_MEDHI16, BFD_RELOC_SH_GOTOFF_HI16, BFD_RELOC_SH_GOTPC_LOW16, BFD_RELOC_SH_GOTPC_MEDLOW16, BFD_RELOC_SH_GOTPC_MEDHI16, BFD_RELOC_SH_GOTPC_HI16, BFD_RELOC_SH_COPY64, BFD_RELOC_SH_GLOB_DAT64, BFD_RELOC_SH_JMP_SLOT64, BFD_RELOC_SH_RELATIVE64, BFD_RELOC_SH_GOT10BY4, BFD_RELOC_SH_GOT10BY8, BFD_RELOC_SH_GOTPLT10BY4, BFD_RELOC_SH_GOTPLT10BY8, BFD_RELOC_SH_GOTPLT32, BFD_RELOC_SH_SHMEDIA_CODE, BFD_RELOC_SH_IMMU5, BFD_RELOC_SH_IMMS6, BFD_RELOC_SH_IMMS6BY32, BFD_RELOC_SH_IMMU6, BFD_RELOC_SH_IMMS10, BFD_RELOC_SH_IMMS10BY2, BFD_RELOC_SH_IMMS10BY4, BFD_RELOC_SH_IMMS10BY8, BFD_RELOC_SH_IMMS16, BFD_RELOC_SH_IMMU16, BFD_RELOC_SH_IMM_LOW16, BFD_RELOC_SH_IMM_LOW16_PCREL, BFD_RELOC_SH_IMM_MEDLOW16, BFD_RELOC_SH_IMM_MEDLOW16_PCREL, BFD_RELOC_SH_IMM_MEDHI16, BFD_RELOC_SH_IMM_MEDHI16_PCREL, BFD_RELOC_SH_IMM_HI16, BFD_RELOC_SH_IMM_HI16_PCREL, BFD_RELOC_SH_PT_16, BFD_RELOC_SH_TLS_GD_32, BFD_RELOC_SH_TLS_LD_32, BFD_RELOC_SH_TLS_LDO_32, BFD_RELOC_SH_TLS_IE_32, BFD_RELOC_SH_TLS_LE_32, BFD_RELOC_SH_TLS_DTPMOD32, BFD_RELOC_SH_TLS_DTPOFF32, BFD_RELOC_SH_TLS_TPOFF32, /* ARC Cores relocs. ARC 22 bit pc-relative branch. The lowest two bits must be zero and are not stored in the instruction. The high 20 bits are installed in bits 26 through 7 of the instruction. */ BFD_RELOC_ARC_B22_PCREL, /* ARC 26 bit absolute branch. The lowest two bits must be zero and are not stored in the instruction. The high 24 bits are installed in bits 23 through 0. */ BFD_RELOC_ARC_B26, /* ADI Blackfin 16 bit immediate absolute reloc. */ BFD_RELOC_BFIN_16_IMM, /* ADI Blackfin 16 bit immediate absolute reloc higher 16 bits. */ BFD_RELOC_BFIN_16_HIGH, /* ADI Blackfin 'a' part of LSETUP. */ BFD_RELOC_BFIN_4_PCREL, /* ADI Blackfin. */ BFD_RELOC_BFIN_5_PCREL, /* ADI Blackfin 16 bit immediate absolute reloc lower 16 bits. */ BFD_RELOC_BFIN_16_LOW, /* ADI Blackfin. */ BFD_RELOC_BFIN_10_PCREL, /* ADI Blackfin 'b' part of LSETUP. */ BFD_RELOC_BFIN_11_PCREL, /* ADI Blackfin. */ BFD_RELOC_BFIN_12_PCREL_JUMP, /* ADI Blackfin Short jump, pcrel. */ BFD_RELOC_BFIN_12_PCREL_JUMP_S, /* ADI Blackfin Call.x not implemented. */ BFD_RELOC_BFIN_24_PCREL_CALL_X, /* 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, /* ADI Blackfin PLTPC relocation. */ BFD_RELOC_BFIN_PLTPC, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_PUSH, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_CONST, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_ADD, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_SUB, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_MULT, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_DIV, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_MOD, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_LSHIFT, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_RSHIFT, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_AND, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_OR, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_XOR, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_LAND, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_LOR, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_LEN, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_NEG, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_COMP, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_PAGE, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_HWPAGE, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_ADDR, /* Mitsubishi D10V relocs. This is a 10-bit reloc with the right 2 bits assumed to be 0. */ BFD_RELOC_D10V_10_PCREL_R, /* Mitsubishi D10V relocs. This is a 10-bit reloc with the right 2 bits assumed to be 0. This is the same as the previous reloc except it is in the left container, i.e., shifted left 15 bits. */ BFD_RELOC_D10V_10_PCREL_L, /* This is an 18-bit reloc with the right 2 bits assumed to be 0. */ BFD_RELOC_D10V_18, /* This is an 18-bit reloc with the right 2 bits assumed to be 0. */ BFD_RELOC_D10V_18_PCREL, /* Mitsubishi D30V relocs. This is a 6-bit absolute reloc. */ BFD_RELOC_D30V_6, /* This is a 6-bit pc-relative reloc with the right 3 bits assumed to be 0. */ BFD_RELOC_D30V_9_PCREL, /* This is a 6-bit pc-relative reloc with the right 3 bits assumed to be 0. Same as the previous reloc but on the right side of the container. */ BFD_RELOC_D30V_9_PCREL_R, /* This is a 12-bit absolute reloc with the right 3 bitsassumed to be 0. */ BFD_RELOC_D30V_15, /* This is a 12-bit pc-relative reloc with the right 3 bits assumed to be 0. */ BFD_RELOC_D30V_15_PCREL, /* This is a 12-bit pc-relative reloc with the right 3 bits assumed to be 0. Same as the previous reloc but on the right side of the container. */ BFD_RELOC_D30V_15_PCREL_R, /* This is an 18-bit absolute reloc with the right 3 bits assumed to be 0. */ BFD_RELOC_D30V_21, /* This is an 18-bit pc-relative reloc with the right 3 bits assumed to be 0. */ BFD_RELOC_D30V_21_PCREL, /* This is an 18-bit pc-relative reloc with the right 3 bits assumed to be 0. Same as the previous reloc but on the right side of the container. */ BFD_RELOC_D30V_21_PCREL_R, /* This is a 32-bit absolute reloc. */ BFD_RELOC_D30V_32, /* This is a 32-bit pc-relative reloc. */ BFD_RELOC_D30V_32_PCREL, /* DLX relocs */ BFD_RELOC_DLX_HI16_S, /* DLX relocs */ BFD_RELOC_DLX_LO16, /* DLX relocs */ BFD_RELOC_DLX_JMP26, /* Renesas M16C/M32C Relocations. */ BFD_RELOC_M32C_HI8, BFD_RELOC_M32C_RL_JUMP, BFD_RELOC_M32C_RL_1ADDR, BFD_RELOC_M32C_RL_2ADDR, /* Renesas M32R (formerly Mitsubishi M32R) relocs. This is a 24 bit absolute address. */ BFD_RELOC_M32R_24, /* This is a 10-bit pc-relative reloc with the right 2 bits assumed to be 0. */ BFD_RELOC_M32R_10_PCREL, /* This is an 18-bit reloc with the right 2 bits assumed to be 0. */ BFD_RELOC_M32R_18_PCREL, /* This is a 26-bit reloc with the right 2 bits assumed to be 0. */ BFD_RELOC_M32R_26_PCREL, /* This is a 16-bit reloc containing the high 16 bits of an address used when the lower 16 bits are treated as unsigned. */ BFD_RELOC_M32R_HI16_ULO, /* This is a 16-bit reloc containing the high 16 bits of an address used when the lower 16 bits are treated as signed. */ BFD_RELOC_M32R_HI16_SLO, /* This is a 16-bit reloc containing the lower 16 bits of an address. */ BFD_RELOC_M32R_LO16, /* This is a 16-bit reloc containing the small data area offset for use in add3, load, and store instructions. */ BFD_RELOC_M32R_SDA16, /* For PIC. */ BFD_RELOC_M32R_GOT24, BFD_RELOC_M32R_26_PLTREL, BFD_RELOC_M32R_COPY, BFD_RELOC_M32R_GLOB_DAT, BFD_RELOC_M32R_JMP_SLOT, BFD_RELOC_M32R_RELATIVE, BFD_RELOC_M32R_GOTOFF, BFD_RELOC_M32R_GOTOFF_HI_ULO, BFD_RELOC_M32R_GOTOFF_HI_SLO, BFD_RELOC_M32R_GOTOFF_LO, BFD_RELOC_M32R_GOTPC24, BFD_RELOC_M32R_GOT16_HI_ULO, BFD_RELOC_M32R_GOT16_HI_SLO, BFD_RELOC_M32R_GOT16_LO, BFD_RELOC_M32R_GOTPC_HI_ULO, BFD_RELOC_M32R_GOTPC_HI_SLO, BFD_RELOC_M32R_GOTPC_LO, /* This is a 9-bit reloc */ BFD_RELOC_V850_9_PCREL, /* This is a 22-bit reloc */ BFD_RELOC_V850_22_PCREL, /* This is a 16 bit offset from the short data area pointer. */ BFD_RELOC_V850_SDA_16_16_OFFSET, /* This is a 16 bit offset (of which only 15 bits are used) from the short data area pointer. */ BFD_RELOC_V850_SDA_15_16_OFFSET, /* This is a 16 bit offset from the zero data area pointer. */ BFD_RELOC_V850_ZDA_16_16_OFFSET, /* This is a 16 bit offset (of which only 15 bits are used) from the zero data area pointer. */ BFD_RELOC_V850_ZDA_15_16_OFFSET, /* This is an 8 bit offset (of which only 6 bits are used) from the tiny data area pointer. */ BFD_RELOC_V850_TDA_6_8_OFFSET, /* This is an 8bit offset (of which only 7 bits are used) from the tiny data area pointer. */ BFD_RELOC_V850_TDA_7_8_OFFSET, /* This is a 7 bit offset from the tiny data area pointer. */ BFD_RELOC_V850_TDA_7_7_OFFSET, /* This is a 16 bit offset from the tiny data area pointer. */ BFD_RELOC_V850_TDA_16_16_OFFSET, /* This is a 5 bit offset (of which only 4 bits are used) from the tiny data area pointer. */ BFD_RELOC_V850_TDA_4_5_OFFSET, /* This is a 4 bit offset from the tiny data area pointer. */ BFD_RELOC_V850_TDA_4_4_OFFSET, /* This is a 16 bit offset from the short data area pointer, with the bits placed non-contiguously in the instruction. */ BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET, /* This is a 16 bit offset from the zero data area pointer, with the bits placed non-contiguously in the instruction. */ BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET, /* This is a 6 bit offset from the call table base pointer. */ BFD_RELOC_V850_CALLT_6_7_OFFSET, /* This is a 16 bit offset from the call table base pointer. */ BFD_RELOC_V850_CALLT_16_16_OFFSET, /* Used for relaxing indirect function calls. */ BFD_RELOC_V850_LONGCALL, /* Used for relaxing indirect jumps. */ BFD_RELOC_V850_LONGJUMP, /* Used to maintain alignment whilst relaxing. */ BFD_RELOC_V850_ALIGN, /* This is a variation of BFD_RELOC_LO16 that can be used in v850e ld.bu instructions. */ BFD_RELOC_V850_LO16_SPLIT_OFFSET, /* This is a 32bit pcrel reloc for the mn10300, offset by two bytes in the instruction. */ BFD_RELOC_MN10300_32_PCREL, /* This is a 16bit pcrel reloc for the mn10300, offset by two bytes in the instruction. */ BFD_RELOC_MN10300_16_PCREL, /* This is a 8bit DP reloc for the tms320c30, where the most significant 8 bits of a 24 bit word are placed into the least significant 8 bits of the opcode. */ BFD_RELOC_TIC30_LDP, /* This is a 7bit reloc for the tms320c54x, where the least significant 7 bits of a 16 bit word are placed into the least significant 7 bits of the opcode. */ BFD_RELOC_TIC54X_PARTLS7, /* This is a 9bit DP reloc for the tms320c54x, where the most significant 9 bits of a 16 bit word are placed into the least significant 9 bits of the opcode. */ BFD_RELOC_TIC54X_PARTMS9, /* This is an extended address 23-bit reloc for the tms320c54x. */ BFD_RELOC_TIC54X_23, /* This is a 16-bit reloc for the tms320c54x, where the least significant 16 bits of a 23-bit extended address are placed into the opcode. */ BFD_RELOC_TIC54X_16_OF_23, /* This is a reloc for the tms320c54x, where the most significant 7 bits of a 23-bit extended address are placed into the opcode. */ BFD_RELOC_TIC54X_MS7_OF_23, /* This is a 48 bit reloc for the FR30 that stores 32 bits. */ BFD_RELOC_FR30_48, /* This is a 32 bit reloc for the FR30 that stores 20 bits split up into two sections. */ BFD_RELOC_FR30_20, /* This is a 16 bit reloc for the FR30 that stores a 6 bit word offset in 4 bits. */ BFD_RELOC_FR30_6_IN_4, /* This is a 16 bit reloc for the FR30 that stores an 8 bit byte offset into 8 bits. */ BFD_RELOC_FR30_8_IN_8, /* This is a 16 bit reloc for the FR30 that stores a 9 bit short offset into 8 bits. */ BFD_RELOC_FR30_9_IN_8, /* This is a 16 bit reloc for the FR30 that stores a 10 bit word offset into 8 bits. */ BFD_RELOC_FR30_10_IN_8, /* This is a 16 bit reloc for the FR30 that stores a 9 bit pc relative short offset into 8 bits. */ BFD_RELOC_FR30_9_PCREL, /* This is a 16 bit reloc for the FR30 that stores a 12 bit pc relative short offset into 11 bits. */ BFD_RELOC_FR30_12_PCREL, /* Motorola Mcore relocations. */ BFD_RELOC_MCORE_PCREL_IMM8BY4, BFD_RELOC_MCORE_PCREL_IMM11BY2, BFD_RELOC_MCORE_PCREL_IMM4BY2, BFD_RELOC_MCORE_PCREL_32, BFD_RELOC_MCORE_PCREL_JSR_IMM11BY2, BFD_RELOC_MCORE_RVA, /* Toshiba Media Processor Relocations. */ BFD_RELOC_MEP_8, BFD_RELOC_MEP_16, BFD_RELOC_MEP_32, BFD_RELOC_MEP_PCREL8A2, BFD_RELOC_MEP_PCREL12A2, BFD_RELOC_MEP_PCREL17A2, BFD_RELOC_MEP_PCREL24A2, BFD_RELOC_MEP_PCABS24A2, BFD_RELOC_MEP_LOW16, BFD_RELOC_MEP_HI16U, BFD_RELOC_MEP_HI16S, BFD_RELOC_MEP_GPREL, BFD_RELOC_MEP_TPREL, BFD_RELOC_MEP_TPREL7, BFD_RELOC_MEP_TPREL7A2, BFD_RELOC_MEP_TPREL7A4, BFD_RELOC_MEP_UIMM24, BFD_RELOC_MEP_ADDR24A4, BFD_RELOC_MEP_GNU_VTINHERIT, BFD_RELOC_MEP_GNU_VTENTRY, /* These are relocations for the GETA instruction. */ BFD_RELOC_MMIX_GETA, BFD_RELOC_MMIX_GETA_1, BFD_RELOC_MMIX_GETA_2, BFD_RELOC_MMIX_GETA_3, /* These are relocations for a conditional branch instruction. */ BFD_RELOC_MMIX_CBRANCH, BFD_RELOC_MMIX_CBRANCH_J, BFD_RELOC_MMIX_CBRANCH_1, BFD_RELOC_MMIX_CBRANCH_2, BFD_RELOC_MMIX_CBRANCH_3, /* These are relocations for the PUSHJ instruction. */ BFD_RELOC_MMIX_PUSHJ, BFD_RELOC_MMIX_PUSHJ_1, BFD_RELOC_MMIX_PUSHJ_2, BFD_RELOC_MMIX_PUSHJ_3, BFD_RELOC_MMIX_PUSHJ_STUBBABLE, /* These are relocations for the JMP instruction. */ BFD_RELOC_MMIX_JMP, BFD_RELOC_MMIX_JMP_1, BFD_RELOC_MMIX_JMP_2, BFD_RELOC_MMIX_JMP_3, /* This is a relocation for a relative address as in a GETA instruction or a branch. */ BFD_RELOC_MMIX_ADDR19, /* This is a relocation for a relative address as in a JMP instruction. */ BFD_RELOC_MMIX_ADDR27, /* This is a relocation for an instruction field that may be a general register or a value 0..255. */ BFD_RELOC_MMIX_REG_OR_BYTE, /* This is a relocation for an instruction field that may be a general register. */ BFD_RELOC_MMIX_REG, /* This is a relocation for two instruction fields holding a register and an offset, the equivalent of the relocation. */ BFD_RELOC_MMIX_BASE_PLUS_OFFSET, /* This relocation is an assertion that the expression is not allocated as a global register. It does not modify contents. */ BFD_RELOC_MMIX_LOCAL, /* This is a 16 bit reloc for the AVR that stores 8 bit pc relative short offset into 7 bits. */ BFD_RELOC_AVR_7_PCREL, /* This is a 16 bit reloc for the AVR that stores 13 bit pc relative short offset into 12 bits. */ BFD_RELOC_AVR_13_PCREL, /* This is a 16 bit reloc for the AVR that stores 17 bit value (usually program memory address) into 16 bits. */ BFD_RELOC_AVR_16_PM, /* This is a 16 bit reloc for the AVR that stores 8 bit value (usually data memory address) into 8 bit immediate value of LDI insn. */ BFD_RELOC_AVR_LO8_LDI, /* This is a 16 bit reloc for the AVR that stores 8 bit value (high 8 bit of data memory address) into 8 bit immediate value of LDI insn. */ BFD_RELOC_AVR_HI8_LDI, /* This is a 16 bit reloc for the AVR that stores 8 bit value (most high 8 bit of program memory address) into 8 bit immediate value of LDI insn. */ BFD_RELOC_AVR_HH8_LDI, /* This is a 16 bit reloc for the AVR that stores 8 bit value (most high 8 bit of 32 bit value) into 8 bit immediate value of LDI insn. */ BFD_RELOC_AVR_MS8_LDI, /* This is a 16 bit reloc for the AVR that stores negated 8 bit value (usually data memory address) into 8 bit immediate value of SUBI insn. */ BFD_RELOC_AVR_LO8_LDI_NEG, /* This is a 16 bit reloc for the AVR that stores negated 8 bit value (high 8 bit of data memory address) into 8 bit immediate value of SUBI insn. */ BFD_RELOC_AVR_HI8_LDI_NEG, /* This is a 16 bit reloc for the AVR that stores negated 8 bit value (most high 8 bit of program memory address) into 8 bit immediate value of LDI or SUBI insn. */ BFD_RELOC_AVR_HH8_LDI_NEG, /* This is a 16 bit reloc for the AVR that stores negated 8 bit value (msb of 32 bit value) into 8 bit immediate value of LDI insn. */ BFD_RELOC_AVR_MS8_LDI_NEG, /* This is a 16 bit reloc for the AVR that stores 8 bit value (usually command address) into 8 bit immediate value of LDI insn. */ BFD_RELOC_AVR_LO8_LDI_PM, /* This is a 16 bit reloc for the AVR that stores 8 bit value (command address) into 8 bit immediate value of LDI insn. If the address is beyond the 128k boundary, the linker inserts a jump stub for this reloc in the lower 128k. */ BFD_RELOC_AVR_LO8_LDI_GS, /* This is a 16 bit reloc for the AVR that stores 8 bit value (high 8 bit of command address) into 8 bit immediate value of LDI insn. */ BFD_RELOC_AVR_HI8_LDI_PM, /* This is a 16 bit reloc for the AVR that stores 8 bit value (high 8 bit of command address) into 8 bit immediate value of LDI insn. If the address is beyond the 128k boundary, the linker inserts a jump stub for this reloc below 128k. */ BFD_RELOC_AVR_HI8_LDI_GS, /* This is a 16 bit reloc for the AVR that stores 8 bit value (most high 8 bit of command address) into 8 bit immediate value of LDI insn. */ BFD_RELOC_AVR_HH8_LDI_PM, /* This is a 16 bit reloc for the AVR that stores negated 8 bit value (usually command address) into 8 bit immediate value of SUBI insn. */ BFD_RELOC_AVR_LO8_LDI_PM_NEG, /* This is a 16 bit reloc for the AVR that stores negated 8 bit value (high 8 bit of 16 bit command address) into 8 bit immediate value of SUBI insn. */ BFD_RELOC_AVR_HI8_LDI_PM_NEG, /* This is a 16 bit reloc for the AVR that stores negated 8 bit value (high 6 bit of 22 bit command address) into 8 bit immediate value of SUBI insn. */ BFD_RELOC_AVR_HH8_LDI_PM_NEG, /* This is a 32 bit reloc for the AVR that stores 23 bit value into 22 bits. */ BFD_RELOC_AVR_CALL, /* This is a 16 bit reloc for the AVR that stores all needed bits for absolute addressing with ldi with overflow check to linktime */ BFD_RELOC_AVR_LDI, /* This is a 6 bit reloc for the AVR that stores offset for ldd/std instructions */ BFD_RELOC_AVR_6, /* This is a 6 bit reloc for the AVR that stores offset for adiw/sbiw instructions */ BFD_RELOC_AVR_6_ADIW, /* Direct 12 bit. */ BFD_RELOC_390_12, /* 12 bit GOT offset. */ BFD_RELOC_390_GOT12, /* 32 bit PC relative PLT address. */ BFD_RELOC_390_PLT32, /* Copy symbol at runtime. */ BFD_RELOC_390_COPY, /* Create GOT entry. */ BFD_RELOC_390_GLOB_DAT, /* Create PLT entry. */ BFD_RELOC_390_JMP_SLOT, /* Adjust by program base. */ BFD_RELOC_390_RELATIVE, /* 32 bit PC relative offset to GOT. */ BFD_RELOC_390_GOTPC, /* 16 bit GOT offset. */ BFD_RELOC_390_GOT16, /* PC relative 16 bit shifted by 1. */ BFD_RELOC_390_PC16DBL, /* 16 bit PC rel. PLT shifted by 1. */ BFD_RELOC_390_PLT16DBL, /* PC relative 32 bit shifted by 1. */ BFD_RELOC_390_PC32DBL, /* 32 bit PC rel. PLT shifted by 1. */ BFD_RELOC_390_PLT32DBL, /* 32 bit PC rel. GOT shifted by 1. */ BFD_RELOC_390_GOTPCDBL, /* 64 bit GOT offset. */ BFD_RELOC_390_GOT64, /* 64 bit PC relative PLT address. */ BFD_RELOC_390_PLT64, /* 32 bit rel. offset to GOT entry. */ BFD_RELOC_390_GOTENT, /* 64 bit offset to GOT. */ BFD_RELOC_390_GOTOFF64, /* 12-bit offset to symbol-entry within GOT, with PLT handling. */ BFD_RELOC_390_GOTPLT12, /* 16-bit offset to symbol-entry within GOT, with PLT handling. */ BFD_RELOC_390_GOTPLT16, /* 32-bit offset to symbol-entry within GOT, with PLT handling. */ BFD_RELOC_390_GOTPLT32, /* 64-bit offset to symbol-entry within GOT, with PLT handling. */ BFD_RELOC_390_GOTPLT64, /* 32-bit rel. offset to symbol-entry within GOT, with PLT handling. */ BFD_RELOC_390_GOTPLTENT, /* 16-bit rel. offset from the GOT to a PLT entry. */ BFD_RELOC_390_PLTOFF16, /* 32-bit rel. offset from the GOT to a PLT entry. */ BFD_RELOC_390_PLTOFF32, /* 64-bit rel. offset from the GOT to a PLT entry. */ BFD_RELOC_390_PLTOFF64, /* s390 tls relocations. */ BFD_RELOC_390_TLS_LOAD, BFD_RELOC_390_TLS_GDCALL, BFD_RELOC_390_TLS_LDCALL, BFD_RELOC_390_TLS_GD32, BFD_RELOC_390_TLS_GD64, BFD_RELOC_390_TLS_GOTIE12, BFD_RELOC_390_TLS_GOTIE32, BFD_RELOC_390_TLS_GOTIE64, BFD_RELOC_390_TLS_LDM32, BFD_RELOC_390_TLS_LDM64, BFD_RELOC_390_TLS_IE32, BFD_RELOC_390_TLS_IE64, BFD_RELOC_390_TLS_IEENT, BFD_RELOC_390_TLS_LE32, BFD_RELOC_390_TLS_LE64, BFD_RELOC_390_TLS_LDO32, BFD_RELOC_390_TLS_LDO64, BFD_RELOC_390_TLS_DTPMOD, BFD_RELOC_390_TLS_DTPOFF, BFD_RELOC_390_TLS_TPOFF, /* Long displacement extension. */ BFD_RELOC_390_20, BFD_RELOC_390_GOT20, BFD_RELOC_390_GOTPLT20, BFD_RELOC_390_TLS_GOTIE20, /* Score relocations */ BFD_RELOC_SCORE_DUMMY1, /* Low 16 bit for load/store */ BFD_RELOC_SCORE_GPREL15, /* This is a 24-bit reloc with the right 1 bit assumed to be 0 */ BFD_RELOC_SCORE_DUMMY2, BFD_RELOC_SCORE_JMP, /* This is a 19-bit reloc with the right 1 bit assumed to be 0 */ BFD_RELOC_SCORE_BRANCH, /* This is a 11-bit reloc with the right 1 bit assumed to be 0 */ BFD_RELOC_SCORE16_JMP, /* This is a 8-bit reloc with the right 1 bit assumed to be 0 */ BFD_RELOC_SCORE16_BRANCH, /* Undocumented Score relocs */ BFD_RELOC_SCORE_GOT15, BFD_RELOC_SCORE_GOT_LO16, BFD_RELOC_SCORE_CALL15, BFD_RELOC_SCORE_DUMMY_HI16, /* Scenix IP2K - 9-bit register number / data address */ BFD_RELOC_IP2K_FR9, /* Scenix IP2K - 4-bit register/data bank number */ BFD_RELOC_IP2K_BANK, /* Scenix IP2K - low 13 bits of instruction word address */ BFD_RELOC_IP2K_ADDR16CJP, /* Scenix IP2K - high 3 bits of instruction word address */ BFD_RELOC_IP2K_PAGE3, /* Scenix IP2K - ext/low/high 8 bits of data address */ BFD_RELOC_IP2K_LO8DATA, BFD_RELOC_IP2K_HI8DATA, BFD_RELOC_IP2K_EX8DATA, /* Scenix IP2K - low/high 8 bits of instruction word address */ BFD_RELOC_IP2K_LO8INSN, BFD_RELOC_IP2K_HI8INSN, /* Scenix IP2K - even/odd PC modifier to modify snb pcl.0 */ BFD_RELOC_IP2K_PC_SKIP, /* Scenix IP2K - 16 bit word address in text section. */ BFD_RELOC_IP2K_TEXT, /* Scenix IP2K - 7-bit sp or dp offset */ BFD_RELOC_IP2K_FR_OFFSET, /* Scenix VPE4K coprocessor - data/insn-space addressing */ BFD_RELOC_VPE4KMATH_DATA, BFD_RELOC_VPE4KMATH_INSN, /* These two relocations are used by the linker to determine which of the entries in a C++ virtual function table are actually used. When the --gc-sections option is given, the linker will zero out the entries that are not used, so that the code for those functions need not be included in the output. VTABLE_INHERIT is a zero-space relocation used to describe to the linker the inheritance tree of a C++ virtual function table. The relocation's symbol should be the parent class' vtable, and the relocation should be located at the child vtable. VTABLE_ENTRY is a zero-space relocation that describes the use of a virtual function table entry. The reloc's symbol should refer to the table of the class mentioned in the code. Off of that base, an offset describes the entry that is being used. For Rela hosts, this offset is stored in the reloc's addend. For Rel hosts, we are forced to put this offset in the reloc's section offset. */ BFD_RELOC_VTABLE_INHERIT, BFD_RELOC_VTABLE_ENTRY, /* Intel IA64 Relocations. */ BFD_RELOC_IA64_IMM14, BFD_RELOC_IA64_IMM22, BFD_RELOC_IA64_IMM64, BFD_RELOC_IA64_DIR32MSB, BFD_RELOC_IA64_DIR32LSB, BFD_RELOC_IA64_DIR64MSB, BFD_RELOC_IA64_DIR64LSB, BFD_RELOC_IA64_GPREL22, BFD_RELOC_IA64_GPREL64I, BFD_RELOC_IA64_GPREL32MSB, BFD_RELOC_IA64_GPREL32LSB, BFD_RELOC_IA64_GPREL64MSB, BFD_RELOC_IA64_GPREL64LSB, BFD_RELOC_IA64_LTOFF22, BFD_RELOC_IA64_LTOFF64I, BFD_RELOC_IA64_PLTOFF22, BFD_RELOC_IA64_PLTOFF64I, BFD_RELOC_IA64_PLTOFF64MSB, BFD_RELOC_IA64_PLTOFF64LSB, BFD_RELOC_IA64_FPTR64I, BFD_RELOC_IA64_FPTR32MSB, BFD_RELOC_IA64_FPTR32LSB, BFD_RELOC_IA64_FPTR64MSB, BFD_RELOC_IA64_FPTR64LSB, BFD_RELOC_IA64_PCREL21B, BFD_RELOC_IA64_PCREL21BI, BFD_RELOC_IA64_PCREL21M, BFD_RELOC_IA64_PCREL21F, BFD_RELOC_IA64_PCREL22, BFD_RELOC_IA64_PCREL60B, BFD_RELOC_IA64_PCREL64I, BFD_RELOC_IA64_PCREL32MSB, BFD_RELOC_IA64_PCREL32LSB, BFD_RELOC_IA64_PCREL64MSB, BFD_RELOC_IA64_PCREL64LSB, BFD_RELOC_IA64_LTOFF_FPTR22, BFD_RELOC_IA64_LTOFF_FPTR64I, BFD_RELOC_IA64_LTOFF_FPTR32MSB, BFD_RELOC_IA64_LTOFF_FPTR32LSB, BFD_RELOC_IA64_LTOFF_FPTR64MSB, BFD_RELOC_IA64_LTOFF_FPTR64LSB, BFD_RELOC_IA64_SEGREL32MSB, BFD_RELOC_IA64_SEGREL32LSB, BFD_RELOC_IA64_SEGREL64MSB, BFD_RELOC_IA64_SEGREL64LSB, BFD_RELOC_IA64_SECREL32MSB, BFD_RELOC_IA64_SECREL32LSB, BFD_RELOC_IA64_SECREL64MSB, BFD_RELOC_IA64_SECREL64LSB, BFD_RELOC_IA64_REL32MSB, BFD_RELOC_IA64_REL32LSB, BFD_RELOC_IA64_REL64MSB, BFD_RELOC_IA64_REL64LSB, BFD_RELOC_IA64_LTV32MSB, BFD_RELOC_IA64_LTV32LSB, BFD_RELOC_IA64_LTV64MSB, BFD_RELOC_IA64_LTV64LSB, BFD_RELOC_IA64_IPLTMSB, BFD_RELOC_IA64_IPLTLSB, BFD_RELOC_IA64_COPY, BFD_RELOC_IA64_LTOFF22X, BFD_RELOC_IA64_LDXMOV, BFD_RELOC_IA64_TPREL14, BFD_RELOC_IA64_TPREL22, BFD_RELOC_IA64_TPREL64I, BFD_RELOC_IA64_TPREL64MSB, BFD_RELOC_IA64_TPREL64LSB, BFD_RELOC_IA64_LTOFF_TPREL22, BFD_RELOC_IA64_DTPMOD64MSB, BFD_RELOC_IA64_DTPMOD64LSB, BFD_RELOC_IA64_LTOFF_DTPMOD22, BFD_RELOC_IA64_DTPREL14, BFD_RELOC_IA64_DTPREL22, BFD_RELOC_IA64_DTPREL64I, BFD_RELOC_IA64_DTPREL32MSB, BFD_RELOC_IA64_DTPREL32LSB, BFD_RELOC_IA64_DTPREL64MSB, BFD_RELOC_IA64_DTPREL64LSB, BFD_RELOC_IA64_LTOFF_DTPREL22, /* Motorola 68HC11 reloc. This is the 8 bit high part of an absolute address. */ BFD_RELOC_M68HC11_HI8, /* Motorola 68HC11 reloc. This is the 8 bit low part of an absolute address. */ BFD_RELOC_M68HC11_LO8, /* Motorola 68HC11 reloc. This is the 3 bit of a value. */ BFD_RELOC_M68HC11_3B, /* Motorola 68HC11 reloc. This reloc marks the beginning of a jump/call instruction. It is used for linker relaxation to correctly identify beginning of instruction and change some branches to use PC-relative addressing mode. */ BFD_RELOC_M68HC11_RL_JUMP, /* Motorola 68HC11 reloc. This reloc marks a group of several instructions that gcc generates and for which the linker relaxation pass can modify and/or remove some of them. */ BFD_RELOC_M68HC11_RL_GROUP, /* Motorola 68HC11 reloc. This is the 16-bit lower part of an address. It is used for 'call' instruction to specify the symbol address without any special transformation (due to memory bank window). */ BFD_RELOC_M68HC11_LO16, /* Motorola 68HC11 reloc. This is a 8-bit reloc that specifies the page number of an address. It is used by 'call' instruction to specify the page number of the symbol. */ BFD_RELOC_M68HC11_PAGE, /* Motorola 68HC11 reloc. This is a 24-bit reloc that represents the address with a 16-bit value and a 8-bit page number. The symbol address is transformed to follow the 16K memory bank of 68HC12 (seen as mapped in the window). */ BFD_RELOC_M68HC11_24, /* Motorola 68HC12 reloc. This is the 5 bits of a value. */ BFD_RELOC_M68HC12_5B, /* NS CR16C Relocations. */ BFD_RELOC_16C_NUM08, BFD_RELOC_16C_NUM08_C, BFD_RELOC_16C_NUM16, BFD_RELOC_16C_NUM16_C, BFD_RELOC_16C_NUM32, BFD_RELOC_16C_NUM32_C, BFD_RELOC_16C_DISP04, BFD_RELOC_16C_DISP04_C, BFD_RELOC_16C_DISP08, BFD_RELOC_16C_DISP08_C, BFD_RELOC_16C_DISP16, BFD_RELOC_16C_DISP16_C, BFD_RELOC_16C_DISP24, BFD_RELOC_16C_DISP24_C, BFD_RELOC_16C_DISP24a, BFD_RELOC_16C_DISP24a_C, BFD_RELOC_16C_REG04, BFD_RELOC_16C_REG04_C, BFD_RELOC_16C_REG04a, BFD_RELOC_16C_REG04a_C, BFD_RELOC_16C_REG14, BFD_RELOC_16C_REG14_C, BFD_RELOC_16C_REG16, BFD_RELOC_16C_REG16_C, BFD_RELOC_16C_REG20, BFD_RELOC_16C_REG20_C, BFD_RELOC_16C_ABS20, BFD_RELOC_16C_ABS20_C, BFD_RELOC_16C_ABS24, BFD_RELOC_16C_ABS24_C, BFD_RELOC_16C_IMM04, BFD_RELOC_16C_IMM04_C, BFD_RELOC_16C_IMM16, BFD_RELOC_16C_IMM16_C, BFD_RELOC_16C_IMM20, BFD_RELOC_16C_IMM20_C, BFD_RELOC_16C_IMM24, BFD_RELOC_16C_IMM24_C, BFD_RELOC_16C_IMM32, BFD_RELOC_16C_IMM32_C, /* NS CR16 Relocations. */ BFD_RELOC_CR16_NUM8, BFD_RELOC_CR16_NUM16, BFD_RELOC_CR16_NUM32, BFD_RELOC_CR16_NUM32a, BFD_RELOC_CR16_REGREL0, BFD_RELOC_CR16_REGREL4, BFD_RELOC_CR16_REGREL4a, BFD_RELOC_CR16_REGREL14, BFD_RELOC_CR16_REGREL14a, BFD_RELOC_CR16_REGREL16, BFD_RELOC_CR16_REGREL20, BFD_RELOC_CR16_REGREL20a, BFD_RELOC_CR16_ABS20, BFD_RELOC_CR16_ABS24, BFD_RELOC_CR16_IMM4, BFD_RELOC_CR16_IMM8, BFD_RELOC_CR16_IMM16, BFD_RELOC_CR16_IMM20, BFD_RELOC_CR16_IMM24, BFD_RELOC_CR16_IMM32, BFD_RELOC_CR16_IMM32a, BFD_RELOC_CR16_DISP4, BFD_RELOC_CR16_DISP8, BFD_RELOC_CR16_DISP16, BFD_RELOC_CR16_DISP20, BFD_RELOC_CR16_DISP24, BFD_RELOC_CR16_DISP24a, /* NS CRX Relocations. */ BFD_RELOC_CRX_REL4, BFD_RELOC_CRX_REL8, BFD_RELOC_CRX_REL8_CMP, BFD_RELOC_CRX_REL16, BFD_RELOC_CRX_REL24, BFD_RELOC_CRX_REL32, BFD_RELOC_CRX_REGREL12, BFD_RELOC_CRX_REGREL22, BFD_RELOC_CRX_REGREL28, BFD_RELOC_CRX_REGREL32, BFD_RELOC_CRX_ABS16, BFD_RELOC_CRX_ABS32, BFD_RELOC_CRX_NUM8, BFD_RELOC_CRX_NUM16, BFD_RELOC_CRX_NUM32, BFD_RELOC_CRX_IMM16, BFD_RELOC_CRX_IMM32, BFD_RELOC_CRX_SWITCH8, BFD_RELOC_CRX_SWITCH16, BFD_RELOC_CRX_SWITCH32, /* These relocs are only used within the CRIS assembler. They are not (at present) written to any object files. */ BFD_RELOC_CRIS_BDISP8, BFD_RELOC_CRIS_UNSIGNED_5, BFD_RELOC_CRIS_SIGNED_6, BFD_RELOC_CRIS_UNSIGNED_6, BFD_RELOC_CRIS_SIGNED_8, BFD_RELOC_CRIS_UNSIGNED_8, BFD_RELOC_CRIS_SIGNED_16, BFD_RELOC_CRIS_UNSIGNED_16, BFD_RELOC_CRIS_LAPCQ_OFFSET, BFD_RELOC_CRIS_UNSIGNED_4, /* Relocs used in ELF shared libraries for CRIS. */ BFD_RELOC_CRIS_COPY, BFD_RELOC_CRIS_GLOB_DAT, BFD_RELOC_CRIS_JUMP_SLOT, BFD_RELOC_CRIS_RELATIVE, /* 32-bit offset to symbol-entry within GOT. */ BFD_RELOC_CRIS_32_GOT, /* 16-bit offset to symbol-entry within GOT. */ BFD_RELOC_CRIS_16_GOT, /* 32-bit offset to symbol-entry within GOT, with PLT handling. */ BFD_RELOC_CRIS_32_GOTPLT, /* 16-bit offset to symbol-entry within GOT, with PLT handling. */ BFD_RELOC_CRIS_16_GOTPLT, /* 32-bit offset to symbol, relative to GOT. */ BFD_RELOC_CRIS_32_GOTREL, /* 32-bit offset to symbol with PLT entry, relative to GOT. */ BFD_RELOC_CRIS_32_PLT_GOTREL, /* 32-bit offset to symbol with PLT entry, relative to this relocation. */ BFD_RELOC_CRIS_32_PLT_PCREL, /* Intel i860 Relocations. */ BFD_RELOC_860_COPY, BFD_RELOC_860_GLOB_DAT, BFD_RELOC_860_JUMP_SLOT, BFD_RELOC_860_RELATIVE, BFD_RELOC_860_PC26, BFD_RELOC_860_PLT26, BFD_RELOC_860_PC16, BFD_RELOC_860_LOW0, BFD_RELOC_860_SPLIT0, BFD_RELOC_860_LOW1, BFD_RELOC_860_SPLIT1, BFD_RELOC_860_LOW2, BFD_RELOC_860_SPLIT2, BFD_RELOC_860_LOW3, BFD_RELOC_860_LOGOT0, BFD_RELOC_860_SPGOT0, BFD_RELOC_860_LOGOT1, BFD_RELOC_860_SPGOT1, BFD_RELOC_860_LOGOTOFF0, BFD_RELOC_860_SPGOTOFF0, BFD_RELOC_860_LOGOTOFF1, BFD_RELOC_860_SPGOTOFF1, BFD_RELOC_860_LOGOTOFF2, BFD_RELOC_860_LOGOTOFF3, BFD_RELOC_860_LOPC, BFD_RELOC_860_HIGHADJ, BFD_RELOC_860_HAGOT, BFD_RELOC_860_HAGOTOFF, BFD_RELOC_860_HAPC, BFD_RELOC_860_HIGH, BFD_RELOC_860_HIGOT, BFD_RELOC_860_HIGOTOFF, /* OpenRISC Relocations. */ BFD_RELOC_OPENRISC_ABS_26, BFD_RELOC_OPENRISC_REL_26, /* H8 elf Relocations. */ BFD_RELOC_H8_DIR16A8, BFD_RELOC_H8_DIR16R8, BFD_RELOC_H8_DIR24A8, BFD_RELOC_H8_DIR24R8, BFD_RELOC_H8_DIR32A16, /* Sony Xstormy16 Relocations. */ BFD_RELOC_XSTORMY16_REL_12, BFD_RELOC_XSTORMY16_12, BFD_RELOC_XSTORMY16_24, BFD_RELOC_XSTORMY16_FPTR16, /* Self-describing complex relocations. */ BFD_RELOC_RELC, /* Infineon Relocations. */ BFD_RELOC_XC16X_PAG, BFD_RELOC_XC16X_POF, BFD_RELOC_XC16X_SEG, BFD_RELOC_XC16X_SOF, /* Relocations used by VAX ELF. */ BFD_RELOC_VAX_GLOB_DAT, BFD_RELOC_VAX_JMP_SLOT, BFD_RELOC_VAX_RELATIVE, /* Morpho MT - 16 bit immediate relocation. */ BFD_RELOC_MT_PC16, /* Morpho MT - Hi 16 bits of an address. */ BFD_RELOC_MT_HI16, /* Morpho MT - Low 16 bits of an address. */ BFD_RELOC_MT_LO16, /* Morpho MT - Used to tell the linker which vtable entries are used. */ BFD_RELOC_MT_GNU_VTINHERIT, /* Morpho MT - Used to tell the linker which vtable entries are used. */ BFD_RELOC_MT_GNU_VTENTRY, /* Morpho MT - 8 bit immediate relocation. */ BFD_RELOC_MT_PCINSN8, /* msp430 specific relocation codes */ BFD_RELOC_MSP430_10_PCREL, BFD_RELOC_MSP430_16_PCREL, BFD_RELOC_MSP430_16, BFD_RELOC_MSP430_16_PCREL_BYTE, BFD_RELOC_MSP430_16_BYTE, BFD_RELOC_MSP430_2X_PCREL, BFD_RELOC_MSP430_RL_PCREL, /* IQ2000 Relocations. */ BFD_RELOC_IQ2000_OFFSET_16, BFD_RELOC_IQ2000_OFFSET_21, BFD_RELOC_IQ2000_UHI16, /* Special Xtensa relocation used only by PLT entries in ELF shared objects to indicate that the runtime linker should set the value to one of its own internal functions or data structures. */ BFD_RELOC_XTENSA_RTLD, /* Xtensa relocations for ELF shared objects. */ BFD_RELOC_XTENSA_GLOB_DAT, BFD_RELOC_XTENSA_JMP_SLOT, BFD_RELOC_XTENSA_RELATIVE, /* Xtensa relocation used in ELF object files for symbols that may require PLT entries. Otherwise, this is just a generic 32-bit relocation. */ BFD_RELOC_XTENSA_PLT, /* Xtensa relocations to mark the difference of two local symbols. These are only needed to support linker relaxation and can be ignored when not relaxing. The field is set to the value of the difference assuming no relaxation. The relocation encodes the position of the first symbol so the linker can determine whether to adjust the field value. */ BFD_RELOC_XTENSA_DIFF8, BFD_RELOC_XTENSA_DIFF16, BFD_RELOC_XTENSA_DIFF32, /* Generic Xtensa relocations for instruction operands. Only the slot number is encoded in the relocation. The relocation applies to the last PC-relative immediate operand, or if there are no PC-relative immediates, to the last immediate operand. */ BFD_RELOC_XTENSA_SLOT0_OP, BFD_RELOC_XTENSA_SLOT1_OP, BFD_RELOC_XTENSA_SLOT2_OP, BFD_RELOC_XTENSA_SLOT3_OP, BFD_RELOC_XTENSA_SLOT4_OP, BFD_RELOC_XTENSA_SLOT5_OP, BFD_RELOC_XTENSA_SLOT6_OP, BFD_RELOC_XTENSA_SLOT7_OP, BFD_RELOC_XTENSA_SLOT8_OP, BFD_RELOC_XTENSA_SLOT9_OP, BFD_RELOC_XTENSA_SLOT10_OP, BFD_RELOC_XTENSA_SLOT11_OP, BFD_RELOC_XTENSA_SLOT12_OP, BFD_RELOC_XTENSA_SLOT13_OP, BFD_RELOC_XTENSA_SLOT14_OP, /* Alternate Xtensa relocations. Only the slot is encoded in the relocation. The meaning of these relocations is opcode-specific. */ BFD_RELOC_XTENSA_SLOT0_ALT, BFD_RELOC_XTENSA_SLOT1_ALT, BFD_RELOC_XTENSA_SLOT2_ALT, BFD_RELOC_XTENSA_SLOT3_ALT, BFD_RELOC_XTENSA_SLOT4_ALT, BFD_RELOC_XTENSA_SLOT5_ALT, BFD_RELOC_XTENSA_SLOT6_ALT, BFD_RELOC_XTENSA_SLOT7_ALT, BFD_RELOC_XTENSA_SLOT8_ALT, BFD_RELOC_XTENSA_SLOT9_ALT, BFD_RELOC_XTENSA_SLOT10_ALT, BFD_RELOC_XTENSA_SLOT11_ALT, BFD_RELOC_XTENSA_SLOT12_ALT, BFD_RELOC_XTENSA_SLOT13_ALT, BFD_RELOC_XTENSA_SLOT14_ALT, /* Xtensa relocations for backward compatibility. These have all been replaced by BFD_RELOC_XTENSA_SLOT0_OP. */ BFD_RELOC_XTENSA_OP0, BFD_RELOC_XTENSA_OP1, BFD_RELOC_XTENSA_OP2, /* Xtensa relocation to mark that the assembler expanded the instructions from an original target. The expansion size is encoded in the reloc size. */ BFD_RELOC_XTENSA_ASM_EXPAND, /* Xtensa relocation to mark that the linker should simplify assembler-expanded instructions. This is commonly used internally by the linker after analysis of a BFD_RELOC_XTENSA_ASM_EXPAND. */ BFD_RELOC_XTENSA_ASM_SIMPLIFY, /* 8 bit signed offset in (ix+d) or (iy+d). */ BFD_RELOC_Z80_DISP8, /* DJNZ offset. */ BFD_RELOC_Z8K_DISP7, /* CALR offset. */ BFD_RELOC_Z8K_CALLR, /* 4 bit value. */ BFD_RELOC_Z8K_IMM4L, BFD_RELOC_UNUSED }; typedef enum bfd_reloc_code_real bfd_reloc_code_real_type; reloc_howto_type *bfd_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code); reloc_howto_type *bfd_reloc_name_lookup (bfd *abfd, const char *reloc_name); const char *bfd_get_reloc_code_name (bfd_reloc_code_real_type code); /* Extracted from syms.c. */ typedef struct bfd_symbol { /* A pointer to the BFD which owns the symbol. This information is necessary so that a back end can work out what additional information (invisible to the application writer) is carried with the symbol. This field is *almost* redundant, since you can use section->owner instead, except that some symbols point to the global sections bfd_{abs,com,und}_section. This could be fixed by making these globals be per-bfd (or per-target-flavor). FIXME. */ struct bfd *the_bfd; /* Use bfd_asymbol_bfd(sym) to access this field. */ /* The text of the symbol. The name is left alone, and not copied; the application may not alter it. */ const char *name; /* The value of the symbol. This really should be a union of a numeric value with a pointer, since some flags indicate that a pointer to another symbol is stored here. */ symvalue value; /* Attributes of a symbol. */ #define BSF_NO_FLAGS 0x00 /* The symbol has local scope; <> in <>. The value is the offset into the section of the data. */ #define BSF_LOCAL 0x01 /* The symbol has global scope; initialized data in <>. The value is the offset into the section of the data. */ #define BSF_GLOBAL 0x02 /* The symbol has global scope and is exported. The value is the offset into the section of the data. */ #define BSF_EXPORT BSF_GLOBAL /* No real difference. */ /* A normal C symbol would be one of: <>, <>, <> or <>. */ /* The symbol is a debugging record. The value has an arbitrary meaning, unless BSF_DEBUGGING_RELOC is also set. */ #define BSF_DEBUGGING 0x08 /* The symbol denotes a function entry point. Used in ELF, perhaps others someday. */ #define BSF_FUNCTION 0x10 /* Used by the linker. */ #define BSF_KEEP 0x20 #define BSF_KEEP_G 0x40 /* A weak global symbol, overridable without warnings by a regular global symbol of the same name. */ #define BSF_WEAK 0x80 /* This symbol was created to point to a section, e.g. ELF's STT_SECTION symbols. */ #define BSF_SECTION_SYM 0x100 /* The symbol used to be a common symbol, but now it is allocated. */ #define BSF_OLD_COMMON 0x200 /* The default value for common data. */ #define BFD_FORT_COMM_DEFAULT_VALUE 0 /* In some files the type of a symbol sometimes alters its location in an output file - ie in coff a <> symbol which is also <> symbol appears where it was declared and not at the end of a section. This bit is set by the target BFD part to convey this information. */ #define BSF_NOT_AT_END 0x400 /* Signal that the symbol is the label of constructor section. */ #define BSF_CONSTRUCTOR 0x800 /* Signal that the symbol is a warning symbol. The name is a warning. The name of the next symbol is the one to warn about; if a reference is made to a symbol with the same name as the next symbol, a warning is issued by the linker. */ #define BSF_WARNING 0x1000 /* Signal that the symbol is indirect. This symbol is an indirect pointer to the symbol with the same name as the next symbol. */ #define BSF_INDIRECT 0x2000 /* BSF_FILE marks symbols that contain a file name. This is used for ELF STT_FILE symbols. */ #define BSF_FILE 0x4000 /* Symbol is from dynamic linking information. */ #define BSF_DYNAMIC 0x8000 /* The symbol denotes a data object. Used in ELF, and perhaps others someday. */ #define BSF_OBJECT 0x10000 /* This symbol is a debugging symbol. The value is the offset into the section of the data. BSF_DEBUGGING should be set as well. */ #define BSF_DEBUGGING_RELOC 0x20000 /* This symbol is thread local. Used in ELF. */ #define BSF_THREAD_LOCAL 0x40000 /* This symbol represents a complex relocation expression, with the expression tree serialized in the symbol name. */ #define BSF_RELC 0x80000 /* This symbol represents a signed complex relocation expression, with the expression tree serialized in the symbol name. */ #define BSF_SRELC 0x100000 flagword flags; /* A pointer to the section to which this symbol is relative. This will always be non NULL, there are special sections for undefined and absolute symbols. */ struct bfd_section *section; /* Back end special data. */ union { void *p; bfd_vma i; } udata; } asymbol; #define bfd_get_symtab_upper_bound(abfd) \ BFD_SEND (abfd, _bfd_get_symtab_upper_bound, (abfd)) bfd_boolean bfd_is_local_label (bfd *abfd, asymbol *sym); bfd_boolean bfd_is_local_label_name (bfd *abfd, const char *name); #define bfd_is_local_label_name(abfd, name) \ BFD_SEND (abfd, _bfd_is_local_label_name, (abfd, name)) bfd_boolean bfd_is_target_special_symbol (bfd *abfd, asymbol *sym); #define bfd_is_target_special_symbol(abfd, sym) \ BFD_SEND (abfd, _bfd_is_target_special_symbol, (abfd, sym)) #define bfd_canonicalize_symtab(abfd, location) \ BFD_SEND (abfd, _bfd_canonicalize_symtab, (abfd, location)) bfd_boolean bfd_set_symtab (bfd *abfd, asymbol **location, unsigned int count); void bfd_print_symbol_vandf (bfd *abfd, void *file, asymbol *symbol); #define bfd_make_empty_symbol(abfd) \ BFD_SEND (abfd, _bfd_make_empty_symbol, (abfd)) asymbol *_bfd_generic_make_empty_symbol (bfd *); #define bfd_make_debug_symbol(abfd,ptr,size) \ BFD_SEND (abfd, _bfd_make_debug_symbol, (abfd, ptr, size)) int bfd_decode_symclass (asymbol *symbol); bfd_boolean bfd_is_undefined_symclass (int symclass); void bfd_symbol_info (asymbol *symbol, symbol_info *ret); bfd_boolean bfd_copy_private_symbol_data (bfd *ibfd, asymbol *isym, bfd *obfd, asymbol *osym); #define bfd_copy_private_symbol_data(ibfd, isymbol, obfd, osymbol) \ BFD_SEND (obfd, _bfd_copy_private_symbol_data, \ (ibfd, isymbol, obfd, osymbol)) /* Extracted from bfd.c. */ struct bfd { /* A unique identifier of the BFD */ unsigned int id; /* The filename the application opened the BFD with. */ const char *filename; /* A pointer to the target jump table. */ const struct bfd_target *xvec; /* The IOSTREAM, and corresponding IO vector that provide access to the file backing the BFD. */ void *iostream; const struct bfd_iovec *iovec; /* Is the file descriptor being cached? That is, can it be closed as needed, and re-opened when accessed later? */ bfd_boolean cacheable; /* Marks whether there was a default target specified when the BFD was opened. This is used to select which matching algorithm to use to choose the back end. */ bfd_boolean target_defaulted; /* The caching routines use these to maintain a least-recently-used list of BFDs. */ struct bfd *lru_prev, *lru_next; /* When a file is closed by the caching routines, BFD retains state information on the file here... */ ufile_ptr where; /* ... and here: (``once'' means at least once). */ bfd_boolean opened_once; /* Set if we have a locally maintained mtime value, rather than getting it from the file each time. */ bfd_boolean mtime_set; /* File modified time, if mtime_set is TRUE. */ long mtime; /* Reserved for an unimplemented file locking extension. */ int ifd; /* The format which belongs to the BFD. (object, core, etc.) */ bfd_format format; /* The direction with which the BFD was opened. */ enum bfd_direction { no_direction = 0, read_direction = 1, write_direction = 2, both_direction = 3 } direction; /* Format_specific flags. */ flagword flags; /* Currently my_archive is tested before adding origin to anything. I believe that this can become always an add of origin, with origin set to 0 for non archive files. */ ufile_ptr origin; /* Remember when output has begun, to stop strange things from happening. */ bfd_boolean output_has_begun; /* A hash table for section names. */ struct bfd_hash_table section_htab; /* Pointer to linked list of sections. */ struct bfd_section *sections; /* The last section on the section list. */ struct bfd_section *section_last; /* The number of sections. */ unsigned int section_count; /* Stuff only useful for object files: The start address. */ bfd_vma start_address; /* Used for input and output. */ unsigned int symcount; /* Symbol table for output BFD (with symcount entries). */ struct bfd_symbol **outsymbols; /* Used for slurped dynamic symbol tables. */ unsigned int dynsymcount; /* Pointer to structure which contains architecture information. */ const struct bfd_arch_info *arch_info; /* Flag set if symbols from this BFD should not be exported. */ bfd_boolean no_export; /* Stuff only useful for archives. */ void *arelt_data; struct bfd *my_archive; /* The containing archive BFD. */ struct bfd *archive_next; /* The next BFD in the archive. */ struct bfd *archive_head; /* The first BFD in the archive. */ bfd_boolean has_armap; /* A chain of BFD structures involved in a link. */ struct bfd *link_next; /* A field used by _bfd_generic_link_add_archive_symbols. This will be used only for archive elements. */ int archive_pass; /* Used by the back end to hold private data. */ union { struct aout_data_struct *aout_data; struct artdata *aout_ar_data; struct _oasys_data *oasys_obj_data; struct _oasys_ar_data *oasys_ar_data; struct coff_tdata *coff_obj_data; struct pe_tdata *pe_obj_data; struct xcoff_tdata *xcoff_obj_data; struct ecoff_tdata *ecoff_obj_data; struct ieee_data_struct *ieee_data; struct ieee_ar_data_struct *ieee_ar_data; struct srec_data_struct *srec_data; struct ihex_data_struct *ihex_data; struct tekhex_data_struct *tekhex_data; struct elf_obj_tdata *elf_obj_data; struct nlm_obj_tdata *nlm_obj_data; struct bout_data_struct *bout_data; struct mmo_data_struct *mmo_data; struct sun_core_struct *sun_core_data; struct sco5_core_struct *sco5_core_data; struct trad_core_struct *trad_core_data; struct som_data_struct *som_data; struct hpux_core_struct *hpux_core_data; struct hppabsd_core_struct *hppabsd_core_data; struct sgi_core_struct *sgi_core_data; struct lynx_core_struct *lynx_core_data; struct osf_core_struct *osf_core_data; struct cisco_core_struct *cisco_core_data; struct versados_data_struct *versados_data; struct netbsd_core_struct *netbsd_core_data; struct mach_o_data_struct *mach_o_data; struct mach_o_fat_data_struct *mach_o_fat_data; struct bfd_pef_data_struct *pef_data; struct bfd_pef_xlib_data_struct *pef_xlib_data; struct bfd_sym_data_struct *sym_data; void *any; } tdata; /* Used by the application to hold private data. */ void *usrdata; /* Where all the allocated stuff under this BFD goes. This is a struct objalloc *, but we use void * to avoid requiring the inclusion of objalloc.h. */ void *memory; }; typedef enum bfd_error { bfd_error_no_error = 0, bfd_error_system_call, bfd_error_invalid_target, bfd_error_wrong_format, bfd_error_wrong_object_format, bfd_error_invalid_operation, bfd_error_no_memory, bfd_error_no_symbols, bfd_error_no_armap, bfd_error_no_more_archived_files, bfd_error_malformed_archive, bfd_error_file_not_recognized, bfd_error_file_ambiguously_recognized, bfd_error_no_contents, bfd_error_nonrepresentable_section, bfd_error_no_debug_section, bfd_error_bad_value, bfd_error_file_truncated, bfd_error_file_too_big, bfd_error_on_input, bfd_error_invalid_error_code } bfd_error_type; bfd_error_type bfd_get_error (void); void bfd_set_error (bfd_error_type error_tag, ...); const char *bfd_errmsg (bfd_error_type error_tag); void bfd_perror (const char *message); typedef void (*bfd_error_handler_type) (const char *, ...); bfd_error_handler_type bfd_set_error_handler (bfd_error_handler_type); void bfd_set_error_program_name (const char *); bfd_error_handler_type bfd_get_error_handler (void); long bfd_get_reloc_upper_bound (bfd *abfd, asection *sect); long bfd_canonicalize_reloc (bfd *abfd, asection *sec, arelent **loc, asymbol **syms); void bfd_set_reloc (bfd *abfd, asection *sec, arelent **rel, unsigned int count); bfd_boolean bfd_set_file_flags (bfd *abfd, flagword flags); int bfd_get_arch_size (bfd *abfd); int bfd_get_sign_extend_vma (bfd *abfd); bfd_boolean bfd_set_start_address (bfd *abfd, bfd_vma vma); unsigned int bfd_get_gp_size (bfd *abfd); void bfd_set_gp_size (bfd *abfd, unsigned int i); bfd_vma bfd_scan_vma (const char *string, const char **end, int base); bfd_boolean bfd_copy_private_header_data (bfd *ibfd, bfd *obfd); #define bfd_copy_private_header_data(ibfd, obfd) \ BFD_SEND (obfd, _bfd_copy_private_header_data, \ (ibfd, obfd)) bfd_boolean bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd); #define bfd_copy_private_bfd_data(ibfd, obfd) \ BFD_SEND (obfd, _bfd_copy_private_bfd_data, \ (ibfd, obfd)) bfd_boolean bfd_merge_private_bfd_data (bfd *ibfd, bfd *obfd); #define bfd_merge_private_bfd_data(ibfd, obfd) \ BFD_SEND (obfd, _bfd_merge_private_bfd_data, \ (ibfd, obfd)) bfd_boolean bfd_set_private_flags (bfd *abfd, flagword flags); #define bfd_set_private_flags(abfd, flags) \ BFD_SEND (abfd, _bfd_set_private_flags, (abfd, flags)) #define bfd_sizeof_headers(abfd, info) \ BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, info)) #define bfd_find_nearest_line(abfd, sec, syms, off, file, func, line) \ BFD_SEND (abfd, _bfd_find_nearest_line, \ (abfd, sec, syms, off, file, func, line)) #define bfd_find_line(abfd, syms, sym, file, line) \ BFD_SEND (abfd, _bfd_find_line, \ (abfd, syms, sym, file, line)) #define bfd_find_inliner_info(abfd, file, func, line) \ BFD_SEND (abfd, _bfd_find_inliner_info, \ (abfd, file, func, line)) #define bfd_debug_info_start(abfd) \ BFD_SEND (abfd, _bfd_debug_info_start, (abfd)) #define bfd_debug_info_end(abfd) \ BFD_SEND (abfd, _bfd_debug_info_end, (abfd)) #define bfd_debug_info_accumulate(abfd, section) \ BFD_SEND (abfd, _bfd_debug_info_accumulate, (abfd, section)) #define bfd_stat_arch_elt(abfd, stat) \ BFD_SEND (abfd, _bfd_stat_arch_elt,(abfd, stat)) #define bfd_update_armap_timestamp(abfd) \ BFD_SEND (abfd, _bfd_update_armap_timestamp, (abfd)) #define bfd_set_arch_mach(abfd, arch, mach)\ BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach)) #define bfd_relax_section(abfd, section, link_info, again) \ BFD_SEND (abfd, _bfd_relax_section, (abfd, section, link_info, again)) #define bfd_gc_sections(abfd, link_info) \ BFD_SEND (abfd, _bfd_gc_sections, (abfd, link_info)) #define bfd_merge_sections(abfd, link_info) \ BFD_SEND (abfd, _bfd_merge_sections, (abfd, link_info)) #define bfd_is_group_section(abfd, sec) \ BFD_SEND (abfd, _bfd_is_group_section, (abfd, sec)) #define bfd_discard_group(abfd, sec) \ BFD_SEND (abfd, _bfd_discard_group, (abfd, sec)) #define bfd_link_hash_table_create(abfd) \ BFD_SEND (abfd, _bfd_link_hash_table_create, (abfd)) #define bfd_link_hash_table_free(abfd, hash) \ BFD_SEND (abfd, _bfd_link_hash_table_free, (hash)) #define bfd_link_add_symbols(abfd, info) \ BFD_SEND (abfd, _bfd_link_add_symbols, (abfd, info)) #define bfd_link_just_syms(abfd, sec, info) \ BFD_SEND (abfd, _bfd_link_just_syms, (sec, info)) #define bfd_final_link(abfd, info) \ BFD_SEND (abfd, _bfd_final_link, (abfd, info)) #define bfd_free_cached_info(abfd) \ BFD_SEND (abfd, _bfd_free_cached_info, (abfd)) #define bfd_get_dynamic_symtab_upper_bound(abfd) \ BFD_SEND (abfd, _bfd_get_dynamic_symtab_upper_bound, (abfd)) #define bfd_print_private_bfd_data(abfd, file)\ BFD_SEND (abfd, _bfd_print_private_bfd_data, (abfd, file)) #define bfd_canonicalize_dynamic_symtab(abfd, asymbols) \ BFD_SEND (abfd, _bfd_canonicalize_dynamic_symtab, (abfd, asymbols)) #define bfd_get_synthetic_symtab(abfd, count, syms, dyncount, dynsyms, ret) \ BFD_SEND (abfd, _bfd_get_synthetic_symtab, (abfd, count, syms, \ dyncount, dynsyms, ret)) #define bfd_get_dynamic_reloc_upper_bound(abfd) \ BFD_SEND (abfd, _bfd_get_dynamic_reloc_upper_bound, (abfd)) #define bfd_canonicalize_dynamic_reloc(abfd, arels, asyms) \ BFD_SEND (abfd, _bfd_canonicalize_dynamic_reloc, (abfd, arels, asyms)) extern bfd_byte *bfd_get_relocated_section_contents (bfd *, struct bfd_link_info *, struct bfd_link_order *, bfd_byte *, bfd_boolean, asymbol **); bfd_boolean bfd_alt_mach_code (bfd *abfd, int alternative); struct bfd_preserve { void *marker; void *tdata; flagword flags; const struct bfd_arch_info *arch_info; struct bfd_section *sections; struct bfd_section *section_last; unsigned int section_count; struct bfd_hash_table section_htab; }; bfd_boolean bfd_preserve_save (bfd *, struct bfd_preserve *); void bfd_preserve_restore (bfd *, struct bfd_preserve *); void bfd_preserve_finish (bfd *, struct bfd_preserve *); bfd_vma bfd_emul_get_maxpagesize (const char *); void bfd_emul_set_maxpagesize (const char *, bfd_vma); bfd_vma bfd_emul_get_commonpagesize (const char *); void bfd_emul_set_commonpagesize (const char *, bfd_vma); char *bfd_demangle (bfd *, const char *, int); /* Extracted from archive.c. */ symindex bfd_get_next_mapent (bfd *abfd, symindex previous, carsym **sym); bfd_boolean bfd_set_archive_head (bfd *output, bfd *new_head); bfd *bfd_openr_next_archived_file (bfd *archive, bfd *previous); /* Extracted from corefile.c. */ const char *bfd_core_file_failing_command (bfd *abfd); int bfd_core_file_failing_signal (bfd *abfd); bfd_boolean core_file_matches_executable_p (bfd *core_bfd, bfd *exec_bfd); bfd_boolean generic_core_file_matches_executable_p (bfd *core_bfd, bfd *exec_bfd); /* Extracted from targets.c. */ #define BFD_SEND(bfd, message, arglist) \ ((*((bfd)->xvec->message)) arglist) #ifdef DEBUG_BFD_SEND #undef BFD_SEND #define BFD_SEND(bfd, message, arglist) \ (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \ ((*((bfd)->xvec->message)) arglist) : \ (bfd_assert (__FILE__,__LINE__), NULL)) #endif #define BFD_SEND_FMT(bfd, message, arglist) \ (((bfd)->xvec->message[(int) ((bfd)->format)]) arglist) #ifdef DEBUG_BFD_SEND #undef BFD_SEND_FMT #define BFD_SEND_FMT(bfd, message, arglist) \ (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \ (((bfd)->xvec->message[(int) ((bfd)->format)]) arglist) : \ (bfd_assert (__FILE__,__LINE__), NULL)) #endif enum bfd_flavour { bfd_target_unknown_flavour, bfd_target_aout_flavour, bfd_target_coff_flavour, bfd_target_ecoff_flavour, bfd_target_xcoff_flavour, bfd_target_elf_flavour, bfd_target_ieee_flavour, bfd_target_nlm_flavour, bfd_target_oasys_flavour, bfd_target_tekhex_flavour, bfd_target_srec_flavour, bfd_target_ihex_flavour, bfd_target_som_flavour, bfd_target_os9k_flavour, bfd_target_versados_flavour, bfd_target_msdos_flavour, bfd_target_ovax_flavour, bfd_target_evax_flavour, bfd_target_mmo_flavour, bfd_target_mach_o_flavour, bfd_target_pef_flavour, bfd_target_pef_xlib_flavour, bfd_target_sym_flavour }; enum bfd_endian { BFD_ENDIAN_BIG, BFD_ENDIAN_LITTLE, BFD_ENDIAN_UNKNOWN }; /* Forward declaration. */ typedef struct bfd_link_info _bfd_link_info; typedef struct bfd_target { /* Identifies the kind of target, e.g., SunOS4, Ultrix, etc. */ char *name; /* The "flavour" of a back end is a general indication about the contents of a file. */ enum bfd_flavour flavour; /* The order of bytes within the data area of a file. */ enum bfd_endian byteorder; /* The order of bytes within the header parts of a file. */ enum bfd_endian header_byteorder; /* A mask of all the flags which an executable may have set - from the set <>, <>, ...<>. */ flagword object_flags; /* A mask of all the flags which a section may have set - from the set <>, <>, ...<>. */ flagword section_flags; /* The character normally found at the front of a symbol. (if any), perhaps `_'. */ char symbol_leading_char; /* The pad character for file names within an archive header. */ char ar_pad_char; /* The maximum number of characters in an archive header. */ unsigned short ar_max_namelen; /* Entries for byte swapping for data. These are different from the other entry points, since they don't take a BFD as the first argument. Certain other handlers could do the same. */ bfd_uint64_t (*bfd_getx64) (const void *); bfd_int64_t (*bfd_getx_signed_64) (const void *); void (*bfd_putx64) (bfd_uint64_t, void *); bfd_vma (*bfd_getx32) (const void *); bfd_signed_vma (*bfd_getx_signed_32) (const void *); void (*bfd_putx32) (bfd_vma, void *); bfd_vma (*bfd_getx16) (const void *); bfd_signed_vma (*bfd_getx_signed_16) (const void *); void (*bfd_putx16) (bfd_vma, void *); /* Byte swapping for the headers. */ bfd_uint64_t (*bfd_h_getx64) (const void *); bfd_int64_t (*bfd_h_getx_signed_64) (const void *); void (*bfd_h_putx64) (bfd_uint64_t, void *); bfd_vma (*bfd_h_getx32) (const void *); bfd_signed_vma (*bfd_h_getx_signed_32) (const void *); void (*bfd_h_putx32) (bfd_vma, void *); bfd_vma (*bfd_h_getx16) (const void *); bfd_signed_vma (*bfd_h_getx_signed_16) (const void *); void (*bfd_h_putx16) (bfd_vma, void *); /* Format dependent routines: these are vectors of entry points within the target vector structure, one for each format to check. */ /* Check the format of a file being read. Return a <> or zero. */ const struct bfd_target *(*_bfd_check_format[bfd_type_end]) (bfd *); /* Set the format of a file being written. */ bfd_boolean (*_bfd_set_format[bfd_type_end]) (bfd *); /* Write cached information into a file being written, at <>. */ bfd_boolean (*_bfd_write_contents[bfd_type_end]) (bfd *); /* Generic entry points. */ #define BFD_JUMP_TABLE_GENERIC(NAME) \ NAME##_close_and_cleanup, \ NAME##_bfd_free_cached_info, \ NAME##_new_section_hook, \ NAME##_get_section_contents, \ NAME##_get_section_contents_in_window /* Called when the BFD is being closed to do any necessary cleanup. */ bfd_boolean (*_close_and_cleanup) (bfd *); /* Ask the BFD to free all cached information. */ bfd_boolean (*_bfd_free_cached_info) (bfd *); /* Called when a new section is created. */ bfd_boolean (*_new_section_hook) (bfd *, sec_ptr); /* Read the contents of a section. */ bfd_boolean (*_bfd_get_section_contents) (bfd *, sec_ptr, void *, file_ptr, bfd_size_type); bfd_boolean (*_bfd_get_section_contents_in_window) (bfd *, sec_ptr, bfd_window *, file_ptr, bfd_size_type); /* Entry points to copy private data. */ #define BFD_JUMP_TABLE_COPY(NAME) \ NAME##_bfd_copy_private_bfd_data, \ NAME##_bfd_merge_private_bfd_data, \ _bfd_generic_init_private_section_data, \ NAME##_bfd_copy_private_section_data, \ NAME##_bfd_copy_private_symbol_data, \ NAME##_bfd_copy_private_header_data, \ NAME##_bfd_set_private_flags, \ NAME##_bfd_print_private_bfd_data /* Called to copy BFD general private data from one object file to another. */ bfd_boolean (*_bfd_copy_private_bfd_data) (bfd *, bfd *); /* Called to merge BFD general private data from one object file to a common output file when linking. */ bfd_boolean (*_bfd_merge_private_bfd_data) (bfd *, bfd *); /* Called to initialize BFD private section data from one object file to another. */ #define bfd_init_private_section_data(ibfd, isec, obfd, osec, link_info) \ BFD_SEND (obfd, _bfd_init_private_section_data, (ibfd, isec, obfd, osec, link_info)) bfd_boolean (*_bfd_init_private_section_data) (bfd *, sec_ptr, bfd *, sec_ptr, struct bfd_link_info *); /* Called to copy BFD private section data from one object file to another. */ bfd_boolean (*_bfd_copy_private_section_data) (bfd *, sec_ptr, bfd *, sec_ptr); /* Called to copy BFD private symbol data from one symbol to another. */ bfd_boolean (*_bfd_copy_private_symbol_data) (bfd *, asymbol *, bfd *, asymbol *); /* Called to copy BFD private header data from one object file to another. */ bfd_boolean (*_bfd_copy_private_header_data) (bfd *, bfd *); /* Called to set private backend flags. */ bfd_boolean (*_bfd_set_private_flags) (bfd *, flagword); /* Called to print private BFD data. */ bfd_boolean (*_bfd_print_private_bfd_data) (bfd *, void *); /* Core file entry points. */ #define BFD_JUMP_TABLE_CORE(NAME) \ NAME##_core_file_failing_command, \ NAME##_core_file_failing_signal, \ NAME##_core_file_matches_executable_p char * (*_core_file_failing_command) (bfd *); int (*_core_file_failing_signal) (bfd *); bfd_boolean (*_core_file_matches_executable_p) (bfd *, bfd *); /* Archive entry points. */ #define BFD_JUMP_TABLE_ARCHIVE(NAME) \ NAME##_slurp_armap, \ NAME##_slurp_extended_name_table, \ NAME##_construct_extended_name_table, \ NAME##_truncate_arname, \ NAME##_write_armap, \ NAME##_read_ar_hdr, \ NAME##_openr_next_archived_file, \ NAME##_get_elt_at_index, \ NAME##_generic_stat_arch_elt, \ NAME##_update_armap_timestamp bfd_boolean (*_bfd_slurp_armap) (bfd *); bfd_boolean (*_bfd_slurp_extended_name_table) (bfd *); bfd_boolean (*_bfd_construct_extended_name_table) (bfd *, char **, bfd_size_type *, const char **); void (*_bfd_truncate_arname) (bfd *, const char *, char *); bfd_boolean (*write_armap) (bfd *, unsigned int, struct orl *, unsigned int, int); void * (*_bfd_read_ar_hdr_fn) (bfd *); bfd * (*openr_next_archived_file) (bfd *, bfd *); #define bfd_get_elt_at_index(b,i) BFD_SEND (b, _bfd_get_elt_at_index, (b,i)) bfd * (*_bfd_get_elt_at_index) (bfd *, symindex); int (*_bfd_stat_arch_elt) (bfd *, struct stat *); bfd_boolean (*_bfd_update_armap_timestamp) (bfd *); /* Entry points used for symbols. */ #define BFD_JUMP_TABLE_SYMBOLS(NAME) \ NAME##_get_symtab_upper_bound, \ NAME##_canonicalize_symtab, \ NAME##_make_empty_symbol, \ NAME##_print_symbol, \ NAME##_get_symbol_info, \ NAME##_bfd_is_local_label_name, \ NAME##_bfd_is_target_special_symbol, \ NAME##_get_lineno, \ NAME##_find_nearest_line, \ _bfd_generic_find_line, \ NAME##_find_inliner_info, \ NAME##_bfd_make_debug_symbol, \ NAME##_read_minisymbols, \ NAME##_minisymbol_to_symbol long (*_bfd_get_symtab_upper_bound) (bfd *); long (*_bfd_canonicalize_symtab) (bfd *, struct bfd_symbol **); struct bfd_symbol * (*_bfd_make_empty_symbol) (bfd *); void (*_bfd_print_symbol) (bfd *, void *, struct bfd_symbol *, bfd_print_symbol_type); #define bfd_print_symbol(b,p,s,e) BFD_SEND (b, _bfd_print_symbol, (b,p,s,e)) void (*_bfd_get_symbol_info) (bfd *, struct bfd_symbol *, symbol_info *); #define bfd_get_symbol_info(b,p,e) BFD_SEND (b, _bfd_get_symbol_info, (b,p,e)) bfd_boolean (*_bfd_is_local_label_name) (bfd *, const char *); bfd_boolean (*_bfd_is_target_special_symbol) (bfd *, asymbol *); alent * (*_get_lineno) (bfd *, struct bfd_symbol *); bfd_boolean (*_bfd_find_nearest_line) (bfd *, struct bfd_section *, struct bfd_symbol **, bfd_vma, const char **, const char **, unsigned int *); bfd_boolean (*_bfd_find_line) (bfd *, struct bfd_symbol **, struct bfd_symbol *, const char **, unsigned int *); bfd_boolean (*_bfd_find_inliner_info) (bfd *, const char **, const char **, unsigned int *); /* Back-door to allow format-aware applications to create debug symbols while using BFD for everything else. Currently used by the assembler when creating COFF files. */ asymbol * (*_bfd_make_debug_symbol) (bfd *, void *, unsigned long size); #define bfd_read_minisymbols(b, d, m, s) \ BFD_SEND (b, _read_minisymbols, (b, d, m, s)) long (*_read_minisymbols) (bfd *, bfd_boolean, void **, unsigned int *); #define bfd_minisymbol_to_symbol(b, d, m, f) \ BFD_SEND (b, _minisymbol_to_symbol, (b, d, m, f)) asymbol * (*_minisymbol_to_symbol) (bfd *, bfd_boolean, const void *, asymbol *); /* Routines for relocs. */ #define BFD_JUMP_TABLE_RELOCS(NAME) \ NAME##_get_reloc_upper_bound, \ NAME##_canonicalize_reloc, \ NAME##_bfd_reloc_type_lookup, \ NAME##_bfd_reloc_name_lookup long (*_get_reloc_upper_bound) (bfd *, sec_ptr); long (*_bfd_canonicalize_reloc) (bfd *, sec_ptr, arelent **, struct bfd_symbol **); /* See documentation on reloc types. */ reloc_howto_type * (*reloc_type_lookup) (bfd *, bfd_reloc_code_real_type); reloc_howto_type * (*reloc_name_lookup) (bfd *, const char *); /* Routines used when writing an object file. */ #define BFD_JUMP_TABLE_WRITE(NAME) \ NAME##_set_arch_mach, \ NAME##_set_section_contents bfd_boolean (*_bfd_set_arch_mach) (bfd *, enum bfd_architecture, unsigned long); bfd_boolean (*_bfd_set_section_contents) (bfd *, sec_ptr, const void *, file_ptr, bfd_size_type); /* Routines used by the linker. */ #define BFD_JUMP_TABLE_LINK(NAME) \ NAME##_sizeof_headers, \ NAME##_bfd_get_relocated_section_contents, \ NAME##_bfd_relax_section, \ NAME##_bfd_link_hash_table_create, \ NAME##_bfd_link_hash_table_free, \ NAME##_bfd_link_add_symbols, \ NAME##_bfd_link_just_syms, \ NAME##_bfd_final_link, \ NAME##_bfd_link_split_section, \ NAME##_bfd_gc_sections, \ NAME##_bfd_merge_sections, \ NAME##_bfd_is_group_section, \ NAME##_bfd_discard_group, \ NAME##_section_already_linked \ int (*_bfd_sizeof_headers) (bfd *, struct bfd_link_info *); bfd_byte * (*_bfd_get_relocated_section_contents) (bfd *, struct bfd_link_info *, struct bfd_link_order *, bfd_byte *, bfd_boolean, struct bfd_symbol **); bfd_boolean (*_bfd_relax_section) (bfd *, struct bfd_section *, struct bfd_link_info *, bfd_boolean *); /* Create a hash table for the linker. Different backends store different information in this table. */ struct bfd_link_hash_table * (*_bfd_link_hash_table_create) (bfd *); /* Release the memory associated with the linker hash table. */ void (*_bfd_link_hash_table_free) (struct bfd_link_hash_table *); /* Add symbols from this object file into the hash table. */ bfd_boolean (*_bfd_link_add_symbols) (bfd *, struct bfd_link_info *); /* Indicate that we are only retrieving symbol values from this section. */ void (*_bfd_link_just_syms) (asection *, struct bfd_link_info *); /* Do a link based on the link_order structures attached to each section of the BFD. */ bfd_boolean (*_bfd_final_link) (bfd *, struct bfd_link_info *); /* Should this section be split up into smaller pieces during linking. */ bfd_boolean (*_bfd_link_split_section) (bfd *, struct bfd_section *); /* Remove sections that are not referenced from the output. */ bfd_boolean (*_bfd_gc_sections) (bfd *, struct bfd_link_info *); /* Attempt to merge SEC_MERGE sections. */ bfd_boolean (*_bfd_merge_sections) (bfd *, struct bfd_link_info *); /* Is this section a member of a group? */ bfd_boolean (*_bfd_is_group_section) (bfd *, const struct bfd_section *); /* Discard members of a group. */ bfd_boolean (*_bfd_discard_group) (bfd *, struct bfd_section *); /* Check if SEC has been already linked during a reloceatable or final link. */ void (*_section_already_linked) (bfd *, struct bfd_section *, struct bfd_link_info *); /* Routines to handle dynamic symbols and relocs. */ #define BFD_JUMP_TABLE_DYNAMIC(NAME) \ NAME##_get_dynamic_symtab_upper_bound, \ NAME##_canonicalize_dynamic_symtab, \ NAME##_get_synthetic_symtab, \ NAME##_get_dynamic_reloc_upper_bound, \ NAME##_canonicalize_dynamic_reloc /* Get the amount of memory required to hold the dynamic symbols. */ long (*_bfd_get_dynamic_symtab_upper_bound) (bfd *); /* Read in the dynamic symbols. */ long (*_bfd_canonicalize_dynamic_symtab) (bfd *, struct bfd_symbol **); /* Create synthetized symbols. */ long (*_bfd_get_synthetic_symtab) (bfd *, long, struct bfd_symbol **, long, struct bfd_symbol **, struct bfd_symbol **); /* Get the amount of memory required to hold the dynamic relocs. */ long (*_bfd_get_dynamic_reloc_upper_bound) (bfd *); /* Read in the dynamic relocs. */ long (*_bfd_canonicalize_dynamic_reloc) (bfd *, arelent **, struct bfd_symbol **); /* Opposite endian version of this target. */ const struct bfd_target * alternative_target; /* Data for use by back-end routines, which isn't generic enough to belong in this structure. */ const void *backend_data; } bfd_target; bfd_boolean bfd_set_default_target (const char *name); const bfd_target *bfd_find_target (const char *target_name, bfd *abfd); const char ** bfd_target_list (void); const bfd_target *bfd_search_for_target (int (*search_func) (const bfd_target *, void *), void *); /* Extracted from format.c. */ bfd_boolean bfd_check_format (bfd *abfd, bfd_format format); bfd_boolean bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching); bfd_boolean bfd_set_format (bfd *abfd, bfd_format format); const char *bfd_format_string (bfd_format format); /* Extracted from linker.c. */ bfd_boolean bfd_link_split_section (bfd *abfd, asection *sec); #define bfd_link_split_section(abfd, sec) \ BFD_SEND (abfd, _bfd_link_split_section, (abfd, sec)) void bfd_section_already_linked (bfd *abfd, asection *sec, struct bfd_link_info *info); #define bfd_section_already_linked(abfd, sec, info) \ BFD_SEND (abfd, _section_already_linked, (abfd, sec, info)) /* Extracted from simple.c. */ bfd_byte *bfd_simple_get_relocated_section_contents (bfd *abfd, asection *sec, bfd_byte *outbuf, asymbol **symbol_table); #ifdef __cplusplus } #endif #endif Index: head/contrib/binutils/bfd/ecoff.c =================================================================== --- head/contrib/binutils/bfd/ecoff.c (revision 275717) +++ head/contrib/binutils/bfd/ecoff.c (revision 275718) @@ -1,4634 +1,4634 @@ /* Generic ECOFF (Extended-COFF) routines. Copyright 1990, 1991, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. Original version by Per Bothner. Full support added by Ian Lance Taylor, ian@cygnus.com. This file is part of BFD, the Binary File Descriptor library. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ #include "sysdep.h" #include "bfd.h" #include "bfdlink.h" #include "libbfd.h" #include "aout/ar.h" #include "aout/ranlib.h" #include "aout/stab_gnu.h" /* FIXME: We need the definitions of N_SET[ADTB], but aout64.h defines some other stuff which we don't want and which conflicts with stuff we do want. */ #include "libaout.h" #include "aout/aout64.h" #undef N_ABS #undef exec_hdr #undef obj_sym_filepos #include "coff/internal.h" #include "coff/sym.h" #include "coff/symconst.h" #include "coff/ecoff.h" #include "libcoff.h" #include "libecoff.h" #include "libiberty.h" #define streq(a, b) (strcmp ((a), (b)) == 0) #define strneq(a, b, n) (strncmp ((a), (b), (n)) == 0) /* This stuff is somewhat copied from coffcode.h. */ static asection bfd_debug_section = { /* name, id, index, next, prev, flags, user_set_vma, */ "*DEBUG*", 0, 0, NULL, NULL, 0, 0, /* linker_mark, linker_has_input, gc_mark, gc_mark_from_eh, */ 0, 0, 1, 0, /* segment_mark, sec_info_type, use_rela_p, has_tls_reloc, */ 0, 0, 0, 0, - /* has_gp_reloc, need_finalize_relax, reloc_done, */ - 0, 0, 0, - /* vma, lma, size, rawsize, */ - 0, 0, 0, 0, + /* has_tls_get_addr_call, has_gp_reloc, need_finalize_relax, */ + 0, 0, 0, + /* reloc_done, vma, lma, size, rawsize, */ + 0, 0, 0, 0, 0, /* output_offset, output_section, alignment_power, */ 0, NULL, 0, /* relocation, orelocation, reloc_count, filepos, rel_filepos, */ NULL, NULL, 0, 0, 0, /* line_filepos, userdata, contents, lineno, lineno_count, */ 0, NULL, NULL, NULL, 0, /* entsize, kept_section, moving_line_filepos, */ 0, NULL, 0, /* target_index, used_by_bfd, constructor_chain, owner, */ 0, NULL, NULL, NULL, /* symbol, */ NULL, /* symbol_ptr_ptr, */ NULL, /* map_head, map_tail */ { NULL }, { NULL } }; /* Create an ECOFF object. */ bfd_boolean _bfd_ecoff_mkobject (bfd *abfd) { bfd_size_type amt = sizeof (ecoff_data_type); abfd->tdata.ecoff_obj_data = bfd_zalloc (abfd, amt); if (abfd->tdata.ecoff_obj_data == NULL) return FALSE; return TRUE; } /* This is a hook called by coff_real_object_p to create any backend specific information. */ void * _bfd_ecoff_mkobject_hook (bfd *abfd, void * filehdr, void * aouthdr) { struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr; struct internal_aouthdr *internal_a = (struct internal_aouthdr *) aouthdr; ecoff_data_type *ecoff; if (! _bfd_ecoff_mkobject (abfd)) return NULL; ecoff = ecoff_data (abfd); ecoff->gp_size = 8; ecoff->sym_filepos = internal_f->f_symptr; if (internal_a != NULL) { int i; ecoff->text_start = internal_a->text_start; ecoff->text_end = internal_a->text_start + internal_a->tsize; ecoff->gp = internal_a->gp_value; ecoff->gprmask = internal_a->gprmask; for (i = 0; i < 4; i++) ecoff->cprmask[i] = internal_a->cprmask[i]; ecoff->fprmask = internal_a->fprmask; if (internal_a->magic == ECOFF_AOUT_ZMAGIC) abfd->flags |= D_PAGED; else abfd->flags &=~ D_PAGED; } /* It turns out that no special action is required by the MIPS or Alpha ECOFF backends. They have different information in the a.out header, but we just copy it all (e.g., gprmask, cprmask and fprmask) and let the swapping routines ensure that only relevant information is written out. */ return (void *) ecoff; } /* Initialize a new section. */ bfd_boolean _bfd_ecoff_new_section_hook (bfd *abfd, asection *section) { unsigned int i; static struct { const char * name; flagword flags; } section_flags [] = { { _TEXT, SEC_ALLOC | SEC_CODE | SEC_LOAD }, { _INIT, SEC_ALLOC | SEC_CODE | SEC_LOAD }, { _FINI, SEC_ALLOC | SEC_CODE | SEC_LOAD }, { _DATA, SEC_ALLOC | SEC_DATA | SEC_LOAD }, { _SDATA, SEC_ALLOC | SEC_DATA | SEC_LOAD }, { _RDATA, SEC_ALLOC | SEC_DATA | SEC_LOAD | SEC_READONLY}, { _LIT8, SEC_ALLOC | SEC_DATA | SEC_LOAD | SEC_READONLY}, { _LIT4, SEC_ALLOC | SEC_DATA | SEC_LOAD | SEC_READONLY}, { _RCONST, SEC_ALLOC | SEC_DATA | SEC_LOAD | SEC_READONLY}, { _PDATA, SEC_ALLOC | SEC_DATA | SEC_LOAD | SEC_READONLY}, { _BSS, SEC_ALLOC}, { _SBSS, SEC_ALLOC}, /* An Irix 4 shared libary. */ { _LIB, SEC_COFF_SHARED_LIBRARY} }; section->alignment_power = 4; for (i = 0; i < ARRAY_SIZE (section_flags); i++) if (streq (section->name, section_flags[i].name)) { section->flags |= section_flags[i].flags; break; } /* Probably any other section name is SEC_NEVER_LOAD, but I'm uncertain about .init on some systems and I don't know how shared libraries work. */ return _bfd_generic_new_section_hook (abfd, section); } /* Determine the machine architecture and type. This is called from the generic COFF routines. It is the inverse of ecoff_get_magic, below. This could be an ECOFF backend routine, with one version for each target, but there aren't all that many ECOFF targets. */ bfd_boolean _bfd_ecoff_set_arch_mach_hook (bfd *abfd, void * filehdr) { struct internal_filehdr *internal_f = filehdr; enum bfd_architecture arch; unsigned long mach; switch (internal_f->f_magic) { case MIPS_MAGIC_1: case MIPS_MAGIC_LITTLE: case MIPS_MAGIC_BIG: arch = bfd_arch_mips; mach = bfd_mach_mips3000; break; case MIPS_MAGIC_LITTLE2: case MIPS_MAGIC_BIG2: /* MIPS ISA level 2: the r6000. */ arch = bfd_arch_mips; mach = bfd_mach_mips6000; break; case MIPS_MAGIC_LITTLE3: case MIPS_MAGIC_BIG3: /* MIPS ISA level 3: the r4000. */ arch = bfd_arch_mips; mach = bfd_mach_mips4000; break; case ALPHA_MAGIC: arch = bfd_arch_alpha; mach = 0; break; default: arch = bfd_arch_obscure; mach = 0; break; } return bfd_default_set_arch_mach (abfd, arch, mach); } /* Get the magic number to use based on the architecture and machine. This is the inverse of _bfd_ecoff_set_arch_mach_hook, above. */ static int ecoff_get_magic (bfd *abfd) { int big, little; switch (bfd_get_arch (abfd)) { case bfd_arch_mips: switch (bfd_get_mach (abfd)) { default: case 0: case bfd_mach_mips3000: big = MIPS_MAGIC_BIG; little = MIPS_MAGIC_LITTLE; break; case bfd_mach_mips6000: big = MIPS_MAGIC_BIG2; little = MIPS_MAGIC_LITTLE2; break; case bfd_mach_mips4000: big = MIPS_MAGIC_BIG3; little = MIPS_MAGIC_LITTLE3; break; } return bfd_big_endian (abfd) ? big : little; case bfd_arch_alpha: return ALPHA_MAGIC; default: abort (); return 0; } } /* Get the section s_flags to use for a section. */ static long ecoff_sec_to_styp_flags (const char *name, flagword flags) { unsigned int i; static struct { const char * name; long flags; } styp_flags [] = { { _TEXT, STYP_TEXT }, { _DATA, STYP_DATA }, { _SDATA, STYP_SDATA }, { _RDATA, STYP_RDATA }, { _LITA, STYP_LITA }, { _LIT8, STYP_LIT8 }, { _LIT4, STYP_LIT4 }, { _BSS, STYP_BSS }, { _SBSS, STYP_SBSS }, { _INIT, STYP_ECOFF_INIT }, { _FINI, STYP_ECOFF_FINI }, { _PDATA, STYP_PDATA }, { _XDATA, STYP_XDATA }, { _LIB, STYP_ECOFF_LIB }, { _GOT, STYP_GOT }, { _HASH, STYP_HASH }, { _DYNAMIC, STYP_DYNAMIC }, { _LIBLIST, STYP_LIBLIST }, { _RELDYN, STYP_RELDYN }, { _CONFLIC, STYP_CONFLIC }, { _DYNSTR, STYP_DYNSTR }, { _DYNSYM, STYP_DYNSYM }, { _RCONST, STYP_RCONST } }; long styp = 0; for (i = 0; i < ARRAY_SIZE (styp_flags); i++) if (streq (name, styp_flags[i].name)) { styp = styp_flags[i].flags; break; } if (styp == 0) { if (streq (name, _COMMENT)) { styp = STYP_COMMENT; flags &=~ SEC_NEVER_LOAD; } else if (flags & SEC_CODE) styp = STYP_TEXT; else if (flags & SEC_DATA) styp = STYP_DATA; else if (flags & SEC_READONLY) styp = STYP_RDATA; else if (flags & SEC_LOAD) styp = STYP_REG; else styp = STYP_BSS; } if (flags & SEC_NEVER_LOAD) styp |= STYP_NOLOAD; return styp; } /* Get the BFD flags to use for a section. */ bfd_boolean _bfd_ecoff_styp_to_sec_flags (bfd *abfd ATTRIBUTE_UNUSED, void * hdr, const char *name ATTRIBUTE_UNUSED, asection *section ATTRIBUTE_UNUSED, flagword * flags_ptr) { struct internal_scnhdr *internal_s = hdr; long styp_flags = internal_s->s_flags; flagword sec_flags = 0; if (styp_flags & STYP_NOLOAD) sec_flags |= SEC_NEVER_LOAD; /* For 386 COFF, at least, an unloadable text or data section is actually a shared library section. */ if ((styp_flags & STYP_TEXT) || (styp_flags & STYP_ECOFF_INIT) || (styp_flags & STYP_ECOFF_FINI) || (styp_flags & STYP_DYNAMIC) || (styp_flags & STYP_LIBLIST) || (styp_flags & STYP_RELDYN) || styp_flags == STYP_CONFLIC || (styp_flags & STYP_DYNSTR) || (styp_flags & STYP_DYNSYM) || (styp_flags & STYP_HASH)) { if (sec_flags & SEC_NEVER_LOAD) sec_flags |= SEC_CODE | SEC_COFF_SHARED_LIBRARY; else sec_flags |= SEC_CODE | SEC_LOAD | SEC_ALLOC; } else if ((styp_flags & STYP_DATA) || (styp_flags & STYP_RDATA) || (styp_flags & STYP_SDATA) || styp_flags == STYP_PDATA || styp_flags == STYP_XDATA || (styp_flags & STYP_GOT) || styp_flags == STYP_RCONST) { if (sec_flags & SEC_NEVER_LOAD) sec_flags |= SEC_DATA | SEC_COFF_SHARED_LIBRARY; else sec_flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC; if ((styp_flags & STYP_RDATA) || styp_flags == STYP_PDATA || styp_flags == STYP_RCONST) sec_flags |= SEC_READONLY; } else if ((styp_flags & STYP_BSS) || (styp_flags & STYP_SBSS)) sec_flags |= SEC_ALLOC; else if ((styp_flags & STYP_INFO) || styp_flags == STYP_COMMENT) sec_flags |= SEC_NEVER_LOAD; else if ((styp_flags & STYP_LITA) || (styp_flags & STYP_LIT8) || (styp_flags & STYP_LIT4)) sec_flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC | SEC_READONLY; else if (styp_flags & STYP_ECOFF_LIB) sec_flags |= SEC_COFF_SHARED_LIBRARY; else sec_flags |= SEC_ALLOC | SEC_LOAD; * flags_ptr = sec_flags; return TRUE; } /* Read in the symbolic header for an ECOFF object file. */ static bfd_boolean ecoff_slurp_symbolic_header (bfd *abfd) { const struct ecoff_backend_data * const backend = ecoff_backend (abfd); bfd_size_type external_hdr_size; void * raw = NULL; HDRR *internal_symhdr; /* See if we've already read it in. */ if (ecoff_data (abfd)->debug_info.symbolic_header.magic == backend->debug_swap.sym_magic) return TRUE; /* See whether there is a symbolic header. */ if (ecoff_data (abfd)->sym_filepos == 0) { bfd_get_symcount (abfd) = 0; return TRUE; } /* At this point bfd_get_symcount (abfd) holds the number of symbols as read from the file header, but on ECOFF this is always the size of the symbolic information header. It would be cleaner to handle this when we first read the file in coffgen.c. */ external_hdr_size = backend->debug_swap.external_hdr_size; if (bfd_get_symcount (abfd) != external_hdr_size) { bfd_set_error (bfd_error_bad_value); return FALSE; } /* Read the symbolic information header. */ raw = bfd_malloc (external_hdr_size); if (raw == NULL) goto error_return; if (bfd_seek (abfd, ecoff_data (abfd)->sym_filepos, SEEK_SET) != 0 || bfd_bread (raw, external_hdr_size, abfd) != external_hdr_size) goto error_return; internal_symhdr = &ecoff_data (abfd)->debug_info.symbolic_header; (*backend->debug_swap.swap_hdr_in) (abfd, raw, internal_symhdr); if (internal_symhdr->magic != backend->debug_swap.sym_magic) { bfd_set_error (bfd_error_bad_value); goto error_return; } /* Now we can get the correct number of symbols. */ bfd_get_symcount (abfd) = (internal_symhdr->isymMax + internal_symhdr->iextMax); if (raw != NULL) free (raw); return TRUE; error_return: if (raw != NULL) free (raw); return FALSE; } /* Read in and swap the important symbolic information for an ECOFF object file. This is called by gdb via the read_debug_info entry point in the backend structure. */ bfd_boolean _bfd_ecoff_slurp_symbolic_info (bfd *abfd, asection *ignore ATTRIBUTE_UNUSED, struct ecoff_debug_info *debug) { const struct ecoff_backend_data * const backend = ecoff_backend (abfd); HDRR *internal_symhdr; bfd_size_type raw_base; bfd_size_type raw_size; void * raw; bfd_size_type external_fdr_size; char *fraw_src; char *fraw_end; struct fdr *fdr_ptr; bfd_size_type raw_end; bfd_size_type cb_end; bfd_size_type amt; file_ptr pos; BFD_ASSERT (debug == &ecoff_data (abfd)->debug_info); /* Check whether we've already gotten it, and whether there's any to get. */ if (ecoff_data (abfd)->raw_syments != NULL) return TRUE; if (ecoff_data (abfd)->sym_filepos == 0) { bfd_get_symcount (abfd) = 0; return TRUE; } if (! ecoff_slurp_symbolic_header (abfd)) return FALSE; internal_symhdr = &debug->symbolic_header; /* Read all the symbolic information at once. */ raw_base = (ecoff_data (abfd)->sym_filepos + backend->debug_swap.external_hdr_size); /* Alpha ecoff makes the determination of raw_size difficult. It has an undocumented debug data section between the symhdr and the first documented section. And the ordering of the sections varies between statically and dynamically linked executables. If bfd supports SEEK_END someday, this code could be simplified. */ raw_end = 0; #define UPDATE_RAW_END(start, count, size) \ cb_end = internal_symhdr->start + internal_symhdr->count * (size); \ if (cb_end > raw_end) \ raw_end = cb_end UPDATE_RAW_END (cbLineOffset, cbLine, sizeof (unsigned char)); UPDATE_RAW_END (cbDnOffset, idnMax, backend->debug_swap.external_dnr_size); UPDATE_RAW_END (cbPdOffset, ipdMax, backend->debug_swap.external_pdr_size); UPDATE_RAW_END (cbSymOffset, isymMax, backend->debug_swap.external_sym_size); /* eraxxon@alumni.rice.edu: ioptMax refers to the size of the optimization symtab, not the number of entries. */ UPDATE_RAW_END (cbOptOffset, ioptMax, sizeof (char)); UPDATE_RAW_END (cbAuxOffset, iauxMax, sizeof (union aux_ext)); UPDATE_RAW_END (cbSsOffset, issMax, sizeof (char)); UPDATE_RAW_END (cbSsExtOffset, issExtMax, sizeof (char)); UPDATE_RAW_END (cbFdOffset, ifdMax, backend->debug_swap.external_fdr_size); UPDATE_RAW_END (cbRfdOffset, crfd, backend->debug_swap.external_rfd_size); UPDATE_RAW_END (cbExtOffset, iextMax, backend->debug_swap.external_ext_size); #undef UPDATE_RAW_END raw_size = raw_end - raw_base; if (raw_size == 0) { ecoff_data (abfd)->sym_filepos = 0; return TRUE; } raw = bfd_alloc (abfd, raw_size); if (raw == NULL) return FALSE; pos = ecoff_data (abfd)->sym_filepos; pos += backend->debug_swap.external_hdr_size; if (bfd_seek (abfd, pos, SEEK_SET) != 0 || bfd_bread (raw, raw_size, abfd) != raw_size) { bfd_release (abfd, raw); return FALSE; } ecoff_data (abfd)->raw_syments = raw; /* Get pointers for the numeric offsets in the HDRR structure. */ #define FIX(off1, off2, type) \ if (internal_symhdr->off1 == 0) \ debug->off2 = NULL; \ else \ debug->off2 = (type) ((char *) raw \ + (internal_symhdr->off1 \ - raw_base)) FIX (cbLineOffset, line, unsigned char *); FIX (cbDnOffset, external_dnr, void *); FIX (cbPdOffset, external_pdr, void *); FIX (cbSymOffset, external_sym, void *); FIX (cbOptOffset, external_opt, void *); FIX (cbAuxOffset, external_aux, union aux_ext *); FIX (cbSsOffset, ss, char *); FIX (cbSsExtOffset, ssext, char *); FIX (cbFdOffset, external_fdr, void *); FIX (cbRfdOffset, external_rfd, void *); FIX (cbExtOffset, external_ext, void *); #undef FIX /* I don't want to always swap all the data, because it will just waste time and most programs will never look at it. The only time the linker needs most of the debugging information swapped is when linking big-endian and little-endian MIPS object files together, which is not a common occurrence. We need to look at the fdr to deal with a lot of information in the symbols, so we swap them here. */ amt = internal_symhdr->ifdMax; amt *= sizeof (struct fdr); debug->fdr = bfd_alloc (abfd, amt); if (debug->fdr == NULL) return FALSE; external_fdr_size = backend->debug_swap.external_fdr_size; fdr_ptr = debug->fdr; fraw_src = (char *) debug->external_fdr; fraw_end = fraw_src + internal_symhdr->ifdMax * external_fdr_size; for (; fraw_src < fraw_end; fraw_src += external_fdr_size, fdr_ptr++) (*backend->debug_swap.swap_fdr_in) (abfd, (void *) fraw_src, fdr_ptr); return TRUE; } /* ECOFF symbol table routines. The ECOFF symbol table is described in gcc/mips-tfile.c. */ /* ECOFF uses two common sections. One is the usual one, and the other is for small objects. All the small objects are kept together, and then referenced via the gp pointer, which yields faster assembler code. This is what we use for the small common section. */ static asection ecoff_scom_section; static asymbol ecoff_scom_symbol; static asymbol *ecoff_scom_symbol_ptr; /* Create an empty symbol. */ asymbol * _bfd_ecoff_make_empty_symbol (bfd *abfd) { ecoff_symbol_type *new; bfd_size_type amt = sizeof (ecoff_symbol_type); new = bfd_zalloc (abfd, amt); if (new == NULL) return NULL; new->symbol.section = NULL; new->fdr = NULL; new->local = FALSE; new->native = NULL; new->symbol.the_bfd = abfd; return &new->symbol; } /* Set the BFD flags and section for an ECOFF symbol. */ static bfd_boolean ecoff_set_symbol_info (bfd *abfd, SYMR *ecoff_sym, asymbol *asym, int ext, int weak) { asym->the_bfd = abfd; asym->value = ecoff_sym->value; asym->section = &bfd_debug_section; asym->udata.i = 0; /* Most symbol types are just for debugging. */ switch (ecoff_sym->st) { case stGlobal: case stStatic: case stLabel: case stProc: case stStaticProc: break; case stNil: if (ECOFF_IS_STAB (ecoff_sym)) { asym->flags = BSF_DEBUGGING; return TRUE; } break; default: asym->flags = BSF_DEBUGGING; return TRUE; } if (weak) asym->flags = BSF_EXPORT | BSF_WEAK; else if (ext) asym->flags = BSF_EXPORT | BSF_GLOBAL; else { asym->flags = BSF_LOCAL; /* Normally, a local stProc symbol will have a corresponding external symbol. We mark the local symbol as a debugging symbol, in order to prevent nm from printing both out. Similarly, we mark stLabel and stabs symbols as debugging symbols. In both cases, we do want to set the value correctly based on the symbol class. */ if (ecoff_sym->st == stProc || ecoff_sym->st == stLabel || ECOFF_IS_STAB (ecoff_sym)) asym->flags |= BSF_DEBUGGING; } if (ecoff_sym->st == stProc || ecoff_sym->st == stStaticProc) asym->flags |= BSF_FUNCTION; switch (ecoff_sym->sc) { case scNil: /* Used for compiler generated labels. Leave them in the debugging section, and mark them as local. If BSF_DEBUGGING is set, then nm does not display them for some reason. If no flags are set then the linker whines about them. */ asym->flags = BSF_LOCAL; break; case scText: asym->section = bfd_make_section_old_way (abfd, _TEXT); asym->value -= asym->section->vma; break; case scData: asym->section = bfd_make_section_old_way (abfd, _DATA); asym->value -= asym->section->vma; break; case scBss: asym->section = bfd_make_section_old_way (abfd, _BSS); asym->value -= asym->section->vma; break; case scRegister: asym->flags = BSF_DEBUGGING; break; case scAbs: asym->section = bfd_abs_section_ptr; break; case scUndefined: asym->section = bfd_und_section_ptr; asym->flags = 0; asym->value = 0; break; case scCdbLocal: case scBits: case scCdbSystem: case scRegImage: case scInfo: case scUserStruct: asym->flags = BSF_DEBUGGING; break; case scSData: asym->section = bfd_make_section_old_way (abfd, ".sdata"); asym->value -= asym->section->vma; break; case scSBss: asym->section = bfd_make_section_old_way (abfd, ".sbss"); asym->value -= asym->section->vma; break; case scRData: asym->section = bfd_make_section_old_way (abfd, ".rdata"); asym->value -= asym->section->vma; break; case scVar: asym->flags = BSF_DEBUGGING; break; case scCommon: if (asym->value > ecoff_data (abfd)->gp_size) { asym->section = bfd_com_section_ptr; asym->flags = 0; break; } /* Fall through. */ case scSCommon: if (ecoff_scom_section.name == NULL) { /* Initialize the small common section. */ ecoff_scom_section.name = SCOMMON; ecoff_scom_section.flags = SEC_IS_COMMON; ecoff_scom_section.output_section = &ecoff_scom_section; ecoff_scom_section.symbol = &ecoff_scom_symbol; ecoff_scom_section.symbol_ptr_ptr = &ecoff_scom_symbol_ptr; ecoff_scom_symbol.name = SCOMMON; ecoff_scom_symbol.flags = BSF_SECTION_SYM; ecoff_scom_symbol.section = &ecoff_scom_section; ecoff_scom_symbol_ptr = &ecoff_scom_symbol; } asym->section = &ecoff_scom_section; asym->flags = 0; break; case scVarRegister: case scVariant: asym->flags = BSF_DEBUGGING; break; case scSUndefined: asym->section = bfd_und_section_ptr; asym->flags = 0; asym->value = 0; break; case scInit: asym->section = bfd_make_section_old_way (abfd, ".init"); asym->value -= asym->section->vma; break; case scBasedVar: case scXData: case scPData: asym->flags = BSF_DEBUGGING; break; case scFini: asym->section = bfd_make_section_old_way (abfd, ".fini"); asym->value -= asym->section->vma; break; case scRConst: asym->section = bfd_make_section_old_way (abfd, ".rconst"); asym->value -= asym->section->vma; break; default: break; } /* Look for special constructors symbols and make relocation entries in a special construction section. These are produced by the -fgnu-linker argument to g++. */ if (ECOFF_IS_STAB (ecoff_sym)) { switch (ECOFF_UNMARK_STAB (ecoff_sym->index)) { default: break; case N_SETA: case N_SETT: case N_SETD: case N_SETB: /* Mark the symbol as a constructor. */ asym->flags |= BSF_CONSTRUCTOR; break; } } return TRUE; } /* Read an ECOFF symbol table. */ bfd_boolean _bfd_ecoff_slurp_symbol_table (bfd *abfd) { const struct ecoff_backend_data * const backend = ecoff_backend (abfd); const bfd_size_type external_ext_size = backend->debug_swap.external_ext_size; const bfd_size_type external_sym_size = backend->debug_swap.external_sym_size; void (* const swap_ext_in) (bfd *, void *, EXTR *) = backend->debug_swap.swap_ext_in; void (* const swap_sym_in) (bfd *, void *, SYMR *) = backend->debug_swap.swap_sym_in; bfd_size_type internal_size; ecoff_symbol_type *internal; ecoff_symbol_type *internal_ptr; char *eraw_src; char *eraw_end; FDR *fdr_ptr; FDR *fdr_end; /* If we've already read in the symbol table, do nothing. */ if (ecoff_data (abfd)->canonical_symbols != NULL) return TRUE; /* Get the symbolic information. */ if (! _bfd_ecoff_slurp_symbolic_info (abfd, NULL, &ecoff_data (abfd)->debug_info)) return FALSE; if (bfd_get_symcount (abfd) == 0) return TRUE; internal_size = bfd_get_symcount (abfd); internal_size *= sizeof (ecoff_symbol_type); internal = bfd_alloc (abfd, internal_size); if (internal == NULL) return FALSE; internal_ptr = internal; eraw_src = (char *) ecoff_data (abfd)->debug_info.external_ext; eraw_end = (eraw_src + (ecoff_data (abfd)->debug_info.symbolic_header.iextMax * external_ext_size)); for (; eraw_src < eraw_end; eraw_src += external_ext_size, internal_ptr++) { EXTR internal_esym; (*swap_ext_in) (abfd, (void *) eraw_src, &internal_esym); internal_ptr->symbol.name = (ecoff_data (abfd)->debug_info.ssext + internal_esym.asym.iss); if (!ecoff_set_symbol_info (abfd, &internal_esym.asym, &internal_ptr->symbol, 1, internal_esym.weakext)) return FALSE; /* The alpha uses a negative ifd field for section symbols. */ if (internal_esym.ifd >= 0) internal_ptr->fdr = (ecoff_data (abfd)->debug_info.fdr + internal_esym.ifd); else internal_ptr->fdr = NULL; internal_ptr->local = FALSE; internal_ptr->native = (void *) eraw_src; } /* The local symbols must be accessed via the fdr's, because the string and aux indices are relative to the fdr information. */ fdr_ptr = ecoff_data (abfd)->debug_info.fdr; fdr_end = fdr_ptr + ecoff_data (abfd)->debug_info.symbolic_header.ifdMax; for (; fdr_ptr < fdr_end; fdr_ptr++) { char *lraw_src; char *lraw_end; lraw_src = ((char *) ecoff_data (abfd)->debug_info.external_sym + fdr_ptr->isymBase * external_sym_size); lraw_end = lraw_src + fdr_ptr->csym * external_sym_size; for (; lraw_src < lraw_end; lraw_src += external_sym_size, internal_ptr++) { SYMR internal_sym; (*swap_sym_in) (abfd, (void *) lraw_src, &internal_sym); internal_ptr->symbol.name = (ecoff_data (abfd)->debug_info.ss + fdr_ptr->issBase + internal_sym.iss); if (!ecoff_set_symbol_info (abfd, &internal_sym, &internal_ptr->symbol, 0, 0)) return FALSE; internal_ptr->fdr = fdr_ptr; internal_ptr->local = TRUE; internal_ptr->native = (void *) lraw_src; } } ecoff_data (abfd)->canonical_symbols = internal; return TRUE; } /* Return the amount of space needed for the canonical symbols. */ long _bfd_ecoff_get_symtab_upper_bound (bfd *abfd) { if (! _bfd_ecoff_slurp_symbolic_info (abfd, NULL, &ecoff_data (abfd)->debug_info)) return -1; if (bfd_get_symcount (abfd) == 0) return 0; return (bfd_get_symcount (abfd) + 1) * (sizeof (ecoff_symbol_type *)); } /* Get the canonical symbols. */ long _bfd_ecoff_canonicalize_symtab (bfd *abfd, asymbol **alocation) { unsigned int counter = 0; ecoff_symbol_type *symbase; ecoff_symbol_type **location = (ecoff_symbol_type **) alocation; if (! _bfd_ecoff_slurp_symbol_table (abfd)) return -1; if (bfd_get_symcount (abfd) == 0) return 0; symbase = ecoff_data (abfd)->canonical_symbols; while (counter < bfd_get_symcount (abfd)) { *(location++) = symbase++; counter++; } *location++ = NULL; return bfd_get_symcount (abfd); } /* Turn ECOFF type information into a printable string. ecoff_emit_aggregate and ecoff_type_to_string are from gcc/mips-tdump.c, with swapping added and used_ptr removed. */ /* Write aggregate information to a string. */ static void ecoff_emit_aggregate (bfd *abfd, FDR *fdr, char *string, RNDXR *rndx, long isym, const char *which) { const struct ecoff_debug_swap * const debug_swap = &ecoff_backend (abfd)->debug_swap; struct ecoff_debug_info * const debug_info = &ecoff_data (abfd)->debug_info; unsigned int ifd = rndx->rfd; unsigned int indx = rndx->index; const char *name; if (ifd == 0xfff) ifd = isym; /* An ifd of -1 is an opaque type. An escaped index of 0 is a struct return type of a procedure compiled without -g. */ if (ifd == 0xffffffff || (rndx->rfd == 0xfff && indx == 0)) name = ""; else if (indx == indexNil) name = ""; else { SYMR sym; if (debug_info->external_rfd == NULL) fdr = debug_info->fdr + ifd; else { RFDT rfd; (*debug_swap->swap_rfd_in) (abfd, ((char *) debug_info->external_rfd + ((fdr->rfdBase + ifd) * debug_swap->external_rfd_size)), &rfd); fdr = debug_info->fdr + rfd; } indx += fdr->isymBase; (*debug_swap->swap_sym_in) (abfd, ((char *) debug_info->external_sym + indx * debug_swap->external_sym_size), &sym); name = debug_info->ss + fdr->issBase + sym.iss; } sprintf (string, "%s %s { ifd = %u, index = %lu }", which, name, ifd, ((long) indx + debug_info->symbolic_header.iextMax)); } /* Convert the type information to string format. */ static char * ecoff_type_to_string (bfd *abfd, FDR *fdr, unsigned int indx) { union aux_ext *aux_ptr; int bigendian; AUXU u; struct qual { unsigned int type; int low_bound; int high_bound; int stride; } qualifiers[7]; unsigned int basic_type; int i; char buffer1[1024]; static char buffer2[1024]; char *p1 = buffer1; char *p2 = buffer2; RNDXR rndx; aux_ptr = ecoff_data (abfd)->debug_info.external_aux + fdr->iauxBase; bigendian = fdr->fBigendian; for (i = 0; i < 7; i++) { qualifiers[i].low_bound = 0; qualifiers[i].high_bound = 0; qualifiers[i].stride = 0; } if (AUX_GET_ISYM (bigendian, &aux_ptr[indx]) == (bfd_vma) -1) return "-1 (no type)"; _bfd_ecoff_swap_tir_in (bigendian, &aux_ptr[indx++].a_ti, &u.ti); basic_type = u.ti.bt; qualifiers[0].type = u.ti.tq0; qualifiers[1].type = u.ti.tq1; qualifiers[2].type = u.ti.tq2; qualifiers[3].type = u.ti.tq3; qualifiers[4].type = u.ti.tq4; qualifiers[5].type = u.ti.tq5; qualifiers[6].type = tqNil; /* Go get the basic type. */ switch (basic_type) { case btNil: /* Undefined. */ strcpy (p1, "nil"); break; case btAdr: /* Address - integer same size as pointer. */ strcpy (p1, "address"); break; case btChar: /* Character. */ strcpy (p1, "char"); break; case btUChar: /* Unsigned character. */ strcpy (p1, "unsigned char"); break; case btShort: /* Short. */ strcpy (p1, "short"); break; case btUShort: /* Unsigned short. */ strcpy (p1, "unsigned short"); break; case btInt: /* Int. */ strcpy (p1, "int"); break; case btUInt: /* Unsigned int. */ strcpy (p1, "unsigned int"); break; case btLong: /* Long. */ strcpy (p1, "long"); break; case btULong: /* Unsigned long. */ strcpy (p1, "unsigned long"); break; case btFloat: /* Float (real). */ strcpy (p1, "float"); break; case btDouble: /* Double (real). */ strcpy (p1, "double"); break; /* Structures add 1-2 aux words: 1st word is [ST_RFDESCAPE, offset] pointer to struct def; 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */ case btStruct: /* Structure (Record). */ _bfd_ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx); ecoff_emit_aggregate (abfd, fdr, p1, &rndx, (long) AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]), "struct"); indx++; /* Skip aux words. */ break; /* Unions add 1-2 aux words: 1st word is [ST_RFDESCAPE, offset] pointer to union def; 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */ case btUnion: /* Union. */ _bfd_ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx); ecoff_emit_aggregate (abfd, fdr, p1, &rndx, (long) AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]), "union"); indx++; /* Skip aux words. */ break; /* Enumerations add 1-2 aux words: 1st word is [ST_RFDESCAPE, offset] pointer to enum def; 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */ case btEnum: /* Enumeration. */ _bfd_ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx); ecoff_emit_aggregate (abfd, fdr, p1, &rndx, (long) AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]), "enum"); indx++; /* Skip aux words. */ break; case btTypedef: /* Defined via a typedef, isymRef points. */ strcpy (p1, "typedef"); break; case btRange: /* Subrange of int. */ strcpy (p1, "subrange"); break; case btSet: /* Pascal sets. */ strcpy (p1, "set"); break; case btComplex: /* Fortran complex. */ strcpy (p1, "complex"); break; case btDComplex: /* Fortran double complex. */ strcpy (p1, "double complex"); break; case btIndirect: /* Forward or unnamed typedef. */ strcpy (p1, "forward/unamed typedef"); break; case btFixedDec: /* Fixed Decimal. */ strcpy (p1, "fixed decimal"); break; case btFloatDec: /* Float Decimal. */ strcpy (p1, "float decimal"); break; case btString: /* Varying Length Character String. */ strcpy (p1, "string"); break; case btBit: /* Aligned Bit String. */ strcpy (p1, "bit"); break; case btPicture: /* Picture. */ strcpy (p1, "picture"); break; case btVoid: /* Void. */ strcpy (p1, "void"); break; default: sprintf (p1, _("Unknown basic type %d"), (int) basic_type); break; } p1 += strlen (buffer1); /* If this is a bitfield, get the bitsize. */ if (u.ti.fBitfield) { int bitsize; bitsize = AUX_GET_WIDTH (bigendian, &aux_ptr[indx++]); sprintf (p1, " : %d", bitsize); p1 += strlen (buffer1); } /* Deal with any qualifiers. */ if (qualifiers[0].type != tqNil) { /* Snarf up any array bounds in the correct order. Arrays store 5 successive words in the aux. table: word 0 RNDXR to type of the bounds (ie, int) word 1 Current file descriptor index word 2 low bound word 3 high bound (or -1 if []) word 4 stride size in bits. */ for (i = 0; i < 7; i++) { if (qualifiers[i].type == tqArray) { qualifiers[i].low_bound = AUX_GET_DNLOW (bigendian, &aux_ptr[indx+2]); qualifiers[i].high_bound = AUX_GET_DNHIGH (bigendian, &aux_ptr[indx+3]); qualifiers[i].stride = AUX_GET_WIDTH (bigendian, &aux_ptr[indx+4]); indx += 5; } } /* Now print out the qualifiers. */ for (i = 0; i < 6; i++) { switch (qualifiers[i].type) { case tqNil: case tqMax: break; case tqPtr: strcpy (p2, "ptr to "); p2 += sizeof ("ptr to ")-1; break; case tqVol: strcpy (p2, "volatile "); p2 += sizeof ("volatile ")-1; break; case tqFar: strcpy (p2, "far "); p2 += sizeof ("far ")-1; break; case tqProc: strcpy (p2, "func. ret. "); p2 += sizeof ("func. ret. "); break; case tqArray: { int first_array = i; int j; /* Print array bounds reversed (ie, in the order the C programmer writes them). C is such a fun language.... */ while (i < 5 && qualifiers[i+1].type == tqArray) i++; for (j = i; j >= first_array; j--) { strcpy (p2, "array ["); p2 += sizeof ("array [")-1; if (qualifiers[j].low_bound != 0) sprintf (p2, "%ld:%ld {%ld bits}", (long) qualifiers[j].low_bound, (long) qualifiers[j].high_bound, (long) qualifiers[j].stride); else if (qualifiers[j].high_bound != -1) sprintf (p2, "%ld {%ld bits}", (long) (qualifiers[j].high_bound + 1), (long) (qualifiers[j].stride)); else sprintf (p2, " {%ld bits}", (long) (qualifiers[j].stride)); p2 += strlen (p2); strcpy (p2, "] of "); p2 += sizeof ("] of ")-1; } } break; } } } strcpy (p2, buffer1); return buffer2; } /* Return information about ECOFF symbol SYMBOL in RET. */ void _bfd_ecoff_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED, asymbol *symbol, symbol_info *ret) { bfd_symbol_info (symbol, ret); } /* Return whether this is a local label. */ bfd_boolean _bfd_ecoff_bfd_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED, const char *name) { return name[0] == '$'; } /* Print information about an ECOFF symbol. */ void _bfd_ecoff_print_symbol (bfd *abfd, void * filep, asymbol *symbol, bfd_print_symbol_type how) { const struct ecoff_debug_swap * const debug_swap = &ecoff_backend (abfd)->debug_swap; FILE *file = (FILE *)filep; switch (how) { case bfd_print_symbol_name: fprintf (file, "%s", symbol->name); break; case bfd_print_symbol_more: if (ecoffsymbol (symbol)->local) { SYMR ecoff_sym; (*debug_swap->swap_sym_in) (abfd, ecoffsymbol (symbol)->native, &ecoff_sym); fprintf (file, "ecoff local "); fprintf_vma (file, (bfd_vma) ecoff_sym.value); fprintf (file, " %x %x", (unsigned) ecoff_sym.st, (unsigned) ecoff_sym.sc); } else { EXTR ecoff_ext; (*debug_swap->swap_ext_in) (abfd, ecoffsymbol (symbol)->native, &ecoff_ext); fprintf (file, "ecoff extern "); fprintf_vma (file, (bfd_vma) ecoff_ext.asym.value); fprintf (file, " %x %x", (unsigned) ecoff_ext.asym.st, (unsigned) ecoff_ext.asym.sc); } break; case bfd_print_symbol_all: /* Print out the symbols in a reasonable way. */ { char type; int pos; EXTR ecoff_ext; char jmptbl; char cobol_main; char weakext; if (ecoffsymbol (symbol)->local) { (*debug_swap->swap_sym_in) (abfd, ecoffsymbol (symbol)->native, &ecoff_ext.asym); type = 'l'; pos = ((((char *) ecoffsymbol (symbol)->native - (char *) ecoff_data (abfd)->debug_info.external_sym) / debug_swap->external_sym_size) + ecoff_data (abfd)->debug_info.symbolic_header.iextMax); jmptbl = ' '; cobol_main = ' '; weakext = ' '; } else { (*debug_swap->swap_ext_in) (abfd, ecoffsymbol (symbol)->native, &ecoff_ext); type = 'e'; pos = (((char *) ecoffsymbol (symbol)->native - (char *) ecoff_data (abfd)->debug_info.external_ext) / debug_swap->external_ext_size); jmptbl = ecoff_ext.jmptbl ? 'j' : ' '; cobol_main = ecoff_ext.cobol_main ? 'c' : ' '; weakext = ecoff_ext.weakext ? 'w' : ' '; } fprintf (file, "[%3d] %c ", pos, type); fprintf_vma (file, (bfd_vma) ecoff_ext.asym.value); fprintf (file, " st %x sc %x indx %x %c%c%c %s", (unsigned) ecoff_ext.asym.st, (unsigned) ecoff_ext.asym.sc, (unsigned) ecoff_ext.asym.index, jmptbl, cobol_main, weakext, symbol->name); if (ecoffsymbol (symbol)->fdr != NULL && ecoff_ext.asym.index != indexNil) { FDR *fdr; unsigned int indx; int bigendian; bfd_size_type sym_base; union aux_ext *aux_base; fdr = ecoffsymbol (symbol)->fdr; indx = ecoff_ext.asym.index; /* sym_base is used to map the fdr relative indices which appear in the file to the position number which we are using. */ sym_base = fdr->isymBase; if (ecoffsymbol (symbol)->local) sym_base += ecoff_data (abfd)->debug_info.symbolic_header.iextMax; /* aux_base is the start of the aux entries for this file; asym.index is an offset from this. */ aux_base = (ecoff_data (abfd)->debug_info.external_aux + fdr->iauxBase); /* The aux entries are stored in host byte order; the order is indicated by a bit in the fdr. */ bigendian = fdr->fBigendian; /* This switch is basically from gcc/mips-tdump.c. */ switch (ecoff_ext.asym.st) { case stNil: case stLabel: break; case stFile: case stBlock: fprintf (file, _("\n End+1 symbol: %ld"), (long) (indx + sym_base)); break; case stEnd: if (ecoff_ext.asym.sc == scText || ecoff_ext.asym.sc == scInfo) fprintf (file, _("\n First symbol: %ld"), (long) (indx + sym_base)); else fprintf (file, _("\n First symbol: %ld"), ((long) (AUX_GET_ISYM (bigendian, &aux_base[ecoff_ext.asym.index]) + sym_base))); break; case stProc: case stStaticProc: if (ECOFF_IS_STAB (&ecoff_ext.asym)) ; else if (ecoffsymbol (symbol)->local) fprintf (file, _("\n End+1 symbol: %-7ld Type: %s"), ((long) (AUX_GET_ISYM (bigendian, &aux_base[ecoff_ext.asym.index]) + sym_base)), ecoff_type_to_string (abfd, fdr, indx + 1)); else fprintf (file, _("\n Local symbol: %ld"), ((long) indx + (long) sym_base + (ecoff_data (abfd) ->debug_info.symbolic_header.iextMax))); break; case stStruct: fprintf (file, _("\n struct; End+1 symbol: %ld"), (long) (indx + sym_base)); break; case stUnion: fprintf (file, _("\n union; End+1 symbol: %ld"), (long) (indx + sym_base)); break; case stEnum: fprintf (file, _("\n enum; End+1 symbol: %ld"), (long) (indx + sym_base)); break; default: if (! ECOFF_IS_STAB (&ecoff_ext.asym)) fprintf (file, _("\n Type: %s"), ecoff_type_to_string (abfd, fdr, indx)); break; } } } break; } } /* Read in the relocs for a section. */ static bfd_boolean ecoff_slurp_reloc_table (bfd *abfd, asection *section, asymbol **symbols) { const struct ecoff_backend_data * const backend = ecoff_backend (abfd); arelent *internal_relocs; bfd_size_type external_reloc_size; bfd_size_type amt; char *external_relocs; arelent *rptr; unsigned int i; if (section->relocation != NULL || section->reloc_count == 0 || (section->flags & SEC_CONSTRUCTOR) != 0) return TRUE; if (! _bfd_ecoff_slurp_symbol_table (abfd)) return FALSE; amt = section->reloc_count; amt *= sizeof (arelent); internal_relocs = bfd_alloc (abfd, amt); external_reloc_size = backend->external_reloc_size; amt = external_reloc_size * section->reloc_count; external_relocs = bfd_alloc (abfd, amt); if (internal_relocs == NULL || external_relocs == NULL) return FALSE; if (bfd_seek (abfd, section->rel_filepos, SEEK_SET) != 0) return FALSE; if (bfd_bread (external_relocs, amt, abfd) != amt) return FALSE; for (i = 0, rptr = internal_relocs; i < section->reloc_count; i++, rptr++) { struct internal_reloc intern; (*backend->swap_reloc_in) (abfd, external_relocs + i * external_reloc_size, &intern); if (intern.r_extern) { /* r_symndx is an index into the external symbols. */ BFD_ASSERT (intern.r_symndx >= 0 && (intern.r_symndx < (ecoff_data (abfd) ->debug_info.symbolic_header.iextMax))); rptr->sym_ptr_ptr = symbols + intern.r_symndx; rptr->addend = 0; } else if (intern.r_symndx == RELOC_SECTION_NONE || intern.r_symndx == RELOC_SECTION_ABS) { rptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; rptr->addend = 0; } else { const char *sec_name; asection *sec; /* r_symndx is a section key. */ switch (intern.r_symndx) { case RELOC_SECTION_TEXT: sec_name = _TEXT; break; case RELOC_SECTION_RDATA: sec_name = _RDATA; break; case RELOC_SECTION_DATA: sec_name = _DATA; break; case RELOC_SECTION_SDATA: sec_name = _SDATA; break; case RELOC_SECTION_SBSS: sec_name = _SBSS; break; case RELOC_SECTION_BSS: sec_name = _BSS; break; case RELOC_SECTION_INIT: sec_name = _INIT; break; case RELOC_SECTION_LIT8: sec_name = _LIT8; break; case RELOC_SECTION_LIT4: sec_name = _LIT4; break; case RELOC_SECTION_XDATA: sec_name = _XDATA; break; case RELOC_SECTION_PDATA: sec_name = _PDATA; break; case RELOC_SECTION_FINI: sec_name = _FINI; break; case RELOC_SECTION_LITA: sec_name = _LITA; break; case RELOC_SECTION_RCONST: sec_name = _RCONST; break; default: abort (); } sec = bfd_get_section_by_name (abfd, sec_name); if (sec == NULL) abort (); rptr->sym_ptr_ptr = sec->symbol_ptr_ptr; rptr->addend = - bfd_get_section_vma (abfd, sec); } rptr->address = intern.r_vaddr - bfd_get_section_vma (abfd, section); /* Let the backend select the howto field and do any other required processing. */ (*backend->adjust_reloc_in) (abfd, &intern, rptr); } bfd_release (abfd, external_relocs); section->relocation = internal_relocs; return TRUE; } /* Get a canonical list of relocs. */ long _bfd_ecoff_canonicalize_reloc (bfd *abfd, asection *section, arelent **relptr, asymbol **symbols) { unsigned int count; if (section->flags & SEC_CONSTRUCTOR) { arelent_chain *chain; /* This section has relocs made up by us, not the file, so take them out of their chain and place them into the data area provided. */ for (count = 0, chain = section->constructor_chain; count < section->reloc_count; count++, chain = chain->next) *relptr++ = &chain->relent; } else { arelent *tblptr; if (! ecoff_slurp_reloc_table (abfd, section, symbols)) return -1; tblptr = section->relocation; for (count = 0; count < section->reloc_count; count++) *relptr++ = tblptr++; } *relptr = NULL; return section->reloc_count; } /* Provided a BFD, a section and an offset into the section, calculate and return the name of the source file and the line nearest to the wanted location. */ bfd_boolean _bfd_ecoff_find_nearest_line (bfd *abfd, asection *section, asymbol **ignore_symbols ATTRIBUTE_UNUSED, bfd_vma offset, const char **filename_ptr, const char **functionname_ptr, unsigned int *retline_ptr) { const struct ecoff_debug_swap * const debug_swap = &ecoff_backend (abfd)->debug_swap; struct ecoff_debug_info * const debug_info = &ecoff_data (abfd)->debug_info; struct ecoff_find_line *line_info; /* Make sure we have the FDR's. */ if (! _bfd_ecoff_slurp_symbolic_info (abfd, NULL, debug_info) || bfd_get_symcount (abfd) == 0) return FALSE; if (ecoff_data (abfd)->find_line_info == NULL) { bfd_size_type amt = sizeof (struct ecoff_find_line); ecoff_data (abfd)->find_line_info = bfd_zalloc (abfd, amt); if (ecoff_data (abfd)->find_line_info == NULL) return FALSE; } line_info = ecoff_data (abfd)->find_line_info; return _bfd_ecoff_locate_line (abfd, section, offset, debug_info, debug_swap, line_info, filename_ptr, functionname_ptr, retline_ptr); } /* Copy private BFD data. This is called by objcopy and strip. We use it to copy the ECOFF debugging information from one BFD to the other. It would be theoretically possible to represent the ECOFF debugging information in the symbol table. However, it would be a lot of work, and there would be little gain (gas, gdb, and ld already access the ECOFF debugging information via the ecoff_debug_info structure, and that structure would have to be retained in order to support ECOFF debugging in MIPS ELF). The debugging information for the ECOFF external symbols comes from the symbol table, so this function only handles the other debugging information. */ bfd_boolean _bfd_ecoff_bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd) { struct ecoff_debug_info *iinfo = &ecoff_data (ibfd)->debug_info; struct ecoff_debug_info *oinfo = &ecoff_data (obfd)->debug_info; int i; asymbol **sym_ptr_ptr; size_t c; bfd_boolean local; /* We only want to copy information over if both BFD's use ECOFF format. */ if (bfd_get_flavour (ibfd) != bfd_target_ecoff_flavour || bfd_get_flavour (obfd) != bfd_target_ecoff_flavour) return TRUE; /* Copy the GP value and the register masks. */ ecoff_data (obfd)->gp = ecoff_data (ibfd)->gp; ecoff_data (obfd)->gprmask = ecoff_data (ibfd)->gprmask; ecoff_data (obfd)->fprmask = ecoff_data (ibfd)->fprmask; for (i = 0; i < 3; i++) ecoff_data (obfd)->cprmask[i] = ecoff_data (ibfd)->cprmask[i]; /* Copy the version stamp. */ oinfo->symbolic_header.vstamp = iinfo->symbolic_header.vstamp; /* If there are no symbols, don't copy any debugging information. */ c = bfd_get_symcount (obfd); sym_ptr_ptr = bfd_get_outsymbols (obfd); if (c == 0 || sym_ptr_ptr == NULL) return TRUE; /* See if there are any local symbols. */ local = FALSE; for (; c > 0; c--, sym_ptr_ptr++) { if (ecoffsymbol (*sym_ptr_ptr)->local) { local = TRUE; break; } } if (local) { /* There are some local symbols. We just bring over all the debugging information. FIXME: This is not quite the right thing to do. If the user has asked us to discard all debugging information, then we are probably going to wind up keeping it because there will probably be some local symbol which objcopy did not discard. We should actually break apart the debugging information and only keep that which applies to the symbols we want to keep. */ oinfo->symbolic_header.ilineMax = iinfo->symbolic_header.ilineMax; oinfo->symbolic_header.cbLine = iinfo->symbolic_header.cbLine; oinfo->line = iinfo->line; oinfo->symbolic_header.idnMax = iinfo->symbolic_header.idnMax; oinfo->external_dnr = iinfo->external_dnr; oinfo->symbolic_header.ipdMax = iinfo->symbolic_header.ipdMax; oinfo->external_pdr = iinfo->external_pdr; oinfo->symbolic_header.isymMax = iinfo->symbolic_header.isymMax; oinfo->external_sym = iinfo->external_sym; oinfo->symbolic_header.ioptMax = iinfo->symbolic_header.ioptMax; oinfo->external_opt = iinfo->external_opt; oinfo->symbolic_header.iauxMax = iinfo->symbolic_header.iauxMax; oinfo->external_aux = iinfo->external_aux; oinfo->symbolic_header.issMax = iinfo->symbolic_header.issMax; oinfo->ss = iinfo->ss; oinfo->symbolic_header.ifdMax = iinfo->symbolic_header.ifdMax; oinfo->external_fdr = iinfo->external_fdr; oinfo->symbolic_header.crfd = iinfo->symbolic_header.crfd; oinfo->external_rfd = iinfo->external_rfd; } else { /* We are discarding all the local symbol information. Look through the external symbols and remove all references to FDR or aux information. */ c = bfd_get_symcount (obfd); sym_ptr_ptr = bfd_get_outsymbols (obfd); for (; c > 0; c--, sym_ptr_ptr++) { EXTR esym; (*(ecoff_backend (obfd)->debug_swap.swap_ext_in)) (obfd, ecoffsymbol (*sym_ptr_ptr)->native, &esym); esym.ifd = ifdNil; esym.asym.index = indexNil; (*(ecoff_backend (obfd)->debug_swap.swap_ext_out)) (obfd, &esym, ecoffsymbol (*sym_ptr_ptr)->native); } } return TRUE; } /* Set the architecture. The supported architecture is stored in the backend pointer. We always set the architecture anyhow, since many callers ignore the return value. */ bfd_boolean _bfd_ecoff_set_arch_mach (bfd *abfd, enum bfd_architecture arch, unsigned long machine) { bfd_default_set_arch_mach (abfd, arch, machine); return arch == ecoff_backend (abfd)->arch; } /* Get the size of the section headers. */ int _bfd_ecoff_sizeof_headers (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED) { asection *current; int c; int ret; c = 0; for (current = abfd->sections; current != NULL; current = current->next) ++c; ret = (bfd_coff_filhsz (abfd) + bfd_coff_aoutsz (abfd) + c * bfd_coff_scnhsz (abfd)); return BFD_ALIGN (ret, 16); } /* Get the contents of a section. */ bfd_boolean _bfd_ecoff_get_section_contents (bfd *abfd, asection *section, void * location, file_ptr offset, bfd_size_type count) { return _bfd_generic_get_section_contents (abfd, section, location, offset, count); } /* Sort sections by VMA, but put SEC_ALLOC sections first. This is called via qsort. */ static int ecoff_sort_hdrs (const void * arg1, const void * arg2) { const asection *hdr1 = *(const asection **) arg1; const asection *hdr2 = *(const asection **) arg2; if ((hdr1->flags & SEC_ALLOC) != 0) { if ((hdr2->flags & SEC_ALLOC) == 0) return -1; } else { if ((hdr2->flags & SEC_ALLOC) != 0) return 1; } if (hdr1->vma < hdr2->vma) return -1; else if (hdr1->vma > hdr2->vma) return 1; else return 0; } /* Calculate the file position for each section, and set reloc_filepos. */ static bfd_boolean ecoff_compute_section_file_positions (bfd *abfd) { file_ptr sofar, file_sofar; asection **sorted_hdrs; asection *current; unsigned int i; file_ptr old_sofar; bfd_boolean rdata_in_text; bfd_boolean first_data, first_nonalloc; const bfd_vma round = ecoff_backend (abfd)->round; bfd_size_type amt; sofar = _bfd_ecoff_sizeof_headers (abfd, NULL); file_sofar = sofar; /* Sort the sections by VMA. */ amt = abfd->section_count; amt *= sizeof (asection *); sorted_hdrs = bfd_malloc (amt); if (sorted_hdrs == NULL) return FALSE; for (current = abfd->sections, i = 0; current != NULL; current = current->next, i++) sorted_hdrs[i] = current; BFD_ASSERT (i == abfd->section_count); qsort (sorted_hdrs, abfd->section_count, sizeof (asection *), ecoff_sort_hdrs); /* Some versions of the OSF linker put the .rdata section in the text segment, and some do not. */ rdata_in_text = ecoff_backend (abfd)->rdata_in_text; if (rdata_in_text) { for (i = 0; i < abfd->section_count; i++) { current = sorted_hdrs[i]; if (streq (current->name, _RDATA)) break; if ((current->flags & SEC_CODE) == 0 && ! streq (current->name, _PDATA) && ! streq (current->name, _RCONST)) { rdata_in_text = FALSE; break; } } } ecoff_data (abfd)->rdata_in_text = rdata_in_text; first_data = TRUE; first_nonalloc = TRUE; for (i = 0; i < abfd->section_count; i++) { unsigned int alignment_power; current = sorted_hdrs[i]; /* For the Alpha ECOFF .pdata section the lnnoptr field is supposed to indicate the number of .pdata entries that are really in the section. Each entry is 8 bytes. We store this away in line_filepos before increasing the section size. */ if (streq (current->name, _PDATA)) current->line_filepos = current->size / 8; alignment_power = current->alignment_power; /* On Ultrix, the data sections in an executable file must be aligned to a page boundary within the file. This does not affect the section size, though. FIXME: Does this work for other platforms? It requires some modification for the Alpha, because .rdata on the Alpha goes with the text, not the data. */ if ((abfd->flags & EXEC_P) != 0 && (abfd->flags & D_PAGED) != 0 && ! first_data && (current->flags & SEC_CODE) == 0 && (! rdata_in_text || ! streq (current->name, _RDATA)) && ! streq (current->name, _PDATA) && ! streq (current->name, _RCONST)) { sofar = (sofar + round - 1) &~ (round - 1); file_sofar = (file_sofar + round - 1) &~ (round - 1); first_data = FALSE; } else if (streq (current->name, _LIB)) { /* On Irix 4, the location of contents of the .lib section from a shared library section is also rounded up to a page boundary. */ sofar = (sofar + round - 1) &~ (round - 1); file_sofar = (file_sofar + round - 1) &~ (round - 1); } else if (first_nonalloc && (current->flags & SEC_ALLOC) == 0 && (abfd->flags & D_PAGED) != 0) { /* Skip up to the next page for an unallocated section, such as the .comment section on the Alpha. This leaves room for the .bss section. */ first_nonalloc = FALSE; sofar = (sofar + round - 1) &~ (round - 1); file_sofar = (file_sofar + round - 1) &~ (round - 1); } /* Align the sections in the file to the same boundary on which they are aligned in virtual memory. */ sofar = BFD_ALIGN (sofar, 1 << alignment_power); if ((current->flags & SEC_HAS_CONTENTS) != 0) file_sofar = BFD_ALIGN (file_sofar, 1 << alignment_power); if ((abfd->flags & D_PAGED) != 0 && (current->flags & SEC_ALLOC) != 0) { sofar += (current->vma - sofar) % round; if ((current->flags & SEC_HAS_CONTENTS) != 0) file_sofar += (current->vma - file_sofar) % round; } if ((current->flags & (SEC_HAS_CONTENTS | SEC_LOAD)) != 0) current->filepos = file_sofar; sofar += current->size; if ((current->flags & SEC_HAS_CONTENTS) != 0) file_sofar += current->size; /* Make sure that this section is of the right size too. */ old_sofar = sofar; sofar = BFD_ALIGN (sofar, 1 << alignment_power); if ((current->flags & SEC_HAS_CONTENTS) != 0) file_sofar = BFD_ALIGN (file_sofar, 1 << alignment_power); current->size += sofar - old_sofar; } free (sorted_hdrs); sorted_hdrs = NULL; ecoff_data (abfd)->reloc_filepos = file_sofar; return TRUE; } /* Determine the location of the relocs for all the sections in the output file, as well as the location of the symbolic debugging information. */ static bfd_size_type ecoff_compute_reloc_file_positions (bfd *abfd) { const bfd_size_type external_reloc_size = ecoff_backend (abfd)->external_reloc_size; file_ptr reloc_base; bfd_size_type reloc_size; asection *current; file_ptr sym_base; if (! abfd->output_has_begun) { if (! ecoff_compute_section_file_positions (abfd)) abort (); abfd->output_has_begun = TRUE; } reloc_base = ecoff_data (abfd)->reloc_filepos; reloc_size = 0; for (current = abfd->sections; current != NULL; current = current->next) { if (current->reloc_count == 0) current->rel_filepos = 0; else { bfd_size_type relsize; current->rel_filepos = reloc_base; relsize = current->reloc_count * external_reloc_size; reloc_size += relsize; reloc_base += relsize; } } sym_base = ecoff_data (abfd)->reloc_filepos + reloc_size; /* At least on Ultrix, the symbol table of an executable file must be aligned to a page boundary. FIXME: Is this true on other platforms? */ if ((abfd->flags & EXEC_P) != 0 && (abfd->flags & D_PAGED) != 0) sym_base = ((sym_base + ecoff_backend (abfd)->round - 1) &~ (ecoff_backend (abfd)->round - 1)); ecoff_data (abfd)->sym_filepos = sym_base; return reloc_size; } /* Set the contents of a section. */ bfd_boolean _bfd_ecoff_set_section_contents (bfd *abfd, asection *section, const void * location, file_ptr offset, bfd_size_type count) { file_ptr pos; /* This must be done first, because bfd_set_section_contents is going to set output_has_begun to TRUE. */ if (! abfd->output_has_begun && ! ecoff_compute_section_file_positions (abfd)) return FALSE; /* Handle the .lib section specially so that Irix 4 shared libraries work out. See coff_set_section_contents in coffcode.h. */ if (streq (section->name, _LIB)) { bfd_byte *rec, *recend; rec = (bfd_byte *) location; recend = rec + count; while (rec < recend) { ++section->lma; rec += bfd_get_32 (abfd, rec) * 4; } BFD_ASSERT (rec == recend); } if (count == 0) return TRUE; pos = section->filepos + offset; if (bfd_seek (abfd, pos, SEEK_SET) != 0 || bfd_bwrite (location, count, abfd) != count) return FALSE; return TRUE; } /* Get the GP value for an ECOFF file. This is a hook used by nlmconv. */ bfd_vma bfd_ecoff_get_gp_value (bfd *abfd) { if (bfd_get_flavour (abfd) != bfd_target_ecoff_flavour || bfd_get_format (abfd) != bfd_object) { bfd_set_error (bfd_error_invalid_operation); return 0; } return ecoff_data (abfd)->gp; } /* Set the GP value for an ECOFF file. This is a hook used by the assembler. */ bfd_boolean bfd_ecoff_set_gp_value (bfd *abfd, bfd_vma gp_value) { if (bfd_get_flavour (abfd) != bfd_target_ecoff_flavour || bfd_get_format (abfd) != bfd_object) { bfd_set_error (bfd_error_invalid_operation); return FALSE; } ecoff_data (abfd)->gp = gp_value; return TRUE; } /* Set the register masks for an ECOFF file. This is a hook used by the assembler. */ bfd_boolean bfd_ecoff_set_regmasks (bfd *abfd, unsigned long gprmask, unsigned long fprmask, unsigned long *cprmask) { ecoff_data_type *tdata; if (bfd_get_flavour (abfd) != bfd_target_ecoff_flavour || bfd_get_format (abfd) != bfd_object) { bfd_set_error (bfd_error_invalid_operation); return FALSE; } tdata = ecoff_data (abfd); tdata->gprmask = gprmask; tdata->fprmask = fprmask; if (cprmask != NULL) { int i; for (i = 0; i < 3; i++) tdata->cprmask[i] = cprmask[i]; } return TRUE; } /* Get ECOFF EXTR information for an external symbol. This function is passed to bfd_ecoff_debug_externals. */ static bfd_boolean ecoff_get_extr (asymbol *sym, EXTR *esym) { ecoff_symbol_type *ecoff_sym_ptr; bfd *input_bfd; if (bfd_asymbol_flavour (sym) != bfd_target_ecoff_flavour || ecoffsymbol (sym)->native == NULL) { /* Don't include debugging, local, or section symbols. */ if ((sym->flags & BSF_DEBUGGING) != 0 || (sym->flags & BSF_LOCAL) != 0 || (sym->flags & BSF_SECTION_SYM) != 0) return FALSE; esym->jmptbl = 0; esym->cobol_main = 0; esym->weakext = (sym->flags & BSF_WEAK) != 0; esym->reserved = 0; esym->ifd = ifdNil; /* FIXME: we can do better than this for st and sc. */ esym->asym.st = stGlobal; esym->asym.sc = scAbs; esym->asym.reserved = 0; esym->asym.index = indexNil; return TRUE; } ecoff_sym_ptr = ecoffsymbol (sym); if (ecoff_sym_ptr->local) return FALSE; input_bfd = bfd_asymbol_bfd (sym); (*(ecoff_backend (input_bfd)->debug_swap.swap_ext_in)) (input_bfd, ecoff_sym_ptr->native, esym); /* If the symbol was defined by the linker, then esym will be undefined but sym will not be. Get a better class for such a symbol. */ if ((esym->asym.sc == scUndefined || esym->asym.sc == scSUndefined) && ! bfd_is_und_section (bfd_get_section (sym))) esym->asym.sc = scAbs; /* Adjust the FDR index for the symbol by that used for the input BFD. */ if (esym->ifd != -1) { struct ecoff_debug_info *input_debug; input_debug = &ecoff_data (input_bfd)->debug_info; BFD_ASSERT (esym->ifd < input_debug->symbolic_header.ifdMax); if (input_debug->ifdmap != NULL) esym->ifd = input_debug->ifdmap[esym->ifd]; } return TRUE; } /* Set the external symbol index. This routine is passed to bfd_ecoff_debug_externals. */ static void ecoff_set_index (asymbol *sym, bfd_size_type indx) { ecoff_set_sym_index (sym, indx); } /* Write out an ECOFF file. */ bfd_boolean _bfd_ecoff_write_object_contents (bfd *abfd) { const struct ecoff_backend_data * const backend = ecoff_backend (abfd); const bfd_vma round = backend->round; const bfd_size_type filhsz = bfd_coff_filhsz (abfd); const bfd_size_type aoutsz = bfd_coff_aoutsz (abfd); const bfd_size_type scnhsz = bfd_coff_scnhsz (abfd); const bfd_size_type external_hdr_size = backend->debug_swap.external_hdr_size; const bfd_size_type external_reloc_size = backend->external_reloc_size; void (* const adjust_reloc_out) (bfd *, const arelent *, struct internal_reloc *) = backend->adjust_reloc_out; void (* const swap_reloc_out) (bfd *, const struct internal_reloc *, void *) = backend->swap_reloc_out; struct ecoff_debug_info * const debug = &ecoff_data (abfd)->debug_info; HDRR * const symhdr = &debug->symbolic_header; asection *current; unsigned int count; bfd_size_type reloc_size; bfd_size_type text_size; bfd_vma text_start; bfd_boolean set_text_start; bfd_size_type data_size; bfd_vma data_start; bfd_boolean set_data_start; bfd_size_type bss_size; void * buff = NULL; void * reloc_buff = NULL; struct internal_filehdr internal_f; struct internal_aouthdr internal_a; int i; /* Determine where the sections and relocs will go in the output file. */ reloc_size = ecoff_compute_reloc_file_positions (abfd); count = 1; for (current = abfd->sections; current != NULL; current = current->next) { current->target_index = count; ++count; } if ((abfd->flags & D_PAGED) != 0) text_size = _bfd_ecoff_sizeof_headers (abfd, NULL); else text_size = 0; text_start = 0; set_text_start = FALSE; data_size = 0; data_start = 0; set_data_start = FALSE; bss_size = 0; /* Write section headers to the file. */ /* Allocate buff big enough to hold a section header, file header, or a.out header. */ { bfd_size_type siz; siz = scnhsz; if (siz < filhsz) siz = filhsz; if (siz < aoutsz) siz = aoutsz; buff = bfd_malloc (siz); if (buff == NULL) goto error_return; } internal_f.f_nscns = 0; if (bfd_seek (abfd, (file_ptr) (filhsz + aoutsz), SEEK_SET) != 0) goto error_return; for (current = abfd->sections; current != NULL; current = current->next) { struct internal_scnhdr section; bfd_vma vma; ++internal_f.f_nscns; strncpy (section.s_name, current->name, sizeof section.s_name); /* This seems to be correct for Irix 4 shared libraries. */ vma = bfd_get_section_vma (abfd, current); if (streq (current->name, _LIB)) section.s_vaddr = 0; else section.s_vaddr = vma; section.s_paddr = current->lma; section.s_size = current->size; /* If this section is unloadable then the scnptr will be 0. */ if ((current->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0) section.s_scnptr = 0; else section.s_scnptr = current->filepos; section.s_relptr = current->rel_filepos; /* FIXME: the lnnoptr of the .sbss or .sdata section of an object file produced by the assembler is supposed to point to information about how much room is required by objects of various different sizes. I think this only matters if we want the linker to compute the best size to use, or something. I don't know what happens if the information is not present. */ if (! streq (current->name, _PDATA)) section.s_lnnoptr = 0; else { /* The Alpha ECOFF .pdata section uses the lnnoptr field to hold the number of entries in the section (each entry is 8 bytes). We stored this in the line_filepos field in ecoff_compute_section_file_positions. */ section.s_lnnoptr = current->line_filepos; } section.s_nreloc = current->reloc_count; section.s_nlnno = 0; section.s_flags = ecoff_sec_to_styp_flags (current->name, current->flags); if (bfd_coff_swap_scnhdr_out (abfd, (void *) §ion, buff) == 0 || bfd_bwrite (buff, scnhsz, abfd) != scnhsz) goto error_return; if ((section.s_flags & STYP_TEXT) != 0 || ((section.s_flags & STYP_RDATA) != 0 && ecoff_data (abfd)->rdata_in_text) || section.s_flags == STYP_PDATA || (section.s_flags & STYP_DYNAMIC) != 0 || (section.s_flags & STYP_LIBLIST) != 0 || (section.s_flags & STYP_RELDYN) != 0 || section.s_flags == STYP_CONFLIC || (section.s_flags & STYP_DYNSTR) != 0 || (section.s_flags & STYP_DYNSYM) != 0 || (section.s_flags & STYP_HASH) != 0 || (section.s_flags & STYP_ECOFF_INIT) != 0 || (section.s_flags & STYP_ECOFF_FINI) != 0 || section.s_flags == STYP_RCONST) { text_size += current->size; if (! set_text_start || text_start > vma) { text_start = vma; set_text_start = TRUE; } } else if ((section.s_flags & STYP_RDATA) != 0 || (section.s_flags & STYP_DATA) != 0 || (section.s_flags & STYP_LITA) != 0 || (section.s_flags & STYP_LIT8) != 0 || (section.s_flags & STYP_LIT4) != 0 || (section.s_flags & STYP_SDATA) != 0 || section.s_flags == STYP_XDATA || (section.s_flags & STYP_GOT) != 0) { data_size += current->size; if (! set_data_start || data_start > vma) { data_start = vma; set_data_start = TRUE; } } else if ((section.s_flags & STYP_BSS) != 0 || (section.s_flags & STYP_SBSS) != 0) bss_size += current->size; else if (section.s_flags == 0 || (section.s_flags & STYP_ECOFF_LIB) != 0 || section.s_flags == STYP_COMMENT) /* Do nothing. */ ; else abort (); } /* Set up the file header. */ internal_f.f_magic = ecoff_get_magic (abfd); /* We will NOT put a fucking timestamp in the header here. Every time you put it back, I will come in and take it out again. I'm sorry. This field does not belong here. We fill it with a 0 so it compares the same but is not a reasonable time. -- gnu@cygnus.com. */ internal_f.f_timdat = 0; if (bfd_get_symcount (abfd) != 0) { /* The ECOFF f_nsyms field is not actually the number of symbols, it's the size of symbolic information header. */ internal_f.f_nsyms = external_hdr_size; internal_f.f_symptr = ecoff_data (abfd)->sym_filepos; } else { internal_f.f_nsyms = 0; internal_f.f_symptr = 0; } internal_f.f_opthdr = aoutsz; internal_f.f_flags = F_LNNO; if (reloc_size == 0) internal_f.f_flags |= F_RELFLG; if (bfd_get_symcount (abfd) == 0) internal_f.f_flags |= F_LSYMS; if (abfd->flags & EXEC_P) internal_f.f_flags |= F_EXEC; if (bfd_little_endian (abfd)) internal_f.f_flags |= F_AR32WR; else internal_f.f_flags |= F_AR32W; /* Set up the ``optional'' header. */ if ((abfd->flags & D_PAGED) != 0) internal_a.magic = ECOFF_AOUT_ZMAGIC; else internal_a.magic = ECOFF_AOUT_OMAGIC; /* FIXME: Is this really correct? */ internal_a.vstamp = symhdr->vstamp; /* At least on Ultrix, these have to be rounded to page boundaries. FIXME: Is this true on other platforms? */ if ((abfd->flags & D_PAGED) != 0) { internal_a.tsize = (text_size + round - 1) &~ (round - 1); internal_a.text_start = text_start &~ (round - 1); internal_a.dsize = (data_size + round - 1) &~ (round - 1); internal_a.data_start = data_start &~ (round - 1); } else { internal_a.tsize = text_size; internal_a.text_start = text_start; internal_a.dsize = data_size; internal_a.data_start = data_start; } /* On Ultrix, the initial portions of the .sbss and .bss segments are at the end of the data section. The bsize field in the optional header records how many bss bytes are required beyond those in the data section. The value is not rounded to a page boundary. */ if (bss_size < internal_a.dsize - data_size) bss_size = 0; else bss_size -= internal_a.dsize - data_size; internal_a.bsize = bss_size; internal_a.bss_start = internal_a.data_start + internal_a.dsize; internal_a.entry = bfd_get_start_address (abfd); internal_a.gp_value = ecoff_data (abfd)->gp; internal_a.gprmask = ecoff_data (abfd)->gprmask; internal_a.fprmask = ecoff_data (abfd)->fprmask; for (i = 0; i < 4; i++) internal_a.cprmask[i] = ecoff_data (abfd)->cprmask[i]; /* Let the backend adjust the headers if necessary. */ if (backend->adjust_headers) { if (! (*backend->adjust_headers) (abfd, &internal_f, &internal_a)) goto error_return; } /* Write out the file header and the optional header. */ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) goto error_return; bfd_coff_swap_filehdr_out (abfd, (void *) &internal_f, buff); if (bfd_bwrite (buff, filhsz, abfd) != filhsz) goto error_return; bfd_coff_swap_aouthdr_out (abfd, (void *) &internal_a, buff); if (bfd_bwrite (buff, aoutsz, abfd) != aoutsz) goto error_return; /* Build the external symbol information. This must be done before writing out the relocs so that we know the symbol indices. We don't do this if this BFD was created by the backend linker, since it will have already handled the symbols and relocs. */ if (! ecoff_data (abfd)->linker) { symhdr->iextMax = 0; symhdr->issExtMax = 0; debug->external_ext = debug->external_ext_end = NULL; debug->ssext = debug->ssext_end = NULL; if (! bfd_ecoff_debug_externals (abfd, debug, &backend->debug_swap, (abfd->flags & EXEC_P) == 0, ecoff_get_extr, ecoff_set_index)) goto error_return; /* Write out the relocs. */ for (current = abfd->sections; current != NULL; current = current->next) { arelent **reloc_ptr_ptr; arelent **reloc_end; char *out_ptr; bfd_size_type amt; if (current->reloc_count == 0) continue; amt = current->reloc_count * external_reloc_size; reloc_buff = bfd_alloc (abfd, amt); if (reloc_buff == NULL) goto error_return; reloc_ptr_ptr = current->orelocation; reloc_end = reloc_ptr_ptr + current->reloc_count; out_ptr = (char *) reloc_buff; for (; reloc_ptr_ptr < reloc_end; reloc_ptr_ptr++, out_ptr += external_reloc_size) { arelent *reloc; asymbol *sym; struct internal_reloc in; memset ((void *) &in, 0, sizeof in); reloc = *reloc_ptr_ptr; sym = *reloc->sym_ptr_ptr; /* If the howto field has not been initialised then skip this reloc. This assumes that an error message has been issued elsewhere. */ if (reloc->howto == NULL) continue; in.r_vaddr = (reloc->address + bfd_get_section_vma (abfd, current)); in.r_type = reloc->howto->type; if ((sym->flags & BSF_SECTION_SYM) == 0) { in.r_symndx = ecoff_get_sym_index (*reloc->sym_ptr_ptr); in.r_extern = 1; } else { const char *name; unsigned int i; static struct { const char * name; long r_symndx; } section_symndx [] = { { _TEXT, RELOC_SECTION_TEXT }, { _RDATA, RELOC_SECTION_RDATA }, { _DATA, RELOC_SECTION_DATA }, { _SDATA, RELOC_SECTION_SDATA }, { _SBSS, RELOC_SECTION_SBSS }, { _BSS, RELOC_SECTION_BSS }, { _INIT, RELOC_SECTION_INIT }, { _LIT8, RELOC_SECTION_LIT8 }, { _LIT4, RELOC_SECTION_LIT4 }, { _XDATA, RELOC_SECTION_XDATA }, { _PDATA, RELOC_SECTION_PDATA }, { _FINI, RELOC_SECTION_FINI }, { _LITA, RELOC_SECTION_LITA }, { "*ABS*", RELOC_SECTION_ABS }, { _RCONST, RELOC_SECTION_RCONST } }; name = bfd_get_section_name (abfd, bfd_get_section (sym)); for (i = 0; i < ARRAY_SIZE (section_symndx); i++) if (streq (name, section_symndx[i].name)) { in.r_symndx = section_symndx[i].r_symndx; break; } if (i == ARRAY_SIZE (section_symndx)) abort (); in.r_extern = 0; } (*adjust_reloc_out) (abfd, reloc, &in); (*swap_reloc_out) (abfd, &in, (void *) out_ptr); } if (bfd_seek (abfd, current->rel_filepos, SEEK_SET) != 0) goto error_return; amt = current->reloc_count * external_reloc_size; if (bfd_bwrite (reloc_buff, amt, abfd) != amt) goto error_return; bfd_release (abfd, reloc_buff); reloc_buff = NULL; } /* Write out the symbolic debugging information. */ if (bfd_get_symcount (abfd) > 0) { /* Write out the debugging information. */ if (! bfd_ecoff_write_debug (abfd, debug, &backend->debug_swap, ecoff_data (abfd)->sym_filepos)) goto error_return; } } /* The .bss section of a demand paged executable must receive an entire page. If there are symbols, the symbols will start on the next page. If there are no symbols, we must fill out the page by hand. */ if (bfd_get_symcount (abfd) == 0 && (abfd->flags & EXEC_P) != 0 && (abfd->flags & D_PAGED) != 0) { char c; if (bfd_seek (abfd, (file_ptr) ecoff_data (abfd)->sym_filepos - 1, SEEK_SET) != 0) goto error_return; if (bfd_bread (&c, (bfd_size_type) 1, abfd) == 0) c = 0; if (bfd_seek (abfd, (file_ptr) ecoff_data (abfd)->sym_filepos - 1, SEEK_SET) != 0) goto error_return; if (bfd_bwrite (&c, (bfd_size_type) 1, abfd) != 1) goto error_return; } if (reloc_buff != NULL) bfd_release (abfd, reloc_buff); if (buff != NULL) free (buff); return TRUE; error_return: if (reloc_buff != NULL) bfd_release (abfd, reloc_buff); if (buff != NULL) free (buff); return FALSE; } /* Archive handling. ECOFF uses what appears to be a unique type of archive header (armap). The byte ordering of the armap and the contents are encoded in the name of the armap itself. At least for now, we only support archives with the same byte ordering in the armap and the contents. The first four bytes in the armap are the number of symbol definitions. This is always a power of two. This is followed by the symbol definitions. Each symbol definition occupies 8 bytes. The first four bytes are the offset from the start of the armap strings to the null-terminated string naming this symbol. The second four bytes are the file offset to the archive member which defines this symbol. If the second four bytes are 0, then this is not actually a symbol definition, and it should be ignored. The symbols are hashed into the armap with a closed hashing scheme. See the functions below for the details of the algorithm. After the symbol definitions comes four bytes holding the size of the string table, followed by the string table itself. */ /* The name of an archive headers looks like this: __________E[BL]E[BL]_ (with a trailing space). The trailing space is changed to an X if the archive is changed to indicate that the armap is out of date. The Alpha seems to use ________64E[BL]E[BL]_. */ #define ARMAP_BIG_ENDIAN 'B' #define ARMAP_LITTLE_ENDIAN 'L' #define ARMAP_MARKER 'E' #define ARMAP_START_LENGTH 10 #define ARMAP_HEADER_MARKER_INDEX 10 #define ARMAP_HEADER_ENDIAN_INDEX 11 #define ARMAP_OBJECT_MARKER_INDEX 12 #define ARMAP_OBJECT_ENDIAN_INDEX 13 #define ARMAP_END_INDEX 14 #define ARMAP_END "_ " /* This is a magic number used in the hashing algorithm. */ #define ARMAP_HASH_MAGIC 0x9dd68ab5 /* This returns the hash value to use for a string. It also sets *REHASH to the rehash adjustment if the first slot is taken. SIZE is the number of entries in the hash table, and HLOG is the log base 2 of SIZE. */ static unsigned int ecoff_armap_hash (const char *s, unsigned int *rehash, unsigned int size, unsigned int hlog) { unsigned int hash; if (hlog == 0) return 0; hash = *s++; while (*s != '\0') hash = ((hash >> 27) | (hash << 5)) + *s++; hash *= ARMAP_HASH_MAGIC; *rehash = (hash & (size - 1)) | 1; return hash >> (32 - hlog); } /* Read in the armap. */ bfd_boolean _bfd_ecoff_slurp_armap (bfd *abfd) { char nextname[17]; unsigned int i; struct areltdata *mapdata; bfd_size_type parsed_size; char *raw_armap; struct artdata *ardata; unsigned int count; char *raw_ptr; struct symdef *symdef_ptr; char *stringbase; bfd_size_type amt; /* Get the name of the first element. */ i = bfd_bread ((void *) nextname, (bfd_size_type) 16, abfd); if (i == 0) return TRUE; if (i != 16) return FALSE; if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0) return FALSE; /* Irix 4.0.5F apparently can use either an ECOFF armap or a standard COFF armap. We could move the ECOFF armap stuff into bfd_slurp_armap, but that seems inappropriate since no other target uses this format. Instead, we check directly for a COFF armap. */ if (CONST_STRNEQ (nextname, "/ ")) return bfd_slurp_armap (abfd); /* See if the first element is an armap. */ if (! strneq (nextname, ecoff_backend (abfd)->armap_start, ARMAP_START_LENGTH) || nextname[ARMAP_HEADER_MARKER_INDEX] != ARMAP_MARKER || (nextname[ARMAP_HEADER_ENDIAN_INDEX] != ARMAP_BIG_ENDIAN && nextname[ARMAP_HEADER_ENDIAN_INDEX] != ARMAP_LITTLE_ENDIAN) || nextname[ARMAP_OBJECT_MARKER_INDEX] != ARMAP_MARKER || (nextname[ARMAP_OBJECT_ENDIAN_INDEX] != ARMAP_BIG_ENDIAN && nextname[ARMAP_OBJECT_ENDIAN_INDEX] != ARMAP_LITTLE_ENDIAN) || ! strneq (nextname + ARMAP_END_INDEX, ARMAP_END, sizeof ARMAP_END - 1)) { bfd_has_map (abfd) = FALSE; return TRUE; } /* Make sure we have the right byte ordering. */ if (((nextname[ARMAP_HEADER_ENDIAN_INDEX] == ARMAP_BIG_ENDIAN) ^ (bfd_header_big_endian (abfd))) || ((nextname[ARMAP_OBJECT_ENDIAN_INDEX] == ARMAP_BIG_ENDIAN) ^ (bfd_big_endian (abfd)))) { bfd_set_error (bfd_error_wrong_format); return FALSE; } /* Read in the armap. */ ardata = bfd_ardata (abfd); mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd); if (mapdata == NULL) return FALSE; parsed_size = mapdata->parsed_size; bfd_release (abfd, (void *) mapdata); raw_armap = bfd_alloc (abfd, parsed_size); if (raw_armap == NULL) return FALSE; if (bfd_bread ((void *) raw_armap, parsed_size, abfd) != parsed_size) { if (bfd_get_error () != bfd_error_system_call) bfd_set_error (bfd_error_malformed_archive); bfd_release (abfd, (void *) raw_armap); return FALSE; } ardata->tdata = (void *) raw_armap; count = H_GET_32 (abfd, raw_armap); ardata->symdef_count = 0; ardata->cache = NULL; /* This code used to overlay the symdefs over the raw archive data, but that doesn't work on a 64 bit host. */ stringbase = raw_armap + count * 8 + 8; #ifdef CHECK_ARMAP_HASH { unsigned int hlog; /* Double check that I have the hashing algorithm right by making sure that every symbol can be looked up successfully. */ hlog = 0; for (i = 1; i < count; i <<= 1) hlog++; BFD_ASSERT (i == count); raw_ptr = raw_armap + 4; for (i = 0; i < count; i++, raw_ptr += 8) { unsigned int name_offset, file_offset; unsigned int hash, rehash, srch; name_offset = H_GET_32 (abfd, raw_ptr); file_offset = H_GET_32 (abfd, (raw_ptr + 4)); if (file_offset == 0) continue; hash = ecoff_armap_hash (stringbase + name_offset, &rehash, count, hlog); if (hash == i) continue; /* See if we can rehash to this location. */ for (srch = (hash + rehash) & (count - 1); srch != hash && srch != i; srch = (srch + rehash) & (count - 1)) BFD_ASSERT (H_GET_32 (abfd, (raw_armap + 8 + srch * 8)) != 0); BFD_ASSERT (srch == i); } } #endif /* CHECK_ARMAP_HASH */ raw_ptr = raw_armap + 4; for (i = 0; i < count; i++, raw_ptr += 8) if (H_GET_32 (abfd, (raw_ptr + 4)) != 0) ++ardata->symdef_count; amt = ardata->symdef_count; amt *= sizeof (struct symdef); symdef_ptr = bfd_alloc (abfd, amt); if (!symdef_ptr) return FALSE; ardata->symdefs = (carsym *) symdef_ptr; raw_ptr = raw_armap + 4; for (i = 0; i < count; i++, raw_ptr += 8) { unsigned int name_offset, file_offset; file_offset = H_GET_32 (abfd, (raw_ptr + 4)); if (file_offset == 0) continue; name_offset = H_GET_32 (abfd, raw_ptr); symdef_ptr->s.name = stringbase + name_offset; symdef_ptr->file_offset = file_offset; ++symdef_ptr; } ardata->first_file_filepos = bfd_tell (abfd); /* Pad to an even boundary. */ ardata->first_file_filepos += ardata->first_file_filepos % 2; bfd_has_map (abfd) = TRUE; return TRUE; } /* Write out an armap. */ bfd_boolean _bfd_ecoff_write_armap (bfd *abfd, unsigned int elength, struct orl *map, unsigned int orl_count, int stridx) { unsigned int hashsize, hashlog; bfd_size_type symdefsize; int padit; unsigned int stringsize; unsigned int mapsize; file_ptr firstreal; struct ar_hdr hdr; struct stat statbuf; unsigned int i; bfd_byte temp[4]; bfd_byte *hashtable; bfd *current; bfd *last_elt; /* Ultrix appears to use as a hash table size the least power of two greater than twice the number of entries. */ for (hashlog = 0; ((unsigned int) 1 << hashlog) <= 2 * orl_count; hashlog++) ; hashsize = 1 << hashlog; symdefsize = hashsize * 8; padit = stridx % 2; stringsize = stridx + padit; /* Include 8 bytes to store symdefsize and stringsize in output. */ mapsize = symdefsize + stringsize + 8; firstreal = SARMAG + sizeof (struct ar_hdr) + mapsize + elength; memset ((void *) &hdr, 0, sizeof hdr); /* Work out the ECOFF armap name. */ strcpy (hdr.ar_name, ecoff_backend (abfd)->armap_start); hdr.ar_name[ARMAP_HEADER_MARKER_INDEX] = ARMAP_MARKER; hdr.ar_name[ARMAP_HEADER_ENDIAN_INDEX] = (bfd_header_big_endian (abfd) ? ARMAP_BIG_ENDIAN : ARMAP_LITTLE_ENDIAN); hdr.ar_name[ARMAP_OBJECT_MARKER_INDEX] = ARMAP_MARKER; hdr.ar_name[ARMAP_OBJECT_ENDIAN_INDEX] = bfd_big_endian (abfd) ? ARMAP_BIG_ENDIAN : ARMAP_LITTLE_ENDIAN; memcpy (hdr.ar_name + ARMAP_END_INDEX, ARMAP_END, sizeof ARMAP_END - 1); /* Write the timestamp of the archive header to be just a little bit later than the timestamp of the file, otherwise the linker will complain that the index is out of date. Actually, the Ultrix linker just checks the archive name; the GNU linker may check the date. */ stat (abfd->filename, &statbuf); sprintf (hdr.ar_date, "%ld", (long) (statbuf.st_mtime + 60)); /* The DECstation uses zeroes for the uid, gid and mode of the armap. */ hdr.ar_uid[0] = '0'; hdr.ar_gid[0] = '0'; /* Building gcc ends up extracting the armap as a file - twice. */ hdr.ar_mode[0] = '6'; hdr.ar_mode[1] = '4'; hdr.ar_mode[2] = '4'; sprintf (hdr.ar_size, "%-10d", (int) mapsize); hdr.ar_fmag[0] = '`'; hdr.ar_fmag[1] = '\012'; /* Turn all null bytes in the header into spaces. */ for (i = 0; i < sizeof (struct ar_hdr); i++) if (((char *) (&hdr))[i] == '\0') (((char *) (&hdr))[i]) = ' '; if (bfd_bwrite ((void *) &hdr, (bfd_size_type) sizeof (struct ar_hdr), abfd) != sizeof (struct ar_hdr)) return FALSE; H_PUT_32 (abfd, hashsize, temp); if (bfd_bwrite ((void *) temp, (bfd_size_type) 4, abfd) != 4) return FALSE; hashtable = bfd_zalloc (abfd, symdefsize); if (!hashtable) return FALSE; current = abfd->archive_head; last_elt = current; for (i = 0; i < orl_count; i++) { unsigned int hash, rehash = 0; /* Advance firstreal to the file position of this archive element. */ if (map[i].u.abfd != last_elt) { do { firstreal += arelt_size (current) + sizeof (struct ar_hdr); firstreal += firstreal % 2; current = current->archive_next; } while (current != map[i].u.abfd); } last_elt = current; hash = ecoff_armap_hash (*map[i].name, &rehash, hashsize, hashlog); if (H_GET_32 (abfd, (hashtable + (hash * 8) + 4)) != 0) { unsigned int srch; /* The desired slot is already taken. */ for (srch = (hash + rehash) & (hashsize - 1); srch != hash; srch = (srch + rehash) & (hashsize - 1)) if (H_GET_32 (abfd, (hashtable + (srch * 8) + 4)) == 0) break; BFD_ASSERT (srch != hash); hash = srch; } H_PUT_32 (abfd, map[i].namidx, (hashtable + hash * 8)); H_PUT_32 (abfd, firstreal, (hashtable + hash * 8 + 4)); } if (bfd_bwrite ((void *) hashtable, symdefsize, abfd) != symdefsize) return FALSE; bfd_release (abfd, hashtable); /* Now write the strings. */ H_PUT_32 (abfd, stringsize, temp); if (bfd_bwrite ((void *) temp, (bfd_size_type) 4, abfd) != 4) return FALSE; for (i = 0; i < orl_count; i++) { bfd_size_type len; len = strlen (*map[i].name) + 1; if (bfd_bwrite ((void *) (*map[i].name), len, abfd) != len) return FALSE; } /* The spec sez this should be a newline. But in order to be bug-compatible for DECstation ar we use a null. */ if (padit) { if (bfd_bwrite ("", (bfd_size_type) 1, abfd) != 1) return FALSE; } return TRUE; } /* See whether this BFD is an archive. If it is, read in the armap and the extended name table. */ const bfd_target * _bfd_ecoff_archive_p (bfd *abfd) { struct artdata *tdata_hold; char armag[SARMAG + 1]; bfd_size_type amt; if (bfd_bread ((void *) armag, (bfd_size_type) SARMAG, abfd) != SARMAG) { if (bfd_get_error () != bfd_error_system_call) bfd_set_error (bfd_error_wrong_format); return NULL; } if (! strneq (armag, ARMAG, SARMAG)) { bfd_set_error (bfd_error_wrong_format); return NULL; } tdata_hold = bfd_ardata (abfd); amt = sizeof (struct artdata); bfd_ardata (abfd) = bfd_zalloc (abfd, amt); if (bfd_ardata (abfd) == NULL) { bfd_ardata (abfd) = tdata_hold; return NULL; } bfd_ardata (abfd)->first_file_filepos = SARMAG; /* Already cleared by bfd_zalloc above. bfd_ardata (abfd)->cache = NULL; bfd_ardata (abfd)->archive_head = NULL; bfd_ardata (abfd)->symdefs = NULL; bfd_ardata (abfd)->extended_names = NULL; bfd_ardata (abfd)->extended_names_size = 0; bfd_ardata (abfd)->tdata = NULL; */ if (! _bfd_ecoff_slurp_armap (abfd) || ! _bfd_ecoff_slurp_extended_name_table (abfd)) { bfd_release (abfd, bfd_ardata (abfd)); bfd_ardata (abfd) = tdata_hold; return NULL; } if (bfd_has_map (abfd)) { bfd *first; /* This archive has a map, so we may presume that the contents are object files. Make sure that if the first file in the archive can be recognized as an object file, it is for this target. If not, assume that this is the wrong format. If the first file is not an object file, somebody is doing something weird, and we permit it so that ar -t will work. */ first = bfd_openr_next_archived_file (abfd, NULL); if (first != NULL) { first->target_defaulted = FALSE; if (bfd_check_format (first, bfd_object) && first->xvec != abfd->xvec) { /* We ought to close `first' here, but we can't, because we have no way to remove it from the archive cache. It's almost impossible to figure out when we can release bfd_ardata. FIXME. */ bfd_set_error (bfd_error_wrong_object_format); bfd_ardata (abfd) = tdata_hold; return NULL; } /* And we ought to close `first' here too. */ } } return abfd->xvec; } /* ECOFF linker code. */ /* Routine to create an entry in an ECOFF link hash table. */ static struct bfd_hash_entry * ecoff_link_hash_newfunc (struct bfd_hash_entry *entry, struct bfd_hash_table *table, const char *string) { struct ecoff_link_hash_entry *ret = (struct ecoff_link_hash_entry *) entry; /* Allocate the structure if it has not already been allocated by a subclass. */ if (ret == NULL) ret = ((struct ecoff_link_hash_entry *) bfd_hash_allocate (table, sizeof (struct ecoff_link_hash_entry))); if (ret == NULL) return NULL; /* Call the allocation method of the superclass. */ ret = ((struct ecoff_link_hash_entry *) _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret, table, string)); if (ret) { /* Set local fields. */ ret->indx = -1; ret->abfd = NULL; ret->written = 0; ret->small = 0; } memset ((void *) &ret->esym, 0, sizeof ret->esym); return (struct bfd_hash_entry *) ret; } /* Create an ECOFF link hash table. */ struct bfd_link_hash_table * _bfd_ecoff_bfd_link_hash_table_create (bfd *abfd) { struct ecoff_link_hash_table *ret; bfd_size_type amt = sizeof (struct ecoff_link_hash_table); ret = bfd_malloc (amt); if (ret == NULL) return NULL; if (!_bfd_link_hash_table_init (&ret->root, abfd, ecoff_link_hash_newfunc, sizeof (struct ecoff_link_hash_entry))) { free (ret); return NULL; } return &ret->root; } /* Look up an entry in an ECOFF link hash table. */ #define ecoff_link_hash_lookup(table, string, create, copy, follow) \ ((struct ecoff_link_hash_entry *) \ bfd_link_hash_lookup (&(table)->root, (string), (create), (copy), (follow))) /* Traverse an ECOFF link hash table. */ #define ecoff_link_hash_traverse(table, func, info) \ (bfd_link_hash_traverse \ (&(table)->root, \ (bfd_boolean (*) (struct bfd_link_hash_entry *, void *)) (func), \ (info))) /* Get the ECOFF link hash table from the info structure. This is just a cast. */ #define ecoff_hash_table(p) ((struct ecoff_link_hash_table *) ((p)->hash)) /* Add the external symbols of an object file to the global linker hash table. The external symbols and strings we are passed are just allocated on the stack, and will be discarded. We must explicitly save any information we may need later on in the link. We do not want to read the external symbol information again. */ static bfd_boolean ecoff_link_add_externals (bfd *abfd, struct bfd_link_info *info, void * external_ext, char *ssext) { const struct ecoff_backend_data * const backend = ecoff_backend (abfd); void (* const swap_ext_in) (bfd *, void *, EXTR *) = backend->debug_swap.swap_ext_in; bfd_size_type external_ext_size = backend->debug_swap.external_ext_size; unsigned long ext_count; struct bfd_link_hash_entry **sym_hash; char *ext_ptr; char *ext_end; bfd_size_type amt; ext_count = ecoff_data (abfd)->debug_info.symbolic_header.iextMax; amt = ext_count; amt *= sizeof (struct bfd_link_hash_entry *); sym_hash = bfd_alloc (abfd, amt); if (!sym_hash) return FALSE; ecoff_data (abfd)->sym_hashes = (struct ecoff_link_hash_entry **) sym_hash; ext_ptr = (char *) external_ext; ext_end = ext_ptr + ext_count * external_ext_size; for (; ext_ptr < ext_end; ext_ptr += external_ext_size, sym_hash++) { EXTR esym; bfd_boolean skip; bfd_vma value; asection *section; const char *name; struct ecoff_link_hash_entry *h; *sym_hash = NULL; (*swap_ext_in) (abfd, (void *) ext_ptr, &esym); /* Skip debugging symbols. */ skip = FALSE; switch (esym.asym.st) { case stGlobal: case stStatic: case stLabel: case stProc: case stStaticProc: break; default: skip = TRUE; break; } if (skip) continue; /* Get the information for this symbol. */ value = esym.asym.value; switch (esym.asym.sc) { default: case scNil: case scRegister: case scCdbLocal: case scBits: case scCdbSystem: case scRegImage: case scInfo: case scUserStruct: case scVar: case scVarRegister: case scVariant: case scBasedVar: case scXData: case scPData: section = NULL; break; case scText: section = bfd_make_section_old_way (abfd, _TEXT); value -= section->vma; break; case scData: section = bfd_make_section_old_way (abfd, _DATA); value -= section->vma; break; case scBss: section = bfd_make_section_old_way (abfd, _BSS); value -= section->vma; break; case scAbs: section = bfd_abs_section_ptr; break; case scUndefined: section = bfd_und_section_ptr; break; case scSData: section = bfd_make_section_old_way (abfd, _SDATA); value -= section->vma; break; case scSBss: section = bfd_make_section_old_way (abfd, _SBSS); value -= section->vma; break; case scRData: section = bfd_make_section_old_way (abfd, _RDATA); value -= section->vma; break; case scCommon: if (value > ecoff_data (abfd)->gp_size) { section = bfd_com_section_ptr; break; } /* Fall through. */ case scSCommon: if (ecoff_scom_section.name == NULL) { /* Initialize the small common section. */ ecoff_scom_section.name = SCOMMON; ecoff_scom_section.flags = SEC_IS_COMMON; ecoff_scom_section.output_section = &ecoff_scom_section; ecoff_scom_section.symbol = &ecoff_scom_symbol; ecoff_scom_section.symbol_ptr_ptr = &ecoff_scom_symbol_ptr; ecoff_scom_symbol.name = SCOMMON; ecoff_scom_symbol.flags = BSF_SECTION_SYM; ecoff_scom_symbol.section = &ecoff_scom_section; ecoff_scom_symbol_ptr = &ecoff_scom_symbol; } section = &ecoff_scom_section; break; case scSUndefined: section = bfd_und_section_ptr; break; case scInit: section = bfd_make_section_old_way (abfd, _INIT); value -= section->vma; break; case scFini: section = bfd_make_section_old_way (abfd, _FINI); value -= section->vma; break; case scRConst: section = bfd_make_section_old_way (abfd, _RCONST); value -= section->vma; break; } if (section == NULL) continue; name = ssext + esym.asym.iss; if (! (_bfd_generic_link_add_one_symbol (info, abfd, name, (flagword) (esym.weakext ? BSF_WEAK : BSF_GLOBAL), section, value, NULL, TRUE, TRUE, sym_hash))) return FALSE; h = (struct ecoff_link_hash_entry *) *sym_hash; /* If we are building an ECOFF hash table, save the external symbol information. */ if (info->hash->creator->flavour == bfd_get_flavour (abfd)) { if (h->abfd == NULL || (! bfd_is_und_section (section) && (! bfd_is_com_section (section) || (h->root.type != bfd_link_hash_defined && h->root.type != bfd_link_hash_defweak)))) { h->abfd = abfd; h->esym = esym; } /* Remember whether this symbol was small undefined. */ if (esym.asym.sc == scSUndefined) h->small = 1; /* If this symbol was ever small undefined, it needs to wind up in a GP relative section. We can't control the section of a defined symbol, but we can control the section of a common symbol. This case is actually needed on Ultrix 4.2 to handle the symbol cred in -lckrb. */ if (h->small && h->root.type == bfd_link_hash_common && streq (h->root.u.c.p->section->name, SCOMMON)) { h->root.u.c.p->section = bfd_make_section_old_way (abfd, SCOMMON); h->root.u.c.p->section->flags = SEC_ALLOC; if (h->esym.asym.sc == scCommon) h->esym.asym.sc = scSCommon; } } } return TRUE; } /* Add symbols from an ECOFF object file to the global linker hash table. */ static bfd_boolean ecoff_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) { HDRR *symhdr; bfd_size_type external_ext_size; void * external_ext = NULL; bfd_size_type esize; char *ssext = NULL; bfd_boolean result; if (! ecoff_slurp_symbolic_header (abfd)) return FALSE; /* If there are no symbols, we don't want it. */ if (bfd_get_symcount (abfd) == 0) return TRUE; symhdr = &ecoff_data (abfd)->debug_info.symbolic_header; /* Read in the external symbols and external strings. */ external_ext_size = ecoff_backend (abfd)->debug_swap.external_ext_size; esize = symhdr->iextMax * external_ext_size; external_ext = bfd_malloc (esize); if (external_ext == NULL && esize != 0) goto error_return; if (bfd_seek (abfd, (file_ptr) symhdr->cbExtOffset, SEEK_SET) != 0 || bfd_bread (external_ext, esize, abfd) != esize) goto error_return; ssext = bfd_malloc ((bfd_size_type) symhdr->issExtMax); if (ssext == NULL && symhdr->issExtMax != 0) goto error_return; if (bfd_seek (abfd, (file_ptr) symhdr->cbSsExtOffset, SEEK_SET) != 0 || (bfd_bread (ssext, (bfd_size_type) symhdr->issExtMax, abfd) != (bfd_size_type) symhdr->issExtMax)) goto error_return; result = ecoff_link_add_externals (abfd, info, external_ext, ssext); if (ssext != NULL) free (ssext); if (external_ext != NULL) free (external_ext); return result; error_return: if (ssext != NULL) free (ssext); if (external_ext != NULL) free (external_ext); return FALSE; } /* This is called if we used _bfd_generic_link_add_archive_symbols because we were not dealing with an ECOFF archive. */ static bfd_boolean ecoff_link_check_archive_element (bfd *abfd, struct bfd_link_info *info, bfd_boolean *pneeded) { const struct ecoff_backend_data * const backend = ecoff_backend (abfd); void (* const swap_ext_in) (bfd *, void *, EXTR *) = backend->debug_swap.swap_ext_in; HDRR *symhdr; bfd_size_type external_ext_size; void * external_ext = NULL; bfd_size_type esize; char *ssext = NULL; char *ext_ptr; char *ext_end; *pneeded = FALSE; if (! ecoff_slurp_symbolic_header (abfd)) goto error_return; /* If there are no symbols, we don't want it. */ if (bfd_get_symcount (abfd) == 0) goto successful_return; symhdr = &ecoff_data (abfd)->debug_info.symbolic_header; /* Read in the external symbols and external strings. */ external_ext_size = backend->debug_swap.external_ext_size; esize = symhdr->iextMax * external_ext_size; external_ext = bfd_malloc (esize); if (external_ext == NULL && esize != 0) goto error_return; if (bfd_seek (abfd, (file_ptr) symhdr->cbExtOffset, SEEK_SET) != 0 || bfd_bread (external_ext, esize, abfd) != esize) goto error_return; ssext = bfd_malloc ((bfd_size_type) symhdr->issExtMax); if (ssext == NULL && symhdr->issExtMax != 0) goto error_return; if (bfd_seek (abfd, (file_ptr) symhdr->cbSsExtOffset, SEEK_SET) != 0 || (bfd_bread (ssext, (bfd_size_type) symhdr->issExtMax, abfd) != (bfd_size_type) symhdr->issExtMax)) goto error_return; /* Look through the external symbols to see if they define some symbol that is currently undefined. */ ext_ptr = (char *) external_ext; ext_end = ext_ptr + esize; for (; ext_ptr < ext_end; ext_ptr += external_ext_size) { EXTR esym; bfd_boolean def; const char *name; struct bfd_link_hash_entry *h; (*swap_ext_in) (abfd, (void *) ext_ptr, &esym); /* See if this symbol defines something. */ if (esym.asym.st != stGlobal && esym.asym.st != stLabel && esym.asym.st != stProc) continue; switch (esym.asym.sc) { case scText: case scData: case scBss: case scAbs: case scSData: case scSBss: case scRData: case scCommon: case scSCommon: case scInit: case scFini: case scRConst: def = TRUE; break; default: def = FALSE; break; } if (! def) continue; name = ssext + esym.asym.iss; h = bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, TRUE); /* Unlike the generic linker, we do not pull in elements because of common symbols. */ if (h == NULL || h->type != bfd_link_hash_undefined) continue; /* Include this element. */ if (! (*info->callbacks->add_archive_element) (info, abfd, name)) goto error_return; if (! ecoff_link_add_externals (abfd, info, external_ext, ssext)) goto error_return; *pneeded = TRUE; goto successful_return; } successful_return: if (external_ext != NULL) free (external_ext); if (ssext != NULL) free (ssext); return TRUE; error_return: if (external_ext != NULL) free (external_ext); if (ssext != NULL) free (ssext); return FALSE; } /* Add the symbols from an archive file to the global hash table. This looks through the undefined symbols, looks each one up in the archive hash table, and adds any associated object file. We do not use _bfd_generic_link_add_archive_symbols because ECOFF archives already have a hash table, so there is no reason to construct another one. */ static bfd_boolean ecoff_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info) { const struct ecoff_backend_data * const backend = ecoff_backend (abfd); const bfd_byte *raw_armap; struct bfd_link_hash_entry **pundef; unsigned int armap_count; unsigned int armap_log; unsigned int i; const bfd_byte *hashtable; const char *stringbase; if (! bfd_has_map (abfd)) { /* An empty archive is a special case. */ if (bfd_openr_next_archived_file (abfd, NULL) == NULL) return TRUE; bfd_set_error (bfd_error_no_armap); return FALSE; } /* If we don't have any raw data for this archive, as can happen on Irix 4.0.5F, we call the generic routine. FIXME: We should be more clever about this, since someday tdata may get to something for a generic archive. */ raw_armap = (const bfd_byte *) bfd_ardata (abfd)->tdata; if (raw_armap == NULL) return (_bfd_generic_link_add_archive_symbols (abfd, info, ecoff_link_check_archive_element)); armap_count = H_GET_32 (abfd, raw_armap); armap_log = 0; for (i = 1; i < armap_count; i <<= 1) armap_log++; BFD_ASSERT (i == armap_count); hashtable = raw_armap + 4; stringbase = (const char *) raw_armap + armap_count * 8 + 8; /* Look through the list of undefined symbols. */ pundef = &info->hash->undefs; while (*pundef != NULL) { struct bfd_link_hash_entry *h; unsigned int hash, rehash = 0; unsigned int file_offset; const char *name; bfd *element; h = *pundef; /* When a symbol is defined, it is not necessarily removed from the list. */ if (h->type != bfd_link_hash_undefined && h->type != bfd_link_hash_common) { /* Remove this entry from the list, for general cleanliness and because we are going to look through the list again if we search any more libraries. We can't remove the entry if it is the tail, because that would lose any entries we add to the list later on. */ if (*pundef != info->hash->undefs_tail) *pundef = (*pundef)->u.undef.next; else pundef = &(*pundef)->u.undef.next; continue; } /* Native ECOFF linkers do not pull in archive elements merely to satisfy common definitions, so neither do we. We leave them on the list, though, in case we are linking against some other object format. */ if (h->type != bfd_link_hash_undefined) { pundef = &(*pundef)->u.undef.next; continue; } /* Look for this symbol in the archive hash table. */ hash = ecoff_armap_hash (h->root.string, &rehash, armap_count, armap_log); file_offset = H_GET_32 (abfd, hashtable + (hash * 8) + 4); if (file_offset == 0) { /* Nothing in this slot. */ pundef = &(*pundef)->u.undef.next; continue; } name = stringbase + H_GET_32 (abfd, hashtable + (hash * 8)); if (name[0] != h->root.string[0] || ! streq (name, h->root.string)) { unsigned int srch; bfd_boolean found; /* That was the wrong symbol. Try rehashing. */ found = FALSE; for (srch = (hash + rehash) & (armap_count - 1); srch != hash; srch = (srch + rehash) & (armap_count - 1)) { file_offset = H_GET_32 (abfd, hashtable + (srch * 8) + 4); if (file_offset == 0) break; name = stringbase + H_GET_32 (abfd, hashtable + (srch * 8)); if (name[0] == h->root.string[0] && streq (name, h->root.string)) { found = TRUE; break; } } if (! found) { pundef = &(*pundef)->u.undef.next; continue; } hash = srch; } element = (*backend->get_elt_at_filepos) (abfd, (file_ptr) file_offset); if (element == NULL) return FALSE; if (! bfd_check_format (element, bfd_object)) return FALSE; /* Unlike the generic linker, we know that this element provides a definition for an undefined symbol and we know that we want to include it. We don't need to check anything. */ if (! (*info->callbacks->add_archive_element) (info, element, name)) return FALSE; if (! ecoff_link_add_object_symbols (element, info)) return FALSE; pundef = &(*pundef)->u.undef.next; } return TRUE; } /* Given an ECOFF BFD, add symbols to the global hash table as appropriate. */ bfd_boolean _bfd_ecoff_bfd_link_add_symbols (bfd *abfd, struct bfd_link_info *info) { switch (bfd_get_format (abfd)) { case bfd_object: return ecoff_link_add_object_symbols (abfd, info); case bfd_archive: return ecoff_link_add_archive_symbols (abfd, info); default: bfd_set_error (bfd_error_wrong_format); return FALSE; } } /* ECOFF final link routines. */ /* Structure used to pass information to ecoff_link_write_external. */ struct extsym_info { bfd *abfd; struct bfd_link_info *info; }; /* Accumulate the debugging information for an input BFD into the output BFD. This must read in the symbolic information of the input BFD. */ static bfd_boolean ecoff_final_link_debug_accumulate (bfd *output_bfd, bfd *input_bfd, struct bfd_link_info *info, void * handle) { struct ecoff_debug_info * const debug = &ecoff_data (input_bfd)->debug_info; const struct ecoff_debug_swap * const swap = &ecoff_backend (input_bfd)->debug_swap; HDRR *symhdr = &debug->symbolic_header; bfd_boolean ret; #define READ(ptr, offset, count, size, type) \ if (symhdr->count == 0) \ debug->ptr = NULL; \ else \ { \ bfd_size_type amt = (bfd_size_type) size * symhdr->count; \ debug->ptr = bfd_malloc (amt); \ if (debug->ptr == NULL) \ { \ ret = FALSE; \ goto return_something; \ } \ if (bfd_seek (input_bfd, (file_ptr) symhdr->offset, SEEK_SET) != 0 \ || bfd_bread (debug->ptr, amt, input_bfd) != amt) \ { \ ret = FALSE; \ goto return_something; \ } \ } /* If raw_syments is not NULL, then the data was already by read by _bfd_ecoff_slurp_symbolic_info. */ if (ecoff_data (input_bfd)->raw_syments == NULL) { READ (line, cbLineOffset, cbLine, sizeof (unsigned char), unsigned char *); READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, void *); READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size, void *); READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size, void *); READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size, void *); READ (external_aux, cbAuxOffset, iauxMax, sizeof (union aux_ext), union aux_ext *); READ (ss, cbSsOffset, issMax, sizeof (char), char *); READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size, void *); READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, void *); } #undef READ /* We do not read the external strings or the external symbols. */ ret = (bfd_ecoff_debug_accumulate (handle, output_bfd, &ecoff_data (output_bfd)->debug_info, &ecoff_backend (output_bfd)->debug_swap, input_bfd, debug, swap, info)); return_something: if (ecoff_data (input_bfd)->raw_syments == NULL) { if (debug->line != NULL) free (debug->line); if (debug->external_dnr != NULL) free (debug->external_dnr); if (debug->external_pdr != NULL) free (debug->external_pdr); if (debug->external_sym != NULL) free (debug->external_sym); if (debug->external_opt != NULL) free (debug->external_opt); if (debug->external_aux != NULL) free (debug->external_aux); if (debug->ss != NULL) free (debug->ss); if (debug->external_fdr != NULL) free (debug->external_fdr); if (debug->external_rfd != NULL) free (debug->external_rfd); /* Make sure we don't accidentally follow one of these pointers into freed memory. */ debug->line = NULL; debug->external_dnr = NULL; debug->external_pdr = NULL; debug->external_sym = NULL; debug->external_opt = NULL; debug->external_aux = NULL; debug->ss = NULL; debug->external_fdr = NULL; debug->external_rfd = NULL; } return ret; } /* Relocate and write an ECOFF section into an ECOFF output file. */ static bfd_boolean ecoff_indirect_link_order (bfd *output_bfd, struct bfd_link_info *info, asection *output_section, struct bfd_link_order *link_order) { asection *input_section; bfd *input_bfd; bfd_byte *contents = NULL; bfd_size_type external_reloc_size; bfd_size_type external_relocs_size; void * external_relocs = NULL; BFD_ASSERT ((output_section->flags & SEC_HAS_CONTENTS) != 0); input_section = link_order->u.indirect.section; input_bfd = input_section->owner; if (input_section->size == 0) return TRUE; BFD_ASSERT (input_section->output_section == output_section); BFD_ASSERT (input_section->output_offset == link_order->offset); BFD_ASSERT (input_section->size == link_order->size); /* Get the section contents. */ if (!bfd_malloc_and_get_section (input_bfd, input_section, &contents)) goto error_return; /* Get the relocs. If we are relaxing MIPS code, they will already have been read in. Otherwise, we read them in now. */ external_reloc_size = ecoff_backend (input_bfd)->external_reloc_size; external_relocs_size = external_reloc_size * input_section->reloc_count; external_relocs = bfd_malloc (external_relocs_size); if (external_relocs == NULL && external_relocs_size != 0) goto error_return; if (bfd_seek (input_bfd, input_section->rel_filepos, SEEK_SET) != 0 || (bfd_bread (external_relocs, external_relocs_size, input_bfd) != external_relocs_size)) goto error_return; /* Relocate the section contents. */ if (! ((*ecoff_backend (input_bfd)->relocate_section) (output_bfd, info, input_bfd, input_section, contents, external_relocs))) goto error_return; /* Write out the relocated section. */ if (! bfd_set_section_contents (output_bfd, output_section, contents, input_section->output_offset, input_section->size)) goto error_return; /* If we are producing relocatable output, the relocs were modified, and we write them out now. We use the reloc_count field of output_section to keep track of the number of relocs we have output so far. */ if (info->relocatable) { file_ptr pos = (output_section->rel_filepos + output_section->reloc_count * external_reloc_size); if (bfd_seek (output_bfd, pos, SEEK_SET) != 0 || (bfd_bwrite (external_relocs, external_relocs_size, output_bfd) != external_relocs_size)) goto error_return; output_section->reloc_count += input_section->reloc_count; } if (contents != NULL) free (contents); if (external_relocs != NULL) free (external_relocs); return TRUE; error_return: if (contents != NULL) free (contents); if (external_relocs != NULL) free (external_relocs); return FALSE; } /* Generate a reloc when linking an ECOFF file. This is a reloc requested by the linker, and does come from any input file. This is used to build constructor and destructor tables when linking with -Ur. */ static bfd_boolean ecoff_reloc_link_order (bfd *output_bfd, struct bfd_link_info *info, asection *output_section, struct bfd_link_order *link_order) { enum bfd_link_order_type type; asection *section; bfd_vma addend; arelent rel; struct internal_reloc in; bfd_size_type external_reloc_size; bfd_byte *rbuf; bfd_boolean ok; file_ptr pos; type = link_order->type; section = NULL; addend = link_order->u.reloc.p->addend; /* We set up an arelent to pass to the backend adjust_reloc_out routine. */ rel.address = link_order->offset; rel.howto = bfd_reloc_type_lookup (output_bfd, link_order->u.reloc.p->reloc); if (rel.howto == 0) { bfd_set_error (bfd_error_bad_value); return FALSE; } if (type == bfd_section_reloc_link_order) { section = link_order->u.reloc.p->u.section; rel.sym_ptr_ptr = section->symbol_ptr_ptr; } else { struct bfd_link_hash_entry *h; /* Treat a reloc against a defined symbol as though it were actually against the section. */ h = bfd_wrapped_link_hash_lookup (output_bfd, info, link_order->u.reloc.p->u.name, FALSE, FALSE, FALSE); if (h != NULL && (h->type == bfd_link_hash_defined || h->type == bfd_link_hash_defweak)) { type = bfd_section_reloc_link_order; section = h->u.def.section->output_section; /* It seems that we ought to add the symbol value to the addend here, but in practice it has already been added because it was passed to constructor_callback. */ addend += section->vma + h->u.def.section->output_offset; } else { /* We can't set up a reloc against a symbol correctly, because we have no asymbol structure. Currently no adjust_reloc_out routine cares. */ rel.sym_ptr_ptr = NULL; } } /* All ECOFF relocs are in-place. Put the addend into the object file. */ BFD_ASSERT (rel.howto->partial_inplace); if (addend != 0) { bfd_size_type size; bfd_reloc_status_type rstat; bfd_byte *buf; size = bfd_get_reloc_size (rel.howto); buf = bfd_zmalloc (size); if (buf == NULL) return FALSE; rstat = _bfd_relocate_contents (rel.howto, output_bfd, (bfd_vma) addend, buf); switch (rstat) { case bfd_reloc_ok: break; default: case bfd_reloc_outofrange: abort (); case bfd_reloc_overflow: if (! ((*info->callbacks->reloc_overflow) (info, NULL, (link_order->type == bfd_section_reloc_link_order ? bfd_section_name (output_bfd, section) : link_order->u.reloc.p->u.name), rel.howto->name, addend, NULL, NULL, (bfd_vma) 0))) { free (buf); return FALSE; } break; } ok = bfd_set_section_contents (output_bfd, output_section, (void *) buf, (file_ptr) link_order->offset, size); free (buf); if (! ok) return FALSE; } rel.addend = 0; /* Move the information into an internal_reloc structure. */ in.r_vaddr = (rel.address + bfd_get_section_vma (output_bfd, output_section)); in.r_type = rel.howto->type; if (type == bfd_symbol_reloc_link_order) { struct ecoff_link_hash_entry *h; h = ((struct ecoff_link_hash_entry *) bfd_wrapped_link_hash_lookup (output_bfd, info, link_order->u.reloc.p->u.name, FALSE, FALSE, TRUE)); if (h != NULL && h->indx != -1) in.r_symndx = h->indx; else { if (! ((*info->callbacks->unattached_reloc) (info, link_order->u.reloc.p->u.name, NULL, NULL, (bfd_vma) 0))) return FALSE; in.r_symndx = 0; } in.r_extern = 1; } else { const char *name; unsigned int i; static struct { const char * name; long r_symndx; } section_symndx [] = { { _TEXT, RELOC_SECTION_TEXT }, { _RDATA, RELOC_SECTION_RDATA }, { _DATA, RELOC_SECTION_DATA }, { _SDATA, RELOC_SECTION_SDATA }, { _SBSS, RELOC_SECTION_SBSS }, { _BSS, RELOC_SECTION_BSS }, { _INIT, RELOC_SECTION_INIT }, { _LIT8, RELOC_SECTION_LIT8 }, { _LIT4, RELOC_SECTION_LIT4 }, { _XDATA, RELOC_SECTION_XDATA }, { _PDATA, RELOC_SECTION_PDATA }, { _FINI, RELOC_SECTION_FINI }, { _LITA, RELOC_SECTION_LITA }, { "*ABS*", RELOC_SECTION_ABS }, { _RCONST, RELOC_SECTION_RCONST } }; name = bfd_get_section_name (output_bfd, section); for (i = 0; i < ARRAY_SIZE (section_symndx); i++) if (streq (name, section_symndx[i].name)) { in.r_symndx = section_symndx[i].r_symndx; break; } if (i == ARRAY_SIZE (section_symndx)) abort (); in.r_extern = 0; } /* Let the BFD backend adjust the reloc. */ (*ecoff_backend (output_bfd)->adjust_reloc_out) (output_bfd, &rel, &in); /* Get some memory and swap out the reloc. */ external_reloc_size = ecoff_backend (output_bfd)->external_reloc_size; rbuf = bfd_malloc (external_reloc_size); if (rbuf == NULL) return FALSE; (*ecoff_backend (output_bfd)->swap_reloc_out) (output_bfd, &in, (void *) rbuf); pos = (output_section->rel_filepos + output_section->reloc_count * external_reloc_size); ok = (bfd_seek (output_bfd, pos, SEEK_SET) == 0 && (bfd_bwrite ((void *) rbuf, external_reloc_size, output_bfd) == external_reloc_size)); if (ok) ++output_section->reloc_count; free (rbuf); return ok; } /* Put out information for an external symbol. These come only from the hash table. */ static bfd_boolean ecoff_link_write_external (struct ecoff_link_hash_entry *h, void * data) { struct extsym_info *einfo = (struct extsym_info *) data; bfd *output_bfd = einfo->abfd; bfd_boolean strip; if (h->root.type == bfd_link_hash_warning) { h = (struct ecoff_link_hash_entry *) h->root.u.i.link; if (h->root.type == bfd_link_hash_new) return TRUE; } /* We need to check if this symbol is being stripped. */ if (h->root.type == bfd_link_hash_undefined || h->root.type == bfd_link_hash_undefweak) strip = FALSE; else if (einfo->info->strip == strip_all || (einfo->info->strip == strip_some && bfd_hash_lookup (einfo->info->keep_hash, h->root.root.string, FALSE, FALSE) == NULL)) strip = TRUE; else strip = FALSE; if (strip || h->written) return TRUE; if (h->abfd == NULL) { h->esym.jmptbl = 0; h->esym.cobol_main = 0; h->esym.weakext = 0; h->esym.reserved = 0; h->esym.ifd = ifdNil; h->esym.asym.value = 0; h->esym.asym.st = stGlobal; if (h->root.type != bfd_link_hash_defined && h->root.type != bfd_link_hash_defweak) h->esym.asym.sc = scAbs; else { asection *output_section; const char *name; unsigned int i; static struct { const char * name; int sc; } section_storage_classes [] = { { _TEXT, scText }, { _DATA, scData }, { _SDATA, scSData }, { _RDATA, scRData }, { _BSS, scBss }, { _SBSS, scSBss }, { _INIT, scInit }, { _FINI, scFini }, { _PDATA, scPData }, { _XDATA, scXData }, { _RCONST, scRConst } }; output_section = h->root.u.def.section->output_section; name = bfd_section_name (output_section->owner, output_section); for (i = 0; i < ARRAY_SIZE (section_storage_classes); i++) if (streq (name, section_storage_classes[i].name)) { h->esym.asym.sc = section_storage_classes[i].sc; break; } if (i == ARRAY_SIZE (section_storage_classes)) h->esym.asym.sc = scAbs; } h->esym.asym.reserved = 0; h->esym.asym.index = indexNil; } else if (h->esym.ifd != -1) { struct ecoff_debug_info *debug; /* Adjust the FDR index for the symbol by that used for the input BFD. */ debug = &ecoff_data (h->abfd)->debug_info; BFD_ASSERT (h->esym.ifd >= 0 && h->esym.ifd < debug->symbolic_header.ifdMax); h->esym.ifd = debug->ifdmap[h->esym.ifd]; } switch (h->root.type) { default: case bfd_link_hash_warning: case bfd_link_hash_new: abort (); case bfd_link_hash_undefined: case bfd_link_hash_undefweak: if (h->esym.asym.sc != scUndefined && h->esym.asym.sc != scSUndefined) h->esym.asym.sc = scUndefined; break; case bfd_link_hash_defined: case bfd_link_hash_defweak: if (h->esym.asym.sc == scUndefined || h->esym.asym.sc == scSUndefined) h->esym.asym.sc = scAbs; else if (h->esym.asym.sc == scCommon) h->esym.asym.sc = scBss; else if (h->esym.asym.sc == scSCommon) h->esym.asym.sc = scSBss; h->esym.asym.value = (h->root.u.def.value + h->root.u.def.section->output_section->vma + h->root.u.def.section->output_offset); break; case bfd_link_hash_common: if (h->esym.asym.sc != scCommon && h->esym.asym.sc != scSCommon) h->esym.asym.sc = scCommon; h->esym.asym.value = h->root.u.c.size; break; case bfd_link_hash_indirect: /* We ignore these symbols, since the indirected symbol is already in the hash table. */ return TRUE; } /* bfd_ecoff_debug_one_external uses iextMax to keep track of the symbol number. */ h->indx = ecoff_data (output_bfd)->debug_info.symbolic_header.iextMax; h->written = 1; return (bfd_ecoff_debug_one_external (output_bfd, &ecoff_data (output_bfd)->debug_info, &ecoff_backend (output_bfd)->debug_swap, h->root.root.string, &h->esym)); } /* ECOFF final link routine. This looks through all the input BFDs and gathers together all the debugging information, and then processes all the link order information. This may cause it to close and reopen some input BFDs; I'll see how bad this is. */ bfd_boolean _bfd_ecoff_bfd_final_link (bfd *abfd, struct bfd_link_info *info) { const struct ecoff_backend_data * const backend = ecoff_backend (abfd); struct ecoff_debug_info * const debug = &ecoff_data (abfd)->debug_info; HDRR *symhdr; void * handle; bfd *input_bfd; asection *o; struct bfd_link_order *p; struct extsym_info einfo; /* We accumulate the debugging information counts in the symbolic header. */ symhdr = &debug->symbolic_header; symhdr->vstamp = 0; symhdr->ilineMax = 0; symhdr->cbLine = 0; symhdr->idnMax = 0; symhdr->ipdMax = 0; symhdr->isymMax = 0; symhdr->ioptMax = 0; symhdr->iauxMax = 0; symhdr->issMax = 0; symhdr->issExtMax = 0; symhdr->ifdMax = 0; symhdr->crfd = 0; symhdr->iextMax = 0; /* We accumulate the debugging information itself in the debug_info structure. */ debug->line = NULL; debug->external_dnr = NULL; debug->external_pdr = NULL; debug->external_sym = NULL; debug->external_opt = NULL; debug->external_aux = NULL; debug->ss = NULL; debug->ssext = debug->ssext_end = NULL; debug->external_fdr = NULL; debug->external_rfd = NULL; debug->external_ext = debug->external_ext_end = NULL; handle = bfd_ecoff_debug_init (abfd, debug, &backend->debug_swap, info); if (handle == NULL) return FALSE; /* Accumulate the debugging symbols from each input BFD. */ for (input_bfd = info->input_bfds; input_bfd != NULL; input_bfd = input_bfd->link_next) { bfd_boolean ret; if (bfd_get_flavour (input_bfd) == bfd_target_ecoff_flavour) { /* Arbitrarily set the symbolic header vstamp to the vstamp of the first object file in the link. */ if (symhdr->vstamp == 0) symhdr->vstamp = ecoff_data (input_bfd)->debug_info.symbolic_header.vstamp; ret = ecoff_final_link_debug_accumulate (abfd, input_bfd, info, handle); } else ret = bfd_ecoff_debug_accumulate_other (handle, abfd, debug, &backend->debug_swap, input_bfd, info); if (! ret) return FALSE; /* Combine the register masks. */ ecoff_data (abfd)->gprmask |= ecoff_data (input_bfd)->gprmask; ecoff_data (abfd)->fprmask |= ecoff_data (input_bfd)->fprmask; ecoff_data (abfd)->cprmask[0] |= ecoff_data (input_bfd)->cprmask[0]; ecoff_data (abfd)->cprmask[1] |= ecoff_data (input_bfd)->cprmask[1]; ecoff_data (abfd)->cprmask[2] |= ecoff_data (input_bfd)->cprmask[2]; ecoff_data (abfd)->cprmask[3] |= ecoff_data (input_bfd)->cprmask[3]; } /* Write out the external symbols. */ einfo.abfd = abfd; einfo.info = info; ecoff_link_hash_traverse (ecoff_hash_table (info), ecoff_link_write_external, (void *) &einfo); if (info->relocatable) { /* We need to make a pass over the link_orders to count up the number of relocations we will need to output, so that we know how much space they will take up. */ for (o = abfd->sections; o != NULL; o = o->next) { o->reloc_count = 0; for (p = o->map_head.link_order; p != NULL; p = p->next) if (p->type == bfd_indirect_link_order) o->reloc_count += p->u.indirect.section->reloc_count; else if (p->type == bfd_section_reloc_link_order || p->type == bfd_symbol_reloc_link_order) ++o->reloc_count; } } /* Compute the reloc and symbol file positions. */ ecoff_compute_reloc_file_positions (abfd); /* Write out the debugging information. */ if (! bfd_ecoff_write_accumulated_debug (handle, abfd, debug, &backend->debug_swap, info, ecoff_data (abfd)->sym_filepos)) return FALSE; bfd_ecoff_debug_free (handle, abfd, debug, &backend->debug_swap, info); if (info->relocatable) { /* Now reset the reloc_count field of the sections in the output BFD to 0, so that we can use them to keep track of how many relocs we have output thus far. */ for (o = abfd->sections; o != NULL; o = o->next) o->reloc_count = 0; } /* Get a value for the GP register. */ if (ecoff_data (abfd)->gp == 0) { struct bfd_link_hash_entry *h; h = bfd_link_hash_lookup (info->hash, "_gp", FALSE, FALSE, TRUE); if (h != NULL && h->type == bfd_link_hash_defined) ecoff_data (abfd)->gp = (h->u.def.value + h->u.def.section->output_section->vma + h->u.def.section->output_offset); else if (info->relocatable) { bfd_vma lo; /* Make up a value. */ lo = (bfd_vma) -1; for (o = abfd->sections; o != NULL; o = o->next) { if (o->vma < lo && (streq (o->name, _SBSS) || streq (o->name, _SDATA) || streq (o->name, _LIT4) || streq (o->name, _LIT8) || streq (o->name, _LITA))) lo = o->vma; } ecoff_data (abfd)->gp = lo + 0x8000; } else { /* If the relocate_section function needs to do a reloc involving the GP value, it should make a reloc_dangerous callback to warn that GP is not defined. */ } } for (o = abfd->sections; o != NULL; o = o->next) { for (p = o->map_head.link_order; p != NULL; p = p->next) { if (p->type == bfd_indirect_link_order && (bfd_get_flavour (p->u.indirect.section->owner) == bfd_target_ecoff_flavour)) { if (! ecoff_indirect_link_order (abfd, info, o, p)) return FALSE; } else if (p->type == bfd_section_reloc_link_order || p->type == bfd_symbol_reloc_link_order) { if (! ecoff_reloc_link_order (abfd, info, o, p)) return FALSE; } else { if (! _bfd_default_link_order (abfd, info, o, p)) return FALSE; } } } bfd_get_symcount (abfd) = symhdr->iextMax + symhdr->isymMax; ecoff_data (abfd)->linker = TRUE; return TRUE; } Index: head/contrib/binutils/bfd/elf32-ppc.c =================================================================== --- head/contrib/binutils/bfd/elf32-ppc.c (revision 275717) +++ head/contrib/binutils/bfd/elf32-ppc.c (revision 275718) @@ -1,7742 +1,7940 @@ /* PowerPC-specific support for 32-bit ELF Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. Written by Ian Lance Taylor, Cygnus Support. This file is part of BFD, the Binary File Descriptor library. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ /* This file is based on a preliminary PowerPC ELF ABI. The information may not match the final PowerPC ELF ABI. It includes suggestions from the in-progress Embedded PowerPC ABI, and that information may also not match. */ #include "sysdep.h" #include #include "bfd.h" #include "bfdlink.h" #include "libbfd.h" #include "elf-bfd.h" #include "elf/ppc.h" #include "elf32-ppc.h" #include "elf-vxworks.h" /* RELA relocations are used here. */ static bfd_reloc_status_type ppc_elf_addr16_ha_reloc (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); static bfd_reloc_status_type ppc_elf_unhandled_reloc (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); /* Branch prediction bit for branch taken relocs. */ #define BRANCH_PREDICT_BIT 0x200000 /* Mask to set RA in memory instructions. */ #define RA_REGISTER_MASK 0x001f0000 /* Value to shift register by to insert RA. */ #define RA_REGISTER_SHIFT 16 /* The name of the dynamic interpreter. This is put in the .interp section. */ #define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1" /* For old-style PLT. */ /* The number of single-slot PLT entries (the rest use two slots). */ #define PLT_NUM_SINGLE_ENTRIES 8192 /* For new-style .glink and .plt. */ #define GLINK_PLTRESOLVE 16*4 #define GLINK_ENTRY_SIZE 4*4 /* VxWorks uses its own plt layout, filled in by the static linker. */ /* The standard VxWorks PLT entry. */ #define VXWORKS_PLT_ENTRY_SIZE 32 static const bfd_vma ppc_elf_vxworks_plt_entry [VXWORKS_PLT_ENTRY_SIZE / 4] = { 0x3d800000, /* lis r12,0 */ 0x818c0000, /* lwz r12,0(r12) */ 0x7d8903a6, /* mtctr r12 */ 0x4e800420, /* bctr */ 0x39600000, /* li r11,0 */ 0x48000000, /* b 14 <.PLT0resolve+0x4> */ 0x60000000, /* nop */ 0x60000000, /* nop */ }; static const bfd_vma ppc_elf_vxworks_pic_plt_entry [VXWORKS_PLT_ENTRY_SIZE / 4] = { 0x3d9e0000, /* addis r12,r30,0 */ 0x818c0000, /* lwz r12,0(r12) */ 0x7d8903a6, /* mtctr r12 */ 0x4e800420, /* bctr */ 0x39600000, /* li r11,0 */ 0x48000000, /* b 14 <.PLT0resolve+0x4> 14: R_PPC_REL24 .PLTresolve */ 0x60000000, /* nop */ 0x60000000, /* nop */ }; /* The initial VxWorks PLT entry. */ #define VXWORKS_PLT_INITIAL_ENTRY_SIZE 32 static const bfd_vma ppc_elf_vxworks_plt0_entry [VXWORKS_PLT_INITIAL_ENTRY_SIZE / 4] = { 0x3d800000, /* lis r12,0 */ 0x398c0000, /* addi r12,r12,0 */ 0x800c0008, /* lwz r0,8(r12) */ 0x7c0903a6, /* mtctr r0 */ 0x818c0004, /* lwz r12,4(r12) */ 0x4e800420, /* bctr */ 0x60000000, /* nop */ 0x60000000, /* nop */ }; static const bfd_vma ppc_elf_vxworks_pic_plt0_entry [VXWORKS_PLT_INITIAL_ENTRY_SIZE / 4] = { 0x819e0008, /* lwz r12,8(r30) */ 0x7d8903a6, /* mtctr r12 */ 0x819e0004, /* lwz r12,4(r30) */ 0x4e800420, /* bctr */ 0x60000000, /* nop */ 0x60000000, /* nop */ 0x60000000, /* nop */ 0x60000000, /* nop */ }; /* For executables, we have some additional relocations in .rela.plt.unloaded, for the kernel loader. */ /* The number of non-JMP_SLOT relocations per PLT0 slot. */ #define VXWORKS_PLT_NON_JMP_SLOT_RELOCS 3 /* The number of relocations in the PLTResolve slot. */ #define VXWORKS_PLTRESOLVE_RELOCS 2 /* The number of relocations in the PLTResolve slot when when creating a shared library. */ #define VXWORKS_PLTRESOLVE_RELOCS_SHLIB 0 /* Some instructions. */ #define ADDIS_11_11 0x3d6b0000 #define ADDIS_11_30 0x3d7e0000 #define ADDIS_12_12 0x3d8c0000 #define ADDI_11_11 0x396b0000 #define ADD_0_11_11 0x7c0b5a14 #define ADD_11_0_11 0x7d605a14 #define B 0x48000000 #define BCL_20_31 0x429f0005 #define BCTR 0x4e800420 #define LIS_11 0x3d600000 #define LIS_12 0x3d800000 #define LWZU_0_12 0x840c0000 #define LWZ_0_12 0x800c0000 #define LWZ_11_11 0x816b0000 #define LWZ_11_30 0x817e0000 #define LWZ_12_12 0x818c0000 #define MFLR_0 0x7c0802a6 #define MFLR_12 0x7d8802a6 #define MTCTR_0 0x7c0903a6 #define MTCTR_11 0x7d6903a6 #define MTLR_0 0x7c0803a6 #define NOP 0x60000000 #define SUB_11_11_12 0x7d6c5850 /* Offset of tp and dtp pointers from start of TLS block. */ #define TP_OFFSET 0x7000 #define DTP_OFFSET 0x8000 static reloc_howto_type *ppc_elf_howto_table[R_PPC_max]; static reloc_howto_type ppc_elf_howto_raw[] = { /* This reloc does nothing. */ HOWTO (R_PPC_NONE, /* 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_PPC_NONE", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ FALSE), /* pcrel_offset */ /* A standard 32 bit relocation. */ HOWTO (R_PPC_ADDR32, /* 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_PPC_ADDR32", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffffffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* An absolute 26 bit branch; the lower two bits must be zero. FIXME: we don't check that, we just clear them. */ HOWTO (R_PPC_ADDR24, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 26, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC_ADDR24", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0x3fffffc, /* dst_mask */ FALSE), /* pcrel_offset */ /* A standard 16 bit relocation. */ HOWTO (R_PPC_ADDR16, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC_ADDR16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* A 16 bit relocation without overflow. */ HOWTO (R_PPC_ADDR16_LO, /* 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_PPC_ADDR16_LO", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* The high order 16 bits of an address. */ HOWTO (R_PPC_ADDR16_HI, /* type */ 16, /* 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_PPC_ADDR16_HI", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* The high order 16 bits of an address, plus 1 if the contents of the low 16 bits, treated as a signed number, is negative. */ HOWTO (R_PPC_ADDR16_HA, /* type */ 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc_elf_addr16_ha_reloc, /* special_function */ "R_PPC_ADDR16_HA", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* An absolute 16 bit branch; the lower two bits must be zero. FIXME: we don't check that, we just clear them. */ HOWTO (R_PPC_ADDR14, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC_ADDR14", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xfffc, /* dst_mask */ FALSE), /* pcrel_offset */ /* An absolute 16 bit branch, for which bit 10 should be set to indicate that the branch is expected to be taken. The lower two bits must be zero. */ HOWTO (R_PPC_ADDR14_BRTAKEN, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC_ADDR14_BRTAKEN",/* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xfffc, /* dst_mask */ FALSE), /* pcrel_offset */ /* An absolute 16 bit branch, for which bit 10 should be set to indicate that the branch is not expected to be taken. The lower two bits must be zero. */ HOWTO (R_PPC_ADDR14_BRNTAKEN, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC_ADDR14_BRNTAKEN",/* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xfffc, /* dst_mask */ FALSE), /* pcrel_offset */ /* A relative 26 bit branch; the lower two bits must be zero. */ HOWTO (R_PPC_REL24, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 26, /* bitsize */ TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC_REL24", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0x3fffffc, /* dst_mask */ TRUE), /* pcrel_offset */ /* A relative 16 bit branch; the lower two bits must be zero. */ HOWTO (R_PPC_REL14, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC_REL14", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xfffc, /* dst_mask */ TRUE), /* pcrel_offset */ /* A relative 16 bit branch. Bit 10 should be set to indicate that the branch is expected to be taken. The lower two bits must be zero. */ HOWTO (R_PPC_REL14_BRTAKEN, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC_REL14_BRTAKEN", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xfffc, /* dst_mask */ TRUE), /* pcrel_offset */ /* A relative 16 bit branch. Bit 10 should be set to indicate that the branch is not expected to be taken. The lower two bits must be zero. */ HOWTO (R_PPC_REL14_BRNTAKEN, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC_REL14_BRNTAKEN",/* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xfffc, /* dst_mask */ TRUE), /* pcrel_offset */ /* Like R_PPC_ADDR16, but referring to the GOT table entry for the symbol. */ HOWTO (R_PPC_GOT16, /* type */ 0, /* 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_PPC_GOT16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like R_PPC_ADDR16_LO, but referring to the GOT table entry for the symbol. */ HOWTO (R_PPC_GOT16_LO, /* 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_PPC_GOT16_LO", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like R_PPC_ADDR16_HI, but referring to the GOT table entry for the symbol. */ HOWTO (R_PPC_GOT16_HI, /* type */ 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC_GOT16_HI", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like R_PPC_ADDR16_HA, but referring to the GOT table entry for the symbol. */ HOWTO (R_PPC_GOT16_HA, /* type */ 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ ppc_elf_addr16_ha_reloc, /* special_function */ "R_PPC_GOT16_HA", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like R_PPC_REL24, but referring to the procedure linkage table entry for the symbol. */ HOWTO (R_PPC_PLTREL24, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 26, /* bitsize */ TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC_PLTREL24", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0x3fffffc, /* dst_mask */ TRUE), /* pcrel_offset */ /* This is used only by the dynamic linker. The symbol should exist both in the object being run and in some shared library. The dynamic linker copies the data addressed by the symbol from the shared library into the object, because the object being run has to have the data at some particular address. */ HOWTO (R_PPC_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_PPC_COPY", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like R_PPC_ADDR32, but used when setting global offset table entries. */ HOWTO (R_PPC_GLOB_DAT, /* 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_PPC_GLOB_DAT", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffffffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Marks a procedure linkage table entry for a symbol. */ HOWTO (R_PPC_JMP_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_PPC_JMP_SLOT", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ FALSE), /* pcrel_offset */ /* Used only by the dynamic linker. When the object is run, this longword is set to the load address of the object, plus the addend. */ HOWTO (R_PPC_RELATIVE, /* 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_PPC_RELATIVE", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffffffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like R_PPC_REL24, but uses the value of the symbol within the object rather than the final value. Normally used for _GLOBAL_OFFSET_TABLE_. */ HOWTO (R_PPC_LOCAL24PC, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 26, /* bitsize */ TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC_LOCAL24PC", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0x3fffffc, /* dst_mask */ TRUE), /* pcrel_offset */ /* Like R_PPC_ADDR32, but may be unaligned. */ HOWTO (R_PPC_UADDR32, /* 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_PPC_UADDR32", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffffffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like R_PPC_ADDR16, but may be unaligned. */ HOWTO (R_PPC_UADDR16, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC_UADDR16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* 32-bit PC relative */ HOWTO (R_PPC_REL32, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC_REL32", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffffffff, /* dst_mask */ TRUE), /* pcrel_offset */ /* 32-bit relocation to the symbol's procedure linkage table. FIXME: not supported. */ HOWTO (R_PPC_PLT32, /* 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_PPC_PLT32", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ FALSE), /* pcrel_offset */ /* 32-bit PC relative relocation to the symbol's procedure linkage table. FIXME: not supported. */ HOWTO (R_PPC_PLTREL32, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC_PLTREL32", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ TRUE), /* pcrel_offset */ /* Like R_PPC_ADDR16_LO, but referring to the PLT table entry for the symbol. */ HOWTO (R_PPC_PLT16_LO, /* 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_PPC_PLT16_LO", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like R_PPC_ADDR16_HI, but referring to the PLT table entry for the symbol. */ HOWTO (R_PPC_PLT16_HI, /* type */ 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC_PLT16_HI", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like R_PPC_ADDR16_HA, but referring to the PLT table entry for the symbol. */ HOWTO (R_PPC_PLT16_HA, /* type */ 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ ppc_elf_addr16_ha_reloc, /* special_function */ "R_PPC_PLT16_HA", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* A sign-extended 16 bit value relative to _SDA_BASE_, for use with small data items. */ HOWTO (R_PPC_SDAREL16, /* type */ 0, /* 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_PPC_SDAREL16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* 16-bit section relative relocation. */ HOWTO (R_PPC_SECTOFF, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC_SECTOFF", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* 16-bit lower half section relative relocation. */ HOWTO (R_PPC_SECTOFF_LO, /* 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_PPC_SECTOFF_LO", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* 16-bit upper half section relative relocation. */ HOWTO (R_PPC_SECTOFF_HI, /* type */ 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC_SECTOFF_HI", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* 16-bit upper half adjusted section relative relocation. */ HOWTO (R_PPC_SECTOFF_HA, /* type */ 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ ppc_elf_addr16_ha_reloc, /* special_function */ "R_PPC_SECTOFF_HA", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ - /* Marker reloc for TLS. */ + /* Marker relocs for TLS. */ HOWTO (R_PPC_TLS, 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC_TLS", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ FALSE), /* pcrel_offset */ + HOWTO (R_PPC_TLSGD, + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_PPC_TLSGD", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (R_PPC_TLSLD, + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_PPC_TLSLD", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + FALSE), /* pcrel_offset */ + /* Computes the load module index of the load module that contains the definition of its TLS sym. */ HOWTO (R_PPC_DTPMOD32, 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc_elf_unhandled_reloc, /* special_function */ "R_PPC_DTPMOD32", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffffffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Computes a dtv-relative displacement, the difference between the value of sym+add and the base address of the thread-local storage block that contains the definition of sym, minus 0x8000. */ HOWTO (R_PPC_DTPREL32, 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc_elf_unhandled_reloc, /* special_function */ "R_PPC_DTPREL32", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffffffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* A 16 bit dtprel reloc. */ HOWTO (R_PPC_DTPREL16, 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ ppc_elf_unhandled_reloc, /* special_function */ "R_PPC_DTPREL16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like DTPREL16, but no overflow. */ HOWTO (R_PPC_DTPREL16_LO, 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc_elf_unhandled_reloc, /* special_function */ "R_PPC_DTPREL16_LO", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like DTPREL16_LO, but next higher group of 16 bits. */ HOWTO (R_PPC_DTPREL16_HI, 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc_elf_unhandled_reloc, /* special_function */ "R_PPC_DTPREL16_HI", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like DTPREL16_HI, but adjust for low 16 bits. */ HOWTO (R_PPC_DTPREL16_HA, 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc_elf_unhandled_reloc, /* special_function */ "R_PPC_DTPREL16_HA", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Computes a tp-relative displacement, the difference between the value of sym+add and the value of the thread pointer (r13). */ HOWTO (R_PPC_TPREL32, 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc_elf_unhandled_reloc, /* special_function */ "R_PPC_TPREL32", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffffffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* A 16 bit tprel reloc. */ HOWTO (R_PPC_TPREL16, 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ ppc_elf_unhandled_reloc, /* special_function */ "R_PPC_TPREL16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like TPREL16, but no overflow. */ HOWTO (R_PPC_TPREL16_LO, 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc_elf_unhandled_reloc, /* special_function */ "R_PPC_TPREL16_LO", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like TPREL16_LO, but next higher group of 16 bits. */ HOWTO (R_PPC_TPREL16_HI, 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc_elf_unhandled_reloc, /* special_function */ "R_PPC_TPREL16_HI", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like TPREL16_HI, but adjust for low 16 bits. */ HOWTO (R_PPC_TPREL16_HA, 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc_elf_unhandled_reloc, /* special_function */ "R_PPC_TPREL16_HA", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Allocates two contiguous entries in the GOT to hold a tls_index structure, with values (sym+add)@dtpmod and (sym+add)@dtprel, and computes the offset to the first entry. */ HOWTO (R_PPC_GOT_TLSGD16, 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ ppc_elf_unhandled_reloc, /* special_function */ "R_PPC_GOT_TLSGD16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like GOT_TLSGD16, but no overflow. */ HOWTO (R_PPC_GOT_TLSGD16_LO, 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc_elf_unhandled_reloc, /* special_function */ "R_PPC_GOT_TLSGD16_LO", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like GOT_TLSGD16_LO, but next higher group of 16 bits. */ HOWTO (R_PPC_GOT_TLSGD16_HI, 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc_elf_unhandled_reloc, /* special_function */ "R_PPC_GOT_TLSGD16_HI", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like GOT_TLSGD16_HI, but adjust for low 16 bits. */ HOWTO (R_PPC_GOT_TLSGD16_HA, 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc_elf_unhandled_reloc, /* special_function */ "R_PPC_GOT_TLSGD16_HA", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Allocates two contiguous entries in the GOT to hold a tls_index structure, with values (sym+add)@dtpmod and zero, and computes the offset to the first entry. */ HOWTO (R_PPC_GOT_TLSLD16, 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ ppc_elf_unhandled_reloc, /* special_function */ "R_PPC_GOT_TLSLD16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like GOT_TLSLD16, but no overflow. */ HOWTO (R_PPC_GOT_TLSLD16_LO, 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc_elf_unhandled_reloc, /* special_function */ "R_PPC_GOT_TLSLD16_LO", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like GOT_TLSLD16_LO, but next higher group of 16 bits. */ HOWTO (R_PPC_GOT_TLSLD16_HI, 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc_elf_unhandled_reloc, /* special_function */ "R_PPC_GOT_TLSLD16_HI", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like GOT_TLSLD16_HI, but adjust for low 16 bits. */ HOWTO (R_PPC_GOT_TLSLD16_HA, 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc_elf_unhandled_reloc, /* special_function */ "R_PPC_GOT_TLSLD16_HA", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Allocates an entry in the GOT with value (sym+add)@dtprel, and computes the offset to the entry. */ HOWTO (R_PPC_GOT_DTPREL16, 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ ppc_elf_unhandled_reloc, /* special_function */ "R_PPC_GOT_DTPREL16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like GOT_DTPREL16, but no overflow. */ HOWTO (R_PPC_GOT_DTPREL16_LO, 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc_elf_unhandled_reloc, /* special_function */ "R_PPC_GOT_DTPREL16_LO", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like GOT_DTPREL16_LO, but next higher group of 16 bits. */ HOWTO (R_PPC_GOT_DTPREL16_HI, 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc_elf_unhandled_reloc, /* special_function */ "R_PPC_GOT_DTPREL16_HI", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like GOT_DTPREL16_HI, but adjust for low 16 bits. */ HOWTO (R_PPC_GOT_DTPREL16_HA, 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc_elf_unhandled_reloc, /* special_function */ "R_PPC_GOT_DTPREL16_HA", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Allocates an entry in the GOT with value (sym+add)@tprel, and computes the offset to the entry. */ HOWTO (R_PPC_GOT_TPREL16, 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ ppc_elf_unhandled_reloc, /* special_function */ "R_PPC_GOT_TPREL16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like GOT_TPREL16, but no overflow. */ HOWTO (R_PPC_GOT_TPREL16_LO, 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc_elf_unhandled_reloc, /* special_function */ "R_PPC_GOT_TPREL16_LO", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like GOT_TPREL16_LO, but next higher group of 16 bits. */ HOWTO (R_PPC_GOT_TPREL16_HI, 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc_elf_unhandled_reloc, /* special_function */ "R_PPC_GOT_TPREL16_HI", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like GOT_TPREL16_HI, but adjust for low 16 bits. */ HOWTO (R_PPC_GOT_TPREL16_HA, 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc_elf_unhandled_reloc, /* special_function */ "R_PPC_GOT_TPREL16_HA", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* The remaining relocs are from the Embedded ELF ABI, and are not in the SVR4 ELF ABI. */ /* 32 bit value resulting from the addend minus the symbol. */ HOWTO (R_PPC_EMB_NADDR32, /* 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_PPC_EMB_NADDR32", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffffffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* 16 bit value resulting from the addend minus the symbol. */ HOWTO (R_PPC_EMB_NADDR16, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC_EMB_NADDR16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* 16 bit value resulting from the addend minus the symbol. */ HOWTO (R_PPC_EMB_NADDR16_LO, /* 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_PPC_EMB_ADDR16_LO", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* The high order 16 bits of the addend minus the symbol. */ HOWTO (R_PPC_EMB_NADDR16_HI, /* type */ 16, /* 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_PPC_EMB_NADDR16_HI", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* The high order 16 bits of the result of the addend minus the address, plus 1 if the contents of the low 16 bits, treated as a signed number, is negative. */ HOWTO (R_PPC_EMB_NADDR16_HA, /* type */ 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc_elf_addr16_ha_reloc, /* special_function */ "R_PPC_EMB_NADDR16_HA", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* 16 bit value resulting from allocating a 4 byte word to hold an address in the .sdata section, and returning the offset from _SDA_BASE_ for that relocation. */ HOWTO (R_PPC_EMB_SDAI16, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC_EMB_SDAI16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* 16 bit value resulting from allocating a 4 byte word to hold an address in the .sdata2 section, and returning the offset from _SDA2_BASE_ for that relocation. */ HOWTO (R_PPC_EMB_SDA2I16, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC_EMB_SDA2I16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* A sign-extended 16 bit value relative to _SDA2_BASE_, for use with small data items. */ HOWTO (R_PPC_EMB_SDA2REL, /* type */ 0, /* 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_PPC_EMB_SDA2REL", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Relocate against either _SDA_BASE_ or _SDA2_BASE_, filling in the 16 bit signed offset from the appropriate base, and filling in the register field with the appropriate register (0, 2, or 13). */ HOWTO (R_PPC_EMB_SDA21, /* type */ 0, /* rightshift */ 2, /* 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_PPC_EMB_SDA21", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Relocation not handled: R_PPC_EMB_MRKREF */ /* Relocation not handled: R_PPC_EMB_RELSEC16 */ /* Relocation not handled: R_PPC_EMB_RELST_LO */ /* Relocation not handled: R_PPC_EMB_RELST_HI */ /* Relocation not handled: R_PPC_EMB_RELST_HA */ /* Relocation not handled: R_PPC_EMB_BIT_FLD */ /* PC relative relocation against either _SDA_BASE_ or _SDA2_BASE_, filling in the 16 bit signed offset from the appropriate base, and filling in the register field with the appropriate register (0, 2, or 13). */ HOWTO (R_PPC_EMB_RELSDA, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC_EMB_RELSDA", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* A 16 bit relative relocation. */ HOWTO (R_PPC_REL16, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC_REL16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ TRUE), /* pcrel_offset */ /* A 16 bit relative relocation without overflow. */ HOWTO (R_PPC_REL16_LO, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont,/* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC_REL16_LO", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ TRUE), /* pcrel_offset */ /* The high order 16 bits of a relative address. */ HOWTO (R_PPC_REL16_HI, /* type */ 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC_REL16_HI", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ TRUE), /* pcrel_offset */ /* The high order 16 bits of a relative address, plus 1 if the contents of the low 16 bits, treated as a signed number, is negative. */ HOWTO (R_PPC_REL16_HA, /* type */ 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc_elf_addr16_ha_reloc, /* special_function */ "R_PPC_REL16_HA", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ TRUE), /* pcrel_offset */ /* GNU extension to record C++ vtable hierarchy. */ HOWTO (R_PPC_GNU_VTINHERIT, /* type */ 0, /* rightshift */ 0, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ NULL, /* special_function */ "R_PPC_GNU_VTINHERIT", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ FALSE), /* pcrel_offset */ /* GNU extension to record C++ vtable member usage. */ HOWTO (R_PPC_GNU_VTENTRY, /* type */ 0, /* rightshift */ 0, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ NULL, /* special_function */ "R_PPC_GNU_VTENTRY", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ FALSE), /* pcrel_offset */ /* Phony reloc to handle AIX style TOC entries. */ HOWTO (R_PPC_TOC16, /* type */ 0, /* 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_PPC_TOC16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ }; /* Initialize the ppc_elf_howto_table, so that linear accesses can be done. */ static void ppc_elf_howto_init (void) { unsigned int i, type; for (i = 0; i < sizeof (ppc_elf_howto_raw) / sizeof (ppc_elf_howto_raw[0]); i++) { type = ppc_elf_howto_raw[i].type; if (type >= (sizeof (ppc_elf_howto_table) / sizeof (ppc_elf_howto_table[0]))) abort (); ppc_elf_howto_table[type] = &ppc_elf_howto_raw[i]; } } static reloc_howto_type * ppc_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code) { enum elf_ppc_reloc_type r; /* Initialize howto table if not already done. */ if (!ppc_elf_howto_table[R_PPC_ADDR32]) ppc_elf_howto_init (); switch (code) { default: return NULL; case BFD_RELOC_NONE: r = R_PPC_NONE; break; case BFD_RELOC_32: r = R_PPC_ADDR32; break; case BFD_RELOC_PPC_BA26: r = R_PPC_ADDR24; break; case BFD_RELOC_16: r = R_PPC_ADDR16; break; case BFD_RELOC_LO16: r = R_PPC_ADDR16_LO; break; case BFD_RELOC_HI16: r = R_PPC_ADDR16_HI; break; case BFD_RELOC_HI16_S: r = R_PPC_ADDR16_HA; break; case BFD_RELOC_PPC_BA16: r = R_PPC_ADDR14; break; case BFD_RELOC_PPC_BA16_BRTAKEN: r = R_PPC_ADDR14_BRTAKEN; break; case BFD_RELOC_PPC_BA16_BRNTAKEN: r = R_PPC_ADDR14_BRNTAKEN; break; case BFD_RELOC_PPC_B26: r = R_PPC_REL24; break; case BFD_RELOC_PPC_B16: r = R_PPC_REL14; break; case BFD_RELOC_PPC_B16_BRTAKEN: r = R_PPC_REL14_BRTAKEN; break; case BFD_RELOC_PPC_B16_BRNTAKEN: r = R_PPC_REL14_BRNTAKEN; break; case BFD_RELOC_16_GOTOFF: r = R_PPC_GOT16; break; case BFD_RELOC_LO16_GOTOFF: r = R_PPC_GOT16_LO; break; case BFD_RELOC_HI16_GOTOFF: r = R_PPC_GOT16_HI; break; case BFD_RELOC_HI16_S_GOTOFF: r = R_PPC_GOT16_HA; break; case BFD_RELOC_24_PLT_PCREL: r = R_PPC_PLTREL24; break; case BFD_RELOC_PPC_COPY: r = R_PPC_COPY; break; case BFD_RELOC_PPC_GLOB_DAT: r = R_PPC_GLOB_DAT; break; case BFD_RELOC_PPC_LOCAL24PC: r = R_PPC_LOCAL24PC; break; case BFD_RELOC_32_PCREL: r = R_PPC_REL32; break; case BFD_RELOC_32_PLTOFF: r = R_PPC_PLT32; break; case BFD_RELOC_32_PLT_PCREL: r = R_PPC_PLTREL32; break; case BFD_RELOC_LO16_PLTOFF: r = R_PPC_PLT16_LO; break; case BFD_RELOC_HI16_PLTOFF: r = R_PPC_PLT16_HI; break; case BFD_RELOC_HI16_S_PLTOFF: r = R_PPC_PLT16_HA; break; case BFD_RELOC_GPREL16: r = R_PPC_SDAREL16; break; case BFD_RELOC_16_BASEREL: r = R_PPC_SECTOFF; break; case BFD_RELOC_LO16_BASEREL: r = R_PPC_SECTOFF_LO; break; case BFD_RELOC_HI16_BASEREL: r = R_PPC_SECTOFF_HI; break; case BFD_RELOC_HI16_S_BASEREL: r = R_PPC_SECTOFF_HA; break; case BFD_RELOC_CTOR: r = R_PPC_ADDR32; break; case BFD_RELOC_PPC_TOC16: r = R_PPC_TOC16; break; case BFD_RELOC_PPC_TLS: r = R_PPC_TLS; break; + case BFD_RELOC_PPC_TLSGD: r = R_PPC_TLSGD; break; + case BFD_RELOC_PPC_TLSLD: r = R_PPC_TLSLD; break; case BFD_RELOC_PPC_DTPMOD: r = R_PPC_DTPMOD32; break; case BFD_RELOC_PPC_TPREL16: r = R_PPC_TPREL16; break; case BFD_RELOC_PPC_TPREL16_LO: r = R_PPC_TPREL16_LO; break; case BFD_RELOC_PPC_TPREL16_HI: r = R_PPC_TPREL16_HI; break; case BFD_RELOC_PPC_TPREL16_HA: r = R_PPC_TPREL16_HA; break; case BFD_RELOC_PPC_TPREL: r = R_PPC_TPREL32; break; case BFD_RELOC_PPC_DTPREL16: r = R_PPC_DTPREL16; break; case BFD_RELOC_PPC_DTPREL16_LO: r = R_PPC_DTPREL16_LO; break; case BFD_RELOC_PPC_DTPREL16_HI: r = R_PPC_DTPREL16_HI; break; case BFD_RELOC_PPC_DTPREL16_HA: r = R_PPC_DTPREL16_HA; break; case BFD_RELOC_PPC_DTPREL: r = R_PPC_DTPREL32; break; case BFD_RELOC_PPC_GOT_TLSGD16: r = R_PPC_GOT_TLSGD16; break; case BFD_RELOC_PPC_GOT_TLSGD16_LO: r = R_PPC_GOT_TLSGD16_LO; break; case BFD_RELOC_PPC_GOT_TLSGD16_HI: r = R_PPC_GOT_TLSGD16_HI; break; case BFD_RELOC_PPC_GOT_TLSGD16_HA: r = R_PPC_GOT_TLSGD16_HA; break; case BFD_RELOC_PPC_GOT_TLSLD16: r = R_PPC_GOT_TLSLD16; break; case BFD_RELOC_PPC_GOT_TLSLD16_LO: r = R_PPC_GOT_TLSLD16_LO; break; case BFD_RELOC_PPC_GOT_TLSLD16_HI: r = R_PPC_GOT_TLSLD16_HI; break; case BFD_RELOC_PPC_GOT_TLSLD16_HA: r = R_PPC_GOT_TLSLD16_HA; break; case BFD_RELOC_PPC_GOT_TPREL16: r = R_PPC_GOT_TPREL16; break; case BFD_RELOC_PPC_GOT_TPREL16_LO: r = R_PPC_GOT_TPREL16_LO; break; case BFD_RELOC_PPC_GOT_TPREL16_HI: r = R_PPC_GOT_TPREL16_HI; break; case BFD_RELOC_PPC_GOT_TPREL16_HA: r = R_PPC_GOT_TPREL16_HA; break; case BFD_RELOC_PPC_GOT_DTPREL16: r = R_PPC_GOT_DTPREL16; break; case BFD_RELOC_PPC_GOT_DTPREL16_LO: r = R_PPC_GOT_DTPREL16_LO; break; case BFD_RELOC_PPC_GOT_DTPREL16_HI: r = R_PPC_GOT_DTPREL16_HI; break; case BFD_RELOC_PPC_GOT_DTPREL16_HA: r = R_PPC_GOT_DTPREL16_HA; break; case BFD_RELOC_PPC_EMB_NADDR32: r = R_PPC_EMB_NADDR32; break; case BFD_RELOC_PPC_EMB_NADDR16: r = R_PPC_EMB_NADDR16; break; case BFD_RELOC_PPC_EMB_NADDR16_LO: r = R_PPC_EMB_NADDR16_LO; break; case BFD_RELOC_PPC_EMB_NADDR16_HI: r = R_PPC_EMB_NADDR16_HI; break; case BFD_RELOC_PPC_EMB_NADDR16_HA: r = R_PPC_EMB_NADDR16_HA; break; case BFD_RELOC_PPC_EMB_SDAI16: r = R_PPC_EMB_SDAI16; break; case BFD_RELOC_PPC_EMB_SDA2I16: r = R_PPC_EMB_SDA2I16; break; case BFD_RELOC_PPC_EMB_SDA2REL: r = R_PPC_EMB_SDA2REL; break; case BFD_RELOC_PPC_EMB_SDA21: r = R_PPC_EMB_SDA21; break; case BFD_RELOC_PPC_EMB_MRKREF: r = R_PPC_EMB_MRKREF; break; case BFD_RELOC_PPC_EMB_RELSEC16: r = R_PPC_EMB_RELSEC16; break; case BFD_RELOC_PPC_EMB_RELST_LO: r = R_PPC_EMB_RELST_LO; break; case BFD_RELOC_PPC_EMB_RELST_HI: r = R_PPC_EMB_RELST_HI; break; case BFD_RELOC_PPC_EMB_RELST_HA: r = R_PPC_EMB_RELST_HA; break; case BFD_RELOC_PPC_EMB_BIT_FLD: r = R_PPC_EMB_BIT_FLD; break; case BFD_RELOC_PPC_EMB_RELSDA: r = R_PPC_EMB_RELSDA; break; case BFD_RELOC_16_PCREL: r = R_PPC_REL16; break; case BFD_RELOC_LO16_PCREL: r = R_PPC_REL16_LO; break; case BFD_RELOC_HI16_PCREL: r = R_PPC_REL16_HI; break; case BFD_RELOC_HI16_S_PCREL: r = R_PPC_REL16_HA; break; case BFD_RELOC_VTABLE_INHERIT: r = R_PPC_GNU_VTINHERIT; break; case BFD_RELOC_VTABLE_ENTRY: r = R_PPC_GNU_VTENTRY; break; } return ppc_elf_howto_table[r]; }; static reloc_howto_type * ppc_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name) { unsigned int i; for (i = 0; i < sizeof (ppc_elf_howto_raw) / sizeof (ppc_elf_howto_raw[0]); i++) if (ppc_elf_howto_raw[i].name != NULL && strcasecmp (ppc_elf_howto_raw[i].name, r_name) == 0) return &ppc_elf_howto_raw[i]; return NULL; } /* Set the howto pointer for a PowerPC ELF reloc. */ static void ppc_elf_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr, Elf_Internal_Rela *dst) { /* Initialize howto table if not already done. */ if (!ppc_elf_howto_table[R_PPC_ADDR32]) ppc_elf_howto_init (); BFD_ASSERT (ELF32_R_TYPE (dst->r_info) < (unsigned int) R_PPC_max); cache_ptr->howto = ppc_elf_howto_table[ELF32_R_TYPE (dst->r_info)]; /* Just because the above assert didn't trigger doesn't mean that ELF32_R_TYPE (dst->r_info) is necessarily a valid relocation. */ if (!cache_ptr->howto) { (*_bfd_error_handler) (_("%B: invalid relocation type %d"), abfd, ELF32_R_TYPE (dst->r_info)); bfd_set_error (bfd_error_bad_value); cache_ptr->howto = ppc_elf_howto_table[R_PPC_NONE]; } } /* Handle the R_PPC_ADDR16_HA and R_PPC_REL16_HA relocs. */ static bfd_reloc_status_type ppc_elf_addr16_ha_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry, asymbol *symbol, void *data ATTRIBUTE_UNUSED, asection *input_section, bfd *output_bfd, char **error_message ATTRIBUTE_UNUSED) { bfd_vma relocation; if (output_bfd != NULL) { reloc_entry->address += input_section->output_offset; return bfd_reloc_ok; } if (reloc_entry->address > bfd_get_section_limit (abfd, input_section)) return bfd_reloc_outofrange; if (bfd_is_com_section (symbol->section)) relocation = 0; else relocation = symbol->value; relocation += symbol->section->output_section->vma; relocation += symbol->section->output_offset; relocation += reloc_entry->addend; if (reloc_entry->howto->pc_relative) relocation -= reloc_entry->address; reloc_entry->addend += (relocation & 0x8000) << 1; return bfd_reloc_continue; } static bfd_reloc_status_type ppc_elf_unhandled_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, void *data, asection *input_section, bfd *output_bfd, char **error_message) { /* If this is a relocatable link (output_bfd test tells us), just call the generic function. Any adjustment will be done at final link time. */ if (output_bfd != NULL) return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message); if (error_message != NULL) { static char buf[60]; sprintf (buf, _("generic linker can't handle %s"), reloc_entry->howto->name); *error_message = buf; } return bfd_reloc_dangerous; } /* Sections created by the linker. */ typedef struct elf_linker_section { /* Pointer to the bfd section. */ asection *section; /* Section name. */ const char *name; /* Associated bss section name. */ const char *bss_name; /* Associated symbol name. */ const char *sym_name; /* Associated symbol. */ struct elf_link_hash_entry *sym; } elf_linker_section_t; /* Linked list of allocated pointer entries. This hangs off of the symbol lists, and provides allows us to return different pointers, based on different addend's. */ typedef struct elf_linker_section_pointers { /* next allocated pointer for this symbol */ struct elf_linker_section_pointers *next; /* offset of pointer from beginning of section */ bfd_vma offset; /* addend used */ bfd_vma addend; /* which linker section this is */ elf_linker_section_t *lsect; } elf_linker_section_pointers_t; struct ppc_elf_obj_tdata { struct elf_obj_tdata elf; /* A mapping from local symbols to offsets into the various linker sections added. This is index by the symbol index. */ elf_linker_section_pointers_t **linker_section_pointers; /* Flags used to auto-detect plt type. */ unsigned int makes_plt_call : 1; unsigned int has_rel16 : 1; }; #define ppc_elf_tdata(bfd) \ ((struct ppc_elf_obj_tdata *) (bfd)->tdata.any) #define elf_local_ptr_offsets(bfd) \ (ppc_elf_tdata (bfd)->linker_section_pointers) /* Override the generic function because we store some extras. */ static bfd_boolean ppc_elf_mkobject (bfd *abfd) { if (abfd->tdata.any == NULL) { bfd_size_type amt = sizeof (struct ppc_elf_obj_tdata); abfd->tdata.any = bfd_zalloc (abfd, amt); if (abfd->tdata.any == NULL) return FALSE; } return bfd_elf_mkobject (abfd); } /* Fix bad default arch selected for a 32 bit input bfd when the default is 64 bit. */ static bfd_boolean ppc_elf_object_p (bfd *abfd) { if (abfd->arch_info->the_default && abfd->arch_info->bits_per_word == 64) { Elf_Internal_Ehdr *i_ehdr = elf_elfheader (abfd); if (i_ehdr->e_ident[EI_CLASS] == ELFCLASS32) { /* Relies on arch after 64 bit default being 32 bit default. */ abfd->arch_info = abfd->arch_info->next; BFD_ASSERT (abfd->arch_info->bits_per_word == 32); } } return TRUE; } /* Function to set whether a module needs the -mrelocatable bit set. */ static bfd_boolean ppc_elf_set_private_flags (bfd *abfd, flagword flags) { BFD_ASSERT (!elf_flags_init (abfd) || elf_elfheader (abfd)->e_flags == flags); elf_elfheader (abfd)->e_flags = flags; elf_flags_init (abfd) = TRUE; return TRUE; } /* Support for core dump NOTE sections. */ static bfd_boolean ppc_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) { int offset; unsigned int size; switch (note->descsz) { default: return FALSE; case 268: /* Linux/PPC. */ /* pr_cursig */ elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12); /* pr_pid */ elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24); /* pr_reg */ offset = 72; size = 192; break; } /* Make a ".reg/999" section. */ return _bfd_elfcore_make_pseudosection (abfd, ".reg", size, note->descpos + offset); } static bfd_boolean ppc_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) { switch (note->descsz) { default: return FALSE; case 128: /* Linux/PPC elf_prpsinfo. */ elf_tdata (abfd)->core_program = _bfd_elfcore_strndup (abfd, note->descdata + 32, 16); elf_tdata (abfd)->core_command = _bfd_elfcore_strndup (abfd, note->descdata + 48, 80); } /* Note that for some reason, a spurious space is tacked onto the end of the args in some (at least one anyway) implementations, so strip it off if it exists. */ { char *command = elf_tdata (abfd)->core_command; int n = strlen (command); if (0 < n && command[n - 1] == ' ') command[n - 1] = '\0'; } return TRUE; } static char * ppc_elf_write_core_note (bfd *abfd, char *buf, int *bufsiz, int note_type, ...) { switch (note_type) { default: return NULL; case NT_PRPSINFO: { char data[128]; va_list ap; va_start (ap, note_type); memset (data, 0, 32); strncpy (data + 32, va_arg (ap, const char *), 16); strncpy (data + 48, va_arg (ap, const char *), 80); va_end (ap); return elfcore_write_note (abfd, buf, bufsiz, "CORE", note_type, data, sizeof (data)); } case NT_PRSTATUS: { char data[268]; va_list ap; long pid; int cursig; const void *greg; va_start (ap, note_type); memset (data, 0, 72); pid = va_arg (ap, long); bfd_put_32 (abfd, pid, data + 24); cursig = va_arg (ap, int); bfd_put_16 (abfd, cursig, data + 12); greg = va_arg (ap, const void *); memcpy (data + 72, greg, 192); memset (data + 264, 0, 4); va_end (ap); return elfcore_write_note (abfd, buf, bufsiz, "CORE", note_type, data, sizeof (data)); } } } /* Return address for Ith PLT stub in section PLT, for relocation REL or (bfd_vma) -1 if it should not be included. */ static bfd_vma ppc_elf_plt_sym_val (bfd_vma i ATTRIBUTE_UNUSED, const asection *plt ATTRIBUTE_UNUSED, const arelent *rel) { return rel->address; } /* Handle a PowerPC specific section when reading an object file. This is called when bfd_section_from_shdr finds a section with an unknown type. */ static bfd_boolean ppc_elf_section_from_shdr (bfd *abfd, Elf_Internal_Shdr *hdr, const char *name, int shindex) { asection *newsect; flagword flags; if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex)) return FALSE; newsect = hdr->bfd_section; flags = bfd_get_section_flags (abfd, newsect); if (hdr->sh_flags & SHF_EXCLUDE) flags |= SEC_EXCLUDE; if (hdr->sh_type == SHT_ORDERED) flags |= SEC_SORT_ENTRIES; bfd_set_section_flags (abfd, newsect, flags); return TRUE; } /* Set up any other section flags and such that may be necessary. */ static bfd_boolean ppc_elf_fake_sections (bfd *abfd ATTRIBUTE_UNUSED, Elf_Internal_Shdr *shdr, asection *asect) { if ((asect->flags & (SEC_GROUP | SEC_EXCLUDE)) == SEC_EXCLUDE) shdr->sh_flags |= SHF_EXCLUDE; if ((asect->flags & SEC_SORT_ENTRIES) != 0) shdr->sh_type = SHT_ORDERED; return TRUE; } /* If we have .sbss2 or .PPC.EMB.sbss0 output sections, we need to bump up the number of section headers. */ static int ppc_elf_additional_program_headers (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED) { asection *s; int ret = 0; s = bfd_get_section_by_name (abfd, ".sbss2"); if (s != NULL && (s->flags & SEC_ALLOC) != 0) ++ret; s = bfd_get_section_by_name (abfd, ".PPC.EMB.sbss0"); if (s != NULL && (s->flags & SEC_ALLOC) != 0) ++ret; return ret; } /* Add extra PPC sections -- Note, for now, make .sbss2 and .PPC.EMB.sbss0 a normal section, and not a bss section so that the linker doesn't crater when trying to make more than 2 sections. */ static const struct bfd_elf_special_section ppc_elf_special_sections[] = { { STRING_COMMA_LEN (".plt"), 0, SHT_NOBITS, SHF_ALLOC + SHF_EXECINSTR }, { STRING_COMMA_LEN (".sbss"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE }, { STRING_COMMA_LEN (".sbss2"), -2, SHT_PROGBITS, SHF_ALLOC }, { STRING_COMMA_LEN (".sdata"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, { STRING_COMMA_LEN (".sdata2"), -2, SHT_PROGBITS, SHF_ALLOC }, { STRING_COMMA_LEN (".tags"), 0, SHT_ORDERED, SHF_ALLOC }, { STRING_COMMA_LEN (".PPC.EMB.apuinfo"), 0, SHT_NOTE, 0 }, { STRING_COMMA_LEN (".PPC.EMB.sbss0"), 0, SHT_PROGBITS, SHF_ALLOC }, { STRING_COMMA_LEN (".PPC.EMB.sdata0"), 0, SHT_PROGBITS, SHF_ALLOC }, { NULL, 0, 0, 0, 0 } }; /* This is what we want for new plt/got. */ static struct bfd_elf_special_section ppc_alt_plt = { STRING_COMMA_LEN (".plt"), 0, SHT_PROGBITS, SHF_ALLOC }; static const struct bfd_elf_special_section * ppc_elf_get_sec_type_attr (bfd *abfd ATTRIBUTE_UNUSED, asection *sec) { const struct bfd_elf_special_section *ssect; /* See if this is one of the special sections. */ if (sec->name == NULL) return NULL; ssect = _bfd_elf_get_special_section (sec->name, ppc_elf_special_sections, sec->use_rela_p); if (ssect != NULL) { if (ssect == ppc_elf_special_sections && (sec->flags & SEC_LOAD) != 0) ssect = &ppc_alt_plt; return ssect; } return _bfd_elf_get_sec_type_attr (abfd, sec); } /* Very simple linked list structure for recording apuinfo values. */ typedef struct apuinfo_list { struct apuinfo_list *next; unsigned long value; } apuinfo_list; static apuinfo_list *head; static void apuinfo_list_init (void) { head = NULL; } static void apuinfo_list_add (unsigned long value) { apuinfo_list *entry = head; while (entry != NULL) { if (entry->value == value) return; entry = entry->next; } entry = bfd_malloc (sizeof (* entry)); if (entry == NULL) return; entry->value = value; entry->next = head; head = entry; } static unsigned apuinfo_list_length (void) { apuinfo_list *entry; unsigned long count; for (entry = head, count = 0; entry; entry = entry->next) ++ count; return count; } static inline unsigned long apuinfo_list_element (unsigned long number) { apuinfo_list * entry; for (entry = head; entry && number --; entry = entry->next) ; return entry ? entry->value : 0; } static void apuinfo_list_finish (void) { apuinfo_list *entry; for (entry = head; entry;) { apuinfo_list *next = entry->next; free (entry); entry = next; } head = NULL; } #define APUINFO_SECTION_NAME ".PPC.EMB.apuinfo" #define APUINFO_LABEL "APUinfo" /* Scan the input BFDs and create a linked list of the APUinfo values that will need to be emitted. */ static void ppc_elf_begin_write_processing (bfd *abfd, struct bfd_link_info *link_info) { bfd *ibfd; asection *asec; char *buffer; unsigned num_input_sections; bfd_size_type output_section_size; unsigned i; unsigned num_entries; unsigned long offset; unsigned long length; const char *error_message = NULL; if (link_info == NULL) return; /* Scan the input bfds, looking for apuinfo sections. */ num_input_sections = 0; output_section_size = 0; for (ibfd = link_info->input_bfds; ibfd; ibfd = ibfd->link_next) { asec = bfd_get_section_by_name (ibfd, APUINFO_SECTION_NAME); if (asec) { ++ num_input_sections; output_section_size += asec->size; } } /* We need at least one input sections in order to make merging worthwhile. */ if (num_input_sections < 1) return; /* Just make sure that the output section exists as well. */ asec = bfd_get_section_by_name (abfd, APUINFO_SECTION_NAME); if (asec == NULL) return; /* Allocate a buffer for the contents of the input sections. */ buffer = bfd_malloc (output_section_size); if (buffer == NULL) return; offset = 0; apuinfo_list_init (); /* Read in the input sections contents. */ for (ibfd = link_info->input_bfds; ibfd; ibfd = ibfd->link_next) { unsigned long datum; char *ptr; asec = bfd_get_section_by_name (ibfd, APUINFO_SECTION_NAME); if (asec == NULL) continue; length = asec->size; if (length < 24) { error_message = _("corrupt or empty %s section in %B"); goto fail; } if (bfd_seek (ibfd, asec->filepos, SEEK_SET) != 0 || (bfd_bread (buffer + offset, length, ibfd) != length)) { error_message = _("unable to read in %s section from %B"); goto fail; } /* Process the contents of the section. */ ptr = buffer + offset; error_message = _("corrupt %s section in %B"); /* Verify the contents of the header. Note - we have to extract the values this way in order to allow for a host whose endian-ness is different from the target. */ datum = bfd_get_32 (ibfd, ptr); if (datum != sizeof APUINFO_LABEL) goto fail; datum = bfd_get_32 (ibfd, ptr + 8); if (datum != 0x2) goto fail; if (strcmp (ptr + 12, APUINFO_LABEL) != 0) goto fail; /* Get the number of bytes used for apuinfo entries. */ datum = bfd_get_32 (ibfd, ptr + 4); if (datum + 20 != length) goto fail; /* Make sure that we do not run off the end of the section. */ if (offset + length > output_section_size) goto fail; /* Scan the apuinfo section, building a list of apuinfo numbers. */ for (i = 0; i < datum; i += 4) apuinfo_list_add (bfd_get_32 (ibfd, ptr + 20 + i)); /* Update the offset. */ offset += length; } error_message = NULL; /* Compute the size of the output section. */ num_entries = apuinfo_list_length (); output_section_size = 20 + num_entries * 4; asec = bfd_get_section_by_name (abfd, APUINFO_SECTION_NAME); if (! bfd_set_section_size (abfd, asec, output_section_size)) ibfd = abfd, error_message = _("warning: unable to set size of %s section in %B"); fail: free (buffer); if (error_message) (*_bfd_error_handler) (error_message, ibfd, APUINFO_SECTION_NAME); } /* Prevent the output section from accumulating the input sections' contents. We have already stored this in our linked list structure. */ static bfd_boolean ppc_elf_write_section (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *link_info ATTRIBUTE_UNUSED, asection *asec, bfd_byte *contents ATTRIBUTE_UNUSED) { return (apuinfo_list_length () && strcmp (asec->name, APUINFO_SECTION_NAME) == 0); } /* Finally we can generate the output section. */ static void ppc_elf_final_write_processing (bfd *abfd, bfd_boolean linker ATTRIBUTE_UNUSED) { bfd_byte *buffer; asection *asec; unsigned i; unsigned num_entries; bfd_size_type length; asec = bfd_get_section_by_name (abfd, APUINFO_SECTION_NAME); if (asec == NULL) return; if (apuinfo_list_length () == 0) return; length = asec->size; if (length < 20) return; buffer = bfd_malloc (length); if (buffer == NULL) { (*_bfd_error_handler) (_("failed to allocate space for new APUinfo section.")); return; } /* Create the apuinfo header. */ num_entries = apuinfo_list_length (); bfd_put_32 (abfd, sizeof APUINFO_LABEL, buffer); bfd_put_32 (abfd, num_entries * 4, buffer + 4); bfd_put_32 (abfd, 0x2, buffer + 8); strcpy ((char *) buffer + 12, APUINFO_LABEL); length = 20; for (i = 0; i < num_entries; i++) { bfd_put_32 (abfd, apuinfo_list_element (i), buffer + length); length += 4; } if (length != asec->size) (*_bfd_error_handler) (_("failed to compute new APUinfo section.")); if (! bfd_set_section_contents (abfd, asec, buffer, (file_ptr) 0, length)) (*_bfd_error_handler) (_("failed to install new APUinfo section.")); free (buffer); apuinfo_list_finish (); } /* The following functions are specific to the ELF linker, while functions above are used generally. They appear in this file more or less in the order in which they are called. eg. ppc_elf_check_relocs is called early in the link process, ppc_elf_finish_dynamic_sections is one of the last functions called. */ /* The PPC linker needs to keep track of the number of relocs that it decides to copy as dynamic relocs in check_relocs for each symbol. This is so that it can later discard them if they are found to be unnecessary. We store the information in a field extending the regular ELF linker hash table. */ struct ppc_elf_dyn_relocs { struct ppc_elf_dyn_relocs *next; /* The input section of the reloc. */ asection *sec; /* Total number of relocs copied for the input section. */ bfd_size_type count; /* Number of pc-relative relocs copied for the input section. */ bfd_size_type pc_count; }; /* Track PLT entries needed for a given symbol. We might need more than one glink entry per symbol. */ struct plt_entry { struct plt_entry *next; /* -fPIC uses multiple GOT sections, one per file, called ".got2". This field stores the offset into .got2 used to initialise the GOT pointer reg. It will always be at least 32768 (and for current gcc this is the only offset used). */ bfd_vma addend; /* The .got2 section. */ asection *sec; /* PLT refcount or offset. */ union { bfd_signed_vma refcount; bfd_vma offset; } plt; /* .glink stub offset. */ bfd_vma glink_offset; }; -/* Of those relocs that might be copied as dynamic relocs, this macro +/* Of those relocs that might be copied as dynamic relocs, this function selects those that must be copied when linking a shared library, even when the symbol is local. */ -#define MUST_BE_DYN_RELOC(RTYPE) \ - ((RTYPE) != R_PPC_REL24 \ - && (RTYPE) != R_PPC_REL14 \ - && (RTYPE) != R_PPC_REL14_BRTAKEN \ - && (RTYPE) != R_PPC_REL14_BRNTAKEN \ - && (RTYPE) != R_PPC_REL32) +static int +must_be_dyn_reloc (struct bfd_link_info *info, + enum elf_ppc_reloc_type r_type) +{ + switch (r_type) + { + default: + return 1; + case R_PPC_REL24: + case R_PPC_REL14: + case R_PPC_REL14_BRTAKEN: + case R_PPC_REL14_BRNTAKEN: + case R_PPC_REL32: + return 0; + + case R_PPC_TPREL32: + case R_PPC_TPREL16: + case R_PPC_TPREL16_LO: + case R_PPC_TPREL16_HI: + case R_PPC_TPREL16_HA: + return !info->executable; + } +} + /* If ELIMINATE_COPY_RELOCS is non-zero, the linker will try to avoid copying dynamic variables from a shared lib into an app's dynbss section, and instead use a dynamic relocation to point into the shared lib. */ #define ELIMINATE_COPY_RELOCS 1 /* PPC ELF linker hash entry. */ struct ppc_elf_link_hash_entry { struct elf_link_hash_entry elf; /* If this symbol is used in the linker created sections, the processor specific backend uses this field to map the field into the offset from the beginning of the section. */ elf_linker_section_pointers_t *linker_section_pointer; /* Track dynamic relocs copied for this symbol. */ struct ppc_elf_dyn_relocs *dyn_relocs; /* Contexts in which symbol is used in the GOT (or TOC). TLS_GD .. TLS_TLS bits are or'd into the mask as the corresponding relocs are encountered during check_relocs. tls_optimize clears TLS_GD .. TLS_TPREL when optimizing to indicate the corresponding GOT entry type is not needed. */ #define TLS_GD 1 /* GD reloc. */ #define TLS_LD 2 /* LD reloc. */ #define TLS_TPREL 4 /* TPREL reloc, => IE. */ #define TLS_DTPREL 8 /* DTPREL reloc, => LD. */ #define TLS_TLS 16 /* Any TLS reloc. */ #define TLS_TPRELGD 32 /* TPREL reloc resulting from GD->IE. */ char tls_mask; /* Nonzero if we have seen a small data relocation referring to this symbol. */ unsigned char has_sda_refs; }; #define ppc_elf_hash_entry(ent) ((struct ppc_elf_link_hash_entry *) (ent)) /* PPC ELF linker hash table. */ struct ppc_elf_link_hash_table { struct elf_link_hash_table elf; /* Short-cuts to get to dynamic linker sections. */ asection *got; asection *relgot; asection *glink; asection *plt; asection *relplt; asection *dynbss; asection *relbss; asection *dynsbss; asection *relsbss; elf_linker_section_t sdata[2]; asection *sbss; /* The (unloaded but important) .rela.plt.unloaded on VxWorks. */ asection *srelplt2; /* The .got.plt section (VxWorks only)*/ asection *sgotplt; - /* Shortcut to .__tls_get_addr. */ + /* Shortcut to __tls_get_addr. */ struct elf_link_hash_entry *tls_get_addr; /* The bfd that forced an old-style PLT. */ bfd *old_bfd; /* TLS local dynamic got entry handling. */ union { bfd_signed_vma refcount; bfd_vma offset; } tlsld_got; /* Offset of PltResolve function in glink. */ bfd_vma glink_pltresolve; /* Size of reserved GOT entries. */ unsigned int got_header_size; /* Non-zero if allocating the header left a gap. */ unsigned int got_gap; /* The type of PLT we have chosen to use. */ enum ppc_elf_plt_type plt_type; /* Set if we should emit symbols for stubs. */ unsigned int emit_stub_syms:1; /* True if the target system is VxWorks. */ unsigned int is_vxworks:1; /* The size of PLT entries. */ int plt_entry_size; /* The distance between adjacent PLT slots. */ int plt_slot_size; /* The size of the first PLT entry. */ int plt_initial_entry_size; /* Small local sym to section mapping cache. */ struct sym_sec_cache sym_sec; }; /* Get the PPC ELF linker hash table from a link_info structure. */ #define ppc_elf_hash_table(p) \ ((struct ppc_elf_link_hash_table *) (p)->hash) /* Create an entry in a PPC ELF linker hash table. */ static struct bfd_hash_entry * ppc_elf_link_hash_newfunc (struct bfd_hash_entry *entry, struct bfd_hash_table *table, const char *string) { /* Allocate the structure if it has not already been allocated by a subclass. */ if (entry == NULL) { entry = bfd_hash_allocate (table, sizeof (struct ppc_elf_link_hash_entry)); if (entry == NULL) return entry; } /* Call the allocation method of the superclass. */ entry = _bfd_elf_link_hash_newfunc (entry, table, string); if (entry != NULL) { ppc_elf_hash_entry (entry)->linker_section_pointer = NULL; ppc_elf_hash_entry (entry)->dyn_relocs = NULL; ppc_elf_hash_entry (entry)->tls_mask = 0; } return entry; } /* Create a PPC ELF linker hash table. */ static struct bfd_link_hash_table * ppc_elf_link_hash_table_create (bfd *abfd) { struct ppc_elf_link_hash_table *ret; ret = bfd_zmalloc (sizeof (struct ppc_elf_link_hash_table)); if (ret == NULL) return NULL; 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; } ret->elf.init_plt_refcount.refcount = 0; ret->elf.init_plt_refcount.glist = NULL; ret->elf.init_plt_offset.offset = 0; ret->elf.init_plt_offset.glist = NULL; ret->sdata[0].name = ".sdata"; ret->sdata[0].sym_name = "_SDA_BASE_"; ret->sdata[0].bss_name = ".sbss"; ret->sdata[1].name = ".sdata2"; ret->sdata[1].sym_name = "_SDA2_BASE_"; ret->sdata[1].bss_name = ".sbss2"; ret->plt_entry_size = 12; ret->plt_slot_size = 8; ret->plt_initial_entry_size = 72; return &ret->elf.root; } /* Create .got and the related sections. */ static bfd_boolean ppc_elf_create_got (bfd *abfd, struct bfd_link_info *info) { struct ppc_elf_link_hash_table *htab; asection *s; flagword flags; if (!_bfd_elf_create_got_section (abfd, info)) return FALSE; htab = ppc_elf_hash_table (info); htab->got = s = bfd_get_section_by_name (abfd, ".got"); if (s == NULL) abort (); if (htab->is_vxworks) { htab->sgotplt = bfd_get_section_by_name (abfd, ".got.plt"); if (!htab->sgotplt) abort (); } else { /* The powerpc .got has a blrl instruction in it. Mark it executable. */ flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); if (!bfd_set_section_flags (abfd, s, flags)) return FALSE; } flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED | SEC_READONLY); htab->relgot = bfd_make_section_with_flags (abfd, ".rela.got", flags); if (!htab->relgot || ! bfd_set_section_alignment (abfd, htab->relgot, 2)) return FALSE; return TRUE; } /* We have to create .dynsbss and .rela.sbss here so that they get mapped to output sections (just like _bfd_elf_create_dynamic_sections has to create .dynbss and .rela.bss). */ static bfd_boolean ppc_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) { struct ppc_elf_link_hash_table *htab; asection *s; flagword flags; htab = ppc_elf_hash_table (info); if (htab->got == NULL && !ppc_elf_create_got (abfd, info)) return FALSE; if (!_bfd_elf_create_dynamic_sections (abfd, info)) return FALSE; flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); s = bfd_make_section_anyway_with_flags (abfd, ".glink", flags | SEC_CODE); htab->glink = s; if (s == NULL || !bfd_set_section_alignment (abfd, s, 4)) return FALSE; htab->dynbss = bfd_get_section_by_name (abfd, ".dynbss"); s = bfd_make_section_with_flags (abfd, ".dynsbss", SEC_ALLOC | SEC_LINKER_CREATED); htab->dynsbss = s; if (s == NULL) return FALSE; if (! info->shared) { htab->relbss = bfd_get_section_by_name (abfd, ".rela.bss"); s = bfd_make_section_with_flags (abfd, ".rela.sbss", flags); htab->relsbss = s; if (s == NULL || ! bfd_set_section_alignment (abfd, s, 2)) return FALSE; } if (htab->is_vxworks && !elf_vxworks_create_dynamic_sections (abfd, info, &htab->srelplt2)) return FALSE; htab->relplt = bfd_get_section_by_name (abfd, ".rela.plt"); htab->plt = s = bfd_get_section_by_name (abfd, ".plt"); if (s == NULL) abort (); flags = SEC_ALLOC | SEC_CODE | SEC_LINKER_CREATED; if (htab->plt_type == PLT_VXWORKS) /* The VxWorks PLT is a loaded section with contents. */ flags |= SEC_HAS_CONTENTS | SEC_LOAD | SEC_READONLY; return bfd_set_section_flags (abfd, s, flags); } /* Copy the extra info we tack onto an elf_link_hash_entry. */ static void ppc_elf_copy_indirect_symbol (struct bfd_link_info *info, struct elf_link_hash_entry *dir, struct elf_link_hash_entry *ind) { struct ppc_elf_link_hash_entry *edir, *eind; edir = (struct ppc_elf_link_hash_entry *) dir; eind = (struct ppc_elf_link_hash_entry *) ind; if (eind->dyn_relocs != NULL) { if (edir->dyn_relocs != NULL) { struct ppc_elf_dyn_relocs **pp; struct ppc_elf_dyn_relocs *p; /* Add reloc counts against the indirect sym to the direct sym list. Merge any entries against the same section. */ for (pp = &eind->dyn_relocs; (p = *pp) != NULL; ) { struct ppc_elf_dyn_relocs *q; for (q = edir->dyn_relocs; q != NULL; q = q->next) if (q->sec == p->sec) { q->pc_count += p->pc_count; q->count += p->count; *pp = p->next; break; } if (q == NULL) pp = &p->next; } *pp = edir->dyn_relocs; } edir->dyn_relocs = eind->dyn_relocs; eind->dyn_relocs = NULL; } edir->tls_mask |= eind->tls_mask; edir->has_sda_refs |= eind->has_sda_refs; /* If called to transfer flags for a weakdef during processing of elf_adjust_dynamic_symbol, don't copy non_got_ref. We clear it ourselves for ELIMINATE_COPY_RELOCS. */ if (!(ELIMINATE_COPY_RELOCS && eind->elf.root.type != bfd_link_hash_indirect && edir->elf.dynamic_adjusted)) edir->elf.non_got_ref |= eind->elf.non_got_ref; edir->elf.ref_dynamic |= eind->elf.ref_dynamic; edir->elf.ref_regular |= eind->elf.ref_regular; edir->elf.ref_regular_nonweak |= eind->elf.ref_regular_nonweak; edir->elf.needs_plt |= eind->elf.needs_plt; /* If we were called to copy over info for a weak sym, that's all. */ if (eind->elf.root.type != bfd_link_hash_indirect) return; /* Copy over the GOT refcount entries that we may have already seen to the symbol which just became indirect. */ edir->elf.got.refcount += eind->elf.got.refcount; eind->elf.got.refcount = 0; /* And plt entries. */ if (eind->elf.plt.plist != NULL) { if (edir->elf.plt.plist != NULL) { struct plt_entry **entp; struct plt_entry *ent; for (entp = &eind->elf.plt.plist; (ent = *entp) != NULL; ) { struct plt_entry *dent; for (dent = edir->elf.plt.plist; dent != NULL; dent = dent->next) if (dent->sec == ent->sec && dent->addend == ent->addend) { dent->plt.refcount += ent->plt.refcount; *entp = ent->next; break; } if (dent == NULL) entp = &ent->next; } *entp = edir->elf.plt.plist; } edir->elf.plt.plist = eind->elf.plt.plist; eind->elf.plt.plist = NULL; } if (eind->elf.dynindx != -1) { if (edir->elf.dynindx != -1) _bfd_elf_strtab_delref (elf_hash_table (info)->dynstr, edir->elf.dynstr_index); edir->elf.dynindx = eind->elf.dynindx; edir->elf.dynstr_index = eind->elf.dynstr_index; eind->elf.dynindx = -1; eind->elf.dynstr_index = 0; } } /* Return 1 if target is one of ours. */ static bfd_boolean is_ppc_elf_target (const struct bfd_target *targ) { extern const bfd_target bfd_elf32_powerpc_vec; extern const bfd_target bfd_elf32_powerpc_vxworks_vec; extern const bfd_target bfd_elf32_powerpcle_vec; return (targ == &bfd_elf32_powerpc_vec || targ == &bfd_elf32_powerpc_vxworks_vec || targ == &bfd_elf32_powerpcle_vec); } /* Hook called by the linker routine which adds symbols from an object file. We use it to put .comm items in .sbss, and not .bss. */ static bfd_boolean ppc_elf_add_symbol_hook (bfd *abfd, struct bfd_link_info *info, Elf_Internal_Sym *sym, const char **namep ATTRIBUTE_UNUSED, flagword *flagsp ATTRIBUTE_UNUSED, asection **secp, bfd_vma *valp) { if (sym->st_shndx == SHN_COMMON && !info->relocatable && sym->st_size <= elf_gp_size (abfd) && is_ppc_elf_target (info->hash->creator)) { /* Common symbols less than or equal to -G nn bytes are automatically put into .sbss. */ struct ppc_elf_link_hash_table *htab; htab = ppc_elf_hash_table (info); if (htab->sbss == NULL) { flagword flags = SEC_IS_COMMON | SEC_LINKER_CREATED; if (!htab->elf.dynobj) htab->elf.dynobj = abfd; htab->sbss = bfd_make_section_anyway_with_flags (htab->elf.dynobj, ".sbss", flags); if (htab->sbss == NULL) return FALSE; } *secp = htab->sbss; *valp = sym->st_size; } return TRUE; } static bfd_boolean create_sdata_sym (struct ppc_elf_link_hash_table *htab, elf_linker_section_t *lsect) { lsect->sym = elf_link_hash_lookup (&htab->elf, lsect->sym_name, TRUE, FALSE, TRUE); if (lsect->sym == NULL) return FALSE; if (lsect->sym->root.type == bfd_link_hash_new) lsect->sym->non_elf = 0; lsect->sym->ref_regular = 1; return TRUE; } /* Create a special linker section. */ static bfd_boolean ppc_elf_create_linker_section (bfd *abfd, struct bfd_link_info *info, flagword flags, elf_linker_section_t *lsect) { struct ppc_elf_link_hash_table *htab = ppc_elf_hash_table (info); asection *s; flags |= (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); /* Record the first bfd that needs the special sections. */ if (!htab->elf.dynobj) htab->elf.dynobj = abfd; s = bfd_make_section_anyway_with_flags (htab->elf.dynobj, lsect->name, flags); if (s == NULL || !bfd_set_section_alignment (htab->elf.dynobj, s, 2)) return FALSE; lsect->section = s; return create_sdata_sym (htab, lsect); } /* Find a linker generated pointer with a given addend and type. */ static elf_linker_section_pointers_t * elf_find_pointer_linker_section (elf_linker_section_pointers_t *linker_pointers, bfd_vma addend, elf_linker_section_t *lsect) { for ( ; linker_pointers != NULL; linker_pointers = linker_pointers->next) if (lsect == linker_pointers->lsect && addend == linker_pointers->addend) return linker_pointers; return NULL; } /* Allocate a pointer to live in a linker created section. */ static bfd_boolean elf_create_pointer_linker_section (bfd *abfd, elf_linker_section_t *lsect, struct elf_link_hash_entry *h, const Elf_Internal_Rela *rel) { elf_linker_section_pointers_t **ptr_linker_section_ptr = NULL; elf_linker_section_pointers_t *linker_section_ptr; unsigned long r_symndx = ELF32_R_SYM (rel->r_info); bfd_size_type amt; BFD_ASSERT (lsect != NULL); /* Is this a global symbol? */ if (h != NULL) { struct ppc_elf_link_hash_entry *eh; /* Has this symbol already been allocated? If so, our work is done. */ eh = (struct ppc_elf_link_hash_entry *) h; if (elf_find_pointer_linker_section (eh->linker_section_pointer, rel->r_addend, lsect)) return TRUE; ptr_linker_section_ptr = &eh->linker_section_pointer; } else { /* Allocation of a pointer to a local symbol. */ elf_linker_section_pointers_t **ptr = elf_local_ptr_offsets (abfd); /* Allocate a table to hold the local symbols if first time. */ if (!ptr) { unsigned int num_symbols = elf_tdata (abfd)->symtab_hdr.sh_info; amt = num_symbols; amt *= sizeof (elf_linker_section_pointers_t *); ptr = bfd_zalloc (abfd, amt); if (!ptr) return FALSE; elf_local_ptr_offsets (abfd) = ptr; } /* Has this symbol already been allocated? If so, our work is done. */ if (elf_find_pointer_linker_section (ptr[r_symndx], rel->r_addend, lsect)) return TRUE; ptr_linker_section_ptr = &ptr[r_symndx]; } /* Allocate space for a pointer in the linker section, and allocate a new pointer record from internal memory. */ BFD_ASSERT (ptr_linker_section_ptr != NULL); amt = sizeof (elf_linker_section_pointers_t); linker_section_ptr = bfd_alloc (abfd, amt); if (!linker_section_ptr) return FALSE; linker_section_ptr->next = *ptr_linker_section_ptr; linker_section_ptr->addend = rel->r_addend; linker_section_ptr->lsect = lsect; *ptr_linker_section_ptr = linker_section_ptr; linker_section_ptr->offset = lsect->section->size; lsect->section->size += 4; #ifdef DEBUG fprintf (stderr, "Create pointer in linker section %s, offset = %ld, section size = %ld\n", lsect->name, (long) linker_section_ptr->offset, (long) lsect->section->size); #endif return TRUE; } static bfd_boolean update_local_sym_info (bfd *abfd, Elf_Internal_Shdr *symtab_hdr, unsigned long r_symndx, int tls_type) { bfd_signed_vma *local_got_refcounts = elf_local_got_refcounts (abfd); char *local_got_tls_masks; if (local_got_refcounts == NULL) { bfd_size_type size = symtab_hdr->sh_info; size *= sizeof (*local_got_refcounts) + sizeof (*local_got_tls_masks); local_got_refcounts = bfd_zalloc (abfd, size); if (local_got_refcounts == NULL) return FALSE; elf_local_got_refcounts (abfd) = local_got_refcounts; } local_got_refcounts[r_symndx] += 1; local_got_tls_masks = (char *) (local_got_refcounts + symtab_hdr->sh_info); local_got_tls_masks[r_symndx] |= tls_type; return TRUE; } static bfd_boolean update_plt_info (bfd *abfd, struct elf_link_hash_entry *h, asection *sec, bfd_vma addend) { struct plt_entry *ent; if (addend < 32768) sec = NULL; for (ent = h->plt.plist; ent != NULL; ent = ent->next) if (ent->sec == sec && ent->addend == addend) break; if (ent == NULL) { bfd_size_type amt = sizeof (*ent); ent = bfd_alloc (abfd, amt); if (ent == NULL) return FALSE; ent->next = h->plt.plist; ent->sec = sec; ent->addend = addend; ent->plt.refcount = 0; h->plt.plist = ent; } ent->plt.refcount += 1; return TRUE; } static struct plt_entry * find_plt_ent (struct elf_link_hash_entry *h, asection *sec, bfd_vma addend) { struct plt_entry *ent; if (addend < 32768) sec = NULL; for (ent = h->plt.plist; ent != NULL; ent = ent->next) if (ent->sec == sec && ent->addend == addend) break; return ent; } static void bad_shared_reloc (bfd *abfd, enum elf_ppc_reloc_type r_type) { (*_bfd_error_handler) (_("%B: relocation %s cannot be used when making a shared object"), abfd, ppc_elf_howto_table[r_type]->name); bfd_set_error (bfd_error_bad_value); } /* Look through the relocs for a section during the first phase, and allocate space in the global offset table or procedure linkage table. */ static bfd_boolean ppc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec, const Elf_Internal_Rela *relocs) { struct ppc_elf_link_hash_table *htab; Elf_Internal_Shdr *symtab_hdr; struct elf_link_hash_entry **sym_hashes; const Elf_Internal_Rela *rel; const Elf_Internal_Rela *rel_end; asection *got2, *sreloc; + struct elf_link_hash_entry *tga; if (info->relocatable) return TRUE; /* Don't do anything special with non-loaded, non-alloced sections. In particular, any relocs in such sections should not affect GOT and PLT reference counting (ie. we don't allow them to create GOT or PLT entries), there's no possibility or desire to optimize TLS relocs, and there's not much point in propagating relocs to shared libs that the dynamic linker won't relocate. */ if ((sec->flags & SEC_ALLOC) == 0) return TRUE; #ifdef DEBUG _bfd_error_handler ("ppc_elf_check_relocs called for section %A in %B", sec, abfd); #endif /* Initialize howto table if not already done. */ if (!ppc_elf_howto_table[R_PPC_ADDR32]) ppc_elf_howto_init (); htab = ppc_elf_hash_table (info); + tga = elf_link_hash_lookup (&htab->elf, "__tls_get_addr", + FALSE, FALSE, TRUE); symtab_hdr = &elf_tdata (abfd)->symtab_hdr; sym_hashes = elf_sym_hashes (abfd); got2 = bfd_get_section_by_name (abfd, ".got2"); sreloc = NULL; rel_end = relocs + sec->reloc_count; for (rel = relocs; rel < rel_end; rel++) { unsigned long r_symndx; enum elf_ppc_reloc_type r_type; struct elf_link_hash_entry *h; - int tls_type = 0; + int tls_type; 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]; 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 a relocation refers to _GLOBAL_OFFSET_TABLE_, create the .got. This shows up in particular in an R_PPC_ADDR32 in the eabi startup code. */ if (h != NULL && htab->got == NULL && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0) { if (htab->elf.dynobj == NULL) htab->elf.dynobj = abfd; if (!ppc_elf_create_got (htab->elf.dynobj, info)) return FALSE; BFD_ASSERT (h == htab->elf.hgot); } + tls_type = 0; r_type = ELF32_R_TYPE (rel->r_info); + if (h != NULL && h == tga) + switch (r_type) + { + default: + break; + + case R_PPC_PLTREL24: + case R_PPC_LOCAL24PC: + case R_PPC_REL24: + case R_PPC_REL14: + case R_PPC_REL14_BRTAKEN: + case R_PPC_REL14_BRNTAKEN: + case R_PPC_ADDR24: + case R_PPC_ADDR14: + case R_PPC_ADDR14_BRTAKEN: + case R_PPC_ADDR14_BRNTAKEN: + if (rel != relocs + && (ELF32_R_TYPE (rel[-1].r_info) == R_PPC_TLSGD + || ELF32_R_TYPE (rel[-1].r_info) == R_PPC_TLSLD)) + /* We have a new-style __tls_get_addr call with a marker + reloc. */ + ; + else + /* Mark this section as having an old-style call. */ + sec->has_tls_get_addr_call = 1; + break; + } + switch (r_type) { + case R_PPC_TLSGD: + case R_PPC_TLSLD: + /* These special tls relocs tie a call to __tls_get_addr with + its parameter symbol. */ + break; + case R_PPC_GOT_TLSLD16: case R_PPC_GOT_TLSLD16_LO: case R_PPC_GOT_TLSLD16_HI: case R_PPC_GOT_TLSLD16_HA: - htab->tlsld_got.refcount += 1; tls_type = TLS_TLS | TLS_LD; goto dogottls; case R_PPC_GOT_TLSGD16: case R_PPC_GOT_TLSGD16_LO: case R_PPC_GOT_TLSGD16_HI: case R_PPC_GOT_TLSGD16_HA: tls_type = TLS_TLS | TLS_GD; goto dogottls; case R_PPC_GOT_TPREL16: case R_PPC_GOT_TPREL16_LO: case R_PPC_GOT_TPREL16_HI: case R_PPC_GOT_TPREL16_HA: - if (info->shared) + if (!info->executable) info->flags |= DF_STATIC_TLS; tls_type = TLS_TLS | TLS_TPREL; goto dogottls; case R_PPC_GOT_DTPREL16: case R_PPC_GOT_DTPREL16_LO: case R_PPC_GOT_DTPREL16_HI: case R_PPC_GOT_DTPREL16_HA: tls_type = TLS_TLS | TLS_DTPREL; dogottls: sec->has_tls_reloc = 1; /* Fall thru */ /* GOT16 relocations */ case R_PPC_GOT16: case R_PPC_GOT16_LO: case R_PPC_GOT16_HI: case R_PPC_GOT16_HA: /* This symbol requires a global offset table entry. */ if (htab->got == NULL) { if (htab->elf.dynobj == NULL) htab->elf.dynobj = abfd; if (!ppc_elf_create_got (htab->elf.dynobj, info)) return FALSE; } if (h != NULL) { h->got.refcount += 1; ppc_elf_hash_entry (h)->tls_mask |= tls_type; } else /* This is a global offset table entry for a local symbol. */ if (!update_local_sym_info (abfd, symtab_hdr, r_symndx, tls_type)) return FALSE; break; /* Indirect .sdata relocation. */ case R_PPC_EMB_SDAI16: if (info->shared) { bad_shared_reloc (abfd, r_type); return FALSE; } if (htab->sdata[0].section == NULL && !ppc_elf_create_linker_section (abfd, info, 0, &htab->sdata[0])) return FALSE; if (!elf_create_pointer_linker_section (abfd, &htab->sdata[0], h, rel)) return FALSE; if (h != NULL) { ppc_elf_hash_entry (h)->has_sda_refs = TRUE; h->non_got_ref = TRUE; } break; /* Indirect .sdata2 relocation. */ case R_PPC_EMB_SDA2I16: if (info->shared) { bad_shared_reloc (abfd, r_type); return FALSE; } if (htab->sdata[1].section == NULL && !ppc_elf_create_linker_section (abfd, info, SEC_READONLY, &htab->sdata[1])) return FALSE; if (!elf_create_pointer_linker_section (abfd, &htab->sdata[1], h, rel)) return FALSE; if (h != NULL) { ppc_elf_hash_entry (h)->has_sda_refs = TRUE; h->non_got_ref = TRUE; } break; case R_PPC_SDAREL16: if (info->shared) { bad_shared_reloc (abfd, r_type); return FALSE; } if (htab->sdata[0].sym == NULL && !create_sdata_sym (htab, &htab->sdata[0])) return FALSE; if (h != NULL) { ppc_elf_hash_entry (h)->has_sda_refs = TRUE; h->non_got_ref = TRUE; } break; case R_PPC_EMB_SDA2REL: if (info->shared) { bad_shared_reloc (abfd, r_type); return FALSE; } if (htab->sdata[1].sym == NULL && !create_sdata_sym (htab, &htab->sdata[1])) return FALSE; if (h != NULL) { ppc_elf_hash_entry (h)->has_sda_refs = TRUE; h->non_got_ref = TRUE; } break; case R_PPC_EMB_SDA21: case R_PPC_EMB_RELSDA: if (info->shared) { bad_shared_reloc (abfd, r_type); return FALSE; } if (htab->sdata[0].sym == NULL && !create_sdata_sym (htab, &htab->sdata[0])) return FALSE; if (htab->sdata[1].sym == NULL && !create_sdata_sym (htab, &htab->sdata[1])) return FALSE; if (h != NULL) { ppc_elf_hash_entry (h)->has_sda_refs = TRUE; h->non_got_ref = TRUE; } break; case R_PPC_EMB_NADDR32: case R_PPC_EMB_NADDR16: case R_PPC_EMB_NADDR16_LO: case R_PPC_EMB_NADDR16_HI: case R_PPC_EMB_NADDR16_HA: if (info->shared) { bad_shared_reloc (abfd, r_type); return FALSE; } if (h != NULL) h->non_got_ref = TRUE; break; case R_PPC_PLT32: case R_PPC_PLTREL24: case R_PPC_PLTREL32: case R_PPC_PLT16_LO: case R_PPC_PLT16_HI: case R_PPC_PLT16_HA: #ifdef DEBUG fprintf (stderr, "Reloc requires a PLT entry\n"); #endif /* This symbol requires a procedure linkage table entry. We actually build the entry in finish_dynamic_symbol, because this might be a case of linking PIC code without linking in any dynamic objects, in which case we don't need to generate a procedure linkage table after all. */ if (h == NULL) { /* It does not make sense to have a procedure linkage table entry for a local symbol. */ (*_bfd_error_handler) (_("%B(%A+0x%lx): %s reloc against " "local symbol"), abfd, sec, (long) rel->r_offset, ppc_elf_howto_table[r_type]->name); bfd_set_error (bfd_error_bad_value); return FALSE; } else { bfd_vma addend = 0; if (r_type == R_PPC_PLTREL24) { ppc_elf_tdata (abfd)->makes_plt_call = 1; addend = rel->r_addend; } h->needs_plt = 1; if (!update_plt_info (abfd, h, got2, addend)) return FALSE; } break; /* The following relocations don't need to propagate the relocation if linking a shared object since they are section relative. */ case R_PPC_SECTOFF: case R_PPC_SECTOFF_LO: case R_PPC_SECTOFF_HI: case R_PPC_SECTOFF_HA: case R_PPC_DTPREL16: case R_PPC_DTPREL16_LO: case R_PPC_DTPREL16_HI: case R_PPC_DTPREL16_HA: case R_PPC_TOC16: break; case R_PPC_REL16: case R_PPC_REL16_LO: case R_PPC_REL16_HI: case R_PPC_REL16_HA: ppc_elf_tdata (abfd)->has_rel16 = 1; break; /* These are just markers. */ case R_PPC_TLS: case R_PPC_EMB_MRKREF: case R_PPC_NONE: case R_PPC_max: break; /* These should only appear in dynamic objects. */ case R_PPC_COPY: case R_PPC_GLOB_DAT: case R_PPC_JMP_SLOT: case R_PPC_RELATIVE: break; /* These aren't handled yet. We'll report an error later. */ case R_PPC_ADDR30: case R_PPC_EMB_RELSEC16: case R_PPC_EMB_RELST_LO: case R_PPC_EMB_RELST_HI: case R_PPC_EMB_RELST_HA: case R_PPC_EMB_BIT_FLD: break; /* This refers only to functions defined in the shared library. */ case R_PPC_LOCAL24PC: - if (h && h == htab->elf.hgot && htab->plt_type == PLT_UNSET) + if (h != NULL && h == htab->elf.hgot && htab->plt_type == PLT_UNSET) { htab->plt_type = PLT_OLD; htab->old_bfd = abfd; } break; /* This relocation describes the C++ object vtable hierarchy. Reconstruct it for later use during GC. */ case R_PPC_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_PPC_GNU_VTENTRY: if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) return FALSE; break; /* We shouldn't really be seeing these. */ case R_PPC_TPREL32: - if (info->shared) + case R_PPC_TPREL16: + case R_PPC_TPREL16_LO: + case R_PPC_TPREL16_HI: + case R_PPC_TPREL16_HA: + if (!info->executable) info->flags |= DF_STATIC_TLS; goto dodyn; /* Nor these. */ case R_PPC_DTPMOD32: case R_PPC_DTPREL32: goto dodyn; - case R_PPC_TPREL16: - case R_PPC_TPREL16_LO: - case R_PPC_TPREL16_HI: - case R_PPC_TPREL16_HA: - if (info->shared) - info->flags |= DF_STATIC_TLS; - goto dodyn; - case R_PPC_REL32: if (h == NULL && got2 != NULL && (sec->flags & SEC_CODE) != 0 && (info->shared || info->pie) && htab->plt_type == PLT_UNSET) { /* Old -fPIC gcc code has .long LCTOC1-LCFx just before the start of a function, which assembles to a REL32 reference to .got2. If we detect one of these, then force the old PLT layout because the linker cannot reliably deduce the GOT pointer value needed for PLT call stubs. */ asection *s; s = bfd_section_from_r_symndx (abfd, &htab->sym_sec, sec, r_symndx); if (s == got2) { htab->plt_type = PLT_OLD; htab->old_bfd = abfd; } } if (h == NULL || h == htab->elf.hgot) break; goto dodyn1; case R_PPC_REL24: case R_PPC_REL14: case R_PPC_REL14_BRTAKEN: case R_PPC_REL14_BRNTAKEN: if (h == NULL) break; if (h == htab->elf.hgot) { if (htab->plt_type == PLT_UNSET) { htab->plt_type = PLT_OLD; htab->old_bfd = abfd; } break; } /* fall through */ case R_PPC_ADDR32: case R_PPC_ADDR24: case R_PPC_ADDR16: case R_PPC_ADDR16_LO: case R_PPC_ADDR16_HI: case R_PPC_ADDR16_HA: case R_PPC_ADDR14: case R_PPC_ADDR14_BRTAKEN: 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 a function defined in a dynamic object. */ if (!update_plt_info (abfd, h, NULL, 0)) return FALSE; /* We may need a copy reloc too. */ h->non_got_ref = 1; } dodyn: /* If we are creating a shared library, and this is a reloc against a global symbol, or a non PC relative reloc against a local symbol, then we need to copy the reloc into the shared library. However, if we are linking with -Bsymbolic, we do not need to copy a reloc against a global symbol which is defined in an object we are including in the link (i.e., DEF_REGULAR is set). At this point we have not seen all the input files, so it is possible that DEF_REGULAR is not set now but will be set later (it is never cleared). In case of a weak definition, DEF_REGULAR may be cleared later by a strong definition in a shared library. We account for that possibility below by storing information in the dyn_relocs field of the hash table entry. A similar situation occurs when creating shared libraries and symbol visibility changes render the symbol local. If on the other hand, we are creating an executable, we may need to keep relocations for symbols satisfied by a dynamic library if we manage to avoid copy relocs for the symbol. */ if ((info->shared - && (MUST_BE_DYN_RELOC (r_type) + && (must_be_dyn_reloc (info, r_type) || (h != NULL && (! info->symbolic || h->root.type == bfd_link_hash_defweak || !h->def_regular)))) || (ELIMINATE_COPY_RELOCS && !info->shared && h != NULL && (h->root.type == bfd_link_hash_defweak || !h->def_regular))) { struct ppc_elf_dyn_relocs *p; struct ppc_elf_dyn_relocs **head; #ifdef DEBUG fprintf (stderr, "ppc_elf_check_relocs needs to " "create relocation for %s\n", (h && h->root.root.string ? h->root.root.string : "")); #endif if (sreloc == NULL) { const char *name; name = (bfd_elf_string_from_elf_section (abfd, elf_elfheader (abfd)->e_shstrndx, elf_section_data (sec)->rel_hdr.sh_name)); if (name == NULL) return FALSE; BFD_ASSERT (CONST_STRNEQ (name, ".rela") && strcmp (bfd_get_section_name (abfd, sec), name + 5) == 0); if (htab->elf.dynobj == NULL) htab->elf.dynobj = abfd; sreloc = bfd_get_section_by_name (htab->elf.dynobj, name); if (sreloc == NULL) { flagword flags; flags = (SEC_HAS_CONTENTS | SEC_READONLY | SEC_IN_MEMORY | SEC_LINKER_CREATED | SEC_ALLOC | SEC_LOAD); sreloc = bfd_make_section_with_flags (htab->elf.dynobj, name, flags); if (sreloc == NULL || ! bfd_set_section_alignment (htab->elf.dynobj, sreloc, 2)) return FALSE; } elf_section_data (sec)->sreloc = sreloc; } /* If this is a global symbol, we count the number of relocations we need for this symbol. */ if (h != NULL) { head = &ppc_elf_hash_entry (h)->dyn_relocs; } else { /* Track dynamic relocs needed for local syms too. We really need local syms available to do this easily. Oh well. */ asection *s; void *vpp; s = bfd_section_from_r_symndx (abfd, &htab->sym_sec, sec, r_symndx); if (s == NULL) return FALSE; vpp = &elf_section_data (s)->local_dynrel; head = (struct ppc_elf_dyn_relocs **) vpp; } p = *head; if (p == NULL || p->sec != sec) { p = bfd_alloc (htab->elf.dynobj, sizeof *p); if (p == NULL) return FALSE; p->next = *head; *head = p; p->sec = sec; p->count = 0; p->pc_count = 0; } p->count += 1; - if (!MUST_BE_DYN_RELOC (r_type)) + if (!must_be_dyn_reloc (info, r_type)) p->pc_count += 1; } break; } } return TRUE; } /* Merge object attributes from IBFD into OBFD. Raise an error if there are conflicting attributes. */ static bfd_boolean ppc_elf_merge_obj_attributes (bfd *ibfd, bfd *obfd) { obj_attribute *in_attr; obj_attribute *out_attr; if (!elf_known_obj_attributes_proc (obfd)[0].i) { /* This is the first object. Copy the attributes. */ _bfd_elf_copy_obj_attributes (ibfd, obfd); /* Use the Tag_null value to indicate the attributes have been initialized. */ elf_known_obj_attributes_proc (obfd)[0].i = 1; return TRUE; } /* Check for conflicting Tag_GNU_Power_ABI_FP attributes and merge non-conflicting ones. */ in_attr = elf_known_obj_attributes (ibfd)[OBJ_ATTR_GNU]; out_attr = elf_known_obj_attributes (obfd)[OBJ_ATTR_GNU]; if (in_attr[Tag_GNU_Power_ABI_FP].i != out_attr[Tag_GNU_Power_ABI_FP].i) { out_attr[Tag_GNU_Power_ABI_FP].type = 1; if (out_attr[Tag_GNU_Power_ABI_FP].i == 0) out_attr[Tag_GNU_Power_ABI_FP].i = in_attr[Tag_GNU_Power_ABI_FP].i; else if (in_attr[Tag_GNU_Power_ABI_FP].i == 0) ; else if (out_attr[Tag_GNU_Power_ABI_FP].i == 1 && in_attr[Tag_GNU_Power_ABI_FP].i == 2) _bfd_error_handler (_("Warning: %B uses hard float, %B uses soft float"), obfd, ibfd); else if (out_attr[Tag_GNU_Power_ABI_FP].i == 2 && in_attr[Tag_GNU_Power_ABI_FP].i == 1) _bfd_error_handler (_("Warning: %B uses hard float, %B uses soft float"), ibfd, obfd); else if (in_attr[Tag_GNU_Power_ABI_FP].i > 2) _bfd_error_handler (_("Warning: %B uses unknown floating point ABI %d"), ibfd, in_attr[Tag_GNU_Power_ABI_FP].i); else _bfd_error_handler (_("Warning: %B uses unknown floating point ABI %d"), obfd, out_attr[Tag_GNU_Power_ABI_FP].i); } /* Merge Tag_compatibility attributes and any common GNU ones. */ _bfd_elf_merge_object_attributes (ibfd, obfd); return TRUE; } /* Merge backend specific data from an object file to the output object file when linking. */ static bfd_boolean ppc_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd) { flagword old_flags; flagword new_flags; bfd_boolean error; if (!is_ppc_elf_target (ibfd->xvec) || !is_ppc_elf_target (obfd->xvec)) return TRUE; /* Check if we have the same endianess. */ if (! _bfd_generic_verify_endian_match (ibfd, obfd)) return FALSE; if (!ppc_elf_merge_obj_attributes (ibfd, obfd)) return FALSE; new_flags = elf_elfheader (ibfd)->e_flags; old_flags = elf_elfheader (obfd)->e_flags; if (!elf_flags_init (obfd)) { /* First call, no flags set. */ elf_flags_init (obfd) = TRUE; elf_elfheader (obfd)->e_flags = new_flags; } /* Compatible flags are ok. */ else if (new_flags == old_flags) ; /* Incompatible flags. */ else { /* Warn about -mrelocatable mismatch. Allow -mrelocatable-lib to be linked with either. */ error = FALSE; if ((new_flags & EF_PPC_RELOCATABLE) != 0 && (old_flags & (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB)) == 0) { error = TRUE; (*_bfd_error_handler) (_("%B: compiled with -mrelocatable and linked with " "modules compiled normally"), ibfd); } else if ((new_flags & (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB)) == 0 && (old_flags & EF_PPC_RELOCATABLE) != 0) { error = TRUE; (*_bfd_error_handler) (_("%B: compiled normally and linked with " "modules compiled with -mrelocatable"), ibfd); } /* The output is -mrelocatable-lib iff both the input files are. */ if (! (new_flags & EF_PPC_RELOCATABLE_LIB)) elf_elfheader (obfd)->e_flags &= ~EF_PPC_RELOCATABLE_LIB; /* The output is -mrelocatable iff it can't be -mrelocatable-lib, but each input file is either -mrelocatable or -mrelocatable-lib. */ if (! (elf_elfheader (obfd)->e_flags & EF_PPC_RELOCATABLE_LIB) && (new_flags & (EF_PPC_RELOCATABLE_LIB | EF_PPC_RELOCATABLE)) && (old_flags & (EF_PPC_RELOCATABLE_LIB | EF_PPC_RELOCATABLE))) elf_elfheader (obfd)->e_flags |= EF_PPC_RELOCATABLE; /* Do not warn about eabi vs. V.4 mismatch, just or in the bit if any module uses it. */ elf_elfheader (obfd)->e_flags |= (new_flags & EF_PPC_EMB); new_flags &= ~(EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB | EF_PPC_EMB); old_flags &= ~(EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB | EF_PPC_EMB); /* Warn about any other mismatches. */ if (new_flags != old_flags) { error = TRUE; (*_bfd_error_handler) (_("%B: uses different e_flags (0x%lx) fields " "than previous modules (0x%lx)"), ibfd, (long) new_flags, (long) old_flags); } if (error) { bfd_set_error (bfd_error_bad_value); return FALSE; } } return TRUE; } /* Choose which PLT scheme to use, and set .plt flags appropriately. Returns -1 on error, 0 for old PLT, 1 for new PLT. */ int ppc_elf_select_plt_layout (bfd *output_bfd ATTRIBUTE_UNUSED, struct bfd_link_info *info, enum ppc_elf_plt_type plt_style, int emit_stub_syms) { struct ppc_elf_link_hash_table *htab; flagword flags; htab = ppc_elf_hash_table (info); if (htab->plt_type == PLT_UNSET) { if (plt_style == PLT_OLD) htab->plt_type = PLT_OLD; else { bfd *ibfd; enum ppc_elf_plt_type plt_type = plt_style; /* Look through the reloc flags left by ppc_elf_check_relocs. Use the old style bss plt if a file makes plt calls without using the new relocs, and if ld isn't given --secure-plt and we never see REL16 relocs. */ if (plt_type == PLT_UNSET) plt_type = PLT_OLD; for (ibfd = info->input_bfds; ibfd; ibfd = ibfd->link_next) if (is_ppc_elf_target (ibfd->xvec)) { if (ppc_elf_tdata (ibfd)->has_rel16) plt_type = PLT_NEW; else if (ppc_elf_tdata (ibfd)->makes_plt_call) { plt_type = PLT_OLD; htab->old_bfd = ibfd; break; } } htab->plt_type = plt_type; } } if (htab->plt_type == PLT_OLD && plt_style == PLT_NEW) info->callbacks->info (_("Using bss-plt due to %B"), htab->old_bfd); htab->emit_stub_syms = emit_stub_syms; BFD_ASSERT (htab->plt_type != PLT_VXWORKS); if (htab->plt_type == PLT_NEW) { flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); /* The new PLT is a loaded section. */ if (htab->plt != NULL && !bfd_set_section_flags (htab->elf.dynobj, htab->plt, flags)) return -1; /* The new GOT is not executable. */ if (htab->got != NULL && !bfd_set_section_flags (htab->elf.dynobj, htab->got, flags)) return -1; } else { /* Stop an unused .glink section from affecting .text alignment. */ if (htab->glink != NULL && !bfd_set_section_alignment (htab->elf.dynobj, htab->glink, 0)) return -1; } return htab->plt_type == PLT_NEW; } /* Return the section that should be marked against GC for a given relocation. */ static asection * ppc_elf_gc_mark_hook (asection *sec, struct bfd_link_info *info, Elf_Internal_Rela *rel, struct elf_link_hash_entry *h, Elf_Internal_Sym *sym) { if (h != NULL) switch (ELF32_R_TYPE (rel->r_info)) { case R_PPC_GNU_VTINHERIT: case R_PPC_GNU_VTENTRY: return NULL; } return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); } /* Update the got, plt and dynamic reloc reference counts for the section being removed. */ static bfd_boolean ppc_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info, asection *sec, const Elf_Internal_Rela *relocs) { struct ppc_elf_link_hash_table *htab; Elf_Internal_Shdr *symtab_hdr; struct elf_link_hash_entry **sym_hashes; bfd_signed_vma *local_got_refcounts; const Elf_Internal_Rela *rel, *relend; asection *got2; if ((sec->flags & SEC_ALLOC) == 0) return TRUE; elf_section_data (sec)->local_dynrel = NULL; htab = ppc_elf_hash_table (info); symtab_hdr = &elf_tdata (abfd)->symtab_hdr; sym_hashes = elf_sym_hashes (abfd); local_got_refcounts = elf_local_got_refcounts (abfd); got2 = bfd_get_section_by_name (abfd, ".got2"); relend = relocs + sec->reloc_count; for (rel = relocs; rel < relend; rel++) { unsigned long r_symndx; enum elf_ppc_reloc_type r_type; struct elf_link_hash_entry *h = NULL; r_symndx = ELF32_R_SYM (rel->r_info); if (r_symndx >= symtab_hdr->sh_info) { struct ppc_elf_dyn_relocs **pp, *p; struct ppc_elf_link_hash_entry *eh; 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; eh = (struct ppc_elf_link_hash_entry *) h; for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) if (p->sec == sec) { /* Everything must go for SEC. */ *pp = p->next; break; } } r_type = ELF32_R_TYPE (rel->r_info); switch (r_type) { case R_PPC_GOT_TLSLD16: case R_PPC_GOT_TLSLD16_LO: case R_PPC_GOT_TLSLD16_HI: case R_PPC_GOT_TLSLD16_HA: - htab->tlsld_got.refcount -= 1; - /* Fall thru */ - case R_PPC_GOT_TLSGD16: case R_PPC_GOT_TLSGD16_LO: case R_PPC_GOT_TLSGD16_HI: case R_PPC_GOT_TLSGD16_HA: case R_PPC_GOT_TPREL16: case R_PPC_GOT_TPREL16_LO: case R_PPC_GOT_TPREL16_HI: case R_PPC_GOT_TPREL16_HA: case R_PPC_GOT_DTPREL16: case R_PPC_GOT_DTPREL16_LO: case R_PPC_GOT_DTPREL16_HI: case R_PPC_GOT_DTPREL16_HA: case R_PPC_GOT16: case R_PPC_GOT16_LO: case R_PPC_GOT16_HI: case R_PPC_GOT16_HA: if (h != NULL) { if (h->got.refcount > 0) h->got.refcount--; } else if (local_got_refcounts != NULL) { if (local_got_refcounts[r_symndx] > 0) local_got_refcounts[r_symndx]--; } break; case R_PPC_REL24: case R_PPC_REL14: case R_PPC_REL14_BRTAKEN: case R_PPC_REL14_BRNTAKEN: case R_PPC_REL32: if (h == NULL || h == htab->elf.hgot) break; /* Fall thru */ case R_PPC_ADDR32: case R_PPC_ADDR24: case R_PPC_ADDR16: case R_PPC_ADDR16_LO: case R_PPC_ADDR16_HI: case R_PPC_ADDR16_HA: case R_PPC_ADDR14: case R_PPC_ADDR14_BRTAKEN: case R_PPC_ADDR14_BRNTAKEN: case R_PPC_UADDR32: case R_PPC_UADDR16: if (info->shared) break; case R_PPC_PLT32: case R_PPC_PLTREL24: case R_PPC_PLTREL32: case R_PPC_PLT16_LO: case R_PPC_PLT16_HI: case R_PPC_PLT16_HA: if (h != NULL) { bfd_vma addend = r_type == R_PPC_PLTREL24 ? rel->r_addend : 0; struct plt_entry *ent = find_plt_ent (h, got2, addend); if (ent->plt.refcount > 0) ent->plt.refcount -= 1; } break; default: break; } } return TRUE; } -/* Set htab->tls_get_addr and call the generic ELF tls_setup function. */ +/* Set plt output section type, htab->tls_get_addr, and call the + generic ELF tls_setup function. */ asection * ppc_elf_tls_setup (bfd *obfd, struct bfd_link_info *info) { struct ppc_elf_link_hash_table *htab; htab = ppc_elf_hash_table (info); if (htab->plt_type == PLT_NEW && htab->plt != NULL && htab->plt->output_section != NULL) { elf_section_type (htab->plt->output_section) = SHT_PROGBITS; elf_section_flags (htab->plt->output_section) = SHF_ALLOC + SHF_WRITE; } htab->tls_get_addr = elf_link_hash_lookup (&htab->elf, "__tls_get_addr", FALSE, FALSE, TRUE); return _bfd_elf_tls_setup (obfd, info); } +/* Return TRUE iff REL is a branch reloc with a global symbol matching + HASH. */ + +static bfd_boolean +branch_reloc_hash_match (const bfd *ibfd, + const Elf_Internal_Rela *rel, + const struct elf_link_hash_entry *hash) +{ + Elf_Internal_Shdr *symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; + enum elf_ppc_reloc_type r_type = ELF32_R_TYPE (rel->r_info); + unsigned int r_symndx = ELF32_R_SYM (rel->r_info); + + if (r_symndx >= symtab_hdr->sh_info + && (r_type == R_PPC_PLTREL24 + || r_type == R_PPC_LOCAL24PC + || r_type == R_PPC_REL14 + || r_type == R_PPC_REL14_BRTAKEN + || r_type == R_PPC_REL14_BRNTAKEN + || r_type == R_PPC_REL24 + || r_type == R_PPC_ADDR24 + || r_type == R_PPC_ADDR14 + || r_type == R_PPC_ADDR14_BRTAKEN + || r_type == R_PPC_ADDR14_BRNTAKEN)) + { + struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (ibfd); + struct elf_link_hash_entry *h; + + h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + while (h->root.type == bfd_link_hash_indirect + || h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + if (h == hash) + return TRUE; + } + return FALSE; +} + /* Run through all the TLS relocs looking for optimization opportunities. */ bfd_boolean ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) { bfd *ibfd; asection *sec; struct ppc_elf_link_hash_table *htab; + int pass; - if (info->relocatable || info->shared) + if (info->relocatable || !info->executable) return TRUE; htab = ppc_elf_hash_table (info); - for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) - { - Elf_Internal_Sym *locsyms = NULL; - Elf_Internal_Shdr *symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; + /* Make two passes through the relocs. First time check that tls + relocs involved in setting up a tls_get_addr call are indeed + followed by such a call. If they are not, exclude them from + the optimizations done on the second pass. */ + for (pass = 0; pass < 2; ++pass) + for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) + { + Elf_Internal_Sym *locsyms = NULL; + Elf_Internal_Shdr *symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; - for (sec = ibfd->sections; sec != NULL; sec = sec->next) - if (sec->has_tls_reloc && !bfd_is_abs_section (sec->output_section)) - { - Elf_Internal_Rela *relstart, *rel, *relend; - int expecting_tls_get_addr; + for (sec = ibfd->sections; sec != NULL; sec = sec->next) + if (sec->has_tls_reloc && !bfd_is_abs_section (sec->output_section)) + { + Elf_Internal_Rela *relstart, *rel, *relend; - /* Read the relocations. */ - relstart = _bfd_elf_link_read_relocs (ibfd, sec, NULL, NULL, - info->keep_memory); - if (relstart == NULL) - return FALSE; + /* Read the relocations. */ + relstart = _bfd_elf_link_read_relocs (ibfd, sec, NULL, NULL, + info->keep_memory); + if (relstart == NULL) + return FALSE; - expecting_tls_get_addr = 0; - relend = relstart + sec->reloc_count; - for (rel = relstart; rel < relend; rel++) - { - enum elf_ppc_reloc_type r_type; - unsigned long r_symndx; - struct elf_link_hash_entry *h = NULL; - char *tls_mask; - char tls_set, tls_clear; - bfd_boolean is_local; + relend = relstart + sec->reloc_count; + for (rel = relstart; rel < relend; rel++) + { + enum elf_ppc_reloc_type r_type; + unsigned long r_symndx; + struct elf_link_hash_entry *h = NULL; + char *tls_mask; + char tls_set, tls_clear; + bfd_boolean is_local; + int expecting_tls_get_addr; + bfd_signed_vma *got_count; - r_symndx = ELF32_R_SYM (rel->r_info); - if (r_symndx >= symtab_hdr->sh_info) - { - struct elf_link_hash_entry **sym_hashes; + r_symndx = ELF32_R_SYM (rel->r_info); + if (r_symndx >= symtab_hdr->sh_info) + { + struct elf_link_hash_entry **sym_hashes; - sym_hashes = elf_sym_hashes (ibfd); - 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; - } + sym_hashes = elf_sym_hashes (ibfd); + 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; + } - is_local = FALSE; - if (h == NULL - || !h->def_dynamic) - is_local = TRUE; + expecting_tls_get_addr = 0; + is_local = FALSE; + if (h == NULL + || !h->def_dynamic) + is_local = TRUE; - r_type = ELF32_R_TYPE (rel->r_info); - switch (r_type) - { - case R_PPC_GOT_TLSLD16: - case R_PPC_GOT_TLSLD16_LO: - case R_PPC_GOT_TLSLD16_HI: - case R_PPC_GOT_TLSLD16_HA: - /* These relocs should never be against a symbol - defined in a shared lib. Leave them alone if - that turns out to be the case. */ - expecting_tls_get_addr = 0; - htab->tlsld_got.refcount -= 1; - if (!is_local) - continue; + r_type = ELF32_R_TYPE (rel->r_info); + switch (r_type) + { + case R_PPC_GOT_TLSLD16: + case R_PPC_GOT_TLSLD16_LO: + expecting_tls_get_addr = 1; + /* Fall thru */ - /* LD -> LE */ - tls_set = 0; - tls_clear = TLS_LD; - expecting_tls_get_addr = 1; - break; + case R_PPC_GOT_TLSLD16_HI: + case R_PPC_GOT_TLSLD16_HA: + /* These relocs should never be against a symbol + defined in a shared lib. Leave them alone if + that turns out to be the case. */ + if (!is_local) + continue; - case R_PPC_GOT_TLSGD16: - case R_PPC_GOT_TLSGD16_LO: - case R_PPC_GOT_TLSGD16_HI: - case R_PPC_GOT_TLSGD16_HA: - if (is_local) - /* GD -> LE */ + /* LD -> LE */ tls_set = 0; - else - /* GD -> IE */ - tls_set = TLS_TLS | TLS_TPRELGD; - tls_clear = TLS_GD; - expecting_tls_get_addr = 1; - break; + tls_clear = TLS_LD; + break; - case R_PPC_GOT_TPREL16: - case R_PPC_GOT_TPREL16_LO: - case R_PPC_GOT_TPREL16_HI: - case R_PPC_GOT_TPREL16_HA: - expecting_tls_get_addr = 0; - if (is_local) - { - /* IE -> LE */ + case R_PPC_GOT_TLSGD16: + case R_PPC_GOT_TLSGD16_LO: + expecting_tls_get_addr = 1; + /* Fall thru */ + + case R_PPC_GOT_TLSGD16_HI: + case R_PPC_GOT_TLSGD16_HA: + if (is_local) + /* GD -> LE */ tls_set = 0; - tls_clear = TLS_TPREL; - break; - } - else + else + /* GD -> IE */ + tls_set = TLS_TLS | TLS_TPRELGD; + tls_clear = TLS_GD; + break; + + case R_PPC_GOT_TPREL16: + case R_PPC_GOT_TPREL16_LO: + case R_PPC_GOT_TPREL16_HI: + case R_PPC_GOT_TPREL16_HA: + if (is_local) + { + /* IE -> LE */ + tls_set = 0; + tls_clear = TLS_TPREL; + break; + } + else + continue; + + default: continue; + } - case R_PPC_REL14: - case R_PPC_REL14_BRTAKEN: - case R_PPC_REL14_BRNTAKEN: - case R_PPC_REL24: - if (expecting_tls_get_addr - && h != NULL - && h == htab->tls_get_addr) - { - struct plt_entry *ent = find_plt_ent (h, NULL, 0); - if (ent != NULL && ent->plt.refcount > 0) - ent->plt.refcount -= 1; - } - expecting_tls_get_addr = 0; - continue; + if (pass == 0) + { + if (!expecting_tls_get_addr + || !sec->has_tls_get_addr_call) + continue; - default: - expecting_tls_get_addr = 0; - continue; - } + if (rel + 1 < relend + && branch_reloc_hash_match (ibfd, rel + 1, + htab->tls_get_addr)) + continue; - if (h != NULL) - { - if (tls_set == 0) - { - /* We managed to get rid of a got entry. */ - if (h->got.refcount > 0) - h->got.refcount -= 1; - } - tls_mask = &ppc_elf_hash_entry (h)->tls_mask; - } - else - { - Elf_Internal_Sym *sym; - bfd_signed_vma *lgot_refs; - char *lgot_masks; + /* Uh oh, we didn't find the expected call. We + could just mark this symbol to exclude it + from tls optimization but it's safer to skip + the entire section. */ + sec->has_tls_reloc = 0; + break; + } - if (locsyms == NULL) - { - locsyms = (Elf_Internal_Sym *) symtab_hdr->contents; - if (locsyms == NULL) - locsyms = bfd_elf_get_elf_syms (ibfd, symtab_hdr, - symtab_hdr->sh_info, - 0, NULL, NULL, NULL); - if (locsyms == NULL) - { - if (elf_section_data (sec)->relocs != relstart) - free (relstart); - return FALSE; - } - } - sym = locsyms + r_symndx; - lgot_refs = elf_local_got_refcounts (ibfd); - if (lgot_refs == NULL) - abort (); - if (tls_set == 0) - { - /* We managed to get rid of a got entry. */ - if (lgot_refs[r_symndx] > 0) - lgot_refs[r_symndx] -= 1; - } - lgot_masks = (char *) (lgot_refs + symtab_hdr->sh_info); - tls_mask = &lgot_masks[r_symndx]; - } + if (h != NULL) + { + tls_mask = &ppc_elf_hash_entry (h)->tls_mask; + got_count = &h->got.refcount; + } + else + { + Elf_Internal_Sym *sym; + bfd_signed_vma *lgot_refs; + char *lgot_masks; - *tls_mask |= tls_set; - *tls_mask &= ~tls_clear; - } + if (locsyms == NULL) + { + locsyms = (Elf_Internal_Sym *) symtab_hdr->contents; + if (locsyms == NULL) + locsyms = bfd_elf_get_elf_syms (ibfd, symtab_hdr, + symtab_hdr->sh_info, + 0, NULL, NULL, NULL); + if (locsyms == NULL) + { + if (elf_section_data (sec)->relocs != relstart) + free (relstart); + return FALSE; + } + } + sym = locsyms + r_symndx; + lgot_refs = elf_local_got_refcounts (ibfd); + if (lgot_refs == NULL) + abort (); + lgot_masks = (char *) (lgot_refs + symtab_hdr->sh_info); + tls_mask = &lgot_masks[r_symndx]; + got_count = &lgot_refs[r_symndx]; + } - if (elf_section_data (sec)->relocs != relstart) - free (relstart); - } + if (tls_set == 0) + { + /* We managed to get rid of a got entry. */ + if (*got_count > 0) + *got_count -= 1; + } - if (locsyms != NULL - && (symtab_hdr->contents != (unsigned char *) locsyms)) - { - if (!info->keep_memory) - free (locsyms); - else - symtab_hdr->contents = (unsigned char *) locsyms; - } - } + if (expecting_tls_get_addr) + { + struct plt_entry *ent; + + ent = find_plt_ent (htab->tls_get_addr, NULL, 0); + if (ent != NULL && ent->plt.refcount > 0) + ent->plt.refcount -= 1; + } + + *tls_mask |= tls_set; + *tls_mask &= ~tls_clear; + } + + if (elf_section_data (sec)->relocs != relstart) + free (relstart); + } + + if (locsyms != NULL + && (symtab_hdr->contents != (unsigned char *) locsyms)) + { + if (!info->keep_memory) + free (locsyms); + else + symtab_hdr->contents = (unsigned char *) locsyms; + } + } return TRUE; } /* Adjust a symbol defined by a dynamic object and referenced by a regular object. The current definition is in some section of the dynamic object, but we're not including those sections. We have to change the definition to something the rest of the link can understand. */ static bfd_boolean ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info, struct elf_link_hash_entry *h) { struct ppc_elf_link_hash_table *htab; asection *s; #ifdef DEBUG fprintf (stderr, "ppc_elf_adjust_dynamic_symbol called for %s\n", h->root.root.string); #endif /* Make sure we know what is going on here. */ htab = ppc_elf_hash_table (info); BFD_ASSERT (htab->elf.dynobj != NULL && (h->needs_plt || h->u.weakdef != NULL || (h->def_dynamic && h->ref_regular && !h->def_regular))); /* Deal with function syms. */ if (h->type == STT_FUNC || h->needs_plt) { /* Clear procedure linkage table information for any symbol that won't need a .plt entry. */ struct plt_entry *ent; for (ent = h->plt.plist; ent != NULL; ent = ent->next) if (ent->plt.refcount > 0) break; if (ent == NULL || SYMBOL_CALLS_LOCAL (info, h) || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT && h->root.type == bfd_link_hash_undefweak)) { /* A PLT entry is not required/allowed when: 1. We are not using ld.so; because then the PLT entry can't be set up, so we can't use one. In this case, ppc_elf_adjust_dynamic_symbol won't even be called. 2. GC has rendered the entry unused. 3. We know for certain that a call to this symbol will go to this object, or will remain undefined. */ h->plt.plist = NULL; h->needs_plt = 0; } return TRUE; } else h->plt.plist = NULL; /* 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; if (ELIMINATE_COPY_RELOCS) h->non_got_ref = h->u.weakdef->non_got_ref; return TRUE; } /* This is a reference to a symbol defined by a dynamic object which is not a function. */ /* If we are creating a shared library, we must presume that the only references to the symbol are via the global offset table. For such cases we need not do anything here; the relocations will be handled correctly by relocate_section. */ if (info->shared) return TRUE; /* If there are no references to this symbol that do not use the GOT, we don't need to generate a copy reloc. */ if (!h->non_got_ref) return TRUE; /* If we didn't find any dynamic relocs in read-only sections, then we'll be keeping the dynamic relocs and avoiding the copy reloc. We can't do this if there are any small data relocations. */ if (ELIMINATE_COPY_RELOCS && !ppc_elf_hash_entry (h)->has_sda_refs) { struct ppc_elf_dyn_relocs *p; for (p = ppc_elf_hash_entry (h)->dyn_relocs; p != NULL; p = p->next) { s = p->sec->output_section; if (s != NULL && (s->flags & SEC_READONLY) != 0) break; } if (p == NULL) { h->non_got_ref = 0; return TRUE; } } if (h->size == 0) { (*_bfd_error_handler) (_("dynamic variable `%s' is zero size"), h->root.root.string); 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. Of course, if the symbol is referenced using SDAREL relocs, we must instead allocate it in .sbss. */ if (ppc_elf_hash_entry (h)->has_sda_refs) s = htab->dynsbss; else s = htab->dynbss; BFD_ASSERT (s != NULL); /* We must generate a R_PPC_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 .rela.bss section we are going to use. */ if ((h->root.u.def.section->flags & SEC_ALLOC) != 0) { asection *srel; if (ppc_elf_hash_entry (h)->has_sda_refs) srel = htab->relsbss; else srel = htab->relbss; BFD_ASSERT (srel != NULL); srel->size += sizeof (Elf32_External_Rela); h->needs_copy = 1; } return _bfd_elf_adjust_dynamic_copy (h, s); } /* Generate a symbol to mark plt call stubs. For non-PIC code the sym is xxxxxxxx.plt_call32. where xxxxxxxx is a hex number, usually 0, specifying the addend on the plt relocation. For -fpic code, the sym is xxxxxxxx.plt_pic32., and for -fPIC xxxxxxxx.got2.plt_pic32.. */ static bfd_boolean add_stub_sym (struct plt_entry *ent, struct elf_link_hash_entry *h, struct bfd_link_info *info) { struct elf_link_hash_entry *sh; size_t len1, len2, len3; char *name; const char *stub; struct ppc_elf_link_hash_table *htab = ppc_elf_hash_table (info); if (info->shared || info->pie) stub = ".plt_pic32."; else stub = ".plt_call32."; len1 = strlen (h->root.root.string); len2 = strlen (stub); len3 = 0; if (ent->sec) len3 = strlen (ent->sec->name); name = bfd_malloc (len1 + len2 + len3 + 9); if (name == NULL) return FALSE; sprintf (name, "%08x", (unsigned) ent->addend & 0xffffffff); if (ent->sec) memcpy (name + 8, ent->sec->name, len3); memcpy (name + 8 + len3, stub, len2); memcpy (name + 8 + len3 + len2, h->root.root.string, len1 + 1); sh = elf_link_hash_lookup (&htab->elf, name, TRUE, FALSE, FALSE); if (sh == NULL) return FALSE; if (sh->root.type == bfd_link_hash_new) { sh->root.type = bfd_link_hash_defined; sh->root.u.def.section = htab->glink; sh->root.u.def.value = ent->glink_offset; sh->ref_regular = 1; sh->def_regular = 1; sh->ref_regular_nonweak = 1; sh->forced_local = 1; sh->non_elf = 0; } return TRUE; } /* Allocate NEED contiguous space in .got, and return the offset. Handles allocation of the got header when crossing 32k. */ static bfd_vma allocate_got (struct ppc_elf_link_hash_table *htab, unsigned int need) { bfd_vma where; unsigned int max_before_header; if (htab->plt_type == PLT_VXWORKS) { where = htab->got->size; htab->got->size += need; } else { max_before_header = htab->plt_type == PLT_NEW ? 32768 : 32764; if (need <= htab->got_gap) { where = max_before_header - htab->got_gap; htab->got_gap -= need; } else { if (htab->got->size + need > max_before_header && htab->got->size <= max_before_header) { htab->got_gap = max_before_header - htab->got->size; htab->got->size = max_before_header + htab->got_header_size; } where = htab->got->size; htab->got->size += need; } } return where; } /* Allocate space in associated reloc sections for dynamic relocs. */ static bfd_boolean allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) { struct bfd_link_info *info = inf; struct ppc_elf_link_hash_entry *eh; struct ppc_elf_link_hash_table *htab; struct ppc_elf_dyn_relocs *p; if (h->root.type == bfd_link_hash_indirect) return TRUE; if (h->root.type == bfd_link_hash_warning) /* When warning symbols are created, they **replace** the "real" entry in the hash table, thus we never get to see the real symbol in a hash traversal. So look at it now. */ h = (struct elf_link_hash_entry *) h->root.u.i.link; htab = ppc_elf_hash_table (info); if (htab->elf.dynamic_sections_created) { struct plt_entry *ent; bfd_boolean doneone = FALSE; bfd_vma plt_offset = 0, glink_offset = 0; for (ent = h->plt.plist; ent != NULL; ent = ent->next) if (ent->plt.refcount > 0) { /* Make sure this symbol is output as a dynamic symbol. */ if (h->dynindx == -1 && !h->forced_local) { if (! bfd_elf_link_record_dynamic_symbol (info, h)) return FALSE; } if (info->shared || WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h)) { asection *s = htab->plt; if (htab->plt_type == PLT_NEW) { if (!doneone) { plt_offset = s->size; s->size += 4; } ent->plt.offset = plt_offset; s = htab->glink; if (!doneone || info->shared || info->pie) { glink_offset = s->size; s->size += GLINK_ENTRY_SIZE; } if (!doneone && !info->shared && !h->def_regular) { h->root.u.def.section = s; h->root.u.def.value = glink_offset; } ent->glink_offset = glink_offset; if (htab->emit_stub_syms && !add_stub_sym (ent, h, info)) return FALSE; } else { if (!doneone) { /* If this is the first .plt entry, make room for the special first entry. */ if (s->size == 0) s->size += htab->plt_initial_entry_size; /* The PowerPC PLT is actually composed of two parts, the first part is 2 words (for a load and a jump), and then there is a remaining word available at the end. */ plt_offset = (htab->plt_initial_entry_size + (htab->plt_slot_size * ((s->size - htab->plt_initial_entry_size) / htab->plt_entry_size))); /* If this symbol is not defined in a regular file, and we are not generating a shared library, then set the symbol to this location in the .plt. This is required to make function pointers compare as equal between the normal executable and the shared library. */ if (! info->shared && !h->def_regular) { h->root.u.def.section = s; h->root.u.def.value = plt_offset; } /* Make room for this entry. */ s->size += htab->plt_entry_size; /* After the 8192nd entry, room for two entries is allocated. */ if (htab->plt_type == PLT_OLD && (s->size - htab->plt_initial_entry_size) / htab->plt_entry_size > PLT_NUM_SINGLE_ENTRIES) s->size += htab->plt_entry_size; } ent->plt.offset = plt_offset; } /* We also need to make an entry in the .rela.plt section. */ if (!doneone) { htab->relplt->size += sizeof (Elf32_External_Rela); if (htab->plt_type == PLT_VXWORKS) { /* Allocate space for the unloaded relocations. */ if (!info->shared) { if (ent->plt.offset == (bfd_vma) htab->plt_initial_entry_size) { htab->srelplt2->size += sizeof (Elf32_External_Rela) * VXWORKS_PLTRESOLVE_RELOCS; } htab->srelplt2->size += sizeof (Elf32_External_Rela) * VXWORKS_PLT_NON_JMP_SLOT_RELOCS; } /* Every PLT entry has an associated GOT entry in .got.plt. */ htab->sgotplt->size += 4; } doneone = TRUE; } } else ent->plt.offset = (bfd_vma) -1; } else ent->plt.offset = (bfd_vma) -1; if (!doneone) { h->plt.plist = NULL; h->needs_plt = 0; } } else { h->plt.plist = NULL; h->needs_plt = 0; } eh = (struct ppc_elf_link_hash_entry *) h; if (eh->elf.got.refcount > 0) { /* Make sure this symbol is output as a dynamic symbol. */ if (eh->elf.dynindx == -1 && !eh->elf.forced_local) { if (!bfd_elf_link_record_dynamic_symbol (info, &eh->elf)) return FALSE; } if (eh->tls_mask == (TLS_TLS | TLS_LD) && !eh->elf.def_dynamic) - /* If just an LD reloc, we'll just use htab->tlsld_got.offset. */ - eh->elf.got.offset = (bfd_vma) -1; + { + /* If just an LD reloc, we'll just use htab->tlsld_got.offset. */ + htab->tlsld_got.refcount += 1; + eh->elf.got.offset = (bfd_vma) -1; + } else { bfd_boolean dyn; unsigned int need = 0; if ((eh->tls_mask & TLS_TLS) != 0) { if ((eh->tls_mask & TLS_LD) != 0) need += 8; if ((eh->tls_mask & TLS_GD) != 0) need += 8; if ((eh->tls_mask & (TLS_TPREL | TLS_TPRELGD)) != 0) need += 4; if ((eh->tls_mask & TLS_DTPREL) != 0) need += 4; } else need += 4; eh->elf.got.offset = allocate_got (htab, need); dyn = htab->elf.dynamic_sections_created; if ((info->shared || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, &eh->elf)) && (ELF_ST_VISIBILITY (eh->elf.other) == STV_DEFAULT || eh->elf.root.type != bfd_link_hash_undefweak)) { /* All the entries we allocated need relocs. Except LD only needs one. */ if ((eh->tls_mask & TLS_LD) != 0) need -= 4; htab->relgot->size += need * (sizeof (Elf32_External_Rela) / 4); } } } else eh->elf.got.offset = (bfd_vma) -1; if (eh->dyn_relocs == NULL) return TRUE; /* In the shared -Bsymbolic case, discard space allocated for dynamic pc-relative relocs against symbols which turn out to be defined in regular objects. For the normal shared case, discard space for relocs that have become local due to symbol visibility changes. */ if (info->shared) { /* Relocs that use pc_count are those that appear on a call insn, - or certain REL relocs (see MUST_BE_DYN_RELOC) that can be + or certain REL relocs (see must_be_dyn_reloc) that can be generated via assembly. We want calls to protected symbols to resolve directly to the function rather than going via the plt. If people want function pointer comparisons to work as expected then they should avoid writing weird assembly. */ if (SYMBOL_CALLS_LOCAL (info, h)) { struct ppc_elf_dyn_relocs **pp; for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) { p->count -= p->pc_count; p->pc_count = 0; if (p->count == 0) *pp = p->next; else pp = &p->next; } } /* Also discard relocs on undefined weak syms with non-default visibility. */ if (eh->dyn_relocs != NULL && h->root.type == bfd_link_hash_undefweak) { if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT) eh->dyn_relocs = NULL; /* Make sure undefined weak symbols are output as a dynamic symbol in PIEs. */ else if (h->dynindx == -1 && !h->forced_local) { if (! bfd_elf_link_record_dynamic_symbol (info, h)) return FALSE; } } } else if (ELIMINATE_COPY_RELOCS) { /* For the non-shared case, discard space for relocs against symbols which turn out to need copy relocs or are not dynamic. */ if (!h->non_got_ref && h->def_dynamic && !h->def_regular) { /* Make sure this symbol is output as a dynamic symbol. Undefined weak syms won't yet be marked as dynamic. */ if (h->dynindx == -1 && !h->forced_local) { if (! bfd_elf_link_record_dynamic_symbol (info, h)) return FALSE; } /* If that succeeded, we know we'll be keeping all the relocs. */ if (h->dynindx != -1) goto keep; } eh->dyn_relocs = NULL; keep: ; } /* Finally, allocate space. */ for (p = eh->dyn_relocs; p != NULL; p = p->next) { asection *sreloc = elf_section_data (p->sec)->sreloc; sreloc->size += p->count * sizeof (Elf32_External_Rela); } return TRUE; } /* Find any dynamic relocs that apply to read-only sections. */ static bfd_boolean readonly_dynrelocs (struct elf_link_hash_entry *h, void *info) { struct ppc_elf_dyn_relocs *p; if (h->root.type == bfd_link_hash_indirect) return TRUE; if (h->root.type == bfd_link_hash_warning) h = (struct elf_link_hash_entry *) h->root.u.i.link; for (p = ppc_elf_hash_entry (h)->dyn_relocs; p != NULL; p = p->next) { asection *s = p->sec->output_section; if (s != NULL && ((s->flags & (SEC_READONLY | SEC_ALLOC)) == (SEC_READONLY | SEC_ALLOC))) { ((struct bfd_link_info *) info)->flags |= DF_TEXTREL; /* Not an error, just cut short the traversal. */ return FALSE; } } return TRUE; } /* Set the sizes of the dynamic sections. */ static bfd_boolean ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) { struct ppc_elf_link_hash_table *htab; asection *s; bfd_boolean relocs; bfd *ibfd; #ifdef DEBUG fprintf (stderr, "ppc_elf_size_dynamic_sections called\n"); #endif htab = ppc_elf_hash_table (info); BFD_ASSERT (htab->elf.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 (htab->elf.dynobj, ".interp"); BFD_ASSERT (s != NULL); s->size = sizeof ELF_DYNAMIC_INTERPRETER; s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; } } if (htab->plt_type == PLT_OLD) htab->got_header_size = 16; else if (htab->plt_type == PLT_NEW) htab->got_header_size = 12; /* Set up .got offsets for local syms, and space for local dynamic relocs. */ for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) { bfd_signed_vma *local_got; bfd_signed_vma *end_local_got; char *lgot_masks; bfd_size_type locsymcount; Elf_Internal_Shdr *symtab_hdr; if (!is_ppc_elf_target (ibfd->xvec)) continue; for (s = ibfd->sections; s != NULL; s = s->next) { struct ppc_elf_dyn_relocs *p; for (p = ((struct ppc_elf_dyn_relocs *) elf_section_data (s)->local_dynrel); p != NULL; p = p->next) { if (!bfd_is_abs_section (p->sec) && bfd_is_abs_section (p->sec->output_section)) { /* Input section has been discarded, either because it is a copy of a linkonce section or due to linker script /DISCARD/, so we'll be discarding the relocs too. */ } else if (p->count != 0) { elf_section_data (p->sec)->sreloc->size += p->count * sizeof (Elf32_External_Rela); if ((p->sec->output_section->flags & (SEC_READONLY | SEC_ALLOC)) == (SEC_READONLY | SEC_ALLOC)) info->flags |= DF_TEXTREL; } } } local_got = elf_local_got_refcounts (ibfd); if (!local_got) continue; symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; locsymcount = symtab_hdr->sh_info; end_local_got = local_got + locsymcount; lgot_masks = (char *) end_local_got; for (; local_got < end_local_got; ++local_got, ++lgot_masks) if (*local_got > 0) { if (*lgot_masks == (TLS_TLS | TLS_LD)) { /* If just an LD reloc, we'll just use htab->tlsld_got.offset. */ htab->tlsld_got.refcount += 1; *local_got = (bfd_vma) -1; } else { unsigned int need = 0; if ((*lgot_masks & TLS_TLS) != 0) { if ((*lgot_masks & TLS_GD) != 0) need += 8; if ((*lgot_masks & (TLS_TPREL | TLS_TPRELGD)) != 0) need += 4; if ((*lgot_masks & TLS_DTPREL) != 0) need += 4; } else need += 4; *local_got = allocate_got (htab, need); if (info->shared) htab->relgot->size += (need * (sizeof (Elf32_External_Rela) / 4)); } } else *local_got = (bfd_vma) -1; } + /* Allocate space for global sym dynamic relocs. */ + elf_link_hash_traverse (elf_hash_table (info), allocate_dynrelocs, info); + if (htab->tlsld_got.refcount > 0) { htab->tlsld_got.offset = allocate_got (htab, 8); if (info->shared) htab->relgot->size += sizeof (Elf32_External_Rela); } else htab->tlsld_got.offset = (bfd_vma) -1; - /* Allocate space for global sym dynamic relocs. */ - elf_link_hash_traverse (elf_hash_table (info), allocate_dynrelocs, info); - if (htab->got != NULL && htab->plt_type != PLT_VXWORKS) { unsigned int g_o_t = 32768; /* If we haven't allocated the header, do so now. When we get here, for old plt/got the got size will be 0 to 32764 (not allocated), or 32780 to 65536 (header allocated). For new plt/got, the corresponding ranges are 0 to 32768 and 32780 to 65536. */ if (htab->got->size <= 32768) { g_o_t = htab->got->size; if (htab->plt_type == PLT_OLD) g_o_t += 4; htab->got->size += htab->got_header_size; } htab->elf.hgot->root.u.def.value = g_o_t; } if (htab->glink != NULL && htab->glink->size != 0) { htab->glink_pltresolve = htab->glink->size; /* Space for the branch table. */ htab->glink->size += htab->glink->size / (GLINK_ENTRY_SIZE / 4) - 4; /* Pad out to align the start of PLTresolve. */ htab->glink->size += -htab->glink->size & 15; htab->glink->size += GLINK_PLTRESOLVE; if (htab->emit_stub_syms) { struct elf_link_hash_entry *sh; sh = elf_link_hash_lookup (&htab->elf, "__glink", TRUE, FALSE, FALSE); if (sh == NULL) return FALSE; if (sh->root.type == bfd_link_hash_new) { sh->root.type = bfd_link_hash_defined; sh->root.u.def.section = htab->glink; sh->root.u.def.value = htab->glink_pltresolve; sh->ref_regular = 1; sh->def_regular = 1; sh->ref_regular_nonweak = 1; sh->forced_local = 1; sh->non_elf = 0; } sh = elf_link_hash_lookup (&htab->elf, "__glink_PLTresolve", TRUE, FALSE, FALSE); if (sh == NULL) return FALSE; if (sh->root.type == bfd_link_hash_new) { sh->root.type = bfd_link_hash_defined; sh->root.u.def.section = htab->glink; sh->root.u.def.value = htab->glink->size - GLINK_PLTRESOLVE; sh->ref_regular = 1; sh->def_regular = 1; sh->ref_regular_nonweak = 1; sh->forced_local = 1; sh->non_elf = 0; } } } /* We've now determined the sizes of the various dynamic sections. Allocate memory for them. */ relocs = FALSE; for (s = htab->elf.dynobj->sections; s != NULL; s = s->next) { bfd_boolean strip_section = TRUE; if ((s->flags & SEC_LINKER_CREATED) == 0) continue; if (s == htab->plt || s == htab->glink || s == htab->got || s == htab->sgotplt || s == htab->sbss || s == htab->dynbss || s == htab->dynsbss) { /* We'd like to strip these sections if they aren't needed, but if we've exported dynamic symbols from them we must leave them. It's too late to tell BFD to get rid of the symbols. */ if ((s == htab->plt || s == htab->got) && htab->elf.hplt != NULL) strip_section = FALSE; /* Strip this section if we don't need it; see the comment below. */ } else if (s == htab->sdata[0].section || s == htab->sdata[1].section) { /* Strip these too. */ } else if (CONST_STRNEQ (bfd_get_section_name (dynobj, s), ".rela")) { if (s->size != 0) { /* Remember whether there are any relocation sections. */ relocs = TRUE; /* We use the reloc_count field as a counter if we need to copy relocs into the output file. */ s->reloc_count = 0; } } else { /* It's not one of our sections, so don't allocate space. */ continue; } if (s->size == 0 && strip_section) { /* If we don't need this section, strip it from the output file. This is mostly to handle .rela.bss and .rela.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 adjust_dynamic_symbol is called, and it is that function which decides whether anything needs to go into these sections. */ s->flags |= SEC_EXCLUDE; continue; } if ((s->flags & SEC_HAS_CONTENTS) == 0) continue; /* Allocate memory for the section contents. */ s->contents = bfd_zalloc (htab->elf.dynobj, s->size); if (s->contents == NULL) return FALSE; } if (htab->elf.dynamic_sections_created) { /* Add some entries to the .dynamic section. We fill in the values later, in ppc_elf_finish_dynamic_sections, but we must add the entries now so that we get the correct size for the .dynamic section. The DT_DEBUG entry is filled in by the dynamic linker and used by the debugger. */ #define add_dynamic_entry(TAG, VAL) \ _bfd_elf_add_dynamic_entry (info, TAG, VAL) if (info->executable) { if (!add_dynamic_entry (DT_DEBUG, 0)) return FALSE; } if (htab->plt != NULL && htab->plt->size != 0) { if (!add_dynamic_entry (DT_PLTGOT, 0) || !add_dynamic_entry (DT_PLTRELSZ, 0) || !add_dynamic_entry (DT_PLTREL, DT_RELA) || !add_dynamic_entry (DT_JMPREL, 0)) return FALSE; } if (htab->glink != NULL && htab->glink->size != 0) { if (!add_dynamic_entry (DT_PPC_GOT, 0)) return FALSE; } if (relocs) { if (!add_dynamic_entry (DT_RELA, 0) || !add_dynamic_entry (DT_RELASZ, 0) || !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela))) return FALSE; } /* If any dynamic relocs apply to a read-only section, then we need a DT_TEXTREL entry. */ if ((info->flags & DF_TEXTREL) == 0) elf_link_hash_traverse (elf_hash_table (info), readonly_dynrelocs, info); if ((info->flags & DF_TEXTREL) != 0) { if (!add_dynamic_entry (DT_TEXTREL, 0)) return FALSE; } } #undef add_dynamic_entry return TRUE; } #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) static const int shared_stub_entry[] = { 0x7c0802a6, /* mflr 0 */ 0x429f0005, /* bcl 20, 31, .Lxxx */ 0x7d6802a6, /* mflr 11 */ 0x3d6b0000, /* addis 11, 11, (xxx-.Lxxx)@ha */ 0x396b0018, /* addi 11, 11, (xxx-.Lxxx)@l */ 0x7c0803a6, /* mtlr 0 */ 0x7d6903a6, /* mtctr 11 */ 0x4e800420, /* bctr */ }; static const int stub_entry[] = { 0x3d600000, /* lis 11,xxx@ha */ 0x396b0000, /* addi 11,11,xxx@l */ 0x7d6903a6, /* mtctr 11 */ 0x4e800420, /* bctr */ }; static bfd_boolean ppc_elf_relax_section (bfd *abfd, asection *isec, struct bfd_link_info *link_info, bfd_boolean *again) { struct one_fixup { struct one_fixup *next; asection *tsec; bfd_vma toff; bfd_vma trampoff; }; Elf_Internal_Shdr *symtab_hdr; bfd_byte *contents = NULL; Elf_Internal_Sym *isymbuf = NULL; Elf_Internal_Rela *internal_relocs = NULL; Elf_Internal_Rela *irel, *irelend; struct one_fixup *fixups = NULL; bfd_boolean changed; struct ppc_elf_link_hash_table *htab; bfd_size_type trampoff; asection *got2; *again = FALSE; /* Nothing to do if there are no relocations, and no need to do anything with non-alloc sections. */ if ((isec->flags & SEC_ALLOC) == 0 || (isec->flags & SEC_RELOC) == 0 || isec->reloc_count == 0) return TRUE; trampoff = (isec->size + 3) & (bfd_vma) -4; /* Space for a branch around any trampolines. */ trampoff += 4; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; /* Get a copy of the native relocations. */ internal_relocs = _bfd_elf_link_read_relocs (abfd, isec, NULL, NULL, link_info->keep_memory); if (internal_relocs == NULL) goto error_return; htab = ppc_elf_hash_table (link_info); got2 = bfd_get_section_by_name (abfd, ".got2"); irelend = internal_relocs + isec->reloc_count; for (irel = internal_relocs; irel < irelend; irel++) { unsigned long r_type = ELF32_R_TYPE (irel->r_info); bfd_vma symaddr, reladdr, toff, roff; asection *tsec; struct one_fixup *f; size_t insn_offset = 0; bfd_vma max_branch_offset, val; bfd_byte *hit_addr; unsigned long t0; unsigned char sym_type; switch (r_type) { case R_PPC_REL24: case R_PPC_LOCAL24PC: case R_PPC_PLTREL24: max_branch_offset = 1 << 25; break; case R_PPC_REL14: case R_PPC_REL14_BRTAKEN: case R_PPC_REL14_BRNTAKEN: max_branch_offset = 1 << 15; break; default: continue; } /* Get the value of the symbol referred to by the reloc. */ if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) { /* A local symbol. */ Elf_Internal_Sym *isym; /* Read this BFD's local symbols. */ if (isymbuf == NULL) { isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; if (isymbuf == NULL) isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, symtab_hdr->sh_info, 0, NULL, NULL, NULL); if (isymbuf == 0) goto error_return; } isym = isymbuf + ELF32_R_SYM (irel->r_info); if (isym->st_shndx == SHN_UNDEF) continue; /* We can't do anything with undefined symbols. */ else if (isym->st_shndx == SHN_ABS) tsec = bfd_abs_section_ptr; else if (isym->st_shndx == SHN_COMMON) tsec = bfd_com_section_ptr; else tsec = bfd_section_from_elf_index (abfd, isym->st_shndx); toff = isym->st_value; sym_type = ELF_ST_TYPE (isym->st_info); } else { /* Global symbol handling. */ unsigned long indx; struct elf_link_hash_entry *h; indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info; h = elf_sym_hashes (abfd)[indx]; 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; tsec = NULL; toff = 0; if (r_type == R_PPC_PLTREL24 && htab->plt != NULL) { struct plt_entry *ent = find_plt_ent (h, got2, irel->r_addend); if (ent != NULL) { if (htab->plt_type == PLT_NEW) { tsec = htab->glink; toff = ent->glink_offset; } else { tsec = htab->plt; toff = ent->plt.offset; } } } if (tsec != NULL) ; else if (h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) { tsec = h->root.u.def.section; toff = h->root.u.def.value; } else continue; sym_type = h->type; } /* If the branch and target are in the same section, you have no hope of adding stubs. We'll error out later should the branch overflow. */ if (tsec == isec) continue; /* There probably isn't any reason to handle symbols in SEC_MERGE sections; SEC_MERGE doesn't seem a likely attribute for a code section, and we are only looking at branches. However, implement it correctly here as a reference for other target relax_section functions. */ if (0 && tsec->sec_info_type == ELF_INFO_TYPE_MERGE) { /* At this stage in linking, no SEC_MERGE symbol has been adjusted, so all references to such symbols need to be passed through _bfd_merged_section_offset. (Later, in relocate_section, all SEC_MERGE symbols *except* for section symbols have been adjusted.) gas may reduce relocations against symbols in SEC_MERGE sections to a relocation against the section symbol when the original addend was zero. When the reloc is against a section symbol we should include the addend in the offset passed to _bfd_merged_section_offset, since the location of interest is the original symbol. On the other hand, an access to "sym+addend" where "sym" is not a section symbol should not include the addend; Such an access is presumed to be an offset from "sym"; The location of interest is just "sym". */ if (sym_type == STT_SECTION) toff += irel->r_addend; toff = _bfd_merged_section_offset (abfd, &tsec, elf_section_data (tsec)->sec_info, toff); if (sym_type != STT_SECTION) toff += irel->r_addend; } /* PLTREL24 addends are special. */ else if (r_type != R_PPC_PLTREL24) toff += irel->r_addend; /* Attempted -shared link of non-pic code loses. */ if (tsec->output_section == NULL) continue; symaddr = tsec->output_section->vma + tsec->output_offset + toff; roff = irel->r_offset; reladdr = isec->output_section->vma + isec->output_offset + roff; /* If the branch is in range, no need to do anything. */ if (symaddr - reladdr + max_branch_offset < 2 * max_branch_offset) continue; /* Look for an existing fixup to this address. */ for (f = fixups; f ; f = f->next) if (f->tsec == tsec && f->toff == toff) break; if (f == NULL) { size_t size; unsigned long stub_rtype; val = trampoff - roff; if (val >= max_branch_offset) /* Oh dear, we can't reach a trampoline. Don't try to add one. We'll report an error later. */ continue; if (link_info->shared) { size = 4 * ARRAY_SIZE (shared_stub_entry); insn_offset = 12; stub_rtype = R_PPC_RELAX32PC; } else { size = 4 * ARRAY_SIZE (stub_entry); insn_offset = 0; stub_rtype = R_PPC_RELAX32; } if (R_PPC_RELAX32_PLT - R_PPC_RELAX32 != R_PPC_RELAX32PC_PLT - R_PPC_RELAX32PC) abort (); if (tsec == htab->plt || tsec == htab->glink) stub_rtype += R_PPC_RELAX32_PLT - R_PPC_RELAX32; /* Hijack the old relocation. Since we need two relocations for this use a "composite" reloc. */ irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), stub_rtype); irel->r_offset = trampoff + insn_offset; /* Record the fixup so we don't do it again this section. */ f = bfd_malloc (sizeof (*f)); f->next = fixups; f->tsec = tsec; f->toff = toff; f->trampoff = trampoff; fixups = f; trampoff += size; } else { val = f->trampoff - roff; if (val >= max_branch_offset) continue; /* Nop out the reloc, since we're finalizing things here. */ irel->r_info = ELF32_R_INFO (0, R_PPC_NONE); } /* Get the section contents. */ if (contents == NULL) { /* Get cached copy if it exists. */ if (elf_section_data (isec)->this_hdr.contents != NULL) contents = elf_section_data (isec)->this_hdr.contents; else { /* Go get them off disk. */ if (!bfd_malloc_and_get_section (abfd, isec, &contents)) goto error_return; } } /* Fix up the existing branch to hit the trampoline. */ hit_addr = contents + roff; switch (r_type) { case R_PPC_REL24: case R_PPC_LOCAL24PC: case R_PPC_PLTREL24: t0 = bfd_get_32 (abfd, hit_addr); t0 &= ~0x3fffffc; t0 |= val & 0x3fffffc; bfd_put_32 (abfd, t0, hit_addr); break; case R_PPC_REL14: case R_PPC_REL14_BRTAKEN: case R_PPC_REL14_BRNTAKEN: t0 = bfd_get_32 (abfd, hit_addr); t0 &= ~0xfffc; t0 |= val & 0xfffc; bfd_put_32 (abfd, t0, hit_addr); break; } } /* Write out the trampolines. */ changed = fixups != NULL; if (fixups != NULL) { const int *stub; bfd_byte *dest; bfd_vma val; int i, size; do { struct one_fixup *f = fixups; fixups = fixups->next; free (f); } while (fixups); contents = bfd_realloc (contents, trampoff); if (contents == NULL) goto error_return; isec->size = (isec->size + 3) & (bfd_vma) -4; /* Branch around the trampolines. */ val = trampoff - isec->size + 0x48000000; dest = contents + isec->size; isec->size = trampoff; bfd_put_32 (abfd, val, dest); dest += 4; if (link_info->shared) { stub = shared_stub_entry; size = ARRAY_SIZE (shared_stub_entry); } else { stub = stub_entry; size = ARRAY_SIZE (stub_entry); } i = 0; while (dest < contents + trampoff) { bfd_put_32 (abfd, stub[i], dest); i++; if (i == size) i = 0; dest += 4; } BFD_ASSERT (i == 0); } if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf) { if (! link_info->keep_memory) free (isymbuf); else { /* Cache the symbols for elf_link_input_bfd. */ symtab_hdr->contents = (unsigned char *) isymbuf; } } if (contents != NULL && elf_section_data (isec)->this_hdr.contents != contents) { if (!changed && !link_info->keep_memory) free (contents); else { /* Cache the section contents for elf_link_input_bfd. */ elf_section_data (isec)->this_hdr.contents = contents; } } if (elf_section_data (isec)->relocs != internal_relocs) { if (!changed) free (internal_relocs); else elf_section_data (isec)->relocs = internal_relocs; } *again = changed; return TRUE; error_return: if (isymbuf != NULL && (unsigned char *) isymbuf != symtab_hdr->contents) free (isymbuf); if (contents != NULL && elf_section_data (isec)->this_hdr.contents != contents) free (contents); if (internal_relocs != NULL && elf_section_data (isec)->relocs != internal_relocs) free (internal_relocs); return FALSE; } /* What to do when ld finds relocations against symbols defined in discarded sections. */ static unsigned int ppc_elf_action_discarded (asection *sec) { if (strcmp (".fixup", sec->name) == 0) return 0; if (strcmp (".got2", sec->name) == 0) return 0; return _bfd_elf_default_action_discarded (sec); } /* Fill in the address for a pointer generated in a linker section. */ static bfd_vma elf_finish_pointer_linker_section (bfd *input_bfd, elf_linker_section_t *lsect, struct elf_link_hash_entry *h, bfd_vma relocation, const Elf_Internal_Rela *rel) { elf_linker_section_pointers_t *linker_section_ptr; BFD_ASSERT (lsect != NULL); if (h != NULL) { /* Handle global symbol. */ struct ppc_elf_link_hash_entry *eh; eh = (struct ppc_elf_link_hash_entry *) h; BFD_ASSERT (eh->elf.def_regular); linker_section_ptr = eh->linker_section_pointer; } else { /* Handle local symbol. */ unsigned long r_symndx = ELF32_R_SYM (rel->r_info); BFD_ASSERT (elf_local_ptr_offsets (input_bfd) != NULL); linker_section_ptr = elf_local_ptr_offsets (input_bfd)[r_symndx]; } linker_section_ptr = elf_find_pointer_linker_section (linker_section_ptr, rel->r_addend, lsect); BFD_ASSERT (linker_section_ptr != NULL); /* Offset will always be a multiple of four, so use the bottom bit as a "written" flag. */ if ((linker_section_ptr->offset & 1) == 0) { bfd_put_32 (lsect->section->owner, relocation + linker_section_ptr->addend, lsect->section->contents + linker_section_ptr->offset); linker_section_ptr->offset += 1; } relocation = (lsect->section->output_offset + linker_section_ptr->offset - 1 - 0x8000); #ifdef DEBUG fprintf (stderr, "Finish pointer in linker section %s, offset = %ld (0x%lx)\n", lsect->name, (long) relocation, (long) relocation); #endif /* Subtract out the addend, because it will get added back in by the normal processing. */ return relocation - linker_section_ptr->addend; } /* The RELOCATE_SECTION function is called by the 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 adjust 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 ppc_elf_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; struct ppc_elf_link_hash_table *htab; Elf_Internal_Rela *rel; Elf_Internal_Rela *relend; Elf_Internal_Rela outrel; bfd_byte *loc; asection *got2, *sreloc = NULL; bfd_vma *local_got_offsets; bfd_boolean ret = TRUE; bfd_vma d_offset = (bfd_big_endian (output_bfd) ? 2 : 0); #ifdef DEBUG _bfd_error_handler ("ppc_elf_relocate_section called for %B section %A, " "%ld relocations%s", input_bfd, input_section, (long) input_section->reloc_count, (info->relocatable) ? " (relocatable)" : ""); #endif got2 = bfd_get_section_by_name (input_bfd, ".got2"); /* Initialize howto table if not already done. */ if (!ppc_elf_howto_table[R_PPC_ADDR32]) ppc_elf_howto_init (); htab = ppc_elf_hash_table (info); local_got_offsets = elf_local_got_offsets (input_bfd); symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; sym_hashes = elf_sym_hashes (input_bfd); rel = relocs; relend = relocs + input_section->reloc_count; for (; rel < relend; rel++) { enum elf_ppc_reloc_type r_type; bfd_vma addend; bfd_reloc_status_type r; Elf_Internal_Sym *sym; asection *sec; struct elf_link_hash_entry *h; const char *sym_name; reloc_howto_type *howto; unsigned long r_symndx; bfd_vma relocation; bfd_vma branch_bit, insn, from; bfd_boolean unresolved_reloc; bfd_boolean warned; unsigned int tls_type, tls_mask, tls_gd; r_type = ELF32_R_TYPE (rel->r_info); sym = NULL; sec = NULL; h = NULL; unresolved_reloc = FALSE; warned = FALSE; r_symndx = ELF32_R_SYM (rel->r_info); if (r_symndx < symtab_hdr->sh_info) { sym = local_syms + r_symndx; sec = local_sections[r_symndx]; sym_name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym, sec); relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); } else { RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, r_symndx, symtab_hdr, sym_hashes, h, sec, relocation, unresolved_reloc, warned); sym_name = h->root.root.string; } if (sec != NULL && elf_discarded_section (sec)) { /* For relocs against symbols from removed linkonce sections, or sections discarded by a linker script, we just want the section contents zeroed. Avoid any special processing. */ howto = NULL; if (r_type < R_PPC_max) howto = ppc_elf_howto_table[r_type]; _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset); rel->r_info = 0; rel->r_addend = 0; continue; } if (info->relocatable) { if (got2 != NULL && r_type == R_PPC_PLTREL24 && rel->r_addend >= 32768) { /* R_PPC_PLTREL24 is rather special. If non-zero, the addend specifies the GOT pointer offset within .got2. */ rel->r_addend += got2->output_offset; } continue; } /* TLS optimizations. Replace instruction sequences and relocs based on information we collected in tls_optimize. We edit RELOCS so that --emit-relocs will output something sensible for the final instruction stream. */ tls_mask = 0; tls_gd = 0; - if (IS_PPC_TLS_RELOC (r_type)) + if (h != NULL) + tls_mask = ((struct ppc_elf_link_hash_entry *) h)->tls_mask; + else if (local_got_offsets != NULL) { - if (h != NULL) - tls_mask = ((struct ppc_elf_link_hash_entry *) h)->tls_mask; - else if (local_got_offsets != NULL) - { - char *lgot_masks; - lgot_masks = (char *) (local_got_offsets + symtab_hdr->sh_info); - tls_mask = lgot_masks[r_symndx]; - } + char *lgot_masks; + lgot_masks = (char *) (local_got_offsets + symtab_hdr->sh_info); + tls_mask = lgot_masks[r_symndx]; } /* Ensure reloc mapping code below stays sane. */ if ((R_PPC_GOT_TLSLD16 & 3) != (R_PPC_GOT_TLSGD16 & 3) || (R_PPC_GOT_TLSLD16_LO & 3) != (R_PPC_GOT_TLSGD16_LO & 3) || (R_PPC_GOT_TLSLD16_HI & 3) != (R_PPC_GOT_TLSGD16_HI & 3) || (R_PPC_GOT_TLSLD16_HA & 3) != (R_PPC_GOT_TLSGD16_HA & 3) || (R_PPC_GOT_TLSLD16 & 3) != (R_PPC_GOT_TPREL16 & 3) || (R_PPC_GOT_TLSLD16_LO & 3) != (R_PPC_GOT_TPREL16_LO & 3) || (R_PPC_GOT_TLSLD16_HI & 3) != (R_PPC_GOT_TPREL16_HI & 3) || (R_PPC_GOT_TLSLD16_HA & 3) != (R_PPC_GOT_TPREL16_HA & 3)) abort (); switch (r_type) { default: break; case R_PPC_GOT_TPREL16: case R_PPC_GOT_TPREL16_LO: if (tls_mask != 0 && (tls_mask & TLS_TPREL) == 0) { bfd_vma insn; insn = bfd_get_32 (output_bfd, contents + rel->r_offset - d_offset); insn &= 31 << 21; insn |= 0x3c020000; /* addis 0,2,0 */ bfd_put_32 (output_bfd, insn, contents + rel->r_offset - d_offset); r_type = R_PPC_TPREL16_HA; rel->r_info = ELF32_R_INFO (r_symndx, r_type); } break; case R_PPC_TLS: if (tls_mask != 0 && (tls_mask & TLS_TPREL) == 0) { bfd_vma insn, rtra; insn = bfd_get_32 (output_bfd, contents + rel->r_offset); if ((insn & ((31 << 26) | (31 << 11))) == ((31 << 26) | (2 << 11))) rtra = insn & ((1 << 26) - (1 << 16)); else if ((insn & ((31 << 26) | (31 << 16))) == ((31 << 26) | (2 << 16))) rtra = (insn & (31 << 21)) | ((insn & (31 << 11)) << 5); else abort (); if ((insn & ((1 << 11) - (1 << 1))) == 266 << 1) /* add -> addi. */ insn = 14 << 26; else if ((insn & (31 << 1)) == 23 << 1 && ((insn & (31 << 6)) < 14 << 6 || ((insn & (31 << 6)) >= 16 << 6 && (insn & (31 << 6)) < 24 << 6))) /* load and store indexed -> dform. */ insn = (32 | ((insn >> 6) & 31)) << 26; else if ((insn & (31 << 1)) == 21 << 1 && (insn & (0x1a << 6)) == 0) /* ldx, ldux, stdx, stdux -> ld, ldu, std, stdu. */ insn = (((58 | ((insn >> 6) & 4)) << 26) | ((insn >> 6) & 1)); else if ((insn & (31 << 1)) == 21 << 1 && (insn & ((1 << 11) - (1 << 1))) == 341 << 1) /* lwax -> lwa. */ insn = (58 << 26) | 2; else abort (); insn |= rtra; bfd_put_32 (output_bfd, insn, contents + rel->r_offset); r_type = R_PPC_TPREL16_LO; rel->r_info = ELF32_R_INFO (r_symndx, r_type); /* Was PPC_TLS which sits on insn boundary, now PPC_TPREL16_LO which is at low-order half-word. */ rel->r_offset += d_offset; } break; case R_PPC_GOT_TLSGD16_HI: case R_PPC_GOT_TLSGD16_HA: tls_gd = TLS_TPRELGD; if (tls_mask != 0 && (tls_mask & TLS_GD) == 0) goto tls_gdld_hi; break; case R_PPC_GOT_TLSLD16_HI: case R_PPC_GOT_TLSLD16_HA: if (tls_mask != 0 && (tls_mask & TLS_LD) == 0) { tls_gdld_hi: if ((tls_mask & tls_gd) != 0) r_type = (((r_type - (R_PPC_GOT_TLSGD16 & 3)) & 3) + R_PPC_GOT_TPREL16); else { bfd_put_32 (output_bfd, NOP, contents + rel->r_offset); rel->r_offset -= d_offset; r_type = R_PPC_NONE; } rel->r_info = ELF32_R_INFO (r_symndx, r_type); } break; case R_PPC_GOT_TLSGD16: case R_PPC_GOT_TLSGD16_LO: tls_gd = TLS_TPRELGD; if (tls_mask != 0 && (tls_mask & TLS_GD) == 0) - goto tls_get_addr_check; + goto tls_ldgd_opt; break; case R_PPC_GOT_TLSLD16: case R_PPC_GOT_TLSLD16_LO: if (tls_mask != 0 && (tls_mask & TLS_LD) == 0) { - tls_get_addr_check: - if (rel + 1 < relend) - { - enum elf_ppc_reloc_type r_type2; - unsigned long r_symndx2; - struct elf_link_hash_entry *h2; - bfd_vma insn1, insn2; - bfd_vma offset; + unsigned int insn1, insn2; + bfd_vma offset; - /* The next instruction should be a call to - __tls_get_addr. Peek at the reloc to be sure. */ - r_type2 = ELF32_R_TYPE (rel[1].r_info); - r_symndx2 = ELF32_R_SYM (rel[1].r_info); - if (r_symndx2 < symtab_hdr->sh_info - || (r_type2 != R_PPC_REL14 - && r_type2 != R_PPC_REL14_BRTAKEN - && r_type2 != R_PPC_REL14_BRNTAKEN - && r_type2 != R_PPC_REL24 - && r_type2 != R_PPC_PLTREL24)) - break; - - h2 = sym_hashes[r_symndx2 - symtab_hdr->sh_info]; - while (h2->root.type == bfd_link_hash_indirect - || h2->root.type == bfd_link_hash_warning) - h2 = (struct elf_link_hash_entry *) h2->root.u.i.link; - if (h2 == NULL || h2 != htab->tls_get_addr) - break; - - /* OK, it checks out. Replace the call. */ - offset = rel[1].r_offset; + tls_ldgd_opt: + offset = (bfd_vma) -1; + /* If not using the newer R_PPC_TLSGD/LD to mark + __tls_get_addr calls, we must trust that the call + stays with its arg setup insns, ie. that the next + reloc is the __tls_get_addr call associated with + the current reloc. Edit both insns. */ + if (input_section->has_tls_get_addr_call + && rel + 1 < relend + && branch_reloc_hash_match (input_bfd, rel + 1, + htab->tls_get_addr)) + offset = rel[1].r_offset; + if ((tls_mask & tls_gd) != 0) + { + /* IE */ insn1 = bfd_get_32 (output_bfd, contents + rel->r_offset - d_offset); - if ((tls_mask & tls_gd) != 0) + insn1 &= (1 << 26) - 1; + insn1 |= 32 << 26; /* lwz */ + if (offset != (bfd_vma) -1) { - /* IE */ - insn1 &= (1 << 26) - 1; - insn1 |= 32 << 26; /* lwz */ + rel[1].r_info + = ELF32_R_INFO (ELF32_R_SYM (rel[1].r_info), + R_PPC_NONE); 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); + bfd_put_32 (output_bfd, insn2, contents + offset); } - else + r_type = (((r_type - (R_PPC_GOT_TLSGD16 & 3)) & 3) + + R_PPC_GOT_TPREL16); + rel->r_info = ELF32_R_INFO (r_symndx, r_type); + } + else + { + /* LE */ + insn1 = 0x3c620000; /* addis 3,2,0 */ + if (tls_gd == 0) { - /* LE */ - insn1 = 0x3c620000; /* addis 3,2,0 */ - insn2 = 0x38630000; /* addi 3,3,0 */ - if (tls_gd == 0) - { - /* Was an LD reloc. */ - r_symndx = 0; - rel->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 += d_offset; - rel[1].r_addend = rel->r_addend; + /* Was an LD reloc. */ + for (r_symndx = 0; + r_symndx < symtab_hdr->sh_info; + r_symndx++) + if (local_sections[r_symndx] == sec) + break; + if (r_symndx >= symtab_hdr->sh_info) + r_symndx = 0; + rel->r_addend = htab->elf.tls_sec->vma + DTP_OFFSET; + if (r_symndx != 0) + rel->r_addend -= (local_syms[r_symndx].st_value + + sec->output_offset + + sec->output_section->vma); } - bfd_put_32 (output_bfd, insn1, contents + rel->r_offset - d_offset); - bfd_put_32 (output_bfd, insn2, contents + offset); - if (tls_gd == 0) + r_type = R_PPC_TPREL16_HA; + rel->r_info = ELF32_R_INFO (r_symndx, r_type); + if (offset != (bfd_vma) -1) { - /* We changed the symbol on an LD reloc. Start over - in order to get h, sym, sec etc. right. */ - rel--; - continue; + rel[1].r_info = ELF32_R_INFO (r_symndx, R_PPC_TPREL16_LO); + rel[1].r_offset = offset + d_offset; + rel[1].r_addend = rel->r_addend; + insn2 = 0x38630000; /* addi 3,3,0 */ + bfd_put_32 (output_bfd, insn2, contents + offset); } } + bfd_put_32 (output_bfd, insn1, + contents + rel->r_offset - d_offset); + if (tls_gd == 0) + { + /* We changed the symbol on an LD reloc. Start over + in order to get h, sym, sec etc. right. */ + rel--; + continue; + } } break; + + case R_PPC_TLSGD: + if (tls_mask != 0 && (tls_mask & TLS_GD) == 0) + { + unsigned int insn2; + bfd_vma offset = rel->r_offset; + + if ((tls_mask & TLS_TPRELGD) != 0) + { + /* IE */ + r_type = R_PPC_NONE; + insn2 = 0x7c631214; /* add 3,3,2 */ + } + else + { + /* LE */ + r_type = R_PPC_TPREL16_LO; + rel->r_offset += d_offset; + insn2 = 0x38630000; /* addi 3,3,0 */ + } + rel->r_info = ELF32_R_INFO (r_symndx, r_type); + bfd_put_32 (output_bfd, insn2, contents + offset); + /* Zap the reloc on the _tls_get_addr call too. */ + BFD_ASSERT (offset == rel[1].r_offset); + rel[1].r_info = ELF32_R_INFO (ELF32_R_SYM (rel[1].r_info), + R_PPC_NONE); + } + break; + + case R_PPC_TLSLD: + if (tls_mask != 0 && (tls_mask & TLS_LD) == 0) + { + unsigned int insn2; + + for (r_symndx = 0; + r_symndx < symtab_hdr->sh_info; + r_symndx++) + if (local_sections[r_symndx] == sec) + break; + if (r_symndx >= symtab_hdr->sh_info) + r_symndx = 0; + rel->r_addend = htab->elf.tls_sec->vma + DTP_OFFSET; + if (r_symndx != 0) + rel->r_addend -= (local_syms[r_symndx].st_value + + sec->output_offset + + sec->output_section->vma); + + rel->r_info = ELF32_R_INFO (r_symndx, R_PPC_TPREL16_LO); + rel->r_offset += d_offset; + insn2 = 0x38630000; /* addi 3,3,0 */ + bfd_put_32 (output_bfd, insn2, + contents + rel->r_offset - d_offset); + /* Zap the reloc on the _tls_get_addr call too. */ + BFD_ASSERT (rel->r_offset - d_offset == rel[1].r_offset); + rel[1].r_info = ELF32_R_INFO (ELF32_R_SYM (rel[1].r_info), + R_PPC_NONE); + rel--; + continue; + } + break; } /* Handle other relocations that tweak non-addend part of insn. */ branch_bit = 0; switch (r_type) { default: break; /* Branch taken prediction relocations. */ case R_PPC_ADDR14_BRTAKEN: case R_PPC_REL14_BRTAKEN: branch_bit = BRANCH_PREDICT_BIT; /* Fall thru */ /* Branch not taken prediction relocations. */ case R_PPC_ADDR14_BRNTAKEN: case R_PPC_REL14_BRNTAKEN: insn = bfd_get_32 (output_bfd, contents + rel->r_offset); insn &= ~BRANCH_PREDICT_BIT; insn |= branch_bit; from = (rel->r_offset + input_section->output_offset + input_section->output_section->vma); /* Invert 'y' bit if not the default. */ if ((bfd_signed_vma) (relocation + rel->r_addend - from) < 0) insn ^= BRANCH_PREDICT_BIT; bfd_put_32 (output_bfd, insn, contents + rel->r_offset); break; } addend = rel->r_addend; tls_type = 0; howto = NULL; if (r_type < R_PPC_max) howto = ppc_elf_howto_table[r_type]; switch (r_type) { default: (*_bfd_error_handler) (_("%B: unknown relocation type %d for symbol %s"), input_bfd, (int) r_type, sym_name); bfd_set_error (bfd_error_bad_value); ret = FALSE; continue; case R_PPC_NONE: case R_PPC_TLS: + case R_PPC_TLSGD: + case R_PPC_TLSLD: case R_PPC_EMB_MRKREF: case R_PPC_GNU_VTINHERIT: case R_PPC_GNU_VTENTRY: continue; /* GOT16 relocations. Like an ADDR16 using the symbol's address in the GOT as relocation value instead of the symbol's value itself. Also, create a GOT entry for the symbol and put the symbol value there. */ case R_PPC_GOT_TLSGD16: case R_PPC_GOT_TLSGD16_LO: case R_PPC_GOT_TLSGD16_HI: case R_PPC_GOT_TLSGD16_HA: tls_type = TLS_TLS | TLS_GD; goto dogot; case R_PPC_GOT_TLSLD16: case R_PPC_GOT_TLSLD16_LO: case R_PPC_GOT_TLSLD16_HI: case R_PPC_GOT_TLSLD16_HA: tls_type = TLS_TLS | TLS_LD; goto dogot; case R_PPC_GOT_TPREL16: case R_PPC_GOT_TPREL16_LO: case R_PPC_GOT_TPREL16_HI: case R_PPC_GOT_TPREL16_HA: tls_type = TLS_TLS | TLS_TPREL; goto dogot; case R_PPC_GOT_DTPREL16: case R_PPC_GOT_DTPREL16_LO: case R_PPC_GOT_DTPREL16_HI: case R_PPC_GOT_DTPREL16_HA: tls_type = TLS_TLS | TLS_DTPREL; goto dogot; case R_PPC_GOT16: case R_PPC_GOT16_LO: case R_PPC_GOT16_HI: case R_PPC_GOT16_HA: + tls_mask = 0; dogot: { /* Relocation is to the entry for this symbol in the global offset table. */ bfd_vma off; bfd_vma *offp; unsigned long indx; if (htab->got == NULL) abort (); indx = 0; if (tls_type == (TLS_TLS | TLS_LD) && (h == NULL || !h->def_dynamic)) offp = &htab->tlsld_got.offset; else if (h != NULL) { bfd_boolean dyn; dyn = htab->elf.dynamic_sections_created; if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h) || (info->shared && SYMBOL_REFERENCES_LOCAL (info, h))) /* This is actually a static link, or it is a -Bsymbolic link and the symbol is defined locally, or the symbol was forced to be local because of a version file. */ ; else { indx = h->dynindx; unresolved_reloc = FALSE; } offp = &h->got.offset; } else { if (local_got_offsets == NULL) abort (); offp = &local_got_offsets[r_symndx]; } /* The offset must always be a multiple of 4. We use the least significant bit to record whether we have already processed this entry. */ off = *offp; if ((off & 1) != 0) off &= ~1; else { unsigned int tls_m = (tls_mask & (TLS_LD | TLS_GD | TLS_DTPREL | TLS_TPREL | TLS_TPRELGD)); if (offp == &htab->tlsld_got.offset) tls_m = TLS_LD; else if (h == NULL || !h->def_dynamic) tls_m &= ~TLS_LD; /* We might have multiple got entries for this sym. Initialize them all. */ do { int tls_ty = 0; if ((tls_m & TLS_LD) != 0) { tls_ty = TLS_TLS | TLS_LD; tls_m &= ~TLS_LD; } else if ((tls_m & TLS_GD) != 0) { tls_ty = TLS_TLS | TLS_GD; tls_m &= ~TLS_GD; } else if ((tls_m & TLS_DTPREL) != 0) { tls_ty = TLS_TLS | TLS_DTPREL; tls_m &= ~TLS_DTPREL; } else if ((tls_m & (TLS_TPREL | TLS_TPRELGD)) != 0) { tls_ty = TLS_TLS | TLS_TPREL; tls_m = 0; } /* Generate relocs for the dynamic linker. */ if ((info->shared || indx != 0) && (h == NULL || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT || h->root.type != bfd_link_hash_undefweak)) { outrel.r_offset = (htab->got->output_section->vma + htab->got->output_offset + off); outrel.r_addend = 0; if (tls_ty & (TLS_LD | TLS_GD)) { outrel.r_info = ELF32_R_INFO (indx, R_PPC_DTPMOD32); if (tls_ty == (TLS_TLS | TLS_GD)) { loc = htab->relgot->contents; loc += (htab->relgot->reloc_count++ * sizeof (Elf32_External_Rela)); bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); outrel.r_offset += 4; outrel.r_info = ELF32_R_INFO (indx, R_PPC_DTPREL32); } } else if (tls_ty == (TLS_TLS | TLS_DTPREL)) outrel.r_info = ELF32_R_INFO (indx, R_PPC_DTPREL32); else if (tls_ty == (TLS_TLS | TLS_TPREL)) outrel.r_info = ELF32_R_INFO (indx, R_PPC_TPREL32); else if (indx == 0) outrel.r_info = ELF32_R_INFO (indx, R_PPC_RELATIVE); else outrel.r_info = ELF32_R_INFO (indx, R_PPC_GLOB_DAT); if (indx == 0) { outrel.r_addend += relocation; if (tls_ty & (TLS_GD | TLS_DTPREL | TLS_TPREL)) outrel.r_addend -= htab->elf.tls_sec->vma; } loc = htab->relgot->contents; loc += (htab->relgot->reloc_count++ * sizeof (Elf32_External_Rela)); bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); } /* Init the .got section contents if we're not emitting a reloc. */ else { bfd_vma value = relocation; if (tls_ty == (TLS_TLS | TLS_LD)) value = 1; else if (tls_ty != 0) { value -= htab->elf.tls_sec->vma + DTP_OFFSET; if (tls_ty == (TLS_TLS | TLS_TPREL)) value += DTP_OFFSET - TP_OFFSET; if (tls_ty == (TLS_TLS | TLS_GD)) { bfd_put_32 (output_bfd, value, htab->got->contents + off + 4); value = 1; } } bfd_put_32 (output_bfd, value, htab->got->contents + off); } off += 4; if (tls_ty & (TLS_LD | TLS_GD)) off += 4; } while (tls_m != 0); off = *offp; *offp = off | 1; } if (off >= (bfd_vma) -2) abort (); if ((tls_type & TLS_TLS) != 0) { if (tls_type != (TLS_TLS | TLS_LD)) { if ((tls_mask & TLS_LD) != 0 && !(h == NULL || !h->def_dynamic)) off += 8; if (tls_type != (TLS_TLS | TLS_GD)) { if ((tls_mask & TLS_GD) != 0) off += 8; if (tls_type != (TLS_TLS | TLS_DTPREL)) { if ((tls_mask & TLS_DTPREL) != 0) off += 4; } } } } relocation = htab->got->output_offset + off; relocation -= htab->elf.hgot->root.u.def.value; /* Addends on got relocations don't make much sense. x+off@got is actually x@got+off, and since the got is generated by a hash table traversal, the value in the got at entry m+n bears little relation to the entry m. */ if (addend != 0) (*_bfd_error_handler) (_("%B(%A+0x%lx): non-zero addend on %s reloc against `%s'"), input_bfd, input_section, (long) rel->r_offset, howto->name, sym_name); } break; /* Relocations that need no special processing. */ case R_PPC_LOCAL24PC: /* It makes no sense to point a local relocation at a symbol not in this object. */ if (unresolved_reloc) { if (! (*info->callbacks->undefined_symbol) (info, h->root.root.string, input_bfd, input_section, rel->r_offset, TRUE)) return FALSE; continue; } break; case R_PPC_DTPREL16: case R_PPC_DTPREL16_LO: case R_PPC_DTPREL16_HI: case R_PPC_DTPREL16_HA: addend -= htab->elf.tls_sec->vma + DTP_OFFSET; break; /* Relocations that may need to be propagated if this is a shared object. */ case R_PPC_TPREL16: case R_PPC_TPREL16_LO: case R_PPC_TPREL16_HI: case R_PPC_TPREL16_HA: addend -= htab->elf.tls_sec->vma + TP_OFFSET; /* The TPREL16 relocs shouldn't really be used in shared libs as they will result in DT_TEXTREL being set, but support them anyway. */ goto dodyn; case R_PPC_TPREL32: addend -= htab->elf.tls_sec->vma + TP_OFFSET; goto dodyn; case R_PPC_DTPREL32: addend -= htab->elf.tls_sec->vma + DTP_OFFSET; goto dodyn; case R_PPC_DTPMOD32: relocation = 1; addend = 0; goto dodyn; case R_PPC_REL16: case R_PPC_REL16_LO: case R_PPC_REL16_HI: case R_PPC_REL16_HA: break; case R_PPC_REL24: case R_PPC_REL32: case R_PPC_REL14: case R_PPC_REL14_BRTAKEN: case R_PPC_REL14_BRNTAKEN: /* If these relocations are not to a named symbol, they can be handled right here, no need to bother the dynamic linker. */ if (SYMBOL_REFERENCES_LOCAL (info, h) || h == htab->elf.hgot) break; /* fall through */ /* Relocations that always need to be propagated if this is a shared object. */ case R_PPC_ADDR32: case R_PPC_ADDR24: case R_PPC_ADDR16: case R_PPC_ADDR16_LO: case R_PPC_ADDR16_HI: case R_PPC_ADDR16_HA: case R_PPC_ADDR14: case R_PPC_ADDR14_BRTAKEN: case R_PPC_ADDR14_BRNTAKEN: case R_PPC_UADDR32: case R_PPC_UADDR16: dodyn: if ((input_section->flags & SEC_ALLOC) == 0) break; /* Fall thru. */ if ((info->shared && (h == NULL || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT || h->root.type != bfd_link_hash_undefweak) - && (MUST_BE_DYN_RELOC (r_type) + && (must_be_dyn_reloc (info, r_type) || !SYMBOL_CALLS_LOCAL (info, h))) || (ELIMINATE_COPY_RELOCS && !info->shared && h != NULL && h->dynindx != -1 && !h->non_got_ref && h->def_dynamic && !h->def_regular)) { int skip; #ifdef DEBUG fprintf (stderr, "ppc_elf_relocate_section needs to " "create relocation for %s\n", (h && h->root.root.string ? h->root.root.string : "")); #endif /* When generating a shared object, these relocations are copied into the output file to be resolved at run time. */ if (sreloc == NULL) { const char *name; name = (bfd_elf_string_from_elf_section (input_bfd, elf_elfheader (input_bfd)->e_shstrndx, elf_section_data (input_section)->rel_hdr.sh_name)); if (name == NULL) return FALSE; BFD_ASSERT (CONST_STRNEQ (name, ".rela") && strcmp (bfd_get_section_name (input_bfd, input_section), name + 5) == 0); sreloc = bfd_get_section_by_name (htab->elf.dynobj, name); BFD_ASSERT (sreloc != NULL); } skip = 0; outrel.r_offset = _bfd_elf_section_offset (output_bfd, info, input_section, rel->r_offset); if (outrel.r_offset == (bfd_vma) -1 || outrel.r_offset == (bfd_vma) -2) skip = (int) outrel.r_offset; outrel.r_offset += (input_section->output_section->vma + input_section->output_offset); if (skip) memset (&outrel, 0, sizeof outrel); else if (!SYMBOL_REFERENCES_LOCAL (info, h)) { unresolved_reloc = FALSE; outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); outrel.r_addend = rel->r_addend; } else { outrel.r_addend = relocation + rel->r_addend; if (r_type == R_PPC_ADDR32) outrel.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE); else { - long indx; + long indx = 0; - if (bfd_is_abs_section (sec)) - indx = 0; + if (r_symndx == 0 || bfd_is_abs_section (sec)) + ; else if (sec == NULL || sec->owner == NULL) { bfd_set_error (bfd_error_bad_value); return FALSE; } else { asection *osec; /* We are turning this relocation into one against a section symbol. It would be proper to subtract the symbol's value, osec->vma, from the emitted reloc addend, but ld.so expects buggy relocs. */ osec = sec->output_section; indx = elf_section_data (osec)->dynindx; if (indx == 0) { osec = htab->elf.text_index_section; indx = elf_section_data (osec)->dynindx; } BFD_ASSERT (indx != 0); #ifdef DEBUG if (indx == 0) printf ("indx=%ld section=%s flags=%08x name=%s\n", indx, osec->name, osec->flags, h->root.root.string); #endif } outrel.r_info = ELF32_R_INFO (indx, r_type); } } loc = sreloc->contents; loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rela); bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); if (skip == -1) continue; /* This reloc will be computed at runtime. We clear the memory so that it contains predictable value. */ if (! skip && ((input_section->flags & SEC_ALLOC) != 0 || ELF32_R_TYPE (outrel.r_info) != R_PPC_RELATIVE)) { relocation = howto->pc_relative ? outrel.r_offset : 0; addend = 0; break; } } break; case R_PPC_RELAX32PC_PLT: case R_PPC_RELAX32_PLT: { struct plt_entry *ent = find_plt_ent (h, got2, addend); if (htab->plt_type == PLT_NEW) relocation = (htab->glink->output_section->vma + htab->glink->output_offset + ent->glink_offset); else relocation = (htab->plt->output_section->vma + htab->plt->output_offset + ent->plt.offset); addend = 0; } if (r_type == R_PPC_RELAX32_PLT) goto relax32; /* Fall thru */ case R_PPC_RELAX32PC: relocation -= (input_section->output_section->vma + input_section->output_offset + rel->r_offset - 4); /* Fall thru */ case R_PPC_RELAX32: relax32: { unsigned long t0; unsigned long t1; t0 = bfd_get_32 (output_bfd, contents + rel->r_offset); t1 = bfd_get_32 (output_bfd, contents + rel->r_offset + 4); /* We're clearing the bits for R_PPC_ADDR16_HA and R_PPC_ADDR16_LO here. */ t0 &= ~0xffff; t1 &= ~0xffff; /* t0 is HA, t1 is LO */ relocation += addend; t0 |= ((relocation + 0x8000) >> 16) & 0xffff; t1 |= relocation & 0xffff; bfd_put_32 (output_bfd, t0, contents + rel->r_offset); bfd_put_32 (output_bfd, t1, contents + rel->r_offset + 4); } continue; /* Indirect .sdata relocation. */ case R_PPC_EMB_SDAI16: BFD_ASSERT (htab->sdata[0].section != NULL); relocation = elf_finish_pointer_linker_section (input_bfd, &htab->sdata[0], h, relocation, rel); break; /* Indirect .sdata2 relocation. */ case R_PPC_EMB_SDA2I16: BFD_ASSERT (htab->sdata[1].section != NULL); relocation = elf_finish_pointer_linker_section (input_bfd, &htab->sdata[1], h, relocation, rel); break; /* Handle the TOC16 reloc. We want to use the offset within the .got section, not the actual VMA. This is appropriate when generating an embedded ELF object, for which the .got section acts like the AIX .toc section. */ case R_PPC_TOC16: /* phony GOT16 relocations */ BFD_ASSERT (sec != NULL); BFD_ASSERT (bfd_is_und_section (sec) || strcmp (bfd_get_section_name (abfd, sec), ".got") == 0 || strcmp (bfd_get_section_name (abfd, sec), ".cgot") == 0); addend -= sec->output_section->vma + sec->output_offset + 0x8000; break; case R_PPC_PLTREL24: /* Relocation is to the entry for this symbol in the procedure linkage table. */ { struct plt_entry *ent = find_plt_ent (h, got2, addend); addend = 0; if (ent == NULL || htab->plt == NULL) { /* We didn't make a PLT entry for this symbol. This happens when statically linking PIC code, or when using -Bsymbolic. */ break; } unresolved_reloc = FALSE; if (htab->plt_type == PLT_NEW) relocation = (htab->glink->output_section->vma + htab->glink->output_offset + ent->glink_offset); else relocation = (htab->plt->output_section->vma + htab->plt->output_offset + ent->plt.offset); } break; /* Relocate against _SDA_BASE_. */ case R_PPC_SDAREL16: { const char *name; struct elf_link_hash_entry *sh; BFD_ASSERT (sec != NULL); name = bfd_get_section_name (abfd, sec->output_section); if (! ((CONST_STRNEQ (name, ".sdata") && (name[6] == 0 || name[6] == '.')) || (CONST_STRNEQ (name, ".sbss") && (name[5] == 0 || name[5] == '.')))) { (*_bfd_error_handler) (_("%B: the target (%s) of a %s relocation is " "in the wrong output section (%s)"), input_bfd, sym_name, howto->name, name); } sh = htab->sdata[0].sym; addend -= (sh->root.u.def.value + sh->root.u.def.section->output_offset + sh->root.u.def.section->output_section->vma); } break; /* Relocate against _SDA2_BASE_. */ case R_PPC_EMB_SDA2REL: { const char *name; struct elf_link_hash_entry *sh; BFD_ASSERT (sec != NULL); name = bfd_get_section_name (abfd, sec->output_section); if (! (CONST_STRNEQ (name, ".sdata2") || CONST_STRNEQ (name, ".sbss2"))) { (*_bfd_error_handler) (_("%B: the target (%s) of a %s relocation is " "in the wrong output section (%s)"), input_bfd, sym_name, howto->name, name); bfd_set_error (bfd_error_bad_value); ret = FALSE; continue; } sh = htab->sdata[1].sym; addend -= (sh->root.u.def.value + sh->root.u.def.section->output_offset + sh->root.u.def.section->output_section->vma); } break; /* Relocate against either _SDA_BASE_, _SDA2_BASE_, or 0. */ case R_PPC_EMB_SDA21: case R_PPC_EMB_RELSDA: { const char *name; int reg; struct elf_link_hash_entry *sh; BFD_ASSERT (sec != NULL); name = bfd_get_section_name (abfd, sec->output_section); if (((CONST_STRNEQ (name, ".sdata") && (name[6] == 0 || name[6] == '.')) || (CONST_STRNEQ (name, ".sbss") && (name[5] == 0 || name[5] == '.')))) { reg = 13; sh = htab->sdata[0].sym; addend -= (sh->root.u.def.value + sh->root.u.def.section->output_offset + sh->root.u.def.section->output_section->vma); } else if (CONST_STRNEQ (name, ".sdata2") || CONST_STRNEQ (name, ".sbss2")) { reg = 2; sh = htab->sdata[1].sym; addend -= (sh->root.u.def.value + sh->root.u.def.section->output_offset + sh->root.u.def.section->output_section->vma); } else if (strcmp (name, ".PPC.EMB.sdata0") == 0 || strcmp (name, ".PPC.EMB.sbss0") == 0) { reg = 0; } else { (*_bfd_error_handler) (_("%B: the target (%s) of a %s relocation is " "in the wrong output section (%s)"), input_bfd, sym_name, howto->name, name); bfd_set_error (bfd_error_bad_value); ret = FALSE; continue; } if (r_type == R_PPC_EMB_SDA21) { /* fill in register field */ insn = bfd_get_32 (output_bfd, contents + rel->r_offset); insn = (insn & ~RA_REGISTER_MASK) | (reg << RA_REGISTER_SHIFT); bfd_put_32 (output_bfd, insn, contents + rel->r_offset); } } break; /* Relocate against the beginning of the section. */ case R_PPC_SECTOFF: case R_PPC_SECTOFF_LO: case R_PPC_SECTOFF_HI: case R_PPC_SECTOFF_HA: BFD_ASSERT (sec != NULL); addend -= sec->output_section->vma; break; /* Negative relocations. */ case R_PPC_EMB_NADDR32: case R_PPC_EMB_NADDR16: case R_PPC_EMB_NADDR16_LO: case R_PPC_EMB_NADDR16_HI: case R_PPC_EMB_NADDR16_HA: addend -= 2 * relocation; break; case R_PPC_COPY: case R_PPC_GLOB_DAT: case R_PPC_JMP_SLOT: case R_PPC_RELATIVE: case R_PPC_PLT32: case R_PPC_PLTREL32: case R_PPC_PLT16_LO: case R_PPC_PLT16_HI: case R_PPC_PLT16_HA: case R_PPC_ADDR30: case R_PPC_EMB_RELSEC16: case R_PPC_EMB_RELST_LO: case R_PPC_EMB_RELST_HI: case R_PPC_EMB_RELST_HA: case R_PPC_EMB_BIT_FLD: (*_bfd_error_handler) (_("%B: relocation %s is not yet supported for symbol %s."), input_bfd, howto->name, sym_name); bfd_set_error (bfd_error_invalid_operation); ret = FALSE; continue; } /* Do any further special processing. */ switch (r_type) { default: break; case R_PPC_ADDR16_HA: case R_PPC_REL16_HA: case R_PPC_SECTOFF_HA: case R_PPC_TPREL16_HA: case R_PPC_DTPREL16_HA: case R_PPC_EMB_NADDR16_HA: case R_PPC_EMB_RELST_HA: /* It's just possible that this symbol is a weak symbol that's not actually defined anywhere. In that case, 'sec' would be NULL, and we should leave the symbol alone (it will be set to zero elsewhere in the link). */ if (sec == NULL) break; /* Fall thru */ case R_PPC_PLT16_HA: case R_PPC_GOT16_HA: case R_PPC_GOT_TLSGD16_HA: case R_PPC_GOT_TLSLD16_HA: case R_PPC_GOT_TPREL16_HA: case R_PPC_GOT_DTPREL16_HA: /* Add 0x10000 if sign bit in 0:15 is set. Bits 0:15 are not used. */ addend += 0x8000; break; } #ifdef DEBUG fprintf (stderr, "\ttype = %s (%d), name = %s, symbol index = %ld, " "offset = %ld, addend = %ld\n", howto->name, (int) r_type, sym_name, r_symndx, (long) rel->r_offset, (long) addend); #endif if (unresolved_reloc && !((input_section->flags & SEC_DEBUGGING) != 0 && h->def_dynamic)) { (*_bfd_error_handler) (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"), input_bfd, input_section, (long) rel->r_offset, howto->name, sym_name); ret = FALSE; } r = _bfd_final_link_relocate (howto, input_bfd, input_section, contents, rel->r_offset, relocation, addend); if (r != bfd_reloc_ok) { if (r == bfd_reloc_overflow) { if (warned) continue; if (h != NULL && h->root.type == bfd_link_hash_undefweak && howto->pc_relative) { /* Assume this is a call protected by other code that detect the symbol is undefined. If this is the case, we can safely ignore the overflow. If not, the program is hosed anyway, and a little warning isn't going to help. */ continue; } if (! (*info->callbacks->reloc_overflow) (info, (h ? &h->root : NULL), sym_name, howto->name, rel->r_addend, input_bfd, input_section, rel->r_offset)) return FALSE; } else { (*_bfd_error_handler) (_("%B(%A+0x%lx): %s reloc against `%s': error %d"), input_bfd, input_section, (long) rel->r_offset, howto->name, sym_name, (int) r); ret = FALSE; } } } #ifdef DEBUG fprintf (stderr, "\n"); #endif return ret; } #define PPC_LO(v) ((v) & 0xffff) #define PPC_HI(v) (((v) >> 16) & 0xffff) #define PPC_HA(v) PPC_HI ((v) + 0x8000) /* Finish up dynamic symbol handling. We set the contents of various dynamic sections here. */ static bfd_boolean ppc_elf_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info, struct elf_link_hash_entry *h, Elf_Internal_Sym *sym) { struct ppc_elf_link_hash_table *htab; struct plt_entry *ent; bfd_boolean doneone; #ifdef DEBUG fprintf (stderr, "ppc_elf_finish_dynamic_symbol called for %s", h->root.root.string); #endif htab = ppc_elf_hash_table (info); BFD_ASSERT (htab->elf.dynobj != NULL); doneone = FALSE; for (ent = h->plt.plist; ent != NULL; ent = ent->next) if (ent->plt.offset != (bfd_vma) -1) { if (!doneone) { Elf_Internal_Rela rela; bfd_byte *loc; bfd_vma reloc_index; if (htab->plt_type == PLT_NEW) reloc_index = ent->plt.offset / 4; else { reloc_index = ((ent->plt.offset - htab->plt_initial_entry_size) / htab->plt_slot_size); if (reloc_index > PLT_NUM_SINGLE_ENTRIES && htab->plt_type == PLT_OLD) reloc_index -= (reloc_index - PLT_NUM_SINGLE_ENTRIES) / 2; } /* This symbol has an entry in the procedure linkage table. Set it up. */ if (htab->plt_type == PLT_VXWORKS) { bfd_vma got_offset; const bfd_vma *plt_entry; /* The first three entries in .got.plt are reserved. */ got_offset = (reloc_index + 3) * 4; /* Use the right PLT. */ plt_entry = info->shared ? ppc_elf_vxworks_pic_plt_entry : ppc_elf_vxworks_plt_entry; /* Fill in the .plt on VxWorks. */ if (info->shared) { bfd_vma got_offset_hi = (got_offset >> 16) + ((got_offset & 0x8000) >> 15); bfd_put_32 (output_bfd, plt_entry[0] | (got_offset_hi & 0xffff), htab->plt->contents + ent->plt.offset + 0); bfd_put_32 (output_bfd, plt_entry[1] | (got_offset & 0xffff), htab->plt->contents + ent->plt.offset + 4); } else { bfd_vma got_loc = (got_offset + htab->elf.hgot->root.u.def.value + htab->elf.hgot->root.u.def.section->output_offset + htab->elf.hgot->root.u.def.section->output_section->vma); bfd_vma got_loc_hi = (got_loc >> 16) + ((got_loc & 0x8000) >> 15); bfd_put_32 (output_bfd, plt_entry[0] | (got_loc_hi & 0xffff), htab->plt->contents + ent->plt.offset + 0); bfd_put_32 (output_bfd, plt_entry[1] | (got_loc & 0xffff), htab->plt->contents + ent->plt.offset + 4); } bfd_put_32 (output_bfd, plt_entry[2], htab->plt->contents + ent->plt.offset + 8); bfd_put_32 (output_bfd, plt_entry[3], htab->plt->contents + ent->plt.offset + 12); /* This instruction is an immediate load. The value loaded is the byte offset of the R_PPC_JMP_SLOT relocation from the start of the .rela.plt section. The value is stored in the low-order 16 bits of the load instruction. */ /* NOTE: It appears that this is now an index rather than a prescaled offset. */ bfd_put_32 (output_bfd, plt_entry[4] | reloc_index, htab->plt->contents + ent->plt.offset + 16); /* This instruction is a PC-relative branch whose target is the start of the PLT section. The address of this branch instruction is 20 bytes beyond the start of this PLT entry. The address is encoded in bits 6-29, inclusive. The value stored is right-shifted by two bits, permitting a 26-bit offset. */ bfd_put_32 (output_bfd, (plt_entry[5] | (-(ent->plt.offset + 20) & 0x03fffffc)), htab->plt->contents + ent->plt.offset + 20); bfd_put_32 (output_bfd, plt_entry[6], htab->plt->contents + ent->plt.offset + 24); bfd_put_32 (output_bfd, plt_entry[7], htab->plt->contents + ent->plt.offset + 28); /* Fill in the GOT entry corresponding to this PLT slot with the address immediately after the the "bctr" instruction in this PLT entry. */ bfd_put_32 (output_bfd, (htab->plt->output_section->vma + htab->plt->output_offset + ent->plt.offset + 16), htab->sgotplt->contents + got_offset); if (!info->shared) { /* Fill in a couple of entries in .rela.plt.unloaded. */ loc = htab->srelplt2->contents + ((VXWORKS_PLTRESOLVE_RELOCS + reloc_index * VXWORKS_PLT_NON_JMP_SLOT_RELOCS) * sizeof (Elf32_External_Rela)); /* Provide the @ha relocation for the first instruction. */ rela.r_offset = (htab->plt->output_section->vma + htab->plt->output_offset + ent->plt.offset + 2); rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_PPC_ADDR16_HA); rela.r_addend = got_offset; bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); loc += sizeof (Elf32_External_Rela); /* Provide the @l relocation for the second instruction. */ rela.r_offset = (htab->plt->output_section->vma + htab->plt->output_offset + ent->plt.offset + 6); rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_PPC_ADDR16_LO); rela.r_addend = got_offset; bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); loc += sizeof (Elf32_External_Rela); /* Provide a relocation for the GOT entry corresponding to this PLT slot. Point it at the middle of the .plt entry. */ rela.r_offset = (htab->sgotplt->output_section->vma + htab->sgotplt->output_offset + got_offset); rela.r_info = ELF32_R_INFO (htab->elf.hplt->indx, R_PPC_ADDR32); rela.r_addend = ent->plt.offset + 16; bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); } /* VxWorks uses non-standard semantics for R_PPC_JMP_SLOT. In particular, the offset for the relocation is not the address of the PLT entry for this function, as specified by the ABI. Instead, the offset is set to the address of the GOT slot for this function. See EABI 4.4.4.1. */ rela.r_offset = (htab->sgotplt->output_section->vma + htab->sgotplt->output_offset + got_offset); } else { rela.r_offset = (htab->plt->output_section->vma + htab->plt->output_offset + ent->plt.offset); if (htab->plt_type == PLT_OLD) { /* We don't need to fill in the .plt. The ppc dynamic linker will fill it in. */ } else { bfd_vma val = (htab->glink_pltresolve + ent->plt.offset + htab->glink->output_section->vma + htab->glink->output_offset); bfd_put_32 (output_bfd, val, htab->plt->contents + ent->plt.offset); } } /* Fill in the entry in the .rela.plt section. */ rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_JMP_SLOT); rela.r_addend = 0; loc = (htab->relplt->contents + reloc_index * sizeof (Elf32_External_Rela)); bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); if (!h->def_regular) { /* Mark the symbol as undefined, rather than as defined in the .plt section. Leave the value alone. */ sym->st_shndx = SHN_UNDEF; /* If the symbol is weak, we do need to clear the value. Otherwise, the PLT entry would provide a definition for the symbol even if the symbol wasn't defined anywhere, and so the symbol would never be NULL. */ if (!h->ref_regular_nonweak) sym->st_value = 0; } doneone = TRUE; } if (htab->plt_type == PLT_NEW) { bfd_vma plt; unsigned char *p; plt = (ent->plt.offset + htab->plt->output_section->vma + htab->plt->output_offset); p = (unsigned char *) htab->glink->contents + ent->glink_offset; if (info->shared || info->pie) { bfd_vma got = 0; if (ent->addend >= 32768) got = (ent->addend + ent->sec->output_section->vma + ent->sec->output_offset); else if (htab->elf.hgot != NULL) got = (htab->elf.hgot->root.u.def.value + htab->elf.hgot->root.u.def.section->output_section->vma + htab->elf.hgot->root.u.def.section->output_offset); plt -= got; if (plt + 0x8000 < 0x10000) { bfd_put_32 (output_bfd, LWZ_11_30 + PPC_LO (plt), p); p += 4; bfd_put_32 (output_bfd, MTCTR_11, p); p += 4; bfd_put_32 (output_bfd, BCTR, p); p += 4; bfd_put_32 (output_bfd, NOP, p); p += 4; } else { bfd_put_32 (output_bfd, ADDIS_11_30 + PPC_HA (plt), p); p += 4; bfd_put_32 (output_bfd, LWZ_11_11 + PPC_LO (plt), p); p += 4; bfd_put_32 (output_bfd, MTCTR_11, p); p += 4; bfd_put_32 (output_bfd, BCTR, p); p += 4; } } else { bfd_put_32 (output_bfd, LIS_11 + PPC_HA (plt), p); p += 4; bfd_put_32 (output_bfd, LWZ_11_11 + PPC_LO (plt), p); p += 4; bfd_put_32 (output_bfd, MTCTR_11, p); p += 4; bfd_put_32 (output_bfd, BCTR, p); p += 4; /* We only need one non-PIC glink stub. */ break; } } else break; } if (h->needs_copy) { asection *s; Elf_Internal_Rela rela; bfd_byte *loc; /* This symbols needs a copy reloc. Set it up. */ #ifdef DEBUG fprintf (stderr, ", copy"); #endif BFD_ASSERT (h->dynindx != -1); if (ppc_elf_hash_entry (h)->has_sda_refs) s = htab->relsbss; else s = htab->relbss; BFD_ASSERT (s != NULL); rela.r_offset = (h->root.u.def.value + h->root.u.def.section->output_section->vma + h->root.u.def.section->output_offset); rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_COPY); rela.r_addend = 0; loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela); bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); } #ifdef DEBUG fprintf (stderr, "\n"); #endif /* Mark some specially defined symbols as absolute. */ if (strcmp (h->root.root.string, "_DYNAMIC") == 0 || (!htab->is_vxworks && (h == htab->elf.hgot || strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0))) sym->st_shndx = SHN_ABS; return TRUE; } static enum elf_reloc_type_class ppc_elf_reloc_type_class (const Elf_Internal_Rela *rela) { switch (ELF32_R_TYPE (rela->r_info)) { case R_PPC_RELATIVE: return reloc_class_relative; case R_PPC_REL24: case R_PPC_ADDR24: case R_PPC_JMP_SLOT: return reloc_class_plt; case R_PPC_COPY: return reloc_class_copy; default: return reloc_class_normal; } } /* Finish up the dynamic sections. */ static bfd_boolean ppc_elf_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) { asection *sdyn; asection *splt; struct ppc_elf_link_hash_table *htab; bfd_vma got; bfd * dynobj; #ifdef DEBUG fprintf (stderr, "ppc_elf_finish_dynamic_sections called\n"); #endif htab = ppc_elf_hash_table (info); dynobj = elf_hash_table (info)->dynobj; sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); if (htab->is_vxworks) splt = bfd_get_section_by_name (dynobj, ".plt"); else splt = NULL; got = 0; if (htab->elf.hgot != NULL) got = (htab->elf.hgot->root.u.def.value + htab->elf.hgot->root.u.def.section->output_section->vma + htab->elf.hgot->root.u.def.section->output_offset); if (htab->elf.dynamic_sections_created) { Elf32_External_Dyn *dyncon, *dynconend; BFD_ASSERT (htab->plt != NULL && sdyn != NULL); dyncon = (Elf32_External_Dyn *) sdyn->contents; dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size); for (; dyncon < dynconend; dyncon++) { Elf_Internal_Dyn dyn; asection *s; bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn); switch (dyn.d_tag) { case DT_PLTGOT: if (htab->is_vxworks) s = htab->sgotplt; else s = htab->plt; dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; break; case DT_PLTRELSZ: dyn.d_un.d_val = htab->relplt->size; break; case DT_JMPREL: s = htab->relplt; dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; break; case DT_PPC_GOT: dyn.d_un.d_ptr = got; break; case DT_RELASZ: if (htab->is_vxworks) { if (htab->relplt) dyn.d_un.d_ptr -= htab->relplt->size; break; } continue; default: continue; } bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); } } /* Add a blrl instruction at _GLOBAL_OFFSET_TABLE_-4 so that a function can easily find the address of the _GLOBAL_OFFSET_TABLE_. */ if (htab->got != NULL) { unsigned char *p = htab->got->contents; bfd_vma val; p += htab->elf.hgot->root.u.def.value; if (htab->plt_type == PLT_OLD) bfd_put_32 (output_bfd, 0x4e800021 /* blrl */, p - 4); val = 0; if (sdyn != NULL) val = sdyn->output_section->vma + sdyn->output_offset; bfd_put_32 (output_bfd, val, p); elf_section_data (htab->got->output_section)->this_hdr.sh_entsize = 4; } /* Fill in the first entry in the VxWorks procedure linkage table. */ if (splt && splt->size > 0) { /* Use the right PLT. */ static const bfd_vma *plt_entry = NULL; plt_entry = info->shared ? ppc_elf_vxworks_pic_plt0_entry : ppc_elf_vxworks_plt0_entry; if (!info->shared) { bfd_vma got_value = (htab->elf.hgot->root.u.def.section->output_section->vma + htab->elf.hgot->root.u.def.section->output_offset + htab->elf.hgot->root.u.def.value); bfd_vma got_hi = (got_value >> 16) + ((got_value & 0x8000) >> 15); bfd_put_32 (output_bfd, plt_entry[0] | (got_hi & 0xffff), splt->contents + 0); bfd_put_32 (output_bfd, plt_entry[1] | (got_value & 0xffff), splt->contents + 4); } else { bfd_put_32 (output_bfd, plt_entry[0], splt->contents + 0); bfd_put_32 (output_bfd, plt_entry[1], splt->contents + 4); } bfd_put_32 (output_bfd, plt_entry[2], splt->contents + 8); bfd_put_32 (output_bfd, plt_entry[3], splt->contents + 12); bfd_put_32 (output_bfd, plt_entry[4], splt->contents + 16); bfd_put_32 (output_bfd, plt_entry[5], splt->contents + 20); bfd_put_32 (output_bfd, plt_entry[6], splt->contents + 24); bfd_put_32 (output_bfd, plt_entry[7], splt->contents + 28); if (! info->shared) { Elf_Internal_Rela rela; bfd_byte *loc; loc = htab->srelplt2->contents; /* Output the @ha relocation for the first instruction. */ rela.r_offset = (htab->plt->output_section->vma + htab->plt->output_offset + 2); rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_PPC_ADDR16_HA); rela.r_addend = 0; bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); loc += sizeof (Elf32_External_Rela); /* Output the @l relocation for the second instruction. */ rela.r_offset = (htab->plt->output_section->vma + htab->plt->output_offset + 6); rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_PPC_ADDR16_LO); rela.r_addend = 0; 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_reloc_in (output_bfd, loc, &rel); rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_PPC_ADDR16_HA); bfd_elf32_swap_reloc_out (output_bfd, &rel, loc); loc += sizeof (Elf32_External_Rela); bfd_elf32_swap_reloc_in (output_bfd, loc, &rel); rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_PPC_ADDR16_LO); bfd_elf32_swap_reloc_out (output_bfd, &rel, loc); loc += sizeof (Elf32_External_Rela); bfd_elf32_swap_reloc_in (output_bfd, loc, &rel); rel.r_info = ELF32_R_INFO (htab->elf.hplt->indx, R_PPC_ADDR32); bfd_elf32_swap_reloc_out (output_bfd, &rel, loc); loc += sizeof (Elf32_External_Rela); } } } if (htab->glink != NULL && htab->glink->contents != NULL) { unsigned char *p; unsigned char *endp; bfd_vma res0; unsigned int i; /* * PIC glink code is the following: * * # ith PLT code stub. * addis 11,30,(plt+(i-1)*4-got)@ha * lwz 11,(plt+(i-1)*4-got)@l(11) * mtctr 11 * bctr * * # A table of branches, one for each plt entry. * # The idea is that the plt call stub loads ctr (and r11) with these * # addresses, so (r11 - res_0) gives the plt index * 4. * res_0: b PLTresolve * res_1: b PLTresolve * . * # Some number of entries towards the end can be nops * res_n_m3: nop * res_n_m2: nop * res_n_m1: * * PLTresolve: * addis 11,11,(1f-res_0)@ha * mflr 0 * bcl 20,31,1f * 1: addi 11,11,(1b-res_0)@l * mflr 12 * mtlr 0 * sub 11,11,12 # r11 = index * 4 * addis 12,12,(got+4-1b)@ha * lwz 0,(got+4-1b)@l(12) # got[1] address of dl_runtime_resolve * lwz 12,(got+8-1b)@l(12) # got[2] contains the map address * mtctr 0 * add 0,11,11 * add 11,0,11 # r11 = index * 12 = reloc offset. * bctr */ static const unsigned int pic_plt_resolve[] = { ADDIS_11_11, MFLR_0, BCL_20_31, ADDI_11_11, MFLR_12, MTLR_0, SUB_11_11_12, ADDIS_12_12, LWZ_0_12, LWZ_12_12, MTCTR_0, ADD_0_11_11, ADD_11_0_11, BCTR, NOP, NOP }; static const unsigned int plt_resolve[] = { LIS_12, ADDIS_11_11, LWZ_0_12, ADDI_11_11, MTCTR_0, ADD_0_11_11, LWZ_12_12, ADD_11_0_11, BCTR, NOP, NOP, NOP, NOP, NOP, NOP, NOP }; if (ARRAY_SIZE (pic_plt_resolve) != GLINK_PLTRESOLVE / 4) abort (); if (ARRAY_SIZE (plt_resolve) != GLINK_PLTRESOLVE / 4) abort (); /* Build the branch table, one for each plt entry (less one), and perhaps some padding. */ p = htab->glink->contents; p += htab->glink_pltresolve; endp = htab->glink->contents; endp += htab->glink->size - GLINK_PLTRESOLVE; while (p < endp - 8 * 4) { bfd_put_32 (output_bfd, B + endp - p, p); p += 4; } while (p < endp) { bfd_put_32 (output_bfd, NOP, p); p += 4; } res0 = (htab->glink_pltresolve + htab->glink->output_section->vma + htab->glink->output_offset); /* Last comes the PLTresolve stub. */ if (info->shared || info->pie) { bfd_vma bcl; for (i = 0; i < ARRAY_SIZE (pic_plt_resolve); i++) { bfd_put_32 (output_bfd, pic_plt_resolve[i], p); p += 4; } p -= 4 * ARRAY_SIZE (pic_plt_resolve); bcl = (htab->glink->size - GLINK_PLTRESOLVE + 3*4 + htab->glink->output_section->vma + htab->glink->output_offset); bfd_put_32 (output_bfd, ADDIS_11_11 + PPC_HA (bcl - res0), p + 0*4); bfd_put_32 (output_bfd, ADDI_11_11 + PPC_LO (bcl - res0), p + 3*4); bfd_put_32 (output_bfd, ADDIS_12_12 + PPC_HA (got + 4 - bcl), p + 7*4); if (PPC_HA (got + 4 - bcl) == PPC_HA (got + 8 - bcl)) { bfd_put_32 (output_bfd, LWZ_0_12 + PPC_LO (got + 4 - bcl), p + 8*4); bfd_put_32 (output_bfd, LWZ_12_12 + PPC_LO (got + 8 - bcl), p + 9*4); } else { bfd_put_32 (output_bfd, LWZU_0_12 + PPC_LO (got + 4 - bcl), p + 8*4); bfd_put_32 (output_bfd, LWZ_12_12 + 4, p + 9*4); } } else { for (i = 0; i < ARRAY_SIZE (plt_resolve); i++) { bfd_put_32 (output_bfd, plt_resolve[i], p); p += 4; } p -= 4 * ARRAY_SIZE (plt_resolve); bfd_put_32 (output_bfd, LIS_12 + PPC_HA (got + 4), p + 0*4); bfd_put_32 (output_bfd, ADDIS_11_11 + PPC_HA (-res0), p + 1*4); bfd_put_32 (output_bfd, ADDI_11_11 + PPC_LO (-res0), p + 3*4); if (PPC_HA (got + 4) == PPC_HA (got + 8)) { bfd_put_32 (output_bfd, LWZ_0_12 + PPC_LO (got + 4), p + 2*4); bfd_put_32 (output_bfd, LWZ_12_12 + PPC_LO (got + 8), p + 6*4); } else { bfd_put_32 (output_bfd, LWZU_0_12 + PPC_LO (got + 4), p + 2*4); bfd_put_32 (output_bfd, LWZ_12_12 + 4, p + 6*4); } } } return TRUE; } #define TARGET_LITTLE_SYM bfd_elf32_powerpcle_vec #define TARGET_LITTLE_NAME "elf32-powerpcle" #define TARGET_BIG_SYM bfd_elf32_powerpc_vec #define TARGET_BIG_NAME "elf32-powerpc-freebsd" #define ELF_ARCH bfd_arch_powerpc #define ELF_MACHINE_CODE EM_PPC #ifdef __QNXTARGET__ #define ELF_MAXPAGESIZE 0x1000 #else #define ELF_MAXPAGESIZE 0x10000 #endif #define ELF_MINPAGESIZE 0x1000 #define ELF_COMMONPAGESIZE 0x1000 #define elf_info_to_howto ppc_elf_info_to_howto #ifdef EM_CYGNUS_POWERPC #define ELF_MACHINE_ALT1 EM_CYGNUS_POWERPC #endif #ifdef EM_PPC_OLD #define ELF_MACHINE_ALT2 EM_PPC_OLD #endif #define elf_backend_plt_not_loaded 1 #define elf_backend_can_gc_sections 1 #define elf_backend_can_refcount 1 #define elf_backend_rela_normal 1 #define bfd_elf32_mkobject ppc_elf_mkobject #define bfd_elf32_bfd_merge_private_bfd_data ppc_elf_merge_private_bfd_data #define bfd_elf32_bfd_relax_section ppc_elf_relax_section #define bfd_elf32_bfd_reloc_type_lookup ppc_elf_reloc_type_lookup #define bfd_elf32_bfd_reloc_name_lookup ppc_elf_reloc_name_lookup #define bfd_elf32_bfd_set_private_flags ppc_elf_set_private_flags #define bfd_elf32_bfd_link_hash_table_create ppc_elf_link_hash_table_create #define elf_backend_object_p ppc_elf_object_p #define elf_backend_gc_mark_hook ppc_elf_gc_mark_hook #define elf_backend_gc_sweep_hook ppc_elf_gc_sweep_hook #define elf_backend_section_from_shdr ppc_elf_section_from_shdr #define elf_backend_relocate_section ppc_elf_relocate_section #define elf_backend_create_dynamic_sections ppc_elf_create_dynamic_sections #define elf_backend_check_relocs ppc_elf_check_relocs #define elf_backend_copy_indirect_symbol ppc_elf_copy_indirect_symbol #define elf_backend_adjust_dynamic_symbol ppc_elf_adjust_dynamic_symbol #define elf_backend_add_symbol_hook ppc_elf_add_symbol_hook #define elf_backend_size_dynamic_sections ppc_elf_size_dynamic_sections #define elf_backend_finish_dynamic_symbol ppc_elf_finish_dynamic_symbol #define elf_backend_finish_dynamic_sections ppc_elf_finish_dynamic_sections #define elf_backend_fake_sections ppc_elf_fake_sections #define elf_backend_additional_program_headers ppc_elf_additional_program_headers #define elf_backend_grok_prstatus ppc_elf_grok_prstatus #define elf_backend_grok_psinfo ppc_elf_grok_psinfo #define elf_backend_write_core_note ppc_elf_write_core_note #define elf_backend_reloc_type_class ppc_elf_reloc_type_class #define elf_backend_begin_write_processing ppc_elf_begin_write_processing #define elf_backend_final_write_processing ppc_elf_final_write_processing #define elf_backend_write_section ppc_elf_write_section #define elf_backend_get_sec_type_attr ppc_elf_get_sec_type_attr #define elf_backend_plt_sym_val ppc_elf_plt_sym_val #define elf_backend_action_discarded ppc_elf_action_discarded #define elf_backend_init_index_section _bfd_elf_init_1_index_section #include "elf32-target.h" /* VxWorks Target */ #undef TARGET_LITTLE_SYM #undef TARGET_LITTLE_NAME #undef TARGET_BIG_SYM #define TARGET_BIG_SYM bfd_elf32_powerpc_vxworks_vec #undef TARGET_BIG_NAME #define TARGET_BIG_NAME "elf32-powerpc-vxworks" /* VxWorks uses the elf default section flags for .plt. */ static const struct bfd_elf_special_section * ppc_elf_vxworks_get_sec_type_attr (bfd *abfd ATTRIBUTE_UNUSED, asection *sec) { if (sec->name == NULL) return NULL; if (strcmp (sec->name, ".plt") == 0) return _bfd_elf_get_sec_type_attr (abfd, sec); return ppc_elf_get_sec_type_attr (abfd, sec); } /* Like ppc_elf_link_hash_table_create, but overrides appropriately for VxWorks. */ static struct bfd_link_hash_table * ppc_elf_vxworks_link_hash_table_create (bfd *abfd) { struct bfd_link_hash_table *ret; ret = ppc_elf_link_hash_table_create (abfd); if (ret) { struct ppc_elf_link_hash_table *htab = (struct ppc_elf_link_hash_table *)ret; htab->is_vxworks = 1; htab->plt_type = PLT_VXWORKS; htab->plt_entry_size = VXWORKS_PLT_ENTRY_SIZE; htab->plt_slot_size = VXWORKS_PLT_ENTRY_SIZE; htab->plt_initial_entry_size = VXWORKS_PLT_INITIAL_ENTRY_SIZE; } return ret; } /* Tweak magic VxWorks symbols as they are loaded. */ static bfd_boolean ppc_elf_vxworks_add_symbol_hook (bfd *abfd, struct bfd_link_info *info, Elf_Internal_Sym *sym, const char **namep ATTRIBUTE_UNUSED, flagword *flagsp ATTRIBUTE_UNUSED, asection **secp, bfd_vma *valp) { if (!elf_vxworks_add_symbol_hook(abfd, info, sym,namep, flagsp, secp, valp)) return FALSE; return ppc_elf_add_symbol_hook(abfd, info, sym,namep, flagsp, secp, valp); } static void ppc_elf_vxworks_final_write_processing (bfd *abfd, bfd_boolean linker) { ppc_elf_final_write_processing(abfd, linker); elf_vxworks_final_write_processing(abfd, linker); } /* On VxWorks, we emit relocations against _PROCEDURE_LINKAGE_TABLE_, so define it. */ #undef elf_backend_want_plt_sym #define elf_backend_want_plt_sym 1 #undef elf_backend_want_got_plt #define elf_backend_want_got_plt 1 #undef elf_backend_got_symbol_offset #define elf_backend_got_symbol_offset 0 #undef elf_backend_plt_not_loaded #define elf_backend_plt_not_loaded 0 #undef elf_backend_plt_readonly #define elf_backend_plt_readonly 1 #undef elf_backend_got_header_size #define elf_backend_got_header_size 12 #undef bfd_elf32_bfd_link_hash_table_create #define bfd_elf32_bfd_link_hash_table_create \ ppc_elf_vxworks_link_hash_table_create #undef elf_backend_add_symbol_hook #define elf_backend_add_symbol_hook \ ppc_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_final_write_processing #define elf_backend_final_write_processing \ ppc_elf_vxworks_final_write_processing #undef elf_backend_get_sec_type_attr #define elf_backend_get_sec_type_attr \ ppc_elf_vxworks_get_sec_type_attr #undef elf_backend_emit_relocs #define elf_backend_emit_relocs \ elf_vxworks_emit_relocs #undef elf32_bed #define elf32_bed ppc_elf_vxworks_bed #include "elf32-target.h" Index: head/contrib/binutils/bfd/elf64-ppc.c =================================================================== --- head/contrib/binutils/bfd/elf64-ppc.c (revision 275717) +++ head/contrib/binutils/bfd/elf64-ppc.c (revision 275718) @@ -1,11500 +1,11835 @@ /* PowerPC64-specific support for 64-bit ELF. Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. Written by Linus Nordberg, Swox AB , based on elf32-ppc.c by Ian Lance Taylor. Largely rewritten by Alan Modra This file is part of BFD, the Binary File Descriptor library. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ /* The 64-bit PowerPC ELF ABI may be found at http://www.linuxbase.org/spec/ELF/ppc64/PPC-elf64abi.txt, and http://www.linuxbase.org/spec/ELF/ppc64/spec/book1.html */ #include "sysdep.h" #include #include "bfd.h" #include "bfdlink.h" #include "libbfd.h" #include "elf-bfd.h" #include "elf/ppc64.h" #include "elf64-ppc.h" static bfd_reloc_status_type ppc64_elf_ha_reloc (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); static bfd_reloc_status_type ppc64_elf_branch_reloc (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); static bfd_reloc_status_type ppc64_elf_brtaken_reloc (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); static bfd_reloc_status_type ppc64_elf_sectoff_reloc (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); static bfd_reloc_status_type ppc64_elf_sectoff_ha_reloc (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); static bfd_reloc_status_type ppc64_elf_toc_reloc (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); static bfd_reloc_status_type ppc64_elf_toc_ha_reloc (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); static bfd_reloc_status_type ppc64_elf_toc64_reloc (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); static bfd_reloc_status_type ppc64_elf_unhandled_reloc (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); static bfd_vma opd_entry_value (asection *, bfd_vma, asection **, bfd_vma *); #define TARGET_LITTLE_SYM bfd_elf64_powerpcle_vec #define TARGET_LITTLE_NAME "elf64-powerpcle" #define TARGET_BIG_SYM bfd_elf64_powerpc_vec #define TARGET_BIG_NAME "elf64-powerpc-freebsd" #define ELF_ARCH bfd_arch_powerpc #define ELF_MACHINE_CODE EM_PPC64 #define ELF_MAXPAGESIZE 0x10000 #define ELF_COMMONPAGESIZE 0x1000 #define elf_info_to_howto ppc64_elf_info_to_howto #define elf_backend_want_got_sym 0 #define elf_backend_want_plt_sym 0 #define elf_backend_plt_alignment 3 #define elf_backend_plt_not_loaded 1 #define elf_backend_got_header_size 8 #define elf_backend_can_gc_sections 1 #define elf_backend_can_refcount 1 #define elf_backend_rela_normal 1 #define elf_backend_default_execstack 0 #define bfd_elf64_mkobject ppc64_elf_mkobject #define bfd_elf64_bfd_reloc_type_lookup ppc64_elf_reloc_type_lookup #define bfd_elf64_bfd_reloc_name_lookup ppc64_elf_reloc_name_lookup #define bfd_elf64_bfd_merge_private_bfd_data ppc64_elf_merge_private_bfd_data #define bfd_elf64_new_section_hook ppc64_elf_new_section_hook #define bfd_elf64_bfd_link_hash_table_create ppc64_elf_link_hash_table_create #define bfd_elf64_bfd_link_hash_table_free ppc64_elf_link_hash_table_free #define bfd_elf64_get_synthetic_symtab ppc64_elf_get_synthetic_symtab #define elf_backend_object_p ppc64_elf_object_p #define elf_backend_grok_prstatus ppc64_elf_grok_prstatus #define elf_backend_grok_psinfo ppc64_elf_grok_psinfo #define elf_backend_write_core_note ppc64_elf_write_core_note #define elf_backend_create_dynamic_sections ppc64_elf_create_dynamic_sections #define elf_backend_copy_indirect_symbol ppc64_elf_copy_indirect_symbol #define elf_backend_add_symbol_hook ppc64_elf_add_symbol_hook #define elf_backend_check_directives ppc64_elf_check_directives #define elf_backend_as_needed_cleanup ppc64_elf_as_needed_cleanup #define elf_backend_archive_symbol_lookup ppc64_elf_archive_symbol_lookup #define elf_backend_check_relocs ppc64_elf_check_relocs #define elf_backend_gc_mark_dynamic_ref ppc64_elf_gc_mark_dynamic_ref #define elf_backend_gc_mark_hook ppc64_elf_gc_mark_hook #define elf_backend_gc_sweep_hook ppc64_elf_gc_sweep_hook #define elf_backend_adjust_dynamic_symbol ppc64_elf_adjust_dynamic_symbol #define elf_backend_hide_symbol ppc64_elf_hide_symbol #define elf_backend_always_size_sections ppc64_elf_func_desc_adjust #define elf_backend_size_dynamic_sections ppc64_elf_size_dynamic_sections #define elf_backend_init_index_section _bfd_elf_init_2_index_sections #define elf_backend_action_discarded ppc64_elf_action_discarded #define elf_backend_relocate_section ppc64_elf_relocate_section #define elf_backend_finish_dynamic_symbol ppc64_elf_finish_dynamic_symbol #define elf_backend_reloc_type_class ppc64_elf_reloc_type_class #define elf_backend_finish_dynamic_sections ppc64_elf_finish_dynamic_sections #define elf_backend_link_output_symbol_hook ppc64_elf_output_symbol_hook #define elf_backend_special_sections ppc64_elf_special_sections /* The name of the dynamic interpreter. This is put in the .interp section. */ #define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1" /* The size in bytes of an entry in the procedure linkage table. */ #define PLT_ENTRY_SIZE 24 /* The initial size of the plt reserved for the dynamic linker. */ #define PLT_INITIAL_ENTRY_SIZE PLT_ENTRY_SIZE /* TOC base pointers offset from start of TOC. */ #define TOC_BASE_OFF 0x8000 /* Offset of tp and dtp pointers from start of TLS block. */ #define TP_OFFSET 0x7000 #define DTP_OFFSET 0x8000 /* .plt call stub instructions. The normal stub is like this, but sometimes the .plt entry crosses a 64k boundary and we need to - insert an addis to adjust r12. */ + insert an addi to adjust r12. */ #define PLT_CALL_STUB_SIZE (7*4) #define ADDIS_R12_R2 0x3d820000 /* addis %r12,%r2,xxx@ha */ #define STD_R2_40R1 0xf8410028 /* std %r2,40(%r1) */ #define LD_R11_0R12 0xe96c0000 /* ld %r11,xxx+0@l(%r12) */ -#define LD_R2_0R12 0xe84c0000 /* ld %r2,xxx+8@l(%r12) */ #define MTCTR_R11 0x7d6903a6 /* mtctr %r11 */ +#define LD_R2_0R12 0xe84c0000 /* ld %r2,xxx+8@l(%r12) */ /* ld %r11,xxx+16@l(%r12) */ #define BCTR 0x4e800420 /* bctr */ #define ADDIS_R12_R12 0x3d8c0000 /* addis %r12,%r12,off@ha */ +#define ADDI_R12_R12 0x398c0000 /* addi %r12,%r12,off@l */ #define ADDIS_R2_R2 0x3c420000 /* addis %r2,%r2,off@ha */ #define ADDI_R2_R2 0x38420000 /* addi %r2,%r2,off@l */ +#define LD_R11_0R2 0xe9620000 /* ld %r11,xxx+0(%r2) */ +#define LD_R2_0R2 0xe8420000 /* ld %r2,xxx+0(%r2) */ + #define LD_R2_40R1 0xe8410028 /* ld %r2,40(%r1) */ /* glink call stub instructions. We enter with the index in R0. */ #define GLINK_CALL_STUB_SIZE (16*4) /* 0: */ /* .quad plt0-1f */ /* __glink: */ #define MFLR_R12 0x7d8802a6 /* mflr %12 */ #define BCL_20_31 0x429f0005 /* bcl 20,31,1f */ /* 1: */ #define MFLR_R11 0x7d6802a6 /* mflr %11 */ #define LD_R2_M16R11 0xe84bfff0 /* ld %2,(0b-1b)(%11) */ #define MTLR_R12 0x7d8803a6 /* mtlr %12 */ #define ADD_R12_R2_R11 0x7d825a14 /* add %12,%2,%11 */ /* ld %11,0(%12) */ /* ld %2,8(%12) */ /* mtctr %11 */ /* ld %11,16(%12) */ /* bctr */ /* Pad with this. */ #define NOP 0x60000000 /* Some other nops. */ #define CROR_151515 0x4def7b82 #define CROR_313131 0x4ffffb82 /* .glink entries for the first 32k functions are two instructions. */ #define LI_R0_0 0x38000000 /* li %r0,0 */ #define B_DOT 0x48000000 /* b . */ /* After that, we need two instructions to load the index, followed by a branch. */ #define LIS_R0_0 0x3c000000 /* lis %r0,0 */ #define ORI_R0_R0_0 0x60000000 /* ori %r0,%r0,0 */ /* Instructions used by the save and restore reg functions. */ #define STD_R0_0R1 0xf8010000 /* std %r0,0(%r1) */ #define STD_R0_0R12 0xf80c0000 /* std %r0,0(%r12) */ #define LD_R0_0R1 0xe8010000 /* ld %r0,0(%r1) */ #define LD_R0_0R12 0xe80c0000 /* ld %r0,0(%r12) */ #define STFD_FR0_0R1 0xd8010000 /* stfd %fr0,0(%r1) */ #define LFD_FR0_0R1 0xc8010000 /* lfd %fr0,0(%r1) */ #define LI_R12_0 0x39800000 /* li %r12,0 */ #define STVX_VR0_R12_R0 0x7c0c01ce /* stvx %v0,%r12,%r0 */ #define LVX_VR0_R12_R0 0x7c0c00ce /* lvx %v0,%r12,%r0 */ #define MTLR_R0 0x7c0803a6 /* mtlr %r0 */ #define BLR 0x4e800020 /* blr */ /* Since .opd is an array of descriptors and each entry will end up with identical R_PPC64_RELATIVE relocs, there is really no need to propagate .opd relocs; The dynamic linker should be taught to relocate .opd without reloc entries. */ #ifndef NO_OPD_RELOCS #define NO_OPD_RELOCS 0 #endif #define ONES(n) (((bfd_vma) 1 << ((n) - 1) << 1) - 1) /* Relocation HOWTO's. */ static reloc_howto_type *ppc64_elf_howto_table[(int) R_PPC64_max]; static reloc_howto_type ppc64_elf_howto_raw[] = { /* This reloc does nothing. */ HOWTO (R_PPC64_NONE, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC64_NONE", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ FALSE), /* pcrel_offset */ /* A standard 32 bit relocation. */ HOWTO (R_PPC64_ADDR32, /* 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_PPC64_ADDR32", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffffffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* An absolute 26 bit branch; the lower two bits must be zero. FIXME: we don't check that, we just clear them. */ HOWTO (R_PPC64_ADDR24, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 26, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC64_ADDR24", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0x03fffffc, /* dst_mask */ FALSE), /* pcrel_offset */ /* A standard 16 bit relocation. */ HOWTO (R_PPC64_ADDR16, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC64_ADDR16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* A 16 bit relocation without overflow. */ HOWTO (R_PPC64_ADDR16_LO, /* 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_PPC64_ADDR16_LO", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Bits 16-31 of an address. */ HOWTO (R_PPC64_ADDR16_HI, /* type */ 16, /* 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_PPC64_ADDR16_HI", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Bits 16-31 of an address, plus 1 if the contents of the low 16 bits, treated as a signed number, is negative. */ HOWTO (R_PPC64_ADDR16_HA, /* type */ 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_ha_reloc, /* special_function */ "R_PPC64_ADDR16_HA", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* An absolute 16 bit branch; the lower two bits must be zero. FIXME: we don't check that, we just clear them. */ HOWTO (R_PPC64_ADDR14, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ ppc64_elf_branch_reloc, /* special_function */ "R_PPC64_ADDR14", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0x0000fffc, /* dst_mask */ FALSE), /* pcrel_offset */ /* An absolute 16 bit branch, for which bit 10 should be set to indicate that the branch is expected to be taken. The lower two bits must be zero. */ HOWTO (R_PPC64_ADDR14_BRTAKEN, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ ppc64_elf_brtaken_reloc, /* special_function */ "R_PPC64_ADDR14_BRTAKEN",/* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0x0000fffc, /* dst_mask */ FALSE), /* pcrel_offset */ /* An absolute 16 bit branch, for which bit 10 should be set to indicate that the branch is not expected to be taken. The lower two bits must be zero. */ HOWTO (R_PPC64_ADDR14_BRNTAKEN, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ ppc64_elf_brtaken_reloc, /* special_function */ "R_PPC64_ADDR14_BRNTAKEN",/* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0x0000fffc, /* dst_mask */ FALSE), /* pcrel_offset */ /* A relative 26 bit branch; the lower two bits must be zero. */ HOWTO (R_PPC64_REL24, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 26, /* bitsize */ TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ ppc64_elf_branch_reloc, /* special_function */ "R_PPC64_REL24", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0x03fffffc, /* dst_mask */ TRUE), /* pcrel_offset */ /* A relative 16 bit branch; the lower two bits must be zero. */ HOWTO (R_PPC64_REL14, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ ppc64_elf_branch_reloc, /* special_function */ "R_PPC64_REL14", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0x0000fffc, /* dst_mask */ TRUE), /* pcrel_offset */ /* A relative 16 bit branch. Bit 10 should be set to indicate that the branch is expected to be taken. The lower two bits must be zero. */ HOWTO (R_PPC64_REL14_BRTAKEN, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ ppc64_elf_brtaken_reloc, /* special_function */ "R_PPC64_REL14_BRTAKEN", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0x0000fffc, /* dst_mask */ TRUE), /* pcrel_offset */ /* A relative 16 bit branch. Bit 10 should be set to indicate that the branch is not expected to be taken. The lower two bits must be zero. */ HOWTO (R_PPC64_REL14_BRNTAKEN, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ ppc64_elf_brtaken_reloc, /* special_function */ "R_PPC64_REL14_BRNTAKEN",/* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0x0000fffc, /* dst_mask */ TRUE), /* pcrel_offset */ /* Like R_PPC64_ADDR16, but referring to the GOT table entry for the symbol. */ HOWTO (R_PPC64_GOT16, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_GOT16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like R_PPC64_ADDR16_LO, but referring to the GOT table entry for the symbol. */ HOWTO (R_PPC64_GOT16_LO, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_GOT16_LO", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like R_PPC64_ADDR16_HI, but referring to the GOT table entry for the symbol. */ HOWTO (R_PPC64_GOT16_HI, /* type */ 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont,/* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_GOT16_HI", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like R_PPC64_ADDR16_HA, but referring to the GOT table entry for the symbol. */ HOWTO (R_PPC64_GOT16_HA, /* type */ 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont,/* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_GOT16_HA", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* This is used only by the dynamic linker. The symbol should exist both in the object being run and in some shared library. The dynamic linker copies the data addressed by the symbol from the shared library into the object, because the object being run has to have the data at some particular address. */ HOWTO (R_PPC64_COPY, /* type */ 0, /* rightshift */ 0, /* this one is variable size */ 0, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_COPY", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like R_PPC64_ADDR64, but used when setting global offset table entries. */ HOWTO (R_PPC64_GLOB_DAT, /* type */ 0, /* rightshift */ 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ 64, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_GLOB_DAT", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ ONES (64), /* dst_mask */ FALSE), /* pcrel_offset */ /* Created by the link editor. Marks a procedure linkage table entry for a symbol. */ HOWTO (R_PPC64_JMP_SLOT, /* type */ 0, /* rightshift */ 0, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_JMP_SLOT", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ FALSE), /* pcrel_offset */ /* Used only by the dynamic linker. When the object is run, this doubleword64 is set to the load address of the object, plus the addend. */ HOWTO (R_PPC64_RELATIVE, /* type */ 0, /* rightshift */ 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ 64, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC64_RELATIVE", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ ONES (64), /* dst_mask */ FALSE), /* pcrel_offset */ /* Like R_PPC64_ADDR32, but may be unaligned. */ HOWTO (R_PPC64_UADDR32, /* 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_PPC64_UADDR32", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffffffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like R_PPC64_ADDR16, but may be unaligned. */ HOWTO (R_PPC64_UADDR16, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC64_UADDR16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* 32-bit PC relative. */ HOWTO (R_PPC64_REL32, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ TRUE, /* pc_relative */ 0, /* bitpos */ /* FIXME: Verify. Was complain_overflow_bitfield. */ complain_overflow_signed, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC64_REL32", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffffffff, /* dst_mask */ TRUE), /* pcrel_offset */ /* 32-bit relocation to the symbol's procedure linkage table. */ HOWTO (R_PPC64_PLT32, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_PLT32", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffffffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* 32-bit PC relative relocation to the symbol's procedure linkage table. FIXME: R_PPC64_PLTREL32 not supported. */ HOWTO (R_PPC64_PLTREL32, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC64_PLTREL32", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffffffff, /* dst_mask */ TRUE), /* pcrel_offset */ /* Like R_PPC64_ADDR16_LO, but referring to the PLT table entry for the symbol. */ HOWTO (R_PPC64_PLT16_LO, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_PLT16_LO", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like R_PPC64_ADDR16_HI, but referring to the PLT table entry for the symbol. */ HOWTO (R_PPC64_PLT16_HI, /* type */ 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_PLT16_HI", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like R_PPC64_ADDR16_HA, but referring to the PLT table entry for the symbol. */ HOWTO (R_PPC64_PLT16_HA, /* type */ 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_PLT16_HA", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* 16-bit section relative relocation. */ HOWTO (R_PPC64_SECTOFF, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ ppc64_elf_sectoff_reloc, /* special_function */ "R_PPC64_SECTOFF", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like R_PPC64_SECTOFF, but no overflow warning. */ HOWTO (R_PPC64_SECTOFF_LO, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_sectoff_reloc, /* special_function */ "R_PPC64_SECTOFF_LO", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* 16-bit upper half section relative relocation. */ HOWTO (R_PPC64_SECTOFF_HI, /* type */ 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_sectoff_reloc, /* special_function */ "R_PPC64_SECTOFF_HI", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* 16-bit upper half adjusted section relative relocation. */ HOWTO (R_PPC64_SECTOFF_HA, /* type */ 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_sectoff_ha_reloc, /* special_function */ "R_PPC64_SECTOFF_HA", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like R_PPC64_REL24 without touching the two least significant bits. */ HOWTO (R_PPC64_REL30, /* type */ 2, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 30, /* bitsize */ TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC64_REL30", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xfffffffc, /* dst_mask */ TRUE), /* pcrel_offset */ /* Relocs in the 64-bit PowerPC ELF ABI, not in the 32-bit ABI. */ /* A standard 64-bit relocation. */ HOWTO (R_PPC64_ADDR64, /* type */ 0, /* rightshift */ 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ 64, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC64_ADDR64", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ ONES (64), /* dst_mask */ FALSE), /* pcrel_offset */ /* The bits 32-47 of an address. */ HOWTO (R_PPC64_ADDR16_HIGHER, /* type */ 32, /* 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_PPC64_ADDR16_HIGHER", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* The bits 32-47 of an address, plus 1 if the contents of the low 16 bits, treated as a signed number, is negative. */ HOWTO (R_PPC64_ADDR16_HIGHERA, /* type */ 32, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_ha_reloc, /* special_function */ "R_PPC64_ADDR16_HIGHERA", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* The bits 48-63 of an address. */ HOWTO (R_PPC64_ADDR16_HIGHEST,/* type */ 48, /* 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_PPC64_ADDR16_HIGHEST", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* The bits 48-63 of an address, plus 1 if the contents of the low 16 bits, treated as a signed number, is negative. */ HOWTO (R_PPC64_ADDR16_HIGHESTA,/* type */ 48, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_ha_reloc, /* special_function */ "R_PPC64_ADDR16_HIGHESTA", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like ADDR64, but may be unaligned. */ HOWTO (R_PPC64_UADDR64, /* type */ 0, /* rightshift */ 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ 64, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC64_UADDR64", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ ONES (64), /* dst_mask */ FALSE), /* pcrel_offset */ /* 64-bit relative relocation. */ HOWTO (R_PPC64_REL64, /* type */ 0, /* rightshift */ 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ 64, /* bitsize */ TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC64_REL64", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ ONES (64), /* dst_mask */ TRUE), /* pcrel_offset */ /* 64-bit relocation to the symbol's procedure linkage table. */ HOWTO (R_PPC64_PLT64, /* type */ 0, /* rightshift */ 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ 64, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_PLT64", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ ONES (64), /* dst_mask */ FALSE), /* pcrel_offset */ /* 64-bit PC relative relocation to the symbol's procedure linkage table. */ /* FIXME: R_PPC64_PLTREL64 not supported. */ HOWTO (R_PPC64_PLTREL64, /* type */ 0, /* rightshift */ 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ 64, /* bitsize */ TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_PLTREL64", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ ONES (64), /* dst_mask */ TRUE), /* pcrel_offset */ /* 16 bit TOC-relative relocation. */ /* R_PPC64_TOC16 47 half16* S + A - .TOC. */ HOWTO (R_PPC64_TOC16, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ ppc64_elf_toc_reloc, /* special_function */ "R_PPC64_TOC16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* 16 bit TOC-relative relocation without overflow. */ /* R_PPC64_TOC16_LO 48 half16 #lo (S + A - .TOC.) */ HOWTO (R_PPC64_TOC16_LO, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_toc_reloc, /* special_function */ "R_PPC64_TOC16_LO", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* 16 bit TOC-relative relocation, high 16 bits. */ /* R_PPC64_TOC16_HI 49 half16 #hi (S + A - .TOC.) */ HOWTO (R_PPC64_TOC16_HI, /* type */ 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_toc_reloc, /* special_function */ "R_PPC64_TOC16_HI", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* 16 bit TOC-relative relocation, high 16 bits, plus 1 if the contents of the low 16 bits, treated as a signed number, is negative. */ /* R_PPC64_TOC16_HA 50 half16 #ha (S + A - .TOC.) */ HOWTO (R_PPC64_TOC16_HA, /* type */ 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_toc_ha_reloc, /* special_function */ "R_PPC64_TOC16_HA", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* 64-bit relocation; insert value of TOC base (.TOC.). */ /* R_PPC64_TOC 51 doubleword64 .TOC. */ HOWTO (R_PPC64_TOC, /* type */ 0, /* rightshift */ 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ 64, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ ppc64_elf_toc64_reloc, /* special_function */ "R_PPC64_TOC", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ ONES (64), /* dst_mask */ FALSE), /* pcrel_offset */ /* Like R_PPC64_GOT16, but also informs the link editor that the value to relocate may (!) refer to a PLT entry which the link editor (a) may replace with the symbol value. If the link editor is unable to fully resolve the symbol, it may (b) create a PLT entry and store the address to the new PLT entry in the GOT. This permits lazy resolution of function symbols at run time. The link editor may also skip all of this and just (c) emit a R_PPC64_GLOB_DAT to tie the symbol to the GOT entry. */ /* FIXME: R_PPC64_PLTGOT16 not implemented. */ HOWTO (R_PPC64_PLTGOT16, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_PLTGOT16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like R_PPC64_PLTGOT16, but without overflow. */ /* FIXME: R_PPC64_PLTGOT16_LO not implemented. */ HOWTO (R_PPC64_PLTGOT16_LO, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_PLTGOT16_LO", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like R_PPC64_PLT_GOT16, but using bits 16-31 of the address. */ /* FIXME: R_PPC64_PLTGOT16_HI not implemented. */ HOWTO (R_PPC64_PLTGOT16_HI, /* type */ 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_PLTGOT16_HI", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like R_PPC64_PLT_GOT16, but using bits 16-31 of the address, plus 1 if the contents of the low 16 bits, treated as a signed number, is negative. */ /* FIXME: R_PPC64_PLTGOT16_HA not implemented. */ HOWTO (R_PPC64_PLTGOT16_HA, /* type */ 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont,/* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_PLTGOT16_HA", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like R_PPC64_ADDR16, but for instructions with a DS field. */ HOWTO (R_PPC64_ADDR16_DS, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC64_ADDR16_DS", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xfffc, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like R_PPC64_ADDR16_LO, but for instructions with a DS field. */ HOWTO (R_PPC64_ADDR16_LO_DS, /* 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_PPC64_ADDR16_LO_DS",/* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xfffc, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like R_PPC64_GOT16, but for instructions with a DS field. */ HOWTO (R_PPC64_GOT16_DS, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_GOT16_DS", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xfffc, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like R_PPC64_GOT16_LO, but for instructions with a DS field. */ HOWTO (R_PPC64_GOT16_LO_DS, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_GOT16_LO_DS", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xfffc, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like R_PPC64_PLT16_LO, but for instructions with a DS field. */ HOWTO (R_PPC64_PLT16_LO_DS, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_PLT16_LO_DS", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xfffc, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like R_PPC64_SECTOFF, but for instructions with a DS field. */ HOWTO (R_PPC64_SECTOFF_DS, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ ppc64_elf_sectoff_reloc, /* special_function */ "R_PPC64_SECTOFF_DS", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xfffc, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like R_PPC64_SECTOFF_LO, but for instructions with a DS field. */ HOWTO (R_PPC64_SECTOFF_LO_DS, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_sectoff_reloc, /* special_function */ "R_PPC64_SECTOFF_LO_DS",/* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xfffc, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like R_PPC64_TOC16, but for instructions with a DS field. */ HOWTO (R_PPC64_TOC16_DS, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ ppc64_elf_toc_reloc, /* special_function */ "R_PPC64_TOC16_DS", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xfffc, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like R_PPC64_TOC16_LO, but for instructions with a DS field. */ HOWTO (R_PPC64_TOC16_LO_DS, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_toc_reloc, /* special_function */ "R_PPC64_TOC16_LO_DS", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xfffc, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like R_PPC64_PLTGOT16, but for instructions with a DS field. */ /* FIXME: R_PPC64_PLTGOT16_DS not implemented. */ HOWTO (R_PPC64_PLTGOT16_DS, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_PLTGOT16_DS", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xfffc, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like R_PPC64_PLTGOT16_LO, but for instructions with a DS field. */ /* FIXME: R_PPC64_PLTGOT16_LO not implemented. */ HOWTO (R_PPC64_PLTGOT16_LO_DS,/* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_PLTGOT16_LO_DS",/* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xfffc, /* dst_mask */ FALSE), /* pcrel_offset */ - /* Marker reloc for TLS. */ + /* Marker relocs for TLS. */ HOWTO (R_PPC64_TLS, 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_PPC64_TLS", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ FALSE), /* pcrel_offset */ + HOWTO (R_PPC64_TLSGD, + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_PPC64_TLSGD", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (R_PPC64_TLSLD, + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_PPC64_TLSLD", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + FALSE), /* pcrel_offset */ + /* Computes the load module index of the load module that contains the definition of its TLS sym. */ HOWTO (R_PPC64_DTPMOD64, 0, /* rightshift */ 4, /* size (0 = byte, 1 = short, 2 = long) */ 64, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_DTPMOD64", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ ONES (64), /* dst_mask */ FALSE), /* pcrel_offset */ /* Computes a dtv-relative displacement, the difference between the value of sym+add and the base address of the thread-local storage block that contains the definition of sym, minus 0x8000. */ HOWTO (R_PPC64_DTPREL64, 0, /* rightshift */ 4, /* size (0 = byte, 1 = short, 2 = long) */ 64, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_DTPREL64", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ ONES (64), /* dst_mask */ FALSE), /* pcrel_offset */ /* A 16 bit dtprel reloc. */ HOWTO (R_PPC64_DTPREL16, 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_DTPREL16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like DTPREL16, but no overflow. */ HOWTO (R_PPC64_DTPREL16_LO, 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_DTPREL16_LO", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like DTPREL16_LO, but next higher group of 16 bits. */ HOWTO (R_PPC64_DTPREL16_HI, 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_DTPREL16_HI", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like DTPREL16_HI, but adjust for low 16 bits. */ HOWTO (R_PPC64_DTPREL16_HA, 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_DTPREL16_HA", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like DTPREL16_HI, but next higher group of 16 bits. */ HOWTO (R_PPC64_DTPREL16_HIGHER, 32, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_DTPREL16_HIGHER", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like DTPREL16_HIGHER, but adjust for low 16 bits. */ HOWTO (R_PPC64_DTPREL16_HIGHERA, 32, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_DTPREL16_HIGHERA", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like DTPREL16_HIGHER, but next higher group of 16 bits. */ HOWTO (R_PPC64_DTPREL16_HIGHEST, 48, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_DTPREL16_HIGHEST", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like DTPREL16_HIGHEST, but adjust for low 16 bits. */ HOWTO (R_PPC64_DTPREL16_HIGHESTA, 48, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_DTPREL16_HIGHESTA", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like DTPREL16, but for insns with a DS field. */ HOWTO (R_PPC64_DTPREL16_DS, 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_DTPREL16_DS", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xfffc, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like DTPREL16_DS, but no overflow. */ HOWTO (R_PPC64_DTPREL16_LO_DS, 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_DTPREL16_LO_DS", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xfffc, /* dst_mask */ FALSE), /* pcrel_offset */ /* Computes a tp-relative displacement, the difference between the value of sym+add and the value of the thread pointer (r13). */ HOWTO (R_PPC64_TPREL64, 0, /* rightshift */ 4, /* size (0 = byte, 1 = short, 2 = long) */ 64, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_TPREL64", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ ONES (64), /* dst_mask */ FALSE), /* pcrel_offset */ /* A 16 bit tprel reloc. */ HOWTO (R_PPC64_TPREL16, 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_TPREL16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like TPREL16, but no overflow. */ HOWTO (R_PPC64_TPREL16_LO, 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_TPREL16_LO", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like TPREL16_LO, but next higher group of 16 bits. */ HOWTO (R_PPC64_TPREL16_HI, 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_TPREL16_HI", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like TPREL16_HI, but adjust for low 16 bits. */ HOWTO (R_PPC64_TPREL16_HA, 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_TPREL16_HA", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like TPREL16_HI, but next higher group of 16 bits. */ HOWTO (R_PPC64_TPREL16_HIGHER, 32, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_TPREL16_HIGHER", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like TPREL16_HIGHER, but adjust for low 16 bits. */ HOWTO (R_PPC64_TPREL16_HIGHERA, 32, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_TPREL16_HIGHERA", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like TPREL16_HIGHER, but next higher group of 16 bits. */ HOWTO (R_PPC64_TPREL16_HIGHEST, 48, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_TPREL16_HIGHEST", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like TPREL16_HIGHEST, but adjust for low 16 bits. */ HOWTO (R_PPC64_TPREL16_HIGHESTA, 48, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_TPREL16_HIGHESTA", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like TPREL16, but for insns with a DS field. */ HOWTO (R_PPC64_TPREL16_DS, 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_TPREL16_DS", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xfffc, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like TPREL16_DS, but no overflow. */ HOWTO (R_PPC64_TPREL16_LO_DS, 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_TPREL16_LO_DS", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xfffc, /* dst_mask */ FALSE), /* pcrel_offset */ /* Allocates two contiguous entries in the GOT to hold a tls_index structure, with values (sym+add)@dtpmod and (sym+add)@dtprel, and computes the offset to the first entry relative to the TOC base (r2). */ HOWTO (R_PPC64_GOT_TLSGD16, 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_GOT_TLSGD16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like GOT_TLSGD16, but no overflow. */ HOWTO (R_PPC64_GOT_TLSGD16_LO, 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_GOT_TLSGD16_LO", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like GOT_TLSGD16_LO, but next higher group of 16 bits. */ HOWTO (R_PPC64_GOT_TLSGD16_HI, 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_GOT_TLSGD16_HI", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like GOT_TLSGD16_HI, but adjust for low 16 bits. */ HOWTO (R_PPC64_GOT_TLSGD16_HA, 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_GOT_TLSGD16_HA", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Allocates two contiguous entries in the GOT to hold a tls_index structure, with values (sym+add)@dtpmod and zero, and computes the offset to the first entry relative to the TOC base (r2). */ HOWTO (R_PPC64_GOT_TLSLD16, 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_GOT_TLSLD16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like GOT_TLSLD16, but no overflow. */ HOWTO (R_PPC64_GOT_TLSLD16_LO, 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_GOT_TLSLD16_LO", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like GOT_TLSLD16_LO, but next higher group of 16 bits. */ HOWTO (R_PPC64_GOT_TLSLD16_HI, 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_GOT_TLSLD16_HI", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like GOT_TLSLD16_HI, but adjust for low 16 bits. */ HOWTO (R_PPC64_GOT_TLSLD16_HA, 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_GOT_TLSLD16_HA", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Allocates an entry in the GOT with value (sym+add)@dtprel, and computes the offset to the entry relative to the TOC base (r2). */ HOWTO (R_PPC64_GOT_DTPREL16_DS, 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_GOT_DTPREL16_DS", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xfffc, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like GOT_DTPREL16_DS, but no overflow. */ HOWTO (R_PPC64_GOT_DTPREL16_LO_DS, 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_GOT_DTPREL16_LO_DS", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xfffc, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like GOT_DTPREL16_LO_DS, but next higher group of 16 bits. */ HOWTO (R_PPC64_GOT_DTPREL16_HI, 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_GOT_DTPREL16_HI", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like GOT_DTPREL16_HI, but adjust for low 16 bits. */ HOWTO (R_PPC64_GOT_DTPREL16_HA, 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_GOT_DTPREL16_HA", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Allocates an entry in the GOT with value (sym+add)@tprel, and computes the offset to the entry relative to the TOC base (r2). */ HOWTO (R_PPC64_GOT_TPREL16_DS, 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_GOT_TPREL16_DS", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xfffc, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like GOT_TPREL16_DS, but no overflow. */ HOWTO (R_PPC64_GOT_TPREL16_LO_DS, 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_GOT_TPREL16_LO_DS", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xfffc, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like GOT_TPREL16_LO_DS, but next higher group of 16 bits. */ HOWTO (R_PPC64_GOT_TPREL16_HI, 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_GOT_TPREL16_HI", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* Like GOT_TPREL16_HI, but adjust for low 16 bits. */ HOWTO (R_PPC64_GOT_TPREL16_HA, 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ ppc64_elf_unhandled_reloc, /* special_function */ "R_PPC64_GOT_TPREL16_HA", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* GNU extension to record C++ vtable hierarchy. */ HOWTO (R_PPC64_GNU_VTINHERIT, /* type */ 0, /* rightshift */ 0, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ NULL, /* special_function */ "R_PPC64_GNU_VTINHERIT", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ FALSE), /* pcrel_offset */ /* GNU extension to record C++ vtable member usage. */ HOWTO (R_PPC64_GNU_VTENTRY, /* type */ 0, /* rightshift */ 0, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ NULL, /* special_function */ "R_PPC64_GNU_VTENTRY", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ FALSE), /* pcrel_offset */ }; /* Initialize the ppc64_elf_howto_table, so that linear accesses can be done. */ static void ppc_howto_init (void) { unsigned int i, type; for (i = 0; i < sizeof (ppc64_elf_howto_raw) / sizeof (ppc64_elf_howto_raw[0]); i++) { type = ppc64_elf_howto_raw[i].type; BFD_ASSERT (type < (sizeof (ppc64_elf_howto_table) / sizeof (ppc64_elf_howto_table[0]))); ppc64_elf_howto_table[type] = &ppc64_elf_howto_raw[i]; } } static reloc_howto_type * ppc64_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code) { enum elf_ppc64_reloc_type r = R_PPC64_NONE; if (!ppc64_elf_howto_table[R_PPC64_ADDR32]) /* Initialize howto table if needed. */ ppc_howto_init (); switch (code) { default: return NULL; case BFD_RELOC_NONE: r = R_PPC64_NONE; break; case BFD_RELOC_32: r = R_PPC64_ADDR32; break; case BFD_RELOC_PPC_BA26: r = R_PPC64_ADDR24; break; case BFD_RELOC_16: r = R_PPC64_ADDR16; break; case BFD_RELOC_LO16: r = R_PPC64_ADDR16_LO; break; case BFD_RELOC_HI16: r = R_PPC64_ADDR16_HI; break; case BFD_RELOC_HI16_S: r = R_PPC64_ADDR16_HA; break; case BFD_RELOC_PPC_BA16: r = R_PPC64_ADDR14; break; case BFD_RELOC_PPC_BA16_BRTAKEN: r = R_PPC64_ADDR14_BRTAKEN; break; case BFD_RELOC_PPC_BA16_BRNTAKEN: r = R_PPC64_ADDR14_BRNTAKEN; break; case BFD_RELOC_PPC_B26: r = R_PPC64_REL24; break; case BFD_RELOC_PPC_B16: r = R_PPC64_REL14; break; case BFD_RELOC_PPC_B16_BRTAKEN: r = R_PPC64_REL14_BRTAKEN; break; case BFD_RELOC_PPC_B16_BRNTAKEN: r = R_PPC64_REL14_BRNTAKEN; break; case BFD_RELOC_16_GOTOFF: r = R_PPC64_GOT16; break; case BFD_RELOC_LO16_GOTOFF: r = R_PPC64_GOT16_LO; break; case BFD_RELOC_HI16_GOTOFF: r = R_PPC64_GOT16_HI; break; case BFD_RELOC_HI16_S_GOTOFF: r = R_PPC64_GOT16_HA; break; case BFD_RELOC_PPC_COPY: r = R_PPC64_COPY; break; case BFD_RELOC_PPC_GLOB_DAT: r = R_PPC64_GLOB_DAT; break; case BFD_RELOC_32_PCREL: r = R_PPC64_REL32; break; case BFD_RELOC_32_PLTOFF: r = R_PPC64_PLT32; break; case BFD_RELOC_32_PLT_PCREL: r = R_PPC64_PLTREL32; break; case BFD_RELOC_LO16_PLTOFF: r = R_PPC64_PLT16_LO; break; case BFD_RELOC_HI16_PLTOFF: r = R_PPC64_PLT16_HI; break; case BFD_RELOC_HI16_S_PLTOFF: r = R_PPC64_PLT16_HA; break; case BFD_RELOC_16_BASEREL: r = R_PPC64_SECTOFF; break; case BFD_RELOC_LO16_BASEREL: r = R_PPC64_SECTOFF_LO; break; case BFD_RELOC_HI16_BASEREL: r = R_PPC64_SECTOFF_HI; break; case BFD_RELOC_HI16_S_BASEREL: r = R_PPC64_SECTOFF_HA; break; case BFD_RELOC_CTOR: r = R_PPC64_ADDR64; break; case BFD_RELOC_64: r = R_PPC64_ADDR64; break; case BFD_RELOC_PPC64_HIGHER: r = R_PPC64_ADDR16_HIGHER; break; case BFD_RELOC_PPC64_HIGHER_S: r = R_PPC64_ADDR16_HIGHERA; break; case BFD_RELOC_PPC64_HIGHEST: r = R_PPC64_ADDR16_HIGHEST; break; case BFD_RELOC_PPC64_HIGHEST_S: r = R_PPC64_ADDR16_HIGHESTA; break; case BFD_RELOC_64_PCREL: r = R_PPC64_REL64; break; case BFD_RELOC_64_PLTOFF: r = R_PPC64_PLT64; break; case BFD_RELOC_64_PLT_PCREL: r = R_PPC64_PLTREL64; break; case BFD_RELOC_PPC_TOC16: r = R_PPC64_TOC16; break; case BFD_RELOC_PPC64_TOC16_LO: r = R_PPC64_TOC16_LO; break; case BFD_RELOC_PPC64_TOC16_HI: r = R_PPC64_TOC16_HI; break; case BFD_RELOC_PPC64_TOC16_HA: r = R_PPC64_TOC16_HA; break; case BFD_RELOC_PPC64_TOC: r = R_PPC64_TOC; break; case BFD_RELOC_PPC64_PLTGOT16: r = R_PPC64_PLTGOT16; break; case BFD_RELOC_PPC64_PLTGOT16_LO: r = R_PPC64_PLTGOT16_LO; break; case BFD_RELOC_PPC64_PLTGOT16_HI: r = R_PPC64_PLTGOT16_HI; break; case BFD_RELOC_PPC64_PLTGOT16_HA: r = R_PPC64_PLTGOT16_HA; break; case BFD_RELOC_PPC64_ADDR16_DS: r = R_PPC64_ADDR16_DS; break; case BFD_RELOC_PPC64_ADDR16_LO_DS: r = R_PPC64_ADDR16_LO_DS; break; case BFD_RELOC_PPC64_GOT16_DS: r = R_PPC64_GOT16_DS; break; case BFD_RELOC_PPC64_GOT16_LO_DS: r = R_PPC64_GOT16_LO_DS; break; case BFD_RELOC_PPC64_PLT16_LO_DS: r = R_PPC64_PLT16_LO_DS; break; case BFD_RELOC_PPC64_SECTOFF_DS: r = R_PPC64_SECTOFF_DS; break; case BFD_RELOC_PPC64_SECTOFF_LO_DS: r = R_PPC64_SECTOFF_LO_DS; break; case BFD_RELOC_PPC64_TOC16_DS: r = R_PPC64_TOC16_DS; break; case BFD_RELOC_PPC64_TOC16_LO_DS: r = R_PPC64_TOC16_LO_DS; break; case BFD_RELOC_PPC64_PLTGOT16_DS: r = R_PPC64_PLTGOT16_DS; break; case BFD_RELOC_PPC64_PLTGOT16_LO_DS: r = R_PPC64_PLTGOT16_LO_DS; break; case BFD_RELOC_PPC_TLS: r = R_PPC64_TLS; break; + case BFD_RELOC_PPC_TLSGD: r = R_PPC64_TLSGD; + break; + case BFD_RELOC_PPC_TLSLD: r = R_PPC64_TLSLD; + break; case BFD_RELOC_PPC_DTPMOD: r = R_PPC64_DTPMOD64; break; case BFD_RELOC_PPC_TPREL16: r = R_PPC64_TPREL16; break; case BFD_RELOC_PPC_TPREL16_LO: r = R_PPC64_TPREL16_LO; break; case BFD_RELOC_PPC_TPREL16_HI: r = R_PPC64_TPREL16_HI; break; case BFD_RELOC_PPC_TPREL16_HA: r = R_PPC64_TPREL16_HA; break; case BFD_RELOC_PPC_TPREL: r = R_PPC64_TPREL64; break; case BFD_RELOC_PPC_DTPREL16: r = R_PPC64_DTPREL16; break; case BFD_RELOC_PPC_DTPREL16_LO: r = R_PPC64_DTPREL16_LO; break; case BFD_RELOC_PPC_DTPREL16_HI: r = R_PPC64_DTPREL16_HI; break; case BFD_RELOC_PPC_DTPREL16_HA: r = R_PPC64_DTPREL16_HA; break; case BFD_RELOC_PPC_DTPREL: r = R_PPC64_DTPREL64; break; case BFD_RELOC_PPC_GOT_TLSGD16: r = R_PPC64_GOT_TLSGD16; break; case BFD_RELOC_PPC_GOT_TLSGD16_LO: r = R_PPC64_GOT_TLSGD16_LO; break; case BFD_RELOC_PPC_GOT_TLSGD16_HI: r = R_PPC64_GOT_TLSGD16_HI; break; case BFD_RELOC_PPC_GOT_TLSGD16_HA: r = R_PPC64_GOT_TLSGD16_HA; break; case BFD_RELOC_PPC_GOT_TLSLD16: r = R_PPC64_GOT_TLSLD16; break; case BFD_RELOC_PPC_GOT_TLSLD16_LO: r = R_PPC64_GOT_TLSLD16_LO; break; case BFD_RELOC_PPC_GOT_TLSLD16_HI: r = R_PPC64_GOT_TLSLD16_HI; break; case BFD_RELOC_PPC_GOT_TLSLD16_HA: r = R_PPC64_GOT_TLSLD16_HA; break; case BFD_RELOC_PPC_GOT_TPREL16: r = R_PPC64_GOT_TPREL16_DS; break; case BFD_RELOC_PPC_GOT_TPREL16_LO: r = R_PPC64_GOT_TPREL16_LO_DS; break; case BFD_RELOC_PPC_GOT_TPREL16_HI: r = R_PPC64_GOT_TPREL16_HI; break; case BFD_RELOC_PPC_GOT_TPREL16_HA: r = R_PPC64_GOT_TPREL16_HA; break; case BFD_RELOC_PPC_GOT_DTPREL16: r = R_PPC64_GOT_DTPREL16_DS; break; case BFD_RELOC_PPC_GOT_DTPREL16_LO: r = R_PPC64_GOT_DTPREL16_LO_DS; break; case BFD_RELOC_PPC_GOT_DTPREL16_HI: r = R_PPC64_GOT_DTPREL16_HI; break; case BFD_RELOC_PPC_GOT_DTPREL16_HA: r = R_PPC64_GOT_DTPREL16_HA; break; case BFD_RELOC_PPC64_TPREL16_DS: r = R_PPC64_TPREL16_DS; break; case BFD_RELOC_PPC64_TPREL16_LO_DS: r = R_PPC64_TPREL16_LO_DS; break; case BFD_RELOC_PPC64_TPREL16_HIGHER: r = R_PPC64_TPREL16_HIGHER; break; case BFD_RELOC_PPC64_TPREL16_HIGHERA: r = R_PPC64_TPREL16_HIGHERA; break; case BFD_RELOC_PPC64_TPREL16_HIGHEST: r = R_PPC64_TPREL16_HIGHEST; break; case BFD_RELOC_PPC64_TPREL16_HIGHESTA: r = R_PPC64_TPREL16_HIGHESTA; break; case BFD_RELOC_PPC64_DTPREL16_DS: r = R_PPC64_DTPREL16_DS; break; case BFD_RELOC_PPC64_DTPREL16_LO_DS: r = R_PPC64_DTPREL16_LO_DS; break; case BFD_RELOC_PPC64_DTPREL16_HIGHER: r = R_PPC64_DTPREL16_HIGHER; break; case BFD_RELOC_PPC64_DTPREL16_HIGHERA: r = R_PPC64_DTPREL16_HIGHERA; break; case BFD_RELOC_PPC64_DTPREL16_HIGHEST: r = R_PPC64_DTPREL16_HIGHEST; break; case BFD_RELOC_PPC64_DTPREL16_HIGHESTA: r = R_PPC64_DTPREL16_HIGHESTA; break; case BFD_RELOC_VTABLE_INHERIT: r = R_PPC64_GNU_VTINHERIT; break; case BFD_RELOC_VTABLE_ENTRY: r = R_PPC64_GNU_VTENTRY; break; } return ppc64_elf_howto_table[r]; }; static reloc_howto_type * ppc64_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name) { unsigned int i; for (i = 0; i < sizeof (ppc64_elf_howto_raw) / sizeof (ppc64_elf_howto_raw[0]); i++) if (ppc64_elf_howto_raw[i].name != NULL && strcasecmp (ppc64_elf_howto_raw[i].name, r_name) == 0) return &ppc64_elf_howto_raw[i]; return NULL; } /* Set the howto pointer for a PowerPC ELF reloc. */ static void ppc64_elf_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr, Elf_Internal_Rela *dst) { unsigned int type; /* Initialize howto table if needed. */ if (!ppc64_elf_howto_table[R_PPC64_ADDR32]) ppc_howto_init (); type = ELF64_R_TYPE (dst->r_info); if (type >= (sizeof (ppc64_elf_howto_table) / sizeof (ppc64_elf_howto_table[0]))) { (*_bfd_error_handler) (_("%B: invalid relocation type %d"), abfd, (int) type); type = R_PPC64_NONE; } cache_ptr->howto = ppc64_elf_howto_table[type]; } /* Handle the R_PPC64_ADDR16_HA and similar relocs. */ static bfd_reloc_status_type ppc64_elf_ha_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, void *data, asection *input_section, bfd *output_bfd, char **error_message) { /* If this is a relocatable link (output_bfd test tells us), just call the generic function. Any adjustment will be done at final link time. */ if (output_bfd != NULL) return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message); /* Adjust the addend for sign extension of the low 16 bits. We won't actually be using the low 16 bits, so trashing them doesn't matter. */ reloc_entry->addend += 0x8000; return bfd_reloc_continue; } static bfd_reloc_status_type ppc64_elf_branch_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, void *data, asection *input_section, bfd *output_bfd, char **error_message) { if (output_bfd != NULL) return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message); if (strcmp (symbol->section->name, ".opd") == 0 && (symbol->section->owner->flags & DYNAMIC) == 0) { bfd_vma dest = opd_entry_value (symbol->section, symbol->value + reloc_entry->addend, NULL, NULL); if (dest != (bfd_vma) -1) reloc_entry->addend = dest - (symbol->value + symbol->section->output_section->vma + symbol->section->output_offset); } return bfd_reloc_continue; } static bfd_reloc_status_type ppc64_elf_brtaken_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, void *data, asection *input_section, bfd *output_bfd, char **error_message) { long insn; enum elf_ppc64_reloc_type r_type; bfd_size_type octets; /* Disabled until we sort out how ld should choose 'y' vs 'at'. */ bfd_boolean is_power4 = FALSE; /* If this is a relocatable link (output_bfd test tells us), just call the generic function. Any adjustment will be done at final link time. */ if (output_bfd != NULL) return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message); octets = reloc_entry->address * bfd_octets_per_byte (abfd); insn = bfd_get_32 (abfd, (bfd_byte *) data + octets); insn &= ~(0x01 << 21); r_type = reloc_entry->howto->type; if (r_type == R_PPC64_ADDR14_BRTAKEN || r_type == R_PPC64_REL14_BRTAKEN) insn |= 0x01 << 21; /* 'y' or 't' bit, lowest bit of BO field. */ if (is_power4) { /* Set 'a' bit. This is 0b00010 in BO field for branch on CR(BI) insns (BO == 001at or 011at), and 0b01000 for branch on CTR insns (BO == 1a00t or 1a01t). */ if ((insn & (0x14 << 21)) == (0x04 << 21)) insn |= 0x02 << 21; else if ((insn & (0x14 << 21)) == (0x10 << 21)) insn |= 0x08 << 21; else goto out; } else { bfd_vma target = 0; bfd_vma from; if (!bfd_is_com_section (symbol->section)) target = symbol->value; target += symbol->section->output_section->vma; target += symbol->section->output_offset; target += reloc_entry->addend; from = (reloc_entry->address + input_section->output_offset + input_section->output_section->vma); /* Invert 'y' bit if not the default. */ if ((bfd_signed_vma) (target - from) < 0) insn ^= 0x01 << 21; } bfd_put_32 (abfd, insn, (bfd_byte *) data + octets); out: return ppc64_elf_branch_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message); } static bfd_reloc_status_type ppc64_elf_sectoff_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, void *data, asection *input_section, bfd *output_bfd, char **error_message) { /* If this is a relocatable link (output_bfd test tells us), just call the generic function. Any adjustment will be done at final link time. */ if (output_bfd != NULL) return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message); /* Subtract the symbol section base address. */ reloc_entry->addend -= symbol->section->output_section->vma; return bfd_reloc_continue; } static bfd_reloc_status_type ppc64_elf_sectoff_ha_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, void *data, asection *input_section, bfd *output_bfd, char **error_message) { /* If this is a relocatable link (output_bfd test tells us), just call the generic function. Any adjustment will be done at final link time. */ if (output_bfd != NULL) return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message); /* Subtract the symbol section base address. */ reloc_entry->addend -= symbol->section->output_section->vma; /* Adjust the addend for sign extension of the low 16 bits. */ reloc_entry->addend += 0x8000; return bfd_reloc_continue; } static bfd_reloc_status_type ppc64_elf_toc_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, void *data, asection *input_section, bfd *output_bfd, char **error_message) { bfd_vma TOCstart; /* If this is a relocatable link (output_bfd test tells us), just call the generic function. Any adjustment will be done at final link time. */ if (output_bfd != NULL) return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message); TOCstart = _bfd_get_gp_value (input_section->output_section->owner); if (TOCstart == 0) TOCstart = ppc64_elf_toc (input_section->output_section->owner); /* Subtract the TOC base address. */ reloc_entry->addend -= TOCstart + TOC_BASE_OFF; return bfd_reloc_continue; } static bfd_reloc_status_type ppc64_elf_toc_ha_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, void *data, asection *input_section, bfd *output_bfd, char **error_message) { bfd_vma TOCstart; /* If this is a relocatable link (output_bfd test tells us), just call the generic function. Any adjustment will be done at final link time. */ if (output_bfd != NULL) return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message); TOCstart = _bfd_get_gp_value (input_section->output_section->owner); if (TOCstart == 0) TOCstart = ppc64_elf_toc (input_section->output_section->owner); /* Subtract the TOC base address. */ reloc_entry->addend -= TOCstart + TOC_BASE_OFF; /* Adjust the addend for sign extension of the low 16 bits. */ reloc_entry->addend += 0x8000; return bfd_reloc_continue; } static bfd_reloc_status_type ppc64_elf_toc64_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, void *data, asection *input_section, bfd *output_bfd, char **error_message) { bfd_vma TOCstart; bfd_size_type octets; /* If this is a relocatable link (output_bfd test tells us), just call the generic function. Any adjustment will be done at final link time. */ if (output_bfd != NULL) return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message); TOCstart = _bfd_get_gp_value (input_section->output_section->owner); if (TOCstart == 0) TOCstart = ppc64_elf_toc (input_section->output_section->owner); octets = reloc_entry->address * bfd_octets_per_byte (abfd); bfd_put_64 (abfd, TOCstart + TOC_BASE_OFF, (bfd_byte *) data + octets); return bfd_reloc_ok; } static bfd_reloc_status_type ppc64_elf_unhandled_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, void *data, asection *input_section, bfd *output_bfd, char **error_message) { /* If this is a relocatable link (output_bfd test tells us), just call the generic function. Any adjustment will be done at final link time. */ if (output_bfd != NULL) return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message); if (error_message != NULL) { static char buf[60]; sprintf (buf, "generic linker can't handle %s", reloc_entry->howto->name); *error_message = buf; } return bfd_reloc_dangerous; } struct ppc64_elf_obj_tdata { struct elf_obj_tdata elf; /* Shortcuts to dynamic linker sections. */ asection *got; asection *relgot; /* Used during garbage collection. We attach global symbols defined on removed .opd entries to this section so that the sym is removed. */ asection *deleted_section; /* TLS local dynamic got entry handling. Suppose for multiple GOT sections means we potentially need one of these for each input bfd. */ union { bfd_signed_vma refcount; bfd_vma offset; } tlsld_got; /* A copy of relocs before they are modified for --emit-relocs. */ Elf_Internal_Rela *opd_relocs; }; #define ppc64_elf_tdata(bfd) \ ((struct ppc64_elf_obj_tdata *) (bfd)->tdata.any) #define ppc64_tlsld_got(bfd) \ (&ppc64_elf_tdata (bfd)->tlsld_got) /* Override the generic function because we store some extras. */ static bfd_boolean ppc64_elf_mkobject (bfd *abfd) { if (abfd->tdata.any == NULL) { bfd_size_type amt = sizeof (struct ppc64_elf_obj_tdata); abfd->tdata.any = bfd_zalloc (abfd, amt); if (abfd->tdata.any == NULL) return FALSE; } return bfd_elf_mkobject (abfd); } /* Return 1 if target is one of ours. */ static bfd_boolean is_ppc64_elf_target (const struct bfd_target *targ) { extern const bfd_target bfd_elf64_powerpc_vec; extern const bfd_target bfd_elf64_powerpcle_vec; return targ == &bfd_elf64_powerpc_vec || targ == &bfd_elf64_powerpcle_vec; } /* Fix bad default arch selected for a 64 bit input bfd when the default is 32 bit. */ static bfd_boolean ppc64_elf_object_p (bfd *abfd) { if (abfd->arch_info->the_default && abfd->arch_info->bits_per_word == 32) { Elf_Internal_Ehdr *i_ehdr = elf_elfheader (abfd); if (i_ehdr->e_ident[EI_CLASS] == ELFCLASS64) { /* Relies on arch after 32 bit default being 64 bit default. */ abfd->arch_info = abfd->arch_info->next; BFD_ASSERT (abfd->arch_info->bits_per_word == 64); } } return TRUE; } /* Support for core dump NOTE sections. */ static bfd_boolean ppc64_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) { size_t offset, size; if (note->descsz != 504) return FALSE; /* pr_cursig */ elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12); /* pr_pid */ elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 32); /* pr_reg */ offset = 112; size = 384; /* Make a ".reg/999" section. */ return _bfd_elfcore_make_pseudosection (abfd, ".reg", size, note->descpos + offset); } static bfd_boolean ppc64_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) { if (note->descsz != 136) return FALSE; elf_tdata (abfd)->core_program = _bfd_elfcore_strndup (abfd, note->descdata + 40, 16); elf_tdata (abfd)->core_command = _bfd_elfcore_strndup (abfd, note->descdata + 56, 80); return TRUE; } static char * ppc64_elf_write_core_note (bfd *abfd, char *buf, int *bufsiz, int note_type, ...) { switch (note_type) { default: return NULL; case NT_PRPSINFO: { char data[136]; va_list ap; va_start (ap, note_type); memset (data, 0, 40); strncpy (data + 40, va_arg (ap, const char *), 16); strncpy (data + 56, va_arg (ap, const char *), 80); va_end (ap); return elfcore_write_note (abfd, buf, bufsiz, "CORE", note_type, data, sizeof (data)); } case NT_PRSTATUS: { char data[504]; va_list ap; long pid; int cursig; const void *greg; va_start (ap, note_type); memset (data, 0, 112); pid = va_arg (ap, long); bfd_put_32 (abfd, pid, data + 32); cursig = va_arg (ap, int); bfd_put_16 (abfd, cursig, data + 12); greg = va_arg (ap, const void *); memcpy (data + 112, greg, 384); memset (data + 496, 0, 8); va_end (ap); return elfcore_write_note (abfd, buf, bufsiz, "CORE", note_type, data, sizeof (data)); } } } /* Merge backend specific data from an object file to the output object file when linking. */ static bfd_boolean ppc64_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd) { /* Check if we have the same endianess. */ if (ibfd->xvec->byteorder != obfd->xvec->byteorder && ibfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN && obfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN) { const char *msg; if (bfd_big_endian (ibfd)) msg = _("%B: compiled for a big endian system " "and target is little endian"); else msg = _("%B: compiled for a little endian system " "and target is big endian"); (*_bfd_error_handler) (msg, ibfd); bfd_set_error (bfd_error_wrong_format); return FALSE; } return TRUE; } /* Add extra PPC sections. */ static const struct bfd_elf_special_section ppc64_elf_special_sections[]= { { STRING_COMMA_LEN (".plt"), 0, SHT_NOBITS, 0 }, { STRING_COMMA_LEN (".sbss"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE }, { STRING_COMMA_LEN (".sdata"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, { STRING_COMMA_LEN (".toc"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, { STRING_COMMA_LEN (".toc1"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, { STRING_COMMA_LEN (".tocbss"), 0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE }, { NULL, 0, 0, 0, 0 } }; enum _ppc64_sec_type { sec_normal = 0, sec_opd = 1, sec_toc = 2 }; struct _ppc64_elf_section_data { struct bfd_elf_section_data elf; /* An array with one entry for each opd function descriptor. */ union { /* Points to the function code section for local opd entries. */ asection **opd_func_sec; /* After editing .opd, adjust references to opd local syms. */ long *opd_adjust; - /* An array for toc sections, indexed by offset/8. - Specifies the relocation symbol index used at a given toc offset. */ - unsigned *t_symndx; + /* An array for toc sections, indexed by offset/8. */ + struct _toc_sec_data + { + /* Specifies the relocation symbol index used at a given toc offset. */ + unsigned *symndx; + + /* And the relocation addend. */ + bfd_vma *add; + } toc; } u; enum _ppc64_sec_type sec_type:2; /* Flag set when small branches are detected. Used to select suitable defaults for the stub group size. */ unsigned int has_14bit_branch:1; }; #define ppc64_elf_section_data(sec) \ ((struct _ppc64_elf_section_data *) elf_section_data (sec)) static bfd_boolean ppc64_elf_new_section_hook (bfd *abfd, asection *sec) { if (!sec->used_by_bfd) { struct _ppc64_elf_section_data *sdata; bfd_size_type amt = sizeof (*sdata); sdata = bfd_zalloc (abfd, amt); if (sdata == NULL) return FALSE; sec->used_by_bfd = sdata; } return _bfd_elf_new_section_hook (abfd, sec); } static void * get_opd_info (asection * sec) { if (sec != NULL && ppc64_elf_section_data (sec) != NULL && ppc64_elf_section_data (sec)->sec_type == sec_opd) return ppc64_elf_section_data (sec)->u.opd_adjust; return NULL; } /* Parameters for the qsort hook. */ static asection *synthetic_opd; static bfd_boolean synthetic_relocatable; /* qsort comparison function for ppc64_elf_get_synthetic_symtab. */ static int compare_symbols (const void *ap, const void *bp) { const asymbol *a = * (const asymbol **) ap; const asymbol *b = * (const asymbol **) bp; /* Section symbols first. */ if ((a->flags & BSF_SECTION_SYM) && !(b->flags & BSF_SECTION_SYM)) return -1; if (!(a->flags & BSF_SECTION_SYM) && (b->flags & BSF_SECTION_SYM)) return 1; /* then .opd symbols. */ if (a->section == synthetic_opd && b->section != synthetic_opd) return -1; if (a->section != synthetic_opd && b->section == synthetic_opd) return 1; /* then other code symbols. */ if ((a->section->flags & (SEC_CODE | SEC_ALLOC | SEC_THREAD_LOCAL)) == (SEC_CODE | SEC_ALLOC) && (b->section->flags & (SEC_CODE | SEC_ALLOC | SEC_THREAD_LOCAL)) != (SEC_CODE | SEC_ALLOC)) return -1; if ((a->section->flags & (SEC_CODE | SEC_ALLOC | SEC_THREAD_LOCAL)) != (SEC_CODE | SEC_ALLOC) && (b->section->flags & (SEC_CODE | SEC_ALLOC | SEC_THREAD_LOCAL)) == (SEC_CODE | SEC_ALLOC)) return 1; if (synthetic_relocatable) { if (a->section->id < b->section->id) return -1; if (a->section->id > b->section->id) return 1; } if (a->value + a->section->vma < b->value + b->section->vma) return -1; if (a->value + a->section->vma > b->value + b->section->vma) return 1; /* For syms with the same value, prefer strong dynamic global function syms over other syms. */ if ((a->flags & BSF_GLOBAL) != 0 && (b->flags & BSF_GLOBAL) == 0) return -1; if ((a->flags & BSF_GLOBAL) == 0 && (b->flags & BSF_GLOBAL) != 0) return 1; if ((a->flags & BSF_FUNCTION) != 0 && (b->flags & BSF_FUNCTION) == 0) return -1; if ((a->flags & BSF_FUNCTION) == 0 && (b->flags & BSF_FUNCTION) != 0) return 1; if ((a->flags & BSF_WEAK) == 0 && (b->flags & BSF_WEAK) != 0) return -1; if ((a->flags & BSF_WEAK) != 0 && (b->flags & BSF_WEAK) == 0) return 1; if ((a->flags & BSF_DYNAMIC) != 0 && (b->flags & BSF_DYNAMIC) == 0) return -1; if ((a->flags & BSF_DYNAMIC) == 0 && (b->flags & BSF_DYNAMIC) != 0) return 1; return 0; } /* Search SYMS for a symbol of the given VALUE. */ static asymbol * sym_exists_at (asymbol **syms, long lo, long hi, int id, bfd_vma value) { long mid; if (id == -1) { while (lo < hi) { mid = (lo + hi) >> 1; if (syms[mid]->value + syms[mid]->section->vma < value) lo = mid + 1; else if (syms[mid]->value + syms[mid]->section->vma > value) hi = mid; else return syms[mid]; } } else { while (lo < hi) { mid = (lo + hi) >> 1; if (syms[mid]->section->id < id) lo = mid + 1; else if (syms[mid]->section->id > id) hi = mid; else if (syms[mid]->value < value) lo = mid + 1; else if (syms[mid]->value > value) hi = mid; else return syms[mid]; } } return NULL; } /* Create synthetic symbols, effectively restoring "dot-symbol" function entry syms. */ static long ppc64_elf_get_synthetic_symtab (bfd *abfd, long static_count, asymbol **static_syms, long dyn_count, asymbol **dyn_syms, asymbol **ret) { asymbol *s; long i; long count; char *names; long symcount, codesecsym, codesecsymend, secsymend, opdsymend; asection *opd; bfd_boolean relocatable = (abfd->flags & (EXEC_P | DYNAMIC)) == 0; asymbol **syms; *ret = NULL; opd = bfd_get_section_by_name (abfd, ".opd"); if (opd == NULL) return 0; symcount = static_count; if (!relocatable) symcount += dyn_count; if (symcount == 0) return 0; syms = bfd_malloc ((symcount + 1) * sizeof (*syms)); if (syms == NULL) return -1; if (!relocatable && static_count != 0 && dyn_count != 0) { /* Use both symbol tables. */ memcpy (syms, static_syms, static_count * sizeof (*syms)); memcpy (syms + static_count, dyn_syms, (dyn_count + 1) * sizeof (*syms)); } else if (!relocatable && static_count == 0) memcpy (syms, dyn_syms, (symcount + 1) * sizeof (*syms)); else memcpy (syms, static_syms, (symcount + 1) * sizeof (*syms)); synthetic_opd = opd; synthetic_relocatable = relocatable; qsort (syms, symcount, sizeof (*syms), compare_symbols); if (!relocatable && symcount > 1) { long j; /* Trim duplicate syms, since we may have merged the normal and dynamic symbols. Actually, we only care about syms that have different values, so trim any with the same value. */ for (i = 1, j = 1; i < symcount; ++i) if (syms[i - 1]->value + syms[i - 1]->section->vma != syms[i]->value + syms[i]->section->vma) syms[j++] = syms[i]; symcount = j; } i = 0; if (syms[i]->section == opd) ++i; codesecsym = i; for (; i < symcount; ++i) if (((syms[i]->section->flags & (SEC_CODE | SEC_ALLOC | SEC_THREAD_LOCAL)) != (SEC_CODE | SEC_ALLOC)) || (syms[i]->flags & BSF_SECTION_SYM) == 0) break; codesecsymend = i; for (; i < symcount; ++i) if ((syms[i]->flags & BSF_SECTION_SYM) == 0) break; secsymend = i; for (; i < symcount; ++i) if (syms[i]->section != opd) break; opdsymend = i; for (; i < symcount; ++i) if ((syms[i]->section->flags & (SEC_CODE | SEC_ALLOC | SEC_THREAD_LOCAL)) != (SEC_CODE | SEC_ALLOC)) break; symcount = i; count = 0; if (opdsymend == secsymend) goto done; if (relocatable) { bfd_boolean (*slurp_relocs) (bfd *, asection *, asymbol **, bfd_boolean); arelent *r; size_t size; long relcount; slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table; relcount = (opd->flags & SEC_RELOC) ? opd->reloc_count : 0; if (relcount == 0) goto done; if (!(*slurp_relocs) (abfd, opd, static_syms, FALSE)) { count = -1; goto done; } size = 0; for (i = secsymend, r = opd->relocation; i < opdsymend; ++i) { asymbol *sym; while (r < opd->relocation + relcount && r->address < syms[i]->value + opd->vma) ++r; if (r == opd->relocation + relcount) break; if (r->address != syms[i]->value + opd->vma) continue; if (r->howto->type != R_PPC64_ADDR64) continue; sym = *r->sym_ptr_ptr; if (!sym_exists_at (syms, opdsymend, symcount, sym->section->id, sym->value + r->addend)) { ++count; size += sizeof (asymbol); size += strlen (syms[i]->name) + 2; } } s = *ret = bfd_malloc (size); if (s == NULL) { count = -1; goto done; } names = (char *) (s + count); for (i = secsymend, r = opd->relocation; i < opdsymend; ++i) { asymbol *sym; while (r < opd->relocation + relcount && r->address < syms[i]->value + opd->vma) ++r; if (r == opd->relocation + relcount) break; if (r->address != syms[i]->value + opd->vma) continue; if (r->howto->type != R_PPC64_ADDR64) continue; sym = *r->sym_ptr_ptr; if (!sym_exists_at (syms, opdsymend, symcount, sym->section->id, sym->value + r->addend)) { size_t len; *s = *syms[i]; s->section = sym->section; s->value = sym->value + r->addend; s->name = names; *names++ = '.'; len = strlen (syms[i]->name); memcpy (names, syms[i]->name, len + 1); names += len + 1; s++; } } } else { bfd_byte *contents; size_t size; if (!bfd_malloc_and_get_section (abfd, opd, &contents)) { if (contents) { free_contents_and_exit: free (contents); } count = -1; goto done; } size = 0; for (i = secsymend; i < opdsymend; ++i) { bfd_vma ent; ent = bfd_get_64 (abfd, contents + syms[i]->value); if (!sym_exists_at (syms, opdsymend, symcount, -1, ent)) { ++count; size += sizeof (asymbol); size += strlen (syms[i]->name) + 2; } } s = *ret = bfd_malloc (size); if (s == NULL) goto free_contents_and_exit; names = (char *) (s + count); for (i = secsymend; i < opdsymend; ++i) { bfd_vma ent; ent = bfd_get_64 (abfd, contents + syms[i]->value); if (!sym_exists_at (syms, opdsymend, symcount, -1, ent)) { long lo, hi; size_t len; asection *sec = abfd->sections; *s = *syms[i]; lo = codesecsym; hi = codesecsymend; while (lo < hi) { long mid = (lo + hi) >> 1; if (syms[mid]->section->vma < ent) lo = mid + 1; else if (syms[mid]->section->vma > ent) hi = mid; else { sec = syms[mid]->section; break; } } if (lo >= hi && lo > codesecsym) sec = syms[lo - 1]->section; for (; sec != NULL; sec = sec->next) { if (sec->vma > ent) break; if ((sec->flags & SEC_ALLOC) == 0 || (sec->flags & SEC_LOAD) == 0) break; if ((sec->flags & SEC_CODE) != 0) s->section = sec; } s->value = ent - s->section->vma; s->name = names; *names++ = '.'; len = strlen (syms[i]->name); memcpy (names, syms[i]->name, len + 1); names += len + 1; s++; } } free (contents); } done: free (syms); return count; } /* The following functions are specific to the ELF linker, while functions above are used generally. Those named ppc64_elf_* are called by the main ELF linker code. They appear in this file more or less in the order in which they are called. eg. ppc64_elf_check_relocs is called early in the link process, ppc64_elf_finish_dynamic_sections is one of the last functions called. PowerPC64-ELF uses a similar scheme to PowerPC64-XCOFF in that functions have both a function code symbol and a function descriptor symbol. A call to foo in a relocatable object file looks like: . .text . x: . bl .foo . nop The function definition in another object file might be: . .section .opd . foo: .quad .foo . .quad .TOC.@tocbase . .quad 0 . . .text . .foo: blr When the linker resolves the call during a static link, the branch unsurprisingly just goes to .foo and the .opd information is unused. If the function definition is in a shared library, things are a little different: The call goes via a plt call stub, the opd information gets copied to the plt, and the linker patches the nop. . x: . bl .foo_stub . ld 2,40(1) . . . .foo_stub: . addis 12,2,Lfoo@toc@ha # in practice, the call stub . addi 12,12,Lfoo@toc@l # is slightly optimized, but . std 2,40(1) # this is the general idea . ld 11,0(12) . ld 2,8(12) . mtctr 11 . ld 11,16(12) . bctr . . .section .plt . Lfoo: reloc (R_PPC64_JMP_SLOT, foo) The "reloc ()" notation is supposed to indicate that the linker emits an R_PPC64_JMP_SLOT reloc against foo. The dynamic linker does the opd copying. What are the difficulties here? Well, firstly, the relocations examined by the linker in check_relocs are against the function code sym .foo, while the dynamic relocation in the plt is emitted against the function descriptor symbol, foo. Somewhere along the line, we need to carefully copy dynamic link information from one symbol to the other. Secondly, the generic part of the elf linker will make .foo a dynamic symbol as is normal for most other backends. We need foo dynamic instead, at least for an application final link. However, when creating a shared library containing foo, we need to have both symbols dynamic so that references to .foo are satisfied during the early stages of linking. Otherwise the linker might decide to pull in a definition from some other object, eg. a static library. Update: As of August 2004, we support a new convention. Function calls may use the function descriptor symbol, ie. "bl foo". This behaves exactly as "bl .foo". */ /* The linker needs to keep track of the number of relocs that it decides to copy as dynamic relocs in check_relocs for each symbol. This is so that it can later discard them if they are found to be unnecessary. We store the information in a field extending the regular ELF linker hash table. */ struct ppc_dyn_relocs { struct ppc_dyn_relocs *next; /* The input section of the reloc. */ asection *sec; /* Total number of relocs copied for the input section. */ bfd_size_type count; /* Number of pc-relative relocs copied for the input section. */ bfd_size_type pc_count; }; /* Track GOT entries needed for a given symbol. We might need more than one got entry per symbol. */ struct got_entry { struct got_entry *next; /* The symbol addend that we'll be placing in the GOT. */ bfd_vma addend; /* Unlike other ELF targets, we use separate GOT entries for the same symbol referenced from different input files. This is to support automatic multiple TOC/GOT sections, where the TOC base can vary - from one input file to another. + from one input file to another. FIXME: After group_sections we + ought to merge entries within the group. Point to the BFD owning this GOT entry. */ bfd *owner; /* Zero for non-tls entries, or TLS_TLS and one of TLS_GD, TLS_LD, TLS_TPREL or TLS_DTPREL for tls entries. */ char tls_type; /* Reference count until size_dynamic_sections, GOT offset thereafter. */ union { bfd_signed_vma refcount; bfd_vma offset; } got; }; /* The same for PLT. */ struct plt_entry { struct plt_entry *next; bfd_vma addend; union { bfd_signed_vma refcount; bfd_vma offset; } plt; }; -/* Of those relocs that might be copied as dynamic relocs, this macro +/* Of those relocs that might be copied as dynamic relocs, this function selects those that must be copied when linking a shared library, even when the symbol is local. */ -#define MUST_BE_DYN_RELOC(RTYPE) \ - ((RTYPE) != R_PPC64_REL32 \ - && (RTYPE) != R_PPC64_REL64 \ - && (RTYPE) != R_PPC64_REL30) +static int +must_be_dyn_reloc (struct bfd_link_info *info, + enum elf_ppc64_reloc_type r_type) +{ + switch (r_type) + { + default: + return 1; + case R_PPC64_REL32: + case R_PPC64_REL64: + case R_PPC64_REL30: + return 0; + + case R_PPC64_TPREL16: + case R_PPC64_TPREL16_LO: + case R_PPC64_TPREL16_HI: + case R_PPC64_TPREL16_HA: + case R_PPC64_TPREL16_DS: + case R_PPC64_TPREL16_LO_DS: + case R_PPC64_TPREL16_HIGHER: + case R_PPC64_TPREL16_HIGHERA: + case R_PPC64_TPREL16_HIGHEST: + case R_PPC64_TPREL16_HIGHESTA: + case R_PPC64_TPREL64: + return !info->executable; + } +} + /* If ELIMINATE_COPY_RELOCS is non-zero, the linker will try to avoid copying dynamic variables from a shared lib into an app's dynbss section, and instead use a dynamic relocation to point into the shared lib. With code that gcc generates, it's vital that this be enabled; In the PowerPC64 ABI, the address of a function is actually the address of a function descriptor, which resides in the .opd section. gcc uses the descriptor directly rather than going via the GOT as some other ABI's do, which means that initialized function pointers must reference the descriptor. Thus, a function pointer initialized to the address of a function in a shared library will either require a copy reloc, or a dynamic reloc. Using a copy reloc redefines the function descriptor symbol to point to the copy. This presents a problem as a plt entry for that function is also initialized from the function descriptor symbol and the copy reloc may not be initialized first. */ #define ELIMINATE_COPY_RELOCS 1 /* Section name for stubs is the associated section name plus this string. */ #define STUB_SUFFIX ".stub" /* Linker stubs. ppc_stub_long_branch: Used when a 14 bit branch (or even a 24 bit branch) can't reach its destination, but a 24 bit branch in a stub section will reach. . b dest ppc_stub_plt_branch: Similar to the above, but a 24 bit branch in the stub section won't reach its destination. . addis %r12,%r2,xxx@toc@ha . ld %r11,xxx@toc@l(%r12) . mtctr %r11 . bctr ppc_stub_plt_call: Used to call a function in a shared library. If it so happens that the plt entry referenced crosses a 64k boundary, then an extra - "addis %r12,%r12,1" will be inserted before the load at xxx+8 or - xxx+16 as appropriate. + "addi %r12,%r12,xxx@toc@l" will be inserted before the "mtctr". . addis %r12,%r2,xxx@toc@ha . std %r2,40(%r1) . ld %r11,xxx+0@toc@l(%r12) - . ld %r2,xxx+8@toc@l(%r12) . mtctr %r11 + . ld %r2,xxx+8@toc@l(%r12) . ld %r11,xxx+16@toc@l(%r12) . bctr ppc_stub_long_branch and ppc_stub_plt_branch may also have additional code to adjust the value and save r2 to support multiple toc sections. A ppc_stub_long_branch with an r2 offset looks like: . std %r2,40(%r1) . addis %r2,%r2,off@ha . addi %r2,%r2,off@l . b dest A ppc_stub_plt_branch with an r2 offset looks like: . std %r2,40(%r1) . addis %r12,%r2,xxx@toc@ha . ld %r11,xxx@toc@l(%r12) . addis %r2,%r2,off@ha . addi %r2,%r2,off@l . mtctr %r11 . bctr + + In cases where the "addis" instruction would add zero, the "addis" is + omitted and following instructions modified slightly in some cases. */ enum ppc_stub_type { ppc_stub_none, ppc_stub_long_branch, ppc_stub_long_branch_r2off, ppc_stub_plt_branch, ppc_stub_plt_branch_r2off, ppc_stub_plt_call }; struct ppc_stub_hash_entry { /* Base hash table entry structure. */ struct bfd_hash_entry root; enum ppc_stub_type stub_type; /* The stub section. */ asection *stub_sec; /* Offset within stub_sec of the beginning of this stub. */ bfd_vma stub_offset; /* Given the symbol's value and its section we can determine its final value when building the stubs (so the stub knows where to jump. */ bfd_vma target_value; asection *target_section; /* The symbol table entry, if any, that this was derived from. */ struct ppc_link_hash_entry *h; /* And the reloc addend that this was derived from. */ bfd_vma addend; /* Where this stub is being called from, or, in the case of combined stub sections, the first input section in the group. */ asection *id_sec; }; struct ppc_branch_hash_entry { /* Base hash table entry structure. */ struct bfd_hash_entry root; /* Offset within branch lookup table. */ unsigned int offset; /* Generation marker. */ unsigned int iter; }; struct ppc_link_hash_entry { struct elf_link_hash_entry elf; union { /* A pointer to the most recently used stub hash entry against this symbol. */ struct ppc_stub_hash_entry *stub_cache; /* A pointer to the next symbol starting with a '.' */ struct ppc_link_hash_entry *next_dot_sym; } u; /* Track dynamic relocs copied for this symbol. */ struct ppc_dyn_relocs *dyn_relocs; /* Link between function code and descriptor symbols. */ struct ppc_link_hash_entry *oh; /* Flag function code and descriptor symbols. */ unsigned int is_func:1; unsigned int is_func_descriptor:1; unsigned int fake:1; /* Whether global opd/toc sym has been adjusted or not. After ppc64_elf_edit_opd/ppc64_elf_edit_toc has run, this flag should be set for all globals defined in any opd/toc section. */ unsigned int adjust_done:1; /* Set if we twiddled this symbol to weak at some stage. */ unsigned int was_undefined:1; /* Contexts in which symbol is used in the GOT (or TOC). TLS_GD .. TLS_EXPLICIT bits are or'd into the mask as the corresponding relocs are encountered during check_relocs. tls_optimize clears TLS_GD .. TLS_TPREL when optimizing to indicate the corresponding GOT entry type is not needed. tls_optimize may also set TLS_TPRELGD when a GD reloc turns into a TPREL one. We use a separate flag rather than setting TPREL just for convenience in distinguishing the two cases. */ #define TLS_GD 1 /* GD reloc. */ #define TLS_LD 2 /* LD reloc. */ #define TLS_TPREL 4 /* TPREL reloc, => IE. */ #define TLS_DTPREL 8 /* DTPREL reloc, => LD. */ #define TLS_TLS 16 /* Any TLS reloc. */ #define TLS_EXPLICIT 32 /* Marks TOC section TLS relocs. */ #define TLS_TPRELGD 64 /* TPREL reloc resulting from GD->IE. */ char tls_mask; }; /* ppc64 ELF linker hash table. */ struct ppc_link_hash_table { struct elf_link_hash_table elf; /* The stub hash table. */ struct bfd_hash_table stub_hash_table; /* Another hash table for plt_branch stubs. */ struct bfd_hash_table branch_hash_table; /* Linker stub bfd. */ bfd *stub_bfd; /* Linker call-backs. */ asection * (*add_stub_section) (const char *, asection *); void (*layout_sections_again) (void); /* Array to keep track of which stub sections have been created, and information on stub grouping. */ struct map_stub { /* This is the section to which stubs in the group will be attached. */ asection *link_sec; /* The stub section. */ asection *stub_sec; /* Along with elf_gp, specifies the TOC pointer used in this group. */ bfd_vma toc_off; } *stub_group; /* Temp used when calculating TOC pointers. */ bfd_vma toc_curr; /* Highest input section id. */ int top_id; /* Highest output section index. */ int top_index; /* Used when adding symbols. */ struct ppc_link_hash_entry *dot_syms; /* List of input sections for each output section. */ asection **input_list; /* Short-cuts to get to dynamic linker sections. */ asection *got; asection *plt; asection *relplt; asection *dynbss; asection *relbss; asection *glink; asection *sfpr; asection *brlt; asection *relbrlt; /* Shortcut to .__tls_get_addr and __tls_get_addr. */ struct ppc_link_hash_entry *tls_get_addr; struct ppc_link_hash_entry *tls_get_addr_fd; /* Statistics. */ unsigned long stub_count[ppc_stub_plt_call]; /* Number of stubs against global syms. */ unsigned long stub_globals; /* Set if we should emit symbols for stubs. */ unsigned int emit_stub_syms:1; /* Support for multiple toc sections. */ unsigned int no_multi_toc:1; unsigned int multi_toc_needed:1; /* Set on error. */ unsigned int stub_error:1; /* Temp used by ppc64_elf_check_directives. */ unsigned int twiddled_syms:1; /* Incremented every time we size stubs. */ unsigned int stub_iteration; /* Small local sym to section mapping cache. */ struct sym_sec_cache sym_sec; }; /* Rename some of the generic section flags to better document how they are used here. */ #define has_toc_reloc has_gp_reloc #define makes_toc_func_call need_finalize_relax #define call_check_in_progress reloc_done /* Get the ppc64 ELF linker hash table from a link_info structure. */ #define ppc_hash_table(p) \ ((struct ppc_link_hash_table *) ((p)->hash)) #define ppc_stub_hash_lookup(table, string, create, copy) \ ((struct ppc_stub_hash_entry *) \ bfd_hash_lookup ((table), (string), (create), (copy))) #define ppc_branch_hash_lookup(table, string, create, copy) \ ((struct ppc_branch_hash_entry *) \ bfd_hash_lookup ((table), (string), (create), (copy))) /* Create an entry in the stub hash table. */ static struct bfd_hash_entry * stub_hash_newfunc (struct bfd_hash_entry *entry, struct bfd_hash_table *table, const char *string) { /* Allocate the structure if it has not already been allocated by a subclass. */ if (entry == NULL) { entry = bfd_hash_allocate (table, sizeof (struct ppc_stub_hash_entry)); if (entry == NULL) return entry; } /* Call the allocation method of the superclass. */ entry = bfd_hash_newfunc (entry, table, string); if (entry != NULL) { struct ppc_stub_hash_entry *eh; /* Initialize the local fields. */ eh = (struct ppc_stub_hash_entry *) entry; eh->stub_type = ppc_stub_none; eh->stub_sec = NULL; eh->stub_offset = 0; eh->target_value = 0; eh->target_section = NULL; eh->h = NULL; eh->id_sec = NULL; } return entry; } /* Create an entry in the branch hash table. */ static struct bfd_hash_entry * branch_hash_newfunc (struct bfd_hash_entry *entry, struct bfd_hash_table *table, const char *string) { /* Allocate the structure if it has not already been allocated by a subclass. */ if (entry == NULL) { entry = bfd_hash_allocate (table, sizeof (struct ppc_branch_hash_entry)); if (entry == NULL) return entry; } /* Call the allocation method of the superclass. */ entry = bfd_hash_newfunc (entry, table, string); if (entry != NULL) { struct ppc_branch_hash_entry *eh; /* Initialize the local fields. */ eh = (struct ppc_branch_hash_entry *) entry; eh->offset = 0; eh->iter = 0; } return entry; } /* Create an entry in a ppc64 ELF linker hash table. */ static struct bfd_hash_entry * link_hash_newfunc (struct bfd_hash_entry *entry, struct bfd_hash_table *table, const char *string) { /* Allocate the structure if it has not already been allocated by a subclass. */ if (entry == NULL) { entry = bfd_hash_allocate (table, sizeof (struct ppc_link_hash_entry)); if (entry == NULL) return entry; } /* Call the allocation method of the superclass. */ entry = _bfd_elf_link_hash_newfunc (entry, table, string); if (entry != NULL) { struct ppc_link_hash_entry *eh = (struct ppc_link_hash_entry *) entry; memset (&eh->u.stub_cache, 0, (sizeof (struct ppc_link_hash_entry) - offsetof (struct ppc_link_hash_entry, u.stub_cache))); /* When making function calls, old ABI code references function entry points (dot symbols), while new ABI code references the function descriptor symbol. We need to make any combination of reference and definition work together, without breaking archive linking. For a defined function "foo" and an undefined call to "bar": An old object defines "foo" and ".foo", references ".bar" (possibly "bar" too). A new object defines "foo" and references "bar". A new object thus has no problem with its undefined symbols being satisfied by definitions in an old object. On the other hand, the old object won't have ".bar" satisfied by a new object. Keep a list of newly added dot-symbols. */ if (string[0] == '.') { struct ppc_link_hash_table *htab; htab = (struct ppc_link_hash_table *) table; eh->u.next_dot_sym = htab->dot_syms; htab->dot_syms = eh; } } return entry; } /* Create a ppc64 ELF linker hash table. */ static struct bfd_link_hash_table * ppc64_elf_link_hash_table_create (bfd *abfd) { struct ppc_link_hash_table *htab; bfd_size_type amt = sizeof (struct ppc_link_hash_table); htab = bfd_zmalloc (amt); if (htab == NULL) return NULL; 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, 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, sizeof (struct ppc_branch_hash_entry))) return NULL; /* Initializing two fields of the union is just cosmetic. We really only care about glist, but when compiled on a 32-bit host the bfd_vma fields are larger. Setting the bfd_vma to zero makes debugger inspection of these fields look nicer. */ htab->elf.init_got_refcount.refcount = 0; htab->elf.init_got_refcount.glist = NULL; htab->elf.init_plt_refcount.refcount = 0; htab->elf.init_plt_refcount.glist = NULL; htab->elf.init_got_offset.offset = 0; htab->elf.init_got_offset.glist = NULL; htab->elf.init_plt_offset.offset = 0; htab->elf.init_plt_offset.glist = NULL; return &htab->elf.root; } /* Free the derived linker hash table. */ static void ppc64_elf_link_hash_table_free (struct bfd_link_hash_table *hash) { struct ppc_link_hash_table *ret = (struct ppc_link_hash_table *) hash; bfd_hash_table_free (&ret->stub_hash_table); bfd_hash_table_free (&ret->branch_hash_table); _bfd_generic_link_hash_table_free (hash); } /* Satisfy the ELF linker by filling in some fields in our fake bfd. */ void ppc64_elf_init_stub_bfd (bfd *abfd, struct bfd_link_info *info) { struct ppc_link_hash_table *htab; elf_elfheader (abfd)->e_ident[EI_CLASS] = ELFCLASS64; /* Always hook our dynamic sections into the first bfd, which is the linker created stub bfd. This ensures that the GOT header is at the start of the output TOC section. */ htab = ppc_hash_table (info); htab->stub_bfd = abfd; htab->elf.dynobj = abfd; } /* Build a name for an entry in the stub hash table. */ static char * ppc_stub_name (const asection *input_section, const asection *sym_sec, const struct ppc_link_hash_entry *h, const Elf_Internal_Rela *rel) { char *stub_name; bfd_size_type len; /* rel->r_addend is actually 64 bit, but who uses more than +/- 2^31 offsets from a sym as a branch target? In fact, we could probably assume the addend is always zero. */ BFD_ASSERT (((int) rel->r_addend & 0xffffffff) == rel->r_addend); if (h) { len = 8 + 1 + strlen (h->elf.root.root.string) + 1 + 8 + 1; stub_name = bfd_malloc (len); if (stub_name == NULL) return stub_name; sprintf (stub_name, "%08x.%s+%x", input_section->id & 0xffffffff, h->elf.root.root.string, (int) rel->r_addend & 0xffffffff); } else { len = 8 + 1 + 8 + 1 + 8 + 1 + 8 + 1; stub_name = bfd_malloc (len); if (stub_name == NULL) return stub_name; sprintf (stub_name, "%08x.%x:%x+%x", input_section->id & 0xffffffff, sym_sec->id & 0xffffffff, (int) ELF64_R_SYM (rel->r_info) & 0xffffffff, (int) rel->r_addend & 0xffffffff); } if (stub_name[len - 2] == '+' && stub_name[len - 1] == '0') stub_name[len - 2] = 0; return stub_name; } /* Look up an entry in the stub hash. Stub entries are cached because creating the stub name takes a bit of time. */ static struct ppc_stub_hash_entry * ppc_get_stub_entry (const asection *input_section, const asection *sym_sec, struct ppc_link_hash_entry *h, const Elf_Internal_Rela *rel, struct ppc_link_hash_table *htab) { struct ppc_stub_hash_entry *stub_entry; const asection *id_sec; /* If this input section is part of a group of sections sharing one stub section, then use the id of the first section in the group. Stub names need to include a section id, as there may well be more than one stub used to reach say, printf, and we need to distinguish between them. */ id_sec = htab->stub_group[input_section->id].link_sec; if (h != NULL && h->u.stub_cache != NULL && h->u.stub_cache->h == h && h->u.stub_cache->id_sec == id_sec) { stub_entry = h->u.stub_cache; } else { char *stub_name; stub_name = ppc_stub_name (id_sec, sym_sec, h, rel); if (stub_name == NULL) return NULL; stub_entry = ppc_stub_hash_lookup (&htab->stub_hash_table, stub_name, FALSE, FALSE); if (h != NULL) h->u.stub_cache = stub_entry; free (stub_name); } return stub_entry; } /* Add a new stub entry to the stub hash. Not all fields of the new stub entry are initialised. */ static struct ppc_stub_hash_entry * ppc_add_stub (const char *stub_name, asection *section, struct ppc_link_hash_table *htab) { asection *link_sec; asection *stub_sec; struct ppc_stub_hash_entry *stub_entry; link_sec = htab->stub_group[section->id].link_sec; stub_sec = htab->stub_group[section->id].stub_sec; if (stub_sec == NULL) { stub_sec = htab->stub_group[link_sec->id].stub_sec; if (stub_sec == NULL) { size_t namelen; bfd_size_type len; char *s_name; namelen = strlen (link_sec->name); len = namelen + sizeof (STUB_SUFFIX); s_name = bfd_alloc (htab->stub_bfd, len); if (s_name == NULL) return NULL; memcpy (s_name, link_sec->name, namelen); memcpy (s_name + namelen, STUB_SUFFIX, sizeof (STUB_SUFFIX)); stub_sec = (*htab->add_stub_section) (s_name, link_sec); if (stub_sec == NULL) return NULL; htab->stub_group[link_sec->id].stub_sec = stub_sec; } htab->stub_group[section->id].stub_sec = stub_sec; } /* Enter this entry into the linker stub hash table. */ stub_entry = ppc_stub_hash_lookup (&htab->stub_hash_table, stub_name, TRUE, FALSE); if (stub_entry == NULL) { (*_bfd_error_handler) (_("%B: cannot create stub entry %s"), section->owner, stub_name); return NULL; } stub_entry->stub_sec = stub_sec; stub_entry->stub_offset = 0; stub_entry->id_sec = link_sec; return stub_entry; } /* Create sections for linker generated code. */ static bfd_boolean create_linkage_sections (bfd *dynobj, struct bfd_link_info *info) { struct ppc_link_hash_table *htab; flagword flags; htab = ppc_hash_table (info); /* Create .sfpr for code to save and restore fp regs. */ flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_READONLY | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); htab->sfpr = bfd_make_section_anyway_with_flags (dynobj, ".sfpr", flags); if (htab->sfpr == NULL || ! bfd_set_section_alignment (dynobj, htab->sfpr, 2)) return FALSE; /* Create .glink for lazy dynamic linking support. */ htab->glink = bfd_make_section_anyway_with_flags (dynobj, ".glink", flags); if (htab->glink == NULL || ! bfd_set_section_alignment (dynobj, htab->glink, 3)) return FALSE; /* Create branch lookup table for plt_branch stubs. */ flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); htab->brlt = bfd_make_section_anyway_with_flags (dynobj, ".branch_lt", flags); if (htab->brlt == NULL || ! bfd_set_section_alignment (dynobj, htab->brlt, 3)) return FALSE; if (!info->shared) return TRUE; flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); htab->relbrlt = bfd_make_section_anyway_with_flags (dynobj, ".rela.branch_lt", flags); if (!htab->relbrlt || ! bfd_set_section_alignment (dynobj, htab->relbrlt, 3)) return FALSE; return TRUE; } /* Create .got and .rela.got sections in ABFD, and .got in dynobj if not already done. */ static bfd_boolean create_got_section (bfd *abfd, struct bfd_link_info *info) { asection *got, *relgot; flagword flags; struct ppc_link_hash_table *htab = ppc_hash_table (info); if (!htab->got) { if (! _bfd_elf_create_got_section (htab->elf.dynobj, info)) return FALSE; htab->got = bfd_get_section_by_name (htab->elf.dynobj, ".got"); if (!htab->got) abort (); } flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); got = bfd_make_section_anyway_with_flags (abfd, ".got", flags); if (!got || !bfd_set_section_alignment (abfd, got, 3)) return FALSE; relgot = bfd_make_section_anyway_with_flags (abfd, ".rela.got", flags | SEC_READONLY); if (!relgot || ! bfd_set_section_alignment (abfd, relgot, 3)) return FALSE; ppc64_elf_tdata (abfd)->got = got; ppc64_elf_tdata (abfd)->relgot = relgot; return TRUE; } /* Create the dynamic sections, and set up shortcuts. */ static bfd_boolean ppc64_elf_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info) { struct ppc_link_hash_table *htab; if (!_bfd_elf_create_dynamic_sections (dynobj, info)) return FALSE; htab = ppc_hash_table (info); if (!htab->got) htab->got = bfd_get_section_by_name (dynobj, ".got"); htab->plt = bfd_get_section_by_name (dynobj, ".plt"); htab->relplt = bfd_get_section_by_name (dynobj, ".rela.plt"); htab->dynbss = bfd_get_section_by_name (dynobj, ".dynbss"); if (!info->shared) htab->relbss = bfd_get_section_by_name (dynobj, ".rela.bss"); if (!htab->got || !htab->plt || !htab->relplt || !htab->dynbss || (!info->shared && !htab->relbss)) abort (); return TRUE; } /* Merge PLT info on FROM with that on TO. */ static void move_plt_plist (struct ppc_link_hash_entry *from, struct ppc_link_hash_entry *to) { if (from->elf.plt.plist != NULL) { if (to->elf.plt.plist != NULL) { struct plt_entry **entp; struct plt_entry *ent; for (entp = &from->elf.plt.plist; (ent = *entp) != NULL; ) { struct plt_entry *dent; for (dent = to->elf.plt.plist; dent != NULL; dent = dent->next) if (dent->addend == ent->addend) { dent->plt.refcount += ent->plt.refcount; *entp = ent->next; break; } if (dent == NULL) entp = &ent->next; } *entp = to->elf.plt.plist; } to->elf.plt.plist = from->elf.plt.plist; from->elf.plt.plist = NULL; } } /* Copy the extra info we tack onto an elf_link_hash_entry. */ static void ppc64_elf_copy_indirect_symbol (struct bfd_link_info *info, struct elf_link_hash_entry *dir, struct elf_link_hash_entry *ind) { struct ppc_link_hash_entry *edir, *eind; edir = (struct ppc_link_hash_entry *) dir; eind = (struct ppc_link_hash_entry *) ind; /* Copy over any dynamic relocs we may have on the indirect sym. */ if (eind->dyn_relocs != NULL) { if (edir->dyn_relocs != NULL) { struct ppc_dyn_relocs **pp; struct ppc_dyn_relocs *p; /* Add reloc counts against the indirect sym to the direct sym list. Merge any entries against the same section. */ for (pp = &eind->dyn_relocs; (p = *pp) != NULL; ) { struct ppc_dyn_relocs *q; for (q = edir->dyn_relocs; q != NULL; q = q->next) if (q->sec == p->sec) { q->pc_count += p->pc_count; q->count += p->count; *pp = p->next; break; } if (q == NULL) pp = &p->next; } *pp = edir->dyn_relocs; } edir->dyn_relocs = eind->dyn_relocs; eind->dyn_relocs = NULL; } edir->is_func |= eind->is_func; edir->is_func_descriptor |= eind->is_func_descriptor; edir->tls_mask |= eind->tls_mask; /* If called to transfer flags for a weakdef during processing of elf_adjust_dynamic_symbol, don't copy NON_GOT_REF. We clear it ourselves for ELIMINATE_COPY_RELOCS. */ if (!(ELIMINATE_COPY_RELOCS && eind->elf.root.type != bfd_link_hash_indirect && edir->elf.dynamic_adjusted)) edir->elf.non_got_ref |= eind->elf.non_got_ref; edir->elf.ref_dynamic |= eind->elf.ref_dynamic; edir->elf.ref_regular |= eind->elf.ref_regular; edir->elf.ref_regular_nonweak |= eind->elf.ref_regular_nonweak; edir->elf.needs_plt |= eind->elf.needs_plt; /* If we were called to copy over info for a weak sym, that's all. */ if (eind->elf.root.type != bfd_link_hash_indirect) return; /* Copy over got entries that we may have already seen to the symbol which just became indirect. */ if (eind->elf.got.glist != NULL) { if (edir->elf.got.glist != NULL) { struct got_entry **entp; struct got_entry *ent; for (entp = &eind->elf.got.glist; (ent = *entp) != NULL; ) { struct got_entry *dent; for (dent = edir->elf.got.glist; dent != NULL; dent = dent->next) if (dent->addend == ent->addend && dent->owner == ent->owner && dent->tls_type == ent->tls_type) { dent->got.refcount += ent->got.refcount; *entp = ent->next; break; } if (dent == NULL) entp = &ent->next; } *entp = edir->elf.got.glist; } edir->elf.got.glist = eind->elf.got.glist; eind->elf.got.glist = NULL; } /* And plt entries. */ move_plt_plist (eind, edir); if (eind->elf.dynindx != -1) { if (edir->elf.dynindx != -1) _bfd_elf_strtab_delref (elf_hash_table (info)->dynstr, edir->elf.dynstr_index); edir->elf.dynindx = eind->elf.dynindx; edir->elf.dynstr_index = eind->elf.dynstr_index; eind->elf.dynindx = -1; eind->elf.dynstr_index = 0; } } /* Find the function descriptor hash entry from the given function code hash entry FH. Link the entries via their OH fields. */ static struct ppc_link_hash_entry * get_fdh (struct ppc_link_hash_entry *fh, struct ppc_link_hash_table *htab) { struct ppc_link_hash_entry *fdh = fh->oh; if (fdh == NULL) { const char *fd_name = fh->elf.root.root.string + 1; fdh = (struct ppc_link_hash_entry *) elf_link_hash_lookup (&htab->elf, fd_name, FALSE, FALSE, FALSE); if (fdh != NULL) { fdh->is_func_descriptor = 1; fdh->oh = fh; fh->is_func = 1; fh->oh = fdh; } } return fdh; } /* Make a fake function descriptor sym for the code sym FH. */ static struct ppc_link_hash_entry * make_fdh (struct bfd_link_info *info, struct ppc_link_hash_entry *fh) { bfd *abfd; asymbol *newsym; struct bfd_link_hash_entry *bh; struct ppc_link_hash_entry *fdh; abfd = fh->elf.root.u.undef.abfd; newsym = bfd_make_empty_symbol (abfd); newsym->name = fh->elf.root.root.string + 1; newsym->section = bfd_und_section_ptr; newsym->value = 0; newsym->flags = BSF_WEAK; bh = NULL; if (!_bfd_generic_link_add_one_symbol (info, abfd, newsym->name, newsym->flags, newsym->section, newsym->value, NULL, FALSE, FALSE, &bh)) return NULL; fdh = (struct ppc_link_hash_entry *) bh; fdh->elf.non_elf = 0; fdh->fake = 1; fdh->is_func_descriptor = 1; fdh->oh = fh; fh->is_func = 1; fh->oh = fdh; return fdh; } /* Fix function descriptor symbols defined in .opd sections to be function type. */ static bfd_boolean ppc64_elf_add_symbol_hook (bfd *ibfd ATTRIBUTE_UNUSED, struct bfd_link_info *info ATTRIBUTE_UNUSED, Elf_Internal_Sym *isym, const char **name ATTRIBUTE_UNUSED, flagword *flags ATTRIBUTE_UNUSED, asection **sec, bfd_vma *value ATTRIBUTE_UNUSED) { if (*sec != NULL && strcmp (bfd_get_section_name (ibfd, *sec), ".opd") == 0) isym->st_info = ELF_ST_INFO (ELF_ST_BIND (isym->st_info), STT_FUNC); return TRUE; } /* This function makes an old ABI object reference to ".bar" cause the inclusion of a new ABI object archive that defines "bar". NAME is a symbol defined in an archive. Return a symbol in the hash table that might be satisfied by the archive symbols. */ static struct elf_link_hash_entry * ppc64_elf_archive_symbol_lookup (bfd *abfd, struct bfd_link_info *info, const char *name) { struct elf_link_hash_entry *h; char *dot_name; size_t len; h = _bfd_elf_archive_symbol_lookup (abfd, info, name); if (h != NULL /* Don't return this sym if it is a fake function descriptor created by add_symbol_adjust. */ && !(h->root.type == bfd_link_hash_undefweak && ((struct ppc_link_hash_entry *) h)->fake)) return h; if (name[0] == '.') return h; len = strlen (name); dot_name = bfd_alloc (abfd, len + 2); if (dot_name == NULL) return (struct elf_link_hash_entry *) 0 - 1; dot_name[0] = '.'; memcpy (dot_name + 1, name, len + 1); h = _bfd_elf_archive_symbol_lookup (abfd, info, dot_name); bfd_release (abfd, dot_name); return h; } /* This function satisfies all old ABI object references to ".bar" if a new ABI object defines "bar". Well, at least, undefined dot symbols are made weak. This stops later archive searches from including an object if we already have a function descriptor definition. It also prevents the linker complaining about undefined symbols. We also check and correct mismatched symbol visibility here. The most restrictive visibility of the function descriptor and the function entry symbol is used. */ static bfd_boolean add_symbol_adjust (struct ppc_link_hash_entry *eh, struct bfd_link_info *info) { struct ppc_link_hash_table *htab; struct ppc_link_hash_entry *fdh; if (eh->elf.root.type == bfd_link_hash_indirect) return TRUE; if (eh->elf.root.type == bfd_link_hash_warning) eh = (struct ppc_link_hash_entry *) eh->elf.root.u.i.link; if (eh->elf.root.root.string[0] != '.') abort (); htab = ppc_hash_table (info); fdh = get_fdh (eh, htab); if (fdh == NULL && !info->relocatable && (eh->elf.root.type == bfd_link_hash_undefined || eh->elf.root.type == bfd_link_hash_undefweak) && eh->elf.ref_regular) { /* Make an undefweak function descriptor sym, which is enough to pull in an --as-needed shared lib, but won't cause link errors. Archives are handled elsewhere. */ fdh = make_fdh (info, eh); if (fdh == NULL) return FALSE; else fdh->elf.ref_regular = 1; } else if (fdh != NULL) { unsigned entry_vis = ELF_ST_VISIBILITY (eh->elf.other) - 1; unsigned descr_vis = ELF_ST_VISIBILITY (fdh->elf.other) - 1; if (entry_vis < descr_vis) fdh->elf.other += entry_vis - descr_vis; else if (entry_vis > descr_vis) eh->elf.other += descr_vis - entry_vis; if ((fdh->elf.root.type == bfd_link_hash_defined || fdh->elf.root.type == bfd_link_hash_defweak) && eh->elf.root.type == bfd_link_hash_undefined) { eh->elf.root.type = bfd_link_hash_undefweak; eh->was_undefined = 1; htab->twiddled_syms = 1; } } return TRUE; } /* Process list of dot-symbols we made in link_hash_newfunc. */ static bfd_boolean ppc64_elf_check_directives (bfd *ibfd, struct bfd_link_info *info) { struct ppc_link_hash_table *htab; struct ppc_link_hash_entry **p, *eh; htab = ppc_hash_table (info); if (!is_ppc64_elf_target (htab->elf.root.creator)) return TRUE; if (is_ppc64_elf_target (ibfd->xvec)) { p = &htab->dot_syms; while ((eh = *p) != NULL) { *p = NULL; if (!add_symbol_adjust (eh, info)) return FALSE; p = &eh->u.next_dot_sym; } } /* Clear the list for non-ppc64 input files. */ p = &htab->dot_syms; while ((eh = *p) != NULL) { *p = NULL; p = &eh->u.next_dot_sym; } /* We need to fix the undefs list for any syms we have twiddled to undef_weak. */ if (htab->twiddled_syms) { bfd_link_repair_undef_list (&htab->elf.root); htab->twiddled_syms = 0; } return TRUE; } /* Undo hash table changes when an --as-needed input file is determined not to be needed. */ static bfd_boolean ppc64_elf_as_needed_cleanup (bfd *ibfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) { ppc_hash_table (info)->dot_syms = NULL; return TRUE; } static bfd_boolean update_local_sym_info (bfd *abfd, Elf_Internal_Shdr *symtab_hdr, unsigned long r_symndx, bfd_vma r_addend, int tls_type) { struct got_entry **local_got_ents = elf_local_got_ents (abfd); char *local_got_tls_masks; if (local_got_ents == NULL) { bfd_size_type size = symtab_hdr->sh_info; size *= sizeof (*local_got_ents) + sizeof (*local_got_tls_masks); local_got_ents = bfd_zalloc (abfd, size); if (local_got_ents == NULL) return FALSE; elf_local_got_ents (abfd) = local_got_ents; } if ((tls_type & TLS_EXPLICIT) == 0) { struct got_entry *ent; for (ent = local_got_ents[r_symndx]; ent != NULL; ent = ent->next) if (ent->addend == r_addend && ent->owner == abfd && ent->tls_type == tls_type) break; if (ent == NULL) { bfd_size_type amt = sizeof (*ent); ent = bfd_alloc (abfd, amt); if (ent == NULL) return FALSE; ent->next = local_got_ents[r_symndx]; ent->addend = r_addend; ent->owner = abfd; ent->tls_type = tls_type; ent->got.refcount = 0; local_got_ents[r_symndx] = ent; } ent->got.refcount += 1; } local_got_tls_masks = (char *) (local_got_ents + symtab_hdr->sh_info); local_got_tls_masks[r_symndx] |= tls_type; return TRUE; } static bfd_boolean update_plt_info (bfd *abfd, struct ppc_link_hash_entry *eh, bfd_vma addend) { struct plt_entry *ent; for (ent = eh->elf.plt.plist; ent != NULL; ent = ent->next) if (ent->addend == addend) break; if (ent == NULL) { bfd_size_type amt = sizeof (*ent); ent = bfd_alloc (abfd, amt); if (ent == NULL) return FALSE; ent->next = eh->elf.plt.plist; ent->addend = addend; ent->plt.refcount = 0; eh->elf.plt.plist = ent; } ent->plt.refcount += 1; eh->elf.needs_plt = 1; if (eh->elf.root.root.string[0] == '.' && eh->elf.root.root.string[1] != '\0') eh->is_func = 1; return TRUE; } /* Look through the relocs for a section during the first phase, and calculate needed space in the global offset table, procedure linkage table, and dynamic reloc sections. */ static bfd_boolean ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec, const Elf_Internal_Rela *relocs) { struct ppc_link_hash_table *htab; 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; asection *sreloc; asection **opd_sym_map; + struct elf_link_hash_entry *tga, *dottga; if (info->relocatable) return TRUE; /* Don't do anything special with non-loaded, non-alloced sections. In particular, any relocs in such sections should not affect GOT and PLT reference counting (ie. we don't allow them to create GOT or PLT entries), there's no possibility or desire to optimize TLS relocs, and there's not much point in propagating relocs to shared libs that the dynamic linker won't relocate. */ if ((sec->flags & SEC_ALLOC) == 0) return TRUE; htab = ppc_hash_table (info); + tga = elf_link_hash_lookup (&htab->elf, "__tls_get_addr", + FALSE, FALSE, TRUE); + dottga = elf_link_hash_lookup (&htab->elf, ".__tls_get_addr", + FALSE, FALSE, TRUE); symtab_hdr = &elf_tdata (abfd)->symtab_hdr; sym_hashes = elf_sym_hashes (abfd); sym_hashes_end = (sym_hashes + symtab_hdr->sh_size / sizeof (Elf64_External_Sym) - symtab_hdr->sh_info); sreloc = NULL; opd_sym_map = NULL; if (strcmp (bfd_get_section_name (abfd, sec), ".opd") == 0) { /* Garbage collection needs some extra help with .opd sections. We don't want to necessarily keep everything referenced by relocs in .opd, as that would keep all functions. Instead, if we reference an .opd symbol (a function descriptor), we want to keep the function code symbol's section. This is easy for global symbols, but for local syms we need to keep information about the associated function section. Later, if edit_opd deletes entries, we'll use this array to adjust local syms in .opd. */ union opd_info { asection *func_section; long entry_adjust; }; bfd_size_type amt; amt = sec->size * sizeof (union opd_info) / 8; opd_sym_map = bfd_zalloc (abfd, amt); if (opd_sym_map == NULL) return FALSE; ppc64_elf_section_data (sec)->u.opd_func_sec = opd_sym_map; BFD_ASSERT (ppc64_elf_section_data (sec)->sec_type == sec_normal); ppc64_elf_section_data (sec)->sec_type = sec_opd; } if (htab->sfpr == NULL && !create_linkage_sections (htab->elf.dynobj, info)) return FALSE; rel_end = relocs + sec->reloc_count; for (rel = relocs; rel < rel_end; rel++) { unsigned long r_symndx; struct elf_link_hash_entry *h; enum elf_ppc64_reloc_type r_type; - int tls_type = 0; + int tls_type; struct _ppc64_elf_section_data *ppc64_sec; r_symndx = ELF64_R_SYM (rel->r_info); if (r_symndx < symtab_hdr->sh_info) h = NULL; 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; } + tls_type = 0; r_type = ELF64_R_TYPE (rel->r_info); + if (h != NULL && (h == tga || h == dottga)) + switch (r_type) + { + default: + break; + + case R_PPC64_REL24: + case R_PPC64_REL14: + case R_PPC64_REL14_BRTAKEN: + case R_PPC64_REL14_BRNTAKEN: + case R_PPC64_ADDR24: + case R_PPC64_ADDR14: + case R_PPC64_ADDR14_BRTAKEN: + case R_PPC64_ADDR14_BRNTAKEN: + if (rel != relocs + && (ELF64_R_TYPE (rel[-1].r_info) == R_PPC64_TLSGD + || ELF64_R_TYPE (rel[-1].r_info) == R_PPC64_TLSLD)) + /* We have a new-style __tls_get_addr call with a marker + reloc. */ + ; + else + /* Mark this section as having an old-style call. */ + sec->has_tls_get_addr_call = 1; + break; + } + switch (r_type) { + case R_PPC64_TLSGD: + case R_PPC64_TLSLD: + /* These special tls relocs tie a call to __tls_get_addr with + its parameter symbol. */ + break; + case R_PPC64_GOT_TLSLD16: case R_PPC64_GOT_TLSLD16_LO: case R_PPC64_GOT_TLSLD16_HI: case R_PPC64_GOT_TLSLD16_HA: - ppc64_tlsld_got (abfd)->refcount += 1; tls_type = TLS_TLS | TLS_LD; goto dogottls; case R_PPC64_GOT_TLSGD16: case R_PPC64_GOT_TLSGD16_LO: case R_PPC64_GOT_TLSGD16_HI: case R_PPC64_GOT_TLSGD16_HA: tls_type = TLS_TLS | TLS_GD; goto dogottls; case R_PPC64_GOT_TPREL16_DS: case R_PPC64_GOT_TPREL16_LO_DS: case R_PPC64_GOT_TPREL16_HI: case R_PPC64_GOT_TPREL16_HA: - if (info->shared) + if (!info->executable) info->flags |= DF_STATIC_TLS; tls_type = TLS_TLS | TLS_TPREL; goto dogottls; case R_PPC64_GOT_DTPREL16_DS: case R_PPC64_GOT_DTPREL16_LO_DS: case R_PPC64_GOT_DTPREL16_HI: case R_PPC64_GOT_DTPREL16_HA: tls_type = TLS_TLS | TLS_DTPREL; dogottls: sec->has_tls_reloc = 1; /* Fall thru */ case R_PPC64_GOT16: case R_PPC64_GOT16_DS: case R_PPC64_GOT16_HA: case R_PPC64_GOT16_HI: case R_PPC64_GOT16_LO: case R_PPC64_GOT16_LO_DS: /* This symbol requires a global offset table entry. */ sec->has_toc_reloc = 1; if (ppc64_elf_tdata (abfd)->got == NULL && !create_got_section (abfd, info)) return FALSE; if (h != NULL) { struct ppc_link_hash_entry *eh; struct got_entry *ent; eh = (struct ppc_link_hash_entry *) h; for (ent = eh->elf.got.glist; ent != NULL; ent = ent->next) if (ent->addend == rel->r_addend && ent->owner == abfd && ent->tls_type == tls_type) break; if (ent == NULL) { bfd_size_type amt = sizeof (*ent); ent = bfd_alloc (abfd, amt); if (ent == NULL) return FALSE; ent->next = eh->elf.got.glist; ent->addend = rel->r_addend; ent->owner = abfd; ent->tls_type = tls_type; ent->got.refcount = 0; eh->elf.got.glist = ent; } ent->got.refcount += 1; eh->tls_mask |= tls_type; } else /* This is a global offset table entry for a local symbol. */ if (!update_local_sym_info (abfd, symtab_hdr, r_symndx, rel->r_addend, tls_type)) return FALSE; break; case R_PPC64_PLT16_HA: case R_PPC64_PLT16_HI: case R_PPC64_PLT16_LO: case R_PPC64_PLT32: case R_PPC64_PLT64: /* This symbol requires a procedure linkage table entry. We actually build the entry in adjust_dynamic_symbol, because this might be a case of linking PIC code without linking in any dynamic objects, in which case we don't need to generate a procedure linkage table after all. */ if (h == NULL) { /* It does not make sense to have a procedure linkage table entry for a local symbol. */ bfd_set_error (bfd_error_bad_value); return FALSE; } else if (!update_plt_info (abfd, (struct ppc_link_hash_entry *) h, rel->r_addend)) return FALSE; break; /* The following relocations don't need to propagate the relocation if linking a shared object since they are section relative. */ case R_PPC64_SECTOFF: case R_PPC64_SECTOFF_LO: case R_PPC64_SECTOFF_HI: case R_PPC64_SECTOFF_HA: case R_PPC64_SECTOFF_DS: case R_PPC64_SECTOFF_LO_DS: case R_PPC64_DTPREL16: case R_PPC64_DTPREL16_LO: case R_PPC64_DTPREL16_HI: case R_PPC64_DTPREL16_HA: case R_PPC64_DTPREL16_DS: case R_PPC64_DTPREL16_LO_DS: case R_PPC64_DTPREL16_HIGHER: case R_PPC64_DTPREL16_HIGHERA: case R_PPC64_DTPREL16_HIGHEST: case R_PPC64_DTPREL16_HIGHESTA: break; /* Nor do these. */ case R_PPC64_TOC16: case R_PPC64_TOC16_LO: case R_PPC64_TOC16_HI: case R_PPC64_TOC16_HA: case R_PPC64_TOC16_DS: case R_PPC64_TOC16_LO_DS: sec->has_toc_reloc = 1; break; /* This relocation describes the C++ object vtable hierarchy. Reconstruct it for later use during GC. */ case R_PPC64_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_PPC64_GNU_VTENTRY: if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) return FALSE; break; case R_PPC64_REL14: case R_PPC64_REL14_BRTAKEN: case R_PPC64_REL14_BRNTAKEN: { asection *dest = NULL; /* Heuristic: If jumping outside our section, chances are we are going to need a stub. */ if (h != NULL) { /* If the sym is weak it may be overridden later, so don't assume we know where a weak sym lives. */ if (h->root.type == bfd_link_hash_defined) dest = h->root.u.def.section; } else dest = bfd_section_from_r_symndx (abfd, &htab->sym_sec, sec, r_symndx); if (dest != sec) ppc64_elf_section_data (sec)->has_14bit_branch = 1; } /* Fall through. */ case R_PPC64_REL24: if (h != NULL) { /* We may need a .plt entry if the function this reloc refers to is in a shared lib. */ if (!update_plt_info (abfd, (struct ppc_link_hash_entry *) h, rel->r_addend)) return FALSE; - if (h == &htab->tls_get_addr->elf - || h == &htab->tls_get_addr_fd->elf) + if (h == tga || h == dottga) sec->has_tls_reloc = 1; - else if (htab->tls_get_addr == NULL - && CONST_STRNEQ (h->root.root.string, ".__tls_get_addr") - && (h->root.root.string[15] == 0 - || h->root.root.string[15] == '@')) - { - htab->tls_get_addr = (struct ppc_link_hash_entry *) h; - sec->has_tls_reloc = 1; - } - else if (htab->tls_get_addr_fd == NULL - && CONST_STRNEQ (h->root.root.string, "__tls_get_addr") - && (h->root.root.string[14] == 0 - || h->root.root.string[14] == '@')) - { - htab->tls_get_addr_fd = (struct ppc_link_hash_entry *) h; - sec->has_tls_reloc = 1; - } } break; case R_PPC64_TPREL64: tls_type = TLS_EXPLICIT | TLS_TLS | TLS_TPREL; - if (info->shared) + if (!info->executable) info->flags |= DF_STATIC_TLS; goto dotlstoc; case R_PPC64_DTPMOD64: if (rel + 1 < rel_end && rel[1].r_info == ELF64_R_INFO (r_symndx, R_PPC64_DTPREL64) && rel[1].r_offset == rel->r_offset + 8) tls_type = TLS_EXPLICIT | TLS_TLS | TLS_GD; else tls_type = TLS_EXPLICIT | TLS_TLS | TLS_LD; goto dotlstoc; case R_PPC64_DTPREL64: tls_type = TLS_EXPLICIT | TLS_TLS | TLS_DTPREL; if (rel != relocs && rel[-1].r_info == ELF64_R_INFO (r_symndx, R_PPC64_DTPMOD64) && rel[-1].r_offset == rel->r_offset - 8) /* This is the second reloc of a dtpmod, dtprel pair. Don't mark with TLS_DTPREL. */ goto dodyn; dotlstoc: sec->has_tls_reloc = 1; if (h != NULL) { struct ppc_link_hash_entry *eh; eh = (struct ppc_link_hash_entry *) h; eh->tls_mask |= tls_type; } else if (!update_local_sym_info (abfd, symtab_hdr, r_symndx, rel->r_addend, tls_type)) return FALSE; ppc64_sec = ppc64_elf_section_data (sec); if (ppc64_sec->sec_type != sec_toc) { + bfd_size_type amt; + /* One extra to simplify get_tls_mask. */ - bfd_size_type amt = sec->size * sizeof (unsigned) / 8 + 1; - ppc64_sec->u.t_symndx = bfd_zalloc (abfd, amt); - if (ppc64_sec->u.t_symndx == NULL) + amt = sec->size * sizeof (unsigned) / 8 + sizeof (unsigned); + ppc64_sec->u.toc.symndx = bfd_zalloc (abfd, amt); + if (ppc64_sec->u.toc.symndx == NULL) return FALSE; + amt = sec->size * sizeof (bfd_vma) / 8; + ppc64_sec->u.toc.add = bfd_zalloc (abfd, amt); + if (ppc64_sec->u.toc.add == NULL) + return FALSE; BFD_ASSERT (ppc64_sec->sec_type == sec_normal); ppc64_sec->sec_type = sec_toc; } BFD_ASSERT (rel->r_offset % 8 == 0); - ppc64_sec->u.t_symndx[rel->r_offset / 8] = r_symndx; + ppc64_sec->u.toc.symndx[rel->r_offset / 8] = r_symndx; + ppc64_sec->u.toc.add[rel->r_offset / 8] = rel->r_addend; /* Mark the second slot of a GD or LD entry. -1 to indicate GD and -2 to indicate LD. */ if (tls_type == (TLS_EXPLICIT | TLS_TLS | TLS_GD)) - ppc64_sec->u.t_symndx[rel->r_offset / 8 + 1] = -1; + ppc64_sec->u.toc.symndx[rel->r_offset / 8 + 1] = -1; else if (tls_type == (TLS_EXPLICIT | TLS_TLS | TLS_LD)) - ppc64_sec->u.t_symndx[rel->r_offset / 8 + 1] = -2; + ppc64_sec->u.toc.symndx[rel->r_offset / 8 + 1] = -2; goto dodyn; case R_PPC64_TPREL16: case R_PPC64_TPREL16_LO: case R_PPC64_TPREL16_HI: case R_PPC64_TPREL16_HA: case R_PPC64_TPREL16_DS: case R_PPC64_TPREL16_LO_DS: case R_PPC64_TPREL16_HIGHER: case R_PPC64_TPREL16_HIGHERA: case R_PPC64_TPREL16_HIGHEST: case R_PPC64_TPREL16_HIGHESTA: if (info->shared) { - info->flags |= DF_STATIC_TLS; + if (!info->executable) + info->flags |= DF_STATIC_TLS; goto dodyn; } break; case R_PPC64_ADDR64: if (opd_sym_map != NULL && rel + 1 < rel_end && ELF64_R_TYPE ((rel + 1)->r_info) == R_PPC64_TOC) { if (h != NULL) { if (h->root.root.string[0] == '.' && h->root.root.string[1] != 0 && get_fdh ((struct ppc_link_hash_entry *) h, htab)) ; else ((struct ppc_link_hash_entry *) h)->is_func = 1; } else { asection *s; s = bfd_section_from_r_symndx (abfd, &htab->sym_sec, sec, r_symndx); if (s == NULL) return FALSE; else if (s != sec) opd_sym_map[rel->r_offset / 8] = s; } } /* Fall through. */ case R_PPC64_REL30: case R_PPC64_REL32: case R_PPC64_REL64: case R_PPC64_ADDR14: case R_PPC64_ADDR14_BRNTAKEN: case R_PPC64_ADDR14_BRTAKEN: case R_PPC64_ADDR16: case R_PPC64_ADDR16_DS: case R_PPC64_ADDR16_HA: case R_PPC64_ADDR16_HI: case R_PPC64_ADDR16_HIGHER: case R_PPC64_ADDR16_HIGHERA: case R_PPC64_ADDR16_HIGHEST: case R_PPC64_ADDR16_HIGHESTA: case R_PPC64_ADDR16_LO: case R_PPC64_ADDR16_LO_DS: case R_PPC64_ADDR24: case R_PPC64_ADDR32: case R_PPC64_UADDR16: case R_PPC64_UADDR32: case R_PPC64_UADDR64: case R_PPC64_TOC: if (h != NULL && !info->shared) /* We may need a copy reloc. */ h->non_got_ref = 1; /* Don't propagate .opd relocs. */ if (NO_OPD_RELOCS && opd_sym_map != NULL) break; /* If we are creating a shared library, and this is a reloc against a global symbol, or a non PC relative reloc against a local symbol, then we need to copy the reloc into the shared library. However, if we are linking with -Bsymbolic, we do not need to copy a reloc against a global symbol which is defined in an object we are including in the link (i.e., DEF_REGULAR is set). At this point we have not seen all the input files, so it is possible that DEF_REGULAR is not set now but will be set later (it is never cleared). In case of a weak definition, DEF_REGULAR may be cleared later by a strong definition in a shared library. We account for that possibility below by storing information in the dyn_relocs field of the hash table entry. A similar situation occurs when creating shared libraries and symbol visibility changes render the symbol local. If on the other hand, we are creating an executable, we may need to keep relocations for symbols satisfied by a dynamic library if we manage to avoid copy relocs for the symbol. */ dodyn: if ((info->shared - && (MUST_BE_DYN_RELOC (r_type) + && (must_be_dyn_reloc (info, r_type) || (h != NULL && (! info->symbolic || h->root.type == bfd_link_hash_defweak || !h->def_regular)))) || (ELIMINATE_COPY_RELOCS && !info->shared && h != NULL && (h->root.type == bfd_link_hash_defweak || !h->def_regular))) { struct ppc_dyn_relocs *p; struct ppc_dyn_relocs **head; /* We must copy these reloc types into the output file. Create a reloc section in dynobj and make room for this reloc. */ if (sreloc == NULL) { const char *name; bfd *dynobj; name = (bfd_elf_string_from_elf_section (abfd, elf_elfheader (abfd)->e_shstrndx, elf_section_data (sec)->rel_hdr.sh_name)); if (name == NULL) return FALSE; if (! CONST_STRNEQ (name, ".rela") || strcmp (bfd_get_section_name (abfd, sec), name + 5) != 0) { (*_bfd_error_handler) (_("%B: bad relocation section name `%s\'"), abfd, name); bfd_set_error (bfd_error_bad_value); } dynobj = htab->elf.dynobj; sreloc = bfd_get_section_by_name (dynobj, name); if (sreloc == NULL) { flagword flags; flags = (SEC_HAS_CONTENTS | SEC_READONLY | SEC_IN_MEMORY | SEC_LINKER_CREATED | SEC_ALLOC | SEC_LOAD); sreloc = bfd_make_section_with_flags (dynobj, name, flags); if (sreloc == NULL || ! bfd_set_section_alignment (dynobj, sreloc, 3)) return FALSE; } elf_section_data (sec)->sreloc = sreloc; } /* If this is a global symbol, we count the number of relocations we need for this symbol. */ if (h != NULL) { head = &((struct ppc_link_hash_entry *) h)->dyn_relocs; } else { /* Track dynamic relocs needed for local syms too. We really need local syms available to do this easily. Oh well. */ asection *s; void *vpp; s = bfd_section_from_r_symndx (abfd, &htab->sym_sec, sec, r_symndx); if (s == NULL) return FALSE; vpp = &elf_section_data (s)->local_dynrel; head = (struct ppc_dyn_relocs **) vpp; } p = *head; if (p == NULL || p->sec != sec) { p = bfd_alloc (htab->elf.dynobj, sizeof *p); if (p == NULL) return FALSE; p->next = *head; *head = p; p->sec = sec; p->count = 0; p->pc_count = 0; } p->count += 1; - if (!MUST_BE_DYN_RELOC (r_type)) + if (!must_be_dyn_reloc (info, r_type)) p->pc_count += 1; } break; default: break; } } return TRUE; } /* OFFSET in OPD_SEC specifies a function descriptor. Return the address of the code entry point, and its section. */ static bfd_vma opd_entry_value (asection *opd_sec, bfd_vma offset, asection **code_sec, bfd_vma *code_off) { bfd *opd_bfd = opd_sec->owner; Elf_Internal_Rela *relocs; Elf_Internal_Rela *lo, *hi, *look; bfd_vma val; /* No relocs implies we are linking a --just-symbols object. */ if (opd_sec->reloc_count == 0) { bfd_vma val; if (!bfd_get_section_contents (opd_bfd, opd_sec, &val, offset, 8)) return (bfd_vma) -1; if (code_sec != NULL) { asection *sec, *likely = NULL; for (sec = opd_bfd->sections; sec != NULL; sec = sec->next) if (sec->vma <= val && (sec->flags & SEC_LOAD) != 0 && (sec->flags & SEC_ALLOC) != 0) likely = sec; if (likely != NULL) { *code_sec = likely; if (code_off != NULL) *code_off = val - likely->vma; } } return val; } relocs = ppc64_elf_tdata (opd_bfd)->opd_relocs; if (relocs == NULL) relocs = _bfd_elf_link_read_relocs (opd_bfd, opd_sec, NULL, NULL, TRUE); /* Go find the opd reloc at the sym address. */ lo = relocs; BFD_ASSERT (lo != NULL); hi = lo + opd_sec->reloc_count - 1; /* ignore last reloc */ val = (bfd_vma) -1; while (lo < hi) { look = lo + (hi - lo) / 2; if (look->r_offset < offset) lo = look + 1; else if (look->r_offset > offset) hi = look; else { Elf_Internal_Shdr *symtab_hdr = &elf_tdata (opd_bfd)->symtab_hdr; if (ELF64_R_TYPE (look->r_info) == R_PPC64_ADDR64 && ELF64_R_TYPE ((look + 1)->r_info) == R_PPC64_TOC) { unsigned long symndx = ELF64_R_SYM (look->r_info); asection *sec; if (symndx < symtab_hdr->sh_info) { Elf_Internal_Sym *sym; sym = (Elf_Internal_Sym *) symtab_hdr->contents; if (sym == NULL) { sym = bfd_elf_get_elf_syms (opd_bfd, symtab_hdr, symtab_hdr->sh_info, 0, NULL, NULL, NULL); if (sym == NULL) break; symtab_hdr->contents = (bfd_byte *) sym; } sym += symndx; val = sym->st_value; sec = NULL; if ((sym->st_shndx != SHN_UNDEF && sym->st_shndx < SHN_LORESERVE) || sym->st_shndx > SHN_HIRESERVE) sec = bfd_section_from_elf_index (opd_bfd, sym->st_shndx); BFD_ASSERT ((sec->flags & SEC_MERGE) == 0); } else { struct elf_link_hash_entry **sym_hashes; struct elf_link_hash_entry *rh; sym_hashes = elf_sym_hashes (opd_bfd); rh = sym_hashes[symndx - symtab_hdr->sh_info]; while (rh->root.type == bfd_link_hash_indirect || rh->root.type == bfd_link_hash_warning) rh = ((struct elf_link_hash_entry *) rh->root.u.i.link); BFD_ASSERT (rh->root.type == bfd_link_hash_defined || rh->root.type == bfd_link_hash_defweak); val = rh->root.u.def.value; sec = rh->root.u.def.section; } val += look->r_addend; if (code_off != NULL) *code_off = val; if (code_sec != NULL) *code_sec = sec; if (sec != NULL && sec->output_section != NULL) val += sec->output_section->vma + sec->output_offset; } break; } } return val; } /* Mark sections containing dynamically referenced symbols. When building shared libraries, we must assume that any visible symbol is referenced. */ static bfd_boolean ppc64_elf_gc_mark_dynamic_ref (struct elf_link_hash_entry *h, void *inf) { struct bfd_link_info *info = (struct bfd_link_info *) inf; struct ppc_link_hash_entry *eh = (struct ppc_link_hash_entry *) h; if (eh->elf.root.type == bfd_link_hash_warning) eh = (struct ppc_link_hash_entry *) eh->elf.root.u.i.link; /* Dynamic linking info is on the func descriptor sym. */ if (eh->oh != NULL && eh->oh->is_func_descriptor && (eh->oh->elf.root.type == bfd_link_hash_defined || eh->oh->elf.root.type == bfd_link_hash_defweak)) eh = eh->oh; if ((eh->elf.root.type == bfd_link_hash_defined || eh->elf.root.type == bfd_link_hash_defweak) && (eh->elf.ref_dynamic || (!info->executable && eh->elf.def_regular && ELF_ST_VISIBILITY (eh->elf.other) != STV_INTERNAL && ELF_ST_VISIBILITY (eh->elf.other) != STV_HIDDEN))) { asection *code_sec; eh->elf.root.u.def.section->flags |= SEC_KEEP; /* Function descriptor syms cause the associated function code sym section to be marked. */ if (eh->is_func_descriptor && (eh->oh->elf.root.type == bfd_link_hash_defined || eh->oh->elf.root.type == bfd_link_hash_defweak)) eh->oh->elf.root.u.def.section->flags |= SEC_KEEP; else if (get_opd_info (eh->elf.root.u.def.section) != NULL && opd_entry_value (eh->elf.root.u.def.section, eh->elf.root.u.def.value, &code_sec, NULL) != (bfd_vma) -1) code_sec->flags |= SEC_KEEP; } return TRUE; } /* Return the section that should be marked against GC for a given relocation. */ static asection * ppc64_elf_gc_mark_hook (asection *sec, struct bfd_link_info *info, Elf_Internal_Rela *rel, struct elf_link_hash_entry *h, Elf_Internal_Sym *sym) { asection *rsec; /* First mark all our entry sym sections. */ if (info->gc_sym_list != NULL) { struct ppc_link_hash_table *htab = ppc_hash_table (info); struct bfd_sym_chain *sym = info->gc_sym_list; info->gc_sym_list = NULL; for (; sym != NULL; sym = sym->next) { struct ppc_link_hash_entry *eh; eh = (struct ppc_link_hash_entry *) elf_link_hash_lookup (&htab->elf, sym->name, FALSE, FALSE, FALSE); if (eh == NULL) continue; if (eh->elf.root.type != bfd_link_hash_defined && eh->elf.root.type != bfd_link_hash_defweak) continue; if (eh->is_func_descriptor && (eh->oh->elf.root.type == bfd_link_hash_defined || eh->oh->elf.root.type == bfd_link_hash_defweak)) rsec = eh->oh->elf.root.u.def.section; else if (get_opd_info (eh->elf.root.u.def.section) != NULL && opd_entry_value (eh->elf.root.u.def.section, eh->elf.root.u.def.value, &rsec, NULL) != (bfd_vma) -1) ; else continue; if (!rsec->gc_mark) _bfd_elf_gc_mark (info, rsec, ppc64_elf_gc_mark_hook); rsec = eh->elf.root.u.def.section; if (!rsec->gc_mark) _bfd_elf_gc_mark (info, rsec, ppc64_elf_gc_mark_hook); } } /* Syms return NULL if we're marking .opd, so we avoid marking all function sections, as all functions are referenced in .opd. */ rsec = NULL; if (get_opd_info (sec) != NULL) return rsec; if (h != NULL) { enum elf_ppc64_reloc_type r_type; struct ppc_link_hash_entry *eh; r_type = ELF64_R_TYPE (rel->r_info); switch (r_type) { case R_PPC64_GNU_VTINHERIT: case R_PPC64_GNU_VTENTRY: break; default: switch (h->root.type) { case bfd_link_hash_defined: case bfd_link_hash_defweak: eh = (struct ppc_link_hash_entry *) h; if (eh->oh != NULL && eh->oh->is_func_descriptor && (eh->oh->elf.root.type == bfd_link_hash_defined || eh->oh->elf.root.type == bfd_link_hash_defweak)) eh = eh->oh; /* Function descriptor syms cause the associated function code sym section to be marked. */ if (eh->is_func_descriptor && (eh->oh->elf.root.type == bfd_link_hash_defined || eh->oh->elf.root.type == bfd_link_hash_defweak)) { /* They also mark their opd section. */ if (!eh->elf.root.u.def.section->gc_mark) _bfd_elf_gc_mark (info, eh->elf.root.u.def.section, ppc64_elf_gc_mark_hook); rsec = eh->oh->elf.root.u.def.section; } else if (get_opd_info (eh->elf.root.u.def.section) != NULL && opd_entry_value (eh->elf.root.u.def.section, eh->elf.root.u.def.value, &rsec, NULL) != (bfd_vma) -1) { if (!eh->elf.root.u.def.section->gc_mark) _bfd_elf_gc_mark (info, eh->elf.root.u.def.section, ppc64_elf_gc_mark_hook); } else rsec = h->root.u.def.section; break; case bfd_link_hash_common: rsec = h->root.u.c.p->section; break; default: break; } } } else { asection **opd_sym_section; rsec = bfd_section_from_elf_index (sec->owner, sym->st_shndx); opd_sym_section = get_opd_info (rsec); if (opd_sym_section != NULL) { if (!rsec->gc_mark) _bfd_elf_gc_mark (info, rsec, ppc64_elf_gc_mark_hook); rsec = opd_sym_section[(sym->st_value + rel->r_addend) / 8]; } } return rsec; } /* Update the .got, .plt. and dynamic reloc reference counts for the section being removed. */ static bfd_boolean ppc64_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info, asection *sec, const Elf_Internal_Rela *relocs) { struct ppc_link_hash_table *htab; Elf_Internal_Shdr *symtab_hdr; struct elf_link_hash_entry **sym_hashes; struct got_entry **local_got_ents; const Elf_Internal_Rela *rel, *relend; if ((sec->flags & SEC_ALLOC) == 0) return TRUE; elf_section_data (sec)->local_dynrel = NULL; htab = ppc_hash_table (info); symtab_hdr = &elf_tdata (abfd)->symtab_hdr; sym_hashes = elf_sym_hashes (abfd); local_got_ents = elf_local_got_ents (abfd); relend = relocs + sec->reloc_count; for (rel = relocs; rel < relend; rel++) { unsigned long r_symndx; enum elf_ppc64_reloc_type r_type; struct elf_link_hash_entry *h = NULL; char tls_type = 0; r_symndx = ELF64_R_SYM (rel->r_info); r_type = ELF64_R_TYPE (rel->r_info); if (r_symndx >= symtab_hdr->sh_info) { struct ppc_link_hash_entry *eh; struct ppc_dyn_relocs **pp; struct ppc_dyn_relocs *p; 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; eh = (struct ppc_link_hash_entry *) h; for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) if (p->sec == sec) { /* Everything must go for SEC. */ *pp = p->next; break; } } switch (r_type) { case R_PPC64_GOT_TLSLD16: case R_PPC64_GOT_TLSLD16_LO: case R_PPC64_GOT_TLSLD16_HI: case R_PPC64_GOT_TLSLD16_HA: - ppc64_tlsld_got (abfd)->refcount -= 1; tls_type = TLS_TLS | TLS_LD; goto dogot; case R_PPC64_GOT_TLSGD16: case R_PPC64_GOT_TLSGD16_LO: case R_PPC64_GOT_TLSGD16_HI: case R_PPC64_GOT_TLSGD16_HA: tls_type = TLS_TLS | TLS_GD; goto dogot; case R_PPC64_GOT_TPREL16_DS: case R_PPC64_GOT_TPREL16_LO_DS: case R_PPC64_GOT_TPREL16_HI: case R_PPC64_GOT_TPREL16_HA: tls_type = TLS_TLS | TLS_TPREL; goto dogot; case R_PPC64_GOT_DTPREL16_DS: case R_PPC64_GOT_DTPREL16_LO_DS: case R_PPC64_GOT_DTPREL16_HI: case R_PPC64_GOT_DTPREL16_HA: tls_type = TLS_TLS | TLS_DTPREL; goto dogot; case R_PPC64_GOT16: case R_PPC64_GOT16_DS: case R_PPC64_GOT16_HA: case R_PPC64_GOT16_HI: case R_PPC64_GOT16_LO: case R_PPC64_GOT16_LO_DS: dogot: { struct got_entry *ent; if (h != NULL) ent = h->got.glist; else ent = local_got_ents[r_symndx]; for (; ent != NULL; ent = ent->next) if (ent->addend == rel->r_addend && ent->owner == abfd && ent->tls_type == tls_type) break; if (ent == NULL) abort (); if (ent->got.refcount > 0) ent->got.refcount -= 1; } break; case R_PPC64_PLT16_HA: case R_PPC64_PLT16_HI: case R_PPC64_PLT16_LO: case R_PPC64_PLT32: case R_PPC64_PLT64: case R_PPC64_REL14: case R_PPC64_REL14_BRNTAKEN: case R_PPC64_REL14_BRTAKEN: case R_PPC64_REL24: if (h != NULL) { struct plt_entry *ent; for (ent = h->plt.plist; ent != NULL; ent = ent->next) if (ent->addend == rel->r_addend) break; if (ent != NULL && ent->plt.refcount > 0) ent->plt.refcount -= 1; } break; default: break; } } return TRUE; } /* The maximum size of .sfpr. */ #define SFPR_MAX (218*4) struct sfpr_def_parms { const char name[12]; unsigned char lo, hi; bfd_byte * (*write_ent) (bfd *, bfd_byte *, int); bfd_byte * (*write_tail) (bfd *, bfd_byte *, int); }; /* Auto-generate _save*, _rest* functions in .sfpr. */ static unsigned int sfpr_define (struct bfd_link_info *info, const struct sfpr_def_parms *parm) { struct ppc_link_hash_table *htab = ppc_hash_table (info); unsigned int i; size_t len = strlen (parm->name); bfd_boolean writing = FALSE; char sym[16]; memcpy (sym, parm->name, len); sym[len + 2] = 0; for (i = parm->lo; i <= parm->hi; i++) { struct elf_link_hash_entry *h; sym[len + 0] = i / 10 + '0'; sym[len + 1] = i % 10 + '0'; h = elf_link_hash_lookup (&htab->elf, sym, FALSE, FALSE, TRUE); if (h != NULL && !h->def_regular) { h->root.type = bfd_link_hash_defined; h->root.u.def.section = htab->sfpr; h->root.u.def.value = htab->sfpr->size; h->type = STT_FUNC; h->def_regular = 1; _bfd_elf_link_hash_hide_symbol (info, h, TRUE); writing = TRUE; if (htab->sfpr->contents == NULL) { htab->sfpr->contents = bfd_alloc (htab->elf.dynobj, SFPR_MAX); if (htab->sfpr->contents == NULL) return FALSE; } } if (writing) { bfd_byte *p = htab->sfpr->contents + htab->sfpr->size; if (i != parm->hi) p = (*parm->write_ent) (htab->elf.dynobj, p, i); else p = (*parm->write_tail) (htab->elf.dynobj, p, i); htab->sfpr->size = p - htab->sfpr->contents; } } return TRUE; } static bfd_byte * savegpr0 (bfd *abfd, bfd_byte *p, int r) { bfd_put_32 (abfd, STD_R0_0R1 + (r << 21) + (1 << 16) - (32 - r) * 8, p); return p + 4; } static bfd_byte * savegpr0_tail (bfd *abfd, bfd_byte *p, int r) { p = savegpr0 (abfd, p, r); bfd_put_32 (abfd, STD_R0_0R1 + 16, p); p = p + 4; bfd_put_32 (abfd, BLR, p); return p + 4; } static bfd_byte * restgpr0 (bfd *abfd, bfd_byte *p, int r) { bfd_put_32 (abfd, LD_R0_0R1 + (r << 21) + (1 << 16) - (32 - r) * 8, p); return p + 4; } static bfd_byte * restgpr0_tail (bfd *abfd, bfd_byte *p, int r) { bfd_put_32 (abfd, LD_R0_0R1 + 16, p); p = p + 4; p = restgpr0 (abfd, p, r); bfd_put_32 (abfd, MTLR_R0, p); p = p + 4; if (r == 29) { p = restgpr0 (abfd, p, 30); p = restgpr0 (abfd, p, 31); } bfd_put_32 (abfd, BLR, p); return p + 4; } static bfd_byte * savegpr1 (bfd *abfd, bfd_byte *p, int r) { bfd_put_32 (abfd, STD_R0_0R12 + (r << 21) + (1 << 16) - (32 - r) * 8, p); return p + 4; } static bfd_byte * savegpr1_tail (bfd *abfd, bfd_byte *p, int r) { p = savegpr1 (abfd, p, r); bfd_put_32 (abfd, BLR, p); return p + 4; } static bfd_byte * restgpr1 (bfd *abfd, bfd_byte *p, int r) { bfd_put_32 (abfd, LD_R0_0R12 + (r << 21) + (1 << 16) - (32 - r) * 8, p); return p + 4; } static bfd_byte * restgpr1_tail (bfd *abfd, bfd_byte *p, int r) { p = restgpr1 (abfd, p, r); bfd_put_32 (abfd, BLR, p); return p + 4; } static bfd_byte * savefpr (bfd *abfd, bfd_byte *p, int r) { bfd_put_32 (abfd, STFD_FR0_0R1 + (r << 21) + (1 << 16) - (32 - r) * 8, p); return p + 4; } static bfd_byte * savefpr0_tail (bfd *abfd, bfd_byte *p, int r) { p = savefpr (abfd, p, r); bfd_put_32 (abfd, STD_R0_0R1 + 16, p); p = p + 4; bfd_put_32 (abfd, BLR, p); return p + 4; } static bfd_byte * restfpr (bfd *abfd, bfd_byte *p, int r) { bfd_put_32 (abfd, LFD_FR0_0R1 + (r << 21) + (1 << 16) - (32 - r) * 8, p); return p + 4; } static bfd_byte * restfpr0_tail (bfd *abfd, bfd_byte *p, int r) { bfd_put_32 (abfd, LD_R0_0R1 + 16, p); p = p + 4; p = restfpr (abfd, p, r); bfd_put_32 (abfd, MTLR_R0, p); p = p + 4; if (r == 29) { p = restfpr (abfd, p, 30); p = restfpr (abfd, p, 31); } bfd_put_32 (abfd, BLR, p); return p + 4; } static bfd_byte * savefpr1_tail (bfd *abfd, bfd_byte *p, int r) { p = savefpr (abfd, p, r); bfd_put_32 (abfd, BLR, p); return p + 4; } static bfd_byte * restfpr1_tail (bfd *abfd, bfd_byte *p, int r) { p = restfpr (abfd, p, r); bfd_put_32 (abfd, BLR, p); return p + 4; } static bfd_byte * savevr (bfd *abfd, bfd_byte *p, int r) { bfd_put_32 (abfd, LI_R12_0 + (1 << 16) - (32 - r) * 16, p); p = p + 4; bfd_put_32 (abfd, STVX_VR0_R12_R0 + (r << 21), p); return p + 4; } static bfd_byte * savevr_tail (bfd *abfd, bfd_byte *p, int r) { p = savevr (abfd, p, r); bfd_put_32 (abfd, BLR, p); return p + 4; } static bfd_byte * restvr (bfd *abfd, bfd_byte *p, int r) { bfd_put_32 (abfd, LI_R12_0 + (1 << 16) - (32 - r) * 16, p); p = p + 4; bfd_put_32 (abfd, LVX_VR0_R12_R0 + (r << 21), p); return p + 4; } static bfd_byte * restvr_tail (bfd *abfd, bfd_byte *p, int r) { p = restvr (abfd, p, r); bfd_put_32 (abfd, BLR, p); return p + 4; } /* Called via elf_link_hash_traverse to transfer dynamic linking information on function code symbol entries to their corresponding function descriptor symbol entries. */ static bfd_boolean func_desc_adjust (struct elf_link_hash_entry *h, void *inf) { struct bfd_link_info *info; struct ppc_link_hash_table *htab; struct plt_entry *ent; struct ppc_link_hash_entry *fh; struct ppc_link_hash_entry *fdh; bfd_boolean force_local; fh = (struct ppc_link_hash_entry *) h; if (fh->elf.root.type == bfd_link_hash_indirect) return TRUE; if (fh->elf.root.type == bfd_link_hash_warning) fh = (struct ppc_link_hash_entry *) fh->elf.root.u.i.link; info = inf; htab = ppc_hash_table (info); /* Resolve undefined references to dot-symbols as the value in the function descriptor, if we have one in a regular object. This is to satisfy cases like ".quad .foo". Calls to functions in dynamic objects are handled elsewhere. */ if (fh->elf.root.type == bfd_link_hash_undefweak && fh->was_undefined && (fh->oh->elf.root.type == bfd_link_hash_defined || fh->oh->elf.root.type == bfd_link_hash_defweak) && get_opd_info (fh->oh->elf.root.u.def.section) != NULL && opd_entry_value (fh->oh->elf.root.u.def.section, fh->oh->elf.root.u.def.value, &fh->elf.root.u.def.section, &fh->elf.root.u.def.value) != (bfd_vma) -1) { fh->elf.root.type = fh->oh->elf.root.type; fh->elf.forced_local = 1; + fh->elf.def_regular = fh->oh->elf.def_regular; + fh->elf.def_dynamic = fh->oh->elf.def_dynamic; } /* If this is a function code symbol, transfer dynamic linking information to the function descriptor symbol. */ if (!fh->is_func) return TRUE; for (ent = fh->elf.plt.plist; ent != NULL; ent = ent->next) if (ent->plt.refcount > 0) break; if (ent == NULL || fh->elf.root.root.string[0] != '.' || fh->elf.root.root.string[1] == '\0') return TRUE; /* Find the corresponding function descriptor symbol. Create it as undefined if necessary. */ fdh = get_fdh (fh, htab); if (fdh != NULL) while (fdh->elf.root.type == bfd_link_hash_indirect || fdh->elf.root.type == bfd_link_hash_warning) fdh = (struct ppc_link_hash_entry *) fdh->elf.root.u.i.link; if (fdh == NULL && info->shared && (fh->elf.root.type == bfd_link_hash_undefined || fh->elf.root.type == bfd_link_hash_undefweak)) { fdh = make_fdh (info, fh); if (fdh == NULL) return FALSE; } /* Fake function descriptors are made undefweak. If the function code symbol is strong undefined, make the fake sym the same. If the function code symbol is defined, then force the fake descriptor local; We can't support overriding of symbols in a shared library on a fake descriptor. */ if (fdh != NULL && fdh->fake && fdh->elf.root.type == bfd_link_hash_undefweak) { if (fh->elf.root.type == bfd_link_hash_undefined) { fdh->elf.root.type = bfd_link_hash_undefined; bfd_link_add_undef (&htab->elf.root, &fdh->elf.root); } else if (fh->elf.root.type == bfd_link_hash_defined || fh->elf.root.type == bfd_link_hash_defweak) { _bfd_elf_link_hash_hide_symbol (info, &fdh->elf, TRUE); } } if (fdh != NULL && !fdh->elf.forced_local && (info->shared || fdh->elf.def_dynamic || fdh->elf.ref_dynamic || (fdh->elf.root.type == bfd_link_hash_undefweak && ELF_ST_VISIBILITY (fdh->elf.other) == STV_DEFAULT))) { if (fdh->elf.dynindx == -1) if (! bfd_elf_link_record_dynamic_symbol (info, &fdh->elf)) return FALSE; fdh->elf.ref_regular |= fh->elf.ref_regular; fdh->elf.ref_dynamic |= fh->elf.ref_dynamic; fdh->elf.ref_regular_nonweak |= fh->elf.ref_regular_nonweak; fdh->elf.non_got_ref |= fh->elf.non_got_ref; if (ELF_ST_VISIBILITY (fh->elf.other) == STV_DEFAULT) { move_plt_plist (fh, fdh); fdh->elf.needs_plt = 1; } fdh->is_func_descriptor = 1; fdh->oh = fh; fh->oh = fdh; } /* Now that the info is on the function descriptor, clear the function code sym info. Any function code syms for which we don't have a definition in a regular file, we force local. This prevents a shared library from exporting syms that have been imported from another library. Function code syms that are really in the library we must leave global to prevent the linker dragging in a definition from a static library. */ force_local = (!fh->elf.def_regular || fdh == NULL || !fdh->elf.def_regular || fdh->elf.forced_local); _bfd_elf_link_hash_hide_symbol (info, &fh->elf, force_local); return TRUE; } /* Called near the start of bfd_elf_size_dynamic_sections. We use this hook to a) provide some gcc support functions, and b) transfer dynamic linking information gathered so far on function code symbol entries, to their corresponding function descriptor symbol entries. */ static bfd_boolean ppc64_elf_func_desc_adjust (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) { struct ppc_link_hash_table *htab; unsigned int i; const struct sfpr_def_parms funcs[] = { { "_savegpr0_", 14, 31, savegpr0, savegpr0_tail }, { "_restgpr0_", 14, 29, restgpr0, restgpr0_tail }, { "_restgpr0_", 30, 31, restgpr0, restgpr0_tail }, { "_savegpr1_", 14, 31, savegpr1, savegpr1_tail }, { "_restgpr1_", 14, 31, restgpr1, restgpr1_tail }, { "_savefpr_", 14, 31, savefpr, savefpr0_tail }, { "_restfpr_", 14, 29, restfpr, restfpr0_tail }, { "_restfpr_", 30, 31, restfpr, restfpr0_tail }, { "._savef", 14, 31, savefpr, savefpr1_tail }, { "._restf", 14, 31, restfpr, restfpr1_tail }, { "_savevr_", 20, 31, savevr, savevr_tail }, { "_restvr_", 20, 31, restvr, restvr_tail } }; htab = ppc_hash_table (info); if (htab->sfpr == NULL) /* We don't have any relocs. */ return TRUE; /* Provide any missing _save* and _rest* functions. */ htab->sfpr->size = 0; for (i = 0; i < sizeof (funcs) / sizeof (funcs[0]); i++) if (!sfpr_define (info, &funcs[i])) return FALSE; elf_link_hash_traverse (&htab->elf, func_desc_adjust, info); if (htab->sfpr->size == 0) htab->sfpr->flags |= SEC_EXCLUDE; return TRUE; } /* Adjust a symbol defined by a dynamic object and referenced by a regular object. The current definition is in some section of the dynamic object, but we're not including those sections. We have to change the definition to something the rest of the link can understand. */ static bfd_boolean ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info, struct elf_link_hash_entry *h) { struct ppc_link_hash_table *htab; asection *s; htab = ppc_hash_table (info); /* Deal with function syms. */ if (h->type == STT_FUNC || h->needs_plt) { /* Clear procedure linkage table information for any symbol that won't need a .plt entry. */ struct plt_entry *ent; for (ent = h->plt.plist; ent != NULL; ent = ent->next) if (ent->plt.refcount > 0) break; if (ent == NULL || SYMBOL_CALLS_LOCAL (info, h) || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT && h->root.type == bfd_link_hash_undefweak)) { h->plt.plist = NULL; h->needs_plt = 0; } } else h->plt.plist = NULL; /* 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; if (ELIMINATE_COPY_RELOCS) h->non_got_ref = h->u.weakdef->non_got_ref; return TRUE; } /* If we are creating a shared library, we must presume that the only references to the symbol are via the global offset table. For such cases we need not do anything here; the relocations will be handled correctly by relocate_section. */ if (info->shared) return TRUE; /* If there are no references to this symbol that do not use the GOT, we don't need to generate a copy reloc. */ if (!h->non_got_ref) return TRUE; /* Don't generate a copy reloc for symbols defined in the executable. */ if (!h->def_dynamic || !h->ref_regular || h->def_regular) return TRUE; if (ELIMINATE_COPY_RELOCS) { struct ppc_link_hash_entry * eh; struct ppc_dyn_relocs *p; eh = (struct ppc_link_hash_entry *) h; for (p = eh->dyn_relocs; p != NULL; p = p->next) { s = p->sec->output_section; if (s != NULL && (s->flags & SEC_READONLY) != 0) break; } /* If we didn't find any dynamic relocs in read-only sections, then we'll be keeping the dynamic relocs and avoiding the copy reloc. */ if (p == NULL) { h->non_got_ref = 0; return TRUE; } } if (h->plt.plist != NULL) { /* We should never get here, but unfortunately there are versions of gcc out there that improperly (for this ABI) put initialized function pointers, vtable refs and suchlike in read-only sections. Allow them to proceed, but warn that this might break at runtime. */ (*_bfd_error_handler) (_("copy reloc against `%s' requires lazy plt linking; " "avoid setting LD_BIND_NOW=1 or upgrade gcc"), h->root.root.string); } /* This is a reference to a symbol defined by a dynamic object which is not a function. */ if (h->size == 0) { (*_bfd_error_handler) (_("dynamic variable `%s' is zero size"), h->root.root.string); 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. */ /* We must generate a R_PPC64_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 .rela.bss section we are going to use. */ if ((h->root.u.def.section->flags & SEC_ALLOC) != 0) { htab->relbss->size += sizeof (Elf64_External_Rela); h->needs_copy = 1; } s = htab->dynbss; return _bfd_elf_adjust_dynamic_copy (h, s); } /* If given a function descriptor symbol, hide both the function code sym and the descriptor. */ static void ppc64_elf_hide_symbol (struct bfd_link_info *info, struct elf_link_hash_entry *h, bfd_boolean force_local) { struct ppc_link_hash_entry *eh; _bfd_elf_link_hash_hide_symbol (info, h, force_local); eh = (struct ppc_link_hash_entry *) h; if (eh->is_func_descriptor) { struct ppc_link_hash_entry *fh = eh->oh; if (fh == NULL) { const char *p, *q; struct ppc_link_hash_table *htab; char save; /* We aren't supposed to use alloca in BFD because on systems which do not have alloca the version in libiberty calls xmalloc, which might cause the program to crash when it runs out of memory. This function doesn't have a return status, so there's no way to gracefully return an error. So cheat. We know that string[-1] can be safely accessed; It's either a string in an ELF string table, or allocated in an objalloc structure. */ p = eh->elf.root.root.string - 1; save = *p; *(char *) p = '.'; htab = ppc_hash_table (info); fh = (struct ppc_link_hash_entry *) elf_link_hash_lookup (&htab->elf, p, FALSE, FALSE, FALSE); *(char *) p = save; /* Unfortunately, if it so happens that the string we were looking for was allocated immediately before this string, then we overwrote the string terminator. That's the only reason the lookup should fail. */ if (fh == NULL) { q = eh->elf.root.root.string + strlen (eh->elf.root.root.string); while (q >= eh->elf.root.root.string && *q == *p) --q, --p; if (q < eh->elf.root.root.string && *p == '.') fh = (struct ppc_link_hash_entry *) elf_link_hash_lookup (&htab->elf, p, FALSE, FALSE, FALSE); } if (fh != NULL) { eh->oh = fh; fh->oh = eh; } } if (fh != NULL) _bfd_elf_link_hash_hide_symbol (info, &fh->elf, force_local); } } static bfd_boolean get_sym_h (struct elf_link_hash_entry **hp, Elf_Internal_Sym **symp, asection **symsecp, char **tls_maskp, Elf_Internal_Sym **locsymsp, unsigned long r_symndx, bfd *ibfd) { Elf_Internal_Shdr *symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; if (r_symndx >= symtab_hdr->sh_info) { struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (ibfd); struct elf_link_hash_entry *h; 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 (hp != NULL) *hp = h; if (symp != NULL) *symp = NULL; if (symsecp != NULL) { asection *symsec = NULL; if (h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) symsec = h->root.u.def.section; *symsecp = symsec; } if (tls_maskp != NULL) { struct ppc_link_hash_entry *eh; eh = (struct ppc_link_hash_entry *) h; *tls_maskp = &eh->tls_mask; } } else { Elf_Internal_Sym *sym; Elf_Internal_Sym *locsyms = *locsymsp; if (locsyms == NULL) { locsyms = (Elf_Internal_Sym *) symtab_hdr->contents; if (locsyms == NULL) locsyms = bfd_elf_get_elf_syms (ibfd, symtab_hdr, symtab_hdr->sh_info, 0, NULL, NULL, NULL); if (locsyms == NULL) return FALSE; *locsymsp = locsyms; } sym = locsyms + r_symndx; if (hp != NULL) *hp = NULL; if (symp != NULL) *symp = sym; if (symsecp != NULL) { asection *symsec = NULL; if ((sym->st_shndx != SHN_UNDEF && sym->st_shndx < SHN_LORESERVE) || sym->st_shndx > SHN_HIRESERVE) symsec = bfd_section_from_elf_index (ibfd, sym->st_shndx); *symsecp = symsec; } if (tls_maskp != NULL) { struct got_entry **lgot_ents; char *tls_mask; tls_mask = NULL; lgot_ents = elf_local_got_ents (ibfd); if (lgot_ents != NULL) { char *lgot_masks = (char *) (lgot_ents + symtab_hdr->sh_info); tls_mask = &lgot_masks[r_symndx]; } *tls_maskp = tls_mask; } } return TRUE; } /* Returns TLS_MASKP for the given REL symbol. Function return is 0 on error, 2 on a toc GD type suitable for optimization, 3 on a toc LD type suitable for optimization, and 1 otherwise. */ static int -get_tls_mask (char **tls_maskp, unsigned long *toc_symndx, +get_tls_mask (char **tls_maskp, + unsigned long *toc_symndx, + bfd_vma *toc_addend, Elf_Internal_Sym **locsymsp, - const Elf_Internal_Rela *rel, bfd *ibfd) + const Elf_Internal_Rela *rel, + bfd *ibfd) { unsigned long r_symndx; int next_r; struct elf_link_hash_entry *h; Elf_Internal_Sym *sym; asection *sec; bfd_vma off; r_symndx = ELF64_R_SYM (rel->r_info); if (!get_sym_h (&h, &sym, &sec, tls_maskp, locsymsp, r_symndx, ibfd)) return 0; if ((*tls_maskp != NULL && **tls_maskp != 0) || sec == NULL || ppc64_elf_section_data (sec)->sec_type != sec_toc) return 1; /* Look inside a TOC section too. */ if (h != NULL) { BFD_ASSERT (h->root.type == bfd_link_hash_defined); off = h->root.u.def.value; } else off = sym->st_value; off += rel->r_addend; BFD_ASSERT (off % 8 == 0); - r_symndx = ppc64_elf_section_data (sec)->u.t_symndx[off / 8]; - next_r = ppc64_elf_section_data (sec)->u.t_symndx[off / 8 + 1]; - if (!get_sym_h (&h, &sym, &sec, tls_maskp, locsymsp, r_symndx, ibfd)) - return 0; + r_symndx = ppc64_elf_section_data (sec)->u.toc.symndx[off / 8]; + next_r = ppc64_elf_section_data (sec)->u.toc.symndx[off / 8 + 1]; if (toc_symndx != NULL) *toc_symndx = r_symndx; + if (toc_addend != NULL) + *toc_addend = ppc64_elf_section_data (sec)->u.toc.add[off / 8]; + if (!get_sym_h (&h, &sym, &sec, tls_maskp, locsymsp, r_symndx, ibfd)) + return 0; if ((h == NULL || ((h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) && !h->def_dynamic)) && (next_r == -1 || next_r == -2)) return 1 - next_r; return 1; } /* Adjust all global syms defined in opd sections. In gcc generated code for the old ABI, these will already have been done. */ static bfd_boolean adjust_opd_syms (struct elf_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED) { struct ppc_link_hash_entry *eh; asection *sym_sec; long *opd_adjust; if (h->root.type == bfd_link_hash_indirect) return TRUE; if (h->root.type == bfd_link_hash_warning) h = (struct elf_link_hash_entry *) h->root.u.i.link; if (h->root.type != bfd_link_hash_defined && h->root.type != bfd_link_hash_defweak) return TRUE; eh = (struct ppc_link_hash_entry *) h; if (eh->adjust_done) return TRUE; sym_sec = eh->elf.root.u.def.section; opd_adjust = get_opd_info (sym_sec); if (opd_adjust != NULL) { long adjust = opd_adjust[eh->elf.root.u.def.value / 8]; if (adjust == -1) { /* This entry has been deleted. */ asection *dsec = ppc64_elf_tdata (sym_sec->owner)->deleted_section; if (dsec == NULL) { for (dsec = sym_sec->owner->sections; dsec; dsec = dsec->next) if (elf_discarded_section (dsec)) { ppc64_elf_tdata (sym_sec->owner)->deleted_section = dsec; break; } } eh->elf.root.u.def.value = 0; eh->elf.root.u.def.section = dsec; } else eh->elf.root.u.def.value += adjust; eh->adjust_done = 1; } return TRUE; } /* Handles decrementing dynamic reloc counts for the reloc specified by R_INFO in section SEC. If LOCAL_SYMS is NULL, then H and SYM_SEC have already been determined. */ static bfd_boolean dec_dynrel_count (bfd_vma r_info, asection *sec, struct bfd_link_info *info, Elf_Internal_Sym **local_syms, struct elf_link_hash_entry *h, asection *sym_sec) { enum elf_ppc64_reloc_type r_type; struct ppc_dyn_relocs *p; struct ppc_dyn_relocs **pp; /* Can this reloc be dynamic? This switch, and later tests here should be kept in sync with the code in check_relocs. */ r_type = ELF64_R_TYPE (r_info); switch (r_type) { default: return TRUE; case R_PPC64_TPREL16: case R_PPC64_TPREL16_LO: case R_PPC64_TPREL16_HI: case R_PPC64_TPREL16_HA: case R_PPC64_TPREL16_DS: case R_PPC64_TPREL16_LO_DS: case R_PPC64_TPREL16_HIGHER: case R_PPC64_TPREL16_HIGHERA: case R_PPC64_TPREL16_HIGHEST: case R_PPC64_TPREL16_HIGHESTA: if (!info->shared) return TRUE; case R_PPC64_TPREL64: case R_PPC64_DTPMOD64: case R_PPC64_DTPREL64: case R_PPC64_ADDR64: case R_PPC64_REL30: case R_PPC64_REL32: case R_PPC64_REL64: case R_PPC64_ADDR14: case R_PPC64_ADDR14_BRNTAKEN: case R_PPC64_ADDR14_BRTAKEN: case R_PPC64_ADDR16: case R_PPC64_ADDR16_DS: case R_PPC64_ADDR16_HA: case R_PPC64_ADDR16_HI: case R_PPC64_ADDR16_HIGHER: case R_PPC64_ADDR16_HIGHERA: case R_PPC64_ADDR16_HIGHEST: case R_PPC64_ADDR16_HIGHESTA: case R_PPC64_ADDR16_LO: case R_PPC64_ADDR16_LO_DS: case R_PPC64_ADDR24: case R_PPC64_ADDR32: case R_PPC64_UADDR16: case R_PPC64_UADDR32: case R_PPC64_UADDR64: case R_PPC64_TOC: break; } if (local_syms != NULL) { unsigned long r_symndx; Elf_Internal_Sym *sym; bfd *ibfd = sec->owner; r_symndx = ELF64_R_SYM (r_info); if (!get_sym_h (&h, &sym, &sym_sec, NULL, local_syms, r_symndx, ibfd)) return FALSE; } if ((info->shared - && (MUST_BE_DYN_RELOC (r_type) + && (must_be_dyn_reloc (info, r_type) || (h != NULL && (!info->symbolic || h->root.type == bfd_link_hash_defweak || !h->def_regular)))) || (ELIMINATE_COPY_RELOCS && !info->shared && h != NULL && (h->root.type == bfd_link_hash_defweak || !h->def_regular))) ; else return TRUE; if (h != NULL) pp = &((struct ppc_link_hash_entry *) h)->dyn_relocs; else { if (sym_sec != NULL) { void *vpp = &elf_section_data (sym_sec)->local_dynrel; pp = (struct ppc_dyn_relocs **) vpp; } else { void *vpp = &elf_section_data (sec)->local_dynrel; pp = (struct ppc_dyn_relocs **) vpp; } /* elf_gc_sweep may have already removed all dyn relocs associated with local syms for a given section. Don't report a dynreloc miscount. */ if (*pp == NULL) return TRUE; } while ((p = *pp) != NULL) { if (p->sec == sec) { - if (!MUST_BE_DYN_RELOC (r_type)) + if (!must_be_dyn_reloc (info, r_type)) p->pc_count -= 1; p->count -= 1; if (p->count == 0) *pp = p->next; return TRUE; } pp = &p->next; } (*_bfd_error_handler) (_("dynreloc miscount for %B, section %A"), sec->owner, sec); bfd_set_error (bfd_error_bad_value); return FALSE; } /* Remove unused Official Procedure Descriptor entries. Currently we only remove those associated with functions in discarded link-once sections, or weakly defined functions that have been overridden. It would be possible to remove many more entries for statically linked applications. */ bfd_boolean ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info, bfd_boolean no_opd_opt, bfd_boolean non_overlapping) { bfd *ibfd; bfd_boolean some_edited = FALSE; asection *need_pad = NULL; for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) { asection *sec; Elf_Internal_Rela *relstart, *rel, *relend; Elf_Internal_Shdr *symtab_hdr; Elf_Internal_Sym *local_syms; struct elf_link_hash_entry **sym_hashes; bfd_vma offset; bfd_size_type amt; long *opd_adjust; bfd_boolean need_edit, add_aux_fields; bfd_size_type cnt_16b = 0; sec = bfd_get_section_by_name (ibfd, ".opd"); if (sec == NULL || sec->size == 0) continue; amt = sec->size * sizeof (long) / 8; opd_adjust = get_opd_info (sec); if (opd_adjust == NULL) { /* check_relocs hasn't been called. Must be a ld -r link or --just-symbols object. */ opd_adjust = bfd_alloc (obfd, amt); if (opd_adjust == NULL) return FALSE; ppc64_elf_section_data (sec)->u.opd_adjust = opd_adjust; BFD_ASSERT (ppc64_elf_section_data (sec)->sec_type == sec_normal); ppc64_elf_section_data (sec)->sec_type = sec_opd; } memset (opd_adjust, 0, amt); if (no_opd_opt) continue; if (sec->sec_info_type == ELF_INFO_TYPE_JUST_SYMS) continue; if (sec->output_section == bfd_abs_section_ptr) continue; /* Look through the section relocs. */ if ((sec->flags & SEC_RELOC) == 0 || sec->reloc_count == 0) continue; local_syms = NULL; symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; sym_hashes = elf_sym_hashes (ibfd); /* Read the relocations. */ relstart = _bfd_elf_link_read_relocs (ibfd, sec, NULL, NULL, info->keep_memory); if (relstart == NULL) return FALSE; /* First run through the relocs to check they are sane, and to determine whether we need to edit this opd section. */ need_edit = FALSE; need_pad = sec; offset = 0; relend = relstart + sec->reloc_count; for (rel = relstart; rel < relend; ) { enum elf_ppc64_reloc_type r_type; unsigned long r_symndx; asection *sym_sec; struct elf_link_hash_entry *h; Elf_Internal_Sym *sym; /* .opd contains a regular array of 16 or 24 byte entries. We're only interested in the reloc pointing to a function entry point. */ if (rel->r_offset != offset || rel + 1 >= relend || (rel + 1)->r_offset != offset + 8) { /* If someone messes with .opd alignment then after a "ld -r" we might have padding in the middle of .opd. Also, there's nothing to prevent someone putting something silly in .opd with the assembler. No .opd optimization for them! */ broken_opd: (*_bfd_error_handler) (_("%B: .opd is not a regular array of opd entries"), ibfd); need_edit = FALSE; break; } if ((r_type = ELF64_R_TYPE (rel->r_info)) != R_PPC64_ADDR64 || (r_type = ELF64_R_TYPE ((rel + 1)->r_info)) != R_PPC64_TOC) { (*_bfd_error_handler) (_("%B: unexpected reloc type %u in .opd section"), ibfd, r_type); need_edit = FALSE; break; } r_symndx = ELF64_R_SYM (rel->r_info); if (!get_sym_h (&h, &sym, &sym_sec, NULL, &local_syms, r_symndx, ibfd)) goto error_ret; if (sym_sec == NULL || sym_sec->owner == NULL) { const char *sym_name; if (h != NULL) sym_name = h->root.root.string; else sym_name = bfd_elf_sym_name (ibfd, symtab_hdr, sym, sym_sec); (*_bfd_error_handler) (_("%B: undefined sym `%s' in .opd section"), ibfd, sym_name); need_edit = FALSE; break; } /* opd entries are always for functions defined in the current input bfd. If the symbol isn't defined in the input bfd, then we won't be using the function in this bfd; It must be defined in a linkonce section in another bfd, or is weak. It's also possible that we are discarding the function due to a linker script /DISCARD/, which we test for via the output_section. */ if (sym_sec->owner != ibfd || sym_sec->output_section == bfd_abs_section_ptr) need_edit = TRUE; rel += 2; if (rel == relend || (rel + 1 == relend && rel->r_offset == offset + 16)) { if (sec->size == offset + 24) { need_pad = NULL; break; } if (rel == relend && sec->size == offset + 16) { cnt_16b++; break; } goto broken_opd; } if (rel->r_offset == offset + 24) offset += 24; else if (rel->r_offset != offset + 16) goto broken_opd; else if (rel + 1 < relend && ELF64_R_TYPE (rel[0].r_info) == R_PPC64_ADDR64 && ELF64_R_TYPE (rel[1].r_info) == R_PPC64_TOC) { offset += 16; cnt_16b++; } else if (rel + 2 < relend && ELF64_R_TYPE (rel[1].r_info) == R_PPC64_ADDR64 && ELF64_R_TYPE (rel[2].r_info) == R_PPC64_TOC) { offset += 24; rel += 1; } else goto broken_opd; } add_aux_fields = non_overlapping && cnt_16b > 0; if (need_edit || add_aux_fields) { Elf_Internal_Rela *write_rel; bfd_byte *rptr, *wptr; bfd_byte *new_contents = NULL; bfd_boolean skip; long opd_ent_size; /* This seems a waste of time as input .opd sections are all zeros as generated by gcc, but I suppose there's no reason this will always be so. We might start putting something in the third word of .opd entries. */ if ((sec->flags & SEC_IN_MEMORY) == 0) { bfd_byte *loc; if (!bfd_malloc_and_get_section (ibfd, sec, &loc)) { if (loc != NULL) free (loc); error_ret: if (local_syms != NULL && symtab_hdr->contents != (unsigned char *) local_syms) free (local_syms); if (elf_section_data (sec)->relocs != relstart) free (relstart); return FALSE; } sec->contents = loc; sec->flags |= (SEC_IN_MEMORY | SEC_HAS_CONTENTS); } elf_section_data (sec)->relocs = relstart; new_contents = sec->contents; if (add_aux_fields) { new_contents = bfd_malloc (sec->size + cnt_16b * 8); if (new_contents == NULL) return FALSE; need_pad = FALSE; } wptr = new_contents; rptr = sec->contents; write_rel = relstart; skip = FALSE; offset = 0; opd_ent_size = 0; for (rel = relstart; rel < relend; rel++) { unsigned long r_symndx; asection *sym_sec; struct elf_link_hash_entry *h; Elf_Internal_Sym *sym; r_symndx = ELF64_R_SYM (rel->r_info); if (!get_sym_h (&h, &sym, &sym_sec, NULL, &local_syms, r_symndx, ibfd)) goto error_ret; if (rel->r_offset == offset) { struct ppc_link_hash_entry *fdh = NULL; /* See if the .opd entry is full 24 byte or 16 byte (with fd_aux entry overlapped with next fd_func). */ opd_ent_size = 24; if ((rel + 2 == relend && sec->size == offset + 16) || (rel + 3 < relend && rel[2].r_offset == offset + 16 && rel[3].r_offset == offset + 24 && ELF64_R_TYPE (rel[2].r_info) == R_PPC64_ADDR64 && ELF64_R_TYPE (rel[3].r_info) == R_PPC64_TOC)) opd_ent_size = 16; if (h != NULL && h->root.root.string[0] == '.') { fdh = get_fdh ((struct ppc_link_hash_entry *) h, ppc_hash_table (info)); if (fdh != NULL && fdh->elf.root.type != bfd_link_hash_defined && fdh->elf.root.type != bfd_link_hash_defweak) fdh = NULL; } skip = (sym_sec->owner != ibfd || sym_sec->output_section == bfd_abs_section_ptr); if (skip) { if (fdh != NULL && sym_sec->owner == ibfd) { /* Arrange for the function descriptor sym to be dropped. */ fdh->elf.root.u.def.value = 0; fdh->elf.root.u.def.section = sym_sec; } opd_adjust[rel->r_offset / 8] = -1; } else { /* We'll be keeping this opd entry. */ if (fdh != NULL) { /* Redefine the function descriptor symbol to this location in the opd section. It is necessary to update the value here rather than using an array of adjustments as we do for local symbols, because various places in the generic ELF code use the value stored in u.def.value. */ fdh->elf.root.u.def.value = wptr - new_contents; fdh->adjust_done = 1; } /* Local syms are a bit tricky. We could tweak them as they can be cached, but we'd need to look through the local syms for the function descriptor sym which we don't have at the moment. So keep an array of adjustments. */ opd_adjust[rel->r_offset / 8] = (wptr - new_contents) - (rptr - sec->contents); if (wptr != rptr) memcpy (wptr, rptr, opd_ent_size); wptr += opd_ent_size; if (add_aux_fields && opd_ent_size == 16) { memset (wptr, '\0', 8); wptr += 8; } } rptr += opd_ent_size; offset += opd_ent_size; } if (skip) { if (!NO_OPD_RELOCS && !info->relocatable && !dec_dynrel_count (rel->r_info, sec, info, NULL, h, sym_sec)) goto error_ret; } else { /* We need to adjust any reloc offsets to point to the new opd entries. While we're at it, we may as well remove redundant relocs. */ rel->r_offset += opd_adjust[(offset - opd_ent_size) / 8]; if (write_rel != rel) memcpy (write_rel, rel, sizeof (*rel)); ++write_rel; } } sec->size = wptr - new_contents; sec->reloc_count = write_rel - relstart; if (add_aux_fields) { free (sec->contents); sec->contents = new_contents; } /* Fudge the header size too, as this is used later in elf_bfd_final_link if we are emitting relocs. */ elf_section_data (sec)->rel_hdr.sh_size = sec->reloc_count * elf_section_data (sec)->rel_hdr.sh_entsize; BFD_ASSERT (elf_section_data (sec)->rel_hdr2 == NULL); some_edited = TRUE; } else if (elf_section_data (sec)->relocs != relstart) free (relstart); if (local_syms != NULL && symtab_hdr->contents != (unsigned char *) local_syms) { if (!info->keep_memory) free (local_syms); else symtab_hdr->contents = (unsigned char *) local_syms; } } if (some_edited) elf_link_hash_traverse (elf_hash_table (info), adjust_opd_syms, NULL); /* If we are doing a final link and the last .opd entry is just 16 byte long, add a 8 byte padding after it. */ if (need_pad != NULL && !info->relocatable) { bfd_byte *p; if ((need_pad->flags & SEC_IN_MEMORY) == 0) { BFD_ASSERT (need_pad->size > 0); p = bfd_malloc (need_pad->size + 8); if (p == NULL) return FALSE; if (! bfd_get_section_contents (need_pad->owner, need_pad, p, 0, need_pad->size)) return FALSE; need_pad->contents = p; need_pad->flags |= (SEC_IN_MEMORY | SEC_HAS_CONTENTS); } else { p = bfd_realloc (need_pad->contents, need_pad->size + 8); if (p == NULL) return FALSE; need_pad->contents = p; } memset (need_pad->contents + need_pad->size, 0, 8); need_pad->size += 8; } return TRUE; } /* Set htab->tls_get_addr and call the generic ELF tls_setup function. */ asection * ppc64_elf_tls_setup (bfd *obfd, struct bfd_link_info *info) { struct ppc_link_hash_table *htab; htab = ppc_hash_table (info); - if (htab->tls_get_addr != NULL) - { - struct ppc_link_hash_entry *h = htab->tls_get_addr; + htab->tls_get_addr = ((struct ppc_link_hash_entry *) + elf_link_hash_lookup (&htab->elf, ".__tls_get_addr", + FALSE, FALSE, TRUE)); + htab->tls_get_addr_fd = ((struct ppc_link_hash_entry *) + elf_link_hash_lookup (&htab->elf, "__tls_get_addr", + FALSE, FALSE, TRUE)); + return _bfd_elf_tls_setup (obfd, info); +} - while (h->elf.root.type == bfd_link_hash_indirect - || h->elf.root.type == bfd_link_hash_warning) - h = (struct ppc_link_hash_entry *) h->elf.root.u.i.link; +/* Return TRUE iff REL is a branch reloc with a global symbol matching + HASH1 or HASH2. */ - htab->tls_get_addr = h; +static bfd_boolean +branch_reloc_hash_match (const bfd *ibfd, + const Elf_Internal_Rela *rel, + const struct ppc_link_hash_entry *hash1, + const struct ppc_link_hash_entry *hash2) +{ + Elf_Internal_Shdr *symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; + enum elf_ppc64_reloc_type r_type = ELF64_R_TYPE (rel->r_info); + unsigned int r_symndx = ELF64_R_SYM (rel->r_info); - if (htab->tls_get_addr_fd == NULL - && h->oh != NULL - && h->oh->is_func_descriptor - && (h->oh->elf.root.type == bfd_link_hash_defined - || h->oh->elf.root.type == bfd_link_hash_defweak)) - htab->tls_get_addr_fd = h->oh; - } - - if (htab->tls_get_addr_fd != NULL) + if (r_symndx >= symtab_hdr->sh_info + && (r_type == R_PPC64_REL24 + || r_type == R_PPC64_REL14 + || r_type == R_PPC64_REL14_BRTAKEN + || r_type == R_PPC64_REL14_BRNTAKEN + || r_type == R_PPC64_ADDR24 + || r_type == R_PPC64_ADDR14 + || r_type == R_PPC64_ADDR14_BRTAKEN + || r_type == R_PPC64_ADDR14_BRNTAKEN)) { - struct ppc_link_hash_entry *h = htab->tls_get_addr_fd; + struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (ibfd); + struct elf_link_hash_entry *h; - while (h->elf.root.type == bfd_link_hash_indirect - || h->elf.root.type == bfd_link_hash_warning) - h = (struct ppc_link_hash_entry *) h->elf.root.u.i.link; - - htab->tls_get_addr_fd = h; + h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + while (h->root.type == bfd_link_hash_indirect + || h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + if (h == &hash1->elf || h == &hash2->elf) + return TRUE; } - - return _bfd_elf_tls_setup (obfd, info); + return FALSE; } /* Run through all the TLS relocs looking for optimization opportunities. The linker has been hacked (see ppc64elf.em) to do a preliminary section layout so that we know the TLS segment offsets. We can't optimize earlier because some optimizations need to know the tp offset, and we need to optimize before allocating dynamic relocations. */ bfd_boolean ppc64_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) { bfd *ibfd; asection *sec; struct ppc_link_hash_table *htab; + int pass; - if (info->relocatable || info->shared) + if (info->relocatable || !info->executable) return TRUE; htab = ppc_hash_table (info); for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) { Elf_Internal_Sym *locsyms = NULL; asection *toc = bfd_get_section_by_name (ibfd, ".toc"); unsigned char *toc_ref = NULL; - /* Look at all the sections for this file, with TOC last. */ - for (sec = (ibfd->sections == toc && toc && toc->next ? toc->next - : ibfd->sections); - sec != NULL; - sec = (sec == toc ? NULL - : sec->next == NULL ? toc - : sec->next == toc && toc->next ? toc->next - : sec->next)) - if (sec->has_tls_reloc && !bfd_is_abs_section (sec->output_section)) - { - Elf_Internal_Rela *relstart, *rel, *relend; - int expecting_tls_get_addr; - long toc_ref_index = 0; + /* Look at all the sections for this file. Make two passes over + the relocs. On the first pass, mark toc entries involved + with tls relocs, and check that tls relocs involved in + setting up a tls_get_addr call are indeed followed by such a + call. If they are not, exclude them from the optimizations + done on the second pass. */ + for (pass = 0; pass < 2; ++pass) + for (sec = ibfd->sections; sec != NULL; sec = sec->next) + if (sec->has_tls_reloc && !bfd_is_abs_section (sec->output_section)) + { + Elf_Internal_Rela *relstart, *rel, *relend; - /* Read the relocations. */ - relstart = _bfd_elf_link_read_relocs (ibfd, sec, NULL, NULL, - info->keep_memory); - if (relstart == NULL) - return FALSE; + /* Read the relocations. */ + relstart = _bfd_elf_link_read_relocs (ibfd, sec, NULL, NULL, + info->keep_memory); + if (relstart == NULL) + return FALSE; - expecting_tls_get_addr = 0; - relend = relstart + sec->reloc_count; - for (rel = relstart; rel < relend; rel++) - { - enum elf_ppc64_reloc_type r_type; - unsigned long r_symndx; - struct elf_link_hash_entry *h; - Elf_Internal_Sym *sym; - asection *sym_sec; - char *tls_mask; - char tls_set, tls_clear, tls_type = 0; - bfd_vma value; - bfd_boolean ok_tprel, is_local; + relend = relstart + sec->reloc_count; + for (rel = relstart; rel < relend; rel++) + { + enum elf_ppc64_reloc_type r_type; + unsigned long r_symndx; + struct elf_link_hash_entry *h; + Elf_Internal_Sym *sym; + asection *sym_sec; + char *tls_mask; + char tls_set, tls_clear, tls_type = 0; + bfd_vma value; + bfd_boolean ok_tprel, is_local; + long toc_ref_index = 0; + int expecting_tls_get_addr = 0; - r_symndx = ELF64_R_SYM (rel->r_info); - if (!get_sym_h (&h, &sym, &sym_sec, &tls_mask, &locsyms, - r_symndx, ibfd)) - { - err_free_rel: - if (elf_section_data (sec)->relocs != relstart) - free (relstart); - if (toc_ref != NULL) - free (toc_ref); - if (locsyms != NULL - && (elf_tdata (ibfd)->symtab_hdr.contents - != (unsigned char *) locsyms)) - free (locsyms); - return FALSE; - } + r_symndx = ELF64_R_SYM (rel->r_info); + if (!get_sym_h (&h, &sym, &sym_sec, &tls_mask, &locsyms, + r_symndx, ibfd)) + { + err_free_rel: + if (elf_section_data (sec)->relocs != relstart) + free (relstart); + if (toc_ref != NULL) + free (toc_ref); + if (locsyms != NULL + && (elf_tdata (ibfd)->symtab_hdr.contents + != (unsigned char *) locsyms)) + free (locsyms); + return FALSE; + } - if (h != NULL) - { - if (h->root.type != bfd_link_hash_defined - && h->root.type != bfd_link_hash_defweak) - continue; - value = h->root.u.def.value; - } - else - /* Symbols referenced by TLS relocs must be of type - STT_TLS. So no need for .opd local sym adjust. */ - value = sym->st_value; + if (h != NULL) + { + if (h->root.type != bfd_link_hash_defined + && h->root.type != bfd_link_hash_defweak) + continue; + value = h->root.u.def.value; + } + else + /* Symbols referenced by TLS relocs must be of type + STT_TLS. So no need for .opd local sym adjust. */ + value = sym->st_value; - ok_tprel = FALSE; - is_local = FALSE; - if (h == NULL - || !h->def_dynamic) - { - is_local = TRUE; - value += sym_sec->output_offset; - value += sym_sec->output_section->vma; - value -= htab->elf.tls_sec->vma; - ok_tprel = (value + TP_OFFSET + ((bfd_vma) 1 << 31) - < (bfd_vma) 1 << 32); - } + ok_tprel = FALSE; + is_local = FALSE; + if (h == NULL + || !h->def_dynamic) + { + is_local = TRUE; + value += sym_sec->output_offset; + value += sym_sec->output_section->vma; + value -= htab->elf.tls_sec->vma; + ok_tprel = (value + TP_OFFSET + ((bfd_vma) 1 << 31) + < (bfd_vma) 1 << 32); + } - r_type = ELF64_R_TYPE (rel->r_info); - switch (r_type) - { - case R_PPC64_GOT_TLSLD16: - case R_PPC64_GOT_TLSLD16_LO: - case R_PPC64_GOT_TLSLD16_HI: - case R_PPC64_GOT_TLSLD16_HA: - /* These relocs should never be against a symbol - defined in a shared lib. Leave them alone if - that turns out to be the case. */ - ppc64_tlsld_got (ibfd)->refcount -= 1; - if (!is_local) - continue; + r_type = ELF64_R_TYPE (rel->r_info); + switch (r_type) + { + case R_PPC64_GOT_TLSLD16: + case R_PPC64_GOT_TLSLD16_LO: + expecting_tls_get_addr = 1; + /* Fall thru */ - /* LD -> LE */ - tls_set = 0; - tls_clear = TLS_LD; - tls_type = TLS_TLS | TLS_LD; - expecting_tls_get_addr = 1; - break; + case R_PPC64_GOT_TLSLD16_HI: + case R_PPC64_GOT_TLSLD16_HA: + /* These relocs should never be against a symbol + defined in a shared lib. Leave them alone if + that turns out to be the case. */ + if (!is_local) + continue; - case R_PPC64_GOT_TLSGD16: - case R_PPC64_GOT_TLSGD16_LO: - case R_PPC64_GOT_TLSGD16_HI: - case R_PPC64_GOT_TLSGD16_HA: - if (ok_tprel) - /* GD -> LE */ + /* LD -> LE */ tls_set = 0; - else - /* GD -> IE */ - tls_set = TLS_TLS | TLS_TPRELGD; - tls_clear = TLS_GD; - tls_type = TLS_TLS | TLS_GD; - expecting_tls_get_addr = 1; - break; + tls_clear = TLS_LD; + tls_type = TLS_TLS | TLS_LD; + break; - case R_PPC64_GOT_TPREL16_DS: - case R_PPC64_GOT_TPREL16_LO_DS: - case R_PPC64_GOT_TPREL16_HI: - case R_PPC64_GOT_TPREL16_HA: - expecting_tls_get_addr = 0; - if (ok_tprel) - { - /* IE -> LE */ + case R_PPC64_GOT_TLSGD16: + case R_PPC64_GOT_TLSGD16_LO: + expecting_tls_get_addr = 1; + /* Fall thru */ + + case R_PPC64_GOT_TLSGD16_HI: + case R_PPC64_GOT_TLSGD16_HA: + if (ok_tprel) + /* GD -> LE */ tls_set = 0; - tls_clear = TLS_TPREL; - tls_type = TLS_TLS | TLS_TPREL; - break; - } - else + else + /* GD -> IE */ + tls_set = TLS_TLS | TLS_TPRELGD; + tls_clear = TLS_GD; + tls_type = TLS_TLS | TLS_GD; + break; + + case R_PPC64_GOT_TPREL16_DS: + case R_PPC64_GOT_TPREL16_LO_DS: + case R_PPC64_GOT_TPREL16_HI: + case R_PPC64_GOT_TPREL16_HA: + if (ok_tprel) + { + /* IE -> LE */ + tls_set = 0; + tls_clear = TLS_TPREL; + tls_type = TLS_TLS | TLS_TPREL; + break; + } continue; - case R_PPC64_REL14: - case R_PPC64_REL14_BRTAKEN: - case R_PPC64_REL14_BRNTAKEN: - case R_PPC64_REL24: - if (h != NULL - && (h == &htab->tls_get_addr->elf - || h == &htab->tls_get_addr_fd->elf)) - { - if (!expecting_tls_get_addr - && rel != relstart - && ((ELF64_R_TYPE (rel[-1].r_info) - == R_PPC64_TOC16) - || (ELF64_R_TYPE (rel[-1].r_info) - == R_PPC64_TOC16_LO))) - { - /* Check for toc tls entries. */ - char *toc_tls; - int retval; + case R_PPC64_TOC16: + case R_PPC64_TOC16_LO: + case R_PPC64_TLS: + case R_PPC64_TLSGD: + case R_PPC64_TLSLD: + if (sym_sec == NULL || sym_sec != toc) + continue; - retval = get_tls_mask (&toc_tls, NULL, &locsyms, - rel - 1, ibfd); - if (retval == 0) - goto err_free_rel; - if (retval > 1 && toc_tls != NULL) - { - expecting_tls_get_addr = 1; - if (toc_ref != NULL) - toc_ref[toc_ref_index] = 1; - } - } + /* Mark this toc entry as referenced by a TLS + code sequence. We can do that now in the + case of R_PPC64_TLS, and after checking for + tls_get_addr for the TOC16 relocs. */ + if (toc_ref == NULL) + { + toc_ref = bfd_zmalloc (toc->size / 8); + if (toc_ref == NULL) + goto err_free_rel; + } + if (h != NULL) + value = h->root.u.def.value; + else + value = sym->st_value; + value += rel->r_addend; + BFD_ASSERT (value < toc->size && value % 8 == 0); + toc_ref_index = value / 8; + if (r_type == R_PPC64_TLS + || r_type == R_PPC64_TLSGD + || r_type == R_PPC64_TLSLD) + { + toc_ref[toc_ref_index] = 1; + continue; + } - if (expecting_tls_get_addr) - { - struct plt_entry *ent; - for (ent = h->plt.plist; ent; ent = ent->next) - if (ent->addend == 0) - { - if (ent->plt.refcount > 0) - ent->plt.refcount -= 1; - break; - } - } - } - expecting_tls_get_addr = 0; - continue; + if (pass != 0 && toc_ref[toc_ref_index] == 0) + continue; - case R_PPC64_TOC16: - case R_PPC64_TOC16_LO: - case R_PPC64_TLS: - expecting_tls_get_addr = 0; - if (sym_sec == toc && toc != NULL) - { - /* Mark this toc entry as referenced by a TLS - code sequence. We can do that now in the - case of R_PPC64_TLS, and after checking for - tls_get_addr for the TOC16 relocs. */ - if (toc_ref == NULL) - { - toc_ref = bfd_zmalloc (toc->size / 8); - if (toc_ref == NULL) - goto err_free_rel; - } - if (h != NULL) - value = h->root.u.def.value; - else - value = sym->st_value; - value += rel->r_addend; - BFD_ASSERT (value < toc->size && value % 8 == 0); - toc_ref_index = value / 8; - if (r_type == R_PPC64_TLS) - toc_ref[toc_ref_index] = 1; - } - continue; + tls_set = 0; + tls_clear = 0; + expecting_tls_get_addr = 2; + break; - case R_PPC64_TPREL64: - expecting_tls_get_addr = 0; - if (sec != toc - || toc_ref == NULL - || !toc_ref[rel->r_offset / 8]) + case R_PPC64_TPREL64: + if (pass == 0 + || sec != toc + || toc_ref == NULL + || !toc_ref[rel->r_offset / 8]) + continue; + if (ok_tprel) + { + /* IE -> LE */ + tls_set = TLS_EXPLICIT; + tls_clear = TLS_TPREL; + break; + } continue; - if (ok_tprel) - { - /* IE -> LE */ - tls_set = TLS_EXPLICIT; - tls_clear = TLS_TPREL; - break; - } - else - continue; - case R_PPC64_DTPMOD64: - expecting_tls_get_addr = 0; - if (sec != toc - || toc_ref == NULL - || !toc_ref[rel->r_offset / 8]) + case R_PPC64_DTPMOD64: + if (pass == 0 + || sec != toc + || toc_ref == NULL + || !toc_ref[rel->r_offset / 8]) + continue; + if (rel + 1 < relend + && (rel[1].r_info + == ELF64_R_INFO (r_symndx, R_PPC64_DTPREL64)) + && rel[1].r_offset == rel->r_offset + 8) + { + if (ok_tprel) + /* GD -> LE */ + tls_set = TLS_EXPLICIT | TLS_GD; + else + /* GD -> IE */ + tls_set = TLS_EXPLICIT | TLS_GD | TLS_TPRELGD; + tls_clear = TLS_GD; + } + else + { + if (!is_local) + continue; + + /* LD -> LE */ + tls_set = TLS_EXPLICIT; + tls_clear = TLS_LD; + } + break; + + default: continue; - if (rel + 1 < relend - && (rel[1].r_info - == ELF64_R_INFO (r_symndx, R_PPC64_DTPREL64)) - && rel[1].r_offset == rel->r_offset + 8) - { - if (ok_tprel) - /* GD -> LE */ - tls_set = TLS_EXPLICIT | TLS_GD; - else - /* GD -> IE */ - tls_set = TLS_EXPLICIT | TLS_GD | TLS_TPRELGD; - tls_clear = TLS_GD; - } - else - { - if (!is_local) + } + + if (pass == 0) + { + if (!expecting_tls_get_addr + || !sec->has_tls_get_addr_call) + continue; + + if (rel + 1 < relend + && branch_reloc_hash_match (ibfd, rel + 1, + htab->tls_get_addr, + htab->tls_get_addr_fd)) + { + if (expecting_tls_get_addr == 2) + { + /* Check for toc tls entries. */ + char *toc_tls; + int retval; + + retval = get_tls_mask (&toc_tls, NULL, NULL, + &locsyms, + rel, ibfd); + if (retval == 0) + goto err_free_rel; + if (retval > 1 && toc_tls != NULL) + toc_ref[toc_ref_index] = 1; + } continue; + } - /* LD -> LE */ - tls_set = TLS_EXPLICIT; - tls_clear = TLS_LD; - } - break; + if (expecting_tls_get_addr != 1) + continue; - default: - expecting_tls_get_addr = 0; + /* Uh oh, we didn't find the expected call. We + could just mark this symbol to exclude it + from tls optimization but it's safer to skip + the entire section. */ + sec->has_tls_reloc = 0; + break; + } + + if (expecting_tls_get_addr) + { + struct plt_entry *ent; + for (ent = htab->tls_get_addr->elf.plt.plist; + ent != NULL; + ent = ent->next) + if (ent->addend == 0) + { + if (ent->plt.refcount > 0) + { + ent->plt.refcount -= 1; + expecting_tls_get_addr = 0; + } + break; + } + } + + if (expecting_tls_get_addr) + { + struct plt_entry *ent; + for (ent = htab->tls_get_addr_fd->elf.plt.plist; + ent != NULL; + ent = ent->next) + if (ent->addend == 0) + { + if (ent->plt.refcount > 0) + ent->plt.refcount -= 1; + break; + } + } + + if (tls_clear == 0) continue; - } - if ((tls_set & TLS_EXPLICIT) == 0) - { - struct got_entry *ent; + if ((tls_set & TLS_EXPLICIT) == 0) + { + struct got_entry *ent; - /* Adjust got entry for this reloc. */ - if (h != NULL) - ent = h->got.glist; - else - ent = elf_local_got_ents (ibfd)[r_symndx]; + /* Adjust got entry for this reloc. */ + if (h != NULL) + ent = h->got.glist; + else + ent = elf_local_got_ents (ibfd)[r_symndx]; - for (; ent != NULL; ent = ent->next) - if (ent->addend == rel->r_addend - && ent->owner == ibfd - && ent->tls_type == tls_type) - break; - if (ent == NULL) - abort (); + for (; ent != NULL; ent = ent->next) + if (ent->addend == rel->r_addend + && ent->owner == ibfd + && ent->tls_type == tls_type) + break; + if (ent == NULL) + abort (); - if (tls_set == 0) - { - /* We managed to get rid of a got entry. */ - if (ent->got.refcount > 0) - ent->got.refcount -= 1; - } - } - else - { - /* If we got rid of a DTPMOD/DTPREL reloc pair then - we'll lose one or two dyn relocs. */ - if (!dec_dynrel_count (rel->r_info, sec, info, - NULL, h, sym_sec)) - return FALSE; + if (tls_set == 0) + { + /* We managed to get rid of a got entry. */ + if (ent->got.refcount > 0) + ent->got.refcount -= 1; + } + } + else + { + /* If we got rid of a DTPMOD/DTPREL reloc pair then + we'll lose one or two dyn relocs. */ + if (!dec_dynrel_count (rel->r_info, sec, info, + NULL, h, sym_sec)) + return FALSE; - if (tls_set == (TLS_EXPLICIT | TLS_GD)) - { - if (!dec_dynrel_count ((rel + 1)->r_info, sec, info, - NULL, h, sym_sec)) - return FALSE; - } - } + if (tls_set == (TLS_EXPLICIT | TLS_GD)) + { + if (!dec_dynrel_count ((rel + 1)->r_info, sec, info, + NULL, h, sym_sec)) + return FALSE; + } + } - *tls_mask |= tls_set; - *tls_mask &= ~tls_clear; - } + *tls_mask |= tls_set; + *tls_mask &= ~tls_clear; + } - if (elf_section_data (sec)->relocs != relstart) - free (relstart); - } + if (elf_section_data (sec)->relocs != relstart) + free (relstart); + } - if (toc_ref != NULL) - free (toc_ref); + if (toc_ref != NULL) + free (toc_ref); - if (locsyms != NULL - && (elf_tdata (ibfd)->symtab_hdr.contents - != (unsigned char *) locsyms)) - { - if (!info->keep_memory) - free (locsyms); - else - elf_tdata (ibfd)->symtab_hdr.contents = (unsigned char *) locsyms; - } - } + if (locsyms != NULL + && (elf_tdata (ibfd)->symtab_hdr.contents + != (unsigned char *) locsyms)) + { + if (!info->keep_memory) + free (locsyms); + else + elf_tdata (ibfd)->symtab_hdr.contents = (unsigned char *) locsyms; + } + } return TRUE; } /* Called via elf_link_hash_traverse from ppc64_elf_edit_toc to adjust the values of any global symbols in a toc section that has been edited. Globals in toc sections should be a rarity, so this function sets a flag if any are found in toc sections other than the one just edited, so that futher hash table traversals can be avoided. */ struct adjust_toc_info { asection *toc; unsigned long *skip; bfd_boolean global_toc_syms; }; static bfd_boolean adjust_toc_syms (struct elf_link_hash_entry *h, void *inf) { struct ppc_link_hash_entry *eh; struct adjust_toc_info *toc_inf = (struct adjust_toc_info *) inf; if (h->root.type == bfd_link_hash_indirect) return TRUE; if (h->root.type == bfd_link_hash_warning) h = (struct elf_link_hash_entry *) h->root.u.i.link; if (h->root.type != bfd_link_hash_defined && h->root.type != bfd_link_hash_defweak) return TRUE; eh = (struct ppc_link_hash_entry *) h; if (eh->adjust_done) return TRUE; if (eh->elf.root.u.def.section == toc_inf->toc) { unsigned long skip = toc_inf->skip[eh->elf.root.u.def.value >> 3]; if (skip != (unsigned long) -1) eh->elf.root.u.def.value -= skip; else { (*_bfd_error_handler) (_("%s defined in removed toc entry"), eh->elf.root.root.string); eh->elf.root.u.def.section = &bfd_abs_section; eh->elf.root.u.def.value = 0; } eh->adjust_done = 1; } else if (strcmp (eh->elf.root.u.def.section->name, ".toc") == 0) toc_inf->global_toc_syms = TRUE; return TRUE; } /* Examine all relocs referencing .toc sections in order to remove unused .toc entries. */ bfd_boolean ppc64_elf_edit_toc (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) { bfd *ibfd; struct adjust_toc_info toc_inf; toc_inf.global_toc_syms = TRUE; for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) { asection *toc, *sec; Elf_Internal_Shdr *symtab_hdr; Elf_Internal_Sym *local_syms; struct elf_link_hash_entry **sym_hashes; Elf_Internal_Rela *relstart, *rel; unsigned long *skip, *drop; unsigned char *used; unsigned char *keep, last, some_unused; toc = bfd_get_section_by_name (ibfd, ".toc"); if (toc == NULL || toc->size == 0 || toc->sec_info_type == ELF_INFO_TYPE_JUST_SYMS || elf_discarded_section (toc)) continue; local_syms = NULL; symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; sym_hashes = elf_sym_hashes (ibfd); /* Look at sections dropped from the final link. */ skip = NULL; relstart = NULL; for (sec = ibfd->sections; sec != NULL; sec = sec->next) { if (sec->reloc_count == 0 || !elf_discarded_section (sec) || get_opd_info (sec) || (sec->flags & SEC_ALLOC) == 0 || (sec->flags & SEC_DEBUGGING) != 0) continue; relstart = _bfd_elf_link_read_relocs (ibfd, sec, NULL, NULL, FALSE); if (relstart == NULL) goto error_ret; /* Run through the relocs to see which toc entries might be unused. */ for (rel = relstart; rel < relstart + sec->reloc_count; ++rel) { enum elf_ppc64_reloc_type r_type; unsigned long r_symndx; asection *sym_sec; struct elf_link_hash_entry *h; Elf_Internal_Sym *sym; bfd_vma val; r_type = ELF64_R_TYPE (rel->r_info); switch (r_type) { default: continue; case R_PPC64_TOC16: case R_PPC64_TOC16_LO: case R_PPC64_TOC16_HI: case R_PPC64_TOC16_HA: case R_PPC64_TOC16_DS: case R_PPC64_TOC16_LO_DS: break; } r_symndx = ELF64_R_SYM (rel->r_info); if (!get_sym_h (&h, &sym, &sym_sec, NULL, &local_syms, r_symndx, ibfd)) goto error_ret; if (sym_sec != toc) continue; if (h != NULL) val = h->root.u.def.value; else val = sym->st_value; val += rel->r_addend; if (val >= toc->size) continue; /* Anything in the toc ought to be aligned to 8 bytes. If not, don't mark as unused. */ if (val & 7) continue; if (skip == NULL) { skip = bfd_zmalloc (sizeof (*skip) * (toc->size + 7) / 8); if (skip == NULL) goto error_ret; } skip[val >> 3] = 1; } if (elf_section_data (sec)->relocs != relstart) free (relstart); } if (skip == NULL) continue; used = bfd_zmalloc (sizeof (*used) * (toc->size + 7) / 8); if (used == NULL) { error_ret: if (local_syms != NULL && symtab_hdr->contents != (unsigned char *) local_syms) free (local_syms); if (sec != NULL && relstart != NULL && elf_section_data (sec)->relocs != relstart) free (relstart); if (skip != NULL) free (skip); return FALSE; } /* Now check all kept sections that might reference the toc. Check the toc itself last. */ for (sec = (ibfd->sections == toc && toc->next ? toc->next : ibfd->sections); sec != NULL; sec = (sec == toc ? NULL : sec->next == NULL ? toc : sec->next == toc && toc->next ? toc->next : sec->next)) { int repeat; if (sec->reloc_count == 0 || elf_discarded_section (sec) || get_opd_info (sec) || (sec->flags & SEC_ALLOC) == 0 || (sec->flags & SEC_DEBUGGING) != 0) continue; relstart = _bfd_elf_link_read_relocs (ibfd, sec, NULL, NULL, TRUE); if (relstart == NULL) goto error_ret; /* Mark toc entries referenced as used. */ repeat = 0; do for (rel = relstart; rel < relstart + sec->reloc_count; ++rel) { enum elf_ppc64_reloc_type r_type; unsigned long r_symndx; asection *sym_sec; struct elf_link_hash_entry *h; Elf_Internal_Sym *sym; bfd_vma val; r_type = ELF64_R_TYPE (rel->r_info); switch (r_type) { case R_PPC64_TOC16: case R_PPC64_TOC16_LO: case R_PPC64_TOC16_HI: case R_PPC64_TOC16_HA: case R_PPC64_TOC16_DS: case R_PPC64_TOC16_LO_DS: /* In case we're taking addresses of toc entries. */ case R_PPC64_ADDR64: break; default: continue; } r_symndx = ELF64_R_SYM (rel->r_info); if (!get_sym_h (&h, &sym, &sym_sec, NULL, &local_syms, r_symndx, ibfd)) { free (used); goto error_ret; } if (sym_sec != toc) continue; if (h != NULL) val = h->root.u.def.value; else val = sym->st_value; val += rel->r_addend; if (val >= toc->size) continue; /* For the toc section, we only mark as used if this entry itself isn't unused. */ if (sec == toc && !used[val >> 3] && (used[rel->r_offset >> 3] || !skip[rel->r_offset >> 3])) /* Do all the relocs again, to catch reference chains. */ repeat = 1; used[val >> 3] = 1; } while (repeat); } /* Merge the used and skip arrays. Assume that TOC doublewords not appearing as either used or unused belong to to an entry more than one doubleword in size. */ for (drop = skip, keep = used, last = 0, some_unused = 0; drop < skip + (toc->size + 7) / 8; ++drop, ++keep) { if (*keep) { *drop = 0; last = 0; } else if (*drop) { some_unused = 1; last = 1; } else *drop = last; } free (used); if (some_unused) { bfd_byte *contents, *src; unsigned long off; /* Shuffle the toc contents, and at the same time convert the skip array from booleans into offsets. */ if (!bfd_malloc_and_get_section (ibfd, toc, &contents)) goto error_ret; elf_section_data (toc)->this_hdr.contents = contents; for (src = contents, off = 0, drop = skip; src < contents + toc->size; src += 8, ++drop) { if (*drop) { *drop = (unsigned long) -1; off += 8; } else if (off != 0) { *drop = off; memcpy (src - off, src, 8); } } toc->rawsize = toc->size; toc->size = src - contents - off; if (toc->reloc_count != 0) { Elf_Internal_Rela *wrel; bfd_size_type sz; /* Read toc relocs. */ relstart = _bfd_elf_link_read_relocs (ibfd, toc, NULL, NULL, TRUE); if (relstart == NULL) goto error_ret; /* Remove unused toc relocs, and adjust those we keep. */ wrel = relstart; for (rel = relstart; rel < relstart + toc->reloc_count; ++rel) if (skip[rel->r_offset >> 3] != (unsigned long) -1) { wrel->r_offset = rel->r_offset - skip[rel->r_offset >> 3]; wrel->r_info = rel->r_info; wrel->r_addend = rel->r_addend; ++wrel; } else if (!dec_dynrel_count (rel->r_info, toc, info, &local_syms, NULL, NULL)) goto error_ret; toc->reloc_count = wrel - relstart; sz = elf_section_data (toc)->rel_hdr.sh_entsize; elf_section_data (toc)->rel_hdr.sh_size = toc->reloc_count * sz; BFD_ASSERT (elf_section_data (toc)->rel_hdr2 == NULL); } /* Adjust addends for relocs against the toc section sym. */ for (sec = ibfd->sections; sec != NULL; sec = sec->next) { if (sec->reloc_count == 0 || elf_discarded_section (sec)) continue; relstart = _bfd_elf_link_read_relocs (ibfd, sec, NULL, NULL, TRUE); if (relstart == NULL) goto error_ret; for (rel = relstart; rel < relstart + sec->reloc_count; ++rel) { enum elf_ppc64_reloc_type r_type; unsigned long r_symndx; asection *sym_sec; struct elf_link_hash_entry *h; Elf_Internal_Sym *sym; r_type = ELF64_R_TYPE (rel->r_info); switch (r_type) { default: continue; case R_PPC64_TOC16: case R_PPC64_TOC16_LO: case R_PPC64_TOC16_HI: case R_PPC64_TOC16_HA: case R_PPC64_TOC16_DS: case R_PPC64_TOC16_LO_DS: case R_PPC64_ADDR64: break; } r_symndx = ELF64_R_SYM (rel->r_info); if (!get_sym_h (&h, &sym, &sym_sec, NULL, &local_syms, r_symndx, ibfd)) goto error_ret; if (sym_sec != toc || h != NULL || sym->st_value != 0) continue; rel->r_addend -= skip[rel->r_addend >> 3]; } } /* We shouldn't have local or global symbols defined in the TOC, but handle them anyway. */ if (local_syms != NULL) { Elf_Internal_Sym *sym; for (sym = local_syms; sym < local_syms + symtab_hdr->sh_info; ++sym) if (sym->st_shndx != SHN_UNDEF && (sym->st_shndx < SHN_LORESERVE || sym->st_shndx > SHN_HIRESERVE) && sym->st_value != 0 && bfd_section_from_elf_index (ibfd, sym->st_shndx) == toc) { if (skip[sym->st_value >> 3] != (unsigned long) -1) sym->st_value -= skip[sym->st_value >> 3]; else { (*_bfd_error_handler) (_("%s defined in removed toc entry"), bfd_elf_sym_name (ibfd, symtab_hdr, sym, NULL)); sym->st_value = 0; sym->st_shndx = SHN_ABS; } symtab_hdr->contents = (unsigned char *) local_syms; } } /* Finally, adjust any global syms defined in the toc. */ if (toc_inf.global_toc_syms) { toc_inf.toc = toc; toc_inf.skip = skip; toc_inf.global_toc_syms = FALSE; elf_link_hash_traverse (elf_hash_table (info), adjust_toc_syms, &toc_inf); } } if (local_syms != NULL && symtab_hdr->contents != (unsigned char *) local_syms) { if (!info->keep_memory) free (local_syms); else symtab_hdr->contents = (unsigned char *) local_syms; } free (skip); } return TRUE; } /* Allocate space in .plt, .got and associated reloc sections for dynamic relocs. */ static bfd_boolean allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) { struct bfd_link_info *info; struct ppc_link_hash_table *htab; asection *s; struct ppc_link_hash_entry *eh; struct ppc_dyn_relocs *p; struct got_entry *gent; if (h->root.type == bfd_link_hash_indirect) return TRUE; if (h->root.type == bfd_link_hash_warning) h = (struct elf_link_hash_entry *) h->root.u.i.link; info = (struct bfd_link_info *) inf; htab = ppc_hash_table (info); if (htab->elf.dynamic_sections_created && h->dynindx != -1 && WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info->shared, h)) { struct plt_entry *pent; bfd_boolean doneone = FALSE; for (pent = h->plt.plist; pent != NULL; pent = pent->next) if (pent->plt.refcount > 0) { /* If this is the first .plt entry, make room for the special first entry. */ s = htab->plt; if (s->size == 0) s->size += PLT_INITIAL_ENTRY_SIZE; pent->plt.offset = s->size; /* Make room for this entry. */ s->size += PLT_ENTRY_SIZE; /* Make room for the .glink code. */ s = htab->glink; if (s->size == 0) s->size += GLINK_CALL_STUB_SIZE; /* We need bigger stubs past index 32767. */ if (s->size >= GLINK_CALL_STUB_SIZE + 32768*2*4) s->size += 4; s->size += 2*4; /* We also need to make an entry in the .rela.plt section. */ s = htab->relplt; s->size += sizeof (Elf64_External_Rela); doneone = TRUE; } else pent->plt.offset = (bfd_vma) -1; if (!doneone) { h->plt.plist = NULL; h->needs_plt = 0; } } else { h->plt.plist = NULL; h->needs_plt = 0; } eh = (struct ppc_link_hash_entry *) h; /* Run through the TLS GD got entries first if we're changing them to TPREL. */ if ((eh->tls_mask & TLS_TPRELGD) != 0) for (gent = h->got.glist; gent != NULL; gent = gent->next) if (gent->got.refcount > 0 && (gent->tls_type & TLS_GD) != 0) { /* This was a GD entry that has been converted to TPREL. If there happens to be a TPREL entry we can use that one. */ struct got_entry *ent; for (ent = h->got.glist; ent != NULL; ent = ent->next) if (ent->got.refcount > 0 && (ent->tls_type & TLS_TPREL) != 0 && ent->addend == gent->addend && ent->owner == gent->owner) { gent->got.refcount = 0; break; } /* If not, then we'll be using our own TPREL entry. */ if (gent->got.refcount != 0) gent->tls_type = TLS_TLS | TLS_TPREL; } for (gent = h->got.glist; gent != NULL; gent = gent->next) if (gent->got.refcount > 0) { bfd_boolean dyn; /* Make sure this symbol is output as a dynamic symbol. Undefined weak syms won't yet be marked as dynamic, nor will all TLS symbols. */ if (h->dynindx == -1 && !h->forced_local) { if (! bfd_elf_link_record_dynamic_symbol (info, h)) return FALSE; } if ((gent->tls_type & TLS_LD) != 0 && !h->def_dynamic) { - gent->got.offset = ppc64_tlsld_got (gent->owner)->offset; + ppc64_tlsld_got (gent->owner)->refcount += 1; + gent->got.offset = (bfd_vma) -1; continue; } s = ppc64_elf_tdata (gent->owner)->got; gent->got.offset = s->size; s->size += (gent->tls_type & eh->tls_mask & (TLS_GD | TLS_LD)) ? 16 : 8; dyn = htab->elf.dynamic_sections_created; if ((info->shared || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)) && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT || h->root.type != bfd_link_hash_undefweak)) ppc64_elf_tdata (gent->owner)->relgot->size += (gent->tls_type & eh->tls_mask & TLS_GD ? 2 * sizeof (Elf64_External_Rela) : sizeof (Elf64_External_Rela)); } else gent->got.offset = (bfd_vma) -1; if (eh->dyn_relocs == NULL) return TRUE; /* In the shared -Bsymbolic case, discard space allocated for dynamic pc-relative relocs against symbols which turn out to be defined in regular objects. For the normal shared case, discard space for relocs that have become local due to symbol visibility changes. */ if (info->shared) { /* Relocs that use pc_count are those that appear on a call insn, - or certain REL relocs (see MUST_BE_DYN_RELOC) that can be + or certain REL relocs (see must_be_dyn_reloc) that can be generated via assembly. We want calls to protected symbols to resolve directly to the function rather than going via the plt. If people want function pointer comparisons to work as expected then they should avoid writing weird assembly. */ if (SYMBOL_CALLS_LOCAL (info, h)) { struct ppc_dyn_relocs **pp; for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) { p->count -= p->pc_count; p->pc_count = 0; if (p->count == 0) *pp = p->next; else pp = &p->next; } } /* Also discard relocs on undefined weak syms with non-default visibility. */ if (eh->dyn_relocs != NULL && h->root.type == bfd_link_hash_undefweak) { if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT) eh->dyn_relocs = NULL; /* Make sure this symbol is output as a dynamic symbol. Undefined weak syms won't yet be marked as dynamic. */ else if (h->dynindx == -1 && !h->forced_local) { if (! bfd_elf_link_record_dynamic_symbol (info, h)) return FALSE; } } } else if (ELIMINATE_COPY_RELOCS) { /* For the non-shared case, discard space for relocs against symbols which turn out to need copy relocs or are not dynamic. */ if (!h->non_got_ref && h->def_dynamic && !h->def_regular) { /* Make sure this symbol is output as a dynamic symbol. Undefined weak syms won't yet be marked as dynamic. */ if (h->dynindx == -1 && !h->forced_local) { if (! bfd_elf_link_record_dynamic_symbol (info, h)) return FALSE; } /* If that succeeded, we know we'll be keeping all the relocs. */ if (h->dynindx != -1) goto keep; } eh->dyn_relocs = NULL; keep: ; } /* Finally, allocate space. */ for (p = eh->dyn_relocs; p != NULL; p = p->next) { asection *sreloc = elf_section_data (p->sec)->sreloc; sreloc->size += p->count * sizeof (Elf64_External_Rela); } return TRUE; } /* Find any dynamic relocs that apply to read-only sections. */ static bfd_boolean readonly_dynrelocs (struct elf_link_hash_entry *h, void *inf) { struct ppc_link_hash_entry *eh; struct ppc_dyn_relocs *p; if (h->root.type == bfd_link_hash_warning) h = (struct elf_link_hash_entry *) h->root.u.i.link; eh = (struct ppc_link_hash_entry *) h; for (p = eh->dyn_relocs; p != NULL; p = p->next) { asection *s = p->sec->output_section; if (s != NULL && (s->flags & SEC_READONLY) != 0) { struct bfd_link_info *info = inf; info->flags |= DF_TEXTREL; /* Not an error, just cut short the traversal. */ return FALSE; } } return TRUE; } /* Set the sizes of the dynamic sections. */ static bfd_boolean ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) { struct ppc_link_hash_table *htab; bfd *dynobj; asection *s; bfd_boolean relocs; bfd *ibfd; htab = ppc_hash_table (info); dynobj = htab->elf.dynobj; if (dynobj == NULL) abort (); if (htab->elf.dynamic_sections_created) { /* Set the contents of the .interp section to the interpreter. */ if (info->executable) { s = bfd_get_section_by_name (dynobj, ".interp"); if (s == NULL) abort (); s->size = sizeof ELF_DYNAMIC_INTERPRETER; s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; } } /* Set up .got offsets for local syms, and space for local dynamic relocs. */ for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) { struct got_entry **lgot_ents; struct got_entry **end_lgot_ents; char *lgot_masks; bfd_size_type locsymcount; Elf_Internal_Shdr *symtab_hdr; asection *srel; if (!is_ppc64_elf_target (ibfd->xvec)) continue; - if (ppc64_tlsld_got (ibfd)->refcount > 0) - { - s = ppc64_elf_tdata (ibfd)->got; - ppc64_tlsld_got (ibfd)->offset = s->size; - s->size += 16; - if (info->shared) - { - srel = ppc64_elf_tdata (ibfd)->relgot; - srel->size += sizeof (Elf64_External_Rela); - } - } - else - ppc64_tlsld_got (ibfd)->offset = (bfd_vma) -1; - for (s = ibfd->sections; s != NULL; s = s->next) { struct ppc_dyn_relocs *p; for (p = elf_section_data (s)->local_dynrel; p != NULL; p = p->next) { if (!bfd_is_abs_section (p->sec) && bfd_is_abs_section (p->sec->output_section)) { /* Input section has been discarded, either because it is a copy of a linkonce section or due to linker script /DISCARD/, so we'll be discarding the relocs too. */ } else if (p->count != 0) { srel = elf_section_data (p->sec)->sreloc; srel->size += p->count * sizeof (Elf64_External_Rela); if ((p->sec->output_section->flags & SEC_READONLY) != 0) info->flags |= DF_TEXTREL; } } } lgot_ents = elf_local_got_ents (ibfd); if (!lgot_ents) continue; symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; locsymcount = symtab_hdr->sh_info; end_lgot_ents = lgot_ents + locsymcount; lgot_masks = (char *) end_lgot_ents; s = ppc64_elf_tdata (ibfd)->got; srel = ppc64_elf_tdata (ibfd)->relgot; for (; lgot_ents < end_lgot_ents; ++lgot_ents, ++lgot_masks) { struct got_entry *ent; for (ent = *lgot_ents; ent != NULL; ent = ent->next) if (ent->got.refcount > 0) { if ((ent->tls_type & *lgot_masks & TLS_LD) != 0) { - if (ppc64_tlsld_got (ibfd)->offset == (bfd_vma) -1) - { - ppc64_tlsld_got (ibfd)->offset = s->size; - s->size += 16; - if (info->shared) - srel->size += sizeof (Elf64_External_Rela); - } - ent->got.offset = ppc64_tlsld_got (ibfd)->offset; + ppc64_tlsld_got (ibfd)->refcount += 1; + ent->got.offset = (bfd_vma) -1; } else { ent->got.offset = s->size; if ((ent->tls_type & *lgot_masks & TLS_GD) != 0) { s->size += 16; if (info->shared) srel->size += 2 * sizeof (Elf64_External_Rela); } else { s->size += 8; if (info->shared) srel->size += sizeof (Elf64_External_Rela); } } } else ent->got.offset = (bfd_vma) -1; } } /* Allocate global sym .plt and .got entries, and space for global sym dynamic relocs. */ elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, info); + for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) + { + if (!is_ppc64_elf_target (ibfd->xvec)) + continue; + + if (ppc64_tlsld_got (ibfd)->refcount > 0) + { + s = ppc64_elf_tdata (ibfd)->got; + ppc64_tlsld_got (ibfd)->offset = s->size; + s->size += 16; + if (info->shared) + { + asection *srel = ppc64_elf_tdata (ibfd)->relgot; + srel->size += sizeof (Elf64_External_Rela); + } + } + else + ppc64_tlsld_got (ibfd)->offset = (bfd_vma) -1; + } + /* We now have determined the sizes of the various dynamic sections. Allocate memory for them. */ relocs = FALSE; for (s = dynobj->sections; s != NULL; s = s->next) { if ((s->flags & SEC_LINKER_CREATED) == 0) continue; if (s == htab->brlt || s == htab->relbrlt) /* These haven't been allocated yet; don't strip. */ continue; else if (s == htab->got || s == htab->plt || s == htab->glink || s == htab->dynbss) { /* Strip this section if we don't need it; see the comment below. */ } else if (CONST_STRNEQ (bfd_get_section_name (dynobj, s), ".rela")) { if (s->size != 0) { if (s != htab->relplt) relocs = TRUE; /* We use the reloc_count field as a counter if we need to copy relocs into the output file. */ s->reloc_count = 0; } } else { /* It's not one of our sections, so don't allocate space. */ continue; } if (s->size == 0) { /* If we don't need this section, strip it from the output file. This is mostly to handle .rela.bss and .rela.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 adjust_dynamic_symbol is called, and it is that function which decides whether anything needs to go into these sections. */ s->flags |= SEC_EXCLUDE; continue; } if ((s->flags & SEC_HAS_CONTENTS) == 0) continue; /* Allocate memory for the section contents. We use bfd_zalloc here in case unused entries are not reclaimed before the section's contents are written out. This should not happen, but this way if it does we get a R_PPC64_NONE reloc in .rela sections instead of garbage. We also rely on the section contents being zero when writing the GOT. */ s->contents = bfd_zalloc (dynobj, s->size); if (s->contents == NULL) return FALSE; } for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) { if (!is_ppc64_elf_target (ibfd->xvec)) continue; s = ppc64_elf_tdata (ibfd)->got; if (s != NULL && s != htab->got) { if (s->size == 0) s->flags |= SEC_EXCLUDE; else { s->contents = bfd_zalloc (ibfd, s->size); if (s->contents == NULL) return FALSE; } } s = ppc64_elf_tdata (ibfd)->relgot; if (s != NULL) { if (s->size == 0) s->flags |= SEC_EXCLUDE; else { s->contents = bfd_zalloc (ibfd, s->size); if (s->contents == NULL) return FALSE; relocs = TRUE; s->reloc_count = 0; } } } if (htab->elf.dynamic_sections_created) { /* Add some entries to the .dynamic section. We fill in the values later, in ppc64_elf_finish_dynamic_sections, but we must add the entries now so that we get the correct size for the .dynamic section. The DT_DEBUG entry is filled in by the dynamic linker and used by the debugger. */ #define add_dynamic_entry(TAG, VAL) \ _bfd_elf_add_dynamic_entry (info, TAG, VAL) if (info->executable) { if (!add_dynamic_entry (DT_DEBUG, 0)) return FALSE; } if (htab->plt != NULL && htab->plt->size != 0) { if (!add_dynamic_entry (DT_PLTGOT, 0) || !add_dynamic_entry (DT_PLTRELSZ, 0) || !add_dynamic_entry (DT_PLTREL, DT_RELA) || !add_dynamic_entry (DT_JMPREL, 0) || !add_dynamic_entry (DT_PPC64_GLINK, 0)) return FALSE; } if (NO_OPD_RELOCS) { if (!add_dynamic_entry (DT_PPC64_OPD, 0) || !add_dynamic_entry (DT_PPC64_OPDSZ, 0)) return FALSE; } if (relocs) { if (!add_dynamic_entry (DT_RELA, 0) || !add_dynamic_entry (DT_RELASZ, 0) || !add_dynamic_entry (DT_RELAENT, sizeof (Elf64_External_Rela))) return FALSE; /* If any dynamic relocs apply to a read-only section, then we need a DT_TEXTREL entry. */ if ((info->flags & DF_TEXTREL) == 0) elf_link_hash_traverse (&htab->elf, readonly_dynrelocs, info); if ((info->flags & DF_TEXTREL) != 0) { if (!add_dynamic_entry (DT_TEXTREL, 0)) return FALSE; } } } #undef add_dynamic_entry return TRUE; } /* Determine the type of stub needed, if any, for a call. */ static inline enum ppc_stub_type ppc_type_of_stub (asection *input_sec, const Elf_Internal_Rela *rel, struct ppc_link_hash_entry **hash, bfd_vma destination) { struct ppc_link_hash_entry *h = *hash; bfd_vma location; bfd_vma branch_offset; bfd_vma max_branch_offset; enum elf_ppc64_reloc_type r_type; if (h != NULL) { struct ppc_link_hash_entry *fdh = h; if (fdh->oh != NULL && fdh->oh->is_func_descriptor) fdh = fdh->oh; if (fdh->elf.dynindx != -1) { struct plt_entry *ent; for (ent = fdh->elf.plt.plist; ent != NULL; ent = ent->next) if (ent->addend == rel->r_addend && ent->plt.offset != (bfd_vma) -1) { *hash = fdh; return ppc_stub_plt_call; } } /* Here, we know we don't have a plt entry. If we don't have a either a defined function descriptor or a defined entry symbol in a regular object file, then it is pointless trying to make any other type of stub. */ if (!((fdh->elf.root.type == bfd_link_hash_defined || fdh->elf.root.type == bfd_link_hash_defweak) && fdh->elf.root.u.def.section->output_section != NULL) && !((h->elf.root.type == bfd_link_hash_defined || h->elf.root.type == bfd_link_hash_defweak) && h->elf.root.u.def.section->output_section != NULL)) return ppc_stub_none; } /* Determine where the call point is. */ location = (input_sec->output_offset + input_sec->output_section->vma + rel->r_offset); branch_offset = destination - location; r_type = ELF64_R_TYPE (rel->r_info); /* Determine if a long branch stub is needed. */ max_branch_offset = 1 << 25; if (r_type != R_PPC64_REL24) max_branch_offset = 1 << 15; if (branch_offset + max_branch_offset >= 2 * max_branch_offset) /* We need a stub. Figure out whether a long_branch or plt_branch is needed later. */ return ppc_stub_long_branch; return ppc_stub_none; } /* Build a .plt call stub. */ static inline bfd_byte * build_plt_stub (bfd *obfd, bfd_byte *p, int offset) { #define PPC_LO(v) ((v) & 0xffff) #define PPC_HI(v) (((v) >> 16) & 0xffff) #define PPC_HA(v) PPC_HI ((v) + 0x8000) - bfd_put_32 (obfd, ADDIS_R12_R2 | PPC_HA (offset), p), p += 4; - bfd_put_32 (obfd, STD_R2_40R1, p), p += 4; - bfd_put_32 (obfd, LD_R11_0R12 | PPC_LO (offset), p), p += 4; - if (PPC_HA (offset + 8) != PPC_HA (offset)) - bfd_put_32 (obfd, ADDIS_R12_R12 | 1, p), p += 4; - offset += 8; - bfd_put_32 (obfd, LD_R2_0R12 | PPC_LO (offset), p), p += 4; - if (PPC_HA (offset + 8) != PPC_HA (offset)) - bfd_put_32 (obfd, ADDIS_R12_R12 | 1, p), p += 4; - offset += 8; - bfd_put_32 (obfd, MTCTR_R11, p), p += 4; - bfd_put_32 (obfd, LD_R11_0R12 | PPC_LO (offset), p), p += 4; - bfd_put_32 (obfd, BCTR, p), p += 4; + if (PPC_HA (offset) != 0) + { + bfd_put_32 (obfd, ADDIS_R12_R2 | PPC_HA (offset), p), p += 4; + bfd_put_32 (obfd, STD_R2_40R1, p), p += 4; + bfd_put_32 (obfd, LD_R11_0R12 | PPC_LO (offset), p), p += 4; + if (PPC_HA (offset + 16) != PPC_HA (offset)) + { + bfd_put_32 (obfd, ADDI_R12_R12 | PPC_LO (offset), p), p += 4; + offset = 0; + } + bfd_put_32 (obfd, MTCTR_R11, p), p += 4; + bfd_put_32 (obfd, LD_R2_0R12 | PPC_LO (offset + 8), p), p += 4; + bfd_put_32 (obfd, LD_R11_0R12 | PPC_LO (offset + 16), p), p += 4; + bfd_put_32 (obfd, BCTR, p), p += 4; + } + else + { + bfd_put_32 (obfd, STD_R2_40R1, p), p += 4; + bfd_put_32 (obfd, LD_R11_0R2 | PPC_LO (offset), p), p += 4; + if (PPC_HA (offset + 16) != PPC_HA (offset)) + { + bfd_put_32 (obfd, ADDI_R2_R2 | PPC_LO (offset), p), p += 4; + offset = 0; + } + bfd_put_32 (obfd, MTCTR_R11, p), p += 4; + bfd_put_32 (obfd, LD_R11_0R2 | PPC_LO (offset + 16), p), p += 4; + bfd_put_32 (obfd, LD_R2_0R2 | PPC_LO (offset + 8), p), p += 4; + bfd_put_32 (obfd, BCTR, p), p += 4; + } return p; } static bfd_boolean ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) { struct ppc_stub_hash_entry *stub_entry; struct ppc_branch_hash_entry *br_entry; struct bfd_link_info *info; struct ppc_link_hash_table *htab; bfd_byte *loc; bfd_byte *p; unsigned int indx; struct plt_entry *ent; bfd_vma dest, off; int size; /* Massage our args to the form they really have. */ stub_entry = (struct ppc_stub_hash_entry *) gen_entry; info = in_arg; htab = ppc_hash_table (info); /* Make a note of the offset within the stubs for this entry. */ stub_entry->stub_offset = stub_entry->stub_sec->size; loc = stub_entry->stub_sec->contents + stub_entry->stub_offset; htab->stub_count[stub_entry->stub_type - 1] += 1; switch (stub_entry->stub_type) { case ppc_stub_long_branch: case ppc_stub_long_branch_r2off: /* Branches are relative. This is where we are going to. */ off = dest = (stub_entry->target_value + stub_entry->target_section->output_offset + stub_entry->target_section->output_section->vma); /* And this is where we are coming from. */ off -= (stub_entry->stub_offset + stub_entry->stub_sec->output_offset + stub_entry->stub_sec->output_section->vma); - if (stub_entry->stub_type != ppc_stub_long_branch_r2off) - size = 4; - else + size = 4; + if (stub_entry->stub_type == ppc_stub_long_branch_r2off) { bfd_vma r2off; r2off = (htab->stub_group[stub_entry->target_section->id].toc_off - htab->stub_group[stub_entry->id_sec->id].toc_off); bfd_put_32 (htab->stub_bfd, STD_R2_40R1, loc); loc += 4; - bfd_put_32 (htab->stub_bfd, ADDIS_R2_R2 | PPC_HA (r2off), loc); - loc += 4; + size = 12; + if (PPC_HA (r2off) != 0) + { + size = 16; + bfd_put_32 (htab->stub_bfd, ADDIS_R2_R2 | PPC_HA (r2off), loc); + loc += 4; + } bfd_put_32 (htab->stub_bfd, ADDI_R2_R2 | PPC_LO (r2off), loc); loc += 4; - off -= 12; - size = 16; + off -= size - 4; } bfd_put_32 (htab->stub_bfd, B_DOT | (off & 0x3fffffc), loc); if (off + (1 << 25) >= (bfd_vma) (1 << 26)) { (*_bfd_error_handler) (_("long branch stub `%s' offset overflow"), stub_entry->root.string); htab->stub_error = TRUE; return FALSE; } if (info->emitrelocations) { Elf_Internal_Rela *relocs, *r; struct bfd_elf_section_data *elfsec_data; elfsec_data = elf_section_data (stub_entry->stub_sec); relocs = elfsec_data->relocs; if (relocs == NULL) { bfd_size_type relsize; relsize = stub_entry->stub_sec->reloc_count * sizeof (*relocs); relocs = bfd_alloc (htab->stub_bfd, relsize); if (relocs == NULL) return FALSE; elfsec_data->relocs = relocs; elfsec_data->rel_hdr.sh_size = relsize; elfsec_data->rel_hdr.sh_entsize = 24; stub_entry->stub_sec->reloc_count = 0; } r = relocs + stub_entry->stub_sec->reloc_count; stub_entry->stub_sec->reloc_count += 1; r->r_offset = loc - stub_entry->stub_sec->contents; r->r_info = ELF64_R_INFO (0, R_PPC64_REL24); r->r_addend = dest; if (stub_entry->h != NULL) { struct elf_link_hash_entry **hashes; unsigned long symndx; struct ppc_link_hash_entry *h; hashes = elf_sym_hashes (htab->stub_bfd); if (hashes == NULL) { bfd_size_type hsize; hsize = (htab->stub_globals + 1) * sizeof (*hashes); hashes = bfd_zalloc (htab->stub_bfd, hsize); if (hashes == NULL) return FALSE; elf_sym_hashes (htab->stub_bfd) = hashes; htab->stub_globals = 1; } symndx = htab->stub_globals++; h = stub_entry->h; hashes[symndx] = &h->elf; r->r_info = ELF64_R_INFO (symndx, R_PPC64_REL24); if (h->oh != NULL && h->oh->is_func) h = h->oh; if (h->elf.root.u.def.section != stub_entry->target_section) /* H is an opd symbol. The addend must be zero. */ r->r_addend = 0; else { off = (h->elf.root.u.def.value + h->elf.root.u.def.section->output_offset + h->elf.root.u.def.section->output_section->vma); r->r_addend -= off; } } } break; case ppc_stub_plt_branch: case ppc_stub_plt_branch_r2off: br_entry = ppc_branch_hash_lookup (&htab->branch_hash_table, stub_entry->root.string + 9, FALSE, FALSE); if (br_entry == NULL) { (*_bfd_error_handler) (_("can't find branch stub `%s'"), stub_entry->root.string); htab->stub_error = TRUE; return FALSE; } off = (stub_entry->target_value + stub_entry->target_section->output_offset + stub_entry->target_section->output_section->vma); bfd_put_64 (htab->brlt->owner, off, htab->brlt->contents + br_entry->offset); if (htab->relbrlt != NULL) { /* Create a reloc for the branch lookup table entry. */ Elf_Internal_Rela rela; bfd_byte *rl; rela.r_offset = (br_entry->offset + htab->brlt->output_offset + htab->brlt->output_section->vma); rela.r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE); rela.r_addend = off; rl = htab->relbrlt->contents; rl += htab->relbrlt->reloc_count++ * sizeof (Elf64_External_Rela); bfd_elf64_swap_reloca_out (htab->relbrlt->owner, &rela, rl); } else if (info->emitrelocations) { Elf_Internal_Rela *relocs, *r; struct bfd_elf_section_data *elfsec_data; elfsec_data = elf_section_data (htab->brlt); relocs = elfsec_data->relocs; if (relocs == NULL) { bfd_size_type relsize; relsize = htab->brlt->reloc_count * sizeof (*relocs); relocs = bfd_alloc (htab->brlt->owner, relsize); if (relocs == NULL) return FALSE; elfsec_data->relocs = relocs; elfsec_data->rel_hdr.sh_size = relsize; elfsec_data->rel_hdr.sh_entsize = 24; htab->brlt->reloc_count = 0; } r = relocs + htab->brlt->reloc_count; htab->brlt->reloc_count += 1; r->r_offset = (br_entry->offset + htab->brlt->output_offset + htab->brlt->output_section->vma); r->r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE); r->r_addend = off; } off = (br_entry->offset + htab->brlt->output_offset + htab->brlt->output_section->vma - elf_gp (htab->brlt->output_section->owner) - htab->stub_group[stub_entry->id_sec->id].toc_off); if (off + 0x80008000 > 0xffffffff || (off & 7) != 0) { (*_bfd_error_handler) (_("linkage table error against `%s'"), stub_entry->root.string); bfd_set_error (bfd_error_bad_value); htab->stub_error = TRUE; return FALSE; } indx = off; if (stub_entry->stub_type != ppc_stub_plt_branch_r2off) { - bfd_put_32 (htab->stub_bfd, ADDIS_R12_R2 | PPC_HA (indx), loc); - loc += 4; - bfd_put_32 (htab->stub_bfd, LD_R11_0R12 | PPC_LO (indx), loc); - size = 16; + if (PPC_HA (indx) != 0) + { + size = 16; + bfd_put_32 (htab->stub_bfd, ADDIS_R12_R2 | PPC_HA (indx), loc); + loc += 4; + bfd_put_32 (htab->stub_bfd, LD_R11_0R12 | PPC_LO (indx), loc); + } + else + { + size = 12; + bfd_put_32 (htab->stub_bfd, LD_R11_0R2 | PPC_LO (indx), loc); + } } else { bfd_vma r2off; r2off = (htab->stub_group[stub_entry->target_section->id].toc_off - htab->stub_group[stub_entry->id_sec->id].toc_off); bfd_put_32 (htab->stub_bfd, STD_R2_40R1, loc); loc += 4; - bfd_put_32 (htab->stub_bfd, ADDIS_R12_R2 | PPC_HA (indx), loc); - loc += 4; - bfd_put_32 (htab->stub_bfd, LD_R11_0R12 | PPC_LO (indx), loc); - loc += 4; - bfd_put_32 (htab->stub_bfd, ADDIS_R2_R2 | PPC_HA (r2off), loc); - loc += 4; + size = 20; + if (PPC_HA (indx) != 0) + { + size += 4; + bfd_put_32 (htab->stub_bfd, ADDIS_R12_R2 | PPC_HA (indx), loc); + loc += 4; + bfd_put_32 (htab->stub_bfd, LD_R11_0R12 | PPC_LO (indx), loc); + loc += 4; + } + else + { + bfd_put_32 (htab->stub_bfd, LD_R11_0R2 | PPC_LO (indx), loc); + loc += 4; + } + + if (PPC_HA (r2off) != 0) + { + size += 4; + bfd_put_32 (htab->stub_bfd, ADDIS_R2_R2 | PPC_HA (r2off), loc); + loc += 4; + } bfd_put_32 (htab->stub_bfd, ADDI_R2_R2 | PPC_LO (r2off), loc); - size = 28; } loc += 4; bfd_put_32 (htab->stub_bfd, MTCTR_R11, loc); loc += 4; bfd_put_32 (htab->stub_bfd, BCTR, loc); break; case ppc_stub_plt_call: /* Do the best we can for shared libraries built without exporting ".foo" for each "foo". This can happen when symbol versioning scripts strip all bar a subset of symbols. */ if (stub_entry->h->oh != NULL && stub_entry->h->oh->elf.root.type != bfd_link_hash_defined && stub_entry->h->oh->elf.root.type != bfd_link_hash_defweak) { /* Point the symbol at the stub. There may be multiple stubs, we don't really care; The main thing is to make this sym defined somewhere. Maybe defining the symbol in the stub section is a silly idea. If we didn't do this, htab->top_id could disappear. */ stub_entry->h->oh->elf.root.type = bfd_link_hash_defined; stub_entry->h->oh->elf.root.u.def.section = stub_entry->stub_sec; stub_entry->h->oh->elf.root.u.def.value = stub_entry->stub_offset; } /* Now build the stub. */ off = (bfd_vma) -1; for (ent = stub_entry->h->elf.plt.plist; ent != NULL; ent = ent->next) if (ent->addend == stub_entry->addend) { off = ent->plt.offset; break; } if (off >= (bfd_vma) -2) abort (); off &= ~ (bfd_vma) 1; off += (htab->plt->output_offset + htab->plt->output_section->vma - elf_gp (htab->plt->output_section->owner) - htab->stub_group[stub_entry->id_sec->id].toc_off); if (off + 0x80008000 > 0xffffffff || (off & 7) != 0) { (*_bfd_error_handler) (_("linkage table error against `%s'"), stub_entry->h->elf.root.root.string); bfd_set_error (bfd_error_bad_value); htab->stub_error = TRUE; return FALSE; } p = build_plt_stub (htab->stub_bfd, loc, off); size = p - loc; break; default: BFD_FAIL (); return FALSE; } stub_entry->stub_sec->size += size; if (htab->emit_stub_syms) { struct elf_link_hash_entry *h; size_t len1, len2; char *name; const char *const stub_str[] = { "long_branch", "long_branch_r2off", "plt_branch", "plt_branch_r2off", "plt_call" }; len1 = strlen (stub_str[stub_entry->stub_type - 1]); len2 = strlen (stub_entry->root.string); name = bfd_malloc (len1 + len2 + 2); if (name == NULL) return FALSE; memcpy (name, stub_entry->root.string, 9); memcpy (name + 9, stub_str[stub_entry->stub_type - 1], len1); memcpy (name + len1 + 9, stub_entry->root.string + 8, len2 - 8 + 1); h = elf_link_hash_lookup (&htab->elf, name, TRUE, FALSE, FALSE); if (h == NULL) return FALSE; if (h->root.type == bfd_link_hash_new) { h->root.type = bfd_link_hash_defined; h->root.u.def.section = stub_entry->stub_sec; h->root.u.def.value = stub_entry->stub_offset; h->ref_regular = 1; h->def_regular = 1; h->ref_regular_nonweak = 1; h->forced_local = 1; h->non_elf = 0; } } return TRUE; } /* As above, but don't actually build the stub. Just bump offset so we know stub section sizes, and select plt_branch stubs where long_branch stubs won't do. */ static bfd_boolean ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) { struct ppc_stub_hash_entry *stub_entry; struct bfd_link_info *info; struct ppc_link_hash_table *htab; bfd_vma off; int size; /* Massage our args to the form they really have. */ stub_entry = (struct ppc_stub_hash_entry *) gen_entry; info = in_arg; htab = ppc_hash_table (info); if (stub_entry->stub_type == ppc_stub_plt_call) { struct plt_entry *ent; off = (bfd_vma) -1; for (ent = stub_entry->h->elf.plt.plist; ent != NULL; ent = ent->next) if (ent->addend == stub_entry->addend) { off = ent->plt.offset & ~(bfd_vma) 1; break; } if (off >= (bfd_vma) -2) abort (); off += (htab->plt->output_offset + htab->plt->output_section->vma - elf_gp (htab->plt->output_section->owner) - htab->stub_group[stub_entry->id_sec->id].toc_off); size = PLT_CALL_STUB_SIZE; + if (PPC_HA (off) == 0) + size -= 4; if (PPC_HA (off + 16) != PPC_HA (off)) size += 4; } else { /* ppc_stub_long_branch or ppc_stub_plt_branch, or their r2off variants. */ + bfd_vma r2off = 0; + off = (stub_entry->target_value + stub_entry->target_section->output_offset + stub_entry->target_section->output_section->vma); off -= (stub_entry->stub_sec->size + stub_entry->stub_sec->output_offset + stub_entry->stub_sec->output_section->vma); /* Reset the stub type from the plt variant in case we now can reach with a shorter stub. */ if (stub_entry->stub_type >= ppc_stub_plt_branch) stub_entry->stub_type += ppc_stub_long_branch - ppc_stub_plt_branch; size = 4; if (stub_entry->stub_type == ppc_stub_long_branch_r2off) { - off -= 12; - size = 16; + r2off = (htab->stub_group[stub_entry->target_section->id].toc_off + - htab->stub_group[stub_entry->id_sec->id].toc_off); + size = 12; + if (PPC_HA (r2off) != 0) + size = 16; + off -= size - 4; } /* If the branch offset if too big, use a ppc_stub_plt_branch. */ if (off + (1 << 25) >= (bfd_vma) (1 << 26)) { struct ppc_branch_hash_entry *br_entry; + unsigned int indx; br_entry = ppc_branch_hash_lookup (&htab->branch_hash_table, stub_entry->root.string + 9, TRUE, FALSE); if (br_entry == NULL) { (*_bfd_error_handler) (_("can't build branch stub `%s'"), stub_entry->root.string); htab->stub_error = TRUE; return FALSE; } if (br_entry->iter != htab->stub_iteration) { br_entry->iter = htab->stub_iteration; br_entry->offset = htab->brlt->size; htab->brlt->size += 8; if (htab->relbrlt != NULL) htab->relbrlt->size += sizeof (Elf64_External_Rela); else if (info->emitrelocations) { htab->brlt->reloc_count += 1; htab->brlt->flags |= SEC_RELOC; } } stub_entry->stub_type += ppc_stub_plt_branch - ppc_stub_long_branch; - size = 16; - if (stub_entry->stub_type != ppc_stub_plt_branch) - size = 28; + off = (br_entry->offset + + htab->brlt->output_offset + + htab->brlt->output_section->vma + - elf_gp (htab->brlt->output_section->owner) + - htab->stub_group[stub_entry->id_sec->id].toc_off); + + indx = off; + if (stub_entry->stub_type != ppc_stub_plt_branch_r2off) + { + size = 12; + if (PPC_HA (indx) != 0) + size = 16; + } + else + { + size = 20; + if (PPC_HA (indx) != 0) + size += 4; + + if (PPC_HA (r2off) != 0) + size += 4; + } } else if (info->emitrelocations) { stub_entry->stub_sec->reloc_count += 1; stub_entry->stub_sec->flags |= SEC_RELOC; } } stub_entry->stub_sec->size += size; return TRUE; } /* Set up various things so that we can make a list of input sections for each output section included in the link. Returns -1 on error, 0 when no stubs will be needed, and 1 on success. */ int ppc64_elf_setup_section_lists (bfd *output_bfd, struct bfd_link_info *info, int no_multi_toc) { bfd *input_bfd; int top_id, top_index, id; asection *section; asection **input_list; bfd_size_type amt; struct ppc_link_hash_table *htab = ppc_hash_table (info); htab->no_multi_toc = no_multi_toc; if (htab->brlt == NULL) return 0; /* Find the top input section id. */ for (input_bfd = info->input_bfds, top_id = 3; input_bfd != NULL; input_bfd = input_bfd->link_next) { for (section = input_bfd->sections; section != NULL; section = section->next) { if (top_id < section->id) top_id = section->id; } } htab->top_id = top_id; amt = sizeof (struct map_stub) * (top_id + 1); htab->stub_group = bfd_zmalloc (amt); if (htab->stub_group == NULL) return -1; /* Set toc_off for com, und, abs and ind sections. */ for (id = 0; id < 3; id++) htab->stub_group[id].toc_off = TOC_BASE_OFF; elf_gp (output_bfd) = htab->toc_curr = ppc64_elf_toc (output_bfd); /* We can't use output_bfd->section_count here to find the top output section index as some sections may have been removed, and strip_excluded_output_sections doesn't renumber the indices. */ for (section = output_bfd->sections, top_index = 0; section != NULL; section = section->next) { if (top_index < section->index) top_index = section->index; } htab->top_index = top_index; amt = sizeof (asection *) * (top_index + 1); input_list = bfd_zmalloc (amt); htab->input_list = input_list; if (input_list == NULL) return -1; return 1; } /* The linker repeatedly calls this function for each TOC input section and linker generated GOT section. Group input bfds such that the toc within a group is less than 64k in size. Will break with cute linker scripts that play games with dot in the output toc section. */ void ppc64_elf_next_toc_section (struct bfd_link_info *info, asection *isec) { struct ppc_link_hash_table *htab = ppc_hash_table (info); if (!htab->no_multi_toc) { bfd_vma addr = isec->output_offset + isec->output_section->vma; bfd_vma off = addr - htab->toc_curr; if (off + isec->size > 0x10000) htab->toc_curr = addr; elf_gp (isec->owner) = (htab->toc_curr - elf_gp (isec->output_section->owner) + TOC_BASE_OFF); } } /* Called after the last call to the above function. */ void ppc64_elf_reinit_toc (bfd *output_bfd, struct bfd_link_info *info) { struct ppc_link_hash_table *htab = ppc_hash_table (info); htab->multi_toc_needed = htab->toc_curr != elf_gp (output_bfd); /* toc_curr tracks the TOC offset used for code sections below in ppc64_elf_next_input_section. Start off at 0x8000. */ htab->toc_curr = TOC_BASE_OFF; } /* No toc references were found in ISEC. If the code in ISEC makes no calls, then there's no need to use toc adjusting stubs when branching into ISEC. Actually, indirect calls from ISEC are OK as they will load r2. Returns -1 on error, 0 for no stub needed, 1 for stub needed, and 2 if a cyclical call-graph was found but no other reason for a stub was detected. If called from the top level, a return of 2 means the same as a return of 0. */ static int toc_adjusting_stub_needed (struct bfd_link_info *info, asection *isec) { Elf_Internal_Rela *relstart, *rel; Elf_Internal_Sym *local_syms; int ret; struct ppc_link_hash_table *htab; /* We know none of our code bearing sections will need toc stubs. */ if ((isec->flags & SEC_LINKER_CREATED) != 0) return 0; if (isec->size == 0) return 0; if (isec->output_section == NULL) return 0; /* Hack for linux kernel. .fixup contains branches, but only back to the function that hit an exception. */ if (strcmp (isec->name, ".fixup") == 0) return 0; if (isec->reloc_count == 0) return 0; relstart = _bfd_elf_link_read_relocs (isec->owner, isec, NULL, NULL, info->keep_memory); if (relstart == NULL) return -1; /* Look for branches to outside of this section. */ local_syms = NULL; ret = 0; htab = ppc_hash_table (info); for (rel = relstart; rel < relstart + isec->reloc_count; ++rel) { enum elf_ppc64_reloc_type r_type; unsigned long r_symndx; struct elf_link_hash_entry *h; + struct ppc_link_hash_entry *eh; Elf_Internal_Sym *sym; asection *sym_sec; long *opd_adjust; bfd_vma sym_value; bfd_vma dest; r_type = ELF64_R_TYPE (rel->r_info); if (r_type != R_PPC64_REL24 && r_type != R_PPC64_REL14 && r_type != R_PPC64_REL14_BRTAKEN && r_type != R_PPC64_REL14_BRNTAKEN) continue; r_symndx = ELF64_R_SYM (rel->r_info); if (!get_sym_h (&h, &sym, &sym_sec, NULL, &local_syms, r_symndx, isec->owner)) { ret = -1; break; } /* Calls to dynamic lib functions go through a plt call stub - that uses r2. Branches to undefined symbols might be a call - using old-style dot symbols that can be satisfied by a plt - call into a new-style dynamic library. */ - if (sym_sec == NULL) + that uses r2. */ + eh = (struct ppc_link_hash_entry *) h; + if (eh != NULL + && (eh->elf.plt.plist != NULL + || (eh->oh != NULL + && eh->oh->elf.plt.plist != NULL))) { - struct ppc_link_hash_entry *eh = (struct ppc_link_hash_entry *) h; - if (eh != NULL - && eh->oh != NULL - && eh->oh->elf.plt.plist != NULL) - { - ret = 1; - break; - } - - /* Ignore other undefined symbols. */ - continue; + ret = 1; + break; } + if (sym_sec == NULL) + /* Ignore other undefined symbols. */ + continue; + /* Assume branches to other sections not included in the link need stubs too, to cover -R and absolute syms. */ if (sym_sec->output_section == NULL) { ret = 1; break; } if (h == NULL) sym_value = sym->st_value; else { if (h->root.type != bfd_link_hash_defined && h->root.type != bfd_link_hash_defweak) abort (); sym_value = h->root.u.def.value; } sym_value += rel->r_addend; /* If this branch reloc uses an opd sym, find the code section. */ opd_adjust = get_opd_info (sym_sec); if (opd_adjust != NULL) { if (h == NULL) { long adjust; adjust = opd_adjust[sym->st_value / 8]; if (adjust == -1) /* Assume deleted functions won't ever be called. */ continue; sym_value += adjust; } dest = opd_entry_value (sym_sec, sym_value, &sym_sec, NULL); if (dest == (bfd_vma) -1) continue; } else dest = (sym_value + sym_sec->output_offset + sym_sec->output_section->vma); /* Ignore branch to self. */ if (sym_sec == isec) continue; /* If the called function uses the toc, we need a stub. */ if (sym_sec->has_toc_reloc || sym_sec->makes_toc_func_call) { ret = 1; break; } /* Assume any branch that needs a long branch stub might in fact need a plt_branch stub. A plt_branch stub uses r2. */ else if (dest - (isec->output_offset + isec->output_section->vma + rel->r_offset) + (1 << 25) >= (2 << 25)) { ret = 1; break; } /* If calling back to a section in the process of being tested, we can't say for sure that no toc adjusting stubs are needed, so don't return zero. */ else if (sym_sec->call_check_in_progress) ret = 2; /* Branches to another section that itself doesn't have any TOC references are OK. Recursively call ourselves to check. */ else if (sym_sec->id <= htab->top_id && htab->stub_group[sym_sec->id].toc_off == 0) { int recur; /* Mark current section as indeterminate, so that other sections that call back to current won't be marked as known. */ isec->call_check_in_progress = 1; recur = toc_adjusting_stub_needed (info, sym_sec); isec->call_check_in_progress = 0; if (recur < 0) { /* An error. Exit. */ ret = -1; break; } else if (recur <= 1) { /* Known result. Mark as checked and set section flag. */ htab->stub_group[sym_sec->id].toc_off = 1; if (recur != 0) { sym_sec->makes_toc_func_call = 1; ret = 1; break; } } else { /* Unknown result. Continue checking. */ ret = 2; } } } if (local_syms != NULL && (elf_tdata (isec->owner)->symtab_hdr.contents != (unsigned char *) local_syms)) free (local_syms); if (elf_section_data (isec)->relocs != relstart) free (relstart); return ret; } /* The linker repeatedly calls this function for each input section, in the order that input sections are linked into output sections. Build lists of input sections to determine groupings between which we may insert linker stubs. */ bfd_boolean ppc64_elf_next_input_section (struct bfd_link_info *info, asection *isec) { struct ppc_link_hash_table *htab = ppc_hash_table (info); if ((isec->output_section->flags & SEC_CODE) != 0 && isec->output_section->index <= htab->top_index) { asection **list = htab->input_list + isec->output_section->index; /* Steal the link_sec pointer for our list. */ #define PREV_SEC(sec) (htab->stub_group[(sec)->id].link_sec) /* This happens to make the list in reverse order, which is what we want. */ PREV_SEC (isec) = *list; *list = isec; } if (htab->multi_toc_needed) { /* If a code section has a function that uses the TOC then we need to use the right TOC (obviously). Also, make sure that .opd gets the correct TOC value for R_PPC64_TOC relocs that don't have or can't find their function symbol (shouldn't ever happen now). */ if (isec->has_toc_reloc || (isec->flags & SEC_CODE) == 0) { if (elf_gp (isec->owner) != 0) htab->toc_curr = elf_gp (isec->owner); } else if (htab->stub_group[isec->id].toc_off == 0) { int ret = toc_adjusting_stub_needed (info, isec); if (ret < 0) return FALSE; else isec->makes_toc_func_call = ret & 1; } } /* Functions that don't use the TOC can belong in any TOC group. Use the last TOC base. This happens to make _init and _fini pasting work. */ htab->stub_group[isec->id].toc_off = htab->toc_curr; return TRUE; } /* See whether we can group stub sections together. Grouping stub sections may result in fewer stubs. More importantly, we need to put all .init* and .fini* stubs at the beginning of the .init or .fini output sections respectively, because glibc splits the _init and _fini functions into multiple parts. Putting a stub in the middle of a function is not a good idea. */ static void group_sections (struct ppc_link_hash_table *htab, bfd_size_type stub_group_size, bfd_boolean stubs_always_before_branch) { asection **list; bfd_size_type stub14_group_size; bfd_boolean suppress_size_errors; suppress_size_errors = FALSE; stub14_group_size = stub_group_size; if (stub_group_size == 1) { /* Default values. */ if (stubs_always_before_branch) { stub_group_size = 0x1e00000; stub14_group_size = 0x7800; } else { stub_group_size = 0x1c00000; stub14_group_size = 0x7000; } suppress_size_errors = TRUE; } list = htab->input_list + htab->top_index; do { asection *tail = *list; while (tail != NULL) { asection *curr; asection *prev; bfd_size_type total; bfd_boolean big_sec; bfd_vma curr_toc; curr = tail; total = tail->size; big_sec = total > (ppc64_elf_section_data (tail)->has_14bit_branch ? stub14_group_size : stub_group_size); if (big_sec && !suppress_size_errors) (*_bfd_error_handler) (_("%B section %A exceeds stub group size"), tail->owner, tail); curr_toc = htab->stub_group[tail->id].toc_off; while ((prev = PREV_SEC (curr)) != NULL && ((total += curr->output_offset - prev->output_offset) < (ppc64_elf_section_data (prev)->has_14bit_branch ? stub14_group_size : stub_group_size)) && htab->stub_group[prev->id].toc_off == curr_toc) curr = prev; /* OK, the size from the start of CURR to the end is less than stub_group_size and thus can be handled by one stub section. (or the tail section is itself larger than stub_group_size, in which case we may be toast.) We should really be keeping track of the total size of stubs added here, as stubs contribute to the final output section size. That's a little tricky, and this way will only break if stubs added make the total size more than 2^25, ie. for the default stub_group_size, if stubs total more than 2097152 bytes, or nearly 75000 plt call stubs. */ do { prev = PREV_SEC (tail); /* Set up this stub group. */ htab->stub_group[tail->id].link_sec = curr; } while (tail != curr && (tail = prev) != NULL); /* But wait, there's more! Input sections up to stub_group_size bytes before the stub section can be handled by it too. Don't do this if we have a really large section after the stubs, as adding more stubs increases the chance that branches may not reach into the stub section. */ if (!stubs_always_before_branch && !big_sec) { total = 0; while (prev != NULL && ((total += tail->output_offset - prev->output_offset) < (ppc64_elf_section_data (prev)->has_14bit_branch ? stub14_group_size : stub_group_size)) && htab->stub_group[prev->id].toc_off == curr_toc) { tail = prev; prev = PREV_SEC (tail); htab->stub_group[tail->id].link_sec = curr; } } tail = prev; } } while (list-- != htab->input_list); free (htab->input_list); #undef PREV_SEC } /* Determine and set the size of the stub section for a final link. The basic idea here is to examine all the relocations looking for PC-relative calls to a target that is unreachable with a "bl" instruction. */ bfd_boolean ppc64_elf_size_stubs (bfd *output_bfd, struct bfd_link_info *info, bfd_signed_vma group_size, asection *(*add_stub_section) (const char *, asection *), void (*layout_sections_again) (void)) { bfd_size_type stub_group_size; bfd_boolean stubs_always_before_branch; struct ppc_link_hash_table *htab = ppc_hash_table (info); /* Stash our params away. */ htab->add_stub_section = add_stub_section; htab->layout_sections_again = layout_sections_again; stubs_always_before_branch = group_size < 0; if (group_size < 0) stub_group_size = -group_size; else stub_group_size = group_size; group_sections (htab, stub_group_size, stubs_always_before_branch); while (1) { bfd *input_bfd; unsigned int bfd_indx; asection *stub_sec; htab->stub_iteration += 1; for (input_bfd = info->input_bfds, bfd_indx = 0; input_bfd != NULL; input_bfd = input_bfd->link_next, bfd_indx++) { Elf_Internal_Shdr *symtab_hdr; asection *section; Elf_Internal_Sym *local_syms = NULL; if (!is_ppc64_elf_target (input_bfd->xvec)) continue; /* We'll need the symbol table in a second. */ symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; if (symtab_hdr->sh_info == 0) continue; /* Walk over each section attached to the input bfd. */ for (section = input_bfd->sections; section != NULL; section = section->next) { Elf_Internal_Rela *internal_relocs, *irelaend, *irela; /* If there aren't any relocs, then there's nothing more to do. */ if ((section->flags & SEC_RELOC) == 0 || (section->flags & SEC_ALLOC) == 0 || (section->flags & SEC_LOAD) == 0 || (section->flags & SEC_CODE) == 0 || section->reloc_count == 0) continue; /* If this section is a link-once section that will be discarded, then don't create any stubs. */ if (section->output_section == NULL || section->output_section->owner != output_bfd) continue; /* Get the relocs. */ internal_relocs = _bfd_elf_link_read_relocs (input_bfd, section, NULL, NULL, info->keep_memory); if (internal_relocs == NULL) goto error_ret_free_local; /* Now examine each relocation. */ irela = internal_relocs; irelaend = irela + section->reloc_count; for (; irela < irelaend; irela++) { enum elf_ppc64_reloc_type r_type; unsigned int r_indx; enum ppc_stub_type stub_type; struct ppc_stub_hash_entry *stub_entry; asection *sym_sec, *code_sec; bfd_vma sym_value; bfd_vma destination; bfd_boolean ok_dest; struct ppc_link_hash_entry *hash; struct ppc_link_hash_entry *fdh; struct elf_link_hash_entry *h; Elf_Internal_Sym *sym; char *stub_name; const asection *id_sec; long *opd_adjust; r_type = ELF64_R_TYPE (irela->r_info); r_indx = ELF64_R_SYM (irela->r_info); if (r_type >= R_PPC64_max) { bfd_set_error (bfd_error_bad_value); goto error_ret_free_internal; } /* Only look for stubs on branch instructions. */ if (r_type != R_PPC64_REL24 && r_type != R_PPC64_REL14 && r_type != R_PPC64_REL14_BRTAKEN && r_type != R_PPC64_REL14_BRNTAKEN) continue; /* Now determine the call target, its name, value, section. */ if (!get_sym_h (&h, &sym, &sym_sec, NULL, &local_syms, r_indx, input_bfd)) goto error_ret_free_internal; hash = (struct ppc_link_hash_entry *) h; ok_dest = FALSE; fdh = NULL; sym_value = 0; if (hash == NULL) { sym_value = sym->st_value; ok_dest = TRUE; } else if (hash->elf.root.type == bfd_link_hash_defined || hash->elf.root.type == bfd_link_hash_defweak) { sym_value = hash->elf.root.u.def.value; if (sym_sec->output_section != NULL) ok_dest = TRUE; } else if (hash->elf.root.type == bfd_link_hash_undefweak || hash->elf.root.type == bfd_link_hash_undefined) { /* Recognise an old ABI func code entry sym, and use the func descriptor sym instead if it is defined. */ if (hash->elf.root.root.string[0] == '.' && (fdh = get_fdh (hash, htab)) != NULL) { if (fdh->elf.root.type == bfd_link_hash_defined || fdh->elf.root.type == bfd_link_hash_defweak) { sym_sec = fdh->elf.root.u.def.section; sym_value = fdh->elf.root.u.def.value; if (sym_sec->output_section != NULL) ok_dest = TRUE; } else fdh = NULL; } } else { bfd_set_error (bfd_error_bad_value); goto error_ret_free_internal; } destination = 0; if (ok_dest) { sym_value += irela->r_addend; destination = (sym_value + sym_sec->output_offset + sym_sec->output_section->vma); } code_sec = sym_sec; opd_adjust = get_opd_info (sym_sec); if (opd_adjust != NULL) { bfd_vma dest; if (hash == NULL) { long adjust = opd_adjust[sym_value / 8]; if (adjust == -1) continue; sym_value += adjust; } dest = opd_entry_value (sym_sec, sym_value, &code_sec, &sym_value); if (dest != (bfd_vma) -1) { destination = dest; if (fdh != NULL) { /* Fixup old ABI sym to point at code entry. */ hash->elf.root.type = bfd_link_hash_defweak; hash->elf.root.u.def.section = code_sec; hash->elf.root.u.def.value = sym_value; } } } /* Determine what (if any) linker stub is needed. */ stub_type = ppc_type_of_stub (section, irela, &hash, destination); if (stub_type != ppc_stub_plt_call) { /* Check whether we need a TOC adjusting stub. Since the linker pastes together pieces from different object files when creating the _init and _fini functions, it may be that a call to what looks like a local sym is in fact a call needing a TOC adjustment. */ if (code_sec != NULL && code_sec->output_section != NULL && (htab->stub_group[code_sec->id].toc_off != htab->stub_group[section->id].toc_off) && (code_sec->has_toc_reloc || code_sec->makes_toc_func_call)) stub_type = ppc_stub_long_branch_r2off; } if (stub_type == ppc_stub_none) continue; /* __tls_get_addr calls might be eliminated. */ if (stub_type != ppc_stub_plt_call && hash != NULL && (hash == htab->tls_get_addr || hash == htab->tls_get_addr_fd) && section->has_tls_reloc && irela != internal_relocs) { /* Get tls info. */ char *tls_mask; - if (!get_tls_mask (&tls_mask, NULL, &local_syms, + if (!get_tls_mask (&tls_mask, NULL, NULL, &local_syms, irela - 1, input_bfd)) goto error_ret_free_internal; if (*tls_mask != 0) continue; } /* Support for grouping stub sections. */ id_sec = htab->stub_group[section->id].link_sec; /* Get the name of this stub. */ stub_name = ppc_stub_name (id_sec, sym_sec, hash, irela); if (!stub_name) goto error_ret_free_internal; stub_entry = ppc_stub_hash_lookup (&htab->stub_hash_table, stub_name, FALSE, FALSE); if (stub_entry != NULL) { /* The proper stub has already been created. */ free (stub_name); continue; } stub_entry = ppc_add_stub (stub_name, section, htab); if (stub_entry == NULL) { free (stub_name); error_ret_free_internal: if (elf_section_data (section)->relocs == NULL) free (internal_relocs); error_ret_free_local: if (local_syms != NULL && (symtab_hdr->contents != (unsigned char *) local_syms)) free (local_syms); return FALSE; } stub_entry->stub_type = stub_type; stub_entry->target_value = sym_value; stub_entry->target_section = code_sec; stub_entry->h = hash; stub_entry->addend = irela->r_addend; if (stub_entry->h != NULL) htab->stub_globals += 1; } /* We're done with the internal relocs, free them. */ if (elf_section_data (section)->relocs != internal_relocs) free (internal_relocs); } if (local_syms != NULL && symtab_hdr->contents != (unsigned char *) local_syms) { if (!info->keep_memory) free (local_syms); else symtab_hdr->contents = (unsigned char *) local_syms; } } /* We may have added some stubs. Find out the new size of the stub sections. */ for (stub_sec = htab->stub_bfd->sections; stub_sec != NULL; stub_sec = stub_sec->next) if ((stub_sec->flags & SEC_LINKER_CREATED) == 0) { stub_sec->rawsize = stub_sec->size; stub_sec->size = 0; stub_sec->reloc_count = 0; stub_sec->flags &= ~SEC_RELOC; } htab->brlt->size = 0; htab->brlt->reloc_count = 0; htab->brlt->flags &= ~SEC_RELOC; if (htab->relbrlt != NULL) htab->relbrlt->size = 0; bfd_hash_traverse (&htab->stub_hash_table, ppc_size_one_stub, info); for (stub_sec = htab->stub_bfd->sections; stub_sec != NULL; stub_sec = stub_sec->next) if ((stub_sec->flags & SEC_LINKER_CREATED) == 0 && stub_sec->rawsize != stub_sec->size) break; /* Exit from this loop when no stubs have been added, and no stubs have changed size. */ if (stub_sec == NULL) break; /* Ask the linker to do its stuff. */ (*htab->layout_sections_again) (); } /* It would be nice to strip htab->brlt from the output if the section is empty, but it's too late. If we strip sections here, the dynamic symbol table is corrupted since the section symbol for the stripped section isn't written. */ return TRUE; } /* Called after we have determined section placement. If sections move, we'll be called again. Provide a value for TOCstart. */ bfd_vma ppc64_elf_toc (bfd *obfd) { asection *s; bfd_vma TOCstart; /* The TOC consists of sections .got, .toc, .tocbss, .plt in that order. The TOC starts where the first of these sections starts. */ s = bfd_get_section_by_name (obfd, ".got"); if (s == NULL) s = bfd_get_section_by_name (obfd, ".toc"); if (s == NULL) s = bfd_get_section_by_name (obfd, ".tocbss"); if (s == NULL) s = bfd_get_section_by_name (obfd, ".plt"); if (s == NULL) { /* This may happen for o references to TOC base (SYM@toc / TOC[tc0]) without a .toc directive o bad linker script o --gc-sections and empty TOC sections FIXME: Warn user? */ /* Look for a likely section. We probably won't even be using TOCstart. */ for (s = obfd->sections; s != NULL; s = s->next) if ((s->flags & (SEC_ALLOC | SEC_SMALL_DATA | SEC_READONLY)) == (SEC_ALLOC | SEC_SMALL_DATA)) break; if (s == NULL) for (s = obfd->sections; s != NULL; s = s->next) if ((s->flags & (SEC_ALLOC | SEC_SMALL_DATA)) == (SEC_ALLOC | SEC_SMALL_DATA)) break; if (s == NULL) for (s = obfd->sections; s != NULL; s = s->next) if ((s->flags & (SEC_ALLOC | SEC_READONLY)) == SEC_ALLOC) break; if (s == NULL) for (s = obfd->sections; s != NULL; s = s->next) if ((s->flags & SEC_ALLOC) == SEC_ALLOC) break; } TOCstart = 0; if (s != NULL) TOCstart = s->output_section->vma + s->output_offset; return TOCstart; } /* Build all the stubs associated with the current output file. The stubs are kept in a hash table attached to the main linker hash table. This function is called via gldelf64ppc_finish. */ bfd_boolean ppc64_elf_build_stubs (bfd_boolean emit_stub_syms, struct bfd_link_info *info, char **stats) { struct ppc_link_hash_table *htab = ppc_hash_table (info); asection *stub_sec; bfd_byte *p; int stub_sec_count = 0; htab->emit_stub_syms = emit_stub_syms; /* Allocate memory to hold the linker stubs. */ for (stub_sec = htab->stub_bfd->sections; stub_sec != NULL; stub_sec = stub_sec->next) if ((stub_sec->flags & SEC_LINKER_CREATED) == 0 && stub_sec->size != 0) { stub_sec->contents = bfd_zalloc (htab->stub_bfd, stub_sec->size); if (stub_sec->contents == NULL) return FALSE; /* We want to check that built size is the same as calculated size. rawsize is a convenient location to use. */ stub_sec->rawsize = stub_sec->size; stub_sec->size = 0; } if (htab->glink != NULL && htab->glink->size != 0) { unsigned int indx; bfd_vma plt0; /* Build the .glink plt call stub. */ if (htab->emit_stub_syms) { struct elf_link_hash_entry *h; h = elf_link_hash_lookup (&htab->elf, "__glink", TRUE, FALSE, FALSE); if (h == NULL) return FALSE; if (h->root.type == bfd_link_hash_new) { h->root.type = bfd_link_hash_defined; h->root.u.def.section = htab->glink; h->root.u.def.value = 8; h->ref_regular = 1; h->def_regular = 1; h->ref_regular_nonweak = 1; h->forced_local = 1; h->non_elf = 0; } } p = htab->glink->contents; plt0 = (htab->plt->output_section->vma + htab->plt->output_offset - (htab->glink->output_section->vma + htab->glink->output_offset + 16)); bfd_put_64 (htab->glink->owner, plt0, p); p += 8; bfd_put_32 (htab->glink->owner, MFLR_R12, p); p += 4; bfd_put_32 (htab->glink->owner, BCL_20_31, p); p += 4; bfd_put_32 (htab->glink->owner, MFLR_R11, p); p += 4; bfd_put_32 (htab->glink->owner, LD_R2_M16R11, p); p += 4; bfd_put_32 (htab->glink->owner, MTLR_R12, p); p += 4; bfd_put_32 (htab->glink->owner, ADD_R12_R2_R11, p); p += 4; bfd_put_32 (htab->glink->owner, LD_R11_0R12, p); p += 4; bfd_put_32 (htab->glink->owner, LD_R2_0R12 | 8, p); p += 4; bfd_put_32 (htab->glink->owner, MTCTR_R11, p); p += 4; bfd_put_32 (htab->glink->owner, LD_R11_0R12 | 16, p); p += 4; bfd_put_32 (htab->glink->owner, BCTR, p); p += 4; while (p - htab->glink->contents < GLINK_CALL_STUB_SIZE) { bfd_put_32 (htab->glink->owner, NOP, p); p += 4; } /* Build the .glink lazy link call stubs. */ indx = 0; while (p < htab->glink->contents + htab->glink->size) { if (indx < 0x8000) { bfd_put_32 (htab->glink->owner, LI_R0_0 | indx, p); p += 4; } else { bfd_put_32 (htab->glink->owner, LIS_R0_0 | PPC_HI (indx), p); p += 4; bfd_put_32 (htab->glink->owner, ORI_R0_R0_0 | PPC_LO (indx), p); p += 4; } bfd_put_32 (htab->glink->owner, B_DOT | ((htab->glink->contents - p + 8) & 0x3fffffc), p); indx++; p += 4; } htab->glink->rawsize = p - htab->glink->contents; } if (htab->brlt->size != 0) { htab->brlt->contents = bfd_zalloc (htab->brlt->owner, htab->brlt->size); if (htab->brlt->contents == NULL) return FALSE; } if (htab->relbrlt != NULL && htab->relbrlt->size != 0) { htab->relbrlt->contents = bfd_zalloc (htab->relbrlt->owner, htab->relbrlt->size); if (htab->relbrlt->contents == NULL) return FALSE; } /* Build the stubs as directed by the stub hash table. */ bfd_hash_traverse (&htab->stub_hash_table, ppc_build_one_stub, info); if (htab->relbrlt != NULL) htab->relbrlt->reloc_count = 0; for (stub_sec = htab->stub_bfd->sections; stub_sec != NULL; stub_sec = stub_sec->next) if ((stub_sec->flags & SEC_LINKER_CREATED) == 0) { stub_sec_count += 1; if (stub_sec->rawsize != stub_sec->size) break; } if (stub_sec != NULL || htab->glink->rawsize != htab->glink->size) { htab->stub_error = TRUE; (*_bfd_error_handler) (_("stubs don't match calculated size")); } if (htab->stub_error) return FALSE; if (stats != NULL) { *stats = bfd_malloc (500); if (*stats == NULL) return FALSE; sprintf (*stats, _("linker stubs in %u group%s\n" " branch %lu\n" " toc adjust %lu\n" " long branch %lu\n" " long toc adj %lu\n" " plt call %lu"), stub_sec_count, stub_sec_count == 1 ? "" : "s", htab->stub_count[ppc_stub_long_branch - 1], htab->stub_count[ppc_stub_long_branch_r2off - 1], htab->stub_count[ppc_stub_plt_branch - 1], htab->stub_count[ppc_stub_plt_branch_r2off - 1], htab->stub_count[ppc_stub_plt_call - 1]); } return TRUE; } /* This function undoes the changes made by add_symbol_adjust. */ static bfd_boolean undo_symbol_twiddle (struct elf_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED) { struct ppc_link_hash_entry *eh; if (h->root.type == bfd_link_hash_indirect) return TRUE; if (h->root.type == bfd_link_hash_warning) h = (struct elf_link_hash_entry *) h->root.u.i.link; eh = (struct ppc_link_hash_entry *) h; if (eh->elf.root.type != bfd_link_hash_undefweak || !eh->was_undefined) return TRUE; eh->elf.root.type = bfd_link_hash_undefined; return TRUE; } void ppc64_elf_restore_symbols (struct bfd_link_info *info) { struct ppc_link_hash_table *htab = ppc_hash_table (info); elf_link_hash_traverse (&htab->elf, undo_symbol_twiddle, info); } /* What to do when ld finds relocations against symbols defined in discarded sections. */ static unsigned int ppc64_elf_action_discarded (asection *sec) { if (strcmp (".opd", sec->name) == 0) return 0; if (strcmp (".toc", sec->name) == 0) return 0; if (strcmp (".toc1", sec->name) == 0) return 0; if (sec->flags & SEC_RELOC) return 0; return _bfd_elf_default_action_discarded (sec); } /* The RELOCATE_SECTION function is called by the 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 adjust 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 ppc64_elf_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) { struct ppc_link_hash_table *htab; Elf_Internal_Shdr *symtab_hdr; struct elf_link_hash_entry **sym_hashes; Elf_Internal_Rela *rel; Elf_Internal_Rela *relend; Elf_Internal_Rela outrel; bfd_byte *loc; struct got_entry **local_got_ents; bfd_vma TOCstart; bfd_boolean ret = TRUE; bfd_boolean is_opd; /* Disabled until we sort out how ld should choose 'y' vs 'at'. */ bfd_boolean is_power4 = FALSE; bfd_vma d_offset = (bfd_big_endian (output_bfd) ? 2 : 0); /* Initialize howto table if needed. */ if (!ppc64_elf_howto_table[R_PPC64_ADDR32]) ppc_howto_init (); htab = ppc_hash_table (info); /* Don't relocate stub sections. */ if (input_section->owner == htab->stub_bfd) return TRUE; local_got_ents = elf_local_got_ents (input_bfd); TOCstart = elf_gp (output_bfd); symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; sym_hashes = elf_sym_hashes (input_bfd); is_opd = ppc64_elf_section_data (input_section)->sec_type == sec_opd; rel = relocs; relend = relocs + input_section->reloc_count; for (; rel < relend; rel++) { enum elf_ppc64_reloc_type r_type; bfd_vma addend, orig_addend; bfd_reloc_status_type r; Elf_Internal_Sym *sym; asection *sec; struct elf_link_hash_entry *h_elf; struct ppc_link_hash_entry *h; struct ppc_link_hash_entry *fdh; const char *sym_name; unsigned long r_symndx, toc_symndx; + bfd_vma toc_addend; char tls_mask, tls_gd, tls_type; char sym_type; bfd_vma relocation; bfd_boolean unresolved_reloc; bfd_boolean warned; unsigned long insn, mask; struct ppc_stub_hash_entry *stub_entry; bfd_vma max_br_offset; bfd_vma from; r_type = ELF64_R_TYPE (rel->r_info); r_symndx = ELF64_R_SYM (rel->r_info); /* For old style R_PPC64_TOC relocs with a zero symbol, use the symbol of the previous ADDR64 reloc. The symbol gives us the proper TOC base to use. */ if (rel->r_info == ELF64_R_INFO (0, R_PPC64_TOC) && rel != relocs && ELF64_R_TYPE (rel[-1].r_info) == R_PPC64_ADDR64 && is_opd) r_symndx = ELF64_R_SYM (rel[-1].r_info); sym = NULL; sec = NULL; h_elf = NULL; sym_name = NULL; unresolved_reloc = FALSE; warned = FALSE; orig_addend = rel->r_addend; if (r_symndx < symtab_hdr->sh_info) { /* It's a local symbol. */ long *opd_adjust; sym = local_syms + r_symndx; sec = local_sections[r_symndx]; sym_name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym, sec); sym_type = ELF64_ST_TYPE (sym->st_info); relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); opd_adjust = get_opd_info (sec); if (opd_adjust != NULL) { long adjust = opd_adjust[(sym->st_value + rel->r_addend) / 8]; if (adjust == -1) relocation = 0; else { /* If this is a relocation against the opd section sym and we have edited .opd, adjust the reloc addend so that ld -r and ld --emit-relocs output is correct. If it is a reloc against some other .opd symbol, then the symbol value will be adjusted later. */ if (ELF_ST_TYPE (sym->st_info) == STT_SECTION) rel->r_addend += adjust; else relocation += adjust; } } } else { RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, r_symndx, symtab_hdr, sym_hashes, h_elf, sec, relocation, unresolved_reloc, warned); sym_name = h_elf->root.root.string; sym_type = h_elf->type; } h = (struct ppc_link_hash_entry *) h_elf; if (sec != NULL && elf_discarded_section (sec)) { /* For relocs against symbols from removed linkonce sections, or sections discarded by a linker script, we just want the section contents zeroed. Avoid any special processing. */ _bfd_clear_contents (ppc64_elf_howto_table[r_type], input_bfd, contents + rel->r_offset); rel->r_info = 0; rel->r_addend = 0; continue; } if (info->relocatable) continue; /* TLS optimizations. Replace instruction sequences and relocs based on information we collected in tls_optimize. We edit RELOCS so that --emit-relocs will output something sensible for the final instruction stream. */ tls_mask = 0; tls_gd = 0; toc_symndx = 0; - if (IS_PPC64_TLS_RELOC (r_type)) + if (h != NULL) + tls_mask = h->tls_mask; + else if (local_got_ents != NULL) { - if (h != NULL) - tls_mask = h->tls_mask; - else if (local_got_ents != NULL) - { - char *lgot_masks; - lgot_masks = (char *) (local_got_ents + symtab_hdr->sh_info); - tls_mask = lgot_masks[r_symndx]; - } - if (tls_mask == 0 && r_type == R_PPC64_TLS) - { - /* Check for toc tls entries. */ - char *toc_tls; + char *lgot_masks; + lgot_masks = (char *) (local_got_ents + symtab_hdr->sh_info); + tls_mask = lgot_masks[r_symndx]; + } + if (tls_mask == 0 + && (r_type == R_PPC64_TLS + || r_type == R_PPC64_TLSGD + || r_type == R_PPC64_TLSLD)) + { + /* Check for toc tls entries. */ + char *toc_tls; - if (!get_tls_mask (&toc_tls, &toc_symndx, &local_syms, - rel, input_bfd)) - return FALSE; + if (!get_tls_mask (&toc_tls, &toc_symndx, &toc_addend, + &local_syms, rel, input_bfd)) + return FALSE; - if (toc_tls) - tls_mask = *toc_tls; - } + if (toc_tls) + tls_mask = *toc_tls; } /* Check that tls relocs are used with tls syms, and non-tls relocs are used with non-tls syms. */ if (r_symndx != 0 && r_type != R_PPC64_NONE && (h == NULL || h->elf.root.type == bfd_link_hash_defined || h->elf.root.type == bfd_link_hash_defweak) - && IS_PPC64_TLS_RELOC (r_type) != (sym_type == STT_TLS)) + && (IS_PPC64_TLS_RELOC (r_type) + != (sym_type == STT_TLS + || (sym_type == STT_SECTION + && (sec->flags & SEC_THREAD_LOCAL) != 0)))) { - if (r_type == R_PPC64_TLS && tls_mask != 0) + if (tls_mask != 0 + && (r_type == R_PPC64_TLS + || r_type == R_PPC64_TLSGD + || r_type == R_PPC64_TLSLD)) /* R_PPC64_TLS is OK against a symbol in the TOC. */ ; else (*_bfd_error_handler) - (sym_type == STT_TLS + (!IS_PPC64_TLS_RELOC (r_type) ? _("%B(%A+0x%lx): %s used with TLS symbol %s") : _("%B(%A+0x%lx): %s used with non-TLS symbol %s"), input_bfd, input_section, (long) rel->r_offset, ppc64_elf_howto_table[r_type]->name, sym_name); } /* Ensure reloc mapping code below stays sane. */ if (R_PPC64_TOC16_LO_DS != R_PPC64_TOC16_DS + 1 || R_PPC64_TOC16_LO != R_PPC64_TOC16 + 1 || (R_PPC64_GOT_TLSLD16 & 3) != (R_PPC64_GOT_TLSGD16 & 3) || (R_PPC64_GOT_TLSLD16_LO & 3) != (R_PPC64_GOT_TLSGD16_LO & 3) || (R_PPC64_GOT_TLSLD16_HI & 3) != (R_PPC64_GOT_TLSGD16_HI & 3) || (R_PPC64_GOT_TLSLD16_HA & 3) != (R_PPC64_GOT_TLSGD16_HA & 3) || (R_PPC64_GOT_TLSLD16 & 3) != (R_PPC64_GOT_TPREL16_DS & 3) || (R_PPC64_GOT_TLSLD16_LO & 3) != (R_PPC64_GOT_TPREL16_LO_DS & 3) || (R_PPC64_GOT_TLSLD16_HI & 3) != (R_PPC64_GOT_TPREL16_HI & 3) || (R_PPC64_GOT_TLSLD16_HA & 3) != (R_PPC64_GOT_TPREL16_HA & 3)) abort (); switch (r_type) { default: break; case R_PPC64_TOC16: case R_PPC64_TOC16_LO: case R_PPC64_TOC16_DS: case R_PPC64_TOC16_LO_DS: { /* Check for toc tls entries. */ char *toc_tls; int retval; - retval = get_tls_mask (&toc_tls, &toc_symndx, &local_syms, - rel, input_bfd); + retval = get_tls_mask (&toc_tls, &toc_symndx, &toc_addend, + &local_syms, rel, input_bfd); if (retval == 0) return FALSE; if (toc_tls) { tls_mask = *toc_tls; if (r_type == R_PPC64_TOC16_DS || r_type == R_PPC64_TOC16_LO_DS) { if (tls_mask != 0 && (tls_mask & (TLS_DTPREL | TLS_TPREL)) == 0) goto toctprel; } else { /* If we found a GD reloc pair, then we might be doing a GD->IE transition. */ if (retval == 2) { tls_gd = TLS_TPRELGD; if (tls_mask != 0 && (tls_mask & TLS_GD) == 0) - goto tls_get_addr_check; + goto tls_ldgd_opt; } else if (retval == 3) { if (tls_mask != 0 && (tls_mask & TLS_LD) == 0) - goto tls_get_addr_check; + goto tls_ldgd_opt; } } } } break; case R_PPC64_GOT_TPREL16_DS: case R_PPC64_GOT_TPREL16_LO_DS: if (tls_mask != 0 && (tls_mask & TLS_TPREL) == 0) { toctprel: insn = bfd_get_32 (output_bfd, contents + rel->r_offset - d_offset); insn &= 31 << 21; insn |= 0x3c0d0000; /* addis 0,13,0 */ bfd_put_32 (output_bfd, insn, contents + rel->r_offset - d_offset); r_type = R_PPC64_TPREL16_HA; if (toc_symndx != 0) { rel->r_info = ELF64_R_INFO (toc_symndx, r_type); /* We changed the symbol. Start over in order to get h, sym, sec etc. right. */ rel--; continue; } else rel->r_info = ELF64_R_INFO (r_symndx, r_type); } break; case R_PPC64_TLS: if (tls_mask != 0 && (tls_mask & TLS_TPREL) == 0) { bfd_vma rtra; insn = bfd_get_32 (output_bfd, contents + rel->r_offset); if ((insn & ((0x3f << 26) | (31 << 11))) == ((31 << 26) | (13 << 11))) rtra = insn & ((1 << 26) - (1 << 16)); else if ((insn & ((0x3f << 26) | (31 << 16))) == ((31 << 26) | (13 << 16))) rtra = (insn & (31 << 21)) | ((insn & (31 << 11)) << 5); else abort (); if ((insn & ((1 << 11) - (1 << 1))) == 266 << 1) /* add -> addi. */ insn = 14 << 26; else if ((insn & (31 << 1)) == 23 << 1 && ((insn & (31 << 6)) < 14 << 6 || ((insn & (31 << 6)) >= 16 << 6 && (insn & (31 << 6)) < 24 << 6))) /* load and store indexed -> dform. */ insn = (32 | ((insn >> 6) & 31)) << 26; else if ((insn & (31 << 1)) == 21 << 1 && (insn & (0x1a << 6)) == 0) /* ldx, ldux, stdx, stdux -> ld, ldu, std, stdu. */ insn = (((58 | ((insn >> 6) & 4)) << 26) | ((insn >> 6) & 1)); else if ((insn & (31 << 1)) == 21 << 1 && (insn & ((1 << 11) - (1 << 1))) == 341 << 1) /* lwax -> lwa. */ insn = (58 << 26) | 2; else abort (); insn |= rtra; bfd_put_32 (output_bfd, insn, contents + rel->r_offset); /* Was PPC64_TLS which sits on insn boundary, now PPC64_TPREL16_LO which is at low-order half-word. */ rel->r_offset += d_offset; r_type = R_PPC64_TPREL16_LO; if (toc_symndx != 0) { rel->r_info = ELF64_R_INFO (toc_symndx, r_type); + rel->r_addend = toc_addend; + rel->r_addend = toc_addend; /* We changed the symbol. Start over in order to get h, sym, sec etc. right. */ rel--; continue; } else rel->r_info = ELF64_R_INFO (r_symndx, r_type); } break; case R_PPC64_GOT_TLSGD16_HI: case R_PPC64_GOT_TLSGD16_HA: tls_gd = TLS_TPRELGD; if (tls_mask != 0 && (tls_mask & TLS_GD) == 0) goto tls_gdld_hi; break; case R_PPC64_GOT_TLSLD16_HI: case R_PPC64_GOT_TLSLD16_HA: if (tls_mask != 0 && (tls_mask & TLS_LD) == 0) { tls_gdld_hi: if ((tls_mask & tls_gd) != 0) r_type = (((r_type - (R_PPC64_GOT_TLSGD16 & 3)) & 3) + R_PPC64_GOT_TPREL16_DS); else { bfd_put_32 (output_bfd, NOP, contents + rel->r_offset); rel->r_offset -= d_offset; r_type = R_PPC64_NONE; } rel->r_info = ELF64_R_INFO (r_symndx, r_type); } break; case R_PPC64_GOT_TLSGD16: case R_PPC64_GOT_TLSGD16_LO: tls_gd = TLS_TPRELGD; if (tls_mask != 0 && (tls_mask & TLS_GD) == 0) - goto tls_get_addr_check; + goto tls_ldgd_opt; break; case R_PPC64_GOT_TLSLD16: case R_PPC64_GOT_TLSLD16_LO: if (tls_mask != 0 && (tls_mask & TLS_LD) == 0) { - tls_get_addr_check: - if (rel + 1 < relend) - { - enum elf_ppc64_reloc_type r_type2; - unsigned long r_symndx2; - struct elf_link_hash_entry *h2; - bfd_vma insn1, insn2, insn3; - bfd_vma offset; + unsigned int insn1, insn2, insn3; + bfd_vma offset; - /* The next instruction should be a call to - __tls_get_addr. Peek at the reloc to be sure. */ - r_type2 = ELF64_R_TYPE (rel[1].r_info); - r_symndx2 = ELF64_R_SYM (rel[1].r_info); - if (r_symndx2 < symtab_hdr->sh_info - || (r_type2 != R_PPC64_REL14 - && r_type2 != R_PPC64_REL14_BRTAKEN - && r_type2 != R_PPC64_REL14_BRNTAKEN - && r_type2 != R_PPC64_REL24)) - break; - - h2 = sym_hashes[r_symndx2 - symtab_hdr->sh_info]; - while (h2->root.type == bfd_link_hash_indirect - || h2->root.type == bfd_link_hash_warning) - h2 = (struct elf_link_hash_entry *) h2->root.u.i.link; - if (h2 == NULL || (h2 != &htab->tls_get_addr->elf - && h2 != &htab->tls_get_addr_fd->elf)) - break; - - /* OK, it checks out. Replace the call. */ - offset = rel[1].r_offset; + tls_ldgd_opt: + offset = (bfd_vma) -1; + /* If not using the newer R_PPC64_TLSGD/LD to mark + __tls_get_addr calls, we must trust that the call + stays with its arg setup insns, ie. that the next + reloc is the __tls_get_addr call associated with + the current reloc. Edit both insns. */ + if (input_section->has_tls_get_addr_call + && rel + 1 < relend + && branch_reloc_hash_match (input_bfd, rel + 1, + htab->tls_get_addr, + htab->tls_get_addr_fd)) + offset = rel[1].r_offset; + if ((tls_mask & tls_gd) != 0) + { + /* IE */ insn1 = bfd_get_32 (output_bfd, contents + rel->r_offset - d_offset); - insn3 = bfd_get_32 (output_bfd, - contents + offset + 4); - if ((tls_mask & tls_gd) != 0) + insn1 &= (1 << 26) - (1 << 2); + insn1 |= 58 << 26; /* ld */ + insn2 = 0x7c636a14; /* add 3,3,13 */ + if (offset != (bfd_vma) -1) + rel[1].r_info = ELF64_R_INFO (ELF64_R_SYM (rel[1].r_info), + R_PPC64_NONE); + if ((tls_mask & TLS_EXPLICIT) == 0) + r_type = (((r_type - (R_PPC64_GOT_TLSGD16 & 3)) & 3) + + R_PPC64_GOT_TPREL16_DS); + else + r_type += R_PPC64_TOC16_DS - R_PPC64_TOC16; + rel->r_info = ELF64_R_INFO (r_symndx, r_type); + } + else + { + /* LE */ + insn1 = 0x3c6d0000; /* addis 3,13,0 */ + insn2 = 0x38630000; /* addi 3,3,0 */ + if (tls_gd == 0) { - /* IE */ - insn1 &= (1 << 26) - (1 << 2); - insn1 |= 58 << 26; /* ld */ - insn2 = 0x7c636a14; /* add 3,3,13 */ - rel[1].r_info = ELF64_R_INFO (r_symndx2, R_PPC64_NONE); - if ((tls_mask & TLS_EXPLICIT) == 0) - r_type = (((r_type - (R_PPC64_GOT_TLSGD16 & 3)) & 3) - + R_PPC64_GOT_TPREL16_DS); - else - r_type += R_PPC64_TOC16_DS - R_PPC64_TOC16; - rel->r_info = ELF64_R_INFO (r_symndx, r_type); + /* Was an LD reloc. */ + if (toc_symndx) + sec = local_sections[toc_symndx]; + for (r_symndx = 0; + r_symndx < symtab_hdr->sh_info; + r_symndx++) + if (local_sections[r_symndx] == sec) + break; + if (r_symndx >= symtab_hdr->sh_info) + r_symndx = 0; + rel->r_addend = htab->elf.tls_sec->vma + DTP_OFFSET; + if (r_symndx != 0) + rel->r_addend -= (local_syms[r_symndx].st_value + + sec->output_offset + + sec->output_section->vma); } - else + else if (toc_symndx != 0) { - /* LE */ - insn1 = 0x3c6d0000; /* addis 3,13,0 */ - insn2 = 0x38630000; /* addi 3,3,0 */ - if (tls_gd == 0) - { - /* 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; - } - else if (toc_symndx != 0) - r_symndx = toc_symndx; - r_type = R_PPC64_TPREL16_HA; - rel->r_info = ELF64_R_INFO (r_symndx, r_type); + r_symndx = toc_symndx; + rel->r_addend = toc_addend; + } + r_type = R_PPC64_TPREL16_HA; + rel->r_info = ELF64_R_INFO (r_symndx, r_type); + if (offset != (bfd_vma) -1) + { rel[1].r_info = ELF64_R_INFO (r_symndx, R_PPC64_TPREL16_LO); - rel[1].r_offset += d_offset; + rel[1].r_offset = offset + d_offset; + rel[1].r_addend = rel->r_addend; } + } + bfd_put_32 (output_bfd, insn1, + contents + rel->r_offset - d_offset); + if (offset != (bfd_vma) -1) + { + insn3 = bfd_get_32 (output_bfd, + contents + offset + 4); if (insn3 == NOP || insn3 == CROR_151515 || insn3 == CROR_313131) { - insn3 = insn2; - insn2 = NOP; rel[1].r_offset += 4; + bfd_put_32 (output_bfd, insn2, contents + offset + 4); + insn2 = NOP; } - bfd_put_32 (output_bfd, insn1, contents + rel->r_offset - d_offset); bfd_put_32 (output_bfd, insn2, contents + offset); - bfd_put_32 (output_bfd, insn3, contents + offset + 4); - if (tls_gd == 0 || toc_symndx != 0) + } + if ((tls_mask & tls_gd) == 0 + && (tls_gd == 0 || toc_symndx != 0)) + { + /* We changed the symbol. Start over in order + to get h, sym, sec etc. right. */ + rel--; + continue; + } + } + break; + + case R_PPC64_TLSGD: + if (tls_mask != 0 && (tls_mask & TLS_GD) == 0) + { + unsigned int insn2, insn3; + bfd_vma offset = rel->r_offset; + + if ((tls_mask & TLS_TPRELGD) != 0) + { + /* IE */ + r_type = R_PPC64_NONE; + insn2 = 0x7c636a14; /* add 3,3,13 */ + } + else + { + /* LE */ + if (toc_symndx != 0) { - /* We changed the symbol. Start over in order - to get h, sym, sec etc. right. */ - rel--; - continue; + r_symndx = toc_symndx; + rel->r_addend = toc_addend; } + r_type = R_PPC64_TPREL16_LO; + rel->r_offset = offset + d_offset; + insn2 = 0x38630000; /* addi 3,3,0 */ } + rel->r_info = ELF64_R_INFO (r_symndx, r_type); + /* Zap the reloc on the _tls_get_addr call too. */ + BFD_ASSERT (offset == rel[1].r_offset); + rel[1].r_info = ELF64_R_INFO (ELF64_R_SYM (rel[1].r_info), + R_PPC64_NONE); + insn3 = bfd_get_32 (output_bfd, + contents + offset + 4); + if (insn3 == NOP + || insn3 == CROR_151515 || insn3 == CROR_313131) + { + rel->r_offset += 4; + bfd_put_32 (output_bfd, insn2, contents + offset + 4); + insn2 = NOP; + } + bfd_put_32 (output_bfd, insn2, contents + offset); + if ((tls_mask & TLS_TPRELGD) == 0 && toc_symndx != 0) + { + rel--; + continue; + } } break; + case R_PPC64_TLSLD: + if (tls_mask != 0 && (tls_mask & TLS_LD) == 0) + { + unsigned int insn2, insn3; + bfd_vma offset = rel->r_offset; + + if (toc_symndx) + sec = local_sections[toc_symndx]; + for (r_symndx = 0; + r_symndx < symtab_hdr->sh_info; + r_symndx++) + if (local_sections[r_symndx] == sec) + break; + if (r_symndx >= symtab_hdr->sh_info) + r_symndx = 0; + rel->r_addend = htab->elf.tls_sec->vma + DTP_OFFSET; + if (r_symndx != 0) + rel->r_addend -= (local_syms[r_symndx].st_value + + sec->output_offset + + sec->output_section->vma); + + r_type = R_PPC64_TPREL16_LO; + rel->r_info = ELF64_R_INFO (r_symndx, r_type); + rel->r_offset = offset + d_offset; + /* Zap the reloc on the _tls_get_addr call too. */ + BFD_ASSERT (offset == rel[1].r_offset); + rel[1].r_info = ELF64_R_INFO (ELF64_R_SYM (rel[1].r_info), + R_PPC64_NONE); + insn2 = 0x38630000; /* addi 3,3,0 */ + insn3 = bfd_get_32 (output_bfd, + contents + offset + 4); + if (insn3 == NOP + || insn3 == CROR_151515 || insn3 == CROR_313131) + { + rel->r_offset += 4; + bfd_put_32 (output_bfd, insn2, contents + offset + 4); + insn2 = NOP; + } + bfd_put_32 (output_bfd, insn2, contents + offset); + rel--; + continue; + } + break; + case R_PPC64_DTPMOD64: if (rel + 1 < relend && rel[1].r_info == ELF64_R_INFO (r_symndx, R_PPC64_DTPREL64) && rel[1].r_offset == rel->r_offset + 8) { if ((tls_mask & TLS_GD) == 0) { rel[1].r_info = ELF64_R_INFO (r_symndx, R_PPC64_NONE); if ((tls_mask & TLS_TPRELGD) != 0) r_type = R_PPC64_TPREL64; else { bfd_put_64 (output_bfd, 1, contents + rel->r_offset); r_type = R_PPC64_NONE; } rel->r_info = ELF64_R_INFO (r_symndx, r_type); } } else { if ((tls_mask & TLS_LD) == 0) { bfd_put_64 (output_bfd, 1, contents + rel->r_offset); r_type = R_PPC64_NONE; rel->r_info = ELF64_R_INFO (r_symndx, r_type); } } break; case R_PPC64_TPREL64: if ((tls_mask & TLS_TPREL) == 0) { r_type = R_PPC64_NONE; rel->r_info = ELF64_R_INFO (r_symndx, r_type); } break; } /* Handle other relocations that tweak non-addend part of insn. */ insn = 0; max_br_offset = 1 << 25; addend = rel->r_addend; switch (r_type) { default: break; /* Branch taken prediction relocations. */ case R_PPC64_ADDR14_BRTAKEN: case R_PPC64_REL14_BRTAKEN: insn = 0x01 << 21; /* 'y' or 't' bit, lowest bit of BO field. */ /* Fall thru. */ /* Branch not taken prediction relocations. */ case R_PPC64_ADDR14_BRNTAKEN: case R_PPC64_REL14_BRNTAKEN: insn |= bfd_get_32 (output_bfd, contents + rel->r_offset) & ~(0x01 << 21); /* Fall thru. */ case R_PPC64_REL14: max_br_offset = 1 << 15; /* Fall thru. */ case R_PPC64_REL24: /* Calls to functions with a different TOC, such as calls to shared objects, need to alter the TOC pointer. This is done using a linkage stub. A REL24 branching to these linkage stubs needs to be followed by a nop, as the nop will be replaced with an instruction to restore the TOC base pointer. */ stub_entry = NULL; fdh = h; if (((h != NULL && (((fdh = h->oh) != NULL && fdh->elf.plt.plist != NULL) || (fdh = h)->elf.plt.plist != NULL)) || (sec != NULL && sec->output_section != NULL && sec->id <= htab->top_id && (htab->stub_group[sec->id].toc_off != htab->stub_group[input_section->id].toc_off))) && (stub_entry = ppc_get_stub_entry (input_section, sec, fdh, rel, htab)) != NULL && (stub_entry->stub_type == ppc_stub_plt_call || stub_entry->stub_type == ppc_stub_plt_branch_r2off || stub_entry->stub_type == ppc_stub_long_branch_r2off)) { bfd_boolean can_plt_call = FALSE; if (rel->r_offset + 8 <= input_section->size) { unsigned long nop; nop = bfd_get_32 (input_bfd, contents + rel->r_offset + 4); if (nop == NOP || nop == CROR_151515 || nop == CROR_313131) { bfd_put_32 (input_bfd, LD_R2_40R1, contents + rel->r_offset + 4); can_plt_call = TRUE; } } if (!can_plt_call) { if (stub_entry->stub_type == ppc_stub_plt_call) { /* If this is a plain branch rather than a branch and link, don't require a nop. However, don't allow tail calls in a shared library as they will result in r2 being corrupted. */ unsigned long br; br = bfd_get_32 (input_bfd, contents + rel->r_offset); if (info->executable && (br & 1) == 0) can_plt_call = TRUE; else stub_entry = NULL; } else if (h != NULL && strcmp (h->elf.root.root.string, ".__libc_start_main") == 0) { /* Allow crt1 branch to go via a toc adjusting stub. */ can_plt_call = TRUE; } else { if (strcmp (input_section->output_section->name, ".init") == 0 || strcmp (input_section->output_section->name, ".fini") == 0) (*_bfd_error_handler) (_("%B(%A+0x%lx): automatic multiple TOCs " "not supported using your crt files; " "recompile with -mminimal-toc or upgrade gcc"), input_bfd, input_section, (long) rel->r_offset); else (*_bfd_error_handler) (_("%B(%A+0x%lx): sibling call optimization to `%s' " "does not allow automatic multiple TOCs; " "recompile with -mminimal-toc or " "-fno-optimize-sibling-calls, " "or make `%s' extern"), input_bfd, input_section, (long) rel->r_offset, sym_name, sym_name); bfd_set_error (bfd_error_bad_value); ret = FALSE; } } if (can_plt_call && stub_entry->stub_type == ppc_stub_plt_call) unresolved_reloc = FALSE; } if (stub_entry == NULL && get_opd_info (sec) != NULL) { /* The branch destination is the value of the opd entry. */ bfd_vma off = (relocation + addend - sec->output_section->vma - sec->output_offset); bfd_vma dest = opd_entry_value (sec, off, NULL, NULL); if (dest != (bfd_vma) -1) { relocation = dest; addend = 0; } } /* If the branch is out of reach we ought to have a long branch stub. */ from = (rel->r_offset + input_section->output_offset + input_section->output_section->vma); if (stub_entry == NULL && (relocation + addend - from + max_br_offset >= 2 * max_br_offset) && r_type != R_PPC64_ADDR14_BRTAKEN && r_type != R_PPC64_ADDR14_BRNTAKEN) stub_entry = ppc_get_stub_entry (input_section, sec, h, rel, htab); if (stub_entry != NULL) { /* Munge up the value and addend so that we call the stub rather than the procedure directly. */ relocation = (stub_entry->stub_offset + stub_entry->stub_sec->output_offset + stub_entry->stub_sec->output_section->vma); addend = 0; } if (insn != 0) { if (is_power4) { /* Set 'a' bit. This is 0b00010 in BO field for branch on CR(BI) insns (BO == 001at or 011at), and 0b01000 for branch on CTR insns (BO == 1a00t or 1a01t). */ if ((insn & (0x14 << 21)) == (0x04 << 21)) insn |= 0x02 << 21; else if ((insn & (0x14 << 21)) == (0x10 << 21)) insn |= 0x08 << 21; else break; } else { /* Invert 'y' bit if not the default. */ if ((bfd_signed_vma) (relocation + addend - from) < 0) insn ^= 0x01 << 21; } bfd_put_32 (output_bfd, insn, contents + rel->r_offset); } /* NOP out calls to undefined weak functions. We can thus call a weak function without first checking whether the function is defined. */ else if (h != NULL && h->elf.root.type == bfd_link_hash_undefweak && r_type == R_PPC64_REL24 && relocation == 0 && addend == 0) { bfd_put_32 (output_bfd, NOP, contents + rel->r_offset); continue; } break; } /* Set `addend'. */ tls_type = 0; switch (r_type) { default: (*_bfd_error_handler) (_("%B: unknown relocation type %d for symbol %s"), input_bfd, (int) r_type, sym_name); bfd_set_error (bfd_error_bad_value); ret = FALSE; continue; case R_PPC64_NONE: case R_PPC64_TLS: + case R_PPC64_TLSGD: + case R_PPC64_TLSLD: case R_PPC64_GNU_VTINHERIT: case R_PPC64_GNU_VTENTRY: continue; /* GOT16 relocations. Like an ADDR16 using the symbol's address in the GOT as relocation value instead of the symbol's value itself. Also, create a GOT entry for the symbol and put the symbol value there. */ case R_PPC64_GOT_TLSGD16: case R_PPC64_GOT_TLSGD16_LO: case R_PPC64_GOT_TLSGD16_HI: case R_PPC64_GOT_TLSGD16_HA: tls_type = TLS_TLS | TLS_GD; goto dogot; case R_PPC64_GOT_TLSLD16: case R_PPC64_GOT_TLSLD16_LO: case R_PPC64_GOT_TLSLD16_HI: case R_PPC64_GOT_TLSLD16_HA: tls_type = TLS_TLS | TLS_LD; goto dogot; case R_PPC64_GOT_TPREL16_DS: case R_PPC64_GOT_TPREL16_LO_DS: case R_PPC64_GOT_TPREL16_HI: case R_PPC64_GOT_TPREL16_HA: tls_type = TLS_TLS | TLS_TPREL; goto dogot; case R_PPC64_GOT_DTPREL16_DS: case R_PPC64_GOT_DTPREL16_LO_DS: case R_PPC64_GOT_DTPREL16_HI: case R_PPC64_GOT_DTPREL16_HA: tls_type = TLS_TLS | TLS_DTPREL; goto dogot; case R_PPC64_GOT16: case R_PPC64_GOT16_LO: case R_PPC64_GOT16_HI: case R_PPC64_GOT16_HA: case R_PPC64_GOT16_DS: case R_PPC64_GOT16_LO_DS: dogot: { /* Relocation is to the entry for this symbol in the global offset table. */ asection *got; bfd_vma *offp; bfd_vma off; unsigned long indx = 0; if (tls_type == (TLS_TLS | TLS_LD) && (h == NULL || !h->elf.def_dynamic)) offp = &ppc64_tlsld_got (input_bfd)->offset; else { struct got_entry *ent; if (h != NULL) { bfd_boolean dyn = htab->elf.dynamic_sections_created; if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, &h->elf) || (info->shared && SYMBOL_REFERENCES_LOCAL (info, &h->elf))) /* This is actually a static link, or it is a -Bsymbolic link and the symbol is defined locally, or the symbol was forced to be local because of a version file. */ ; else { indx = h->elf.dynindx; unresolved_reloc = FALSE; } ent = h->elf.got.glist; } else { if (local_got_ents == NULL) abort (); ent = local_got_ents[r_symndx]; } for (; ent != NULL; ent = ent->next) if (ent->addend == orig_addend && ent->owner == input_bfd && ent->tls_type == tls_type) break; if (ent == NULL) abort (); offp = &ent->got.offset; } got = ppc64_elf_tdata (input_bfd)->got; if (got == NULL) abort (); /* The offset must always be a multiple of 8. We use the least significant bit to record whether we have already processed this entry. */ off = *offp; if ((off & 1) != 0) off &= ~1; else { /* Generate relocs for the dynamic linker, except in the case of TLSLD where we'll use one entry per module. */ asection *relgot = ppc64_elf_tdata (input_bfd)->relgot; *offp = off | 1; if ((info->shared || indx != 0) - && (h == NULL + && (offp == &ppc64_tlsld_got (input_bfd)->offset + || h == NULL || ELF_ST_VISIBILITY (h->elf.other) == STV_DEFAULT || h->elf.root.type != bfd_link_hash_undefweak)) { outrel.r_offset = (got->output_section->vma + got->output_offset + off); outrel.r_addend = addend; if (tls_type & (TLS_LD | TLS_GD)) { outrel.r_addend = 0; outrel.r_info = ELF64_R_INFO (indx, R_PPC64_DTPMOD64); if (tls_type == (TLS_TLS | TLS_GD)) { loc = relgot->contents; loc += (relgot->reloc_count++ * sizeof (Elf64_External_Rela)); bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc); outrel.r_offset += 8; outrel.r_addend = addend; outrel.r_info = ELF64_R_INFO (indx, R_PPC64_DTPREL64); } } else if (tls_type == (TLS_TLS | TLS_DTPREL)) outrel.r_info = ELF64_R_INFO (indx, R_PPC64_DTPREL64); else if (tls_type == (TLS_TLS | TLS_TPREL)) outrel.r_info = ELF64_R_INFO (indx, R_PPC64_TPREL64); else if (indx == 0) { outrel.r_info = ELF64_R_INFO (indx, R_PPC64_RELATIVE); /* Write the .got section contents for the sake of prelink. */ loc = got->contents + off; bfd_put_64 (output_bfd, outrel.r_addend + relocation, loc); } else outrel.r_info = ELF64_R_INFO (indx, R_PPC64_GLOB_DAT); if (indx == 0 && tls_type != (TLS_TLS | TLS_LD)) { outrel.r_addend += relocation; if (tls_type & (TLS_GD | TLS_DTPREL | TLS_TPREL)) outrel.r_addend -= htab->elf.tls_sec->vma; } loc = relgot->contents; loc += (relgot->reloc_count++ * sizeof (Elf64_External_Rela)); bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc); } /* Init the .got section contents here if we're not emitting a reloc. */ else { relocation += addend; if (tls_type == (TLS_TLS | TLS_LD)) relocation = 1; else if (tls_type != 0) { relocation -= htab->elf.tls_sec->vma + DTP_OFFSET; if (tls_type == (TLS_TLS | TLS_TPREL)) relocation += DTP_OFFSET - TP_OFFSET; if (tls_type == (TLS_TLS | TLS_GD)) { bfd_put_64 (output_bfd, relocation, got->contents + off + 8); relocation = 1; } } bfd_put_64 (output_bfd, relocation, got->contents + off); } } if (off >= (bfd_vma) -2) abort (); relocation = got->output_offset + off; /* TOC base (r2) is TOC start plus 0x8000. */ addend = -TOC_BASE_OFF; } break; case R_PPC64_PLT16_HA: case R_PPC64_PLT16_HI: case R_PPC64_PLT16_LO: case R_PPC64_PLT32: case R_PPC64_PLT64: /* Relocation is to the entry for this symbol in the procedure linkage table. */ /* Resolve a PLT reloc against a local symbol directly, without using the procedure linkage table. */ if (h == NULL) break; /* It's possible that we didn't make a PLT entry for this symbol. This happens when statically linking PIC code, or when using -Bsymbolic. Go find a match if there is a PLT entry. */ if (htab->plt != NULL) { struct plt_entry *ent; for (ent = h->elf.plt.plist; ent != NULL; ent = ent->next) if (ent->addend == orig_addend && ent->plt.offset != (bfd_vma) -1) { relocation = (htab->plt->output_section->vma + htab->plt->output_offset + ent->plt.offset); unresolved_reloc = FALSE; } } break; case R_PPC64_TOC: /* Relocation value is TOC base. */ relocation = TOCstart; if (r_symndx == 0) relocation += htab->stub_group[input_section->id].toc_off; else if (unresolved_reloc) ; else if (sec != NULL && sec->id <= htab->top_id) relocation += htab->stub_group[sec->id].toc_off; else unresolved_reloc = TRUE; goto dodyn; /* TOC16 relocs. We want the offset relative to the TOC base, which is the address of the start of the TOC plus 0x8000. The TOC consists of sections .got, .toc, .tocbss, and .plt, in this order. */ case R_PPC64_TOC16: case R_PPC64_TOC16_LO: case R_PPC64_TOC16_HI: case R_PPC64_TOC16_DS: case R_PPC64_TOC16_LO_DS: case R_PPC64_TOC16_HA: addend -= TOCstart + htab->stub_group[input_section->id].toc_off; break; /* Relocate against the beginning of the section. */ case R_PPC64_SECTOFF: case R_PPC64_SECTOFF_LO: case R_PPC64_SECTOFF_HI: case R_PPC64_SECTOFF_DS: case R_PPC64_SECTOFF_LO_DS: case R_PPC64_SECTOFF_HA: if (sec != NULL) addend -= sec->output_section->vma; break; case R_PPC64_REL14: case R_PPC64_REL14_BRNTAKEN: case R_PPC64_REL14_BRTAKEN: case R_PPC64_REL24: break; case R_PPC64_TPREL16: case R_PPC64_TPREL16_LO: case R_PPC64_TPREL16_HI: case R_PPC64_TPREL16_HA: case R_PPC64_TPREL16_DS: case R_PPC64_TPREL16_LO_DS: case R_PPC64_TPREL16_HIGHER: case R_PPC64_TPREL16_HIGHERA: case R_PPC64_TPREL16_HIGHEST: case R_PPC64_TPREL16_HIGHESTA: addend -= htab->elf.tls_sec->vma + TP_OFFSET; if (info->shared) /* The TPREL16 relocs shouldn't really be used in shared libs as they will result in DT_TEXTREL being set, but support them anyway. */ goto dodyn; break; case R_PPC64_DTPREL16: case R_PPC64_DTPREL16_LO: case R_PPC64_DTPREL16_HI: case R_PPC64_DTPREL16_HA: case R_PPC64_DTPREL16_DS: case R_PPC64_DTPREL16_LO_DS: case R_PPC64_DTPREL16_HIGHER: case R_PPC64_DTPREL16_HIGHERA: case R_PPC64_DTPREL16_HIGHEST: case R_PPC64_DTPREL16_HIGHESTA: addend -= htab->elf.tls_sec->vma + DTP_OFFSET; break; case R_PPC64_DTPMOD64: relocation = 1; addend = 0; goto dodyn; case R_PPC64_TPREL64: addend -= htab->elf.tls_sec->vma + TP_OFFSET; goto dodyn; case R_PPC64_DTPREL64: addend -= htab->elf.tls_sec->vma + DTP_OFFSET; /* Fall thru */ /* Relocations that may need to be propagated if this is a dynamic object. */ case R_PPC64_REL30: case R_PPC64_REL32: case R_PPC64_REL64: case R_PPC64_ADDR14: case R_PPC64_ADDR14_BRNTAKEN: case R_PPC64_ADDR14_BRTAKEN: case R_PPC64_ADDR16: case R_PPC64_ADDR16_DS: case R_PPC64_ADDR16_HA: case R_PPC64_ADDR16_HI: case R_PPC64_ADDR16_HIGHER: case R_PPC64_ADDR16_HIGHERA: case R_PPC64_ADDR16_HIGHEST: case R_PPC64_ADDR16_HIGHESTA: case R_PPC64_ADDR16_LO: case R_PPC64_ADDR16_LO_DS: case R_PPC64_ADDR24: case R_PPC64_ADDR32: case R_PPC64_ADDR64: case R_PPC64_UADDR16: case R_PPC64_UADDR32: case R_PPC64_UADDR64: dodyn: if ((input_section->flags & SEC_ALLOC) == 0) break; if (NO_OPD_RELOCS && is_opd) break; if ((info->shared && (h == NULL || ELF_ST_VISIBILITY (h->elf.other) == STV_DEFAULT || h->elf.root.type != bfd_link_hash_undefweak) - && (MUST_BE_DYN_RELOC (r_type) + && (must_be_dyn_reloc (info, r_type) || !SYMBOL_CALLS_LOCAL (info, &h->elf))) || (ELIMINATE_COPY_RELOCS && !info->shared && h != NULL && h->elf.dynindx != -1 && !h->elf.non_got_ref && h->elf.def_dynamic && !h->elf.def_regular)) { Elf_Internal_Rela outrel; bfd_boolean skip, relocate; asection *sreloc; bfd_byte *loc; bfd_vma out_off; /* When generating a dynamic object, these relocations are copied into the output file to be resolved at run time. */ skip = FALSE; relocate = FALSE; out_off = _bfd_elf_section_offset (output_bfd, info, input_section, rel->r_offset); if (out_off == (bfd_vma) -1) skip = TRUE; else if (out_off == (bfd_vma) -2) skip = TRUE, relocate = TRUE; out_off += (input_section->output_section->vma + input_section->output_offset); outrel.r_offset = out_off; outrel.r_addend = rel->r_addend; /* Optimize unaligned reloc use. */ if ((r_type == R_PPC64_ADDR64 && (out_off & 7) != 0) || (r_type == R_PPC64_UADDR64 && (out_off & 7) == 0)) r_type ^= R_PPC64_ADDR64 ^ R_PPC64_UADDR64; else if ((r_type == R_PPC64_ADDR32 && (out_off & 3) != 0) || (r_type == R_PPC64_UADDR32 && (out_off & 3) == 0)) r_type ^= R_PPC64_ADDR32 ^ R_PPC64_UADDR32; else if ((r_type == R_PPC64_ADDR16 && (out_off & 1) != 0) || (r_type == R_PPC64_UADDR16 && (out_off & 1) == 0)) r_type ^= R_PPC64_ADDR16 ^ R_PPC64_UADDR16; if (skip) memset (&outrel, 0, sizeof outrel); else if (!SYMBOL_REFERENCES_LOCAL (info, &h->elf) && !is_opd && r_type != R_PPC64_TOC) outrel.r_info = ELF64_R_INFO (h->elf.dynindx, r_type); else { /* This symbol is local, or marked to become local, or this is an opd section reloc which must point at a local function. */ outrel.r_addend += relocation; if (r_type == R_PPC64_ADDR64 || r_type == R_PPC64_TOC) { if (is_opd && h != NULL) { /* Lie about opd entries. This case occurs when building shared libraries and we reference a function in another shared lib. The same thing happens for a weak definition in an application that's overridden by a strong definition in a shared lib. (I believe this is a generic bug in binutils handling of weak syms.) In these cases we won't use the opd entry in this lib. */ unresolved_reloc = FALSE; } outrel.r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE); /* We need to relocate .opd contents for ld.so. Prelink also wants simple and consistent rules for relocs. This make all RELATIVE relocs have *r_offset equal to r_addend. */ relocate = TRUE; } else { long indx = 0; - if (bfd_is_abs_section (sec)) + if (r_symndx == 0 || bfd_is_abs_section (sec)) ; else if (sec == NULL || sec->owner == NULL) { bfd_set_error (bfd_error_bad_value); return FALSE; } else { asection *osec; osec = sec->output_section; indx = elf_section_data (osec)->dynindx; if (indx == 0) { if ((osec->flags & SEC_READONLY) == 0 && htab->elf.data_index_section != NULL) osec = htab->elf.data_index_section; else osec = htab->elf.text_index_section; indx = elf_section_data (osec)->dynindx; } BFD_ASSERT (indx != 0); /* We are turning this relocation into one against a section symbol, so subtract out the output section's address but not the offset of the input section in the output section. */ outrel.r_addend -= osec->vma; } outrel.r_info = ELF64_R_INFO (indx, r_type); } } sreloc = elf_section_data (input_section)->sreloc; if (sreloc == NULL) abort (); if (sreloc->reloc_count * sizeof (Elf64_External_Rela) >= sreloc->size) abort (); loc = sreloc->contents; loc += sreloc->reloc_count++ * sizeof (Elf64_External_Rela); bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc); /* If this reloc is against an external symbol, it will be computed at runtime, so there's no need to do anything now. However, for the sake of prelink ensure that the section contents are a known value. */ if (! relocate) { unresolved_reloc = FALSE; /* The value chosen here is quite arbitrary as ld.so ignores section contents except for the special case of .opd where the contents might be accessed before relocation. Choose zero, as that won't cause reloc overflow. */ relocation = 0; addend = 0; /* Use *r_offset == r_addend for R_PPC64_ADDR64 relocs to improve backward compatibility with older versions of ld. */ if (r_type == R_PPC64_ADDR64) addend = outrel.r_addend; /* Adjust pc_relative relocs to have zero in *r_offset. */ else if (ppc64_elf_howto_table[r_type]->pc_relative) addend = (input_section->output_section->vma + input_section->output_offset + rel->r_offset); } } break; case R_PPC64_COPY: case R_PPC64_GLOB_DAT: case R_PPC64_JMP_SLOT: case R_PPC64_RELATIVE: /* We shouldn't ever see these dynamic relocs in relocatable files. */ /* Fall through. */ case R_PPC64_PLTGOT16: case R_PPC64_PLTGOT16_DS: case R_PPC64_PLTGOT16_HA: case R_PPC64_PLTGOT16_HI: case R_PPC64_PLTGOT16_LO: case R_PPC64_PLTGOT16_LO_DS: case R_PPC64_PLTREL32: case R_PPC64_PLTREL64: /* These ones haven't been implemented yet. */ (*_bfd_error_handler) (_("%B: relocation %s is not supported for symbol %s."), input_bfd, ppc64_elf_howto_table[r_type]->name, sym_name); bfd_set_error (bfd_error_invalid_operation); ret = FALSE; continue; } /* Do any further special processing. */ switch (r_type) { default: break; case R_PPC64_ADDR16_HA: case R_PPC64_ADDR16_HIGHERA: case R_PPC64_ADDR16_HIGHESTA: case R_PPC64_TOC16_HA: case R_PPC64_SECTOFF_HA: case R_PPC64_TPREL16_HA: case R_PPC64_DTPREL16_HA: case R_PPC64_TPREL16_HIGHER: case R_PPC64_TPREL16_HIGHERA: case R_PPC64_TPREL16_HIGHEST: case R_PPC64_TPREL16_HIGHESTA: case R_PPC64_DTPREL16_HIGHER: case R_PPC64_DTPREL16_HIGHERA: case R_PPC64_DTPREL16_HIGHEST: case R_PPC64_DTPREL16_HIGHESTA: /* It's just possible that this symbol is a weak symbol that's not actually defined anywhere. In that case, 'sec' would be NULL, and we should leave the symbol alone (it will be set to zero elsewhere in the link). */ if (sec == NULL) break; /* Fall thru */ case R_PPC64_GOT16_HA: case R_PPC64_PLTGOT16_HA: case R_PPC64_PLT16_HA: case R_PPC64_GOT_TLSGD16_HA: case R_PPC64_GOT_TLSLD16_HA: case R_PPC64_GOT_TPREL16_HA: case R_PPC64_GOT_DTPREL16_HA: /* Add 0x10000 if sign bit in 0:15 is set. Bits 0:15 are not used. */ addend += 0x8000; break; case R_PPC64_ADDR16_DS: case R_PPC64_ADDR16_LO_DS: case R_PPC64_GOT16_DS: case R_PPC64_GOT16_LO_DS: case R_PPC64_PLT16_LO_DS: case R_PPC64_SECTOFF_DS: case R_PPC64_SECTOFF_LO_DS: case R_PPC64_TOC16_DS: case R_PPC64_TOC16_LO_DS: case R_PPC64_PLTGOT16_DS: case R_PPC64_PLTGOT16_LO_DS: case R_PPC64_GOT_TPREL16_DS: case R_PPC64_GOT_TPREL16_LO_DS: case R_PPC64_GOT_DTPREL16_DS: case R_PPC64_GOT_DTPREL16_LO_DS: case R_PPC64_TPREL16_DS: case R_PPC64_TPREL16_LO_DS: case R_PPC64_DTPREL16_DS: case R_PPC64_DTPREL16_LO_DS: insn = bfd_get_32 (input_bfd, contents + (rel->r_offset & ~3)); mask = 3; /* If this reloc is against an lq insn, then the value must be a multiple of 16. This is somewhat of a hack, but the "correct" way to do this by defining _DQ forms of all the _DS relocs bloats all reloc switches in this file. It doesn't seem to make much sense to use any of these relocs in data, so testing the insn should be safe. */ if ((insn & (0x3f << 26)) == (56u << 26)) mask = 15; if (((relocation + addend) & mask) != 0) { (*_bfd_error_handler) (_("%B: error: relocation %s not a multiple of %d"), input_bfd, ppc64_elf_howto_table[r_type]->name, mask + 1); bfd_set_error (bfd_error_bad_value); ret = FALSE; continue; } break; } /* Dynamic relocs are not propagated for SEC_DEBUGGING sections because such sections are not SEC_ALLOC and thus ld.so will not process them. */ if (unresolved_reloc && !((input_section->flags & SEC_DEBUGGING) != 0 && h->elf.def_dynamic)) { (*_bfd_error_handler) (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"), input_bfd, input_section, (long) rel->r_offset, ppc64_elf_howto_table[(int) r_type]->name, h->elf.root.root.string); ret = FALSE; } r = _bfd_final_link_relocate (ppc64_elf_howto_table[(int) r_type], input_bfd, input_section, contents, rel->r_offset, relocation, addend); if (r != bfd_reloc_ok) { if (sym_name == NULL) sym_name = "(null)"; if (r == bfd_reloc_overflow) { if (warned) continue; if (h != NULL && h->elf.root.type == bfd_link_hash_undefweak && ppc64_elf_howto_table[r_type]->pc_relative) { /* Assume this is a call protected by other code that detects the symbol is undefined. If this is the case, we can safely ignore the overflow. If not, the program is hosed anyway, and a little warning isn't going to help. */ continue; } if (!((*info->callbacks->reloc_overflow) (info, (h ? &h->elf.root : NULL), sym_name, ppc64_elf_howto_table[r_type]->name, orig_addend, input_bfd, input_section, rel->r_offset))) return FALSE; } else { (*_bfd_error_handler) (_("%B(%A+0x%lx): %s reloc against `%s': error %d"), input_bfd, input_section, (long) rel->r_offset, ppc64_elf_howto_table[r_type]->name, sym_name, (int) r); ret = FALSE; } } } /* If we're emitting relocations, then shortly after this function returns, reloc offsets and addends for this section will be adjusted. Worse, reloc symbol indices will be for the output file rather than the input. Save a copy of the relocs for opd_entry_value. */ if (is_opd && (info->emitrelocations || info->relocatable)) { bfd_size_type amt; amt = input_section->reloc_count * sizeof (Elf_Internal_Rela); rel = bfd_alloc (input_bfd, amt); BFD_ASSERT (ppc64_elf_tdata (input_bfd)->opd_relocs == NULL); ppc64_elf_tdata (input_bfd)->opd_relocs = rel; if (rel == NULL) return FALSE; memcpy (rel, relocs, amt); } return ret; } /* Adjust the value of any local symbols in opd sections. */ static bfd_boolean ppc64_elf_output_symbol_hook (struct bfd_link_info *info, const char *name ATTRIBUTE_UNUSED, Elf_Internal_Sym *elfsym, asection *input_sec, struct elf_link_hash_entry *h) { long *opd_adjust, adjust; bfd_vma value; if (h != NULL) return TRUE; opd_adjust = get_opd_info (input_sec); if (opd_adjust == NULL) return TRUE; value = elfsym->st_value - input_sec->output_offset; if (!info->relocatable) value -= input_sec->output_section->vma; adjust = opd_adjust[value / 8]; if (adjust == -1) elfsym->st_value = 0; else elfsym->st_value += adjust; return TRUE; } /* Finish up dynamic symbol handling. We set the contents of various dynamic sections here. */ static bfd_boolean ppc64_elf_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info, struct elf_link_hash_entry *h, Elf_Internal_Sym *sym) { struct ppc_link_hash_table *htab; struct plt_entry *ent; Elf_Internal_Rela rela; bfd_byte *loc; htab = ppc_hash_table (info); for (ent = h->plt.plist; ent != NULL; ent = ent->next) if (ent->plt.offset != (bfd_vma) -1) { /* This symbol has an entry in the procedure linkage table. Set it up. */ if (htab->plt == NULL || htab->relplt == NULL || htab->glink == NULL) abort (); /* Create a JMP_SLOT reloc to inform the dynamic linker to fill in the PLT entry. */ rela.r_offset = (htab->plt->output_section->vma + htab->plt->output_offset + ent->plt.offset); rela.r_info = ELF64_R_INFO (h->dynindx, R_PPC64_JMP_SLOT); rela.r_addend = ent->addend; loc = htab->relplt->contents; loc += ((ent->plt.offset - PLT_INITIAL_ENTRY_SIZE) / PLT_ENTRY_SIZE * sizeof (Elf64_External_Rela)); bfd_elf64_swap_reloca_out (output_bfd, &rela, loc); } if (h->needs_copy) { Elf_Internal_Rela rela; bfd_byte *loc; /* This symbol needs a copy reloc. Set it up. */ if (h->dynindx == -1 || (h->root.type != bfd_link_hash_defined && h->root.type != bfd_link_hash_defweak) || htab->relbss == NULL) abort (); rela.r_offset = (h->root.u.def.value + h->root.u.def.section->output_section->vma + h->root.u.def.section->output_offset); rela.r_info = ELF64_R_INFO (h->dynindx, R_PPC64_COPY); rela.r_addend = 0; loc = htab->relbss->contents; loc += htab->relbss->reloc_count++ * sizeof (Elf64_External_Rela); bfd_elf64_swap_reloca_out (output_bfd, &rela, loc); } /* Mark some specially defined symbols as absolute. */ if (strcmp (h->root.root.string, "_DYNAMIC") == 0) sym->st_shndx = SHN_ABS; return TRUE; } /* Used to decide how to sort relocs in an optimal manner for the dynamic linker, before writing them out. */ static enum elf_reloc_type_class ppc64_elf_reloc_type_class (const Elf_Internal_Rela *rela) { enum elf_ppc64_reloc_type r_type; r_type = ELF64_R_TYPE (rela->r_info); switch (r_type) { case R_PPC64_RELATIVE: return reloc_class_relative; case R_PPC64_JMP_SLOT: return reloc_class_plt; case R_PPC64_COPY: return reloc_class_copy; default: return reloc_class_normal; } } /* Finish up the dynamic sections. */ static bfd_boolean ppc64_elf_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) { struct ppc_link_hash_table *htab; bfd *dynobj; asection *sdyn; htab = ppc_hash_table (info); dynobj = htab->elf.dynobj; sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); if (htab->elf.dynamic_sections_created) { Elf64_External_Dyn *dyncon, *dynconend; if (sdyn == NULL || htab->got == NULL) abort (); dyncon = (Elf64_External_Dyn *) sdyn->contents; dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->size); for (; dyncon < dynconend; dyncon++) { Elf_Internal_Dyn dyn; asection *s; bfd_elf64_swap_dyn_in (dynobj, dyncon, &dyn); switch (dyn.d_tag) { default: continue; case DT_PPC64_GLINK: s = htab->glink; dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; /* We stupidly defined DT_PPC64_GLINK to be the start of glink rather than the first entry point, which is what ld.so needs, and now have a bigger stub to support automatic multiple TOCs. */ dyn.d_un.d_ptr += GLINK_CALL_STUB_SIZE - 32; break; case DT_PPC64_OPD: s = bfd_get_section_by_name (output_bfd, ".opd"); if (s == NULL) continue; dyn.d_un.d_ptr = s->vma; break; case DT_PPC64_OPDSZ: s = bfd_get_section_by_name (output_bfd, ".opd"); if (s == NULL) continue; dyn.d_un.d_val = s->size; break; case DT_PLTGOT: s = htab->plt; dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; break; case DT_JMPREL: s = htab->relplt; dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; break; case DT_PLTRELSZ: dyn.d_un.d_val = htab->relplt->size; break; case DT_RELASZ: /* Don't count procedure linkage table relocs in the overall reloc count. */ s = htab->relplt; if (s == NULL) continue; dyn.d_un.d_val -= s->size; break; case DT_RELA: /* We may not be using the standard ELF linker script. If .rela.plt is the first .rela section, we adjust DT_RELA to not include it. */ s = htab->relplt; if (s == NULL) continue; if (dyn.d_un.d_ptr != s->output_section->vma + s->output_offset) continue; dyn.d_un.d_ptr += s->size; break; } bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon); } } if (htab->got != NULL && htab->got->size != 0) { /* Fill in the first entry in the global offset table. We use it to hold the link-time TOCbase. */ bfd_put_64 (output_bfd, elf_gp (output_bfd) + TOC_BASE_OFF, htab->got->contents); /* Set .got entry size. */ elf_section_data (htab->got->output_section)->this_hdr.sh_entsize = 8; } if (htab->plt != NULL && htab->plt->size != 0) { /* Set .plt entry size. */ elf_section_data (htab->plt->output_section)->this_hdr.sh_entsize = PLT_ENTRY_SIZE; } /* brlt is SEC_LINKER_CREATED, so we need to write out relocs for brlt ourselves if emitrelocations. */ if (htab->brlt != NULL && htab->brlt->reloc_count != 0 && !_bfd_elf_link_output_relocs (output_bfd, htab->brlt, &elf_section_data (htab->brlt)->rel_hdr, elf_section_data (htab->brlt)->relocs, NULL)) return FALSE; /* We need to handle writing out multiple GOT sections ourselves, since we didn't add them to DYNOBJ. We know dynobj is the first bfd. */ while ((dynobj = dynobj->link_next) != NULL) { asection *s; if (!is_ppc64_elf_target (dynobj->xvec)) continue; s = ppc64_elf_tdata (dynobj)->got; if (s != NULL && s->size != 0 && s->output_section != bfd_abs_section_ptr && !bfd_set_section_contents (output_bfd, s->output_section, s->contents, s->output_offset, s->size)) return FALSE; s = ppc64_elf_tdata (dynobj)->relgot; if (s != NULL && s->size != 0 && s->output_section != bfd_abs_section_ptr && !bfd_set_section_contents (output_bfd, s->output_section, s->contents, s->output_offset, s->size)) return FALSE; } return TRUE; } #include "elf64-target.h" Index: head/contrib/binutils/bfd/libbfd.h =================================================================== --- head/contrib/binutils/bfd/libbfd.h (revision 275717) +++ head/contrib/binutils/bfd/libbfd.h (revision 275718) @@ -1,2031 +1,2033 @@ /* DO NOT EDIT! -*- buffer-read-only: t -*- This file is automatically generated from "libbfd-in.h", "init.c", "libbfd.c", "bfdio.c", "bfdwin.c", "cache.c", "reloc.c", "archures.c" and "elf.c". Run "make headers" in your build bfd/ to regenerate. */ /* libbfd.h -- Declarations used by bfd library *implementation*. (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, 2006, 2007 Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ #include "hashtab.h" /* Align an address upward to a boundary, expressed as a number of bytes. E.g. align to an 8-byte boundary with argument of 8. Take care never to wrap around if the address is within boundary-1 of the end of the address space. */ #define BFD_ALIGN(this, boundary) \ ((((bfd_vma) (this) + (boundary) - 1) >= (bfd_vma) (this)) \ ? (((bfd_vma) (this) + ((boundary) - 1)) & ~ (bfd_vma) ((boundary)-1)) \ : ~ (bfd_vma) 0) /* If you want to read and write large blocks, you might want to do it in quanta of this amount */ #define DEFAULT_BUFFERSIZE 8192 /* Set a tdata field. Can't use the other macros for this, since they do casts, and casting to the left of assignment isn't portable. */ #define set_tdata(bfd, v) ((bfd)->tdata.any = (v)) /* If BFD_IN_MEMORY is set for a BFD, then the iostream fields points to an instance of this structure. */ struct bfd_in_memory { /* Size of buffer. */ bfd_size_type size; /* Buffer holding contents of BFD. */ 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. */ struct artdata { file_ptr first_file_filepos; /* Speed up searching the armap */ htab_t cache; bfd *archive_head; /* Only interesting in output routines */ carsym *symdefs; /* the symdef entries */ symindex symdef_count; /* how many there are */ char *extended_names; /* clever intel extension */ bfd_size_type extended_names_size; /* Size of extended names */ /* when more compilers are standard C, this can be a time_t */ long armap_timestamp; /* Timestamp value written into armap. This is used for BSD archives to check that the timestamp is recent enough for the BSD linker to not complain, just before we finish writing an archive. */ file_ptr armap_datepos; /* Position within archive to seek to rewrite the date field. */ void *tdata; /* Backend specific information. */ }; #define bfd_ardata(bfd) ((bfd)->tdata.aout_ar_data) /* Goes in bfd's arelt_data slot */ struct areltdata { char * arch_header; /* it's actually a string */ unsigned int parsed_size; /* octets of filesize not including ar_hdr */ char *filename; /* null-terminated */ }; #define arelt_size(bfd) (((struct areltdata *)((bfd)->arelt_data))->parsed_size) extern void *bfd_malloc (bfd_size_type); extern void *bfd_realloc (void *, bfd_size_type); extern void *bfd_zmalloc (bfd_size_type); extern void *bfd_malloc2 (bfd_size_type, bfd_size_type); extern void *bfd_realloc2 (void *, bfd_size_type, bfd_size_type); extern void *bfd_zmalloc2 (bfd_size_type, bfd_size_type); extern void _bfd_default_error_handler (const char *s, ...); extern bfd_error_handler_type _bfd_error_handler; /* These routines allocate and free things on the BFD's objalloc. */ extern void *bfd_alloc (bfd *, bfd_size_type); extern void *bfd_zalloc (bfd *, bfd_size_type); extern void *bfd_alloc2 (bfd *, bfd_size_type, bfd_size_type); extern void *bfd_zalloc2 (bfd *, bfd_size_type, bfd_size_type); extern void bfd_release (bfd *, void *); bfd * _bfd_create_empty_archive_element_shell (bfd *obfd); bfd * _bfd_look_for_bfd_in_cache (bfd *, file_ptr); bfd_boolean _bfd_add_bfd_to_archive_cache (bfd *, file_ptr, bfd *); bfd_boolean _bfd_generic_mkarchive (bfd *abfd); const bfd_target *bfd_generic_archive_p (bfd *abfd); bfd_boolean bfd_slurp_armap (bfd *abfd); bfd_boolean bfd_slurp_bsd_armap_f2 (bfd *abfd); #define bfd_slurp_bsd_armap bfd_slurp_armap #define bfd_slurp_coff_armap bfd_slurp_armap bfd_boolean _bfd_slurp_extended_name_table (bfd *abfd); extern bfd_boolean _bfd_construct_extended_name_table (bfd *, bfd_boolean, char **, bfd_size_type *); bfd_boolean _bfd_write_archive_contents (bfd *abfd); bfd_boolean _bfd_compute_and_write_armap (bfd *, unsigned int elength); bfd *_bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos); extern bfd *_bfd_generic_get_elt_at_index (bfd *, symindex); bfd * _bfd_new_bfd (void); void _bfd_delete_bfd (bfd *); bfd_boolean _bfd_free_cached_info (bfd *); bfd_boolean bfd_false (bfd *ignore); bfd_boolean bfd_true (bfd *ignore); void *bfd_nullvoidptr (bfd *ignore); int bfd_0 (bfd *ignore); unsigned int bfd_0u (bfd *ignore); long bfd_0l (bfd *ignore); long _bfd_n1 (bfd *ignore); void bfd_void (bfd *ignore); bfd *_bfd_new_bfd_contained_in (bfd *); const bfd_target *_bfd_dummy_target (bfd *abfd); void bfd_dont_truncate_arname (bfd *abfd, const char *filename, char *hdr); void bfd_bsd_truncate_arname (bfd *abfd, const char *filename, char *hdr); void bfd_gnu_truncate_arname (bfd *abfd, const char *filename, char *hdr); bfd_boolean bsd_write_armap (bfd *arch, unsigned int elength, struct orl *map, unsigned int orl_count, int stridx); bfd_boolean coff_write_armap (bfd *arch, unsigned int elength, struct orl *map, unsigned int orl_count, int stridx); extern void *_bfd_generic_read_ar_hdr (bfd *); extern void _bfd_ar_spacepad (char *, size_t, const char *, long); extern void *_bfd_generic_read_ar_hdr_mag (bfd *, const char *); bfd * bfd_generic_openr_next_archived_file (bfd *archive, bfd *last_file); int bfd_generic_stat_arch_elt (bfd *, struct stat *); #define _bfd_read_ar_hdr(abfd) \ BFD_SEND (abfd, _bfd_read_ar_hdr_fn, (abfd)) /* Generic routines to use for BFD_JUMP_TABLE_GENERIC. Use BFD_JUMP_TABLE_GENERIC (_bfd_generic). */ #define _bfd_generic_close_and_cleanup bfd_true #define _bfd_generic_bfd_free_cached_info bfd_true extern bfd_boolean _bfd_generic_new_section_hook (bfd *, asection *); extern bfd_boolean _bfd_generic_get_section_contents (bfd *, asection *, void *, file_ptr, bfd_size_type); extern bfd_boolean _bfd_generic_get_section_contents_in_window (bfd *, asection *, bfd_window *, file_ptr, bfd_size_type); /* Generic routines to use for BFD_JUMP_TABLE_COPY. Use BFD_JUMP_TABLE_COPY (_bfd_generic). */ #define _bfd_generic_bfd_copy_private_bfd_data \ ((bfd_boolean (*) (bfd *, bfd *)) bfd_true) #define _bfd_generic_bfd_merge_private_bfd_data \ ((bfd_boolean (*) (bfd *, bfd *)) bfd_true) #define _bfd_generic_bfd_set_private_flags \ ((bfd_boolean (*) (bfd *, flagword)) bfd_true) #define _bfd_generic_bfd_copy_private_section_data \ ((bfd_boolean (*) (bfd *, asection *, bfd *, asection *)) bfd_true) #define _bfd_generic_bfd_copy_private_symbol_data \ ((bfd_boolean (*) (bfd *, asymbol *, bfd *, asymbol *)) bfd_true) #define _bfd_generic_bfd_copy_private_header_data \ ((bfd_boolean (*) (bfd *, bfd *)) bfd_true) #define _bfd_generic_bfd_print_private_bfd_data \ ((bfd_boolean (*) (bfd *, void *)) bfd_true) extern bfd_boolean _bfd_generic_init_private_section_data (bfd *, asection *, bfd *, asection *, struct bfd_link_info *); /* Routines to use for BFD_JUMP_TABLE_CORE when there is no core file support. Use BFD_JUMP_TABLE_CORE (_bfd_nocore). */ extern char *_bfd_nocore_core_file_failing_command (bfd *); extern int _bfd_nocore_core_file_failing_signal (bfd *); extern bfd_boolean _bfd_nocore_core_file_matches_executable_p (bfd *, bfd *); /* Routines to use for BFD_JUMP_TABLE_ARCHIVE when there is no archive file support. Use BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive). */ #define _bfd_noarchive_slurp_armap bfd_false #define _bfd_noarchive_slurp_extended_name_table bfd_false #define _bfd_noarchive_construct_extended_name_table \ ((bfd_boolean (*) (bfd *, char **, bfd_size_type *, const char **)) \ bfd_false) #define _bfd_noarchive_truncate_arname \ ((void (*) (bfd *, const char *, char *)) bfd_void) #define _bfd_noarchive_write_armap \ ((bfd_boolean (*) (bfd *, unsigned int, struct orl *, unsigned int, int)) \ bfd_false) #define _bfd_noarchive_read_ar_hdr bfd_nullvoidptr #define _bfd_noarchive_openr_next_archived_file \ ((bfd *(*) (bfd *, bfd *)) bfd_nullvoidptr) #define _bfd_noarchive_get_elt_at_index \ ((bfd *(*) (bfd *, symindex)) bfd_nullvoidptr) #define _bfd_noarchive_generic_stat_arch_elt bfd_generic_stat_arch_elt #define _bfd_noarchive_update_armap_timestamp bfd_false /* Routines to use for BFD_JUMP_TABLE_ARCHIVE to get BSD style archives. Use BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_bsd). */ #define _bfd_archive_bsd_slurp_armap bfd_slurp_bsd_armap #define _bfd_archive_bsd_slurp_extended_name_table \ _bfd_slurp_extended_name_table extern bfd_boolean _bfd_archive_bsd_construct_extended_name_table (bfd *, char **, bfd_size_type *, const char **); #define _bfd_archive_bsd_truncate_arname bfd_bsd_truncate_arname #define _bfd_archive_bsd_write_armap bsd_write_armap #define _bfd_archive_bsd_read_ar_hdr _bfd_generic_read_ar_hdr #define _bfd_archive_bsd_openr_next_archived_file \ bfd_generic_openr_next_archived_file #define _bfd_archive_bsd_get_elt_at_index _bfd_generic_get_elt_at_index #define _bfd_archive_bsd_generic_stat_arch_elt \ bfd_generic_stat_arch_elt extern bfd_boolean _bfd_archive_bsd_update_armap_timestamp (bfd *); /* Routines to use for BFD_JUMP_TABLE_ARCHIVE to get COFF style archives. Use BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff). */ #define _bfd_archive_coff_slurp_armap bfd_slurp_coff_armap #define _bfd_archive_coff_slurp_extended_name_table \ _bfd_slurp_extended_name_table extern bfd_boolean _bfd_archive_coff_construct_extended_name_table (bfd *, char **, bfd_size_type *, const char **); #define _bfd_archive_coff_truncate_arname bfd_dont_truncate_arname #define _bfd_archive_coff_write_armap coff_write_armap #define _bfd_archive_coff_read_ar_hdr _bfd_generic_read_ar_hdr #define _bfd_archive_coff_openr_next_archived_file \ bfd_generic_openr_next_archived_file #define _bfd_archive_coff_get_elt_at_index _bfd_generic_get_elt_at_index #define _bfd_archive_coff_generic_stat_arch_elt \ bfd_generic_stat_arch_elt #define _bfd_archive_coff_update_armap_timestamp bfd_true /* Routines to use for BFD_JUMP_TABLE_SYMBOLS where there is no symbol support. Use BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols). */ #define _bfd_nosymbols_get_symtab_upper_bound _bfd_n1 #define _bfd_nosymbols_canonicalize_symtab \ ((long (*) (bfd *, asymbol **)) _bfd_n1) #define _bfd_nosymbols_make_empty_symbol _bfd_generic_make_empty_symbol #define _bfd_nosymbols_print_symbol \ ((void (*) (bfd *, void *, asymbol *, bfd_print_symbol_type)) bfd_void) #define _bfd_nosymbols_get_symbol_info \ ((void (*) (bfd *, asymbol *, symbol_info *)) bfd_void) #define _bfd_nosymbols_bfd_is_local_label_name \ ((bfd_boolean (*) (bfd *, const char *)) bfd_false) #define _bfd_nosymbols_bfd_is_target_special_symbol \ ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false) #define _bfd_nosymbols_get_lineno \ ((alent *(*) (bfd *, asymbol *)) bfd_nullvoidptr) #define _bfd_nosymbols_find_nearest_line \ ((bfd_boolean (*) (bfd *, asection *, asymbol **, bfd_vma, const char **, \ const char **, unsigned int *)) \ bfd_false) #define _bfd_nosymbols_find_inliner_info \ ((bfd_boolean (*) (bfd *, const char **, const char **, unsigned int *)) \ bfd_false) #define _bfd_nosymbols_bfd_make_debug_symbol \ ((asymbol *(*) (bfd *, void *, unsigned long)) bfd_nullvoidptr) #define _bfd_nosymbols_read_minisymbols \ ((long (*) (bfd *, bfd_boolean, void **, unsigned int *)) _bfd_n1) #define _bfd_nosymbols_minisymbol_to_symbol \ ((asymbol *(*) (bfd *, bfd_boolean, const void *, asymbol *)) \ bfd_nullvoidptr) /* Routines to use for BFD_JUMP_TABLE_RELOCS when there is no reloc support. Use BFD_JUMP_TABLE_RELOCS (_bfd_norelocs). */ extern long _bfd_norelocs_get_reloc_upper_bound (bfd *, asection *); extern long _bfd_norelocs_canonicalize_reloc (bfd *, asection *, arelent **, asymbol **); #define _bfd_norelocs_bfd_reloc_type_lookup \ ((reloc_howto_type *(*) (bfd *, bfd_reloc_code_real_type)) bfd_nullvoidptr) #define _bfd_norelocs_bfd_reloc_name_lookup \ ((reloc_howto_type *(*) (bfd *, const char *)) bfd_nullvoidptr) /* Routines to use for BFD_JUMP_TABLE_WRITE for targets which may not be written. Use BFD_JUMP_TABLE_WRITE (_bfd_nowrite). */ #define _bfd_nowrite_set_arch_mach \ ((bfd_boolean (*) (bfd *, enum bfd_architecture, unsigned long)) \ bfd_false) #define _bfd_nowrite_set_section_contents \ ((bfd_boolean (*) (bfd *, asection *, const void *, file_ptr, bfd_size_type)) \ bfd_false) /* Generic routines to use for BFD_JUMP_TABLE_WRITE. Use BFD_JUMP_TABLE_WRITE (_bfd_generic). */ #define _bfd_generic_set_arch_mach bfd_default_set_arch_mach extern bfd_boolean _bfd_generic_set_section_contents (bfd *, asection *, const void *, file_ptr, bfd_size_type); /* Routines to use for BFD_JUMP_TABLE_LINK for targets which do not support linking. Use BFD_JUMP_TABLE_LINK (_bfd_nolink). */ #define _bfd_nolink_sizeof_headers \ ((int (*) (bfd *, struct bfd_link_info *)) bfd_0) #define _bfd_nolink_bfd_get_relocated_section_contents \ ((bfd_byte *(*) (bfd *, struct bfd_link_info *, struct bfd_link_order *, \ bfd_byte *, bfd_boolean, asymbol **)) \ bfd_nullvoidptr) #define _bfd_nolink_bfd_relax_section \ ((bfd_boolean (*) \ (bfd *, asection *, struct bfd_link_info *, bfd_boolean *)) \ bfd_false) #define _bfd_nolink_bfd_gc_sections \ ((bfd_boolean (*) (bfd *, struct bfd_link_info *)) \ bfd_false) #define _bfd_nolink_bfd_merge_sections \ ((bfd_boolean (*) (bfd *, struct bfd_link_info *)) \ bfd_false) #define _bfd_nolink_bfd_is_group_section \ ((bfd_boolean (*) (bfd *, const struct bfd_section *)) \ bfd_false) #define _bfd_nolink_bfd_discard_group \ ((bfd_boolean (*) (bfd *, struct bfd_section *)) \ bfd_false) #define _bfd_nolink_bfd_link_hash_table_create \ ((struct bfd_link_hash_table *(*) (bfd *)) bfd_nullvoidptr) #define _bfd_nolink_bfd_link_hash_table_free \ ((void (*) (struct bfd_link_hash_table *)) bfd_void) #define _bfd_nolink_bfd_link_add_symbols \ ((bfd_boolean (*) (bfd *, struct bfd_link_info *)) bfd_false) #define _bfd_nolink_bfd_link_just_syms \ ((void (*) (asection *, struct bfd_link_info *)) bfd_void) #define _bfd_nolink_bfd_final_link \ ((bfd_boolean (*) (bfd *, struct bfd_link_info *)) bfd_false) #define _bfd_nolink_bfd_link_split_section \ ((bfd_boolean (*) (bfd *, struct bfd_section *)) bfd_false) #define _bfd_nolink_section_already_linked \ ((void (*) (bfd *, struct bfd_section *, struct bfd_link_info *)) bfd_void) /* Routines to use for BFD_JUMP_TABLE_DYNAMIC for targets which do not have dynamic symbols or relocs. Use BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic). */ #define _bfd_nodynamic_get_dynamic_symtab_upper_bound _bfd_n1 #define _bfd_nodynamic_canonicalize_dynamic_symtab \ ((long (*) (bfd *, asymbol **)) _bfd_n1) #define _bfd_nodynamic_get_synthetic_symtab \ ((long (*) (bfd *, long, asymbol **, long, asymbol **, asymbol **)) _bfd_n1) #define _bfd_nodynamic_get_dynamic_reloc_upper_bound _bfd_n1 #define _bfd_nodynamic_canonicalize_dynamic_reloc \ ((long (*) (bfd *, arelent **, asymbol **)) _bfd_n1) /* Generic routine to determine of the given symbol is a local label. */ extern bfd_boolean bfd_generic_is_local_label_name (bfd *, const char *); /* Generic minisymbol routines. */ extern long _bfd_generic_read_minisymbols (bfd *, bfd_boolean, void **, unsigned int *); extern asymbol *_bfd_generic_minisymbol_to_symbol (bfd *, bfd_boolean, const void *, asymbol *); /* Find the nearest line using .stab/.stabstr sections. */ extern bfd_boolean _bfd_stab_section_find_nearest_line (bfd *, asymbol **, asection *, bfd_vma, bfd_boolean *, const char **, const char **, unsigned int *, void **); /* Find the nearest line using DWARF 1 debugging information. */ extern bfd_boolean _bfd_dwarf1_find_nearest_line (bfd *, asection *, asymbol **, bfd_vma, const char **, const char **, unsigned int *); /* Find the nearest line using DWARF 2 debugging information. */ extern bfd_boolean _bfd_dwarf2_find_nearest_line (bfd *, asection *, asymbol **, bfd_vma, const char **, const char **, unsigned int *, unsigned int, void **); /* Find the line using DWARF 2 debugging information. */ extern bfd_boolean _bfd_dwarf2_find_line (bfd *, asymbol **, asymbol *, const char **, unsigned int *, unsigned int, void **); bfd_boolean _bfd_generic_find_line (bfd *, asymbol **, asymbol *, const char **, unsigned int *); /* Find inliner info after calling bfd_find_nearest_line. */ extern bfd_boolean _bfd_dwarf2_find_inliner_info (bfd *, const char **, const char **, unsigned int *, void **); /* Create a new section entry. */ extern struct bfd_hash_entry *bfd_section_hash_newfunc (struct bfd_hash_entry *, struct bfd_hash_table *, const char *); /* A routine to create entries for a bfd_link_hash_table. */ extern struct bfd_hash_entry *_bfd_link_hash_newfunc (struct bfd_hash_entry *entry, struct bfd_hash_table *table, const char *string); /* Initialize a bfd_link_hash_table. */ 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 *), unsigned int); /* Generic link hash table creation routine. */ extern struct bfd_link_hash_table *_bfd_generic_link_hash_table_create (bfd *); /* Generic link hash table destruction routine. */ extern void _bfd_generic_link_hash_table_free (struct bfd_link_hash_table *); /* Generic add symbol routine. */ extern bfd_boolean _bfd_generic_link_add_symbols (bfd *, struct bfd_link_info *); /* Generic add symbol routine. This version is used by targets for which the linker must collect constructors and destructors by name, as the collect2 program does. */ extern bfd_boolean _bfd_generic_link_add_symbols_collect (bfd *, struct bfd_link_info *); /* Generic archive add symbol routine. */ extern bfd_boolean _bfd_generic_link_add_archive_symbols (bfd *, struct bfd_link_info *, bfd_boolean (*) (bfd *, struct bfd_link_info *, bfd_boolean *)); /* Forward declaration to avoid prototype errors. */ typedef struct bfd_link_hash_entry _bfd_link_hash_entry; /* Generic routine to add a single symbol. */ extern bfd_boolean _bfd_generic_link_add_one_symbol (struct bfd_link_info *, bfd *, const char *name, flagword, asection *, bfd_vma, const char *, bfd_boolean copy, bfd_boolean constructor, struct bfd_link_hash_entry **); /* Generic routine to mark section as supplying symbols only. */ extern void _bfd_generic_link_just_syms (asection *, struct bfd_link_info *); /* Generic link routine. */ extern bfd_boolean _bfd_generic_final_link (bfd *, struct bfd_link_info *); extern bfd_boolean _bfd_generic_link_split_section (bfd *, struct bfd_section *); extern void _bfd_generic_section_already_linked (bfd *, struct bfd_section *, struct bfd_link_info *); /* Generic reloc_link_order processing routine. */ extern bfd_boolean _bfd_generic_reloc_link_order (bfd *, struct bfd_link_info *, asection *, struct bfd_link_order *); /* Default link order processing routine. */ extern bfd_boolean _bfd_default_link_order (bfd *, struct bfd_link_info *, asection *, struct bfd_link_order *); /* Count the number of reloc entries in a link order list. */ extern unsigned int _bfd_count_link_order_relocs (struct bfd_link_order *); /* Final link relocation routine. */ extern bfd_reloc_status_type _bfd_final_link_relocate (reloc_howto_type *, bfd *, asection *, bfd_byte *, bfd_vma, bfd_vma, bfd_vma); /* Relocate a particular location by a howto and a value. */ extern bfd_reloc_status_type _bfd_relocate_contents (reloc_howto_type *, bfd *, bfd_vma, bfd_byte *); /* Clear a given location using a given howto. */ extern void _bfd_clear_contents (reloc_howto_type *howto, bfd *input_bfd, bfd_byte *location); /* Link stabs in sections in the first pass. */ extern bfd_boolean _bfd_link_section_stabs (bfd *, struct stab_info *, asection *, asection *, void **, bfd_size_type *); /* Eliminate stabs for discarded functions and symbols. */ extern bfd_boolean _bfd_discard_section_stabs (bfd *, asection *, void *, bfd_boolean (*) (bfd_vma, void *), void *); /* Write out the .stab section when linking stabs in sections. */ extern bfd_boolean _bfd_write_section_stabs (bfd *, struct stab_info *, asection *, void **, bfd_byte *); /* Write out the .stabstr string table when linking stabs in sections. */ extern bfd_boolean _bfd_write_stab_strings (bfd *, struct stab_info *); /* Find an offset within a .stab section when linking stabs in sections. */ extern bfd_vma _bfd_stab_section_offset (asection *, void *, bfd_vma); /* Register a SEC_MERGE section as a candidate for merging. */ extern bfd_boolean _bfd_add_merge_section (bfd *, void **, asection *, void **); /* Attempt to merge SEC_MERGE sections. */ extern bfd_boolean _bfd_merge_sections (bfd *, struct bfd_link_info *, void *, void (*) (bfd *, asection *)); /* Write out a merged section. */ extern bfd_boolean _bfd_write_merged_section (bfd *, asection *, void *); /* Find an offset within a modified SEC_MERGE section. */ extern bfd_vma _bfd_merged_section_offset (bfd *, asection **, void *, bfd_vma); /* Create a string table. */ extern struct bfd_strtab_hash *_bfd_stringtab_init (void); /* Create an XCOFF .debug section style string table. */ extern struct bfd_strtab_hash *_bfd_xcoff_stringtab_init (void); /* Free a string table. */ extern void _bfd_stringtab_free (struct bfd_strtab_hash *); /* Get the size of a string table. */ extern bfd_size_type _bfd_stringtab_size (struct bfd_strtab_hash *); /* Add a string to a string table. */ extern bfd_size_type _bfd_stringtab_add (struct bfd_strtab_hash *, const char *, bfd_boolean hash, bfd_boolean copy); /* Write out a string table. */ extern bfd_boolean _bfd_stringtab_emit (bfd *, struct bfd_strtab_hash *); /* Check that endianness of input and output file match. */ extern bfd_boolean _bfd_generic_verify_endian_match (bfd *, bfd *); /* Macros to tell if bfds are read or write enabled. Note that bfds open for read may be scribbled into if the fd passed to bfd_fdopenr is actually open both for read and write simultaneously. However an output bfd will never be open for read. Therefore sometimes you want to check bfd_read_p or !bfd_read_p, and only sometimes bfd_write_p. */ #define bfd_read_p(abfd) \ ((abfd)->direction == read_direction || (abfd)->direction == both_direction) #define bfd_write_p(abfd) \ ((abfd)->direction == write_direction || (abfd)->direction == both_direction) void bfd_assert (const char*,int); #define BFD_ASSERT(x) \ do { if (!(x)) bfd_assert(__FILE__,__LINE__); } while (0) #define BFD_FAIL() \ do { bfd_assert(__FILE__,__LINE__); } while (0) extern void _bfd_abort (const char *, int, const char *) ATTRIBUTE_NORETURN; /* if gcc >= 2.6, we can give a function name, too */ #if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 6) #define __PRETTY_FUNCTION__ ((char *) NULL) #endif #undef abort #define abort() _bfd_abort (__FILE__, __LINE__, __PRETTY_FUNCTION__) /* Manipulate a system FILE but using BFD's "file_ptr", rather than the system "off_t" or "off64_t", as the offset. */ extern file_ptr real_ftell (FILE *file); extern int real_fseek (FILE *file, file_ptr offset, int whence); extern FILE *real_fopen (const char *filename, const char *modes); /* List of supported target vectors, and the default vector (if bfd_default_vector[0] is NULL, there is no default). */ extern const bfd_target * const *bfd_target_vector; extern const bfd_target *bfd_default_vector[]; /* List of associated target vectors. */ extern const bfd_target * const *bfd_associated_vector; /* Functions shared by the ECOFF and MIPS ELF backends, which have no other common header files. */ #if defined(__STDC__) || defined(ALMOST_STDC) struct ecoff_find_line; #endif extern bfd_boolean _bfd_ecoff_locate_line (bfd *, asection *, bfd_vma, struct ecoff_debug_info * const, const struct ecoff_debug_swap * const, struct ecoff_find_line *, const char **, const char **, unsigned int *); extern bfd_boolean _bfd_ecoff_get_accumulated_pdr (void *, bfd_byte *); extern bfd_boolean _bfd_ecoff_get_accumulated_sym (void *, bfd_byte *); extern bfd_boolean _bfd_ecoff_get_accumulated_ss (void *, bfd_byte *); extern bfd_vma _bfd_get_gp_value (bfd *); extern void _bfd_set_gp_value (bfd *, bfd_vma); /* Function shared by the COFF and ELF SH backends, which have no other common header files. */ #ifndef _bfd_sh_align_load_span extern bfd_boolean _bfd_sh_align_load_span (bfd *, asection *, bfd_byte *, bfd_boolean (*) (bfd *, asection *, void *, bfd_byte *, bfd_vma), void *, bfd_vma **, bfd_vma *, bfd_vma, bfd_vma, bfd_boolean *); #endif /* This is the shape of the elements inside the already_linked hash table. It maps a name onto a list of already_linked elements with the same name. */ struct bfd_section_already_linked_hash_entry { struct bfd_hash_entry root; struct bfd_section_already_linked *entry; }; struct bfd_section_already_linked { struct bfd_section_already_linked *next; asection *sec; }; extern struct bfd_section_already_linked_hash_entry * bfd_section_already_linked_table_lookup (const char *); extern void bfd_section_already_linked_table_insert (struct bfd_section_already_linked_hash_entry *, asection *); extern void bfd_section_already_linked_table_traverse (bfd_boolean (*) (struct bfd_section_already_linked_hash_entry *, void *), void *); extern bfd_vma read_unsigned_leb128 (bfd *, bfd_byte *, unsigned int *); extern bfd_signed_vma read_signed_leb128 (bfd *, bfd_byte *, unsigned int *); /* Extracted from init.c. */ /* Extracted from libbfd.c. */ bfd_boolean bfd_write_bigendian_4byte_int (bfd *, unsigned int); unsigned int bfd_log2 (bfd_vma x); /* Extracted from bfdio.c. */ struct bfd_iovec { /* To avoid problems with macros, a "b" rather than "f" prefix is prepended to each method name. */ /* Attempt to read/write NBYTES on ABFD's IOSTREAM storing/fetching bytes starting at PTR. Return the number of bytes actually transfered (a read past end-of-file returns less than NBYTES), or -1 (setting <>) if an error occurs. */ file_ptr (*bread) (struct bfd *abfd, void *ptr, file_ptr nbytes); file_ptr (*bwrite) (struct bfd *abfd, const void *ptr, file_ptr nbytes); /* Return the current IOSTREAM file offset, or -1 (setting <> if an error occurs. */ file_ptr (*btell) (struct bfd *abfd); /* For the following, on successful completion a value of 0 is returned. Otherwise, a value of -1 is returned (and <> is set). */ int (*bseek) (struct bfd *abfd, file_ptr offset, int whence); int (*bclose) (struct bfd *abfd); int (*bflush) (struct bfd *abfd); int (*bstat) (struct bfd *abfd, struct stat *sb); }; /* Extracted from bfdwin.c. */ struct _bfd_window_internal { struct _bfd_window_internal *next; void *data; bfd_size_type size; int refcount : 31; /* should be enough... */ unsigned mapped : 1; /* 1 = mmap, 0 = malloc */ }; /* Extracted from cache.c. */ bfd_boolean bfd_cache_init (bfd *abfd); bfd_boolean bfd_cache_close (bfd *abfd); FILE* bfd_open_file (bfd *abfd); /* Extracted from reloc.c. */ #ifdef _BFD_MAKE_TABLE_bfd_reloc_code_real static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_64", "BFD_RELOC_32", "BFD_RELOC_26", "BFD_RELOC_24", "BFD_RELOC_16", "BFD_RELOC_14", "BFD_RELOC_8", "BFD_RELOC_64_PCREL", "BFD_RELOC_32_PCREL", "BFD_RELOC_24_PCREL", "BFD_RELOC_16_PCREL", "BFD_RELOC_12_PCREL", "BFD_RELOC_8_PCREL", "BFD_RELOC_32_SECREL", "BFD_RELOC_32_GOT_PCREL", "BFD_RELOC_16_GOT_PCREL", "BFD_RELOC_8_GOT_PCREL", "BFD_RELOC_32_GOTOFF", "BFD_RELOC_16_GOTOFF", "BFD_RELOC_LO16_GOTOFF", "BFD_RELOC_HI16_GOTOFF", "BFD_RELOC_HI16_S_GOTOFF", "BFD_RELOC_8_GOTOFF", "BFD_RELOC_64_PLT_PCREL", "BFD_RELOC_32_PLT_PCREL", "BFD_RELOC_24_PLT_PCREL", "BFD_RELOC_16_PLT_PCREL", "BFD_RELOC_8_PLT_PCREL", "BFD_RELOC_64_PLTOFF", "BFD_RELOC_32_PLTOFF", "BFD_RELOC_16_PLTOFF", "BFD_RELOC_LO16_PLTOFF", "BFD_RELOC_HI16_PLTOFF", "BFD_RELOC_HI16_S_PLTOFF", "BFD_RELOC_8_PLTOFF", "BFD_RELOC_68K_GLOB_DAT", "BFD_RELOC_68K_JMP_SLOT", "BFD_RELOC_68K_RELATIVE", "BFD_RELOC_32_BASEREL", "BFD_RELOC_16_BASEREL", "BFD_RELOC_LO16_BASEREL", "BFD_RELOC_HI16_BASEREL", "BFD_RELOC_HI16_S_BASEREL", "BFD_RELOC_8_BASEREL", "BFD_RELOC_RVA", "BFD_RELOC_8_FFnn", "BFD_RELOC_32_PCREL_S2", "BFD_RELOC_16_PCREL_S2", "BFD_RELOC_23_PCREL_S2", "BFD_RELOC_HI22", "BFD_RELOC_LO10", "BFD_RELOC_GPREL16", "BFD_RELOC_GPREL32", "BFD_RELOC_I960_CALLJ", "BFD_RELOC_NONE", "BFD_RELOC_SPARC_WDISP22", "BFD_RELOC_SPARC22", "BFD_RELOC_SPARC13", "BFD_RELOC_SPARC_GOT10", "BFD_RELOC_SPARC_GOT13", "BFD_RELOC_SPARC_GOT22", "BFD_RELOC_SPARC_PC10", "BFD_RELOC_SPARC_PC22", "BFD_RELOC_SPARC_WPLT30", "BFD_RELOC_SPARC_COPY", "BFD_RELOC_SPARC_GLOB_DAT", "BFD_RELOC_SPARC_JMP_SLOT", "BFD_RELOC_SPARC_RELATIVE", "BFD_RELOC_SPARC_UA16", "BFD_RELOC_SPARC_UA32", "BFD_RELOC_SPARC_UA64", "BFD_RELOC_SPARC_BASE13", "BFD_RELOC_SPARC_BASE22", "BFD_RELOC_SPARC_10", "BFD_RELOC_SPARC_11", "BFD_RELOC_SPARC_OLO10", "BFD_RELOC_SPARC_HH22", "BFD_RELOC_SPARC_HM10", "BFD_RELOC_SPARC_LM22", "BFD_RELOC_SPARC_PC_HH22", "BFD_RELOC_SPARC_PC_HM10", "BFD_RELOC_SPARC_PC_LM22", "BFD_RELOC_SPARC_WDISP16", "BFD_RELOC_SPARC_WDISP19", "BFD_RELOC_SPARC_7", "BFD_RELOC_SPARC_6", "BFD_RELOC_SPARC_5", "BFD_RELOC_SPARC_PLT32", "BFD_RELOC_SPARC_PLT64", "BFD_RELOC_SPARC_HIX22", "BFD_RELOC_SPARC_LOX10", "BFD_RELOC_SPARC_H44", "BFD_RELOC_SPARC_M44", "BFD_RELOC_SPARC_L44", "BFD_RELOC_SPARC_REGISTER", "BFD_RELOC_SPARC_REV32", "BFD_RELOC_SPARC_TLS_GD_HI22", "BFD_RELOC_SPARC_TLS_GD_LO10", "BFD_RELOC_SPARC_TLS_GD_ADD", "BFD_RELOC_SPARC_TLS_GD_CALL", "BFD_RELOC_SPARC_TLS_LDM_HI22", "BFD_RELOC_SPARC_TLS_LDM_LO10", "BFD_RELOC_SPARC_TLS_LDM_ADD", "BFD_RELOC_SPARC_TLS_LDM_CALL", "BFD_RELOC_SPARC_TLS_LDO_HIX22", "BFD_RELOC_SPARC_TLS_LDO_LOX10", "BFD_RELOC_SPARC_TLS_LDO_ADD", "BFD_RELOC_SPARC_TLS_IE_HI22", "BFD_RELOC_SPARC_TLS_IE_LO10", "BFD_RELOC_SPARC_TLS_IE_LD", "BFD_RELOC_SPARC_TLS_IE_LDX", "BFD_RELOC_SPARC_TLS_IE_ADD", "BFD_RELOC_SPARC_TLS_LE_HIX22", "BFD_RELOC_SPARC_TLS_LE_LOX10", "BFD_RELOC_SPARC_TLS_DTPMOD32", "BFD_RELOC_SPARC_TLS_DTPMOD64", "BFD_RELOC_SPARC_TLS_DTPOFF32", "BFD_RELOC_SPARC_TLS_DTPOFF64", "BFD_RELOC_SPARC_TLS_TPOFF32", "BFD_RELOC_SPARC_TLS_TPOFF64", "BFD_RELOC_SPU_IMM7", "BFD_RELOC_SPU_IMM8", "BFD_RELOC_SPU_IMM10", "BFD_RELOC_SPU_IMM10W", "BFD_RELOC_SPU_IMM16", "BFD_RELOC_SPU_IMM16W", "BFD_RELOC_SPU_IMM18", "BFD_RELOC_SPU_PCREL9a", "BFD_RELOC_SPU_PCREL9b", "BFD_RELOC_SPU_PCREL16", "BFD_RELOC_SPU_LO16", "BFD_RELOC_SPU_HI16", "BFD_RELOC_SPU_PPU32", "BFD_RELOC_SPU_PPU64", "BFD_RELOC_ALPHA_GPDISP_HI16", "BFD_RELOC_ALPHA_GPDISP_LO16", "BFD_RELOC_ALPHA_GPDISP", "BFD_RELOC_ALPHA_LITERAL", "BFD_RELOC_ALPHA_ELF_LITERAL", "BFD_RELOC_ALPHA_LITUSE", "BFD_RELOC_ALPHA_HINT", "BFD_RELOC_ALPHA_LINKAGE", "BFD_RELOC_ALPHA_CODEADDR", "BFD_RELOC_ALPHA_GPREL_HI16", "BFD_RELOC_ALPHA_GPREL_LO16", "BFD_RELOC_ALPHA_BRSGP", "BFD_RELOC_ALPHA_TLSGD", "BFD_RELOC_ALPHA_TLSLDM", "BFD_RELOC_ALPHA_DTPMOD64", "BFD_RELOC_ALPHA_GOTDTPREL16", "BFD_RELOC_ALPHA_DTPREL64", "BFD_RELOC_ALPHA_DTPREL_HI16", "BFD_RELOC_ALPHA_DTPREL_LO16", "BFD_RELOC_ALPHA_DTPREL16", "BFD_RELOC_ALPHA_GOTTPREL16", "BFD_RELOC_ALPHA_TPREL64", "BFD_RELOC_ALPHA_TPREL_HI16", "BFD_RELOC_ALPHA_TPREL_LO16", "BFD_RELOC_ALPHA_TPREL16", "BFD_RELOC_MIPS_JMP", "BFD_RELOC_MIPS16_JMP", "BFD_RELOC_MIPS16_GPREL", "BFD_RELOC_HI16", "BFD_RELOC_HI16_S", "BFD_RELOC_LO16", "BFD_RELOC_HI16_PCREL", "BFD_RELOC_HI16_S_PCREL", "BFD_RELOC_LO16_PCREL", "BFD_RELOC_MIPS16_HI16", "BFD_RELOC_MIPS16_HI16_S", "BFD_RELOC_MIPS16_LO16", "BFD_RELOC_MIPS_LITERAL", "BFD_RELOC_MIPS_GOT16", "BFD_RELOC_MIPS_CALL16", "BFD_RELOC_MIPS_GOT_HI16", "BFD_RELOC_MIPS_GOT_LO16", "BFD_RELOC_MIPS_CALL_HI16", "BFD_RELOC_MIPS_CALL_LO16", "BFD_RELOC_MIPS_SUB", "BFD_RELOC_MIPS_GOT_PAGE", "BFD_RELOC_MIPS_GOT_OFST", "BFD_RELOC_MIPS_GOT_DISP", "BFD_RELOC_MIPS_SHIFT5", "BFD_RELOC_MIPS_SHIFT6", "BFD_RELOC_MIPS_INSERT_A", "BFD_RELOC_MIPS_INSERT_B", "BFD_RELOC_MIPS_DELETE", "BFD_RELOC_MIPS_HIGHEST", "BFD_RELOC_MIPS_HIGHER", "BFD_RELOC_MIPS_SCN_DISP", "BFD_RELOC_MIPS_REL16", "BFD_RELOC_MIPS_RELGOT", "BFD_RELOC_MIPS_JALR", "BFD_RELOC_MIPS_TLS_DTPMOD32", "BFD_RELOC_MIPS_TLS_DTPREL32", "BFD_RELOC_MIPS_TLS_DTPMOD64", "BFD_RELOC_MIPS_TLS_DTPREL64", "BFD_RELOC_MIPS_TLS_GD", "BFD_RELOC_MIPS_TLS_LDM", "BFD_RELOC_MIPS_TLS_DTPREL_HI16", "BFD_RELOC_MIPS_TLS_DTPREL_LO16", "BFD_RELOC_MIPS_TLS_GOTTPREL", "BFD_RELOC_MIPS_TLS_TPREL32", "BFD_RELOC_MIPS_TLS_TPREL64", "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", "BFD_RELOC_FRV_HI16", "BFD_RELOC_FRV_GPREL12", "BFD_RELOC_FRV_GPRELU12", "BFD_RELOC_FRV_GPREL32", "BFD_RELOC_FRV_GPRELHI", "BFD_RELOC_FRV_GPRELLO", "BFD_RELOC_FRV_GOT12", "BFD_RELOC_FRV_GOTHI", "BFD_RELOC_FRV_GOTLO", "BFD_RELOC_FRV_FUNCDESC", "BFD_RELOC_FRV_FUNCDESC_GOT12", "BFD_RELOC_FRV_FUNCDESC_GOTHI", "BFD_RELOC_FRV_FUNCDESC_GOTLO", "BFD_RELOC_FRV_FUNCDESC_VALUE", "BFD_RELOC_FRV_FUNCDESC_GOTOFF12", "BFD_RELOC_FRV_FUNCDESC_GOTOFFHI", "BFD_RELOC_FRV_FUNCDESC_GOTOFFLO", "BFD_RELOC_FRV_GOTOFF12", "BFD_RELOC_FRV_GOTOFFHI", "BFD_RELOC_FRV_GOTOFFLO", "BFD_RELOC_FRV_GETTLSOFF", "BFD_RELOC_FRV_TLSDESC_VALUE", "BFD_RELOC_FRV_GOTTLSDESC12", "BFD_RELOC_FRV_GOTTLSDESCHI", "BFD_RELOC_FRV_GOTTLSDESCLO", "BFD_RELOC_FRV_TLSMOFF12", "BFD_RELOC_FRV_TLSMOFFHI", "BFD_RELOC_FRV_TLSMOFFLO", "BFD_RELOC_FRV_GOTTLSOFF12", "BFD_RELOC_FRV_GOTTLSOFFHI", "BFD_RELOC_FRV_GOTTLSOFFLO", "BFD_RELOC_FRV_TLSOFF", "BFD_RELOC_FRV_TLSDESC_RELAX", "BFD_RELOC_FRV_GETTLSOFF_RELAX", "BFD_RELOC_FRV_TLSOFF_RELAX", "BFD_RELOC_FRV_TLSMOFF", "BFD_RELOC_MN10300_GOTOFF24", "BFD_RELOC_MN10300_GOT32", "BFD_RELOC_MN10300_GOT24", "BFD_RELOC_MN10300_GOT16", "BFD_RELOC_MN10300_COPY", "BFD_RELOC_MN10300_GLOB_DAT", "BFD_RELOC_MN10300_JMP_SLOT", "BFD_RELOC_MN10300_RELATIVE", "BFD_RELOC_386_GOT32", "BFD_RELOC_386_PLT32", "BFD_RELOC_386_COPY", "BFD_RELOC_386_GLOB_DAT", "BFD_RELOC_386_JUMP_SLOT", "BFD_RELOC_386_RELATIVE", "BFD_RELOC_386_GOTOFF", "BFD_RELOC_386_GOTPC", "BFD_RELOC_386_TLS_TPOFF", "BFD_RELOC_386_TLS_IE", "BFD_RELOC_386_TLS_GOTIE", "BFD_RELOC_386_TLS_LE", "BFD_RELOC_386_TLS_GD", "BFD_RELOC_386_TLS_LDM", "BFD_RELOC_386_TLS_LDO_32", "BFD_RELOC_386_TLS_IE_32", "BFD_RELOC_386_TLS_LE_32", "BFD_RELOC_386_TLS_DTPMOD32", "BFD_RELOC_386_TLS_DTPOFF32", "BFD_RELOC_386_TLS_TPOFF32", "BFD_RELOC_386_TLS_GOTDESC", "BFD_RELOC_386_TLS_DESC_CALL", "BFD_RELOC_386_TLS_DESC", "BFD_RELOC_X86_64_GOT32", "BFD_RELOC_X86_64_PLT32", "BFD_RELOC_X86_64_COPY", "BFD_RELOC_X86_64_GLOB_DAT", "BFD_RELOC_X86_64_JUMP_SLOT", "BFD_RELOC_X86_64_RELATIVE", "BFD_RELOC_X86_64_GOTPCREL", "BFD_RELOC_X86_64_32S", "BFD_RELOC_X86_64_DTPMOD64", "BFD_RELOC_X86_64_DTPOFF64", "BFD_RELOC_X86_64_TPOFF64", "BFD_RELOC_X86_64_TLSGD", "BFD_RELOC_X86_64_TLSLD", "BFD_RELOC_X86_64_DTPOFF32", "BFD_RELOC_X86_64_GOTTPOFF", "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", "BFD_RELOC_NS32K_IMM_8", "BFD_RELOC_NS32K_IMM_16", "BFD_RELOC_NS32K_IMM_32", "BFD_RELOC_NS32K_IMM_8_PCREL", "BFD_RELOC_NS32K_IMM_16_PCREL", "BFD_RELOC_NS32K_IMM_32_PCREL", "BFD_RELOC_NS32K_DISP_8", "BFD_RELOC_NS32K_DISP_16", "BFD_RELOC_NS32K_DISP_32", "BFD_RELOC_NS32K_DISP_8_PCREL", "BFD_RELOC_NS32K_DISP_16_PCREL", "BFD_RELOC_NS32K_DISP_32_PCREL", "BFD_RELOC_PDP11_DISP_8_PCREL", "BFD_RELOC_PDP11_DISP_6_PCREL", "BFD_RELOC_PJ_CODE_HI16", "BFD_RELOC_PJ_CODE_LO16", "BFD_RELOC_PJ_CODE_DIR16", "BFD_RELOC_PJ_CODE_DIR32", "BFD_RELOC_PJ_CODE_REL16", "BFD_RELOC_PJ_CODE_REL32", "BFD_RELOC_PPC_B26", "BFD_RELOC_PPC_BA26", "BFD_RELOC_PPC_TOC16", "BFD_RELOC_PPC_B16", "BFD_RELOC_PPC_B16_BRTAKEN", "BFD_RELOC_PPC_B16_BRNTAKEN", "BFD_RELOC_PPC_BA16", "BFD_RELOC_PPC_BA16_BRTAKEN", "BFD_RELOC_PPC_BA16_BRNTAKEN", "BFD_RELOC_PPC_COPY", "BFD_RELOC_PPC_GLOB_DAT", "BFD_RELOC_PPC_JMP_SLOT", "BFD_RELOC_PPC_RELATIVE", "BFD_RELOC_PPC_LOCAL24PC", "BFD_RELOC_PPC_EMB_NADDR32", "BFD_RELOC_PPC_EMB_NADDR16", "BFD_RELOC_PPC_EMB_NADDR16_LO", "BFD_RELOC_PPC_EMB_NADDR16_HI", "BFD_RELOC_PPC_EMB_NADDR16_HA", "BFD_RELOC_PPC_EMB_SDAI16", "BFD_RELOC_PPC_EMB_SDA2I16", "BFD_RELOC_PPC_EMB_SDA2REL", "BFD_RELOC_PPC_EMB_SDA21", "BFD_RELOC_PPC_EMB_MRKREF", "BFD_RELOC_PPC_EMB_RELSEC16", "BFD_RELOC_PPC_EMB_RELST_LO", "BFD_RELOC_PPC_EMB_RELST_HI", "BFD_RELOC_PPC_EMB_RELST_HA", "BFD_RELOC_PPC_EMB_BIT_FLD", "BFD_RELOC_PPC_EMB_RELSDA", "BFD_RELOC_PPC64_HIGHER", "BFD_RELOC_PPC64_HIGHER_S", "BFD_RELOC_PPC64_HIGHEST", "BFD_RELOC_PPC64_HIGHEST_S", "BFD_RELOC_PPC64_TOC16_LO", "BFD_RELOC_PPC64_TOC16_HI", "BFD_RELOC_PPC64_TOC16_HA", "BFD_RELOC_PPC64_TOC", "BFD_RELOC_PPC64_PLTGOT16", "BFD_RELOC_PPC64_PLTGOT16_LO", "BFD_RELOC_PPC64_PLTGOT16_HI", "BFD_RELOC_PPC64_PLTGOT16_HA", "BFD_RELOC_PPC64_ADDR16_DS", "BFD_RELOC_PPC64_ADDR16_LO_DS", "BFD_RELOC_PPC64_GOT16_DS", "BFD_RELOC_PPC64_GOT16_LO_DS", "BFD_RELOC_PPC64_PLT16_LO_DS", "BFD_RELOC_PPC64_SECTOFF_DS", "BFD_RELOC_PPC64_SECTOFF_LO_DS", "BFD_RELOC_PPC64_TOC16_DS", "BFD_RELOC_PPC64_TOC16_LO_DS", "BFD_RELOC_PPC64_PLTGOT16_DS", "BFD_RELOC_PPC64_PLTGOT16_LO_DS", "BFD_RELOC_PPC_TLS", + "BFD_RELOC_PPC_TLSGD", + "BFD_RELOC_PPC_TLSLD", "BFD_RELOC_PPC_DTPMOD", "BFD_RELOC_PPC_TPREL16", "BFD_RELOC_PPC_TPREL16_LO", "BFD_RELOC_PPC_TPREL16_HI", "BFD_RELOC_PPC_TPREL16_HA", "BFD_RELOC_PPC_TPREL", "BFD_RELOC_PPC_DTPREL16", "BFD_RELOC_PPC_DTPREL16_LO", "BFD_RELOC_PPC_DTPREL16_HI", "BFD_RELOC_PPC_DTPREL16_HA", "BFD_RELOC_PPC_DTPREL", "BFD_RELOC_PPC_GOT_TLSGD16", "BFD_RELOC_PPC_GOT_TLSGD16_LO", "BFD_RELOC_PPC_GOT_TLSGD16_HI", "BFD_RELOC_PPC_GOT_TLSGD16_HA", "BFD_RELOC_PPC_GOT_TLSLD16", "BFD_RELOC_PPC_GOT_TLSLD16_LO", "BFD_RELOC_PPC_GOT_TLSLD16_HI", "BFD_RELOC_PPC_GOT_TLSLD16_HA", "BFD_RELOC_PPC_GOT_TPREL16", "BFD_RELOC_PPC_GOT_TPREL16_LO", "BFD_RELOC_PPC_GOT_TPREL16_HI", "BFD_RELOC_PPC_GOT_TPREL16_HA", "BFD_RELOC_PPC_GOT_DTPREL16", "BFD_RELOC_PPC_GOT_DTPREL16_LO", "BFD_RELOC_PPC_GOT_DTPREL16_HI", "BFD_RELOC_PPC_GOT_DTPREL16_HA", "BFD_RELOC_PPC64_TPREL16_DS", "BFD_RELOC_PPC64_TPREL16_LO_DS", "BFD_RELOC_PPC64_TPREL16_HIGHER", "BFD_RELOC_PPC64_TPREL16_HIGHERA", "BFD_RELOC_PPC64_TPREL16_HIGHEST", "BFD_RELOC_PPC64_TPREL16_HIGHESTA", "BFD_RELOC_PPC64_DTPREL16_DS", "BFD_RELOC_PPC64_DTPREL16_LO_DS", "BFD_RELOC_PPC64_DTPREL16_HIGHER", "BFD_RELOC_PPC64_DTPREL16_HIGHERA", "BFD_RELOC_PPC64_DTPREL16_HIGHEST", "BFD_RELOC_PPC64_DTPREL16_HIGHESTA", "BFD_RELOC_I370_D12", "BFD_RELOC_CTOR", "BFD_RELOC_ARM_PCREL_BRANCH", "BFD_RELOC_ARM_PCREL_BLX", "BFD_RELOC_THUMB_PCREL_BLX", "BFD_RELOC_ARM_PCREL_CALL", "BFD_RELOC_ARM_PCREL_JUMP", "BFD_RELOC_THUMB_PCREL_BRANCH7", "BFD_RELOC_THUMB_PCREL_BRANCH9", "BFD_RELOC_THUMB_PCREL_BRANCH12", "BFD_RELOC_THUMB_PCREL_BRANCH20", "BFD_RELOC_THUMB_PCREL_BRANCH23", "BFD_RELOC_THUMB_PCREL_BRANCH25", "BFD_RELOC_ARM_OFFSET_IMM", "BFD_RELOC_ARM_THUMB_OFFSET", "BFD_RELOC_ARM_TARGET1", "BFD_RELOC_ARM_ROSEGREL32", "BFD_RELOC_ARM_SBREL32", "BFD_RELOC_ARM_TARGET2", "BFD_RELOC_ARM_PREL31", "BFD_RELOC_ARM_MOVW", "BFD_RELOC_ARM_MOVT", "BFD_RELOC_ARM_MOVW_PCREL", "BFD_RELOC_ARM_MOVT_PCREL", "BFD_RELOC_ARM_THUMB_MOVW", "BFD_RELOC_ARM_THUMB_MOVT", "BFD_RELOC_ARM_THUMB_MOVW_PCREL", "BFD_RELOC_ARM_THUMB_MOVT_PCREL", "BFD_RELOC_ARM_JUMP_SLOT", "BFD_RELOC_ARM_GLOB_DAT", "BFD_RELOC_ARM_GOT32", "BFD_RELOC_ARM_PLT32", "BFD_RELOC_ARM_RELATIVE", "BFD_RELOC_ARM_GOTOFF", "BFD_RELOC_ARM_GOTPC", "BFD_RELOC_ARM_TLS_GD32", "BFD_RELOC_ARM_TLS_LDO32", "BFD_RELOC_ARM_TLS_LDM32", "BFD_RELOC_ARM_TLS_DTPOFF32", "BFD_RELOC_ARM_TLS_DTPMOD32", "BFD_RELOC_ARM_TLS_TPOFF32", "BFD_RELOC_ARM_TLS_IE32", "BFD_RELOC_ARM_TLS_LE32", "BFD_RELOC_ARM_ALU_PC_G0_NC", "BFD_RELOC_ARM_ALU_PC_G0", "BFD_RELOC_ARM_ALU_PC_G1_NC", "BFD_RELOC_ARM_ALU_PC_G1", "BFD_RELOC_ARM_ALU_PC_G2", "BFD_RELOC_ARM_LDR_PC_G0", "BFD_RELOC_ARM_LDR_PC_G1", "BFD_RELOC_ARM_LDR_PC_G2", "BFD_RELOC_ARM_LDRS_PC_G0", "BFD_RELOC_ARM_LDRS_PC_G1", "BFD_RELOC_ARM_LDRS_PC_G2", "BFD_RELOC_ARM_LDC_PC_G0", "BFD_RELOC_ARM_LDC_PC_G1", "BFD_RELOC_ARM_LDC_PC_G2", "BFD_RELOC_ARM_ALU_SB_G0_NC", "BFD_RELOC_ARM_ALU_SB_G0", "BFD_RELOC_ARM_ALU_SB_G1_NC", "BFD_RELOC_ARM_ALU_SB_G1", "BFD_RELOC_ARM_ALU_SB_G2", "BFD_RELOC_ARM_LDR_SB_G0", "BFD_RELOC_ARM_LDR_SB_G1", "BFD_RELOC_ARM_LDR_SB_G2", "BFD_RELOC_ARM_LDRS_SB_G0", "BFD_RELOC_ARM_LDRS_SB_G1", "BFD_RELOC_ARM_LDRS_SB_G2", "BFD_RELOC_ARM_LDC_SB_G0", "BFD_RELOC_ARM_LDC_SB_G1", "BFD_RELOC_ARM_LDC_SB_G2", "BFD_RELOC_ARM_IMMEDIATE", "BFD_RELOC_ARM_ADRL_IMMEDIATE", "BFD_RELOC_ARM_T32_IMMEDIATE", "BFD_RELOC_ARM_T32_ADD_IMM", "BFD_RELOC_ARM_T32_IMM12", "BFD_RELOC_ARM_T32_ADD_PC12", "BFD_RELOC_ARM_SHIFT_IMM", "BFD_RELOC_ARM_SMC", "BFD_RELOC_ARM_SWI", "BFD_RELOC_ARM_MULTI", "BFD_RELOC_ARM_CP_OFF_IMM", "BFD_RELOC_ARM_CP_OFF_IMM_S2", "BFD_RELOC_ARM_T32_CP_OFF_IMM", "BFD_RELOC_ARM_T32_CP_OFF_IMM_S2", "BFD_RELOC_ARM_ADR_IMM", "BFD_RELOC_ARM_LDR_IMM", "BFD_RELOC_ARM_LITERAL", "BFD_RELOC_ARM_IN_POOL", "BFD_RELOC_ARM_OFFSET_IMM8", "BFD_RELOC_ARM_T32_OFFSET_U8", "BFD_RELOC_ARM_T32_OFFSET_IMM", "BFD_RELOC_ARM_HWLITERAL", "BFD_RELOC_ARM_THUMB_ADD", "BFD_RELOC_ARM_THUMB_IMM", "BFD_RELOC_ARM_THUMB_SHIFT", "BFD_RELOC_SH_PCDISP8BY2", "BFD_RELOC_SH_PCDISP12BY2", "BFD_RELOC_SH_IMM3", "BFD_RELOC_SH_IMM3U", "BFD_RELOC_SH_DISP12", "BFD_RELOC_SH_DISP12BY2", "BFD_RELOC_SH_DISP12BY4", "BFD_RELOC_SH_DISP12BY8", "BFD_RELOC_SH_DISP20", "BFD_RELOC_SH_DISP20BY8", "BFD_RELOC_SH_IMM4", "BFD_RELOC_SH_IMM4BY2", "BFD_RELOC_SH_IMM4BY4", "BFD_RELOC_SH_IMM8", "BFD_RELOC_SH_IMM8BY2", "BFD_RELOC_SH_IMM8BY4", "BFD_RELOC_SH_PCRELIMM8BY2", "BFD_RELOC_SH_PCRELIMM8BY4", "BFD_RELOC_SH_SWITCH16", "BFD_RELOC_SH_SWITCH32", "BFD_RELOC_SH_USES", "BFD_RELOC_SH_COUNT", "BFD_RELOC_SH_ALIGN", "BFD_RELOC_SH_CODE", "BFD_RELOC_SH_DATA", "BFD_RELOC_SH_LABEL", "BFD_RELOC_SH_LOOP_START", "BFD_RELOC_SH_LOOP_END", "BFD_RELOC_SH_COPY", "BFD_RELOC_SH_GLOB_DAT", "BFD_RELOC_SH_JMP_SLOT", "BFD_RELOC_SH_RELATIVE", "BFD_RELOC_SH_GOTPC", "BFD_RELOC_SH_GOT_LOW16", "BFD_RELOC_SH_GOT_MEDLOW16", "BFD_RELOC_SH_GOT_MEDHI16", "BFD_RELOC_SH_GOT_HI16", "BFD_RELOC_SH_GOTPLT_LOW16", "BFD_RELOC_SH_GOTPLT_MEDLOW16", "BFD_RELOC_SH_GOTPLT_MEDHI16", "BFD_RELOC_SH_GOTPLT_HI16", "BFD_RELOC_SH_PLT_LOW16", "BFD_RELOC_SH_PLT_MEDLOW16", "BFD_RELOC_SH_PLT_MEDHI16", "BFD_RELOC_SH_PLT_HI16", "BFD_RELOC_SH_GOTOFF_LOW16", "BFD_RELOC_SH_GOTOFF_MEDLOW16", "BFD_RELOC_SH_GOTOFF_MEDHI16", "BFD_RELOC_SH_GOTOFF_HI16", "BFD_RELOC_SH_GOTPC_LOW16", "BFD_RELOC_SH_GOTPC_MEDLOW16", "BFD_RELOC_SH_GOTPC_MEDHI16", "BFD_RELOC_SH_GOTPC_HI16", "BFD_RELOC_SH_COPY64", "BFD_RELOC_SH_GLOB_DAT64", "BFD_RELOC_SH_JMP_SLOT64", "BFD_RELOC_SH_RELATIVE64", "BFD_RELOC_SH_GOT10BY4", "BFD_RELOC_SH_GOT10BY8", "BFD_RELOC_SH_GOTPLT10BY4", "BFD_RELOC_SH_GOTPLT10BY8", "BFD_RELOC_SH_GOTPLT32", "BFD_RELOC_SH_SHMEDIA_CODE", "BFD_RELOC_SH_IMMU5", "BFD_RELOC_SH_IMMS6", "BFD_RELOC_SH_IMMS6BY32", "BFD_RELOC_SH_IMMU6", "BFD_RELOC_SH_IMMS10", "BFD_RELOC_SH_IMMS10BY2", "BFD_RELOC_SH_IMMS10BY4", "BFD_RELOC_SH_IMMS10BY8", "BFD_RELOC_SH_IMMS16", "BFD_RELOC_SH_IMMU16", "BFD_RELOC_SH_IMM_LOW16", "BFD_RELOC_SH_IMM_LOW16_PCREL", "BFD_RELOC_SH_IMM_MEDLOW16", "BFD_RELOC_SH_IMM_MEDLOW16_PCREL", "BFD_RELOC_SH_IMM_MEDHI16", "BFD_RELOC_SH_IMM_MEDHI16_PCREL", "BFD_RELOC_SH_IMM_HI16", "BFD_RELOC_SH_IMM_HI16_PCREL", "BFD_RELOC_SH_PT_16", "BFD_RELOC_SH_TLS_GD_32", "BFD_RELOC_SH_TLS_LD_32", "BFD_RELOC_SH_TLS_LDO_32", "BFD_RELOC_SH_TLS_IE_32", "BFD_RELOC_SH_TLS_LE_32", "BFD_RELOC_SH_TLS_DTPMOD32", "BFD_RELOC_SH_TLS_DTPOFF32", "BFD_RELOC_SH_TLS_TPOFF32", "BFD_RELOC_ARC_B22_PCREL", "BFD_RELOC_ARC_B26", "BFD_RELOC_BFIN_16_IMM", "BFD_RELOC_BFIN_16_HIGH", "BFD_RELOC_BFIN_4_PCREL", "BFD_RELOC_BFIN_5_PCREL", "BFD_RELOC_BFIN_16_LOW", "BFD_RELOC_BFIN_10_PCREL", "BFD_RELOC_BFIN_11_PCREL", "BFD_RELOC_BFIN_12_PCREL_JUMP", "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", "BFD_ARELOC_BFIN_CONST", "BFD_ARELOC_BFIN_ADD", "BFD_ARELOC_BFIN_SUB", "BFD_ARELOC_BFIN_MULT", "BFD_ARELOC_BFIN_DIV", "BFD_ARELOC_BFIN_MOD", "BFD_ARELOC_BFIN_LSHIFT", "BFD_ARELOC_BFIN_RSHIFT", "BFD_ARELOC_BFIN_AND", "BFD_ARELOC_BFIN_OR", "BFD_ARELOC_BFIN_XOR", "BFD_ARELOC_BFIN_LAND", "BFD_ARELOC_BFIN_LOR", "BFD_ARELOC_BFIN_LEN", "BFD_ARELOC_BFIN_NEG", "BFD_ARELOC_BFIN_COMP", "BFD_ARELOC_BFIN_PAGE", "BFD_ARELOC_BFIN_HWPAGE", "BFD_ARELOC_BFIN_ADDR", "BFD_RELOC_D10V_10_PCREL_R", "BFD_RELOC_D10V_10_PCREL_L", "BFD_RELOC_D10V_18", "BFD_RELOC_D10V_18_PCREL", "BFD_RELOC_D30V_6", "BFD_RELOC_D30V_9_PCREL", "BFD_RELOC_D30V_9_PCREL_R", "BFD_RELOC_D30V_15", "BFD_RELOC_D30V_15_PCREL", "BFD_RELOC_D30V_15_PCREL_R", "BFD_RELOC_D30V_21", "BFD_RELOC_D30V_21_PCREL", "BFD_RELOC_D30V_21_PCREL_R", "BFD_RELOC_D30V_32", "BFD_RELOC_D30V_32_PCREL", "BFD_RELOC_DLX_HI16_S", "BFD_RELOC_DLX_LO16", "BFD_RELOC_DLX_JMP26", "BFD_RELOC_M32C_HI8", "BFD_RELOC_M32C_RL_JUMP", "BFD_RELOC_M32C_RL_1ADDR", "BFD_RELOC_M32C_RL_2ADDR", "BFD_RELOC_M32R_24", "BFD_RELOC_M32R_10_PCREL", "BFD_RELOC_M32R_18_PCREL", "BFD_RELOC_M32R_26_PCREL", "BFD_RELOC_M32R_HI16_ULO", "BFD_RELOC_M32R_HI16_SLO", "BFD_RELOC_M32R_LO16", "BFD_RELOC_M32R_SDA16", "BFD_RELOC_M32R_GOT24", "BFD_RELOC_M32R_26_PLTREL", "BFD_RELOC_M32R_COPY", "BFD_RELOC_M32R_GLOB_DAT", "BFD_RELOC_M32R_JMP_SLOT", "BFD_RELOC_M32R_RELATIVE", "BFD_RELOC_M32R_GOTOFF", "BFD_RELOC_M32R_GOTOFF_HI_ULO", "BFD_RELOC_M32R_GOTOFF_HI_SLO", "BFD_RELOC_M32R_GOTOFF_LO", "BFD_RELOC_M32R_GOTPC24", "BFD_RELOC_M32R_GOT16_HI_ULO", "BFD_RELOC_M32R_GOT16_HI_SLO", "BFD_RELOC_M32R_GOT16_LO", "BFD_RELOC_M32R_GOTPC_HI_ULO", "BFD_RELOC_M32R_GOTPC_HI_SLO", "BFD_RELOC_M32R_GOTPC_LO", "BFD_RELOC_V850_9_PCREL", "BFD_RELOC_V850_22_PCREL", "BFD_RELOC_V850_SDA_16_16_OFFSET", "BFD_RELOC_V850_SDA_15_16_OFFSET", "BFD_RELOC_V850_ZDA_16_16_OFFSET", "BFD_RELOC_V850_ZDA_15_16_OFFSET", "BFD_RELOC_V850_TDA_6_8_OFFSET", "BFD_RELOC_V850_TDA_7_8_OFFSET", "BFD_RELOC_V850_TDA_7_7_OFFSET", "BFD_RELOC_V850_TDA_16_16_OFFSET", "BFD_RELOC_V850_TDA_4_5_OFFSET", "BFD_RELOC_V850_TDA_4_4_OFFSET", "BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET", "BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET", "BFD_RELOC_V850_CALLT_6_7_OFFSET", "BFD_RELOC_V850_CALLT_16_16_OFFSET", "BFD_RELOC_V850_LONGCALL", "BFD_RELOC_V850_LONGJUMP", "BFD_RELOC_V850_ALIGN", "BFD_RELOC_V850_LO16_SPLIT_OFFSET", "BFD_RELOC_MN10300_32_PCREL", "BFD_RELOC_MN10300_16_PCREL", "BFD_RELOC_TIC30_LDP", "BFD_RELOC_TIC54X_PARTLS7", "BFD_RELOC_TIC54X_PARTMS9", "BFD_RELOC_TIC54X_23", "BFD_RELOC_TIC54X_16_OF_23", "BFD_RELOC_TIC54X_MS7_OF_23", "BFD_RELOC_FR30_48", "BFD_RELOC_FR30_20", "BFD_RELOC_FR30_6_IN_4", "BFD_RELOC_FR30_8_IN_8", "BFD_RELOC_FR30_9_IN_8", "BFD_RELOC_FR30_10_IN_8", "BFD_RELOC_FR30_9_PCREL", "BFD_RELOC_FR30_12_PCREL", "BFD_RELOC_MCORE_PCREL_IMM8BY4", "BFD_RELOC_MCORE_PCREL_IMM11BY2", "BFD_RELOC_MCORE_PCREL_IMM4BY2", "BFD_RELOC_MCORE_PCREL_32", "BFD_RELOC_MCORE_PCREL_JSR_IMM11BY2", "BFD_RELOC_MCORE_RVA", "BFD_RELOC_MEP_8", "BFD_RELOC_MEP_16", "BFD_RELOC_MEP_32", "BFD_RELOC_MEP_PCREL8A2", "BFD_RELOC_MEP_PCREL12A2", "BFD_RELOC_MEP_PCREL17A2", "BFD_RELOC_MEP_PCREL24A2", "BFD_RELOC_MEP_PCABS24A2", "BFD_RELOC_MEP_LOW16", "BFD_RELOC_MEP_HI16U", "BFD_RELOC_MEP_HI16S", "BFD_RELOC_MEP_GPREL", "BFD_RELOC_MEP_TPREL", "BFD_RELOC_MEP_TPREL7", "BFD_RELOC_MEP_TPREL7A2", "BFD_RELOC_MEP_TPREL7A4", "BFD_RELOC_MEP_UIMM24", "BFD_RELOC_MEP_ADDR24A4", "BFD_RELOC_MEP_GNU_VTINHERIT", "BFD_RELOC_MEP_GNU_VTENTRY", "BFD_RELOC_MMIX_GETA", "BFD_RELOC_MMIX_GETA_1", "BFD_RELOC_MMIX_GETA_2", "BFD_RELOC_MMIX_GETA_3", "BFD_RELOC_MMIX_CBRANCH", "BFD_RELOC_MMIX_CBRANCH_J", "BFD_RELOC_MMIX_CBRANCH_1", "BFD_RELOC_MMIX_CBRANCH_2", "BFD_RELOC_MMIX_CBRANCH_3", "BFD_RELOC_MMIX_PUSHJ", "BFD_RELOC_MMIX_PUSHJ_1", "BFD_RELOC_MMIX_PUSHJ_2", "BFD_RELOC_MMIX_PUSHJ_3", "BFD_RELOC_MMIX_PUSHJ_STUBBABLE", "BFD_RELOC_MMIX_JMP", "BFD_RELOC_MMIX_JMP_1", "BFD_RELOC_MMIX_JMP_2", "BFD_RELOC_MMIX_JMP_3", "BFD_RELOC_MMIX_ADDR19", "BFD_RELOC_MMIX_ADDR27", "BFD_RELOC_MMIX_REG_OR_BYTE", "BFD_RELOC_MMIX_REG", "BFD_RELOC_MMIX_BASE_PLUS_OFFSET", "BFD_RELOC_MMIX_LOCAL", "BFD_RELOC_AVR_7_PCREL", "BFD_RELOC_AVR_13_PCREL", "BFD_RELOC_AVR_16_PM", "BFD_RELOC_AVR_LO8_LDI", "BFD_RELOC_AVR_HI8_LDI", "BFD_RELOC_AVR_HH8_LDI", "BFD_RELOC_AVR_MS8_LDI", "BFD_RELOC_AVR_LO8_LDI_NEG", "BFD_RELOC_AVR_HI8_LDI_NEG", "BFD_RELOC_AVR_HH8_LDI_NEG", "BFD_RELOC_AVR_MS8_LDI_NEG", "BFD_RELOC_AVR_LO8_LDI_PM", "BFD_RELOC_AVR_LO8_LDI_GS", "BFD_RELOC_AVR_HI8_LDI_PM", "BFD_RELOC_AVR_HI8_LDI_GS", "BFD_RELOC_AVR_HH8_LDI_PM", "BFD_RELOC_AVR_LO8_LDI_PM_NEG", "BFD_RELOC_AVR_HI8_LDI_PM_NEG", "BFD_RELOC_AVR_HH8_LDI_PM_NEG", "BFD_RELOC_AVR_CALL", "BFD_RELOC_AVR_LDI", "BFD_RELOC_AVR_6", "BFD_RELOC_AVR_6_ADIW", "BFD_RELOC_390_12", "BFD_RELOC_390_GOT12", "BFD_RELOC_390_PLT32", "BFD_RELOC_390_COPY", "BFD_RELOC_390_GLOB_DAT", "BFD_RELOC_390_JMP_SLOT", "BFD_RELOC_390_RELATIVE", "BFD_RELOC_390_GOTPC", "BFD_RELOC_390_GOT16", "BFD_RELOC_390_PC16DBL", "BFD_RELOC_390_PLT16DBL", "BFD_RELOC_390_PC32DBL", "BFD_RELOC_390_PLT32DBL", "BFD_RELOC_390_GOTPCDBL", "BFD_RELOC_390_GOT64", "BFD_RELOC_390_PLT64", "BFD_RELOC_390_GOTENT", "BFD_RELOC_390_GOTOFF64", "BFD_RELOC_390_GOTPLT12", "BFD_RELOC_390_GOTPLT16", "BFD_RELOC_390_GOTPLT32", "BFD_RELOC_390_GOTPLT64", "BFD_RELOC_390_GOTPLTENT", "BFD_RELOC_390_PLTOFF16", "BFD_RELOC_390_PLTOFF32", "BFD_RELOC_390_PLTOFF64", "BFD_RELOC_390_TLS_LOAD", "BFD_RELOC_390_TLS_GDCALL", "BFD_RELOC_390_TLS_LDCALL", "BFD_RELOC_390_TLS_GD32", "BFD_RELOC_390_TLS_GD64", "BFD_RELOC_390_TLS_GOTIE12", "BFD_RELOC_390_TLS_GOTIE32", "BFD_RELOC_390_TLS_GOTIE64", "BFD_RELOC_390_TLS_LDM32", "BFD_RELOC_390_TLS_LDM64", "BFD_RELOC_390_TLS_IE32", "BFD_RELOC_390_TLS_IE64", "BFD_RELOC_390_TLS_IEENT", "BFD_RELOC_390_TLS_LE32", "BFD_RELOC_390_TLS_LE64", "BFD_RELOC_390_TLS_LDO32", "BFD_RELOC_390_TLS_LDO64", "BFD_RELOC_390_TLS_DTPMOD", "BFD_RELOC_390_TLS_DTPOFF", "BFD_RELOC_390_TLS_TPOFF", "BFD_RELOC_390_20", "BFD_RELOC_390_GOT20", "BFD_RELOC_390_GOTPLT20", "BFD_RELOC_390_TLS_GOTIE20", "BFD_RELOC_SCORE_DUMMY1", "BFD_RELOC_SCORE_GPREL15", "BFD_RELOC_SCORE_DUMMY2", "BFD_RELOC_SCORE_JMP", "BFD_RELOC_SCORE_BRANCH", "BFD_RELOC_SCORE16_JMP", "BFD_RELOC_SCORE16_BRANCH", "BFD_RELOC_SCORE_GOT15", "BFD_RELOC_SCORE_GOT_LO16", "BFD_RELOC_SCORE_CALL15", "BFD_RELOC_SCORE_DUMMY_HI16", "BFD_RELOC_IP2K_FR9", "BFD_RELOC_IP2K_BANK", "BFD_RELOC_IP2K_ADDR16CJP", "BFD_RELOC_IP2K_PAGE3", "BFD_RELOC_IP2K_LO8DATA", "BFD_RELOC_IP2K_HI8DATA", "BFD_RELOC_IP2K_EX8DATA", "BFD_RELOC_IP2K_LO8INSN", "BFD_RELOC_IP2K_HI8INSN", "BFD_RELOC_IP2K_PC_SKIP", "BFD_RELOC_IP2K_TEXT", "BFD_RELOC_IP2K_FR_OFFSET", "BFD_RELOC_VPE4KMATH_DATA", "BFD_RELOC_VPE4KMATH_INSN", "BFD_RELOC_VTABLE_INHERIT", "BFD_RELOC_VTABLE_ENTRY", "BFD_RELOC_IA64_IMM14", "BFD_RELOC_IA64_IMM22", "BFD_RELOC_IA64_IMM64", "BFD_RELOC_IA64_DIR32MSB", "BFD_RELOC_IA64_DIR32LSB", "BFD_RELOC_IA64_DIR64MSB", "BFD_RELOC_IA64_DIR64LSB", "BFD_RELOC_IA64_GPREL22", "BFD_RELOC_IA64_GPREL64I", "BFD_RELOC_IA64_GPREL32MSB", "BFD_RELOC_IA64_GPREL32LSB", "BFD_RELOC_IA64_GPREL64MSB", "BFD_RELOC_IA64_GPREL64LSB", "BFD_RELOC_IA64_LTOFF22", "BFD_RELOC_IA64_LTOFF64I", "BFD_RELOC_IA64_PLTOFF22", "BFD_RELOC_IA64_PLTOFF64I", "BFD_RELOC_IA64_PLTOFF64MSB", "BFD_RELOC_IA64_PLTOFF64LSB", "BFD_RELOC_IA64_FPTR64I", "BFD_RELOC_IA64_FPTR32MSB", "BFD_RELOC_IA64_FPTR32LSB", "BFD_RELOC_IA64_FPTR64MSB", "BFD_RELOC_IA64_FPTR64LSB", "BFD_RELOC_IA64_PCREL21B", "BFD_RELOC_IA64_PCREL21BI", "BFD_RELOC_IA64_PCREL21M", "BFD_RELOC_IA64_PCREL21F", "BFD_RELOC_IA64_PCREL22", "BFD_RELOC_IA64_PCREL60B", "BFD_RELOC_IA64_PCREL64I", "BFD_RELOC_IA64_PCREL32MSB", "BFD_RELOC_IA64_PCREL32LSB", "BFD_RELOC_IA64_PCREL64MSB", "BFD_RELOC_IA64_PCREL64LSB", "BFD_RELOC_IA64_LTOFF_FPTR22", "BFD_RELOC_IA64_LTOFF_FPTR64I", "BFD_RELOC_IA64_LTOFF_FPTR32MSB", "BFD_RELOC_IA64_LTOFF_FPTR32LSB", "BFD_RELOC_IA64_LTOFF_FPTR64MSB", "BFD_RELOC_IA64_LTOFF_FPTR64LSB", "BFD_RELOC_IA64_SEGREL32MSB", "BFD_RELOC_IA64_SEGREL32LSB", "BFD_RELOC_IA64_SEGREL64MSB", "BFD_RELOC_IA64_SEGREL64LSB", "BFD_RELOC_IA64_SECREL32MSB", "BFD_RELOC_IA64_SECREL32LSB", "BFD_RELOC_IA64_SECREL64MSB", "BFD_RELOC_IA64_SECREL64LSB", "BFD_RELOC_IA64_REL32MSB", "BFD_RELOC_IA64_REL32LSB", "BFD_RELOC_IA64_REL64MSB", "BFD_RELOC_IA64_REL64LSB", "BFD_RELOC_IA64_LTV32MSB", "BFD_RELOC_IA64_LTV32LSB", "BFD_RELOC_IA64_LTV64MSB", "BFD_RELOC_IA64_LTV64LSB", "BFD_RELOC_IA64_IPLTMSB", "BFD_RELOC_IA64_IPLTLSB", "BFD_RELOC_IA64_COPY", "BFD_RELOC_IA64_LTOFF22X", "BFD_RELOC_IA64_LDXMOV", "BFD_RELOC_IA64_TPREL14", "BFD_RELOC_IA64_TPREL22", "BFD_RELOC_IA64_TPREL64I", "BFD_RELOC_IA64_TPREL64MSB", "BFD_RELOC_IA64_TPREL64LSB", "BFD_RELOC_IA64_LTOFF_TPREL22", "BFD_RELOC_IA64_DTPMOD64MSB", "BFD_RELOC_IA64_DTPMOD64LSB", "BFD_RELOC_IA64_LTOFF_DTPMOD22", "BFD_RELOC_IA64_DTPREL14", "BFD_RELOC_IA64_DTPREL22", "BFD_RELOC_IA64_DTPREL64I", "BFD_RELOC_IA64_DTPREL32MSB", "BFD_RELOC_IA64_DTPREL32LSB", "BFD_RELOC_IA64_DTPREL64MSB", "BFD_RELOC_IA64_DTPREL64LSB", "BFD_RELOC_IA64_LTOFF_DTPREL22", "BFD_RELOC_M68HC11_HI8", "BFD_RELOC_M68HC11_LO8", "BFD_RELOC_M68HC11_3B", "BFD_RELOC_M68HC11_RL_JUMP", "BFD_RELOC_M68HC11_RL_GROUP", "BFD_RELOC_M68HC11_LO16", "BFD_RELOC_M68HC11_PAGE", "BFD_RELOC_M68HC11_24", "BFD_RELOC_M68HC12_5B", "BFD_RELOC_16C_NUM08", "BFD_RELOC_16C_NUM08_C", "BFD_RELOC_16C_NUM16", "BFD_RELOC_16C_NUM16_C", "BFD_RELOC_16C_NUM32", "BFD_RELOC_16C_NUM32_C", "BFD_RELOC_16C_DISP04", "BFD_RELOC_16C_DISP04_C", "BFD_RELOC_16C_DISP08", "BFD_RELOC_16C_DISP08_C", "BFD_RELOC_16C_DISP16", "BFD_RELOC_16C_DISP16_C", "BFD_RELOC_16C_DISP24", "BFD_RELOC_16C_DISP24_C", "BFD_RELOC_16C_DISP24a", "BFD_RELOC_16C_DISP24a_C", "BFD_RELOC_16C_REG04", "BFD_RELOC_16C_REG04_C", "BFD_RELOC_16C_REG04a", "BFD_RELOC_16C_REG04a_C", "BFD_RELOC_16C_REG14", "BFD_RELOC_16C_REG14_C", "BFD_RELOC_16C_REG16", "BFD_RELOC_16C_REG16_C", "BFD_RELOC_16C_REG20", "BFD_RELOC_16C_REG20_C", "BFD_RELOC_16C_ABS20", "BFD_RELOC_16C_ABS20_C", "BFD_RELOC_16C_ABS24", "BFD_RELOC_16C_ABS24_C", "BFD_RELOC_16C_IMM04", "BFD_RELOC_16C_IMM04_C", "BFD_RELOC_16C_IMM16", "BFD_RELOC_16C_IMM16_C", "BFD_RELOC_16C_IMM20", "BFD_RELOC_16C_IMM20_C", "BFD_RELOC_16C_IMM24", "BFD_RELOC_16C_IMM24_C", "BFD_RELOC_16C_IMM32", "BFD_RELOC_16C_IMM32_C", "BFD_RELOC_CR16_NUM8", "BFD_RELOC_CR16_NUM16", "BFD_RELOC_CR16_NUM32", "BFD_RELOC_CR16_NUM32a", "BFD_RELOC_CR16_REGREL0", "BFD_RELOC_CR16_REGREL4", "BFD_RELOC_CR16_REGREL4a", "BFD_RELOC_CR16_REGREL14", "BFD_RELOC_CR16_REGREL14a", "BFD_RELOC_CR16_REGREL16", "BFD_RELOC_CR16_REGREL20", "BFD_RELOC_CR16_REGREL20a", "BFD_RELOC_CR16_ABS20", "BFD_RELOC_CR16_ABS24", "BFD_RELOC_CR16_IMM4", "BFD_RELOC_CR16_IMM8", "BFD_RELOC_CR16_IMM16", "BFD_RELOC_CR16_IMM20", "BFD_RELOC_CR16_IMM24", "BFD_RELOC_CR16_IMM32", "BFD_RELOC_CR16_IMM32a", "BFD_RELOC_CR16_DISP4", "BFD_RELOC_CR16_DISP8", "BFD_RELOC_CR16_DISP16", "BFD_RELOC_CR16_DISP20", "BFD_RELOC_CR16_DISP24", "BFD_RELOC_CR16_DISP24a", "BFD_RELOC_CRX_REL4", "BFD_RELOC_CRX_REL8", "BFD_RELOC_CRX_REL8_CMP", "BFD_RELOC_CRX_REL16", "BFD_RELOC_CRX_REL24", "BFD_RELOC_CRX_REL32", "BFD_RELOC_CRX_REGREL12", "BFD_RELOC_CRX_REGREL22", "BFD_RELOC_CRX_REGREL28", "BFD_RELOC_CRX_REGREL32", "BFD_RELOC_CRX_ABS16", "BFD_RELOC_CRX_ABS32", "BFD_RELOC_CRX_NUM8", "BFD_RELOC_CRX_NUM16", "BFD_RELOC_CRX_NUM32", "BFD_RELOC_CRX_IMM16", "BFD_RELOC_CRX_IMM32", "BFD_RELOC_CRX_SWITCH8", "BFD_RELOC_CRX_SWITCH16", "BFD_RELOC_CRX_SWITCH32", "BFD_RELOC_CRIS_BDISP8", "BFD_RELOC_CRIS_UNSIGNED_5", "BFD_RELOC_CRIS_SIGNED_6", "BFD_RELOC_CRIS_UNSIGNED_6", "BFD_RELOC_CRIS_SIGNED_8", "BFD_RELOC_CRIS_UNSIGNED_8", "BFD_RELOC_CRIS_SIGNED_16", "BFD_RELOC_CRIS_UNSIGNED_16", "BFD_RELOC_CRIS_LAPCQ_OFFSET", "BFD_RELOC_CRIS_UNSIGNED_4", "BFD_RELOC_CRIS_COPY", "BFD_RELOC_CRIS_GLOB_DAT", "BFD_RELOC_CRIS_JUMP_SLOT", "BFD_RELOC_CRIS_RELATIVE", "BFD_RELOC_CRIS_32_GOT", "BFD_RELOC_CRIS_16_GOT", "BFD_RELOC_CRIS_32_GOTPLT", "BFD_RELOC_CRIS_16_GOTPLT", "BFD_RELOC_CRIS_32_GOTREL", "BFD_RELOC_CRIS_32_PLT_GOTREL", "BFD_RELOC_CRIS_32_PLT_PCREL", "BFD_RELOC_860_COPY", "BFD_RELOC_860_GLOB_DAT", "BFD_RELOC_860_JUMP_SLOT", "BFD_RELOC_860_RELATIVE", "BFD_RELOC_860_PC26", "BFD_RELOC_860_PLT26", "BFD_RELOC_860_PC16", "BFD_RELOC_860_LOW0", "BFD_RELOC_860_SPLIT0", "BFD_RELOC_860_LOW1", "BFD_RELOC_860_SPLIT1", "BFD_RELOC_860_LOW2", "BFD_RELOC_860_SPLIT2", "BFD_RELOC_860_LOW3", "BFD_RELOC_860_LOGOT0", "BFD_RELOC_860_SPGOT0", "BFD_RELOC_860_LOGOT1", "BFD_RELOC_860_SPGOT1", "BFD_RELOC_860_LOGOTOFF0", "BFD_RELOC_860_SPGOTOFF0", "BFD_RELOC_860_LOGOTOFF1", "BFD_RELOC_860_SPGOTOFF1", "BFD_RELOC_860_LOGOTOFF2", "BFD_RELOC_860_LOGOTOFF3", "BFD_RELOC_860_LOPC", "BFD_RELOC_860_HIGHADJ", "BFD_RELOC_860_HAGOT", "BFD_RELOC_860_HAGOTOFF", "BFD_RELOC_860_HAPC", "BFD_RELOC_860_HIGH", "BFD_RELOC_860_HIGOT", "BFD_RELOC_860_HIGOTOFF", "BFD_RELOC_OPENRISC_ABS_26", "BFD_RELOC_OPENRISC_REL_26", "BFD_RELOC_H8_DIR16A8", "BFD_RELOC_H8_DIR16R8", "BFD_RELOC_H8_DIR24A8", "BFD_RELOC_H8_DIR24R8", "BFD_RELOC_H8_DIR32A16", "BFD_RELOC_XSTORMY16_REL_12", "BFD_RELOC_XSTORMY16_12", "BFD_RELOC_XSTORMY16_24", "BFD_RELOC_XSTORMY16_FPTR16", "BFD_RELOC_RELC", "BFD_RELOC_XC16X_PAG", "BFD_RELOC_XC16X_POF", "BFD_RELOC_XC16X_SEG", "BFD_RELOC_XC16X_SOF", "BFD_RELOC_VAX_GLOB_DAT", "BFD_RELOC_VAX_JMP_SLOT", "BFD_RELOC_VAX_RELATIVE", "BFD_RELOC_MT_PC16", "BFD_RELOC_MT_HI16", "BFD_RELOC_MT_LO16", "BFD_RELOC_MT_GNU_VTINHERIT", "BFD_RELOC_MT_GNU_VTENTRY", "BFD_RELOC_MT_PCINSN8", "BFD_RELOC_MSP430_10_PCREL", "BFD_RELOC_MSP430_16_PCREL", "BFD_RELOC_MSP430_16", "BFD_RELOC_MSP430_16_PCREL_BYTE", "BFD_RELOC_MSP430_16_BYTE", "BFD_RELOC_MSP430_2X_PCREL", "BFD_RELOC_MSP430_RL_PCREL", "BFD_RELOC_IQ2000_OFFSET_16", "BFD_RELOC_IQ2000_OFFSET_21", "BFD_RELOC_IQ2000_UHI16", "BFD_RELOC_XTENSA_RTLD", "BFD_RELOC_XTENSA_GLOB_DAT", "BFD_RELOC_XTENSA_JMP_SLOT", "BFD_RELOC_XTENSA_RELATIVE", "BFD_RELOC_XTENSA_PLT", "BFD_RELOC_XTENSA_DIFF8", "BFD_RELOC_XTENSA_DIFF16", "BFD_RELOC_XTENSA_DIFF32", "BFD_RELOC_XTENSA_SLOT0_OP", "BFD_RELOC_XTENSA_SLOT1_OP", "BFD_RELOC_XTENSA_SLOT2_OP", "BFD_RELOC_XTENSA_SLOT3_OP", "BFD_RELOC_XTENSA_SLOT4_OP", "BFD_RELOC_XTENSA_SLOT5_OP", "BFD_RELOC_XTENSA_SLOT6_OP", "BFD_RELOC_XTENSA_SLOT7_OP", "BFD_RELOC_XTENSA_SLOT8_OP", "BFD_RELOC_XTENSA_SLOT9_OP", "BFD_RELOC_XTENSA_SLOT10_OP", "BFD_RELOC_XTENSA_SLOT11_OP", "BFD_RELOC_XTENSA_SLOT12_OP", "BFD_RELOC_XTENSA_SLOT13_OP", "BFD_RELOC_XTENSA_SLOT14_OP", "BFD_RELOC_XTENSA_SLOT0_ALT", "BFD_RELOC_XTENSA_SLOT1_ALT", "BFD_RELOC_XTENSA_SLOT2_ALT", "BFD_RELOC_XTENSA_SLOT3_ALT", "BFD_RELOC_XTENSA_SLOT4_ALT", "BFD_RELOC_XTENSA_SLOT5_ALT", "BFD_RELOC_XTENSA_SLOT6_ALT", "BFD_RELOC_XTENSA_SLOT7_ALT", "BFD_RELOC_XTENSA_SLOT8_ALT", "BFD_RELOC_XTENSA_SLOT9_ALT", "BFD_RELOC_XTENSA_SLOT10_ALT", "BFD_RELOC_XTENSA_SLOT11_ALT", "BFD_RELOC_XTENSA_SLOT12_ALT", "BFD_RELOC_XTENSA_SLOT13_ALT", "BFD_RELOC_XTENSA_SLOT14_ALT", "BFD_RELOC_XTENSA_OP0", "BFD_RELOC_XTENSA_OP1", "BFD_RELOC_XTENSA_OP2", "BFD_RELOC_XTENSA_ASM_EXPAND", "BFD_RELOC_XTENSA_ASM_SIMPLIFY", "BFD_RELOC_Z80_DISP8", "BFD_RELOC_Z8K_DISP7", "BFD_RELOC_Z8K_CALLR", "BFD_RELOC_Z8K_IMM4L", "@@overflow: BFD_RELOC_UNUSED@@", }; #endif reloc_howto_type *bfd_default_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code); bfd_boolean bfd_generic_relax_section (bfd *abfd, asection *section, struct bfd_link_info *, bfd_boolean *); bfd_boolean bfd_generic_gc_sections (bfd *, struct bfd_link_info *); bfd_boolean bfd_generic_merge_sections (bfd *, struct bfd_link_info *); bfd_byte *bfd_generic_get_relocated_section_contents (bfd *abfd, struct bfd_link_info *link_info, struct bfd_link_order *link_order, bfd_byte *data, bfd_boolean relocatable, asymbol **symbols); /* Extracted from archures.c. */ extern const bfd_arch_info_type bfd_default_arch_struct; bfd_boolean bfd_default_set_arch_mach (bfd *abfd, enum bfd_architecture arch, unsigned long mach); const bfd_arch_info_type *bfd_default_compatible (const bfd_arch_info_type *a, const bfd_arch_info_type *b); bfd_boolean bfd_default_scan (const struct bfd_arch_info *info, const char *string); /* Extracted from elf.c. */ struct elf_internal_shdr *bfd_elf_find_section (bfd *abfd, char *name); Index: head/contrib/binutils/bfd/reloc.c =================================================================== --- head/contrib/binutils/bfd/reloc.c (revision 275717) +++ head/contrib/binutils/bfd/reloc.c (revision 275718) @@ -1,5299 +1,5303 @@ /* BFD support for handling relocation entries. Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ /* SECTION Relocations BFD maintains relocations in much the same way it maintains symbols: they are left alone until required, then read in en-masse and translated into an internal form. A common routine <> acts upon the canonical form to do the fixup. Relocations are maintained on a per section basis, while symbols are maintained on a per BFD basis. All that a back end has to do to fit the BFD interface is to create a <> for each relocation in a particular section, and fill in the right bits of the structures. @menu @* typedef arelent:: @* howto manager:: @end menu */ /* DO compile in the reloc_code name table from libbfd.h. */ #define _BFD_MAKE_TABLE_bfd_reloc_code_real #include "sysdep.h" #include "bfd.h" #include "bfdlink.h" #include "libbfd.h" /* DOCDD INODE typedef arelent, howto manager, Relocations, Relocations SUBSECTION typedef arelent This is the structure of a relocation entry: CODE_FRAGMENT . .typedef enum bfd_reloc_status .{ . {* No errors detected. *} . bfd_reloc_ok, . . {* The relocation was performed, but there was an overflow. *} . bfd_reloc_overflow, . . {* The address to relocate was not within the section supplied. *} . bfd_reloc_outofrange, . . {* Used by special functions. *} . bfd_reloc_continue, . . {* Unsupported relocation size requested. *} . bfd_reloc_notsupported, . . {* Unused. *} . bfd_reloc_other, . . {* The symbol to relocate against was undefined. *} . bfd_reloc_undefined, . . {* The relocation was performed, but may not be ok - presently . generated only when linking i960 coff files with i960 b.out . symbols. If this type is returned, the error_message argument . to bfd_perform_relocation will be set. *} . bfd_reloc_dangerous . } . bfd_reloc_status_type; . . .typedef struct reloc_cache_entry .{ . {* A pointer into the canonical table of pointers. *} . struct bfd_symbol **sym_ptr_ptr; . . {* offset in section. *} . bfd_size_type address; . . {* addend for relocation value. *} . bfd_vma addend; . . {* Pointer to how to perform the required relocation. *} . reloc_howto_type *howto; . .} .arelent; . */ /* DESCRIPTION Here is a description of each of the fields within an <>: o <> The symbol table pointer points to a pointer to the symbol associated with the relocation request. It is the pointer into the table returned by the back end's <> action. @xref{Symbols}. The symbol is referenced through a pointer to a pointer so that tools like the linker can fix up all the symbols of the same name by modifying only one pointer. The relocation routine looks in the symbol and uses the base of the section the symbol is attached to and the value of the symbol as the initial relocation offset. If the symbol pointer is zero, then the section provided is looked up. o <
> The <
> field gives the offset in bytes from the base of the section data which owns the relocation record to the first byte of relocatable information. The actual data relocated will be relative to this point; for example, a relocation type which modifies the bottom two bytes of a four byte word would not touch the first byte pointed to in a big endian world. o <> The <> is a value provided by the back end to be added (!) to the relocation offset. Its interpretation is dependent upon the howto. For example, on the 68k the code: | char foo[]; | main() | { | return foo[0x12345678]; | } Could be compiled into: | linkw fp,#-4 | moveb @@#12345678,d0 | extbl d0 | unlk fp | rts This could create a reloc pointing to <>, but leave the offset in the data, something like: |RELOCATION RECORDS FOR [.text]: |offset type value |00000006 32 _foo | |00000000 4e56 fffc ; linkw fp,#-4 |00000004 1039 1234 5678 ; moveb @@#12345678,d0 |0000000a 49c0 ; extbl d0 |0000000c 4e5e ; unlk fp |0000000e 4e75 ; rts Using coff and an 88k, some instructions don't have enough space in them to represent the full address range, and pointers have to be loaded in two parts. So you'd get something like: | or.u r13,r0,hi16(_foo+0x12345678) | ld.b r2,r13,lo16(_foo+0x12345678) | jmp r1 This should create two relocs, both pointing to <<_foo>>, and with 0x12340000 in their addend field. The data would consist of: |RELOCATION RECORDS FOR [.text]: |offset type value |00000002 HVRT16 _foo+0x12340000 |00000006 LVRT16 _foo+0x12340000 | |00000000 5da05678 ; or.u r13,r0,0x5678 |00000004 1c4d5678 ; ld.b r2,r13,0x5678 |00000008 f400c001 ; jmp r1 The relocation routine digs out the value from the data, adds it to the addend to get the original offset, and then adds the value of <<_foo>>. Note that all 32 bits have to be kept around somewhere, to cope with carry from bit 15 to bit 16. One further example is the sparc and the a.out format. The sparc has a similar problem to the 88k, in that some instructions don't have room for an entire offset, but on the sparc the parts are created in odd sized lumps. The designers of the a.out format chose to not use the data within the section for storing part of the offset; all the offset is kept within the reloc. Anything in the data should be ignored. | save %sp,-112,%sp | sethi %hi(_foo+0x12345678),%g2 | ldsb [%g2+%lo(_foo+0x12345678)],%i0 | ret | restore Both relocs contain a pointer to <>, and the offsets contain junk. |RELOCATION RECORDS FOR [.text]: |offset type value |00000004 HI22 _foo+0x12345678 |00000008 LO10 _foo+0x12345678 | |00000000 9de3bf90 ; save %sp,-112,%sp |00000004 05000000 ; sethi %hi(_foo+0),%g2 |00000008 f048a000 ; ldsb [%g2+%lo(_foo+0)],%i0 |0000000c 81c7e008 ; ret |00000010 81e80000 ; restore o <> The <> field can be imagined as a relocation instruction. It is a pointer to a structure which contains information on what to do with all of the other information in the reloc record and data section. A back end would normally have a relocation instruction set and turn relocations into pointers to the correct structure on input - but it would be possible to create each howto field on demand. */ /* SUBSUBSECTION <> Indicates what sort of overflow checking should be done when performing a relocation. CODE_FRAGMENT . .enum complain_overflow .{ . {* Do not complain on overflow. *} . complain_overflow_dont, . . {* Complain if the value overflows when considered as a signed . number one bit larger than the field. ie. A bitfield of N bits . is allowed to represent -2**n to 2**n-1. *} . complain_overflow_bitfield, . . {* Complain if the value overflows when considered as a signed . number. *} . complain_overflow_signed, . . {* Complain if the value overflows when considered as an . unsigned number. *} . complain_overflow_unsigned .}; */ /* SUBSUBSECTION <> The <> is a structure which contains all the information that libbfd needs to know to tie up a back end's data. CODE_FRAGMENT .struct bfd_symbol; {* Forward declaration. *} . .struct reloc_howto_struct .{ . {* The type field has mainly a documentary use - the back end can . do what it wants with it, though normally the back end's . external idea of what a reloc number is stored . in this field. For example, a PC relative word relocation . in a coff environment has the type 023 - because that's . what the outside world calls a R_PCRWORD reloc. *} . unsigned int type; . . {* The value the final relocation is shifted right by. This drops . unwanted data from the relocation. *} . unsigned int rightshift; . . {* The size of the item to be relocated. This is *not* a . power-of-two measure. To get the number of bytes operated . on by a type of relocation, use bfd_get_reloc_size. *} . int size; . . {* The number of bits in the item to be relocated. This is used . when doing overflow checking. *} . unsigned int bitsize; . . {* Notes that the relocation is relative to the location in the . data section of the addend. The relocation function will . subtract from the relocation value the address of the location . being relocated. *} . bfd_boolean pc_relative; . . {* The bit position of the reloc value in the destination. . The relocated value is left shifted by this amount. *} . unsigned int bitpos; . . {* What type of overflow error should be checked for when . relocating. *} . enum complain_overflow complain_on_overflow; . . {* If this field is non null, then the supplied function is . called rather than the normal function. This allows really . strange relocation methods to be accommodated (e.g., i960 callj . instructions). *} . bfd_reloc_status_type (*special_function) . (bfd *, arelent *, struct bfd_symbol *, void *, asection *, . bfd *, char **); . . {* The textual name of the relocation type. *} . char *name; . . {* Some formats record a relocation addend in the section contents . rather than with the relocation. For ELF formats this is the . distinction between USE_REL and USE_RELA (though the code checks . for USE_REL == 1/0). The value of this field is TRUE if the . addend is recorded with the section contents; when performing a . partial link (ld -r) the section contents (the data) will be . modified. The value of this field is FALSE if addends are . recorded with the relocation (in arelent.addend); when performing . a partial link the relocation will be modified. . All relocations for all ELF USE_RELA targets should set this field . to FALSE (values of TRUE should be looked on with suspicion). . However, the converse is not true: not all relocations of all ELF . USE_REL targets set this field to TRUE. Why this is so is peculiar . to each particular target. For relocs that aren't used in partial . links (e.g. GOT stuff) it doesn't matter what this is set to. *} . bfd_boolean partial_inplace; . . {* src_mask selects the part of the instruction (or data) to be used . in the relocation sum. If the target relocations don't have an . addend in the reloc, eg. ELF USE_REL, src_mask will normally equal . dst_mask to extract the addend from the section contents. If . relocations do have an addend in the reloc, eg. ELF USE_RELA, this . field should be zero. Non-zero values for ELF USE_RELA targets are . bogus as in those cases the value in the dst_mask part of the . section contents should be treated as garbage. *} . bfd_vma src_mask; . . {* dst_mask selects which parts of the instruction (or data) are . replaced with a relocated value. *} . bfd_vma dst_mask; . . {* When some formats create PC relative instructions, they leave . the value of the pc of the place being relocated in the offset . slot of the instruction, so that a PC relative relocation can . be made just by adding in an ordinary offset (e.g., sun3 a.out). . Some formats leave the displacement part of an instruction . empty (e.g., m88k bcs); this flag signals the fact. *} . bfd_boolean pcrel_offset; .}; . */ /* FUNCTION The HOWTO Macro DESCRIPTION The HOWTO define is horrible and will go away. .#define HOWTO(C, R, S, B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC) \ . { (unsigned) C, R, S, B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC } DESCRIPTION And will be replaced with the totally magic way. But for the moment, we are compatible, so do it this way. .#define NEWHOWTO(FUNCTION, NAME, SIZE, REL, IN) \ . HOWTO (0, 0, SIZE, 0, REL, 0, complain_overflow_dont, FUNCTION, \ . NAME, FALSE, 0, 0, IN) . DESCRIPTION This is used to fill in an empty howto entry in an array. .#define EMPTY_HOWTO(C) \ . HOWTO ((C), 0, 0, 0, FALSE, 0, complain_overflow_dont, NULL, \ . NULL, FALSE, 0, 0, FALSE) . DESCRIPTION Helper routine to turn a symbol into a relocation value. .#define HOWTO_PREPARE(relocation, symbol) \ . { \ . if (symbol != NULL) \ . { \ . if (bfd_is_com_section (symbol->section)) \ . { \ . relocation = 0; \ . } \ . else \ . { \ . relocation = symbol->value; \ . } \ . } \ . } . */ /* FUNCTION bfd_get_reloc_size SYNOPSIS unsigned int bfd_get_reloc_size (reloc_howto_type *); DESCRIPTION For a reloc_howto_type that operates on a fixed number of bytes, this returns the number of bytes operated on. */ unsigned int bfd_get_reloc_size (reloc_howto_type *howto) { switch (howto->size) { case 0: return 1; case 1: return 2; case 2: return 4; case 3: return 0; case 4: return 8; case 8: return 16; case -2: return 4; default: abort (); } } /* TYPEDEF arelent_chain DESCRIPTION How relocs are tied together in an <>: .typedef struct relent_chain .{ . arelent relent; . struct relent_chain *next; .} .arelent_chain; . */ /* N_ONES produces N one bits, without overflowing machine arithmetic. */ #define N_ONES(n) (((((bfd_vma) 1 << ((n) - 1)) - 1) << 1) | 1) /* FUNCTION bfd_check_overflow SYNOPSIS bfd_reloc_status_type bfd_check_overflow (enum complain_overflow how, unsigned int bitsize, unsigned int rightshift, unsigned int addrsize, bfd_vma relocation); DESCRIPTION Perform overflow checking on @var{relocation} which has @var{bitsize} significant bits and will be shifted right by @var{rightshift} bits, on a machine with addresses containing @var{addrsize} significant bits. The result is either of @code{bfd_reloc_ok} or @code{bfd_reloc_overflow}. */ bfd_reloc_status_type bfd_check_overflow (enum complain_overflow how, unsigned int bitsize, unsigned int rightshift, unsigned int addrsize, bfd_vma relocation) { bfd_vma fieldmask, addrmask, signmask, ss, a; bfd_reloc_status_type flag = bfd_reloc_ok; /* Note: BITSIZE should always be <= ADDRSIZE, but in case it's not, we'll be permissive: extra bits in the field mask will automatically extend the address mask for purposes of the overflow check. */ fieldmask = N_ONES (bitsize); signmask = ~fieldmask; addrmask = N_ONES (addrsize) | fieldmask; a = (relocation & addrmask) >> rightshift;; switch (how) { case complain_overflow_dont: break; case complain_overflow_signed: /* If any sign bits are set, all sign bits must be set. That is, A must be a valid negative address after shifting. */ signmask = ~ (fieldmask >> 1); /* Fall thru */ case complain_overflow_bitfield: /* Bitfields are sometimes signed, sometimes unsigned. We explicitly allow an address wrap too, which means a bitfield of n bits is allowed to store -2**n to 2**n-1. Thus overflow if the value has some, but not all, bits set outside the field. */ ss = a & signmask; if (ss != 0 && ss != ((addrmask >> rightshift) & signmask)) flag = bfd_reloc_overflow; break; case complain_overflow_unsigned: /* We have an overflow if the address does not fit in the field. */ if ((a & signmask) != 0) flag = bfd_reloc_overflow; break; default: abort (); } return flag; } /* FUNCTION bfd_perform_relocation SYNOPSIS bfd_reloc_status_type bfd_perform_relocation (bfd *abfd, arelent *reloc_entry, void *data, asection *input_section, bfd *output_bfd, char **error_message); DESCRIPTION If @var{output_bfd} is supplied to this function, the generated image will be relocatable; the relocations are copied to the output file after they have been changed to reflect the new state of the world. There are two ways of reflecting the results of partial linkage in an output file: by modifying the output data in place, and by modifying the relocation record. Some native formats (e.g., basic a.out and basic coff) have no way of specifying an addend in the relocation type, so the addend has to go in the output data. This is no big deal since in these formats the output data slot will always be big enough for the addend. Complex reloc types with addends were invented to solve just this problem. The @var{error_message} argument is set to an error message if this return @code{bfd_reloc_dangerous}. */ bfd_reloc_status_type bfd_perform_relocation (bfd *abfd, arelent *reloc_entry, void *data, asection *input_section, bfd *output_bfd, char **error_message) { bfd_vma relocation; bfd_reloc_status_type flag = bfd_reloc_ok; bfd_size_type octets = reloc_entry->address * bfd_octets_per_byte (abfd); bfd_vma output_base = 0; reloc_howto_type *howto = reloc_entry->howto; asection *reloc_target_output_section; asymbol *symbol; symbol = *(reloc_entry->sym_ptr_ptr); if (bfd_is_abs_section (symbol->section) && output_bfd != NULL) { reloc_entry->address += input_section->output_offset; return bfd_reloc_ok; } /* If we are not producing relocatable output, return an error if the symbol is not defined. An undefined weak symbol is considered to have a value of zero (SVR4 ABI, p. 4-27). */ if (bfd_is_und_section (symbol->section) && (symbol->flags & BSF_WEAK) == 0 && output_bfd == NULL) flag = bfd_reloc_undefined; /* If there is a function supplied to handle this relocation type, call it. It'll return `bfd_reloc_continue' if further processing can be done. */ if (howto->special_function) { bfd_reloc_status_type cont; cont = howto->special_function (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message); if (cont != bfd_reloc_continue) return cont; } /* 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; /* Work out which section the relocation is targeted at and the initial relocation command value. */ /* Get symbol value. (Common symbols are special.) */ if (bfd_is_com_section (symbol->section)) relocation = 0; else relocation = symbol->value; reloc_target_output_section = symbol->section->output_section; /* Convert input-section-relative symbol value to absolute. */ if ((output_bfd && ! howto->partial_inplace) || reloc_target_output_section == NULL) output_base = 0; else output_base = reloc_target_output_section->vma; relocation += output_base + symbol->section->output_offset; /* 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. */ if (howto->pc_relative) { /* This is a PC relative relocation. We want to set RELOCATION to the distance between the address of the symbol and the location. RELOCATION is already the address of the symbol. We start by subtracting the address of the section containing the location. If pcrel_offset is set, we must further subtract the position of the location within the section. Some targets arrange for the addend to be the negative of the position of the location within the section; for example, i386-aout does this. For i386-aout, pcrel_offset is FALSE. Some other targets do not include the position of the location; for example, m88kbcs, or ELF. For those targets, pcrel_offset is TRUE. If we are producing relocatable output, then we must ensure that this reloc will be correctly computed when the final relocation is done. If pcrel_offset is FALSE we want to wind up with the negative of the location within the section, which means we must adjust the existing addend by the change in the location within the section. If pcrel_offset is TRUE we do not want to adjust the existing addend at all. FIXME: This seems logical to me, but for the case of producing relocatable output it is not what the code actually does. I don't want to change it, because it seems far too likely that something will break. */ relocation -= input_section->output_section->vma + input_section->output_offset; if (howto->pcrel_offset) relocation -= reloc_entry->address; } if (output_bfd != NULL) { if (! howto->partial_inplace) { /* This is a partial relocation, and we want to apply the relocation to the reloc entry rather than the raw data. Modify the reloc inplace to reflect what we now know. */ reloc_entry->addend = relocation; reloc_entry->address += input_section->output_offset; return flag; } else { /* This is a partial relocation, but inplace, so modify the reloc record a bit. If we've relocated with a symbol with a section, change into a ref to the section belonging to the symbol. */ reloc_entry->address += input_section->output_offset; /* WTF?? */ if (abfd->xvec->flavour == bfd_target_coff_flavour && strcmp (abfd->xvec->name, "coff-Intel-little") != 0 && strcmp (abfd->xvec->name, "coff-Intel-big") != 0) { /* For m68k-coff, the addend was being subtracted twice during relocation with -r. Removing the line below this comment fixes that problem; see PR 2953. However, Ian wrote the following, regarding removing the line below, which explains why it is still enabled: --djm If you put a patch like that into BFD you need to check all the COFF linkers. I am fairly certain that patch will break coff-i386 (e.g., SCO); see coff_i386_reloc in coff-i386.c where I worked around the problem in a different way. There may very well be a reason that the code works as it does. Hmmm. The first obvious point is that bfd_perform_relocation should not have any tests that depend upon the flavour. It's seem like entirely the wrong place for such a thing. The second obvious point is that the current code ignores the reloc addend when producing relocatable output for COFF. That's peculiar. In fact, I really have no idea what the point of the line you want to remove is. A typical COFF reloc subtracts the old value of the symbol and adds in the new value to the location in the object file (if it's a pc relative reloc it adds the difference between the symbol value and the location). When relocating we need to preserve that property. BFD handles this by setting the addend to the negative of the old value of the symbol. Unfortunately it handles common symbols in a non-standard way (it doesn't subtract the old value) but that's a different story (we can't change it without losing backward compatibility with old object files) (coff-i386 does subtract the old value, to be compatible with existing coff-i386 targets, like SCO). So everything works fine when not producing relocatable output. When we are producing relocatable output, logically we should do exactly what we do when not producing relocatable output. Therefore, your patch is correct. In fact, it should probably always just set reloc_entry->addend to 0 for all cases, since it is, in fact, going to add the value into the object file. This won't hurt the COFF code, which doesn't use the addend; I'm not sure what it will do to other formats (the thing to check for would be whether any formats both use the addend and set partial_inplace). When I wanted to make coff-i386 produce relocatable output, I ran into the problem that you are running into: I wanted to remove that line. Rather than risk it, I made the coff-i386 relocs use a special function; it's coff_i386_reloc in coff-i386.c. The function specifically adds the addend field into the object file, knowing that bfd_perform_relocation is not going to. If you remove that line, then coff-i386.c will wind up adding the addend field in twice. It's trivial to fix; it just needs to be done. The problem with removing the line is just that it may break some working code. With BFD it's hard to be sure of anything. The right way to deal with this is simply to build and test at least all the supported COFF targets. It should be straightforward if time and disk space consuming. For each target: 1) build the linker 2) generate some executable, and link it using -r (I would probably use paranoia.o and link against newlib/libc.a, which for all the supported targets would be available in /usr/cygnus/progressive/H-host/target/lib/libc.a). 3) make the change to reloc.c 4) rebuild the linker 5) repeat step 2 6) if the resulting object files are the same, you have at least made it no worse 7) if they are different you have to figure out which version is right */ relocation -= reloc_entry->addend; reloc_entry->addend = 0; } else { reloc_entry->addend = relocation; } } } else { reloc_entry->addend = 0; } /* FIXME: This overflow checking is incomplete, because the value might have overflowed before we get here. For a correct check we need to compute the value in a size larger than bitsize, but we can't reasonably do that for a reloc the same size as a host machine word. FIXME: We should also do overflow checking on the result after adding in the value contained in the object file. */ if (howto->complain_on_overflow != complain_overflow_dont && flag == bfd_reloc_ok) flag = bfd_check_overflow (howto->complain_on_overflow, howto->bitsize, howto->rightshift, bfd_arch_bits_per_address (abfd), relocation); /* Either we are relocating all the way, or we don't want to apply the relocation to the reloc entry (probably because there isn't any room in the output format to describe addends to relocs). */ /* The cast to bfd_vma avoids a bug in the Alpha OSF/1 C compiler (OSF version 1.3, compiler version 3.11). It miscompiles the following program: struct str { unsigned int i0; } s = { 0 }; int main () { unsigned long x; x = 0x100000000; x <<= (unsigned long) s.i0; if (x == 0) printf ("failed\n"); else printf ("succeeded (%lx)\n", x); } */ relocation >>= (bfd_vma) howto->rightshift; /* Shift everything up to where it's going to be used. */ relocation <<= (bfd_vma) howto->bitpos; /* Wait for the day when all have the mask in them. */ /* What we do: i instruction to be left alone o offset within instruction r relocation offset to apply S src mask D dst mask N ~dst mask A part 1 B part 2 R result Do this: (( i i i i i o o o o o from bfd_get and S S S S S) to get the size offset we want + r r r r r r r r r r) to get the final value to place and D D D D D to chop to right size ----------------------- = A A A A A And this: ( i i i i i o o o o o from bfd_get and N N N N N ) get instruction ----------------------- = B B B B B And then: ( B B B B B or A A A A A) ----------------------- = R R R R R R R R R R put into bfd_put */ #define DOIT(x) \ x = ( (x & ~howto->dst_mask) | (((x & howto->src_mask) + relocation) & howto->dst_mask)) switch (howto->size) { case 0: { char x = bfd_get_8 (abfd, (char *) data + octets); DOIT (x); bfd_put_8 (abfd, x, (unsigned char *) data + octets); } break; case 1: { short x = bfd_get_16 (abfd, (bfd_byte *) data + octets); DOIT (x); bfd_put_16 (abfd, (bfd_vma) x, (unsigned char *) data + octets); } break; case 2: { long x = bfd_get_32 (abfd, (bfd_byte *) data + octets); DOIT (x); bfd_put_32 (abfd, (bfd_vma) x, (bfd_byte *) data + octets); } break; case -2: { long x = bfd_get_32 (abfd, (bfd_byte *) data + octets); relocation = -relocation; DOIT (x); bfd_put_32 (abfd, (bfd_vma) x, (bfd_byte *) data + octets); } break; case -1: { long x = bfd_get_16 (abfd, (bfd_byte *) data + octets); relocation = -relocation; DOIT (x); bfd_put_16 (abfd, (bfd_vma) x, (bfd_byte *) data + octets); } break; case 3: /* Do nothing */ break; case 4: #ifdef BFD64 { bfd_vma x = bfd_get_64 (abfd, (bfd_byte *) data + octets); DOIT (x); bfd_put_64 (abfd, x, (bfd_byte *) data + octets); } #else abort (); #endif break; default: return bfd_reloc_other; } return flag; } /* FUNCTION bfd_install_relocation SYNOPSIS bfd_reloc_status_type bfd_install_relocation (bfd *abfd, arelent *reloc_entry, void *data, bfd_vma data_start, asection *input_section, char **error_message); DESCRIPTION This looks remarkably like <>, except it does not expect that the section contents have been filled in. I.e., it's suitable for use when creating, rather than applying a relocation. For now, this function should be considered reserved for the assembler. */ bfd_reloc_status_type bfd_install_relocation (bfd *abfd, arelent *reloc_entry, void *data_start, bfd_vma data_start_offset, asection *input_section, char **error_message) { bfd_vma relocation; bfd_reloc_status_type flag = bfd_reloc_ok; bfd_size_type octets = reloc_entry->address * bfd_octets_per_byte (abfd); bfd_vma output_base = 0; reloc_howto_type *howto = reloc_entry->howto; asection *reloc_target_output_section; asymbol *symbol; bfd_byte *data; symbol = *(reloc_entry->sym_ptr_ptr); if (bfd_is_abs_section (symbol->section)) { reloc_entry->address += input_section->output_offset; return bfd_reloc_ok; } /* If there is a function supplied to handle this relocation type, call it. It'll return `bfd_reloc_continue' if further processing can be done. */ if (howto->special_function) { bfd_reloc_status_type cont; /* XXX - The special_function calls haven't been fixed up to deal with creating new relocations and section contents. */ cont = howto->special_function (abfd, reloc_entry, symbol, /* XXX - Non-portable! */ ((bfd_byte *) data_start - data_start_offset), input_section, abfd, error_message); if (cont != bfd_reloc_continue) return cont; } /* 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; /* Work out which section the relocation is targeted at and the initial relocation command value. */ /* Get symbol value. (Common symbols are special.) */ if (bfd_is_com_section (symbol->section)) relocation = 0; else relocation = symbol->value; reloc_target_output_section = symbol->section->output_section; /* Convert input-section-relative symbol value to absolute. */ if (! howto->partial_inplace) output_base = 0; else output_base = reloc_target_output_section->vma; relocation += output_base + symbol->section->output_offset; /* 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. */ if (howto->pc_relative) { /* This is a PC relative relocation. We want to set RELOCATION to the distance between the address of the symbol and the location. RELOCATION is already the address of the symbol. We start by subtracting the address of the section containing the location. If pcrel_offset is set, we must further subtract the position of the location within the section. Some targets arrange for the addend to be the negative of the position of the location within the section; for example, i386-aout does this. For i386-aout, pcrel_offset is FALSE. Some other targets do not include the position of the location; for example, m88kbcs, or ELF. For those targets, pcrel_offset is TRUE. If we are producing relocatable output, then we must ensure that this reloc will be correctly computed when the final relocation is done. If pcrel_offset is FALSE we want to wind up with the negative of the location within the section, which means we must adjust the existing addend by the change in the location within the section. If pcrel_offset is TRUE we do not want to adjust the existing addend at all. FIXME: This seems logical to me, but for the case of producing relocatable output it is not what the code actually does. I don't want to change it, because it seems far too likely that something will break. */ relocation -= input_section->output_section->vma + input_section->output_offset; if (howto->pcrel_offset && howto->partial_inplace) relocation -= reloc_entry->address; } if (! howto->partial_inplace) { /* This is a partial relocation, and we want to apply the relocation to the reloc entry rather than the raw data. Modify the reloc inplace to reflect what we now know. */ reloc_entry->addend = relocation; reloc_entry->address += input_section->output_offset; return flag; } else { /* This is a partial relocation, but inplace, so modify the reloc record a bit. If we've relocated with a symbol with a section, change into a ref to the section belonging to the symbol. */ reloc_entry->address += input_section->output_offset; /* WTF?? */ if (abfd->xvec->flavour == bfd_target_coff_flavour && strcmp (abfd->xvec->name, "coff-Intel-little") != 0 && strcmp (abfd->xvec->name, "coff-Intel-big") != 0) { /* For m68k-coff, the addend was being subtracted twice during relocation with -r. Removing the line below this comment fixes that problem; see PR 2953. However, Ian wrote the following, regarding removing the line below, which explains why it is still enabled: --djm If you put a patch like that into BFD you need to check all the COFF linkers. I am fairly certain that patch will break coff-i386 (e.g., SCO); see coff_i386_reloc in coff-i386.c where I worked around the problem in a different way. There may very well be a reason that the code works as it does. Hmmm. The first obvious point is that bfd_install_relocation should not have any tests that depend upon the flavour. It's seem like entirely the wrong place for such a thing. The second obvious point is that the current code ignores the reloc addend when producing relocatable output for COFF. That's peculiar. In fact, I really have no idea what the point of the line you want to remove is. A typical COFF reloc subtracts the old value of the symbol and adds in the new value to the location in the object file (if it's a pc relative reloc it adds the difference between the symbol value and the location). When relocating we need to preserve that property. BFD handles this by setting the addend to the negative of the old value of the symbol. Unfortunately it handles common symbols in a non-standard way (it doesn't subtract the old value) but that's a different story (we can't change it without losing backward compatibility with old object files) (coff-i386 does subtract the old value, to be compatible with existing coff-i386 targets, like SCO). So everything works fine when not producing relocatable output. When we are producing relocatable output, logically we should do exactly what we do when not producing relocatable output. Therefore, your patch is correct. In fact, it should probably always just set reloc_entry->addend to 0 for all cases, since it is, in fact, going to add the value into the object file. This won't hurt the COFF code, which doesn't use the addend; I'm not sure what it will do to other formats (the thing to check for would be whether any formats both use the addend and set partial_inplace). When I wanted to make coff-i386 produce relocatable output, I ran into the problem that you are running into: I wanted to remove that line. Rather than risk it, I made the coff-i386 relocs use a special function; it's coff_i386_reloc in coff-i386.c. The function specifically adds the addend field into the object file, knowing that bfd_install_relocation is not going to. If you remove that line, then coff-i386.c will wind up adding the addend field in twice. It's trivial to fix; it just needs to be done. The problem with removing the line is just that it may break some working code. With BFD it's hard to be sure of anything. The right way to deal with this is simply to build and test at least all the supported COFF targets. It should be straightforward if time and disk space consuming. For each target: 1) build the linker 2) generate some executable, and link it using -r (I would probably use paranoia.o and link against newlib/libc.a, which for all the supported targets would be available in /usr/cygnus/progressive/H-host/target/lib/libc.a). 3) make the change to reloc.c 4) rebuild the linker 5) repeat step 2 6) if the resulting object files are the same, you have at least made it no worse 7) if they are different you have to figure out which version is right. */ relocation -= reloc_entry->addend; /* FIXME: There should be no target specific code here... */ if (strcmp (abfd->xvec->name, "coff-z8k") != 0) reloc_entry->addend = 0; } else { reloc_entry->addend = relocation; } } /* FIXME: This overflow checking is incomplete, because the value might have overflowed before we get here. For a correct check we need to compute the value in a size larger than bitsize, but we can't reasonably do that for a reloc the same size as a host machine word. FIXME: We should also do overflow checking on the result after adding in the value contained in the object file. */ if (howto->complain_on_overflow != complain_overflow_dont) flag = bfd_check_overflow (howto->complain_on_overflow, howto->bitsize, howto->rightshift, bfd_arch_bits_per_address (abfd), relocation); /* Either we are relocating all the way, or we don't want to apply the relocation to the reloc entry (probably because there isn't any room in the output format to describe addends to relocs). */ /* The cast to bfd_vma avoids a bug in the Alpha OSF/1 C compiler (OSF version 1.3, compiler version 3.11). It miscompiles the following program: struct str { unsigned int i0; } s = { 0 }; int main () { unsigned long x; x = 0x100000000; x <<= (unsigned long) s.i0; if (x == 0) printf ("failed\n"); else printf ("succeeded (%lx)\n", x); } */ relocation >>= (bfd_vma) howto->rightshift; /* Shift everything up to where it's going to be used. */ relocation <<= (bfd_vma) howto->bitpos; /* Wait for the day when all have the mask in them. */ /* What we do: i instruction to be left alone o offset within instruction r relocation offset to apply S src mask D dst mask N ~dst mask A part 1 B part 2 R result Do this: (( i i i i i o o o o o from bfd_get and S S S S S) to get the size offset we want + r r r r r r r r r r) to get the final value to place and D D D D D to chop to right size ----------------------- = A A A A A And this: ( i i i i i o o o o o from bfd_get and N N N N N ) get instruction ----------------------- = B B B B B And then: ( B B B B B or A A A A A) ----------------------- = R R R R R R R R R R put into bfd_put */ #define DOIT(x) \ x = ( (x & ~howto->dst_mask) | (((x & howto->src_mask) + relocation) & howto->dst_mask)) data = (bfd_byte *) data_start + (octets - data_start_offset); switch (howto->size) { case 0: { char x = bfd_get_8 (abfd, data); DOIT (x); bfd_put_8 (abfd, x, data); } break; case 1: { short x = bfd_get_16 (abfd, data); DOIT (x); bfd_put_16 (abfd, (bfd_vma) x, data); } break; case 2: { long x = bfd_get_32 (abfd, data); DOIT (x); bfd_put_32 (abfd, (bfd_vma) x, data); } break; case -2: { long x = bfd_get_32 (abfd, data); relocation = -relocation; DOIT (x); bfd_put_32 (abfd, (bfd_vma) x, data); } break; case 3: /* Do nothing */ break; case 4: { bfd_vma x = bfd_get_64 (abfd, data); DOIT (x); bfd_put_64 (abfd, x, data); } break; default: return bfd_reloc_other; } return flag; } /* This relocation routine is used by some of the backend linkers. They do not construct asymbol or arelent structures, so there is no reason for them to use bfd_perform_relocation. Also, bfd_perform_relocation is so hacked up it is easier to write a new function than to try to deal with it. This routine does a final relocation. Whether it is useful for a relocatable link depends upon how the object format defines relocations. FIXME: This routine ignores any special_function in the HOWTO, since the existing special_function values have been written for bfd_perform_relocation. HOWTO is the reloc howto information. INPUT_BFD is the BFD which the reloc applies to. INPUT_SECTION is the section which the reloc applies to. CONTENTS is the contents of the section. ADDRESS is the address of the reloc within INPUT_SECTION. VALUE is the value of the symbol the reloc refers to. ADDEND is the addend of the reloc. */ bfd_reloc_status_type _bfd_final_link_relocate (reloc_howto_type *howto, bfd *input_bfd, asection *input_section, bfd_byte *contents, bfd_vma address, bfd_vma value, bfd_vma addend) { bfd_vma relocation; /* Sanity check the address. */ if (address > bfd_get_section_limit (input_bfd, input_section)) return bfd_reloc_outofrange; /* This function assumes that we are dealing with a basic relocation against a symbol. We want to compute the value of the symbol to relocate to. This is just VALUE, the value of the symbol, plus ADDEND, any addend associated with the reloc. */ relocation = value + addend; /* If the relocation is PC relative, we want to set RELOCATION to the distance between the symbol (currently in RELOCATION) and the location we are relocating. Some targets (e.g., i386-aout) arrange for the contents of the section to be the negative of the offset of the location within the section; for such targets pcrel_offset is FALSE. Other targets (e.g., m88kbcs or ELF) simply leave the contents of the section as zero; for such targets pcrel_offset is TRUE. If pcrel_offset is FALSE we do not need to subtract out the offset of the location within the section (which is just ADDRESS). */ if (howto->pc_relative) { relocation -= (input_section->output_section->vma + input_section->output_offset); if (howto->pcrel_offset) relocation -= address; } return _bfd_relocate_contents (howto, input_bfd, relocation, contents + address); } /* Relocate a given location using a given value and howto. */ bfd_reloc_status_type _bfd_relocate_contents (reloc_howto_type *howto, bfd *input_bfd, bfd_vma relocation, bfd_byte *location) { int size; bfd_vma x = 0; bfd_reloc_status_type flag; unsigned int rightshift = howto->rightshift; unsigned int bitpos = howto->bitpos; /* If the size is negative, negate RELOCATION. This isn't very general. */ if (howto->size < 0) relocation = -relocation; /* Get the value we are going to relocate. */ size = bfd_get_reloc_size (howto); switch (size) { default: case 0: abort (); case 1: x = bfd_get_8 (input_bfd, location); break; case 2: x = bfd_get_16 (input_bfd, location); break; case 4: x = bfd_get_32 (input_bfd, location); break; case 8: #ifdef BFD64 x = bfd_get_64 (input_bfd, location); #else abort (); #endif break; } /* Check for overflow. FIXME: We may drop bits during the addition which we don't check for. We must either check at every single operation, which would be tedious, or we must do the computations in a type larger than bfd_vma, which would be inefficient. */ flag = bfd_reloc_ok; if (howto->complain_on_overflow != complain_overflow_dont) { bfd_vma addrmask, fieldmask, signmask, ss; bfd_vma a, b, sum; /* Get the values to be added together. For signed and unsigned relocations, we assume that all values should be truncated to the size of an address. For bitfields, all the bits matter. See also bfd_check_overflow. */ fieldmask = N_ONES (howto->bitsize); signmask = ~fieldmask; addrmask = N_ONES (bfd_arch_bits_per_address (input_bfd)) | fieldmask; a = (relocation & addrmask) >> rightshift; b = (x & howto->src_mask & addrmask) >> bitpos; switch (howto->complain_on_overflow) { case complain_overflow_signed: /* If any sign bits are set, all sign bits must be set. That is, A must be a valid negative address after shifting. */ signmask = ~(fieldmask >> 1); /* Fall thru */ case complain_overflow_bitfield: /* Much like the signed check, but for a field one bit wider. We allow a bitfield to represent numbers in the range -2**n to 2**n-1, where n is the number of bits in the field. Note that when bfd_vma is 32 bits, a 32-bit reloc can't overflow, which is exactly what we want. */ ss = a & signmask; if (ss != 0 && ss != ((addrmask >> rightshift) & signmask)) flag = bfd_reloc_overflow; /* We only need this next bit of code if the sign bit of B is below the sign bit of A. This would only happen if SRC_MASK had fewer bits than BITSIZE. Note that if SRC_MASK has more bits than BITSIZE, we can get into trouble; we would need to verify that B is in range, as we do for A above. */ ss = ((~howto->src_mask) >> 1) & howto->src_mask; ss >>= bitpos; /* Set all the bits above the sign bit. */ b = (b ^ ss) - ss; /* Now we can do the addition. */ sum = a + b; /* See if the result has the correct sign. Bits above the sign bit are junk now; ignore them. If the sum is positive, make sure we did not have all negative inputs; if the sum is negative, make sure we did not have all positive inputs. The test below looks only at the sign bits, and it really just SIGN (A) == SIGN (B) && SIGN (A) != SIGN (SUM) We mask with addrmask here to explicitly allow an address wrap-around. The Linux kernel relies on it, and it is the only way to write assembler code which can run when loaded at a location 0x80000000 away from the location at which it is linked. */ if (((~(a ^ b)) & (a ^ sum)) & signmask & addrmask) flag = bfd_reloc_overflow; break; case complain_overflow_unsigned: /* Checking for an unsigned overflow is relatively easy: trim the addresses and add, and trim the result as well. Overflow is normally indicated when the result does not fit in the field. However, we also need to consider the case when, e.g., fieldmask is 0x7fffffff or smaller, an input is 0x80000000, and bfd_vma is only 32 bits; then we will get sum == 0, but there is an overflow, since the inputs did not fit in the field. Instead of doing a separate test, we can check for this by or-ing in the operands when testing for the sum overflowing its final field. */ sum = (a + b) & addrmask; if ((a | b | sum) & signmask) flag = bfd_reloc_overflow; break; default: abort (); } } /* Put RELOCATION in the right bits. */ relocation >>= (bfd_vma) rightshift; relocation <<= (bfd_vma) bitpos; /* Add RELOCATION to the right bits of X. */ x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + relocation) & howto->dst_mask)); /* Put the relocated value back in the object file. */ switch (size) { default: abort (); case 1: bfd_put_8 (input_bfd, x, location); break; case 2: bfd_put_16 (input_bfd, x, location); break; case 4: bfd_put_32 (input_bfd, x, location); break; case 8: #ifdef BFD64 bfd_put_64 (input_bfd, x, location); #else abort (); #endif break; } return flag; } /* Clear a given location using a given howto, by applying a relocation value of zero and discarding any in-place addend. This is used for fixed-up relocations against discarded symbols, to make ignorable debug or unwind information more obvious. */ void _bfd_clear_contents (reloc_howto_type *howto, bfd *input_bfd, bfd_byte *location) { int size; bfd_vma x = 0; /* Get the value we are going to relocate. */ size = bfd_get_reloc_size (howto); switch (size) { default: case 0: abort (); case 1: x = bfd_get_8 (input_bfd, location); break; case 2: x = bfd_get_16 (input_bfd, location); break; case 4: x = bfd_get_32 (input_bfd, location); break; case 8: #ifdef BFD64 x = bfd_get_64 (input_bfd, location); #else abort (); #endif break; } /* Zero out the unwanted bits of X. */ x &= ~howto->dst_mask; /* Put the relocated value back in the object file. */ switch (size) { default: case 0: abort (); case 1: bfd_put_8 (input_bfd, x, location); break; case 2: bfd_put_16 (input_bfd, x, location); break; case 4: bfd_put_32 (input_bfd, x, location); break; case 8: #ifdef BFD64 bfd_put_64 (input_bfd, x, location); #else abort (); #endif break; } } /* DOCDD INODE howto manager, , typedef arelent, Relocations SUBSECTION The howto manager When an application wants to create a relocation, but doesn't know what the target machine might call it, it can find out by using this bit of code. */ /* TYPEDEF bfd_reloc_code_type DESCRIPTION The insides of a reloc code. The idea is that, eventually, there will be one enumerator for every type of relocation we ever do. Pass one of these values to <>, and it'll return a howto pointer. This does mean that the application must determine the correct enumerator value; you can't get a howto pointer from a random set of attributes. SENUM bfd_reloc_code_real ENUM BFD_RELOC_64 ENUMX BFD_RELOC_32 ENUMX BFD_RELOC_26 ENUMX BFD_RELOC_24 ENUMX BFD_RELOC_16 ENUMX BFD_RELOC_14 ENUMX BFD_RELOC_8 ENUMDOC Basic absolute relocations of N bits. ENUM BFD_RELOC_64_PCREL ENUMX BFD_RELOC_32_PCREL ENUMX BFD_RELOC_24_PCREL ENUMX BFD_RELOC_16_PCREL ENUMX BFD_RELOC_12_PCREL ENUMX BFD_RELOC_8_PCREL ENUMDOC PC-relative relocations. Sometimes these are relative to the address of the relocation itself; sometimes they are relative to the start of the section containing the relocation. It depends on the specific target. The 24-bit relocation is used in some Intel 960 configurations. ENUM BFD_RELOC_32_SECREL ENUMDOC Section relative relocations. Some targets need this for DWARF2. ENUM BFD_RELOC_32_GOT_PCREL ENUMX BFD_RELOC_16_GOT_PCREL ENUMX BFD_RELOC_8_GOT_PCREL ENUMX BFD_RELOC_32_GOTOFF ENUMX BFD_RELOC_16_GOTOFF ENUMX BFD_RELOC_LO16_GOTOFF ENUMX BFD_RELOC_HI16_GOTOFF ENUMX BFD_RELOC_HI16_S_GOTOFF ENUMX BFD_RELOC_8_GOTOFF ENUMX BFD_RELOC_64_PLT_PCREL ENUMX BFD_RELOC_32_PLT_PCREL ENUMX BFD_RELOC_24_PLT_PCREL ENUMX BFD_RELOC_16_PLT_PCREL ENUMX BFD_RELOC_8_PLT_PCREL ENUMX BFD_RELOC_64_PLTOFF ENUMX BFD_RELOC_32_PLTOFF ENUMX BFD_RELOC_16_PLTOFF ENUMX BFD_RELOC_LO16_PLTOFF ENUMX BFD_RELOC_HI16_PLTOFF ENUMX BFD_RELOC_HI16_S_PLTOFF ENUMX BFD_RELOC_8_PLTOFF ENUMDOC For ELF. ENUM BFD_RELOC_68K_GLOB_DAT ENUMX BFD_RELOC_68K_JMP_SLOT ENUMX BFD_RELOC_68K_RELATIVE ENUMDOC Relocations used by 68K ELF. ENUM BFD_RELOC_32_BASEREL ENUMX BFD_RELOC_16_BASEREL ENUMX BFD_RELOC_LO16_BASEREL ENUMX BFD_RELOC_HI16_BASEREL ENUMX BFD_RELOC_HI16_S_BASEREL ENUMX BFD_RELOC_8_BASEREL ENUMX BFD_RELOC_RVA ENUMDOC Linkage-table relative. ENUM BFD_RELOC_8_FFnn ENUMDOC Absolute 8-bit relocation, but used to form an address like 0xFFnn. ENUM BFD_RELOC_32_PCREL_S2 ENUMX BFD_RELOC_16_PCREL_S2 ENUMX BFD_RELOC_23_PCREL_S2 ENUMDOC These PC-relative relocations are stored as word displacements -- i.e., byte displacements shifted right two bits. The 30-bit word displacement (<<32_PCREL_S2>> -- 32 bits, shifted 2) is used on the SPARC. (SPARC tools generally refer to this as <>.) The signed 16-bit displacement is used on the MIPS, and the 23-bit displacement is used on the Alpha. ENUM BFD_RELOC_HI22 ENUMX BFD_RELOC_LO10 ENUMDOC High 22 bits and low 10 bits of 32-bit value, placed into lower bits of the target word. These are used on the SPARC. ENUM BFD_RELOC_GPREL16 ENUMX BFD_RELOC_GPREL32 ENUMDOC For systems that allocate a Global Pointer register, these are displacements off that register. These relocation types are handled specially, because the value the register will have is decided relatively late. ENUM BFD_RELOC_I960_CALLJ ENUMDOC Reloc types used for i960/b.out. ENUM BFD_RELOC_NONE ENUMX BFD_RELOC_SPARC_WDISP22 ENUMX BFD_RELOC_SPARC22 ENUMX BFD_RELOC_SPARC13 ENUMX BFD_RELOC_SPARC_GOT10 ENUMX BFD_RELOC_SPARC_GOT13 ENUMX BFD_RELOC_SPARC_GOT22 ENUMX BFD_RELOC_SPARC_PC10 ENUMX BFD_RELOC_SPARC_PC22 ENUMX BFD_RELOC_SPARC_WPLT30 ENUMX BFD_RELOC_SPARC_COPY ENUMX BFD_RELOC_SPARC_GLOB_DAT ENUMX BFD_RELOC_SPARC_JMP_SLOT ENUMX BFD_RELOC_SPARC_RELATIVE ENUMX BFD_RELOC_SPARC_UA16 ENUMX BFD_RELOC_SPARC_UA32 ENUMX BFD_RELOC_SPARC_UA64 ENUMDOC SPARC ELF relocations. There is probably some overlap with other relocation types already defined. ENUM BFD_RELOC_SPARC_BASE13 ENUMX BFD_RELOC_SPARC_BASE22 ENUMDOC I think these are specific to SPARC a.out (e.g., Sun 4). ENUMEQ BFD_RELOC_SPARC_64 BFD_RELOC_64 ENUMX BFD_RELOC_SPARC_10 ENUMX BFD_RELOC_SPARC_11 ENUMX BFD_RELOC_SPARC_OLO10 ENUMX BFD_RELOC_SPARC_HH22 ENUMX BFD_RELOC_SPARC_HM10 ENUMX BFD_RELOC_SPARC_LM22 ENUMX BFD_RELOC_SPARC_PC_HH22 ENUMX BFD_RELOC_SPARC_PC_HM10 ENUMX BFD_RELOC_SPARC_PC_LM22 ENUMX BFD_RELOC_SPARC_WDISP16 ENUMX BFD_RELOC_SPARC_WDISP19 ENUMX BFD_RELOC_SPARC_7 ENUMX BFD_RELOC_SPARC_6 ENUMX BFD_RELOC_SPARC_5 ENUMEQX BFD_RELOC_SPARC_DISP64 BFD_RELOC_64_PCREL ENUMX BFD_RELOC_SPARC_PLT32 ENUMX BFD_RELOC_SPARC_PLT64 ENUMX BFD_RELOC_SPARC_HIX22 ENUMX BFD_RELOC_SPARC_LOX10 ENUMX BFD_RELOC_SPARC_H44 ENUMX BFD_RELOC_SPARC_M44 ENUMX BFD_RELOC_SPARC_L44 ENUMX BFD_RELOC_SPARC_REGISTER ENUMDOC SPARC64 relocations ENUM BFD_RELOC_SPARC_REV32 ENUMDOC SPARC little endian relocation ENUM BFD_RELOC_SPARC_TLS_GD_HI22 ENUMX BFD_RELOC_SPARC_TLS_GD_LO10 ENUMX BFD_RELOC_SPARC_TLS_GD_ADD ENUMX BFD_RELOC_SPARC_TLS_GD_CALL ENUMX BFD_RELOC_SPARC_TLS_LDM_HI22 ENUMX BFD_RELOC_SPARC_TLS_LDM_LO10 ENUMX BFD_RELOC_SPARC_TLS_LDM_ADD ENUMX BFD_RELOC_SPARC_TLS_LDM_CALL ENUMX BFD_RELOC_SPARC_TLS_LDO_HIX22 ENUMX BFD_RELOC_SPARC_TLS_LDO_LOX10 ENUMX BFD_RELOC_SPARC_TLS_LDO_ADD ENUMX BFD_RELOC_SPARC_TLS_IE_HI22 ENUMX BFD_RELOC_SPARC_TLS_IE_LO10 ENUMX BFD_RELOC_SPARC_TLS_IE_LD ENUMX BFD_RELOC_SPARC_TLS_IE_LDX ENUMX BFD_RELOC_SPARC_TLS_IE_ADD ENUMX BFD_RELOC_SPARC_TLS_LE_HIX22 ENUMX BFD_RELOC_SPARC_TLS_LE_LOX10 ENUMX BFD_RELOC_SPARC_TLS_DTPMOD32 ENUMX BFD_RELOC_SPARC_TLS_DTPMOD64 ENUMX BFD_RELOC_SPARC_TLS_DTPOFF32 ENUMX BFD_RELOC_SPARC_TLS_DTPOFF64 ENUMX BFD_RELOC_SPARC_TLS_TPOFF32 ENUMX BFD_RELOC_SPARC_TLS_TPOFF64 ENUMDOC SPARC TLS relocations ENUM BFD_RELOC_SPU_IMM7 ENUMX BFD_RELOC_SPU_IMM8 ENUMX BFD_RELOC_SPU_IMM10 ENUMX BFD_RELOC_SPU_IMM10W ENUMX BFD_RELOC_SPU_IMM16 ENUMX BFD_RELOC_SPU_IMM16W ENUMX BFD_RELOC_SPU_IMM18 ENUMX BFD_RELOC_SPU_PCREL9a ENUMX BFD_RELOC_SPU_PCREL9b ENUMX BFD_RELOC_SPU_PCREL16 ENUMX BFD_RELOC_SPU_LO16 ENUMX BFD_RELOC_SPU_HI16 ENUMX BFD_RELOC_SPU_PPU32 ENUMX BFD_RELOC_SPU_PPU64 ENUMDOC SPU Relocations. ENUM BFD_RELOC_ALPHA_GPDISP_HI16 ENUMDOC Alpha ECOFF and ELF relocations. Some of these treat the symbol or "addend" in some special way. For GPDISP_HI16 ("gpdisp") relocations, the symbol is ignored when writing; when reading, it will be the absolute section symbol. The addend is the displacement in bytes of the "lda" instruction from the "ldah" instruction (which is at the address of this reloc). ENUM BFD_RELOC_ALPHA_GPDISP_LO16 ENUMDOC For GPDISP_LO16 ("ignore") relocations, the symbol is handled as with GPDISP_HI16 relocs. The addend is ignored when writing the relocations out, and is filled in with the file's GP value on reading, for convenience. ENUM BFD_RELOC_ALPHA_GPDISP ENUMDOC The ELF GPDISP relocation is exactly the same as the GPDISP_HI16 relocation except that there is no accompanying GPDISP_LO16 relocation. ENUM BFD_RELOC_ALPHA_LITERAL ENUMX BFD_RELOC_ALPHA_ELF_LITERAL ENUMX BFD_RELOC_ALPHA_LITUSE ENUMDOC The Alpha LITERAL/LITUSE relocs are produced by a symbol reference; the assembler turns it into a LDQ instruction to load the address of the symbol, and then fills in a register in the real instruction. The LITERAL reloc, at the LDQ instruction, refers to the .lita section symbol. The addend is ignored when writing, but is filled in with the file's GP value on reading, for convenience, as with the GPDISP_LO16 reloc. The ELF_LITERAL reloc is somewhere between 16_GOTOFF and GPDISP_LO16. It should refer to the symbol to be referenced, as with 16_GOTOFF, but it generates output not based on the position within the .got section, but relative to the GP value chosen for the file during the final link stage. The LITUSE reloc, on the instruction using the loaded address, gives information to the linker that it might be able to use to optimize away some literal section references. The symbol is ignored (read as the absolute section symbol), and the "addend" indicates the type of instruction using the register: 1 - "memory" fmt insn 2 - byte-manipulation (byte offset reg) 3 - jsr (target of branch) ENUM BFD_RELOC_ALPHA_HINT ENUMDOC The HINT relocation indicates a value that should be filled into the "hint" field of a jmp/jsr/ret instruction, for possible branch- prediction logic which may be provided on some processors. ENUM BFD_RELOC_ALPHA_LINKAGE ENUMDOC The LINKAGE relocation outputs a linkage pair in the object file, which is filled by the linker. ENUM BFD_RELOC_ALPHA_CODEADDR ENUMDOC The CODEADDR relocation outputs a STO_CA in the object file, which is filled by the linker. ENUM BFD_RELOC_ALPHA_GPREL_HI16 ENUMX BFD_RELOC_ALPHA_GPREL_LO16 ENUMDOC The GPREL_HI/LO relocations together form a 32-bit offset from the GP register. ENUM BFD_RELOC_ALPHA_BRSGP ENUMDOC Like BFD_RELOC_23_PCREL_S2, except that the source and target must share a common GP, and the target address is adjusted for STO_ALPHA_STD_GPLOAD. ENUM BFD_RELOC_ALPHA_TLSGD ENUMX BFD_RELOC_ALPHA_TLSLDM ENUMX BFD_RELOC_ALPHA_DTPMOD64 ENUMX BFD_RELOC_ALPHA_GOTDTPREL16 ENUMX BFD_RELOC_ALPHA_DTPREL64 ENUMX BFD_RELOC_ALPHA_DTPREL_HI16 ENUMX BFD_RELOC_ALPHA_DTPREL_LO16 ENUMX BFD_RELOC_ALPHA_DTPREL16 ENUMX BFD_RELOC_ALPHA_GOTTPREL16 ENUMX BFD_RELOC_ALPHA_TPREL64 ENUMX BFD_RELOC_ALPHA_TPREL_HI16 ENUMX BFD_RELOC_ALPHA_TPREL_LO16 ENUMX BFD_RELOC_ALPHA_TPREL16 ENUMDOC Alpha thread-local storage relocations. ENUM BFD_RELOC_MIPS_JMP ENUMDOC Bits 27..2 of the relocation address shifted right 2 bits; simple reloc otherwise. ENUM BFD_RELOC_MIPS16_JMP ENUMDOC The MIPS16 jump instruction. ENUM BFD_RELOC_MIPS16_GPREL ENUMDOC MIPS16 GP relative reloc. ENUM BFD_RELOC_HI16 ENUMDOC High 16 bits of 32-bit value; simple reloc. ENUM BFD_RELOC_HI16_S ENUMDOC High 16 bits of 32-bit value but the low 16 bits will be sign extended and added to form the final result. If the low 16 bits form a negative number, we need to add one to the high value to compensate for the borrow when the low bits are added. ENUM BFD_RELOC_LO16 ENUMDOC Low 16 bits. ENUM BFD_RELOC_HI16_PCREL ENUMDOC High 16 bits of 32-bit pc-relative value ENUM BFD_RELOC_HI16_S_PCREL ENUMDOC High 16 bits of 32-bit pc-relative value, adjusted ENUM BFD_RELOC_LO16_PCREL ENUMDOC Low 16 bits of pc-relative value ENUM BFD_RELOC_MIPS16_HI16 ENUMDOC MIPS16 high 16 bits of 32-bit value. ENUM BFD_RELOC_MIPS16_HI16_S ENUMDOC MIPS16 high 16 bits of 32-bit value but the low 16 bits will be sign extended and added to form the final result. If the low 16 bits form a negative number, we need to add one to the high value to compensate for the borrow when the low bits are added. ENUM BFD_RELOC_MIPS16_LO16 ENUMDOC MIPS16 low 16 bits. ENUM BFD_RELOC_MIPS_LITERAL ENUMDOC Relocation against a MIPS literal section. ENUM BFD_RELOC_MIPS_GOT16 ENUMX BFD_RELOC_MIPS_CALL16 ENUMX BFD_RELOC_MIPS_GOT_HI16 ENUMX BFD_RELOC_MIPS_GOT_LO16 ENUMX BFD_RELOC_MIPS_CALL_HI16 ENUMX BFD_RELOC_MIPS_CALL_LO16 ENUMX BFD_RELOC_MIPS_SUB ENUMX BFD_RELOC_MIPS_GOT_PAGE ENUMX BFD_RELOC_MIPS_GOT_OFST ENUMX BFD_RELOC_MIPS_GOT_DISP ENUMX BFD_RELOC_MIPS_SHIFT5 ENUMX BFD_RELOC_MIPS_SHIFT6 ENUMX BFD_RELOC_MIPS_INSERT_A ENUMX BFD_RELOC_MIPS_INSERT_B ENUMX BFD_RELOC_MIPS_DELETE ENUMX BFD_RELOC_MIPS_HIGHEST ENUMX BFD_RELOC_MIPS_HIGHER ENUMX BFD_RELOC_MIPS_SCN_DISP ENUMX BFD_RELOC_MIPS_REL16 ENUMX BFD_RELOC_MIPS_RELGOT ENUMX BFD_RELOC_MIPS_JALR ENUMX BFD_RELOC_MIPS_TLS_DTPMOD32 ENUMX BFD_RELOC_MIPS_TLS_DTPREL32 ENUMX BFD_RELOC_MIPS_TLS_DTPMOD64 ENUMX BFD_RELOC_MIPS_TLS_DTPREL64 ENUMX BFD_RELOC_MIPS_TLS_GD ENUMX BFD_RELOC_MIPS_TLS_LDM ENUMX BFD_RELOC_MIPS_TLS_DTPREL_HI16 ENUMX BFD_RELOC_MIPS_TLS_DTPREL_LO16 ENUMX BFD_RELOC_MIPS_TLS_GOTTPREL ENUMX BFD_RELOC_MIPS_TLS_TPREL32 ENUMX BFD_RELOC_MIPS_TLS_TPREL64 ENUMX BFD_RELOC_MIPS_TLS_TPREL_HI16 ENUMX BFD_RELOC_MIPS_TLS_TPREL_LO16 ENUMDOC MIPS ELF relocations. 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 ENUMX BFD_RELOC_FRV_LO16 ENUMX BFD_RELOC_FRV_HI16 ENUMX BFD_RELOC_FRV_GPREL12 ENUMX BFD_RELOC_FRV_GPRELU12 ENUMX BFD_RELOC_FRV_GPREL32 ENUMX BFD_RELOC_FRV_GPRELHI ENUMX BFD_RELOC_FRV_GPRELLO ENUMX BFD_RELOC_FRV_GOT12 ENUMX BFD_RELOC_FRV_GOTHI ENUMX BFD_RELOC_FRV_GOTLO ENUMX BFD_RELOC_FRV_FUNCDESC ENUMX BFD_RELOC_FRV_FUNCDESC_GOT12 ENUMX BFD_RELOC_FRV_FUNCDESC_GOTHI ENUMX BFD_RELOC_FRV_FUNCDESC_GOTLO ENUMX BFD_RELOC_FRV_FUNCDESC_VALUE ENUMX BFD_RELOC_FRV_FUNCDESC_GOTOFF12 ENUMX BFD_RELOC_FRV_FUNCDESC_GOTOFFHI ENUMX BFD_RELOC_FRV_FUNCDESC_GOTOFFLO ENUMX BFD_RELOC_FRV_GOTOFF12 ENUMX BFD_RELOC_FRV_GOTOFFHI ENUMX BFD_RELOC_FRV_GOTOFFLO ENUMX BFD_RELOC_FRV_GETTLSOFF ENUMX BFD_RELOC_FRV_TLSDESC_VALUE ENUMX BFD_RELOC_FRV_GOTTLSDESC12 ENUMX BFD_RELOC_FRV_GOTTLSDESCHI ENUMX BFD_RELOC_FRV_GOTTLSDESCLO ENUMX BFD_RELOC_FRV_TLSMOFF12 ENUMX BFD_RELOC_FRV_TLSMOFFHI ENUMX BFD_RELOC_FRV_TLSMOFFLO ENUMX BFD_RELOC_FRV_GOTTLSOFF12 ENUMX BFD_RELOC_FRV_GOTTLSOFFHI ENUMX BFD_RELOC_FRV_GOTTLSOFFLO ENUMX BFD_RELOC_FRV_TLSOFF ENUMX BFD_RELOC_FRV_TLSDESC_RELAX ENUMX BFD_RELOC_FRV_GETTLSOFF_RELAX ENUMX BFD_RELOC_FRV_TLSOFF_RELAX ENUMX BFD_RELOC_FRV_TLSMOFF ENUMDOC Fujitsu Frv Relocations. COMMENT ENUM BFD_RELOC_MN10300_GOTOFF24 ENUMDOC This is a 24bit GOT-relative reloc for the mn10300. ENUM BFD_RELOC_MN10300_GOT32 ENUMDOC This is a 32bit GOT-relative reloc for the mn10300, offset by two bytes in the instruction. ENUM BFD_RELOC_MN10300_GOT24 ENUMDOC This is a 24bit GOT-relative reloc for the mn10300, offset by two bytes in the instruction. ENUM BFD_RELOC_MN10300_GOT16 ENUMDOC This is a 16bit GOT-relative reloc for the mn10300, offset by two bytes in the instruction. ENUM BFD_RELOC_MN10300_COPY ENUMDOC Copy symbol at runtime. ENUM BFD_RELOC_MN10300_GLOB_DAT ENUMDOC Create GOT entry. ENUM BFD_RELOC_MN10300_JMP_SLOT ENUMDOC Create PLT entry. ENUM BFD_RELOC_MN10300_RELATIVE ENUMDOC Adjust by program base. COMMENT ENUM BFD_RELOC_386_GOT32 ENUMX BFD_RELOC_386_PLT32 ENUMX BFD_RELOC_386_COPY ENUMX BFD_RELOC_386_GLOB_DAT ENUMX BFD_RELOC_386_JUMP_SLOT ENUMX BFD_RELOC_386_RELATIVE ENUMX BFD_RELOC_386_GOTOFF ENUMX BFD_RELOC_386_GOTPC ENUMX BFD_RELOC_386_TLS_TPOFF ENUMX BFD_RELOC_386_TLS_IE ENUMX BFD_RELOC_386_TLS_GOTIE ENUMX BFD_RELOC_386_TLS_LE ENUMX BFD_RELOC_386_TLS_GD ENUMX BFD_RELOC_386_TLS_LDM ENUMX BFD_RELOC_386_TLS_LDO_32 ENUMX BFD_RELOC_386_TLS_IE_32 ENUMX BFD_RELOC_386_TLS_LE_32 ENUMX BFD_RELOC_386_TLS_DTPMOD32 ENUMX BFD_RELOC_386_TLS_DTPOFF32 ENUMX BFD_RELOC_386_TLS_TPOFF32 ENUMX BFD_RELOC_386_TLS_GOTDESC ENUMX BFD_RELOC_386_TLS_DESC_CALL ENUMX BFD_RELOC_386_TLS_DESC ENUMDOC i386/elf relocations ENUM BFD_RELOC_X86_64_GOT32 ENUMX BFD_RELOC_X86_64_PLT32 ENUMX BFD_RELOC_X86_64_COPY ENUMX BFD_RELOC_X86_64_GLOB_DAT ENUMX BFD_RELOC_X86_64_JUMP_SLOT ENUMX BFD_RELOC_X86_64_RELATIVE ENUMX BFD_RELOC_X86_64_GOTPCREL ENUMX BFD_RELOC_X86_64_32S ENUMX BFD_RELOC_X86_64_DTPMOD64 ENUMX BFD_RELOC_X86_64_DTPOFF64 ENUMX BFD_RELOC_X86_64_TPOFF64 ENUMX BFD_RELOC_X86_64_TLSGD ENUMX BFD_RELOC_X86_64_TLSLD ENUMX BFD_RELOC_X86_64_DTPOFF32 ENUMX BFD_RELOC_X86_64_GOTTPOFF ENUMX BFD_RELOC_X86_64_TPOFF32 ENUMX BFD_RELOC_X86_64_GOTOFF64 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 ENUMX BFD_RELOC_X86_64_TLSDESC ENUMDOC x86-64/elf relocations ENUM BFD_RELOC_NS32K_IMM_8 ENUMX BFD_RELOC_NS32K_IMM_16 ENUMX BFD_RELOC_NS32K_IMM_32 ENUMX BFD_RELOC_NS32K_IMM_8_PCREL ENUMX BFD_RELOC_NS32K_IMM_16_PCREL ENUMX BFD_RELOC_NS32K_IMM_32_PCREL ENUMX BFD_RELOC_NS32K_DISP_8 ENUMX BFD_RELOC_NS32K_DISP_16 ENUMX BFD_RELOC_NS32K_DISP_32 ENUMX BFD_RELOC_NS32K_DISP_8_PCREL ENUMX BFD_RELOC_NS32K_DISP_16_PCREL ENUMX BFD_RELOC_NS32K_DISP_32_PCREL ENUMDOC ns32k relocations ENUM BFD_RELOC_PDP11_DISP_8_PCREL ENUMX BFD_RELOC_PDP11_DISP_6_PCREL ENUMDOC PDP11 relocations ENUM BFD_RELOC_PJ_CODE_HI16 ENUMX BFD_RELOC_PJ_CODE_LO16 ENUMX BFD_RELOC_PJ_CODE_DIR16 ENUMX BFD_RELOC_PJ_CODE_DIR32 ENUMX BFD_RELOC_PJ_CODE_REL16 ENUMX BFD_RELOC_PJ_CODE_REL32 ENUMDOC Picojava relocs. Not all of these appear in object files. ENUM BFD_RELOC_PPC_B26 ENUMX BFD_RELOC_PPC_BA26 ENUMX BFD_RELOC_PPC_TOC16 ENUMX BFD_RELOC_PPC_B16 ENUMX BFD_RELOC_PPC_B16_BRTAKEN ENUMX BFD_RELOC_PPC_B16_BRNTAKEN ENUMX BFD_RELOC_PPC_BA16 ENUMX BFD_RELOC_PPC_BA16_BRTAKEN ENUMX BFD_RELOC_PPC_BA16_BRNTAKEN ENUMX BFD_RELOC_PPC_COPY ENUMX BFD_RELOC_PPC_GLOB_DAT ENUMX BFD_RELOC_PPC_JMP_SLOT ENUMX BFD_RELOC_PPC_RELATIVE ENUMX BFD_RELOC_PPC_LOCAL24PC ENUMX BFD_RELOC_PPC_EMB_NADDR32 ENUMX BFD_RELOC_PPC_EMB_NADDR16 ENUMX BFD_RELOC_PPC_EMB_NADDR16_LO ENUMX BFD_RELOC_PPC_EMB_NADDR16_HI ENUMX BFD_RELOC_PPC_EMB_NADDR16_HA ENUMX BFD_RELOC_PPC_EMB_SDAI16 ENUMX BFD_RELOC_PPC_EMB_SDA2I16 ENUMX BFD_RELOC_PPC_EMB_SDA2REL ENUMX BFD_RELOC_PPC_EMB_SDA21 ENUMX BFD_RELOC_PPC_EMB_MRKREF ENUMX BFD_RELOC_PPC_EMB_RELSEC16 ENUMX BFD_RELOC_PPC_EMB_RELST_LO ENUMX BFD_RELOC_PPC_EMB_RELST_HI ENUMX BFD_RELOC_PPC_EMB_RELST_HA ENUMX BFD_RELOC_PPC_EMB_BIT_FLD ENUMX BFD_RELOC_PPC_EMB_RELSDA ENUMX BFD_RELOC_PPC64_HIGHER ENUMX BFD_RELOC_PPC64_HIGHER_S ENUMX BFD_RELOC_PPC64_HIGHEST ENUMX BFD_RELOC_PPC64_HIGHEST_S ENUMX BFD_RELOC_PPC64_TOC16_LO ENUMX BFD_RELOC_PPC64_TOC16_HI ENUMX BFD_RELOC_PPC64_TOC16_HA ENUMX BFD_RELOC_PPC64_TOC ENUMX BFD_RELOC_PPC64_PLTGOT16 ENUMX BFD_RELOC_PPC64_PLTGOT16_LO ENUMX BFD_RELOC_PPC64_PLTGOT16_HI ENUMX BFD_RELOC_PPC64_PLTGOT16_HA ENUMX BFD_RELOC_PPC64_ADDR16_DS ENUMX BFD_RELOC_PPC64_ADDR16_LO_DS ENUMX BFD_RELOC_PPC64_GOT16_DS ENUMX BFD_RELOC_PPC64_GOT16_LO_DS ENUMX BFD_RELOC_PPC64_PLT16_LO_DS ENUMX BFD_RELOC_PPC64_SECTOFF_DS ENUMX BFD_RELOC_PPC64_SECTOFF_LO_DS ENUMX BFD_RELOC_PPC64_TOC16_DS ENUMX BFD_RELOC_PPC64_TOC16_LO_DS ENUMX BFD_RELOC_PPC64_PLTGOT16_DS ENUMX BFD_RELOC_PPC64_PLTGOT16_LO_DS ENUMDOC Power(rs6000) and PowerPC relocations. ENUM BFD_RELOC_PPC_TLS ENUMX + BFD_RELOC_PPC_TLSGD +ENUMX + BFD_RELOC_PPC_TLSLD +ENUMX BFD_RELOC_PPC_DTPMOD ENUMX BFD_RELOC_PPC_TPREL16 ENUMX BFD_RELOC_PPC_TPREL16_LO ENUMX BFD_RELOC_PPC_TPREL16_HI ENUMX BFD_RELOC_PPC_TPREL16_HA ENUMX BFD_RELOC_PPC_TPREL ENUMX BFD_RELOC_PPC_DTPREL16 ENUMX BFD_RELOC_PPC_DTPREL16_LO ENUMX BFD_RELOC_PPC_DTPREL16_HI ENUMX BFD_RELOC_PPC_DTPREL16_HA ENUMX BFD_RELOC_PPC_DTPREL ENUMX BFD_RELOC_PPC_GOT_TLSGD16 ENUMX BFD_RELOC_PPC_GOT_TLSGD16_LO ENUMX BFD_RELOC_PPC_GOT_TLSGD16_HI ENUMX BFD_RELOC_PPC_GOT_TLSGD16_HA ENUMX BFD_RELOC_PPC_GOT_TLSLD16 ENUMX BFD_RELOC_PPC_GOT_TLSLD16_LO ENUMX BFD_RELOC_PPC_GOT_TLSLD16_HI ENUMX BFD_RELOC_PPC_GOT_TLSLD16_HA ENUMX BFD_RELOC_PPC_GOT_TPREL16 ENUMX BFD_RELOC_PPC_GOT_TPREL16_LO ENUMX BFD_RELOC_PPC_GOT_TPREL16_HI ENUMX BFD_RELOC_PPC_GOT_TPREL16_HA ENUMX BFD_RELOC_PPC_GOT_DTPREL16 ENUMX BFD_RELOC_PPC_GOT_DTPREL16_LO ENUMX BFD_RELOC_PPC_GOT_DTPREL16_HI ENUMX BFD_RELOC_PPC_GOT_DTPREL16_HA ENUMX BFD_RELOC_PPC64_TPREL16_DS ENUMX BFD_RELOC_PPC64_TPREL16_LO_DS ENUMX BFD_RELOC_PPC64_TPREL16_HIGHER ENUMX BFD_RELOC_PPC64_TPREL16_HIGHERA ENUMX BFD_RELOC_PPC64_TPREL16_HIGHEST ENUMX BFD_RELOC_PPC64_TPREL16_HIGHESTA ENUMX BFD_RELOC_PPC64_DTPREL16_DS ENUMX BFD_RELOC_PPC64_DTPREL16_LO_DS ENUMX BFD_RELOC_PPC64_DTPREL16_HIGHER ENUMX BFD_RELOC_PPC64_DTPREL16_HIGHERA ENUMX BFD_RELOC_PPC64_DTPREL16_HIGHEST ENUMX BFD_RELOC_PPC64_DTPREL16_HIGHESTA ENUMDOC PowerPC and PowerPC64 thread-local storage relocations. ENUM BFD_RELOC_I370_D12 ENUMDOC IBM 370/390 relocations ENUM BFD_RELOC_CTOR ENUMDOC The type of reloc used to build a constructor table - at the moment probably a 32 bit wide absolute relocation, but the target can choose. It generally does map to one of the other relocation types. ENUM BFD_RELOC_ARM_PCREL_BRANCH ENUMDOC ARM 26 bit pc-relative branch. The lowest two bits must be zero and are not stored in the instruction. ENUM BFD_RELOC_ARM_PCREL_BLX ENUMDOC ARM 26 bit pc-relative branch. The lowest bit must be zero and is not stored in the instruction. The 2nd lowest bit comes from a 1 bit field in the instruction. ENUM BFD_RELOC_THUMB_PCREL_BLX ENUMDOC Thumb 22 bit pc-relative branch. The lowest bit must be zero and is not stored in the instruction. The 2nd lowest bit comes from a 1 bit field in the instruction. ENUM BFD_RELOC_ARM_PCREL_CALL ENUMDOC ARM 26-bit pc-relative branch for an unconditional BL or BLX instruction. ENUM BFD_RELOC_ARM_PCREL_JUMP ENUMDOC ARM 26-bit pc-relative branch for B or conditional BL instruction. ENUM BFD_RELOC_THUMB_PCREL_BRANCH7 ENUMX BFD_RELOC_THUMB_PCREL_BRANCH9 ENUMX BFD_RELOC_THUMB_PCREL_BRANCH12 ENUMX BFD_RELOC_THUMB_PCREL_BRANCH20 ENUMX BFD_RELOC_THUMB_PCREL_BRANCH23 ENUMX BFD_RELOC_THUMB_PCREL_BRANCH25 ENUMDOC Thumb 7-, 9-, 12-, 20-, 23-, and 25-bit pc-relative branches. The lowest bit must be zero and is not stored in the instruction. Note that the corresponding ELF R_ARM_THM_JUMPnn constant has an "nn" one smaller in all cases. Note further that BRANCH23 corresponds to R_ARM_THM_CALL. ENUM BFD_RELOC_ARM_OFFSET_IMM ENUMDOC 12-bit immediate offset, used in ARM-format ldr and str instructions. ENUM BFD_RELOC_ARM_THUMB_OFFSET ENUMDOC 5-bit immediate offset, used in Thumb-format ldr and str instructions. ENUM BFD_RELOC_ARM_TARGET1 ENUMDOC Pc-relative or absolute relocation depending on target. Used for entries in .init_array sections. ENUM BFD_RELOC_ARM_ROSEGREL32 ENUMDOC Read-only segment base relative address. ENUM BFD_RELOC_ARM_SBREL32 ENUMDOC Data segment base relative address. ENUM BFD_RELOC_ARM_TARGET2 ENUMDOC This reloc is used for references to RTTI data from exception handling tables. The actual definition depends on the target. It may be a pc-relative or some form of GOT-indirect relocation. ENUM BFD_RELOC_ARM_PREL31 ENUMDOC 31-bit PC relative address. ENUM BFD_RELOC_ARM_MOVW ENUMX BFD_RELOC_ARM_MOVT ENUMX BFD_RELOC_ARM_MOVW_PCREL ENUMX BFD_RELOC_ARM_MOVT_PCREL ENUMX BFD_RELOC_ARM_THUMB_MOVW ENUMX BFD_RELOC_ARM_THUMB_MOVT ENUMX BFD_RELOC_ARM_THUMB_MOVW_PCREL ENUMX BFD_RELOC_ARM_THUMB_MOVT_PCREL ENUMDOC Low and High halfword relocations for MOVW and MOVT instructions. ENUM BFD_RELOC_ARM_JUMP_SLOT ENUMX BFD_RELOC_ARM_GLOB_DAT ENUMX BFD_RELOC_ARM_GOT32 ENUMX BFD_RELOC_ARM_PLT32 ENUMX BFD_RELOC_ARM_RELATIVE ENUMX BFD_RELOC_ARM_GOTOFF ENUMX BFD_RELOC_ARM_GOTPC ENUMDOC Relocations for setting up GOTs and PLTs for shared libraries. ENUM BFD_RELOC_ARM_TLS_GD32 ENUMX BFD_RELOC_ARM_TLS_LDO32 ENUMX BFD_RELOC_ARM_TLS_LDM32 ENUMX BFD_RELOC_ARM_TLS_DTPOFF32 ENUMX BFD_RELOC_ARM_TLS_DTPMOD32 ENUMX BFD_RELOC_ARM_TLS_TPOFF32 ENUMX BFD_RELOC_ARM_TLS_IE32 ENUMX BFD_RELOC_ARM_TLS_LE32 ENUMDOC ARM thread-local storage relocations. ENUM BFD_RELOC_ARM_ALU_PC_G0_NC ENUMX BFD_RELOC_ARM_ALU_PC_G0 ENUMX BFD_RELOC_ARM_ALU_PC_G1_NC ENUMX BFD_RELOC_ARM_ALU_PC_G1 ENUMX BFD_RELOC_ARM_ALU_PC_G2 ENUMX BFD_RELOC_ARM_LDR_PC_G0 ENUMX BFD_RELOC_ARM_LDR_PC_G1 ENUMX BFD_RELOC_ARM_LDR_PC_G2 ENUMX BFD_RELOC_ARM_LDRS_PC_G0 ENUMX BFD_RELOC_ARM_LDRS_PC_G1 ENUMX BFD_RELOC_ARM_LDRS_PC_G2 ENUMX BFD_RELOC_ARM_LDC_PC_G0 ENUMX BFD_RELOC_ARM_LDC_PC_G1 ENUMX BFD_RELOC_ARM_LDC_PC_G2 ENUMX BFD_RELOC_ARM_ALU_SB_G0_NC ENUMX BFD_RELOC_ARM_ALU_SB_G0 ENUMX BFD_RELOC_ARM_ALU_SB_G1_NC ENUMX BFD_RELOC_ARM_ALU_SB_G1 ENUMX BFD_RELOC_ARM_ALU_SB_G2 ENUMX BFD_RELOC_ARM_LDR_SB_G0 ENUMX BFD_RELOC_ARM_LDR_SB_G1 ENUMX BFD_RELOC_ARM_LDR_SB_G2 ENUMX BFD_RELOC_ARM_LDRS_SB_G0 ENUMX BFD_RELOC_ARM_LDRS_SB_G1 ENUMX BFD_RELOC_ARM_LDRS_SB_G2 ENUMX BFD_RELOC_ARM_LDC_SB_G0 ENUMX BFD_RELOC_ARM_LDC_SB_G1 ENUMX BFD_RELOC_ARM_LDC_SB_G2 ENUMDOC ARM group relocations. ENUM BFD_RELOC_ARM_IMMEDIATE ENUMX BFD_RELOC_ARM_ADRL_IMMEDIATE ENUMX BFD_RELOC_ARM_T32_IMMEDIATE ENUMX BFD_RELOC_ARM_T32_ADD_IMM ENUMX BFD_RELOC_ARM_T32_IMM12 ENUMX BFD_RELOC_ARM_T32_ADD_PC12 ENUMX BFD_RELOC_ARM_SHIFT_IMM ENUMX BFD_RELOC_ARM_SMC ENUMX BFD_RELOC_ARM_SWI ENUMX BFD_RELOC_ARM_MULTI ENUMX BFD_RELOC_ARM_CP_OFF_IMM ENUMX BFD_RELOC_ARM_CP_OFF_IMM_S2 ENUMX BFD_RELOC_ARM_T32_CP_OFF_IMM ENUMX BFD_RELOC_ARM_T32_CP_OFF_IMM_S2 ENUMX BFD_RELOC_ARM_ADR_IMM ENUMX BFD_RELOC_ARM_LDR_IMM ENUMX BFD_RELOC_ARM_LITERAL ENUMX BFD_RELOC_ARM_IN_POOL ENUMX BFD_RELOC_ARM_OFFSET_IMM8 ENUMX BFD_RELOC_ARM_T32_OFFSET_U8 ENUMX BFD_RELOC_ARM_T32_OFFSET_IMM ENUMX BFD_RELOC_ARM_HWLITERAL ENUMX BFD_RELOC_ARM_THUMB_ADD ENUMX BFD_RELOC_ARM_THUMB_IMM ENUMX BFD_RELOC_ARM_THUMB_SHIFT ENUMDOC These relocs are only used within the ARM assembler. They are not (at present) written to any object files. ENUM BFD_RELOC_SH_PCDISP8BY2 ENUMX BFD_RELOC_SH_PCDISP12BY2 ENUMX BFD_RELOC_SH_IMM3 ENUMX BFD_RELOC_SH_IMM3U ENUMX BFD_RELOC_SH_DISP12 ENUMX BFD_RELOC_SH_DISP12BY2 ENUMX BFD_RELOC_SH_DISP12BY4 ENUMX BFD_RELOC_SH_DISP12BY8 ENUMX BFD_RELOC_SH_DISP20 ENUMX BFD_RELOC_SH_DISP20BY8 ENUMX BFD_RELOC_SH_IMM4 ENUMX BFD_RELOC_SH_IMM4BY2 ENUMX BFD_RELOC_SH_IMM4BY4 ENUMX BFD_RELOC_SH_IMM8 ENUMX BFD_RELOC_SH_IMM8BY2 ENUMX BFD_RELOC_SH_IMM8BY4 ENUMX BFD_RELOC_SH_PCRELIMM8BY2 ENUMX BFD_RELOC_SH_PCRELIMM8BY4 ENUMX BFD_RELOC_SH_SWITCH16 ENUMX BFD_RELOC_SH_SWITCH32 ENUMX BFD_RELOC_SH_USES ENUMX BFD_RELOC_SH_COUNT ENUMX BFD_RELOC_SH_ALIGN ENUMX BFD_RELOC_SH_CODE ENUMX BFD_RELOC_SH_DATA ENUMX BFD_RELOC_SH_LABEL ENUMX BFD_RELOC_SH_LOOP_START ENUMX BFD_RELOC_SH_LOOP_END ENUMX BFD_RELOC_SH_COPY ENUMX BFD_RELOC_SH_GLOB_DAT ENUMX BFD_RELOC_SH_JMP_SLOT ENUMX BFD_RELOC_SH_RELATIVE ENUMX BFD_RELOC_SH_GOTPC ENUMX BFD_RELOC_SH_GOT_LOW16 ENUMX BFD_RELOC_SH_GOT_MEDLOW16 ENUMX BFD_RELOC_SH_GOT_MEDHI16 ENUMX BFD_RELOC_SH_GOT_HI16 ENUMX BFD_RELOC_SH_GOTPLT_LOW16 ENUMX BFD_RELOC_SH_GOTPLT_MEDLOW16 ENUMX BFD_RELOC_SH_GOTPLT_MEDHI16 ENUMX BFD_RELOC_SH_GOTPLT_HI16 ENUMX BFD_RELOC_SH_PLT_LOW16 ENUMX BFD_RELOC_SH_PLT_MEDLOW16 ENUMX BFD_RELOC_SH_PLT_MEDHI16 ENUMX BFD_RELOC_SH_PLT_HI16 ENUMX BFD_RELOC_SH_GOTOFF_LOW16 ENUMX BFD_RELOC_SH_GOTOFF_MEDLOW16 ENUMX BFD_RELOC_SH_GOTOFF_MEDHI16 ENUMX BFD_RELOC_SH_GOTOFF_HI16 ENUMX BFD_RELOC_SH_GOTPC_LOW16 ENUMX BFD_RELOC_SH_GOTPC_MEDLOW16 ENUMX BFD_RELOC_SH_GOTPC_MEDHI16 ENUMX BFD_RELOC_SH_GOTPC_HI16 ENUMX BFD_RELOC_SH_COPY64 ENUMX BFD_RELOC_SH_GLOB_DAT64 ENUMX BFD_RELOC_SH_JMP_SLOT64 ENUMX BFD_RELOC_SH_RELATIVE64 ENUMX BFD_RELOC_SH_GOT10BY4 ENUMX BFD_RELOC_SH_GOT10BY8 ENUMX BFD_RELOC_SH_GOTPLT10BY4 ENUMX BFD_RELOC_SH_GOTPLT10BY8 ENUMX BFD_RELOC_SH_GOTPLT32 ENUMX BFD_RELOC_SH_SHMEDIA_CODE ENUMX BFD_RELOC_SH_IMMU5 ENUMX BFD_RELOC_SH_IMMS6 ENUMX BFD_RELOC_SH_IMMS6BY32 ENUMX BFD_RELOC_SH_IMMU6 ENUMX BFD_RELOC_SH_IMMS10 ENUMX BFD_RELOC_SH_IMMS10BY2 ENUMX BFD_RELOC_SH_IMMS10BY4 ENUMX BFD_RELOC_SH_IMMS10BY8 ENUMX BFD_RELOC_SH_IMMS16 ENUMX BFD_RELOC_SH_IMMU16 ENUMX BFD_RELOC_SH_IMM_LOW16 ENUMX BFD_RELOC_SH_IMM_LOW16_PCREL ENUMX BFD_RELOC_SH_IMM_MEDLOW16 ENUMX BFD_RELOC_SH_IMM_MEDLOW16_PCREL ENUMX BFD_RELOC_SH_IMM_MEDHI16 ENUMX BFD_RELOC_SH_IMM_MEDHI16_PCREL ENUMX BFD_RELOC_SH_IMM_HI16 ENUMX BFD_RELOC_SH_IMM_HI16_PCREL ENUMX BFD_RELOC_SH_PT_16 ENUMX BFD_RELOC_SH_TLS_GD_32 ENUMX BFD_RELOC_SH_TLS_LD_32 ENUMX BFD_RELOC_SH_TLS_LDO_32 ENUMX BFD_RELOC_SH_TLS_IE_32 ENUMX BFD_RELOC_SH_TLS_LE_32 ENUMX BFD_RELOC_SH_TLS_DTPMOD32 ENUMX BFD_RELOC_SH_TLS_DTPOFF32 ENUMX BFD_RELOC_SH_TLS_TPOFF32 ENUMDOC Renesas / SuperH SH relocs. Not all of these appear in object files. ENUM BFD_RELOC_ARC_B22_PCREL ENUMDOC ARC Cores relocs. ARC 22 bit pc-relative branch. The lowest two bits must be zero and are not stored in the instruction. The high 20 bits are installed in bits 26 through 7 of the instruction. ENUM BFD_RELOC_ARC_B26 ENUMDOC ARC 26 bit absolute branch. The lowest two bits must be zero and are not stored in the instruction. The high 24 bits are installed in bits 23 through 0. ENUM BFD_RELOC_BFIN_16_IMM ENUMDOC ADI Blackfin 16 bit immediate absolute reloc. ENUM BFD_RELOC_BFIN_16_HIGH ENUMDOC ADI Blackfin 16 bit immediate absolute reloc higher 16 bits. ENUM BFD_RELOC_BFIN_4_PCREL ENUMDOC ADI Blackfin 'a' part of LSETUP. ENUM BFD_RELOC_BFIN_5_PCREL ENUMDOC ADI Blackfin. ENUM BFD_RELOC_BFIN_16_LOW ENUMDOC ADI Blackfin 16 bit immediate absolute reloc lower 16 bits. ENUM BFD_RELOC_BFIN_10_PCREL ENUMDOC ADI Blackfin. ENUM BFD_RELOC_BFIN_11_PCREL ENUMDOC ADI Blackfin 'b' part of LSETUP. ENUM BFD_RELOC_BFIN_12_PCREL_JUMP ENUMDOC ADI Blackfin. ENUM BFD_RELOC_BFIN_12_PCREL_JUMP_S ENUMDOC ADI Blackfin Short jump, pcrel. ENUM BFD_RELOC_BFIN_24_PCREL_CALL_X ENUMDOC ADI Blackfin Call.x not implemented. ENUM BFD_RELOC_BFIN_24_PCREL_JUMP_L 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. ENUM BFD_RELOC_BFIN_PLTPC ENUMDOC ADI Blackfin PLTPC relocation. ENUM BFD_ARELOC_BFIN_PUSH ENUMDOC ADI Blackfin arithmetic relocation. ENUM BFD_ARELOC_BFIN_CONST ENUMDOC ADI Blackfin arithmetic relocation. ENUM BFD_ARELOC_BFIN_ADD ENUMDOC ADI Blackfin arithmetic relocation. ENUM BFD_ARELOC_BFIN_SUB ENUMDOC ADI Blackfin arithmetic relocation. ENUM BFD_ARELOC_BFIN_MULT ENUMDOC ADI Blackfin arithmetic relocation. ENUM BFD_ARELOC_BFIN_DIV ENUMDOC ADI Blackfin arithmetic relocation. ENUM BFD_ARELOC_BFIN_MOD ENUMDOC ADI Blackfin arithmetic relocation. ENUM BFD_ARELOC_BFIN_LSHIFT ENUMDOC ADI Blackfin arithmetic relocation. ENUM BFD_ARELOC_BFIN_RSHIFT ENUMDOC ADI Blackfin arithmetic relocation. ENUM BFD_ARELOC_BFIN_AND ENUMDOC ADI Blackfin arithmetic relocation. ENUM BFD_ARELOC_BFIN_OR ENUMDOC ADI Blackfin arithmetic relocation. ENUM BFD_ARELOC_BFIN_XOR ENUMDOC ADI Blackfin arithmetic relocation. ENUM BFD_ARELOC_BFIN_LAND ENUMDOC ADI Blackfin arithmetic relocation. ENUM BFD_ARELOC_BFIN_LOR ENUMDOC ADI Blackfin arithmetic relocation. ENUM BFD_ARELOC_BFIN_LEN ENUMDOC ADI Blackfin arithmetic relocation. ENUM BFD_ARELOC_BFIN_NEG ENUMDOC ADI Blackfin arithmetic relocation. ENUM BFD_ARELOC_BFIN_COMP ENUMDOC ADI Blackfin arithmetic relocation. ENUM BFD_ARELOC_BFIN_PAGE ENUMDOC ADI Blackfin arithmetic relocation. ENUM BFD_ARELOC_BFIN_HWPAGE ENUMDOC ADI Blackfin arithmetic relocation. ENUM BFD_ARELOC_BFIN_ADDR ENUMDOC ADI Blackfin arithmetic relocation. ENUM BFD_RELOC_D10V_10_PCREL_R ENUMDOC Mitsubishi D10V relocs. This is a 10-bit reloc with the right 2 bits assumed to be 0. ENUM BFD_RELOC_D10V_10_PCREL_L ENUMDOC Mitsubishi D10V relocs. This is a 10-bit reloc with the right 2 bits assumed to be 0. This is the same as the previous reloc except it is in the left container, i.e., shifted left 15 bits. ENUM BFD_RELOC_D10V_18 ENUMDOC This is an 18-bit reloc with the right 2 bits assumed to be 0. ENUM BFD_RELOC_D10V_18_PCREL ENUMDOC This is an 18-bit reloc with the right 2 bits assumed to be 0. ENUM BFD_RELOC_D30V_6 ENUMDOC Mitsubishi D30V relocs. This is a 6-bit absolute reloc. ENUM BFD_RELOC_D30V_9_PCREL ENUMDOC This is a 6-bit pc-relative reloc with the right 3 bits assumed to be 0. ENUM BFD_RELOC_D30V_9_PCREL_R ENUMDOC This is a 6-bit pc-relative reloc with the right 3 bits assumed to be 0. Same as the previous reloc but on the right side of the container. ENUM BFD_RELOC_D30V_15 ENUMDOC This is a 12-bit absolute reloc with the right 3 bitsassumed to be 0. ENUM BFD_RELOC_D30V_15_PCREL ENUMDOC This is a 12-bit pc-relative reloc with the right 3 bits assumed to be 0. ENUM BFD_RELOC_D30V_15_PCREL_R ENUMDOC This is a 12-bit pc-relative reloc with the right 3 bits assumed to be 0. Same as the previous reloc but on the right side of the container. ENUM BFD_RELOC_D30V_21 ENUMDOC This is an 18-bit absolute reloc with the right 3 bits assumed to be 0. ENUM BFD_RELOC_D30V_21_PCREL ENUMDOC This is an 18-bit pc-relative reloc with the right 3 bits assumed to be 0. ENUM BFD_RELOC_D30V_21_PCREL_R ENUMDOC This is an 18-bit pc-relative reloc with the right 3 bits assumed to be 0. Same as the previous reloc but on the right side of the container. ENUM BFD_RELOC_D30V_32 ENUMDOC This is a 32-bit absolute reloc. ENUM BFD_RELOC_D30V_32_PCREL ENUMDOC This is a 32-bit pc-relative reloc. ENUM BFD_RELOC_DLX_HI16_S ENUMDOC DLX relocs ENUM BFD_RELOC_DLX_LO16 ENUMDOC DLX relocs ENUM BFD_RELOC_DLX_JMP26 ENUMDOC DLX relocs ENUM BFD_RELOC_M32C_HI8 ENUMX BFD_RELOC_M32C_RL_JUMP ENUMX BFD_RELOC_M32C_RL_1ADDR ENUMX BFD_RELOC_M32C_RL_2ADDR ENUMDOC Renesas M16C/M32C Relocations. ENUM BFD_RELOC_M32R_24 ENUMDOC Renesas M32R (formerly Mitsubishi M32R) relocs. This is a 24 bit absolute address. ENUM BFD_RELOC_M32R_10_PCREL ENUMDOC This is a 10-bit pc-relative reloc with the right 2 bits assumed to be 0. ENUM BFD_RELOC_M32R_18_PCREL ENUMDOC This is an 18-bit reloc with the right 2 bits assumed to be 0. ENUM BFD_RELOC_M32R_26_PCREL ENUMDOC This is a 26-bit reloc with the right 2 bits assumed to be 0. ENUM BFD_RELOC_M32R_HI16_ULO ENUMDOC This is a 16-bit reloc containing the high 16 bits of an address used when the lower 16 bits are treated as unsigned. ENUM BFD_RELOC_M32R_HI16_SLO ENUMDOC This is a 16-bit reloc containing the high 16 bits of an address used when the lower 16 bits are treated as signed. ENUM BFD_RELOC_M32R_LO16 ENUMDOC This is a 16-bit reloc containing the lower 16 bits of an address. ENUM BFD_RELOC_M32R_SDA16 ENUMDOC This is a 16-bit reloc containing the small data area offset for use in add3, load, and store instructions. ENUM BFD_RELOC_M32R_GOT24 ENUMX BFD_RELOC_M32R_26_PLTREL ENUMX BFD_RELOC_M32R_COPY ENUMX BFD_RELOC_M32R_GLOB_DAT ENUMX BFD_RELOC_M32R_JMP_SLOT ENUMX BFD_RELOC_M32R_RELATIVE ENUMX BFD_RELOC_M32R_GOTOFF ENUMX BFD_RELOC_M32R_GOTOFF_HI_ULO ENUMX BFD_RELOC_M32R_GOTOFF_HI_SLO ENUMX BFD_RELOC_M32R_GOTOFF_LO ENUMX BFD_RELOC_M32R_GOTPC24 ENUMX BFD_RELOC_M32R_GOT16_HI_ULO ENUMX BFD_RELOC_M32R_GOT16_HI_SLO ENUMX BFD_RELOC_M32R_GOT16_LO ENUMX BFD_RELOC_M32R_GOTPC_HI_ULO ENUMX BFD_RELOC_M32R_GOTPC_HI_SLO ENUMX BFD_RELOC_M32R_GOTPC_LO ENUMDOC For PIC. ENUM BFD_RELOC_V850_9_PCREL ENUMDOC This is a 9-bit reloc ENUM BFD_RELOC_V850_22_PCREL ENUMDOC This is a 22-bit reloc ENUM BFD_RELOC_V850_SDA_16_16_OFFSET ENUMDOC This is a 16 bit offset from the short data area pointer. ENUM BFD_RELOC_V850_SDA_15_16_OFFSET ENUMDOC This is a 16 bit offset (of which only 15 bits are used) from the short data area pointer. ENUM BFD_RELOC_V850_ZDA_16_16_OFFSET ENUMDOC This is a 16 bit offset from the zero data area pointer. ENUM BFD_RELOC_V850_ZDA_15_16_OFFSET ENUMDOC This is a 16 bit offset (of which only 15 bits are used) from the zero data area pointer. ENUM BFD_RELOC_V850_TDA_6_8_OFFSET ENUMDOC This is an 8 bit offset (of which only 6 bits are used) from the tiny data area pointer. ENUM BFD_RELOC_V850_TDA_7_8_OFFSET ENUMDOC This is an 8bit offset (of which only 7 bits are used) from the tiny data area pointer. ENUM BFD_RELOC_V850_TDA_7_7_OFFSET ENUMDOC This is a 7 bit offset from the tiny data area pointer. ENUM BFD_RELOC_V850_TDA_16_16_OFFSET ENUMDOC This is a 16 bit offset from the tiny data area pointer. COMMENT ENUM BFD_RELOC_V850_TDA_4_5_OFFSET ENUMDOC This is a 5 bit offset (of which only 4 bits are used) from the tiny data area pointer. ENUM BFD_RELOC_V850_TDA_4_4_OFFSET ENUMDOC This is a 4 bit offset from the tiny data area pointer. ENUM BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET ENUMDOC This is a 16 bit offset from the short data area pointer, with the bits placed non-contiguously in the instruction. ENUM BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET ENUMDOC This is a 16 bit offset from the zero data area pointer, with the bits placed non-contiguously in the instruction. ENUM BFD_RELOC_V850_CALLT_6_7_OFFSET ENUMDOC This is a 6 bit offset from the call table base pointer. ENUM BFD_RELOC_V850_CALLT_16_16_OFFSET ENUMDOC This is a 16 bit offset from the call table base pointer. ENUM BFD_RELOC_V850_LONGCALL ENUMDOC Used for relaxing indirect function calls. ENUM BFD_RELOC_V850_LONGJUMP ENUMDOC Used for relaxing indirect jumps. ENUM BFD_RELOC_V850_ALIGN ENUMDOC Used to maintain alignment whilst relaxing. ENUM BFD_RELOC_V850_LO16_SPLIT_OFFSET ENUMDOC This is a variation of BFD_RELOC_LO16 that can be used in v850e ld.bu instructions. ENUM BFD_RELOC_MN10300_32_PCREL ENUMDOC This is a 32bit pcrel reloc for the mn10300, offset by two bytes in the instruction. ENUM BFD_RELOC_MN10300_16_PCREL ENUMDOC This is a 16bit pcrel reloc for the mn10300, offset by two bytes in the instruction. ENUM BFD_RELOC_TIC30_LDP ENUMDOC This is a 8bit DP reloc for the tms320c30, where the most significant 8 bits of a 24 bit word are placed into the least significant 8 bits of the opcode. ENUM BFD_RELOC_TIC54X_PARTLS7 ENUMDOC This is a 7bit reloc for the tms320c54x, where the least significant 7 bits of a 16 bit word are placed into the least significant 7 bits of the opcode. ENUM BFD_RELOC_TIC54X_PARTMS9 ENUMDOC This is a 9bit DP reloc for the tms320c54x, where the most significant 9 bits of a 16 bit word are placed into the least significant 9 bits of the opcode. ENUM BFD_RELOC_TIC54X_23 ENUMDOC This is an extended address 23-bit reloc for the tms320c54x. ENUM BFD_RELOC_TIC54X_16_OF_23 ENUMDOC This is a 16-bit reloc for the tms320c54x, where the least significant 16 bits of a 23-bit extended address are placed into the opcode. ENUM BFD_RELOC_TIC54X_MS7_OF_23 ENUMDOC This is a reloc for the tms320c54x, where the most significant 7 bits of a 23-bit extended address are placed into the opcode. ENUM BFD_RELOC_FR30_48 ENUMDOC This is a 48 bit reloc for the FR30 that stores 32 bits. ENUM BFD_RELOC_FR30_20 ENUMDOC This is a 32 bit reloc for the FR30 that stores 20 bits split up into two sections. ENUM BFD_RELOC_FR30_6_IN_4 ENUMDOC This is a 16 bit reloc for the FR30 that stores a 6 bit word offset in 4 bits. ENUM BFD_RELOC_FR30_8_IN_8 ENUMDOC This is a 16 bit reloc for the FR30 that stores an 8 bit byte offset into 8 bits. ENUM BFD_RELOC_FR30_9_IN_8 ENUMDOC This is a 16 bit reloc for the FR30 that stores a 9 bit short offset into 8 bits. ENUM BFD_RELOC_FR30_10_IN_8 ENUMDOC This is a 16 bit reloc for the FR30 that stores a 10 bit word offset into 8 bits. ENUM BFD_RELOC_FR30_9_PCREL ENUMDOC This is a 16 bit reloc for the FR30 that stores a 9 bit pc relative short offset into 8 bits. ENUM BFD_RELOC_FR30_12_PCREL ENUMDOC This is a 16 bit reloc for the FR30 that stores a 12 bit pc relative short offset into 11 bits. ENUM BFD_RELOC_MCORE_PCREL_IMM8BY4 ENUMX BFD_RELOC_MCORE_PCREL_IMM11BY2 ENUMX BFD_RELOC_MCORE_PCREL_IMM4BY2 ENUMX BFD_RELOC_MCORE_PCREL_32 ENUMX BFD_RELOC_MCORE_PCREL_JSR_IMM11BY2 ENUMX BFD_RELOC_MCORE_RVA ENUMDOC Motorola Mcore relocations. ENUM BFD_RELOC_MEP_8 ENUMX BFD_RELOC_MEP_16 ENUMX BFD_RELOC_MEP_32 ENUMX BFD_RELOC_MEP_PCREL8A2 ENUMX BFD_RELOC_MEP_PCREL12A2 ENUMX BFD_RELOC_MEP_PCREL17A2 ENUMX BFD_RELOC_MEP_PCREL24A2 ENUMX BFD_RELOC_MEP_PCABS24A2 ENUMX BFD_RELOC_MEP_LOW16 ENUMX BFD_RELOC_MEP_HI16U ENUMX BFD_RELOC_MEP_HI16S ENUMX BFD_RELOC_MEP_GPREL ENUMX BFD_RELOC_MEP_TPREL ENUMX BFD_RELOC_MEP_TPREL7 ENUMX BFD_RELOC_MEP_TPREL7A2 ENUMX BFD_RELOC_MEP_TPREL7A4 ENUMX BFD_RELOC_MEP_UIMM24 ENUMX BFD_RELOC_MEP_ADDR24A4 ENUMX BFD_RELOC_MEP_GNU_VTINHERIT ENUMX BFD_RELOC_MEP_GNU_VTENTRY ENUMDOC Toshiba Media Processor Relocations. COMMENT ENUM BFD_RELOC_MMIX_GETA ENUMX BFD_RELOC_MMIX_GETA_1 ENUMX BFD_RELOC_MMIX_GETA_2 ENUMX BFD_RELOC_MMIX_GETA_3 ENUMDOC These are relocations for the GETA instruction. ENUM BFD_RELOC_MMIX_CBRANCH ENUMX BFD_RELOC_MMIX_CBRANCH_J ENUMX BFD_RELOC_MMIX_CBRANCH_1 ENUMX BFD_RELOC_MMIX_CBRANCH_2 ENUMX BFD_RELOC_MMIX_CBRANCH_3 ENUMDOC These are relocations for a conditional branch instruction. ENUM BFD_RELOC_MMIX_PUSHJ ENUMX BFD_RELOC_MMIX_PUSHJ_1 ENUMX BFD_RELOC_MMIX_PUSHJ_2 ENUMX BFD_RELOC_MMIX_PUSHJ_3 ENUMX BFD_RELOC_MMIX_PUSHJ_STUBBABLE ENUMDOC These are relocations for the PUSHJ instruction. ENUM BFD_RELOC_MMIX_JMP ENUMX BFD_RELOC_MMIX_JMP_1 ENUMX BFD_RELOC_MMIX_JMP_2 ENUMX BFD_RELOC_MMIX_JMP_3 ENUMDOC These are relocations for the JMP instruction. ENUM BFD_RELOC_MMIX_ADDR19 ENUMDOC This is a relocation for a relative address as in a GETA instruction or a branch. ENUM BFD_RELOC_MMIX_ADDR27 ENUMDOC This is a relocation for a relative address as in a JMP instruction. ENUM BFD_RELOC_MMIX_REG_OR_BYTE ENUMDOC This is a relocation for an instruction field that may be a general register or a value 0..255. ENUM BFD_RELOC_MMIX_REG ENUMDOC This is a relocation for an instruction field that may be a general register. ENUM BFD_RELOC_MMIX_BASE_PLUS_OFFSET ENUMDOC This is a relocation for two instruction fields holding a register and an offset, the equivalent of the relocation. ENUM BFD_RELOC_MMIX_LOCAL ENUMDOC This relocation is an assertion that the expression is not allocated as a global register. It does not modify contents. ENUM BFD_RELOC_AVR_7_PCREL ENUMDOC This is a 16 bit reloc for the AVR that stores 8 bit pc relative short offset into 7 bits. ENUM BFD_RELOC_AVR_13_PCREL ENUMDOC This is a 16 bit reloc for the AVR that stores 13 bit pc relative short offset into 12 bits. ENUM BFD_RELOC_AVR_16_PM ENUMDOC This is a 16 bit reloc for the AVR that stores 17 bit value (usually program memory address) into 16 bits. ENUM BFD_RELOC_AVR_LO8_LDI ENUMDOC This is a 16 bit reloc for the AVR that stores 8 bit value (usually data memory address) into 8 bit immediate value of LDI insn. ENUM BFD_RELOC_AVR_HI8_LDI ENUMDOC This is a 16 bit reloc for the AVR that stores 8 bit value (high 8 bit of data memory address) into 8 bit immediate value of LDI insn. ENUM BFD_RELOC_AVR_HH8_LDI ENUMDOC This is a 16 bit reloc for the AVR that stores 8 bit value (most high 8 bit of program memory address) into 8 bit immediate value of LDI insn. ENUM BFD_RELOC_AVR_MS8_LDI ENUMDOC This is a 16 bit reloc for the AVR that stores 8 bit value (most high 8 bit of 32 bit value) into 8 bit immediate value of LDI insn. ENUM BFD_RELOC_AVR_LO8_LDI_NEG ENUMDOC This is a 16 bit reloc for the AVR that stores negated 8 bit value (usually data memory address) into 8 bit immediate value of SUBI insn. ENUM BFD_RELOC_AVR_HI8_LDI_NEG ENUMDOC This is a 16 bit reloc for the AVR that stores negated 8 bit value (high 8 bit of data memory address) into 8 bit immediate value of SUBI insn. ENUM BFD_RELOC_AVR_HH8_LDI_NEG ENUMDOC This is a 16 bit reloc for the AVR that stores negated 8 bit value (most high 8 bit of program memory address) into 8 bit immediate value of LDI or SUBI insn. ENUM BFD_RELOC_AVR_MS8_LDI_NEG ENUMDOC This is a 16 bit reloc for the AVR that stores negated 8 bit value (msb of 32 bit value) into 8 bit immediate value of LDI insn. ENUM BFD_RELOC_AVR_LO8_LDI_PM ENUMDOC This is a 16 bit reloc for the AVR that stores 8 bit value (usually command address) into 8 bit immediate value of LDI insn. ENUM BFD_RELOC_AVR_LO8_LDI_GS ENUMDOC This is a 16 bit reloc for the AVR that stores 8 bit value (command address) into 8 bit immediate value of LDI insn. If the address is beyond the 128k boundary, the linker inserts a jump stub for this reloc in the lower 128k. ENUM BFD_RELOC_AVR_HI8_LDI_PM ENUMDOC This is a 16 bit reloc for the AVR that stores 8 bit value (high 8 bit of command address) into 8 bit immediate value of LDI insn. ENUM BFD_RELOC_AVR_HI8_LDI_GS ENUMDOC This is a 16 bit reloc for the AVR that stores 8 bit value (high 8 bit of command address) into 8 bit immediate value of LDI insn. If the address is beyond the 128k boundary, the linker inserts a jump stub for this reloc below 128k. ENUM BFD_RELOC_AVR_HH8_LDI_PM ENUMDOC This is a 16 bit reloc for the AVR that stores 8 bit value (most high 8 bit of command address) into 8 bit immediate value of LDI insn. ENUM BFD_RELOC_AVR_LO8_LDI_PM_NEG ENUMDOC This is a 16 bit reloc for the AVR that stores negated 8 bit value (usually command address) into 8 bit immediate value of SUBI insn. ENUM BFD_RELOC_AVR_HI8_LDI_PM_NEG ENUMDOC This is a 16 bit reloc for the AVR that stores negated 8 bit value (high 8 bit of 16 bit command address) into 8 bit immediate value of SUBI insn. ENUM BFD_RELOC_AVR_HH8_LDI_PM_NEG ENUMDOC This is a 16 bit reloc for the AVR that stores negated 8 bit value (high 6 bit of 22 bit command address) into 8 bit immediate value of SUBI insn. ENUM BFD_RELOC_AVR_CALL ENUMDOC This is a 32 bit reloc for the AVR that stores 23 bit value into 22 bits. ENUM BFD_RELOC_AVR_LDI ENUMDOC This is a 16 bit reloc for the AVR that stores all needed bits for absolute addressing with ldi with overflow check to linktime ENUM BFD_RELOC_AVR_6 ENUMDOC This is a 6 bit reloc for the AVR that stores offset for ldd/std instructions ENUM BFD_RELOC_AVR_6_ADIW ENUMDOC This is a 6 bit reloc for the AVR that stores offset for adiw/sbiw instructions ENUM BFD_RELOC_390_12 ENUMDOC Direct 12 bit. ENUM BFD_RELOC_390_GOT12 ENUMDOC 12 bit GOT offset. ENUM BFD_RELOC_390_PLT32 ENUMDOC 32 bit PC relative PLT address. ENUM BFD_RELOC_390_COPY ENUMDOC Copy symbol at runtime. ENUM BFD_RELOC_390_GLOB_DAT ENUMDOC Create GOT entry. ENUM BFD_RELOC_390_JMP_SLOT ENUMDOC Create PLT entry. ENUM BFD_RELOC_390_RELATIVE ENUMDOC Adjust by program base. ENUM BFD_RELOC_390_GOTPC ENUMDOC 32 bit PC relative offset to GOT. ENUM BFD_RELOC_390_GOT16 ENUMDOC 16 bit GOT offset. ENUM BFD_RELOC_390_PC16DBL ENUMDOC PC relative 16 bit shifted by 1. ENUM BFD_RELOC_390_PLT16DBL ENUMDOC 16 bit PC rel. PLT shifted by 1. ENUM BFD_RELOC_390_PC32DBL ENUMDOC PC relative 32 bit shifted by 1. ENUM BFD_RELOC_390_PLT32DBL ENUMDOC 32 bit PC rel. PLT shifted by 1. ENUM BFD_RELOC_390_GOTPCDBL ENUMDOC 32 bit PC rel. GOT shifted by 1. ENUM BFD_RELOC_390_GOT64 ENUMDOC 64 bit GOT offset. ENUM BFD_RELOC_390_PLT64 ENUMDOC 64 bit PC relative PLT address. ENUM BFD_RELOC_390_GOTENT ENUMDOC 32 bit rel. offset to GOT entry. ENUM BFD_RELOC_390_GOTOFF64 ENUMDOC 64 bit offset to GOT. ENUM BFD_RELOC_390_GOTPLT12 ENUMDOC 12-bit offset to symbol-entry within GOT, with PLT handling. ENUM BFD_RELOC_390_GOTPLT16 ENUMDOC 16-bit offset to symbol-entry within GOT, with PLT handling. ENUM BFD_RELOC_390_GOTPLT32 ENUMDOC 32-bit offset to symbol-entry within GOT, with PLT handling. ENUM BFD_RELOC_390_GOTPLT64 ENUMDOC 64-bit offset to symbol-entry within GOT, with PLT handling. ENUM BFD_RELOC_390_GOTPLTENT ENUMDOC 32-bit rel. offset to symbol-entry within GOT, with PLT handling. ENUM BFD_RELOC_390_PLTOFF16 ENUMDOC 16-bit rel. offset from the GOT to a PLT entry. ENUM BFD_RELOC_390_PLTOFF32 ENUMDOC 32-bit rel. offset from the GOT to a PLT entry. ENUM BFD_RELOC_390_PLTOFF64 ENUMDOC 64-bit rel. offset from the GOT to a PLT entry. ENUM BFD_RELOC_390_TLS_LOAD ENUMX BFD_RELOC_390_TLS_GDCALL ENUMX BFD_RELOC_390_TLS_LDCALL ENUMX BFD_RELOC_390_TLS_GD32 ENUMX BFD_RELOC_390_TLS_GD64 ENUMX BFD_RELOC_390_TLS_GOTIE12 ENUMX BFD_RELOC_390_TLS_GOTIE32 ENUMX BFD_RELOC_390_TLS_GOTIE64 ENUMX BFD_RELOC_390_TLS_LDM32 ENUMX BFD_RELOC_390_TLS_LDM64 ENUMX BFD_RELOC_390_TLS_IE32 ENUMX BFD_RELOC_390_TLS_IE64 ENUMX BFD_RELOC_390_TLS_IEENT ENUMX BFD_RELOC_390_TLS_LE32 ENUMX BFD_RELOC_390_TLS_LE64 ENUMX BFD_RELOC_390_TLS_LDO32 ENUMX BFD_RELOC_390_TLS_LDO64 ENUMX BFD_RELOC_390_TLS_DTPMOD ENUMX BFD_RELOC_390_TLS_DTPOFF ENUMX BFD_RELOC_390_TLS_TPOFF ENUMDOC s390 tls relocations. ENUM BFD_RELOC_390_20 ENUMX BFD_RELOC_390_GOT20 ENUMX BFD_RELOC_390_GOTPLT20 ENUMX BFD_RELOC_390_TLS_GOTIE20 ENUMDOC Long displacement extension. ENUM BFD_RELOC_SCORE_DUMMY1 ENUMDOC Score relocations ENUM BFD_RELOC_SCORE_GPREL15 ENUMDOC Low 16 bit for load/store ENUM BFD_RELOC_SCORE_DUMMY2 ENUMX BFD_RELOC_SCORE_JMP ENUMDOC This is a 24-bit reloc with the right 1 bit assumed to be 0 ENUM BFD_RELOC_SCORE_BRANCH ENUMDOC This is a 19-bit reloc with the right 1 bit assumed to be 0 ENUM BFD_RELOC_SCORE16_JMP ENUMDOC This is a 11-bit reloc with the right 1 bit assumed to be 0 ENUM BFD_RELOC_SCORE16_BRANCH ENUMDOC This is a 8-bit reloc with the right 1 bit assumed to be 0 ENUM BFD_RELOC_SCORE_GOT15 ENUMX BFD_RELOC_SCORE_GOT_LO16 ENUMX BFD_RELOC_SCORE_CALL15 ENUMX BFD_RELOC_SCORE_DUMMY_HI16 ENUMDOC Undocumented Score relocs ENUM BFD_RELOC_IP2K_FR9 ENUMDOC Scenix IP2K - 9-bit register number / data address ENUM BFD_RELOC_IP2K_BANK ENUMDOC Scenix IP2K - 4-bit register/data bank number ENUM BFD_RELOC_IP2K_ADDR16CJP ENUMDOC Scenix IP2K - low 13 bits of instruction word address ENUM BFD_RELOC_IP2K_PAGE3 ENUMDOC Scenix IP2K - high 3 bits of instruction word address ENUM BFD_RELOC_IP2K_LO8DATA ENUMX BFD_RELOC_IP2K_HI8DATA ENUMX BFD_RELOC_IP2K_EX8DATA ENUMDOC Scenix IP2K - ext/low/high 8 bits of data address ENUM BFD_RELOC_IP2K_LO8INSN ENUMX BFD_RELOC_IP2K_HI8INSN ENUMDOC Scenix IP2K - low/high 8 bits of instruction word address ENUM BFD_RELOC_IP2K_PC_SKIP ENUMDOC Scenix IP2K - even/odd PC modifier to modify snb pcl.0 ENUM BFD_RELOC_IP2K_TEXT ENUMDOC Scenix IP2K - 16 bit word address in text section. ENUM BFD_RELOC_IP2K_FR_OFFSET ENUMDOC Scenix IP2K - 7-bit sp or dp offset ENUM BFD_RELOC_VPE4KMATH_DATA ENUMX BFD_RELOC_VPE4KMATH_INSN ENUMDOC Scenix VPE4K coprocessor - data/insn-space addressing ENUM BFD_RELOC_VTABLE_INHERIT ENUMX BFD_RELOC_VTABLE_ENTRY ENUMDOC These two relocations are used by the linker to determine which of the entries in a C++ virtual function table are actually used. When the --gc-sections option is given, the linker will zero out the entries that are not used, so that the code for those functions need not be included in the output. VTABLE_INHERIT is a zero-space relocation used to describe to the linker the inheritance tree of a C++ virtual function table. The relocation's symbol should be the parent class' vtable, and the relocation should be located at the child vtable. VTABLE_ENTRY is a zero-space relocation that describes the use of a virtual function table entry. The reloc's symbol should refer to the table of the class mentioned in the code. Off of that base, an offset describes the entry that is being used. For Rela hosts, this offset is stored in the reloc's addend. For Rel hosts, we are forced to put this offset in the reloc's section offset. ENUM BFD_RELOC_IA64_IMM14 ENUMX BFD_RELOC_IA64_IMM22 ENUMX BFD_RELOC_IA64_IMM64 ENUMX BFD_RELOC_IA64_DIR32MSB ENUMX BFD_RELOC_IA64_DIR32LSB ENUMX BFD_RELOC_IA64_DIR64MSB ENUMX BFD_RELOC_IA64_DIR64LSB ENUMX BFD_RELOC_IA64_GPREL22 ENUMX BFD_RELOC_IA64_GPREL64I ENUMX BFD_RELOC_IA64_GPREL32MSB ENUMX BFD_RELOC_IA64_GPREL32LSB ENUMX BFD_RELOC_IA64_GPREL64MSB ENUMX BFD_RELOC_IA64_GPREL64LSB ENUMX BFD_RELOC_IA64_LTOFF22 ENUMX BFD_RELOC_IA64_LTOFF64I ENUMX BFD_RELOC_IA64_PLTOFF22 ENUMX BFD_RELOC_IA64_PLTOFF64I ENUMX BFD_RELOC_IA64_PLTOFF64MSB ENUMX BFD_RELOC_IA64_PLTOFF64LSB ENUMX BFD_RELOC_IA64_FPTR64I ENUMX BFD_RELOC_IA64_FPTR32MSB ENUMX BFD_RELOC_IA64_FPTR32LSB ENUMX BFD_RELOC_IA64_FPTR64MSB ENUMX BFD_RELOC_IA64_FPTR64LSB ENUMX BFD_RELOC_IA64_PCREL21B ENUMX BFD_RELOC_IA64_PCREL21BI ENUMX BFD_RELOC_IA64_PCREL21M ENUMX BFD_RELOC_IA64_PCREL21F ENUMX BFD_RELOC_IA64_PCREL22 ENUMX BFD_RELOC_IA64_PCREL60B ENUMX BFD_RELOC_IA64_PCREL64I ENUMX BFD_RELOC_IA64_PCREL32MSB ENUMX BFD_RELOC_IA64_PCREL32LSB ENUMX BFD_RELOC_IA64_PCREL64MSB ENUMX BFD_RELOC_IA64_PCREL64LSB ENUMX BFD_RELOC_IA64_LTOFF_FPTR22 ENUMX BFD_RELOC_IA64_LTOFF_FPTR64I ENUMX BFD_RELOC_IA64_LTOFF_FPTR32MSB ENUMX BFD_RELOC_IA64_LTOFF_FPTR32LSB ENUMX BFD_RELOC_IA64_LTOFF_FPTR64MSB ENUMX BFD_RELOC_IA64_LTOFF_FPTR64LSB ENUMX BFD_RELOC_IA64_SEGREL32MSB ENUMX BFD_RELOC_IA64_SEGREL32LSB ENUMX BFD_RELOC_IA64_SEGREL64MSB ENUMX BFD_RELOC_IA64_SEGREL64LSB ENUMX BFD_RELOC_IA64_SECREL32MSB ENUMX BFD_RELOC_IA64_SECREL32LSB ENUMX BFD_RELOC_IA64_SECREL64MSB ENUMX BFD_RELOC_IA64_SECREL64LSB ENUMX BFD_RELOC_IA64_REL32MSB ENUMX BFD_RELOC_IA64_REL32LSB ENUMX BFD_RELOC_IA64_REL64MSB ENUMX BFD_RELOC_IA64_REL64LSB ENUMX BFD_RELOC_IA64_LTV32MSB ENUMX BFD_RELOC_IA64_LTV32LSB ENUMX BFD_RELOC_IA64_LTV64MSB ENUMX BFD_RELOC_IA64_LTV64LSB ENUMX BFD_RELOC_IA64_IPLTMSB ENUMX BFD_RELOC_IA64_IPLTLSB ENUMX BFD_RELOC_IA64_COPY ENUMX BFD_RELOC_IA64_LTOFF22X ENUMX BFD_RELOC_IA64_LDXMOV ENUMX BFD_RELOC_IA64_TPREL14 ENUMX BFD_RELOC_IA64_TPREL22 ENUMX BFD_RELOC_IA64_TPREL64I ENUMX BFD_RELOC_IA64_TPREL64MSB ENUMX BFD_RELOC_IA64_TPREL64LSB ENUMX BFD_RELOC_IA64_LTOFF_TPREL22 ENUMX BFD_RELOC_IA64_DTPMOD64MSB ENUMX BFD_RELOC_IA64_DTPMOD64LSB ENUMX BFD_RELOC_IA64_LTOFF_DTPMOD22 ENUMX BFD_RELOC_IA64_DTPREL14 ENUMX BFD_RELOC_IA64_DTPREL22 ENUMX BFD_RELOC_IA64_DTPREL64I ENUMX BFD_RELOC_IA64_DTPREL32MSB ENUMX BFD_RELOC_IA64_DTPREL32LSB ENUMX BFD_RELOC_IA64_DTPREL64MSB ENUMX BFD_RELOC_IA64_DTPREL64LSB ENUMX BFD_RELOC_IA64_LTOFF_DTPREL22 ENUMDOC Intel IA64 Relocations. ENUM BFD_RELOC_M68HC11_HI8 ENUMDOC Motorola 68HC11 reloc. This is the 8 bit high part of an absolute address. ENUM BFD_RELOC_M68HC11_LO8 ENUMDOC Motorola 68HC11 reloc. This is the 8 bit low part of an absolute address. ENUM BFD_RELOC_M68HC11_3B ENUMDOC Motorola 68HC11 reloc. This is the 3 bit of a value. ENUM BFD_RELOC_M68HC11_RL_JUMP ENUMDOC Motorola 68HC11 reloc. This reloc marks the beginning of a jump/call instruction. It is used for linker relaxation to correctly identify beginning of instruction and change some branches to use PC-relative addressing mode. ENUM BFD_RELOC_M68HC11_RL_GROUP ENUMDOC Motorola 68HC11 reloc. This reloc marks a group of several instructions that gcc generates and for which the linker relaxation pass can modify and/or remove some of them. ENUM BFD_RELOC_M68HC11_LO16 ENUMDOC Motorola 68HC11 reloc. This is the 16-bit lower part of an address. It is used for 'call' instruction to specify the symbol address without any special transformation (due to memory bank window). ENUM BFD_RELOC_M68HC11_PAGE ENUMDOC Motorola 68HC11 reloc. This is a 8-bit reloc that specifies the page number of an address. It is used by 'call' instruction to specify the page number of the symbol. ENUM BFD_RELOC_M68HC11_24 ENUMDOC Motorola 68HC11 reloc. This is a 24-bit reloc that represents the address with a 16-bit value and a 8-bit page number. The symbol address is transformed to follow the 16K memory bank of 68HC12 (seen as mapped in the window). ENUM BFD_RELOC_M68HC12_5B ENUMDOC Motorola 68HC12 reloc. This is the 5 bits of a value. ENUM BFD_RELOC_16C_NUM08 ENUMX BFD_RELOC_16C_NUM08_C ENUMX BFD_RELOC_16C_NUM16 ENUMX BFD_RELOC_16C_NUM16_C ENUMX BFD_RELOC_16C_NUM32 ENUMX BFD_RELOC_16C_NUM32_C ENUMX BFD_RELOC_16C_DISP04 ENUMX BFD_RELOC_16C_DISP04_C ENUMX BFD_RELOC_16C_DISP08 ENUMX BFD_RELOC_16C_DISP08_C ENUMX BFD_RELOC_16C_DISP16 ENUMX BFD_RELOC_16C_DISP16_C ENUMX BFD_RELOC_16C_DISP24 ENUMX BFD_RELOC_16C_DISP24_C ENUMX BFD_RELOC_16C_DISP24a ENUMX BFD_RELOC_16C_DISP24a_C ENUMX BFD_RELOC_16C_REG04 ENUMX BFD_RELOC_16C_REG04_C ENUMX BFD_RELOC_16C_REG04a ENUMX BFD_RELOC_16C_REG04a_C ENUMX BFD_RELOC_16C_REG14 ENUMX BFD_RELOC_16C_REG14_C ENUMX BFD_RELOC_16C_REG16 ENUMX BFD_RELOC_16C_REG16_C ENUMX BFD_RELOC_16C_REG20 ENUMX BFD_RELOC_16C_REG20_C ENUMX BFD_RELOC_16C_ABS20 ENUMX BFD_RELOC_16C_ABS20_C ENUMX BFD_RELOC_16C_ABS24 ENUMX BFD_RELOC_16C_ABS24_C ENUMX BFD_RELOC_16C_IMM04 ENUMX BFD_RELOC_16C_IMM04_C ENUMX BFD_RELOC_16C_IMM16 ENUMX BFD_RELOC_16C_IMM16_C ENUMX BFD_RELOC_16C_IMM20 ENUMX BFD_RELOC_16C_IMM20_C ENUMX BFD_RELOC_16C_IMM24 ENUMX BFD_RELOC_16C_IMM24_C ENUMX BFD_RELOC_16C_IMM32 ENUMX BFD_RELOC_16C_IMM32_C ENUMDOC NS CR16C Relocations. ENUM BFD_RELOC_CR16_NUM8 ENUMX BFD_RELOC_CR16_NUM16 ENUMX BFD_RELOC_CR16_NUM32 ENUMX BFD_RELOC_CR16_NUM32a ENUMX BFD_RELOC_CR16_REGREL0 ENUMX BFD_RELOC_CR16_REGREL4 ENUMX BFD_RELOC_CR16_REGREL4a ENUMX BFD_RELOC_CR16_REGREL14 ENUMX BFD_RELOC_CR16_REGREL14a ENUMX BFD_RELOC_CR16_REGREL16 ENUMX BFD_RELOC_CR16_REGREL20 ENUMX BFD_RELOC_CR16_REGREL20a ENUMX BFD_RELOC_CR16_ABS20 ENUMX BFD_RELOC_CR16_ABS24 ENUMX BFD_RELOC_CR16_IMM4 ENUMX BFD_RELOC_CR16_IMM8 ENUMX BFD_RELOC_CR16_IMM16 ENUMX BFD_RELOC_CR16_IMM20 ENUMX BFD_RELOC_CR16_IMM24 ENUMX BFD_RELOC_CR16_IMM32 ENUMX BFD_RELOC_CR16_IMM32a ENUMX BFD_RELOC_CR16_DISP4 ENUMX BFD_RELOC_CR16_DISP8 ENUMX BFD_RELOC_CR16_DISP16 ENUMX BFD_RELOC_CR16_DISP20 ENUMX BFD_RELOC_CR16_DISP24 ENUMX BFD_RELOC_CR16_DISP24a ENUMDOC NS CR16 Relocations. ENUM BFD_RELOC_CRX_REL4 ENUMX BFD_RELOC_CRX_REL8 ENUMX BFD_RELOC_CRX_REL8_CMP ENUMX BFD_RELOC_CRX_REL16 ENUMX BFD_RELOC_CRX_REL24 ENUMX BFD_RELOC_CRX_REL32 ENUMX BFD_RELOC_CRX_REGREL12 ENUMX BFD_RELOC_CRX_REGREL22 ENUMX BFD_RELOC_CRX_REGREL28 ENUMX BFD_RELOC_CRX_REGREL32 ENUMX BFD_RELOC_CRX_ABS16 ENUMX BFD_RELOC_CRX_ABS32 ENUMX BFD_RELOC_CRX_NUM8 ENUMX BFD_RELOC_CRX_NUM16 ENUMX BFD_RELOC_CRX_NUM32 ENUMX BFD_RELOC_CRX_IMM16 ENUMX BFD_RELOC_CRX_IMM32 ENUMX BFD_RELOC_CRX_SWITCH8 ENUMX BFD_RELOC_CRX_SWITCH16 ENUMX BFD_RELOC_CRX_SWITCH32 ENUMDOC NS CRX Relocations. ENUM BFD_RELOC_CRIS_BDISP8 ENUMX BFD_RELOC_CRIS_UNSIGNED_5 ENUMX BFD_RELOC_CRIS_SIGNED_6 ENUMX BFD_RELOC_CRIS_UNSIGNED_6 ENUMX BFD_RELOC_CRIS_SIGNED_8 ENUMX BFD_RELOC_CRIS_UNSIGNED_8 ENUMX BFD_RELOC_CRIS_SIGNED_16 ENUMX BFD_RELOC_CRIS_UNSIGNED_16 ENUMX BFD_RELOC_CRIS_LAPCQ_OFFSET ENUMX BFD_RELOC_CRIS_UNSIGNED_4 ENUMDOC These relocs are only used within the CRIS assembler. They are not (at present) written to any object files. ENUM BFD_RELOC_CRIS_COPY ENUMX BFD_RELOC_CRIS_GLOB_DAT ENUMX BFD_RELOC_CRIS_JUMP_SLOT ENUMX BFD_RELOC_CRIS_RELATIVE ENUMDOC Relocs used in ELF shared libraries for CRIS. ENUM BFD_RELOC_CRIS_32_GOT ENUMDOC 32-bit offset to symbol-entry within GOT. ENUM BFD_RELOC_CRIS_16_GOT ENUMDOC 16-bit offset to symbol-entry within GOT. ENUM BFD_RELOC_CRIS_32_GOTPLT ENUMDOC 32-bit offset to symbol-entry within GOT, with PLT handling. ENUM BFD_RELOC_CRIS_16_GOTPLT ENUMDOC 16-bit offset to symbol-entry within GOT, with PLT handling. ENUM BFD_RELOC_CRIS_32_GOTREL ENUMDOC 32-bit offset to symbol, relative to GOT. ENUM BFD_RELOC_CRIS_32_PLT_GOTREL ENUMDOC 32-bit offset to symbol with PLT entry, relative to GOT. ENUM BFD_RELOC_CRIS_32_PLT_PCREL ENUMDOC 32-bit offset to symbol with PLT entry, relative to this relocation. ENUM BFD_RELOC_860_COPY ENUMX BFD_RELOC_860_GLOB_DAT ENUMX BFD_RELOC_860_JUMP_SLOT ENUMX BFD_RELOC_860_RELATIVE ENUMX BFD_RELOC_860_PC26 ENUMX BFD_RELOC_860_PLT26 ENUMX BFD_RELOC_860_PC16 ENUMX BFD_RELOC_860_LOW0 ENUMX BFD_RELOC_860_SPLIT0 ENUMX BFD_RELOC_860_LOW1 ENUMX BFD_RELOC_860_SPLIT1 ENUMX BFD_RELOC_860_LOW2 ENUMX BFD_RELOC_860_SPLIT2 ENUMX BFD_RELOC_860_LOW3 ENUMX BFD_RELOC_860_LOGOT0 ENUMX BFD_RELOC_860_SPGOT0 ENUMX BFD_RELOC_860_LOGOT1 ENUMX BFD_RELOC_860_SPGOT1 ENUMX BFD_RELOC_860_LOGOTOFF0 ENUMX BFD_RELOC_860_SPGOTOFF0 ENUMX BFD_RELOC_860_LOGOTOFF1 ENUMX BFD_RELOC_860_SPGOTOFF1 ENUMX BFD_RELOC_860_LOGOTOFF2 ENUMX BFD_RELOC_860_LOGOTOFF3 ENUMX BFD_RELOC_860_LOPC ENUMX BFD_RELOC_860_HIGHADJ ENUMX BFD_RELOC_860_HAGOT ENUMX BFD_RELOC_860_HAGOTOFF ENUMX BFD_RELOC_860_HAPC ENUMX BFD_RELOC_860_HIGH ENUMX BFD_RELOC_860_HIGOT ENUMX BFD_RELOC_860_HIGOTOFF ENUMDOC Intel i860 Relocations. ENUM BFD_RELOC_OPENRISC_ABS_26 ENUMX BFD_RELOC_OPENRISC_REL_26 ENUMDOC OpenRISC Relocations. ENUM BFD_RELOC_H8_DIR16A8 ENUMX BFD_RELOC_H8_DIR16R8 ENUMX BFD_RELOC_H8_DIR24A8 ENUMX BFD_RELOC_H8_DIR24R8 ENUMX BFD_RELOC_H8_DIR32A16 ENUMDOC H8 elf Relocations. ENUM BFD_RELOC_XSTORMY16_REL_12 ENUMX BFD_RELOC_XSTORMY16_12 ENUMX BFD_RELOC_XSTORMY16_24 ENUMX BFD_RELOC_XSTORMY16_FPTR16 ENUMDOC Sony Xstormy16 Relocations. ENUM BFD_RELOC_RELC ENUMDOC Self-describing complex relocations. COMMENT ENUM BFD_RELOC_XC16X_PAG ENUMX BFD_RELOC_XC16X_POF ENUMX BFD_RELOC_XC16X_SEG ENUMX BFD_RELOC_XC16X_SOF ENUMDOC Infineon Relocations. ENUM BFD_RELOC_VAX_GLOB_DAT ENUMX BFD_RELOC_VAX_JMP_SLOT ENUMX BFD_RELOC_VAX_RELATIVE ENUMDOC Relocations used by VAX ELF. ENUM BFD_RELOC_MT_PC16 ENUMDOC Morpho MT - 16 bit immediate relocation. ENUM BFD_RELOC_MT_HI16 ENUMDOC Morpho MT - Hi 16 bits of an address. ENUM BFD_RELOC_MT_LO16 ENUMDOC Morpho MT - Low 16 bits of an address. ENUM BFD_RELOC_MT_GNU_VTINHERIT ENUMDOC Morpho MT - Used to tell the linker which vtable entries are used. ENUM BFD_RELOC_MT_GNU_VTENTRY ENUMDOC Morpho MT - Used to tell the linker which vtable entries are used. ENUM BFD_RELOC_MT_PCINSN8 ENUMDOC Morpho MT - 8 bit immediate relocation. ENUM BFD_RELOC_MSP430_10_PCREL ENUMX BFD_RELOC_MSP430_16_PCREL ENUMX BFD_RELOC_MSP430_16 ENUMX BFD_RELOC_MSP430_16_PCREL_BYTE ENUMX BFD_RELOC_MSP430_16_BYTE ENUMX BFD_RELOC_MSP430_2X_PCREL ENUMX BFD_RELOC_MSP430_RL_PCREL ENUMDOC msp430 specific relocation codes ENUM BFD_RELOC_IQ2000_OFFSET_16 ENUMX BFD_RELOC_IQ2000_OFFSET_21 ENUMX BFD_RELOC_IQ2000_UHI16 ENUMDOC IQ2000 Relocations. ENUM BFD_RELOC_XTENSA_RTLD ENUMDOC Special Xtensa relocation used only by PLT entries in ELF shared objects to indicate that the runtime linker should set the value to one of its own internal functions or data structures. ENUM BFD_RELOC_XTENSA_GLOB_DAT ENUMX BFD_RELOC_XTENSA_JMP_SLOT ENUMX BFD_RELOC_XTENSA_RELATIVE ENUMDOC Xtensa relocations for ELF shared objects. ENUM BFD_RELOC_XTENSA_PLT ENUMDOC Xtensa relocation used in ELF object files for symbols that may require PLT entries. Otherwise, this is just a generic 32-bit relocation. ENUM BFD_RELOC_XTENSA_DIFF8 ENUMX BFD_RELOC_XTENSA_DIFF16 ENUMX BFD_RELOC_XTENSA_DIFF32 ENUMDOC Xtensa relocations to mark the difference of two local symbols. These are only needed to support linker relaxation and can be ignored when not relaxing. The field is set to the value of the difference assuming no relaxation. The relocation encodes the position of the first symbol so the linker can determine whether to adjust the field value. ENUM BFD_RELOC_XTENSA_SLOT0_OP ENUMX BFD_RELOC_XTENSA_SLOT1_OP ENUMX BFD_RELOC_XTENSA_SLOT2_OP ENUMX BFD_RELOC_XTENSA_SLOT3_OP ENUMX BFD_RELOC_XTENSA_SLOT4_OP ENUMX BFD_RELOC_XTENSA_SLOT5_OP ENUMX BFD_RELOC_XTENSA_SLOT6_OP ENUMX BFD_RELOC_XTENSA_SLOT7_OP ENUMX BFD_RELOC_XTENSA_SLOT8_OP ENUMX BFD_RELOC_XTENSA_SLOT9_OP ENUMX BFD_RELOC_XTENSA_SLOT10_OP ENUMX BFD_RELOC_XTENSA_SLOT11_OP ENUMX BFD_RELOC_XTENSA_SLOT12_OP ENUMX BFD_RELOC_XTENSA_SLOT13_OP ENUMX BFD_RELOC_XTENSA_SLOT14_OP ENUMDOC Generic Xtensa relocations for instruction operands. Only the slot number is encoded in the relocation. The relocation applies to the last PC-relative immediate operand, or if there are no PC-relative immediates, to the last immediate operand. ENUM BFD_RELOC_XTENSA_SLOT0_ALT ENUMX BFD_RELOC_XTENSA_SLOT1_ALT ENUMX BFD_RELOC_XTENSA_SLOT2_ALT ENUMX BFD_RELOC_XTENSA_SLOT3_ALT ENUMX BFD_RELOC_XTENSA_SLOT4_ALT ENUMX BFD_RELOC_XTENSA_SLOT5_ALT ENUMX BFD_RELOC_XTENSA_SLOT6_ALT ENUMX BFD_RELOC_XTENSA_SLOT7_ALT ENUMX BFD_RELOC_XTENSA_SLOT8_ALT ENUMX BFD_RELOC_XTENSA_SLOT9_ALT ENUMX BFD_RELOC_XTENSA_SLOT10_ALT ENUMX BFD_RELOC_XTENSA_SLOT11_ALT ENUMX BFD_RELOC_XTENSA_SLOT12_ALT ENUMX BFD_RELOC_XTENSA_SLOT13_ALT ENUMX BFD_RELOC_XTENSA_SLOT14_ALT ENUMDOC Alternate Xtensa relocations. Only the slot is encoded in the relocation. The meaning of these relocations is opcode-specific. ENUM BFD_RELOC_XTENSA_OP0 ENUMX BFD_RELOC_XTENSA_OP1 ENUMX BFD_RELOC_XTENSA_OP2 ENUMDOC Xtensa relocations for backward compatibility. These have all been replaced by BFD_RELOC_XTENSA_SLOT0_OP. ENUM BFD_RELOC_XTENSA_ASM_EXPAND ENUMDOC Xtensa relocation to mark that the assembler expanded the instructions from an original target. The expansion size is encoded in the reloc size. ENUM BFD_RELOC_XTENSA_ASM_SIMPLIFY ENUMDOC Xtensa relocation to mark that the linker should simplify assembler-expanded instructions. This is commonly used internally by the linker after analysis of a BFD_RELOC_XTENSA_ASM_EXPAND. ENUM BFD_RELOC_Z80_DISP8 ENUMDOC 8 bit signed offset in (ix+d) or (iy+d). ENUM BFD_RELOC_Z8K_DISP7 ENUMDOC DJNZ offset. ENUM BFD_RELOC_Z8K_CALLR ENUMDOC CALR offset. ENUM BFD_RELOC_Z8K_IMM4L ENUMDOC 4 bit value. ENDSENUM BFD_RELOC_UNUSED CODE_FRAGMENT . .typedef enum bfd_reloc_code_real bfd_reloc_code_real_type; */ /* FUNCTION bfd_reloc_type_lookup bfd_reloc_name_lookup SYNOPSIS reloc_howto_type *bfd_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code); reloc_howto_type *bfd_reloc_name_lookup (bfd *abfd, const char *reloc_name); DESCRIPTION Return a pointer to a howto structure which, when invoked, will perform the relocation @var{code} on data from the architecture noted. */ reloc_howto_type * bfd_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code) { return BFD_SEND (abfd, reloc_type_lookup, (abfd, code)); } reloc_howto_type * bfd_reloc_name_lookup (bfd *abfd, const char *reloc_name) { return BFD_SEND (abfd, reloc_name_lookup, (abfd, reloc_name)); } static reloc_howto_type bfd_howto_32 = HOWTO (0, 00, 2, 32, FALSE, 0, complain_overflow_dont, 0, "VRT32", FALSE, 0xffffffff, 0xffffffff, TRUE); /* INTERNAL_FUNCTION bfd_default_reloc_type_lookup SYNOPSIS reloc_howto_type *bfd_default_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code); DESCRIPTION Provides a default relocation lookup routine for any architecture. */ reloc_howto_type * bfd_default_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code) { switch (code) { case BFD_RELOC_CTOR: /* The type of reloc used in a ctor, which will be as wide as the address - so either a 64, 32, or 16 bitter. */ switch (bfd_get_arch_info (abfd)->bits_per_address) { case 64: BFD_FAIL (); case 32: return &bfd_howto_32; case 16: BFD_FAIL (); default: BFD_FAIL (); } default: BFD_FAIL (); } return NULL; } /* FUNCTION bfd_get_reloc_code_name SYNOPSIS const char *bfd_get_reloc_code_name (bfd_reloc_code_real_type code); DESCRIPTION Provides a printable name for the supplied relocation code. Useful mainly for printing error messages. */ const char * bfd_get_reloc_code_name (bfd_reloc_code_real_type code) { if (code > BFD_RELOC_UNUSED) return 0; return bfd_reloc_code_real_names[code]; } /* INTERNAL_FUNCTION bfd_generic_relax_section SYNOPSIS bfd_boolean bfd_generic_relax_section (bfd *abfd, asection *section, struct bfd_link_info *, bfd_boolean *); DESCRIPTION Provides default handling for relaxing for back ends which don't do relaxing. */ bfd_boolean bfd_generic_relax_section (bfd *abfd ATTRIBUTE_UNUSED, asection *section ATTRIBUTE_UNUSED, struct bfd_link_info *link_info ATTRIBUTE_UNUSED, bfd_boolean *again) { *again = FALSE; return TRUE; } /* INTERNAL_FUNCTION bfd_generic_gc_sections SYNOPSIS bfd_boolean bfd_generic_gc_sections (bfd *, struct bfd_link_info *); DESCRIPTION Provides default handling for relaxing for back ends which don't do section gc -- i.e., does nothing. */ bfd_boolean bfd_generic_gc_sections (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info ATTRIBUTE_UNUSED) { return TRUE; } /* INTERNAL_FUNCTION bfd_generic_merge_sections SYNOPSIS bfd_boolean bfd_generic_merge_sections (bfd *, struct bfd_link_info *); DESCRIPTION Provides default handling for SEC_MERGE section merging for back ends which don't have SEC_MERGE support -- i.e., does nothing. */ bfd_boolean bfd_generic_merge_sections (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *link_info ATTRIBUTE_UNUSED) { return TRUE; } /* INTERNAL_FUNCTION bfd_generic_get_relocated_section_contents SYNOPSIS bfd_byte *bfd_generic_get_relocated_section_contents (bfd *abfd, struct bfd_link_info *link_info, struct bfd_link_order *link_order, bfd_byte *data, bfd_boolean relocatable, asymbol **symbols); DESCRIPTION Provides default handling of relocation effort for back ends which can't be bothered to do it efficiently. */ bfd_byte * bfd_generic_get_relocated_section_contents (bfd *abfd, struct bfd_link_info *link_info, struct bfd_link_order *link_order, bfd_byte *data, bfd_boolean relocatable, asymbol **symbols) { /* Get enough memory to hold the stuff. */ bfd *input_bfd = link_order->u.indirect.section->owner; asection *input_section = link_order->u.indirect.section; long reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section); arelent **reloc_vector = NULL; long reloc_count; bfd_size_type sz; if (reloc_size < 0) goto error_return; reloc_vector = bfd_malloc (reloc_size); if (reloc_vector == NULL && reloc_size != 0) goto error_return; /* Read in the section. */ sz = input_section->rawsize ? input_section->rawsize : input_section->size; if (!bfd_get_section_contents (input_bfd, input_section, data, 0, sz)) goto error_return; reloc_count = bfd_canonicalize_reloc (input_bfd, input_section, reloc_vector, symbols); if (reloc_count < 0) goto error_return; if (reloc_count > 0) { arelent **parent; for (parent = reloc_vector; *parent != NULL; parent++) { char *error_message = NULL; asymbol *symbol; bfd_reloc_status_type r; symbol = *(*parent)->sym_ptr_ptr; if (symbol->section && elf_discarded_section (symbol->section)) { bfd_byte *p; static reloc_howto_type none_howto = HOWTO (0, 0, 0, 0, FALSE, 0, complain_overflow_dont, NULL, "unused", FALSE, 0, 0, FALSE); p = data + (*parent)->address * bfd_octets_per_byte (input_bfd); _bfd_clear_contents ((*parent)->howto, input_bfd, p); (*parent)->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr; (*parent)->addend = 0; (*parent)->howto = &none_howto; r = bfd_reloc_ok; } else r = bfd_perform_relocation (input_bfd, *parent, data, input_section, relocatable ? abfd : NULL, &error_message); if (relocatable) { asection *os = input_section->output_section; /* A partial link, so keep the relocs. */ os->orelocation[os->reloc_count] = *parent; os->reloc_count++; } if (r != bfd_reloc_ok) { switch (r) { case bfd_reloc_undefined: if (!((*link_info->callbacks->undefined_symbol) (link_info, bfd_asymbol_name (*(*parent)->sym_ptr_ptr), input_bfd, input_section, (*parent)->address, TRUE))) goto error_return; break; case bfd_reloc_dangerous: BFD_ASSERT (error_message != NULL); if (!((*link_info->callbacks->reloc_dangerous) (link_info, error_message, input_bfd, input_section, (*parent)->address))) goto error_return; break; case bfd_reloc_overflow: if (!((*link_info->callbacks->reloc_overflow) (link_info, NULL, bfd_asymbol_name (*(*parent)->sym_ptr_ptr), (*parent)->howto->name, (*parent)->addend, input_bfd, input_section, (*parent)->address))) goto error_return; break; case bfd_reloc_outofrange: default: abort (); break; } } } } if (reloc_vector != NULL) free (reloc_vector); return data; error_return: if (reloc_vector != NULL) free (reloc_vector); return NULL; } Index: head/contrib/binutils/bfd/section.c =================================================================== --- head/contrib/binutils/bfd/section.c (revision 275717) +++ head/contrib/binutils/bfd/section.c (revision 275718) @@ -1,1526 +1,1529 @@ /* 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, 2006, 2007 + 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ /* SECTION Sections The raw data contained within a BFD is maintained through the section abstraction. A single BFD may have any number of sections. It keeps hold of them by pointing to the first; each one points to the next in the list. Sections are supported in BFD in <>. @menu @* Section Input:: @* Section Output:: @* typedef asection:: @* section prototypes:: @end menu INODE Section Input, Section Output, Sections, Sections SUBSECTION Section input When a BFD is opened for reading, the section structures are created and attached to the BFD. Each section has a name which describes the section in the outside world---for example, <> would contain at least three sections, called <<.text>>, <<.data>> and <<.bss>>. Names need not be unique; for example a COFF file may have several sections named <<.data>>. Sometimes a BFD will contain more than the ``natural'' number of sections. A back end may attach other sections containing constructor data, or an application may add a section (using <>) to the sections attached to an already open BFD. For example, the linker creates an extra section <> for each input file's BFD to hold information about common storage. The raw data is not necessarily read in when the section descriptor is created. Some targets may leave the data in place until a <> call is made. Other back ends may read in all the data at once. For example, an S-record file has to be read once to determine the size of the data. An IEEE-695 file doesn't contain raw data in sections, but data and relocation expressions intermixed, so the data area has to be parsed to get out the data and relocations. INODE Section Output, typedef asection, Section Input, Sections SUBSECTION Section output To write a new object style BFD, the various sections to be written have to be created. They are attached to the BFD in the same way as input sections; data is written to the sections using <>. Any program that creates or combines sections (e.g., the assembler and linker) must use the <> fields <> and <> to indicate the file sections to which each section must be written. (If the section is being created from scratch, <> should probably point to the section itself and <> should probably be zero.) The data to be written comes from input sections attached (via <> pointers) to the output sections. The output section structure can be considered a filter for the input section: the output section determines the vma of the output data and the name, but the input section determines the offset into the output section of the data to be written. E.g., to create a section "O", starting at 0x100, 0x123 long, containing two subsections, "A" at offset 0x0 (i.e., at vma 0x100) and "B" at offset 0x20 (i.e., at vma 0x120) the <> structures would look like: | section name "A" | output_offset 0x00 | size 0x20 | output_section -----------> section name "O" | | vma 0x100 | section name "B" | size 0x123 | output_offset 0x20 | | size 0x103 | | output_section --------| SUBSECTION Link orders The data within a section is stored in a @dfn{link_order}. These are much like the fixups in <>. The link_order abstraction allows a section to grow and shrink within itself. A link_order knows how big it is, and which is the next link_order and where the raw data for it is; it also points to a list of relocations which apply to it. The link_order is used by the linker to perform relaxing on final code. The compiler creates code which is as big as necessary to make it work without relaxing, and the user can select whether to relax. Sometimes relaxing takes a lot of time. The linker runs around the relocations to see if any are attached to data which can be shrunk, if so it does it on a link_order by link_order basis. */ #include "sysdep.h" #include "bfd.h" #include "libbfd.h" #include "bfdlink.h" /* DOCDD INODE typedef asection, section prototypes, Section Output, Sections SUBSECTION typedef asection Here is the section structure: CODE_FRAGMENT . .typedef struct bfd_section .{ . {* The name of the section; the name isn't a copy, the pointer is . the same as that passed to bfd_make_section. *} . const char *name; . . {* A unique sequence number. *} . int id; . . {* Which section in the bfd; 0..n-1 as sections are created in a bfd. *} . int index; . . {* The next section in the list belonging to the BFD, or NULL. *} . struct bfd_section *next; . . {* The previous section in the list belonging to the BFD, or NULL. *} . struct bfd_section *prev; . . {* The field flags contains attributes of the section. Some . flags are read in from the object file, and some are . synthesized from other information. *} . flagword flags; . .#define SEC_NO_FLAGS 0x000 . . {* Tells the OS to allocate space for this section when loading. . This is clear for a section containing debug information only. *} .#define SEC_ALLOC 0x001 . . {* Tells the OS to load the section from the file when loading. . This is clear for a .bss section. *} .#define SEC_LOAD 0x002 . . {* The section contains data still to be relocated, so there is . some relocation information too. *} .#define SEC_RELOC 0x004 . . {* A signal to the OS that the section contains read only data. *} .#define SEC_READONLY 0x008 . . {* The section contains code only. *} .#define SEC_CODE 0x010 . . {* The section contains data only. *} .#define SEC_DATA 0x020 . . {* The section will reside in ROM. *} .#define SEC_ROM 0x040 . . {* The section contains constructor information. This section . type is used by the linker to create lists of constructors and . destructors used by <>. When a back end sees a symbol . which should be used in a constructor list, it creates a new . section for the type of name (e.g., <<__CTOR_LIST__>>), attaches . the symbol to it, and builds a relocation. To build the lists . of constructors, all the linker has to do is catenate all the . sections called <<__CTOR_LIST__>> and relocate the data . contained within - exactly the operations it would peform on . standard data. *} .#define SEC_CONSTRUCTOR 0x080 . . {* The section has contents - a data section could be . <> | <>; a debug section could be . <> *} .#define SEC_HAS_CONTENTS 0x100 . . {* An instruction to the linker to not output the section . even if it has information which would normally be written. *} .#define SEC_NEVER_LOAD 0x200 . . {* The section contains thread local data. *} .#define SEC_THREAD_LOCAL 0x400 . . {* The section has GOT references. This flag is only for the . linker, and is currently only used by the elf32-hppa back end. . It will be set if global offset table references were detected . in this section, which indicate to the linker that the section . contains PIC code, and must be handled specially when doing a . static link. *} .#define SEC_HAS_GOT_REF 0x800 . . {* The section contains common symbols (symbols may be defined . multiple times, the value of a symbol is the amount of . space it requires, and the largest symbol value is the one . used). Most targets have exactly one of these (which we . translate to bfd_com_section_ptr), but ECOFF has two. *} .#define SEC_IS_COMMON 0x1000 . . {* The section contains only debugging information. For . example, this is set for ELF .debug and .stab sections. . strip tests this flag to see if a section can be . discarded. *} .#define SEC_DEBUGGING 0x2000 . . {* The contents of this section are held in memory pointed to . by the contents field. This is checked by bfd_get_section_contents, . and the data is retrieved from memory if appropriate. *} .#define SEC_IN_MEMORY 0x4000 . . {* The contents of this section are to be excluded by the . linker for executable and shared objects unless those . objects are to be further relocated. *} .#define SEC_EXCLUDE 0x8000 . . {* The contents of this section are to be sorted based on the sum of . the symbol and addend values specified by the associated relocation . entries. Entries without associated relocation entries will be . appended to the end of the section in an unspecified order. *} .#define SEC_SORT_ENTRIES 0x10000 . . {* When linking, duplicate sections of the same name should be . discarded, rather than being combined into a single section as . is usually done. This is similar to how common symbols are . handled. See SEC_LINK_DUPLICATES below. *} .#define SEC_LINK_ONCE 0x20000 . . {* If SEC_LINK_ONCE is set, this bitfield describes how the linker . should handle duplicate sections. *} .#define SEC_LINK_DUPLICATES 0x40000 . . {* This value for SEC_LINK_DUPLICATES means that duplicate . sections with the same name should simply be discarded. *} .#define SEC_LINK_DUPLICATES_DISCARD 0x0 . . {* This value for SEC_LINK_DUPLICATES means that the linker . should warn if there are any duplicate sections, although . it should still only link one copy. *} .#define SEC_LINK_DUPLICATES_ONE_ONLY 0x80000 . . {* This value for SEC_LINK_DUPLICATES means that the linker . should warn if any duplicate sections are a different size. *} .#define SEC_LINK_DUPLICATES_SAME_SIZE 0x100000 . . {* This value for SEC_LINK_DUPLICATES means that the linker . should warn if any duplicate sections contain different . contents. *} .#define SEC_LINK_DUPLICATES_SAME_CONTENTS \ . (SEC_LINK_DUPLICATES_ONE_ONLY | SEC_LINK_DUPLICATES_SAME_SIZE) . . {* This section was created by the linker as part of dynamic . relocation or other arcane processing. It is skipped when . going through the first-pass output, trusting that someone . else up the line will take care of it later. *} .#define SEC_LINKER_CREATED 0x200000 . . {* This section should not be subject to garbage collection. . Also set to inform the linker that this section should not be . listed in the link map as discarded. *} .#define SEC_KEEP 0x400000 . . {* This section contains "short" data, and should be placed . "near" the GP. *} .#define SEC_SMALL_DATA 0x800000 . . {* Attempt to merge identical entities in the section. . Entity size is given in the entsize field. *} .#define SEC_MERGE 0x1000000 . . {* If given with SEC_MERGE, entities to merge are zero terminated . strings where entsize specifies character size instead of fixed . size entries. *} .#define SEC_STRINGS 0x2000000 . . {* This section contains data about section groups. *} .#define SEC_GROUP 0x4000000 . . {* The section is a COFF shared library section. This flag is . only for the linker. If this type of section appears in . the input file, the linker must copy it to the output file . without changing the vma or size. FIXME: Although this . was originally intended to be general, it really is COFF . specific (and the flag was renamed to indicate this). It . might be cleaner to have some more general mechanism to . allow the back end to control what the linker does with . sections. *} .#define SEC_COFF_SHARED_LIBRARY 0x10000000 . . {* This section contains data which may be shared with other . executables or shared objects. This is for COFF only. *} .#define SEC_COFF_SHARED 0x20000000 . . {* When a section with this flag is being linked, then if the size of . the input section is less than a page, it should not cross a page . boundary. If the size of the input section is one page or more, . it should be aligned on a page boundary. This is for TI . TMS320C54X only. *} .#define SEC_TIC54X_BLOCK 0x40000000 . . {* Conditionally link this section; do not link if there are no . references found to any symbol in the section. This is for TI . TMS320C54X only. *} .#define SEC_TIC54X_CLINK 0x80000000 . . {* End of section flags. *} . . {* Some internal packed boolean fields. *} . . {* See the vma field. *} . unsigned int user_set_vma : 1; . . {* A mark flag used by some of the linker backends. *} . unsigned int linker_mark : 1; . . {* Another mark flag used by some of the linker backends. Set for . output sections that have an input section. *} . unsigned int linker_has_input : 1; . . {* Mark flags used by some linker backends for garbage collection. *} . unsigned int gc_mark : 1; . unsigned int gc_mark_from_eh : 1; . . {* The following flags are used by the ELF linker. *} . . {* Mark sections which have been allocated to segments. *} . unsigned int segment_mark : 1; . . {* Type of sec_info information. *} . unsigned int sec_info_type:3; .#define ELF_INFO_TYPE_NONE 0 .#define ELF_INFO_TYPE_STABS 1 .#define ELF_INFO_TYPE_MERGE 2 .#define ELF_INFO_TYPE_EH_FRAME 3 .#define ELF_INFO_TYPE_JUST_SYMS 4 . . {* Nonzero if this section uses RELA relocations, rather than REL. *} . unsigned int use_rela_p:1; . . {* Bits used by various backends. The generic code doesn't touch . these fields. *} . . {* Nonzero if this section has TLS related relocations. *} . unsigned int has_tls_reloc:1; . +. {* Nonzero if this section has a call to __tls_get_addr. *} +. unsigned int has_tls_get_addr_call:1; +. . {* Nonzero if this section has a gp reloc. *} . unsigned int has_gp_reloc:1; . . {* Nonzero if this section needs the relax finalize pass. *} . unsigned int need_finalize_relax:1; . . {* Whether relocations have been processed. *} . unsigned int reloc_done : 1; . . {* End of internal packed boolean fields. *} . . {* The virtual memory address of the section - where it will be . at run time. The symbols are relocated against this. The . user_set_vma flag is maintained by bfd; if it's not set, the . backend can assign addresses (for example, in <>, where . the default address for <<.data>> is dependent on the specific . target and various flags). *} . bfd_vma vma; . . {* The load address of the section - where it would be in a . rom image; really only used for writing section header . information. *} . bfd_vma lma; . . {* The size of the section in octets, as it will be output. . Contains a value even if the section has no contents (e.g., the . size of <<.bss>>). *} . bfd_size_type size; . . {* For input sections, the original size on disk of the section, in . octets. This field is used by the linker relaxation code. It is . currently only set for sections where the linker relaxation scheme . doesn't cache altered section and reloc contents (stabs, eh_frame, . SEC_MERGE, some coff relaxing targets), and thus the original size . needs to be kept to read the section multiple times. . For output sections, rawsize holds the section size calculated on . a previous linker relaxation pass. *} . bfd_size_type rawsize; . . {* If this section is going to be output, then this value is the . offset in *bytes* into the output section of the first byte in the . input section (byte ==> smallest addressable unit on the . target). In most cases, if this was going to start at the . 100th octet (8-bit quantity) in the output section, this value . would be 100. However, if the target byte size is 16 bits . (bfd_octets_per_byte is "2"), this value would be 50. *} . bfd_vma output_offset; . . {* The output section through which to map on output. *} . struct bfd_section *output_section; . . {* The alignment requirement of the section, as an exponent of 2 - . e.g., 3 aligns to 2^3 (or 8). *} . unsigned int alignment_power; . . {* If an input section, a pointer to a vector of relocation . records for the data in this section. *} . struct reloc_cache_entry *relocation; . . {* If an output section, a pointer to a vector of pointers to . relocation records for the data in this section. *} . struct reloc_cache_entry **orelocation; . . {* The number of relocation records in one of the above. *} . unsigned reloc_count; . . {* Information below is back end specific - and not always used . or updated. *} . . {* File position of section data. *} . file_ptr filepos; . . {* File position of relocation info. *} . file_ptr rel_filepos; . . {* File position of line data. *} . file_ptr line_filepos; . . {* Pointer to data for applications. *} . void *userdata; . . {* If the SEC_IN_MEMORY flag is set, this points to the actual . contents. *} . unsigned char *contents; . . {* Attached line number information. *} . alent *lineno; . . {* Number of line number records. *} . unsigned int lineno_count; . . {* Entity size for merging purposes. *} . unsigned int entsize; . . {* Points to the kept section if this section is a link-once section, . and is discarded. *} . struct bfd_section *kept_section; . . {* When a section is being output, this value changes as more . linenumbers are written out. *} . file_ptr moving_line_filepos; . . {* What the section number is in the target world. *} . int target_index; . . void *used_by_bfd; . . {* If this is a constructor section then here is a list of the . relocations created to relocate items within it. *} . struct relent_chain *constructor_chain; . . {* The BFD which owns the section. *} . bfd *owner; . . {* A symbol which points at this section only. *} . struct bfd_symbol *symbol; . struct bfd_symbol **symbol_ptr_ptr; . . {* Early in the link process, map_head and map_tail are used to build . a list of input sections attached to an output section. Later, . output sections use these fields for a list of bfd_link_order . structs. *} . union { . struct bfd_link_order *link_order; . struct bfd_section *s; . } map_head, map_tail; .} asection; . .{* These sections are global, and are managed by BFD. The application . and target back end are not permitted to change the values in . these sections. New code should use the section_ptr macros rather . than referring directly to the const sections. The const sections . may eventually vanish. *} .#define BFD_ABS_SECTION_NAME "*ABS*" .#define BFD_UND_SECTION_NAME "*UND*" .#define BFD_COM_SECTION_NAME "*COM*" .#define BFD_IND_SECTION_NAME "*IND*" . .{* The absolute section. *} .extern asection bfd_abs_section; .#define bfd_abs_section_ptr ((asection *) &bfd_abs_section) .#define bfd_is_abs_section(sec) ((sec) == bfd_abs_section_ptr) .{* Pointer to the undefined section. *} .extern asection bfd_und_section; .#define bfd_und_section_ptr ((asection *) &bfd_und_section) .#define bfd_is_und_section(sec) ((sec) == bfd_und_section_ptr) .{* Pointer to the common section. *} .extern asection bfd_com_section; .#define bfd_com_section_ptr ((asection *) &bfd_com_section) .{* Pointer to the indirect section. *} .extern asection bfd_ind_section; .#define bfd_ind_section_ptr ((asection *) &bfd_ind_section) .#define bfd_is_ind_section(sec) ((sec) == bfd_ind_section_ptr) . .#define bfd_is_const_section(SEC) \ . ( ((SEC) == bfd_abs_section_ptr) \ . || ((SEC) == bfd_und_section_ptr) \ . || ((SEC) == bfd_com_section_ptr) \ . || ((SEC) == bfd_ind_section_ptr)) . .{* Macros to handle insertion and deletion of a bfd's sections. These . only handle the list pointers, ie. do not adjust section_count, . target_index etc. *} .#define bfd_section_list_remove(ABFD, S) \ . do \ . { \ . asection *_s = S; \ . asection *_next = _s->next; \ . asection *_prev = _s->prev; \ . if (_prev) \ . _prev->next = _next; \ . else \ . (ABFD)->sections = _next; \ . if (_next) \ . _next->prev = _prev; \ . else \ . (ABFD)->section_last = _prev; \ . } \ . while (0) .#define bfd_section_list_append(ABFD, S) \ . do \ . { \ . asection *_s = S; \ . bfd *_abfd = ABFD; \ . _s->next = NULL; \ . if (_abfd->section_last) \ . { \ . _s->prev = _abfd->section_last; \ . _abfd->section_last->next = _s; \ . } \ . else \ . { \ . _s->prev = NULL; \ . _abfd->sections = _s; \ . } \ . _abfd->section_last = _s; \ . } \ . while (0) .#define bfd_section_list_prepend(ABFD, S) \ . do \ . { \ . asection *_s = S; \ . bfd *_abfd = ABFD; \ . _s->prev = NULL; \ . if (_abfd->sections) \ . { \ . _s->next = _abfd->sections; \ . _abfd->sections->prev = _s; \ . } \ . else \ . { \ . _s->next = NULL; \ . _abfd->section_last = _s; \ . } \ . _abfd->sections = _s; \ . } \ . while (0) .#define bfd_section_list_insert_after(ABFD, A, S) \ . do \ . { \ . asection *_a = A; \ . asection *_s = S; \ . asection *_next = _a->next; \ . _s->next = _next; \ . _s->prev = _a; \ . _a->next = _s; \ . if (_next) \ . _next->prev = _s; \ . else \ . (ABFD)->section_last = _s; \ . } \ . while (0) .#define bfd_section_list_insert_before(ABFD, B, S) \ . do \ . { \ . asection *_b = B; \ . asection *_s = S; \ . asection *_prev = _b->prev; \ . _s->prev = _prev; \ . _s->next = _b; \ . _b->prev = _s; \ . if (_prev) \ . _prev->next = _s; \ . else \ . (ABFD)->sections = _s; \ . } \ . while (0) .#define bfd_section_removed_from_list(ABFD, S) \ . ((S)->next == NULL ? (ABFD)->section_last != (S) : (S)->next->prev != (S)) . .#define BFD_FAKE_SECTION(SEC, FLAGS, SYM, NAME, IDX) \ . {* name, id, index, next, prev, flags, user_set_vma, *} \ . { NAME, IDX, 0, NULL, NULL, FLAGS, 0, \ . \ . {* linker_mark, linker_has_input, gc_mark, gc_mark_from_eh, *} \ . 0, 0, 1, 0, \ . \ . {* segment_mark, sec_info_type, use_rela_p, has_tls_reloc, *} \ . 0, 0, 0, 0, \ . \ -. {* has_gp_reloc, need_finalize_relax, reloc_done, *} \ -. 0, 0, 0, \ +. {* has_tls_get_addr_call, has_gp_reloc, need_finalize_relax, *} \ +. 0, 0, 0, \ . \ -. {* vma, lma, size, rawsize *} \ -. 0, 0, 0, 0, \ +. {* reloc_done, vma, lma, size, rawsize *} \ +. 0, 0, 0, 0, 0, \ . \ . {* output_offset, output_section, alignment_power, *} \ . 0, (struct bfd_section *) &SEC, 0, \ . \ . {* relocation, orelocation, reloc_count, filepos, rel_filepos, *} \ . NULL, NULL, 0, 0, 0, \ . \ . {* line_filepos, userdata, contents, lineno, lineno_count, *} \ . 0, NULL, NULL, NULL, 0, \ . \ . {* entsize, kept_section, moving_line_filepos, *} \ . 0, NULL, 0, \ . \ . {* target_index, used_by_bfd, constructor_chain, owner, *} \ . 0, NULL, NULL, NULL, \ . \ . {* symbol, symbol_ptr_ptr, *} \ . (struct bfd_symbol *) SYM, &SEC.symbol, \ . \ . {* map_head, map_tail *} \ . { NULL }, { NULL } \ . } . */ /* We use a macro to initialize the static asymbol structures because traditional C does not permit us to initialize a union member while gcc warns if we don't initialize it. */ /* the_bfd, name, value, attr, section [, udata] */ #ifdef __STDC__ #define GLOBAL_SYM_INIT(NAME, SECTION) \ { 0, NAME, 0, BSF_SECTION_SYM, (asection *) SECTION, { 0 }} #else #define GLOBAL_SYM_INIT(NAME, SECTION) \ { 0, NAME, 0, BSF_SECTION_SYM, (asection *) SECTION } #endif /* These symbols are global, not specific to any BFD. Therefore, anything that tries to change them is broken, and should be repaired. */ static const asymbol global_syms[] = { GLOBAL_SYM_INIT (BFD_COM_SECTION_NAME, &bfd_com_section), GLOBAL_SYM_INIT (BFD_UND_SECTION_NAME, &bfd_und_section), GLOBAL_SYM_INIT (BFD_ABS_SECTION_NAME, &bfd_abs_section), GLOBAL_SYM_INIT (BFD_IND_SECTION_NAME, &bfd_ind_section) }; #define STD_SECTION(SEC, FLAGS, NAME, IDX) \ asection SEC = BFD_FAKE_SECTION(SEC, FLAGS, &global_syms[IDX], \ NAME, IDX) STD_SECTION (bfd_com_section, SEC_IS_COMMON, BFD_COM_SECTION_NAME, 0); STD_SECTION (bfd_und_section, 0, BFD_UND_SECTION_NAME, 1); STD_SECTION (bfd_abs_section, 0, BFD_ABS_SECTION_NAME, 2); STD_SECTION (bfd_ind_section, 0, BFD_IND_SECTION_NAME, 3); #undef STD_SECTION /* Initialize an entry in the section hash table. */ struct bfd_hash_entry * bfd_section_hash_newfunc (struct bfd_hash_entry *entry, struct bfd_hash_table *table, const char *string) { /* Allocate the structure if it has not already been allocated by a subclass. */ if (entry == NULL) { entry = (struct bfd_hash_entry *) bfd_hash_allocate (table, sizeof (struct section_hash_entry)); if (entry == NULL) return entry; } /* Call the allocation method of the superclass. */ entry = bfd_hash_newfunc (entry, table, string); if (entry != NULL) memset (&((struct section_hash_entry *) entry)->section, 0, sizeof (asection)); return entry; } #define section_hash_lookup(table, string, create, copy) \ ((struct section_hash_entry *) \ bfd_hash_lookup ((table), (string), (create), (copy))) /* Create a symbol whose only job is to point to this section. This is useful for things like relocs which are relative to the base of a section. */ bfd_boolean _bfd_generic_new_section_hook (bfd *abfd, asection *newsect) { newsect->symbol = bfd_make_empty_symbol (abfd); if (newsect->symbol == NULL) return FALSE; newsect->symbol->name = newsect->name; newsect->symbol->value = 0; newsect->symbol->section = newsect; newsect->symbol->flags = BSF_SECTION_SYM; newsect->symbol_ptr_ptr = &newsect->symbol; return TRUE; } /* Initializes a new section. NEWSECT->NAME is already set. */ static asection * bfd_section_init (bfd *abfd, asection *newsect) { static int section_id = 0x10; /* id 0 to 3 used by STD_SECTION. */ newsect->id = section_id; newsect->index = abfd->section_count; newsect->owner = abfd; if (! BFD_SEND (abfd, _new_section_hook, (abfd, newsect))) return NULL; section_id++; abfd->section_count++; bfd_section_list_append (abfd, newsect); return newsect; } /* DOCDD INODE section prototypes, , typedef asection, Sections SUBSECTION Section prototypes These are the functions exported by the section handling part of BFD. */ /* FUNCTION bfd_section_list_clear SYNOPSIS void bfd_section_list_clear (bfd *); DESCRIPTION Clears the section list, and also resets the section count and hash table entries. */ void bfd_section_list_clear (bfd *abfd) { abfd->sections = NULL; abfd->section_last = NULL; abfd->section_count = 0; memset (abfd->section_htab.table, 0, abfd->section_htab.size * sizeof (struct bfd_hash_entry *)); } /* FUNCTION bfd_get_section_by_name SYNOPSIS asection *bfd_get_section_by_name (bfd *abfd, const char *name); DESCRIPTION Run through @var{abfd} and return the one of the <>s whose name matches @var{name}, otherwise <>. @xref{Sections}, for more information. This should only be used in special cases; the normal way to process all sections of a given name is to use <> and <> on the name (or better yet, base it on the section flags or something else) for each section. */ asection * bfd_get_section_by_name (bfd *abfd, const char *name) { struct section_hash_entry *sh; sh = section_hash_lookup (&abfd->section_htab, name, FALSE, FALSE); if (sh != NULL) return &sh->section; return NULL; } /* FUNCTION bfd_get_section_by_name_if SYNOPSIS asection *bfd_get_section_by_name_if (bfd *abfd, const char *name, bfd_boolean (*func) (bfd *abfd, asection *sect, void *obj), void *obj); DESCRIPTION Call the provided function @var{func} for each section attached to the BFD @var{abfd} whose name matches @var{name}, passing @var{obj} as an argument. The function will be called as if by | func (abfd, the_section, obj); It returns the first section for which @var{func} returns true, otherwise <>. */ asection * bfd_get_section_by_name_if (bfd *abfd, const char *name, bfd_boolean (*operation) (bfd *, asection *, void *), void *user_storage) { struct section_hash_entry *sh; unsigned long hash; sh = section_hash_lookup (&abfd->section_htab, name, FALSE, FALSE); if (sh == NULL) return NULL; hash = sh->root.hash; do { if ((*operation) (abfd, &sh->section, user_storage)) return &sh->section; sh = (struct section_hash_entry *) sh->root.next; } while (sh != NULL && sh->root.hash == hash && strcmp (sh->root.string, name) == 0); return NULL; } /* FUNCTION bfd_get_unique_section_name SYNOPSIS char *bfd_get_unique_section_name (bfd *abfd, const char *templat, int *count); DESCRIPTION Invent a section name that is unique in @var{abfd} by tacking a dot and a digit suffix onto the original @var{templat}. If @var{count} is non-NULL, then it specifies the first number tried as a suffix to generate a unique name. The value pointed to by @var{count} will be incremented in this case. */ char * bfd_get_unique_section_name (bfd *abfd, const char *templat, int *count) { int num; unsigned int len; char *sname; len = strlen (templat); sname = bfd_malloc (len + 8); if (sname == NULL) return NULL; memcpy (sname, templat, len); num = 1; if (count != NULL) num = *count; do { /* If we have a million sections, something is badly wrong. */ if (num > 999999) abort (); sprintf (sname + len, ".%d", num++); } while (section_hash_lookup (&abfd->section_htab, sname, FALSE, FALSE)); if (count != NULL) *count = num; return sname; } /* FUNCTION bfd_make_section_old_way SYNOPSIS asection *bfd_make_section_old_way (bfd *abfd, const char *name); DESCRIPTION Create a new empty section called @var{name} and attach it to the end of the chain of sections for the BFD @var{abfd}. An attempt to create a section with a name which is already in use returns its pointer without changing the section chain. It has the funny name since this is the way it used to be before it was rewritten.... Possible errors are: o <> - If output has already started for this BFD. o <> - If memory allocation fails. */ asection * bfd_make_section_old_way (bfd *abfd, const char *name) { asection *newsect; if (abfd->output_has_begun) { bfd_set_error (bfd_error_invalid_operation); return NULL; } if (strcmp (name, BFD_ABS_SECTION_NAME) == 0) newsect = bfd_abs_section_ptr; else if (strcmp (name, BFD_COM_SECTION_NAME) == 0) newsect = bfd_com_section_ptr; else if (strcmp (name, BFD_UND_SECTION_NAME) == 0) newsect = bfd_und_section_ptr; else if (strcmp (name, BFD_IND_SECTION_NAME) == 0) newsect = bfd_ind_section_ptr; else { struct section_hash_entry *sh; sh = section_hash_lookup (&abfd->section_htab, name, TRUE, FALSE); if (sh == NULL) return NULL; newsect = &sh->section; if (newsect->name != NULL) { /* Section already exists. */ return newsect; } newsect->name = name; return bfd_section_init (abfd, newsect); } /* Call new_section_hook when "creating" the standard abs, com, und and ind sections to tack on format specific section data. Also, create a proper section symbol. */ if (! BFD_SEND (abfd, _new_section_hook, (abfd, newsect))) return NULL; return newsect; } /* FUNCTION bfd_make_section_anyway_with_flags SYNOPSIS asection *bfd_make_section_anyway_with_flags (bfd *abfd, const char *name, flagword flags); DESCRIPTION Create a new empty section called @var{name} and attach it to the end of the chain of sections for @var{abfd}. Create a new section even if there is already a section with that name. Also set the attributes of the new section to the value @var{flags}. Return <> and set <> on error; possible errors are: o <> - If output has already started for @var{abfd}. o <> - If memory allocation fails. */ sec_ptr bfd_make_section_anyway_with_flags (bfd *abfd, const char *name, flagword flags) { struct section_hash_entry *sh; asection *newsect; if (abfd->output_has_begun) { bfd_set_error (bfd_error_invalid_operation); return NULL; } sh = section_hash_lookup (&abfd->section_htab, name, TRUE, FALSE); if (sh == NULL) return NULL; newsect = &sh->section; if (newsect->name != NULL) { /* We are making a section of the same name. Put it in the section hash table. Even though we can't find it directly by a hash lookup, we'll be able to find the section by traversing sh->root.next quicker than looking at all the bfd sections. */ struct section_hash_entry *new_sh; new_sh = (struct section_hash_entry *) bfd_section_hash_newfunc (NULL, &abfd->section_htab, name); if (new_sh == NULL) return NULL; new_sh->root = sh->root; sh->root.next = &new_sh->root; newsect = &new_sh->section; } newsect->flags = flags; newsect->name = name; return bfd_section_init (abfd, newsect); } /* FUNCTION bfd_make_section_anyway SYNOPSIS asection *bfd_make_section_anyway (bfd *abfd, const char *name); DESCRIPTION Create a new empty section called @var{name} and attach it to the end of the chain of sections for @var{abfd}. Create a new section even if there is already a section with that name. Return <> and set <> on error; possible errors are: o <> - If output has already started for @var{abfd}. o <> - If memory allocation fails. */ sec_ptr bfd_make_section_anyway (bfd *abfd, const char *name) { return bfd_make_section_anyway_with_flags (abfd, name, 0); } /* FUNCTION bfd_make_section_with_flags SYNOPSIS asection *bfd_make_section_with_flags (bfd *, const char *name, flagword flags); DESCRIPTION Like <>, but return <> (without calling bfd_set_error ()) without changing the section chain if there is already a section named @var{name}. Also set the attributes of the new section to the value @var{flags}. If there is an error, return <> and set <>. */ asection * bfd_make_section_with_flags (bfd *abfd, const char *name, flagword flags) { struct section_hash_entry *sh; asection *newsect; if (abfd->output_has_begun) { bfd_set_error (bfd_error_invalid_operation); return NULL; } if (strcmp (name, BFD_ABS_SECTION_NAME) == 0 || strcmp (name, BFD_COM_SECTION_NAME) == 0 || strcmp (name, BFD_UND_SECTION_NAME) == 0 || strcmp (name, BFD_IND_SECTION_NAME) == 0) return NULL; sh = section_hash_lookup (&abfd->section_htab, name, TRUE, FALSE); if (sh == NULL) return NULL; newsect = &sh->section; if (newsect->name != NULL) { /* Section already exists. */ return NULL; } newsect->name = name; newsect->flags = flags; return bfd_section_init (abfd, newsect); } /* FUNCTION bfd_make_section SYNOPSIS asection *bfd_make_section (bfd *, const char *name); DESCRIPTION Like <>, but return <> (without calling bfd_set_error ()) without changing the section chain if there is already a section named @var{name}. If there is an error, return <> and set <>. */ asection * bfd_make_section (bfd *abfd, const char *name) { return bfd_make_section_with_flags (abfd, name, 0); } /* FUNCTION bfd_set_section_flags SYNOPSIS bfd_boolean bfd_set_section_flags (bfd *abfd, asection *sec, flagword flags); DESCRIPTION Set the attributes of the section @var{sec} in the BFD @var{abfd} to the value @var{flags}. Return <> on success, <> on error. Possible error returns are: o <> - The section cannot have one or more of the attributes requested. For example, a .bss section in <> may not have the <> field set. */ bfd_boolean bfd_set_section_flags (bfd *abfd ATTRIBUTE_UNUSED, sec_ptr section, flagword flags) { section->flags = flags; return TRUE; } /* FUNCTION bfd_map_over_sections SYNOPSIS void bfd_map_over_sections (bfd *abfd, void (*func) (bfd *abfd, asection *sect, void *obj), void *obj); DESCRIPTION Call the provided function @var{func} for each section attached to the BFD @var{abfd}, passing @var{obj} as an argument. The function will be called as if by | func (abfd, the_section, obj); This is the preferred method for iterating over sections; an alternative would be to use a loop: | section *p; | for (p = abfd->sections; p != NULL; p = p->next) | func (abfd, p, ...) */ void bfd_map_over_sections (bfd *abfd, void (*operation) (bfd *, asection *, void *), void *user_storage) { asection *sect; unsigned int i = 0; for (sect = abfd->sections; sect != NULL; i++, sect = sect->next) (*operation) (abfd, sect, user_storage); if (i != abfd->section_count) /* Debugging */ abort (); } /* FUNCTION bfd_sections_find_if SYNOPSIS asection *bfd_sections_find_if (bfd *abfd, bfd_boolean (*operation) (bfd *abfd, asection *sect, void *obj), void *obj); DESCRIPTION Call the provided function @var{operation} for each section attached to the BFD @var{abfd}, passing @var{obj} as an argument. The function will be called as if by | operation (abfd, the_section, obj); It returns the first section for which @var{operation} returns true. */ asection * bfd_sections_find_if (bfd *abfd, bfd_boolean (*operation) (bfd *, asection *, void *), void *user_storage) { asection *sect; for (sect = abfd->sections; sect != NULL; sect = sect->next) if ((*operation) (abfd, sect, user_storage)) break; return sect; } /* FUNCTION bfd_set_section_size SYNOPSIS bfd_boolean bfd_set_section_size (bfd *abfd, asection *sec, bfd_size_type val); DESCRIPTION Set @var{sec} to the size @var{val}. If the operation is ok, then <> is returned, else <>. Possible error returns: o <> - Writing has started to the BFD, so setting the size is invalid. */ bfd_boolean bfd_set_section_size (bfd *abfd, sec_ptr ptr, bfd_size_type val) { /* Once you've started writing to any section you cannot create or change the size of any others. */ if (abfd->output_has_begun) { bfd_set_error (bfd_error_invalid_operation); return FALSE; } ptr->size = val; return TRUE; } /* FUNCTION bfd_set_section_contents SYNOPSIS bfd_boolean bfd_set_section_contents (bfd *abfd, asection *section, const void *data, file_ptr offset, bfd_size_type count); DESCRIPTION Sets the contents of the section @var{section} in BFD @var{abfd} to the data starting in memory at @var{data}. The data is written to the output section starting at offset @var{offset} for @var{count} octets. Normally <> is returned, else <>. Possible error returns are: o <> - The output section does not have the <> attribute, so nothing can be written to it. o and some more too This routine is front end to the back end function <<_bfd_set_section_contents>>. */ bfd_boolean bfd_set_section_contents (bfd *abfd, sec_ptr section, const void *location, file_ptr offset, bfd_size_type count) { bfd_size_type sz; if (!(bfd_get_section_flags (abfd, section) & SEC_HAS_CONTENTS)) { bfd_set_error (bfd_error_no_contents); return FALSE; } sz = section->size; if ((bfd_size_type) offset > sz || count > sz || offset + count > sz || count != (size_t) count) { bfd_set_error (bfd_error_bad_value); return FALSE; } if (!bfd_write_p (abfd)) { bfd_set_error (bfd_error_invalid_operation); return FALSE; } /* Record a copy of the data in memory if desired. */ if (section->contents && location != section->contents + offset) memcpy (section->contents + offset, location, (size_t) count); if (BFD_SEND (abfd, _bfd_set_section_contents, (abfd, section, location, offset, count))) { abfd->output_has_begun = TRUE; return TRUE; } return FALSE; } /* FUNCTION bfd_get_section_contents SYNOPSIS bfd_boolean bfd_get_section_contents (bfd *abfd, asection *section, void *location, file_ptr offset, bfd_size_type count); DESCRIPTION Read data from @var{section} in BFD @var{abfd} into memory starting at @var{location}. The data is read at an offset of @var{offset} from the start of the input section, and is read for @var{count} bytes. If the contents of a constructor with the <> flag set are requested or if the section does not have the <> flag set, then the @var{location} is filled with zeroes. If no errors occur, <> is returned, else <>. */ bfd_boolean bfd_get_section_contents (bfd *abfd, sec_ptr section, void *location, file_ptr offset, bfd_size_type count) { bfd_size_type sz; if (section->flags & SEC_CONSTRUCTOR) { memset (location, 0, (size_t) count); return TRUE; } sz = section->rawsize ? section->rawsize : section->size; if ((bfd_size_type) offset > sz || count > sz || offset + count > sz || count != (size_t) count) { bfd_set_error (bfd_error_bad_value); return FALSE; } if (count == 0) /* Don't bother. */ return TRUE; if ((section->flags & SEC_HAS_CONTENTS) == 0) { memset (location, 0, (size_t) count); return TRUE; } if ((section->flags & SEC_IN_MEMORY) != 0) { memcpy (location, section->contents + offset, (size_t) count); return TRUE; } return BFD_SEND (abfd, _bfd_get_section_contents, (abfd, section, location, offset, count)); } /* FUNCTION bfd_malloc_and_get_section SYNOPSIS bfd_boolean bfd_malloc_and_get_section (bfd *abfd, asection *section, bfd_byte **buf); DESCRIPTION Read all data from @var{section} in BFD @var{abfd} into a buffer, *@var{buf}, malloc'd by this function. */ bfd_boolean bfd_malloc_and_get_section (bfd *abfd, sec_ptr sec, bfd_byte **buf) { bfd_size_type sz = sec->rawsize ? sec->rawsize : sec->size; bfd_byte *p = NULL; *buf = p; if (sz == 0) return TRUE; p = bfd_malloc (sec->rawsize > sec->size ? sec->rawsize : sec->size); if (p == NULL) return FALSE; *buf = p; return bfd_get_section_contents (abfd, sec, p, 0, sz); } /* FUNCTION bfd_copy_private_section_data SYNOPSIS bfd_boolean bfd_copy_private_section_data (bfd *ibfd, asection *isec, bfd *obfd, asection *osec); DESCRIPTION Copy private section information from @var{isec} in the BFD @var{ibfd} to the section @var{osec} in the BFD @var{obfd}. Return <> on success, <> on error. Possible error returns are: o <> - Not enough memory exists to create private data for @var{osec}. .#define bfd_copy_private_section_data(ibfd, isection, obfd, osection) \ . BFD_SEND (obfd, _bfd_copy_private_section_data, \ . (ibfd, isection, obfd, osection)) */ /* FUNCTION bfd_generic_is_group_section SYNOPSIS bfd_boolean bfd_generic_is_group_section (bfd *, const asection *sec); DESCRIPTION Returns TRUE if @var{sec} is a member of a group. */ bfd_boolean bfd_generic_is_group_section (bfd *abfd ATTRIBUTE_UNUSED, const asection *sec ATTRIBUTE_UNUSED) { return FALSE; } /* FUNCTION bfd_generic_discard_group SYNOPSIS bfd_boolean bfd_generic_discard_group (bfd *abfd, asection *group); DESCRIPTION Remove all members of @var{group} from the output. */ bfd_boolean bfd_generic_discard_group (bfd *abfd ATTRIBUTE_UNUSED, asection *group ATTRIBUTE_UNUSED) { return TRUE; } Index: head/contrib/binutils/include/elf/ChangeLog =================================================================== --- head/contrib/binutils/include/elf/ChangeLog (revision 275717) +++ head/contrib/binutils/include/elf/ChangeLog (revision 275718) @@ -1,636 +1,641 @@ +2009-03-04 Alan Modra + + * ppc.h (R_PPC_TLSGD, R_PPC_TLSLD): Add new relocs. + * ppc64.h (R_PPC64_TLSGD, R_PPC64_TLSLD): Add new relocs. + 2007-06-29 Joseph Myers * ppc.h (Tag_GNU_Power_ABI_FP): Define. 2007-06-29 Joseph Myers * mips.h (Tag_GNU_MIPS_ABI_FP): Define. 2007-06-29 Joseph Myers * arm.h (elf32_arm_add_eabi_attr_int, elf32_arm_add_eabi_attr_string, elf32_arm_add_eabi_attr_compat, elf32_arm_get_eabi_attr_int, elf32_arm_set_eabi_attr_contents, elf32_arm_eabi_attr_size, Tag_NULL, Tag_File, Tag_Section, Tag_Symbol, Tag_compatibility): Remove. * common.h (SHT_GNU_ATTRIBUTES): Define. 2007-06-29 M R Swami Reddy * common.h (EM_CR16): New entry for CR16 cpu. * cr16.h: New file. 2007-06-11 Sterling Augustine Bob Wilson * xtensa.h (XTENSA_PROP_INSN_NO_TRANSFORM): Renamed to... (XTENSA_PROP_NO_TRANSFORM): ...this. 2007-05-18 Caroline Tice * dwarf2.h: (enum dwarf_location_atom): Add new DW_OP, DW_OP_GNU_uninit. 2007-05-12 Alan Modra * spu.h (R_SPU_ADDR16X): Define. (R_SPU_PPU32, R_SPU_PPU64): Renumber. 2007-05-11 Alan Modra * spu.h (R_SPU_PPU32, R_SPU_PPU64): Define. 2007-05-02 Alan Modra * internal.h (ELF_IS_SECTION_IN_SEGMENT): Check both file offset and vma for appropriate sections. 2007-04-26 Jan Beulich * common.h (DT_ENCODING): Correct value (back to spec mandated value). 2007-03-08 Alan Modra * v850.h (V850_OTHER_TDA_BYTE): Delete. (V850_OTHER_SDA, V850_OTHER_ZDA, V850_OTHER_TDA): Assign bits that don't clash with visibility bits. 2007-03-07 Alan Modra * common.h (ELF_ST_VISIBILITY): Comment typo fix. 2007-02-05 Dave Brolley Richard Sandiford Richard Henderson DJ Delorie Ben Elliston * mep.h: New file. * common.h (EM_CYGNUS_MEP): Define. 2007-02-15 Dave Brolley From Graydon Hoare : * common.h (STT_RELC, STT_SRELC, R_RELC): New macros. 2007-01-08 Kazu Hirata * m68k.h (EF_M68K_FIDO): New. (EF_M68K_ARCH_MASK): OR EF_M68K_FIDO. (EF_M68K_CPU32_FIDO_A, EF_M68K_CPU32_MASK): Remove. 2006-12-25 Kazu Hirata * m68k.h (EF_M68K_CPU32_FIDO_A, EF_M68K_CPU32_MASK): New. 2006-12-19 Kazu Hirata * m68k.h (EF_M68K_ARCH_MASK): New. 2006-12-19 Nathan Sidwell * internal.h (struct elf_segment_map): Add p_vaddr_offset field. 2006-12-07 Kazu Hirata * m68k.h (EF_M68K_ISA_MASK, EF_M68K_ISA_A_NODIV, EF_M68K_ISA_A, EF_M68K_ISA_A_PLUS, EF_M68K_ISA_B_NOUSP, EF_M68K_ISA_B, EF_M68K_ISA_C, EF_M68K_MAC_MASK, EF_M68K_MAC, EF_M68K_EMAC, EF_M68K_EMAC_B, EF_M68K_FLOAT): Rename to EF_M68K_CF_ISA_MASK, EF_M68K_CF_ISA_A_NODIV, EF_M68K_CF_ISA_A, EF_M68K_CF_ISA_A_PLUS, EF_M68K_CF_ISA_B_NOUSP, EF_M68K_CF_ISA_B, EF_M68K_CF_ISA_C, EF_M68K_CF_MAC_MASK, EF_M68K_CF_MAC, EF_M68K_CF_EMAC, EF_M68K_CF_EMAC_B, EF_M68K_CF_FLOAT, respectively. 2006-12-05 Michael Tautschnig Nick Clifton * external.h (struct Elf_External_Versym): Use ATTRIBUTE_PACKED. 2006-10-28 Richard Sandiford * mips.h (R_MIPS_GLOB_DAT): Define (R_MIPS_max): Bump by 1. 2006-10-25 Trevor Smigiel Yukishige Shibata Nobuhisa Fujinami Takeaki Fukuoka Alan Modra * common.h (EM_SPU): Define. * spu.h: New file. 2006-10-19 Mei Ligang * score.h (EF_SCORE_PIC): Redefine EF_SCORE_PIC as 0x80000000. (EF_SCORE_FIXDEP): Redefine EF_SCORE_FIXDEP as 0x40000000. (EF_SCORE_HASENTRY): Delete. 2006-09-17 Mei Ligang * score.h: New file. * common.h: Add Score machine number. 2006-07-10 Jakub Jelinek * common.h (SHT_GNU_HASH, DT_GNU_HASH): Define. 2006-05-31 H.J. Lu * internal.h (ELF_SECTION_SIZE): New. (ELF_IS_SECTION_IN_SEGMENT): Likewise. (ELF_IS_SECTION_IN_SEGMENT_FILE): Updated. (ELF_IS_SECTION_IN_SEGMENT_MEMORY): Likewise. 2006-05-27 H.J. Lu * internal.h (struct elf_segment_map): Add p_align and p_align_valid. 2006-05-24 Carlos O'Donell Randolph Chung * hppa.h (R_PARISC_TLS_GD21L, R_PARISC_TLS_GD14R, R_PARISC_TLS_GDCALL, R_PARISC_TLS_LDM21L, R_PARISC_TLS_LDM14R, R_PARISC_TLS_LDMCALL, R_PARISC_TLS_LDO21L, R_PARISC_TLS_LDO14R, R_PARISC_TLS_DTPMOD32, R_PARISC_TLS_DTPMOD64, R_PARISC_TLS_DTPOFF32, R_PARISC_TLS_DTPOFF64): New TLS relocs. (R_PARISC_TLS_LE21L, R_PARISC_TLS_LE14R, R_PARISC_TLS_IE21L, R_PARISC_TLS_IE14R, R_PARISC_TLS_TPREL32, R_PARISC_TLS_TPREL64): Define TLS relocs using existing equivalents. 2006-05-24 Bjoern Haase * avr.h: Add E_AVR_MACH_AVR6, R_AVR_LO8_LDI_GS and R_AVR_HI8_LDI_GS. 2006-03-22 Richard Sandiford Daniel Jacobowitz Phil Edwards Zack Weinberg Mark Mitchell Nathan Sidwell * mips.h (R_MIPS_COPY, R_MIPS_JUMP_SLOT): New relocs. 2006-03-19 John David Anglin * hppa.h (SHF_HP_TLS, SHF_HP_NEAR_SHARED, SHF_HP_FAR_SHARED, SHF_HP_COMDAT, SHF_HP_CONST, SHN_TLS_COMMON, SHN_NS_COMMON, SHN_NS_UNDEF, SHN_FS_UNDEF, SHN_HP_EXTERN, SHN_HP_EXTHINT, SHN_HP_UNDEF_BIND_IMM, SHT_HP_OVLBITS, SHT_HP_DLKM, SHT_HP_COMDAT, SHT_HP_OBJDICT, SHT_HP_ANNOT, STB_HP_ALIAS): Define. 2006-03-10 Paul Brook * arm.h (EF_ARM_EABI_VER5): Define. 2006-03-06 Nathan Sidwell * m68k.h (EF_M68K_ISA_MASK, EF_M68K_ISA_A, EF_M68K_ISA_A_PLUS, EF_M68K_ISA_B, EF_M68K_ISA_C): Adjust. (EF_M68K_ISA_A_NODIV, EF_M68K_ISA_B_NOUSP): New. (EF_M68K_HW_DIV, EF_M68K_USP): Remove. (EF_M68K_MAC, EF_M68K_EMAC, EF_M68K_FLOAT): Adjust. (EF_M68K_EMAC_B): New. 2006-03-03 Bjoern Haase * avr.h (R_AVR_MS8_LDI,R_AVR_MS8_LDI_NEG): Add. (EF_AVR_LINKRELAX_PREPARED): Add. 2006-03-02 Ben Elliston Import from the GCC tree: 2006-03-01 Jakub Jelinek * dwarf2.h (DW_TAG_condition, DW_TAG_shared_type): New constants from DWARF 3. (DW_AT_description, DW_AT_binary_scale, DW_AT_decimal_scale, DW_AT_small, DW_AT_decimal_sign, DW_AT_digit_count, DW_AT_picture_string, DW_AT_mutable, DW_AT_threads_scaled, DW_AT_explicit, DW_AT_object_pointer, DW_AT_endianity, DW_AT_elemental, DW_AT_pure, DW_AT_recursive): New. (DW_OP_form_tls_address, DW_OP_call_frame_cfa, DW_OP_bit_piece): New. (DW_ATE_packed_decimal, DW_ATE_numeric_string, DW_ATE_edited, DW_ATE_signed_fixed, DW_ATE_unsigned_fixed): New. (DW_DS_unsigned, DW_DS_leading_overpunch, DW_DS_trailing_overpunch, DW_DS_leading_separate, DW_DS_trailing_separate): New. (DW_END_default, DW_END_big, DW_END_little): New. (DW_END_lo_user, DW_END_hi_user): Define. (DW_LNE_lo_user, DW_LNE_hi_user): Define. (DW_CFA_val_offset, DW_CFA_val_offset_sf, DW_CFA_val_expression): New. (DW_LANG_PLI, DW_LANG_ObjC, DW_LANG_ObjC_plus_plus, DW_LANG_UPC, DW_LANG_D): New. 2006-02-24 DJ Delorie * m32c.h: Add relax relocs. 2006-02-17 Shrirang Khisti Anil Paranjape Shilin Shakti * common.h (EM_XC16X): New entry for xc16x cpu. Sort other EM_* numbers into numerical order. * xc16x.h: New file. 2006-02-10 H.J. Lu PR binutils/2258 * internal.h (ELF_IS_SECTION_IN_SEGMENT_FILE): New. (ELF_IS_SECTION_IN_SEGMENT_MEMORY): Likewise. 2006-02-07 Nathan Sidwell * m68k.h (EF_CPU32, EF_M68000, EF_CFV4E): Rename to ... (EF_M68K_CPU32, EF_M68K_M68000, EF_M68K_CFV4E): ... here. (EF_M68K_ISA_MASK, EF_M68K_ISA_A, EF_M68K_M68K_ISA_A_PLUS, EF_M68K_ISA_B, EF_M68K_HW_DIV, EF_M68K_MAC_MASK, EF_M68K_MAC, EF_M68K_EMAC, EF_M68K_USP, EF_M68K_FLOAT): New. 2006-02-06 Steve Ellcey * ia64.h (SHF_IA_64_HP_TLS): New. 2006-01-18 Alexandre Oliva Introduce TLS descriptors for i386 and x86_64. * common.h (DT_TLSDESC_GOT, DT_TLSDESC_PLT): New. * i386.h (R_386_TLS_GOTDESC, R_386_TLS_DESC_CALL, R_386_TLS_DESC): New. * x86-64.h (R_X86_64_GOTPC32_TLSDESC, R_X86_64_TLSDESC_CALL, R_X86_64_TLSDESC): New. 2006-01-09 Mike Frysinger : * common.h (EM_ALTERA_NIOS2, EM_NIOS32) Define. 2005-12-16 Nathan Sidwell Second part of ms1 to mt renaming. * common.h (EM_MT): Renamed. * mt.h: Rename relocs, cpu & other defines. 2005-12-12 Paul Brook * arm.h (elf32_arm_get_eabi_attr_int): Add prototype. 2005-11-11 Nick Clifton PR 1150 * mips.h (STO_OPTIONAL): Define. (ELF_MIPS_IS_OPTIONAL): Define. 2005-09-30 Catherine Moore * bfin.h: New file. * common.h (EM_BLACKFIN): Define. 2005-10-08 Paul Brook * arm.h: Add prototypes for BFD object attribute routines. 2005-09-09 Richard Earnshaw * arm.h (SHT_ARM_PREEMPTMAP, SHT_ARM_ATTRIBUTES): New defines. 2005-08-09 John David Anglin * hppa.h (SHT_PARISC_DLKM, SHF_PARISC_WEAKORDER, PT_PARISC_WEAKORDER): New defines. 2005-08-04 John David Anglin * hppa.h (PF_HP_CODE, PF_HP_MODIFY, PF_HP_LAZYSWAP): Revise defines. (PF_HP_CODE_DEPR, PF_HP_MODIFY_DEPR, PF_HP_LAZYSWAP_DEPR): New deprecated defines. (DT_HP_EPLTREL, DT_HP_EPLTRELSZ, DT_HP_FILTERED, DT_HP_FILTER_TLS, DT_HP_COMPAT_FILTERED, DT_HP_LAZYLOAD, DT_HP_BIND_NOW_COUNT, DT_PLT, DT_PLT_SIZE, DT_DLT, DT_DLT_SIZE, DT_HP_BIND_DEPTH_FIRST, DT_HP_GST, DT_HP_SHLIB_FIXED, DT_HP_MERGE_SHLIB_SEG, DT_HP_NODELETE, DT_HP_GROUP, DT_HP_PROTECT_LINKAGE_TABLE, PT_HP_OPT_ANNOT, PT_HP_HSL_ANNOT, PT_HP_STACK, PT_HP_CORE_UTSNAME, NT_HP_COMPILER, NT_HP_COPYRIGHT, NT_HP_VERSION, NT_HP_SRCFILE_INFO, NT_HP_LINKER, NT_HP_INSTRUMENTED, NT_HP_UX_OPTIONS): Define. 2005-07-25 DJ Delorie * m32c.h: Add R_M32C_8, R_M32C_LO16, R_M32C_HI8, and R_M32C_HI16. 2005-07-25 Jan Hubicka * x86-64.h (SHN_X86_64_LCOMMON): New. (SHF_X86_64_LARGE): New. 2005-07-20 Kazuhiro Inaoka * m32r.h (R_M32R_REL32): Added. 2005-07-18 Ben Elliston * dwarf2.h (enum dwarf_type): Remove DW_AT_GNU_decimal_float. Replace with DW_ATE_decimal_float (now in DWARF 3). 2005-07-14 Jim Blandy Add support for Renesas M32C and M16C. * common.h (EM_M32C): New machine number. * m32c.h: New file. 2005-06-17 Jan Beulich * x86-64.h (elf_x86_64_reloc_type): Adjust comment for R_X86_64_GOTPCREL. Add R_X86_64_PC64, R_X86_64_GOTOFF64, and R_X86_64_GOTPC32. 2005-06-07 Aldy Hernandez Michael Snyder Stan Cox * common.h (EM_MS1): Define. * ms1.h: New file. 2005-05-31 Richard Henderson * alpha.h (LITUSE_ALPHA_JSRDIRECT): New. 2005-05-29 Richard Henderson * alpha.h (DT_ALPHA_PLTRO): New. 2005-05-19 Ben Elliston * dwarf2.h (enum dwarf_type): Assign DW_ATE_GNU_decimal_float from the user-defined encoding space pending inclusion in the standard. 2005-05-18 Zack Weinberg * arm.h: Make all #ifndef OLD_ARM_ABI blocks unconditional, delete all #ifdef OLD_ARM_ABI blocks. 2005-05-17 Zack Weinberg * arm.h: Import complete list of official relocation names and numbers from AAELF. Define FAKE_RELOCs for old names. Remove a few old names no longer used anywhere. 2005-05-14 Alan Modra * ppc.h (DT_PPC_GOT): Rename from DT_PPC_GLINK. 2005-05-11 Alan Modra * ppc.h (R_PPC_RELAX32, R_PPC_RELAX32PC, R_PPC_RELAX32_PLT, R_PPC_RELAX32PC_PLT) Adjust. (R_PPC_REL16, R_PPC_REL16_LO, R_PPC_REL16_HI, R_PPC_REL16_HA): Define. (DT_PPC_GLINK): Define. 2005-05-10 Nick Clifton * Update the address and phone number of the FSF organization in the GPL notices in the following files: alpha.h, arc.h, arm.h, avr.h, common.h, cr16c.h, cris.h, crx.h, d10v.h, d30v.h, dlx.h, dwarf.h, dwarf2.h, external.h, fr30.h, frv.h, h8.h, hppa.h, i370.h, i386.h, i860.h, i960.h, ia64.h, internal.h, ip2k.h, iq2000.h, m32r.h, m68hc11.h, m68k.h, mcore.h, mips.h, mmix.h, mn10200.h, mn10300.h, msp430.h, openrisc.h, or32.h, pj.h, ppc.h, ppc64.h, reloc-macros.h, s390.h, sh.h, sparc.h, v850.h, vax.h, x86-64.h, xstormy16.h, xtensa.h 2005-04-13 H.J. Lu Moved from ../ChangeLog 2004-10-27 Richard Earnshaw * arm.h: Add R_ARM_CALL and R_ARM_JUMP32. 2004-10-12 Paul Brook * arm.h (EF_ARM_EABI_VER4): Define. 2004-10-08 Daniel Jacobowitz * common.h (PT_SUNW_EH_FRAME): Define. * x86-64.h (SHT_X86_64_UNWIND): Define. 2004-10-07 Bob Wilson * xtensa.h (R_XTENSA_DIFF8, R_XTENSA_DIFF16, R_XTENSA_DIFF32, R_XTENSA_SLOT*_OP, R_XTENSA_SLOT*_ALT): New relocations. (XTENSA_PROP_SEC_NAME): Define. (property_table_entry): Add flags field. (XTENSA_PROP_*, GET_XTENSA_PROP_*, SET_XTENSA_PROP_*): Define. 2004-09-17 Paul Brook * arm.h: Remove R_ARM_STKCHK and R_ARM_THM_STKCHK. Add R_ARM_TARGET2, R_ARM_PREL31, R_ARM_GOT_ABS, R_ARM_GOT_PREL, R_ARM_GOT_BREL12, R_ARM_GOTOFF12 and R_ARM_GOTRELAX. 2004-09-13 Paul Brook * arm.h: Rename RELABS to TARGET1. 2004-05-11 Jakub Jelinek * common.h (PT_GNU_EH_FRAME, PT_GNU_STACK): Add comments. (PT_GNU_RELRO): Define. 2005-03-29 Daniel Jacobowitz Phil Blundell * arm.h: Add TLS relocations. 2005-03-23 Ben Elliston * dwarf.h: Merge with GCC's dwarf.h. 2005-03-18 C Jaipraash * m68k.h (EF_CFV4E): Define. 2005-03-17 Paul Brook Dan Jacobowitz Mark Mitchell * arm.h (PT_ARM_EXIDX): Define. 2005-03-02 Daniel Jacobowitz Joseph Myers * mips.h: Define MIPS TLS relocations. 2005-02-15 Nigel Stephens Maciej W. Rozycki * mips.h (R_MIPS16_GOT16): New reloc code. (R_MIPS16_CALL16): Likewise. (R_MIPS16_HI16): Likewise. (R_MIPS16_LO16): Likewise. (R_MIPS16_min): New fake reloc code. (R_MIPS16_max): Likewise. 2005-02-11 Maciej W. Rozycki * mips.h (R_MIPS_max): Use FAKE_RELOC to define. 2005-01-25 Alexandre Oliva 2004-12-10 Alexandre Oliva * frv.h: Add R_FRV_TLSMOFF. 2004-11-10 Alexandre Oliva * frv.h: Add TLS relocations. 2005-01-17 Nick Clifton * sh.h (EF_SH2A_SH4_NOFPU, EF_SH2A_SH3_NOFPU, EF_SH2A_SH4, EF_SH2A_SH3E): New flags. (EF_SH_BFD_TABLE): Add these new flags to the table. 2005-01-12 Alan Modra * ppc.h (R_PPC_RELAX32_PLT, R_PPC_RELAX32PC_PLT): Define. (R_PPC_RELAX32, R_PPC_RELAX32PC): Adjust value. 2004-12-22 Klaus Rudolph * avr.h (R_AVR_LDI, R_AVR_6, R_AVR_6_ADIW): New relocs. 2004-12-16 Richard Sandiford * v850.h (R_V850_LO16_SPLIT_OFFSET): New reloc. 2004-12-09 Ian Lance Taylor * mips.h (E_MIPS_MACH_9000): Define. 2004-11-04 Hans-Peter Nilsson * cris.h (EF_CRIS_VARIANT_MASK, EF_CRIS_VARIANT_ANY_V0_V10) (EF_CRIS_VARIANT_V32, EF_CRIS_VARIANT_COMMON_V10_V32): New macros. 2004-10-06 Eric Christopher * dwarf2.h: Sync with gcc dwarf2.h. Fix typo. 2004-10-01 Paul Brook * arm.h (SHT_ARM_EXIDX): Define. (ELF_STRING_ARM_unwind, ELF_STRING_ARM_unwind, ELF_STRING_ARM_unwind_once, ELF_STRING_ARM_unwind_info_once): Define. 2004-08-25 Dmitry Diky * msp430.h: Add new relocs. 2004-08-12 H.J. Lu * i386.h (R_386_USED_BY_INTEL_200): New. 2004-07-29 Alexandre Oliva Introduce SH2a support. 2004-02-18 Corinna Vinschen * sh.h (EF_SH2A_NOFPU): New. 2003-12-01 Michael Snyder * sh.h (EF_SH2A): New. 2004-07-27 Tomer Levi * crx.h: Add BFD_RELOC_CRX_SWITCH8, BFD_RELOC_CRX_SWITCH16, BFD_RELOC_CRX_SWITCH32. 2004-07-06 Tomer Levi * common.h (EM_CRX): Define. * crx.h: New file. 2004-06-25 Kazuhiro Inaoka * m32r.h: Add defintions of R_M32R_GOTOFF_HI_ULO, R_M32R_GOTOFF_HI_SLO and R_M32R_GOTOFF_LO. 2004-06-19 Alan Modra * common.h (ELF64_R_INFO): Warning fix. 2004-06-14 Chris Demetriou * mips.h (R_MIPS_PC32): Add back (undoing removal on 2004-04-24), with an updated comment. 2004-05-28 Andrew Stubbs * sh.h (EF_SH_HAS_DSP): Remove. (EF_SH_HAS_FP): Remove. (EF_SH_MERGE_MACH): Remove. (EF_SH4_NOFPU): Convert to decimal. (EF_SH4A_NOFPU): Likewise. (EF_SH4_NOMMU_NOFPU): Likewise. (EF_SH3_NOMMU): Add new macro. (EF_SH_BFD_TABLE): Likewise. (sh_find_elf_flags): Add prototype. (sh_elf_get_flags_from_mach): Likewise. 2004-04-24 Chris Demetriou * mips.h (R_MIPS_PC32, R_MIPS_PC64, R_MIPS_GNU_REL_LO16) (R_MIPS_GNU_REL_HI16): Remove. (R_MIPS_GNU_REL16_S2): Update comment. 2004-30-30 Galit Heller Tomer Levi * common.h (EM_CR): Define. * cr16c.h: New file. 2004-03-23 Paul Brook * arm.h (EF_ERM_BE8, EF_ARM_LE8, EF_ARM_EABI_VER3): Add. 2003-03-03 Andrew Stubbs * sh.h: Add EF_SH4_NOMMU_NOFPU. 2004-03-01 Richard Sandiford * frv.h (EF_FRV_CPU_FR405, EF_FRV_CPU_FR450): Define. 2004-01-28 Roland McGrath * common.h (AT_SECURE): New macro. 2004-01-21 Roland McGrath * common.h (AT_SUN_UID, AT_SUN_RUID, AT_SUN_GID): New macros. (AT_SUN_RGID, AT_SUN_LDELF, AT_SUN_LDSHDR, AT_SUN_LDNAME, AT_SUN_LPAGESZ, AT_SUN_PLATFORM, AT_SUN_HWCAP, AT_SUN_IFLUSH, AT_SUN_CPU, AT_SUN_EMUL_ENTRY, AT_SUN_EMUL_EXECFD, AT_SUN_EXECNAME) AT_SUN_MMU, AT_SUN_LDDATA): Likewise. 2004-01-17 Mark Kettenis * common.h (NT_OPENBSD_IDENT): Define. 2004-01-06 Alexandre Oliva 2003-09-18 Alexandre Oliva * frv.h (EF_FRV_FDPIC): New macro. (EF_FRV_PIC_FLAGS): Adjust. 2003-08-08 Alexandre Oliva * frv.h (R_FRV_FUNCDESC_VALUE, R_FRV_FUNCDESC_GOTOFF12, R_FRV_FUNCDESC_GOTOFFLO, R_FRV_FUNCDESC_GOTOFFHI, R_FRV_GOTOFF12, R_FRV_GOTOFFLO, R_FRV_GOTOFFHI): New. 2003-08-04 Alexandre Oliva * frv.h (R_FRV_GOT12, R_FRV_GOTHI, R_FRV_GOTLO, R_FRV_FUNCDESC, R_FRV_FUNCDESC_GOT12, R_FRV_FUNCDESC_GOTHI, R_FRV_FUNCDESC_GOTLO): New. For older changes see ChangeLog-9103 Local Variables: mode: change-log left-margin: 8 fill-column: 74 version-control: never End: Index: head/contrib/binutils/include/elf/ppc.h =================================================================== --- head/contrib/binutils/include/elf/ppc.h (revision 275717) +++ head/contrib/binutils/include/elf/ppc.h (revision 275718) @@ -1,185 +1,187 @@ /* PPC ELF support for BFD. Copyright 1995, 1996, 1998, 2000, 2001, 2002, 2003, 2005 Free Software Foundation, Inc. By Michael Meissner, Cygnus Support, , from information in the System V Application Binary Interface, PowerPC Processor Supplement and the PowerPC Embedded Application Binary Interface (eabi). This file is part of BFD, the Binary File Descriptor library. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ /* This file holds definitions specific to the PPC ELF ABI. Note that most of this is not actually implemented by BFD. */ #ifndef _ELF_PPC_H #define _ELF_PPC_H #include "elf/reloc-macros.h" /* Relocations. */ START_RELOC_NUMBERS (elf_ppc_reloc_type) RELOC_NUMBER (R_PPC_NONE, 0) RELOC_NUMBER (R_PPC_ADDR32, 1) RELOC_NUMBER (R_PPC_ADDR24, 2) RELOC_NUMBER (R_PPC_ADDR16, 3) RELOC_NUMBER (R_PPC_ADDR16_LO, 4) RELOC_NUMBER (R_PPC_ADDR16_HI, 5) RELOC_NUMBER (R_PPC_ADDR16_HA, 6) RELOC_NUMBER (R_PPC_ADDR14, 7) RELOC_NUMBER (R_PPC_ADDR14_BRTAKEN, 8) RELOC_NUMBER (R_PPC_ADDR14_BRNTAKEN, 9) RELOC_NUMBER (R_PPC_REL24, 10) RELOC_NUMBER (R_PPC_REL14, 11) RELOC_NUMBER (R_PPC_REL14_BRTAKEN, 12) RELOC_NUMBER (R_PPC_REL14_BRNTAKEN, 13) RELOC_NUMBER (R_PPC_GOT16, 14) RELOC_NUMBER (R_PPC_GOT16_LO, 15) RELOC_NUMBER (R_PPC_GOT16_HI, 16) RELOC_NUMBER (R_PPC_GOT16_HA, 17) RELOC_NUMBER (R_PPC_PLTREL24, 18) RELOC_NUMBER (R_PPC_COPY, 19) RELOC_NUMBER (R_PPC_GLOB_DAT, 20) RELOC_NUMBER (R_PPC_JMP_SLOT, 21) RELOC_NUMBER (R_PPC_RELATIVE, 22) RELOC_NUMBER (R_PPC_LOCAL24PC, 23) RELOC_NUMBER (R_PPC_UADDR32, 24) RELOC_NUMBER (R_PPC_UADDR16, 25) RELOC_NUMBER (R_PPC_REL32, 26) RELOC_NUMBER (R_PPC_PLT32, 27) RELOC_NUMBER (R_PPC_PLTREL32, 28) RELOC_NUMBER (R_PPC_PLT16_LO, 29) RELOC_NUMBER (R_PPC_PLT16_HI, 30) RELOC_NUMBER (R_PPC_PLT16_HA, 31) RELOC_NUMBER (R_PPC_SDAREL16, 32) RELOC_NUMBER (R_PPC_SECTOFF, 33) RELOC_NUMBER (R_PPC_SECTOFF_LO, 34) RELOC_NUMBER (R_PPC_SECTOFF_HI, 35) RELOC_NUMBER (R_PPC_SECTOFF_HA, 36) RELOC_NUMBER (R_PPC_ADDR30, 37) /* Relocs added to support TLS. */ RELOC_NUMBER (R_PPC_TLS, 67) RELOC_NUMBER (R_PPC_DTPMOD32, 68) RELOC_NUMBER (R_PPC_TPREL16, 69) RELOC_NUMBER (R_PPC_TPREL16_LO, 70) RELOC_NUMBER (R_PPC_TPREL16_HI, 71) RELOC_NUMBER (R_PPC_TPREL16_HA, 72) RELOC_NUMBER (R_PPC_TPREL32, 73) RELOC_NUMBER (R_PPC_DTPREL16, 74) RELOC_NUMBER (R_PPC_DTPREL16_LO, 75) RELOC_NUMBER (R_PPC_DTPREL16_HI, 76) RELOC_NUMBER (R_PPC_DTPREL16_HA, 77) RELOC_NUMBER (R_PPC_DTPREL32, 78) RELOC_NUMBER (R_PPC_GOT_TLSGD16, 79) RELOC_NUMBER (R_PPC_GOT_TLSGD16_LO, 80) RELOC_NUMBER (R_PPC_GOT_TLSGD16_HI, 81) RELOC_NUMBER (R_PPC_GOT_TLSGD16_HA, 82) RELOC_NUMBER (R_PPC_GOT_TLSLD16, 83) RELOC_NUMBER (R_PPC_GOT_TLSLD16_LO, 84) RELOC_NUMBER (R_PPC_GOT_TLSLD16_HI, 85) RELOC_NUMBER (R_PPC_GOT_TLSLD16_HA, 86) RELOC_NUMBER (R_PPC_GOT_TPREL16, 87) RELOC_NUMBER (R_PPC_GOT_TPREL16_LO, 88) RELOC_NUMBER (R_PPC_GOT_TPREL16_HI, 89) RELOC_NUMBER (R_PPC_GOT_TPREL16_HA, 90) RELOC_NUMBER (R_PPC_GOT_DTPREL16, 91) RELOC_NUMBER (R_PPC_GOT_DTPREL16_LO, 92) RELOC_NUMBER (R_PPC_GOT_DTPREL16_HI, 93) RELOC_NUMBER (R_PPC_GOT_DTPREL16_HA, 94) + RELOC_NUMBER (R_PPC_TLSGD, 95) + RELOC_NUMBER (R_PPC_TLSLD, 96) /* The remaining relocs are from the Embedded ELF ABI, and are not in the SVR4 ELF ABI. */ RELOC_NUMBER (R_PPC_EMB_NADDR32, 101) RELOC_NUMBER (R_PPC_EMB_NADDR16, 102) RELOC_NUMBER (R_PPC_EMB_NADDR16_LO, 103) RELOC_NUMBER (R_PPC_EMB_NADDR16_HI, 104) RELOC_NUMBER (R_PPC_EMB_NADDR16_HA, 105) RELOC_NUMBER (R_PPC_EMB_SDAI16, 106) RELOC_NUMBER (R_PPC_EMB_SDA2I16, 107) RELOC_NUMBER (R_PPC_EMB_SDA2REL, 108) RELOC_NUMBER (R_PPC_EMB_SDA21, 109) RELOC_NUMBER (R_PPC_EMB_MRKREF, 110) RELOC_NUMBER (R_PPC_EMB_RELSEC16, 111) RELOC_NUMBER (R_PPC_EMB_RELST_LO, 112) RELOC_NUMBER (R_PPC_EMB_RELST_HI, 113) RELOC_NUMBER (R_PPC_EMB_RELST_HA, 114) RELOC_NUMBER (R_PPC_EMB_BIT_FLD, 115) RELOC_NUMBER (R_PPC_EMB_RELSDA, 116) /* Fake relocations for branch stubs, only used internally by ld. */ #define R_PPC_RELAX32 245 #define R_PPC_RELAX32PC 246 #define R_PPC_RELAX32_PLT 247 #define R_PPC_RELAX32PC_PLT 248 /* These are GNU extensions used in PIC code sequences. */ RELOC_NUMBER (R_PPC_REL16, 249) RELOC_NUMBER (R_PPC_REL16_LO, 250) RELOC_NUMBER (R_PPC_REL16_HI, 251) RELOC_NUMBER (R_PPC_REL16_HA, 252) /* These are GNU extensions to enable C++ vtable garbage collection. */ RELOC_NUMBER (R_PPC_GNU_VTINHERIT, 253) RELOC_NUMBER (R_PPC_GNU_VTENTRY, 254) /* This is a phony reloc to handle any old fashioned TOC16 references that may still be in object files. */ RELOC_NUMBER (R_PPC_TOC16, 255) END_RELOC_NUMBERS (R_PPC_max) #define IS_PPC_TLS_RELOC(R) \ ((R) >= R_PPC_TLS && (R) <= R_PPC_GOT_DTPREL16_HA) /* Specify the value of _GLOBAL_OFFSET_TABLE_. */ #define DT_PPC_GOT DT_LOPROC /* Processor specific flags for the ELF header e_flags field. */ #define EF_PPC_EMB 0x80000000 /* PowerPC embedded flag. */ #define EF_PPC_RELOCATABLE 0x00010000 /* PowerPC -mrelocatable flag. */ #define EF_PPC_RELOCATABLE_LIB 0x00008000 /* PowerPC -mrelocatable-lib flag. */ /* Processor specific section headers, sh_type field. */ #define SHT_ORDERED SHT_HIPROC /* Link editor is to sort the \ entries in this section \ based on the address \ specified in the associated \ symbol table entry. */ /* Processor specific section flags, sh_flags field. */ #define SHF_EXCLUDE 0x80000000 /* Link editor is to exclude \ this section from executable \ and shared objects that it \ builds when those objects \ are not to be furhter \ relocated. */ /* Object attribute tags. */ enum { /* 0-3 are generic. */ Tag_GNU_Power_ABI_FP = 4, /* Value 1 for hard-float, 2 for soft-float; 0 for not tagged or not using any ABIs affected by the differences. */ }; #endif /* _ELF_PPC_H */ Index: head/contrib/binutils/include/elf/ppc64.h =================================================================== --- head/contrib/binutils/include/elf/ppc64.h (revision 275717) +++ head/contrib/binutils/include/elf/ppc64.h (revision 275718) @@ -1,156 +1,158 @@ /* PPC64 ELF support for BFD. - Copyright 2003 Free Software Foundation, Inc. + Copyright 2003, 2005, 2009 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _ELF_PPC64_H #define _ELF_PPC64_H #include "elf/reloc-macros.h" /* Relocations. */ START_RELOC_NUMBERS (elf_ppc64_reloc_type) RELOC_NUMBER (R_PPC64_NONE, 0) RELOC_NUMBER (R_PPC64_ADDR32, 1) RELOC_NUMBER (R_PPC64_ADDR24, 2) RELOC_NUMBER (R_PPC64_ADDR16, 3) RELOC_NUMBER (R_PPC64_ADDR16_LO, 4) RELOC_NUMBER (R_PPC64_ADDR16_HI, 5) RELOC_NUMBER (R_PPC64_ADDR16_HA, 6) RELOC_NUMBER (R_PPC64_ADDR14, 7) RELOC_NUMBER (R_PPC64_ADDR14_BRTAKEN, 8) RELOC_NUMBER (R_PPC64_ADDR14_BRNTAKEN, 9) RELOC_NUMBER (R_PPC64_REL24, 10) RELOC_NUMBER (R_PPC64_REL14, 11) RELOC_NUMBER (R_PPC64_REL14_BRTAKEN, 12) RELOC_NUMBER (R_PPC64_REL14_BRNTAKEN, 13) RELOC_NUMBER (R_PPC64_GOT16, 14) RELOC_NUMBER (R_PPC64_GOT16_LO, 15) RELOC_NUMBER (R_PPC64_GOT16_HI, 16) RELOC_NUMBER (R_PPC64_GOT16_HA, 17) /* 18 unused. 32-bit reloc is R_PPC_PLTREL24. */ RELOC_NUMBER (R_PPC64_COPY, 19) RELOC_NUMBER (R_PPC64_GLOB_DAT, 20) RELOC_NUMBER (R_PPC64_JMP_SLOT, 21) RELOC_NUMBER (R_PPC64_RELATIVE, 22) /* 23 unused. 32-bit reloc is R_PPC_LOCAL24PC. */ RELOC_NUMBER (R_PPC64_UADDR32, 24) RELOC_NUMBER (R_PPC64_UADDR16, 25) RELOC_NUMBER (R_PPC64_REL32, 26) RELOC_NUMBER (R_PPC64_PLT32, 27) RELOC_NUMBER (R_PPC64_PLTREL32, 28) RELOC_NUMBER (R_PPC64_PLT16_LO, 29) RELOC_NUMBER (R_PPC64_PLT16_HI, 30) RELOC_NUMBER (R_PPC64_PLT16_HA, 31) /* 32 unused. 32-bit reloc is R_PPC_SDAREL16. */ RELOC_NUMBER (R_PPC64_SECTOFF, 33) RELOC_NUMBER (R_PPC64_SECTOFF_LO, 34) RELOC_NUMBER (R_PPC64_SECTOFF_HI, 35) RELOC_NUMBER (R_PPC64_SECTOFF_HA, 36) RELOC_NUMBER (R_PPC64_REL30, 37) RELOC_NUMBER (R_PPC64_ADDR64, 38) RELOC_NUMBER (R_PPC64_ADDR16_HIGHER, 39) RELOC_NUMBER (R_PPC64_ADDR16_HIGHERA, 40) RELOC_NUMBER (R_PPC64_ADDR16_HIGHEST, 41) RELOC_NUMBER (R_PPC64_ADDR16_HIGHESTA, 42) RELOC_NUMBER (R_PPC64_UADDR64, 43) RELOC_NUMBER (R_PPC64_REL64, 44) RELOC_NUMBER (R_PPC64_PLT64, 45) RELOC_NUMBER (R_PPC64_PLTREL64, 46) RELOC_NUMBER (R_PPC64_TOC16, 47) RELOC_NUMBER (R_PPC64_TOC16_LO, 48) RELOC_NUMBER (R_PPC64_TOC16_HI, 49) RELOC_NUMBER (R_PPC64_TOC16_HA, 50) RELOC_NUMBER (R_PPC64_TOC, 51) RELOC_NUMBER (R_PPC64_PLTGOT16, 52) RELOC_NUMBER (R_PPC64_PLTGOT16_LO, 53) RELOC_NUMBER (R_PPC64_PLTGOT16_HI, 54) RELOC_NUMBER (R_PPC64_PLTGOT16_HA, 55) /* The following relocs were added in the 64-bit PowerPC ELF ABI revision 1.2. */ RELOC_NUMBER (R_PPC64_ADDR16_DS, 56) RELOC_NUMBER (R_PPC64_ADDR16_LO_DS, 57) RELOC_NUMBER (R_PPC64_GOT16_DS, 58) RELOC_NUMBER (R_PPC64_GOT16_LO_DS, 59) RELOC_NUMBER (R_PPC64_PLT16_LO_DS, 60) RELOC_NUMBER (R_PPC64_SECTOFF_DS, 61) RELOC_NUMBER (R_PPC64_SECTOFF_LO_DS, 62) RELOC_NUMBER (R_PPC64_TOC16_DS, 63) RELOC_NUMBER (R_PPC64_TOC16_LO_DS, 64) RELOC_NUMBER (R_PPC64_PLTGOT16_DS, 65) RELOC_NUMBER (R_PPC64_PLTGOT16_LO_DS, 66) /* Relocs added to support TLS. PowerPC64 ELF ABI revision 1.5. */ RELOC_NUMBER (R_PPC64_TLS, 67) RELOC_NUMBER (R_PPC64_DTPMOD64, 68) RELOC_NUMBER (R_PPC64_TPREL16, 69) RELOC_NUMBER (R_PPC64_TPREL16_LO, 70) RELOC_NUMBER (R_PPC64_TPREL16_HI, 71) RELOC_NUMBER (R_PPC64_TPREL16_HA, 72) RELOC_NUMBER (R_PPC64_TPREL64, 73) RELOC_NUMBER (R_PPC64_DTPREL16, 74) RELOC_NUMBER (R_PPC64_DTPREL16_LO, 75) RELOC_NUMBER (R_PPC64_DTPREL16_HI, 76) RELOC_NUMBER (R_PPC64_DTPREL16_HA, 77) RELOC_NUMBER (R_PPC64_DTPREL64, 78) RELOC_NUMBER (R_PPC64_GOT_TLSGD16, 79) RELOC_NUMBER (R_PPC64_GOT_TLSGD16_LO, 80) RELOC_NUMBER (R_PPC64_GOT_TLSGD16_HI, 81) RELOC_NUMBER (R_PPC64_GOT_TLSGD16_HA, 82) RELOC_NUMBER (R_PPC64_GOT_TLSLD16, 83) RELOC_NUMBER (R_PPC64_GOT_TLSLD16_LO, 84) RELOC_NUMBER (R_PPC64_GOT_TLSLD16_HI, 85) RELOC_NUMBER (R_PPC64_GOT_TLSLD16_HA, 86) RELOC_NUMBER (R_PPC64_GOT_TPREL16_DS, 87) RELOC_NUMBER (R_PPC64_GOT_TPREL16_LO_DS, 88) RELOC_NUMBER (R_PPC64_GOT_TPREL16_HI, 89) RELOC_NUMBER (R_PPC64_GOT_TPREL16_HA, 90) RELOC_NUMBER (R_PPC64_GOT_DTPREL16_DS, 91) RELOC_NUMBER (R_PPC64_GOT_DTPREL16_LO_DS, 92) RELOC_NUMBER (R_PPC64_GOT_DTPREL16_HI, 93) RELOC_NUMBER (R_PPC64_GOT_DTPREL16_HA, 94) RELOC_NUMBER (R_PPC64_TPREL16_DS, 95) RELOC_NUMBER (R_PPC64_TPREL16_LO_DS, 96) RELOC_NUMBER (R_PPC64_TPREL16_HIGHER, 97) RELOC_NUMBER (R_PPC64_TPREL16_HIGHERA, 98) RELOC_NUMBER (R_PPC64_TPREL16_HIGHEST, 99) RELOC_NUMBER (R_PPC64_TPREL16_HIGHESTA, 100) RELOC_NUMBER (R_PPC64_DTPREL16_DS, 101) RELOC_NUMBER (R_PPC64_DTPREL16_LO_DS, 102) RELOC_NUMBER (R_PPC64_DTPREL16_HIGHER, 103) RELOC_NUMBER (R_PPC64_DTPREL16_HIGHERA, 104) RELOC_NUMBER (R_PPC64_DTPREL16_HIGHEST, 105) RELOC_NUMBER (R_PPC64_DTPREL16_HIGHESTA, 106) + RELOC_NUMBER (R_PPC64_TLSGD, 107) + RELOC_NUMBER (R_PPC64_TLSLD, 108) /* These are GNU extensions to enable C++ vtable garbage collection. */ RELOC_NUMBER (R_PPC64_GNU_VTINHERIT, 253) RELOC_NUMBER (R_PPC64_GNU_VTENTRY, 254) END_RELOC_NUMBERS (R_PPC64_max) #define IS_PPC64_TLS_RELOC(R) \ ((R) >= R_PPC64_TLS && (R) <= R_PPC64_DTPREL16_HIGHESTA) /* Specify the start of the .glink section. */ #define DT_PPC64_GLINK DT_LOPROC /* Specify the start and size of the .opd section. */ #define DT_PPC64_OPD (DT_LOPROC + 1) #define DT_PPC64_OPDSZ (DT_LOPROC + 2) #endif /* _ELF_PPC64_H */ Index: head/gnu/usr.bin/binutils/libbfd/bfd.h =================================================================== --- head/gnu/usr.bin/binutils/libbfd/bfd.h (revision 275717) +++ head/gnu/usr.bin/binutils/libbfd/bfd.h (revision 275718) @@ -1,5405 +1,5410 @@ /* $FreeBSD$ */ /* DO NOT EDIT! -*- buffer-read-only: t -*- This file is automatically generated from "bfd-in.h", "init.c", "opncls.c", "libbfd.c", "bfdio.c", "bfdwin.c", "section.c", "archures.c", "reloc.c", "syms.c", "bfd.c", "archive.c", "corefile.c", "targets.c", "format.c", "linker.c" and "simple.c". Run "make headers" in your build bfd/ to regenerate. */ /* Main header file for the bfd library -- portable access to object files. Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. Contributed by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __BFD_H_SEEN__ #define __BFD_H_SEEN__ #ifdef __cplusplus extern "C" { #endif #include "ansidecl.h" #include "symcat.h" #if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE) #ifndef SABER /* This hack is to avoid a problem with some strict ANSI C preprocessors. The problem is, "32_" is not a valid preprocessing token, and we don't want extra underscores (e.g., "nlm_32_"). The XCONCAT2 macro will cause the inner CONCAT2 macros to be evaluated first, producing still-valid pp-tokens. Then the final concatenation can be done. */ #undef CONCAT4 #define CONCAT4(a,b,c,d) XCONCAT2(CONCAT2(a,b),CONCAT2(c,d)) #endif #endif /* This is a utility macro to handle the situation where the code wants to place a constant string into the code, followed by a comma and then the length of the string. Doing this by hand is error prone, so using this macro is safer. The macro will also safely handle the case where a NULL is passed as the arg. */ #define STRING_COMMA_LEN(STR) (STR), ((STR) ? sizeof (STR) - 1 : 0) /* Unfortunately it is not possible to use the STRING_COMMA_LEN macro to create the arguments to another macro, since the preprocessor will mis-count the number of arguments to the outer macro (by not evaluating STRING_COMMA_LEN and so missing the comma). This is a problem for example when trying to use STRING_COMMA_LEN to build the arguments to the strncmp() macro. Hence this alternative definition of strncmp is provided here. Note - these macros do NOT work if STR2 is not a constant string. */ #define CONST_STRNEQ(STR1,STR2) (strncmp ((STR1), (STR2), sizeof (STR2) - 1) == 0) /* strcpy() can have a similar problem, but since we know we are copying a constant string, we can use memcpy which will be faster since there is no need to check for a NUL byte inside STR. We can also save time if we do not need to copy the terminating NUL. */ #define LITMEMCPY(DEST,STR2) memcpy ((DEST), (STR2), sizeof (STR2) - 1) #define LITSTRCPY(DEST,STR2) memcpy ((DEST), (STR2), sizeof (STR2)) /* The word size used by BFD on the host. This may be 64 with a 32 bit target if the host is 64 bit, or if other 64 bit targets have been selected with --enable-targets, or if --enable-64-bit-bfd. */ #define BFD_ARCH_SIZE 64 #if defined(__i386__) || defined(__powerpc__) || defined(__arm__) || defined(__mips__) #define BFD_HOST_64BIT_LONG 0 #define BFD_HOST_64_BIT long long #define BFD_HOST_U_64_BIT unsigned long long #elif defined(__alpha__) || defined(__sparc64__) || defined(__amd64__) #define BFD_HOST_64BIT_LONG 1 #define BFD_HOST_64_BIT long #define BFD_HOST_U_64_BIT unsigned long #else #error Unsupported architecture/platform. #endif /* 64-bit host */ #define BFD_HOST_LONG_LONG 1 typedef BFD_HOST_64_BIT bfd_int64_t; typedef BFD_HOST_U_64_BIT bfd_uint64_t; #if BFD_ARCH_SIZE >= 64 #define BFD64 #endif #ifndef INLINE #if __GNUC__ >= 2 #define INLINE __inline__ #else #define INLINE #endif #endif /* Forward declaration. */ typedef struct bfd bfd; /* Boolean type used in bfd. Too many systems define their own versions of "boolean" for us to safely typedef a "boolean" of our own. Using an enum for "bfd_boolean" has its own set of problems, with strange looking casts required to avoid warnings on some older compilers. Thus we just use an int. General rule: Functions which are bfd_boolean return TRUE on success and FALSE on failure (unless they're a predicate). */ typedef int bfd_boolean; #undef FALSE #undef TRUE #define FALSE 0 #define TRUE 1 #ifdef BFD64 #ifndef BFD_HOST_64_BIT #error No 64 bit integer type available #endif /* ! defined (BFD_HOST_64_BIT) */ typedef BFD_HOST_U_64_BIT bfd_vma; typedef BFD_HOST_64_BIT bfd_signed_vma; typedef BFD_HOST_U_64_BIT bfd_size_type; typedef BFD_HOST_U_64_BIT symvalue; #ifndef fprintf_vma #if BFD_HOST_64BIT_LONG #define sprintf_vma(s,x) sprintf (s, "%016lx", x) #define fprintf_vma(f,x) fprintf (f, "%016lx", x) #else #define _bfd_int64_low(x) ((unsigned long) (((x) & 0xffffffff))) #define _bfd_int64_high(x) ((unsigned long) (((x) >> 32) & 0xffffffff)) #define fprintf_vma(s,x) \ fprintf ((s), "%08lx%08lx", _bfd_int64_high (x), _bfd_int64_low (x)) #define sprintf_vma(s,x) \ sprintf ((s), "%08lx%08lx", _bfd_int64_high (x), _bfd_int64_low (x)) #endif #endif #else /* not BFD64 */ /* Represent a target address. Also used as a generic unsigned type which is guaranteed to be big enough to hold any arithmetic types we need to deal with. */ typedef unsigned long bfd_vma; /* A generic signed type which is guaranteed to be big enough to hold any arithmetic types we need to deal with. Can be assumed to be compatible with bfd_vma in the same way that signed and unsigned ints are compatible (as parameters, in assignment, etc). */ typedef long bfd_signed_vma; typedef unsigned long symvalue; typedef unsigned long bfd_size_type; /* Print a bfd_vma x on stream s. */ #define fprintf_vma(s,x) fprintf (s, "%08lx", x) #define sprintf_vma(s,x) sprintf (s, "%08lx", x) #endif /* not BFD64 */ #define HALF_BFD_SIZE_TYPE \ (((bfd_size_type) 1) << (8 * sizeof (bfd_size_type) / 2)) #ifndef BFD_HOST_64_BIT /* Fall back on a 32 bit type. The idea is to make these types always available for function return types, but in the case that BFD_HOST_64_BIT is undefined such a function should abort or otherwise signal an error. */ typedef bfd_signed_vma bfd_int64_t; typedef bfd_vma bfd_uint64_t; #endif /* An offset into a file. BFD always uses the largest possible offset based on the build time availability of fseek, fseeko, or fseeko64. */ typedef BFD_HOST_64_BIT file_ptr; typedef unsigned BFD_HOST_64_BIT ufile_ptr; extern void bfd_sprintf_vma (bfd *, char *, bfd_vma); extern void bfd_fprintf_vma (bfd *, void *, bfd_vma); #define printf_vma(x) fprintf_vma(stdout,x) #define bfd_printf_vma(abfd,x) bfd_fprintf_vma (abfd,stdout,x) typedef unsigned int flagword; /* 32 bits of flags */ typedef unsigned char bfd_byte; /* File formats. */ typedef enum bfd_format { bfd_unknown = 0, /* File format is unknown. */ bfd_object, /* Linker/assembler/compiler output. */ bfd_archive, /* Object archive file. */ bfd_core, /* Core dump. */ bfd_type_end /* Marks the end; don't use it! */ } bfd_format; /* Values that may appear in the flags field of a BFD. These also appear in the object_flags field of the bfd_target structure, where they indicate the set of flags used by that backend (not all flags are meaningful for all object file formats) (FIXME: at the moment, the object_flags values have mostly just been copied from backend to another, and are not necessarily correct). */ /* No flags. */ #define BFD_NO_FLAGS 0x00 /* BFD contains relocation entries. */ #define HAS_RELOC 0x01 /* BFD is directly executable. */ #define EXEC_P 0x02 /* BFD has line number information (basically used for F_LNNO in a COFF header). */ #define HAS_LINENO 0x04 /* BFD has debugging information. */ #define HAS_DEBUG 0x08 /* BFD has symbols. */ #define HAS_SYMS 0x10 /* BFD has local symbols (basically used for F_LSYMS in a COFF header). */ #define HAS_LOCALS 0x20 /* BFD is a dynamic object. */ #define DYNAMIC 0x40 /* Text section is write protected (if D_PAGED is not set, this is like an a.out NMAGIC file) (the linker sets this by default, but clears it for -r or -N). */ #define WP_TEXT 0x80 /* BFD is dynamically paged (this is like an a.out ZMAGIC file) (the linker sets this by default, but clears it for -r or -n or -N). */ #define D_PAGED 0x100 /* BFD is relaxable (this means that bfd_relax_section may be able to do something) (sometimes bfd_relax_section can do something even if this is not set). */ #define BFD_IS_RELAXABLE 0x200 /* This may be set before writing out a BFD to request using a traditional format. For example, this is used to request that when writing out an a.out object the symbols not be hashed to eliminate duplicates. */ #define BFD_TRADITIONAL_FORMAT 0x400 /* This flag indicates that the BFD contents are actually cached in memory. If this is set, iostream points to a bfd_in_memory struct. */ #define BFD_IN_MEMORY 0x800 /* The sections in this BFD specify a memory page. */ #define HAS_LOAD_PAGE 0x1000 /* This BFD has been created by the linker and doesn't correspond to any input file. */ #define BFD_LINKER_CREATED 0x2000 /* Symbols and relocation. */ /* A count of carsyms (canonical archive symbols). */ typedef unsigned long symindex; /* How to perform a relocation. */ typedef const struct reloc_howto_struct reloc_howto_type; #define BFD_NO_MORE_SYMBOLS ((symindex) ~0) /* General purpose part of a symbol X; target specific parts are in libcoff.h, libaout.h, etc. */ #define bfd_get_section(x) ((x)->section) #define bfd_get_output_section(x) ((x)->section->output_section) #define bfd_set_section(x,y) ((x)->section) = (y) #define bfd_asymbol_base(x) ((x)->section->vma) #define bfd_asymbol_value(x) (bfd_asymbol_base(x) + (x)->value) #define bfd_asymbol_name(x) ((x)->name) /*Perhaps future: #define bfd_asymbol_bfd(x) ((x)->section->owner)*/ #define bfd_asymbol_bfd(x) ((x)->the_bfd) #define bfd_asymbol_flavour(x) (bfd_asymbol_bfd(x)->xvec->flavour) /* A canonical archive symbol. */ /* This is a type pun with struct ranlib on purpose! */ typedef struct carsym { char *name; file_ptr file_offset; /* Look here to find the file. */ } carsym; /* To make these you call a carsymogen. */ /* Used in generating armaps (archive tables of contents). Perhaps just a forward definition would do? */ struct orl /* Output ranlib. */ { char **name; /* Symbol name. */ union { file_ptr pos; bfd *abfd; } u; /* bfd* or file position. */ int namidx; /* Index into string table. */ }; /* Linenumber stuff. */ typedef struct lineno_cache_entry { unsigned int line_number; /* Linenumber from start of function. */ union { struct bfd_symbol *sym; /* Function name. */ bfd_vma offset; /* Offset into section. */ } u; } alent; /* Object and core file sections. */ #define align_power(addr, align) \ (((addr) + ((bfd_vma) 1 << (align)) - 1) & ((bfd_vma) -1 << (align))) typedef struct bfd_section *sec_ptr; #define bfd_get_section_name(bfd, ptr) ((ptr)->name + 0) #define bfd_get_section_vma(bfd, ptr) ((ptr)->vma + 0) #define bfd_get_section_lma(bfd, ptr) ((ptr)->lma + 0) #define bfd_get_section_alignment(bfd, ptr) ((ptr)->alignment_power + 0) #define bfd_section_name(bfd, ptr) ((ptr)->name) #define bfd_section_size(bfd, ptr) ((ptr)->size) #define bfd_get_section_size(ptr) ((ptr)->size) #define bfd_section_vma(bfd, ptr) ((ptr)->vma) #define bfd_section_lma(bfd, ptr) ((ptr)->lma) #define bfd_section_alignment(bfd, ptr) ((ptr)->alignment_power) #define bfd_get_section_flags(bfd, ptr) ((ptr)->flags + 0) #define bfd_get_section_userdata(bfd, ptr) ((ptr)->userdata) #define bfd_is_com_section(ptr) (((ptr)->flags & SEC_IS_COMMON) != 0) #define bfd_set_section_vma(bfd, ptr, val) (((ptr)->vma = (ptr)->lma = (val)), ((ptr)->user_set_vma = TRUE), TRUE) #define bfd_set_section_alignment(bfd, ptr, val) (((ptr)->alignment_power = (val)),TRUE) #define bfd_set_section_userdata(bfd, ptr, val) (((ptr)->userdata = (val)),TRUE) /* Find the address one past the end of SEC. */ #define bfd_get_section_limit(bfd, sec) \ (((sec)->rawsize ? (sec)->rawsize : (sec)->size) \ / bfd_octets_per_byte (bfd)) /* Return TRUE if section has been discarded. */ #define elf_discarded_section(sec) \ (!bfd_is_abs_section (sec) \ && bfd_is_abs_section ((sec)->output_section) \ && (sec)->sec_info_type != ELF_INFO_TYPE_MERGE \ && (sec)->sec_info_type != ELF_INFO_TYPE_JUST_SYMS) /* Forward define. */ struct stat; typedef enum bfd_print_symbol { bfd_print_symbol_name, bfd_print_symbol_more, bfd_print_symbol_all } bfd_print_symbol_type; /* Information about a symbol that nm needs. */ typedef struct _symbol_info { symvalue value; char type; const char *name; /* Symbol name. */ unsigned char stab_type; /* Stab type. */ char stab_other; /* Stab other. */ short stab_desc; /* Stab desc. */ const char *stab_name; /* String for stab type. */ } symbol_info; /* Get the name of a stabs type code. */ extern const char *bfd_get_stab_name (int); /* Hash table routines. There is no way to free up a hash table. */ /* An element in the hash table. Most uses will actually use a larger structure, and an instance of this will be the first field. */ struct bfd_hash_entry { /* Next entry for this hash code. */ struct bfd_hash_entry *next; /* String being hashed. */ const char *string; /* Hash code. This is the full hash code, not the index into the table. */ unsigned long hash; }; /* A hash table. */ struct bfd_hash_table { /* The hash array. */ struct bfd_hash_entry **table; /* A function used to create new elements in the hash table. The first entry is itself a pointer to an element. When this function is first invoked, this pointer will be NULL. However, having the pointer permits a hierarchy of method functions to be built each of which calls the function in the superclass. Thus each function should be written to allocate a new block of memory only if the argument is NULL. */ struct bfd_hash_entry *(*newfunc) (struct bfd_hash_entry *, struct bfd_hash_table *, const char *); /* An objalloc for this hash table. This is a struct objalloc *, but we use void * to avoid requiring the inclusion of objalloc.h. */ void *memory; /* The number of slots in the hash table. */ unsigned int size; /* The number of entries in the hash table. */ unsigned int count; /* The size of elements. */ unsigned int entsize; /* If non-zero, don't grow the hash table. */ unsigned int frozen:1; }; /* Initialize a hash table. */ 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 *), unsigned int); /* Initialize a hash table specifying a size. */ extern bfd_boolean bfd_hash_table_init_n (struct bfd_hash_table *, struct bfd_hash_entry *(*) (struct bfd_hash_entry *, struct bfd_hash_table *, const char *), unsigned int, unsigned int); /* Free up a hash table. */ extern void bfd_hash_table_free (struct bfd_hash_table *); /* Look up a string in a hash table. If CREATE is TRUE, a new entry will be created for this string if one does not already exist. The COPY argument must be TRUE if this routine should copy the string into newly allocated memory when adding an entry. */ extern struct bfd_hash_entry *bfd_hash_lookup (struct bfd_hash_table *, const char *, bfd_boolean create, bfd_boolean copy); /* Replace an entry in a hash table. */ extern void bfd_hash_replace (struct bfd_hash_table *, struct bfd_hash_entry *old, struct bfd_hash_entry *nw); /* Base method for creating a hash table entry. */ extern struct bfd_hash_entry *bfd_hash_newfunc (struct bfd_hash_entry *, struct bfd_hash_table *, const char *); /* Grab some space for a hash table entry. */ extern void *bfd_hash_allocate (struct bfd_hash_table *, unsigned int); /* Traverse a hash table in a random order, calling a function on each element. If the function returns FALSE, the traversal stops. The INFO argument is passed to the function. */ extern void bfd_hash_traverse (struct bfd_hash_table *, bfd_boolean (*) (struct bfd_hash_entry *, void *), void *info); /* Allows the default size of a hash table to be configured. New hash tables allocated using bfd_hash_table_init will be created with this size. */ extern void bfd_hash_set_default_size (bfd_size_type); /* This structure is used to keep track of stabs in sections information while linking. */ struct stab_info { /* A hash table used to hold stabs strings. */ struct bfd_strtab_hash *strings; /* The header file hash table. */ struct bfd_hash_table includes; /* The first .stabstr section. */ struct bfd_section *stabstr; }; #define COFF_SWAP_TABLE (void *) &bfd_coff_std_swap_table /* User program access to BFD facilities. */ /* Direct I/O routines, for programs which know more about the object file than BFD does. Use higher level routines if possible. */ extern bfd_size_type bfd_bread (void *, bfd_size_type, bfd *); extern bfd_size_type bfd_bwrite (const void *, bfd_size_type, bfd *); extern int bfd_seek (bfd *, file_ptr, int); extern file_ptr bfd_tell (bfd *); extern int bfd_flush (bfd *); extern int bfd_stat (bfd *, struct stat *); /* Deprecated old routines. */ #if __GNUC__ #define bfd_read(BUF, ELTSIZE, NITEMS, ABFD) \ (warn_deprecated ("bfd_read", __FILE__, __LINE__, __FUNCTION__), \ bfd_bread ((BUF), (ELTSIZE) * (NITEMS), (ABFD))) #define bfd_write(BUF, ELTSIZE, NITEMS, ABFD) \ (warn_deprecated ("bfd_write", __FILE__, __LINE__, __FUNCTION__), \ bfd_bwrite ((BUF), (ELTSIZE) * (NITEMS), (ABFD))) #else #define bfd_read(BUF, ELTSIZE, NITEMS, ABFD) \ (warn_deprecated ("bfd_read", (const char *) 0, 0, (const char *) 0), \ bfd_bread ((BUF), (ELTSIZE) * (NITEMS), (ABFD))) #define bfd_write(BUF, ELTSIZE, NITEMS, ABFD) \ (warn_deprecated ("bfd_write", (const char *) 0, 0, (const char *) 0),\ bfd_bwrite ((BUF), (ELTSIZE) * (NITEMS), (ABFD))) #endif extern void warn_deprecated (const char *, const char *, int, const char *); /* Cast from const char * to char * so that caller can assign to a char * without a warning. */ #define bfd_get_filename(abfd) ((char *) (abfd)->filename) #define bfd_get_cacheable(abfd) ((abfd)->cacheable) #define bfd_get_format(abfd) ((abfd)->format) #define bfd_get_target(abfd) ((abfd)->xvec->name) #define bfd_get_flavour(abfd) ((abfd)->xvec->flavour) #define bfd_family_coff(abfd) \ (bfd_get_flavour (abfd) == bfd_target_coff_flavour || \ bfd_get_flavour (abfd) == bfd_target_xcoff_flavour) #define bfd_big_endian(abfd) ((abfd)->xvec->byteorder == BFD_ENDIAN_BIG) #define bfd_little_endian(abfd) ((abfd)->xvec->byteorder == BFD_ENDIAN_LITTLE) #define bfd_header_big_endian(abfd) \ ((abfd)->xvec->header_byteorder == BFD_ENDIAN_BIG) #define bfd_header_little_endian(abfd) \ ((abfd)->xvec->header_byteorder == BFD_ENDIAN_LITTLE) #define bfd_get_file_flags(abfd) ((abfd)->flags) #define bfd_applicable_file_flags(abfd) ((abfd)->xvec->object_flags) #define bfd_applicable_section_flags(abfd) ((abfd)->xvec->section_flags) #define bfd_my_archive(abfd) ((abfd)->my_archive) #define bfd_has_map(abfd) ((abfd)->has_armap) #define bfd_valid_reloc_types(abfd) ((abfd)->xvec->valid_reloc_types) #define bfd_usrdata(abfd) ((abfd)->usrdata) #define bfd_get_start_address(abfd) ((abfd)->start_address) #define bfd_get_symcount(abfd) ((abfd)->symcount) #define bfd_get_outsymbols(abfd) ((abfd)->outsymbols) #define bfd_count_sections(abfd) ((abfd)->section_count) #define bfd_get_dynamic_symcount(abfd) ((abfd)->dynsymcount) #define bfd_get_symbol_leading_char(abfd) ((abfd)->xvec->symbol_leading_char) #define bfd_set_cacheable(abfd,bool) (((abfd)->cacheable = bool), TRUE) extern bfd_boolean bfd_cache_close (bfd *abfd); /* NB: This declaration should match the autogenerated one in libbfd.h. */ extern bfd_boolean bfd_cache_close_all (void); extern bfd_boolean bfd_record_phdr (bfd *, unsigned long, bfd_boolean, flagword, bfd_boolean, bfd_vma, bfd_boolean, bfd_boolean, unsigned int, struct bfd_section **); /* Byte swapping routines. */ bfd_uint64_t bfd_getb64 (const void *); bfd_uint64_t bfd_getl64 (const void *); bfd_int64_t bfd_getb_signed_64 (const void *); bfd_int64_t bfd_getl_signed_64 (const void *); bfd_vma bfd_getb32 (const void *); bfd_vma bfd_getl32 (const void *); bfd_signed_vma bfd_getb_signed_32 (const void *); bfd_signed_vma bfd_getl_signed_32 (const void *); bfd_vma bfd_getb16 (const void *); bfd_vma bfd_getl16 (const void *); bfd_signed_vma bfd_getb_signed_16 (const void *); bfd_signed_vma bfd_getl_signed_16 (const void *); void bfd_putb64 (bfd_uint64_t, void *); void bfd_putl64 (bfd_uint64_t, void *); void bfd_putb32 (bfd_vma, void *); void bfd_putl32 (bfd_vma, void *); void bfd_putb16 (bfd_vma, void *); void bfd_putl16 (bfd_vma, void *); /* Byte swapping routines which take size and endiannes as arguments. */ bfd_uint64_t bfd_get_bits (const void *, int, bfd_boolean); void bfd_put_bits (bfd_uint64_t, void *, int, bfd_boolean); extern bfd_boolean bfd_section_already_linked_table_init (void); extern void bfd_section_already_linked_table_free (void); /* Externally visible ECOFF routines. */ #if defined(__STDC__) || defined(ALMOST_STDC) struct ecoff_debug_info; struct ecoff_debug_swap; struct ecoff_extr; struct bfd_symbol; struct bfd_link_info; struct bfd_link_hash_entry; struct bfd_elf_version_tree; #endif extern bfd_vma bfd_ecoff_get_gp_value (bfd * abfd); extern bfd_boolean bfd_ecoff_set_gp_value (bfd *abfd, bfd_vma gp_value); extern bfd_boolean bfd_ecoff_set_regmasks (bfd *abfd, unsigned long gprmask, unsigned long fprmask, unsigned long *cprmask); extern void *bfd_ecoff_debug_init (bfd *output_bfd, struct ecoff_debug_info *output_debug, const struct ecoff_debug_swap *output_swap, struct bfd_link_info *); extern void bfd_ecoff_debug_free (void *handle, bfd *output_bfd, struct ecoff_debug_info *output_debug, const struct ecoff_debug_swap *output_swap, struct bfd_link_info *); extern bfd_boolean bfd_ecoff_debug_accumulate (void *handle, bfd *output_bfd, struct ecoff_debug_info *output_debug, const struct ecoff_debug_swap *output_swap, bfd *input_bfd, struct ecoff_debug_info *input_debug, const struct ecoff_debug_swap *input_swap, struct bfd_link_info *); extern bfd_boolean bfd_ecoff_debug_accumulate_other (void *handle, bfd *output_bfd, struct ecoff_debug_info *output_debug, const struct ecoff_debug_swap *output_swap, bfd *input_bfd, struct bfd_link_info *); extern bfd_boolean bfd_ecoff_debug_externals (bfd *abfd, struct ecoff_debug_info *debug, const struct ecoff_debug_swap *swap, bfd_boolean relocatable, bfd_boolean (*get_extr) (struct bfd_symbol *, struct ecoff_extr *), void (*set_index) (struct bfd_symbol *, bfd_size_type)); extern bfd_boolean bfd_ecoff_debug_one_external (bfd *abfd, struct ecoff_debug_info *debug, const struct ecoff_debug_swap *swap, const char *name, struct ecoff_extr *esym); extern bfd_size_type bfd_ecoff_debug_size (bfd *abfd, struct ecoff_debug_info *debug, const struct ecoff_debug_swap *swap); extern bfd_boolean bfd_ecoff_write_debug (bfd *abfd, struct ecoff_debug_info *debug, const struct ecoff_debug_swap *swap, file_ptr where); extern bfd_boolean bfd_ecoff_write_accumulated_debug (void *handle, bfd *abfd, struct ecoff_debug_info *debug, const struct ecoff_debug_swap *swap, struct bfd_link_info *info, file_ptr where); /* Externally visible ELF routines. */ struct bfd_link_needed_list { struct bfd_link_needed_list *next; bfd *by; const char *name; }; enum dynamic_lib_link_class { DYN_NORMAL = 0, DYN_AS_NEEDED = 1, DYN_DT_NEEDED = 2, DYN_NO_ADD_NEEDED = 4, DYN_NO_NEEDED = 8 }; enum notice_asneeded_action { notice_as_needed, notice_not_needed, notice_needed }; extern bfd_boolean bfd_elf_record_link_assignment (bfd *, struct bfd_link_info *, const char *, bfd_boolean, bfd_boolean); extern struct bfd_link_needed_list *bfd_elf_get_needed_list (bfd *, struct bfd_link_info *); extern bfd_boolean bfd_elf_get_bfd_needed_list (bfd *, struct bfd_link_needed_list **); extern bfd_boolean bfd_elf_size_dynamic_sections (bfd *, const char *, const char *, const char *, const char * const *, struct bfd_link_info *, struct bfd_section **, struct bfd_elf_version_tree *); extern bfd_boolean bfd_elf_size_dynsym_hash_dynstr (bfd *, struct bfd_link_info *); extern void bfd_elf_set_dt_needed_name (bfd *, const char *); extern const char *bfd_elf_get_dt_soname (bfd *); extern void bfd_elf_set_dyn_lib_class (bfd *, enum dynamic_lib_link_class); extern int bfd_elf_get_dyn_lib_class (bfd *); extern struct bfd_link_needed_list *bfd_elf_get_runpath_list (bfd *, struct bfd_link_info *); extern bfd_boolean bfd_elf_discard_info (bfd *, struct bfd_link_info *); extern unsigned int _bfd_elf_default_action_discarded (struct bfd_section *); /* Return an upper bound on the number of bytes required to store a copy of ABFD's program header table entries. Return -1 if an error occurs; bfd_get_error will return an appropriate code. */ extern long bfd_get_elf_phdr_upper_bound (bfd *abfd); /* Copy ABFD's program header table entries to *PHDRS. The entries will be stored as an array of Elf_Internal_Phdr structures, as defined in include/elf/internal.h. To find out how large the buffer needs to be, call bfd_get_elf_phdr_upper_bound. Return the number of program header table entries read, or -1 if an error occurs; bfd_get_error will return an appropriate code. */ extern int bfd_get_elf_phdrs (bfd *abfd, void *phdrs); /* Create a new BFD as if by bfd_openr. Rather than opening a file, reconstruct an ELF file by reading the segments out of remote memory based on the ELF file header at EHDR_VMA and the ELF program headers it points to. If not null, *LOADBASEP is filled in with the difference between the VMAs from which the segments were read, and the VMAs the file headers (and hence BFD's idea of each section's VMA) put them at. The function TARGET_READ_MEMORY is called to copy LEN bytes from the remote memory at target address VMA into the local buffer at MYADDR; it should return zero on success or an `errno' code on failure. TEMPL must be a BFD for an ELF target with the word size and byte order found in the remote memory. */ extern bfd *bfd_elf_bfd_from_remote_memory (bfd *templ, bfd_vma ehdr_vma, bfd_vma *loadbasep, int (*target_read_memory) (bfd_vma vma, bfd_byte *myaddr, int len)); /* Return the arch_size field of an elf bfd, or -1 if not elf. */ extern int bfd_get_arch_size (bfd *); /* Return TRUE if address "naturally" sign extends, or -1 if not elf. */ extern int bfd_get_sign_extend_vma (bfd *); extern struct bfd_section *_bfd_elf_tls_setup (bfd *, struct bfd_link_info *); extern void _bfd_fix_excluded_sec_syms (bfd *, struct bfd_link_info *); extern unsigned bfd_m68k_mach_to_features (int); extern int bfd_m68k_features_to_mach (unsigned); extern bfd_boolean bfd_m68k_elf32_create_embedded_relocs (bfd *, struct bfd_link_info *, struct bfd_section *, struct bfd_section *, char **); extern bfd_boolean bfd_bfin_elf32_create_embedded_relocs (bfd *, struct bfd_link_info *, struct bfd_section *, struct bfd_section *, char **); /* SunOS shared library support routines for the linker. */ extern struct bfd_link_needed_list *bfd_sunos_get_needed_list (bfd *, struct bfd_link_info *); extern bfd_boolean bfd_sunos_record_link_assignment (bfd *, struct bfd_link_info *, const char *); extern bfd_boolean bfd_sunos_size_dynamic_sections (bfd *, struct bfd_link_info *, struct bfd_section **, struct bfd_section **, struct bfd_section **); /* Linux shared library support routines for the linker. */ extern bfd_boolean bfd_i386linux_size_dynamic_sections (bfd *, struct bfd_link_info *); extern bfd_boolean bfd_m68klinux_size_dynamic_sections (bfd *, struct bfd_link_info *); extern bfd_boolean bfd_sparclinux_size_dynamic_sections (bfd *, struct bfd_link_info *); /* mmap hacks */ struct _bfd_window_internal; typedef struct _bfd_window_internal bfd_window_internal; typedef struct _bfd_window { /* What the user asked for. */ void *data; bfd_size_type size; /* The actual window used by BFD. Small user-requested read-only regions sharing a page may share a single window into the object file. Read-write versions shouldn't until I've fixed things to keep track of which portions have been claimed by the application; don't want to give the same region back when the application wants two writable copies! */ struct _bfd_window_internal *i; } bfd_window; extern void bfd_init_window (bfd_window *); extern void bfd_free_window (bfd_window *); extern bfd_boolean bfd_get_file_window (bfd *, file_ptr, bfd_size_type, bfd_window *, bfd_boolean); /* XCOFF support routines for the linker. */ extern bfd_boolean bfd_xcoff_link_record_set (bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *, bfd_size_type); extern bfd_boolean bfd_xcoff_import_symbol (bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *, bfd_vma, const char *, const char *, const char *, unsigned int); extern bfd_boolean bfd_xcoff_export_symbol (bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *); extern bfd_boolean bfd_xcoff_link_count_reloc (bfd *, struct bfd_link_info *, const char *); extern bfd_boolean bfd_xcoff_record_link_assignment (bfd *, struct bfd_link_info *, const char *); extern bfd_boolean bfd_xcoff_size_dynamic_sections (bfd *, struct bfd_link_info *, const char *, const char *, unsigned long, unsigned long, unsigned long, bfd_boolean, int, bfd_boolean, bfd_boolean, struct bfd_section **, bfd_boolean); extern bfd_boolean bfd_xcoff_link_generate_rtinit (bfd *, const char *, const char *, bfd_boolean); /* XCOFF support routines for ar. */ extern bfd_boolean bfd_xcoff_ar_archive_set_magic (bfd *, char *); /* Externally visible COFF routines. */ #if defined(__STDC__) || defined(ALMOST_STDC) struct internal_syment; union internal_auxent; #endif extern bfd_boolean bfd_coff_get_syment (bfd *, struct bfd_symbol *, struct internal_syment *); extern bfd_boolean bfd_coff_get_auxent (bfd *, struct bfd_symbol *, int, union internal_auxent *); extern bfd_boolean bfd_coff_set_symbol_class (bfd *, struct bfd_symbol *, unsigned int); extern bfd_boolean bfd_m68k_coff_create_embedded_relocs (bfd *, struct bfd_link_info *, struct bfd_section *, struct bfd_section *, char **); /* ARM VFP11 erratum workaround support. */ typedef enum { BFD_ARM_VFP11_FIX_DEFAULT, BFD_ARM_VFP11_FIX_NONE, BFD_ARM_VFP11_FIX_SCALAR, BFD_ARM_VFP11_FIX_VECTOR } bfd_arm_vfp11_fix; extern void bfd_elf32_arm_init_maps (bfd *); extern void bfd_elf32_arm_set_vfp11_fix (bfd *, struct bfd_link_info *); extern bfd_boolean bfd_elf32_arm_vfp11_erratum_scan (bfd *, struct bfd_link_info *); extern void bfd_elf32_arm_vfp11_fix_veneer_locations (bfd *, struct bfd_link_info *); /* ARM Interworking support. Called from linker. */ extern bfd_boolean bfd_arm_allocate_interworking_sections (struct bfd_link_info *); extern bfd_boolean bfd_arm_process_before_allocation (bfd *, struct bfd_link_info *, int); extern bfd_boolean bfd_arm_get_bfd_for_interworking (bfd *, struct bfd_link_info *); /* PE ARM Interworking support. Called from linker. */ extern bfd_boolean bfd_arm_pe_allocate_interworking_sections (struct bfd_link_info *); extern bfd_boolean bfd_arm_pe_process_before_allocation (bfd *, struct bfd_link_info *, int); extern bfd_boolean bfd_arm_pe_get_bfd_for_interworking (bfd *, struct bfd_link_info *); /* ELF ARM Interworking support. Called from linker. */ extern bfd_boolean bfd_elf32_arm_allocate_interworking_sections (struct bfd_link_info *); extern bfd_boolean bfd_elf32_arm_process_before_allocation (bfd *, struct bfd_link_info *); void bfd_elf32_arm_set_target_relocs (bfd *, struct bfd_link_info *, int, char *, int, int, bfd_arm_vfp11_fix, int, int); extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking (bfd *, struct bfd_link_info *); extern bfd_boolean bfd_elf32_arm_add_glue_sections_to_bfd (bfd *, struct bfd_link_info *); /* ELF ARM mapping symbol support */ #define BFD_ARM_SPECIAL_SYM_TYPE_MAP (1 << 0) #define BFD_ARM_SPECIAL_SYM_TYPE_TAG (1 << 1) #define BFD_ARM_SPECIAL_SYM_TYPE_OTHER (1 << 2) #define BFD_ARM_SPECIAL_SYM_TYPE_ANY (~0) extern bfd_boolean bfd_is_arm_special_symbol_name (const char * name, int type); extern void bfd_elf32_arm_set_byteswap_code (struct bfd_link_info *, int); /* ARM Note section processing. */ extern bfd_boolean bfd_arm_merge_machines (bfd *, bfd *); extern bfd_boolean bfd_arm_update_notes (bfd *, const char *); extern unsigned int bfd_arm_get_mach_from_notes (bfd *, const char *); /* TI COFF load page support. */ extern void bfd_ticoff_set_section_load_page (struct bfd_section *, int); extern int bfd_ticoff_get_section_load_page (struct bfd_section *); /* H8/300 functions. */ extern bfd_vma bfd_h8300_pad_address (bfd *, bfd_vma); /* IA64 Itanium code generation. Called from linker. */ extern void bfd_elf32_ia64_after_parse (int); extern void bfd_elf64_ia64_after_parse (int); /* This structure is used for a comdat section, as in PE. A comdat section is associated with a particular symbol. When the linker sees a comdat section, it keeps only one of the sections with a given name and associated with a given symbol. */ struct coff_comdat_info { /* The name of the symbol associated with a comdat section. */ const char *name; /* The local symbol table index of the symbol associated with a comdat section. This is only meaningful to the object file format specific code; it is not an index into the list returned by bfd_canonicalize_symtab. */ long symbol; }; extern struct coff_comdat_info *bfd_coff_get_comdat_section (bfd *, struct bfd_section *); /* Extracted from init.c. */ void bfd_init (void); /* Extracted from opncls.c. */ bfd *bfd_fopen (const char *filename, const char *target, const char *mode, int fd); bfd *bfd_openr (const char *filename, const char *target); bfd *bfd_fdopenr (const char *filename, const char *target, int fd); bfd *bfd_openstreamr (const char *, const char *, void *); bfd *bfd_openr_iovec (const char *filename, const char *target, void *(*open) (struct bfd *nbfd, void *open_closure), void *open_closure, file_ptr (*pread) (struct bfd *nbfd, void *stream, void *buf, file_ptr nbytes, file_ptr offset), int (*close) (struct bfd *nbfd, void *stream), int (*stat) (struct bfd *abfd, void *stream, struct stat *sb)); bfd *bfd_openw (const char *filename, const char *target); bfd_boolean bfd_close (bfd *abfd); bfd_boolean bfd_close_all_done (bfd *); bfd *bfd_create (const char *filename, bfd *templ); bfd_boolean bfd_make_writable (bfd *abfd); bfd_boolean bfd_make_readable (bfd *abfd); unsigned long bfd_calc_gnu_debuglink_crc32 (unsigned long crc, const unsigned char *buf, bfd_size_type len); char *bfd_follow_gnu_debuglink (bfd *abfd, const char *dir); struct bfd_section *bfd_create_gnu_debuglink_section (bfd *abfd, const char *filename); bfd_boolean bfd_fill_in_gnu_debuglink_section (bfd *abfd, struct bfd_section *sect, const char *filename); /* Extracted from libbfd.c. */ /* Byte swapping macros for user section data. */ #define bfd_put_8(abfd, val, ptr) \ ((void) (*((unsigned char *) (ptr)) = (val) & 0xff)) #define bfd_put_signed_8 \ bfd_put_8 #define bfd_get_8(abfd, ptr) \ (*(unsigned char *) (ptr) & 0xff) #define bfd_get_signed_8(abfd, ptr) \ (((*(unsigned char *) (ptr) & 0xff) ^ 0x80) - 0x80) #define bfd_put_16(abfd, val, ptr) \ BFD_SEND (abfd, bfd_putx16, ((val),(ptr))) #define bfd_put_signed_16 \ bfd_put_16 #define bfd_get_16(abfd, ptr) \ BFD_SEND (abfd, bfd_getx16, (ptr)) #define bfd_get_signed_16(abfd, ptr) \ BFD_SEND (abfd, bfd_getx_signed_16, (ptr)) #define bfd_put_32(abfd, val, ptr) \ BFD_SEND (abfd, bfd_putx32, ((val),(ptr))) #define bfd_put_signed_32 \ bfd_put_32 #define bfd_get_32(abfd, ptr) \ BFD_SEND (abfd, bfd_getx32, (ptr)) #define bfd_get_signed_32(abfd, ptr) \ BFD_SEND (abfd, bfd_getx_signed_32, (ptr)) #define bfd_put_64(abfd, val, ptr) \ BFD_SEND (abfd, bfd_putx64, ((val), (ptr))) #define bfd_put_signed_64 \ bfd_put_64 #define bfd_get_64(abfd, ptr) \ BFD_SEND (abfd, bfd_getx64, (ptr)) #define bfd_get_signed_64(abfd, ptr) \ BFD_SEND (abfd, bfd_getx_signed_64, (ptr)) #define bfd_get(bits, abfd, ptr) \ ((bits) == 8 ? (bfd_vma) bfd_get_8 (abfd, ptr) \ : (bits) == 16 ? bfd_get_16 (abfd, ptr) \ : (bits) == 32 ? bfd_get_32 (abfd, ptr) \ : (bits) == 64 ? bfd_get_64 (abfd, ptr) \ : (abort (), (bfd_vma) - 1)) #define bfd_put(bits, abfd, val, ptr) \ ((bits) == 8 ? bfd_put_8 (abfd, val, ptr) \ : (bits) == 16 ? bfd_put_16 (abfd, val, ptr) \ : (bits) == 32 ? bfd_put_32 (abfd, val, ptr) \ : (bits) == 64 ? bfd_put_64 (abfd, val, ptr) \ : (abort (), (void) 0)) /* Byte swapping macros for file header data. */ #define bfd_h_put_8(abfd, val, ptr) \ bfd_put_8 (abfd, val, ptr) #define bfd_h_put_signed_8(abfd, val, ptr) \ bfd_put_8 (abfd, val, ptr) #define bfd_h_get_8(abfd, ptr) \ bfd_get_8 (abfd, ptr) #define bfd_h_get_signed_8(abfd, ptr) \ bfd_get_signed_8 (abfd, ptr) #define bfd_h_put_16(abfd, val, ptr) \ BFD_SEND (abfd, bfd_h_putx16, (val, ptr)) #define bfd_h_put_signed_16 \ bfd_h_put_16 #define bfd_h_get_16(abfd, ptr) \ BFD_SEND (abfd, bfd_h_getx16, (ptr)) #define bfd_h_get_signed_16(abfd, ptr) \ BFD_SEND (abfd, bfd_h_getx_signed_16, (ptr)) #define bfd_h_put_32(abfd, val, ptr) \ BFD_SEND (abfd, bfd_h_putx32, (val, ptr)) #define bfd_h_put_signed_32 \ bfd_h_put_32 #define bfd_h_get_32(abfd, ptr) \ BFD_SEND (abfd, bfd_h_getx32, (ptr)) #define bfd_h_get_signed_32(abfd, ptr) \ BFD_SEND (abfd, bfd_h_getx_signed_32, (ptr)) #define bfd_h_put_64(abfd, val, ptr) \ BFD_SEND (abfd, bfd_h_putx64, (val, ptr)) #define bfd_h_put_signed_64 \ bfd_h_put_64 #define bfd_h_get_64(abfd, ptr) \ BFD_SEND (abfd, bfd_h_getx64, (ptr)) #define bfd_h_get_signed_64(abfd, ptr) \ BFD_SEND (abfd, bfd_h_getx_signed_64, (ptr)) /* Aliases for the above, which should eventually go away. */ #define H_PUT_64 bfd_h_put_64 #define H_PUT_32 bfd_h_put_32 #define H_PUT_16 bfd_h_put_16 #define H_PUT_8 bfd_h_put_8 #define H_PUT_S64 bfd_h_put_signed_64 #define H_PUT_S32 bfd_h_put_signed_32 #define H_PUT_S16 bfd_h_put_signed_16 #define H_PUT_S8 bfd_h_put_signed_8 #define H_GET_64 bfd_h_get_64 #define H_GET_32 bfd_h_get_32 #define H_GET_16 bfd_h_get_16 #define H_GET_8 bfd_h_get_8 #define H_GET_S64 bfd_h_get_signed_64 #define H_GET_S32 bfd_h_get_signed_32 #define H_GET_S16 bfd_h_get_signed_16 #define H_GET_S8 bfd_h_get_signed_8 /* Extracted from bfdio.c. */ long bfd_get_mtime (bfd *abfd); file_ptr bfd_get_size (bfd *abfd); /* Extracted from bfdwin.c. */ /* Extracted from section.c. */ typedef struct bfd_section { /* The name of the section; the name isn't a copy, the pointer is the same as that passed to bfd_make_section. */ const char *name; /* A unique sequence number. */ int id; /* Which section in the bfd; 0..n-1 as sections are created in a bfd. */ int index; /* The next section in the list belonging to the BFD, or NULL. */ struct bfd_section *next; /* The previous section in the list belonging to the BFD, or NULL. */ struct bfd_section *prev; /* The field flags contains attributes of the section. Some flags are read in from the object file, and some are synthesized from other information. */ flagword flags; #define SEC_NO_FLAGS 0x000 /* Tells the OS to allocate space for this section when loading. This is clear for a section containing debug information only. */ #define SEC_ALLOC 0x001 /* Tells the OS to load the section from the file when loading. This is clear for a .bss section. */ #define SEC_LOAD 0x002 /* The section contains data still to be relocated, so there is some relocation information too. */ #define SEC_RELOC 0x004 /* A signal to the OS that the section contains read only data. */ #define SEC_READONLY 0x008 /* The section contains code only. */ #define SEC_CODE 0x010 /* The section contains data only. */ #define SEC_DATA 0x020 /* The section will reside in ROM. */ #define SEC_ROM 0x040 /* The section contains constructor information. This section type is used by the linker to create lists of constructors and destructors used by <>. When a back end sees a symbol which should be used in a constructor list, it creates a new section for the type of name (e.g., <<__CTOR_LIST__>>), attaches the symbol to it, and builds a relocation. To build the lists of constructors, all the linker has to do is catenate all the sections called <<__CTOR_LIST__>> and relocate the data contained within - exactly the operations it would peform on standard data. */ #define SEC_CONSTRUCTOR 0x080 /* The section has contents - a data section could be <> | <>; a debug section could be <> */ #define SEC_HAS_CONTENTS 0x100 /* An instruction to the linker to not output the section even if it has information which would normally be written. */ #define SEC_NEVER_LOAD 0x200 /* The section contains thread local data. */ #define SEC_THREAD_LOCAL 0x400 /* The section has GOT references. This flag is only for the linker, and is currently only used by the elf32-hppa back end. It will be set if global offset table references were detected in this section, which indicate to the linker that the section contains PIC code, and must be handled specially when doing a static link. */ #define SEC_HAS_GOT_REF 0x800 /* The section contains common symbols (symbols may be defined multiple times, the value of a symbol is the amount of space it requires, and the largest symbol value is the one used). Most targets have exactly one of these (which we translate to bfd_com_section_ptr), but ECOFF has two. */ #define SEC_IS_COMMON 0x1000 /* The section contains only debugging information. For example, this is set for ELF .debug and .stab sections. strip tests this flag to see if a section can be discarded. */ #define SEC_DEBUGGING 0x2000 /* The contents of this section are held in memory pointed to by the contents field. This is checked by bfd_get_section_contents, and the data is retrieved from memory if appropriate. */ #define SEC_IN_MEMORY 0x4000 /* The contents of this section are to be excluded by the linker for executable and shared objects unless those objects are to be further relocated. */ #define SEC_EXCLUDE 0x8000 /* The contents of this section are to be sorted based on the sum of the symbol and addend values specified by the associated relocation entries. Entries without associated relocation entries will be appended to the end of the section in an unspecified order. */ #define SEC_SORT_ENTRIES 0x10000 /* When linking, duplicate sections of the same name should be discarded, rather than being combined into a single section as is usually done. This is similar to how common symbols are handled. See SEC_LINK_DUPLICATES below. */ #define SEC_LINK_ONCE 0x20000 /* If SEC_LINK_ONCE is set, this bitfield describes how the linker should handle duplicate sections. */ #define SEC_LINK_DUPLICATES 0x40000 /* This value for SEC_LINK_DUPLICATES means that duplicate sections with the same name should simply be discarded. */ #define SEC_LINK_DUPLICATES_DISCARD 0x0 /* This value for SEC_LINK_DUPLICATES means that the linker should warn if there are any duplicate sections, although it should still only link one copy. */ #define SEC_LINK_DUPLICATES_ONE_ONLY 0x80000 /* This value for SEC_LINK_DUPLICATES means that the linker should warn if any duplicate sections are a different size. */ #define SEC_LINK_DUPLICATES_SAME_SIZE 0x100000 /* This value for SEC_LINK_DUPLICATES means that the linker should warn if any duplicate sections contain different contents. */ #define SEC_LINK_DUPLICATES_SAME_CONTENTS \ (SEC_LINK_DUPLICATES_ONE_ONLY | SEC_LINK_DUPLICATES_SAME_SIZE) /* This section was created by the linker as part of dynamic relocation or other arcane processing. It is skipped when going through the first-pass output, trusting that someone else up the line will take care of it later. */ #define SEC_LINKER_CREATED 0x200000 /* This section should not be subject to garbage collection. Also set to inform the linker that this section should not be listed in the link map as discarded. */ #define SEC_KEEP 0x400000 /* This section contains "short" data, and should be placed "near" the GP. */ #define SEC_SMALL_DATA 0x800000 /* Attempt to merge identical entities in the section. Entity size is given in the entsize field. */ #define SEC_MERGE 0x1000000 /* If given with SEC_MERGE, entities to merge are zero terminated strings where entsize specifies character size instead of fixed size entries. */ #define SEC_STRINGS 0x2000000 /* This section contains data about section groups. */ #define SEC_GROUP 0x4000000 /* The section is a COFF shared library section. This flag is only for the linker. If this type of section appears in the input file, the linker must copy it to the output file without changing the vma or size. FIXME: Although this was originally intended to be general, it really is COFF specific (and the flag was renamed to indicate this). It might be cleaner to have some more general mechanism to allow the back end to control what the linker does with sections. */ #define SEC_COFF_SHARED_LIBRARY 0x10000000 /* This section contains data which may be shared with other executables or shared objects. This is for COFF only. */ #define SEC_COFF_SHARED 0x20000000 /* When a section with this flag is being linked, then if the size of the input section is less than a page, it should not cross a page boundary. If the size of the input section is one page or more, it should be aligned on a page boundary. This is for TI TMS320C54X only. */ #define SEC_TIC54X_BLOCK 0x40000000 /* Conditionally link this section; do not link if there are no references found to any symbol in the section. This is for TI TMS320C54X only. */ #define SEC_TIC54X_CLINK 0x80000000 /* End of section flags. */ /* Some internal packed boolean fields. */ /* See the vma field. */ unsigned int user_set_vma : 1; /* A mark flag used by some of the linker backends. */ unsigned int linker_mark : 1; /* Another mark flag used by some of the linker backends. Set for output sections that have an input section. */ unsigned int linker_has_input : 1; /* Mark flags used by some linker backends for garbage collection. */ unsigned int gc_mark : 1; unsigned int gc_mark_from_eh : 1; /* The following flags are used by the ELF linker. */ /* Mark sections which have been allocated to segments. */ unsigned int segment_mark : 1; /* Type of sec_info information. */ unsigned int sec_info_type:3; #define ELF_INFO_TYPE_NONE 0 #define ELF_INFO_TYPE_STABS 1 #define ELF_INFO_TYPE_MERGE 2 #define ELF_INFO_TYPE_EH_FRAME 3 #define ELF_INFO_TYPE_JUST_SYMS 4 /* Nonzero if this section uses RELA relocations, rather than REL. */ unsigned int use_rela_p:1; /* Bits used by various backends. The generic code doesn't touch these fields. */ /* Nonzero if this section has TLS related relocations. */ unsigned int has_tls_reloc:1; + /* Nonzero if this section has a call to __tls_get_addr. */ + unsigned int has_tls_get_addr_call:1; + /* Nonzero if this section has a gp reloc. */ unsigned int has_gp_reloc:1; /* Nonzero if this section needs the relax finalize pass. */ unsigned int need_finalize_relax:1; /* Whether relocations have been processed. */ unsigned int reloc_done : 1; /* End of internal packed boolean fields. */ /* The virtual memory address of the section - where it will be at run time. The symbols are relocated against this. The user_set_vma flag is maintained by bfd; if it's not set, the backend can assign addresses (for example, in <>, where the default address for <<.data>> is dependent on the specific target and various flags). */ bfd_vma vma; /* The load address of the section - where it would be in a rom image; really only used for writing section header information. */ bfd_vma lma; /* The size of the section in octets, as it will be output. Contains a value even if the section has no contents (e.g., the size of <<.bss>>). */ bfd_size_type size; /* For input sections, the original size on disk of the section, in octets. This field is used by the linker relaxation code. It is currently only set for sections where the linker relaxation scheme doesn't cache altered section and reloc contents (stabs, eh_frame, SEC_MERGE, some coff relaxing targets), and thus the original size needs to be kept to read the section multiple times. For output sections, rawsize holds the section size calculated on a previous linker relaxation pass. */ bfd_size_type rawsize; /* If this section is going to be output, then this value is the offset in *bytes* into the output section of the first byte in the input section (byte ==> smallest addressable unit on the target). In most cases, if this was going to start at the 100th octet (8-bit quantity) in the output section, this value would be 100. However, if the target byte size is 16 bits (bfd_octets_per_byte is "2"), this value would be 50. */ bfd_vma output_offset; /* The output section through which to map on output. */ struct bfd_section *output_section; /* The alignment requirement of the section, as an exponent of 2 - e.g., 3 aligns to 2^3 (or 8). */ unsigned int alignment_power; /* If an input section, a pointer to a vector of relocation records for the data in this section. */ struct reloc_cache_entry *relocation; /* If an output section, a pointer to a vector of pointers to relocation records for the data in this section. */ struct reloc_cache_entry **orelocation; /* The number of relocation records in one of the above. */ unsigned reloc_count; /* Information below is back end specific - and not always used or updated. */ /* File position of section data. */ file_ptr filepos; /* File position of relocation info. */ file_ptr rel_filepos; /* File position of line data. */ file_ptr line_filepos; /* Pointer to data for applications. */ void *userdata; /* If the SEC_IN_MEMORY flag is set, this points to the actual contents. */ unsigned char *contents; /* Attached line number information. */ alent *lineno; /* Number of line number records. */ unsigned int lineno_count; /* Entity size for merging purposes. */ unsigned int entsize; /* Points to the kept section if this section is a link-once section, and is discarded. */ struct bfd_section *kept_section; /* When a section is being output, this value changes as more linenumbers are written out. */ file_ptr moving_line_filepos; /* What the section number is in the target world. */ int target_index; void *used_by_bfd; /* If this is a constructor section then here is a list of the relocations created to relocate items within it. */ struct relent_chain *constructor_chain; /* The BFD which owns the section. */ bfd *owner; /* A symbol which points at this section only. */ struct bfd_symbol *symbol; struct bfd_symbol **symbol_ptr_ptr; /* Early in the link process, map_head and map_tail are used to build a list of input sections attached to an output section. Later, output sections use these fields for a list of bfd_link_order structs. */ union { struct bfd_link_order *link_order; struct bfd_section *s; } map_head, map_tail; } asection; /* These sections are global, and are managed by BFD. The application and target back end are not permitted to change the values in these sections. New code should use the section_ptr macros rather than referring directly to the const sections. The const sections may eventually vanish. */ #define BFD_ABS_SECTION_NAME "*ABS*" #define BFD_UND_SECTION_NAME "*UND*" #define BFD_COM_SECTION_NAME "*COM*" #define BFD_IND_SECTION_NAME "*IND*" /* The absolute section. */ extern asection bfd_abs_section; #define bfd_abs_section_ptr ((asection *) &bfd_abs_section) #define bfd_is_abs_section(sec) ((sec) == bfd_abs_section_ptr) /* Pointer to the undefined section. */ extern asection bfd_und_section; #define bfd_und_section_ptr ((asection *) &bfd_und_section) #define bfd_is_und_section(sec) ((sec) == bfd_und_section_ptr) /* Pointer to the common section. */ extern asection bfd_com_section; #define bfd_com_section_ptr ((asection *) &bfd_com_section) /* Pointer to the indirect section. */ extern asection bfd_ind_section; #define bfd_ind_section_ptr ((asection *) &bfd_ind_section) #define bfd_is_ind_section(sec) ((sec) == bfd_ind_section_ptr) #define bfd_is_const_section(SEC) \ ( ((SEC) == bfd_abs_section_ptr) \ || ((SEC) == bfd_und_section_ptr) \ || ((SEC) == bfd_com_section_ptr) \ || ((SEC) == bfd_ind_section_ptr)) /* Macros to handle insertion and deletion of a bfd's sections. These only handle the list pointers, ie. do not adjust section_count, target_index etc. */ #define bfd_section_list_remove(ABFD, S) \ do \ { \ asection *_s = S; \ asection *_next = _s->next; \ asection *_prev = _s->prev; \ if (_prev) \ _prev->next = _next; \ else \ (ABFD)->sections = _next; \ if (_next) \ _next->prev = _prev; \ else \ (ABFD)->section_last = _prev; \ } \ while (0) #define bfd_section_list_append(ABFD, S) \ do \ { \ asection *_s = S; \ bfd *_abfd = ABFD; \ _s->next = NULL; \ if (_abfd->section_last) \ { \ _s->prev = _abfd->section_last; \ _abfd->section_last->next = _s; \ } \ else \ { \ _s->prev = NULL; \ _abfd->sections = _s; \ } \ _abfd->section_last = _s; \ } \ while (0) #define bfd_section_list_prepend(ABFD, S) \ do \ { \ asection *_s = S; \ bfd *_abfd = ABFD; \ _s->prev = NULL; \ if (_abfd->sections) \ { \ _s->next = _abfd->sections; \ _abfd->sections->prev = _s; \ } \ else \ { \ _s->next = NULL; \ _abfd->section_last = _s; \ } \ _abfd->sections = _s; \ } \ while (0) #define bfd_section_list_insert_after(ABFD, A, S) \ do \ { \ asection *_a = A; \ asection *_s = S; \ asection *_next = _a->next; \ _s->next = _next; \ _s->prev = _a; \ _a->next = _s; \ if (_next) \ _next->prev = _s; \ else \ (ABFD)->section_last = _s; \ } \ while (0) #define bfd_section_list_insert_before(ABFD, B, S) \ do \ { \ asection *_b = B; \ asection *_s = S; \ asection *_prev = _b->prev; \ _s->prev = _prev; \ _s->next = _b; \ _b->prev = _s; \ if (_prev) \ _prev->next = _s; \ else \ (ABFD)->sections = _s; \ } \ while (0) #define bfd_section_removed_from_list(ABFD, S) \ ((S)->next == NULL ? (ABFD)->section_last != (S) : (S)->next->prev != (S)) #define BFD_FAKE_SECTION(SEC, FLAGS, SYM, NAME, IDX) \ /* name, id, index, next, prev, flags, user_set_vma, */ \ { NAME, IDX, 0, NULL, NULL, FLAGS, 0, \ \ /* linker_mark, linker_has_input, gc_mark, gc_mark_from_eh, */ \ 0, 0, 1, 0, \ \ /* segment_mark, sec_info_type, use_rela_p, has_tls_reloc, */ \ 0, 0, 0, 0, \ \ - /* has_gp_reloc, need_finalize_relax, reloc_done, */ \ - 0, 0, 0, \ + /* has_tls_get_addr_call, has_gp_reloc, need_finalize_relax, */ \ + 0, 0, 0, \ \ - /* vma, lma, size, rawsize */ \ - 0, 0, 0, 0, \ + /* reloc_done, vma, lma, size, rawsize */ \ + 0, 0, 0, 0, 0, \ \ /* output_offset, output_section, alignment_power, */ \ 0, (struct bfd_section *) &SEC, 0, \ \ /* relocation, orelocation, reloc_count, filepos, rel_filepos, */ \ NULL, NULL, 0, 0, 0, \ \ /* line_filepos, userdata, contents, lineno, lineno_count, */ \ 0, NULL, NULL, NULL, 0, \ \ /* entsize, kept_section, moving_line_filepos, */ \ 0, NULL, 0, \ \ /* target_index, used_by_bfd, constructor_chain, owner, */ \ 0, NULL, NULL, NULL, \ \ /* symbol, symbol_ptr_ptr, */ \ (struct bfd_symbol *) SYM, &SEC.symbol, \ \ /* map_head, map_tail */ \ { NULL }, { NULL } \ } void bfd_section_list_clear (bfd *); asection *bfd_get_section_by_name (bfd *abfd, const char *name); asection *bfd_get_section_by_name_if (bfd *abfd, const char *name, bfd_boolean (*func) (bfd *abfd, asection *sect, void *obj), void *obj); char *bfd_get_unique_section_name (bfd *abfd, const char *templat, int *count); asection *bfd_make_section_old_way (bfd *abfd, const char *name); asection *bfd_make_section_anyway_with_flags (bfd *abfd, const char *name, flagword flags); asection *bfd_make_section_anyway (bfd *abfd, const char *name); asection *bfd_make_section_with_flags (bfd *, const char *name, flagword flags); asection *bfd_make_section (bfd *, const char *name); bfd_boolean bfd_set_section_flags (bfd *abfd, asection *sec, flagword flags); void bfd_map_over_sections (bfd *abfd, void (*func) (bfd *abfd, asection *sect, void *obj), void *obj); asection *bfd_sections_find_if (bfd *abfd, bfd_boolean (*operation) (bfd *abfd, asection *sect, void *obj), void *obj); bfd_boolean bfd_set_section_size (bfd *abfd, asection *sec, bfd_size_type val); bfd_boolean bfd_set_section_contents (bfd *abfd, asection *section, const void *data, file_ptr offset, bfd_size_type count); bfd_boolean bfd_get_section_contents (bfd *abfd, asection *section, void *location, file_ptr offset, bfd_size_type count); bfd_boolean bfd_malloc_and_get_section (bfd *abfd, asection *section, bfd_byte **buf); bfd_boolean bfd_copy_private_section_data (bfd *ibfd, asection *isec, bfd *obfd, asection *osec); #define bfd_copy_private_section_data(ibfd, isection, obfd, osection) \ BFD_SEND (obfd, _bfd_copy_private_section_data, \ (ibfd, isection, obfd, osection)) bfd_boolean bfd_generic_is_group_section (bfd *, const asection *sec); bfd_boolean bfd_generic_discard_group (bfd *abfd, asection *group); /* Extracted from archures.c. */ enum bfd_architecture { bfd_arch_unknown, /* File arch not known. */ bfd_arch_obscure, /* Arch known, not one of these. */ bfd_arch_m68k, /* Motorola 68xxx */ #define bfd_mach_m68000 1 #define bfd_mach_m68008 2 #define bfd_mach_m68010 3 #define bfd_mach_m68020 4 #define bfd_mach_m68030 5 #define bfd_mach_m68040 6 #define bfd_mach_m68060 7 #define bfd_mach_cpu32 8 #define bfd_mach_fido 9 #define bfd_mach_mcf_isa_a_nodiv 10 #define bfd_mach_mcf_isa_a 11 #define bfd_mach_mcf_isa_a_mac 12 #define bfd_mach_mcf_isa_a_emac 13 #define bfd_mach_mcf_isa_aplus 14 #define bfd_mach_mcf_isa_aplus_mac 15 #define bfd_mach_mcf_isa_aplus_emac 16 #define bfd_mach_mcf_isa_b_nousp 17 #define bfd_mach_mcf_isa_b_nousp_mac 18 #define bfd_mach_mcf_isa_b_nousp_emac 19 #define bfd_mach_mcf_isa_b 20 #define bfd_mach_mcf_isa_b_mac 21 #define bfd_mach_mcf_isa_b_emac 22 #define bfd_mach_mcf_isa_b_float 23 #define bfd_mach_mcf_isa_b_float_mac 24 #define bfd_mach_mcf_isa_b_float_emac 25 #define bfd_mach_mcf_isa_c 26 #define bfd_mach_mcf_isa_c_mac 27 #define bfd_mach_mcf_isa_c_emac 28 bfd_arch_vax, /* DEC Vax */ bfd_arch_i960, /* Intel 960 */ /* The order of the following is important. lower number indicates a machine type that only accepts a subset of the instructions available to machines with higher numbers. The exception is the "ca", which is incompatible with all other machines except "core". */ #define bfd_mach_i960_core 1 #define bfd_mach_i960_ka_sa 2 #define bfd_mach_i960_kb_sb 3 #define bfd_mach_i960_mc 4 #define bfd_mach_i960_xa 5 #define bfd_mach_i960_ca 6 #define bfd_mach_i960_jx 7 #define bfd_mach_i960_hx 8 bfd_arch_or32, /* OpenRISC 32 */ bfd_arch_sparc, /* SPARC */ #define bfd_mach_sparc 1 /* The difference between v8plus and v9 is that v9 is a true 64 bit env. */ #define bfd_mach_sparc_sparclet 2 #define bfd_mach_sparc_sparclite 3 #define bfd_mach_sparc_v8plus 4 #define bfd_mach_sparc_v8plusa 5 /* with ultrasparc add'ns. */ #define bfd_mach_sparc_sparclite_le 6 #define bfd_mach_sparc_v9 7 #define bfd_mach_sparc_v9a 8 /* with ultrasparc add'ns. */ #define bfd_mach_sparc_v8plusb 9 /* with cheetah add'ns. */ #define bfd_mach_sparc_v9b 10 /* with cheetah add'ns. */ /* Nonzero if MACH has the v9 instruction set. */ #define bfd_mach_sparc_v9_p(mach) \ ((mach) >= bfd_mach_sparc_v8plus && (mach) <= bfd_mach_sparc_v9b \ && (mach) != bfd_mach_sparc_sparclite_le) /* Nonzero if MACH is a 64 bit sparc architecture. */ #define bfd_mach_sparc_64bit_p(mach) \ ((mach) >= bfd_mach_sparc_v9 && (mach) != bfd_mach_sparc_v8plusb) bfd_arch_spu, /* PowerPC SPU */ #define bfd_mach_spu 256 bfd_arch_mips, /* MIPS Rxxxx */ #define bfd_mach_mips3000 3000 #define bfd_mach_mips3900 3900 #define bfd_mach_mips4000 4000 #define bfd_mach_mips4010 4010 #define bfd_mach_mips4100 4100 #define bfd_mach_mips4111 4111 #define bfd_mach_mips4120 4120 #define bfd_mach_mips4300 4300 #define bfd_mach_mips4400 4400 #define bfd_mach_mips4600 4600 #define bfd_mach_mips4650 4650 #define bfd_mach_mips5000 5000 #define bfd_mach_mips5400 5400 #define bfd_mach_mips5500 5500 #define bfd_mach_mips6000 6000 #define bfd_mach_mips7000 7000 #define bfd_mach_mips8000 8000 #define bfd_mach_mips9000 9000 #define bfd_mach_mips10000 10000 #define bfd_mach_mips12000 12000 #define bfd_mach_mips16 16 #define bfd_mach_mips5 5 #define bfd_mach_mips_octeon 6502 #define bfd_mach_mips_sb1 12310201 /* octal 'SB', 01 */ #define bfd_mach_mipsisa32 32 #define bfd_mach_mipsisa32r2 33 #define bfd_mach_mipsisa64 64 #define bfd_mach_mipsisa64r2 65 bfd_arch_i386, /* Intel 386 */ #define bfd_mach_i386_i386 1 #define bfd_mach_i386_i8086 2 #define bfd_mach_i386_i386_intel_syntax 3 #define bfd_mach_x86_64 64 #define bfd_mach_x86_64_intel_syntax 65 bfd_arch_we32k, /* AT&T WE32xxx */ bfd_arch_tahoe, /* CCI/Harris Tahoe */ bfd_arch_i860, /* Intel 860 */ bfd_arch_i370, /* IBM 360/370 Mainframes */ bfd_arch_romp, /* IBM ROMP PC/RT */ bfd_arch_convex, /* Convex */ bfd_arch_m88k, /* Motorola 88xxx */ bfd_arch_m98k, /* Motorola 98xxx */ bfd_arch_pyramid, /* Pyramid Technology */ bfd_arch_h8300, /* Renesas H8/300 (formerly Hitachi H8/300) */ #define bfd_mach_h8300 1 #define bfd_mach_h8300h 2 #define bfd_mach_h8300s 3 #define bfd_mach_h8300hn 4 #define bfd_mach_h8300sn 5 #define bfd_mach_h8300sx 6 #define bfd_mach_h8300sxn 7 bfd_arch_pdp11, /* DEC PDP-11 */ bfd_arch_powerpc, /* PowerPC */ #define bfd_mach_ppc 32 #define bfd_mach_ppc64 64 #define bfd_mach_ppc_403 403 #define bfd_mach_ppc_403gc 4030 #define bfd_mach_ppc_505 505 #define bfd_mach_ppc_601 601 #define bfd_mach_ppc_602 602 #define bfd_mach_ppc_603 603 #define bfd_mach_ppc_ec603e 6031 #define bfd_mach_ppc_604 604 #define bfd_mach_ppc_620 620 #define bfd_mach_ppc_630 630 #define bfd_mach_ppc_750 750 #define bfd_mach_ppc_860 860 #define bfd_mach_ppc_a35 35 #define bfd_mach_ppc_rs64ii 642 #define bfd_mach_ppc_rs64iii 643 #define bfd_mach_ppc_7400 7400 #define bfd_mach_ppc_e500 500 bfd_arch_rs6000, /* IBM RS/6000 */ #define bfd_mach_rs6k 6000 #define bfd_mach_rs6k_rs1 6001 #define bfd_mach_rs6k_rsc 6003 #define bfd_mach_rs6k_rs2 6002 bfd_arch_hppa, /* HP PA RISC */ #define bfd_mach_hppa10 10 #define bfd_mach_hppa11 11 #define bfd_mach_hppa20 20 #define bfd_mach_hppa20w 25 bfd_arch_d10v, /* Mitsubishi D10V */ #define bfd_mach_d10v 1 #define bfd_mach_d10v_ts2 2 #define bfd_mach_d10v_ts3 3 bfd_arch_d30v, /* Mitsubishi D30V */ bfd_arch_dlx, /* DLX */ bfd_arch_m68hc11, /* Motorola 68HC11 */ bfd_arch_m68hc12, /* Motorola 68HC12 */ #define bfd_mach_m6812_default 0 #define bfd_mach_m6812 1 #define bfd_mach_m6812s 2 bfd_arch_z8k, /* Zilog Z8000 */ #define bfd_mach_z8001 1 #define bfd_mach_z8002 2 bfd_arch_h8500, /* Renesas H8/500 (formerly Hitachi H8/500) */ bfd_arch_sh, /* Renesas / SuperH SH (formerly Hitachi SH) */ #define bfd_mach_sh 1 #define bfd_mach_sh2 0x20 #define bfd_mach_sh_dsp 0x2d #define bfd_mach_sh2a 0x2a #define bfd_mach_sh2a_nofpu 0x2b #define bfd_mach_sh2a_nofpu_or_sh4_nommu_nofpu 0x2a1 #define bfd_mach_sh2a_nofpu_or_sh3_nommu 0x2a2 #define bfd_mach_sh2a_or_sh4 0x2a3 #define bfd_mach_sh2a_or_sh3e 0x2a4 #define bfd_mach_sh2e 0x2e #define bfd_mach_sh3 0x30 #define bfd_mach_sh3_nommu 0x31 #define bfd_mach_sh3_dsp 0x3d #define bfd_mach_sh3e 0x3e #define bfd_mach_sh4 0x40 #define bfd_mach_sh4_nofpu 0x41 #define bfd_mach_sh4_nommu_nofpu 0x42 #define bfd_mach_sh4a 0x4a #define bfd_mach_sh4a_nofpu 0x4b #define bfd_mach_sh4al_dsp 0x4d #define bfd_mach_sh5 0x50 bfd_arch_alpha, /* Dec Alpha */ #define bfd_mach_alpha_ev4 0x10 #define bfd_mach_alpha_ev5 0x20 #define bfd_mach_alpha_ev6 0x30 bfd_arch_arm, /* Advanced Risc Machines ARM. */ #define bfd_mach_arm_unknown 0 #define bfd_mach_arm_2 1 #define bfd_mach_arm_2a 2 #define bfd_mach_arm_3 3 #define bfd_mach_arm_3M 4 #define bfd_mach_arm_4 5 #define bfd_mach_arm_4T 6 #define bfd_mach_arm_5 7 #define bfd_mach_arm_5T 8 #define bfd_mach_arm_5TE 9 #define bfd_mach_arm_XScale 10 #define bfd_mach_arm_ep9312 11 #define bfd_mach_arm_iWMMXt 12 #define bfd_mach_arm_iWMMXt2 13 bfd_arch_ns32k, /* National Semiconductors ns32000 */ bfd_arch_w65, /* WDC 65816 */ bfd_arch_tic30, /* Texas Instruments TMS320C30 */ bfd_arch_tic4x, /* Texas Instruments TMS320C3X/4X */ #define bfd_mach_tic3x 30 #define bfd_mach_tic4x 40 bfd_arch_tic54x, /* Texas Instruments TMS320C54X */ bfd_arch_tic80, /* TI TMS320c80 (MVP) */ bfd_arch_v850, /* NEC V850 */ #define bfd_mach_v850 1 #define bfd_mach_v850e 'E' #define bfd_mach_v850e1 '1' bfd_arch_arc, /* ARC Cores */ #define bfd_mach_arc_5 5 #define bfd_mach_arc_6 6 #define bfd_mach_arc_7 7 #define bfd_mach_arc_8 8 bfd_arch_m32c, /* Renesas M16C/M32C. */ #define bfd_mach_m16c 0x75 #define bfd_mach_m32c 0x78 bfd_arch_m32r, /* Renesas M32R (formerly Mitsubishi M32R/D) */ #define bfd_mach_m32r 1 /* For backwards compatibility. */ #define bfd_mach_m32rx 'x' #define bfd_mach_m32r2 '2' bfd_arch_mn10200, /* Matsushita MN10200 */ bfd_arch_mn10300, /* Matsushita MN10300 */ #define bfd_mach_mn10300 300 #define bfd_mach_am33 330 #define bfd_mach_am33_2 332 bfd_arch_fr30, #define bfd_mach_fr30 0x46523330 bfd_arch_frv, #define bfd_mach_frv 1 #define bfd_mach_frvsimple 2 #define bfd_mach_fr300 300 #define bfd_mach_fr400 400 #define bfd_mach_fr450 450 #define bfd_mach_frvtomcat 499 /* fr500 prototype */ #define bfd_mach_fr500 500 #define bfd_mach_fr550 550 bfd_arch_mcore, bfd_arch_mep, #define bfd_mach_mep 1 #define bfd_mach_mep_h1 0x6831 bfd_arch_ia64, /* HP/Intel ia64 */ #define bfd_mach_ia64_elf64 64 #define bfd_mach_ia64_elf32 32 bfd_arch_ip2k, /* Ubicom IP2K microcontrollers. */ #define bfd_mach_ip2022 1 #define bfd_mach_ip2022ext 2 bfd_arch_iq2000, /* Vitesse IQ2000. */ #define bfd_mach_iq2000 1 #define bfd_mach_iq10 2 bfd_arch_mt, #define bfd_mach_ms1 1 #define bfd_mach_mrisc2 2 #define bfd_mach_ms2 3 bfd_arch_pj, bfd_arch_avr, /* Atmel AVR microcontrollers. */ #define bfd_mach_avr1 1 #define bfd_mach_avr2 2 #define bfd_mach_avr3 3 #define bfd_mach_avr4 4 #define bfd_mach_avr5 5 #define bfd_mach_avr6 6 bfd_arch_bfin, /* ADI Blackfin */ #define bfd_mach_bfin 1 bfd_arch_cr16, /* National Semiconductor CompactRISC (ie CR16). */ #define bfd_mach_cr16 1 bfd_arch_cr16c, /* National Semiconductor CompactRISC. */ #define bfd_mach_cr16c 1 bfd_arch_crx, /* National Semiconductor CRX. */ #define bfd_mach_crx 1 bfd_arch_cris, /* Axis CRIS */ #define bfd_mach_cris_v0_v10 255 #define bfd_mach_cris_v32 32 #define bfd_mach_cris_v10_v32 1032 bfd_arch_s390, /* IBM s390 */ #define bfd_mach_s390_31 31 #define bfd_mach_s390_64 64 bfd_arch_score, /* Sunplus score */ bfd_arch_openrisc, /* OpenRISC */ bfd_arch_mmix, /* Donald Knuth's educational processor. */ bfd_arch_xstormy16, #define bfd_mach_xstormy16 1 bfd_arch_msp430, /* Texas Instruments MSP430 architecture. */ #define bfd_mach_msp11 11 #define bfd_mach_msp110 110 #define bfd_mach_msp12 12 #define bfd_mach_msp13 13 #define bfd_mach_msp14 14 #define bfd_mach_msp15 15 #define bfd_mach_msp16 16 #define bfd_mach_msp21 21 #define bfd_mach_msp31 31 #define bfd_mach_msp32 32 #define bfd_mach_msp33 33 #define bfd_mach_msp41 41 #define bfd_mach_msp42 42 #define bfd_mach_msp43 43 #define bfd_mach_msp44 44 bfd_arch_xc16x, /* Infineon's XC16X Series. */ #define bfd_mach_xc16x 1 #define bfd_mach_xc16xl 2 #define bfd_mach_xc16xs 3 bfd_arch_xtensa, /* Tensilica's Xtensa cores. */ #define bfd_mach_xtensa 1 bfd_arch_maxq, /* Dallas MAXQ 10/20 */ #define bfd_mach_maxq10 10 #define bfd_mach_maxq20 20 bfd_arch_z80, #define bfd_mach_z80strict 1 /* No undocumented opcodes. */ #define bfd_mach_z80 3 /* With ixl, ixh, iyl, and iyh. */ #define bfd_mach_z80full 7 /* All undocumented instructions. */ #define bfd_mach_r800 11 /* R800: successor with multiplication. */ bfd_arch_last }; typedef struct bfd_arch_info { int bits_per_word; int bits_per_address; int bits_per_byte; enum bfd_architecture arch; unsigned long mach; const char *arch_name; const char *printable_name; unsigned int section_align_power; /* TRUE if this is the default machine for the architecture. The default arch should be the first entry for an arch so that all the entries for that arch can be accessed via <>. */ bfd_boolean the_default; const struct bfd_arch_info * (*compatible) (const struct bfd_arch_info *a, const struct bfd_arch_info *b); bfd_boolean (*scan) (const struct bfd_arch_info *, const char *); const struct bfd_arch_info *next; } bfd_arch_info_type; const char *bfd_printable_name (bfd *abfd); const bfd_arch_info_type *bfd_scan_arch (const char *string); const char **bfd_arch_list (void); const bfd_arch_info_type *bfd_arch_get_compatible (const bfd *abfd, const bfd *bbfd, bfd_boolean accept_unknowns); void bfd_set_arch_info (bfd *abfd, const bfd_arch_info_type *arg); enum bfd_architecture bfd_get_arch (bfd *abfd); unsigned long bfd_get_mach (bfd *abfd); unsigned int bfd_arch_bits_per_byte (bfd *abfd); unsigned int bfd_arch_bits_per_address (bfd *abfd); const bfd_arch_info_type *bfd_get_arch_info (bfd *abfd); const bfd_arch_info_type *bfd_lookup_arch (enum bfd_architecture arch, unsigned long machine); const char *bfd_printable_arch_mach (enum bfd_architecture arch, unsigned long machine); unsigned int bfd_octets_per_byte (bfd *abfd); unsigned int bfd_arch_mach_octets_per_byte (enum bfd_architecture arch, unsigned long machine); /* Extracted from reloc.c. */ typedef enum bfd_reloc_status { /* No errors detected. */ bfd_reloc_ok, /* The relocation was performed, but there was an overflow. */ bfd_reloc_overflow, /* The address to relocate was not within the section supplied. */ bfd_reloc_outofrange, /* Used by special functions. */ bfd_reloc_continue, /* Unsupported relocation size requested. */ bfd_reloc_notsupported, /* Unused. */ bfd_reloc_other, /* The symbol to relocate against was undefined. */ bfd_reloc_undefined, /* The relocation was performed, but may not be ok - presently generated only when linking i960 coff files with i960 b.out symbols. If this type is returned, the error_message argument to bfd_perform_relocation will be set. */ bfd_reloc_dangerous } bfd_reloc_status_type; typedef struct reloc_cache_entry { /* A pointer into the canonical table of pointers. */ struct bfd_symbol **sym_ptr_ptr; /* offset in section. */ bfd_size_type address; /* addend for relocation value. */ bfd_vma addend; /* Pointer to how to perform the required relocation. */ reloc_howto_type *howto; } arelent; enum complain_overflow { /* Do not complain on overflow. */ complain_overflow_dont, /* Complain if the value overflows when considered as a signed number one bit larger than the field. ie. A bitfield of N bits is allowed to represent -2**n to 2**n-1. */ complain_overflow_bitfield, /* Complain if the value overflows when considered as a signed number. */ complain_overflow_signed, /* Complain if the value overflows when considered as an unsigned number. */ complain_overflow_unsigned }; struct reloc_howto_struct { /* The type field has mainly a documentary use - the back end can do what it wants with it, though normally the back end's external idea of what a reloc number is stored in this field. For example, a PC relative word relocation in a coff environment has the type 023 - because that's what the outside world calls a R_PCRWORD reloc. */ unsigned int type; /* The value the final relocation is shifted right by. This drops unwanted data from the relocation. */ unsigned int rightshift; /* The size of the item to be relocated. This is *not* a power-of-two measure. To get the number of bytes operated on by a type of relocation, use bfd_get_reloc_size. */ int size; /* The number of bits in the item to be relocated. This is used when doing overflow checking. */ unsigned int bitsize; /* Notes that the relocation is relative to the location in the data section of the addend. The relocation function will subtract from the relocation value the address of the location being relocated. */ bfd_boolean pc_relative; /* The bit position of the reloc value in the destination. The relocated value is left shifted by this amount. */ unsigned int bitpos; /* What type of overflow error should be checked for when relocating. */ enum complain_overflow complain_on_overflow; /* If this field is non null, then the supplied function is called rather than the normal function. This allows really strange relocation methods to be accommodated (e.g., i960 callj instructions). */ bfd_reloc_status_type (*special_function) (bfd *, arelent *, struct bfd_symbol *, void *, asection *, bfd *, char **); /* The textual name of the relocation type. */ char *name; /* Some formats record a relocation addend in the section contents rather than with the relocation. For ELF formats this is the distinction between USE_REL and USE_RELA (though the code checks for USE_REL == 1/0). The value of this field is TRUE if the addend is recorded with the section contents; when performing a partial link (ld -r) the section contents (the data) will be modified. The value of this field is FALSE if addends are recorded with the relocation (in arelent.addend); when performing a partial link the relocation will be modified. All relocations for all ELF USE_RELA targets should set this field to FALSE (values of TRUE should be looked on with suspicion). However, the converse is not true: not all relocations of all ELF USE_REL targets set this field to TRUE. Why this is so is peculiar to each particular target. For relocs that aren't used in partial links (e.g. GOT stuff) it doesn't matter what this is set to. */ bfd_boolean partial_inplace; /* src_mask selects the part of the instruction (or data) to be used in the relocation sum. If the target relocations don't have an addend in the reloc, eg. ELF USE_REL, src_mask will normally equal dst_mask to extract the addend from the section contents. If relocations do have an addend in the reloc, eg. ELF USE_RELA, this field should be zero. Non-zero values for ELF USE_RELA targets are bogus as in those cases the value in the dst_mask part of the section contents should be treated as garbage. */ bfd_vma src_mask; /* dst_mask selects which parts of the instruction (or data) are replaced with a relocated value. */ bfd_vma dst_mask; /* When some formats create PC relative instructions, they leave the value of the pc of the place being relocated in the offset slot of the instruction, so that a PC relative relocation can be made just by adding in an ordinary offset (e.g., sun3 a.out). Some formats leave the displacement part of an instruction empty (e.g., m88k bcs); this flag signals the fact. */ bfd_boolean pcrel_offset; }; #define HOWTO(C, R, S, B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC) \ { (unsigned) C, R, S, B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC } #define NEWHOWTO(FUNCTION, NAME, SIZE, REL, IN) \ HOWTO (0, 0, SIZE, 0, REL, 0, complain_overflow_dont, FUNCTION, \ NAME, FALSE, 0, 0, IN) #define EMPTY_HOWTO(C) \ HOWTO ((C), 0, 0, 0, FALSE, 0, complain_overflow_dont, NULL, \ NULL, FALSE, 0, 0, FALSE) #define HOWTO_PREPARE(relocation, symbol) \ { \ if (symbol != NULL) \ { \ if (bfd_is_com_section (symbol->section)) \ { \ relocation = 0; \ } \ else \ { \ relocation = symbol->value; \ } \ } \ } unsigned int bfd_get_reloc_size (reloc_howto_type *); typedef struct relent_chain { arelent relent; struct relent_chain *next; } arelent_chain; bfd_reloc_status_type bfd_check_overflow (enum complain_overflow how, unsigned int bitsize, unsigned int rightshift, unsigned int addrsize, bfd_vma relocation); bfd_reloc_status_type bfd_perform_relocation (bfd *abfd, arelent *reloc_entry, void *data, asection *input_section, bfd *output_bfd, char **error_message); bfd_reloc_status_type bfd_install_relocation (bfd *abfd, arelent *reloc_entry, void *data, bfd_vma data_start, asection *input_section, char **error_message); enum bfd_reloc_code_real { _dummy_first_bfd_reloc_code_real, /* Basic absolute relocations of N bits. */ BFD_RELOC_64, BFD_RELOC_32, BFD_RELOC_26, BFD_RELOC_24, BFD_RELOC_16, BFD_RELOC_14, BFD_RELOC_8, /* PC-relative relocations. Sometimes these are relative to the address of the relocation itself; sometimes they are relative to the start of the section containing the relocation. It depends on the specific target. The 24-bit relocation is used in some Intel 960 configurations. */ BFD_RELOC_64_PCREL, BFD_RELOC_32_PCREL, BFD_RELOC_24_PCREL, BFD_RELOC_16_PCREL, BFD_RELOC_12_PCREL, BFD_RELOC_8_PCREL, /* Section relative relocations. Some targets need this for DWARF2. */ BFD_RELOC_32_SECREL, /* For ELF. */ BFD_RELOC_32_GOT_PCREL, BFD_RELOC_16_GOT_PCREL, BFD_RELOC_8_GOT_PCREL, BFD_RELOC_32_GOTOFF, BFD_RELOC_16_GOTOFF, BFD_RELOC_LO16_GOTOFF, BFD_RELOC_HI16_GOTOFF, BFD_RELOC_HI16_S_GOTOFF, BFD_RELOC_8_GOTOFF, BFD_RELOC_64_PLT_PCREL, BFD_RELOC_32_PLT_PCREL, BFD_RELOC_24_PLT_PCREL, BFD_RELOC_16_PLT_PCREL, BFD_RELOC_8_PLT_PCREL, BFD_RELOC_64_PLTOFF, BFD_RELOC_32_PLTOFF, BFD_RELOC_16_PLTOFF, BFD_RELOC_LO16_PLTOFF, BFD_RELOC_HI16_PLTOFF, BFD_RELOC_HI16_S_PLTOFF, BFD_RELOC_8_PLTOFF, /* Relocations used by 68K ELF. */ BFD_RELOC_68K_GLOB_DAT, BFD_RELOC_68K_JMP_SLOT, BFD_RELOC_68K_RELATIVE, /* Linkage-table relative. */ BFD_RELOC_32_BASEREL, BFD_RELOC_16_BASEREL, BFD_RELOC_LO16_BASEREL, BFD_RELOC_HI16_BASEREL, BFD_RELOC_HI16_S_BASEREL, BFD_RELOC_8_BASEREL, BFD_RELOC_RVA, /* Absolute 8-bit relocation, but used to form an address like 0xFFnn. */ BFD_RELOC_8_FFnn, /* These PC-relative relocations are stored as word displacements -- i.e., byte displacements shifted right two bits. The 30-bit word displacement (<<32_PCREL_S2>> -- 32 bits, shifted 2) is used on the SPARC. (SPARC tools generally refer to this as <>.) The signed 16-bit displacement is used on the MIPS, and the 23-bit displacement is used on the Alpha. */ BFD_RELOC_32_PCREL_S2, BFD_RELOC_16_PCREL_S2, BFD_RELOC_23_PCREL_S2, /* High 22 bits and low 10 bits of 32-bit value, placed into lower bits of the target word. These are used on the SPARC. */ BFD_RELOC_HI22, BFD_RELOC_LO10, /* For systems that allocate a Global Pointer register, these are displacements off that register. These relocation types are handled specially, because the value the register will have is decided relatively late. */ BFD_RELOC_GPREL16, BFD_RELOC_GPREL32, /* Reloc types used for i960/b.out. */ BFD_RELOC_I960_CALLJ, /* SPARC ELF relocations. There is probably some overlap with other relocation types already defined. */ BFD_RELOC_NONE, BFD_RELOC_SPARC_WDISP22, BFD_RELOC_SPARC22, BFD_RELOC_SPARC13, BFD_RELOC_SPARC_GOT10, BFD_RELOC_SPARC_GOT13, BFD_RELOC_SPARC_GOT22, BFD_RELOC_SPARC_PC10, BFD_RELOC_SPARC_PC22, BFD_RELOC_SPARC_WPLT30, BFD_RELOC_SPARC_COPY, BFD_RELOC_SPARC_GLOB_DAT, BFD_RELOC_SPARC_JMP_SLOT, BFD_RELOC_SPARC_RELATIVE, BFD_RELOC_SPARC_UA16, BFD_RELOC_SPARC_UA32, BFD_RELOC_SPARC_UA64, /* I think these are specific to SPARC a.out (e.g., Sun 4). */ BFD_RELOC_SPARC_BASE13, BFD_RELOC_SPARC_BASE22, /* SPARC64 relocations */ #define BFD_RELOC_SPARC_64 BFD_RELOC_64 BFD_RELOC_SPARC_10, BFD_RELOC_SPARC_11, BFD_RELOC_SPARC_OLO10, BFD_RELOC_SPARC_HH22, BFD_RELOC_SPARC_HM10, BFD_RELOC_SPARC_LM22, BFD_RELOC_SPARC_PC_HH22, BFD_RELOC_SPARC_PC_HM10, BFD_RELOC_SPARC_PC_LM22, BFD_RELOC_SPARC_WDISP16, BFD_RELOC_SPARC_WDISP19, BFD_RELOC_SPARC_7, BFD_RELOC_SPARC_6, BFD_RELOC_SPARC_5, #define BFD_RELOC_SPARC_DISP64 BFD_RELOC_64_PCREL BFD_RELOC_SPARC_PLT32, BFD_RELOC_SPARC_PLT64, BFD_RELOC_SPARC_HIX22, BFD_RELOC_SPARC_LOX10, BFD_RELOC_SPARC_H44, BFD_RELOC_SPARC_M44, BFD_RELOC_SPARC_L44, BFD_RELOC_SPARC_REGISTER, /* SPARC little endian relocation */ BFD_RELOC_SPARC_REV32, /* SPARC TLS relocations */ BFD_RELOC_SPARC_TLS_GD_HI22, BFD_RELOC_SPARC_TLS_GD_LO10, BFD_RELOC_SPARC_TLS_GD_ADD, BFD_RELOC_SPARC_TLS_GD_CALL, BFD_RELOC_SPARC_TLS_LDM_HI22, BFD_RELOC_SPARC_TLS_LDM_LO10, BFD_RELOC_SPARC_TLS_LDM_ADD, BFD_RELOC_SPARC_TLS_LDM_CALL, BFD_RELOC_SPARC_TLS_LDO_HIX22, BFD_RELOC_SPARC_TLS_LDO_LOX10, BFD_RELOC_SPARC_TLS_LDO_ADD, BFD_RELOC_SPARC_TLS_IE_HI22, BFD_RELOC_SPARC_TLS_IE_LO10, BFD_RELOC_SPARC_TLS_IE_LD, BFD_RELOC_SPARC_TLS_IE_LDX, BFD_RELOC_SPARC_TLS_IE_ADD, BFD_RELOC_SPARC_TLS_LE_HIX22, BFD_RELOC_SPARC_TLS_LE_LOX10, BFD_RELOC_SPARC_TLS_DTPMOD32, BFD_RELOC_SPARC_TLS_DTPMOD64, BFD_RELOC_SPARC_TLS_DTPOFF32, BFD_RELOC_SPARC_TLS_DTPOFF64, BFD_RELOC_SPARC_TLS_TPOFF32, BFD_RELOC_SPARC_TLS_TPOFF64, /* SPU Relocations. */ BFD_RELOC_SPU_IMM7, BFD_RELOC_SPU_IMM8, BFD_RELOC_SPU_IMM10, BFD_RELOC_SPU_IMM10W, BFD_RELOC_SPU_IMM16, BFD_RELOC_SPU_IMM16W, BFD_RELOC_SPU_IMM18, BFD_RELOC_SPU_PCREL9a, BFD_RELOC_SPU_PCREL9b, BFD_RELOC_SPU_PCREL16, BFD_RELOC_SPU_LO16, BFD_RELOC_SPU_HI16, BFD_RELOC_SPU_PPU32, BFD_RELOC_SPU_PPU64, /* Alpha ECOFF and ELF relocations. Some of these treat the symbol or "addend" in some special way. For GPDISP_HI16 ("gpdisp") relocations, the symbol is ignored when writing; when reading, it will be the absolute section symbol. The addend is the displacement in bytes of the "lda" instruction from the "ldah" instruction (which is at the address of this reloc). */ BFD_RELOC_ALPHA_GPDISP_HI16, /* For GPDISP_LO16 ("ignore") relocations, the symbol is handled as with GPDISP_HI16 relocs. The addend is ignored when writing the relocations out, and is filled in with the file's GP value on reading, for convenience. */ BFD_RELOC_ALPHA_GPDISP_LO16, /* The ELF GPDISP relocation is exactly the same as the GPDISP_HI16 relocation except that there is no accompanying GPDISP_LO16 relocation. */ BFD_RELOC_ALPHA_GPDISP, /* The Alpha LITERAL/LITUSE relocs are produced by a symbol reference; the assembler turns it into a LDQ instruction to load the address of the symbol, and then fills in a register in the real instruction. The LITERAL reloc, at the LDQ instruction, refers to the .lita section symbol. The addend is ignored when writing, but is filled in with the file's GP value on reading, for convenience, as with the GPDISP_LO16 reloc. The ELF_LITERAL reloc is somewhere between 16_GOTOFF and GPDISP_LO16. It should refer to the symbol to be referenced, as with 16_GOTOFF, but it generates output not based on the position within the .got section, but relative to the GP value chosen for the file during the final link stage. The LITUSE reloc, on the instruction using the loaded address, gives information to the linker that it might be able to use to optimize away some literal section references. The symbol is ignored (read as the absolute section symbol), and the "addend" indicates the type of instruction using the register: 1 - "memory" fmt insn 2 - byte-manipulation (byte offset reg) 3 - jsr (target of branch) */ BFD_RELOC_ALPHA_LITERAL, BFD_RELOC_ALPHA_ELF_LITERAL, BFD_RELOC_ALPHA_LITUSE, /* The HINT relocation indicates a value that should be filled into the "hint" field of a jmp/jsr/ret instruction, for possible branch- prediction logic which may be provided on some processors. */ BFD_RELOC_ALPHA_HINT, /* The LINKAGE relocation outputs a linkage pair in the object file, which is filled by the linker. */ BFD_RELOC_ALPHA_LINKAGE, /* The CODEADDR relocation outputs a STO_CA in the object file, which is filled by the linker. */ BFD_RELOC_ALPHA_CODEADDR, /* The GPREL_HI/LO relocations together form a 32-bit offset from the GP register. */ BFD_RELOC_ALPHA_GPREL_HI16, BFD_RELOC_ALPHA_GPREL_LO16, /* Like BFD_RELOC_23_PCREL_S2, except that the source and target must share a common GP, and the target address is adjusted for STO_ALPHA_STD_GPLOAD. */ BFD_RELOC_ALPHA_BRSGP, /* Alpha thread-local storage relocations. */ BFD_RELOC_ALPHA_TLSGD, BFD_RELOC_ALPHA_TLSLDM, BFD_RELOC_ALPHA_DTPMOD64, BFD_RELOC_ALPHA_GOTDTPREL16, BFD_RELOC_ALPHA_DTPREL64, BFD_RELOC_ALPHA_DTPREL_HI16, BFD_RELOC_ALPHA_DTPREL_LO16, BFD_RELOC_ALPHA_DTPREL16, BFD_RELOC_ALPHA_GOTTPREL16, BFD_RELOC_ALPHA_TPREL64, BFD_RELOC_ALPHA_TPREL_HI16, BFD_RELOC_ALPHA_TPREL_LO16, BFD_RELOC_ALPHA_TPREL16, /* Bits 27..2 of the relocation address shifted right 2 bits; simple reloc otherwise. */ BFD_RELOC_MIPS_JMP, /* The MIPS16 jump instruction. */ BFD_RELOC_MIPS16_JMP, /* MIPS16 GP relative reloc. */ BFD_RELOC_MIPS16_GPREL, /* High 16 bits of 32-bit value; simple reloc. */ BFD_RELOC_HI16, /* High 16 bits of 32-bit value but the low 16 bits will be sign extended and added to form the final result. If the low 16 bits form a negative number, we need to add one to the high value to compensate for the borrow when the low bits are added. */ BFD_RELOC_HI16_S, /* Low 16 bits. */ BFD_RELOC_LO16, /* High 16 bits of 32-bit pc-relative value */ BFD_RELOC_HI16_PCREL, /* High 16 bits of 32-bit pc-relative value, adjusted */ BFD_RELOC_HI16_S_PCREL, /* Low 16 bits of pc-relative value */ BFD_RELOC_LO16_PCREL, /* MIPS16 high 16 bits of 32-bit value. */ BFD_RELOC_MIPS16_HI16, /* MIPS16 high 16 bits of 32-bit value but the low 16 bits will be sign extended and added to form the final result. If the low 16 bits form a negative number, we need to add one to the high value to compensate for the borrow when the low bits are added. */ BFD_RELOC_MIPS16_HI16_S, /* MIPS16 low 16 bits. */ BFD_RELOC_MIPS16_LO16, /* Relocation against a MIPS literal section. */ BFD_RELOC_MIPS_LITERAL, /* MIPS ELF relocations. */ BFD_RELOC_MIPS_GOT16, BFD_RELOC_MIPS_CALL16, BFD_RELOC_MIPS_GOT_HI16, BFD_RELOC_MIPS_GOT_LO16, BFD_RELOC_MIPS_CALL_HI16, BFD_RELOC_MIPS_CALL_LO16, BFD_RELOC_MIPS_SUB, BFD_RELOC_MIPS_GOT_PAGE, BFD_RELOC_MIPS_GOT_OFST, BFD_RELOC_MIPS_GOT_DISP, BFD_RELOC_MIPS_SHIFT5, BFD_RELOC_MIPS_SHIFT6, BFD_RELOC_MIPS_INSERT_A, BFD_RELOC_MIPS_INSERT_B, BFD_RELOC_MIPS_DELETE, BFD_RELOC_MIPS_HIGHEST, BFD_RELOC_MIPS_HIGHER, BFD_RELOC_MIPS_SCN_DISP, BFD_RELOC_MIPS_REL16, BFD_RELOC_MIPS_RELGOT, BFD_RELOC_MIPS_JALR, BFD_RELOC_MIPS_TLS_DTPMOD32, BFD_RELOC_MIPS_TLS_DTPREL32, BFD_RELOC_MIPS_TLS_DTPMOD64, BFD_RELOC_MIPS_TLS_DTPREL64, BFD_RELOC_MIPS_TLS_GD, BFD_RELOC_MIPS_TLS_LDM, BFD_RELOC_MIPS_TLS_DTPREL_HI16, BFD_RELOC_MIPS_TLS_DTPREL_LO16, BFD_RELOC_MIPS_TLS_GOTTPREL, BFD_RELOC_MIPS_TLS_TPREL32, BFD_RELOC_MIPS_TLS_TPREL64, BFD_RELOC_MIPS_TLS_TPREL_HI16, 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, BFD_RELOC_FRV_LO16, BFD_RELOC_FRV_HI16, BFD_RELOC_FRV_GPREL12, BFD_RELOC_FRV_GPRELU12, BFD_RELOC_FRV_GPREL32, BFD_RELOC_FRV_GPRELHI, BFD_RELOC_FRV_GPRELLO, BFD_RELOC_FRV_GOT12, BFD_RELOC_FRV_GOTHI, BFD_RELOC_FRV_GOTLO, BFD_RELOC_FRV_FUNCDESC, BFD_RELOC_FRV_FUNCDESC_GOT12, BFD_RELOC_FRV_FUNCDESC_GOTHI, BFD_RELOC_FRV_FUNCDESC_GOTLO, BFD_RELOC_FRV_FUNCDESC_VALUE, BFD_RELOC_FRV_FUNCDESC_GOTOFF12, BFD_RELOC_FRV_FUNCDESC_GOTOFFHI, BFD_RELOC_FRV_FUNCDESC_GOTOFFLO, BFD_RELOC_FRV_GOTOFF12, BFD_RELOC_FRV_GOTOFFHI, BFD_RELOC_FRV_GOTOFFLO, BFD_RELOC_FRV_GETTLSOFF, BFD_RELOC_FRV_TLSDESC_VALUE, BFD_RELOC_FRV_GOTTLSDESC12, BFD_RELOC_FRV_GOTTLSDESCHI, BFD_RELOC_FRV_GOTTLSDESCLO, BFD_RELOC_FRV_TLSMOFF12, BFD_RELOC_FRV_TLSMOFFHI, BFD_RELOC_FRV_TLSMOFFLO, BFD_RELOC_FRV_GOTTLSOFF12, BFD_RELOC_FRV_GOTTLSOFFHI, BFD_RELOC_FRV_GOTTLSOFFLO, BFD_RELOC_FRV_TLSOFF, BFD_RELOC_FRV_TLSDESC_RELAX, BFD_RELOC_FRV_GETTLSOFF_RELAX, BFD_RELOC_FRV_TLSOFF_RELAX, BFD_RELOC_FRV_TLSMOFF, /* This is a 24bit GOT-relative reloc for the mn10300. */ BFD_RELOC_MN10300_GOTOFF24, /* This is a 32bit GOT-relative reloc for the mn10300, offset by two bytes in the instruction. */ BFD_RELOC_MN10300_GOT32, /* This is a 24bit GOT-relative reloc for the mn10300, offset by two bytes in the instruction. */ BFD_RELOC_MN10300_GOT24, /* This is a 16bit GOT-relative reloc for the mn10300, offset by two bytes in the instruction. */ BFD_RELOC_MN10300_GOT16, /* Copy symbol at runtime. */ BFD_RELOC_MN10300_COPY, /* Create GOT entry. */ BFD_RELOC_MN10300_GLOB_DAT, /* Create PLT entry. */ BFD_RELOC_MN10300_JMP_SLOT, /* Adjust by program base. */ BFD_RELOC_MN10300_RELATIVE, /* i386/elf relocations */ BFD_RELOC_386_GOT32, BFD_RELOC_386_PLT32, BFD_RELOC_386_COPY, BFD_RELOC_386_GLOB_DAT, BFD_RELOC_386_JUMP_SLOT, BFD_RELOC_386_RELATIVE, BFD_RELOC_386_GOTOFF, BFD_RELOC_386_GOTPC, BFD_RELOC_386_TLS_TPOFF, BFD_RELOC_386_TLS_IE, BFD_RELOC_386_TLS_GOTIE, BFD_RELOC_386_TLS_LE, BFD_RELOC_386_TLS_GD, BFD_RELOC_386_TLS_LDM, BFD_RELOC_386_TLS_LDO_32, BFD_RELOC_386_TLS_IE_32, BFD_RELOC_386_TLS_LE_32, BFD_RELOC_386_TLS_DTPMOD32, BFD_RELOC_386_TLS_DTPOFF32, BFD_RELOC_386_TLS_TPOFF32, BFD_RELOC_386_TLS_GOTDESC, BFD_RELOC_386_TLS_DESC_CALL, BFD_RELOC_386_TLS_DESC, /* x86-64/elf relocations */ BFD_RELOC_X86_64_GOT32, BFD_RELOC_X86_64_PLT32, BFD_RELOC_X86_64_COPY, BFD_RELOC_X86_64_GLOB_DAT, BFD_RELOC_X86_64_JUMP_SLOT, BFD_RELOC_X86_64_RELATIVE, BFD_RELOC_X86_64_GOTPCREL, BFD_RELOC_X86_64_32S, BFD_RELOC_X86_64_DTPMOD64, BFD_RELOC_X86_64_DTPOFF64, BFD_RELOC_X86_64_TPOFF64, BFD_RELOC_X86_64_TLSGD, BFD_RELOC_X86_64_TLSLD, BFD_RELOC_X86_64_DTPOFF32, BFD_RELOC_X86_64_GOTTPOFF, 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, /* ns32k relocations */ BFD_RELOC_NS32K_IMM_8, BFD_RELOC_NS32K_IMM_16, BFD_RELOC_NS32K_IMM_32, BFD_RELOC_NS32K_IMM_8_PCREL, BFD_RELOC_NS32K_IMM_16_PCREL, BFD_RELOC_NS32K_IMM_32_PCREL, BFD_RELOC_NS32K_DISP_8, BFD_RELOC_NS32K_DISP_16, BFD_RELOC_NS32K_DISP_32, BFD_RELOC_NS32K_DISP_8_PCREL, BFD_RELOC_NS32K_DISP_16_PCREL, BFD_RELOC_NS32K_DISP_32_PCREL, /* PDP11 relocations */ BFD_RELOC_PDP11_DISP_8_PCREL, BFD_RELOC_PDP11_DISP_6_PCREL, /* Picojava relocs. Not all of these appear in object files. */ BFD_RELOC_PJ_CODE_HI16, BFD_RELOC_PJ_CODE_LO16, BFD_RELOC_PJ_CODE_DIR16, BFD_RELOC_PJ_CODE_DIR32, BFD_RELOC_PJ_CODE_REL16, BFD_RELOC_PJ_CODE_REL32, /* Power(rs6000) and PowerPC relocations. */ BFD_RELOC_PPC_B26, BFD_RELOC_PPC_BA26, BFD_RELOC_PPC_TOC16, BFD_RELOC_PPC_B16, BFD_RELOC_PPC_B16_BRTAKEN, BFD_RELOC_PPC_B16_BRNTAKEN, BFD_RELOC_PPC_BA16, BFD_RELOC_PPC_BA16_BRTAKEN, BFD_RELOC_PPC_BA16_BRNTAKEN, BFD_RELOC_PPC_COPY, BFD_RELOC_PPC_GLOB_DAT, BFD_RELOC_PPC_JMP_SLOT, BFD_RELOC_PPC_RELATIVE, BFD_RELOC_PPC_LOCAL24PC, BFD_RELOC_PPC_EMB_NADDR32, BFD_RELOC_PPC_EMB_NADDR16, BFD_RELOC_PPC_EMB_NADDR16_LO, BFD_RELOC_PPC_EMB_NADDR16_HI, BFD_RELOC_PPC_EMB_NADDR16_HA, BFD_RELOC_PPC_EMB_SDAI16, BFD_RELOC_PPC_EMB_SDA2I16, BFD_RELOC_PPC_EMB_SDA2REL, BFD_RELOC_PPC_EMB_SDA21, BFD_RELOC_PPC_EMB_MRKREF, BFD_RELOC_PPC_EMB_RELSEC16, BFD_RELOC_PPC_EMB_RELST_LO, BFD_RELOC_PPC_EMB_RELST_HI, BFD_RELOC_PPC_EMB_RELST_HA, BFD_RELOC_PPC_EMB_BIT_FLD, BFD_RELOC_PPC_EMB_RELSDA, BFD_RELOC_PPC64_HIGHER, BFD_RELOC_PPC64_HIGHER_S, BFD_RELOC_PPC64_HIGHEST, BFD_RELOC_PPC64_HIGHEST_S, BFD_RELOC_PPC64_TOC16_LO, BFD_RELOC_PPC64_TOC16_HI, BFD_RELOC_PPC64_TOC16_HA, BFD_RELOC_PPC64_TOC, BFD_RELOC_PPC64_PLTGOT16, BFD_RELOC_PPC64_PLTGOT16_LO, BFD_RELOC_PPC64_PLTGOT16_HI, BFD_RELOC_PPC64_PLTGOT16_HA, BFD_RELOC_PPC64_ADDR16_DS, BFD_RELOC_PPC64_ADDR16_LO_DS, BFD_RELOC_PPC64_GOT16_DS, BFD_RELOC_PPC64_GOT16_LO_DS, BFD_RELOC_PPC64_PLT16_LO_DS, BFD_RELOC_PPC64_SECTOFF_DS, BFD_RELOC_PPC64_SECTOFF_LO_DS, BFD_RELOC_PPC64_TOC16_DS, BFD_RELOC_PPC64_TOC16_LO_DS, BFD_RELOC_PPC64_PLTGOT16_DS, BFD_RELOC_PPC64_PLTGOT16_LO_DS, /* PowerPC and PowerPC64 thread-local storage relocations. */ BFD_RELOC_PPC_TLS, + BFD_RELOC_PPC_TLSGD, + BFD_RELOC_PPC_TLSLD, BFD_RELOC_PPC_DTPMOD, BFD_RELOC_PPC_TPREL16, BFD_RELOC_PPC_TPREL16_LO, BFD_RELOC_PPC_TPREL16_HI, BFD_RELOC_PPC_TPREL16_HA, BFD_RELOC_PPC_TPREL, BFD_RELOC_PPC_DTPREL16, BFD_RELOC_PPC_DTPREL16_LO, BFD_RELOC_PPC_DTPREL16_HI, BFD_RELOC_PPC_DTPREL16_HA, BFD_RELOC_PPC_DTPREL, BFD_RELOC_PPC_GOT_TLSGD16, BFD_RELOC_PPC_GOT_TLSGD16_LO, BFD_RELOC_PPC_GOT_TLSGD16_HI, BFD_RELOC_PPC_GOT_TLSGD16_HA, BFD_RELOC_PPC_GOT_TLSLD16, BFD_RELOC_PPC_GOT_TLSLD16_LO, BFD_RELOC_PPC_GOT_TLSLD16_HI, BFD_RELOC_PPC_GOT_TLSLD16_HA, BFD_RELOC_PPC_GOT_TPREL16, BFD_RELOC_PPC_GOT_TPREL16_LO, BFD_RELOC_PPC_GOT_TPREL16_HI, BFD_RELOC_PPC_GOT_TPREL16_HA, BFD_RELOC_PPC_GOT_DTPREL16, BFD_RELOC_PPC_GOT_DTPREL16_LO, BFD_RELOC_PPC_GOT_DTPREL16_HI, BFD_RELOC_PPC_GOT_DTPREL16_HA, BFD_RELOC_PPC64_TPREL16_DS, BFD_RELOC_PPC64_TPREL16_LO_DS, BFD_RELOC_PPC64_TPREL16_HIGHER, BFD_RELOC_PPC64_TPREL16_HIGHERA, BFD_RELOC_PPC64_TPREL16_HIGHEST, BFD_RELOC_PPC64_TPREL16_HIGHESTA, BFD_RELOC_PPC64_DTPREL16_DS, BFD_RELOC_PPC64_DTPREL16_LO_DS, BFD_RELOC_PPC64_DTPREL16_HIGHER, BFD_RELOC_PPC64_DTPREL16_HIGHERA, BFD_RELOC_PPC64_DTPREL16_HIGHEST, BFD_RELOC_PPC64_DTPREL16_HIGHESTA, /* IBM 370/390 relocations */ BFD_RELOC_I370_D12, /* The type of reloc used to build a constructor table - at the moment probably a 32 bit wide absolute relocation, but the target can choose. It generally does map to one of the other relocation types. */ BFD_RELOC_CTOR, /* ARM 26 bit pc-relative branch. The lowest two bits must be zero and are not stored in the instruction. */ BFD_RELOC_ARM_PCREL_BRANCH, /* ARM 26 bit pc-relative branch. The lowest bit must be zero and is not stored in the instruction. The 2nd lowest bit comes from a 1 bit field in the instruction. */ BFD_RELOC_ARM_PCREL_BLX, /* Thumb 22 bit pc-relative branch. The lowest bit must be zero and is not stored in the instruction. The 2nd lowest bit comes from a 1 bit field in the instruction. */ BFD_RELOC_THUMB_PCREL_BLX, /* ARM 26-bit pc-relative branch for an unconditional BL or BLX instruction. */ BFD_RELOC_ARM_PCREL_CALL, /* ARM 26-bit pc-relative branch for B or conditional BL instruction. */ BFD_RELOC_ARM_PCREL_JUMP, /* Thumb 7-, 9-, 12-, 20-, 23-, and 25-bit pc-relative branches. The lowest bit must be zero and is not stored in the instruction. Note that the corresponding ELF R_ARM_THM_JUMPnn constant has an "nn" one smaller in all cases. Note further that BRANCH23 corresponds to R_ARM_THM_CALL. */ BFD_RELOC_THUMB_PCREL_BRANCH7, BFD_RELOC_THUMB_PCREL_BRANCH9, BFD_RELOC_THUMB_PCREL_BRANCH12, BFD_RELOC_THUMB_PCREL_BRANCH20, BFD_RELOC_THUMB_PCREL_BRANCH23, BFD_RELOC_THUMB_PCREL_BRANCH25, /* 12-bit immediate offset, used in ARM-format ldr and str instructions. */ BFD_RELOC_ARM_OFFSET_IMM, /* 5-bit immediate offset, used in Thumb-format ldr and str instructions. */ BFD_RELOC_ARM_THUMB_OFFSET, /* Pc-relative or absolute relocation depending on target. Used for entries in .init_array sections. */ BFD_RELOC_ARM_TARGET1, /* Read-only segment base relative address. */ BFD_RELOC_ARM_ROSEGREL32, /* Data segment base relative address. */ BFD_RELOC_ARM_SBREL32, /* This reloc is used for references to RTTI data from exception handling tables. The actual definition depends on the target. It may be a pc-relative or some form of GOT-indirect relocation. */ BFD_RELOC_ARM_TARGET2, /* 31-bit PC relative address. */ BFD_RELOC_ARM_PREL31, /* Low and High halfword relocations for MOVW and MOVT instructions. */ BFD_RELOC_ARM_MOVW, BFD_RELOC_ARM_MOVT, BFD_RELOC_ARM_MOVW_PCREL, BFD_RELOC_ARM_MOVT_PCREL, BFD_RELOC_ARM_THUMB_MOVW, BFD_RELOC_ARM_THUMB_MOVT, BFD_RELOC_ARM_THUMB_MOVW_PCREL, BFD_RELOC_ARM_THUMB_MOVT_PCREL, /* Relocations for setting up GOTs and PLTs for shared libraries. */ BFD_RELOC_ARM_JUMP_SLOT, BFD_RELOC_ARM_GLOB_DAT, BFD_RELOC_ARM_GOT32, BFD_RELOC_ARM_PLT32, BFD_RELOC_ARM_RELATIVE, BFD_RELOC_ARM_GOTOFF, BFD_RELOC_ARM_GOTPC, /* ARM thread-local storage relocations. */ BFD_RELOC_ARM_TLS_GD32, BFD_RELOC_ARM_TLS_LDO32, BFD_RELOC_ARM_TLS_LDM32, BFD_RELOC_ARM_TLS_DTPOFF32, BFD_RELOC_ARM_TLS_DTPMOD32, BFD_RELOC_ARM_TLS_TPOFF32, BFD_RELOC_ARM_TLS_IE32, BFD_RELOC_ARM_TLS_LE32, /* ARM group relocations. */ BFD_RELOC_ARM_ALU_PC_G0_NC, BFD_RELOC_ARM_ALU_PC_G0, BFD_RELOC_ARM_ALU_PC_G1_NC, BFD_RELOC_ARM_ALU_PC_G1, BFD_RELOC_ARM_ALU_PC_G2, BFD_RELOC_ARM_LDR_PC_G0, BFD_RELOC_ARM_LDR_PC_G1, BFD_RELOC_ARM_LDR_PC_G2, BFD_RELOC_ARM_LDRS_PC_G0, BFD_RELOC_ARM_LDRS_PC_G1, BFD_RELOC_ARM_LDRS_PC_G2, BFD_RELOC_ARM_LDC_PC_G0, BFD_RELOC_ARM_LDC_PC_G1, BFD_RELOC_ARM_LDC_PC_G2, BFD_RELOC_ARM_ALU_SB_G0_NC, BFD_RELOC_ARM_ALU_SB_G0, BFD_RELOC_ARM_ALU_SB_G1_NC, BFD_RELOC_ARM_ALU_SB_G1, BFD_RELOC_ARM_ALU_SB_G2, BFD_RELOC_ARM_LDR_SB_G0, BFD_RELOC_ARM_LDR_SB_G1, BFD_RELOC_ARM_LDR_SB_G2, BFD_RELOC_ARM_LDRS_SB_G0, BFD_RELOC_ARM_LDRS_SB_G1, BFD_RELOC_ARM_LDRS_SB_G2, BFD_RELOC_ARM_LDC_SB_G0, BFD_RELOC_ARM_LDC_SB_G1, BFD_RELOC_ARM_LDC_SB_G2, /* These relocs are only used within the ARM assembler. They are not (at present) written to any object files. */ BFD_RELOC_ARM_IMMEDIATE, BFD_RELOC_ARM_ADRL_IMMEDIATE, BFD_RELOC_ARM_T32_IMMEDIATE, BFD_RELOC_ARM_T32_ADD_IMM, BFD_RELOC_ARM_T32_IMM12, BFD_RELOC_ARM_T32_ADD_PC12, BFD_RELOC_ARM_SHIFT_IMM, BFD_RELOC_ARM_SMC, BFD_RELOC_ARM_SWI, BFD_RELOC_ARM_MULTI, BFD_RELOC_ARM_CP_OFF_IMM, BFD_RELOC_ARM_CP_OFF_IMM_S2, BFD_RELOC_ARM_T32_CP_OFF_IMM, BFD_RELOC_ARM_T32_CP_OFF_IMM_S2, BFD_RELOC_ARM_ADR_IMM, BFD_RELOC_ARM_LDR_IMM, BFD_RELOC_ARM_LITERAL, BFD_RELOC_ARM_IN_POOL, BFD_RELOC_ARM_OFFSET_IMM8, BFD_RELOC_ARM_T32_OFFSET_U8, BFD_RELOC_ARM_T32_OFFSET_IMM, BFD_RELOC_ARM_HWLITERAL, BFD_RELOC_ARM_THUMB_ADD, BFD_RELOC_ARM_THUMB_IMM, BFD_RELOC_ARM_THUMB_SHIFT, /* Renesas / SuperH SH relocs. Not all of these appear in object files. */ BFD_RELOC_SH_PCDISP8BY2, BFD_RELOC_SH_PCDISP12BY2, BFD_RELOC_SH_IMM3, BFD_RELOC_SH_IMM3U, BFD_RELOC_SH_DISP12, BFD_RELOC_SH_DISP12BY2, BFD_RELOC_SH_DISP12BY4, BFD_RELOC_SH_DISP12BY8, BFD_RELOC_SH_DISP20, BFD_RELOC_SH_DISP20BY8, BFD_RELOC_SH_IMM4, BFD_RELOC_SH_IMM4BY2, BFD_RELOC_SH_IMM4BY4, BFD_RELOC_SH_IMM8, BFD_RELOC_SH_IMM8BY2, BFD_RELOC_SH_IMM8BY4, BFD_RELOC_SH_PCRELIMM8BY2, BFD_RELOC_SH_PCRELIMM8BY4, BFD_RELOC_SH_SWITCH16, BFD_RELOC_SH_SWITCH32, BFD_RELOC_SH_USES, BFD_RELOC_SH_COUNT, BFD_RELOC_SH_ALIGN, BFD_RELOC_SH_CODE, BFD_RELOC_SH_DATA, BFD_RELOC_SH_LABEL, BFD_RELOC_SH_LOOP_START, BFD_RELOC_SH_LOOP_END, BFD_RELOC_SH_COPY, BFD_RELOC_SH_GLOB_DAT, BFD_RELOC_SH_JMP_SLOT, BFD_RELOC_SH_RELATIVE, BFD_RELOC_SH_GOTPC, BFD_RELOC_SH_GOT_LOW16, BFD_RELOC_SH_GOT_MEDLOW16, BFD_RELOC_SH_GOT_MEDHI16, BFD_RELOC_SH_GOT_HI16, BFD_RELOC_SH_GOTPLT_LOW16, BFD_RELOC_SH_GOTPLT_MEDLOW16, BFD_RELOC_SH_GOTPLT_MEDHI16, BFD_RELOC_SH_GOTPLT_HI16, BFD_RELOC_SH_PLT_LOW16, BFD_RELOC_SH_PLT_MEDLOW16, BFD_RELOC_SH_PLT_MEDHI16, BFD_RELOC_SH_PLT_HI16, BFD_RELOC_SH_GOTOFF_LOW16, BFD_RELOC_SH_GOTOFF_MEDLOW16, BFD_RELOC_SH_GOTOFF_MEDHI16, BFD_RELOC_SH_GOTOFF_HI16, BFD_RELOC_SH_GOTPC_LOW16, BFD_RELOC_SH_GOTPC_MEDLOW16, BFD_RELOC_SH_GOTPC_MEDHI16, BFD_RELOC_SH_GOTPC_HI16, BFD_RELOC_SH_COPY64, BFD_RELOC_SH_GLOB_DAT64, BFD_RELOC_SH_JMP_SLOT64, BFD_RELOC_SH_RELATIVE64, BFD_RELOC_SH_GOT10BY4, BFD_RELOC_SH_GOT10BY8, BFD_RELOC_SH_GOTPLT10BY4, BFD_RELOC_SH_GOTPLT10BY8, BFD_RELOC_SH_GOTPLT32, BFD_RELOC_SH_SHMEDIA_CODE, BFD_RELOC_SH_IMMU5, BFD_RELOC_SH_IMMS6, BFD_RELOC_SH_IMMS6BY32, BFD_RELOC_SH_IMMU6, BFD_RELOC_SH_IMMS10, BFD_RELOC_SH_IMMS10BY2, BFD_RELOC_SH_IMMS10BY4, BFD_RELOC_SH_IMMS10BY8, BFD_RELOC_SH_IMMS16, BFD_RELOC_SH_IMMU16, BFD_RELOC_SH_IMM_LOW16, BFD_RELOC_SH_IMM_LOW16_PCREL, BFD_RELOC_SH_IMM_MEDLOW16, BFD_RELOC_SH_IMM_MEDLOW16_PCREL, BFD_RELOC_SH_IMM_MEDHI16, BFD_RELOC_SH_IMM_MEDHI16_PCREL, BFD_RELOC_SH_IMM_HI16, BFD_RELOC_SH_IMM_HI16_PCREL, BFD_RELOC_SH_PT_16, BFD_RELOC_SH_TLS_GD_32, BFD_RELOC_SH_TLS_LD_32, BFD_RELOC_SH_TLS_LDO_32, BFD_RELOC_SH_TLS_IE_32, BFD_RELOC_SH_TLS_LE_32, BFD_RELOC_SH_TLS_DTPMOD32, BFD_RELOC_SH_TLS_DTPOFF32, BFD_RELOC_SH_TLS_TPOFF32, /* ARC Cores relocs. ARC 22 bit pc-relative branch. The lowest two bits must be zero and are not stored in the instruction. The high 20 bits are installed in bits 26 through 7 of the instruction. */ BFD_RELOC_ARC_B22_PCREL, /* ARC 26 bit absolute branch. The lowest two bits must be zero and are not stored in the instruction. The high 24 bits are installed in bits 23 through 0. */ BFD_RELOC_ARC_B26, /* ADI Blackfin 16 bit immediate absolute reloc. */ BFD_RELOC_BFIN_16_IMM, /* ADI Blackfin 16 bit immediate absolute reloc higher 16 bits. */ BFD_RELOC_BFIN_16_HIGH, /* ADI Blackfin 'a' part of LSETUP. */ BFD_RELOC_BFIN_4_PCREL, /* ADI Blackfin. */ BFD_RELOC_BFIN_5_PCREL, /* ADI Blackfin 16 bit immediate absolute reloc lower 16 bits. */ BFD_RELOC_BFIN_16_LOW, /* ADI Blackfin. */ BFD_RELOC_BFIN_10_PCREL, /* ADI Blackfin 'b' part of LSETUP. */ BFD_RELOC_BFIN_11_PCREL, /* ADI Blackfin. */ BFD_RELOC_BFIN_12_PCREL_JUMP, /* ADI Blackfin Short jump, pcrel. */ BFD_RELOC_BFIN_12_PCREL_JUMP_S, /* ADI Blackfin Call.x not implemented. */ BFD_RELOC_BFIN_24_PCREL_CALL_X, /* 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, /* ADI Blackfin PLTPC relocation. */ BFD_RELOC_BFIN_PLTPC, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_PUSH, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_CONST, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_ADD, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_SUB, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_MULT, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_DIV, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_MOD, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_LSHIFT, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_RSHIFT, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_AND, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_OR, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_XOR, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_LAND, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_LOR, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_LEN, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_NEG, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_COMP, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_PAGE, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_HWPAGE, /* ADI Blackfin arithmetic relocation. */ BFD_ARELOC_BFIN_ADDR, /* Mitsubishi D10V relocs. This is a 10-bit reloc with the right 2 bits assumed to be 0. */ BFD_RELOC_D10V_10_PCREL_R, /* Mitsubishi D10V relocs. This is a 10-bit reloc with the right 2 bits assumed to be 0. This is the same as the previous reloc except it is in the left container, i.e., shifted left 15 bits. */ BFD_RELOC_D10V_10_PCREL_L, /* This is an 18-bit reloc with the right 2 bits assumed to be 0. */ BFD_RELOC_D10V_18, /* This is an 18-bit reloc with the right 2 bits assumed to be 0. */ BFD_RELOC_D10V_18_PCREL, /* Mitsubishi D30V relocs. This is a 6-bit absolute reloc. */ BFD_RELOC_D30V_6, /* This is a 6-bit pc-relative reloc with the right 3 bits assumed to be 0. */ BFD_RELOC_D30V_9_PCREL, /* This is a 6-bit pc-relative reloc with the right 3 bits assumed to be 0. Same as the previous reloc but on the right side of the container. */ BFD_RELOC_D30V_9_PCREL_R, /* This is a 12-bit absolute reloc with the right 3 bitsassumed to be 0. */ BFD_RELOC_D30V_15, /* This is a 12-bit pc-relative reloc with the right 3 bits assumed to be 0. */ BFD_RELOC_D30V_15_PCREL, /* This is a 12-bit pc-relative reloc with the right 3 bits assumed to be 0. Same as the previous reloc but on the right side of the container. */ BFD_RELOC_D30V_15_PCREL_R, /* This is an 18-bit absolute reloc with the right 3 bits assumed to be 0. */ BFD_RELOC_D30V_21, /* This is an 18-bit pc-relative reloc with the right 3 bits assumed to be 0. */ BFD_RELOC_D30V_21_PCREL, /* This is an 18-bit pc-relative reloc with the right 3 bits assumed to be 0. Same as the previous reloc but on the right side of the container. */ BFD_RELOC_D30V_21_PCREL_R, /* This is a 32-bit absolute reloc. */ BFD_RELOC_D30V_32, /* This is a 32-bit pc-relative reloc. */ BFD_RELOC_D30V_32_PCREL, /* DLX relocs */ BFD_RELOC_DLX_HI16_S, /* DLX relocs */ BFD_RELOC_DLX_LO16, /* DLX relocs */ BFD_RELOC_DLX_JMP26, /* Renesas M16C/M32C Relocations. */ BFD_RELOC_M32C_HI8, BFD_RELOC_M32C_RL_JUMP, BFD_RELOC_M32C_RL_1ADDR, BFD_RELOC_M32C_RL_2ADDR, /* Renesas M32R (formerly Mitsubishi M32R) relocs. This is a 24 bit absolute address. */ BFD_RELOC_M32R_24, /* This is a 10-bit pc-relative reloc with the right 2 bits assumed to be 0. */ BFD_RELOC_M32R_10_PCREL, /* This is an 18-bit reloc with the right 2 bits assumed to be 0. */ BFD_RELOC_M32R_18_PCREL, /* This is a 26-bit reloc with the right 2 bits assumed to be 0. */ BFD_RELOC_M32R_26_PCREL, /* This is a 16-bit reloc containing the high 16 bits of an address used when the lower 16 bits are treated as unsigned. */ BFD_RELOC_M32R_HI16_ULO, /* This is a 16-bit reloc containing the high 16 bits of an address used when the lower 16 bits are treated as signed. */ BFD_RELOC_M32R_HI16_SLO, /* This is a 16-bit reloc containing the lower 16 bits of an address. */ BFD_RELOC_M32R_LO16, /* This is a 16-bit reloc containing the small data area offset for use in add3, load, and store instructions. */ BFD_RELOC_M32R_SDA16, /* For PIC. */ BFD_RELOC_M32R_GOT24, BFD_RELOC_M32R_26_PLTREL, BFD_RELOC_M32R_COPY, BFD_RELOC_M32R_GLOB_DAT, BFD_RELOC_M32R_JMP_SLOT, BFD_RELOC_M32R_RELATIVE, BFD_RELOC_M32R_GOTOFF, BFD_RELOC_M32R_GOTOFF_HI_ULO, BFD_RELOC_M32R_GOTOFF_HI_SLO, BFD_RELOC_M32R_GOTOFF_LO, BFD_RELOC_M32R_GOTPC24, BFD_RELOC_M32R_GOT16_HI_ULO, BFD_RELOC_M32R_GOT16_HI_SLO, BFD_RELOC_M32R_GOT16_LO, BFD_RELOC_M32R_GOTPC_HI_ULO, BFD_RELOC_M32R_GOTPC_HI_SLO, BFD_RELOC_M32R_GOTPC_LO, /* This is a 9-bit reloc */ BFD_RELOC_V850_9_PCREL, /* This is a 22-bit reloc */ BFD_RELOC_V850_22_PCREL, /* This is a 16 bit offset from the short data area pointer. */ BFD_RELOC_V850_SDA_16_16_OFFSET, /* This is a 16 bit offset (of which only 15 bits are used) from the short data area pointer. */ BFD_RELOC_V850_SDA_15_16_OFFSET, /* This is a 16 bit offset from the zero data area pointer. */ BFD_RELOC_V850_ZDA_16_16_OFFSET, /* This is a 16 bit offset (of which only 15 bits are used) from the zero data area pointer. */ BFD_RELOC_V850_ZDA_15_16_OFFSET, /* This is an 8 bit offset (of which only 6 bits are used) from the tiny data area pointer. */ BFD_RELOC_V850_TDA_6_8_OFFSET, /* This is an 8bit offset (of which only 7 bits are used) from the tiny data area pointer. */ BFD_RELOC_V850_TDA_7_8_OFFSET, /* This is a 7 bit offset from the tiny data area pointer. */ BFD_RELOC_V850_TDA_7_7_OFFSET, /* This is a 16 bit offset from the tiny data area pointer. */ BFD_RELOC_V850_TDA_16_16_OFFSET, /* This is a 5 bit offset (of which only 4 bits are used) from the tiny data area pointer. */ BFD_RELOC_V850_TDA_4_5_OFFSET, /* This is a 4 bit offset from the tiny data area pointer. */ BFD_RELOC_V850_TDA_4_4_OFFSET, /* This is a 16 bit offset from the short data area pointer, with the bits placed non-contiguously in the instruction. */ BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET, /* This is a 16 bit offset from the zero data area pointer, with the bits placed non-contiguously in the instruction. */ BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET, /* This is a 6 bit offset from the call table base pointer. */ BFD_RELOC_V850_CALLT_6_7_OFFSET, /* This is a 16 bit offset from the call table base pointer. */ BFD_RELOC_V850_CALLT_16_16_OFFSET, /* Used for relaxing indirect function calls. */ BFD_RELOC_V850_LONGCALL, /* Used for relaxing indirect jumps. */ BFD_RELOC_V850_LONGJUMP, /* Used to maintain alignment whilst relaxing. */ BFD_RELOC_V850_ALIGN, /* This is a variation of BFD_RELOC_LO16 that can be used in v850e ld.bu instructions. */ BFD_RELOC_V850_LO16_SPLIT_OFFSET, /* This is a 32bit pcrel reloc for the mn10300, offset by two bytes in the instruction. */ BFD_RELOC_MN10300_32_PCREL, /* This is a 16bit pcrel reloc for the mn10300, offset by two bytes in the instruction. */ BFD_RELOC_MN10300_16_PCREL, /* This is a 8bit DP reloc for the tms320c30, where the most significant 8 bits of a 24 bit word are placed into the least significant 8 bits of the opcode. */ BFD_RELOC_TIC30_LDP, /* This is a 7bit reloc for the tms320c54x, where the least significant 7 bits of a 16 bit word are placed into the least significant 7 bits of the opcode. */ BFD_RELOC_TIC54X_PARTLS7, /* This is a 9bit DP reloc for the tms320c54x, where the most significant 9 bits of a 16 bit word are placed into the least significant 9 bits of the opcode. */ BFD_RELOC_TIC54X_PARTMS9, /* This is an extended address 23-bit reloc for the tms320c54x. */ BFD_RELOC_TIC54X_23, /* This is a 16-bit reloc for the tms320c54x, where the least significant 16 bits of a 23-bit extended address are placed into the opcode. */ BFD_RELOC_TIC54X_16_OF_23, /* This is a reloc for the tms320c54x, where the most significant 7 bits of a 23-bit extended address are placed into the opcode. */ BFD_RELOC_TIC54X_MS7_OF_23, /* This is a 48 bit reloc for the FR30 that stores 32 bits. */ BFD_RELOC_FR30_48, /* This is a 32 bit reloc for the FR30 that stores 20 bits split up into two sections. */ BFD_RELOC_FR30_20, /* This is a 16 bit reloc for the FR30 that stores a 6 bit word offset in 4 bits. */ BFD_RELOC_FR30_6_IN_4, /* This is a 16 bit reloc for the FR30 that stores an 8 bit byte offset into 8 bits. */ BFD_RELOC_FR30_8_IN_8, /* This is a 16 bit reloc for the FR30 that stores a 9 bit short offset into 8 bits. */ BFD_RELOC_FR30_9_IN_8, /* This is a 16 bit reloc for the FR30 that stores a 10 bit word offset into 8 bits. */ BFD_RELOC_FR30_10_IN_8, /* This is a 16 bit reloc for the FR30 that stores a 9 bit pc relative short offset into 8 bits. */ BFD_RELOC_FR30_9_PCREL, /* This is a 16 bit reloc for the FR30 that stores a 12 bit pc relative short offset into 11 bits. */ BFD_RELOC_FR30_12_PCREL, /* Motorola Mcore relocations. */ BFD_RELOC_MCORE_PCREL_IMM8BY4, BFD_RELOC_MCORE_PCREL_IMM11BY2, BFD_RELOC_MCORE_PCREL_IMM4BY2, BFD_RELOC_MCORE_PCREL_32, BFD_RELOC_MCORE_PCREL_JSR_IMM11BY2, BFD_RELOC_MCORE_RVA, /* Toshiba Media Processor Relocations. */ BFD_RELOC_MEP_8, BFD_RELOC_MEP_16, BFD_RELOC_MEP_32, BFD_RELOC_MEP_PCREL8A2, BFD_RELOC_MEP_PCREL12A2, BFD_RELOC_MEP_PCREL17A2, BFD_RELOC_MEP_PCREL24A2, BFD_RELOC_MEP_PCABS24A2, BFD_RELOC_MEP_LOW16, BFD_RELOC_MEP_HI16U, BFD_RELOC_MEP_HI16S, BFD_RELOC_MEP_GPREL, BFD_RELOC_MEP_TPREL, BFD_RELOC_MEP_TPREL7, BFD_RELOC_MEP_TPREL7A2, BFD_RELOC_MEP_TPREL7A4, BFD_RELOC_MEP_UIMM24, BFD_RELOC_MEP_ADDR24A4, BFD_RELOC_MEP_GNU_VTINHERIT, BFD_RELOC_MEP_GNU_VTENTRY, /* These are relocations for the GETA instruction. */ BFD_RELOC_MMIX_GETA, BFD_RELOC_MMIX_GETA_1, BFD_RELOC_MMIX_GETA_2, BFD_RELOC_MMIX_GETA_3, /* These are relocations for a conditional branch instruction. */ BFD_RELOC_MMIX_CBRANCH, BFD_RELOC_MMIX_CBRANCH_J, BFD_RELOC_MMIX_CBRANCH_1, BFD_RELOC_MMIX_CBRANCH_2, BFD_RELOC_MMIX_CBRANCH_3, /* These are relocations for the PUSHJ instruction. */ BFD_RELOC_MMIX_PUSHJ, BFD_RELOC_MMIX_PUSHJ_1, BFD_RELOC_MMIX_PUSHJ_2, BFD_RELOC_MMIX_PUSHJ_3, BFD_RELOC_MMIX_PUSHJ_STUBBABLE, /* These are relocations for the JMP instruction. */ BFD_RELOC_MMIX_JMP, BFD_RELOC_MMIX_JMP_1, BFD_RELOC_MMIX_JMP_2, BFD_RELOC_MMIX_JMP_3, /* This is a relocation for a relative address as in a GETA instruction or a branch. */ BFD_RELOC_MMIX_ADDR19, /* This is a relocation for a relative address as in a JMP instruction. */ BFD_RELOC_MMIX_ADDR27, /* This is a relocation for an instruction field that may be a general register or a value 0..255. */ BFD_RELOC_MMIX_REG_OR_BYTE, /* This is a relocation for an instruction field that may be a general register. */ BFD_RELOC_MMIX_REG, /* This is a relocation for two instruction fields holding a register and an offset, the equivalent of the relocation. */ BFD_RELOC_MMIX_BASE_PLUS_OFFSET, /* This relocation is an assertion that the expression is not allocated as a global register. It does not modify contents. */ BFD_RELOC_MMIX_LOCAL, /* This is a 16 bit reloc for the AVR that stores 8 bit pc relative short offset into 7 bits. */ BFD_RELOC_AVR_7_PCREL, /* This is a 16 bit reloc for the AVR that stores 13 bit pc relative short offset into 12 bits. */ BFD_RELOC_AVR_13_PCREL, /* This is a 16 bit reloc for the AVR that stores 17 bit value (usually program memory address) into 16 bits. */ BFD_RELOC_AVR_16_PM, /* This is a 16 bit reloc for the AVR that stores 8 bit value (usually data memory address) into 8 bit immediate value of LDI insn. */ BFD_RELOC_AVR_LO8_LDI, /* This is a 16 bit reloc for the AVR that stores 8 bit value (high 8 bit of data memory address) into 8 bit immediate value of LDI insn. */ BFD_RELOC_AVR_HI8_LDI, /* This is a 16 bit reloc for the AVR that stores 8 bit value (most high 8 bit of program memory address) into 8 bit immediate value of LDI insn. */ BFD_RELOC_AVR_HH8_LDI, /* This is a 16 bit reloc for the AVR that stores 8 bit value (most high 8 bit of 32 bit value) into 8 bit immediate value of LDI insn. */ BFD_RELOC_AVR_MS8_LDI, /* This is a 16 bit reloc for the AVR that stores negated 8 bit value (usually data memory address) into 8 bit immediate value of SUBI insn. */ BFD_RELOC_AVR_LO8_LDI_NEG, /* This is a 16 bit reloc for the AVR that stores negated 8 bit value (high 8 bit of data memory address) into 8 bit immediate value of SUBI insn. */ BFD_RELOC_AVR_HI8_LDI_NEG, /* This is a 16 bit reloc for the AVR that stores negated 8 bit value (most high 8 bit of program memory address) into 8 bit immediate value of LDI or SUBI insn. */ BFD_RELOC_AVR_HH8_LDI_NEG, /* This is a 16 bit reloc for the AVR that stores negated 8 bit value (msb of 32 bit value) into 8 bit immediate value of LDI insn. */ BFD_RELOC_AVR_MS8_LDI_NEG, /* This is a 16 bit reloc for the AVR that stores 8 bit value (usually command address) into 8 bit immediate value of LDI insn. */ BFD_RELOC_AVR_LO8_LDI_PM, /* This is a 16 bit reloc for the AVR that stores 8 bit value (command address) into 8 bit immediate value of LDI insn. If the address is beyond the 128k boundary, the linker inserts a jump stub for this reloc in the lower 128k. */ BFD_RELOC_AVR_LO8_LDI_GS, /* This is a 16 bit reloc for the AVR that stores 8 bit value (high 8 bit of command address) into 8 bit immediate value of LDI insn. */ BFD_RELOC_AVR_HI8_LDI_PM, /* This is a 16 bit reloc for the AVR that stores 8 bit value (high 8 bit of command address) into 8 bit immediate value of LDI insn. If the address is beyond the 128k boundary, the linker inserts a jump stub for this reloc below 128k. */ BFD_RELOC_AVR_HI8_LDI_GS, /* This is a 16 bit reloc for the AVR that stores 8 bit value (most high 8 bit of command address) into 8 bit immediate value of LDI insn. */ BFD_RELOC_AVR_HH8_LDI_PM, /* This is a 16 bit reloc for the AVR that stores negated 8 bit value (usually command address) into 8 bit immediate value of SUBI insn. */ BFD_RELOC_AVR_LO8_LDI_PM_NEG, /* This is a 16 bit reloc for the AVR that stores negated 8 bit value (high 8 bit of 16 bit command address) into 8 bit immediate value of SUBI insn. */ BFD_RELOC_AVR_HI8_LDI_PM_NEG, /* This is a 16 bit reloc for the AVR that stores negated 8 bit value (high 6 bit of 22 bit command address) into 8 bit immediate value of SUBI insn. */ BFD_RELOC_AVR_HH8_LDI_PM_NEG, /* This is a 32 bit reloc for the AVR that stores 23 bit value into 22 bits. */ BFD_RELOC_AVR_CALL, /* This is a 16 bit reloc for the AVR that stores all needed bits for absolute addressing with ldi with overflow check to linktime */ BFD_RELOC_AVR_LDI, /* This is a 6 bit reloc for the AVR that stores offset for ldd/std instructions */ BFD_RELOC_AVR_6, /* This is a 6 bit reloc for the AVR that stores offset for adiw/sbiw instructions */ BFD_RELOC_AVR_6_ADIW, /* Direct 12 bit. */ BFD_RELOC_390_12, /* 12 bit GOT offset. */ BFD_RELOC_390_GOT12, /* 32 bit PC relative PLT address. */ BFD_RELOC_390_PLT32, /* Copy symbol at runtime. */ BFD_RELOC_390_COPY, /* Create GOT entry. */ BFD_RELOC_390_GLOB_DAT, /* Create PLT entry. */ BFD_RELOC_390_JMP_SLOT, /* Adjust by program base. */ BFD_RELOC_390_RELATIVE, /* 32 bit PC relative offset to GOT. */ BFD_RELOC_390_GOTPC, /* 16 bit GOT offset. */ BFD_RELOC_390_GOT16, /* PC relative 16 bit shifted by 1. */ BFD_RELOC_390_PC16DBL, /* 16 bit PC rel. PLT shifted by 1. */ BFD_RELOC_390_PLT16DBL, /* PC relative 32 bit shifted by 1. */ BFD_RELOC_390_PC32DBL, /* 32 bit PC rel. PLT shifted by 1. */ BFD_RELOC_390_PLT32DBL, /* 32 bit PC rel. GOT shifted by 1. */ BFD_RELOC_390_GOTPCDBL, /* 64 bit GOT offset. */ BFD_RELOC_390_GOT64, /* 64 bit PC relative PLT address. */ BFD_RELOC_390_PLT64, /* 32 bit rel. offset to GOT entry. */ BFD_RELOC_390_GOTENT, /* 64 bit offset to GOT. */ BFD_RELOC_390_GOTOFF64, /* 12-bit offset to symbol-entry within GOT, with PLT handling. */ BFD_RELOC_390_GOTPLT12, /* 16-bit offset to symbol-entry within GOT, with PLT handling. */ BFD_RELOC_390_GOTPLT16, /* 32-bit offset to symbol-entry within GOT, with PLT handling. */ BFD_RELOC_390_GOTPLT32, /* 64-bit offset to symbol-entry within GOT, with PLT handling. */ BFD_RELOC_390_GOTPLT64, /* 32-bit rel. offset to symbol-entry within GOT, with PLT handling. */ BFD_RELOC_390_GOTPLTENT, /* 16-bit rel. offset from the GOT to a PLT entry. */ BFD_RELOC_390_PLTOFF16, /* 32-bit rel. offset from the GOT to a PLT entry. */ BFD_RELOC_390_PLTOFF32, /* 64-bit rel. offset from the GOT to a PLT entry. */ BFD_RELOC_390_PLTOFF64, /* s390 tls relocations. */ BFD_RELOC_390_TLS_LOAD, BFD_RELOC_390_TLS_GDCALL, BFD_RELOC_390_TLS_LDCALL, BFD_RELOC_390_TLS_GD32, BFD_RELOC_390_TLS_GD64, BFD_RELOC_390_TLS_GOTIE12, BFD_RELOC_390_TLS_GOTIE32, BFD_RELOC_390_TLS_GOTIE64, BFD_RELOC_390_TLS_LDM32, BFD_RELOC_390_TLS_LDM64, BFD_RELOC_390_TLS_IE32, BFD_RELOC_390_TLS_IE64, BFD_RELOC_390_TLS_IEENT, BFD_RELOC_390_TLS_LE32, BFD_RELOC_390_TLS_LE64, BFD_RELOC_390_TLS_LDO32, BFD_RELOC_390_TLS_LDO64, BFD_RELOC_390_TLS_DTPMOD, BFD_RELOC_390_TLS_DTPOFF, BFD_RELOC_390_TLS_TPOFF, /* Long displacement extension. */ BFD_RELOC_390_20, BFD_RELOC_390_GOT20, BFD_RELOC_390_GOTPLT20, BFD_RELOC_390_TLS_GOTIE20, /* Score relocations */ BFD_RELOC_SCORE_DUMMY1, /* Low 16 bit for load/store */ BFD_RELOC_SCORE_GPREL15, /* This is a 24-bit reloc with the right 1 bit assumed to be 0 */ BFD_RELOC_SCORE_DUMMY2, BFD_RELOC_SCORE_JMP, /* This is a 19-bit reloc with the right 1 bit assumed to be 0 */ BFD_RELOC_SCORE_BRANCH, /* This is a 11-bit reloc with the right 1 bit assumed to be 0 */ BFD_RELOC_SCORE16_JMP, /* This is a 8-bit reloc with the right 1 bit assumed to be 0 */ BFD_RELOC_SCORE16_BRANCH, /* Undocumented Score relocs */ BFD_RELOC_SCORE_GOT15, BFD_RELOC_SCORE_GOT_LO16, BFD_RELOC_SCORE_CALL15, BFD_RELOC_SCORE_DUMMY_HI16, /* Scenix IP2K - 9-bit register number / data address */ BFD_RELOC_IP2K_FR9, /* Scenix IP2K - 4-bit register/data bank number */ BFD_RELOC_IP2K_BANK, /* Scenix IP2K - low 13 bits of instruction word address */ BFD_RELOC_IP2K_ADDR16CJP, /* Scenix IP2K - high 3 bits of instruction word address */ BFD_RELOC_IP2K_PAGE3, /* Scenix IP2K - ext/low/high 8 bits of data address */ BFD_RELOC_IP2K_LO8DATA, BFD_RELOC_IP2K_HI8DATA, BFD_RELOC_IP2K_EX8DATA, /* Scenix IP2K - low/high 8 bits of instruction word address */ BFD_RELOC_IP2K_LO8INSN, BFD_RELOC_IP2K_HI8INSN, /* Scenix IP2K - even/odd PC modifier to modify snb pcl.0 */ BFD_RELOC_IP2K_PC_SKIP, /* Scenix IP2K - 16 bit word address in text section. */ BFD_RELOC_IP2K_TEXT, /* Scenix IP2K - 7-bit sp or dp offset */ BFD_RELOC_IP2K_FR_OFFSET, /* Scenix VPE4K coprocessor - data/insn-space addressing */ BFD_RELOC_VPE4KMATH_DATA, BFD_RELOC_VPE4KMATH_INSN, /* These two relocations are used by the linker to determine which of the entries in a C++ virtual function table are actually used. When the --gc-sections option is given, the linker will zero out the entries that are not used, so that the code for those functions need not be included in the output. VTABLE_INHERIT is a zero-space relocation used to describe to the linker the inheritance tree of a C++ virtual function table. The relocation's symbol should be the parent class' vtable, and the relocation should be located at the child vtable. VTABLE_ENTRY is a zero-space relocation that describes the use of a virtual function table entry. The reloc's symbol should refer to the table of the class mentioned in the code. Off of that base, an offset describes the entry that is being used. For Rela hosts, this offset is stored in the reloc's addend. For Rel hosts, we are forced to put this offset in the reloc's section offset. */ BFD_RELOC_VTABLE_INHERIT, BFD_RELOC_VTABLE_ENTRY, /* Intel IA64 Relocations. */ BFD_RELOC_IA64_IMM14, BFD_RELOC_IA64_IMM22, BFD_RELOC_IA64_IMM64, BFD_RELOC_IA64_DIR32MSB, BFD_RELOC_IA64_DIR32LSB, BFD_RELOC_IA64_DIR64MSB, BFD_RELOC_IA64_DIR64LSB, BFD_RELOC_IA64_GPREL22, BFD_RELOC_IA64_GPREL64I, BFD_RELOC_IA64_GPREL32MSB, BFD_RELOC_IA64_GPREL32LSB, BFD_RELOC_IA64_GPREL64MSB, BFD_RELOC_IA64_GPREL64LSB, BFD_RELOC_IA64_LTOFF22, BFD_RELOC_IA64_LTOFF64I, BFD_RELOC_IA64_PLTOFF22, BFD_RELOC_IA64_PLTOFF64I, BFD_RELOC_IA64_PLTOFF64MSB, BFD_RELOC_IA64_PLTOFF64LSB, BFD_RELOC_IA64_FPTR64I, BFD_RELOC_IA64_FPTR32MSB, BFD_RELOC_IA64_FPTR32LSB, BFD_RELOC_IA64_FPTR64MSB, BFD_RELOC_IA64_FPTR64LSB, BFD_RELOC_IA64_PCREL21B, BFD_RELOC_IA64_PCREL21BI, BFD_RELOC_IA64_PCREL21M, BFD_RELOC_IA64_PCREL21F, BFD_RELOC_IA64_PCREL22, BFD_RELOC_IA64_PCREL60B, BFD_RELOC_IA64_PCREL64I, BFD_RELOC_IA64_PCREL32MSB, BFD_RELOC_IA64_PCREL32LSB, BFD_RELOC_IA64_PCREL64MSB, BFD_RELOC_IA64_PCREL64LSB, BFD_RELOC_IA64_LTOFF_FPTR22, BFD_RELOC_IA64_LTOFF_FPTR64I, BFD_RELOC_IA64_LTOFF_FPTR32MSB, BFD_RELOC_IA64_LTOFF_FPTR32LSB, BFD_RELOC_IA64_LTOFF_FPTR64MSB, BFD_RELOC_IA64_LTOFF_FPTR64LSB, BFD_RELOC_IA64_SEGREL32MSB, BFD_RELOC_IA64_SEGREL32LSB, BFD_RELOC_IA64_SEGREL64MSB, BFD_RELOC_IA64_SEGREL64LSB, BFD_RELOC_IA64_SECREL32MSB, BFD_RELOC_IA64_SECREL32LSB, BFD_RELOC_IA64_SECREL64MSB, BFD_RELOC_IA64_SECREL64LSB, BFD_RELOC_IA64_REL32MSB, BFD_RELOC_IA64_REL32LSB, BFD_RELOC_IA64_REL64MSB, BFD_RELOC_IA64_REL64LSB, BFD_RELOC_IA64_LTV32MSB, BFD_RELOC_IA64_LTV32LSB, BFD_RELOC_IA64_LTV64MSB, BFD_RELOC_IA64_LTV64LSB, BFD_RELOC_IA64_IPLTMSB, BFD_RELOC_IA64_IPLTLSB, BFD_RELOC_IA64_COPY, BFD_RELOC_IA64_LTOFF22X, BFD_RELOC_IA64_LDXMOV, BFD_RELOC_IA64_TPREL14, BFD_RELOC_IA64_TPREL22, BFD_RELOC_IA64_TPREL64I, BFD_RELOC_IA64_TPREL64MSB, BFD_RELOC_IA64_TPREL64LSB, BFD_RELOC_IA64_LTOFF_TPREL22, BFD_RELOC_IA64_DTPMOD64MSB, BFD_RELOC_IA64_DTPMOD64LSB, BFD_RELOC_IA64_LTOFF_DTPMOD22, BFD_RELOC_IA64_DTPREL14, BFD_RELOC_IA64_DTPREL22, BFD_RELOC_IA64_DTPREL64I, BFD_RELOC_IA64_DTPREL32MSB, BFD_RELOC_IA64_DTPREL32LSB, BFD_RELOC_IA64_DTPREL64MSB, BFD_RELOC_IA64_DTPREL64LSB, BFD_RELOC_IA64_LTOFF_DTPREL22, /* Motorola 68HC11 reloc. This is the 8 bit high part of an absolute address. */ BFD_RELOC_M68HC11_HI8, /* Motorola 68HC11 reloc. This is the 8 bit low part of an absolute address. */ BFD_RELOC_M68HC11_LO8, /* Motorola 68HC11 reloc. This is the 3 bit of a value. */ BFD_RELOC_M68HC11_3B, /* Motorola 68HC11 reloc. This reloc marks the beginning of a jump/call instruction. It is used for linker relaxation to correctly identify beginning of instruction and change some branches to use PC-relative addressing mode. */ BFD_RELOC_M68HC11_RL_JUMP, /* Motorola 68HC11 reloc. This reloc marks a group of several instructions that gcc generates and for which the linker relaxation pass can modify and/or remove some of them. */ BFD_RELOC_M68HC11_RL_GROUP, /* Motorola 68HC11 reloc. This is the 16-bit lower part of an address. It is used for 'call' instruction to specify the symbol address without any special transformation (due to memory bank window). */ BFD_RELOC_M68HC11_LO16, /* Motorola 68HC11 reloc. This is a 8-bit reloc that specifies the page number of an address. It is used by 'call' instruction to specify the page number of the symbol. */ BFD_RELOC_M68HC11_PAGE, /* Motorola 68HC11 reloc. This is a 24-bit reloc that represents the address with a 16-bit value and a 8-bit page number. The symbol address is transformed to follow the 16K memory bank of 68HC12 (seen as mapped in the window). */ BFD_RELOC_M68HC11_24, /* Motorola 68HC12 reloc. This is the 5 bits of a value. */ BFD_RELOC_M68HC12_5B, /* NS CR16C Relocations. */ BFD_RELOC_16C_NUM08, BFD_RELOC_16C_NUM08_C, BFD_RELOC_16C_NUM16, BFD_RELOC_16C_NUM16_C, BFD_RELOC_16C_NUM32, BFD_RELOC_16C_NUM32_C, BFD_RELOC_16C_DISP04, BFD_RELOC_16C_DISP04_C, BFD_RELOC_16C_DISP08, BFD_RELOC_16C_DISP08_C, BFD_RELOC_16C_DISP16, BFD_RELOC_16C_DISP16_C, BFD_RELOC_16C_DISP24, BFD_RELOC_16C_DISP24_C, BFD_RELOC_16C_DISP24a, BFD_RELOC_16C_DISP24a_C, BFD_RELOC_16C_REG04, BFD_RELOC_16C_REG04_C, BFD_RELOC_16C_REG04a, BFD_RELOC_16C_REG04a_C, BFD_RELOC_16C_REG14, BFD_RELOC_16C_REG14_C, BFD_RELOC_16C_REG16, BFD_RELOC_16C_REG16_C, BFD_RELOC_16C_REG20, BFD_RELOC_16C_REG20_C, BFD_RELOC_16C_ABS20, BFD_RELOC_16C_ABS20_C, BFD_RELOC_16C_ABS24, BFD_RELOC_16C_ABS24_C, BFD_RELOC_16C_IMM04, BFD_RELOC_16C_IMM04_C, BFD_RELOC_16C_IMM16, BFD_RELOC_16C_IMM16_C, BFD_RELOC_16C_IMM20, BFD_RELOC_16C_IMM20_C, BFD_RELOC_16C_IMM24, BFD_RELOC_16C_IMM24_C, BFD_RELOC_16C_IMM32, BFD_RELOC_16C_IMM32_C, /* NS CR16 Relocations. */ BFD_RELOC_CR16_NUM8, BFD_RELOC_CR16_NUM16, BFD_RELOC_CR16_NUM32, BFD_RELOC_CR16_NUM32a, BFD_RELOC_CR16_REGREL0, BFD_RELOC_CR16_REGREL4, BFD_RELOC_CR16_REGREL4a, BFD_RELOC_CR16_REGREL14, BFD_RELOC_CR16_REGREL14a, BFD_RELOC_CR16_REGREL16, BFD_RELOC_CR16_REGREL20, BFD_RELOC_CR16_REGREL20a, BFD_RELOC_CR16_ABS20, BFD_RELOC_CR16_ABS24, BFD_RELOC_CR16_IMM4, BFD_RELOC_CR16_IMM8, BFD_RELOC_CR16_IMM16, BFD_RELOC_CR16_IMM20, BFD_RELOC_CR16_IMM24, BFD_RELOC_CR16_IMM32, BFD_RELOC_CR16_IMM32a, BFD_RELOC_CR16_DISP4, BFD_RELOC_CR16_DISP8, BFD_RELOC_CR16_DISP16, BFD_RELOC_CR16_DISP20, BFD_RELOC_CR16_DISP24, BFD_RELOC_CR16_DISP24a, /* NS CRX Relocations. */ BFD_RELOC_CRX_REL4, BFD_RELOC_CRX_REL8, BFD_RELOC_CRX_REL8_CMP, BFD_RELOC_CRX_REL16, BFD_RELOC_CRX_REL24, BFD_RELOC_CRX_REL32, BFD_RELOC_CRX_REGREL12, BFD_RELOC_CRX_REGREL22, BFD_RELOC_CRX_REGREL28, BFD_RELOC_CRX_REGREL32, BFD_RELOC_CRX_ABS16, BFD_RELOC_CRX_ABS32, BFD_RELOC_CRX_NUM8, BFD_RELOC_CRX_NUM16, BFD_RELOC_CRX_NUM32, BFD_RELOC_CRX_IMM16, BFD_RELOC_CRX_IMM32, BFD_RELOC_CRX_SWITCH8, BFD_RELOC_CRX_SWITCH16, BFD_RELOC_CRX_SWITCH32, /* These relocs are only used within the CRIS assembler. They are not (at present) written to any object files. */ BFD_RELOC_CRIS_BDISP8, BFD_RELOC_CRIS_UNSIGNED_5, BFD_RELOC_CRIS_SIGNED_6, BFD_RELOC_CRIS_UNSIGNED_6, BFD_RELOC_CRIS_SIGNED_8, BFD_RELOC_CRIS_UNSIGNED_8, BFD_RELOC_CRIS_SIGNED_16, BFD_RELOC_CRIS_UNSIGNED_16, BFD_RELOC_CRIS_LAPCQ_OFFSET, BFD_RELOC_CRIS_UNSIGNED_4, /* Relocs used in ELF shared libraries for CRIS. */ BFD_RELOC_CRIS_COPY, BFD_RELOC_CRIS_GLOB_DAT, BFD_RELOC_CRIS_JUMP_SLOT, BFD_RELOC_CRIS_RELATIVE, /* 32-bit offset to symbol-entry within GOT. */ BFD_RELOC_CRIS_32_GOT, /* 16-bit offset to symbol-entry within GOT. */ BFD_RELOC_CRIS_16_GOT, /* 32-bit offset to symbol-entry within GOT, with PLT handling. */ BFD_RELOC_CRIS_32_GOTPLT, /* 16-bit offset to symbol-entry within GOT, with PLT handling. */ BFD_RELOC_CRIS_16_GOTPLT, /* 32-bit offset to symbol, relative to GOT. */ BFD_RELOC_CRIS_32_GOTREL, /* 32-bit offset to symbol with PLT entry, relative to GOT. */ BFD_RELOC_CRIS_32_PLT_GOTREL, /* 32-bit offset to symbol with PLT entry, relative to this relocation. */ BFD_RELOC_CRIS_32_PLT_PCREL, /* Intel i860 Relocations. */ BFD_RELOC_860_COPY, BFD_RELOC_860_GLOB_DAT, BFD_RELOC_860_JUMP_SLOT, BFD_RELOC_860_RELATIVE, BFD_RELOC_860_PC26, BFD_RELOC_860_PLT26, BFD_RELOC_860_PC16, BFD_RELOC_860_LOW0, BFD_RELOC_860_SPLIT0, BFD_RELOC_860_LOW1, BFD_RELOC_860_SPLIT1, BFD_RELOC_860_LOW2, BFD_RELOC_860_SPLIT2, BFD_RELOC_860_LOW3, BFD_RELOC_860_LOGOT0, BFD_RELOC_860_SPGOT0, BFD_RELOC_860_LOGOT1, BFD_RELOC_860_SPGOT1, BFD_RELOC_860_LOGOTOFF0, BFD_RELOC_860_SPGOTOFF0, BFD_RELOC_860_LOGOTOFF1, BFD_RELOC_860_SPGOTOFF1, BFD_RELOC_860_LOGOTOFF2, BFD_RELOC_860_LOGOTOFF3, BFD_RELOC_860_LOPC, BFD_RELOC_860_HIGHADJ, BFD_RELOC_860_HAGOT, BFD_RELOC_860_HAGOTOFF, BFD_RELOC_860_HAPC, BFD_RELOC_860_HIGH, BFD_RELOC_860_HIGOT, BFD_RELOC_860_HIGOTOFF, /* OpenRISC Relocations. */ BFD_RELOC_OPENRISC_ABS_26, BFD_RELOC_OPENRISC_REL_26, /* H8 elf Relocations. */ BFD_RELOC_H8_DIR16A8, BFD_RELOC_H8_DIR16R8, BFD_RELOC_H8_DIR24A8, BFD_RELOC_H8_DIR24R8, BFD_RELOC_H8_DIR32A16, /* Sony Xstormy16 Relocations. */ BFD_RELOC_XSTORMY16_REL_12, BFD_RELOC_XSTORMY16_12, BFD_RELOC_XSTORMY16_24, BFD_RELOC_XSTORMY16_FPTR16, /* Self-describing complex relocations. */ BFD_RELOC_RELC, /* Infineon Relocations. */ BFD_RELOC_XC16X_PAG, BFD_RELOC_XC16X_POF, BFD_RELOC_XC16X_SEG, BFD_RELOC_XC16X_SOF, /* Relocations used by VAX ELF. */ BFD_RELOC_VAX_GLOB_DAT, BFD_RELOC_VAX_JMP_SLOT, BFD_RELOC_VAX_RELATIVE, /* Morpho MT - 16 bit immediate relocation. */ BFD_RELOC_MT_PC16, /* Morpho MT - Hi 16 bits of an address. */ BFD_RELOC_MT_HI16, /* Morpho MT - Low 16 bits of an address. */ BFD_RELOC_MT_LO16, /* Morpho MT - Used to tell the linker which vtable entries are used. */ BFD_RELOC_MT_GNU_VTINHERIT, /* Morpho MT - Used to tell the linker which vtable entries are used. */ BFD_RELOC_MT_GNU_VTENTRY, /* Morpho MT - 8 bit immediate relocation. */ BFD_RELOC_MT_PCINSN8, /* msp430 specific relocation codes */ BFD_RELOC_MSP430_10_PCREL, BFD_RELOC_MSP430_16_PCREL, BFD_RELOC_MSP430_16, BFD_RELOC_MSP430_16_PCREL_BYTE, BFD_RELOC_MSP430_16_BYTE, BFD_RELOC_MSP430_2X_PCREL, BFD_RELOC_MSP430_RL_PCREL, /* IQ2000 Relocations. */ BFD_RELOC_IQ2000_OFFSET_16, BFD_RELOC_IQ2000_OFFSET_21, BFD_RELOC_IQ2000_UHI16, /* Special Xtensa relocation used only by PLT entries in ELF shared objects to indicate that the runtime linker should set the value to one of its own internal functions or data structures. */ BFD_RELOC_XTENSA_RTLD, /* Xtensa relocations for ELF shared objects. */ BFD_RELOC_XTENSA_GLOB_DAT, BFD_RELOC_XTENSA_JMP_SLOT, BFD_RELOC_XTENSA_RELATIVE, /* Xtensa relocation used in ELF object files for symbols that may require PLT entries. Otherwise, this is just a generic 32-bit relocation. */ BFD_RELOC_XTENSA_PLT, /* Xtensa relocations to mark the difference of two local symbols. These are only needed to support linker relaxation and can be ignored when not relaxing. The field is set to the value of the difference assuming no relaxation. The relocation encodes the position of the first symbol so the linker can determine whether to adjust the field value. */ BFD_RELOC_XTENSA_DIFF8, BFD_RELOC_XTENSA_DIFF16, BFD_RELOC_XTENSA_DIFF32, /* Generic Xtensa relocations for instruction operands. Only the slot number is encoded in the relocation. The relocation applies to the last PC-relative immediate operand, or if there are no PC-relative immediates, to the last immediate operand. */ BFD_RELOC_XTENSA_SLOT0_OP, BFD_RELOC_XTENSA_SLOT1_OP, BFD_RELOC_XTENSA_SLOT2_OP, BFD_RELOC_XTENSA_SLOT3_OP, BFD_RELOC_XTENSA_SLOT4_OP, BFD_RELOC_XTENSA_SLOT5_OP, BFD_RELOC_XTENSA_SLOT6_OP, BFD_RELOC_XTENSA_SLOT7_OP, BFD_RELOC_XTENSA_SLOT8_OP, BFD_RELOC_XTENSA_SLOT9_OP, BFD_RELOC_XTENSA_SLOT10_OP, BFD_RELOC_XTENSA_SLOT11_OP, BFD_RELOC_XTENSA_SLOT12_OP, BFD_RELOC_XTENSA_SLOT13_OP, BFD_RELOC_XTENSA_SLOT14_OP, /* Alternate Xtensa relocations. Only the slot is encoded in the relocation. The meaning of these relocations is opcode-specific. */ BFD_RELOC_XTENSA_SLOT0_ALT, BFD_RELOC_XTENSA_SLOT1_ALT, BFD_RELOC_XTENSA_SLOT2_ALT, BFD_RELOC_XTENSA_SLOT3_ALT, BFD_RELOC_XTENSA_SLOT4_ALT, BFD_RELOC_XTENSA_SLOT5_ALT, BFD_RELOC_XTENSA_SLOT6_ALT, BFD_RELOC_XTENSA_SLOT7_ALT, BFD_RELOC_XTENSA_SLOT8_ALT, BFD_RELOC_XTENSA_SLOT9_ALT, BFD_RELOC_XTENSA_SLOT10_ALT, BFD_RELOC_XTENSA_SLOT11_ALT, BFD_RELOC_XTENSA_SLOT12_ALT, BFD_RELOC_XTENSA_SLOT13_ALT, BFD_RELOC_XTENSA_SLOT14_ALT, /* Xtensa relocations for backward compatibility. These have all been replaced by BFD_RELOC_XTENSA_SLOT0_OP. */ BFD_RELOC_XTENSA_OP0, BFD_RELOC_XTENSA_OP1, BFD_RELOC_XTENSA_OP2, /* Xtensa relocation to mark that the assembler expanded the instructions from an original target. The expansion size is encoded in the reloc size. */ BFD_RELOC_XTENSA_ASM_EXPAND, /* Xtensa relocation to mark that the linker should simplify assembler-expanded instructions. This is commonly used internally by the linker after analysis of a BFD_RELOC_XTENSA_ASM_EXPAND. */ BFD_RELOC_XTENSA_ASM_SIMPLIFY, /* 8 bit signed offset in (ix+d) or (iy+d). */ BFD_RELOC_Z80_DISP8, /* DJNZ offset. */ BFD_RELOC_Z8K_DISP7, /* CALR offset. */ BFD_RELOC_Z8K_CALLR, /* 4 bit value. */ BFD_RELOC_Z8K_IMM4L, BFD_RELOC_UNUSED }; typedef enum bfd_reloc_code_real bfd_reloc_code_real_type; reloc_howto_type *bfd_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code); reloc_howto_type *bfd_reloc_name_lookup (bfd *abfd, const char *reloc_name); const char *bfd_get_reloc_code_name (bfd_reloc_code_real_type code); /* Extracted from syms.c. */ typedef struct bfd_symbol { /* A pointer to the BFD which owns the symbol. This information is necessary so that a back end can work out what additional information (invisible to the application writer) is carried with the symbol. This field is *almost* redundant, since you can use section->owner instead, except that some symbols point to the global sections bfd_{abs,com,und}_section. This could be fixed by making these globals be per-bfd (or per-target-flavor). FIXME. */ struct bfd *the_bfd; /* Use bfd_asymbol_bfd(sym) to access this field. */ /* The text of the symbol. The name is left alone, and not copied; the application may not alter it. */ const char *name; /* The value of the symbol. This really should be a union of a numeric value with a pointer, since some flags indicate that a pointer to another symbol is stored here. */ symvalue value; /* Attributes of a symbol. */ #define BSF_NO_FLAGS 0x00 /* The symbol has local scope; <> in <>. The value is the offset into the section of the data. */ #define BSF_LOCAL 0x01 /* The symbol has global scope; initialized data in <>. The value is the offset into the section of the data. */ #define BSF_GLOBAL 0x02 /* The symbol has global scope and is exported. The value is the offset into the section of the data. */ #define BSF_EXPORT BSF_GLOBAL /* No real difference. */ /* A normal C symbol would be one of: <>, <>, <> or <>. */ /* The symbol is a debugging record. The value has an arbitrary meaning, unless BSF_DEBUGGING_RELOC is also set. */ #define BSF_DEBUGGING 0x08 /* The symbol denotes a function entry point. Used in ELF, perhaps others someday. */ #define BSF_FUNCTION 0x10 /* Used by the linker. */ #define BSF_KEEP 0x20 #define BSF_KEEP_G 0x40 /* A weak global symbol, overridable without warnings by a regular global symbol of the same name. */ #define BSF_WEAK 0x80 /* This symbol was created to point to a section, e.g. ELF's STT_SECTION symbols. */ #define BSF_SECTION_SYM 0x100 /* The symbol used to be a common symbol, but now it is allocated. */ #define BSF_OLD_COMMON 0x200 /* The default value for common data. */ #define BFD_FORT_COMM_DEFAULT_VALUE 0 /* In some files the type of a symbol sometimes alters its location in an output file - ie in coff a <> symbol which is also <> symbol appears where it was declared and not at the end of a section. This bit is set by the target BFD part to convey this information. */ #define BSF_NOT_AT_END 0x400 /* Signal that the symbol is the label of constructor section. */ #define BSF_CONSTRUCTOR 0x800 /* Signal that the symbol is a warning symbol. The name is a warning. The name of the next symbol is the one to warn about; if a reference is made to a symbol with the same name as the next symbol, a warning is issued by the linker. */ #define BSF_WARNING 0x1000 /* Signal that the symbol is indirect. This symbol is an indirect pointer to the symbol with the same name as the next symbol. */ #define BSF_INDIRECT 0x2000 /* BSF_FILE marks symbols that contain a file name. This is used for ELF STT_FILE symbols. */ #define BSF_FILE 0x4000 /* Symbol is from dynamic linking information. */ #define BSF_DYNAMIC 0x8000 /* The symbol denotes a data object. Used in ELF, and perhaps others someday. */ #define BSF_OBJECT 0x10000 /* This symbol is a debugging symbol. The value is the offset into the section of the data. BSF_DEBUGGING should be set as well. */ #define BSF_DEBUGGING_RELOC 0x20000 /* This symbol is thread local. Used in ELF. */ #define BSF_THREAD_LOCAL 0x40000 /* This symbol represents a complex relocation expression, with the expression tree serialized in the symbol name. */ #define BSF_RELC 0x80000 /* This symbol represents a signed complex relocation expression, with the expression tree serialized in the symbol name. */ #define BSF_SRELC 0x100000 flagword flags; /* A pointer to the section to which this symbol is relative. This will always be non NULL, there are special sections for undefined and absolute symbols. */ struct bfd_section *section; /* Back end special data. */ union { void *p; bfd_vma i; } udata; } asymbol; #define bfd_get_symtab_upper_bound(abfd) \ BFD_SEND (abfd, _bfd_get_symtab_upper_bound, (abfd)) bfd_boolean bfd_is_local_label (bfd *abfd, asymbol *sym); bfd_boolean bfd_is_local_label_name (bfd *abfd, const char *name); #define bfd_is_local_label_name(abfd, name) \ BFD_SEND (abfd, _bfd_is_local_label_name, (abfd, name)) bfd_boolean bfd_is_target_special_symbol (bfd *abfd, asymbol *sym); #define bfd_is_target_special_symbol(abfd, sym) \ BFD_SEND (abfd, _bfd_is_target_special_symbol, (abfd, sym)) #define bfd_canonicalize_symtab(abfd, location) \ BFD_SEND (abfd, _bfd_canonicalize_symtab, (abfd, location)) bfd_boolean bfd_set_symtab (bfd *abfd, asymbol **location, unsigned int count); void bfd_print_symbol_vandf (bfd *abfd, void *file, asymbol *symbol); #define bfd_make_empty_symbol(abfd) \ BFD_SEND (abfd, _bfd_make_empty_symbol, (abfd)) asymbol *_bfd_generic_make_empty_symbol (bfd *); #define bfd_make_debug_symbol(abfd,ptr,size) \ BFD_SEND (abfd, _bfd_make_debug_symbol, (abfd, ptr, size)) int bfd_decode_symclass (asymbol *symbol); bfd_boolean bfd_is_undefined_symclass (int symclass); void bfd_symbol_info (asymbol *symbol, symbol_info *ret); bfd_boolean bfd_copy_private_symbol_data (bfd *ibfd, asymbol *isym, bfd *obfd, asymbol *osym); #define bfd_copy_private_symbol_data(ibfd, isymbol, obfd, osymbol) \ BFD_SEND (obfd, _bfd_copy_private_symbol_data, \ (ibfd, isymbol, obfd, osymbol)) /* Extracted from bfd.c. */ struct bfd { /* A unique identifier of the BFD */ unsigned int id; /* The filename the application opened the BFD with. */ const char *filename; /* A pointer to the target jump table. */ const struct bfd_target *xvec; /* The IOSTREAM, and corresponding IO vector that provide access to the file backing the BFD. */ void *iostream; const struct bfd_iovec *iovec; /* Is the file descriptor being cached? That is, can it be closed as needed, and re-opened when accessed later? */ bfd_boolean cacheable; /* Marks whether there was a default target specified when the BFD was opened. This is used to select which matching algorithm to use to choose the back end. */ bfd_boolean target_defaulted; /* The caching routines use these to maintain a least-recently-used list of BFDs. */ struct bfd *lru_prev, *lru_next; /* When a file is closed by the caching routines, BFD retains state information on the file here... */ ufile_ptr where; /* ... and here: (``once'' means at least once). */ bfd_boolean opened_once; /* Set if we have a locally maintained mtime value, rather than getting it from the file each time. */ bfd_boolean mtime_set; /* File modified time, if mtime_set is TRUE. */ long mtime; /* Reserved for an unimplemented file locking extension. */ int ifd; /* The format which belongs to the BFD. (object, core, etc.) */ bfd_format format; /* The direction with which the BFD was opened. */ enum bfd_direction { no_direction = 0, read_direction = 1, write_direction = 2, both_direction = 3 } direction; /* Format_specific flags. */ flagword flags; /* Currently my_archive is tested before adding origin to anything. I believe that this can become always an add of origin, with origin set to 0 for non archive files. */ ufile_ptr origin; /* Remember when output has begun, to stop strange things from happening. */ bfd_boolean output_has_begun; /* A hash table for section names. */ struct bfd_hash_table section_htab; /* Pointer to linked list of sections. */ struct bfd_section *sections; /* The last section on the section list. */ struct bfd_section *section_last; /* The number of sections. */ unsigned int section_count; /* Stuff only useful for object files: The start address. */ bfd_vma start_address; /* Used for input and output. */ unsigned int symcount; /* Symbol table for output BFD (with symcount entries). */ struct bfd_symbol **outsymbols; /* Used for slurped dynamic symbol tables. */ unsigned int dynsymcount; /* Pointer to structure which contains architecture information. */ const struct bfd_arch_info *arch_info; /* Flag set if symbols from this BFD should not be exported. */ bfd_boolean no_export; /* Stuff only useful for archives. */ void *arelt_data; struct bfd *my_archive; /* The containing archive BFD. */ struct bfd *archive_next; /* The next BFD in the archive. */ struct bfd *archive_head; /* The first BFD in the archive. */ bfd_boolean has_armap; /* A chain of BFD structures involved in a link. */ struct bfd *link_next; /* A field used by _bfd_generic_link_add_archive_symbols. This will be used only for archive elements. */ int archive_pass; /* Used by the back end to hold private data. */ union { struct aout_data_struct *aout_data; struct artdata *aout_ar_data; struct _oasys_data *oasys_obj_data; struct _oasys_ar_data *oasys_ar_data; struct coff_tdata *coff_obj_data; struct pe_tdata *pe_obj_data; struct xcoff_tdata *xcoff_obj_data; struct ecoff_tdata *ecoff_obj_data; struct ieee_data_struct *ieee_data; struct ieee_ar_data_struct *ieee_ar_data; struct srec_data_struct *srec_data; struct ihex_data_struct *ihex_data; struct tekhex_data_struct *tekhex_data; struct elf_obj_tdata *elf_obj_data; struct nlm_obj_tdata *nlm_obj_data; struct bout_data_struct *bout_data; struct mmo_data_struct *mmo_data; struct sun_core_struct *sun_core_data; struct sco5_core_struct *sco5_core_data; struct trad_core_struct *trad_core_data; struct som_data_struct *som_data; struct hpux_core_struct *hpux_core_data; struct hppabsd_core_struct *hppabsd_core_data; struct sgi_core_struct *sgi_core_data; struct lynx_core_struct *lynx_core_data; struct osf_core_struct *osf_core_data; struct cisco_core_struct *cisco_core_data; struct versados_data_struct *versados_data; struct netbsd_core_struct *netbsd_core_data; struct mach_o_data_struct *mach_o_data; struct mach_o_fat_data_struct *mach_o_fat_data; struct bfd_pef_data_struct *pef_data; struct bfd_pef_xlib_data_struct *pef_xlib_data; struct bfd_sym_data_struct *sym_data; void *any; } tdata; /* Used by the application to hold private data. */ void *usrdata; /* Where all the allocated stuff under this BFD goes. This is a struct objalloc *, but we use void * to avoid requiring the inclusion of objalloc.h. */ void *memory; }; typedef enum bfd_error { bfd_error_no_error = 0, bfd_error_system_call, bfd_error_invalid_target, bfd_error_wrong_format, bfd_error_wrong_object_format, bfd_error_invalid_operation, bfd_error_no_memory, bfd_error_no_symbols, bfd_error_no_armap, bfd_error_no_more_archived_files, bfd_error_malformed_archive, bfd_error_file_not_recognized, bfd_error_file_ambiguously_recognized, bfd_error_no_contents, bfd_error_nonrepresentable_section, bfd_error_no_debug_section, bfd_error_bad_value, bfd_error_file_truncated, bfd_error_file_too_big, bfd_error_on_input, bfd_error_invalid_error_code } bfd_error_type; bfd_error_type bfd_get_error (void); void bfd_set_error (bfd_error_type error_tag, ...); const char *bfd_errmsg (bfd_error_type error_tag); void bfd_perror (const char *message); typedef void (*bfd_error_handler_type) (const char *, ...); bfd_error_handler_type bfd_set_error_handler (bfd_error_handler_type); void bfd_set_error_program_name (const char *); bfd_error_handler_type bfd_get_error_handler (void); long bfd_get_reloc_upper_bound (bfd *abfd, asection *sect); long bfd_canonicalize_reloc (bfd *abfd, asection *sec, arelent **loc, asymbol **syms); void bfd_set_reloc (bfd *abfd, asection *sec, arelent **rel, unsigned int count); bfd_boolean bfd_set_file_flags (bfd *abfd, flagword flags); int bfd_get_arch_size (bfd *abfd); int bfd_get_sign_extend_vma (bfd *abfd); bfd_boolean bfd_set_start_address (bfd *abfd, bfd_vma vma); unsigned int bfd_get_gp_size (bfd *abfd); void bfd_set_gp_size (bfd *abfd, unsigned int i); bfd_vma bfd_scan_vma (const char *string, const char **end, int base); bfd_boolean bfd_copy_private_header_data (bfd *ibfd, bfd *obfd); #define bfd_copy_private_header_data(ibfd, obfd) \ BFD_SEND (obfd, _bfd_copy_private_header_data, \ (ibfd, obfd)) bfd_boolean bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd); #define bfd_copy_private_bfd_data(ibfd, obfd) \ BFD_SEND (obfd, _bfd_copy_private_bfd_data, \ (ibfd, obfd)) bfd_boolean bfd_merge_private_bfd_data (bfd *ibfd, bfd *obfd); #define bfd_merge_private_bfd_data(ibfd, obfd) \ BFD_SEND (obfd, _bfd_merge_private_bfd_data, \ (ibfd, obfd)) bfd_boolean bfd_set_private_flags (bfd *abfd, flagword flags); #define bfd_set_private_flags(abfd, flags) \ BFD_SEND (abfd, _bfd_set_private_flags, (abfd, flags)) #define bfd_sizeof_headers(abfd, info) \ BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, info)) #define bfd_find_nearest_line(abfd, sec, syms, off, file, func, line) \ BFD_SEND (abfd, _bfd_find_nearest_line, \ (abfd, sec, syms, off, file, func, line)) #define bfd_find_line(abfd, syms, sym, file, line) \ BFD_SEND (abfd, _bfd_find_line, \ (abfd, syms, sym, file, line)) #define bfd_find_inliner_info(abfd, file, func, line) \ BFD_SEND (abfd, _bfd_find_inliner_info, \ (abfd, file, func, line)) #define bfd_debug_info_start(abfd) \ BFD_SEND (abfd, _bfd_debug_info_start, (abfd)) #define bfd_debug_info_end(abfd) \ BFD_SEND (abfd, _bfd_debug_info_end, (abfd)) #define bfd_debug_info_accumulate(abfd, section) \ BFD_SEND (abfd, _bfd_debug_info_accumulate, (abfd, section)) #define bfd_stat_arch_elt(abfd, stat) \ BFD_SEND (abfd, _bfd_stat_arch_elt,(abfd, stat)) #define bfd_update_armap_timestamp(abfd) \ BFD_SEND (abfd, _bfd_update_armap_timestamp, (abfd)) #define bfd_set_arch_mach(abfd, arch, mach)\ BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach)) #define bfd_relax_section(abfd, section, link_info, again) \ BFD_SEND (abfd, _bfd_relax_section, (abfd, section, link_info, again)) #define bfd_gc_sections(abfd, link_info) \ BFD_SEND (abfd, _bfd_gc_sections, (abfd, link_info)) #define bfd_merge_sections(abfd, link_info) \ BFD_SEND (abfd, _bfd_merge_sections, (abfd, link_info)) #define bfd_is_group_section(abfd, sec) \ BFD_SEND (abfd, _bfd_is_group_section, (abfd, sec)) #define bfd_discard_group(abfd, sec) \ BFD_SEND (abfd, _bfd_discard_group, (abfd, sec)) #define bfd_link_hash_table_create(abfd) \ BFD_SEND (abfd, _bfd_link_hash_table_create, (abfd)) #define bfd_link_hash_table_free(abfd, hash) \ BFD_SEND (abfd, _bfd_link_hash_table_free, (hash)) #define bfd_link_add_symbols(abfd, info) \ BFD_SEND (abfd, _bfd_link_add_symbols, (abfd, info)) #define bfd_link_just_syms(abfd, sec, info) \ BFD_SEND (abfd, _bfd_link_just_syms, (sec, info)) #define bfd_final_link(abfd, info) \ BFD_SEND (abfd, _bfd_final_link, (abfd, info)) #define bfd_free_cached_info(abfd) \ BFD_SEND (abfd, _bfd_free_cached_info, (abfd)) #define bfd_get_dynamic_symtab_upper_bound(abfd) \ BFD_SEND (abfd, _bfd_get_dynamic_symtab_upper_bound, (abfd)) #define bfd_print_private_bfd_data(abfd, file)\ BFD_SEND (abfd, _bfd_print_private_bfd_data, (abfd, file)) #define bfd_canonicalize_dynamic_symtab(abfd, asymbols) \ BFD_SEND (abfd, _bfd_canonicalize_dynamic_symtab, (abfd, asymbols)) #define bfd_get_synthetic_symtab(abfd, count, syms, dyncount, dynsyms, ret) \ BFD_SEND (abfd, _bfd_get_synthetic_symtab, (abfd, count, syms, \ dyncount, dynsyms, ret)) #define bfd_get_dynamic_reloc_upper_bound(abfd) \ BFD_SEND (abfd, _bfd_get_dynamic_reloc_upper_bound, (abfd)) #define bfd_canonicalize_dynamic_reloc(abfd, arels, asyms) \ BFD_SEND (abfd, _bfd_canonicalize_dynamic_reloc, (abfd, arels, asyms)) extern bfd_byte *bfd_get_relocated_section_contents (bfd *, struct bfd_link_info *, struct bfd_link_order *, bfd_byte *, bfd_boolean, asymbol **); bfd_boolean bfd_alt_mach_code (bfd *abfd, int alternative); struct bfd_preserve { void *marker; void *tdata; flagword flags; const struct bfd_arch_info *arch_info; struct bfd_section *sections; struct bfd_section *section_last; unsigned int section_count; struct bfd_hash_table section_htab; }; bfd_boolean bfd_preserve_save (bfd *, struct bfd_preserve *); void bfd_preserve_restore (bfd *, struct bfd_preserve *); void bfd_preserve_finish (bfd *, struct bfd_preserve *); bfd_vma bfd_emul_get_maxpagesize (const char *); void bfd_emul_set_maxpagesize (const char *, bfd_vma); bfd_vma bfd_emul_get_commonpagesize (const char *); void bfd_emul_set_commonpagesize (const char *, bfd_vma); char *bfd_demangle (bfd *, const char *, int); /* Extracted from archive.c. */ symindex bfd_get_next_mapent (bfd *abfd, symindex previous, carsym **sym); bfd_boolean bfd_set_archive_head (bfd *output, bfd *new_head); bfd *bfd_openr_next_archived_file (bfd *archive, bfd *previous); /* Extracted from corefile.c. */ const char *bfd_core_file_failing_command (bfd *abfd); int bfd_core_file_failing_signal (bfd *abfd); bfd_boolean core_file_matches_executable_p (bfd *core_bfd, bfd *exec_bfd); bfd_boolean generic_core_file_matches_executable_p (bfd *core_bfd, bfd *exec_bfd); /* Extracted from targets.c. */ #define BFD_SEND(bfd, message, arglist) \ ((*((bfd)->xvec->message)) arglist) #ifdef DEBUG_BFD_SEND #undef BFD_SEND #define BFD_SEND(bfd, message, arglist) \ (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \ ((*((bfd)->xvec->message)) arglist) : \ (bfd_assert (__FILE__,__LINE__), NULL)) #endif #define BFD_SEND_FMT(bfd, message, arglist) \ (((bfd)->xvec->message[(int) ((bfd)->format)]) arglist) #ifdef DEBUG_BFD_SEND #undef BFD_SEND_FMT #define BFD_SEND_FMT(bfd, message, arglist) \ (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \ (((bfd)->xvec->message[(int) ((bfd)->format)]) arglist) : \ (bfd_assert (__FILE__,__LINE__), NULL)) #endif enum bfd_flavour { bfd_target_unknown_flavour, bfd_target_aout_flavour, bfd_target_coff_flavour, bfd_target_ecoff_flavour, bfd_target_xcoff_flavour, bfd_target_elf_flavour, bfd_target_ieee_flavour, bfd_target_nlm_flavour, bfd_target_oasys_flavour, bfd_target_tekhex_flavour, bfd_target_srec_flavour, bfd_target_ihex_flavour, bfd_target_som_flavour, bfd_target_os9k_flavour, bfd_target_versados_flavour, bfd_target_msdos_flavour, bfd_target_ovax_flavour, bfd_target_evax_flavour, bfd_target_mmo_flavour, bfd_target_mach_o_flavour, bfd_target_pef_flavour, bfd_target_pef_xlib_flavour, bfd_target_sym_flavour }; enum bfd_endian { BFD_ENDIAN_BIG, BFD_ENDIAN_LITTLE, BFD_ENDIAN_UNKNOWN }; /* Forward declaration. */ typedef struct bfd_link_info _bfd_link_info; typedef struct bfd_target { /* Identifies the kind of target, e.g., SunOS4, Ultrix, etc. */ char *name; /* The "flavour" of a back end is a general indication about the contents of a file. */ enum bfd_flavour flavour; /* The order of bytes within the data area of a file. */ enum bfd_endian byteorder; /* The order of bytes within the header parts of a file. */ enum bfd_endian header_byteorder; /* A mask of all the flags which an executable may have set - from the set <>, <>, ...<>. */ flagword object_flags; /* A mask of all the flags which a section may have set - from the set <>, <>, ...<>. */ flagword section_flags; /* The character normally found at the front of a symbol. (if any), perhaps `_'. */ char symbol_leading_char; /* The pad character for file names within an archive header. */ char ar_pad_char; /* The maximum number of characters in an archive header. */ unsigned short ar_max_namelen; /* Entries for byte swapping for data. These are different from the other entry points, since they don't take a BFD as the first argument. Certain other handlers could do the same. */ bfd_uint64_t (*bfd_getx64) (const void *); bfd_int64_t (*bfd_getx_signed_64) (const void *); void (*bfd_putx64) (bfd_uint64_t, void *); bfd_vma (*bfd_getx32) (const void *); bfd_signed_vma (*bfd_getx_signed_32) (const void *); void (*bfd_putx32) (bfd_vma, void *); bfd_vma (*bfd_getx16) (const void *); bfd_signed_vma (*bfd_getx_signed_16) (const void *); void (*bfd_putx16) (bfd_vma, void *); /* Byte swapping for the headers. */ bfd_uint64_t (*bfd_h_getx64) (const void *); bfd_int64_t (*bfd_h_getx_signed_64) (const void *); void (*bfd_h_putx64) (bfd_uint64_t, void *); bfd_vma (*bfd_h_getx32) (const void *); bfd_signed_vma (*bfd_h_getx_signed_32) (const void *); void (*bfd_h_putx32) (bfd_vma, void *); bfd_vma (*bfd_h_getx16) (const void *); bfd_signed_vma (*bfd_h_getx_signed_16) (const void *); void (*bfd_h_putx16) (bfd_vma, void *); /* Format dependent routines: these are vectors of entry points within the target vector structure, one for each format to check. */ /* Check the format of a file being read. Return a <> or zero. */ const struct bfd_target *(*_bfd_check_format[bfd_type_end]) (bfd *); /* Set the format of a file being written. */ bfd_boolean (*_bfd_set_format[bfd_type_end]) (bfd *); /* Write cached information into a file being written, at <>. */ bfd_boolean (*_bfd_write_contents[bfd_type_end]) (bfd *); /* Generic entry points. */ #define BFD_JUMP_TABLE_GENERIC(NAME) \ NAME##_close_and_cleanup, \ NAME##_bfd_free_cached_info, \ NAME##_new_section_hook, \ NAME##_get_section_contents, \ NAME##_get_section_contents_in_window /* Called when the BFD is being closed to do any necessary cleanup. */ bfd_boolean (*_close_and_cleanup) (bfd *); /* Ask the BFD to free all cached information. */ bfd_boolean (*_bfd_free_cached_info) (bfd *); /* Called when a new section is created. */ bfd_boolean (*_new_section_hook) (bfd *, sec_ptr); /* Read the contents of a section. */ bfd_boolean (*_bfd_get_section_contents) (bfd *, sec_ptr, void *, file_ptr, bfd_size_type); bfd_boolean (*_bfd_get_section_contents_in_window) (bfd *, sec_ptr, bfd_window *, file_ptr, bfd_size_type); /* Entry points to copy private data. */ #define BFD_JUMP_TABLE_COPY(NAME) \ NAME##_bfd_copy_private_bfd_data, \ NAME##_bfd_merge_private_bfd_data, \ _bfd_generic_init_private_section_data, \ NAME##_bfd_copy_private_section_data, \ NAME##_bfd_copy_private_symbol_data, \ NAME##_bfd_copy_private_header_data, \ NAME##_bfd_set_private_flags, \ NAME##_bfd_print_private_bfd_data /* Called to copy BFD general private data from one object file to another. */ bfd_boolean (*_bfd_copy_private_bfd_data) (bfd *, bfd *); /* Called to merge BFD general private data from one object file to a common output file when linking. */ bfd_boolean (*_bfd_merge_private_bfd_data) (bfd *, bfd *); /* Called to initialize BFD private section data from one object file to another. */ #define bfd_init_private_section_data(ibfd, isec, obfd, osec, link_info) \ BFD_SEND (obfd, _bfd_init_private_section_data, (ibfd, isec, obfd, osec, link_info)) bfd_boolean (*_bfd_init_private_section_data) (bfd *, sec_ptr, bfd *, sec_ptr, struct bfd_link_info *); /* Called to copy BFD private section data from one object file to another. */ bfd_boolean (*_bfd_copy_private_section_data) (bfd *, sec_ptr, bfd *, sec_ptr); /* Called to copy BFD private symbol data from one symbol to another. */ bfd_boolean (*_bfd_copy_private_symbol_data) (bfd *, asymbol *, bfd *, asymbol *); /* Called to copy BFD private header data from one object file to another. */ bfd_boolean (*_bfd_copy_private_header_data) (bfd *, bfd *); /* Called to set private backend flags. */ bfd_boolean (*_bfd_set_private_flags) (bfd *, flagword); /* Called to print private BFD data. */ bfd_boolean (*_bfd_print_private_bfd_data) (bfd *, void *); /* Core file entry points. */ #define BFD_JUMP_TABLE_CORE(NAME) \ NAME##_core_file_failing_command, \ NAME##_core_file_failing_signal, \ NAME##_core_file_matches_executable_p char * (*_core_file_failing_command) (bfd *); int (*_core_file_failing_signal) (bfd *); bfd_boolean (*_core_file_matches_executable_p) (bfd *, bfd *); /* Archive entry points. */ #define BFD_JUMP_TABLE_ARCHIVE(NAME) \ NAME##_slurp_armap, \ NAME##_slurp_extended_name_table, \ NAME##_construct_extended_name_table, \ NAME##_truncate_arname, \ NAME##_write_armap, \ NAME##_read_ar_hdr, \ NAME##_openr_next_archived_file, \ NAME##_get_elt_at_index, \ NAME##_generic_stat_arch_elt, \ NAME##_update_armap_timestamp bfd_boolean (*_bfd_slurp_armap) (bfd *); bfd_boolean (*_bfd_slurp_extended_name_table) (bfd *); bfd_boolean (*_bfd_construct_extended_name_table) (bfd *, char **, bfd_size_type *, const char **); void (*_bfd_truncate_arname) (bfd *, const char *, char *); bfd_boolean (*write_armap) (bfd *, unsigned int, struct orl *, unsigned int, int); void * (*_bfd_read_ar_hdr_fn) (bfd *); bfd * (*openr_next_archived_file) (bfd *, bfd *); #define bfd_get_elt_at_index(b,i) BFD_SEND (b, _bfd_get_elt_at_index, (b,i)) bfd * (*_bfd_get_elt_at_index) (bfd *, symindex); int (*_bfd_stat_arch_elt) (bfd *, struct stat *); bfd_boolean (*_bfd_update_armap_timestamp) (bfd *); /* Entry points used for symbols. */ #define BFD_JUMP_TABLE_SYMBOLS(NAME) \ NAME##_get_symtab_upper_bound, \ NAME##_canonicalize_symtab, \ NAME##_make_empty_symbol, \ NAME##_print_symbol, \ NAME##_get_symbol_info, \ NAME##_bfd_is_local_label_name, \ NAME##_bfd_is_target_special_symbol, \ NAME##_get_lineno, \ NAME##_find_nearest_line, \ _bfd_generic_find_line, \ NAME##_find_inliner_info, \ NAME##_bfd_make_debug_symbol, \ NAME##_read_minisymbols, \ NAME##_minisymbol_to_symbol long (*_bfd_get_symtab_upper_bound) (bfd *); long (*_bfd_canonicalize_symtab) (bfd *, struct bfd_symbol **); struct bfd_symbol * (*_bfd_make_empty_symbol) (bfd *); void (*_bfd_print_symbol) (bfd *, void *, struct bfd_symbol *, bfd_print_symbol_type); #define bfd_print_symbol(b,p,s,e) BFD_SEND (b, _bfd_print_symbol, (b,p,s,e)) void (*_bfd_get_symbol_info) (bfd *, struct bfd_symbol *, symbol_info *); #define bfd_get_symbol_info(b,p,e) BFD_SEND (b, _bfd_get_symbol_info, (b,p,e)) bfd_boolean (*_bfd_is_local_label_name) (bfd *, const char *); bfd_boolean (*_bfd_is_target_special_symbol) (bfd *, asymbol *); alent * (*_get_lineno) (bfd *, struct bfd_symbol *); bfd_boolean (*_bfd_find_nearest_line) (bfd *, struct bfd_section *, struct bfd_symbol **, bfd_vma, const char **, const char **, unsigned int *); bfd_boolean (*_bfd_find_line) (bfd *, struct bfd_symbol **, struct bfd_symbol *, const char **, unsigned int *); bfd_boolean (*_bfd_find_inliner_info) (bfd *, const char **, const char **, unsigned int *); /* Back-door to allow format-aware applications to create debug symbols while using BFD for everything else. Currently used by the assembler when creating COFF files. */ asymbol * (*_bfd_make_debug_symbol) (bfd *, void *, unsigned long size); #define bfd_read_minisymbols(b, d, m, s) \ BFD_SEND (b, _read_minisymbols, (b, d, m, s)) long (*_read_minisymbols) (bfd *, bfd_boolean, void **, unsigned int *); #define bfd_minisymbol_to_symbol(b, d, m, f) \ BFD_SEND (b, _minisymbol_to_symbol, (b, d, m, f)) asymbol * (*_minisymbol_to_symbol) (bfd *, bfd_boolean, const void *, asymbol *); /* Routines for relocs. */ #define BFD_JUMP_TABLE_RELOCS(NAME) \ NAME##_get_reloc_upper_bound, \ NAME##_canonicalize_reloc, \ NAME##_bfd_reloc_type_lookup, \ NAME##_bfd_reloc_name_lookup long (*_get_reloc_upper_bound) (bfd *, sec_ptr); long (*_bfd_canonicalize_reloc) (bfd *, sec_ptr, arelent **, struct bfd_symbol **); /* See documentation on reloc types. */ reloc_howto_type * (*reloc_type_lookup) (bfd *, bfd_reloc_code_real_type); reloc_howto_type * (*reloc_name_lookup) (bfd *, const char *); /* Routines used when writing an object file. */ #define BFD_JUMP_TABLE_WRITE(NAME) \ NAME##_set_arch_mach, \ NAME##_set_section_contents bfd_boolean (*_bfd_set_arch_mach) (bfd *, enum bfd_architecture, unsigned long); bfd_boolean (*_bfd_set_section_contents) (bfd *, sec_ptr, const void *, file_ptr, bfd_size_type); /* Routines used by the linker. */ #define BFD_JUMP_TABLE_LINK(NAME) \ NAME##_sizeof_headers, \ NAME##_bfd_get_relocated_section_contents, \ NAME##_bfd_relax_section, \ NAME##_bfd_link_hash_table_create, \ NAME##_bfd_link_hash_table_free, \ NAME##_bfd_link_add_symbols, \ NAME##_bfd_link_just_syms, \ NAME##_bfd_final_link, \ NAME##_bfd_link_split_section, \ NAME##_bfd_gc_sections, \ NAME##_bfd_merge_sections, \ NAME##_bfd_is_group_section, \ NAME##_bfd_discard_group, \ NAME##_section_already_linked \ int (*_bfd_sizeof_headers) (bfd *, struct bfd_link_info *); bfd_byte * (*_bfd_get_relocated_section_contents) (bfd *, struct bfd_link_info *, struct bfd_link_order *, bfd_byte *, bfd_boolean, struct bfd_symbol **); bfd_boolean (*_bfd_relax_section) (bfd *, struct bfd_section *, struct bfd_link_info *, bfd_boolean *); /* Create a hash table for the linker. Different backends store different information in this table. */ struct bfd_link_hash_table * (*_bfd_link_hash_table_create) (bfd *); /* Release the memory associated with the linker hash table. */ void (*_bfd_link_hash_table_free) (struct bfd_link_hash_table *); /* Add symbols from this object file into the hash table. */ bfd_boolean (*_bfd_link_add_symbols) (bfd *, struct bfd_link_info *); /* Indicate that we are only retrieving symbol values from this section. */ void (*_bfd_link_just_syms) (asection *, struct bfd_link_info *); /* Do a link based on the link_order structures attached to each section of the BFD. */ bfd_boolean (*_bfd_final_link) (bfd *, struct bfd_link_info *); /* Should this section be split up into smaller pieces during linking. */ bfd_boolean (*_bfd_link_split_section) (bfd *, struct bfd_section *); /* Remove sections that are not referenced from the output. */ bfd_boolean (*_bfd_gc_sections) (bfd *, struct bfd_link_info *); /* Attempt to merge SEC_MERGE sections. */ bfd_boolean (*_bfd_merge_sections) (bfd *, struct bfd_link_info *); /* Is this section a member of a group? */ bfd_boolean (*_bfd_is_group_section) (bfd *, const struct bfd_section *); /* Discard members of a group. */ bfd_boolean (*_bfd_discard_group) (bfd *, struct bfd_section *); /* Check if SEC has been already linked during a reloceatable or final link. */ void (*_section_already_linked) (bfd *, struct bfd_section *, struct bfd_link_info *); /* Routines to handle dynamic symbols and relocs. */ #define BFD_JUMP_TABLE_DYNAMIC(NAME) \ NAME##_get_dynamic_symtab_upper_bound, \ NAME##_canonicalize_dynamic_symtab, \ NAME##_get_synthetic_symtab, \ NAME##_get_dynamic_reloc_upper_bound, \ NAME##_canonicalize_dynamic_reloc /* Get the amount of memory required to hold the dynamic symbols. */ long (*_bfd_get_dynamic_symtab_upper_bound) (bfd *); /* Read in the dynamic symbols. */ long (*_bfd_canonicalize_dynamic_symtab) (bfd *, struct bfd_symbol **); /* Create synthetized symbols. */ long (*_bfd_get_synthetic_symtab) (bfd *, long, struct bfd_symbol **, long, struct bfd_symbol **, struct bfd_symbol **); /* Get the amount of memory required to hold the dynamic relocs. */ long (*_bfd_get_dynamic_reloc_upper_bound) (bfd *); /* Read in the dynamic relocs. */ long (*_bfd_canonicalize_dynamic_reloc) (bfd *, arelent **, struct bfd_symbol **); /* Opposite endian version of this target. */ const struct bfd_target * alternative_target; /* Data for use by back-end routines, which isn't generic enough to belong in this structure. */ const void *backend_data; } bfd_target; bfd_boolean bfd_set_default_target (const char *name); const bfd_target *bfd_find_target (const char *target_name, bfd *abfd); const char ** bfd_target_list (void); const bfd_target *bfd_search_for_target (int (*search_func) (const bfd_target *, void *), void *); /* Extracted from format.c. */ bfd_boolean bfd_check_format (bfd *abfd, bfd_format format); bfd_boolean bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching); bfd_boolean bfd_set_format (bfd *abfd, bfd_format format); const char *bfd_format_string (bfd_format format); /* Extracted from linker.c. */ bfd_boolean bfd_link_split_section (bfd *abfd, asection *sec); #define bfd_link_split_section(abfd, sec) \ BFD_SEND (abfd, _bfd_link_split_section, (abfd, sec)) void bfd_section_already_linked (bfd *abfd, asection *sec, struct bfd_link_info *info); #define bfd_section_already_linked(abfd, sec, info) \ BFD_SEND (abfd, _section_already_linked, (abfd, sec, info)) /* Extracted from simple.c. */ bfd_byte *bfd_simple_get_relocated_section_contents (bfd *abfd, asection *sec, bfd_byte *outbuf, asymbol **symbol_table); #ifdef __cplusplus } #endif #endif