diff options
Diffstat (limited to 'lib/DebugInfo')
-rw-r--r-- | lib/DebugInfo/DWARFCompileUnit.cpp | 4 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFContext.cpp | 160 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFContext.h | 3 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFDebugInfoEntry.cpp | 340 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFDebugInfoEntry.h | 11 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFFormValue.cpp | 91 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFFormValue.h | 82 |
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 |