Print statistics about merge sections with --stats.

This commit is contained in:
Ian Lance Taylor
2007-12-18 21:24:10 +00:00
parent cb2dde36a0
commit 38c5e8b493
5 changed files with 124 additions and 1 deletions

View File

@ -2062,6 +2062,11 @@ Layout::print_stats() const
this->namepool_.print_stats("section name pool"); this->namepool_.print_stats("section name pool");
this->sympool_.print_stats("output symbol name pool"); this->sympool_.print_stats("output symbol name pool");
this->dynpool_.print_stats("dynamic 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. // Write_sections_task methods.

View File

@ -414,6 +414,8 @@ Output_merge_data::do_add_input_section(Relobj* object, unsigned int shndx)
if (len % entsize != 0) if (len % entsize != 0)
return false; return false;
this->input_count_ += len / entsize;
for (section_size_type i = 0; i < len; i += entsize, p += 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 // 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_); 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. // Class Output_merge_string.
// Add an input section to a merged string section. // 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; return false;
} }
size_t count = 0;
// The index I is in bytes, not characters. // The index I is in bytes, not characters.
section_size_type i = 0; section_size_type i = 0;
while (i < len) while (i < len)
@ -512,8 +528,11 @@ Output_merge_string<Char_type>::do_add_input_section(Relobj* object,
p = pl + 1; p = pl + 1;
i += bytelen_with_null; i += bytelen_with_null;
++count;
} }
this->input_count_ += count;
return true; 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()); 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. // Instantiate the templates we need.
template template

View File

@ -108,9 +108,11 @@ class Output_merge_data : public Output_merge_base
public: public:
Output_merge_data(uint64_t entsize, uint64_t addralign) Output_merge_data(uint64_t entsize, uint64_t addralign)
: Output_merge_base(entsize, addralign), p_(NULL), len_(0), alc_(0), : Output_merge_base(entsize, addralign), p_(NULL), len_(0), alc_(0),
input_count_(0),
hashtable_(128, Merge_data_hash(this), Merge_data_eq(this)) hashtable_(128, Merge_data_hash(this), Merge_data_eq(this))
{ } { }
protected:
// Add an input section. // Add an input section.
bool bool
do_add_input_section(Relobj* object, unsigned int shndx); do_add_input_section(Relobj* object, unsigned int shndx);
@ -127,6 +129,10 @@ class Output_merge_data : public Output_merge_base
void void
do_write_to_buffer(unsigned char*); do_write_to_buffer(unsigned char*);
// Print merge stats to stderr.
void
do_print_merge_stats(const char* section_name);
private: private:
// We build a hash table of the fixed-size constants. Each constant // We build a hash table of the fixed-size constants. Each constant
// is stored as a pointer into the section data we are accumulating. // 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_; section_size_type len_;
// The size of the allocated buffer. // The size of the allocated buffer.
section_size_type alc_; section_size_type alc_;
// The number of entries seen in input files.
size_t input_count_;
// The hash table. // The hash table.
Merge_data_hashtable hashtable_; Merge_data_hashtable hashtable_;
}; };
@ -210,7 +218,7 @@ class Output_merge_string : public Output_merge_base
public: public:
Output_merge_string(uint64_t addralign) Output_merge_string(uint64_t addralign)
: Output_merge_base(sizeof(Char_type), addralign), stringpool_(), : Output_merge_base(sizeof(Char_type), addralign), stringpool_(),
merged_strings_() merged_strings_(), input_count_(0)
{ {
gold_assert(addralign <= sizeof(Char_type)); gold_assert(addralign <= sizeof(Char_type));
this->stringpool_.set_no_zero_null(); this->stringpool_.set_no_zero_null();
@ -238,6 +246,10 @@ class Output_merge_string : public Output_merge_base
void void
do_write_to_buffer(unsigned char*); 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. // Writes the stringpool to a buffer.
void void
stringpool_to_buffer(unsigned char* buffer, section_size_type buffer_size) 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(); } { this->stringpool_.clear(); }
private: 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 // As we see input sections, we build a mapping from object, section
// index and offset to strings. // index and offset to strings.
struct Merged_string 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 // Map from a location in an input object to an entry in the
// Stringpool. // Stringpool.
Merged_strings merged_strings_; Merged_strings merged_strings_;
// The number of entries seen in input files.
size_t input_count_;
}; };
} // End namespace gold. } // End namespace gold.

View 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 methods.
Output_segment::Output_segment(elfcpp::Elf_Word type, elfcpp::Elf_Word flags) Output_segment::Output_segment(elfcpp::Elf_Word type, elfcpp::Elf_Word flags)

View File

@ -472,6 +472,12 @@ class Output_section_data : public Output_data
write_to_buffer(unsigned char* buffer) write_to_buffer(unsigned char* buffer)
{ this->do_write_to_buffer(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: protected:
// The child class must implement do_write. // The child class must implement do_write.
@ -500,6 +506,11 @@ class Output_section_data : public Output_data
do_write_to_buffer(unsigned char*) do_write_to_buffer(unsigned char*)
{ gold_unreachable(); } { gold_unreachable(); }
// Print merge statistics.
virtual void
do_print_merge_stats(const char*)
{ gold_unreachable(); }
// Return the required alignment. // Return the required alignment.
uint64_t uint64_t
do_addralign() const do_addralign() const
@ -1678,6 +1689,10 @@ class Output_section : public Output_data
write_header(const Layout*, const Stringpool*, write_header(const Layout*, const Stringpool*,
elfcpp::Shdr_write<size, big_endian>*) const; elfcpp::Shdr_write<size, big_endian>*) const;
// Print merge statistics to stderr.
void
print_merge_stats();
protected: protected:
// Return the section index in the output file. // Return the section index in the output file.
unsigned int unsigned int
@ -1896,6 +1911,15 @@ class Output_section : public Output_data
void void
write_to_buffer(unsigned char*); 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: private:
// Code values which appear in shndx_. If the value is not one of // 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. // these codes, it is the input section index in the object file.