mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-09-10 01:42:21 +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->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.
|
||||||
|
@ -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
|
||||||
|
20
gold/merge.h
20
gold/merge.h
@ -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.
|
||||||
|
@ -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)
|
||||||
|
@ -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.
|
||||||
|
Reference in New Issue
Block a user