[lldb] Fix warning: 'sprintf' is deprecated in RNBSocketTest
[llvm-project.git] / llvm / unittests / DebugInfo / LogicalView / DWARFReaderTest.cpp
bloba1bd5dee3565660607226c9c740df097588d932e
1 //===- llvm/unittest/DebugInfo/LogicalView/DWARFReaderTest.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/DebugInfo/LogicalView/Core/LVCompare.h"
10 #include "llvm/DebugInfo/LogicalView/Core/LVLine.h"
11 #include "llvm/DebugInfo/LogicalView/Core/LVScope.h"
12 #include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h"
13 #include "llvm/DebugInfo/LogicalView/Core/LVType.h"
14 #include "llvm/DebugInfo/LogicalView/LVReaderHandler.h"
15 #include "llvm/MC/TargetRegistry.h"
16 #include "llvm/Support/COM.h"
17 #include "llvm/Support/InitLLVM.h"
18 #include "llvm/Support/ScopedPrinter.h"
19 #include "llvm/Support/TargetSelect.h"
20 #include "llvm/Support/ToolOutputFile.h"
21 #include "llvm/Testing/Support/Error.h"
23 #include "gtest/gtest.h"
25 using namespace llvm;
26 using namespace llvm::logicalview;
28 extern const char *TestMainArgv0;
30 namespace {
32 const char *DwarfClang = "test-dwarf-clang.o";
33 const char *DwarfGcc = "test-dwarf-gcc.o";
35 // Helper function to get the first compile unit.
36 LVScopeCompileUnit *getFirstCompileUnit(LVScopeRoot *Root) {
37 EXPECT_NE(Root, nullptr);
38 const LVScopes *CompileUnits = Root->getScopes();
39 EXPECT_NE(CompileUnits, nullptr);
40 EXPECT_EQ(CompileUnits->size(), 1u);
42 LVScopes::const_iterator Iter = CompileUnits->begin();
43 EXPECT_NE(Iter, nullptr);
44 LVScopeCompileUnit *CompileUnit = static_cast<LVScopeCompileUnit *>(*Iter);
45 EXPECT_NE(CompileUnit, nullptr);
46 return CompileUnit;
49 // Helper function to create a reader.
50 std::unique_ptr<LVReader> createReader(LVReaderHandler &ReaderHandler,
51 SmallString<128> &InputsDir,
52 StringRef Filename) {
53 SmallString<128> ObjectName(InputsDir);
54 llvm::sys::path::append(ObjectName, Filename);
56 Expected<std::unique_ptr<LVReader>> ReaderOrErr =
57 ReaderHandler.createReader(std::string(ObjectName));
58 EXPECT_THAT_EXPECTED(ReaderOrErr, Succeeded());
59 std::unique_ptr<LVReader> Reader = std::move(*ReaderOrErr);
60 EXPECT_NE(Reader, nullptr);
61 return Reader;
64 // Check the logical elements basic properties.
65 void checkElementProperties(LVReader *Reader) {
66 LVScopeRoot *Root = Reader->getScopesRoot();
67 LVScopeCompileUnit *CompileUnit = getFirstCompileUnit(Root);
69 EXPECT_EQ(Root->getFileFormatName(), "elf64-x86-64");
70 EXPECT_EQ(Root->getName(), DwarfClang);
72 EXPECT_EQ(CompileUnit->getBaseAddress(), 0u);
73 EXPECT_TRUE(CompileUnit->getProducer().starts_with("clang"));
74 EXPECT_EQ(CompileUnit->getName(), "test.cpp");
76 EXPECT_EQ(CompileUnit->lineCount(), 0u);
77 EXPECT_EQ(CompileUnit->scopeCount(), 1u);
78 EXPECT_EQ(CompileUnit->symbolCount(), 0u);
79 EXPECT_EQ(CompileUnit->typeCount(), 7u);
80 EXPECT_EQ(CompileUnit->rangeCount(), 1u);
82 const LVLocations *Ranges = CompileUnit->getRanges();
83 ASSERT_NE(Ranges, nullptr);
84 ASSERT_EQ(Ranges->size(), 1u);
85 LVLocations::const_iterator IterLocation = Ranges->begin();
86 LVLocation *Location = (*IterLocation);
87 EXPECT_STREQ(Location->getIntervalInfo().c_str(),
88 "{Range} Lines 2:9 [0x0000000000:0x000000003a]");
90 LVRange RangeList;
91 CompileUnit->getRanges(RangeList);
93 const LVRangeEntries &RangeEntries = RangeList.getEntries();
94 ASSERT_EQ(RangeEntries.size(), 2u);
95 LVRangeEntries::const_iterator IterRanges = RangeEntries.cbegin();
96 LVRangeEntry RangeEntry = *IterRanges;
97 EXPECT_EQ(RangeEntry.lower(), 0u);
98 EXPECT_EQ(RangeEntry.upper(), 0x3au);
99 EXPECT_EQ(RangeEntry.scope()->getLineNumber(), 0u);
100 EXPECT_EQ(RangeEntry.scope()->getName(), "test.cpp");
101 EXPECT_EQ(RangeEntry.scope()->getOffset(), 0x0bu);
103 ++IterRanges;
104 RangeEntry = *IterRanges;
105 EXPECT_EQ(RangeEntry.lower(), 0x1cu);
106 EXPECT_EQ(RangeEntry.upper(), 0x2fu);
107 EXPECT_EQ(RangeEntry.scope()->getLineNumber(), 0u);
108 EXPECT_EQ(RangeEntry.scope()->getName(), "foo::?");
109 EXPECT_EQ(RangeEntry.scope()->getOffset(), 0x71u);
111 const LVPublicNames &PublicNames = CompileUnit->getPublicNames();
112 ASSERT_EQ(PublicNames.size(), 1u);
113 LVPublicNames::const_iterator IterNames = PublicNames.cbegin();
114 LVScope *Function = (*IterNames).first;
115 EXPECT_EQ(Function->getName(), "foo");
116 EXPECT_EQ(Function->getLineNumber(), 2u);
117 LVNameInfo NameInfo = (*IterNames).second;
118 EXPECT_EQ(NameInfo.first, 0u);
119 EXPECT_EQ(NameInfo.second, 0x3au);
121 // Lines (debug and assembler) for 'foo'.
122 const LVLines *Lines = Function->getLines();
123 ASSERT_NE(Lines, nullptr);
124 ASSERT_EQ(Lines->size(), 0x12u);
127 // Check the logical elements selection.
128 void checkElementSelection(LVReader *Reader) {
129 LVScopeRoot *Root = Reader->getScopesRoot();
130 LVScopeCompileUnit *CompileUnit = getFirstCompileUnit(Root);
132 // Get the matched elements.
133 LVElements MatchedElements = CompileUnit->getMatchedElements();
134 std::map<LVOffset, LVElement *> MapElements;
135 for (LVElement *Element : MatchedElements)
136 MapElements[Element->getOffset()] = Element;
137 ASSERT_EQ(MapElements.size(), 0xeu);
139 LVElement *Element = MapElements[0x000000004b]; // 'foo'
140 ASSERT_NE(Element, nullptr);
141 EXPECT_NE(Element->getName().find("foo"), StringRef::npos);
142 EXPECT_EQ(Element->getIsScope(), 1);
144 Element = MapElements[0x00000000c0]; // 'CONSTANT'
145 ASSERT_NE(Element, nullptr);
146 EXPECT_NE(Element->getName().find("CONSTANT"), StringRef::npos);
147 EXPECT_EQ(Element->getIsSymbol(), 1);
149 Element = MapElements[0x000000002d]; // 'INTPTR'
150 ASSERT_NE(Element, nullptr);
151 EXPECT_NE(Element->getName().find("INTPTR"), StringRef::npos);
152 EXPECT_EQ(Element->getIsType(), 1);
154 Element = MapElements[0x00000000af]; // 'INTEGER'
155 ASSERT_NE(Element, nullptr);
156 EXPECT_NE(Element->getName().find("INTEGER"), StringRef::npos);
157 EXPECT_EQ(Element->getIsType(), 1);
159 Element = MapElements[0x000000000f]; // 'movl %edx, %eax'
160 ASSERT_NE(Element, nullptr);
161 EXPECT_NE(Element->getName().find("movl"), StringRef::npos);
162 EXPECT_EQ(Element->getIsLine(), 1);
164 // Get the parents for the matched elements.
165 LVScopes MatchedScopes = CompileUnit->getMatchedScopes();
166 std::set<LVOffset> SetScopes;
167 for (LVScope *Scope : MatchedScopes)
168 SetScopes.insert(Scope->getOffset());
169 std::set<LVOffset>::iterator Iter;
170 ASSERT_EQ(SetScopes.size(), 3u);
172 Iter = SetScopes.find(0x000000000b); // CompileUnit <- 'foo'
173 EXPECT_NE(Iter, SetScopes.end());
174 Iter = SetScopes.find(0x000000009e); // Function <- 'movl %edx, %eax'
175 EXPECT_NE(Iter, SetScopes.end());
176 Iter = SetScopes.find(0x000000009e); // LexicalScope <- 'INTEGER'
177 EXPECT_NE(Iter, SetScopes.end());
180 // Check the logical elements comparison.
181 void checkElementComparison(LVReader *Reference, LVReader *Target) {
182 LVCompare Compare(nulls());
183 Error Err = Compare.execute(Reference, Target);
184 ASSERT_THAT_ERROR(std::move(Err), Succeeded());
186 // Get comparison table.
187 LVPassTable PassTable = Compare.getPassTable();
188 ASSERT_EQ(PassTable.size(), 5u);
190 LVReader *Reader;
191 LVElement *Element;
192 LVComparePass Pass;
194 // Reference: Missing Variable 'CONSTANT'
195 std::tie(Reader, Element, Pass) = PassTable[0];
196 ASSERT_NE(Reader, nullptr);
197 ASSERT_NE(Element, nullptr);
198 EXPECT_EQ(Reader, Reference);
199 EXPECT_EQ(Element->getLevel(), 4u);
200 EXPECT_EQ(Element->getLineNumber(), 5u);
201 EXPECT_EQ(Element->getName(), "CONSTANT");
202 EXPECT_EQ(Pass, LVComparePass::Missing);
204 // Reference: Missing TypeDefinition 'INTEGER'
205 std::tie(Reader, Element, Pass) = PassTable[1];
206 ASSERT_NE(Reader, nullptr);
207 ASSERT_NE(Element, nullptr);
208 EXPECT_EQ(Reader, Reference);
209 EXPECT_EQ(Element->getLevel(), 3u);
210 EXPECT_EQ(Element->getLineNumber(), 4u);
211 EXPECT_EQ(Element->getName(), "INTEGER");
212 EXPECT_EQ(Pass, LVComparePass::Missing);
214 // Reference: Missing DebugLine
215 std::tie(Reader, Element, Pass) = PassTable[2];
216 ASSERT_NE(Reader, nullptr);
217 ASSERT_NE(Element, nullptr);
218 EXPECT_EQ(Reader, Reference);
219 EXPECT_EQ(Element->getLevel(), 3u);
220 EXPECT_EQ(Element->getLineNumber(), 8u);
221 EXPECT_EQ(Element->getName(), "");
222 EXPECT_EQ(Pass, LVComparePass::Missing);
224 // Target: Added Variable 'CONSTANT'
225 std::tie(Reader, Element, Pass) = PassTable[3];
226 ASSERT_NE(Reader, nullptr);
227 ASSERT_NE(Element, nullptr);
228 EXPECT_EQ(Reader, Target);
229 EXPECT_EQ(Element->getLevel(), 4u);
230 EXPECT_EQ(Element->getLineNumber(), 5u);
231 EXPECT_EQ(Element->getName(), "CONSTANT");
232 EXPECT_EQ(Pass, LVComparePass::Added);
234 // Target: Added TypeDefinition 'INTEGER'
235 std::tie(Reader, Element, Pass) = PassTable[4];
236 ASSERT_NE(Reader, nullptr);
237 ASSERT_NE(Element, nullptr);
238 EXPECT_EQ(Reader, Target);
239 EXPECT_EQ(Element->getLevel(), 4u);
240 EXPECT_EQ(Element->getLineNumber(), 4u);
241 EXPECT_EQ(Element->getName(), "INTEGER");
242 EXPECT_EQ(Pass, LVComparePass::Added);
245 // Logical elements properties.
246 void elementProperties(SmallString<128> &InputsDir) {
247 // Reader options.
248 LVOptions ReaderOptions;
249 ReaderOptions.setAttributeOffset();
250 ReaderOptions.setAttributeFormat();
251 ReaderOptions.setAttributeFilename();
252 ReaderOptions.setAttributeProducer();
253 ReaderOptions.setAttributePublics();
254 ReaderOptions.setAttributeRange();
255 ReaderOptions.setAttributeLocation();
256 ReaderOptions.setPrintAll();
257 ReaderOptions.resolveDependencies();
259 std::vector<std::string> Objects;
260 ScopedPrinter W(outs());
261 LVReaderHandler ReaderHandler(Objects, W, ReaderOptions);
263 // Check logical elements properties.
264 std::unique_ptr<LVReader> Reader =
265 createReader(ReaderHandler, InputsDir, DwarfClang);
266 checkElementProperties(Reader.get());
269 // Logical elements selection.
270 void elementSelection(SmallString<128> &InputsDir) {
271 // Reader options.
272 LVOptions ReaderOptions;
273 ReaderOptions.setAttributeOffset();
274 ReaderOptions.setPrintAll();
276 ReaderOptions.setSelectIgnoreCase();
277 ReaderOptions.setSelectUseRegex();
279 ReaderOptions.setReportList(); // Matched elements.
280 ReaderOptions.setReportView(); // Parents for matched elements.
282 // Add patterns.
283 ReaderOptions.Select.Generic.insert("foo");
284 ReaderOptions.Select.Generic.insert("movl[ \t]?%");
285 ReaderOptions.Select.Generic.insert("INT[a-z]*");
286 ReaderOptions.Select.Generic.insert("CONSTANT");
288 ReaderOptions.resolveDependencies();
290 std::vector<std::string> Objects;
291 ScopedPrinter W(outs());
292 LVReaderHandler ReaderHandler(Objects, W, ReaderOptions);
294 // Check logical elements selection.
295 std::unique_ptr<LVReader> Reader =
296 createReader(ReaderHandler, InputsDir, DwarfGcc);
297 checkElementSelection(Reader.get());
300 // Compare logical elements.
301 void compareElements(SmallString<128> &InputsDir) {
302 // Reader options.
303 LVOptions ReaderOptions;
304 ReaderOptions.setAttributeOffset();
305 ReaderOptions.setPrintLines();
306 ReaderOptions.setPrintSymbols();
307 ReaderOptions.setPrintTypes();
308 ReaderOptions.setCompareLines();
309 ReaderOptions.setCompareSymbols();
310 ReaderOptions.setCompareTypes();
312 ReaderOptions.resolveDependencies();
314 std::vector<std::string> Objects;
315 ScopedPrinter W(outs());
316 LVReaderHandler ReaderHandler(Objects, W, ReaderOptions);
318 // Check logical comparison.
319 std::unique_ptr<LVReader> Reference =
320 createReader(ReaderHandler, InputsDir, DwarfClang);
321 std::unique_ptr<LVReader> Target =
322 createReader(ReaderHandler, InputsDir, DwarfGcc);
323 checkElementComparison(Reference.get(), Target.get());
326 TEST(LogicalViewTest, DWARFReader) {
327 // Initialize targets and assembly printers/parsers.
328 llvm::InitializeAllTargetInfos();
329 llvm::InitializeAllTargetMCs();
330 InitializeAllDisassemblers();
332 llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded);
334 // This test requires a x86-registered-target.
335 Triple TT;
336 TT.setArch(Triple::x86_64);
337 TT.setVendor(Triple::UnknownVendor);
338 TT.setOS(Triple::UnknownOS);
340 std::string TargetLookupError;
341 if (!TargetRegistry::lookupTarget(std::string(TT.str()), TargetLookupError))
342 GTEST_SKIP();
344 SmallString<128> InputsDir = unittest::getInputFileDirectory(TestMainArgv0);
346 // Logical elements general properties and selection.
347 elementProperties(InputsDir);
348 elementSelection(InputsDir);
350 // Compare logical elements.
351 compareElements(InputsDir);
354 } // namespace