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 //===----------------------------------------------------------------------===//
9 
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"
23 
24 #include "gtest/gtest.h"
25 #include <string>
26 
27 using namespace llvm;
28 using namespace gsym;
29 
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);
42 }
43 
44 void checkError(std::string ExpectedMsg, Error Err) {
45   checkError(ArrayRef<std::string>{ExpectedMsg}, std::move(Err));
46 }
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);
78 }
79 
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());
103 
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);
126 
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);
138 
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);
146 
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);
152 
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);
158 }
159 
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());
171 }
172 
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");
202 }
203 
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());
213 }
214 
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");
223 
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");
230 
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");
237 }
238 
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());
258 }
259 
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);
268 }
269 
270 
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);
280 }
281 
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);
292 
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);
299 
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);
306 
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);
314 }
315 
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());
333 }
334 
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());
346 }
347 
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));
357 }
358 
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());
371 
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:
375   //
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);
402 
403   // Make sure an address that is out of range won't match
404   EXPECT_FALSE(Root.getInlineStack(0x50));
405 
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));
409 
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));
414 
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);
425 
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);
438 
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);
451 
452   // Test encoding and decoding InlineInfo objects
453   TestInlineInfoEncodeDecode(llvm::support::little, Root);
454   TestInlineInfoEncodeDecode(llvm::support::big, Root);
455 }
456 
457 TEST(GSYMTest, TestInlineInfoEncodeErrors) {
458   // Test InlineInfo encoding errors.
459 
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);
466 
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);
474 
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);
487 
488 }
489 
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");
514 }
515 
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;
522 
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);
540 }
541 
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);
549 
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));
557 
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);
572 
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);
583 
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);
593 
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));
601 
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));
609 
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));
621 
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)));
633 
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));
641 
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));
646 
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));
651 
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));
662 
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));
668 }
669 
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), "");
681 }
682 
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);
710 
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));
726 }
727 
728 TEST(GSYMTest, TestFileWriter) {
729   TestFileWriterHelper(llvm::support::little);
730   TestFileWriterHelper(llvm::support::big);
731 }
732 
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);
750 
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);
757 }
758 
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);
766 
767   std::string Bytes(OutStrm.str());
768   uint8_t AddressSize = 4;
769   DataExtractor Data(Bytes, ByteOrder == llvm::support::little, AddressSize);
770 
771   AddressRanges DecodedRanges;
772   uint64_t Offset = 0;
773   DecodedRanges.decode(Data, BaseAddr, Offset);
774   EXPECT_EQ(Ranges, DecodedRanges);
775 }
776 
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;
783 
784   // Test encoding and decoding with no ranges.
785   AddressRanges Ranges;
786   TestAddressRangeEncodeDecodeHelper(Ranges, BaseAddr);
787 
788   // Test encoding and decoding with 1 range.
789   Ranges.insert(AddressRange(0x1000, 0x1010));
790   TestAddressRangeEncodeDecodeHelper(Ranges, BaseAddr);
791 
792   // Test encoding and decoding with multiple ranges.
793   Ranges.insert(AddressRange(0x1020, 0x1030));
794   Ranges.insert(AddressRange(0x1050, 0x1070));
795   TestAddressRangeEncodeDecodeHelper(Ranges, BaseAddr);
796 }
797 
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());
814 }
815 
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);
840 
841   // Test encoding and decoding line tables.
842   TestLineTableHelper(llvm::support::little, LT);
843   TestLineTableHelper(llvm::support::big, LT);
844 
845   // Verify the clear method works as expected.
846   LT.clear();
847   ASSERT_TRUE(LT.empty());
848   ASSERT_EQ(LT.size(), (size_t)0);
849 
850   LineTable LT1;
851   LineTable LT2;
852 
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 < LT1);
857   ASSERT_FALSE(LT1 < LT2);
858   ASSERT_FALSE(LT2 < LT1);
859   ASSERT_FALSE(LT2 < LT2);
860 
861   // Test that a line table with less number of line entries is less than a
862   // line table with more line entries and that they are not equal.
863   LT2.push(Line0);
864   ASSERT_LT(LT1, LT2);
865   ASSERT_NE(LT1, LT2);
866 
867   // Test that two line tables with the same entries are equal.
868   LT1.push(Line0);
869   ASSERT_EQ(LT1, LT2);
870   ASSERT_FALSE(LT1 < LT2);
871   ASSERT_FALSE(LT2 < LT2);
872 }
873 
874 static void TestLineTableDecodeError(llvm::support::endianness ByteOrder,
875                                      std::string Bytes,
876                                      const uint64_t BaseAddr,
877                                      std::string ExpectedErrorMsg) {
878   uint8_t AddressSize = 4;
879   DataExtractor Data(Bytes, ByteOrder == llvm::support::little, AddressSize);
880   llvm::Expected<LineTable> Decoded = LineTable::decode(Data, BaseAddr);
881   // Make sure decoding fails.
882   ASSERT_FALSE((bool)Decoded);
883   // Make sure decoded object is the same as the one we encoded.
884   checkError(ExpectedErrorMsg, Decoded.takeError());
885 }
886 
887 TEST(GSYMTest, TestLineTableDecodeErrors) {
888   // Test decoding InlineInfo objects that ensure we report an appropriate
889   // error message.
890   const llvm::support::endianness ByteOrder = llvm::support::little;
891   SmallString<512> Str;
892   raw_svector_ostream OutStrm(Str);
893   FileWriter FW(OutStrm, ByteOrder);
894   const uint64_t BaseAddr = 0x100;
895   TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
896       "0x00000000: missing LineTable MinDelta");
897   FW.writeU8(1); // MinDelta (ULEB)
898   TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
899       "0x00000001: missing LineTable MaxDelta");
900   FW.writeU8(10); // MaxDelta (ULEB)
901   TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
902       "0x00000002: missing LineTable FirstLine");
903   FW.writeU8(20); // FirstLine (ULEB)
904   TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
905       "0x00000003: EOF found before EndSequence");
906   // Test a SetFile with the argument missing from the stream
907   FW.writeU8(1); // SetFile opcode (uint8_t)
908   TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
909       "0x00000004: EOF found before SetFile value");
910   FW.writeU8(5); // SetFile value as index (ULEB)
911   // Test a AdvancePC with the argument missing from the stream
912   FW.writeU8(2); // AdvancePC opcode (uint8_t)
913   TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
914       "0x00000006: EOF found before AdvancePC value");
915   FW.writeU8(20); // AdvancePC value as offset (ULEB)
916   // Test a AdvancePC with the argument missing from the stream
917   FW.writeU8(3); // AdvanceLine opcode (uint8_t)
918   TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
919       "0x00000008: EOF found before AdvanceLine value");
920   FW.writeU8(20); // AdvanceLine value as offset (LLEB)
921 }
922 
923 TEST(GSYMTest, TestLineTableEncodeErrors) {
924   const uint64_t BaseAddr = 0x1000;
925   const uint32_t FileIdx = 1;
926   const llvm::support::endianness ByteOrder = llvm::support::little;
927   SmallString<512> Str;
928   raw_svector_ostream OutStrm(Str);
929   FileWriter FW(OutStrm, ByteOrder);
930   LineTable LT;
931   checkError("attempted to encode invalid LineTable object",
932              LT.encode(FW, BaseAddr));
933 
934   // Try to encode a line table where a line entry has an address that is less
935   // than BaseAddr and verify we get an appropriate error.
936   LineEntry Line0(BaseAddr+0x000, FileIdx, 10);
937   LineEntry Line1(BaseAddr+0x010, FileIdx, 11);
938   LT.push(Line0);
939   LT.push(Line1);
940   checkError("LineEntry has address 0x1000 which is less than the function "
941              "start address 0x1010", LT.encode(FW, BaseAddr+0x10));
942   LT.clear();
943 
944   // Try to encode a line table where a line entries  has an address that is less
945   // than BaseAddr and verify we get an appropriate error.
946   LT.push(Line1);
947   LT.push(Line0);
948   checkError("LineEntry in LineTable not in ascending order",
949              LT.encode(FW, BaseAddr));
950   LT.clear();
951 }
952 
953 static void TestHeaderEncodeError(const Header &H,
954                                   std::string ExpectedErrorMsg) {
955   const support::endianness ByteOrder = llvm::support::little;
956   SmallString<512> Str;
957   raw_svector_ostream OutStrm(Str);
958   FileWriter FW(OutStrm, ByteOrder);
959   llvm::Error Err = H.encode(FW);
960   checkError(ExpectedErrorMsg, std::move(Err));
961 }
962 
963 static void TestHeaderDecodeError(std::string Bytes,
964                                   std::string ExpectedErrorMsg) {
965   const support::endianness ByteOrder = llvm::support::little;
966   uint8_t AddressSize = 4;
967   DataExtractor Data(Bytes, ByteOrder == llvm::support::little, AddressSize);
968   llvm::Expected<Header> Decoded = Header::decode(Data);
969   // Make sure decoding fails.
970   ASSERT_FALSE((bool)Decoded);
971   // Make sure decoded object is the same as the one we encoded.
972   checkError(ExpectedErrorMsg, Decoded.takeError());
973 }
974 
975 // Populate a GSYM header with valid values.
976 static void InitHeader(Header &H) {
977   H.Magic = GSYM_MAGIC;
978   H.Version = GSYM_VERSION;
979   H.AddrOffSize = 4;
980   H.UUIDSize = 16;
981   H.BaseAddress = 0x1000;
982   H.NumAddresses = 1;
983   H.StrtabOffset= 0x2000;
984   H.StrtabSize = 0x1000;
985   for (size_t i=0; i<GSYM_MAX_UUID_SIZE; ++i) {
986     if (i < H.UUIDSize)
987       H.UUID[i] = i;
988     else
989       H.UUID[i] = 0;
990   }
991 }
992 
993 TEST(GSYMTest, TestHeaderEncodeErrors) {
994   Header H;
995   InitHeader(H);
996   H.Magic = 12;
997   TestHeaderEncodeError(H, "invalid GSYM magic 0x0000000c");
998   InitHeader(H);
999   H.Version = 12;
1000   TestHeaderEncodeError(H, "unsupported GSYM version 12");
1001   InitHeader(H);
1002   H.AddrOffSize = 12;
1003   TestHeaderEncodeError(H, "invalid address offset size 12");
1004   InitHeader(H);
1005   H.UUIDSize = 128;
1006   TestHeaderEncodeError(H, "invalid UUID size 128");
1007 }
1008 
1009 TEST(GSYMTest, TestHeaderDecodeErrors) {
1010   const llvm::support::endianness ByteOrder = llvm::support::little;
1011   SmallString<512> Str;
1012   raw_svector_ostream OutStrm(Str);
1013   FileWriter FW(OutStrm, ByteOrder);
1014   Header H;
1015   InitHeader(H);
1016   llvm::Error Err = H.encode(FW);
1017   ASSERT_FALSE(Err);
1018   FW.fixup32(12, offsetof(Header, Magic));
1019   TestHeaderDecodeError(OutStrm.str(), "invalid GSYM magic 0x0000000c");
1020   FW.fixup32(GSYM_MAGIC, offsetof(Header, Magic));
1021   FW.fixup32(12, offsetof(Header, Version));
1022   TestHeaderDecodeError(OutStrm.str(), "unsupported GSYM version 12");
1023   FW.fixup32(GSYM_VERSION, offsetof(Header, Version));
1024   FW.fixup32(12, offsetof(Header, AddrOffSize));
1025   TestHeaderDecodeError(OutStrm.str(), "invalid address offset size 12");
1026   FW.fixup32(4, offsetof(Header, AddrOffSize));
1027   FW.fixup32(128, offsetof(Header, UUIDSize));
1028   TestHeaderDecodeError(OutStrm.str(), "invalid UUID size 128");
1029 }
1030 
1031 static void TestHeaderEncodeDecode(const Header &H,
1032                                    support::endianness ByteOrder) {
1033   uint8_t AddressSize = 4;
1034   SmallString<512> Str;
1035   raw_svector_ostream OutStrm(Str);
1036   FileWriter FW(OutStrm, ByteOrder);
1037   llvm::Error Err = H.encode(FW);
1038   ASSERT_FALSE(Err);
1039   std::string Bytes(OutStrm.str());
1040   DataExtractor Data(Bytes, ByteOrder == llvm::support::little, AddressSize);
1041   llvm::Expected<Header> Decoded = Header::decode(Data);
1042   // Make sure decoding succeeded.
1043   ASSERT_TRUE((bool)Decoded);
1044   EXPECT_EQ(H, Decoded.get());
1045 
1046 }
1047 TEST(GSYMTest, TestHeaderEncodeDecode) {
1048   Header H;
1049   InitHeader(H);
1050   TestHeaderEncodeDecode(H, llvm::support::little);
1051   TestHeaderEncodeDecode(H, llvm::support::big);
1052 }
1053 
1054 static void TestGsymCreatorEncodeError(llvm::support::endianness ByteOrder,
1055                                        const GsymCreator &GC,
1056                                        std::string ExpectedErrorMsg) {
1057   SmallString<512> Str;
1058   raw_svector_ostream OutStrm(Str);
1059   FileWriter FW(OutStrm, ByteOrder);
1060   llvm::Error Err = GC.encode(FW);
1061   ASSERT_TRUE(bool(Err));
1062   checkError(ExpectedErrorMsg, std::move(Err));
1063 }
1064 
1065 TEST(GSYMTest, TestGsymCreatorEncodeErrors) {
1066   const uint8_t ValidUUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
1067                                14, 15, 16};
1068   const uint8_t InvalidUUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
1069                                  14, 15, 16, 17, 18, 19, 20, 21};
1070   // Verify we get an error when trying to encode an GsymCreator with no
1071   // function infos. We shouldn't be saving a GSYM file in this case since
1072   // there is nothing inside of it.
1073   GsymCreator GC;
1074   TestGsymCreatorEncodeError(llvm::support::little, GC,
1075                              "no functions to encode");
1076   const uint64_t FuncAddr = 0x1000;
1077   const uint64_t FuncSize = 0x100;
1078   const uint32_t FuncName = GC.insertString("foo");
1079   // Verify we get an error trying to encode a GsymCreator that isn't
1080   // finalized.
1081   GC.addFunctionInfo(FunctionInfo(FuncAddr, FuncSize, FuncName));
1082   TestGsymCreatorEncodeError(llvm::support::little, GC,
1083                              "GsymCreator wasn't finalized prior to encoding");
1084   std::string finalizeIssues;
1085   raw_string_ostream OS(finalizeIssues);
1086   llvm::Error finalizeErr = GC.finalize(OS);
1087   ASSERT_FALSE(bool(finalizeErr));
1088   finalizeErr = GC.finalize(OS);
1089   ASSERT_TRUE(bool(finalizeErr));
1090   checkError("already finalized", std::move(finalizeErr));
1091   // Verify we get an error trying to encode a GsymCreator with a UUID that is
1092   // too long.
1093   GC.setUUID(InvalidUUID);
1094   TestGsymCreatorEncodeError(llvm::support::little, GC,
1095                              "invalid UUID size 21");
1096   GC.setUUID(ValidUUID);
1097   // Verify errors are propagated when we try to encoding an invalid line
1098   // table.
1099   GC.forEachFunctionInfo([](FunctionInfo &FI) -> bool {
1100     FI.OptLineTable = LineTable(); // Invalid line table.
1101     return false; // Stop iterating
1102   });
1103   TestGsymCreatorEncodeError(llvm::support::little, GC,
1104                              "attempted to encode invalid LineTable object");
1105   // Verify errors are propagated when we try to encoding an invalid inline
1106   // info.
1107   GC.forEachFunctionInfo([](FunctionInfo &FI) -> bool {
1108     FI.OptLineTable = llvm::None;
1109     FI.Inline = InlineInfo(); // Invalid InlineInfo.
1110     return false; // Stop iterating
1111   });
1112   TestGsymCreatorEncodeError(llvm::support::little, GC,
1113                              "attempted to encode invalid InlineInfo object");
1114 }
1115 
1116 static void Compare(const GsymCreator &GC, const GsymReader &GR) {
1117   // Verify that all of the data in a GsymCreator is correctly decoded from
1118   // a GsymReader. To do this, we iterator over
1119   GC.forEachFunctionInfo([&](const FunctionInfo &FI) -> bool {
1120     auto DecodedFI = GR.getFunctionInfo(FI.Range.Start);
1121     EXPECT_TRUE(bool(DecodedFI));
1122     EXPECT_EQ(FI, *DecodedFI);
1123     return true; // Keep iterating over all FunctionInfo objects.
1124   });
1125 }
1126 
1127 static void TestEncodeDecode(const GsymCreator &GC,
1128                              support::endianness ByteOrder, uint16_t Version,
1129                              uint8_t AddrOffSize, uint64_t BaseAddress,
1130                              uint32_t NumAddresses, ArrayRef<uint8_t> UUID) {
1131   SmallString<512> Str;
1132   raw_svector_ostream OutStrm(Str);
1133   FileWriter FW(OutStrm, ByteOrder);
1134   llvm::Error Err = GC.encode(FW);
1135   ASSERT_FALSE((bool)Err);
1136   Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());
1137   ASSERT_TRUE(bool(GR));
1138   const Header &Hdr = GR->getHeader();
1139   EXPECT_EQ(Hdr.Version, Version);
1140   EXPECT_EQ(Hdr.AddrOffSize, AddrOffSize);
1141   EXPECT_EQ(Hdr.UUIDSize, UUID.size());
1142   EXPECT_EQ(Hdr.BaseAddress, BaseAddress);
1143   EXPECT_EQ(Hdr.NumAddresses, NumAddresses);
1144   EXPECT_EQ(ArrayRef<uint8_t>(Hdr.UUID, Hdr.UUIDSize), UUID);
1145   Compare(GC, GR.get());
1146 }
1147 
1148 TEST(GSYMTest, TestGsymCreator1ByteAddrOffsets) {
1149   uint8_t UUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
1150   GsymCreator GC;
1151   GC.setUUID(UUID);
1152   constexpr uint64_t BaseAddr = 0x1000;
1153   constexpr uint8_t AddrOffSize = 1;
1154   const uint32_t Func1Name = GC.insertString("foo");
1155   const uint32_t Func2Name = GC.insertString("bar");
1156   GC.addFunctionInfo(FunctionInfo(BaseAddr+0x00, 0x10, Func1Name));
1157   GC.addFunctionInfo(FunctionInfo(BaseAddr+0x20, 0x10, Func2Name));
1158   Error Err = GC.finalize(llvm::nulls());
1159   ASSERT_FALSE(Err);
1160   TestEncodeDecode(GC, llvm::support::little,
1161                    GSYM_VERSION,
1162                    AddrOffSize,
1163                    BaseAddr,
1164                    2, // NumAddresses
1165                    ArrayRef<uint8_t>(UUID));
1166   TestEncodeDecode(GC, llvm::support::big,
1167                    GSYM_VERSION,
1168                    AddrOffSize,
1169                    BaseAddr,
1170                    2, // NumAddresses
1171                    ArrayRef<uint8_t>(UUID));
1172 }
1173 
1174 TEST(GSYMTest, TestGsymCreator2ByteAddrOffsets) {
1175   uint8_t UUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
1176   GsymCreator GC;
1177   GC.setUUID(UUID);
1178   constexpr uint64_t BaseAddr = 0x1000;
1179   constexpr uint8_t AddrOffSize = 2;
1180   const uint32_t Func1Name = GC.insertString("foo");
1181   const uint32_t Func2Name = GC.insertString("bar");
1182   GC.addFunctionInfo(FunctionInfo(BaseAddr+0x000, 0x100, Func1Name));
1183   GC.addFunctionInfo(FunctionInfo(BaseAddr+0x200, 0x100, Func2Name));
1184   Error Err = GC.finalize(llvm::nulls());
1185   ASSERT_FALSE(Err);
1186   TestEncodeDecode(GC, llvm::support::little,
1187                    GSYM_VERSION,
1188                    AddrOffSize,
1189                    BaseAddr,
1190                    2, // NumAddresses
1191                    ArrayRef<uint8_t>(UUID));
1192   TestEncodeDecode(GC, llvm::support::big,
1193                    GSYM_VERSION,
1194                    AddrOffSize,
1195                    BaseAddr,
1196                    2, // NumAddresses
1197                    ArrayRef<uint8_t>(UUID));
1198 }
1199 
1200 TEST(GSYMTest, TestGsymCreator4ByteAddrOffsets) {
1201   uint8_t UUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
1202   GsymCreator GC;
1203   GC.setUUID(UUID);
1204   constexpr uint64_t BaseAddr = 0x1000;
1205   constexpr uint8_t AddrOffSize = 4;
1206   const uint32_t Func1Name = GC.insertString("foo");
1207   const uint32_t Func2Name = GC.insertString("bar");
1208   GC.addFunctionInfo(FunctionInfo(BaseAddr+0x000, 0x100, Func1Name));
1209   GC.addFunctionInfo(FunctionInfo(BaseAddr+0x20000, 0x100, Func2Name));
1210   Error Err = GC.finalize(llvm::nulls());
1211   ASSERT_FALSE(Err);
1212   TestEncodeDecode(GC, llvm::support::little,
1213                    GSYM_VERSION,
1214                    AddrOffSize,
1215                    BaseAddr,
1216                    2, // NumAddresses
1217                    ArrayRef<uint8_t>(UUID));
1218   TestEncodeDecode(GC, llvm::support::big,
1219                    GSYM_VERSION,
1220                    AddrOffSize,
1221                    BaseAddr,
1222                    2, // NumAddresses
1223                    ArrayRef<uint8_t>(UUID));
1224 }
1225 
1226 TEST(GSYMTest, TestGsymCreator8ByteAddrOffsets) {
1227   uint8_t UUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
1228   GsymCreator GC;
1229   GC.setUUID(UUID);
1230   constexpr uint64_t BaseAddr = 0x1000;
1231   constexpr uint8_t AddrOffSize = 8;
1232   const uint32_t Func1Name = GC.insertString("foo");
1233   const uint32_t Func2Name = GC.insertString("bar");
1234   GC.addFunctionInfo(FunctionInfo(BaseAddr+0x000, 0x100, Func1Name));
1235   GC.addFunctionInfo(FunctionInfo(BaseAddr+0x100000000, 0x100, Func2Name));
1236   Error Err = GC.finalize(llvm::nulls());
1237   ASSERT_FALSE(Err);
1238   TestEncodeDecode(GC, llvm::support::little,
1239                    GSYM_VERSION,
1240                    AddrOffSize,
1241                    BaseAddr,
1242                    2, // NumAddresses
1243                    ArrayRef<uint8_t>(UUID));
1244   TestEncodeDecode(GC, llvm::support::big,
1245                    GSYM_VERSION,
1246                    AddrOffSize,
1247                    BaseAddr,
1248                    2, // NumAddresses
1249                    ArrayRef<uint8_t>(UUID));
1250 }
1251 
1252 static void VerifyFunctionInfo(const GsymReader &GR, uint64_t Addr,
1253                                const FunctionInfo &FI) {
1254   auto ExpFI = GR.getFunctionInfo(Addr);
1255   ASSERT_TRUE(bool(ExpFI));
1256   ASSERT_EQ(FI, ExpFI.get());
1257 }
1258 
1259 static void VerifyFunctionInfoError(const GsymReader &GR, uint64_t Addr,
1260                                     std::string ErrMessage) {
1261   auto ExpFI = GR.getFunctionInfo(Addr);
1262   ASSERT_FALSE(bool(ExpFI));
1263   checkError(ErrMessage, ExpFI.takeError());
1264 }
1265 
1266 TEST(GSYMTest, TestGsymReader) {
1267   uint8_t UUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
1268   GsymCreator GC;
1269   GC.setUUID(UUID);
1270   constexpr uint64_t BaseAddr = 0x1000;
1271   constexpr uint64_t Func1Addr = BaseAddr;
1272   constexpr uint64_t Func2Addr = BaseAddr+0x20;
1273   constexpr uint64_t FuncSize = 0x10;
1274   const uint32_t Func1Name = GC.insertString("foo");
1275   const uint32_t Func2Name = GC.insertString("bar");
1276   const auto ByteOrder = support::endian::system_endianness();
1277   GC.addFunctionInfo(FunctionInfo(Func1Addr, FuncSize, Func1Name));
1278   GC.addFunctionInfo(FunctionInfo(Func2Addr, FuncSize, Func2Name));
1279   Error FinalizeErr = GC.finalize(llvm::nulls());
1280   ASSERT_FALSE(FinalizeErr);
1281   SmallString<512> Str;
1282   raw_svector_ostream OutStrm(Str);
1283   FileWriter FW(OutStrm, ByteOrder);
1284   llvm::Error Err = GC.encode(FW);
1285   ASSERT_FALSE((bool)Err);
1286   if (auto ExpectedGR = GsymReader::copyBuffer(OutStrm.str())) {
1287     const GsymReader &GR = ExpectedGR.get();
1288     VerifyFunctionInfoError(GR, Func1Addr-1, "address 0xfff not in GSYM");
1289 
1290     FunctionInfo Func1(Func1Addr, FuncSize, Func1Name);
1291     VerifyFunctionInfo(GR, Func1Addr, Func1);
1292     VerifyFunctionInfo(GR, Func1Addr+1, Func1);
1293     VerifyFunctionInfo(GR, Func1Addr+FuncSize-1, Func1);
1294     VerifyFunctionInfoError(GR, Func1Addr+FuncSize,
1295                             "address 0x1010 not in GSYM");
1296     VerifyFunctionInfoError(GR, Func2Addr-1, "address 0x101f not in GSYM");
1297     FunctionInfo Func2(Func2Addr, FuncSize, Func2Name);
1298     VerifyFunctionInfo(GR, Func2Addr, Func2);
1299     VerifyFunctionInfo(GR, Func2Addr+1, Func2);
1300     VerifyFunctionInfo(GR, Func2Addr+FuncSize-1, Func2);
1301     VerifyFunctionInfoError(GR, Func2Addr+FuncSize,
1302                             "address 0x1030 not in GSYM");
1303   }
1304 }
1305