mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-02-17 13:10:12 +08:00
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:
parent
af06b00b54
commit
0d31c79dad
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
287
gold/arm-reloc-property.cc
Normal 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
360
gold/arm-reloc-property.h
Normal 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
194
gold/arm-reloc.def
Normal 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)
|
47
gold/arm.cc
47
gold/arm.cc
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user