aboutsummaryrefslogtreecommitdiff
path: root/gold/output.cc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>2010-01-08 19:33:18 +0000
committerIan Lance Taylor <ian@airs.com>2010-01-08 19:33:18 +0000
commite291e7b9c9cd9e432fdcc63922f2529647f5b930 (patch)
treedf4d976076d4d37f7b062a60f9f6bcb47b7f0ddb /gold/output.cc
parentdd35de74344bc1dad410ed21fedd14671ab57aff (diff)
downloadfsf-binutils-gdb-e291e7b9c9cd9e432fdcc63922f2529647f5b930.zip
fsf-binutils-gdb-e291e7b9c9cd9e432fdcc63922f2529647f5b930.tar.gz
fsf-binutils-gdb-e291e7b9c9cd9e432fdcc63922f2529647f5b930.tar.bz2
PR 10287
PR 11063 * i386.cc (class Target_i386): Change return type of plt_section to be non-const. (class Output_data_plt_i386): Add tls_desc_rel_ field. (Output_data_plt_i386::Output_data_plt_i386): Initialize tls_desc_rel_ field. (Output_data_plt_i386::rel_tls_desc): New function. (Target_i386::rel_tls_desc_section): New function. (Target_i386::Scan::local): Rewrite R_386_TLS_GOTDESC handling. (Target_i386::Scan::global): For R_386_TLS_GOTDESC put R_386_TLS_DESC reloc in rel_tls_desc_section. * x86_64.cc (class Target_x86_64): Add tlsdesc_reloc_info_ field. Define struct Tlsdesc_info. (Target_x86_64::Target_x86_64): Initialize tlsdesc_reloc_info_. (Target_x86_64::do_reloc_symbol_index): New function. (Target_x86_64::add_tlsdesc_info): New function. (class Output_data_plt_x86_64): Add tlsdesc_rel_ field. (Output_data_plt_x86_64::Output_data_plt_x86_64): Initialize tlsdesc_rel_ field. (Output_data_plt_x86_64::rela_plt): Rename from rel_plt. Change all callers. (Output_data_plt_x86_64::rela_tlsdesc): New function. (Target_x86_64::rela_tlsdesc_section): New function. (Target_x86_64::Scan::local): Rewrite R_X86_64_GOTPC32_TLSDESC handling. (Target_x86_64::Scan::global): For R_X86_64_GOTPC32_TLSDESC put (Target_x86_64::do_reloc_addend): New function. R_X86_64_TLSDESC reloc in rela_tlsdesc_section. * output.h (class Output_reloc) [SHT_REL]: Add new constructor declarations. Define TARGET_CODE. Add arg field to u1_ union. (Output_reloc::type): New function. (Output_reloc::is_local_section_symbol): Check for TARGET_CODE. (Output_reloc::is_target_specific): New function. (Output_reloc::target_arg): New function. (class Output_reloc) [SHT_RELA]: Add four new constructors for absolute relocs and target specific relocs. (class Output_data_reloc) [SHT_REL]: Add add_absolute and add_target_specific. (class Output_data_reloc) [SHT_RELA]: Likewise. * output.cc (Output_reloc::Output_reloc): Add four new versions for absolute relocs and target specific relocs. (Output_reloc::set_needs_dynsym_index): Add TARGET_CODE case. (Output_reloc::get_symbol_index): Likewise. (Output_reloc::local_section_offset): Check that local_sym_index_ is not TARGET_CODE or 0. (Output_reloc::symbol_value): Likewise. (Output_reloc::write) [SHT_RELA]: Call target for target specific reloc. * target.h (class Target): Add reloc_symbol_index and reloc_addend functions. Add do_reloc_symbol_index and do_reloc_addend virtual functions. * layout.cc (add_target_dynamic_tags): Use output section for DT_PLTRELSZ and DT_JMPREL.
Diffstat (limited to 'gold/output.cc')
-rw-r--r--gold/output.cc84
1 files changed, 83 insertions, 1 deletions
diff --git a/gold/output.cc b/gold/output.cc
index b9ded6e..bb61d86 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -756,6 +756,72 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
os->set_needs_symtab_index();
}
+// An absolute relocation.
+
+template<bool dynamic, int size, bool big_endian>
+Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
+ unsigned int type,
+ Output_data* od,
+ Address address)
+ : address_(address), local_sym_index_(0), type_(type),
+ is_relative_(false), is_section_symbol_(false), shndx_(INVALID_CODE)
+{
+ // this->type_ is a bitfield; make sure TYPE fits.
+ gold_assert(this->type_ == type);
+ this->u1_.relobj = NULL;
+ this->u2_.od = od;
+}
+
+template<bool dynamic, int size, bool big_endian>
+Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
+ unsigned int type,
+ Sized_relobj<size, big_endian>* relobj,
+ unsigned int shndx,
+ Address address)
+ : address_(address), local_sym_index_(0), type_(type),
+ is_relative_(false), is_section_symbol_(false), shndx_(shndx)
+{
+ gold_assert(shndx != INVALID_CODE);
+ // this->type_ is a bitfield; make sure TYPE fits.
+ gold_assert(this->type_ == type);
+ this->u1_.relobj = NULL;
+ this->u2_.relobj = relobj;
+}
+
+// A target specific relocation.
+
+template<bool dynamic, int size, bool big_endian>
+Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
+ unsigned int type,
+ void* arg,
+ Output_data* od,
+ Address address)
+ : address_(address), local_sym_index_(TARGET_CODE), type_(type),
+ is_relative_(false), is_section_symbol_(false), shndx_(INVALID_CODE)
+{
+ // this->type_ is a bitfield; make sure TYPE fits.
+ gold_assert(this->type_ == type);
+ this->u1_.arg = arg;
+ this->u2_.od = od;
+}
+
+template<bool dynamic, int size, bool big_endian>
+Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
+ unsigned int type,
+ void* arg,
+ Sized_relobj<size, big_endian>* relobj,
+ unsigned int shndx,
+ Address address)
+ : address_(address), local_sym_index_(TARGET_CODE), type_(type),
+ is_relative_(false), is_section_symbol_(false), shndx_(shndx)
+{
+ gold_assert(shndx != INVALID_CODE);
+ // this->type_ is a bitfield; make sure TYPE fits.
+ gold_assert(this->type_ == type);
+ this->u1_.arg = arg;
+ this->u2_.relobj = relobj;
+}
+
// Record that we need a dynamic symbol index for this relocation.
template<bool dynamic, int size, bool big_endian>
@@ -778,6 +844,10 @@ set_needs_dynsym_index()
this->u1_.os->set_needs_dynsym_index();
break;
+ case TARGET_CODE:
+ // The target must take care of this if necessary.
+ break;
+
case 0:
break;
@@ -822,6 +892,11 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::get_symbol_index()
index = this->u1_.os->symtab_index();
break;
+ case TARGET_CODE:
+ index = parameters->target().reloc_symbol_index(this->u1_.arg,
+ this->type_);
+ break;
+
case 0:
// Relocations without symbols use a symbol index of 0.
index = 0;
@@ -863,7 +938,9 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::
{
gold_assert(this->local_sym_index_ != GSYM_CODE
&& this->local_sym_index_ != SECTION_CODE
+ && this->local_sym_index_ != TARGET_CODE
&& this->local_sym_index_ != INVALID_CODE
+ && this->local_sym_index_ != 0
&& this->is_section_symbol_);
const unsigned int lsi = this->local_sym_index_;
Output_section* os = this->u1_.relobj->output_section(lsi);
@@ -942,7 +1019,9 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::symbol_value(
return sym->value() + addend;
}
gold_assert(this->local_sym_index_ != SECTION_CODE
+ && this->local_sym_index_ != TARGET_CODE
&& this->local_sym_index_ != INVALID_CODE
+ && this->local_sym_index_ != 0
&& !this->is_section_symbol_);
const unsigned int lsi = this->local_sym_index_;
const Symbol_value<size>* symval = this->u1_.relobj->local_symbol(lsi);
@@ -1010,7 +1089,10 @@ Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>::write(
elfcpp::Rela_write<size, big_endian> orel(pov);
this->rel_.write_rel(&orel);
Addend addend = this->addend_;
- if (this->rel_.is_relative())
+ if (this->rel_.is_target_specific())
+ addend = parameters->target().reloc_addend(this->rel_.target_arg(),
+ this->rel_.type(), addend);
+ else if (this->rel_.is_relative())
addend = this->rel_.symbol_value(addend);
else if (this->rel_.is_local_section_symbol())
addend = this->rel_.local_section_offset(addend);