246 lines
7 KiB
C
246 lines
7 KiB
C
|
// aarch64-reloc-property.h -- AArch64 relocation properties -*- C++ -*-
|
||
|
|
||
|
// Copyright (C) 2014-2022 Free Software Foundation, Inc.
|
||
|
// Written by Han Shen <shenhan@google.com> and Jing Yu <jingyu@google.com>.
|
||
|
|
||
|
// This file is part of gold.
|
||
|
|
||
|
// This program is free software; you can redistribute it and/or modify
|
||
|
// it under the terms of the GNU General Public License as published by
|
||
|
// the Free Software Foundation; either version 3 of the License, or
|
||
|
// (at your option) any later version.
|
||
|
|
||
|
// This program is distributed in the hope that it will be useful,
|
||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
// GNU General Public License for more details.
|
||
|
|
||
|
// You should have received a copy of the GNU General Public License
|
||
|
// along with this program; if not, write to the Free Software
|
||
|
// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
|
||
|
// MA 02110-1301, USA.
|
||
|
|
||
|
#ifndef GOLD_AARCH64_RELOC_PROPERTY_H
|
||
|
#define GOLD_AARCH64_RELOC_PROPERTY_H
|
||
|
|
||
|
#include<vector>
|
||
|
#include<string>
|
||
|
|
||
|
#include"aarch64.h"
|
||
|
|
||
|
namespace gold
|
||
|
{
|
||
|
// The AArch64_reloc_property class is to store information about a particular
|
||
|
// relocation code.
|
||
|
|
||
|
class AArch64_reloc_property
|
||
|
{
|
||
|
public:
|
||
|
// Types of relocation codes.
|
||
|
enum Reloc_type {
|
||
|
RT_NONE, // No relocation type.
|
||
|
RT_STATIC, // Relocations processed by static linkers.
|
||
|
RT_DYNAMIC, // Relocations processed by dynamic linkers.
|
||
|
};
|
||
|
|
||
|
// Classes of relocation codes.
|
||
|
enum Reloc_class {
|
||
|
RC_NONE, // No relocation class.
|
||
|
RC_DATA, // Data relocation.
|
||
|
RC_AARCH64, // Static AArch64 relocations
|
||
|
RC_CFLOW, // Control flow
|
||
|
RC_TLS, // Thread local storage
|
||
|
RC_DYNAMIC, // Dynamic relocation
|
||
|
};
|
||
|
|
||
|
// Instructions that are associated with relocations.
|
||
|
enum Reloc_inst {
|
||
|
INST_DATA = 0,
|
||
|
INST_MOVW = 1, // movz, movk, movn
|
||
|
INST_LD = 2, // ld literal
|
||
|
INST_ADR = 3, // adr
|
||
|
INST_ADRP = 4, // adrp
|
||
|
INST_ADD = 5, // add
|
||
|
INST_LDST = 6, // ld/st
|
||
|
INST_TBZNZ = 7, // tbz/tbnz
|
||
|
INST_CONDB = 8, // B.cond
|
||
|
INST_B = 9, // b [25:0]
|
||
|
INST_CALL = 10, // bl [25:0]
|
||
|
INST_NUM = 11, // total number of entries in the table
|
||
|
};
|
||
|
|
||
|
// Types of bases of relative addressing relocation codes.
|
||
|
// enum Relative_address_base {
|
||
|
// RAB_NONE, // Relocation is not relative addressing
|
||
|
// };
|
||
|
|
||
|
typedef bool (*rvalue_checkup_func_p)(int64_t);
|
||
|
typedef uint64_t (*rvalue_bit_select_func)(uint64_t);
|
||
|
|
||
|
// Relocation code represented by this.
|
||
|
unsigned int
|
||
|
code() const
|
||
|
{ return this->code_; }
|
||
|
|
||
|
// Name of the relocation code.
|
||
|
const std::string&
|
||
|
name() const
|
||
|
{ return this->name_; }
|
||
|
|
||
|
// Type of relocation code.
|
||
|
Reloc_type
|
||
|
reloc_type() const
|
||
|
{ return this->reloc_type_; }
|
||
|
|
||
|
// Class of relocation code.
|
||
|
Reloc_class
|
||
|
reloc_class() const
|
||
|
{ return this->reloc_class_; }
|
||
|
|
||
|
// Whether this code is implemented in gold.
|
||
|
bool
|
||
|
is_implemented() const
|
||
|
{ return this->is_implemented_; }
|
||
|
|
||
|
// If code is a group relocation code, return the group number, otherwise -1.
|
||
|
int
|
||
|
group_index() const
|
||
|
{ return this->group_index_; }
|
||
|
|
||
|
// Return alignment of relocation.
|
||
|
size_t
|
||
|
align() const
|
||
|
{ return this->align_; }
|
||
|
|
||
|
int
|
||
|
reference_flags() const
|
||
|
{ return this->reference_flags_; }
|
||
|
|
||
|
// Instruction associated with this relocation.
|
||
|
Reloc_inst
|
||
|
reloc_inst() const
|
||
|
{ return this->reloc_inst_; }
|
||
|
|
||
|
// Check overflow of x
|
||
|
bool checkup_x_value(int64_t x) const
|
||
|
{ return this->rvalue_checkup_func_(x); }
|
||
|
|
||
|
// Return portions of x as is defined in aarch64-reloc.def.
|
||
|
uint64_t select_x_value(uint64_t x) const
|
||
|
{ return this->rvalue_bit_select_func_(x); }
|
||
|
|
||
|
protected:
|
||
|
// These are protected. We only allow AArch64_reloc_property_table to
|
||
|
// manage AArch64_reloc_property.
|
||
|
AArch64_reloc_property(unsigned int code, const char* name, Reloc_type rtype,
|
||
|
Reloc_class rclass,
|
||
|
bool is_implemented,
|
||
|
int group_index,
|
||
|
int reference_flags,
|
||
|
Reloc_inst reloc_inst,
|
||
|
rvalue_checkup_func_p rvalue_checkup_func,
|
||
|
rvalue_bit_select_func rvalue_bit_select);
|
||
|
|
||
|
friend class AArch64_reloc_property_table;
|
||
|
|
||
|
private:
|
||
|
// Copying is not allowed.
|
||
|
AArch64_reloc_property(const AArch64_reloc_property&);
|
||
|
AArch64_reloc_property& operator=(const AArch64_reloc_property&);
|
||
|
|
||
|
// Relocation code.
|
||
|
const unsigned int code_;
|
||
|
// Relocation name.
|
||
|
const std::string name_;
|
||
|
// Type of relocation.
|
||
|
Reloc_type reloc_type_;
|
||
|
// Class of relocation.
|
||
|
Reloc_class reloc_class_;
|
||
|
// Group index (0, 1, or 2) if this is a group relocation or -1 otherwise.
|
||
|
int group_index_;
|
||
|
// Size of relocation.
|
||
|
size_t size_;
|
||
|
// Alignment of relocation.
|
||
|
size_t align_;
|
||
|
// Relative address base.
|
||
|
// Relative_address_base relative_address_base_;
|
||
|
// Whether this is deprecated.
|
||
|
bool is_deprecated_ : 1;
|
||
|
// Whether this is implemented in gold.
|
||
|
bool is_implemented_ : 1;
|
||
|
// Whether this checks overflow.
|
||
|
bool checks_overflow_ : 1;
|
||
|
const int reference_flags_;
|
||
|
// Instruction associated with relocation.
|
||
|
Reloc_inst reloc_inst_;
|
||
|
rvalue_checkup_func_p rvalue_checkup_func_;
|
||
|
rvalue_bit_select_func rvalue_bit_select_func_;
|
||
|
};
|
||
|
|
||
|
class AArch64_reloc_property_table
|
||
|
{
|
||
|
public:
|
||
|
AArch64_reloc_property_table();
|
||
|
|
||
|
const AArch64_reloc_property*
|
||
|
get_reloc_property(unsigned int code) const
|
||
|
{
|
||
|
unsigned int idx = code_to_array_index(code);
|
||
|
return this->table_[idx];
|
||
|
}
|
||
|
|
||
|
// Like get_reloc_property but only return non-NULL if relocation code is
|
||
|
// static and implemented.
|
||
|
const AArch64_reloc_property*
|
||
|
get_implemented_static_reloc_property(unsigned int code) const
|
||
|
{
|
||
|
unsigned int idx = code_to_array_index(code);
|
||
|
const AArch64_reloc_property* arp = this->table_[idx];
|
||
|
return ((arp != NULL
|
||
|
&& (arp->reloc_type() == AArch64_reloc_property::RT_STATIC)
|
||
|
&& arp->is_implemented())
|
||
|
? arp
|
||
|
: NULL);
|
||
|
}
|
||
|
|
||
|
// Return a string describing the relocation code that is not
|
||
|
// an implemented static reloc code.
|
||
|
std::string
|
||
|
reloc_name_in_error_message(unsigned int code);
|
||
|
|
||
|
private:
|
||
|
// Copying is not allowed.
|
||
|
AArch64_reloc_property_table(const AArch64_reloc_property_table&);
|
||
|
AArch64_reloc_property_table& operator=(const AArch64_reloc_property_table&);
|
||
|
|
||
|
// Map aarch64 rtypes into range(0,300) as following
|
||
|
// 256 ~ 313 -> 0 ~ 57
|
||
|
// 512 ~ 573 -> 128 ~ 189
|
||
|
int
|
||
|
code_to_array_index(unsigned int code) const
|
||
|
{
|
||
|
if (code == 0) return 0;
|
||
|
if (!((code >= elfcpp::R_AARCH64_ABS64 &&
|
||
|
code <= elfcpp::R_AARCH64_LD64_GOTPAGE_LO15)
|
||
|
|| (code >= elfcpp::R_AARCH64_TLSGD_ADR_PREL21 &&
|
||
|
code <= elfcpp::R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC)))
|
||
|
{
|
||
|
gold_error(_("Invalid/unrecognized reloc reloc %d."), code);
|
||
|
}
|
||
|
unsigned int rv = -1;
|
||
|
if (code & (1 << 9))
|
||
|
rv = 128 + code - 512; // 512 - 573
|
||
|
else if (code & (1 << 8))
|
||
|
rv = code - 256; // 256 - 313
|
||
|
gold_assert(rv <= Property_table_size);
|
||
|
return rv;
|
||
|
}
|
||
|
|
||
|
static const unsigned int Property_table_size = 300;
|
||
|
AArch64_reloc_property* table_[Property_table_size];
|
||
|
}; // End of class AArch64_reloc_property_table
|
||
|
|
||
|
} // End namespace gold.
|
||
|
|
||
|
#endif // !defined(GOLD_AARCH64_RELOC_PROPERTY_H)
|