xref: /llvm-project/llvm/unittests/DebugInfo/DWARF/DWARFDieTest.cpp (revision 9de73b20404f0b2db1cbf70d164cfe0789d5bb94)
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 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/BinaryFormat/Dwarf.h"
10 #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
11 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
12 #include "llvm/DebugInfo/DWARF/DWARFTypePrinter.h"
13 #include "llvm/ObjectYAML/DWARFEmitter.h"
14 #include "llvm/Testing/Support/Error.h"
15 #include "gtest/gtest.h"
16 
17 using namespace llvm;
18 using namespace llvm::dwarf;
19 
20 namespace {
21 
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());
78 
79   EXPECT_THAT_EXPECTED(Die.getLocations(DW_AT_location),
80                        HasValue(testing::ElementsAre(DWARFLocationExpression{
81                            DWARFAddressRange{1, 3}, {}})));
82 
83   EXPECT_THAT_EXPECTED(Die.getLocations(DW_AT_data_member_location),
84                        HasValue(testing::ElementsAre(
85                            DWARFLocationExpression{std::nullopt, {0x47}})));
86 
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")));
92 
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)"));
97 
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")));
102 }
103 
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
154   )";
155 
156   // Given DWARF like this:
157   //
158   // 0x0000000b: DW_TAG_compile_unit
159   //               DW_AT_stmt_list (0x00000000)
160   //
161   // 0x00000010:   DW_TAG_subprogram
162   //                 DW_AT_decl_file ("/tmp/main.cpp")
163   //
164   // 0x00000012:   NULL
165   //
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.
168 
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());
180 
181   DWARFDie MainDie = Die.getFirstChild();
182   ASSERT_TRUE(MainDie.isValid());
183 
184   std::string DeclFile = MainDie.getDeclFile(
185       DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath);
186 
187   std::string Ref =
188       ("/tmp" + llvm::sys::path::get_separator() + "main.cpp").str();
189   EXPECT_EQ(DeclFile, Ref);
190 }
191 
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
251   )";
252 
253   // Given DWARF like this:
254   //
255   // 0x0000000b: DW_TAG_compile_unit
256   //               DW_AT_stmt_list (0x00000000)
257   //
258   // 0x00000010:   DW_TAG_subprogram
259   //                 DW_AT_abstract_origin (0x0000000000000015)
260   //
261   // 0x00000015:   DW_TAG_subprogram
262   //                 DW_AT_decl_file ("/tmp/main.cpp")
263   //
264   // 0x00000017:   NULL
265   //
266   //
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".
270   //
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.
274 
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());
286 
287   DWARFDie MainDie = Die.getFirstChild();
288   ASSERT_TRUE(MainDie.isValid());
289 
290   std::string DeclFile = MainDie.getDeclFile(
291       DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath);
292 
293   std::string Ref =
294       ("/tmp" + llvm::sys::path::get_separator() + "main.cpp").str();
295   EXPECT_EQ(DeclFile, Ref);
296 }
297 
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
357   )";
358 
359   // Given DWARF like this:
360   //
361   // 0x0000000b: DW_TAG_compile_unit
362   //               DW_AT_stmt_list   (0x00000000)
363   //
364   // 0x00000010:   DW_TAG_subprogram
365   //                 DW_AT_specification     (0x0000000000000015)
366   //
367   // 0x00000015:   DW_TAG_subprogram
368   //                 DW_AT_decl_file ("/tmp/main.cpp")
369   //
370   // 0x00000017:   NULL
371   //
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".
375   //
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.
379 
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());
391 
392   DWARFDie MainDie = Die.getFirstChild();
393   ASSERT_TRUE(MainDie.isValid());
394 
395   std::string DeclFile = MainDie.getDeclFile(
396       DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath);
397 
398   std::string Ref =
399       ("/tmp" + llvm::sys::path::get_separator() + "main.cpp").str();
400   EXPECT_EQ(DeclFile, Ref);
401 }
402 
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
473   )";
474 
475   // Given DWARF like this:
476   //
477   // 0x0000000b: DW_TAG_compile_unit
478   //
479   // 0x0000000c:   DW_TAG_subprogram
480   //                 DW_AT_abstract_origin (0x0000000000000022)
481   //
482   // 0x00000011:   NULL
483   //
484   // 0x0000001d: DW_TAG_compile_unit
485   //               DW_AT_stmt_list (0x00000000)
486   //
487   // 0x00000022:   DW_TAG_subprogram
488   //                 DW_AT_decl_file ("/tmp/main.cpp")
489   //
490   // 0x00000024:   NULL
491   //
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.
495   //
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.
501 
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());
513 
514   DWARFDie MainDie = Die.getFirstChild();
515   ASSERT_TRUE(MainDie.isValid());
516 
517   std::string DeclFile = MainDie.getDeclFile(
518       DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath);
519 
520   std::string Ref =
521       ("/tmp" + llvm::sys::path::get_separator() + "main.cpp").str();
522   EXPECT_EQ(DeclFile, Ref);
523 }
524 
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
595   )";
596 
597   // Given DWARF like this:
598   //
599   // 0x0000000b: DW_TAG_compile_unit
600   //
601   // 0x0000000c:   DW_TAG_subprogram
602   //                 DW_AT_specification     (0x0000000000000022)
603   //
604   // 0x00000011:   NULL
605   //
606   // 0x0000001d: DW_TAG_compile_unit
607   //               DW_AT_stmt_list   (0x00000000)
608   //
609   // 0x00000022:   DW_TAG_subprogram
610   //                 DW_AT_decl_file ("/tmp/main.cpp")
611   //
612   // 0x00000024:   NULL
613   //
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.
617   //
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.
623 
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());
635 
636   DWARFDie MainDie = Die.getFirstChild();
637   ASSERT_TRUE(MainDie.isValid());
638 
639   std::string DeclFile = MainDie.getDeclFile(
640       DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath);
641 
642   std::string Ref =
643       ("/tmp" + llvm::sys::path::get_separator() + "main.cpp").str();
644   EXPECT_EQ(DeclFile, Ref);
645 }
646 
647 TEST(DWARFDie, getNameFromTypeUnit) {
648   const char *yamldata = R"(
649   debug_abbrev:
650     - ID:              0
651       Table:
652         - Code:            0x1
653           Tag:             DW_TAG_compile_unit
654           Children:        DW_CHILDREN_yes
655         - Code:            0x2
656           Tag:             DW_TAG_structure_type
657           Children:        DW_CHILDREN_no
658           Attributes:
659             - Attribute:       DW_AT_signature
660               Form:            DW_FORM_ref_sig8
661         - Code:            0x3
662           Tag:             DW_TAG_type_unit
663           Children:        DW_CHILDREN_yes
664         - Code:            0x4
665           Tag:             DW_TAG_structure_type
666           Children:        DW_CHILDREN_no
667           Attributes:
668             - Attribute:       DW_AT_name
669               Form:            DW_FORM_string
670   debug_info:
671     - Version:         5
672       UnitType:        DW_UT_compile
673       AbbrevTableID:   0
674       Entries:
675         - AbbrCode:        0x1
676         - AbbrCode:        0x2
677           Values:
678             - Value:           0xdeadbeefbaadf00d
679         - AbbrCode:        0x0
680     - Version:         5
681       UnitType:        DW_UT_type
682       AbbrevTableID:   0
683       TypeSignature:   0xdeadbeefbaadf00d
684       TypeOffset:      25
685       Entries:
686         - AbbrCode:        0x3
687         - AbbrCode:        0x4
688           Values:
689             - CStr:        "STRUCT"
690         - AbbrCode:        0x0
691   )";
692 
693   Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections =
694       DWARFYAML::emitDebugSections(StringRef(yamldata),
695                                    /*IsLittleEndian=*/true,
696                                    /*Is64BitAddrSize=*/true);
697   ASSERT_THAT_EXPECTED(Sections, Succeeded());
698   std::unique_ptr<DWARFContext> Ctx =
699       DWARFContext::create(*Sections, 4, /*isLittleEndian=*/true);
700   DWARFCompileUnit *CU = Ctx->getCompileUnitForOffset(0);
701   ASSERT_NE(nullptr, CU);
702   DWARFDie Die = CU->getUnitDIE(/*ExtractUnitDIEOnly=*/false).getFirstChild();
703   ASSERT_TRUE(Die.isValid());
704 
705   ASSERT_STREQ(Die.getName(DINameKind::ShortName), "STRUCT");
706 }
707 
708 void testAppendAndTerminateTemplateParameters(const DWARFDie &DIE,
709                                               const std::string &Expected) {
710   std::string TemplateName;
711   llvm::raw_string_ostream TemplateNameOS(TemplateName);
712   llvm::DWARFTypePrinter<DWARFDie> TemplateNamePrinter(TemplateNameOS);
713   TemplateNamePrinter.appendAndTerminateTemplateParameters(DIE);
714   EXPECT_THAT(TemplateName, Expected);
715 }
716 
717 void testAppendQualifiedName(const DWARFDie &DIE, const std::string &Expected) {
718   std::string QualifiedName;
719   llvm::raw_string_ostream TemplateNameOS(QualifiedName);
720   llvm::DWARFTypePrinter<DWARFDie> TemplateNamePrinter(TemplateNameOS);
721   TemplateNamePrinter.appendQualifiedName(DIE);
722   EXPECT_THAT(QualifiedName, Expected);
723 }
724 
725 TEST(DWARFDie, DWARFTypePrinterTest) {
726   // Make sure we can get template parameters and qualified names correctly with
727   // DWARFTypePrinter when using -gsimple-template-names.
728 
729   // 0x0000000b: DW_TAG_compile_unit
730   // 0x0000000c:   DW_TAG_base_type
731   //                 DW_AT_name      ("int")
732   // 0x00000011:   DW_TAG_structure_type
733   //                 DW_AT_name      ("t1")
734   // 0x00000015:     DW_TAG_template_type_parameter
735   //                   DW_AT_type    (0x0000001f "t3<int>")
736   // 0x0000001a:     DW_TAG_structure_type
737   //                   DW_AT_name    ("t2")
738   // 0x0000001e:     NULL
739   // 0x0000001f:   DW_TAG_structure_type
740   //                 DW_AT_name      ("t3")
741   // 0x00000023:     DW_TAG_template_type_parameter
742   //                   DW_AT_type    (0x0000000c "int")
743   // 0x00000028:     NULL
744   // 0x00000029:   NULL
745   const char *yamldata = R"(
746   debug_abbrev:
747     - ID:              0
748       Table:
749         - Code:            0x1
750           Tag:             DW_TAG_compile_unit
751           Children:        DW_CHILDREN_yes
752         - Code:            0x2
753           Tag:             DW_TAG_base_type
754           Children:        DW_CHILDREN_no
755           Attributes:
756             - Attribute:       DW_AT_name
757               Form:            DW_FORM_string
758         - Code:            0x3
759           Tag:             DW_TAG_structure_type
760           Children:        DW_CHILDREN_yes
761           Attributes:
762             - Attribute:       DW_AT_name
763               Form:            DW_FORM_string
764         - Code:            0x4
765           Tag:             DW_TAG_template_type_parameter
766           Children:        DW_CHILDREN_no
767           Attributes:
768             - Attribute:       DW_AT_type
769               Form:            DW_FORM_ref4
770         - Code:            0x5
771           Tag:             DW_TAG_structure_type
772           Children:        DW_CHILDREN_no
773           Attributes:
774             - Attribute:       DW_AT_name
775               Form:            DW_FORM_string
776         - Code:            0x6
777           Tag:             DW_TAG_structure_type
778           Children:        DW_CHILDREN_yes
779           Attributes:
780             - Attribute:       DW_AT_name
781               Form:            DW_FORM_string
782         - Code:            0x7
783           Tag:             DW_TAG_template_type_parameter
784           Children:        DW_CHILDREN_no
785           Attributes:
786             - Attribute:       DW_AT_type
787               Form:            DW_FORM_ref4
788         - Code:            0x8
789           Tag:             DW_TAG_typedef
790           Children:        DW_CHILDREN_no
791           Attributes:
792             - Attribute:       DW_AT_type
793               Form:            DW_FORM_ref4
794             - Attribute:       DW_AT_name
795               Form:            DW_FORM_string
796   debug_info:
797     - Version:         4
798       AddrSize:        8
799       Entries:
800         - AbbrCode:        0x1
801         - AbbrCode:        0x2
802           Values:
803             - Value:           0xDEADBEEFDEADBEEF
804               CStr:            int
805         - AbbrCode:        0x3
806           Values:
807             - Value:           0xDEADBEEFDEADBEEF
808               CStr:            t1
809         - AbbrCode:        0x4
810           Values:
811             - Value:            0x0000001f # update
812         - AbbrCode:        0x5
813           Values:
814             - Value:           0xDEADBEEFDEADBEEF
815               CStr:            t2
816         - AbbrCode:        0x0
817         - AbbrCode:        0x6
818           Values:
819             - Value:           0xDEADBEEFDEADBEEF
820               CStr:            t3
821         - AbbrCode:        0x7
822           Values:
823             - Value:            0x0000000c # update
824         - AbbrCode:        0x8
825           Values:
826             - Value:            0x0000000c
827             - CStr:            my_int
828         - AbbrCode:        0x0
829         - AbbrCode:        0x0)";
830   Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections =
831       DWARFYAML::emitDebugSections(StringRef(yamldata),
832                                    /*IsLittleEndian=*/true,
833                                    /*Is64BitAddrSize=*/true);
834   ASSERT_THAT_EXPECTED(Sections, Succeeded());
835   std::unique_ptr<DWARFContext> Ctx =
836       DWARFContext::create(*Sections, 4, /*isLittleEndian=*/true);
837   testAppendAndTerminateTemplateParameters(Ctx->getDIEForOffset(0x11),
838                                            "<t3<int> >");
839   testAppendQualifiedName(Ctx->getDIEForOffset(0x1a), "t1<t3<int> >::t2");
840   testAppendQualifiedName(Ctx->getDIEForOffset(0x28), "t3<int>::my_int");
841 }
842 } // end anonymous namespace
843