mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-10-11 18:06:03 +08:00
From Craig Silverstein: Templatize the Dwarf reader.
This commit is contained in:
@ -118,7 +118,8 @@ ResetLineStateMachine(struct LineStateMachine* lsm, bool default_is_stmt)
|
|||||||
|
|
||||||
template<int size, bool big_endian>
|
template<int size, bool big_endian>
|
||||||
const unsigned char*
|
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);
|
uint32_t initial_length = elfcpp::Swap<32, big_endian>::readval(lineptr);
|
||||||
lineptr += 4;
|
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 header for a debug_line section is mildly complicated, because
|
||||||
// the line info is very tightly encoded.
|
// the line info is very tightly encoded.
|
||||||
|
|
||||||
|
template<int size, bool big_endian>
|
||||||
const unsigned char*
|
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.
|
// It is legal for the directory entry table to be empty.
|
||||||
if (*lineptr)
|
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
|
// simpler) code, but would bloat the binary. Speed isn't important
|
||||||
// here.
|
// here.
|
||||||
|
|
||||||
|
template<int size, bool big_endian>
|
||||||
bool
|
bool
|
||||||
Dwarf_line_info::process_one_opcode(int size, bool big_endian,
|
Dwarf_line_info<size, big_endian>::process_one_opcode(
|
||||||
const unsigned char* start,
|
const unsigned char* start, struct LineStateMachine* lsm, size_t* len)
|
||||||
struct LineStateMachine* lsm,
|
|
||||||
size_t* len)
|
|
||||||
{
|
{
|
||||||
size_t oplen = 0;
|
size_t oplen = 0;
|
||||||
size_t templen;
|
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:
|
case elfcpp::DW_LNS_fixed_advance_pc:
|
||||||
{
|
{
|
||||||
int advance_address;
|
int advance_address;
|
||||||
if (big_endian)
|
advance_address = elfcpp::Swap<16, big_endian>::readval(start);
|
||||||
advance_address = elfcpp::Swap<16, true>::readval(start);
|
|
||||||
else
|
|
||||||
advance_address = elfcpp::Swap<16, false>::readval(start);
|
|
||||||
oplen += 2;
|
oplen += 2;
|
||||||
lsm->address += advance_address;
|
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:
|
case elfcpp::DW_LNE_set_address:
|
||||||
// FIXME: modify the address based on the reloc
|
// FIXME: modify the address based on the reloc
|
||||||
if (size == 32 && big_endian == false)
|
lsm->address = elfcpp::Swap<size, big_endian>::readval(start);
|
||||||
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.
|
|
||||||
// FIXME: set lsm->shndx from the reloc
|
// FIXME: set lsm->shndx from the reloc
|
||||||
lsm->shndx = 1;
|
lsm->shndx = 1;
|
||||||
break;
|
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
|
// Read the debug information at LINEPTR and store it in the line
|
||||||
// number map.
|
// number map.
|
||||||
|
|
||||||
|
template<int size, bool big_endian>
|
||||||
unsigned const char*
|
unsigned const char*
|
||||||
Dwarf_line_info::read_lines(int size, bool big_endian,
|
Dwarf_line_info<size, big_endian>::read_lines(unsigned const char* lineptr)
|
||||||
unsigned const char* lineptr)
|
|
||||||
{
|
{
|
||||||
struct LineStateMachine lsm;
|
struct LineStateMachine lsm;
|
||||||
|
|
||||||
@ -431,8 +421,7 @@ Dwarf_line_info::read_lines(int size, bool big_endian,
|
|||||||
while (!lsm.end_sequence)
|
while (!lsm.end_sequence)
|
||||||
{
|
{
|
||||||
size_t oplength;
|
size_t oplength;
|
||||||
bool add_line = this->process_one_opcode(size, big_endian,
|
bool add_line = this->process_one_opcode(lineptr, &lsm, &oplength);
|
||||||
lineptr, &lsm, &oplength);
|
|
||||||
if (add_line)
|
if (add_line)
|
||||||
{
|
{
|
||||||
Offset_to_lineno_entry entry
|
Offset_to_lineno_entry entry
|
||||||
@ -446,12 +435,21 @@ Dwarf_line_info::read_lines(int size, bool big_endian,
|
|||||||
return lengthstart + header_.total_length;
|
return lengthstart + header_.total_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called after all line numbers have been read.
|
template<int size, bool big_endian>
|
||||||
|
|
||||||
void
|
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 != line_number_map_.end();
|
||||||
++it)
|
++it)
|
||||||
// Each vector needs to be sorted by offset.
|
// 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.
|
// Return a string for a file name and line number.
|
||||||
|
|
||||||
|
template<int size, bool big_endian>
|
||||||
std::string
|
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 };
|
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>& 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);
|
= std::lower_bound(offsets.begin(), offsets.end(), lookup_key);
|
||||||
|
|
||||||
// If we found an exact match, great, otherwise find the last entry
|
// 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
|
#ifdef HAVE_TARGET_32_LITTLE
|
||||||
template
|
template
|
||||||
const unsigned char*
|
class Dwarf_line_info<32, false>;
|
||||||
Dwarf_line_info::read_header_prolog<32, false>(const unsigned char* lineptr);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_TARGET_32_BIG
|
#ifdef HAVE_TARGET_32_BIG
|
||||||
template
|
template
|
||||||
const unsigned char*
|
class Dwarf_line_info<32, true>;
|
||||||
Dwarf_line_info::read_header_prolog<32, true>(const unsigned char* lineptr);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_TARGET_64_LITTLE
|
#ifdef HAVE_TARGET_64_LITTLE
|
||||||
template
|
template
|
||||||
const unsigned char*
|
class Dwarf_line_info<64, false>;
|
||||||
Dwarf_line_info::read_header_prolog<64, false>(const unsigned char* lineptr);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_TARGET_64_BIG
|
#ifdef HAVE_TARGET_64_BIG
|
||||||
template
|
template
|
||||||
const unsigned char*
|
class Dwarf_line_info<64, true>;
|
||||||
Dwarf_line_info::read_header_prolog<64, true>(const unsigned char* lineptr);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} // End namespace gold.
|
} // End namespace gold.
|
||||||
|
@ -36,6 +36,7 @@ struct LineStateMachine;
|
|||||||
// This class is used to read the line information from the debugging
|
// This class is used to read the line information from the debugging
|
||||||
// section of an object file.
|
// section of an object file.
|
||||||
|
|
||||||
|
template<int size, bool big_endian>
|
||||||
class Dwarf_line_info
|
class Dwarf_line_info
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -49,20 +50,8 @@ class Dwarf_line_info
|
|||||||
{ }
|
{ }
|
||||||
|
|
||||||
// Start processing line info, and populates the offset_map_.
|
// Start processing line info, and populates the offset_map_.
|
||||||
template<int size, bool big_endian>
|
|
||||||
void
|
void
|
||||||
read_line_mappings()
|
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Given a section number and an offset, returns the associated
|
// Given a section number and an offset, returns the associated
|
||||||
// file and line-number, as a string: "file:lineno". If unable
|
// file and line-number, as a string: "file:lineno". If unable
|
||||||
@ -74,7 +63,6 @@ class Dwarf_line_info
|
|||||||
private:
|
private:
|
||||||
// Reads the DWARF2/3 header for this line info. Each takes as input
|
// Reads the DWARF2/3 header for this line info. Each takes as input
|
||||||
// a starting buffer position, and returns the ending position.
|
// a starting buffer position, and returns the ending position.
|
||||||
template<int size, bool big_endian>
|
|
||||||
const unsigned char*
|
const unsigned char*
|
||||||
read_header_prolog(const unsigned char* lineptr);
|
read_header_prolog(const unsigned char* lineptr);
|
||||||
|
|
||||||
@ -83,22 +71,16 @@ class Dwarf_line_info
|
|||||||
|
|
||||||
// Reads the DWARF2/3 line information.
|
// Reads the DWARF2/3 line information.
|
||||||
const unsigned char*
|
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
|
// Process a single line info opcode at START using the state
|
||||||
// machine at LSM. Return true if we should define a line using the
|
// 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
|
// current state of the line state machine. Place the length of the
|
||||||
// opcode in LEN.
|
// opcode in LEN.
|
||||||
bool
|
bool
|
||||||
process_one_opcode(int size, bool big_endian,
|
process_one_opcode(const unsigned char* start,
|
||||||
const unsigned char* start,
|
|
||||||
struct LineStateMachine* lsm, size_t* len);
|
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
|
// 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
|
// actual file, as the one in the file may have a 32 bit or 64 bit
|
||||||
// lengths.
|
// lengths.
|
||||||
|
@ -919,8 +919,9 @@ Relocate_info<size, big_endian>::location(size_t, off_t offset) const
|
|||||||
shndx, &debuglines_size, false);
|
shndx, &debuglines_size, false);
|
||||||
if (debuglines)
|
if (debuglines)
|
||||||
{
|
{
|
||||||
Dwarf_line_info line_info(debuglines, debuglines_size);
|
Dwarf_line_info<size, big_endian> line_info(debuglines,
|
||||||
line_info.read_line_mappings<size, big_endian>();
|
debuglines_size);
|
||||||
|
line_info.read_line_mappings();
|
||||||
file_and_lineno = line_info.addr2line(this->data_shndx, offset);
|
file_and_lineno = line_info.addr2line(this->data_shndx, offset);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
Reference in New Issue
Block a user