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/GSYM/Header.h" 13 #include "llvm/DebugInfo/GSYM/FileEntry.h" 14 #include "llvm/DebugInfo/GSYM/FileWriter.h" 15 #include "llvm/DebugInfo/GSYM/FunctionInfo.h" 16 #include "llvm/DebugInfo/GSYM/GsymCreator.h" 17 #include "llvm/DebugInfo/GSYM/GsymReader.h" 18 #include "llvm/DebugInfo/GSYM/InlineInfo.h" 19 #include "llvm/DebugInfo/GSYM/Range.h" 20 #include "llvm/DebugInfo/GSYM/StringTable.h" 21 #include "llvm/Support/DataExtractor.h" 22 #include "llvm/Support/Endian.h" 23 24 #include "gtest/gtest.h" 25 #include <string> 26 27 using namespace llvm; 28 using namespace gsym; 29 30 void checkError(ArrayRef<std::string> ExpectedMsgs, Error Err) { 31 ASSERT_TRUE(bool(Err)); 32 size_t WhichMsg = 0; 33 Error Remaining = 34 handleErrors(std::move(Err), [&](const ErrorInfoBase &Actual) { 35 ASSERT_LT(WhichMsg, ExpectedMsgs.size()); 36 // Use .str(), because googletest doesn't visualise a StringRef 37 // properly. 38 EXPECT_EQ(Actual.message(), ExpectedMsgs[WhichMsg++]); 39 }); 40 EXPECT_EQ(WhichMsg, ExpectedMsgs.size()); 41 EXPECT_FALSE(Remaining); 42 } 43 44 void checkError(std::string ExpectedMsg, Error Err) { 45 checkError(ArrayRef<std::string>{ExpectedMsg}, std::move(Err)); 46 } 47 TEST(GSYMTest, TestFileEntry) { 48 // Make sure default constructed GSYM FileEntry has zeroes in the 49 // directory and basename string table indexes. 50 FileEntry empty1; 51 FileEntry empty2; 52 EXPECT_EQ(empty1.Dir, 0u); 53 EXPECT_EQ(empty1.Base, 0u); 54 // Verify equality operator works 55 FileEntry a1(10, 30); 56 FileEntry a2(10, 30); 57 FileEntry b(10, 40); 58 EXPECT_EQ(empty1, empty2); 59 EXPECT_EQ(a1, a2); 60 EXPECT_NE(a1, b); 61 EXPECT_NE(a1, empty1); 62 // Test we can use llvm::gsym::FileEntry in llvm::DenseMap. 63 DenseMap<FileEntry, uint32_t> EntryToIndex; 64 constexpr uint32_t Index1 = 1; 65 constexpr uint32_t Index2 = 1; 66 auto R = EntryToIndex.insert(std::make_pair(a1, Index1)); 67 EXPECT_TRUE(R.second); 68 EXPECT_EQ(R.first->second, Index1); 69 R = EntryToIndex.insert(std::make_pair(a1, Index1)); 70 EXPECT_FALSE(R.second); 71 EXPECT_EQ(R.first->second, Index1); 72 R = EntryToIndex.insert(std::make_pair(b, Index2)); 73 EXPECT_TRUE(R.second); 74 EXPECT_EQ(R.first->second, Index2); 75 R = EntryToIndex.insert(std::make_pair(a1, Index2)); 76 EXPECT_FALSE(R.second); 77 EXPECT_EQ(R.first->second, Index2); 78 } 79 80 TEST(GSYMTest, TestFunctionInfo) { 81 // Test GSYM FunctionInfo structs and functionality. 82 FunctionInfo invalid; 83 EXPECT_FALSE(invalid.isValid()); 84 EXPECT_FALSE(invalid.hasRichInfo()); 85 const uint64_t StartAddr = 0x1000; 86 const uint64_t EndAddr = 0x1100; 87 const uint64_t Size = EndAddr - StartAddr; 88 const uint32_t NameOffset = 30; 89 FunctionInfo FI(StartAddr, Size, NameOffset); 90 EXPECT_TRUE(FI.isValid()); 91 EXPECT_FALSE(FI.hasRichInfo()); 92 EXPECT_EQ(FI.startAddress(), StartAddr); 93 EXPECT_EQ(FI.endAddress(), EndAddr); 94 EXPECT_EQ(FI.size(), Size); 95 const uint32_t FileIdx = 1; 96 const uint32_t Line = 12; 97 FI.OptLineTable = LineTable(); 98 FI.OptLineTable->push(LineEntry(StartAddr,FileIdx,Line)); 99 EXPECT_TRUE(FI.hasRichInfo()); 100 FI.clear(); 101 EXPECT_FALSE(FI.isValid()); 102 EXPECT_FALSE(FI.hasRichInfo()); 103 104 FunctionInfo A1(0x1000, 0x100, NameOffset); 105 FunctionInfo A2(0x1000, 0x100, NameOffset); 106 FunctionInfo B; 107 // Check == operator 108 EXPECT_EQ(A1, A2); 109 // Make sure things are not equal if they only differ by start address. 110 B = A2; 111 B.setStartAddress(0x2000); 112 EXPECT_NE(B, A2); 113 // Make sure things are not equal if they only differ by size. 114 B = A2; 115 B.setSize(0x101); 116 EXPECT_NE(B, A2); 117 // Make sure things are not equal if they only differ by name. 118 B = A2; 119 B.Name = 60; 120 EXPECT_NE(B, A2); 121 // Check < operator. 122 // Check less than where address differs. 123 B = A2; 124 B.setStartAddress(A2.startAddress() + 0x1000); 125 EXPECT_LT(A1, B); 126 127 // We use the < operator to take a variety of different FunctionInfo 128 // structs from a variety of sources: symtab, debug info, runtime info 129 // and we sort them and want the sorting to allow us to quickly get the 130 // best version of a function info. 131 FunctionInfo FISymtab(StartAddr, Size, NameOffset); 132 FunctionInfo FIWithLines(StartAddr, Size, NameOffset); 133 FIWithLines.OptLineTable = LineTable(); 134 FIWithLines.OptLineTable->push(LineEntry(StartAddr,FileIdx,Line)); 135 // Test that a FunctionInfo with just a name and size is less than one 136 // that has name, size and any number of line table entries 137 EXPECT_LT(FISymtab, FIWithLines); 138 139 FunctionInfo FIWithLinesAndInline = FIWithLines; 140 FIWithLinesAndInline.Inline = InlineInfo(); 141 FIWithLinesAndInline.Inline->Ranges.insert( 142 AddressRange(StartAddr, StartAddr + 0x10)); 143 // Test that a FunctionInfo with name, size, and line entries is less than 144 // the same one with valid inline info 145 EXPECT_LT(FIWithLines, FIWithLinesAndInline); 146 147 // Test if we have an entry with lines and one with more lines for the same 148 // range, the ones with more lines is greater than the one with less. 149 FunctionInfo FIWithMoreLines = FIWithLines; 150 FIWithMoreLines.OptLineTable->push(LineEntry(StartAddr,FileIdx,Line+5)); 151 EXPECT_LT(FIWithLines, FIWithMoreLines); 152 153 // Test that if we have the same number of lines we compare the line entries 154 // in the FunctionInfo.OptLineTable.Lines vector. 155 FunctionInfo FIWithLinesWithHigherAddress = FIWithLines; 156 FIWithLinesWithHigherAddress.OptLineTable->get(0).Addr += 0x10; 157 EXPECT_LT(FIWithLines, FIWithLinesWithHigherAddress); 158 } 159 160 static void TestFunctionInfoDecodeError(llvm::support::endianness ByteOrder, 161 std::string Bytes, 162 const uint64_t BaseAddr, 163 std::string ExpectedErrorMsg) { 164 uint8_t AddressSize = 4; 165 DataExtractor Data(Bytes, ByteOrder == llvm::support::little, AddressSize); 166 llvm::Expected<FunctionInfo> Decoded = FunctionInfo::decode(Data, BaseAddr); 167 // Make sure decoding fails. 168 ASSERT_FALSE((bool)Decoded); 169 // Make sure decoded object is the same as the one we encoded. 170 checkError(ExpectedErrorMsg, Decoded.takeError()); 171 } 172 173 TEST(GSYMTest, TestFunctionInfoDecodeErrors) { 174 // Test decoding FunctionInfo objects that ensure we report an appropriate 175 // error message. 176 const llvm::support::endianness ByteOrder = llvm::support::little; 177 SmallString<512> Str; 178 raw_svector_ostream OutStrm(Str); 179 FileWriter FW(OutStrm, ByteOrder); 180 const uint64_t BaseAddr = 0x100; 181 TestFunctionInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr, 182 "0x00000000: missing FunctionInfo Size"); 183 FW.writeU32(0x100); // Function size. 184 TestFunctionInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr, 185 "0x00000004: missing FunctionInfo Name"); 186 // Write out an invalid Name string table offset of zero. 187 FW.writeU32(0); 188 TestFunctionInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr, 189 "0x00000004: invalid FunctionInfo Name value 0x00000000"); 190 // Modify the Name to be 0x00000001, which is a valid value. 191 FW.fixup32(0x00000001, 4); 192 TestFunctionInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr, 193 "0x00000008: missing FunctionInfo InfoType value"); 194 auto FixupOffset = FW.tell(); 195 FW.writeU32(1); // InfoType::LineTableInfo. 196 TestFunctionInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr, 197 "0x0000000c: missing FunctionInfo InfoType length"); 198 FW.fixup32(4, FixupOffset); // Write an invalid InfoType enumeration value 199 FW.writeU32(0); // LineTableInfo InfoType data length. 200 TestFunctionInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr, 201 "0x00000008: unsupported InfoType 4"); 202 } 203 204 static void TestFunctionInfoEncodeError(llvm::support::endianness ByteOrder, 205 const FunctionInfo &FI, 206 std::string ExpectedErrorMsg) { 207 SmallString<512> Str; 208 raw_svector_ostream OutStrm(Str); 209 FileWriter FW(OutStrm, ByteOrder); 210 Expected<uint64_t> ExpectedOffset = FI.encode(FW); 211 ASSERT_FALSE(ExpectedOffset); 212 checkError(ExpectedErrorMsg, ExpectedOffset.takeError()); 213 } 214 215 TEST(GSYMTest, TestFunctionInfoEncodeErrors) { 216 const uint64_t FuncAddr = 0x1000; 217 const uint64_t FuncSize = 0x100; 218 const uint32_t InvalidName = 0; 219 const uint32_t ValidName = 1; 220 FunctionInfo InvalidNameFI(FuncAddr, FuncSize, InvalidName); 221 TestFunctionInfoEncodeError(llvm::support::little, InvalidNameFI, 222 "attempted to encode invalid FunctionInfo object"); 223 224 FunctionInfo InvalidLineTableFI(FuncAddr, FuncSize, ValidName); 225 // Empty line tables are not valid. Verify if the encoding of anything 226 // in our line table fails, that we see get the error propagated. 227 InvalidLineTableFI.OptLineTable = LineTable(); 228 TestFunctionInfoEncodeError(llvm::support::little, InvalidLineTableFI, 229 "attempted to encode invalid LineTable object"); 230 231 FunctionInfo InvalidInlineInfoFI(FuncAddr, FuncSize, ValidName); 232 // Empty line tables are not valid. Verify if the encoding of anything 233 // in our line table fails, that we see get the error propagated. 234 InvalidInlineInfoFI.Inline = InlineInfo(); 235 TestFunctionInfoEncodeError(llvm::support::little, InvalidInlineInfoFI, 236 "attempted to encode invalid InlineInfo object"); 237 } 238 239 static void TestFunctionInfoEncodeDecode(llvm::support::endianness ByteOrder, 240 const FunctionInfo &FI) { 241 // Test encoding and decoding FunctionInfo objects. 242 SmallString<512> Str; 243 raw_svector_ostream OutStrm(Str); 244 FileWriter FW(OutStrm, ByteOrder); 245 llvm::Expected<uint64_t> ExpectedOffset = FI.encode(FW); 246 ASSERT_TRUE(bool(ExpectedOffset)); 247 // Verify we got the encoded offset back from the encode function. 248 ASSERT_EQ(ExpectedOffset.get(), 0ULL); 249 std::string Bytes(OutStrm.str()); 250 uint8_t AddressSize = 4; 251 DataExtractor Data(Bytes, ByteOrder == llvm::support::little, AddressSize); 252 llvm::Expected<FunctionInfo> Decoded = FunctionInfo::decode(Data, 253 FI.Range.Start); 254 // Make sure decoding succeeded. 255 ASSERT_TRUE((bool)Decoded); 256 // Make sure decoded object is the same as the one we encoded. 257 EXPECT_EQ(FI, Decoded.get()); 258 } 259 260 static void AddLines(uint64_t FuncAddr, uint32_t FileIdx, FunctionInfo &FI) { 261 FI.OptLineTable = LineTable(); 262 LineEntry Line0(FuncAddr + 0x000, FileIdx, 10); 263 LineEntry Line1(FuncAddr + 0x010, FileIdx, 11); 264 LineEntry Line2(FuncAddr + 0x100, FileIdx, 1000); 265 FI.OptLineTable->push(Line0); 266 FI.OptLineTable->push(Line1); 267 FI.OptLineTable->push(Line2); 268 } 269 270 271 static void AddInline(uint64_t FuncAddr, uint64_t FuncSize, FunctionInfo &FI) { 272 FI.Inline = InlineInfo(); 273 FI.Inline->Ranges.insert(AddressRange(FuncAddr, FuncAddr + FuncSize)); 274 InlineInfo Inline1; 275 Inline1.Ranges.insert(AddressRange(FuncAddr + 0x10, FuncAddr + 0x30)); 276 Inline1.Name = 1; 277 Inline1.CallFile = 1; 278 Inline1.CallLine = 11; 279 FI.Inline->Children.push_back(Inline1); 280 } 281 282 TEST(GSYMTest, TestFunctionInfoEncoding) { 283 constexpr uint64_t FuncAddr = 0x1000; 284 constexpr uint64_t FuncSize = 0x100; 285 constexpr uint32_t FuncName = 1; 286 constexpr uint32_t FileIdx = 1; 287 // Make sure that we can encode and decode a FunctionInfo with no line table 288 // or inline info. 289 FunctionInfo FI(FuncAddr, FuncSize, FuncName); 290 TestFunctionInfoEncodeDecode(llvm::support::little, FI); 291 TestFunctionInfoEncodeDecode(llvm::support::big, FI); 292 293 // Make sure that we can encode and decode a FunctionInfo with a line table 294 // and no inline info. 295 FunctionInfo FILines(FuncAddr, FuncSize, FuncName); 296 AddLines(FuncAddr, FileIdx, FILines); 297 TestFunctionInfoEncodeDecode(llvm::support::little, FILines); 298 TestFunctionInfoEncodeDecode(llvm::support::big, FILines); 299 300 // Make sure that we can encode and decode a FunctionInfo with no line table 301 // and with inline info. 302 FunctionInfo FIInline(FuncAddr, FuncSize, FuncName); 303 AddInline(FuncAddr, FuncSize, FIInline); 304 TestFunctionInfoEncodeDecode(llvm::support::little, FIInline); 305 TestFunctionInfoEncodeDecode(llvm::support::big, FIInline); 306 307 // Make sure that we can encode and decode a FunctionInfo with no line table 308 // and with inline info. 309 FunctionInfo FIBoth(FuncAddr, FuncSize, FuncName); 310 AddLines(FuncAddr, FileIdx, FIBoth); 311 AddInline(FuncAddr, FuncSize, FIBoth); 312 TestFunctionInfoEncodeDecode(llvm::support::little, FIBoth); 313 TestFunctionInfoEncodeDecode(llvm::support::big, FIBoth); 314 } 315 316 static void TestInlineInfoEncodeDecode(llvm::support::endianness ByteOrder, 317 const InlineInfo &Inline) { 318 // Test encoding and decoding InlineInfo objects 319 SmallString<512> Str; 320 raw_svector_ostream OutStrm(Str); 321 FileWriter FW(OutStrm, ByteOrder); 322 const uint64_t BaseAddr = Inline.Ranges[0].Start; 323 llvm::Error Err = Inline.encode(FW, BaseAddr); 324 ASSERT_FALSE(Err); 325 std::string Bytes(OutStrm.str()); 326 uint8_t AddressSize = 4; 327 DataExtractor Data(Bytes, ByteOrder == llvm::support::little, AddressSize); 328 llvm::Expected<InlineInfo> Decoded = InlineInfo::decode(Data, BaseAddr); 329 // Make sure decoding succeeded. 330 ASSERT_TRUE((bool)Decoded); 331 // Make sure decoded object is the same as the one we encoded. 332 EXPECT_EQ(Inline, Decoded.get()); 333 } 334 335 static void TestInlineInfoDecodeError(llvm::support::endianness ByteOrder, 336 std::string Bytes, 337 const uint64_t BaseAddr, 338 std::string ExpectedErrorMsg) { 339 uint8_t AddressSize = 4; 340 DataExtractor Data(Bytes, ByteOrder == llvm::support::little, AddressSize); 341 llvm::Expected<InlineInfo> Decoded = InlineInfo::decode(Data, BaseAddr); 342 // Make sure decoding fails. 343 ASSERT_FALSE((bool)Decoded); 344 // Make sure decoded object is the same as the one we encoded. 345 checkError(ExpectedErrorMsg, Decoded.takeError()); 346 } 347 348 static void TestInlineInfoEncodeError(llvm::support::endianness ByteOrder, 349 const InlineInfo &Inline, 350 std::string ExpectedErrorMsg) { 351 SmallString<512> Str; 352 raw_svector_ostream OutStrm(Str); 353 FileWriter FW(OutStrm, ByteOrder); 354 const uint64_t BaseAddr = Inline.Ranges.empty() ? 0 : Inline.Ranges[0].Start; 355 llvm::Error Err = Inline.encode(FW, BaseAddr); 356 checkError(ExpectedErrorMsg, std::move(Err)); 357 } 358 359 TEST(GSYMTest, TestInlineInfo) { 360 // Test InlineInfo structs. 361 InlineInfo II; 362 EXPECT_FALSE(II.isValid()); 363 II.Ranges.insert(AddressRange(0x1000, 0x2000)); 364 // Make sure InlineInfo in valid with just an address range since 365 // top level InlineInfo objects have ranges with no name, call file 366 // or call line 367 EXPECT_TRUE(II.isValid()); 368 // Make sure InlineInfo isn't after being cleared. 369 II.clear(); 370 EXPECT_FALSE(II.isValid()); 371 372 // Create an InlineInfo that contains the following data. The 373 // indentation of the address range indicates the parent child 374 // relationships of the InlineInfo objects: 375 // 376 // Variable Range and values 377 // =========== ==================================================== 378 // Root [0x100-0x200) (no name, file, or line) 379 // Inline1 [0x150-0x160) Name = 1, File = 1, Line = 11 380 // Inline1Sub1 [0x152-0x155) Name = 2, File = 2, Line = 22 381 // Inline1Sub2 [0x157-0x158) Name = 3, File = 3, Line = 33 382 InlineInfo Root; 383 Root.Ranges.insert(AddressRange(0x100, 0x200)); 384 InlineInfo Inline1; 385 Inline1.Ranges.insert(AddressRange(0x150, 0x160)); 386 Inline1.Name = 1; 387 Inline1.CallFile = 1; 388 Inline1.CallLine = 11; 389 InlineInfo Inline1Sub1; 390 Inline1Sub1.Ranges.insert(AddressRange(0x152, 0x155)); 391 Inline1Sub1.Name = 2; 392 Inline1Sub1.CallFile = 2; 393 Inline1Sub1.CallLine = 22; 394 InlineInfo Inline1Sub2; 395 Inline1Sub2.Ranges.insert(AddressRange(0x157, 0x158)); 396 Inline1Sub2.Name = 3; 397 Inline1Sub2.CallFile = 3; 398 Inline1Sub2.CallLine = 33; 399 Inline1.Children.push_back(Inline1Sub1); 400 Inline1.Children.push_back(Inline1Sub2); 401 Root.Children.push_back(Inline1); 402 403 // Make sure an address that is out of range won't match 404 EXPECT_FALSE(Root.getInlineStack(0x50)); 405 406 // Verify that we get no inline stacks for addresses out of [0x100-0x200) 407 EXPECT_FALSE(Root.getInlineStack(Root.Ranges[0].Start - 1)); 408 EXPECT_FALSE(Root.getInlineStack(Root.Ranges[0].End)); 409 410 // Verify we get no inline stack entries for addresses that are in 411 // [0x100-0x200) but not in [0x150-0x160) 412 EXPECT_FALSE(Root.getInlineStack(Inline1.Ranges[0].Start - 1)); 413 EXPECT_FALSE(Root.getInlineStack(Inline1.Ranges[0].End)); 414 415 // Verify we get one inline stack entry for addresses that are in 416 // [[0x150-0x160)) but not in [0x152-0x155) or [0x157-0x158) 417 auto InlineInfos = Root.getInlineStack(Inline1.Ranges[0].Start); 418 ASSERT_TRUE(InlineInfos); 419 ASSERT_EQ(InlineInfos->size(), 1u); 420 ASSERT_EQ(*InlineInfos->at(0), Inline1); 421 InlineInfos = Root.getInlineStack(Inline1.Ranges[0].End - 1); 422 EXPECT_TRUE(InlineInfos); 423 ASSERT_EQ(InlineInfos->size(), 1u); 424 ASSERT_EQ(*InlineInfos->at(0), Inline1); 425 426 // Verify we get two inline stack entries for addresses that are in 427 // [0x152-0x155) 428 InlineInfos = Root.getInlineStack(Inline1Sub1.Ranges[0].Start); 429 EXPECT_TRUE(InlineInfos); 430 ASSERT_EQ(InlineInfos->size(), 2u); 431 ASSERT_EQ(*InlineInfos->at(0), Inline1Sub1); 432 ASSERT_EQ(*InlineInfos->at(1), Inline1); 433 InlineInfos = Root.getInlineStack(Inline1Sub1.Ranges[0].End - 1); 434 EXPECT_TRUE(InlineInfos); 435 ASSERT_EQ(InlineInfos->size(), 2u); 436 ASSERT_EQ(*InlineInfos->at(0), Inline1Sub1); 437 ASSERT_EQ(*InlineInfos->at(1), Inline1); 438 439 // Verify we get two inline stack entries for addresses that are in 440 // [0x157-0x158) 441 InlineInfos = Root.getInlineStack(Inline1Sub2.Ranges[0].Start); 442 EXPECT_TRUE(InlineInfos); 443 ASSERT_EQ(InlineInfos->size(), 2u); 444 ASSERT_EQ(*InlineInfos->at(0), Inline1Sub2); 445 ASSERT_EQ(*InlineInfos->at(1), Inline1); 446 InlineInfos = Root.getInlineStack(Inline1Sub2.Ranges[0].End - 1); 447 EXPECT_TRUE(InlineInfos); 448 ASSERT_EQ(InlineInfos->size(), 2u); 449 ASSERT_EQ(*InlineInfos->at(0), Inline1Sub2); 450 ASSERT_EQ(*InlineInfos->at(1), Inline1); 451 452 // Test encoding and decoding InlineInfo objects 453 TestInlineInfoEncodeDecode(llvm::support::little, Root); 454 TestInlineInfoEncodeDecode(llvm::support::big, Root); 455 } 456 457 TEST(GSYMTest, TestInlineInfoEncodeErrors) { 458 // Test InlineInfo encoding errors. 459 460 // Test that we get an error when trying to encode an InlineInfo object 461 // that has no ranges. 462 InlineInfo Empty; 463 std::string EmptyErr("attempted to encode invalid InlineInfo object"); 464 TestInlineInfoEncodeError(llvm::support::little, Empty, EmptyErr); 465 TestInlineInfoEncodeError(llvm::support::big, Empty, EmptyErr); 466 467 // Verify that we get an error trying to encode an InlineInfo object that has 468 // a child InlineInfo that has no ranges. 469 InlineInfo ContainsEmpty; 470 ContainsEmpty.Ranges.insert({0x100,200}); 471 ContainsEmpty.Children.push_back(Empty); 472 TestInlineInfoEncodeError(llvm::support::little, ContainsEmpty, EmptyErr); 473 TestInlineInfoEncodeError(llvm::support::big, ContainsEmpty, EmptyErr); 474 475 // Verify that we get an error trying to encode an InlineInfo object that has 476 // a child whose address range is not contained in the parent address range. 477 InlineInfo ChildNotContained; 478 std::string ChildNotContainedErr("child range not contained in parent"); 479 ChildNotContained.Ranges.insert({0x100,200}); 480 InlineInfo ChildNotContainedChild; 481 ChildNotContainedChild.Ranges.insert({0x200,300}); 482 ChildNotContained.Children.push_back(ChildNotContainedChild); 483 TestInlineInfoEncodeError(llvm::support::little, ChildNotContained, 484 ChildNotContainedErr); 485 TestInlineInfoEncodeError(llvm::support::big, ChildNotContained, 486 ChildNotContainedErr); 487 488 } 489 490 TEST(GSYMTest, TestInlineInfoDecodeErrors) { 491 // Test decoding InlineInfo objects that ensure we report an appropriate 492 // error message. 493 const llvm::support::endianness ByteOrder = llvm::support::little; 494 SmallString<512> Str; 495 raw_svector_ostream OutStrm(Str); 496 FileWriter FW(OutStrm, ByteOrder); 497 const uint64_t BaseAddr = 0x100; 498 TestInlineInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr, 499 "0x00000000: missing InlineInfo address ranges data"); 500 AddressRanges Ranges; 501 Ranges.insert({BaseAddr, BaseAddr+0x100}); 502 Ranges.encode(FW, BaseAddr); 503 TestInlineInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr, 504 "0x00000004: missing InlineInfo uint8_t indicating children"); 505 FW.writeU8(0); 506 TestInlineInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr, 507 "0x00000005: missing InlineInfo uint32_t for name"); 508 FW.writeU32(0); 509 TestInlineInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr, 510 "0x00000009: missing ULEB128 for InlineInfo call file"); 511 FW.writeU8(0); 512 TestInlineInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr, 513 "0x0000000a: missing ULEB128 for InlineInfo call line"); 514 } 515 516 TEST(GSYMTest, TestLineEntry) { 517 // test llvm::gsym::LineEntry structs. 518 const uint64_t ValidAddr = 0x1000; 519 const uint64_t InvalidFileIdx = 0; 520 const uint32_t ValidFileIdx = 1; 521 const uint32_t ValidLine = 5; 522 523 LineEntry Invalid; 524 EXPECT_FALSE(Invalid.isValid()); 525 // Make sure that an entry is invalid if it has a bad file index. 526 LineEntry BadFile(ValidAddr, InvalidFileIdx, ValidLine); 527 EXPECT_FALSE(BadFile.isValid()); 528 // Test operators 529 LineEntry E1(ValidAddr, ValidFileIdx, ValidLine); 530 LineEntry E2(ValidAddr, ValidFileIdx, ValidLine); 531 LineEntry DifferentAddr(ValidAddr + 1, ValidFileIdx, ValidLine); 532 LineEntry DifferentFile(ValidAddr, ValidFileIdx + 1, ValidLine); 533 LineEntry DifferentLine(ValidAddr, ValidFileIdx, ValidLine + 1); 534 EXPECT_TRUE(E1.isValid()); 535 EXPECT_EQ(E1, E2); 536 EXPECT_NE(E1, DifferentAddr); 537 EXPECT_NE(E1, DifferentFile); 538 EXPECT_NE(E1, DifferentLine); 539 EXPECT_LT(E1, DifferentAddr); 540 } 541 542 TEST(GSYMTest, TestRanges) { 543 // test llvm::gsym::AddressRange. 544 const uint64_t StartAddr = 0x1000; 545 const uint64_t EndAddr = 0x2000; 546 // Verify constructor and API to ensure it takes start and end address. 547 const AddressRange Range(StartAddr, EndAddr); 548 EXPECT_EQ(Range.size(), EndAddr - StartAddr); 549 550 // Verify llvm::gsym::AddressRange::contains(). 551 EXPECT_FALSE(Range.contains(0)); 552 EXPECT_FALSE(Range.contains(StartAddr - 1)); 553 EXPECT_TRUE(Range.contains(StartAddr)); 554 EXPECT_TRUE(Range.contains(EndAddr - 1)); 555 EXPECT_FALSE(Range.contains(EndAddr)); 556 EXPECT_FALSE(Range.contains(UINT64_MAX)); 557 558 const AddressRange RangeSame(StartAddr, EndAddr); 559 const AddressRange RangeDifferentStart(StartAddr + 1, EndAddr); 560 const AddressRange RangeDifferentEnd(StartAddr, EndAddr + 1); 561 const AddressRange RangeDifferentStartEnd(StartAddr + 1, EndAddr + 1); 562 // Test == and != with values that are the same 563 EXPECT_EQ(Range, RangeSame); 564 EXPECT_FALSE(Range != RangeSame); 565 // Test == and != with values that are the different 566 EXPECT_NE(Range, RangeDifferentStart); 567 EXPECT_NE(Range, RangeDifferentEnd); 568 EXPECT_NE(Range, RangeDifferentStartEnd); 569 EXPECT_FALSE(Range == RangeDifferentStart); 570 EXPECT_FALSE(Range == RangeDifferentEnd); 571 EXPECT_FALSE(Range == RangeDifferentStartEnd); 572 573 // Test "bool operator<(const AddressRange &, const AddressRange &)". 574 EXPECT_FALSE(Range < RangeSame); 575 EXPECT_FALSE(RangeSame < Range); 576 EXPECT_LT(Range, RangeDifferentStart); 577 EXPECT_LT(Range, RangeDifferentEnd); 578 EXPECT_LT(Range, RangeDifferentStartEnd); 579 // Test "bool operator<(const AddressRange &, uint64_t)" 580 EXPECT_LT(Range.Start, StartAddr + 1); 581 // Test "bool operator<(uint64_t, const AddressRange &)" 582 EXPECT_LT(StartAddr - 1, Range.Start); 583 584 // Verify llvm::gsym::AddressRange::isContiguousWith() and 585 // llvm::gsym::AddressRange::intersects(). 586 const AddressRange EndsBeforeRangeStart(0, StartAddr - 1); 587 const AddressRange EndsAtRangeStart(0, StartAddr); 588 const AddressRange OverlapsRangeStart(StartAddr - 1, StartAddr + 1); 589 const AddressRange InsideRange(StartAddr + 1, EndAddr - 1); 590 const AddressRange OverlapsRangeEnd(EndAddr - 1, EndAddr + 1); 591 const AddressRange StartsAtRangeEnd(EndAddr, EndAddr + 0x100); 592 const AddressRange StartsAfterRangeEnd(EndAddr + 1, EndAddr + 0x100); 593 594 EXPECT_FALSE(Range.intersects(EndsBeforeRangeStart)); 595 EXPECT_FALSE(Range.intersects(EndsAtRangeStart)); 596 EXPECT_TRUE(Range.intersects(OverlapsRangeStart)); 597 EXPECT_TRUE(Range.intersects(InsideRange)); 598 EXPECT_TRUE(Range.intersects(OverlapsRangeEnd)); 599 EXPECT_FALSE(Range.intersects(StartsAtRangeEnd)); 600 EXPECT_FALSE(Range.intersects(StartsAfterRangeEnd)); 601 602 // Test the functions that maintain GSYM address ranges: 603 // "bool AddressRange::contains(uint64_t Addr) const;" 604 // "void AddressRanges::insert(const AddressRange &R);" 605 AddressRanges Ranges; 606 Ranges.insert(AddressRange(0x1000, 0x2000)); 607 Ranges.insert(AddressRange(0x2000, 0x3000)); 608 Ranges.insert(AddressRange(0x4000, 0x5000)); 609 610 EXPECT_FALSE(Ranges.contains(0)); 611 EXPECT_FALSE(Ranges.contains(0x1000 - 1)); 612 EXPECT_TRUE(Ranges.contains(0x1000)); 613 EXPECT_TRUE(Ranges.contains(0x2000)); 614 EXPECT_TRUE(Ranges.contains(0x4000)); 615 EXPECT_TRUE(Ranges.contains(0x2000 - 1)); 616 EXPECT_TRUE(Ranges.contains(0x3000 - 1)); 617 EXPECT_FALSE(Ranges.contains(0x3000 + 1)); 618 EXPECT_TRUE(Ranges.contains(0x5000 - 1)); 619 EXPECT_FALSE(Ranges.contains(0x5000 + 1)); 620 EXPECT_FALSE(Ranges.contains(UINT64_MAX)); 621 622 EXPECT_FALSE(Ranges.contains(AddressRange())); 623 EXPECT_FALSE(Ranges.contains(AddressRange(0x1000-1, 0x1000))); 624 EXPECT_FALSE(Ranges.contains(AddressRange(0x1000, 0x1000))); 625 EXPECT_TRUE(Ranges.contains(AddressRange(0x1000, 0x1000+1))); 626 EXPECT_TRUE(Ranges.contains(AddressRange(0x1000, 0x2000))); 627 EXPECT_FALSE(Ranges.contains(AddressRange(0x1000, 0x2001))); 628 EXPECT_TRUE(Ranges.contains(AddressRange(0x2000, 0x3000))); 629 EXPECT_FALSE(Ranges.contains(AddressRange(0x2000, 0x3001))); 630 EXPECT_FALSE(Ranges.contains(AddressRange(0x3000, 0x3001))); 631 EXPECT_FALSE(Ranges.contains(AddressRange(0x1500, 0x4500))); 632 EXPECT_FALSE(Ranges.contains(AddressRange(0x5000, 0x5001))); 633 634 // Verify that intersecting ranges get combined 635 Ranges.clear(); 636 Ranges.insert(AddressRange(0x1100, 0x1F00)); 637 // Verify a wholy contained range that is added doesn't do anything. 638 Ranges.insert(AddressRange(0x1500, 0x1F00)); 639 EXPECT_EQ(Ranges.size(), 1u); 640 EXPECT_EQ(Ranges[0], AddressRange(0x1100, 0x1F00)); 641 642 // Verify a range that starts before and intersects gets combined. 643 Ranges.insert(AddressRange(0x1000, Ranges[0].Start + 1)); 644 EXPECT_EQ(Ranges.size(), 1u); 645 EXPECT_EQ(Ranges[0], AddressRange(0x1000, 0x1F00)); 646 647 // Verify a range that starts inside and extends ranges gets combined. 648 Ranges.insert(AddressRange(Ranges[0].End - 1, 0x2000)); 649 EXPECT_EQ(Ranges.size(), 1u); 650 EXPECT_EQ(Ranges[0], AddressRange(0x1000, 0x2000)); 651 652 // Verify that adjacent ranges don't get combined 653 Ranges.insert(AddressRange(0x2000, 0x3000)); 654 EXPECT_EQ(Ranges.size(), 2u); 655 EXPECT_EQ(Ranges[0], AddressRange(0x1000, 0x2000)); 656 EXPECT_EQ(Ranges[1], AddressRange(0x2000, 0x3000)); 657 // Verify if we add an address range that intersects two ranges 658 // that they get combined 659 Ranges.insert(AddressRange(Ranges[0].End - 1, Ranges[1].Start + 1)); 660 EXPECT_EQ(Ranges.size(), 1u); 661 EXPECT_EQ(Ranges[0], AddressRange(0x1000, 0x3000)); 662 663 Ranges.insert(AddressRange(0x3000, 0x4000)); 664 Ranges.insert(AddressRange(0x4000, 0x5000)); 665 Ranges.insert(AddressRange(0x2000, 0x4500)); 666 EXPECT_EQ(Ranges.size(), 1u); 667 EXPECT_EQ(Ranges[0], AddressRange(0x1000, 0x5000)); 668 } 669 670 TEST(GSYMTest, TestStringTable) { 671 StringTable StrTab(StringRef("\0Hello\0World\0", 13)); 672 // Test extracting strings from a string table. 673 EXPECT_EQ(StrTab.getString(0), ""); 674 EXPECT_EQ(StrTab.getString(1), "Hello"); 675 EXPECT_EQ(StrTab.getString(7), "World"); 676 EXPECT_EQ(StrTab.getString(8), "orld"); 677 // Test pointing to last NULL terminator gets empty string. 678 EXPECT_EQ(StrTab.getString(12), ""); 679 // Test pointing to past end gets empty string. 680 EXPECT_EQ(StrTab.getString(13), ""); 681 } 682 683 static void TestFileWriterHelper(llvm::support::endianness ByteOrder) { 684 SmallString<512> Str; 685 raw_svector_ostream OutStrm(Str); 686 FileWriter FW(OutStrm, ByteOrder); 687 const int64_t MinSLEB = INT64_MIN; 688 const int64_t MaxSLEB = INT64_MAX; 689 const uint64_t MinULEB = 0; 690 const uint64_t MaxULEB = UINT64_MAX; 691 const uint8_t U8 = 0x10; 692 const uint16_t U16 = 0x1122; 693 const uint32_t U32 = 0x12345678; 694 const uint64_t U64 = 0x33445566778899aa; 695 const char *Hello = "hello"; 696 FW.writeU8(U8); 697 FW.writeU16(U16); 698 FW.writeU32(U32); 699 FW.writeU64(U64); 700 FW.alignTo(16); 701 const off_t FixupOffset = FW.tell(); 702 FW.writeU32(0); 703 FW.writeSLEB(MinSLEB); 704 FW.writeSLEB(MaxSLEB); 705 FW.writeULEB(MinULEB); 706 FW.writeULEB(MaxULEB); 707 FW.writeNullTerminated(Hello); 708 // Test Seek, Tell using Fixup32. 709 FW.fixup32(U32, FixupOffset); 710 711 std::string Bytes(OutStrm.str()); 712 uint8_t AddressSize = 4; 713 DataExtractor Data(Bytes, ByteOrder == llvm::support::little, AddressSize); 714 uint64_t Offset = 0; 715 EXPECT_EQ(Data.getU8(&Offset), U8); 716 EXPECT_EQ(Data.getU16(&Offset), U16); 717 EXPECT_EQ(Data.getU32(&Offset), U32); 718 EXPECT_EQ(Data.getU64(&Offset), U64); 719 Offset = alignTo(Offset, 16); 720 EXPECT_EQ(Data.getU32(&Offset), U32); 721 EXPECT_EQ(Data.getSLEB128(&Offset), MinSLEB); 722 EXPECT_EQ(Data.getSLEB128(&Offset), MaxSLEB); 723 EXPECT_EQ(Data.getULEB128(&Offset), MinULEB); 724 EXPECT_EQ(Data.getULEB128(&Offset), MaxULEB); 725 EXPECT_EQ(Data.getCStrRef(&Offset), StringRef(Hello)); 726 } 727 728 TEST(GSYMTest, TestFileWriter) { 729 TestFileWriterHelper(llvm::support::little); 730 TestFileWriterHelper(llvm::support::big); 731 } 732 733 TEST(GSYMTest, TestAddressRangeEncodeDecode) { 734 // Test encoding and decoding AddressRange objects. AddressRange objects 735 // are always stored as offsets from the a base address. The base address 736 // is the FunctionInfo's base address for function level ranges, and is 737 // the base address of the parent range for subranges. 738 SmallString<512> Str; 739 raw_svector_ostream OutStrm(Str); 740 const auto ByteOrder = llvm::support::endian::system_endianness(); 741 FileWriter FW(OutStrm, ByteOrder); 742 const uint64_t BaseAddr = 0x1000; 743 const AddressRange Range1(0x1000, 0x1010); 744 const AddressRange Range2(0x1020, 0x1030); 745 Range1.encode(FW, BaseAddr); 746 Range2.encode(FW, BaseAddr); 747 std::string Bytes(OutStrm.str()); 748 uint8_t AddressSize = 4; 749 DataExtractor Data(Bytes, ByteOrder == llvm::support::little, AddressSize); 750 751 AddressRange DecodedRange1, DecodedRange2; 752 uint64_t Offset = 0; 753 DecodedRange1.decode(Data, BaseAddr, Offset); 754 DecodedRange2.decode(Data, BaseAddr, Offset); 755 EXPECT_EQ(Range1, DecodedRange1); 756 EXPECT_EQ(Range2, DecodedRange2); 757 } 758 759 static void TestAddressRangeEncodeDecodeHelper(const AddressRanges &Ranges, 760 const uint64_t BaseAddr) { 761 SmallString<512> Str; 762 raw_svector_ostream OutStrm(Str); 763 const auto ByteOrder = llvm::support::endian::system_endianness(); 764 FileWriter FW(OutStrm, ByteOrder); 765 Ranges.encode(FW, BaseAddr); 766 767 std::string Bytes(OutStrm.str()); 768 uint8_t AddressSize = 4; 769 DataExtractor Data(Bytes, ByteOrder == llvm::support::little, AddressSize); 770 771 AddressRanges DecodedRanges; 772 uint64_t Offset = 0; 773 DecodedRanges.decode(Data, BaseAddr, Offset); 774 EXPECT_EQ(Ranges, DecodedRanges); 775 } 776 777 TEST(GSYMTest, TestAddressRangesEncodeDecode) { 778 // Test encoding and decoding AddressRanges. AddressRanges objects contain 779 // ranges that are stored as offsets from the a base address. The base address 780 // is the FunctionInfo's base address for function level ranges, and is the 781 // base address of the parent range for subranges. 782 const uint64_t BaseAddr = 0x1000; 783 784 // Test encoding and decoding with no ranges. 785 AddressRanges Ranges; 786 TestAddressRangeEncodeDecodeHelper(Ranges, BaseAddr); 787 788 // Test encoding and decoding with 1 range. 789 Ranges.insert(AddressRange(0x1000, 0x1010)); 790 TestAddressRangeEncodeDecodeHelper(Ranges, BaseAddr); 791 792 // Test encoding and decoding with multiple ranges. 793 Ranges.insert(AddressRange(0x1020, 0x1030)); 794 Ranges.insert(AddressRange(0x1050, 0x1070)); 795 TestAddressRangeEncodeDecodeHelper(Ranges, BaseAddr); 796 } 797 798 static void TestLineTableHelper(llvm::support::endianness ByteOrder, 799 const LineTable <) { 800 SmallString<512> Str; 801 raw_svector_ostream OutStrm(Str); 802 FileWriter FW(OutStrm, ByteOrder); 803 const uint64_t BaseAddr = LT[0].Addr; 804 llvm::Error Err = LT.encode(FW, BaseAddr); 805 ASSERT_FALSE(Err); 806 std::string Bytes(OutStrm.str()); 807 uint8_t AddressSize = 4; 808 DataExtractor Data(Bytes, ByteOrder == llvm::support::little, AddressSize); 809 llvm::Expected<LineTable> Decoded = LineTable::decode(Data, BaseAddr); 810 // Make sure decoding succeeded. 811 ASSERT_TRUE((bool)Decoded); 812 // Make sure decoded object is the same as the one we encoded. 813 EXPECT_EQ(LT, Decoded.get()); 814 } 815 816 TEST(GSYMTest, TestLineTable) { 817 const uint64_t StartAddr = 0x1000; 818 const uint32_t FileIdx = 1; 819 LineTable LT; 820 LineEntry Line0(StartAddr+0x000, FileIdx, 10); 821 LineEntry Line1(StartAddr+0x010, FileIdx, 11); 822 LineEntry Line2(StartAddr+0x100, FileIdx, 1000); 823 ASSERT_TRUE(LT.empty()); 824 ASSERT_EQ(LT.size(), (size_t)0); 825 LT.push(Line0); 826 ASSERT_EQ(LT.size(), (size_t)1); 827 LT.push(Line1); 828 LT.push(Line2); 829 LT.push(LineEntry(StartAddr+0x120, FileIdx, 900)); 830 LT.push(LineEntry(StartAddr+0x120, FileIdx, 2000)); 831 LT.push(LineEntry(StartAddr+0x121, FileIdx, 2001)); 832 LT.push(LineEntry(StartAddr+0x122, FileIdx, 2002)); 833 LT.push(LineEntry(StartAddr+0x123, FileIdx, 2003)); 834 ASSERT_FALSE(LT.empty()); 835 ASSERT_EQ(LT.size(), (size_t)8); 836 // Test operator[]. 837 ASSERT_EQ(LT[0], Line0); 838 ASSERT_EQ(LT[1], Line1); 839 ASSERT_EQ(LT[2], Line2); 840 841 // Test encoding and decoding line tables. 842 TestLineTableHelper(llvm::support::little, LT); 843 TestLineTableHelper(llvm::support::big, LT); 844 845 // Verify the clear method works as expected. 846 LT.clear(); 847 ASSERT_TRUE(LT.empty()); 848 ASSERT_EQ(LT.size(), (size_t)0); 849 850 LineTable LT1; 851 LineTable LT2; 852 853 // Test that two empty line tables are equal and neither are less than 854 // each other. 855 ASSERT_EQ(LT1, LT2); 856 ASSERT_FALSE(LT1 < LT1); 857 ASSERT_FALSE(LT1 < LT2); 858 ASSERT_FALSE(LT2 < LT1); 859 ASSERT_FALSE(LT2 < LT2); 860 861 // Test that a line table with less number of line entries is less than a 862 // line table with more line entries and that they are not equal. 863 LT2.push(Line0); 864 ASSERT_LT(LT1, LT2); 865 ASSERT_NE(LT1, LT2); 866 867 // Test that two line tables with the same entries are equal. 868 LT1.push(Line0); 869 ASSERT_EQ(LT1, LT2); 870 ASSERT_FALSE(LT1 < LT2); 871 ASSERT_FALSE(LT2 < LT2); 872 } 873 874 static void TestLineTableDecodeError(llvm::support::endianness ByteOrder, 875 std::string Bytes, 876 const uint64_t BaseAddr, 877 std::string ExpectedErrorMsg) { 878 uint8_t AddressSize = 4; 879 DataExtractor Data(Bytes, ByteOrder == llvm::support::little, AddressSize); 880 llvm::Expected<LineTable> Decoded = LineTable::decode(Data, BaseAddr); 881 // Make sure decoding fails. 882 ASSERT_FALSE((bool)Decoded); 883 // Make sure decoded object is the same as the one we encoded. 884 checkError(ExpectedErrorMsg, Decoded.takeError()); 885 } 886 887 TEST(GSYMTest, TestLineTableDecodeErrors) { 888 // Test decoding InlineInfo objects that ensure we report an appropriate 889 // error message. 890 const llvm::support::endianness ByteOrder = llvm::support::little; 891 SmallString<512> Str; 892 raw_svector_ostream OutStrm(Str); 893 FileWriter FW(OutStrm, ByteOrder); 894 const uint64_t BaseAddr = 0x100; 895 TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr, 896 "0x00000000: missing LineTable MinDelta"); 897 FW.writeU8(1); // MinDelta (ULEB) 898 TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr, 899 "0x00000001: missing LineTable MaxDelta"); 900 FW.writeU8(10); // MaxDelta (ULEB) 901 TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr, 902 "0x00000002: missing LineTable FirstLine"); 903 FW.writeU8(20); // FirstLine (ULEB) 904 TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr, 905 "0x00000003: EOF found before EndSequence"); 906 // Test a SetFile with the argument missing from the stream 907 FW.writeU8(1); // SetFile opcode (uint8_t) 908 TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr, 909 "0x00000004: EOF found before SetFile value"); 910 FW.writeU8(5); // SetFile value as index (ULEB) 911 // Test a AdvancePC with the argument missing from the stream 912 FW.writeU8(2); // AdvancePC opcode (uint8_t) 913 TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr, 914 "0x00000006: EOF found before AdvancePC value"); 915 FW.writeU8(20); // AdvancePC value as offset (ULEB) 916 // Test a AdvancePC with the argument missing from the stream 917 FW.writeU8(3); // AdvanceLine opcode (uint8_t) 918 TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr, 919 "0x00000008: EOF found before AdvanceLine value"); 920 FW.writeU8(20); // AdvanceLine value as offset (LLEB) 921 } 922 923 TEST(GSYMTest, TestLineTableEncodeErrors) { 924 const uint64_t BaseAddr = 0x1000; 925 const uint32_t FileIdx = 1; 926 const llvm::support::endianness ByteOrder = llvm::support::little; 927 SmallString<512> Str; 928 raw_svector_ostream OutStrm(Str); 929 FileWriter FW(OutStrm, ByteOrder); 930 LineTable LT; 931 checkError("attempted to encode invalid LineTable object", 932 LT.encode(FW, BaseAddr)); 933 934 // Try to encode a line table where a line entry has an address that is less 935 // than BaseAddr and verify we get an appropriate error. 936 LineEntry Line0(BaseAddr+0x000, FileIdx, 10); 937 LineEntry Line1(BaseAddr+0x010, FileIdx, 11); 938 LT.push(Line0); 939 LT.push(Line1); 940 checkError("LineEntry has address 0x1000 which is less than the function " 941 "start address 0x1010", LT.encode(FW, BaseAddr+0x10)); 942 LT.clear(); 943 944 // Try to encode a line table where a line entries has an address that is less 945 // than BaseAddr and verify we get an appropriate error. 946 LT.push(Line1); 947 LT.push(Line0); 948 checkError("LineEntry in LineTable not in ascending order", 949 LT.encode(FW, BaseAddr)); 950 LT.clear(); 951 } 952 953 static void TestHeaderEncodeError(const Header &H, 954 std::string ExpectedErrorMsg) { 955 const support::endianness ByteOrder = llvm::support::little; 956 SmallString<512> Str; 957 raw_svector_ostream OutStrm(Str); 958 FileWriter FW(OutStrm, ByteOrder); 959 llvm::Error Err = H.encode(FW); 960 checkError(ExpectedErrorMsg, std::move(Err)); 961 } 962 963 static void TestHeaderDecodeError(std::string Bytes, 964 std::string ExpectedErrorMsg) { 965 const support::endianness ByteOrder = llvm::support::little; 966 uint8_t AddressSize = 4; 967 DataExtractor Data(Bytes, ByteOrder == llvm::support::little, AddressSize); 968 llvm::Expected<Header> Decoded = Header::decode(Data); 969 // Make sure decoding fails. 970 ASSERT_FALSE((bool)Decoded); 971 // Make sure decoded object is the same as the one we encoded. 972 checkError(ExpectedErrorMsg, Decoded.takeError()); 973 } 974 975 // Populate a GSYM header with valid values. 976 static void InitHeader(Header &H) { 977 H.Magic = GSYM_MAGIC; 978 H.Version = GSYM_VERSION; 979 H.AddrOffSize = 4; 980 H.UUIDSize = 16; 981 H.BaseAddress = 0x1000; 982 H.NumAddresses = 1; 983 H.StrtabOffset= 0x2000; 984 H.StrtabSize = 0x1000; 985 for (size_t i=0; i<GSYM_MAX_UUID_SIZE; ++i) { 986 if (i < H.UUIDSize) 987 H.UUID[i] = i; 988 else 989 H.UUID[i] = 0; 990 } 991 } 992 993 TEST(GSYMTest, TestHeaderEncodeErrors) { 994 Header H; 995 InitHeader(H); 996 H.Magic = 12; 997 TestHeaderEncodeError(H, "invalid GSYM magic 0x0000000c"); 998 InitHeader(H); 999 H.Version = 12; 1000 TestHeaderEncodeError(H, "unsupported GSYM version 12"); 1001 InitHeader(H); 1002 H.AddrOffSize = 12; 1003 TestHeaderEncodeError(H, "invalid address offset size 12"); 1004 InitHeader(H); 1005 H.UUIDSize = 128; 1006 TestHeaderEncodeError(H, "invalid UUID size 128"); 1007 } 1008 1009 TEST(GSYMTest, TestHeaderDecodeErrors) { 1010 const llvm::support::endianness ByteOrder = llvm::support::little; 1011 SmallString<512> Str; 1012 raw_svector_ostream OutStrm(Str); 1013 FileWriter FW(OutStrm, ByteOrder); 1014 Header H; 1015 InitHeader(H); 1016 llvm::Error Err = H.encode(FW); 1017 ASSERT_FALSE(Err); 1018 FW.fixup32(12, offsetof(Header, Magic)); 1019 TestHeaderDecodeError(OutStrm.str(), "invalid GSYM magic 0x0000000c"); 1020 FW.fixup32(GSYM_MAGIC, offsetof(Header, Magic)); 1021 FW.fixup32(12, offsetof(Header, Version)); 1022 TestHeaderDecodeError(OutStrm.str(), "unsupported GSYM version 12"); 1023 FW.fixup32(GSYM_VERSION, offsetof(Header, Version)); 1024 FW.fixup32(12, offsetof(Header, AddrOffSize)); 1025 TestHeaderDecodeError(OutStrm.str(), "invalid address offset size 12"); 1026 FW.fixup32(4, offsetof(Header, AddrOffSize)); 1027 FW.fixup32(128, offsetof(Header, UUIDSize)); 1028 TestHeaderDecodeError(OutStrm.str(), "invalid UUID size 128"); 1029 } 1030 1031 static void TestHeaderEncodeDecode(const Header &H, 1032 support::endianness ByteOrder) { 1033 uint8_t AddressSize = 4; 1034 SmallString<512> Str; 1035 raw_svector_ostream OutStrm(Str); 1036 FileWriter FW(OutStrm, ByteOrder); 1037 llvm::Error Err = H.encode(FW); 1038 ASSERT_FALSE(Err); 1039 std::string Bytes(OutStrm.str()); 1040 DataExtractor Data(Bytes, ByteOrder == llvm::support::little, AddressSize); 1041 llvm::Expected<Header> Decoded = Header::decode(Data); 1042 // Make sure decoding succeeded. 1043 ASSERT_TRUE((bool)Decoded); 1044 EXPECT_EQ(H, Decoded.get()); 1045 1046 } 1047 TEST(GSYMTest, TestHeaderEncodeDecode) { 1048 Header H; 1049 InitHeader(H); 1050 TestHeaderEncodeDecode(H, llvm::support::little); 1051 TestHeaderEncodeDecode(H, llvm::support::big); 1052 } 1053 1054 static void TestGsymCreatorEncodeError(llvm::support::endianness ByteOrder, 1055 const GsymCreator &GC, 1056 std::string ExpectedErrorMsg) { 1057 SmallString<512> Str; 1058 raw_svector_ostream OutStrm(Str); 1059 FileWriter FW(OutStrm, ByteOrder); 1060 llvm::Error Err = GC.encode(FW); 1061 ASSERT_TRUE(bool(Err)); 1062 checkError(ExpectedErrorMsg, std::move(Err)); 1063 } 1064 1065 TEST(GSYMTest, TestGsymCreatorEncodeErrors) { 1066 const uint8_t ValidUUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1067 14, 15, 16}; 1068 const uint8_t InvalidUUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1069 14, 15, 16, 17, 18, 19, 20, 21}; 1070 // Verify we get an error when trying to encode an GsymCreator with no 1071 // function infos. We shouldn't be saving a GSYM file in this case since 1072 // there is nothing inside of it. 1073 GsymCreator GC; 1074 TestGsymCreatorEncodeError(llvm::support::little, GC, 1075 "no functions to encode"); 1076 const uint64_t FuncAddr = 0x1000; 1077 const uint64_t FuncSize = 0x100; 1078 const uint32_t FuncName = GC.insertString("foo"); 1079 // Verify we get an error trying to encode a GsymCreator that isn't 1080 // finalized. 1081 GC.addFunctionInfo(FunctionInfo(FuncAddr, FuncSize, FuncName)); 1082 TestGsymCreatorEncodeError(llvm::support::little, GC, 1083 "GsymCreator wasn't finalized prior to encoding"); 1084 std::string finalizeIssues; 1085 raw_string_ostream OS(finalizeIssues); 1086 llvm::Error finalizeErr = GC.finalize(OS); 1087 ASSERT_FALSE(bool(finalizeErr)); 1088 finalizeErr = GC.finalize(OS); 1089 ASSERT_TRUE(bool(finalizeErr)); 1090 checkError("already finalized", std::move(finalizeErr)); 1091 // Verify we get an error trying to encode a GsymCreator with a UUID that is 1092 // too long. 1093 GC.setUUID(InvalidUUID); 1094 TestGsymCreatorEncodeError(llvm::support::little, GC, 1095 "invalid UUID size 21"); 1096 GC.setUUID(ValidUUID); 1097 // Verify errors are propagated when we try to encoding an invalid line 1098 // table. 1099 GC.forEachFunctionInfo([](FunctionInfo &FI) -> bool { 1100 FI.OptLineTable = LineTable(); // Invalid line table. 1101 return false; // Stop iterating 1102 }); 1103 TestGsymCreatorEncodeError(llvm::support::little, GC, 1104 "attempted to encode invalid LineTable object"); 1105 // Verify errors are propagated when we try to encoding an invalid inline 1106 // info. 1107 GC.forEachFunctionInfo([](FunctionInfo &FI) -> bool { 1108 FI.OptLineTable = llvm::None; 1109 FI.Inline = InlineInfo(); // Invalid InlineInfo. 1110 return false; // Stop iterating 1111 }); 1112 TestGsymCreatorEncodeError(llvm::support::little, GC, 1113 "attempted to encode invalid InlineInfo object"); 1114 } 1115 1116 static void Compare(const GsymCreator &GC, const GsymReader &GR) { 1117 // Verify that all of the data in a GsymCreator is correctly decoded from 1118 // a GsymReader. To do this, we iterator over 1119 GC.forEachFunctionInfo([&](const FunctionInfo &FI) -> bool { 1120 auto DecodedFI = GR.getFunctionInfo(FI.Range.Start); 1121 EXPECT_TRUE(bool(DecodedFI)); 1122 EXPECT_EQ(FI, *DecodedFI); 1123 return true; // Keep iterating over all FunctionInfo objects. 1124 }); 1125 } 1126 1127 static void TestEncodeDecode(const GsymCreator &GC, 1128 support::endianness ByteOrder, uint16_t Version, 1129 uint8_t AddrOffSize, uint64_t BaseAddress, 1130 uint32_t NumAddresses, ArrayRef<uint8_t> UUID) { 1131 SmallString<512> Str; 1132 raw_svector_ostream OutStrm(Str); 1133 FileWriter FW(OutStrm, ByteOrder); 1134 llvm::Error Err = GC.encode(FW); 1135 ASSERT_FALSE((bool)Err); 1136 Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str()); 1137 ASSERT_TRUE(bool(GR)); 1138 const Header &Hdr = GR->getHeader(); 1139 EXPECT_EQ(Hdr.Version, Version); 1140 EXPECT_EQ(Hdr.AddrOffSize, AddrOffSize); 1141 EXPECT_EQ(Hdr.UUIDSize, UUID.size()); 1142 EXPECT_EQ(Hdr.BaseAddress, BaseAddress); 1143 EXPECT_EQ(Hdr.NumAddresses, NumAddresses); 1144 EXPECT_EQ(ArrayRef<uint8_t>(Hdr.UUID, Hdr.UUIDSize), UUID); 1145 Compare(GC, GR.get()); 1146 } 1147 1148 TEST(GSYMTest, TestGsymCreator1ByteAddrOffsets) { 1149 uint8_t UUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; 1150 GsymCreator GC; 1151 GC.setUUID(UUID); 1152 constexpr uint64_t BaseAddr = 0x1000; 1153 constexpr uint8_t AddrOffSize = 1; 1154 const uint32_t Func1Name = GC.insertString("foo"); 1155 const uint32_t Func2Name = GC.insertString("bar"); 1156 GC.addFunctionInfo(FunctionInfo(BaseAddr+0x00, 0x10, Func1Name)); 1157 GC.addFunctionInfo(FunctionInfo(BaseAddr+0x20, 0x10, Func2Name)); 1158 Error Err = GC.finalize(llvm::nulls()); 1159 ASSERT_FALSE(Err); 1160 TestEncodeDecode(GC, llvm::support::little, 1161 GSYM_VERSION, 1162 AddrOffSize, 1163 BaseAddr, 1164 2, // NumAddresses 1165 ArrayRef<uint8_t>(UUID)); 1166 TestEncodeDecode(GC, llvm::support::big, 1167 GSYM_VERSION, 1168 AddrOffSize, 1169 BaseAddr, 1170 2, // NumAddresses 1171 ArrayRef<uint8_t>(UUID)); 1172 } 1173 1174 TEST(GSYMTest, TestGsymCreator2ByteAddrOffsets) { 1175 uint8_t UUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; 1176 GsymCreator GC; 1177 GC.setUUID(UUID); 1178 constexpr uint64_t BaseAddr = 0x1000; 1179 constexpr uint8_t AddrOffSize = 2; 1180 const uint32_t Func1Name = GC.insertString("foo"); 1181 const uint32_t Func2Name = GC.insertString("bar"); 1182 GC.addFunctionInfo(FunctionInfo(BaseAddr+0x000, 0x100, Func1Name)); 1183 GC.addFunctionInfo(FunctionInfo(BaseAddr+0x200, 0x100, Func2Name)); 1184 Error Err = GC.finalize(llvm::nulls()); 1185 ASSERT_FALSE(Err); 1186 TestEncodeDecode(GC, llvm::support::little, 1187 GSYM_VERSION, 1188 AddrOffSize, 1189 BaseAddr, 1190 2, // NumAddresses 1191 ArrayRef<uint8_t>(UUID)); 1192 TestEncodeDecode(GC, llvm::support::big, 1193 GSYM_VERSION, 1194 AddrOffSize, 1195 BaseAddr, 1196 2, // NumAddresses 1197 ArrayRef<uint8_t>(UUID)); 1198 } 1199 1200 TEST(GSYMTest, TestGsymCreator4ByteAddrOffsets) { 1201 uint8_t UUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; 1202 GsymCreator GC; 1203 GC.setUUID(UUID); 1204 constexpr uint64_t BaseAddr = 0x1000; 1205 constexpr uint8_t AddrOffSize = 4; 1206 const uint32_t Func1Name = GC.insertString("foo"); 1207 const uint32_t Func2Name = GC.insertString("bar"); 1208 GC.addFunctionInfo(FunctionInfo(BaseAddr+0x000, 0x100, Func1Name)); 1209 GC.addFunctionInfo(FunctionInfo(BaseAddr+0x20000, 0x100, Func2Name)); 1210 Error Err = GC.finalize(llvm::nulls()); 1211 ASSERT_FALSE(Err); 1212 TestEncodeDecode(GC, llvm::support::little, 1213 GSYM_VERSION, 1214 AddrOffSize, 1215 BaseAddr, 1216 2, // NumAddresses 1217 ArrayRef<uint8_t>(UUID)); 1218 TestEncodeDecode(GC, llvm::support::big, 1219 GSYM_VERSION, 1220 AddrOffSize, 1221 BaseAddr, 1222 2, // NumAddresses 1223 ArrayRef<uint8_t>(UUID)); 1224 } 1225 1226 TEST(GSYMTest, TestGsymCreator8ByteAddrOffsets) { 1227 uint8_t UUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; 1228 GsymCreator GC; 1229 GC.setUUID(UUID); 1230 constexpr uint64_t BaseAddr = 0x1000; 1231 constexpr uint8_t AddrOffSize = 8; 1232 const uint32_t Func1Name = GC.insertString("foo"); 1233 const uint32_t Func2Name = GC.insertString("bar"); 1234 GC.addFunctionInfo(FunctionInfo(BaseAddr+0x000, 0x100, Func1Name)); 1235 GC.addFunctionInfo(FunctionInfo(BaseAddr+0x100000000, 0x100, Func2Name)); 1236 Error Err = GC.finalize(llvm::nulls()); 1237 ASSERT_FALSE(Err); 1238 TestEncodeDecode(GC, llvm::support::little, 1239 GSYM_VERSION, 1240 AddrOffSize, 1241 BaseAddr, 1242 2, // NumAddresses 1243 ArrayRef<uint8_t>(UUID)); 1244 TestEncodeDecode(GC, llvm::support::big, 1245 GSYM_VERSION, 1246 AddrOffSize, 1247 BaseAddr, 1248 2, // NumAddresses 1249 ArrayRef<uint8_t>(UUID)); 1250 } 1251 1252 static void VerifyFunctionInfo(const GsymReader &GR, uint64_t Addr, 1253 const FunctionInfo &FI) { 1254 auto ExpFI = GR.getFunctionInfo(Addr); 1255 ASSERT_TRUE(bool(ExpFI)); 1256 ASSERT_EQ(FI, ExpFI.get()); 1257 } 1258 1259 static void VerifyFunctionInfoError(const GsymReader &GR, uint64_t Addr, 1260 std::string ErrMessage) { 1261 auto ExpFI = GR.getFunctionInfo(Addr); 1262 ASSERT_FALSE(bool(ExpFI)); 1263 checkError(ErrMessage, ExpFI.takeError()); 1264 } 1265 1266 TEST(GSYMTest, TestGsymReader) { 1267 uint8_t UUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; 1268 GsymCreator GC; 1269 GC.setUUID(UUID); 1270 constexpr uint64_t BaseAddr = 0x1000; 1271 constexpr uint64_t Func1Addr = BaseAddr; 1272 constexpr uint64_t Func2Addr = BaseAddr+0x20; 1273 constexpr uint64_t FuncSize = 0x10; 1274 const uint32_t Func1Name = GC.insertString("foo"); 1275 const uint32_t Func2Name = GC.insertString("bar"); 1276 const auto ByteOrder = support::endian::system_endianness(); 1277 GC.addFunctionInfo(FunctionInfo(Func1Addr, FuncSize, Func1Name)); 1278 GC.addFunctionInfo(FunctionInfo(Func2Addr, FuncSize, Func2Name)); 1279 Error FinalizeErr = GC.finalize(llvm::nulls()); 1280 ASSERT_FALSE(FinalizeErr); 1281 SmallString<512> Str; 1282 raw_svector_ostream OutStrm(Str); 1283 FileWriter FW(OutStrm, ByteOrder); 1284 llvm::Error Err = GC.encode(FW); 1285 ASSERT_FALSE((bool)Err); 1286 if (auto ExpectedGR = GsymReader::copyBuffer(OutStrm.str())) { 1287 const GsymReader &GR = ExpectedGR.get(); 1288 VerifyFunctionInfoError(GR, Func1Addr-1, "address 0xfff not in GSYM"); 1289 1290 FunctionInfo Func1(Func1Addr, FuncSize, Func1Name); 1291 VerifyFunctionInfo(GR, Func1Addr, Func1); 1292 VerifyFunctionInfo(GR, Func1Addr+1, Func1); 1293 VerifyFunctionInfo(GR, Func1Addr+FuncSize-1, Func1); 1294 VerifyFunctionInfoError(GR, Func1Addr+FuncSize, 1295 "address 0x1010 not in GSYM"); 1296 VerifyFunctionInfoError(GR, Func2Addr-1, "address 0x101f not in GSYM"); 1297 FunctionInfo Func2(Func2Addr, FuncSize, Func2Name); 1298 VerifyFunctionInfo(GR, Func2Addr, Func2); 1299 VerifyFunctionInfo(GR, Func2Addr+1, Func2); 1300 VerifyFunctionInfo(GR, Func2Addr+FuncSize-1, Func2); 1301 VerifyFunctionInfoError(GR, Func2Addr+FuncSize, 1302 "address 0x1030 not in GSYM"); 1303 } 1304 } 1305