LLVM: lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
24
25using namespace llvm;
26using namespace object;
28
31 std::unique_ptr DICtx,
32 bool UntagAddresses) {
34 std::unique_ptr res(
35 new SymbolizableObjectFile(Obj, std::move(DICtx), UntagAddresses));
36 std::unique_ptr OpdExtractor;
38
39
43 if (!NameOrErr)
45
46 if (*NameOrErr == ".opd") {
48 if (!E)
49 return E.takeError();
50 OpdExtractor.reset(new DataExtractor(*E, Obj->isLittleEndian(),
51 Obj->getBytesInAddress()));
52 OpdAddress = Section->getAddress();
53 break;
54 }
55 }
56 }
57 std::vector<std::pair<SymbolRef, uint64_t>> Symbols =
59 for (auto &P : Symbols)
61 res->addSymbol(P.first, P.second, OpdExtractor.get(), OpdAddress))
62 return std::move(E);
63
64
65
66 if (Symbols.empty()) {
68 if (Error E = res->addCoffExportSymbols(CoffObj))
69 return std::move(E);
70 }
71
72 std::vector &SS = res->Symbols;
73
74
75
77 auto I = SS.begin(), E = SS.end(), J = SS.begin();
78 while (I != E) {
79 auto OI = I;
80 while (++I != E && OI->Addr == I->Addr) {
81 }
82 *J++ = I[-1];
83 }
84 SS.erase(J, SS.end());
85
86 return std::move(res);
87}
88
89SymbolizableObjectFile::SymbolizableObjectFile(const ObjectFile *Obj,
90 std::unique_ptr DICtx,
91 bool UntagAddresses)
92 : Module(Obj), DebugInfoContext(std::move(DICtx)),
93 UntagAddresses(UntagAddresses) {}
94
95namespace {
96
97struct OffsetNamePair {
100
101 bool operator<(const OffsetNamePair &R) const {
102 return Offset < R.Offset;
103 }
104};
105
106}
107
108Error SymbolizableObjectFile::addCoffExportSymbols(
110
111 std::vector ExportSyms;
113 StringRef Name;
115 if (auto EC = Ref.getSymbolName(Name))
116 return EC;
117 if (auto EC = Ref.getExportRVA(Offset))
118 return EC;
119 ExportSyms.push_back(OffsetNamePair{Offset, Name});
120 }
121 if (ExportSyms.empty())
123
124
125 array_pod_sort(ExportSyms.begin(), ExportSyms.end());
126
127
128
129 uint64_t ImageBase = CoffObj->getImageBase();
130 for (auto I = ExportSyms.begin(), E = ExportSyms.end(); I != E; ++I) {
131 OffsetNamePair &Export = *I;
132
133 uint32_t NextOffset = I != E ? I->Offset : Export.Offset + 1;
135 uint64_t SymbolSize = NextOffset - Export.Offset;
137 }
139}
140
141Error SymbolizableObjectFile::addSymbol(const SymbolRef &Symbol,
142 uint64_t SymbolSize,
143 DataExtractor *OpdExtractor,
144 uint64_t OpdAddress) {
145
147 Expected SymbolNameOrErr = Symbol.getName();
148 if (!SymbolNameOrErr)
149 return SymbolNameOrErr.takeError();
150 StringRef SymbolName = *SymbolNameOrErr;
151
152 uint32_t ELFSymIdx =
153 Obj.isELF() ? ELFSymbolRef(Symbol).getRawDataRefImpl().d.b : 0;
154 Expected<section_iterator> Sec = Symbol.getSection();
155 if (!Sec || Obj.section_end() == *Sec) {
156 if (Obj.isELF()) {
157
158 ELFSymbolRef ESym(Symbol);
160 FileSymbols.emplace_back(ELFSymIdx, SymbolName);
161 }
163 }
164
165 ExpectedSymbolRef::Type SymbolTypeOrErr = Symbol.getType();
166 if (!SymbolTypeOrErr)
167 return SymbolTypeOrErr.takeError();
169 if (Obj.isELF()) {
170
171
172 if ((elf_section_iterator(*Sec)->getFlags() & ELF::SHF_ALLOC) == 0)
174
175
176
177 uint8_t Type = ELFSymbolRef(Symbol).getELFType();
181
182
184 if (Flags & SymbolRef::SF_FormatSpecific)
189 }
190
191 Expected<uint64_t> SymbolAddressOrErr = Symbol.getAddress();
192 if (!SymbolAddressOrErr)
193 return SymbolAddressOrErr.takeError();
194 uint64_t SymbolAddress = *SymbolAddressOrErr;
195 if (UntagAddresses) {
196
197
198 SymbolAddress &= (1ull << 56) - 1;
199 SymbolAddress = (int64_t(SymbolAddress) << 8) >> 8;
200 }
201 if (OpdExtractor) {
202
203
204
205
206
207 uint64_t OpdOffset = SymbolAddress - OpdAddress;
209 SymbolAddress = OpdExtractor->getAddress(&OpdOffset);
210 }
211
212 if (Module->isMachO())
214
215 if (Obj.isELF() && ELFSymbolRef(Symbol).getBinding() != ELF::STB_LOCAL)
216 ELFSymIdx = 0;
217 Symbols.push_back({SymbolAddress, SymbolSize, SymbolName, ELFSymIdx});
219}
220
221
226
229 return CoffObject->getImageBase();
230 return 0;
231}
232
233bool SymbolizableObjectFile::getNameFromSymbolTable(
235 std::string &FileName) const {
238 if (SymbolIterator == Symbols.begin())
239 return false;
240 --SymbolIterator;
241 if (SymbolIterator->Size != 0 &&
242 SymbolIterator->Addr + SymbolIterator->Size <= Address)
243 return false;
244 Name = SymbolIterator->Name.str();
245 Addr = SymbolIterator->Addr;
246 Size = SymbolIterator->Size;
247
248 if (SymbolIterator->ELFLocalSymIdx != 0) {
249
250
251
254 FileSymbols,
255 std::make_pair(SymbolIterator->ELFLocalSymIdx, StringRef()));
256 if (It != FileSymbols.begin())
257 FileName = It[-1].second.str();
258 }
259 return true;
260}
261
262bool SymbolizableObjectFile::shouldOverrideWithSymbolTable(
264
265
266
267
268 return FNKind == FunctionNameKind::LinkageName && UseSymbolTable &&
270}
271
272DILineInfo
275 bool UseSymbolTable) const {
278 getModuleSectionIndexForAddress(ModuleOffset.Address);
280 std::optional DBGLineInfo =
281 DebugInfoContext->getLineInfoForAddress(ModuleOffset, LineInfoSpecifier);
282 if (DBGLineInfo)
283 LineInfo = *DBGLineInfo;
284
285
286 if (shouldOverrideWithSymbolTable(LineInfoSpecifier.FNKind, UseSymbolTable)) {
287 std::string FunctionName, FileName;
289 if (getNameFromSymbolTable(ModuleOffset.Address, FunctionName, Start, Size,
290 FileName)) {
291 LineInfo.FunctionName = FunctionName;
292 LineInfo.StartAddress = Start;
293
294
295 if (!DBGLineInfo && !FileName.empty())
296 LineInfo.FileName = FileName;
297 }
298 }
299 return LineInfo;
300}
301
307 getModuleSectionIndexForAddress(ModuleOffset.Address);
309 ModuleOffset, LineInfoSpecifier);
310
311
312 bool EmptyFrameAdded = false;
314 EmptyFrameAdded = true;
316 }
317
318
319 if (shouldOverrideWithSymbolTable(LineInfoSpecifier.FNKind, UseSymbolTable)) {
320 std::string FunctionName, FileName;
322 if (getNameFromSymbolTable(ModuleOffset.Address, FunctionName, Start, Size,
323 FileName)) {
328
329
330 if (EmptyFrameAdded && !FileName.empty())
332 }
333 }
334
336}
337
341 std::string FileName;
343 FileName);
345
346
347 std::optional DL =
348 DebugInfoContext->getLineInfoForDataAddress(ModuleOffset);
349 if (DL && DL->Line != 0) {
352 }
353 return Res;
354}
355
360 getModuleSectionIndexForAddress(ModuleOffset.Address);
361 return DebugInfoContext->getLocalsForAddress(ModuleOffset);
362}
363
364std::vectorobject::SectionedAddress
366 std::vectorobject::SectionedAddress Result;
367 for (const SymbolDesc &Sym : Symbols) {
368 if (Sym.Name == Symbol) {
370 if (Offset < Sym.Size)
373 Result.push_back(A);
374 }
375 }
376 return Result;
377}
378
379
380uint64_t SymbolizableObjectFile::getModuleSectionIndexForAddress(
382
384 if (!Sec.isText() || Sec.isVirtual())
385 continue;
386
387 if (Address >= Sec.getAddress() &&
388 Address < Sec.getAddress() + Sec.getSize())
389 return Sec.getIndex();
390 }
391
393}
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.
iterator_range< export_directory_iterator > export_directories() const
uint64_t getImageBase() const
This class is the base class for all object file types.
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
Definition SymbolizableObjectFile.cpp:338
DILineInfo symbolizeCode(object::SectionedAddress ModuleOffset, DILineInfoSpecifier LineInfoSpecifier, bool UseSymbolTable) const override
Definition SymbolizableObjectFile.cpp:273
static Expected< std::unique_ptr< SymbolizableObjectFile > > create(const object::ObjectFile *Obj, std::unique_ptr< DIContext > DICtx, bool UntagAddresses)
Definition SymbolizableObjectFile.cpp:30
std::vector< object::SectionedAddress > findSymbol(StringRef Symbol, uint64_t Offset) const override
Definition SymbolizableObjectFile.cpp:365
uint64_t getModulePreferredBase() const override
Definition SymbolizableObjectFile.cpp:227
std::vector< DILocal > symbolizeFrame(object::SectionedAddress ModuleOffset) const override
Definition SymbolizableObjectFile.cpp:356
bool isWin32Module() const override
Definition SymbolizableObjectFile.cpp:222
DIInliningInfo symbolizeInlinedCode(object::SectionedAddress ModuleOffset, DILineInfoSpecifier LineInfoSpecifier, bool UseSymbolTable) const override
Definition SymbolizableObjectFile.cpp:302
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 - 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 - 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