summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid S. Miller <davem@redhat.com>2012-04-17 01:50:39 +0000
committerDavid S. Miller <davem@redhat.com>2012-04-17 01:50:39 +0000
commit13cf9988bc2852ba66d6096578a518c94bfccdcd (patch)
tree683c5e39327f7de26f38a4205562ed60446491b4
parent31821be097c4154d3d7d201d9f4939a47af97ac6 (diff)
downloadbinutils-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/ChangeLog13
-rw-r--r--gold/output.cc19
-rw-r--r--gold/output.h56
-rw-r--r--gold/powerpc.cc6
-rw-r--r--gold/sparc.cc4
-rw-r--r--gold/x86_64.cc14
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);
}
}
}