[InstCombine] Signed saturation patterns
[llvm-core.git] / unittests / DebugInfo / GSYM / GSYMTest.cpp
blob90d8594eec6e74bf92eb6440747a4953d4fe07ab
1 //===- llvm/unittest/DebugInfo/GSYMTest.cpp -------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
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"
25 #include <string>
27 using namespace llvm;
28 using namespace gsym;
30 void checkError(ArrayRef<std::string> ExpectedMsgs, Error Err) {
31 ASSERT_TRUE(bool(Err));
32 size_t WhichMsg = 0;
33 Error Remaining =
34 handleErrors(std::move(Err), [&](const ErrorInfoBase &Actual) {
35 ASSERT_LT(WhichMsg, ExpectedMsgs.size());
36 // Use .str(), because googletest doesn't visualise a StringRef
37 // properly.
38 EXPECT_EQ(Actual.message(), ExpectedMsgs[WhichMsg++]);
39 });
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.
50 FileEntry empty1;
51 FileEntry empty2;
52 EXPECT_EQ(empty1.Dir, 0u);
53 EXPECT_EQ(empty1.Base, 0u);
54 // Verify equality operator works
55 FileEntry a1(10, 30);
56 FileEntry a2(10, 30);
57 FileEntry b(10, 40);
58 EXPECT_EQ(empty1, empty2);
59 EXPECT_EQ(a1, a2);
60 EXPECT_NE(a1, b);
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.
82 FunctionInfo invalid;
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());
100 FI.clear();
101 EXPECT_FALSE(FI.isValid());
102 EXPECT_FALSE(FI.hasRichInfo());
104 FunctionInfo A1(0x1000, 0x100, NameOffset);
105 FunctionInfo A2(0x1000, 0x100, NameOffset);
106 FunctionInfo B;
107 // Check == operator
108 EXPECT_EQ(A1, A2);
109 // Make sure things are not equal if they only differ by start address.
110 B = A2;
111 B.setStartAddress(0x2000);
112 EXPECT_NE(B, A2);
113 // Make sure things are not equal if they only differ by size.
114 B = A2;
115 B.setSize(0x101);
116 EXPECT_NE(B, A2);
117 // Make sure things are not equal if they only differ by name.
118 B = A2;
119 B.Name = 60;
120 EXPECT_NE(B, A2);
121 // Check < operator.
122 // Check less than where address differs.
123 B = A2;
124 B.setStartAddress(A2.startAddress() + 0x1000);
125 EXPECT_LT(A1, B);
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,
161 std::string Bytes,
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
175 // error message.
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.
187 FW.writeU32(0);
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,
253 FI.Range.Start);
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));
274 InlineInfo Inline1;
275 Inline1.Ranges.insert(AddressRange(FuncAddr + 0x10, FuncAddr + 0x30));
276 Inline1.Name = 1;
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
288 // or inline info.
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);
324 ASSERT_FALSE(Err);
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,
336 std::string Bytes,
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.
361 InlineInfo II;
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
366 // or call line
367 EXPECT_TRUE(II.isValid());
368 // Make sure InlineInfo isn't after being cleared.
369 II.clear();
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
382 InlineInfo Root;
383 Root.Ranges.insert(AddressRange(0x100, 0x200));
384 InlineInfo Inline1;
385 Inline1.Ranges.insert(AddressRange(0x150, 0x160));
386 Inline1.Name = 1;
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
427 // [0x152-0x155)
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
440 // [0x157-0x158)
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.
462 InlineInfo Empty;
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
492 // error message.
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");
505 FW.writeU8(0);
506 TestInlineInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
507 "0x00000005: missing InlineInfo uint32_t for name");
508 FW.writeU32(0);
509 TestInlineInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
510 "0x00000009: missing ULEB128 for InlineInfo call file");
511 FW.writeU8(0);
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;
523 LineEntry Invalid;
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());
528 // Test operators
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());
535 EXPECT_EQ(E1, E2);
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
635 Ranges.clear();
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";
696 FW.writeU8(U8);
697 FW.writeU16(U16);
698 FW.writeU32(U32);
699 FW.writeU64(U64);
700 FW.alignTo(16);
701 const off_t FixupOffset = FW.tell();
702 FW.writeU32(0);
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);
714 uint64_t Offset = 0;
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;
752 uint64_t Offset = 0;
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;
772 uint64_t Offset = 0;
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 &LT) {
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);
805 ASSERT_FALSE(Err);
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;
819 LineTable LT;
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);
825 LT.push(Line0);
826 ASSERT_EQ(LT.size(), (size_t)1);
827 LT.push(Line1);
828 LT.push(Line2);
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);
836 // Test operator[].
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.
846 LT.clear();
847 ASSERT_TRUE(LT.empty());
848 ASSERT_EQ(LT.size(), (size_t)0);
850 LineTable LT1;
851 LineTable LT2;
853 // Test that two empty line tables are equal and neither are less than
854 // each other.
855 ASSERT_EQ(LT1, LT2);
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.
861 LT2.push(Line0);
862 ASSERT_LT(LT1, LT2);
863 ASSERT_NE(LT1, LT2);
865 // Test that two line tables with the same entries are equal.
866 LT1.push(Line0);
867 ASSERT_EQ(LT1, LT2);
868 ASSERT_FALSE(LT1 < LT2);
869 ASSERT_FALSE(LT2 < LT2);
872 static void TestLineTableDecodeError(llvm::support::endianness ByteOrder,
873 std::string Bytes,
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
887 // error message.
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);
928 LineTable LT;
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);
936 LT.push(Line0);
937 LT.push(Line1);
938 checkError("LineEntry has address 0x1000 which is less than the function "
939 "start address 0x1010", LT.encode(FW, BaseAddr+0x10));
940 LT.clear();
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.
944 LT.push(Line1);
945 LT.push(Line0);
946 checkError("LineEntry in LineTable not in ascending order",
947 LT.encode(FW, BaseAddr));
948 LT.clear();
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;
977 H.AddrOffSize = 4;
978 H.UUIDSize = 16;
979 H.BaseAddress = 0x1000;
980 H.NumAddresses = 1;
981 H.StrtabOffset= 0x2000;
982 H.StrtabSize = 0x1000;
983 for (size_t i=0; i<GSYM_MAX_UUID_SIZE; ++i) {
984 if (i < H.UUIDSize)
985 H.UUID[i] = i;
986 else
987 H.UUID[i] = 0;
991 TEST(GSYMTest, TestHeaderEncodeErrors) {
992 Header H;
993 InitHeader(H);
994 H.Magic = 12;
995 TestHeaderEncodeError(H, "invalid GSYM magic 0x0000000c");
996 InitHeader(H);
997 H.Version = 12;
998 TestHeaderEncodeError(H, "unsupported GSYM version 12");
999 InitHeader(H);
1000 H.AddrOffSize = 12;
1001 TestHeaderEncodeError(H, "invalid address offset size 12");
1002 InitHeader(H);
1003 H.UUIDSize = 128;
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);
1012 Header H;
1013 InitHeader(H);
1014 llvm::Error Err = H.encode(FW);
1015 ASSERT_FALSE(Err);
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);
1036 ASSERT_FALSE(Err);
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) {
1046 Header H;
1047 InitHeader(H);
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,
1065 14, 15, 16};
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.
1071 GsymCreator GC;
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
1078 // finalized.
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
1090 // too long.
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
1096 // table.
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
1104 // info.
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};
1148 GsymCreator GC;
1149 GC.setUUID(UUID);
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());
1157 ASSERT_FALSE(Err);
1158 TestEncodeDecode(GC, llvm::support::little,
1159 GSYM_VERSION,
1160 AddrOffSize,
1161 BaseAddr,
1162 2, // NumAddresses
1163 ArrayRef<uint8_t>(UUID));
1164 TestEncodeDecode(GC, llvm::support::big,
1165 GSYM_VERSION,
1166 AddrOffSize,
1167 BaseAddr,
1168 2, // NumAddresses
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};
1174 GsymCreator GC;
1175 GC.setUUID(UUID);
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());
1183 ASSERT_FALSE(Err);
1184 TestEncodeDecode(GC, llvm::support::little,
1185 GSYM_VERSION,
1186 AddrOffSize,
1187 BaseAddr,
1188 2, // NumAddresses
1189 ArrayRef<uint8_t>(UUID));
1190 TestEncodeDecode(GC, llvm::support::big,
1191 GSYM_VERSION,
1192 AddrOffSize,
1193 BaseAddr,
1194 2, // NumAddresses
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};
1200 GsymCreator GC;
1201 GC.setUUID(UUID);
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());
1209 ASSERT_FALSE(Err);
1210 TestEncodeDecode(GC, llvm::support::little,
1211 GSYM_VERSION,
1212 AddrOffSize,
1213 BaseAddr,
1214 2, // NumAddresses
1215 ArrayRef<uint8_t>(UUID));
1216 TestEncodeDecode(GC, llvm::support::big,
1217 GSYM_VERSION,
1218 AddrOffSize,
1219 BaseAddr,
1220 2, // NumAddresses
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};
1226 GsymCreator GC;
1227 GC.setUUID(UUID);
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());
1235 ASSERT_FALSE(Err);
1236 TestEncodeDecode(GC, llvm::support::little,
1237 GSYM_VERSION,
1238 AddrOffSize,
1239 BaseAddr,
1240 2, // NumAddresses
1241 ArrayRef<uint8_t>(UUID));
1242 TestEncodeDecode(GC, llvm::support::big,
1243 GSYM_VERSION,
1244 AddrOffSize,
1245 BaseAddr,
1246 2, // NumAddresses
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};
1266 GsymCreator GC;
1267 GC.setUUID(UUID);
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");