1//===- SymbolizableObjectFile.cpp -----------------------------------------===//
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
7//===----------------------------------------------------------------------===//
9// Implementation of SymbolizableObjectFile class.
11//===----------------------------------------------------------------------===//
31 std::unique_ptr<DIContext> DICtx,
32 bool UntagAddresses) {
34 std::unique_ptr<SymbolizableObjectFile> res(
35 new SymbolizableObjectFile(Obj, std::move(DICtx), UntagAddresses));
36 std::unique_ptr<DataExtractor> OpdExtractor;
38 // Find the .opd (function descriptor) section if any, for big-endian
46 if (*NameOrErr ==
".opd") {
52 OpdAddress = Section->getAddress();
57 std::vector<std::pair<SymbolRef, uint64_t>> Symbols =
59 for (
auto &
P : Symbols)
61 res->addSymbol(
P.first,
P.second, OpdExtractor.get(), OpdAddress))
64 // If this is a COFF object and we didn't find any symbols, try the export
66 if (Symbols.empty()) {
68 if (
Error E = res->addCoffExportSymbols(CoffObj))
72 std::vector<SymbolDesc> &SS = res->Symbols;
73 // Sort by (Addr,Size,Name). If several SymbolDescs share the same Addr,
74 // pick the one with the largest Size. This helps us avoid symbols with no
75 // size information (Size=0).
77 auto I = SS.begin(), E = SS.end(), J = SS.begin();
80 while (++
I != E && OI->Addr ==
I->Addr) {
84 SS.erase(J, SS.end());
86 return std::move(res);
89SymbolizableObjectFile::SymbolizableObjectFile(
const ObjectFile *Obj,
90 std::unique_ptr<DIContext> DICtx,
93 UntagAddresses(UntagAddresses) {}
97struct OffsetNamePair {
101 bool operator<(
const OffsetNamePair &R)
const {
106}
// end anonymous namespace
108Error SymbolizableObjectFile::addCoffExportSymbols(
110 // Get all export names and offsets.
111 std::vector<OffsetNamePair> ExportSyms;
115 if (
auto EC =
Ref.getSymbolName(Name))
119 ExportSyms.push_back(OffsetNamePair{
Offset,
Name});
121 if (ExportSyms.empty())
124 // Sort by ascending offset.
127 // Approximate the symbol sizes by assuming they run to the next symbol.
128 // FIXME: This assumes all exports are functions.
130 for (
auto I = ExportSyms.begin(),
E = ExportSyms.end();
I !=
E; ++
I) {
132 // FIXME: The last export has a one byte size now.
133 uint32_t NextOffset =
I !=
E ?
I->Offset :
Export.Offset + 1;
135 uint64_t SymbolSize = NextOffset -
Export.Offset;
143 DataExtractor *OpdExtractor,
144 uint64_t OpdAddress) {
145 // Avoid adding symbols from an unknown/undefined section.
147 Expected<StringRef> SymbolNameOrErr =
Symbol.getName();
148 if (!SymbolNameOrErr)
153 Obj.
isELF() ? ELFSymbolRef(Symbol).getRawDataRefImpl().d.b : 0;
154 Expected<section_iterator> Sec =
Symbol.getSection();
157 // Store the (index, filename) pair for a file symbol.
158 ELFSymbolRef ESym(Symbol);
160 FileSymbols.emplace_back(ELFSymIdx, SymbolName);
165 Expected<SymbolRef::Type> SymbolTypeOrErr =
Symbol.getType();
166 if (!SymbolTypeOrErr)
170 // Ignore any symbols coming from sections that don't have runtime
172 if ((elf_section_iterator(*Sec)->getFlags() &
ELF::SHF_ALLOC) == 0)
175 // Allow function and data symbols. Additionally allow STT_NONE, which are
176 // common for functions defined in assembly.
177 uint8_t
Type = ELFSymbolRef(Symbol).getELFType();
181 // Some STT_NOTYPE symbols are not desired. This excludes STT_SECTION and
182 // ARM mapping symbols.
184 if (Flags & SymbolRef::SF_FormatSpecific)
191 Expected<uint64_t> SymbolAddressOrErr =
Symbol.getAddress();
192 if (!SymbolAddressOrErr)
194 uint64_t SymbolAddress = *SymbolAddressOrErr;
195 if (UntagAddresses) {
196 // For kernel addresses, bits 56-63 need to be set, so we sign extend bit 55
197 // into bits 56-63 instead of masking them out.
198 SymbolAddress &= (1ull << 56) - 1;
199 SymbolAddress = (int64_t(SymbolAddress) << 8) >> 8;
202 // For big-endian PowerPC64 ELF, symbols in the .opd section refer to
203 // function descriptors. The first word of the descriptor is a pointer to
204 // the function's code.
205 // For the purposes of symbolization, pretend the symbol's address is that
206 // of the function's code, not the descriptor.
207 uint64_t OpdOffset = SymbolAddress - OpdAddress;
209 SymbolAddress = OpdExtractor->
getAddress(&OpdOffset);
211 // Mach-O symbol table names have leading underscore, skip it.
212 if (Module->isMachO())
217 Symbols.push_back({SymbolAddress, SymbolSize,
SymbolName, ELFSymIdx});
221// Return true if this is a 32-bit x86 PE COFF module.
229 return CoffObject->getImageBase();
233bool SymbolizableObjectFile::getNameFromSymbolTable(
235 std::string &FileName)
const {
238 if (SymbolIterator == Symbols.begin())
241 if (SymbolIterator->Size != 0 &&
242 SymbolIterator->Addr + SymbolIterator->Size <=
Address)
244 Name = SymbolIterator->Name.str();
245 Addr = SymbolIterator->Addr;
246 Size = SymbolIterator->Size;
248 if (SymbolIterator->ELFLocalSymIdx != 0) {
249 // If this is an ELF local symbol, find the STT_FILE symbol preceding
250 // SymbolIterator to get the filename. The ELF spec requires the STT_FILE
251 // symbol (if present) precedes the other STB_LOCAL symbols for the file.
255 std::make_pair(SymbolIterator->ELFLocalSymIdx,
StringRef()));
256 if (It != FileSymbols.begin())
257 FileName = It[-1].second.str();
262bool SymbolizableObjectFile::shouldOverrideWithSymbolTable(
264 // When DWARF is used with -gline-tables-only / -gmlt, the symbol table gives
265 // better answers for linkage names than the DIContext. Otherwise, we are
266 // probably using PEs and PDBs, and we shouldn't do the override. PE files
267 // generally only contain the names of exported symbols.
268 return FNKind == FunctionNameKind::LinkageName && UseSymbolTable &&
275 bool UseSymbolTable)
const {
278 getModuleSectionIndexForAddress(ModuleOffset.
Address);
280 std::optional<DILineInfo> DBGLineInfo =
281 DebugInfoContext->getLineInfoForAddress(ModuleOffset, LineInfoSpecifier);
283 LineInfo = *DBGLineInfo;
285 // Override function name from symbol table if necessary.
286 if (shouldOverrideWithSymbolTable(LineInfoSpecifier.
FNKind, UseSymbolTable)) {
287 std::string FunctionName, FileName;
289 if (getNameFromSymbolTable(ModuleOffset.
Address, FunctionName, Start,
Size,
291 LineInfo.FunctionName = FunctionName;
292 LineInfo.StartAddress = Start;
293 // Only use the filename from symbol table if the debug info for the
294 // address is missing.
295 if (!DBGLineInfo && !FileName.empty())
296 LineInfo.FileName = FileName;
307 getModuleSectionIndexForAddress(ModuleOffset.
Address);
309 ModuleOffset, LineInfoSpecifier);
311 // Make sure there is at least one frame in context.
312 bool EmptyFrameAdded =
false;
314 EmptyFrameAdded =
true;
318 // Override the function name in lower frame with name from symbol table.
319 if (shouldOverrideWithSymbolTable(LineInfoSpecifier.
FNKind, UseSymbolTable)) {
320 std::string FunctionName, FileName;
322 if (getNameFromSymbolTable(ModuleOffset.
Address, FunctionName, Start,
Size,
328 // Only use the filename from symbol table if the debug info for the
329 // address is missing.
330 if (EmptyFrameAdded && !FileName.empty())
341 std::string FileName;
346 // Try and get a better filename:lineno pair from the debuginfo, if present.
347 std::optional<DILineInfo>
DL =
348 DebugInfoContext->getLineInfoForDataAddress(ModuleOffset);
349 if (
DL &&
DL->Line != 0) {
360 getModuleSectionIndexForAddress(ModuleOffset.
Address);
361 return DebugInfoContext->getLocalsForAddress(ModuleOffset);
364std::vector<object::SectionedAddress>
366 std::vector<object::SectionedAddress> Result;
367 for (
const SymbolDesc &Sym : Symbols) {
368 if (Sym.Name == Symbol) {
379/// Search for the first occurence of specified Address in ObjectFile.
380uint64_t SymbolizableObjectFile::getModuleSectionIndexForAddress(
384 if (!Sec.isText() || Sec.isVirtual())
387 if (
Address >= Sec.getAddress() &&
388 Address < Sec.getAddress() + Sec.getSize())
389 return Sec.getIndex();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
A format-neutral container for inlined code description.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
A Module instance is used to store all the information related to an LLVM module.
StringRef - Represent a constant reference to a string, i.e.
bool isLittleEndian() const
iterator_range< export_directory_iterator > export_directories() const
uint64_t getImageBase() const
This class is the base class for all object file types.
virtual section_iterator section_end() const =0
virtual uint8_t getBytesInAddress() const =0
The number of bytes used to represent an address in this object file format.
section_iterator_range sections() const
virtual Triple::ArchType getArch() const =0
This is a value type class that represents a single section in the list of sections in the object fil...
This is a value type class that represents a single symbol in the list of symbols in the object file.
DIGlobal symbolizeData(object::SectionedAddress ModuleOffset) const override
DILineInfo symbolizeCode(object::SectionedAddress ModuleOffset, DILineInfoSpecifier LineInfoSpecifier, bool UseSymbolTable) const override
static Expected< std::unique_ptr< SymbolizableObjectFile > > create(const object::ObjectFile *Obj, std::unique_ptr< DIContext > DICtx, bool UntagAddresses)
std::vector< object::SectionedAddress > findSymbol(StringRef Symbol, uint64_t Offset) const override
uint64_t getModulePreferredBase() const override
std::vector< DILocal > symbolizeFrame(object::SectionedAddress ModuleOffset) const override
bool isWin32Module() const override
DIInliningInfo symbolizeInlinedCode(object::SectionedAddress ModuleOffset, DILineInfoSpecifier LineInfoSpecifier, bool UseSymbolTable) const override
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
@ IMAGE_FILE_MACHINE_I386
content_iterator< SectionRef > section_iterator
LLVM_ABI std::vector< std::pair< SymbolRef, uint64_t > > computeSymbolSizes(const ObjectFile &O)
DILineInfoSpecifier::FunctionNameKind FunctionNameKind
This is an optimization pass for GlobalISel generic memory operations.
bool operator<(int64_t V1, const APSInt &V2)
void stable_sort(R &&Range)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
@ Export
Export information to summary.
auto upper_bound(R &&Range, T &&Value)
Provide wrappers to std::upper_bound which take ranges instead of having to pass begin/end explicitly...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
@ Ref
The access may reference the value stored in memory.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
void array_pod_sort(IteratorTy Start, IteratorTy End)
array_pod_sort - This sorts an array with the specified start and end extent.
Implement std::hash so that hash_code can be used in STL containers.
Container for description of a global variable.
Controls which fields of DILineInfo container should be filled with data.
A format-neutral container for source line information.
std::optional< uint64_t > StartAddress
static const uint64_t UndefSection