aboutsummaryrefslogtreecommitdiffstats
path: root/lib/DebugInfo
diff options
context:
space:
mode:
authorAlexey Samsonov <samsonov@google.com>2013-10-28 23:01:48 +0000
committerAlexey Samsonov <samsonov@google.com>2013-10-28 23:01:48 +0000
commitc5253237f8b3b4eb888f7f85f39acd7d4d0f57cf (patch)
tree203b75962c5da40e7263f2ca12d9452fe602fef3 /lib/DebugInfo
parent730e3c69952d4f26a0c51b55902ac55c88238ee8 (diff)
downloadexternal_llvm-c5253237f8b3b4eb888f7f85f39acd7d4d0f57cf.zip
external_llvm-c5253237f8b3b4eb888f7f85f39acd7d4d0f57cf.tar.gz
external_llvm-c5253237f8b3b4eb888f7f85f39acd7d4d0f57cf.tar.bz2
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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@193553 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/DebugInfo')
-rw-r--r--lib/DebugInfo/DWARFContext.cpp8
-rw-r--r--lib/DebugInfo/DWARFDebugInfoEntry.cpp55
-rw-r--r--lib/DebugInfo/DWARFDebugInfoEntry.h9
-rw-r--r--lib/DebugInfo/DWARFFormValue.cpp137
-rw-r--r--lib/DebugInfo/DWARFUnit.cpp16
5 files changed, 158 insertions, 67 deletions
diff --git a/lib/DebugInfo/DWARFContext.cpp b/lib/DebugInfo/DWARFContext.cpp
index 9dc8f14..6056de7 100644
--- a/lib/DebugInfo/DWARFContext.cpp
+++ b/lib/DebugInfo/DWARFContext.cpp
@@ -102,8 +102,8 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) {
DWARFCompileUnit *cu = getCompileUnitAtIndex(i);
savedAddressByteSize = cu->getAddressByteSize();
unsigned stmtOffset =
- cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list,
- -1U);
+ cu->getCompileUnitDIE()->getAttributeValueAsSectionOffset(
+ cu, DW_AT_stmt_list, -1U);
if (stmtOffset != -1U) {
DataExtractor lineData(getLineSection().Data, isLittleEndian(),
savedAddressByteSize);
@@ -262,8 +262,8 @@ DWARFContext::getLineTableForCompileUnit(DWARFCompileUnit *cu) {
Line.reset(new DWARFDebugLine(&getLineSection().Relocs));
unsigned stmtOffset =
- cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list,
- -1U);
+ cu->getCompileUnitDIE()->getAttributeValueAsSectionOffset(
+ cu, DW_AT_stmt_list, -1U);
if (stmtOffset == -1U)
return 0; // No line table for this compile unit.
diff --git a/lib/DebugInfo/DWARFDebugInfoEntry.cpp b/lib/DebugInfo/DWARFDebugInfoEntry.cpp
index 9bb49df..e8b8748 100644
--- a/lib/DebugInfo/DWARFDebugInfoEntry.cpp
+++ b/lib/DebugInfo/DWARFDebugInfoEntry.cpp
@@ -160,8 +160,11 @@ bool DWARFDebugInfoEntryMinimal::extract(const DWARFUnit *U,
((Attr == DW_AT_entry_pc) || (Attr == DW_AT_low_pc))) {
DWARFFormValue FormValue(Form);
if (FormValue.extractValue(DebugInfoData, OffsetPtr, U)) {
- if (Attr == DW_AT_low_pc || Attr == DW_AT_entry_pc)
- const_cast<DWARFUnit *>(U)->setBaseAddress(FormValue.getUnsigned());
+ if (Attr == DW_AT_low_pc || Attr == DW_AT_entry_pc) {
+ 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)) {
// Restore the original offset.
@@ -210,33 +213,46 @@ bool DWARFDebugInfoEntryMinimal::getAttributeValue(
const char *DWARFDebugInfoEntryMinimal::getAttributeValueAsString(
const DWARFUnit *U, const uint16_t Attr, const char *FailValue) const {
DWARFFormValue FormValue;
- if (getAttributeValue(U, Attr, FormValue))
- return FormValue.getAsCString(U);
- return FailValue;
+ if (!getAttributeValue(U, Attr, FormValue))
+ return FailValue;
+ Optional<const char *> Result = FormValue.getAsCString(U);
+ return Result.hasValue() ? Result.getValue() : FailValue;
}
uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsAddress(
const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const {
DWARFFormValue FormValue;
- if (getAttributeValue(U, Attr, FormValue))
- return FormValue.getAsAddress(U);
- return FailValue;
+ if (!getAttributeValue(U, Attr, FormValue))
+ 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 {
DWARFFormValue FormValue;
- if (getAttributeValue(U, Attr, FormValue))
- return FormValue.getUnsigned();
- return FailValue;
+ if (!getAttributeValue(U, Attr, FormValue))
+ return FailValue;
+ Optional<uint64_t> Result = FormValue.getAsUnsignedConstant();
+ return Result.hasValue() ? Result.getValue() : FailValue;
}
uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsReference(
const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const {
DWARFFormValue FormValue;
- if (getAttributeValue(U, Attr, FormValue))
- return FormValue.getReference(U);
- return FailValue;
+ if (!getAttributeValue(U, Attr, FormValue))
+ 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,
@@ -277,7 +293,8 @@ bool DWARFDebugInfoEntryMinimal::addressRangeContainsAddress(
if (getLowAndHighPC(U, LowPC, HighPC))
return (LowPC <= Address && Address <= HighPC);
// 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) {
DWARFDebugRangeList RangeList;
if (U->extractRangeList(RangesOffset, RangeList))
@@ -325,9 +342,9 @@ void DWARFDebugInfoEntryMinimal::getCallerFrame(const DWARFUnit *U,
uint32_t &CallFile,
uint32_t &CallLine,
uint32_t &CallColumn) const {
- CallFile = getAttributeValueAsUnsigned(U, DW_AT_call_file, 0);
- CallLine = getAttributeValueAsUnsigned(U, DW_AT_call_line, 0);
- CallColumn = getAttributeValueAsUnsigned(U, DW_AT_call_column, 0);
+ CallFile = getAttributeValueAsUnsignedConstant(U, DW_AT_call_file, 0);
+ CallLine = getAttributeValueAsUnsignedConstant(U, DW_AT_call_line, 0);
+ CallColumn = getAttributeValueAsUnsignedConstant(U, DW_AT_call_column, 0);
}
DWARFDebugInfoEntryInlinedChain
diff --git a/lib/DebugInfo/DWARFDebugInfoEntry.h b/lib/DebugInfo/DWARFDebugInfoEntry.h
index e1d88ee..e073d87 100644
--- a/lib/DebugInfo/DWARFDebugInfoEntry.h
+++ b/lib/DebugInfo/DWARFDebugInfoEntry.h
@@ -129,12 +129,17 @@ public:
uint64_t getAttributeValueAsAddress(const DWARFUnit *U, const uint16_t Attr,
uint64_t FailValue) const;
- uint64_t getAttributeValueAsUnsigned(const DWARFUnit *U, const uint16_t Attr,
- uint64_t FailValue) const;
+ uint64_t getAttributeValueAsUnsignedConstant(const DWARFUnit *U,
+ const uint16_t Attr,
+ uint64_t FailValue) const;
uint64_t getAttributeValueAsReference(const DWARFUnit *U, const uint16_t Attr,
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.
/// Returns true if both attributes are present.
bool getLowAndHighPC(const DWARFUnit *U, uint64_t &LowPC,
diff --git a/lib/DebugInfo/DWARFFormValue.cpp b/lib/DebugInfo/DWARFFormValue.cpp
index 0dddb7e..1a59dd8 100644
--- a/lib/DebugInfo/DWARFFormValue.cpp
+++ b/lib/DebugInfo/DWARFFormValue.cpp
@@ -10,6 +10,8 @@
#include "llvm/DebugInfo/DWARFFormValue.h"
#include "DWARFCompileUnit.h"
#include "DWARFContext.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/Format.h"
@@ -74,6 +76,57 @@ DWARFFormValue::getFixedFormSizes(uint8_t AddrSize, uint16_t Version) {
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,
const DWARFUnit *cu) {
bool indirect = false;
@@ -155,10 +208,6 @@ bool DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
break;
case DW_FORM_string:
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;
case DW_FORM_indirect:
Form = data.getULEB128(offset_ptr);
@@ -313,7 +362,7 @@ void
DWARFFormValue::dump(raw_ostream &OS, const DWARFUnit *cu) const {
DataExtractor debug_str_data(cu->getStringSection(), 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;
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_string:
OS << '"';
- OS.write_escaped(getAsCString(NULL));
+ OS.write_escaped(Value.cstr);
OS << '"';
break;
case DW_FORM_exprloc:
@@ -368,24 +417,24 @@ DWARFFormValue::dump(raw_ostream &OS, const DWARFUnit *cu) const {
}
break;
- case DW_FORM_sdata: OS << getSigned(); break;
- case DW_FORM_udata: OS << getUnsigned(); break;
+ case DW_FORM_sdata: OS << Value.sval; break;
+ case DW_FORM_udata: OS << Value.uval; break;
case DW_FORM_strp: {
OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue);
- const char* dbg_str = getAsCString(cu);
- if (dbg_str) {
+ Optional<const char *> DbgStr = getAsCString(cu);
+ if (DbgStr.hasValue()) {
OS << '"';
- OS.write_escaped(dbg_str);
+ OS.write_escaped(DbgStr.getValue());
OS << '"';
}
break;
}
case DW_FORM_GNU_str_index: {
OS << format(" indexed (%8.8x) string = ", (uint32_t)uvalue);
- const char *dbg_str = getAsCString(cu);
- if (dbg_str) {
+ Optional<const char *> DbgStr = getAsCString(cu);
+ if (DbgStr.hasValue()) {
OS << '"';
- OS.write_escaped(dbg_str);
+ OS.write_escaped(DbgStr.getValue());
OS << '"';
}
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));
}
-const char *DWARFFormValue::getAsCString(const DWARFUnit *CU) const {
- if (isInlinedCStr())
+Optional<const char *> DWARFFormValue::getAsCString(const DWARFUnit *U) const {
+ if (!isFormClass(FC_String))
+ return None;
+ if (Form == DW_FORM_string)
return Value.cstr;
- if (!CU)
- return NULL;
+ if (U == 0)
+ return None;
uint32_t Offset = Value.uval;
if (Form == DW_FORM_GNU_str_index) {
uint32_t StrOffset;
- if (!CU->getStringOffsetSectionItem(Offset, StrOffset))
- return NULL;
+ if (!U->getStringOffsetSectionItem(Offset, StrOffset))
+ return None;
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 {
- if (!CU)
- return 0;
+Optional<uint64_t> DWARFFormValue::getAsAddress(const DWARFUnit *U) const {
+ if (!isFormClass(FC_Address))
+ return None;
if (Form == DW_FORM_GNU_addr_index) {
uint32_t Index = Value.uval;
- uint64_t Address;
- if (!CU->getAddrOffsetSectionItem(Index, Address))
- return 0;
- return Address;
+ uint64_t Result;
+ if (U == 0 || !U->getAddrOffsetSectionItem(Index, Result))
+ return None;
+ return Result;
}
return Value.uval;
}
-uint64_t DWARFFormValue::getReference(const DWARFUnit *cu) const {
- uint64_t die_offset = Value.uval;
+Optional<uint64_t> DWARFFormValue::getAsReference(const DWARFUnit *U) const {
+ if (!isFormClass(FC_Reference))
+ return None;
switch (Form) {
case DW_FORM_ref1:
case DW_FORM_ref2:
case DW_FORM_ref4:
case DW_FORM_ref8:
case DW_FORM_ref_udata:
- die_offset += (cu ? cu->getOffset() : 0);
- break;
+ if (U == 0)
+ 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:
- 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;
}
diff --git a/lib/DebugInfo/DWARFUnit.cpp b/lib/DebugInfo/DWARFUnit.cpp
index 770c65b..25062cd 100644
--- a/lib/DebugInfo/DWARFUnit.cpp
+++ b/lib/DebugInfo/DWARFUnit.cpp
@@ -144,7 +144,7 @@ uint64_t DWARFUnit::getDWOId() {
if (DieArray.empty())
return FailValue;
return DieArray[0]
- .getAttributeValueAsUnsigned(this, DW_AT_GNU_dwo_id, FailValue);
+ .getAttributeValueAsUnsignedConstant(this, DW_AT_GNU_dwo_id, FailValue);
}
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 (!HasCUDie) {
uint64_t BaseAddr =
- DieArray[0].getAttributeValueAsUnsigned(this, DW_AT_low_pc, -1U);
- if (BaseAddr == -1U)
- BaseAddr = DieArray[0].getAttributeValueAsUnsigned(this, DW_AT_entry_pc, 0);
+ DieArray[0].getAttributeValueAsAddress(this, DW_AT_low_pc, -1ULL);
+ if (BaseAddr == -1ULL)
+ BaseAddr = DieArray[0].getAttributeValueAsAddress(this, DW_AT_entry_pc, 0);
setBaseAddress(BaseAddr);
- AddrOffsetSectionBase =
- DieArray[0].getAttributeValueAsReference(this, DW_AT_GNU_addr_base, 0);
- RangeSectionBase =
- DieArray[0].getAttributeValueAsReference(this, DW_AT_GNU_ranges_base, 0);
+ AddrOffsetSectionBase = DieArray[0].getAttributeValueAsSectionOffset(
+ this, DW_AT_GNU_addr_base, 0);
+ RangeSectionBase = DieArray[0].getAttributeValueAsSectionOffset(
+ this, DW_AT_GNU_ranges_base, 0);
}
setDIERelations();