brintos

brintos / llvm-project-archived public Read only

0
0
Text · 195.1 KiB · d560073 Raw
5088 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/ADT/DenseMap.h"10#include "llvm/ADT/SmallString.h"11#include "llvm/DebugInfo/DWARF/DWARFContext.h"12#include "llvm/DebugInfo/GSYM/DwarfTransformer.h"13#include "llvm/DebugInfo/GSYM/ExtractRanges.h"14#include "llvm/DebugInfo/GSYM/FileEntry.h"15#include "llvm/DebugInfo/GSYM/FileWriter.h"16#include "llvm/DebugInfo/GSYM/FunctionInfo.h"17#include "llvm/DebugInfo/GSYM/GsymCreator.h"18#include "llvm/DebugInfo/GSYM/GsymReader.h"19#include "llvm/DebugInfo/GSYM/Header.h"20#include "llvm/DebugInfo/GSYM/InlineInfo.h"21#include "llvm/DebugInfo/GSYM/OutputAggregator.h"22#include "llvm/DebugInfo/GSYM/StringTable.h"23#include "llvm/ObjectYAML/DWARFEmitter.h"24#include "llvm/Support/DataExtractor.h"25#include "llvm/Testing/Support/Error.h"26 27#include "gtest/gtest.h"28#include "gmock/gmock.h"29#include <string>30 31using namespace llvm;32using namespace gsym;33 34void 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 StringRef41        // properly.42        EXPECT_EQ(Actual.message(), ExpectedMsgs[WhichMsg++]);43      });44  EXPECT_EQ(WhichMsg, ExpectedMsgs.size());45  EXPECT_FALSE(Remaining);46}47 48void checkError(std::string ExpectedMsg, Error Err) {49  checkError(ArrayRef<std::string>{ExpectedMsg}, std::move(Err));50}51TEST(GSYMTest, TestFileEntry) {52  // Make sure default constructed GSYM FileEntry has zeroes in the53  // 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 works59  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 84TEST(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 == operator112  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 FunctionInfo132  // structs from a variety of sources: symtab, debug info, runtime info133  // and we sort them and want the sorting to allow us to quickly get the134  // 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 one140  // that has name, size and any number of line table entries141  EXPECT_LT(FISymtab, FIWithLines);142 143  // Test that if we have a function info without inline info and one with144  // that the one without inline info is less than the one with.145  FunctionInfo FIWithInlines = FISymtab;146  FIWithInlines.Inline = InlineInfo();147  FIWithInlines.Inline->Ranges.insert(148      AddressRange(StartAddr, StartAddr + 0x10));149  EXPECT_LT(FISymtab, FIWithInlines);150 151  // Test that if we have a function info with inline entries and one more152  // inline entries that the one with fewer inline functins is less than the153  // one with more.154  FunctionInfo FIWithMoreInlines = FIWithInlines;155  FIWithMoreInlines.Inline->Children.push_back(InlineInfo());156  EXPECT_LT(FIWithInlines, FIWithMoreInlines);157 158  FunctionInfo FIWithLinesAndInline = FIWithLines;159  FIWithLinesAndInline.Inline = InlineInfo();160  FIWithLinesAndInline.Inline->Ranges.insert(161      AddressRange(StartAddr, StartAddr + 0x10));162  // Test that a FunctionInfo with name, size, and line entries is less than163  // the same one with valid inline info164  EXPECT_LT(FIWithLines, FIWithLinesAndInline);165 166  // Test if we have an entry with lines and one with more lines for the same167  // range, the ones with more lines is greater than the one with less.168  FunctionInfo FIWithMoreLines = FIWithLines;169  FIWithMoreLines.OptLineTable->push(LineEntry(StartAddr,FileIdx,Line+5));170  EXPECT_LT(FIWithLines, FIWithMoreLines);171 172  // Test that if we have the same number of lines we compare the line entries173  // in the FunctionInfo.OptLineTable.Lines vector.174  FunctionInfo FIWithLinesWithHigherAddress = FIWithLines;175  FIWithLinesWithHigherAddress.OptLineTable->get(0).Addr += 0x10;176  EXPECT_LT(FIWithLines, FIWithLinesWithHigherAddress);177}178 179static void TestFunctionInfoDecodeError(llvm::endianness ByteOrder,180                                        StringRef Bytes,181                                        const uint64_t BaseAddr,182                                        std::string ExpectedErrorMsg) {183  uint8_t AddressSize = 4;184  DataExtractor Data(Bytes, ByteOrder == llvm::endianness::little, AddressSize);185  llvm::Expected<FunctionInfo> Decoded = FunctionInfo::decode(Data, BaseAddr);186  // Make sure decoding fails.187  ASSERT_FALSE((bool)Decoded);188  // Make sure decoded object is the same as the one we encoded.189  checkError(ExpectedErrorMsg, Decoded.takeError());190}191 192TEST(GSYMTest, TestFunctionInfoDecodeErrors) {193  // Test decoding FunctionInfo objects that ensure we report an appropriate194  // error message.195  const llvm::endianness ByteOrder = llvm::endianness::little;196  SmallString<512> Str;197  raw_svector_ostream OutStrm(Str);198  FileWriter FW(OutStrm, ByteOrder);199  const uint64_t BaseAddr = 0x100;200  TestFunctionInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,201      "0x00000000: missing FunctionInfo Size");202  FW.writeU32(0x100); // Function size.203  TestFunctionInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,204      "0x00000004: missing FunctionInfo Name");205  // Write out an invalid Name string table offset of zero.206  FW.writeU32(0);207  TestFunctionInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,208      "0x00000004: invalid FunctionInfo Name value 0x00000000");209  // Modify the Name to be 0x00000001, which is a valid value.210  FW.fixup32(0x00000001, 4);211  TestFunctionInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,212      "0x00000008: missing FunctionInfo InfoType value");213  auto FixupOffset = FW.tell();214  FW.writeU32(1); // InfoType::LineTableInfo.215  TestFunctionInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,216      "0x0000000c: missing FunctionInfo InfoType length");217  FW.fixup32(7, FixupOffset); // Write an invalid InfoType enumeration value218  FW.writeU32(0); // LineTableInfo InfoType data length.219  TestFunctionInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,220                              "0x00000008: unsupported InfoType 7");221}222 223static void TestFunctionInfoEncodeError(llvm::endianness ByteOrder,224                                        const FunctionInfo &FI,225                                        std::string ExpectedErrorMsg) {226  SmallString<512> Str;227  raw_svector_ostream OutStrm(Str);228  FileWriter FW(OutStrm, ByteOrder);229  Expected<uint64_t> ExpectedOffset = FI.encode(FW);230  ASSERT_FALSE(ExpectedOffset);231  checkError(ExpectedErrorMsg, ExpectedOffset.takeError());232}233 234TEST(GSYMTest, TestFunctionInfoEncodeErrors) {235  const uint64_t FuncAddr = 0x1000;236  const uint64_t FuncSize = 0x100;237  const uint32_t InvalidName = 0;238  const uint32_t ValidName = 1;239  FunctionInfo InvalidNameFI(FuncAddr, FuncSize, InvalidName);240  TestFunctionInfoEncodeError(241      llvm::endianness::little, InvalidNameFI,242      "attempted to encode invalid FunctionInfo object");243 244  FunctionInfo InvalidLineTableFI(FuncAddr, FuncSize, ValidName);245  // Empty line tables are not valid. Verify if the encoding of anything246  // in our line table fails, that we see get the error propagated.247  InvalidLineTableFI.OptLineTable = LineTable();248  TestFunctionInfoEncodeError(llvm::endianness::little, InvalidLineTableFI,249                              "attempted to encode invalid LineTable object");250 251  FunctionInfo InvalidInlineInfoFI(FuncAddr, FuncSize, ValidName);252  // Empty line tables are not valid. Verify if the encoding of anything253  // in our line table fails, that we see get the error propagated.254  InvalidInlineInfoFI.Inline = InlineInfo();255  TestFunctionInfoEncodeError(llvm::endianness::little, InvalidInlineInfoFI,256                              "attempted to encode invalid InlineInfo object");257}258 259static void TestFunctionInfoEncodeDecode(llvm::endianness ByteOrder,260                                         const FunctionInfo &FI) {261  // Test encoding and decoding FunctionInfo objects.262  SmallString<512> Str;263  raw_svector_ostream OutStrm(Str);264  FileWriter FW(OutStrm, ByteOrder);265  llvm::Expected<uint64_t> ExpectedOffset = FI.encode(FW);266  ASSERT_TRUE(bool(ExpectedOffset));267  // Verify we got the encoded offset back from the encode function.268  ASSERT_EQ(ExpectedOffset.get(), 0ULL);269  std::string Bytes(OutStrm.str());270  uint8_t AddressSize = 4;271  DataExtractor Data(Bytes, ByteOrder == llvm::endianness::little, AddressSize);272  llvm::Expected<FunctionInfo> Decoded =273      FunctionInfo::decode(Data, FI.Range.start());274  // Make sure decoding succeeded.275  ASSERT_TRUE((bool)Decoded);276  // Make sure decoded object is the same as the one we encoded.277  EXPECT_EQ(FI, Decoded.get());278}279 280static void AddLines(uint64_t FuncAddr, uint32_t FileIdx, FunctionInfo &FI) {281    FI.OptLineTable = LineTable();282    LineEntry Line0(FuncAddr + 0x000, FileIdx, 10);283    LineEntry Line1(FuncAddr + 0x010, FileIdx, 11);284    LineEntry Line2(FuncAddr + 0x100, FileIdx, 1000);285    FI.OptLineTable->push(Line0);286    FI.OptLineTable->push(Line1);287    FI.OptLineTable->push(Line2);288}289 290 291static void AddInline(uint64_t FuncAddr, uint64_t FuncSize, FunctionInfo &FI) {292    FI.Inline = InlineInfo();293    FI.Inline->Ranges.insert(AddressRange(FuncAddr, FuncAddr + FuncSize));294    InlineInfo Inline1;295    Inline1.Ranges.insert(AddressRange(FuncAddr + 0x10, FuncAddr + 0x30));296    Inline1.Name = 1;297    Inline1.CallFile = 1;298    Inline1.CallLine = 11;299    FI.Inline->Children.push_back(Inline1);300}301 302TEST(GSYMTest, TestFunctionInfoEncoding) {303  constexpr uint64_t FuncAddr = 0x1000;304  constexpr uint64_t FuncSize = 0x100;305  constexpr uint32_t FuncName = 1;306  constexpr uint32_t FileIdx = 1;307  // Make sure that we can encode and decode a FunctionInfo with no line table308  // or inline info.309  FunctionInfo FI(FuncAddr, FuncSize, FuncName);310  TestFunctionInfoEncodeDecode(llvm::endianness::little, FI);311  TestFunctionInfoEncodeDecode(llvm::endianness::big, FI);312 313  // Make sure that we can encode and decode a FunctionInfo with a line table314  // and no inline info.315  FunctionInfo FILines(FuncAddr, FuncSize, FuncName);316  AddLines(FuncAddr, FileIdx, FILines);317  TestFunctionInfoEncodeDecode(llvm::endianness::little, FILines);318  TestFunctionInfoEncodeDecode(llvm::endianness::big, FILines);319 320  // Make sure that we can encode and decode a FunctionInfo with no line table321  // and with inline info.322  FunctionInfo FIInline(FuncAddr, FuncSize, FuncName);323  AddInline(FuncAddr, FuncSize, FIInline);324  TestFunctionInfoEncodeDecode(llvm::endianness::little, FIInline);325  TestFunctionInfoEncodeDecode(llvm::endianness::big, FIInline);326 327  // Make sure that we can encode and decode a FunctionInfo with no line table328  // and with inline info.329  FunctionInfo FIBoth(FuncAddr, FuncSize, FuncName);330  AddLines(FuncAddr, FileIdx, FIBoth);331  AddInline(FuncAddr, FuncSize, FIBoth);332  TestFunctionInfoEncodeDecode(llvm::endianness::little, FIBoth);333  TestFunctionInfoEncodeDecode(llvm::endianness::big, FIBoth);334}335 336static void TestInlineInfoEncodeDecode(llvm::endianness ByteOrder,337                                       const InlineInfo &Inline) {338  // Test encoding and decoding InlineInfo objects339  SmallString<512> Str;340  raw_svector_ostream OutStrm(Str);341  FileWriter FW(OutStrm, ByteOrder);342  const uint64_t BaseAddr = Inline.Ranges[0].start();343  llvm::Error Err = Inline.encode(FW, BaseAddr);344  ASSERT_FALSE(Err);345  std::string Bytes(OutStrm.str());346  uint8_t AddressSize = 4;347  DataExtractor Data(Bytes, ByteOrder == llvm::endianness::little, AddressSize);348  llvm::Expected<InlineInfo> Decoded = InlineInfo::decode(Data, BaseAddr);349  // Make sure decoding succeeded.350  ASSERT_TRUE((bool)Decoded);351  // Make sure decoded object is the same as the one we encoded.352  EXPECT_EQ(Inline, Decoded.get());353}354 355static void TestInlineInfoDecodeError(llvm::endianness ByteOrder,356                                      StringRef Bytes, const uint64_t BaseAddr,357                                      std::string ExpectedErrorMsg) {358  uint8_t AddressSize = 4;359  DataExtractor Data(Bytes, ByteOrder == llvm::endianness::little, AddressSize);360  llvm::Expected<InlineInfo> Decoded = InlineInfo::decode(Data, BaseAddr);361  // Make sure decoding fails.362  ASSERT_FALSE((bool)Decoded);363  // Make sure decoded object is the same as the one we encoded.364  checkError(ExpectedErrorMsg, Decoded.takeError());365}366 367static void TestInlineInfoEncodeError(llvm::endianness ByteOrder,368                                      const InlineInfo &Inline,369                                      std::string ExpectedErrorMsg) {370  SmallString<512> Str;371  raw_svector_ostream OutStrm(Str);372  FileWriter FW(OutStrm, ByteOrder);373  const uint64_t BaseAddr =374      Inline.Ranges.empty() ? 0 : Inline.Ranges[0].start();375  llvm::Error Err = Inline.encode(FW, BaseAddr);376  checkError(ExpectedErrorMsg, std::move(Err));377}378 379TEST(GSYMTest, TestInlineInfo) {380  // Test InlineInfo structs.381  InlineInfo II;382  EXPECT_FALSE(II.isValid());383  II.Ranges.insert(AddressRange(0x1000, 0x2000));384  // Make sure InlineInfo in valid with just an address range since385  // top level InlineInfo objects have ranges with no name, call file386  // or call line387  EXPECT_TRUE(II.isValid());388  // Make sure InlineInfo isn't after being cleared.389  II.clear();390  EXPECT_FALSE(II.isValid());391 392  // Create an InlineInfo that contains the following data. The393  // indentation of the address range indicates the parent child394  // relationships of the InlineInfo objects:395  //396  // Variable    Range and values397  // =========== ====================================================398  // Root        [0x100-0x200) (no name, file, or line)399  // Inline1       [0x150-0x160) Name = 1, File = 1, Line = 11400  // Inline1Sub1     [0x152-0x155) Name = 2, File = 2, Line = 22401  // Inline1Sub2     [0x157-0x158) Name = 3, File = 3, Line = 33402  InlineInfo Root;403  Root.Ranges.insert(AddressRange(0x100, 0x200));404  InlineInfo Inline1;405  Inline1.Ranges.insert(AddressRange(0x150, 0x160));406  Inline1.Name = 1;407  Inline1.CallFile = 1;408  Inline1.CallLine = 11;409  InlineInfo Inline1Sub1;410  Inline1Sub1.Ranges.insert(AddressRange(0x152, 0x155));411  Inline1Sub1.Name = 2;412  Inline1Sub1.CallFile = 2;413  Inline1Sub1.CallLine = 22;414  InlineInfo Inline1Sub2;415  Inline1Sub2.Ranges.insert(AddressRange(0x157, 0x158));416  Inline1Sub2.Name = 3;417  Inline1Sub2.CallFile = 3;418  Inline1Sub2.CallLine = 33;419  Inline1.Children.push_back(Inline1Sub1);420  Inline1.Children.push_back(Inline1Sub2);421  Root.Children.push_back(Inline1);422 423  // Make sure an address that is out of range won't match424  EXPECT_FALSE(Root.getInlineStack(0x50));425 426  // Verify that we get no inline stacks for addresses out of [0x100-0x200)427  EXPECT_FALSE(Root.getInlineStack(Root.Ranges[0].start() - 1));428  EXPECT_FALSE(Root.getInlineStack(Root.Ranges[0].end()));429 430  // Verify we get no inline stack entries for addresses that are in431  // [0x100-0x200) but not in [0x150-0x160)432  EXPECT_FALSE(Root.getInlineStack(Inline1.Ranges[0].start() - 1));433  EXPECT_FALSE(Root.getInlineStack(Inline1.Ranges[0].end()));434 435  // Verify we get one inline stack entry for addresses that are in436  // [[0x150-0x160)) but not in [0x152-0x155) or [0x157-0x158)437  auto InlineInfos = Root.getInlineStack(Inline1.Ranges[0].start());438  ASSERT_TRUE(InlineInfos);439  ASSERT_EQ(InlineInfos->size(), 1u);440  ASSERT_EQ(*InlineInfos->at(0), Inline1);441  InlineInfos = Root.getInlineStack(Inline1.Ranges[0].end() - 1);442  EXPECT_TRUE(InlineInfos);443  ASSERT_EQ(InlineInfos->size(), 1u);444  ASSERT_EQ(*InlineInfos->at(0), Inline1);445 446  // Verify we get two inline stack entries for addresses that are in447  // [0x152-0x155)448  InlineInfos = Root.getInlineStack(Inline1Sub1.Ranges[0].start());449  EXPECT_TRUE(InlineInfos);450  ASSERT_EQ(InlineInfos->size(), 2u);451  ASSERT_EQ(*InlineInfos->at(0), Inline1Sub1);452  ASSERT_EQ(*InlineInfos->at(1), Inline1);453  InlineInfos = Root.getInlineStack(Inline1Sub1.Ranges[0].end() - 1);454  EXPECT_TRUE(InlineInfos);455  ASSERT_EQ(InlineInfos->size(), 2u);456  ASSERT_EQ(*InlineInfos->at(0), Inline1Sub1);457  ASSERT_EQ(*InlineInfos->at(1), Inline1);458 459  // Verify we get two inline stack entries for addresses that are in460  // [0x157-0x158)461  InlineInfos = Root.getInlineStack(Inline1Sub2.Ranges[0].start());462  EXPECT_TRUE(InlineInfos);463  ASSERT_EQ(InlineInfos->size(), 2u);464  ASSERT_EQ(*InlineInfos->at(0), Inline1Sub2);465  ASSERT_EQ(*InlineInfos->at(1), Inline1);466  InlineInfos = Root.getInlineStack(Inline1Sub2.Ranges[0].end() - 1);467  EXPECT_TRUE(InlineInfos);468  ASSERT_EQ(InlineInfos->size(), 2u);469  ASSERT_EQ(*InlineInfos->at(0), Inline1Sub2);470  ASSERT_EQ(*InlineInfos->at(1), Inline1);471 472  // Test encoding and decoding InlineInfo objects473  TestInlineInfoEncodeDecode(llvm::endianness::little, Root);474  TestInlineInfoEncodeDecode(llvm::endianness::big, Root);475}476 477TEST(GSYMTest, TestInlineInfoEncodeErrors) {478  // Test InlineInfo encoding errors.479 480  // Test that we get an error when trying to encode an InlineInfo object481  // that has no ranges.482  InlineInfo Empty;483  std::string EmptyErr("attempted to encode invalid InlineInfo object");484  TestInlineInfoEncodeError(llvm::endianness::little, Empty, EmptyErr);485  TestInlineInfoEncodeError(llvm::endianness::big, Empty, EmptyErr);486 487  // Verify that we get an error trying to encode an InlineInfo object that has488  // a child InlineInfo that has no ranges.489  InlineInfo ContainsEmpty;490  ContainsEmpty.Ranges.insert({0x100, 0x200});491  ContainsEmpty.Children.push_back(Empty);492  TestInlineInfoEncodeError(llvm::endianness::little, ContainsEmpty, EmptyErr);493  TestInlineInfoEncodeError(llvm::endianness::big, ContainsEmpty, EmptyErr);494 495  // Verify that we get an error trying to encode an InlineInfo object that has496  // a child whose address range is not contained in the parent address range.497  InlineInfo ChildNotContained;498  std::string ChildNotContainedErr("child range not contained in parent");499  ChildNotContained.Ranges.insert({0x100, 0x200});500  InlineInfo ChildNotContainedChild;501  ChildNotContainedChild.Ranges.insert({0x200, 0x300});502  ChildNotContained.Children.push_back(ChildNotContainedChild);503  TestInlineInfoEncodeError(llvm::endianness::little, ChildNotContained,504                            ChildNotContainedErr);505  TestInlineInfoEncodeError(llvm::endianness::big, ChildNotContained,506                            ChildNotContainedErr);507}508 509TEST(GSYMTest, TestInlineInfoDecodeErrors) {510  // Test decoding InlineInfo objects that ensure we report an appropriate511  // error message.512  const llvm::endianness ByteOrder = llvm::endianness::little;513  SmallString<512> Str;514  raw_svector_ostream OutStrm(Str);515  FileWriter FW(OutStrm, ByteOrder);516  const uint64_t BaseAddr = 0x100;517  TestInlineInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,518      "0x00000000: missing InlineInfo address ranges data");519  AddressRanges Ranges;520  Ranges.insert({BaseAddr, BaseAddr+0x100});521  encodeRanges(Ranges, FW, BaseAddr);522  TestInlineInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,523      "0x00000004: missing InlineInfo uint8_t indicating children");524  FW.writeU8(0);525  TestInlineInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,526      "0x00000005: missing InlineInfo uint32_t for name");527  FW.writeU32(0);528  TestInlineInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,529      "0x00000009: missing ULEB128 for InlineInfo call file");530  FW.writeU8(0);531  TestInlineInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,532      "0x0000000a: missing ULEB128 for InlineInfo call line");533}534 535TEST(GSYMTest, TestLineEntry) {536  // test llvm::gsym::LineEntry structs.537  const uint64_t ValidAddr = 0x1000;538  const uint64_t InvalidFileIdx = 0;539  const uint32_t ValidFileIdx = 1;540  const uint32_t ValidLine = 5;541 542  LineEntry Invalid;543  EXPECT_FALSE(Invalid.isValid());544  // Make sure that an entry is invalid if it has a bad file index.545  LineEntry BadFile(ValidAddr, InvalidFileIdx, ValidLine);546  EXPECT_FALSE(BadFile.isValid());547  // Test operators548  LineEntry E1(ValidAddr, ValidFileIdx, ValidLine);549  LineEntry E2(ValidAddr, ValidFileIdx, ValidLine);550  LineEntry DifferentAddr(ValidAddr + 1, ValidFileIdx, ValidLine);551  LineEntry DifferentFile(ValidAddr, ValidFileIdx + 1, ValidLine);552  LineEntry DifferentLine(ValidAddr, ValidFileIdx, ValidLine + 1);553  EXPECT_TRUE(E1.isValid());554  EXPECT_EQ(E1, E2);555  EXPECT_NE(E1, DifferentAddr);556  EXPECT_NE(E1, DifferentFile);557  EXPECT_NE(E1, DifferentLine);558  EXPECT_LT(E1, DifferentAddr);559}560 561TEST(GSYMTest, TestStringTable) {562  StringTable StrTab(StringRef("\0Hello\0World\0", 13));563  // Test extracting strings from a string table.564  EXPECT_EQ(StrTab.getString(0), "");565  EXPECT_EQ(StrTab.getString(1), "Hello");566  EXPECT_EQ(StrTab.getString(7), "World");567  EXPECT_EQ(StrTab.getString(8), "orld");568  // Test pointing to last NULL terminator gets empty string.569  EXPECT_EQ(StrTab.getString(12), "");570  // Test pointing to past end gets empty string.571  EXPECT_EQ(StrTab.getString(13), "");572}573 574static void TestFileWriterHelper(llvm::endianness ByteOrder) {575  SmallString<512> Str;576  raw_svector_ostream OutStrm(Str);577  FileWriter FW(OutStrm, ByteOrder);578  const int64_t MinSLEB = INT64_MIN;579  const int64_t MaxSLEB = INT64_MAX;580  const uint64_t MinULEB = 0;581  const uint64_t MaxULEB = UINT64_MAX;582  const uint8_t U8 = 0x10;583  const uint16_t U16 = 0x1122;584  const uint32_t U32 = 0x12345678;585  const uint64_t U64 = 0x33445566778899aa;586  const char *Hello = "hello";587  FW.writeU8(U8);588  FW.writeU16(U16);589  FW.writeU32(U32);590  FW.writeU64(U64);591  FW.alignTo(16);592  const off_t FixupOffset = FW.tell();593  FW.writeU32(0);594  FW.writeSLEB(MinSLEB);595  FW.writeSLEB(MaxSLEB);596  FW.writeULEB(MinULEB);597  FW.writeULEB(MaxULEB);598  FW.writeNullTerminated(Hello);599  // Test Seek, Tell using Fixup32.600  FW.fixup32(U32, FixupOffset);601 602  std::string Bytes(OutStrm.str());603  uint8_t AddressSize = 4;604  DataExtractor Data(Bytes, ByteOrder == llvm::endianness::little, AddressSize);605  uint64_t Offset = 0;606  EXPECT_EQ(Data.getU8(&Offset), U8);607  EXPECT_EQ(Data.getU16(&Offset), U16);608  EXPECT_EQ(Data.getU32(&Offset), U32);609  EXPECT_EQ(Data.getU64(&Offset), U64);610  Offset = alignTo(Offset, 16);611  EXPECT_EQ(Data.getU32(&Offset), U32);612  EXPECT_EQ(Data.getSLEB128(&Offset), MinSLEB);613  EXPECT_EQ(Data.getSLEB128(&Offset), MaxSLEB);614  EXPECT_EQ(Data.getULEB128(&Offset), MinULEB);615  EXPECT_EQ(Data.getULEB128(&Offset), MaxULEB);616  EXPECT_EQ(Data.getCStrRef(&Offset), StringRef(Hello));617}618 619TEST(GSYMTest, TestFileWriter) {620  TestFileWriterHelper(llvm::endianness::little);621  TestFileWriterHelper(llvm::endianness::big);622}623 624TEST(GSYMTest, TestAddressRangeEncodeDecode) {625  // Test encoding and decoding AddressRange objects. AddressRange objects626  // are always stored as offsets from the a base address. The base address627  // is the FunctionInfo's base address for function level ranges, and is628  // the base address of the parent range for subranges.629  SmallString<512> Str;630  raw_svector_ostream OutStrm(Str);631  const auto ByteOrder = llvm::endianness::native;632  FileWriter FW(OutStrm, ByteOrder);633  const uint64_t BaseAddr = 0x1000;634  const AddressRange Range1(0x1000, 0x1010);635  const AddressRange Range2(0x1020, 0x1030);636  encodeRange(Range1, FW, BaseAddr);637  encodeRange(Range2, FW, BaseAddr);638  std::string Bytes(OutStrm.str());639  uint8_t AddressSize = 4;640  DataExtractor Data(Bytes, ByteOrder == llvm::endianness::little, AddressSize);641 642  AddressRange DecodedRange1, DecodedRange2;643  uint64_t Offset = 0;644  DecodedRange1 = decodeRange(Data, BaseAddr, Offset);645  DecodedRange2 = decodeRange(Data, BaseAddr, Offset);646  EXPECT_EQ(Range1, DecodedRange1);647  EXPECT_EQ(Range2, DecodedRange2);648}649 650static void TestAddressRangeEncodeDecodeHelper(const AddressRanges &Ranges,651                                               const uint64_t BaseAddr) {652  SmallString<512> Str;653  raw_svector_ostream OutStrm(Str);654  const auto ByteOrder = llvm::endianness::native;655  FileWriter FW(OutStrm, ByteOrder);656  encodeRanges(Ranges, FW, BaseAddr);657 658  std::string Bytes(OutStrm.str());659  uint8_t AddressSize = 4;660  DataExtractor Data(Bytes, ByteOrder == llvm::endianness::little, AddressSize);661 662  AddressRanges DecodedRanges;663  uint64_t Offset = 0;664  decodeRanges(DecodedRanges, Data, BaseAddr, Offset);665  EXPECT_EQ(Ranges, DecodedRanges);666}667 668TEST(GSYMTest, TestAddressRangesEncodeDecode) {669  // Test encoding and decoding AddressRanges. AddressRanges objects contain670  // ranges that are stored as offsets from the a base address. The base address671  // is the FunctionInfo's base address for function level ranges, and is the672  // base address of the parent range for subranges.673  const uint64_t BaseAddr = 0x1000;674 675  // Test encoding and decoding with no ranges.676  AddressRanges Ranges;677  TestAddressRangeEncodeDecodeHelper(Ranges, BaseAddr);678 679  // Test encoding and decoding with 1 range.680  Ranges.insert(AddressRange(0x1000, 0x1010));681  TestAddressRangeEncodeDecodeHelper(Ranges, BaseAddr);682 683  // Test encoding and decoding with multiple ranges.684  Ranges.insert(AddressRange(0x1020, 0x1030));685  Ranges.insert(AddressRange(0x1050, 0x1070));686  TestAddressRangeEncodeDecodeHelper(Ranges, BaseAddr);687}688 689static void TestLineTableHelper(llvm::endianness ByteOrder,690                                const LineTable &LT) {691  SmallString<512> Str;692  raw_svector_ostream OutStrm(Str);693  FileWriter FW(OutStrm, ByteOrder);694  const uint64_t BaseAddr = LT[0].Addr;695  llvm::Error Err = LT.encode(FW, BaseAddr);696  ASSERT_FALSE(Err);697  std::string Bytes(OutStrm.str());698  uint8_t AddressSize = 4;699  DataExtractor Data(Bytes, ByteOrder == llvm::endianness::little, AddressSize);700  llvm::Expected<LineTable> Decoded = LineTable::decode(Data, BaseAddr);701  // Make sure decoding succeeded.702  ASSERT_TRUE((bool)Decoded);703  // Make sure decoded object is the same as the one we encoded.704  EXPECT_EQ(LT, Decoded.get());705}706 707TEST(GSYMTest, TestLineTable) {708  const uint64_t StartAddr = 0x1000;709  const uint32_t FileIdx = 1;710  LineTable LT;711  LineEntry Line0(StartAddr+0x000, FileIdx, 10);712  LineEntry Line1(StartAddr+0x010, FileIdx, 11);713  LineEntry Line2(StartAddr+0x100, FileIdx, 1000);714  ASSERT_TRUE(LT.empty());715  ASSERT_EQ(LT.size(), (size_t)0);716  LT.push(Line0);717  ASSERT_EQ(LT.size(), (size_t)1);718  LT.push(Line1);719  LT.push(Line2);720  LT.push(LineEntry(StartAddr+0x120, FileIdx, 900));721  LT.push(LineEntry(StartAddr+0x120, FileIdx, 2000));722  LT.push(LineEntry(StartAddr+0x121, FileIdx, 2001));723  LT.push(LineEntry(StartAddr+0x122, FileIdx, 2002));724  LT.push(LineEntry(StartAddr+0x123, FileIdx, 2003));725  ASSERT_FALSE(LT.empty());726  ASSERT_EQ(LT.size(), (size_t)8);727  // Test operator[].728  ASSERT_EQ(LT[0], Line0);729  ASSERT_EQ(LT[1], Line1);730  ASSERT_EQ(LT[2], Line2);731 732  // Test encoding and decoding line tables.733  TestLineTableHelper(llvm::endianness::little, LT);734  TestLineTableHelper(llvm::endianness::big, LT);735 736  // Verify the clear method works as expected.737  LT.clear();738  ASSERT_TRUE(LT.empty());739  ASSERT_EQ(LT.size(), (size_t)0);740 741  LineTable LT1;742  LineTable LT2;743 744  // Test that two empty line tables are equal and neither are less than745  // each other.746  ASSERT_EQ(LT1, LT2);747  ASSERT_FALSE(LT1 < LT1);748  ASSERT_FALSE(LT1 < LT2);749  ASSERT_FALSE(LT2 < LT1);750  ASSERT_FALSE(LT2 < LT2);751 752  // Test that a line table with less number of line entries is less than a753  // line table with more line entries and that they are not equal.754  LT2.push(Line0);755  ASSERT_LT(LT1, LT2);756  ASSERT_NE(LT1, LT2);757 758  // Test that two line tables with the same entries are equal.759  LT1.push(Line0);760  ASSERT_EQ(LT1, LT2);761  ASSERT_FALSE(LT1 < LT2);762  ASSERT_FALSE(LT2 < LT2);763}764 765static void TestLineTableDecodeError(llvm::endianness ByteOrder,766                                     StringRef Bytes, const uint64_t BaseAddr,767                                     std::string ExpectedErrorMsg) {768  uint8_t AddressSize = 4;769  DataExtractor Data(Bytes, ByteOrder == llvm::endianness::little, AddressSize);770  llvm::Expected<LineTable> Decoded = LineTable::decode(Data, BaseAddr);771  // Make sure decoding fails.772  ASSERT_FALSE((bool)Decoded);773  // Make sure decoded object is the same as the one we encoded.774  checkError(ExpectedErrorMsg, Decoded.takeError());775}776 777TEST(GSYMTest, TestLineTableDecodeErrors) {778  // Test decoding InlineInfo objects that ensure we report an appropriate779  // error message.780  const llvm::endianness ByteOrder = llvm::endianness::little;781  SmallString<512> Str;782  raw_svector_ostream OutStrm(Str);783  FileWriter FW(OutStrm, ByteOrder);784  const uint64_t BaseAddr = 0x100;785  TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr,786      "0x00000000: missing LineTable MinDelta");787  FW.writeU8(1); // MinDelta (ULEB)788  TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr,789      "0x00000001: missing LineTable MaxDelta");790  FW.writeU8(10); // MaxDelta (ULEB)791  TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr,792      "0x00000002: missing LineTable FirstLine");793  FW.writeU8(20); // FirstLine (ULEB)794  TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr,795      "0x00000003: EOF found before EndSequence");796  // Test a SetFile with the argument missing from the stream797  FW.writeU8(1); // SetFile opcode (uint8_t)798  TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr,799      "0x00000004: EOF found before SetFile value");800  FW.writeU8(5); // SetFile value as index (ULEB)801  // Test a AdvancePC with the argument missing from the stream802  FW.writeU8(2); // AdvancePC opcode (uint8_t)803  TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr,804      "0x00000006: EOF found before AdvancePC value");805  FW.writeU8(20); // AdvancePC value as offset (ULEB)806  // Test a AdvancePC with the argument missing from the stream807  FW.writeU8(3); // AdvanceLine opcode (uint8_t)808  TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr,809      "0x00000008: EOF found before AdvanceLine value");810  FW.writeU8(20); // AdvanceLine value as offset (LLEB)811}812 813TEST(GSYMTest, TestLineTableEncodeErrors) {814  const uint64_t BaseAddr = 0x1000;815  const uint32_t FileIdx = 1;816  const llvm::endianness ByteOrder = llvm::endianness::little;817  SmallString<512> Str;818  raw_svector_ostream OutStrm(Str);819  FileWriter FW(OutStrm, ByteOrder);820  LineTable LT;821  checkError("attempted to encode invalid LineTable object",822             LT.encode(FW, BaseAddr));823 824  // Try to encode a line table where a line entry has an address that is less825  // than BaseAddr and verify we get an appropriate error.826  LineEntry Line0(BaseAddr+0x000, FileIdx, 10);827  LineEntry Line1(BaseAddr+0x010, FileIdx, 11);828  LT.push(Line0);829  LT.push(Line1);830  checkError("LineEntry has address 0x1000 which is less than the function "831             "start address 0x1010", LT.encode(FW, BaseAddr+0x10));832  LT.clear();833 834  // Try to encode a line table where a line entries  has an address that is less835  // than BaseAddr and verify we get an appropriate error.836  LT.push(Line1);837  LT.push(Line0);838  checkError("LineEntry in LineTable not in ascending order",839             LT.encode(FW, BaseAddr));840  LT.clear();841}842 843static void TestHeaderEncodeError(const Header &H,844                                  std::string ExpectedErrorMsg) {845  const llvm::endianness ByteOrder = llvm::endianness::little;846  SmallString<512> Str;847  raw_svector_ostream OutStrm(Str);848  FileWriter FW(OutStrm, ByteOrder);849  llvm::Error Err = H.encode(FW);850  checkError(ExpectedErrorMsg, std::move(Err));851}852 853static void TestHeaderDecodeError(StringRef Bytes,854                                  std::string ExpectedErrorMsg) {855  const llvm::endianness ByteOrder = llvm::endianness::little;856  uint8_t AddressSize = 4;857  DataExtractor Data(Bytes, ByteOrder == llvm::endianness::little, AddressSize);858  llvm::Expected<Header> Decoded = Header::decode(Data);859  // Make sure decoding fails.860  ASSERT_FALSE((bool)Decoded);861  // Make sure decoded object is the same as the one we encoded.862  checkError(ExpectedErrorMsg, Decoded.takeError());863}864 865// Populate a GSYM header with valid values.866static void InitHeader(Header &H) {867  H.Magic = GSYM_MAGIC;868  H.Version = GSYM_VERSION;869  H.AddrOffSize = 4;870  H.UUIDSize = 16;871  H.BaseAddress = 0x1000;872  H.NumAddresses = 1;873  H.StrtabOffset= 0x2000;874  H.StrtabSize = 0x1000;875  for (size_t i=0; i<GSYM_MAX_UUID_SIZE; ++i) {876    if (i < H.UUIDSize)877      H.UUID[i] = i;878    else879      H.UUID[i] = 0;880  }881}882 883TEST(GSYMTest, TestHeaderEncodeErrors) {884  Header H;885  InitHeader(H);886  H.Magic = 12;887  TestHeaderEncodeError(H, "invalid GSYM magic 0x0000000c");888  InitHeader(H);889  H.Version = 12;890  TestHeaderEncodeError(H, "unsupported GSYM version 12");891  InitHeader(H);892  H.AddrOffSize = 12;893  TestHeaderEncodeError(H, "invalid address offset size 12");894  InitHeader(H);895  H.UUIDSize = 128;896  TestHeaderEncodeError(H, "invalid UUID size 128");897}898 899TEST(GSYMTest, TestHeaderDecodeErrors) {900  const llvm::endianness ByteOrder = llvm::endianness::little;901  SmallString<512> Str;902  raw_svector_ostream OutStrm(Str);903  FileWriter FW(OutStrm, ByteOrder);904  Header H;905  InitHeader(H);906  llvm::Error Err = H.encode(FW);907  ASSERT_FALSE(Err);908  FW.fixup32(12, offsetof(Header, Magic));909  TestHeaderDecodeError(OutStrm.str(), "invalid GSYM magic 0x0000000c");910  FW.fixup32(GSYM_MAGIC, offsetof(Header, Magic));911  FW.fixup32(12, offsetof(Header, Version));912  TestHeaderDecodeError(OutStrm.str(), "unsupported GSYM version 12");913  FW.fixup32(GSYM_VERSION, offsetof(Header, Version));914  FW.fixup32(12, offsetof(Header, AddrOffSize));915  TestHeaderDecodeError(OutStrm.str(), "invalid address offset size 12");916  FW.fixup32(4, offsetof(Header, AddrOffSize));917  FW.fixup32(128, offsetof(Header, UUIDSize));918  TestHeaderDecodeError(OutStrm.str(), "invalid UUID size 128");919}920 921static void TestHeaderEncodeDecode(const Header &H,922                                   llvm::endianness ByteOrder) {923  uint8_t AddressSize = 4;924  SmallString<512> Str;925  raw_svector_ostream OutStrm(Str);926  FileWriter FW(OutStrm, ByteOrder);927  llvm::Error Err = H.encode(FW);928  ASSERT_FALSE(Err);929  std::string Bytes(OutStrm.str());930  DataExtractor Data(Bytes, ByteOrder == llvm::endianness::little, AddressSize);931  llvm::Expected<Header> Decoded = Header::decode(Data);932  // Make sure decoding succeeded.933  ASSERT_TRUE((bool)Decoded);934  EXPECT_EQ(H, Decoded.get());935}936TEST(GSYMTest, TestHeaderEncodeDecode) {937  Header H;938  InitHeader(H);939  TestHeaderEncodeDecode(H, llvm::endianness::little);940  TestHeaderEncodeDecode(H, llvm::endianness::big);941}942 943static void TestGsymCreatorEncodeError(llvm::endianness ByteOrder,944                                       const GsymCreator &GC,945                                       std::string ExpectedErrorMsg) {946  SmallString<512> Str;947  raw_svector_ostream OutStrm(Str);948  FileWriter FW(OutStrm, ByteOrder);949  llvm::Error Err = GC.encode(FW);950  ASSERT_TRUE(bool(Err));951  checkError(ExpectedErrorMsg, std::move(Err));952}953 954TEST(GSYMTest, TestGsymCreatorEncodeErrors) {955  const uint8_t ValidUUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,956                               14, 15, 16};957  const uint8_t InvalidUUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,958                                 14, 15, 16, 17, 18, 19, 20, 21};959  // Verify we get an error when trying to encode an GsymCreator with no960  // function infos. We shouldn't be saving a GSYM file in this case since961  // there is nothing inside of it.962  GsymCreator GC;963  TestGsymCreatorEncodeError(llvm::endianness::little, GC,964                             "no functions to encode");965  const uint64_t FuncAddr = 0x1000;966  const uint64_t FuncSize = 0x100;967  const uint32_t FuncName = GC.insertString("foo");968  // Verify we get an error trying to encode a GsymCreator that isn't969  // finalized.970  GC.addFunctionInfo(FunctionInfo(FuncAddr, FuncSize, FuncName));971  TestGsymCreatorEncodeError(llvm::endianness::little, GC,972                             "GsymCreator wasn't finalized prior to encoding");973  std::string finalizeIssues;974  raw_string_ostream OS(finalizeIssues);975  OutputAggregator Agg(&OS);976  llvm::Error finalizeErr = GC.finalize(Agg);977  ASSERT_FALSE(bool(finalizeErr));978  finalizeErr = GC.finalize(Agg);979  ASSERT_TRUE(bool(finalizeErr));980  checkError("already finalized", std::move(finalizeErr));981  // Verify we get an error trying to encode a GsymCreator with a UUID that is982  // too long.983  GC.setUUID(InvalidUUID);984  TestGsymCreatorEncodeError(llvm::endianness::little, GC,985                             "invalid UUID size 21");986  GC.setUUID(ValidUUID);987  // Verify errors are propagated when we try to encoding an invalid line988  // table.989  GC.forEachFunctionInfo([](FunctionInfo &FI) -> bool {990    FI.OptLineTable = LineTable(); // Invalid line table.991    return false; // Stop iterating992  });993  TestGsymCreatorEncodeError(llvm::endianness::little, GC,994                             "attempted to encode invalid LineTable object");995  // Verify errors are propagated when we try to encoding an invalid inline996  // info.997  GC.forEachFunctionInfo([](FunctionInfo &FI) -> bool {998    FI.OptLineTable = std::nullopt;999    FI.Inline = InlineInfo(); // Invalid InlineInfo.1000    return false; // Stop iterating1001  });1002  TestGsymCreatorEncodeError(llvm::endianness::little, GC,1003                             "attempted to encode invalid InlineInfo object");1004}1005 1006static void Compare(const GsymCreator &GC, const GsymReader &GR) {1007  // Verify that all of the data in a GsymCreator is correctly decoded from1008  // a GsymReader. To do this, we iterator over1009  GC.forEachFunctionInfo([&](const FunctionInfo &FI) -> bool {1010    auto DecodedFI = GR.getFunctionInfo(FI.Range.start());1011    EXPECT_TRUE(bool(DecodedFI));1012    EXPECT_EQ(FI, *DecodedFI);1013    return true; // Keep iterating over all FunctionInfo objects.1014  });1015}1016 1017static void TestEncodeDecode(const GsymCreator &GC, llvm::endianness ByteOrder,1018                             uint16_t Version, uint8_t AddrOffSize,1019                             uint64_t BaseAddress, uint32_t NumAddresses,1020                             ArrayRef<uint8_t> UUID) {1021  SmallString<512> Str;1022  raw_svector_ostream OutStrm(Str);1023  FileWriter FW(OutStrm, ByteOrder);1024  llvm::Error Err = GC.encode(FW);1025  ASSERT_FALSE((bool)Err);1026  Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());1027  ASSERT_TRUE(bool(GR));1028  const Header &Hdr = GR->getHeader();1029  EXPECT_EQ(Hdr.Version, Version);1030  EXPECT_EQ(Hdr.AddrOffSize, AddrOffSize);1031  EXPECT_EQ(Hdr.UUIDSize, UUID.size());1032  EXPECT_EQ(Hdr.BaseAddress, BaseAddress);1033  EXPECT_EQ(Hdr.NumAddresses, NumAddresses);1034  EXPECT_EQ(ArrayRef<uint8_t>(Hdr.UUID, Hdr.UUIDSize), UUID);1035  Compare(GC, GR.get());1036}1037 1038TEST(GSYMTest, TestGsymCreator1ByteAddrOffsets) {1039  uint8_t UUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};1040  GsymCreator GC;1041  GC.setUUID(UUID);1042  constexpr uint64_t BaseAddr = 0x1000;1043  constexpr uint8_t AddrOffSize = 1;1044  const uint32_t Func1Name = GC.insertString("foo");1045  const uint32_t Func2Name = GC.insertString("bar");1046  GC.addFunctionInfo(FunctionInfo(BaseAddr+0x00, 0x10, Func1Name));1047  GC.addFunctionInfo(FunctionInfo(BaseAddr+0x20, 0x10, Func2Name));1048  OutputAggregator Null(nullptr);1049  Error Err = GC.finalize(Null);1050  ASSERT_FALSE(Err);1051  TestEncodeDecode(GC, llvm::endianness::little, GSYM_VERSION, AddrOffSize,1052                   BaseAddr,1053                   2, // NumAddresses1054                   ArrayRef<uint8_t>(UUID));1055  TestEncodeDecode(GC, llvm::endianness::big, GSYM_VERSION, AddrOffSize,1056                   BaseAddr,1057                   2, // NumAddresses1058                   ArrayRef<uint8_t>(UUID));1059}1060 1061TEST(GSYMTest, TestGsymCreator2ByteAddrOffsets) {1062  uint8_t UUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};1063  GsymCreator GC;1064  GC.setUUID(UUID);1065  constexpr uint64_t BaseAddr = 0x1000;1066  constexpr uint8_t AddrOffSize = 2;1067  const uint32_t Func1Name = GC.insertString("foo");1068  const uint32_t Func2Name = GC.insertString("bar");1069  GC.addFunctionInfo(FunctionInfo(BaseAddr+0x000, 0x100, Func1Name));1070  GC.addFunctionInfo(FunctionInfo(BaseAddr+0x200, 0x100, Func2Name));1071  OutputAggregator Null(nullptr);1072  Error Err = GC.finalize(Null);1073  ASSERT_FALSE(Err);1074  TestEncodeDecode(GC, llvm::endianness::little, GSYM_VERSION, AddrOffSize,1075                   BaseAddr,1076                   2, // NumAddresses1077                   ArrayRef<uint8_t>(UUID));1078  TestEncodeDecode(GC, llvm::endianness::big, GSYM_VERSION, AddrOffSize,1079                   BaseAddr,1080                   2, // NumAddresses1081                   ArrayRef<uint8_t>(UUID));1082}1083 1084TEST(GSYMTest, TestGsymCreator4ByteAddrOffsets) {1085  uint8_t UUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};1086  GsymCreator GC;1087  GC.setUUID(UUID);1088  constexpr uint64_t BaseAddr = 0x1000;1089  constexpr uint8_t AddrOffSize = 4;1090  const uint32_t Func1Name = GC.insertString("foo");1091  const uint32_t Func2Name = GC.insertString("bar");1092  GC.addFunctionInfo(FunctionInfo(BaseAddr+0x000, 0x100, Func1Name));1093  GC.addFunctionInfo(FunctionInfo(BaseAddr+0x20000, 0x100, Func2Name));1094  OutputAggregator Null(nullptr);1095  Error Err = GC.finalize(Null);1096  ASSERT_FALSE(Err);1097  TestEncodeDecode(GC, llvm::endianness::little, GSYM_VERSION, AddrOffSize,1098                   BaseAddr,1099                   2, // NumAddresses1100                   ArrayRef<uint8_t>(UUID));1101  TestEncodeDecode(GC, llvm::endianness::big, GSYM_VERSION, AddrOffSize,1102                   BaseAddr,1103                   2, // NumAddresses1104                   ArrayRef<uint8_t>(UUID));1105}1106 1107TEST(GSYMTest, TestGsymCreator8ByteAddrOffsets) {1108  uint8_t UUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};1109  GsymCreator GC;1110  GC.setUUID(UUID);1111  constexpr uint64_t BaseAddr = 0x1000;1112  constexpr uint8_t AddrOffSize = 8;1113  const uint32_t Func1Name = GC.insertString("foo");1114  const uint32_t Func2Name = GC.insertString("bar");1115  GC.addFunctionInfo(FunctionInfo(BaseAddr+0x000, 0x100, Func1Name));1116  GC.addFunctionInfo(FunctionInfo(BaseAddr+0x100000000, 0x100, Func2Name));1117  OutputAggregator Null(nullptr);1118  Error Err = GC.finalize(Null);1119  ASSERT_FALSE(Err);1120  TestEncodeDecode(GC, llvm::endianness::little, GSYM_VERSION, AddrOffSize,1121                   BaseAddr,1122                   2, // NumAddresses1123                   ArrayRef<uint8_t>(UUID));1124  TestEncodeDecode(GC, llvm::endianness::big, GSYM_VERSION, AddrOffSize,1125                   BaseAddr,1126                   2, // NumAddresses1127                   ArrayRef<uint8_t>(UUID));1128}1129 1130static void VerifyFunctionInfo(const GsymReader &GR, uint64_t Addr,1131                               const FunctionInfo &FI) {1132  auto ExpFI = GR.getFunctionInfo(Addr);1133  ASSERT_THAT_EXPECTED(ExpFI, Succeeded());1134  ASSERT_EQ(FI, ExpFI.get());1135}1136 1137static void VerifyFunctionInfoError(const GsymReader &GR, uint64_t Addr,1138                                    std::string ErrMessage) {1139  auto ExpFI = GR.getFunctionInfo(Addr);1140  ASSERT_FALSE(bool(ExpFI));1141  checkError(ErrMessage, ExpFI.takeError());1142}1143 1144TEST(GSYMTest, TestGsymReader) {1145  uint8_t UUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};1146  GsymCreator GC;1147  GC.setUUID(UUID);1148  constexpr uint64_t BaseAddr = 0x1000;1149  constexpr uint64_t Func1Addr = BaseAddr;1150  constexpr uint64_t Func2Addr = BaseAddr+0x20;1151  constexpr uint64_t FuncSize = 0x10;1152  const uint32_t Func1Name = GC.insertString("foo");1153  const uint32_t Func2Name = GC.insertString("bar");1154  const auto ByteOrder = llvm::endianness::native;1155  GC.addFunctionInfo(FunctionInfo(Func1Addr, FuncSize, Func1Name));1156  GC.addFunctionInfo(FunctionInfo(Func2Addr, FuncSize, Func2Name));1157  OutputAggregator Null(nullptr);1158  Error FinalizeErr = GC.finalize(Null);1159  ASSERT_FALSE(FinalizeErr);1160  SmallString<512> Str;1161  raw_svector_ostream OutStrm(Str);1162  FileWriter FW(OutStrm, ByteOrder);1163  llvm::Error Err = GC.encode(FW);1164  ASSERT_FALSE((bool)Err);1165  if (auto ExpectedGR = GsymReader::copyBuffer(OutStrm.str())) {1166    const GsymReader &GR = ExpectedGR.get();1167    VerifyFunctionInfoError(GR, Func1Addr-1, "address 0xfff is not in GSYM");1168 1169    FunctionInfo Func1(Func1Addr, FuncSize, Func1Name);1170    VerifyFunctionInfo(GR, Func1Addr, Func1);1171    VerifyFunctionInfo(GR, Func1Addr+1, Func1);1172    VerifyFunctionInfo(GR, Func1Addr+FuncSize-1, Func1);1173    VerifyFunctionInfoError(GR, Func1Addr+FuncSize,1174                            "address 0x1010 is not in GSYM");1175    VerifyFunctionInfoError(GR, Func2Addr-1, "address 0x101f is not in GSYM");1176    FunctionInfo Func2(Func2Addr, FuncSize, Func2Name);1177    VerifyFunctionInfo(GR, Func2Addr, Func2);1178    VerifyFunctionInfo(GR, Func2Addr+1, Func2);1179    VerifyFunctionInfo(GR, Func2Addr+FuncSize-1, Func2);1180    VerifyFunctionInfoError(GR, Func2Addr+FuncSize,1181                            "address 0x1030 is not in GSYM");1182  }1183}1184 1185TEST(GSYMTest, TestGsymLookups) {1186  // Test creating a GSYM file with a function that has a inline information.1187  // Verify that lookups work correctly. Lookups do not decode the entire1188  // FunctionInfo or InlineInfo, they only extract information needed for the1189  // lookup to happen which avoids allocations which can slow down1190  // symbolication.1191  GsymCreator GC;1192  FunctionInfo FI(0x1000, 0x100, GC.insertString("main"));1193  const auto ByteOrder = llvm::endianness::native;1194  FI.OptLineTable = LineTable();1195  const uint32_t MainFileIndex = GC.insertFile("/tmp/main.c");1196  const uint32_t FooFileIndex = GC.insertFile("/tmp/foo.h");1197  FI.OptLineTable->push(LineEntry(0x1000, MainFileIndex, 5));1198  FI.OptLineTable->push(LineEntry(0x1010, FooFileIndex, 10));1199  FI.OptLineTable->push(LineEntry(0x1012, FooFileIndex, 20));1200  FI.OptLineTable->push(LineEntry(0x1014, FooFileIndex, 11));1201  FI.OptLineTable->push(LineEntry(0x1016, FooFileIndex, 30));1202  FI.OptLineTable->push(LineEntry(0x1018, FooFileIndex, 12));1203  FI.OptLineTable->push(LineEntry(0x1020, MainFileIndex, 8));1204  FI.Inline = InlineInfo();1205 1206  FI.Inline->Name = GC.insertString("inline1");1207  FI.Inline->CallFile = MainFileIndex;1208  FI.Inline->CallLine = 6;1209  FI.Inline->Ranges.insert(AddressRange(0x1010, 0x1020));1210  InlineInfo Inline2;1211  Inline2.Name = GC.insertString("inline2");1212  Inline2.CallFile = FooFileIndex;1213  Inline2.CallLine = 33;1214  Inline2.Ranges.insert(AddressRange(0x1012, 0x1014));1215  FI.Inline->Children.emplace_back(Inline2);1216  InlineInfo Inline3;1217  Inline3.Name = GC.insertString("inline3");1218  Inline3.CallFile = FooFileIndex;1219  Inline3.CallLine = 35;1220  Inline3.Ranges.insert(AddressRange(0x1016, 0x1018));1221  FI.Inline->Children.emplace_back(Inline3);1222  GC.addFunctionInfo(std::move(FI));1223  OutputAggregator Null(nullptr);1224  Error FinalizeErr = GC.finalize(Null);1225  ASSERT_FALSE(FinalizeErr);1226  SmallString<512> Str;1227  raw_svector_ostream OutStrm(Str);1228  FileWriter FW(OutStrm, ByteOrder);1229  llvm::Error Err = GC.encode(FW);1230  ASSERT_FALSE((bool)Err);1231  Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());1232  ASSERT_TRUE(bool(GR));1233 1234  // Verify inline info is correct when doing lookups.1235  auto LR = GR->lookup(0x1000);1236  ASSERT_THAT_EXPECTED(LR, Succeeded());1237  EXPECT_THAT(LR->Locations,1238    testing::ElementsAre(SourceLocation{"main", "/tmp", "main.c", 5}));1239  LR = GR->lookup(0x100F);1240  ASSERT_THAT_EXPECTED(LR, Succeeded());1241  EXPECT_THAT(LR->Locations,1242    testing::ElementsAre(SourceLocation{"main", "/tmp", "main.c", 5, 15}));1243 1244  LR = GR->lookup(0x1010);1245  ASSERT_THAT_EXPECTED(LR, Succeeded());1246 1247  EXPECT_THAT(LR->Locations,1248    testing::ElementsAre(SourceLocation{"inline1", "/tmp", "foo.h", 10},1249                         SourceLocation{"main", "/tmp", "main.c", 6, 16}));1250 1251  LR = GR->lookup(0x1012);1252  ASSERT_THAT_EXPECTED(LR, Succeeded());1253  EXPECT_THAT(LR->Locations,1254    testing::ElementsAre(SourceLocation{"inline2", "/tmp", "foo.h", 20},1255                         SourceLocation{"inline1", "/tmp", "foo.h", 33, 2},1256                         SourceLocation{"main", "/tmp", "main.c", 6, 18}));1257 1258  LR = GR->lookup(0x1014);1259  ASSERT_THAT_EXPECTED(LR, Succeeded());1260  EXPECT_THAT(LR->Locations,1261    testing::ElementsAre(SourceLocation{"inline1", "/tmp", "foo.h", 11, 4},1262                         SourceLocation{"main", "/tmp", "main.c", 6, 20}));1263 1264  LR = GR->lookup(0x1016);1265  ASSERT_THAT_EXPECTED(LR, Succeeded());1266  EXPECT_THAT(LR->Locations,1267    testing::ElementsAre(SourceLocation{"inline3", "/tmp", "foo.h", 30},1268                         SourceLocation{"inline1", "/tmp", "foo.h", 35, 6},1269                         SourceLocation{"main", "/tmp", "main.c", 6, 22}));1270 1271  LR = GR->lookup(0x1018);1272  ASSERT_THAT_EXPECTED(LR, Succeeded());1273  EXPECT_THAT(LR->Locations,1274    testing::ElementsAre(SourceLocation{"inline1", "/tmp", "foo.h", 12, 8},1275                         SourceLocation{"main", "/tmp", "main.c", 6, 24}));1276 1277  LR = GR->lookup(0x1020);1278  ASSERT_THAT_EXPECTED(LR, Succeeded());1279  EXPECT_THAT(LR->Locations,1280    testing::ElementsAre(SourceLocation{"main", "/tmp", "main.c", 8, 32}));1281}1282 1283 1284TEST(GSYMTest, TestDWARFFunctionWithAddresses) {1285  // Create a single compile unit with a single function and make sure it gets1286  // converted to DWARF correctly. The function's address range is in where1287  // DW_AT_low_pc and DW_AT_high_pc are both addresses.1288  StringRef yamldata = R"(1289  debug_str:1290    - ''1291    - /tmp/main.c1292    - main1293  debug_abbrev:1294    - Table:1295        - Code:            0x000000011296          Tag:             DW_TAG_compile_unit1297          Children:        DW_CHILDREN_yes1298          Attributes:1299            - Attribute:       DW_AT_name1300              Form:            DW_FORM_strp1301            - Attribute:       DW_AT_low_pc1302              Form:            DW_FORM_addr1303            - Attribute:       DW_AT_high_pc1304              Form:            DW_FORM_addr1305            - Attribute:       DW_AT_language1306              Form:            DW_FORM_data21307        - Code:            0x000000021308          Tag:             DW_TAG_subprogram1309          Children:        DW_CHILDREN_no1310          Attributes:1311            - Attribute:       DW_AT_name1312              Form:            DW_FORM_strp1313            - Attribute:       DW_AT_low_pc1314              Form:            DW_FORM_addr1315            - Attribute:       DW_AT_high_pc1316              Form:            DW_FORM_addr1317  debug_info:1318    - Version:         41319      AddrSize:        81320      Entries:1321        - AbbrCode:        0x000000011322          Values:1323            - Value:           0x00000000000000011324            - Value:           0x00000000000010001325            - Value:           0x00000000000020001326            - Value:           0x00000000000000041327        - AbbrCode:        0x000000021328          Values:1329            - Value:           0x000000000000000D1330            - Value:           0x00000000000010001331            - Value:           0x00000000000020001332        - AbbrCode:        0x000000001333  )";1334  auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);1335  ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());1336  std::unique_ptr<DWARFContext> DwarfContext =1337      DWARFContext::create(*ErrOrSections, 8);1338  ASSERT_TRUE(DwarfContext.get() != nullptr);1339  auto &OS = llvm::nulls();1340  OutputAggregator OSAgg(&OS);1341  GsymCreator GC;1342  DwarfTransformer DT(*DwarfContext, GC);1343  const uint32_t ThreadCount = 1;1344  ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());1345  ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());1346  SmallString<512> Str;1347  raw_svector_ostream OutStrm(Str);1348  const auto ByteOrder = llvm::endianness::native;1349  FileWriter FW(OutStrm, ByteOrder);1350  ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());1351  Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());1352  ASSERT_THAT_EXPECTED(GR, Succeeded());1353  // There should only be one function in our GSYM.1354  EXPECT_EQ(GR->getNumAddresses(), 1u);1355  auto ExpFI = GR->getFunctionInfo(0x1000);1356  ASSERT_THAT_EXPECTED(ExpFI, Succeeded());1357  ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x2000));1358  EXPECT_FALSE(ExpFI->OptLineTable.has_value());1359  EXPECT_FALSE(ExpFI->Inline.has_value());1360}1361 1362TEST(GSYMTest, TestDWARFFunctionWithAddressAndOffset) {1363  // Create a single compile unit with a single function and make sure it gets1364  // converted to DWARF correctly. The function's address range is in where1365  // DW_AT_low_pc is an address and the DW_AT_high_pc is an offset.1366  StringRef yamldata = R"(1367  debug_str:1368    - ''1369    - /tmp/main.c1370    - main1371  debug_abbrev:1372    - Table:1373        - Code:            0x000000011374          Tag:             DW_TAG_compile_unit1375          Children:        DW_CHILDREN_yes1376          Attributes:1377            - Attribute:       DW_AT_name1378              Form:            DW_FORM_strp1379            - Attribute:       DW_AT_low_pc1380              Form:            DW_FORM_addr1381            - Attribute:       DW_AT_high_pc1382              Form:            DW_FORM_data41383            - Attribute:       DW_AT_language1384              Form:            DW_FORM_data21385        - Code:            0x000000021386          Tag:             DW_TAG_subprogram1387          Children:        DW_CHILDREN_no1388          Attributes:1389            - Attribute:       DW_AT_name1390              Form:            DW_FORM_strp1391            - Attribute:       DW_AT_low_pc1392              Form:            DW_FORM_addr1393            - Attribute:       DW_AT_high_pc1394              Form:            DW_FORM_data41395  debug_info:1396    - Version:         41397      AddrSize:        81398      Entries:1399        - AbbrCode:        0x000000011400          Values:1401            - Value:           0x00000000000000011402            - Value:           0x00000000000010001403            - Value:           0x00000000000010001404            - Value:           0x00000000000000041405        - AbbrCode:        0x000000021406          Values:1407            - Value:           0x000000000000000D1408            - Value:           0x00000000000010001409            - Value:           0x00000000000010001410        - AbbrCode:        0x000000001411  )";1412  auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);1413  ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());1414  std::unique_ptr<DWARFContext> DwarfContext =1415      DWARFContext::create(*ErrOrSections, 8);1416  ASSERT_TRUE(DwarfContext.get() != nullptr);1417  auto &OS = llvm::nulls();1418  OutputAggregator OSAgg(&OS);1419  GsymCreator GC;1420  DwarfTransformer DT(*DwarfContext, GC);1421  const uint32_t ThreadCount = 1;1422  ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());1423  ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());1424  SmallString<512> Str;1425  raw_svector_ostream OutStrm(Str);1426  const auto ByteOrder = llvm::endianness::native;1427  FileWriter FW(OutStrm, ByteOrder);1428  ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());1429  Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());1430  ASSERT_THAT_EXPECTED(GR, Succeeded());1431  // There should only be one function in our GSYM.1432  EXPECT_EQ(GR->getNumAddresses(), 1u);1433  auto ExpFI = GR->getFunctionInfo(0x1000);1434  ASSERT_THAT_EXPECTED(ExpFI, Succeeded());1435  ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x2000));1436  EXPECT_FALSE(ExpFI->OptLineTable.has_value());1437  EXPECT_FALSE(ExpFI->Inline.has_value());1438}1439 1440TEST(GSYMTest, TestDWARFStructMethodNoMangled) {1441  // Sometimes the compiler will omit the mangled name in the DWARF for static1442  // and member functions of classes and structs. This test verifies that the1443  // fully qualified name of the method is computed and used as the string for1444  // the function in the GSYM in these cases. Otherwise we might just get a1445  // function name like "erase" instead of "std::vector<int>::erase".1446  StringRef yamldata = R"(1447  debug_str:1448    - ''1449    - /tmp/main.c1450    - Foo1451    - dump1452    - this1453  debug_abbrev:1454    - Table:1455        - Code:            0x000000011456          Tag:             DW_TAG_compile_unit1457          Children:        DW_CHILDREN_yes1458          Attributes:1459            - Attribute:       DW_AT_name1460              Form:            DW_FORM_strp1461            - Attribute:       DW_AT_low_pc1462              Form:            DW_FORM_addr1463            - Attribute:       DW_AT_high_pc1464              Form:            DW_FORM_addr1465            - Attribute:       DW_AT_language1466              Form:            DW_FORM_data21467        - Code:            0x000000021468          Tag:             DW_TAG_structure_type1469          Children:        DW_CHILDREN_yes1470          Attributes:1471            - Attribute:       DW_AT_name1472              Form:            DW_FORM_strp1473        - Code:            0x000000031474          Tag:             DW_TAG_subprogram1475          Children:        DW_CHILDREN_yes1476          Attributes:1477            - Attribute:       DW_AT_name1478              Form:            DW_FORM_strp1479            - Attribute:       DW_AT_low_pc1480              Form:            DW_FORM_addr1481            - Attribute:       DW_AT_high_pc1482              Form:            DW_FORM_addr1483        - Code:            0x000000041484          Tag:             DW_TAG_formal_parameter1485          Children:        DW_CHILDREN_no1486          Attributes:1487            - Attribute:       DW_AT_name1488              Form:            DW_FORM_strp1489            - Attribute:       DW_AT_type1490              Form:            DW_FORM_ref41491            - Attribute:       DW_AT_artificial1492              Form:            DW_FORM_flag_present1493  debug_info:1494    - Version:         41495      AddrSize:        81496      Entries:1497        - AbbrCode:        0x000000011498          Values:1499            - Value:           0x00000000000000011500            - Value:           0x00000000000010001501            - Value:           0x00000000000020001502            - Value:           0x00000000000000041503        - AbbrCode:        0x000000021504          Values:1505            - Value:           0x000000000000000D1506        - AbbrCode:        0x000000031507          Values:1508            - Value:           0x00000000000000111509            - Value:           0x00000000000010001510            - Value:           0x00000000000020001511        - AbbrCode:        0x000000041512          Values:1513            - Value:           0x00000000000000161514            - Value:           0x00000000000000221515            - Value:           0x00000000000000011516        - AbbrCode:        0x000000001517        - AbbrCode:        0x000000001518        - AbbrCode:        0x000000001519  )";1520  auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);1521  ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());1522  std::unique_ptr<DWARFContext> DwarfContext =1523      DWARFContext::create(*ErrOrSections, 8);1524  ASSERT_TRUE(DwarfContext.get() != nullptr);1525  auto &OS = llvm::nulls();1526  OutputAggregator OSAgg(&OS);1527  GsymCreator GC;1528  DwarfTransformer DT(*DwarfContext, GC);1529  const uint32_t ThreadCount = 1;1530  ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());1531  ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());1532  SmallString<512> Str;1533  raw_svector_ostream OutStrm(Str);1534  const auto ByteOrder = llvm::endianness::native;1535  FileWriter FW(OutStrm, ByteOrder);1536  ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());1537  Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());1538  ASSERT_THAT_EXPECTED(GR, Succeeded());1539  // There should only be one function in our GSYM.1540  EXPECT_EQ(GR->getNumAddresses(), 1u);1541  auto ExpFI = GR->getFunctionInfo(0x1000);1542  ASSERT_THAT_EXPECTED(ExpFI, Succeeded());1543  ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x2000));1544  EXPECT_FALSE(ExpFI->OptLineTable.has_value());1545  EXPECT_FALSE(ExpFI->Inline.has_value());1546  StringRef MethodName = GR->getString(ExpFI->Name);1547  EXPECT_EQ(MethodName, "Foo::dump");1548}1549 1550TEST(GSYMTest, TestDWARFTextRanges) {1551  // Linkers don't understand DWARF, they just like to concatenate and1552  // relocate data within the DWARF sections. This means that if a function1553  // gets dead stripped, and if those functions use an offset as the1554  // DW_AT_high_pc, we can end up with many functions at address zero. The1555  // DwarfTransformer allows clients to specify valid .text address ranges1556  // and any addresses of any functions must fall within those ranges if any1557  // have been specified. This means that an object file can calcuate the1558  // address ranges within the binary where code lives and set these ranges1559  // as constraints in the DwarfTransformer. ObjectFile instances can1560  // add a address ranges of sections that have executable permissions. This1561  // keeps bad information from being added to a GSYM file and causing issues1562  // when symbolicating.1563  StringRef yamldata = R"(1564  debug_str:1565    - ''1566    - /tmp/main.c1567    - main1568    - dead_stripped1569    - dead_stripped21570  debug_abbrev:1571    - Table:1572        - Code:            0x000000011573          Tag:             DW_TAG_compile_unit1574          Children:        DW_CHILDREN_yes1575          Attributes:1576            - Attribute:       DW_AT_name1577              Form:            DW_FORM_strp1578            - Attribute:       DW_AT_low_pc1579              Form:            DW_FORM_addr1580            - Attribute:       DW_AT_high_pc1581              Form:            DW_FORM_data41582            - Attribute:       DW_AT_language1583              Form:            DW_FORM_data21584        - Code:            0x000000021585          Tag:             DW_TAG_subprogram1586          Children:        DW_CHILDREN_no1587          Attributes:1588            - Attribute:       DW_AT_name1589              Form:            DW_FORM_strp1590            - Attribute:       DW_AT_low_pc1591              Form:            DW_FORM_addr1592            - Attribute:       DW_AT_high_pc1593              Form:            DW_FORM_data41594  debug_info:1595    - Version:         41596      AddrSize:        81597      Entries:1598        - AbbrCode:        0x000000011599          Values:1600            - Value:           0x00000000000000011601            - Value:           0x00000000000010001602            - Value:           0x00000000000010001603            - Value:           0x00000000000000041604        - AbbrCode:        0x000000021605          Values:1606            - Value:           0x000000000000000D1607            - Value:           0x00000000000010001608            - Value:           0x00000000000010001609        - AbbrCode:        0x000000021610          Values:1611            - Value:           0x00000000000000121612            - Value:           0x00000000000000001613            - Value:           0x00000000000001001614        - AbbrCode:        0x000000021615          Values:1616            - Value:           0x00000000000000201617            - Value:           0x00000000000000001618            - Value:           0x00000000000000401619        - AbbrCode:        0x000000001620  )";1621  auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);1622  ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());1623  std::unique_ptr<DWARFContext> DwarfContext =1624      DWARFContext::create(*ErrOrSections, 8);1625  ASSERT_TRUE(DwarfContext.get() != nullptr);1626  auto &OS = llvm::nulls();1627  OutputAggregator OSAgg(&OS);1628  GsymCreator GC;1629  DwarfTransformer DT(*DwarfContext, GC);1630  // Only allow addresses between [0x1000 - 0x2000) to be linked into the1631  // GSYM.1632  AddressRanges TextRanges;1633  TextRanges.insert(AddressRange(0x1000, 0x2000));1634  GC.SetValidTextRanges(TextRanges);1635  const uint32_t ThreadCount = 1;1636  ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());1637  ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());1638  SmallString<512> Str;1639  raw_svector_ostream OutStrm(Str);1640  const auto ByteOrder = llvm::endianness::native;1641  FileWriter FW(OutStrm, ByteOrder);1642  ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());1643  Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());1644  ASSERT_THAT_EXPECTED(GR, Succeeded());1645  // There should only be one function in our GSYM.1646  EXPECT_EQ(GR->getNumAddresses(), 1u);1647  auto ExpFI = GR->getFunctionInfo(0x1000);1648  ASSERT_THAT_EXPECTED(ExpFI, Succeeded());1649  ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x2000));1650  EXPECT_FALSE(ExpFI->OptLineTable.has_value());1651  EXPECT_FALSE(ExpFI->Inline.has_value());1652  StringRef MethodName = GR->getString(ExpFI->Name);1653  EXPECT_EQ(MethodName, "main");1654}1655 1656TEST(GSYMTest, TestEmptySymbolEndAddressOfTextRanges) {1657  // Test that if we have valid text ranges and we have a symbol with no size1658  // as the last FunctionInfo entry that the size of the symbol gets set to the1659  // end address of the text range.1660  GsymCreator GC;1661  AddressRanges TextRanges;1662  TextRanges.insert(AddressRange(0x1000, 0x2000));1663  GC.SetValidTextRanges(TextRanges);1664  GC.addFunctionInfo(FunctionInfo(0x1500, 0, GC.insertString("symbol")));1665  OutputAggregator Null(nullptr);1666  ASSERT_THAT_ERROR(GC.finalize(Null), Succeeded());1667  SmallString<512> Str;1668  raw_svector_ostream OutStrm(Str);1669  const auto ByteOrder = llvm::endianness::native;1670  FileWriter FW(OutStrm, ByteOrder);1671  ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());1672  Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());1673  ASSERT_THAT_EXPECTED(GR, Succeeded());1674  // There should only be one function in our GSYM.1675  EXPECT_EQ(GR->getNumAddresses(), 1u);1676  auto ExpFI = GR->getFunctionInfo(0x1500);1677  ASSERT_THAT_EXPECTED(ExpFI, Succeeded());1678  ASSERT_EQ(ExpFI->Range, AddressRange(0x1500, 0x2000));1679  EXPECT_FALSE(ExpFI->OptLineTable.has_value());1680  EXPECT_FALSE(ExpFI->Inline.has_value());1681  StringRef MethodName = GR->getString(ExpFI->Name);1682  EXPECT_EQ(MethodName, "symbol");1683}1684 1685TEST(GSYMTest, TestDWARFInlineInfo) {1686  // Make sure we parse the line table and inline information correctly from1687  // DWARF.1688  StringRef yamldata = R"(1689  debug_str:1690    - ''1691    - /tmp/main.c1692    - main1693    - inline11694  debug_abbrev:1695    - Table:1696        - Code:            0x000000011697          Tag:             DW_TAG_compile_unit1698          Children:        DW_CHILDREN_yes1699          Attributes:1700            - Attribute:       DW_AT_name1701              Form:            DW_FORM_strp1702            - Attribute:       DW_AT_low_pc1703              Form:            DW_FORM_addr1704            - Attribute:       DW_AT_high_pc1705              Form:            DW_FORM_data41706            - Attribute:       DW_AT_language1707              Form:            DW_FORM_data21708            - Attribute:       DW_AT_stmt_list1709              Form:            DW_FORM_sec_offset1710        - Code:            0x000000021711          Tag:             DW_TAG_subprogram1712          Children:        DW_CHILDREN_yes1713          Attributes:1714            - Attribute:       DW_AT_name1715              Form:            DW_FORM_strp1716            - Attribute:       DW_AT_low_pc1717              Form:            DW_FORM_addr1718            - Attribute:       DW_AT_high_pc1719              Form:            DW_FORM_data41720        - Code:            0x000000031721          Tag:             DW_TAG_inlined_subroutine1722          Children:        DW_CHILDREN_no1723          Attributes:1724            - Attribute:       DW_AT_name1725              Form:            DW_FORM_strp1726            - Attribute:       DW_AT_low_pc1727              Form:            DW_FORM_addr1728            - Attribute:       DW_AT_high_pc1729              Form:            DW_FORM_data41730            - Attribute:       DW_AT_call_file1731              Form:            DW_FORM_data41732            - Attribute:       DW_AT_call_line1733              Form:            DW_FORM_data41734  debug_info:1735    - Version:         41736      AddrSize:        81737      Entries:1738        - AbbrCode:        0x000000011739          Values:1740            - Value:           0x00000000000000011741            - Value:           0x00000000000010001742            - Value:           0x00000000000010001743            - Value:           0x00000000000000041744            - Value:           0x00000000000000001745        - AbbrCode:        0x000000021746          Values:1747            - Value:           0x000000000000000D1748            - Value:           0x00000000000010001749            - Value:           0x00000000000010001750        - AbbrCode:        0x000000031751          Values:1752            - Value:           0x00000000000000121753            - Value:           0x00000000000011001754            - Value:           0x00000000000001001755            - Value:           0x00000000000000011756            - Value:           0x000000000000000A1757        - AbbrCode:        0x000000001758        - AbbrCode:        0x000000001759  debug_line:1760    - Length:          961761      Version:         21762      PrologueLength:  461763      MinInstLength:   11764      DefaultIsStmt:   11765      LineBase:        2511766      LineRange:       141767      OpcodeBase:      131768      StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]1769      IncludeDirs:1770        - /tmp1771      Files:1772        - Name:            main.c1773          DirIdx:          11774          ModTime:         01775          Length:          01776        - Name:            inline.h1777          DirIdx:          11778          ModTime:         01779          Length:          01780      Opcodes:1781        - Opcode:          DW_LNS_extended_op1782          ExtLen:          91783          SubOpcode:       DW_LNE_set_address1784          Data:            40961785        - Opcode:          DW_LNS_advance_line1786          SData:           91787          Data:            40961788        - Opcode:          DW_LNS_copy1789          Data:            40961790        - Opcode:          DW_LNS_advance_pc1791          Data:            2561792        - Opcode:          DW_LNS_set_file1793          Data:            21794        - Opcode:          DW_LNS_advance_line1795          SData:           101796          Data:            21797        - Opcode:          DW_LNS_copy1798          Data:            21799        - Opcode:          DW_LNS_advance_pc1800          Data:            1281801        - Opcode:          DW_LNS_advance_line1802          SData:           11803          Data:            1281804        - Opcode:          DW_LNS_copy1805          Data:            1281806        - Opcode:          DW_LNS_advance_pc1807          Data:            1281808        - Opcode:          DW_LNS_set_file1809          Data:            11810        - Opcode:          DW_LNS_advance_line1811          SData:           -101812          Data:            11813        - Opcode:          DW_LNS_copy1814          Data:            11815        - Opcode:          DW_LNS_advance_pc1816          Data:            35841817        - Opcode:          DW_LNS_advance_line1818          SData:           11819          Data:            35841820        - Opcode:          DW_LNS_extended_op1821          ExtLen:          11822          SubOpcode:       DW_LNE_end_sequence1823          Data:            35841824  )";1825  auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);1826  ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());1827  std::unique_ptr<DWARFContext> DwarfContext =1828      DWARFContext::create(*ErrOrSections, 8);1829  ASSERT_TRUE(DwarfContext.get() != nullptr);1830  auto &OS = llvm::nulls();1831  OutputAggregator OSAgg(&OS);1832  GsymCreator GC;1833  DwarfTransformer DT(*DwarfContext, GC);1834  const uint32_t ThreadCount = 1;1835  ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());1836  ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());1837  SmallString<512> Str;1838  raw_svector_ostream OutStrm(Str);1839  const auto ByteOrder = llvm::endianness::native;1840  FileWriter FW(OutStrm, ByteOrder);1841  ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());1842  Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());1843  ASSERT_THAT_EXPECTED(GR, Succeeded());1844  // There should only be one function in our GSYM.1845  EXPECT_EQ(GR->getNumAddresses(), 1u);1846  auto ExpFI = GR->getFunctionInfo(0x1000);1847  ASSERT_THAT_EXPECTED(ExpFI, Succeeded());1848  ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x2000));1849  EXPECT_TRUE(ExpFI->OptLineTable.has_value());1850  EXPECT_TRUE(ExpFI->Inline.has_value());1851  StringRef MethodName = GR->getString(ExpFI->Name);1852  EXPECT_EQ(MethodName, "main");1853 1854    // Verify inline info is correct when doing lookups.1855  auto LR = GR->lookup(0x1000);1856  ASSERT_THAT_EXPECTED(LR, Succeeded());1857  EXPECT_THAT(LR->Locations,1858    testing::ElementsAre(SourceLocation{"main", "/tmp", "main.c", 10}));1859  LR = GR->lookup(0x1100-1);1860  ASSERT_THAT_EXPECTED(LR, Succeeded());1861  EXPECT_THAT(LR->Locations,1862    testing::ElementsAre(SourceLocation{"main", "/tmp", "main.c", 10, 255}));1863 1864  LR = GR->lookup(0x1100);1865  ASSERT_THAT_EXPECTED(LR, Succeeded());1866  EXPECT_THAT(LR->Locations,1867    testing::ElementsAre(SourceLocation{"inline1", "/tmp", "inline.h", 20},1868                         SourceLocation{"main", "/tmp", "main.c", 10, 256}));1869  LR = GR->lookup(0x1180-1);1870  ASSERT_THAT_EXPECTED(LR, Succeeded());1871  EXPECT_THAT(LR->Locations,1872    testing::ElementsAre(SourceLocation{"inline1", "/tmp", "inline.h", 20, 127},1873                         SourceLocation{"main", "/tmp", "main.c", 10, 383}));1874  LR = GR->lookup(0x1180);1875  ASSERT_THAT_EXPECTED(LR, Succeeded());1876  EXPECT_THAT(LR->Locations,1877    testing::ElementsAre(SourceLocation{"inline1", "/tmp", "inline.h", 21, 128},1878                         SourceLocation{"main", "/tmp", "main.c", 10, 384}));1879  LR = GR->lookup(0x1200-1);1880  ASSERT_THAT_EXPECTED(LR, Succeeded());1881  EXPECT_THAT(LR->Locations,1882    testing::ElementsAre(SourceLocation{"inline1", "/tmp", "inline.h", 21, 255},1883                         SourceLocation{"main", "/tmp", "main.c", 10, 511}));1884  LR = GR->lookup(0x1200);1885  ASSERT_THAT_EXPECTED(LR, Succeeded());1886  EXPECT_THAT(LR->Locations,1887    testing::ElementsAre(SourceLocation{"main", "/tmp", "main.c", 11, 512}));1888}1889 1890 1891TEST(GSYMTest, TestDWARFNoLines) {1892  // Check that if a DW_TAG_subprogram doesn't have line table entries that1893  // we fall back and use the DW_AT_decl_file and DW_AT_decl_line to at least1894  // point to the function definition. This DWARF file has 4 functions:1895  //  "lines_no_decl": has line table entries, no DW_AT_decl_file/line attrs.1896  //  "lines_with_decl": has line table entries and has DW_AT_decl_file/line,1897  //                     make sure we don't use DW_AT_decl_file/line and make1898  //                     sure there is a line table.1899  //  "no_lines_no_decl": no line table entries and no DW_AT_decl_file/line,1900  //                      make sure there is no line table for this function.1901  //  "no_lines_with_decl": no line table and has DW_AT_decl_file/line, make1902  //                        sure we have one line table entry that starts at1903  //                        the function start address and the decl file and1904  //                        line.1905  //1906  // 0x0000000b: DW_TAG_compile_unit1907  //               DW_AT_name	("/tmp/main.c")1908  //               DW_AT_low_pc	(0x0000000000001000)1909  //               DW_AT_high_pc	(0x0000000000002000)1910  //               DW_AT_language	(DW_LANG_C_plus_plus)1911  //               DW_AT_stmt_list	(0x00000000)1912  //1913  // 0x00000022:   DW_TAG_subprogram1914  //                 DW_AT_name	("lines_no_decl")1915  //                 DW_AT_low_pc	(0x0000000000001000)1916  //                 DW_AT_high_pc	(0x0000000000002000)1917  //1918  // 0x00000033:   DW_TAG_subprogram1919  //                 DW_AT_name	("lines_with_decl")1920  //                 DW_AT_low_pc	(0x0000000000002000)1921  //                 DW_AT_high_pc	(0x0000000000003000)1922  //                 DW_AT_decl_file	("/tmp/main.c")1923  //                 DW_AT_decl_line	(20)1924  //1925  // 0x00000046:   DW_TAG_subprogram1926  //                 DW_AT_name	("no_lines_no_decl")1927  //                 DW_AT_low_pc	(0x0000000000003000)1928  //                 DW_AT_high_pc	(0x0000000000004000)1929  //1930  // 0x00000057:   DW_TAG_subprogram1931  //                 DW_AT_name	("no_lines_with_decl")1932  //                 DW_AT_low_pc	(0x0000000000004000)1933  //                 DW_AT_high_pc	(0x0000000000005000)1934  //                 DW_AT_decl_file	("/tmp/main.c")1935  //                 DW_AT_decl_line	(40)1936  //1937  // 0x0000006a:   NULL1938 1939  StringRef yamldata = R"(1940  debug_str:1941    - ''1942    - '/tmp/main.c'1943    - lines_no_decl1944    - lines_with_decl1945    - no_lines_no_decl1946    - no_lines_with_decl1947  debug_abbrev:1948    - Table:1949        - Code:            0x000000011950          Tag:             DW_TAG_compile_unit1951          Children:        DW_CHILDREN_yes1952          Attributes:1953            - Attribute:       DW_AT_name1954              Form:            DW_FORM_strp1955            - Attribute:       DW_AT_low_pc1956              Form:            DW_FORM_addr1957            - Attribute:       DW_AT_high_pc1958              Form:            DW_FORM_data41959            - Attribute:       DW_AT_language1960              Form:            DW_FORM_data21961            - Attribute:       DW_AT_stmt_list1962              Form:            DW_FORM_sec_offset1963        - Code:            0x000000021964          Tag:             DW_TAG_subprogram1965          Children:        DW_CHILDREN_no1966          Attributes:1967            - Attribute:       DW_AT_name1968              Form:            DW_FORM_strp1969            - Attribute:       DW_AT_low_pc1970              Form:            DW_FORM_addr1971            - Attribute:       DW_AT_high_pc1972              Form:            DW_FORM_data41973        - Code:            0x000000031974          Tag:             DW_TAG_subprogram1975          Children:        DW_CHILDREN_no1976          Attributes:1977            - Attribute:       DW_AT_name1978              Form:            DW_FORM_strp1979            - Attribute:       DW_AT_low_pc1980              Form:            DW_FORM_addr1981            - Attribute:       DW_AT_high_pc1982              Form:            DW_FORM_data41983            - Attribute:       DW_AT_decl_file1984              Form:            DW_FORM_data11985            - Attribute:       DW_AT_decl_line1986              Form:            DW_FORM_data11987  debug_info:1988    - Version:         41989      AddrSize:        81990      Entries:1991        - AbbrCode:        0x000000011992          Values:1993            - Value:           0x00000000000000011994            - Value:           0x00000000000010001995            - Value:           0x00000000000010001996            - Value:           0x00000000000000041997            - Value:           0x00000000000000001998        - AbbrCode:        0x000000021999          Values:2000            - Value:           0x000000000000000D2001            - Value:           0x00000000000010002002            - Value:           0x00000000000010002003        - AbbrCode:        0x000000032004          Values:2005            - Value:           0x000000000000001B2006            - Value:           0x00000000000020002007            - Value:           0x00000000000010002008            - Value:           0x00000000000000012009            - Value:           0x00000000000000142010        - AbbrCode:        0x000000022011          Values:2012            - Value:           0x000000000000002B2013            - Value:           0x00000000000030002014            - Value:           0x00000000000010002015        - AbbrCode:        0x000000032016          Values:2017            - Value:           0x000000000000003C2018            - Value:           0x00000000000040002019            - Value:           0x00000000000010002020            - Value:           0x00000000000000012021            - Value:           0x00000000000000282022        - AbbrCode:        0x000000002023  debug_line:2024    - Length:          922025      Version:         22026      PrologueLength:  342027      MinInstLength:   12028      DefaultIsStmt:   12029      LineBase:        2512030      LineRange:       142031      OpcodeBase:      132032      StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]2033      IncludeDirs:2034        - '/tmp'2035      Files:2036        - Name:            main.c2037          DirIdx:          12038          ModTime:         02039          Length:          02040      Opcodes:2041        - Opcode:          DW_LNS_extended_op2042          ExtLen:          92043          SubOpcode:       DW_LNE_set_address2044          Data:            40962045        - Opcode:          DW_LNS_advance_line2046          SData:           102047          Data:            02048        - Opcode:          DW_LNS_copy2049          Data:            02050        - Opcode:          DW_LNS_advance_pc2051          Data:            5122052        - Opcode:          DW_LNS_advance_line2053          SData:           12054          Data:            02055        - Opcode:          DW_LNS_copy2056          Data:            02057        - Opcode:          DW_LNS_advance_pc2058          Data:            35842059        - Opcode:          DW_LNS_extended_op2060          ExtLen:          12061          SubOpcode:       DW_LNE_end_sequence2062          Data:            02063        - Opcode:          DW_LNS_extended_op2064          ExtLen:          92065          SubOpcode:       DW_LNE_set_address2066          Data:            81922067        - Opcode:          DW_LNS_advance_line2068          SData:           202069          Data:            02070        - Opcode:          DW_LNS_copy2071          Data:            02072        - Opcode:          DW_LNS_advance_pc2073          Data:            5122074        - Opcode:          DW_LNS_advance_line2075          SData:           12076          Data:            02077        - Opcode:          DW_LNS_copy2078          Data:            02079        - Opcode:          DW_LNS_advance_pc2080          Data:            35842081        - Opcode:          DW_LNS_extended_op2082          ExtLen:          12083          SubOpcode:       DW_LNE_end_sequence2084          Data:            02085  )";2086  auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);2087  ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());2088  std::unique_ptr<DWARFContext> DwarfContext =2089      DWARFContext::create(*ErrOrSections, 8);2090  ASSERT_TRUE(DwarfContext.get() != nullptr);2091  auto &OS = llvm::nulls();2092  OutputAggregator OSAgg(&OS);2093  GsymCreator GC;2094  DwarfTransformer DT(*DwarfContext, GC);2095  const uint32_t ThreadCount = 1;2096  ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());2097  ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());2098  SmallString<512> Str;2099  raw_svector_ostream OutStrm(Str);2100  const auto ByteOrder = llvm::endianness::native;2101  FileWriter FW(OutStrm, ByteOrder);2102  ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());2103  Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());2104  ASSERT_THAT_EXPECTED(GR, Succeeded());2105 2106  EXPECT_EQ(GR->getNumAddresses(), 4u);2107 2108  auto ExpFI = GR->getFunctionInfo(0x1000);2109  ASSERT_THAT_EXPECTED(ExpFI, Succeeded());2110  ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x2000));2111  EXPECT_TRUE(ExpFI->OptLineTable);2112  StringRef MethodName = GR->getString(ExpFI->Name);2113  EXPECT_EQ(MethodName, "lines_no_decl");2114  // Make sure have two line table entries and that get the first line entry2115  // correct.2116  EXPECT_EQ(ExpFI->OptLineTable->size(), 2u);2117  EXPECT_EQ(ExpFI->OptLineTable->first()->Addr, 0x1000u);2118  EXPECT_EQ(ExpFI->OptLineTable->first()->Line, 11u);2119 2120  ExpFI = GR->getFunctionInfo(0x2000);2121  ASSERT_THAT_EXPECTED(ExpFI, Succeeded());2122  ASSERT_EQ(ExpFI->Range, AddressRange(0x2000, 0x3000));2123  EXPECT_TRUE(ExpFI->OptLineTable);2124  MethodName = GR->getString(ExpFI->Name);2125  EXPECT_EQ(MethodName, "lines_with_decl");2126  // Make sure have two line table entries and that we don't use line 202127  // from the DW_AT_decl_file/line as a line table entry.2128  EXPECT_EQ(ExpFI->OptLineTable->size(), 2u);2129  EXPECT_EQ(ExpFI->OptLineTable->first()->Addr, 0x2000u);2130  EXPECT_EQ(ExpFI->OptLineTable->first()->Line, 21u);2131 2132  ExpFI = GR->getFunctionInfo(0x3000);2133  ASSERT_THAT_EXPECTED(ExpFI, Succeeded());2134  ASSERT_EQ(ExpFI->Range, AddressRange(0x3000, 0x4000));2135  // Make sure we have no line table.2136  EXPECT_FALSE(ExpFI->OptLineTable.has_value());2137  MethodName = GR->getString(ExpFI->Name);2138  EXPECT_EQ(MethodName, "no_lines_no_decl");2139 2140  ExpFI = GR->getFunctionInfo(0x4000);2141  ASSERT_THAT_EXPECTED(ExpFI, Succeeded());2142  ASSERT_EQ(ExpFI->Range, AddressRange(0x4000, 0x5000));2143  EXPECT_TRUE(ExpFI->OptLineTable.has_value());2144  MethodName = GR->getString(ExpFI->Name);2145  EXPECT_EQ(MethodName, "no_lines_with_decl");2146  // Make sure we have one line table entry that uses the DW_AT_decl_file/line2147  // as the one and only line entry.2148  EXPECT_EQ(ExpFI->OptLineTable->size(), 1u);2149  EXPECT_EQ(ExpFI->OptLineTable->first()->Addr, 0x4000u);2150  EXPECT_EQ(ExpFI->OptLineTable->first()->Line, 40u);2151}2152 2153 2154TEST(GSYMTest, TestDWARFDeadStripAddr4) {2155  // Check that various techniques that compilers use for dead code stripping2156  // work for 4 byte addresses. Make sure we keep the good functions and2157  // strip any functions whose name starts with "stripped".2158  //2159  // 1 - Compilers might set the low PC to -1 (UINT32_MAX) for compile unit2160  //     with 4 byte addresses ("stripped1")2161  // 2 - Set the low and high PC to the same value ("stripped2")2162  // 3 - Have the high PC lower than the low PC ("stripped3")2163  //2164  // 0x0000000b: DW_TAG_compile_unit2165  //               DW_AT_name	("/tmp/main.c")2166  //               DW_AT_low_pc	(0x0000000000001000)2167  //               DW_AT_high_pc	(0x0000000000002000)2168  //               DW_AT_language	(DW_LANG_C_plus_plus)2169  //2170  // 0x0000001a:   DW_TAG_subprogram2171  //                 DW_AT_name	("main")2172  //                 DW_AT_low_pc	(0x0000000000001000)2173  //                 DW_AT_high_pc	(0x0000000000002000)2174  //2175  // 0x00000027:   DW_TAG_subprogram2176  //                 DW_AT_name	("stripped1")2177  //                 DW_AT_low_pc	(0x00000000ffffffff)2178  //                 DW_AT_high_pc	(0x0000000100000000)2179  //2180  // 0x00000034:   DW_TAG_subprogram2181  //                 DW_AT_name	("stripped2")2182  //                 DW_AT_low_pc	(0x0000000000003000)2183  //                 DW_AT_high_pc	(0x0000000000003000)2184  //2185  // 0x00000041:   DW_TAG_subprogram2186  //                 DW_AT_name	("stripped3")2187  //                 DW_AT_low_pc	(0x0000000000004000)2188  //                 DW_AT_high_pc	(0x0000000000003fff)2189  //2190  // 0x0000004e:   NULL2191 2192  StringRef yamldata = R"(2193  debug_str:2194    - ''2195    - '/tmp/main.c'2196    - main2197    - stripped12198    - stripped22199    - stripped32200  debug_abbrev:2201    - Table:2202        - Code:            0x000000012203          Tag:             DW_TAG_compile_unit2204          Children:        DW_CHILDREN_yes2205          Attributes:2206            - Attribute:       DW_AT_name2207              Form:            DW_FORM_strp2208            - Attribute:       DW_AT_low_pc2209              Form:            DW_FORM_addr2210            - Attribute:       DW_AT_high_pc2211              Form:            DW_FORM_data42212            - Attribute:       DW_AT_language2213              Form:            DW_FORM_data22214        - Code:            0x000000022215          Tag:             DW_TAG_subprogram2216          Children:        DW_CHILDREN_no2217          Attributes:2218            - Attribute:       DW_AT_name2219              Form:            DW_FORM_strp2220            - Attribute:       DW_AT_low_pc2221              Form:            DW_FORM_addr2222            - Attribute:       DW_AT_high_pc2223              Form:            DW_FORM_data42224        - Code:            0x000000032225          Tag:             DW_TAG_subprogram2226          Children:        DW_CHILDREN_no2227          Attributes:2228            - Attribute:       DW_AT_name2229              Form:            DW_FORM_strp2230            - Attribute:       DW_AT_low_pc2231              Form:            DW_FORM_addr2232            - Attribute:       DW_AT_high_pc2233              Form:            DW_FORM_addr2234  debug_info:2235    - Version:         42236      AddrSize:        42237      Entries:2238        - AbbrCode:        0x000000012239          Values:2240            - Value:           0x00000000000000012241            - Value:           0x00000000000010002242            - Value:           0x00000000000010002243            - Value:           0x00000000000000042244        - AbbrCode:        0x000000022245          Values:2246            - Value:           0x000000000000000D2247            - Value:           0x00000000000010002248            - Value:           0x00000000000010002249        - AbbrCode:        0x000000022250          Values:2251            - Value:           0x00000000000000122252            - Value:           0x00000000FFFFFFFF2253            - Value:           0x00000000000000012254        - AbbrCode:        0x000000032255          Values:2256            - Value:           0x000000000000001C2257            - Value:           0x00000000000030002258            - Value:           0x00000000000030002259        - AbbrCode:        0x000000032260          Values:2261            - Value:           0x00000000000000262262            - Value:           0x00000000000040002263            - Value:           0x0000000000003FFF2264        - AbbrCode:        0x000000002265  )";2266  auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);2267  ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());2268  std::unique_ptr<DWARFContext> DwarfContext =2269      DWARFContext::create(*ErrOrSections, 4);2270  ASSERT_TRUE(DwarfContext.get() != nullptr);2271  auto &OS = llvm::nulls();2272  OutputAggregator OSAgg(&OS);2273  GsymCreator GC;2274  DwarfTransformer DT(*DwarfContext, GC);2275  const uint32_t ThreadCount = 1;2276  ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());2277  ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());2278  SmallString<512> Str;2279  raw_svector_ostream OutStrm(Str);2280  const auto ByteOrder = llvm::endianness::native;2281  FileWriter FW(OutStrm, ByteOrder);2282  ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());2283  Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());2284  ASSERT_THAT_EXPECTED(GR, Succeeded());2285 2286  // Test that the only function that made it was the "main" function.2287  EXPECT_EQ(GR->getNumAddresses(), 1u);2288  auto ExpFI = GR->getFunctionInfo(0x1000);2289  ASSERT_THAT_EXPECTED(ExpFI, Succeeded());2290  ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x2000));2291  StringRef MethodName = GR->getString(ExpFI->Name);2292  EXPECT_EQ(MethodName, "main");2293}2294 2295TEST(GSYMTest, TestDWARFDeadStripAddr8) {2296  // Check that various techniques that compilers use for dead code stripping2297  // work for 4 byte addresses. Make sure we keep the good functions and2298  // strip any functions whose name starts with "stripped".2299  //2300  // 1 - Compilers might set the low PC to -1 (UINT64_MAX) for compile unit2301  //     with 8 byte addresses ("stripped1")2302  // 2 - Set the low and high PC to the same value ("stripped2")2303  // 3 - Have the high PC lower than the low PC ("stripped3")2304  //2305  // 0x0000000b: DW_TAG_compile_unit2306  //               DW_AT_name	("/tmp/main.c")2307  //               DW_AT_low_pc	(0x0000000000001000)2308  //               DW_AT_high_pc	(0x0000000000002000)2309  //               DW_AT_language	(DW_LANG_C_plus_plus)2310  //2311  // 0x0000001e:   DW_TAG_subprogram2312  //                 DW_AT_name	("main")2313  //                 DW_AT_low_pc	(0x0000000000001000)2314  //                 DW_AT_high_pc	(0x0000000000002000)2315  //2316  // 0x0000002f:   DW_TAG_subprogram2317  //                 DW_AT_name	("stripped1")2318  //                 DW_AT_low_pc	(0xffffffffffffffff)2319  //                 DW_AT_high_pc	(0x0000000000000000)2320  //2321  // 0x00000040:   DW_TAG_subprogram2322  //                 DW_AT_name	("stripped2")2323  //                 DW_AT_low_pc	(0x0000000000003000)2324  //                 DW_AT_high_pc	(0x0000000000003000)2325  //2326  // 0x00000055:   DW_TAG_subprogram2327  //                 DW_AT_name	("stripped3")2328  //                 DW_AT_low_pc	(0x0000000000004000)2329  //                 DW_AT_high_pc	(0x0000000000003fff)2330  //2331  // 0x0000006a:   NULL2332 2333  StringRef yamldata = R"(2334  debug_str:2335    - ''2336    - '/tmp/main.c'2337    - main2338    - stripped12339    - stripped22340    - stripped32341  debug_abbrev:2342    - Table:2343        - Code:            0x000000012344          Tag:             DW_TAG_compile_unit2345          Children:        DW_CHILDREN_yes2346          Attributes:2347            - Attribute:       DW_AT_name2348              Form:            DW_FORM_strp2349            - Attribute:       DW_AT_low_pc2350              Form:            DW_FORM_addr2351            - Attribute:       DW_AT_high_pc2352              Form:            DW_FORM_data42353            - Attribute:       DW_AT_language2354              Form:            DW_FORM_data22355        - Code:            0x000000022356          Tag:             DW_TAG_subprogram2357          Children:        DW_CHILDREN_no2358          Attributes:2359            - Attribute:       DW_AT_name2360              Form:            DW_FORM_strp2361            - Attribute:       DW_AT_low_pc2362              Form:            DW_FORM_addr2363            - Attribute:       DW_AT_high_pc2364              Form:            DW_FORM_data42365        - Code:            0x000000032366          Tag:             DW_TAG_subprogram2367          Children:        DW_CHILDREN_no2368          Attributes:2369            - Attribute:       DW_AT_name2370              Form:            DW_FORM_strp2371            - Attribute:       DW_AT_low_pc2372              Form:            DW_FORM_addr2373            - Attribute:       DW_AT_high_pc2374              Form:            DW_FORM_addr2375  debug_info:2376    - Version:         42377      AddrSize:        82378      Entries:2379        - AbbrCode:        0x000000012380          Values:2381            - Value:           0x00000000000000012382            - Value:           0x00000000000010002383            - Value:           0x00000000000010002384            - Value:           0x00000000000000042385        - AbbrCode:        0x000000022386          Values:2387            - Value:           0x000000000000000D2388            - Value:           0x00000000000010002389            - Value:           0x00000000000010002390        - AbbrCode:        0x000000022391          Values:2392            - Value:           0x00000000000000122393            - Value:           0xFFFFFFFFFFFFFFFF2394            - Value:           0x00000000000000012395        - AbbrCode:        0x000000032396          Values:2397            - Value:           0x000000000000001C2398            - Value:           0x00000000000030002399            - Value:           0x00000000000030002400        - AbbrCode:        0x000000032401          Values:2402            - Value:           0x00000000000000262403            - Value:           0x00000000000040002404            - Value:           0x0000000000003FFF2405        - AbbrCode:        0x000000002406  )";2407  auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);2408  ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());2409  std::unique_ptr<DWARFContext> DwarfContext =2410      DWARFContext::create(*ErrOrSections, 8);2411  ASSERT_TRUE(DwarfContext.get() != nullptr);2412  auto &OS = llvm::nulls();2413  OutputAggregator OSAgg(&OS);2414  GsymCreator GC;2415  DwarfTransformer DT(*DwarfContext, GC);2416  const uint32_t ThreadCount = 1;2417  ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());2418  ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());2419  SmallString<512> Str;2420  raw_svector_ostream OutStrm(Str);2421  const auto ByteOrder = llvm::endianness::native;2422  FileWriter FW(OutStrm, ByteOrder);2423  ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());2424  Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());2425  ASSERT_THAT_EXPECTED(GR, Succeeded());2426 2427  // Test that the only function that made it was the "main" function.2428  EXPECT_EQ(GR->getNumAddresses(), 1u);2429  auto ExpFI = GR->getFunctionInfo(0x1000);2430  ASSERT_THAT_EXPECTED(ExpFI, Succeeded());2431  ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x2000));2432  StringRef MethodName = GR->getString(ExpFI->Name);2433  EXPECT_EQ(MethodName, "main");2434}2435 2436TEST(GSYMTest, TestGsymCreatorMultipleSymbolsWithNoSize) {2437  // Multiple symbols at the same address with zero size were being emitted2438  // instead of being combined into a single entry. This function tests to make2439  // sure we only get one symbol.2440  uint8_t UUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};2441  GsymCreator GC;2442  GC.setUUID(UUID);2443  constexpr uint64_t BaseAddr = 0x1000;2444  constexpr uint8_t AddrOffSize = 1;2445  const uint32_t Func1Name = GC.insertString("foo");2446  const uint32_t Func2Name = GC.insertString("bar");2447  GC.addFunctionInfo(FunctionInfo(BaseAddr, 0, Func1Name));2448  GC.addFunctionInfo(FunctionInfo(BaseAddr, 0, Func2Name));2449  OutputAggregator Null(nullptr);2450  Error Err = GC.finalize(Null);2451  ASSERT_FALSE(Err);2452  TestEncodeDecode(GC, llvm::endianness::little, GSYM_VERSION, AddrOffSize,2453                   BaseAddr,2454                   1, // NumAddresses2455                   ArrayRef<uint8_t>(UUID));2456  TestEncodeDecode(GC, llvm::endianness::big, GSYM_VERSION, AddrOffSize,2457                   BaseAddr,2458                   1, // NumAddresses2459                   ArrayRef<uint8_t>(UUID));2460}2461 2462// Helper function to quickly create a FunctionInfo in a GsymCreator for testing.2463static void AddFunctionInfo(GsymCreator &GC, const char *FuncName,2464                            uint64_t FuncAddr, const char *SourcePath,2465                            const char *HeaderPath) {2466  FunctionInfo FI(FuncAddr, 0x30, GC.insertString(FuncName));2467  FI.OptLineTable = LineTable();2468  const uint32_t SourceFileIdx = GC.insertFile(SourcePath);2469  const uint32_t HeaderFileIdx = GC.insertFile(HeaderPath);2470  FI.OptLineTable->push(LineEntry(FuncAddr+0x00, SourceFileIdx, 5));2471  FI.OptLineTable->push(LineEntry(FuncAddr+0x10, HeaderFileIdx, 10));2472  FI.OptLineTable->push(LineEntry(FuncAddr+0x12, HeaderFileIdx, 20));2473  FI.OptLineTable->push(LineEntry(FuncAddr+0x14, HeaderFileIdx, 11));2474  FI.OptLineTable->push(LineEntry(FuncAddr+0x16, HeaderFileIdx, 30));2475  FI.OptLineTable->push(LineEntry(FuncAddr+0x18, HeaderFileIdx, 12));2476  FI.OptLineTable->push(LineEntry(FuncAddr+0x20, SourceFileIdx, 8));2477  FI.Inline = InlineInfo();2478 2479  std::string InlineName1(FuncName); InlineName1.append("1");2480  std::string InlineName2(FuncName); InlineName2.append("2");2481  std::string InlineName3(FuncName); InlineName3.append("3");2482 2483  FI.Inline->Name = GC.insertString(InlineName1);2484  FI.Inline->CallFile = SourceFileIdx;2485  FI.Inline->CallLine = 6;2486  FI.Inline->Ranges.insert(AddressRange(FuncAddr + 0x10, FuncAddr + 0x20));2487  InlineInfo Inline2;2488  Inline2.Name = GC.insertString(InlineName2);2489  Inline2.CallFile = HeaderFileIdx;2490  Inline2.CallLine = 33;2491  Inline2.Ranges.insert(AddressRange(FuncAddr + 0x12, FuncAddr + 0x14));2492  FI.Inline->Children.emplace_back(Inline2);2493  InlineInfo Inline3;2494  Inline3.Name = GC.insertString(InlineName3);2495  Inline3.CallFile = HeaderFileIdx;2496  Inline3.CallLine = 35;2497  Inline3.Ranges.insert(AddressRange(FuncAddr + 0x16, FuncAddr + 0x18));2498  FI.Inline->Children.emplace_back(Inline3);2499  GC.addFunctionInfo(std::move(FI));2500}2501 2502// Finalize a GsymCreator, encode it and decode it and return the error or2503// GsymReader that was successfully decoded.2504static Expected<GsymReader> FinalizeEncodeAndDecode(GsymCreator &GC) {2505  OutputAggregator Null(nullptr);2506  Error FinalizeErr = GC.finalize(Null);2507  if (FinalizeErr)2508    return std::move(FinalizeErr);2509  SmallString<1024> Str;2510  raw_svector_ostream OutStrm(Str);2511  const auto ByteOrder = llvm::endianness::native;2512  FileWriter FW(OutStrm, ByteOrder);2513  llvm::Error Err = GC.encode(FW);2514  if (Err)2515    return std::move(Err);2516  return GsymReader::copyBuffer(OutStrm.str());2517}2518 2519TEST(GSYMTest, TestGsymSegmenting) {2520  // Test creating a GSYM file with function infos and segment the information.2521  // We verify segmenting is working by creating a full GSYM and also by2522  // encoding multiple segments, then we verify that we get the same information2523  // when doing lookups on the full GSYM that was decoded from encoding the2524  // entire GSYM and also by decoding information from the segments themselves.2525  GsymCreator GC;2526  GC.setBaseAddress(0);2527  AddFunctionInfo(GC, "main", 0x1000, "/tmp/main.c", "/tmp/main.h");2528  AddFunctionInfo(GC, "foo", 0x2000, "/tmp/foo.c", "/tmp/foo.h");2529  AddFunctionInfo(GC, "bar", 0x3000, "/tmp/bar.c", "/tmp/bar.h");2530  AddFunctionInfo(GC, "baz", 0x4000, "/tmp/baz.c", "/tmp/baz.h");2531  Expected<GsymReader> GR = FinalizeEncodeAndDecode(GC);2532  ASSERT_THAT_EXPECTED(GR, Succeeded());2533  //GR->dump(outs());2534 2535  // Create segmented GSYM files where each file contains 1 function. We will2536  // then test doing lookups on the "GR", or the full GSYM file and then test2537  // doing lookups on the GsymReader objects for each segment to ensure we get2538  // the exact same information. So after all of the code below we will have2539  // GsymReader objects that each contain one function. We name the creators2540  // and readers to match the one and only address they contain.2541  // GC1000 and GR1000 are for [0x1000-0x1030)2542  // GC2000 and GR2000 are for [0x2000-0x2030)2543  // GC3000 and GR3000 are for [0x3000-0x3030)2544  // GC4000 and GR4000 are for [0x4000-0x4030)2545 2546  // Create the segments and verify that FuncIdx, an in/out parameter, gets2547  // updated as expected.2548  size_t FuncIdx = 0;2549  // Make sure we get an error if the segment size is too small to encode a2550  // single function info.2551  llvm::Expected<std::unique_ptr<GsymCreator>> GCError =2552      GC.createSegment(57, FuncIdx);2553  ASSERT_FALSE((bool)GCError);2554  checkError("a segment size of 57 is to small to fit any function infos, "2555             "specify a larger value", GCError.takeError());2556  // Make sure that the function index didn't get incremented when we didn't2557  // encode any values into the segmented GsymCreator.2558  ASSERT_EQ(FuncIdx, (size_t)0);2559 2560  llvm::Expected<std::unique_ptr<GsymCreator>> GC1000 =2561      GC.createSegment(128, FuncIdx);2562  ASSERT_THAT_EXPECTED(GC1000, Succeeded());2563  ASSERT_EQ(FuncIdx, (size_t)1);2564  llvm::Expected<std::unique_ptr<GsymCreator>> GC2000 =2565      GC.createSegment(128, FuncIdx);2566  ASSERT_THAT_EXPECTED(GC2000, Succeeded());2567  ASSERT_EQ(FuncIdx, (size_t)2);2568  llvm::Expected<std::unique_ptr<GsymCreator>> GC3000 =2569      GC.createSegment(128, FuncIdx);2570  ASSERT_THAT_EXPECTED(GC3000, Succeeded());2571  ASSERT_EQ(FuncIdx, (size_t)3);2572  llvm::Expected<std::unique_ptr<GsymCreator>> GC4000 =2573      GC.createSegment(128, FuncIdx);2574  ASSERT_THAT_EXPECTED(GC4000, Succeeded());2575  ASSERT_EQ(FuncIdx, (size_t)4);2576  // When there are no function infos left to encode we expect to get  no error2577  // and get a NULL GsymCreator in the return value from createSegment.2578  llvm::Expected<std::unique_ptr<GsymCreator>> GCNull =2579      GC.createSegment(128, FuncIdx);2580  ASSERT_THAT_EXPECTED(GCNull, Succeeded());2581  ASSERT_TRUE(GC1000.get() != nullptr);2582  ASSERT_TRUE(GC2000.get() != nullptr);2583  ASSERT_TRUE(GC3000.get() != nullptr);2584  ASSERT_TRUE(GC4000.get() != nullptr);2585  ASSERT_TRUE(GCNull.get() == nullptr);2586  // Encode and decode the GsymReader for each segment and verify they succeed.2587  Expected<GsymReader> GR1000 = FinalizeEncodeAndDecode(*GC1000.get());2588  ASSERT_THAT_EXPECTED(GR1000, Succeeded());2589  Expected<GsymReader> GR2000 = FinalizeEncodeAndDecode(*GC2000.get());2590  ASSERT_THAT_EXPECTED(GR2000, Succeeded());2591  Expected<GsymReader> GR3000 = FinalizeEncodeAndDecode(*GC3000.get());2592  ASSERT_THAT_EXPECTED(GR3000, Succeeded());2593  Expected<GsymReader> GR4000 = FinalizeEncodeAndDecode(*GC4000.get());2594  ASSERT_THAT_EXPECTED(GR4000, Succeeded());2595 2596  // Verify that all lookups match the range [0x1000-0x1030) when doing lookups2597  // in the GsymReader that contains all functions and from the segmented2598  // GsymReader in GR1000.2599  for (uint64_t Addr = 0x1000; Addr < 0x1030; ++Addr) {2600    // Lookup in the main GsymReader that contains all function infos2601    auto MainLR = GR->lookup(Addr);2602    ASSERT_THAT_EXPECTED(MainLR, Succeeded());2603    auto SegmentLR = GR1000->lookup(Addr);2604    ASSERT_THAT_EXPECTED(SegmentLR, Succeeded());2605    // Make sure the lookup results match.2606    EXPECT_EQ(MainLR.get(), SegmentLR.get());2607    // Make sure that the lookups on the functions that are not in the segment2608    // fail as expected.2609    ASSERT_THAT_EXPECTED(GR1000->lookup(0x2000), Failed());2610    ASSERT_THAT_EXPECTED(GR1000->lookup(0x3000), Failed());2611    ASSERT_THAT_EXPECTED(GR1000->lookup(0x4000), Failed());2612  }2613 2614  // Verify that all lookups match the range [0x2000-0x2030) when doing lookups2615  // in the GsymReader that contains all functions and from the segmented2616  // GsymReader in GR2000.2617  for (uint64_t Addr = 0x2000; Addr < 0x2030; ++Addr) {2618    // Lookup in the main GsymReader that contains all function infos2619    auto MainLR = GR->lookup(Addr);2620    ASSERT_THAT_EXPECTED(MainLR, Succeeded());2621    auto SegmentLR = GR2000->lookup(Addr);2622    ASSERT_THAT_EXPECTED(SegmentLR, Succeeded());2623    // Make sure the lookup results match.2624    EXPECT_EQ(MainLR.get(), SegmentLR.get());2625    // Make sure that the lookups on the functions that are not in the segment2626    // fail as expected.2627    ASSERT_THAT_EXPECTED(GR2000->lookup(0x1000), Failed());2628    ASSERT_THAT_EXPECTED(GR2000->lookup(0x3000), Failed());2629    ASSERT_THAT_EXPECTED(GR2000->lookup(0x4000), Failed());2630 2631  }2632 2633  // Verify that all lookups match the range [0x3000-0x3030) when doing lookups2634  // in the GsymReader that contains all functions and from the segmented2635  // GsymReader in GR3000.2636  for (uint64_t Addr = 0x3000; Addr < 0x3030; ++Addr) {2637    // Lookup in the main GsymReader that contains all function infos2638    auto MainLR = GR->lookup(Addr);2639    ASSERT_THAT_EXPECTED(MainLR, Succeeded());2640    auto SegmentLR = GR3000->lookup(Addr);2641    ASSERT_THAT_EXPECTED(SegmentLR, Succeeded());2642    // Make sure the lookup results match.2643    EXPECT_EQ(MainLR.get(), SegmentLR.get());2644    // Make sure that the lookups on the functions that are not in the segment2645    // fail as expected.2646    ASSERT_THAT_EXPECTED(GR3000->lookup(0x1000), Failed());2647    ASSERT_THAT_EXPECTED(GR3000->lookup(0x2000), Failed());2648    ASSERT_THAT_EXPECTED(GR3000->lookup(0x4000), Failed());2649}2650 2651  // Verify that all lookups match the range [0x4000-0x4030) when doing lookups2652  // in the GsymReader that contains all functions and from the segmented2653  // GsymReader in GR4000.2654  for (uint64_t Addr = 0x4000; Addr < 0x4030; ++Addr) {2655    // Lookup in the main GsymReader that contains all function infos2656    auto MainLR = GR->lookup(Addr);2657    ASSERT_THAT_EXPECTED(MainLR, Succeeded());2658    // Lookup in the GsymReader for that contains 0x40002659    auto SegmentLR = GR4000->lookup(Addr);2660    ASSERT_THAT_EXPECTED(SegmentLR, Succeeded());2661    // Make sure the lookup results match.2662    EXPECT_EQ(MainLR.get(), SegmentLR.get());2663    // Make sure that the lookups on the functions that are not in the segment2664    // fail as expected.2665    ASSERT_THAT_EXPECTED(GR4000->lookup(0x1000), Failed());2666    ASSERT_THAT_EXPECTED(GR4000->lookup(0x2000), Failed());2667    ASSERT_THAT_EXPECTED(GR4000->lookup(0x3000), Failed());2668  }2669}2670 2671TEST(GSYMTest, TestGsymSegmentingNoBase) {2672  // Test creating a GSYM file with function infos and segment the information.2673  // We verify segmenting is working by creating a full GSYM and also by2674  // encoding multiple segments, then we verify that we get the same information2675  // when doing lookups on the full GSYM that was decoded from encoding the2676  // entire GSYM and also by decoding information from the segments themselves.2677  GsymCreator GC;2678  AddFunctionInfo(GC, "main", 0x1000, "/tmp/main.c", "/tmp/main.h");2679  AddFunctionInfo(GC, "foo", 0x2000, "/tmp/foo.c", "/tmp/foo.h");2680  AddFunctionInfo(GC, "bar", 0x3000, "/tmp/bar.c", "/tmp/bar.h");2681  AddFunctionInfo(GC, "baz", 0x4000, "/tmp/baz.c", "/tmp/baz.h");2682  Expected<GsymReader> GR = FinalizeEncodeAndDecode(GC);2683  ASSERT_THAT_EXPECTED(GR, Succeeded());2684  //GR->dump(outs());2685 2686  // Create segmented GSYM files where each file contains 1 function. We will2687  // then test doing lookups on the "GR", or the full GSYM file and then test2688  // doing lookups on the GsymReader objects for each segment to ensure we get2689  // the exact same information. So after all of the code below we will have2690  // GsymReader objects that each contain one function. We name the creators2691  // and readers to match the one and only address they contain.2692  // GC1000 and GR1000 are for [0x1000-0x1030)2693  // GC2000 and GR2000 are for [0x2000-0x2030)2694  // GC3000 and GR3000 are for [0x3000-0x3030)2695  // GC4000 and GR4000 are for [0x4000-0x4030)2696 2697  // Create the segments and verify that FuncIdx, an in/out parameter, gets2698  // updated as expected.2699  size_t FuncIdx = 0;2700  // Make sure we get an error if the segment size is too small to encode a2701  // single function info.2702  llvm::Expected<std::unique_ptr<GsymCreator>> GCError =2703      GC.createSegment(57, FuncIdx);2704  ASSERT_FALSE((bool)GCError);2705  checkError("a segment size of 57 is to small to fit any function infos, "2706             "specify a larger value", GCError.takeError());2707  // Make sure that the function index didn't get incremented when we didn't2708  // encode any values into the segmented GsymCreator.2709  ASSERT_EQ(FuncIdx, (size_t)0);2710 2711  llvm::Expected<std::unique_ptr<GsymCreator>> GC1000 =2712      GC.createSegment(128, FuncIdx);2713  ASSERT_THAT_EXPECTED(GC1000, Succeeded());2714  ASSERT_EQ(FuncIdx, (size_t)1);2715  llvm::Expected<std::unique_ptr<GsymCreator>> GC2000 =2716      GC.createSegment(128, FuncIdx);2717  ASSERT_THAT_EXPECTED(GC2000, Succeeded());2718  ASSERT_EQ(FuncIdx, (size_t)2);2719  llvm::Expected<std::unique_ptr<GsymCreator>> GC3000 =2720      GC.createSegment(128, FuncIdx);2721  ASSERT_THAT_EXPECTED(GC3000, Succeeded());2722  ASSERT_EQ(FuncIdx, (size_t)3);2723  llvm::Expected<std::unique_ptr<GsymCreator>> GC4000 =2724      GC.createSegment(128, FuncIdx);2725  ASSERT_THAT_EXPECTED(GC4000, Succeeded());2726  ASSERT_EQ(FuncIdx, (size_t)4);2727  // When there are no function infos left to encode we expect to get  no error2728  // and get a NULL GsymCreator in the return value from createSegment.2729  llvm::Expected<std::unique_ptr<GsymCreator>> GCNull =2730      GC.createSegment(128, FuncIdx);2731  ASSERT_THAT_EXPECTED(GCNull, Succeeded());2732  ASSERT_TRUE(GC1000.get() != nullptr);2733  ASSERT_TRUE(GC2000.get() != nullptr);2734  ASSERT_TRUE(GC3000.get() != nullptr);2735  ASSERT_TRUE(GC4000.get() != nullptr);2736  ASSERT_TRUE(GCNull.get() == nullptr);2737  // Encode and decode the GsymReader for each segment and verify they succeed.2738  Expected<GsymReader> GR1000 = FinalizeEncodeAndDecode(*GC1000.get());2739  ASSERT_THAT_EXPECTED(GR1000, Succeeded());2740  Expected<GsymReader> GR2000 = FinalizeEncodeAndDecode(*GC2000.get());2741  ASSERT_THAT_EXPECTED(GR2000, Succeeded());2742  Expected<GsymReader> GR3000 = FinalizeEncodeAndDecode(*GC3000.get());2743  ASSERT_THAT_EXPECTED(GR3000, Succeeded());2744  Expected<GsymReader> GR4000 = FinalizeEncodeAndDecode(*GC4000.get());2745  ASSERT_THAT_EXPECTED(GR4000, Succeeded());2746 2747  // Verify that all lookups match the range [0x1000-0x1030) when doing lookups2748  // in the GsymReader that contains all functions and from the segmented2749  // GsymReader in GR1000.2750  for (uint64_t Addr = 0x1000; Addr < 0x1030; ++Addr) {2751    // Lookup in the main GsymReader that contains all function infos2752    auto MainLR = GR->lookup(Addr);2753    ASSERT_THAT_EXPECTED(MainLR, Succeeded());2754    auto SegmentLR = GR1000->lookup(Addr);2755    ASSERT_THAT_EXPECTED(SegmentLR, Succeeded());2756    // Make sure the lookup results match.2757    EXPECT_EQ(MainLR.get(), SegmentLR.get());2758    // Make sure that the lookups on the functions that are not in the segment2759    // fail as expected.2760    ASSERT_THAT_EXPECTED(GR1000->lookup(0x2000), Failed());2761    ASSERT_THAT_EXPECTED(GR1000->lookup(0x3000), Failed());2762    ASSERT_THAT_EXPECTED(GR1000->lookup(0x4000), Failed());2763  }2764 2765  // Verify that all lookups match the range [0x2000-0x2030) when doing lookups2766  // in the GsymReader that contains all functions and from the segmented2767  // GsymReader in GR2000.2768  for (uint64_t Addr = 0x2000; Addr < 0x2030; ++Addr) {2769    // Lookup in the main GsymReader that contains all function infos2770    auto MainLR = GR->lookup(Addr);2771    ASSERT_THAT_EXPECTED(MainLR, Succeeded());2772    auto SegmentLR = GR2000->lookup(Addr);2773    ASSERT_THAT_EXPECTED(SegmentLR, Succeeded());2774    // Make sure the lookup results match.2775    EXPECT_EQ(MainLR.get(), SegmentLR.get());2776    // Make sure that the lookups on the functions that are not in the segment2777    // fail as expected.2778    ASSERT_THAT_EXPECTED(GR2000->lookup(0x1000), Failed());2779    ASSERT_THAT_EXPECTED(GR2000->lookup(0x3000), Failed());2780    ASSERT_THAT_EXPECTED(GR2000->lookup(0x4000), Failed());2781 2782  }2783 2784  // Verify that all lookups match the range [0x3000-0x3030) when doing lookups2785  // in the GsymReader that contains all functions and from the segmented2786  // GsymReader in GR3000.2787  for (uint64_t Addr = 0x3000; Addr < 0x3030; ++Addr) {2788    // Lookup in the main GsymReader that contains all function infos2789    auto MainLR = GR->lookup(Addr);2790    ASSERT_THAT_EXPECTED(MainLR, Succeeded());2791    auto SegmentLR = GR3000->lookup(Addr);2792    ASSERT_THAT_EXPECTED(SegmentLR, Succeeded());2793    // Make sure the lookup results match.2794    EXPECT_EQ(MainLR.get(), SegmentLR.get());2795    // Make sure that the lookups on the functions that are not in the segment2796    // fail as expected.2797    ASSERT_THAT_EXPECTED(GR3000->lookup(0x1000), Failed());2798    ASSERT_THAT_EXPECTED(GR3000->lookup(0x2000), Failed());2799    ASSERT_THAT_EXPECTED(GR3000->lookup(0x4000), Failed());2800}2801 2802  // Verify that all lookups match the range [0x4000-0x4030) when doing lookups2803  // in the GsymReader that contains all functions and from the segmented2804  // GsymReader in GR4000.2805  for (uint64_t Addr = 0x4000; Addr < 0x4030; ++Addr) {2806    // Lookup in the main GsymReader that contains all function infos2807    auto MainLR = GR->lookup(Addr);2808    ASSERT_THAT_EXPECTED(MainLR, Succeeded());2809    // Lookup in the GsymReader for that contains 0x40002810    auto SegmentLR = GR4000->lookup(Addr);2811    ASSERT_THAT_EXPECTED(SegmentLR, Succeeded());2812    // Make sure the lookup results match.2813    EXPECT_EQ(MainLR.get(), SegmentLR.get());2814    // Make sure that the lookups on the functions that are not in the segment2815    // fail as expected.2816    ASSERT_THAT_EXPECTED(GR4000->lookup(0x1000), Failed());2817    ASSERT_THAT_EXPECTED(GR4000->lookup(0x2000), Failed());2818    ASSERT_THAT_EXPECTED(GR4000->lookup(0x3000), Failed());2819  }2820}2821 2822 2823TEST(GSYMTest, TestDWARFInlineRangeScopes) {2824  // Test cases where inlined functions address ranges are not contained in the2825  // parent ranges and that we can successfully remove them and emit error2826  // messages. The DWARF for this looks like the dump below. The inlined2827  // functions named "invalid1" and "invalid2" are expected to be removed and2828  // an appropriate error message will be emitted.2829  //2830  // 0x0000000b: DW_TAG_compile_unit2831  //               DW_AT_name	("/tmp/main.cpp")2832  //               DW_AT_language	(DW_LANG_C)2833  //               DW_AT_stmt_list	(0x00000000)2834  //2835  // 0x00000015:   DW_TAG_subprogram2836  //                 DW_AT_name	("foo")2837  //                 DW_AT_low_pc	(0x0000000000001000)2838  //                 DW_AT_high_pc	(0x0000000000002000)2839  //2840  // 0x0000002a:     DW_TAG_inlined_subroutine2841  //                   DW_AT_name	("invalid1")2842  //                   DW_AT_low_pc	(0x0000000000000fff)2843  //                   DW_AT_high_pc	(0x0000000000001001)2844  //                   DW_AT_call_file	("/tmp/main.cpp")2845  //                   DW_AT_call_line	(10)2846  //2847  // 0x00000041:     DW_TAG_inlined_subroutine2848  //                   DW_AT_name	("valid1")2849  //                   DW_AT_low_pc	(0x0000000000001010)2850  //                   DW_AT_high_pc	(0x0000000000001100)2851  //                   DW_AT_call_file	("/tmp/main.cpp")2852  //                   DW_AT_call_line	(11)2853  //2854  // 0x00000058:       DW_TAG_inlined_subroutine2855  //                     DW_AT_name	("invalid2")2856  //                     DW_AT_low_pc	(0x0000000000001000)2857  //                     DW_AT_high_pc	(0x0000000000001100)2858  //                     DW_AT_call_file	("/tmp/main.cpp")2859  //                     DW_AT_call_line	(12)2860  //2861  // 0x0000006f:       DW_TAG_inlined_subroutine2862  //                     DW_AT_name	("valid2")2863  //                     DW_AT_low_pc	(0x0000000000001020)2864  //                     DW_AT_high_pc	(0x0000000000001030)2865  //                     DW_AT_call_file	("/tmp/main.cpp")2866  //                     DW_AT_call_line	(13)2867  //2868  // 0x00000086:       NULL2869  //2870  // 0x00000087:     NULL2871  //2872  // 0x00000088:   NULL2873 2874  StringRef yamldata = R"(2875  debug_str:2876    - ''2877    - '/tmp/main.cpp'2878    - foo2879    - invalid12880    - valid12881    - invalid22882    - valid22883  debug_abbrev:2884    - ID:              02885      Table:2886        - Code:            0x12887          Tag:             DW_TAG_compile_unit2888          Children:        DW_CHILDREN_yes2889          Attributes:2890            - Attribute:       DW_AT_name2891              Form:            DW_FORM_strp2892            - Attribute:       DW_AT_language2893              Form:            DW_FORM_udata2894            - Attribute:       DW_AT_stmt_list2895              Form:            DW_FORM_sec_offset2896        - Code:            0x22897          Tag:             DW_TAG_subprogram2898          Children:        DW_CHILDREN_yes2899          Attributes:2900            - Attribute:       DW_AT_name2901              Form:            DW_FORM_strp2902            - Attribute:       DW_AT_low_pc2903              Form:            DW_FORM_addr2904            - Attribute:       DW_AT_high_pc2905              Form:            DW_FORM_addr2906        - Code:            0x32907          Tag:             DW_TAG_inlined_subroutine2908          Children:        DW_CHILDREN_no2909          Attributes:2910            - Attribute:       DW_AT_name2911              Form:            DW_FORM_strp2912            - Attribute:       DW_AT_low_pc2913              Form:            DW_FORM_addr2914            - Attribute:       DW_AT_high_pc2915              Form:            DW_FORM_addr2916            - Attribute:       DW_AT_call_file2917              Form:            DW_FORM_data12918            - Attribute:       DW_AT_call_line2919              Form:            DW_FORM_data12920        - Code:            0x42921          Tag:             DW_TAG_inlined_subroutine2922          Children:        DW_CHILDREN_yes2923          Attributes:2924            - Attribute:       DW_AT_name2925              Form:            DW_FORM_strp2926            - Attribute:       DW_AT_low_pc2927              Form:            DW_FORM_addr2928            - Attribute:       DW_AT_high_pc2929              Form:            DW_FORM_addr2930            - Attribute:       DW_AT_call_file2931              Form:            DW_FORM_data12932            - Attribute:       DW_AT_call_line2933              Form:            DW_FORM_data12934  debug_info:2935    - Length:          0x852936      Version:         42937      AbbrevTableID:   02938      AbbrOffset:      0x02939      AddrSize:        82940      Entries:2941        - AbbrCode:        0x12942          Values:2943            - Value:           0x12944            - Value:           0x22945            - Value:           0x02946        - AbbrCode:        0x22947          Values:2948            - Value:           0xF2949            - Value:           0x10002950            - Value:           0x20002951        - AbbrCode:        0x32952          Values:2953            - Value:           0x132954            - Value:           0xFFF2955            - Value:           0x10012956            - Value:           0x12957            - Value:           0xA2958        - AbbrCode:        0x42959          Values:2960            - Value:           0x1C2961            - Value:           0x10102962            - Value:           0x11002963            - Value:           0x12964            - Value:           0xB2965        - AbbrCode:        0x32966          Values:2967            - Value:           0x232968            - Value:           0x10002969            - Value:           0x11002970            - Value:           0x12971            - Value:           0xC2972        - AbbrCode:        0x32973          Values:2974            - Value:           0x2C2975            - Value:           0x10202976            - Value:           0x10302977            - Value:           0x12978            - Value:           0xD2979        - AbbrCode:        0x02980        - AbbrCode:        0x02981        - AbbrCode:        0x02982  debug_line:2983    - Length:          842984      Version:         22985      PrologueLength:  362986      MinInstLength:   12987      DefaultIsStmt:   12988      LineBase:        2512989      LineRange:       142990      OpcodeBase:      132991      StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]2992      IncludeDirs:2993        - '/tmp'2994      Files:2995        - Name:            main.cpp2996          DirIdx:          12997          ModTime:         02998          Length:          02999      Opcodes:3000        - Opcode:          DW_LNS_extended_op3001          ExtLen:          93002          SubOpcode:       DW_LNE_set_address3003          Data:            40963004        - Opcode:          DW_LNS_advance_line3005          SData:           93006          Data:            03007        - Opcode:          DW_LNS_copy3008          Data:            03009        - Opcode:          DW_LNS_advance_pc3010          Data:            163011        - Opcode:          DW_LNS_advance_line3012          SData:           13013          Data:            03014        - Opcode:          DW_LNS_copy3015          Data:            03016        - Opcode:          DW_LNS_advance_pc3017          Data:            163018        - Opcode:          DW_LNS_advance_line3019          SData:           13020          Data:            03021        - Opcode:          DW_LNS_copy3022          Data:            03023        - Opcode:          DW_LNS_advance_pc3024          Data:            163025        - Opcode:          DW_LNS_advance_line3026          SData:           13027          Data:            03028        - Opcode:          DW_LNS_copy3029          Data:            03030        - Opcode:          DW_LNS_advance_pc3031          Data:            40483032        - Opcode:          DW_LNS_advance_line3033          SData:           13034          Data:            03035        - Opcode:          DW_LNS_copy3036          Data:            03037        - Opcode:          DW_LNS_advance_pc3038          Data:            163039        - Opcode:          DW_LNS_advance_line3040          SData:           -13041          Data:            03042        - Opcode:          DW_LNS_extended_op3043          ExtLen:          13044          SubOpcode:       DW_LNE_end_sequence3045          Data:            03046  )";3047  auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);3048  ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());3049  std::unique_ptr<DWARFContext> DwarfContext =3050      DWARFContext::create(*ErrOrSections, 8);3051  ASSERT_TRUE(DwarfContext.get() != nullptr);3052  std::string errors;3053  raw_string_ostream OS(errors);3054  OutputAggregator OSAgg(&OS);3055  GsymCreator GC;3056  DwarfTransformer DT(*DwarfContext, GC);3057  const uint32_t ThreadCount = 1;3058  ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());3059  ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());3060  SmallString<512> Str;3061  raw_svector_ostream OutStrm(Str);3062  const auto ByteOrder = llvm::endianness::native;3063  FileWriter FW(OutStrm, ByteOrder);3064  ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());3065  Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());3066  ASSERT_THAT_EXPECTED(GR, Succeeded());3067  // There should only be one function in our GSYM.3068  EXPECT_EQ(GR->getNumAddresses(), 1u);3069  auto ExpFI = GR->getFunctionInfo(0x1000);3070  ASSERT_THAT_EXPECTED(ExpFI, Succeeded());3071  ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x2000));3072  EXPECT_TRUE(ExpFI->OptLineTable.has_value());3073  EXPECT_TRUE(ExpFI->Inline.has_value());3074  StringRef FuncName = GR->getString(ExpFI->Name);3075  EXPECT_EQ(FuncName, "foo");3076  std::vector<std::string> ExpectedLogErrors = {3077    "error: inlined function DIE at 0x0000002a has a range [0x0000000000000fff "3078    "- 0x0000000000001001) that isn't contained in any parent address ranges, "3079    "this inline range will be removed.",3080    "error: inlined function DIE at 0x00000058 has a range [0x0000000000001000 "3081    "- 0x0000000000001100) that isn't contained in any parent address ranges, "3082    "this inline range will be removed."3083  };3084  // Make sure all expected errors are in the error stream for the two invalid3085  // inlined functions that we removed due to invalid range scoping.3086  for (const auto &Error: ExpectedLogErrors) {3087    EXPECT_TRUE(OS.str().find(Error) != std::string::npos);3088  }3089  // The top level inline info is for the function "foo" itself. Verify that3090  // we have only 1 inline function inside of this, even though the DWARF3091  // contains two. One of the inline functions in "foo" is invalid, so we must3092  // only end up with 1.3093  StringRef InlineFuncName = GR->getString(ExpFI->Inline->Name);3094  EXPECT_EQ(InlineFuncName, "foo");3095  EXPECT_EQ(ExpFI->Inline->CallFile, 0u);3096  EXPECT_EQ(ExpFI->Inline->CallLine, 0u);3097  EXPECT_EQ(ExpFI->Inline->Children.size(), 1u);3098 3099 3100  // The first inline function "valid1" contains two inline functions in the3101  // DWARF, but one has an address range which isn't contained in any ranges3102  // from "foo", so only 1 inline function be parsed.3103  InlineInfo &Inline1 = ExpFI->Inline->Children[0];3104  StringRef Inline1Name = GR->getString(Inline1.Name);3105  EXPECT_EQ(Inline1Name, "valid1");3106  EXPECT_EQ(Inline1.CallFile, 1u);3107  EXPECT_EQ(Inline1.CallLine, 11u);3108  EXPECT_EQ(Inline1.Children.size(), 1u);3109 3110 3111  // The second inline function "valid2" contains two inline functions in the3112  // DWARF, but one has an address range which isn't contained in any ranges3113  // from "valid1", so only 1 inline function be parsed.3114  InlineInfo &Inline2 = Inline1.Children[0];3115  StringRef Inline2Name = GR->getString(Inline2.Name);3116  EXPECT_EQ(Inline2Name, "valid2");3117  EXPECT_EQ(Inline2.CallFile, 1u);3118  EXPECT_EQ(Inline2.CallLine, 13u);3119  EXPECT_EQ(Inline2.Children.size(), 0u);3120}3121 3122TEST(GSYMTest, TestDWARFEmptyInline) {3123  // Test cases where we have inline function information in the DWARF that3124  // results in us trying to parse the inline info, but since the inline3125  // info ends up not adding any valid inline functions due to ranges3126  // not being correct, we end up not encoding any inline information. This3127  // tests that if we end up creating an empty inline info struct, we end up3128  // not encoding it into the GSYM file.3129  //3130  // 0x0000000b: DW_TAG_compile_unit3131  //               DW_AT_name	("/tmp/main.cpp")3132  //               DW_AT_language	(DW_LANG_C)3133  //               DW_AT_stmt_list	(0x00000000)3134  //3135  // 0x00000015:   DW_TAG_subprogram3136  //                 DW_AT_name	("foo")3137  //                 DW_AT_low_pc	(0x0000000000001000)3138  //                 DW_AT_high_pc	(0x0000000000001050)3139  //3140  // 0x0000002a:     DW_TAG_inlined_subroutine3141  //                   DW_AT_name	("inlineWithInvalidRange")3142  //                   DW_AT_low_pc	(0x0000000000001100)3143  //                   DW_AT_high_pc	(0x0000000000001200)3144  //                   DW_AT_call_file	("/tmp/main.cpp")3145  //                   DW_AT_call_line	(11)3146  //3147  // 0x00000047:     NULL3148  //3149  // 0x00000048:   NULL3150 3151  StringRef yamldata = R"(3152  debug_str:3153    - ''3154    - '/tmp/main.cpp'3155    - foo3156    - inlineWithInvalidRange3157  debug_abbrev:3158    - ID:              03159      Table:3160        - Code:            0x13161          Tag:             DW_TAG_compile_unit3162          Children:        DW_CHILDREN_yes3163          Attributes:3164            - Attribute:       DW_AT_name3165              Form:            DW_FORM_strp3166            - Attribute:       DW_AT_language3167              Form:            DW_FORM_udata3168            - Attribute:       DW_AT_stmt_list3169              Form:            DW_FORM_sec_offset3170        - Code:            0x23171          Tag:             DW_TAG_subprogram3172          Children:        DW_CHILDREN_yes3173          Attributes:3174            - Attribute:       DW_AT_name3175              Form:            DW_FORM_strp3176            - Attribute:       DW_AT_low_pc3177              Form:            DW_FORM_addr3178            - Attribute:       DW_AT_high_pc3179              Form:            DW_FORM_addr3180        - Code:            0x33181          Tag:             DW_TAG_inlined_subroutine3182          Children:        DW_CHILDREN_no3183          Attributes:3184            - Attribute:       DW_AT_name3185              Form:            DW_FORM_strp3186            - Attribute:       DW_AT_low_pc3187              Form:            DW_FORM_addr3188            - Attribute:       DW_AT_high_pc3189              Form:            DW_FORM_addr3190            - Attribute:       DW_AT_call_file3191              Form:            DW_FORM_data43192            - Attribute:       DW_AT_call_line3193              Form:            DW_FORM_data43194  debug_info:3195    - Length:          0x453196      Version:         43197      AbbrevTableID:   03198      AbbrOffset:      0x03199      AddrSize:        83200      Entries:3201        - AbbrCode:        0x13202          Values:3203            - Value:           0x13204            - Value:           0x23205            - Value:           0x03206        - AbbrCode:        0x23207          Values:3208            - Value:           0xF3209            - Value:           0x10003210            - Value:           0x10503211        - AbbrCode:        0x33212          Values:3213            - Value:           0x133214            - Value:           0x11003215            - Value:           0x12003216            - Value:           0x13217            - Value:           0xB3218        - AbbrCode:        0x03219        - AbbrCode:        0x03220  debug_line:3221    - Length:          763222      Version:         23223      PrologueLength:  363224      MinInstLength:   13225      DefaultIsStmt:   13226      LineBase:        2513227      LineRange:       143228      OpcodeBase:      133229      StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]3230      IncludeDirs:3231        - '/tmp'3232      Files:3233        - Name:            main.cpp3234          DirIdx:          13235          ModTime:         03236          Length:          03237      Opcodes:3238        - Opcode:          DW_LNS_extended_op3239          ExtLen:          93240          SubOpcode:       DW_LNE_set_address3241          Data:            40963242        - Opcode:          DW_LNS_advance_line3243          SData:           93244          Data:            03245        - Opcode:          DW_LNS_copy3246          Data:            03247        - Opcode:          DW_LNS_advance_pc3248          Data:            163249        - Opcode:          DW_LNS_advance_line3250          SData:           13251          Data:            03252        - Opcode:          DW_LNS_copy3253          Data:            03254        - Opcode:          DW_LNS_advance_pc3255          Data:            163256        - Opcode:          DW_LNS_advance_line3257          SData:           13258          Data:            03259        - Opcode:          DW_LNS_copy3260          Data:            03261        - Opcode:          DW_LNS_advance_pc3262          Data:            163263        - Opcode:          DW_LNS_advance_line3264          SData:           13265          Data:            03266        - Opcode:          DW_LNS_copy3267          Data:            03268        - Opcode:          DW_LNS_advance_pc3269          Data:            323270        - Opcode:          DW_LNS_extended_op3271          ExtLen:          13272          SubOpcode:       DW_LNE_end_sequence3273          Data:            03274  )";3275  auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);3276  ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());3277  std::unique_ptr<DWARFContext> DwarfContext =3278      DWARFContext::create(*ErrOrSections, 8);3279  ASSERT_TRUE(DwarfContext.get() != nullptr);3280  std::string errors;3281  raw_string_ostream OS(errors);3282  OutputAggregator OSAgg(&OS);3283  GsymCreator GC;3284  DwarfTransformer DT(*DwarfContext, GC);3285  const uint32_t ThreadCount = 1;3286  ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());3287  ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());3288  SmallString<512> Str;3289  raw_svector_ostream OutStrm(Str);3290  const auto ByteOrder = llvm::endianness::native;3291  FileWriter FW(OutStrm, ByteOrder);3292  ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());3293  Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());3294  ASSERT_THAT_EXPECTED(GR, Succeeded());3295  // There should only be one function in our GSYM.3296  EXPECT_EQ(GR->getNumAddresses(), 1u);3297  auto ExpFI = GR->getFunctionInfo(0x1000);3298  ASSERT_THAT_EXPECTED(ExpFI, Succeeded());3299  ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x1050));3300  EXPECT_TRUE(ExpFI->OptLineTable.has_value());3301  EXPECT_FALSE(ExpFI->Inline.has_value());3302  StringRef FuncName = GR->getString(ExpFI->Name);3303  EXPECT_EQ(FuncName, "foo");3304  std::vector<std::string> ExpectedLogErrors = {3305    "error: inlined function DIE at 0x0000002a has a range [0x0000000000001100"3306    " - 0x0000000000001200) that isn't contained in any parent address ranges,"3307    " this inline range will be removed.",3308    "warning: DIE contains inline function information that has no valid "3309    "ranges, removing inline information:",3310  };3311  // Make sure all expected errors are in the error stream for the two invalid3312  // inlined functions that we removed due to invalid range scoping.3313  for (const auto &Error: ExpectedLogErrors) {3314    EXPECT_TRUE(OS.str().find(Error) != std::string::npos);3315  }3316}3317 3318TEST(GSYMTest, TestFinalizeForLineTables) {3319  // This example has two compile units:3320  // - one contains a function "foo" with line table entries and "bar" without3321  // - one contains a function "bar" with line table entries and "foo" without3322  // This test ensures that no matter what order information gets processed,3323  // we want to make sure that we prioritize the entries with the most debug3324  // info.3325  //3326  // The DWARF is the same for the functions, but the first compile unit has3327  // lines entries for "foo" and the second one doesn't. And the first compile3328  // unit has no line entries for "bar", but the second one does. We expect the3329  // resulting gsym file to have a "foo" and "bar" that both have line entries.3330  //3331  // 0x0000000b: DW_TAG_compile_unit3332  //               DW_AT_name	("/tmp/main.cpp")3333  //               DW_AT_language	(DW_LANG_C)3334  //               DW_AT_stmt_list	(0x00000000)3335  //3336  // 0x00000015:   DW_TAG_subprogram3337  //                 DW_AT_name	("foo")3338  //                 DW_AT_low_pc	(0x0000000000001000)3339  //                 DW_AT_high_pc	(0x0000000000001050)3340  //3341  // 0x0000002a:   DW_TAG_subprogram3342  //                 DW_AT_name	("bar")3343  //                 DW_AT_low_pc	(0x0000000000002000)3344  //                 DW_AT_high_pc	(0x0000000000002050)3345  //3346  // 0x0000003f:   NULL3347  // 0x00000040: Compile Unit: length = 0x0000003c, format = DWARF32, version = 0x0004, abbr_offset = 0x0000, addr_size = 0x08 (next unit at 0x00000080)3348  //3349  // 0x0000004b: DW_TAG_compile_unit3350  //               DW_AT_name	("/tmp/main.cpp")3351  //               DW_AT_language	(DW_LANG_C)3352  //               DW_AT_stmt_list	(0x00000043)3353  //3354  // 0x00000055:   DW_TAG_subprogram3355  //                 DW_AT_name	("foo")3356  //                 DW_AT_low_pc	(0x0000000000001000)3357  //                 DW_AT_high_pc	(0x0000000000001050)3358  //3359  // 0x0000006a:   DW_TAG_subprogram3360  //                 DW_AT_name	("bar")3361  //                 DW_AT_low_pc	(0x0000000000002000)3362  //                 DW_AT_high_pc	(0x0000000000002050)3363  //3364  // 0x0000007f:   NULL3365 3366  StringRef yamldata = R"(3367  debug_str:3368    - ''3369    - '/tmp/main.cpp'3370    - foo3371    - bar3372  debug_abbrev:3373    - ID:              03374      Table:3375        - Code:            0x13376          Tag:             DW_TAG_compile_unit3377          Children:        DW_CHILDREN_yes3378          Attributes:3379            - Attribute:       DW_AT_name3380              Form:            DW_FORM_strp3381            - Attribute:       DW_AT_language3382              Form:            DW_FORM_udata3383            - Attribute:       DW_AT_stmt_list3384              Form:            DW_FORM_sec_offset3385        - Code:            0x23386          Tag:             DW_TAG_subprogram3387          Children:        DW_CHILDREN_no3388          Attributes:3389            - Attribute:       DW_AT_name3390              Form:            DW_FORM_strp3391            - Attribute:       DW_AT_low_pc3392              Form:            DW_FORM_addr3393            - Attribute:       DW_AT_high_pc3394              Form:            DW_FORM_addr3395  debug_info:3396    - Length:          0x3C3397      Version:         43398      AbbrevTableID:   03399      AbbrOffset:      0x03400      AddrSize:        83401      Entries:3402        - AbbrCode:        0x13403          Values:3404            - Value:           0x13405            - Value:           0x23406            - Value:           0x03407        - AbbrCode:        0x23408          Values:3409            - Value:           0xF3410            - Value:           0x10003411            - Value:           0x10503412        - AbbrCode:        0x23413          Values:3414            - Value:           0x133415            - Value:           0x20003416            - Value:           0x20503417        - AbbrCode:        0x03418    - Length:          0x3C3419      Version:         43420      AbbrevTableID:   03421      AbbrOffset:      0x03422      AddrSize:        83423      Entries:3424        - AbbrCode:        0x13425          Values:3426            - Value:           0x13427            - Value:           0x23428            - Value:           0x433429        - AbbrCode:        0x23430          Values:3431            - Value:           0xF3432            - Value:           0x10003433            - Value:           0x10503434        - AbbrCode:        0x23435          Values:3436            - Value:           0x133437            - Value:           0x20003438            - Value:           0x20503439        - AbbrCode:        0x03440  debug_line:3441    - Length:          633442      Version:         23443      PrologueLength:  363444      MinInstLength:   13445      DefaultIsStmt:   13446      LineBase:        2513447      LineRange:       143448      OpcodeBase:      133449      StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]3450      IncludeDirs:3451        - '/tmp'3452      Files:3453        - Name:            main.cpp3454          DirIdx:          13455          ModTime:         03456          Length:          03457      Opcodes:3458        - Opcode:          DW_LNS_extended_op3459          ExtLen:          93460          SubOpcode:       DW_LNE_set_address3461          Data:            40963462        - Opcode:          DW_LNS_advance_line3463          SData:           93464          Data:            03465        - Opcode:          DW_LNS_copy3466          Data:            03467        - Opcode:          DW_LNS_advance_pc3468          Data:            803469        - Opcode:          DW_LNS_advance_line3470          SData:           13471          Data:            03472        - Opcode:          DW_LNS_extended_op3473          ExtLen:          13474          SubOpcode:       DW_LNE_end_sequence3475          Data:            03476    - Length:          633477      Version:         23478      PrologueLength:  363479      MinInstLength:   13480      DefaultIsStmt:   13481      LineBase:        2513482      LineRange:       143483      OpcodeBase:      133484      StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]3485      IncludeDirs:3486        - '/tmp'3487      Files:3488        - Name:            main.cpp3489          DirIdx:          13490          ModTime:         03491          Length:          03492      Opcodes:3493        - Opcode:          DW_LNS_extended_op3494          ExtLen:          93495          SubOpcode:       DW_LNE_set_address3496          Data:            81923497        - Opcode:          DW_LNS_advance_line3498          SData:           193499          Data:            03500        - Opcode:          DW_LNS_copy3501          Data:            03502        - Opcode:          DW_LNS_advance_pc3503          Data:            803504        - Opcode:          DW_LNS_advance_line3505          SData:           13506          Data:            03507        - Opcode:          DW_LNS_extended_op3508          ExtLen:          13509          SubOpcode:       DW_LNE_end_sequence3510          Data:            03511  )";3512  auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);3513  ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());3514  std::unique_ptr<DWARFContext> DwarfContext =3515      DWARFContext::create(*ErrOrSections, 8);3516  ASSERT_TRUE(DwarfContext.get() != nullptr);3517  std::string errors;3518  raw_string_ostream OS(errors);3519  OutputAggregator OSAgg(&OS);3520  GsymCreator GC;3521  DwarfTransformer DT(*DwarfContext, GC);3522  const uint32_t ThreadCount = 1;3523  ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());3524  ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());3525  SmallString<512> Str;3526  raw_svector_ostream OutStrm(Str);3527  const auto ByteOrder = llvm::endianness::native;3528  FileWriter FW(OutStrm, ByteOrder);3529  ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());3530  Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());3531  ASSERT_THAT_EXPECTED(GR, Succeeded());3532  // There should only be two functions in our GSYM.3533  EXPECT_EQ(GR->getNumAddresses(), 2u);3534  // Verify "foo" is present and has a line table3535  auto ExpFI = GR->getFunctionInfo(0x1000);3536  ASSERT_THAT_EXPECTED(ExpFI, Succeeded());3537  ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x1050));3538  EXPECT_TRUE(ExpFI->OptLineTable.has_value());3539  EXPECT_FALSE(ExpFI->Inline.has_value());3540  StringRef FuncName = GR->getString(ExpFI->Name);3541  EXPECT_EQ(FuncName, "foo");3542 3543  // Verify "foo" is present and has a line table3544  auto ExpFI2 = GR->getFunctionInfo(0x2000);3545  ASSERT_THAT_EXPECTED(ExpFI2, Succeeded());3546  ASSERT_EQ(ExpFI2->Range, AddressRange(0x2000, 0x2050));3547  EXPECT_TRUE(ExpFI2->OptLineTable.has_value());3548  EXPECT_FALSE(ExpFI2->Inline.has_value());3549  StringRef FuncName2 = GR->getString(ExpFI2->Name);3550  EXPECT_EQ(FuncName2, "bar");3551}3552 3553 3554TEST(GSYMTest, TestRangeWarnings) {3555  // This example has a single compile unit that has a DW_TAG_subprogram that3556  // has two discontiguous ranges. We will create two FunctionInfo objects for3557  // each range in the function that only contains info for each range. We also3558  // want to verify that we only emit errors and warnings for ranges that3559  // aren't contained in any parent address ranges if this is true. Prior to3560  // this fix we would create two FunctionInfo objects and as each one was3561  // being created we would end up warning about all of the ranges that weren't3562  // in the current FunctionInfo's range even though the DWARF was well formed.3563  // Now we don't incorrectly emit errors when there are none.3564  //3565  // 0x0000000b: DW_TAG_compile_unit3566  //               DW_AT_name	("/tmp/main.cpp")3567  //               DW_AT_language	(DW_LANG_C)3568  //               DW_AT_stmt_list	(0x00000000)3569  //3570  // 0x00000015:   DW_TAG_subprogram3571  //                 DW_AT_name	("foo")3572  //                 DW_AT_ranges	(0x000000003573  //                    [0x0000000000001000, 0x0000000000001050)3574  //                    [0x0000000000002000, 0x0000000000002050))3575  //3576  // 0x0000001e:     DW_TAG_inlined_subroutine3577  //                   DW_AT_name	("inline1")3578  //                   DW_AT_ranges	(0x000000303579  //                      [0x0000000000001010, 0x0000000000001040)3580  //                      [0x0000000000002010, 0x0000000000002040))3581  //                   DW_AT_call_file	("/tmp/main.cpp")3582  //                   DW_AT_call_line	(11)3583  //3584  // 0x0000002f:       DW_TAG_inlined_subroutine3585  //                     DW_AT_name	("inline2")3586  //                     DW_AT_ranges	(0x000000603587  //                        [0x0000000000001015, 0x0000000000001020)3588  //                        [0x0000000000002015, 0x0000000000002020))3589  //                     DW_AT_call_file	("/tmp/inline.h")3590  //                     DW_AT_call_line	(21)3591  //3592  // 0x00000040:       NULL3593  //3594  // 0x00000041:     NULL3595  //3596  // 0x00000042:   NULL3597 3598  StringRef yamldata = R"(3599  debug_str:3600    - ''3601    - '/tmp/main.cpp'3602    - foo3603    - inline13604    - inline23605  debug_abbrev:3606    - ID:              03607      Table:3608        - Code:            0x13609          Tag:             DW_TAG_compile_unit3610          Children:        DW_CHILDREN_yes3611          Attributes:3612            - Attribute:       DW_AT_name3613              Form:            DW_FORM_strp3614            - Attribute:       DW_AT_language3615              Form:            DW_FORM_udata3616            - Attribute:       DW_AT_stmt_list3617              Form:            DW_FORM_sec_offset3618        - Code:            0x23619          Tag:             DW_TAG_subprogram3620          Children:        DW_CHILDREN_yes3621          Attributes:3622            - Attribute:       DW_AT_name3623              Form:            DW_FORM_strp3624            - Attribute:       DW_AT_ranges3625              Form:            DW_FORM_sec_offset3626        - Code:            0x33627          Tag:             DW_TAG_inlined_subroutine3628          Children:        DW_CHILDREN_yes3629          Attributes:3630            - Attribute:       DW_AT_name3631              Form:            DW_FORM_strp3632            - Attribute:       DW_AT_ranges3633              Form:            DW_FORM_sec_offset3634            - Attribute:       DW_AT_call_file3635              Form:            DW_FORM_data43636            - Attribute:       DW_AT_call_line3637              Form:            DW_FORM_data43638        - Code:            0x43639          Tag:             DW_TAG_inlined_subroutine3640          Children:        DW_CHILDREN_no3641          Attributes:3642            - Attribute:       DW_AT_name3643              Form:            DW_FORM_strp3644            - Attribute:       DW_AT_ranges3645              Form:            DW_FORM_sec_offset3646            - Attribute:       DW_AT_call_file3647              Form:            DW_FORM_data43648            - Attribute:       DW_AT_call_line3649              Form:            DW_FORM_data43650  debug_ranges:3651    - Offset:          0x03652      AddrSize:        0x83653      Entries:3654        - LowOffset:       0x10003655          HighOffset:      0x10503656        - LowOffset:       0x20003657          HighOffset:      0x20503658    - Offset:          0x303659      AddrSize:        0x83660      Entries:3661        - LowOffset:       0x10103662          HighOffset:      0x10403663        - LowOffset:       0x20103664          HighOffset:      0x20403665    - Offset:          0x603666      AddrSize:        0x83667      Entries:3668        - LowOffset:       0x10153669          HighOffset:      0x10203670        - LowOffset:       0x20153671          HighOffset:      0x20203672  debug_info:3673    - Length:          0x3F3674      Version:         43675      AbbrevTableID:   03676      AbbrOffset:      0x03677      AddrSize:        83678      Entries:3679        - AbbrCode:        0x13680          Values:3681            - Value:           0x13682            - Value:           0x23683            - Value:           0x03684        - AbbrCode:        0x23685          Values:3686            - Value:           0xF3687            - Value:           0x03688        - AbbrCode:        0x33689          Values:3690            - Value:           0x133691            - Value:           0x303692            - Value:           0x13693            - Value:           0xB3694        - AbbrCode:        0x43695          Values:3696            - Value:           0x1B3697            - Value:           0x603698            - Value:           0x23699            - Value:           0x153700        - AbbrCode:        0x03701        - AbbrCode:        0x03702        - AbbrCode:        0x03703  debug_line:3704    - Length:          1203705      Version:         23706      PrologueLength:  483707      MinInstLength:   13708      DefaultIsStmt:   13709      LineBase:        2513710      LineRange:       143711      OpcodeBase:      133712      StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]3713      IncludeDirs:3714        - '/tmp'3715      Files:3716        - Name:            main.cpp3717          DirIdx:          13718          ModTime:         03719          Length:          03720        - Name:            inline.h3721          DirIdx:          13722          ModTime:         03723          Length:          03724      Opcodes:3725        - Opcode:          DW_LNS_extended_op3726          ExtLen:          93727          SubOpcode:       DW_LNE_set_address3728          Data:            40963729        - Opcode:          DW_LNS_advance_line3730          SData:           93731          Data:            03732        - Opcode:          DW_LNS_copy3733          Data:            03734        - Opcode:          DW_LNS_advance_pc3735          Data:            163736        - Opcode:          DW_LNS_set_file3737          Data:            23738        - Opcode:          DW_LNS_advance_line3739          SData:           103740          Data:            03741        - Opcode:          DW_LNS_copy3742          Data:            03743        - Opcode:          DW_LNS_advance_pc3744          Data:            163745        - Opcode:          DW_LNS_advance_line3746          SData:           13747          Data:            03748        - Opcode:          DW_LNS_copy3749          Data:            03750        - Opcode:          DW_LNS_advance_pc3751          Data:            483752        - Opcode:          DW_LNS_set_file3753          Data:            13754        - Opcode:          DW_LNS_advance_line3755          SData:           -103756          Data:            03757        - Opcode:          DW_LNS_extended_op3758          ExtLen:          13759          SubOpcode:       DW_LNE_end_sequence3760          Data:            03761        - Opcode:          DW_LNS_extended_op3762          ExtLen:          93763          SubOpcode:       DW_LNE_set_address3764          Data:            81923765        - Opcode:          DW_LNS_advance_line3766          SData:           193767          Data:            03768        - Opcode:          DW_LNS_copy3769          Data:            03770        - Opcode:          DW_LNS_advance_pc3771          Data:            163772        - Opcode:          DW_LNS_set_file3773          Data:            23774        - Opcode:          DW_LNS_copy3775          Data:            03776        - Opcode:          DW_LNS_advance_pc3777          Data:            163778        - Opcode:          DW_LNS_advance_line3779          SData:           13780          Data:            03781        - Opcode:          DW_LNS_copy3782          Data:            03783        - Opcode:          DW_LNS_advance_pc3784          Data:            483785        - Opcode:          DW_LNS_set_file3786          Data:            13787        - Opcode:          DW_LNS_extended_op3788          ExtLen:          13789          SubOpcode:       DW_LNE_end_sequence3790          Data:            03791  )";3792  auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);3793  ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());3794  std::unique_ptr<DWARFContext> DwarfContext =3795      DWARFContext::create(*ErrOrSections, 8);3796  ASSERT_TRUE(DwarfContext.get() != nullptr);3797  std::string errors;3798  raw_string_ostream OS(errors);3799  OutputAggregator OSAgg(&OS);3800  GsymCreator GC;3801  DwarfTransformer DT(*DwarfContext, GC);3802  const uint32_t ThreadCount = 1;3803  ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());3804  ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());3805  SmallString<512> Str;3806  raw_svector_ostream OutStrm(Str);3807  const auto ByteOrder = llvm::endianness::native;3808  FileWriter FW(OutStrm, ByteOrder);3809  ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());3810  Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());3811  ASSERT_THAT_EXPECTED(GR, Succeeded());3812  // There should be two functions in our GSYM.3813  EXPECT_EQ(GR->getNumAddresses(), 2u);3814  // Verify "foo" is present and has a line table3815  auto ExpFI = GR->getFunctionInfo(0x1000);3816  ASSERT_THAT_EXPECTED(ExpFI, Succeeded());3817  ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x1050));3818  EXPECT_TRUE(ExpFI->OptLineTable.has_value());3819  EXPECT_TRUE(ExpFI->Inline.has_value());3820  StringRef FuncName = GR->getString(ExpFI->Name);3821  EXPECT_EQ(FuncName, "foo");3822 3823  // Verify "foo" is present and has a line table3824  auto ExpFI2 = GR->getFunctionInfo(0x2000);3825  ASSERT_THAT_EXPECTED(ExpFI2, Succeeded());3826  ASSERT_EQ(ExpFI2->Range, AddressRange(0x2000, 0x2050));3827  EXPECT_TRUE(ExpFI2->OptLineTable.has_value());3828  EXPECT_TRUE(ExpFI2->Inline.has_value());3829  StringRef FuncName2 = GR->getString(ExpFI2->Name);3830  EXPECT_EQ(FuncName2, "foo");3831 3832  // Make sure we don't see spurious errors in the output:3833  EXPECT_TRUE(errors.find("error:") == std::string::npos);3834}3835 3836TEST(GSYMTest, TestEmptyRangeWarnings) {3837  // This example has a single compile unit that has a DW_TAG_subprogram that3838  // has a function that contains an inlined function that has an empty range.3839  // We want to make sure that if we run into only empty inline functions3840  // inside of a real function, that we don't end up with inline information3841  // in the GSYM and we don't warn about the inline function's range not being3842  // contined in the parent ranges since it is ok for inline functions to be3843  // elided.3844  //3845  // 0x0000000b: DW_TAG_compile_unit3846  //               DW_AT_name	("/tmp/main.cpp")3847  //               DW_AT_language	(DW_LANG_C)3848  //               DW_AT_stmt_list	(0x00000000)3849  //3850  // 0x00000015:   DW_TAG_subprogram3851  //                 DW_AT_name	("foo")3852  //                 DW_AT_low_pc	(0x0000000000001000)3853  //                 DW_AT_high_pc	(0x0000000000001050)3854  //3855  // 0x0000002a:     DW_TAG_inlined_subroutine3856  //                   DW_AT_name	("inline1")3857  //                   DW_AT_low_pc	(0x0000000000001010)3858  //                   DW_AT_high_pc	(0x0000000000001010)3859  //                   DW_AT_call_file	("/tmp/main.cpp")3860  //                   DW_AT_call_line	(11)3861  //3862  // 0x00000047:     NULL3863  //3864  // 0x00000048:   NULL3865 3866  StringRef yamldata = R"(3867  debug_str:3868    - ''3869    - '/tmp/main.cpp'3870    - foo3871    - inline13872  debug_abbrev:3873    - ID:              03874      Table:3875        - Code:            0x13876          Tag:             DW_TAG_compile_unit3877          Children:        DW_CHILDREN_yes3878          Attributes:3879            - Attribute:       DW_AT_name3880              Form:            DW_FORM_strp3881            - Attribute:       DW_AT_language3882              Form:            DW_FORM_udata3883            - Attribute:       DW_AT_stmt_list3884              Form:            DW_FORM_sec_offset3885        - Code:            0x23886          Tag:             DW_TAG_subprogram3887          Children:        DW_CHILDREN_yes3888          Attributes:3889            - Attribute:       DW_AT_name3890              Form:            DW_FORM_strp3891            - Attribute:       DW_AT_low_pc3892              Form:            DW_FORM_addr3893            - Attribute:       DW_AT_high_pc3894              Form:            DW_FORM_addr3895        - Code:            0x33896          Tag:             DW_TAG_inlined_subroutine3897          Children:        DW_CHILDREN_no3898          Attributes:3899            - Attribute:       DW_AT_name3900              Form:            DW_FORM_strp3901            - Attribute:       DW_AT_low_pc3902              Form:            DW_FORM_addr3903            - Attribute:       DW_AT_high_pc3904              Form:            DW_FORM_addr3905            - Attribute:       DW_AT_call_file3906              Form:            DW_FORM_data43907            - Attribute:       DW_AT_call_line3908              Form:            DW_FORM_data43909  debug_info:3910    - Length:          0x453911      Version:         43912      AbbrevTableID:   03913      AbbrOffset:      0x03914      AddrSize:        83915      Entries:3916        - AbbrCode:        0x13917          Values:3918            - Value:           0x13919            - Value:           0x23920            - Value:           0x03921        - AbbrCode:        0x23922          Values:3923            - Value:           0xF3924            - Value:           0x10003925            - Value:           0x10503926        - AbbrCode:        0x33927          Values:3928            - Value:           0x133929            - Value:           0x10103930            - Value:           0x10103931            - Value:           0x13932            - Value:           0xB3933        - AbbrCode:        0x03934        - AbbrCode:        0x03935  debug_line:3936    - Length:          893937      Version:         23938      PrologueLength:  483939      MinInstLength:   13940      DefaultIsStmt:   13941      LineBase:        2513942      LineRange:       143943      OpcodeBase:      133944      StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]3945      IncludeDirs:3946        - '/tmp'3947      Files:3948        - Name:            main.cpp3949          DirIdx:          13950          ModTime:         03951          Length:          03952        - Name:            inline.h3953          DirIdx:          13954          ModTime:         03955          Length:          03956      Opcodes:3957        - Opcode:          DW_LNS_extended_op3958          ExtLen:          93959          SubOpcode:       DW_LNE_set_address3960          Data:            40963961        - Opcode:          DW_LNS_advance_line3962          SData:           93963          Data:            03964        - Opcode:          DW_LNS_copy3965          Data:            03966        - Opcode:          DW_LNS_advance_pc3967          Data:            163968        - Opcode:          DW_LNS_set_file3969          Data:            23970        - Opcode:          DW_LNS_advance_line3971          SData:           103972          Data:            03973        - Opcode:          DW_LNS_copy3974          Data:            03975        - Opcode:          DW_LNS_advance_pc3976          Data:            163977        - Opcode:          DW_LNS_advance_line3978          SData:           13979          Data:            03980        - Opcode:          DW_LNS_copy3981          Data:            03982        - Opcode:          DW_LNS_advance_pc3983          Data:            483984        - Opcode:          DW_LNS_set_file3985          Data:            13986        - Opcode:          DW_LNS_advance_line3987          SData:           -103988          Data:            03989        - Opcode:          DW_LNS_extended_op3990          ExtLen:          13991          SubOpcode:       DW_LNE_end_sequence3992          Data:            03993  )";3994  auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);3995  ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());3996  std::unique_ptr<DWARFContext> DwarfContext =3997      DWARFContext::create(*ErrOrSections, 8);3998  ASSERT_TRUE(DwarfContext.get() != nullptr);3999  std::string errors;4000  raw_string_ostream OS(errors);4001  OutputAggregator OSAgg(&OS);4002  GsymCreator GC;4003  DwarfTransformer DT(*DwarfContext, GC);4004  const uint32_t ThreadCount = 1;4005  ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());4006  ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());4007  SmallString<512> Str;4008  raw_svector_ostream OutStrm(Str);4009  const auto ByteOrder = llvm::endianness::native;4010  FileWriter FW(OutStrm, ByteOrder);4011  ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());4012  Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());4013  ASSERT_THAT_EXPECTED(GR, Succeeded());4014  // There should be one function in our GSYM.4015  EXPECT_EQ(GR->getNumAddresses(), 1u);4016  // Verify "foo" is present and has a line table and no inline info.4017  auto ExpFI = GR->getFunctionInfo(0x1000);4018  ASSERT_THAT_EXPECTED(ExpFI, Succeeded());4019  ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x1050));4020  EXPECT_TRUE(ExpFI->OptLineTable.has_value());4021  EXPECT_FALSE(ExpFI->Inline.has_value());4022  StringRef FuncName = GR->getString(ExpFI->Name);4023  EXPECT_EQ(FuncName, "foo");4024 4025  // Make sure we don't see spurious errors in the output:4026  EXPECT_TRUE(errors.find("error:") == std::string::npos);4027}4028 4029 4030TEST(GSYMTest, TestEmptyLinkageName) {4031  // This example has a single compile unit that has a DW_TAG_subprogram that4032  // has a function that has an empty linkage name and a valid normal name.4033  // Previously this would cause an encoding error:4034  //4035  // DWARF conversion failed: attempted to encode invalid FunctionInfo object4036  //4037  // This was because we would get a valid but empty linkage name and we would4038  // try to use this in the GSYM FunctionInfo and that would cause the error4039  // as the name was empty.4040  //4041  // 0x0000000b: DW_TAG_compile_unit4042  //               DW_AT_name        ("/tmp/main.cpp")4043  //               DW_AT_language    (DW_LANG_C)4044  //               DW_AT_stmt_list   (0x00000000)4045  //4046  // 0x00000015:   DW_TAG_subprogram4047  //                 DW_AT_name      ("foo")4048  //                 DW_AT_linkage_name      ("")4049  //                 DW_AT_low_pc    (0x0000000000001000)4050  //                 DW_AT_high_pc   (0x0000000000001050)4051  //4052  // 0x0000002e:   NULL4053 4054 4055  StringRef yamldata = R"(4056  debug_str:4057    - ''4058    - '/tmp/main.cpp'4059    - foo4060    - ''4061  debug_abbrev:4062    - ID:              04063      Table:4064        - Code:            0x14065          Tag:             DW_TAG_compile_unit4066          Children:        DW_CHILDREN_yes4067          Attributes:4068            - Attribute:       DW_AT_name4069              Form:            DW_FORM_strp4070            - Attribute:       DW_AT_language4071              Form:            DW_FORM_udata4072            - Attribute:       DW_AT_stmt_list4073              Form:            DW_FORM_sec_offset4074        - Code:            0x24075          Tag:             DW_TAG_subprogram4076          Children:        DW_CHILDREN_no4077          Attributes:4078            - Attribute:       DW_AT_name4079              Form:            DW_FORM_strp4080            - Attribute:       DW_AT_linkage_name4081              Form:            DW_FORM_strp4082            - Attribute:       DW_AT_low_pc4083              Form:            DW_FORM_addr4084            - Attribute:       DW_AT_high_pc4085              Form:            DW_FORM_addr4086  debug_info:4087    - Length:          0x2B4088      Version:         44089      AbbrevTableID:   04090      AbbrOffset:      0x04091      AddrSize:        84092      Entries:4093        - AbbrCode:        0x14094          Values:4095            - Value:           0x14096            - Value:           0x24097            - Value:           0x04098        - AbbrCode:        0x24099          Values:4100            - Value:           0xF4101            - Value:           0x134102            - Value:           0x10004103            - Value:           0x10504104        - AbbrCode:        0x04105  debug_line:4106    - Length:          684107      Version:         24108      PrologueLength:  364109      MinInstLength:   14110      DefaultIsStmt:   14111      LineBase:        2514112      LineRange:       144113      OpcodeBase:      134114      StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]4115      IncludeDirs:4116        - '/tmp'4117      Files:4118        - Name:            main.cpp4119          DirIdx:          14120          ModTime:         04121          Length:          04122      Opcodes:4123        - Opcode:          DW_LNS_extended_op4124          ExtLen:          94125          SubOpcode:       DW_LNE_set_address4126          Data:            40964127        - Opcode:          DW_LNS_advance_line4128          SData:           94129          Data:            04130        - Opcode:          DW_LNS_copy4131          Data:            04132        - Opcode:          DW_LNS_advance_pc4133          Data:            2564134        - Opcode:          DW_LNS_advance_line4135          SData:           14136          Data:            04137        - Opcode:          DW_LNS_copy4138          Data:            04139        - Opcode:          DW_LNS_advance_pc4140          Data:            2564141        - Opcode:          DW_LNS_extended_op4142          ExtLen:          14143          SubOpcode:       DW_LNE_end_sequence4144          Data:            04145  )";4146  auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);4147  ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());4148  std::unique_ptr<DWARFContext> DwarfContext =4149      DWARFContext::create(*ErrOrSections, 8);4150  ASSERT_TRUE(DwarfContext.get() != nullptr);4151  std::string errors;4152  raw_string_ostream OS(errors);4153  OutputAggregator OSAgg(&OS);4154  GsymCreator GC;4155  DwarfTransformer DT(*DwarfContext, GC);4156  const uint32_t ThreadCount = 1;4157  ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());4158  ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());4159  SmallString<512> Str;4160  raw_svector_ostream OutStrm(Str);4161  const auto ByteOrder = llvm::endianness::native;4162  FileWriter FW(OutStrm, ByteOrder);4163  ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());4164  Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());4165  ASSERT_THAT_EXPECTED(GR, Succeeded());4166  // There should be one function in our GSYM.4167  EXPECT_EQ(GR->getNumAddresses(), 1u);4168  // Verify "foo" is present and has a line table and no inline info.4169  auto ExpFI = GR->getFunctionInfo(0x1000);4170  ASSERT_THAT_EXPECTED(ExpFI, Succeeded());4171  ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x1050));4172  EXPECT_TRUE(ExpFI->OptLineTable.has_value());4173  EXPECT_FALSE(ExpFI->Inline.has_value());4174  StringRef FuncName = GR->getString(ExpFI->Name);4175  EXPECT_EQ(FuncName, "foo");4176 4177  // Make sure we don't see spurious errors in the output:4178  EXPECT_TRUE(errors.find("error:") == std::string::npos);4179}4180 4181TEST(GSYMTest, TestLineTablesWithEmptyRanges) {4182  // Test that lookups find the right line table entry when there are multiple4183  // line entries with the same address. When we have multiple line table4184  // entries with the same address, we need to pick the last one in the line4185  // table. We do this because a line entry's start address in the defined by4186  // the line table entry's address and the size is determined by the4187  // subtracting the next line table's address. If the current line table4188  // entry's address is the same as the next one, then there is no code4189  // assiciated with the current line table entry and it should be ignored.4190  //4191  // 0x0000000b: DW_TAG_compile_unit4192  //               DW_AT_name        ("/tmp/main.cpp")4193  //               DW_AT_language    (DW_LANG_C)4194  //               DW_AT_stmt_list   (0x00000000)4195  //4196  // 0x00000015:   DW_TAG_subprogram4197  //                 DW_AT_name      ("foo")4198  //                 DW_AT_low_pc    (0x0000000000001000)4199  //                 DW_AT_high_pc   (0x0000000000001050)4200  //4201  // 0x0000002a:   NULL4202  //4203  // The line table has a duplicate entry at 0x1010:4204  //4205  // Address    Line   Column File   ISA Discriminator Flags4206  // ---------- ------ ------ ------ --- ------------- -------------4207  // 0x00001000     10      0      1   0             0  is_stmt4208  // 0x00001010     11      0      1   0             0  is_stmt4209  // 0x00001010     12      0      1   0             0  is_stmt4210  // 0x00001050     13      0      1   0             0  is_stmt end_sequence4211 4212  StringRef yamldata = R"(4213  debug_str:4214    - ''4215    - '/tmp/main.cpp'4216    - foo4217  debug_abbrev:4218    - ID:              04219      Table:4220        - Code:            0x14221          Tag:             DW_TAG_compile_unit4222          Children:        DW_CHILDREN_yes4223          Attributes:4224            - Attribute:       DW_AT_name4225              Form:            DW_FORM_strp4226            - Attribute:       DW_AT_language4227              Form:            DW_FORM_udata4228            - Attribute:       DW_AT_stmt_list4229              Form:            DW_FORM_sec_offset4230        - Code:            0x24231          Tag:             DW_TAG_subprogram4232          Children:        DW_CHILDREN_no4233          Attributes:4234            - Attribute:       DW_AT_name4235              Form:            DW_FORM_strp4236            - Attribute:       DW_AT_low_pc4237              Form:            DW_FORM_addr4238            - Attribute:       DW_AT_high_pc4239              Form:            DW_FORM_addr4240  debug_info:4241    - Length:          0x274242      Version:         44243      AbbrevTableID:   04244      AbbrOffset:      0x04245      AddrSize:        84246      Entries:4247        - AbbrCode:        0x14248          Values:4249            - Value:           0x14250            - Value:           0x24251            - Value:           0x04252        - AbbrCode:        0x24253          Values:4254            - Value:           0xF4255            - Value:           0x10004256            - Value:           0x10504257        - AbbrCode:        0x04258  debug_line:4259    - Length:          714260      Version:         24261      PrologueLength:  364262      MinInstLength:   14263      DefaultIsStmt:   14264      LineBase:        2514265      LineRange:       144266      OpcodeBase:      134267      StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]4268      IncludeDirs:4269        - '/tmp'4270      Files:4271        - Name:            main.cpp4272          DirIdx:          14273          ModTime:         04274          Length:          04275      Opcodes:4276        - Opcode:          DW_LNS_extended_op4277          ExtLen:          94278          SubOpcode:       DW_LNE_set_address4279          Data:            40964280        - Opcode:          DW_LNS_advance_line4281          SData:           94282          Data:            04283        - Opcode:          DW_LNS_copy4284          Data:            04285        - Opcode:          DW_LNS_advance_pc4286          Data:            164287        - Opcode:          DW_LNS_advance_line4288          SData:           14289          Data:            04290        - Opcode:          DW_LNS_copy4291          Data:            04292        - Opcode:          DW_LNS_advance_line4293          SData:           14294          Data:            04295        - Opcode:          DW_LNS_copy4296          Data:            04297        - Opcode:          DW_LNS_advance_pc4298          Data:            644299        - Opcode:          DW_LNS_advance_line4300          SData:           14301          Data:            04302        - Opcode:          DW_LNS_extended_op4303          ExtLen:          14304          SubOpcode:       DW_LNE_end_sequence4305          Data:            04306  )";4307  auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);4308  ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());4309  std::unique_ptr<DWARFContext> DwarfContext =4310      DWARFContext::create(*ErrOrSections, 8);4311  ASSERT_TRUE(DwarfContext.get() != nullptr);4312  std::string errors;4313  raw_string_ostream OS(errors);4314  OutputAggregator OSAgg(&OS);4315  GsymCreator GC;4316  DwarfTransformer DT(*DwarfContext, GC);4317  const uint32_t ThreadCount = 1;4318  ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());4319  ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());4320  SmallString<512> Str;4321  raw_svector_ostream OutStrm(Str);4322  const auto ByteOrder = llvm::endianness::native;4323  FileWriter FW(OutStrm, ByteOrder);4324  ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());4325  Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());4326  ASSERT_THAT_EXPECTED(GR, Succeeded());4327  // There should be one function in our GSYM.4328  EXPECT_EQ(GR->getNumAddresses(), 1u);4329  // Verify "foo" is present and has a line table and no inline info.4330  auto ExpFI = GR->getFunctionInfo(0x1000);4331  ASSERT_THAT_EXPECTED(ExpFI, Succeeded());4332  ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x1050));4333  EXPECT_TRUE(ExpFI->OptLineTable.has_value());4334  EXPECT_FALSE(ExpFI->Inline.has_value());4335  StringRef FuncName = GR->getString(ExpFI->Name);4336  EXPECT_EQ(FuncName, "foo");4337 4338  // Make sure we don't see spurious errors in the output:4339  EXPECT_TRUE(errors.find("error:") == std::string::npos);4340 4341  // Make sure that when we lookup address 0x1010, that we get the entry that4342  // matches line 12, the second line entry that also has the address of4343  // 0x1010.4344  auto LR = GR->lookup(0x1010);4345  ASSERT_THAT_EXPECTED(LR, Succeeded());4346  SourceLocation src_loc = {"foo", "/tmp", "main.cpp", 12, 16};4347  EXPECT_THAT(LR->Locations, testing::ElementsAre(src_loc));4348}4349 4350TEST(GSYMTest, TestHandlingOfInvalidFileIndexes) {4351  // Test that llvm-gsymutil can handle invalid file indexes in the following4352  // cases:4353  //  - In line entries in the line table4354  //  - When parsing inline entries that have a DW_AT_call_file4355  //  - When parsing function dies with no line table entries and it tries to4356  //    use the DW_AT_decl_file4357  //4358  //4359  // 0x0000000b: DW_TAG_compile_unit4360  //               DW_AT_name        ("/tmp/main.cpp")4361  //               DW_AT_language    (DW_LANG_C)4362  //               DW_AT_stmt_list   (0x00000000)4363  //4364  // 0x00000015:   DW_TAG_subprogram4365  //                 DW_AT_name      ("foo")4366  //                 DW_AT_low_pc    (0x0000000000001000)4367  //                 DW_AT_high_pc   (0x0000000000001050)4368  //4369  // 0x0000002a:     DW_TAG_inlined_subroutine4370  //                   DW_AT_name    ("inline_with_invalid_call_file")4371  //                   DW_AT_low_pc  (0x0000000000001010)4372  //                   DW_AT_high_pc (0x0000000000001020)4373  //                   DW_AT_call_file       (0x0000000a)4374  //                   DW_AT_call_line       (11)4375  //4376  // 0x00000047:       DW_TAG_inlined_subroutine4377  //                     DW_AT_name4378  //                     ("inline_inside_parent_with_invalid_call_file")4379  //                     DW_AT_low_pc        (0x0000000000001010)4380  //                     DW_AT_high_pc       (0x0000000000001015)4381  //                     DW_AT_call_file     ("/tmp/main.cpp")4382  //                     DW_AT_call_line     (12)4383  //4384  // 0x00000064:       NULL4385  //4386  // 0x00000065:     DW_TAG_inlined_subroutine4387  //                   DW_AT_name    ("inline_with_valid_call_file")4388  //                   DW_AT_low_pc  (0x0000000000001020)4389  //                   DW_AT_high_pc (0x0000000000001030)4390  //                   DW_AT_call_file       ("/tmp/main.cpp")4391  //                   DW_AT_call_line       (13)4392  //4393  // 0x00000082:       DW_TAG_inlined_subroutine4394  //                     DW_AT_name4395  //                     ("inline_inside_parent_with_valid_call_file")4396  //                     DW_AT_low_pc        (0x0000000000001020)4397  //                     DW_AT_high_pc       (0x0000000000001025)4398  //                     DW_AT_call_file     ("/tmp/main.cpp")4399  //                     DW_AT_call_line     (14)4400  //4401  // 0x0000009f:       NULL4402  //4403  // 0x000000a0:     NULL4404  //4405  // 0x000000a1:   DW_TAG_subprogram4406  //                 DW_AT_name      ("func_with_valid_decl_file")4407  //                 DW_AT_decl_file ("/tmp/main.cpp")4408  //                 DW_AT_decl_line (20)4409  //                 DW_AT_low_pc    (0x0000000000002000)4410  //                 DW_AT_high_pc   (0x0000000000002050)4411  //4412  // 0x000000b8:   DW_TAG_subprogram4413  //                 DW_AT_name      ("func_with_invalid_decl_file")4414  //                 DW_AT_decl_file (0x0a)4415  //                 DW_AT_decl_line (20)4416  //                 DW_AT_low_pc    (0x0000000000003000)4417  //                 DW_AT_high_pc   (0x0000000000003050)4418  //4419  // 0x000000cf:   NULL4420  //4421  // The table looks has an entry at address 0x0000000000001010 that has an4422  // invalid file index that needs to be removed.4423  //4424  // Address            Line   Column File   ISA Discriminator Flags4425  // ---------- ------ ------ ------ --- ------------- -------------4426  // 0x00001000     10      0      1   0             0  is_stmt4427  // 0x00001010     11      0     10   0             0  is_stmt4428  // 0x00001020     11      0      1   0             0  is_stmt4429  // 0x00001030     12      0      1   0             0  is_stmt4430  // 0x00001050     12      0      1   0             0  is_stmt end_sequence4431 4432  StringRef yamldata = R"(4433  debug_str:4434    - ''4435    - '/tmp/main.cpp'4436    - foo4437    - inline_with_invalid_call_file4438    - inline_inside_parent_with_invalid_call_file4439    - inline_with_valid_call_file4440    - inline_inside_parent_with_valid_call_file4441    - func_with_valid_decl_file4442    - func_with_invalid_decl_file4443  debug_abbrev:4444    - ID:              04445      Table:4446        - Code:            0x14447          Tag:             DW_TAG_compile_unit4448          Children:        DW_CHILDREN_yes4449          Attributes:4450            - Attribute:       DW_AT_name4451              Form:            DW_FORM_strp4452            - Attribute:       DW_AT_language4453              Form:            DW_FORM_udata4454            - Attribute:       DW_AT_stmt_list4455              Form:            DW_FORM_sec_offset4456        - Code:            0x24457          Tag:             DW_TAG_subprogram4458          Children:        DW_CHILDREN_yes4459          Attributes:4460            - Attribute:       DW_AT_name4461              Form:            DW_FORM_strp4462            - Attribute:       DW_AT_low_pc4463              Form:            DW_FORM_addr4464            - Attribute:       DW_AT_high_pc4465              Form:            DW_FORM_addr4466        - Code:            0x34467          Tag:             DW_TAG_inlined_subroutine4468          Children:        DW_CHILDREN_yes4469          Attributes:4470            - Attribute:       DW_AT_name4471              Form:            DW_FORM_strp4472            - Attribute:       DW_AT_low_pc4473              Form:            DW_FORM_addr4474            - Attribute:       DW_AT_high_pc4475              Form:            DW_FORM_addr4476            - Attribute:       DW_AT_call_file4477              Form:            DW_FORM_data44478            - Attribute:       DW_AT_call_line4479              Form:            DW_FORM_data44480        - Code:            0x44481          Tag:             DW_TAG_inlined_subroutine4482          Children:        DW_CHILDREN_no4483          Attributes:4484            - Attribute:       DW_AT_name4485              Form:            DW_FORM_strp4486            - Attribute:       DW_AT_low_pc4487              Form:            DW_FORM_addr4488            - Attribute:       DW_AT_high_pc4489              Form:            DW_FORM_addr4490            - Attribute:       DW_AT_call_file4491              Form:            DW_FORM_data44492            - Attribute:       DW_AT_call_line4493              Form:            DW_FORM_data44494        - Code:            0x54495          Tag:             DW_TAG_subprogram4496          Children:        DW_CHILDREN_no4497          Attributes:4498            - Attribute:       DW_AT_name4499              Form:            DW_FORM_strp4500            - Attribute:       DW_AT_decl_file4501              Form:            DW_FORM_data14502            - Attribute:       DW_AT_decl_line4503              Form:            DW_FORM_data14504            - Attribute:       DW_AT_low_pc4505              Form:            DW_FORM_addr4506            - Attribute:       DW_AT_high_pc4507              Form:            DW_FORM_addr4508  debug_info:4509    - Length:          0xCC4510      Version:         44511      AbbrevTableID:   04512      AbbrOffset:      0x04513      AddrSize:        84514      Entries:4515        - AbbrCode:        0x14516          Values:4517            - Value:           0x14518            - Value:           0x24519            - Value:           0x04520        - AbbrCode:        0x24521          Values:4522            - Value:           0xF4523            - Value:           0x10004524            - Value:           0x10504525        - AbbrCode:        0x34526          Values:4527            - Value:           0x134528            - Value:           0x10104529            - Value:           0x10204530            - Value:           0xA4531            - Value:           0xB4532        - AbbrCode:        0x44533          Values:4534            - Value:           0x314535            - Value:           0x10104536            - Value:           0x10154537            - Value:           0x14538            - Value:           0xC4539        - AbbrCode:        0x04540        - AbbrCode:        0x34541          Values:4542            - Value:           0x5D4543            - Value:           0x10204544            - Value:           0x10304545            - Value:           0x14546            - Value:           0xD4547        - AbbrCode:        0x44548          Values:4549            - Value:           0x794550            - Value:           0x10204551            - Value:           0x10254552            - Value:           0x14553            - Value:           0xE4554        - AbbrCode:        0x04555        - AbbrCode:        0x04556        - AbbrCode:        0x54557          Values:4558            - Value:           0xA34559            - Value:           0x14560            - Value:           0x144561            - Value:           0x20004562            - Value:           0x20504563        - AbbrCode:        0x54564          Values:4565            - Value:           0xBD4566            - Value:           0xA4567            - Value:           0x144568            - Value:           0x30004569            - Value:           0x30504570        - AbbrCode:        0x04571  debug_line:4572    - Length:          784573      Version:         24574      PrologueLength:  364575      MinInstLength:   14576      DefaultIsStmt:   14577      LineBase:        2514578      LineRange:       144579      OpcodeBase:      134580      StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]4581      IncludeDirs:4582        - '/tmp'4583      Files:4584        - Name:            main.cpp4585          DirIdx:          14586          ModTime:         04587          Length:          04588      Opcodes:4589        - Opcode:          DW_LNS_extended_op4590          ExtLen:          94591          SubOpcode:       DW_LNE_set_address4592          Data:            40964593        - Opcode:          DW_LNS_advance_line4594          SData:           94595          Data:            04596        - Opcode:          DW_LNS_copy4597          Data:            04598        - Opcode:          DW_LNS_advance_pc4599          Data:            164600        - Opcode:          DW_LNS_set_file4601          Data:            104602        - Opcode:          DW_LNS_advance_line4603          SData:           14604          Data:            04605        - Opcode:          DW_LNS_copy4606          Data:            04607        - Opcode:          DW_LNS_advance_pc4608          Data:            164609        - Opcode:          DW_LNS_set_file4610          Data:            14611        - Opcode:          DW_LNS_copy4612          Data:            04613        - Opcode:          DW_LNS_advance_pc4614          Data:            164615        - Opcode:          DW_LNS_advance_line4616          SData:           14617          Data:            04618        - Opcode:          DW_LNS_copy4619          Data:            04620        - Opcode:          DW_LNS_advance_pc4621          Data:            324622        - Opcode:          DW_LNS_extended_op4623          ExtLen:          14624          SubOpcode:       DW_LNE_end_sequence4625          Data:            04626  )";4627  auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);4628  ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());4629  std::unique_ptr<DWARFContext> DwarfContext =4630      DWARFContext::create(*ErrOrSections, 8);4631  ASSERT_TRUE(DwarfContext.get() != nullptr);4632  std::string errors;4633  raw_string_ostream OS(errors);4634  OutputAggregator OSAgg(&OS);4635  GsymCreator GC;4636  DwarfTransformer DT(*DwarfContext, GC);4637  const uint32_t ThreadCount = 1;4638  ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());4639  ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());4640  SmallString<512> Str;4641  raw_svector_ostream OutStrm(Str);4642  const auto ByteOrder = llvm::endianness::native;4643  FileWriter FW(OutStrm, ByteOrder);4644  ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());4645  Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());4646  ASSERT_THAT_EXPECTED(GR, Succeeded());4647  // There should be one function in our GSYM.4648  EXPECT_EQ(GR->getNumAddresses(), 3u);4649  // Verify "foo" is present and has a line table and no inline info.4650  auto ExpFI = GR->getFunctionInfo(0x1000);4651  ASSERT_THAT_EXPECTED(ExpFI, Succeeded());4652  ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x1050));4653  StringRef FuncName = GR->getString(ExpFI->Name);4654  EXPECT_EQ(FuncName, "foo");4655 4656  EXPECT_TRUE(ExpFI->OptLineTable.has_value());4657  // Make sure we only have 3 entries to show we removed the line entry with4658  // the invalid file index whose address is 0x0000000000001010.4659  ASSERT_EQ(ExpFI->OptLineTable->size(), 3u);4660  EXPECT_TRUE(ExpFI->Inline.has_value());4661 4662  // Make sure that we only have one inline function, not two. We remove one of4663  // the inline functions because it has an invalid DW_AT_call_file attribute.4664  ASSERT_EQ(ExpFI->Inline->Children.size(), 1u);4665  StringRef InlineName = GR->getString(ExpFI->Inline->Children[0].Name);4666  EXPECT_EQ(InlineName, "inline_with_valid_call_file");4667 4668  ExpFI = GR->getFunctionInfo(0x0000000000002000);4669  ASSERT_THAT_EXPECTED(ExpFI, Succeeded());4670  ASSERT_EQ(ExpFI->Range, AddressRange(0x2000, 0x2050));4671  FuncName = GR->getString(ExpFI->Name);4672  EXPECT_EQ(FuncName, "func_with_valid_decl_file");4673  EXPECT_FALSE(ExpFI->Inline.has_value());4674  // Make sure we only have 1 entry in the line table which indicates we were4675  // able to parse the DW_AT_decl_file/DW_AT_decl_line correctly.4676  EXPECT_TRUE(ExpFI->OptLineTable.has_value());4677  ASSERT_EQ(ExpFI->OptLineTable->size(), 1u);4678 4679  ExpFI = GR->getFunctionInfo(0x0000000000003000);4680  ASSERT_THAT_EXPECTED(ExpFI, Succeeded());4681  ASSERT_EQ(ExpFI->Range, AddressRange(0x3000, 0x3050));4682  FuncName = GR->getString(ExpFI->Name);4683  EXPECT_EQ(FuncName, "func_with_invalid_decl_file");4684  EXPECT_FALSE(ExpFI->Inline.has_value());4685  // Make sure we only no line table because there are no line entries in the4686  // line table and the DW_AT_decl_file attribute was invalid so we were not4687  // able to parse the DW_AT_decl_file/DW_AT_decl_line correctly.4688  EXPECT_FALSE(ExpFI->OptLineTable.has_value());4689 4690  // Make sure we don't see spurious errors in the output:4691  std::vector<std::string> ExpectedLogErrors = {4692      "error: function DIE at 0x00000015 has a line entry with invalid DWARF "4693      "file index, this entry will be removed:",4694      "error: inlined function DIE at 0x0000002a has an invalid file index 10 "4695      "in its DW_AT_call_file attribute, this inline entry and all children "4696      "will be removed.",4697      "error: function DIE at 0x000000b8 has an invalid file index 10 in its "4698      "DW_AT_decl_file attribute, unable to create a single line entry from "4699      "the DW_AT_decl_file/DW_AT_decl_line attributes."};4700  // Make sure all expected errors are in the error stream for the two invalid4701  // inlined functions that we removed due to invalid range scoping.4702  for (const auto &Error : ExpectedLogErrors)4703    EXPECT_TRUE(errors.find(Error) != std::string::npos);4704}4705 4706TEST(GSYMTest, TestLookupsOfOverlappingAndUnequalRanges) {4707  // Test that llvm-gsymutil lookup the correct funtion info when address4708  // ranges overlap. When functions overlap we always want to pick the first4709  // function info when symbolicating if there are multiple entries with the4710  // same address. Previous to this fix we would just binary search the address4711  // table and pick the first function info that matched the address. After4712  // this fix we now always select the first matching entry whose address range4713  // contains the lookup address to ensure we have the most debug info. We have4714  // seen case where the debug info would contain a small range and a symbol4715  // would have the same start address but the range was larger and sometimes,4716  // depending on how the binary search of the address table happened, we would4717  // pick these latter entries. We want the first entries because they always4718  // have the most debug info.4719  //4720  // To repro this case, we just make some simple DWARF that has two4721  // overlapping ranges and ensure that any lookups between 0x1000 and 0x104f4722  // match "foo", and any ranges between 0x1050 and 0x1fff match "bar".4723  //4724  // 0x0000000b: DW_TAG_compile_unit4725  //               DW_AT_name	("/tmp/main.cpp")4726  //               DW_AT_language	(DW_LANG_C)4727  //               DW_AT_stmt_list	(0x00000000)4728  //4729  // 0x00000015:   DW_TAG_subprogram4730  //                 DW_AT_name	("foo")4731  //                 DW_AT_low_pc	(0x0000000000001000)4732  //                 DW_AT_high_pc	(0x0000000000001050)4733  //4734  // 0x0000002a:   DW_TAG_subprogram4735  //                 DW_AT_name	("bar")4736  //                 DW_AT_low_pc	(0x0000000000001000)4737  //                 DW_AT_high_pc	(0x0000000000001100)4738  //4739  // 0x0000003f:   NULL4740 4741  StringRef yamldata = R"(4742  debug_str:4743    - ''4744    - '/tmp/main.cpp'4745    - foo4746    - bar4747  debug_abbrev:4748    - ID:              04749      Table:4750        - Code:            0x14751          Tag:             DW_TAG_compile_unit4752          Children:        DW_CHILDREN_yes4753          Attributes:4754            - Attribute:       DW_AT_name4755              Form:            DW_FORM_strp4756            - Attribute:       DW_AT_language4757              Form:            DW_FORM_udata4758            - Attribute:       DW_AT_stmt_list4759              Form:            DW_FORM_sec_offset4760        - Code:            0x24761          Tag:             DW_TAG_subprogram4762          Children:        DW_CHILDREN_no4763          Attributes:4764            - Attribute:       DW_AT_name4765              Form:            DW_FORM_strp4766            - Attribute:       DW_AT_low_pc4767              Form:            DW_FORM_addr4768            - Attribute:       DW_AT_high_pc4769              Form:            DW_FORM_addr4770  debug_info:4771    - Length:          0x3C4772      Version:         44773      AbbrevTableID:   04774      AbbrOffset:      0x04775      AddrSize:        84776      Entries:4777        - AbbrCode:        0x14778          Values:4779            - Value:           0x14780            - Value:           0x24781            - Value:           0x04782        - AbbrCode:        0x24783          Values:4784            - Value:           0xF4785            - Value:           0x10004786            - Value:           0x10504787        - AbbrCode:        0x24788          Values:4789            - Value:           0x134790            - Value:           0x10004791            - Value:           0x11004792        - AbbrCode:        0x04793  debug_line:4794    - Length:          714795      Version:         24796      PrologueLength:  364797      MinInstLength:   14798      DefaultIsStmt:   14799      LineBase:        2514800      LineRange:       144801      OpcodeBase:      134802      StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]4803      IncludeDirs:4804        - '/tmp'4805      Files:4806        - Name:            main.cpp4807          DirIdx:          14808          ModTime:         04809          Length:          04810      Opcodes:4811        - Opcode:          DW_LNS_extended_op4812          ExtLen:          94813          SubOpcode:       DW_LNE_set_address4814          Data:            40964815        - Opcode:          DW_LNS_advance_line4816          SData:           94817          Data:            04818        - Opcode:          DW_LNS_copy4819          Data:            04820        - Opcode:          DW_LNS_advance_pc4821          Data:            164822        - Opcode:          DW_LNS_advance_line4823          SData:           14824          Data:            04825        - Opcode:          DW_LNS_copy4826          Data:            04827        - Opcode:          DW_LNS_advance_line4828          SData:           14829          Data:            04830        - Opcode:          DW_LNS_copy4831          Data:            04832        - Opcode:          DW_LNS_advance_pc4833          Data:            644834        - Opcode:          DW_LNS_advance_line4835          SData:           14836          Data:            04837        - Opcode:          DW_LNS_extended_op4838          ExtLen:          14839          SubOpcode:       DW_LNE_end_sequence4840          Data:            04841  )";4842  auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);4843  ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());4844  std::unique_ptr<DWARFContext> DwarfContext =4845      DWARFContext::create(*ErrOrSections, 8);4846  ASSERT_TRUE(DwarfContext.get() != nullptr);4847  std::string errors;4848  raw_string_ostream OS(errors);4849  OutputAggregator OSAgg(&OS);4850  GsymCreator GC;4851  DwarfTransformer DT(*DwarfContext, GC);4852  const uint32_t ThreadCount = 1;4853  ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());4854  ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());4855  SmallString<512> Str;4856  raw_svector_ostream OutStrm(Str);4857  const auto ByteOrder = llvm::endianness::native;4858  FileWriter FW(OutStrm, ByteOrder);4859  ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());4860  Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());4861  ASSERT_THAT_EXPECTED(GR, Succeeded());4862  // There should be two functions in our GSYM.4863  EXPECT_EQ(GR->getNumAddresses(), 2u);4864  // Verify "foo" is correctly looked up for each of its addresses.4865  for (uint64_t Addr = 0x1000; Addr < 0x1050; ++Addr) {4866    auto ExpFI = GR->getFunctionInfo(Addr);4867    ASSERT_THAT_EXPECTED(ExpFI, Succeeded());4868    ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x1050));4869    StringRef FuncName = GR->getString(ExpFI->Name);4870    EXPECT_EQ(FuncName, "foo");4871  }4872 4873  // Verify "bar" is correctly looked up for each of its addresses.4874  for (uint64_t Addr = 0x1050; Addr < 0x1100; ++Addr) {4875    auto ExpFI = GR->getFunctionInfo(Addr);4876    ASSERT_THAT_EXPECTED(ExpFI, Succeeded());4877    ASSERT_EQ(ExpFI->Range, AddressRange(0x1000, 0x1100));4878    StringRef FuncName = GR->getString(ExpFI->Name);4879    EXPECT_EQ(FuncName, "bar");4880  }4881 4882  // Prior to the fix for this issue when we dumped an entire GSYM file, we4883  // were using a function that would extract a FunctionInfo object for a4884  // given address which caused us to always dump the first FunctionInfo4885  // entry for a given address. We now dump it correctly using an address4886  // index. Below we verify that we dump the right FunctionInfo gets dumped.4887 4888  SmallString<512> DumpStr;4889  raw_svector_ostream DumpStrm(DumpStr);4890  GR->dump(DumpStrm);4891 4892  // Make sure we see both "foo" and "bar" in the output of an entire GSYM4893  // dump. Prior to this fix we would two "foo" entries.4894  std::vector<std::string> ExpectedDumpLines = {4895      "@ 0x00000068: [0x0000000000001000 - 0x0000000000001050) \"foo\"",4896      "@ 0x00000088: [0x0000000000001000 - 0x0000000000001100) \"bar\""};4897  // Make sure all expected errors are in the error stream for the two invalid4898  // inlined functions that we removed due to invalid range scoping.4899  for (const auto &Line : ExpectedDumpLines)4900    EXPECT_TRUE(DumpStr.find(Line) != std::string::npos);4901}4902 4903TEST(GSYMTest, TestUnableToLocateDWO) {4904  // Test that llvm-gsymutil will not produce "uanble to locate DWO file" for4905  // Apple binaries. Apple uses DW_AT_GNU_dwo_id for non split DWARF purposes4906  // and this makes llvm-gsymutil create warnings and errors.4907  //4908  // 0x0000000b: DW_TAG_compile_unit4909  //               DW_AT_name        ("main.cpp")4910  //               DW_AT_language    (DW_LANG_C)4911  //               DW_AT_GNU_dwo_id  (0xfffffffe)4912  StringRef yamldata = R"(4913  debug_str:4914    - ''4915    - main.cpp4916  debug_abbrev:4917    - ID:              04918      Table:4919        - Code:            0x14920          Tag:             DW_TAG_compile_unit4921          Children:        DW_CHILDREN_no4922          Attributes:4923            - Attribute:       DW_AT_name4924              Form:            DW_FORM_strp4925            - Attribute:       DW_AT_language4926              Form:            DW_FORM_udata4927            - Attribute:       DW_AT_GNU_dwo_id4928              Form:            DW_FORM_data44929  debug_info:4930    - Length:          0x114931      Version:         44932      AbbrevTableID:   04933      AbbrOffset:      0x04934      AddrSize:        84935      Entries:4936        - AbbrCode:        0x14937          Values:4938            - Value:           0x14939            - Value:           0x24940            - Value:           0xFFFFFFFE4941  )";4942  auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);4943  ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());4944  std::unique_ptr<DWARFContext> DwarfContext =4945      DWARFContext::create(*ErrOrSections, 8);4946  ASSERT_TRUE(DwarfContext.get() != nullptr);4947  std::string errors;4948  raw_string_ostream OS(errors);4949  OutputAggregator OSAgg(&OS);4950  GsymCreator GC;4951  // Make a DWARF transformer that is MachO (Apple) to avoid warnings about4952  // not finding DWO files.4953  DwarfTransformer DT(*DwarfContext, GC, /*LDCS=*/false, /*MachO*/ true);4954  const uint32_t ThreadCount = 1;4955  ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());4956  ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());4957 4958  // Make sure this warning is not in the binary4959  std::string warn("warning: Unable to retrieve DWO .debug_info section for");4960  EXPECT_TRUE(errors.find(warn) == std::string::npos);4961}4962 4963TEST(GSYMTest, TestDWARFTransformNoErrorForMissingFileDecl) {4964  // Test that if llvm-gsymutil finds a line table for a compile unit and if4965  // there are no matching entries for a function in that compile unit, that4966  // it doesn't print out a error saying that a DIE has an invalid file index4967  // if there is no DW_AT_decl_file attribute.4968  //4969  // 0x0000000b: DW_TAG_compile_unit4970  //               DW_AT_name        ("main.cpp")4971  //               DW_AT_language    (DW_LANG_C)4972  //               DW_AT_stmt_list   (0x00000000)4973  //4974  // 0x00000015:   DW_TAG_subprogram4975  //                 DW_AT_name      ("foo")4976  //                 DW_AT_low_pc    (0x0000000000001000)4977  //                 DW_AT_high_pc   (0x0000000000001050)4978  //4979  // 0x0000002a:   NULL4980  //4981  // Line table that has entries, but none that match "foo":4982  //4983  // Address            Line   Column File   ISA Discriminator OpIndex Flags4984  // ------------------ ------ ------ ------ --- ------------- ------- -----4985  // 0x0000000000002000     10      0      1   0             0       0 is_stmt4986  // 0x0000000000002050     13      0      1   0             0       0 is_stmt4987 4988  StringRef yamldata = R"(4989  debug_str:4990    - ''4991    - main.cpp4992  debug_abbrev:4993    - ID:              04994      Table:4995        - Code:            0x14996          Tag:             DW_TAG_compile_unit4997          Children:        DW_CHILDREN_yes4998          Attributes:4999            - Attribute:       DW_AT_name5000              Form:            DW_FORM_strp5001            - Attribute:       DW_AT_language5002              Form:            DW_FORM_udata5003            - Attribute:       DW_AT_stmt_list5004              Form:            DW_FORM_sec_offset5005        - Code:            0x25006          Tag:             DW_TAG_subprogram5007          Children:        DW_CHILDREN_no5008          Attributes:5009            - Attribute:       DW_AT_name5010              Form:            DW_FORM_string5011            - Attribute:       DW_AT_low_pc5012              Form:            DW_FORM_addr5013            - Attribute:       DW_AT_high_pc5014              Form:            DW_FORM_addr5015  debug_info:5016    - Length:          0x275017      Version:         45018      AbbrevTableID:   05019      AbbrOffset:      0x05020      AddrSize:        85021      Entries:5022        - AbbrCode:        0x15023          Values:5024            - Value:           0x15025            - Value:           0x25026            - Value:           0x05027        - AbbrCode:        0x25028          Values:5029            - Value:           0xDEADBEEFDEADBEEF5030              CStr:            foo5031            - Value:           0x10005032            - Value:           0x10505033        - AbbrCode:        0x05034  debug_line:5035    - Length:          585036      Version:         25037      PrologueLength:  315038      MinInstLength:   15039      DefaultIsStmt:   15040      LineBase:        2515041      LineRange:       145042      OpcodeBase:      135043      StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]5044      Files:5045        - Name:            main.cpp5046          DirIdx:          05047          ModTime:         05048          Length:          05049      Opcodes:5050        - Opcode:          DW_LNS_extended_op5051          ExtLen:          95052          SubOpcode:       DW_LNE_set_address5053          Data:            81925054        - Opcode:          DW_LNS_advance_line5055          SData:           95056          Data:            05057        - Opcode:          DW_LNS_copy5058          Data:            05059        - Opcode:          DW_LNS_advance_pc5060          Data:            805061        - Opcode:          DW_LNS_advance_line5062          SData:           35063          Data:            05064        - Opcode:          DW_LNS_extended_op5065          ExtLen:          15066          SubOpcode:       DW_LNE_end_sequence5067          Data:            05068  )";5069  auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);5070  ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());5071  std::unique_ptr<DWARFContext> DwarfContext =5072      DWARFContext::create(*ErrOrSections, 8);5073  ASSERT_TRUE(DwarfContext.get() != nullptr);5074  std::string errors;5075  raw_string_ostream OS(errors);5076  OutputAggregator OSAgg(&OS);5077  GsymCreator GC;5078  DwarfTransformer DT(*DwarfContext, GC);5079  const uint32_t ThreadCount = 1;5080  ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());5081  ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());5082 5083  // Make sure this warning is not in the binary5084  std::string error_str("error: function DIE at 0x00000015 has an invalid file "5085                        "index 4294967295 in its DW_AT_decl_file attribute");5086  EXPECT_TRUE(errors.find(error_str) == std::string::npos);5087}5088