[docs] Fix build-docs.sh
[llvm-project.git] / llvm / unittests / DebugInfo / DWARF / DWARFDieTest.cpp
blob2754ba0afdf0cd0bb081335d77fc56e45188d72f
1 //===- llvm/unittest/DebugInfo/DWARFDieTest.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 //===----------------------------------------------------------------------===//
9 #include "llvm/BinaryFormat/Dwarf.h"
10 #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
11 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
12 #include "llvm/ObjectYAML/DWARFEmitter.h"
13 #include "llvm/Testing/Support/Error.h"
14 #include "gtest/gtest.h"
16 using namespace llvm;
17 using namespace llvm::dwarf;
18 using object::SectionedAddress;
20 namespace {
22 TEST(DWARFDie, getLocations) {
23 const char *yamldata = R"(
24 debug_abbrev:
25 - Table:
26 - Code: 0x00000001
27 Tag: DW_TAG_compile_unit
28 Children: DW_CHILDREN_no
29 Attributes:
30 - Attribute: DW_AT_location
31 Form: DW_FORM_sec_offset
32 - Attribute: DW_AT_data_member_location
33 Form: DW_FORM_exprloc
34 - Attribute: DW_AT_vtable_elem_location
35 Form: DW_FORM_sec_offset
36 - Attribute: DW_AT_call_data_location
37 Form: DW_FORM_sec_offset
38 debug_info:
39 - Version: 5
40 UnitType: DW_UT_compile
41 AddrSize: 4
42 Entries:
43 - AbbrCode: 0x00000001
44 Values:
45 - Value: 12
46 - Value: 0x0000000000000001
47 BlockData: [ 0x47 ]
48 - Value: 20
49 - Value: 25
50 debug_loclists:
51 - AddressSize: 4
52 OffsetEntryCount: 0
53 Lists:
54 - Entries:
55 - Operator: DW_LLE_start_length
56 Values: [ 0x01, 0x02 ]
57 - Operator: DW_LLE_end_of_list
58 - Entries:
59 - Operator: DW_LLE_startx_length
60 Values: [ 0x01, 0x02 ]
61 - Operator: DW_LLE_end_of_list
62 - Entries:
63 - Operator: DW_LLE_start_length
64 Values: [ 0x01, 0x02 ]
65 ## end_of_list intentionally missing.
66 )";
67 Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections =
68 DWARFYAML::emitDebugSections(StringRef(yamldata),
69 /*IsLittleEndian=*/true,
70 /*Is64BitAddrSize=*/false);
71 ASSERT_THAT_EXPECTED(Sections, Succeeded());
72 std::unique_ptr<DWARFContext> Ctx =
73 DWARFContext::create(*Sections, 4, /*isLittleEndian=*/true);
74 DWARFCompileUnit *CU = Ctx->getCompileUnitForOffset(0);
75 ASSERT_NE(nullptr, CU);
76 DWARFDie Die = CU->getUnitDIE();
77 ASSERT_TRUE(Die.isValid());
79 EXPECT_THAT_EXPECTED(Die.getLocations(DW_AT_location),
80 HasValue(testing::ElementsAre(DWARFLocationExpression{
81 DWARFAddressRange{1, 3}, {}})));
83 EXPECT_THAT_EXPECTED(
84 Die.getLocations(DW_AT_data_member_location),
85 HasValue(testing::ElementsAre(DWARFLocationExpression{None, {0x47}})));
87 EXPECT_THAT_EXPECTED(
88 Die.getLocations(DW_AT_vtable_elem_location),
89 Failed<ErrorInfoBase>(testing::Property(
90 &ErrorInfoBase::message,
91 "unable to resolve indirect address 1 for: DW_LLE_startx_length")));
93 EXPECT_THAT_EXPECTED(
94 Die.getLocations(DW_AT_call_data_location),
95 FailedWithMessage(
96 "unexpected end of data at offset 0x20 while reading [0x20, 0x21)"));
98 EXPECT_THAT_EXPECTED(
99 Die.getLocations(DW_AT_call_data_value),
100 Failed<ErrorInfoBase>(testing::Property(&ErrorInfoBase::message,
101 "No DW_AT_call_data_value")));
104 TEST(DWARFDie, getDeclFile) {
105 const char *yamldata = R"(
106 debug_str:
107 - ''
108 debug_abbrev:
109 - ID: 0
110 Table:
111 - Code: 0x1
112 Tag: DW_TAG_compile_unit
113 Children: DW_CHILDREN_yes
114 Attributes:
115 - Attribute: DW_AT_stmt_list
116 Form: DW_FORM_sec_offset
117 - Code: 0x2
118 Tag: DW_TAG_subprogram
119 Children: DW_CHILDREN_no
120 Attributes:
121 - Attribute: DW_AT_decl_file
122 Form: DW_FORM_data1
123 debug_info:
124 - Length: 0xF
125 Version: 4
126 AbbrevTableID: 0
127 AbbrOffset: 0x0
128 AddrSize: 8
129 Entries:
130 - AbbrCode: 0x1
131 Values:
132 - Value: 0x0
133 - AbbrCode: 0x2
134 Values:
135 - Value: 0x1
136 - AbbrCode: 0x0
137 debug_line:
138 - Length: 42
139 Version: 2
140 PrologueLength: 36
141 MinInstLength: 1
142 DefaultIsStmt: 1
143 LineBase: 251
144 LineRange: 14
145 OpcodeBase: 13
146 StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]
147 IncludeDirs:
148 - '/tmp'
149 Files:
150 - Name: main.cpp
151 DirIdx: 1
152 ModTime: 0
153 Length: 0
156 // Given DWARF like this:
158 // 0x0000000b: DW_TAG_compile_unit
159 // DW_AT_stmt_list (0x00000000)
161 // 0x00000010: DW_TAG_subprogram
162 // DW_AT_decl_file ("/tmp/main.cpp")
164 // 0x00000012: NULL
166 // This tests that we can extract the right DW_AT_decl_file from a DIE that
167 // has a DW_AT_decl_file attribute.
169 Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections =
170 DWARFYAML::emitDebugSections(StringRef(yamldata),
171 /*IsLittleEndian=*/true,
172 /*Is64BitAddrSize=*/true);
173 ASSERT_THAT_EXPECTED(Sections, Succeeded());
174 std::unique_ptr<DWARFContext> Ctx =
175 DWARFContext::create(*Sections, 4, /*isLittleEndian=*/true);
176 DWARFCompileUnit *CU = Ctx->getCompileUnitForOffset(0);
177 ASSERT_NE(nullptr, CU);
178 DWARFDie Die = CU->getUnitDIE(/*ExtractUnitDIEOnly=*/false);
179 ASSERT_TRUE(Die.isValid());
181 DWARFDie MainDie = Die.getFirstChild();
182 ASSERT_TRUE(MainDie.isValid());
184 std::string DeclFile = MainDie.getDeclFile(
185 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath);
187 std::string Ref =
188 ("/tmp" + llvm::sys::path::get_separator() + "main.cpp").str();
189 EXPECT_EQ(DeclFile, Ref);
192 TEST(DWARFDie, getDeclFileAbstractOrigin) {
193 const char *yamldata = R"(
194 debug_str:
195 - ''
196 debug_abbrev:
197 - ID: 0
198 Table:
199 - Code: 0x1
200 Tag: DW_TAG_compile_unit
201 Children: DW_CHILDREN_yes
202 Attributes:
203 - Attribute: DW_AT_stmt_list
204 Form: DW_FORM_sec_offset
205 - Code: 0x2
206 Tag: DW_TAG_subprogram
207 Children: DW_CHILDREN_no
208 Attributes:
209 - Attribute: DW_AT_abstract_origin
210 Form: DW_FORM_ref_addr
211 - Code: 0x3
212 Tag: DW_TAG_subprogram
213 Children: DW_CHILDREN_no
214 Attributes:
215 - Attribute: DW_AT_decl_file
216 Form: DW_FORM_data1
217 debug_info:
218 - Length: 0x14
219 Version: 4
220 AbbrevTableID: 0
221 AbbrOffset: 0x0
222 AddrSize: 8
223 Entries:
224 - AbbrCode: 0x1
225 Values:
226 - Value: 0x0
227 - AbbrCode: 0x2
228 Values:
229 - Value: 0x15
230 - AbbrCode: 0x3
231 Values:
232 - Value: 0x1
233 - AbbrCode: 0x0
234 debug_line:
235 - Length: 42
236 Version: 2
237 PrologueLength: 36
238 MinInstLength: 1
239 DefaultIsStmt: 1
240 LineBase: 251
241 LineRange: 14
242 OpcodeBase: 13
243 StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]
244 IncludeDirs:
245 - '/tmp'
246 Files:
247 - Name: main.cpp
248 DirIdx: 1
249 ModTime: 0
250 Length: 0
253 // Given DWARF like this:
255 // 0x0000000b: DW_TAG_compile_unit
256 // DW_AT_stmt_list (0x00000000)
258 // 0x00000010: DW_TAG_subprogram
259 // DW_AT_abstract_origin (0x0000000000000015)
261 // 0x00000015: DW_TAG_subprogram
262 // DW_AT_decl_file ("/tmp/main.cpp")
264 // 0x00000017: NULL
267 // The DIE at 0x00000010 uses a DW_AT_abstract_origin to point to the DIE at
268 // 0x00000015, make sure that DWARFDie::getDeclFile() succeeds by extracting
269 // the right file name of "/tmp/main.cpp".
271 // This tests that when we have a DW_AT_abstract_origin with a compile unit
272 // relative form (DW_FORM_ref4) to another DIE that we get the right
273 // DW_AT_decl_file value.
275 Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections =
276 DWARFYAML::emitDebugSections(StringRef(yamldata),
277 /*IsLittleEndian=*/true,
278 /*Is64BitAddrSize=*/true);
279 ASSERT_THAT_EXPECTED(Sections, Succeeded());
280 std::unique_ptr<DWARFContext> Ctx =
281 DWARFContext::create(*Sections, 4, /*isLittleEndian=*/true);
282 DWARFCompileUnit *CU = Ctx->getCompileUnitForOffset(0);
283 ASSERT_NE(nullptr, CU);
284 DWARFDie Die = CU->getUnitDIE(/*ExtractUnitDIEOnly=*/false);
285 ASSERT_TRUE(Die.isValid());
287 DWARFDie MainDie = Die.getFirstChild();
288 ASSERT_TRUE(MainDie.isValid());
290 std::string DeclFile = MainDie.getDeclFile(
291 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath);
293 std::string Ref =
294 ("/tmp" + llvm::sys::path::get_separator() + "main.cpp").str();
295 EXPECT_EQ(DeclFile, Ref);
298 TEST(DWARFDie, getDeclFileSpecification) {
299 const char *yamldata = R"(
300 debug_str:
301 - ''
302 debug_abbrev:
303 - ID: 0
304 Table:
305 - Code: 0x1
306 Tag: DW_TAG_compile_unit
307 Children: DW_CHILDREN_yes
308 Attributes:
309 - Attribute: DW_AT_stmt_list
310 Form: DW_FORM_sec_offset
311 - Code: 0x2
312 Tag: DW_TAG_subprogram
313 Children: DW_CHILDREN_no
314 Attributes:
315 - Attribute: DW_AT_specification
316 Form: DW_FORM_ref_addr
317 - Code: 0x3
318 Tag: DW_TAG_subprogram
319 Children: DW_CHILDREN_no
320 Attributes:
321 - Attribute: DW_AT_decl_file
322 Form: DW_FORM_data1
323 debug_info:
324 - Length: 0x14
325 Version: 4
326 AbbrevTableID: 0
327 AbbrOffset: 0x0
328 AddrSize: 8
329 Entries:
330 - AbbrCode: 0x1
331 Values:
332 - Value: 0x0
333 - AbbrCode: 0x2
334 Values:
335 - Value: 0x15
336 - AbbrCode: 0x3
337 Values:
338 - Value: 0x1
339 - AbbrCode: 0x0
340 debug_line:
341 - Length: 42
342 Version: 2
343 PrologueLength: 36
344 MinInstLength: 1
345 DefaultIsStmt: 1
346 LineBase: 251
347 LineRange: 14
348 OpcodeBase: 13
349 StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]
350 IncludeDirs:
351 - '/tmp'
352 Files:
353 - Name: main.cpp
354 DirIdx: 1
355 ModTime: 0
356 Length: 0
359 // Given DWARF like this:
361 // 0x0000000b: DW_TAG_compile_unit
362 // DW_AT_stmt_list (0x00000000)
364 // 0x00000010: DW_TAG_subprogram
365 // DW_AT_specification (0x0000000000000015)
367 // 0x00000015: DW_TAG_subprogram
368 // DW_AT_decl_file ("/tmp/main.cpp")
370 // 0x00000017: NULL
372 // The DIE at 0x00000010 uses a DW_AT_specification to point to the DIE at
373 // 0x00000015, make sure that DWARFDie::getDeclFile() succeeds by extracting
374 // the right file name of "/tmp/main.cpp".
376 // This tests that when we have a DW_AT_specification with a compile unit
377 // relative form (DW_FORM_ref4) to another DIE that we get the right
378 // DW_AT_decl_file value.
380 Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections =
381 DWARFYAML::emitDebugSections(StringRef(yamldata),
382 /*IsLittleEndian=*/true,
383 /*Is64BitAddrSize=*/true);
384 ASSERT_THAT_EXPECTED(Sections, Succeeded());
385 std::unique_ptr<DWARFContext> Ctx =
386 DWARFContext::create(*Sections, 4, /*isLittleEndian=*/true);
387 DWARFCompileUnit *CU = Ctx->getCompileUnitForOffset(0);
388 ASSERT_NE(nullptr, CU);
389 DWARFDie Die = CU->getUnitDIE(/*ExtractUnitDIEOnly=*/false);
390 ASSERT_TRUE(Die.isValid());
392 DWARFDie MainDie = Die.getFirstChild();
393 ASSERT_TRUE(MainDie.isValid());
395 std::string DeclFile = MainDie.getDeclFile(
396 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath);
398 std::string Ref =
399 ("/tmp" + llvm::sys::path::get_separator() + "main.cpp").str();
400 EXPECT_EQ(DeclFile, Ref);
403 TEST(DWARFDie, getDeclFileAbstractOriginAcrossCUBoundary) {
404 const char *yamldata = R"(
405 debug_str:
406 - ''
407 debug_abbrev:
408 - ID: 0
409 Table:
410 - Code: 0x1
411 Tag: DW_TAG_compile_unit
412 Children: DW_CHILDREN_yes
413 - Code: 0x2
414 Tag: DW_TAG_subprogram
415 Children: DW_CHILDREN_no
416 Attributes:
417 - Attribute: DW_AT_abstract_origin
418 Form: DW_FORM_ref_addr
419 - Code: 0x3
420 Tag: DW_TAG_compile_unit
421 Children: DW_CHILDREN_yes
422 Attributes:
423 - Attribute: DW_AT_stmt_list
424 Form: DW_FORM_sec_offset
425 - Code: 0x4
426 Tag: DW_TAG_subprogram
427 Children: DW_CHILDREN_no
428 Attributes:
429 - Attribute: DW_AT_decl_file
430 Form: DW_FORM_data1
431 debug_info:
432 - Length: 0xE
433 Version: 4
434 AbbrevTableID: 0
435 AbbrOffset: 0x0
436 AddrSize: 8
437 Entries:
438 - AbbrCode: 0x1
439 - AbbrCode: 0x2
440 Values:
441 - Value: 0x22
442 - AbbrCode: 0x0
443 - Length: 0xF
444 Version: 4
445 AbbrevTableID: 0
446 AbbrOffset: 0x0
447 AddrSize: 8
448 Entries:
449 - AbbrCode: 0x3
450 Values:
451 - Value: 0x0
452 - AbbrCode: 0x4
453 Values:
454 - Value: 0x1
455 - AbbrCode: 0x0
456 debug_line:
457 - Length: 42
458 Version: 2
459 PrologueLength: 36
460 MinInstLength: 1
461 DefaultIsStmt: 1
462 LineBase: 251
463 LineRange: 14
464 OpcodeBase: 13
465 StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]
466 IncludeDirs:
467 - '/tmp'
468 Files:
469 - Name: main.cpp
470 DirIdx: 1
471 ModTime: 0
472 Length: 0
475 // Given DWARF like this:
477 // 0x0000000b: DW_TAG_compile_unit
479 // 0x0000000c: DW_TAG_subprogram
480 // DW_AT_abstract_origin (0x0000000000000022)
482 // 0x00000011: NULL
484 // 0x0000001d: DW_TAG_compile_unit
485 // DW_AT_stmt_list (0x00000000)
487 // 0x00000022: DW_TAG_subprogram
488 // DW_AT_decl_file ("/tmp/main.cpp")
490 // 0x00000024: NULL
492 // This tests that when we have a DW_AT_abstract_origin with a
493 // DW_FORM_ref_addr to another DIE in another compile unit that we use the
494 // right file table when converting the file index of the DW_AT_decl_file.
496 // The DIE at 0x0000000c uses a DW_AT_abstract_origin to point to the DIE at
497 // 0x00000022, make sure that DWARFDie::getDeclFile() succeeds by extracting
498 // the right file name of "/tmp/main.cpp". The DW_AT_decl_file must grab the
499 // file from the line table prologue of the compile unit at offset
500 // 0x0000001d.
502 Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections =
503 DWARFYAML::emitDebugSections(StringRef(yamldata),
504 /*IsLittleEndian=*/true,
505 /*Is64BitAddrSize=*/true);
506 ASSERT_THAT_EXPECTED(Sections, Succeeded());
507 std::unique_ptr<DWARFContext> Ctx =
508 DWARFContext::create(*Sections, 4, /*isLittleEndian=*/true);
509 DWARFCompileUnit *CU = Ctx->getCompileUnitForOffset(0);
510 ASSERT_NE(nullptr, CU);
511 DWARFDie Die = CU->getUnitDIE(/*ExtractUnitDIEOnly=*/false);
512 ASSERT_TRUE(Die.isValid());
514 DWARFDie MainDie = Die.getFirstChild();
515 ASSERT_TRUE(MainDie.isValid());
517 std::string DeclFile = MainDie.getDeclFile(
518 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath);
520 std::string Ref =
521 ("/tmp" + llvm::sys::path::get_separator() + "main.cpp").str();
522 EXPECT_EQ(DeclFile, Ref);
525 TEST(DWARFDie, getDeclFileSpecificationAcrossCUBoundary) {
526 const char *yamldata = R"(
527 debug_str:
528 - ''
529 debug_abbrev:
530 - ID: 0
531 Table:
532 - Code: 0x1
533 Tag: DW_TAG_compile_unit
534 Children: DW_CHILDREN_yes
535 - Code: 0x2
536 Tag: DW_TAG_subprogram
537 Children: DW_CHILDREN_no
538 Attributes:
539 - Attribute: DW_AT_specification
540 Form: DW_FORM_ref_addr
541 - Code: 0x3
542 Tag: DW_TAG_compile_unit
543 Children: DW_CHILDREN_yes
544 Attributes:
545 - Attribute: DW_AT_stmt_list
546 Form: DW_FORM_sec_offset
547 - Code: 0x4
548 Tag: DW_TAG_subprogram
549 Children: DW_CHILDREN_no
550 Attributes:
551 - Attribute: DW_AT_decl_file
552 Form: DW_FORM_data1
553 debug_info:
554 - Length: 0xE
555 Version: 4
556 AbbrevTableID: 0
557 AbbrOffset: 0x0
558 AddrSize: 8
559 Entries:
560 - AbbrCode: 0x1
561 - AbbrCode: 0x2
562 Values:
563 - Value: 0x22
564 - AbbrCode: 0x0
565 - Length: 0xF
566 Version: 4
567 AbbrevTableID: 0
568 AbbrOffset: 0x0
569 AddrSize: 8
570 Entries:
571 - AbbrCode: 0x3
572 Values:
573 - Value: 0x0
574 - AbbrCode: 0x4
575 Values:
576 - Value: 0x1
577 - AbbrCode: 0x0
578 debug_line:
579 - Length: 42
580 Version: 2
581 PrologueLength: 36
582 MinInstLength: 1
583 DefaultIsStmt: 1
584 LineBase: 251
585 LineRange: 14
586 OpcodeBase: 13
587 StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]
588 IncludeDirs:
589 - '/tmp'
590 Files:
591 - Name: main.cpp
592 DirIdx: 1
593 ModTime: 0
594 Length: 0
597 // Given DWARF like this:
599 // 0x0000000b: DW_TAG_compile_unit
601 // 0x0000000c: DW_TAG_subprogram
602 // DW_AT_specification (0x0000000000000022)
604 // 0x00000011: NULL
606 // 0x0000001d: DW_TAG_compile_unit
607 // DW_AT_stmt_list (0x00000000)
609 // 0x00000022: DW_TAG_subprogram
610 // DW_AT_decl_file ("/tmp/main.cpp")
612 // 0x00000024: NULL
614 // This tests that when we have a DW_AT_specification with a
615 // DW_FORM_ref_addr to another DIE in another compile unit that we use the
616 // right file table when converting the file index of the DW_AT_decl_file.
618 // The DIE at 0x0000000c uses a DW_AT_specification to point to the DIE at
619 // 0x00000022, make sure that DWARFDie::getDeclFile() succeeds by extracting
620 // the right file name of "/tmp/main.cpp". The DW_AT_decl_file must grab the
621 // file from the line table prologue of the compile unit at offset
622 // 0x0000001d.
624 Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections =
625 DWARFYAML::emitDebugSections(StringRef(yamldata),
626 /*IsLittleEndian=*/true,
627 /*Is64BitAddrSize=*/true);
628 ASSERT_THAT_EXPECTED(Sections, Succeeded());
629 std::unique_ptr<DWARFContext> Ctx =
630 DWARFContext::create(*Sections, 4, /*isLittleEndian=*/true);
631 DWARFCompileUnit *CU = Ctx->getCompileUnitForOffset(0);
632 ASSERT_NE(nullptr, CU);
633 DWARFDie Die = CU->getUnitDIE(/*ExtractUnitDIEOnly=*/false);
634 ASSERT_TRUE(Die.isValid());
636 DWARFDie MainDie = Die.getFirstChild();
637 ASSERT_TRUE(MainDie.isValid());
639 std::string DeclFile = MainDie.getDeclFile(
640 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath);
642 std::string Ref =
643 ("/tmp" + llvm::sys::path::get_separator() + "main.cpp").str();
644 EXPECT_EQ(DeclFile, Ref);
647 } // end anonymous namespace