// A class to handle the PLT data.
+template<int size>
class Output_data_plt_x86_64 : public Output_section_data
{
public:
- typedef Output_data_reloc<elfcpp::SHT_RELA, true, 64, false> Reloc_section;
+ typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, false> Reloc_section;
Output_data_plt_x86_64(Layout* layout, Output_data_got<64, false>* got,
Output_data_space* got_plt,
// Add an entry to the PLT for a local STT_GNU_IFUNC symbol.
unsigned int
add_local_ifunc_entry(Symbol_table* symtab, Layout*,
- Sized_relobj_file<64, false>* relobj,
+ Sized_relobj_file<size, false>* relobj,
unsigned int local_sym_index);
// Add the relocation for a PLT entry.
// http://people.redhat.com/drepper/tls.pdf
// http://www.lsd.ic.unicamp.br/~oliva/writeups/TLS/RFC-TLSDESC-x86.txt
-class Target_x86_64 : public Sized_target<64, false>
+template<int size>
+class Target_x86_64 : public Sized_target<size, false>
{
public:
// In the x86_64 ABI (p 68), it says "The AMD64 ABI architectures
// uses only Elf64_Rela relocation entries with explicit addends."
- typedef Output_data_reloc<elfcpp::SHT_RELA, true, 64, false> Reloc_section;
+ typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, false> Reloc_section;
Target_x86_64()
- : Sized_target<64, false>(&x86_64_info),
+ : Sized_target<size, false>(&x86_64_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),
void
gc_process_relocs(Symbol_table* symtab,
Layout* layout,
- Sized_relobj_file<64, false>* object,
+ Sized_relobj_file<size, false>* object,
unsigned int data_shndx,
unsigned int sh_type,
const unsigned char* prelocs,
void
scan_relocs(Symbol_table* symtab,
Layout* layout,
- Sized_relobj_file<64, false>* object,
+ Sized_relobj_file<size, false>* object,
unsigned int data_shndx,
unsigned int sh_type,
const unsigned char* prelocs,
// Relocate a section.
void
- relocate_section(const Relocate_info<64, false>*,
+ relocate_section(const Relocate_info<size, false>*,
unsigned int sh_type,
const unsigned char* prelocs,
size_t reloc_count,
Output_section* output_section,
bool needs_special_offset_handling,
unsigned char* view,
- elfcpp::Elf_types<64>::Elf_Addr view_address,
+ typename elfcpp::Elf_types<size>::Elf_Addr view_address,
section_size_type view_size,
const Reloc_symbol_changes*);
void
scan_relocatable_relocs(Symbol_table* symtab,
Layout* layout,
- Sized_relobj_file<64, false>* object,
+ Sized_relobj_file<size, false>* object,
unsigned int data_shndx,
unsigned int sh_type,
const unsigned char* prelocs,
// Relocate a section during a relocatable link.
void
- relocate_for_relocatable(const Relocate_info<64, false>*,
- unsigned int sh_type,
- const unsigned char* prelocs,
- size_t reloc_count,
- Output_section* output_section,
- off_t offset_in_output_section,
- const Relocatable_relocs*,
- unsigned char* view,
- elfcpp::Elf_types<64>::Elf_Addr view_address,
- section_size_type view_size,
- unsigned char* reloc_view,
- section_size_type reloc_view_size);
+ relocate_for_relocatable(
+ const Relocate_info<size, false>*,
+ unsigned int sh_type,
+ const unsigned char* prelocs,
+ size_t reloc_count,
+ Output_section* output_section,
+ off_t offset_in_output_section,
+ const Relocatable_relocs*,
+ unsigned char* view,
+ typename elfcpp::Elf_types<size>::Elf_Addr view_address,
+ section_size_type view_size,
+ unsigned char* reloc_view,
+ section_size_type reloc_view_size);
// Return a string used to fill a code section with nops.
std::string
// necessary dynamic relocations.
void
reserve_local_got_entry(unsigned int got_index,
- Sized_relobj<64, false>* obj,
+ Sized_relobj<size, false>* obj,
unsigned int r_sym,
unsigned int got_type);
// Apply an incremental relocation.
void
- apply_relocation(const Relocate_info<64, false>* relinfo,
- elfcpp::Elf_types<64>::Elf_Addr r_offset,
+ apply_relocation(const Relocate_info<size, false>* relinfo,
+ typename elfcpp::Elf_types<size>::Elf_Addr r_offset,
unsigned int r_type,
- elfcpp::Elf_types<64>::Elf_Swxword r_addend,
+ typename elfcpp::Elf_types<size>::Elf_Swxword r_addend,
const Symbol* gsym,
unsigned char* view,
- elfcpp::Elf_types<64>::Elf_Addr address,
+ typename elfcpp::Elf_types<size>::Elf_Addr address,
section_size_type view_size);
// Add a new reloc argument, returning the index in the vector.
size_t
- add_tlsdesc_info(Sized_relobj_file<64, false>* object, unsigned int r_sym)
+ add_tlsdesc_info(Sized_relobj_file<size, false>* object, unsigned int r_sym)
{
this->tlsdesc_reloc_info_.push_back(Tlsdesc_info(object, r_sym));
return this->tlsdesc_reloc_info_.size() - 1;
inline void
local(Symbol_table* symtab, Layout* layout, Target_x86_64* target,
- Sized_relobj_file<64, false>* object,
+ Sized_relobj_file<size, false>* object,
unsigned int data_shndx,
Output_section* output_section,
- const elfcpp::Rela<64, false>& reloc, unsigned int r_type,
- const elfcpp::Sym<64, false>& lsym);
+ const elfcpp::Rela<size, false>& reloc, unsigned int r_type,
+ const elfcpp::Sym<size, false>& lsym);
inline void
global(Symbol_table* symtab, Layout* layout, Target_x86_64* target,
- Sized_relobj_file<64, false>* object,
+ Sized_relobj_file<size, false>* object,
unsigned int data_shndx,
Output_section* output_section,
- const elfcpp::Rela<64, false>& reloc, unsigned int r_type,
+ const elfcpp::Rela<size, false>& reloc, unsigned int r_type,
Symbol* gsym);
inline bool
local_reloc_may_be_function_pointer(Symbol_table* symtab, Layout* layout,
Target_x86_64* target,
- Sized_relobj_file<64, false>* object,
+ Sized_relobj_file<size, false>* object,
unsigned int data_shndx,
Output_section* output_section,
- const elfcpp::Rela<64, false>& reloc,
+ const elfcpp::Rela<size, false>& reloc,
unsigned int r_type,
- const elfcpp::Sym<64, false>& lsym);
+ const elfcpp::Sym<size, false>& lsym);
inline bool
global_reloc_may_be_function_pointer(Symbol_table* symtab, Layout* layout,
Target_x86_64* target,
- Sized_relobj_file<64, false>* object,
+ Sized_relobj_file<size, false>* object,
unsigned int data_shndx,
Output_section* output_section,
- const elfcpp::Rela<64, false>& reloc,
+ const elfcpp::Rela<size, false>& reloc,
unsigned int r_type,
Symbol* gsym);
private:
static void
- unsupported_reloc_local(Sized_relobj_file<64, false>*, unsigned int r_type);
+ unsupported_reloc_local(Sized_relobj_file<size, false>*,
+ unsigned int r_type);
static void
- unsupported_reloc_global(Sized_relobj_file<64, false>*, unsigned int r_type,
- Symbol*);
+ unsupported_reloc_global(Sized_relobj_file<size, false>*,
+ unsigned int r_type, Symbol*);
void
check_non_pic(Relobj*, unsigned int r_type, Symbol*);
possible_function_pointer_reloc(unsigned int r_type);
bool
- reloc_needs_plt_for_ifunc(Sized_relobj_file<64, false>*,
+ reloc_needs_plt_for_ifunc(Sized_relobj_file<size, false>*,
unsigned int r_type);
// Whether we have issued an error about a non-PIC compilation.
// Do a relocation. Return false if the caller should not issue
// any warnings about this relocation.
inline bool
- relocate(const Relocate_info<64, false>*, Target_x86_64*, Output_section*,
- size_t relnum, const elfcpp::Rela<64, false>&,
- unsigned int r_type, const Sized_symbol<64>*,
- const Symbol_value<64>*,
- unsigned char*, elfcpp::Elf_types<64>::Elf_Addr,
+ relocate(const Relocate_info<size, false>*, Target_x86_64*,
+ Output_section*,
+ size_t relnum, const elfcpp::Rela<size, false>&,
+ unsigned int r_type, const Sized_symbol<size>*,
+ const Symbol_value<size>*,
+ unsigned char*, typename elfcpp::Elf_types<size>::Elf_Addr,
section_size_type);
private:
// Do a TLS relocation.
inline void
- relocate_tls(const Relocate_info<64, false>*, Target_x86_64*,
- size_t relnum, const elfcpp::Rela<64, false>&,
- unsigned int r_type, const Sized_symbol<64>*,
- const Symbol_value<64>*,
- unsigned char*, elfcpp::Elf_types<64>::Elf_Addr,
+ relocate_tls(const Relocate_info<size, false>*, Target_x86_64*,
+ size_t relnum, const elfcpp::Rela<size, false>&,
+ unsigned int r_type, const Sized_symbol<size>*,
+ const Symbol_value<size>*,
+ unsigned char*, typename elfcpp::Elf_types<size>::Elf_Addr,
section_size_type);
// Do a TLS General-Dynamic to Initial-Exec transition.
inline void
- tls_gd_to_ie(const Relocate_info<64, false>*, size_t relnum,
+ tls_gd_to_ie(const Relocate_info<size, false>*, size_t relnum,
Output_segment* tls_segment,
- const elfcpp::Rela<64, false>&, unsigned int r_type,
- elfcpp::Elf_types<64>::Elf_Addr value,
+ const elfcpp::Rela<size, false>&, unsigned int r_type,
+ typename elfcpp::Elf_types<size>::Elf_Addr value,
unsigned char* view,
- elfcpp::Elf_types<64>::Elf_Addr,
+ typename elfcpp::Elf_types<size>::Elf_Addr,
section_size_type view_size);
// Do a TLS General-Dynamic to Local-Exec transition.
inline void
- tls_gd_to_le(const Relocate_info<64, false>*, size_t relnum,
+ tls_gd_to_le(const Relocate_info<size, false>*, size_t relnum,
Output_segment* tls_segment,
- const elfcpp::Rela<64, false>&, unsigned int r_type,
- elfcpp::Elf_types<64>::Elf_Addr value,
+ const elfcpp::Rela<size, false>&, unsigned int r_type,
+ typename elfcpp::Elf_types<size>::Elf_Addr value,
unsigned char* view,
section_size_type view_size);
// Do a TLSDESC-style General-Dynamic to Initial-Exec transition.
inline void
- tls_desc_gd_to_ie(const Relocate_info<64, false>*, size_t relnum,
+ tls_desc_gd_to_ie(const Relocate_info<size, false>*, size_t relnum,
Output_segment* tls_segment,
- const elfcpp::Rela<64, false>&, unsigned int r_type,
- elfcpp::Elf_types<64>::Elf_Addr value,
+ const elfcpp::Rela<size, false>&, unsigned int r_type,
+ typename elfcpp::Elf_types<size>::Elf_Addr value,
unsigned char* view,
- elfcpp::Elf_types<64>::Elf_Addr,
+ typename elfcpp::Elf_types<size>::Elf_Addr,
section_size_type view_size);
// Do a TLSDESC-style General-Dynamic to Local-Exec transition.
inline void
- tls_desc_gd_to_le(const Relocate_info<64, false>*, size_t relnum,
+ tls_desc_gd_to_le(const Relocate_info<size, false>*, size_t relnum,
Output_segment* tls_segment,
- const elfcpp::Rela<64, false>&, unsigned int r_type,
- elfcpp::Elf_types<64>::Elf_Addr value,
+ const elfcpp::Rela<size, false>&, unsigned int r_type,
+ typename elfcpp::Elf_types<size>::Elf_Addr value,
unsigned char* view,
section_size_type view_size);
// Do a TLS Local-Dynamic to Local-Exec transition.
inline void
- tls_ld_to_le(const Relocate_info<64, false>*, size_t relnum,
+ tls_ld_to_le(const Relocate_info<size, false>*, size_t relnum,
Output_segment* tls_segment,
- const elfcpp::Rela<64, false>&, unsigned int r_type,
- elfcpp::Elf_types<64>::Elf_Addr value,
+ const elfcpp::Rela<size, false>&, unsigned int r_type,
+ typename elfcpp::Elf_types<size>::Elf_Addr value,
unsigned char* view,
section_size_type view_size);
// Do a TLS Initial-Exec to Local-Exec transition.
static inline void
- tls_ie_to_le(const Relocate_info<64, false>*, size_t relnum,
+ tls_ie_to_le(const Relocate_info<size, false>*, size_t relnum,
Output_segment* tls_segment,
- const elfcpp::Rela<64, false>&, unsigned int r_type,
- elfcpp::Elf_types<64>::Elf_Addr value,
+ const elfcpp::Rela<size, false>&, unsigned int r_type,
+ typename elfcpp::Elf_types<size>::Elf_Addr value,
unsigned char* view,
section_size_type view_size);
// Create a PLT entry for a local STT_GNU_IFUNC symbol.
void
make_local_ifunc_plt_entry(Symbol_table*, Layout*,
- Sized_relobj_file<64, false>* relobj,
+ Sized_relobj_file<size, false>* relobj,
unsigned int local_sym_index);
// Define the _TLS_MODULE_BASE_ symbol in the TLS segment.
// Create a GOT entry for the TLS module index.
unsigned int
got_mod_index_entry(Symbol_table* symtab, Layout* layout,
- Sized_relobj_file<64, false>* object);
+ Sized_relobj_file<size, false>* object);
// Get the PLT section.
- Output_data_plt_x86_64*
+ Output_data_plt_x86_64<size>*
plt_section() const
{
gold_assert(this->plt_ != NULL);
// Add a potential copy relocation.
void
copy_reloc(Symbol_table* symtab, Layout* layout,
- Sized_relobj_file<64, false>* object,
+ Sized_relobj_file<size, false>* object,
unsigned int shndx, Output_section* output_section,
- Symbol* sym, const elfcpp::Rela<64, false>& reloc)
+ Symbol* sym, const elfcpp::Rela<size, false>& reloc)
{
this->copy_relocs_.copy_reloc(symtab, layout,
- symtab->get_sized_symbol<64>(sym),
+ symtab->get_sized_symbol<size>(sym),
object, shndx, output_section,
reloc, this->rela_dyn_section(layout));
}
// R_X86_64_TLSDESC against a local symbol.
struct Tlsdesc_info
{
- Tlsdesc_info(Sized_relobj_file<64, false>* a_object, unsigned int a_r_sym)
+ Tlsdesc_info(Sized_relobj_file<size, false>* a_object, unsigned int a_r_sym)
: object(a_object), r_sym(a_r_sym)
{ }
// The object in which the local symbol is defined.
- Sized_relobj_file<64, false>* object;
+ Sized_relobj_file<size, false>* object;
// The local symbol index in the object.
unsigned int r_sym;
};
// The GOT section.
Output_data_got<64, false>* got_;
// The PLT section.
- Output_data_plt_x86_64* plt_;
+ Output_data_plt_x86_64<size>* plt_;
// The GOT PLT section.
Output_data_space* got_plt_;
// The GOT section for IRELATIVE relocations.
// The section to use for IRELATIVE relocs.
Reloc_section* rela_irelative_;
// Relocs saved to avoid a COPY reloc.
- Copy_relocs<elfcpp::SHT_RELA, 64, false> copy_relocs_;
+ Copy_relocs<elfcpp::SHT_RELA, size, false> copy_relocs_;
// Space for variables copied with a COPY reloc.
Output_data_space* dynbss_;
// Offset of the GOT entry for the TLS module index.
bool tls_base_symbol_defined_;
};
-const Target::Target_info Target_x86_64::x86_64_info =
+template<>
+const Target::Target_info Target_x86_64<64>::x86_64_info =
{
64, // size
false, // is_big_endian
NULL // attributes_vendor
};
+template<>
+const Target::Target_info Target_x86_64<32>::x86_64_info =
+{
+ 32, // size
+ false, // is_big_endian
+ elfcpp::EM_X86_64, // machine_code
+ false, // has_make_symbol
+ false, // has_resolve
+ true, // has_code_fill
+ true, // is_default_stack_executable
+ true, // can_icf_inline_merge_sections
+ '\0', // wrap_char
+ "/libx32/ldx32.so.1", // program interpreter
+ 0x400000, // default_text_segment_address
+ 0x1000, // abi_pagesize (overridable by -z max-page-size)
+ 0x1000, // common_pagesize (overridable by -z common-page-size)
+ elfcpp::SHN_UNDEF, // small_common_shndx
+ elfcpp::SHN_X86_64_LCOMMON, // large_common_shndx
+ 0, // small_common_section_flags
+ elfcpp::SHF_X86_64_LARGE, // large_common_section_flags
+ NULL, // attributes_section
+ NULL // attributes_vendor
+};
+
// This is called when a new output section is created. This is where
// we handle the SHF_X86_64_LARGE.
+template<int size>
void
-Target_x86_64::do_new_output_section(Output_section* os) const
+Target_x86_64<size>::do_new_output_section(Output_section* os) const
{
if ((os->flags() & elfcpp::SHF_X86_64_LARGE) != 0)
os->set_is_large_section();
// Get the GOT section, creating it if necessary.
+template<int size>
Output_data_got<64, false>*
-Target_x86_64::got_section(Symbol_table* symtab, Layout* layout)
+Target_x86_64<size>::got_section(Symbol_table* symtab, Layout* layout)
{
if (this->got_ == NULL)
{
// Get the dynamic reloc section, creating it if necessary.
-Target_x86_64::Reloc_section*
-Target_x86_64::rela_dyn_section(Layout* layout)
+template<int size>
+typename Target_x86_64<size>::Reloc_section*
+Target_x86_64<size>::rela_dyn_section(Layout* layout)
{
if (this->rela_dyn_ == NULL)
{
// that they can refer to global variables initialized by those
// relocs.
-Target_x86_64::Reloc_section*
-Target_x86_64::rela_irelative_section(Layout* layout)
+template<int size>
+typename Target_x86_64<size>::Reloc_section*
+Target_x86_64<size>::rela_irelative_section(Layout* layout)
{
if (this->rela_irelative_ == NULL)
{
// Initialize the PLT section.
+template<int size>
void
-Output_data_plt_x86_64::init(Layout* layout)
+Output_data_plt_x86_64<size>::init(Layout* layout)
{
this->rel_ = new Reloc_section(false);
layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA,
plt_eh_frame_fde, plt_eh_frame_fde_size);
}
+template<int size>
void
-Output_data_plt_x86_64::do_adjust_output_section(Output_section* os)
+Output_data_plt_x86_64<size>::do_adjust_output_section(Output_section* os)
{
os->set_entsize(plt_entry_size);
}
// Add an entry to the PLT.
+template<int size>
void
-Output_data_plt_x86_64::add_entry(Symbol_table* symtab, Layout* layout,
- Symbol* gsym)
+Output_data_plt_x86_64<size>::add_entry(Symbol_table* symtab, Layout* layout,
+ Symbol* gsym)
{
gold_assert(!gsym->has_plt_offset());
// Add an entry to the PLT for a local STT_GNU_IFUNC symbol. Return
// the PLT offset.
+template<int size>
unsigned int
-Output_data_plt_x86_64::add_local_ifunc_entry(
+Output_data_plt_x86_64<size>::add_local_ifunc_entry(
Symbol_table* symtab,
Layout* layout,
- Sized_relobj_file<64, false>* relobj,
+ Sized_relobj_file<size, false>* relobj,
unsigned int local_sym_index)
{
unsigned int plt_offset = this->irelative_count_ * plt_entry_size;
// Add the relocation for a PLT entry.
+template<int size>
void
-Output_data_plt_x86_64::add_relocation(Symbol_table* symtab, Layout* layout,
- Symbol* gsym, unsigned int got_offset)
+Output_data_plt_x86_64<size>::add_relocation(Symbol_table* symtab,
+ Layout* layout,
+ Symbol* gsym,
+ unsigned int got_offset)
{
if (gsym->type() == elfcpp::STT_GNU_IFUNC
&& gsym->can_use_relative_reloc(false))
// Return where the TLSDESC relocations should go, creating it if
// necessary. These follow the JUMP_SLOT relocations.
-Output_data_plt_x86_64::Reloc_section*
-Output_data_plt_x86_64::rela_tlsdesc(Layout* layout)
+template<int size>
+typename Output_data_plt_x86_64<size>::Reloc_section*
+Output_data_plt_x86_64<size>::rela_tlsdesc(Layout* layout)
{
if (this->tlsdesc_rel_ == NULL)
{
// Return where the IRELATIVE relocations should go in the PLT. These
// follow the JUMP_SLOT and the TLSDESC relocations.
-Output_data_plt_x86_64::Reloc_section*
-Output_data_plt_x86_64::rela_irelative(Symbol_table* symtab, Layout* layout)
+template<int size>
+typename Output_data_plt_x86_64<size>::Reloc_section*
+Output_data_plt_x86_64<size>::rela_irelative(Symbol_table* symtab,
+ Layout* layout)
{
if (this->irelative_rel_ == NULL)
{
// Return the PLT address to use for a global symbol.
+template<int size>
uint64_t
-Output_data_plt_x86_64::address_for_global(const Symbol* gsym)
+Output_data_plt_x86_64<size>::address_for_global(const Symbol* gsym)
{
uint64_t offset = 0;
if (gsym->type() == elfcpp::STT_GNU_IFUNC
// Return the PLT address to use for a local symbol. These are always
// IRELATIVE relocs.
+template<int size>
uint64_t
-Output_data_plt_x86_64::address_for_local(const Relobj*, unsigned int)
+Output_data_plt_x86_64<size>::address_for_local(const Relobj*, unsigned int)
{
return this->address() + (this->count_ + 1) * plt_entry_size;
}
// Set the final size.
+template<int size>
void
-Output_data_plt_x86_64::set_final_data_size()
+Output_data_plt_x86_64<size>::set_final_data_size()
{
unsigned int count = this->count_ + this->irelative_count_;
if (this->has_tlsdesc_entry())
// The first entry in the PLT for an executable.
-const unsigned char Output_data_plt_x86_64::first_plt_entry[plt_entry_size] =
+template<int size>
+const unsigned char
+Output_data_plt_x86_64<size>::first_plt_entry[plt_entry_size] =
{
// From AMD64 ABI Draft 0.98, page 76
0xff, 0x35, // pushq contents of memory address
// Subsequent entries in the PLT for an executable.
-const unsigned char Output_data_plt_x86_64::plt_entry[plt_entry_size] =
+template<int size>
+const unsigned char
+Output_data_plt_x86_64<size>::plt_entry[plt_entry_size] =
{
// From AMD64 ABI Draft 0.98, page 76
0xff, 0x25, // jmpq indirect
// The reserved TLSDESC entry in the PLT for an executable.
-const unsigned char Output_data_plt_x86_64::tlsdesc_plt_entry[plt_entry_size] =
+template<int size>
+const unsigned char
+Output_data_plt_x86_64<size>::tlsdesc_plt_entry[plt_entry_size] =
{
// From Alexandre Oliva, "Thread-Local Storage Descriptors for IA32
// and AMD64/EM64T", Version 0.9.4 (2005-10-10).
// The .eh_frame unwind information for the PLT.
+template<int size>
const unsigned char
-Output_data_plt_x86_64::plt_eh_frame_cie[plt_eh_frame_cie_size] =
+Output_data_plt_x86_64<size>::plt_eh_frame_cie[plt_eh_frame_cie_size] =
{
1, // CIE version.
'z', // Augmentation: augmentation size included.
elfcpp::DW_CFA_nop
};
+template<int size>
const unsigned char
-Output_data_plt_x86_64::plt_eh_frame_fde[plt_eh_frame_fde_size] =
+Output_data_plt_x86_64<size>::plt_eh_frame_fde[plt_eh_frame_fde_size] =
{
0, 0, 0, 0, // Replaced with offset to .plt.
0, 0, 0, 0, // Replaced with size of .plt.
// Write out the PLT. This uses the hand-coded instructions above,
// and adjusts them as needed. This is specified by the AMD64 ABI.
+template<int size>
void
-Output_data_plt_x86_64::do_write(Output_file* of)
+Output_data_plt_x86_64<size>::do_write(Output_file* of)
{
const off_t offset = this->offset();
const section_size_type oview_size =
unsigned char* pov = oview;
// The base address of the .plt section.
- elfcpp::Elf_types<64>::Elf_Addr plt_address = this->address();
+ typename elfcpp::Elf_types<size>::Elf_Addr plt_address = this->address();
// The base address of the .got section.
- elfcpp::Elf_types<64>::Elf_Addr got_base = this->got_->address();
+ typename elfcpp::Elf_types<size>::Elf_Addr got_base = this->got_->address();
// The base address of the PLT portion of the .got section,
// which is where the GOT pointer will point, and where the
// three reserved GOT entries are located.
- elfcpp::Elf_types<64>::Elf_Addr got_address = this->got_plt_->address();
+ typename elfcpp::Elf_types<size>::Elf_Addr got_address
+ = this->got_plt_->address();
memcpy(pov, first_plt_entry, plt_entry_size);
// We do a jmp relative to the PC at the end of this instruction.
// Create the PLT section.
+template<int size>
void
-Target_x86_64::make_plt_section(Symbol_table* symtab, Layout* layout)
+Target_x86_64<size>::make_plt_section(Symbol_table* symtab, Layout* layout)
{
if (this->plt_ == NULL)
{
// Create the GOT sections first.
this->got_section(symtab, layout);
- this->plt_ = new Output_data_plt_x86_64(layout, this->got_,
- this->got_plt_,
- this->got_irelative_);
+ this->plt_ = new Output_data_plt_x86_64<size>(layout, this->got_,
+ this->got_plt_,
+ this->got_irelative_);
layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
(elfcpp::SHF_ALLOC
| elfcpp::SHF_EXECINSTR),
// Return the section for TLSDESC relocations.
-Target_x86_64::Reloc_section*
-Target_x86_64::rela_tlsdesc_section(Layout* layout) const
+template<int size>
+typename Target_x86_64<size>::Reloc_section*
+Target_x86_64<size>::rela_tlsdesc_section(Layout* layout) const
{
return this->plt_section()->rela_tlsdesc(layout);
}
// Create a PLT entry for a global symbol.
+template<int size>
void
-Target_x86_64::make_plt_entry(Symbol_table* symtab, Layout* layout,
- Symbol* gsym)
+Target_x86_64<size>::make_plt_entry(Symbol_table* symtab, Layout* layout,
+ Symbol* gsym)
{
if (gsym->has_plt_offset())
return;
// Make a PLT entry for a local STT_GNU_IFUNC symbol.
+template<int size>
void
-Target_x86_64::make_local_ifunc_plt_entry(Symbol_table* symtab, Layout* layout,
- Sized_relobj_file<64, false>* relobj,
- unsigned int local_sym_index)
+Target_x86_64<size>::make_local_ifunc_plt_entry(
+ Symbol_table* symtab, Layout* layout,
+ Sized_relobj_file<size, false>* relobj,
+ unsigned int local_sym_index)
{
if (relobj->local_has_plt_offset(local_sym_index))
return;
// Return the number of entries in the PLT.
+template<int size>
unsigned int
-Target_x86_64::plt_entry_count() const
+Target_x86_64<size>::plt_entry_count() const
{
if (this->plt_ == NULL)
return 0;
// Return the offset of the first non-reserved PLT entry.
+template<int size>
unsigned int
-Target_x86_64::first_plt_entry_offset() const
+Target_x86_64<size>::first_plt_entry_offset() const
{
- return Output_data_plt_x86_64::first_plt_entry_offset();
+ return Output_data_plt_x86_64<size>::first_plt_entry_offset();
}
// Return the size of each PLT entry.
+template<int size>
unsigned int
-Target_x86_64::plt_entry_size() const
+Target_x86_64<size>::plt_entry_size() const
{
- return Output_data_plt_x86_64::get_plt_entry_size();
+ return Output_data_plt_x86_64<size>::get_plt_entry_size();
}
// Create the GOT and PLT sections for an incremental update.
+template<int size>
Output_data_got_base*
-Target_x86_64::init_got_plt_for_update(Symbol_table* symtab,
+Target_x86_64<size>::init_got_plt_for_update(Symbol_table* symtab,
Layout* layout,
unsigned int got_count,
unsigned int plt_count)
ORDER_NON_RELRO_FIRST, false);
// Create the PLT section.
- this->plt_ = new Output_data_plt_x86_64(layout, this->got_, this->got_plt_,
- this->got_irelative_, plt_count);
+ this->plt_ = new Output_data_plt_x86_64<size>(layout, this->got_,
+ this->got_plt_,
+ this->got_irelative_,
+ plt_count);
layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
elfcpp::SHF_ALLOC | elfcpp::SHF_EXECINSTR,
this->plt_, ORDER_PLT, false);
// Reserve a GOT entry for a local symbol, and regenerate any
// necessary dynamic relocations.
+template<int size>
void
-Target_x86_64::reserve_local_got_entry(
+Target_x86_64<size>::reserve_local_got_entry(
unsigned int got_index,
- Sized_relobj<64, false>* obj,
+ Sized_relobj<size, false>* obj,
unsigned int r_sym,
unsigned int got_type)
{
// Reserve a GOT entry for a global symbol, and regenerate any
// necessary dynamic relocations.
+template<int size>
void
-Target_x86_64::reserve_global_got_entry(unsigned int got_index, Symbol* gsym,
- unsigned int got_type)
+Target_x86_64<size>::reserve_global_got_entry(unsigned int got_index,
+ Symbol* gsym,
+ unsigned int got_type)
{
unsigned int got_offset = got_index * 8;
Reloc_section* rela_dyn = this->rela_dyn_section(NULL);
// Register an existing PLT entry for a global symbol.
+template<int size>
void
-Target_x86_64::register_global_plt_entry(Symbol_table* symtab,
- Layout* layout,
- unsigned int plt_index,
- Symbol* gsym)
+Target_x86_64<size>::register_global_plt_entry(Symbol_table* symtab,
+ Layout* layout,
+ unsigned int plt_index,
+ Symbol* gsym)
{
gold_assert(this->plt_ != NULL);
gold_assert(!gsym->has_plt_offset());
// Force a COPY relocation for a given symbol.
+template<int size>
void
-Target_x86_64::emit_copy_reloc(
+Target_x86_64<size>::emit_copy_reloc(
Symbol_table* symtab, Symbol* sym, Output_section* os, off_t offset)
{
this->copy_relocs_.emit_copy_reloc(symtab,
- symtab->get_sized_symbol<64>(sym),
+ symtab->get_sized_symbol<size>(sym),
os,
offset,
this->rela_dyn_section(NULL));
// Define the _TLS_MODULE_BASE_ symbol in the TLS segment.
+template<int size>
void
-Target_x86_64::define_tls_base_symbol(Symbol_table* symtab, Layout* layout)
+Target_x86_64<size>::define_tls_base_symbol(Symbol_table* symtab,
+ Layout* layout)
{
if (this->tls_base_symbol_defined_)
return;
// Create the reserved PLT and GOT entries for the TLS descriptor resolver.
+template<int size>
void
-Target_x86_64::reserve_tlsdesc_entries(Symbol_table* symtab,
+Target_x86_64<size>::reserve_tlsdesc_entries(Symbol_table* symtab,
Layout* layout)
{
if (this->plt_ == NULL)
// Create a GOT entry for the TLS module index.
+template<int size>
unsigned int
-Target_x86_64::got_mod_index_entry(Symbol_table* symtab, Layout* layout,
- Sized_relobj_file<64, false>* object)
+Target_x86_64<size>::got_mod_index_entry(Symbol_table* symtab, Layout* layout,
+ Sized_relobj_file<size, false>* object)
{
if (this->got_mod_index_offset_ == -1U)
{
// symbol. IS_FINAL is true if the final address of this symbol is
// known at link time.
+template<int size>
tls::Tls_optimization
-Target_x86_64::optimize_tls_reloc(bool is_final, int r_type)
+Target_x86_64<size>::optimize_tls_reloc(bool is_final, int r_type)
{
// If we are generating a shared library, then we can't do anything
// in the linker.
// Get the Reference_flags for a particular relocation.
+template<int size>
int
-Target_x86_64::Scan::get_reference_flags(unsigned int r_type)
+Target_x86_64<size>::Scan::get_reference_flags(unsigned int r_type)
{
switch (r_type)
{
// Report an unsupported relocation against a local symbol.
+template<int size>
void
-Target_x86_64::Scan::unsupported_reloc_local(
- Sized_relobj_file<64, false>* object,
+Target_x86_64<size>::Scan::unsupported_reloc_local(
+ Sized_relobj_file<size, false>* object,
unsigned int r_type)
{
gold_error(_("%s: unsupported reloc %u against local symbol"),
// it is the symbol the relocation is against; if it is NULL, the
// relocation is against a local symbol.
+template<int size>
void
-Target_x86_64::Scan::check_non_pic(Relobj* object, unsigned int r_type,
- Symbol* gsym)
+Target_x86_64<size>::Scan::check_non_pic(Relobj* object, unsigned int r_type,
+ Symbol* gsym)
{
switch (r_type)
{
// Return whether we need to make a PLT entry for a relocation of the
// given type against a STT_GNU_IFUNC symbol.
+template<int size>
bool
-Target_x86_64::Scan::reloc_needs_plt_for_ifunc(
- Sized_relobj_file<64, false>* object,
+Target_x86_64<size>::Scan::reloc_needs_plt_for_ifunc(
+ Sized_relobj_file<size, false>* object,
unsigned int r_type)
{
int flags = Scan::get_reference_flags(r_type);
// Scan a relocation for a local symbol.
+template<int size>
inline void
-Target_x86_64::Scan::local(Symbol_table* symtab,
- Layout* layout,
- Target_x86_64* target,
- Sized_relobj_file<64, false>* object,
- unsigned int data_shndx,
- Output_section* output_section,
- const elfcpp::Rela<64, false>& reloc,
- unsigned int r_type,
- const elfcpp::Sym<64, false>& lsym)
+Target_x86_64<size>::Scan::local(Symbol_table* symtab,
+ Layout* layout,
+ Target_x86_64<size>* target,
+ Sized_relobj_file<size, false>* object,
+ unsigned int data_shndx,
+ Output_section* output_section,
+ const elfcpp::Rela<size, false>& reloc,
+ unsigned int r_type,
+ const elfcpp::Sym<size, false>& lsym)
{
// A local STT_GNU_IFUNC symbol may require a PLT entry.
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());
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
target->make_local_ifunc_plt_entry(symtab, layout, object, r_sym);
}
// relocate it easily.
if (parameters->options().output_is_position_independent())
{
- unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info());
+ 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,
this->check_non_pic(object, r_type, NULL);
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
- unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info());
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
if (lsym.get_st_type() != elfcpp::STT_SECTION)
rela_dyn->add_local(object, r_sym, r_type, output_section,
data_shndx, reloc.get_r_offset(),
{
// The symbol requires a GOT entry.
Output_data_got<64, false>* got = target->got_section(symtab, layout);
- unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info());
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
// For a STT_GNU_IFUNC symbol we want the PLT offset. That
// lets function pointers compare correctly with shared
{
bool output_is_shared = parameters->options().shared();
const tls::Tls_optimization optimized_type
- = Target_x86_64::optimize_tls_reloc(!output_is_shared, r_type);
+ = Target_x86_64<size>::optimize_tls_reloc(!output_is_shared,
+ r_type);
switch (r_type)
{
case elfcpp::R_X86_64_TLSGD: // General-dynamic
// dtv-relative offset.
Output_data_got<64, false>* got
= target->got_section(symtab, layout);
- unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info());
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
unsigned int shndx = lsym.get_st_shndx();
bool is_ordinary;
shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary);
// make sure the section has been created.
target->got_section(symtab, layout);
Output_data_got<64, false>* got = target->got_tlsdesc_section();
- unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info());
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
if (!object->local_has_got_offset(r_sym, GOT_TYPE_TLS_DESC))
{
unsigned int got_offset = got->add_constant(0);
// Create a GOT entry for the tp-relative offset.
Output_data_got<64, false>* got
= target->got_section(symtab, layout);
- unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info());
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
got->add_local_with_rel(object, r_sym, GOT_TYPE_TLS_OFFSET,
target->rela_dyn_section(layout),
elfcpp::R_X86_64_TPOFF64);
// Report an unsupported relocation against a global symbol.
+template<int size>
void
-Target_x86_64::Scan::unsupported_reloc_global(
- Sized_relobj_file<64, false>* object,
+Target_x86_64<size>::Scan::unsupported_reloc_global(
+ Sized_relobj_file<size, false>* object,
unsigned int r_type,
Symbol* gsym)
{
}
// Returns true if this relocation type could be that of a function pointer.
+template<int size>
inline bool
-Target_x86_64::Scan::possible_function_pointer_reloc(unsigned int r_type)
+Target_x86_64<size>::Scan::possible_function_pointer_reloc(unsigned int r_type)
{
switch (r_type)
{
// corresponds to a function pointer being taken. In that case mark
// the function whose pointer was taken as not foldable.
+template<int size>
inline bool
-Target_x86_64::Scan::local_reloc_may_be_function_pointer(
+Target_x86_64<size>::Scan::local_reloc_may_be_function_pointer(
Symbol_table* ,
Layout* ,
- Target_x86_64* ,
- Sized_relobj_file<64, false>* ,
+ Target_x86_64<size>* ,
+ Sized_relobj_file<size, false>* ,
unsigned int ,
Output_section* ,
- const elfcpp::Rela<64, false>& ,
+ const elfcpp::Rela<size, false>& ,
unsigned int r_type,
- const elfcpp::Sym<64, false>&)
+ const elfcpp::Sym<size, false>&)
{
// When building a shared library, do not fold any local symbols as it is
// not possible to distinguish pointer taken versus a call by looking at
// corresponds to a function pointer being taken. In that case mark
// the function whose pointer was taken as not foldable.
+template<int size>
inline bool
-Target_x86_64::Scan::global_reloc_may_be_function_pointer(
+Target_x86_64<size>::Scan::global_reloc_may_be_function_pointer(
Symbol_table*,
Layout* ,
- Target_x86_64* ,
- Sized_relobj_file<64, false>* ,
+ Target_x86_64<size>* ,
+ Sized_relobj_file<size, false>* ,
unsigned int ,
Output_section* ,
- const elfcpp::Rela<64, false>& ,
+ const elfcpp::Rela<size, false>& ,
unsigned int r_type,
Symbol* gsym)
{
// Scan a relocation for a global symbol.
+template<int size>
inline void
-Target_x86_64::Scan::global(Symbol_table* symtab,
+Target_x86_64<size>::Scan::global(Symbol_table* symtab,
Layout* layout,
- Target_x86_64* target,
- Sized_relobj_file<64, false>* object,
+ Target_x86_64<size>* target,
+ Sized_relobj_file<size, false>* object,
unsigned int data_shndx,
Output_section* output_section,
- const elfcpp::Rela<64, false>& reloc,
+ const elfcpp::Rela<size, false>& reloc,
unsigned int r_type,
Symbol* gsym)
{
{
const bool is_final = gsym->final_value_is_known();
const tls::Tls_optimization optimized_type
- = Target_x86_64::optimize_tls_reloc(is_final, r_type);
+ = Target_x86_64<size>::optimize_tls_reloc(is_final, r_type);
switch (r_type)
{
case elfcpp::R_X86_64_TLSGD: // General-dynamic
}
}
+template<int size>
void
-Target_x86_64::gc_process_relocs(Symbol_table* symtab,
- Layout* layout,
- Sized_relobj_file<64, false>* object,
- unsigned int data_shndx,
- unsigned int sh_type,
- const unsigned char* prelocs,
- size_t reloc_count,
- Output_section* output_section,
- bool needs_special_offset_handling,
- size_t local_symbol_count,
- const unsigned char* plocal_symbols)
+Target_x86_64<size>::gc_process_relocs(Symbol_table* symtab,
+ Layout* layout,
+ Sized_relobj_file<size, false>* object,
+ unsigned int data_shndx,
+ unsigned int sh_type,
+ const unsigned char* prelocs,
+ size_t reloc_count,
+ Output_section* output_section,
+ bool needs_special_offset_handling,
+ size_t local_symbol_count,
+ const unsigned char* plocal_symbols)
{
if (sh_type == elfcpp::SHT_REL)
return;
}
- gold::gc_process_relocs<64, false, Target_x86_64, elfcpp::SHT_RELA,
- Target_x86_64::Scan,
- Target_x86_64::Relocatable_size_for_reloc>(
+ gold::gc_process_relocs<size, false, Target_x86_64<size>, elfcpp::SHT_RELA,
+ Target_x86_64<size>::Scan,
+ Target_x86_64<size>::Relocatable_size_for_reloc>(
symtab,
layout,
this,
}
// Scan relocations for a section.
+template<int size>
void
-Target_x86_64::scan_relocs(Symbol_table* symtab,
- Layout* layout,
- Sized_relobj_file<64, false>* object,
- unsigned int data_shndx,
- unsigned int sh_type,
- const unsigned char* prelocs,
- size_t reloc_count,
- Output_section* output_section,
- bool needs_special_offset_handling,
- size_t local_symbol_count,
- const unsigned char* plocal_symbols)
+Target_x86_64<size>::scan_relocs(Symbol_table* symtab,
+ Layout* layout,
+ Sized_relobj_file<size, false>* object,
+ unsigned int data_shndx,
+ unsigned int sh_type,
+ const unsigned char* prelocs,
+ size_t reloc_count,
+ Output_section* output_section,
+ bool needs_special_offset_handling,
+ size_t local_symbol_count,
+ const unsigned char* plocal_symbols)
{
if (sh_type == elfcpp::SHT_REL)
{
return;
}
- gold::scan_relocs<64, false, Target_x86_64, elfcpp::SHT_RELA,
- Target_x86_64::Scan>(
+ gold::scan_relocs<size, false, Target_x86_64<size>, elfcpp::SHT_RELA,
+ Target_x86_64<size>::Scan>(
symtab,
layout,
this,
// Finalize the sections.
+template<int size>
void
-Target_x86_64::do_finalize_sections(
+Target_x86_64<size>::do_finalize_sections(
Layout* layout,
const Input_objects*,
Symbol_table* symtab)
if (sym != NULL)
{
uint64_t data_size = this->got_plt_->current_data_size();
- symtab->get_sized_symbol<64>(sym)->set_symsize(data_size);
+ symtab->get_sized_symbol<size>(sym)->set_symsize(data_size);
}
if (parameters->doing_static_link()
// Perform a relocation.
+template<int size>
inline bool
-Target_x86_64::Relocate::relocate(const Relocate_info<64, false>* relinfo,
- Target_x86_64* target,
- Output_section*,
- size_t relnum,
- const elfcpp::Rela<64, false>& rela,
- unsigned int r_type,
- const Sized_symbol<64>* gsym,
- const Symbol_value<64>* psymval,
- unsigned char* view,
- elfcpp::Elf_types<64>::Elf_Addr address,
- section_size_type view_size)
+Target_x86_64<size>::Relocate::relocate(
+ const Relocate_info<size, false>* relinfo,
+ Target_x86_64<size>* target,
+ Output_section*,
+ size_t relnum,
+ const elfcpp::Rela<size, false>& rela,
+ unsigned int r_type,
+ const Sized_symbol<size>* gsym,
+ const Symbol_value<size>* psymval,
+ unsigned char* view,
+ typename elfcpp::Elf_types<size>::Elf_Addr address,
+ section_size_type view_size)
{
if (this->skip_call_tls_get_addr_)
{
}
}
- const Sized_relobj_file<64, false>* object = relinfo->object;
+ const Sized_relobj_file<size, false>* object = relinfo->object;
// Pick the value to use for symbols defined in the PLT.
- Symbol_value<64> symval;
+ Symbol_value<size> symval;
if (gsym != NULL
&& gsym->use_plt_offset(Scan::get_reference_flags(r_type)))
{
}
else if (gsym == NULL && psymval->is_ifunc_symbol())
{
- unsigned int r_sym = elfcpp::elf_r_sym<64>(rela.get_r_info());
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
if (object->local_has_plt_offset(r_sym))
{
symval.set_output_value(target->plt_address_for_local(object, r_sym)
}
else
{
- unsigned int r_sym = elfcpp::elf_r_sym<64>(rela.get_r_info());
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
got_offset = (object->local_got_offset(r_sym, GOT_TYPE_STANDARD)
- target->got_size());
break;
case elfcpp::R_X86_64_64:
- Relocate_functions<64, false>::rela64(view, object, psymval, addend);
+ Relocate_functions<size, false>::rela64(view, object, psymval, addend);
break;
case elfcpp::R_X86_64_PC64:
- Relocate_functions<64, false>::pcrela64(view, object, psymval, addend,
+ Relocate_functions<size, false>::pcrela64(view, object, psymval, addend,
address);
break;
// uint64_t x = value + addend;
// x == static_cast<uint64_t>(static_cast<uint32_t>(x))
// Likewise for other <=32-bit relocations (but see R_X86_64_32S).
- Relocate_functions<64, false>::rela32(view, object, psymval, addend);
+ Relocate_functions<size, false>::rela32(view, object, psymval, addend);
break;
case elfcpp::R_X86_64_32S:
// FIXME: we need to verify that value + addend fits into 32 bits:
// int64_t x = value + addend; // note this quantity is signed!
// x == static_cast<int64_t>(static_cast<int32_t>(x))
- Relocate_functions<64, false>::rela32(view, object, psymval, addend);
+ Relocate_functions<size, false>::rela32(view, object, psymval, addend);
break;
case elfcpp::R_X86_64_PC32:
- Relocate_functions<64, false>::pcrela32(view, object, psymval, addend,
- address);
+ Relocate_functions<size, false>::pcrela32(view, object, psymval, addend,
+ address);
break;
case elfcpp::R_X86_64_16:
- Relocate_functions<64, false>::rela16(view, object, psymval, addend);
+ Relocate_functions<size, false>::rela16(view, object, psymval, addend);
break;
case elfcpp::R_X86_64_PC16:
- Relocate_functions<64, false>::pcrela16(view, object, psymval, addend,
- address);
+ Relocate_functions<size, false>::pcrela16(view, object, psymval, addend,
+ address);
break;
case elfcpp::R_X86_64_8:
- Relocate_functions<64, false>::rela8(view, object, psymval, addend);
+ Relocate_functions<size, false>::rela8(view, object, psymval, addend);
break;
case elfcpp::R_X86_64_PC8:
- Relocate_functions<64, false>::pcrela8(view, object, psymval, addend,
- address);
+ Relocate_functions<size, false>::pcrela8(view, object, psymval, addend,
+ address);
break;
case elfcpp::R_X86_64_PLT32:
// Note: while this code looks the same as for R_X86_64_PC32, it
// behaves differently because psymval was set to point to
// the PLT entry, rather than the symbol, in Scan::global().
- Relocate_functions<64, false>::pcrela32(view, object, psymval, addend,
- address);
+ Relocate_functions<size, false>::pcrela32(view, object, psymval, addend,
+ address);
break;
case elfcpp::R_X86_64_PLTOFF64:
gold_assert(gsym);
gold_assert(gsym->has_plt_offset()
|| gsym->final_value_is_known());
- elfcpp::Elf_types<64>::Elf_Addr got_address;
+ typename elfcpp::Elf_types<size>::Elf_Addr got_address;
got_address = target->got_section(NULL, NULL)->address();
- Relocate_functions<64, false>::rela64(view, object, psymval,
- addend - got_address);
+ Relocate_functions<size, false>::rela64(view, object, psymval,
+ addend - got_address);
}
case elfcpp::R_X86_64_GOT32:
gold_assert(have_got_offset);
- Relocate_functions<64, false>::rela32(view, got_offset, addend);
+ Relocate_functions<size, false>::rela32(view, got_offset, addend);
break;
case elfcpp::R_X86_64_GOTPC32:
{
gold_assert(gsym);
- elfcpp::Elf_types<64>::Elf_Addr value;
+ typename elfcpp::Elf_types<size>::Elf_Addr value;
value = target->got_plt_section()->address();
- Relocate_functions<64, false>::pcrela32(view, value, addend, address);
+ Relocate_functions<size, false>::pcrela32(view, value, addend, address);
}
break;
// Since we always add a PLT entry, this is equivalent.
case elfcpp::R_X86_64_GOTPLT64:
gold_assert(have_got_offset);
- Relocate_functions<64, false>::rela64(view, got_offset, addend);
+ Relocate_functions<size, false>::rela64(view, got_offset, addend);
break;
case elfcpp::R_X86_64_GOTPC64:
{
gold_assert(gsym);
- elfcpp::Elf_types<64>::Elf_Addr value;
+ typename elfcpp::Elf_types<size>::Elf_Addr value;
value = target->got_plt_section()->address();
- Relocate_functions<64, false>::pcrela64(view, value, addend, address);
+ Relocate_functions<size, false>::pcrela64(view, value, addend, address);
}
break;
case elfcpp::R_X86_64_GOTOFF64:
{
- elfcpp::Elf_types<64>::Elf_Addr value;
+ typename elfcpp::Elf_types<size>::Elf_Addr value;
value = (psymval->value(object, 0)
- target->got_plt_section()->address());
- Relocate_functions<64, false>::rela64(view, value, addend);
+ Relocate_functions<size, false>::rela64(view, value, addend);
}
break;
case elfcpp::R_X86_64_GOTPCREL:
{
gold_assert(have_got_offset);
- elfcpp::Elf_types<64>::Elf_Addr value;
+ typename elfcpp::Elf_types<size>::Elf_Addr value;
value = target->got_plt_section()->address() + got_offset;
- Relocate_functions<64, false>::pcrela32(view, value, addend, address);
+ Relocate_functions<size, false>::pcrela32(view, value, addend, address);
}
break;
case elfcpp::R_X86_64_GOTPCREL64:
{
gold_assert(have_got_offset);
- elfcpp::Elf_types<64>::Elf_Addr value;
+ typename elfcpp::Elf_types<size>::Elf_Addr value;
value = target->got_plt_section()->address() + got_offset;
- Relocate_functions<64, false>::pcrela64(view, value, addend, address);
+ Relocate_functions<size, false>::pcrela64(view, value, addend, address);
}
break;
// Perform a TLS relocation.
+template<int size>
inline void
-Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo,
- Target_x86_64* target,
- size_t relnum,
- const elfcpp::Rela<64, false>& rela,
- unsigned int r_type,
- const Sized_symbol<64>* gsym,
- const Symbol_value<64>* psymval,
- unsigned char* view,
- elfcpp::Elf_types<64>::Elf_Addr address,
- section_size_type view_size)
+Target_x86_64<size>::Relocate::relocate_tls(
+ const Relocate_info<size, false>* relinfo,
+ Target_x86_64<size>* target,
+ size_t relnum,
+ const elfcpp::Rela<size, false>& rela,
+ unsigned int r_type,
+ const Sized_symbol<size>* gsym,
+ const Symbol_value<size>* psymval,
+ unsigned char* view,
+ typename elfcpp::Elf_types<size>::Elf_Addr address,
+ section_size_type view_size)
{
Output_segment* tls_segment = relinfo->layout->tls_segment();
- const Sized_relobj_file<64, false>* object = relinfo->object;
+ const Sized_relobj_file<size, false>* object = relinfo->object;
const elfcpp::Elf_Xword addend = rela.get_r_addend();
- elfcpp::Shdr<64, false> data_shdr(relinfo->data_shdr);
+ elfcpp::Shdr<size, false> data_shdr(relinfo->data_shdr);
bool is_executable = (data_shdr.get_sh_flags() & elfcpp::SHF_EXECINSTR) != 0;
- elfcpp::Elf_types<64>::Elf_Addr value = psymval->value(relinfo->object, 0);
+ typename elfcpp::Elf_types<size>::Elf_Addr value = psymval->value(relinfo->object, 0);
const bool is_final = (gsym == NULL
? !parameters->options().shared()
: gsym->final_value_is_known());
tls::Tls_optimization optimized_type
- = Target_x86_64::optimize_tls_reloc(is_final, r_type);
+ = Target_x86_64<size>::optimize_tls_reloc(is_final, r_type);
switch (r_type)
{
case elfcpp::R_X86_64_TLSGD: // Global-dynamic
}
else
{
- unsigned int r_sym = elfcpp::elf_r_sym<64>(rela.get_r_info());
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
gold_assert(object->local_has_got_offset(r_sym, got_type));
got_offset = (object->local_got_offset(r_sym, got_type)
- target->got_size());
// Relocate the field with the offset of the pair of GOT
// entries.
value = target->got_plt_section()->address() + got_offset;
- Relocate_functions<64, false>::pcrela32(view, value, addend,
- address);
+ Relocate_functions<size, false>::pcrela32(view, value, addend,
+ address);
break;
}
}
}
else
{
- unsigned int r_sym = elfcpp::elf_r_sym<64>(rela.get_r_info());
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
gold_assert(object->local_has_got_offset(r_sym, got_type));
got_offset += (object->local_got_offset(r_sym, got_type)
- target->got_size());
// Relocate the field with the offset of the pair of GOT
// entries.
value = target->got_plt_section()->address() + got_offset;
- Relocate_functions<64, false>::pcrela32(view, value, addend,
- address);
+ Relocate_functions<size, false>::pcrela32(view, value, addend,
+ address);
}
break;
}
got_offset = (target->got_mod_index_entry(NULL, NULL, NULL)
- target->got_size());
value = target->got_plt_section()->address() + got_offset;
- Relocate_functions<64, false>::pcrela32(view, value, addend,
- address);
+ Relocate_functions<size, false>::pcrela32(view, value, addend,
+ address);
break;
}
gold_error_at_location(relinfo, relnum, rela.get_r_offset(),
}
value -= tls_segment->memsz();
}
- Relocate_functions<64, false>::rela32(view, value, addend);
+ Relocate_functions<size, false>::rela32(view, value, addend);
break;
case elfcpp::R_X86_64_DTPOFF64:
}
value -= tls_segment->memsz();
}
- Relocate_functions<64, false>::rela64(view, value, addend);
+ Relocate_functions<size, false>::rela64(view, value, addend);
break;
case elfcpp::R_X86_64_GOTTPOFF: // Initial-exec
|| issue_undefined_symbol_error(gsym));
return;
}
- Target_x86_64::Relocate::tls_ie_to_le(relinfo, relnum, tls_segment,
- rela, r_type, value, view,
- view_size);
+ Target_x86_64<size>::Relocate::tls_ie_to_le(relinfo, relnum,
+ tls_segment, rela,
+ r_type, value, view,
+ view_size);
break;
}
else if (optimized_type == tls::TLSOPT_NONE)
}
else
{
- unsigned int r_sym = elfcpp::elf_r_sym<64>(rela.get_r_info());
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
gold_assert(object->local_has_got_offset(r_sym,
GOT_TYPE_TLS_OFFSET));
got_offset = (object->local_got_offset(r_sym, GOT_TYPE_TLS_OFFSET)
- target->got_size());
}
value = target->got_plt_section()->address() + got_offset;
- Relocate_functions<64, false>::pcrela32(view, value, addend, address);
+ Relocate_functions<size, false>::pcrela32(view, value, addend,
+ address);
break;
}
gold_error_at_location(relinfo, relnum, rela.get_r_offset(),
return;
}
value -= tls_segment->memsz();
- Relocate_functions<64, false>::rela32(view, value, addend);
+ Relocate_functions<size, false>::rela32(view, value, addend);
break;
}
}
// Do a relocation in which we convert a TLS General-Dynamic to an
// Initial-Exec.
+template<int size>
inline void
-Target_x86_64::Relocate::tls_gd_to_ie(const Relocate_info<64, false>* relinfo,
- size_t relnum,
- Output_segment*,
- const elfcpp::Rela<64, false>& rela,
- unsigned int,
- elfcpp::Elf_types<64>::Elf_Addr value,
- unsigned char* view,
- elfcpp::Elf_types<64>::Elf_Addr address,
- section_size_type view_size)
+Target_x86_64<size>::Relocate::tls_gd_to_ie(
+ const Relocate_info<size, false>* relinfo,
+ size_t relnum,
+ Output_segment*,
+ const elfcpp::Rela<size, false>& rela,
+ unsigned int,
+ typename elfcpp::Elf_types<size>::Elf_Addr value,
+ unsigned char* view,
+ typename elfcpp::Elf_types<size>::Elf_Addr address,
+ section_size_type view_size)
{
// .byte 0x66; leaq foo@tlsgd(%rip),%rdi;
// .word 0x6666; rex64; call __tls_get_addr
memcpy(view - 4, "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x03\x05\0\0\0\0", 16);
const elfcpp::Elf_Xword addend = rela.get_r_addend();
- Relocate_functions<64, false>::pcrela32(view + 8, value, addend - 8, address);
+ Relocate_functions<size, false>::pcrela32(view + 8, value, addend - 8,
+ address);
// The next reloc should be a PLT32 reloc against __tls_get_addr.
// We can skip it.
// Do a relocation in which we convert a TLS General-Dynamic to a
// Local-Exec.
+template<int size>
inline void
-Target_x86_64::Relocate::tls_gd_to_le(const Relocate_info<64, false>* relinfo,
- size_t relnum,
- Output_segment* tls_segment,
- const elfcpp::Rela<64, false>& rela,
- unsigned int,
- elfcpp::Elf_types<64>::Elf_Addr value,
- unsigned char* view,
- section_size_type view_size)
+Target_x86_64<size>::Relocate::tls_gd_to_le(
+ const Relocate_info<size, false>* relinfo,
+ size_t relnum,
+ Output_segment* tls_segment,
+ const elfcpp::Rela<size, false>& rela,
+ unsigned int,
+ typename elfcpp::Elf_types<size>::Elf_Addr value,
+ unsigned char* view,
+ section_size_type view_size)
{
// .byte 0x66; leaq foo@tlsgd(%rip),%rdi;
// .word 0x6666; rex64; call __tls_get_addr
memcpy(view - 4, "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x8d\x80\0\0\0\0", 16);
value -= tls_segment->memsz();
- Relocate_functions<64, false>::rela32(view + 8, value, 0);
+ Relocate_functions<size, false>::rela32(view + 8, value, 0);
// The next reloc should be a PLT32 reloc against __tls_get_addr.
// We can skip it.
// Do a TLSDESC-style General-Dynamic to Initial-Exec transition.
+template<int size>
inline void
-Target_x86_64::Relocate::tls_desc_gd_to_ie(
- const Relocate_info<64, false>* relinfo,
+Target_x86_64<size>::Relocate::tls_desc_gd_to_ie(
+ const Relocate_info<size, false>* relinfo,
size_t relnum,
Output_segment*,
- const elfcpp::Rela<64, false>& rela,
+ const elfcpp::Rela<size, false>& rela,
unsigned int r_type,
- elfcpp::Elf_types<64>::Elf_Addr value,
+ typename elfcpp::Elf_types<size>::Elf_Addr value,
unsigned char* view,
- elfcpp::Elf_types<64>::Elf_Addr address,
+ typename elfcpp::Elf_types<size>::Elf_Addr address,
section_size_type view_size)
{
if (r_type == elfcpp::R_X86_64_GOTPC32_TLSDESC)
view[-3] == 0x48 && view[-2] == 0x8d && view[-1] == 0x05);
view[-2] = 0x8b;
const elfcpp::Elf_Xword addend = rela.get_r_addend();
- Relocate_functions<64, false>::pcrela32(view, value, addend, address);
+ Relocate_functions<size, false>::pcrela32(view, value, addend, address);
}
else
{
// Do a TLSDESC-style General-Dynamic to Local-Exec transition.
+template<int size>
inline void
-Target_x86_64::Relocate::tls_desc_gd_to_le(
- const Relocate_info<64, false>* relinfo,
+Target_x86_64<size>::Relocate::tls_desc_gd_to_le(
+ const Relocate_info<size, false>* relinfo,
size_t relnum,
Output_segment* tls_segment,
- const elfcpp::Rela<64, false>& rela,
+ const elfcpp::Rela<size, false>& rela,
unsigned int r_type,
- elfcpp::Elf_types<64>::Elf_Addr value,
+ typename elfcpp::Elf_types<size>::Elf_Addr value,
unsigned char* view,
section_size_type view_size)
{
view[-2] = 0xc7;
view[-1] = 0xc0;
value -= tls_segment->memsz();
- Relocate_functions<64, false>::rela32(view, value, 0);
+ Relocate_functions<size, false>::rela32(view, value, 0);
}
else
{
}
}
+template<int size>
inline void
-Target_x86_64::Relocate::tls_ld_to_le(const Relocate_info<64, false>* relinfo,
- size_t relnum,
- Output_segment*,
- const elfcpp::Rela<64, false>& rela,
- unsigned int,
- elfcpp::Elf_types<64>::Elf_Addr,
- unsigned char* view,
- section_size_type view_size)
+Target_x86_64<size>::Relocate::tls_ld_to_le(
+ const Relocate_info<size, false>* relinfo,
+ size_t relnum,
+ Output_segment*,
+ const elfcpp::Rela<size, false>& rela,
+ unsigned int,
+ typename elfcpp::Elf_types<size>::Elf_Addr,
+ unsigned char* view,
+ section_size_type view_size)
{
// leaq foo@tlsld(%rip),%rdi; call __tls_get_addr@plt;
// ... leq foo@dtpoff(%rax),%reg
// Do a relocation in which we convert a TLS Initial-Exec to a
// Local-Exec.
+template<int size>
inline void
-Target_x86_64::Relocate::tls_ie_to_le(const Relocate_info<64, false>* relinfo,
- size_t relnum,
- Output_segment* tls_segment,
- const elfcpp::Rela<64, false>& rela,
- unsigned int,
- elfcpp::Elf_types<64>::Elf_Addr value,
- unsigned char* view,
- section_size_type view_size)
+Target_x86_64<size>::Relocate::tls_ie_to_le(
+ const Relocate_info<size, false>* relinfo,
+ size_t relnum,
+ Output_segment* tls_segment,
+ const elfcpp::Rela<size, false>& rela,
+ unsigned int,
+ typename elfcpp::Elf_types<size>::Elf_Addr value,
+ unsigned char* view,
+ section_size_type view_size)
{
// We need to examine the opcodes to figure out which instruction we
// are looking at.
}
value -= tls_segment->memsz();
- Relocate_functions<64, false>::rela32(view, value, 0);
+ Relocate_functions<size, false>::rela32(view, value, 0);
}
// Relocate section data.
+template<int size>
void
-Target_x86_64::relocate_section(
- const Relocate_info<64, false>* relinfo,
+Target_x86_64<size>::relocate_section(
+ const Relocate_info<size, false>* relinfo,
unsigned int sh_type,
const unsigned char* prelocs,
size_t reloc_count,
Output_section* output_section,
bool needs_special_offset_handling,
unsigned char* view,
- elfcpp::Elf_types<64>::Elf_Addr address,
+ typename elfcpp::Elf_types<size>::Elf_Addr address,
section_size_type view_size,
const Reloc_symbol_changes* reloc_symbol_changes)
{
gold_assert(sh_type == elfcpp::SHT_RELA);
- gold::relocate_section<64, false, Target_x86_64, elfcpp::SHT_RELA,
- Target_x86_64::Relocate>(
+ gold::relocate_section<size, false, Target_x86_64<size>, elfcpp::SHT_RELA,
+ Target_x86_64<size>::Relocate>(
relinfo,
this,
prelocs,
// Apply an incremental relocation. Incremental relocations always refer
// to global symbols.
+template<int size>
void
-Target_x86_64::apply_relocation(
- const Relocate_info<64, false>* relinfo,
- elfcpp::Elf_types<64>::Elf_Addr r_offset,
+Target_x86_64<size>::apply_relocation(
+ const Relocate_info<size, false>* relinfo,
+ typename elfcpp::Elf_types<size>::Elf_Addr r_offset,
unsigned int r_type,
- elfcpp::Elf_types<64>::Elf_Swxword r_addend,
+ typename elfcpp::Elf_types<size>::Elf_Swxword r_addend,
const Symbol* gsym,
unsigned char* view,
- elfcpp::Elf_types<64>::Elf_Addr address,
+ typename elfcpp::Elf_types<size>::Elf_Addr address,
section_size_type view_size)
{
- gold::apply_relocation<64, false, Target_x86_64, Target_x86_64::Relocate>(
+ gold::apply_relocation<size, false, Target_x86_64<size>,
+ Target_x86_64<size>::Relocate>(
relinfo,
this,
r_offset,
// Return the size of a relocation while scanning during a relocatable
// link.
+template<int size>
unsigned int
-Target_x86_64::Relocatable_size_for_reloc::get_size_for_reloc(
+Target_x86_64<size>::Relocatable_size_for_reloc::get_size_for_reloc(
unsigned int r_type,
Relobj* object)
{
// Scan the relocs during a relocatable link.
+template<int size>
void
-Target_x86_64::scan_relocatable_relocs(Symbol_table* symtab,
- Layout* layout,
- Sized_relobj_file<64, false>* object,
- unsigned int data_shndx,
- unsigned int sh_type,
- const unsigned char* prelocs,
- size_t reloc_count,
- Output_section* output_section,
- bool needs_special_offset_handling,
- size_t local_symbol_count,
- const unsigned char* plocal_symbols,
- Relocatable_relocs* rr)
+Target_x86_64<size>::scan_relocatable_relocs(
+ Symbol_table* symtab,
+ Layout* layout,
+ Sized_relobj_file<size, false>* object,
+ unsigned int data_shndx,
+ unsigned int sh_type,
+ const unsigned char* prelocs,
+ size_t reloc_count,
+ Output_section* output_section,
+ bool needs_special_offset_handling,
+ size_t local_symbol_count,
+ const unsigned char* plocal_symbols,
+ Relocatable_relocs* rr)
{
gold_assert(sh_type == elfcpp::SHT_RELA);
typedef gold::Default_scan_relocatable_relocs<elfcpp::SHT_RELA,
Relocatable_size_for_reloc> Scan_relocatable_relocs;
- gold::scan_relocatable_relocs<64, false, elfcpp::SHT_RELA,
+ gold::scan_relocatable_relocs<size, false, elfcpp::SHT_RELA,
Scan_relocatable_relocs>(
symtab,
layout,
// Relocate a section during a relocatable link.
+template<int size>
void
-Target_x86_64::relocate_for_relocatable(
- const Relocate_info<64, false>* relinfo,
+Target_x86_64<size>::relocate_for_relocatable(
+ const Relocate_info<size, false>* relinfo,
unsigned int sh_type,
const unsigned char* prelocs,
size_t reloc_count,
off_t offset_in_output_section,
const Relocatable_relocs* rr,
unsigned char* view,
- elfcpp::Elf_types<64>::Elf_Addr view_address,
+ typename elfcpp::Elf_types<size>::Elf_Addr view_address,
section_size_type view_size,
unsigned char* reloc_view,
section_size_type reloc_view_size)
{
gold_assert(sh_type == elfcpp::SHT_RELA);
- gold::relocate_for_relocatable<64, false, elfcpp::SHT_RELA>(
+ gold::relocate_for_relocatable<size, false, elfcpp::SHT_RELA>(
relinfo,
prelocs,
reloc_count,
// pointers across shared library boundaries, as described in the
// processor specific ABI supplement.
+template<int size>
uint64_t
-Target_x86_64::do_dynsym_value(const Symbol* gsym) const
+Target_x86_64<size>::do_dynsym_value(const Symbol* gsym) const
{
gold_assert(gsym->is_from_dynobj() && gsym->has_plt_offset());
return this->plt_address_for_global(gsym) + gsym->plt_offset();
// Return a string used to fill a code section with nops to take up
// the specified length.
+template<int size>
std::string
-Target_x86_64::do_code_fill(section_size_type length) const
+Target_x86_64<size>::do_code_fill(section_size_type length) const
{
if (length >= 16)
{
// symbol. We want to set the addend is the offset of the local
// symbol in the TLS segment.
+template<int size>
uint64_t
-Target_x86_64::do_reloc_addend(void* arg, unsigned int r_type,
- uint64_t) const
+Target_x86_64<size>::do_reloc_addend(void* arg, unsigned int r_type,
+ uint64_t) const
{
gold_assert(r_type == elfcpp::R_X86_64_TLSDESC);
uintptr_t intarg = reinterpret_cast<uintptr_t>(arg);
gold_assert(intarg < this->tlsdesc_reloc_info_.size());
const Tlsdesc_info& ti(this->tlsdesc_reloc_info_[intarg]);
- const Symbol_value<64>* psymval = ti.object->local_symbol(ti.r_sym);
+ const Symbol_value<size>* psymval = ti.object->local_symbol(ti.r_sym);
gold_assert(psymval->is_tls_symbol());
// The value of a TLS symbol is the offset in the TLS segment.
return psymval->value(ti.object, 0);
// different sections, so instead of using a pc-relative value they
// use an offset from the GOT.
+template<int size>
uint64_t
-Target_x86_64::do_ehframe_datarel_base() const
+Target_x86_64<size>::do_ehframe_datarel_base() const
{
gold_assert(this->global_offset_table_ != NULL);
Symbol* sym = this->global_offset_table_;
- Sized_symbol<64>* ssym = static_cast<Sized_symbol<64>*>(sym);
+ Sized_symbol<size>* ssym = static_cast<Sized_symbol<size>*>(sym);
return ssym->value();
}
// code. We have to change the function so that it always ensures
// that it has enough stack space to run some random function.
+template<int size>
void
-Target_x86_64::do_calls_non_split(Relobj* object, unsigned int shndx,
- section_offset_type fnoffset,
- section_size_type fnsize,
- unsigned char* view,
- section_size_type view_size,
- std::string* from,
- std::string* to) const
+Target_x86_64<size>::do_calls_non_split(Relobj* object, unsigned int shndx,
+ section_offset_type fnoffset,
+ section_size_type fnsize,
+ unsigned char* view,
+ section_size_type view_size,
+ std::string* from,
+ std::string* to) const
{
// The function starts with a comparison of the stack pointer and a
// field in the TCB. This is followed by a jump.
// The selector for x86_64 object files.
+template<int size>
class Target_selector_x86_64 : public Target_selector_freebsd
{
public:
Target_selector_x86_64()
- : Target_selector_freebsd(elfcpp::EM_X86_64, 64, false, "elf64-x86-64",
- "elf64-x86-64-freebsd", "elf_x86_64")
+ : Target_selector_freebsd(elfcpp::EM_X86_64, size, false,
+ (size == 64
+ ? "elf64-x86-64" : "elf32-x86-64"),
+ (size == 64
+ ? "elf64-x86-64-freebsd"
+ : "elf32-x86-64-freebsd"),
+ (size == 64 ? "elf_x86_64" : "elf32_x86_64"))
{ }
Target*
do_instantiate_target()
- { return new Target_x86_64(); }
+ { return new Target_x86_64<size>(); }
};
-Target_selector_x86_64 target_selector_x86_64;
+Target_selector_x86_64<64> target_selector_x86_64;
+Target_selector_x86_64<32> target_selector_x32;
} // End anonymous namespace.