xref: /llvm-project/llvm/unittests/DebugInfo/LogicalView/DWARFGeneratedTest.cpp (revision 3ffee0086c1e31094e544c878f9d5cc413d36b46)
1 //===- llvm/unittest/DebugInfo/LogicalView/DWARFGeneratedTest.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 "../DWARF/DwarfGenerator.h"
10 #include "../DWARF/DwarfUtils.h"
11 #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
12 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
13 #include "llvm/DebugInfo/LogicalView/Core/LVReader.h"
14 #include "llvm/DebugInfo/LogicalView/Core/LVScope.h"
15 #include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h"
16 #include "llvm/DebugInfo/LogicalView/Core/LVType.h"
17 #include "llvm/DebugInfo/LogicalView/LVReaderHandler.h"
18 #include "llvm/MC/TargetRegistry.h"
19 #include "llvm/Support/COM.h"
20 #include "llvm/Support/InitLLVM.h"
21 #include "llvm/Support/ScopedPrinter.h"
22 #include "llvm/Support/TargetSelect.h"
23 #include "llvm/Support/ToolOutputFile.h"
24 #include "llvm/Testing/Support/Error.h"
25 #include "llvm/Testing/Support/SupportHelpers.h"
26 
27 #include "gtest/gtest.h"
28 
29 using namespace llvm;
30 using namespace llvm::logicalview;
31 using namespace llvm::dwarf;
32 using namespace llvm::dwarf::utils;
33 
34 namespace {
35 
36 // Helper function to get the first compile unit.
37 LVScopeCompileUnit *getFirstCompileUnit(LVScopeRoot *Root) {
38   if (!Root)
39     return nullptr;
40 
41   const LVScopes *CompileUnits = Root->getScopes();
42   if (!CompileUnits)
43     return nullptr;
44 
45   LVScopes::const_iterator Iter = CompileUnits->begin();
46   return (Iter != CompileUnits->end())
47              ? static_cast<LVScopeCompileUnit *>(*Iter)
48              : nullptr;
49 }
50 
51 // Helper function to create a reader.
52 std::unique_ptr<LVReader> createReader(LVReaderHandler &ReaderHandler,
53                                        SmallString<128> &InputsDir,
54                                        StringRef Filename) {
55   SmallString<128> ObjectName(InputsDir);
56   llvm::sys::path::append(ObjectName, Filename);
57 
58   Expected<std::unique_ptr<LVReader>> ReaderOrErr =
59       ReaderHandler.createReader(std::string(ObjectName));
60   EXPECT_THAT_EXPECTED(ReaderOrErr, Succeeded());
61   std::unique_ptr<LVReader> Reader = std::move(*ReaderOrErr);
62   return Reader;
63 }
64 
65 // Create a file with generated DWARF.
66 void generateDebugInfo(StringRef Path, Triple &Triple) {
67   uint16_t Version = 5;
68   auto ExpectedDG = dwarfgen::Generator::create(Triple, Version);
69   ASSERT_THAT_EXPECTED(ExpectedDG, Succeeded());
70   dwarfgen::Generator *DG = ExpectedDG.get().get();
71   dwarfgen::CompileUnit &CU = DG->addCompileUnit();
72 
73   dwarfgen::DIE CUDie = CU.getUnitDIE();
74   CUDie.addAttribute(DW_AT_name, DW_FORM_strp, "test.cpp");
75   CUDie.addAttribute(DW_AT_language, DW_FORM_data2, DW_LANG_C_plus_plus);
76   CUDie.addAttribute(DW_AT_producer, DW_FORM_strp, "dwarfgen::Generator");
77 
78   dwarfgen::DIE ScopeValueDie = CUDie.addChild(DW_TAG_inlined_subroutine);
79   ScopeValueDie.addAttribute(DW_AT_accessibility, DW_FORM_data1, 1);
80   ScopeValueDie.addAttribute(DW_AT_inline, DW_FORM_data4, 2);
81   ScopeValueDie.addAttribute(DW_AT_virtuality, DW_FORM_data4, 3);
82   ScopeValueDie.addAttribute(DW_AT_call_file, DW_FORM_data4, 4);
83   ScopeValueDie.addAttribute(DW_AT_call_line, DW_FORM_data4, 5);
84   ScopeValueDie.addAttribute(DW_AT_decl_file, DW_FORM_data4, 6);
85   ScopeValueDie.addAttribute(DW_AT_decl_line, DW_FORM_data4, 7);
86   ScopeValueDie.addAttribute(DW_AT_GNU_discriminator, DW_FORM_data4, 8);
87 
88   dwarfgen::DIE ScopeNoValueDie = CUDie.addChild(DW_TAG_inlined_subroutine);
89   ScopeNoValueDie.addAttribute(DW_AT_accessibility, DW_FORM_sdata, 1);
90   ScopeNoValueDie.addAttribute(DW_AT_inline, DW_FORM_sdata, 2);
91   ScopeNoValueDie.addAttribute(DW_AT_virtuality, DW_FORM_sdata, 3);
92   ScopeNoValueDie.addAttribute(DW_AT_call_file, DW_FORM_sdata, 4);
93   ScopeNoValueDie.addAttribute(DW_AT_call_line, DW_FORM_sdata, 5);
94   ScopeNoValueDie.addAttribute(DW_AT_decl_file, DW_FORM_sdata, 6);
95   ScopeNoValueDie.addAttribute(DW_AT_decl_line, DW_FORM_sdata, 7);
96   ScopeNoValueDie.addAttribute(DW_AT_GNU_discriminator, DW_FORM_sdata, 8);
97 
98   dwarfgen::DIE ScopeImplicitDie = CUDie.addChild(DW_TAG_inlined_subroutine);
99   ScopeImplicitDie.addAttribute(DW_AT_accessibility, DW_FORM_implicit_const, 1);
100   ScopeImplicitDie.addAttribute(DW_AT_inline, DW_FORM_implicit_const, 2);
101   ScopeImplicitDie.addAttribute(DW_AT_virtuality, DW_FORM_implicit_const, 3);
102   ScopeImplicitDie.addAttribute(DW_AT_call_file, DW_FORM_implicit_const, 4);
103   ScopeImplicitDie.addAttribute(DW_AT_call_line, DW_FORM_implicit_const, 5);
104   ScopeImplicitDie.addAttribute(DW_AT_decl_file, DW_FORM_implicit_const, 6);
105   ScopeImplicitDie.addAttribute(DW_AT_decl_line, DW_FORM_implicit_const, 7);
106   ScopeImplicitDie.addAttribute(DW_AT_GNU_discriminator, DW_FORM_implicit_const,
107                                 8);
108 
109   dwarfgen::DIE SymbolValueDie = CUDie.addChild(DW_TAG_variable);
110   SymbolValueDie.addAttribute(DW_AT_bit_size, DW_FORM_data1, 1);
111 
112   dwarfgen::DIE SymbolNoValueDie = CUDie.addChild(DW_TAG_variable);
113   SymbolNoValueDie.addAttribute(DW_AT_bit_size, DW_FORM_sdata, 1);
114 
115   dwarfgen::DIE SymbolImplicitDie = CUDie.addChild(DW_TAG_variable);
116   SymbolImplicitDie.addAttribute(DW_AT_bit_size, DW_FORM_implicit_const, 1);
117 
118   dwarfgen::DIE TypeValueCountDie = CUDie.addChild(DW_TAG_subrange_type);
119   TypeValueCountDie.addAttribute(DW_AT_count, DW_FORM_data4, 1);
120 
121   dwarfgen::DIE TypeNoValueCountDie = CUDie.addChild(DW_TAG_subrange_type);
122   TypeNoValueCountDie.addAttribute(DW_AT_count, DW_FORM_sdata, 1);
123 
124   dwarfgen::DIE TypeImplicitCountDie = CUDie.addChild(DW_TAG_subrange_type);
125   TypeImplicitCountDie.addAttribute(DW_AT_count, DW_FORM_implicit_const, 1);
126 
127   dwarfgen::DIE TypeValueRangeDie = CUDie.addChild(DW_TAG_subrange_type);
128   TypeValueRangeDie.addAttribute(DW_AT_lower_bound, DW_FORM_data4, 1);
129   TypeValueRangeDie.addAttribute(DW_AT_upper_bound, DW_FORM_data4, 2);
130 
131   dwarfgen::DIE TypeNoValueRangeDie = CUDie.addChild(DW_TAG_subrange_type);
132   TypeNoValueRangeDie.addAttribute(DW_AT_lower_bound, DW_FORM_addr, 3);
133   TypeNoValueRangeDie.addAttribute(DW_AT_upper_bound, DW_FORM_addr, 4);
134 
135   dwarfgen::DIE TypeImplicitRangeDie = CUDie.addChild(DW_TAG_subrange_type);
136   TypeImplicitRangeDie.addAttribute(DW_AT_lower_bound, DW_FORM_implicit_const,
137                                     5);
138   TypeImplicitRangeDie.addAttribute(DW_AT_upper_bound, DW_FORM_implicit_const,
139                                     6);
140 
141   // Generate the DWARF.
142   StringRef FileBytes = DG->generate();
143   MemoryBufferRef FileBuffer(FileBytes, "dwarf");
144   auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
145   EXPECT_TRUE((bool)Obj);
146   std::unique_ptr<DWARFContext> DwarfContext = DWARFContext::create(**Obj);
147 
148   // Verify the number of compile units is correct.
149   uint32_t NumCUs = DwarfContext->getNumCompileUnits();
150   EXPECT_EQ(NumCUs, 1u);
151   DWARFCompileUnit *U = cast<DWARFCompileUnit>(DwarfContext->getUnitAtIndex(0));
152   auto DieDG = U->getUnitDIE(false);
153   EXPECT_TRUE(DieDG.isValid());
154 
155   // Verify the siblings correct order.
156   //   ScopeValue
157   //   ScopeNoValue
158   //   ScopeImplicit
159   auto ScopeValueDieDG = DieDG.getFirstChild();
160   EXPECT_TRUE(ScopeValueDieDG.isValid());
161   EXPECT_EQ(ScopeValueDieDG.getTag(), DW_TAG_inlined_subroutine);
162   auto ScopeNoValueDieDG = ScopeValueDieDG.getSibling();
163   EXPECT_TRUE(ScopeNoValueDieDG.isValid());
164   EXPECT_EQ(ScopeNoValueDieDG.getTag(), DW_TAG_inlined_subroutine);
165   auto ScopeImplicitDieDG = ScopeNoValueDieDG.getSibling();
166   EXPECT_TRUE(ScopeImplicitDieDG.isValid());
167   EXPECT_EQ(ScopeImplicitDieDG.getTag(), DW_TAG_inlined_subroutine);
168 
169   // Verify the siblings correct order.
170   //   SymbolValue
171   //   SymbolNoValue
172   //   SymbolImplicitValue
173   auto SymbolValueDieDG = ScopeImplicitDieDG.getSibling();
174   EXPECT_TRUE(SymbolValueDieDG.isValid());
175   EXPECT_EQ(SymbolValueDieDG.getTag(), DW_TAG_variable);
176   auto SymbolNoValueDieDG = SymbolValueDieDG.getSibling();
177   EXPECT_TRUE(SymbolNoValueDieDG.isValid());
178   EXPECT_EQ(SymbolNoValueDieDG.getTag(), DW_TAG_variable);
179   auto SymbolImplicitDieDG = SymbolNoValueDieDG.getSibling();
180   EXPECT_TRUE(SymbolImplicitDieDG.isValid());
181   EXPECT_EQ(SymbolImplicitDieDG.getTag(), DW_TAG_variable);
182 
183   // Verify the siblings correct order.
184   //   TypeValueCount
185   //   TypeNoValueCount
186   //   TypeImplicitValueCount
187   auto TypeValueCountDieDG = SymbolImplicitDieDG.getSibling();
188   EXPECT_TRUE(TypeValueCountDieDG.isValid());
189   EXPECT_EQ(TypeValueCountDieDG.getTag(), DW_TAG_subrange_type);
190   auto TypeNoValueCountDieDG = TypeValueCountDieDG.getSibling();
191   EXPECT_TRUE(TypeNoValueCountDieDG.isValid());
192   EXPECT_EQ(TypeNoValueCountDieDG.getTag(), DW_TAG_subrange_type);
193   auto TypeImplicitCountDieDG = TypeNoValueCountDieDG.getSibling();
194   EXPECT_TRUE(TypeImplicitCountDieDG.isValid());
195   EXPECT_EQ(TypeImplicitCountDieDG.getTag(), DW_TAG_subrange_type);
196 
197   // Verify the siblings correct order.
198   //   TypeValueRange
199   //   TypeNoValueRange
200   //   TypeImplicitValueRange
201   auto TypeValueRangeDieDG = TypeImplicitCountDieDG.getSibling();
202   EXPECT_TRUE(TypeValueRangeDieDG.isValid());
203   EXPECT_EQ(TypeValueRangeDieDG.getTag(), DW_TAG_subrange_type);
204   auto TypeNoValueRangeDieDG = TypeValueRangeDieDG.getSibling();
205   EXPECT_TRUE(TypeNoValueRangeDieDG.isValid());
206   EXPECT_EQ(TypeNoValueRangeDieDG.getTag(), DW_TAG_subrange_type);
207   auto TypeImplicitRangeDieDG = TypeNoValueRangeDieDG.getSibling();
208   EXPECT_TRUE(TypeImplicitRangeDieDG.isValid());
209   EXPECT_EQ(TypeImplicitRangeDieDG.getTag(), DW_TAG_subrange_type);
210 
211   // Save the generated DWARF file to disk.
212   EXPECT_TRUE(DG->saveFile(Path));
213 }
214 
215 // Check the logical elements basic properties.
216 void checkElementAttributes(LVReader *Reader) {
217   LVScopeRoot *Root = Reader->getScopesRoot();
218   ASSERT_NE(Root, nullptr);
219   LVScopeCompileUnit *CompileUnit = getFirstCompileUnit(Root);
220   ASSERT_NE(CompileUnit, nullptr);
221 
222   const LVScopes *Scopes = CompileUnit->getScopes();
223   ASSERT_NE(Scopes, nullptr);
224   ASSERT_EQ(Scopes->size(), 3u);
225 
226   // Check values.
227   LVScopes::const_iterator ScopeIter = Scopes->begin();
228   ASSERT_NE(ScopeIter, Scopes->end());
229   LVScope *Scope = static_cast<LVScope *>(*ScopeIter);
230   ASSERT_NE(Scope, nullptr);
231   EXPECT_EQ(Scope->getAccessibilityCode(), 1u); // Element
232   EXPECT_EQ(Scope->getInlineCode(), 2u);        // Element
233   EXPECT_EQ(Scope->getVirtualityCode(), 3u);    // Element
234   EXPECT_EQ(Scope->getCallFilenameIndex(), 5u); // ScopeFunctionInlined
235   EXPECT_EQ(Scope->getCallLineNumber(), 5u);    // ScopeFunctionInlined
236   EXPECT_EQ(Scope->getFilenameIndex(), 7u);     // Element
237   EXPECT_EQ(Scope->getLineNumber(), 7u);        // Element
238   EXPECT_EQ(Scope->getDiscriminator(), 8u);     // ScopeFunctionInlined
239 
240   // Check no-values.
241   ASSERT_NE(++ScopeIter, Scopes->end());
242   Scope = static_cast<LVScope *>(*ScopeIter);
243   ASSERT_NE(Scope, nullptr);
244   EXPECT_EQ(Scope->getAccessibilityCode(), 0u); // Element
245   EXPECT_EQ(Scope->getInlineCode(), 0u);        // Element
246   EXPECT_EQ(Scope->getVirtualityCode(), 0u);    // Element
247   EXPECT_EQ(Scope->getCallFilenameIndex(), 1u); // ScopeFunctionInlined
248   EXPECT_EQ(Scope->getCallLineNumber(), 0u);    // ScopeFunctionInlined
249   EXPECT_EQ(Scope->getFilenameIndex(), 1u);     // Element
250   EXPECT_EQ(Scope->getLineNumber(), 0u);        // Element
251   EXPECT_EQ(Scope->getDiscriminator(), 0u);     // ScopeFunctionInlined
252 
253   // Check implicit values.
254   ASSERT_NE(++ScopeIter, Scopes->end());
255   Scope = static_cast<LVScope *>(*ScopeIter);
256   ASSERT_NE(Scope, nullptr);
257   EXPECT_EQ(Scope->getAccessibilityCode(), 1u); // Element
258   EXPECT_EQ(Scope->getInlineCode(), 2u);        // Element
259   EXPECT_EQ(Scope->getVirtualityCode(), 3u);    // Element
260   EXPECT_EQ(Scope->getCallFilenameIndex(), 5u); // ScopeFunctionInlined
261   EXPECT_EQ(Scope->getCallLineNumber(), 5u);    // ScopeFunctionInlined
262   EXPECT_EQ(Scope->getFilenameIndex(), 7u);     // Element
263   EXPECT_EQ(Scope->getLineNumber(), 7u);        // Element
264   EXPECT_EQ(Scope->getDiscriminator(), 8u);     // ScopeFunctionInlined
265 
266   const LVSymbols *Symbols = CompileUnit->getSymbols();
267   ASSERT_NE(Symbols, nullptr);
268   ASSERT_EQ(Symbols->size(), 3u);
269 
270   LVSymbols::const_iterator SymbolIter = Symbols->begin();
271   ASSERT_NE(SymbolIter, Symbols->end());
272   LVSymbol *Symbol = static_cast<LVSymbol *>(*SymbolIter);
273   ASSERT_NE(Symbol, nullptr);
274   EXPECT_EQ(Symbol->getBitSize(), 1u); // Symbol
275 
276   ASSERT_NE(++SymbolIter, Symbols->end());
277   Symbol = static_cast<LVSymbol *>(*SymbolIter);
278   ASSERT_NE(Symbol, nullptr);
279   EXPECT_EQ(Symbol->getBitSize(), 0u); // Symbol
280 
281   ASSERT_NE(++SymbolIter, Symbols->end());
282   Symbol = static_cast<LVSymbol *>(*SymbolIter);
283   ASSERT_NE(Symbol, nullptr);
284   EXPECT_EQ(Symbol->getBitSize(), 1u); // Symbol
285 
286   const LVTypes *Types = CompileUnit->getTypes();
287   ASSERT_NE(Types, nullptr);
288   ASSERT_EQ(Types->size(), 6u);
289 
290   LVTypes::const_iterator TypeIter = Types->begin();
291   ASSERT_NE(TypeIter, Types->end());
292   LVType *Type = static_cast<LVType *>(*TypeIter);
293   ASSERT_NE(Type, nullptr);
294   EXPECT_EQ(Type->getCount(), 1u); // Type
295 
296   ASSERT_NE(++TypeIter, Types->end());
297   Type = static_cast<LVType *>(*TypeIter);
298   ASSERT_NE(Type, nullptr);
299   EXPECT_EQ(Type->getCount(), 0u); // Type
300 
301   ASSERT_NE(++TypeIter, Types->end());
302   Type = static_cast<LVType *>(*TypeIter);
303   ASSERT_NE(Type, nullptr);
304   EXPECT_EQ(Type->getCount(), 1u); // Type
305 
306   ASSERT_NE(++TypeIter, Types->end());
307   Type = static_cast<LVType *>(*TypeIter);
308   ASSERT_NE(Type, nullptr);
309   EXPECT_EQ(Type->getLowerBound(), 1u); // Type
310   EXPECT_EQ(Type->getUpperBound(), 2u); // Type
311 
312   ASSERT_NE(++TypeIter, Types->end());
313   Type = static_cast<LVType *>(*TypeIter);
314   ASSERT_NE(Type, nullptr);
315   EXPECT_EQ(Type->getLowerBound(), 0u); // Type
316   EXPECT_EQ(Type->getUpperBound(), 0u); // Type
317 
318   ASSERT_NE(++TypeIter, Types->end());
319   Type = static_cast<LVType *>(*TypeIter);
320   ASSERT_NE(Type, nullptr);
321   EXPECT_EQ(Type->getLowerBound(), 5u); // Type
322   EXPECT_EQ(Type->getUpperBound(), 6u); // Type
323 }
324 
325 TEST(LogicalViewTest, ElementAttributes) {
326   // Initialize targets and assembly printers/parsers.
327   llvm::InitializeAllTargetInfos();
328   llvm::InitializeAllTargetMCs();
329   InitializeAllDisassemblers();
330 
331   llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded);
332 
333   Triple Triple(Triple::normalize("x86_64-pc-linux-gnu"));
334   if (!isConfigurationSupported(Triple))
335     GTEST_SKIP();
336 
337   unittest::TempDir TestDirectory("dwarf-test", /*Unique=*/true);
338   llvm::SmallString<128> DirName(TestDirectory.path());
339   StringRef Filename("test.o");
340   llvm::SmallString<128> Path(TestDirectory.path(Filename));
341   generateDebugInfo(Path, Triple);
342 
343   // Reader options.
344   LVOptions ReaderOptions;
345   ReaderOptions.setPrintScopes();
346   ReaderOptions.setPrintSymbols();
347   ReaderOptions.setPrintTypes();
348   ReaderOptions.resolveDependencies();
349 
350   std::vector<std::string> Objects;
351   ScopedPrinter W(outs());
352   LVReaderHandler ReaderHandler(Objects, W, ReaderOptions);
353 
354   // Check logical elements properties.
355   std::unique_ptr<LVReader> Reader =
356       createReader(ReaderHandler, DirName, Filename);
357   ASSERT_NE(Reader, nullptr);
358 
359   checkElementAttributes(Reader.get());
360 }
361 
362 } // namespace
363