]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Support compressed debug in dyn objects.
authorCary Coutant <ccoutant@google.com>
Mon, 9 Feb 2015 23:58:33 +0000 (15:58 -0800)
committerCary Coutant <ccoutant@google.com>
Mon, 23 Feb 2015 07:44:23 +0000 (23:44 -0800)
2015-02-09  Cary Coutant  <ccoutant@google.com>

gold/
* dwp.cc (Sized_relobj_dwo::do_decompressed_section_contents): Delete.
(Sized_relobj_dwo::setup): Setup map of compressed sections.
(print_version): Update copyright.
* dynobj.cc (Sized_dynobj::base_read_symbols): Set up map of compressed
sections.
* object.cc (Sized_relobj_file::compressed_sections): Delete.
(build_compressed_section_map): Add decompress_if_needed parameter.
Adjust callers.
(Sized_relobj_file::do_find_special_sections): Set compressed sections
map in Object base class.
(Sized_relobj_file::do_decompressed_section_contents): Rename to
Object::decompressed_section_contents.
(Sized_relobj_file::do_discard_decompressed_sections): Rename to
Object::discard_decompressed_sections.
* object.h (Object::compressed_sections_): New data member.
(Object::section_is_compressed): Remove virtual, implement here.
(Object::decompressed_section_contents): Remove virtual.
(Object::do_section_is_compressed): Delete.
(Object::do_decompressed_section_contents): Delete.
(Object::set_compressed_sections): New method.
(Object::compressed_sections): New method.
(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): Delete.

gold/dwp.cc
gold/dynobj.cc
gold/object.cc
gold/object.h

index 6d44d87851f5919c125253e0f5a41f77a90c2a18..16d471ce05f993ebbe8d4915fb05335c19b63b76 100644 (file)
@@ -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()
@@ -2352,7 +2334,7 @@ print_version()
 {
   // This output is intended to follow the GNU standards.
   printf("GNU dwp %s\n", BFD_VERSION_STRING);
-  printf(_("Copyright (C) 2014-2015 Free Software Foundation, Inc.\n"));
+  printf(_("Copyright (C) 2015 Free Software Foundation, Inc.\n"));
   printf(_("\
 This program is free software; you may redistribute it under the terms of\n\
 the GNU General Public License version 3 or (at your option) any later version.\n\
index 8bf6251f74b1ba0bafea6da90bc91faa76bc779a..13e3f616a606979ddcb13243122a53eae44a5a7f 100644 (file)
@@ -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.
index 8f16fe7dd356ed026c5c443f72a908695e803a2e..50ca7392d246b98e156043759f87726d36acafd2 100644 (file)
@@ -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;
index cce6c8c204e5955e6b214b4edd580a40c5c6539e..ef1065d52953ffb034c9203779fac89b865479b7 100644 (file)
@@ -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.