elfcpp/
[binutils-gdb.git] / gold / object.cc
index d3835df900011d46834d306d4bc2806224984dc9..2b4fe0227917fd77403466a9e76a657c920e2f57 100644 (file)
@@ -421,6 +421,7 @@ Sized_relobj_file<size, big_endian>::Sized_relobj_file(
     deferred_layout_relocs_(),
     compressed_sections_()
 {
+  this->e_type_ = ehdr.get_e_type();
 }
 
 template<int size, bool big_endian>
@@ -549,8 +550,26 @@ Sized_relobj_file<size, big_endian>::find_eh_frame(
   return false;
 }
 
+#ifdef ENABLE_THREADS
+
+// Return TRUE if this is a section whose contents will be needed in the
+// Add_symbols task.
+
+static bool
+need_decompressed_section(const char* name)
+{
+  // We will need .zdebug_str if this is not an incremental link
+  // (i.e., we are processing string merge sections).
+  if (!parameters->incremental() && strcmp(name, ".zdebug_str") == 0)
+    return true;
+
+  return false;
+}
+
+#endif
+
 // Build a table for any compressed debug sections, mapping each section index
-// to the uncompressed size.
+// to the uncompressed size and (if needed) the decompressed contents.
 
 template<int size, bool big_endian>
 Compressed_section_map*
@@ -561,9 +580,10 @@ build_compressed_section_map(
     section_size_type names_size,
     Sized_relobj_file<size, big_endian>* obj)
 {
-  Compressed_section_map* uncompressed_sizes = new Compressed_section_map();
+  Compressed_section_map* uncompressed_map = new Compressed_section_map();
   const unsigned int shdr_size = elfcpp::Elf_sizes<size>::shdr_size;
   const unsigned char* p = pshdrs + shdr_size;
+
   for (unsigned int i = 1; i < shnum; ++i, p += shdr_size)
     {
       typename elfcpp::Shdr<size, big_endian> shdr(p);
@@ -585,12 +605,38 @@ build_compressed_section_map(
                  obj->section_contents(i, &len, false);
              uint64_t uncompressed_size = get_uncompressed_size(contents, len);
              if (uncompressed_size != -1ULL)
-               (*uncompressed_sizes)[i] =
-                   convert_to_section_size_type(uncompressed_size);
+               {
+                 Compressed_section_info info;
+                 info.size = convert_to_section_size_type(uncompressed_size);
+                 info.contents = NULL;
+
+#ifdef ENABLE_THREADS
+                 // If we're multi-threaded, it will help to decompress
+                 // any sections that will be needed during the Add_symbols
+                 // task, so that several decompressions can run in
+                 // parallel.
+                 if (parameters->options().threads())
+                   {
+                     unsigned char* uncompressed_data = NULL;
+                     if (need_decompressed_section(name))
+                       {
+                         uncompressed_data = new unsigned char[uncompressed_size];
+                         if (decompress_input_section(contents, len,
+                                                      uncompressed_data,
+                                                      uncompressed_size))
+                           info.contents = uncompressed_data;
+                         else
+                           delete[] uncompressed_data;
+                       }
+                   }
+#endif
+
+                 (*uncompressed_map)[i] = info;
+               }
            }
        }
     }
-  return uncompressed_sizes;
+  return uncompressed_map;
 }
 
 // Read the sections and symbols from an object file.
@@ -748,10 +794,11 @@ Sized_relobj_file<size, big_endian>::include_section_group(
   // just like ordinary sections.
   elfcpp::Elf_Word flags = elfcpp::Swap<32, big_endian>::readval(pword);
 
-  // Look up the group signature, which is the name of a symbol.  This
-  // is a lot of effort to go to to read a string.  Why didn't they
-  // just have the group signature point into the string table, rather
-  // than indirect through a symbol?
+  // Look up the group signature, which is the name of a symbol.  ELF
+  // uses a symbol name because some group signatures are long, and
+  // the name is generally already in the symbol table, so it makes
+  // sense to put the long string just once in .strtab rather than in
+  // both .strtab and .shstrtab.
 
   // Get the appropriate symbol table header (this will normally be
   // the single SHT_SYMTAB section, but in principle it need not be).
@@ -1147,7 +1194,6 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
   section_size_type section_names_size;
   const unsigned char* symbols_data = NULL;
   section_size_type symbols_size;
-  section_offset_type external_symbols_offset;
   const unsigned char* symbol_names_data = NULL;
   section_size_type symbol_names_size;
  
@@ -1157,7 +1203,6 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
       section_names_size = gc_sd->section_names_size;
       symbols_data = gc_sd->symbols_data;
       symbols_size = gc_sd->symbols_size;
-      external_symbols_offset = gc_sd->external_symbols_offset;
       symbol_names_data = gc_sd->symbol_names_data;
       symbol_names_size = gc_sd->symbol_names_size;
     }
@@ -1168,7 +1213,6 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
       if (sd->symbols != NULL)
         symbols_data = sd->symbols->data();
       symbols_size = sd->symbols_size;
-      external_symbols_offset = sd->external_symbols_offset;
       if (sd->symbol_names != NULL)
         symbol_names_data = sd->symbol_names->data();
       symbol_names_size = sd->symbol_names_size;
@@ -1345,9 +1389,7 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
          Incremental_inputs* incremental_inputs = layout->incremental_inputs();
          if (incremental_inputs != NULL
              && !discard
-             && (shdr.get_sh_type() == elfcpp::SHT_PROGBITS
-                 || shdr.get_sh_type() == elfcpp::SHT_NOBITS
-                 || shdr.get_sh_type() == elfcpp::SHT_NOTE))
+             && can_incremental_update(shdr.get_sh_type()))
            {
              off_t sh_size = shdr.get_sh_size();
              section_size_type uncompressed_size;
@@ -1580,8 +1622,6 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
        p != eh_frame_sections.end();
        ++p)
     {
-      gold_assert(external_symbols_offset != 0);
-
       unsigned int i = *p;
       const unsigned char* pshdr;
       pshdr = section_headers_data + i * This::shdr_size;
@@ -1824,7 +1864,8 @@ Sized_relobj_file<size, big_endian>::local_has_plt_offset(
 
 template<int size, bool big_endian>
 unsigned int
-Sized_relobj_file<size, big_endian>::local_plt_offset(unsigned int symndx) const
+Sized_relobj_file<size, big_endian>::do_local_plt_offset(
+    unsigned int symndx) const
 {
   typename Local_plt_offsets::const_iterator p =
     this->local_plt_offsets_.find(symndx);
@@ -2561,6 +2602,85 @@ Sized_relobj_file<size, big_endian>::do_get_global_symbol_counts(
   *used = count;
 }
 
+// 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.
+
+template<int size, bool big_endian>
+const unsigned char*
+Sized_relobj_file<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->section_contents(shndx, &buffer_size,
+                                                      false);
+
+  if (this->compressed_sections_ == NULL)
+    {
+      *plen = buffer_size;
+      *is_new = false;
+      return buffer;
+    }
+
+  Compressed_section_map::const_iterator p =
+      this->compressed_sections_->find(shndx);
+  if (p == this->compressed_sections_->end())
+    {
+      *plen = buffer_size;
+      *is_new = false;
+      return buffer;
+    }
+
+  section_size_type uncompressed_size = p->second.size;
+  if (p->second.contents != NULL)
+    {
+      *plen = uncompressed_size;
+      *is_new = false;
+      return p->second.contents;
+    }
+
+  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->do_section_name(shndx).c_str());
+
+  // We could cache the results in p->second.contents and store
+  // false in *IS_NEW, but build_compressed_section_map() would
+  // have done so if it had expected it to be profitable.  If
+  // we reach this point, we expect to need the contents only
+  // once in this pass.
+  *plen = uncompressed_size;
+  *is_new = true;
+  return uncompressed_data;
+}
+
+// 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()
+{
+  if (this->compressed_sections_ == NULL)
+    return;
+
+  for (Compressed_section_map::iterator p = this->compressed_sections_->begin();
+       p != this->compressed_sections_->end();
+       ++p)
+    {
+      if (p->second.contents != NULL)
+        {
+          delete[] p->second.contents;
+          p->second.contents = NULL;
+        }
+    }
+}
+
 // Input_objects methods.
 
 // Add a regular relocatable object to the list.  Return false if this