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.
This commit is contained in:
David S. Miller 2012-04-17 01:50:39 +00:00
parent 31821be097
commit 13cf9988bc
6 changed files with 69 additions and 43 deletions

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}