aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gold/ChangeLog23
-rw-r--r--gold/dynobj.cc8
-rw-r--r--gold/dynobj.h4
-rw-r--r--gold/object.cc49
-rw-r--r--gold/object.h9
-rw-r--r--gold/target.cc80
-rw-r--r--gold/target.h46
7 files changed, 165 insertions, 54 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog
index 687693a..a8683de 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,3 +1,26 @@
+2009-08-18 Doug Kwan <dougkwan@google.com>
+
+ * dynobj.cc (Sized_dynobj::setup): Take a Target object instead of
+ an elcpp::Ehdr as parameter. Adjust call to set_target.
+ * dynobj.h (Sized_dynobj::setup): Take a Target object instead of
+ an elfcpp::Ehdr as parameter.
+ * object.cc (Object::set_target): Remove the version that looks up
+ a target and sets it.
+ (Sized_relobj::setup): Take a Target object instead of
+ an elfcpp::Ehdr as parameter. Adjust call to set_target.
+ (make_elf_sized_object): Find target and ask target to
+ make an ELF object.
+ * object.h: (Object::set_target): Remove the version that looks up
+ a target and sets it.
+ (Sized_relobj::setup): Take a Target object instead of
+ an elfcpp:Ehdr as parameter.
+ * target.cc: Include dynobj.h.
+ (Target::do_make_elf_object_implementation): New.
+ (Target::do_make_elf_object): New.
+ * target.h (Target::make_elf_object): New template declaration.
+ (Target::do_make_elf_object): New method declarations.
+ (Target::do_make_elf_object_implementation): New template declaration.
+
2009-08-14 Ian Lance Taylor <iant@google.com>
* gold.h (FUNCTION_NAME): Define.
diff --git a/gold/dynobj.cc b/gold/dynobj.cc
index 8761eaa..df2afeb 100644
--- a/gold/dynobj.cc
+++ b/gold/dynobj.cc
@@ -83,13 +83,9 @@ Sized_dynobj<size, big_endian>::Sized_dynobj(
template<int size, bool big_endian>
void
-Sized_dynobj<size, big_endian>::setup(
- const elfcpp::Ehdr<size, big_endian>& ehdr)
+Sized_dynobj<size, big_endian>::setup(Target *target)
{
- this->set_target(ehdr.get_e_machine(), size, big_endian,
- ehdr.get_e_ident()[elfcpp::EI_OSABI],
- ehdr.get_e_ident()[elfcpp::EI_ABIVERSION]);
-
+ this->set_target(target);
const unsigned int shnum = this->elf_file_.shnum();
this->set_shnum(shnum);
}
diff --git a/gold/dynobj.h b/gold/dynobj.h
index a15e2a4..f6c6538 100644
--- a/gold/dynobj.h
+++ b/gold/dynobj.h
@@ -161,9 +161,9 @@ class Sized_dynobj : public Dynobj
Sized_dynobj(const std::string& name, Input_file* input_file, off_t offset,
const typename elfcpp::Ehdr<size, big_endian>&);
- // Set up the object file based on the ELF header.
+ // Set up the object file based on TARGET.
void
- setup(const typename elfcpp::Ehdr<size, big_endian>&);
+ setup(Target *target);
// Read the symbols.
void
diff --git a/gold/object.cc b/gold/object.cc
index b72fb58..be6294c 100644
--- a/gold/object.cc
+++ b/gold/object.cc
@@ -132,19 +132,6 @@ Xindex::sym_xindex_to_shndx(Object* object, unsigned int symndx)
// Class Object.
-// Set the target based on fields in the ELF file header.
-
-void
-Object::set_target(int machine, int size, bool big_endian, int osabi,
- int abiversion)
-{
- Target* target = select_target(machine, size, big_endian, osabi, abiversion);
- if (target == NULL)
- gold_fatal(_("%s: unsupported ELF machine number %d"),
- this->name().c_str(), machine);
- this->target_ = target;
-}
-
// Report an error for this object file. This is used by the
// elfcpp::Elf_file interface, and also called by the Object code
// itself.
@@ -353,12 +340,9 @@ Sized_relobj<size, big_endian>::~Sized_relobj()
template<int size, bool big_endian>
void
-Sized_relobj<size, big_endian>::setup(
- const elfcpp::Ehdr<size, big_endian>& ehdr)
+Sized_relobj<size, big_endian>::setup(Target *target)
{
- this->set_target(ehdr.get_e_machine(), size, big_endian,
- ehdr.get_e_ident()[elfcpp::EI_OSABI],
- ehdr.get_e_ident()[elfcpp::EI_ABIVERSION]);
+ this->set_target(target);
const unsigned int shnum = this->elf_file_.shnum();
this->set_shnum(shnum);
@@ -2237,27 +2221,14 @@ Object*
make_elf_sized_object(const std::string& name, Input_file* input_file,
off_t offset, const elfcpp::Ehdr<size, big_endian>& ehdr)
{
- int et = ehdr.get_e_type();
- if (et == elfcpp::ET_REL)
- {
- Sized_relobj<size, big_endian>* obj =
- new Sized_relobj<size, big_endian>(name, input_file, offset, ehdr);
- obj->setup(ehdr);
- return obj;
- }
- else if (et == elfcpp::ET_DYN)
- {
- Sized_dynobj<size, big_endian>* obj =
- new Sized_dynobj<size, big_endian>(name, input_file, offset, ehdr);
- obj->setup(ehdr);
- return obj;
- }
- else
- {
- gold_error(_("%s: unsupported ELF file type %d"),
- name.c_str(), et);
- return NULL;
- }
+ Target* target = select_target(ehdr.get_e_machine(), size, big_endian,
+ ehdr.get_e_ident()[elfcpp::EI_OSABI],
+ ehdr.get_e_ident()[elfcpp::EI_ABIVERSION]);
+ if (target == NULL)
+ gold_fatal(_("%s: unsupported ELF machine number %d"),
+ name.c_str(), ehdr.get_e_machine());
+ return target->make_elf_object<size, big_endian>(name, input_file, offset,
+ ehdr);
}
} // End anonymous namespace.
diff --git a/gold/object.h b/gold/object.h
index df090d0..4394318 100644
--- a/gold/object.h
+++ b/gold/object.h
@@ -545,11 +545,6 @@ class Object
virtual void
do_get_global_symbol_counts(const Symbol_table*, size_t*, size_t*) const = 0;
- // Set the target.
- void
- set_target(int machine, int size, bool big_endian, int osabi,
- int abiversion);
-
// Set the number of sections.
void
set_shnum(int shnum)
@@ -1311,9 +1306,9 @@ class Sized_relobj : public Relobj
is_output_section_offset_invalid(unsigned int shndx) const
{ return this->get_output_section_offset(shndx) == invalid_address; }
- // Set up the object file based on the ELF header.
+ // Set up the object file based on TARGET.
void
- setup(const typename elfcpp::Ehdr<size, big_endian>&);
+ setup(Target *target);
// Return the number of symbols. This is only valid after
// Object::add_symbols has been called.
diff --git a/gold/target.cc b/gold/target.cc
index b6844d0..2dca98a 100644
--- a/gold/target.cc
+++ b/gold/target.cc
@@ -22,6 +22,7 @@
#include "gold.h"
#include "target.h"
+#include "dynobj.h"
namespace gold
{
@@ -55,4 +56,83 @@ Target::do_is_local_label_name (const char* name) const
return false;
}
+// Implementations of methods Target::do_make_elf_object are almost identical
+// except for the address sizes and endianities. So we extract this
+// into a template.
+
+template<int size, bool big_endian>
+inline Object*
+Target::do_make_elf_object_implementation(
+ const std::string& name,
+ Input_file* input_file,
+ off_t offset,
+ const elfcpp::Ehdr<size, big_endian>& ehdr)
+{
+ int et = ehdr.get_e_type();
+ if (et == elfcpp::ET_REL)
+ {
+ Sized_relobj<size, big_endian>* obj =
+ new Sized_relobj<size, big_endian>(name, input_file, offset, ehdr);
+ obj->setup(this);
+ return obj;
+ }
+ else if (et == elfcpp::ET_DYN)
+ {
+ Sized_dynobj<size, big_endian>* obj =
+ new Sized_dynobj<size, big_endian>(name, input_file, offset, ehdr);
+ obj->setup(this);
+ return obj;
+ }
+ else
+ {
+ gold_error(_("%s: unsupported ELF file type %d"),
+ name.c_str(), et);
+ return NULL;
+ }
+}
+
+// Make an ELF object called NAME by reading INPUT_FILE at OFFSET. EHDR
+// is the ELF header of the object. There are four versions of this
+// for different address sizes and endianities.
+
+#ifdef HAVE_TARGET_32_LITTLE
+Object*
+Target::do_make_elf_object(const std::string& name, Input_file* input_file,
+ off_t offset, const elfcpp::Ehdr<32, false>& ehdr)
+{
+ return this->do_make_elf_object_implementation<32, false>(name, input_file,
+ offset, ehdr);
+}
+#endif
+
+#ifdef HAVE_TARGET_32_BIG
+Object*
+Target::do_make_elf_object(const std::string& name, Input_file* input_file,
+ off_t offset, const elfcpp::Ehdr<32, true>& ehdr)
+{
+ return this->do_make_elf_object_implementation<32, true>(name, input_file,
+ offset, ehdr);
+}
+#endif
+
+#ifdef HAVE_TARGET_64_LITTLE
+Object*
+Target::do_make_elf_object(const std::string& name, Input_file* input_file,
+ off_t offset, const elfcpp::Ehdr<64, false>& ehdr)
+{
+ return this->do_make_elf_object_implementation<64, false>(name, input_file,
+ offset, ehdr);
+}
+#endif
+
+#ifdef HAVE_TARGET_64_BIG
+Object*
+Target::do_make_elf_object(const std::string& name, Input_file* input_file,
+ off_t offset, const elfcpp::Ehdr<64, true>& ehdr)
+{
+ return this->do_make_elf_object_implementation<64, true>(name, input_file,
+ offset, ehdr);
+}
+#endif
+
} // End namespace gold.
diff --git a/gold/target.h b/gold/target.h
index 597a4f9..c9b07a8 100644
--- a/gold/target.h
+++ b/gold/target.h
@@ -216,6 +216,13 @@ class Target
is_local_label_name(const char* name) const
{ return this->do_is_local_label_name(name); }
+ // Make an ELF object.
+ template<int size, bool big_endian>
+ Object*
+ make_elf_object(const std::string& name, Input_file* input_file,
+ off_t offset, const elfcpp::Ehdr<size, big_endian>& ehdr)
+ { return this->do_make_elf_object(name, input_file, offset, ehdr); }
+
protected:
// This struct holds the constant information for a child class. We
// use a struct to avoid the overhead of virtual function calls for
@@ -301,7 +308,46 @@ class Target
virtual bool
do_is_local_label_name(const char*) const;
+ // make_elf_object hooks. There are four versions of these for
+ // different address sizes and endianities.
+
+#ifdef HAVE_TARGET_32_LITTLE
+ // Virtual functions which may be overriden by the child class.
+ virtual Object*
+ do_make_elf_object(const std::string&, Input_file*, off_t,
+ const elfcpp::Ehdr<32, false>&);
+#endif
+
+#ifdef HAVE_TARGET_32_BIG
+ // Virtual functions which may be overriden by the child class.
+ virtual Object*
+ do_make_elf_object(const std::string&, Input_file*, off_t,
+ const elfcpp::Ehdr<32, true>&);
+#endif
+
+#ifdef HAVE_TARGET_64_LITTLE
+ // Virtual functions which may be overriden by the child class.
+ virtual Object*
+ do_make_elf_object(const std::string&, Input_file*, off_t,
+ const elfcpp::Ehdr<64, false>& ehdr);
+#endif
+
+#ifdef HAVE_TARGET_64_BIG
+ // Virtual functions which may be overriden by the child class.
+ virtual Object*
+ do_make_elf_object(const std::string& name, Input_file* input_file,
+ off_t offset, const elfcpp::Ehdr<64, true>& ehdr);
+#endif
+
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.
+ // for their implementations.
+ template<int size, bool big_endian>
+ inline Object*
+ do_make_elf_object_implementation(const std::string&, Input_file*, off_t,
+ const elfcpp::Ehdr<size, big_endian>&);
+
Target(const Target&);
Target& operator=(const Target&);