OSDN Git Service

Add support for local GOT offsets.
authoriant <iant>
Mon, 8 Oct 2007 07:22:21 +0000 (07:22 +0000)
committeriant <iant>
Mon, 8 Oct 2007 07:22:21 +0000 (07:22 +0000)
gold/object.cc
gold/object.h
gold/output.cc
gold/output.h

index 9986383..cfdb17c 100644 (file)
@@ -147,7 +147,8 @@ Sized_relobj<size, big_endian>::Sized_relobj(
     output_local_symbol_count_(0),
     symbols_(NULL),
     local_symbol_offset_(0),
-    local_values_()
+    local_values_(),
+    local_got_offsets_()
 {
 }
 
@@ -662,6 +663,17 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(unsigned int index,
   return index;
 }
 
+// Return the value of the local symbol symndx.
+template<int size, bool big_endian>
+typename elfcpp::Elf_types<size>::Elf_Addr
+Sized_relobj<size, big_endian>::local_symbol_value(unsigned int symndx) const
+{
+  gold_assert(symndx < this->local_symbol_count_);
+  gold_assert(symndx < this->local_values_.size());
+  const Symbol_value<size>& lv(this->local_values_[symndx]);
+  return lv.value(this, 0);
+}
+
 // Return the value of a local symbol defined in input section SHNDX,
 // with value VALUE, adding addend ADDEND.  IS_SECTION_SYMBOL
 // indicates whether the symbol is a section symbol.  This handles
index e4359ac..2baf2da 100644 (file)
@@ -612,6 +612,54 @@ class Sized_relobj : public Relobj
     return this->local_values_[sym].output_symtab_index();
   }
 
+  // Return the appropriate Sized_target structure.
+  Sized_target<size, big_endian>*
+  sized_target()
+  {
+    return this->Object::sized_target
+      SELECT_SIZE_ENDIAN_NAME(size, big_endian) (
+          SELECT_SIZE_ENDIAN_ONLY(size, big_endian));
+  }
+
+  // Return the value of the local symbol symndx.
+  Address
+  local_symbol_value(unsigned int symndx) const;
+
+  // Return the value of a local symbol defined in input section
+  // SHNDX, with value VALUE, adding addend ADDEND.  IS_SECTION_SYMBOL
+  // indicates whether the symbol is a section symbol.  This handles
+  // SHF_MERGE sections.
+  Address
+  local_value(unsigned int shndx, Address value, bool is_section_symbol,
+             Address addend) const;
+
+  // Return whether the local symbol SYMNDX has a GOT offset.
+  bool
+  local_has_got_offset(unsigned int symndx) const
+  {
+    return (this->local_got_offsets_.find(symndx)
+            != this->local_got_offsets_.end());
+  }
+
+  // Return the GOT offset of the local symbol SYMNDX.
+  unsigned int
+  local_got_offset(unsigned int symndx) const
+  {
+    Local_got_offsets::const_iterator p =
+        this->local_got_offsets_.find(symndx);
+    gold_assert(p != this->local_got_offsets_.end());
+    return p->second;
+  }
+
+  // Set the GOT offset of the local symbol SYMNDX to GOT_OFFSET.
+  void
+  set_local_got_offset(unsigned int symndx, unsigned int got_offset)
+  {
+    std::pair<Local_got_offsets::iterator, bool> ins =
+        this->local_got_offsets_.insert(std::make_pair(symndx, got_offset));
+    gold_assert(ins.second);
+  }
+
   // Read the symbols.
   void
   do_read_symbols(Read_symbols_data*);
@@ -658,23 +706,6 @@ class Sized_relobj : public Relobj
   do_section_flags(unsigned int shndx)
   { return this->elf_file_.section_flags(shndx); }
 
-  // Return the appropriate Sized_target structure.
-  Sized_target<size, big_endian>*
-  sized_target()
-  {
-    return this->Object::sized_target
-      SELECT_SIZE_ENDIAN_NAME(size, big_endian) (
-          SELECT_SIZE_ENDIAN_ONLY(size, big_endian));
-  }
-
-  // Return the value of a local symbol define in input section SHNDX,
-  // with value VALUE, adding addend ADDEND.  IS_SECTION_SYMBOL
-  // indicates whether the symbol is a section symbol.  This handles
-  // SHF_MERGE sections.
-  Address
-  local_value(unsigned int shndx, Address value, bool is_section_symbol,
-             Address addend) const;
-
  private:
   // For convenience.
   typedef Sized_relobj<size, big_endian> This;
@@ -724,6 +755,9 @@ class Sized_relobj : public Relobj
   write_local_symbols(Output_file*,
                      const Stringpool_template<char>*);
 
+  // The GOT offsets of local symbols.
+  typedef Unordered_map<unsigned int, unsigned int> Local_got_offsets;
+
   // General access to the ELF file.
   elfcpp::Elf_file<size, big_endian, Object> elf_file_;
   // Index of SHT_SYMTAB section.
@@ -738,6 +772,8 @@ class Sized_relobj : public Relobj
   off_t local_symbol_offset_;
   // Values of local symbols.
   Local_values local_values_;
+  // GOT offsets for local symbols, indexed by symbol number.
+  Local_got_offsets local_got_offsets_;
 };
 
 // A class to manage the list of all objects.
index 34fdc67..f217b03 100644 (file)
@@ -679,7 +679,8 @@ Output_data_got<size, big_endian>::Got_entry::write(unsigned char* pov) const
       break;
 
     default:
-      gold_unreachable();
+      val = this->u_.object->local_symbol_value(this->local_sym_index_);
+      break;
     }
 
   elfcpp::Swap<size, big_endian>::writeval(pov, val);
@@ -704,6 +705,24 @@ Output_data_got<size, big_endian>::add_global(Symbol* gsym)
   return true;
 }
 
+// Add an entry for a local symbol to the GOT.  This returns true if
+// this is a new GOT entry, false if the symbol already has a GOT
+// entry.
+
+template<int size, bool big_endian>
+bool
+Output_data_got<size, big_endian>::add_local(
+    Sized_relobj<size, big_endian>* object,
+    unsigned int symndx)
+{
+  if (object->local_has_got_offset(symndx))
+    return false;
+  this->entries_.push_back(Got_entry(object, symndx));
+  this->set_got_size();
+  object->set_local_got_offset(symndx, this->last_got_offset());
+  return true;
+}
+
 // Write out the GOT.
 
 template<int size, bool big_endian>
index 7f783d6..997a821 100644 (file)
@@ -909,15 +909,11 @@ class Output_data_got : public Output_section_data
   bool
   add_global(Symbol* gsym);
 
-  // Add an entry for a local symbol to the GOT.  This returns the
-  // offset of the new entry from the start of the GOT.
-  unsigned int
-  add_local(Object* object, unsigned int sym_index)
-  {
-    this->entries_.push_back(Got_entry(object, sym_index));
-    this->set_got_size();
-    return this->last_got_offset();
-  }
+  // Add an entry for a local symbol to the GOT.  This returns true if
+  // this is a new GOT entry, false if the symbol already has a GOT
+  // entry.
+  bool
+  add_local(Sized_relobj<size, big_endian>* object, unsigned int sym_index);
 
   // Add a constant to the GOT.  This returns the offset of the new
   // entry from the start of the GOT.
@@ -949,7 +945,8 @@ class Output_data_got : public Output_section_data
     { this->u_.gsym = gsym; }
 
     // Create a local symbol entry.
-    Got_entry(Object* object, unsigned int local_sym_index)
+    Got_entry(Sized_relobj<size, big_endian>* object,
+              unsigned int local_sym_index)
       : local_sym_index_(local_sym_index)
     {
       gold_assert(local_sym_index != GSYM_CODE
@@ -977,7 +974,7 @@ class Output_data_got : public Output_section_data
     union
     {
       // For a local symbol, the object.
-      Object* object;
+      Sized_relobj<size, big_endian>* object;
       // For a global symbol, the symbol.
       Symbol* gsym;
       // For a constant, the constant.