Add support for parsing the DW_AT_ranges attributes

This enables the DWARF reader to properly parse DW_AT_ranges attributes
in compilation units and functions. Code covered by a function is now
represented by a vector of ranges instead of a single contiguous range
and DW_AT_ranges entries are used to populate it. All the code and tests
that assumed functions to be contiguous entities has been updated to
reflect the change. DW_AT_ranges attributes found in compilation units
are parsed but no data is generated for them as it is not currently needed.

BUG=754

Change-Id: I310391b525aaba0dd329f1e3187486f2e0c6d442
Reviewed-on: https://chromium-review.googlesource.com/1124721
Reviewed-by: Ted Mielczarek <ted.mielczarek@gmail.com>
This commit is contained in:
Gabriele Svelto
2018-08-04 00:59:34 +02:00
committed by Ted Mielczarek
parent 7b98edabb6
commit 16e08520e6
20 changed files with 653 additions and 122 deletions

View File

@@ -1247,6 +1247,41 @@ void LineInfo::ReadLines() {
after_header_ = lengthstart + header_.total_length;
}
RangeListReader::RangeListReader(const uint8_t *buffer, uint64 size,
ByteReader *reader, RangeListHandler *handler)
: buffer_(buffer), size_(size), reader_(reader), handler_(handler) { }
bool RangeListReader::ReadRangeList(uint64 offset) {
const uint64 max_address =
(reader_->AddressSize() == 4) ? 0xffffffffUL
: 0xffffffffffffffffULL;
const uint64 entry_size = reader_->AddressSize() * 2;
bool list_end = false;
do {
if (offset > size_ - entry_size) {
return false; // Invalid range detected
}
uint64 start_address = reader_->ReadAddress(buffer_ + offset);
uint64 end_address =
reader_->ReadAddress(buffer_ + offset + reader_->AddressSize());
if (start_address == max_address) { // Base address selection
handler_->SetBaseAddress(end_address);
} else if (start_address == 0 && end_address == 0) { // End-of-list
handler_->Finish();
list_end = true;
} else { // Add a range entry
handler_->AddRange(start_address, end_address);
}
offset += entry_size;
} while (!list_end);
return true;
}
// A DWARF rule for recovering the address or value of a register, or
// computing the canonical frame address. There is one subclass of this for
// each '*Rule' member function in CallFrameInfo::Handler.

View File

@@ -187,6 +187,36 @@ class LineInfoHandler {
uint32 file_num, uint32 line_num, uint32 column_num) { }
};
class RangeListHandler {
public:
RangeListHandler() { }
virtual ~RangeListHandler() { }
// Add a range.
virtual void AddRange(uint64 begin, uint64 end) { };
// A new base address must be set for computing the ranges' addresses.
virtual void SetBaseAddress(uint64 base_address) { };
// Finish processing the range list.
virtual void Finish() { };
};
class RangeListReader {
public:
RangeListReader(const uint8_t *buffer, uint64 size, ByteReader *reader,
RangeListHandler *handler);
bool ReadRangeList(uint64 offset);
private:
const uint8_t *buffer_;
uint64 size_;
ByteReader* reader_;
RangeListHandler *handler_;
};
// This class is the main interface between the reader and the
// client. The virtual functions inside this get called for
// interesting events that happen during DWARF2 reading.

View File

@@ -184,6 +184,9 @@ void CUFunctionInfoHandler::ProcessAttributeUnsigned(uint64 offset,
case DW_AT_decl_file:
current_function_info_->file = files_->at(data).name;
break;
case DW_AT_ranges:
current_function_info->ranges = data;
break;
default:
break;
}

View File

@@ -58,6 +58,8 @@ struct FunctionInfo {
uint64 lowpc;
// End address for this function.
uint64 highpc;
// Ranges offset
uint64 ranges;
};
struct SourceFileInfo {