aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gold/layout.cc5
-rw-r--r--gold/merge.cc64
-rw-r--r--gold/merge.h20
-rw-r--r--gold/output.cc12
-rw-r--r--gold/output.h24
5 files changed, 124 insertions, 1 deletions
diff --git a/gold/layout.cc b/gold/layout.cc
index 71e3ab4..ff0425d 100644
--- a/gold/layout.cc
+++ b/gold/layout.cc
@@ -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.
diff --git a/gold/merge.cc b/gold/merge.cc
index 25aac76..65acf82 100644
--- a/gold/merge.cc
+++ b/gold/merge.cc
@@ -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
diff --git a/gold/merge.h b/gold/merge.h
index a649321..056c2c6 100644
--- a/gold/merge.h
+++ b/gold/merge.h
@@ -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.
diff --git a/gold/output.cc b/gold/output.cc
index 5a8cae7..c7fb32d 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -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)
diff --git a/gold/output.h b/gold/output.h
index 76db946..51c8502 100644
--- a/gold/output.h
+++ b/gold/output.h
@@ -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.