2013-07-22 Sterling Augustine <saugustine@google.com>
authorSterling Augustine <saugustine@google.com>
Mon, 29 Jul 2013 18:29:12 +0000 (18:29 +0000)
committerSterling Augustine <saugustine@google.com>
Mon, 29 Jul 2013 18:29:12 +0000 (18:29 +0000)
* dwarf_reader.cc (Dwarf_pubnames_table::read_section):
Convert parameter shndx to local variable. Add parameters symtab
and symtab_size.  Scan over section names.  Find relocation
section corresponding to current section.  Create and initialize
reloc_mapper_ and reloc_type_.
(Dwarf_pubnames_table::read_header):  Add assertion.  Change
unit_length to off_t.  Initialize member unit_length_.  Fill in field
cu_offset_.
* dwarf_reader.h (Dwarf_pubnames_table::Dwarf_pubnames_table):
Initialize new fields unit_length_ and cu_offset_.
(Dwarf_pubnames_table::read_section): Update prototype.
(Dwarf_pubnames_table::cu_offset): New member function.
(Dwarf_pubnames_table::subsection_size): Likewise.
(Dwarf_pubnames_table::cu_offset_, Dwarf_pubnames_table::unit_length):
New fields.
(Dwarf_info_reader::symtab, Dwarf_info_reader::symtab_size): Make
member functions public.
* gdb_index.cc (Gdb_index_info_reader::read_pubnames_and_pubtypes):
Update comment.  Rework logic.  Move repeated parts to...
(Gdb_index_info_reader::read_pubtable): ...here. New function.
(Gdb_index::Gdb_index): Initialize new fields, pubnames_table_,
pubtypes_table_, and stmt_list_offset.
(Gdb_index::map_pubtable_to_dies, Gdb_index::find_pubname_offset,
Gdb_index::find_pubtype_offset,
Gdb_index::map_pubnames_and_types_to_dies): Define new functions.
(Gdb_index::pubnames_read): Update prototype and rework logic.
* gdb_index.h (Gdb_index_info_reader, Dwarf_pubnames_table):
Forward declare.
(Gdb_index::map_pubtable_to_dies, Gdb_index::find_pubname_offset,
Gdb_index::find_pubtype_offset, Gdb_index::pubnames_table)
Gdb_index::pubtypes_table, Gdb_index::map_pubnames_and_types_to_dies,
Gdb_index::map_pubtable_to_dies):
Declare functions.
(Gdb_index::pubnames_read): Update declaration.
(Gdb_index::Pubname_offset_map): New type.
(Gdb_index::cu_pubname_map_, Gdb_index::cu_pubtype_map_,
Gdb_index::pubnames_table_, Gdb_index::pubtypes_table_,
Gdb_index::stmt_list_offset): Declare.
(Gdb_index::pubnames_shndx_, Gdb_index::pubnames_offet_,
Gdb_index::pubtypes_object_, Gdb_index::pubtypes_shndx_)
Gdb_index::pubtypes_offset_): Remove.

gold/ChangeLog
gold/dwarf_reader.cc
gold/dwarf_reader.h
gold/gdb-index.cc
gold/gdb-index.h

index 676b670..e6e75d3 100644 (file)
@@ -1,3 +1,47 @@
+2013-07-22  Sterling Augustine  <saugustine@google.com>
+
+       * dwarf_reader.cc (Dwarf_pubnames_table::read_section):
+       Convert parameter shndx to local variable. Add parameters symtab
+       and symtab_size.  Scan over section names.  Find relocation
+       section corresponding to current section.  Create and initialize
+       reloc_mapper_ and reloc_type_.
+       (Dwarf_pubnames_table::read_header):  Add assertion.  Change
+       unit_length to off_t.  Initialize member unit_length_.  Fill in field
+       cu_offset_.
+       * dwarf_reader.h (Dwarf_pubnames_table::Dwarf_pubnames_table):
+       Initialize new fields unit_length_ and cu_offset_.
+       (Dwarf_pubnames_table::read_section): Update prototype.
+       (Dwarf_pubnames_table::cu_offset): New member function.
+       (Dwarf_pubnames_table::subsection_size): Likewise.
+       (Dwarf_pubnames_table::cu_offset_, Dwarf_pubnames_table::unit_length):
+       New fields.
+       (Dwarf_info_reader::symtab, Dwarf_info_reader::symtab_size): Make
+       member functions public.
+       * gdb_index.cc (Gdb_index_info_reader::read_pubnames_and_pubtypes):
+       Update comment.  Rework logic.  Move repeated parts to...
+       (Gdb_index_info_reader::read_pubtable): ...here. New function.
+       (Gdb_index::Gdb_index): Initialize new fields, pubnames_table_,
+       pubtypes_table_, and stmt_list_offset.
+       (Gdb_index::map_pubtable_to_dies, Gdb_index::find_pubname_offset,
+       Gdb_index::find_pubtype_offset,
+       Gdb_index::map_pubnames_and_types_to_dies): Define new functions.
+       (Gdb_index::pubnames_read): Update prototype and rework logic.
+       * gdb_index.h (Gdb_index_info_reader, Dwarf_pubnames_table):
+       Forward declare.
+       (Gdb_index::map_pubtable_to_dies, Gdb_index::find_pubname_offset,
+       Gdb_index::find_pubtype_offset, Gdb_index::pubnames_table)
+       Gdb_index::pubtypes_table, Gdb_index::map_pubnames_and_types_to_dies,
+       Gdb_index::map_pubtable_to_dies):
+       Declare functions.
+       (Gdb_index::pubnames_read): Update declaration.
+       (Gdb_index::Pubname_offset_map): New type.
+       (Gdb_index::cu_pubname_map_, Gdb_index::cu_pubtype_map_,
+       Gdb_index::pubnames_table_, Gdb_index::pubtypes_table_,
+       Gdb_index::stmt_list_offset): Declare.
+       (Gdb_index::pubnames_shndx_, Gdb_index::pubnames_offet_,
+       Gdb_index::pubtypes_object_, Gdb_index::pubtypes_shndx_)
+       Gdb_index::pubtypes_offset_): Remove.
+
 2013-07-19  Roland McGrath  <mcgrathr@google.com>
 
        * options.h (General_options): Add -Trodata-segment option.
 2013-07-19  Roland McGrath  <mcgrathr@google.com>
 
        * options.h (General_options): Add -Trodata-segment option.
index 4233954..3aad27f 100644 (file)
@@ -478,32 +478,31 @@ Dwarf_ranges_table::lookup_reloc(off_t off, off_t* target_off)
 
 // class Dwarf_pubnames_table
 
 
 // class Dwarf_pubnames_table
 
-// Read the pubnames section SHNDX from the object file.
+// Read the pubnames section from the object file.
 
 bool
 
 bool
-Dwarf_pubnames_table::read_section(Relobj* object, unsigned int shndx)
+Dwarf_pubnames_table::read_section(Relobj* object, const unsigned char* symtab,
+                                   off_t symtab_size)
 {
   section_size_type buffer_size;
 {
   section_size_type buffer_size;
+  unsigned int shndx = 0;
 
 
-  // If we don't have relocations, shndx will be 0, and
-  // we'll have to hunt for the .debug_pubnames/pubtypes section.
-  if (shndx == 0)
+  // Find the .debug_pubnames/pubtypes section.
+  const char* name = (this->is_pubtypes_
+                      ? ".debug_pubtypes"
+                      : ".debug_pubnames");
+  for (unsigned int i = 1; i < object->shnum(); ++i)
     {
     {
-      const char* name = (this->is_pubtypes_
-                         ? ".debug_pubtypes"
-                         : ".debug_pubnames");
-      for (unsigned int i = 1; i < object->shnum(); ++i)
-       {
-         if (object->section_name(i) == name)
-           {
-             shndx = i;
-             this->output_section_offset_ = object->output_section_offset(i);
-             break;
-           }
-       }
-      if (shndx == 0)
-       return false;
+      if (object->section_name(i) == name)
+        {
+          shndx = i;
+          this->output_section_offset_ = object->output_section_offset(i);
+          break;
+        }
     }
     }
+  if (shndx == 0)
+    return false;
+
 
   this->buffer_ = object->decompressed_section_contents(shndx,
                                                        &buffer_size,
 
   this->buffer_ = object->decompressed_section_contents(shndx,
                                                        &buffer_size,
@@ -511,6 +510,30 @@ Dwarf_pubnames_table::read_section(Relobj* object, unsigned int shndx)
   if (this->buffer_ == NULL)
     return false;
   this->buffer_end_ = this->buffer_ + buffer_size;
   if (this->buffer_ == NULL)
     return false;
   this->buffer_end_ = this->buffer_ + buffer_size;
+
+  // For incremental objects, we have no relocations.
+  if (object->is_incremental())
+    return true;
+
+  // Find the relocation section
+  unsigned int reloc_shndx = 0;
+  unsigned int reloc_type = 0;
+  for (unsigned int i = 0; i < object->shnum(); ++i)
+    {
+      reloc_type = object->section_type(i);
+      if ((reloc_type == elfcpp::SHT_REL
+          || reloc_type == elfcpp::SHT_RELA)
+         && object->section_info(i) == shndx)
+       {
+         reloc_shndx = i;
+         break;
+       }
+    }
+
+  this->reloc_mapper_ = make_elf_reloc_mapper(object, symtab, symtab_size);
+  this->reloc_mapper_->initialize(reloc_shndx, reloc_type);
+  this->reloc_type_ = reloc_type;
+
   return true;
 }
 
   return true;
 }
 
@@ -519,6 +542,9 @@ Dwarf_pubnames_table::read_section(Relobj* object, unsigned int shndx)
 bool
 Dwarf_pubnames_table::read_header(off_t offset)
 {
 bool
 Dwarf_pubnames_table::read_header(off_t offset)
 {
+  // Make sure we have actually read the section.
+  gold_assert(this->buffer_ != NULL);
+
   // Correct the offset.  For incremental update links, we have a
   // relocated offset that is relative to the output section, but
   // here we need an offset relative to the input section.
   // Correct the offset.  For incremental update links, we have a
   // relocated offset that is relative to the output section, but
   // here we need an offset relative to the input section.
@@ -530,16 +556,20 @@ Dwarf_pubnames_table::read_header(off_t offset)
   const unsigned char* pinfo = this->buffer_ + offset;
 
   // Read the unit_length field.
   const unsigned char* pinfo = this->buffer_ + offset;
 
   // Read the unit_length field.
-  uint32_t unit_length = this->dwinfo_->read_from_pointer<32>(pinfo);
+  uint64_t unit_length = this->dwinfo_->read_from_pointer<32>(pinfo);
   pinfo += 4;
   if (unit_length == 0xffffffff)
     {
       unit_length = this->dwinfo_->read_from_pointer<64>(pinfo);
   pinfo += 4;
   if (unit_length == 0xffffffff)
     {
       unit_length = this->dwinfo_->read_from_pointer<64>(pinfo);
+      this->unit_length_ = unit_length + 12;
       pinfo += 8;
       this->offset_size_ = 8;
     }
   else
       pinfo += 8;
       this->offset_size_ = 8;
     }
   else
-    this->offset_size_ = 4;
+    {
+      this->unit_length_ = unit_length + 4;
+      this->offset_size_ = 4;
+    }
 
   // Check the version.
   unsigned int version = this->dwinfo_->read_from_pointer<16>(pinfo);
 
   // Check the version.
   unsigned int version = this->dwinfo_->read_from_pointer<16>(pinfo);
@@ -547,6 +577,9 @@ Dwarf_pubnames_table::read_header(off_t offset)
   if (version != 2)
     return false;
 
   if (version != 2)
     return false;
 
+  this->reloc_mapper_->get_reloc_target(pinfo - this->buffer_,
+                                        &this->cu_offset_);
+
   // Skip the debug_info_offset and debug_info_size fields.
   pinfo += 2 * this->offset_size_;
 
   // Skip the debug_info_offset and debug_info_size fields.
   pinfo += 2 * this->offset_size_;
 
index 9ee483c..9cf22ff 100644 (file)
@@ -400,7 +400,7 @@ class Dwarf_pubnames_table
   Dwarf_pubnames_table(Dwarf_info_reader* dwinfo, bool is_pubtypes)
     : dwinfo_(dwinfo), buffer_(NULL), buffer_end_(NULL), owns_buffer_(false),
       offset_size_(0), pinfo_(NULL), is_pubtypes_(is_pubtypes),
   Dwarf_pubnames_table(Dwarf_info_reader* dwinfo, bool is_pubtypes)
     : dwinfo_(dwinfo), buffer_(NULL), buffer_end_(NULL), owns_buffer_(false),
       offset_size_(0), pinfo_(NULL), is_pubtypes_(is_pubtypes),
-      output_section_offset_(0)
+      output_section_offset_(0), unit_length_(0), cu_offset_(0)
   { }
 
   ~Dwarf_pubnames_table()
   { }
 
   ~Dwarf_pubnames_table()
@@ -409,14 +409,27 @@ class Dwarf_pubnames_table
       delete[] this->buffer_;
   }
 
       delete[] this->buffer_;
   }
 
-  // Read the pubnames section SHNDX from the object file.
+  // Read the pubnames section from the object file, using the symbol
+  // table for relocating it.
   bool
   bool
-  read_section(Relobj* object, unsigned int shndx);
+  read_section(Relobj* object, const unsigned char* symbol_table,
+               off_t symtab_size);
 
   // Read the header for the set at OFFSET.
   bool
   read_header(off_t offset);
 
 
   // Read the header for the set at OFFSET.
   bool
   read_header(off_t offset);
 
+  // Return the offset to the cu within the info or types section.
+  off_t
+  cu_offset()
+  { return this->cu_offset_; }
+
+  // Return the size of this subsection of the table.  The unit length
+  // doesn't include the size of its own field.
+  off_t
+  subsection_size()
+  { return this->unit_length_; }
+
   // Read the next name from the set.
   const char*
   next_name();
   // Read the next name from the set.
   const char*
   next_name();
@@ -440,6 +453,15 @@ class Dwarf_pubnames_table
   // relocated data will be relative to the output section, and need
   // to be corrected before reading data from the input section.
   uint64_t output_section_offset_;
   // relocated data will be relative to the output section, and need
   // to be corrected before reading data from the input section.
   uint64_t output_section_offset_;
+  // Fields read from the header.
+  uint64_t unit_length_;
+  off_t cu_offset_;
+
+  // Track relocations for this table so we can find the CUs that
+  // correspond to the subsections.
+  Elf_reloc_mapper* reloc_mapper_;
+  // Type of the relocation section (SHT_REL or SHT_RELA).
+  unsigned int reloc_type_;
 };
 
 // This class represents a DWARF Debug Info Entry (DIE).
 };
 
 // This class represents a DWARF Debug Info Entry (DIE).
@@ -747,6 +769,21 @@ class Dwarf_info_reader
   set_abbrev_shndx(unsigned int abbrev_shndx)
   { this->abbrev_shndx_ = abbrev_shndx; }
 
   set_abbrev_shndx(unsigned int abbrev_shndx)
   { this->abbrev_shndx_ = abbrev_shndx; }
 
+  // Return a pointer to the object file's ELF symbol table.
+  const unsigned char*
+  symtab() const
+  { return this->symtab_; }
+
+  // Return the size of the object file's ELF symbol table.
+  off_t
+  symtab_size() const
+  { return this->symtab_size_; }
+
+  // Return the offset of the current compilation unit.
+  off_t
+  cu_offset() const
+  { return this->cu_offset_; }
+
  protected:
   // Begin parsing the debug info.  This calls visit_compilation_unit()
   // or visit_type_unit() for each compilation or type unit found in the
  protected:
   // Begin parsing the debug info.  This calls visit_compilation_unit()
   // or visit_type_unit() for each compilation or type unit found in the
@@ -785,16 +822,6 @@ class Dwarf_info_reader
   object() const
   { return this->object_; }
 
   object() const
   { return this->object_; }
 
-  // Return a pointer to the object file's ELF symbol table.
-  const unsigned char*
-  symtab() const
-  { return this->symtab_; }
-
-  // Return the size of the object file's ELF symbol table.
-  off_t
-  symtab_size() const
-  { return this->symtab_size_; }
-
   // Checkpoint the relocation tracker.
   uint64_t
   get_reloc_checkpoint() const
   // Checkpoint the relocation tracker.
   uint64_t
   get_reloc_checkpoint() const
index 91634a4..d42fbbd 100644 (file)
@@ -273,10 +273,14 @@ class Gdb_index_info_reader : public Dwarf_info_reader
   void
   record_cu_ranges(Dwarf_die* die);
 
   void
   record_cu_ranges(Dwarf_die* die);
 
-  // Read the .debug_pubnames and .debug_pubtypes tables.
+  // Wrapper for read_pubtable.
   bool
   read_pubnames_and_pubtypes(Dwarf_die* die);
 
   bool
   read_pubnames_and_pubtypes(Dwarf_die* die);
 
+  // Read the .debug_pubnames and .debug_pubtypes tables.
+  bool
+  read_pubtable(Dwarf_pubnames_table* table, off_t offset);
+
   // Clear the declarations map.
   void
   clear_declarations();
   // Clear the declarations map.
   void
   clear_declarations();
@@ -851,69 +855,86 @@ Gdb_index_info_reader::record_cu_ranges(Dwarf_die* die)
     }
 }
 
     }
 }
 
-// Read the .debug_pubnames and .debug_pubtypes tables for the CU or TU.
-// Returns TRUE if either a pubnames or pubtypes section was found.
+// Read table and add the relevant names to the index.  Returns true
+// if any names were added.
 
 bool
 
 bool
-Gdb_index_info_reader::read_pubnames_and_pubtypes(Dwarf_die* die)
+Gdb_index_info_reader::read_pubtable(Dwarf_pubnames_table* table, off_t offset)
 {
 {
-  bool ret = false;
-
-  // If we find a DW_AT_GNU_pubnames attribute, read the pubnames table.
-  unsigned int pubnames_shndx;
-  off_t pubnames_offset = die->ref_attribute(elfcpp::DW_AT_GNU_pubnames,
-                                            &pubnames_shndx);
-  if (pubnames_offset != -1)
+  // If we couldn't read the section when building the cu_pubname_map,
+  // then we won't find any pubnames now.
+  if (table == NULL)
+    return false;
+
+  if (!table->read_header(offset))
+    return false;
+  while (true)
     {
     {
-      if (this->gdb_index_->pubnames_read(this->object(), pubnames_shndx,
-                                          pubnames_offset))
-       ret = true;
-      else
-       {
-         Dwarf_pubnames_table pubnames(this, false);
-         if (!pubnames.read_section(this->object(), pubnames_shndx))
-           return false;
-         if (!pubnames.read_header(pubnames_offset))
-           return false;
-         while (true)
-           {
-             const char* name = pubnames.next_name();
-             if (name == NULL)
-               break;
-             this->gdb_index_->add_symbol(this->cu_index_, name);
-           }
-         ret = true;
-       }
+      const char* name = table->next_name();
+      if (name == NULL)
+        break;
+
+      this->gdb_index_->add_symbol(this->cu_index_, name);
     }
     }
+  return true;
+}
+
+// Read the .debug_pubnames and .debug_pubtypes tables for the CU or TU.
+// Returns TRUE if either a pubnames or pubtypes section was found.
 
 
-  // If we find a DW_AT_GNU_pubtypes attribute, read the pubtypes table.
-  unsigned int pubtypes_shndx;
-  off_t pubtypes_offset = die->ref_attribute(elfcpp::DW_AT_GNU_pubtypes,
-                                            &pubtypes_shndx);
-  if (pubtypes_offset != -1)
+bool
+Gdb_index_info_reader::read_pubnames_and_pubtypes(Dwarf_die* die)
+{
+  // We use stmt_list_off as a unique identifier for the
+  // compilation unit and its associated type units.
+  unsigned int shndx;
+  off_t stmt_list_off = die->ref_attribute (elfcpp::DW_AT_stmt_list,
+                                            &shndx);
+  // Look for the attr as either a flag or a ref.
+  off_t offset = die->ref_attribute(elfcpp::DW_AT_GNU_pubnames, &shndx);
+
+  // Newer versions of GCC generate CUs, but not TUs, with
+  // DW_AT_FORM_flag_present.
+  unsigned int flag = die->uint_attribute(elfcpp::DW_AT_GNU_pubnames);
+  if (offset == -1 && flag == 0)
     {
     {
-      if (this->gdb_index_->pubtypes_read(this->object(),
-                                          pubtypes_shndx, pubtypes_offset))
-       ret = true;
+      // Didn't find the attribute.
+      if (die->tag() == elfcpp::DW_TAG_type_unit)
+        {
+          // If die is a TU, then it might correspond to a CU which we
+          // have read. If it does, then no need to read the pubnames.
+          // If it doesn't, then the caller will have to parse the
+          // dies manually to find the names.
+          return this->gdb_index_->pubnames_read(this->object(),
+                                                 stmt_list_off);
+        }
       else
       else
-       {
-         Dwarf_pubnames_table pubtypes(this, true);
-         if (!pubtypes.read_section(this->object(), pubtypes_shndx))
-           return false;
-         if (!pubtypes.read_header(pubtypes_offset))
-           return false;
-         while (true)
-           {
-             const char* name = pubtypes.next_name();
-             if (name == NULL)
-               break;
-             this->gdb_index_->add_symbol(this->cu_index_, name);
-           }
-         ret = true;
-       }
+        {
+          // No attribute on the CU means that no pubnames were read.
+          return false;
+        }
     }
 
     }
 
-  return ret;
+  // We found the attribute, so we can check if the corresponding
+  // pubnames have been read.
+  if (this->gdb_index_->pubnames_read(this->object(), stmt_list_off))
+    return true;
+
+  this->gdb_index_->set_pubnames_read(this->object(), stmt_list_off);
+
+  // We have an attribute, and the pubnames haven't been read, so read
+  // them.
+  bool names = false;
+  // In some of the cases, we could rely on the previous value of
+  // offset here, but sorting out which cases complicates the logic
+  // enough that it isn't worth it. So just look up the offset again.
+  offset = this->gdb_index_->find_pubname_offset(this->cu_offset());
+  names = this->read_pubtable(this->gdb_index_->pubnames_table(), offset);
+
+  bool types = false;
+  offset = this->gdb_index_->find_pubtype_offset(this->cu_offset());
+  types = this->read_pubtable(this->gdb_index_->pubtypes_table(), offset);
+  return names || types;
 }
 
 // Clear the declarations map.
 }
 
 // Clear the declarations map.
@@ -952,6 +973,8 @@ Gdb_index_info_reader::print_stats()
 
 Gdb_index::Gdb_index(Output_section* gdb_index_section)
   : Output_section_data(4),
 
 Gdb_index::Gdb_index(Output_section* gdb_index_section)
   : Output_section_data(4),
+    pubnames_table_(NULL),
+    pubtypes_table_(NULL),
     gdb_index_section_(gdb_index_section),
     comp_units_(),
     type_units_(),
     gdb_index_section_(gdb_index_section),
     comp_units_(),
     type_units_(),
@@ -965,11 +988,7 @@ Gdb_index::Gdb_index(Output_section* gdb_index_section)
     cu_pool_offset_(0),
     stringpool_offset_(0),
     pubnames_object_(NULL),
     cu_pool_offset_(0),
     stringpool_offset_(0),
     pubnames_object_(NULL),
-    pubnames_shndx_(0),
-    pubnames_offset_(0),
-    pubtypes_object_(NULL),
-    pubtypes_shndx_(0),
-    pubtypes_offset_(0)
+    stmt_list_offset_(-1)
 {
   this->gdb_symtab_ = new Gdb_hashtab<Gdb_symbol>();
 }
 {
   this->gdb_symtab_ = new Gdb_hashtab<Gdb_symbol>();
 }
@@ -983,6 +1002,93 @@ Gdb_index::~Gdb_index()
     delete this->cu_vector_list_[i];
 }
 
     delete this->cu_vector_list_[i];
 }
 
+
+// Scan the pubnames and pubtypes sections and build a map of the
+// various cus and tus they refer to, so we can process the entries
+// when we encounter the die for that cu or tu.
+// Return the just-read table so it can be cached.
+
+Dwarf_pubnames_table*
+Gdb_index::map_pubtable_to_dies(unsigned int attr,
+                                Gdb_index_info_reader* dwinfo,
+                                Relobj* object,
+                                const unsigned char* symbols,
+                                off_t symbols_size)
+{
+  uint64_t section_offset = 0;
+  Dwarf_pubnames_table* table;
+  Pubname_offset_map* map;
+
+  if (attr == elfcpp::DW_AT_GNU_pubnames)
+    {
+      table = new Dwarf_pubnames_table(dwinfo, false);
+      map = &this->cu_pubname_map_;
+    }
+  else
+    {
+      table = new Dwarf_pubnames_table(dwinfo, true);
+      map = &this->cu_pubtype_map_;
+    }
+
+  map->clear();
+  if (!table->read_section(object, symbols, symbols_size))
+    return NULL;
+
+  while (table->read_header(section_offset))
+    {
+      map->insert(std::make_pair(table->cu_offset(), section_offset));
+      section_offset += table->subsection_size();
+    }
+
+  return table;
+}
+
+// Wrapper for map_pubtable_to_dies
+
+void
+Gdb_index::map_pubnames_and_types_to_dies(Gdb_index_info_reader* dwinfo,
+                                          Relobj* object,
+                                          const unsigned char* symbols,
+                                          off_t symbols_size)
+{
+  // This is a new object, so reset the relevant variables.
+  this->pubnames_object_ = object;
+  this->stmt_list_offset_ = -1;
+
+  delete this->pubnames_table_;
+  this->pubnames_table_
+      = this->map_pubtable_to_dies(elfcpp::DW_AT_GNU_pubnames, dwinfo,
+                                   object, symbols, symbols_size);
+  delete this->pubtypes_table_;
+  this->pubtypes_table_
+      = this->map_pubtable_to_dies(elfcpp::DW_AT_GNU_pubtypes, dwinfo,
+                                   object, symbols, symbols_size);
+}
+
+// Given a cu_offset, find the associated section of the pubnames
+// table.
+
+off_t
+Gdb_index::find_pubname_offset(off_t cu_offset)
+{
+  Pubname_offset_map::iterator it = this->cu_pubname_map_.find(cu_offset);
+  if (it != this->cu_pubname_map_.end())
+    return it->second;
+  return -1;
+}
+
+// Given a cu_offset, find the associated section of the pubnames
+// table.
+
+off_t
+Gdb_index::find_pubtype_offset(off_t cu_offset)
+{
+  Pubname_offset_map::iterator it = this->cu_pubtype_map_.find(cu_offset);
+  if (it != this->cu_pubtype_map_.end())
+    return it->second;
+  return -1;
+}
+
 // Scan a .debug_info or .debug_types input section.
 
 void
 // Scan a .debug_info or .debug_types input section.
 
 void
@@ -998,6 +1104,8 @@ Gdb_index::scan_debug_info(bool is_type_unit,
                               symbols, symbols_size,
                               shndx, reloc_shndx,
                               reloc_type, this);
                               symbols, symbols_size,
                               shndx, reloc_shndx,
                               reloc_type, this);
+  if (object != this->pubnames_object_)
+    map_pubnames_and_types_to_dies(&dwinfo, object, symbols, symbols_size);
   dwinfo.parse();
 }
 
   dwinfo.parse();
 }
 
@@ -1035,34 +1143,25 @@ Gdb_index::add_symbol(int cu_index, const char* sym_name)
     cu_vec->push_back(cu_index);
 }
 
     cu_vec->push_back(cu_index);
 }
 
-// Return TRUE if we have already processed the pubnames set at
-// OFFSET in section SHNDX
+// Return TRUE if we have already processed the pubnames associated
+// with the statement list at the given OFFSET.
 
 bool
 
 bool
-Gdb_index::pubnames_read(const Relobj* object, unsigned int shndx, off_t offset)
+Gdb_index::pubnames_read(const Relobj* object, off_t offset)
 {
   bool ret = (this->pubnames_object_ == object
 {
   bool ret = (this->pubnames_object_ == object
-              && this->pubnames_shndx_ == shndx
-             && this->pubnames_offset_ == offset);
-  this->pubnames_object_ = object;
-  this->pubnames_shndx_ = shndx;
-  this->pubnames_offset_ = offset;
+             && this->stmt_list_offset_ == offset);
   return ret;
 }
 
   return ret;
 }
 
-// Return TRUE if we have already processed the pubtypes set at
-// OFFSET in section SHNDX
+// Record that we have processed the pubnames associated with the
+// statement list for OBJECT at the given OFFSET.
 
 
-bool
-Gdb_index::pubtypes_read(const Relobj* object, unsigned int shndx, off_t offset)
+void
+Gdb_index::set_pubnames_read(const Relobj* object, off_t offset)
 {
 {
-  bool ret = (this->pubtypes_object_ == object
-              && this->pubtypes_shndx_ == shndx
-             && this->pubtypes_offset_ == offset);
-  this->pubtypes_object_ = object;
-  this->pubtypes_shndx_ = shndx;
-  this->pubtypes_offset_ = offset;
-  return ret;
+  this->pubnames_object_ = object;
+  this->stmt_list_offset_ = offset;
 }
 
 // Set the size of the .gdb_index section.
 }
 
 // Set the size of the .gdb_index section.
index 14c1583..5d9fe47 100644 (file)
@@ -42,6 +42,8 @@ class Sized_relobj;
 class Dwarf_range_list;
 template <typename T>
 class Gdb_hashtab;
 class Dwarf_range_list;
 template <typename T>
 class Gdb_hashtab;
+class Gdb_index_info_reader;
+class Dwarf_pubnames_table;
 
 // This class manages the .gdb_index section, which is a fast
 // lookup table for DWARF information used by the gdb debugger.
 
 // This class manages the .gdb_index section, which is a fast
 // lookup table for DWARF information used by the gdb debugger.
@@ -91,15 +93,35 @@ class Gdb_index : public Output_section_data
   void
   add_symbol(int cu_index, const char* sym_name);
 
   void
   add_symbol(int cu_index, const char* sym_name);
 
-  // Return TRUE if we have already processed the pubnames set for
-  // OBJECT at OFFSET in section SHNDX
-  bool
-  pubnames_read(const Relobj* object, unsigned int shndx, off_t offset);
+  // Return the offset into the pubnames table for the cu at the given
+  // offset.
+  off_t
+  find_pubname_offset(off_t cu_offset);
+
+  // Return the offset into the pubtypes table for the cu at the
+  // given offset.
+  off_t
+  find_pubtype_offset(off_t cu_offset);
 
 
-  // Return TRUE if we have already processed the pubtypes set for
-  // OBJECT at OFFSET in section SHNDX
+  // Return TRUE if we have already processed the pubnames and types
+  // set for OBJECT of the CUs and TUS associated with the statement
+  // list at OFFSET.
   bool
   bool
-  pubtypes_read(const Relobj* object,  unsigned int shndx, off_t offset);
+  pubnames_read(const Relobj* object, off_t offset);
+
+  // Record that we have already read the pubnames associated with
+  // OBJECT and OFFSET.
+  void
+  set_pubnames_read(const Relobj* object, off_t offset);
+
+  // Return a pointer to the given table.
+  Dwarf_pubnames_table*
+  pubnames_table()
+  { return pubnames_table_; }
+
+  Dwarf_pubnames_table*
+  pubtypes_table()
+  { return pubtypes_table_; }
 
   // Print usage statistics.
   static void
 
   // Print usage statistics.
   static void
@@ -125,6 +147,21 @@ class Gdb_index : public Output_section_data
   do_print_to_mapfile(Mapfile* mapfile) const
   { mapfile->print_output_data(this, _("** gdb_index")); }
 
   do_print_to_mapfile(Mapfile* mapfile) const
   { mapfile->print_output_data(this, _("** gdb_index")); }
 
+  // Create a map from dies to pubnames.
+  Dwarf_pubnames_table*
+  map_pubtable_to_dies(unsigned int attr,
+                       Gdb_index_info_reader* dwinfo,
+                       Relobj* object,
+                       const unsigned char* symbols,
+                       off_t symbols_size);
+
+  // Wrapper for map_pubtable_to_dies
+  void
+  map_pubnames_and_types_to_dies(Gdb_index_info_reader* dwinfo,
+                                 Relobj* object,
+                                 const unsigned char* symbols,
+                                 off_t symbols_size);
+
  private:
   // An entry in the compilation unit list.
   struct Comp_unit
  private:
   // An entry in the compilation unit list.
   struct Comp_unit
@@ -178,6 +215,21 @@ class Gdb_index : public Output_section_data
 
   typedef std::vector<int> Cu_vector;
 
 
   typedef std::vector<int> Cu_vector;
 
+  typedef Unordered_map<off_t, off_t> Pubname_offset_map;
+  Pubname_offset_map cu_pubname_map_;
+  Pubname_offset_map cu_pubtype_map_;
+
+  // Scan the given pubtable and build a map of the various dies it
+  // refers to, so we can process the entries when we encounter the
+  // die.
+  void
+  map_pubtable_to_dies(Dwarf_pubnames_table* table,
+                       Pubname_offset_map* map);
+
+  // Tables to store the pubnames section of the current object.
+  Dwarf_pubnames_table* pubnames_table_;
+  Dwarf_pubnames_table* pubtypes_table_;
+
   // The .gdb_index section.
   Output_section* gdb_index_section_;
   // The list of DWARF compilation units.
   // The .gdb_index section.
   Output_section* gdb_index_section_;
   // The list of DWARF compilation units.
@@ -200,14 +252,10 @@ class Gdb_index : public Output_section_data
   off_t symtab_offset_;
   off_t cu_pool_offset_;
   off_t stringpool_offset_;
   off_t symtab_offset_;
   off_t cu_pool_offset_;
   off_t stringpool_offset_;
-  // Object, section index and offset of last read pubnames section.
+  // Object, stmt list offset of the CUs and TUs associated with the
+  // last read pubnames and pubtypes sections.
   const Relobj* pubnames_object_;
   const Relobj* pubnames_object_;
-  unsigned int pubnames_shndx_;
-  off_t pubnames_offset_;
-  // Object, section index and offset of last read pubtypes section.
-  const Relobj* pubtypes_object_;
-  unsigned int pubtypes_shndx_;
-  off_t pubtypes_offset_;
+  off_t stmt_list_offset_;
 };
 
 } // End namespace gold.
 };
 
 } // End namespace gold.