llvm.org GIT mirror llvm / e302dc7
[DWARF] Introduce verification for the unit header chain in .debug_info section to llvm-dwarfdump. This patch adds verification checks for the unit header chain in the .debug_info section. Specifically, for each unit in the .debug_info section, the verifier checks that: The unit length is valid (i.e. the unit can actually fit in the .debug_info section) The dwarf version of the unit is valid The address size is valid (4 or 8) The unit type (if the unit is in dwarf5) is valid The debug_abbrev_offset is valid git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@307975 91177308-0d34-0410-b5e6-96231b3b80d8 Spyridoula Gravani 2 years ago
5 changed file(s) with 235 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
237237
238238 uint8_t getUnitType() const { return UnitType; }
239239
240 static bool isValidUnitType(uint8_t UnitType) {
241 return UnitType == dwarf::DW_UT_compile || UnitType == dwarf::DW_UT_type ||
242 UnitType == dwarf::DW_UT_partial ||
243 UnitType == dwarf::DW_UT_skeleton ||
244 UnitType == dwarf::DW_UT_split_compile ||
245 UnitType == dwarf::DW_UT_split_type;
246 }
247
248 /// \brief Return the number of bytes for the header of a unit of
249 /// UnitType type.
250 ///
251 /// This function must be called with a valid unit type which in
252 /// DWARF5 is defined as one of the following six types.
253 static uint32_t getDWARF5HeaderSize(uint8_t UnitType) {
254 switch (UnitType) {
255 case dwarf::DW_UT_compile:
256 case dwarf::DW_UT_partial:
257 return 12;
258 case dwarf::DW_UT_skeleton:
259 case dwarf::DW_UT_split_compile:
260 return 20;
261 case dwarf::DW_UT_type:
262 case dwarf::DW_UT_split_type:
263 return 24;
264 }
265 llvm_unreachable("Invalid UnitType.");
266 }
267
240268 uint64_t getBaseAddress() const { return BaseAddr; }
241269
242270 void setBaseAddress(uint64_t base_addr) {
2020 class DWARFDie;
2121 class DWARFUnit;
2222 class DWARFAcceleratorTable;
23 class DWARFDataExtractor;
2324
2425 /// A class that verifies DWARF debug information given a DWARF Context.
2526 class DWARFVerifier {
3233 uint32_t NumDebugInfoErrors = 0;
3334 uint32_t NumDebugLineErrors = 0;
3435 uint32_t NumAppleNamesErrors = 0;
36
37 /// Verifies the header of a unit in the .debug_info section.
38 ///
39 /// This function currently checks for:
40 /// - Unit is in 32-bit DWARF format. The function can be modified to
41 /// support 64-bit format.
42 /// - The DWARF version is valid
43 /// - The unit type is valid (if unit is in version >=5)
44 /// - The unit doesn't extend beyond .debug_info section
45 /// - The address size is valid
46 /// - The offset in the .debug_abbrev section is valid
47 ///
48 /// \param DebugInfoData The .debug_info section data
49 /// \param Offset A reference to the offset start of the unit. The offset will
50 /// be updated to point to the next unit in .debug_info
51 /// \param UnitIndex The index of the unit to be verified
52 /// \param isUnitDWARF64 A reference to a flag that shows whether the unit is
53 /// in 64-bit format.
54 ///
55 /// \returns true if the header is verified successfully, false otherwise.
56 bool verifyUnitHeader(const DWARFDataExtractor DebugInfoData,
57 uint32_t *Offset, unsigned UnitIndex,
58 bool &isUnitDWARF64);
3559
3660 /// Verifies the attribute's DWARF attribute and its value.
3761 ///
77101 public:
78102 DWARFVerifier(raw_ostream &S, DWARFContext &D)
79103 : OS(S), DCtx(D) {}
104 /// Verify the unit header chain in the .debug_info section.
105 ///
106 /// Any errors are reported to the stream that this object was
107 /// constructed with.
108 ///
109 /// \returns true if the unit header chain verifies successfully, false
110 /// otherwise.
111 bool handleDebugInfoUnitHeaderChain();
80112 /// Verify the information in the .debug_info section.
81113 ///
82114 /// Any errors are reported to the stream that was this object was
413413 bool DWARFContext::verify(raw_ostream &OS, DIDumpType DumpType) {
414414 bool Success = true;
415415 DWARFVerifier verifier(OS, *this);
416 if (!verifier.handleDebugInfoUnitHeaderChain())
417 Success = false;
416418 if (DumpType == DIDT_All || DumpType == DIDT_Info) {
417419 if (!verifier.handleDebugInfo())
418420 Success = false;
2222 using namespace llvm;
2323 using namespace dwarf;
2424 using namespace object;
25
26 bool DWARFVerifier::verifyUnitHeader(const DWARFDataExtractor DebugInfoData,
27 uint32_t *Offset, unsigned UnitIndex,
28 bool &isUnitDWARF64) {
29 uint32_t AbbrOffset, Length;
30 uint8_t AddrSize = 0, UnitType = 0;
31 uint16_t Version;
32 bool Success = true;
33 uint32_t HeaderSize =
34 11; // means that we have only compile units in .debug_info
35
36 bool ValidLength = false;
37 bool ValidVersion = false;
38 bool ValidAddrSize = false;
39 bool ValidType = true;
40 bool ValidAbbrevOffset = true;
41
42 uint32_t OffsetStart = *Offset;
43 Length = DebugInfoData.getU32(Offset);
44 if (Length == UINT32_MAX) {
45 isUnitDWARF64 = true;
46 OS << format(
47 "Unit[%d] is in 64-bit DWARF format; cannot verify from this point.\n",
48 UnitIndex);
49 return false;
50 }
51 Version = DebugInfoData.getU16(Offset);
52
53 if (Version >= 5) {
54 UnitType = DebugInfoData.getU8(Offset);
55 AddrSize = DebugInfoData.getU8(Offset);
56 AbbrOffset = DebugInfoData.getU32(Offset);
57 ValidType = DWARFUnit::isValidUnitType(UnitType);
58 if (ValidType)
59 HeaderSize = DWARFUnit::getDWARF5HeaderSize(UnitType);
60 } else {
61 AbbrOffset = DebugInfoData.getU32(Offset);
62 AddrSize = DebugInfoData.getU8(Offset);
63 }
64
65 if (!DCtx.getDebugAbbrev()->getAbbreviationDeclarationSet(AbbrOffset))
66 ValidAbbrevOffset = false;
67
68 ValidLength = DebugInfoData.isValidOffset(OffsetStart + Length + 3);
69 ValidVersion = DWARFContext::isSupportedVersion(Version);
70 ValidAddrSize = AddrSize == 4 || AddrSize == 8;
71 if (!ValidLength || !ValidVersion || !ValidAddrSize || !ValidAbbrevOffset ||
72 !ValidType) {
73 Success = false;
74 OS << format("Units[%d] - start offset: 0x%08x \n", UnitIndex, OffsetStart);
75 if (!ValidLength)
76 OS << "\tError: The length for this unit is too "
77 "large for the .debug_info provided.\n";
78 if (!ValidVersion)
79 OS << "\tError: The 16 bit unit header version is not valid.\n";
80 if (!ValidType)
81 OS << "\tError: The unit type encoding is not valid.\n";
82 if (!ValidAbbrevOffset)
83 OS << "\tError: The offset into the .debug_abbrev section is "
84 "not valid.\n";
85 if (!ValidAddrSize)
86 OS << "\tError: The address size is unsupported.\n";
87 }
88 *Offset = OffsetStart + Length + 4;
89 return Success;
90 }
91
92 bool DWARFVerifier::handleDebugInfoUnitHeaderChain() {
93 OS << "Verifying .debug_info Unit Header Chain...\n";
94
95 DWARFDataExtractor DebugInfoData(DCtx.getInfoSection(), DCtx.isLittleEndian(),
96 0);
97 uint32_t OffsetStart, Offset = 0, UnitIdx = 0;
98 bool isUnitDWARF64 = false;
99 bool Success = true;
100 bool hasDIE = DebugInfoData.isValidOffset(Offset);
101 while (hasDIE) {
102 OffsetStart = Offset;
103 if (!verifyUnitHeader(DebugInfoData, &Offset, UnitIdx, isUnitDWARF64)) {
104 Success = false;
105 if (isUnitDWARF64)
106 break;
107 }
108 hasDIE = DebugInfoData.isValidOffset(Offset);
109 ++UnitIdx;
110 }
111 if (UnitIdx == 0 && !hasDIE) {
112 OS << "Warning: .debug_info is empty.\n";
113 Success = true;
114 }
115 return Success;
116 }
25117
26118 void DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
27119 DWARFAttribute &AttrValue) {
0 # RUN: llvm-mc %s -filetype obj -triple x86_64-apple-darwin -o - \
1 # RUN: | not llvm-dwarfdump -verify - \
2 # RUN: | FileCheck %s
3
4 # CHECK: Verifying .debug_info Unit Header Chain...
5 # CHECK-NEXT: Units[1] - start offset: 0x0000000d
6 # CHECK-NEXT: Error: The unit type encoding is not valid.
7 # CHECK-NEXT: Error: The address size is unsupported.
8 # CHECK-NEXT: Units[2] - start offset: 0x00000026
9 # CHECK-NEXT: Error: The 16 bit unit header version is not valid.
10 # CHECK-NEXT: Error: The offset into the .debug_abbrev section is not valid.
11 # CHECK-NEXT: Units[4] - start offset: 0x00000041
12 # CHECK-NEXT: Error: The length for this unit is too large for the .debug_info provided.
13
14 .section __TEXT,__text,regular,pure_instructions
15 .file 1 "basic.c"
16 .comm _i,4,2 ## @i
17 .comm _j,4,2 ## @j
18 .section __DWARF,__debug_str,regular,debug
19 Linfo_string:
20 .asciz "clang version 5.0.0 (trunk 307232) (llvm/trunk 307042)" ## string offset=0
21 .asciz "basic.c" ## string offset=55
22 .asciz "/Users/sgravani/Development/tests" ## string offset=63
23 .asciz "i" ## string offset=97
24 .asciz "int" ## string offset=99
25 .asciz "j" ## string offset=103
26 .section __DWARF,__debug_abbrev,regular,debug
27 Lsection_abbrev:
28 .byte 1 ## Abbreviation Code
29 .byte 17 ## DW_TAG_compile_unit
30 .byte 0 ## EOM(1)
31 .byte 0 ## EOM(2)
32 .byte 0 ## EOM(3)
33 .section __DWARF,__debug_info,regular,debug
34 Lsection_info:
35 Lcu_begin0:
36 .long 9 ## Length of Unit
37 .short 4 ## DWARF version number
38 Lset0 = Lsection_abbrev-Lsection_abbrev ## Offset Into Abbrev. Section
39 .long Lset0
40 .byte 4 ## Address Size (in bytes)
41 .byte 1 ## Abbrev [1] 0xc:0x45 DW_TAG_compile_unit
42 .byte 0 ## End Of Children Mark
43 Ltu_begin0:
44 .long 21 ## Length of Unit
45 .short 5 ## DWARF version number
46 .byte 0 ## DWARF Unit Type -- Error: The unit type encoding is not valid.
47 .byte 3 ## Address Size (in bytes) -- Error: The address size is unsupported.
48 .long 0
49 .quad 0
50 .long 0
51 .byte 0
52 Lcu_begin1:
53 .long 10 ## Length of Unit
54 .short 6 ## DWARF version number -- Error: The 16 bit unit header version is not valid.
55 .byte 1 ## DWARF Unit Type
56 .byte 4 ## Address Size (in bytes) -- The offset into the .debug_abbrev section is not valid.
57 .long Lline_table_start0
58 .byte 1 ## Abbrev [1] 0xc:0x45 DW_TAG_compile_unit
59 .byte 0 ## End Of Children Mark
60 Lcu_begin2:
61 .long 9 ## Length of Unit
62 .short 5 ## DWARF version number
63 .byte 1 ## DWARF Unit Type
64 .byte 4 ## Address Size (in bytes)
65 .long 0 ## Abbrev offset
66 .byte 0
67 Ltu_begin1:
68 .long 26 ## Length of Unit -- Error: The length for this unit is too large for the .debug_info provided.
69 .short 5 ## DWARF version number
70 .byte 2 ## DWARF Unit Type
71 .byte 4 ## Address Size (in bytes)
72 .long 0
73 .quad 0
74 .long 0
75 .byte 0
76
77 .subsections_via_symbols
78 .section __DWARF,__debug_line,regular,debug
79 Lsection_line:
80 Lline_table_start0: