During a -r (or --emit-relocs) link, if two sections had the same name but
different section types, gold would put relocations for both sections into
the same relocation section even though the data sections remained separate.
For .eh_frame sections, when one section is PROGBITS and another is
X86_64_UNWIND, we really should be using the UNWIND section type and
combining the sections anyway. For other sections, we should be
creating one relocation section for each output data section.
gold/
PR gold/23016
* incremental.cc (can_incremental_update): Check for unwind section
type.
* layout.h (Layout::layout): Add sh_type parameter.
* layout.cc (Layout::layout): Likewise.
(Layout::layout_reloc): Create new output reloc section if data
section does not already have one.
(Layout::layout_eh_frame): Check for unwind section type.
(Layout::make_eh_frame_section): Use unwind section type for .eh_frame
and .eh_frame_hdr.
* object.h (Sized_relobj_file::Shdr_write): New typedef.
(Sized_relobj_file::layout_section): Add sh_type parameter.
(Sized_relobj_file::Deferred_layout::Deferred_layout): Add sh_type
parameter.
* object.cc (Sized_relobj_file::check_eh_frame_flags): Check for
unwind section type.
(Sized_relobj_file::layout_section): Add sh_type parameter; pass it
to Layout::layout.
(Sized_relobj_file::do_layout): Make local copy of sh_type.
Force .eh_frame sections to unwind section type.
Pass sh_type to layout_section.
(Sized_relobj_file<size, big_endian>::do_layout_deferred_sections):
Pass sh_type to layout_section.
* output.cc (Output_section::Output_section): Initialize reloc_section_.
* output.h (Output_section::reloc_section): New method.
(Output_section::set_reloc_section): New method.
(Output_section::reloc_section_): New data member.
* target.h (Target::unwind_section_type): New method.
(Target::Target_info::unwind_section_type): New data member.
* aarch64.cc (aarch64_info): Add unwind_section_type.
* arm.cc (arm_info, arm_nacl_info): Likewise.
* i386.cc (i386_info, i386_nacl_info, iamcu_info): Likewise.
* mips.cc (mips_info, mips_nacl_info): Likewise.
* powerpc.cc (powerpc_info): Likewise.
* s390.cc (s390_info): Likewise.
* sparc.cc (sparc_info): Likewise.
* tilegx.cc (tilegx_info): Likewise.
* x86_64.cc (x86_64_info, x86_64_nacl_info): Likewise.
* testsuite/Makefile.am (pr23016_1, pr23016_2): New test cases.
* testsuite/Makefile.in: Regenerate.
* testsuite/testfile.cc: Add unwind_section_type.
* testsuite/pr23016_1.sh: New test script.
* testsuite/pr23016_1a.s: New source file.
* testsuite/pr23016_1b.s: New source file.
* testsuite/pr23016_2.sh: New test script.
* testsuite/pr23016_2a.s: New source file.
* testsuite/pr23016_2b.s: New source file.
gold/ChangeLog:
* s390.cc (Target_s390::match_view_u): New helper method.
(Target_s390::do_is_call_to_non_split): New method.
(Target_s390::ss_code_st_r14): New const.
(Target_s390::ss_code_l_r14): New const.
(Target_s390::ss_code_bras_8): New const.
(Target_s390::ss_code_l_basr): New const.
(Target_s390::ss_code_a_basr): New const.
(Target_s390::ss_code_ear): New const.
(Target_s390::ss_code_c): New const.
(Target_s390::ss_code_larl): New const.
(Target_s390::ss_code_brasl): New const.
(Target_s390::ss_code_jg): New const.
(Target_s390::ss_code_jgl): New const.
(Target_s390::ss_match_mcount): New helper method.
(Target_s390::ss_match_l): New helper method.
(Target_s390::ss_match_ahi): New helper method.
(Target_s390::ss_match_alfi): New helper method.
(Target_s390::ss_match_cr): New helper method.
(Target_s390::do_calls_non_split): New method.
* testsuite/Makefile.am: Added new tests.
* testsuite/split_s390.sh: New test.
* testsuite/split_s390_1_a1.s: New test.
* testsuite/split_s390_1_a2.s: New test.
* testsuite/split_s390_1_n1.s: New test.
* testsuite/split_s390_1_n2.s: New test.
* testsuite/split_s390_1_z1.s: New test.
* testsuite/split_s390_1_z2.s: New test.
* testsuite/split_s390_1_z3.s: New test.
* testsuite/split_s390_1_z4.s: New test.
* testsuite/split_s390_2_ns.s: New test.
* testsuite/split_s390_2_s.s: New test.
* testsuite/split_s390x_1_a1.s: New test.
* testsuite/split_s390x_1_a2.s: New test.
* testsuite/split_s390x_1_n1.s: New test.
* testsuite/split_s390x_1_n2.s: New test.
* testsuite/split_s390x_1_z1.s: New test.
* testsuite/split_s390x_1_z2.s: New test.
* testsuite/split_s390x_1_z3.s: New test.
* testsuite/split_s390x_1_z4.s: New test.
* testsuite/split_s390x_2_ns.s: New test.
* testsuite/split_s390x_2_s.s: New test.
For MIPS-64, the r_info field in the relocation format is
replaced by several individual fields, including r_sym and
r_type. To enable support for this format, I've refactored
target-independent code to remove almost all uses of the r_info
field. (I've left alone a couple of routines used only for
incremental linking, which I can update if/when the MIPS target
adds support for incremental linking.)
For routines that are already templated on a Classify_reloc class
(namely, gc_process_relocs, relocate_section, and
relocate_relocs), I've extended the Classify_reloc interface to
include sh_type (which no longer needs to be a separate template
parameter) as well as get_r_sym() and get_r_type() methods for
extracting the r_sym and r_type fields. For
scan_relocatable_relocs, I've extended the
Default_scan_relocatable_relocs class by converting it to a class
template with Classify_reloc as a template parameter. For the
remaining routines that need to access r_sym, I've added a
virtual Target::get_r_sym() method with an override for the MIPS
target.
In elfcpp, I've added Mips64_rel, etc., accessor classes and
corresponding internal data structures. The MIPS target uses
these new classes within its own Mips_classify_reloc class.
The Mips64_ accessor classes also expose the r_ssym, r_type2,
and r_type3 fields from the relocation.
These changes should be functionally the same for all but the
MIPS target.
elfcpp/
* elfcpp.h (Mips64_rel, Mips64_rel_write): New classes.
(Mips64_rela, Mips64_rela_write): New classes.
* elfcpp_internal.h (Mips64_rel_data, Mips64_rela_data): New structs.
gold/
* gc.h (get_embedded_addend_size): Remove sh_type parameter.
(gc_process_relocs): Remove sh_type template parameter.
Use Classify_reloc to access r_sym, r_type, and r_addend fields.
* object.h (Sized_relobj_file::split_stack_adjust): Add target
parameter.
(Sized_relobj_file::split_stack_adjust_reltype): Likewise.
* reloc-types.h (Reloc_types::copy_reloc_addend): (SHT_REL and SHT_RELA
specializations) Remove.
* reloc.cc (Emit_relocs_strategy): Rename and move to target-reloc.h.
(Sized_relobj_file::emit_relocs_scan): Call Target::emit_relocs_scan().
(Sized_relobj_file::emit_relocs_scan_reltype): Remove.
(Sized_relobj_file::split_stack_adjust): Add target parameter.
Adjust all callers.
(Sized_relobj_file::split_stack_adjust_reltype): Likewise. Call
Target::get_r_sym() to get r_sym field from relocations.
(Track_relocs::next_symndx): Call Target::get_r_sym().
* target-reloc.h (scan_relocs): Remove sh_type template parameter;
add Classify_reloc template parameter. Use for accessing r_sym and
r_type.
(relocate_section): Likewise.
(Default_classify_reloc): New class (renamed and moved from reloc.cc).
(Default_scan_relocatable_relocs): Remove sh_type template parameter.
(Default_scan_relocatable_relocs::Reltype): New typedef.
(Default_scan_relocatable_relocs::reloc_size): New const.
(Default_scan_relocatable_relocs::sh_type): New const.
(Default_scan_relocatable_relocs::get_r_sym): New method.
(Default_scan_relocatable_relocs::get_r_type): New method.
(Default_emit_relocs_strategy): New class.
(scan_relocatable_relocs): Replace sh_type template parameter with
Scan_relocatable_relocs class. Use it to access r_sym and r_type
fields.
(relocate_relocs): Replace sh_type template parameter with
Classify_reloc class. Use it to access r_sym and r_type fields.
* target.h (Target::is_call_to_non_split): Replace r_type parameter
with pointer to relocation. Adjust all callers.
(Target::do_is_call_to_non_split): Likewise.
(Target::emit_relocs_scan): New virtual method.
(Sized_target::get_r_sym): New virtual method.
* target.cc (Target::do_is_call_to_non_split): Replace r_type parameter
with pointer to relocation.
* aarch64.cc (Target_aarch64::emit_relocs_scan): New method.
(Target_aarch64::Relocatable_size_for_reloc): Remove.
(Target_aarch64::gc_process_relocs): Use Default_classify_reloc.
(Target_aarch64::scan_relocs): Likewise.
(Target_aarch64::relocate_section): Likewise.
(Target_aarch64::Relocatable_size_for_reloc::get_size_for_reloc):
Remove.
(Target_aarch64::scan_relocatable_relocs): Use Default_classify_reloc.
(Target_aarch64::relocate_relocs): Use Default_classify_reloc.
* arm.cc (Target_arm::Arm_scan_relocatable_relocs): Remove sh_type
template parameter.
(Target_arm::emit_relocs_scan): New method.
(Target_arm::Relocatable_size_for_reloc): Replace with...
(Target_arm::Classify_reloc): ...this.
(Target_arm::gc_process_relocs): Use Classify_reloc.
(Target_arm::scan_relocs): Likewise.
(Target_arm::relocate_section): Likewise.
(Target_arm::scan_relocatable_relocs): Likewise.
(Target_arm::relocate_relocs): Likewise.
* i386.cc (Target_i386::emit_relocs_scan): New method.
(Target_i386::Relocatable_size_for_reloc): Replace with...
(Target_i386::Classify_reloc): ...this.
(Target_i386::gc_process_relocs): Use Classify_reloc.
(Target_i386::scan_relocs): Likewise.
(Target_i386::relocate_section): Likewise.
(Target_i386::scan_relocatable_relocs): Likewise.
(Target_i386::relocate_relocs): Likewise.
* mips.cc (Mips_scan_relocatable_relocs): Remove sh_type template
parameter.
(Mips_reloc_types): New class template.
(Mips_classify_reloc): New class template.
(Target_mips::Reltype): New typedef.
(Target_mips::Relatype): New typedef.
(Target_mips::emit_relocs_scan): New method.
(Target_mips::get_r_sym): New method.
(Target_mips::Relocatable_size_for_reloc): Replace with
Mips_classify_reloc.
(Target_mips::copy_reloc): Use Mips_classify_reloc.
(Target_mips::gc_process_relocs): Likewise.
(Target_mips::scan_relocs): Likewise.
(Target_mips::relocate_section): Likewise.
(Target_mips::scan_relocatable_relocs): Likewise.
(Target_mips::relocate_relocs): Likewise.
(mips_get_size_for_reloc): New function, factored out from
Relocatable_size_for_reloc::get_size_for_reloc.
(Target_mips::Scan::local): Use Mips_classify_reloc.
(Target_mips::Scan::global): Likewise.
(Target_mips::Relocate::relocate): Likewise.
* powerpc.cc (Target_powerpc::emit_relocs_scan): New method.
(Target_powerpc::Relocatable_size_for_reloc): Remove.
(Target_powerpc::gc_process_relocs): Use Default_classify_reloc.
(Target_powerpc::scan_relocs): Likewise.
(Target_powerpc::relocate_section): Likewise.
(Powerpc_scan_relocatable_reloc): Convert to class template.
(Powerpc_scan_relocatable_reloc::Reltype): New typedef.
(Powerpc_scan_relocatable_reloc::reloc_size): New const.
(Powerpc_scan_relocatable_reloc::sh_type): New const.
(Powerpc_scan_relocatable_reloc::get_r_sym): New method.
(Powerpc_scan_relocatable_reloc::get_r_type): New method.
(Target_powerpc::scan_relocatable_relocs): Use
Powerpc_scan_relocatable_reloc.
(Target_powerpc::relocate_relocs): Use Default_classify_reloc.
* s390.cc (Target_s390::emit_relocs_scan): New method.
(Target_s390::Relocatable_size_for_reloc): Remove.
(Target_s390::gc_process_relocs): Use Default_classify_reloc.
(Target_s390::scan_relocs): Likewise.
(Target_s390::relocate_section): Likewise.
(Target_s390::Relocatable_size_for_reloc::get_size_for_reloc):
Remove.
(Target_s390::scan_relocatable_relocs): Use Default_classify_reloc.
(Target_s390::relocate_relocs): Use Default_classify_reloc.
* sparc.cc (Target_sparc::emit_relocs_scan): New method.
(Target_sparc::Relocatable_size_for_reloc): Remove.
(Target_sparc::gc_process_relocs): Use Default_classify_reloc.
(Target_sparc::scan_relocs): Likewise.
(Target_sparc::relocate_section): Likewise.
(Target_sparc::Relocatable_size_for_reloc::get_size_for_reloc):
Remove.
(Target_sparc::scan_relocatable_relocs): Use Default_classify_reloc.
(Target_sparc::relocate_relocs): Use Default_classify_reloc.
* tilegx.cc (Target_tilegx::emit_relocs_scan): New method.
(Target_tilegx::Relocatable_size_for_reloc): Remove.
(Target_tilegx::gc_process_relocs): Use Default_classify_reloc.
(Target_tilegx::scan_relocs): Likewise.
(Target_tilegx::relocate_section): Likewise.
(Target_tilegx::Relocatable_size_for_reloc::get_size_for_reloc):
Remove.
(Target_tilegx::scan_relocatable_relocs): Use Default_classify_reloc.
(Target_tilegx::relocate_relocs): Use Default_classify_reloc.
* x86_64.cc (Target_x86_64::emit_relocs_scan): New method.
(Target_x86_64::Relocatable_size_for_reloc): Remove.
(Target_x86_64::gc_process_relocs): Use Default_classify_reloc.
(Target_x86_64::scan_relocs): Likewise.
(Target_x86_64::relocate_section): Likewise.
(Target_x86_64::Relocatable_size_for_reloc::get_size_for_reloc):
Remove.
(Target_x86_64::scan_relocatable_relocs): Use Default_classify_reloc.
(Target_x86_64::relocate_relocs): Use Default_classify_reloc.
* testsuite/testfile.cc (Target_test::emit_relocs_scan): New method.
Some linker code editing needs to change multiple insns. In some
cases multiple relocations are involved and it is not sufficient to
make the changes independently as relocations are processed, because
doing so might lead to a partial edit. So in order to safely edit we
need all the relocations available in relocate(). Also, to emit
edited relocs corresponding to the edited code sequence we need some
way to pass information from relocate() to relocate_relocs(),
particularly if the edit depends on insns. We can't modify input
relocs in relocate() as they are mmapped PROT_READ, nor it is
particularly clean to write relocs to the output at that stage. So
add a Relocatable_relocs* field to relinfo to mark edited relocs.
Given that relocate is passed the raw reloc pointer, it makes sense to
remove the rel/rela parameter and r_type too. However, that means the
mips relocate() needs to know whether SHT_REL or SHT_RELA relocs are
being processed. So add a rel_type for mips, which also has the
benefit of removing relocate() overloading there.
This patch adds the infrastructure without making use of it.
Note that relinfo->rr will be NULL if not outputting relocations.
* object.h (struct Relocate_info): Add "rr".
* reloc.h (Relocatable_relocs::set_strategy): New accessor.
* reloc.cc (Sized_relobj_file::do_relocate_sections): Init
relinfo.rr for relocate_section and relocate_relocs.
* powerpc.cc (relocate): Add rel_type and preloc parameters.
Delete rela and r_type params, instead recalculate these from
preloc.
(relocate_relocs): Delete Relocatable_relocs* param, instead
use relinfo->rr.
* aarch64.cc: Likewise.
* arm.cc: Likewise.
* i386.cc: Likewise.
* mips.cc: Likewise.
* s390.cc: Likewise.
* sparc.cc: Likewise.
* target.h: Likewise.
* tilegx.cc: Likewise.
* x86_64.cc: Likewise.
* testsuite/testfile.cc: Likewise.
* target-reloc.h (relocate_section): Adjust to suit.
(apply_relocation, relocate_relocs): Likewise.