[PATCH][GOLD] Add ARM relocation property table.

Doug Kwan (關振德) dougkwan@google.com
Wed Feb 3 02:47:00 GMT 2010


Here is an updated patch.

-Doug

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/2/2 Doug Kwan (關振德) <dougkwan@google.com>:
> 2010/2/2 Ian Lance Taylor <iant@google.com>:
>
>
>> I don't like the fact that we will pay in linker startup time for
>> every linker which includes the ARM target, even if we are not
>> linking ARM.  This is problematic because by default the linker
>> includes support for all targets.  Can we arrange for this to only be
>> constructed when the ARM target is being used?
>
> We can initialize this went we set the default target.  That should be
> MT-safe, right?
>
>
>> Do we ever actually destroy a Tree_node structure?  If not, there is
>> no reason to have a destructor.
>
> We do.  trees are temporary.  We can keep them in the
> Arm_reloc_property object but currently we have no further use.  So I
> delete a tree at the end of Arm_reloc_property's constructor.
>
>> If you keep this, s/for(/for (/ and s/<this/< this/
>>
>>
>>> +  ~Arm_reloc_property_table()
>>> +  {
>>> +    for (size_t code = 0; code < Property_table_size; ++code)
>>> +      delete this->table_[code];
>>> +  }
>>
>> Do we ever actually destroy an Arm_reloc_property_table?
>>
>
> No.  We can remove it.
>
>> This is a cute idea.  Can you think of a way to make it a bit more
>> general so that it is easier for other targets to use it?
>
> We can have a general way for all target but this is done in way so
> that a part of arm-reloc.def is almost identical to a relocation code
> table in the ARM ELF file format document.  That is intentional, I
> want it to be very easy to verify manually that the information in
> arm-reloc.def is correct.   Maybe we can use S-expression as the
> common description language but there will still be quite a bit of
> target-specific code in the analysis.  I'm open to suggestions.
>
>> You need to arrange to add arm-reloc-property.$(OBJEXT) to targetobjs
>> in gold/configure.ac when using --enable-target=arm.  Look at how we
>> set ${targ_obj}.\$(OBJEXT), where targ_obj is set in configure.tgt.
>
> ok.  Will send an updated patch.
>
> The reason I want to do this is to make some parts of the ARM backend
> more data driven.   I remove code from arm.cc by adding more code
> elsewhere :)
>
> -Doug
>
-------------- next part --------------
? gold/autom4te.cache
Index: gold/Makefile.am
===================================================================
RCS file: /cvs/src/src/gold/Makefile.am,v
retrieving revision 1.59
diff -u -u -p -r1.59 Makefile.am
--- gold/Makefile.am	11 Jan 2010 19:38:22 -0000	1.59
+++ gold/Makefile.am	3 Feb 2010 02:38:52 -0000
@@ -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
Index: gold/Makefile.in
===================================================================
RCS file: /cvs/src/src/gold/Makefile.in,v
retrieving revision 1.82
diff -u -u -p -r1.82 Makefile.in
--- gold/Makefile.in	11 Jan 2010 19:38:22 -0000	1.82
+++ gold/Makefile.in	3 Feb 2010 02:38:52 -0000
@@ -92,7 +92,7 @@ am__objects_1 = archive.$(OBJEXT) attrib
 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@
Index: gold/arm-reloc-property.cc
===================================================================
RCS file: gold/arm-reloc-property.cc
diff -N gold/arm-reloc-property.cc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gold/arm-reloc-property.cc	3 Feb 2010 02:38:52 -0000
@@ -0,0 +1,286 @@
+// 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];
+  strcpy(buffer, s.c_str());
+  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.
Index: gold/arm-reloc-property.h
===================================================================
RCS file: gold/arm-reloc-property.h
diff -N gold/arm-reloc-property.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gold/arm-reloc-property.h	3 Feb 2010 02:38:52 -0000
@@ -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)
Index: gold/arm-reloc.def
===================================================================
RCS file: gold/arm-reloc.def
diff -N gold/arm-reloc.def
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gold/arm-reloc.def	3 Feb 2010 02:38:53 -0000
@@ -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)
Index: gold/arm.cc
===================================================================
RCS file: /cvs/src/src/gold/arm.cc,v
retrieving revision 1.73
diff -u -u -p -r1.73 arm.cc
--- gold/arm.cc	2 Feb 2010 00:25:57 -0000	1.73
+++ gold/arm.cc	3 Feb 2010 02:38:53 -0000
@@ -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
 // 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<3
   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
Index: gold/configure.tgt
===================================================================
RCS file: /cvs/src/src/gold/configure.tgt,v
retrieving revision 1.7
diff -u -u -p -r1.7 configure.tgt
--- gold/configure.tgt	29 May 2009 00:15:12 -0000	1.7
+++ gold/configure.tgt	3 Feb 2010 02:38:53 -0000
@@ -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
Index: gold/parameters.cc
===================================================================
RCS file: /cvs/src/src/gold/parameters.cc,v
retrieving revision 1.30
diff -u -u -p -r1.30 parameters.cc
--- gold/parameters.cc	14 Dec 2009 19:53:05 -0000	1.30
+++ gold/parameters.cc	3 Feb 2010 02:38:53 -0000
@@ -141,7 +141,10 @@ set_parameters_options(const General_opt
 
 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)
Index: gold/target.h
===================================================================
RCS file: /cvs/src/src/gold/target.h,v
retrieving revision 1.43
diff -u -u -p -r1.43 target.h
--- gold/target.h	8 Jan 2010 19:33:18 -0000	1.43
+++ gold/target.h	3 Feb 2010 02:38:53 -0000
@@ -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.


More information about the Binutils mailing list