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