[PATCH][GOLD] Add make_elf_object target hooks.

Doug Kwan (關振德) dougkwan@google.com
Tue Aug 18 19:08:00 GMT 2009


Hi,

    I have updated the patch.

-Doug

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/8/18 Ian Lance Taylor <iant@google.com>:
> "Doug Kwan (關振德)" <dougkwan@google.com> writes:
>
>> 2009/8/18 Ian Lance Taylor <iant@google.com>:
>>
>>>> +      obj->setup(ehdr);
>>>
>>> It no longer makes sense for Object::setup to take an ehdr parameter.
>>> It should take a target parameter, and avoid looking up the target
>>> again.
>>
>> Agree. I suppose all objects have targets and their targets do not
>> change.   Should setup() be simply part of the constructor?
>
> I originally left it out because it can fail, and it's weird to have a
> constructor fail.  I guess I'd prefer to keep it separate for now.
>
>
>>> Interesting problem.  I wonder if there is anything we can do to make
>>> that easier to write.
>>
>> Unfortunately, virtual functions cannot be templated.  That's why I
>> mentioned changing the paratmeter ehdr back to a raw unsigned char
>> pointer.  If we do so,  we only have one virtual function instead of
>> four.  The downside of doing that is that callers must ensure that the
>> pointer points to something valid.   Passing an
>> Elfcpp::Ehdr<size,big_endian> object enforces that automatically.
>
> Yeah, I guess the way you did it is fine.
>
> Ian
>
-------------- next part --------------
Index: gold/dynobj.cc
===================================================================
RCS file: /cvs/src/src/gold/dynobj.cc,v
retrieving revision 1.43
diff -u -p -r1.43 dynobj.cc
--- gold/dynobj.cc	13 Feb 2009 19:04:44 -0000	1.43
+++ gold/dynobj.cc	18 Aug 2009 18:50:10 -0000
@@ -83,13 +83,9 @@ Sized_dynobj<size, big_endian>::Sized_dy
 
 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: gold/dynobj.h
===================================================================
RCS file: /cvs/src/src/gold/dynobj.h,v
retrieving revision 1.31
diff -u -p -r1.31 dynobj.h
--- gold/dynobj.h	10 Aug 2009 02:29:30 -0000	1.31
+++ gold/dynobj.h	18 Aug 2009 18:50:10 -0000
@@ -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: gold/object.cc
===================================================================
RCS file: /cvs/src/src/gold/object.cc,v
retrieving revision 1.97
diff -u -p -r1.97 object.cc
--- gold/object.cc	5 Aug 2009 20:51:56 -0000	1.97
+++ gold/object.cc	18 Aug 2009 18:50:11 -0000
@@ -132,19 +132,6 @@ Xindex::sym_xindex_to_shndx(Object* obje
 
 // 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_r
 
 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: gold/object.h
===================================================================
RCS file: /cvs/src/src/gold/object.h,v
retrieving revision 1.77
diff -u -p -r1.77 object.h
--- gold/object.h	5 Aug 2009 20:51:56 -0000	1.77
+++ gold/object.h	18 Aug 2009 18:50:11 -0000
@@ -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: gold/target.cc
===================================================================
RCS file: /cvs/src/src/gold/target.cc,v
retrieving revision 1.1
diff -u -p -r1.1 target.cc
--- gold/target.cc	5 Jun 2009 21:32:56 -0000	1.1
+++ gold/target.cc	18 Aug 2009 18:50:11 -0000
@@ -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 ch
   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: gold/target.h
===================================================================
RCS file: /cvs/src/src/gold/target.h,v
retrieving revision 1.34
diff -u -p -r1.34 target.h
--- gold/target.h	22 Jun 2009 06:51:53 -0000	1.34
+++ gold/target.h	18 Aug 2009 18:50:11 -0000
@@ -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&);
 


More information about the Binutils mailing list