mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-09-09 21:22:20 +08:00
Print statistics about merge sections with --stats.
This commit is contained in:
@ -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.
|
||||
|
@ -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
|
||||
|
20
gold/merge.h
20
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.
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
|
Reference in New Issue
Block a user