mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
DebugInfo: Introduce the notion of "form classes"
Summary: Use DWARF4 table of form classes to fetch attributes from DIE in a more consistent way. This shouldn't change the functionality and serves as a refactoring for upcoming change: DW_AT_high_pc has different semantics depending on its form class. Reviewers: dblaikie, echristo Reviewed By: echristo CC: echristo, llvm-commits Differential Revision: http://llvm-reviews.chandlerc.com/D1961 llvm-svn: 193553
This commit is contained in:
parent
918eded7e7
commit
c8dd7e63e8
@ -10,6 +10,7 @@
|
|||||||
#ifndef LLVM_DEBUGINFO_DWARFFORMVALUE_H
|
#ifndef LLVM_DEBUGINFO_DWARFFORMVALUE_H
|
||||||
#define LLVM_DEBUGINFO_DWARFFORMVALUE_H
|
#define LLVM_DEBUGINFO_DWARFFORMVALUE_H
|
||||||
|
|
||||||
|
#include "llvm/ADT/Optional.h"
|
||||||
#include "llvm/Support/DataExtractor.h"
|
#include "llvm/Support/DataExtractor.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
@ -18,6 +19,21 @@ class DWARFUnit;
|
|||||||
class raw_ostream;
|
class raw_ostream;
|
||||||
|
|
||||||
class DWARFFormValue {
|
class DWARFFormValue {
|
||||||
|
public:
|
||||||
|
enum FormClass {
|
||||||
|
FC_Unknown,
|
||||||
|
FC_Address,
|
||||||
|
FC_Block,
|
||||||
|
FC_Constant,
|
||||||
|
FC_String,
|
||||||
|
FC_Flag,
|
||||||
|
FC_Reference,
|
||||||
|
FC_Indirect,
|
||||||
|
FC_SectionOffset,
|
||||||
|
FC_Exprloc
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
struct ValueType {
|
struct ValueType {
|
||||||
ValueType() : data(NULL) {
|
ValueType() : data(NULL) {
|
||||||
uval = 0;
|
uval = 0;
|
||||||
@ -35,9 +51,10 @@ class DWARFFormValue {
|
|||||||
ValueType Value; // Contains all data for the form.
|
ValueType Value; // Contains all data for the form.
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DWARFFormValue(uint16_t form = 0) : Form(form) {}
|
DWARFFormValue(uint16_t Form = 0) : Form(Form) {}
|
||||||
uint16_t getForm() const { return Form; }
|
uint16_t getForm() const { return Form; }
|
||||||
const ValueType& value() const { return Value; }
|
bool isFormClass(FormClass FC) const;
|
||||||
|
|
||||||
void dump(raw_ostream &OS, const DWARFUnit *U) const;
|
void dump(raw_ostream &OS, const DWARFUnit *U) const;
|
||||||
bool extractValue(DataExtractor data, uint32_t *offset_ptr,
|
bool extractValue(DataExtractor data, uint32_t *offset_ptr,
|
||||||
const DWARFUnit *u);
|
const DWARFUnit *u);
|
||||||
@ -45,11 +62,13 @@ public:
|
|||||||
return Value.data != NULL && Value.data == (const uint8_t*)Value.cstr;
|
return Value.data != NULL && Value.data == (const uint8_t*)Value.cstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t getReference(const DWARFUnit *U) const;
|
/// getAsFoo functions below return the extracted value as Foo if only
|
||||||
uint64_t getUnsigned() const { return Value.uval; }
|
/// DWARFFormValue has form class is suitable for representing Foo.
|
||||||
int64_t getSigned() const { return Value.sval; }
|
Optional<uint64_t> getAsReference(const DWARFUnit *U) const;
|
||||||
const char *getAsCString(const DWARFUnit *U) const;
|
Optional<uint64_t> getAsUnsignedConstant() const;
|
||||||
uint64_t getAsAddress(const DWARFUnit *U) const;
|
Optional<const char *> getAsCString(const DWARFUnit *U) const;
|
||||||
|
Optional<uint64_t> getAsAddress(const DWARFUnit *U) const;
|
||||||
|
Optional<uint64_t> getAsSectionOffset() const;
|
||||||
|
|
||||||
bool skipValue(DataExtractor debug_info_data, uint32_t *offset_ptr,
|
bool skipValue(DataExtractor debug_info_data, uint32_t *offset_ptr,
|
||||||
const DWARFUnit *u) const;
|
const DWARFUnit *u) const;
|
||||||
|
@ -102,8 +102,8 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) {
|
|||||||
DWARFCompileUnit *cu = getCompileUnitAtIndex(i);
|
DWARFCompileUnit *cu = getCompileUnitAtIndex(i);
|
||||||
savedAddressByteSize = cu->getAddressByteSize();
|
savedAddressByteSize = cu->getAddressByteSize();
|
||||||
unsigned stmtOffset =
|
unsigned stmtOffset =
|
||||||
cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list,
|
cu->getCompileUnitDIE()->getAttributeValueAsSectionOffset(
|
||||||
-1U);
|
cu, DW_AT_stmt_list, -1U);
|
||||||
if (stmtOffset != -1U) {
|
if (stmtOffset != -1U) {
|
||||||
DataExtractor lineData(getLineSection().Data, isLittleEndian(),
|
DataExtractor lineData(getLineSection().Data, isLittleEndian(),
|
||||||
savedAddressByteSize);
|
savedAddressByteSize);
|
||||||
@ -262,8 +262,8 @@ DWARFContext::getLineTableForCompileUnit(DWARFCompileUnit *cu) {
|
|||||||
Line.reset(new DWARFDebugLine(&getLineSection().Relocs));
|
Line.reset(new DWARFDebugLine(&getLineSection().Relocs));
|
||||||
|
|
||||||
unsigned stmtOffset =
|
unsigned stmtOffset =
|
||||||
cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list,
|
cu->getCompileUnitDIE()->getAttributeValueAsSectionOffset(
|
||||||
-1U);
|
cu, DW_AT_stmt_list, -1U);
|
||||||
if (stmtOffset == -1U)
|
if (stmtOffset == -1U)
|
||||||
return 0; // No line table for this compile unit.
|
return 0; // No line table for this compile unit.
|
||||||
|
|
||||||
|
@ -160,8 +160,11 @@ bool DWARFDebugInfoEntryMinimal::extract(const DWARFUnit *U,
|
|||||||
((Attr == DW_AT_entry_pc) || (Attr == DW_AT_low_pc))) {
|
((Attr == DW_AT_entry_pc) || (Attr == DW_AT_low_pc))) {
|
||||||
DWARFFormValue FormValue(Form);
|
DWARFFormValue FormValue(Form);
|
||||||
if (FormValue.extractValue(DebugInfoData, OffsetPtr, U)) {
|
if (FormValue.extractValue(DebugInfoData, OffsetPtr, U)) {
|
||||||
if (Attr == DW_AT_low_pc || Attr == DW_AT_entry_pc)
|
if (Attr == DW_AT_low_pc || Attr == DW_AT_entry_pc) {
|
||||||
const_cast<DWARFUnit *>(U)->setBaseAddress(FormValue.getUnsigned());
|
Optional<uint64_t> BaseAddr = FormValue.getAsAddress(U);
|
||||||
|
if (BaseAddr.hasValue())
|
||||||
|
const_cast<DWARFUnit *>(U)->setBaseAddress(BaseAddr.getValue());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (!DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr, U)) {
|
} else if (!DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr, U)) {
|
||||||
// Restore the original offset.
|
// Restore the original offset.
|
||||||
@ -210,33 +213,46 @@ bool DWARFDebugInfoEntryMinimal::getAttributeValue(
|
|||||||
const char *DWARFDebugInfoEntryMinimal::getAttributeValueAsString(
|
const char *DWARFDebugInfoEntryMinimal::getAttributeValueAsString(
|
||||||
const DWARFUnit *U, const uint16_t Attr, const char *FailValue) const {
|
const DWARFUnit *U, const uint16_t Attr, const char *FailValue) const {
|
||||||
DWARFFormValue FormValue;
|
DWARFFormValue FormValue;
|
||||||
if (getAttributeValue(U, Attr, FormValue))
|
if (!getAttributeValue(U, Attr, FormValue))
|
||||||
return FormValue.getAsCString(U);
|
return FailValue;
|
||||||
return FailValue;
|
Optional<const char *> Result = FormValue.getAsCString(U);
|
||||||
|
return Result.hasValue() ? Result.getValue() : FailValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsAddress(
|
uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsAddress(
|
||||||
const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const {
|
const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const {
|
||||||
DWARFFormValue FormValue;
|
DWARFFormValue FormValue;
|
||||||
if (getAttributeValue(U, Attr, FormValue))
|
if (!getAttributeValue(U, Attr, FormValue))
|
||||||
return FormValue.getAsAddress(U);
|
return FailValue;
|
||||||
return FailValue;
|
Optional<uint64_t> Result = FormValue.getAsAddress(U);
|
||||||
|
return Result.hasValue() ? Result.getValue() : FailValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsUnsigned(
|
uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsUnsignedConstant(
|
||||||
const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const {
|
const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const {
|
||||||
DWARFFormValue FormValue;
|
DWARFFormValue FormValue;
|
||||||
if (getAttributeValue(U, Attr, FormValue))
|
if (!getAttributeValue(U, Attr, FormValue))
|
||||||
return FormValue.getUnsigned();
|
return FailValue;
|
||||||
return FailValue;
|
Optional<uint64_t> Result = FormValue.getAsUnsignedConstant();
|
||||||
|
return Result.hasValue() ? Result.getValue() : FailValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsReference(
|
uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsReference(
|
||||||
const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const {
|
const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const {
|
||||||
DWARFFormValue FormValue;
|
DWARFFormValue FormValue;
|
||||||
if (getAttributeValue(U, Attr, FormValue))
|
if (!getAttributeValue(U, Attr, FormValue))
|
||||||
return FormValue.getReference(U);
|
return FailValue;
|
||||||
return FailValue;
|
Optional<uint64_t> Result = FormValue.getAsReference(U);
|
||||||
|
return Result.hasValue() ? Result.getValue() : FailValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsSectionOffset(
|
||||||
|
const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const {
|
||||||
|
DWARFFormValue FormValue;
|
||||||
|
if (!getAttributeValue(U, Attr, FormValue))
|
||||||
|
return FailValue;
|
||||||
|
Optional<uint64_t> Result = FormValue.getAsSectionOffset();
|
||||||
|
return Result.hasValue() ? Result.getValue() : FailValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DWARFDebugInfoEntryMinimal::getLowAndHighPC(const DWARFUnit *U,
|
bool DWARFDebugInfoEntryMinimal::getLowAndHighPC(const DWARFUnit *U,
|
||||||
@ -277,7 +293,8 @@ bool DWARFDebugInfoEntryMinimal::addressRangeContainsAddress(
|
|||||||
if (getLowAndHighPC(U, LowPC, HighPC))
|
if (getLowAndHighPC(U, LowPC, HighPC))
|
||||||
return (LowPC <= Address && Address <= HighPC);
|
return (LowPC <= Address && Address <= HighPC);
|
||||||
// Try to get address ranges from .debug_ranges section.
|
// Try to get address ranges from .debug_ranges section.
|
||||||
uint32_t RangesOffset = getAttributeValueAsReference(U, DW_AT_ranges, -1U);
|
uint32_t RangesOffset =
|
||||||
|
getAttributeValueAsSectionOffset(U, DW_AT_ranges, -1U);
|
||||||
if (RangesOffset != -1U) {
|
if (RangesOffset != -1U) {
|
||||||
DWARFDebugRangeList RangeList;
|
DWARFDebugRangeList RangeList;
|
||||||
if (U->extractRangeList(RangesOffset, RangeList))
|
if (U->extractRangeList(RangesOffset, RangeList))
|
||||||
@ -325,9 +342,9 @@ void DWARFDebugInfoEntryMinimal::getCallerFrame(const DWARFUnit *U,
|
|||||||
uint32_t &CallFile,
|
uint32_t &CallFile,
|
||||||
uint32_t &CallLine,
|
uint32_t &CallLine,
|
||||||
uint32_t &CallColumn) const {
|
uint32_t &CallColumn) const {
|
||||||
CallFile = getAttributeValueAsUnsigned(U, DW_AT_call_file, 0);
|
CallFile = getAttributeValueAsUnsignedConstant(U, DW_AT_call_file, 0);
|
||||||
CallLine = getAttributeValueAsUnsigned(U, DW_AT_call_line, 0);
|
CallLine = getAttributeValueAsUnsignedConstant(U, DW_AT_call_line, 0);
|
||||||
CallColumn = getAttributeValueAsUnsigned(U, DW_AT_call_column, 0);
|
CallColumn = getAttributeValueAsUnsignedConstant(U, DW_AT_call_column, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
DWARFDebugInfoEntryInlinedChain
|
DWARFDebugInfoEntryInlinedChain
|
||||||
|
@ -129,12 +129,17 @@ public:
|
|||||||
uint64_t getAttributeValueAsAddress(const DWARFUnit *U, const uint16_t Attr,
|
uint64_t getAttributeValueAsAddress(const DWARFUnit *U, const uint16_t Attr,
|
||||||
uint64_t FailValue) const;
|
uint64_t FailValue) const;
|
||||||
|
|
||||||
uint64_t getAttributeValueAsUnsigned(const DWARFUnit *U, const uint16_t Attr,
|
uint64_t getAttributeValueAsUnsignedConstant(const DWARFUnit *U,
|
||||||
uint64_t FailValue) const;
|
const uint16_t Attr,
|
||||||
|
uint64_t FailValue) const;
|
||||||
|
|
||||||
uint64_t getAttributeValueAsReference(const DWARFUnit *U, const uint16_t Attr,
|
uint64_t getAttributeValueAsReference(const DWARFUnit *U, const uint16_t Attr,
|
||||||
uint64_t FailValue) const;
|
uint64_t FailValue) const;
|
||||||
|
|
||||||
|
uint64_t getAttributeValueAsSectionOffset(const DWARFUnit *U,
|
||||||
|
const uint16_t Attr,
|
||||||
|
uint64_t FailValue) const;
|
||||||
|
|
||||||
/// Retrieves DW_AT_low_pc and DW_AT_high_pc from CU.
|
/// Retrieves DW_AT_low_pc and DW_AT_high_pc from CU.
|
||||||
/// Returns true if both attributes are present.
|
/// Returns true if both attributes are present.
|
||||||
bool getLowAndHighPC(const DWARFUnit *U, uint64_t &LowPC,
|
bool getLowAndHighPC(const DWARFUnit *U, uint64_t &LowPC,
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
#include "llvm/DebugInfo/DWARFFormValue.h"
|
#include "llvm/DebugInfo/DWARFFormValue.h"
|
||||||
#include "DWARFCompileUnit.h"
|
#include "DWARFCompileUnit.h"
|
||||||
#include "DWARFContext.h"
|
#include "DWARFContext.h"
|
||||||
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
|
#include "llvm/ADT/StringRef.h"
|
||||||
#include "llvm/Support/Debug.h"
|
#include "llvm/Support/Debug.h"
|
||||||
#include "llvm/Support/Dwarf.h"
|
#include "llvm/Support/Dwarf.h"
|
||||||
#include "llvm/Support/Format.h"
|
#include "llvm/Support/Format.h"
|
||||||
@ -74,6 +76,57 @@ DWARFFormValue::getFixedFormSizes(uint8_t AddrSize, uint16_t Version) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const DWARFFormValue::FormClass DWARF4FormClasses[] = {
|
||||||
|
DWARFFormValue::FC_Unknown, // 0x0
|
||||||
|
DWARFFormValue::FC_Address, // 0x01 DW_FORM_addr
|
||||||
|
DWARFFormValue::FC_Unknown, // 0x02 unused
|
||||||
|
DWARFFormValue::FC_Block, // 0x03 DW_FORM_block2
|
||||||
|
DWARFFormValue::FC_Block, // 0x04 DW_FORM_block4
|
||||||
|
DWARFFormValue::FC_Constant, // 0x05 DW_FORM_data2
|
||||||
|
// --- These can be FC_SectionOffset in DWARF3 and below:
|
||||||
|
DWARFFormValue::FC_Constant, // 0x06 DW_FORM_data4
|
||||||
|
DWARFFormValue::FC_Constant, // 0x07 DW_FORM_data8
|
||||||
|
// ---
|
||||||
|
DWARFFormValue::FC_String, // 0x08 DW_FORM_string
|
||||||
|
DWARFFormValue::FC_Block, // 0x09 DW_FORM_block
|
||||||
|
DWARFFormValue::FC_Block, // 0x0a DW_FORM_block1
|
||||||
|
DWARFFormValue::FC_Constant, // 0x0b DW_FORM_data1
|
||||||
|
DWARFFormValue::FC_Flag, // 0x0c DW_FORM_flag
|
||||||
|
DWARFFormValue::FC_Constant, // 0x0d DW_FORM_sdata
|
||||||
|
DWARFFormValue::FC_String, // 0x0e DW_FORM_strp
|
||||||
|
DWARFFormValue::FC_Constant, // 0x0f DW_FORM_udata
|
||||||
|
DWARFFormValue::FC_Reference, // 0x10 DW_FORM_ref_addr
|
||||||
|
DWARFFormValue::FC_Reference, // 0x11 DW_FORM_ref1
|
||||||
|
DWARFFormValue::FC_Reference, // 0x12 DW_FORM_ref2
|
||||||
|
DWARFFormValue::FC_Reference, // 0x13 DW_FORM_ref4
|
||||||
|
DWARFFormValue::FC_Reference, // 0x14 DW_FORM_ref8
|
||||||
|
DWARFFormValue::FC_Reference, // 0x15 DW_FORM_ref_udata
|
||||||
|
DWARFFormValue::FC_Indirect, // 0x16 DW_FORM_indirect
|
||||||
|
DWARFFormValue::FC_SectionOffset, // 0x17 DW_FORM_sec_offset
|
||||||
|
DWARFFormValue::FC_Exprloc, // 0x18 DW_FORM_exprloc
|
||||||
|
DWARFFormValue::FC_Flag, // 0x19 DW_FORM_flag_present
|
||||||
|
DWARFFormValue::FC_Reference, // 0x20 DW_FORM_ref_sig8
|
||||||
|
};
|
||||||
|
|
||||||
|
bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const {
|
||||||
|
// First, check DWARF4 form classes.
|
||||||
|
if (Form < ArrayRef<FormClass>(DWARF4FormClasses).size() &&
|
||||||
|
DWARF4FormClasses[Form] == FC)
|
||||||
|
return true;
|
||||||
|
// Check for some DWARF5 forms.
|
||||||
|
if (Form == DW_FORM_GNU_addr_index)
|
||||||
|
return (FC == FC_Address);
|
||||||
|
if (Form == DW_FORM_GNU_str_index)
|
||||||
|
return (FC == FC_String);
|
||||||
|
// In DWARF3 DW_FORM_data4 and DW_FORM_data8 served also as a section offset.
|
||||||
|
// Don't check for DWARF version here, as some producers may still do this
|
||||||
|
// by mistake.
|
||||||
|
if ((Form == DW_FORM_data4 || Form == DW_FORM_data8) &&
|
||||||
|
FC == FC_SectionOffset)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
|
bool DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
|
||||||
const DWARFUnit *cu) {
|
const DWARFUnit *cu) {
|
||||||
bool indirect = false;
|
bool indirect = false;
|
||||||
@ -155,10 +208,6 @@ bool DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
|
|||||||
break;
|
break;
|
||||||
case DW_FORM_string:
|
case DW_FORM_string:
|
||||||
Value.cstr = data.getCStr(offset_ptr);
|
Value.cstr = data.getCStr(offset_ptr);
|
||||||
// Set the string value to also be the data for inlined cstr form
|
|
||||||
// values only so we can tell the differnence between DW_FORM_string
|
|
||||||
// and DW_FORM_strp form values
|
|
||||||
Value.data = (const uint8_t*)Value.cstr;
|
|
||||||
break;
|
break;
|
||||||
case DW_FORM_indirect:
|
case DW_FORM_indirect:
|
||||||
Form = data.getULEB128(offset_ptr);
|
Form = data.getULEB128(offset_ptr);
|
||||||
@ -313,7 +362,7 @@ void
|
|||||||
DWARFFormValue::dump(raw_ostream &OS, const DWARFUnit *cu) const {
|
DWARFFormValue::dump(raw_ostream &OS, const DWARFUnit *cu) const {
|
||||||
DataExtractor debug_str_data(cu->getStringSection(), true, 0);
|
DataExtractor debug_str_data(cu->getStringSection(), true, 0);
|
||||||
DataExtractor debug_str_offset_data(cu->getStringOffsetSection(), true, 0);
|
DataExtractor debug_str_offset_data(cu->getStringOffsetSection(), true, 0);
|
||||||
uint64_t uvalue = getUnsigned();
|
uint64_t uvalue = Value.uval;
|
||||||
bool cu_relative_offset = false;
|
bool cu_relative_offset = false;
|
||||||
|
|
||||||
switch (Form) {
|
switch (Form) {
|
||||||
@ -336,7 +385,7 @@ DWARFFormValue::dump(raw_ostream &OS, const DWARFUnit *cu) const {
|
|||||||
case DW_FORM_data8: OS << format("0x%016" PRIx64, uvalue); break;
|
case DW_FORM_data8: OS << format("0x%016" PRIx64, uvalue); break;
|
||||||
case DW_FORM_string:
|
case DW_FORM_string:
|
||||||
OS << '"';
|
OS << '"';
|
||||||
OS.write_escaped(getAsCString(NULL));
|
OS.write_escaped(Value.cstr);
|
||||||
OS << '"';
|
OS << '"';
|
||||||
break;
|
break;
|
||||||
case DW_FORM_exprloc:
|
case DW_FORM_exprloc:
|
||||||
@ -368,24 +417,24 @@ DWARFFormValue::dump(raw_ostream &OS, const DWARFUnit *cu) const {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_FORM_sdata: OS << getSigned(); break;
|
case DW_FORM_sdata: OS << Value.sval; break;
|
||||||
case DW_FORM_udata: OS << getUnsigned(); break;
|
case DW_FORM_udata: OS << Value.uval; break;
|
||||||
case DW_FORM_strp: {
|
case DW_FORM_strp: {
|
||||||
OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue);
|
OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue);
|
||||||
const char* dbg_str = getAsCString(cu);
|
Optional<const char *> DbgStr = getAsCString(cu);
|
||||||
if (dbg_str) {
|
if (DbgStr.hasValue()) {
|
||||||
OS << '"';
|
OS << '"';
|
||||||
OS.write_escaped(dbg_str);
|
OS.write_escaped(DbgStr.getValue());
|
||||||
OS << '"';
|
OS << '"';
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DW_FORM_GNU_str_index: {
|
case DW_FORM_GNU_str_index: {
|
||||||
OS << format(" indexed (%8.8x) string = ", (uint32_t)uvalue);
|
OS << format(" indexed (%8.8x) string = ", (uint32_t)uvalue);
|
||||||
const char *dbg_str = getAsCString(cu);
|
Optional<const char *> DbgStr = getAsCString(cu);
|
||||||
if (dbg_str) {
|
if (DbgStr.hasValue()) {
|
||||||
OS << '"';
|
OS << '"';
|
||||||
OS.write_escaped(dbg_str);
|
OS.write_escaped(DbgStr.getValue());
|
||||||
OS << '"';
|
OS << '"';
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -434,47 +483,67 @@ DWARFFormValue::dump(raw_ostream &OS, const DWARFUnit *cu) const {
|
|||||||
OS << format(" => {0x%8.8" PRIx64 "}", uvalue + (cu ? cu->getOffset() : 0));
|
OS << format(" => {0x%8.8" PRIx64 "}", uvalue + (cu ? cu->getOffset() : 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *DWARFFormValue::getAsCString(const DWARFUnit *CU) const {
|
Optional<const char *> DWARFFormValue::getAsCString(const DWARFUnit *U) const {
|
||||||
if (isInlinedCStr())
|
if (!isFormClass(FC_String))
|
||||||
|
return None;
|
||||||
|
if (Form == DW_FORM_string)
|
||||||
return Value.cstr;
|
return Value.cstr;
|
||||||
if (!CU)
|
if (U == 0)
|
||||||
return NULL;
|
return None;
|
||||||
uint32_t Offset = Value.uval;
|
uint32_t Offset = Value.uval;
|
||||||
if (Form == DW_FORM_GNU_str_index) {
|
if (Form == DW_FORM_GNU_str_index) {
|
||||||
uint32_t StrOffset;
|
uint32_t StrOffset;
|
||||||
if (!CU->getStringOffsetSectionItem(Offset, StrOffset))
|
if (!U->getStringOffsetSectionItem(Offset, StrOffset))
|
||||||
return NULL;
|
return None;
|
||||||
Offset = StrOffset;
|
Offset = StrOffset;
|
||||||
}
|
}
|
||||||
return CU->getStringExtractor().getCStr(&Offset);
|
if (const char *Str = U->getStringExtractor().getCStr(&Offset)) {
|
||||||
|
return Str;
|
||||||
|
}
|
||||||
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t DWARFFormValue::getAsAddress(const DWARFUnit *CU) const {
|
Optional<uint64_t> DWARFFormValue::getAsAddress(const DWARFUnit *U) const {
|
||||||
if (!CU)
|
if (!isFormClass(FC_Address))
|
||||||
return 0;
|
return None;
|
||||||
if (Form == DW_FORM_GNU_addr_index) {
|
if (Form == DW_FORM_GNU_addr_index) {
|
||||||
uint32_t Index = Value.uval;
|
uint32_t Index = Value.uval;
|
||||||
uint64_t Address;
|
uint64_t Result;
|
||||||
if (!CU->getAddrOffsetSectionItem(Index, Address))
|
if (U == 0 || !U->getAddrOffsetSectionItem(Index, Result))
|
||||||
return 0;
|
return None;
|
||||||
return Address;
|
return Result;
|
||||||
}
|
}
|
||||||
return Value.uval;
|
return Value.uval;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t DWARFFormValue::getReference(const DWARFUnit *cu) const {
|
Optional<uint64_t> DWARFFormValue::getAsReference(const DWARFUnit *U) const {
|
||||||
uint64_t die_offset = Value.uval;
|
if (!isFormClass(FC_Reference))
|
||||||
|
return None;
|
||||||
switch (Form) {
|
switch (Form) {
|
||||||
case DW_FORM_ref1:
|
case DW_FORM_ref1:
|
||||||
case DW_FORM_ref2:
|
case DW_FORM_ref2:
|
||||||
case DW_FORM_ref4:
|
case DW_FORM_ref4:
|
||||||
case DW_FORM_ref8:
|
case DW_FORM_ref8:
|
||||||
case DW_FORM_ref_udata:
|
case DW_FORM_ref_udata:
|
||||||
die_offset += (cu ? cu->getOffset() : 0);
|
if (U == 0)
|
||||||
break;
|
return None;
|
||||||
|
return Value.uval + U->getOffset();
|
||||||
|
case DW_FORM_ref_addr:
|
||||||
|
return Value.uval;
|
||||||
|
// FIXME: Add proper support for DW_FORM_ref_sig8
|
||||||
default:
|
default:
|
||||||
break;
|
return Value.uval;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return die_offset;
|
|
||||||
|
Optional<uint64_t> DWARFFormValue::getAsSectionOffset() const {
|
||||||
|
if (!isFormClass(FC_SectionOffset))
|
||||||
|
return None;
|
||||||
|
return Value.uval;
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<uint64_t> DWARFFormValue::getAsUnsignedConstant() const {
|
||||||
|
if (!isFormClass(FC_Constant) || Form == DW_FORM_sdata)
|
||||||
|
return None;
|
||||||
|
return Value.uval;
|
||||||
}
|
}
|
||||||
|
@ -144,7 +144,7 @@ uint64_t DWARFUnit::getDWOId() {
|
|||||||
if (DieArray.empty())
|
if (DieArray.empty())
|
||||||
return FailValue;
|
return FailValue;
|
||||||
return DieArray[0]
|
return DieArray[0]
|
||||||
.getAttributeValueAsUnsigned(this, DW_AT_GNU_dwo_id, FailValue);
|
.getAttributeValueAsUnsignedConstant(this, DW_AT_GNU_dwo_id, FailValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DWARFUnit::setDIERelations() {
|
void DWARFUnit::setDIERelations() {
|
||||||
@ -251,14 +251,14 @@ size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) {
|
|||||||
// If CU DIE was just parsed, copy several attribute values from it.
|
// If CU DIE was just parsed, copy several attribute values from it.
|
||||||
if (!HasCUDie) {
|
if (!HasCUDie) {
|
||||||
uint64_t BaseAddr =
|
uint64_t BaseAddr =
|
||||||
DieArray[0].getAttributeValueAsUnsigned(this, DW_AT_low_pc, -1U);
|
DieArray[0].getAttributeValueAsAddress(this, DW_AT_low_pc, -1ULL);
|
||||||
if (BaseAddr == -1U)
|
if (BaseAddr == -1ULL)
|
||||||
BaseAddr = DieArray[0].getAttributeValueAsUnsigned(this, DW_AT_entry_pc, 0);
|
BaseAddr = DieArray[0].getAttributeValueAsAddress(this, DW_AT_entry_pc, 0);
|
||||||
setBaseAddress(BaseAddr);
|
setBaseAddress(BaseAddr);
|
||||||
AddrOffsetSectionBase =
|
AddrOffsetSectionBase = DieArray[0].getAttributeValueAsSectionOffset(
|
||||||
DieArray[0].getAttributeValueAsReference(this, DW_AT_GNU_addr_base, 0);
|
this, DW_AT_GNU_addr_base, 0);
|
||||||
RangeSectionBase =
|
RangeSectionBase = DieArray[0].getAttributeValueAsSectionOffset(
|
||||||
DieArray[0].getAttributeValueAsReference(this, DW_AT_GNU_ranges_base, 0);
|
this, DW_AT_GNU_ranges_base, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
setDIERelations();
|
setDIERelations();
|
||||||
|
@ -28,4 +28,21 @@ TEST(DWARFFormValue, FixedFormSizes) {
|
|||||||
EXPECT_EQ(0, DWARFFormValue::getFixedFormSizes(16, 2));
|
EXPECT_EQ(0, DWARFFormValue::getFixedFormSizes(16, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isFormClass(uint16_t Form, DWARFFormValue::FormClass FC) {
|
||||||
|
return DWARFFormValue(Form).isFormClass(FC);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(DWARFFormValue, FormClass) {
|
||||||
|
EXPECT_TRUE(isFormClass(DW_FORM_addr, DWARFFormValue::FC_Address));
|
||||||
|
EXPECT_FALSE(isFormClass(DW_FORM_data8, DWARFFormValue::FC_Address));
|
||||||
|
EXPECT_TRUE(isFormClass(DW_FORM_data8, DWARFFormValue::FC_Constant));
|
||||||
|
EXPECT_TRUE(isFormClass(DW_FORM_data8, DWARFFormValue::FC_SectionOffset));
|
||||||
|
EXPECT_TRUE(
|
||||||
|
isFormClass(DW_FORM_sec_offset, DWARFFormValue::FC_SectionOffset));
|
||||||
|
EXPECT_TRUE(isFormClass(DW_FORM_GNU_str_index, DWARFFormValue::FC_String));
|
||||||
|
EXPECT_TRUE(isFormClass(DW_FORM_GNU_addr_index, DWARFFormValue::FC_Address));
|
||||||
|
EXPECT_FALSE(isFormClass(DW_FORM_ref_addr, DWARFFormValue::FC_Address));
|
||||||
|
EXPECT_TRUE(isFormClass(DW_FORM_ref_addr, DWARFFormValue::FC_Reference));
|
||||||
|
}
|
||||||
|
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
Loading…
Reference in New Issue
Block a user