summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCary Coutant <ccoutant@gmail.com>2017-04-25 19:21:57 -0700
committerCary Coutant <ccoutant@gmail.com>2017-04-25 20:07:52 -0700
commit8c13bcd2209cb776aa2cf7e5016b7884b0aecbf6 (patch)
treedc131c444a7e2a372b057cca03b68bc21ae50f28
parent4658f12e9c5ec0d2efb04f1688f6cd6bd9f1a47d (diff)
downloadbinutils-gdb-users/ccoutant/experimental-relr.tar.gz
Experimental implementation of RELR-style relocations.users/ccoutant/experimental-relr
For x86-64 only. Instead of R_X86_64_RELATIVE relocations, we write the offsets of the relocation targets to a new section, .relr.dyn, with section type SHT_RELR.
-rw-r--r--elfcpp/elfcpp.h49
-rw-r--r--elfcpp/elfcpp_internal.h6
-rw-r--r--gold/layout.cc11
-rw-r--r--gold/layout.h3
-rw-r--r--gold/options.h4
-rw-r--r--gold/output.cc33
-rw-r--r--gold/output.h219
-rw-r--r--gold/reloc-types.h21
-rw-r--r--gold/x86_64.cc135
9 files changed, 446 insertions, 35 deletions
diff --git a/elfcpp/elfcpp.h b/elfcpp/elfcpp.h
index cce40d41ded..d4c0a63b2bf 100644
--- a/elfcpp/elfcpp.h
+++ b/elfcpp/elfcpp.h
@@ -358,6 +358,7 @@ enum SHT
SHT_PREINIT_ARRAY = 16,
SHT_GROUP = 17,
SHT_SYMTAB_SHNDX = 18,
+ SHT_RELR = 19, // Experimental
SHT_LOOS = 0x60000000,
SHT_HIOS = 0x6fffffff,
SHT_LOPROC = 0x70000000,
@@ -719,6 +720,11 @@ enum DT
DT_PREINIT_ARRAY = 32,
DT_PREINIT_ARRAYSZ = 33,
+ DT_SYMTAB_SHNDX = 34,
+ DT_RELRSZ = 35, // Experimental
+ DT_RELR = 36, // Experimental
+ DT_RELRENT = 37, // Experimental
+
DT_LOOS = 0x6000000d,
DT_HIOS = 0x6ffff000,
DT_LOPROC = 0x70000000,
@@ -1021,6 +1027,7 @@ struct Elf_sizes
// Sizes of ELF reloc entries.
static const int rel_size = sizeof(internal::Rel_data<size>);
static const int rela_size = sizeof(internal::Rela_data<size>);
+ static const int relr_size = sizeof(internal::Relr_data<size>);
// Size of ELF dynamic entry.
static const int dyn_size = sizeof(internal::Dyn_data<size>);
// Size of ELF version structures.
@@ -1666,6 +1673,48 @@ class Rela_write
internal::Rela_data<size>* p_;
};
+// Accessor class for an ELF Relr relocation.
+
+template<int size, bool big_endian>
+class Relr
+{
+ public:
+ Relr(const unsigned char* p)
+ : p_(reinterpret_cast<const internal::Relr_data<size>*>(p))
+ { }
+
+ template<typename File>
+ Relr(File* file, typename File::Location loc)
+ : p_(reinterpret_cast<const internal::Relr_data<size>*>(
+ file->view(loc.file_offset, loc.data_size).data()))
+ { }
+
+ typename Elf_types<size>::Elf_Addr
+ get_r_offset() const
+ { return Convert<size, big_endian>::convert_host(this->p_->r_offset); }
+
+ private:
+ const internal::Relr_data<size>* p_;
+};
+
+// Writer class for an ELF Relr relocation.
+
+template<int size, bool big_endian>
+class Relr_write
+{
+ public:
+ Relr_write(unsigned char* p)
+ : p_(reinterpret_cast<internal::Relr_data<size>*>(p))
+ { }
+
+ void
+ put_r_offset(typename Elf_types<size>::Elf_Addr v)
+ { this->p_->r_offset = Convert<size, big_endian>::convert_host(v); }
+
+ private:
+ internal::Relr_data<size>* p_;
+};
+
// MIPS-64 has a non-standard relocation layout.
template<bool big_endian>
diff --git a/elfcpp/elfcpp_internal.h b/elfcpp/elfcpp_internal.h
index 14adfdef344..a1cfcf5ce6f 100644
--- a/elfcpp/elfcpp_internal.h
+++ b/elfcpp/elfcpp_internal.h
@@ -180,6 +180,12 @@ struct Rela_data
typename Elf_types<size>::Elf_Swxword r_addend;
};
+template<int size>
+struct Relr_data
+{
+ typename Elf_types<size>::Elf_Addr r_offset;
+};
+
// MIPS-64 has a non-standard layout for relocations.
struct Mips64_rel_data
diff --git a/gold/layout.cc b/gold/layout.cc
index 07a359074e0..504028a968e 100644
--- a/gold/layout.cc
+++ b/gold/layout.cc
@@ -4710,7 +4710,8 @@ void
Layout::add_target_dynamic_tags(bool use_rel, const Output_data* plt_got,
const Output_data* plt_rel,
const Output_data_reloc_generic* dyn_rel,
- bool add_debug, bool dynrel_includes_plt)
+ bool add_debug, bool dynrel_includes_plt,
+ const Output_data_reloc_generic* dyn_relr)
{
Output_data_dynamic* odyn = this->dynamic_data_;
if (odyn == NULL)
@@ -4783,6 +4784,14 @@ Layout::add_target_dynamic_tags(bool use_rel, const Output_data* plt_got,
}
}
+ if (dyn_relr != NULL && dyn_relr->output_section() != NULL)
+ {
+ const int size = parameters->target().get_size();
+ odyn->add_section_address(elfcpp::DT_RELR, dyn_relr->output_section());
+ odyn->add_section_size(elfcpp::DT_RELRSZ, dyn_relr->output_section());
+ odyn->add_constant(elfcpp::DT_RELRENT, size / 8);
+ }
+
if (add_debug && !parameters->options().shared())
{
// The value of the DT_DEBUG tag is filled in by the dynamic
diff --git a/gold/layout.h b/gold/layout.h
index 5f58c2c67f6..5852898cc3f 100644
--- a/gold/layout.h
+++ b/gold/layout.h
@@ -900,7 +900,8 @@ class Layout
add_target_dynamic_tags(bool use_rel, const Output_data* plt_got,
const Output_data* plt_rel,
const Output_data_reloc_generic* dyn_rel,
- bool add_debug, bool dynrel_includes_plt);
+ bool add_debug, bool dynrel_includes_plt,
+ const Output_data_reloc_generic* dyn_relr = NULL);
// Add a target-specific dynamic tag with constant value.
void
diff --git a/gold/options.h b/gold/options.h
index a8b1d46aa10..b08acad34a1 100644
--- a/gold/options.h
+++ b/gold/options.h
@@ -834,6 +834,10 @@ class General_options
N_("Exclude libraries from automatic export"),
N_(("lib,lib ...")));
+ DEFINE_bool(experimental_use_relr, options::TWO_DASHES, '\0', false,
+ N_("(x86-64 only) Generate RELR dynamic relocations"),
+ N_("Do not generate RELR dynamic relocations"));
+
DEFINE_bool(export_dynamic, options::TWO_DASHES, 'E', false,
N_("Export all dynamic symbols"),
N_("Do not export all dynamic symbols"));
diff --git a/gold/output.cc b/gold/output.cc
index 5b1e601d491..8c27ad49779 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -1224,6 +1224,17 @@ Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>::write(
orel.put_r_addend(addend);
}
+// Write out a Relr relocation.
+
+template<bool dynamic, int size, bool big_endian>
+void
+Output_reloc<elfcpp::SHT_RELR, dynamic, size, big_endian>::write(
+ unsigned char* pov) const
+{
+ elfcpp::Relr_write<size, big_endian> orel(pov);
+ orel.put_r_offset(this->rel_.get_address());
+}
+
// Output_data_reloc_base methods.
// Adjust the output section.
@@ -1237,6 +1248,8 @@ Output_data_reloc_base<sh_type, dynamic, size, big_endian>
os->set_entsize(elfcpp::Elf_sizes<size>::rel_size);
else if (sh_type == elfcpp::SHT_RELA)
os->set_entsize(elfcpp::Elf_sizes<size>::rela_size);
+ else if (sh_type == elfcpp::SHT_RELR)
+ os->set_entsize(elfcpp::Elf_sizes<size>::relr_size);
else
gold_unreachable();
@@ -5528,6 +5541,26 @@ class Output_data_reloc<elfcpp::SHT_RELA, true, 64, true>;
#ifdef HAVE_TARGET_32_LITTLE
template
+class Output_data_reloc<elfcpp::SHT_RELR, true, 32, false>;
+#endif
+
+#ifdef HAVE_TARGET_32_BIG
+template
+class Output_data_reloc<elfcpp::SHT_RELR, true, 32, true>;
+#endif
+
+#ifdef HAVE_TARGET_64_LITTLE
+template
+class Output_data_reloc<elfcpp::SHT_RELR, true, 64, false>;
+#endif
+
+#ifdef HAVE_TARGET_64_BIG
+template
+class Output_data_reloc<elfcpp::SHT_RELR, true, 64, true>;
+#endif
+
+#ifdef HAVE_TARGET_32_LITTLE
+template
class Output_relocatable_relocs<elfcpp::SHT_REL, 32, false>;
#endif
diff --git a/gold/output.h b/gold/output.h
index 157cef272d8..f33a7f838a0 100644
--- a/gold/output.h
+++ b/gold/output.h
@@ -1500,6 +1500,104 @@ class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
Addend addend_;
};
+// The SHT_RELR version of Output_reloc<>. This is a relative reloc,
+// and holds nothing but an offset. Rather than duplicate all the fields
+// of the SHT_REL version except for the symbol and relocation type, we
+// simply use an SHT_REL as a proxy.
+
+template<bool dynamic, int size, bool big_endian>
+class Output_reloc<elfcpp::SHT_RELR, dynamic, size, big_endian>
+{
+ public:
+ typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
+
+ // An uninitialized entry.
+ Output_reloc()
+ : rel_()
+ { }
+
+ // A reloc against a global symbol.
+
+ Output_reloc(Symbol* gsym, Output_data* od, Address address)
+ : rel_(gsym, 0, od, address, true, true, false)
+ { }
+
+ Output_reloc(Symbol* gsym, Sized_relobj<size, big_endian>* relobj,
+ unsigned int shndx, Address address)
+ : rel_(gsym, 0, relobj, shndx, address, true, true, false)
+ { }
+
+ // A reloc against a local symbol.
+
+ Output_reloc(Sized_relobj<size, big_endian>* relobj,
+ unsigned int local_sym_index, Output_data* od, Address address,
+ bool is_section_symbol)
+ : rel_(relobj, local_sym_index, 0, od, address, true,
+ true, is_section_symbol, false)
+ { }
+
+ Output_reloc(Sized_relobj<size, big_endian>* relobj,
+ unsigned int local_sym_index, unsigned int shndx,
+ Address address, bool is_section_symbol)
+ : rel_(relobj, local_sym_index, 0, shndx, address, true,
+ true, is_section_symbol, false)
+ { }
+
+ // A reloc against the STT_SECTION symbol of an output section.
+
+ Output_reloc(Output_section* os, Output_data* od, Address address)
+ : rel_(os, 0, od, address, true)
+ { }
+
+ Output_reloc(Output_section* os, Sized_relobj<size, big_endian>* relobj,
+ unsigned int shndx, Address address)
+ : rel_(os, 0, relobj, shndx, address, true)
+ { }
+
+ // A relative relocation with no symbol.
+
+ Output_reloc(Output_data* od, Address address)
+ : rel_(0, od, address, true)
+ { }
+
+ Output_reloc(Sized_relobj<size, big_endian>* relobj,
+ unsigned int shndx, Address address)
+ : rel_(0, relobj, shndx, address, true)
+ { }
+
+ // Return whether this is a RELATIVE relocation.
+ bool
+ is_relative() const
+ { return true; }
+
+ // Return whether this is a relocation which should not use
+ // a symbol, but which obtains its addend from a symbol.
+ bool
+ is_symbolless() const
+ { return true; }
+
+ // If this relocation is against an input section, return the
+ // relocatable object containing the input section.
+ Sized_relobj<size, big_endian>*
+ get_relobj() const
+ { return this->rel_.get_relobj(); }
+
+ // Write the reloc entry to an output view.
+ void
+ write(unsigned char* pov) const;
+
+ // Return whether this reloc should be sorted before the argument
+ // when sorting dynamic relocs.
+ bool
+ sort_before(const Output_reloc<elfcpp::SHT_RELR, dynamic, size, big_endian>&
+ r2) const
+ { return this->rel_.compare(r2.rel_) < 0; }
+
+ private:
+ // The basic reloc.
+ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian> rel_;
+};
+
// Output_data_reloc_generic is a non-template base class for
// Output_data_reloc_base. This gives the generic code a way to hold
// a pointer to a reloc section.
@@ -2344,6 +2442,127 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
}
};
+// The SHT_RELR version of Output_data_reloc.
+
+template<bool dynamic, int size, bool big_endian>
+class Output_data_reloc<elfcpp::SHT_RELR, dynamic, size, big_endian>
+ : public Output_data_reloc_base<elfcpp::SHT_RELR, dynamic, size, big_endian>
+{
+ private:
+ typedef Output_data_reloc_base<elfcpp::SHT_RELR, dynamic, size,
+ big_endian> Base;
+
+ public:
+ typedef typename Base::Output_reloc_type Output_reloc_type;
+ typedef typename Output_reloc_type::Address Address;
+
+ Output_data_reloc()
+ : Output_data_reloc_base<elfcpp::SHT_RELR, dynamic, size, big_endian>(false)
+ { }
+
+ void
+ add_global_generic(Symbol*, unsigned int, Output_data*, uint64_t, uint64_t)
+ {
+ gold_unreachable();
+ }
+
+ void
+ add_global_generic(Symbol*, unsigned int, Output_data*, Relobj*,
+ unsigned int, uint64_t, uint64_t)
+ {
+ gold_unreachable();
+ }
+
+ // Add a RELATIVE reloc against a global symbol. The final relocation
+ // will not reference the symbol.
+
+ void
+ add_global_relative(Symbol* gsym, Output_data* od, Address address)
+ {
+ this->add(od, Output_reloc_type(gsym, od, address));
+ }
+
+ void
+ add_global_relative(Symbol* gsym, Output_data* od,
+ Sized_relobj<size, big_endian>* relobj,
+ unsigned int shndx, Address address)
+ {
+ this->add(od, Output_reloc_type(gsym, relobj, shndx, address));
+ }
+
+ void
+ add_local_generic(Relobj*, unsigned int, unsigned int, Output_data*, uint64_t,
+ uint64_t)
+ {
+ gold_unreachable();
+ }
+
+ void
+ add_local_generic(Relobj*, unsigned int, unsigned int, Output_data*,
+ unsigned int, uint64_t, uint64_t)
+ {
+ gold_unreachable();
+ }
+
+ // Add a RELATIVE reloc against a local symbol.
+
+ void
+ add_local_relative(Sized_relobj<size, big_endian>* relobj,
+ unsigned int local_sym_index, Output_data* od,
+ Address address)
+ {
+ this->add(od, Output_reloc_type(relobj, local_sym_index, od, address,
+ false));
+ }
+
+ void
+ add_local_relative(Sized_relobj<size, big_endian>* relobj,
+ unsigned int local_sym_index, Output_data* od,
+ unsigned int shndx, Address address)
+ {
+ this->add(od, Output_reloc_type(relobj, local_sym_index, shndx, address,
+ false));
+ }
+
+ void
+ add_output_section_generic(Output_section*, unsigned int, Output_data*,
+ uint64_t, uint64_t)
+ {
+ gold_unreachable();
+ }
+
+ void
+ add_output_section_generic(Output_section*, unsigned int, Output_data*,
+ Relobj*, unsigned int, uint64_t, uint64_t)
+ {
+ gold_unreachable();
+ }
+
+ // Add a RELATIVE reloc against an output section symbol.
+
+ void
+ add_output_section_relative(Output_section* os, Output_data* od,
+ Address address)
+ { this->add(od, Output_reloc_type(os, od, address)); }
+
+ void
+ add_output_section_relative(Output_section* os, Output_data* od,
+ Sized_relobj<size, big_endian>* relobj,
+ unsigned int shndx, Address address)
+ { this->add(od, Output_reloc_type(os, relobj, shndx, address)); }
+
+ // Add a relative relocation
+
+ void
+ add_relative(Output_data* od, Address address)
+ { this->add(od, Output_reloc_type(od, address)); }
+
+ void
+ add_relative(Output_data* od, Sized_relobj<size, big_endian>* relobj,
+ unsigned int shndx, Address address)
+ { this->add(od, Output_reloc_type(relobj, shndx, address)); }
+};
+
// Output_relocatable_relocs represents a relocation section in a
// relocatable link. The actual data is written out in the target
// hook relocate_relocs. This just saves space for it.
diff --git a/gold/reloc-types.h b/gold/reloc-types.h
index eea7dd6b2df..f25cd5b8580 100644
--- a/gold/reloc-types.h
+++ b/gold/reloc-types.h
@@ -79,6 +79,27 @@ struct Reloc_types<elfcpp::SHT_RELA, size, big_endian>
{ p->put_r_addend(val); }
};
+template<int size, bool big_endian>
+struct Reloc_types<elfcpp::SHT_RELR, size, big_endian>
+{
+ typedef typename elfcpp::Relr<size, big_endian> Reloc;
+ typedef typename elfcpp::Relr_write<size, big_endian> Reloc_write;
+ static const int reloc_size = elfcpp::Elf_sizes<size>::relr_size;
+
+ static inline typename elfcpp::Elf_types<size>::Elf_Swxword
+ get_reloc_addend(const Reloc*)
+ { gold_unreachable(); }
+
+ static inline typename elfcpp::Elf_types<size>::Elf_Swxword
+ get_reloc_addend_noerror(const Reloc*)
+ { return 0; }
+
+ static inline void
+ set_reloc_addend(Reloc_write*,
+ typename elfcpp::Elf_types<size>::Elf_Swxword)
+ { gold_unreachable(); }
+};
+
}; // End namespace gold.
#endif // !defined(GOLD_RELOC_TYPE_SH)
diff --git a/gold/x86_64.cc b/gold/x86_64.cc
index 7f1742dd5f6..53c9d198a8e 100644
--- a/gold/x86_64.cc
+++ b/gold/x86_64.cc
@@ -584,13 +584,15 @@ class Target_x86_64 : public Sized_target<size, false>
// uses only Elf64_Rela relocation entries with explicit addends."
typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, false> Reloc_section;
+ typedef Output_data_reloc<elfcpp::SHT_RELR, true, size, false> Relr_section;
+
Target_x86_64(const Target::Target_info* info = &x86_64_info)
: Sized_target<size, false>(info),
got_(NULL), plt_(NULL), got_plt_(NULL), got_irelative_(NULL),
got_tlsdesc_(NULL), global_offset_table_(NULL), rela_dyn_(NULL),
- rela_irelative_(NULL), copy_relocs_(elfcpp::R_X86_64_COPY),
- got_mod_index_offset_(-1U), tlsdesc_reloc_info_(),
- tls_base_symbol_defined_(false)
+ rela_irelative_(NULL), relr_dyn_(NULL),
+ copy_relocs_(elfcpp::R_X86_64_COPY), got_mod_index_offset_(-1U),
+ tlsdesc_reloc_info_(), tls_base_symbol_defined_(false)
{ }
// Hook for a new output section.
@@ -1172,6 +1174,10 @@ class Target_x86_64 : public Sized_target<size, false>
Reloc_section*
rela_irelative_section(Layout*);
+ // Get the RELR dynamic reloc section, creating it if necessary.
+ Relr_section*
+ relr_dyn_section(Layout*);
+
// Add a potential copy relocation.
void
copy_reloc(Symbol_table* symtab, Layout* layout,
@@ -1235,6 +1241,8 @@ class Target_x86_64 : public Sized_target<size, false>
Reloc_section* rela_dyn_;
// The section to use for IRELATIVE relocs.
Reloc_section* rela_irelative_;
+ // The RELR dynamic reloc section.
+ Relr_section* relr_dyn_;
// Relocs saved to avoid a COPY reloc.
Copy_relocs<elfcpp::SHT_RELA, size, false> copy_relocs_;
// Offset of the GOT entry for the TLS module index.
@@ -1431,6 +1439,23 @@ Target_x86_64<size>::rela_irelative_section(Layout* layout)
return this->rela_irelative_;
}
+// Get the RELR dynamic reloc section, creating it if necessary.
+
+template<int size>
+typename Target_x86_64<size>::Relr_section*
+Target_x86_64<size>::relr_dyn_section(Layout* layout)
+{
+ if (this->relr_dyn_ == NULL)
+ {
+ gold_assert(layout != NULL);
+ this->relr_dyn_ = new Relr_section();
+ layout->add_output_section_data(".relr.dyn", elfcpp::SHT_RELR,
+ elfcpp::SHF_ALLOC, this->relr_dyn_,
+ ORDER_DYNAMIC_RELOCS, false);
+ }
+ return this->relr_dyn_;
+}
+
// Write the first three reserved words of the .got.plt section.
// The remainder of the section is written while writing the PLT
// in Output_data_plt_i386::do_write.
@@ -2966,14 +2991,25 @@ Target_x86_64<size>::Scan::local(Symbol_table* symtab,
if (parameters->options().output_is_position_independent())
{
unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
- Reloc_section* rela_dyn = target->rela_dyn_section(layout);
- rela_dyn->add_local_relative(object, r_sym,
- (size == 32
- ? elfcpp::R_X86_64_RELATIVE64
- : elfcpp::R_X86_64_RELATIVE),
- output_section, data_shndx,
- reloc.get_r_offset(),
- reloc.get_r_addend(), is_ifunc);
+ if (size == 64
+ && !is_ifunc
+ && parameters->options().experimental_use_relr())
+ {
+ Relr_section* relr_dyn = target->relr_dyn_section(layout);
+ relr_dyn->add_local_relative(object, r_sym, output_section,
+ data_shndx, reloc.get_r_offset());
+ }
+ else
+ {
+ Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+ rela_dyn->add_local_relative(object, r_sym,
+ (size == 32
+ ? elfcpp::R_X86_64_RELATIVE64
+ : elfcpp::R_X86_64_RELATIVE),
+ output_section, data_shndx,
+ reloc.get_r_offset(),
+ reloc.get_r_addend(), is_ifunc);
+ }
}
break;
@@ -2991,12 +3027,22 @@ Target_x86_64<size>::Scan::local(Symbol_table* symtab,
if (size == 32 && r_type == elfcpp::R_X86_64_32)
{
unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
- Reloc_section* rela_dyn = target->rela_dyn_section(layout);
- rela_dyn->add_local_relative(object, r_sym,
- elfcpp::R_X86_64_RELATIVE,
- output_section, data_shndx,
- reloc.get_r_offset(),
- reloc.get_r_addend(), is_ifunc);
+ if (!is_ifunc && parameters->options().experimental_use_relr())
+ {
+ Relr_section* relr_dyn = target->relr_dyn_section(layout);
+ relr_dyn->add_local_relative(object, r_sym, output_section,
+ data_shndx,
+ reloc.get_r_offset());
+ }
+ else
+ {
+ Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+ rela_dyn->add_local_relative(object, r_sym,
+ elfcpp::R_X86_64_RELATIVE,
+ output_section, data_shndx,
+ reloc.get_r_offset(),
+ reloc.get_r_addend(), is_ifunc);
+ }
break;
}
@@ -3099,15 +3145,7 @@ Target_x86_64<size>::Scan::local(Symbol_table* symtab,
{
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
// R_X86_64_RELATIVE assumes a 64-bit relocation.
- if (r_type != elfcpp::R_X86_64_GOT32)
- {
- unsigned int got_offset =
- 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, is_ifunc);
- }
- else
+ if (r_type == elfcpp::R_X86_64_GOT32)
{
this->check_non_pic(object, r_type, NULL);
@@ -3116,6 +3154,24 @@ Target_x86_64<size>::Scan::local(Symbol_table* symtab,
object, r_sym, r_type, got,
object->local_got_offset(r_sym, GOT_TYPE_STANDARD), 0);
}
+ else if (size == 64
+ && !is_ifunc
+ && parameters->options().experimental_use_relr())
+ {
+ Relr_section* relr_dyn = target->relr_dyn_section(layout);
+ unsigned int got_offset =
+ object->local_got_offset(r_sym, GOT_TYPE_STANDARD);
+ relr_dyn->add_local_relative(object, r_sym, got,
+ got_offset);
+ }
+ else
+ {
+ unsigned int got_offset =
+ 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, is_ifunc);
+ }
}
}
// For GOTPLT64, we'd normally want a PLT section, but since
@@ -3478,12 +3534,24 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab,
|| (size == 32 && r_type == elfcpp::R_X86_64_32))
&& gsym->can_use_relative_reloc(false))
{
- Reloc_section* rela_dyn = target->rela_dyn_section(layout);
- rela_dyn->add_global_relative(gsym, elfcpp::R_X86_64_RELATIVE,
- output_section, object,
- data_shndx,
- reloc.get_r_offset(),
- reloc.get_r_addend(), false);
+ if (parameters->options().experimental_use_relr())
+ {
+ Relr_section* relr_dyn = target->relr_dyn_section(layout);
+ relr_dyn->add_global_relative(gsym,
+ output_section, object,
+ data_shndx,
+ reloc.get_r_offset());
+ }
+ else
+ {
+ Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+ rela_dyn->add_global_relative(gsym,
+ elfcpp::R_X86_64_RELATIVE,
+ output_section, object,
+ data_shndx,
+ reloc.get_r_offset(),
+ reloc.get_r_addend(), false);
+ }
}
else
{
@@ -3886,7 +3954,8 @@ Target_x86_64<size>::do_finalize_sections(
? NULL
: this->plt_->rela_plt());
layout->add_target_dynamic_tags(false, this->got_plt_, rel_plt,
- this->rela_dyn_, true, false);
+ this->rela_dyn_, true, false,
+ this->relr_dyn_);
// Fill in some more dynamic tags.
Output_data_dynamic* const odyn = layout->dynamic_data();