1 //===- llvm/unittest/DebugInfo/GSYMTest.cpp -------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/ADT/DenseMap.h"
11 #include "llvm/ADT/SmallString.h"
12 #include "llvm/DebugInfo/GSYM/FileEntry.h"
13 #include "llvm/DebugInfo/GSYM/FileWriter.h"
14 #include "llvm/DebugInfo/GSYM/FunctionInfo.h"
15 #include "llvm/DebugInfo/GSYM/InlineInfo.h"
16 #include "llvm/DebugInfo/GSYM/Range.h"
17 #include "llvm/DebugInfo/GSYM/StringTable.h"
18 #include "llvm/Support/DataExtractor.h"
19 #include "llvm/Support/Endian.h"
21 #include "gtest/gtest.h"
27 TEST(GSYMTest
, TestFileEntry
) {
28 // Make sure default constructed GSYM FileEntry has zeroes in the
29 // directory and basename string table indexes.
32 EXPECT_EQ(empty1
.Dir
, 0u);
33 EXPECT_EQ(empty1
.Base
, 0u);
34 // Verify equality operator works
38 EXPECT_EQ(empty1
, empty2
);
41 EXPECT_NE(a1
, empty1
);
42 // Test we can use llvm::gsym::FileEntry in llvm::DenseMap.
43 DenseMap
<FileEntry
, uint32_t> EntryToIndex
;
44 constexpr uint32_t Index1
= 1;
45 constexpr uint32_t Index2
= 1;
46 auto R
= EntryToIndex
.insert(std::make_pair(a1
, Index1
));
47 EXPECT_TRUE(R
.second
);
48 EXPECT_EQ(R
.first
->second
, Index1
);
49 R
= EntryToIndex
.insert(std::make_pair(a1
, Index1
));
50 EXPECT_FALSE(R
.second
);
51 EXPECT_EQ(R
.first
->second
, Index1
);
52 R
= EntryToIndex
.insert(std::make_pair(b
, Index2
));
53 EXPECT_TRUE(R
.second
);
54 EXPECT_EQ(R
.first
->second
, Index2
);
55 R
= EntryToIndex
.insert(std::make_pair(a1
, Index2
));
56 EXPECT_FALSE(R
.second
);
57 EXPECT_EQ(R
.first
->second
, Index2
);
60 TEST(GSYMTest
, TestFunctionInfo
) {
61 // Test GSYM FunctionInfo structs and functionality.
63 EXPECT_FALSE(invalid
.isValid());
64 EXPECT_FALSE(invalid
.hasRichInfo());
65 const uint64_t StartAddr
= 0x1000;
66 const uint64_t EndAddr
= 0x1100;
67 const uint64_t Size
= EndAddr
- StartAddr
;
68 const uint32_t NameOffset
= 30;
69 FunctionInfo
FI(StartAddr
, Size
, NameOffset
);
70 EXPECT_TRUE(FI
.isValid());
71 EXPECT_FALSE(FI
.hasRichInfo());
72 EXPECT_EQ(FI
.startAddress(), StartAddr
);
73 EXPECT_EQ(FI
.endAddress(), EndAddr
);
74 EXPECT_EQ(FI
.size(), Size
);
75 const uint32_t FileIdx
= 1;
76 const uint32_t Line
= 12;
77 FI
.Lines
.push_back(LineEntry(StartAddr
, FileIdx
, Line
));
78 EXPECT_TRUE(FI
.hasRichInfo());
80 EXPECT_FALSE(FI
.isValid());
81 EXPECT_FALSE(FI
.hasRichInfo());
83 FunctionInfo
A1(0x1000, 0x100, NameOffset
);
84 FunctionInfo
A2(0x1000, 0x100, NameOffset
);
88 // Make sure things are not equal if they only differ by start address.
90 B
.setStartAddress(0x2000);
92 // Make sure things are not equal if they only differ by size.
96 // Make sure things are not equal if they only differ by name.
101 // Check less than where address differs.
103 B
.setStartAddress(A2
.startAddress() + 0x1000);
106 // We use the < operator to take a variety of different FunctionInfo
107 // structs from a variety of sources: symtab, debug info, runtime info
108 // and we sort them and want the sorting to allow us to quickly get the
109 // best version of a function info.
110 FunctionInfo
FISymtab(StartAddr
, Size
, NameOffset
);
111 FunctionInfo
FIWithLines(StartAddr
, Size
, NameOffset
);
112 FIWithLines
.Lines
.push_back(LineEntry(StartAddr
, FileIdx
, Line
));
113 // Test that a FunctionInfo with just a name and size is less than one
114 // that has name, size and any number of line table entries
115 EXPECT_LT(FISymtab
, FIWithLines
);
117 FunctionInfo FIWithLinesAndInline
= FIWithLines
;
118 FIWithLinesAndInline
.Inline
.Ranges
.insert(
119 AddressRange(StartAddr
, StartAddr
+ 0x10));
120 // Test that a FunctionInfo with name, size, and line entries is less than
121 // the same one with valid inline info
122 EXPECT_LT(FIWithLines
, FIWithLinesAndInline
);
124 // Test if we have an entry with lines and one with more lines for the same
125 // range, the ones with more lines is greater than the one with less.
126 FunctionInfo FIWithMoreLines
= FIWithLines
;
127 FIWithMoreLines
.Lines
.push_back(LineEntry(StartAddr
, FileIdx
, Line
+ 5));
128 EXPECT_LT(FIWithLines
, FIWithMoreLines
);
130 // Test that if we have the same number of lines we compare the line entries
131 // in the FunctionInfo.Lines vector.
132 FunctionInfo FIWithLinesWithHigherAddress
= FIWithLines
;
133 FIWithLinesWithHigherAddress
.Lines
[0].Addr
+= 0x10;
134 EXPECT_LT(FIWithLines
, FIWithLinesWithHigherAddress
);
137 void checkError(ArrayRef
<std::string
> ExpectedMsgs
, Error Err
) {
138 ASSERT_TRUE(Err
.operator bool());
141 handleErrors(std::move(Err
), [&](const ErrorInfoBase
&Actual
) {
142 ASSERT_LT(WhichMsg
, ExpectedMsgs
.size());
143 // Use .str(), because googletest doesn't visualise a StringRef
145 EXPECT_EQ(Actual
.message(), ExpectedMsgs
[WhichMsg
++]);
147 EXPECT_EQ(WhichMsg
, ExpectedMsgs
.size());
148 EXPECT_FALSE(Remaining
);
151 void checkError(std::string ExpectedMsg
, Error Err
) {
152 checkError(ArrayRef
<std::string
>{ExpectedMsg
}, std::move(Err
));
155 static void TestInlineInfoEncodeDecode(llvm::support::endianness ByteOrder
,
156 const InlineInfo
&Inline
) {
157 // Test encoding and decoding InlineInfo objects
158 SmallString
<512> Str
;
159 raw_svector_ostream
OutStrm(Str
);
160 FileWriter
FW(OutStrm
, ByteOrder
);
161 const uint64_t BaseAddr
= Inline
.Ranges
[0].Start
;
162 llvm::Error Err
= Inline
.encode(FW
, BaseAddr
);
164 std::string
Bytes(OutStrm
.str());
165 uint8_t AddressSize
= 4;
166 DataExtractor
Data(Bytes
, ByteOrder
== llvm::support::little
, AddressSize
);
167 llvm::Expected
<InlineInfo
> Decoded
= InlineInfo::decode(Data
, BaseAddr
);
168 // Make sure decoding succeeded.
169 ASSERT_TRUE((bool)Decoded
);
170 // Make sure decoded object is the same as the one we encoded.
171 EXPECT_EQ(Inline
, Decoded
.get());
174 static void TestInlineInfoDecodeError(llvm::support::endianness ByteOrder
,
176 const uint64_t BaseAddr
,
177 std::string ExpectedErrorMsg
) {
178 uint8_t AddressSize
= 4;
179 DataExtractor
Data(Bytes
, ByteOrder
== llvm::support::little
, AddressSize
);
180 llvm::Expected
<InlineInfo
> Decoded
= InlineInfo::decode(Data
, BaseAddr
);
181 // Make sure decoding fails.
182 ASSERT_FALSE((bool)Decoded
);
183 // Make sure decoded object is the same as the one we encoded.
184 checkError(ExpectedErrorMsg
, Decoded
.takeError());
187 static void TestInlineInfoEncodeError(llvm::support::endianness ByteOrder
,
188 const InlineInfo
&Inline
,
189 std::string ExpectedErrorMsg
) {
190 SmallString
<512> Str
;
191 raw_svector_ostream
OutStrm(Str
);
192 FileWriter
FW(OutStrm
, ByteOrder
);
193 const uint64_t BaseAddr
= Inline
.Ranges
.empty() ? 0 : Inline
.Ranges
[0].Start
;
194 llvm::Error Err
= Inline
.encode(FW
, BaseAddr
);
195 checkError(ExpectedErrorMsg
, std::move(Err
));
198 TEST(GSYMTest
, TestInlineInfo
) {
199 // Test InlineInfo structs.
201 EXPECT_FALSE(II
.isValid());
202 II
.Ranges
.insert(AddressRange(0x1000, 0x2000));
203 // Make sure InlineInfo in valid with just an address range since
204 // top level InlineInfo objects have ranges with no name, call file
206 EXPECT_TRUE(II
.isValid());
207 // Make sure InlineInfo isn't after being cleared.
209 EXPECT_FALSE(II
.isValid());
211 // Create an InlineInfo that contains the following data. The
212 // indentation of the address range indicates the parent child
213 // relationships of the InlineInfo objects:
215 // Variable Range and values
216 // =========== ====================================================
217 // Root [0x100-0x200) (no name, file, or line)
218 // Inline1 [0x150-0x160) Name = 1, File = 1, Line = 11
219 // Inline1Sub1 [0x152-0x155) Name = 2, File = 2, Line = 22
220 // Inline1Sub2 [0x157-0x158) Name = 3, File = 3, Line = 33
222 Root
.Ranges
.insert(AddressRange(0x100, 0x200));
224 Inline1
.Ranges
.insert(AddressRange(0x150, 0x160));
226 Inline1
.CallFile
= 1;
227 Inline1
.CallLine
= 11;
228 InlineInfo Inline1Sub1
;
229 Inline1Sub1
.Ranges
.insert(AddressRange(0x152, 0x155));
230 Inline1Sub1
.Name
= 2;
231 Inline1Sub1
.CallFile
= 2;
232 Inline1Sub1
.CallLine
= 22;
233 InlineInfo Inline1Sub2
;
234 Inline1Sub2
.Ranges
.insert(AddressRange(0x157, 0x158));
235 Inline1Sub2
.Name
= 3;
236 Inline1Sub2
.CallFile
= 3;
237 Inline1Sub2
.CallLine
= 33;
238 Inline1
.Children
.push_back(Inline1Sub1
);
239 Inline1
.Children
.push_back(Inline1Sub2
);
240 Root
.Children
.push_back(Inline1
);
242 // Make sure an address that is out of range won't match
243 EXPECT_FALSE(Root
.getInlineStack(0x50));
245 // Verify that we get no inline stacks for addresses out of [0x100-0x200)
246 EXPECT_FALSE(Root
.getInlineStack(Root
.Ranges
[0].Start
- 1));
247 EXPECT_FALSE(Root
.getInlineStack(Root
.Ranges
[0].End
));
249 // Verify we get no inline stack entries for addresses that are in
250 // [0x100-0x200) but not in [0x150-0x160)
251 EXPECT_FALSE(Root
.getInlineStack(Inline1
.Ranges
[0].Start
- 1));
252 EXPECT_FALSE(Root
.getInlineStack(Inline1
.Ranges
[0].End
));
254 // Verify we get one inline stack entry for addresses that are in
255 // [[0x150-0x160)) but not in [0x152-0x155) or [0x157-0x158)
256 auto InlineInfos
= Root
.getInlineStack(Inline1
.Ranges
[0].Start
);
257 ASSERT_TRUE(InlineInfos
);
258 ASSERT_EQ(InlineInfos
->size(), 1u);
259 ASSERT_EQ(*InlineInfos
->at(0), Inline1
);
260 InlineInfos
= Root
.getInlineStack(Inline1
.Ranges
[0].End
- 1);
261 EXPECT_TRUE(InlineInfos
);
262 ASSERT_EQ(InlineInfos
->size(), 1u);
263 ASSERT_EQ(*InlineInfos
->at(0), Inline1
);
265 // Verify we get two inline stack entries for addresses that are in
267 InlineInfos
= Root
.getInlineStack(Inline1Sub1
.Ranges
[0].Start
);
268 EXPECT_TRUE(InlineInfos
);
269 ASSERT_EQ(InlineInfos
->size(), 2u);
270 ASSERT_EQ(*InlineInfos
->at(0), Inline1Sub1
);
271 ASSERT_EQ(*InlineInfos
->at(1), Inline1
);
272 InlineInfos
= Root
.getInlineStack(Inline1Sub1
.Ranges
[0].End
- 1);
273 EXPECT_TRUE(InlineInfos
);
274 ASSERT_EQ(InlineInfos
->size(), 2u);
275 ASSERT_EQ(*InlineInfos
->at(0), Inline1Sub1
);
276 ASSERT_EQ(*InlineInfos
->at(1), Inline1
);
278 // Verify we get two inline stack entries for addresses that are in
280 InlineInfos
= Root
.getInlineStack(Inline1Sub2
.Ranges
[0].Start
);
281 EXPECT_TRUE(InlineInfos
);
282 ASSERT_EQ(InlineInfos
->size(), 2u);
283 ASSERT_EQ(*InlineInfos
->at(0), Inline1Sub2
);
284 ASSERT_EQ(*InlineInfos
->at(1), Inline1
);
285 InlineInfos
= Root
.getInlineStack(Inline1Sub2
.Ranges
[0].End
- 1);
286 EXPECT_TRUE(InlineInfos
);
287 ASSERT_EQ(InlineInfos
->size(), 2u);
288 ASSERT_EQ(*InlineInfos
->at(0), Inline1Sub2
);
289 ASSERT_EQ(*InlineInfos
->at(1), Inline1
);
291 // Test encoding and decoding InlineInfo objects
292 TestInlineInfoEncodeDecode(llvm::support::little
, Root
);
293 TestInlineInfoEncodeDecode(llvm::support::big
, Root
);
296 TEST(GSYMTest
, TestInlineInfoEncodeErrors
) {
297 // Test InlineInfo encoding errors.
299 // Test that we get an error when trying to encode an InlineInfo object
300 // that has no ranges.
302 std::string
EmptyErr("attempted to encode invalid InlineInfo object");
303 TestInlineInfoEncodeError(llvm::support::little
, Empty
, EmptyErr
);
304 TestInlineInfoEncodeError(llvm::support::big
, Empty
, EmptyErr
);
306 // Verify that we get an error trying to encode an InlineInfo object that has
307 // a child InlineInfo that has no ranges.
308 InlineInfo ContainsEmpty
;
309 ContainsEmpty
.Ranges
.insert({0x100,200});
310 ContainsEmpty
.Children
.push_back(Empty
);
311 TestInlineInfoEncodeError(llvm::support::little
, ContainsEmpty
, EmptyErr
);
312 TestInlineInfoEncodeError(llvm::support::big
, ContainsEmpty
, EmptyErr
);
314 // Verify that we get an error trying to encode an InlineInfo object that has
315 // a child whose address range is not contained in the parent address range.
316 InlineInfo ChildNotContained
;
317 std::string
ChildNotContainedErr("child range not contained in parent");
318 ChildNotContained
.Ranges
.insert({0x100,200});
319 InlineInfo ChildNotContainedChild
;
320 ChildNotContainedChild
.Ranges
.insert({0x200,300});
321 ChildNotContained
.Children
.push_back(ChildNotContainedChild
);
322 TestInlineInfoEncodeError(llvm::support::little
, ChildNotContained
,
323 ChildNotContainedErr
);
324 TestInlineInfoEncodeError(llvm::support::big
, ChildNotContained
,
325 ChildNotContainedErr
);
329 TEST(GSYMTest
, TestInlineInfoDecodeErrors
) {
330 // Test decoding InlineInfo objects that ensure we report an appropriate
332 const llvm::support::endianness ByteOrder
= llvm::support::little
;
333 SmallString
<512> Str
;
334 raw_svector_ostream
OutStrm(Str
);
335 FileWriter
FW(OutStrm
, ByteOrder
);
336 const uint64_t BaseAddr
= 0x100;
337 TestInlineInfoDecodeError(ByteOrder
, OutStrm
.str(), BaseAddr
,
338 "0x00000000: missing InlineInfo address ranges data");
339 AddressRanges Ranges
;
340 Ranges
.insert({BaseAddr
, BaseAddr
+0x100});
341 Ranges
.encode(FW
, BaseAddr
);
342 TestInlineInfoDecodeError(ByteOrder
, OutStrm
.str(), BaseAddr
,
343 "0x00000004: missing InlineInfo uint8_t indicating children");
345 TestInlineInfoDecodeError(ByteOrder
, OutStrm
.str(), BaseAddr
,
346 "0x00000005: missing InlineInfo uint32_t for name");
348 TestInlineInfoDecodeError(ByteOrder
, OutStrm
.str(), BaseAddr
,
349 "0x00000009: missing ULEB128 for InlineInfo call file");
351 TestInlineInfoDecodeError(ByteOrder
, OutStrm
.str(), BaseAddr
,
352 "0x0000000a: missing ULEB128 for InlineInfo call line");
355 TEST(GSYMTest
, TestLineEntry
) {
356 // test llvm::gsym::LineEntry structs.
357 const uint64_t ValidAddr
= 0x1000;
358 const uint64_t InvalidFileIdx
= 0;
359 const uint32_t ValidFileIdx
= 1;
360 const uint32_t ValidLine
= 5;
363 EXPECT_FALSE(Invalid
.isValid());
364 // Make sure that an entry is invalid if it has a bad file index.
365 LineEntry
BadFile(ValidAddr
, InvalidFileIdx
, ValidLine
);
366 EXPECT_FALSE(BadFile
.isValid());
368 LineEntry
E1(ValidAddr
, ValidFileIdx
, ValidLine
);
369 LineEntry
E2(ValidAddr
, ValidFileIdx
, ValidLine
);
370 LineEntry
DifferentAddr(ValidAddr
+ 1, ValidFileIdx
, ValidLine
);
371 LineEntry
DifferentFile(ValidAddr
, ValidFileIdx
+ 1, ValidLine
);
372 LineEntry
DifferentLine(ValidAddr
, ValidFileIdx
, ValidLine
+ 1);
373 EXPECT_TRUE(E1
.isValid());
375 EXPECT_NE(E1
, DifferentAddr
);
376 EXPECT_NE(E1
, DifferentFile
);
377 EXPECT_NE(E1
, DifferentLine
);
378 EXPECT_LT(E1
, DifferentAddr
);
381 TEST(GSYMTest
, TestRanges
) {
382 // test llvm::gsym::AddressRange.
383 const uint64_t StartAddr
= 0x1000;
384 const uint64_t EndAddr
= 0x2000;
385 // Verify constructor and API to ensure it takes start and end address.
386 const AddressRange
Range(StartAddr
, EndAddr
);
387 EXPECT_EQ(Range
.size(), EndAddr
- StartAddr
);
389 // Verify llvm::gsym::AddressRange::contains().
390 EXPECT_FALSE(Range
.contains(0));
391 EXPECT_FALSE(Range
.contains(StartAddr
- 1));
392 EXPECT_TRUE(Range
.contains(StartAddr
));
393 EXPECT_TRUE(Range
.contains(EndAddr
- 1));
394 EXPECT_FALSE(Range
.contains(EndAddr
));
395 EXPECT_FALSE(Range
.contains(UINT64_MAX
));
397 const AddressRange
RangeSame(StartAddr
, EndAddr
);
398 const AddressRange
RangeDifferentStart(StartAddr
+ 1, EndAddr
);
399 const AddressRange
RangeDifferentEnd(StartAddr
, EndAddr
+ 1);
400 const AddressRange
RangeDifferentStartEnd(StartAddr
+ 1, EndAddr
+ 1);
401 // Test == and != with values that are the same
402 EXPECT_EQ(Range
, RangeSame
);
403 EXPECT_FALSE(Range
!= RangeSame
);
404 // Test == and != with values that are the different
405 EXPECT_NE(Range
, RangeDifferentStart
);
406 EXPECT_NE(Range
, RangeDifferentEnd
);
407 EXPECT_NE(Range
, RangeDifferentStartEnd
);
408 EXPECT_FALSE(Range
== RangeDifferentStart
);
409 EXPECT_FALSE(Range
== RangeDifferentEnd
);
410 EXPECT_FALSE(Range
== RangeDifferentStartEnd
);
412 // Test "bool operator<(const AddressRange &, const AddressRange &)".
413 EXPECT_FALSE(Range
< RangeSame
);
414 EXPECT_FALSE(RangeSame
< Range
);
415 EXPECT_LT(Range
, RangeDifferentStart
);
416 EXPECT_LT(Range
, RangeDifferentEnd
);
417 EXPECT_LT(Range
, RangeDifferentStartEnd
);
418 // Test "bool operator<(const AddressRange &, uint64_t)"
419 EXPECT_LT(Range
.Start
, StartAddr
+ 1);
420 // Test "bool operator<(uint64_t, const AddressRange &)"
421 EXPECT_LT(StartAddr
- 1, Range
.Start
);
423 // Verify llvm::gsym::AddressRange::isContiguousWith() and
424 // llvm::gsym::AddressRange::intersects().
425 const AddressRange
EndsBeforeRangeStart(0, StartAddr
- 1);
426 const AddressRange
EndsAtRangeStart(0, StartAddr
);
427 const AddressRange
OverlapsRangeStart(StartAddr
- 1, StartAddr
+ 1);
428 const AddressRange
InsideRange(StartAddr
+ 1, EndAddr
- 1);
429 const AddressRange
OverlapsRangeEnd(EndAddr
- 1, EndAddr
+ 1);
430 const AddressRange
StartsAtRangeEnd(EndAddr
, EndAddr
+ 0x100);
431 const AddressRange
StartsAfterRangeEnd(EndAddr
+ 1, EndAddr
+ 0x100);
433 EXPECT_FALSE(Range
.intersects(EndsBeforeRangeStart
));
434 EXPECT_FALSE(Range
.intersects(EndsAtRangeStart
));
435 EXPECT_TRUE(Range
.intersects(OverlapsRangeStart
));
436 EXPECT_TRUE(Range
.intersects(InsideRange
));
437 EXPECT_TRUE(Range
.intersects(OverlapsRangeEnd
));
438 EXPECT_FALSE(Range
.intersects(StartsAtRangeEnd
));
439 EXPECT_FALSE(Range
.intersects(StartsAfterRangeEnd
));
441 // Test the functions that maintain GSYM address ranges:
442 // "bool AddressRange::contains(uint64_t Addr) const;"
443 // "void AddressRanges::insert(const AddressRange &R);"
444 AddressRanges Ranges
;
445 Ranges
.insert(AddressRange(0x1000, 0x2000));
446 Ranges
.insert(AddressRange(0x2000, 0x3000));
447 Ranges
.insert(AddressRange(0x4000, 0x5000));
449 EXPECT_FALSE(Ranges
.contains(0));
450 EXPECT_FALSE(Ranges
.contains(0x1000 - 1));
451 EXPECT_TRUE(Ranges
.contains(0x1000));
452 EXPECT_TRUE(Ranges
.contains(0x2000));
453 EXPECT_TRUE(Ranges
.contains(0x4000));
454 EXPECT_TRUE(Ranges
.contains(0x2000 - 1));
455 EXPECT_TRUE(Ranges
.contains(0x3000 - 1));
456 EXPECT_FALSE(Ranges
.contains(0x3000 + 1));
457 EXPECT_TRUE(Ranges
.contains(0x5000 - 1));
458 EXPECT_FALSE(Ranges
.contains(0x5000 + 1));
459 EXPECT_FALSE(Ranges
.contains(UINT64_MAX
));
461 EXPECT_FALSE(Ranges
.contains(AddressRange()));
462 EXPECT_FALSE(Ranges
.contains(AddressRange(0x1000-1, 0x1000)));
463 EXPECT_FALSE(Ranges
.contains(AddressRange(0x1000, 0x1000)));
464 EXPECT_TRUE(Ranges
.contains(AddressRange(0x1000, 0x1000+1)));
465 EXPECT_TRUE(Ranges
.contains(AddressRange(0x1000, 0x2000)));
466 EXPECT_FALSE(Ranges
.contains(AddressRange(0x1000, 0x2001)));
467 EXPECT_TRUE(Ranges
.contains(AddressRange(0x2000, 0x3000)));
468 EXPECT_FALSE(Ranges
.contains(AddressRange(0x2000, 0x3001)));
469 EXPECT_FALSE(Ranges
.contains(AddressRange(0x3000, 0x3001)));
470 EXPECT_FALSE(Ranges
.contains(AddressRange(0x1500, 0x4500)));
471 EXPECT_FALSE(Ranges
.contains(AddressRange(0x5000, 0x5001)));
473 // Verify that intersecting ranges get combined
475 Ranges
.insert(AddressRange(0x1100, 0x1F00));
476 // Verify a wholy contained range that is added doesn't do anything.
477 Ranges
.insert(AddressRange(0x1500, 0x1F00));
478 EXPECT_EQ(Ranges
.size(), 1u);
479 EXPECT_EQ(Ranges
[0], AddressRange(0x1100, 0x1F00));
481 // Verify a range that starts before and intersects gets combined.
482 Ranges
.insert(AddressRange(0x1000, Ranges
[0].Start
+ 1));
483 EXPECT_EQ(Ranges
.size(), 1u);
484 EXPECT_EQ(Ranges
[0], AddressRange(0x1000, 0x1F00));
486 // Verify a range that starts inside and extends ranges gets combined.
487 Ranges
.insert(AddressRange(Ranges
[0].End
- 1, 0x2000));
488 EXPECT_EQ(Ranges
.size(), 1u);
489 EXPECT_EQ(Ranges
[0], AddressRange(0x1000, 0x2000));
491 // Verify that adjacent ranges don't get combined
492 Ranges
.insert(AddressRange(0x2000, 0x3000));
493 EXPECT_EQ(Ranges
.size(), 2u);
494 EXPECT_EQ(Ranges
[0], AddressRange(0x1000, 0x2000));
495 EXPECT_EQ(Ranges
[1], AddressRange(0x2000, 0x3000));
496 // Verify if we add an address range that intersects two ranges
497 // that they get combined
498 Ranges
.insert(AddressRange(Ranges
[0].End
- 1, Ranges
[1].Start
+ 1));
499 EXPECT_EQ(Ranges
.size(), 1u);
500 EXPECT_EQ(Ranges
[0], AddressRange(0x1000, 0x3000));
502 Ranges
.insert(AddressRange(0x3000, 0x4000));
503 Ranges
.insert(AddressRange(0x4000, 0x5000));
504 Ranges
.insert(AddressRange(0x2000, 0x4500));
505 EXPECT_EQ(Ranges
.size(), 1u);
506 EXPECT_EQ(Ranges
[0], AddressRange(0x1000, 0x5000));
509 TEST(GSYMTest
, TestStringTable
) {
510 StringTable
StrTab(StringRef("\0Hello\0World\0", 13));
511 // Test extracting strings from a string table.
512 EXPECT_EQ(StrTab
.getString(0), "");
513 EXPECT_EQ(StrTab
.getString(1), "Hello");
514 EXPECT_EQ(StrTab
.getString(7), "World");
515 EXPECT_EQ(StrTab
.getString(8), "orld");
516 // Test pointing to last NULL terminator gets empty string.
517 EXPECT_EQ(StrTab
.getString(12), "");
518 // Test pointing to past end gets empty string.
519 EXPECT_EQ(StrTab
.getString(13), "");
522 static void TestFileWriterHelper(llvm::support::endianness ByteOrder
) {
523 SmallString
<512> Str
;
524 raw_svector_ostream
OutStrm(Str
);
525 FileWriter
FW(OutStrm
, ByteOrder
);
526 const int64_t MinSLEB
= INT64_MIN
;
527 const int64_t MaxSLEB
= INT64_MAX
;
528 const uint64_t MinULEB
= 0;
529 const uint64_t MaxULEB
= UINT64_MAX
;
530 const uint8_t U8
= 0x10;
531 const uint16_t U16
= 0x1122;
532 const uint32_t U32
= 0x12345678;
533 const uint64_t U64
= 0x33445566778899aa;
534 const char *Hello
= "hello";
540 const off_t FixupOffset
= FW
.tell();
542 FW
.writeSLEB(MinSLEB
);
543 FW
.writeSLEB(MaxSLEB
);
544 FW
.writeULEB(MinULEB
);
545 FW
.writeULEB(MaxULEB
);
546 FW
.writeNullTerminated(Hello
);
547 // Test Seek, Tell using Fixup32.
548 FW
.fixup32(U32
, FixupOffset
);
550 std::string
Bytes(OutStrm
.str());
551 uint8_t AddressSize
= 4;
552 DataExtractor
Data(Bytes
, ByteOrder
== llvm::support::little
, AddressSize
);
554 EXPECT_EQ(Data
.getU8(&Offset
), U8
);
555 EXPECT_EQ(Data
.getU16(&Offset
), U16
);
556 EXPECT_EQ(Data
.getU32(&Offset
), U32
);
557 EXPECT_EQ(Data
.getU64(&Offset
), U64
);
558 Offset
= alignTo(Offset
, 16);
559 EXPECT_EQ(Data
.getU32(&Offset
), U32
);
560 EXPECT_EQ(Data
.getSLEB128(&Offset
), MinSLEB
);
561 EXPECT_EQ(Data
.getSLEB128(&Offset
), MaxSLEB
);
562 EXPECT_EQ(Data
.getULEB128(&Offset
), MinULEB
);
563 EXPECT_EQ(Data
.getULEB128(&Offset
), MaxULEB
);
564 EXPECT_EQ(Data
.getCStrRef(&Offset
), StringRef(Hello
));
567 TEST(GSYMTest
, TestFileWriter
) {
568 TestFileWriterHelper(llvm::support::little
);
569 TestFileWriterHelper(llvm::support::big
);
572 TEST(GSYMTest
, TestAddressRangeEncodeDecode
) {
573 // Test encoding and decoding AddressRange objects. AddressRange objects
574 // are always stored as offsets from the a base address. The base address
575 // is the FunctionInfo's base address for function level ranges, and is
576 // the base address of the parent range for subranges.
577 SmallString
<512> Str
;
578 raw_svector_ostream
OutStrm(Str
);
579 const auto ByteOrder
= llvm::support::endian::system_endianness();
580 FileWriter
FW(OutStrm
, ByteOrder
);
581 const uint64_t BaseAddr
= 0x1000;
582 const AddressRange
Range1(0x1000, 0x1010);
583 const AddressRange
Range2(0x1020, 0x1030);
584 Range1
.encode(FW
, BaseAddr
);
585 Range2
.encode(FW
, BaseAddr
);
586 std::string
Bytes(OutStrm
.str());
587 uint8_t AddressSize
= 4;
588 DataExtractor
Data(Bytes
, ByteOrder
== llvm::support::little
, AddressSize
);
590 AddressRange DecodedRange1
, DecodedRange2
;
592 DecodedRange1
.decode(Data
, BaseAddr
, Offset
);
593 DecodedRange2
.decode(Data
, BaseAddr
, Offset
);
594 EXPECT_EQ(Range1
, DecodedRange1
);
595 EXPECT_EQ(Range2
, DecodedRange2
);
598 static void TestAddressRangeEncodeDecodeHelper(const AddressRanges
&Ranges
,
599 const uint64_t BaseAddr
) {
600 SmallString
<512> Str
;
601 raw_svector_ostream
OutStrm(Str
);
602 const auto ByteOrder
= llvm::support::endian::system_endianness();
603 FileWriter
FW(OutStrm
, ByteOrder
);
604 Ranges
.encode(FW
, BaseAddr
);
606 std::string
Bytes(OutStrm
.str());
607 uint8_t AddressSize
= 4;
608 DataExtractor
Data(Bytes
, ByteOrder
== llvm::support::little
, AddressSize
);
610 AddressRanges DecodedRanges
;
612 DecodedRanges
.decode(Data
, BaseAddr
, Offset
);
613 EXPECT_EQ(Ranges
, DecodedRanges
);
616 TEST(GSYMTest
, TestAddressRangesEncodeDecode
) {
617 // Test encoding and decoding AddressRanges. AddressRanges objects contain
618 // ranges that are stored as offsets from the a base address. The base address
619 // is the FunctionInfo's base address for function level ranges, and is the
620 // base address of the parent range for subranges.
621 const uint64_t BaseAddr
= 0x1000;
623 // Test encoding and decoding with no ranges.
624 AddressRanges Ranges
;
625 TestAddressRangeEncodeDecodeHelper(Ranges
, BaseAddr
);
627 // Test encoding and decoding with 1 range.
628 Ranges
.insert(AddressRange(0x1000, 0x1010));
629 TestAddressRangeEncodeDecodeHelper(Ranges
, BaseAddr
);
631 // Test encoding and decoding with multiple ranges.
632 Ranges
.insert(AddressRange(0x1020, 0x1030));
633 Ranges
.insert(AddressRange(0x1050, 0x1070));
634 TestAddressRangeEncodeDecodeHelper(Ranges
, BaseAddr
);