14b6c9de8SGreg Clayton //===- FunctionInfo.cpp ---------------------------------------------------===// 2044776bfSGreg Clayton // 3b52650d5SGreg Clayton // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4b52650d5SGreg Clayton // See https://llvm.org/LICENSE.txt for license information. 5b52650d5SGreg Clayton // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6044776bfSGreg Clayton // 7044776bfSGreg Clayton //===----------------------------------------------------------------------===// 8044776bfSGreg Clayton 9044776bfSGreg Clayton #include "llvm/DebugInfo/GSYM/FunctionInfo.h" 10b52650d5SGreg Clayton #include "llvm/DebugInfo/GSYM/FileWriter.h" 11aeda128aSGreg Clayton #include "llvm/DebugInfo/GSYM/GsymReader.h" 12b52650d5SGreg Clayton #include "llvm/DebugInfo/GSYM/LineTable.h" 13b52650d5SGreg Clayton #include "llvm/DebugInfo/GSYM/InlineInfo.h" 14b52650d5SGreg Clayton #include "llvm/Support/DataExtractor.h" 15367515d4SKazu Hirata #include <optional> 16044776bfSGreg Clayton 17044776bfSGreg Clayton using namespace llvm; 18044776bfSGreg Clayton using namespace gsym; 19044776bfSGreg Clayton 20b52650d5SGreg Clayton /// FunctionInfo information type that is used to encode the optional data 21b52650d5SGreg Clayton /// that is associated with a FunctionInfo object. 22b52650d5SGreg Clayton enum InfoType : uint32_t { 23b52650d5SGreg Clayton EndOfList = 0u, 24b52650d5SGreg Clayton LineTableInfo = 1u, 25cb5dc1faSalx32 InlineInfo = 2u, 26cb5dc1faSalx32 MergedFunctionsInfo = 3u, 275147e594Salx32 CallSiteInfo = 4u, 28b52650d5SGreg Clayton }; 29b52650d5SGreg Clayton 30044776bfSGreg Clayton raw_ostream &llvm::gsym::operator<<(raw_ostream &OS, const FunctionInfo &FI) { 3119602b71SGreg Clayton OS << FI.Range << ": " << "Name=" << HEX32(FI.Name) << '\n'; 3219602b71SGreg Clayton if (FI.OptLineTable) 3319602b71SGreg Clayton OS << FI.OptLineTable << '\n'; 3419602b71SGreg Clayton if (FI.Inline) 3519602b71SGreg Clayton OS << FI.Inline << '\n'; 365147e594Salx32 if (FI.CallSites) 375147e594Salx32 OS << *FI.CallSites << '\n'; 38044776bfSGreg Clayton return OS; 39044776bfSGreg Clayton } 40b52650d5SGreg Clayton 41b52650d5SGreg Clayton llvm::Expected<FunctionInfo> FunctionInfo::decode(DataExtractor &Data, 42b52650d5SGreg Clayton uint64_t BaseAddr) { 43b52650d5SGreg Clayton FunctionInfo FI; 44b52650d5SGreg Clayton uint64_t Offset = 0; 45b52650d5SGreg Clayton if (!Data.isValidOffsetForDataOfSize(Offset, 4)) 46b52650d5SGreg Clayton return createStringError(std::errc::io_error, 47b52650d5SGreg Clayton "0x%8.8" PRIx64 ": missing FunctionInfo Size", Offset); 48854c3394SAlexey Lapshin FI.Range = {BaseAddr, BaseAddr + Data.getU32(&Offset)}; 49b52650d5SGreg Clayton if (!Data.isValidOffsetForDataOfSize(Offset, 4)) 50b52650d5SGreg Clayton return createStringError(std::errc::io_error, 51b52650d5SGreg Clayton "0x%8.8" PRIx64 ": missing FunctionInfo Name", Offset); 52b52650d5SGreg Clayton FI.Name = Data.getU32(&Offset); 53b52650d5SGreg Clayton if (FI.Name == 0) 54b52650d5SGreg Clayton return createStringError(std::errc::io_error, 55b52650d5SGreg Clayton "0x%8.8" PRIx64 ": invalid FunctionInfo Name value 0x%8.8x", 56b52650d5SGreg Clayton Offset - 4, FI.Name); 57b52650d5SGreg Clayton bool Done = false; 58b52650d5SGreg Clayton while (!Done) { 59b52650d5SGreg Clayton if (!Data.isValidOffsetForDataOfSize(Offset, 4)) 60b52650d5SGreg Clayton return createStringError(std::errc::io_error, 61b52650d5SGreg Clayton "0x%8.8" PRIx64 ": missing FunctionInfo InfoType value", Offset); 62b52650d5SGreg Clayton const uint32_t IT = Data.getU32(&Offset); 63b52650d5SGreg Clayton if (!Data.isValidOffsetForDataOfSize(Offset, 4)) 64b52650d5SGreg Clayton return createStringError(std::errc::io_error, 65b52650d5SGreg Clayton "0x%8.8" PRIx64 ": missing FunctionInfo InfoType length", Offset); 66b52650d5SGreg Clayton const uint32_t InfoLength = Data.getU32(&Offset); 67b52650d5SGreg Clayton if (!Data.isValidOffsetForDataOfSize(Offset, InfoLength)) 68b52650d5SGreg Clayton return createStringError(std::errc::io_error, 69b52650d5SGreg Clayton "0x%8.8" PRIx64 ": missing FunctionInfo data for InfoType %u", 70b52650d5SGreg Clayton Offset, IT); 71b52650d5SGreg Clayton DataExtractor InfoData(Data.getData().substr(Offset, InfoLength), 72b52650d5SGreg Clayton Data.isLittleEndian(), 73b52650d5SGreg Clayton Data.getAddressSize()); 74b52650d5SGreg Clayton switch (IT) { 75b52650d5SGreg Clayton case InfoType::EndOfList: 76b52650d5SGreg Clayton Done = true; 77b52650d5SGreg Clayton break; 78b52650d5SGreg Clayton 79b52650d5SGreg Clayton case InfoType::LineTableInfo: 80b52650d5SGreg Clayton if (Expected<LineTable> LT = LineTable::decode(InfoData, BaseAddr)) 81b52650d5SGreg Clayton FI.OptLineTable = std::move(LT.get()); 82b52650d5SGreg Clayton else 83b52650d5SGreg Clayton return LT.takeError(); 84b52650d5SGreg Clayton break; 85b52650d5SGreg Clayton 86b52650d5SGreg Clayton case InfoType::InlineInfo: 87b52650d5SGreg Clayton if (Expected<InlineInfo> II = InlineInfo::decode(InfoData, BaseAddr)) 88b52650d5SGreg Clayton FI.Inline = std::move(II.get()); 89b52650d5SGreg Clayton else 90b52650d5SGreg Clayton return II.takeError(); 91b52650d5SGreg Clayton break; 92b52650d5SGreg Clayton 93cb5dc1faSalx32 case InfoType::MergedFunctionsInfo: 94cb5dc1faSalx32 if (Expected<MergedFunctionsInfo> MI = 95cb5dc1faSalx32 MergedFunctionsInfo::decode(InfoData, BaseAddr)) 96cb5dc1faSalx32 FI.MergedFunctions = std::move(MI.get()); 97cb5dc1faSalx32 else 98cb5dc1faSalx32 return MI.takeError(); 99cb5dc1faSalx32 break; 100cb5dc1faSalx32 1015147e594Salx32 case InfoType::CallSiteInfo: 1025147e594Salx32 if (Expected<llvm::gsym::CallSiteInfoCollection> CI = 1035147e594Salx32 llvm::gsym::CallSiteInfoCollection::decode(InfoData)) 1045147e594Salx32 FI.CallSites = std::move(CI.get()); 1055147e594Salx32 else 1065147e594Salx32 return CI.takeError(); 1075147e594Salx32 break; 1085147e594Salx32 109b52650d5SGreg Clayton default: 110b52650d5SGreg Clayton return createStringError(std::errc::io_error, 111b52650d5SGreg Clayton "0x%8.8" PRIx64 ": unsupported InfoType %u", 112b52650d5SGreg Clayton Offset-8, IT); 113b52650d5SGreg Clayton } 114b52650d5SGreg Clayton Offset += InfoLength; 115b52650d5SGreg Clayton } 116c55cf4afSBill Wendling return std::move(FI); 117b52650d5SGreg Clayton } 118b52650d5SGreg Clayton 119d8e077e2SGreg Clayton uint64_t FunctionInfo::cacheEncoding() { 120d8e077e2SGreg Clayton EncodingCache.clear(); 121d8e077e2SGreg Clayton if (!isValid()) 122d8e077e2SGreg Clayton return 0; 123d8e077e2SGreg Clayton raw_svector_ostream OutStrm(EncodingCache); 1246b31b026SKazu Hirata FileWriter FW(OutStrm, llvm::endianness::native); 125d8e077e2SGreg Clayton llvm::Expected<uint64_t> Result = encode(FW); 126d8e077e2SGreg Clayton if (!Result) { 127d8e077e2SGreg Clayton EncodingCache.clear(); 128d8e077e2SGreg Clayton consumeError(Result.takeError()); 129d8e077e2SGreg Clayton return 0; 130d8e077e2SGreg Clayton } 131d8e077e2SGreg Clayton return EncodingCache.size(); 132d8e077e2SGreg Clayton } 133d8e077e2SGreg Clayton 134cb5dc1faSalx32 llvm::Expected<uint64_t> FunctionInfo::encode(FileWriter &Out, 135cb5dc1faSalx32 bool NoPadding) const { 136b52650d5SGreg Clayton if (!isValid()) 137b52650d5SGreg Clayton return createStringError(std::errc::invalid_argument, 138b52650d5SGreg Clayton "attempted to encode invalid FunctionInfo object"); 139cb5dc1faSalx32 // Align FunctionInfo data to a 4 byte alignment, if padding is allowed 140cb5dc1faSalx32 if (NoPadding == false) 141d8e077e2SGreg Clayton Out.alignTo(4); 142d8e077e2SGreg Clayton const uint64_t FuncInfoOffset = Out.tell(); 143d8e077e2SGreg Clayton // Check if we have already encoded this function info into EncodingCache. 144d8e077e2SGreg Clayton // This will be non empty when creating segmented GSYM files as we need to 145d8e077e2SGreg Clayton // precompute exactly how big FunctionInfo objects encode into so we can 146d8e077e2SGreg Clayton // accurately make segments of a specific size. 147d8e077e2SGreg Clayton if (!EncodingCache.empty() && 1486b31b026SKazu Hirata llvm::endianness::native == Out.getByteOrder()) { 149d8e077e2SGreg Clayton // We already encoded this object, just write out the bytes. 150d8e077e2SGreg Clayton Out.writeData(llvm::ArrayRef<uint8_t>((const uint8_t *)EncodingCache.data(), 151d8e077e2SGreg Clayton EncodingCache.size())); 152d8e077e2SGreg Clayton return FuncInfoOffset; 153d8e077e2SGreg Clayton } 154b52650d5SGreg Clayton // Write the size in bytes of this function as a uint32_t. This can be zero 155b52650d5SGreg Clayton // if we just have a symbol from a symbol table and that symbol has no size. 156d8e077e2SGreg Clayton Out.writeU32(size()); 157b52650d5SGreg Clayton // Write the name of this function as a uint32_t string table offset. 158d8e077e2SGreg Clayton Out.writeU32(Name); 159b52650d5SGreg Clayton 160e0e687a6SKazu Hirata if (OptLineTable) { 161d8e077e2SGreg Clayton Out.writeU32(InfoType::LineTableInfo); 162b52650d5SGreg Clayton // Write a uint32_t length as zero for now, we will fix this up after 163b52650d5SGreg Clayton // writing the LineTable out with the number of bytes that were written. 164d8e077e2SGreg Clayton Out.writeU32(0); 165d8e077e2SGreg Clayton const auto StartOffset = Out.tell(); 166d8e077e2SGreg Clayton llvm::Error err = OptLineTable->encode(Out, Range.start()); 167b52650d5SGreg Clayton if (err) 168c55cf4afSBill Wendling return std::move(err); 169d8e077e2SGreg Clayton const auto Length = Out.tell() - StartOffset; 170b52650d5SGreg Clayton if (Length > UINT32_MAX) 171b52650d5SGreg Clayton return createStringError(std::errc::invalid_argument, 172b52650d5SGreg Clayton "LineTable length is greater than UINT32_MAX"); 173b52650d5SGreg Clayton // Fixup the size of the LineTable data with the correct size. 174d8e077e2SGreg Clayton Out.fixup32(static_cast<uint32_t>(Length), StartOffset - 4); 175b52650d5SGreg Clayton } 176b52650d5SGreg Clayton 177b52650d5SGreg Clayton // Write out the inline function info if we have any and if it is valid. 178e0e687a6SKazu Hirata if (Inline) { 179d8e077e2SGreg Clayton Out.writeU32(InfoType::InlineInfo); 180b52650d5SGreg Clayton // Write a uint32_t length as zero for now, we will fix this up after 181b52650d5SGreg Clayton // writing the LineTable out with the number of bytes that were written. 182d8e077e2SGreg Clayton Out.writeU32(0); 183d8e077e2SGreg Clayton const auto StartOffset = Out.tell(); 184d8e077e2SGreg Clayton llvm::Error err = Inline->encode(Out, Range.start()); 185b52650d5SGreg Clayton if (err) 186c55cf4afSBill Wendling return std::move(err); 187d8e077e2SGreg Clayton const auto Length = Out.tell() - StartOffset; 188b52650d5SGreg Clayton if (Length > UINT32_MAX) 189b52650d5SGreg Clayton return createStringError(std::errc::invalid_argument, 190b52650d5SGreg Clayton "InlineInfo length is greater than UINT32_MAX"); 191b52650d5SGreg Clayton // Fixup the size of the InlineInfo data with the correct size. 192d8e077e2SGreg Clayton Out.fixup32(static_cast<uint32_t>(Length), StartOffset - 4); 193b52650d5SGreg Clayton } 194b52650d5SGreg Clayton 195cb5dc1faSalx32 // Write out the merged functions info if we have any and if it is valid. 196cb5dc1faSalx32 if (MergedFunctions) { 197cb5dc1faSalx32 Out.writeU32(InfoType::MergedFunctionsInfo); 198cb5dc1faSalx32 // Write a uint32_t length as zero for now, we will fix this up after 199cb5dc1faSalx32 // writing the LineTable out with the number of bytes that were written. 200cb5dc1faSalx32 Out.writeU32(0); 201cb5dc1faSalx32 const auto StartOffset = Out.tell(); 202cb5dc1faSalx32 llvm::Error err = MergedFunctions->encode(Out); 203cb5dc1faSalx32 if (err) 204cb5dc1faSalx32 return std::move(err); 205cb5dc1faSalx32 const auto Length = Out.tell() - StartOffset; 206cb5dc1faSalx32 if (Length > UINT32_MAX) 207cb5dc1faSalx32 return createStringError( 208cb5dc1faSalx32 std::errc::invalid_argument, 209cb5dc1faSalx32 "MergedFunctionsInfo length is greater than UINT32_MAX"); 210cb5dc1faSalx32 // Fixup the size of the MergedFunctionsInfo data with the correct size. 211cb5dc1faSalx32 Out.fixup32(static_cast<uint32_t>(Length), StartOffset - 4); 212cb5dc1faSalx32 } 213cb5dc1faSalx32 2145147e594Salx32 // Write out the call sites if we have any and if they are valid. 2155147e594Salx32 if (CallSites) { 2165147e594Salx32 Out.writeU32(InfoType::CallSiteInfo); 2175147e594Salx32 // Write a uint32_t length as zero for now, we will fix this up after 2185147e594Salx32 // writing the CallSites out with the number of bytes that were written. 2195147e594Salx32 Out.writeU32(0); 2205147e594Salx32 const auto StartOffset = Out.tell(); 2215147e594Salx32 Error Err = CallSites->encode(Out); 2225147e594Salx32 if (Err) 2235147e594Salx32 return std::move(Err); 2245147e594Salx32 const auto Length = Out.tell() - StartOffset; 2255147e594Salx32 if (Length > UINT32_MAX) 2265147e594Salx32 return createStringError(std::errc::invalid_argument, 2275147e594Salx32 "CallSites length is greater than UINT32_MAX"); 2285147e594Salx32 // Fixup the size of the CallSites data with the correct size. 2295147e594Salx32 Out.fixup32(static_cast<uint32_t>(Length), StartOffset - 4); 2305147e594Salx32 } 2315147e594Salx32 2325147e594Salx32 // Terminate the data chunks with an end of list with zero size. 233d8e077e2SGreg Clayton Out.writeU32(InfoType::EndOfList); 234d8e077e2SGreg Clayton Out.writeU32(0); 235b52650d5SGreg Clayton return FuncInfoOffset; 236b52650d5SGreg Clayton } 237aeda128aSGreg Clayton 2386f28b4b5Salx32 llvm::Expected<LookupResult> 2396f28b4b5Salx32 FunctionInfo::lookup(DataExtractor &Data, const GsymReader &GR, 2406f28b4b5Salx32 uint64_t FuncAddr, uint64_t Addr, 2416f28b4b5Salx32 std::optional<DataExtractor> *MergedFuncsData) { 242aeda128aSGreg Clayton LookupResult LR; 243aeda128aSGreg Clayton LR.LookupAddr = Addr; 244aeda128aSGreg Clayton uint64_t Offset = 0; 245854c3394SAlexey Lapshin LR.FuncRange = {FuncAddr, FuncAddr + Data.getU32(&Offset)}; 246aeda128aSGreg Clayton uint32_t NameOffset = Data.getU32(&Offset); 247aeda128aSGreg Clayton // The "lookup" functions doesn't report errors as accurately as the "decode" 248aeda128aSGreg Clayton // function as it is meant to be fast. For more accurage errors we could call 249aeda128aSGreg Clayton // "decode". 250aeda128aSGreg Clayton if (!Data.isValidOffset(Offset)) 251aeda128aSGreg Clayton return createStringError(std::errc::io_error, 252aeda128aSGreg Clayton "FunctionInfo data is truncated"); 253aeda128aSGreg Clayton // This function will be called with the result of a binary search of the 254aeda128aSGreg Clayton // address table, we must still make sure the address does not fall into a 255aeda128aSGreg Clayton // gap between functions are after the last function. 2562f6cc21fSGreg Clayton if (LR.FuncRange.size() > 0 && !LR.FuncRange.contains(Addr)) 257aeda128aSGreg Clayton return createStringError(std::errc::io_error, 258aeda128aSGreg Clayton "address 0x%" PRIx64 " is not in GSYM", Addr); 259aeda128aSGreg Clayton 260aeda128aSGreg Clayton if (NameOffset == 0) 261aeda128aSGreg Clayton return createStringError(std::errc::io_error, 262aeda128aSGreg Clayton "0x%8.8" PRIx64 ": invalid FunctionInfo Name value 0x00000000", 263aeda128aSGreg Clayton Offset - 4); 264aeda128aSGreg Clayton LR.FuncName = GR.getString(NameOffset); 265aeda128aSGreg Clayton bool Done = false; 266367515d4SKazu Hirata std::optional<LineEntry> LineEntry; 267367515d4SKazu Hirata std::optional<DataExtractor> InlineInfoData; 268aeda128aSGreg Clayton while (!Done) { 269aeda128aSGreg Clayton if (!Data.isValidOffsetForDataOfSize(Offset, 8)) 270aeda128aSGreg Clayton return createStringError(std::errc::io_error, 271aeda128aSGreg Clayton "FunctionInfo data is truncated"); 2727f63db19SReid Kleckner const uint32_t IT = Data.getU32(&Offset); 273aeda128aSGreg Clayton const uint32_t InfoLength = Data.getU32(&Offset); 274aeda128aSGreg Clayton const StringRef InfoBytes = Data.getData().substr(Offset, InfoLength); 275aeda128aSGreg Clayton if (InfoLength != InfoBytes.size()) 276aeda128aSGreg Clayton return createStringError(std::errc::io_error, 277aeda128aSGreg Clayton "FunctionInfo data is truncated"); 278aeda128aSGreg Clayton DataExtractor InfoData(InfoBytes, Data.isLittleEndian(), 279aeda128aSGreg Clayton Data.getAddressSize()); 2807f63db19SReid Kleckner switch (IT) { 281aeda128aSGreg Clayton case InfoType::EndOfList: 282aeda128aSGreg Clayton Done = true; 283aeda128aSGreg Clayton break; 284aeda128aSGreg Clayton 285aeda128aSGreg Clayton case InfoType::LineTableInfo: 286aeda128aSGreg Clayton if (auto ExpectedLE = LineTable::lookup(InfoData, FuncAddr, Addr)) 287aeda128aSGreg Clayton LineEntry = ExpectedLE.get(); 288aeda128aSGreg Clayton else 289aeda128aSGreg Clayton return ExpectedLE.takeError(); 290aeda128aSGreg Clayton break; 291aeda128aSGreg Clayton 2926f28b4b5Salx32 case InfoType::MergedFunctionsInfo: 2936f28b4b5Salx32 // Store the merged functions data for later parsing, if needed. 2946f28b4b5Salx32 if (MergedFuncsData) 2956f28b4b5Salx32 *MergedFuncsData = InfoData; 2966f28b4b5Salx32 break; 2976f28b4b5Salx32 298aeda128aSGreg Clayton case InfoType::InlineInfo: 299aeda128aSGreg Clayton // We will parse the inline info after our line table, but only if 300aeda128aSGreg Clayton // we have a line entry. 301aeda128aSGreg Clayton InlineInfoData = InfoData; 302aeda128aSGreg Clayton break; 303aeda128aSGreg Clayton 3044a1c33d3Salx32 case InfoType::CallSiteInfo: 3054a1c33d3Salx32 if (auto CSIC = CallSiteInfoCollection::decode(InfoData)) { 3064a1c33d3Salx32 // Find matching call site based on relative offset 3074a1c33d3Salx32 for (const auto &CS : CSIC->CallSites) { 3084a1c33d3Salx32 // Check if the call site matches the lookup address 3094a1c33d3Salx32 if (CS.ReturnOffset == Addr - FuncAddr) { 3104a1c33d3Salx32 // Get regex patterns 3114a1c33d3Salx32 for (uint32_t RegexOffset : CS.MatchRegex) { 3124a1c33d3Salx32 LR.CallSiteFuncRegex.push_back(GR.getString(RegexOffset)); 3134a1c33d3Salx32 } 3144a1c33d3Salx32 break; 3154a1c33d3Salx32 } 3164a1c33d3Salx32 } 3174a1c33d3Salx32 } else { 3184a1c33d3Salx32 return CSIC.takeError(); 3194a1c33d3Salx32 } 320*e4f03b15SKazu Hirata break; 3214a1c33d3Salx32 322aeda128aSGreg Clayton default: 323aeda128aSGreg Clayton break; 324aeda128aSGreg Clayton } 325aeda128aSGreg Clayton Offset += InfoLength; 326aeda128aSGreg Clayton } 327aeda128aSGreg Clayton 328aeda128aSGreg Clayton if (!LineEntry) { 329aeda128aSGreg Clayton // We don't have a valid line entry for our address, fill in our source 330aeda128aSGreg Clayton // location as best we can and return. 331aeda128aSGreg Clayton SourceLocation SrcLoc; 332aeda128aSGreg Clayton SrcLoc.Name = LR.FuncName; 33395e39561SGreg Clayton SrcLoc.Offset = Addr - FuncAddr; 334aeda128aSGreg Clayton LR.Locations.push_back(SrcLoc); 335aeda128aSGreg Clayton return LR; 336aeda128aSGreg Clayton } 337aeda128aSGreg Clayton 33889fab98eSFangrui Song std::optional<FileEntry> LineEntryFile = GR.getFile(LineEntry->File); 339aeda128aSGreg Clayton if (!LineEntryFile) 340aeda128aSGreg Clayton return createStringError(std::errc::invalid_argument, 341aeda128aSGreg Clayton "failed to extract file[%" PRIu32 "]", 342aeda128aSGreg Clayton LineEntry->File); 343aeda128aSGreg Clayton 344aeda128aSGreg Clayton SourceLocation SrcLoc; 345aeda128aSGreg Clayton SrcLoc.Name = LR.FuncName; 34695e39561SGreg Clayton SrcLoc.Offset = Addr - FuncAddr; 347aeda128aSGreg Clayton SrcLoc.Dir = GR.getString(LineEntryFile->Dir); 348aeda128aSGreg Clayton SrcLoc.Base = GR.getString(LineEntryFile->Base); 349aeda128aSGreg Clayton SrcLoc.Line = LineEntry->Line; 350aeda128aSGreg Clayton LR.Locations.push_back(SrcLoc); 351aeda128aSGreg Clayton // If we don't have inline information, we are done. 352aeda128aSGreg Clayton if (!InlineInfoData) 353aeda128aSGreg Clayton return LR; 354aeda128aSGreg Clayton // We have inline information. Try to augment the lookup result with this 355aeda128aSGreg Clayton // data. 356aeda128aSGreg Clayton llvm::Error Err = InlineInfo::lookup(GR, *InlineInfoData, FuncAddr, Addr, 357aeda128aSGreg Clayton LR.Locations); 358aeda128aSGreg Clayton if (Err) 359c55cf4afSBill Wendling return std::move(Err); 360aeda128aSGreg Clayton return LR; 361aeda128aSGreg Clayton } 362