mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-02-23 13:21:43 +08:00
The 3rd patch for aarch64 gold.
This enables - 1. static linking hello world 2. limited support for TLSIE and TLSLE 3. limited support for linking shared library, linking executable against shared library. gold/ChangeLog 2014-08-29 Han Shen <shenhan@google.com> Jing Yu <jingyu@google.com> * aarch64-reloc-property.cc (AArch64_reloc_property_table::reloc_name_in_error_message): Fix bug in reference reloc property in the table. * aarch64-reloc.def: Add TLSLE reloc types and fix some errors in 3 other entries. * aarch64.cc: (Output_data_got_aarch64::add_static_reloc): 2 new overloaded methods. (Output_data_got_aarch64::do_write): Add code to write out static relocs. (class Output_data_got_aarch64::Static_reloc): New class to wrap static relocs. (Output_data_got_aarch64::static_relocs): New vector to hold static relocs. (Target_aarch64::TCB_SIZE): New const static memeber. (Target_aarch64::tcb_size): New method. (Target_aarch64::Relocate::relocate): Add code handling new reloc types. (Target_aarch64::Relocate::relocate_tls): New method. (Target_aarch64::Scan::local): Add code handling new reloc types. (Target_aarch64::Scan::global): Add code handling new reloc types.
This commit is contained in:
parent
6128f9cf2b
commit
8e33481e13
@ -1,3 +1,26 @@
|
||||
2014-08-29 Han Shen <shenhan@google.com>
|
||||
Jing Yu <jingyu@google.com>
|
||||
|
||||
* aarch64-reloc-property.cc
|
||||
(AArch64_reloc_property_table::reloc_name_in_error_message): Fix bug in
|
||||
reference reloc property in the table.
|
||||
* aarch64-reloc.def: Add TLSLE reloc types and fix some errors in
|
||||
3 other entries.
|
||||
* aarch64.cc: (Output_data_got_aarch64::add_static_reloc):
|
||||
2 new overloaded methods.
|
||||
(Output_data_got_aarch64::do_write): Add code to write out
|
||||
static relocs.
|
||||
(class Output_data_got_aarch64::Static_reloc): New class to wrap
|
||||
static relocs.
|
||||
(Output_data_got_aarch64::static_relocs): New vector to
|
||||
hold static relocs.
|
||||
(Target_aarch64::TCB_SIZE): New const static memeber.
|
||||
(Target_aarch64::tcb_size): New method.
|
||||
(Target_aarch64::Relocate::relocate): Add code handling new reloc types.
|
||||
(Target_aarch64::Relocate::relocate_tls): New method.
|
||||
(Target_aarch64::Scan::local): Add code handling new reloc types.
|
||||
(Target_aarch64::Scan::global): Add code handling new reloc types.
|
||||
|
||||
2014-08-13 Sriraman Tallam <tmsriram@google.com>
|
||||
|
||||
* options.h (-no-pie): Add option.
|
||||
|
@ -130,9 +130,8 @@ AArch64_reloc_property_table::AArch64_reloc_property_table()
|
||||
std::string
|
||||
AArch64_reloc_property_table::reloc_name_in_error_message(unsigned int code)
|
||||
{
|
||||
gold_assert(code < Property_table_size);
|
||||
|
||||
const AArch64_reloc_property* arp = this->table_[code];
|
||||
int tidx = code_to_array_index(code);
|
||||
const AArch64_reloc_property* arp = this->table_[tidx];
|
||||
|
||||
if (arp == NULL)
|
||||
{
|
||||
|
@ -50,8 +50,8 @@ ARD(LDST128_ABS_LO12_NC , STATIC , AARCH64 , Y, -1, 0,RL_CHEC
|
||||
ARD(ADD_ABS_LO12_NC , STATIC , AARCH64 , Y, -1, 0,0 , 0,11 , Symbol::ABSOLUTE_REF , ADD )
|
||||
ARD(ADR_GOT_PAGE , STATIC , AARCH64 , Y, -1, 32,32 , 12,32 , Symbol::RELATIVE_REF , ADRP )
|
||||
ARD(LD64_GOT_LO12_NC , STATIC , AARCH64 , Y, -1, 0,RL_CHECK_ALIGN8 , 3,11 , Symbol::ABSOLUTE_REF , LDST )
|
||||
ARD(TSTBR14 , STATIC , CFLOW , N, -1, 15,15 , 2,15 , Symbol::ABSOLUTE_REF , TBZNZ )
|
||||
ARD(CONDBR19 , STATIC , CFLOW , N, -1, 20,20 , 2,20 , Symbol::ABSOLUTE_REF , CONDB )
|
||||
ARD(TSTBR14 , STATIC , CFLOW , N, -1, 15,15 , 2,15 , (Symbol::FUNCTION_CALL|Symbol::ABSOLUTE_REF) , TBZNZ )
|
||||
ARD(CONDBR19 , STATIC , CFLOW , N, -1, 20,20 , 2,20 , (Symbol::FUNCTION_CALL|Symbol::ABSOLUTE_REF) , CONDB )
|
||||
ARD(CALL26 , STATIC , CFLOW , Y, -1, 27,27 , 2,27 , (Symbol::FUNCTION_CALL|Symbol::RELATIVE_REF) , CALL )
|
||||
ARD(JUMP26 , STATIC , CFLOW , Y, -1, 27,27 , 2,27 , (Symbol::FUNCTION_CALL|Symbol::RELATIVE_REF) , B )
|
||||
// Above is from Table 4-10, Relocations for control-flow instructions,
|
||||
@ -60,10 +60,15 @@ ARD(JUMP26 , STATIC , CFLOW , Y, -1, 27,27
|
||||
ARD(TLSIE_MOVW_GOTTPREL_G1 , STATIC , AARCH64 , N, -1, 0,0 , 16,31 , Symbol::ABSOLUTE_REF , MOVW )
|
||||
ARD(TLSIE_MOVW_GOTTPREL_G0_NC , STATIC , AARCH64 , N, -1, 0,0 , 0,15 , Symbol::ABSOLUTE_REF , MOVW )
|
||||
ARD(TLSIE_ADR_GOTTPREL_PAGE21 , STATIC , AARCH64 , Y, -1, 32,32 , 12,32 , Symbol::ABSOLUTE_REF , ADRP )
|
||||
ARD(TLSIE_LD64_GOTTPREL_LO12_NC , STATIC , AARCH64 , N, -1, 32,32 , 12,32 , Symbol::ABSOLUTE_REF , LDST )
|
||||
ARD(TLSIE_LD64_GOTTPREL_LO12_NC , STATIC , AARCH64 , Y, -1, 0,RL_CHECK_ALIGN8 , 3,11 , Symbol::ABSOLUTE_REF , LDST )
|
||||
ARD(TLSIE_LD_GOTTPREL_PREL19 , STATIC , AARCH64 , N, -1, 20,20 , 2,20 , Symbol::ABSOLUTE_REF , LD )
|
||||
// Above is from Table 4-17, Initial Exec TLS relocations, 539-543.
|
||||
|
||||
ARD(TLSLE_ADD_TPREL_HI12 , STATIC , AARCH64 , Y, -1, 0,24 , 12,23 , Symbol::ABSOLUTE_REF , ADD )
|
||||
ARD(TLSLE_ADD_TPREL_LO12 , STATIC , AARCH64 , Y, -1, 0,12 , 0,11 , Symbol::ABSOLUTE_REF , ADD )
|
||||
ARD(TLSLE_ADD_TPREL_LO12_NC , STATIC , AARCH64 , Y, -1, 0,0 , 0,11 , Symbol::ABSOLUTE_REF , ADD )
|
||||
// Above is from Table 4-18, Local Exec TLS relocations, 544-571.
|
||||
|
||||
// Note -
|
||||
// A - Checking X, (L,U), if L == 0 && U == 0, no check. Otherwise, L!=0,
|
||||
// check that -2^L<=X<2^U. Also an extra alignment check could be embeded
|
||||
|
645
gold/aarch64.cc
645
gold/aarch64.cc
@ -76,6 +76,27 @@ class Output_data_got_aarch64 : public Output_data_got<size, big_endian>
|
||||
symbol_table_(symtab), layout_(layout)
|
||||
{ }
|
||||
|
||||
// Add a static entry for the GOT entry at OFFSET. GSYM is a global
|
||||
// symbol and R_TYPE is the code of a dynamic relocation that needs to be
|
||||
// applied in a static link.
|
||||
void
|
||||
add_static_reloc(unsigned int got_offset, unsigned int r_type, Symbol* gsym)
|
||||
{ this->static_relocs_.push_back(Static_reloc(got_offset, r_type, gsym)); }
|
||||
|
||||
|
||||
// Add a static reloc for the GOT entry at OFFSET. RELOBJ is an object
|
||||
// defining a local symbol with INDEX. R_TYPE is the code of a dynamic
|
||||
// relocation that needs to be applied in a static link.
|
||||
void
|
||||
add_static_reloc(unsigned int got_offset, unsigned int r_type,
|
||||
Sized_relobj_file<size, big_endian>* relobj,
|
||||
unsigned int index)
|
||||
{
|
||||
this->static_relocs_.push_back(Static_reloc(got_offset, r_type, relobj,
|
||||
index));
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
// Write out the GOT table.
|
||||
void
|
||||
@ -86,6 +107,104 @@ class Output_data_got_aarch64 : public Output_data_got<size, big_endian>
|
||||
Valtype dynamic_addr = dynamic == NULL ? 0 : dynamic->address();
|
||||
this->replace_constant(0, dynamic_addr);
|
||||
Output_data_got<size, big_endian>::do_write(of);
|
||||
|
||||
// Handling static relocs
|
||||
if (this->static_relocs_.empty())
|
||||
return;
|
||||
|
||||
typedef typename elfcpp::Elf_types<size>::Elf_Addr AArch64_address;
|
||||
|
||||
gold_assert(parameters->doing_static_link());
|
||||
const off_t offset = this->offset();
|
||||
const section_size_type oview_size =
|
||||
convert_to_section_size_type(this->data_size());
|
||||
unsigned char* const oview = of->get_output_view(offset, oview_size);
|
||||
|
||||
Output_segment* tls_segment = this->layout_->tls_segment();
|
||||
gold_assert(tls_segment != NULL);
|
||||
|
||||
AArch64_address aligned_tcb_address =
|
||||
align_address(Target_aarch64<size,big_endian>::TCB_SIZE,
|
||||
tls_segment->maximum_alignment());
|
||||
|
||||
for (size_t i = 0; i < this->static_relocs_.size(); ++i)
|
||||
{
|
||||
Static_reloc& reloc(this->static_relocs_[i]);
|
||||
AArch64_address value;
|
||||
|
||||
if (!reloc.symbol_is_global())
|
||||
{
|
||||
Sized_relobj_file<size, big_endian>* object = reloc.relobj();
|
||||
const Symbol_value<size>* psymval =
|
||||
reloc.relobj()->local_symbol(reloc.index());
|
||||
|
||||
// We are doing static linking. Issue an error and skip this
|
||||
// relocation if the symbol is undefined or in a discarded_section.
|
||||
bool is_ordinary;
|
||||
unsigned int shndx = psymval->input_shndx(&is_ordinary);
|
||||
if ((shndx == elfcpp::SHN_UNDEF)
|
||||
|| (is_ordinary
|
||||
&& shndx != elfcpp::SHN_UNDEF
|
||||
&& !object->is_section_included(shndx)
|
||||
&& !this->symbol_table_->is_section_folded(object, shndx)))
|
||||
{
|
||||
gold_error(_("undefined or discarded local symbol %u from "
|
||||
" object %s in GOT"),
|
||||
reloc.index(), reloc.relobj()->name().c_str());
|
||||
continue;
|
||||
}
|
||||
value = psymval->value(object, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
const Symbol* gsym = reloc.symbol();
|
||||
gold_assert(gsym != NULL);
|
||||
if (gsym->is_forwarder())
|
||||
gsym = this->symbol_table_->resolve_forwards(gsym);
|
||||
|
||||
// We are doing static linking. Issue an error and skip this
|
||||
// relocation if the symbol is undefined or in a discarded_section
|
||||
// unless it is a weakly_undefined symbol.
|
||||
if ((gsym->is_defined_in_discarded_section()
|
||||
|| gsym->is_undefined())
|
||||
&& !gsym->is_weak_undefined())
|
||||
{
|
||||
gold_error(_("undefined or discarded symbol %s in GOT"),
|
||||
gsym->name());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!gsym->is_weak_undefined())
|
||||
{
|
||||
const Sized_symbol<size>* sym =
|
||||
static_cast<const Sized_symbol<size>*>(gsym);
|
||||
value = sym->value();
|
||||
}
|
||||
else
|
||||
value = 0;
|
||||
}
|
||||
|
||||
unsigned got_offset = reloc.got_offset();
|
||||
gold_assert(got_offset < oview_size);
|
||||
|
||||
typedef typename elfcpp::Swap<size, big_endian>::Valtype Valtype;
|
||||
Valtype* wv = reinterpret_cast<Valtype*>(oview + got_offset);
|
||||
Valtype x;
|
||||
switch (reloc.r_type())
|
||||
{
|
||||
case elfcpp::R_AARCH64_TLS_DTPREL64:
|
||||
x = value;
|
||||
break;
|
||||
case elfcpp::R_AARCH64_TLS_TPREL64:
|
||||
x = value + aligned_tcb_address;
|
||||
break;
|
||||
default:
|
||||
gold_unreachable();
|
||||
}
|
||||
elfcpp::Swap<size, big_endian>::writeval(wv, x);
|
||||
}
|
||||
|
||||
of->write_output_view(offset, oview_size, oview);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -94,6 +213,90 @@ class Output_data_got_aarch64 : public Output_data_got<size, big_endian>
|
||||
// A pointer to the Layout class, so that we can find the .dynamic
|
||||
// section when we write out the GOT section.
|
||||
Layout* layout_;
|
||||
|
||||
|
||||
// This class represent dynamic relocations that need to be applied by
|
||||
// gold because we are using TLS relocations in a static link.
|
||||
class Static_reloc
|
||||
{
|
||||
public:
|
||||
Static_reloc(unsigned int got_offset, unsigned int r_type, Symbol* gsym)
|
||||
: got_offset_(got_offset), r_type_(r_type), symbol_is_global_(true)
|
||||
{ this->u_.global.symbol = gsym; }
|
||||
|
||||
Static_reloc(unsigned int got_offset, unsigned int r_type,
|
||||
Sized_relobj_file<size, big_endian>* relobj, unsigned int index)
|
||||
: got_offset_(got_offset), r_type_(r_type), symbol_is_global_(false)
|
||||
{
|
||||
this->u_.local.relobj = relobj;
|
||||
this->u_.local.index = index;
|
||||
}
|
||||
|
||||
// Return the GOT offset.
|
||||
unsigned int
|
||||
got_offset() const
|
||||
{ return this->got_offset_; }
|
||||
|
||||
// Relocation type.
|
||||
unsigned int
|
||||
r_type() const
|
||||
{ return this->r_type_; }
|
||||
|
||||
// Whether the symbol is global or not.
|
||||
bool
|
||||
symbol_is_global() const
|
||||
{ return this->symbol_is_global_; }
|
||||
|
||||
// For a relocation against a global symbol, the global symbol.
|
||||
Symbol*
|
||||
symbol() const
|
||||
{
|
||||
gold_assert(this->symbol_is_global_);
|
||||
return this->u_.global.symbol;
|
||||
}
|
||||
|
||||
// For a relocation against a local symbol, the defining object.
|
||||
Sized_relobj_file<size, big_endian>*
|
||||
relobj() const
|
||||
{
|
||||
gold_assert(!this->symbol_is_global_);
|
||||
return this->u_.local.relobj;
|
||||
}
|
||||
|
||||
// For a relocation against a local symbol, the local symbol index.
|
||||
unsigned int
|
||||
index() const
|
||||
{
|
||||
gold_assert(!this->symbol_is_global_);
|
||||
return this->u_.local.index;
|
||||
}
|
||||
|
||||
private:
|
||||
// GOT offset of the entry to which this relocation is applied.
|
||||
unsigned int got_offset_;
|
||||
// Type of relocation.
|
||||
unsigned int r_type_;
|
||||
// Whether this relocation is against a global symbol.
|
||||
bool symbol_is_global_;
|
||||
// A global or local symbol.
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
// For a global symbol, the symbol itself.
|
||||
Symbol* symbol;
|
||||
} global;
|
||||
struct
|
||||
{
|
||||
// For a local symbol, the object defining object.
|
||||
Sized_relobj_file<size, big_endian>* relobj;
|
||||
// For a local symbol, the symbol index.
|
||||
unsigned int index;
|
||||
} local;
|
||||
} u_;
|
||||
}; // End of inner class Static_reloc
|
||||
|
||||
std::vector<Static_reloc> static_relocs_;
|
||||
};
|
||||
|
||||
AArch64_reloc_property_table* aarch64_reloc_property_table = NULL;
|
||||
@ -105,9 +308,11 @@ template<int size, bool big_endian>
|
||||
class Target_aarch64 : public Sized_target<size, big_endian>
|
||||
{
|
||||
public:
|
||||
typedef Target_aarch64<size,big_endian> This;
|
||||
typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian>
|
||||
Reloc_section;
|
||||
typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
|
||||
const static int TCB_SIZE = size / 8 * 2;
|
||||
|
||||
Target_aarch64(const Target::Target_info* info = &aarch64_info)
|
||||
: Sized_target<size, big_endian>(info),
|
||||
@ -214,6 +419,9 @@ class Target_aarch64 : public Sized_target<size, big_endian>
|
||||
unsigned int
|
||||
plt_entry_size() const;
|
||||
|
||||
unsigned int
|
||||
tcb_size() const { return This::TCB_SIZE; }
|
||||
|
||||
protected:
|
||||
void
|
||||
do_select_as_default_target()
|
||||
@ -321,7 +529,18 @@ class Target_aarch64 : public Sized_target<size, big_endian>
|
||||
unsigned char*, typename elfcpp::Elf_types<size>::Elf_Addr,
|
||||
section_size_type);
|
||||
|
||||
};
|
||||
private:
|
||||
inline typename AArch64_relocate_functions<size,big_endian>::Status
|
||||
relocate_tls(const Relocate_info<size,big_endian>*,
|
||||
Target_aarch64<size, big_endian>*,
|
||||
size_t,
|
||||
const elfcpp::Rela<size, big_endian>&,
|
||||
unsigned int r_type, const Sized_symbol<size>*,
|
||||
const Symbol_value<size>*,
|
||||
unsigned char*,
|
||||
typename elfcpp::Elf_types<size>::Elf_Addr);
|
||||
|
||||
}; // End of class Relocate
|
||||
|
||||
// A class which returns the size required for a relocation type,
|
||||
// used while scanning relocs during a relocatable link.
|
||||
@ -410,7 +629,7 @@ class Target_aarch64 : public Sized_target<size, big_endian>
|
||||
Reloc_section* rela_dyn_;
|
||||
// Relocs saved to avoid a COPY reloc.
|
||||
Copy_relocs<elfcpp::SHT_RELA, size, big_endian> copy_relocs_;
|
||||
};
|
||||
}; // End of Target_aarch64
|
||||
|
||||
template<>
|
||||
const Target::Target_info Target_aarch64<64, false>::aarch64_info =
|
||||
@ -829,7 +1048,7 @@ void
|
||||
Output_data_plt_aarch64<size, big_endian>::set_final_data_size()
|
||||
{
|
||||
this->set_data_size(this->first_plt_entry_offset()
|
||||
+ this->count_ * this->get_plt_entry_size());
|
||||
+ this->count_ * this->get_plt_entry_size());
|
||||
}
|
||||
|
||||
template<int size, bool big_endian>
|
||||
@ -1617,13 +1836,13 @@ Target_aarch64<size, big_endian>::Scan::check_non_pic(Relobj* object,
|
||||
template<int size, bool big_endian>
|
||||
inline void
|
||||
Target_aarch64<size, big_endian>::Scan::local(
|
||||
Symbol_table* /* symtab */,
|
||||
Layout* /* layout */,
|
||||
Target_aarch64<size, big_endian>* /* target */,
|
||||
Symbol_table* symtab,
|
||||
Layout* layout,
|
||||
Target_aarch64<size, big_endian>* target,
|
||||
Sized_relobj_file<size, big_endian>* object,
|
||||
unsigned int /* data_shndx */,
|
||||
Output_section* /* output_section */,
|
||||
const elfcpp::Rela<size, big_endian>& /* reloc */,
|
||||
unsigned int data_shndx,
|
||||
Output_section* output_section,
|
||||
const elfcpp::Rela<size, big_endian>& rela,
|
||||
unsigned int r_type,
|
||||
const elfcpp::Sym<size, big_endian>& /* lsym */,
|
||||
bool is_discarded)
|
||||
@ -1631,33 +1850,99 @@ Target_aarch64<size, big_endian>::Scan::local(
|
||||
if (is_discarded)
|
||||
return;
|
||||
|
||||
typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian>
|
||||
Reloc_section;
|
||||
|
||||
switch (r_type)
|
||||
{
|
||||
case elfcpp::R_AARCH64_ABS64:
|
||||
case elfcpp::R_AARCH64_ABS32:
|
||||
case elfcpp::R_AARCH64_ABS16:
|
||||
// If building a shared library or pie, we need to mark this as a dynmic
|
||||
// reloction, so that the dynamic loader can relocate it.
|
||||
// Not supported yet.
|
||||
if (parameters->options().output_is_position_independent())
|
||||
{
|
||||
gold_error(_("%s: unsupported ABS64 relocation type for pie or "
|
||||
"shared library.\n"),
|
||||
object->name().c_str());
|
||||
gold_error(_("%s: unsupported reloc %u in pos independent link."),
|
||||
object->name().c_str(), r_type);
|
||||
}
|
||||
break;
|
||||
|
||||
// Relocations to generate 19, 21 and 33-bit PC-relative address
|
||||
case elfcpp::R_AARCH64_ABS64:
|
||||
// If building a shared library or pie, we need to mark this as a dynmic
|
||||
// reloction, so that the dynamic loader can relocate it.
|
||||
if (parameters->options().output_is_position_independent())
|
||||
{
|
||||
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
|
||||
unsigned int r_sym = elfcpp::elf_r_sym<64>(rela.get_r_info());
|
||||
rela_dyn->add_local_relative(object, r_sym,
|
||||
elfcpp::R_AARCH64_RELATIVE,
|
||||
output_section,
|
||||
data_shndx,
|
||||
rela.get_r_offset(),
|
||||
rela.get_r_addend(),
|
||||
false /* is ifunc */);
|
||||
}
|
||||
break;
|
||||
|
||||
case elfcpp::R_AARCH64_PREL64:
|
||||
case elfcpp::R_AARCH64_PREL32:
|
||||
case elfcpp::R_AARCH64_PREL16:
|
||||
break;
|
||||
|
||||
// Relocations to generate 19, 21 and 33-bit PC-relative address
|
||||
case elfcpp::R_AARCH64_ADR_PREL_PG_HI21: // 275
|
||||
case elfcpp::R_AARCH64_LDST8_ABS_LO12_NC: // 278
|
||||
case elfcpp::R_AARCH64_LDST16_ABS_LO12_NC: // 284
|
||||
case elfcpp::R_AARCH64_LDST32_ABS_LO12_NC: // 285
|
||||
case elfcpp::R_AARCH64_LDST64_ABS_LO12_NC: // 286
|
||||
case elfcpp::R_AARCH64_LDST128_ABS_LO12_NC: // 299
|
||||
case elfcpp::R_AARCH64_ADD_ABS_LO12_NC: // 277
|
||||
break;
|
||||
|
||||
// Control flow, pc-relative. We don't need to do anything for a relative
|
||||
// addressing relocation against a local symbol if it does not reference
|
||||
// the GOT.
|
||||
case elfcpp::R_AARCH64_CALL26: // 283
|
||||
// Control flow, pc-relative. We don't need to do anything for a relative
|
||||
// addressing relocation against a local symbol if it does not reference
|
||||
// the GOT.
|
||||
case elfcpp::R_AARCH64_TSTBR14:
|
||||
case elfcpp::R_AARCH64_CONDBR19:
|
||||
case elfcpp::R_AARCH64_JUMP26:
|
||||
case elfcpp::R_AARCH64_CALL26:
|
||||
break;
|
||||
|
||||
case elfcpp::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
|
||||
case elfcpp::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
|
||||
{
|
||||
layout->set_has_static_tls();
|
||||
// Create a GOT entry for the tp-relative offset.
|
||||
Output_data_got_aarch64<size, big_endian>* got =
|
||||
target->got_section(symtab, layout);
|
||||
unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
|
||||
if (!parameters->doing_static_link())
|
||||
{
|
||||
got->add_local_with_rel(object, r_sym, GOT_TYPE_TLS_OFFSET,
|
||||
target->rela_dyn_section(layout),
|
||||
elfcpp::R_AARCH64_TLS_TPREL64);
|
||||
}
|
||||
else if (!object->local_has_got_offset(r_sym,
|
||||
GOT_TYPE_TLS_OFFSET))
|
||||
{
|
||||
got->add_local(object, r_sym, GOT_TYPE_TLS_OFFSET);
|
||||
unsigned int got_offset =
|
||||
object->local_got_offset(r_sym, GOT_TYPE_TLS_OFFSET);
|
||||
const elfcpp::Elf_Xword addend = rela.get_r_addend();
|
||||
gold_assert(addend == 0);
|
||||
got->add_static_reloc(got_offset, elfcpp::R_AARCH64_TLS_TPREL64,
|
||||
object, r_sym);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_HI12:
|
||||
case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_LO12:
|
||||
case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
|
||||
{
|
||||
layout->set_has_static_tls();
|
||||
bool output_is_shared = parameters->options().shared();
|
||||
if (output_is_shared)
|
||||
gold_error(_("%s: unsupported TLSLEreloc %u in shard code."),
|
||||
object->name().c_str(), r_type);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1685,16 +1970,74 @@ Target_aarch64<size, big_endian>::Scan::global(
|
||||
Symbol_table* symtab,
|
||||
Layout* layout,
|
||||
Target_aarch64<size, big_endian>* target,
|
||||
Sized_relobj_file<size, big_endian>* /* object */,
|
||||
unsigned int /* data_shndx */,
|
||||
Output_section* /* output_section */,
|
||||
const elfcpp::Rela<size, big_endian>& /* reloc */,
|
||||
Sized_relobj_file<size, big_endian> * object,
|
||||
unsigned int data_shndx,
|
||||
Output_section* output_section,
|
||||
const elfcpp::Rela<size, big_endian>& rela,
|
||||
unsigned int r_type,
|
||||
Symbol* gsym)
|
||||
{
|
||||
typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian>
|
||||
Reloc_section;
|
||||
switch (r_type)
|
||||
{
|
||||
case elfcpp::R_AARCH64_ABS16:
|
||||
case elfcpp::R_AARCH64_ABS32:
|
||||
case elfcpp::R_AARCH64_ABS64:
|
||||
{
|
||||
// Make a PLT entry if necessary.
|
||||
if (gsym->needs_plt_entry())
|
||||
{
|
||||
target->make_plt_entry(symtab, layout, gsym);
|
||||
// Since this is not a PC-relative relocation, we may be
|
||||
// taking the address of a function. In that case we need to
|
||||
// set the entry in the dynamic symbol table to the address of
|
||||
// the PLT entry.
|
||||
if (gsym->is_from_dynobj() && !parameters->options().shared())
|
||||
gsym->set_needs_dynsym_value();
|
||||
}
|
||||
// Make a dynamic relocation if necessary.
|
||||
const AArch64_reloc_property* arp =
|
||||
aarch64_reloc_property_table->get_reloc_property(r_type);
|
||||
gold_assert(arp != NULL);
|
||||
if (gsym->needs_dynamic_reloc(arp->reference_flags()))
|
||||
{
|
||||
if (!parameters->options().output_is_position_independent()
|
||||
&& gsym->may_need_copy_reloc())
|
||||
{
|
||||
gold_error(
|
||||
_("%s: unsupported reloc %u which may need copyreloc."),
|
||||
object->name().c_str(), r_type);
|
||||
}
|
||||
else if (r_type == elfcpp::R_AARCH64_ABS64
|
||||
&& gsym->can_use_relative_reloc(false))
|
||||
{
|
||||
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
|
||||
rela_dyn->add_global_relative(gsym,
|
||||
elfcpp::R_AARCH64_RELATIVE,
|
||||
output_section,
|
||||
object,
|
||||
data_shndx,
|
||||
rela.get_r_offset(),
|
||||
rela.get_r_addend(),
|
||||
false);
|
||||
}
|
||||
else
|
||||
{
|
||||
check_non_pic(object, r_type);
|
||||
Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian>*
|
||||
rela_dyn = target->rela_dyn_section(layout);
|
||||
rela_dyn->add_global(
|
||||
gsym, r_type, output_section, object,
|
||||
data_shndx, rela.get_r_offset(),rela.get_r_addend());
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case elfcpp::R_AARCH64_PREL16:
|
||||
case elfcpp::R_AARCH64_PREL32:
|
||||
case elfcpp::R_AARCH64_PREL64:
|
||||
// This is used to fill the GOT absolute address.
|
||||
if (gsym->needs_plt_entry())
|
||||
{
|
||||
@ -1704,6 +2047,11 @@ Target_aarch64<size, big_endian>::Scan::global(
|
||||
|
||||
case elfcpp::R_AARCH64_ADR_PREL_PG_HI21:
|
||||
case elfcpp::R_AARCH64_ADR_PREL_PG_HI21_NC:
|
||||
case elfcpp::R_AARCH64_LDST8_ABS_LO12_NC: // 278
|
||||
case elfcpp::R_AARCH64_LDST16_ABS_LO12_NC: // 284
|
||||
case elfcpp::R_AARCH64_LDST32_ABS_LO12_NC: // 285
|
||||
case elfcpp::R_AARCH64_LDST64_ABS_LO12_NC: // 286
|
||||
case elfcpp::R_AARCH64_LDST128_ABS_LO12_NC: // 299
|
||||
case elfcpp::R_AARCH64_ADD_ABS_LO12_NC:
|
||||
{
|
||||
// Do nothing here.
|
||||
@ -1741,6 +2089,8 @@ Target_aarch64<size, big_endian>::Scan::global(
|
||||
break;
|
||||
}
|
||||
|
||||
case elfcpp::R_AARCH64_TSTBR14:
|
||||
case elfcpp::R_AARCH64_CONDBR19:
|
||||
case elfcpp::R_AARCH64_JUMP26:
|
||||
case elfcpp::R_AARCH64_CALL26:
|
||||
{
|
||||
@ -1760,10 +2110,48 @@ Target_aarch64<size, big_endian>::Scan::global(
|
||||
break;
|
||||
}
|
||||
|
||||
case elfcpp::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
|
||||
case elfcpp::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
|
||||
{
|
||||
layout->set_has_static_tls();
|
||||
// Create a GOT entry for the tp-relative offset.
|
||||
Output_data_got_aarch64<size, big_endian>* got
|
||||
= target->got_section(symtab, layout);
|
||||
if (!parameters->doing_static_link())
|
||||
{
|
||||
got->add_global_with_rel(
|
||||
gsym, GOT_TYPE_TLS_OFFSET,
|
||||
target->rela_dyn_section(layout),
|
||||
elfcpp::R_AARCH64_TLS_TPREL64);
|
||||
}
|
||||
if (!gsym->has_got_offset(GOT_TYPE_TLS_OFFSET))
|
||||
{
|
||||
got->add_global(gsym, GOT_TYPE_TLS_OFFSET);
|
||||
unsigned int got_offset =
|
||||
gsym->got_offset(GOT_TYPE_TLS_OFFSET);
|
||||
const elfcpp::Elf_Xword addend = rela.get_r_addend();
|
||||
gold_assert(addend == 0);
|
||||
got->add_static_reloc(got_offset,
|
||||
elfcpp::R_AARCH64_TLS_TPREL64, gsym);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_HI12:
|
||||
case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_LO12:
|
||||
case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
|
||||
layout->set_has_static_tls();
|
||||
if (parameters->options().shared())
|
||||
gold_error(_("%s: unsupported TLSLE reloc type %u in shared objects."),
|
||||
object->name().c_str(), r_type);
|
||||
break;
|
||||
|
||||
default:
|
||||
gold_error(_("%s: unsupported reloc type"),
|
||||
aarch64_reloc_property_table->
|
||||
reloc_name_in_error_message(r_type).c_str());
|
||||
const AArch64_reloc_property* arp =
|
||||
aarch64_reloc_property_table->get_reloc_property(r_type);
|
||||
gold_assert(arp != NULL);
|
||||
gold_error(_("%s: unsupported reloc type in global scan"),
|
||||
arp->name().c_str());
|
||||
}
|
||||
return;
|
||||
} // End of Scan::global
|
||||
@ -2056,6 +2444,24 @@ Target_aarch64<size, big_endian>::Relocate::relocate(
|
||||
}
|
||||
have_got_offset = true;
|
||||
break;
|
||||
|
||||
case elfcpp::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
|
||||
case elfcpp::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
|
||||
if (gsym != NULL)
|
||||
{
|
||||
gold_assert(gsym->has_got_offset(GOT_TYPE_TLS_OFFSET));
|
||||
got_offset = gsym->got_offset(GOT_TYPE_TLS_OFFSET) - got_base;
|
||||
}
|
||||
else
|
||||
{
|
||||
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)
|
||||
- got_base);
|
||||
}
|
||||
have_got_offset = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -2110,6 +2516,8 @@ Target_aarch64<size, big_endian>::Relocate::relocate(
|
||||
view, object, psymval, addend, reloc_property);
|
||||
break;
|
||||
|
||||
case elfcpp::R_AARCH64_TSTBR14:
|
||||
case elfcpp::R_AARCH64_CONDBR19:
|
||||
case elfcpp::R_AARCH64_CALL26:
|
||||
case elfcpp::R_AARCH64_JUMP26:
|
||||
reloc_status = Reloc::template pcrela_general<32>(
|
||||
@ -2129,6 +2537,19 @@ Target_aarch64<size, big_endian>::Relocate::relocate(
|
||||
view, value, addend, reloc_property);
|
||||
break;
|
||||
|
||||
case elfcpp::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
|
||||
case elfcpp::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
|
||||
reloc_status = relocate_tls(relinfo, target, relnum, rela, r_type,
|
||||
gsym, psymval, view, address);
|
||||
break;
|
||||
|
||||
case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_HI12:
|
||||
case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_LO12:
|
||||
case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
|
||||
reloc_status = relocate_tls(relinfo, target, relnum, rela, r_type,
|
||||
gsym, psymval, view, address);
|
||||
break;
|
||||
|
||||
default:
|
||||
gold_error_at_location(relinfo, relnum, rela.get_r_offset(),
|
||||
_("unsupported reloc aaa %u"),
|
||||
@ -2161,6 +2582,98 @@ Target_aarch64<size, big_endian>::Relocate::relocate(
|
||||
return true;
|
||||
}
|
||||
|
||||
template<int size, bool big_endian>
|
||||
inline
|
||||
typename AArch64_relocate_functions<size,big_endian>::Status
|
||||
Target_aarch64<size, big_endian>::Relocate::relocate_tls(
|
||||
const Relocate_info<size,big_endian> * relinfo,
|
||||
Target_aarch64<size, big_endian> * target,
|
||||
size_t /* relnum */,
|
||||
const elfcpp::Rela<size, big_endian> & 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)
|
||||
{
|
||||
typedef AArch64_relocate_functions<size,big_endian> aarch64_reloc_funcs;
|
||||
typedef typename elfcpp::Elf_types<size>::Elf_Addr AArch64_Addr;
|
||||
|
||||
const AArch64_reloc_property * reloc_property =
|
||||
aarch64_reloc_property_table->get_reloc_property(r_type);
|
||||
gold_assert(reloc_property != NULL);
|
||||
|
||||
Sized_relobj_file<size,big_endian> * object = relinfo->object;
|
||||
switch (r_type)
|
||||
{
|
||||
case elfcpp::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
|
||||
case elfcpp::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
|
||||
{
|
||||
// Not implemented - possible IE->LE relaxation opportunity:
|
||||
// adrp xd, :gottprel:var => movz xd, :tprel_g1:var
|
||||
typename elfcpp::Elf_types<size>::Elf_Addr got_entry_address;
|
||||
if (gsym != NULL)
|
||||
{
|
||||
gold_assert(gsym->has_got_offset(GOT_TYPE_TLS_OFFSET));
|
||||
got_entry_address = target->got_->address() +
|
||||
gsym->got_offset(GOT_TYPE_TLS_OFFSET);
|
||||
}
|
||||
else
|
||||
{
|
||||
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_entry_address = target->got_->address() +
|
||||
object->local_got_offset(r_sym, GOT_TYPE_TLS_OFFSET);
|
||||
}
|
||||
if (r_type == elfcpp::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21)
|
||||
{
|
||||
return aarch64_reloc_funcs::adrp(
|
||||
view, got_entry_address, address);
|
||||
}
|
||||
else if (r_type == elfcpp::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC)
|
||||
{
|
||||
return aarch64_reloc_funcs::template rela_general<64>(
|
||||
view, got_entry_address, 0, reloc_property);
|
||||
}
|
||||
gold_assert(false);
|
||||
}
|
||||
break;
|
||||
|
||||
case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_HI12:
|
||||
case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_LO12:
|
||||
case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
|
||||
{
|
||||
Output_segment * tls_segment = relinfo->layout->tls_segment();
|
||||
gold_assert(tls_segment != NULL);
|
||||
AArch64_Addr value = psymval->value(object, 0);
|
||||
const elfcpp::Elf_Xword addend = rela.get_r_addend();
|
||||
|
||||
if (!parameters->options().shared())
|
||||
{
|
||||
AArch64_Addr aligned_tcb_size =
|
||||
align_address(target->tcb_size(),
|
||||
tls_segment->maximum_alignment());
|
||||
return aarch64_reloc_funcs::template
|
||||
rela_general<32>(view,
|
||||
value + aligned_tcb_size,
|
||||
addend,
|
||||
reloc_property);
|
||||
}
|
||||
else
|
||||
gold_error(_("%s: unsupported reloc %u "
|
||||
"in non-static TLSLE mode."),
|
||||
object->name().c_str(), r_type);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
gold_error(_("%s: unsupported TLS reloc %u."),
|
||||
object->name().c_str(), r_type);
|
||||
}
|
||||
return aarch64_reloc_funcs::STATUS_BAD_RELOC;
|
||||
}
|
||||
|
||||
|
||||
// Relocate section data.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
@ -2213,21 +2726,37 @@ get_size_for_reloc(
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Target_aarch64<size, big_endian>::scan_relocatable_relocs(
|
||||
Symbol_table* /* symtab */,
|
||||
Layout* /* layout */,
|
||||
Sized_relobj_file<size, big_endian>* /* object */,
|
||||
unsigned int /* data_shndx */,
|
||||
Symbol_table* symtab,
|
||||
Layout* layout,
|
||||
Sized_relobj_file<size, big_endian>* 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 */)
|
||||
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)
|
||||
{
|
||||
//TODO
|
||||
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<size, big_endian, elfcpp::SHT_RELA,
|
||||
Scan_relocatable_relocs>(
|
||||
symtab,
|
||||
layout,
|
||||
object,
|
||||
data_shndx,
|
||||
prelocs,
|
||||
reloc_count,
|
||||
output_section,
|
||||
needs_special_offset_handling,
|
||||
local_symbol_count,
|
||||
plocal_symbols,
|
||||
rr);
|
||||
}
|
||||
|
||||
// Relocate a section during a relocatable link.
|
||||
@ -2235,21 +2764,33 @@ Target_aarch64<size, big_endian>::scan_relocatable_relocs(
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Target_aarch64<size, big_endian>::relocate_relocs(
|
||||
const Relocate_info<size, big_endian>* /* relinfo */,
|
||||
const Relocate_info<size, big_endian>* relinfo,
|
||||
unsigned int sh_type,
|
||||
const unsigned char* /* prelocs */,
|
||||
size_t /* reloc_count */,
|
||||
Output_section* /* output_section */,
|
||||
typename elfcpp::Elf_types<size>::Elf_Off /* offset_in_output_section */,
|
||||
const Relocatable_relocs* /* rr */,
|
||||
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 */)
|
||||
const unsigned char* prelocs,
|
||||
size_t reloc_count,
|
||||
Output_section* output_section,
|
||||
typename elfcpp::Elf_types<size>::Elf_Off offset_in_output_section,
|
||||
const Relocatable_relocs* rr,
|
||||
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)
|
||||
{
|
||||
//TODO
|
||||
gold_assert(sh_type == elfcpp::SHT_RELA);
|
||||
|
||||
gold::relocate_relocs<size, big_endian, elfcpp::SHT_RELA>(
|
||||
relinfo,
|
||||
prelocs,
|
||||
reloc_count,
|
||||
output_section,
|
||||
offset_in_output_section,
|
||||
rr,
|
||||
view,
|
||||
view_address,
|
||||
view_size,
|
||||
reloc_view,
|
||||
reloc_view_size);
|
||||
}
|
||||
|
||||
// The selector for aarch64 object files.
|
||||
|
Loading…
Reference in New Issue
Block a user