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/DebugInfo/DWARF/DWARFContext.h" |
11 | #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.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/Errc.h" |
16 | #include <cstddef> |
17 | #include <cstdint> |
18 | |
19 | using namespace llvm; |
20 | using namespace dwarf; |
21 | |
22 | bool DWARFDebugInfoEntry::(const DWARFUnit &U, uint64_t *OffsetPtr, |
23 | const DWARFDataExtractor &DebugInfoData, |
24 | uint64_t UEndOffset, uint32_t ParentIdx) { |
25 | Offset = *OffsetPtr; |
26 | this->ParentIdx = ParentIdx; |
27 | if (Offset >= UEndOffset) { |
28 | U.getContext().getWarningHandler()( |
29 | createStringError(EC: errc::invalid_argument, |
30 | Fmt: "DWARF unit from offset 0x%8.8" PRIx64 " incl. " |
31 | "to offset 0x%8.8" PRIx64 " excl. " |
32 | "tries to read DIEs at offset 0x%8.8" PRIx64, |
33 | Vals: U.getOffset(), Vals: U.getNextUnitOffset(), Vals: *OffsetPtr)); |
34 | return false; |
35 | } |
36 | assert(DebugInfoData.isValidOffset(UEndOffset - 1)); |
37 | uint64_t AbbrCode = DebugInfoData.getULEB128(offset_ptr: OffsetPtr); |
38 | if (0 == AbbrCode) { |
39 | // NULL debug tag entry. |
40 | AbbrevDecl = nullptr; |
41 | return true; |
42 | } |
43 | const auto *AbbrevSet = U.getAbbreviations(); |
44 | if (!AbbrevSet) { |
45 | U.getContext().getWarningHandler()( |
46 | createStringError(EC: errc::invalid_argument, |
47 | Fmt: "DWARF unit at offset 0x%8.8" PRIx64 " " |
48 | "contains invalid abbreviation set offset 0x%" PRIx64, |
49 | Vals: U.getOffset(), Vals: U.getAbbreviationsOffset())); |
50 | // Restore the original offset. |
51 | *OffsetPtr = Offset; |
52 | return false; |
53 | } |
54 | AbbrevDecl = AbbrevSet->getAbbreviationDeclaration(AbbrCode); |
55 | if (!AbbrevDecl) { |
56 | U.getContext().getWarningHandler()( |
57 | createStringError(EC: errc::invalid_argument, |
58 | Fmt: "DWARF unit at offset 0x%8.8" PRIx64 " " |
59 | "contains invalid abbreviation %" PRIu64 " at " |
60 | "offset 0x%8.8" PRIx64 ", valid abbreviations are %s" , |
61 | Vals: U.getOffset(), Vals: AbbrCode, Vals: *OffsetPtr, |
62 | Vals: AbbrevSet->getCodeRange().c_str())); |
63 | // Restore the original offset. |
64 | *OffsetPtr = Offset; |
65 | return false; |
66 | } |
67 | // See if all attributes in this DIE have fixed byte sizes. If so, we can |
68 | // just add this size to the offset to skip to the next DIE. |
69 | if (std::optional<size_t> FixedSize = |
70 | AbbrevDecl->getFixedAttributesByteSize(U)) { |
71 | *OffsetPtr += *FixedSize; |
72 | return true; |
73 | } |
74 | |
75 | // Skip all data in the .debug_info for the attributes |
76 | for (const auto &AttrSpec : AbbrevDecl->attributes()) { |
77 | // Check if this attribute has a fixed byte size. |
78 | if (auto FixedSize = AttrSpec.getByteSize(U)) { |
79 | // Attribute byte size if fixed, just add the size to the offset. |
80 | *OffsetPtr += *FixedSize; |
81 | } else if (!DWARFFormValue::skipValue(Form: AttrSpec.Form, DebugInfoData, |
82 | OffsetPtr, FormParams: U.getFormParams())) { |
83 | // We failed to skip this attribute's value, restore the original offset |
84 | // and return the failure status. |
85 | U.getContext().getWarningHandler()(createStringError( |
86 | EC: errc::invalid_argument, |
87 | Fmt: "DWARF unit at offset 0x%8.8" PRIx64 " " |
88 | "contains invalid FORM_* 0x%" PRIx16 " at offset 0x%8.8" PRIx64, |
89 | Vals: U.getOffset(), Vals: AttrSpec.Form, Vals: *OffsetPtr)); |
90 | *OffsetPtr = Offset; |
91 | return false; |
92 | } |
93 | } |
94 | return true; |
95 | } |
96 | |