diff --git a/lib/DebugInfo/DWARFDebugInfoEntry.cpp b/lib/DebugInfo/DWARFDebugInfoEntry.cpp index 02b15d69043..0fd5d488ae0 100644 --- a/lib/DebugInfo/DWARFDebugInfoEntry.cpp +++ b/lib/DebugInfo/DWARFDebugInfoEntry.cpp @@ -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; igetFormByIndex(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; +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(CU)->setBaseAddress(0); - uint64_t abbrCode = debug_info_data.getULEB128(&offset); + // 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 (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(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(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; + 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(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 9c1b2be0a71..9003591cbe1 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; }