diff options
author | David S. Miller <davem@redhat.com> | 2012-04-17 01:50:39 +0000 |
---|---|---|
committer | David S. Miller <davem@redhat.com> | 2012-04-17 01:50:39 +0000 |
commit | 13cf9988bc2852ba66d6096578a518c94bfccdcd (patch) | |
tree | 683c5e39327f7de26f38a4205562ed60446491b4 | |
parent | 31821be097c4154d3d7d201d9f4939a47af97ac6 (diff) | |
download | binutils-gdb-13cf9988bc2852ba66d6096578a518c94bfccdcd.tar.gz |
gold: Allow use_plt_offset to be specified for global relocations.
gold/
* output.h (Output_reloc): Allow use_plt_offset for global relocs too.
(class Output_data_reloc): Adjust calls to Output_reloc_type.
(Output_data_reloc::add_global_relative): (RELA only) Add use_plt_offset.
* output.cc (Output_reloc::Output_reloc): Add use_plt_offset flag for
global relocs too.
(Output_reloc::symbol_value): Respect use_plt_offset_ for global symbols.
* powerpc.cc (Target_powerpc::Scan::global): Adjust add_global_relative
calls.
* sparc.cc (Target_sparc::Scan::global): Likewise.
* x86_64.cc (Target_x86_64::Scan::global): Likewise.
-rw-r--r-- | gold/ChangeLog | 13 | ||||
-rw-r--r-- | gold/output.cc | 19 | ||||
-rw-r--r-- | gold/output.h | 56 | ||||
-rw-r--r-- | gold/powerpc.cc | 6 | ||||
-rw-r--r-- | gold/sparc.cc | 4 | ||||
-rw-r--r-- | gold/x86_64.cc | 14 |
6 files changed, 69 insertions, 43 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog index 471db35160b..b88577ab66f 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,16 @@ +2012-04-16 David S. Miller <davem@davemloft.net> + + * output.h (Output_reloc): Allow use_plt_offset for global relocs too. + (class Output_data_reloc): Adjust calls to Output_reloc_type. + (Output_data_reloc::add_global_relative): (RELA only) Add use_plt_offset. + * output.cc (Output_reloc::Output_reloc): Add use_plt_offset flag for + global relocs too. + (Output_reloc::symbol_value): Respect use_plt_offset_ for global symbols. + * powerpc.cc (Target_powerpc::Scan::global): Adjust add_global_relative + calls. + * sparc.cc (Target_sparc::Scan::global): Likewise. + * x86_64.cc (Target_x86_64::Scan::global): Likewise. + 2012-04-16 Cary Coutant <ccoutant@google.com> * archive.cc (Library_base::should_include_member): Check for diff --git a/gold/output.cc b/gold/output.cc index ca190392d14..2236916054a 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -705,10 +705,11 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc( Output_data* od, Address address, bool is_relative, - bool is_symbolless) + bool is_symbolless, + bool use_plt_offset) : address_(address), local_sym_index_(GSYM_CODE), type_(type), is_relative_(is_relative), is_symbolless_(is_symbolless), - is_section_symbol_(false), use_plt_offset_(false), shndx_(INVALID_CODE) + is_section_symbol_(false), use_plt_offset_(use_plt_offset), shndx_(INVALID_CODE) { // this->type_ is a bitfield; make sure TYPE fits. gold_assert(this->type_ == type); @@ -726,10 +727,11 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc( unsigned int shndx, Address address, bool is_relative, - bool is_symbolless) + bool is_symbolless, + bool use_plt_offset) : address_(address), local_sym_index_(GSYM_CODE), type_(type), is_relative_(is_relative), is_symbolless_(is_symbolless), - is_section_symbol_(false), use_plt_offset_(false), shndx_(shndx) + is_section_symbol_(false), use_plt_offset_(use_plt_offset), shndx_(shndx) { gold_assert(shndx != INVALID_CODE); // this->type_ is a bitfield; make sure TYPE fits. @@ -1116,7 +1118,14 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::symbol_value( { const Sized_symbol<size>* sym; sym = static_cast<const Sized_symbol<size>*>(this->u1_.gsym); - return sym->value() + addend; + if (this->use_plt_offset_ && sym->has_plt_offset()) + { + uint64_t plt_address = + parameters->target().plt_address_for_global(sym); + return plt_address + sym->plt_offset(); + } + else + return sym->value() + addend; } gold_assert(this->local_sym_index_ != SECTION_CODE && this->local_sym_index_ != TARGET_CODE diff --git a/gold/output.h b/gold/output.h index 838ca3d4dd6..3796e9120ce 100644 --- a/gold/output.h +++ b/gold/output.h @@ -1021,12 +1021,13 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian> // A reloc against a global symbol. Output_reloc(Symbol* gsym, unsigned int type, Output_data* od, - Address address, bool is_relative, bool is_symbolless); + Address address, bool is_relative, bool is_symbolless, + bool use_plt_offset); Output_reloc(Symbol* gsym, unsigned int type, Sized_relobj<size, big_endian>* relobj, unsigned int shndx, Address address, bool is_relative, - bool is_symbolless); + bool is_symbolless, bool use_plt_offset); // A reloc against a local symbol or local section symbol. @@ -1226,8 +1227,7 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian> bool is_symbolless_ : 1; // True if the relocation is against a section symbol. bool is_section_symbol_ : 1; - // True if the addend should be the PLT offset. This is used only - // for RELATIVE relocations to local symbols. + // True if the addend should be the PLT offset. // (Used only for RELA, but stored here for space.) bool use_plt_offset_ : 1; // If the reloc address is an input section in an object, the @@ -1255,17 +1255,18 @@ class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian> Output_reloc(Symbol* gsym, unsigned int type, Output_data* od, Address address, Addend addend, bool is_relative, - bool is_symbolless) - : rel_(gsym, type, od, address, is_relative, is_symbolless), + bool is_symbolless, bool use_plt_offset) + : rel_(gsym, type, od, address, is_relative, is_symbolless, + use_plt_offset), addend_(addend) { } Output_reloc(Symbol* gsym, unsigned int type, Sized_relobj<size, big_endian>* relobj, unsigned int shndx, Address address, Addend addend, - bool is_relative, bool is_symbolless) + bool is_relative, bool is_symbolless, bool use_plt_offset) : rel_(gsym, type, relobj, shndx, address, is_relative, - is_symbolless), addend_(addend) + is_symbolless, use_plt_offset), addend_(addend) { } // A reloc against a local symbol. @@ -1558,14 +1559,14 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian> void add_global(Symbol* gsym, unsigned int type, Output_data* od, Address address) - { this->add(od, Output_reloc_type(gsym, type, od, address, false, false)); } + { this->add(od, Output_reloc_type(gsym, type, od, address, false, false, false)); } void add_global(Symbol* gsym, unsigned int type, Output_data* od, Sized_relobj<size, big_endian>* relobj, unsigned int shndx, Address address) { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address, - false, false)); } + false, false, false)); } void add_global_generic(Symbol* gsym, unsigned int type, Output_data* od, @@ -1574,7 +1575,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian> gold_assert(addend == 0); this->add(od, Output_reloc_type(gsym, type, od, convert_types<Address, uint64_t>(address), - false, false)); + false, false, false)); } void @@ -1587,7 +1588,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian> static_cast<Sized_relobj<size, big_endian>*>(relobj); this->add(od, Output_reloc_type(gsym, type, sized_relobj, shndx, convert_types<Address, uint64_t>(address), - false, false)); + false, false, false)); } // Add a RELATIVE reloc against a global symbol. The final relocation @@ -1596,7 +1597,8 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian> void add_global_relative(Symbol* gsym, unsigned int type, Output_data* od, Address address) - { this->add(od, Output_reloc_type(gsym, type, od, address, true, true)); } + { this->add(od, Output_reloc_type(gsym, type, od, address, true, true, + false)); } void add_global_relative(Symbol* gsym, unsigned int type, Output_data* od, @@ -1604,7 +1606,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian> unsigned int shndx, Address address) { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address, - true, true)); + true, true, false)); } // Add a global relocation which does not use a symbol for the relocation, @@ -1613,7 +1615,8 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian> void add_symbolless_global_addend(Symbol* gsym, unsigned int type, Output_data* od, Address address) - { this->add(od, Output_reloc_type(gsym, type, od, address, false, true)); } + { this->add(od, Output_reloc_type(gsym, type, od, address, false, true, + false)); } void add_symbolless_global_addend(Symbol* gsym, unsigned int type, @@ -1622,7 +1625,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian> unsigned int shndx, Address address) { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address, - false, true)); + false, true, false)); } // Add a reloc against a local symbol. @@ -1825,7 +1828,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian> add_global(Symbol* gsym, unsigned int type, Output_data* od, Address address, Addend addend) { this->add(od, Output_reloc_type(gsym, type, od, address, addend, - false, false)); } + false, false, false)); } void add_global(Symbol* gsym, unsigned int type, Output_data* od, @@ -1833,7 +1836,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian> unsigned int shndx, Address address, Addend addend) { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address, - addend, false, false)); } + addend, false, false, false)); } void add_global_generic(Symbol* gsym, unsigned int type, Output_data* od, @@ -1842,7 +1845,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian> this->add(od, Output_reloc_type(gsym, type, od, convert_types<Address, uint64_t>(address), convert_types<Addend, uint64_t>(addend), - false, false)); + false, false, false)); } void @@ -1855,7 +1858,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian> this->add(od, Output_reloc_type(gsym, type, sized_relobj, shndx, convert_types<Address, uint64_t>(address), convert_types<Addend, uint64_t>(addend), - false, false)); + false, false, false)); } // Add a RELATIVE reloc against a global symbol. The final output @@ -1865,16 +1868,17 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian> void add_global_relative(Symbol* gsym, unsigned int type, Output_data* od, - Address address, Addend addend) + Address address, Addend addend, bool use_plt_offset) { this->add(od, Output_reloc_type(gsym, type, od, address, addend, true, - true)); } + true, use_plt_offset)); } void add_global_relative(Symbol* gsym, unsigned int type, Output_data* od, Sized_relobj<size, big_endian>* relobj, - unsigned int shndx, Address address, Addend addend) + unsigned int shndx, Address address, Addend addend, + bool use_plt_offset) { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address, - addend, true, true)); } + addend, true, true, use_plt_offset)); } // Add a global relocation which does not use a symbol for the relocation, // but which gets its addend from a symbol. @@ -1883,7 +1887,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian> add_symbolless_global_addend(Symbol* gsym, unsigned int type, Output_data* od, Address address, Addend addend) { this->add(od, Output_reloc_type(gsym, type, od, address, addend, - false, true)); } + false, true, false)); } void add_symbolless_global_addend(Symbol* gsym, unsigned int type, @@ -1891,7 +1895,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian> Sized_relobj<size, big_endian>* relobj, unsigned int shndx, Address address, Addend addend) { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address, - addend, false, true)); } + addend, false, true, false)); } // Add a reloc against a local symbol. diff --git a/gold/powerpc.cc b/gold/powerpc.cc index 372443ffa6c..b4433047906 100644 --- a/gold/powerpc.cc +++ b/gold/powerpc.cc @@ -1486,7 +1486,7 @@ Target_powerpc<size, big_endian>::Scan::global( rela_dyn->add_global_relative(gsym, elfcpp::R_POWERPC_RELATIVE, output_section, object, data_shndx, reloc.get_r_offset(), - reloc.get_r_addend()); + reloc.get_r_addend(), false); } else { @@ -1505,7 +1505,7 @@ Target_powerpc<size, big_endian>::Scan::global( output_section, object, data_shndx, reloc.get_r_offset(), - reloc.get_r_addend()); + reloc.get_r_addend(), false); } } } @@ -1574,7 +1574,7 @@ Target_powerpc<size, big_endian>::Scan::global( gsym->set_got_offset(GOT_TYPE_STANDARD, off); rela_dyn->add_global_relative(gsym, elfcpp::R_POWERPC_RELATIVE, - got, off, 0); + got, off, 0, false); } } } diff --git a/gold/sparc.cc b/gold/sparc.cc index ee82367f9eb..e1bdc8e0f37 100644 --- a/gold/sparc.cc +++ b/gold/sparc.cc @@ -2333,7 +2333,7 @@ Target_sparc<size, big_endian>::Scan::global( rela_dyn->add_global_relative(gsym, elfcpp::R_SPARC_RELATIVE, output_section, object, data_shndx, reloc.get_r_offset(), - reloc.get_r_addend()); + reloc.get_r_addend(), false); } else { @@ -2387,7 +2387,7 @@ Target_sparc<size, big_endian>::Scan::global( gsym->set_got_offset(GOT_TYPE_STANDARD, off); rela_dyn->add_global_relative(gsym, elfcpp::R_SPARC_RELATIVE, - got, off, 0); + got, off, 0, false); } } } diff --git a/gold/x86_64.cc b/gold/x86_64.cc index 3962e1ea364..d67924b3791 100644 --- a/gold/x86_64.cc +++ b/gold/x86_64.cc @@ -1667,24 +1667,24 @@ Target_x86_64<size>::reserve_global_got_entry(unsigned int got_index, this->got_, got_offset, 0); else rela_dyn->add_global_relative(gsym, elfcpp::R_X86_64_RELATIVE, - this->got_, got_offset, 0); + this->got_, got_offset, 0, false); } break; case GOT_TYPE_TLS_OFFSET: rela_dyn->add_global_relative(gsym, elfcpp::R_X86_64_TPOFF64, - this->got_, got_offset, 0); + this->got_, got_offset, 0, false); break; case GOT_TYPE_TLS_PAIR: this->got_->reserve_slot(got_index + 1); rela_dyn->add_global_relative(gsym, elfcpp::R_X86_64_DTPMOD64, - this->got_, got_offset, 0); + this->got_, got_offset, 0, false); rela_dyn->add_global_relative(gsym, elfcpp::R_X86_64_DTPOFF64, - this->got_, got_offset + 8, 0); + this->got_, got_offset + 8, 0, false); break; case GOT_TYPE_TLS_DESC: this->got_->reserve_slot(got_index + 1); rela_dyn->add_global_relative(gsym, elfcpp::R_X86_64_TLSDESC, - this->got_, got_offset, 0); + this->got_, got_offset, 0, false); break; default: gold_unreachable(); @@ -2505,7 +2505,7 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab, output_section, object, data_shndx, reloc.get_r_offset(), - reloc.get_r_addend()); + reloc.get_r_addend(), false); } else { @@ -2612,7 +2612,7 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab, unsigned int got_off = gsym->got_offset(GOT_TYPE_STANDARD); rela_dyn->add_global_relative(gsym, elfcpp::R_X86_64_RELATIVE, - got, got_off, 0); + got, got_off, 0, false); } } } |