Print statistics about merge sections with --stats.
authorIan Lance Taylor <iant@google.com>
Tue, 18 Dec 2007 21:24:10 +0000 (21:24 +0000)
committerIan Lance Taylor <iant@google.com>
Tue, 18 Dec 2007 21:24:10 +0000 (21:24 +0000)
gold/layout.cc
gold/merge.cc
gold/merge.h
gold/output.cc
gold/output.h

index 71e3ab473b3ab4d133b34fe1d865a4d35f156e44..ff0425d24de8958090c315751ad6592c24487c42 100644 (file)
@@ -2062,6 +2062,11 @@ Layout::print_stats() const
   this->namepool_.print_stats("section name pool");
   this->sympool_.print_stats("output symbol name pool");
   this->dynpool_.print_stats("dynamic name pool");
+
+  for (Section_list::const_iterator p = this->section_list_.begin();
+       p != this->section_list_.end();
+       ++p)
+    (*p)->print_merge_stats();
 }
 
 // Write_sections_task methods.
index 25aac76de6ad07e31c0938ddef766fc382211c2b..65acf827214a5635f42492091cd7a88258549a3a 100644 (file)
@@ -414,6 +414,8 @@ Output_merge_data::do_add_input_section(Relobj* object, unsigned int shndx)
   if (len % entsize != 0)
     return false;
 
+  this->input_count_ += len / entsize;
+
   for (section_size_type i = 0; i < len; i += entsize, p += entsize)
     {
       // Add the constant to the section contents.  If we find that it
@@ -467,6 +469,18 @@ Output_merge_data::do_write_to_buffer(unsigned char* buffer)
   memcpy(buffer, this->p_, this->len_);
 }
 
+// Print merge stats to stderr.
+
+void
+Output_merge_data::do_print_merge_stats(const char* section_name)
+{
+  fprintf(stderr,
+         _("%s: %s merged constants size: %lu; input: %zu; output: %zu\n"),
+         program_name, section_name,
+         static_cast<unsigned long>(this->entsize()),
+         this->input_count_, this->hashtable_.size());
+}
+
 // Class Output_merge_string.
 
 // Add an input section to a merged string section.
@@ -489,6 +503,8 @@ Output_merge_string<Char_type>::do_add_input_section(Relobj* object,
       return false;
     }
 
+  size_t count = 0;
+
   // The index I is in bytes, not characters.
   section_size_type i = 0;
   while (i < len)
@@ -512,8 +528,11 @@ Output_merge_string<Char_type>::do_add_input_section(Relobj* object,
 
       p = pl + 1;
       i += bytelen_with_null;
+      ++count;
     }
 
+  this->input_count_ += count;
+
   return true;
 }
 
@@ -565,6 +584,51 @@ Output_merge_string<Char_type>::do_write_to_buffer(unsigned char* buffer)
   this->stringpool_.write_to_buffer(buffer, this->data_size());
 }
 
+// Return the name of the types of string to use with
+// do_print_merge_stats.
+
+template<typename Char_type>
+const char*
+Output_merge_string<Char_type>::string_name()
+{
+  gold_unreachable();
+  return NULL;
+}
+
+template<>
+const char*
+Output_merge_string<char>::string_name()
+{
+  return "strings";
+}
+
+template<>
+const char*
+Output_merge_string<uint16_t>::string_name()
+{
+  return "16-bit strings";
+}
+
+template<>
+const char*
+Output_merge_string<uint32_t>::string_name()
+{
+  return "32-bit strings";
+}
+
+// Print merge stats to stderr.
+
+template<typename Char_type>
+void
+Output_merge_string<Char_type>::do_print_merge_stats(const char* section_name)
+{
+  char buf[200];
+  snprintf(buf, sizeof buf, "%s merged %s", section_name, this->string_name());
+  fprintf(stderr, _("%s: %s input: %zu\n"),
+         program_name, buf, this->input_count_);
+  this->stringpool_.print_stats(buf);
+}
+
 // Instantiate the templates we need.
 
 template
index a64932180ec762f22a83492f6e5782c00a49e925..056c2c677158d2792df4f12010e057b4858f71bb 100644 (file)
@@ -108,9 +108,11 @@ class Output_merge_data : public Output_merge_base
  public:
   Output_merge_data(uint64_t entsize, uint64_t addralign)
     : Output_merge_base(entsize, addralign), p_(NULL), len_(0), alc_(0),
+      input_count_(0),
       hashtable_(128, Merge_data_hash(this), Merge_data_eq(this))
   { }
 
+ protected:
   // Add an input section.
   bool
   do_add_input_section(Relobj* object, unsigned int shndx);
@@ -127,6 +129,10 @@ class Output_merge_data : public Output_merge_base
   void
   do_write_to_buffer(unsigned char*);
 
+  // Print merge stats to stderr.
+  void
+  do_print_merge_stats(const char* section_name);
+
  private:
   // We build a hash table of the fixed-size constants.  Each constant
   // is stored as a pointer into the section data we are accumulating.
@@ -197,6 +203,8 @@ class Output_merge_data : public Output_merge_base
   section_size_type len_;
   // The size of the allocated buffer.
   section_size_type alc_;
+  // The number of entries seen in input files.
+  size_t input_count_;
   // The hash table.
   Merge_data_hashtable hashtable_;
 };
@@ -210,7 +218,7 @@ class Output_merge_string : public Output_merge_base
  public:
   Output_merge_string(uint64_t addralign)
     : Output_merge_base(sizeof(Char_type), addralign), stringpool_(),
-      merged_strings_()
+      merged_strings_(), input_count_(0)
   {
     gold_assert(addralign <= sizeof(Char_type));
     this->stringpool_.set_no_zero_null();
@@ -238,6 +246,10 @@ class Output_merge_string : public Output_merge_base
   void
   do_write_to_buffer(unsigned char*);
 
+  // Print merge stats to stderr.
+  void
+  do_print_merge_stats(const char* section_name);
+
   // Writes the stringpool to a buffer.
   void
   stringpool_to_buffer(unsigned char* buffer, section_size_type buffer_size)
@@ -249,6 +261,10 @@ class Output_merge_string : public Output_merge_base
   { this->stringpool_.clear(); }
 
  private:
+  // The name of the string type, for stats.
+  const char*
+  string_name();
+
   // As we see input sections, we build a mapping from object, section
   // index and offset to strings.
   struct Merged_string
@@ -279,6 +295,8 @@ class Output_merge_string : public Output_merge_base
   // Map from a location in an input object to an entry in the
   // Stringpool.
   Merged_strings merged_strings_;
+  // The number of entries seen in input files.
+  size_t input_count_;
 };
 
 } // End namespace gold.
index 5a8cae7338c4ce0c52a1ca6cc97efd4a9cd765cb..c7fb32dae66dc0cda06616e3458d76fdac3c25ac 100644 (file)
@@ -1860,6 +1860,18 @@ Output_section::write_to_postprocessing_buffer()
     }
 }
 
+// Print stats for merge sections to stderr.
+
+void
+Output_section::print_merge_stats()
+{
+  Input_section_list::iterator p;
+  for (p = this->input_sections_.begin();
+       p != this->input_sections_.end();
+       ++p)
+    p->print_merge_stats(this->name_);
+}
+
 // Output segment methods.
 
 Output_segment::Output_segment(elfcpp::Elf_Word type, elfcpp::Elf_Word flags)
index 76db946812231c451efde5aadddd4c2a9377ffaa..51c85026c9b4833a836660f201434d3cc39cf7fa 100644 (file)
@@ -472,6 +472,12 @@ class Output_section_data : public Output_data
   write_to_buffer(unsigned char* buffer)
   { this->do_write_to_buffer(buffer); }
 
+  // Print merge stats to stderr.  This should only be called for
+  // SHF_MERGE sections.
+  void
+  print_merge_stats(const char* section_name)
+  { this->do_print_merge_stats(section_name); }
+
  protected:
   // The child class must implement do_write.
 
@@ -500,6 +506,11 @@ class Output_section_data : public Output_data
   do_write_to_buffer(unsigned char*)
   { gold_unreachable(); }
 
+  // Print merge statistics.
+  virtual void
+  do_print_merge_stats(const char*)
+  { gold_unreachable(); }
+
   // Return the required alignment.
   uint64_t
   do_addralign() const
@@ -1678,6 +1689,10 @@ class Output_section : public Output_data
   write_header(const Layout*, const Stringpool*,
               elfcpp::Shdr_write<size, big_endian>*) const;
 
+  // Print merge statistics to stderr.
+  void
+  print_merge_stats();
+
  protected:
   // Return the section index in the output file.
   unsigned int
@@ -1896,6 +1911,15 @@ class Output_section : public Output_data
     void
     write_to_buffer(unsigned char*);
 
+    // Print statistics about merge sections to stderr.
+    void
+    print_merge_stats(const char* section_name)
+    {
+      if (this->shndx_ == MERGE_DATA_SECTION_CODE
+         || this->shndx_ == MERGE_STRING_SECTION_CODE)
+       this->u2_.posd->print_merge_stats(section_name);
+    }
+
    private:
     // Code values which appear in shndx_.  If the value is not one of
     // these codes, it is the input section index in the object file.