LLVM  14.0.0git
SymbolizableObjectFile.cpp
Go to the documentation of this file.
1 //===- SymbolizableObjectFile.cpp -----------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Implementation of SymbolizableObjectFile class.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "SymbolizableObjectFile.h"
14 #include "llvm/ADT/STLExtras.h"
15 #include "llvm/ADT/Triple.h"
16 #include "llvm/BinaryFormat/COFF.h"
18 #include "llvm/Object/COFF.h"
20 #include "llvm/Object/ObjectFile.h"
21 #include "llvm/Object/SymbolSize.h"
22 #include "llvm/Support/Casting.h"
24 #include <algorithm>
25 
26 using namespace llvm;
27 using namespace object;
28 using namespace symbolize;
29 
31 SymbolizableObjectFile::create(const object::ObjectFile *Obj,
32  std::unique_ptr<DIContext> DICtx,
33  bool UntagAddresses) {
34  assert(DICtx);
35  std::unique_ptr<SymbolizableObjectFile> res(
36  new SymbolizableObjectFile(Obj, std::move(DICtx), UntagAddresses));
37  std::unique_ptr<DataExtractor> OpdExtractor;
38  uint64_t OpdAddress = 0;
39  // Find the .opd (function descriptor) section if any, for big-endian
40  // PowerPC64 ELF.
41  if (Obj->getArch() == Triple::ppc64) {
42  for (section_iterator Section : Obj->sections()) {
43  Expected<StringRef> NameOrErr = Section->getName();
44  if (!NameOrErr)
45  return NameOrErr.takeError();
46 
47  if (*NameOrErr == ".opd") {
48  Expected<StringRef> E = Section->getContents();
49  if (!E)
50  return E.takeError();
51  OpdExtractor.reset(new DataExtractor(*E, Obj->isLittleEndian(),
52  Obj->getBytesInAddress()));
53  OpdAddress = Section->getAddress();
54  break;
55  }
56  }
57  }
58  std::vector<std::pair<SymbolRef, uint64_t>> Symbols =
59  computeSymbolSizes(*Obj);
60  for (auto &P : Symbols)
61  if (Error E =
62  res->addSymbol(P.first, P.second, OpdExtractor.get(), OpdAddress))
63  return std::move(E);
64 
65  // If this is a COFF object and we didn't find any symbols, try the export
66  // table.
67  if (Symbols.empty()) {
68  if (auto *CoffObj = dyn_cast<COFFObjectFile>(Obj))
69  if (Error E = res->addCoffExportSymbols(CoffObj))
70  return std::move(E);
71  }
72 
73  std::vector<SymbolDesc> &SS = res->Symbols;
74  // Sort by (Addr,Size,Name). If several SymbolDescs share the same Addr,
75  // pick the one with the largest Size. This helps us avoid symbols with no
76  // size information (Size=0).
78  auto I = SS.begin(), E = SS.end(), J = SS.begin();
79  while (I != E) {
80  auto OI = I;
81  while (++I != E && OI->Addr == I->Addr) {
82  }
83  *J++ = I[-1];
84  }
85  SS.erase(J, SS.end());
86 
87  return std::move(res);
88 }
89 
90 SymbolizableObjectFile::SymbolizableObjectFile(const ObjectFile *Obj,
91  std::unique_ptr<DIContext> DICtx,
92  bool UntagAddresses)
93  : Module(Obj), DebugInfoContext(std::move(DICtx)),
94  UntagAddresses(UntagAddresses) {}
95 
96 namespace {
97 
98 struct OffsetNamePair {
100  StringRef Name;
101 
102  bool operator<(const OffsetNamePair &R) const {
103  return Offset < R.Offset;
104  }
105 };
106 
107 } // end anonymous namespace
108 
109 Error SymbolizableObjectFile::addCoffExportSymbols(
110  const COFFObjectFile *CoffObj) {
111  // Get all export names and offsets.
112  std::vector<OffsetNamePair> ExportSyms;
113  for (const ExportDirectoryEntryRef &Ref : CoffObj->export_directories()) {
114  StringRef Name;
116  if (auto EC = Ref.getSymbolName(Name))
117  return EC;
118  if (auto EC = Ref.getExportRVA(Offset))
119  return EC;
120  ExportSyms.push_back(OffsetNamePair{Offset, Name});
121  }
122  if (ExportSyms.empty())
123  return Error::success();
124 
125  // Sort by ascending offset.
126  array_pod_sort(ExportSyms.begin(), ExportSyms.end());
127 
128  // Approximate the symbol sizes by assuming they run to the next symbol.
129  // FIXME: This assumes all exports are functions.
130  uint64_t ImageBase = CoffObj->getImageBase();
131  for (auto I = ExportSyms.begin(), E = ExportSyms.end(); I != E; ++I) {
132  OffsetNamePair &Export = *I;
133  // FIXME: The last export has a one byte size now.
134  uint32_t NextOffset = I != E ? I->Offset : Export.Offset + 1;
135  uint64_t SymbolStart = ImageBase + Export.Offset;
136  uint64_t SymbolSize = NextOffset - Export.Offset;
137  Symbols.push_back({SymbolStart, SymbolSize, Export.Name, 0});
138  }
139  return Error::success();
140 }
141 
142 Error SymbolizableObjectFile::addSymbol(const SymbolRef &Symbol,
143  uint64_t SymbolSize,
144  DataExtractor *OpdExtractor,
145  uint64_t OpdAddress) {
146  // Avoid adding symbols from an unknown/undefined section.
147  const ObjectFile &Obj = *Symbol.getObject();
148  Expected<StringRef> SymbolNameOrErr = Symbol.getName();
149  if (!SymbolNameOrErr)
150  return SymbolNameOrErr.takeError();
151  StringRef SymbolName = *SymbolNameOrErr;
152 
153  uint32_t ELFSymIdx =
154  Obj.isELF() ? ELFSymbolRef(Symbol).getRawDataRefImpl().d.b : 0;
155  Expected<section_iterator> Sec = Symbol.getSection();
156  if (!Sec || Obj.section_end() == *Sec) {
157  if (Obj.isELF()) {
158  // Store the (index, filename) pair for a file symbol.
159  ELFSymbolRef ESym(Symbol);
160  if (ESym.getELFType() == ELF::STT_FILE)
161  FileSymbols.emplace_back(ELFSymIdx, SymbolName);
162  }
163  return Error::success();
164  }
165 
166  Expected<SymbolRef::Type> SymbolTypeOrErr = Symbol.getType();
167  if (!SymbolTypeOrErr)
168  return SymbolTypeOrErr.takeError();
169  SymbolRef::Type SymbolType = *SymbolTypeOrErr;
170  if (Obj.isELF()) {
171  // Allow function and data symbols. Additionally allow STT_NONE, which are
172  // common for functions defined in assembly.
173  uint8_t Type = ELFSymbolRef(Symbol).getELFType();
174  if (Type != ELF::STT_NOTYPE && Type != ELF::STT_FUNC &&
176  return Error::success();
177  // Some STT_NOTYPE symbols are not desired. This excludes STT_SECTION and
178  // ARM mapping symbols.
179  uint32_t Flags = cantFail(Symbol.getFlags());
180  if (Flags & SymbolRef::SF_FormatSpecific)
181  return Error::success();
182  } else if (SymbolType != SymbolRef::ST_Function &&
184  return Error::success();
185  }
186 
187  Expected<uint64_t> SymbolAddressOrErr = Symbol.getAddress();
188  if (!SymbolAddressOrErr)
189  return SymbolAddressOrErr.takeError();
190  uint64_t SymbolAddress = *SymbolAddressOrErr;
191  if (UntagAddresses) {
192  // For kernel addresses, bits 56-63 need to be set, so we sign extend bit 55
193  // into bits 56-63 instead of masking them out.
194  SymbolAddress &= (1ull << 56) - 1;
195  SymbolAddress = (int64_t(SymbolAddress) << 8) >> 8;
196  }
197  if (OpdExtractor) {
198  // For big-endian PowerPC64 ELF, symbols in the .opd section refer to
199  // function descriptors. The first word of the descriptor is a pointer to
200  // the function's code.
201  // For the purposes of symbolization, pretend the symbol's address is that
202  // of the function's code, not the descriptor.
203  uint64_t OpdOffset = SymbolAddress - OpdAddress;
204  if (OpdExtractor->isValidOffsetForAddress(OpdOffset))
205  SymbolAddress = OpdExtractor->getAddress(&OpdOffset);
206  }
207  // Mach-O symbol table names have leading underscore, skip it.
208  if (Module->isMachO() && !SymbolName.empty() && SymbolName[0] == '_')
209  SymbolName = SymbolName.drop_front();
210 
211  if (Obj.isELF() && ELFSymbolRef(Symbol).getBinding() != ELF::STB_LOCAL)
212  ELFSymIdx = 0;
213  Symbols.push_back({SymbolAddress, SymbolSize, SymbolName, ELFSymIdx});
214  return Error::success();
215 }
216 
217 // Return true if this is a 32-bit x86 PE COFF module.
219  auto *CoffObject = dyn_cast<COFFObjectFile>(Module);
220  return CoffObject && CoffObject->getMachine() == COFF::IMAGE_FILE_MACHINE_I386;
221 }
222 
224  if (auto *CoffObject = dyn_cast<COFFObjectFile>(Module))
225  return CoffObject->getImageBase();
226  return 0;
227 }
228 
229 bool SymbolizableObjectFile::getNameFromSymbolTable(
230  uint64_t Address, std::string &Name, uint64_t &Addr, uint64_t &Size,
231  std::string &FileName) const {
232  SymbolDesc SD{Address, UINT64_C(-1), StringRef(), 0};
233  auto SymbolIterator = llvm::upper_bound(Symbols, SD);
234  if (SymbolIterator == Symbols.begin())
235  return false;
236  --SymbolIterator;
237  if (SymbolIterator->Size != 0 &&
238  SymbolIterator->Addr + SymbolIterator->Size <= Address)
239  return false;
240  Name = SymbolIterator->Name.str();
241  Addr = SymbolIterator->Addr;
242  Size = SymbolIterator->Size;
243 
244  if (SymbolIterator->ELFLocalSymIdx != 0) {
245  // If this is an ELF local symbol, find the STT_FILE symbol preceding
246  // SymbolIterator to get the filename. The ELF spec requires the STT_FILE
247  // symbol (if present) precedes the other STB_LOCAL symbols for the file.
248  assert(Module->isELF());
249  auto It = llvm::upper_bound(
250  FileSymbols,
251  std::make_pair(SymbolIterator->ELFLocalSymIdx, StringRef()));
252  if (It != FileSymbols.begin())
253  FileName = It[-1].second.str();
254  }
255  return true;
256 }
257 
258 bool SymbolizableObjectFile::shouldOverrideWithSymbolTable(
259  FunctionNameKind FNKind, bool UseSymbolTable) const {
260  // When DWARF is used with -gline-tables-only / -gmlt, the symbol table gives
261  // better answers for linkage names than the DIContext. Otherwise, we are
262  // probably using PEs and PDBs, and we shouldn't do the override. PE files
263  // generally only contain the names of exported symbols.
264  return FNKind == FunctionNameKind::LinkageName && UseSymbolTable &&
265  isa<DWARFContext>(DebugInfoContext.get());
266 }
267 
270  DILineInfoSpecifier LineInfoSpecifier,
271  bool UseSymbolTable) const {
273  ModuleOffset.SectionIndex =
274  getModuleSectionIndexForAddress(ModuleOffset.Address);
275  DILineInfo LineInfo =
276  DebugInfoContext->getLineInfoForAddress(ModuleOffset, LineInfoSpecifier);
277 
278  // Override function name from symbol table if necessary.
279  if (shouldOverrideWithSymbolTable(LineInfoSpecifier.FNKind, UseSymbolTable)) {
280  std::string FunctionName, FileName;
281  uint64_t Start, Size;
282  if (getNameFromSymbolTable(ModuleOffset.Address, FunctionName, Start, Size,
283  FileName)) {
284  LineInfo.FunctionName = FunctionName;
285  LineInfo.StartAddress = Start;
286  if (LineInfo.FileName == DILineInfo::BadString && !FileName.empty())
287  LineInfo.FileName = FileName;
288  }
289  }
290  return LineInfo;
291 }
292 
294  object::SectionedAddress ModuleOffset,
295  DILineInfoSpecifier LineInfoSpecifier, bool UseSymbolTable) const {
297  ModuleOffset.SectionIndex =
298  getModuleSectionIndexForAddress(ModuleOffset.Address);
299  DIInliningInfo InlinedContext = DebugInfoContext->getInliningInfoForAddress(
300  ModuleOffset, LineInfoSpecifier);
301 
302  // Make sure there is at least one frame in context.
303  if (InlinedContext.getNumberOfFrames() == 0)
304  InlinedContext.addFrame(DILineInfo());
305 
306  // Override the function name in lower frame with name from symbol table.
307  if (shouldOverrideWithSymbolTable(LineInfoSpecifier.FNKind, UseSymbolTable)) {
308  std::string FunctionName, FileName;
309  uint64_t Start, Size;
310  if (getNameFromSymbolTable(ModuleOffset.Address, FunctionName, Start, Size,
311  FileName)) {
312  DILineInfo *LI = InlinedContext.getMutableFrame(
313  InlinedContext.getNumberOfFrames() - 1);
314  LI->FunctionName = FunctionName;
315  LI->StartAddress = Start;
316  if (LI->FileName == DILineInfo::BadString && !FileName.empty())
317  LI->FileName = FileName;
318  }
319  }
320 
321  return InlinedContext;
322 }
323 
325  object::SectionedAddress ModuleOffset) const {
326  DIGlobal Res;
327  std::string FileName;
328  getNameFromSymbolTable(ModuleOffset.Address, Res.Name, Res.Start, Res.Size,
329  FileName);
330  return Res;
331 }
332 
334  object::SectionedAddress ModuleOffset) const {
336  ModuleOffset.SectionIndex =
337  getModuleSectionIndexForAddress(ModuleOffset.Address);
338  return DebugInfoContext->getLocalsForAddress(ModuleOffset);
339 }
340 
341 /// Search for the first occurence of specified Address in ObjectFile.
342 uint64_t SymbolizableObjectFile::getModuleSectionIndexForAddress(
343  uint64_t Address) const {
344 
345  for (SectionRef Sec : Module->sections()) {
346  if (!Sec.isText() || Sec.isVirtual())
347  continue;
348 
349  if (Address >= Sec.getAddress() &&
350  Address < Sec.getAddress() + Sec.getSize())
351  return Sec.getIndex();
352  }
353 
355 }
llvm::Check::Size
@ Size
Definition: FileCheck.h:73
llvm::array_pod_sort
void array_pod_sort(IteratorTy Start, IteratorTy End)
array_pod_sort - This sorts an array with the specified start and end extent.
Definition: STLExtras.h:1499
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AllocatorList.h:23
llvm::object::ObjectFile::getBytesInAddress
virtual uint8_t getBytesInAddress() const =0
The number of bytes used to represent an address in this object file format.
llvm::symbolize::SymbolizableObjectFile::isWin32Module
bool isWin32Module() const override
Definition: SymbolizableObjectFile.cpp:218
llvm::upper_bound
auto upper_bound(R &&Range, T &&Value)
Provide wrappers to std::upper_bound which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:1723
llvm::DIInliningInfo
A format-neutral container for inlined code description.
Definition: DIContext.h:87
llvm::DILineInfoSpecifier
Controls which fields of DILineInfo container should be filled with data.
Definition: DIContext.h:135
P
This currently compiles esp xmm0 movsd esp eax eax esp ret We should use not the dag combiner This is because dagcombine2 needs to be able to see through the X86ISD::Wrapper which DAGCombine can t really do The code for turning x load into a single vector load is target independent and should be moved to the dag combiner The code for turning x load into a vector load can only handle a direct load from a global or a direct load from the stack It should be generalized to handle any load from P
Definition: README-SSE.txt:411
llvm::object::Binary::isLittleEndian
bool isLittleEndian() const
Definition: Binary.h:148
llvm::object::SectionedAddress::Address
uint64_t Address
Definition: ObjectFile.h:147
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:331
llvm::XCOFF::SymbolType
SymbolType
Definition: XCOFF.h:196
DWARFContext.h
COFF.h
llvm::DILineInfo::BadString
static constexpr const char *const BadString
Definition: DIContext.h:33
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
llvm::object::ObjectFile::getArch
virtual Triple::ArchType getArch() const =0
SymbolSize.h
Offset
uint64_t Offset
Definition: ELFObjHandler.cpp:81
llvm::object::SymbolRef::ST_Data
@ ST_Data
Definition: ObjectFile.h:173
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:42
STLExtras.h
llvm::DINameKind::LinkageName
@ LinkageName
llvm::object::SectionedAddress::SectionIndex
uint64_t SectionIndex
Definition: ObjectFile.h:148
llvm::DILineInfo::FunctionName
std::string FunctionName
Definition: DIContext.h:37
SymbolizableObjectFile.h
llvm::ARMBuildAttrs::Section
@ Section
Legacy Tags.
Definition: ARMBuildAttributes.h:82
llvm::COFF::IMAGE_FILE_MACHINE_I386
@ IMAGE_FILE_MACHINE_I386
Definition: COFF.h:103
llvm::DIGlobal::Start
uint64_t Start
Definition: DIContext.h:113
llvm::DINameKind
DINameKind
A DINameKind is passed to name search methods to specify a preference regarding the type of name reso...
Definition: DIContext.h:131
llvm::ModRefInfo::Ref
@ Ref
The access may reference the value stored in memory.
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::symbolize::SymbolizableObjectFile::symbolizeCode
DILineInfo symbolizeCode(object::SectionedAddress ModuleOffset, DILineInfoSpecifier LineInfoSpecifier, bool UseSymbolTable) const override
Definition: SymbolizableObjectFile.cpp:269
llvm::DataExtractor::isValidOffsetForAddress
bool isValidOffsetForAddress(uint64_t offset) const
Test the availability of enough bytes of data for a pointer from offset.
Definition: DataExtractor.h:683
llvm::Triple::ppc64
@ ppc64
Definition: Triple.h:69
llvm::ELF::STT_FILE
@ STT_FILE
Definition: ELF.h:1160
llvm::symbolize::SymbolizableObjectFile::symbolizeData
DIGlobal symbolizeData(object::SectionedAddress ModuleOffset) const override
Definition: SymbolizableObjectFile.cpp:324
llvm::symbolize::SymbolizableObjectFile
Definition: SymbolizableObjectFile.h:31
llvm::ELF::STT_FUNC
@ STT_FUNC
Definition: ELF.h:1158
llvm::ELF::STB_LOCAL
@ STB_LOCAL
Definition: ELF.h:1144
llvm::object::SectionRef
This is a value type class that represents a single section in the list of sections in the object fil...
Definition: ObjectFile.h:80
object
bar al al movzbl eax ret Missed when stored in a memory object
Definition: README.txt:1411
llvm::object::BasicSymbolRef::SF_FormatSpecific
@ SF_FormatSpecific
Definition: SymbolicFile.h:115
uint64_t
llvm::object::SymbolRef::ST_Function
@ ST_Function
Definition: ObjectFile.h:176
Addr
uint64_t Addr
Definition: ELFObjHandler.cpp:80
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::object::SectionedAddress::UndefSection
const static uint64_t UndefSection
Definition: ObjectFile.h:145
llvm::operator<
bool operator<(int64_t V1, const APSInt &V2)
Definition: APSInt.h:338
I
#define I(x, y, z)
Definition: MD5.cpp:59
llvm::DILineInfo
A format-neutral container for source line information.
Definition: DIContext.h:31
llvm::HighlightColor::Address
@ Address
llvm::X86AS::SS
@ SS
Definition: X86.h:189
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::move
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1658
ObjectFile.h
llvm::object::content_iterator
Definition: SymbolicFile.h:67
llvm::DIGlobal::Name
std::string Name
Definition: DIContext.h:112
llvm::codeview::CompileSym2Flags::EC
@ EC
llvm::codeview::CodeViewContainer::ObjectFile
@ ObjectFile
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:67
Triple.h
llvm::ELF::STT_OBJECT
@ STT_OBJECT
Definition: ELF.h:1157
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
llvm::object::ObjectFile
This class is the base class for all object file types.
Definition: ObjectFile.h:228
llvm::cantFail
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Definition: Error.h:747
uint32_t
llvm::symbolize::SymbolizableObjectFile::getModulePreferredBase
uint64_t getModulePreferredBase() const override
Definition: SymbolizableObjectFile.cpp:223
llvm::DILineInfoSpecifier::FNKind
FunctionNameKind FNKind
Definition: DIContext.h:149
ELFObjectFile.h
llvm::sampleprof::InlinedContext
@ InlinedContext
Definition: SampleProf.h:404
llvm::AMDGPU::HSAMD::Kernel::Key::SymbolName
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
Definition: AMDGPUMetadata.h:381
llvm::stable_sort
void stable_sort(R &&Range)
Definition: STLExtras.h:1735
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:52
std
Definition: BitVector.h:838
llvm::DIGlobal
Container for description of a global variable.
Definition: DIContext.h:111
llvm::object::SymbolRef::Type
Type
Definition: ObjectFile.h:171
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
Casting.h
DataExtractor.h
llvm::DIGlobal::Size
uint64_t Size
Definition: DIContext.h:114
llvm::DILineInfo::StartAddress
Optional< uint64_t > StartAddress
Definition: DIContext.h:43
llvm::ARMBuildAttrs::Symbol
@ Symbol
Definition: ARMBuildAttributes.h:83
llvm::object::computeSymbolSizes
std::vector< std::pair< SymbolRef, uint64_t > > computeSymbolSizes(const ObjectFile &O)
Definition: SymbolSize.cpp:50
llvm::Expected::takeError
Error takeError()
Take ownership of the stored error.
Definition: Error.h:599
llvm::DILineInfo::FileName
std::string FileName
Definition: DIContext.h:36
llvm::DataExtractor
Definition: DataExtractor.h:41
COFF.h
llvm::object::SectionedAddress
Definition: ObjectFile.h:144
llvm::object::ObjectFile::sections
section_iterator_range sections() const
Definition: ObjectFile.h:322
llvm::symbolize::SymbolizableObjectFile::symbolizeFrame
std::vector< DILocal > symbolizeFrame(object::SectionedAddress ModuleOffset) const override
Definition: SymbolizableObjectFile.cpp:333
llvm::DataExtractor::getAddress
uint64_t getAddress(uint64_t *offset_ptr) const
Extract an pointer from *offset_ptr.
Definition: DataExtractor.h:325
llvm::ELF::STT_GNU_IFUNC
@ STT_GNU_IFUNC
Definition: ELF.h:1163
llvm::ELF::STT_NOTYPE
@ STT_NOTYPE
Definition: ELF.h:1156
llvm::pdb::PDB_SymType::Export
@ Export
llvm::symbolize::SymbolizableObjectFile::symbolizeInlinedCode
DIInliningInfo symbolizeInlinedCode(object::SectionedAddress ModuleOffset, DILineInfoSpecifier LineInfoSpecifier, bool UseSymbolTable) const override
Definition: SymbolizableObjectFile.cpp:293