-//===-- DWARFDebugInfoEntry.cpp --------------------------------------------===//
+//===-- DWARFDebugInfoEntry.cpp -------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
uint32_t offset = Offset;
if (debug_info_data.isValidOffset(offset)) {
- uint64_t abbrCode = debug_info_data.getULEB128(&offset);
+ uint32_t abbrCode = debug_info_data.getULEB128(&offset);
OS << format("\n0x%8.8x: ", Offset);
if (abbrCode) {
if (AbbrevDecl) {
- OS.indent(indent) << TagString(AbbrevDecl->getTag())
- << format(" [%u] %c\n", abbrCode,
- AbbrevDecl->hasChildren() ? '*': ' ');
+ const char *tagString = TagString(getTag());
+ if (tagString)
+ OS.indent(indent) << tagString;
+ else
+ OS.indent(indent) << format("DW_TAG_Unknown_%x", getTag());
+ OS << format(" [%u] %c\n", abbrCode,
+ AbbrevDecl->hasChildren() ? '*' : ' ');
// Dump all data in the .debug_info for the attributes
const uint32_t numAttributes = AbbrevDecl->getNumAttributes();
uint16_t form,
unsigned indent) const {
OS << format("0x%8.8x: ", *offset_ptr);
- OS.indent(indent+2) << AttributeString(attr)
- << " [" << FormEncodingString(form) << ']';
+ OS.indent(indent+2);
+ const char *attrString = AttributeString(attr);
+ if (attrString)
+ OS << attrString;
+ else
+ OS << format("DW_AT_Unknown_%x", attr);
+ const char *formString = FormEncodingString(form);
+ if (formString)
+ OS << " [" << formString << ']';
+ else
+ OS << format(" [DW_FORM_Unknown_%x]", form);
DWARFFormValue formValue(form);
return;
OS << "\t(";
- formValue.dump(OS, 0, cu);
+ formValue.dump(OS, cu);
OS << ")\n";
}
DataExtractor debug_info_data = cu->getDebugInfoExtractor();
uint64_t abbrCode = debug_info_data.getULEB128(offset_ptr);
- assert (fixed_form_sizes); // For best performance this should be specified!
+ assert(fixed_form_sizes); // For best performance this should be specified!
if (abbrCode) {
uint32_t offset = *offset_ptr;
switch (form) {
// Blocks if inlined data that have a length field and the data bytes
// inlined in the .debug_info.
+ case DW_FORM_exprloc:
case DW_FORM_block:
form_size = debug_info_data.getULEB128(&offset);
break;
form_size = cu->getAddressByteSize();
break;
+ // 0 sized form.
+ case DW_FORM_flag_present:
+ form_size = 0;
+ break;
+
// 1 byte values
case DW_FORM_data1:
case DW_FORM_flag:
// 8 byte values
case DW_FORM_data8:
case DW_FORM_ref8:
+ case DW_FORM_ref_sig8:
form_size = 8;
break;
form = debug_info_data.getULEB128(&offset);
break;
+ case DW_FORM_sec_offset:
+ if (cu->getAddressByteSize() == 4)
+ debug_info_data.getU32(offset_ptr);
+ else
+ debug_info_data.getU64(offset_ptr);
+ break;
+
default:
*offset_ptr = Offset;
return false;
AbbrevDecl = NULL;
return true; // NULL debug tag entry
}
-
- return false;
}
bool
switch (form) {
// Blocks if inlined data that have a length field and the data
// bytes // inlined in the .debug_info
+ case DW_FORM_exprloc:
case DW_FORM_block:
form_size = debug_info_data.getULEB128(&offset);
break;
form_size = cu_addr_size;
break;
+ // 0 byte value
+ case DW_FORM_flag_present:
+ form_size = 0;
+ break;
+
// 1 byte values
case DW_FORM_data1:
case DW_FORM_flag:
// 8 byte values
case DW_FORM_data8:
case DW_FORM_ref8:
+ case DW_FORM_ref_sig8:
form_size = 8;
break;
form_is_indirect = true;
break;
+ case DW_FORM_sec_offset:
+ if (cu->getAddressByteSize() == 4)
+ debug_info_data.getU32(offset_ptr);
+ else
+ debug_info_data.getU64(offset_ptr);
+ break;
+
default:
*offset_ptr = offset;
return false;
return false;
}
+bool DWARFDebugInfoEntryMinimal::isSubprogramDIE() const {
+ return getTag() == DW_TAG_subprogram;
+}
+
+bool DWARFDebugInfoEntryMinimal::isSubroutineDIE() const {
+ uint32_t Tag = getTag();
+ return Tag == DW_TAG_subprogram ||
+ Tag == DW_TAG_inlined_subroutine;
+}
+
uint32_t
DWARFDebugInfoEntryMinimal::getAttributeValue(const DWARFCompileUnit *cu,
const uint16_t attr,
const char*
DWARFDebugInfoEntryMinimal::getAttributeValueAsString(
- const DWARFCompileUnit* cu,
- const uint16_t attr,
- const char* fail_value) const {
+ const DWARFCompileUnit* cu,
+ const uint16_t attr,
+ const char* fail_value)
+ const {
DWARFFormValue form_value;
if (getAttributeValue(cu, attr, form_value)) {
DataExtractor stringExtractor(cu->getContext().getStringSection(),
uint64_t
DWARFDebugInfoEntryMinimal::getAttributeValueAsUnsigned(
- const DWARFCompileUnit* cu,
- const uint16_t attr,
- uint64_t fail_value) const {
+ const DWARFCompileUnit* cu,
+ const uint16_t attr,
+ uint64_t fail_value) const {
DWARFFormValue form_value;
if (getAttributeValue(cu, attr, form_value))
return form_value.getUnsigned();
int64_t
DWARFDebugInfoEntryMinimal::getAttributeValueAsSigned(
- const DWARFCompileUnit* cu,
- const uint16_t attr,
- int64_t fail_value) const {
+ const DWARFCompileUnit* cu,
+ const uint16_t attr,
+ int64_t fail_value) const {
DWARFFormValue form_value;
if (getAttributeValue(cu, attr, form_value))
return form_value.getSigned();
}
uint64_t
-DWARFDebugInfoEntryMinimal::getAttributeValueAsReference(const DWARFCompileUnit* cu,
- const uint16_t attr,
- uint64_t fail_value) const {
+DWARFDebugInfoEntryMinimal::getAttributeValueAsReference(
+ const DWARFCompileUnit* cu,
+ const uint16_t attr,
+ uint64_t fail_value)
+ const {
DWARFFormValue form_value;
if (getAttributeValue(cu, attr, form_value))
return form_value.getReference(cu);
return fail_value;
}
+
+bool DWARFDebugInfoEntryMinimal::getLowAndHighPC(const DWARFCompileUnit *CU,
+ uint64_t &LowPC,
+ uint64_t &HighPC) const {
+ HighPC = -1ULL;
+ LowPC = getAttributeValueAsUnsigned(CU, DW_AT_low_pc, -1ULL);
+ if (LowPC != -1ULL)
+ HighPC = getAttributeValueAsUnsigned(CU, DW_AT_high_pc, -1ULL);
+ return (HighPC != -1ULL);
+}
+
+void
+DWARFDebugInfoEntryMinimal::buildAddressRangeTable(const DWARFCompileUnit *CU,
+ DWARFDebugAranges *DebugAranges)
+ const {
+ if (AbbrevDecl) {
+ if (isSubprogramDIE()) {
+ uint64_t LowPC, HighPC;
+ if (getLowAndHighPC(CU, LowPC, HighPC)) {
+ DebugAranges->appendRange(CU->getOffset(), LowPC, HighPC);
+ }
+ // FIXME: try to append ranges from .debug_ranges section.
+ }
+
+ const DWARFDebugInfoEntryMinimal *child = getFirstChild();
+ while (child) {
+ child->buildAddressRangeTable(CU, DebugAranges);
+ child = child->getSibling();
+ }
+ }
+}
+
+bool
+DWARFDebugInfoEntryMinimal::addressRangeContainsAddress(
+ const DWARFCompileUnit *CU,
+ const uint64_t Address)
+ const {
+ if (isNULL())
+ return false;
+ uint64_t LowPC, HighPC;
+ if (getLowAndHighPC(CU, LowPC, HighPC))
+ return (LowPC <= Address && Address <= HighPC);
+ // Try to get address ranges from .debug_ranges section.
+ uint32_t RangesOffset = getAttributeValueAsReference(CU, DW_AT_ranges, -1U);
+ if (RangesOffset != -1U) {
+ DWARFDebugRangeList RangeList;
+ if (CU->extractRangeList(RangesOffset, RangeList))
+ return RangeList.containsAddress(CU->getBaseAddress(), Address);
+ }
+ return false;
+}
+
+const char*
+DWARFDebugInfoEntryMinimal::getSubroutineName(const DWARFCompileUnit *CU)
+ const {
+ if (!isSubroutineDIE())
+ return 0;
+ // Try to get mangled name if possible.
+ if (const char *name =
+ getAttributeValueAsString(CU, DW_AT_MIPS_linkage_name, 0))
+ return name;
+ if (const char *name = getAttributeValueAsString(CU, DW_AT_linkage_name, 0))
+ return name;
+ if (const char *name = getAttributeValueAsString(CU, DW_AT_name, 0))
+ return name;
+ // Try to get name from specification DIE.
+ uint32_t spec_ref =
+ getAttributeValueAsReference(CU, DW_AT_specification, -1U);
+ if (spec_ref != -1U) {
+ DWARFDebugInfoEntryMinimal spec_die;
+ if (spec_die.extract(CU, &spec_ref)) {
+ if (const char *name = spec_die.getSubroutineName(CU))
+ return name;
+ }
+ }
+ // Try to get name from abstract origin DIE.
+ uint32_t abs_origin_ref =
+ getAttributeValueAsReference(CU, DW_AT_abstract_origin, -1U);
+ if (abs_origin_ref != -1U) {
+ DWARFDebugInfoEntryMinimal abs_origin_die;
+ if (abs_origin_die.extract(CU, &abs_origin_ref)) {
+ if (const char *name = abs_origin_die.getSubroutineName(CU))
+ return name;
+ }
+ }
+ return 0;
+}
+
+void DWARFDebugInfoEntryMinimal::getCallerFrame(const DWARFCompileUnit *CU,
+ uint32_t &CallFile,
+ uint32_t &CallLine,
+ uint32_t &CallColumn) const {
+ CallFile = getAttributeValueAsUnsigned(CU, DW_AT_call_file, 0);
+ CallLine = getAttributeValueAsUnsigned(CU, DW_AT_call_line, 0);
+ CallColumn = getAttributeValueAsUnsigned(CU, DW_AT_call_column, 0);
+}
+
+DWARFDebugInfoEntryMinimal::InlinedChain
+DWARFDebugInfoEntryMinimal::getInlinedChainForAddress(
+ const DWARFCompileUnit *CU,
+ const uint64_t Address)
+ const {
+ DWARFDebugInfoEntryMinimal::InlinedChain InlinedChain;
+ if (isNULL())
+ return InlinedChain;
+ for (const DWARFDebugInfoEntryMinimal *DIE = this; DIE; ) {
+ // Append current DIE to inlined chain only if it has correct tag
+ // (e.g. it is not a lexical block).
+ if (DIE->isSubroutineDIE()) {
+ InlinedChain.push_back(*DIE);
+ }
+ // Try to get child which also contains provided address.
+ const DWARFDebugInfoEntryMinimal *Child = DIE->getFirstChild();
+ while (Child) {
+ if (Child->addressRangeContainsAddress(CU, Address)) {
+ // Assume there is only one such child.
+ break;
+ }
+ Child = Child->getSibling();
+ }
+ DIE = Child;
+ }
+ // Reverse the obtained chain to make the root of inlined chain last.
+ std::reverse(InlinedChain.begin(), InlinedChain.end());
+ return InlinedChain;
+}