xref: /llvm-project/llvm/lib/DebugInfo/GSYM/FunctionInfo.cpp (revision e4f03b158c97098e1835cc1f00d0175398974f98)
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