aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rwxr-xr-xconfigure2
-rw-r--r--configure.ac2
-rw-r--r--gold/ChangeLog8
-rw-r--r--gold/Makefile.am5
-rw-r--r--gold/Makefile.in5
-rw-r--r--gold/arm.cc672
-rw-r--r--gold/configure.tgt14
8 files changed, 707 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index b91cfce..adacc3d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2009-05-28 Doug Kwan <dougkwan@google.com>
+
+ * configure.ac: Support gold for target arm*-*-*.
+ * configure: Regenerate.
+
2009-05-27 Alexandre Oliva <aoliva@redhat.com>
* Makefile.tpl (all): Avoid harmless warning in make all when
diff --git a/configure b/configure
index 8559109..d750b42 100755
--- a/configure
+++ b/configure
@@ -2077,7 +2077,7 @@ if test "${ENABLE_GOLD}" = "yes"; then
if test "$is_elf" = "yes"; then
# Check for target supported by gold.
case "${target}" in
- i?86-*-* | x86_64-*-* | sparc*-*-* | powerpc*-*-*)
+ i?86-*-* | x86_64-*-* | sparc*-*-* | powerpc*-*-* | arm*-*-*)
configdirs="`echo " ${configdirs} " | sed -e 's/ ld / gold /'`"
;;
esac
diff --git a/configure.ac b/configure.ac
index ee63082..ba45bd5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -318,7 +318,7 @@ if test "${ENABLE_GOLD}" = "yes"; then
if test "$is_elf" = "yes"; then
# Check for target supported by gold.
case "${target}" in
- i?86-*-* | x86_64-*-* | sparc*-*-* | powerpc*-*-*)
+ i?86-*-* | x86_64-*-* | sparc*-*-* | powerpc*-*-* | arm*-*-*)
configdirs="`echo " ${configdirs} " | sed -e 's/ ld / gold /'`"
;;
esac
diff --git a/gold/ChangeLog b/gold/ChangeLog
index 00f8464..1e03ba4 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,3 +1,11 @@
+2009-05-28 Doug Kwan <dougkwan@google.com>
+
+ * Makefile.am (TARGETSOURCES): Add arm.cc.
+ (ALL_TARGETOBJECTS): Add arm.$(OBJEXT)
+ * Makefile.in: Regenerate.
+ * arm.cc: New file.
+ * configure.tgt: Add armbe*-*-*, armeb*-*-* and arm*-*-* targets.
+
2009-05-26 Doug Kwan <dougkwan@google.com>
* options.cc (General_options::parse_exclude_libs). Fix a comment.
diff --git a/gold/Makefile.am b/gold/Makefile.am
index 360cb7f..c0ab159 100644
--- a/gold/Makefile.am
+++ b/gold/Makefile.am
@@ -123,10 +123,11 @@ YFILES = \
EXTRA_DIST = yyscript.c yyscript.h
TARGETSOURCES = \
- i386.cc x86_64.cc sparc.cc powerpc.cc
+ i386.cc x86_64.cc sparc.cc powerpc.cc arm.cc
ALL_TARGETOBJS = \
- i386.$(OBJEXT) x86_64.$(OBJEXT) sparc.$(OBJEXT) powerpc.$(OBJEXT)
+ i386.$(OBJEXT) x86_64.$(OBJEXT) sparc.$(OBJEXT) powerpc.$(OBJEXT) \
+ arm.$(OBJEXT)
libgold_a_SOURCES = $(CCFILES) $(HFILES) $(YFILES)
diff --git a/gold/Makefile.in b/gold/Makefile.in
index fe3474d..3e6b725 100644
--- a/gold/Makefile.in
+++ b/gold/Makefile.in
@@ -406,10 +406,11 @@ YFILES = \
EXTRA_DIST = yyscript.c yyscript.h
TARGETSOURCES = \
- i386.cc x86_64.cc sparc.cc powerpc.cc
+ i386.cc x86_64.cc sparc.cc powerpc.cc arm.cc
ALL_TARGETOBJS = \
- i386.$(OBJEXT) x86_64.$(OBJEXT) sparc.$(OBJEXT) powerpc.$(OBJEXT)
+ i386.$(OBJEXT) x86_64.$(OBJEXT) sparc.$(OBJEXT) powerpc.$(OBJEXT) \
+ arm.$(OBJEXT)
libgold_a_SOURCES = $(CCFILES) $(HFILES) $(YFILES)
sources_var = main.cc
diff --git a/gold/arm.cc b/gold/arm.cc
new file mode 100644
index 0000000..580b3ef
--- /dev/null
+++ b/gold/arm.cc
@@ -0,0 +1,672 @@
+// arm.cc -- arm target support for gold.
+
+// Copyright 2009 Free Software Foundation, Inc.
+// Written by Doug Kwan <dougkwan@google.com> based on the i386 code
+// by Ian Lance Taylor <iant@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 <limits>
+#include <cstdio>
+#include <string>
+
+#include "elfcpp.h"
+#include "parameters.h"
+#include "reloc.h"
+#include "arm.h"
+#include "object.h"
+#include "symtab.h"
+#include "layout.h"
+#include "output.h"
+#include "copy-relocs.h"
+#include "target.h"
+#include "target-reloc.h"
+#include "target-select.h"
+#include "tls.h"
+#include "defstd.h"
+
+namespace
+{
+
+using namespace gold;
+
+// The arm target class.
+//
+// This is a very simple port of gold for ARM-EABI. It is intended for
+// supporting Android only for the time being. Only these relocation types
+// are supported.
+//
+// R_ARM_NONE
+// R_ARM_ABS32
+// R_ARM_REL32
+// R_ARM_THM_CALL
+// R_ARM_COPY
+// R_ARM_GLOB_DAT
+// R_ARM_BASE_PREL
+// R_ARM_JUMP_SLOT
+// R_ARM_RELATIVE
+// R_ARM_GOTOFF32
+// R_ARM_GOT_BREL
+// R_ARM_PLT32
+// R_ARM_CALL
+// R_ARM_JUMP24
+// R_ARM_TARGET1
+// R_ARM_PREL31
+//
+// Coming soon (pending patches):
+// - Support for dynamic symbols (GOT, PLT and etc).
+// - Local scanner
+// - Global scanner
+// - Relocation
+// - Defining section symbols __exidx_start and __exidx_stop.
+// - Support interworking.
+// - Mergeing all .ARM.xxx.yyy sections into .ARM.xxx. Currently, they
+// are incorrectly merged into an .ARM section.
+//
+// TODOs:
+// - Create a PT_ARM_EXIDX program header for a shared object that
+// might throw an exception.
+// - Support more relocation types as needed.
+
+template<bool big_endian>
+class Target_arm : public Sized_target<32, big_endian>
+{
+ public:
+ typedef Output_data_reloc<elfcpp::SHT_REL, true, 32, big_endian>
+ Reloc_section;
+
+ Target_arm()
+ : Sized_target<32, big_endian>(&arm_info)
+ { }
+
+ // Process the relocations to determine unreferenced sections for
+ // garbage collection.
+ void
+ gc_process_relocs(const General_options& options,
+ Symbol_table* symtab,
+ Layout* layout,
+ Sized_relobj<32, big_endian>* object,
+ unsigned int data_shndx,
+ unsigned int sh_type,
+ const unsigned char* prelocs,
+ size_t reloc_count,
+ Output_section* output_section,
+ bool needs_special_offset_handling,
+ size_t local_symbol_count,
+ const unsigned char* plocal_symbols);
+
+ // Scan the relocations to look for symbol adjustments.
+ void
+ scan_relocs(const General_options& options,
+ Symbol_table* symtab,
+ Layout* layout,
+ Sized_relobj<32, big_endian>* object,
+ unsigned int data_shndx,
+ unsigned int sh_type,
+ const unsigned char* prelocs,
+ size_t reloc_count,
+ Output_section* output_section,
+ bool needs_special_offset_handling,
+ size_t local_symbol_count,
+ const unsigned char* plocal_symbols);
+
+ // Finalize the sections.
+ void
+ do_finalize_sections(Layout*);
+
+ // Return the value to use for a dynamic which requires special
+ // treatment.
+ uint64_t
+ do_dynsym_value(const Symbol*) const;
+
+ // Relocate a section.
+ void
+ relocate_section(const Relocate_info<32, big_endian>*,
+ unsigned int sh_type,
+ const unsigned char* prelocs,
+ size_t reloc_count,
+ Output_section* output_section,
+ bool needs_special_offset_handling,
+ unsigned char* view,
+ elfcpp::Elf_types<32>::Elf_Addr view_address,
+ section_size_type view_size);
+
+ // Scan the relocs during a relocatable link.
+ void
+ scan_relocatable_relocs(const General_options& options,
+ Symbol_table* symtab,
+ Layout* layout,
+ Sized_relobj<32, big_endian>* object,
+ unsigned int data_shndx,
+ unsigned int sh_type,
+ const unsigned char* prelocs,
+ size_t reloc_count,
+ Output_section* output_section,
+ bool needs_special_offset_handling,
+ size_t local_symbol_count,
+ const unsigned char* plocal_symbols,
+ Relocatable_relocs*);
+
+ // Relocate a section during a relocatable link.
+ void
+ relocate_for_relocatable(const Relocate_info<32, big_endian>*,
+ unsigned int sh_type,
+ const unsigned char* prelocs,
+ size_t reloc_count,
+ Output_section* output_section,
+ off_t offset_in_output_section,
+ const Relocatable_relocs*,
+ unsigned char* view,
+ elfcpp::Elf_types<32>::Elf_Addr view_address,
+ section_size_type view_size,
+ unsigned char* reloc_view,
+ section_size_type reloc_view_size);
+
+ // Return whether SYM is defined by the ABI.
+ bool
+ do_is_defined_by_abi(Symbol* sym) const
+ { return strcmp(sym->name(), "__tls_get_addr") == 0; }
+
+ // Map platform-specific reloc types
+ static unsigned int
+ get_real_reloc_type (unsigned int r_type);
+
+ private:
+ // The class which scans relocations.
+ class Scan
+ {
+ public:
+ Scan()
+ { }
+
+ inline void
+ local(const General_options& options, Symbol_table* symtab,
+ Layout* layout, Target_arm* target,
+ Sized_relobj<32, big_endian>* object,
+ unsigned int data_shndx,
+ Output_section* output_section,
+ const elfcpp::Rel<32, big_endian>& reloc, unsigned int r_type,
+ const elfcpp::Sym<32, big_endian>& lsym);
+
+ inline void
+ global(const General_options& options, Symbol_table* symtab,
+ Layout* layout, Target_arm* target,
+ Sized_relobj<32, big_endian>* object,
+ unsigned int data_shndx,
+ Output_section* output_section,
+ const elfcpp::Rel<32, big_endian>& reloc, unsigned int r_type,
+ Symbol* gsym);
+
+ private:
+ static void
+ unsupported_reloc_local(Sized_relobj<32, big_endian>*,
+ unsigned int r_type);
+
+ static void
+ unsupported_reloc_global(Sized_relobj<32, big_endian>*,
+ unsigned int r_type, Symbol*);
+ };
+
+ // The class which implements relocation.
+ class Relocate
+ {
+ public:
+ Relocate()
+ { }
+
+ ~Relocate()
+ { }
+
+ // Do a relocation. Return false if the caller should not issue
+ // any warnings about this relocation.
+ inline bool
+ relocate(const Relocate_info<32, big_endian>*, Target_arm*,
+ Output_section*, size_t relnum,
+ const elfcpp::Rel<32, big_endian>&,
+ unsigned int r_type, const Sized_symbol<32>*,
+ const Symbol_value<32>*,
+ unsigned char*, elfcpp::Elf_types<32>::Elf_Addr,
+ section_size_type);
+ };
+
+ // A class which returns the size required for a relocation type,
+ // used while scanning relocs during a relocatable link.
+ class Relocatable_size_for_reloc
+ {
+ public:
+ unsigned int
+ get_size_for_reloc(unsigned int, Relobj*);
+ };
+
+ // Information about this specific target which we pass to the
+ // general Target structure.
+ static const Target::Target_info arm_info;
+};
+
+template<bool big_endian>
+const Target::Target_info Target_arm<big_endian>::arm_info =
+{
+ 32, // size
+ big_endian, // is_big_endian
+ elfcpp::EM_ARM, // machine_code
+ false, // has_make_symbol
+ false, // has_resolve
+ false, // has_code_fill
+ true, // is_default_stack_executable
+ '\0', // wrap_char
+ "/usr/lib/libc.so.1", // dynamic_linker
+ 0x8000, // default_text_segment_address
+ 0x1000, // abi_pagesize (overridable by -z max-page-size)
+ 0x1000 // common_pagesize (overridable by -z common-page-size)
+};
+
+// Report an unsupported relocation against a local symbol.
+
+template<bool big_endian>
+void
+Target_arm<big_endian>::Scan::unsupported_reloc_local(
+ Sized_relobj<32, big_endian>* object,
+ unsigned int r_type)
+{
+ gold_error(_("%s: unsupported reloc %u against local symbol"),
+ object->name().c_str(), r_type);
+}
+
+// Scan a relocation for a local symbol.
+
+template<bool big_endian>
+inline void
+Target_arm<big_endian>::Scan::local(const General_options&,
+ Symbol_table* /* symtab */,
+ Layout* /* layout */,
+ Target_arm* /* target */,
+ Sized_relobj<32, big_endian>* object,
+ unsigned int /* data_shndx */,
+ Output_section* /* output_section */,
+ const elfcpp::Rel<32, big_endian>& /* reloc */,
+ unsigned int r_type,
+ const elfcpp::Sym<32, big_endian>&)
+{
+ r_type = get_real_reloc_type(r_type);
+ switch (r_type)
+ {
+ case elfcpp::R_ARM_NONE:
+ break;
+
+ default:
+ unsupported_reloc_local(object, r_type);
+ break;
+ }
+}
+
+// Report an unsupported relocation against a global symbol.
+
+template<bool big_endian>
+void
+Target_arm<big_endian>::Scan::unsupported_reloc_global(
+ Sized_relobj<32, big_endian>* object,
+ unsigned int r_type,
+ Symbol* gsym)
+{
+ gold_error(_("%s: unsupported reloc %u against global symbol %s"),
+ object->name().c_str(), r_type, gsym->demangled_name().c_str());
+}
+
+// Scan a relocation for a global symbol.
+
+template<bool big_endian>
+inline void
+Target_arm<big_endian>::Scan::global(const General_options&,
+ Symbol_table* /* symtab */,
+ Layout* /* layout */,
+ Target_arm* /* target */,
+ Sized_relobj<32, big_endian>* object,
+ unsigned int /* data_shndx */,
+ Output_section* /* output_section */,
+ const elfcpp::Rel<32, big_endian>& /* reloc */,
+ unsigned int r_type,
+ Symbol* gsym)
+{
+ r_type = get_real_reloc_type(r_type);
+ switch (r_type)
+ {
+ case elfcpp::R_ARM_NONE:
+ break;
+
+ default:
+ unsupported_reloc_global(object, r_type, gsym);
+ break;
+ }
+}
+
+// Process relocations for gc.
+
+template<bool big_endian>
+void
+Target_arm<big_endian>::gc_process_relocs(const General_options& options,
+ Symbol_table* symtab,
+ Layout* layout,
+ Sized_relobj<32, big_endian>* object,
+ unsigned int data_shndx,
+ unsigned int,
+ const unsigned char* prelocs,
+ size_t reloc_count,
+ Output_section* output_section,
+ bool needs_special_offset_handling,
+ size_t local_symbol_count,
+ const unsigned char* plocal_symbols)
+{
+ typedef Target_arm<big_endian> Arm;
+ typedef typename Target_arm<big_endian>::Scan Scan;
+
+ gold::gc_process_relocs<32, big_endian, Arm, elfcpp::SHT_REL, Scan>(
+ options,
+ symtab,
+ layout,
+ this,
+ object,
+ data_shndx,
+ prelocs,
+ reloc_count,
+ output_section,
+ needs_special_offset_handling,
+ local_symbol_count,
+ plocal_symbols);
+}
+
+// Scan relocations for a section.
+
+template<bool big_endian>
+void
+Target_arm<big_endian>::scan_relocs(const General_options& options,
+ Symbol_table* symtab,
+ Layout* layout,
+ Sized_relobj<32, big_endian>* object,
+ unsigned int data_shndx,
+ unsigned int sh_type,
+ const unsigned char* prelocs,
+ size_t reloc_count,
+ Output_section* output_section,
+ bool needs_special_offset_handling,
+ size_t local_symbol_count,
+ const unsigned char* plocal_symbols)
+{
+ typedef typename Target_arm<big_endian>::Scan Scan;
+ if (sh_type == elfcpp::SHT_RELA)
+ {
+ gold_error(_("%s: unsupported RELA reloc section"),
+ object->name().c_str());
+ return;
+ }
+
+ gold::scan_relocs<32, big_endian, Target_arm, elfcpp::SHT_REL, Scan>(
+ options,
+ symtab,
+ layout,
+ this,
+ object,
+ data_shndx,
+ prelocs,
+ reloc_count,
+ output_section,
+ needs_special_offset_handling,
+ local_symbol_count,
+ plocal_symbols);
+}
+
+// Finalize the sections.
+
+template<bool big_endian>
+void
+Target_arm<big_endian>::do_finalize_sections(Layout* /* layout */)
+{
+ gold_unreachable ();
+}
+
+// Perform a relocation.
+
+template<bool big_endian>
+inline bool
+Target_arm<big_endian>::Relocate::relocate(
+ const Relocate_info<32, big_endian>* /* relinfo */,
+ Target_arm* /* target */,
+ Output_section* /* output_section */,
+ size_t /* relnum */,
+ const elfcpp::Rel<32, big_endian>& /* rel */,
+ unsigned int r_type,
+ const Sized_symbol<32>* /* gsym */,
+ const Symbol_value<32>* /* psymval */,
+ unsigned char* /* view */,
+ elfcpp::Elf_types<32>::Elf_Addr /* address */,
+ section_size_type /* view_size */ )
+{
+ switch (r_type)
+ {
+ case elfcpp::R_ARM_NONE:
+ break;
+
+ default:
+ gold_unreachable();
+ }
+
+ return true;
+}
+
+// Relocate section data.
+
+template<bool big_endian>
+void
+Target_arm<big_endian>::relocate_section(
+ const Relocate_info<32, big_endian>* relinfo,
+ unsigned int sh_type,
+ const unsigned char* prelocs,
+ size_t reloc_count,
+ Output_section* output_section,
+ bool needs_special_offset_handling,
+ unsigned char* view,
+ elfcpp::Elf_types<32>::Elf_Addr address,
+ section_size_type view_size)
+{
+ typedef typename Target_arm<big_endian>::Relocate Arm_relocate;
+ gold_assert(sh_type == elfcpp::SHT_REL);
+
+ gold::relocate_section<32, big_endian, Target_arm, elfcpp::SHT_REL,
+ Arm_relocate>(
+ relinfo,
+ this,
+ prelocs,
+ reloc_count,
+ output_section,
+ needs_special_offset_handling,
+ view,
+ address,
+ view_size);
+}
+
+// Return the size of a relocation while scanning during a relocatable
+// link.
+
+template<bool big_endian>
+unsigned int
+Target_arm<big_endian>::Relocatable_size_for_reloc::get_size_for_reloc(
+ unsigned int r_type,
+ Relobj* object)
+{
+ r_type = get_real_reloc_type(r_type);
+ switch (r_type)
+ {
+ case elfcpp::R_ARM_NONE:
+ return 0;
+
+ case elfcpp::R_ARM_ABS32:
+ case elfcpp::R_ARM_REL32:
+ case elfcpp::R_ARM_THM_CALL:
+ case elfcpp::R_ARM_GOTOFF32:
+ case elfcpp::R_ARM_BASE_PREL:
+ case elfcpp::R_ARM_GOT_BREL:
+ case elfcpp::R_ARM_PLT32:
+ case elfcpp::R_ARM_CALL:
+ case elfcpp::R_ARM_JUMP24:
+ case elfcpp::R_ARM_PREL31:
+ return 4;
+
+ case elfcpp::R_ARM_TARGET1:
+ // This should have been mapped to another type already.
+ // Fall through.
+ case elfcpp::R_ARM_COPY:
+ case elfcpp::R_ARM_GLOB_DAT:
+ case elfcpp::R_ARM_JUMP_SLOT:
+ case elfcpp::R_ARM_RELATIVE:
+ // These are relocations which should only be seen by the
+ // dynamic linker, and should never be seen here.
+ gold_error(_("%s: unexpected reloc %u in object file"),
+ object->name().c_str(), r_type);
+ return 0;
+
+ default:
+ object->error(_("unsupported reloc %u in object file"), r_type);
+ return 0;
+ }
+}
+
+// Scan the relocs during a relocatable link.
+
+template<bool big_endian>
+void
+Target_arm<big_endian>::scan_relocatable_relocs(
+ const General_options& options,
+ Symbol_table* symtab,
+ Layout* layout,
+ Sized_relobj<32, big_endian>* object,
+ unsigned int data_shndx,
+ unsigned int sh_type,
+ const unsigned char* prelocs,
+ size_t reloc_count,
+ Output_section* output_section,
+ bool needs_special_offset_handling,
+ size_t local_symbol_count,
+ const unsigned char* plocal_symbols,
+ Relocatable_relocs* rr)
+{
+ gold_assert(sh_type == elfcpp::SHT_REL);
+
+ typedef gold::Default_scan_relocatable_relocs<elfcpp::SHT_REL,
+ Relocatable_size_for_reloc> Scan_relocatable_relocs;
+
+ gold::scan_relocatable_relocs<32, big_endian, elfcpp::SHT_REL,
+ Scan_relocatable_relocs>(
+ options,
+ symtab,
+ layout,
+ object,
+ data_shndx,
+ prelocs,
+ reloc_count,
+ output_section,
+ needs_special_offset_handling,
+ local_symbol_count,
+ plocal_symbols,
+ rr);
+}
+
+// Relocate a section during a relocatable link.
+
+template<bool big_endian>
+void
+Target_arm<big_endian>::relocate_for_relocatable(
+ const Relocate_info<32, big_endian>* relinfo,
+ unsigned int sh_type,
+ const unsigned char* prelocs,
+ size_t reloc_count,
+ Output_section* output_section,
+ off_t offset_in_output_section,
+ const Relocatable_relocs* rr,
+ unsigned char* view,
+ elfcpp::Elf_types<32>::Elf_Addr view_address,
+ section_size_type view_size,
+ unsigned char* reloc_view,
+ section_size_type reloc_view_size)
+{
+ gold_assert(sh_type == elfcpp::SHT_REL);
+
+ gold::relocate_for_relocatable<32, big_endian, elfcpp::SHT_REL>(
+ relinfo,
+ prelocs,
+ reloc_count,
+ output_section,
+ offset_in_output_section,
+ rr,
+ view,
+ view_address,
+ view_size,
+ reloc_view,
+ reloc_view_size);
+}
+
+template<bool big_endian>
+uint64_t
+Target_arm<big_endian>::do_dynsym_value(const Symbol* /*gsym*/) const
+{
+ gold_unreachable ();
+ return 0;
+}
+
+// Map platform-specific relocs to real relocs
+//
+template<bool big_endian>
+unsigned int
+Target_arm<big_endian>::get_real_reloc_type (unsigned int r_type)
+{
+ switch (r_type)
+ {
+ case elfcpp::R_ARM_TARGET1:
+ // This is either R_ARM_ABS32 or R_ARM_REL32;
+ return elfcpp::R_ARM_ABS32;
+
+ case elfcpp::R_ARM_TARGET2:
+ // This can be any reloc type but ususally is R_ARM_GOT_PREL
+ return elfcpp::R_ARM_GOT_PREL;
+
+ default:
+ return r_type;
+ }
+}
+
+// The selector for arm object files.
+
+template<bool big_endian>
+class Target_selector_arm : public Target_selector
+{
+ public:
+ Target_selector_arm()
+ : Target_selector(elfcpp::EM_ARM, 32, big_endian,
+ (big_endian ? "elf32-bigarm" : "elf32-littlearm"))
+ { }
+
+ Target*
+ do_instantiate_target()
+ { return new Target_arm<big_endian>(); }
+};
+
+Target_selector_arm<false> target_selector_arm;
+Target_selector_arm<true> target_selector_armbe;
+
+} // End anonymous namespace.
diff --git a/gold/configure.tgt b/gold/configure.tgt
index b4ef376..de6d4f9 100644
--- a/gold/configure.tgt
+++ b/gold/configure.tgt
@@ -104,6 +104,20 @@ powerpc64-*)
targ_big_endian=true
targ_extra_big_endian=false
;;
+armeb*-*-*|armbe*-*-*)
+ targ_obj=arm
+ targ_machine=EM_ARM
+ targ_size=32
+ targ_big_endian=true
+ targ_extra_big_endian=false
+ ;;
+arm*-*-*)
+ targ_obj=arm
+ targ_machine=EM_ARM
+ targ_size=32
+ targ_big_endian=false
+ targ_extra_big_endian=true
+ ;;
*)
targ_obj=UNKNOWN
;;