From 397b129b2a1e3d186e62ff37ecdbc329bf6bbc53 Mon Sep 17 00:00:00 2001 From: Cary Coutant Date: Mon, 10 Oct 2011 17:29:52 +0000 Subject: [PATCH] PR gold/13249 * gold/output.cc (Output_reloc::Output_reloc): Add use_plt_offset flag. (Output_reloc::symbol_value): Return PLT offset if flag is set. * gold/output.h (class Output_reloc): Add use_plt_offset flag. (Output_reloc::type_): Adjust size of bit field. (Output_reloc::use_plt_offset_): New bit field. (class Output_data_reloc): Adjust all calls to Output_reloc_type. (Output_data_reloc::add_local_relative): (RELA only) Add use_plt_offset flag. Adjust all callers. * gold/x86_64.cc (Target_x86_64::Scan::local): Check for IFUNC when creating RELATIVE relocations. --- gold/ChangeLog | 14 +++++++++++ gold/output.cc | 34 ++++++++++++++++---------- gold/output.h | 64 ++++++++++++++++++++++++++++++------------------- gold/powerpc.cc | 4 ++-- gold/sparc.cc | 4 ++-- gold/x86_64.cc | 12 +++++----- 6 files changed, 85 insertions(+), 47 deletions(-) diff --git a/gold/ChangeLog b/gold/ChangeLog index 5e0a3352c7f..318e5156d28 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,17 @@ +2011-10-10 Cary Coutant + + PR gold/13249 + * gold/output.cc (Output_reloc::Output_reloc): Add use_plt_offset flag. + (Output_reloc::symbol_value): Return PLT offset if flag is set. + * gold/output.h (class Output_reloc): Add use_plt_offset flag. + (Output_reloc::type_): Adjust size of bit field. + (Output_reloc::use_plt_offset_): New bit field. + (class Output_data_reloc): Adjust all calls to Output_reloc_type. + (Output_data_reloc::add_local_relative): (RELA only) Add use_plt_offset + flag. Adjust all callers. + * gold/x86_64.cc (Target_x86_64::Scan::local): Check for IFUNC when + creating RELATIVE relocations. + 2011-10-10 Nick Clifton * po/es.po: Updated Spanish translation. diff --git a/gold/output.cc b/gold/output.cc index 63f01090c89..d6bdabacbc5 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -706,7 +706,7 @@ Output_reloc::Output_reloc( bool is_symbolless) : address_(address), local_sym_index_(GSYM_CODE), type_(type), is_relative_(is_relative), is_symbolless_(is_symbolless), - is_section_symbol_(false), shndx_(INVALID_CODE) + is_section_symbol_(false), use_plt_offset_(false), shndx_(INVALID_CODE) { // this->type_ is a bitfield; make sure TYPE fits. gold_assert(this->type_ == type); @@ -727,7 +727,7 @@ Output_reloc::Output_reloc( bool is_symbolless) : address_(address), local_sym_index_(GSYM_CODE), type_(type), is_relative_(is_relative), is_symbolless_(is_symbolless), - is_section_symbol_(false), shndx_(shndx) + is_section_symbol_(false), use_plt_offset_(false), shndx_(shndx) { gold_assert(shndx != INVALID_CODE); // this->type_ is a bitfield; make sure TYPE fits. @@ -749,10 +749,12 @@ Output_reloc::Output_reloc( Address address, bool is_relative, bool is_symbolless, - bool is_section_symbol) + bool is_section_symbol, + bool use_plt_offset) : address_(address), local_sym_index_(local_sym_index), type_(type), is_relative_(is_relative), is_symbolless_(is_symbolless), - is_section_symbol_(is_section_symbol), shndx_(INVALID_CODE) + is_section_symbol_(is_section_symbol), use_plt_offset_(use_plt_offset), + shndx_(INVALID_CODE) { gold_assert(local_sym_index != GSYM_CODE && local_sym_index != INVALID_CODE); @@ -773,10 +775,12 @@ Output_reloc::Output_reloc( Address address, bool is_relative, bool is_symbolless, - bool is_section_symbol) + bool is_section_symbol, + bool use_plt_offset) : address_(address), local_sym_index_(local_sym_index), type_(type), is_relative_(is_relative), is_symbolless_(is_symbolless), - is_section_symbol_(is_section_symbol), shndx_(shndx) + is_section_symbol_(is_section_symbol), use_plt_offset_(use_plt_offset), + shndx_(shndx) { gold_assert(local_sym_index != GSYM_CODE && local_sym_index != INVALID_CODE); @@ -799,7 +803,7 @@ Output_reloc::Output_reloc( Address address) : address_(address), local_sym_index_(SECTION_CODE), type_(type), is_relative_(false), is_symbolless_(false), - is_section_symbol_(true), shndx_(INVALID_CODE) + is_section_symbol_(true), use_plt_offset_(false), shndx_(INVALID_CODE) { // this->type_ is a bitfield; make sure TYPE fits. gold_assert(this->type_ == type); @@ -820,7 +824,7 @@ Output_reloc::Output_reloc( Address address) : address_(address), local_sym_index_(SECTION_CODE), type_(type), is_relative_(false), is_symbolless_(false), - is_section_symbol_(true), shndx_(shndx) + is_section_symbol_(true), use_plt_offset_(false), shndx_(shndx) { gold_assert(shndx != INVALID_CODE); // this->type_ is a bitfield; make sure TYPE fits. @@ -842,7 +846,7 @@ Output_reloc::Output_reloc( Address address) : address_(address), local_sym_index_(0), type_(type), is_relative_(false), is_symbolless_(false), - is_section_symbol_(false), shndx_(INVALID_CODE) + is_section_symbol_(false), use_plt_offset_(false), shndx_(INVALID_CODE) { // this->type_ is a bitfield; make sure TYPE fits. gold_assert(this->type_ == type); @@ -858,7 +862,7 @@ Output_reloc::Output_reloc( Address address) : address_(address), local_sym_index_(0), type_(type), is_relative_(false), is_symbolless_(false), - is_section_symbol_(false), shndx_(shndx) + is_section_symbol_(false), use_plt_offset_(false), shndx_(shndx) { gold_assert(shndx != INVALID_CODE); // this->type_ is a bitfield; make sure TYPE fits. @@ -877,7 +881,7 @@ Output_reloc::Output_reloc( Address address) : address_(address), local_sym_index_(TARGET_CODE), type_(type), is_relative_(false), is_symbolless_(false), - is_section_symbol_(false), shndx_(INVALID_CODE) + is_section_symbol_(false), use_plt_offset_(false), shndx_(INVALID_CODE) { // this->type_ is a bitfield; make sure TYPE fits. gold_assert(this->type_ == type); @@ -894,7 +898,7 @@ Output_reloc::Output_reloc( Address address) : address_(address), local_sym_index_(TARGET_CODE), type_(type), is_relative_(false), is_symbolless_(false), - is_section_symbol_(false), shndx_(shndx) + is_section_symbol_(false), use_plt_offset_(false), shndx_(shndx) { gold_assert(shndx != INVALID_CODE); // this->type_ is a bitfield; make sure TYPE fits. @@ -1121,6 +1125,12 @@ Output_reloc::symbol_value( Sized_relobj_file* relobj = this->u1_.relobj->sized_relobj(); gold_assert(relobj != NULL); + if (this->use_plt_offset_) + { + uint64_t plt_address = + parameters->target().plt_address_for_local(relobj, lsi); + return plt_address + relobj->local_plt_offset(lsi); + } const Symbol_value* symval = relobj->local_symbol(lsi); return symval->value(relobj, addend); } diff --git a/gold/output.h b/gold/output.h index cabec5c8d37..e704213b0cb 100644 --- a/gold/output.h +++ b/gold/output.h @@ -1033,12 +1033,14 @@ class Output_reloc Output_reloc(Sized_relobj* relobj, unsigned int local_sym_index, unsigned int type, Output_data* od, Address address, bool is_relative, - bool is_symbolless, bool is_section_symbol); + bool is_symbolless, bool is_section_symbol, + bool use_plt_offset); Output_reloc(Sized_relobj* relobj, unsigned int local_sym_index, unsigned int type, unsigned int shndx, Address address, bool is_relative, - bool is_symbolless, bool is_section_symbol); + bool is_symbolless, bool is_section_symbol, + bool use_plt_offset); // A reloc against the STT_SECTION symbol of an output section. @@ -1216,7 +1218,7 @@ class Output_reloc // input file. unsigned int local_sym_index_; // The reloc type--a processor specific code. - unsigned int type_ : 29; + unsigned int type_ : 28; // True if the relocation is a RELATIVE relocation. bool is_relative_ : 1; // True if the relocation is one which should not use @@ -1224,6 +1226,10 @@ 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. + // (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 // section index. This is INVALID_CODE if the reloc address is // specified in some other way. @@ -1268,9 +1274,10 @@ class Output_reloc unsigned int local_sym_index, unsigned int type, Output_data* od, Address address, Addend addend, bool is_relative, - bool is_symbolless, bool is_section_symbol) + bool is_symbolless, bool is_section_symbol, + bool use_plt_offset) : rel_(relobj, local_sym_index, type, od, address, is_relative, - is_symbolless, is_section_symbol), + is_symbolless, is_section_symbol, use_plt_offset), addend_(addend) { } @@ -1278,9 +1285,10 @@ class Output_reloc unsigned int local_sym_index, unsigned int type, unsigned int shndx, Address address, Addend addend, bool is_relative, - bool is_symbolless, bool is_section_symbol) + bool is_symbolless, bool is_section_symbol, + bool use_plt_offset) : rel_(relobj, local_sym_index, type, shndx, address, is_relative, - is_symbolless, is_section_symbol), + is_symbolless, is_section_symbol, use_plt_offset), addend_(addend) { } @@ -1571,7 +1579,7 @@ class Output_data_reloc Output_data* od, Address address) { this->add(od, Output_reloc_type(relobj, local_sym_index, type, od, - address, false, false, false)); + address, false, false, false, false)); } void @@ -1580,7 +1588,7 @@ class Output_data_reloc Output_data* od, unsigned int shndx, Address address) { this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx, - address, false, false, false)); + address, false, false, false, false)); } // Add a RELATIVE reloc against a local symbol. @@ -1591,7 +1599,7 @@ class Output_data_reloc Output_data* od, Address address) { this->add(od, Output_reloc_type(relobj, local_sym_index, type, od, - address, true, true, false)); + address, true, true, false, false)); } void @@ -1600,7 +1608,7 @@ class Output_data_reloc Output_data* od, unsigned int shndx, Address address) { this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx, - address, true, true, false)); + address, true, true, false, false)); } // Add a local relocation which does not use a symbol for the relocation, @@ -1612,7 +1620,7 @@ class Output_data_reloc Output_data* od, Address address) { this->add(od, Output_reloc_type(relobj, local_sym_index, type, od, - address, false, true, false)); + address, false, true, false, false)); } void @@ -1622,7 +1630,7 @@ class Output_data_reloc Address address) { this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx, - address, false, true, false)); + address, false, true, false, false)); } // Add a reloc against a local section symbol. This will be @@ -1635,7 +1643,7 @@ class Output_data_reloc Output_data* od, Address address) { this->add(od, Output_reloc_type(relobj, input_shndx, type, od, - address, false, false, true)); + address, false, false, true, false)); } void @@ -1644,7 +1652,7 @@ class Output_data_reloc Output_data* od, unsigned int shndx, Address address) { this->add(od, Output_reloc_type(relobj, input_shndx, type, shndx, - address, false, false, true)); + address, false, false, true, false)); } // A reloc against the STT_SECTION symbol of an output section. @@ -1767,7 +1775,7 @@ class Output_data_reloc Output_data* od, Address address, Addend addend) { this->add(od, Output_reloc_type(relobj, local_sym_index, type, od, address, - addend, false, false, false)); + addend, false, false, false, false)); } void @@ -1777,7 +1785,8 @@ class Output_data_reloc Addend addend) { this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx, - address, addend, false, false, false)); + address, addend, false, false, false, + false)); } // Add a RELATIVE reloc against a local symbol. @@ -1785,20 +1794,23 @@ class Output_data_reloc void add_local_relative(Sized_relobj* relobj, unsigned int local_sym_index, unsigned int type, - Output_data* od, Address address, Addend addend) + Output_data* od, Address address, Addend addend, + bool use_plt_offset) { this->add(od, Output_reloc_type(relobj, local_sym_index, type, od, address, - addend, true, true, false)); + addend, true, true, false, + use_plt_offset)); } void add_local_relative(Sized_relobj* relobj, unsigned int local_sym_index, unsigned int type, Output_data* od, unsigned int shndx, Address address, - Addend addend) + Addend addend, bool use_plt_offset) { this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx, - address, addend, true, true, false)); + address, addend, true, true, false, + use_plt_offset)); } // Add a local relocation which does not use a symbol for the relocation, @@ -1810,7 +1822,7 @@ class Output_data_reloc Output_data* od, Address address, Addend addend) { this->add(od, Output_reloc_type(relobj, local_sym_index, type, od, address, - addend, false, true, false)); + addend, false, true, false, false)); } void @@ -1820,7 +1832,8 @@ class Output_data_reloc Address address, Addend addend) { this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx, - address, addend, false, true, false)); + address, addend, false, true, false, + false)); } // Add a reloc against a local section symbol. This will be @@ -1833,7 +1846,7 @@ class Output_data_reloc Output_data* od, Address address, Addend addend) { this->add(od, Output_reloc_type(relobj, input_shndx, type, od, address, - addend, false, false, true)); + addend, false, false, true, false)); } void @@ -1843,7 +1856,8 @@ class Output_data_reloc Addend addend) { this->add(od, Output_reloc_type(relobj, input_shndx, type, shndx, - address, addend, false, false, true)); + address, addend, false, false, true, + false)); } // A reloc against the STT_SECTION symbol of an output section. diff --git a/gold/powerpc.cc b/gold/powerpc.cc index 45783c3933f..62a17ca7ac6 100644 --- a/gold/powerpc.cc +++ b/gold/powerpc.cc @@ -1329,7 +1329,7 @@ Target_powerpc::Scan::local( rela_dyn->add_local_relative(object, r_sym, r_type, output_section, data_shndx, reloc.get_r_offset(), - reloc.get_r_addend()); + reloc.get_r_addend(), false); } } break; @@ -1372,7 +1372,7 @@ Target_powerpc::Scan::local( object->set_local_got_offset(r_sym, GOT_TYPE_STANDARD, off); rela_dyn->add_local_relative(object, r_sym, elfcpp::R_POWERPC_RELATIVE, - got, off, 0); + got, off, 0, false); } } else diff --git a/gold/sparc.cc b/gold/sparc.cc index 9145fcb0ead..1d2cbad319d 100644 --- a/gold/sparc.cc +++ b/gold/sparc.cc @@ -1852,7 +1852,7 @@ Target_sparc::Scan::local( rela_dyn->add_local_relative(object, r_sym, elfcpp::R_SPARC_RELATIVE, output_section, data_shndx, reloc.get_r_offset(), - reloc.get_r_addend()); + reloc.get_r_addend(), false); } break; @@ -1943,7 +1943,7 @@ Target_sparc::Scan::local( object->set_local_got_offset(r_sym, GOT_TYPE_STANDARD, off); rela_dyn->add_local_relative(object, r_sym, elfcpp::R_SPARC_RELATIVE, - got, off, 0); + got, off, 0, false); } } else diff --git a/gold/x86_64.cc b/gold/x86_64.cc index e6b00210762..e61d7d1bf59 100644 --- a/gold/x86_64.cc +++ b/gold/x86_64.cc @@ -1549,7 +1549,7 @@ Target_x86_64::reserve_local_got_entry( case GOT_TYPE_STANDARD: if (parameters->options().output_is_position_independent()) rela_dyn->add_local_relative(obj, r_sym, 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_local(obj, r_sym, elfcpp::R_X86_64_TPOFF64, @@ -1953,8 +1953,8 @@ Target_x86_64::Scan::local(Symbol_table* symtab, const elfcpp::Sym<64, false>& lsym) { // A local STT_GNU_IFUNC symbol may require a PLT entry. - if (lsym.get_st_type() == elfcpp::STT_GNU_IFUNC - && this->reloc_needs_plt_for_ifunc(object, r_type)) + bool is_ifunc = lsym.get_st_type() == elfcpp::STT_GNU_IFUNC; + if (is_ifunc && this->reloc_needs_plt_for_ifunc(object, r_type)) { unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info()); target->make_local_ifunc_plt_entry(symtab, layout, object, r_sym); @@ -1982,7 +1982,7 @@ Target_x86_64::Scan::local(Symbol_table* symtab, elfcpp::R_X86_64_RELATIVE, output_section, data_shndx, reloc.get_r_offset(), - reloc.get_r_addend()); + reloc.get_r_addend(), is_ifunc); } break; @@ -2058,7 +2058,7 @@ Target_x86_64::Scan::local(Symbol_table* symtab, // lets function pointers compare correctly with shared // libraries. Otherwise we would need an IRELATIVE reloc. bool is_new; - if (lsym.get_st_type() == elfcpp::STT_GNU_IFUNC) + if (is_ifunc) is_new = got->add_local_plt(object, r_sym, GOT_TYPE_STANDARD); else is_new = got->add_local(object, r_sym, GOT_TYPE_STANDARD); @@ -2076,7 +2076,7 @@ Target_x86_64::Scan::local(Symbol_table* symtab, object->local_got_offset(r_sym, GOT_TYPE_STANDARD); rela_dyn->add_local_relative(object, r_sym, elfcpp::R_X86_64_RELATIVE, - got, got_offset, 0); + got, got_offset, 0, is_ifunc); } else { -- 2.30.2