xref: /llvm-project/llvm/unittests/DebugInfo/GSYM/GSYMTest.cpp (revision 5147e5941d40ae89b6ecab89aa36f8f5def28f1e)
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/OutputAggregator.h"
22 #include "llvm/DebugInfo/GSYM/StringTable.h"
23 #include "llvm/ObjectYAML/DWARFEmitter.h"
24 #include "llvm/Support/DataExtractor.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   // Test that if we have a function info without inline info and one with
144   // that the one without inline info is less than the one with.
145   FunctionInfo FIWithInlines = FISymtab;
146   FIWithInlines.Inline = InlineInfo();
147   FIWithInlines.Inline->Ranges.insert(
148       AddressRange(StartAddr, StartAddr + 0x10));
149   EXPECT_LT(FISymtab, FIWithInlines);
150 
151   // Test that if we have a function info with inline entries and one more
152   // inline entries that the one with fewer inline functins is less than the
153   // one with more.
154   FunctionInfo FIWithMoreInlines = FIWithInlines;
155   FIWithMoreInlines.Inline->Children.push_back(InlineInfo());
156   EXPECT_LT(FIWithInlines, FIWithMoreInlines);
157 
158   FunctionInfo FIWithLinesAndInline = FIWithLines;
159   FIWithLinesAndInline.Inline = InlineInfo();
160   FIWithLinesAndInline.Inline->Ranges.insert(
161       AddressRange(StartAddr, StartAddr + 0x10));
162   // Test that a FunctionInfo with name, size, and line entries is less than
163   // the same one with valid inline info
164   EXPECT_LT(FIWithLines, FIWithLinesAndInline);
165 
166   // Test if we have an entry with lines and one with more lines for the same
167   // range, the ones with more lines is greater than the one with less.
168   FunctionInfo FIWithMoreLines = FIWithLines;
169   FIWithMoreLines.OptLineTable->push(LineEntry(StartAddr,FileIdx,Line+5));
170   EXPECT_LT(FIWithLines, FIWithMoreLines);
171 
172   // Test that if we have the same number of lines we compare the line entries
173   // in the FunctionInfo.OptLineTable.Lines vector.
174   FunctionInfo FIWithLinesWithHigherAddress = FIWithLines;
175   FIWithLinesWithHigherAddress.OptLineTable->get(0).Addr += 0x10;
176   EXPECT_LT(FIWithLines, FIWithLinesWithHigherAddress);
177 }
178 
179 static void TestFunctionInfoDecodeError(llvm::endianness ByteOrder,
180                                         StringRef Bytes,
181                                         const uint64_t BaseAddr,
182                                         std::string ExpectedErrorMsg) {
183   uint8_t AddressSize = 4;
184   DataExtractor Data(Bytes, ByteOrder == llvm::endianness::little, AddressSize);
185   llvm::Expected<FunctionInfo> Decoded = FunctionInfo::decode(Data, BaseAddr);
186   // Make sure decoding fails.
187   ASSERT_FALSE((bool)Decoded);
188   // Make sure decoded object is the same as the one we encoded.
189   checkError(ExpectedErrorMsg, Decoded.takeError());
190 }
191 
192 TEST(GSYMTest, TestFunctionInfoDecodeErrors) {
193   // Test decoding FunctionInfo objects that ensure we report an appropriate
194   // error message.
195   const llvm::endianness ByteOrder = llvm::endianness::little;
196   SmallString<512> Str;
197   raw_svector_ostream OutStrm(Str);
198   FileWriter FW(OutStrm, ByteOrder);
199   const uint64_t BaseAddr = 0x100;
200   TestFunctionInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
201       "0x00000000: missing FunctionInfo Size");
202   FW.writeU32(0x100); // Function size.
203   TestFunctionInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
204       "0x00000004: missing FunctionInfo Name");
205   // Write out an invalid Name string table offset of zero.
206   FW.writeU32(0);
207   TestFunctionInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
208       "0x00000004: invalid FunctionInfo Name value 0x00000000");
209   // Modify the Name to be 0x00000001, which is a valid value.
210   FW.fixup32(0x00000001, 4);
211   TestFunctionInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
212       "0x00000008: missing FunctionInfo InfoType value");
213   auto FixupOffset = FW.tell();
214   FW.writeU32(1); // InfoType::LineTableInfo.
215   TestFunctionInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
216       "0x0000000c: missing FunctionInfo InfoType length");
217   FW.fixup32(7, FixupOffset); // Write an invalid InfoType enumeration value
218   FW.writeU32(0); // LineTableInfo InfoType data length.
219   TestFunctionInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
220                               "0x00000008: unsupported InfoType 7");
221 }
222 
223 static void TestFunctionInfoEncodeError(llvm::endianness ByteOrder,
224                                         const FunctionInfo &FI,
225                                         std::string ExpectedErrorMsg) {
226   SmallString<512> Str;
227   raw_svector_ostream OutStrm(Str);
228   FileWriter FW(OutStrm, ByteOrder);
229   Expected<uint64_t> ExpectedOffset = FI.encode(FW);
230   ASSERT_FALSE(ExpectedOffset);
231   checkError(ExpectedErrorMsg, ExpectedOffset.takeError());
232 }
233 
234 TEST(GSYMTest, TestFunctionInfoEncodeErrors) {
235   const uint64_t FuncAddr = 0x1000;
236   const uint64_t FuncSize = 0x100;
237   const uint32_t InvalidName = 0;
238   const uint32_t ValidName = 1;
239   FunctionInfo InvalidNameFI(FuncAddr, FuncSize, InvalidName);
240   TestFunctionInfoEncodeError(
241       llvm::endianness::little, InvalidNameFI,
242       "attempted to encode invalid FunctionInfo object");
243 
244   FunctionInfo InvalidLineTableFI(FuncAddr, FuncSize, ValidName);
245   // Empty line tables are not valid. Verify if the encoding of anything
246   // in our line table fails, that we see get the error propagated.
247   InvalidLineTableFI.OptLineTable = LineTable();
248   TestFunctionInfoEncodeError(llvm::endianness::little, InvalidLineTableFI,
249                               "attempted to encode invalid LineTable object");
250 
251   FunctionInfo InvalidInlineInfoFI(FuncAddr, FuncSize, ValidName);
252   // Empty line tables are not valid. Verify if the encoding of anything
253   // in our line table fails, that we see get the error propagated.
254   InvalidInlineInfoFI.Inline = InlineInfo();
255   TestFunctionInfoEncodeError(llvm::endianness::little, InvalidInlineInfoFI,
256                               "attempted to encode invalid InlineInfo object");
257 }
258 
259 static void TestFunctionInfoEncodeDecode(llvm::endianness ByteOrder,
260                                          const FunctionInfo &FI) {
261   // Test encoding and decoding FunctionInfo objects.
262   SmallString<512> Str;
263   raw_svector_ostream OutStrm(Str);
264   FileWriter FW(OutStrm, ByteOrder);
265   llvm::Expected<uint64_t> ExpectedOffset = FI.encode(FW);
266   ASSERT_TRUE(bool(ExpectedOffset));
267   // Verify we got the encoded offset back from the encode function.
268   ASSERT_EQ(ExpectedOffset.get(), 0ULL);
269   std::string Bytes(OutStrm.str());
270   uint8_t AddressSize = 4;
271   DataExtractor Data(Bytes, ByteOrder == llvm::endianness::little, AddressSize);
272   llvm::Expected<FunctionInfo> Decoded =
273       FunctionInfo::decode(Data, FI.Range.start());
274   // Make sure decoding succeeded.
275   ASSERT_TRUE((bool)Decoded);
276   // Make sure decoded object is the same as the one we encoded.
277   EXPECT_EQ(FI, Decoded.get());
278 }
279 
280 static void AddLines(uint64_t FuncAddr, uint32_t FileIdx, FunctionInfo &FI) {
281     FI.OptLineTable = LineTable();
282     LineEntry Line0(FuncAddr + 0x000, FileIdx, 10);
283     LineEntry Line1(FuncAddr + 0x010, FileIdx, 11);
284     LineEntry Line2(FuncAddr + 0x100, FileIdx, 1000);
285     FI.OptLineTable->push(Line0);
286     FI.OptLineTable->push(Line1);
287     FI.OptLineTable->push(Line2);
288 }
289 
290 
291 static void AddInline(uint64_t FuncAddr, uint64_t FuncSize, FunctionInfo &FI) {
292     FI.Inline = InlineInfo();
293     FI.Inline->Ranges.insert(AddressRange(FuncAddr, FuncAddr + FuncSize));
294     InlineInfo Inline1;
295     Inline1.Ranges.insert(AddressRange(FuncAddr + 0x10, FuncAddr + 0x30));
296     Inline1.Name = 1;
297     Inline1.CallFile = 1;
298     Inline1.CallLine = 11;
299     FI.Inline->Children.push_back(Inline1);
300 }
301 
302 TEST(GSYMTest, TestFunctionInfoEncoding) {
303   constexpr uint64_t FuncAddr = 0x1000;
304   constexpr uint64_t FuncSize = 0x100;
305   constexpr uint32_t FuncName = 1;
306   constexpr uint32_t FileIdx = 1;
307   // Make sure that we can encode and decode a FunctionInfo with no line table
308   // or inline info.
309   FunctionInfo FI(FuncAddr, FuncSize, FuncName);
310   TestFunctionInfoEncodeDecode(llvm::endianness::little, FI);
311   TestFunctionInfoEncodeDecode(llvm::endianness::big, FI);
312 
313   // Make sure that we can encode and decode a FunctionInfo with a line table
314   // and no inline info.
315   FunctionInfo FILines(FuncAddr, FuncSize, FuncName);
316   AddLines(FuncAddr, FileIdx, FILines);
317   TestFunctionInfoEncodeDecode(llvm::endianness::little, FILines);
318   TestFunctionInfoEncodeDecode(llvm::endianness::big, FILines);
319 
320   // Make sure that we can encode and decode a FunctionInfo with no line table
321   // and with inline info.
322   FunctionInfo FIInline(FuncAddr, FuncSize, FuncName);
323   AddInline(FuncAddr, FuncSize, FIInline);
324   TestFunctionInfoEncodeDecode(llvm::endianness::little, FIInline);
325   TestFunctionInfoEncodeDecode(llvm::endianness::big, FIInline);
326 
327   // Make sure that we can encode and decode a FunctionInfo with no line table
328   // and with inline info.
329   FunctionInfo FIBoth(FuncAddr, FuncSize, FuncName);
330   AddLines(FuncAddr, FileIdx, FIBoth);
331   AddInline(FuncAddr, FuncSize, FIBoth);
332   TestFunctionInfoEncodeDecode(llvm::endianness::little, FIBoth);
333   TestFunctionInfoEncodeDecode(llvm::endianness::big, FIBoth);
334 }
335 
336 static void TestInlineInfoEncodeDecode(llvm::endianness ByteOrder,
337                                        const InlineInfo &Inline) {
338   // Test encoding and decoding InlineInfo objects
339   SmallString<512> Str;
340   raw_svector_ostream OutStrm(Str);
341   FileWriter FW(OutStrm, ByteOrder);
342   const uint64_t BaseAddr = Inline.Ranges[0].start();
343   llvm::Error Err = Inline.encode(FW, BaseAddr);
344   ASSERT_FALSE(Err);
345   std::string Bytes(OutStrm.str());
346   uint8_t AddressSize = 4;
347   DataExtractor Data(Bytes, ByteOrder == llvm::endianness::little, AddressSize);
348   llvm::Expected<InlineInfo> Decoded = InlineInfo::decode(Data, BaseAddr);
349   // Make sure decoding succeeded.
350   ASSERT_TRUE((bool)Decoded);
351   // Make sure decoded object is the same as the one we encoded.
352   EXPECT_EQ(Inline, Decoded.get());
353 }
354 
355 static void TestInlineInfoDecodeError(llvm::endianness ByteOrder,
356                                       StringRef Bytes, const uint64_t BaseAddr,
357                                       std::string ExpectedErrorMsg) {
358   uint8_t AddressSize = 4;
359   DataExtractor Data(Bytes, ByteOrder == llvm::endianness::little, AddressSize);
360   llvm::Expected<InlineInfo> Decoded = InlineInfo::decode(Data, BaseAddr);
361   // Make sure decoding fails.
362   ASSERT_FALSE((bool)Decoded);
363   // Make sure decoded object is the same as the one we encoded.
364   checkError(ExpectedErrorMsg, Decoded.takeError());
365 }
366 
367 static void TestInlineInfoEncodeError(llvm::endianness ByteOrder,
368                                       const InlineInfo &Inline,
369                                       std::string ExpectedErrorMsg) {
370   SmallString<512> Str;
371   raw_svector_ostream OutStrm(Str);
372   FileWriter FW(OutStrm, ByteOrder);
373   const uint64_t BaseAddr =
374       Inline.Ranges.empty() ? 0 : Inline.Ranges[0].start();
375   llvm::Error Err = Inline.encode(FW, BaseAddr);
376   checkError(ExpectedErrorMsg, std::move(Err));
377 }
378 
379 TEST(GSYMTest, TestInlineInfo) {
380   // Test InlineInfo structs.
381   InlineInfo II;
382   EXPECT_FALSE(II.isValid());
383   II.Ranges.insert(AddressRange(0x1000, 0x2000));
384   // Make sure InlineInfo in valid with just an address range since
385   // top level InlineInfo objects have ranges with no name, call file
386   // or call line
387   EXPECT_TRUE(II.isValid());
388   // Make sure InlineInfo isn't after being cleared.
389   II.clear();
390   EXPECT_FALSE(II.isValid());
391 
392   // Create an InlineInfo that contains the following data. The
393   // indentation of the address range indicates the parent child
394   // relationships of the InlineInfo objects:
395   //
396   // Variable    Range and values
397   // =========== ====================================================
398   // Root        [0x100-0x200) (no name, file, or line)
399   // Inline1       [0x150-0x160) Name = 1, File = 1, Line = 11
400   // Inline1Sub1     [0x152-0x155) Name = 2, File = 2, Line = 22
401   // Inline1Sub2     [0x157-0x158) Name = 3, File = 3, Line = 33
402   InlineInfo Root;
403   Root.Ranges.insert(AddressRange(0x100, 0x200));
404   InlineInfo Inline1;
405   Inline1.Ranges.insert(AddressRange(0x150, 0x160));
406   Inline1.Name = 1;
407   Inline1.CallFile = 1;
408   Inline1.CallLine = 11;
409   InlineInfo Inline1Sub1;
410   Inline1Sub1.Ranges.insert(AddressRange(0x152, 0x155));
411   Inline1Sub1.Name = 2;
412   Inline1Sub1.CallFile = 2;
413   Inline1Sub1.CallLine = 22;
414   InlineInfo Inline1Sub2;
415   Inline1Sub2.Ranges.insert(AddressRange(0x157, 0x158));
416   Inline1Sub2.Name = 3;
417   Inline1Sub2.CallFile = 3;
418   Inline1Sub2.CallLine = 33;
419   Inline1.Children.push_back(Inline1Sub1);
420   Inline1.Children.push_back(Inline1Sub2);
421   Root.Children.push_back(Inline1);
422 
423   // Make sure an address that is out of range won't match
424   EXPECT_FALSE(Root.getInlineStack(0x50));
425 
426   // Verify that we get no inline stacks for addresses out of [0x100-0x200)
427   EXPECT_FALSE(Root.getInlineStack(Root.Ranges[0].start() - 1));
428   EXPECT_FALSE(Root.getInlineStack(Root.Ranges[0].end()));
429 
430   // Verify we get no inline stack entries for addresses that are in
431   // [0x100-0x200) but not in [0x150-0x160)
432   EXPECT_FALSE(Root.getInlineStack(Inline1.Ranges[0].start() - 1));
433   EXPECT_FALSE(Root.getInlineStack(Inline1.Ranges[0].end()));
434 
435   // Verify we get one inline stack entry for addresses that are in
436   // [[0x150-0x160)) but not in [0x152-0x155) or [0x157-0x158)
437   auto InlineInfos = Root.getInlineStack(Inline1.Ranges[0].start());
438   ASSERT_TRUE(InlineInfos);
439   ASSERT_EQ(InlineInfos->size(), 1u);
440   ASSERT_EQ(*InlineInfos->at(0), Inline1);
441   InlineInfos = Root.getInlineStack(Inline1.Ranges[0].end() - 1);
442   EXPECT_TRUE(InlineInfos);
443   ASSERT_EQ(InlineInfos->size(), 1u);
444   ASSERT_EQ(*InlineInfos->at(0), Inline1);
445 
446   // Verify we get two inline stack entries for addresses that are in
447   // [0x152-0x155)
448   InlineInfos = Root.getInlineStack(Inline1Sub1.Ranges[0].start());
449   EXPECT_TRUE(InlineInfos);
450   ASSERT_EQ(InlineInfos->size(), 2u);
451   ASSERT_EQ(*InlineInfos->at(0), Inline1Sub1);
452   ASSERT_EQ(*InlineInfos->at(1), Inline1);
453   InlineInfos = Root.getInlineStack(Inline1Sub1.Ranges[0].end() - 1);
454   EXPECT_TRUE(InlineInfos);
455   ASSERT_EQ(InlineInfos->size(), 2u);
456   ASSERT_EQ(*InlineInfos->at(0), Inline1Sub1);
457   ASSERT_EQ(*InlineInfos->at(1), Inline1);
458 
459   // Verify we get two inline stack entries for addresses that are in
460   // [0x157-0x158)
461   InlineInfos = Root.getInlineStack(Inline1Sub2.Ranges[0].start());
462   EXPECT_TRUE(InlineInfos);
463   ASSERT_EQ(InlineInfos->size(), 2u);
464   ASSERT_EQ(*InlineInfos->at(0), Inline1Sub2);
465   ASSERT_EQ(*InlineInfos->at(1), Inline1);
466   InlineInfos = Root.getInlineStack(Inline1Sub2.Ranges[0].end() - 1);
467   EXPECT_TRUE(InlineInfos);
468   ASSERT_EQ(InlineInfos->size(), 2u);
469   ASSERT_EQ(*InlineInfos->at(0), Inline1Sub2);
470   ASSERT_EQ(*InlineInfos->at(1), Inline1);
471 
472   // Test encoding and decoding InlineInfo objects
473   TestInlineInfoEncodeDecode(llvm::endianness::little, Root);
474   TestInlineInfoEncodeDecode(llvm::endianness::big, Root);
475 }
476 
477 TEST(GSYMTest, TestInlineInfoEncodeErrors) {
478   // Test InlineInfo encoding errors.
479 
480   // Test that we get an error when trying to encode an InlineInfo object
481   // that has no ranges.
482   InlineInfo Empty;
483   std::string EmptyErr("attempted to encode invalid InlineInfo object");
484   TestInlineInfoEncodeError(llvm::endianness::little, Empty, EmptyErr);
485   TestInlineInfoEncodeError(llvm::endianness::big, Empty, EmptyErr);
486 
487   // Verify that we get an error trying to encode an InlineInfo object that has
488   // a child InlineInfo that has no ranges.
489   InlineInfo ContainsEmpty;
490   ContainsEmpty.Ranges.insert({0x100, 0x200});
491   ContainsEmpty.Children.push_back(Empty);
492   TestInlineInfoEncodeError(llvm::endianness::little, ContainsEmpty, EmptyErr);
493   TestInlineInfoEncodeError(llvm::endianness::big, ContainsEmpty, EmptyErr);
494 
495   // Verify that we get an error trying to encode an InlineInfo object that has
496   // a child whose address range is not contained in the parent address range.
497   InlineInfo ChildNotContained;
498   std::string ChildNotContainedErr("child range not contained in parent");
499   ChildNotContained.Ranges.insert({0x100, 0x200});
500   InlineInfo ChildNotContainedChild;
501   ChildNotContainedChild.Ranges.insert({0x200, 0x300});
502   ChildNotContained.Children.push_back(ChildNotContainedChild);
503   TestInlineInfoEncodeError(llvm::endianness::little, ChildNotContained,
504                             ChildNotContainedErr);
505   TestInlineInfoEncodeError(llvm::endianness::big, ChildNotContained,
506                             ChildNotContainedErr);
507 }
508 
509 TEST(GSYMTest, TestInlineInfoDecodeErrors) {
510   // Test decoding InlineInfo objects that ensure we report an appropriate
511   // error message.
512   const llvm::endianness ByteOrder = llvm::endianness::little;
513   SmallString<512> Str;
514   raw_svector_ostream OutStrm(Str);
515   FileWriter FW(OutStrm, ByteOrder);
516   const uint64_t BaseAddr = 0x100;
517   TestInlineInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
518       "0x00000000: missing InlineInfo address ranges data");
519   AddressRanges Ranges;
520   Ranges.insert({BaseAddr, BaseAddr+0x100});
521   encodeRanges(Ranges, FW, BaseAddr);
522   TestInlineInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
523       "0x00000004: missing InlineInfo uint8_t indicating children");
524   FW.writeU8(0);
525   TestInlineInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
526       "0x00000005: missing InlineInfo uint32_t for name");
527   FW.writeU32(0);
528   TestInlineInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
529       "0x00000009: missing ULEB128 for InlineInfo call file");
530   FW.writeU8(0);
531   TestInlineInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
532       "0x0000000a: missing ULEB128 for InlineInfo call line");
533 }
534 
535 TEST(GSYMTest, TestLineEntry) {
536   // test llvm::gsym::LineEntry structs.
537   const uint64_t ValidAddr = 0x1000;
538   const uint64_t InvalidFileIdx = 0;
539   const uint32_t ValidFileIdx = 1;
540   const uint32_t ValidLine = 5;
541 
542   LineEntry Invalid;
543   EXPECT_FALSE(Invalid.isValid());
544   // Make sure that an entry is invalid if it has a bad file index.
545   LineEntry BadFile(ValidAddr, InvalidFileIdx, ValidLine);
546   EXPECT_FALSE(BadFile.isValid());
547   // Test operators
548   LineEntry E1(ValidAddr, ValidFileIdx, ValidLine);
549   LineEntry E2(ValidAddr, ValidFileIdx, ValidLine);
550   LineEntry DifferentAddr(ValidAddr + 1, ValidFileIdx, ValidLine);
551   LineEntry DifferentFile(ValidAddr, ValidFileIdx + 1, ValidLine);
552   LineEntry DifferentLine(ValidAddr, ValidFileIdx, ValidLine + 1);
553   EXPECT_TRUE(E1.isValid());
554   EXPECT_EQ(E1, E2);
555   EXPECT_NE(E1, DifferentAddr);
556   EXPECT_NE(E1, DifferentFile);
557   EXPECT_NE(E1, DifferentLine);
558   EXPECT_LT(E1, DifferentAddr);
559 }
560 
561 TEST(GSYMTest, TestStringTable) {
562   StringTable StrTab(StringRef("\0Hello\0World\0", 13));
563   // Test extracting strings from a string table.
564   EXPECT_EQ(StrTab.getString(0), "");
565   EXPECT_EQ(StrTab.getString(1), "Hello");
566   EXPECT_EQ(StrTab.getString(7), "World");
567   EXPECT_EQ(StrTab.getString(8), "orld");
568   // Test pointing to last NULL terminator gets empty string.
569   EXPECT_EQ(StrTab.getString(12), "");
570   // Test pointing to past end gets empty string.
571   EXPECT_EQ(StrTab.getString(13), "");
572 }
573 
574 static void TestFileWriterHelper(llvm::endianness ByteOrder) {
575   SmallString<512> Str;
576   raw_svector_ostream OutStrm(Str);
577   FileWriter FW(OutStrm, ByteOrder);
578   const int64_t MinSLEB = INT64_MIN;
579   const int64_t MaxSLEB = INT64_MAX;
580   const uint64_t MinULEB = 0;
581   const uint64_t MaxULEB = UINT64_MAX;
582   const uint8_t U8 = 0x10;
583   const uint16_t U16 = 0x1122;
584   const uint32_t U32 = 0x12345678;
585   const uint64_t U64 = 0x33445566778899aa;
586   const char *Hello = "hello";
587   FW.writeU8(U8);
588   FW.writeU16(U16);
589   FW.writeU32(U32);
590   FW.writeU64(U64);
591   FW.alignTo(16);
592   const off_t FixupOffset = FW.tell();
593   FW.writeU32(0);
594   FW.writeSLEB(MinSLEB);
595   FW.writeSLEB(MaxSLEB);
596   FW.writeULEB(MinULEB);
597   FW.writeULEB(MaxULEB);
598   FW.writeNullTerminated(Hello);
599   // Test Seek, Tell using Fixup32.
600   FW.fixup32(U32, FixupOffset);
601 
602   std::string Bytes(OutStrm.str());
603   uint8_t AddressSize = 4;
604   DataExtractor Data(Bytes, ByteOrder == llvm::endianness::little, AddressSize);
605   uint64_t Offset = 0;
606   EXPECT_EQ(Data.getU8(&Offset), U8);
607   EXPECT_EQ(Data.getU16(&Offset), U16);
608   EXPECT_EQ(Data.getU32(&Offset), U32);
609   EXPECT_EQ(Data.getU64(&Offset), U64);
610   Offset = alignTo(Offset, 16);
611   EXPECT_EQ(Data.getU32(&Offset), U32);
612   EXPECT_EQ(Data.getSLEB128(&Offset), MinSLEB);
613   EXPECT_EQ(Data.getSLEB128(&Offset), MaxSLEB);
614   EXPECT_EQ(Data.getULEB128(&Offset), MinULEB);
615   EXPECT_EQ(Data.getULEB128(&Offset), MaxULEB);
616   EXPECT_EQ(Data.getCStrRef(&Offset), StringRef(Hello));
617 }
618 
619 TEST(GSYMTest, TestFileWriter) {
620   TestFileWriterHelper(llvm::endianness::little);
621   TestFileWriterHelper(llvm::endianness::big);
622 }
623 
624 TEST(GSYMTest, TestAddressRangeEncodeDecode) {
625   // Test encoding and decoding AddressRange objects. AddressRange objects
626   // are always stored as offsets from the a base address. The base address
627   // is the FunctionInfo's base address for function level ranges, and is
628   // the base address of the parent range for subranges.
629   SmallString<512> Str;
630   raw_svector_ostream OutStrm(Str);
631   const auto ByteOrder = llvm::endianness::native;
632   FileWriter FW(OutStrm, ByteOrder);
633   const uint64_t BaseAddr = 0x1000;
634   const AddressRange Range1(0x1000, 0x1010);
635   const AddressRange Range2(0x1020, 0x1030);
636   encodeRange(Range1, FW, BaseAddr);
637   encodeRange(Range2, FW, BaseAddr);
638   std::string Bytes(OutStrm.str());
639   uint8_t AddressSize = 4;
640   DataExtractor Data(Bytes, ByteOrder == llvm::endianness::little, AddressSize);
641 
642   AddressRange DecodedRange1, DecodedRange2;
643   uint64_t Offset = 0;
644   DecodedRange1 = decodeRange(Data, BaseAddr, Offset);
645   DecodedRange2 = decodeRange(Data, BaseAddr, Offset);
646   EXPECT_EQ(Range1, DecodedRange1);
647   EXPECT_EQ(Range2, DecodedRange2);
648 }
649 
650 static void TestAddressRangeEncodeDecodeHelper(const AddressRanges &Ranges,
651                                                const uint64_t BaseAddr) {
652   SmallString<512> Str;
653   raw_svector_ostream OutStrm(Str);
654   const auto ByteOrder = llvm::endianness::native;
655   FileWriter FW(OutStrm, ByteOrder);
656   encodeRanges(Ranges, FW, BaseAddr);
657 
658   std::string Bytes(OutStrm.str());
659   uint8_t AddressSize = 4;
660   DataExtractor Data(Bytes, ByteOrder == llvm::endianness::little, AddressSize);
661 
662   AddressRanges DecodedRanges;
663   uint64_t Offset = 0;
664   decodeRanges(DecodedRanges, Data, BaseAddr, Offset);
665   EXPECT_EQ(Ranges, DecodedRanges);
666 }
667 
668 TEST(GSYMTest, TestAddressRangesEncodeDecode) {
669   // Test encoding and decoding AddressRanges. AddressRanges objects contain
670   // ranges that are stored as offsets from the a base address. The base address
671   // is the FunctionInfo's base address for function level ranges, and is the
672   // base address of the parent range for subranges.
673   const uint64_t BaseAddr = 0x1000;
674 
675   // Test encoding and decoding with no ranges.
676   AddressRanges Ranges;
677   TestAddressRangeEncodeDecodeHelper(Ranges, BaseAddr);
678 
679   // Test encoding and decoding with 1 range.
680   Ranges.insert(AddressRange(0x1000, 0x1010));
681   TestAddressRangeEncodeDecodeHelper(Ranges, BaseAddr);
682 
683   // Test encoding and decoding with multiple ranges.
684   Ranges.insert(AddressRange(0x1020, 0x1030));
685   Ranges.insert(AddressRange(0x1050, 0x1070));
686   TestAddressRangeEncodeDecodeHelper(Ranges, BaseAddr);
687 }
688 
689 static void TestLineTableHelper(llvm::endianness ByteOrder,
690                                 const LineTable &LT) {
691   SmallString<512> Str;
692   raw_svector_ostream OutStrm(Str);
693   FileWriter FW(OutStrm, ByteOrder);
694   const uint64_t BaseAddr = LT[0].Addr;
695   llvm::Error Err = LT.encode(FW, BaseAddr);
696   ASSERT_FALSE(Err);
697   std::string Bytes(OutStrm.str());
698   uint8_t AddressSize = 4;
699   DataExtractor Data(Bytes, ByteOrder == llvm::endianness::little, AddressSize);
700   llvm::Expected<LineTable> Decoded = LineTable::decode(Data, BaseAddr);
701   // Make sure decoding succeeded.
702   ASSERT_TRUE((bool)Decoded);
703   // Make sure decoded object is the same as the one we encoded.
704   EXPECT_EQ(LT, Decoded.get());
705 }
706 
707 TEST(GSYMTest, TestLineTable) {
708   const uint64_t StartAddr = 0x1000;
709   const uint32_t FileIdx = 1;
710   LineTable LT;
711   LineEntry Line0(StartAddr+0x000, FileIdx, 10);
712   LineEntry Line1(StartAddr+0x010, FileIdx, 11);
713   LineEntry Line2(StartAddr+0x100, FileIdx, 1000);
714   ASSERT_TRUE(LT.empty());
715   ASSERT_EQ(LT.size(), (size_t)0);
716   LT.push(Line0);
717   ASSERT_EQ(LT.size(), (size_t)1);
718   LT.push(Line1);
719   LT.push(Line2);
720   LT.push(LineEntry(StartAddr+0x120, FileIdx, 900));
721   LT.push(LineEntry(StartAddr+0x120, FileIdx, 2000));
722   LT.push(LineEntry(StartAddr+0x121, FileIdx, 2001));
723   LT.push(LineEntry(StartAddr+0x122, FileIdx, 2002));
724   LT.push(LineEntry(StartAddr+0x123, FileIdx, 2003));
725   ASSERT_FALSE(LT.empty());
726   ASSERT_EQ(LT.size(), (size_t)8);
727   // Test operator[].
728   ASSERT_EQ(LT[0], Line0);
729   ASSERT_EQ(LT[1], Line1);
730   ASSERT_EQ(LT[2], Line2);
731 
732   // Test encoding and decoding line tables.
733   TestLineTableHelper(llvm::endianness::little, LT);
734   TestLineTableHelper(llvm::endianness::big, LT);
735 
736   // Verify the clear method works as expected.
737   LT.clear();
738   ASSERT_TRUE(LT.empty());
739   ASSERT_EQ(LT.size(), (size_t)0);
740 
741   LineTable LT1;
742   LineTable LT2;
743 
744   // Test that two empty line tables are equal and neither are less than
745   // each other.
746   ASSERT_EQ(LT1, LT2);
747   ASSERT_FALSE(LT1 < LT1);
748   ASSERT_FALSE(LT1 < LT2);
749   ASSERT_FALSE(LT2 < LT1);
750   ASSERT_FALSE(LT2 < LT2);
751 
752   // Test that a line table with less number of line entries is less than a
753   // line table with more line entries and that they are not equal.
754   LT2.push(Line0);
755   ASSERT_LT(LT1, LT2);
756   ASSERT_NE(LT1, LT2);
757 
758   // Test that two line tables with the same entries are equal.
759   LT1.push(Line0);
760   ASSERT_EQ(LT1, LT2);
761   ASSERT_FALSE(LT1 < LT2);
762   ASSERT_FALSE(LT2 < LT2);
763 }
764 
765 static void TestLineTableDecodeError(llvm::endianness ByteOrder,
766                                      StringRef Bytes, const uint64_t BaseAddr,
767                                      std::string ExpectedErrorMsg) {
768   uint8_t AddressSize = 4;
769   DataExtractor Data(Bytes, ByteOrder == llvm::endianness::little, AddressSize);
770   llvm::Expected<LineTable> Decoded = LineTable::decode(Data, BaseAddr);
771   // Make sure decoding fails.
772   ASSERT_FALSE((bool)Decoded);
773   // Make sure decoded object is the same as the one we encoded.
774   checkError(ExpectedErrorMsg, Decoded.takeError());
775 }
776 
777 TEST(GSYMTest, TestLineTableDecodeErrors) {
778   // Test decoding InlineInfo objects that ensure we report an appropriate
779   // error message.
780   const llvm::endianness ByteOrder = llvm::endianness::little;
781   SmallString<512> Str;
782   raw_svector_ostream OutStrm(Str);
783   FileWriter FW(OutStrm, ByteOrder);
784   const uint64_t BaseAddr = 0x100;
785   TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
786       "0x00000000: missing LineTable MinDelta");
787   FW.writeU8(1); // MinDelta (ULEB)
788   TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
789       "0x00000001: missing LineTable MaxDelta");
790   FW.writeU8(10); // MaxDelta (ULEB)
791   TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
792       "0x00000002: missing LineTable FirstLine");
793   FW.writeU8(20); // FirstLine (ULEB)
794   TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
795       "0x00000003: EOF found before EndSequence");
796   // Test a SetFile with the argument missing from the stream
797   FW.writeU8(1); // SetFile opcode (uint8_t)
798   TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
799       "0x00000004: EOF found before SetFile value");
800   FW.writeU8(5); // SetFile value as index (ULEB)
801   // Test a AdvancePC with the argument missing from the stream
802   FW.writeU8(2); // AdvancePC opcode (uint8_t)
803   TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
804       "0x00000006: EOF found before AdvancePC value");
805   FW.writeU8(20); // AdvancePC value as offset (ULEB)
806   // Test a AdvancePC with the argument missing from the stream
807   FW.writeU8(3); // AdvanceLine opcode (uint8_t)
808   TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
809       "0x00000008: EOF found before AdvanceLine value");
810   FW.writeU8(20); // AdvanceLine value as offset (LLEB)
811 }
812 
813 TEST(GSYMTest, TestLineTableEncodeErrors) {
814   const uint64_t BaseAddr = 0x1000;
815   const uint32_t FileIdx = 1;
816   const llvm::endianness ByteOrder = llvm::endianness::little;
817   SmallString<512> Str;
818   raw_svector_ostream OutStrm(Str);
819   FileWriter FW(OutStrm, ByteOrder);
820   LineTable LT;
821   checkError("attempted to encode invalid LineTable object",
822              LT.encode(FW, BaseAddr));
823 
824   // Try to encode a line table where a line entry has an address that is less
825   // than BaseAddr and verify we get an appropriate error.
826   LineEntry Line0(BaseAddr+0x000, FileIdx, 10);
827   LineEntry Line1(BaseAddr+0x010, FileIdx, 11);
828   LT.push(Line0);
829   LT.push(Line1);
830   checkError("LineEntry has address 0x1000 which is less than the function "
831              "start address 0x1010", LT.encode(FW, BaseAddr+0x10));
832   LT.clear();
833 
834   // Try to encode a line table where a line entries  has an address that is less
835   // than BaseAddr and verify we get an appropriate error.
836   LT.push(Line1);
837   LT.push(Line0);
838   checkError("LineEntry in LineTable not in ascending order",
839              LT.encode(FW, BaseAddr));
840   LT.clear();
841 }
842 
843 static void TestHeaderEncodeError(const Header &H,
844                                   std::string ExpectedErrorMsg) {
845   const llvm::endianness ByteOrder = llvm::endianness::little;
846   SmallString<512> Str;
847   raw_svector_ostream OutStrm(Str);
848   FileWriter FW(OutStrm, ByteOrder);
849   llvm::Error Err = H.encode(FW);
850   checkError(ExpectedErrorMsg, std::move(Err));
851 }
852 
853 static void TestHeaderDecodeError(StringRef Bytes,
854                                   std::string ExpectedErrorMsg) {
855   const llvm::endianness ByteOrder = llvm::endianness::little;
856   uint8_t AddressSize = 4;
857   DataExtractor Data(Bytes, ByteOrder == llvm::endianness::little, AddressSize);
858   llvm::Expected<Header> Decoded = Header::decode(Data);
859   // Make sure decoding fails.
860   ASSERT_FALSE((bool)Decoded);
861   // Make sure decoded object is the same as the one we encoded.
862   checkError(ExpectedErrorMsg, Decoded.takeError());
863 }
864 
865 // Populate a GSYM header with valid values.
866 static void InitHeader(Header &H) {
867   H.Magic = GSYM_MAGIC;
868   H.Version = GSYM_VERSION;
869   H.AddrOffSize = 4;
870   H.UUIDSize = 16;
871   H.BaseAddress = 0x1000;
872   H.NumAddresses = 1;
873   H.StrtabOffset= 0x2000;
874   H.StrtabSize = 0x1000;
875   for (size_t i=0; i<GSYM_MAX_UUID_SIZE; ++i) {
876     if (i < H.UUIDSize)
877       H.UUID[i] = i;
878     else
879       H.UUID[i] = 0;
880   }
881 }
882 
883 TEST(GSYMTest, TestHeaderEncodeErrors) {
884   Header H;
885   InitHeader(H);
886   H.Magic = 12;
887   TestHeaderEncodeError(H, "invalid GSYM magic 0x0000000c");
888   InitHeader(H);
889   H.Version = 12;
890   TestHeaderEncodeError(H, "unsupported GSYM version 12");
891   InitHeader(H);
892   H.AddrOffSize = 12;
893   TestHeaderEncodeError(H, "invalid address offset size 12");
894   InitHeader(H);
895   H.UUIDSize = 128;
896   TestHeaderEncodeError(H, "invalid UUID size 128");
897 }
898 
899 TEST(GSYMTest, TestHeaderDecodeErrors) {
900   const llvm::endianness ByteOrder = llvm::endianness::little;
901   SmallString<512> Str;
902   raw_svector_ostream OutStrm(Str);
903   FileWriter FW(OutStrm, ByteOrder);
904   Header H;
905   InitHeader(H);
906   llvm::Error Err = H.encode(FW);
907   ASSERT_FALSE(Err);
908   FW.fixup32(12, offsetof(Header, Magic));
909   TestHeaderDecodeError(OutStrm.str(), "invalid GSYM magic 0x0000000c");
910   FW.fixup32(GSYM_MAGIC, offsetof(Header, Magic));
911   FW.fixup32(12, offsetof(Header, Version));
912   TestHeaderDecodeError(OutStrm.str(), "unsupported GSYM version 12");
913   FW.fixup32(GSYM_VERSION, offsetof(Header, Version));
914   FW.fixup32(12, offsetof(Header, AddrOffSize));
915   TestHeaderDecodeError(OutStrm.str(), "invalid address offset size 12");
916   FW.fixup32(4, offsetof(Header, AddrOffSize));
917   FW.fixup32(128, offsetof(Header, UUIDSize));
918   TestHeaderDecodeError(OutStrm.str(), "invalid UUID size 128");
919 }
920 
921 static void TestHeaderEncodeDecode(const Header &H,
922                                    llvm::endianness ByteOrder) {
923   uint8_t AddressSize = 4;
924   SmallString<512> Str;
925   raw_svector_ostream OutStrm(Str);
926   FileWriter FW(OutStrm, ByteOrder);
927   llvm::Error Err = H.encode(FW);
928   ASSERT_FALSE(Err);
929   std::string Bytes(OutStrm.str());
930   DataExtractor Data(Bytes, ByteOrder == llvm::endianness::little, AddressSize);
931   llvm::Expected<Header> Decoded = Header::decode(Data);
932   // Make sure decoding succeeded.
933   ASSERT_TRUE((bool)Decoded);
934   EXPECT_EQ(H, Decoded.get());
935 }
936 TEST(GSYMTest, TestHeaderEncodeDecode) {
937   Header H;
938   InitHeader(H);
939   TestHeaderEncodeDecode(H, llvm::endianness::little);
940   TestHeaderEncodeDecode(H, llvm::endianness::big);
941 }
942 
943 static void TestGsymCreatorEncodeError(llvm::endianness ByteOrder,
944                                        const GsymCreator &GC,
945                                        std::string ExpectedErrorMsg) {
946   SmallString<512> Str;
947   raw_svector_ostream OutStrm(Str);
948   FileWriter FW(OutStrm, ByteOrder);
949   llvm::Error Err = GC.encode(FW);
950   ASSERT_TRUE(bool(Err));
951   checkError(ExpectedErrorMsg, std::move(Err));
952 }
953 
954 TEST(GSYMTest, TestGsymCreatorEncodeErrors) {
955   const uint8_t ValidUUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
956                                14, 15, 16};
957   const uint8_t InvalidUUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
958                                  14, 15, 16, 17, 18, 19, 20, 21};
959   // Verify we get an error when trying to encode an GsymCreator with no
960   // function infos. We shouldn't be saving a GSYM file in this case since
961   // there is nothing inside of it.
962   GsymCreator GC;
963   TestGsymCreatorEncodeError(llvm::endianness::little, GC,
964                              "no functions to encode");
965   const uint64_t FuncAddr = 0x1000;
966   const uint64_t FuncSize = 0x100;
967   const uint32_t FuncName = GC.insertString("foo");
968   // Verify we get an error trying to encode a GsymCreator that isn't
969   // finalized.
970   GC.addFunctionInfo(FunctionInfo(FuncAddr, FuncSize, FuncName));
971   TestGsymCreatorEncodeError(llvm::endianness::little, GC,
972                              "GsymCreator wasn't finalized prior to encoding");
973   std::string finalizeIssues;
974   raw_string_ostream OS(finalizeIssues);
975   OutputAggregator Agg(&OS);
976   llvm::Error finalizeErr = GC.finalize(Agg);
977   ASSERT_FALSE(bool(finalizeErr));
978   finalizeErr = GC.finalize(Agg);
979   ASSERT_TRUE(bool(finalizeErr));
980   checkError("already finalized", std::move(finalizeErr));
981   // Verify we get an error trying to encode a GsymCreator with a UUID that is
982   // too long.
983   GC.setUUID(InvalidUUID);
984   TestGsymCreatorEncodeError(llvm::endianness::little, GC,
985                              "invalid UUID size 21");
986   GC.setUUID(ValidUUID);
987   // Verify errors are propagated when we try to encoding an invalid line
988   // table.
989   GC.forEachFunctionInfo([](FunctionInfo &FI) -> bool {
990     FI.OptLineTable = LineTable(); // Invalid line table.
991     return false; // Stop iterating
992   });
993   TestGsymCreatorEncodeError(llvm::endianness::little, GC,
994                              "attempted to encode invalid LineTable object");
995   // Verify errors are propagated when we try to encoding an invalid inline
996   // info.
997   GC.forEachFunctionInfo([](FunctionInfo &FI) -> bool {
998     FI.OptLineTable = std::nullopt;
999     FI.Inline = InlineInfo(); // Invalid InlineInfo.
1000     return false; // Stop iterating
1001   });
1002   TestGsymCreatorEncodeError(llvm::endianness::little, GC,
1003                              "attempted to encode invalid InlineInfo object");
1004 }
1005 
1006 static void Compare(const GsymCreator &GC, const GsymReader &GR) {
1007   // Verify that all of the data in a GsymCreator is correctly decoded from
1008   // a GsymReader. To do this, we iterator over
1009   GC.forEachFunctionInfo([&](const FunctionInfo &FI) -> bool {
1010     auto DecodedFI = GR.getFunctionInfo(FI.Range.start());
1011     EXPECT_TRUE(bool(DecodedFI));
1012     EXPECT_EQ(FI, *DecodedFI);
1013     return true; // Keep iterating over all FunctionInfo objects.
1014   });
1015 }
1016 
1017 static void TestEncodeDecode(const GsymCreator &GC, llvm::endianness ByteOrder,
1018                              uint16_t Version, uint8_t AddrOffSize,
1019                              uint64_t BaseAddress, uint32_t NumAddresses,
1020                              ArrayRef<uint8_t> UUID) {
1021   SmallString<512> Str;
1022   raw_svector_ostream OutStrm(Str);
1023   FileWriter FW(OutStrm, ByteOrder);
1024   llvm::Error Err = GC.encode(FW);
1025   ASSERT_FALSE((bool)Err);
1026   Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());
1027   ASSERT_TRUE(bool(GR));
1028   const Header &Hdr = GR->getHeader();
1029   EXPECT_EQ(Hdr.Version, Version);
1030   EXPECT_EQ(Hdr.AddrOffSize, AddrOffSize);
1031   EXPECT_EQ(Hdr.UUIDSize, UUID.size());
1032   EXPECT_EQ(Hdr.BaseAddress, BaseAddress);
1033   EXPECT_EQ(Hdr.NumAddresses, NumAddresses);
1034   EXPECT_EQ(ArrayRef<uint8_t>(Hdr.UUID, Hdr.UUIDSize), UUID);
1035   Compare(GC, GR.get());
1036 }
1037 
1038 TEST(GSYMTest, TestGsymCreator1ByteAddrOffsets) {
1039   uint8_t UUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
1040   GsymCreator GC;
1041   GC.setUUID(UUID);
1042   constexpr uint64_t BaseAddr = 0x1000;
1043   constexpr uint8_t AddrOffSize = 1;
1044   const uint32_t Func1Name = GC.insertString("foo");
1045   const uint32_t Func2Name = GC.insertString("bar");
1046   GC.addFunctionInfo(FunctionInfo(BaseAddr+0x00, 0x10, Func1Name));
1047   GC.addFunctionInfo(FunctionInfo(BaseAddr+0x20, 0x10, Func2Name));
1048   OutputAggregator Null(nullptr);
1049   Error Err = GC.finalize(Null);
1050   ASSERT_FALSE(Err);
1051   TestEncodeDecode(GC, llvm::endianness::little, GSYM_VERSION, AddrOffSize,
1052                    BaseAddr,
1053                    2, // NumAddresses
1054                    ArrayRef<uint8_t>(UUID));
1055   TestEncodeDecode(GC, llvm::endianness::big, GSYM_VERSION, AddrOffSize,
1056                    BaseAddr,
1057                    2, // NumAddresses
1058                    ArrayRef<uint8_t>(UUID));
1059 }
1060 
1061 TEST(GSYMTest, TestGsymCreator2ByteAddrOffsets) {
1062   uint8_t UUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
1063   GsymCreator GC;
1064   GC.setUUID(UUID);
1065   constexpr uint64_t BaseAddr = 0x1000;
1066   constexpr uint8_t AddrOffSize = 2;
1067   const uint32_t Func1Name = GC.insertString("foo");
1068   const uint32_t Func2Name = GC.insertString("bar");
1069   GC.addFunctionInfo(FunctionInfo(BaseAddr+0x000, 0x100, Func1Name));
1070   GC.addFunctionInfo(FunctionInfo(BaseAddr+0x200, 0x100, Func2Name));
1071   OutputAggregator Null(nullptr);
1072   Error Err = GC.finalize(Null);
1073   ASSERT_FALSE(Err);
1074   TestEncodeDecode(GC, llvm::endianness::little, GSYM_VERSION, AddrOffSize,
1075                    BaseAddr,
1076                    2, // NumAddresses
1077                    ArrayRef<uint8_t>(UUID));
1078   TestEncodeDecode(GC, llvm::endianness::big, GSYM_VERSION, AddrOffSize,
1079                    BaseAddr,
1080                    2, // NumAddresses
1081                    ArrayRef<uint8_t>(UUID));
1082 }
1083 
1084 TEST(GSYMTest, TestGsymCreator4ByteAddrOffsets) {
1085   uint8_t UUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
1086   GsymCreator GC;
1087   GC.setUUID(UUID);
1088   constexpr uint64_t BaseAddr = 0x1000;
1089   constexpr uint8_t AddrOffSize = 4;
1090   const uint32_t Func1Name = GC.insertString("foo");
1091   const uint32_t Func2Name = GC.insertString("bar");
1092   GC.addFunctionInfo(FunctionInfo(BaseAddr+0x000, 0x100, Func1Name));
1093   GC.addFunctionInfo(FunctionInfo(BaseAddr+0x20000, 0x100, Func2Name));
1094   OutputAggregator Null(nullptr);
1095   Error Err = GC.finalize(Null);
1096   ASSERT_FALSE(Err);
1097   TestEncodeDecode(GC, llvm::endianness::little, GSYM_VERSION, AddrOffSize,
1098                    BaseAddr,
1099                    2, // NumAddresses
1100                    ArrayRef<uint8_t>(UUID));
1101   TestEncodeDecode(GC, llvm::endianness::big, GSYM_VERSION, AddrOffSize,
1102                    BaseAddr,
1103                    2, // NumAddresses
1104                    ArrayRef<uint8_t>(UUID));
1105 }
1106 
1107 TEST(GSYMTest, TestGsymCreator8ByteAddrOffsets) {
1108   uint8_t UUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
1109   GsymCreator GC;
1110   GC.setUUID(UUID);
1111   constexpr uint64_t BaseAddr = 0x1000;
1112   constexpr uint8_t AddrOffSize = 8;
1113   const uint32_t Func1Name = GC.insertString("foo");
1114   const uint32_t Func2Name = GC.insertString("bar");
1115   GC.addFunctionInfo(FunctionInfo(BaseAddr+0x000, 0x100, Func1Name));
1116   GC.addFunctionInfo(FunctionInfo(BaseAddr+0x100000000, 0x100, Func2Name));
1117   OutputAggregator Null(nullptr);
1118   Error Err = GC.finalize(Null);
1119   ASSERT_FALSE(Err);
1120   TestEncodeDecode(GC, llvm::endianness::little, GSYM_VERSION, AddrOffSize,
1121                    BaseAddr,
1122                    2, // NumAddresses
1123                    ArrayRef<uint8_t>(UUID));
1124   TestEncodeDecode(GC, llvm::endianness::big, GSYM_VERSION, AddrOffSize,
1125                    BaseAddr,
1126                    2, // NumAddresses
1127                    ArrayRef<uint8_t>(UUID));
1128 }
1129 
1130 static void VerifyFunctionInfo(const GsymReader &GR, uint64_t Addr,
1131                                const FunctionInfo &FI) {
1132   auto ExpFI = GR.getFunctionInfo(Addr);
1133   ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
1134   ASSERT_EQ(FI, ExpFI.get());
1135 }
1136 
1137 static void VerifyFunctionInfoError(const GsymReader &GR, uint64_t Addr,
1138                                     std::string ErrMessage) {
1139   auto ExpFI = GR.getFunctionInfo(Addr);
1140   ASSERT_FALSE(bool(ExpFI));
1141   checkError(ErrMessage, ExpFI.takeError());
1142 }
1143 
1144 TEST(GSYMTest, TestGsymReader) {
1145   uint8_t UUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
1146   GsymCreator GC;
1147   GC.setUUID(UUID);
1148   constexpr uint64_t BaseAddr = 0x1000;
1149   constexpr uint64_t Func1Addr = BaseAddr;
1150   constexpr uint64_t Func2Addr = BaseAddr+0x20;
1151   constexpr uint64_t FuncSize = 0x10;
1152   const uint32_t Func1Name = GC.insertString("foo");
1153   const uint32_t Func2Name = GC.insertString("bar");
1154   const auto ByteOrder = llvm::endianness::native;
1155   GC.addFunctionInfo(FunctionInfo(Func1Addr, FuncSize, Func1Name));
1156   GC.addFunctionInfo(FunctionInfo(Func2Addr, FuncSize, Func2Name));
1157   OutputAggregator Null(nullptr);
1158   Error FinalizeErr = GC.finalize(Null);
1159   ASSERT_FALSE(FinalizeErr);
1160   SmallString<512> Str;
1161   raw_svector_ostream OutStrm(Str);
1162   FileWriter FW(OutStrm, ByteOrder);
1163   llvm::Error Err = GC.encode(FW);
1164   ASSERT_FALSE((bool)Err);
1165   if (auto ExpectedGR = GsymReader::copyBuffer(OutStrm.str())) {
1166     const GsymReader &GR = ExpectedGR.get();
1167     VerifyFunctionInfoError(GR, Func1Addr-1, "address 0xfff is not in GSYM");
1168 
1169     FunctionInfo Func1(Func1Addr, FuncSize, Func1Name);
1170     VerifyFunctionInfo(GR, Func1Addr, Func1);
1171     VerifyFunctionInfo(GR, Func1Addr+1, Func1);
1172     VerifyFunctionInfo(GR, Func1Addr+FuncSize-1, Func1);
1173     VerifyFunctionInfoError(GR, Func1Addr+FuncSize,
1174                             "address 0x1010 is not in GSYM");
1175     VerifyFunctionInfoError(GR, Func2Addr-1, "address 0x101f is not in GSYM");
1176     FunctionInfo Func2(Func2Addr, FuncSize, Func2Name);
1177     VerifyFunctionInfo(GR, Func2Addr, Func2);
1178     VerifyFunctionInfo(GR, Func2Addr+1, Func2);
1179     VerifyFunctionInfo(GR, Func2Addr+FuncSize-1, Func2);
1180     VerifyFunctionInfoError(GR, Func2Addr+FuncSize,
1181                             "address 0x1030 is not in GSYM");
1182   }
1183 }
1184 
1185 TEST(GSYMTest, TestGsymLookups) {
1186   // Test creating a GSYM file with a function that has a inline information.
1187   // Verify that lookups work correctly. Lookups do not decode the entire
1188   // FunctionInfo or InlineInfo, they only extract information needed for the
1189   // lookup to happen which avoids allocations which can slow down
1190   // symbolication.
1191   GsymCreator GC;
1192   FunctionInfo FI(0x1000, 0x100, GC.insertString("main"));
1193   const auto ByteOrder = llvm::endianness::native;
1194   FI.OptLineTable = LineTable();
1195   const uint32_t MainFileIndex = GC.insertFile("/tmp/main.c");
1196   const uint32_t FooFileIndex = GC.insertFile("/tmp/foo.h");
1197   FI.OptLineTable->push(LineEntry(0x1000, MainFileIndex, 5));
1198   FI.OptLineTable->push(LineEntry(0x1010, FooFileIndex, 10));
1199   FI.OptLineTable->push(LineEntry(0x1012, FooFileIndex, 20));
1200   FI.OptLineTable->push(LineEntry(0x1014, FooFileIndex, 11));
1201   FI.OptLineTable->push(LineEntry(0x1016, FooFileIndex, 30));
1202   FI.OptLineTable->push(LineEntry(0x1018, FooFileIndex, 12));
1203   FI.OptLineTable->push(LineEntry(0x1020, MainFileIndex, 8));
1204   FI.Inline = InlineInfo();
1205 
1206   FI.Inline->Name = GC.insertString("inline1");
1207   FI.Inline->CallFile = MainFileIndex;
1208   FI.Inline->CallLine = 6;
1209   FI.Inline->Ranges.insert(AddressRange(0x1010, 0x1020));
1210   InlineInfo Inline2;
1211   Inline2.Name = GC.insertString("inline2");
1212   Inline2.CallFile = FooFileIndex;
1213   Inline2.CallLine = 33;
1214   Inline2.Ranges.insert(AddressRange(0x1012, 0x1014));
1215   FI.Inline->Children.emplace_back(Inline2);
1216   InlineInfo Inline3;
1217   Inline3.Name = GC.insertString("inline3");
1218   Inline3.CallFile = FooFileIndex;
1219   Inline3.CallLine = 35;
1220   Inline3.Ranges.insert(AddressRange(0x1016, 0x1018));
1221   FI.Inline->Children.emplace_back(Inline3);
1222   GC.addFunctionInfo(std::move(FI));
1223   OutputAggregator Null(nullptr);
1224   Error FinalizeErr = GC.finalize(Null);
1225   ASSERT_FALSE(FinalizeErr);
1226   SmallString<512> Str;
1227   raw_svector_ostream OutStrm(Str);
1228   FileWriter FW(OutStrm, ByteOrder);
1229   llvm::Error Err = GC.encode(FW);
1230   ASSERT_FALSE((bool)Err);
1231   Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());
1232   ASSERT_TRUE(bool(GR));
1233 
1234   // Verify inline info is correct when doing lookups.
1235   auto LR = GR->lookup(0x1000);
1236   ASSERT_THAT_EXPECTED(LR, Succeeded());
1237   EXPECT_THAT(LR->Locations,
1238     testing::ElementsAre(SourceLocation{"main", "/tmp", "main.c", 5}));
1239   LR = GR->lookup(0x100F);
1240   ASSERT_THAT_EXPECTED(LR, Succeeded());
1241   EXPECT_THAT(LR->Locations,
1242     testing::ElementsAre(SourceLocation{"main", "/tmp", "main.c", 5, 15}));
1243 
1244   LR = GR->lookup(0x1010);
1245   ASSERT_THAT_EXPECTED(LR, Succeeded());
1246 
1247   EXPECT_THAT(LR->Locations,
1248     testing::ElementsAre(SourceLocation{"inline1", "/tmp", "foo.h", 10},
1249                          SourceLocation{"main", "/tmp", "main.c", 6, 16}));
1250 
1251   LR = GR->lookup(0x1012);
1252   ASSERT_THAT_EXPECTED(LR, Succeeded());
1253   EXPECT_THAT(LR->Locations,
1254     testing::ElementsAre(SourceLocation{"inline2", "/tmp", "foo.h", 20},
1255                          SourceLocation{"inline1", "/tmp", "foo.h", 33, 2},
1256                          SourceLocation{"main", "/tmp", "main.c", 6, 18}));
1257 
1258   LR = GR->lookup(0x1014);
1259   ASSERT_THAT_EXPECTED(LR, Succeeded());
1260   EXPECT_THAT(LR->Locations,
1261     testing::ElementsAre(SourceLocation{"inline1", "/tmp", "foo.h", 11, 4},
1262                          SourceLocation{"main", "/tmp", "main.c", 6, 20}));
1263 
1264   LR = GR->lookup(0x1016);
1265   ASSERT_THAT_EXPECTED(LR, Succeeded());
1266   EXPECT_THAT(LR->Locations,
1267     testing::ElementsAre(SourceLocation{"inline3", "/tmp", "foo.h", 30},
1268                          SourceLocation{"inline1", "/tmp", "foo.h", 35, 6},
1269                          SourceLocation{"main", "/tmp", "main.c", 6, 22}));
1270 
1271   LR = GR->lookup(0x1018);
1272   ASSERT_THAT_EXPECTED(LR, Succeeded());
1273   EXPECT_THAT(LR->Locations,
1274     testing::ElementsAre(SourceLocation{"inline1", "/tmp", "foo.h", 12, 8},
1275                          SourceLocation{"main", "/tmp", "main.c", 6, 24}));
1276 
1277   LR = GR->lookup(0x1020);
1278   ASSERT_THAT_EXPECTED(LR, Succeeded());
1279   EXPECT_THAT(LR->Locations,
1280     testing::ElementsAre(SourceLocation{"main", "/tmp", "main.c", 8, 32}));
1281 }
1282 
1283 
1284 TEST(GSYMTest, TestDWARFFunctionWithAddresses) {
1285   // Create a single compile unit with a single function and make sure it gets
1286   // converted to DWARF correctly. The function's address range is in where
1287   // DW_AT_low_pc and DW_AT_high_pc are both addresses.
1288   StringRef yamldata = R"(
1289   debug_str:
1290     - ''
1291     - /tmp/main.c
1292     - main
1293   debug_abbrev:
1294     - Table:
1295         - Code:            0x00000001
1296           Tag:             DW_TAG_compile_unit
1297           Children:        DW_CHILDREN_yes
1298           Attributes:
1299             - Attribute:       DW_AT_name
1300               Form:            DW_FORM_strp
1301             - Attribute:       DW_AT_low_pc
1302               Form:            DW_FORM_addr
1303             - Attribute:       DW_AT_high_pc
1304               Form:            DW_FORM_addr
1305             - Attribute:       DW_AT_language
1306               Form:            DW_FORM_data2
1307         - Code:            0x00000002
1308           Tag:             DW_TAG_subprogram
1309           Children:        DW_CHILDREN_no
1310           Attributes:
1311             - Attribute:       DW_AT_name
1312               Form:            DW_FORM_strp
1313             - Attribute:       DW_AT_low_pc
1314               Form:            DW_FORM_addr
1315             - Attribute:       DW_AT_high_pc
1316               Form:            DW_FORM_addr
1317   debug_info:
1318     - Version:         4
1319       AddrSize:        8
1320       Entries:
1321         - AbbrCode:        0x00000001
1322           Values:
1323             - Value:           0x0000000000000001
1324             - Value:           0x0000000000001000
1325             - Value:           0x0000000000002000
1326             - Value:           0x0000000000000004
1327         - AbbrCode:        0x00000002
1328           Values:
1329             - Value:           0x000000000000000D
1330             - Value:           0x0000000000001000
1331             - Value:           0x0000000000002000
1332         - AbbrCode:        0x00000000
1333   )";
1334   auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);
1335   ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());
1336   std::unique_ptr<DWARFContext> DwarfContext =
1337       DWARFContext::create(*ErrOrSections, 8);
1338   ASSERT_TRUE(DwarfContext.get() != nullptr);
1339   auto &OS = llvm::nulls();
1340   OutputAggregator OSAgg(&OS);
1341   GsymCreator GC;
1342   DwarfTransformer DT(*DwarfContext, GC);
1343   const uint32_t ThreadCount = 1;
1344   ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());
1345   ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());
1346   SmallString<512> Str;
1347   raw_svector_ostream OutStrm(Str);
1348   const auto ByteOrder = llvm::endianness::native;
1349   FileWriter FW(OutStrm, ByteOrder);
1350   ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());
1351   Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());
1352   ASSERT_THAT_EXPECTED(GR, Succeeded());
1353   // There should only be one function in our GSYM.
1354   EXPECT_EQ(GR->getNumAddresses(), 1u);
1355   auto ExpFI = GR->getFunctionInfo(0x1000);
1356   ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
1357   ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x2000));
1358   EXPECT_FALSE(ExpFI->OptLineTable.has_value());
1359   EXPECT_FALSE(ExpFI->Inline.has_value());
1360 }
1361 
1362 TEST(GSYMTest, TestDWARFFunctionWithAddressAndOffset) {
1363   // Create a single compile unit with a single function and make sure it gets
1364   // converted to DWARF correctly. The function's address range is in where
1365   // DW_AT_low_pc is an address and the DW_AT_high_pc is an offset.
1366   StringRef yamldata = R"(
1367   debug_str:
1368     - ''
1369     - /tmp/main.c
1370     - main
1371   debug_abbrev:
1372     - Table:
1373         - Code:            0x00000001
1374           Tag:             DW_TAG_compile_unit
1375           Children:        DW_CHILDREN_yes
1376           Attributes:
1377             - Attribute:       DW_AT_name
1378               Form:            DW_FORM_strp
1379             - Attribute:       DW_AT_low_pc
1380               Form:            DW_FORM_addr
1381             - Attribute:       DW_AT_high_pc
1382               Form:            DW_FORM_data4
1383             - Attribute:       DW_AT_language
1384               Form:            DW_FORM_data2
1385         - Code:            0x00000002
1386           Tag:             DW_TAG_subprogram
1387           Children:        DW_CHILDREN_no
1388           Attributes:
1389             - Attribute:       DW_AT_name
1390               Form:            DW_FORM_strp
1391             - Attribute:       DW_AT_low_pc
1392               Form:            DW_FORM_addr
1393             - Attribute:       DW_AT_high_pc
1394               Form:            DW_FORM_data4
1395   debug_info:
1396     - Version:         4
1397       AddrSize:        8
1398       Entries:
1399         - AbbrCode:        0x00000001
1400           Values:
1401             - Value:           0x0000000000000001
1402             - Value:           0x0000000000001000
1403             - Value:           0x0000000000001000
1404             - Value:           0x0000000000000004
1405         - AbbrCode:        0x00000002
1406           Values:
1407             - Value:           0x000000000000000D
1408             - Value:           0x0000000000001000
1409             - Value:           0x0000000000001000
1410         - AbbrCode:        0x00000000
1411   )";
1412   auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);
1413   ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());
1414   std::unique_ptr<DWARFContext> DwarfContext =
1415       DWARFContext::create(*ErrOrSections, 8);
1416   ASSERT_TRUE(DwarfContext.get() != nullptr);
1417   auto &OS = llvm::nulls();
1418   OutputAggregator OSAgg(&OS);
1419   GsymCreator GC;
1420   DwarfTransformer DT(*DwarfContext, GC);
1421   const uint32_t ThreadCount = 1;
1422   ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());
1423   ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());
1424   SmallString<512> Str;
1425   raw_svector_ostream OutStrm(Str);
1426   const auto ByteOrder = llvm::endianness::native;
1427   FileWriter FW(OutStrm, ByteOrder);
1428   ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());
1429   Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());
1430   ASSERT_THAT_EXPECTED(GR, Succeeded());
1431   // There should only be one function in our GSYM.
1432   EXPECT_EQ(GR->getNumAddresses(), 1u);
1433   auto ExpFI = GR->getFunctionInfo(0x1000);
1434   ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
1435   ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x2000));
1436   EXPECT_FALSE(ExpFI->OptLineTable.has_value());
1437   EXPECT_FALSE(ExpFI->Inline.has_value());
1438 }
1439 
1440 TEST(GSYMTest, TestDWARFStructMethodNoMangled) {
1441   // Sometimes the compiler will omit the mangled name in the DWARF for static
1442   // and member functions of classes and structs. This test verifies that the
1443   // fully qualified name of the method is computed and used as the string for
1444   // the function in the GSYM in these cases. Otherwise we might just get a
1445   // function name like "erase" instead of "std::vector<int>::erase".
1446   StringRef yamldata = R"(
1447   debug_str:
1448     - ''
1449     - /tmp/main.c
1450     - Foo
1451     - dump
1452     - this
1453   debug_abbrev:
1454     - Table:
1455         - Code:            0x00000001
1456           Tag:             DW_TAG_compile_unit
1457           Children:        DW_CHILDREN_yes
1458           Attributes:
1459             - Attribute:       DW_AT_name
1460               Form:            DW_FORM_strp
1461             - Attribute:       DW_AT_low_pc
1462               Form:            DW_FORM_addr
1463             - Attribute:       DW_AT_high_pc
1464               Form:            DW_FORM_addr
1465             - Attribute:       DW_AT_language
1466               Form:            DW_FORM_data2
1467         - Code:            0x00000002
1468           Tag:             DW_TAG_structure_type
1469           Children:        DW_CHILDREN_yes
1470           Attributes:
1471             - Attribute:       DW_AT_name
1472               Form:            DW_FORM_strp
1473         - Code:            0x00000003
1474           Tag:             DW_TAG_subprogram
1475           Children:        DW_CHILDREN_yes
1476           Attributes:
1477             - Attribute:       DW_AT_name
1478               Form:            DW_FORM_strp
1479             - Attribute:       DW_AT_low_pc
1480               Form:            DW_FORM_addr
1481             - Attribute:       DW_AT_high_pc
1482               Form:            DW_FORM_addr
1483         - Code:            0x00000004
1484           Tag:             DW_TAG_formal_parameter
1485           Children:        DW_CHILDREN_no
1486           Attributes:
1487             - Attribute:       DW_AT_name
1488               Form:            DW_FORM_strp
1489             - Attribute:       DW_AT_type
1490               Form:            DW_FORM_ref4
1491             - Attribute:       DW_AT_artificial
1492               Form:            DW_FORM_flag_present
1493   debug_info:
1494     - Version:         4
1495       AddrSize:        8
1496       Entries:
1497         - AbbrCode:        0x00000001
1498           Values:
1499             - Value:           0x0000000000000001
1500             - Value:           0x0000000000001000
1501             - Value:           0x0000000000002000
1502             - Value:           0x0000000000000004
1503         - AbbrCode:        0x00000002
1504           Values:
1505             - Value:           0x000000000000000D
1506         - AbbrCode:        0x00000003
1507           Values:
1508             - Value:           0x0000000000000011
1509             - Value:           0x0000000000001000
1510             - Value:           0x0000000000002000
1511         - AbbrCode:        0x00000004
1512           Values:
1513             - Value:           0x0000000000000016
1514             - Value:           0x0000000000000022
1515             - Value:           0x0000000000000001
1516         - AbbrCode:        0x00000000
1517         - AbbrCode:        0x00000000
1518         - AbbrCode:        0x00000000
1519   )";
1520   auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);
1521   ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());
1522   std::unique_ptr<DWARFContext> DwarfContext =
1523       DWARFContext::create(*ErrOrSections, 8);
1524   ASSERT_TRUE(DwarfContext.get() != nullptr);
1525   auto &OS = llvm::nulls();
1526   OutputAggregator OSAgg(&OS);
1527   GsymCreator GC;
1528   DwarfTransformer DT(*DwarfContext, GC);
1529   const uint32_t ThreadCount = 1;
1530   ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());
1531   ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());
1532   SmallString<512> Str;
1533   raw_svector_ostream OutStrm(Str);
1534   const auto ByteOrder = llvm::endianness::native;
1535   FileWriter FW(OutStrm, ByteOrder);
1536   ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());
1537   Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());
1538   ASSERT_THAT_EXPECTED(GR, Succeeded());
1539   // There should only be one function in our GSYM.
1540   EXPECT_EQ(GR->getNumAddresses(), 1u);
1541   auto ExpFI = GR->getFunctionInfo(0x1000);
1542   ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
1543   ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x2000));
1544   EXPECT_FALSE(ExpFI->OptLineTable.has_value());
1545   EXPECT_FALSE(ExpFI->Inline.has_value());
1546   StringRef MethodName = GR->getString(ExpFI->Name);
1547   EXPECT_EQ(MethodName, "Foo::dump");
1548 }
1549 
1550 TEST(GSYMTest, TestDWARFTextRanges) {
1551   // Linkers don't understand DWARF, they just like to concatenate and
1552   // relocate data within the DWARF sections. This means that if a function
1553   // gets dead stripped, and if those functions use an offset as the
1554   // DW_AT_high_pc, we can end up with many functions at address zero. The
1555   // DwarfTransformer allows clients to specify valid .text address ranges
1556   // and any addresses of any functions must fall within those ranges if any
1557   // have been specified. This means that an object file can calcuate the
1558   // address ranges within the binary where code lives and set these ranges
1559   // as constraints in the DwarfTransformer. ObjectFile instances can
1560   // add a address ranges of sections that have executable permissions. This
1561   // keeps bad information from being added to a GSYM file and causing issues
1562   // when symbolicating.
1563   StringRef yamldata = R"(
1564   debug_str:
1565     - ''
1566     - /tmp/main.c
1567     - main
1568     - dead_stripped
1569     - dead_stripped2
1570   debug_abbrev:
1571     - Table:
1572         - Code:            0x00000001
1573           Tag:             DW_TAG_compile_unit
1574           Children:        DW_CHILDREN_yes
1575           Attributes:
1576             - Attribute:       DW_AT_name
1577               Form:            DW_FORM_strp
1578             - Attribute:       DW_AT_low_pc
1579               Form:            DW_FORM_addr
1580             - Attribute:       DW_AT_high_pc
1581               Form:            DW_FORM_data4
1582             - Attribute:       DW_AT_language
1583               Form:            DW_FORM_data2
1584         - Code:            0x00000002
1585           Tag:             DW_TAG_subprogram
1586           Children:        DW_CHILDREN_no
1587           Attributes:
1588             - Attribute:       DW_AT_name
1589               Form:            DW_FORM_strp
1590             - Attribute:       DW_AT_low_pc
1591               Form:            DW_FORM_addr
1592             - Attribute:       DW_AT_high_pc
1593               Form:            DW_FORM_data4
1594   debug_info:
1595     - Version:         4
1596       AddrSize:        8
1597       Entries:
1598         - AbbrCode:        0x00000001
1599           Values:
1600             - Value:           0x0000000000000001
1601             - Value:           0x0000000000001000
1602             - Value:           0x0000000000001000
1603             - Value:           0x0000000000000004
1604         - AbbrCode:        0x00000002
1605           Values:
1606             - Value:           0x000000000000000D
1607             - Value:           0x0000000000001000
1608             - Value:           0x0000000000001000
1609         - AbbrCode:        0x00000002
1610           Values:
1611             - Value:           0x0000000000000012
1612             - Value:           0x0000000000000000
1613             - Value:           0x0000000000000100
1614         - AbbrCode:        0x00000002
1615           Values:
1616             - Value:           0x0000000000000020
1617             - Value:           0x0000000000000000
1618             - Value:           0x0000000000000040
1619         - AbbrCode:        0x00000000
1620   )";
1621   auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);
1622   ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());
1623   std::unique_ptr<DWARFContext> DwarfContext =
1624       DWARFContext::create(*ErrOrSections, 8);
1625   ASSERT_TRUE(DwarfContext.get() != nullptr);
1626   auto &OS = llvm::nulls();
1627   OutputAggregator OSAgg(&OS);
1628   GsymCreator GC;
1629   DwarfTransformer DT(*DwarfContext, GC);
1630   // Only allow addresses between [0x1000 - 0x2000) to be linked into the
1631   // GSYM.
1632   AddressRanges TextRanges;
1633   TextRanges.insert(AddressRange(0x1000, 0x2000));
1634   GC.SetValidTextRanges(TextRanges);
1635   const uint32_t ThreadCount = 1;
1636   ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());
1637   ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());
1638   SmallString<512> Str;
1639   raw_svector_ostream OutStrm(Str);
1640   const auto ByteOrder = llvm::endianness::native;
1641   FileWriter FW(OutStrm, ByteOrder);
1642   ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());
1643   Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());
1644   ASSERT_THAT_EXPECTED(GR, Succeeded());
1645   // There should only be one function in our GSYM.
1646   EXPECT_EQ(GR->getNumAddresses(), 1u);
1647   auto ExpFI = GR->getFunctionInfo(0x1000);
1648   ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
1649   ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x2000));
1650   EXPECT_FALSE(ExpFI->OptLineTable.has_value());
1651   EXPECT_FALSE(ExpFI->Inline.has_value());
1652   StringRef MethodName = GR->getString(ExpFI->Name);
1653   EXPECT_EQ(MethodName, "main");
1654 }
1655 
1656 TEST(GSYMTest, TestEmptySymbolEndAddressOfTextRanges) {
1657   // Test that if we have valid text ranges and we have a symbol with no size
1658   // as the last FunctionInfo entry that the size of the symbol gets set to the
1659   // end address of the text range.
1660   GsymCreator GC;
1661   AddressRanges TextRanges;
1662   TextRanges.insert(AddressRange(0x1000, 0x2000));
1663   GC.SetValidTextRanges(TextRanges);
1664   GC.addFunctionInfo(FunctionInfo(0x1500, 0, GC.insertString("symbol")));
1665   OutputAggregator Null(nullptr);
1666   ASSERT_THAT_ERROR(GC.finalize(Null), Succeeded());
1667   SmallString<512> Str;
1668   raw_svector_ostream OutStrm(Str);
1669   const auto ByteOrder = llvm::endianness::native;
1670   FileWriter FW(OutStrm, ByteOrder);
1671   ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());
1672   Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());
1673   ASSERT_THAT_EXPECTED(GR, Succeeded());
1674   // There should only be one function in our GSYM.
1675   EXPECT_EQ(GR->getNumAddresses(), 1u);
1676   auto ExpFI = GR->getFunctionInfo(0x1500);
1677   ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
1678   ASSERT_EQ(ExpFI->Range, AddressRange(0x1500, 0x2000));
1679   EXPECT_FALSE(ExpFI->OptLineTable.has_value());
1680   EXPECT_FALSE(ExpFI->Inline.has_value());
1681   StringRef MethodName = GR->getString(ExpFI->Name);
1682   EXPECT_EQ(MethodName, "symbol");
1683 }
1684 
1685 TEST(GSYMTest, TestDWARFInlineInfo) {
1686   // Make sure we parse the line table and inline information correctly from
1687   // DWARF.
1688   StringRef yamldata = R"(
1689   debug_str:
1690     - ''
1691     - /tmp/main.c
1692     - main
1693     - inline1
1694   debug_abbrev:
1695     - Table:
1696         - Code:            0x00000001
1697           Tag:             DW_TAG_compile_unit
1698           Children:        DW_CHILDREN_yes
1699           Attributes:
1700             - Attribute:       DW_AT_name
1701               Form:            DW_FORM_strp
1702             - Attribute:       DW_AT_low_pc
1703               Form:            DW_FORM_addr
1704             - Attribute:       DW_AT_high_pc
1705               Form:            DW_FORM_data4
1706             - Attribute:       DW_AT_language
1707               Form:            DW_FORM_data2
1708             - Attribute:       DW_AT_stmt_list
1709               Form:            DW_FORM_sec_offset
1710         - Code:            0x00000002
1711           Tag:             DW_TAG_subprogram
1712           Children:        DW_CHILDREN_yes
1713           Attributes:
1714             - Attribute:       DW_AT_name
1715               Form:            DW_FORM_strp
1716             - Attribute:       DW_AT_low_pc
1717               Form:            DW_FORM_addr
1718             - Attribute:       DW_AT_high_pc
1719               Form:            DW_FORM_data4
1720         - Code:            0x00000003
1721           Tag:             DW_TAG_inlined_subroutine
1722           Children:        DW_CHILDREN_no
1723           Attributes:
1724             - Attribute:       DW_AT_name
1725               Form:            DW_FORM_strp
1726             - Attribute:       DW_AT_low_pc
1727               Form:            DW_FORM_addr
1728             - Attribute:       DW_AT_high_pc
1729               Form:            DW_FORM_data4
1730             - Attribute:       DW_AT_call_file
1731               Form:            DW_FORM_data4
1732             - Attribute:       DW_AT_call_line
1733               Form:            DW_FORM_data4
1734   debug_info:
1735     - Version:         4
1736       AddrSize:        8
1737       Entries:
1738         - AbbrCode:        0x00000001
1739           Values:
1740             - Value:           0x0000000000000001
1741             - Value:           0x0000000000001000
1742             - Value:           0x0000000000001000
1743             - Value:           0x0000000000000004
1744             - Value:           0x0000000000000000
1745         - AbbrCode:        0x00000002
1746           Values:
1747             - Value:           0x000000000000000D
1748             - Value:           0x0000000000001000
1749             - Value:           0x0000000000001000
1750         - AbbrCode:        0x00000003
1751           Values:
1752             - Value:           0x0000000000000012
1753             - Value:           0x0000000000001100
1754             - Value:           0x0000000000000100
1755             - Value:           0x0000000000000001
1756             - Value:           0x000000000000000A
1757         - AbbrCode:        0x00000000
1758         - AbbrCode:        0x00000000
1759   debug_line:
1760     - Length:          96
1761       Version:         2
1762       PrologueLength:  46
1763       MinInstLength:   1
1764       DefaultIsStmt:   1
1765       LineBase:        251
1766       LineRange:       14
1767       OpcodeBase:      13
1768       StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]
1769       IncludeDirs:
1770         - /tmp
1771       Files:
1772         - Name:            main.c
1773           DirIdx:          1
1774           ModTime:         0
1775           Length:          0
1776         - Name:            inline.h
1777           DirIdx:          1
1778           ModTime:         0
1779           Length:          0
1780       Opcodes:
1781         - Opcode:          DW_LNS_extended_op
1782           ExtLen:          9
1783           SubOpcode:       DW_LNE_set_address
1784           Data:            4096
1785         - Opcode:          DW_LNS_advance_line
1786           SData:           9
1787           Data:            4096
1788         - Opcode:          DW_LNS_copy
1789           Data:            4096
1790         - Opcode:          DW_LNS_advance_pc
1791           Data:            256
1792         - Opcode:          DW_LNS_set_file
1793           Data:            2
1794         - Opcode:          DW_LNS_advance_line
1795           SData:           10
1796           Data:            2
1797         - Opcode:          DW_LNS_copy
1798           Data:            2
1799         - Opcode:          DW_LNS_advance_pc
1800           Data:            128
1801         - Opcode:          DW_LNS_advance_line
1802           SData:           1
1803           Data:            128
1804         - Opcode:          DW_LNS_copy
1805           Data:            128
1806         - Opcode:          DW_LNS_advance_pc
1807           Data:            128
1808         - Opcode:          DW_LNS_set_file
1809           Data:            1
1810         - Opcode:          DW_LNS_advance_line
1811           SData:           -10
1812           Data:            1
1813         - Opcode:          DW_LNS_copy
1814           Data:            1
1815         - Opcode:          DW_LNS_advance_pc
1816           Data:            3584
1817         - Opcode:          DW_LNS_advance_line
1818           SData:           1
1819           Data:            3584
1820         - Opcode:          DW_LNS_extended_op
1821           ExtLen:          1
1822           SubOpcode:       DW_LNE_end_sequence
1823           Data:            3584
1824   )";
1825   auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);
1826   ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());
1827   std::unique_ptr<DWARFContext> DwarfContext =
1828       DWARFContext::create(*ErrOrSections, 8);
1829   ASSERT_TRUE(DwarfContext.get() != nullptr);
1830   auto &OS = llvm::nulls();
1831   OutputAggregator OSAgg(&OS);
1832   GsymCreator GC;
1833   DwarfTransformer DT(*DwarfContext, GC);
1834   const uint32_t ThreadCount = 1;
1835   ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());
1836   ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());
1837   SmallString<512> Str;
1838   raw_svector_ostream OutStrm(Str);
1839   const auto ByteOrder = llvm::endianness::native;
1840   FileWriter FW(OutStrm, ByteOrder);
1841   ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());
1842   Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());
1843   ASSERT_THAT_EXPECTED(GR, Succeeded());
1844   // There should only be one function in our GSYM.
1845   EXPECT_EQ(GR->getNumAddresses(), 1u);
1846   auto ExpFI = GR->getFunctionInfo(0x1000);
1847   ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
1848   ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x2000));
1849   EXPECT_TRUE(ExpFI->OptLineTable.has_value());
1850   EXPECT_TRUE(ExpFI->Inline.has_value());
1851   StringRef MethodName = GR->getString(ExpFI->Name);
1852   EXPECT_EQ(MethodName, "main");
1853 
1854     // Verify inline info is correct when doing lookups.
1855   auto LR = GR->lookup(0x1000);
1856   ASSERT_THAT_EXPECTED(LR, Succeeded());
1857   EXPECT_THAT(LR->Locations,
1858     testing::ElementsAre(SourceLocation{"main", "/tmp", "main.c", 10}));
1859   LR = GR->lookup(0x1100-1);
1860   ASSERT_THAT_EXPECTED(LR, Succeeded());
1861   EXPECT_THAT(LR->Locations,
1862     testing::ElementsAre(SourceLocation{"main", "/tmp", "main.c", 10, 255}));
1863 
1864   LR = GR->lookup(0x1100);
1865   ASSERT_THAT_EXPECTED(LR, Succeeded());
1866   EXPECT_THAT(LR->Locations,
1867     testing::ElementsAre(SourceLocation{"inline1", "/tmp", "inline.h", 20},
1868                          SourceLocation{"main", "/tmp", "main.c", 10, 256}));
1869   LR = GR->lookup(0x1180-1);
1870   ASSERT_THAT_EXPECTED(LR, Succeeded());
1871   EXPECT_THAT(LR->Locations,
1872     testing::ElementsAre(SourceLocation{"inline1", "/tmp", "inline.h", 20, 127},
1873                          SourceLocation{"main", "/tmp", "main.c", 10, 383}));
1874   LR = GR->lookup(0x1180);
1875   ASSERT_THAT_EXPECTED(LR, Succeeded());
1876   EXPECT_THAT(LR->Locations,
1877     testing::ElementsAre(SourceLocation{"inline1", "/tmp", "inline.h", 21, 128},
1878                          SourceLocation{"main", "/tmp", "main.c", 10, 384}));
1879   LR = GR->lookup(0x1200-1);
1880   ASSERT_THAT_EXPECTED(LR, Succeeded());
1881   EXPECT_THAT(LR->Locations,
1882     testing::ElementsAre(SourceLocation{"inline1", "/tmp", "inline.h", 21, 255},
1883                          SourceLocation{"main", "/tmp", "main.c", 10, 511}));
1884   LR = GR->lookup(0x1200);
1885   ASSERT_THAT_EXPECTED(LR, Succeeded());
1886   EXPECT_THAT(LR->Locations,
1887     testing::ElementsAre(SourceLocation{"main", "/tmp", "main.c", 11, 512}));
1888 }
1889 
1890 
1891 TEST(GSYMTest, TestDWARFNoLines) {
1892   // Check that if a DW_TAG_subprogram doesn't have line table entries that
1893   // we fall back and use the DW_AT_decl_file and DW_AT_decl_line to at least
1894   // point to the function definition. This DWARF file has 4 functions:
1895   //  "lines_no_decl": has line table entries, no DW_AT_decl_file/line attrs.
1896   //  "lines_with_decl": has line table entries and has DW_AT_decl_file/line,
1897   //                     make sure we don't use DW_AT_decl_file/line and make
1898   //                     sure there is a line table.
1899   //  "no_lines_no_decl": no line table entries and no DW_AT_decl_file/line,
1900   //                      make sure there is no line table for this function.
1901   //  "no_lines_with_decl": no line table and has DW_AT_decl_file/line, make
1902   //                        sure we have one line table entry that starts at
1903   //                        the function start address and the decl file and
1904   //                        line.
1905   //
1906   // 0x0000000b: DW_TAG_compile_unit
1907   //               DW_AT_name	("/tmp/main.c")
1908   //               DW_AT_low_pc	(0x0000000000001000)
1909   //               DW_AT_high_pc	(0x0000000000002000)
1910   //               DW_AT_language	(DW_LANG_C_plus_plus)
1911   //               DW_AT_stmt_list	(0x00000000)
1912   //
1913   // 0x00000022:   DW_TAG_subprogram
1914   //                 DW_AT_name	("lines_no_decl")
1915   //                 DW_AT_low_pc	(0x0000000000001000)
1916   //                 DW_AT_high_pc	(0x0000000000002000)
1917   //
1918   // 0x00000033:   DW_TAG_subprogram
1919   //                 DW_AT_name	("lines_with_decl")
1920   //                 DW_AT_low_pc	(0x0000000000002000)
1921   //                 DW_AT_high_pc	(0x0000000000003000)
1922   //                 DW_AT_decl_file	("/tmp/main.c")
1923   //                 DW_AT_decl_line	(20)
1924   //
1925   // 0x00000046:   DW_TAG_subprogram
1926   //                 DW_AT_name	("no_lines_no_decl")
1927   //                 DW_AT_low_pc	(0x0000000000003000)
1928   //                 DW_AT_high_pc	(0x0000000000004000)
1929   //
1930   // 0x00000057:   DW_TAG_subprogram
1931   //                 DW_AT_name	("no_lines_with_decl")
1932   //                 DW_AT_low_pc	(0x0000000000004000)
1933   //                 DW_AT_high_pc	(0x0000000000005000)
1934   //                 DW_AT_decl_file	("/tmp/main.c")
1935   //                 DW_AT_decl_line	(40)
1936   //
1937   // 0x0000006a:   NULL
1938 
1939   StringRef yamldata = R"(
1940   debug_str:
1941     - ''
1942     - '/tmp/main.c'
1943     - lines_no_decl
1944     - lines_with_decl
1945     - no_lines_no_decl
1946     - no_lines_with_decl
1947   debug_abbrev:
1948     - Table:
1949         - Code:            0x00000001
1950           Tag:             DW_TAG_compile_unit
1951           Children:        DW_CHILDREN_yes
1952           Attributes:
1953             - Attribute:       DW_AT_name
1954               Form:            DW_FORM_strp
1955             - Attribute:       DW_AT_low_pc
1956               Form:            DW_FORM_addr
1957             - Attribute:       DW_AT_high_pc
1958               Form:            DW_FORM_data4
1959             - Attribute:       DW_AT_language
1960               Form:            DW_FORM_data2
1961             - Attribute:       DW_AT_stmt_list
1962               Form:            DW_FORM_sec_offset
1963         - Code:            0x00000002
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         - Code:            0x00000003
1974           Tag:             DW_TAG_subprogram
1975           Children:        DW_CHILDREN_no
1976           Attributes:
1977             - Attribute:       DW_AT_name
1978               Form:            DW_FORM_strp
1979             - Attribute:       DW_AT_low_pc
1980               Form:            DW_FORM_addr
1981             - Attribute:       DW_AT_high_pc
1982               Form:            DW_FORM_data4
1983             - Attribute:       DW_AT_decl_file
1984               Form:            DW_FORM_data1
1985             - Attribute:       DW_AT_decl_line
1986               Form:            DW_FORM_data1
1987   debug_info:
1988     - Version:         4
1989       AddrSize:        8
1990       Entries:
1991         - AbbrCode:        0x00000001
1992           Values:
1993             - Value:           0x0000000000000001
1994             - Value:           0x0000000000001000
1995             - Value:           0x0000000000001000
1996             - Value:           0x0000000000000004
1997             - Value:           0x0000000000000000
1998         - AbbrCode:        0x00000002
1999           Values:
2000             - Value:           0x000000000000000D
2001             - Value:           0x0000000000001000
2002             - Value:           0x0000000000001000
2003         - AbbrCode:        0x00000003
2004           Values:
2005             - Value:           0x000000000000001B
2006             - Value:           0x0000000000002000
2007             - Value:           0x0000000000001000
2008             - Value:           0x0000000000000001
2009             - Value:           0x0000000000000014
2010         - AbbrCode:        0x00000002
2011           Values:
2012             - Value:           0x000000000000002B
2013             - Value:           0x0000000000003000
2014             - Value:           0x0000000000001000
2015         - AbbrCode:        0x00000003
2016           Values:
2017             - Value:           0x000000000000003C
2018             - Value:           0x0000000000004000
2019             - Value:           0x0000000000001000
2020             - Value:           0x0000000000000001
2021             - Value:           0x0000000000000028
2022         - AbbrCode:        0x00000000
2023   debug_line:
2024     - Length:          92
2025       Version:         2
2026       PrologueLength:  34
2027       MinInstLength:   1
2028       DefaultIsStmt:   1
2029       LineBase:        251
2030       LineRange:       14
2031       OpcodeBase:      13
2032       StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]
2033       IncludeDirs:
2034         - '/tmp'
2035       Files:
2036         - Name:            main.c
2037           DirIdx:          1
2038           ModTime:         0
2039           Length:          0
2040       Opcodes:
2041         - Opcode:          DW_LNS_extended_op
2042           ExtLen:          9
2043           SubOpcode:       DW_LNE_set_address
2044           Data:            4096
2045         - Opcode:          DW_LNS_advance_line
2046           SData:           10
2047           Data:            0
2048         - Opcode:          DW_LNS_copy
2049           Data:            0
2050         - Opcode:          DW_LNS_advance_pc
2051           Data:            512
2052         - Opcode:          DW_LNS_advance_line
2053           SData:           1
2054           Data:            0
2055         - Opcode:          DW_LNS_copy
2056           Data:            0
2057         - Opcode:          DW_LNS_advance_pc
2058           Data:            3584
2059         - Opcode:          DW_LNS_extended_op
2060           ExtLen:          1
2061           SubOpcode:       DW_LNE_end_sequence
2062           Data:            0
2063         - Opcode:          DW_LNS_extended_op
2064           ExtLen:          9
2065           SubOpcode:       DW_LNE_set_address
2066           Data:            8192
2067         - Opcode:          DW_LNS_advance_line
2068           SData:           20
2069           Data:            0
2070         - Opcode:          DW_LNS_copy
2071           Data:            0
2072         - Opcode:          DW_LNS_advance_pc
2073           Data:            512
2074         - Opcode:          DW_LNS_advance_line
2075           SData:           1
2076           Data:            0
2077         - Opcode:          DW_LNS_copy
2078           Data:            0
2079         - Opcode:          DW_LNS_advance_pc
2080           Data:            3584
2081         - Opcode:          DW_LNS_extended_op
2082           ExtLen:          1
2083           SubOpcode:       DW_LNE_end_sequence
2084           Data:            0
2085   )";
2086   auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);
2087   ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());
2088   std::unique_ptr<DWARFContext> DwarfContext =
2089       DWARFContext::create(*ErrOrSections, 8);
2090   ASSERT_TRUE(DwarfContext.get() != nullptr);
2091   auto &OS = llvm::nulls();
2092   OutputAggregator OSAgg(&OS);
2093   GsymCreator GC;
2094   DwarfTransformer DT(*DwarfContext, GC);
2095   const uint32_t ThreadCount = 1;
2096   ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());
2097   ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());
2098   SmallString<512> Str;
2099   raw_svector_ostream OutStrm(Str);
2100   const auto ByteOrder = llvm::endianness::native;
2101   FileWriter FW(OutStrm, ByteOrder);
2102   ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());
2103   Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());
2104   ASSERT_THAT_EXPECTED(GR, Succeeded());
2105 
2106   EXPECT_EQ(GR->getNumAddresses(), 4u);
2107 
2108   auto ExpFI = GR->getFunctionInfo(0x1000);
2109   ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
2110   ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x2000));
2111   EXPECT_TRUE(ExpFI->OptLineTable);
2112   StringRef MethodName = GR->getString(ExpFI->Name);
2113   EXPECT_EQ(MethodName, "lines_no_decl");
2114   // Make sure have two line table entries and that get the first line entry
2115   // correct.
2116   EXPECT_EQ(ExpFI->OptLineTable->size(), 2u);
2117   EXPECT_EQ(ExpFI->OptLineTable->first()->Addr, 0x1000u);
2118   EXPECT_EQ(ExpFI->OptLineTable->first()->Line, 11u);
2119 
2120   ExpFI = GR->getFunctionInfo(0x2000);
2121   ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
2122   ASSERT_EQ(ExpFI->Range, AddressRange(0x2000, 0x3000));
2123   EXPECT_TRUE(ExpFI->OptLineTable);
2124   MethodName = GR->getString(ExpFI->Name);
2125   EXPECT_EQ(MethodName, "lines_with_decl");
2126   // Make sure have two line table entries and that we don't use line 20
2127   // from the DW_AT_decl_file/line as a line table entry.
2128   EXPECT_EQ(ExpFI->OptLineTable->size(), 2u);
2129   EXPECT_EQ(ExpFI->OptLineTable->first()->Addr, 0x2000u);
2130   EXPECT_EQ(ExpFI->OptLineTable->first()->Line, 21u);
2131 
2132   ExpFI = GR->getFunctionInfo(0x3000);
2133   ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
2134   ASSERT_EQ(ExpFI->Range, AddressRange(0x3000, 0x4000));
2135   // Make sure we have no line table.
2136   EXPECT_FALSE(ExpFI->OptLineTable.has_value());
2137   MethodName = GR->getString(ExpFI->Name);
2138   EXPECT_EQ(MethodName, "no_lines_no_decl");
2139 
2140   ExpFI = GR->getFunctionInfo(0x4000);
2141   ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
2142   ASSERT_EQ(ExpFI->Range, AddressRange(0x4000, 0x5000));
2143   EXPECT_TRUE(ExpFI->OptLineTable.has_value());
2144   MethodName = GR->getString(ExpFI->Name);
2145   EXPECT_EQ(MethodName, "no_lines_with_decl");
2146   // Make sure we have one line table entry that uses the DW_AT_decl_file/line
2147   // as the one and only line entry.
2148   EXPECT_EQ(ExpFI->OptLineTable->size(), 1u);
2149   EXPECT_EQ(ExpFI->OptLineTable->first()->Addr, 0x4000u);
2150   EXPECT_EQ(ExpFI->OptLineTable->first()->Line, 40u);
2151 }
2152 
2153 
2154 TEST(GSYMTest, TestDWARFDeadStripAddr4) {
2155   // Check that various techniques that compilers use for dead code stripping
2156   // work for 4 byte addresses. Make sure we keep the good functions and
2157   // strip any functions whose name starts with "stripped".
2158   //
2159   // 1 - Compilers might set the low PC to -1 (UINT32_MAX) for compile unit
2160   //     with 4 byte addresses ("stripped1")
2161   // 2 - Set the low and high PC to the same value ("stripped2")
2162   // 3 - Have the high PC lower than the low PC ("stripped3")
2163   //
2164   // 0x0000000b: DW_TAG_compile_unit
2165   //               DW_AT_name	("/tmp/main.c")
2166   //               DW_AT_low_pc	(0x0000000000001000)
2167   //               DW_AT_high_pc	(0x0000000000002000)
2168   //               DW_AT_language	(DW_LANG_C_plus_plus)
2169   //
2170   // 0x0000001a:   DW_TAG_subprogram
2171   //                 DW_AT_name	("main")
2172   //                 DW_AT_low_pc	(0x0000000000001000)
2173   //                 DW_AT_high_pc	(0x0000000000002000)
2174   //
2175   // 0x00000027:   DW_TAG_subprogram
2176   //                 DW_AT_name	("stripped1")
2177   //                 DW_AT_low_pc	(0x00000000ffffffff)
2178   //                 DW_AT_high_pc	(0x0000000100000000)
2179   //
2180   // 0x00000034:   DW_TAG_subprogram
2181   //                 DW_AT_name	("stripped2")
2182   //                 DW_AT_low_pc	(0x0000000000003000)
2183   //                 DW_AT_high_pc	(0x0000000000003000)
2184   //
2185   // 0x00000041:   DW_TAG_subprogram
2186   //                 DW_AT_name	("stripped3")
2187   //                 DW_AT_low_pc	(0x0000000000004000)
2188   //                 DW_AT_high_pc	(0x0000000000003fff)
2189   //
2190   // 0x0000004e:   NULL
2191 
2192   StringRef yamldata = R"(
2193   debug_str:
2194     - ''
2195     - '/tmp/main.c'
2196     - main
2197     - stripped1
2198     - stripped2
2199     - stripped3
2200   debug_abbrev:
2201     - Table:
2202         - Code:            0x00000001
2203           Tag:             DW_TAG_compile_unit
2204           Children:        DW_CHILDREN_yes
2205           Attributes:
2206             - Attribute:       DW_AT_name
2207               Form:            DW_FORM_strp
2208             - Attribute:       DW_AT_low_pc
2209               Form:            DW_FORM_addr
2210             - Attribute:       DW_AT_high_pc
2211               Form:            DW_FORM_data4
2212             - Attribute:       DW_AT_language
2213               Form:            DW_FORM_data2
2214         - Code:            0x00000002
2215           Tag:             DW_TAG_subprogram
2216           Children:        DW_CHILDREN_no
2217           Attributes:
2218             - Attribute:       DW_AT_name
2219               Form:            DW_FORM_strp
2220             - Attribute:       DW_AT_low_pc
2221               Form:            DW_FORM_addr
2222             - Attribute:       DW_AT_high_pc
2223               Form:            DW_FORM_data4
2224         - Code:            0x00000003
2225           Tag:             DW_TAG_subprogram
2226           Children:        DW_CHILDREN_no
2227           Attributes:
2228             - Attribute:       DW_AT_name
2229               Form:            DW_FORM_strp
2230             - Attribute:       DW_AT_low_pc
2231               Form:            DW_FORM_addr
2232             - Attribute:       DW_AT_high_pc
2233               Form:            DW_FORM_addr
2234   debug_info:
2235     - Version:         4
2236       AddrSize:        4
2237       Entries:
2238         - AbbrCode:        0x00000001
2239           Values:
2240             - Value:           0x0000000000000001
2241             - Value:           0x0000000000001000
2242             - Value:           0x0000000000001000
2243             - Value:           0x0000000000000004
2244         - AbbrCode:        0x00000002
2245           Values:
2246             - Value:           0x000000000000000D
2247             - Value:           0x0000000000001000
2248             - Value:           0x0000000000001000
2249         - AbbrCode:        0x00000002
2250           Values:
2251             - Value:           0x0000000000000012
2252             - Value:           0x00000000FFFFFFFF
2253             - Value:           0x0000000000000001
2254         - AbbrCode:        0x00000003
2255           Values:
2256             - Value:           0x000000000000001C
2257             - Value:           0x0000000000003000
2258             - Value:           0x0000000000003000
2259         - AbbrCode:        0x00000003
2260           Values:
2261             - Value:           0x0000000000000026
2262             - Value:           0x0000000000004000
2263             - Value:           0x0000000000003FFF
2264         - AbbrCode:        0x00000000
2265   )";
2266   auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);
2267   ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());
2268   std::unique_ptr<DWARFContext> DwarfContext =
2269       DWARFContext::create(*ErrOrSections, 4);
2270   ASSERT_TRUE(DwarfContext.get() != nullptr);
2271   auto &OS = llvm::nulls();
2272   OutputAggregator OSAgg(&OS);
2273   GsymCreator GC;
2274   DwarfTransformer DT(*DwarfContext, GC);
2275   const uint32_t ThreadCount = 1;
2276   ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());
2277   ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());
2278   SmallString<512> Str;
2279   raw_svector_ostream OutStrm(Str);
2280   const auto ByteOrder = llvm::endianness::native;
2281   FileWriter FW(OutStrm, ByteOrder);
2282   ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());
2283   Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());
2284   ASSERT_THAT_EXPECTED(GR, Succeeded());
2285 
2286   // Test that the only function that made it was the "main" function.
2287   EXPECT_EQ(GR->getNumAddresses(), 1u);
2288   auto ExpFI = GR->getFunctionInfo(0x1000);
2289   ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
2290   ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x2000));
2291   StringRef MethodName = GR->getString(ExpFI->Name);
2292   EXPECT_EQ(MethodName, "main");
2293 }
2294 
2295 TEST(GSYMTest, TestDWARFDeadStripAddr8) {
2296   // Check that various techniques that compilers use for dead code stripping
2297   // work for 4 byte addresses. Make sure we keep the good functions and
2298   // strip any functions whose name starts with "stripped".
2299   //
2300   // 1 - Compilers might set the low PC to -1 (UINT64_MAX) for compile unit
2301   //     with 8 byte addresses ("stripped1")
2302   // 2 - Set the low and high PC to the same value ("stripped2")
2303   // 3 - Have the high PC lower than the low PC ("stripped3")
2304   //
2305   // 0x0000000b: DW_TAG_compile_unit
2306   //               DW_AT_name	("/tmp/main.c")
2307   //               DW_AT_low_pc	(0x0000000000001000)
2308   //               DW_AT_high_pc	(0x0000000000002000)
2309   //               DW_AT_language	(DW_LANG_C_plus_plus)
2310   //
2311   // 0x0000001e:   DW_TAG_subprogram
2312   //                 DW_AT_name	("main")
2313   //                 DW_AT_low_pc	(0x0000000000001000)
2314   //                 DW_AT_high_pc	(0x0000000000002000)
2315   //
2316   // 0x0000002f:   DW_TAG_subprogram
2317   //                 DW_AT_name	("stripped1")
2318   //                 DW_AT_low_pc	(0xffffffffffffffff)
2319   //                 DW_AT_high_pc	(0x0000000000000000)
2320   //
2321   // 0x00000040:   DW_TAG_subprogram
2322   //                 DW_AT_name	("stripped2")
2323   //                 DW_AT_low_pc	(0x0000000000003000)
2324   //                 DW_AT_high_pc	(0x0000000000003000)
2325   //
2326   // 0x00000055:   DW_TAG_subprogram
2327   //                 DW_AT_name	("stripped3")
2328   //                 DW_AT_low_pc	(0x0000000000004000)
2329   //                 DW_AT_high_pc	(0x0000000000003fff)
2330   //
2331   // 0x0000006a:   NULL
2332 
2333   StringRef yamldata = R"(
2334   debug_str:
2335     - ''
2336     - '/tmp/main.c'
2337     - main
2338     - stripped1
2339     - stripped2
2340     - stripped3
2341   debug_abbrev:
2342     - Table:
2343         - Code:            0x00000001
2344           Tag:             DW_TAG_compile_unit
2345           Children:        DW_CHILDREN_yes
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             - Attribute:       DW_AT_language
2354               Form:            DW_FORM_data2
2355         - Code:            0x00000002
2356           Tag:             DW_TAG_subprogram
2357           Children:        DW_CHILDREN_no
2358           Attributes:
2359             - Attribute:       DW_AT_name
2360               Form:            DW_FORM_strp
2361             - Attribute:       DW_AT_low_pc
2362               Form:            DW_FORM_addr
2363             - Attribute:       DW_AT_high_pc
2364               Form:            DW_FORM_data4
2365         - Code:            0x00000003
2366           Tag:             DW_TAG_subprogram
2367           Children:        DW_CHILDREN_no
2368           Attributes:
2369             - Attribute:       DW_AT_name
2370               Form:            DW_FORM_strp
2371             - Attribute:       DW_AT_low_pc
2372               Form:            DW_FORM_addr
2373             - Attribute:       DW_AT_high_pc
2374               Form:            DW_FORM_addr
2375   debug_info:
2376     - Version:         4
2377       AddrSize:        8
2378       Entries:
2379         - AbbrCode:        0x00000001
2380           Values:
2381             - Value:           0x0000000000000001
2382             - Value:           0x0000000000001000
2383             - Value:           0x0000000000001000
2384             - Value:           0x0000000000000004
2385         - AbbrCode:        0x00000002
2386           Values:
2387             - Value:           0x000000000000000D
2388             - Value:           0x0000000000001000
2389             - Value:           0x0000000000001000
2390         - AbbrCode:        0x00000002
2391           Values:
2392             - Value:           0x0000000000000012
2393             - Value:           0xFFFFFFFFFFFFFFFF
2394             - Value:           0x0000000000000001
2395         - AbbrCode:        0x00000003
2396           Values:
2397             - Value:           0x000000000000001C
2398             - Value:           0x0000000000003000
2399             - Value:           0x0000000000003000
2400         - AbbrCode:        0x00000003
2401           Values:
2402             - Value:           0x0000000000000026
2403             - Value:           0x0000000000004000
2404             - Value:           0x0000000000003FFF
2405         - AbbrCode:        0x00000000
2406   )";
2407   auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);
2408   ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());
2409   std::unique_ptr<DWARFContext> DwarfContext =
2410       DWARFContext::create(*ErrOrSections, 8);
2411   ASSERT_TRUE(DwarfContext.get() != nullptr);
2412   auto &OS = llvm::nulls();
2413   OutputAggregator OSAgg(&OS);
2414   GsymCreator GC;
2415   DwarfTransformer DT(*DwarfContext, GC);
2416   const uint32_t ThreadCount = 1;
2417   ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());
2418   ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());
2419   SmallString<512> Str;
2420   raw_svector_ostream OutStrm(Str);
2421   const auto ByteOrder = llvm::endianness::native;
2422   FileWriter FW(OutStrm, ByteOrder);
2423   ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());
2424   Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());
2425   ASSERT_THAT_EXPECTED(GR, Succeeded());
2426 
2427   // Test that the only function that made it was the "main" function.
2428   EXPECT_EQ(GR->getNumAddresses(), 1u);
2429   auto ExpFI = GR->getFunctionInfo(0x1000);
2430   ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
2431   ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x2000));
2432   StringRef MethodName = GR->getString(ExpFI->Name);
2433   EXPECT_EQ(MethodName, "main");
2434 }
2435 
2436 TEST(GSYMTest, TestGsymCreatorMultipleSymbolsWithNoSize) {
2437   // Multiple symbols at the same address with zero size were being emitted
2438   // instead of being combined into a single entry. This function tests to make
2439   // sure we only get one symbol.
2440   uint8_t UUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
2441   GsymCreator GC;
2442   GC.setUUID(UUID);
2443   constexpr uint64_t BaseAddr = 0x1000;
2444   constexpr uint8_t AddrOffSize = 1;
2445   const uint32_t Func1Name = GC.insertString("foo");
2446   const uint32_t Func2Name = GC.insertString("bar");
2447   GC.addFunctionInfo(FunctionInfo(BaseAddr, 0, Func1Name));
2448   GC.addFunctionInfo(FunctionInfo(BaseAddr, 0, Func2Name));
2449   OutputAggregator Null(nullptr);
2450   Error Err = GC.finalize(Null);
2451   ASSERT_FALSE(Err);
2452   TestEncodeDecode(GC, llvm::endianness::little, GSYM_VERSION, AddrOffSize,
2453                    BaseAddr,
2454                    1, // NumAddresses
2455                    ArrayRef<uint8_t>(UUID));
2456   TestEncodeDecode(GC, llvm::endianness::big, GSYM_VERSION, AddrOffSize,
2457                    BaseAddr,
2458                    1, // NumAddresses
2459                    ArrayRef<uint8_t>(UUID));
2460 }
2461 
2462 // Helper function to quickly create a FunctionInfo in a GsymCreator for testing.
2463 static void AddFunctionInfo(GsymCreator &GC, const char *FuncName,
2464                             uint64_t FuncAddr, const char *SourcePath,
2465                             const char *HeaderPath) {
2466   FunctionInfo FI(FuncAddr, 0x30, GC.insertString(FuncName));
2467   FI.OptLineTable = LineTable();
2468   const uint32_t SourceFileIdx = GC.insertFile(SourcePath);
2469   const uint32_t HeaderFileIdx = GC.insertFile(HeaderPath);
2470   FI.OptLineTable->push(LineEntry(FuncAddr+0x00, SourceFileIdx, 5));
2471   FI.OptLineTable->push(LineEntry(FuncAddr+0x10, HeaderFileIdx, 10));
2472   FI.OptLineTable->push(LineEntry(FuncAddr+0x12, HeaderFileIdx, 20));
2473   FI.OptLineTable->push(LineEntry(FuncAddr+0x14, HeaderFileIdx, 11));
2474   FI.OptLineTable->push(LineEntry(FuncAddr+0x16, HeaderFileIdx, 30));
2475   FI.OptLineTable->push(LineEntry(FuncAddr+0x18, HeaderFileIdx, 12));
2476   FI.OptLineTable->push(LineEntry(FuncAddr+0x20, SourceFileIdx, 8));
2477   FI.Inline = InlineInfo();
2478 
2479   std::string InlineName1(FuncName); InlineName1.append("1");
2480   std::string InlineName2(FuncName); InlineName2.append("2");
2481   std::string InlineName3(FuncName); InlineName3.append("3");
2482 
2483   FI.Inline->Name = GC.insertString(InlineName1);
2484   FI.Inline->CallFile = SourceFileIdx;
2485   FI.Inline->CallLine = 6;
2486   FI.Inline->Ranges.insert(AddressRange(FuncAddr + 0x10, FuncAddr + 0x20));
2487   InlineInfo Inline2;
2488   Inline2.Name = GC.insertString(InlineName2);
2489   Inline2.CallFile = HeaderFileIdx;
2490   Inline2.CallLine = 33;
2491   Inline2.Ranges.insert(AddressRange(FuncAddr + 0x12, FuncAddr + 0x14));
2492   FI.Inline->Children.emplace_back(Inline2);
2493   InlineInfo Inline3;
2494   Inline3.Name = GC.insertString(InlineName3);
2495   Inline3.CallFile = HeaderFileIdx;
2496   Inline3.CallLine = 35;
2497   Inline3.Ranges.insert(AddressRange(FuncAddr + 0x16, FuncAddr + 0x18));
2498   FI.Inline->Children.emplace_back(Inline3);
2499   GC.addFunctionInfo(std::move(FI));
2500 }
2501 
2502 // Finalize a GsymCreator, encode it and decode it and return the error or
2503 // GsymReader that was successfully decoded.
2504 static Expected<GsymReader> FinalizeEncodeAndDecode(GsymCreator &GC) {
2505   OutputAggregator Null(nullptr);
2506   Error FinalizeErr = GC.finalize(Null);
2507   if (FinalizeErr)
2508     return std::move(FinalizeErr);
2509   SmallString<1024> Str;
2510   raw_svector_ostream OutStrm(Str);
2511   const auto ByteOrder = llvm::endianness::native;
2512   FileWriter FW(OutStrm, ByteOrder);
2513   llvm::Error Err = GC.encode(FW);
2514   if (Err)
2515     return std::move(Err);
2516   return GsymReader::copyBuffer(OutStrm.str());
2517 }
2518 
2519 TEST(GSYMTest, TestGsymSegmenting) {
2520   // Test creating a GSYM file with function infos and segment the information.
2521   // We verify segmenting is working by creating a full GSYM and also by
2522   // encoding multiple segments, then we verify that we get the same information
2523   // when doing lookups on the full GSYM that was decoded from encoding the
2524   // entire GSYM and also by decoding information from the segments themselves.
2525   GsymCreator GC;
2526   GC.setBaseAddress(0);
2527   AddFunctionInfo(GC, "main", 0x1000, "/tmp/main.c", "/tmp/main.h");
2528   AddFunctionInfo(GC, "foo", 0x2000, "/tmp/foo.c", "/tmp/foo.h");
2529   AddFunctionInfo(GC, "bar", 0x3000, "/tmp/bar.c", "/tmp/bar.h");
2530   AddFunctionInfo(GC, "baz", 0x4000, "/tmp/baz.c", "/tmp/baz.h");
2531   Expected<GsymReader> GR = FinalizeEncodeAndDecode(GC);
2532   ASSERT_THAT_EXPECTED(GR, Succeeded());
2533   //GR->dump(outs());
2534 
2535   // Create segmented GSYM files where each file contains 1 function. We will
2536   // then test doing lookups on the "GR", or the full GSYM file and then test
2537   // doing lookups on the GsymReader objects for each segment to ensure we get
2538   // the exact same information. So after all of the code below we will have
2539   // GsymReader objects that each contain one function. We name the creators
2540   // and readers to match the one and only address they contain.
2541   // GC1000 and GR1000 are for [0x1000-0x1030)
2542   // GC2000 and GR2000 are for [0x2000-0x2030)
2543   // GC3000 and GR3000 are for [0x3000-0x3030)
2544   // GC4000 and GR4000 are for [0x4000-0x4030)
2545 
2546   // Create the segments and verify that FuncIdx, an in/out parameter, gets
2547   // updated as expected.
2548   size_t FuncIdx = 0;
2549   // Make sure we get an error if the segment size is too small to encode a
2550   // single function info.
2551   llvm::Expected<std::unique_ptr<GsymCreator>> GCError =
2552       GC.createSegment(57, FuncIdx);
2553   ASSERT_FALSE((bool)GCError);
2554   checkError("a segment size of 57 is to small to fit any function infos, "
2555              "specify a larger value", GCError.takeError());
2556   // Make sure that the function index didn't get incremented when we didn't
2557   // encode any values into the segmented GsymCreator.
2558   ASSERT_EQ(FuncIdx, (size_t)0);
2559 
2560   llvm::Expected<std::unique_ptr<GsymCreator>> GC1000 =
2561       GC.createSegment(128, FuncIdx);
2562   ASSERT_THAT_EXPECTED(GC1000, Succeeded());
2563   ASSERT_EQ(FuncIdx, (size_t)1);
2564   llvm::Expected<std::unique_ptr<GsymCreator>> GC2000 =
2565       GC.createSegment(128, FuncIdx);
2566   ASSERT_THAT_EXPECTED(GC2000, Succeeded());
2567   ASSERT_EQ(FuncIdx, (size_t)2);
2568   llvm::Expected<std::unique_ptr<GsymCreator>> GC3000 =
2569       GC.createSegment(128, FuncIdx);
2570   ASSERT_THAT_EXPECTED(GC3000, Succeeded());
2571   ASSERT_EQ(FuncIdx, (size_t)3);
2572   llvm::Expected<std::unique_ptr<GsymCreator>> GC4000 =
2573       GC.createSegment(128, FuncIdx);
2574   ASSERT_THAT_EXPECTED(GC4000, Succeeded());
2575   ASSERT_EQ(FuncIdx, (size_t)4);
2576   // When there are no function infos left to encode we expect to get  no error
2577   // and get a NULL GsymCreator in the return value from createSegment.
2578   llvm::Expected<std::unique_ptr<GsymCreator>> GCNull =
2579       GC.createSegment(128, FuncIdx);
2580   ASSERT_THAT_EXPECTED(GCNull, Succeeded());
2581   ASSERT_TRUE(GC1000.get() != nullptr);
2582   ASSERT_TRUE(GC2000.get() != nullptr);
2583   ASSERT_TRUE(GC3000.get() != nullptr);
2584   ASSERT_TRUE(GC4000.get() != nullptr);
2585   ASSERT_TRUE(GCNull.get() == nullptr);
2586   // Encode and decode the GsymReader for each segment and verify they succeed.
2587   Expected<GsymReader> GR1000 = FinalizeEncodeAndDecode(*GC1000.get());
2588   ASSERT_THAT_EXPECTED(GR1000, Succeeded());
2589   Expected<GsymReader> GR2000 = FinalizeEncodeAndDecode(*GC2000.get());
2590   ASSERT_THAT_EXPECTED(GR2000, Succeeded());
2591   Expected<GsymReader> GR3000 = FinalizeEncodeAndDecode(*GC3000.get());
2592   ASSERT_THAT_EXPECTED(GR3000, Succeeded());
2593   Expected<GsymReader> GR4000 = FinalizeEncodeAndDecode(*GC4000.get());
2594   ASSERT_THAT_EXPECTED(GR4000, Succeeded());
2595 
2596   // Verify that all lookups match the range [0x1000-0x1030) when doing lookups
2597   // in the GsymReader that contains all functions and from the segmented
2598   // GsymReader in GR1000.
2599   for (uint64_t Addr = 0x1000; Addr < 0x1030; ++Addr) {
2600     // Lookup in the main GsymReader that contains all function infos
2601     auto MainLR = GR->lookup(Addr);
2602     ASSERT_THAT_EXPECTED(MainLR, Succeeded());
2603     auto SegmentLR = GR1000->lookup(Addr);
2604     ASSERT_THAT_EXPECTED(SegmentLR, Succeeded());
2605     // Make sure the lookup results match.
2606     EXPECT_EQ(MainLR.get(), SegmentLR.get());
2607     // Make sure that the lookups on the functions that are not in the segment
2608     // fail as expected.
2609     ASSERT_THAT_EXPECTED(GR1000->lookup(0x2000), Failed());
2610     ASSERT_THAT_EXPECTED(GR1000->lookup(0x3000), Failed());
2611     ASSERT_THAT_EXPECTED(GR1000->lookup(0x4000), Failed());
2612   }
2613 
2614   // Verify that all lookups match the range [0x2000-0x2030) when doing lookups
2615   // in the GsymReader that contains all functions and from the segmented
2616   // GsymReader in GR2000.
2617   for (uint64_t Addr = 0x2000; Addr < 0x2030; ++Addr) {
2618     // Lookup in the main GsymReader that contains all function infos
2619     auto MainLR = GR->lookup(Addr);
2620     ASSERT_THAT_EXPECTED(MainLR, Succeeded());
2621     auto SegmentLR = GR2000->lookup(Addr);
2622     ASSERT_THAT_EXPECTED(SegmentLR, Succeeded());
2623     // Make sure the lookup results match.
2624     EXPECT_EQ(MainLR.get(), SegmentLR.get());
2625     // Make sure that the lookups on the functions that are not in the segment
2626     // fail as expected.
2627     ASSERT_THAT_EXPECTED(GR2000->lookup(0x1000), Failed());
2628     ASSERT_THAT_EXPECTED(GR2000->lookup(0x3000), Failed());
2629     ASSERT_THAT_EXPECTED(GR2000->lookup(0x4000), Failed());
2630 
2631   }
2632 
2633   // Verify that all lookups match the range [0x3000-0x3030) when doing lookups
2634   // in the GsymReader that contains all functions and from the segmented
2635   // GsymReader in GR3000.
2636   for (uint64_t Addr = 0x3000; Addr < 0x3030; ++Addr) {
2637     // Lookup in the main GsymReader that contains all function infos
2638     auto MainLR = GR->lookup(Addr);
2639     ASSERT_THAT_EXPECTED(MainLR, Succeeded());
2640     auto SegmentLR = GR3000->lookup(Addr);
2641     ASSERT_THAT_EXPECTED(SegmentLR, Succeeded());
2642     // Make sure the lookup results match.
2643     EXPECT_EQ(MainLR.get(), SegmentLR.get());
2644     // Make sure that the lookups on the functions that are not in the segment
2645     // fail as expected.
2646     ASSERT_THAT_EXPECTED(GR3000->lookup(0x1000), Failed());
2647     ASSERT_THAT_EXPECTED(GR3000->lookup(0x2000), Failed());
2648     ASSERT_THAT_EXPECTED(GR3000->lookup(0x4000), Failed());
2649 }
2650 
2651   // Verify that all lookups match the range [0x4000-0x4030) when doing lookups
2652   // in the GsymReader that contains all functions and from the segmented
2653   // GsymReader in GR4000.
2654   for (uint64_t Addr = 0x4000; Addr < 0x4030; ++Addr) {
2655     // Lookup in the main GsymReader that contains all function infos
2656     auto MainLR = GR->lookup(Addr);
2657     ASSERT_THAT_EXPECTED(MainLR, Succeeded());
2658     // Lookup in the GsymReader for that contains 0x4000
2659     auto SegmentLR = GR4000->lookup(Addr);
2660     ASSERT_THAT_EXPECTED(SegmentLR, Succeeded());
2661     // Make sure the lookup results match.
2662     EXPECT_EQ(MainLR.get(), SegmentLR.get());
2663     // Make sure that the lookups on the functions that are not in the segment
2664     // fail as expected.
2665     ASSERT_THAT_EXPECTED(GR4000->lookup(0x1000), Failed());
2666     ASSERT_THAT_EXPECTED(GR4000->lookup(0x2000), Failed());
2667     ASSERT_THAT_EXPECTED(GR4000->lookup(0x3000), Failed());
2668   }
2669 }
2670 
2671 TEST(GSYMTest, TestGsymSegmentingNoBase) {
2672   // Test creating a GSYM file with function infos and segment the information.
2673   // We verify segmenting is working by creating a full GSYM and also by
2674   // encoding multiple segments, then we verify that we get the same information
2675   // when doing lookups on the full GSYM that was decoded from encoding the
2676   // entire GSYM and also by decoding information from the segments themselves.
2677   GsymCreator GC;
2678   AddFunctionInfo(GC, "main", 0x1000, "/tmp/main.c", "/tmp/main.h");
2679   AddFunctionInfo(GC, "foo", 0x2000, "/tmp/foo.c", "/tmp/foo.h");
2680   AddFunctionInfo(GC, "bar", 0x3000, "/tmp/bar.c", "/tmp/bar.h");
2681   AddFunctionInfo(GC, "baz", 0x4000, "/tmp/baz.c", "/tmp/baz.h");
2682   Expected<GsymReader> GR = FinalizeEncodeAndDecode(GC);
2683   ASSERT_THAT_EXPECTED(GR, Succeeded());
2684   //GR->dump(outs());
2685 
2686   // Create segmented GSYM files where each file contains 1 function. We will
2687   // then test doing lookups on the "GR", or the full GSYM file and then test
2688   // doing lookups on the GsymReader objects for each segment to ensure we get
2689   // the exact same information. So after all of the code below we will have
2690   // GsymReader objects that each contain one function. We name the creators
2691   // and readers to match the one and only address they contain.
2692   // GC1000 and GR1000 are for [0x1000-0x1030)
2693   // GC2000 and GR2000 are for [0x2000-0x2030)
2694   // GC3000 and GR3000 are for [0x3000-0x3030)
2695   // GC4000 and GR4000 are for [0x4000-0x4030)
2696 
2697   // Create the segments and verify that FuncIdx, an in/out parameter, gets
2698   // updated as expected.
2699   size_t FuncIdx = 0;
2700   // Make sure we get an error if the segment size is too small to encode a
2701   // single function info.
2702   llvm::Expected<std::unique_ptr<GsymCreator>> GCError =
2703       GC.createSegment(57, FuncIdx);
2704   ASSERT_FALSE((bool)GCError);
2705   checkError("a segment size of 57 is to small to fit any function infos, "
2706              "specify a larger value", GCError.takeError());
2707   // Make sure that the function index didn't get incremented when we didn't
2708   // encode any values into the segmented GsymCreator.
2709   ASSERT_EQ(FuncIdx, (size_t)0);
2710 
2711   llvm::Expected<std::unique_ptr<GsymCreator>> GC1000 =
2712       GC.createSegment(128, FuncIdx);
2713   ASSERT_THAT_EXPECTED(GC1000, Succeeded());
2714   ASSERT_EQ(FuncIdx, (size_t)1);
2715   llvm::Expected<std::unique_ptr<GsymCreator>> GC2000 =
2716       GC.createSegment(128, FuncIdx);
2717   ASSERT_THAT_EXPECTED(GC2000, Succeeded());
2718   ASSERT_EQ(FuncIdx, (size_t)2);
2719   llvm::Expected<std::unique_ptr<GsymCreator>> GC3000 =
2720       GC.createSegment(128, FuncIdx);
2721   ASSERT_THAT_EXPECTED(GC3000, Succeeded());
2722   ASSERT_EQ(FuncIdx, (size_t)3);
2723   llvm::Expected<std::unique_ptr<GsymCreator>> GC4000 =
2724       GC.createSegment(128, FuncIdx);
2725   ASSERT_THAT_EXPECTED(GC4000, Succeeded());
2726   ASSERT_EQ(FuncIdx, (size_t)4);
2727   // When there are no function infos left to encode we expect to get  no error
2728   // and get a NULL GsymCreator in the return value from createSegment.
2729   llvm::Expected<std::unique_ptr<GsymCreator>> GCNull =
2730       GC.createSegment(128, FuncIdx);
2731   ASSERT_THAT_EXPECTED(GCNull, Succeeded());
2732   ASSERT_TRUE(GC1000.get() != nullptr);
2733   ASSERT_TRUE(GC2000.get() != nullptr);
2734   ASSERT_TRUE(GC3000.get() != nullptr);
2735   ASSERT_TRUE(GC4000.get() != nullptr);
2736   ASSERT_TRUE(GCNull.get() == nullptr);
2737   // Encode and decode the GsymReader for each segment and verify they succeed.
2738   Expected<GsymReader> GR1000 = FinalizeEncodeAndDecode(*GC1000.get());
2739   ASSERT_THAT_EXPECTED(GR1000, Succeeded());
2740   Expected<GsymReader> GR2000 = FinalizeEncodeAndDecode(*GC2000.get());
2741   ASSERT_THAT_EXPECTED(GR2000, Succeeded());
2742   Expected<GsymReader> GR3000 = FinalizeEncodeAndDecode(*GC3000.get());
2743   ASSERT_THAT_EXPECTED(GR3000, Succeeded());
2744   Expected<GsymReader> GR4000 = FinalizeEncodeAndDecode(*GC4000.get());
2745   ASSERT_THAT_EXPECTED(GR4000, Succeeded());
2746 
2747   // Verify that all lookups match the range [0x1000-0x1030) when doing lookups
2748   // in the GsymReader that contains all functions and from the segmented
2749   // GsymReader in GR1000.
2750   for (uint64_t Addr = 0x1000; Addr < 0x1030; ++Addr) {
2751     // Lookup in the main GsymReader that contains all function infos
2752     auto MainLR = GR->lookup(Addr);
2753     ASSERT_THAT_EXPECTED(MainLR, Succeeded());
2754     auto SegmentLR = GR1000->lookup(Addr);
2755     ASSERT_THAT_EXPECTED(SegmentLR, Succeeded());
2756     // Make sure the lookup results match.
2757     EXPECT_EQ(MainLR.get(), SegmentLR.get());
2758     // Make sure that the lookups on the functions that are not in the segment
2759     // fail as expected.
2760     ASSERT_THAT_EXPECTED(GR1000->lookup(0x2000), Failed());
2761     ASSERT_THAT_EXPECTED(GR1000->lookup(0x3000), Failed());
2762     ASSERT_THAT_EXPECTED(GR1000->lookup(0x4000), Failed());
2763   }
2764 
2765   // Verify that all lookups match the range [0x2000-0x2030) when doing lookups
2766   // in the GsymReader that contains all functions and from the segmented
2767   // GsymReader in GR2000.
2768   for (uint64_t Addr = 0x2000; Addr < 0x2030; ++Addr) {
2769     // Lookup in the main GsymReader that contains all function infos
2770     auto MainLR = GR->lookup(Addr);
2771     ASSERT_THAT_EXPECTED(MainLR, Succeeded());
2772     auto SegmentLR = GR2000->lookup(Addr);
2773     ASSERT_THAT_EXPECTED(SegmentLR, Succeeded());
2774     // Make sure the lookup results match.
2775     EXPECT_EQ(MainLR.get(), SegmentLR.get());
2776     // Make sure that the lookups on the functions that are not in the segment
2777     // fail as expected.
2778     ASSERT_THAT_EXPECTED(GR2000->lookup(0x1000), Failed());
2779     ASSERT_THAT_EXPECTED(GR2000->lookup(0x3000), Failed());
2780     ASSERT_THAT_EXPECTED(GR2000->lookup(0x4000), Failed());
2781 
2782   }
2783 
2784   // Verify that all lookups match the range [0x3000-0x3030) when doing lookups
2785   // in the GsymReader that contains all functions and from the segmented
2786   // GsymReader in GR3000.
2787   for (uint64_t Addr = 0x3000; Addr < 0x3030; ++Addr) {
2788     // Lookup in the main GsymReader that contains all function infos
2789     auto MainLR = GR->lookup(Addr);
2790     ASSERT_THAT_EXPECTED(MainLR, Succeeded());
2791     auto SegmentLR = GR3000->lookup(Addr);
2792     ASSERT_THAT_EXPECTED(SegmentLR, Succeeded());
2793     // Make sure the lookup results match.
2794     EXPECT_EQ(MainLR.get(), SegmentLR.get());
2795     // Make sure that the lookups on the functions that are not in the segment
2796     // fail as expected.
2797     ASSERT_THAT_EXPECTED(GR3000->lookup(0x1000), Failed());
2798     ASSERT_THAT_EXPECTED(GR3000->lookup(0x2000), Failed());
2799     ASSERT_THAT_EXPECTED(GR3000->lookup(0x4000), Failed());
2800 }
2801 
2802   // Verify that all lookups match the range [0x4000-0x4030) when doing lookups
2803   // in the GsymReader that contains all functions and from the segmented
2804   // GsymReader in GR4000.
2805   for (uint64_t Addr = 0x4000; Addr < 0x4030; ++Addr) {
2806     // Lookup in the main GsymReader that contains all function infos
2807     auto MainLR = GR->lookup(Addr);
2808     ASSERT_THAT_EXPECTED(MainLR, Succeeded());
2809     // Lookup in the GsymReader for that contains 0x4000
2810     auto SegmentLR = GR4000->lookup(Addr);
2811     ASSERT_THAT_EXPECTED(SegmentLR, Succeeded());
2812     // Make sure the lookup results match.
2813     EXPECT_EQ(MainLR.get(), SegmentLR.get());
2814     // Make sure that the lookups on the functions that are not in the segment
2815     // fail as expected.
2816     ASSERT_THAT_EXPECTED(GR4000->lookup(0x1000), Failed());
2817     ASSERT_THAT_EXPECTED(GR4000->lookup(0x2000), Failed());
2818     ASSERT_THAT_EXPECTED(GR4000->lookup(0x3000), Failed());
2819   }
2820 }
2821 
2822 
2823 TEST(GSYMTest, TestDWARFInlineRangeScopes) {
2824   // Test cases where inlined functions address ranges are not contained in the
2825   // parent ranges and that we can successfully remove them and emit error
2826   // messages. The DWARF for this looks like the dump below. The inlined
2827   // functions named "invalid1" and "invalid2" are expected to be removed and
2828   // an appropriate error message will be emitted.
2829   //
2830   // 0x0000000b: DW_TAG_compile_unit
2831   //               DW_AT_name	("/tmp/main.cpp")
2832   //               DW_AT_language	(DW_LANG_C)
2833   //               DW_AT_stmt_list	(0x00000000)
2834   //
2835   // 0x00000015:   DW_TAG_subprogram
2836   //                 DW_AT_name	("foo")
2837   //                 DW_AT_low_pc	(0x0000000000001000)
2838   //                 DW_AT_high_pc	(0x0000000000002000)
2839   //
2840   // 0x0000002a:     DW_TAG_inlined_subroutine
2841   //                   DW_AT_name	("invalid1")
2842   //                   DW_AT_low_pc	(0x0000000000000fff)
2843   //                   DW_AT_high_pc	(0x0000000000001001)
2844   //                   DW_AT_call_file	("/tmp/main.cpp")
2845   //                   DW_AT_call_line	(10)
2846   //
2847   // 0x00000041:     DW_TAG_inlined_subroutine
2848   //                   DW_AT_name	("valid1")
2849   //                   DW_AT_low_pc	(0x0000000000001010)
2850   //                   DW_AT_high_pc	(0x0000000000001100)
2851   //                   DW_AT_call_file	("/tmp/main.cpp")
2852   //                   DW_AT_call_line	(11)
2853   //
2854   // 0x00000058:       DW_TAG_inlined_subroutine
2855   //                     DW_AT_name	("invalid2")
2856   //                     DW_AT_low_pc	(0x0000000000001000)
2857   //                     DW_AT_high_pc	(0x0000000000001100)
2858   //                     DW_AT_call_file	("/tmp/main.cpp")
2859   //                     DW_AT_call_line	(12)
2860   //
2861   // 0x0000006f:       DW_TAG_inlined_subroutine
2862   //                     DW_AT_name	("valid2")
2863   //                     DW_AT_low_pc	(0x0000000000001020)
2864   //                     DW_AT_high_pc	(0x0000000000001030)
2865   //                     DW_AT_call_file	("/tmp/main.cpp")
2866   //                     DW_AT_call_line	(13)
2867   //
2868   // 0x00000086:       NULL
2869   //
2870   // 0x00000087:     NULL
2871   //
2872   // 0x00000088:   NULL
2873 
2874   StringRef yamldata = R"(
2875   debug_str:
2876     - ''
2877     - '/tmp/main.cpp'
2878     - foo
2879     - invalid1
2880     - valid1
2881     - invalid2
2882     - valid2
2883   debug_abbrev:
2884     - ID:              0
2885       Table:
2886         - Code:            0x1
2887           Tag:             DW_TAG_compile_unit
2888           Children:        DW_CHILDREN_yes
2889           Attributes:
2890             - Attribute:       DW_AT_name
2891               Form:            DW_FORM_strp
2892             - Attribute:       DW_AT_language
2893               Form:            DW_FORM_udata
2894             - Attribute:       DW_AT_stmt_list
2895               Form:            DW_FORM_sec_offset
2896         - Code:            0x2
2897           Tag:             DW_TAG_subprogram
2898           Children:        DW_CHILDREN_yes
2899           Attributes:
2900             - Attribute:       DW_AT_name
2901               Form:            DW_FORM_strp
2902             - Attribute:       DW_AT_low_pc
2903               Form:            DW_FORM_addr
2904             - Attribute:       DW_AT_high_pc
2905               Form:            DW_FORM_addr
2906         - Code:            0x3
2907           Tag:             DW_TAG_inlined_subroutine
2908           Children:        DW_CHILDREN_no
2909           Attributes:
2910             - Attribute:       DW_AT_name
2911               Form:            DW_FORM_strp
2912             - Attribute:       DW_AT_low_pc
2913               Form:            DW_FORM_addr
2914             - Attribute:       DW_AT_high_pc
2915               Form:            DW_FORM_addr
2916             - Attribute:       DW_AT_call_file
2917               Form:            DW_FORM_data1
2918             - Attribute:       DW_AT_call_line
2919               Form:            DW_FORM_data1
2920         - Code:            0x4
2921           Tag:             DW_TAG_inlined_subroutine
2922           Children:        DW_CHILDREN_yes
2923           Attributes:
2924             - Attribute:       DW_AT_name
2925               Form:            DW_FORM_strp
2926             - Attribute:       DW_AT_low_pc
2927               Form:            DW_FORM_addr
2928             - Attribute:       DW_AT_high_pc
2929               Form:            DW_FORM_addr
2930             - Attribute:       DW_AT_call_file
2931               Form:            DW_FORM_data1
2932             - Attribute:       DW_AT_call_line
2933               Form:            DW_FORM_data1
2934   debug_info:
2935     - Length:          0x85
2936       Version:         4
2937       AbbrevTableID:   0
2938       AbbrOffset:      0x0
2939       AddrSize:        8
2940       Entries:
2941         - AbbrCode:        0x1
2942           Values:
2943             - Value:           0x1
2944             - Value:           0x2
2945             - Value:           0x0
2946         - AbbrCode:        0x2
2947           Values:
2948             - Value:           0xF
2949             - Value:           0x1000
2950             - Value:           0x2000
2951         - AbbrCode:        0x3
2952           Values:
2953             - Value:           0x13
2954             - Value:           0xFFF
2955             - Value:           0x1001
2956             - Value:           0x1
2957             - Value:           0xA
2958         - AbbrCode:        0x4
2959           Values:
2960             - Value:           0x1C
2961             - Value:           0x1010
2962             - Value:           0x1100
2963             - Value:           0x1
2964             - Value:           0xB
2965         - AbbrCode:        0x3
2966           Values:
2967             - Value:           0x23
2968             - Value:           0x1000
2969             - Value:           0x1100
2970             - Value:           0x1
2971             - Value:           0xC
2972         - AbbrCode:        0x3
2973           Values:
2974             - Value:           0x2C
2975             - Value:           0x1020
2976             - Value:           0x1030
2977             - Value:           0x1
2978             - Value:           0xD
2979         - AbbrCode:        0x0
2980         - AbbrCode:        0x0
2981         - AbbrCode:        0x0
2982   debug_line:
2983     - Length:          84
2984       Version:         2
2985       PrologueLength:  36
2986       MinInstLength:   1
2987       DefaultIsStmt:   1
2988       LineBase:        251
2989       LineRange:       14
2990       OpcodeBase:      13
2991       StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]
2992       IncludeDirs:
2993         - '/tmp'
2994       Files:
2995         - Name:            main.cpp
2996           DirIdx:          1
2997           ModTime:         0
2998           Length:          0
2999       Opcodes:
3000         - Opcode:          DW_LNS_extended_op
3001           ExtLen:          9
3002           SubOpcode:       DW_LNE_set_address
3003           Data:            4096
3004         - Opcode:          DW_LNS_advance_line
3005           SData:           9
3006           Data:            0
3007         - Opcode:          DW_LNS_copy
3008           Data:            0
3009         - Opcode:          DW_LNS_advance_pc
3010           Data:            16
3011         - Opcode:          DW_LNS_advance_line
3012           SData:           1
3013           Data:            0
3014         - Opcode:          DW_LNS_copy
3015           Data:            0
3016         - Opcode:          DW_LNS_advance_pc
3017           Data:            16
3018         - Opcode:          DW_LNS_advance_line
3019           SData:           1
3020           Data:            0
3021         - Opcode:          DW_LNS_copy
3022           Data:            0
3023         - Opcode:          DW_LNS_advance_pc
3024           Data:            16
3025         - Opcode:          DW_LNS_advance_line
3026           SData:           1
3027           Data:            0
3028         - Opcode:          DW_LNS_copy
3029           Data:            0
3030         - Opcode:          DW_LNS_advance_pc
3031           Data:            4048
3032         - Opcode:          DW_LNS_advance_line
3033           SData:           1
3034           Data:            0
3035         - Opcode:          DW_LNS_copy
3036           Data:            0
3037         - Opcode:          DW_LNS_advance_pc
3038           Data:            16
3039         - Opcode:          DW_LNS_advance_line
3040           SData:           -1
3041           Data:            0
3042         - Opcode:          DW_LNS_extended_op
3043           ExtLen:          1
3044           SubOpcode:       DW_LNE_end_sequence
3045           Data:            0
3046   )";
3047   auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);
3048   ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());
3049   std::unique_ptr<DWARFContext> DwarfContext =
3050       DWARFContext::create(*ErrOrSections, 8);
3051   ASSERT_TRUE(DwarfContext.get() != nullptr);
3052   std::string errors;
3053   raw_string_ostream OS(errors);
3054   OutputAggregator OSAgg(&OS);
3055   GsymCreator GC;
3056   DwarfTransformer DT(*DwarfContext, GC);
3057   const uint32_t ThreadCount = 1;
3058   ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());
3059   ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());
3060   SmallString<512> Str;
3061   raw_svector_ostream OutStrm(Str);
3062   const auto ByteOrder = llvm::endianness::native;
3063   FileWriter FW(OutStrm, ByteOrder);
3064   ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());
3065   Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());
3066   ASSERT_THAT_EXPECTED(GR, Succeeded());
3067   // There should only be one function in our GSYM.
3068   EXPECT_EQ(GR->getNumAddresses(), 1u);
3069   auto ExpFI = GR->getFunctionInfo(0x1000);
3070   ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
3071   ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x2000));
3072   EXPECT_TRUE(ExpFI->OptLineTable.has_value());
3073   EXPECT_TRUE(ExpFI->Inline.has_value());
3074   StringRef FuncName = GR->getString(ExpFI->Name);
3075   EXPECT_EQ(FuncName, "foo");
3076   std::vector<std::string> ExpectedLogErrors = {
3077     "error: inlined function DIE at 0x0000002a has a range [0x0000000000000fff "
3078     "- 0x0000000000001001) that isn't contained in any parent address ranges, "
3079     "this inline range will be removed.",
3080     "error: inlined function DIE at 0x00000058 has a range [0x0000000000001000 "
3081     "- 0x0000000000001100) that isn't contained in any parent address ranges, "
3082     "this inline range will be removed."
3083   };
3084   // Make sure all expected errors are in the error stream for the two invalid
3085   // inlined functions that we removed due to invalid range scoping.
3086   for (const auto &Error: ExpectedLogErrors) {
3087     EXPECT_TRUE(OS.str().find(Error) != std::string::npos);
3088   }
3089   // The top level inline info is for the function "foo" itself. Verify that
3090   // we have only 1 inline function inside of this, even though the DWARF
3091   // contains two. One of the inline functions in "foo" is invalid, so we must
3092   // only end up with 1.
3093   StringRef InlineFuncName = GR->getString(ExpFI->Inline->Name);
3094   EXPECT_EQ(InlineFuncName, "foo");
3095   EXPECT_EQ(ExpFI->Inline->CallFile, 0u);
3096   EXPECT_EQ(ExpFI->Inline->CallLine, 0u);
3097   EXPECT_EQ(ExpFI->Inline->Children.size(), 1u);
3098 
3099 
3100   // The first inline function "valid1" contains two inline functions in the
3101   // DWARF, but one has an address range which isn't contained in any ranges
3102   // from "foo", so only 1 inline function be parsed.
3103   InlineInfo &Inline1 = ExpFI->Inline->Children[0];
3104   StringRef Inline1Name = GR->getString(Inline1.Name);
3105   EXPECT_EQ(Inline1Name, "valid1");
3106   EXPECT_EQ(Inline1.CallFile, 1u);
3107   EXPECT_EQ(Inline1.CallLine, 11u);
3108   EXPECT_EQ(Inline1.Children.size(), 1u);
3109 
3110 
3111   // The second inline function "valid2" contains two inline functions in the
3112   // DWARF, but one has an address range which isn't contained in any ranges
3113   // from "valid1", so only 1 inline function be parsed.
3114   InlineInfo &Inline2 = Inline1.Children[0];
3115   StringRef Inline2Name = GR->getString(Inline2.Name);
3116   EXPECT_EQ(Inline2Name, "valid2");
3117   EXPECT_EQ(Inline2.CallFile, 1u);
3118   EXPECT_EQ(Inline2.CallLine, 13u);
3119   EXPECT_EQ(Inline2.Children.size(), 0u);
3120 }
3121 
3122 TEST(GSYMTest, TestDWARFEmptyInline) {
3123   // Test cases where we have inline function information in the DWARF that
3124   // results in us trying to parse the inline info, but since the inline
3125   // info ends up not adding any valid inline functions due to ranges
3126   // not being correct, we end up not encoding any inline information. This
3127   // tests that if we end up creating an empty inline info struct, we end up
3128   // not encoding it into the GSYM file.
3129   //
3130   // 0x0000000b: DW_TAG_compile_unit
3131   //               DW_AT_name	("/tmp/main.cpp")
3132   //               DW_AT_language	(DW_LANG_C)
3133   //               DW_AT_stmt_list	(0x00000000)
3134   //
3135   // 0x00000015:   DW_TAG_subprogram
3136   //                 DW_AT_name	("foo")
3137   //                 DW_AT_low_pc	(0x0000000000001000)
3138   //                 DW_AT_high_pc	(0x0000000000001050)
3139   //
3140   // 0x0000002a:     DW_TAG_inlined_subroutine
3141   //                   DW_AT_name	("inlineWithInvalidRange")
3142   //                   DW_AT_low_pc	(0x0000000000001100)
3143   //                   DW_AT_high_pc	(0x0000000000001200)
3144   //                   DW_AT_call_file	("/tmp/main.cpp")
3145   //                   DW_AT_call_line	(11)
3146   //
3147   // 0x00000047:     NULL
3148   //
3149   // 0x00000048:   NULL
3150 
3151   StringRef yamldata = R"(
3152   debug_str:
3153     - ''
3154     - '/tmp/main.cpp'
3155     - foo
3156     - inlineWithInvalidRange
3157   debug_abbrev:
3158     - ID:              0
3159       Table:
3160         - Code:            0x1
3161           Tag:             DW_TAG_compile_unit
3162           Children:        DW_CHILDREN_yes
3163           Attributes:
3164             - Attribute:       DW_AT_name
3165               Form:            DW_FORM_strp
3166             - Attribute:       DW_AT_language
3167               Form:            DW_FORM_udata
3168             - Attribute:       DW_AT_stmt_list
3169               Form:            DW_FORM_sec_offset
3170         - Code:            0x2
3171           Tag:             DW_TAG_subprogram
3172           Children:        DW_CHILDREN_yes
3173           Attributes:
3174             - Attribute:       DW_AT_name
3175               Form:            DW_FORM_strp
3176             - Attribute:       DW_AT_low_pc
3177               Form:            DW_FORM_addr
3178             - Attribute:       DW_AT_high_pc
3179               Form:            DW_FORM_addr
3180         - Code:            0x3
3181           Tag:             DW_TAG_inlined_subroutine
3182           Children:        DW_CHILDREN_no
3183           Attributes:
3184             - Attribute:       DW_AT_name
3185               Form:            DW_FORM_strp
3186             - Attribute:       DW_AT_low_pc
3187               Form:            DW_FORM_addr
3188             - Attribute:       DW_AT_high_pc
3189               Form:            DW_FORM_addr
3190             - Attribute:       DW_AT_call_file
3191               Form:            DW_FORM_data4
3192             - Attribute:       DW_AT_call_line
3193               Form:            DW_FORM_data4
3194   debug_info:
3195     - Length:          0x45
3196       Version:         4
3197       AbbrevTableID:   0
3198       AbbrOffset:      0x0
3199       AddrSize:        8
3200       Entries:
3201         - AbbrCode:        0x1
3202           Values:
3203             - Value:           0x1
3204             - Value:           0x2
3205             - Value:           0x0
3206         - AbbrCode:        0x2
3207           Values:
3208             - Value:           0xF
3209             - Value:           0x1000
3210             - Value:           0x1050
3211         - AbbrCode:        0x3
3212           Values:
3213             - Value:           0x13
3214             - Value:           0x1100
3215             - Value:           0x1200
3216             - Value:           0x1
3217             - Value:           0xB
3218         - AbbrCode:        0x0
3219         - AbbrCode:        0x0
3220   debug_line:
3221     - Length:          76
3222       Version:         2
3223       PrologueLength:  36
3224       MinInstLength:   1
3225       DefaultIsStmt:   1
3226       LineBase:        251
3227       LineRange:       14
3228       OpcodeBase:      13
3229       StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]
3230       IncludeDirs:
3231         - '/tmp'
3232       Files:
3233         - Name:            main.cpp
3234           DirIdx:          1
3235           ModTime:         0
3236           Length:          0
3237       Opcodes:
3238         - Opcode:          DW_LNS_extended_op
3239           ExtLen:          9
3240           SubOpcode:       DW_LNE_set_address
3241           Data:            4096
3242         - Opcode:          DW_LNS_advance_line
3243           SData:           9
3244           Data:            0
3245         - Opcode:          DW_LNS_copy
3246           Data:            0
3247         - Opcode:          DW_LNS_advance_pc
3248           Data:            16
3249         - Opcode:          DW_LNS_advance_line
3250           SData:           1
3251           Data:            0
3252         - Opcode:          DW_LNS_copy
3253           Data:            0
3254         - Opcode:          DW_LNS_advance_pc
3255           Data:            16
3256         - Opcode:          DW_LNS_advance_line
3257           SData:           1
3258           Data:            0
3259         - Opcode:          DW_LNS_copy
3260           Data:            0
3261         - Opcode:          DW_LNS_advance_pc
3262           Data:            16
3263         - Opcode:          DW_LNS_advance_line
3264           SData:           1
3265           Data:            0
3266         - Opcode:          DW_LNS_copy
3267           Data:            0
3268         - Opcode:          DW_LNS_advance_pc
3269           Data:            32
3270         - Opcode:          DW_LNS_extended_op
3271           ExtLen:          1
3272           SubOpcode:       DW_LNE_end_sequence
3273           Data:            0
3274   )";
3275   auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);
3276   ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());
3277   std::unique_ptr<DWARFContext> DwarfContext =
3278       DWARFContext::create(*ErrOrSections, 8);
3279   ASSERT_TRUE(DwarfContext.get() != nullptr);
3280   std::string errors;
3281   raw_string_ostream OS(errors);
3282   OutputAggregator OSAgg(&OS);
3283   GsymCreator GC;
3284   DwarfTransformer DT(*DwarfContext, GC);
3285   const uint32_t ThreadCount = 1;
3286   ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());
3287   ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());
3288   SmallString<512> Str;
3289   raw_svector_ostream OutStrm(Str);
3290   const auto ByteOrder = llvm::endianness::native;
3291   FileWriter FW(OutStrm, ByteOrder);
3292   ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());
3293   Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());
3294   ASSERT_THAT_EXPECTED(GR, Succeeded());
3295   // There should only be one function in our GSYM.
3296   EXPECT_EQ(GR->getNumAddresses(), 1u);
3297   auto ExpFI = GR->getFunctionInfo(0x1000);
3298   ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
3299   ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x1050));
3300   EXPECT_TRUE(ExpFI->OptLineTable.has_value());
3301   EXPECT_FALSE(ExpFI->Inline.has_value());
3302   StringRef FuncName = GR->getString(ExpFI->Name);
3303   EXPECT_EQ(FuncName, "foo");
3304   std::vector<std::string> ExpectedLogErrors = {
3305     "error: inlined function DIE at 0x0000002a has a range [0x0000000000001100"
3306     " - 0x0000000000001200) that isn't contained in any parent address ranges,"
3307     " this inline range will be removed.",
3308     "warning: DIE contains inline function information that has no valid "
3309     "ranges, removing inline information:",
3310   };
3311   // Make sure all expected errors are in the error stream for the two invalid
3312   // inlined functions that we removed due to invalid range scoping.
3313   for (const auto &Error: ExpectedLogErrors) {
3314     EXPECT_TRUE(OS.str().find(Error) != std::string::npos);
3315   }
3316 }
3317 
3318 TEST(GSYMTest, TestFinalizeForLineTables) {
3319   // This example has two compile units:
3320   // - one contains a function "foo" with line table entries and "bar" without
3321   // - one contains a function "bar" with line table entries and "foo" without
3322   // This test ensures that no matter what order information gets processed,
3323   // we want to make sure that we prioritize the entries with the most debug
3324   // info.
3325   //
3326   // The DWARF is the same for the functions, but the first compile unit has
3327   // lines entries for "foo" and the second one doesn't. And the first compile
3328   // unit has no line entries for "bar", but the second one does. We expect the
3329   // resulting gsym file to have a "foo" and "bar" that both have line entries.
3330   //
3331   // 0x0000000b: DW_TAG_compile_unit
3332   //               DW_AT_name	("/tmp/main.cpp")
3333   //               DW_AT_language	(DW_LANG_C)
3334   //               DW_AT_stmt_list	(0x00000000)
3335   //
3336   // 0x00000015:   DW_TAG_subprogram
3337   //                 DW_AT_name	("foo")
3338   //                 DW_AT_low_pc	(0x0000000000001000)
3339   //                 DW_AT_high_pc	(0x0000000000001050)
3340   //
3341   // 0x0000002a:   DW_TAG_subprogram
3342   //                 DW_AT_name	("bar")
3343   //                 DW_AT_low_pc	(0x0000000000002000)
3344   //                 DW_AT_high_pc	(0x0000000000002050)
3345   //
3346   // 0x0000003f:   NULL
3347   // 0x00000040: Compile Unit: length = 0x0000003c, format = DWARF32, version = 0x0004, abbr_offset = 0x0000, addr_size = 0x08 (next unit at 0x00000080)
3348   //
3349   // 0x0000004b: DW_TAG_compile_unit
3350   //               DW_AT_name	("/tmp/main.cpp")
3351   //               DW_AT_language	(DW_LANG_C)
3352   //               DW_AT_stmt_list	(0x00000043)
3353   //
3354   // 0x00000055:   DW_TAG_subprogram
3355   //                 DW_AT_name	("foo")
3356   //                 DW_AT_low_pc	(0x0000000000001000)
3357   //                 DW_AT_high_pc	(0x0000000000001050)
3358   //
3359   // 0x0000006a:   DW_TAG_subprogram
3360   //                 DW_AT_name	("bar")
3361   //                 DW_AT_low_pc	(0x0000000000002000)
3362   //                 DW_AT_high_pc	(0x0000000000002050)
3363   //
3364   // 0x0000007f:   NULL
3365 
3366   StringRef yamldata = R"(
3367   debug_str:
3368     - ''
3369     - '/tmp/main.cpp'
3370     - foo
3371     - bar
3372   debug_abbrev:
3373     - ID:              0
3374       Table:
3375         - Code:            0x1
3376           Tag:             DW_TAG_compile_unit
3377           Children:        DW_CHILDREN_yes
3378           Attributes:
3379             - Attribute:       DW_AT_name
3380               Form:            DW_FORM_strp
3381             - Attribute:       DW_AT_language
3382               Form:            DW_FORM_udata
3383             - Attribute:       DW_AT_stmt_list
3384               Form:            DW_FORM_sec_offset
3385         - Code:            0x2
3386           Tag:             DW_TAG_subprogram
3387           Children:        DW_CHILDREN_no
3388           Attributes:
3389             - Attribute:       DW_AT_name
3390               Form:            DW_FORM_strp
3391             - Attribute:       DW_AT_low_pc
3392               Form:            DW_FORM_addr
3393             - Attribute:       DW_AT_high_pc
3394               Form:            DW_FORM_addr
3395   debug_info:
3396     - Length:          0x3C
3397       Version:         4
3398       AbbrevTableID:   0
3399       AbbrOffset:      0x0
3400       AddrSize:        8
3401       Entries:
3402         - AbbrCode:        0x1
3403           Values:
3404             - Value:           0x1
3405             - Value:           0x2
3406             - Value:           0x0
3407         - AbbrCode:        0x2
3408           Values:
3409             - Value:           0xF
3410             - Value:           0x1000
3411             - Value:           0x1050
3412         - AbbrCode:        0x2
3413           Values:
3414             - Value:           0x13
3415             - Value:           0x2000
3416             - Value:           0x2050
3417         - AbbrCode:        0x0
3418     - Length:          0x3C
3419       Version:         4
3420       AbbrevTableID:   0
3421       AbbrOffset:      0x0
3422       AddrSize:        8
3423       Entries:
3424         - AbbrCode:        0x1
3425           Values:
3426             - Value:           0x1
3427             - Value:           0x2
3428             - Value:           0x43
3429         - AbbrCode:        0x2
3430           Values:
3431             - Value:           0xF
3432             - Value:           0x1000
3433             - Value:           0x1050
3434         - AbbrCode:        0x2
3435           Values:
3436             - Value:           0x13
3437             - Value:           0x2000
3438             - Value:           0x2050
3439         - AbbrCode:        0x0
3440   debug_line:
3441     - Length:          63
3442       Version:         2
3443       PrologueLength:  36
3444       MinInstLength:   1
3445       DefaultIsStmt:   1
3446       LineBase:        251
3447       LineRange:       14
3448       OpcodeBase:      13
3449       StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]
3450       IncludeDirs:
3451         - '/tmp'
3452       Files:
3453         - Name:            main.cpp
3454           DirIdx:          1
3455           ModTime:         0
3456           Length:          0
3457       Opcodes:
3458         - Opcode:          DW_LNS_extended_op
3459           ExtLen:          9
3460           SubOpcode:       DW_LNE_set_address
3461           Data:            4096
3462         - Opcode:          DW_LNS_advance_line
3463           SData:           9
3464           Data:            0
3465         - Opcode:          DW_LNS_copy
3466           Data:            0
3467         - Opcode:          DW_LNS_advance_pc
3468           Data:            80
3469         - Opcode:          DW_LNS_advance_line
3470           SData:           1
3471           Data:            0
3472         - Opcode:          DW_LNS_extended_op
3473           ExtLen:          1
3474           SubOpcode:       DW_LNE_end_sequence
3475           Data:            0
3476     - Length:          63
3477       Version:         2
3478       PrologueLength:  36
3479       MinInstLength:   1
3480       DefaultIsStmt:   1
3481       LineBase:        251
3482       LineRange:       14
3483       OpcodeBase:      13
3484       StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]
3485       IncludeDirs:
3486         - '/tmp'
3487       Files:
3488         - Name:            main.cpp
3489           DirIdx:          1
3490           ModTime:         0
3491           Length:          0
3492       Opcodes:
3493         - Opcode:          DW_LNS_extended_op
3494           ExtLen:          9
3495           SubOpcode:       DW_LNE_set_address
3496           Data:            8192
3497         - Opcode:          DW_LNS_advance_line
3498           SData:           19
3499           Data:            0
3500         - Opcode:          DW_LNS_copy
3501           Data:            0
3502         - Opcode:          DW_LNS_advance_pc
3503           Data:            80
3504         - Opcode:          DW_LNS_advance_line
3505           SData:           1
3506           Data:            0
3507         - Opcode:          DW_LNS_extended_op
3508           ExtLen:          1
3509           SubOpcode:       DW_LNE_end_sequence
3510           Data:            0
3511   )";
3512   auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);
3513   ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());
3514   std::unique_ptr<DWARFContext> DwarfContext =
3515       DWARFContext::create(*ErrOrSections, 8);
3516   ASSERT_TRUE(DwarfContext.get() != nullptr);
3517   std::string errors;
3518   raw_string_ostream OS(errors);
3519   OutputAggregator OSAgg(&OS);
3520   GsymCreator GC;
3521   DwarfTransformer DT(*DwarfContext, GC);
3522   const uint32_t ThreadCount = 1;
3523   ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());
3524   ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());
3525   SmallString<512> Str;
3526   raw_svector_ostream OutStrm(Str);
3527   const auto ByteOrder = llvm::endianness::native;
3528   FileWriter FW(OutStrm, ByteOrder);
3529   ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());
3530   Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());
3531   ASSERT_THAT_EXPECTED(GR, Succeeded());
3532   // There should only be two functions in our GSYM.
3533   EXPECT_EQ(GR->getNumAddresses(), 2u);
3534   // Verify "foo" is present and has a line table
3535   auto ExpFI = GR->getFunctionInfo(0x1000);
3536   ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
3537   ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x1050));
3538   EXPECT_TRUE(ExpFI->OptLineTable.has_value());
3539   EXPECT_FALSE(ExpFI->Inline.has_value());
3540   StringRef FuncName = GR->getString(ExpFI->Name);
3541   EXPECT_EQ(FuncName, "foo");
3542 
3543   // Verify "foo" is present and has a line table
3544   auto ExpFI2 = GR->getFunctionInfo(0x2000);
3545   ASSERT_THAT_EXPECTED(ExpFI2, Succeeded());
3546   ASSERT_EQ(ExpFI2->Range, AddressRange(0x2000, 0x2050));
3547   EXPECT_TRUE(ExpFI2->OptLineTable.has_value());
3548   EXPECT_FALSE(ExpFI2->Inline.has_value());
3549   StringRef FuncName2 = GR->getString(ExpFI2->Name);
3550   EXPECT_EQ(FuncName2, "bar");
3551 }
3552 
3553 
3554 TEST(GSYMTest, TestRangeWarnings) {
3555   // This example has a single compile unit that has a DW_TAG_subprogram that
3556   // has two discontiguous ranges. We will create two FunctionInfo objects for
3557   // each range in the function that only contains info for each range. We also
3558   // want to verify that we only emit errors and warnings for ranges that
3559   // aren't contained in any parent address ranges if this is true. Prior to
3560   // this fix we would create two FunctionInfo objects and as each one was
3561   // being created we would end up warning about all of the ranges that weren't
3562   // in the current FunctionInfo's range even though the DWARF was well formed.
3563   // Now we don't incorrectly emit errors when there are none.
3564   //
3565   // 0x0000000b: DW_TAG_compile_unit
3566   //               DW_AT_name	("/tmp/main.cpp")
3567   //               DW_AT_language	(DW_LANG_C)
3568   //               DW_AT_stmt_list	(0x00000000)
3569   //
3570   // 0x00000015:   DW_TAG_subprogram
3571   //                 DW_AT_name	("foo")
3572   //                 DW_AT_ranges	(0x00000000
3573   //                    [0x0000000000001000, 0x0000000000001050)
3574   //                    [0x0000000000002000, 0x0000000000002050))
3575   //
3576   // 0x0000001e:     DW_TAG_inlined_subroutine
3577   //                   DW_AT_name	("inline1")
3578   //                   DW_AT_ranges	(0x00000030
3579   //                      [0x0000000000001010, 0x0000000000001040)
3580   //                      [0x0000000000002010, 0x0000000000002040))
3581   //                   DW_AT_call_file	("/tmp/main.cpp")
3582   //                   DW_AT_call_line	(11)
3583   //
3584   // 0x0000002f:       DW_TAG_inlined_subroutine
3585   //                     DW_AT_name	("inline2")
3586   //                     DW_AT_ranges	(0x00000060
3587   //                        [0x0000000000001015, 0x0000000000001020)
3588   //                        [0x0000000000002015, 0x0000000000002020))
3589   //                     DW_AT_call_file	("/tmp/inline.h")
3590   //                     DW_AT_call_line	(21)
3591   //
3592   // 0x00000040:       NULL
3593   //
3594   // 0x00000041:     NULL
3595   //
3596   // 0x00000042:   NULL
3597 
3598   StringRef yamldata = R"(
3599   debug_str:
3600     - ''
3601     - '/tmp/main.cpp'
3602     - foo
3603     - inline1
3604     - inline2
3605   debug_abbrev:
3606     - ID:              0
3607       Table:
3608         - Code:            0x1
3609           Tag:             DW_TAG_compile_unit
3610           Children:        DW_CHILDREN_yes
3611           Attributes:
3612             - Attribute:       DW_AT_name
3613               Form:            DW_FORM_strp
3614             - Attribute:       DW_AT_language
3615               Form:            DW_FORM_udata
3616             - Attribute:       DW_AT_stmt_list
3617               Form:            DW_FORM_sec_offset
3618         - Code:            0x2
3619           Tag:             DW_TAG_subprogram
3620           Children:        DW_CHILDREN_yes
3621           Attributes:
3622             - Attribute:       DW_AT_name
3623               Form:            DW_FORM_strp
3624             - Attribute:       DW_AT_ranges
3625               Form:            DW_FORM_sec_offset
3626         - Code:            0x3
3627           Tag:             DW_TAG_inlined_subroutine
3628           Children:        DW_CHILDREN_yes
3629           Attributes:
3630             - Attribute:       DW_AT_name
3631               Form:            DW_FORM_strp
3632             - Attribute:       DW_AT_ranges
3633               Form:            DW_FORM_sec_offset
3634             - Attribute:       DW_AT_call_file
3635               Form:            DW_FORM_data4
3636             - Attribute:       DW_AT_call_line
3637               Form:            DW_FORM_data4
3638         - Code:            0x4
3639           Tag:             DW_TAG_inlined_subroutine
3640           Children:        DW_CHILDREN_no
3641           Attributes:
3642             - Attribute:       DW_AT_name
3643               Form:            DW_FORM_strp
3644             - Attribute:       DW_AT_ranges
3645               Form:            DW_FORM_sec_offset
3646             - Attribute:       DW_AT_call_file
3647               Form:            DW_FORM_data4
3648             - Attribute:       DW_AT_call_line
3649               Form:            DW_FORM_data4
3650   debug_ranges:
3651     - Offset:          0x0
3652       AddrSize:        0x8
3653       Entries:
3654         - LowOffset:       0x1000
3655           HighOffset:      0x1050
3656         - LowOffset:       0x2000
3657           HighOffset:      0x2050
3658     - Offset:          0x30
3659       AddrSize:        0x8
3660       Entries:
3661         - LowOffset:       0x1010
3662           HighOffset:      0x1040
3663         - LowOffset:       0x2010
3664           HighOffset:      0x2040
3665     - Offset:          0x60
3666       AddrSize:        0x8
3667       Entries:
3668         - LowOffset:       0x1015
3669           HighOffset:      0x1020
3670         - LowOffset:       0x2015
3671           HighOffset:      0x2020
3672   debug_info:
3673     - Length:          0x3F
3674       Version:         4
3675       AbbrevTableID:   0
3676       AbbrOffset:      0x0
3677       AddrSize:        8
3678       Entries:
3679         - AbbrCode:        0x1
3680           Values:
3681             - Value:           0x1
3682             - Value:           0x2
3683             - Value:           0x0
3684         - AbbrCode:        0x2
3685           Values:
3686             - Value:           0xF
3687             - Value:           0x0
3688         - AbbrCode:        0x3
3689           Values:
3690             - Value:           0x13
3691             - Value:           0x30
3692             - Value:           0x1
3693             - Value:           0xB
3694         - AbbrCode:        0x4
3695           Values:
3696             - Value:           0x1B
3697             - Value:           0x60
3698             - Value:           0x2
3699             - Value:           0x15
3700         - AbbrCode:        0x0
3701         - AbbrCode:        0x0
3702         - AbbrCode:        0x0
3703   debug_line:
3704     - Length:          120
3705       Version:         2
3706       PrologueLength:  48
3707       MinInstLength:   1
3708       DefaultIsStmt:   1
3709       LineBase:        251
3710       LineRange:       14
3711       OpcodeBase:      13
3712       StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]
3713       IncludeDirs:
3714         - '/tmp'
3715       Files:
3716         - Name:            main.cpp
3717           DirIdx:          1
3718           ModTime:         0
3719           Length:          0
3720         - Name:            inline.h
3721           DirIdx:          1
3722           ModTime:         0
3723           Length:          0
3724       Opcodes:
3725         - Opcode:          DW_LNS_extended_op
3726           ExtLen:          9
3727           SubOpcode:       DW_LNE_set_address
3728           Data:            4096
3729         - Opcode:          DW_LNS_advance_line
3730           SData:           9
3731           Data:            0
3732         - Opcode:          DW_LNS_copy
3733           Data:            0
3734         - Opcode:          DW_LNS_advance_pc
3735           Data:            16
3736         - Opcode:          DW_LNS_set_file
3737           Data:            2
3738         - Opcode:          DW_LNS_advance_line
3739           SData:           10
3740           Data:            0
3741         - Opcode:          DW_LNS_copy
3742           Data:            0
3743         - Opcode:          DW_LNS_advance_pc
3744           Data:            16
3745         - Opcode:          DW_LNS_advance_line
3746           SData:           1
3747           Data:            0
3748         - Opcode:          DW_LNS_copy
3749           Data:            0
3750         - Opcode:          DW_LNS_advance_pc
3751           Data:            48
3752         - Opcode:          DW_LNS_set_file
3753           Data:            1
3754         - Opcode:          DW_LNS_advance_line
3755           SData:           -10
3756           Data:            0
3757         - Opcode:          DW_LNS_extended_op
3758           ExtLen:          1
3759           SubOpcode:       DW_LNE_end_sequence
3760           Data:            0
3761         - Opcode:          DW_LNS_extended_op
3762           ExtLen:          9
3763           SubOpcode:       DW_LNE_set_address
3764           Data:            8192
3765         - Opcode:          DW_LNS_advance_line
3766           SData:           19
3767           Data:            0
3768         - Opcode:          DW_LNS_copy
3769           Data:            0
3770         - Opcode:          DW_LNS_advance_pc
3771           Data:            16
3772         - Opcode:          DW_LNS_set_file
3773           Data:            2
3774         - Opcode:          DW_LNS_copy
3775           Data:            0
3776         - Opcode:          DW_LNS_advance_pc
3777           Data:            16
3778         - Opcode:          DW_LNS_advance_line
3779           SData:           1
3780           Data:            0
3781         - Opcode:          DW_LNS_copy
3782           Data:            0
3783         - Opcode:          DW_LNS_advance_pc
3784           Data:            48
3785         - Opcode:          DW_LNS_set_file
3786           Data:            1
3787         - Opcode:          DW_LNS_extended_op
3788           ExtLen:          1
3789           SubOpcode:       DW_LNE_end_sequence
3790           Data:            0
3791   )";
3792   auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);
3793   ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());
3794   std::unique_ptr<DWARFContext> DwarfContext =
3795       DWARFContext::create(*ErrOrSections, 8);
3796   ASSERT_TRUE(DwarfContext.get() != nullptr);
3797   std::string errors;
3798   raw_string_ostream OS(errors);
3799   OutputAggregator OSAgg(&OS);
3800   GsymCreator GC;
3801   DwarfTransformer DT(*DwarfContext, GC);
3802   const uint32_t ThreadCount = 1;
3803   ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());
3804   ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());
3805   SmallString<512> Str;
3806   raw_svector_ostream OutStrm(Str);
3807   const auto ByteOrder = llvm::endianness::native;
3808   FileWriter FW(OutStrm, ByteOrder);
3809   ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());
3810   Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());
3811   ASSERT_THAT_EXPECTED(GR, Succeeded());
3812   // There should be two functions in our GSYM.
3813   EXPECT_EQ(GR->getNumAddresses(), 2u);
3814   // Verify "foo" is present and has a line table
3815   auto ExpFI = GR->getFunctionInfo(0x1000);
3816   ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
3817   ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x1050));
3818   EXPECT_TRUE(ExpFI->OptLineTable.has_value());
3819   EXPECT_TRUE(ExpFI->Inline.has_value());
3820   StringRef FuncName = GR->getString(ExpFI->Name);
3821   EXPECT_EQ(FuncName, "foo");
3822 
3823   // Verify "foo" is present and has a line table
3824   auto ExpFI2 = GR->getFunctionInfo(0x2000);
3825   ASSERT_THAT_EXPECTED(ExpFI2, Succeeded());
3826   ASSERT_EQ(ExpFI2->Range, AddressRange(0x2000, 0x2050));
3827   EXPECT_TRUE(ExpFI2->OptLineTable.has_value());
3828   EXPECT_TRUE(ExpFI2->Inline.has_value());
3829   StringRef FuncName2 = GR->getString(ExpFI2->Name);
3830   EXPECT_EQ(FuncName2, "foo");
3831 
3832   // Make sure we don't see spurious errors in the output:
3833   EXPECT_TRUE(errors.find("error:") == std::string::npos);
3834 }
3835 
3836 TEST(GSYMTest, TestEmptyRangeWarnings) {
3837   // This example has a single compile unit that has a DW_TAG_subprogram that
3838   // has a function that contains an inlined function that has an empty range.
3839   // We want to make sure that if we run into only empty inline functions
3840   // inside of a real function, that we don't end up with inline information
3841   // in the GSYM and we don't warn about the inline function's range not being
3842   // contined in the parent ranges since it is ok for inline functions to be
3843   // elided.
3844   //
3845   // 0x0000000b: DW_TAG_compile_unit
3846   //               DW_AT_name	("/tmp/main.cpp")
3847   //               DW_AT_language	(DW_LANG_C)
3848   //               DW_AT_stmt_list	(0x00000000)
3849   //
3850   // 0x00000015:   DW_TAG_subprogram
3851   //                 DW_AT_name	("foo")
3852   //                 DW_AT_low_pc	(0x0000000000001000)
3853   //                 DW_AT_high_pc	(0x0000000000001050)
3854   //
3855   // 0x0000002a:     DW_TAG_inlined_subroutine
3856   //                   DW_AT_name	("inline1")
3857   //                   DW_AT_low_pc	(0x0000000000001010)
3858   //                   DW_AT_high_pc	(0x0000000000001010)
3859   //                   DW_AT_call_file	("/tmp/main.cpp")
3860   //                   DW_AT_call_line	(11)
3861   //
3862   // 0x00000047:     NULL
3863   //
3864   // 0x00000048:   NULL
3865 
3866   StringRef yamldata = R"(
3867   debug_str:
3868     - ''
3869     - '/tmp/main.cpp'
3870     - foo
3871     - inline1
3872   debug_abbrev:
3873     - ID:              0
3874       Table:
3875         - Code:            0x1
3876           Tag:             DW_TAG_compile_unit
3877           Children:        DW_CHILDREN_yes
3878           Attributes:
3879             - Attribute:       DW_AT_name
3880               Form:            DW_FORM_strp
3881             - Attribute:       DW_AT_language
3882               Form:            DW_FORM_udata
3883             - Attribute:       DW_AT_stmt_list
3884               Form:            DW_FORM_sec_offset
3885         - Code:            0x2
3886           Tag:             DW_TAG_subprogram
3887           Children:        DW_CHILDREN_yes
3888           Attributes:
3889             - Attribute:       DW_AT_name
3890               Form:            DW_FORM_strp
3891             - Attribute:       DW_AT_low_pc
3892               Form:            DW_FORM_addr
3893             - Attribute:       DW_AT_high_pc
3894               Form:            DW_FORM_addr
3895         - Code:            0x3
3896           Tag:             DW_TAG_inlined_subroutine
3897           Children:        DW_CHILDREN_no
3898           Attributes:
3899             - Attribute:       DW_AT_name
3900               Form:            DW_FORM_strp
3901             - Attribute:       DW_AT_low_pc
3902               Form:            DW_FORM_addr
3903             - Attribute:       DW_AT_high_pc
3904               Form:            DW_FORM_addr
3905             - Attribute:       DW_AT_call_file
3906               Form:            DW_FORM_data4
3907             - Attribute:       DW_AT_call_line
3908               Form:            DW_FORM_data4
3909   debug_info:
3910     - Length:          0x45
3911       Version:         4
3912       AbbrevTableID:   0
3913       AbbrOffset:      0x0
3914       AddrSize:        8
3915       Entries:
3916         - AbbrCode:        0x1
3917           Values:
3918             - Value:           0x1
3919             - Value:           0x2
3920             - Value:           0x0
3921         - AbbrCode:        0x2
3922           Values:
3923             - Value:           0xF
3924             - Value:           0x1000
3925             - Value:           0x1050
3926         - AbbrCode:        0x3
3927           Values:
3928             - Value:           0x13
3929             - Value:           0x1010
3930             - Value:           0x1010
3931             - Value:           0x1
3932             - Value:           0xB
3933         - AbbrCode:        0x0
3934         - AbbrCode:        0x0
3935   debug_line:
3936     - Length:          89
3937       Version:         2
3938       PrologueLength:  48
3939       MinInstLength:   1
3940       DefaultIsStmt:   1
3941       LineBase:        251
3942       LineRange:       14
3943       OpcodeBase:      13
3944       StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]
3945       IncludeDirs:
3946         - '/tmp'
3947       Files:
3948         - Name:            main.cpp
3949           DirIdx:          1
3950           ModTime:         0
3951           Length:          0
3952         - Name:            inline.h
3953           DirIdx:          1
3954           ModTime:         0
3955           Length:          0
3956       Opcodes:
3957         - Opcode:          DW_LNS_extended_op
3958           ExtLen:          9
3959           SubOpcode:       DW_LNE_set_address
3960           Data:            4096
3961         - Opcode:          DW_LNS_advance_line
3962           SData:           9
3963           Data:            0
3964         - Opcode:          DW_LNS_copy
3965           Data:            0
3966         - Opcode:          DW_LNS_advance_pc
3967           Data:            16
3968         - Opcode:          DW_LNS_set_file
3969           Data:            2
3970         - Opcode:          DW_LNS_advance_line
3971           SData:           10
3972           Data:            0
3973         - Opcode:          DW_LNS_copy
3974           Data:            0
3975         - Opcode:          DW_LNS_advance_pc
3976           Data:            16
3977         - Opcode:          DW_LNS_advance_line
3978           SData:           1
3979           Data:            0
3980         - Opcode:          DW_LNS_copy
3981           Data:            0
3982         - Opcode:          DW_LNS_advance_pc
3983           Data:            48
3984         - Opcode:          DW_LNS_set_file
3985           Data:            1
3986         - Opcode:          DW_LNS_advance_line
3987           SData:           -10
3988           Data:            0
3989         - Opcode:          DW_LNS_extended_op
3990           ExtLen:          1
3991           SubOpcode:       DW_LNE_end_sequence
3992           Data:            0
3993   )";
3994   auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);
3995   ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());
3996   std::unique_ptr<DWARFContext> DwarfContext =
3997       DWARFContext::create(*ErrOrSections, 8);
3998   ASSERT_TRUE(DwarfContext.get() != nullptr);
3999   std::string errors;
4000   raw_string_ostream OS(errors);
4001   OutputAggregator OSAgg(&OS);
4002   GsymCreator GC;
4003   DwarfTransformer DT(*DwarfContext, GC);
4004   const uint32_t ThreadCount = 1;
4005   ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());
4006   ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());
4007   SmallString<512> Str;
4008   raw_svector_ostream OutStrm(Str);
4009   const auto ByteOrder = llvm::endianness::native;
4010   FileWriter FW(OutStrm, ByteOrder);
4011   ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());
4012   Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());
4013   ASSERT_THAT_EXPECTED(GR, Succeeded());
4014   // There should be one function in our GSYM.
4015   EXPECT_EQ(GR->getNumAddresses(), 1u);
4016   // Verify "foo" is present and has a line table and no inline info.
4017   auto ExpFI = GR->getFunctionInfo(0x1000);
4018   ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
4019   ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x1050));
4020   EXPECT_TRUE(ExpFI->OptLineTable.has_value());
4021   EXPECT_FALSE(ExpFI->Inline.has_value());
4022   StringRef FuncName = GR->getString(ExpFI->Name);
4023   EXPECT_EQ(FuncName, "foo");
4024 
4025   // Make sure we don't see spurious errors in the output:
4026   EXPECT_TRUE(errors.find("error:") == std::string::npos);
4027 }
4028 
4029 
4030 TEST(GSYMTest, TestEmptyLinkageName) {
4031   // This example has a single compile unit that has a DW_TAG_subprogram that
4032   // has a function that has an empty linkage name and a valid normal name.
4033   // Previously this would cause an encoding error:
4034   //
4035   // DWARF conversion failed: attempted to encode invalid FunctionInfo object
4036   //
4037   // This was because we would get a valid but empty linkage name and we would
4038   // try to use this in the GSYM FunctionInfo and that would cause the error
4039   // as the name was empty.
4040   //
4041   // 0x0000000b: DW_TAG_compile_unit
4042   //               DW_AT_name        ("/tmp/main.cpp")
4043   //               DW_AT_language    (DW_LANG_C)
4044   //               DW_AT_stmt_list   (0x00000000)
4045   //
4046   // 0x00000015:   DW_TAG_subprogram
4047   //                 DW_AT_name      ("foo")
4048   //                 DW_AT_linkage_name      ("")
4049   //                 DW_AT_low_pc    (0x0000000000001000)
4050   //                 DW_AT_high_pc   (0x0000000000001050)
4051   //
4052   // 0x0000002e:   NULL
4053 
4054 
4055   StringRef yamldata = R"(
4056   debug_str:
4057     - ''
4058     - '/tmp/main.cpp'
4059     - foo
4060     - ''
4061   debug_abbrev:
4062     - ID:              0
4063       Table:
4064         - Code:            0x1
4065           Tag:             DW_TAG_compile_unit
4066           Children:        DW_CHILDREN_yes
4067           Attributes:
4068             - Attribute:       DW_AT_name
4069               Form:            DW_FORM_strp
4070             - Attribute:       DW_AT_language
4071               Form:            DW_FORM_udata
4072             - Attribute:       DW_AT_stmt_list
4073               Form:            DW_FORM_sec_offset
4074         - Code:            0x2
4075           Tag:             DW_TAG_subprogram
4076           Children:        DW_CHILDREN_no
4077           Attributes:
4078             - Attribute:       DW_AT_name
4079               Form:            DW_FORM_strp
4080             - Attribute:       DW_AT_linkage_name
4081               Form:            DW_FORM_strp
4082             - Attribute:       DW_AT_low_pc
4083               Form:            DW_FORM_addr
4084             - Attribute:       DW_AT_high_pc
4085               Form:            DW_FORM_addr
4086   debug_info:
4087     - Length:          0x2B
4088       Version:         4
4089       AbbrevTableID:   0
4090       AbbrOffset:      0x0
4091       AddrSize:        8
4092       Entries:
4093         - AbbrCode:        0x1
4094           Values:
4095             - Value:           0x1
4096             - Value:           0x2
4097             - Value:           0x0
4098         - AbbrCode:        0x2
4099           Values:
4100             - Value:           0xF
4101             - Value:           0x13
4102             - Value:           0x1000
4103             - Value:           0x1050
4104         - AbbrCode:        0x0
4105   debug_line:
4106     - Length:          68
4107       Version:         2
4108       PrologueLength:  36
4109       MinInstLength:   1
4110       DefaultIsStmt:   1
4111       LineBase:        251
4112       LineRange:       14
4113       OpcodeBase:      13
4114       StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]
4115       IncludeDirs:
4116         - '/tmp'
4117       Files:
4118         - Name:            main.cpp
4119           DirIdx:          1
4120           ModTime:         0
4121           Length:          0
4122       Opcodes:
4123         - Opcode:          DW_LNS_extended_op
4124           ExtLen:          9
4125           SubOpcode:       DW_LNE_set_address
4126           Data:            4096
4127         - Opcode:          DW_LNS_advance_line
4128           SData:           9
4129           Data:            0
4130         - Opcode:          DW_LNS_copy
4131           Data:            0
4132         - Opcode:          DW_LNS_advance_pc
4133           Data:            256
4134         - Opcode:          DW_LNS_advance_line
4135           SData:           1
4136           Data:            0
4137         - Opcode:          DW_LNS_copy
4138           Data:            0
4139         - Opcode:          DW_LNS_advance_pc
4140           Data:            256
4141         - Opcode:          DW_LNS_extended_op
4142           ExtLen:          1
4143           SubOpcode:       DW_LNE_end_sequence
4144           Data:            0
4145   )";
4146   auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);
4147   ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());
4148   std::unique_ptr<DWARFContext> DwarfContext =
4149       DWARFContext::create(*ErrOrSections, 8);
4150   ASSERT_TRUE(DwarfContext.get() != nullptr);
4151   std::string errors;
4152   raw_string_ostream OS(errors);
4153   OutputAggregator OSAgg(&OS);
4154   GsymCreator GC;
4155   DwarfTransformer DT(*DwarfContext, GC);
4156   const uint32_t ThreadCount = 1;
4157   ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());
4158   ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());
4159   SmallString<512> Str;
4160   raw_svector_ostream OutStrm(Str);
4161   const auto ByteOrder = llvm::endianness::native;
4162   FileWriter FW(OutStrm, ByteOrder);
4163   ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());
4164   Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());
4165   ASSERT_THAT_EXPECTED(GR, Succeeded());
4166   // There should be one function in our GSYM.
4167   EXPECT_EQ(GR->getNumAddresses(), 1u);
4168   // Verify "foo" is present and has a line table and no inline info.
4169   auto ExpFI = GR->getFunctionInfo(0x1000);
4170   ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
4171   ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x1050));
4172   EXPECT_TRUE(ExpFI->OptLineTable.has_value());
4173   EXPECT_FALSE(ExpFI->Inline.has_value());
4174   StringRef FuncName = GR->getString(ExpFI->Name);
4175   EXPECT_EQ(FuncName, "foo");
4176 
4177   // Make sure we don't see spurious errors in the output:
4178   EXPECT_TRUE(errors.find("error:") == std::string::npos);
4179 }
4180 
4181 TEST(GSYMTest, TestLineTablesWithEmptyRanges) {
4182   // Test that lookups find the right line table entry when there are multiple
4183   // line entries with the same address. When we have multiple line table
4184   // entries with the same address, we need to pick the last one in the line
4185   // table. We do this because a line entry's start address in the defined by
4186   // the line table entry's address and the size is determined by the
4187   // subtracting the next line table's address. If the current line table
4188   // entry's address is the same as the next one, then there is no code
4189   // assiciated with the current line table entry and it should be ignored.
4190   //
4191   // 0x0000000b: DW_TAG_compile_unit
4192   //               DW_AT_name        ("/tmp/main.cpp")
4193   //               DW_AT_language    (DW_LANG_C)
4194   //               DW_AT_stmt_list   (0x00000000)
4195   //
4196   // 0x00000015:   DW_TAG_subprogram
4197   //                 DW_AT_name      ("foo")
4198   //                 DW_AT_low_pc    (0x0000000000001000)
4199   //                 DW_AT_high_pc   (0x0000000000001050)
4200   //
4201   // 0x0000002a:   NULL
4202   //
4203   // The line table has a duplicate entry at 0x1010:
4204   //
4205   // Address    Line   Column File   ISA Discriminator Flags
4206   // ---------- ------ ------ ------ --- ------------- -------------
4207   // 0x00001000     10      0      1   0             0  is_stmt
4208   // 0x00001010     11      0      1   0             0  is_stmt
4209   // 0x00001010     12      0      1   0             0  is_stmt
4210   // 0x00001050     13      0      1   0             0  is_stmt end_sequence
4211 
4212   StringRef yamldata = R"(
4213   debug_str:
4214     - ''
4215     - '/tmp/main.cpp'
4216     - foo
4217   debug_abbrev:
4218     - ID:              0
4219       Table:
4220         - Code:            0x1
4221           Tag:             DW_TAG_compile_unit
4222           Children:        DW_CHILDREN_yes
4223           Attributes:
4224             - Attribute:       DW_AT_name
4225               Form:            DW_FORM_strp
4226             - Attribute:       DW_AT_language
4227               Form:            DW_FORM_udata
4228             - Attribute:       DW_AT_stmt_list
4229               Form:            DW_FORM_sec_offset
4230         - Code:            0x2
4231           Tag:             DW_TAG_subprogram
4232           Children:        DW_CHILDREN_no
4233           Attributes:
4234             - Attribute:       DW_AT_name
4235               Form:            DW_FORM_strp
4236             - Attribute:       DW_AT_low_pc
4237               Form:            DW_FORM_addr
4238             - Attribute:       DW_AT_high_pc
4239               Form:            DW_FORM_addr
4240   debug_info:
4241     - Length:          0x27
4242       Version:         4
4243       AbbrevTableID:   0
4244       AbbrOffset:      0x0
4245       AddrSize:        8
4246       Entries:
4247         - AbbrCode:        0x1
4248           Values:
4249             - Value:           0x1
4250             - Value:           0x2
4251             - Value:           0x0
4252         - AbbrCode:        0x2
4253           Values:
4254             - Value:           0xF
4255             - Value:           0x1000
4256             - Value:           0x1050
4257         - AbbrCode:        0x0
4258   debug_line:
4259     - Length:          71
4260       Version:         2
4261       PrologueLength:  36
4262       MinInstLength:   1
4263       DefaultIsStmt:   1
4264       LineBase:        251
4265       LineRange:       14
4266       OpcodeBase:      13
4267       StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]
4268       IncludeDirs:
4269         - '/tmp'
4270       Files:
4271         - Name:            main.cpp
4272           DirIdx:          1
4273           ModTime:         0
4274           Length:          0
4275       Opcodes:
4276         - Opcode:          DW_LNS_extended_op
4277           ExtLen:          9
4278           SubOpcode:       DW_LNE_set_address
4279           Data:            4096
4280         - Opcode:          DW_LNS_advance_line
4281           SData:           9
4282           Data:            0
4283         - Opcode:          DW_LNS_copy
4284           Data:            0
4285         - Opcode:          DW_LNS_advance_pc
4286           Data:            16
4287         - Opcode:          DW_LNS_advance_line
4288           SData:           1
4289           Data:            0
4290         - Opcode:          DW_LNS_copy
4291           Data:            0
4292         - Opcode:          DW_LNS_advance_line
4293           SData:           1
4294           Data:            0
4295         - Opcode:          DW_LNS_copy
4296           Data:            0
4297         - Opcode:          DW_LNS_advance_pc
4298           Data:            64
4299         - Opcode:          DW_LNS_advance_line
4300           SData:           1
4301           Data:            0
4302         - Opcode:          DW_LNS_extended_op
4303           ExtLen:          1
4304           SubOpcode:       DW_LNE_end_sequence
4305           Data:            0
4306   )";
4307   auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);
4308   ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());
4309   std::unique_ptr<DWARFContext> DwarfContext =
4310       DWARFContext::create(*ErrOrSections, 8);
4311   ASSERT_TRUE(DwarfContext.get() != nullptr);
4312   std::string errors;
4313   raw_string_ostream OS(errors);
4314   OutputAggregator OSAgg(&OS);
4315   GsymCreator GC;
4316   DwarfTransformer DT(*DwarfContext, GC);
4317   const uint32_t ThreadCount = 1;
4318   ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());
4319   ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());
4320   SmallString<512> Str;
4321   raw_svector_ostream OutStrm(Str);
4322   const auto ByteOrder = llvm::endianness::native;
4323   FileWriter FW(OutStrm, ByteOrder);
4324   ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());
4325   Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());
4326   ASSERT_THAT_EXPECTED(GR, Succeeded());
4327   // There should be one function in our GSYM.
4328   EXPECT_EQ(GR->getNumAddresses(), 1u);
4329   // Verify "foo" is present and has a line table and no inline info.
4330   auto ExpFI = GR->getFunctionInfo(0x1000);
4331   ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
4332   ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x1050));
4333   EXPECT_TRUE(ExpFI->OptLineTable.has_value());
4334   EXPECT_FALSE(ExpFI->Inline.has_value());
4335   StringRef FuncName = GR->getString(ExpFI->Name);
4336   EXPECT_EQ(FuncName, "foo");
4337 
4338   // Make sure we don't see spurious errors in the output:
4339   EXPECT_TRUE(errors.find("error:") == std::string::npos);
4340 
4341   // Make sure that when we lookup address 0x1010, that we get the entry that
4342   // matches line 12, the second line entry that also has the address of
4343   // 0x1010.
4344   auto LR = GR->lookup(0x1010);
4345   ASSERT_THAT_EXPECTED(LR, Succeeded());
4346   SourceLocation src_loc = {"foo", "/tmp", "main.cpp", 12, 16};
4347   EXPECT_THAT(LR->Locations, testing::ElementsAre(src_loc));
4348 }
4349 
4350 TEST(GSYMTest, TestHandlingOfInvalidFileIndexes) {
4351   // Test that llvm-gsymutil can handle invalid file indexes in the following
4352   // cases:
4353   //  - In line entries in the line table
4354   //  - When parsing inline entries that have a DW_AT_call_file
4355   //  - When parsing function dies with no line table entries and it tries to
4356   //    use the DW_AT_decl_file
4357   //
4358   //
4359   // 0x0000000b: DW_TAG_compile_unit
4360   //               DW_AT_name        ("/tmp/main.cpp")
4361   //               DW_AT_language    (DW_LANG_C)
4362   //               DW_AT_stmt_list   (0x00000000)
4363   //
4364   // 0x00000015:   DW_TAG_subprogram
4365   //                 DW_AT_name      ("foo")
4366   //                 DW_AT_low_pc    (0x0000000000001000)
4367   //                 DW_AT_high_pc   (0x0000000000001050)
4368   //
4369   // 0x0000002a:     DW_TAG_inlined_subroutine
4370   //                   DW_AT_name    ("inline_with_invalid_call_file")
4371   //                   DW_AT_low_pc  (0x0000000000001010)
4372   //                   DW_AT_high_pc (0x0000000000001020)
4373   //                   DW_AT_call_file       (0x0000000a)
4374   //                   DW_AT_call_line       (11)
4375   //
4376   // 0x00000047:       DW_TAG_inlined_subroutine
4377   //                     DW_AT_name
4378   //                     ("inline_inside_parent_with_invalid_call_file")
4379   //                     DW_AT_low_pc        (0x0000000000001010)
4380   //                     DW_AT_high_pc       (0x0000000000001015)
4381   //                     DW_AT_call_file     ("/tmp/main.cpp")
4382   //                     DW_AT_call_line     (12)
4383   //
4384   // 0x00000064:       NULL
4385   //
4386   // 0x00000065:     DW_TAG_inlined_subroutine
4387   //                   DW_AT_name    ("inline_with_valid_call_file")
4388   //                   DW_AT_low_pc  (0x0000000000001020)
4389   //                   DW_AT_high_pc (0x0000000000001030)
4390   //                   DW_AT_call_file       ("/tmp/main.cpp")
4391   //                   DW_AT_call_line       (13)
4392   //
4393   // 0x00000082:       DW_TAG_inlined_subroutine
4394   //                     DW_AT_name
4395   //                     ("inline_inside_parent_with_valid_call_file")
4396   //                     DW_AT_low_pc        (0x0000000000001020)
4397   //                     DW_AT_high_pc       (0x0000000000001025)
4398   //                     DW_AT_call_file     ("/tmp/main.cpp")
4399   //                     DW_AT_call_line     (14)
4400   //
4401   // 0x0000009f:       NULL
4402   //
4403   // 0x000000a0:     NULL
4404   //
4405   // 0x000000a1:   DW_TAG_subprogram
4406   //                 DW_AT_name      ("func_with_valid_decl_file")
4407   //                 DW_AT_decl_file ("/tmp/main.cpp")
4408   //                 DW_AT_decl_line (20)
4409   //                 DW_AT_low_pc    (0x0000000000002000)
4410   //                 DW_AT_high_pc   (0x0000000000002050)
4411   //
4412   // 0x000000b8:   DW_TAG_subprogram
4413   //                 DW_AT_name      ("func_with_invalid_decl_file")
4414   //                 DW_AT_decl_file (0x0a)
4415   //                 DW_AT_decl_line (20)
4416   //                 DW_AT_low_pc    (0x0000000000003000)
4417   //                 DW_AT_high_pc   (0x0000000000003050)
4418   //
4419   // 0x000000cf:   NULL
4420   //
4421   // The table looks has an entry at address 0x0000000000001010 that has an
4422   // invalid file index that needs to be removed.
4423   //
4424   // Address            Line   Column File   ISA Discriminator Flags
4425   // ---------- ------ ------ ------ --- ------------- -------------
4426   // 0x00001000     10      0      1   0             0  is_stmt
4427   // 0x00001010     11      0     10   0             0  is_stmt
4428   // 0x00001020     11      0      1   0             0  is_stmt
4429   // 0x00001030     12      0      1   0             0  is_stmt
4430   // 0x00001050     12      0      1   0             0  is_stmt end_sequence
4431 
4432   StringRef yamldata = R"(
4433   debug_str:
4434     - ''
4435     - '/tmp/main.cpp'
4436     - foo
4437     - inline_with_invalid_call_file
4438     - inline_inside_parent_with_invalid_call_file
4439     - inline_with_valid_call_file
4440     - inline_inside_parent_with_valid_call_file
4441     - func_with_valid_decl_file
4442     - func_with_invalid_decl_file
4443   debug_abbrev:
4444     - ID:              0
4445       Table:
4446         - Code:            0x1
4447           Tag:             DW_TAG_compile_unit
4448           Children:        DW_CHILDREN_yes
4449           Attributes:
4450             - Attribute:       DW_AT_name
4451               Form:            DW_FORM_strp
4452             - Attribute:       DW_AT_language
4453               Form:            DW_FORM_udata
4454             - Attribute:       DW_AT_stmt_list
4455               Form:            DW_FORM_sec_offset
4456         - Code:            0x2
4457           Tag:             DW_TAG_subprogram
4458           Children:        DW_CHILDREN_yes
4459           Attributes:
4460             - Attribute:       DW_AT_name
4461               Form:            DW_FORM_strp
4462             - Attribute:       DW_AT_low_pc
4463               Form:            DW_FORM_addr
4464             - Attribute:       DW_AT_high_pc
4465               Form:            DW_FORM_addr
4466         - Code:            0x3
4467           Tag:             DW_TAG_inlined_subroutine
4468           Children:        DW_CHILDREN_yes
4469           Attributes:
4470             - Attribute:       DW_AT_name
4471               Form:            DW_FORM_strp
4472             - Attribute:       DW_AT_low_pc
4473               Form:            DW_FORM_addr
4474             - Attribute:       DW_AT_high_pc
4475               Form:            DW_FORM_addr
4476             - Attribute:       DW_AT_call_file
4477               Form:            DW_FORM_data4
4478             - Attribute:       DW_AT_call_line
4479               Form:            DW_FORM_data4
4480         - Code:            0x4
4481           Tag:             DW_TAG_inlined_subroutine
4482           Children:        DW_CHILDREN_no
4483           Attributes:
4484             - Attribute:       DW_AT_name
4485               Form:            DW_FORM_strp
4486             - Attribute:       DW_AT_low_pc
4487               Form:            DW_FORM_addr
4488             - Attribute:       DW_AT_high_pc
4489               Form:            DW_FORM_addr
4490             - Attribute:       DW_AT_call_file
4491               Form:            DW_FORM_data4
4492             - Attribute:       DW_AT_call_line
4493               Form:            DW_FORM_data4
4494         - Code:            0x5
4495           Tag:             DW_TAG_subprogram
4496           Children:        DW_CHILDREN_no
4497           Attributes:
4498             - Attribute:       DW_AT_name
4499               Form:            DW_FORM_strp
4500             - Attribute:       DW_AT_decl_file
4501               Form:            DW_FORM_data1
4502             - Attribute:       DW_AT_decl_line
4503               Form:            DW_FORM_data1
4504             - Attribute:       DW_AT_low_pc
4505               Form:            DW_FORM_addr
4506             - Attribute:       DW_AT_high_pc
4507               Form:            DW_FORM_addr
4508   debug_info:
4509     - Length:          0xCC
4510       Version:         4
4511       AbbrevTableID:   0
4512       AbbrOffset:      0x0
4513       AddrSize:        8
4514       Entries:
4515         - AbbrCode:        0x1
4516           Values:
4517             - Value:           0x1
4518             - Value:           0x2
4519             - Value:           0x0
4520         - AbbrCode:        0x2
4521           Values:
4522             - Value:           0xF
4523             - Value:           0x1000
4524             - Value:           0x1050
4525         - AbbrCode:        0x3
4526           Values:
4527             - Value:           0x13
4528             - Value:           0x1010
4529             - Value:           0x1020
4530             - Value:           0xA
4531             - Value:           0xB
4532         - AbbrCode:        0x4
4533           Values:
4534             - Value:           0x31
4535             - Value:           0x1010
4536             - Value:           0x1015
4537             - Value:           0x1
4538             - Value:           0xC
4539         - AbbrCode:        0x0
4540         - AbbrCode:        0x3
4541           Values:
4542             - Value:           0x5D
4543             - Value:           0x1020
4544             - Value:           0x1030
4545             - Value:           0x1
4546             - Value:           0xD
4547         - AbbrCode:        0x4
4548           Values:
4549             - Value:           0x79
4550             - Value:           0x1020
4551             - Value:           0x1025
4552             - Value:           0x1
4553             - Value:           0xE
4554         - AbbrCode:        0x0
4555         - AbbrCode:        0x0
4556         - AbbrCode:        0x5
4557           Values:
4558             - Value:           0xA3
4559             - Value:           0x1
4560             - Value:           0x14
4561             - Value:           0x2000
4562             - Value:           0x2050
4563         - AbbrCode:        0x5
4564           Values:
4565             - Value:           0xBD
4566             - Value:           0xA
4567             - Value:           0x14
4568             - Value:           0x3000
4569             - Value:           0x3050
4570         - AbbrCode:        0x0
4571   debug_line:
4572     - Length:          78
4573       Version:         2
4574       PrologueLength:  36
4575       MinInstLength:   1
4576       DefaultIsStmt:   1
4577       LineBase:        251
4578       LineRange:       14
4579       OpcodeBase:      13
4580       StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]
4581       IncludeDirs:
4582         - '/tmp'
4583       Files:
4584         - Name:            main.cpp
4585           DirIdx:          1
4586           ModTime:         0
4587           Length:          0
4588       Opcodes:
4589         - Opcode:          DW_LNS_extended_op
4590           ExtLen:          9
4591           SubOpcode:       DW_LNE_set_address
4592           Data:            4096
4593         - Opcode:          DW_LNS_advance_line
4594           SData:           9
4595           Data:            0
4596         - Opcode:          DW_LNS_copy
4597           Data:            0
4598         - Opcode:          DW_LNS_advance_pc
4599           Data:            16
4600         - Opcode:          DW_LNS_set_file
4601           Data:            10
4602         - Opcode:          DW_LNS_advance_line
4603           SData:           1
4604           Data:            0
4605         - Opcode:          DW_LNS_copy
4606           Data:            0
4607         - Opcode:          DW_LNS_advance_pc
4608           Data:            16
4609         - Opcode:          DW_LNS_set_file
4610           Data:            1
4611         - Opcode:          DW_LNS_copy
4612           Data:            0
4613         - Opcode:          DW_LNS_advance_pc
4614           Data:            16
4615         - Opcode:          DW_LNS_advance_line
4616           SData:           1
4617           Data:            0
4618         - Opcode:          DW_LNS_copy
4619           Data:            0
4620         - Opcode:          DW_LNS_advance_pc
4621           Data:            32
4622         - Opcode:          DW_LNS_extended_op
4623           ExtLen:          1
4624           SubOpcode:       DW_LNE_end_sequence
4625           Data:            0
4626   )";
4627   auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);
4628   ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());
4629   std::unique_ptr<DWARFContext> DwarfContext =
4630       DWARFContext::create(*ErrOrSections, 8);
4631   ASSERT_TRUE(DwarfContext.get() != nullptr);
4632   std::string errors;
4633   raw_string_ostream OS(errors);
4634   OutputAggregator OSAgg(&OS);
4635   GsymCreator GC;
4636   DwarfTransformer DT(*DwarfContext, GC);
4637   const uint32_t ThreadCount = 1;
4638   ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());
4639   ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());
4640   SmallString<512> Str;
4641   raw_svector_ostream OutStrm(Str);
4642   const auto ByteOrder = llvm::endianness::native;
4643   FileWriter FW(OutStrm, ByteOrder);
4644   ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());
4645   Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());
4646   ASSERT_THAT_EXPECTED(GR, Succeeded());
4647   // There should be one function in our GSYM.
4648   EXPECT_EQ(GR->getNumAddresses(), 3u);
4649   // Verify "foo" is present and has a line table and no inline info.
4650   auto ExpFI = GR->getFunctionInfo(0x1000);
4651   ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
4652   ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x1050));
4653   StringRef FuncName = GR->getString(ExpFI->Name);
4654   EXPECT_EQ(FuncName, "foo");
4655 
4656   EXPECT_TRUE(ExpFI->OptLineTable.has_value());
4657   // Make sure we only have 3 entries to show we removed the line entry with
4658   // the invalid file index whose address is 0x0000000000001010.
4659   ASSERT_EQ(ExpFI->OptLineTable->size(), 3u);
4660   EXPECT_TRUE(ExpFI->Inline.has_value());
4661 
4662   // Make sure that we only have one inline function, not two. We remove one of
4663   // the inline functions because it has an invalid DW_AT_call_file attribute.
4664   ASSERT_EQ(ExpFI->Inline->Children.size(), 1u);
4665   StringRef InlineName = GR->getString(ExpFI->Inline->Children[0].Name);
4666   EXPECT_EQ(InlineName, "inline_with_valid_call_file");
4667 
4668   ExpFI = GR->getFunctionInfo(0x0000000000002000);
4669   ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
4670   ASSERT_EQ(ExpFI->Range, AddressRange(0x2000, 0x2050));
4671   FuncName = GR->getString(ExpFI->Name);
4672   EXPECT_EQ(FuncName, "func_with_valid_decl_file");
4673   EXPECT_FALSE(ExpFI->Inline.has_value());
4674   // Make sure we only have 1 entry in the line table which indicates we were
4675   // able to parse the DW_AT_decl_file/DW_AT_decl_line correctly.
4676   EXPECT_TRUE(ExpFI->OptLineTable.has_value());
4677   ASSERT_EQ(ExpFI->OptLineTable->size(), 1u);
4678 
4679   ExpFI = GR->getFunctionInfo(0x0000000000003000);
4680   ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
4681   ASSERT_EQ(ExpFI->Range, AddressRange(0x3000, 0x3050));
4682   FuncName = GR->getString(ExpFI->Name);
4683   EXPECT_EQ(FuncName, "func_with_invalid_decl_file");
4684   EXPECT_FALSE(ExpFI->Inline.has_value());
4685   // Make sure we only no line table because there are no line entries in the
4686   // line table and the DW_AT_decl_file attribute was invalid so we were not
4687   // able to parse the DW_AT_decl_file/DW_AT_decl_line correctly.
4688   EXPECT_FALSE(ExpFI->OptLineTable.has_value());
4689 
4690   // Make sure we don't see spurious errors in the output:
4691   std::vector<std::string> ExpectedLogErrors = {
4692       "error: function DIE at 0x00000015 has a line entry with invalid DWARF "
4693       "file index, this entry will be removed:",
4694       "error: inlined function DIE at 0x0000002a has an invalid file index 10 "
4695       "in its DW_AT_call_file attribute, this inline entry and all children "
4696       "will be removed.",
4697       "error: function DIE at 0x000000b8 has an invalid file index 10 in its "
4698       "DW_AT_decl_file attribute, unable to create a single line entry from "
4699       "the DW_AT_decl_file/DW_AT_decl_line attributes."};
4700   // Make sure all expected errors are in the error stream for the two invalid
4701   // inlined functions that we removed due to invalid range scoping.
4702   for (const auto &Error : ExpectedLogErrors)
4703     EXPECT_TRUE(errors.find(Error) != std::string::npos);
4704 }
4705 
4706 TEST(GSYMTest, TestLookupsOfOverlappingAndUnequalRanges) {
4707   // Test that llvm-gsymutil lookup the correct funtion info when address
4708   // ranges overlap. When functions overlap we always want to pick the first
4709   // function info when symbolicating if there are multiple entries with the
4710   // same address. Previous to this fix we would just binary search the address
4711   // table and pick the first function info that matched the address. After
4712   // this fix we now always select the first matching entry whose address range
4713   // contains the lookup address to ensure we have the most debug info. We have
4714   // seen case where the debug info would contain a small range and a symbol
4715   // would have the same start address but the range was larger and sometimes,
4716   // depending on how the binary search of the address table happened, we would
4717   // pick these latter entries. We want the first entries because they always
4718   // have the most debug info.
4719   //
4720   // To repro this case, we just make some simple DWARF that has two
4721   // overlapping ranges and ensure that any lookups between 0x1000 and 0x104f
4722   // match "foo", and any ranges between 0x1050 and 0x1fff match "bar".
4723   //
4724   // 0x0000000b: DW_TAG_compile_unit
4725   //               DW_AT_name	("/tmp/main.cpp")
4726   //               DW_AT_language	(DW_LANG_C)
4727   //               DW_AT_stmt_list	(0x00000000)
4728   //
4729   // 0x00000015:   DW_TAG_subprogram
4730   //                 DW_AT_name	("foo")
4731   //                 DW_AT_low_pc	(0x0000000000001000)
4732   //                 DW_AT_high_pc	(0x0000000000001050)
4733   //
4734   // 0x0000002a:   DW_TAG_subprogram
4735   //                 DW_AT_name	("bar")
4736   //                 DW_AT_low_pc	(0x0000000000001000)
4737   //                 DW_AT_high_pc	(0x0000000000001100)
4738   //
4739   // 0x0000003f:   NULL
4740 
4741   StringRef yamldata = R"(
4742   debug_str:
4743     - ''
4744     - '/tmp/main.cpp'
4745     - foo
4746     - bar
4747   debug_abbrev:
4748     - ID:              0
4749       Table:
4750         - Code:            0x1
4751           Tag:             DW_TAG_compile_unit
4752           Children:        DW_CHILDREN_yes
4753           Attributes:
4754             - Attribute:       DW_AT_name
4755               Form:            DW_FORM_strp
4756             - Attribute:       DW_AT_language
4757               Form:            DW_FORM_udata
4758             - Attribute:       DW_AT_stmt_list
4759               Form:            DW_FORM_sec_offset
4760         - Code:            0x2
4761           Tag:             DW_TAG_subprogram
4762           Children:        DW_CHILDREN_no
4763           Attributes:
4764             - Attribute:       DW_AT_name
4765               Form:            DW_FORM_strp
4766             - Attribute:       DW_AT_low_pc
4767               Form:            DW_FORM_addr
4768             - Attribute:       DW_AT_high_pc
4769               Form:            DW_FORM_addr
4770   debug_info:
4771     - Length:          0x3C
4772       Version:         4
4773       AbbrevTableID:   0
4774       AbbrOffset:      0x0
4775       AddrSize:        8
4776       Entries:
4777         - AbbrCode:        0x1
4778           Values:
4779             - Value:           0x1
4780             - Value:           0x2
4781             - Value:           0x0
4782         - AbbrCode:        0x2
4783           Values:
4784             - Value:           0xF
4785             - Value:           0x1000
4786             - Value:           0x1050
4787         - AbbrCode:        0x2
4788           Values:
4789             - Value:           0x13
4790             - Value:           0x1000
4791             - Value:           0x1100
4792         - AbbrCode:        0x0
4793   debug_line:
4794     - Length:          71
4795       Version:         2
4796       PrologueLength:  36
4797       MinInstLength:   1
4798       DefaultIsStmt:   1
4799       LineBase:        251
4800       LineRange:       14
4801       OpcodeBase:      13
4802       StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]
4803       IncludeDirs:
4804         - '/tmp'
4805       Files:
4806         - Name:            main.cpp
4807           DirIdx:          1
4808           ModTime:         0
4809           Length:          0
4810       Opcodes:
4811         - Opcode:          DW_LNS_extended_op
4812           ExtLen:          9
4813           SubOpcode:       DW_LNE_set_address
4814           Data:            4096
4815         - Opcode:          DW_LNS_advance_line
4816           SData:           9
4817           Data:            0
4818         - Opcode:          DW_LNS_copy
4819           Data:            0
4820         - Opcode:          DW_LNS_advance_pc
4821           Data:            16
4822         - Opcode:          DW_LNS_advance_line
4823           SData:           1
4824           Data:            0
4825         - Opcode:          DW_LNS_copy
4826           Data:            0
4827         - Opcode:          DW_LNS_advance_line
4828           SData:           1
4829           Data:            0
4830         - Opcode:          DW_LNS_copy
4831           Data:            0
4832         - Opcode:          DW_LNS_advance_pc
4833           Data:            64
4834         - Opcode:          DW_LNS_advance_line
4835           SData:           1
4836           Data:            0
4837         - Opcode:          DW_LNS_extended_op
4838           ExtLen:          1
4839           SubOpcode:       DW_LNE_end_sequence
4840           Data:            0
4841   )";
4842   auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);
4843   ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());
4844   std::unique_ptr<DWARFContext> DwarfContext =
4845       DWARFContext::create(*ErrOrSections, 8);
4846   ASSERT_TRUE(DwarfContext.get() != nullptr);
4847   std::string errors;
4848   raw_string_ostream OS(errors);
4849   OutputAggregator OSAgg(&OS);
4850   GsymCreator GC;
4851   DwarfTransformer DT(*DwarfContext, GC);
4852   const uint32_t ThreadCount = 1;
4853   ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());
4854   ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());
4855   SmallString<512> Str;
4856   raw_svector_ostream OutStrm(Str);
4857   const auto ByteOrder = llvm::endianness::native;
4858   FileWriter FW(OutStrm, ByteOrder);
4859   ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());
4860   Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());
4861   ASSERT_THAT_EXPECTED(GR, Succeeded());
4862   // There should be two functions in our GSYM.
4863   EXPECT_EQ(GR->getNumAddresses(), 2u);
4864   // Verify "foo" is correctly looked up for each of its addresses.
4865   for (uint64_t Addr = 0x1000; Addr < 0x1050; ++Addr) {
4866     auto ExpFI = GR->getFunctionInfo(Addr);
4867     ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
4868     ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x1050));
4869     StringRef FuncName = GR->getString(ExpFI->Name);
4870     EXPECT_EQ(FuncName, "foo");
4871   }
4872 
4873   // Verify "bar" is correctly looked up for each of its addresses.
4874   for (uint64_t Addr = 0x1050; Addr < 0x1100; ++Addr) {
4875     auto ExpFI = GR->getFunctionInfo(Addr);
4876     ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
4877     ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x1100));
4878     StringRef FuncName = GR->getString(ExpFI->Name);
4879     EXPECT_EQ(FuncName, "bar");
4880   }
4881 
4882   // Prior to the fix for this issue when we dumped an entire GSYM file, we
4883   // were using a function that would extract a FunctionInfo object for a
4884   // given address which caused us to always dump the first FunctionInfo
4885   // entry for a given address. We now dump it correctly using an address
4886   // index. Below we verify that we dump the right FunctionInfo gets dumped.
4887 
4888   SmallString<512> DumpStr;
4889   raw_svector_ostream DumpStrm(DumpStr);
4890   GR->dump(DumpStrm);
4891 
4892   // Make sure we see both "foo" and "bar" in the output of an entire GSYM
4893   // dump. Prior to this fix we would two "foo" entries.
4894   std::vector<std::string> ExpectedDumpLines = {
4895       "@ 0x00000068: [0x0000000000001000 - 0x0000000000001050) \"foo\"",
4896       "@ 0x00000088: [0x0000000000001000 - 0x0000000000001100) \"bar\""};
4897   // Make sure all expected errors are in the error stream for the two invalid
4898   // inlined functions that we removed due to invalid range scoping.
4899   for (const auto &Line : ExpectedDumpLines)
4900     EXPECT_TRUE(DumpStr.find(Line) != std::string::npos);
4901 }
4902