From Craig Silverstein: Templatize the Dwarf reader.
This commit is contained in:
parent
a7a81c1d9d
commit
e43872e995
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue