mirror of
https://github.com/yuzu-emu/breakpad.git
synced 2024-11-28 00:14:14 +01:00
Add and handle various dwarf5 addrx forms.
Given the almost nonexistent direct dwarfreader tests, I think the best way to test these dwarf5 additions will be to add a full dwarf5 compilation unit similar to the ones used incidentally in the other tests. But I can't do that until enough dwarf5 is correctly implemented. Change-Id: I3418bda7212ae85c4b67232a2ab8fea9b9ca5d42 Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/2258838 Reviewed-by: Mark Mentovai <mark@chromium.org> Reviewed-by: Mike Frysinger <vapier@chromium.org>
This commit is contained in:
parent
feb2dca989
commit
72c118f4a6
@ -50,6 +50,17 @@ inline uint16_t ByteReader::ReadTwoBytes(const uint8_t *buffer) const {
|
||||
}
|
||||
}
|
||||
|
||||
inline uint64_t ByteReader::ReadThreeBytes(const uint8_t* buffer) const {
|
||||
const uint32_t buffer0 = buffer[0];
|
||||
const uint32_t buffer1 = buffer[1];
|
||||
const uint32_t buffer2 = buffer[2];
|
||||
if (endian_ == ENDIANNESS_LITTLE) {
|
||||
return buffer0 | buffer1 << 8 | buffer2 << 16;
|
||||
} else {
|
||||
return buffer2 | buffer1 << 8 | buffer0 << 16;
|
||||
}
|
||||
}
|
||||
|
||||
inline uint64_t ByteReader::ReadFourBytes(const uint8_t *buffer) const {
|
||||
const uint32_t buffer0 = buffer[0];
|
||||
const uint32_t buffer1 = buffer[1];
|
||||
|
@ -68,6 +68,11 @@ class ByteReader {
|
||||
// number, using this ByteReader's endianness.
|
||||
uint16_t ReadTwoBytes(const uint8_t *buffer) const;
|
||||
|
||||
// Read three bytes from BUFFER and return them as an unsigned 64 bit
|
||||
// number, using this ByteReader's endianness. DWARF 5 uses this encoding
|
||||
// for various index-related DW_FORMs.
|
||||
uint64_t ReadThreeBytes(const uint8_t* buffer) const;
|
||||
|
||||
// Read four bytes from BUFFER and return them as an unsigned 32 bit
|
||||
// number, using this ByteReader's endianness. This function returns
|
||||
// a uint64_t so that it is compatible with ReadAddress and
|
||||
|
@ -164,6 +164,12 @@ enum DwarfForm {
|
||||
DW_FORM_strx3 = 0x27,
|
||||
DW_FORM_strx4 = 0x28,
|
||||
|
||||
DW_FORM_addrx = 0x1b,
|
||||
DW_FORM_addrx1 = 0x29,
|
||||
DW_FORM_addrx2 = 0x2a,
|
||||
DW_FORM_addrx3 = 0x2b,
|
||||
DW_FORM_addrx4 = 0x2c,
|
||||
|
||||
// Extensions for Fission. See http://gcc.gnu.org/wiki/DebugFission.
|
||||
DW_FORM_GNU_addr_index = 0x1f01,
|
||||
DW_FORM_GNU_str_index = 0x1f02
|
||||
|
@ -182,17 +182,21 @@ const uint8_t *CompilationUnit::SkipAttribute(const uint8_t *start,
|
||||
|
||||
case DW_FORM_flag_present:
|
||||
return start;
|
||||
case DW_FORM_addrx1:
|
||||
case DW_FORM_data1:
|
||||
case DW_FORM_flag:
|
||||
case DW_FORM_ref1:
|
||||
case DW_FORM_strx1:
|
||||
return start + 1;
|
||||
case DW_FORM_addrx2:
|
||||
case DW_FORM_ref2:
|
||||
case DW_FORM_data2:
|
||||
case DW_FORM_strx2:
|
||||
return start + 2;
|
||||
case DW_FORM_addrx3:
|
||||
case DW_FORM_strx3:
|
||||
return start + 3;
|
||||
case DW_FORM_addrx4:
|
||||
case DW_FORM_ref4:
|
||||
case DW_FORM_data4:
|
||||
case DW_FORM_strx4:
|
||||
@ -208,6 +212,7 @@ const uint8_t *CompilationUnit::SkipAttribute(const uint8_t *start,
|
||||
case DW_FORM_strx:
|
||||
case DW_FORM_GNU_str_index:
|
||||
case DW_FORM_GNU_addr_index:
|
||||
case DW_FORM_addrx:
|
||||
reader_->ReadUnsignedLEB128(start, &len);
|
||||
return start + len;
|
||||
|
||||
@ -549,8 +554,7 @@ const uint8_t *CompilationUnit::ProcessAttribute(
|
||||
return start + 2;
|
||||
}
|
||||
case DW_FORM_strx3: {
|
||||
uint64_t str_index = reader_->ReadTwoBytes(start);
|
||||
str_index *= reader_->ReadOneByte(start + 2);
|
||||
uint64_t str_index = reader_->ReadThreeBytes(start);
|
||||
ProcessFormStringIndex(dieoffset, attr, form, str_index);
|
||||
return start + 3;
|
||||
}
|
||||
@ -560,14 +564,27 @@ const uint8_t *CompilationUnit::ProcessAttribute(
|
||||
return start + 4;
|
||||
}
|
||||
|
||||
case DW_FORM_GNU_addr_index: {
|
||||
uint64_t addr_index = reader_->ReadUnsignedLEB128(start, &len);
|
||||
const uint8_t* addr_ptr =
|
||||
addr_buffer_ + addr_base_ + addr_index * reader_->AddressSize();
|
||||
ProcessAttributeUnsigned(dieoffset, attr, form,
|
||||
reader_->ReadAddress(addr_ptr));
|
||||
case DW_FORM_addrx:
|
||||
case DW_FORM_GNU_addr_index:
|
||||
ProcessAttributeAddrIndex(
|
||||
dieoffset, attr, form, reader_->ReadUnsignedLEB128(start, &len));
|
||||
return start + len;
|
||||
}
|
||||
case DW_FORM_addrx1:
|
||||
ProcessAttributeAddrIndex(
|
||||
dieoffset, attr, form, reader_->ReadOneByte(start));
|
||||
return start + 1;
|
||||
case DW_FORM_addrx2:
|
||||
ProcessAttributeAddrIndex(
|
||||
dieoffset, attr, form, reader_->ReadTwoBytes(start));
|
||||
return start + 2;
|
||||
case DW_FORM_addrx3:
|
||||
ProcessAttributeAddrIndex(
|
||||
dieoffset, attr, form, reader_->ReadThreeBytes(start));
|
||||
return start + 3;
|
||||
case DW_FORM_addrx4:
|
||||
ProcessAttributeAddrIndex(
|
||||
dieoffset, attr, form, reader_->ReadFourBytes(start));
|
||||
return start + 4;
|
||||
}
|
||||
fprintf(stderr, "Unhandled form type\n");
|
||||
return NULL;
|
||||
|
@ -499,6 +499,18 @@ class CompilationUnit {
|
||||
handler_->ProcessAttributeString(offset, attr, form, data);
|
||||
}
|
||||
|
||||
// Called to handle common portions of DW_FORM_addrx and variations, as well
|
||||
// as DW_FORM_GNU_addr_index.
|
||||
void ProcessAttributeAddrIndex(uint64_t offset,
|
||||
enum DwarfAttribute attr,
|
||||
enum DwarfForm form,
|
||||
uint64_t addr_index) {
|
||||
const uint8_t* addr_ptr =
|
||||
addr_buffer_ + addr_base_ + addr_index * reader_->AddressSize();
|
||||
ProcessAttributeUnsigned(
|
||||
offset, attr, form, reader_->ReadAddress(addr_ptr));
|
||||
}
|
||||
|
||||
// Processes all DIEs for this compilation unit
|
||||
void ProcessDIEs();
|
||||
|
||||
|
@ -593,7 +593,12 @@ void DwarfCUToModule::FuncHandler::Finish() {
|
||||
if (!ranges_) {
|
||||
// Make high_pc_ an address, if it isn't already.
|
||||
if (high_pc_form_ != dwarf2reader::DW_FORM_addr &&
|
||||
high_pc_form_ != dwarf2reader::DW_FORM_GNU_addr_index) {
|
||||
high_pc_form_ != dwarf2reader::DW_FORM_GNU_addr_index &&
|
||||
high_pc_form_ != dwarf2reader::DW_FORM_addrx &&
|
||||
high_pc_form_ != dwarf2reader::DW_FORM_addrx1 &&
|
||||
high_pc_form_ != dwarf2reader::DW_FORM_addrx2 &&
|
||||
high_pc_form_ != dwarf2reader::DW_FORM_addrx3 &&
|
||||
high_pc_form_ != dwarf2reader::DW_FORM_addrx4) {
|
||||
high_pc_ += low_pc_;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user