2015-03-21  Cary Coutant  <cary@google.com>

gold/
	* dwp.cc (Sized_relobj_dwo::do_section_contents): Delete.
	(Sized_relobj_dwo::setup): Build compressed section map.
	(Sized_relobj_dwo::do_decompressed_section_contents): Delete.
	* dynobj.cc (Sized_dynobj::base_read_symbols): Build compressed
	section map.
	* object.cc (Sized_relobj_file::Sized_relobj_file): Remove
	compressed_sections_ field.
	(build_compressed_section_map): Take Object instead of
	Sized_relobj_file parameter; add decompress_if_needed parameter.
	(Sized_relobj_file::do_find_special_sections): Store compressed
	section map in parent Object.
	(Sized_relobj_file::do_decompressed_section_contents): Move
	implementation to Object::decompressed_section_contents.
	(Sized_relobj_file::do_discard_decompressed_sections): Move
	implementation to Object::discard_decompressed_sections.
	* object.h (build_compressed_section_map): Declare.
	(Object::Object): Add compressed_sections_ field.
	(Object::section_is_compressed): Move implementation here.
	(Object::decompressed_section_contents): De-virtualize.
	(Object::discard_decompressed_sections): De-virtualize.
	(Object::do_section_is_compressed): Delete.
	(Object::do_decompressed_section_contents): Delete.
	(Object::set_compressed_sections): New method.
	(Object::compressed_sections): New method.
	(Object::compressed_sections_): New data member.
	(Compressed_section_info, Compressed_section_map): Move to top of file.
	(Sized_relobj_file::do_section_is_compressed): Delete.
	(Sized_relobj_file::do_decompressed_section_contents): Delete.
	(Sized_relobj_file::do_discard_decompressed_sections): Delete.
	(Sized_relobj_file::compressed_sections_): Move to Object class.


 gold/dwp.cc    |  72 ++++++++++++++---------------------
 gold/dynobj.cc |  11 ++++++
 gold/object.cc |  25 +++++++------
 gold/object.h  | 116 +++++++++++++++++++++------------------------------------
 4 files changed, 95 insertions(+), 129 deletions(-)

diff --git a/gold/dwp.cc b/gold/dwp.cc
index d5e19ef..16d471c 100644
--- a/gold/dwp.cc
+++ b/gold/dwp.cc
@@ -284,14 +284,6 @@ class Sized_relobj_dwo : public Sized_relobj<size, big_endian>
   const unsigned char*
   do_section_contents(unsigned int, section_size_type*, bool);
 
-  // Return a view of the uncompressed contents of a section.  Set *PLEN
-  // to the size.  Set *IS_NEW to true if the contents need to be deleted
-  // by the caller.
-  const unsigned char*
-  do_decompressed_section_contents(unsigned int shndx,
-				   section_size_type* plen,
-				   bool* is_new);
-
   // The following virtual functions are abstract in the base classes,
   // but are not used here.
 
@@ -781,9 +773,36 @@ template <int size, bool big_endian>
 void
 Sized_relobj_dwo<size, big_endian>::setup()
 {
+  const int shdr_size = elfcpp::Elf_sizes<size>::shdr_size;
+  const off_t shoff = this->elf_file_.shoff();
   const unsigned int shnum = this->elf_file_.shnum();
+
   this->set_shnum(shnum);
   this->section_offsets().resize(shnum);
+
+  // Read the section headers.
+  const unsigned char* const pshdrs = this->get_view(shoff, shnum * shdr_size,
+						     true, false);
+
+  // Read the section names.
+  const unsigned char* pshdrnames =
+      pshdrs + this->elf_file_.shstrndx() * shdr_size;
+  typename elfcpp::Shdr<size, big_endian> shdrnames(pshdrnames);
+  if (shdrnames.get_sh_type() != elfcpp::SHT_STRTAB)
+    this->error(_("section name section has wrong type: %u"),
+		static_cast<unsigned int>(shdrnames.get_sh_type()));
+  section_size_type section_names_size =
+      convert_to_section_size_type(shdrnames.get_sh_size());
+  const unsigned char* namesu = this->get_view(shdrnames.get_sh_offset(),
+					       section_names_size, false,
+					       false);
+  const char* names = reinterpret_cast<const char*>(namesu);
+
+  Compressed_section_map* compressed_sections =
+      build_compressed_section_map<size, big_endian>(
+	  pshdrs, this->shnum(), names, section_names_size, this, true);
+  if (compressed_sections != NULL && !compressed_sections->empty())
+    this->set_compressed_sections(compressed_sections);
 }
 
 // Return a view of the contents of a section.
@@ -805,43 +824,6 @@ Sized_relobj_dwo<size, big_endian>::do_section_contents(
   return this->get_view(loc.file_offset, *plen, true, cache);
 }
 
-// Return a view of the uncompressed contents of a section.  Set *PLEN
-// to the size.  Set *IS_NEW to true if the contents need to be deleted
-// by the caller.
-
-template <int size, bool big_endian>
-const unsigned char*
-Sized_relobj_dwo<size, big_endian>::do_decompressed_section_contents(
-    unsigned int shndx,
-    section_size_type* plen,
-    bool* is_new)
-{
-  section_size_type buffer_size;
-  const unsigned char* buffer = this->do_section_contents(shndx, &buffer_size,
-							  false);
-
-  std::string sect_name = this->do_section_name(shndx);
-  if (!is_prefix_of(".zdebug_", sect_name.c_str()))
-    {
-      *plen = buffer_size;
-      *is_new = false;
-      return buffer;
-    }
-
-  section_size_type uncompressed_size = get_uncompressed_size(buffer,
-							      buffer_size);
-  unsigned char* uncompressed_data = new unsigned char[uncompressed_size];
-  if (!decompress_input_section(buffer,
-				buffer_size,
-				uncompressed_data,
-				uncompressed_size))
-    this->error(_("could not decompress section %s"),
-		this->section_name(shndx).c_str());
-  *plen = uncompressed_size;
-  *is_new = true;
-  return uncompressed_data;
-}
-
 // Class Dwo_file.
 
 Dwo_file::~Dwo_file()
diff --git a/gold/dynobj.cc b/gold/dynobj.cc
index 8bf6251..13e3f61 100644
--- a/gold/dynobj.cc
+++ b/gold/dynobj.cc
@@ -374,6 +374,17 @@ Sized_dynobj<size, big_endian>::base_read_symbols(Read_symbols_data* sd)
   sd->verneed_size = 0;
   sd->verneed_info = 0;
 
+  const unsigned char* namesu = sd->section_names->data();
+  const char* names = reinterpret_cast<const char*>(namesu);
+  if (memmem(names, sd->section_names_size, ".zdebug_", 8) != NULL)
+    {
+      Compressed_section_map* compressed_sections =
+	  build_compressed_section_map<size, big_endian>(
+	      pshdrs, this->shnum(), names, sd->section_names_size, this, true);
+      if (compressed_sections != NULL)
+        this->set_compressed_sections(compressed_sections);
+    }
+
   if (this->dynsym_shndx_ != -1U)
     {
       // Get the dynamic symbols.
diff --git a/gold/object.cc b/gold/object.cc
index 8f16fe7..50ca739 100644
--- a/gold/object.cc
+++ b/gold/object.cc
@@ -432,8 +432,7 @@ Sized_relobj_file<size, big_endian>::Sized_relobj_file(
     discarded_eh_frame_shndx_(-1U),
     is_deferred_layout_(false),
     deferred_layout_(),
-    deferred_layout_relocs_(),
-    compressed_sections_()
+    deferred_layout_relocs_()
 {
   this->e_type_ = ehdr.get_e_type();
 }
@@ -675,7 +674,8 @@ build_compressed_section_map(
     unsigned int shnum,
     const char* names,
     section_size_type names_size,
-    Sized_relobj_file<size, big_endian>* obj)
+    Object* obj,
+    bool decompress_if_needed)
 {
   Compressed_section_map* uncompressed_map = new Compressed_section_map();
   const unsigned int shdr_size = elfcpp::Elf_sizes<size>::shdr_size;
@@ -707,7 +707,7 @@ build_compressed_section_map(
 	      if (uncompressed_size != -1ULL)
 		{
 		  unsigned char* uncompressed_data = NULL;
-		  if (need_decompressed_section(name))
+		  if (decompress_if_needed && need_decompressed_section(name))
 		    {
 		      uncompressed_data = new unsigned char[uncompressed_size];
 		      if (decompress_input_section(contents, len,
@@ -741,9 +741,14 @@ Sized_relobj_file<size, big_endian>::do_find_special_sections(
     this->has_eh_frame_ = true;
 
   if (memmem(names, sd->section_names_size, ".zdebug_", 8) != NULL)
-    this->compressed_sections_
-      = build_compressed_section_map(pshdrs, this->shnum(), names,
-				     sd->section_names_size, this);
+    {
+      Compressed_section_map* compressed_sections =
+	  build_compressed_section_map<size, big_endian>(
+	      pshdrs, this->shnum(), names, sd->section_names_size, this, true);
+      if (compressed_sections != NULL)
+        this->set_compressed_sections(compressed_sections);
+    }
+
   return (this->has_eh_frame_
 	  || (!parameters->options().relocatable()
 	      && parameters->options().gdb_index()
@@ -2804,9 +2809,8 @@ Sized_relobj_file<size, big_endian>::do_get_global_symbol_counts(
 // to the size.  Set *IS_NEW to true if the contents need to be freed
 // by the caller.
 
-template<int size, bool big_endian>
 const unsigned char*
-Sized_relobj_file<size, big_endian>::do_decompressed_section_contents(
+Object::decompressed_section_contents(
     unsigned int shndx,
     section_size_type* plen,
     bool* is_new)
@@ -2860,9 +2864,8 @@ Sized_relobj_file<size, big_endian>::do_decompressed_section_contents(
 // Discard any buffers of uncompressed sections.  This is done
 // at the end of the Add_symbols task.
 
-template<int size, bool big_endian>
 void
-Sized_relobj_file<size, big_endian>::do_discard_decompressed_sections()
+Object::discard_decompressed_sections()
 {
   if (this->compressed_sections_ == NULL)
     return;
diff --git a/gold/object.h b/gold/object.h
index cce6c8c..ef1065d 100644
--- a/gold/object.h
+++ b/gold/object.h
@@ -314,6 +314,21 @@ class Got_offset_list
   Got_offset_list* got_next_;
 };
 
+// Type for mapping section index to uncompressed size and contents.
+
+struct Compressed_section_info
+{
+  section_size_type size;
+  const unsigned char* contents;
+};
+typedef std::map<unsigned int, Compressed_section_info> Compressed_section_map;
+
+template<int size, bool big_endian>
+Compressed_section_map*
+build_compressed_section_map(const unsigned char* pshdrs, unsigned int shnum,
+			     const char* names, section_size_type names_size,
+			     Object* obj, bool decompress_if_needed);
+
 // Object is an abstract base class which represents either a 32-bit
 // or a 64-bit input object.  This can be a regular object file
 // (ET_REL) or a shared object (ET_DYN).
@@ -332,7 +347,8 @@ class Object
     : name_(name), input_file_(input_file), offset_(offset), shnum_(-1U),
       is_dynamic_(is_dynamic), is_needed_(false), uses_split_stack_(false),
       has_no_split_stack_(false), no_export_(false),
-      is_in_system_directory_(false), as_needed_(false), xindex_(NULL)
+      is_in_system_directory_(false), as_needed_(false), xindex_(NULL),
+      compressed_sections_(NULL)
   {
     if (input_file != NULL)
       {
@@ -725,26 +741,34 @@ class Object
   set_no_export(bool value)
   { this->no_export_ = value; }
 
-  // Return TRUE if the section is a compressed debug section, and set
-  // *UNCOMPRESSED_SIZE to the size of the uncompressed data.
   bool
   section_is_compressed(unsigned int shndx,
 			section_size_type* uncompressed_size) const
-  { return this->do_section_is_compressed(shndx, uncompressed_size); }
+  {
+    if (this->compressed_sections_ == NULL)
+      return false;
+    Compressed_section_map::const_iterator p =
+        this->compressed_sections_->find(shndx);
+    if (p != this->compressed_sections_->end())
+      {
+	if (uncompressed_size != NULL)
+	  *uncompressed_size = p->second.size;
+	return true;
+      }
+    return false;
+  }
 
   // Return a view of the decompressed contents of a section.  Set *PLEN
   // to the size.  Set *IS_NEW to true if the contents need to be freed
   // by the caller.
   const unsigned char*
   decompressed_section_contents(unsigned int shndx, section_size_type* plen,
-				bool* is_cached)
-  { return this->do_decompressed_section_contents(shndx, plen, is_cached); }
+				bool* is_cached);
 
   // Discard any buffers of decompressed sections.  This is done
   // at the end of the Add_symbols task.
   void
-  discard_decompressed_sections()
-  { this->do_discard_decompressed_sections(); }
+  discard_decompressed_sections();
 
   // Return the index of the first incremental relocation for symbol SYMNDX.
   unsigned int
@@ -923,27 +947,6 @@ class Object
   bool
   handle_split_stack_section(const char* name);
 
-  // Return TRUE if the section is a compressed debug section, and set
-  // *UNCOMPRESSED_SIZE to the size of the uncompressed data.
-  virtual bool
-  do_section_is_compressed(unsigned int, section_size_type*) const
-  { return false; }
-
-  // Return a view of the decompressed contents of a section.  Set *PLEN
-  // to the size.  This default implementation simply returns the
-  // raw section contents and sets *IS_NEW to false to indicate
-  // that the contents do not need to be freed by the caller.
-  // This function must be overridden for any types of object files
-  // that might contain compressed sections.
-  virtual const unsigned char*
-  do_decompressed_section_contents(unsigned int shndx,
-				   section_size_type* plen,
-				   bool* is_new)
-  {
-    *is_new = false;
-    return this->do_section_contents(shndx, plen, false);
-  }
-
   // Discard any buffers of decompressed sections.  This is done
   // at the end of the Add_symbols task.
   virtual void
@@ -962,6 +965,14 @@ class Object
   do_get_incremental_reloc_count(unsigned int) const
   { gold_unreachable(); }
 
+  void
+  set_compressed_sections(Compressed_section_map* compressed_sections)
+  { this->compressed_sections_ = compressed_sections; }
+
+  Compressed_section_map*
+  compressed_sections()
+  { return this->compressed_sections_; }
+
  private:
   // This class may not be copied.
   Object(const Object&);
@@ -996,6 +1007,9 @@ class Object
   bool as_needed_ : 1;
   // Many sections for objects with more than SHN_LORESERVE sections.
   Xindex* xindex_;
+  // For compressed debug sections, map section index to uncompressed size
+  // and contents.
+  Compressed_section_map* compressed_sections_;
 };
 
 // A regular object (ET_REL).  This is an abstract base class itself.
@@ -1862,15 +1876,6 @@ class Reloc_symbol_changes
   std::vector<Symbol*> vec_;
 };
 
-// Type for mapping section index to uncompressed size and contents.
-
-struct Compressed_section_info
-{
-  section_size_type size;
-  const unsigned char* contents;
-};
-typedef std::map<unsigned int, Compressed_section_info> Compressed_section_map;
-
 // Abstract base class for a regular object file, either a real object file
 // or an incremental (unchanged) object.  This is size and endian specific.
 
@@ -2453,38 +2458,6 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
   set_output_local_symbol_count(unsigned int value)
   { this->output_local_symbol_count_ = value; }
 
-  // Return TRUE if the section is a compressed debug section, and set
-  // *UNCOMPRESSED_SIZE to the size of the uncompressed data.
-  bool
-  do_section_is_compressed(unsigned int shndx,
-			   section_size_type* uncompressed_size) const
-  {
-    if (this->compressed_sections_ == NULL)
-      return false;
-    Compressed_section_map::const_iterator p =
-        this->compressed_sections_->find(shndx);
-    if (p != this->compressed_sections_->end())
-      {
-	if (uncompressed_size != NULL)
-	  *uncompressed_size = p->second.size;
-	return true;
-      }
-    return false;
-  }
-
-  // Return a view of the uncompressed contents of a section.  Set *PLEN
-  // to the size.  Set *IS_NEW to true if the contents need to be deleted
-  // by the caller.
-  const unsigned char*
-  do_decompressed_section_contents(unsigned int shndx,
-				   section_size_type* plen,
-				   bool* is_new);
-
-  // Discard any buffers of decompressed sections.  This is done
-  // at the end of the Add_symbols task.
-  void
-  do_discard_decompressed_sections();
-
  private:
   // For convenience.
   typedef Sized_relobj_file<size, big_endian> This;
@@ -2751,9 +2724,6 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
   std::vector<Deferred_layout> deferred_layout_;
   // The list of relocation sections whose layout was deferred.
   std::vector<Deferred_layout> deferred_layout_relocs_;
-  // For compressed debug sections, map section index to uncompressed size
-  // and contents.
-  Compressed_section_map* compressed_sections_;
 };
 
 // A class to manage the list of all objects.
-- 
2.2.1

