summaryrefslogtreecommitdiffstats
path: root/lib/DebugInfo
diff options
context:
space:
mode:
Diffstat (limited to 'lib/DebugInfo')
-rw-r--r--lib/DebugInfo/DWARFCompileUnit.cpp4
-rw-r--r--lib/DebugInfo/DWARFContext.cpp160
-rw-r--r--lib/DebugInfo/DWARFContext.h3
-rw-r--r--lib/DebugInfo/DWARFDebugInfoEntry.cpp340
-rw-r--r--lib/DebugInfo/DWARFDebugInfoEntry.h11
-rw-r--r--lib/DebugInfo/DWARFFormValue.cpp91
-rw-r--r--lib/DebugInfo/DWARFFormValue.h82
7 files changed, 229 insertions, 462 deletions
diff --git a/lib/DebugInfo/DWARFCompileUnit.cpp b/lib/DebugInfo/DWARFCompileUnit.cpp
index e3e4ccd..4f0eed4 100644
--- a/lib/DebugInfo/DWARFCompileUnit.cpp
+++ b/lib/DebugInfo/DWARFCompileUnit.cpp
@@ -9,7 +9,7 @@
#include "DWARFCompileUnit.h"
#include "DWARFContext.h"
-#include "DWARFFormValue.h"
+#include "llvm/DebugInfo/DWARFFormValue.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
@@ -165,7 +165,7 @@ size_t DWARFCompileUnit::extractDIEsIfNeeded(bool cu_die_only) {
// we were told to parse
const uint8_t *fixed_form_sizes =
- DWARFFormValue::getFixedFormSizesForAddressSize(getAddressByteSize());
+ DWARFFormValue::getFixedFormSizes(getAddressByteSize(), getVersion());
while (offset < next_cu_offset &&
die.extractFast(this, fixed_form_sizes, &offset)) {
diff --git a/lib/DebugInfo/DWARFContext.cpp b/lib/DebugInfo/DWARFContext.cpp
index 9e19310..9f52133 100644
--- a/lib/DebugInfo/DWARFContext.cpp
+++ b/lib/DebugInfo/DWARFContext.cpp
@@ -9,6 +9,9 @@
#include "DWARFContext.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Compression.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Path.h"
@@ -107,36 +110,43 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) {
}
if (DumpType == DIDT_All || DumpType == DIDT_AbbrevDwo) {
- OS << "\n.debug_abbrev.dwo contents:\n";
- getDebugAbbrevDWO()->dump(OS);
+ const DWARFDebugAbbrev *D = getDebugAbbrevDWO();
+ if (D) {
+ OS << "\n.debug_abbrev.dwo contents:\n";
+ getDebugAbbrevDWO()->dump(OS);
+ }
}
- if (DumpType == DIDT_All || DumpType == DIDT_InfoDwo) {
- OS << "\n.debug_info.dwo contents:\n";
- for (unsigned i = 0, e = getNumDWOCompileUnits(); i != e; ++i)
- getDWOCompileUnitAtIndex(i)->dump(OS);
- }
+ if (DumpType == DIDT_All || DumpType == DIDT_InfoDwo)
+ if (getNumDWOCompileUnits()) {
+ OS << "\n.debug_info.dwo contents:\n";
+ for (unsigned i = 0, e = getNumDWOCompileUnits(); i != e; ++i)
+ getDWOCompileUnitAtIndex(i)->dump(OS);
+ }
- if (DumpType == DIDT_All || DumpType == DIDT_StrDwo) {
- OS << "\n.debug_str.dwo contents:\n";
- DataExtractor strDWOData(getStringDWOSection(), isLittleEndian(), 0);
- offset = 0;
- uint32_t strDWOOffset = 0;
- while (const char *s = strDWOData.getCStr(&offset)) {
- OS << format("0x%8.8x: \"%s\"\n", strDWOOffset, s);
- strDWOOffset = offset;
+ if (DumpType == DIDT_All || DumpType == DIDT_StrDwo)
+ if (!getStringDWOSection().empty()) {
+ OS << "\n.debug_str.dwo contents:\n";
+ DataExtractor strDWOData(getStringDWOSection(), isLittleEndian(), 0);
+ offset = 0;
+ uint32_t strDWOOffset = 0;
+ while (const char *s = strDWOData.getCStr(&offset)) {
+ OS << format("0x%8.8x: \"%s\"\n", strDWOOffset, s);
+ strDWOOffset = offset;
+ }
}
- }
- if (DumpType == DIDT_All || DumpType == DIDT_StrOffsetsDwo) {
- OS << "\n.debug_str_offsets.dwo contents:\n";
- DataExtractor strOffsetExt(getStringOffsetDWOSection(), isLittleEndian(), 0);
- offset = 0;
- while (offset < getStringOffsetDWOSection().size()) {
- OS << format("0x%8.8x: ", offset);
- OS << format("%8.8x\n", strOffsetExt.getU32(&offset));
+ if (DumpType == DIDT_All || DumpType == DIDT_StrOffsetsDwo)
+ if (!getStringOffsetDWOSection().empty()) {
+ OS << "\n.debug_str_offsets.dwo contents:\n";
+ DataExtractor strOffsetExt(getStringOffsetDWOSection(), isLittleEndian(), 0);
+ offset = 0;
+ uint64_t size = getStringOffsetDWOSection().size();
+ while (offset < size) {
+ OS << format("0x%8.8x: ", offset);
+ OS << format("%8.8x\n", strOffsetExt.getU32(&offset));
+ }
}
- }
}
const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() {
@@ -482,6 +492,22 @@ DIInliningInfo DWARFContext::getInliningInfoForAddress(uint64_t Address,
return InliningInfo;
}
+static bool consumeCompressedDebugSectionHeader(StringRef &data,
+ uint64_t &OriginalSize) {
+ // Consume "ZLIB" prefix.
+ if (!data.startswith("ZLIB"))
+ return false;
+ data = data.substr(4);
+ // Consume uncompressed section size (big-endian 8 bytes).
+ DataExtractor extractor(data, false, 8);
+ uint32_t Offset = 0;
+ OriginalSize = extractor.getU64(&Offset);
+ if (Offset == 0)
+ return false;
+ data = data.substr(Offset);
+ return true;
+}
+
DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) :
IsLittleEndian(Obj->isLittleEndian()),
AddressSize(Obj->getBytesInAddress()) {
@@ -495,49 +521,55 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) :
i->getContents(data);
name = name.substr(name.find_first_not_of("._")); // Skip . and _ prefixes.
- if (name == "debug_info")
- InfoSection = data;
- else if (name == "debug_abbrev")
- AbbrevSection = data;
- else if (name == "debug_line")
- LineSection = data;
- else if (name == "debug_aranges")
- ARangeSection = data;
- else if (name == "debug_frame")
- DebugFrameSection = data;
- else if (name == "debug_str")
- StringSection = data;
- else if (name == "debug_ranges") {
+
+ // Check if debug info section is compressed with zlib.
+ if (name.startswith("zdebug_")) {
+ uint64_t OriginalSize;
+ if (!zlib::isAvailable() ||
+ !consumeCompressedDebugSectionHeader(data, OriginalSize))
+ continue;
+ OwningPtr<MemoryBuffer> UncompressedSection;
+ if (zlib::uncompress(data, UncompressedSection, OriginalSize) !=
+ zlib::StatusOK)
+ continue;
+ // Make data point to uncompressed section contents and save its contents.
+ name = name.substr(1);
+ data = UncompressedSection->getBuffer();
+ UncompressedSections.push_back(UncompressedSection.take());
+ }
+
+ StringRef *Section = StringSwitch<StringRef*>(name)
+ .Case("debug_info", &InfoSection)
+ .Case("debug_abbrev", &AbbrevSection)
+ .Case("debug_line", &LineSection)
+ .Case("debug_aranges", &ARangeSection)
+ .Case("debug_frame", &DebugFrameSection)
+ .Case("debug_str", &StringSection)
+ .Case("debug_ranges", &RangeSection)
+ .Case("debug_pubnames", &PubNamesSection)
+ .Case("debug_info.dwo", &InfoDWOSection)
+ .Case("debug_abbrev.dwo", &AbbrevDWOSection)
+ .Case("debug_str.dwo", &StringDWOSection)
+ .Case("debug_str_offsets.dwo", &StringOffsetDWOSection)
+ .Case("debug_addr", &AddrSection)
+ // Any more debug info sections go here.
+ .Default(0);
+ if (!Section)
+ continue;
+ *Section = data;
+ if (name == "debug_ranges") {
// FIXME: Use the other dwo range section when we emit it.
RangeDWOSection = data;
- RangeSection = data;
}
- else if (name == "debug_pubnames")
- PubNamesSection = data;
- else if (name == "debug_info.dwo")
- InfoDWOSection = data;
- else if (name == "debug_abbrev.dwo")
- AbbrevDWOSection = data;
- else if (name == "debug_str.dwo")
- StringDWOSection = data;
- else if (name == "debug_str_offsets.dwo")
- StringOffsetDWOSection = data;
- else if (name == "debug_addr")
- AddrSection = data;
- // Any more debug info sections go here.
- else
- continue;
// TODO: Add support for relocations in other sections as needed.
// Record relocations for the debug_info and debug_line sections.
- RelocAddrMap *Map;
- if (name == "debug_info")
- Map = &InfoRelocMap;
- else if (name == "debug_info.dwo")
- Map = &InfoDWORelocMap;
- else if (name == "debug_line")
- Map = &LineRelocMap;
- else
+ RelocAddrMap *Map = StringSwitch<RelocAddrMap*>(name)
+ .Case("debug_info", &InfoRelocMap)
+ .Case("debug_info.dwo", &InfoDWORelocMap)
+ .Case("debug_line", &LineRelocMap)
+ .Default(0);
+ if (!Map)
continue;
if (i->begin_relocations() != i->end_relocations()) {
@@ -547,7 +579,7 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) :
reloc_e = i->end_relocations();
reloc_i != reloc_e; reloc_i.increment(ec)) {
uint64_t Address;
- reloc_i->getAddress(Address);
+ reloc_i->getOffset(Address);
uint64_t Type;
reloc_i->getType(Type);
uint64_t SymAddr = 0;
@@ -593,4 +625,8 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) :
}
}
+DWARFContextInMemory::~DWARFContextInMemory() {
+ DeleteContainerPointers(UncompressedSections);
+}
+
void DWARFContextInMemory::anchor() { }
diff --git a/lib/DebugInfo/DWARFContext.h b/lib/DebugInfo/DWARFContext.h
index 37b2729..78c18e6 100644
--- a/lib/DebugInfo/DWARFContext.h
+++ b/lib/DebugInfo/DWARFContext.h
@@ -161,8 +161,11 @@ class DWARFContextInMemory : public DWARFContext {
StringRef RangeDWOSection;
StringRef AddrSection;
+ SmallVector<MemoryBuffer*, 4> UncompressedSections;
+
public:
DWARFContextInMemory(object::ObjectFile *);
+ ~DWARFContextInMemory();
virtual bool isLittleEndian() const { return IsLittleEndian; }
virtual uint8_t getAddressSize() const { return AddressSize; }
virtual const RelocAddrMap &infoRelocMap() const { return InfoRelocMap; }
diff --git a/lib/DebugInfo/DWARFDebugInfoEntry.cpp b/lib/DebugInfo/DWARFDebugInfoEntry.cpp
index 02b15d6..10be7b4 100644
--- a/lib/DebugInfo/DWARFDebugInfoEntry.cpp
+++ b/lib/DebugInfo/DWARFDebugInfoEntry.cpp
@@ -11,7 +11,7 @@
#include "DWARFCompileUnit.h"
#include "DWARFContext.h"
#include "DWARFDebugAbbrev.h"
-#include "DWARFFormValue.h"
+#include "llvm/DebugInfo/DWARFFormValue.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/Format.h"
@@ -94,279 +94,87 @@ void DWARFDebugInfoEntryMinimal::dumpAttribute(raw_ostream &OS,
OS << ")\n";
}
-bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFCompileUnit *cu,
- const uint8_t *fixed_form_sizes,
- uint32_t *offset_ptr) {
- Offset = *offset_ptr;
-
- 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!
-
- if (abbrCode) {
- uint32_t offset = *offset_ptr;
-
- AbbrevDecl = cu->getAbbreviations()->getAbbreviationDeclaration(abbrCode);
-
- // Skip all data in the .debug_info for the attributes
- const uint32_t numAttributes = AbbrevDecl->getNumAttributes();
- uint32_t i;
- uint16_t form;
- for (i=0; i<numAttributes; ++i) {
-
- form = AbbrevDecl->getFormByIndex(i);
-
- // FIXME: Currently we're checking if this is less than the last
- // entry in the fixed_form_sizes table, but this should be changed
- // to use dynamic dispatch.
- const uint8_t fixed_skip_size = (form < DW_FORM_ref_sig8) ?
- fixed_form_sizes[form] : 0;
- if (fixed_skip_size)
- offset += fixed_skip_size;
- else {
- bool form_is_indirect = false;
- do {
- form_is_indirect = false;
- uint32_t form_size = 0;
- 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;
- case DW_FORM_block1:
- form_size = debug_info_data.getU8(&offset);
- break;
- case DW_FORM_block2:
- form_size = debug_info_data.getU16(&offset);
- break;
- case DW_FORM_block4:
- form_size = debug_info_data.getU32(&offset);
- break;
-
- // Inlined NULL terminated C-strings
- case DW_FORM_string:
- debug_info_data.getCStr(&offset);
- break;
-
- // Compile unit address sized values
- case DW_FORM_addr:
- case DW_FORM_ref_addr:
- 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:
- case DW_FORM_ref1:
- form_size = 1;
- break;
-
- // 2 byte values
- case DW_FORM_data2:
- case DW_FORM_ref2:
- form_size = 2;
- break;
-
- // 4 byte values
- case DW_FORM_strp:
- case DW_FORM_data4:
- case DW_FORM_ref4:
- form_size = 4;
- break;
-
- // 8 byte values
- case DW_FORM_data8:
- case DW_FORM_ref8:
- case DW_FORM_ref_sig8:
- form_size = 8;
- break;
-
- // signed or unsigned LEB 128 values
- case DW_FORM_sdata:
- case DW_FORM_udata:
- case DW_FORM_ref_udata:
- case DW_FORM_GNU_str_index:
- case DW_FORM_GNU_addr_index:
- debug_info_data.getULEB128(&offset);
- break;
-
- case DW_FORM_indirect:
- form_is_indirect = true;
- form = debug_info_data.getULEB128(&offset);
- break;
-
- // FIXME: 64-bit for DWARF64
- case DW_FORM_sec_offset:
- debug_info_data.getU32(offset_ptr);
- break;
-
- default:
- *offset_ptr = Offset;
- return false;
- }
- offset += form_size;
- } while (form_is_indirect);
- }
- }
- *offset_ptr = offset;
- return true;
- } else {
+bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFCompileUnit *CU,
+ const uint8_t *FixedFormSizes,
+ uint32_t *OffsetPtr) {
+ Offset = *OffsetPtr;
+ DataExtractor DebugInfoData = CU->getDebugInfoExtractor();
+ uint64_t AbbrCode = DebugInfoData.getULEB128(OffsetPtr);
+ if (0 == AbbrCode) {
+ // NULL debug tag entry.
AbbrevDecl = NULL;
- return true; // NULL debug tag entry
+ return true;
+ }
+ AbbrevDecl = CU->getAbbreviations()->getAbbreviationDeclaration(AbbrCode);
+ assert(AbbrevDecl);
+ assert(FixedFormSizes); // For best performance this should be specified!
+
+ // Skip all data in the .debug_info for the attributes
+ for (uint32_t i = 0, n = AbbrevDecl->getNumAttributes(); i < n; ++i) {
+ uint16_t Form = AbbrevDecl->getFormByIndex(i);
+
+ // FIXME: Currently we're checking if this is less than the last
+ // entry in the fixed_form_sizes table, but this should be changed
+ // to use dynamic dispatch.
+ uint8_t FixedFormSize =
+ (Form < DW_FORM_ref_sig8) ? FixedFormSizes[Form] : 0;
+ if (FixedFormSize)
+ *OffsetPtr += FixedFormSize;
+ else if (!DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr,
+ CU)) {
+ // Restore the original offset.
+ *OffsetPtr = Offset;
+ return false;
+ }
}
+ return true;
}
bool
-DWARFDebugInfoEntryMinimal::extract(const DWARFCompileUnit *cu,
- uint32_t *offset_ptr) {
- DataExtractor debug_info_data = cu->getDebugInfoExtractor();
- const uint32_t cu_end_offset = cu->getNextCompileUnitOffset();
- const uint8_t cu_addr_size = cu->getAddressByteSize();
- uint32_t offset = *offset_ptr;
- if ((offset < cu_end_offset) && debug_info_data.isValidOffset(offset)) {
- Offset = offset;
-
- uint64_t abbrCode = debug_info_data.getULEB128(&offset);
-
- if (abbrCode) {
- AbbrevDecl = cu->getAbbreviations()->getAbbreviationDeclaration(abbrCode);
-
- if (AbbrevDecl) {
- uint16_t tag = AbbrevDecl->getTag();
-
- bool isCompileUnitTag = tag == DW_TAG_compile_unit;
- if(cu && isCompileUnitTag)
- const_cast<DWARFCompileUnit*>(cu)->setBaseAddress(0);
-
- // Skip all data in the .debug_info for the attributes
- const uint32_t numAttributes = AbbrevDecl->getNumAttributes();
- for (uint32_t i = 0; i != numAttributes; ++i) {
- uint16_t attr = AbbrevDecl->getAttrByIndex(i);
- uint16_t form = AbbrevDecl->getFormByIndex(i);
-
- if (isCompileUnitTag &&
- ((attr == DW_AT_entry_pc) || (attr == DW_AT_low_pc))) {
- DWARFFormValue form_value(form);
- if (form_value.extractValue(debug_info_data, &offset, cu)) {
- if (attr == DW_AT_low_pc || attr == DW_AT_entry_pc)
- const_cast<DWARFCompileUnit*>(cu)
- ->setBaseAddress(form_value.getUnsigned());
- }
- } else {
- bool form_is_indirect = false;
- do {
- form_is_indirect = false;
- register uint32_t form_size = 0;
- 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;
- case DW_FORM_block1:
- form_size = debug_info_data.getU8(&offset);
- break;
- case DW_FORM_block2:
- form_size = debug_info_data.getU16(&offset);
- break;
- case DW_FORM_block4:
- form_size = debug_info_data.getU32(&offset);
- break;
-
- // Inlined NULL terminated C-strings
- case DW_FORM_string:
- debug_info_data.getCStr(&offset);
- break;
-
- // Compile unit address sized values
- case DW_FORM_addr:
- case DW_FORM_ref_addr:
- 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:
- case DW_FORM_ref1:
- form_size = 1;
- break;
-
- // 2 byte values
- case DW_FORM_data2:
- case DW_FORM_ref2:
- form_size = 2;
- break;
-
- // 4 byte values
- case DW_FORM_strp:
- form_size = 4;
- break;
-
- case DW_FORM_data4:
- case DW_FORM_ref4:
- form_size = 4;
- break;
-
- // 8 byte values
- case DW_FORM_data8:
- case DW_FORM_ref8:
- case DW_FORM_ref_sig8:
- form_size = 8;
- break;
-
- // signed or unsigned LEB 128 values
- case DW_FORM_sdata:
- case DW_FORM_udata:
- case DW_FORM_ref_udata:
- case DW_FORM_GNU_str_index:
- case DW_FORM_GNU_addr_index:
- debug_info_data.getULEB128(&offset);
- break;
-
- case DW_FORM_indirect:
- form = debug_info_data.getULEB128(&offset);
- form_is_indirect = true;
- break;
-
- // FIXME: 64-bit for DWARF64.
- case DW_FORM_sec_offset:
- debug_info_data.getU32(offset_ptr);
- break;
-
- default:
- *offset_ptr = offset;
- return false;
- }
-
- offset += form_size;
- } while (form_is_indirect);
- }
- }
- *offset_ptr = offset;
- return true;
+DWARFDebugInfoEntryMinimal::extract(const DWARFCompileUnit *CU,
+ uint32_t *OffsetPtr) {
+ DataExtractor DebugInfoData = CU->getDebugInfoExtractor();
+ const uint32_t CUEndOffset = CU->getNextCompileUnitOffset();
+ Offset = *OffsetPtr;
+ if ((Offset >= CUEndOffset) || !DebugInfoData.isValidOffset(Offset))
+ return false;
+ uint64_t AbbrCode = DebugInfoData.getULEB128(OffsetPtr);
+ if (0 == AbbrCode) {
+ // NULL debug tag entry.
+ AbbrevDecl = NULL;
+ return true;
+ }
+ AbbrevDecl = CU->getAbbreviations()->getAbbreviationDeclaration(AbbrCode);
+ if (0 == AbbrevDecl) {
+ // Restore the original offset.
+ *OffsetPtr = Offset;
+ return false;
+ }
+ bool IsCompileUnitTag = (AbbrevDecl->getTag() == DW_TAG_compile_unit);
+ if (IsCompileUnitTag)
+ const_cast<DWARFCompileUnit*>(CU)->setBaseAddress(0);
+
+ // Skip all data in the .debug_info for the attributes
+ for (uint32_t i = 0, n = AbbrevDecl->getNumAttributes(); i < n; ++i) {
+ uint16_t Attr = AbbrevDecl->getAttrByIndex(i);
+ uint16_t Form = AbbrevDecl->getFormByIndex(i);
+
+ if (IsCompileUnitTag &&
+ ((Attr == DW_AT_entry_pc) || (Attr == DW_AT_low_pc))) {
+ DWARFFormValue FormValue(Form);
+ if (FormValue.extractValue(DebugInfoData, OffsetPtr, CU)) {
+ if (Attr == DW_AT_low_pc || Attr == DW_AT_entry_pc)
+ const_cast<DWARFCompileUnit*>(CU)
+ ->setBaseAddress(FormValue.getUnsigned());
}
- } else {
- AbbrevDecl = NULL;
- *offset_ptr = offset;
- return true; // NULL debug tag entry
+ } else if (!DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr,
+ CU)) {
+ // Restore the original offset.
+ *OffsetPtr = Offset;
+ return false;
}
}
-
- return false;
+ return true;
}
bool DWARFDebugInfoEntryMinimal::isSubprogramDIE() const {
diff --git a/lib/DebugInfo/DWARFDebugInfoEntry.h b/lib/DebugInfo/DWARFDebugInfoEntry.h
index 9c1b2be..9003591 100644
--- a/lib/DebugInfo/DWARFDebugInfoEntry.h
+++ b/lib/DebugInfo/DWARFDebugInfoEntry.h
@@ -45,12 +45,17 @@ public:
uint32_t *offset_ptr, uint16_t attr, uint16_t form,
unsigned indent = 0) const;
- bool extractFast(const DWARFCompileUnit *cu, const uint8_t *fixed_form_sizes,
- uint32_t *offset_ptr);
+ /// Extracts a debug info entry, which is a child of a given compile unit,
+ /// starting at a given offset. If DIE can't be extracted, returns false and
+ /// doesn't change OffsetPtr.
+ bool extractFast(const DWARFCompileUnit *CU, const uint8_t *FixedFormSizes,
+ uint32_t *OffsetPtr);
/// Extract a debug info entry for a given compile unit from the
/// .debug_info and .debug_abbrev data starting at the given offset.
- bool extract(const DWARFCompileUnit *cu, uint32_t *offset_ptr);
+ /// If compile unit can't be parsed, returns false and doesn't change
+ /// OffsetPtr.
+ bool extract(const DWARFCompileUnit *CU, uint32_t *OffsetPtr);
uint32_t getTag() const { return AbbrevDecl ? AbbrevDecl->getTag() : 0; }
bool isNULL() const { return AbbrevDecl == 0; }
diff --git a/lib/DebugInfo/DWARFFormValue.cpp b/lib/DebugInfo/DWARFFormValue.cpp
index 9f807aa..c5583f9 100644
--- a/lib/DebugInfo/DWARFFormValue.cpp
+++ b/lib/DebugInfo/DWARFFormValue.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
-#include "DWARFFormValue.h"
+#include "llvm/DebugInfo/DWARFFormValue.h"
#include "DWARFCompileUnit.h"
#include "DWARFContext.h"
#include "llvm/Support/Debug.h"
@@ -18,39 +18,16 @@
using namespace llvm;
using namespace dwarf;
-static const uint8_t form_sizes_addr4[] = {
- 0, // 0x00 unused
- 4, // 0x01 DW_FORM_addr
- 0, // 0x02 unused
- 0, // 0x03 DW_FORM_block2
- 0, // 0x04 DW_FORM_block4
- 2, // 0x05 DW_FORM_data2
- 4, // 0x06 DW_FORM_data4
- 8, // 0x07 DW_FORM_data8
- 0, // 0x08 DW_FORM_string
- 0, // 0x09 DW_FORM_block
- 0, // 0x0a DW_FORM_block1
- 1, // 0x0b DW_FORM_data1
- 1, // 0x0c DW_FORM_flag
- 0, // 0x0d DW_FORM_sdata
- 4, // 0x0e DW_FORM_strp
- 0, // 0x0f DW_FORM_udata
- 4, // 0x10 DW_FORM_ref_addr
- 1, // 0x11 DW_FORM_ref1
- 2, // 0x12 DW_FORM_ref2
- 4, // 0x13 DW_FORM_ref4
- 8, // 0x14 DW_FORM_ref8
- 0, // 0x15 DW_FORM_ref_udata
- 0, // 0x16 DW_FORM_indirect
- 4, // 0x17 DW_FORM_sec_offset
- 0, // 0x18 DW_FORM_exprloc
- 0, // 0x19 DW_FORM_flag_present
- 8, // 0x20 DW_FORM_ref_sig8
+namespace {
+template <uint8_t AddrSize, uint8_t RefAddrSize> struct FixedFormSizes {
+ static const uint8_t sizes[];
};
+}
-static const uint8_t form_sizes_addr8[] = {
+template <uint8_t AddrSize, uint8_t RefAddrSize>
+const uint8_t FixedFormSizes<AddrSize, RefAddrSize>::sizes[] = {
0, // 0x00 unused
- 8, // 0x01 DW_FORM_addr
+ AddrSize, // 0x01 DW_FORM_addr
0, // 0x02 unused
0, // 0x03 DW_FORM_block2
0, // 0x04 DW_FORM_block4
@@ -65,7 +42,7 @@ static const uint8_t form_sizes_addr8[] = {
0, // 0x0d DW_FORM_sdata
4, // 0x0e DW_FORM_strp
0, // 0x0f DW_FORM_udata
- 8, // 0x10 DW_FORM_ref_addr
+ RefAddrSize, // 0x10 DW_FORM_ref_addr
1, // 0x11 DW_FORM_ref1
2, // 0x12 DW_FORM_ref2
4, // 0x13 DW_FORM_ref4
@@ -78,13 +55,23 @@ static const uint8_t form_sizes_addr8[] = {
8, // 0x20 DW_FORM_ref_sig8
};
+static uint8_t getRefAddrSize(uint8_t AddrSize, uint16_t Version) {
+ // FIXME: Support DWARF64.
+ return (Version == 2) ? AddrSize : 4;
+}
+
const uint8_t *
-DWARFFormValue::getFixedFormSizesForAddressSize(uint8_t addr_size) {
- switch (addr_size) {
- case 4: return form_sizes_addr4;
- case 8: return form_sizes_addr8;
- }
- return NULL;
+DWARFFormValue::getFixedFormSizes(uint8_t AddrSize, uint16_t Version) {
+ uint8_t RefAddrSize = getRefAddrSize(AddrSize, Version);
+ if (AddrSize == 4 && RefAddrSize == 4)
+ return FixedFormSizes<4, 4>::sizes;
+ if (AddrSize == 4 && RefAddrSize == 8)
+ return FixedFormSizes<4, 8>::sizes;
+ if (AddrSize == 8 && RefAddrSize == 4)
+ return FixedFormSizes<8, 4>::sizes;
+ if (AddrSize == 8 && RefAddrSize == 8)
+ return FixedFormSizes<8, 8>::sizes;
+ return 0;
}
bool
@@ -100,14 +87,16 @@ DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
switch (Form) {
case DW_FORM_addr:
case DW_FORM_ref_addr: {
- RelocAddrMap::const_iterator AI
- = cu->getRelocMap()->find(*offset_ptr);
+ uint16_t AddrSize =
+ (Form == DW_FORM_addr)
+ ? cu->getAddressByteSize()
+ : getRefAddrSize(cu->getAddressByteSize(), cu->getVersion());
+ RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr);
if (AI != cu->getRelocMap()->end()) {
const std::pair<uint8_t, int64_t> &R = AI->second;
- Value.uval = data.getUnsigned(offset_ptr, cu->getAddressByteSize()) +
- R.second;
+ Value.uval = data.getUnsigned(offset_ptr, AddrSize) + R.second;
} else
- Value.uval = data.getUnsigned(offset_ptr, cu->getAddressByteSize());
+ Value.uval = data.getUnsigned(offset_ptr, AddrSize);
break;
}
case DW_FORM_exprloc:
@@ -172,10 +161,17 @@ DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
Form = data.getULEB128(offset_ptr);
indirect = true;
break;
- case DW_FORM_sec_offset:
+ case DW_FORM_sec_offset: {
// FIXME: This is 64-bit for DWARF64.
- Value.uval = data.getU32(offset_ptr);
+ RelocAddrMap::const_iterator AI
+ = cu->getRelocMap()->find(*offset_ptr);
+ if (AI != cu->getRelocMap()->end()) {
+ const std::pair<uint8_t, int64_t> &R = AI->second;
+ Value.uval = data.getU32(offset_ptr) + R.second;
+ } else
+ Value.uval = data.getU32(offset_ptr);
break;
+ }
case DW_FORM_flag_present:
Value.uval = 1;
break;
@@ -216,7 +212,6 @@ DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data,
uint32_t *offset_ptr, const DWARFCompileUnit *cu) {
bool indirect = false;
do {
- indirect = false;
switch (form) {
// Blocks if inlined data that have a length field and the data bytes
// inlined in the .debug_info
@@ -249,9 +244,11 @@ DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data,
// Compile unit address sized values
case DW_FORM_addr:
- case DW_FORM_ref_addr:
*offset_ptr += cu->getAddressByteSize();
return true;
+ case DW_FORM_ref_addr:
+ *offset_ptr += getRefAddrSize(cu->getAddressByteSize(), cu->getVersion());
+ return true;
// 0 byte values - implied from the form.
case DW_FORM_flag_present:
diff --git a/lib/DebugInfo/DWARFFormValue.h b/lib/DebugInfo/DWARFFormValue.h
deleted file mode 100644
index b863001..0000000
--- a/lib/DebugInfo/DWARFFormValue.h
+++ /dev/null
@@ -1,82 +0,0 @@
-//===-- DWARFFormValue.h ----------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_DEBUGINFO_DWARFFORMVALUE_H
-#define LLVM_DEBUGINFO_DWARFFORMVALUE_H
-
-#include "llvm/Support/DataExtractor.h"
-
-namespace llvm {
-
-class DWARFCompileUnit;
-class raw_ostream;
-
-class DWARFFormValue {
-public:
- struct ValueType {
- ValueType() : data(NULL) {
- uval = 0;
- }
-
- union {
- uint64_t uval;
- int64_t sval;
- const char* cstr;
- };
- const uint8_t* data;
- };
-
- enum {
- eValueTypeInvalid = 0,
- eValueTypeUnsigned,
- eValueTypeSigned,
- eValueTypeCStr,
- eValueTypeBlock
- };
-
-private:
- uint16_t Form; // Form for this value.
- ValueType Value; // Contains all data for the form.
-
-public:
- DWARFFormValue(uint16_t form = 0) : Form(form) {}
- uint16_t getForm() const { return Form; }
- const ValueType& value() const { return Value; }
- void dump(raw_ostream &OS, const DWARFCompileUnit* cu) const;
- bool extractValue(DataExtractor data, uint32_t *offset_ptr,
- const DWARFCompileUnit *cu);
- bool isInlinedCStr() const {
- return Value.data != NULL && Value.data == (const uint8_t*)Value.cstr;
- }
- const uint8_t *BlockData() const;
- uint64_t getReference(const DWARFCompileUnit* cu) const;
-
- /// Resolve any compile unit specific references so that we don't need
- /// the compile unit at a later time in order to work with the form
- /// value.
- bool resolveCompileUnitReferences(const DWARFCompileUnit* cu);
- uint64_t getUnsigned() const { return Value.uval; }
- int64_t getSigned() const { return Value.sval; }
- const char *getAsCString(const DataExtractor *debug_str_data_ptr) const;
- const char *getIndirectCString(const DataExtractor *,
- const DataExtractor *) const;
- uint64_t getIndirectAddress(const DataExtractor *,
- const DWARFCompileUnit *) const;
- bool skipValue(DataExtractor debug_info_data, uint32_t *offset_ptr,
- const DWARFCompileUnit *cu) const;
- static bool skipValue(uint16_t form, DataExtractor debug_info_data,
- uint32_t *offset_ptr, const DWARFCompileUnit *cu);
- static bool isBlockForm(uint16_t form);
- static bool isDataForm(uint16_t form);
- static const uint8_t *getFixedFormSizesForAddressSize(uint8_t addr_size);
-};
-
-}
-
-#endif
OpenPOWER on IntegriCloud