OSDN Git Service

2009-08-18 Doug Kwan <dougkwan@google.com>
authorDoug Kwan <dougkwan@google.com>
Tue, 18 Aug 2009 23:49:29 +0000 (23:49 +0000)
committerDoug Kwan <dougkwan@google.com>
Tue, 18 Aug 2009 23:49:29 +0000 (23:49 +0000)
* 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.

gold/ChangeLog
gold/dynobj.cc
gold/dynobj.h
gold/object.cc
gold/object.h
gold/target.cc
gold/target.h

index 687693a..a8683de 100644 (file)
@@ -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.
index 8761eaa..df2afeb 100644 (file)
@@ -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);
 }
index a15e2a4..f6c6538 100644 (file)
@@ -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
index b72fb58..be6294c 100644 (file)
@@ -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.
index df090d0..4394318 100644 (file)
@@ -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.
index b6844d0..2dca98a 100644 (file)
@@ -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.
index 597a4f9..c9b07a8 100644 (file)
@@ -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&);