2010-02-02 Doug Kwan <dougkwan@google.com>

* Makefile.am (HFILES): Add arm-reloc-property.h.
	(DEFFILES): New.
 	(TARGETSOURCES): Add arm-reloc-property.cc
 	(ALL_TARGETOBJS): Add arm-reloc-property.$(OBJEXT)
	(libgold_a_SOURCES): $(DEFFILES)
	* Makefile.in: Regenerate.
	* arm-reloc-property.cc: New file.
	* arm-reloc-property.h: New file.
	* arm-reloc.def: New file.
	* arm.cc: Update comments.
	(arm-reloc-property.h): New included header.
	(arm_reloc_property_table): New global variable.
	(Target_arm::do_select_as_default_target): New method definition.
	* configure.tgt (armeb*-*-*,armbe*-*-*,arm*-*-*): Add
	arm-reloc-property to targ_extra_obj.
	* parameters.cc (set_parameters_target): Call
	Target::select_as_default_target().
	* target.h (Target::select_as_default_target): New method definition.
	(Target::do_select_as_default_target): Same.
This commit is contained in:
Doug Kwan 2010-02-03 05:36:55 +00:00
parent af06b00b54
commit 0d31c79dad
10 changed files with 920 additions and 28 deletions

View File

@ -1,3 +1,25 @@
2010-02-02 Doug Kwan <dougkwan@google.com>
* Makefile.am (HFILES): Add arm-reloc-property.h.
(DEFFILES): New.
(TARGETSOURCES): Add arm-reloc-property.cc
(ALL_TARGETOBJS): Add arm-reloc-property.$(OBJEXT)
(libgold_a_SOURCES): $(DEFFILES)
* Makefile.in: Regenerate.
* arm-reloc-property.cc: New file.
* arm-reloc-property.h: New file.
* arm-reloc.def: New file.
* arm.cc: Update comments.
(arm-reloc-property.h): New included header.
(arm_reloc_property_table): New global variable.
(Target_arm::do_select_as_default_target): New method definition.
* configure.tgt (armeb*-*-*,armbe*-*-*,arm*-*-*): Add
arm-reloc-property to targ_extra_obj.
* parameters.cc (set_parameters_target): Call
Target::select_as_default_target().
* target.h (Target::select_as_default_target): New method definition.
(Target::do_select_as_default_target): Same.
2010-02-01 Doug Kwan <dougkwan@google.com>
* arm.cc (Arm_exidx_fixup::Arm_exidx_fixup): Initialize

View File

@ -84,6 +84,7 @@ CCFILES = \
workqueue-threads.cc
HFILES = \
arm-reloc-property.h \
archive.h \
attributes.h \
binary.h \
@ -134,16 +135,18 @@ HFILES = \
YFILES = \
yyscript.y
DEFFILES = arm-reloc.def
EXTRA_DIST = yyscript.c yyscript.h
TARGETSOURCES = \
i386.cc x86_64.cc sparc.cc powerpc.cc arm.cc
i386.cc x86_64.cc sparc.cc powerpc.cc arm.cc arm-reloc-property.cc
ALL_TARGETOBJS = \
i386.$(OBJEXT) x86_64.$(OBJEXT) sparc.$(OBJEXT) powerpc.$(OBJEXT) \
arm.$(OBJEXT)
arm.$(OBJEXT) arm-reloc-property.$(OBJEXT)
libgold_a_SOURCES = $(CCFILES) $(HFILES) $(YFILES)
libgold_a_SOURCES = $(CCFILES) $(HFILES) $(YFILES) $(DEFFILES)
libgold_a_LIBADD = $(LIBOBJS)
sources_var = main.cc

View File

@ -92,7 +92,7 @@ am__objects_1 = archive.$(OBJEXT) attributes.$(OBJEXT) \
am__objects_2 =
am__objects_3 = yyscript.$(OBJEXT)
am_libgold_a_OBJECTS = $(am__objects_1) $(am__objects_2) \
$(am__objects_3)
$(am__objects_3) $(am__objects_2)
libgold_a_OBJECTS = $(am_libgold_a_OBJECTS)
PROGRAMS = $(noinst_PROGRAMS)
am_incremental_dump_OBJECTS = incremental-dump.$(OBJEXT)
@ -398,6 +398,7 @@ CCFILES = \
workqueue-threads.cc
HFILES = \
arm-reloc-property.h \
archive.h \
attributes.h \
binary.h \
@ -448,15 +449,16 @@ HFILES = \
YFILES = \
yyscript.y
DEFFILES = arm-reloc.def
EXTRA_DIST = yyscript.c yyscript.h
TARGETSOURCES = \
i386.cc x86_64.cc sparc.cc powerpc.cc arm.cc
i386.cc x86_64.cc sparc.cc powerpc.cc arm.cc arm-reloc-property.cc
ALL_TARGETOBJS = \
i386.$(OBJEXT) x86_64.$(OBJEXT) sparc.$(OBJEXT) powerpc.$(OBJEXT) \
arm.$(OBJEXT)
arm.$(OBJEXT) arm-reloc-property.$(OBJEXT)
libgold_a_SOURCES = $(CCFILES) $(HFILES) $(YFILES)
libgold_a_SOURCES = $(CCFILES) $(HFILES) $(YFILES) $(DEFFILES)
libgold_a_LIBADD = $(LIBOBJS)
sources_var = main.cc
deps_var = $(TARGETOBJS) libgold.a $(LIBIBERTY) $(LIBINTL_DEP)
@ -598,6 +600,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/mremap.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/pread.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/archive.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arm-reloc-property.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arm.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/attributes.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/binary.Po@am__quote@

287
gold/arm-reloc-property.cc Normal file
View File

@ -0,0 +1,287 @@
// arm-reloc-property.cc -- ARM relocation property.
// Copyright 2010 Free Software Foundation, Inc.
// Written by Doug Kwan <dougkwan@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.
#include "gold.h"
#include <cstring>
#include <stack>
#include <string>
#include <vector>
#include "elfcpp.h"
#include "arm.h"
#include "arm-reloc-property.h"
namespace gold
{
// Arm_reloc_property::Tree_node methods.
// Parse an S-expression S and build a tree and return the root node.
// Caller is responsible for releasing tree after use.
Arm_reloc_property::Tree_node*
Arm_reloc_property::Tree_node::make_tree(const std::string& s)
{
std::stack<size_t> size_stack;
Tree_node_vector node_stack;
// strtok needs a non-const string pointer.
char* buffer = new char[s.size() + 1];
memcpy(buffer, s.data(), s.size());
buffer[s.size()] = '\0';
char* token = strtok(buffer, " ");
while (token != NULL)
{
if (strcmp(token, "(") == 0)
// Remember the node stack position for start of a new internal node.
size_stack.push(node_stack.size());
else if (strcmp(token, ")") == 0)
{
// Pop all tree nodes after the previous '(' and use them as
// children to build a new internal node. Push internal node back.
size_t current_size = node_stack.size();
size_t prev_size = size_stack.top();
size_stack.pop();
Tree_node* node =
new Tree_node(node_stack.begin() + prev_size,
node_stack.begin() + current_size);
node_stack.resize(prev_size);
node_stack.push_back(node);
}
else
// Just push a leaf node to node_stack.
node_stack.push_back(new Tree_node(token));
token = strtok(NULL, " ");
}
delete[] buffer;
// At this point, size_stack should be empty and node_stack should only
// contain the root node.
gold_assert(size_stack.empty() && node_stack.size() == 1);
return node_stack[0];
}
// Arm_reloc_property methods.
// Constructor.
Arm_reloc_property::Arm_reloc_property(
unsigned int code,
const char* name,
Reloc_type rtype,
bool is_deprecated,
Reloc_class rclass,
const std::string& operation,
bool is_implemented,
int group_index,
bool checks_overflow)
: code_(code), name_(name), reloc_type_(rtype), reloc_class_(rclass),
group_index_(group_index), size_(0), align_(1),
relative_address_base_(RAB_NONE), is_deprecated_(is_deprecated),
is_implemented_(is_implemented), checks_overflow_(checks_overflow),
uses_got_entry_(false), uses_got_origin_(false), uses_plt_entry_(false),
uses_thumb_bit_(false), uses_symbol_base_(false), uses_addend_(false)
{
// Set size and alignment of static and dynamic relocations.
if (rtype == RT_STATIC)
{
switch (rclass)
{
case RC_DATA:
// Except for R_ARM_ABS16 and R_ARM_ABS8, all static data relocations
// have size 4. All static data relocations have alignment of 1.
if (code == elfcpp::R_ARM_ABS8)
this->size_ = 1;
else if (code == elfcpp::R_ARM_ABS16)
this->size_ = 2;
else
this->size_ = 4;
this->align_ = 1;
break;
case RC_MISC:
// R_ARM_V4BX should be treated as an ARM relocation. For all
// others, just use defaults.
if (code != elfcpp::R_ARM_V4BX)
break;
// Fall through.
case RC_ARM:
this->size_ = 4;
this->align_ = 4;
break;
case RC_THM16:
this->size_ = 2;
this->align_ = 2;
break;
case RC_THM32:
this->size_ = 4;
this->align_ = 2;
break;
default:
gold_unreachable();
}
}
else if (rtype == RT_DYNAMIC)
{
// With the exception of R_ARM_COPY, all dynamic relocations requires
// that the place being relocated is a word-aligned 32-bit object.
if (code != elfcpp::R_ARM_COPY)
{
this->size_ = 4;
this->align_ = 4;
}
}
// If no relocation operation is specified, we are done.
if (operation == "NONE")
return;
// Extract information from relocation operation.
Tree_node* root_node = Tree_node::make_tree(operation);
Tree_node* node = root_node;
// Check for an expression of the form XXX - YYY.
if (!node->is_leaf()
&& node->child(0)->is_leaf()
&& node->child(0)->name() == "-")
{
struct RAB_table_entry
{
Relative_address_base rab;
const char* name;
};
static const RAB_table_entry rab_table[] =
{
{ RAB_B_S, "( B S )" },
{ RAB_DELTA_B_S, "( DELTA_B ( S ) )" },
{ RAB_GOT_ORG, "GOT_ORG" },
{ RAB_P, "P" },
{ RAB_Pa, "Pa" },
{ RAB_TLS, "TLS" },
{ RAB_tp, "tp" }
};
static size_t rab_table_size = sizeof(rab_table) / sizeof(rab_table[0]);
const std::string rhs(node->child(2)->s_expression());
for (size_t i = 0; i < rab_table_size; ++i)
if (rhs == rab_table[i].name)
{
this->relative_address_base_ = rab_table[i].rab;
break;
}
gold_assert(this->relative_address_base_ != RAB_NONE);
if (this->relative_address_base_ == RAB_B_S)
this->uses_symbol_base_ = true;
node = node->child(1);
}
// Check for an expression of the form XXX | T.
if (!node->is_leaf()
&& node->child(0)->is_leaf()
&& node->child(0)->name() == "|")
{
gold_assert(node->number_of_children() == 3
&& node->child(2)->is_leaf()
&& node->child(2)->name() == "T");
this->uses_thumb_bit_ = true;
node = node->child(1);
}
// Check for an expression of the form XXX + A.
if (!node->is_leaf()
&& node->child(0)->is_leaf()
&& node->child(0)->name() == "+")
{
gold_assert(node->number_of_children() == 3
&& node->child(2)->is_leaf()
&& node->child(2)->name() == "A");
this->uses_addend_ = true;
node = node->child(1);
}
// Check for an expression of the form XXX(S).
if (!node->is_leaf() && node->child(0)->is_leaf())
{
gold_assert(node->number_of_children() == 2
&& node->child(1)->is_leaf()
&& node->child(1)->name() == "S");
const std::string func(node->child(0)->name());
if (func == "B")
this->uses_symbol_base_ = true;
else if (func == "GOT")
this->uses_got_entry_ = true;
else if (func == "PLT")
this->uses_plt_entry_ = true;
else if (func == "Module" || func == "DELTA_B")
// These are used in dynamic relocations.
;
else
gold_unreachable();
node = node->child(1);
}
gold_assert(node->is_leaf() && node->name() == "S");
delete root_node;
}
// Arm_reloc_property_table methods.
// Constructor. This processing informations in arm-reloc.def to
// initialize the table.
Arm_reloc_property_table::Arm_reloc_property_table()
{
// These appers in arm-reloc.def. Do not rename them.
Parse_expression A("A"), GOT_ORG("GOT_ORG"), NONE("NONE"), P("P"),
Pa("Pa"), S("S"), T("T"), TLS("TLS"), tp("tp");
const bool Y(true), N(false);
for (unsigned int i = 0; i < Property_table_size; ++i)
this->table_[i] = NULL;
#undef RD
#define RD(name, type, deprecated, class, operation, is_implemented, \
group_index, checks_oveflow) \
do \
{ \
unsigned int code = elfcpp::R_ARM_##name; \
gold_assert(code < Property_table_size); \
this->table_[code] = \
new Arm_reloc_property(elfcpp::R_ARM_##name, "R_ARM_" #name, \
Arm_reloc_property::RT_##type, deprecated, \
Arm_reloc_property::RC_##class, \
(operation).s_expression(), is_implemented, \
group_index, checks_oveflow); \
} \
while(0);
#include "arm-reloc.def"
#undef RD
}
} // End namespace gold.

360
gold/arm-reloc-property.h Normal file
View File

@ -0,0 +1,360 @@
// arm-reloc-property.h -- ARM relocation properties -*- C++ -*-
// Copyright 2010 Free Software Foundation, Inc.
// Written by Doug Kwan <dougkwan@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_ARM_RELOC_PROPERTY_H
#define GOLD_ARM_RELOC_PROPERTY_H
namespace gold
{
// The Arm_reloc_property class is to store information about a paticular
// relocation code.
class Arm_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.
RT_PRIVATE, // Private relocations, not supported by gold.
RT_OBSOLETE // Obsolete relocations that should not be used.
};
// Classes of relocation codes.
enum Reloc_class {
RC_NONE, // No relocation class.
RC_DATA, // Data relocation.
RC_ARM, // ARM instruction relocation.
RC_THM16, // 16-bit THUMB instruction relocation.
RC_THM32, // 32-bit THUMB instruction relocation.
RC_MISC // Miscellaneous class.
};
// Types of bases of relative addressing relocation codes.
enum Relative_address_base {
RAB_NONE, // Relocation is not relative addressing
RAB_B_S, // Address origin of output segment of defining symbol.
RAB_DELTA_B_S, // Change of address origin.
RAB_GOT_ORG, // Origin of GOT.
RAB_P, // Address of the place being relocated.
RAB_Pa, // Adjusted address (P & 0xfffffffc).
RAB_TLS, // Thread local storage.
RAB_tp // Thread pointer.
};
// 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_; }
// Whether this code is deprecated.
bool
is_deprecated() const
{ return this->is_deprecated_; }
// 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_; }
// Whether relocation checks for overflow.
bool
checks_overflow() const
{ return this->checks_overflow_; }
// Return size of relocation.
size_t
size() const
{ return this->size_; }
// Return alignment of relocation.
size_t
align() const
{ return this->align_; }
// Whether relocation use a GOT entry.
bool
uses_got_entry() const
{ return this->uses_got_entry_; }
// Whether relocation use a GOT origin.
bool
uses_got_origin() const
{ return this->uses_got_origin_; }
// Whether relocation uses the Thumb-bit in a symbol address.
bool
uses_thumb_bit() const
{ return this->uses_thumb_bit_; }
// Whether relocation uses the symbol base.
bool
uses_symbol_base() const
{ return this->uses_symbol_base_; }
// Return the type of relative address base or RAB_NONE if this
// is not a relative addressing relocation.
Relative_address_base
relative_address_base() const
{ return this->relative_address_base_; }
protected:
// These are protected. We only allow Arm_reloc_property_table to
// manage Arm_reloc_property.
Arm_reloc_property(unsigned int code, const char* name, Reloc_type rtype,
bool is_deprecated, Reloc_class rclass,
const std::string& operation, bool is_implemented,
int group_index, bool checks_overflow);
friend class Arm_reloc_property_table;
private:
// Copying is not allowed.
Arm_reloc_property(const Arm_reloc_property&);
Arm_reloc_property& operator=(const Arm_reloc_property&);
// The Tree_node class is used to represent parsed relocation operations.
// We look at Trees to extract information about relocation operations.
class Tree_node
{
public:
typedef std::vector<Tree_node*> Tree_node_vector;
// Construct a leaf node.
Tree_node(const char* name)
: is_leaf_(true), name_(name), children_()
{ }
// Construct an internal node. A node owns all its children and is
// responsible for releasing them at its own destruction.
Tree_node(Tree_node_vector::const_iterator begin,
Tree_node_vector::const_iterator end)
: is_leaf_(false), name_(), children_()
{
for (Tree_node_vector::const_iterator p = begin; p != end; ++p)
this->children_.push_back(*p);
}
~Tree_node()
{
for(size_t i = 0; i <this->children_.size(); ++i)
delete this->children_[i];
}
// Whether this is a leaf node.
bool
is_leaf() const
{ return this->is_leaf_; }
// Return name of this. This is only valid for a leaf node.
const std::string&
name() const
{
gold_assert(this->is_leaf_);
return this->name_;
}
// Return the number of children. This is only valid for a non-leaf node.
size_t
number_of_children() const
{
gold_assert(!this->is_leaf_);
return this->children_.size();
}
// Return the i-th child of this. This is only valid for a non-leaf node.
Tree_node*
child(size_t i) const
{
gold_assert(!this->is_leaf_ && i < this->children_.size());
return this->children_[i];
}
// Parse an S-expression string and build a tree and return the root node.
// Caller is responsible for releasing tree after use.
static Tree_node*
make_tree(const std::string&);
// Convert a tree back to an S-expression string.
std::string
s_expression() const
{
if (this->is_leaf_)
return this->name_;
// Concatenate S-expressions of children. Enclose them with
// a pair of parentheses and use space as token delimiters.
std::string s("(");
for(size_t i = 0; i <this->children_.size(); ++i)
s = s + " " + this->children_[i]->s_expression();
return s + " )";
}
private:
// Whether this is a leaf node.
bool is_leaf_;
// Name of this if this is a leaf node.
std::string name_;
// Children of this if this a non-leaf node.
Tree_node_vector children_;
};
// Relocation code.
unsigned int code_;
// Relocation name.
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;
// Whether this uses a GOT entry.
bool uses_got_entry_ : 1;
// Whether this uses a GOT origin.
bool uses_got_origin_ : 1;
// Whether this uses a PLT entry.
bool uses_plt_entry_ : 1;
// Whether this uses the THUMB bit in symbol address.
bool uses_thumb_bit_ : 1;
// Whether this uses the symbol base.
bool uses_symbol_base_ : 1;
// Whether this uses an addend.
bool uses_addend_ : 1;
};
// Arm_reloc_property_table. This table is used for looking up propeties
// of relocationt types. The table entries are initialized using information
// from arm-reloc.def.
class Arm_reloc_property_table
{
public:
Arm_reloc_property_table();
// Return an Arm_reloc_property object for CODE if it is a valid relocation
// code or NULL otherwise.
const Arm_reloc_property*
get_reloc_property(unsigned int code) const
{
gold_assert(code < Property_table_size);
return this->table_[code];
}
private:
// Copying is not allowed.
Arm_reloc_property_table(const Arm_reloc_property_table&);
Arm_reloc_property_table& operator=(const Arm_reloc_property_table&);
// The Parse_expression class is used to convert relocation operations in
// arm-reloc.def into S-expression strings, which are parsed again to
// build actual expression trees. We do not build the expression trees
// directly because the parser for operations in arm-reloc.def is simpler
// this way. Coversion from S-expressions to trees is simple.
class Parse_expression
{
public:
// Construction a Parse_expression with an S-expression string.
Parse_expression(const std::string& s_expression)
: s_expression_(s_expression)
{ }
// Value of this expression as an S-expression string.
const std::string&
s_expression() const
{ return this->s_expression_; }
// We want to overload operators used in relocation operations so
// that we can execute operations in arm-reloc.def to generate
// S-expressions directly.
#define DEF_OPERATOR_OVERLOAD(op) \
Parse_expression \
operator op (const Parse_expression& e) \
{ \
return Parse_expression("( " #op " " + this->s_expression_ + " " + \
e.s_expression_ + " )"); \
}
// Operator appearing in relocation operations in arm-reloc.def.
DEF_OPERATOR_OVERLOAD(+)
DEF_OPERATOR_OVERLOAD(-)
DEF_OPERATOR_OVERLOAD(|)
private:
// This represented as an S-expression string.
std::string s_expression_;
};
#define DEF_RELOC_FUNC(name) \
static Parse_expression \
(name)(const Parse_expression& arg) \
{ return Parse_expression("( " #name " " + arg.s_expression() + " )"); }
// Functions appearing in relocation operations in arm-reloc.def.
DEF_RELOC_FUNC(B)
DEF_RELOC_FUNC(DELTA_B)
DEF_RELOC_FUNC(GOT)
DEF_RELOC_FUNC(Module)
DEF_RELOC_FUNC(PLT)
static const unsigned int Property_table_size = 256;
// The property table.
Arm_reloc_property* table_[Property_table_size];
};
} // End namespace gold.
#endif // !defined(GOLD_ARM_RELOC_PROPERTY_H)

194
gold/arm-reloc.def Normal file
View File

@ -0,0 +1,194 @@
// arm-reloc.def -- ARM relocation definitions.
// Copyright 2010 Free Software Foundation, Inc.
// Written by Doug Kwan <dougkwan@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.
// The information here is based on the official ARM document "ELF for ARM
// Architecture" (Document number ARM IHI 0044C). The first five columns of
// the table below are derived from Table 4-8 in the ARM ELF document. Each
// relocation from Table 4-8 corresponds to one relocation definition in the
// table below. A relocation defintion has the following information:
//
// Name: This is the name of the relocation without the "R_ARM_" prefix.
//
// Type: Relocation type. There are four.
// - STATIC for static relocations processed by a static linker.
// - DYNAMIC for dynamic relocations processed by a dynamic linker.
// - PRIVATE for R_ARM_PRIVATE_<n> private relocation type.
// - OBSOLETE for old relocation types no longer used.
// We do not use DEPRECATED as a distinct type since we still have to
// handle deprecated relocations so we one of the types above.
//
// Deprecated: Whether this is a deprecated relocation type. The linker
// is expected to handle these though they should not be generated by fully
// conforming tool-chains.
//
// Operation: An expression specifying how the linker should performace a
// relocation. If there is no operation or the operation cannot be
// specified, it is "NONE".
//
// Implemented: Whether this is implemented by the gold.
//
// Group_index: For a group relocation type, it is one of 0, 1 or 2. For
// a non-group relocation type, it is -1.
//
// Overflow: Whether gold should check for overflow. This is "No" by default
// for relocation types DYNAMIC, PRIVATE and OBSOLETE.
//
// Overflow-----------------------------------------------------------------+
// Group index----------------------------------------------------------+ |
// Implemented-------------------------------------------------------+ | |
// Operation-------------------------------+ | | |
// Class----------------------------+ | | | |
// Deprecated--------------------+ | | | | |
// Type----------------+ | | | | | |
// Name | | | | | | |
// | | | | | | | |
RD(NONE , STATIC , N, MISC , NONE , Y, -1, N)
RD(PC24 , STATIC , Y, ARM , ((S + A) | T) - P , Y, -1, Y)
RD(ABS32 , STATIC , N, DATA , (S + A) | T , Y, -1, N)
RD(REL32 , STATIC , N, DATA , ((S + A) | T) - P , Y, -1, N)
RD(LDR_PC_G0 , STATIC , N, ARM , S + A - P , Y, 0, Y)
RD(ABS16 , STATIC , N, DATA , S + A , Y, -1, Y)
RD(ABS12 , STATIC , N, ARM , S + A , Y, -1, Y)
RD(THM_ABS5 , STATIC , N, THM16, S + A , Y, -1, Y)
RD(ABS8 , STATIC , N, DATA , S + A , Y, -1, Y)
RD(SBREL32 , STATIC , N, DATA , ((S + A) | T) - B(S) , N, -1, N)
RD(THM_CALL , STATIC , N, THM32, ((S + A) | T) - P , Y, -1, Y)
RD(THM_PC8 , STATIC , N, THM16, S + A - Pa , Y, -1, Y)
RD(BREL_ADJ , DYNAMIC , N, DATA , DELTA_B(S) + A , Y, -1, N)
RD(TLS_DESC , DYNAMIC , N, DATA , NONE , Y, -1, N)
RD(THM_SWI8 , OBSOLETE, N, NONE , NONE , N, -1, N)
RD(XPC25 , OBSOLETE, N, NONE , NONE , N, -1, N)
RD(THM_XPC22 , OBSOLETE, N, NONE , NONE , N, -1, N)
RD(TLS_DTPMOD32 , DYNAMIC , N, DATA , Module(S) , Y, -1, N)
RD(TLS_DTPOFF32 , DYNAMIC , N, DATA , S + A - TLS , Y, -1, N)
RD(TLS_TPOFF32 , DYNAMIC , N, DATA , S + A - tp , Y, -1, N)
RD(COPY , DYNAMIC , N, MISC , NONE , Y, -1, N)
RD(GLOB_DAT , DYNAMIC , N, DATA , (S + A) | T , Y, -1, N)
RD(JUMP_SLOT , DYNAMIC , N, DATA , (S + A) | T , Y, -1, N)
RD(RELATIVE , DYNAMIC , N, DATA , B(S) + A , Y, -1, N)
RD(GOTOFF32 , STATIC , N, DATA , ((S + A) | T) - GOT_ORG, Y, -1, N)
RD(BASE_PREL , STATIC , N, DATA , B(S) + A - P , Y, -1, N)
RD(GOT_BREL , STATIC , N, DATA , GOT(S) + A - GOT_ORG , Y, -1, N)
RD(PLT32 , STATIC , Y, ARM , ((S + A) | T) - P , Y, -1, Y)
RD(CALL , STATIC , N, ARM , ((S + A) | T) - P , Y, -1, Y)
RD(JUMP24 , STATIC , N, ARM , ((S + A) | T) - P , Y, -1, Y)
RD(THM_JUMP24 , STATIC , N, THM32, ((S + A) | T) - P , Y, -1, Y)
RD(BASE_ABS , STATIC , N, DATA , B(S) + A , Y, -1, N)
RD(ALU_PCREL_7_0 , OBSOLETE, N, NONE , NONE , N, -1, N)
RD(ALU_PCREL_15_8 , OBSOLETE, N, NONE , NONE , N, -1, N)
RD(ALU_PCREL_23_15 , OBSOLETE, N, NONE , NONE , N, -1, N)
RD(LDR_SBREL_11_0_NC , STATIC , Y, ARM , S + A - B(S) , N, -1, N)
RD(ALU_SBREL_19_12_NC, STATIC , Y, ARM , S + A - B(S) , N, -1, N)
RD(ALU_SBREL_27_20_CK, STATIC , Y, ARM , S + A - B(S) , N, -1, Y)
RD(TARGET1 , STATIC , N, MISC , NONE , Y, -1, N)
RD(SBREL31 , STATIC , Y, DATA , ((S + A) | T) - B(S) , N, -1, N)
RD(V4BX , STATIC , N, MISC , NONE , Y, -1, N)
RD(TARGET2 , STATIC , N, MISC , NONE , Y, -1, N)
RD(PREL31 , STATIC , N, DATA , ((S + A) | T) - P , Y, -1, Y)
RD(MOVW_ABS_NC , STATIC , N, ARM , (S + A) | T , Y, -1, N)
RD(MOVT_ABS , STATIC , N, ARM , S + A , Y, -1, Y)
RD(MOVW_PREL_NC , STATIC , N, ARM , ((S + A) | T) - P , Y, -1, N)
RD(MOVT_PREL , STATIC , N, ARM , (S + A) - P , Y, -1, Y)
RD(THM_MOVW_ABS_NC , STATIC , N, THM32, (S + A) | T , Y, -1, N)
RD(THM_MOVT_ABS , STATIC , N, THM32, S + A , Y, -1, Y)
RD(THM_MOVW_PREL_NC , STATIC , N, THM32, ((S + A) | T) - P , Y, -1, N)
RD(THM_MOVT_PREL , STATIC , N, THM32, S + A - P , Y, -1, Y)
RD(THM_JUMP19 , STATIC , N, THM32, ((S + A) | T) - P , Y, -1, Y)
RD(THM_JUMP6 , STATIC , N, THM16, S + A - P , Y, -1, Y)
RD(THM_ALU_PREL_11_0 , STATIC , N, THM32, ((S + A) | T) - Pa , Y, -1, Y)
RD(THM_PC12 , STATIC , N, THM32, S + A - Pa , Y, -1, Y)
RD(ABS32_NOI , STATIC , N, DATA , S + A , Y, -1, N)
RD(REL32_NOI , STATIC , N, DATA , S + A - P , N, -1, N)
RD(ALU_PC_G0_NC , STATIC , N, ARM , ((S + A) | T) - P , Y, 0, N)
RD(ALU_PC_G0 , STATIC , N, ARM , ((S + A) | T) - P , Y, 0, Y)
RD(ALU_PC_G1_NC , STATIC , N, ARM , ((S + A) | T) - P , Y, 1, N)
RD(ALU_PC_G1 , STATIC , N, ARM , ((S + A) | T) - P , Y, 1, Y)
RD(ALU_PC_G2 , STATIC , N, ARM , ((S + A) | T) - P , Y, 2, Y)
RD(LDR_PC_G1 , STATIC , N, ARM , S + A - P , Y, 1, Y)
RD(LDR_PC_G2 , STATIC , N, ARM , S + A - P , Y, 2, Y)
RD(LDRS_PC_G0 , STATIC , N, ARM , S + A - P , Y, 0, Y)
RD(LDRS_PC_G1 , STATIC , N, ARM , S + A - P , Y, 1, Y)
RD(LDRS_PC_G2 , STATIC , N, ARM , S + A - P , Y, 2, Y)
RD(LDC_PC_G0 , STATIC , N, ARM , S + A - P , Y, 0, Y)
RD(LDC_PC_G1 , STATIC , N, ARM , S + A - P , Y, 1, Y)
RD(LDC_PC_G2 , STATIC , N, ARM , S + A - P , Y, 2, Y)
RD(ALU_SB_G0_NC , STATIC , N, ARM , ((S + A) | T) - B(S) , Y, 0, N)
RD(ALU_SB_G0 , STATIC , N, ARM , ((S + A) | T) - B(S) , Y, 0, Y)
RD(ALU_SB_G1_NC , STATIC , N, ARM , ((S + A) | T) - B(S) , Y, 1, N)
RD(ALU_SB_G1 , STATIC , N, ARM , ((S + A) | T) - B(S) , Y, 1, Y)
RD(ALU_SB_G2 , STATIC , N, ARM , ((S + A) | T) - B(S) , Y, 2, Y)
RD(LDR_SB_G0 , STATIC , N, ARM , S + A - B(S) , Y, 0, Y)
RD(LDR_SB_G1 , STATIC , N, ARM , S + A - B(S) , Y, 1, Y)
RD(LDR_SB_G2 , STATIC , N, ARM , S + A - B(S) , Y, 2, Y)
RD(LDRS_SB_G0 , STATIC , N, ARM , S + A - B(S) , Y, 0, Y)
RD(LDRS_SB_G1 , STATIC , N, ARM , S + A - B(S) , Y, 1, Y)
RD(LDRS_SB_G2 , STATIC , N, ARM , S + A - B(S) , Y, 2, Y)
RD(LDC_SB_G0 , STATIC , N, ARM , S + A - B(S) , Y, 0, Y)
RD(LDC_SB_G1 , STATIC , N, ARM , S + A - B(S) , Y, 1, Y)
RD(LDC_SB_G2 , STATIC , N, ARM , S + A - B(S) , Y, 2, Y)
RD(MOVW_BREL_NC , STATIC , N, ARM , ((S + A) | T) - B(S) , Y, -1, N)
RD(MOVT_BREL , STATIC , N, ARM , S + A - B(S) , Y, -1, Y)
RD(MOVW_BREL , STATIC , N, ARM , ((S + A) | T) - B(S) , Y, -1, Y)
RD(THM_MOVW_BREL_NC , STATIC , N, THM32, ((S + A) | T) - B(S) , Y, -1, N)
RD(THM_MOVT_BREL , STATIC , N, THM32, S + A - B(S) , Y, -1, Y)
RD(THM_MOVW_BREL , STATIC , N, THM32, ((S + A) | T) - B(S) , Y, -1, Y)
RD(TLS_GOTDESC , STATIC , N, DATA , NONE , Y, -1, N)
RD(TLS_CALL , STATIC , N, ARM , NONE , N, -1, Y)
RD(TLS_DESCSEQ , STATIC , N, ARM , NONE , N, -1, Y)
RD(THM_TLS_CALL , STATIC , N, THM32, NONE , N, -1, Y)
RD(PLT32_ABS , STATIC , N, DATA , PLT(S) + A , N, -1, N)
RD(GOT_ABS , STATIC , N, DATA , GOT(S) + A , N, -1, N)
RD(GOT_PREL , STATIC , N, DATA , GOT(S) + A - P , N, -1, N)
RD(GOT_BREL12 , STATIC , N, ARM , GOT(S) + A - GOT_ORG , N, -1, Y)
RD(GOTOFF12 , STATIC , N, ARM , S + A - GOT_ORG , N, -1, Y)
RD(GOTRELAX , STATIC , N, MISC , NONE , N, -1, N)
RD(GNU_VTENTRY , STATIC , Y, DATA , NONE , Y, -1, N)
RD(GNU_VTINHERIT , STATIC , Y, DATA , NONE , Y, -1, N)
RD(THM_JUMP11 , STATIC , N, THM16, S + A - P , Y, -1, Y)
RD(THM_JUMP8 , STATIC , N, THM16, S + A - P , Y, -1, Y)
RD(TLS_GD32 , STATIC , N, DATA , GOT(S) + A - P , N, -1, N)
RD(TLS_LDM32 , STATIC , N, DATA , GOT(S) + A - P , N, -1, N)
RD(TLS_LDO32 , STATIC , N, DATA , S + A - TLS , N, -1, N)
RD(TLS_IE32 , STATIC , N, DATA , GOT(S) + A - P , N, -1, N)
RD(TLS_LE32 , STATIC , N, DATA , S + A - tp , N, -1, N)
RD(TLS_LDO12 , STATIC , N, ARM , S + A - TLS , N, -1, Y)
RD(TLS_LE12 , STATIC , N, ARM , S + A - tp , N, -1, Y)
RD(TLS_IE12GP , STATIC , N, ARM , GOT(S) + A - GOT_ORG , N, -1, Y)
RD(PRIVATE_0 , PRIVATE , N, NONE , NONE , N, -1, N)
RD(PRIVATE_1 , PRIVATE , N, NONE , NONE , N, -1, N)
RD(PRIVATE_2 , PRIVATE , N, NONE , NONE , N, -1, N)
RD(PRIVATE_3 , PRIVATE , N, NONE , NONE , N, -1, N)
RD(PRIVATE_4 , PRIVATE , N, NONE , NONE , N, -1, N)
RD(PRIVATE_5 , PRIVATE , N, NONE , NONE , N, -1, N)
RD(PRIVATE_6 , PRIVATE , N, NONE , NONE , N, -1, N)
RD(PRIVATE_7 , PRIVATE , N, NONE , NONE , N, -1, N)
RD(PRIVATE_8 , PRIVATE , N, NONE , NONE , N, -1, N)
RD(PRIVATE_9 , PRIVATE , N, NONE , NONE , N, -1, N)
RD(PRIVATE_10 , PRIVATE , N, NONE , NONE , N, -1, N)
RD(PRIVATE_11 , PRIVATE , N, NONE , NONE , N, -1, N)
RD(PRIVATE_12 , PRIVATE , N, NONE , NONE , N, -1, N)
RD(PRIVATE_13 , PRIVATE , N, NONE , NONE , N, -1, N)
RD(PRIVATE_14 , PRIVATE , N, NONE , NONE , N, -1, N)
RD(PRIVATE_15 , PRIVATE , N, NONE , NONE , N, -1, N)
RD(ME_TOO , OBSOLETE, N, NONE , NONE , N, -1, N)
RD(THM_TLS_DESCSEQ16 , STATIC , N, THM16, NONE , N, -1, Y)
RD(THM_TLS_DESCSEQ32 , STATIC , N, THM32, NONE , N, -1, Y)

View File

@ -50,6 +50,7 @@
#include "defstd.h"
#include "gc.h"
#include "attributes.h"
#include "arm-reloc-property.h"
namespace
{
@ -99,30 +100,25 @@ const int32_t THM2_MAX_BWD_BRANCH_OFFSET = (-(1 << 24) + 4);
// supporting Android only for the time being.
//
// TODOs:
// - Support the following relocation types as needed:
// R_ARM_SBREL32
// R_ARM_LDR_SBREL_11_0_NC
// R_ARM_ALU_SBREL_19_12_NC
// R_ARM_ALU_SBREL_27_20_CK
// R_ARM_SBREL31
// R_ARM_REL32_NOI
// R_ARM_PLT32_ABS
// R_ARM_GOT_ABS
// R_ARM_GOT_BREL12
// R_ARM_GOTOFF12
// R_ARM_TLS_GD32
// R_ARM_TLS_LDM32
// R_ARM_TLS_LDO32
// R_ARM_TLS_IE32
// R_ARM_TLS_LE32
// R_ARM_TLS_LDO12
// R_ARM_TLS_LE12
// R_ARM_TLS_IE12GP
//
// - Implement all static relocation types documented in arm-reloc.def.
// - Make PLTs more flexible for different architecture features like
// Thumb-2 and BE8.
// There are probably a lot more.
// Ideally we would like to avoid using global variables but this is used
// very in many places and sometimes in loops. If we use a function
// returning a static instance of Arm_reloc_property_table, it will very
// slow in an threaded environment since the static instance needs to be
// locked. The pointer is below initialized in the
// Target::do_select_as_default_target() hook so that we do not spend time
// building the table if we are not linking ARM objects.
//
// An alternative is to to process the information in arm-reloc.def in
// compilation time and generate a representation of it in PODs only. That
// way we can avoid initialization when the linker starts.
Arm_reloc_property_table *arm_reloc_property_table = NULL;
// Instruction template class. This class is similar to the insn_sequence
// struct in bfd/elf32-arm.c.
@ -2133,6 +2129,17 @@ class Target_arm : public Sized_target<32, big_endian>
int
do_attributes_order(int num) const;
// This is called when the target is selected as the default.
void
do_select_as_default_target()
{
// No locking is required since there should only be one default target.
// We cannot have both the big-endian and little-endian ARM targets
// as the default.
gold_assert(arm_reloc_property_table == NULL);
arm_reloc_property_table = new Arm_reloc_property_table();
}
private:
// The class which scans relocations.
class Scan

View File

@ -106,6 +106,7 @@ powerpc64-*)
;;
armeb*-*-*|armbe*-*-*)
targ_obj=arm
targ_extra_obj=arm-reloc-property
targ_machine=EM_ARM
targ_size=32
targ_big_endian=true
@ -113,6 +114,7 @@ armeb*-*-*|armbe*-*-*)
;;
arm*-*-*)
targ_obj=arm
targ_extra_obj=arm-reloc-property
targ_machine=EM_ARM
targ_size=32
targ_big_endian=false

View File

@ -141,7 +141,10 @@ set_parameters_options(const General_options* options)
void
set_parameters_target(Target* target)
{ static_parameters.set_target(target); }
{
static_parameters.set_target(target);
target->select_as_default_target();
}
void
set_parameters_doing_static_link(bool doing_static_link)

View File

@ -325,6 +325,12 @@ class Target
attributes_order(int num) const
{ return this->do_attributes_order(num); }
// When a target is selected as the default target, we call this method,
// which may be used for expensive, target-specific initialization.
void
select_as_default_target()
{ this->do_select_as_default_target(); }
protected:
// This struct holds the constant information for a child class. We
// use a struct to avoid the overhead of virtual function calls for
@ -510,6 +516,11 @@ class Target
do_attributes_order(int num) const
{ return num; }
// This may be overridden by the child class.
virtual void
do_select_as_default_target()
{ }
private:
// The implementations of the four do_make_elf_object virtual functions are
// almost identical except for their sizes and endianity. We use a template.