1 //===- llvm/unittest/DebugInfo/LogicalView/LocationRangesTest.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/DebugInfo/LogicalView/Core/LVLine.h"
10 #include "llvm/DebugInfo/LogicalView/Core/LVReader.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/Support/ScopedPrinter.h"
15 #include "llvm/Support/ToolOutputFile.h"
16 #include "llvm/Testing/Support/Error.h"
17
18 #include "gtest/gtest.h"
19
20 using namespace llvm;
21 using namespace llvm::logicalview;
22
23 namespace {
24
25 class ReaderTest : public LVReader {
26 protected:
27 void add(LVSymbol *Symbol, LVLine *LowerLine, LVLine *UpperLine);
28 void add(LVScope *Parent, LVElement *Element);
29 void set(LVElement *Element, StringRef Name, LVOffset Offset,
30 uint32_t LineNumber = 0, LVElement *Type = nullptr);
31 void set(LVLocation *Location, LVLine *LowerLine, LVLine *UpperLine,
32 LVAddress LowerAddress, LVAddress UpperAddress);
33
34 public:
ReaderTest(ScopedPrinter & W)35 ReaderTest(ScopedPrinter &W) : LVReader("", "", W) { setInstance(this); }
36
createScopes()37 Error createScopes() { return LVReader::createScopes(); }
38 };
39
40 // Helper function to add a logical element to a given scope.
add(LVScope * Parent,LVElement * Child)41 void ReaderTest::add(LVScope *Parent, LVElement *Child) {
42 Parent->addElement(Child);
43 EXPECT_EQ(Child->getParent(), Parent);
44 EXPECT_EQ(Child->getLevel(), Parent->getLevel() + 1);
45 }
46
47 // Helper function to set the initial values for a given logical element.
set(LVElement * Element,StringRef Name,LVOffset Offset,uint32_t LineNumber,LVElement * Type)48 void ReaderTest::set(LVElement *Element, StringRef Name, LVOffset Offset,
49 uint32_t LineNumber, LVElement *Type) {
50 Element->setName(Name);
51 Element->setOffset(Offset);
52 Element->setLineNumber(LineNumber);
53 Element->setType(Type);
54 EXPECT_EQ(Element->getName(), Name);
55 EXPECT_EQ(Element->getOffset(), Offset);
56 EXPECT_EQ(Element->getLineNumber(), LineNumber);
57 EXPECT_EQ(Element->getType(), Type);
58 }
59
60 // Helper function to set the initial values for a given logical location.
set(LVLocation * Location,LVLine * LowerLine,LVLine * UpperLine,LVAddress LowerAddress,LVAddress UpperAddress)61 void ReaderTest::set(LVLocation *Location, LVLine *LowerLine, LVLine *UpperLine,
62 LVAddress LowerAddress, LVAddress UpperAddress) {
63 Location->setLowerLine(LowerLine);
64 Location->setUpperLine(UpperLine);
65 Location->setLowerAddress(LowerAddress);
66 Location->setUpperAddress(UpperAddress);
67 EXPECT_EQ(Location->getLowerLine(), LowerLine);
68 EXPECT_EQ(Location->getUpperLine(), UpperLine);
69 EXPECT_EQ(Location->getLowerAddress(), LowerAddress);
70 EXPECT_EQ(Location->getUpperAddress(), UpperAddress);
71 }
72
73 // Helper function to add a logical location to a logical symbol.
add(LVSymbol * Symbol,LVLine * LowerLine,LVLine * UpperLine)74 void ReaderTest::add(LVSymbol *Symbol, LVLine *LowerLine, LVLine *UpperLine) {
75 dwarf::Attribute Attr = dwarf::DW_AT_location;
76
77 Symbol->addLocation(Attr, LowerLine->getAddress(), UpperLine->getAddress(),
78 /*SectionOffset=*/0, /*LocDesOffset=*/0);
79 }
80
81 class ReaderTestLocations : public ReaderTest {
82 #define CREATE(VARIABLE, CREATE_FUNCTION) \
83 VARIABLE = CREATE_FUNCTION(); \
84 EXPECT_NE(VARIABLE, nullptr);
85
86 // Types.
87 LVType *IntegerType = nullptr;
88
89 // Scopes.
90 LVScope *NestedScope = nullptr;
91 LVScopeFunction *Function = nullptr;
92
93 // Symbols.
94 LVSymbol *LocalVariable = nullptr;
95 LVSymbol *NestedVariable = nullptr;
96 LVSymbol *Parameter = nullptr;
97
98 // Lines.
99 LVLine *LineOne = nullptr;
100 LVLine *LineTwo = nullptr;
101 LVLine *LineThree = nullptr;
102 LVLine *LineFour = nullptr;
103 LVLine *LineFive = nullptr;
104 LVLine *LineSix = nullptr;
105
106 // Locations.
107 LVLocation *LocationOne = nullptr;
108 LVLocation *LocationTwo = nullptr;
109 LVLocation *LocationThree = nullptr;
110 LVLocation *LocationFour = nullptr;
111 LVLocation *LocationFive = nullptr;
112 LVLocation *LocationSix = nullptr;
113
114 public:
ReaderTestLocations(ScopedPrinter & W)115 ReaderTestLocations(ScopedPrinter &W) : ReaderTest(W) {}
116
117 void createElements();
118 void addElements();
119 void initElements();
120 };
121
122 // Create the logical elements.
createElements()123 void ReaderTestLocations::createElements() {
124 // Create scope root.
125 Error Err = createScopes();
126 ASSERT_THAT_ERROR(std::move(Err), Succeeded());
127 Root = getScopesRoot();
128 EXPECT_NE(Root, nullptr);
129
130 // Create the logical types.
131 CREATE(IntegerType, createType);
132
133 // Create the logical scopes.
134 CREATE(NestedScope, createScope);
135 CREATE(CompileUnit, createScopeCompileUnit);
136 CREATE(Function, createScopeFunction);
137
138 // Create the logical symbols.
139 CREATE(LocalVariable, createSymbol);
140 CREATE(NestedVariable, createSymbol);
141 CREATE(Parameter, createSymbol);
142
143 // Create the logical lines.
144 CREATE(LineOne, createLine);
145 CREATE(LineTwo, createLine);
146 CREATE(LineThree, createLine);
147 CREATE(LineFour, createLine);
148 CREATE(LineFive, createLine);
149 CREATE(LineSix, createLine);
150
151 // Create the logical locations.
152 CREATE(LocationOne, createLocation);
153 CREATE(LocationTwo, createLocation);
154 CREATE(LocationThree, createLocation);
155 CREATE(LocationFour, createLocation);
156 CREATE(LocationFive, createLocation);
157 CREATE(LocationSix, createLocation);
158 }
159
160 // Create the logical view adding the created logical elements.
addElements()161 void ReaderTestLocations::addElements() {
162 setCompileUnit(CompileUnit);
163
164 // Root
165 // CompileUnit
166 // IntegerType
167 // Function
168 // LocationOne
169 // LocationTwo
170 // LocationFive
171 // LocationSix
172 // Parameter
173 // LocalVariable
174 // LineOne
175 // LineTwo
176 // NestedScope
177 // LocationThree
178 // LocationFour
179 // NestedVariable
180 // LineThree
181 // LineFour
182 // LineFive
183 // LineSix
184
185 // Add elements to Root.
186 add(Root, CompileUnit);
187
188 // Add elements to CompileUnit.
189 add(CompileUnit, IntegerType);
190 add(CompileUnit, Function);
191
192 // Add elements to Function.
193 add(Function, Parameter);
194 add(Function, LocalVariable);
195 add(Function, LineOne);
196 add(Function, LineTwo);
197 add(Function, LineFive);
198 add(Function, LineSix);
199 add(Function, NestedScope);
200
201 // Add elements to NestedScope.
202 add(NestedScope, NestedVariable);
203 add(NestedScope, LineThree);
204 add(NestedScope, LineFour);
205 }
206
207 // Set initial values to logical elements.
initElements()208 void ReaderTestLocations::initElements() {
209 // Types.
210 set(IntegerType, "int", 0x1000);
211
212 // Scopes.
213 set(CompileUnit, "foo.cpp", 0x2000);
214 set(Function, "foo", 0x2010, 100, IntegerType);
215 set(NestedScope, "", 0x2020, 300);
216
217 // Symbols.
218 set(Parameter, "Param", 0x3000, 110, IntegerType);
219 set(LocalVariable, "LocalVariable", 0x3000, 120, IntegerType);
220 set(NestedVariable, "NestedVariable", 0x3010, 310, IntegerType);
221
222 // Lines.
223 set(LineOne, "", 0x5000, 100);
224 set(LineTwo, "", 0x5200, 200);
225 set(LineThree, "", 0x5400, 300);
226 set(LineFour, "", 0x5600, 400);
227 set(LineFive, "", 0x5800, 500);
228 set(LineSix, "", 0x6000, 600);
229
230 // Locations.
231 set(LocationOne, LineOne, LineOne, 0x5000, 0x5100);
232 EXPECT_STREQ(LocationOne->getIntervalInfo().c_str(),
233 " Lines 100:100 [0x0000005000:0x0000005100]");
234
235 set(LocationTwo, LineTwo, LineTwo, 0x5200, 0x5300);
236 EXPECT_STREQ(LocationTwo->getIntervalInfo().c_str(),
237 " Lines 200:200 [0x0000005200:0x0000005300]");
238
239 set(LocationThree, LineThree, LineThree, 0x5400, 0x5500);
240 EXPECT_STREQ(LocationThree->getIntervalInfo().c_str(),
241 " Lines 300:300 [0x0000005400:0x0000005500]");
242
243 set(LocationFour, LineFour, LineFour, 0x5600, 0x5700);
244 LocationFour->setIsAddressRange();
245 EXPECT_STREQ(LocationFour->getIntervalInfo().c_str(),
246 "{Range} Lines 400:400 [0x0000005600:0x0000005700]");
247
248 set(LocationFive, LineFive, LineFive, 0x5800, 0x5900);
249 LocationFive->setIsAddressRange();
250 EXPECT_STREQ(LocationFive->getIntervalInfo().c_str(),
251 "{Range} Lines 500:500 [0x0000005800:0x0000005900]");
252
253 set(LocationSix, LineSix, LineSix, 0x6000, 0x6100);
254 LocationSix->setIsAddressRange();
255 EXPECT_STREQ(LocationSix->getIntervalInfo().c_str(),
256 "{Range} Lines 600:600 [0x0000006000:0x0000006100]");
257
258 // Add ranges to Function.
259 // Function: LocationOne, LocationTwo, LocationFive, LocationSix
260 Function->addObject(LocationOne);
261 Function->addObject(LocationTwo);
262 Function->addObject(LocationFive);
263 Function->addObject(LocationSix);
264 EXPECT_EQ(Function->rangeCount(), 4u);
265
266 // Add ranges to NestedScope.
267 // NestedScope: LocationThree, LocationFour
268 NestedScope->addObject(LocationThree);
269 NestedScope->addObject(LocationFour);
270 EXPECT_EQ(NestedScope->rangeCount(), 2u);
271
272 // Get all ranges.
273 LVRange Ranges;
274 CompileUnit->getRanges(Ranges);
275 Ranges.startSearch();
276 EXPECT_EQ(Ranges.getEntry(0x4000), nullptr);
277
278 EXPECT_EQ(Ranges.getEntry(0x5060), Function);
279 EXPECT_EQ(Ranges.getEntry(0x5850), Function);
280 EXPECT_EQ(Ranges.getEntry(0x5010, 0x5090), Function);
281 EXPECT_EQ(Ranges.getEntry(0x5210, 0x5290), Function);
282 EXPECT_EQ(Ranges.getEntry(0x5810, 0x5890), Function);
283 EXPECT_EQ(Ranges.getEntry(0x6010, 0x6090), Function);
284
285 EXPECT_EQ(Ranges.getEntry(0x5400), NestedScope);
286 EXPECT_EQ(Ranges.getEntry(0x5650), NestedScope);
287 EXPECT_EQ(Ranges.getEntry(0x5410, 0x5490), NestedScope);
288 EXPECT_EQ(Ranges.getEntry(0x5610, 0x5690), NestedScope);
289
290 EXPECT_EQ(Ranges.getEntry(0x8000), nullptr);
291 Ranges.endSearch();
292
293 // Add locations to symbols.
294 // Parameter: [LineOne, LineSix]
295 // LocalVariable: [LineTwo, LineSix], [LineFour, LineFive]
296 // NestedVariable: [LineThree, LineFour]
297 add(Parameter, LineOne, LineSix);
298 add(LocalVariable, LineTwo, LineSix);
299 add(LocalVariable, LineFour, LineFive);
300 add(NestedVariable, LineThree, LineFour);
301
302 LVLocation *Location;
303 LVLocations Locations;
304 Parameter->getLocations(Locations);
305 ASSERT_EQ(Locations.size(), 1u);
306 Location = Locations[0];
307 EXPECT_EQ(Location->getLowerAddress(), LineOne->getAddress());
308 EXPECT_EQ(Location->getUpperAddress(), LineSix->getAddress());
309
310 Locations.clear();
311 LocalVariable->getLocations(Locations);
312 ASSERT_EQ(Locations.size(), 2u);
313 Location = Locations[0];
314 EXPECT_EQ(Location->getLowerAddress(), LineTwo->getAddress());
315 EXPECT_EQ(Location->getUpperAddress(), LineSix->getAddress());
316 Location = Locations[1];
317 EXPECT_EQ(Location->getLowerAddress(), LineFour->getAddress());
318 EXPECT_EQ(Location->getUpperAddress(), LineFive->getAddress());
319
320 Locations.clear();
321 NestedVariable->getLocations(Locations);
322 ASSERT_EQ(Locations.size(), 1u);
323 Location = Locations[0];
324 EXPECT_EQ(Location->getLowerAddress(), LineThree->getAddress());
325 EXPECT_EQ(Location->getUpperAddress(), LineFour->getAddress());
326 }
327
328 class ReaderTestCoverage : public ReaderTest {
329 // Types.
330 LVType *IntegerType = nullptr;
331
332 // Scopes.
333 LVScopeFunction *Function = nullptr;
334 LVScopeFunctionInlined *InlinedFunction = nullptr;
335
336 // Symbols.
337 LVSymbol *Variable = nullptr;
338 LVSymbol *Parameter = nullptr;
339
340 // Lines.
341 LVLine *LineOne = nullptr;
342 LVLine *LineTwo = nullptr;
343 LVLine *LineThree = nullptr;
344 LVLine *LineFour = nullptr;
345 LVLine *LineFive = nullptr;
346 LVLine *LineSix = nullptr;
347
348 // Locations.
349 LVLocation *LocationOne = nullptr;
350 LVLocation *LocationTwo = nullptr;
351 LVLocation *LocationFive = nullptr;
352 LVLocation *LocationSix = nullptr;
353
354 public:
ReaderTestCoverage(ScopedPrinter & W)355 ReaderTestCoverage(ScopedPrinter &W) : ReaderTest(W) {}
356
357 void createElements();
358 void addElements();
359 void initElements();
360 };
361
362 // Create the logical elements.
createElements()363 void ReaderTestCoverage::createElements() {
364 // Create scope root.
365 Error Err = createScopes();
366 ASSERT_THAT_ERROR(std::move(Err), Succeeded());
367 Root = getScopesRoot();
368 EXPECT_NE(Root, nullptr);
369
370 // Create the logical types.
371 IntegerType = createType();
372 EXPECT_NE(IntegerType, nullptr);
373
374 // Create the logical scopes.
375 CompileUnit = createScopeCompileUnit();
376 EXPECT_NE(CompileUnit, nullptr);
377 Function = createScopeFunction();
378 EXPECT_NE(Function, nullptr);
379 InlinedFunction = createScopeFunctionInlined();
380 EXPECT_NE(InlinedFunction, nullptr);
381
382 // Create the logical symbols.
383 Variable = createSymbol();
384 EXPECT_NE(Variable, nullptr);
385 Parameter = createSymbol();
386 EXPECT_NE(Parameter, nullptr);
387
388 // Create the logical lines.
389 LineOne = createLine();
390 EXPECT_NE(LineOne, nullptr);
391 LineTwo = createLine();
392 EXPECT_NE(LineTwo, nullptr);
393 LineThree = createLine();
394 EXPECT_NE(LineThree, nullptr);
395 LineFour = createLine();
396 EXPECT_NE(LineFour, nullptr);
397 LineFive = createLine();
398 EXPECT_NE(LineFive, nullptr);
399 LineSix = createLine();
400 EXPECT_NE(LineSix, nullptr);
401
402 // Create the logical locations.
403 LocationOne = createLocation();
404 EXPECT_NE(LocationOne, nullptr);
405 LocationTwo = createLocation();
406 EXPECT_NE(LocationTwo, nullptr);
407 LocationFive = createLocation();
408 EXPECT_NE(LocationFive, nullptr);
409 LocationSix = createLocation();
410 EXPECT_NE(LocationSix, nullptr);
411 }
412
413 // Create the logical view adding the created logical elements.
addElements()414 void ReaderTestCoverage::addElements() {
415 setCompileUnit(CompileUnit);
416
417 // Root
418 // CompileUnit
419 // IntegerType
420 // Function
421 // Ranges
422 // [LineOne, LineOne]
423 // [LineTwo, LineSix]
424 // [LineSix, LineSix]
425 // LineOne
426 // LineTwo
427 // InlinedFunction
428 // Ranges
429 // [LineFive, LineFive]
430 // Parameter
431 // Location
432 // [LineThree, LineThree]
433 // Variable
434 // Location
435 // [LineFour, LineFive]
436 // [LineFive, LineSix]
437 // LineThree
438 // LineFour
439 // LineFive
440 // LineSix
441
442 // Add elements to Root.
443 add(Root, CompileUnit);
444
445 // Add elements to CompileUnit.
446 add(CompileUnit, IntegerType);
447 add(CompileUnit, Function);
448
449 // Add elements to Function.
450 add(Function, InlinedFunction);
451 add(Function, LineOne);
452 add(Function, LineTwo);
453 add(Function, LineSix);
454
455 // Add elements to function InlinedFunction.
456 add(InlinedFunction, Parameter);
457 add(InlinedFunction, Variable);
458 add(InlinedFunction, LineThree);
459 add(InlinedFunction, LineFour);
460 add(InlinedFunction, LineFive);
461 }
462
463 // Set initial values to logical elements.
initElements()464 void ReaderTestCoverage::initElements() {
465 // Types.
466 set(IntegerType, "int", 0x1000);
467
468 // Scopes.
469 set(CompileUnit, "foo.cpp", 0x2000);
470 set(Function, "foo", 0x2500, 100, IntegerType);
471 set(InlinedFunction, "InlinedFunction", 0x3000, 300);
472
473 // Symbols.
474 set(Parameter, "Parameter", 0x3100, 310, IntegerType);
475 set(Variable, "Variable", 0x3200, 320, IntegerType);
476
477 // Lines.
478 set(LineOne, "", 0x5000, 100);
479 set(LineTwo, "", 0x5200, 200);
480 set(LineThree, "", 0x5400, 300);
481 set(LineFour, "", 0x5600, 400);
482 set(LineFive, "", 0x5800, 500);
483 set(LineSix, "", 0x6000, 600);
484
485 // Locations.
486 set(LocationOne, LineOne, LineOne, 0x5000, 0x5199);
487 EXPECT_STREQ(LocationOne->getIntervalInfo().c_str(),
488 " Lines 100:100 [0x0000005000:0x0000005199]");
489
490 set(LocationTwo, LineTwo, LineSix, 0x5200, 0x6100);
491 EXPECT_STREQ(LocationTwo->getIntervalInfo().c_str(),
492 " Lines 200:600 [0x0000005200:0x0000006100]");
493
494 set(LocationFive, LineFive, LineFive, 0x5800, 0x5900);
495 EXPECT_STREQ(LocationFive->getIntervalInfo().c_str(),
496 " Lines 500:500 [0x0000005800:0x0000005900]");
497
498 set(LocationSix, LineSix, LineSix, 0x6000, 0x6100);
499 EXPECT_STREQ(LocationSix->getIntervalInfo().c_str(),
500 " Lines 600:600 [0x0000006000:0x0000006100]");
501
502 // Add ranges to Function.
503 // Function: LocationOne, LocationTwo, LocationSix
504 Function->addObject(LocationOne);
505 Function->addObject(LocationTwo);
506 Function->addObject(LocationSix);
507 EXPECT_EQ(Function->rangeCount(), 3u);
508
509 // Add ranges to Inlined.
510 // Inlined: LocationFive
511 InlinedFunction->addObject(LocationFive);
512 EXPECT_EQ(InlinedFunction->rangeCount(), 1u);
513
514 // Add locations to symbols.
515 // Parameter: [LineThree, LineThree]
516 // Variable: [LineFour, LineFive], [LineFive, LineSix]
517 add(Parameter, LineThree, LineThree);
518 add(Variable, LineFour, LineFive);
519 add(Variable, LineFive, LineSix);
520
521 CompileUnit->processRangeLocationCoverage();
522
523 LVLocation *Location;
524 LVLocations Locations;
525 Parameter->getLocations(Locations);
526 ASSERT_EQ(Locations.size(), 1u);
527 Location = Locations[0];
528 EXPECT_EQ(Location->getLowerAddress(), LineThree->getAddress());
529 EXPECT_EQ(Location->getUpperAddress(), LineThree->getAddress());
530
531 Locations.clear();
532 Variable->getLocations(Locations);
533 ASSERT_EQ(Locations.size(), 2u);
534 Location = Locations[0];
535 EXPECT_EQ(Location->getLowerAddress(), LineFour->getAddress());
536 EXPECT_EQ(Location->getUpperAddress(), LineFive->getAddress());
537 Location = Locations[1];
538 EXPECT_EQ(Location->getLowerAddress(), LineFive->getAddress());
539 EXPECT_EQ(Location->getUpperAddress(), LineSix->getAddress());
540
541 // Test the changes done to 'LVScope::outermostParent' to use the
542 // ranges allocated int the current scope during the scopes traversal.
543 // These are the pre-conditions for the symbol:
544 // - Its parent must be an inlined function.
545 // - Have more than one location description.
546
547 // Before the changes: Parameter: CoveragePercentage = 100.00
548 // After the changes: Parameter: CoveragePercentage = 100.00
549 EXPECT_FLOAT_EQ(Parameter->getCoveragePercentage(), 100.00f);
550
551 // Before the changes: Variable: CoveragePercentage = 1000.00
552 // After the changes: Variable: CoveragePercentage = 56.83
553 EXPECT_FLOAT_EQ(Variable->getCoveragePercentage(), 56.83f);
554 }
555
TEST(LogicalViewTest,LocationRanges)556 TEST(LogicalViewTest, LocationRanges) {
557 ScopedPrinter W(outs());
558 ReaderTestLocations Reader(W);
559
560 // Reader options.
561 LVOptions ReaderOptions;
562 ReaderOptions.setAttributeOffset();
563 ReaderOptions.setPrintAll();
564 ReaderOptions.resolveDependencies();
565 options().setOptions(&ReaderOptions);
566
567 Reader.createElements();
568 Reader.addElements();
569 Reader.initElements();
570 }
571
TEST(LogicalViewTest,LocationCoverage)572 TEST(LogicalViewTest, LocationCoverage) {
573 ScopedPrinter W(outs());
574 ReaderTestCoverage Reader(W);
575
576 // Reader options.
577 LVOptions ReaderOptions;
578 ReaderOptions.setAttributeOffset();
579 ReaderOptions.setAttributeRange();
580 ReaderOptions.setAttributeLocation();
581 ReaderOptions.setPrintAll();
582 ReaderOptions.resolveDependencies();
583 options().setOptions(&ReaderOptions);
584
585 Reader.createElements();
586 Reader.addElements();
587 Reader.initElements();
588 }
589
590 } // namespace
591