* 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.
This commit is contained in:
parent
f54ae065b8
commit
7404fe1b8d
@ -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
|
||||
|
32
gold/arm.cc
32
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,
|
||||
|
32
gold/i386.cc
32
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,
|
||||
|
@ -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&);
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
240
gold/powerpc.cc
240
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;
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user