diff options
-rw-r--r-- | gold/ChangeLog | 23 | ||||
-rw-r--r-- | gold/dynobj.cc | 8 | ||||
-rw-r--r-- | gold/dynobj.h | 4 | ||||
-rw-r--r-- | gold/object.cc | 49 | ||||
-rw-r--r-- | gold/object.h | 9 | ||||
-rw-r--r-- | gold/target.cc | 80 | ||||
-rw-r--r-- | gold/target.h | 46 |
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&); |