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 <) {
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