diff options
author | Alan Modra <amodra@gmail.com> | 2012-09-05 00:34:20 +0000 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2012-09-05 00:34:20 +0000 |
commit | 7404fe1b8d20b30162a7e56307d5a2d400cb5645 (patch) | |
tree | 71cfb8fde4ad34ab2eb812996ad807feec50828b | |
parent | f54ae065b8f805b626729a8f60bacf8312a182db (diff) | |
download | gdb-7404fe1b8d20b30162a7e56307d5a2d400cb5645.zip gdb-7404fe1b8d20b30162a7e56307d5a2d400cb5645.tar.gz gdb-7404fe1b8d20b30162a7e56307d5a2d400cb5645.tar.bz2 |
* object.h (Sized_relobj_file::emit_relocs): Delete.
(Sized_relobj_file::emit_relocs_reltype): Delete.
* reloc.cc (Sized_relobj_file::do_relocate_sections): Call target
relocate_relocs for --emit-relocs.
(Sized_relobj_file::emit_relocs, emit_relocs_reltype): Delete.
* output.h: Update comment.
(Output_segment::first_section): New function.
(Output_segment::first_section_load_address): Use first_section.
* output.cc (Output_segment::first_section): New function extracted..
(Output_segment::first_section_load_address): ..from here. Delete.
* target-reloc.h (relocate_for_relocatable): Rename to relocate_relocs.
* target.h (Sized_target::relocate_for_relocatable): Likewise.
* arm.cc (Target_arm::relocate_for_relocatable): Likewise, and
adjust call to target.h function.
* i386.cc (Target_i386): Likewise.
* sparc.cc (Target_sparc): Likewise.
* x86_64.cc (Target_x86_64): Likewise.
* powerpc.cc (Target_powerpc): Likewise.
(Target_powerpc::Scan::local, global): Handle R_POWERPC_TLS. Ensure
first tls section has section symbol for optimised local dynamic
output relocs.
(Target_powerpc::Relocate::relocate): Correct local dynamic value.
(Target_powerpc::relocate_relocs): Adjust relocs emitted for
optimised tls code.
* testsuite/testfile.cc (Target_test::relocate_for_relocatable):
Rename to relocate_relocs. Update error message.
-rw-r--r-- | gold/ChangeLog | 29 | ||||
-rw-r--r-- | gold/arm.cc | 32 | ||||
-rw-r--r-- | gold/i386.cc | 32 | ||||
-rw-r--r-- | gold/object.h | 21 | ||||
-rw-r--r-- | gold/output.cc | 10 | ||||
-rw-r--r-- | gold/output.h | 12 | ||||
-rw-r--r-- | gold/powerpc.cc | 240 | ||||
-rw-r--r-- | gold/reloc.cc | 90 | ||||
-rw-r--r-- | gold/sparc.cc | 33 | ||||
-rw-r--r-- | gold/target-reloc.h | 6 | ||||
-rw-r--r-- | gold/target.h | 31 | ||||
-rw-r--r-- | gold/testsuite/testfile.cc | 16 | ||||
-rw-r--r-- | gold/x86_64.cc | 8 |
13 files changed, 325 insertions, 235 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog index d812165..ea52ea2 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,32 @@ +2012-09-05 Alan Modra <amodra@gmail.com> + + * object.h (Sized_relobj_file::emit_relocs): Delete. + (Sized_relobj_file::emit_relocs_reltype): Delete. + * reloc.cc (Sized_relobj_file::do_relocate_sections): Call target + relocate_relocs for --emit-relocs. + (Sized_relobj_file::emit_relocs, emit_relocs_reltype): Delete. + * output.h: Update comment. + (Output_segment::first_section): New function. + (Output_segment::first_section_load_address): Use first_section. + * output.cc (Output_segment::first_section): New function extracted.. + (Output_segment::first_section_load_address): ..from here. Delete. + * target-reloc.h (relocate_for_relocatable): Rename to relocate_relocs. + * target.h (Sized_target::relocate_for_relocatable): Likewise. + * arm.cc (Target_arm::relocate_for_relocatable): Likewise, and + adjust call to target.h function. + * i386.cc (Target_i386): Likewise. + * sparc.cc (Target_sparc): Likewise. + * x86_64.cc (Target_x86_64): Likewise. + * powerpc.cc (Target_powerpc): Likewise. + (Target_powerpc::Scan::local, global): Handle R_POWERPC_TLS. Ensure + first tls section has section symbol for optimised local dynamic + output relocs. + (Target_powerpc::Relocate::relocate): Correct local dynamic value. + (Target_powerpc::relocate_relocs): Adjust relocs emitted for + optimised tls code. + * testsuite/testfile.cc (Target_test::relocate_for_relocatable): + Rename to relocate_relocs. Update error message. + 2012-09-04 Andreas Schwab <schwab@linux-m68k.org> * powerpc.cc (do_make_elf_object): Allow ET_EXEC files with diff --git a/gold/arm.cc b/gold/arm.cc index fa257a7..fc7d981 100644 --- a/gold/arm.cc +++ b/gold/arm.cc @@ -2286,20 +2286,20 @@ class Target_arm : public Sized_target<32, big_endian> const unsigned char* plocal_symbols, Relocatable_relocs*); - // Relocate a section during a relocatable link. + // Emit relocations for a section. void - relocate_for_relocatable(const Relocate_info<32, big_endian>*, - unsigned int sh_type, - const unsigned char* prelocs, - size_t reloc_count, - Output_section* output_section, - off_t offset_in_output_section, - const Relocatable_relocs*, - unsigned char* view, - Arm_address view_address, - section_size_type view_size, - unsigned char* reloc_view, - section_size_type reloc_view_size); + relocate_relocs(const Relocate_info<32, big_endian>*, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + off_t offset_in_output_section, + const Relocatable_relocs*, + unsigned char* view, + Arm_address view_address, + section_size_type view_size, + unsigned char* reloc_view, + section_size_type reloc_view_size); // Perform target-specific processing in a relocatable link. This is // only used if we use the relocation strategy RELOC_SPECIAL. @@ -9588,11 +9588,11 @@ Target_arm<big_endian>::scan_relocatable_relocs( rr); } -// Relocate a section during a relocatable link. +// Emit relocations for a section. template<bool big_endian> void -Target_arm<big_endian>::relocate_for_relocatable( +Target_arm<big_endian>::relocate_relocs( const Relocate_info<32, big_endian>* relinfo, unsigned int sh_type, const unsigned char* prelocs, @@ -9608,7 +9608,7 @@ Target_arm<big_endian>::relocate_for_relocatable( { gold_assert(sh_type == elfcpp::SHT_REL); - gold::relocate_for_relocatable<32, big_endian, elfcpp::SHT_REL>( + gold::relocate_relocs<32, big_endian, elfcpp::SHT_REL>( relinfo, prelocs, reloc_count, diff --git a/gold/i386.cc b/gold/i386.cc index 47f33a0..b7f16eb 100644 --- a/gold/i386.cc +++ b/gold/i386.cc @@ -407,20 +407,20 @@ class Target_i386 : public Sized_target<32, false> const unsigned char* plocal_symbols, Relocatable_relocs*); - // Relocate a section during a relocatable link. + // Emit relocations for a section. void - relocate_for_relocatable(const Relocate_info<32, false>*, - unsigned int sh_type, - const unsigned char* prelocs, - size_t reloc_count, - Output_section* output_section, - off_t offset_in_output_section, - const Relocatable_relocs*, - unsigned char* view, - elfcpp::Elf_types<32>::Elf_Addr view_address, - section_size_type view_size, - unsigned char* reloc_view, - section_size_type reloc_view_size); + relocate_relocs(const Relocate_info<32, false>*, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + off_t offset_in_output_section, + const Relocatable_relocs*, + unsigned char* view, + elfcpp::Elf_types<32>::Elf_Addr view_address, + section_size_type view_size, + unsigned char* reloc_view, + section_size_type reloc_view_size); // Return a string used to fill a code section with nops. std::string @@ -3602,10 +3602,10 @@ Target_i386::scan_relocatable_relocs(Symbol_table* symtab, rr); } -// Relocate a section during a relocatable link. +// Emit relocations for a section. void -Target_i386::relocate_for_relocatable( +Target_i386::relocate_relocs( const Relocate_info<32, false>* relinfo, unsigned int sh_type, const unsigned char* prelocs, @@ -3621,7 +3621,7 @@ Target_i386::relocate_for_relocatable( { gold_assert(sh_type == elfcpp::SHT_REL); - gold::relocate_for_relocatable<32, false, elfcpp::SHT_REL>( + gold::relocate_relocs<32, false, elfcpp::SHT_REL>( relinfo, prelocs, reloc_count, diff --git a/gold/object.h b/gold/object.h index b4d2ffe..492ef63 100644 --- a/gold/object.h +++ b/gold/object.h @@ -2499,27 +2499,6 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian> const Read_relocs_data::Relocs_list::iterator&, Relocatable_relocs*); - // Emit the relocs for --emit-relocs. - void - emit_relocs(const Relocate_info<size, big_endian>*, unsigned int, - unsigned int sh_type, const unsigned char* prelocs, - size_t reloc_count, Output_section*, Address output_offset, - unsigned char* view, Address address, - section_size_type view_size, - unsigned char* reloc_view, section_size_type reloc_view_size); - - // Emit the relocs for --emit-relocs, templatized on the type of the - // relocation section. - template<int sh_type> - void - emit_relocs_reltype(const Relocate_info<size, big_endian>*, unsigned int, - const unsigned char* prelocs, size_t reloc_count, - Output_section*, Address output_offset, - unsigned char* view, Address address, - section_size_type view_size, - unsigned char* reloc_view, - section_size_type reloc_view_size); - // Scan the input relocations for --incremental. void incremental_relocs_scan(const Read_relocs_data::Relocs_list::iterator&); diff --git a/gold/output.cc b/gold/output.cc index 68fe573..664e408 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -4613,10 +4613,10 @@ Output_segment::set_tls_offsets() (*p)->set_tls_offset(this->vaddr_); } -// Return the load address of the first section. +// Return the first section. -uint64_t -Output_segment::first_section_load_address() const +Output_section* +Output_segment::first_section() const { for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i) { @@ -4626,9 +4626,7 @@ Output_segment::first_section_load_address() const ++p) { if ((*p)->is_section()) - return ((*p)->has_load_address() - ? (*p)->load_address() - : (*p)->address()); + return (*p)->output_section(); } } gold_unreachable(); diff --git a/gold/output.h b/gold/output.h index 98c07fc..14c5aac 100644 --- a/gold/output.h +++ b/gold/output.h @@ -2123,7 +2123,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian> // Output_relocatable_relocs represents a relocation section in a // relocatable link. The actual data is written out in the target -// hook relocate_for_relocatable. This just saves space for it. +// hook relocate_relocs. This just saves space for it. template<int sh_type, int size, bool big_endian> class Output_relocatable_relocs : public Output_section_data @@ -4406,9 +4406,17 @@ class Output_segment bool has_dynamic_reloc() const; + // Return the first section. + Output_section* + first_section() const; + // Return the address of the first section. uint64_t - first_section_load_address() const; + first_section_load_address() const + { + const Output_section* os = this->first_section(); + return os->has_load_address() ? os->load_address() : os->address(); + } // Return whether the addresses have been set already. bool diff --git a/gold/powerpc.cc b/gold/powerpc.cc index f4a9385..c4b543d 100644 --- a/gold/powerpc.cc +++ b/gold/powerpc.cc @@ -261,20 +261,20 @@ class Target_powerpc : public Sized_target<size, big_endian> const unsigned char* plocal_symbols, Relocatable_relocs*); - // Relocate a section during a relocatable link. + // Emit relocations for a section. void - relocate_for_relocatable(const Relocate_info<size, big_endian>*, - unsigned int sh_type, - const unsigned char* prelocs, - size_t reloc_count, - Output_section* output_section, - off_t offset_in_output_section, - const Relocatable_relocs*, - unsigned char*, - Address view_address, - section_size_type, - unsigned char* reloc_view, - section_size_type reloc_view_size); + relocate_relocs(const Relocate_info<size, big_endian>*, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + off_t offset_in_output_section, + const Relocatable_relocs*, + unsigned char*, + Address view_address, + section_size_type, + unsigned char* reloc_view, + section_size_type reloc_view_size); // Return whether SYM is defined by the ABI. bool @@ -2294,6 +2294,7 @@ Target_powerpc<size, big_endian>::Scan::local( case elfcpp::R_POWERPC_GNU_VTENTRY: case elfcpp::R_PPC64_TOCSAVE: case elfcpp::R_PPC_EMB_MRKREF: + case elfcpp::R_POWERPC_TLS: break; case elfcpp::R_PPC64_TOC: @@ -2485,6 +2486,12 @@ Target_powerpc<size, big_endian>::Scan::local( else if (tls_type == tls::TLSOPT_TO_LE) { // no GOT relocs needed for Local Exec. + if (parameters->options().emit_relocs()) + { + Output_section* os = layout->tls_segment()->first_section(); + gold_assert(os != NULL); + os->set_needs_symtab_index(); + } } else gold_unreachable(); @@ -2573,6 +2580,7 @@ Target_powerpc<size, big_endian>::Scan::global( case elfcpp::R_POWERPC_GNU_VTENTRY: case elfcpp::R_PPC_LOCAL24PC: case elfcpp::R_PPC_EMB_MRKREF: + case elfcpp::R_POWERPC_TLS: break; case elfcpp::R_PPC64_TOC: @@ -2817,6 +2825,12 @@ Target_powerpc<size, big_endian>::Scan::global( else if (tls_type == tls::TLSOPT_TO_LE) { // no GOT relocs needed for Local Exec. + if (parameters->options().emit_relocs()) + { + Output_section* os = layout->tls_segment()->first_section(); + gold_assert(os != NULL); + os->set_needs_symtab_index(); + } } else gold_unreachable(); @@ -3201,7 +3215,7 @@ Target_powerpc<size, big_endian>::Relocate::relocate( insn = addis_3_2; elfcpp::Swap<32, big_endian>::writeval(iview, insn); r_type = elfcpp::R_POWERPC_TPREL16_HA; - value = relinfo->layout->tls_segment()->vaddr() + dtp_offset; + value = dtp_offset; } else { @@ -3327,7 +3341,7 @@ Target_powerpc<size, big_endian>::Relocate::relocate( this->call_tls_get_addr_ = CALL_SKIP; r_type = elfcpp::R_POWERPC_TPREL16_LO; view += 2 * big_endian; - value = relinfo->layout->tls_segment()->vaddr() + dtp_offset; + value = dtp_offset; } } else if (r_type == elfcpp::R_POWERPC_TLS) @@ -3883,7 +3897,7 @@ Target_powerpc<size, big_endian>::scan_relocatable_relocs( rr); } -// Relocate a section during a relocatable link. +// Emit relocations for a section. // This is a modified version of the function by the same name in // target-reloc.h. Using relocate_special_relocatable for // R_PPC_PLTREL24 would require duplication of the entire body of the @@ -3891,7 +3905,7 @@ Target_powerpc<size, big_endian>::scan_relocatable_relocs( template<int size, bool big_endian> void -Target_powerpc<size, big_endian>::relocate_for_relocatable( +Target_powerpc<size, big_endian>::relocate_relocs( const Relocate_info<size, big_endian>* relinfo, unsigned int sh_type, const unsigned char* prelocs, @@ -3926,7 +3940,7 @@ Target_powerpc<size, big_endian>::relocate_for_relocatable( } unsigned char* pwrite = reloc_view; - + bool zap_next = false; for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size) { Relocatable_relocs::Reloc_strategy strategy = rr->strategy(i); @@ -3936,25 +3950,35 @@ Target_powerpc<size, big_endian>::relocate_for_relocatable( Reltype reloc(prelocs); Reltype_write reloc_write(pwrite); + Address offset = reloc.get_r_offset(); typename elfcpp::Elf_types<size>::Elf_WXword r_info = reloc.get_r_info(); - const unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info); - const unsigned int r_type = elfcpp::elf_r_type<size>(r_info); + unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info); + unsigned int r_type = elfcpp::elf_r_type<size>(r_info); + const unsigned int orig_r_sym = r_sym; + typename elfcpp::Elf_types<size>::Elf_Swxword addend + = reloc.get_r_addend(); + const Symbol* gsym = NULL; + + if (zap_next) + { + // We could arrange to discard these and other relocs for + // tls optimised sequences in the strategy methods, but for + // now do as BFD ld does. + r_type = elfcpp::R_POWERPC_NONE; + zap_next = false; + } // Get the new symbol index. - - unsigned int new_symndx; if (r_sym < local_count) { switch (strategy) { case Relocatable_relocs::RELOC_COPY: case Relocatable_relocs::RELOC_SPECIAL: - if (r_sym == 0) - new_symndx = 0; - else + if (r_sym != 0) { - new_symndx = object->symtab_index(r_sym); - gold_assert(new_symndx != -1U); + r_sym = object->symtab_index(r_sym); + gold_assert(r_sym != -1U); } break; @@ -3972,7 +3996,7 @@ Target_powerpc<size, big_endian>::relocate_for_relocatable( Output_section* os = object->output_section(shndx); gold_assert(os != NULL); gold_assert(os->needs_symtab_index()); - new_symndx = os->symtab_index(); + r_sym = os->symtab_index(); } break; @@ -3982,22 +4006,19 @@ Target_powerpc<size, big_endian>::relocate_for_relocatable( } else { - const Symbol* gsym = object->global_symbol(r_sym); + gsym = object->global_symbol(r_sym); gold_assert(gsym != NULL); if (gsym->is_forwarder()) gsym = relinfo->symtab->resolve_forwards(gsym); gold_assert(gsym->has_symtab_index()); - new_symndx = gsym->symtab_index(); + r_sym = gsym->symtab_index(); } // Get the new offset--the location in the output section where // this relocation should be applied. - - Address offset = reloc.get_r_offset(); - Address new_offset; if (static_cast<Address>(offset_in_output_section) != invalid_address) - new_offset = offset + offset_in_output_section; + offset += offset_in_output_section; else { section_offset_type sot_offset = @@ -4006,34 +4027,25 @@ Target_powerpc<size, big_endian>::relocate_for_relocatable( output_section->output_offset(object, relinfo->data_shndx, sot_offset); gold_assert(new_sot_offset != -1); - new_offset = new_sot_offset; + offset = new_sot_offset; } // In an object file, r_offset is an offset within the section. // In an executable or dynamic object, generated by // --emit-relocs, r_offset is an absolute address. - // FIXME: Arrange to call this function for --emit-relocs too, - // so that we can make emitted relocs match edited TLS code. - if (0 && !parameters->options().relocatable()) + if (!parameters->options().relocatable()) { - new_offset += view_address; + offset += view_address; if (static_cast<Address>(offset_in_output_section) != invalid_address) - new_offset -= offset_in_output_section; + offset -= offset_in_output_section; } - reloc_write.put_r_offset(new_offset); - reloc_write.put_r_info(elfcpp::elf_r_info<size>(new_symndx, r_type)); - // Handle the reloc addend based on the strategy. - typename elfcpp::Elf_types<size>::Elf_Swxword addend; - addend = Reloc_types<elfcpp::SHT_RELA, size, big_endian>:: - get_reloc_addend(&reloc); - if (strategy == Relocatable_relocs::RELOC_COPY) ; else if (strategy == Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA) { - const Symbol_value<size>* psymval = object->local_symbol(r_sym); + const Symbol_value<size>* psymval = object->local_symbol(orig_r_sym); addend = psymval->value(object, addend); } else if (strategy == Relocatable_relocs::RELOC_SPECIAL) @@ -4044,8 +4056,136 @@ Target_powerpc<size, big_endian>::relocate_for_relocatable( else gold_unreachable(); - Reloc_types<elfcpp::SHT_RELA, size, big_endian>:: - set_reloc_addend(&reloc_write, addend); + if (!parameters->options().relocatable()) + { + if (r_type == elfcpp::R_POWERPC_GOT_TLSGD16 + || r_type == elfcpp::R_POWERPC_GOT_TLSGD16_LO + || r_type == elfcpp::R_POWERPC_GOT_TLSGD16_HI + || r_type == elfcpp::R_POWERPC_GOT_TLSGD16_HA) + { + // First instruction of a global dynamic sequence, + // arg setup insn. + const bool final = gsym == NULL || gsym->final_value_is_known(); + switch (this->optimize_tls_gd(final)) + { + case tls::TLSOPT_TO_IE: + r_type += (elfcpp::R_POWERPC_GOT_TPREL16 + - elfcpp::R_POWERPC_GOT_TLSGD16); + break; + case tls::TLSOPT_TO_LE: + if (r_type == elfcpp::R_POWERPC_GOT_TLSGD16 + || r_type == elfcpp::R_POWERPC_GOT_TLSGD16_LO) + r_type = elfcpp::R_POWERPC_TPREL16_HA; + else + { + r_type = elfcpp::R_POWERPC_NONE; + offset -= 2 * big_endian; + } + break; + default: + break; + } + } + else if (r_type == elfcpp::R_POWERPC_GOT_TLSLD16 + || r_type == elfcpp::R_POWERPC_GOT_TLSLD16_LO + || r_type == elfcpp::R_POWERPC_GOT_TLSLD16_HI + || r_type == elfcpp::R_POWERPC_GOT_TLSLD16_HA) + { + // First instruction of a local dynamic sequence, + // arg setup insn. + if (this->optimize_tls_ld() == tls::TLSOPT_TO_LE) + { + if (r_type == elfcpp::R_POWERPC_GOT_TLSLD16 + || r_type == elfcpp::R_POWERPC_GOT_TLSLD16_LO) + { + r_type = elfcpp::R_POWERPC_TPREL16_HA; + const Output_section* os = relinfo->layout->tls_segment() + ->first_section(); + gold_assert(os != NULL); + gold_assert(os->needs_symtab_index()); + r_sym = os->symtab_index(); + addend = dtp_offset; + } + else + { + r_type = elfcpp::R_POWERPC_NONE; + offset -= 2 * big_endian; + } + } + } + else if (r_type == elfcpp::R_POWERPC_GOT_TPREL16 + || r_type == elfcpp::R_POWERPC_GOT_TPREL16_LO + || r_type == elfcpp::R_POWERPC_GOT_TPREL16_HI + || r_type == elfcpp::R_POWERPC_GOT_TPREL16_HA) + { + // First instruction of initial exec sequence. + const bool final = gsym == NULL || gsym->final_value_is_known(); + if (this->optimize_tls_ie(final) == tls::TLSOPT_TO_LE) + { + if (r_type == elfcpp::R_POWERPC_GOT_TPREL16 + || r_type == elfcpp::R_POWERPC_GOT_TPREL16_LO) + r_type = elfcpp::R_POWERPC_TPREL16_HA; + else + { + r_type = elfcpp::R_POWERPC_NONE; + offset -= 2 * big_endian; + } + } + } + else if ((size == 64 && r_type == elfcpp::R_PPC64_TLSGD) + || (size == 32 && r_type == elfcpp::R_PPC_TLSGD)) + { + // Second instruction of a global dynamic sequence, + // the __tls_get_addr call + const bool final = gsym == NULL || gsym->final_value_is_known(); + switch (this->optimize_tls_gd(final)) + { + case tls::TLSOPT_TO_IE: + r_type = elfcpp::R_POWERPC_NONE; + zap_next = true; + break; + case tls::TLSOPT_TO_LE: + r_type = elfcpp::R_POWERPC_TPREL16_LO; + offset += 2 * big_endian; + zap_next = true; + break; + default: + break; + } + } + else if ((size == 64 && r_type == elfcpp::R_PPC64_TLSLD) + || (size == 32 && r_type == elfcpp::R_PPC_TLSLD)) + { + // Second instruction of a local dynamic sequence, + // the __tls_get_addr call + if (this->optimize_tls_ld() == tls::TLSOPT_TO_LE) + { + const Output_section* os = relinfo->layout->tls_segment() + ->first_section(); + gold_assert(os != NULL); + gold_assert(os->needs_symtab_index()); + r_sym = os->symtab_index(); + addend = dtp_offset; + r_type = elfcpp::R_POWERPC_TPREL16_LO; + offset += 2 * big_endian; + zap_next = true; + } + } + else if (r_type == elfcpp::R_POWERPC_TLS) + { + // Second instruction of an initial exec sequence + const bool final = gsym == NULL || gsym->final_value_is_known(); + if (this->optimize_tls_ie(final) == tls::TLSOPT_TO_LE) + { + r_type = elfcpp::R_POWERPC_TPREL16_LO; + offset += 2 * big_endian; + } + } + } + + reloc_write.put_r_offset(offset); + reloc_write.put_r_info(elfcpp::elf_r_info<size>(r_sym, r_type)); + reloc_write.put_r_addend(addend); pwrite += reloc_size; } diff --git a/gold/reloc.cc b/gold/reloc.cc index 4c28b03..ca7f32f 100644 --- a/gold/reloc.cc +++ b/gold/reloc.cc @@ -1014,9 +1014,14 @@ Sized_relobj_file<size, big_endian>::do_relocate_sections( output_offset == invalid_address, view, address, view_size, reloc_map); if (parameters->options().emit_relocs()) - this->emit_relocs(&relinfo, i, sh_type, prelocs, reloc_count, - os, output_offset, view, address, view_size, - (*pviews)[i].view, (*pviews)[i].view_size); + { + Relocatable_relocs* rr = this->relocatable_relocs(i); + target->relocate_relocs(&relinfo, sh_type, prelocs, reloc_count, + os, output_offset, rr, + view, address, view_size, + (*pviews)[i].view, + (*pviews)[i].view_size); + } if (parameters->incremental()) this->incremental_relocs_write(&relinfo, sh_type, prelocs, reloc_count, os, output_offset, of); @@ -1024,84 +1029,15 @@ Sized_relobj_file<size, big_endian>::do_relocate_sections( else { Relocatable_relocs* rr = this->relocatable_relocs(i); - target->relocate_for_relocatable(&relinfo, sh_type, prelocs, - reloc_count, os, output_offset, rr, - view, address, view_size, - (*pviews)[i].view, - (*pviews)[i].view_size); + target->relocate_relocs(&relinfo, sh_type, prelocs, reloc_count, + os, output_offset, rr, + view, address, view_size, + (*pviews)[i].view, + (*pviews)[i].view_size); } } } -// Emit the relocs for --emit-relocs. - -template<int size, bool big_endian> -void -Sized_relobj_file<size, big_endian>::emit_relocs( - const Relocate_info<size, big_endian>* relinfo, - unsigned int i, - unsigned int sh_type, - const unsigned char* prelocs, - size_t reloc_count, - Output_section* output_section, - typename elfcpp::Elf_types<size>::Elf_Addr offset_in_output_section, - unsigned char* view, - typename elfcpp::Elf_types<size>::Elf_Addr address, - section_size_type view_size, - unsigned char* reloc_view, - section_size_type reloc_view_size) -{ - if (sh_type == elfcpp::SHT_REL) - this->emit_relocs_reltype<elfcpp::SHT_REL>(relinfo, i, prelocs, - reloc_count, output_section, - offset_in_output_section, - view, address, view_size, - reloc_view, reloc_view_size); - else - { - gold_assert(sh_type == elfcpp::SHT_RELA); - this->emit_relocs_reltype<elfcpp::SHT_RELA>(relinfo, i, prelocs, - reloc_count, output_section, - offset_in_output_section, - view, address, view_size, - reloc_view, reloc_view_size); - } -} - -// Emit the relocs for --emit-relocs, templatized on the type of the -// relocation section. - -template<int size, bool big_endian> -template<int sh_type> -void -Sized_relobj_file<size, big_endian>::emit_relocs_reltype( - const Relocate_info<size, big_endian>* relinfo, - unsigned int i, - const unsigned char* prelocs, - size_t reloc_count, - Output_section* output_section, - typename elfcpp::Elf_types<size>::Elf_Addr offset_in_output_section, - unsigned char* view, - typename elfcpp::Elf_types<size>::Elf_Addr address, - section_size_type view_size, - unsigned char* reloc_view, - section_size_type reloc_view_size) -{ - const Relocatable_relocs* rr = this->relocatable_relocs(i); - relocate_for_relocatable<size, big_endian, sh_type>( - relinfo, - prelocs, - reloc_count, - output_section, - offset_in_output_section, - rr, - view, - address, - view_size, - reloc_view, - reloc_view_size); -} - // Write the incremental relocs. template<int size, bool big_endian> diff --git a/gold/sparc.cc b/gold/sparc.cc index 7b78311..f8c59ec 100644 --- a/gold/sparc.cc +++ b/gold/sparc.cc @@ -131,20 +131,21 @@ class Target_sparc : public Sized_target<size, big_endian> const unsigned char* plocal_symbols, Relocatable_relocs*); - // Relocate a section during a relocatable link. + // Emit relocations for a section. void - relocate_for_relocatable(const Relocate_info<size, big_endian>*, - unsigned int sh_type, - const unsigned char* prelocs, - size_t reloc_count, - Output_section* output_section, - off_t offset_in_output_section, - const Relocatable_relocs*, - unsigned char* view, - typename elfcpp::Elf_types<size>::Elf_Addr view_address, - section_size_type view_size, - unsigned char* reloc_view, - section_size_type reloc_view_size); + relocate_relocs(const Relocate_info<size, big_endian>*, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + off_t offset_in_output_section, + const Relocatable_relocs*, + unsigned char* view, + typename elfcpp::Elf_types<size>::Elf_Addr view_address, + section_size_type view_size, + unsigned char* reloc_view, + section_size_type reloc_view_size); + // Return whether SYM is defined by the ABI. bool do_is_defined_by_abi(const Symbol* sym) const @@ -4197,11 +4198,11 @@ Target_sparc<size, big_endian>::scan_relocatable_relocs( rr); } -// Relocate a section during a relocatable link. +// Emit relocations for a section. template<int size, bool big_endian> void -Target_sparc<size, big_endian>::relocate_for_relocatable( +Target_sparc<size, big_endian>::relocate_relocs( const Relocate_info<size, big_endian>* relinfo, unsigned int sh_type, const unsigned char* prelocs, @@ -4217,7 +4218,7 @@ Target_sparc<size, big_endian>::relocate_for_relocatable( { gold_assert(sh_type == elfcpp::SHT_RELA); - gold::relocate_for_relocatable<size, big_endian, elfcpp::SHT_RELA>( + gold::relocate_relocs<size, big_endian, elfcpp::SHT_RELA>( relinfo, prelocs, reloc_count, diff --git a/gold/target-reloc.h b/gold/target-reloc.h index 6efcdf4..96f2614 100644 --- a/gold/target-reloc.h +++ b/gold/target-reloc.h @@ -590,12 +590,12 @@ scan_relocatable_relocs( } } -// Relocate relocs during a relocatable link. This is a default -// definition which should work for most targets. +// Relocate relocs. Called for a relocatable link, and for --emit-relocs. +// This is a default definition which should work for most targets. template<int size, bool big_endian, int sh_type> void -relocate_for_relocatable( +relocate_relocs( const Relocate_info<size, big_endian>* relinfo, const unsigned char* prelocs, size_t reloc_count, diff --git a/gold/target.h b/gold/target.h index 19092e1..25ac96b 100644 --- a/gold/target.h +++ b/gold/target.h @@ -801,23 +801,22 @@ class Sized_target : public Target const unsigned char* plocal_symbols, Relocatable_relocs*) = 0; - // Relocate a section during a relocatable link. The parameters are - // like relocate_section, with additional parameters for the view of - // the output reloc section. + // Emit relocations for a section during a relocatable link, and for + // --emit-relocs. The parameters are like relocate_section, with + // additional parameters for the view of the output reloc section. virtual void - relocate_for_relocatable(const Relocate_info<size, big_endian>*, - unsigned int sh_type, - const unsigned char* prelocs, - size_t reloc_count, - Output_section* output_section, - off_t offset_in_output_section, - const Relocatable_relocs*, - unsigned char* view, - typename elfcpp::Elf_types<size>::Elf_Addr - view_address, - section_size_type view_size, - unsigned char* reloc_view, - section_size_type reloc_view_size) = 0; + relocate_relocs(const Relocate_info<size, big_endian>*, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + off_t offset_in_output_section, + const Relocatable_relocs*, + unsigned char* view, + typename elfcpp::Elf_types<size>::Elf_Addr view_address, + section_size_type view_size, + unsigned char* reloc_view, + section_size_type reloc_view_size) = 0; // Perform target-specific processing in a relocatable link. This is // only used if we use the relocation strategy RELOC_SPECIAL. diff --git a/gold/testsuite/testfile.cc b/gold/testsuite/testfile.cc index e963d4d..3ce0c97 100644 --- a/gold/testsuite/testfile.cc +++ b/gold/testsuite/testfile.cc @@ -72,14 +72,14 @@ class Target_test : public Sized_target<size, big_endian> { ERROR("call to Target_test::scan_relocatable_relocs"); } void - relocate_for_relocatable(const Relocate_info<size, big_endian>*, - unsigned int, const unsigned char*, size_t, - Output_section*, off_t, const Relocatable_relocs*, - unsigned char*, - typename elfcpp::Elf_types<size>::Elf_Addr, - section_size_type, unsigned char*, - section_size_type) - { ERROR("call to Target_test::relocate_for_relocatable"); } + relocate_relocs(const Relocate_info<size, big_endian>*, + unsigned int, const unsigned char*, size_t, + Output_section*, off_t, const Relocatable_relocs*, + unsigned char*, + typename elfcpp::Elf_types<size>::Elf_Addr, + section_size_type, unsigned char*, + section_size_type) + { ERROR("call to Target_test::relocate_relocs"); } static const Target::Target_info test_target_info; }; diff --git a/gold/x86_64.cc b/gold/x86_64.cc index 625aff8..a15b6ae 100644 --- a/gold/x86_64.cc +++ b/gold/x86_64.cc @@ -469,9 +469,9 @@ class Target_x86_64 : public Sized_target<size, false> const unsigned char* plocal_symbols, Relocatable_relocs*); - // Relocate a section during a relocatable link. + // Emit relocations for a section. void - relocate_for_relocatable( + relocate_relocs( const Relocate_info<size, false>*, unsigned int sh_type, const unsigned char* prelocs, @@ -4208,7 +4208,7 @@ Target_x86_64<size>::scan_relocatable_relocs( template<int size> void -Target_x86_64<size>::relocate_for_relocatable( +Target_x86_64<size>::relocate_relocs( const Relocate_info<size, false>* relinfo, unsigned int sh_type, const unsigned char* prelocs, @@ -4224,7 +4224,7 @@ Target_x86_64<size>::relocate_for_relocatable( { gold_assert(sh_type == elfcpp::SHT_RELA); - gold::relocate_for_relocatable<size, false, elfcpp::SHT_RELA>( + gold::relocate_relocs<size, false, elfcpp::SHT_RELA>( relinfo, prelocs, reloc_count, |