1 //===- llvm/unittest/DebugInfo/GSYMTest.cpp -------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/ADT/DenseMap.h"
10 #include "llvm/ADT/SmallString.h"
11 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
12 #include "llvm/DebugInfo/GSYM/DwarfTransformer.h"
13 #include "llvm/DebugInfo/GSYM/ExtractRanges.h"
14 #include "llvm/DebugInfo/GSYM/FileEntry.h"
15 #include "llvm/DebugInfo/GSYM/FileWriter.h"
16 #include "llvm/DebugInfo/GSYM/FunctionInfo.h"
17 #include "llvm/DebugInfo/GSYM/GsymCreator.h"
18 #include "llvm/DebugInfo/GSYM/GsymReader.h"
19 #include "llvm/DebugInfo/GSYM/Header.h"
20 #include "llvm/DebugInfo/GSYM/InlineInfo.h"
21 #include "llvm/DebugInfo/GSYM/StringTable.h"
22 #include "llvm/ObjectYAML/DWARFEmitter.h"
23 #include "llvm/Support/DataExtractor.h"
24 #include "llvm/Support/Endian.h"
25 #include "llvm/Testing/Support/Error.h"
26 
27 #include "gtest/gtest.h"
28 #include "gmock/gmock.h"
29 #include <string>
30 
31 using namespace llvm;
32 using namespace gsym;
33 
34 void checkError(ArrayRef<std::string> ExpectedMsgs, Error Err) {
35   ASSERT_TRUE(bool(Err));
36   size_t WhichMsg = 0;
37   Error Remaining =
38       handleErrors(std::move(Err), [&](const ErrorInfoBase &Actual) {
39         ASSERT_LT(WhichMsg, ExpectedMsgs.size());
40         // Use .str(), because googletest doesn't visualise a StringRef
41         // properly.
42         EXPECT_EQ(Actual.message(), ExpectedMsgs[WhichMsg++]);
43       });
44   EXPECT_EQ(WhichMsg, ExpectedMsgs.size());
45   EXPECT_FALSE(Remaining);
46 }
47 
48 void checkError(std::string ExpectedMsg, Error Err) {
49   checkError(ArrayRef<std::string>{ExpectedMsg}, std::move(Err));
50 }
51 TEST(GSYMTest, TestFileEntry) {
52   // Make sure default constructed GSYM FileEntry has zeroes in the
53   // directory and basename string table indexes.
54   FileEntry empty1;
55   FileEntry empty2;
56   EXPECT_EQ(empty1.Dir, 0u);
57   EXPECT_EQ(empty1.Base, 0u);
58   // Verify equality operator works
59   FileEntry a1(10, 30);
60   FileEntry a2(10, 30);
61   FileEntry b(10, 40);
62   EXPECT_EQ(empty1, empty2);
63   EXPECT_EQ(a1, a2);
64   EXPECT_NE(a1, b);
65   EXPECT_NE(a1, empty1);
66   // Test we can use llvm::gsym::FileEntry in llvm::DenseMap.
67   DenseMap<FileEntry, uint32_t> EntryToIndex;
68   constexpr uint32_t Index1 = 1;
69   constexpr uint32_t Index2 = 1;
70   auto R = EntryToIndex.insert(std::make_pair(a1, Index1));
71   EXPECT_TRUE(R.second);
72   EXPECT_EQ(R.first->second, Index1);
73   R = EntryToIndex.insert(std::make_pair(a1, Index1));
74   EXPECT_FALSE(R.second);
75   EXPECT_EQ(R.first->second, Index1);
76   R = EntryToIndex.insert(std::make_pair(b, Index2));
77   EXPECT_TRUE(R.second);
78   EXPECT_EQ(R.first->second, Index2);
79   R = EntryToIndex.insert(std::make_pair(a1, Index2));
80   EXPECT_FALSE(R.second);
81   EXPECT_EQ(R.first->second, Index2);
82 }
83 
84 TEST(GSYMTest, TestFunctionInfo) {
85   // Test GSYM FunctionInfo structs and functionality.
86   FunctionInfo invalid;
87   EXPECT_FALSE(invalid.isValid());
88   EXPECT_FALSE(invalid.hasRichInfo());
89   const uint64_t StartAddr = 0x1000;
90   const uint64_t EndAddr = 0x1100;
91   const uint64_t Size = EndAddr - StartAddr;
92   const uint32_t NameOffset = 30;
93   FunctionInfo FI(StartAddr, Size, NameOffset);
94   EXPECT_TRUE(FI.isValid());
95   EXPECT_FALSE(FI.hasRichInfo());
96   EXPECT_EQ(FI.startAddress(), StartAddr);
97   EXPECT_EQ(FI.endAddress(), EndAddr);
98   EXPECT_EQ(FI.size(), Size);
99   const uint32_t FileIdx = 1;
100   const uint32_t Line = 12;
101   FI.OptLineTable = LineTable();
102   FI.OptLineTable->push(LineEntry(StartAddr,FileIdx,Line));
103   EXPECT_TRUE(FI.hasRichInfo());
104   FI.clear();
105   EXPECT_FALSE(FI.isValid());
106   EXPECT_FALSE(FI.hasRichInfo());
107 
108   FunctionInfo A1(0x1000, 0x100, NameOffset);
109   FunctionInfo A2(0x1000, 0x100, NameOffset);
110   FunctionInfo B;
111   // Check == operator
112   EXPECT_EQ(A1, A2);
113   // Make sure things are not equal if they only differ by start address.
114   B = A2;
115   B.Range = {0x1001, B.endAddress()};
116   EXPECT_NE(B, A2);
117   // Make sure things are not equal if they only differ by size.
118   B = A2;
119   B.Range = {B.startAddress(), B.startAddress() + 0x101};
120   EXPECT_NE(B, A2);
121   // Make sure things are not equal if they only differ by name.
122   B = A2;
123   B.Name = 60;
124   EXPECT_NE(B, A2);
125   // Check < operator.
126   // Check less than where address differs.
127   B = A2;
128   B.Range = {A2.startAddress() + 0x1000, A2.endAddress() + 0x1000};
129   EXPECT_LT(A1, B);
130 
131   // We use the < operator to take a variety of different FunctionInfo
132   // structs from a variety of sources: symtab, debug info, runtime info
133   // and we sort them and want the sorting to allow us to quickly get the
134   // best version of a function info.
135   FunctionInfo FISymtab(StartAddr, Size, NameOffset);
136   FunctionInfo FIWithLines(StartAddr, Size, NameOffset);
137   FIWithLines.OptLineTable = LineTable();
138   FIWithLines.OptLineTable->push(LineEntry(StartAddr,FileIdx,Line));
139   // Test that a FunctionInfo with just a name and size is less than one
140   // that has name, size and any number of line table entries
141   EXPECT_LT(FISymtab, FIWithLines);
142 
143   FunctionInfo FIWithLinesAndInline = FIWithLines;
144   FIWithLinesAndInline.Inline = InlineInfo();
145   FIWithLinesAndInline.Inline->Ranges.insert(
146       AddressRange(StartAddr, StartAddr + 0x10));
147   // Test that a FunctionInfo with name, size, and line entries is less than
148   // the same one with valid inline info
149   EXPECT_LT(FIWithLines, FIWithLinesAndInline);
150 
151   // Test if we have an entry with lines and one with more lines for the same
152   // range, the ones with more lines is greater than the one with less.
153   FunctionInfo FIWithMoreLines = FIWithLines;
154   FIWithMoreLines.OptLineTable->push(LineEntry(StartAddr,FileIdx,Line+5));
155   EXPECT_LT(FIWithLines, FIWithMoreLines);
156 
157   // Test that if we have the same number of lines we compare the line entries
158   // in the FunctionInfo.OptLineTable.Lines vector.
159   FunctionInfo FIWithLinesWithHigherAddress = FIWithLines;
160   FIWithLinesWithHigherAddress.OptLineTable->get(0).Addr += 0x10;
161   EXPECT_LT(FIWithLines, FIWithLinesWithHigherAddress);
162 }
163 
164 static void TestFunctionInfoDecodeError(llvm::support::endianness ByteOrder,
165                                         StringRef Bytes,
166                                         const uint64_t BaseAddr,
167                                         std::string ExpectedErrorMsg) {
168   uint8_t AddressSize = 4;
169   DataExtractor Data(Bytes, ByteOrder == llvm::support::little, AddressSize);
170   llvm::Expected<FunctionInfo> Decoded = FunctionInfo::decode(Data, BaseAddr);
171   // Make sure decoding fails.
172   ASSERT_FALSE((bool)Decoded);
173   // Make sure decoded object is the same as the one we encoded.
174   checkError(ExpectedErrorMsg, Decoded.takeError());
175 }
176 
177 TEST(GSYMTest, TestFunctionInfoDecodeErrors) {
178   // Test decoding FunctionInfo objects that ensure we report an appropriate
179   // error message.
180   const llvm::support::endianness ByteOrder = llvm::support::little;
181   SmallString<512> Str;
182   raw_svector_ostream OutStrm(Str);
183   FileWriter FW(OutStrm, ByteOrder);
184   const uint64_t BaseAddr = 0x100;
185   TestFunctionInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
186       "0x00000000: missing FunctionInfo Size");
187   FW.writeU32(0x100); // Function size.
188   TestFunctionInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
189       "0x00000004: missing FunctionInfo Name");
190   // Write out an invalid Name string table offset of zero.
191   FW.writeU32(0);
192   TestFunctionInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
193       "0x00000004: invalid FunctionInfo Name value 0x00000000");
194   // Modify the Name to be 0x00000001, which is a valid value.
195   FW.fixup32(0x00000001, 4);
196   TestFunctionInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
197       "0x00000008: missing FunctionInfo InfoType value");
198   auto FixupOffset = FW.tell();
199   FW.writeU32(1); // InfoType::LineTableInfo.
200   TestFunctionInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
201       "0x0000000c: missing FunctionInfo InfoType length");
202   FW.fixup32(4, FixupOffset); // Write an invalid InfoType enumeration value
203   FW.writeU32(0); // LineTableInfo InfoType data length.
204   TestFunctionInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
205       "0x00000008: unsupported InfoType 4");
206 }
207 
208 static void TestFunctionInfoEncodeError(llvm::support::endianness ByteOrder,
209                                       const FunctionInfo &FI,
210                                       std::string ExpectedErrorMsg) {
211   SmallString<512> Str;
212   raw_svector_ostream OutStrm(Str);
213   FileWriter FW(OutStrm, ByteOrder);
214   Expected<uint64_t> ExpectedOffset = FI.encode(FW);
215   ASSERT_FALSE(ExpectedOffset);
216   checkError(ExpectedErrorMsg, ExpectedOffset.takeError());
217 }
218 
219 TEST(GSYMTest, TestFunctionInfoEncodeErrors) {
220   const uint64_t FuncAddr = 0x1000;
221   const uint64_t FuncSize = 0x100;
222   const uint32_t InvalidName = 0;
223   const uint32_t ValidName = 1;
224   FunctionInfo InvalidNameFI(FuncAddr, FuncSize, InvalidName);
225   TestFunctionInfoEncodeError(llvm::support::little, InvalidNameFI,
226       "attempted to encode invalid FunctionInfo object");
227 
228   FunctionInfo InvalidLineTableFI(FuncAddr, FuncSize, ValidName);
229   // Empty line tables are not valid. Verify if the encoding of anything
230   // in our line table fails, that we see get the error propagated.
231   InvalidLineTableFI.OptLineTable = LineTable();
232   TestFunctionInfoEncodeError(llvm::support::little, InvalidLineTableFI,
233       "attempted to encode invalid LineTable object");
234 
235   FunctionInfo InvalidInlineInfoFI(FuncAddr, FuncSize, ValidName);
236   // Empty line tables are not valid. Verify if the encoding of anything
237   // in our line table fails, that we see get the error propagated.
238   InvalidInlineInfoFI.Inline = InlineInfo();
239   TestFunctionInfoEncodeError(llvm::support::little, InvalidInlineInfoFI,
240       "attempted to encode invalid InlineInfo object");
241 }
242 
243 static void TestFunctionInfoEncodeDecode(llvm::support::endianness ByteOrder,
244                                          const FunctionInfo &FI) {
245   // Test encoding and decoding FunctionInfo objects.
246   SmallString<512> Str;
247   raw_svector_ostream OutStrm(Str);
248   FileWriter FW(OutStrm, ByteOrder);
249   llvm::Expected<uint64_t> ExpectedOffset = FI.encode(FW);
250   ASSERT_TRUE(bool(ExpectedOffset));
251   // Verify we got the encoded offset back from the encode function.
252   ASSERT_EQ(ExpectedOffset.get(), 0ULL);
253   std::string Bytes(OutStrm.str());
254   uint8_t AddressSize = 4;
255   DataExtractor Data(Bytes, ByteOrder == llvm::support::little, AddressSize);
256   llvm::Expected<FunctionInfo> Decoded =
257       FunctionInfo::decode(Data, FI.Range.start());
258   // Make sure decoding succeeded.
259   ASSERT_TRUE((bool)Decoded);
260   // Make sure decoded object is the same as the one we encoded.
261   EXPECT_EQ(FI, Decoded.get());
262 }
263 
264 static void AddLines(uint64_t FuncAddr, uint32_t FileIdx, FunctionInfo &FI) {
265     FI.OptLineTable = LineTable();
266     LineEntry Line0(FuncAddr + 0x000, FileIdx, 10);
267     LineEntry Line1(FuncAddr + 0x010, FileIdx, 11);
268     LineEntry Line2(FuncAddr + 0x100, FileIdx, 1000);
269     FI.OptLineTable->push(Line0);
270     FI.OptLineTable->push(Line1);
271     FI.OptLineTable->push(Line2);
272 }
273 
274 
275 static void AddInline(uint64_t FuncAddr, uint64_t FuncSize, FunctionInfo &FI) {
276     FI.Inline = InlineInfo();
277     FI.Inline->Ranges.insert(AddressRange(FuncAddr, FuncAddr + FuncSize));
278     InlineInfo Inline1;
279     Inline1.Ranges.insert(AddressRange(FuncAddr + 0x10, FuncAddr + 0x30));
280     Inline1.Name = 1;
281     Inline1.CallFile = 1;
282     Inline1.CallLine = 11;
283     FI.Inline->Children.push_back(Inline1);
284 }
285 
286 TEST(GSYMTest, TestFunctionInfoEncoding) {
287   constexpr uint64_t FuncAddr = 0x1000;
288   constexpr uint64_t FuncSize = 0x100;
289   constexpr uint32_t FuncName = 1;
290   constexpr uint32_t FileIdx = 1;
291   // Make sure that we can encode and decode a FunctionInfo with no line table
292   // or inline info.
293   FunctionInfo FI(FuncAddr, FuncSize, FuncName);
294   TestFunctionInfoEncodeDecode(llvm::support::little, FI);
295   TestFunctionInfoEncodeDecode(llvm::support::big, FI);
296 
297   // Make sure that we can encode and decode a FunctionInfo with a line table
298   // and no inline info.
299   FunctionInfo FILines(FuncAddr, FuncSize, FuncName);
300   AddLines(FuncAddr, FileIdx, FILines);
301   TestFunctionInfoEncodeDecode(llvm::support::little, FILines);
302   TestFunctionInfoEncodeDecode(llvm::support::big, FILines);
303 
304   // Make sure that we can encode and decode a FunctionInfo with no line table
305   // and with inline info.
306   FunctionInfo FIInline(FuncAddr, FuncSize, FuncName);
307   AddInline(FuncAddr, FuncSize, FIInline);
308   TestFunctionInfoEncodeDecode(llvm::support::little, FIInline);
309   TestFunctionInfoEncodeDecode(llvm::support::big, FIInline);
310 
311   // Make sure that we can encode and decode a FunctionInfo with no line table
312   // and with inline info.
313   FunctionInfo FIBoth(FuncAddr, FuncSize, FuncName);
314   AddLines(FuncAddr, FileIdx, FIBoth);
315   AddInline(FuncAddr, FuncSize, FIBoth);
316   TestFunctionInfoEncodeDecode(llvm::support::little, FIBoth);
317   TestFunctionInfoEncodeDecode(llvm::support::big, FIBoth);
318 }
319 
320 static void TestInlineInfoEncodeDecode(llvm::support::endianness ByteOrder,
321                                        const InlineInfo &Inline) {
322   // Test encoding and decoding InlineInfo objects
323   SmallString<512> Str;
324   raw_svector_ostream OutStrm(Str);
325   FileWriter FW(OutStrm, ByteOrder);
326   const uint64_t BaseAddr = Inline.Ranges[0].start();
327   llvm::Error Err = Inline.encode(FW, BaseAddr);
328   ASSERT_FALSE(Err);
329   std::string Bytes(OutStrm.str());
330   uint8_t AddressSize = 4;
331   DataExtractor Data(Bytes, ByteOrder == llvm::support::little, AddressSize);
332   llvm::Expected<InlineInfo> Decoded = InlineInfo::decode(Data, BaseAddr);
333   // Make sure decoding succeeded.
334   ASSERT_TRUE((bool)Decoded);
335   // Make sure decoded object is the same as the one we encoded.
336   EXPECT_EQ(Inline, Decoded.get());
337 }
338 
339 static void TestInlineInfoDecodeError(llvm::support::endianness ByteOrder,
340                                       StringRef Bytes, const uint64_t BaseAddr,
341                                       std::string ExpectedErrorMsg) {
342   uint8_t AddressSize = 4;
343   DataExtractor Data(Bytes, ByteOrder == llvm::support::little, AddressSize);
344   llvm::Expected<InlineInfo> Decoded = InlineInfo::decode(Data, BaseAddr);
345   // Make sure decoding fails.
346   ASSERT_FALSE((bool)Decoded);
347   // Make sure decoded object is the same as the one we encoded.
348   checkError(ExpectedErrorMsg, Decoded.takeError());
349 }
350 
351 static void TestInlineInfoEncodeError(llvm::support::endianness ByteOrder,
352                                       const InlineInfo &Inline,
353                                       std::string ExpectedErrorMsg) {
354   SmallString<512> Str;
355   raw_svector_ostream OutStrm(Str);
356   FileWriter FW(OutStrm, ByteOrder);
357   const uint64_t BaseAddr =
358       Inline.Ranges.empty() ? 0 : Inline.Ranges[0].start();
359   llvm::Error Err = Inline.encode(FW, BaseAddr);
360   checkError(ExpectedErrorMsg, std::move(Err));
361 }
362 
363 TEST(GSYMTest, TestInlineInfo) {
364   // Test InlineInfo structs.
365   InlineInfo II;
366   EXPECT_FALSE(II.isValid());
367   II.Ranges.insert(AddressRange(0x1000, 0x2000));
368   // Make sure InlineInfo in valid with just an address range since
369   // top level InlineInfo objects have ranges with no name, call file
370   // or call line
371   EXPECT_TRUE(II.isValid());
372   // Make sure InlineInfo isn't after being cleared.
373   II.clear();
374   EXPECT_FALSE(II.isValid());
375 
376   // Create an InlineInfo that contains the following data. The
377   // indentation of the address range indicates the parent child
378   // relationships of the InlineInfo objects:
379   //
380   // Variable    Range and values
381   // =========== ====================================================
382   // Root        [0x100-0x200) (no name, file, or line)
383   // Inline1       [0x150-0x160) Name = 1, File = 1, Line = 11
384   // Inline1Sub1     [0x152-0x155) Name = 2, File = 2, Line = 22
385   // Inline1Sub2     [0x157-0x158) Name = 3, File = 3, Line = 33
386   InlineInfo Root;
387   Root.Ranges.insert(AddressRange(0x100, 0x200));
388   InlineInfo Inline1;
389   Inline1.Ranges.insert(AddressRange(0x150, 0x160));
390   Inline1.Name = 1;
391   Inline1.CallFile = 1;
392   Inline1.CallLine = 11;
393   InlineInfo Inline1Sub1;
394   Inline1Sub1.Ranges.insert(AddressRange(0x152, 0x155));
395   Inline1Sub1.Name = 2;
396   Inline1Sub1.CallFile = 2;
397   Inline1Sub1.CallLine = 22;
398   InlineInfo Inline1Sub2;
399   Inline1Sub2.Ranges.insert(AddressRange(0x157, 0x158));
400   Inline1Sub2.Name = 3;
401   Inline1Sub2.CallFile = 3;
402   Inline1Sub2.CallLine = 33;
403   Inline1.Children.push_back(Inline1Sub1);
404   Inline1.Children.push_back(Inline1Sub2);
405   Root.Children.push_back(Inline1);
406 
407   // Make sure an address that is out of range won't match
408   EXPECT_FALSE(Root.getInlineStack(0x50));
409 
410   // Verify that we get no inline stacks for addresses out of [0x100-0x200)
411   EXPECT_FALSE(Root.getInlineStack(Root.Ranges[0].start() - 1));
412   EXPECT_FALSE(Root.getInlineStack(Root.Ranges[0].end()));
413 
414   // Verify we get no inline stack entries for addresses that are in
415   // [0x100-0x200) but not in [0x150-0x160)
416   EXPECT_FALSE(Root.getInlineStack(Inline1.Ranges[0].start() - 1));
417   EXPECT_FALSE(Root.getInlineStack(Inline1.Ranges[0].end()));
418 
419   // Verify we get one inline stack entry for addresses that are in
420   // [[0x150-0x160)) but not in [0x152-0x155) or [0x157-0x158)
421   auto InlineInfos = Root.getInlineStack(Inline1.Ranges[0].start());
422   ASSERT_TRUE(InlineInfos);
423   ASSERT_EQ(InlineInfos->size(), 1u);
424   ASSERT_EQ(*InlineInfos->at(0), Inline1);
425   InlineInfos = Root.getInlineStack(Inline1.Ranges[0].end() - 1);
426   EXPECT_TRUE(InlineInfos);
427   ASSERT_EQ(InlineInfos->size(), 1u);
428   ASSERT_EQ(*InlineInfos->at(0), Inline1);
429 
430   // Verify we get two inline stack entries for addresses that are in
431   // [0x152-0x155)
432   InlineInfos = Root.getInlineStack(Inline1Sub1.Ranges[0].start());
433   EXPECT_TRUE(InlineInfos);
434   ASSERT_EQ(InlineInfos->size(), 2u);
435   ASSERT_EQ(*InlineInfos->at(0), Inline1Sub1);
436   ASSERT_EQ(*InlineInfos->at(1), Inline1);
437   InlineInfos = Root.getInlineStack(Inline1Sub1.Ranges[0].end() - 1);
438   EXPECT_TRUE(InlineInfos);
439   ASSERT_EQ(InlineInfos->size(), 2u);
440   ASSERT_EQ(*InlineInfos->at(0), Inline1Sub1);
441   ASSERT_EQ(*InlineInfos->at(1), Inline1);
442 
443   // Verify we get two inline stack entries for addresses that are in
444   // [0x157-0x158)
445   InlineInfos = Root.getInlineStack(Inline1Sub2.Ranges[0].start());
446   EXPECT_TRUE(InlineInfos);
447   ASSERT_EQ(InlineInfos->size(), 2u);
448   ASSERT_EQ(*InlineInfos->at(0), Inline1Sub2);
449   ASSERT_EQ(*InlineInfos->at(1), Inline1);
450   InlineInfos = Root.getInlineStack(Inline1Sub2.Ranges[0].end() - 1);
451   EXPECT_TRUE(InlineInfos);
452   ASSERT_EQ(InlineInfos->size(), 2u);
453   ASSERT_EQ(*InlineInfos->at(0), Inline1Sub2);
454   ASSERT_EQ(*InlineInfos->at(1), Inline1);
455 
456   // Test encoding and decoding InlineInfo objects
457   TestInlineInfoEncodeDecode(llvm::support::little, Root);
458   TestInlineInfoEncodeDecode(llvm::support::big, Root);
459 }
460 
461 TEST(GSYMTest, TestInlineInfoEncodeErrors) {
462   // Test InlineInfo encoding errors.
463 
464   // Test that we get an error when trying to encode an InlineInfo object
465   // that has no ranges.
466   InlineInfo Empty;
467   std::string EmptyErr("attempted to encode invalid InlineInfo object");
468   TestInlineInfoEncodeError(llvm::support::little, Empty, EmptyErr);
469   TestInlineInfoEncodeError(llvm::support::big, Empty, EmptyErr);
470 
471   // Verify that we get an error trying to encode an InlineInfo object that has
472   // a child InlineInfo that has no ranges.
473   InlineInfo ContainsEmpty;
474   ContainsEmpty.Ranges.insert({0x100, 0x200});
475   ContainsEmpty.Children.push_back(Empty);
476   TestInlineInfoEncodeError(llvm::support::little, ContainsEmpty, EmptyErr);
477   TestInlineInfoEncodeError(llvm::support::big, ContainsEmpty, EmptyErr);
478 
479   // Verify that we get an error trying to encode an InlineInfo object that has
480   // a child whose address range is not contained in the parent address range.
481   InlineInfo ChildNotContained;
482   std::string ChildNotContainedErr("child range not contained in parent");
483   ChildNotContained.Ranges.insert({0x100, 0x200});
484   InlineInfo ChildNotContainedChild;
485   ChildNotContainedChild.Ranges.insert({0x200, 0x300});
486   ChildNotContained.Children.push_back(ChildNotContainedChild);
487   TestInlineInfoEncodeError(llvm::support::little, ChildNotContained,
488                             ChildNotContainedErr);
489   TestInlineInfoEncodeError(llvm::support::big, ChildNotContained,
490                             ChildNotContainedErr);
491 
492 }
493 
494 TEST(GSYMTest, TestInlineInfoDecodeErrors) {
495   // Test decoding InlineInfo objects that ensure we report an appropriate
496   // error message.
497   const llvm::support::endianness ByteOrder = llvm::support::little;
498   SmallString<512> Str;
499   raw_svector_ostream OutStrm(Str);
500   FileWriter FW(OutStrm, ByteOrder);
501   const uint64_t BaseAddr = 0x100;
502   TestInlineInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
503       "0x00000000: missing InlineInfo address ranges data");
504   AddressRanges Ranges;
505   Ranges.insert({BaseAddr, BaseAddr+0x100});
506   encodeRanges(Ranges, FW, BaseAddr);
507   TestInlineInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
508       "0x00000004: missing InlineInfo uint8_t indicating children");
509   FW.writeU8(0);
510   TestInlineInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
511       "0x00000005: missing InlineInfo uint32_t for name");
512   FW.writeU32(0);
513   TestInlineInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
514       "0x00000009: missing ULEB128 for InlineInfo call file");
515   FW.writeU8(0);
516   TestInlineInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
517       "0x0000000a: missing ULEB128 for InlineInfo call line");
518 }
519 
520 TEST(GSYMTest, TestLineEntry) {
521   // test llvm::gsym::LineEntry structs.
522   const uint64_t ValidAddr = 0x1000;
523   const uint64_t InvalidFileIdx = 0;
524   const uint32_t ValidFileIdx = 1;
525   const uint32_t ValidLine = 5;
526 
527   LineEntry Invalid;
528   EXPECT_FALSE(Invalid.isValid());
529   // Make sure that an entry is invalid if it has a bad file index.
530   LineEntry BadFile(ValidAddr, InvalidFileIdx, ValidLine);
531   EXPECT_FALSE(BadFile.isValid());
532   // Test operators
533   LineEntry E1(ValidAddr, ValidFileIdx, ValidLine);
534   LineEntry E2(ValidAddr, ValidFileIdx, ValidLine);
535   LineEntry DifferentAddr(ValidAddr + 1, ValidFileIdx, ValidLine);
536   LineEntry DifferentFile(ValidAddr, ValidFileIdx + 1, ValidLine);
537   LineEntry DifferentLine(ValidAddr, ValidFileIdx, ValidLine + 1);
538   EXPECT_TRUE(E1.isValid());
539   EXPECT_EQ(E1, E2);
540   EXPECT_NE(E1, DifferentAddr);
541   EXPECT_NE(E1, DifferentFile);
542   EXPECT_NE(E1, DifferentLine);
543   EXPECT_LT(E1, DifferentAddr);
544 }
545 
546 TEST(GSYMTest, TestStringTable) {
547   StringTable StrTab(StringRef("\0Hello\0World\0", 13));
548   // Test extracting strings from a string table.
549   EXPECT_EQ(StrTab.getString(0), "");
550   EXPECT_EQ(StrTab.getString(1), "Hello");
551   EXPECT_EQ(StrTab.getString(7), "World");
552   EXPECT_EQ(StrTab.getString(8), "orld");
553   // Test pointing to last NULL terminator gets empty string.
554   EXPECT_EQ(StrTab.getString(12), "");
555   // Test pointing to past end gets empty string.
556   EXPECT_EQ(StrTab.getString(13), "");
557 }
558 
559 static void TestFileWriterHelper(llvm::support::endianness ByteOrder) {
560   SmallString<512> Str;
561   raw_svector_ostream OutStrm(Str);
562   FileWriter FW(OutStrm, ByteOrder);
563   const int64_t MinSLEB = INT64_MIN;
564   const int64_t MaxSLEB = INT64_MAX;
565   const uint64_t MinULEB = 0;
566   const uint64_t MaxULEB = UINT64_MAX;
567   const uint8_t U8 = 0x10;
568   const uint16_t U16 = 0x1122;
569   const uint32_t U32 = 0x12345678;
570   const uint64_t U64 = 0x33445566778899aa;
571   const char *Hello = "hello";
572   FW.writeU8(U8);
573   FW.writeU16(U16);
574   FW.writeU32(U32);
575   FW.writeU64(U64);
576   FW.alignTo(16);
577   const off_t FixupOffset = FW.tell();
578   FW.writeU32(0);
579   FW.writeSLEB(MinSLEB);
580   FW.writeSLEB(MaxSLEB);
581   FW.writeULEB(MinULEB);
582   FW.writeULEB(MaxULEB);
583   FW.writeNullTerminated(Hello);
584   // Test Seek, Tell using Fixup32.
585   FW.fixup32(U32, FixupOffset);
586 
587   std::string Bytes(OutStrm.str());
588   uint8_t AddressSize = 4;
589   DataExtractor Data(Bytes, ByteOrder == llvm::support::little, AddressSize);
590   uint64_t Offset = 0;
591   EXPECT_EQ(Data.getU8(&Offset), U8);
592   EXPECT_EQ(Data.getU16(&Offset), U16);
593   EXPECT_EQ(Data.getU32(&Offset), U32);
594   EXPECT_EQ(Data.getU64(&Offset), U64);
595   Offset = alignTo(Offset, 16);
596   EXPECT_EQ(Data.getU32(&Offset), U32);
597   EXPECT_EQ(Data.getSLEB128(&Offset), MinSLEB);
598   EXPECT_EQ(Data.getSLEB128(&Offset), MaxSLEB);
599   EXPECT_EQ(Data.getULEB128(&Offset), MinULEB);
600   EXPECT_EQ(Data.getULEB128(&Offset), MaxULEB);
601   EXPECT_EQ(Data.getCStrRef(&Offset), StringRef(Hello));
602 }
603 
604 TEST(GSYMTest, TestFileWriter) {
605   TestFileWriterHelper(llvm::support::little);
606   TestFileWriterHelper(llvm::support::big);
607 }
608 
609 TEST(GSYMTest, TestAddressRangeEncodeDecode) {
610   // Test encoding and decoding AddressRange objects. AddressRange objects
611   // are always stored as offsets from the a base address. The base address
612   // is the FunctionInfo's base address for function level ranges, and is
613   // the base address of the parent range for subranges.
614   SmallString<512> Str;
615   raw_svector_ostream OutStrm(Str);
616   const auto ByteOrder = llvm::support::endian::system_endianness();
617   FileWriter FW(OutStrm, ByteOrder);
618   const uint64_t BaseAddr = 0x1000;
619   const AddressRange Range1(0x1000, 0x1010);
620   const AddressRange Range2(0x1020, 0x1030);
621   encodeRange(Range1, FW, BaseAddr);
622   encodeRange(Range2, FW, BaseAddr);
623   std::string Bytes(OutStrm.str());
624   uint8_t AddressSize = 4;
625   DataExtractor Data(Bytes, ByteOrder == llvm::support::little, AddressSize);
626 
627   AddressRange DecodedRange1, DecodedRange2;
628   uint64_t Offset = 0;
629   DecodedRange1 = decodeRange(Data, BaseAddr, Offset);
630   DecodedRange2 = decodeRange(Data, BaseAddr, Offset);
631   EXPECT_EQ(Range1, DecodedRange1);
632   EXPECT_EQ(Range2, DecodedRange2);
633 }
634 
635 static void TestAddressRangeEncodeDecodeHelper(const AddressRanges &Ranges,
636                                                const uint64_t BaseAddr) {
637   SmallString<512> Str;
638   raw_svector_ostream OutStrm(Str);
639   const auto ByteOrder = llvm::support::endian::system_endianness();
640   FileWriter FW(OutStrm, ByteOrder);
641   encodeRanges(Ranges, FW, BaseAddr);
642 
643   std::string Bytes(OutStrm.str());
644   uint8_t AddressSize = 4;
645   DataExtractor Data(Bytes, ByteOrder == llvm::support::little, AddressSize);
646 
647   AddressRanges DecodedRanges;
648   uint64_t Offset = 0;
649   decodeRanges(DecodedRanges, Data, BaseAddr, Offset);
650   EXPECT_EQ(Ranges, DecodedRanges);
651 }
652 
653 TEST(GSYMTest, TestAddressRangesEncodeDecode) {
654   // Test encoding and decoding AddressRanges. AddressRanges objects contain
655   // ranges that are stored as offsets from the a base address. The base address
656   // is the FunctionInfo's base address for function level ranges, and is the
657   // base address of the parent range for subranges.
658   const uint64_t BaseAddr = 0x1000;
659 
660   // Test encoding and decoding with no ranges.
661   AddressRanges Ranges;
662   TestAddressRangeEncodeDecodeHelper(Ranges, BaseAddr);
663 
664   // Test encoding and decoding with 1 range.
665   Ranges.insert(AddressRange(0x1000, 0x1010));
666   TestAddressRangeEncodeDecodeHelper(Ranges, BaseAddr);
667 
668   // Test encoding and decoding with multiple ranges.
669   Ranges.insert(AddressRange(0x1020, 0x1030));
670   Ranges.insert(AddressRange(0x1050, 0x1070));
671   TestAddressRangeEncodeDecodeHelper(Ranges, BaseAddr);
672 }
673 
674 static void TestLineTableHelper(llvm::support::endianness ByteOrder,
675                                 const LineTable &LT) {
676   SmallString<512> Str;
677   raw_svector_ostream OutStrm(Str);
678   FileWriter FW(OutStrm, ByteOrder);
679   const uint64_t BaseAddr = LT[0].Addr;
680   llvm::Error Err = LT.encode(FW, BaseAddr);
681   ASSERT_FALSE(Err);
682   std::string Bytes(OutStrm.str());
683   uint8_t AddressSize = 4;
684   DataExtractor Data(Bytes, ByteOrder == llvm::support::little, AddressSize);
685   llvm::Expected<LineTable> Decoded = LineTable::decode(Data, BaseAddr);
686   // Make sure decoding succeeded.
687   ASSERT_TRUE((bool)Decoded);
688   // Make sure decoded object is the same as the one we encoded.
689   EXPECT_EQ(LT, Decoded.get());
690 }
691 
692 TEST(GSYMTest, TestLineTable) {
693   const uint64_t StartAddr = 0x1000;
694   const uint32_t FileIdx = 1;
695   LineTable LT;
696   LineEntry Line0(StartAddr+0x000, FileIdx, 10);
697   LineEntry Line1(StartAddr+0x010, FileIdx, 11);
698   LineEntry Line2(StartAddr+0x100, FileIdx, 1000);
699   ASSERT_TRUE(LT.empty());
700   ASSERT_EQ(LT.size(), (size_t)0);
701   LT.push(Line0);
702   ASSERT_EQ(LT.size(), (size_t)1);
703   LT.push(Line1);
704   LT.push(Line2);
705   LT.push(LineEntry(StartAddr+0x120, FileIdx, 900));
706   LT.push(LineEntry(StartAddr+0x120, FileIdx, 2000));
707   LT.push(LineEntry(StartAddr+0x121, FileIdx, 2001));
708   LT.push(LineEntry(StartAddr+0x122, FileIdx, 2002));
709   LT.push(LineEntry(StartAddr+0x123, FileIdx, 2003));
710   ASSERT_FALSE(LT.empty());
711   ASSERT_EQ(LT.size(), (size_t)8);
712   // Test operator[].
713   ASSERT_EQ(LT[0], Line0);
714   ASSERT_EQ(LT[1], Line1);
715   ASSERT_EQ(LT[2], Line2);
716 
717   // Test encoding and decoding line tables.
718   TestLineTableHelper(llvm::support::little, LT);
719   TestLineTableHelper(llvm::support::big, LT);
720 
721   // Verify the clear method works as expected.
722   LT.clear();
723   ASSERT_TRUE(LT.empty());
724   ASSERT_EQ(LT.size(), (size_t)0);
725 
726   LineTable LT1;
727   LineTable LT2;
728 
729   // Test that two empty line tables are equal and neither are less than
730   // each other.
731   ASSERT_EQ(LT1, LT2);
732   ASSERT_FALSE(LT1 < LT1);
733   ASSERT_FALSE(LT1 < LT2);
734   ASSERT_FALSE(LT2 < LT1);
735   ASSERT_FALSE(LT2 < LT2);
736 
737   // Test that a line table with less number of line entries is less than a
738   // line table with more line entries and that they are not equal.
739   LT2.push(Line0);
740   ASSERT_LT(LT1, LT2);
741   ASSERT_NE(LT1, LT2);
742 
743   // Test that two line tables with the same entries are equal.
744   LT1.push(Line0);
745   ASSERT_EQ(LT1, LT2);
746   ASSERT_FALSE(LT1 < LT2);
747   ASSERT_FALSE(LT2 < LT2);
748 }
749 
750 static void TestLineTableDecodeError(llvm::support::endianness ByteOrder,
751                                      StringRef Bytes, const uint64_t BaseAddr,
752                                      std::string ExpectedErrorMsg) {
753   uint8_t AddressSize = 4;
754   DataExtractor Data(Bytes, ByteOrder == llvm::support::little, AddressSize);
755   llvm::Expected<LineTable> Decoded = LineTable::decode(Data, BaseAddr);
756   // Make sure decoding fails.
757   ASSERT_FALSE((bool)Decoded);
758   // Make sure decoded object is the same as the one we encoded.
759   checkError(ExpectedErrorMsg, Decoded.takeError());
760 }
761 
762 TEST(GSYMTest, TestLineTableDecodeErrors) {
763   // Test decoding InlineInfo objects that ensure we report an appropriate
764   // error message.
765   const llvm::support::endianness ByteOrder = llvm::support::little;
766   SmallString<512> Str;
767   raw_svector_ostream OutStrm(Str);
768   FileWriter FW(OutStrm, ByteOrder);
769   const uint64_t BaseAddr = 0x100;
770   TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
771       "0x00000000: missing LineTable MinDelta");
772   FW.writeU8(1); // MinDelta (ULEB)
773   TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
774       "0x00000001: missing LineTable MaxDelta");
775   FW.writeU8(10); // MaxDelta (ULEB)
776   TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
777       "0x00000002: missing LineTable FirstLine");
778   FW.writeU8(20); // FirstLine (ULEB)
779   TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
780       "0x00000003: EOF found before EndSequence");
781   // Test a SetFile with the argument missing from the stream
782   FW.writeU8(1); // SetFile opcode (uint8_t)
783   TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
784       "0x00000004: EOF found before SetFile value");
785   FW.writeU8(5); // SetFile value as index (ULEB)
786   // Test a AdvancePC with the argument missing from the stream
787   FW.writeU8(2); // AdvancePC opcode (uint8_t)
788   TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
789       "0x00000006: EOF found before AdvancePC value");
790   FW.writeU8(20); // AdvancePC value as offset (ULEB)
791   // Test a AdvancePC with the argument missing from the stream
792   FW.writeU8(3); // AdvanceLine opcode (uint8_t)
793   TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
794       "0x00000008: EOF found before AdvanceLine value");
795   FW.writeU8(20); // AdvanceLine value as offset (LLEB)
796 }
797 
798 TEST(GSYMTest, TestLineTableEncodeErrors) {
799   const uint64_t BaseAddr = 0x1000;
800   const uint32_t FileIdx = 1;
801   const llvm::support::endianness ByteOrder = llvm::support::little;
802   SmallString<512> Str;
803   raw_svector_ostream OutStrm(Str);
804   FileWriter FW(OutStrm, ByteOrder);
805   LineTable LT;
806   checkError("attempted to encode invalid LineTable object",
807              LT.encode(FW, BaseAddr));
808 
809   // Try to encode a line table where a line entry has an address that is less
810   // than BaseAddr and verify we get an appropriate error.
811   LineEntry Line0(BaseAddr+0x000, FileIdx, 10);
812   LineEntry Line1(BaseAddr+0x010, FileIdx, 11);
813   LT.push(Line0);
814   LT.push(Line1);
815   checkError("LineEntry has address 0x1000 which is less than the function "
816              "start address 0x1010", LT.encode(FW, BaseAddr+0x10));
817   LT.clear();
818 
819   // Try to encode a line table where a line entries  has an address that is less
820   // than BaseAddr and verify we get an appropriate error.
821   LT.push(Line1);
822   LT.push(Line0);
823   checkError("LineEntry in LineTable not in ascending order",
824              LT.encode(FW, BaseAddr));
825   LT.clear();
826 }
827 
828 static void TestHeaderEncodeError(const Header &H,
829                                   std::string ExpectedErrorMsg) {
830   const support::endianness ByteOrder = llvm::support::little;
831   SmallString<512> Str;
832   raw_svector_ostream OutStrm(Str);
833   FileWriter FW(OutStrm, ByteOrder);
834   llvm::Error Err = H.encode(FW);
835   checkError(ExpectedErrorMsg, std::move(Err));
836 }
837 
838 static void TestHeaderDecodeError(StringRef Bytes,
839                                   std::string ExpectedErrorMsg) {
840   const support::endianness ByteOrder = llvm::support::little;
841   uint8_t AddressSize = 4;
842   DataExtractor Data(Bytes, ByteOrder == llvm::support::little, AddressSize);
843   llvm::Expected<Header> Decoded = Header::decode(Data);
844   // Make sure decoding fails.
845   ASSERT_FALSE((bool)Decoded);
846   // Make sure decoded object is the same as the one we encoded.
847   checkError(ExpectedErrorMsg, Decoded.takeError());
848 }
849 
850 // Populate a GSYM header with valid values.
851 static void InitHeader(Header &H) {
852   H.Magic = GSYM_MAGIC;
853   H.Version = GSYM_VERSION;
854   H.AddrOffSize = 4;
855   H.UUIDSize = 16;
856   H.BaseAddress = 0x1000;
857   H.NumAddresses = 1;
858   H.StrtabOffset= 0x2000;
859   H.StrtabSize = 0x1000;
860   for (size_t i=0; i<GSYM_MAX_UUID_SIZE; ++i) {
861     if (i < H.UUIDSize)
862       H.UUID[i] = i;
863     else
864       H.UUID[i] = 0;
865   }
866 }
867 
868 TEST(GSYMTest, TestHeaderEncodeErrors) {
869   Header H;
870   InitHeader(H);
871   H.Magic = 12;
872   TestHeaderEncodeError(H, "invalid GSYM magic 0x0000000c");
873   InitHeader(H);
874   H.Version = 12;
875   TestHeaderEncodeError(H, "unsupported GSYM version 12");
876   InitHeader(H);
877   H.AddrOffSize = 12;
878   TestHeaderEncodeError(H, "invalid address offset size 12");
879   InitHeader(H);
880   H.UUIDSize = 128;
881   TestHeaderEncodeError(H, "invalid UUID size 128");
882 }
883 
884 TEST(GSYMTest, TestHeaderDecodeErrors) {
885   const llvm::support::endianness ByteOrder = llvm::support::little;
886   SmallString<512> Str;
887   raw_svector_ostream OutStrm(Str);
888   FileWriter FW(OutStrm, ByteOrder);
889   Header H;
890   InitHeader(H);
891   llvm::Error Err = H.encode(FW);
892   ASSERT_FALSE(Err);
893   FW.fixup32(12, offsetof(Header, Magic));
894   TestHeaderDecodeError(OutStrm.str(), "invalid GSYM magic 0x0000000c");
895   FW.fixup32(GSYM_MAGIC, offsetof(Header, Magic));
896   FW.fixup32(12, offsetof(Header, Version));
897   TestHeaderDecodeError(OutStrm.str(), "unsupported GSYM version 12");
898   FW.fixup32(GSYM_VERSION, offsetof(Header, Version));
899   FW.fixup32(12, offsetof(Header, AddrOffSize));
900   TestHeaderDecodeError(OutStrm.str(), "invalid address offset size 12");
901   FW.fixup32(4, offsetof(Header, AddrOffSize));
902   FW.fixup32(128, offsetof(Header, UUIDSize));
903   TestHeaderDecodeError(OutStrm.str(), "invalid UUID size 128");
904 }
905 
906 static void TestHeaderEncodeDecode(const Header &H,
907                                    support::endianness ByteOrder) {
908   uint8_t AddressSize = 4;
909   SmallString<512> Str;
910   raw_svector_ostream OutStrm(Str);
911   FileWriter FW(OutStrm, ByteOrder);
912   llvm::Error Err = H.encode(FW);
913   ASSERT_FALSE(Err);
914   std::string Bytes(OutStrm.str());
915   DataExtractor Data(Bytes, ByteOrder == llvm::support::little, AddressSize);
916   llvm::Expected<Header> Decoded = Header::decode(Data);
917   // Make sure decoding succeeded.
918   ASSERT_TRUE((bool)Decoded);
919   EXPECT_EQ(H, Decoded.get());
920 
921 }
922 TEST(GSYMTest, TestHeaderEncodeDecode) {
923   Header H;
924   InitHeader(H);
925   TestHeaderEncodeDecode(H, llvm::support::little);
926   TestHeaderEncodeDecode(H, llvm::support::big);
927 }
928 
929 static void TestGsymCreatorEncodeError(llvm::support::endianness ByteOrder,
930                                        const GsymCreator &GC,
931                                        std::string ExpectedErrorMsg) {
932   SmallString<512> Str;
933   raw_svector_ostream OutStrm(Str);
934   FileWriter FW(OutStrm, ByteOrder);
935   llvm::Error Err = GC.encode(FW);
936   ASSERT_TRUE(bool(Err));
937   checkError(ExpectedErrorMsg, std::move(Err));
938 }
939 
940 TEST(GSYMTest, TestGsymCreatorEncodeErrors) {
941   const uint8_t ValidUUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
942                                14, 15, 16};
943   const uint8_t InvalidUUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
944                                  14, 15, 16, 17, 18, 19, 20, 21};
945   // Verify we get an error when trying to encode an GsymCreator with no
946   // function infos. We shouldn't be saving a GSYM file in this case since
947   // there is nothing inside of it.
948   GsymCreator GC;
949   TestGsymCreatorEncodeError(llvm::support::little, GC,
950                              "no functions to encode");
951   const uint64_t FuncAddr = 0x1000;
952   const uint64_t FuncSize = 0x100;
953   const uint32_t FuncName = GC.insertString("foo");
954   // Verify we get an error trying to encode a GsymCreator that isn't
955   // finalized.
956   GC.addFunctionInfo(FunctionInfo(FuncAddr, FuncSize, FuncName));
957   TestGsymCreatorEncodeError(llvm::support::little, GC,
958                              "GsymCreator wasn't finalized prior to encoding");
959   std::string finalizeIssues;
960   raw_string_ostream OS(finalizeIssues);
961   llvm::Error finalizeErr = GC.finalize(OS);
962   ASSERT_FALSE(bool(finalizeErr));
963   finalizeErr = GC.finalize(OS);
964   ASSERT_TRUE(bool(finalizeErr));
965   checkError("already finalized", std::move(finalizeErr));
966   // Verify we get an error trying to encode a GsymCreator with a UUID that is
967   // too long.
968   GC.setUUID(InvalidUUID);
969   TestGsymCreatorEncodeError(llvm::support::little, GC,
970                              "invalid UUID size 21");
971   GC.setUUID(ValidUUID);
972   // Verify errors are propagated when we try to encoding an invalid line
973   // table.
974   GC.forEachFunctionInfo([](FunctionInfo &FI) -> bool {
975     FI.OptLineTable = LineTable(); // Invalid line table.
976     return false; // Stop iterating
977   });
978   TestGsymCreatorEncodeError(llvm::support::little, GC,
979                              "attempted to encode invalid LineTable object");
980   // Verify errors are propagated when we try to encoding an invalid inline
981   // info.
982   GC.forEachFunctionInfo([](FunctionInfo &FI) -> bool {
983     FI.OptLineTable = llvm::None;
984     FI.Inline = InlineInfo(); // Invalid InlineInfo.
985     return false; // Stop iterating
986   });
987   TestGsymCreatorEncodeError(llvm::support::little, GC,
988                              "attempted to encode invalid InlineInfo object");
989 }
990 
991 static void Compare(const GsymCreator &GC, const GsymReader &GR) {
992   // Verify that all of the data in a GsymCreator is correctly decoded from
993   // a GsymReader. To do this, we iterator over
994   GC.forEachFunctionInfo([&](const FunctionInfo &FI) -> bool {
995     auto DecodedFI = GR.getFunctionInfo(FI.Range.start());
996     EXPECT_TRUE(bool(DecodedFI));
997     EXPECT_EQ(FI, *DecodedFI);
998     return true; // Keep iterating over all FunctionInfo objects.
999   });
1000 }
1001 
1002 static void TestEncodeDecode(const GsymCreator &GC,
1003                              support::endianness ByteOrder, uint16_t Version,
1004                              uint8_t AddrOffSize, uint64_t BaseAddress,
1005                              uint32_t NumAddresses, ArrayRef<uint8_t> UUID) {
1006   SmallString<512> Str;
1007   raw_svector_ostream OutStrm(Str);
1008   FileWriter FW(OutStrm, ByteOrder);
1009   llvm::Error Err = GC.encode(FW);
1010   ASSERT_FALSE((bool)Err);
1011   Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());
1012   ASSERT_TRUE(bool(GR));
1013   const Header &Hdr = GR->getHeader();
1014   EXPECT_EQ(Hdr.Version, Version);
1015   EXPECT_EQ(Hdr.AddrOffSize, AddrOffSize);
1016   EXPECT_EQ(Hdr.UUIDSize, UUID.size());
1017   EXPECT_EQ(Hdr.BaseAddress, BaseAddress);
1018   EXPECT_EQ(Hdr.NumAddresses, NumAddresses);
1019   EXPECT_EQ(ArrayRef<uint8_t>(Hdr.UUID, Hdr.UUIDSize), UUID);
1020   Compare(GC, GR.get());
1021 }
1022 
1023 TEST(GSYMTest, TestGsymCreator1ByteAddrOffsets) {
1024   uint8_t UUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
1025   GsymCreator GC;
1026   GC.setUUID(UUID);
1027   constexpr uint64_t BaseAddr = 0x1000;
1028   constexpr uint8_t AddrOffSize = 1;
1029   const uint32_t Func1Name = GC.insertString("foo");
1030   const uint32_t Func2Name = GC.insertString("bar");
1031   GC.addFunctionInfo(FunctionInfo(BaseAddr+0x00, 0x10, Func1Name));
1032   GC.addFunctionInfo(FunctionInfo(BaseAddr+0x20, 0x10, Func2Name));
1033   Error Err = GC.finalize(llvm::nulls());
1034   ASSERT_FALSE(Err);
1035   TestEncodeDecode(GC, llvm::support::little,
1036                    GSYM_VERSION,
1037                    AddrOffSize,
1038                    BaseAddr,
1039                    2, // NumAddresses
1040                    ArrayRef<uint8_t>(UUID));
1041   TestEncodeDecode(GC, llvm::support::big,
1042                    GSYM_VERSION,
1043                    AddrOffSize,
1044                    BaseAddr,
1045                    2, // NumAddresses
1046                    ArrayRef<uint8_t>(UUID));
1047 }
1048 
1049 TEST(GSYMTest, TestGsymCreator2ByteAddrOffsets) {
1050   uint8_t UUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
1051   GsymCreator GC;
1052   GC.setUUID(UUID);
1053   constexpr uint64_t BaseAddr = 0x1000;
1054   constexpr uint8_t AddrOffSize = 2;
1055   const uint32_t Func1Name = GC.insertString("foo");
1056   const uint32_t Func2Name = GC.insertString("bar");
1057   GC.addFunctionInfo(FunctionInfo(BaseAddr+0x000, 0x100, Func1Name));
1058   GC.addFunctionInfo(FunctionInfo(BaseAddr+0x200, 0x100, Func2Name));
1059   Error Err = GC.finalize(llvm::nulls());
1060   ASSERT_FALSE(Err);
1061   TestEncodeDecode(GC, llvm::support::little,
1062                    GSYM_VERSION,
1063                    AddrOffSize,
1064                    BaseAddr,
1065                    2, // NumAddresses
1066                    ArrayRef<uint8_t>(UUID));
1067   TestEncodeDecode(GC, llvm::support::big,
1068                    GSYM_VERSION,
1069                    AddrOffSize,
1070                    BaseAddr,
1071                    2, // NumAddresses
1072                    ArrayRef<uint8_t>(UUID));
1073 }
1074 
1075 TEST(GSYMTest, TestGsymCreator4ByteAddrOffsets) {
1076   uint8_t UUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
1077   GsymCreator GC;
1078   GC.setUUID(UUID);
1079   constexpr uint64_t BaseAddr = 0x1000;
1080   constexpr uint8_t AddrOffSize = 4;
1081   const uint32_t Func1Name = GC.insertString("foo");
1082   const uint32_t Func2Name = GC.insertString("bar");
1083   GC.addFunctionInfo(FunctionInfo(BaseAddr+0x000, 0x100, Func1Name));
1084   GC.addFunctionInfo(FunctionInfo(BaseAddr+0x20000, 0x100, Func2Name));
1085   Error Err = GC.finalize(llvm::nulls());
1086   ASSERT_FALSE(Err);
1087   TestEncodeDecode(GC, llvm::support::little,
1088                    GSYM_VERSION,
1089                    AddrOffSize,
1090                    BaseAddr,
1091                    2, // NumAddresses
1092                    ArrayRef<uint8_t>(UUID));
1093   TestEncodeDecode(GC, llvm::support::big,
1094                    GSYM_VERSION,
1095                    AddrOffSize,
1096                    BaseAddr,
1097                    2, // NumAddresses
1098                    ArrayRef<uint8_t>(UUID));
1099 }
1100 
1101 TEST(GSYMTest, TestGsymCreator8ByteAddrOffsets) {
1102   uint8_t UUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
1103   GsymCreator GC;
1104   GC.setUUID(UUID);
1105   constexpr uint64_t BaseAddr = 0x1000;
1106   constexpr uint8_t AddrOffSize = 8;
1107   const uint32_t Func1Name = GC.insertString("foo");
1108   const uint32_t Func2Name = GC.insertString("bar");
1109   GC.addFunctionInfo(FunctionInfo(BaseAddr+0x000, 0x100, Func1Name));
1110   GC.addFunctionInfo(FunctionInfo(BaseAddr+0x100000000, 0x100, Func2Name));
1111   Error Err = GC.finalize(llvm::nulls());
1112   ASSERT_FALSE(Err);
1113   TestEncodeDecode(GC, llvm::support::little,
1114                    GSYM_VERSION,
1115                    AddrOffSize,
1116                    BaseAddr,
1117                    2, // NumAddresses
1118                    ArrayRef<uint8_t>(UUID));
1119   TestEncodeDecode(GC, llvm::support::big,
1120                    GSYM_VERSION,
1121                    AddrOffSize,
1122                    BaseAddr,
1123                    2, // NumAddresses
1124                    ArrayRef<uint8_t>(UUID));
1125 }
1126 
1127 static void VerifyFunctionInfo(const GsymReader &GR, uint64_t Addr,
1128                                const FunctionInfo &FI) {
1129   auto ExpFI = GR.getFunctionInfo(Addr);
1130   ASSERT_TRUE(bool(ExpFI));
1131   ASSERT_EQ(FI, ExpFI.get());
1132 }
1133 
1134 static void VerifyFunctionInfoError(const GsymReader &GR, uint64_t Addr,
1135                                     std::string ErrMessage) {
1136   auto ExpFI = GR.getFunctionInfo(Addr);
1137   ASSERT_FALSE(bool(ExpFI));
1138   checkError(ErrMessage, ExpFI.takeError());
1139 }
1140 
1141 TEST(GSYMTest, TestGsymReader) {
1142   uint8_t UUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
1143   GsymCreator GC;
1144   GC.setUUID(UUID);
1145   constexpr uint64_t BaseAddr = 0x1000;
1146   constexpr uint64_t Func1Addr = BaseAddr;
1147   constexpr uint64_t Func2Addr = BaseAddr+0x20;
1148   constexpr uint64_t FuncSize = 0x10;
1149   const uint32_t Func1Name = GC.insertString("foo");
1150   const uint32_t Func2Name = GC.insertString("bar");
1151   const auto ByteOrder = support::endian::system_endianness();
1152   GC.addFunctionInfo(FunctionInfo(Func1Addr, FuncSize, Func1Name));
1153   GC.addFunctionInfo(FunctionInfo(Func2Addr, FuncSize, Func2Name));
1154   Error FinalizeErr = GC.finalize(llvm::nulls());
1155   ASSERT_FALSE(FinalizeErr);
1156   SmallString<512> Str;
1157   raw_svector_ostream OutStrm(Str);
1158   FileWriter FW(OutStrm, ByteOrder);
1159   llvm::Error Err = GC.encode(FW);
1160   ASSERT_FALSE((bool)Err);
1161   if (auto ExpectedGR = GsymReader::copyBuffer(OutStrm.str())) {
1162     const GsymReader &GR = ExpectedGR.get();
1163     VerifyFunctionInfoError(GR, Func1Addr-1, "address 0xfff is not in GSYM");
1164 
1165     FunctionInfo Func1(Func1Addr, FuncSize, Func1Name);
1166     VerifyFunctionInfo(GR, Func1Addr, Func1);
1167     VerifyFunctionInfo(GR, Func1Addr+1, Func1);
1168     VerifyFunctionInfo(GR, Func1Addr+FuncSize-1, Func1);
1169     VerifyFunctionInfoError(GR, Func1Addr+FuncSize,
1170                             "address 0x1010 is not in GSYM");
1171     VerifyFunctionInfoError(GR, Func2Addr-1, "address 0x101f is not in GSYM");
1172     FunctionInfo Func2(Func2Addr, FuncSize, Func2Name);
1173     VerifyFunctionInfo(GR, Func2Addr, Func2);
1174     VerifyFunctionInfo(GR, Func2Addr+1, Func2);
1175     VerifyFunctionInfo(GR, Func2Addr+FuncSize-1, Func2);
1176     VerifyFunctionInfoError(GR, Func2Addr+FuncSize,
1177                             "address 0x1030 is not in GSYM");
1178   }
1179 }
1180 
1181 TEST(GSYMTest, TestGsymLookups) {
1182   // Test creating a GSYM file with a function that has a inline information.
1183   // Verify that lookups work correctly. Lookups do not decode the entire
1184   // FunctionInfo or InlineInfo, they only extract information needed for the
1185   // lookup to happen which avoids allocations which can slow down
1186   // symbolication.
1187   GsymCreator GC;
1188   FunctionInfo FI(0x1000, 0x100, GC.insertString("main"));
1189   const auto ByteOrder = support::endian::system_endianness();
1190   FI.OptLineTable = LineTable();
1191   const uint32_t MainFileIndex = GC.insertFile("/tmp/main.c");
1192   const uint32_t FooFileIndex = GC.insertFile("/tmp/foo.h");
1193   FI.OptLineTable->push(LineEntry(0x1000, MainFileIndex, 5));
1194   FI.OptLineTable->push(LineEntry(0x1010, FooFileIndex, 10));
1195   FI.OptLineTable->push(LineEntry(0x1012, FooFileIndex, 20));
1196   FI.OptLineTable->push(LineEntry(0x1014, FooFileIndex, 11));
1197   FI.OptLineTable->push(LineEntry(0x1016, FooFileIndex, 30));
1198   FI.OptLineTable->push(LineEntry(0x1018, FooFileIndex, 12));
1199   FI.OptLineTable->push(LineEntry(0x1020, MainFileIndex, 8));
1200   FI.Inline = InlineInfo();
1201 
1202   FI.Inline->Name = GC.insertString("inline1");
1203   FI.Inline->CallFile = MainFileIndex;
1204   FI.Inline->CallLine = 6;
1205   FI.Inline->Ranges.insert(AddressRange(0x1010, 0x1020));
1206   InlineInfo Inline2;
1207   Inline2.Name = GC.insertString("inline2");
1208   Inline2.CallFile = FooFileIndex;
1209   Inline2.CallLine = 33;
1210   Inline2.Ranges.insert(AddressRange(0x1012, 0x1014));
1211   FI.Inline->Children.emplace_back(Inline2);
1212   InlineInfo Inline3;
1213   Inline3.Name = GC.insertString("inline3");
1214   Inline3.CallFile = FooFileIndex;
1215   Inline3.CallLine = 35;
1216   Inline3.Ranges.insert(AddressRange(0x1016, 0x1018));
1217   FI.Inline->Children.emplace_back(Inline3);
1218   GC.addFunctionInfo(std::move(FI));
1219   Error FinalizeErr = GC.finalize(llvm::nulls());
1220   ASSERT_FALSE(FinalizeErr);
1221   SmallString<512> Str;
1222   raw_svector_ostream OutStrm(Str);
1223   FileWriter FW(OutStrm, ByteOrder);
1224   llvm::Error Err = GC.encode(FW);
1225   ASSERT_FALSE((bool)Err);
1226   Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());
1227   ASSERT_TRUE(bool(GR));
1228 
1229   // Verify inline info is correct when doing lookups.
1230   auto LR = GR->lookup(0x1000);
1231   ASSERT_THAT_EXPECTED(LR, Succeeded());
1232   EXPECT_THAT(LR->Locations,
1233     testing::ElementsAre(SourceLocation{"main", "/tmp", "main.c", 5}));
1234   LR = GR->lookup(0x100F);
1235   ASSERT_THAT_EXPECTED(LR, Succeeded());
1236   EXPECT_THAT(LR->Locations,
1237     testing::ElementsAre(SourceLocation{"main", "/tmp", "main.c", 5, 15}));
1238 
1239   LR = GR->lookup(0x1010);
1240   ASSERT_THAT_EXPECTED(LR, Succeeded());
1241 
1242   EXPECT_THAT(LR->Locations,
1243     testing::ElementsAre(SourceLocation{"inline1", "/tmp", "foo.h", 10},
1244                          SourceLocation{"main", "/tmp", "main.c", 6, 16}));
1245 
1246   LR = GR->lookup(0x1012);
1247   ASSERT_THAT_EXPECTED(LR, Succeeded());
1248   EXPECT_THAT(LR->Locations,
1249     testing::ElementsAre(SourceLocation{"inline2", "/tmp", "foo.h", 20},
1250                          SourceLocation{"inline1", "/tmp", "foo.h", 33, 2},
1251                          SourceLocation{"main", "/tmp", "main.c", 6, 18}));
1252 
1253   LR = GR->lookup(0x1014);
1254   ASSERT_THAT_EXPECTED(LR, Succeeded());
1255   EXPECT_THAT(LR->Locations,
1256     testing::ElementsAre(SourceLocation{"inline1", "/tmp", "foo.h", 11, 4},
1257                          SourceLocation{"main", "/tmp", "main.c", 6, 20}));
1258 
1259   LR = GR->lookup(0x1016);
1260   ASSERT_THAT_EXPECTED(LR, Succeeded());
1261   EXPECT_THAT(LR->Locations,
1262     testing::ElementsAre(SourceLocation{"inline3", "/tmp", "foo.h", 30},
1263                          SourceLocation{"inline1", "/tmp", "foo.h", 35, 6},
1264                          SourceLocation{"main", "/tmp", "main.c", 6, 22}));
1265 
1266   LR = GR->lookup(0x1018);
1267   ASSERT_THAT_EXPECTED(LR, Succeeded());
1268   EXPECT_THAT(LR->Locations,
1269     testing::ElementsAre(SourceLocation{"inline1", "/tmp", "foo.h", 12, 8},
1270                          SourceLocation{"main", "/tmp", "main.c", 6, 24}));
1271 
1272   LR = GR->lookup(0x1020);
1273   ASSERT_THAT_EXPECTED(LR, Succeeded());
1274   EXPECT_THAT(LR->Locations,
1275     testing::ElementsAre(SourceLocation{"main", "/tmp", "main.c", 8, 32}));
1276 }
1277 
1278 
1279 TEST(GSYMTest, TestDWARFFunctionWithAddresses) {
1280   // Create a single compile unit with a single function and make sure it gets
1281   // converted to DWARF correctly. The function's address range is in where
1282   // DW_AT_low_pc and DW_AT_high_pc are both addresses.
1283   StringRef yamldata = R"(
1284   debug_str:
1285     - ''
1286     - /tmp/main.c
1287     - main
1288   debug_abbrev:
1289     - Table:
1290         - Code:            0x00000001
1291           Tag:             DW_TAG_compile_unit
1292           Children:        DW_CHILDREN_yes
1293           Attributes:
1294             - Attribute:       DW_AT_name
1295               Form:            DW_FORM_strp
1296             - Attribute:       DW_AT_low_pc
1297               Form:            DW_FORM_addr
1298             - Attribute:       DW_AT_high_pc
1299               Form:            DW_FORM_addr
1300             - Attribute:       DW_AT_language
1301               Form:            DW_FORM_data2
1302         - Code:            0x00000002
1303           Tag:             DW_TAG_subprogram
1304           Children:        DW_CHILDREN_no
1305           Attributes:
1306             - Attribute:       DW_AT_name
1307               Form:            DW_FORM_strp
1308             - Attribute:       DW_AT_low_pc
1309               Form:            DW_FORM_addr
1310             - Attribute:       DW_AT_high_pc
1311               Form:            DW_FORM_addr
1312   debug_info:
1313     - Version:         4
1314       AddrSize:        8
1315       Entries:
1316         - AbbrCode:        0x00000001
1317           Values:
1318             - Value:           0x0000000000000001
1319             - Value:           0x0000000000001000
1320             - Value:           0x0000000000002000
1321             - Value:           0x0000000000000004
1322         - AbbrCode:        0x00000002
1323           Values:
1324             - Value:           0x000000000000000D
1325             - Value:           0x0000000000001000
1326             - Value:           0x0000000000002000
1327         - AbbrCode:        0x00000000
1328   )";
1329   auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);
1330   ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());
1331   std::unique_ptr<DWARFContext> DwarfContext =
1332       DWARFContext::create(*ErrOrSections, 8);
1333   ASSERT_TRUE(DwarfContext.get() != nullptr);
1334   auto &OS = llvm::nulls();
1335   GsymCreator GC;
1336   DwarfTransformer DT(*DwarfContext, OS, GC);
1337   const uint32_t ThreadCount = 1;
1338   ASSERT_THAT_ERROR(DT.convert(ThreadCount), Succeeded());
1339   ASSERT_THAT_ERROR(GC.finalize(OS), Succeeded());
1340   SmallString<512> Str;
1341   raw_svector_ostream OutStrm(Str);
1342   const auto ByteOrder = support::endian::system_endianness();
1343   FileWriter FW(OutStrm, ByteOrder);
1344   ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());
1345   Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());
1346   ASSERT_THAT_EXPECTED(GR, Succeeded());
1347   // There should only be one function in our GSYM.
1348   EXPECT_EQ(GR->getNumAddresses(), 1u);
1349   auto ExpFI = GR->getFunctionInfo(0x1000);
1350   ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
1351   ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x2000));
1352   EXPECT_FALSE(ExpFI->OptLineTable.has_value());
1353   EXPECT_FALSE(ExpFI->Inline.has_value());
1354 }
1355 
1356 TEST(GSYMTest, TestDWARFFunctionWithAddressAndOffset) {
1357   // Create a single compile unit with a single function and make sure it gets
1358   // converted to DWARF correctly. The function's address range is in where
1359   // DW_AT_low_pc is an address and the DW_AT_high_pc is an offset.
1360   StringRef yamldata = R"(
1361   debug_str:
1362     - ''
1363     - /tmp/main.c
1364     - main
1365   debug_abbrev:
1366     - Table:
1367         - Code:            0x00000001
1368           Tag:             DW_TAG_compile_unit
1369           Children:        DW_CHILDREN_yes
1370           Attributes:
1371             - Attribute:       DW_AT_name
1372               Form:            DW_FORM_strp
1373             - Attribute:       DW_AT_low_pc
1374               Form:            DW_FORM_addr
1375             - Attribute:       DW_AT_high_pc
1376               Form:            DW_FORM_data4
1377             - Attribute:       DW_AT_language
1378               Form:            DW_FORM_data2
1379         - Code:            0x00000002
1380           Tag:             DW_TAG_subprogram
1381           Children:        DW_CHILDREN_no
1382           Attributes:
1383             - Attribute:       DW_AT_name
1384               Form:            DW_FORM_strp
1385             - Attribute:       DW_AT_low_pc
1386               Form:            DW_FORM_addr
1387             - Attribute:       DW_AT_high_pc
1388               Form:            DW_FORM_data4
1389   debug_info:
1390     - Version:         4
1391       AddrSize:        8
1392       Entries:
1393         - AbbrCode:        0x00000001
1394           Values:
1395             - Value:           0x0000000000000001
1396             - Value:           0x0000000000001000
1397             - Value:           0x0000000000001000
1398             - Value:           0x0000000000000004
1399         - AbbrCode:        0x00000002
1400           Values:
1401             - Value:           0x000000000000000D
1402             - Value:           0x0000000000001000
1403             - Value:           0x0000000000001000
1404         - AbbrCode:        0x00000000
1405   )";
1406   auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);
1407   ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());
1408   std::unique_ptr<DWARFContext> DwarfContext =
1409       DWARFContext::create(*ErrOrSections, 8);
1410   ASSERT_TRUE(DwarfContext.get() != nullptr);
1411   auto &OS = llvm::nulls();
1412   GsymCreator GC;
1413   DwarfTransformer DT(*DwarfContext, OS, GC);
1414   const uint32_t ThreadCount = 1;
1415   ASSERT_THAT_ERROR(DT.convert(ThreadCount), Succeeded());
1416   ASSERT_THAT_ERROR(GC.finalize(OS), Succeeded());
1417   SmallString<512> Str;
1418   raw_svector_ostream OutStrm(Str);
1419   const auto ByteOrder = support::endian::system_endianness();
1420   FileWriter FW(OutStrm, ByteOrder);
1421   ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());
1422   Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());
1423   ASSERT_THAT_EXPECTED(GR, Succeeded());
1424   // There should only be one function in our GSYM.
1425   EXPECT_EQ(GR->getNumAddresses(), 1u);
1426   auto ExpFI = GR->getFunctionInfo(0x1000);
1427   ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
1428   ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x2000));
1429   EXPECT_FALSE(ExpFI->OptLineTable.has_value());
1430   EXPECT_FALSE(ExpFI->Inline.has_value());
1431 }
1432 
1433 TEST(GSYMTest, TestDWARFStructMethodNoMangled) {
1434   // Sometimes the compiler will omit the mangled name in the DWARF for static
1435   // and member functions of classes and structs. This test verifies that the
1436   // fully qualified name of the method is computed and used as the string for
1437   // the function in the GSYM in these cases. Otherwise we might just get a
1438   // function name like "erase" instead of "std::vector<int>::erase".
1439   StringRef yamldata = R"(
1440   debug_str:
1441     - ''
1442     - /tmp/main.c
1443     - Foo
1444     - dump
1445     - this
1446   debug_abbrev:
1447     - Table:
1448         - Code:            0x00000001
1449           Tag:             DW_TAG_compile_unit
1450           Children:        DW_CHILDREN_yes
1451           Attributes:
1452             - Attribute:       DW_AT_name
1453               Form:            DW_FORM_strp
1454             - Attribute:       DW_AT_low_pc
1455               Form:            DW_FORM_addr
1456             - Attribute:       DW_AT_high_pc
1457               Form:            DW_FORM_addr
1458             - Attribute:       DW_AT_language
1459               Form:            DW_FORM_data2
1460         - Code:            0x00000002
1461           Tag:             DW_TAG_structure_type
1462           Children:        DW_CHILDREN_yes
1463           Attributes:
1464             - Attribute:       DW_AT_name
1465               Form:            DW_FORM_strp
1466         - Code:            0x00000003
1467           Tag:             DW_TAG_subprogram
1468           Children:        DW_CHILDREN_yes
1469           Attributes:
1470             - Attribute:       DW_AT_name
1471               Form:            DW_FORM_strp
1472             - Attribute:       DW_AT_low_pc
1473               Form:            DW_FORM_addr
1474             - Attribute:       DW_AT_high_pc
1475               Form:            DW_FORM_addr
1476         - Code:            0x00000004
1477           Tag:             DW_TAG_formal_parameter
1478           Children:        DW_CHILDREN_no
1479           Attributes:
1480             - Attribute:       DW_AT_name
1481               Form:            DW_FORM_strp
1482             - Attribute:       DW_AT_type
1483               Form:            DW_FORM_ref4
1484             - Attribute:       DW_AT_artificial
1485               Form:            DW_FORM_flag_present
1486   debug_info:
1487     - Version:         4
1488       AddrSize:        8
1489       Entries:
1490         - AbbrCode:        0x00000001
1491           Values:
1492             - Value:           0x0000000000000001
1493             - Value:           0x0000000000001000
1494             - Value:           0x0000000000002000
1495             - Value:           0x0000000000000004
1496         - AbbrCode:        0x00000002
1497           Values:
1498             - Value:           0x000000000000000D
1499         - AbbrCode:        0x00000003
1500           Values:
1501             - Value:           0x0000000000000011
1502             - Value:           0x0000000000001000
1503             - Value:           0x0000000000002000
1504         - AbbrCode:        0x00000004
1505           Values:
1506             - Value:           0x0000000000000016
1507             - Value:           0x0000000000000022
1508             - Value:           0x0000000000000001
1509         - AbbrCode:        0x00000000
1510         - AbbrCode:        0x00000000
1511         - AbbrCode:        0x00000000
1512   )";
1513   auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);
1514   ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());
1515   std::unique_ptr<DWARFContext> DwarfContext =
1516       DWARFContext::create(*ErrOrSections, 8);
1517   ASSERT_TRUE(DwarfContext.get() != nullptr);
1518   auto &OS = llvm::nulls();
1519   GsymCreator GC;
1520   DwarfTransformer DT(*DwarfContext, OS, GC);
1521   const uint32_t ThreadCount = 1;
1522   ASSERT_THAT_ERROR(DT.convert(ThreadCount), Succeeded());
1523   ASSERT_THAT_ERROR(GC.finalize(OS), Succeeded());
1524   SmallString<512> Str;
1525   raw_svector_ostream OutStrm(Str);
1526   const auto ByteOrder = support::endian::system_endianness();
1527   FileWriter FW(OutStrm, ByteOrder);
1528   ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());
1529   Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());
1530   ASSERT_THAT_EXPECTED(GR, Succeeded());
1531   // There should only be one function in our GSYM.
1532   EXPECT_EQ(GR->getNumAddresses(), 1u);
1533   auto ExpFI = GR->getFunctionInfo(0x1000);
1534   ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
1535   ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x2000));
1536   EXPECT_FALSE(ExpFI->OptLineTable.has_value());
1537   EXPECT_FALSE(ExpFI->Inline.has_value());
1538   StringRef MethodName = GR->getString(ExpFI->Name);
1539   EXPECT_EQ(MethodName, "Foo::dump");
1540 }
1541 
1542 TEST(GSYMTest, TestDWARFTextRanges) {
1543   // Linkers don't understand DWARF, they just like to concatenate and
1544   // relocate data within the DWARF sections. This means that if a function
1545   // gets dead stripped, and if those functions use an offset as the
1546   // DW_AT_high_pc, we can end up with many functions at address zero. The
1547   // DwarfTransformer allows clients to specify valid .text address ranges
1548   // and any addresses of any functions must fall within those ranges if any
1549   // have been specified. This means that an object file can calcuate the
1550   // address ranges within the binary where code lives and set these ranges
1551   // as constraints in the DwarfTransformer. ObjectFile instances can
1552   // add a address ranges of sections that have executable permissions. This
1553   // keeps bad information from being added to a GSYM file and causing issues
1554   // when symbolicating.
1555   StringRef yamldata = R"(
1556   debug_str:
1557     - ''
1558     - /tmp/main.c
1559     - main
1560     - dead_stripped
1561     - dead_stripped2
1562   debug_abbrev:
1563     - Table:
1564         - Code:            0x00000001
1565           Tag:             DW_TAG_compile_unit
1566           Children:        DW_CHILDREN_yes
1567           Attributes:
1568             - Attribute:       DW_AT_name
1569               Form:            DW_FORM_strp
1570             - Attribute:       DW_AT_low_pc
1571               Form:            DW_FORM_addr
1572             - Attribute:       DW_AT_high_pc
1573               Form:            DW_FORM_data4
1574             - Attribute:       DW_AT_language
1575               Form:            DW_FORM_data2
1576         - Code:            0x00000002
1577           Tag:             DW_TAG_subprogram
1578           Children:        DW_CHILDREN_no
1579           Attributes:
1580             - Attribute:       DW_AT_name
1581               Form:            DW_FORM_strp
1582             - Attribute:       DW_AT_low_pc
1583               Form:            DW_FORM_addr
1584             - Attribute:       DW_AT_high_pc
1585               Form:            DW_FORM_data4
1586   debug_info:
1587     - Version:         4
1588       AddrSize:        8
1589       Entries:
1590         - AbbrCode:        0x00000001
1591           Values:
1592             - Value:           0x0000000000000001
1593             - Value:           0x0000000000001000
1594             - Value:           0x0000000000001000
1595             - Value:           0x0000000000000004
1596         - AbbrCode:        0x00000002
1597           Values:
1598             - Value:           0x000000000000000D
1599             - Value:           0x0000000000001000
1600             - Value:           0x0000000000001000
1601         - AbbrCode:        0x00000002
1602           Values:
1603             - Value:           0x0000000000000012
1604             - Value:           0x0000000000000000
1605             - Value:           0x0000000000000100
1606         - AbbrCode:        0x00000002
1607           Values:
1608             - Value:           0x0000000000000020
1609             - Value:           0x0000000000000000
1610             - Value:           0x0000000000000040
1611         - AbbrCode:        0x00000000
1612   )";
1613   auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);
1614   ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());
1615   std::unique_ptr<DWARFContext> DwarfContext =
1616       DWARFContext::create(*ErrOrSections, 8);
1617   ASSERT_TRUE(DwarfContext.get() != nullptr);
1618   auto &OS = llvm::nulls();
1619   GsymCreator GC;
1620   DwarfTransformer DT(*DwarfContext, OS, GC);
1621   // Only allow addresses between [0x1000 - 0x2000) to be linked into the
1622   // GSYM.
1623   AddressRanges TextRanges;
1624   TextRanges.insert(AddressRange(0x1000, 0x2000));
1625   GC.SetValidTextRanges(TextRanges);
1626   const uint32_t ThreadCount = 1;
1627   ASSERT_THAT_ERROR(DT.convert(ThreadCount), Succeeded());
1628   ASSERT_THAT_ERROR(GC.finalize(OS), Succeeded());
1629   SmallString<512> Str;
1630   raw_svector_ostream OutStrm(Str);
1631   const auto ByteOrder = support::endian::system_endianness();
1632   FileWriter FW(OutStrm, ByteOrder);
1633   ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());
1634   Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());
1635   ASSERT_THAT_EXPECTED(GR, Succeeded());
1636   // There should only be one function in our GSYM.
1637   EXPECT_EQ(GR->getNumAddresses(), 1u);
1638   auto ExpFI = GR->getFunctionInfo(0x1000);
1639   ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
1640   ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x2000));
1641   EXPECT_FALSE(ExpFI->OptLineTable.has_value());
1642   EXPECT_FALSE(ExpFI->Inline.has_value());
1643   StringRef MethodName = GR->getString(ExpFI->Name);
1644   EXPECT_EQ(MethodName, "main");
1645 }
1646 
1647 TEST(GSYMTest, TestEmptySymbolEndAddressOfTextRanges) {
1648   // Test that if we have valid text ranges and we have a symbol with no size
1649   // as the last FunctionInfo entry that the size of the symbol gets set to the
1650   // end address of the text range.
1651   GsymCreator GC;
1652   AddressRanges TextRanges;
1653   TextRanges.insert(AddressRange(0x1000, 0x2000));
1654   GC.SetValidTextRanges(TextRanges);
1655   GC.addFunctionInfo(FunctionInfo(0x1500, 0, GC.insertString("symbol")));
1656   auto &OS = llvm::nulls();
1657   ASSERT_THAT_ERROR(GC.finalize(OS), Succeeded());
1658   SmallString<512> Str;
1659   raw_svector_ostream OutStrm(Str);
1660   const auto ByteOrder = support::endian::system_endianness();
1661   FileWriter FW(OutStrm, ByteOrder);
1662   ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());
1663   Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());
1664   ASSERT_THAT_EXPECTED(GR, Succeeded());
1665   // There should only be one function in our GSYM.
1666   EXPECT_EQ(GR->getNumAddresses(), 1u);
1667   auto ExpFI = GR->getFunctionInfo(0x1500);
1668   ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
1669   ASSERT_EQ(ExpFI->Range, AddressRange(0x1500, 0x2000));
1670   EXPECT_FALSE(ExpFI->OptLineTable.has_value());
1671   EXPECT_FALSE(ExpFI->Inline.has_value());
1672   StringRef MethodName = GR->getString(ExpFI->Name);
1673   EXPECT_EQ(MethodName, "symbol");
1674 }
1675 
1676 TEST(GSYMTest, TestDWARFInlineInfo) {
1677   // Make sure we parse the line table and inline information correctly from
1678   // DWARF.
1679   StringRef yamldata = R"(
1680   debug_str:
1681     - ''
1682     - /tmp/main.c
1683     - main
1684     - inline1
1685   debug_abbrev:
1686     - Table:
1687         - Code:            0x00000001
1688           Tag:             DW_TAG_compile_unit
1689           Children:        DW_CHILDREN_yes
1690           Attributes:
1691             - Attribute:       DW_AT_name
1692               Form:            DW_FORM_strp
1693             - Attribute:       DW_AT_low_pc
1694               Form:            DW_FORM_addr
1695             - Attribute:       DW_AT_high_pc
1696               Form:            DW_FORM_data4
1697             - Attribute:       DW_AT_language
1698               Form:            DW_FORM_data2
1699             - Attribute:       DW_AT_stmt_list
1700               Form:            DW_FORM_sec_offset
1701         - Code:            0x00000002
1702           Tag:             DW_TAG_subprogram
1703           Children:        DW_CHILDREN_yes
1704           Attributes:
1705             - Attribute:       DW_AT_name
1706               Form:            DW_FORM_strp
1707             - Attribute:       DW_AT_low_pc
1708               Form:            DW_FORM_addr
1709             - Attribute:       DW_AT_high_pc
1710               Form:            DW_FORM_data4
1711         - Code:            0x00000003
1712           Tag:             DW_TAG_inlined_subroutine
1713           Children:        DW_CHILDREN_no
1714           Attributes:
1715             - Attribute:       DW_AT_name
1716               Form:            DW_FORM_strp
1717             - Attribute:       DW_AT_low_pc
1718               Form:            DW_FORM_addr
1719             - Attribute:       DW_AT_high_pc
1720               Form:            DW_FORM_data4
1721             - Attribute:       DW_AT_call_file
1722               Form:            DW_FORM_data4
1723             - Attribute:       DW_AT_call_line
1724               Form:            DW_FORM_data4
1725   debug_info:
1726     - Version:         4
1727       AddrSize:        8
1728       Entries:
1729         - AbbrCode:        0x00000001
1730           Values:
1731             - Value:           0x0000000000000001
1732             - Value:           0x0000000000001000
1733             - Value:           0x0000000000001000
1734             - Value:           0x0000000000000004
1735             - Value:           0x0000000000000000
1736         - AbbrCode:        0x00000002
1737           Values:
1738             - Value:           0x000000000000000D
1739             - Value:           0x0000000000001000
1740             - Value:           0x0000000000001000
1741         - AbbrCode:        0x00000003
1742           Values:
1743             - Value:           0x0000000000000012
1744             - Value:           0x0000000000001100
1745             - Value:           0x0000000000000100
1746             - Value:           0x0000000000000001
1747             - Value:           0x000000000000000A
1748         - AbbrCode:        0x00000000
1749         - AbbrCode:        0x00000000
1750   debug_line:
1751     - Length:          96
1752       Version:         2
1753       PrologueLength:  46
1754       MinInstLength:   1
1755       DefaultIsStmt:   1
1756       LineBase:        251
1757       LineRange:       14
1758       OpcodeBase:      13
1759       StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]
1760       IncludeDirs:
1761         - /tmp
1762       Files:
1763         - Name:            main.c
1764           DirIdx:          1
1765           ModTime:         0
1766           Length:          0
1767         - Name:            inline.h
1768           DirIdx:          1
1769           ModTime:         0
1770           Length:          0
1771       Opcodes:
1772         - Opcode:          DW_LNS_extended_op
1773           ExtLen:          9
1774           SubOpcode:       DW_LNE_set_address
1775           Data:            4096
1776         - Opcode:          DW_LNS_advance_line
1777           SData:           9
1778           Data:            4096
1779         - Opcode:          DW_LNS_copy
1780           Data:            4096
1781         - Opcode:          DW_LNS_advance_pc
1782           Data:            256
1783         - Opcode:          DW_LNS_set_file
1784           Data:            2
1785         - Opcode:          DW_LNS_advance_line
1786           SData:           10
1787           Data:            2
1788         - Opcode:          DW_LNS_copy
1789           Data:            2
1790         - Opcode:          DW_LNS_advance_pc
1791           Data:            128
1792         - Opcode:          DW_LNS_advance_line
1793           SData:           1
1794           Data:            128
1795         - Opcode:          DW_LNS_copy
1796           Data:            128
1797         - Opcode:          DW_LNS_advance_pc
1798           Data:            128
1799         - Opcode:          DW_LNS_set_file
1800           Data:            1
1801         - Opcode:          DW_LNS_advance_line
1802           SData:           -10
1803           Data:            1
1804         - Opcode:          DW_LNS_copy
1805           Data:            1
1806         - Opcode:          DW_LNS_advance_pc
1807           Data:            3584
1808         - Opcode:          DW_LNS_advance_line
1809           SData:           1
1810           Data:            3584
1811         - Opcode:          DW_LNS_extended_op
1812           ExtLen:          1
1813           SubOpcode:       DW_LNE_end_sequence
1814           Data:            3584
1815   )";
1816   auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);
1817   ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());
1818   std::unique_ptr<DWARFContext> DwarfContext =
1819       DWARFContext::create(*ErrOrSections, 8);
1820   ASSERT_TRUE(DwarfContext.get() != nullptr);
1821   auto &OS = llvm::nulls();
1822   GsymCreator GC;
1823   DwarfTransformer DT(*DwarfContext, OS, GC);
1824   const uint32_t ThreadCount = 1;
1825   ASSERT_THAT_ERROR(DT.convert(ThreadCount), Succeeded());
1826   ASSERT_THAT_ERROR(GC.finalize(OS), Succeeded());
1827   SmallString<512> Str;
1828   raw_svector_ostream OutStrm(Str);
1829   const auto ByteOrder = support::endian::system_endianness();
1830   FileWriter FW(OutStrm, ByteOrder);
1831   ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());
1832   Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());
1833   ASSERT_THAT_EXPECTED(GR, Succeeded());
1834   // There should only be one function in our GSYM.
1835   EXPECT_EQ(GR->getNumAddresses(), 1u);
1836   auto ExpFI = GR->getFunctionInfo(0x1000);
1837   ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
1838   ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x2000));
1839   EXPECT_TRUE(ExpFI->OptLineTable.has_value());
1840   EXPECT_TRUE(ExpFI->Inline.has_value());
1841   StringRef MethodName = GR->getString(ExpFI->Name);
1842   EXPECT_EQ(MethodName, "main");
1843 
1844     // Verify inline info is correct when doing lookups.
1845   auto LR = GR->lookup(0x1000);
1846   ASSERT_THAT_EXPECTED(LR, Succeeded());
1847   EXPECT_THAT(LR->Locations,
1848     testing::ElementsAre(SourceLocation{"main", "/tmp", "main.c", 10}));
1849   LR = GR->lookup(0x1100-1);
1850   ASSERT_THAT_EXPECTED(LR, Succeeded());
1851   EXPECT_THAT(LR->Locations,
1852     testing::ElementsAre(SourceLocation{"main", "/tmp", "main.c", 10, 255}));
1853 
1854   LR = GR->lookup(0x1100);
1855   ASSERT_THAT_EXPECTED(LR, Succeeded());
1856   EXPECT_THAT(LR->Locations,
1857     testing::ElementsAre(SourceLocation{"inline1", "/tmp", "inline.h", 20},
1858                          SourceLocation{"main", "/tmp", "main.c", 10, 256}));
1859   LR = GR->lookup(0x1180-1);
1860   ASSERT_THAT_EXPECTED(LR, Succeeded());
1861   EXPECT_THAT(LR->Locations,
1862     testing::ElementsAre(SourceLocation{"inline1", "/tmp", "inline.h", 20, 127},
1863                          SourceLocation{"main", "/tmp", "main.c", 10, 383}));
1864   LR = GR->lookup(0x1180);
1865   ASSERT_THAT_EXPECTED(LR, Succeeded());
1866   EXPECT_THAT(LR->Locations,
1867     testing::ElementsAre(SourceLocation{"inline1", "/tmp", "inline.h", 21, 128},
1868                          SourceLocation{"main", "/tmp", "main.c", 10, 384}));
1869   LR = GR->lookup(0x1200-1);
1870   ASSERT_THAT_EXPECTED(LR, Succeeded());
1871   EXPECT_THAT(LR->Locations,
1872     testing::ElementsAre(SourceLocation{"inline1", "/tmp", "inline.h", 21, 255},
1873                          SourceLocation{"main", "/tmp", "main.c", 10, 511}));
1874   LR = GR->lookup(0x1200);
1875   ASSERT_THAT_EXPECTED(LR, Succeeded());
1876   EXPECT_THAT(LR->Locations,
1877     testing::ElementsAre(SourceLocation{"main", "/tmp", "main.c", 11, 512}));
1878 }
1879 
1880 
1881 TEST(GSYMTest, TestDWARFNoLines) {
1882   // Check that if a DW_TAG_subprogram doesn't have line table entries that
1883   // we fall back and use the DW_AT_decl_file and DW_AT_decl_line to at least
1884   // point to the function definition. This DWARF file has 4 functions:
1885   //  "lines_no_decl": has line table entries, no DW_AT_decl_file/line attrs.
1886   //  "lines_with_decl": has line table entries and has DW_AT_decl_file/line,
1887   //                     make sure we don't use DW_AT_decl_file/line and make
1888   //                     sure there is a line table.
1889   //  "no_lines_no_decl": no line table entries and no DW_AT_decl_file/line,
1890   //                      make sure there is no line table for this function.
1891   //  "no_lines_with_decl": no line table and has DW_AT_decl_file/line, make
1892   //                        sure we have one line table entry that starts at
1893   //                        the function start address and the decl file and
1894   //                        line.
1895   //
1896   // 0x0000000b: DW_TAG_compile_unit
1897   //               DW_AT_name	("/tmp/main.c")
1898   //               DW_AT_low_pc	(0x0000000000001000)
1899   //               DW_AT_high_pc	(0x0000000000002000)
1900   //               DW_AT_language	(DW_LANG_C_plus_plus)
1901   //               DW_AT_stmt_list	(0x00000000)
1902   //
1903   // 0x00000022:   DW_TAG_subprogram
1904   //                 DW_AT_name	("lines_no_decl")
1905   //                 DW_AT_low_pc	(0x0000000000001000)
1906   //                 DW_AT_high_pc	(0x0000000000002000)
1907   //
1908   // 0x00000033:   DW_TAG_subprogram
1909   //                 DW_AT_name	("lines_with_decl")
1910   //                 DW_AT_low_pc	(0x0000000000002000)
1911   //                 DW_AT_high_pc	(0x0000000000003000)
1912   //                 DW_AT_decl_file	("/tmp/main.c")
1913   //                 DW_AT_decl_line	(20)
1914   //
1915   // 0x00000046:   DW_TAG_subprogram
1916   //                 DW_AT_name	("no_lines_no_decl")
1917   //                 DW_AT_low_pc	(0x0000000000003000)
1918   //                 DW_AT_high_pc	(0x0000000000004000)
1919   //
1920   // 0x00000057:   DW_TAG_subprogram
1921   //                 DW_AT_name	("no_lines_with_decl")
1922   //                 DW_AT_low_pc	(0x0000000000004000)
1923   //                 DW_AT_high_pc	(0x0000000000005000)
1924   //                 DW_AT_decl_file	("/tmp/main.c")
1925   //                 DW_AT_decl_line	(40)
1926   //
1927   // 0x0000006a:   NULL
1928 
1929   StringRef yamldata = R"(
1930   debug_str:
1931     - ''
1932     - '/tmp/main.c'
1933     - lines_no_decl
1934     - lines_with_decl
1935     - no_lines_no_decl
1936     - no_lines_with_decl
1937   debug_abbrev:
1938     - Table:
1939         - Code:            0x00000001
1940           Tag:             DW_TAG_compile_unit
1941           Children:        DW_CHILDREN_yes
1942           Attributes:
1943             - Attribute:       DW_AT_name
1944               Form:            DW_FORM_strp
1945             - Attribute:       DW_AT_low_pc
1946               Form:            DW_FORM_addr
1947             - Attribute:       DW_AT_high_pc
1948               Form:            DW_FORM_data4
1949             - Attribute:       DW_AT_language
1950               Form:            DW_FORM_data2
1951             - Attribute:       DW_AT_stmt_list
1952               Form:            DW_FORM_sec_offset
1953         - Code:            0x00000002
1954           Tag:             DW_TAG_subprogram
1955           Children:        DW_CHILDREN_no
1956           Attributes:
1957             - Attribute:       DW_AT_name
1958               Form:            DW_FORM_strp
1959             - Attribute:       DW_AT_low_pc
1960               Form:            DW_FORM_addr
1961             - Attribute:       DW_AT_high_pc
1962               Form:            DW_FORM_data4
1963         - Code:            0x00000003
1964           Tag:             DW_TAG_subprogram
1965           Children:        DW_CHILDREN_no
1966           Attributes:
1967             - Attribute:       DW_AT_name
1968               Form:            DW_FORM_strp
1969             - Attribute:       DW_AT_low_pc
1970               Form:            DW_FORM_addr
1971             - Attribute:       DW_AT_high_pc
1972               Form:            DW_FORM_data4
1973             - Attribute:       DW_AT_decl_file
1974               Form:            DW_FORM_data1
1975             - Attribute:       DW_AT_decl_line
1976               Form:            DW_FORM_data1
1977   debug_info:
1978     - Version:         4
1979       AddrSize:        8
1980       Entries:
1981         - AbbrCode:        0x00000001
1982           Values:
1983             - Value:           0x0000000000000001
1984             - Value:           0x0000000000001000
1985             - Value:           0x0000000000001000
1986             - Value:           0x0000000000000004
1987             - Value:           0x0000000000000000
1988         - AbbrCode:        0x00000002
1989           Values:
1990             - Value:           0x000000000000000D
1991             - Value:           0x0000000000001000
1992             - Value:           0x0000000000001000
1993         - AbbrCode:        0x00000003
1994           Values:
1995             - Value:           0x000000000000001B
1996             - Value:           0x0000000000002000
1997             - Value:           0x0000000000001000
1998             - Value:           0x0000000000000001
1999             - Value:           0x0000000000000014
2000         - AbbrCode:        0x00000002
2001           Values:
2002             - Value:           0x000000000000002B
2003             - Value:           0x0000000000003000
2004             - Value:           0x0000000000001000
2005         - AbbrCode:        0x00000003
2006           Values:
2007             - Value:           0x000000000000003C
2008             - Value:           0x0000000000004000
2009             - Value:           0x0000000000001000
2010             - Value:           0x0000000000000001
2011             - Value:           0x0000000000000028
2012         - AbbrCode:        0x00000000
2013   debug_line:
2014     - Length:          92
2015       Version:         2
2016       PrologueLength:  34
2017       MinInstLength:   1
2018       DefaultIsStmt:   1
2019       LineBase:        251
2020       LineRange:       14
2021       OpcodeBase:      13
2022       StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]
2023       IncludeDirs:
2024         - '/tmp'
2025       Files:
2026         - Name:            main.c
2027           DirIdx:          1
2028           ModTime:         0
2029           Length:          0
2030       Opcodes:
2031         - Opcode:          DW_LNS_extended_op
2032           ExtLen:          9
2033           SubOpcode:       DW_LNE_set_address
2034           Data:            4096
2035         - Opcode:          DW_LNS_advance_line
2036           SData:           10
2037           Data:            0
2038         - Opcode:          DW_LNS_copy
2039           Data:            0
2040         - Opcode:          DW_LNS_advance_pc
2041           Data:            512
2042         - Opcode:          DW_LNS_advance_line
2043           SData:           1
2044           Data:            0
2045         - Opcode:          DW_LNS_copy
2046           Data:            0
2047         - Opcode:          DW_LNS_advance_pc
2048           Data:            3584
2049         - Opcode:          DW_LNS_extended_op
2050           ExtLen:          1
2051           SubOpcode:       DW_LNE_end_sequence
2052           Data:            0
2053         - Opcode:          DW_LNS_extended_op
2054           ExtLen:          9
2055           SubOpcode:       DW_LNE_set_address
2056           Data:            8192
2057         - Opcode:          DW_LNS_advance_line
2058           SData:           20
2059           Data:            0
2060         - Opcode:          DW_LNS_copy
2061           Data:            0
2062         - Opcode:          DW_LNS_advance_pc
2063           Data:            512
2064         - Opcode:          DW_LNS_advance_line
2065           SData:           1
2066           Data:            0
2067         - Opcode:          DW_LNS_copy
2068           Data:            0
2069         - Opcode:          DW_LNS_advance_pc
2070           Data:            3584
2071         - Opcode:          DW_LNS_extended_op
2072           ExtLen:          1
2073           SubOpcode:       DW_LNE_end_sequence
2074           Data:            0
2075   )";
2076   auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);
2077   ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());
2078   std::unique_ptr<DWARFContext> DwarfContext =
2079       DWARFContext::create(*ErrOrSections, 8);
2080   ASSERT_TRUE(DwarfContext.get() != nullptr);
2081   auto &OS = llvm::nulls();
2082   GsymCreator GC;
2083   DwarfTransformer DT(*DwarfContext, OS, GC);
2084   const uint32_t ThreadCount = 1;
2085   ASSERT_THAT_ERROR(DT.convert(ThreadCount), Succeeded());
2086   ASSERT_THAT_ERROR(GC.finalize(OS), Succeeded());
2087   SmallString<512> Str;
2088   raw_svector_ostream OutStrm(Str);
2089   const auto ByteOrder = support::endian::system_endianness();
2090   FileWriter FW(OutStrm, ByteOrder);
2091   ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());
2092   Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());
2093   ASSERT_THAT_EXPECTED(GR, Succeeded());
2094 
2095   EXPECT_EQ(GR->getNumAddresses(), 4u);
2096 
2097   auto ExpFI = GR->getFunctionInfo(0x1000);
2098   ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
2099   ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x2000));
2100   EXPECT_TRUE(ExpFI->OptLineTable);
2101   StringRef MethodName = GR->getString(ExpFI->Name);
2102   EXPECT_EQ(MethodName, "lines_no_decl");
2103   // Make sure have two line table entries and that get the first line entry
2104   // correct.
2105   EXPECT_EQ(ExpFI->OptLineTable->size(), 2u);
2106   EXPECT_EQ(ExpFI->OptLineTable->first()->Addr, 0x1000u);
2107   EXPECT_EQ(ExpFI->OptLineTable->first()->Line, 11u);
2108 
2109   ExpFI = GR->getFunctionInfo(0x2000);
2110   ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
2111   ASSERT_EQ(ExpFI->Range, AddressRange(0x2000, 0x3000));
2112   EXPECT_TRUE(ExpFI->OptLineTable);
2113   MethodName = GR->getString(ExpFI->Name);
2114   EXPECT_EQ(MethodName, "lines_with_decl");
2115   // Make sure have two line table entries and that we don't use line 20
2116   // from the DW_AT_decl_file/line as a line table entry.
2117   EXPECT_EQ(ExpFI->OptLineTable->size(), 2u);
2118   EXPECT_EQ(ExpFI->OptLineTable->first()->Addr, 0x2000u);
2119   EXPECT_EQ(ExpFI->OptLineTable->first()->Line, 21u);
2120 
2121   ExpFI = GR->getFunctionInfo(0x3000);
2122   ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
2123   ASSERT_EQ(ExpFI->Range, AddressRange(0x3000, 0x4000));
2124   // Make sure we have no line table.
2125   EXPECT_FALSE(ExpFI->OptLineTable.has_value());
2126   MethodName = GR->getString(ExpFI->Name);
2127   EXPECT_EQ(MethodName, "no_lines_no_decl");
2128 
2129   ExpFI = GR->getFunctionInfo(0x4000);
2130   ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
2131   ASSERT_EQ(ExpFI->Range, AddressRange(0x4000, 0x5000));
2132   EXPECT_TRUE(ExpFI->OptLineTable.has_value());
2133   MethodName = GR->getString(ExpFI->Name);
2134   EXPECT_EQ(MethodName, "no_lines_with_decl");
2135   // Make sure we have one line table entry that uses the DW_AT_decl_file/line
2136   // as the one and only line entry.
2137   EXPECT_EQ(ExpFI->OptLineTable->size(), 1u);
2138   EXPECT_EQ(ExpFI->OptLineTable->first()->Addr, 0x4000u);
2139   EXPECT_EQ(ExpFI->OptLineTable->first()->Line, 40u);
2140 }
2141 
2142 
2143 TEST(GSYMTest, TestDWARFDeadStripAddr4) {
2144   // Check that various techniques that compilers use for dead code stripping
2145   // work for 4 byte addresses. Make sure we keep the good functions and
2146   // strip any functions whose name starts with "stripped".
2147   //
2148   // 1 - Compilers might set the low PC to -1 (UINT32_MAX) for compile unit
2149   //     with 4 byte addresses ("stripped1")
2150   // 2 - Set the low and high PC to the same value ("stripped2")
2151   // 3 - Have the high PC lower than the low PC ("stripped3")
2152   //
2153   // 0x0000000b: DW_TAG_compile_unit
2154   //               DW_AT_name	("/tmp/main.c")
2155   //               DW_AT_low_pc	(0x0000000000001000)
2156   //               DW_AT_high_pc	(0x0000000000002000)
2157   //               DW_AT_language	(DW_LANG_C_plus_plus)
2158   //
2159   // 0x0000001a:   DW_TAG_subprogram
2160   //                 DW_AT_name	("main")
2161   //                 DW_AT_low_pc	(0x0000000000001000)
2162   //                 DW_AT_high_pc	(0x0000000000002000)
2163   //
2164   // 0x00000027:   DW_TAG_subprogram
2165   //                 DW_AT_name	("stripped1")
2166   //                 DW_AT_low_pc	(0x00000000ffffffff)
2167   //                 DW_AT_high_pc	(0x0000000100000000)
2168   //
2169   // 0x00000034:   DW_TAG_subprogram
2170   //                 DW_AT_name	("stripped2")
2171   //                 DW_AT_low_pc	(0x0000000000003000)
2172   //                 DW_AT_high_pc	(0x0000000000003000)
2173   //
2174   // 0x00000041:   DW_TAG_subprogram
2175   //                 DW_AT_name	("stripped3")
2176   //                 DW_AT_low_pc	(0x0000000000004000)
2177   //                 DW_AT_high_pc	(0x0000000000003fff)
2178   //
2179   // 0x0000004e:   NULL
2180 
2181   StringRef yamldata = R"(
2182   debug_str:
2183     - ''
2184     - '/tmp/main.c'
2185     - main
2186     - stripped1
2187     - stripped2
2188     - stripped3
2189   debug_abbrev:
2190     - Table:
2191         - Code:            0x00000001
2192           Tag:             DW_TAG_compile_unit
2193           Children:        DW_CHILDREN_yes
2194           Attributes:
2195             - Attribute:       DW_AT_name
2196               Form:            DW_FORM_strp
2197             - Attribute:       DW_AT_low_pc
2198               Form:            DW_FORM_addr
2199             - Attribute:       DW_AT_high_pc
2200               Form:            DW_FORM_data4
2201             - Attribute:       DW_AT_language
2202               Form:            DW_FORM_data2
2203         - Code:            0x00000002
2204           Tag:             DW_TAG_subprogram
2205           Children:        DW_CHILDREN_no
2206           Attributes:
2207             - Attribute:       DW_AT_name
2208               Form:            DW_FORM_strp
2209             - Attribute:       DW_AT_low_pc
2210               Form:            DW_FORM_addr
2211             - Attribute:       DW_AT_high_pc
2212               Form:            DW_FORM_data4
2213         - Code:            0x00000003
2214           Tag:             DW_TAG_subprogram
2215           Children:        DW_CHILDREN_no
2216           Attributes:
2217             - Attribute:       DW_AT_name
2218               Form:            DW_FORM_strp
2219             - Attribute:       DW_AT_low_pc
2220               Form:            DW_FORM_addr
2221             - Attribute:       DW_AT_high_pc
2222               Form:            DW_FORM_addr
2223   debug_info:
2224     - Version:         4
2225       AddrSize:        4
2226       Entries:
2227         - AbbrCode:        0x00000001
2228           Values:
2229             - Value:           0x0000000000000001
2230             - Value:           0x0000000000001000
2231             - Value:           0x0000000000001000
2232             - Value:           0x0000000000000004
2233         - AbbrCode:        0x00000002
2234           Values:
2235             - Value:           0x000000000000000D
2236             - Value:           0x0000000000001000
2237             - Value:           0x0000000000001000
2238         - AbbrCode:        0x00000002
2239           Values:
2240             - Value:           0x0000000000000012
2241             - Value:           0x00000000FFFFFFFF
2242             - Value:           0x0000000000000001
2243         - AbbrCode:        0x00000003
2244           Values:
2245             - Value:           0x000000000000001C
2246             - Value:           0x0000000000003000
2247             - Value:           0x0000000000003000
2248         - AbbrCode:        0x00000003
2249           Values:
2250             - Value:           0x0000000000000026
2251             - Value:           0x0000000000004000
2252             - Value:           0x0000000000003FFF
2253         - AbbrCode:        0x00000000
2254   )";
2255   auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);
2256   ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());
2257   std::unique_ptr<DWARFContext> DwarfContext =
2258       DWARFContext::create(*ErrOrSections, 4);
2259   ASSERT_TRUE(DwarfContext.get() != nullptr);
2260   auto &OS = llvm::nulls();
2261   GsymCreator GC;
2262   DwarfTransformer DT(*DwarfContext, OS, GC);
2263   const uint32_t ThreadCount = 1;
2264   ASSERT_THAT_ERROR(DT.convert(ThreadCount), Succeeded());
2265   ASSERT_THAT_ERROR(GC.finalize(OS), Succeeded());
2266   SmallString<512> Str;
2267   raw_svector_ostream OutStrm(Str);
2268   const auto ByteOrder = support::endian::system_endianness();
2269   FileWriter FW(OutStrm, ByteOrder);
2270   ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());
2271   Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());
2272   ASSERT_THAT_EXPECTED(GR, Succeeded());
2273 
2274   // Test that the only function that made it was the "main" function.
2275   EXPECT_EQ(GR->getNumAddresses(), 1u);
2276   auto ExpFI = GR->getFunctionInfo(0x1000);
2277   ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
2278   ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x2000));
2279   StringRef MethodName = GR->getString(ExpFI->Name);
2280   EXPECT_EQ(MethodName, "main");
2281 }
2282 
2283 TEST(GSYMTest, TestDWARFDeadStripAddr8) {
2284   // Check that various techniques that compilers use for dead code stripping
2285   // work for 4 byte addresses. Make sure we keep the good functions and
2286   // strip any functions whose name starts with "stripped".
2287   //
2288   // 1 - Compilers might set the low PC to -1 (UINT64_MAX) for compile unit
2289   //     with 8 byte addresses ("stripped1")
2290   // 2 - Set the low and high PC to the same value ("stripped2")
2291   // 3 - Have the high PC lower than the low PC ("stripped3")
2292   //
2293   // 0x0000000b: DW_TAG_compile_unit
2294   //               DW_AT_name	("/tmp/main.c")
2295   //               DW_AT_low_pc	(0x0000000000001000)
2296   //               DW_AT_high_pc	(0x0000000000002000)
2297   //               DW_AT_language	(DW_LANG_C_plus_plus)
2298   //
2299   // 0x0000001e:   DW_TAG_subprogram
2300   //                 DW_AT_name	("main")
2301   //                 DW_AT_low_pc	(0x0000000000001000)
2302   //                 DW_AT_high_pc	(0x0000000000002000)
2303   //
2304   // 0x0000002f:   DW_TAG_subprogram
2305   //                 DW_AT_name	("stripped1")
2306   //                 DW_AT_low_pc	(0xffffffffffffffff)
2307   //                 DW_AT_high_pc	(0x0000000000000000)
2308   //
2309   // 0x00000040:   DW_TAG_subprogram
2310   //                 DW_AT_name	("stripped2")
2311   //                 DW_AT_low_pc	(0x0000000000003000)
2312   //                 DW_AT_high_pc	(0x0000000000003000)
2313   //
2314   // 0x00000055:   DW_TAG_subprogram
2315   //                 DW_AT_name	("stripped3")
2316   //                 DW_AT_low_pc	(0x0000000000004000)
2317   //                 DW_AT_high_pc	(0x0000000000003fff)
2318   //
2319   // 0x0000006a:   NULL
2320 
2321   StringRef yamldata = R"(
2322   debug_str:
2323     - ''
2324     - '/tmp/main.c'
2325     - main
2326     - stripped1
2327     - stripped2
2328     - stripped3
2329   debug_abbrev:
2330     - Table:
2331         - Code:            0x00000001
2332           Tag:             DW_TAG_compile_unit
2333           Children:        DW_CHILDREN_yes
2334           Attributes:
2335             - Attribute:       DW_AT_name
2336               Form:            DW_FORM_strp
2337             - Attribute:       DW_AT_low_pc
2338               Form:            DW_FORM_addr
2339             - Attribute:       DW_AT_high_pc
2340               Form:            DW_FORM_data4
2341             - Attribute:       DW_AT_language
2342               Form:            DW_FORM_data2
2343         - Code:            0x00000002
2344           Tag:             DW_TAG_subprogram
2345           Children:        DW_CHILDREN_no
2346           Attributes:
2347             - Attribute:       DW_AT_name
2348               Form:            DW_FORM_strp
2349             - Attribute:       DW_AT_low_pc
2350               Form:            DW_FORM_addr
2351             - Attribute:       DW_AT_high_pc
2352               Form:            DW_FORM_data4
2353         - Code:            0x00000003
2354           Tag:             DW_TAG_subprogram
2355           Children:        DW_CHILDREN_no
2356           Attributes:
2357             - Attribute:       DW_AT_name
2358               Form:            DW_FORM_strp
2359             - Attribute:       DW_AT_low_pc
2360               Form:            DW_FORM_addr
2361             - Attribute:       DW_AT_high_pc
2362               Form:            DW_FORM_addr
2363   debug_info:
2364     - Version:         4
2365       AddrSize:        8
2366       Entries:
2367         - AbbrCode:        0x00000001
2368           Values:
2369             - Value:           0x0000000000000001
2370             - Value:           0x0000000000001000
2371             - Value:           0x0000000000001000
2372             - Value:           0x0000000000000004
2373         - AbbrCode:        0x00000002
2374           Values:
2375             - Value:           0x000000000000000D
2376             - Value:           0x0000000000001000
2377             - Value:           0x0000000000001000
2378         - AbbrCode:        0x00000002
2379           Values:
2380             - Value:           0x0000000000000012
2381             - Value:           0xFFFFFFFFFFFFFFFF
2382             - Value:           0x0000000000000001
2383         - AbbrCode:        0x00000003
2384           Values:
2385             - Value:           0x000000000000001C
2386             - Value:           0x0000000000003000
2387             - Value:           0x0000000000003000
2388         - AbbrCode:        0x00000003
2389           Values:
2390             - Value:           0x0000000000000026
2391             - Value:           0x0000000000004000
2392             - Value:           0x0000000000003FFF
2393         - AbbrCode:        0x00000000
2394   )";
2395   auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);
2396   ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());
2397   std::unique_ptr<DWARFContext> DwarfContext =
2398       DWARFContext::create(*ErrOrSections, 8);
2399   ASSERT_TRUE(DwarfContext.get() != nullptr);
2400   auto &OS = llvm::nulls();
2401   GsymCreator GC;
2402   DwarfTransformer DT(*DwarfContext, OS, GC);
2403   const uint32_t ThreadCount = 1;
2404   ASSERT_THAT_ERROR(DT.convert(ThreadCount), Succeeded());
2405   ASSERT_THAT_ERROR(GC.finalize(OS), Succeeded());
2406   SmallString<512> Str;
2407   raw_svector_ostream OutStrm(Str);
2408   const auto ByteOrder = support::endian::system_endianness();
2409   FileWriter FW(OutStrm, ByteOrder);
2410   ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());
2411   Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());
2412   ASSERT_THAT_EXPECTED(GR, Succeeded());
2413 
2414   // Test that the only function that made it was the "main" function.
2415   EXPECT_EQ(GR->getNumAddresses(), 1u);
2416   auto ExpFI = GR->getFunctionInfo(0x1000);
2417   ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
2418   ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x2000));
2419   StringRef MethodName = GR->getString(ExpFI->Name);
2420   EXPECT_EQ(MethodName, "main");
2421 }
2422 
2423 TEST(GSYMTest, TestGsymCreatorMultipleSymbolsWithNoSize) {
2424   // Multiple symbols at the same address with zero size were being emitted
2425   // instead of being combined into a single entry. This function tests to make
2426   // sure we only get one symbol.
2427   uint8_t UUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
2428   GsymCreator GC;
2429   GC.setUUID(UUID);
2430   constexpr uint64_t BaseAddr = 0x1000;
2431   constexpr uint8_t AddrOffSize = 1;
2432   const uint32_t Func1Name = GC.insertString("foo");
2433   const uint32_t Func2Name = GC.insertString("bar");
2434   GC.addFunctionInfo(FunctionInfo(BaseAddr, 0, Func1Name));
2435   GC.addFunctionInfo(FunctionInfo(BaseAddr, 0, Func2Name));
2436   Error Err = GC.finalize(llvm::nulls());
2437   ASSERT_FALSE(Err);
2438   TestEncodeDecode(GC, llvm::support::little, GSYM_VERSION, AddrOffSize,
2439                    BaseAddr,
2440                    1, // NumAddresses
2441                    ArrayRef<uint8_t>(UUID));
2442   TestEncodeDecode(GC, llvm::support::big, GSYM_VERSION, AddrOffSize, BaseAddr,
2443                    1, // NumAddresses
2444                    ArrayRef<uint8_t>(UUID));
2445 }
2446