diff options
author | Ian Lance Taylor <iant@google.com> | 2007-11-07 00:49:56 +0000 |
---|---|---|
committer | Ian Lance Taylor <iant@google.com> | 2007-11-07 00:49:56 +0000 |
commit | e43872e995f19a24dfc933627009b5d3c55aab18 (patch) | |
tree | abdfeb32414f47a9450bf4b8f717924d81389ecc | |
parent | a7a81c1d9d5e6191ec7a2c3ce2ecc03e1264e4df (diff) | |
download | gdb-e43872e995f19a24dfc933627009b5d3c55aab18.zip gdb-e43872e995f19a24dfc933627009b5d3c55aab18.tar.gz gdb-e43872e995f19a24dfc933627009b5d3c55aab18.tar.bz2 |
From Craig Silverstein: Templatize the Dwarf reader.
-rw-r--r-- | gold/dwarf_reader.cc | 71 | ||||
-rw-r--r-- | gold/dwarf_reader.h | 26 | ||||
-rw-r--r-- | gold/object.cc | 5 |
3 files changed, 40 insertions, 62 deletions
diff --git a/gold/dwarf_reader.cc b/gold/dwarf_reader.cc index 05809a7..7d8967b 100644 --- a/gold/dwarf_reader.cc +++ b/gold/dwarf_reader.cc @@ -118,7 +118,8 @@ ResetLineStateMachine(struct LineStateMachine* lsm, bool default_is_stmt) template<int size, bool big_endian> const unsigned char* -Dwarf_line_info::read_header_prolog(const unsigned char* lineptr) +Dwarf_line_info<size, big_endian>::read_header_prolog( + const unsigned char* lineptr) { uint32_t initial_length = elfcpp::Swap<32, big_endian>::readval(lineptr); lineptr += 4; @@ -176,8 +177,10 @@ Dwarf_line_info::read_header_prolog(const unsigned char* lineptr) // The header for a debug_line section is mildly complicated, because // the line info is very tightly encoded. +template<int size, bool big_endian> const unsigned char* -Dwarf_line_info::read_header_tables(const unsigned char* lineptr) +Dwarf_line_info<size, big_endian>::read_header_tables( + const unsigned char* lineptr) { // It is legal for the directory entry table to be empty. if (*lineptr) @@ -231,11 +234,10 @@ Dwarf_line_info::read_header_tables(const unsigned char* lineptr) // simpler) code, but would bloat the binary. Speed isn't important // here. +template<int size, bool big_endian> bool -Dwarf_line_info::process_one_opcode(int size, bool big_endian, - const unsigned char* start, - struct LineStateMachine* lsm, - size_t* len) +Dwarf_line_info<size, big_endian>::process_one_opcode( + const unsigned char* start, struct LineStateMachine* lsm, size_t* len) { size_t oplen = 0; size_t templen; @@ -312,10 +314,7 @@ Dwarf_line_info::process_one_opcode(int size, bool big_endian, case elfcpp::DW_LNS_fixed_advance_pc: { int advance_address; - if (big_endian) - advance_address = elfcpp::Swap<16, true>::readval(start); - else - advance_address = elfcpp::Swap<16, false>::readval(start); + advance_address = elfcpp::Swap<16, big_endian>::readval(start); oplen += 2; lsm->address += advance_address; } @@ -349,16 +348,7 @@ Dwarf_line_info::process_one_opcode(int size, bool big_endian, case elfcpp::DW_LNE_set_address: // FIXME: modify the address based on the reloc - if (size == 32 && big_endian == false) - lsm->address = elfcpp::Swap<32, false>::readval(start); - else if (size == 32 && big_endian == true) - lsm->address = elfcpp::Swap<32, true>::readval(start); - else if (size == 64 && big_endian == false) - lsm->address = elfcpp::Swap<64, false>::readval(start); - else if (size == 64 && big_endian == true) - lsm->address = elfcpp::Swap<64, true>::readval(start); - else - gold_assert(false); // We need to implement more cases, then. + lsm->address = elfcpp::Swap<size, big_endian>::readval(start); // FIXME: set lsm->shndx from the reloc lsm->shndx = 1; break; @@ -408,9 +398,9 @@ Dwarf_line_info::process_one_opcode(int size, bool big_endian, // Read the debug information at LINEPTR and store it in the line // number map. +template<int size, bool big_endian> unsigned const char* -Dwarf_line_info::read_lines(int size, bool big_endian, - unsigned const char* lineptr) +Dwarf_line_info<size, big_endian>::read_lines(unsigned const char* lineptr) { struct LineStateMachine lsm; @@ -431,8 +421,7 @@ Dwarf_line_info::read_lines(int size, bool big_endian, while (!lsm.end_sequence) { size_t oplength; - bool add_line = this->process_one_opcode(size, big_endian, - lineptr, &lsm, &oplength); + bool add_line = this->process_one_opcode(lineptr, &lsm, &oplength); if (add_line) { Offset_to_lineno_entry entry @@ -446,12 +435,21 @@ Dwarf_line_info::read_lines(int size, bool big_endian, return lengthstart + header_.total_length; } -// Called after all line numbers have been read. - +template<int size, bool big_endian> void -Dwarf_line_info::finalize_line_number_map() +Dwarf_line_info<size, big_endian>::read_line_mappings() { - for (Lineno_map::iterator it = line_number_map_.begin(); + while (buffer_ < buffer_end_) + { + const unsigned char* lineptr = buffer_; + lineptr = this->read_header_prolog(lineptr); + lineptr = this->read_header_tables(lineptr); + lineptr = this->read_lines(lineptr); + buffer_ = lineptr; + } + + // Sort the lines numbers, so addr2line can use binary search. + for (typename Lineno_map::iterator it = line_number_map_.begin(); it != line_number_map_.end(); ++it) // Each vector needs to be sorted by offset. @@ -460,12 +458,13 @@ Dwarf_line_info::finalize_line_number_map() // Return a string for a file name and line number. +template<int size, bool big_endian> std::string -Dwarf_line_info::addr2line(unsigned int shndx, off_t offset) +Dwarf_line_info<size, big_endian>::addr2line(unsigned int shndx, off_t offset) { const Offset_to_lineno_entry lookup_key = { offset, 0, 0 }; std::vector<Offset_to_lineno_entry>& offsets = line_number_map_[shndx]; - std::vector<Offset_to_lineno_entry>::const_iterator it + typename std::vector<Offset_to_lineno_entry>::const_iterator it = std::lower_bound(offsets.begin(), offsets.end(), lookup_key); // If we found an exact match, great, otherwise find the last entry @@ -504,26 +503,22 @@ Dwarf_line_info::addr2line(unsigned int shndx, off_t offset) #ifdef HAVE_TARGET_32_LITTLE template -const unsigned char* -Dwarf_line_info::read_header_prolog<32, false>(const unsigned char* lineptr); +class Dwarf_line_info<32, false>; #endif #ifdef HAVE_TARGET_32_BIG template -const unsigned char* -Dwarf_line_info::read_header_prolog<32, true>(const unsigned char* lineptr); +class Dwarf_line_info<32, true>; #endif #ifdef HAVE_TARGET_64_LITTLE template -const unsigned char* -Dwarf_line_info::read_header_prolog<64, false>(const unsigned char* lineptr); +class Dwarf_line_info<64, false>; #endif #ifdef HAVE_TARGET_64_BIG template -const unsigned char* -Dwarf_line_info::read_header_prolog<64, true>(const unsigned char* lineptr); +class Dwarf_line_info<64, true>; #endif } // End namespace gold. diff --git a/gold/dwarf_reader.h b/gold/dwarf_reader.h index a367715..a016342 100644 --- a/gold/dwarf_reader.h +++ b/gold/dwarf_reader.h @@ -36,6 +36,7 @@ struct LineStateMachine; // This class is used to read the line information from the debugging // section of an object file. +template<int size, bool big_endian> class Dwarf_line_info { public: @@ -49,20 +50,8 @@ class Dwarf_line_info { } // Start processing line info, and populates the offset_map_. - template<int size, bool big_endian> void - read_line_mappings() - { - while (buffer_ < buffer_end_) - { - const unsigned char* lineptr = buffer_; - lineptr = this->read_header_prolog<size, big_endian>(lineptr); - lineptr = this->read_header_tables(lineptr); - lineptr = this->read_lines(size, big_endian, lineptr); - buffer_ = lineptr; - } - finalize_line_number_map(); - } + read_line_mappings(); // Given a section number and an offset, returns the associated // file and line-number, as a string: "file:lineno". If unable @@ -74,7 +63,6 @@ class Dwarf_line_info private: // Reads the DWARF2/3 header for this line info. Each takes as input // a starting buffer position, and returns the ending position. - template<int size, bool big_endian> const unsigned char* read_header_prolog(const unsigned char* lineptr); @@ -83,22 +71,16 @@ class Dwarf_line_info // Reads the DWARF2/3 line information. const unsigned char* - read_lines(int size, bool big_endian, const unsigned char* lineptr); + read_lines(const unsigned char* lineptr); // Process a single line info opcode at START using the state // machine at LSM. Return true if we should define a line using the // current state of the line state machine. Place the length of the // opcode in LEN. bool - process_one_opcode(int size, bool big_endian, - const unsigned char* start, + process_one_opcode(const unsigned char* start, struct LineStateMachine* lsm, size_t* len); - // Called after all line number have been read, to ready - // line_number_map_ for calls to addr2line(). - void - finalize_line_number_map(); - // A DWARF2/3 line info header. This is not the same size as in the // actual file, as the one in the file may have a 32 bit or 64 bit // lengths. diff --git a/gold/object.cc b/gold/object.cc index 8efd4ec..0b71be1 100644 --- a/gold/object.cc +++ b/gold/object.cc @@ -919,8 +919,9 @@ Relocate_info<size, big_endian>::location(size_t, off_t offset) const shndx, &debuglines_size, false); if (debuglines) { - Dwarf_line_info line_info(debuglines, debuglines_size); - line_info.read_line_mappings<size, big_endian>(); + Dwarf_line_info<size, big_endian> line_info(debuglines, + debuglines_size); + line_info.read_line_mappings(); file_and_lineno = line_info.addr2line(this->data_shndx, offset); } break; |