From 13cf9988bc2852ba66d6096578a518c94bfccdcd Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 17 Apr 2012 01:50:39 +0000 Subject: [PATCH] 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. --- gold/ChangeLog | 13 ++++++++++++ gold/output.cc | 19 ++++++++++++----- gold/output.h | 56 ++++++++++++++++++++++++++----------------------- gold/powerpc.cc | 6 +++--- gold/sparc.cc | 4 ++-- gold/x86_64.cc | 14 ++++++------- 6 files changed, 69 insertions(+), 43 deletions(-) diff --git a/gold/ChangeLog b/gold/ChangeLog index 471db35160..b88577ab66 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,16 @@ +2012-04-16 David S. Miller + + * 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 * archive.cc (Library_base::should_include_member): Check for diff --git a/gold/output.cc b/gold/output.cc index ca190392d1..2236916054 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -705,10 +705,11 @@ Output_reloc::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::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::symbol_value( { const Sized_symbol* sym; sym = static_cast*>(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 838ca3d4dd..3796e9120c 100644 --- a/gold/output.h +++ b/gold/output.h @@ -1021,12 +1021,13 @@ class Output_reloc // 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* 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 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 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* 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 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* 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 gold_assert(addend == 0); this->add(od, Output_reloc_type(gsym, type, od, convert_types(address), - false, false)); + false, false, false)); } void @@ -1587,7 +1588,7 @@ class Output_data_reloc static_cast*>(relobj); this->add(od, Output_reloc_type(gsym, type, sized_relobj, shndx, convert_types(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 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 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 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 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 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 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 this->add(od, Output_reloc_type(gsym, type, od, convert_types(address), convert_types(addend), - false, false)); + false, false, false)); } void @@ -1855,7 +1858,7 @@ class Output_data_reloc this->add(od, Output_reloc_type(gsym, type, sized_relobj, shndx, convert_types(address), convert_types(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 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* 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 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 Sized_relobj* 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 372443ffa6..b443304790 100644 --- a/gold/powerpc.cc +++ b/gold/powerpc.cc @@ -1486,7 +1486,7 @@ Target_powerpc::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::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::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 ee82367f9e..e1bdc8e0f3 100644 --- a/gold/sparc.cc +++ b/gold/sparc.cc @@ -2333,7 +2333,7 @@ Target_sparc::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::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 3962e1ea36..d67924b379 100644 --- a/gold/x86_64.cc +++ b/gold/x86_64.cc @@ -1667,24 +1667,24 @@ Target_x86_64::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::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::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); } } }