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/Header.h"
13 #include "llvm/DebugInfo/GSYM/FileEntry.h"
14 #include "llvm/DebugInfo/GSYM/FileWriter.h"
15 #include "llvm/DebugInfo/GSYM/FunctionInfo.h"
16 #include "llvm/DebugInfo/GSYM/GsymCreator.h"
17 #include "llvm/DebugInfo/GSYM/GsymReader.h"
18 #include "llvm/DebugInfo/GSYM/InlineInfo.h"
19 #include "llvm/DebugInfo/GSYM/Range.h"
20 #include "llvm/DebugInfo/GSYM/StringTable.h"
21 #include "llvm/Support/DataExtractor.h"
22 #include "llvm/Support/Endian.h"
24 #include "gtest/gtest.h"
30 void checkError(ArrayRef
<std::string
> ExpectedMsgs
, Error Err
) {
31 ASSERT_TRUE(bool(Err
));
34 handleErrors(std::move(Err
), [&](const ErrorInfoBase
&Actual
) {
35 ASSERT_LT(WhichMsg
, ExpectedMsgs
.size());
36 // Use .str(), because googletest doesn't visualise a StringRef
38 EXPECT_EQ(Actual
.message(), ExpectedMsgs
[WhichMsg
++]);
40 EXPECT_EQ(WhichMsg
, ExpectedMsgs
.size());
41 EXPECT_FALSE(Remaining
);
44 void checkError(std::string ExpectedMsg
, Error Err
) {
45 checkError(ArrayRef
<std::string
>{ExpectedMsg
}, std::move(Err
));
47 TEST(GSYMTest
, TestFileEntry
) {
48 // Make sure default constructed GSYM FileEntry has zeroes in the
49 // directory and basename string table indexes.
52 EXPECT_EQ(empty1
.Dir
, 0u);
53 EXPECT_EQ(empty1
.Base
, 0u);
54 // Verify equality operator works
58 EXPECT_EQ(empty1
, empty2
);
61 EXPECT_NE(a1
, empty1
);
62 // Test we can use llvm::gsym::FileEntry in llvm::DenseMap.
63 DenseMap
<FileEntry
, uint32_t> EntryToIndex
;
64 constexpr uint32_t Index1
= 1;
65 constexpr uint32_t Index2
= 1;
66 auto R
= EntryToIndex
.insert(std::make_pair(a1
, Index1
));
67 EXPECT_TRUE(R
.second
);
68 EXPECT_EQ(R
.first
->second
, Index1
);
69 R
= EntryToIndex
.insert(std::make_pair(a1
, Index1
));
70 EXPECT_FALSE(R
.second
);
71 EXPECT_EQ(R
.first
->second
, Index1
);
72 R
= EntryToIndex
.insert(std::make_pair(b
, Index2
));
73 EXPECT_TRUE(R
.second
);
74 EXPECT_EQ(R
.first
->second
, Index2
);
75 R
= EntryToIndex
.insert(std::make_pair(a1
, Index2
));
76 EXPECT_FALSE(R
.second
);
77 EXPECT_EQ(R
.first
->second
, Index2
);
80 TEST(GSYMTest
, TestFunctionInfo
) {
81 // Test GSYM FunctionInfo structs and functionality.
83 EXPECT_FALSE(invalid
.isValid());
84 EXPECT_FALSE(invalid
.hasRichInfo());
85 const uint64_t StartAddr
= 0x1000;
86 const uint64_t EndAddr
= 0x1100;
87 const uint64_t Size
= EndAddr
- StartAddr
;
88 const uint32_t NameOffset
= 30;
89 FunctionInfo
FI(StartAddr
, Size
, NameOffset
);
90 EXPECT_TRUE(FI
.isValid());
91 EXPECT_FALSE(FI
.hasRichInfo());
92 EXPECT_EQ(FI
.startAddress(), StartAddr
);
93 EXPECT_EQ(FI
.endAddress(), EndAddr
);
94 EXPECT_EQ(FI
.size(), Size
);
95 const uint32_t FileIdx
= 1;
96 const uint32_t Line
= 12;
97 FI
.OptLineTable
= LineTable();
98 FI
.OptLineTable
->push(LineEntry(StartAddr
,FileIdx
,Line
));
99 EXPECT_TRUE(FI
.hasRichInfo());
101 EXPECT_FALSE(FI
.isValid());
102 EXPECT_FALSE(FI
.hasRichInfo());
104 FunctionInfo
A1(0x1000, 0x100, NameOffset
);
105 FunctionInfo
A2(0x1000, 0x100, NameOffset
);
109 // Make sure things are not equal if they only differ by start address.
111 B
.setStartAddress(0x2000);
113 // Make sure things are not equal if they only differ by size.
117 // Make sure things are not equal if they only differ by name.
122 // Check less than where address differs.
124 B
.setStartAddress(A2
.startAddress() + 0x1000);
127 // We use the < operator to take a variety of different FunctionInfo
128 // structs from a variety of sources: symtab, debug info, runtime info
129 // and we sort them and want the sorting to allow us to quickly get the
130 // best version of a function info.
131 FunctionInfo
FISymtab(StartAddr
, Size
, NameOffset
);
132 FunctionInfo
FIWithLines(StartAddr
, Size
, NameOffset
);
133 FIWithLines
.OptLineTable
= LineTable();
134 FIWithLines
.OptLineTable
->push(LineEntry(StartAddr
,FileIdx
,Line
));
135 // Test that a FunctionInfo with just a name and size is less than one
136 // that has name, size and any number of line table entries
137 EXPECT_LT(FISymtab
, FIWithLines
);
139 FunctionInfo FIWithLinesAndInline
= FIWithLines
;
140 FIWithLinesAndInline
.Inline
= InlineInfo();
141 FIWithLinesAndInline
.Inline
->Ranges
.insert(
142 AddressRange(StartAddr
, StartAddr
+ 0x10));
143 // Test that a FunctionInfo with name, size, and line entries is less than
144 // the same one with valid inline info
145 EXPECT_LT(FIWithLines
, FIWithLinesAndInline
);
147 // Test if we have an entry with lines and one with more lines for the same
148 // range, the ones with more lines is greater than the one with less.
149 FunctionInfo FIWithMoreLines
= FIWithLines
;
150 FIWithMoreLines
.OptLineTable
->push(LineEntry(StartAddr
,FileIdx
,Line
+5));
151 EXPECT_LT(FIWithLines
, FIWithMoreLines
);
153 // Test that if we have the same number of lines we compare the line entries
154 // in the FunctionInfo.OptLineTable.Lines vector.
155 FunctionInfo FIWithLinesWithHigherAddress
= FIWithLines
;
156 FIWithLinesWithHigherAddress
.OptLineTable
->get(0).Addr
+= 0x10;
157 EXPECT_LT(FIWithLines
, FIWithLinesWithHigherAddress
);
160 static void TestFunctionInfoDecodeError(llvm::support::endianness ByteOrder
,
162 const uint64_t BaseAddr
,
163 std::string ExpectedErrorMsg
) {
164 uint8_t AddressSize
= 4;
165 DataExtractor
Data(Bytes
, ByteOrder
== llvm::support::little
, AddressSize
);
166 llvm::Expected
<FunctionInfo
> Decoded
= FunctionInfo::decode(Data
, BaseAddr
);
167 // Make sure decoding fails.
168 ASSERT_FALSE((bool)Decoded
);
169 // Make sure decoded object is the same as the one we encoded.
170 checkError(ExpectedErrorMsg
, Decoded
.takeError());
173 TEST(GSYMTest
, TestFunctionInfoDecodeErrors
) {
174 // Test decoding FunctionInfo objects that ensure we report an appropriate
176 const llvm::support::endianness ByteOrder
= llvm::support::little
;
177 SmallString
<512> Str
;
178 raw_svector_ostream
OutStrm(Str
);
179 FileWriter
FW(OutStrm
, ByteOrder
);
180 const uint64_t BaseAddr
= 0x100;
181 TestFunctionInfoDecodeError(ByteOrder
, OutStrm
.str(), BaseAddr
,
182 "0x00000000: missing FunctionInfo Size");
183 FW
.writeU32(0x100); // Function size.
184 TestFunctionInfoDecodeError(ByteOrder
, OutStrm
.str(), BaseAddr
,
185 "0x00000004: missing FunctionInfo Name");
186 // Write out an invalid Name string table offset of zero.
188 TestFunctionInfoDecodeError(ByteOrder
, OutStrm
.str(), BaseAddr
,
189 "0x00000004: invalid FunctionInfo Name value 0x00000000");
190 // Modify the Name to be 0x00000001, which is a valid value.
191 FW
.fixup32(0x00000001, 4);
192 TestFunctionInfoDecodeError(ByteOrder
, OutStrm
.str(), BaseAddr
,
193 "0x00000008: missing FunctionInfo InfoType value");
194 auto FixupOffset
= FW
.tell();
195 FW
.writeU32(1); // InfoType::LineTableInfo.
196 TestFunctionInfoDecodeError(ByteOrder
, OutStrm
.str(), BaseAddr
,
197 "0x0000000c: missing FunctionInfo InfoType length");
198 FW
.fixup32(4, FixupOffset
); // Write an invalid InfoType enumeration value
199 FW
.writeU32(0); // LineTableInfo InfoType data length.
200 TestFunctionInfoDecodeError(ByteOrder
, OutStrm
.str(), BaseAddr
,
201 "0x00000008: unsupported InfoType 4");
204 static void TestFunctionInfoEncodeError(llvm::support::endianness ByteOrder
,
205 const FunctionInfo
&FI
,
206 std::string ExpectedErrorMsg
) {
207 SmallString
<512> Str
;
208 raw_svector_ostream
OutStrm(Str
);
209 FileWriter
FW(OutStrm
, ByteOrder
);
210 Expected
<uint64_t> ExpectedOffset
= FI
.encode(FW
);
211 ASSERT_FALSE(ExpectedOffset
);
212 checkError(ExpectedErrorMsg
, ExpectedOffset
.takeError());
215 TEST(GSYMTest
, TestFunctionInfoEncodeErrors
) {
216 const uint64_t FuncAddr
= 0x1000;
217 const uint64_t FuncSize
= 0x100;
218 const uint32_t InvalidName
= 0;
219 const uint32_t ValidName
= 1;
220 FunctionInfo
InvalidNameFI(FuncAddr
, FuncSize
, InvalidName
);
221 TestFunctionInfoEncodeError(llvm::support::little
, InvalidNameFI
,
222 "attempted to encode invalid FunctionInfo object");
224 FunctionInfo
InvalidLineTableFI(FuncAddr
, FuncSize
, ValidName
);
225 // Empty line tables are not valid. Verify if the encoding of anything
226 // in our line table fails, that we see get the error propagated.
227 InvalidLineTableFI
.OptLineTable
= LineTable();
228 TestFunctionInfoEncodeError(llvm::support::little
, InvalidLineTableFI
,
229 "attempted to encode invalid LineTable object");
231 FunctionInfo
InvalidInlineInfoFI(FuncAddr
, FuncSize
, ValidName
);
232 // Empty line tables are not valid. Verify if the encoding of anything
233 // in our line table fails, that we see get the error propagated.
234 InvalidInlineInfoFI
.Inline
= InlineInfo();
235 TestFunctionInfoEncodeError(llvm::support::little
, InvalidInlineInfoFI
,
236 "attempted to encode invalid InlineInfo object");
239 static void TestFunctionInfoEncodeDecode(llvm::support::endianness ByteOrder
,
240 const FunctionInfo
&FI
) {
241 // Test encoding and decoding FunctionInfo objects.
242 SmallString
<512> Str
;
243 raw_svector_ostream
OutStrm(Str
);
244 FileWriter
FW(OutStrm
, ByteOrder
);
245 llvm::Expected
<uint64_t> ExpectedOffset
= FI
.encode(FW
);
246 ASSERT_TRUE(bool(ExpectedOffset
));
247 // Verify we got the encoded offset back from the encode function.
248 ASSERT_EQ(ExpectedOffset
.get(), 0ULL);
249 std::string
Bytes(OutStrm
.str());
250 uint8_t AddressSize
= 4;
251 DataExtractor
Data(Bytes
, ByteOrder
== llvm::support::little
, AddressSize
);
252 llvm::Expected
<FunctionInfo
> Decoded
= FunctionInfo::decode(Data
,
254 // Make sure decoding succeeded.
255 ASSERT_TRUE((bool)Decoded
);
256 // Make sure decoded object is the same as the one we encoded.
257 EXPECT_EQ(FI
, Decoded
.get());
260 static void AddLines(uint64_t FuncAddr
, uint32_t FileIdx
, FunctionInfo
&FI
) {
261 FI
.OptLineTable
= LineTable();
262 LineEntry
Line0(FuncAddr
+ 0x000, FileIdx
, 10);
263 LineEntry
Line1(FuncAddr
+ 0x010, FileIdx
, 11);
264 LineEntry
Line2(FuncAddr
+ 0x100, FileIdx
, 1000);
265 FI
.OptLineTable
->push(Line0
);
266 FI
.OptLineTable
->push(Line1
);
267 FI
.OptLineTable
->push(Line2
);
271 static void AddInline(uint64_t FuncAddr
, uint64_t FuncSize
, FunctionInfo
&FI
) {
272 FI
.Inline
= InlineInfo();
273 FI
.Inline
->Ranges
.insert(AddressRange(FuncAddr
, FuncAddr
+ FuncSize
));
275 Inline1
.Ranges
.insert(AddressRange(FuncAddr
+ 0x10, FuncAddr
+ 0x30));
277 Inline1
.CallFile
= 1;
278 Inline1
.CallLine
= 11;
279 FI
.Inline
->Children
.push_back(Inline1
);
282 TEST(GSYMTest
, TestFunctionInfoEncoding
) {
283 constexpr uint64_t FuncAddr
= 0x1000;
284 constexpr uint64_t FuncSize
= 0x100;
285 constexpr uint32_t FuncName
= 1;
286 constexpr uint32_t FileIdx
= 1;
287 // Make sure that we can encode and decode a FunctionInfo with no line table
289 FunctionInfo
FI(FuncAddr
, FuncSize
, FuncName
);
290 TestFunctionInfoEncodeDecode(llvm::support::little
, FI
);
291 TestFunctionInfoEncodeDecode(llvm::support::big
, FI
);
293 // Make sure that we can encode and decode a FunctionInfo with a line table
294 // and no inline info.
295 FunctionInfo
FILines(FuncAddr
, FuncSize
, FuncName
);
296 AddLines(FuncAddr
, FileIdx
, FILines
);
297 TestFunctionInfoEncodeDecode(llvm::support::little
, FILines
);
298 TestFunctionInfoEncodeDecode(llvm::support::big
, FILines
);
300 // Make sure that we can encode and decode a FunctionInfo with no line table
301 // and with inline info.
302 FunctionInfo
FIInline(FuncAddr
, FuncSize
, FuncName
);
303 AddInline(FuncAddr
, FuncSize
, FIInline
);
304 TestFunctionInfoEncodeDecode(llvm::support::little
, FIInline
);
305 TestFunctionInfoEncodeDecode(llvm::support::big
, FIInline
);
307 // Make sure that we can encode and decode a FunctionInfo with no line table
308 // and with inline info.
309 FunctionInfo
FIBoth(FuncAddr
, FuncSize
, FuncName
);
310 AddLines(FuncAddr
, FileIdx
, FIBoth
);
311 AddInline(FuncAddr
, FuncSize
, FIBoth
);
312 TestFunctionInfoEncodeDecode(llvm::support::little
, FIBoth
);
313 TestFunctionInfoEncodeDecode(llvm::support::big
, FIBoth
);
316 static void TestInlineInfoEncodeDecode(llvm::support::endianness ByteOrder
,
317 const InlineInfo
&Inline
) {
318 // Test encoding and decoding InlineInfo objects
319 SmallString
<512> Str
;
320 raw_svector_ostream
OutStrm(Str
);
321 FileWriter
FW(OutStrm
, ByteOrder
);
322 const uint64_t BaseAddr
= Inline
.Ranges
[0].Start
;
323 llvm::Error Err
= Inline
.encode(FW
, BaseAddr
);
325 std::string
Bytes(OutStrm
.str());
326 uint8_t AddressSize
= 4;
327 DataExtractor
Data(Bytes
, ByteOrder
== llvm::support::little
, AddressSize
);
328 llvm::Expected
<InlineInfo
> Decoded
= InlineInfo::decode(Data
, BaseAddr
);
329 // Make sure decoding succeeded.
330 ASSERT_TRUE((bool)Decoded
);
331 // Make sure decoded object is the same as the one we encoded.
332 EXPECT_EQ(Inline
, Decoded
.get());
335 static void TestInlineInfoDecodeError(llvm::support::endianness ByteOrder
,
337 const uint64_t BaseAddr
,
338 std::string ExpectedErrorMsg
) {
339 uint8_t AddressSize
= 4;
340 DataExtractor
Data(Bytes
, ByteOrder
== llvm::support::little
, AddressSize
);
341 llvm::Expected
<InlineInfo
> Decoded
= InlineInfo::decode(Data
, BaseAddr
);
342 // Make sure decoding fails.
343 ASSERT_FALSE((bool)Decoded
);
344 // Make sure decoded object is the same as the one we encoded.
345 checkError(ExpectedErrorMsg
, Decoded
.takeError());
348 static void TestInlineInfoEncodeError(llvm::support::endianness ByteOrder
,
349 const InlineInfo
&Inline
,
350 std::string ExpectedErrorMsg
) {
351 SmallString
<512> Str
;
352 raw_svector_ostream
OutStrm(Str
);
353 FileWriter
FW(OutStrm
, ByteOrder
);
354 const uint64_t BaseAddr
= Inline
.Ranges
.empty() ? 0 : Inline
.Ranges
[0].Start
;
355 llvm::Error Err
= Inline
.encode(FW
, BaseAddr
);
356 checkError(ExpectedErrorMsg
, std::move(Err
));
359 TEST(GSYMTest
, TestInlineInfo
) {
360 // Test InlineInfo structs.
362 EXPECT_FALSE(II
.isValid());
363 II
.Ranges
.insert(AddressRange(0x1000, 0x2000));
364 // Make sure InlineInfo in valid with just an address range since
365 // top level InlineInfo objects have ranges with no name, call file
367 EXPECT_TRUE(II
.isValid());
368 // Make sure InlineInfo isn't after being cleared.
370 EXPECT_FALSE(II
.isValid());
372 // Create an InlineInfo that contains the following data. The
373 // indentation of the address range indicates the parent child
374 // relationships of the InlineInfo objects:
376 // Variable Range and values
377 // =========== ====================================================
378 // Root [0x100-0x200) (no name, file, or line)
379 // Inline1 [0x150-0x160) Name = 1, File = 1, Line = 11
380 // Inline1Sub1 [0x152-0x155) Name = 2, File = 2, Line = 22
381 // Inline1Sub2 [0x157-0x158) Name = 3, File = 3, Line = 33
383 Root
.Ranges
.insert(AddressRange(0x100, 0x200));
385 Inline1
.Ranges
.insert(AddressRange(0x150, 0x160));
387 Inline1
.CallFile
= 1;
388 Inline1
.CallLine
= 11;
389 InlineInfo Inline1Sub1
;
390 Inline1Sub1
.Ranges
.insert(AddressRange(0x152, 0x155));
391 Inline1Sub1
.Name
= 2;
392 Inline1Sub1
.CallFile
= 2;
393 Inline1Sub1
.CallLine
= 22;
394 InlineInfo Inline1Sub2
;
395 Inline1Sub2
.Ranges
.insert(AddressRange(0x157, 0x158));
396 Inline1Sub2
.Name
= 3;
397 Inline1Sub2
.CallFile
= 3;
398 Inline1Sub2
.CallLine
= 33;
399 Inline1
.Children
.push_back(Inline1Sub1
);
400 Inline1
.Children
.push_back(Inline1Sub2
);
401 Root
.Children
.push_back(Inline1
);
403 // Make sure an address that is out of range won't match
404 EXPECT_FALSE(Root
.getInlineStack(0x50));
406 // Verify that we get no inline stacks for addresses out of [0x100-0x200)
407 EXPECT_FALSE(Root
.getInlineStack(Root
.Ranges
[0].Start
- 1));
408 EXPECT_FALSE(Root
.getInlineStack(Root
.Ranges
[0].End
));
410 // Verify we get no inline stack entries for addresses that are in
411 // [0x100-0x200) but not in [0x150-0x160)
412 EXPECT_FALSE(Root
.getInlineStack(Inline1
.Ranges
[0].Start
- 1));
413 EXPECT_FALSE(Root
.getInlineStack(Inline1
.Ranges
[0].End
));
415 // Verify we get one inline stack entry for addresses that are in
416 // [[0x150-0x160)) but not in [0x152-0x155) or [0x157-0x158)
417 auto InlineInfos
= Root
.getInlineStack(Inline1
.Ranges
[0].Start
);
418 ASSERT_TRUE(InlineInfos
);
419 ASSERT_EQ(InlineInfos
->size(), 1u);
420 ASSERT_EQ(*InlineInfos
->at(0), Inline1
);
421 InlineInfos
= Root
.getInlineStack(Inline1
.Ranges
[0].End
- 1);
422 EXPECT_TRUE(InlineInfos
);
423 ASSERT_EQ(InlineInfos
->size(), 1u);
424 ASSERT_EQ(*InlineInfos
->at(0), Inline1
);
426 // Verify we get two inline stack entries for addresses that are in
428 InlineInfos
= Root
.getInlineStack(Inline1Sub1
.Ranges
[0].Start
);
429 EXPECT_TRUE(InlineInfos
);
430 ASSERT_EQ(InlineInfos
->size(), 2u);
431 ASSERT_EQ(*InlineInfos
->at(0), Inline1Sub1
);
432 ASSERT_EQ(*InlineInfos
->at(1), Inline1
);
433 InlineInfos
= Root
.getInlineStack(Inline1Sub1
.Ranges
[0].End
- 1);
434 EXPECT_TRUE(InlineInfos
);
435 ASSERT_EQ(InlineInfos
->size(), 2u);
436 ASSERT_EQ(*InlineInfos
->at(0), Inline1Sub1
);
437 ASSERT_EQ(*InlineInfos
->at(1), Inline1
);
439 // Verify we get two inline stack entries for addresses that are in
441 InlineInfos
= Root
.getInlineStack(Inline1Sub2
.Ranges
[0].Start
);
442 EXPECT_TRUE(InlineInfos
);
443 ASSERT_EQ(InlineInfos
->size(), 2u);
444 ASSERT_EQ(*InlineInfos
->at(0), Inline1Sub2
);
445 ASSERT_EQ(*InlineInfos
->at(1), Inline1
);
446 InlineInfos
= Root
.getInlineStack(Inline1Sub2
.Ranges
[0].End
- 1);
447 EXPECT_TRUE(InlineInfos
);
448 ASSERT_EQ(InlineInfos
->size(), 2u);
449 ASSERT_EQ(*InlineInfos
->at(0), Inline1Sub2
);
450 ASSERT_EQ(*InlineInfos
->at(1), Inline1
);
452 // Test encoding and decoding InlineInfo objects
453 TestInlineInfoEncodeDecode(llvm::support::little
, Root
);
454 TestInlineInfoEncodeDecode(llvm::support::big
, Root
);
457 TEST(GSYMTest
, TestInlineInfoEncodeErrors
) {
458 // Test InlineInfo encoding errors.
460 // Test that we get an error when trying to encode an InlineInfo object
461 // that has no ranges.
463 std::string
EmptyErr("attempted to encode invalid InlineInfo object");
464 TestInlineInfoEncodeError(llvm::support::little
, Empty
, EmptyErr
);
465 TestInlineInfoEncodeError(llvm::support::big
, Empty
, EmptyErr
);
467 // Verify that we get an error trying to encode an InlineInfo object that has
468 // a child InlineInfo that has no ranges.
469 InlineInfo ContainsEmpty
;
470 ContainsEmpty
.Ranges
.insert({0x100,200});
471 ContainsEmpty
.Children
.push_back(Empty
);
472 TestInlineInfoEncodeError(llvm::support::little
, ContainsEmpty
, EmptyErr
);
473 TestInlineInfoEncodeError(llvm::support::big
, ContainsEmpty
, EmptyErr
);
475 // Verify that we get an error trying to encode an InlineInfo object that has
476 // a child whose address range is not contained in the parent address range.
477 InlineInfo ChildNotContained
;
478 std::string
ChildNotContainedErr("child range not contained in parent");
479 ChildNotContained
.Ranges
.insert({0x100,200});
480 InlineInfo ChildNotContainedChild
;
481 ChildNotContainedChild
.Ranges
.insert({0x200,300});
482 ChildNotContained
.Children
.push_back(ChildNotContainedChild
);
483 TestInlineInfoEncodeError(llvm::support::little
, ChildNotContained
,
484 ChildNotContainedErr
);
485 TestInlineInfoEncodeError(llvm::support::big
, ChildNotContained
,
486 ChildNotContainedErr
);
490 TEST(GSYMTest
, TestInlineInfoDecodeErrors
) {
491 // Test decoding InlineInfo objects that ensure we report an appropriate
493 const llvm::support::endianness ByteOrder
= llvm::support::little
;
494 SmallString
<512> Str
;
495 raw_svector_ostream
OutStrm(Str
);
496 FileWriter
FW(OutStrm
, ByteOrder
);
497 const uint64_t BaseAddr
= 0x100;
498 TestInlineInfoDecodeError(ByteOrder
, OutStrm
.str(), BaseAddr
,
499 "0x00000000: missing InlineInfo address ranges data");
500 AddressRanges Ranges
;
501 Ranges
.insert({BaseAddr
, BaseAddr
+0x100});
502 Ranges
.encode(FW
, BaseAddr
);
503 TestInlineInfoDecodeError(ByteOrder
, OutStrm
.str(), BaseAddr
,
504 "0x00000004: missing InlineInfo uint8_t indicating children");
506 TestInlineInfoDecodeError(ByteOrder
, OutStrm
.str(), BaseAddr
,
507 "0x00000005: missing InlineInfo uint32_t for name");
509 TestInlineInfoDecodeError(ByteOrder
, OutStrm
.str(), BaseAddr
,
510 "0x00000009: missing ULEB128 for InlineInfo call file");
512 TestInlineInfoDecodeError(ByteOrder
, OutStrm
.str(), BaseAddr
,
513 "0x0000000a: missing ULEB128 for InlineInfo call line");
516 TEST(GSYMTest
, TestLineEntry
) {
517 // test llvm::gsym::LineEntry structs.
518 const uint64_t ValidAddr
= 0x1000;
519 const uint64_t InvalidFileIdx
= 0;
520 const uint32_t ValidFileIdx
= 1;
521 const uint32_t ValidLine
= 5;
524 EXPECT_FALSE(Invalid
.isValid());
525 // Make sure that an entry is invalid if it has a bad file index.
526 LineEntry
BadFile(ValidAddr
, InvalidFileIdx
, ValidLine
);
527 EXPECT_FALSE(BadFile
.isValid());
529 LineEntry
E1(ValidAddr
, ValidFileIdx
, ValidLine
);
530 LineEntry
E2(ValidAddr
, ValidFileIdx
, ValidLine
);
531 LineEntry
DifferentAddr(ValidAddr
+ 1, ValidFileIdx
, ValidLine
);
532 LineEntry
DifferentFile(ValidAddr
, ValidFileIdx
+ 1, ValidLine
);
533 LineEntry
DifferentLine(ValidAddr
, ValidFileIdx
, ValidLine
+ 1);
534 EXPECT_TRUE(E1
.isValid());
536 EXPECT_NE(E1
, DifferentAddr
);
537 EXPECT_NE(E1
, DifferentFile
);
538 EXPECT_NE(E1
, DifferentLine
);
539 EXPECT_LT(E1
, DifferentAddr
);
542 TEST(GSYMTest
, TestRanges
) {
543 // test llvm::gsym::AddressRange.
544 const uint64_t StartAddr
= 0x1000;
545 const uint64_t EndAddr
= 0x2000;
546 // Verify constructor and API to ensure it takes start and end address.
547 const AddressRange
Range(StartAddr
, EndAddr
);
548 EXPECT_EQ(Range
.size(), EndAddr
- StartAddr
);
550 // Verify llvm::gsym::AddressRange::contains().
551 EXPECT_FALSE(Range
.contains(0));
552 EXPECT_FALSE(Range
.contains(StartAddr
- 1));
553 EXPECT_TRUE(Range
.contains(StartAddr
));
554 EXPECT_TRUE(Range
.contains(EndAddr
- 1));
555 EXPECT_FALSE(Range
.contains(EndAddr
));
556 EXPECT_FALSE(Range
.contains(UINT64_MAX
));
558 const AddressRange
RangeSame(StartAddr
, EndAddr
);
559 const AddressRange
RangeDifferentStart(StartAddr
+ 1, EndAddr
);
560 const AddressRange
RangeDifferentEnd(StartAddr
, EndAddr
+ 1);
561 const AddressRange
RangeDifferentStartEnd(StartAddr
+ 1, EndAddr
+ 1);
562 // Test == and != with values that are the same
563 EXPECT_EQ(Range
, RangeSame
);
564 EXPECT_FALSE(Range
!= RangeSame
);
565 // Test == and != with values that are the different
566 EXPECT_NE(Range
, RangeDifferentStart
);
567 EXPECT_NE(Range
, RangeDifferentEnd
);
568 EXPECT_NE(Range
, RangeDifferentStartEnd
);
569 EXPECT_FALSE(Range
== RangeDifferentStart
);
570 EXPECT_FALSE(Range
== RangeDifferentEnd
);
571 EXPECT_FALSE(Range
== RangeDifferentStartEnd
);
573 // Test "bool operator<(const AddressRange &, const AddressRange &)".
574 EXPECT_FALSE(Range
< RangeSame
);
575 EXPECT_FALSE(RangeSame
< Range
);
576 EXPECT_LT(Range
, RangeDifferentStart
);
577 EXPECT_LT(Range
, RangeDifferentEnd
);
578 EXPECT_LT(Range
, RangeDifferentStartEnd
);
579 // Test "bool operator<(const AddressRange &, uint64_t)"
580 EXPECT_LT(Range
.Start
, StartAddr
+ 1);
581 // Test "bool operator<(uint64_t, const AddressRange &)"
582 EXPECT_LT(StartAddr
- 1, Range
.Start
);
584 // Verify llvm::gsym::AddressRange::isContiguousWith() and
585 // llvm::gsym::AddressRange::intersects().
586 const AddressRange
EndsBeforeRangeStart(0, StartAddr
- 1);
587 const AddressRange
EndsAtRangeStart(0, StartAddr
);
588 const AddressRange
OverlapsRangeStart(StartAddr
- 1, StartAddr
+ 1);
589 const AddressRange
InsideRange(StartAddr
+ 1, EndAddr
- 1);
590 const AddressRange
OverlapsRangeEnd(EndAddr
- 1, EndAddr
+ 1);
591 const AddressRange
StartsAtRangeEnd(EndAddr
, EndAddr
+ 0x100);
592 const AddressRange
StartsAfterRangeEnd(EndAddr
+ 1, EndAddr
+ 0x100);
594 EXPECT_FALSE(Range
.intersects(EndsBeforeRangeStart
));
595 EXPECT_FALSE(Range
.intersects(EndsAtRangeStart
));
596 EXPECT_TRUE(Range
.intersects(OverlapsRangeStart
));
597 EXPECT_TRUE(Range
.intersects(InsideRange
));
598 EXPECT_TRUE(Range
.intersects(OverlapsRangeEnd
));
599 EXPECT_FALSE(Range
.intersects(StartsAtRangeEnd
));
600 EXPECT_FALSE(Range
.intersects(StartsAfterRangeEnd
));
602 // Test the functions that maintain GSYM address ranges:
603 // "bool AddressRange::contains(uint64_t Addr) const;"
604 // "void AddressRanges::insert(const AddressRange &R);"
605 AddressRanges Ranges
;
606 Ranges
.insert(AddressRange(0x1000, 0x2000));
607 Ranges
.insert(AddressRange(0x2000, 0x3000));
608 Ranges
.insert(AddressRange(0x4000, 0x5000));
610 EXPECT_FALSE(Ranges
.contains(0));
611 EXPECT_FALSE(Ranges
.contains(0x1000 - 1));
612 EXPECT_TRUE(Ranges
.contains(0x1000));
613 EXPECT_TRUE(Ranges
.contains(0x2000));
614 EXPECT_TRUE(Ranges
.contains(0x4000));
615 EXPECT_TRUE(Ranges
.contains(0x2000 - 1));
616 EXPECT_TRUE(Ranges
.contains(0x3000 - 1));
617 EXPECT_FALSE(Ranges
.contains(0x3000 + 1));
618 EXPECT_TRUE(Ranges
.contains(0x5000 - 1));
619 EXPECT_FALSE(Ranges
.contains(0x5000 + 1));
620 EXPECT_FALSE(Ranges
.contains(UINT64_MAX
));
622 EXPECT_FALSE(Ranges
.contains(AddressRange()));
623 EXPECT_FALSE(Ranges
.contains(AddressRange(0x1000-1, 0x1000)));
624 EXPECT_FALSE(Ranges
.contains(AddressRange(0x1000, 0x1000)));
625 EXPECT_TRUE(Ranges
.contains(AddressRange(0x1000, 0x1000+1)));
626 EXPECT_TRUE(Ranges
.contains(AddressRange(0x1000, 0x2000)));
627 EXPECT_FALSE(Ranges
.contains(AddressRange(0x1000, 0x2001)));
628 EXPECT_TRUE(Ranges
.contains(AddressRange(0x2000, 0x3000)));
629 EXPECT_FALSE(Ranges
.contains(AddressRange(0x2000, 0x3001)));
630 EXPECT_FALSE(Ranges
.contains(AddressRange(0x3000, 0x3001)));
631 EXPECT_FALSE(Ranges
.contains(AddressRange(0x1500, 0x4500)));
632 EXPECT_FALSE(Ranges
.contains(AddressRange(0x5000, 0x5001)));
634 // Verify that intersecting ranges get combined
636 Ranges
.insert(AddressRange(0x1100, 0x1F00));
637 // Verify a wholy contained range that is added doesn't do anything.
638 Ranges
.insert(AddressRange(0x1500, 0x1F00));
639 EXPECT_EQ(Ranges
.size(), 1u);
640 EXPECT_EQ(Ranges
[0], AddressRange(0x1100, 0x1F00));
642 // Verify a range that starts before and intersects gets combined.
643 Ranges
.insert(AddressRange(0x1000, Ranges
[0].Start
+ 1));
644 EXPECT_EQ(Ranges
.size(), 1u);
645 EXPECT_EQ(Ranges
[0], AddressRange(0x1000, 0x1F00));
647 // Verify a range that starts inside and extends ranges gets combined.
648 Ranges
.insert(AddressRange(Ranges
[0].End
- 1, 0x2000));
649 EXPECT_EQ(Ranges
.size(), 1u);
650 EXPECT_EQ(Ranges
[0], AddressRange(0x1000, 0x2000));
652 // Verify that adjacent ranges don't get combined
653 Ranges
.insert(AddressRange(0x2000, 0x3000));
654 EXPECT_EQ(Ranges
.size(), 2u);
655 EXPECT_EQ(Ranges
[0], AddressRange(0x1000, 0x2000));
656 EXPECT_EQ(Ranges
[1], AddressRange(0x2000, 0x3000));
657 // Verify if we add an address range that intersects two ranges
658 // that they get combined
659 Ranges
.insert(AddressRange(Ranges
[0].End
- 1, Ranges
[1].Start
+ 1));
660 EXPECT_EQ(Ranges
.size(), 1u);
661 EXPECT_EQ(Ranges
[0], AddressRange(0x1000, 0x3000));
663 Ranges
.insert(AddressRange(0x3000, 0x4000));
664 Ranges
.insert(AddressRange(0x4000, 0x5000));
665 Ranges
.insert(AddressRange(0x2000, 0x4500));
666 EXPECT_EQ(Ranges
.size(), 1u);
667 EXPECT_EQ(Ranges
[0], AddressRange(0x1000, 0x5000));
670 TEST(GSYMTest
, TestStringTable
) {
671 StringTable
StrTab(StringRef("\0Hello\0World\0", 13));
672 // Test extracting strings from a string table.
673 EXPECT_EQ(StrTab
.getString(0), "");
674 EXPECT_EQ(StrTab
.getString(1), "Hello");
675 EXPECT_EQ(StrTab
.getString(7), "World");
676 EXPECT_EQ(StrTab
.getString(8), "orld");
677 // Test pointing to last NULL terminator gets empty string.
678 EXPECT_EQ(StrTab
.getString(12), "");
679 // Test pointing to past end gets empty string.
680 EXPECT_EQ(StrTab
.getString(13), "");
683 static void TestFileWriterHelper(llvm::support::endianness ByteOrder
) {
684 SmallString
<512> Str
;
685 raw_svector_ostream
OutStrm(Str
);
686 FileWriter
FW(OutStrm
, ByteOrder
);
687 const int64_t MinSLEB
= INT64_MIN
;
688 const int64_t MaxSLEB
= INT64_MAX
;
689 const uint64_t MinULEB
= 0;
690 const uint64_t MaxULEB
= UINT64_MAX
;
691 const uint8_t U8
= 0x10;
692 const uint16_t U16
= 0x1122;
693 const uint32_t U32
= 0x12345678;
694 const uint64_t U64
= 0x33445566778899aa;
695 const char *Hello
= "hello";
701 const off_t FixupOffset
= FW
.tell();
703 FW
.writeSLEB(MinSLEB
);
704 FW
.writeSLEB(MaxSLEB
);
705 FW
.writeULEB(MinULEB
);
706 FW
.writeULEB(MaxULEB
);
707 FW
.writeNullTerminated(Hello
);
708 // Test Seek, Tell using Fixup32.
709 FW
.fixup32(U32
, FixupOffset
);
711 std::string
Bytes(OutStrm
.str());
712 uint8_t AddressSize
= 4;
713 DataExtractor
Data(Bytes
, ByteOrder
== llvm::support::little
, AddressSize
);
715 EXPECT_EQ(Data
.getU8(&Offset
), U8
);
716 EXPECT_EQ(Data
.getU16(&Offset
), U16
);
717 EXPECT_EQ(Data
.getU32(&Offset
), U32
);
718 EXPECT_EQ(Data
.getU64(&Offset
), U64
);
719 Offset
= alignTo(Offset
, 16);
720 EXPECT_EQ(Data
.getU32(&Offset
), U32
);
721 EXPECT_EQ(Data
.getSLEB128(&Offset
), MinSLEB
);
722 EXPECT_EQ(Data
.getSLEB128(&Offset
), MaxSLEB
);
723 EXPECT_EQ(Data
.getULEB128(&Offset
), MinULEB
);
724 EXPECT_EQ(Data
.getULEB128(&Offset
), MaxULEB
);
725 EXPECT_EQ(Data
.getCStrRef(&Offset
), StringRef(Hello
));
728 TEST(GSYMTest
, TestFileWriter
) {
729 TestFileWriterHelper(llvm::support::little
);
730 TestFileWriterHelper(llvm::support::big
);
733 TEST(GSYMTest
, TestAddressRangeEncodeDecode
) {
734 // Test encoding and decoding AddressRange objects. AddressRange objects
735 // are always stored as offsets from the a base address. The base address
736 // is the FunctionInfo's base address for function level ranges, and is
737 // the base address of the parent range for subranges.
738 SmallString
<512> Str
;
739 raw_svector_ostream
OutStrm(Str
);
740 const auto ByteOrder
= llvm::support::endian::system_endianness();
741 FileWriter
FW(OutStrm
, ByteOrder
);
742 const uint64_t BaseAddr
= 0x1000;
743 const AddressRange
Range1(0x1000, 0x1010);
744 const AddressRange
Range2(0x1020, 0x1030);
745 Range1
.encode(FW
, BaseAddr
);
746 Range2
.encode(FW
, BaseAddr
);
747 std::string
Bytes(OutStrm
.str());
748 uint8_t AddressSize
= 4;
749 DataExtractor
Data(Bytes
, ByteOrder
== llvm::support::little
, AddressSize
);
751 AddressRange DecodedRange1
, DecodedRange2
;
753 DecodedRange1
.decode(Data
, BaseAddr
, Offset
);
754 DecodedRange2
.decode(Data
, BaseAddr
, Offset
);
755 EXPECT_EQ(Range1
, DecodedRange1
);
756 EXPECT_EQ(Range2
, DecodedRange2
);
759 static void TestAddressRangeEncodeDecodeHelper(const AddressRanges
&Ranges
,
760 const uint64_t BaseAddr
) {
761 SmallString
<512> Str
;
762 raw_svector_ostream
OutStrm(Str
);
763 const auto ByteOrder
= llvm::support::endian::system_endianness();
764 FileWriter
FW(OutStrm
, ByteOrder
);
765 Ranges
.encode(FW
, BaseAddr
);
767 std::string
Bytes(OutStrm
.str());
768 uint8_t AddressSize
= 4;
769 DataExtractor
Data(Bytes
, ByteOrder
== llvm::support::little
, AddressSize
);
771 AddressRanges DecodedRanges
;
773 DecodedRanges
.decode(Data
, BaseAddr
, Offset
);
774 EXPECT_EQ(Ranges
, DecodedRanges
);
777 TEST(GSYMTest
, TestAddressRangesEncodeDecode
) {
778 // Test encoding and decoding AddressRanges. AddressRanges objects contain
779 // ranges that are stored as offsets from the a base address. The base address
780 // is the FunctionInfo's base address for function level ranges, and is the
781 // base address of the parent range for subranges.
782 const uint64_t BaseAddr
= 0x1000;
784 // Test encoding and decoding with no ranges.
785 AddressRanges Ranges
;
786 TestAddressRangeEncodeDecodeHelper(Ranges
, BaseAddr
);
788 // Test encoding and decoding with 1 range.
789 Ranges
.insert(AddressRange(0x1000, 0x1010));
790 TestAddressRangeEncodeDecodeHelper(Ranges
, BaseAddr
);
792 // Test encoding and decoding with multiple ranges.
793 Ranges
.insert(AddressRange(0x1020, 0x1030));
794 Ranges
.insert(AddressRange(0x1050, 0x1070));
795 TestAddressRangeEncodeDecodeHelper(Ranges
, BaseAddr
);
798 static void TestLineTableHelper(llvm::support::endianness ByteOrder
,
799 const LineTable
<
) {
800 SmallString
<512> Str
;
801 raw_svector_ostream
OutStrm(Str
);
802 FileWriter
FW(OutStrm
, ByteOrder
);
803 const uint64_t BaseAddr
= LT
[0].Addr
;
804 llvm::Error Err
= LT
.encode(FW
, BaseAddr
);
806 std::string
Bytes(OutStrm
.str());
807 uint8_t AddressSize
= 4;
808 DataExtractor
Data(Bytes
, ByteOrder
== llvm::support::little
, AddressSize
);
809 llvm::Expected
<LineTable
> Decoded
= LineTable::decode(Data
, BaseAddr
);
810 // Make sure decoding succeeded.
811 ASSERT_TRUE((bool)Decoded
);
812 // Make sure decoded object is the same as the one we encoded.
813 EXPECT_EQ(LT
, Decoded
.get());
816 TEST(GSYMTest
, TestLineTable
) {
817 const uint64_t StartAddr
= 0x1000;
818 const uint32_t FileIdx
= 1;
820 LineEntry
Line0(StartAddr
+0x000, FileIdx
, 10);
821 LineEntry
Line1(StartAddr
+0x010, FileIdx
, 11);
822 LineEntry
Line2(StartAddr
+0x100, FileIdx
, 1000);
823 ASSERT_TRUE(LT
.empty());
824 ASSERT_EQ(LT
.size(), (size_t)0);
826 ASSERT_EQ(LT
.size(), (size_t)1);
829 LT
.push(LineEntry(StartAddr
+0x120, FileIdx
, 900));
830 LT
.push(LineEntry(StartAddr
+0x120, FileIdx
, 2000));
831 LT
.push(LineEntry(StartAddr
+0x121, FileIdx
, 2001));
832 LT
.push(LineEntry(StartAddr
+0x122, FileIdx
, 2002));
833 LT
.push(LineEntry(StartAddr
+0x123, FileIdx
, 2003));
834 ASSERT_FALSE(LT
.empty());
835 ASSERT_EQ(LT
.size(), (size_t)8);
837 ASSERT_EQ(LT
[0], Line0
);
838 ASSERT_EQ(LT
[1], Line1
);
839 ASSERT_EQ(LT
[2], Line2
);
841 // Test encoding and decoding line tables.
842 TestLineTableHelper(llvm::support::little
, LT
);
843 TestLineTableHelper(llvm::support::big
, LT
);
845 // Verify the clear method works as expected.
847 ASSERT_TRUE(LT
.empty());
848 ASSERT_EQ(LT
.size(), (size_t)0);
853 // Test that two empty line tables are equal and neither are less than
856 ASSERT_FALSE(LT1
< LT2
);
857 ASSERT_FALSE(LT2
< LT2
);
859 // Test that a line table with less number of line entries is less than a
860 // line table with more line entries and that they are not equal.
865 // Test that two line tables with the same entries are equal.
868 ASSERT_FALSE(LT1
< LT2
);
869 ASSERT_FALSE(LT2
< LT2
);
872 static void TestLineTableDecodeError(llvm::support::endianness ByteOrder
,
874 const uint64_t BaseAddr
,
875 std::string ExpectedErrorMsg
) {
876 uint8_t AddressSize
= 4;
877 DataExtractor
Data(Bytes
, ByteOrder
== llvm::support::little
, AddressSize
);
878 llvm::Expected
<LineTable
> Decoded
= LineTable::decode(Data
, BaseAddr
);
879 // Make sure decoding fails.
880 ASSERT_FALSE((bool)Decoded
);
881 // Make sure decoded object is the same as the one we encoded.
882 checkError(ExpectedErrorMsg
, Decoded
.takeError());
885 TEST(GSYMTest
, TestLineTableDecodeErrors
) {
886 // Test decoding InlineInfo objects that ensure we report an appropriate
888 const llvm::support::endianness ByteOrder
= llvm::support::little
;
889 SmallString
<512> Str
;
890 raw_svector_ostream
OutStrm(Str
);
891 FileWriter
FW(OutStrm
, ByteOrder
);
892 const uint64_t BaseAddr
= 0x100;
893 TestLineTableDecodeError(ByteOrder
, OutStrm
.str(), BaseAddr
,
894 "0x00000000: missing LineTable MinDelta");
895 FW
.writeU8(1); // MinDelta (ULEB)
896 TestLineTableDecodeError(ByteOrder
, OutStrm
.str(), BaseAddr
,
897 "0x00000001: missing LineTable MaxDelta");
898 FW
.writeU8(10); // MaxDelta (ULEB)
899 TestLineTableDecodeError(ByteOrder
, OutStrm
.str(), BaseAddr
,
900 "0x00000002: missing LineTable FirstLine");
901 FW
.writeU8(20); // FirstLine (ULEB)
902 TestLineTableDecodeError(ByteOrder
, OutStrm
.str(), BaseAddr
,
903 "0x00000003: EOF found before EndSequence");
904 // Test a SetFile with the argument missing from the stream
905 FW
.writeU8(1); // SetFile opcode (uint8_t)
906 TestLineTableDecodeError(ByteOrder
, OutStrm
.str(), BaseAddr
,
907 "0x00000004: EOF found before SetFile value");
908 FW
.writeU8(5); // SetFile value as index (ULEB)
909 // Test a AdvancePC with the argument missing from the stream
910 FW
.writeU8(2); // AdvancePC opcode (uint8_t)
911 TestLineTableDecodeError(ByteOrder
, OutStrm
.str(), BaseAddr
,
912 "0x00000006: EOF found before AdvancePC value");
913 FW
.writeU8(20); // AdvancePC value as offset (ULEB)
914 // Test a AdvancePC with the argument missing from the stream
915 FW
.writeU8(3); // AdvanceLine opcode (uint8_t)
916 TestLineTableDecodeError(ByteOrder
, OutStrm
.str(), BaseAddr
,
917 "0x00000008: EOF found before AdvanceLine value");
918 FW
.writeU8(20); // AdvanceLine value as offset (LLEB)
921 TEST(GSYMTest
, TestLineTableEncodeErrors
) {
922 const uint64_t BaseAddr
= 0x1000;
923 const uint32_t FileIdx
= 1;
924 const llvm::support::endianness ByteOrder
= llvm::support::little
;
925 SmallString
<512> Str
;
926 raw_svector_ostream
OutStrm(Str
);
927 FileWriter
FW(OutStrm
, ByteOrder
);
929 checkError("attempted to encode invalid LineTable object",
930 LT
.encode(FW
, BaseAddr
));
932 // Try to encode a line table where a line entry has an address that is less
933 // than BaseAddr and verify we get an appropriate error.
934 LineEntry
Line0(BaseAddr
+0x000, FileIdx
, 10);
935 LineEntry
Line1(BaseAddr
+0x010, FileIdx
, 11);
938 checkError("LineEntry has address 0x1000 which is less than the function "
939 "start address 0x1010", LT
.encode(FW
, BaseAddr
+0x10));
942 // Try to encode a line table where a line entries has an address that is less
943 // than BaseAddr and verify we get an appropriate error.
946 checkError("LineEntry in LineTable not in ascending order",
947 LT
.encode(FW
, BaseAddr
));
951 static void TestHeaderEncodeError(const Header
&H
,
952 std::string ExpectedErrorMsg
) {
953 const support::endianness ByteOrder
= llvm::support::little
;
954 SmallString
<512> Str
;
955 raw_svector_ostream
OutStrm(Str
);
956 FileWriter
FW(OutStrm
, ByteOrder
);
957 llvm::Error Err
= H
.encode(FW
);
958 checkError(ExpectedErrorMsg
, std::move(Err
));
961 static void TestHeaderDecodeError(std::string Bytes
,
962 std::string ExpectedErrorMsg
) {
963 const support::endianness ByteOrder
= llvm::support::little
;
964 uint8_t AddressSize
= 4;
965 DataExtractor
Data(Bytes
, ByteOrder
== llvm::support::little
, AddressSize
);
966 llvm::Expected
<Header
> Decoded
= Header::decode(Data
);
967 // Make sure decoding fails.
968 ASSERT_FALSE((bool)Decoded
);
969 // Make sure decoded object is the same as the one we encoded.
970 checkError(ExpectedErrorMsg
, Decoded
.takeError());
973 // Populate a GSYM header with valid values.
974 static void InitHeader(Header
&H
) {
975 H
.Magic
= GSYM_MAGIC
;
976 H
.Version
= GSYM_VERSION
;
979 H
.BaseAddress
= 0x1000;
981 H
.StrtabOffset
= 0x2000;
982 H
.StrtabSize
= 0x1000;
983 for (size_t i
=0; i
<GSYM_MAX_UUID_SIZE
; ++i
) {
991 TEST(GSYMTest
, TestHeaderEncodeErrors
) {
995 TestHeaderEncodeError(H
, "invalid GSYM magic 0x0000000c");
998 TestHeaderEncodeError(H
, "unsupported GSYM version 12");
1001 TestHeaderEncodeError(H
, "invalid address offset size 12");
1004 TestHeaderEncodeError(H
, "invalid UUID size 128");
1007 TEST(GSYMTest
, TestHeaderDecodeErrors
) {
1008 const llvm::support::endianness ByteOrder
= llvm::support::little
;
1009 SmallString
<512> Str
;
1010 raw_svector_ostream
OutStrm(Str
);
1011 FileWriter
FW(OutStrm
, ByteOrder
);
1014 llvm::Error Err
= H
.encode(FW
);
1016 FW
.fixup32(12, offsetof(Header
, Magic
));
1017 TestHeaderDecodeError(OutStrm
.str(), "invalid GSYM magic 0x0000000c");
1018 FW
.fixup32(GSYM_MAGIC
, offsetof(Header
, Magic
));
1019 FW
.fixup32(12, offsetof(Header
, Version
));
1020 TestHeaderDecodeError(OutStrm
.str(), "unsupported GSYM version 12");
1021 FW
.fixup32(GSYM_VERSION
, offsetof(Header
, Version
));
1022 FW
.fixup32(12, offsetof(Header
, AddrOffSize
));
1023 TestHeaderDecodeError(OutStrm
.str(), "invalid address offset size 12");
1024 FW
.fixup32(4, offsetof(Header
, AddrOffSize
));
1025 FW
.fixup32(128, offsetof(Header
, UUIDSize
));
1026 TestHeaderDecodeError(OutStrm
.str(), "invalid UUID size 128");
1029 static void TestHeaderEncodeDecode(const Header
&H
,
1030 support::endianness ByteOrder
) {
1031 uint8_t AddressSize
= 4;
1032 SmallString
<512> Str
;
1033 raw_svector_ostream
OutStrm(Str
);
1034 FileWriter
FW(OutStrm
, ByteOrder
);
1035 llvm::Error Err
= H
.encode(FW
);
1037 std::string
Bytes(OutStrm
.str());
1038 DataExtractor
Data(Bytes
, ByteOrder
== llvm::support::little
, AddressSize
);
1039 llvm::Expected
<Header
> Decoded
= Header::decode(Data
);
1040 // Make sure decoding succeeded.
1041 ASSERT_TRUE((bool)Decoded
);
1042 EXPECT_EQ(H
, Decoded
.get());
1045 TEST(GSYMTest
, TestHeaderEncodeDecode
) {
1048 TestHeaderEncodeDecode(H
, llvm::support::little
);
1049 TestHeaderEncodeDecode(H
, llvm::support::big
);
1052 static void TestGsymCreatorEncodeError(llvm::support::endianness ByteOrder
,
1053 const GsymCreator
&GC
,
1054 std::string ExpectedErrorMsg
) {
1055 SmallString
<512> Str
;
1056 raw_svector_ostream
OutStrm(Str
);
1057 FileWriter
FW(OutStrm
, ByteOrder
);
1058 llvm::Error Err
= GC
.encode(FW
);
1059 ASSERT_TRUE(bool(Err
));
1060 checkError(ExpectedErrorMsg
, std::move(Err
));
1063 TEST(GSYMTest
, TestGsymCreatorEncodeErrors
) {
1064 const uint8_t ValidUUID
[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
1066 const uint8_t InvalidUUID
[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
1067 14, 15, 16, 17, 18, 19, 20, 21};
1068 // Verify we get an error when trying to encode an GsymCreator with no
1069 // function infos. We shouldn't be saving a GSYM file in this case since
1070 // there is nothing inside of it.
1072 TestGsymCreatorEncodeError(llvm::support::little
, GC
,
1073 "no functions to encode");
1074 const uint64_t FuncAddr
= 0x1000;
1075 const uint64_t FuncSize
= 0x100;
1076 const uint32_t FuncName
= GC
.insertString("foo");
1077 // Verify we get an error trying to encode a GsymCreator that isn't
1079 GC
.addFunctionInfo(FunctionInfo(FuncAddr
, FuncSize
, FuncName
));
1080 TestGsymCreatorEncodeError(llvm::support::little
, GC
,
1081 "GsymCreator wasn't finalized prior to encoding");
1082 std::string finalizeIssues
;
1083 raw_string_ostream
OS(finalizeIssues
);
1084 llvm::Error finalizeErr
= GC
.finalize(OS
);
1085 ASSERT_FALSE(bool(finalizeErr
));
1086 finalizeErr
= GC
.finalize(OS
);
1087 ASSERT_TRUE(bool(finalizeErr
));
1088 checkError("already finalized", std::move(finalizeErr
));
1089 // Verify we get an error trying to encode a GsymCreator with a UUID that is
1091 GC
.setUUID(InvalidUUID
);
1092 TestGsymCreatorEncodeError(llvm::support::little
, GC
,
1093 "invalid UUID size 21");
1094 GC
.setUUID(ValidUUID
);
1095 // Verify errors are propagated when we try to encoding an invalid line
1097 GC
.forEachFunctionInfo([](FunctionInfo
&FI
) -> bool {
1098 FI
.OptLineTable
= LineTable(); // Invalid line table.
1099 return false; // Stop iterating
1101 TestGsymCreatorEncodeError(llvm::support::little
, GC
,
1102 "attempted to encode invalid LineTable object");
1103 // Verify errors are propagated when we try to encoding an invalid inline
1105 GC
.forEachFunctionInfo([](FunctionInfo
&FI
) -> bool {
1106 FI
.OptLineTable
= llvm::None
;
1107 FI
.Inline
= InlineInfo(); // Invalid InlineInfo.
1108 return false; // Stop iterating
1110 TestGsymCreatorEncodeError(llvm::support::little
, GC
,
1111 "attempted to encode invalid InlineInfo object");
1114 static void Compare(const GsymCreator
&GC
, const GsymReader
&GR
) {
1115 // Verify that all of the data in a GsymCreator is correctly decoded from
1116 // a GsymReader. To do this, we iterator over
1117 GC
.forEachFunctionInfo([&](const FunctionInfo
&FI
) -> bool {
1118 auto DecodedFI
= GR
.getFunctionInfo(FI
.Range
.Start
);
1119 EXPECT_TRUE(bool(DecodedFI
));
1120 EXPECT_EQ(FI
, *DecodedFI
);
1121 return true; // Keep iterating over all FunctionInfo objects.
1125 static void TestEncodeDecode(const GsymCreator
&GC
,
1126 support::endianness ByteOrder
, uint16_t Version
,
1127 uint8_t AddrOffSize
, uint64_t BaseAddress
,
1128 uint32_t NumAddresses
, ArrayRef
<uint8_t> UUID
) {
1129 SmallString
<512> Str
;
1130 raw_svector_ostream
OutStrm(Str
);
1131 FileWriter
FW(OutStrm
, ByteOrder
);
1132 llvm::Error Err
= GC
.encode(FW
);
1133 ASSERT_FALSE((bool)Err
);
1134 Expected
<GsymReader
> GR
= GsymReader::copyBuffer(OutStrm
.str());
1135 ASSERT_TRUE(bool(GR
));
1136 const Header
&Hdr
= GR
->getHeader();
1137 EXPECT_EQ(Hdr
.Version
, Version
);
1138 EXPECT_EQ(Hdr
.AddrOffSize
, AddrOffSize
);
1139 EXPECT_EQ(Hdr
.UUIDSize
, UUID
.size());
1140 EXPECT_EQ(Hdr
.BaseAddress
, BaseAddress
);
1141 EXPECT_EQ(Hdr
.NumAddresses
, NumAddresses
);
1142 EXPECT_EQ(ArrayRef
<uint8_t>(Hdr
.UUID
, Hdr
.UUIDSize
), UUID
);
1143 Compare(GC
, GR
.get());
1146 TEST(GSYMTest
, TestGsymCreator1ByteAddrOffsets
) {
1147 uint8_t UUID
[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
1150 constexpr uint64_t BaseAddr
= 0x1000;
1151 constexpr uint8_t AddrOffSize
= 1;
1152 const uint32_t Func1Name
= GC
.insertString("foo");
1153 const uint32_t Func2Name
= GC
.insertString("bar");
1154 GC
.addFunctionInfo(FunctionInfo(BaseAddr
+0x00, 0x10, Func1Name
));
1155 GC
.addFunctionInfo(FunctionInfo(BaseAddr
+0x20, 0x10, Func2Name
));
1156 Error Err
= GC
.finalize(llvm::nulls());
1158 TestEncodeDecode(GC
, llvm::support::little
,
1163 ArrayRef
<uint8_t>(UUID
));
1164 TestEncodeDecode(GC
, llvm::support::big
,
1169 ArrayRef
<uint8_t>(UUID
));
1172 TEST(GSYMTest
, TestGsymCreator2ByteAddrOffsets
) {
1173 uint8_t UUID
[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
1176 constexpr uint64_t BaseAddr
= 0x1000;
1177 constexpr uint8_t AddrOffSize
= 2;
1178 const uint32_t Func1Name
= GC
.insertString("foo");
1179 const uint32_t Func2Name
= GC
.insertString("bar");
1180 GC
.addFunctionInfo(FunctionInfo(BaseAddr
+0x000, 0x100, Func1Name
));
1181 GC
.addFunctionInfo(FunctionInfo(BaseAddr
+0x200, 0x100, Func2Name
));
1182 Error Err
= GC
.finalize(llvm::nulls());
1184 TestEncodeDecode(GC
, llvm::support::little
,
1189 ArrayRef
<uint8_t>(UUID
));
1190 TestEncodeDecode(GC
, llvm::support::big
,
1195 ArrayRef
<uint8_t>(UUID
));
1198 TEST(GSYMTest
, TestGsymCreator4ByteAddrOffsets
) {
1199 uint8_t UUID
[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
1202 constexpr uint64_t BaseAddr
= 0x1000;
1203 constexpr uint8_t AddrOffSize
= 4;
1204 const uint32_t Func1Name
= GC
.insertString("foo");
1205 const uint32_t Func2Name
= GC
.insertString("bar");
1206 GC
.addFunctionInfo(FunctionInfo(BaseAddr
+0x000, 0x100, Func1Name
));
1207 GC
.addFunctionInfo(FunctionInfo(BaseAddr
+0x20000, 0x100, Func2Name
));
1208 Error Err
= GC
.finalize(llvm::nulls());
1210 TestEncodeDecode(GC
, llvm::support::little
,
1215 ArrayRef
<uint8_t>(UUID
));
1216 TestEncodeDecode(GC
, llvm::support::big
,
1221 ArrayRef
<uint8_t>(UUID
));
1224 TEST(GSYMTest
, TestGsymCreator8ByteAddrOffsets
) {
1225 uint8_t UUID
[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
1228 constexpr uint64_t BaseAddr
= 0x1000;
1229 constexpr uint8_t AddrOffSize
= 8;
1230 const uint32_t Func1Name
= GC
.insertString("foo");
1231 const uint32_t Func2Name
= GC
.insertString("bar");
1232 GC
.addFunctionInfo(FunctionInfo(BaseAddr
+0x000, 0x100, Func1Name
));
1233 GC
.addFunctionInfo(FunctionInfo(BaseAddr
+0x100000000, 0x100, Func2Name
));
1234 Error Err
= GC
.finalize(llvm::nulls());
1236 TestEncodeDecode(GC
, llvm::support::little
,
1241 ArrayRef
<uint8_t>(UUID
));
1242 TestEncodeDecode(GC
, llvm::support::big
,
1247 ArrayRef
<uint8_t>(UUID
));
1250 static void VerifyFunctionInfo(const GsymReader
&GR
, uint64_t Addr
,
1251 const FunctionInfo
&FI
) {
1252 auto ExpFI
= GR
.getFunctionInfo(Addr
);
1253 ASSERT_TRUE(bool(ExpFI
));
1254 ASSERT_EQ(FI
, ExpFI
.get());
1257 static void VerifyFunctionInfoError(const GsymReader
&GR
, uint64_t Addr
,
1258 std::string ErrMessage
) {
1259 auto ExpFI
= GR
.getFunctionInfo(Addr
);
1260 ASSERT_FALSE(bool(ExpFI
));
1261 checkError(ErrMessage
, ExpFI
.takeError());
1264 TEST(GSYMTest
, TestGsymReader
) {
1265 uint8_t UUID
[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
1268 constexpr uint64_t BaseAddr
= 0x1000;
1269 constexpr uint64_t Func1Addr
= BaseAddr
;
1270 constexpr uint64_t Func2Addr
= BaseAddr
+0x20;
1271 constexpr uint64_t FuncSize
= 0x10;
1272 const uint32_t Func1Name
= GC
.insertString("foo");
1273 const uint32_t Func2Name
= GC
.insertString("bar");
1274 const auto ByteOrder
= support::endian::system_endianness();
1275 GC
.addFunctionInfo(FunctionInfo(Func1Addr
, FuncSize
, Func1Name
));
1276 GC
.addFunctionInfo(FunctionInfo(Func2Addr
, FuncSize
, Func2Name
));
1277 Error FinalizeErr
= GC
.finalize(llvm::nulls());
1278 ASSERT_FALSE(FinalizeErr
);
1279 SmallString
<512> Str
;
1280 raw_svector_ostream
OutStrm(Str
);
1281 FileWriter
FW(OutStrm
, ByteOrder
);
1282 llvm::Error Err
= GC
.encode(FW
);
1283 ASSERT_FALSE((bool)Err
);
1284 if (auto ExpectedGR
= GsymReader::copyBuffer(OutStrm
.str())) {
1285 const GsymReader
&GR
= ExpectedGR
.get();
1286 VerifyFunctionInfoError(GR
, Func1Addr
-1, "address 0xfff not in GSYM");
1288 FunctionInfo
Func1(Func1Addr
, FuncSize
, Func1Name
);
1289 VerifyFunctionInfo(GR
, Func1Addr
, Func1
);
1290 VerifyFunctionInfo(GR
, Func1Addr
+1, Func1
);
1291 VerifyFunctionInfo(GR
, Func1Addr
+FuncSize
-1, Func1
);
1292 VerifyFunctionInfoError(GR
, Func1Addr
+FuncSize
,
1293 "address 0x1010 not in GSYM");
1294 VerifyFunctionInfoError(GR
, Func2Addr
-1, "address 0x101f not in GSYM");
1295 FunctionInfo
Func2(Func2Addr
, FuncSize
, Func2Name
);
1296 VerifyFunctionInfo(GR
, Func2Addr
, Func2
);
1297 VerifyFunctionInfo(GR
, Func2Addr
+1, Func2
);
1298 VerifyFunctionInfo(GR
, Func2Addr
+FuncSize
-1, Func2
);
1299 VerifyFunctionInfoError(GR
, Func2Addr
+FuncSize
,
1300 "address 0x1030 not in GSYM");