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