1 //===- DWARFDebugInfoEntry.cpp --------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h" 10 #include "llvm/ADT/Optional.h" 11 #include "llvm/DebugInfo/DWARF/DWARFContext.h" 12 #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" 13 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" 14 #include "llvm/DebugInfo/DWARF/DWARFUnit.h" 15 #include "llvm/Support/DataExtractor.h" 16 #include <cstddef> 17 #include <cstdint> 18 19 using namespace llvm; 20 using namespace dwarf; 21 22 bool DWARFDebugInfoEntry::extractFast(const DWARFUnit &U, 23 uint64_t *OffsetPtr) { 24 DWARFDataExtractor DebugInfoData = U.getDebugInfoExtractor(); 25 const uint64_t UEndOffset = U.getNextUnitOffset(); 26 return extractFast(U, OffsetPtr, DebugInfoData, UEndOffset, 0); 27 } 28 29 bool DWARFDebugInfoEntry::extractFast(const DWARFUnit &U, uint64_t *OffsetPtr, 30 const DWARFDataExtractor &DebugInfoData, 31 uint64_t UEndOffset, uint32_t D) { 32 Offset = *OffsetPtr; 33 Depth = D; 34 if (Offset >= UEndOffset) { 35 U.getContext().getWarningHandler()( 36 createStringError(errc::invalid_argument, 37 "DWARF unit from offset 0x%8.8" PRIx64 " incl. " 38 "to offset 0x%8.8" PRIx64 " excl. " 39 "tries to read DIEs at offset 0x%8.8" PRIx64, 40 U.getOffset(), U.getNextUnitOffset(), *OffsetPtr)); 41 return false; 42 } 43 assert(DebugInfoData.isValidOffset(UEndOffset - 1)); 44 uint64_t AbbrCode = DebugInfoData.getULEB128(OffsetPtr); 45 if (0 == AbbrCode) { 46 // NULL debug tag entry. 47 AbbrevDecl = nullptr; 48 return true; 49 } 50 const auto *AbbrevSet = U.getAbbreviations(); 51 if (!AbbrevSet) { 52 U.getContext().getWarningHandler()( 53 createStringError(errc::invalid_argument, 54 "DWARF unit at offset 0x%8.8" PRIx64 " " 55 "contains invalid abbreviation set offset 0x%" PRIx64, 56 U.getOffset(), U.getAbbreviationsOffset())); 57 // Restore the original offset. 58 *OffsetPtr = Offset; 59 return false; 60 } 61 AbbrevDecl = AbbrevSet->getAbbreviationDeclaration(AbbrCode); 62 if (!AbbrevDecl) { 63 U.getContext().getWarningHandler()( 64 createStringError(errc::invalid_argument, 65 "DWARF unit at offset 0x%8.8" PRIx64 " " 66 "contains invalid abbreviation %" PRIu64 " at " 67 "offset 0x%8.8" PRIx64 ", valid abbreviations are %s", 68 U.getOffset(), AbbrCode, *OffsetPtr, 69 AbbrevSet->getCodeRange().c_str())); 70 // Restore the original offset. 71 *OffsetPtr = Offset; 72 return false; 73 } 74 // See if all attributes in this DIE have fixed byte sizes. If so, we can 75 // just add this size to the offset to skip to the next DIE. 76 if (Optional<size_t> FixedSize = AbbrevDecl->getFixedAttributesByteSize(U)) { 77 *OffsetPtr += *FixedSize; 78 return true; 79 } 80 81 // Skip all data in the .debug_info for the attributes 82 for (const auto &AttrSpec : AbbrevDecl->attributes()) { 83 // Check if this attribute has a fixed byte size. 84 if (auto FixedSize = AttrSpec.getByteSize(U)) { 85 // Attribute byte size if fixed, just add the size to the offset. 86 *OffsetPtr += *FixedSize; 87 } else if (!DWARFFormValue::skipValue(AttrSpec.Form, DebugInfoData, 88 OffsetPtr, U.getFormParams())) { 89 // We failed to skip this attribute's value, restore the original offset 90 // and return the failure status. 91 U.getContext().getWarningHandler()(createStringError( 92 errc::invalid_argument, 93 "DWARF unit at offset 0x%8.8" PRIx64 " " 94 "contains invalid FORM_* 0x%" PRIx16 " at offset 0x%8.8" PRIx64, 95 U.getOffset(), AttrSpec.Form, *OffsetPtr)); 96 *OffsetPtr = Offset; 97 return false; 98 } 99 } 100 return true; 101 } 102