* incremental-dump.cc (dump_incremental_inputs): Print local
authorCary Coutant <ccoutant@google.com>
Mon, 25 Apr 2011 20:28:48 +0000 (20:28 +0000)
committerCary Coutant <ccoutant@google.com>
Mon, 25 Apr 2011 20:28:48 +0000 (20:28 +0000)
symbol info for each input file.
* incremental.cc
(Output_section_incremental_inputs::set_final_data_size): Add local
symbol info to input file entries in incremental info.
(Output_section_incremental_inputs::write_info_blocks): Likewise.
(Sized_incr_relobj::Sized_incr_relobj): Initialize new data members.
(Sized_incr_relobj::do_add_symbols): Cosmetic change.
(Sized_incr_relobj::do_count_local_symbols): Replace stub with
implementation.
(Sized_incr_relobj::do_finalize_local_symbols): Likewise.
(Sized_incr_relobj::do_relocate): Write the local symbols.
(Sized_incr_dynobj::do_add_symbols): Cosmetic change.
* incremental.h (Incremental_inputs_reader::get_symbol_offset):
Adjust size of input file header.
(Incremental_inputs_reader::get_local_symbol_offset): New function.
(Incremental_inputs_reader::get_local_symbol_count): New function.
(Incremental_inputs_reader::get_input_section): Adjust size of input
file header.
(Incremental_inputs_reader::get_global_symbol_reader): Likewise.
(Sized_incr_relobj::This): New typedef.
(Sized_incr_relobj::sym_size): New const data member.
(Sized_incr_relobj::Local_symbol): New struct.
(Sized_incr_relobj::do_output_local_symbol_count): New function.
(Sized_incr_relobj::do_local_symbol_offset): New function.
(Sized_incr_relobj::local_symbol_count_): New data member.
(Sized_incr_relobj::output_local_dynsym_count_): New data member.
(Sized_incr_relobj::local_symbol_index_): New data member.
(Sized_incr_relobj::local_symbol_offset_): New data member.
(Sized_incr_relobj::local_dynsym_offset_): New data member.
(Sized_incr_relobj::local_symbols_): New data member.
* object.h (Relobj::output_local_symbol_count): New function.
(Relobj::local_symbol_offset): New function.
(Relobj::do_output_local_symbol_count): New function.
(Relobj::do_local_symbol_offset): New function.
(Sized_relobj::do_output_local_symbol_count): New function.
(Sized_relobj::do_local_symbol_offset): New function.

gold/ChangeLog
gold/incremental-dump.cc
gold/incremental.cc
gold/incremental.h
gold/object.h

index d9da5f8..94c19bc 100644 (file)
@@ -1,3 +1,43 @@
+2011-04-25 Cary Coutant  <ccoutant@google.com>
+
+       * incremental-dump.cc (dump_incremental_inputs): Print local
+       symbol info for each input file.
+       * incremental.cc
+       (Output_section_incremental_inputs::set_final_data_size): Add local
+       symbol info to input file entries in incremental info.
+       (Output_section_incremental_inputs::write_info_blocks): Likewise.
+       (Sized_incr_relobj::Sized_incr_relobj): Initialize new data members.
+       (Sized_incr_relobj::do_add_symbols): Cosmetic change.
+       (Sized_incr_relobj::do_count_local_symbols): Replace stub with
+       implementation.
+       (Sized_incr_relobj::do_finalize_local_symbols): Likewise.
+       (Sized_incr_relobj::do_relocate): Write the local symbols.
+       (Sized_incr_dynobj::do_add_symbols): Cosmetic change.
+       * incremental.h (Incremental_inputs_reader::get_symbol_offset):
+       Adjust size of input file header.
+       (Incremental_inputs_reader::get_local_symbol_offset): New function.
+       (Incremental_inputs_reader::get_local_symbol_count): New function.
+       (Incremental_inputs_reader::get_input_section): Adjust size of input
+       file header.
+       (Incremental_inputs_reader::get_global_symbol_reader): Likewise.
+       (Sized_incr_relobj::This): New typedef.
+       (Sized_incr_relobj::sym_size): New const data member.
+       (Sized_incr_relobj::Local_symbol): New struct.
+       (Sized_incr_relobj::do_output_local_symbol_count): New function.
+       (Sized_incr_relobj::do_local_symbol_offset): New function.
+       (Sized_incr_relobj::local_symbol_count_): New data member.
+       (Sized_incr_relobj::output_local_dynsym_count_): New data member.
+       (Sized_incr_relobj::local_symbol_index_): New data member.
+       (Sized_incr_relobj::local_symbol_offset_): New data member.
+       (Sized_incr_relobj::local_dynsym_offset_): New data member.
+       (Sized_incr_relobj::local_symbols_): New data member.
+       * object.h (Relobj::output_local_symbol_count): New function.
+       (Relobj::local_symbol_offset): New function.
+       (Relobj::do_output_local_symbol_count): New function.
+       (Relobj::do_local_symbol_offset): New function.
+       (Sized_relobj::do_output_local_symbol_count): New function.
+       (Sized_relobj::do_local_symbol_offset): New function.
+
 2011-04-22  Vladimir Simonov  <sv@sw.ru>
 
        * descriptors.cc (set_close_on_exec): New function.
index 3a77ee8..5ac6e6c 100644 (file)
@@ -138,18 +138,17 @@ dump_incremental_inputs(const char* argv0, const char* filename,
       switch (input_type)
        {
        case INCREMENTAL_INPUT_OBJECT:
-         printf("Object\n");
-         printf("    Input section count: %d\n",
-                input_file.get_input_section_count());
-         printf("    Symbol count: %d\n",
-                input_file.get_global_symbol_count());
-         break;
        case INCREMENTAL_INPUT_ARCHIVE_MEMBER:
-         printf("Archive member\n");
+         printf("%s\n", (input_type == INCREMENTAL_INPUT_OBJECT
+                         ? "Object" : "Archive member"));
          printf("    Input section count: %d\n",
                 input_file.get_input_section_count());
-         printf("    Symbol count: %d\n",
+         printf("    Global symbol count: %d\n",
                 input_file.get_global_symbol_count());
+         printf("    Local symbol offset: %d\n",
+                input_file.get_local_symbol_offset());
+         printf("    Local symbol count: %d\n",
+                input_file.get_local_symbol_count());
          break;
        case INCREMENTAL_INPUT_ARCHIVE:
          printf("Archive\n");
index 3de22f1..1250d70 100644 (file)
@@ -1055,8 +1055,9 @@ Output_section_incremental_inputs<size, big_endian>::set_final_data_size()
            Incremental_object_entry* entry = (*p)->object_entry();
            gold_assert(entry != NULL);
            (*p)->set_info_offset(info_offset);
-           // Input section count + global symbol count.
-           info_offset += 8;
+           // Input section count, global symbol count, local symbol offset,
+           // local symbol count.
+           info_offset += 16;
            // Each input section.
            info_offset += (entry->get_input_section_count()
                            * (8 + 2 * sizeof_addr));
@@ -1295,13 +1296,18 @@ Output_section_incremental_inputs<size, big_endian>::write_info_blocks(
            Incremental_object_entry* entry = (*p)->object_entry();
            gold_assert(entry != NULL);
            const Object* obj = entry->object();
+           const Relobj* relobj = static_cast<const Relobj*>(obj);
            const Object::Symbols* syms = obj->get_global_symbols();
            // Write the input section count and global symbol count.
            unsigned int nsections = entry->get_input_section_count();
            unsigned int nsyms = syms->size();
+           off_t locals_offset = relobj->local_symbol_offset();
+           unsigned int nlocals = relobj->output_local_symbol_count();
            Swap32::writeval(pov, nsections);
            Swap32::writeval(pov + 4, nsyms);
-           pov += 8;
+           Swap32::writeval(pov + 8, static_cast<unsigned int>(locals_offset));
+           Swap32::writeval(pov + 12, nlocals);
+           pov += 16;
 
            // Build a temporary array to map input section indexes
            // from the original object file index to the index in the
@@ -1671,8 +1677,11 @@ Sized_incr_relobj<size, big_endian>::Sized_incr_relobj(
   : Sized_relobj_base<size, big_endian>(name, NULL), ibase_(ibase),
     input_file_index_(input_file_index),
     input_reader_(ibase->inputs_reader().input_file(input_file_index)),
+    local_symbol_count_(0), output_local_dynsym_count_(0),
+    local_symbol_index_(0), local_symbol_offset_(0), local_dynsym_offset_(0),
     symbols_(), section_offsets_(), incr_reloc_offset_(-1U),
-    incr_reloc_count_(0), incr_reloc_output_index_(0), incr_relocs_(NULL)
+    incr_reloc_count_(0), incr_reloc_output_index_(0), incr_relocs_(NULL),
+    local_symbols_()
 {
   if (this->input_reader_.is_in_system_directory())
     this->set_is_in_system_directory();
@@ -1756,7 +1765,7 @@ Sized_incr_relobj<size, big_endian>::do_add_symbols(
   unsigned int isym_count = isymtab.symbol_count();
   unsigned int first_global = symtab_count - isym_count;
 
-  unsigned const char* sym_p;
+  const unsigned char* sym_p;
   for (unsigned int i = 0; i < nsyms; ++i)
     {
       Incremental_global_symbol_reader<big_endian> info =
@@ -2027,10 +2036,40 @@ Sized_incr_relobj<size, big_endian>::do_scan_relocs(Symbol_table*,
 template<int size, bool big_endian>
 void
 Sized_incr_relobj<size, big_endian>::do_count_local_symbols(
-    Stringpool_template<char>*,
+    Stringpool_template<char>* pool,
     Stringpool_template<char>*)
 {
-  // FIXME: Count local symbols.
+  const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
+
+  // Set the count of local symbols based on the incremental info.
+  unsigned int nlocals = this->input_reader_.get_local_symbol_count();
+  this->local_symbol_count_ = nlocals;
+  this->local_symbols_.reserve(nlocals);
+
+  // Get views of the base file's symbol table and string table.
+  Incremental_binary::View symtab_view(NULL);
+  unsigned int symtab_count;
+  elfcpp::Elf_strtab strtab(NULL, 0);
+  this->ibase_->get_symtab_view(&symtab_view, &symtab_count, &strtab);
+
+  // Read the local symbols from the base file's symbol table.
+  off_t off = this->input_reader_.get_local_symbol_offset();
+  const unsigned char* symp = symtab_view.data() + off;
+  for (unsigned int i = 0; i < nlocals; ++i, symp += sym_size)
+    {
+      elfcpp::Sym<size, big_endian> sym(symp);
+      const char* name;
+      if (!strtab.get_c_string(sym.get_st_name(), &name))
+        name = "";
+      gold_debug(DEBUG_INCREMENTAL, "Local symbol %d: %s", i, name);
+      name = pool->add(name, true, NULL);
+      this->local_symbols_.push_back(Local_symbol(name,
+                                                 sym.get_st_value(),
+                                                 sym.get_st_size(),
+                                                 sym.get_st_shndx(),
+                                                 sym.get_st_type(),
+                                                 false));
+    }
 }
 
 // Finalize the local symbols.
@@ -2039,11 +2078,12 @@ template<int size, bool big_endian>
 unsigned int
 Sized_incr_relobj<size, big_endian>::do_finalize_local_symbols(
     unsigned int index,
-    off_t,
+    off_t off,
     Symbol_table*)
 {
-  // FIXME: Finalize local symbols.
-  return index;
+  this->local_symbol_index_ = index;
+  this->local_symbol_offset_ = off;
+  return index + this->local_symbol_count_;
 }
 
 // Set the offset where local dynamic symbol information will be stored.
@@ -2109,6 +2149,91 @@ Sized_incr_relobj<size, big_endian>::do_relocate(const Symbol_table*,
     }
 
   of->write_output_view(off, len, view);
+
+  // Get views into the output file for the portions of the symbol table
+  // and the dynamic symbol table that we will be writing.
+  off_t symtab_off = layout->symtab_section()->offset();
+  off_t output_size = this->local_symbol_count_ * This::sym_size;
+  unsigned char* oview = NULL;
+  if (output_size > 0)
+    oview = of->get_output_view(symtab_off + this->local_symbol_offset_,
+                               output_size);
+
+  off_t dyn_output_size = this->output_local_dynsym_count_ * sym_size;
+  unsigned char* dyn_oview = NULL;
+  if (dyn_output_size > 0)
+    dyn_oview = of->get_output_view(this->local_dynsym_offset_,
+                                    dyn_output_size);
+
+  // Write the local symbols.
+  unsigned char* ov = oview;
+  unsigned char* dyn_ov = dyn_oview;
+  const Stringpool* sympool = layout->sympool();
+  const Stringpool* dynpool = layout->dynpool();
+  Output_symtab_xindex* symtab_xindex = layout->symtab_xindex();
+  Output_symtab_xindex* dynsym_xindex = layout->dynsym_xindex();
+  for (unsigned int i = 0; i < this->local_symbol_count_; ++i)
+    {
+      Local_symbol& lsym(this->local_symbols_[i]);
+
+      bool is_ordinary;
+      unsigned int st_shndx = this->adjust_sym_shndx(i, lsym.st_shndx,
+                                                    &is_ordinary);
+      if (is_ordinary)
+       {
+         Output_section* os = this->ibase_->output_section(st_shndx);
+         st_shndx = os->out_shndx();
+         if (st_shndx >= elfcpp::SHN_LORESERVE)
+           {
+             symtab_xindex->add(this->local_symbol_index_ + i, st_shndx);
+             if (lsym.needs_dynsym_entry)
+               dynsym_xindex->add(lsym.output_dynsym_index, st_shndx);
+             st_shndx = elfcpp::SHN_XINDEX;
+           }
+       }
+
+      // Write the symbol to the output symbol table.
+      {
+       elfcpp::Sym_write<size, big_endian> osym(ov);
+       osym.put_st_name(sympool->get_offset(lsym.name));
+       osym.put_st_value(lsym.st_value);
+       osym.put_st_size(lsym.st_size);
+       osym.put_st_info(elfcpp::STB_LOCAL,
+                        static_cast<elfcpp::STT>(lsym.st_type));
+       osym.put_st_other(0);
+       osym.put_st_shndx(st_shndx);
+       ov += sym_size;
+      }
+
+      // Write the symbol to the output dynamic symbol table.
+      if (lsym.needs_dynsym_entry)
+        {
+          gold_assert(dyn_ov < dyn_oview + dyn_output_size);
+          elfcpp::Sym_write<size, big_endian> osym(dyn_ov);
+          osym.put_st_name(dynpool->get_offset(lsym.name));
+          osym.put_st_value(lsym.st_value);
+          osym.put_st_size(lsym.st_size);
+         osym.put_st_info(elfcpp::STB_LOCAL,
+                          static_cast<elfcpp::STT>(lsym.st_type));
+          osym.put_st_other(0);
+          osym.put_st_shndx(st_shndx);
+          dyn_ov += sym_size;
+        }
+    }
+
+  if (output_size > 0)
+    {
+      gold_assert(ov - oview == output_size);
+      of->write_output_view(symtab_off + this->local_symbol_offset_,
+                           output_size, oview);
+    }
+
+  if (dyn_output_size > 0)
+    {
+      gold_assert(dyn_ov - dyn_oview == dyn_output_size);
+      of->write_output_view(this->local_dynsym_offset_, dyn_output_size,
+                            dyn_oview);
+    }
 }
 
 // Set the offset of a section.
@@ -2187,7 +2312,7 @@ Sized_incr_dynobj<size, big_endian>::do_add_symbols(
   unsigned int isym_count = isymtab.symbol_count();
   unsigned int first_global = symtab_count - isym_count;
 
-  unsigned const char* sym_p;
+  const unsigned char* sym_p;
   for (unsigned int i = 0; i < nsyms; ++i)
     {
       bool is_def;
index dad5d66..41ae188 100644 (file)
@@ -725,7 +725,7 @@ class Incremental_inputs_reader
                  || this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER);
 
       unsigned int section_count = this->get_input_section_count();
-      return (this->info_offset_ + 8
+      return (this->info_offset_ + 16
              + section_count * input_section_entry_size
              + symndx * 20);
     }
@@ -746,6 +746,26 @@ class Incremental_inputs_reader
        }
     }
 
+    // Return the offset of the first local symbol -- for objects only.
+    unsigned int
+    get_local_symbol_offset() const
+    {
+      gold_assert(this->type() == INCREMENTAL_INPUT_OBJECT
+                 || this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER);
+
+      return Swap32::readval(this->inputs_->p_ + this->info_offset_ + 8);
+    }
+
+    // Return the local symbol count -- for objects only.
+    unsigned int
+    get_local_symbol_count() const
+    {
+      gold_assert(this->type() == INCREMENTAL_INPUT_OBJECT
+                 || this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER);
+
+      return Swap32::readval(this->inputs_->p_ + this->info_offset_ + 12);
+    }
+
     // Return the object count -- for scripts only.
     unsigned int
     get_object_count() const
@@ -816,7 +836,7 @@ class Incremental_inputs_reader
     {
       Input_section_info info;
       const unsigned char* p = (this->inputs_->p_
-                               + this->info_offset_ + 8
+                               + this->info_offset_ + 16
                                + n * input_section_entry_size);
       unsigned int name_offset = Swap32::readval(p);
       info.name = this->inputs_->get_string(name_offset);
@@ -834,7 +854,7 @@ class Incremental_inputs_reader
                  || this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER);
       unsigned int section_count = this->get_input_section_count();
       const unsigned char* p = (this->inputs_->p_
-                               + this->info_offset_ + 8
+                               + this->info_offset_ + 16
                                + section_count * input_section_entry_size
                                + n * 20);
       return Incremental_global_symbol_reader<big_endian>(p);
@@ -1522,12 +1542,42 @@ class Sized_incr_relobj : public Sized_relobj_base<size, big_endian>
   }
 
  private:
+  // For convenience.
+  typedef Sized_incr_relobj<size, big_endian> This;
+  static const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
+
   typedef typename Sized_relobj_base<size, big_endian>::Output_sections
       Output_sections;
   typedef Incremental_inputs_reader<size, big_endian> Inputs_reader;
   typedef typename Inputs_reader::Incremental_input_entry_reader
       Input_entry_reader;
 
+  // A local symbol.
+  struct Local_symbol
+  {
+    Local_symbol(const char* name_, Address value_, unsigned int size_,
+                unsigned int shndx_, unsigned int type_,
+                bool needs_dynsym_entry_)
+      : st_value(value_), name(name_), st_size(size_), st_shndx(shndx_),
+       st_type(type_), output_dynsym_index(0),
+       needs_dynsym_entry(needs_dynsym_entry_)
+    { }
+    // The symbol value.
+    Address st_value;
+    // The symbol name.  This points to the stringpool entry.
+    const char* name;
+    // The symbol size.
+    unsigned int st_size;
+    // The output section index.
+    unsigned int st_shndx : 28;
+    // The symbol type.
+    unsigned int st_type : 4;
+    // The index of the symbol in the output dynamic symbol table.
+    unsigned int output_dynsym_index : 31;
+    // TRUE if the symbol needs to appear in the dynamic symbol table.
+    unsigned int needs_dynsym_entry : 1;
+  };
+
   // Return TRUE if this is an incremental (unchanged) input file.
   bool
   do_is_incremental() const
@@ -1625,7 +1675,17 @@ class Sized_incr_relobj : public Sized_relobj_base<size, big_endian>
   // Return the number of local symbols.
   unsigned int
   do_local_symbol_count() const
-  { return 0; }
+  { return this->local_symbol_count_; }
+
+  // Return the number of local symbols in the output symbol table.
+  unsigned int
+  do_output_local_symbol_count() const
+  { return this->local_symbol_count_; }
+
+  // Return the file offset for local symbols in the output symbol table.
+  off_t
+  do_local_symbol_offset() const
+  { return this->local_symbol_offset_; }
 
   // Read the relocs.
   void
@@ -1671,6 +1731,17 @@ class Sized_incr_relobj : public Sized_relobj_base<size, big_endian>
   unsigned int input_file_index_;
   // The reader for the input file.
   Input_entry_reader input_reader_;
+  // The number of local symbols.
+  unsigned int local_symbol_count_;
+  // The number of local symbols which go into the output file's dynamic
+  // symbol table.
+  unsigned int output_local_dynsym_count_;
+  // This starting symbol index in the output symbol table.
+  unsigned int local_symbol_index_;
+  // The file offset for local symbols in the output symbol table.
+  unsigned int local_symbol_offset_;
+  // The file offset for local symbols in the output symbol table.
+  unsigned int local_dynsym_offset_;
   // The entries in the symbol table for the external symbols.
   Symbols symbols_;
   // For each input section, the offset of the input section in its
@@ -1686,6 +1757,8 @@ class Sized_incr_relobj : public Sized_relobj_base<size, big_endian>
   unsigned int incr_reloc_output_index_;
   // A copy of the incremental relocations from this object.
   unsigned char* incr_relocs_;
+  // The local symbols.
+  std::vector<Local_symbol> local_symbols_;
 };
 
 // An incremental Dynobj.  This class represents a shared object that has
index c814e76..dc56136 100644 (file)
@@ -987,6 +987,16 @@ class Relobj : public Object
   local_symbol_count() const
   { return this->do_local_symbol_count(); }
 
+  // The number of local symbols in the output symbol table.
+  virtual unsigned int
+  output_local_symbol_count() const
+  { return this->do_output_local_symbol_count(); }
+
+  // The file offset for local symbols in the output symbol table.
+  virtual off_t
+  local_symbol_offset() const
+  { return this->do_local_symbol_offset(); }
+
   // Initial local symbol processing: count the number of local symbols
   // in the output symbol table and dynamic symbol table; add local symbol
   // names to *POOL and *DYNPOOL.
@@ -1115,6 +1125,14 @@ class Relobj : public Object
   virtual unsigned int
   do_local_symbol_count() const = 0;
 
+  // Return the number of output local symbols--implemented by child class.
+  virtual unsigned int
+  do_output_local_symbol_count() const = 0;
+
+  // Return the file offset for local symbols--implemented by child class.
+  virtual off_t
+  do_local_symbol_offset() const = 0;
+
   // Count local symbols--implemented by child class.
   virtual void
   do_count_local_symbols(Stringpool_template<char>*,
@@ -1911,6 +1929,16 @@ class Sized_relobj : public Sized_relobj_base<size, big_endian>
   do_local_symbol_count() const
   { return this->local_symbol_count_; }
 
+  // Return the number of local symbols in the output symbol table.
+  unsigned int
+  do_output_local_symbol_count() const
+  { return this->output_local_symbol_count_; }
+
+  // Return the number of local symbols in the output symbol table.
+  off_t
+  do_local_symbol_offset() const
+  { return this->local_symbol_offset_; }
+
   // Lay out the input sections.
   void
   do_layout(Symbol_table*, Layout*, Read_symbols_data*);