diff options
author | Ian Lance Taylor <iant@google.com> | 2007-12-18 21:24:10 +0000 |
---|---|---|
committer | Ian Lance Taylor <iant@google.com> | 2007-12-18 21:24:10 +0000 |
commit | 38c5e8b493ec72879187ffca3d8533acd2c014a5 (patch) | |
tree | da1699c0936f8c22611469fe0bafae8e117a6658 | |
parent | cb2dde36a0abb8f59c950187153a245264759fa1 (diff) | |
download | gdb-38c5e8b493ec72879187ffca3d8533acd2c014a5.zip gdb-38c5e8b493ec72879187ffca3d8533acd2c014a5.tar.gz gdb-38c5e8b493ec72879187ffca3d8533acd2c014a5.tar.bz2 |
Print statistics about merge sections with --stats.
-rw-r--r-- | gold/layout.cc | 5 | ||||
-rw-r--r-- | gold/merge.cc | 64 | ||||
-rw-r--r-- | gold/merge.h | 20 | ||||
-rw-r--r-- | gold/output.cc | 12 | ||||
-rw-r--r-- | gold/output.h | 24 |
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. |