Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/tools/llvm-readobj/ELFDumper.cpp
35231 views
1
//===- ELFDumper.cpp - ELF-specific dumper --------------------------------===//
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
/// \file
10
/// This file implements the ELF-specific dumper for llvm-readobj.
11
///
12
//===----------------------------------------------------------------------===//
13
14
#include "ARMEHABIPrinter.h"
15
#include "DwarfCFIEHPrinter.h"
16
#include "ObjDumper.h"
17
#include "StackMapPrinter.h"
18
#include "llvm-readobj.h"
19
#include "llvm/ADT/ArrayRef.h"
20
#include "llvm/ADT/BitVector.h"
21
#include "llvm/ADT/DenseMap.h"
22
#include "llvm/ADT/DenseSet.h"
23
#include "llvm/ADT/MapVector.h"
24
#include "llvm/ADT/STLExtras.h"
25
#include "llvm/ADT/SmallString.h"
26
#include "llvm/ADT/SmallVector.h"
27
#include "llvm/ADT/StringExtras.h"
28
#include "llvm/ADT/StringRef.h"
29
#include "llvm/ADT/Twine.h"
30
#include "llvm/BinaryFormat/AMDGPUMetadataVerifier.h"
31
#include "llvm/BinaryFormat/ELF.h"
32
#include "llvm/BinaryFormat/MsgPackDocument.h"
33
#include "llvm/Demangle/Demangle.h"
34
#include "llvm/Object/Archive.h"
35
#include "llvm/Object/ELF.h"
36
#include "llvm/Object/ELFObjectFile.h"
37
#include "llvm/Object/ELFTypes.h"
38
#include "llvm/Object/Error.h"
39
#include "llvm/Object/ObjectFile.h"
40
#include "llvm/Object/RelocationResolver.h"
41
#include "llvm/Object/StackMapParser.h"
42
#include "llvm/Support/AMDGPUMetadata.h"
43
#include "llvm/Support/ARMAttributeParser.h"
44
#include "llvm/Support/ARMBuildAttributes.h"
45
#include "llvm/Support/Casting.h"
46
#include "llvm/Support/Compiler.h"
47
#include "llvm/Support/Endian.h"
48
#include "llvm/Support/ErrorHandling.h"
49
#include "llvm/Support/Format.h"
50
#include "llvm/Support/FormatVariadic.h"
51
#include "llvm/Support/FormattedStream.h"
52
#include "llvm/Support/HexagonAttributeParser.h"
53
#include "llvm/Support/LEB128.h"
54
#include "llvm/Support/MSP430AttributeParser.h"
55
#include "llvm/Support/MSP430Attributes.h"
56
#include "llvm/Support/MathExtras.h"
57
#include "llvm/Support/MipsABIFlags.h"
58
#include "llvm/Support/RISCVAttributeParser.h"
59
#include "llvm/Support/RISCVAttributes.h"
60
#include "llvm/Support/ScopedPrinter.h"
61
#include "llvm/Support/SystemZ/zOSSupport.h"
62
#include "llvm/Support/raw_ostream.h"
63
#include <algorithm>
64
#include <array>
65
#include <cinttypes>
66
#include <cstddef>
67
#include <cstdint>
68
#include <cstdlib>
69
#include <iterator>
70
#include <memory>
71
#include <optional>
72
#include <string>
73
#include <system_error>
74
#include <vector>
75
76
using namespace llvm;
77
using namespace llvm::object;
78
using namespace llvm::support;
79
using namespace ELF;
80
81
#define LLVM_READOBJ_ENUM_CASE(ns, enum) \
82
case ns::enum: \
83
return #enum;
84
85
#define ENUM_ENT(enum, altName) \
86
{ #enum, altName, ELF::enum }
87
88
#define ENUM_ENT_1(enum) \
89
{ #enum, #enum, ELF::enum }
90
91
namespace {
92
93
template <class ELFT> struct RelSymbol {
94
RelSymbol(const typename ELFT::Sym *S, StringRef N)
95
: Sym(S), Name(N.str()) {}
96
const typename ELFT::Sym *Sym;
97
std::string Name;
98
};
99
100
/// Represents a contiguous uniform range in the file. We cannot just create a
101
/// range directly because when creating one of these from the .dynamic table
102
/// the size, entity size and virtual address are different entries in arbitrary
103
/// order (DT_REL, DT_RELSZ, DT_RELENT for example).
104
struct DynRegionInfo {
105
DynRegionInfo(const Binary &Owner, const ObjDumper &D)
106
: Obj(&Owner), Dumper(&D) {}
107
DynRegionInfo(const Binary &Owner, const ObjDumper &D, const uint8_t *A,
108
uint64_t S, uint64_t ES)
109
: Addr(A), Size(S), EntSize(ES), Obj(&Owner), Dumper(&D) {}
110
111
/// Address in current address space.
112
const uint8_t *Addr = nullptr;
113
/// Size in bytes of the region.
114
uint64_t Size = 0;
115
/// Size of each entity in the region.
116
uint64_t EntSize = 0;
117
118
/// Owner object. Used for error reporting.
119
const Binary *Obj;
120
/// Dumper used for error reporting.
121
const ObjDumper *Dumper;
122
/// Error prefix. Used for error reporting to provide more information.
123
std::string Context;
124
/// Region size name. Used for error reporting.
125
StringRef SizePrintName = "size";
126
/// Entry size name. Used for error reporting. If this field is empty, errors
127
/// will not mention the entry size.
128
StringRef EntSizePrintName = "entry size";
129
130
template <typename Type> ArrayRef<Type> getAsArrayRef() const {
131
const Type *Start = reinterpret_cast<const Type *>(Addr);
132
if (!Start)
133
return {Start, Start};
134
135
const uint64_t Offset =
136
Addr - (const uint8_t *)Obj->getMemoryBufferRef().getBufferStart();
137
const uint64_t ObjSize = Obj->getMemoryBufferRef().getBufferSize();
138
139
if (Size > ObjSize - Offset) {
140
Dumper->reportUniqueWarning(
141
"unable to read data at 0x" + Twine::utohexstr(Offset) +
142
" of size 0x" + Twine::utohexstr(Size) + " (" + SizePrintName +
143
"): it goes past the end of the file of size 0x" +
144
Twine::utohexstr(ObjSize));
145
return {Start, Start};
146
}
147
148
if (EntSize == sizeof(Type) && (Size % EntSize == 0))
149
return {Start, Start + (Size / EntSize)};
150
151
std::string Msg;
152
if (!Context.empty())
153
Msg += Context + " has ";
154
155
Msg += ("invalid " + SizePrintName + " (0x" + Twine::utohexstr(Size) + ")")
156
.str();
157
if (!EntSizePrintName.empty())
158
Msg +=
159
(" or " + EntSizePrintName + " (0x" + Twine::utohexstr(EntSize) + ")")
160
.str();
161
162
Dumper->reportUniqueWarning(Msg);
163
return {Start, Start};
164
}
165
};
166
167
struct GroupMember {
168
StringRef Name;
169
uint64_t Index;
170
};
171
172
struct GroupSection {
173
StringRef Name;
174
std::string Signature;
175
uint64_t ShName;
176
uint64_t Index;
177
uint32_t Link;
178
uint32_t Info;
179
uint32_t Type;
180
std::vector<GroupMember> Members;
181
};
182
183
namespace {
184
185
struct NoteType {
186
uint32_t ID;
187
StringRef Name;
188
};
189
190
} // namespace
191
192
template <class ELFT> class Relocation {
193
public:
194
Relocation(const typename ELFT::Rel &R, bool IsMips64EL)
195
: Type(R.getType(IsMips64EL)), Symbol(R.getSymbol(IsMips64EL)),
196
Offset(R.r_offset), Info(R.r_info) {}
197
198
Relocation(const typename ELFT::Rela &R, bool IsMips64EL)
199
: Relocation((const typename ELFT::Rel &)R, IsMips64EL) {
200
Addend = R.r_addend;
201
}
202
203
uint32_t Type;
204
uint32_t Symbol;
205
typename ELFT::uint Offset;
206
typename ELFT::uint Info;
207
std::optional<int64_t> Addend;
208
};
209
210
template <class ELFT> class MipsGOTParser;
211
212
template <typename ELFT> class ELFDumper : public ObjDumper {
213
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
214
215
public:
216
ELFDumper(const object::ELFObjectFile<ELFT> &ObjF, ScopedPrinter &Writer);
217
218
void printUnwindInfo() override;
219
void printNeededLibraries() override;
220
void printHashTable() override;
221
void printGnuHashTable() override;
222
void printLoadName() override;
223
void printVersionInfo() override;
224
void printArchSpecificInfo() override;
225
void printStackMap() const override;
226
void printMemtag() override;
227
ArrayRef<uint8_t> getMemtagGlobalsSectionContents(uint64_t ExpectedAddr);
228
229
// Hash histogram shows statistics of how efficient the hash was for the
230
// dynamic symbol table. The table shows the number of hash buckets for
231
// different lengths of chains as an absolute number and percentage of the
232
// total buckets, and the cumulative coverage of symbols for each set of
233
// buckets.
234
void printHashHistograms() override;
235
236
const object::ELFObjectFile<ELFT> &getElfObject() const { return ObjF; };
237
238
std::string describe(const Elf_Shdr &Sec) const;
239
240
unsigned getHashTableEntSize() const {
241
// EM_S390 and ELF::EM_ALPHA platforms use 8-bytes entries in SHT_HASH
242
// sections. This violates the ELF specification.
243
if (Obj.getHeader().e_machine == ELF::EM_S390 ||
244
Obj.getHeader().e_machine == ELF::EM_ALPHA)
245
return 8;
246
return 4;
247
}
248
249
std::vector<EnumEntry<unsigned>>
250
getOtherFlagsFromSymbol(const Elf_Ehdr &Header, const Elf_Sym &Symbol) const;
251
252
Elf_Dyn_Range dynamic_table() const {
253
// A valid .dynamic section contains an array of entries terminated
254
// with a DT_NULL entry. However, sometimes the section content may
255
// continue past the DT_NULL entry, so to dump the section correctly,
256
// we first find the end of the entries by iterating over them.
257
Elf_Dyn_Range Table = DynamicTable.template getAsArrayRef<Elf_Dyn>();
258
259
size_t Size = 0;
260
while (Size < Table.size())
261
if (Table[Size++].getTag() == DT_NULL)
262
break;
263
264
return Table.slice(0, Size);
265
}
266
267
Elf_Sym_Range dynamic_symbols() const {
268
if (!DynSymRegion)
269
return Elf_Sym_Range();
270
return DynSymRegion->template getAsArrayRef<Elf_Sym>();
271
}
272
273
const Elf_Shdr *findSectionByName(StringRef Name) const;
274
275
StringRef getDynamicStringTable() const { return DynamicStringTable; }
276
277
protected:
278
virtual void printVersionSymbolSection(const Elf_Shdr *Sec) = 0;
279
virtual void printVersionDefinitionSection(const Elf_Shdr *Sec) = 0;
280
virtual void printVersionDependencySection(const Elf_Shdr *Sec) = 0;
281
282
void
283
printDependentLibsHelper(function_ref<void(const Elf_Shdr &)> OnSectionStart,
284
function_ref<void(StringRef, uint64_t)> OnLibEntry);
285
286
virtual void printRelRelaReloc(const Relocation<ELFT> &R,
287
const RelSymbol<ELFT> &RelSym) = 0;
288
virtual void printDynamicRelocHeader(unsigned Type, StringRef Name,
289
const DynRegionInfo &Reg) {}
290
void printReloc(const Relocation<ELFT> &R, unsigned RelIndex,
291
const Elf_Shdr &Sec, const Elf_Shdr *SymTab);
292
void printDynamicReloc(const Relocation<ELFT> &R);
293
void printDynamicRelocationsHelper();
294
void printRelocationsHelper(const Elf_Shdr &Sec);
295
void forEachRelocationDo(
296
const Elf_Shdr &Sec,
297
llvm::function_ref<void(const Relocation<ELFT> &, unsigned,
298
const Elf_Shdr &, const Elf_Shdr *)>
299
RelRelaFn);
300
301
virtual void printSymtabMessage(const Elf_Shdr *Symtab, size_t Offset,
302
bool NonVisibilityBitsUsed,
303
bool ExtraSymInfo) const {};
304
virtual void printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,
305
DataRegion<Elf_Word> ShndxTable,
306
std::optional<StringRef> StrTable, bool IsDynamic,
307
bool NonVisibilityBitsUsed,
308
bool ExtraSymInfo) const = 0;
309
310
virtual void printMipsABIFlags() = 0;
311
virtual void printMipsGOT(const MipsGOTParser<ELFT> &Parser) = 0;
312
virtual void printMipsPLT(const MipsGOTParser<ELFT> &Parser) = 0;
313
314
virtual void printMemtag(
315
const ArrayRef<std::pair<std::string, std::string>> DynamicEntries,
316
const ArrayRef<uint8_t> AndroidNoteDesc,
317
const ArrayRef<std::pair<uint64_t, uint64_t>> Descriptors) = 0;
318
319
virtual void printHashHistogram(const Elf_Hash &HashTable) const;
320
virtual void printGnuHashHistogram(const Elf_GnuHash &GnuHashTable) const;
321
virtual void printHashHistogramStats(size_t NBucket, size_t MaxChain,
322
size_t TotalSyms, ArrayRef<size_t> Count,
323
bool IsGnu) const = 0;
324
325
Expected<ArrayRef<Elf_Versym>>
326
getVersionTable(const Elf_Shdr &Sec, ArrayRef<Elf_Sym> *SymTab,
327
StringRef *StrTab, const Elf_Shdr **SymTabSec) const;
328
StringRef getPrintableSectionName(const Elf_Shdr &Sec) const;
329
330
std::vector<GroupSection> getGroups();
331
332
// Returns the function symbol index for the given address. Matches the
333
// symbol's section with FunctionSec when specified.
334
// Returns std::nullopt if no function symbol can be found for the address or
335
// in case it is not defined in the specified section.
336
SmallVector<uint32_t> getSymbolIndexesForFunctionAddress(
337
uint64_t SymValue, std::optional<const Elf_Shdr *> FunctionSec);
338
bool printFunctionStackSize(uint64_t SymValue,
339
std::optional<const Elf_Shdr *> FunctionSec,
340
const Elf_Shdr &StackSizeSec, DataExtractor Data,
341
uint64_t *Offset);
342
void printStackSize(const Relocation<ELFT> &R, const Elf_Shdr &RelocSec,
343
unsigned Ndx, const Elf_Shdr *SymTab,
344
const Elf_Shdr *FunctionSec, const Elf_Shdr &StackSizeSec,
345
const RelocationResolver &Resolver, DataExtractor Data);
346
virtual void printStackSizeEntry(uint64_t Size,
347
ArrayRef<std::string> FuncNames) = 0;
348
349
void printRelocatableStackSizes(std::function<void()> PrintHeader);
350
void printNonRelocatableStackSizes(std::function<void()> PrintHeader);
351
352
const object::ELFObjectFile<ELFT> &ObjF;
353
const ELFFile<ELFT> &Obj;
354
StringRef FileName;
355
356
Expected<DynRegionInfo> createDRI(uint64_t Offset, uint64_t Size,
357
uint64_t EntSize) {
358
if (Offset + Size < Offset || Offset + Size > Obj.getBufSize())
359
return createError("offset (0x" + Twine::utohexstr(Offset) +
360
") + size (0x" + Twine::utohexstr(Size) +
361
") is greater than the file size (0x" +
362
Twine::utohexstr(Obj.getBufSize()) + ")");
363
return DynRegionInfo(ObjF, *this, Obj.base() + Offset, Size, EntSize);
364
}
365
366
void printAttributes(unsigned, std::unique_ptr<ELFAttributeParser>,
367
llvm::endianness);
368
void printMipsReginfo();
369
void printMipsOptions();
370
371
std::pair<const Elf_Phdr *, const Elf_Shdr *> findDynamic();
372
void loadDynamicTable();
373
void parseDynamicTable();
374
375
Expected<StringRef> getSymbolVersion(const Elf_Sym &Sym,
376
bool &IsDefault) const;
377
Expected<SmallVector<std::optional<VersionEntry>, 0> *> getVersionMap() const;
378
379
DynRegionInfo DynRelRegion;
380
DynRegionInfo DynRelaRegion;
381
DynRegionInfo DynCrelRegion;
382
DynRegionInfo DynRelrRegion;
383
DynRegionInfo DynPLTRelRegion;
384
std::optional<DynRegionInfo> DynSymRegion;
385
DynRegionInfo DynSymTabShndxRegion;
386
DynRegionInfo DynamicTable;
387
StringRef DynamicStringTable;
388
const Elf_Hash *HashTable = nullptr;
389
const Elf_GnuHash *GnuHashTable = nullptr;
390
const Elf_Shdr *DotSymtabSec = nullptr;
391
const Elf_Shdr *DotDynsymSec = nullptr;
392
const Elf_Shdr *DotAddrsigSec = nullptr;
393
DenseMap<const Elf_Shdr *, ArrayRef<Elf_Word>> ShndxTables;
394
std::optional<uint64_t> SONameOffset;
395
std::optional<DenseMap<uint64_t, std::vector<uint32_t>>> AddressToIndexMap;
396
397
const Elf_Shdr *SymbolVersionSection = nullptr; // .gnu.version
398
const Elf_Shdr *SymbolVersionNeedSection = nullptr; // .gnu.version_r
399
const Elf_Shdr *SymbolVersionDefSection = nullptr; // .gnu.version_d
400
401
std::string getFullSymbolName(const Elf_Sym &Symbol, unsigned SymIndex,
402
DataRegion<Elf_Word> ShndxTable,
403
std::optional<StringRef> StrTable,
404
bool IsDynamic) const;
405
Expected<unsigned>
406
getSymbolSectionIndex(const Elf_Sym &Symbol, unsigned SymIndex,
407
DataRegion<Elf_Word> ShndxTable) const;
408
Expected<StringRef> getSymbolSectionName(const Elf_Sym &Symbol,
409
unsigned SectionIndex) const;
410
std::string getStaticSymbolName(uint32_t Index) const;
411
StringRef getDynamicString(uint64_t Value) const;
412
413
std::pair<Elf_Sym_Range, std::optional<StringRef>> getSymtabAndStrtab() const;
414
void printSymbolsHelper(bool IsDynamic, bool ExtraSymInfo) const;
415
std::string getDynamicEntry(uint64_t Type, uint64_t Value) const;
416
417
Expected<RelSymbol<ELFT>> getRelocationTarget(const Relocation<ELFT> &R,
418
const Elf_Shdr *SymTab) const;
419
420
ArrayRef<Elf_Word> getShndxTable(const Elf_Shdr *Symtab) const;
421
422
private:
423
mutable SmallVector<std::optional<VersionEntry>, 0> VersionMap;
424
};
425
426
template <class ELFT>
427
std::string ELFDumper<ELFT>::describe(const Elf_Shdr &Sec) const {
428
return ::describe(Obj, Sec);
429
}
430
431
namespace {
432
433
template <class ELFT> struct SymtabLink {
434
typename ELFT::SymRange Symbols;
435
StringRef StringTable;
436
const typename ELFT::Shdr *SymTab;
437
};
438
439
// Returns the linked symbol table, symbols and associated string table for a
440
// given section.
441
template <class ELFT>
442
Expected<SymtabLink<ELFT>> getLinkAsSymtab(const ELFFile<ELFT> &Obj,
443
const typename ELFT::Shdr &Sec,
444
unsigned ExpectedType) {
445
Expected<const typename ELFT::Shdr *> SymtabOrErr =
446
Obj.getSection(Sec.sh_link);
447
if (!SymtabOrErr)
448
return createError("invalid section linked to " + describe(Obj, Sec) +
449
": " + toString(SymtabOrErr.takeError()));
450
451
if ((*SymtabOrErr)->sh_type != ExpectedType)
452
return createError(
453
"invalid section linked to " + describe(Obj, Sec) + ": expected " +
454
object::getELFSectionTypeName(Obj.getHeader().e_machine, ExpectedType) +
455
", but got " +
456
object::getELFSectionTypeName(Obj.getHeader().e_machine,
457
(*SymtabOrErr)->sh_type));
458
459
Expected<StringRef> StrTabOrErr = Obj.getLinkAsStrtab(**SymtabOrErr);
460
if (!StrTabOrErr)
461
return createError(
462
"can't get a string table for the symbol table linked to " +
463
describe(Obj, Sec) + ": " + toString(StrTabOrErr.takeError()));
464
465
Expected<typename ELFT::SymRange> SymsOrErr = Obj.symbols(*SymtabOrErr);
466
if (!SymsOrErr)
467
return createError("unable to read symbols from the " + describe(Obj, Sec) +
468
": " + toString(SymsOrErr.takeError()));
469
470
return SymtabLink<ELFT>{*SymsOrErr, *StrTabOrErr, *SymtabOrErr};
471
}
472
473
} // namespace
474
475
template <class ELFT>
476
Expected<ArrayRef<typename ELFT::Versym>>
477
ELFDumper<ELFT>::getVersionTable(const Elf_Shdr &Sec, ArrayRef<Elf_Sym> *SymTab,
478
StringRef *StrTab,
479
const Elf_Shdr **SymTabSec) const {
480
assert((!SymTab && !StrTab && !SymTabSec) || (SymTab && StrTab && SymTabSec));
481
if (reinterpret_cast<uintptr_t>(Obj.base() + Sec.sh_offset) %
482
sizeof(uint16_t) !=
483
0)
484
return createError("the " + describe(Sec) + " is misaligned");
485
486
Expected<ArrayRef<Elf_Versym>> VersionsOrErr =
487
Obj.template getSectionContentsAsArray<Elf_Versym>(Sec);
488
if (!VersionsOrErr)
489
return createError("cannot read content of " + describe(Sec) + ": " +
490
toString(VersionsOrErr.takeError()));
491
492
Expected<SymtabLink<ELFT>> SymTabOrErr =
493
getLinkAsSymtab(Obj, Sec, SHT_DYNSYM);
494
if (!SymTabOrErr) {
495
reportUniqueWarning(SymTabOrErr.takeError());
496
return *VersionsOrErr;
497
}
498
499
if (SymTabOrErr->Symbols.size() != VersionsOrErr->size())
500
reportUniqueWarning(describe(Sec) + ": the number of entries (" +
501
Twine(VersionsOrErr->size()) +
502
") does not match the number of symbols (" +
503
Twine(SymTabOrErr->Symbols.size()) +
504
") in the symbol table with index " +
505
Twine(Sec.sh_link));
506
507
if (SymTab) {
508
*SymTab = SymTabOrErr->Symbols;
509
*StrTab = SymTabOrErr->StringTable;
510
*SymTabSec = SymTabOrErr->SymTab;
511
}
512
return *VersionsOrErr;
513
}
514
515
template <class ELFT>
516
std::pair<typename ELFDumper<ELFT>::Elf_Sym_Range, std::optional<StringRef>>
517
ELFDumper<ELFT>::getSymtabAndStrtab() const {
518
assert(DotSymtabSec);
519
Elf_Sym_Range Syms(nullptr, nullptr);
520
std::optional<StringRef> StrTable;
521
if (Expected<StringRef> StrTableOrErr =
522
Obj.getStringTableForSymtab(*DotSymtabSec))
523
StrTable = *StrTableOrErr;
524
else
525
reportUniqueWarning(
526
"unable to get the string table for the SHT_SYMTAB section: " +
527
toString(StrTableOrErr.takeError()));
528
529
if (Expected<Elf_Sym_Range> SymsOrErr = Obj.symbols(DotSymtabSec))
530
Syms = *SymsOrErr;
531
else
532
reportUniqueWarning("unable to read symbols from the SHT_SYMTAB section: " +
533
toString(SymsOrErr.takeError()));
534
return {Syms, StrTable};
535
}
536
537
template <class ELFT>
538
void ELFDumper<ELFT>::printSymbolsHelper(bool IsDynamic,
539
bool ExtraSymInfo) const {
540
std::optional<StringRef> StrTable;
541
size_t Entries = 0;
542
Elf_Sym_Range Syms(nullptr, nullptr);
543
const Elf_Shdr *SymtabSec = IsDynamic ? DotDynsymSec : DotSymtabSec;
544
545
if (IsDynamic) {
546
StrTable = DynamicStringTable;
547
Syms = dynamic_symbols();
548
Entries = Syms.size();
549
} else if (DotSymtabSec) {
550
std::tie(Syms, StrTable) = getSymtabAndStrtab();
551
Entries = DotSymtabSec->getEntityCount();
552
}
553
if (Syms.empty())
554
return;
555
556
// The st_other field has 2 logical parts. The first two bits hold the symbol
557
// visibility (STV_*) and the remainder hold other platform-specific values.
558
bool NonVisibilityBitsUsed =
559
llvm::any_of(Syms, [](const Elf_Sym &S) { return S.st_other & ~0x3; });
560
561
DataRegion<Elf_Word> ShndxTable =
562
IsDynamic ? DataRegion<Elf_Word>(
563
(const Elf_Word *)this->DynSymTabShndxRegion.Addr,
564
this->getElfObject().getELFFile().end())
565
: DataRegion<Elf_Word>(this->getShndxTable(SymtabSec));
566
567
printSymtabMessage(SymtabSec, Entries, NonVisibilityBitsUsed, ExtraSymInfo);
568
for (const Elf_Sym &Sym : Syms)
569
printSymbol(Sym, &Sym - Syms.begin(), ShndxTable, StrTable, IsDynamic,
570
NonVisibilityBitsUsed, ExtraSymInfo);
571
}
572
573
template <typename ELFT> class GNUELFDumper : public ELFDumper<ELFT> {
574
formatted_raw_ostream &OS;
575
576
public:
577
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
578
579
GNUELFDumper(const object::ELFObjectFile<ELFT> &ObjF, ScopedPrinter &Writer)
580
: ELFDumper<ELFT>(ObjF, Writer),
581
OS(static_cast<formatted_raw_ostream &>(Writer.getOStream())) {
582
assert(&this->W.getOStream() == &llvm::fouts());
583
}
584
585
void printFileSummary(StringRef FileStr, ObjectFile &Obj,
586
ArrayRef<std::string> InputFilenames,
587
const Archive *A) override;
588
void printFileHeaders() override;
589
void printGroupSections() override;
590
void printRelocations() override;
591
void printSectionHeaders() override;
592
void printSymbols(bool PrintSymbols, bool PrintDynamicSymbols,
593
bool ExtraSymInfo) override;
594
void printHashSymbols() override;
595
void printSectionDetails() override;
596
void printDependentLibs() override;
597
void printDynamicTable() override;
598
void printDynamicRelocations() override;
599
void printSymtabMessage(const Elf_Shdr *Symtab, size_t Offset,
600
bool NonVisibilityBitsUsed,
601
bool ExtraSymInfo) const override;
602
void printProgramHeaders(bool PrintProgramHeaders,
603
cl::boolOrDefault PrintSectionMapping) override;
604
void printVersionSymbolSection(const Elf_Shdr *Sec) override;
605
void printVersionDefinitionSection(const Elf_Shdr *Sec) override;
606
void printVersionDependencySection(const Elf_Shdr *Sec) override;
607
void printCGProfile() override;
608
void printBBAddrMaps(bool PrettyPGOAnalysis) override;
609
void printAddrsig() override;
610
void printNotes() override;
611
void printELFLinkerOptions() override;
612
void printStackSizes() override;
613
void printMemtag(
614
const ArrayRef<std::pair<std::string, std::string>> DynamicEntries,
615
const ArrayRef<uint8_t> AndroidNoteDesc,
616
const ArrayRef<std::pair<uint64_t, uint64_t>> Descriptors) override;
617
void printHashHistogramStats(size_t NBucket, size_t MaxChain,
618
size_t TotalSyms, ArrayRef<size_t> Count,
619
bool IsGnu) const override;
620
621
private:
622
void printHashTableSymbols(const Elf_Hash &HashTable);
623
void printGnuHashTableSymbols(const Elf_GnuHash &GnuHashTable);
624
625
struct Field {
626
std::string Str;
627
unsigned Column;
628
629
Field(StringRef S, unsigned Col) : Str(std::string(S)), Column(Col) {}
630
Field(unsigned Col) : Column(Col) {}
631
};
632
633
template <typename T, typename TEnum>
634
std::string printFlags(T Value, ArrayRef<EnumEntry<TEnum>> EnumValues,
635
TEnum EnumMask1 = {}, TEnum EnumMask2 = {},
636
TEnum EnumMask3 = {}) const {
637
std::string Str;
638
for (const EnumEntry<TEnum> &Flag : EnumValues) {
639
if (Flag.Value == 0)
640
continue;
641
642
TEnum EnumMask{};
643
if (Flag.Value & EnumMask1)
644
EnumMask = EnumMask1;
645
else if (Flag.Value & EnumMask2)
646
EnumMask = EnumMask2;
647
else if (Flag.Value & EnumMask3)
648
EnumMask = EnumMask3;
649
bool IsEnum = (Flag.Value & EnumMask) != 0;
650
if ((!IsEnum && (Value & Flag.Value) == Flag.Value) ||
651
(IsEnum && (Value & EnumMask) == Flag.Value)) {
652
if (!Str.empty())
653
Str += ", ";
654
Str += Flag.AltName;
655
}
656
}
657
return Str;
658
}
659
660
formatted_raw_ostream &printField(struct Field F) const {
661
if (F.Column != 0)
662
OS.PadToColumn(F.Column);
663
OS << F.Str;
664
OS.flush();
665
return OS;
666
}
667
void printHashedSymbol(const Elf_Sym *Sym, unsigned SymIndex,
668
DataRegion<Elf_Word> ShndxTable, StringRef StrTable,
669
uint32_t Bucket);
670
void printRelr(const Elf_Shdr &Sec);
671
void printRelRelaReloc(const Relocation<ELFT> &R,
672
const RelSymbol<ELFT> &RelSym) override;
673
void printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,
674
DataRegion<Elf_Word> ShndxTable,
675
std::optional<StringRef> StrTable, bool IsDynamic,
676
bool NonVisibilityBitsUsed,
677
bool ExtraSymInfo) const override;
678
void printDynamicRelocHeader(unsigned Type, StringRef Name,
679
const DynRegionInfo &Reg) override;
680
681
std::string getSymbolSectionNdx(const Elf_Sym &Symbol, unsigned SymIndex,
682
DataRegion<Elf_Word> ShndxTable,
683
bool ExtraSymInfo = false) const;
684
void printProgramHeaders() override;
685
void printSectionMapping() override;
686
void printGNUVersionSectionProlog(const typename ELFT::Shdr &Sec,
687
const Twine &Label, unsigned EntriesNum);
688
689
void printStackSizeEntry(uint64_t Size,
690
ArrayRef<std::string> FuncNames) override;
691
692
void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override;
693
void printMipsPLT(const MipsGOTParser<ELFT> &Parser) override;
694
void printMipsABIFlags() override;
695
};
696
697
template <typename ELFT> class LLVMELFDumper : public ELFDumper<ELFT> {
698
public:
699
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
700
701
LLVMELFDumper(const object::ELFObjectFile<ELFT> &ObjF, ScopedPrinter &Writer)
702
: ELFDumper<ELFT>(ObjF, Writer), W(Writer) {}
703
704
void printFileHeaders() override;
705
void printGroupSections() override;
706
void printRelocations() override;
707
void printSectionHeaders() override;
708
void printSymbols(bool PrintSymbols, bool PrintDynamicSymbols,
709
bool ExtraSymInfo) override;
710
void printDependentLibs() override;
711
void printDynamicTable() override;
712
void printDynamicRelocations() override;
713
void printProgramHeaders(bool PrintProgramHeaders,
714
cl::boolOrDefault PrintSectionMapping) override;
715
void printVersionSymbolSection(const Elf_Shdr *Sec) override;
716
void printVersionDefinitionSection(const Elf_Shdr *Sec) override;
717
void printVersionDependencySection(const Elf_Shdr *Sec) override;
718
void printCGProfile() override;
719
void printBBAddrMaps(bool PrettyPGOAnalysis) override;
720
void printAddrsig() override;
721
void printNotes() override;
722
void printELFLinkerOptions() override;
723
void printStackSizes() override;
724
void printMemtag(
725
const ArrayRef<std::pair<std::string, std::string>> DynamicEntries,
726
const ArrayRef<uint8_t> AndroidNoteDesc,
727
const ArrayRef<std::pair<uint64_t, uint64_t>> Descriptors) override;
728
void printSymbolSection(const Elf_Sym &Symbol, unsigned SymIndex,
729
DataRegion<Elf_Word> ShndxTable) const;
730
void printHashHistogramStats(size_t NBucket, size_t MaxChain,
731
size_t TotalSyms, ArrayRef<size_t> Count,
732
bool IsGnu) const override;
733
734
private:
735
void printRelRelaReloc(const Relocation<ELFT> &R,
736
const RelSymbol<ELFT> &RelSym) override;
737
738
void printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,
739
DataRegion<Elf_Word> ShndxTable,
740
std::optional<StringRef> StrTable, bool IsDynamic,
741
bool /*NonVisibilityBitsUsed*/,
742
bool /*ExtraSymInfo*/) const override;
743
void printProgramHeaders() override;
744
void printSectionMapping() override {}
745
void printStackSizeEntry(uint64_t Size,
746
ArrayRef<std::string> FuncNames) override;
747
748
void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override;
749
void printMipsPLT(const MipsGOTParser<ELFT> &Parser) override;
750
void printMipsABIFlags() override;
751
virtual void printZeroSymbolOtherField(const Elf_Sym &Symbol) const;
752
753
protected:
754
virtual std::string getGroupSectionHeaderName() const;
755
void printSymbolOtherField(const Elf_Sym &Symbol) const;
756
virtual void printExpandedRelRelaReloc(const Relocation<ELFT> &R,
757
StringRef SymbolName,
758
StringRef RelocName);
759
virtual void printDefaultRelRelaReloc(const Relocation<ELFT> &R,
760
StringRef SymbolName,
761
StringRef RelocName);
762
virtual void printRelocationSectionInfo(const Elf_Shdr &Sec, StringRef Name,
763
const unsigned SecNdx);
764
virtual void printSectionGroupMembers(StringRef Name, uint64_t Idx) const;
765
virtual void printEmptyGroupMessage() const;
766
767
ScopedPrinter &W;
768
};
769
770
// JSONELFDumper shares most of the same implementation as LLVMELFDumper except
771
// it uses a JSONScopedPrinter.
772
template <typename ELFT> class JSONELFDumper : public LLVMELFDumper<ELFT> {
773
public:
774
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
775
776
JSONELFDumper(const object::ELFObjectFile<ELFT> &ObjF, ScopedPrinter &Writer)
777
: LLVMELFDumper<ELFT>(ObjF, Writer) {}
778
779
std::string getGroupSectionHeaderName() const override;
780
781
void printFileSummary(StringRef FileStr, ObjectFile &Obj,
782
ArrayRef<std::string> InputFilenames,
783
const Archive *A) override;
784
virtual void printZeroSymbolOtherField(const Elf_Sym &Symbol) const override;
785
786
void printDefaultRelRelaReloc(const Relocation<ELFT> &R,
787
StringRef SymbolName,
788
StringRef RelocName) override;
789
790
void printRelocationSectionInfo(const Elf_Shdr &Sec, StringRef Name,
791
const unsigned SecNdx) override;
792
793
void printSectionGroupMembers(StringRef Name, uint64_t Idx) const override;
794
795
void printEmptyGroupMessage() const override;
796
797
void printDynamicTable() override;
798
799
private:
800
void printAuxillaryDynamicTableEntryInfo(const Elf_Dyn &Entry);
801
802
std::unique_ptr<DictScope> FileScope;
803
};
804
805
} // end anonymous namespace
806
807
namespace llvm {
808
809
template <class ELFT>
810
static std::unique_ptr<ObjDumper>
811
createELFDumper(const ELFObjectFile<ELFT> &Obj, ScopedPrinter &Writer) {
812
if (opts::Output == opts::GNU)
813
return std::make_unique<GNUELFDumper<ELFT>>(Obj, Writer);
814
else if (opts::Output == opts::JSON)
815
return std::make_unique<JSONELFDumper<ELFT>>(Obj, Writer);
816
return std::make_unique<LLVMELFDumper<ELFT>>(Obj, Writer);
817
}
818
819
std::unique_ptr<ObjDumper> createELFDumper(const object::ELFObjectFileBase &Obj,
820
ScopedPrinter &Writer) {
821
// Little-endian 32-bit
822
if (const ELF32LEObjectFile *ELFObj = dyn_cast<ELF32LEObjectFile>(&Obj))
823
return createELFDumper(*ELFObj, Writer);
824
825
// Big-endian 32-bit
826
if (const ELF32BEObjectFile *ELFObj = dyn_cast<ELF32BEObjectFile>(&Obj))
827
return createELFDumper(*ELFObj, Writer);
828
829
// Little-endian 64-bit
830
if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(&Obj))
831
return createELFDumper(*ELFObj, Writer);
832
833
// Big-endian 64-bit
834
return createELFDumper(*cast<ELF64BEObjectFile>(&Obj), Writer);
835
}
836
837
} // end namespace llvm
838
839
template <class ELFT>
840
Expected<SmallVector<std::optional<VersionEntry>, 0> *>
841
ELFDumper<ELFT>::getVersionMap() const {
842
// If the VersionMap has already been loaded or if there is no dynamic symtab
843
// or version table, there is nothing to do.
844
if (!VersionMap.empty() || !DynSymRegion || !SymbolVersionSection)
845
return &VersionMap;
846
847
Expected<SmallVector<std::optional<VersionEntry>, 0>> MapOrErr =
848
Obj.loadVersionMap(SymbolVersionNeedSection, SymbolVersionDefSection);
849
if (MapOrErr)
850
VersionMap = *MapOrErr;
851
else
852
return MapOrErr.takeError();
853
854
return &VersionMap;
855
}
856
857
template <typename ELFT>
858
Expected<StringRef> ELFDumper<ELFT>::getSymbolVersion(const Elf_Sym &Sym,
859
bool &IsDefault) const {
860
// This is a dynamic symbol. Look in the GNU symbol version table.
861
if (!SymbolVersionSection) {
862
// No version table.
863
IsDefault = false;
864
return "";
865
}
866
867
assert(DynSymRegion && "DynSymRegion has not been initialised");
868
// Determine the position in the symbol table of this entry.
869
size_t EntryIndex = (reinterpret_cast<uintptr_t>(&Sym) -
870
reinterpret_cast<uintptr_t>(DynSymRegion->Addr)) /
871
sizeof(Elf_Sym);
872
873
// Get the corresponding version index entry.
874
Expected<const Elf_Versym *> EntryOrErr =
875
Obj.template getEntry<Elf_Versym>(*SymbolVersionSection, EntryIndex);
876
if (!EntryOrErr)
877
return EntryOrErr.takeError();
878
879
unsigned Version = (*EntryOrErr)->vs_index;
880
if (Version == VER_NDX_LOCAL || Version == VER_NDX_GLOBAL) {
881
IsDefault = false;
882
return "";
883
}
884
885
Expected<SmallVector<std::optional<VersionEntry>, 0> *> MapOrErr =
886
getVersionMap();
887
if (!MapOrErr)
888
return MapOrErr.takeError();
889
890
return Obj.getSymbolVersionByIndex(Version, IsDefault, **MapOrErr,
891
Sym.st_shndx == ELF::SHN_UNDEF);
892
}
893
894
template <typename ELFT>
895
Expected<RelSymbol<ELFT>>
896
ELFDumper<ELFT>::getRelocationTarget(const Relocation<ELFT> &R,
897
const Elf_Shdr *SymTab) const {
898
if (R.Symbol == 0)
899
return RelSymbol<ELFT>(nullptr, "");
900
901
Expected<const Elf_Sym *> SymOrErr =
902
Obj.template getEntry<Elf_Sym>(*SymTab, R.Symbol);
903
if (!SymOrErr)
904
return createError("unable to read an entry with index " + Twine(R.Symbol) +
905
" from " + describe(*SymTab) + ": " +
906
toString(SymOrErr.takeError()));
907
const Elf_Sym *Sym = *SymOrErr;
908
if (!Sym)
909
return RelSymbol<ELFT>(nullptr, "");
910
911
Expected<StringRef> StrTableOrErr = Obj.getStringTableForSymtab(*SymTab);
912
if (!StrTableOrErr)
913
return StrTableOrErr.takeError();
914
915
const Elf_Sym *FirstSym =
916
cantFail(Obj.template getEntry<Elf_Sym>(*SymTab, 0));
917
std::string SymbolName =
918
getFullSymbolName(*Sym, Sym - FirstSym, getShndxTable(SymTab),
919
*StrTableOrErr, SymTab->sh_type == SHT_DYNSYM);
920
return RelSymbol<ELFT>(Sym, SymbolName);
921
}
922
923
template <typename ELFT>
924
ArrayRef<typename ELFT::Word>
925
ELFDumper<ELFT>::getShndxTable(const Elf_Shdr *Symtab) const {
926
if (Symtab) {
927
auto It = ShndxTables.find(Symtab);
928
if (It != ShndxTables.end())
929
return It->second;
930
}
931
return {};
932
}
933
934
static std::string maybeDemangle(StringRef Name) {
935
return opts::Demangle ? demangle(Name) : Name.str();
936
}
937
938
template <typename ELFT>
939
std::string ELFDumper<ELFT>::getStaticSymbolName(uint32_t Index) const {
940
auto Warn = [&](Error E) -> std::string {
941
reportUniqueWarning("unable to read the name of symbol with index " +
942
Twine(Index) + ": " + toString(std::move(E)));
943
return "<?>";
944
};
945
946
Expected<const typename ELFT::Sym *> SymOrErr =
947
Obj.getSymbol(DotSymtabSec, Index);
948
if (!SymOrErr)
949
return Warn(SymOrErr.takeError());
950
951
Expected<StringRef> StrTabOrErr = Obj.getStringTableForSymtab(*DotSymtabSec);
952
if (!StrTabOrErr)
953
return Warn(StrTabOrErr.takeError());
954
955
Expected<StringRef> NameOrErr = (*SymOrErr)->getName(*StrTabOrErr);
956
if (!NameOrErr)
957
return Warn(NameOrErr.takeError());
958
return maybeDemangle(*NameOrErr);
959
}
960
961
template <typename ELFT>
962
std::string ELFDumper<ELFT>::getFullSymbolName(
963
const Elf_Sym &Symbol, unsigned SymIndex, DataRegion<Elf_Word> ShndxTable,
964
std::optional<StringRef> StrTable, bool IsDynamic) const {
965
if (!StrTable)
966
return "<?>";
967
968
std::string SymbolName;
969
if (Expected<StringRef> NameOrErr = Symbol.getName(*StrTable)) {
970
SymbolName = maybeDemangle(*NameOrErr);
971
} else {
972
reportUniqueWarning(NameOrErr.takeError());
973
return "<?>";
974
}
975
976
if (SymbolName.empty() && Symbol.getType() == ELF::STT_SECTION) {
977
Expected<unsigned> SectionIndex =
978
getSymbolSectionIndex(Symbol, SymIndex, ShndxTable);
979
if (!SectionIndex) {
980
reportUniqueWarning(SectionIndex.takeError());
981
return "<?>";
982
}
983
Expected<StringRef> NameOrErr = getSymbolSectionName(Symbol, *SectionIndex);
984
if (!NameOrErr) {
985
reportUniqueWarning(NameOrErr.takeError());
986
return ("<section " + Twine(*SectionIndex) + ">").str();
987
}
988
return std::string(*NameOrErr);
989
}
990
991
if (!IsDynamic)
992
return SymbolName;
993
994
bool IsDefault;
995
Expected<StringRef> VersionOrErr = getSymbolVersion(Symbol, IsDefault);
996
if (!VersionOrErr) {
997
reportUniqueWarning(VersionOrErr.takeError());
998
return SymbolName + "@<corrupt>";
999
}
1000
1001
if (!VersionOrErr->empty()) {
1002
SymbolName += (IsDefault ? "@@" : "@");
1003
SymbolName += *VersionOrErr;
1004
}
1005
return SymbolName;
1006
}
1007
1008
template <typename ELFT>
1009
Expected<unsigned>
1010
ELFDumper<ELFT>::getSymbolSectionIndex(const Elf_Sym &Symbol, unsigned SymIndex,
1011
DataRegion<Elf_Word> ShndxTable) const {
1012
unsigned Ndx = Symbol.st_shndx;
1013
if (Ndx == SHN_XINDEX)
1014
return object::getExtendedSymbolTableIndex<ELFT>(Symbol, SymIndex,
1015
ShndxTable);
1016
if (Ndx != SHN_UNDEF && Ndx < SHN_LORESERVE)
1017
return Ndx;
1018
1019
auto CreateErr = [&](const Twine &Name,
1020
std::optional<unsigned> Offset = std::nullopt) {
1021
std::string Desc;
1022
if (Offset)
1023
Desc = (Name + "+0x" + Twine::utohexstr(*Offset)).str();
1024
else
1025
Desc = Name.str();
1026
return createError(
1027
"unable to get section index for symbol with st_shndx = 0x" +
1028
Twine::utohexstr(Ndx) + " (" + Desc + ")");
1029
};
1030
1031
if (Ndx >= ELF::SHN_LOPROC && Ndx <= ELF::SHN_HIPROC)
1032
return CreateErr("SHN_LOPROC", Ndx - ELF::SHN_LOPROC);
1033
if (Ndx >= ELF::SHN_LOOS && Ndx <= ELF::SHN_HIOS)
1034
return CreateErr("SHN_LOOS", Ndx - ELF::SHN_LOOS);
1035
if (Ndx == ELF::SHN_UNDEF)
1036
return CreateErr("SHN_UNDEF");
1037
if (Ndx == ELF::SHN_ABS)
1038
return CreateErr("SHN_ABS");
1039
if (Ndx == ELF::SHN_COMMON)
1040
return CreateErr("SHN_COMMON");
1041
return CreateErr("SHN_LORESERVE", Ndx - SHN_LORESERVE);
1042
}
1043
1044
template <typename ELFT>
1045
Expected<StringRef>
1046
ELFDumper<ELFT>::getSymbolSectionName(const Elf_Sym &Symbol,
1047
unsigned SectionIndex) const {
1048
Expected<const Elf_Shdr *> SecOrErr = Obj.getSection(SectionIndex);
1049
if (!SecOrErr)
1050
return SecOrErr.takeError();
1051
return Obj.getSectionName(**SecOrErr);
1052
}
1053
1054
template <class ELFO>
1055
static const typename ELFO::Elf_Shdr *
1056
findNotEmptySectionByAddress(const ELFO &Obj, StringRef FileName,
1057
uint64_t Addr) {
1058
for (const typename ELFO::Elf_Shdr &Shdr : cantFail(Obj.sections()))
1059
if (Shdr.sh_addr == Addr && Shdr.sh_size > 0)
1060
return &Shdr;
1061
return nullptr;
1062
}
1063
1064
const EnumEntry<unsigned> ElfClass[] = {
1065
{"None", "none", ELF::ELFCLASSNONE},
1066
{"32-bit", "ELF32", ELF::ELFCLASS32},
1067
{"64-bit", "ELF64", ELF::ELFCLASS64},
1068
};
1069
1070
const EnumEntry<unsigned> ElfDataEncoding[] = {
1071
{"None", "none", ELF::ELFDATANONE},
1072
{"LittleEndian", "2's complement, little endian", ELF::ELFDATA2LSB},
1073
{"BigEndian", "2's complement, big endian", ELF::ELFDATA2MSB},
1074
};
1075
1076
const EnumEntry<unsigned> ElfObjectFileType[] = {
1077
{"None", "NONE (none)", ELF::ET_NONE},
1078
{"Relocatable", "REL (Relocatable file)", ELF::ET_REL},
1079
{"Executable", "EXEC (Executable file)", ELF::ET_EXEC},
1080
{"SharedObject", "DYN (Shared object file)", ELF::ET_DYN},
1081
{"Core", "CORE (Core file)", ELF::ET_CORE},
1082
};
1083
1084
const EnumEntry<unsigned> ElfOSABI[] = {
1085
{"SystemV", "UNIX - System V", ELF::ELFOSABI_NONE},
1086
{"HPUX", "UNIX - HP-UX", ELF::ELFOSABI_HPUX},
1087
{"NetBSD", "UNIX - NetBSD", ELF::ELFOSABI_NETBSD},
1088
{"GNU/Linux", "UNIX - GNU", ELF::ELFOSABI_LINUX},
1089
{"GNU/Hurd", "GNU/Hurd", ELF::ELFOSABI_HURD},
1090
{"Solaris", "UNIX - Solaris", ELF::ELFOSABI_SOLARIS},
1091
{"AIX", "UNIX - AIX", ELF::ELFOSABI_AIX},
1092
{"IRIX", "UNIX - IRIX", ELF::ELFOSABI_IRIX},
1093
{"FreeBSD", "UNIX - FreeBSD", ELF::ELFOSABI_FREEBSD},
1094
{"TRU64", "UNIX - TRU64", ELF::ELFOSABI_TRU64},
1095
{"Modesto", "Novell - Modesto", ELF::ELFOSABI_MODESTO},
1096
{"OpenBSD", "UNIX - OpenBSD", ELF::ELFOSABI_OPENBSD},
1097
{"OpenVMS", "VMS - OpenVMS", ELF::ELFOSABI_OPENVMS},
1098
{"NSK", "HP - Non-Stop Kernel", ELF::ELFOSABI_NSK},
1099
{"AROS", "AROS", ELF::ELFOSABI_AROS},
1100
{"FenixOS", "FenixOS", ELF::ELFOSABI_FENIXOS},
1101
{"CloudABI", "CloudABI", ELF::ELFOSABI_CLOUDABI},
1102
{"CUDA", "NVIDIA - CUDA", ELF::ELFOSABI_CUDA},
1103
{"Standalone", "Standalone App", ELF::ELFOSABI_STANDALONE}
1104
};
1105
1106
const EnumEntry<unsigned> AMDGPUElfOSABI[] = {
1107
{"AMDGPU_HSA", "AMDGPU - HSA", ELF::ELFOSABI_AMDGPU_HSA},
1108
{"AMDGPU_PAL", "AMDGPU - PAL", ELF::ELFOSABI_AMDGPU_PAL},
1109
{"AMDGPU_MESA3D", "AMDGPU - MESA3D", ELF::ELFOSABI_AMDGPU_MESA3D}
1110
};
1111
1112
const EnumEntry<unsigned> ARMElfOSABI[] = {
1113
{"ARM", "ARM", ELF::ELFOSABI_ARM},
1114
{"ARM FDPIC", "ARM FDPIC", ELF::ELFOSABI_ARM_FDPIC},
1115
};
1116
1117
const EnumEntry<unsigned> C6000ElfOSABI[] = {
1118
{"C6000_ELFABI", "Bare-metal C6000", ELF::ELFOSABI_C6000_ELFABI},
1119
{"C6000_LINUX", "Linux C6000", ELF::ELFOSABI_C6000_LINUX}
1120
};
1121
1122
const EnumEntry<unsigned> ElfMachineType[] = {
1123
ENUM_ENT(EM_NONE, "None"),
1124
ENUM_ENT(EM_M32, "WE32100"),
1125
ENUM_ENT(EM_SPARC, "Sparc"),
1126
ENUM_ENT(EM_386, "Intel 80386"),
1127
ENUM_ENT(EM_68K, "MC68000"),
1128
ENUM_ENT(EM_88K, "MC88000"),
1129
ENUM_ENT(EM_IAMCU, "EM_IAMCU"),
1130
ENUM_ENT(EM_860, "Intel 80860"),
1131
ENUM_ENT(EM_MIPS, "MIPS R3000"),
1132
ENUM_ENT(EM_S370, "IBM System/370"),
1133
ENUM_ENT(EM_MIPS_RS3_LE, "MIPS R3000 little-endian"),
1134
ENUM_ENT(EM_PARISC, "HPPA"),
1135
ENUM_ENT(EM_VPP500, "Fujitsu VPP500"),
1136
ENUM_ENT(EM_SPARC32PLUS, "Sparc v8+"),
1137
ENUM_ENT(EM_960, "Intel 80960"),
1138
ENUM_ENT(EM_PPC, "PowerPC"),
1139
ENUM_ENT(EM_PPC64, "PowerPC64"),
1140
ENUM_ENT(EM_S390, "IBM S/390"),
1141
ENUM_ENT(EM_SPU, "SPU"),
1142
ENUM_ENT(EM_V800, "NEC V800 series"),
1143
ENUM_ENT(EM_FR20, "Fujistsu FR20"),
1144
ENUM_ENT(EM_RH32, "TRW RH-32"),
1145
ENUM_ENT(EM_RCE, "Motorola RCE"),
1146
ENUM_ENT(EM_ARM, "ARM"),
1147
ENUM_ENT(EM_ALPHA, "EM_ALPHA"),
1148
ENUM_ENT(EM_SH, "Hitachi SH"),
1149
ENUM_ENT(EM_SPARCV9, "Sparc v9"),
1150
ENUM_ENT(EM_TRICORE, "Siemens Tricore"),
1151
ENUM_ENT(EM_ARC, "ARC"),
1152
ENUM_ENT(EM_H8_300, "Hitachi H8/300"),
1153
ENUM_ENT(EM_H8_300H, "Hitachi H8/300H"),
1154
ENUM_ENT(EM_H8S, "Hitachi H8S"),
1155
ENUM_ENT(EM_H8_500, "Hitachi H8/500"),
1156
ENUM_ENT(EM_IA_64, "Intel IA-64"),
1157
ENUM_ENT(EM_MIPS_X, "Stanford MIPS-X"),
1158
ENUM_ENT(EM_COLDFIRE, "Motorola Coldfire"),
1159
ENUM_ENT(EM_68HC12, "Motorola MC68HC12 Microcontroller"),
1160
ENUM_ENT(EM_MMA, "Fujitsu Multimedia Accelerator"),
1161
ENUM_ENT(EM_PCP, "Siemens PCP"),
1162
ENUM_ENT(EM_NCPU, "Sony nCPU embedded RISC processor"),
1163
ENUM_ENT(EM_NDR1, "Denso NDR1 microprocesspr"),
1164
ENUM_ENT(EM_STARCORE, "Motorola Star*Core processor"),
1165
ENUM_ENT(EM_ME16, "Toyota ME16 processor"),
1166
ENUM_ENT(EM_ST100, "STMicroelectronics ST100 processor"),
1167
ENUM_ENT(EM_TINYJ, "Advanced Logic Corp. TinyJ embedded processor"),
1168
ENUM_ENT(EM_X86_64, "Advanced Micro Devices X86-64"),
1169
ENUM_ENT(EM_PDSP, "Sony DSP processor"),
1170
ENUM_ENT(EM_PDP10, "Digital Equipment Corp. PDP-10"),
1171
ENUM_ENT(EM_PDP11, "Digital Equipment Corp. PDP-11"),
1172
ENUM_ENT(EM_FX66, "Siemens FX66 microcontroller"),
1173
ENUM_ENT(EM_ST9PLUS, "STMicroelectronics ST9+ 8/16 bit microcontroller"),
1174
ENUM_ENT(EM_ST7, "STMicroelectronics ST7 8-bit microcontroller"),
1175
ENUM_ENT(EM_68HC16, "Motorola MC68HC16 Microcontroller"),
1176
ENUM_ENT(EM_68HC11, "Motorola MC68HC11 Microcontroller"),
1177
ENUM_ENT(EM_68HC08, "Motorola MC68HC08 Microcontroller"),
1178
ENUM_ENT(EM_68HC05, "Motorola MC68HC05 Microcontroller"),
1179
ENUM_ENT(EM_SVX, "Silicon Graphics SVx"),
1180
ENUM_ENT(EM_ST19, "STMicroelectronics ST19 8-bit microcontroller"),
1181
ENUM_ENT(EM_VAX, "Digital VAX"),
1182
ENUM_ENT(EM_CRIS, "Axis Communications 32-bit embedded processor"),
1183
ENUM_ENT(EM_JAVELIN, "Infineon Technologies 32-bit embedded cpu"),
1184
ENUM_ENT(EM_FIREPATH, "Element 14 64-bit DSP processor"),
1185
ENUM_ENT(EM_ZSP, "LSI Logic's 16-bit DSP processor"),
1186
ENUM_ENT(EM_MMIX, "Donald Knuth's educational 64-bit processor"),
1187
ENUM_ENT(EM_HUANY, "Harvard Universitys's machine-independent object format"),
1188
ENUM_ENT(EM_PRISM, "Vitesse Prism"),
1189
ENUM_ENT(EM_AVR, "Atmel AVR 8-bit microcontroller"),
1190
ENUM_ENT(EM_FR30, "Fujitsu FR30"),
1191
ENUM_ENT(EM_D10V, "Mitsubishi D10V"),
1192
ENUM_ENT(EM_D30V, "Mitsubishi D30V"),
1193
ENUM_ENT(EM_V850, "NEC v850"),
1194
ENUM_ENT(EM_M32R, "Renesas M32R (formerly Mitsubishi M32r)"),
1195
ENUM_ENT(EM_MN10300, "Matsushita MN10300"),
1196
ENUM_ENT(EM_MN10200, "Matsushita MN10200"),
1197
ENUM_ENT(EM_PJ, "picoJava"),
1198
ENUM_ENT(EM_OPENRISC, "OpenRISC 32-bit embedded processor"),
1199
ENUM_ENT(EM_ARC_COMPACT, "EM_ARC_COMPACT"),
1200
ENUM_ENT(EM_XTENSA, "Tensilica Xtensa Processor"),
1201
ENUM_ENT(EM_VIDEOCORE, "Alphamosaic VideoCore processor"),
1202
ENUM_ENT(EM_TMM_GPP, "Thompson Multimedia General Purpose Processor"),
1203
ENUM_ENT(EM_NS32K, "National Semiconductor 32000 series"),
1204
ENUM_ENT(EM_TPC, "Tenor Network TPC processor"),
1205
ENUM_ENT(EM_SNP1K, "EM_SNP1K"),
1206
ENUM_ENT(EM_ST200, "STMicroelectronics ST200 microcontroller"),
1207
ENUM_ENT(EM_IP2K, "Ubicom IP2xxx 8-bit microcontrollers"),
1208
ENUM_ENT(EM_MAX, "MAX Processor"),
1209
ENUM_ENT(EM_CR, "National Semiconductor CompactRISC"),
1210
ENUM_ENT(EM_F2MC16, "Fujitsu F2MC16"),
1211
ENUM_ENT(EM_MSP430, "Texas Instruments msp430 microcontroller"),
1212
ENUM_ENT(EM_BLACKFIN, "Analog Devices Blackfin"),
1213
ENUM_ENT(EM_SE_C33, "S1C33 Family of Seiko Epson processors"),
1214
ENUM_ENT(EM_SEP, "Sharp embedded microprocessor"),
1215
ENUM_ENT(EM_ARCA, "Arca RISC microprocessor"),
1216
ENUM_ENT(EM_UNICORE, "Unicore"),
1217
ENUM_ENT(EM_EXCESS, "eXcess 16/32/64-bit configurable embedded CPU"),
1218
ENUM_ENT(EM_DXP, "Icera Semiconductor Inc. Deep Execution Processor"),
1219
ENUM_ENT(EM_ALTERA_NIOS2, "Altera Nios"),
1220
ENUM_ENT(EM_CRX, "National Semiconductor CRX microprocessor"),
1221
ENUM_ENT(EM_XGATE, "Motorola XGATE embedded processor"),
1222
ENUM_ENT(EM_C166, "Infineon Technologies xc16x"),
1223
ENUM_ENT(EM_M16C, "Renesas M16C"),
1224
ENUM_ENT(EM_DSPIC30F, "Microchip Technology dsPIC30F Digital Signal Controller"),
1225
ENUM_ENT(EM_CE, "Freescale Communication Engine RISC core"),
1226
ENUM_ENT(EM_M32C, "Renesas M32C"),
1227
ENUM_ENT(EM_TSK3000, "Altium TSK3000 core"),
1228
ENUM_ENT(EM_RS08, "Freescale RS08 embedded processor"),
1229
ENUM_ENT(EM_SHARC, "EM_SHARC"),
1230
ENUM_ENT(EM_ECOG2, "Cyan Technology eCOG2 microprocessor"),
1231
ENUM_ENT(EM_SCORE7, "SUNPLUS S+Core"),
1232
ENUM_ENT(EM_DSP24, "New Japan Radio (NJR) 24-bit DSP Processor"),
1233
ENUM_ENT(EM_VIDEOCORE3, "Broadcom VideoCore III processor"),
1234
ENUM_ENT(EM_LATTICEMICO32, "Lattice Mico32"),
1235
ENUM_ENT(EM_SE_C17, "Seiko Epson C17 family"),
1236
ENUM_ENT(EM_TI_C6000, "Texas Instruments TMS320C6000 DSP family"),
1237
ENUM_ENT(EM_TI_C2000, "Texas Instruments TMS320C2000 DSP family"),
1238
ENUM_ENT(EM_TI_C5500, "Texas Instruments TMS320C55x DSP family"),
1239
ENUM_ENT(EM_MMDSP_PLUS, "STMicroelectronics 64bit VLIW Data Signal Processor"),
1240
ENUM_ENT(EM_CYPRESS_M8C, "Cypress M8C microprocessor"),
1241
ENUM_ENT(EM_R32C, "Renesas R32C series microprocessors"),
1242
ENUM_ENT(EM_TRIMEDIA, "NXP Semiconductors TriMedia architecture family"),
1243
ENUM_ENT(EM_HEXAGON, "Qualcomm Hexagon"),
1244
ENUM_ENT(EM_8051, "Intel 8051 and variants"),
1245
ENUM_ENT(EM_STXP7X, "STMicroelectronics STxP7x family"),
1246
ENUM_ENT(EM_NDS32, "Andes Technology compact code size embedded RISC processor family"),
1247
ENUM_ENT(EM_ECOG1, "Cyan Technology eCOG1 microprocessor"),
1248
// FIXME: Following EM_ECOG1X definitions is dead code since EM_ECOG1X has
1249
// an identical number to EM_ECOG1.
1250
ENUM_ENT(EM_ECOG1X, "Cyan Technology eCOG1X family"),
1251
ENUM_ENT(EM_MAXQ30, "Dallas Semiconductor MAXQ30 Core microcontrollers"),
1252
ENUM_ENT(EM_XIMO16, "New Japan Radio (NJR) 16-bit DSP Processor"),
1253
ENUM_ENT(EM_MANIK, "M2000 Reconfigurable RISC Microprocessor"),
1254
ENUM_ENT(EM_CRAYNV2, "Cray Inc. NV2 vector architecture"),
1255
ENUM_ENT(EM_RX, "Renesas RX"),
1256
ENUM_ENT(EM_METAG, "Imagination Technologies Meta processor architecture"),
1257
ENUM_ENT(EM_MCST_ELBRUS, "MCST Elbrus general purpose hardware architecture"),
1258
ENUM_ENT(EM_ECOG16, "Cyan Technology eCOG16 family"),
1259
ENUM_ENT(EM_CR16, "National Semiconductor CompactRISC 16-bit processor"),
1260
ENUM_ENT(EM_ETPU, "Freescale Extended Time Processing Unit"),
1261
ENUM_ENT(EM_SLE9X, "Infineon Technologies SLE9X core"),
1262
ENUM_ENT(EM_L10M, "EM_L10M"),
1263
ENUM_ENT(EM_K10M, "EM_K10M"),
1264
ENUM_ENT(EM_AARCH64, "AArch64"),
1265
ENUM_ENT(EM_AVR32, "Atmel Corporation 32-bit microprocessor family"),
1266
ENUM_ENT(EM_STM8, "STMicroeletronics STM8 8-bit microcontroller"),
1267
ENUM_ENT(EM_TILE64, "Tilera TILE64 multicore architecture family"),
1268
ENUM_ENT(EM_TILEPRO, "Tilera TILEPro multicore architecture family"),
1269
ENUM_ENT(EM_MICROBLAZE, "Xilinx MicroBlaze 32-bit RISC soft processor core"),
1270
ENUM_ENT(EM_CUDA, "NVIDIA CUDA architecture"),
1271
ENUM_ENT(EM_TILEGX, "Tilera TILE-Gx multicore architecture family"),
1272
ENUM_ENT(EM_CLOUDSHIELD, "EM_CLOUDSHIELD"),
1273
ENUM_ENT(EM_COREA_1ST, "EM_COREA_1ST"),
1274
ENUM_ENT(EM_COREA_2ND, "EM_COREA_2ND"),
1275
ENUM_ENT(EM_ARC_COMPACT2, "EM_ARC_COMPACT2"),
1276
ENUM_ENT(EM_OPEN8, "EM_OPEN8"),
1277
ENUM_ENT(EM_RL78, "Renesas RL78"),
1278
ENUM_ENT(EM_VIDEOCORE5, "Broadcom VideoCore V processor"),
1279
ENUM_ENT(EM_78KOR, "EM_78KOR"),
1280
ENUM_ENT(EM_56800EX, "EM_56800EX"),
1281
ENUM_ENT(EM_AMDGPU, "EM_AMDGPU"),
1282
ENUM_ENT(EM_RISCV, "RISC-V"),
1283
ENUM_ENT(EM_LANAI, "EM_LANAI"),
1284
ENUM_ENT(EM_BPF, "EM_BPF"),
1285
ENUM_ENT(EM_VE, "NEC SX-Aurora Vector Engine"),
1286
ENUM_ENT(EM_LOONGARCH, "LoongArch"),
1287
};
1288
1289
const EnumEntry<unsigned> ElfSymbolBindings[] = {
1290
{"Local", "LOCAL", ELF::STB_LOCAL},
1291
{"Global", "GLOBAL", ELF::STB_GLOBAL},
1292
{"Weak", "WEAK", ELF::STB_WEAK},
1293
{"Unique", "UNIQUE", ELF::STB_GNU_UNIQUE}};
1294
1295
const EnumEntry<unsigned> ElfSymbolVisibilities[] = {
1296
{"DEFAULT", "DEFAULT", ELF::STV_DEFAULT},
1297
{"INTERNAL", "INTERNAL", ELF::STV_INTERNAL},
1298
{"HIDDEN", "HIDDEN", ELF::STV_HIDDEN},
1299
{"PROTECTED", "PROTECTED", ELF::STV_PROTECTED}};
1300
1301
const EnumEntry<unsigned> AMDGPUSymbolTypes[] = {
1302
{ "AMDGPU_HSA_KERNEL", ELF::STT_AMDGPU_HSA_KERNEL }
1303
};
1304
1305
static const char *getGroupType(uint32_t Flag) {
1306
if (Flag & ELF::GRP_COMDAT)
1307
return "COMDAT";
1308
else
1309
return "(unknown)";
1310
}
1311
1312
const EnumEntry<unsigned> ElfSectionFlags[] = {
1313
ENUM_ENT(SHF_WRITE, "W"),
1314
ENUM_ENT(SHF_ALLOC, "A"),
1315
ENUM_ENT(SHF_EXECINSTR, "X"),
1316
ENUM_ENT(SHF_MERGE, "M"),
1317
ENUM_ENT(SHF_STRINGS, "S"),
1318
ENUM_ENT(SHF_INFO_LINK, "I"),
1319
ENUM_ENT(SHF_LINK_ORDER, "L"),
1320
ENUM_ENT(SHF_OS_NONCONFORMING, "O"),
1321
ENUM_ENT(SHF_GROUP, "G"),
1322
ENUM_ENT(SHF_TLS, "T"),
1323
ENUM_ENT(SHF_COMPRESSED, "C"),
1324
ENUM_ENT(SHF_EXCLUDE, "E"),
1325
};
1326
1327
const EnumEntry<unsigned> ElfGNUSectionFlags[] = {
1328
ENUM_ENT(SHF_GNU_RETAIN, "R")
1329
};
1330
1331
const EnumEntry<unsigned> ElfSolarisSectionFlags[] = {
1332
ENUM_ENT(SHF_SUNW_NODISCARD, "R")
1333
};
1334
1335
const EnumEntry<unsigned> ElfXCoreSectionFlags[] = {
1336
ENUM_ENT(XCORE_SHF_CP_SECTION, ""),
1337
ENUM_ENT(XCORE_SHF_DP_SECTION, "")
1338
};
1339
1340
const EnumEntry<unsigned> ElfARMSectionFlags[] = {
1341
ENUM_ENT(SHF_ARM_PURECODE, "y")
1342
};
1343
1344
const EnumEntry<unsigned> ElfHexagonSectionFlags[] = {
1345
ENUM_ENT(SHF_HEX_GPREL, "")
1346
};
1347
1348
const EnumEntry<unsigned> ElfMipsSectionFlags[] = {
1349
ENUM_ENT(SHF_MIPS_NODUPES, ""),
1350
ENUM_ENT(SHF_MIPS_NAMES, ""),
1351
ENUM_ENT(SHF_MIPS_LOCAL, ""),
1352
ENUM_ENT(SHF_MIPS_NOSTRIP, ""),
1353
ENUM_ENT(SHF_MIPS_GPREL, ""),
1354
ENUM_ENT(SHF_MIPS_MERGE, ""),
1355
ENUM_ENT(SHF_MIPS_ADDR, ""),
1356
ENUM_ENT(SHF_MIPS_STRING, "")
1357
};
1358
1359
const EnumEntry<unsigned> ElfX86_64SectionFlags[] = {
1360
ENUM_ENT(SHF_X86_64_LARGE, "l")
1361
};
1362
1363
static std::vector<EnumEntry<unsigned>>
1364
getSectionFlagsForTarget(unsigned EOSAbi, unsigned EMachine) {
1365
std::vector<EnumEntry<unsigned>> Ret(std::begin(ElfSectionFlags),
1366
std::end(ElfSectionFlags));
1367
switch (EOSAbi) {
1368
case ELFOSABI_SOLARIS:
1369
Ret.insert(Ret.end(), std::begin(ElfSolarisSectionFlags),
1370
std::end(ElfSolarisSectionFlags));
1371
break;
1372
default:
1373
Ret.insert(Ret.end(), std::begin(ElfGNUSectionFlags),
1374
std::end(ElfGNUSectionFlags));
1375
break;
1376
}
1377
switch (EMachine) {
1378
case EM_ARM:
1379
Ret.insert(Ret.end(), std::begin(ElfARMSectionFlags),
1380
std::end(ElfARMSectionFlags));
1381
break;
1382
case EM_HEXAGON:
1383
Ret.insert(Ret.end(), std::begin(ElfHexagonSectionFlags),
1384
std::end(ElfHexagonSectionFlags));
1385
break;
1386
case EM_MIPS:
1387
Ret.insert(Ret.end(), std::begin(ElfMipsSectionFlags),
1388
std::end(ElfMipsSectionFlags));
1389
break;
1390
case EM_X86_64:
1391
Ret.insert(Ret.end(), std::begin(ElfX86_64SectionFlags),
1392
std::end(ElfX86_64SectionFlags));
1393
break;
1394
case EM_XCORE:
1395
Ret.insert(Ret.end(), std::begin(ElfXCoreSectionFlags),
1396
std::end(ElfXCoreSectionFlags));
1397
break;
1398
default:
1399
break;
1400
}
1401
return Ret;
1402
}
1403
1404
static std::string getGNUFlags(unsigned EOSAbi, unsigned EMachine,
1405
uint64_t Flags) {
1406
// Here we are trying to build the flags string in the same way as GNU does.
1407
// It is not that straightforward. Imagine we have sh_flags == 0x90000000.
1408
// SHF_EXCLUDE ("E") has a value of 0x80000000 and SHF_MASKPROC is 0xf0000000.
1409
// GNU readelf will not print "E" or "Ep" in this case, but will print just
1410
// "p". It only will print "E" when no other processor flag is set.
1411
std::string Str;
1412
bool HasUnknownFlag = false;
1413
bool HasOSFlag = false;
1414
bool HasProcFlag = false;
1415
std::vector<EnumEntry<unsigned>> FlagsList =
1416
getSectionFlagsForTarget(EOSAbi, EMachine);
1417
while (Flags) {
1418
// Take the least significant bit as a flag.
1419
uint64_t Flag = Flags & -Flags;
1420
Flags -= Flag;
1421
1422
// Find the flag in the known flags list.
1423
auto I = llvm::find_if(FlagsList, [=](const EnumEntry<unsigned> &E) {
1424
// Flags with empty names are not printed in GNU style output.
1425
return E.Value == Flag && !E.AltName.empty();
1426
});
1427
if (I != FlagsList.end()) {
1428
Str += I->AltName;
1429
continue;
1430
}
1431
1432
// If we did not find a matching regular flag, then we deal with an OS
1433
// specific flag, processor specific flag or an unknown flag.
1434
if (Flag & ELF::SHF_MASKOS) {
1435
HasOSFlag = true;
1436
Flags &= ~ELF::SHF_MASKOS;
1437
} else if (Flag & ELF::SHF_MASKPROC) {
1438
HasProcFlag = true;
1439
// Mask off all the processor-specific bits. This removes the SHF_EXCLUDE
1440
// bit if set so that it doesn't also get printed.
1441
Flags &= ~ELF::SHF_MASKPROC;
1442
} else {
1443
HasUnknownFlag = true;
1444
}
1445
}
1446
1447
// "o", "p" and "x" are printed last.
1448
if (HasOSFlag)
1449
Str += "o";
1450
if (HasProcFlag)
1451
Str += "p";
1452
if (HasUnknownFlag)
1453
Str += "x";
1454
return Str;
1455
}
1456
1457
static StringRef segmentTypeToString(unsigned Arch, unsigned Type) {
1458
// Check potentially overlapped processor-specific program header type.
1459
switch (Arch) {
1460
case ELF::EM_ARM:
1461
switch (Type) { LLVM_READOBJ_ENUM_CASE(ELF, PT_ARM_EXIDX); }
1462
break;
1463
case ELF::EM_MIPS:
1464
case ELF::EM_MIPS_RS3_LE:
1465
switch (Type) {
1466
LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_REGINFO);
1467
LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_RTPROC);
1468
LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_OPTIONS);
1469
LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_ABIFLAGS);
1470
}
1471
break;
1472
case ELF::EM_RISCV:
1473
switch (Type) { LLVM_READOBJ_ENUM_CASE(ELF, PT_RISCV_ATTRIBUTES); }
1474
}
1475
1476
switch (Type) {
1477
LLVM_READOBJ_ENUM_CASE(ELF, PT_NULL);
1478
LLVM_READOBJ_ENUM_CASE(ELF, PT_LOAD);
1479
LLVM_READOBJ_ENUM_CASE(ELF, PT_DYNAMIC);
1480
LLVM_READOBJ_ENUM_CASE(ELF, PT_INTERP);
1481
LLVM_READOBJ_ENUM_CASE(ELF, PT_NOTE);
1482
LLVM_READOBJ_ENUM_CASE(ELF, PT_SHLIB);
1483
LLVM_READOBJ_ENUM_CASE(ELF, PT_PHDR);
1484
LLVM_READOBJ_ENUM_CASE(ELF, PT_TLS);
1485
1486
LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_EH_FRAME);
1487
LLVM_READOBJ_ENUM_CASE(ELF, PT_SUNW_UNWIND);
1488
1489
LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_STACK);
1490
LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_RELRO);
1491
LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_PROPERTY);
1492
1493
LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_MUTABLE);
1494
LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_RANDOMIZE);
1495
LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_WXNEEDED);
1496
LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_NOBTCFI);
1497
LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_SYSCALLS);
1498
LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_BOOTDATA);
1499
default:
1500
return "";
1501
}
1502
}
1503
1504
static std::string getGNUPtType(unsigned Arch, unsigned Type) {
1505
StringRef Seg = segmentTypeToString(Arch, Type);
1506
if (Seg.empty())
1507
return std::string("<unknown>: ") + to_string(format_hex(Type, 1));
1508
1509
// E.g. "PT_ARM_EXIDX" -> "EXIDX".
1510
if (Seg.consume_front("PT_ARM_"))
1511
return Seg.str();
1512
1513
// E.g. "PT_MIPS_REGINFO" -> "REGINFO".
1514
if (Seg.consume_front("PT_MIPS_"))
1515
return Seg.str();
1516
1517
// E.g. "PT_RISCV_ATTRIBUTES"
1518
if (Seg.consume_front("PT_RISCV_"))
1519
return Seg.str();
1520
1521
// E.g. "PT_LOAD" -> "LOAD".
1522
assert(Seg.starts_with("PT_"));
1523
return Seg.drop_front(3).str();
1524
}
1525
1526
const EnumEntry<unsigned> ElfSegmentFlags[] = {
1527
LLVM_READOBJ_ENUM_ENT(ELF, PF_X),
1528
LLVM_READOBJ_ENUM_ENT(ELF, PF_W),
1529
LLVM_READOBJ_ENUM_ENT(ELF, PF_R)
1530
};
1531
1532
const EnumEntry<unsigned> ElfHeaderMipsFlags[] = {
1533
ENUM_ENT(EF_MIPS_NOREORDER, "noreorder"),
1534
ENUM_ENT(EF_MIPS_PIC, "pic"),
1535
ENUM_ENT(EF_MIPS_CPIC, "cpic"),
1536
ENUM_ENT(EF_MIPS_ABI2, "abi2"),
1537
ENUM_ENT(EF_MIPS_32BITMODE, "32bitmode"),
1538
ENUM_ENT(EF_MIPS_FP64, "fp64"),
1539
ENUM_ENT(EF_MIPS_NAN2008, "nan2008"),
1540
ENUM_ENT(EF_MIPS_ABI_O32, "o32"),
1541
ENUM_ENT(EF_MIPS_ABI_O64, "o64"),
1542
ENUM_ENT(EF_MIPS_ABI_EABI32, "eabi32"),
1543
ENUM_ENT(EF_MIPS_ABI_EABI64, "eabi64"),
1544
ENUM_ENT(EF_MIPS_MACH_3900, "3900"),
1545
ENUM_ENT(EF_MIPS_MACH_4010, "4010"),
1546
ENUM_ENT(EF_MIPS_MACH_4100, "4100"),
1547
ENUM_ENT(EF_MIPS_MACH_4650, "4650"),
1548
ENUM_ENT(EF_MIPS_MACH_4120, "4120"),
1549
ENUM_ENT(EF_MIPS_MACH_4111, "4111"),
1550
ENUM_ENT(EF_MIPS_MACH_SB1, "sb1"),
1551
ENUM_ENT(EF_MIPS_MACH_OCTEON, "octeon"),
1552
ENUM_ENT(EF_MIPS_MACH_XLR, "xlr"),
1553
ENUM_ENT(EF_MIPS_MACH_OCTEON2, "octeon2"),
1554
ENUM_ENT(EF_MIPS_MACH_OCTEON3, "octeon3"),
1555
ENUM_ENT(EF_MIPS_MACH_5400, "5400"),
1556
ENUM_ENT(EF_MIPS_MACH_5900, "5900"),
1557
ENUM_ENT(EF_MIPS_MACH_5500, "5500"),
1558
ENUM_ENT(EF_MIPS_MACH_9000, "9000"),
1559
ENUM_ENT(EF_MIPS_MACH_LS2E, "loongson-2e"),
1560
ENUM_ENT(EF_MIPS_MACH_LS2F, "loongson-2f"),
1561
ENUM_ENT(EF_MIPS_MACH_LS3A, "loongson-3a"),
1562
ENUM_ENT(EF_MIPS_MICROMIPS, "micromips"),
1563
ENUM_ENT(EF_MIPS_ARCH_ASE_M16, "mips16"),
1564
ENUM_ENT(EF_MIPS_ARCH_ASE_MDMX, "mdmx"),
1565
ENUM_ENT(EF_MIPS_ARCH_1, "mips1"),
1566
ENUM_ENT(EF_MIPS_ARCH_2, "mips2"),
1567
ENUM_ENT(EF_MIPS_ARCH_3, "mips3"),
1568
ENUM_ENT(EF_MIPS_ARCH_4, "mips4"),
1569
ENUM_ENT(EF_MIPS_ARCH_5, "mips5"),
1570
ENUM_ENT(EF_MIPS_ARCH_32, "mips32"),
1571
ENUM_ENT(EF_MIPS_ARCH_64, "mips64"),
1572
ENUM_ENT(EF_MIPS_ARCH_32R2, "mips32r2"),
1573
ENUM_ENT(EF_MIPS_ARCH_64R2, "mips64r2"),
1574
ENUM_ENT(EF_MIPS_ARCH_32R6, "mips32r6"),
1575
ENUM_ENT(EF_MIPS_ARCH_64R6, "mips64r6")
1576
};
1577
1578
// clang-format off
1579
#define AMDGPU_MACH_ENUM_ENTS \
1580
ENUM_ENT(EF_AMDGPU_MACH_NONE, "none"), \
1581
ENUM_ENT(EF_AMDGPU_MACH_R600_R600, "r600"), \
1582
ENUM_ENT(EF_AMDGPU_MACH_R600_R630, "r630"), \
1583
ENUM_ENT(EF_AMDGPU_MACH_R600_RS880, "rs880"), \
1584
ENUM_ENT(EF_AMDGPU_MACH_R600_RV670, "rv670"), \
1585
ENUM_ENT(EF_AMDGPU_MACH_R600_RV710, "rv710"), \
1586
ENUM_ENT(EF_AMDGPU_MACH_R600_RV730, "rv730"), \
1587
ENUM_ENT(EF_AMDGPU_MACH_R600_RV770, "rv770"), \
1588
ENUM_ENT(EF_AMDGPU_MACH_R600_CEDAR, "cedar"), \
1589
ENUM_ENT(EF_AMDGPU_MACH_R600_CYPRESS, "cypress"), \
1590
ENUM_ENT(EF_AMDGPU_MACH_R600_JUNIPER, "juniper"), \
1591
ENUM_ENT(EF_AMDGPU_MACH_R600_REDWOOD, "redwood"), \
1592
ENUM_ENT(EF_AMDGPU_MACH_R600_SUMO, "sumo"), \
1593
ENUM_ENT(EF_AMDGPU_MACH_R600_BARTS, "barts"), \
1594
ENUM_ENT(EF_AMDGPU_MACH_R600_CAICOS, "caicos"), \
1595
ENUM_ENT(EF_AMDGPU_MACH_R600_CAYMAN, "cayman"), \
1596
ENUM_ENT(EF_AMDGPU_MACH_R600_TURKS, "turks"), \
1597
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX600, "gfx600"), \
1598
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX601, "gfx601"), \
1599
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX602, "gfx602"), \
1600
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX700, "gfx700"), \
1601
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX701, "gfx701"), \
1602
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX702, "gfx702"), \
1603
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX703, "gfx703"), \
1604
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX704, "gfx704"), \
1605
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX705, "gfx705"), \
1606
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX801, "gfx801"), \
1607
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX802, "gfx802"), \
1608
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX803, "gfx803"), \
1609
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX805, "gfx805"), \
1610
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX810, "gfx810"), \
1611
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX900, "gfx900"), \
1612
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX902, "gfx902"), \
1613
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX904, "gfx904"), \
1614
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX906, "gfx906"), \
1615
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX908, "gfx908"), \
1616
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX909, "gfx909"), \
1617
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX90A, "gfx90a"), \
1618
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX90C, "gfx90c"), \
1619
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX940, "gfx940"), \
1620
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX941, "gfx941"), \
1621
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX942, "gfx942"), \
1622
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1010, "gfx1010"), \
1623
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1011, "gfx1011"), \
1624
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1012, "gfx1012"), \
1625
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1013, "gfx1013"), \
1626
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1030, "gfx1030"), \
1627
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1031, "gfx1031"), \
1628
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1032, "gfx1032"), \
1629
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1033, "gfx1033"), \
1630
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1034, "gfx1034"), \
1631
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1035, "gfx1035"), \
1632
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1036, "gfx1036"), \
1633
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1100, "gfx1100"), \
1634
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1101, "gfx1101"), \
1635
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1102, "gfx1102"), \
1636
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1103, "gfx1103"), \
1637
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1150, "gfx1150"), \
1638
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1151, "gfx1151"), \
1639
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1152, "gfx1152"), \
1640
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1200, "gfx1200"), \
1641
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1201, "gfx1201"), \
1642
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX9_GENERIC, "gfx9-generic"), \
1643
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX10_1_GENERIC, "gfx10-1-generic"), \
1644
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX10_3_GENERIC, "gfx10-3-generic"), \
1645
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX11_GENERIC, "gfx11-generic"), \
1646
ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX12_GENERIC, "gfx12-generic")
1647
// clang-format on
1648
1649
const EnumEntry<unsigned> ElfHeaderAMDGPUFlagsABIVersion3[] = {
1650
AMDGPU_MACH_ENUM_ENTS,
1651
ENUM_ENT(EF_AMDGPU_FEATURE_XNACK_V3, "xnack"),
1652
ENUM_ENT(EF_AMDGPU_FEATURE_SRAMECC_V3, "sramecc"),
1653
};
1654
1655
const EnumEntry<unsigned> ElfHeaderAMDGPUFlagsABIVersion4[] = {
1656
AMDGPU_MACH_ENUM_ENTS,
1657
ENUM_ENT(EF_AMDGPU_FEATURE_XNACK_ANY_V4, "xnack"),
1658
ENUM_ENT(EF_AMDGPU_FEATURE_XNACK_OFF_V4, "xnack-"),
1659
ENUM_ENT(EF_AMDGPU_FEATURE_XNACK_ON_V4, "xnack+"),
1660
ENUM_ENT(EF_AMDGPU_FEATURE_SRAMECC_ANY_V4, "sramecc"),
1661
ENUM_ENT(EF_AMDGPU_FEATURE_SRAMECC_OFF_V4, "sramecc-"),
1662
ENUM_ENT(EF_AMDGPU_FEATURE_SRAMECC_ON_V4, "sramecc+"),
1663
};
1664
1665
const EnumEntry<unsigned> ElfHeaderNVPTXFlags[] = {
1666
ENUM_ENT(EF_CUDA_SM20, "sm_20"), ENUM_ENT(EF_CUDA_SM21, "sm_21"),
1667
ENUM_ENT(EF_CUDA_SM30, "sm_30"), ENUM_ENT(EF_CUDA_SM32, "sm_32"),
1668
ENUM_ENT(EF_CUDA_SM35, "sm_35"), ENUM_ENT(EF_CUDA_SM37, "sm_37"),
1669
ENUM_ENT(EF_CUDA_SM50, "sm_50"), ENUM_ENT(EF_CUDA_SM52, "sm_52"),
1670
ENUM_ENT(EF_CUDA_SM53, "sm_53"), ENUM_ENT(EF_CUDA_SM60, "sm_60"),
1671
ENUM_ENT(EF_CUDA_SM61, "sm_61"), ENUM_ENT(EF_CUDA_SM62, "sm_62"),
1672
ENUM_ENT(EF_CUDA_SM70, "sm_70"), ENUM_ENT(EF_CUDA_SM72, "sm_72"),
1673
ENUM_ENT(EF_CUDA_SM75, "sm_75"), ENUM_ENT(EF_CUDA_SM80, "sm_80"),
1674
ENUM_ENT(EF_CUDA_SM86, "sm_86"), ENUM_ENT(EF_CUDA_SM87, "sm_87"),
1675
ENUM_ENT(EF_CUDA_SM89, "sm_89"), ENUM_ENT(EF_CUDA_SM90, "sm_90"),
1676
};
1677
1678
const EnumEntry<unsigned> ElfHeaderRISCVFlags[] = {
1679
ENUM_ENT(EF_RISCV_RVC, "RVC"),
1680
ENUM_ENT(EF_RISCV_FLOAT_ABI_SINGLE, "single-float ABI"),
1681
ENUM_ENT(EF_RISCV_FLOAT_ABI_DOUBLE, "double-float ABI"),
1682
ENUM_ENT(EF_RISCV_FLOAT_ABI_QUAD, "quad-float ABI"),
1683
ENUM_ENT(EF_RISCV_RVE, "RVE"),
1684
ENUM_ENT(EF_RISCV_TSO, "TSO"),
1685
};
1686
1687
const EnumEntry<unsigned> ElfHeaderAVRFlags[] = {
1688
LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR1),
1689
LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR2),
1690
LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR25),
1691
LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR3),
1692
LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR31),
1693
LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR35),
1694
LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR4),
1695
LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR5),
1696
LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR51),
1697
LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR6),
1698
LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVRTINY),
1699
LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA1),
1700
LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA2),
1701
LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA3),
1702
LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA4),
1703
LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA5),
1704
LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA6),
1705
LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA7),
1706
ENUM_ENT(EF_AVR_LINKRELAX_PREPARED, "relaxable"),
1707
};
1708
1709
const EnumEntry<unsigned> ElfHeaderLoongArchFlags[] = {
1710
ENUM_ENT(EF_LOONGARCH_ABI_SOFT_FLOAT, "SOFT-FLOAT"),
1711
ENUM_ENT(EF_LOONGARCH_ABI_SINGLE_FLOAT, "SINGLE-FLOAT"),
1712
ENUM_ENT(EF_LOONGARCH_ABI_DOUBLE_FLOAT, "DOUBLE-FLOAT"),
1713
ENUM_ENT(EF_LOONGARCH_OBJABI_V0, "OBJ-v0"),
1714
ENUM_ENT(EF_LOONGARCH_OBJABI_V1, "OBJ-v1"),
1715
};
1716
1717
static const EnumEntry<unsigned> ElfHeaderXtensaFlags[] = {
1718
LLVM_READOBJ_ENUM_ENT(ELF, EF_XTENSA_MACH_NONE),
1719
LLVM_READOBJ_ENUM_ENT(ELF, EF_XTENSA_XT_INSN),
1720
LLVM_READOBJ_ENUM_ENT(ELF, EF_XTENSA_XT_LIT)
1721
};
1722
1723
const EnumEntry<unsigned> ElfSymOtherFlags[] = {
1724
LLVM_READOBJ_ENUM_ENT(ELF, STV_INTERNAL),
1725
LLVM_READOBJ_ENUM_ENT(ELF, STV_HIDDEN),
1726
LLVM_READOBJ_ENUM_ENT(ELF, STV_PROTECTED)
1727
};
1728
1729
const EnumEntry<unsigned> ElfMipsSymOtherFlags[] = {
1730
LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_OPTIONAL),
1731
LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_PLT),
1732
LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_PIC),
1733
LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_MICROMIPS)
1734
};
1735
1736
const EnumEntry<unsigned> ElfAArch64SymOtherFlags[] = {
1737
LLVM_READOBJ_ENUM_ENT(ELF, STO_AARCH64_VARIANT_PCS)
1738
};
1739
1740
const EnumEntry<unsigned> ElfMips16SymOtherFlags[] = {
1741
LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_OPTIONAL),
1742
LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_PLT),
1743
LLVM_READOBJ_ENUM_ENT(ELF, STO_MIPS_MIPS16)
1744
};
1745
1746
const EnumEntry<unsigned> ElfRISCVSymOtherFlags[] = {
1747
LLVM_READOBJ_ENUM_ENT(ELF, STO_RISCV_VARIANT_CC)};
1748
1749
static const char *getElfMipsOptionsOdkType(unsigned Odk) {
1750
switch (Odk) {
1751
LLVM_READOBJ_ENUM_CASE(ELF, ODK_NULL);
1752
LLVM_READOBJ_ENUM_CASE(ELF, ODK_REGINFO);
1753
LLVM_READOBJ_ENUM_CASE(ELF, ODK_EXCEPTIONS);
1754
LLVM_READOBJ_ENUM_CASE(ELF, ODK_PAD);
1755
LLVM_READOBJ_ENUM_CASE(ELF, ODK_HWPATCH);
1756
LLVM_READOBJ_ENUM_CASE(ELF, ODK_FILL);
1757
LLVM_READOBJ_ENUM_CASE(ELF, ODK_TAGS);
1758
LLVM_READOBJ_ENUM_CASE(ELF, ODK_HWAND);
1759
LLVM_READOBJ_ENUM_CASE(ELF, ODK_HWOR);
1760
LLVM_READOBJ_ENUM_CASE(ELF, ODK_GP_GROUP);
1761
LLVM_READOBJ_ENUM_CASE(ELF, ODK_IDENT);
1762
LLVM_READOBJ_ENUM_CASE(ELF, ODK_PAGESIZE);
1763
default:
1764
return "Unknown";
1765
}
1766
}
1767
1768
template <typename ELFT>
1769
std::pair<const typename ELFT::Phdr *, const typename ELFT::Shdr *>
1770
ELFDumper<ELFT>::findDynamic() {
1771
// Try to locate the PT_DYNAMIC header.
1772
const Elf_Phdr *DynamicPhdr = nullptr;
1773
if (Expected<ArrayRef<Elf_Phdr>> PhdrsOrErr = Obj.program_headers()) {
1774
for (const Elf_Phdr &Phdr : *PhdrsOrErr) {
1775
if (Phdr.p_type != ELF::PT_DYNAMIC)
1776
continue;
1777
DynamicPhdr = &Phdr;
1778
break;
1779
}
1780
} else {
1781
reportUniqueWarning(
1782
"unable to read program headers to locate the PT_DYNAMIC segment: " +
1783
toString(PhdrsOrErr.takeError()));
1784
}
1785
1786
// Try to locate the .dynamic section in the sections header table.
1787
const Elf_Shdr *DynamicSec = nullptr;
1788
for (const Elf_Shdr &Sec : cantFail(Obj.sections())) {
1789
if (Sec.sh_type != ELF::SHT_DYNAMIC)
1790
continue;
1791
DynamicSec = &Sec;
1792
break;
1793
}
1794
1795
if (DynamicPhdr && ((DynamicPhdr->p_offset + DynamicPhdr->p_filesz >
1796
ObjF.getMemoryBufferRef().getBufferSize()) ||
1797
(DynamicPhdr->p_offset + DynamicPhdr->p_filesz <
1798
DynamicPhdr->p_offset))) {
1799
reportUniqueWarning(
1800
"PT_DYNAMIC segment offset (0x" +
1801
Twine::utohexstr(DynamicPhdr->p_offset) + ") + file size (0x" +
1802
Twine::utohexstr(DynamicPhdr->p_filesz) +
1803
") exceeds the size of the file (0x" +
1804
Twine::utohexstr(ObjF.getMemoryBufferRef().getBufferSize()) + ")");
1805
// Don't use the broken dynamic header.
1806
DynamicPhdr = nullptr;
1807
}
1808
1809
if (DynamicPhdr && DynamicSec) {
1810
if (DynamicSec->sh_addr + DynamicSec->sh_size >
1811
DynamicPhdr->p_vaddr + DynamicPhdr->p_memsz ||
1812
DynamicSec->sh_addr < DynamicPhdr->p_vaddr)
1813
reportUniqueWarning(describe(*DynamicSec) +
1814
" is not contained within the "
1815
"PT_DYNAMIC segment");
1816
1817
if (DynamicSec->sh_addr != DynamicPhdr->p_vaddr)
1818
reportUniqueWarning(describe(*DynamicSec) + " is not at the start of "
1819
"PT_DYNAMIC segment");
1820
}
1821
1822
return std::make_pair(DynamicPhdr, DynamicSec);
1823
}
1824
1825
template <typename ELFT>
1826
void ELFDumper<ELFT>::loadDynamicTable() {
1827
const Elf_Phdr *DynamicPhdr;
1828
const Elf_Shdr *DynamicSec;
1829
std::tie(DynamicPhdr, DynamicSec) = findDynamic();
1830
if (!DynamicPhdr && !DynamicSec)
1831
return;
1832
1833
DynRegionInfo FromPhdr(ObjF, *this);
1834
bool IsPhdrTableValid = false;
1835
if (DynamicPhdr) {
1836
// Use cantFail(), because p_offset/p_filesz fields of a PT_DYNAMIC are
1837
// validated in findDynamic() and so createDRI() is not expected to fail.
1838
FromPhdr = cantFail(createDRI(DynamicPhdr->p_offset, DynamicPhdr->p_filesz,
1839
sizeof(Elf_Dyn)));
1840
FromPhdr.SizePrintName = "PT_DYNAMIC size";
1841
FromPhdr.EntSizePrintName = "";
1842
IsPhdrTableValid = !FromPhdr.template getAsArrayRef<Elf_Dyn>().empty();
1843
}
1844
1845
// Locate the dynamic table described in a section header.
1846
// Ignore sh_entsize and use the expected value for entry size explicitly.
1847
// This allows us to dump dynamic sections with a broken sh_entsize
1848
// field.
1849
DynRegionInfo FromSec(ObjF, *this);
1850
bool IsSecTableValid = false;
1851
if (DynamicSec) {
1852
Expected<DynRegionInfo> RegOrErr =
1853
createDRI(DynamicSec->sh_offset, DynamicSec->sh_size, sizeof(Elf_Dyn));
1854
if (RegOrErr) {
1855
FromSec = *RegOrErr;
1856
FromSec.Context = describe(*DynamicSec);
1857
FromSec.EntSizePrintName = "";
1858
IsSecTableValid = !FromSec.template getAsArrayRef<Elf_Dyn>().empty();
1859
} else {
1860
reportUniqueWarning("unable to read the dynamic table from " +
1861
describe(*DynamicSec) + ": " +
1862
toString(RegOrErr.takeError()));
1863
}
1864
}
1865
1866
// When we only have information from one of the SHT_DYNAMIC section header or
1867
// PT_DYNAMIC program header, just use that.
1868
if (!DynamicPhdr || !DynamicSec) {
1869
if ((DynamicPhdr && IsPhdrTableValid) || (DynamicSec && IsSecTableValid)) {
1870
DynamicTable = DynamicPhdr ? FromPhdr : FromSec;
1871
parseDynamicTable();
1872
} else {
1873
reportUniqueWarning("no valid dynamic table was found");
1874
}
1875
return;
1876
}
1877
1878
// At this point we have tables found from the section header and from the
1879
// dynamic segment. Usually they match, but we have to do sanity checks to
1880
// verify that.
1881
1882
if (FromPhdr.Addr != FromSec.Addr)
1883
reportUniqueWarning("SHT_DYNAMIC section header and PT_DYNAMIC "
1884
"program header disagree about "
1885
"the location of the dynamic table");
1886
1887
if (!IsPhdrTableValid && !IsSecTableValid) {
1888
reportUniqueWarning("no valid dynamic table was found");
1889
return;
1890
}
1891
1892
// Information in the PT_DYNAMIC program header has priority over the
1893
// information in a section header.
1894
if (IsPhdrTableValid) {
1895
if (!IsSecTableValid)
1896
reportUniqueWarning(
1897
"SHT_DYNAMIC dynamic table is invalid: PT_DYNAMIC will be used");
1898
DynamicTable = FromPhdr;
1899
} else {
1900
reportUniqueWarning(
1901
"PT_DYNAMIC dynamic table is invalid: SHT_DYNAMIC will be used");
1902
DynamicTable = FromSec;
1903
}
1904
1905
parseDynamicTable();
1906
}
1907
1908
template <typename ELFT>
1909
ELFDumper<ELFT>::ELFDumper(const object::ELFObjectFile<ELFT> &O,
1910
ScopedPrinter &Writer)
1911
: ObjDumper(Writer, O.getFileName()), ObjF(O), Obj(O.getELFFile()),
1912
FileName(O.getFileName()), DynRelRegion(O, *this),
1913
DynRelaRegion(O, *this), DynCrelRegion(O, *this), DynRelrRegion(O, *this),
1914
DynPLTRelRegion(O, *this), DynSymTabShndxRegion(O, *this),
1915
DynamicTable(O, *this) {
1916
if (!O.IsContentValid())
1917
return;
1918
1919
typename ELFT::ShdrRange Sections = cantFail(Obj.sections());
1920
for (const Elf_Shdr &Sec : Sections) {
1921
switch (Sec.sh_type) {
1922
case ELF::SHT_SYMTAB:
1923
if (!DotSymtabSec)
1924
DotSymtabSec = &Sec;
1925
break;
1926
case ELF::SHT_DYNSYM:
1927
if (!DotDynsymSec)
1928
DotDynsymSec = &Sec;
1929
1930
if (!DynSymRegion) {
1931
Expected<DynRegionInfo> RegOrErr =
1932
createDRI(Sec.sh_offset, Sec.sh_size, Sec.sh_entsize);
1933
if (RegOrErr) {
1934
DynSymRegion = *RegOrErr;
1935
DynSymRegion->Context = describe(Sec);
1936
1937
if (Expected<StringRef> E = Obj.getStringTableForSymtab(Sec))
1938
DynamicStringTable = *E;
1939
else
1940
reportUniqueWarning("unable to get the string table for the " +
1941
describe(Sec) + ": " + toString(E.takeError()));
1942
} else {
1943
reportUniqueWarning("unable to read dynamic symbols from " +
1944
describe(Sec) + ": " +
1945
toString(RegOrErr.takeError()));
1946
}
1947
}
1948
break;
1949
case ELF::SHT_SYMTAB_SHNDX: {
1950
uint32_t SymtabNdx = Sec.sh_link;
1951
if (SymtabNdx >= Sections.size()) {
1952
reportUniqueWarning(
1953
"unable to get the associated symbol table for " + describe(Sec) +
1954
": sh_link (" + Twine(SymtabNdx) +
1955
") is greater than or equal to the total number of sections (" +
1956
Twine(Sections.size()) + ")");
1957
continue;
1958
}
1959
1960
if (Expected<ArrayRef<Elf_Word>> ShndxTableOrErr =
1961
Obj.getSHNDXTable(Sec)) {
1962
if (!ShndxTables.insert({&Sections[SymtabNdx], *ShndxTableOrErr})
1963
.second)
1964
reportUniqueWarning(
1965
"multiple SHT_SYMTAB_SHNDX sections are linked to " +
1966
describe(Sec));
1967
} else {
1968
reportUniqueWarning(ShndxTableOrErr.takeError());
1969
}
1970
break;
1971
}
1972
case ELF::SHT_GNU_versym:
1973
if (!SymbolVersionSection)
1974
SymbolVersionSection = &Sec;
1975
break;
1976
case ELF::SHT_GNU_verdef:
1977
if (!SymbolVersionDefSection)
1978
SymbolVersionDefSection = &Sec;
1979
break;
1980
case ELF::SHT_GNU_verneed:
1981
if (!SymbolVersionNeedSection)
1982
SymbolVersionNeedSection = &Sec;
1983
break;
1984
case ELF::SHT_LLVM_ADDRSIG:
1985
if (!DotAddrsigSec)
1986
DotAddrsigSec = &Sec;
1987
break;
1988
}
1989
}
1990
1991
loadDynamicTable();
1992
}
1993
1994
template <typename ELFT> void ELFDumper<ELFT>::parseDynamicTable() {
1995
auto toMappedAddr = [&](uint64_t Tag, uint64_t VAddr) -> const uint8_t * {
1996
auto MappedAddrOrError = Obj.toMappedAddr(VAddr, [&](const Twine &Msg) {
1997
this->reportUniqueWarning(Msg);
1998
return Error::success();
1999
});
2000
if (!MappedAddrOrError) {
2001
this->reportUniqueWarning("unable to parse DT_" +
2002
Obj.getDynamicTagAsString(Tag) + ": " +
2003
llvm::toString(MappedAddrOrError.takeError()));
2004
return nullptr;
2005
}
2006
return MappedAddrOrError.get();
2007
};
2008
2009
const char *StringTableBegin = nullptr;
2010
uint64_t StringTableSize = 0;
2011
std::optional<DynRegionInfo> DynSymFromTable;
2012
for (const Elf_Dyn &Dyn : dynamic_table()) {
2013
if (Obj.getHeader().e_machine == EM_AARCH64) {
2014
switch (Dyn.d_tag) {
2015
case ELF::DT_AARCH64_AUTH_RELRSZ:
2016
DynRelrRegion.Size = Dyn.getVal();
2017
DynRelrRegion.SizePrintName = "DT_AARCH64_AUTH_RELRSZ value";
2018
continue;
2019
case ELF::DT_AARCH64_AUTH_RELRENT:
2020
DynRelrRegion.EntSize = Dyn.getVal();
2021
DynRelrRegion.EntSizePrintName = "DT_AARCH64_AUTH_RELRENT value";
2022
continue;
2023
}
2024
}
2025
switch (Dyn.d_tag) {
2026
case ELF::DT_HASH:
2027
HashTable = reinterpret_cast<const Elf_Hash *>(
2028
toMappedAddr(Dyn.getTag(), Dyn.getPtr()));
2029
break;
2030
case ELF::DT_GNU_HASH:
2031
GnuHashTable = reinterpret_cast<const Elf_GnuHash *>(
2032
toMappedAddr(Dyn.getTag(), Dyn.getPtr()));
2033
break;
2034
case ELF::DT_STRTAB:
2035
StringTableBegin = reinterpret_cast<const char *>(
2036
toMappedAddr(Dyn.getTag(), Dyn.getPtr()));
2037
break;
2038
case ELF::DT_STRSZ:
2039
StringTableSize = Dyn.getVal();
2040
break;
2041
case ELF::DT_SYMTAB: {
2042
// If we can't map the DT_SYMTAB value to an address (e.g. when there are
2043
// no program headers), we ignore its value.
2044
if (const uint8_t *VA = toMappedAddr(Dyn.getTag(), Dyn.getPtr())) {
2045
DynSymFromTable.emplace(ObjF, *this);
2046
DynSymFromTable->Addr = VA;
2047
DynSymFromTable->EntSize = sizeof(Elf_Sym);
2048
DynSymFromTable->EntSizePrintName = "";
2049
}
2050
break;
2051
}
2052
case ELF::DT_SYMENT: {
2053
uint64_t Val = Dyn.getVal();
2054
if (Val != sizeof(Elf_Sym))
2055
this->reportUniqueWarning("DT_SYMENT value of 0x" +
2056
Twine::utohexstr(Val) +
2057
" is not the size of a symbol (0x" +
2058
Twine::utohexstr(sizeof(Elf_Sym)) + ")");
2059
break;
2060
}
2061
case ELF::DT_RELA:
2062
DynRelaRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());
2063
break;
2064
case ELF::DT_RELASZ:
2065
DynRelaRegion.Size = Dyn.getVal();
2066
DynRelaRegion.SizePrintName = "DT_RELASZ value";
2067
break;
2068
case ELF::DT_RELAENT:
2069
DynRelaRegion.EntSize = Dyn.getVal();
2070
DynRelaRegion.EntSizePrintName = "DT_RELAENT value";
2071
break;
2072
case ELF::DT_CREL:
2073
DynCrelRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());
2074
break;
2075
case ELF::DT_SONAME:
2076
SONameOffset = Dyn.getVal();
2077
break;
2078
case ELF::DT_REL:
2079
DynRelRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());
2080
break;
2081
case ELF::DT_RELSZ:
2082
DynRelRegion.Size = Dyn.getVal();
2083
DynRelRegion.SizePrintName = "DT_RELSZ value";
2084
break;
2085
case ELF::DT_RELENT:
2086
DynRelRegion.EntSize = Dyn.getVal();
2087
DynRelRegion.EntSizePrintName = "DT_RELENT value";
2088
break;
2089
case ELF::DT_RELR:
2090
case ELF::DT_ANDROID_RELR:
2091
case ELF::DT_AARCH64_AUTH_RELR:
2092
DynRelrRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());
2093
break;
2094
case ELF::DT_RELRSZ:
2095
case ELF::DT_ANDROID_RELRSZ:
2096
case ELF::DT_AARCH64_AUTH_RELRSZ:
2097
DynRelrRegion.Size = Dyn.getVal();
2098
DynRelrRegion.SizePrintName = Dyn.d_tag == ELF::DT_RELRSZ
2099
? "DT_RELRSZ value"
2100
: "DT_ANDROID_RELRSZ value";
2101
break;
2102
case ELF::DT_RELRENT:
2103
case ELF::DT_ANDROID_RELRENT:
2104
case ELF::DT_AARCH64_AUTH_RELRENT:
2105
DynRelrRegion.EntSize = Dyn.getVal();
2106
DynRelrRegion.EntSizePrintName = Dyn.d_tag == ELF::DT_RELRENT
2107
? "DT_RELRENT value"
2108
: "DT_ANDROID_RELRENT value";
2109
break;
2110
case ELF::DT_PLTREL:
2111
if (Dyn.getVal() == DT_REL)
2112
DynPLTRelRegion.EntSize = sizeof(Elf_Rel);
2113
else if (Dyn.getVal() == DT_RELA)
2114
DynPLTRelRegion.EntSize = sizeof(Elf_Rela);
2115
else if (Dyn.getVal() == DT_CREL)
2116
DynPLTRelRegion.EntSize = 1;
2117
else
2118
reportUniqueWarning(Twine("unknown DT_PLTREL value of ") +
2119
Twine((uint64_t)Dyn.getVal()));
2120
DynPLTRelRegion.EntSizePrintName = "PLTREL entry size";
2121
break;
2122
case ELF::DT_JMPREL:
2123
DynPLTRelRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());
2124
break;
2125
case ELF::DT_PLTRELSZ:
2126
DynPLTRelRegion.Size = Dyn.getVal();
2127
DynPLTRelRegion.SizePrintName = "DT_PLTRELSZ value";
2128
break;
2129
case ELF::DT_SYMTAB_SHNDX:
2130
DynSymTabShndxRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());
2131
DynSymTabShndxRegion.EntSize = sizeof(Elf_Word);
2132
break;
2133
}
2134
}
2135
2136
if (StringTableBegin) {
2137
const uint64_t FileSize = Obj.getBufSize();
2138
const uint64_t Offset = (const uint8_t *)StringTableBegin - Obj.base();
2139
if (StringTableSize > FileSize - Offset)
2140
reportUniqueWarning(
2141
"the dynamic string table at 0x" + Twine::utohexstr(Offset) +
2142
" goes past the end of the file (0x" + Twine::utohexstr(FileSize) +
2143
") with DT_STRSZ = 0x" + Twine::utohexstr(StringTableSize));
2144
else
2145
DynamicStringTable = StringRef(StringTableBegin, StringTableSize);
2146
}
2147
2148
const bool IsHashTableSupported = getHashTableEntSize() == 4;
2149
if (DynSymRegion) {
2150
// Often we find the information about the dynamic symbol table
2151
// location in the SHT_DYNSYM section header. However, the value in
2152
// DT_SYMTAB has priority, because it is used by dynamic loaders to
2153
// locate .dynsym at runtime. The location we find in the section header
2154
// and the location we find here should match.
2155
if (DynSymFromTable && DynSymFromTable->Addr != DynSymRegion->Addr)
2156
reportUniqueWarning(
2157
createError("SHT_DYNSYM section header and DT_SYMTAB disagree about "
2158
"the location of the dynamic symbol table"));
2159
2160
// According to the ELF gABI: "The number of symbol table entries should
2161
// equal nchain". Check to see if the DT_HASH hash table nchain value
2162
// conflicts with the number of symbols in the dynamic symbol table
2163
// according to the section header.
2164
if (HashTable && IsHashTableSupported) {
2165
if (DynSymRegion->EntSize == 0)
2166
reportUniqueWarning("SHT_DYNSYM section has sh_entsize == 0");
2167
else if (HashTable->nchain != DynSymRegion->Size / DynSymRegion->EntSize)
2168
reportUniqueWarning(
2169
"hash table nchain (" + Twine(HashTable->nchain) +
2170
") differs from symbol count derived from SHT_DYNSYM section "
2171
"header (" +
2172
Twine(DynSymRegion->Size / DynSymRegion->EntSize) + ")");
2173
}
2174
}
2175
2176
// Delay the creation of the actual dynamic symbol table until now, so that
2177
// checks can always be made against the section header-based properties,
2178
// without worrying about tag order.
2179
if (DynSymFromTable) {
2180
if (!DynSymRegion) {
2181
DynSymRegion = DynSymFromTable;
2182
} else {
2183
DynSymRegion->Addr = DynSymFromTable->Addr;
2184
DynSymRegion->EntSize = DynSymFromTable->EntSize;
2185
DynSymRegion->EntSizePrintName = DynSymFromTable->EntSizePrintName;
2186
}
2187
}
2188
2189
// Derive the dynamic symbol table size from the DT_HASH hash table, if
2190
// present.
2191
if (HashTable && IsHashTableSupported && DynSymRegion) {
2192
const uint64_t FileSize = Obj.getBufSize();
2193
const uint64_t DerivedSize =
2194
(uint64_t)HashTable->nchain * DynSymRegion->EntSize;
2195
const uint64_t Offset = (const uint8_t *)DynSymRegion->Addr - Obj.base();
2196
if (DerivedSize > FileSize - Offset)
2197
reportUniqueWarning(
2198
"the size (0x" + Twine::utohexstr(DerivedSize) +
2199
") of the dynamic symbol table at 0x" + Twine::utohexstr(Offset) +
2200
", derived from the hash table, goes past the end of the file (0x" +
2201
Twine::utohexstr(FileSize) + ") and will be ignored");
2202
else
2203
DynSymRegion->Size = HashTable->nchain * DynSymRegion->EntSize;
2204
}
2205
}
2206
2207
template <typename ELFT> void ELFDumper<ELFT>::printVersionInfo() {
2208
// Dump version symbol section.
2209
printVersionSymbolSection(SymbolVersionSection);
2210
2211
// Dump version definition section.
2212
printVersionDefinitionSection(SymbolVersionDefSection);
2213
2214
// Dump version dependency section.
2215
printVersionDependencySection(SymbolVersionNeedSection);
2216
}
2217
2218
#define LLVM_READOBJ_DT_FLAG_ENT(prefix, enum) \
2219
{ #enum, prefix##_##enum }
2220
2221
const EnumEntry<unsigned> ElfDynamicDTFlags[] = {
2222
LLVM_READOBJ_DT_FLAG_ENT(DF, ORIGIN),
2223
LLVM_READOBJ_DT_FLAG_ENT(DF, SYMBOLIC),
2224
LLVM_READOBJ_DT_FLAG_ENT(DF, TEXTREL),
2225
LLVM_READOBJ_DT_FLAG_ENT(DF, BIND_NOW),
2226
LLVM_READOBJ_DT_FLAG_ENT(DF, STATIC_TLS)
2227
};
2228
2229
const EnumEntry<unsigned> ElfDynamicDTFlags1[] = {
2230
LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOW),
2231
LLVM_READOBJ_DT_FLAG_ENT(DF_1, GLOBAL),
2232
LLVM_READOBJ_DT_FLAG_ENT(DF_1, GROUP),
2233
LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODELETE),
2234
LLVM_READOBJ_DT_FLAG_ENT(DF_1, LOADFLTR),
2235
LLVM_READOBJ_DT_FLAG_ENT(DF_1, INITFIRST),
2236
LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOOPEN),
2237
LLVM_READOBJ_DT_FLAG_ENT(DF_1, ORIGIN),
2238
LLVM_READOBJ_DT_FLAG_ENT(DF_1, DIRECT),
2239
LLVM_READOBJ_DT_FLAG_ENT(DF_1, TRANS),
2240
LLVM_READOBJ_DT_FLAG_ENT(DF_1, INTERPOSE),
2241
LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODEFLIB),
2242
LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODUMP),
2243
LLVM_READOBJ_DT_FLAG_ENT(DF_1, CONFALT),
2244
LLVM_READOBJ_DT_FLAG_ENT(DF_1, ENDFILTEE),
2245
LLVM_READOBJ_DT_FLAG_ENT(DF_1, DISPRELDNE),
2246
LLVM_READOBJ_DT_FLAG_ENT(DF_1, DISPRELPND),
2247
LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODIRECT),
2248
LLVM_READOBJ_DT_FLAG_ENT(DF_1, IGNMULDEF),
2249
LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOKSYMS),
2250
LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOHDR),
2251
LLVM_READOBJ_DT_FLAG_ENT(DF_1, EDITED),
2252
LLVM_READOBJ_DT_FLAG_ENT(DF_1, NORELOC),
2253
LLVM_READOBJ_DT_FLAG_ENT(DF_1, SYMINTPOSE),
2254
LLVM_READOBJ_DT_FLAG_ENT(DF_1, GLOBAUDIT),
2255
LLVM_READOBJ_DT_FLAG_ENT(DF_1, SINGLETON),
2256
LLVM_READOBJ_DT_FLAG_ENT(DF_1, PIE),
2257
};
2258
2259
const EnumEntry<unsigned> ElfDynamicDTMipsFlags[] = {
2260
LLVM_READOBJ_DT_FLAG_ENT(RHF, NONE),
2261
LLVM_READOBJ_DT_FLAG_ENT(RHF, QUICKSTART),
2262
LLVM_READOBJ_DT_FLAG_ENT(RHF, NOTPOT),
2263
LLVM_READOBJ_DT_FLAG_ENT(RHS, NO_LIBRARY_REPLACEMENT),
2264
LLVM_READOBJ_DT_FLAG_ENT(RHF, NO_MOVE),
2265
LLVM_READOBJ_DT_FLAG_ENT(RHF, SGI_ONLY),
2266
LLVM_READOBJ_DT_FLAG_ENT(RHF, GUARANTEE_INIT),
2267
LLVM_READOBJ_DT_FLAG_ENT(RHF, DELTA_C_PLUS_PLUS),
2268
LLVM_READOBJ_DT_FLAG_ENT(RHF, GUARANTEE_START_INIT),
2269
LLVM_READOBJ_DT_FLAG_ENT(RHF, PIXIE),
2270
LLVM_READOBJ_DT_FLAG_ENT(RHF, DEFAULT_DELAY_LOAD),
2271
LLVM_READOBJ_DT_FLAG_ENT(RHF, REQUICKSTART),
2272
LLVM_READOBJ_DT_FLAG_ENT(RHF, REQUICKSTARTED),
2273
LLVM_READOBJ_DT_FLAG_ENT(RHF, CORD),
2274
LLVM_READOBJ_DT_FLAG_ENT(RHF, NO_UNRES_UNDEF),
2275
LLVM_READOBJ_DT_FLAG_ENT(RHF, RLD_ORDER_SAFE)
2276
};
2277
2278
#undef LLVM_READOBJ_DT_FLAG_ENT
2279
2280
template <typename T, typename TFlag>
2281
void printFlags(T Value, ArrayRef<EnumEntry<TFlag>> Flags, raw_ostream &OS) {
2282
SmallVector<EnumEntry<TFlag>, 10> SetFlags;
2283
for (const EnumEntry<TFlag> &Flag : Flags)
2284
if (Flag.Value != 0 && (Value & Flag.Value) == Flag.Value)
2285
SetFlags.push_back(Flag);
2286
2287
for (const EnumEntry<TFlag> &Flag : SetFlags)
2288
OS << Flag.Name << " ";
2289
}
2290
2291
template <class ELFT>
2292
const typename ELFT::Shdr *
2293
ELFDumper<ELFT>::findSectionByName(StringRef Name) const {
2294
for (const Elf_Shdr &Shdr : cantFail(Obj.sections())) {
2295
if (Expected<StringRef> NameOrErr = Obj.getSectionName(Shdr)) {
2296
if (*NameOrErr == Name)
2297
return &Shdr;
2298
} else {
2299
reportUniqueWarning("unable to read the name of " + describe(Shdr) +
2300
": " + toString(NameOrErr.takeError()));
2301
}
2302
}
2303
return nullptr;
2304
}
2305
2306
template <class ELFT>
2307
std::string ELFDumper<ELFT>::getDynamicEntry(uint64_t Type,
2308
uint64_t Value) const {
2309
auto FormatHexValue = [](uint64_t V) {
2310
std::string Str;
2311
raw_string_ostream OS(Str);
2312
const char *ConvChar =
2313
(opts::Output == opts::GNU) ? "0x%" PRIx64 : "0x%" PRIX64;
2314
OS << format(ConvChar, V);
2315
return OS.str();
2316
};
2317
2318
auto FormatFlags = [](uint64_t V,
2319
llvm::ArrayRef<llvm::EnumEntry<unsigned int>> Array) {
2320
std::string Str;
2321
raw_string_ostream OS(Str);
2322
printFlags(V, Array, OS);
2323
return OS.str();
2324
};
2325
2326
// Handle custom printing of architecture specific tags
2327
switch (Obj.getHeader().e_machine) {
2328
case EM_AARCH64:
2329
switch (Type) {
2330
case DT_AARCH64_BTI_PLT:
2331
case DT_AARCH64_PAC_PLT:
2332
case DT_AARCH64_VARIANT_PCS:
2333
case DT_AARCH64_MEMTAG_GLOBALSSZ:
2334
return std::to_string(Value);
2335
case DT_AARCH64_MEMTAG_MODE:
2336
switch (Value) {
2337
case 0:
2338
return "Synchronous (0)";
2339
case 1:
2340
return "Asynchronous (1)";
2341
default:
2342
return (Twine("Unknown (") + Twine(Value) + ")").str();
2343
}
2344
case DT_AARCH64_MEMTAG_HEAP:
2345
case DT_AARCH64_MEMTAG_STACK:
2346
switch (Value) {
2347
case 0:
2348
return "Disabled (0)";
2349
case 1:
2350
return "Enabled (1)";
2351
default:
2352
return (Twine("Unknown (") + Twine(Value) + ")").str();
2353
}
2354
case DT_AARCH64_MEMTAG_GLOBALS:
2355
return (Twine("0x") + utohexstr(Value, /*LowerCase=*/true)).str();
2356
default:
2357
break;
2358
}
2359
break;
2360
case EM_HEXAGON:
2361
switch (Type) {
2362
case DT_HEXAGON_VER:
2363
return std::to_string(Value);
2364
case DT_HEXAGON_SYMSZ:
2365
case DT_HEXAGON_PLT:
2366
return FormatHexValue(Value);
2367
default:
2368
break;
2369
}
2370
break;
2371
case EM_MIPS:
2372
switch (Type) {
2373
case DT_MIPS_RLD_VERSION:
2374
case DT_MIPS_LOCAL_GOTNO:
2375
case DT_MIPS_SYMTABNO:
2376
case DT_MIPS_UNREFEXTNO:
2377
return std::to_string(Value);
2378
case DT_MIPS_TIME_STAMP:
2379
case DT_MIPS_ICHECKSUM:
2380
case DT_MIPS_IVERSION:
2381
case DT_MIPS_BASE_ADDRESS:
2382
case DT_MIPS_MSYM:
2383
case DT_MIPS_CONFLICT:
2384
case DT_MIPS_LIBLIST:
2385
case DT_MIPS_CONFLICTNO:
2386
case DT_MIPS_LIBLISTNO:
2387
case DT_MIPS_GOTSYM:
2388
case DT_MIPS_HIPAGENO:
2389
case DT_MIPS_RLD_MAP:
2390
case DT_MIPS_DELTA_CLASS:
2391
case DT_MIPS_DELTA_CLASS_NO:
2392
case DT_MIPS_DELTA_INSTANCE:
2393
case DT_MIPS_DELTA_RELOC:
2394
case DT_MIPS_DELTA_RELOC_NO:
2395
case DT_MIPS_DELTA_SYM:
2396
case DT_MIPS_DELTA_SYM_NO:
2397
case DT_MIPS_DELTA_CLASSSYM:
2398
case DT_MIPS_DELTA_CLASSSYM_NO:
2399
case DT_MIPS_CXX_FLAGS:
2400
case DT_MIPS_PIXIE_INIT:
2401
case DT_MIPS_SYMBOL_LIB:
2402
case DT_MIPS_LOCALPAGE_GOTIDX:
2403
case DT_MIPS_LOCAL_GOTIDX:
2404
case DT_MIPS_HIDDEN_GOTIDX:
2405
case DT_MIPS_PROTECTED_GOTIDX:
2406
case DT_MIPS_OPTIONS:
2407
case DT_MIPS_INTERFACE:
2408
case DT_MIPS_DYNSTR_ALIGN:
2409
case DT_MIPS_INTERFACE_SIZE:
2410
case DT_MIPS_RLD_TEXT_RESOLVE_ADDR:
2411
case DT_MIPS_PERF_SUFFIX:
2412
case DT_MIPS_COMPACT_SIZE:
2413
case DT_MIPS_GP_VALUE:
2414
case DT_MIPS_AUX_DYNAMIC:
2415
case DT_MIPS_PLTGOT:
2416
case DT_MIPS_RWPLT:
2417
case DT_MIPS_RLD_MAP_REL:
2418
case DT_MIPS_XHASH:
2419
return FormatHexValue(Value);
2420
case DT_MIPS_FLAGS:
2421
return FormatFlags(Value, ArrayRef(ElfDynamicDTMipsFlags));
2422
default:
2423
break;
2424
}
2425
break;
2426
default:
2427
break;
2428
}
2429
2430
switch (Type) {
2431
case DT_PLTREL:
2432
if (Value == DT_REL)
2433
return "REL";
2434
if (Value == DT_RELA)
2435
return "RELA";
2436
if (Value == DT_CREL)
2437
return "CREL";
2438
[[fallthrough]];
2439
case DT_PLTGOT:
2440
case DT_HASH:
2441
case DT_STRTAB:
2442
case DT_SYMTAB:
2443
case DT_RELA:
2444
case DT_INIT:
2445
case DT_FINI:
2446
case DT_REL:
2447
case DT_JMPREL:
2448
case DT_INIT_ARRAY:
2449
case DT_FINI_ARRAY:
2450
case DT_PREINIT_ARRAY:
2451
case DT_DEBUG:
2452
case DT_CREL:
2453
case DT_VERDEF:
2454
case DT_VERNEED:
2455
case DT_VERSYM:
2456
case DT_GNU_HASH:
2457
case DT_NULL:
2458
return FormatHexValue(Value);
2459
case DT_RELACOUNT:
2460
case DT_RELCOUNT:
2461
case DT_VERDEFNUM:
2462
case DT_VERNEEDNUM:
2463
return std::to_string(Value);
2464
case DT_PLTRELSZ:
2465
case DT_RELASZ:
2466
case DT_RELAENT:
2467
case DT_STRSZ:
2468
case DT_SYMENT:
2469
case DT_RELSZ:
2470
case DT_RELENT:
2471
case DT_INIT_ARRAYSZ:
2472
case DT_FINI_ARRAYSZ:
2473
case DT_PREINIT_ARRAYSZ:
2474
case DT_RELRSZ:
2475
case DT_RELRENT:
2476
case DT_AARCH64_AUTH_RELRSZ:
2477
case DT_AARCH64_AUTH_RELRENT:
2478
case DT_ANDROID_RELSZ:
2479
case DT_ANDROID_RELASZ:
2480
return std::to_string(Value) + " (bytes)";
2481
case DT_NEEDED:
2482
case DT_SONAME:
2483
case DT_AUXILIARY:
2484
case DT_USED:
2485
case DT_FILTER:
2486
case DT_RPATH:
2487
case DT_RUNPATH: {
2488
const std::map<uint64_t, const char *> TagNames = {
2489
{DT_NEEDED, "Shared library"}, {DT_SONAME, "Library soname"},
2490
{DT_AUXILIARY, "Auxiliary library"}, {DT_USED, "Not needed object"},
2491
{DT_FILTER, "Filter library"}, {DT_RPATH, "Library rpath"},
2492
{DT_RUNPATH, "Library runpath"},
2493
};
2494
2495
return (Twine(TagNames.at(Type)) + ": [" + getDynamicString(Value) + "]")
2496
.str();
2497
}
2498
case DT_FLAGS:
2499
return FormatFlags(Value, ArrayRef(ElfDynamicDTFlags));
2500
case DT_FLAGS_1:
2501
return FormatFlags(Value, ArrayRef(ElfDynamicDTFlags1));
2502
default:
2503
return FormatHexValue(Value);
2504
}
2505
}
2506
2507
template <class ELFT>
2508
StringRef ELFDumper<ELFT>::getDynamicString(uint64_t Value) const {
2509
if (DynamicStringTable.empty() && !DynamicStringTable.data()) {
2510
reportUniqueWarning("string table was not found");
2511
return "<?>";
2512
}
2513
2514
auto WarnAndReturn = [this](const Twine &Msg, uint64_t Offset) {
2515
reportUniqueWarning("string table at offset 0x" + Twine::utohexstr(Offset) +
2516
Msg);
2517
return "<?>";
2518
};
2519
2520
const uint64_t FileSize = Obj.getBufSize();
2521
const uint64_t Offset =
2522
(const uint8_t *)DynamicStringTable.data() - Obj.base();
2523
if (DynamicStringTable.size() > FileSize - Offset)
2524
return WarnAndReturn(" with size 0x" +
2525
Twine::utohexstr(DynamicStringTable.size()) +
2526
" goes past the end of the file (0x" +
2527
Twine::utohexstr(FileSize) + ")",
2528
Offset);
2529
2530
if (Value >= DynamicStringTable.size())
2531
return WarnAndReturn(
2532
": unable to read the string at 0x" + Twine::utohexstr(Offset + Value) +
2533
": it goes past the end of the table (0x" +
2534
Twine::utohexstr(Offset + DynamicStringTable.size()) + ")",
2535
Offset);
2536
2537
if (DynamicStringTable.back() != '\0')
2538
return WarnAndReturn(": unable to read the string at 0x" +
2539
Twine::utohexstr(Offset + Value) +
2540
": the string table is not null-terminated",
2541
Offset);
2542
2543
return DynamicStringTable.data() + Value;
2544
}
2545
2546
template <class ELFT> void ELFDumper<ELFT>::printUnwindInfo() {
2547
DwarfCFIEH::PrinterContext<ELFT> Ctx(W, ObjF);
2548
Ctx.printUnwindInformation();
2549
}
2550
2551
// The namespace is needed to fix the compilation with GCC older than 7.0+.
2552
namespace {
2553
template <> void ELFDumper<ELF32LE>::printUnwindInfo() {
2554
if (Obj.getHeader().e_machine == EM_ARM) {
2555
ARM::EHABI::PrinterContext<ELF32LE> Ctx(W, Obj, ObjF.getFileName(),
2556
DotSymtabSec);
2557
Ctx.PrintUnwindInformation();
2558
}
2559
DwarfCFIEH::PrinterContext<ELF32LE> Ctx(W, ObjF);
2560
Ctx.printUnwindInformation();
2561
}
2562
} // namespace
2563
2564
template <class ELFT> void ELFDumper<ELFT>::printNeededLibraries() {
2565
ListScope D(W, "NeededLibraries");
2566
2567
std::vector<StringRef> Libs;
2568
for (const auto &Entry : dynamic_table())
2569
if (Entry.d_tag == ELF::DT_NEEDED)
2570
Libs.push_back(getDynamicString(Entry.d_un.d_val));
2571
2572
llvm::sort(Libs);
2573
2574
for (StringRef L : Libs)
2575
W.printString(L);
2576
}
2577
2578
template <class ELFT>
2579
static Error checkHashTable(const ELFDumper<ELFT> &Dumper,
2580
const typename ELFT::Hash *H,
2581
bool *IsHeaderValid = nullptr) {
2582
const ELFFile<ELFT> &Obj = Dumper.getElfObject().getELFFile();
2583
const uint64_t SecOffset = (const uint8_t *)H - Obj.base();
2584
if (Dumper.getHashTableEntSize() == 8) {
2585
auto It = llvm::find_if(ElfMachineType, [&](const EnumEntry<unsigned> &E) {
2586
return E.Value == Obj.getHeader().e_machine;
2587
});
2588
if (IsHeaderValid)
2589
*IsHeaderValid = false;
2590
return createError("the hash table at 0x" + Twine::utohexstr(SecOffset) +
2591
" is not supported: it contains non-standard 8 "
2592
"byte entries on " +
2593
It->AltName + " platform");
2594
}
2595
2596
auto MakeError = [&](const Twine &Msg = "") {
2597
return createError("the hash table at offset 0x" +
2598
Twine::utohexstr(SecOffset) +
2599
" goes past the end of the file (0x" +
2600
Twine::utohexstr(Obj.getBufSize()) + ")" + Msg);
2601
};
2602
2603
// Each SHT_HASH section starts from two 32-bit fields: nbucket and nchain.
2604
const unsigned HeaderSize = 2 * sizeof(typename ELFT::Word);
2605
2606
if (IsHeaderValid)
2607
*IsHeaderValid = Obj.getBufSize() - SecOffset >= HeaderSize;
2608
2609
if (Obj.getBufSize() - SecOffset < HeaderSize)
2610
return MakeError();
2611
2612
if (Obj.getBufSize() - SecOffset - HeaderSize <
2613
((uint64_t)H->nbucket + H->nchain) * sizeof(typename ELFT::Word))
2614
return MakeError(", nbucket = " + Twine(H->nbucket) +
2615
", nchain = " + Twine(H->nchain));
2616
return Error::success();
2617
}
2618
2619
template <class ELFT>
2620
static Error checkGNUHashTable(const ELFFile<ELFT> &Obj,
2621
const typename ELFT::GnuHash *GnuHashTable,
2622
bool *IsHeaderValid = nullptr) {
2623
const uint8_t *TableData = reinterpret_cast<const uint8_t *>(GnuHashTable);
2624
assert(TableData >= Obj.base() && TableData < Obj.base() + Obj.getBufSize() &&
2625
"GnuHashTable must always point to a location inside the file");
2626
2627
uint64_t TableOffset = TableData - Obj.base();
2628
if (IsHeaderValid)
2629
*IsHeaderValid = TableOffset + /*Header size:*/ 16 < Obj.getBufSize();
2630
if (TableOffset + 16 + (uint64_t)GnuHashTable->nbuckets * 4 +
2631
(uint64_t)GnuHashTable->maskwords * sizeof(typename ELFT::Off) >=
2632
Obj.getBufSize())
2633
return createError("unable to dump the SHT_GNU_HASH "
2634
"section at 0x" +
2635
Twine::utohexstr(TableOffset) +
2636
": it goes past the end of the file");
2637
return Error::success();
2638
}
2639
2640
template <typename ELFT> void ELFDumper<ELFT>::printHashTable() {
2641
DictScope D(W, "HashTable");
2642
if (!HashTable)
2643
return;
2644
2645
bool IsHeaderValid;
2646
Error Err = checkHashTable(*this, HashTable, &IsHeaderValid);
2647
if (IsHeaderValid) {
2648
W.printNumber("Num Buckets", HashTable->nbucket);
2649
W.printNumber("Num Chains", HashTable->nchain);
2650
}
2651
2652
if (Err) {
2653
reportUniqueWarning(std::move(Err));
2654
return;
2655
}
2656
2657
W.printList("Buckets", HashTable->buckets());
2658
W.printList("Chains", HashTable->chains());
2659
}
2660
2661
template <class ELFT>
2662
static Expected<ArrayRef<typename ELFT::Word>>
2663
getGnuHashTableChains(std::optional<DynRegionInfo> DynSymRegion,
2664
const typename ELFT::GnuHash *GnuHashTable) {
2665
if (!DynSymRegion)
2666
return createError("no dynamic symbol table found");
2667
2668
ArrayRef<typename ELFT::Sym> DynSymTable =
2669
DynSymRegion->template getAsArrayRef<typename ELFT::Sym>();
2670
size_t NumSyms = DynSymTable.size();
2671
if (!NumSyms)
2672
return createError("the dynamic symbol table is empty");
2673
2674
if (GnuHashTable->symndx < NumSyms)
2675
return GnuHashTable->values(NumSyms);
2676
2677
// A normal empty GNU hash table section produced by linker might have
2678
// symndx set to the number of dynamic symbols + 1 (for the zero symbol)
2679
// and have dummy null values in the Bloom filter and in the buckets
2680
// vector (or no values at all). It happens because the value of symndx is not
2681
// important for dynamic loaders when the GNU hash table is empty. They just
2682
// skip the whole object during symbol lookup. In such cases, the symndx value
2683
// is irrelevant and we should not report a warning.
2684
ArrayRef<typename ELFT::Word> Buckets = GnuHashTable->buckets();
2685
if (!llvm::all_of(Buckets, [](typename ELFT::Word V) { return V == 0; }))
2686
return createError(
2687
"the first hashed symbol index (" + Twine(GnuHashTable->symndx) +
2688
") is greater than or equal to the number of dynamic symbols (" +
2689
Twine(NumSyms) + ")");
2690
// There is no way to represent an array of (dynamic symbols count - symndx)
2691
// length.
2692
return ArrayRef<typename ELFT::Word>();
2693
}
2694
2695
template <typename ELFT>
2696
void ELFDumper<ELFT>::printGnuHashTable() {
2697
DictScope D(W, "GnuHashTable");
2698
if (!GnuHashTable)
2699
return;
2700
2701
bool IsHeaderValid;
2702
Error Err = checkGNUHashTable<ELFT>(Obj, GnuHashTable, &IsHeaderValid);
2703
if (IsHeaderValid) {
2704
W.printNumber("Num Buckets", GnuHashTable->nbuckets);
2705
W.printNumber("First Hashed Symbol Index", GnuHashTable->symndx);
2706
W.printNumber("Num Mask Words", GnuHashTable->maskwords);
2707
W.printNumber("Shift Count", GnuHashTable->shift2);
2708
}
2709
2710
if (Err) {
2711
reportUniqueWarning(std::move(Err));
2712
return;
2713
}
2714
2715
ArrayRef<typename ELFT::Off> BloomFilter = GnuHashTable->filter();
2716
W.printHexList("Bloom Filter", BloomFilter);
2717
2718
ArrayRef<Elf_Word> Buckets = GnuHashTable->buckets();
2719
W.printList("Buckets", Buckets);
2720
2721
Expected<ArrayRef<Elf_Word>> Chains =
2722
getGnuHashTableChains<ELFT>(DynSymRegion, GnuHashTable);
2723
if (!Chains) {
2724
reportUniqueWarning("unable to dump 'Values' for the SHT_GNU_HASH "
2725
"section: " +
2726
toString(Chains.takeError()));
2727
return;
2728
}
2729
2730
W.printHexList("Values", *Chains);
2731
}
2732
2733
template <typename ELFT> void ELFDumper<ELFT>::printHashHistograms() {
2734
// Print histogram for the .hash section.
2735
if (this->HashTable) {
2736
if (Error E = checkHashTable<ELFT>(*this, this->HashTable))
2737
this->reportUniqueWarning(std::move(E));
2738
else
2739
printHashHistogram(*this->HashTable);
2740
}
2741
2742
// Print histogram for the .gnu.hash section.
2743
if (this->GnuHashTable) {
2744
if (Error E = checkGNUHashTable<ELFT>(this->Obj, this->GnuHashTable))
2745
this->reportUniqueWarning(std::move(E));
2746
else
2747
printGnuHashHistogram(*this->GnuHashTable);
2748
}
2749
}
2750
2751
template <typename ELFT>
2752
void ELFDumper<ELFT>::printHashHistogram(const Elf_Hash &HashTable) const {
2753
size_t NBucket = HashTable.nbucket;
2754
size_t NChain = HashTable.nchain;
2755
ArrayRef<Elf_Word> Buckets = HashTable.buckets();
2756
ArrayRef<Elf_Word> Chains = HashTable.chains();
2757
size_t TotalSyms = 0;
2758
// If hash table is correct, we have at least chains with 0 length.
2759
size_t MaxChain = 1;
2760
2761
if (NChain == 0 || NBucket == 0)
2762
return;
2763
2764
std::vector<size_t> ChainLen(NBucket, 0);
2765
// Go over all buckets and note chain lengths of each bucket (total
2766
// unique chain lengths).
2767
for (size_t B = 0; B < NBucket; ++B) {
2768
BitVector Visited(NChain);
2769
for (size_t C = Buckets[B]; C < NChain; C = Chains[C]) {
2770
if (C == ELF::STN_UNDEF)
2771
break;
2772
if (Visited[C]) {
2773
this->reportUniqueWarning(
2774
".hash section is invalid: bucket " + Twine(C) +
2775
": a cycle was detected in the linked chain");
2776
break;
2777
}
2778
Visited[C] = true;
2779
if (MaxChain <= ++ChainLen[B])
2780
++MaxChain;
2781
}
2782
TotalSyms += ChainLen[B];
2783
}
2784
2785
if (!TotalSyms)
2786
return;
2787
2788
std::vector<size_t> Count(MaxChain, 0);
2789
// Count how long is the chain for each bucket.
2790
for (size_t B = 0; B < NBucket; B++)
2791
++Count[ChainLen[B]];
2792
// Print Number of buckets with each chain lengths and their cumulative
2793
// coverage of the symbols.
2794
printHashHistogramStats(NBucket, MaxChain, TotalSyms, Count, /*IsGnu=*/false);
2795
}
2796
2797
template <class ELFT>
2798
void ELFDumper<ELFT>::printGnuHashHistogram(
2799
const Elf_GnuHash &GnuHashTable) const {
2800
Expected<ArrayRef<Elf_Word>> ChainsOrErr =
2801
getGnuHashTableChains<ELFT>(this->DynSymRegion, &GnuHashTable);
2802
if (!ChainsOrErr) {
2803
this->reportUniqueWarning("unable to print the GNU hash table histogram: " +
2804
toString(ChainsOrErr.takeError()));
2805
return;
2806
}
2807
2808
ArrayRef<Elf_Word> Chains = *ChainsOrErr;
2809
size_t Symndx = GnuHashTable.symndx;
2810
size_t TotalSyms = 0;
2811
size_t MaxChain = 1;
2812
2813
size_t NBucket = GnuHashTable.nbuckets;
2814
if (Chains.empty() || NBucket == 0)
2815
return;
2816
2817
ArrayRef<Elf_Word> Buckets = GnuHashTable.buckets();
2818
std::vector<size_t> ChainLen(NBucket, 0);
2819
for (size_t B = 0; B < NBucket; ++B) {
2820
if (!Buckets[B])
2821
continue;
2822
size_t Len = 1;
2823
for (size_t C = Buckets[B] - Symndx;
2824
C < Chains.size() && (Chains[C] & 1) == 0; ++C)
2825
if (MaxChain < ++Len)
2826
++MaxChain;
2827
ChainLen[B] = Len;
2828
TotalSyms += Len;
2829
}
2830
++MaxChain;
2831
2832
if (!TotalSyms)
2833
return;
2834
2835
std::vector<size_t> Count(MaxChain, 0);
2836
for (size_t B = 0; B < NBucket; ++B)
2837
++Count[ChainLen[B]];
2838
// Print Number of buckets with each chain lengths and their cumulative
2839
// coverage of the symbols.
2840
printHashHistogramStats(NBucket, MaxChain, TotalSyms, Count, /*IsGnu=*/true);
2841
}
2842
2843
template <typename ELFT> void ELFDumper<ELFT>::printLoadName() {
2844
StringRef SOName = "<Not found>";
2845
if (SONameOffset)
2846
SOName = getDynamicString(*SONameOffset);
2847
W.printString("LoadName", SOName);
2848
}
2849
2850
template <class ELFT> void ELFDumper<ELFT>::printArchSpecificInfo() {
2851
switch (Obj.getHeader().e_machine) {
2852
case EM_HEXAGON:
2853
printAttributes(ELF::SHT_HEXAGON_ATTRIBUTES,
2854
std::make_unique<HexagonAttributeParser>(&W),
2855
llvm::endianness::little);
2856
break;
2857
case EM_ARM:
2858
printAttributes(
2859
ELF::SHT_ARM_ATTRIBUTES, std::make_unique<ARMAttributeParser>(&W),
2860
Obj.isLE() ? llvm::endianness::little : llvm::endianness::big);
2861
break;
2862
case EM_RISCV:
2863
if (Obj.isLE())
2864
printAttributes(ELF::SHT_RISCV_ATTRIBUTES,
2865
std::make_unique<RISCVAttributeParser>(&W),
2866
llvm::endianness::little);
2867
else
2868
reportUniqueWarning("attribute printing not implemented for big-endian "
2869
"RISC-V objects");
2870
break;
2871
case EM_MSP430:
2872
printAttributes(ELF::SHT_MSP430_ATTRIBUTES,
2873
std::make_unique<MSP430AttributeParser>(&W),
2874
llvm::endianness::little);
2875
break;
2876
case EM_MIPS: {
2877
printMipsABIFlags();
2878
printMipsOptions();
2879
printMipsReginfo();
2880
MipsGOTParser<ELFT> Parser(*this);
2881
if (Error E = Parser.findGOT(dynamic_table(), dynamic_symbols()))
2882
reportUniqueWarning(std::move(E));
2883
else if (!Parser.isGotEmpty())
2884
printMipsGOT(Parser);
2885
2886
if (Error E = Parser.findPLT(dynamic_table()))
2887
reportUniqueWarning(std::move(E));
2888
else if (!Parser.isPltEmpty())
2889
printMipsPLT(Parser);
2890
break;
2891
}
2892
default:
2893
break;
2894
}
2895
}
2896
2897
template <class ELFT>
2898
void ELFDumper<ELFT>::printAttributes(
2899
unsigned AttrShType, std::unique_ptr<ELFAttributeParser> AttrParser,
2900
llvm::endianness Endianness) {
2901
assert((AttrShType != ELF::SHT_NULL) && AttrParser &&
2902
"Incomplete ELF attribute implementation");
2903
DictScope BA(W, "BuildAttributes");
2904
for (const Elf_Shdr &Sec : cantFail(Obj.sections())) {
2905
if (Sec.sh_type != AttrShType)
2906
continue;
2907
2908
ArrayRef<uint8_t> Contents;
2909
if (Expected<ArrayRef<uint8_t>> ContentOrErr =
2910
Obj.getSectionContents(Sec)) {
2911
Contents = *ContentOrErr;
2912
if (Contents.empty()) {
2913
reportUniqueWarning("the " + describe(Sec) + " is empty");
2914
continue;
2915
}
2916
} else {
2917
reportUniqueWarning("unable to read the content of the " + describe(Sec) +
2918
": " + toString(ContentOrErr.takeError()));
2919
continue;
2920
}
2921
2922
W.printHex("FormatVersion", Contents[0]);
2923
2924
if (Error E = AttrParser->parse(Contents, Endianness))
2925
reportUniqueWarning("unable to dump attributes from the " +
2926
describe(Sec) + ": " + toString(std::move(E)));
2927
}
2928
}
2929
2930
namespace {
2931
2932
template <class ELFT> class MipsGOTParser {
2933
public:
2934
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
2935
using Entry = typename ELFT::Addr;
2936
using Entries = ArrayRef<Entry>;
2937
2938
const bool IsStatic;
2939
const ELFFile<ELFT> &Obj;
2940
const ELFDumper<ELFT> &Dumper;
2941
2942
MipsGOTParser(const ELFDumper<ELFT> &D);
2943
Error findGOT(Elf_Dyn_Range DynTable, Elf_Sym_Range DynSyms);
2944
Error findPLT(Elf_Dyn_Range DynTable);
2945
2946
bool isGotEmpty() const { return GotEntries.empty(); }
2947
bool isPltEmpty() const { return PltEntries.empty(); }
2948
2949
uint64_t getGp() const;
2950
2951
const Entry *getGotLazyResolver() const;
2952
const Entry *getGotModulePointer() const;
2953
const Entry *getPltLazyResolver() const;
2954
const Entry *getPltModulePointer() const;
2955
2956
Entries getLocalEntries() const;
2957
Entries getGlobalEntries() const;
2958
Entries getOtherEntries() const;
2959
Entries getPltEntries() const;
2960
2961
uint64_t getGotAddress(const Entry * E) const;
2962
int64_t getGotOffset(const Entry * E) const;
2963
const Elf_Sym *getGotSym(const Entry *E) const;
2964
2965
uint64_t getPltAddress(const Entry * E) const;
2966
const Elf_Sym *getPltSym(const Entry *E) const;
2967
2968
StringRef getPltStrTable() const { return PltStrTable; }
2969
const Elf_Shdr *getPltSymTable() const { return PltSymTable; }
2970
2971
private:
2972
const Elf_Shdr *GotSec;
2973
size_t LocalNum;
2974
size_t GlobalNum;
2975
2976
const Elf_Shdr *PltSec;
2977
const Elf_Shdr *PltRelSec;
2978
const Elf_Shdr *PltSymTable;
2979
StringRef FileName;
2980
2981
Elf_Sym_Range GotDynSyms;
2982
StringRef PltStrTable;
2983
2984
Entries GotEntries;
2985
Entries PltEntries;
2986
};
2987
2988
} // end anonymous namespace
2989
2990
template <class ELFT>
2991
MipsGOTParser<ELFT>::MipsGOTParser(const ELFDumper<ELFT> &D)
2992
: IsStatic(D.dynamic_table().empty()), Obj(D.getElfObject().getELFFile()),
2993
Dumper(D), GotSec(nullptr), LocalNum(0), GlobalNum(0), PltSec(nullptr),
2994
PltRelSec(nullptr), PltSymTable(nullptr),
2995
FileName(D.getElfObject().getFileName()) {}
2996
2997
template <class ELFT>
2998
Error MipsGOTParser<ELFT>::findGOT(Elf_Dyn_Range DynTable,
2999
Elf_Sym_Range DynSyms) {
3000
// See "Global Offset Table" in Chapter 5 in the following document
3001
// for detailed GOT description.
3002
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
3003
3004
// Find static GOT secton.
3005
if (IsStatic) {
3006
GotSec = Dumper.findSectionByName(".got");
3007
if (!GotSec)
3008
return Error::success();
3009
3010
ArrayRef<uint8_t> Content =
3011
unwrapOrError(FileName, Obj.getSectionContents(*GotSec));
3012
GotEntries = Entries(reinterpret_cast<const Entry *>(Content.data()),
3013
Content.size() / sizeof(Entry));
3014
LocalNum = GotEntries.size();
3015
return Error::success();
3016
}
3017
3018
// Lookup dynamic table tags which define the GOT layout.
3019
std::optional<uint64_t> DtPltGot;
3020
std::optional<uint64_t> DtLocalGotNum;
3021
std::optional<uint64_t> DtGotSym;
3022
for (const auto &Entry : DynTable) {
3023
switch (Entry.getTag()) {
3024
case ELF::DT_PLTGOT:
3025
DtPltGot = Entry.getVal();
3026
break;
3027
case ELF::DT_MIPS_LOCAL_GOTNO:
3028
DtLocalGotNum = Entry.getVal();
3029
break;
3030
case ELF::DT_MIPS_GOTSYM:
3031
DtGotSym = Entry.getVal();
3032
break;
3033
}
3034
}
3035
3036
if (!DtPltGot && !DtLocalGotNum && !DtGotSym)
3037
return Error::success();
3038
3039
if (!DtPltGot)
3040
return createError("cannot find PLTGOT dynamic tag");
3041
if (!DtLocalGotNum)
3042
return createError("cannot find MIPS_LOCAL_GOTNO dynamic tag");
3043
if (!DtGotSym)
3044
return createError("cannot find MIPS_GOTSYM dynamic tag");
3045
3046
size_t DynSymTotal = DynSyms.size();
3047
if (*DtGotSym > DynSymTotal)
3048
return createError("DT_MIPS_GOTSYM value (" + Twine(*DtGotSym) +
3049
") exceeds the number of dynamic symbols (" +
3050
Twine(DynSymTotal) + ")");
3051
3052
GotSec = findNotEmptySectionByAddress(Obj, FileName, *DtPltGot);
3053
if (!GotSec)
3054
return createError("there is no non-empty GOT section at 0x" +
3055
Twine::utohexstr(*DtPltGot));
3056
3057
LocalNum = *DtLocalGotNum;
3058
GlobalNum = DynSymTotal - *DtGotSym;
3059
3060
ArrayRef<uint8_t> Content =
3061
unwrapOrError(FileName, Obj.getSectionContents(*GotSec));
3062
GotEntries = Entries(reinterpret_cast<const Entry *>(Content.data()),
3063
Content.size() / sizeof(Entry));
3064
GotDynSyms = DynSyms.drop_front(*DtGotSym);
3065
3066
return Error::success();
3067
}
3068
3069
template <class ELFT>
3070
Error MipsGOTParser<ELFT>::findPLT(Elf_Dyn_Range DynTable) {
3071
// Lookup dynamic table tags which define the PLT layout.
3072
std::optional<uint64_t> DtMipsPltGot;
3073
std::optional<uint64_t> DtJmpRel;
3074
for (const auto &Entry : DynTable) {
3075
switch (Entry.getTag()) {
3076
case ELF::DT_MIPS_PLTGOT:
3077
DtMipsPltGot = Entry.getVal();
3078
break;
3079
case ELF::DT_JMPREL:
3080
DtJmpRel = Entry.getVal();
3081
break;
3082
}
3083
}
3084
3085
if (!DtMipsPltGot && !DtJmpRel)
3086
return Error::success();
3087
3088
// Find PLT section.
3089
if (!DtMipsPltGot)
3090
return createError("cannot find MIPS_PLTGOT dynamic tag");
3091
if (!DtJmpRel)
3092
return createError("cannot find JMPREL dynamic tag");
3093
3094
PltSec = findNotEmptySectionByAddress(Obj, FileName, *DtMipsPltGot);
3095
if (!PltSec)
3096
return createError("there is no non-empty PLTGOT section at 0x" +
3097
Twine::utohexstr(*DtMipsPltGot));
3098
3099
PltRelSec = findNotEmptySectionByAddress(Obj, FileName, *DtJmpRel);
3100
if (!PltRelSec)
3101
return createError("there is no non-empty RELPLT section at 0x" +
3102
Twine::utohexstr(*DtJmpRel));
3103
3104
if (Expected<ArrayRef<uint8_t>> PltContentOrErr =
3105
Obj.getSectionContents(*PltSec))
3106
PltEntries =
3107
Entries(reinterpret_cast<const Entry *>(PltContentOrErr->data()),
3108
PltContentOrErr->size() / sizeof(Entry));
3109
else
3110
return createError("unable to read PLTGOT section content: " +
3111
toString(PltContentOrErr.takeError()));
3112
3113
if (Expected<const Elf_Shdr *> PltSymTableOrErr =
3114
Obj.getSection(PltRelSec->sh_link))
3115
PltSymTable = *PltSymTableOrErr;
3116
else
3117
return createError("unable to get a symbol table linked to the " +
3118
describe(Obj, *PltRelSec) + ": " +
3119
toString(PltSymTableOrErr.takeError()));
3120
3121
if (Expected<StringRef> StrTabOrErr =
3122
Obj.getStringTableForSymtab(*PltSymTable))
3123
PltStrTable = *StrTabOrErr;
3124
else
3125
return createError("unable to get a string table for the " +
3126
describe(Obj, *PltSymTable) + ": " +
3127
toString(StrTabOrErr.takeError()));
3128
3129
return Error::success();
3130
}
3131
3132
template <class ELFT> uint64_t MipsGOTParser<ELFT>::getGp() const {
3133
return GotSec->sh_addr + 0x7ff0;
3134
}
3135
3136
template <class ELFT>
3137
const typename MipsGOTParser<ELFT>::Entry *
3138
MipsGOTParser<ELFT>::getGotLazyResolver() const {
3139
return LocalNum > 0 ? &GotEntries[0] : nullptr;
3140
}
3141
3142
template <class ELFT>
3143
const typename MipsGOTParser<ELFT>::Entry *
3144
MipsGOTParser<ELFT>::getGotModulePointer() const {
3145
if (LocalNum < 2)
3146
return nullptr;
3147
const Entry &E = GotEntries[1];
3148
if ((E >> (sizeof(Entry) * 8 - 1)) == 0)
3149
return nullptr;
3150
return &E;
3151
}
3152
3153
template <class ELFT>
3154
typename MipsGOTParser<ELFT>::Entries
3155
MipsGOTParser<ELFT>::getLocalEntries() const {
3156
size_t Skip = getGotModulePointer() ? 2 : 1;
3157
if (LocalNum - Skip <= 0)
3158
return Entries();
3159
return GotEntries.slice(Skip, LocalNum - Skip);
3160
}
3161
3162
template <class ELFT>
3163
typename MipsGOTParser<ELFT>::Entries
3164
MipsGOTParser<ELFT>::getGlobalEntries() const {
3165
if (GlobalNum == 0)
3166
return Entries();
3167
return GotEntries.slice(LocalNum, GlobalNum);
3168
}
3169
3170
template <class ELFT>
3171
typename MipsGOTParser<ELFT>::Entries
3172
MipsGOTParser<ELFT>::getOtherEntries() const {
3173
size_t OtherNum = GotEntries.size() - LocalNum - GlobalNum;
3174
if (OtherNum == 0)
3175
return Entries();
3176
return GotEntries.slice(LocalNum + GlobalNum, OtherNum);
3177
}
3178
3179
template <class ELFT>
3180
uint64_t MipsGOTParser<ELFT>::getGotAddress(const Entry *E) const {
3181
int64_t Offset = std::distance(GotEntries.data(), E) * sizeof(Entry);
3182
return GotSec->sh_addr + Offset;
3183
}
3184
3185
template <class ELFT>
3186
int64_t MipsGOTParser<ELFT>::getGotOffset(const Entry *E) const {
3187
int64_t Offset = std::distance(GotEntries.data(), E) * sizeof(Entry);
3188
return Offset - 0x7ff0;
3189
}
3190
3191
template <class ELFT>
3192
const typename MipsGOTParser<ELFT>::Elf_Sym *
3193
MipsGOTParser<ELFT>::getGotSym(const Entry *E) const {
3194
int64_t Offset = std::distance(GotEntries.data(), E);
3195
return &GotDynSyms[Offset - LocalNum];
3196
}
3197
3198
template <class ELFT>
3199
const typename MipsGOTParser<ELFT>::Entry *
3200
MipsGOTParser<ELFT>::getPltLazyResolver() const {
3201
return PltEntries.empty() ? nullptr : &PltEntries[0];
3202
}
3203
3204
template <class ELFT>
3205
const typename MipsGOTParser<ELFT>::Entry *
3206
MipsGOTParser<ELFT>::getPltModulePointer() const {
3207
return PltEntries.size() < 2 ? nullptr : &PltEntries[1];
3208
}
3209
3210
template <class ELFT>
3211
typename MipsGOTParser<ELFT>::Entries
3212
MipsGOTParser<ELFT>::getPltEntries() const {
3213
if (PltEntries.size() <= 2)
3214
return Entries();
3215
return PltEntries.slice(2, PltEntries.size() - 2);
3216
}
3217
3218
template <class ELFT>
3219
uint64_t MipsGOTParser<ELFT>::getPltAddress(const Entry *E) const {
3220
int64_t Offset = std::distance(PltEntries.data(), E) * sizeof(Entry);
3221
return PltSec->sh_addr + Offset;
3222
}
3223
3224
template <class ELFT>
3225
const typename MipsGOTParser<ELFT>::Elf_Sym *
3226
MipsGOTParser<ELFT>::getPltSym(const Entry *E) const {
3227
int64_t Offset = std::distance(getPltEntries().data(), E);
3228
if (PltRelSec->sh_type == ELF::SHT_REL) {
3229
Elf_Rel_Range Rels = unwrapOrError(FileName, Obj.rels(*PltRelSec));
3230
return unwrapOrError(FileName,
3231
Obj.getRelocationSymbol(Rels[Offset], PltSymTable));
3232
} else {
3233
Elf_Rela_Range Rels = unwrapOrError(FileName, Obj.relas(*PltRelSec));
3234
return unwrapOrError(FileName,
3235
Obj.getRelocationSymbol(Rels[Offset], PltSymTable));
3236
}
3237
}
3238
3239
const EnumEntry<unsigned> ElfMipsISAExtType[] = {
3240
{"None", Mips::AFL_EXT_NONE},
3241
{"Broadcom SB-1", Mips::AFL_EXT_SB1},
3242
{"Cavium Networks Octeon", Mips::AFL_EXT_OCTEON},
3243
{"Cavium Networks Octeon2", Mips::AFL_EXT_OCTEON2},
3244
{"Cavium Networks OcteonP", Mips::AFL_EXT_OCTEONP},
3245
{"Cavium Networks Octeon3", Mips::AFL_EXT_OCTEON3},
3246
{"LSI R4010", Mips::AFL_EXT_4010},
3247
{"Loongson 2E", Mips::AFL_EXT_LOONGSON_2E},
3248
{"Loongson 2F", Mips::AFL_EXT_LOONGSON_2F},
3249
{"Loongson 3A", Mips::AFL_EXT_LOONGSON_3A},
3250
{"MIPS R4650", Mips::AFL_EXT_4650},
3251
{"MIPS R5900", Mips::AFL_EXT_5900},
3252
{"MIPS R10000", Mips::AFL_EXT_10000},
3253
{"NEC VR4100", Mips::AFL_EXT_4100},
3254
{"NEC VR4111/VR4181", Mips::AFL_EXT_4111},
3255
{"NEC VR4120", Mips::AFL_EXT_4120},
3256
{"NEC VR5400", Mips::AFL_EXT_5400},
3257
{"NEC VR5500", Mips::AFL_EXT_5500},
3258
{"RMI Xlr", Mips::AFL_EXT_XLR},
3259
{"Toshiba R3900", Mips::AFL_EXT_3900}
3260
};
3261
3262
const EnumEntry<unsigned> ElfMipsASEFlags[] = {
3263
{"DSP", Mips::AFL_ASE_DSP},
3264
{"DSPR2", Mips::AFL_ASE_DSPR2},
3265
{"Enhanced VA Scheme", Mips::AFL_ASE_EVA},
3266
{"MCU", Mips::AFL_ASE_MCU},
3267
{"MDMX", Mips::AFL_ASE_MDMX},
3268
{"MIPS-3D", Mips::AFL_ASE_MIPS3D},
3269
{"MT", Mips::AFL_ASE_MT},
3270
{"SmartMIPS", Mips::AFL_ASE_SMARTMIPS},
3271
{"VZ", Mips::AFL_ASE_VIRT},
3272
{"MSA", Mips::AFL_ASE_MSA},
3273
{"MIPS16", Mips::AFL_ASE_MIPS16},
3274
{"microMIPS", Mips::AFL_ASE_MICROMIPS},
3275
{"XPA", Mips::AFL_ASE_XPA},
3276
{"CRC", Mips::AFL_ASE_CRC},
3277
{"GINV", Mips::AFL_ASE_GINV},
3278
};
3279
3280
const EnumEntry<unsigned> ElfMipsFpABIType[] = {
3281
{"Hard or soft float", Mips::Val_GNU_MIPS_ABI_FP_ANY},
3282
{"Hard float (double precision)", Mips::Val_GNU_MIPS_ABI_FP_DOUBLE},
3283
{"Hard float (single precision)", Mips::Val_GNU_MIPS_ABI_FP_SINGLE},
3284
{"Soft float", Mips::Val_GNU_MIPS_ABI_FP_SOFT},
3285
{"Hard float (MIPS32r2 64-bit FPU 12 callee-saved)",
3286
Mips::Val_GNU_MIPS_ABI_FP_OLD_64},
3287
{"Hard float (32-bit CPU, Any FPU)", Mips::Val_GNU_MIPS_ABI_FP_XX},
3288
{"Hard float (32-bit CPU, 64-bit FPU)", Mips::Val_GNU_MIPS_ABI_FP_64},
3289
{"Hard float compat (32-bit CPU, 64-bit FPU)",
3290
Mips::Val_GNU_MIPS_ABI_FP_64A}
3291
};
3292
3293
static const EnumEntry<unsigned> ElfMipsFlags1[] {
3294
{"ODDSPREG", Mips::AFL_FLAGS1_ODDSPREG},
3295
};
3296
3297
static int getMipsRegisterSize(uint8_t Flag) {
3298
switch (Flag) {
3299
case Mips::AFL_REG_NONE:
3300
return 0;
3301
case Mips::AFL_REG_32:
3302
return 32;
3303
case Mips::AFL_REG_64:
3304
return 64;
3305
case Mips::AFL_REG_128:
3306
return 128;
3307
default:
3308
return -1;
3309
}
3310
}
3311
3312
template <class ELFT>
3313
static void printMipsReginfoData(ScopedPrinter &W,
3314
const Elf_Mips_RegInfo<ELFT> &Reginfo) {
3315
W.printHex("GP", Reginfo.ri_gp_value);
3316
W.printHex("General Mask", Reginfo.ri_gprmask);
3317
W.printHex("Co-Proc Mask0", Reginfo.ri_cprmask[0]);
3318
W.printHex("Co-Proc Mask1", Reginfo.ri_cprmask[1]);
3319
W.printHex("Co-Proc Mask2", Reginfo.ri_cprmask[2]);
3320
W.printHex("Co-Proc Mask3", Reginfo.ri_cprmask[3]);
3321
}
3322
3323
template <class ELFT> void ELFDumper<ELFT>::printMipsReginfo() {
3324
const Elf_Shdr *RegInfoSec = findSectionByName(".reginfo");
3325
if (!RegInfoSec) {
3326
W.startLine() << "There is no .reginfo section in the file.\n";
3327
return;
3328
}
3329
3330
Expected<ArrayRef<uint8_t>> ContentsOrErr =
3331
Obj.getSectionContents(*RegInfoSec);
3332
if (!ContentsOrErr) {
3333
this->reportUniqueWarning(
3334
"unable to read the content of the .reginfo section (" +
3335
describe(*RegInfoSec) + "): " + toString(ContentsOrErr.takeError()));
3336
return;
3337
}
3338
3339
if (ContentsOrErr->size() < sizeof(Elf_Mips_RegInfo<ELFT>)) {
3340
this->reportUniqueWarning("the .reginfo section has an invalid size (0x" +
3341
Twine::utohexstr(ContentsOrErr->size()) + ")");
3342
return;
3343
}
3344
3345
DictScope GS(W, "MIPS RegInfo");
3346
printMipsReginfoData(W, *reinterpret_cast<const Elf_Mips_RegInfo<ELFT> *>(
3347
ContentsOrErr->data()));
3348
}
3349
3350
template <class ELFT>
3351
static Expected<const Elf_Mips_Options<ELFT> *>
3352
readMipsOptions(const uint8_t *SecBegin, ArrayRef<uint8_t> &SecData,
3353
bool &IsSupported) {
3354
if (SecData.size() < sizeof(Elf_Mips_Options<ELFT>))
3355
return createError("the .MIPS.options section has an invalid size (0x" +
3356
Twine::utohexstr(SecData.size()) + ")");
3357
3358
const Elf_Mips_Options<ELFT> *O =
3359
reinterpret_cast<const Elf_Mips_Options<ELFT> *>(SecData.data());
3360
const uint8_t Size = O->size;
3361
if (Size > SecData.size()) {
3362
const uint64_t Offset = SecData.data() - SecBegin;
3363
const uint64_t SecSize = Offset + SecData.size();
3364
return createError("a descriptor of size 0x" + Twine::utohexstr(Size) +
3365
" at offset 0x" + Twine::utohexstr(Offset) +
3366
" goes past the end of the .MIPS.options "
3367
"section of size 0x" +
3368
Twine::utohexstr(SecSize));
3369
}
3370
3371
IsSupported = O->kind == ODK_REGINFO;
3372
const size_t ExpectedSize =
3373
sizeof(Elf_Mips_Options<ELFT>) + sizeof(Elf_Mips_RegInfo<ELFT>);
3374
3375
if (IsSupported)
3376
if (Size < ExpectedSize)
3377
return createError(
3378
"a .MIPS.options entry of kind " +
3379
Twine(getElfMipsOptionsOdkType(O->kind)) +
3380
" has an invalid size (0x" + Twine::utohexstr(Size) +
3381
"), the expected size is 0x" + Twine::utohexstr(ExpectedSize));
3382
3383
SecData = SecData.drop_front(Size);
3384
return O;
3385
}
3386
3387
template <class ELFT> void ELFDumper<ELFT>::printMipsOptions() {
3388
const Elf_Shdr *MipsOpts = findSectionByName(".MIPS.options");
3389
if (!MipsOpts) {
3390
W.startLine() << "There is no .MIPS.options section in the file.\n";
3391
return;
3392
}
3393
3394
DictScope GS(W, "MIPS Options");
3395
3396
ArrayRef<uint8_t> Data =
3397
unwrapOrError(ObjF.getFileName(), Obj.getSectionContents(*MipsOpts));
3398
const uint8_t *const SecBegin = Data.begin();
3399
while (!Data.empty()) {
3400
bool IsSupported;
3401
Expected<const Elf_Mips_Options<ELFT> *> OptsOrErr =
3402
readMipsOptions<ELFT>(SecBegin, Data, IsSupported);
3403
if (!OptsOrErr) {
3404
reportUniqueWarning(OptsOrErr.takeError());
3405
break;
3406
}
3407
3408
unsigned Kind = (*OptsOrErr)->kind;
3409
const char *Type = getElfMipsOptionsOdkType(Kind);
3410
if (!IsSupported) {
3411
W.startLine() << "Unsupported MIPS options tag: " << Type << " (" << Kind
3412
<< ")\n";
3413
continue;
3414
}
3415
3416
DictScope GS(W, Type);
3417
if (Kind == ODK_REGINFO)
3418
printMipsReginfoData(W, (*OptsOrErr)->getRegInfo());
3419
else
3420
llvm_unreachable("unexpected .MIPS.options section descriptor kind");
3421
}
3422
}
3423
3424
template <class ELFT> void ELFDumper<ELFT>::printStackMap() const {
3425
const Elf_Shdr *StackMapSection = findSectionByName(".llvm_stackmaps");
3426
if (!StackMapSection)
3427
return;
3428
3429
auto Warn = [&](Error &&E) {
3430
this->reportUniqueWarning("unable to read the stack map from " +
3431
describe(*StackMapSection) + ": " +
3432
toString(std::move(E)));
3433
};
3434
3435
Expected<ArrayRef<uint8_t>> ContentOrErr =
3436
Obj.getSectionContents(*StackMapSection);
3437
if (!ContentOrErr) {
3438
Warn(ContentOrErr.takeError());
3439
return;
3440
}
3441
3442
if (Error E =
3443
StackMapParser<ELFT::Endianness>::validateHeader(*ContentOrErr)) {
3444
Warn(std::move(E));
3445
return;
3446
}
3447
3448
prettyPrintStackMap(W, StackMapParser<ELFT::Endianness>(*ContentOrErr));
3449
}
3450
3451
template <class ELFT>
3452
void ELFDumper<ELFT>::printReloc(const Relocation<ELFT> &R, unsigned RelIndex,
3453
const Elf_Shdr &Sec, const Elf_Shdr *SymTab) {
3454
Expected<RelSymbol<ELFT>> Target = getRelocationTarget(R, SymTab);
3455
if (!Target)
3456
reportUniqueWarning("unable to print relocation " + Twine(RelIndex) +
3457
" in " + describe(Sec) + ": " +
3458
toString(Target.takeError()));
3459
else
3460
printRelRelaReloc(R, *Target);
3461
}
3462
3463
template <class ELFT>
3464
std::vector<EnumEntry<unsigned>>
3465
ELFDumper<ELFT>::getOtherFlagsFromSymbol(const Elf_Ehdr &Header,
3466
const Elf_Sym &Symbol) const {
3467
std::vector<EnumEntry<unsigned>> SymOtherFlags(std::begin(ElfSymOtherFlags),
3468
std::end(ElfSymOtherFlags));
3469
if (Header.e_machine == EM_MIPS) {
3470
// Someone in their infinite wisdom decided to make STO_MIPS_MIPS16
3471
// flag overlap with other ST_MIPS_xxx flags. So consider both
3472
// cases separately.
3473
if ((Symbol.st_other & STO_MIPS_MIPS16) == STO_MIPS_MIPS16)
3474
SymOtherFlags.insert(SymOtherFlags.end(),
3475
std::begin(ElfMips16SymOtherFlags),
3476
std::end(ElfMips16SymOtherFlags));
3477
else
3478
SymOtherFlags.insert(SymOtherFlags.end(),
3479
std::begin(ElfMipsSymOtherFlags),
3480
std::end(ElfMipsSymOtherFlags));
3481
} else if (Header.e_machine == EM_AARCH64) {
3482
SymOtherFlags.insert(SymOtherFlags.end(),
3483
std::begin(ElfAArch64SymOtherFlags),
3484
std::end(ElfAArch64SymOtherFlags));
3485
} else if (Header.e_machine == EM_RISCV) {
3486
SymOtherFlags.insert(SymOtherFlags.end(), std::begin(ElfRISCVSymOtherFlags),
3487
std::end(ElfRISCVSymOtherFlags));
3488
}
3489
return SymOtherFlags;
3490
}
3491
3492
static inline void printFields(formatted_raw_ostream &OS, StringRef Str1,
3493
StringRef Str2) {
3494
OS.PadToColumn(2u);
3495
OS << Str1;
3496
OS.PadToColumn(37u);
3497
OS << Str2 << "\n";
3498
OS.flush();
3499
}
3500
3501
template <class ELFT>
3502
static std::string getSectionHeadersNumString(const ELFFile<ELFT> &Obj,
3503
StringRef FileName) {
3504
const typename ELFT::Ehdr &ElfHeader = Obj.getHeader();
3505
if (ElfHeader.e_shnum != 0)
3506
return to_string(ElfHeader.e_shnum);
3507
3508
Expected<ArrayRef<typename ELFT::Shdr>> ArrOrErr = Obj.sections();
3509
if (!ArrOrErr) {
3510
// In this case we can ignore an error, because we have already reported a
3511
// warning about the broken section header table earlier.
3512
consumeError(ArrOrErr.takeError());
3513
return "<?>";
3514
}
3515
3516
if (ArrOrErr->empty())
3517
return "0";
3518
return "0 (" + to_string((*ArrOrErr)[0].sh_size) + ")";
3519
}
3520
3521
template <class ELFT>
3522
static std::string getSectionHeaderTableIndexString(const ELFFile<ELFT> &Obj,
3523
StringRef FileName) {
3524
const typename ELFT::Ehdr &ElfHeader = Obj.getHeader();
3525
if (ElfHeader.e_shstrndx != SHN_XINDEX)
3526
return to_string(ElfHeader.e_shstrndx);
3527
3528
Expected<ArrayRef<typename ELFT::Shdr>> ArrOrErr = Obj.sections();
3529
if (!ArrOrErr) {
3530
// In this case we can ignore an error, because we have already reported a
3531
// warning about the broken section header table earlier.
3532
consumeError(ArrOrErr.takeError());
3533
return "<?>";
3534
}
3535
3536
if (ArrOrErr->empty())
3537
return "65535 (corrupt: out of range)";
3538
return to_string(ElfHeader.e_shstrndx) + " (" +
3539
to_string((*ArrOrErr)[0].sh_link) + ")";
3540
}
3541
3542
static const EnumEntry<unsigned> *getObjectFileEnumEntry(unsigned Type) {
3543
auto It = llvm::find_if(ElfObjectFileType, [&](const EnumEntry<unsigned> &E) {
3544
return E.Value == Type;
3545
});
3546
if (It != ArrayRef(ElfObjectFileType).end())
3547
return It;
3548
return nullptr;
3549
}
3550
3551
template <class ELFT>
3552
void GNUELFDumper<ELFT>::printFileSummary(StringRef FileStr, ObjectFile &Obj,
3553
ArrayRef<std::string> InputFilenames,
3554
const Archive *A) {
3555
if (InputFilenames.size() > 1 || A) {
3556
this->W.startLine() << "\n";
3557
this->W.printString("File", FileStr);
3558
}
3559
}
3560
3561
template <class ELFT> void GNUELFDumper<ELFT>::printFileHeaders() {
3562
const Elf_Ehdr &e = this->Obj.getHeader();
3563
OS << "ELF Header:\n";
3564
OS << " Magic: ";
3565
std::string Str;
3566
for (int i = 0; i < ELF::EI_NIDENT; i++)
3567
OS << format(" %02x", static_cast<int>(e.e_ident[i]));
3568
OS << "\n";
3569
Str = enumToString(e.e_ident[ELF::EI_CLASS], ArrayRef(ElfClass));
3570
printFields(OS, "Class:", Str);
3571
Str = enumToString(e.e_ident[ELF::EI_DATA], ArrayRef(ElfDataEncoding));
3572
printFields(OS, "Data:", Str);
3573
OS.PadToColumn(2u);
3574
OS << "Version:";
3575
OS.PadToColumn(37u);
3576
OS << utohexstr(e.e_ident[ELF::EI_VERSION]);
3577
if (e.e_version == ELF::EV_CURRENT)
3578
OS << " (current)";
3579
OS << "\n";
3580
auto OSABI = ArrayRef(ElfOSABI);
3581
if (e.e_ident[ELF::EI_OSABI] >= ELF::ELFOSABI_FIRST_ARCH &&
3582
e.e_ident[ELF::EI_OSABI] <= ELF::ELFOSABI_LAST_ARCH) {
3583
switch (e.e_machine) {
3584
case ELF::EM_ARM:
3585
OSABI = ArrayRef(ARMElfOSABI);
3586
break;
3587
case ELF::EM_AMDGPU:
3588
OSABI = ArrayRef(AMDGPUElfOSABI);
3589
break;
3590
default:
3591
break;
3592
}
3593
}
3594
Str = enumToString(e.e_ident[ELF::EI_OSABI], OSABI);
3595
printFields(OS, "OS/ABI:", Str);
3596
printFields(OS,
3597
"ABI Version:", std::to_string(e.e_ident[ELF::EI_ABIVERSION]));
3598
3599
if (const EnumEntry<unsigned> *E = getObjectFileEnumEntry(e.e_type)) {
3600
Str = E->AltName.str();
3601
} else {
3602
if (e.e_type >= ET_LOPROC)
3603
Str = "Processor Specific: (" + utohexstr(e.e_type, /*LowerCase=*/true) + ")";
3604
else if (e.e_type >= ET_LOOS)
3605
Str = "OS Specific: (" + utohexstr(e.e_type, /*LowerCase=*/true) + ")";
3606
else
3607
Str = "<unknown>: " + utohexstr(e.e_type, /*LowerCase=*/true);
3608
}
3609
printFields(OS, "Type:", Str);
3610
3611
Str = enumToString(e.e_machine, ArrayRef(ElfMachineType));
3612
printFields(OS, "Machine:", Str);
3613
Str = "0x" + utohexstr(e.e_version);
3614
printFields(OS, "Version:", Str);
3615
Str = "0x" + utohexstr(e.e_entry);
3616
printFields(OS, "Entry point address:", Str);
3617
Str = to_string(e.e_phoff) + " (bytes into file)";
3618
printFields(OS, "Start of program headers:", Str);
3619
Str = to_string(e.e_shoff) + " (bytes into file)";
3620
printFields(OS, "Start of section headers:", Str);
3621
std::string ElfFlags;
3622
if (e.e_machine == EM_MIPS)
3623
ElfFlags = printFlags(
3624
e.e_flags, ArrayRef(ElfHeaderMipsFlags), unsigned(ELF::EF_MIPS_ARCH),
3625
unsigned(ELF::EF_MIPS_ABI), unsigned(ELF::EF_MIPS_MACH));
3626
else if (e.e_machine == EM_RISCV)
3627
ElfFlags = printFlags(e.e_flags, ArrayRef(ElfHeaderRISCVFlags));
3628
else if (e.e_machine == EM_AVR)
3629
ElfFlags = printFlags(e.e_flags, ArrayRef(ElfHeaderAVRFlags),
3630
unsigned(ELF::EF_AVR_ARCH_MASK));
3631
else if (e.e_machine == EM_LOONGARCH)
3632
ElfFlags = printFlags(e.e_flags, ArrayRef(ElfHeaderLoongArchFlags),
3633
unsigned(ELF::EF_LOONGARCH_ABI_MODIFIER_MASK),
3634
unsigned(ELF::EF_LOONGARCH_OBJABI_MASK));
3635
else if (e.e_machine == EM_XTENSA)
3636
ElfFlags = printFlags(e.e_flags, ArrayRef(ElfHeaderXtensaFlags),
3637
unsigned(ELF::EF_XTENSA_MACH));
3638
else if (e.e_machine == EM_CUDA)
3639
ElfFlags = printFlags(e.e_flags, ArrayRef(ElfHeaderNVPTXFlags),
3640
unsigned(ELF::EF_CUDA_SM));
3641
else if (e.e_machine == EM_AMDGPU) {
3642
switch (e.e_ident[ELF::EI_ABIVERSION]) {
3643
default:
3644
break;
3645
case 0:
3646
// ELFOSABI_AMDGPU_PAL, ELFOSABI_AMDGPU_MESA3D support *_V3 flags.
3647
[[fallthrough]];
3648
case ELF::ELFABIVERSION_AMDGPU_HSA_V3:
3649
ElfFlags =
3650
printFlags(e.e_flags, ArrayRef(ElfHeaderAMDGPUFlagsABIVersion3),
3651
unsigned(ELF::EF_AMDGPU_MACH));
3652
break;
3653
case ELF::ELFABIVERSION_AMDGPU_HSA_V4:
3654
case ELF::ELFABIVERSION_AMDGPU_HSA_V5:
3655
ElfFlags =
3656
printFlags(e.e_flags, ArrayRef(ElfHeaderAMDGPUFlagsABIVersion4),
3657
unsigned(ELF::EF_AMDGPU_MACH),
3658
unsigned(ELF::EF_AMDGPU_FEATURE_XNACK_V4),
3659
unsigned(ELF::EF_AMDGPU_FEATURE_SRAMECC_V4));
3660
break;
3661
case ELF::ELFABIVERSION_AMDGPU_HSA_V6: {
3662
ElfFlags =
3663
printFlags(e.e_flags, ArrayRef(ElfHeaderAMDGPUFlagsABIVersion4),
3664
unsigned(ELF::EF_AMDGPU_MACH),
3665
unsigned(ELF::EF_AMDGPU_FEATURE_XNACK_V4),
3666
unsigned(ELF::EF_AMDGPU_FEATURE_SRAMECC_V4));
3667
if (auto GenericV = e.e_flags & ELF::EF_AMDGPU_GENERIC_VERSION) {
3668
ElfFlags +=
3669
", generic_v" +
3670
to_string(GenericV >> ELF::EF_AMDGPU_GENERIC_VERSION_OFFSET);
3671
}
3672
} break;
3673
}
3674
}
3675
Str = "0x" + utohexstr(e.e_flags);
3676
if (!ElfFlags.empty())
3677
Str = Str + ", " + ElfFlags;
3678
printFields(OS, "Flags:", Str);
3679
Str = to_string(e.e_ehsize) + " (bytes)";
3680
printFields(OS, "Size of this header:", Str);
3681
Str = to_string(e.e_phentsize) + " (bytes)";
3682
printFields(OS, "Size of program headers:", Str);
3683
Str = to_string(e.e_phnum);
3684
printFields(OS, "Number of program headers:", Str);
3685
Str = to_string(e.e_shentsize) + " (bytes)";
3686
printFields(OS, "Size of section headers:", Str);
3687
Str = getSectionHeadersNumString(this->Obj, this->FileName);
3688
printFields(OS, "Number of section headers:", Str);
3689
Str = getSectionHeaderTableIndexString(this->Obj, this->FileName);
3690
printFields(OS, "Section header string table index:", Str);
3691
}
3692
3693
template <class ELFT> std::vector<GroupSection> ELFDumper<ELFT>::getGroups() {
3694
auto GetSignature = [&](const Elf_Sym &Sym, unsigned SymNdx,
3695
const Elf_Shdr &Symtab) -> StringRef {
3696
Expected<StringRef> StrTableOrErr = Obj.getStringTableForSymtab(Symtab);
3697
if (!StrTableOrErr) {
3698
reportUniqueWarning("unable to get the string table for " +
3699
describe(Symtab) + ": " +
3700
toString(StrTableOrErr.takeError()));
3701
return "<?>";
3702
}
3703
3704
StringRef Strings = *StrTableOrErr;
3705
if (Sym.st_name >= Strings.size()) {
3706
reportUniqueWarning("unable to get the name of the symbol with index " +
3707
Twine(SymNdx) + ": st_name (0x" +
3708
Twine::utohexstr(Sym.st_name) +
3709
") is past the end of the string table of size 0x" +
3710
Twine::utohexstr(Strings.size()));
3711
return "<?>";
3712
}
3713
3714
return StrTableOrErr->data() + Sym.st_name;
3715
};
3716
3717
std::vector<GroupSection> Ret;
3718
uint64_t I = 0;
3719
for (const Elf_Shdr &Sec : cantFail(Obj.sections())) {
3720
++I;
3721
if (Sec.sh_type != ELF::SHT_GROUP)
3722
continue;
3723
3724
StringRef Signature = "<?>";
3725
if (Expected<const Elf_Shdr *> SymtabOrErr = Obj.getSection(Sec.sh_link)) {
3726
if (Expected<const Elf_Sym *> SymOrErr =
3727
Obj.template getEntry<Elf_Sym>(**SymtabOrErr, Sec.sh_info))
3728
Signature = GetSignature(**SymOrErr, Sec.sh_info, **SymtabOrErr);
3729
else
3730
reportUniqueWarning("unable to get the signature symbol for " +
3731
describe(Sec) + ": " +
3732
toString(SymOrErr.takeError()));
3733
} else {
3734
reportUniqueWarning("unable to get the symbol table for " +
3735
describe(Sec) + ": " +
3736
toString(SymtabOrErr.takeError()));
3737
}
3738
3739
ArrayRef<Elf_Word> Data;
3740
if (Expected<ArrayRef<Elf_Word>> ContentsOrErr =
3741
Obj.template getSectionContentsAsArray<Elf_Word>(Sec)) {
3742
if (ContentsOrErr->empty())
3743
reportUniqueWarning("unable to read the section group flag from the " +
3744
describe(Sec) + ": the section is empty");
3745
else
3746
Data = *ContentsOrErr;
3747
} else {
3748
reportUniqueWarning("unable to get the content of the " + describe(Sec) +
3749
": " + toString(ContentsOrErr.takeError()));
3750
}
3751
3752
Ret.push_back({getPrintableSectionName(Sec),
3753
maybeDemangle(Signature),
3754
Sec.sh_name,
3755
I - 1,
3756
Sec.sh_link,
3757
Sec.sh_info,
3758
Data.empty() ? Elf_Word(0) : Data[0],
3759
{}});
3760
3761
if (Data.empty())
3762
continue;
3763
3764
std::vector<GroupMember> &GM = Ret.back().Members;
3765
for (uint32_t Ndx : Data.slice(1)) {
3766
if (Expected<const Elf_Shdr *> SecOrErr = Obj.getSection(Ndx)) {
3767
GM.push_back({getPrintableSectionName(**SecOrErr), Ndx});
3768
} else {
3769
reportUniqueWarning("unable to get the section with index " +
3770
Twine(Ndx) + " when dumping the " + describe(Sec) +
3771
": " + toString(SecOrErr.takeError()));
3772
GM.push_back({"<?>", Ndx});
3773
}
3774
}
3775
}
3776
return Ret;
3777
}
3778
3779
static DenseMap<uint64_t, const GroupSection *>
3780
mapSectionsToGroups(ArrayRef<GroupSection> Groups) {
3781
DenseMap<uint64_t, const GroupSection *> Ret;
3782
for (const GroupSection &G : Groups)
3783
for (const GroupMember &GM : G.Members)
3784
Ret.insert({GM.Index, &G});
3785
return Ret;
3786
}
3787
3788
template <class ELFT> void GNUELFDumper<ELFT>::printGroupSections() {
3789
std::vector<GroupSection> V = this->getGroups();
3790
DenseMap<uint64_t, const GroupSection *> Map = mapSectionsToGroups(V);
3791
for (const GroupSection &G : V) {
3792
OS << "\n"
3793
<< getGroupType(G.Type) << " group section ["
3794
<< format_decimal(G.Index, 5) << "] `" << G.Name << "' [" << G.Signature
3795
<< "] contains " << G.Members.size() << " sections:\n"
3796
<< " [Index] Name\n";
3797
for (const GroupMember &GM : G.Members) {
3798
const GroupSection *MainGroup = Map[GM.Index];
3799
if (MainGroup != &G)
3800
this->reportUniqueWarning(
3801
"section with index " + Twine(GM.Index) +
3802
", included in the group section with index " +
3803
Twine(MainGroup->Index) +
3804
", was also found in the group section with index " +
3805
Twine(G.Index));
3806
OS << " [" << format_decimal(GM.Index, 5) << "] " << GM.Name << "\n";
3807
}
3808
}
3809
3810
if (V.empty())
3811
OS << "There are no section groups in this file.\n";
3812
}
3813
3814
template <class ELFT>
3815
void GNUELFDumper<ELFT>::printRelRelaReloc(const Relocation<ELFT> &R,
3816
const RelSymbol<ELFT> &RelSym) {
3817
// First two fields are bit width dependent. The rest of them are fixed width.
3818
unsigned Bias = ELFT::Is64Bits ? 8 : 0;
3819
Field Fields[5] = {0, 10 + Bias, 19 + 2 * Bias, 42 + 2 * Bias, 53 + 2 * Bias};
3820
unsigned Width = ELFT::Is64Bits ? 16 : 8;
3821
3822
Fields[0].Str = to_string(format_hex_no_prefix(R.Offset, Width));
3823
Fields[1].Str = to_string(format_hex_no_prefix(R.Info, Width));
3824
3825
SmallString<32> RelocName;
3826
this->Obj.getRelocationTypeName(R.Type, RelocName);
3827
Fields[2].Str = RelocName.c_str();
3828
3829
if (RelSym.Sym)
3830
Fields[3].Str =
3831
to_string(format_hex_no_prefix(RelSym.Sym->getValue(), Width));
3832
if (RelSym.Sym && RelSym.Name.empty())
3833
Fields[4].Str = "<null>";
3834
else
3835
Fields[4].Str = std::string(RelSym.Name);
3836
3837
for (const Field &F : Fields)
3838
printField(F);
3839
3840
std::string Addend;
3841
if (std::optional<int64_t> A = R.Addend) {
3842
int64_t RelAddend = *A;
3843
if (!Fields[4].Str.empty()) {
3844
if (RelAddend < 0) {
3845
Addend = " - ";
3846
RelAddend = -static_cast<uint64_t>(RelAddend);
3847
} else {
3848
Addend = " + ";
3849
}
3850
}
3851
Addend += utohexstr(RelAddend, /*LowerCase=*/true);
3852
}
3853
OS << Addend << "\n";
3854
}
3855
3856
template <class ELFT>
3857
static void printRelocHeaderFields(formatted_raw_ostream &OS, unsigned SType,
3858
const typename ELFT::Ehdr &EHeader,
3859
uint64_t CrelHdr = 0) {
3860
bool IsRela = SType == ELF::SHT_RELA || SType == ELF::SHT_ANDROID_RELA;
3861
if (ELFT::Is64Bits)
3862
OS << " Offset Info Type Symbol's "
3863
"Value Symbol's Name";
3864
else
3865
OS << " Offset Info Type Sym. Value Symbol's Name";
3866
if (IsRela || (SType == ELF::SHT_CREL && (CrelHdr & CREL_HDR_ADDEND)))
3867
OS << " + Addend";
3868
OS << "\n";
3869
}
3870
3871
template <class ELFT>
3872
void GNUELFDumper<ELFT>::printDynamicRelocHeader(unsigned Type, StringRef Name,
3873
const DynRegionInfo &Reg) {
3874
uint64_t Offset = Reg.Addr - this->Obj.base();
3875
OS << "\n'" << Name.str().c_str() << "' relocation section at offset 0x"
3876
<< utohexstr(Offset, /*LowerCase=*/true);
3877
if (Type != ELF::SHT_CREL)
3878
OS << " contains " << Reg.Size << " bytes";
3879
OS << ":\n";
3880
printRelocHeaderFields<ELFT>(OS, Type, this->Obj.getHeader());
3881
}
3882
3883
template <class ELFT>
3884
static bool isRelocationSec(const typename ELFT::Shdr &Sec,
3885
const typename ELFT::Ehdr &EHeader) {
3886
return Sec.sh_type == ELF::SHT_REL || Sec.sh_type == ELF::SHT_RELA ||
3887
Sec.sh_type == ELF::SHT_RELR || Sec.sh_type == ELF::SHT_CREL ||
3888
Sec.sh_type == ELF::SHT_ANDROID_REL ||
3889
Sec.sh_type == ELF::SHT_ANDROID_RELA ||
3890
Sec.sh_type == ELF::SHT_ANDROID_RELR ||
3891
(EHeader.e_machine == EM_AARCH64 &&
3892
Sec.sh_type == ELF::SHT_AARCH64_AUTH_RELR);
3893
}
3894
3895
template <class ELFT> void GNUELFDumper<ELFT>::printRelocations() {
3896
auto PrintAsRelr = [&](const Elf_Shdr &Sec) {
3897
return Sec.sh_type == ELF::SHT_RELR ||
3898
Sec.sh_type == ELF::SHT_ANDROID_RELR ||
3899
(this->Obj.getHeader().e_machine == EM_AARCH64 &&
3900
Sec.sh_type == ELF::SHT_AARCH64_AUTH_RELR);
3901
};
3902
auto GetEntriesNum = [&](const Elf_Shdr &Sec) -> Expected<size_t> {
3903
// Android's packed relocation section needs to be unpacked first
3904
// to get the actual number of entries.
3905
if (Sec.sh_type == ELF::SHT_ANDROID_REL ||
3906
Sec.sh_type == ELF::SHT_ANDROID_RELA) {
3907
Expected<std::vector<typename ELFT::Rela>> RelasOrErr =
3908
this->Obj.android_relas(Sec);
3909
if (!RelasOrErr)
3910
return RelasOrErr.takeError();
3911
return RelasOrErr->size();
3912
}
3913
3914
if (Sec.sh_type == ELF::SHT_CREL) {
3915
Expected<ArrayRef<uint8_t>> ContentsOrErr =
3916
this->Obj.getSectionContents(Sec);
3917
if (!ContentsOrErr)
3918
return ContentsOrErr.takeError();
3919
auto NumOrErr = this->Obj.getCrelHeader(*ContentsOrErr);
3920
if (!NumOrErr)
3921
return NumOrErr.takeError();
3922
return *NumOrErr / 8;
3923
}
3924
3925
if (PrintAsRelr(Sec)) {
3926
Expected<Elf_Relr_Range> RelrsOrErr = this->Obj.relrs(Sec);
3927
if (!RelrsOrErr)
3928
return RelrsOrErr.takeError();
3929
return this->Obj.decode_relrs(*RelrsOrErr).size();
3930
}
3931
3932
return Sec.getEntityCount();
3933
};
3934
3935
bool HasRelocSections = false;
3936
for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) {
3937
if (!isRelocationSec<ELFT>(Sec, this->Obj.getHeader()))
3938
continue;
3939
HasRelocSections = true;
3940
3941
std::string EntriesNum = "<?>";
3942
if (Expected<size_t> NumOrErr = GetEntriesNum(Sec))
3943
EntriesNum = std::to_string(*NumOrErr);
3944
else
3945
this->reportUniqueWarning("unable to get the number of relocations in " +
3946
this->describe(Sec) + ": " +
3947
toString(NumOrErr.takeError()));
3948
3949
uintX_t Offset = Sec.sh_offset;
3950
StringRef Name = this->getPrintableSectionName(Sec);
3951
OS << "\nRelocation section '" << Name << "' at offset 0x"
3952
<< utohexstr(Offset, /*LowerCase=*/true) << " contains " << EntriesNum
3953
<< " entries:\n";
3954
3955
if (PrintAsRelr(Sec)) {
3956
printRelr(Sec);
3957
} else {
3958
uint64_t CrelHdr = 0;
3959
// For CREL, read the header and call printRelocationsHelper only if
3960
// GetEntriesNum(Sec) succeeded.
3961
if (Sec.sh_type == ELF::SHT_CREL && EntriesNum != "<?>") {
3962
CrelHdr = cantFail(this->Obj.getCrelHeader(
3963
cantFail(this->Obj.getSectionContents(Sec))));
3964
}
3965
printRelocHeaderFields<ELFT>(OS, Sec.sh_type, this->Obj.getHeader(),
3966
CrelHdr);
3967
if (Sec.sh_type != ELF::SHT_CREL || EntriesNum != "<?>")
3968
this->printRelocationsHelper(Sec);
3969
}
3970
}
3971
if (!HasRelocSections)
3972
OS << "\nThere are no relocations in this file.\n";
3973
}
3974
3975
template <class ELFT> void GNUELFDumper<ELFT>::printRelr(const Elf_Shdr &Sec) {
3976
Expected<Elf_Relr_Range> RangeOrErr = this->Obj.relrs(Sec);
3977
if (!RangeOrErr) {
3978
this->reportUniqueWarning("unable to read relocations from " +
3979
this->describe(Sec) + ": " +
3980
toString(RangeOrErr.takeError()));
3981
return;
3982
}
3983
if (ELFT::Is64Bits)
3984
OS << "Index: Entry Address Symbolic Address\n";
3985
else
3986
OS << "Index: Entry Address Symbolic Address\n";
3987
3988
// If .symtab is available, collect its defined symbols and sort them by
3989
// st_value.
3990
SmallVector<std::pair<uint64_t, std::string>, 0> Syms;
3991
if (this->DotSymtabSec) {
3992
Elf_Sym_Range Symtab;
3993
std::optional<StringRef> Strtab;
3994
std::tie(Symtab, Strtab) = this->getSymtabAndStrtab();
3995
if (Symtab.size() && Strtab) {
3996
for (auto [I, Sym] : enumerate(Symtab)) {
3997
if (!Sym.st_shndx)
3998
continue;
3999
Syms.emplace_back(Sym.st_value,
4000
this->getFullSymbolName(Sym, I, ArrayRef<Elf_Word>(),
4001
*Strtab, false));
4002
}
4003
}
4004
}
4005
llvm::stable_sort(Syms);
4006
4007
typename ELFT::uint Base = 0;
4008
size_t I = 0;
4009
auto Print = [&](uint64_t Where) {
4010
OS << format_hex_no_prefix(Where, ELFT::Is64Bits ? 16 : 8);
4011
for (; I < Syms.size() && Syms[I].first <= Where; ++I)
4012
;
4013
// Try symbolizing the address. Find the nearest symbol before or at the
4014
// address and print the symbol and the address difference.
4015
if (I) {
4016
OS << " " << Syms[I - 1].second;
4017
if (Syms[I - 1].first < Where)
4018
OS << " + 0x" << Twine::utohexstr(Where - Syms[I - 1].first);
4019
}
4020
OS << '\n';
4021
};
4022
for (auto [Index, R] : enumerate(*RangeOrErr)) {
4023
typename ELFT::uint Entry = R;
4024
OS << formatv("{0:4}: ", Index)
4025
<< format_hex_no_prefix(Entry, ELFT::Is64Bits ? 16 : 8) << ' ';
4026
if ((Entry & 1) == 0) {
4027
Print(Entry);
4028
Base = Entry + sizeof(typename ELFT::uint);
4029
} else {
4030
bool First = true;
4031
for (auto Where = Base; Entry >>= 1;
4032
Where += sizeof(typename ELFT::uint)) {
4033
if (Entry & 1) {
4034
if (First)
4035
First = false;
4036
else
4037
OS.indent(ELFT::Is64Bits ? 24 : 16);
4038
Print(Where);
4039
}
4040
}
4041
Base += (CHAR_BIT * sizeof(Entry) - 1) * sizeof(typename ELFT::uint);
4042
}
4043
}
4044
}
4045
4046
// Print the offset of a particular section from anyone of the ranges:
4047
// [SHT_LOOS, SHT_HIOS], [SHT_LOPROC, SHT_HIPROC], [SHT_LOUSER, SHT_HIUSER].
4048
// If 'Type' does not fall within any of those ranges, then a string is
4049
// returned as '<unknown>' followed by the type value.
4050
static std::string getSectionTypeOffsetString(unsigned Type) {
4051
if (Type >= SHT_LOOS && Type <= SHT_HIOS)
4052
return "LOOS+0x" + utohexstr(Type - SHT_LOOS);
4053
else if (Type >= SHT_LOPROC && Type <= SHT_HIPROC)
4054
return "LOPROC+0x" + utohexstr(Type - SHT_LOPROC);
4055
else if (Type >= SHT_LOUSER && Type <= SHT_HIUSER)
4056
return "LOUSER+0x" + utohexstr(Type - SHT_LOUSER);
4057
return "0x" + utohexstr(Type) + ": <unknown>";
4058
}
4059
4060
static std::string getSectionTypeString(unsigned Machine, unsigned Type) {
4061
StringRef Name = getELFSectionTypeName(Machine, Type);
4062
4063
// Handle SHT_GNU_* type names.
4064
if (Name.consume_front("SHT_GNU_")) {
4065
if (Name == "HASH")
4066
return "GNU_HASH";
4067
// E.g. SHT_GNU_verneed -> VERNEED.
4068
return Name.upper();
4069
}
4070
4071
if (Name == "SHT_SYMTAB_SHNDX")
4072
return "SYMTAB SECTION INDICES";
4073
4074
if (Name.consume_front("SHT_"))
4075
return Name.str();
4076
return getSectionTypeOffsetString(Type);
4077
}
4078
4079
static void printSectionDescription(formatted_raw_ostream &OS,
4080
unsigned EMachine) {
4081
OS << "Key to Flags:\n";
4082
OS << " W (write), A (alloc), X (execute), M (merge), S (strings), I "
4083
"(info),\n";
4084
OS << " L (link order), O (extra OS processing required), G (group), T "
4085
"(TLS),\n";
4086
OS << " C (compressed), x (unknown), o (OS specific), E (exclude),\n";
4087
OS << " R (retain)";
4088
4089
if (EMachine == EM_X86_64)
4090
OS << ", l (large)";
4091
else if (EMachine == EM_ARM)
4092
OS << ", y (purecode)";
4093
4094
OS << ", p (processor specific)\n";
4095
}
4096
4097
template <class ELFT> void GNUELFDumper<ELFT>::printSectionHeaders() {
4098
ArrayRef<Elf_Shdr> Sections = cantFail(this->Obj.sections());
4099
if (Sections.empty()) {
4100
OS << "\nThere are no sections in this file.\n";
4101
Expected<StringRef> SecStrTableOrErr =
4102
this->Obj.getSectionStringTable(Sections, this->WarningHandler);
4103
if (!SecStrTableOrErr)
4104
this->reportUniqueWarning(SecStrTableOrErr.takeError());
4105
return;
4106
}
4107
unsigned Bias = ELFT::Is64Bits ? 0 : 8;
4108
OS << "There are " << to_string(Sections.size())
4109
<< " section headers, starting at offset "
4110
<< "0x" << utohexstr(this->Obj.getHeader().e_shoff, /*LowerCase=*/true) << ":\n\n";
4111
OS << "Section Headers:\n";
4112
Field Fields[11] = {
4113
{"[Nr]", 2}, {"Name", 7}, {"Type", 25},
4114
{"Address", 41}, {"Off", 58 - Bias}, {"Size", 65 - Bias},
4115
{"ES", 72 - Bias}, {"Flg", 75 - Bias}, {"Lk", 79 - Bias},
4116
{"Inf", 82 - Bias}, {"Al", 86 - Bias}};
4117
for (const Field &F : Fields)
4118
printField(F);
4119
OS << "\n";
4120
4121
StringRef SecStrTable;
4122
if (Expected<StringRef> SecStrTableOrErr =
4123
this->Obj.getSectionStringTable(Sections, this->WarningHandler))
4124
SecStrTable = *SecStrTableOrErr;
4125
else
4126
this->reportUniqueWarning(SecStrTableOrErr.takeError());
4127
4128
size_t SectionIndex = 0;
4129
for (const Elf_Shdr &Sec : Sections) {
4130
Fields[0].Str = to_string(SectionIndex);
4131
if (SecStrTable.empty())
4132
Fields[1].Str = "<no-strings>";
4133
else
4134
Fields[1].Str = std::string(unwrapOrError<StringRef>(
4135
this->FileName, this->Obj.getSectionName(Sec, SecStrTable)));
4136
Fields[2].Str =
4137
getSectionTypeString(this->Obj.getHeader().e_machine, Sec.sh_type);
4138
Fields[3].Str =
4139
to_string(format_hex_no_prefix(Sec.sh_addr, ELFT::Is64Bits ? 16 : 8));
4140
Fields[4].Str = to_string(format_hex_no_prefix(Sec.sh_offset, 6));
4141
Fields[5].Str = to_string(format_hex_no_prefix(Sec.sh_size, 6));
4142
Fields[6].Str = to_string(format_hex_no_prefix(Sec.sh_entsize, 2));
4143
Fields[7].Str = getGNUFlags(this->Obj.getHeader().e_ident[ELF::EI_OSABI],
4144
this->Obj.getHeader().e_machine, Sec.sh_flags);
4145
Fields[8].Str = to_string(Sec.sh_link);
4146
Fields[9].Str = to_string(Sec.sh_info);
4147
Fields[10].Str = to_string(Sec.sh_addralign);
4148
4149
OS.PadToColumn(Fields[0].Column);
4150
OS << "[" << right_justify(Fields[0].Str, 2) << "]";
4151
for (int i = 1; i < 7; i++)
4152
printField(Fields[i]);
4153
OS.PadToColumn(Fields[7].Column);
4154
OS << right_justify(Fields[7].Str, 3);
4155
OS.PadToColumn(Fields[8].Column);
4156
OS << right_justify(Fields[8].Str, 2);
4157
OS.PadToColumn(Fields[9].Column);
4158
OS << right_justify(Fields[9].Str, 3);
4159
OS.PadToColumn(Fields[10].Column);
4160
OS << right_justify(Fields[10].Str, 2);
4161
OS << "\n";
4162
++SectionIndex;
4163
}
4164
printSectionDescription(OS, this->Obj.getHeader().e_machine);
4165
}
4166
4167
template <class ELFT>
4168
void GNUELFDumper<ELFT>::printSymtabMessage(const Elf_Shdr *Symtab,
4169
size_t Entries,
4170
bool NonVisibilityBitsUsed,
4171
bool ExtraSymInfo) const {
4172
StringRef Name;
4173
if (Symtab)
4174
Name = this->getPrintableSectionName(*Symtab);
4175
if (!Name.empty())
4176
OS << "\nSymbol table '" << Name << "'";
4177
else
4178
OS << "\nSymbol table for image";
4179
OS << " contains " << Entries << " entries:\n";
4180
4181
if (ELFT::Is64Bits) {
4182
OS << " Num: Value Size Type Bind Vis";
4183
if (ExtraSymInfo)
4184
OS << "+Other";
4185
} else {
4186
OS << " Num: Value Size Type Bind Vis";
4187
if (ExtraSymInfo)
4188
OS << "+Other";
4189
}
4190
4191
OS.PadToColumn((ELFT::Is64Bits ? 56 : 48) + (NonVisibilityBitsUsed ? 13 : 0));
4192
if (ExtraSymInfo)
4193
OS << "Ndx(SecName) Name [+ Version Info]\n";
4194
else
4195
OS << "Ndx Name\n";
4196
}
4197
4198
template <class ELFT>
4199
std::string GNUELFDumper<ELFT>::getSymbolSectionNdx(
4200
const Elf_Sym &Symbol, unsigned SymIndex, DataRegion<Elf_Word> ShndxTable,
4201
bool ExtraSymInfo) const {
4202
unsigned SectionIndex = Symbol.st_shndx;
4203
switch (SectionIndex) {
4204
case ELF::SHN_UNDEF:
4205
return "UND";
4206
case ELF::SHN_ABS:
4207
return "ABS";
4208
case ELF::SHN_COMMON:
4209
return "COM";
4210
case ELF::SHN_XINDEX: {
4211
Expected<uint32_t> IndexOrErr =
4212
object::getExtendedSymbolTableIndex<ELFT>(Symbol, SymIndex, ShndxTable);
4213
if (!IndexOrErr) {
4214
assert(Symbol.st_shndx == SHN_XINDEX &&
4215
"getExtendedSymbolTableIndex should only fail due to an invalid "
4216
"SHT_SYMTAB_SHNDX table/reference");
4217
this->reportUniqueWarning(IndexOrErr.takeError());
4218
return "RSV[0xffff]";
4219
}
4220
SectionIndex = *IndexOrErr;
4221
break;
4222
}
4223
default:
4224
// Find if:
4225
// Processor specific
4226
if (SectionIndex >= ELF::SHN_LOPROC && SectionIndex <= ELF::SHN_HIPROC)
4227
return std::string("PRC[0x") +
4228
to_string(format_hex_no_prefix(SectionIndex, 4)) + "]";
4229
// OS specific
4230
if (SectionIndex >= ELF::SHN_LOOS && SectionIndex <= ELF::SHN_HIOS)
4231
return std::string("OS[0x") +
4232
to_string(format_hex_no_prefix(SectionIndex, 4)) + "]";
4233
// Architecture reserved:
4234
if (SectionIndex >= ELF::SHN_LORESERVE &&
4235
SectionIndex <= ELF::SHN_HIRESERVE)
4236
return std::string("RSV[0x") +
4237
to_string(format_hex_no_prefix(SectionIndex, 4)) + "]";
4238
break;
4239
}
4240
4241
std::string Extra;
4242
if (ExtraSymInfo) {
4243
auto Sec = this->Obj.getSection(SectionIndex);
4244
if (!Sec) {
4245
this->reportUniqueWarning(Sec.takeError());
4246
} else {
4247
auto SecName = this->Obj.getSectionName(**Sec);
4248
if (!SecName)
4249
this->reportUniqueWarning(SecName.takeError());
4250
else
4251
Extra = Twine(" (" + *SecName + ")").str();
4252
}
4253
}
4254
return to_string(format_decimal(SectionIndex, 3)) + Extra;
4255
}
4256
4257
template <class ELFT>
4258
void GNUELFDumper<ELFT>::printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,
4259
DataRegion<Elf_Word> ShndxTable,
4260
std::optional<StringRef> StrTable,
4261
bool IsDynamic, bool NonVisibilityBitsUsed,
4262
bool ExtraSymInfo) const {
4263
unsigned Bias = ELFT::Is64Bits ? 8 : 0;
4264
Field Fields[8] = {0, 8, 17 + Bias, 23 + Bias,
4265
31 + Bias, 38 + Bias, 48 + Bias, 51 + Bias};
4266
Fields[0].Str = to_string(format_decimal(SymIndex, 6)) + ":";
4267
Fields[1].Str =
4268
to_string(format_hex_no_prefix(Symbol.st_value, ELFT::Is64Bits ? 16 : 8));
4269
Fields[2].Str = to_string(format_decimal(Symbol.st_size, 5));
4270
4271
unsigned char SymbolType = Symbol.getType();
4272
if (this->Obj.getHeader().e_machine == ELF::EM_AMDGPU &&
4273
SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS)
4274
Fields[3].Str = enumToString(SymbolType, ArrayRef(AMDGPUSymbolTypes));
4275
else
4276
Fields[3].Str = enumToString(SymbolType, ArrayRef(ElfSymbolTypes));
4277
4278
Fields[4].Str =
4279
enumToString(Symbol.getBinding(), ArrayRef(ElfSymbolBindings));
4280
Fields[5].Str =
4281
enumToString(Symbol.getVisibility(), ArrayRef(ElfSymbolVisibilities));
4282
4283
if (Symbol.st_other & ~0x3) {
4284
if (this->Obj.getHeader().e_machine == ELF::EM_AARCH64) {
4285
uint8_t Other = Symbol.st_other & ~0x3;
4286
if (Other & STO_AARCH64_VARIANT_PCS) {
4287
Other &= ~STO_AARCH64_VARIANT_PCS;
4288
Fields[5].Str += " [VARIANT_PCS";
4289
if (Other != 0)
4290
Fields[5].Str.append(" | " + utohexstr(Other, /*LowerCase=*/true));
4291
Fields[5].Str.append("]");
4292
}
4293
} else if (this->Obj.getHeader().e_machine == ELF::EM_RISCV) {
4294
uint8_t Other = Symbol.st_other & ~0x3;
4295
if (Other & STO_RISCV_VARIANT_CC) {
4296
Other &= ~STO_RISCV_VARIANT_CC;
4297
Fields[5].Str += " [VARIANT_CC";
4298
if (Other != 0)
4299
Fields[5].Str.append(" | " + utohexstr(Other, /*LowerCase=*/true));
4300
Fields[5].Str.append("]");
4301
}
4302
} else {
4303
Fields[5].Str +=
4304
" [<other: " + to_string(format_hex(Symbol.st_other, 2)) + ">]";
4305
}
4306
}
4307
4308
Fields[6].Column += NonVisibilityBitsUsed ? 13 : 0;
4309
Fields[6].Str =
4310
getSymbolSectionNdx(Symbol, SymIndex, ShndxTable, ExtraSymInfo);
4311
4312
Fields[7].Column += ExtraSymInfo ? 10 : 0;
4313
Fields[7].Str = this->getFullSymbolName(Symbol, SymIndex, ShndxTable,
4314
StrTable, IsDynamic);
4315
for (const Field &Entry : Fields)
4316
printField(Entry);
4317
OS << "\n";
4318
}
4319
4320
template <class ELFT>
4321
void GNUELFDumper<ELFT>::printHashedSymbol(const Elf_Sym *Symbol,
4322
unsigned SymIndex,
4323
DataRegion<Elf_Word> ShndxTable,
4324
StringRef StrTable,
4325
uint32_t Bucket) {
4326
unsigned Bias = ELFT::Is64Bits ? 8 : 0;
4327
Field Fields[9] = {0, 6, 11, 20 + Bias, 25 + Bias,
4328
34 + Bias, 41 + Bias, 49 + Bias, 53 + Bias};
4329
Fields[0].Str = to_string(format_decimal(SymIndex, 5));
4330
Fields[1].Str = to_string(format_decimal(Bucket, 3)) + ":";
4331
4332
Fields[2].Str = to_string(
4333
format_hex_no_prefix(Symbol->st_value, ELFT::Is64Bits ? 16 : 8));
4334
Fields[3].Str = to_string(format_decimal(Symbol->st_size, 5));
4335
4336
unsigned char SymbolType = Symbol->getType();
4337
if (this->Obj.getHeader().e_machine == ELF::EM_AMDGPU &&
4338
SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS)
4339
Fields[4].Str = enumToString(SymbolType, ArrayRef(AMDGPUSymbolTypes));
4340
else
4341
Fields[4].Str = enumToString(SymbolType, ArrayRef(ElfSymbolTypes));
4342
4343
Fields[5].Str =
4344
enumToString(Symbol->getBinding(), ArrayRef(ElfSymbolBindings));
4345
Fields[6].Str =
4346
enumToString(Symbol->getVisibility(), ArrayRef(ElfSymbolVisibilities));
4347
Fields[7].Str = getSymbolSectionNdx(*Symbol, SymIndex, ShndxTable);
4348
Fields[8].Str =
4349
this->getFullSymbolName(*Symbol, SymIndex, ShndxTable, StrTable, true);
4350
4351
for (const Field &Entry : Fields)
4352
printField(Entry);
4353
OS << "\n";
4354
}
4355
4356
template <class ELFT>
4357
void GNUELFDumper<ELFT>::printSymbols(bool PrintSymbols,
4358
bool PrintDynamicSymbols,
4359
bool ExtraSymInfo) {
4360
if (!PrintSymbols && !PrintDynamicSymbols)
4361
return;
4362
// GNU readelf prints both the .dynsym and .symtab with --symbols.
4363
this->printSymbolsHelper(true, ExtraSymInfo);
4364
if (PrintSymbols)
4365
this->printSymbolsHelper(false, ExtraSymInfo);
4366
}
4367
4368
template <class ELFT>
4369
void GNUELFDumper<ELFT>::printHashTableSymbols(const Elf_Hash &SysVHash) {
4370
if (this->DynamicStringTable.empty())
4371
return;
4372
4373
if (ELFT::Is64Bits)
4374
OS << " Num Buc: Value Size Type Bind Vis Ndx Name";
4375
else
4376
OS << " Num Buc: Value Size Type Bind Vis Ndx Name";
4377
OS << "\n";
4378
4379
Elf_Sym_Range DynSyms = this->dynamic_symbols();
4380
const Elf_Sym *FirstSym = DynSyms.empty() ? nullptr : &DynSyms[0];
4381
if (!FirstSym) {
4382
this->reportUniqueWarning(
4383
Twine("unable to print symbols for the .hash table: the "
4384
"dynamic symbol table ") +
4385
(this->DynSymRegion ? "is empty" : "was not found"));
4386
return;
4387
}
4388
4389
DataRegion<Elf_Word> ShndxTable(
4390
(const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end());
4391
auto Buckets = SysVHash.buckets();
4392
auto Chains = SysVHash.chains();
4393
for (uint32_t Buc = 0; Buc < SysVHash.nbucket; Buc++) {
4394
if (Buckets[Buc] == ELF::STN_UNDEF)
4395
continue;
4396
BitVector Visited(SysVHash.nchain);
4397
for (uint32_t Ch = Buckets[Buc]; Ch < SysVHash.nchain; Ch = Chains[Ch]) {
4398
if (Ch == ELF::STN_UNDEF)
4399
break;
4400
4401
if (Visited[Ch]) {
4402
this->reportUniqueWarning(".hash section is invalid: bucket " +
4403
Twine(Ch) +
4404
": a cycle was detected in the linked chain");
4405
break;
4406
}
4407
4408
printHashedSymbol(FirstSym + Ch, Ch, ShndxTable, this->DynamicStringTable,
4409
Buc);
4410
Visited[Ch] = true;
4411
}
4412
}
4413
}
4414
4415
template <class ELFT>
4416
void GNUELFDumper<ELFT>::printGnuHashTableSymbols(const Elf_GnuHash &GnuHash) {
4417
if (this->DynamicStringTable.empty())
4418
return;
4419
4420
Elf_Sym_Range DynSyms = this->dynamic_symbols();
4421
const Elf_Sym *FirstSym = DynSyms.empty() ? nullptr : &DynSyms[0];
4422
if (!FirstSym) {
4423
this->reportUniqueWarning(
4424
Twine("unable to print symbols for the .gnu.hash table: the "
4425
"dynamic symbol table ") +
4426
(this->DynSymRegion ? "is empty" : "was not found"));
4427
return;
4428
}
4429
4430
auto GetSymbol = [&](uint64_t SymIndex,
4431
uint64_t SymsTotal) -> const Elf_Sym * {
4432
if (SymIndex >= SymsTotal) {
4433
this->reportUniqueWarning(
4434
"unable to print hashed symbol with index " + Twine(SymIndex) +
4435
", which is greater than or equal to the number of dynamic symbols "
4436
"(" +
4437
Twine::utohexstr(SymsTotal) + ")");
4438
return nullptr;
4439
}
4440
return FirstSym + SymIndex;
4441
};
4442
4443
Expected<ArrayRef<Elf_Word>> ValuesOrErr =
4444
getGnuHashTableChains<ELFT>(this->DynSymRegion, &GnuHash);
4445
ArrayRef<Elf_Word> Values;
4446
if (!ValuesOrErr)
4447
this->reportUniqueWarning("unable to get hash values for the SHT_GNU_HASH "
4448
"section: " +
4449
toString(ValuesOrErr.takeError()));
4450
else
4451
Values = *ValuesOrErr;
4452
4453
DataRegion<Elf_Word> ShndxTable(
4454
(const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end());
4455
ArrayRef<Elf_Word> Buckets = GnuHash.buckets();
4456
for (uint32_t Buc = 0; Buc < GnuHash.nbuckets; Buc++) {
4457
if (Buckets[Buc] == ELF::STN_UNDEF)
4458
continue;
4459
uint32_t Index = Buckets[Buc];
4460
// Print whole chain.
4461
while (true) {
4462
uint32_t SymIndex = Index++;
4463
if (const Elf_Sym *Sym = GetSymbol(SymIndex, DynSyms.size()))
4464
printHashedSymbol(Sym, SymIndex, ShndxTable, this->DynamicStringTable,
4465
Buc);
4466
else
4467
break;
4468
4469
if (SymIndex < GnuHash.symndx) {
4470
this->reportUniqueWarning(
4471
"unable to read the hash value for symbol with index " +
4472
Twine(SymIndex) +
4473
", which is less than the index of the first hashed symbol (" +
4474
Twine(GnuHash.symndx) + ")");
4475
break;
4476
}
4477
4478
// Chain ends at symbol with stopper bit.
4479
if ((Values[SymIndex - GnuHash.symndx] & 1) == 1)
4480
break;
4481
}
4482
}
4483
}
4484
4485
template <class ELFT> void GNUELFDumper<ELFT>::printHashSymbols() {
4486
if (this->HashTable) {
4487
OS << "\n Symbol table of .hash for image:\n";
4488
if (Error E = checkHashTable<ELFT>(*this, this->HashTable))
4489
this->reportUniqueWarning(std::move(E));
4490
else
4491
printHashTableSymbols(*this->HashTable);
4492
}
4493
4494
// Try printing the .gnu.hash table.
4495
if (this->GnuHashTable) {
4496
OS << "\n Symbol table of .gnu.hash for image:\n";
4497
if (ELFT::Is64Bits)
4498
OS << " Num Buc: Value Size Type Bind Vis Ndx Name";
4499
else
4500
OS << " Num Buc: Value Size Type Bind Vis Ndx Name";
4501
OS << "\n";
4502
4503
if (Error E = checkGNUHashTable<ELFT>(this->Obj, this->GnuHashTable))
4504
this->reportUniqueWarning(std::move(E));
4505
else
4506
printGnuHashTableSymbols(*this->GnuHashTable);
4507
}
4508
}
4509
4510
template <class ELFT> void GNUELFDumper<ELFT>::printSectionDetails() {
4511
ArrayRef<Elf_Shdr> Sections = cantFail(this->Obj.sections());
4512
if (Sections.empty()) {
4513
OS << "\nThere are no sections in this file.\n";
4514
Expected<StringRef> SecStrTableOrErr =
4515
this->Obj.getSectionStringTable(Sections, this->WarningHandler);
4516
if (!SecStrTableOrErr)
4517
this->reportUniqueWarning(SecStrTableOrErr.takeError());
4518
return;
4519
}
4520
OS << "There are " << to_string(Sections.size())
4521
<< " section headers, starting at offset "
4522
<< "0x" << utohexstr(this->Obj.getHeader().e_shoff, /*LowerCase=*/true) << ":\n\n";
4523
4524
OS << "Section Headers:\n";
4525
4526
auto PrintFields = [&](ArrayRef<Field> V) {
4527
for (const Field &F : V)
4528
printField(F);
4529
OS << "\n";
4530
};
4531
4532
PrintFields({{"[Nr]", 2}, {"Name", 7}});
4533
4534
constexpr bool Is64 = ELFT::Is64Bits;
4535
PrintFields({{"Type", 7},
4536
{Is64 ? "Address" : "Addr", 23},
4537
{"Off", Is64 ? 40 : 32},
4538
{"Size", Is64 ? 47 : 39},
4539
{"ES", Is64 ? 54 : 46},
4540
{"Lk", Is64 ? 59 : 51},
4541
{"Inf", Is64 ? 62 : 54},
4542
{"Al", Is64 ? 66 : 57}});
4543
PrintFields({{"Flags", 7}});
4544
4545
StringRef SecStrTable;
4546
if (Expected<StringRef> SecStrTableOrErr =
4547
this->Obj.getSectionStringTable(Sections, this->WarningHandler))
4548
SecStrTable = *SecStrTableOrErr;
4549
else
4550
this->reportUniqueWarning(SecStrTableOrErr.takeError());
4551
4552
size_t SectionIndex = 0;
4553
const unsigned AddrSize = Is64 ? 16 : 8;
4554
for (const Elf_Shdr &S : Sections) {
4555
StringRef Name = "<?>";
4556
if (Expected<StringRef> NameOrErr =
4557
this->Obj.getSectionName(S, SecStrTable))
4558
Name = *NameOrErr;
4559
else
4560
this->reportUniqueWarning(NameOrErr.takeError());
4561
4562
OS.PadToColumn(2);
4563
OS << "[" << right_justify(to_string(SectionIndex), 2) << "]";
4564
PrintFields({{Name, 7}});
4565
PrintFields(
4566
{{getSectionTypeString(this->Obj.getHeader().e_machine, S.sh_type), 7},
4567
{to_string(format_hex_no_prefix(S.sh_addr, AddrSize)), 23},
4568
{to_string(format_hex_no_prefix(S.sh_offset, 6)), Is64 ? 39 : 32},
4569
{to_string(format_hex_no_prefix(S.sh_size, 6)), Is64 ? 47 : 39},
4570
{to_string(format_hex_no_prefix(S.sh_entsize, 2)), Is64 ? 54 : 46},
4571
{to_string(S.sh_link), Is64 ? 59 : 51},
4572
{to_string(S.sh_info), Is64 ? 63 : 55},
4573
{to_string(S.sh_addralign), Is64 ? 66 : 58}});
4574
4575
OS.PadToColumn(7);
4576
OS << "[" << to_string(format_hex_no_prefix(S.sh_flags, AddrSize)) << "]: ";
4577
4578
DenseMap<unsigned, StringRef> FlagToName = {
4579
{SHF_WRITE, "WRITE"}, {SHF_ALLOC, "ALLOC"},
4580
{SHF_EXECINSTR, "EXEC"}, {SHF_MERGE, "MERGE"},
4581
{SHF_STRINGS, "STRINGS"}, {SHF_INFO_LINK, "INFO LINK"},
4582
{SHF_LINK_ORDER, "LINK ORDER"}, {SHF_OS_NONCONFORMING, "OS NONCONF"},
4583
{SHF_GROUP, "GROUP"}, {SHF_TLS, "TLS"},
4584
{SHF_COMPRESSED, "COMPRESSED"}, {SHF_EXCLUDE, "EXCLUDE"}};
4585
4586
uint64_t Flags = S.sh_flags;
4587
uint64_t UnknownFlags = 0;
4588
ListSeparator LS;
4589
while (Flags) {
4590
// Take the least significant bit as a flag.
4591
uint64_t Flag = Flags & -Flags;
4592
Flags -= Flag;
4593
4594
auto It = FlagToName.find(Flag);
4595
if (It != FlagToName.end())
4596
OS << LS << It->second;
4597
else
4598
UnknownFlags |= Flag;
4599
}
4600
4601
auto PrintUnknownFlags = [&](uint64_t Mask, StringRef Name) {
4602
uint64_t FlagsToPrint = UnknownFlags & Mask;
4603
if (!FlagsToPrint)
4604
return;
4605
4606
OS << LS << Name << " ("
4607
<< to_string(format_hex_no_prefix(FlagsToPrint, AddrSize)) << ")";
4608
UnknownFlags &= ~Mask;
4609
};
4610
4611
PrintUnknownFlags(SHF_MASKOS, "OS");
4612
PrintUnknownFlags(SHF_MASKPROC, "PROC");
4613
PrintUnknownFlags(uint64_t(-1), "UNKNOWN");
4614
4615
OS << "\n";
4616
++SectionIndex;
4617
4618
if (!(S.sh_flags & SHF_COMPRESSED))
4619
continue;
4620
Expected<ArrayRef<uint8_t>> Data = this->Obj.getSectionContents(S);
4621
if (!Data || Data->size() < sizeof(Elf_Chdr)) {
4622
consumeError(Data.takeError());
4623
reportWarning(createError("SHF_COMPRESSED section '" + Name +
4624
"' does not have an Elf_Chdr header"),
4625
this->FileName);
4626
OS.indent(7);
4627
OS << "[<corrupt>]";
4628
} else {
4629
OS.indent(7);
4630
auto *Chdr = reinterpret_cast<const Elf_Chdr *>(Data->data());
4631
if (Chdr->ch_type == ELFCOMPRESS_ZLIB)
4632
OS << "ZLIB";
4633
else if (Chdr->ch_type == ELFCOMPRESS_ZSTD)
4634
OS << "ZSTD";
4635
else
4636
OS << format("[<unknown>: 0x%x]", unsigned(Chdr->ch_type));
4637
OS << ", " << format_hex_no_prefix(Chdr->ch_size, ELFT::Is64Bits ? 16 : 8)
4638
<< ", " << Chdr->ch_addralign;
4639
}
4640
OS << '\n';
4641
}
4642
}
4643
4644
static inline std::string printPhdrFlags(unsigned Flag) {
4645
std::string Str;
4646
Str = (Flag & PF_R) ? "R" : " ";
4647
Str += (Flag & PF_W) ? "W" : " ";
4648
Str += (Flag & PF_X) ? "E" : " ";
4649
return Str;
4650
}
4651
4652
template <class ELFT>
4653
static bool checkTLSSections(const typename ELFT::Phdr &Phdr,
4654
const typename ELFT::Shdr &Sec) {
4655
if (Sec.sh_flags & ELF::SHF_TLS) {
4656
// .tbss must only be shown in the PT_TLS segment.
4657
if (Sec.sh_type == ELF::SHT_NOBITS)
4658
return Phdr.p_type == ELF::PT_TLS;
4659
4660
// SHF_TLS sections are only shown in PT_TLS, PT_LOAD or PT_GNU_RELRO
4661
// segments.
4662
return (Phdr.p_type == ELF::PT_TLS) || (Phdr.p_type == ELF::PT_LOAD) ||
4663
(Phdr.p_type == ELF::PT_GNU_RELRO);
4664
}
4665
4666
// PT_TLS must only have SHF_TLS sections.
4667
return Phdr.p_type != ELF::PT_TLS;
4668
}
4669
4670
template <class ELFT>
4671
static bool checkPTDynamic(const typename ELFT::Phdr &Phdr,
4672
const typename ELFT::Shdr &Sec) {
4673
if (Phdr.p_type != ELF::PT_DYNAMIC || Phdr.p_memsz == 0 || Sec.sh_size != 0)
4674
return true;
4675
4676
// We get here when we have an empty section. Only non-empty sections can be
4677
// at the start or at the end of PT_DYNAMIC.
4678
// Is section within the phdr both based on offset and VMA?
4679
bool CheckOffset = (Sec.sh_type == ELF::SHT_NOBITS) ||
4680
(Sec.sh_offset > Phdr.p_offset &&
4681
Sec.sh_offset < Phdr.p_offset + Phdr.p_filesz);
4682
bool CheckVA = !(Sec.sh_flags & ELF::SHF_ALLOC) ||
4683
(Sec.sh_addr > Phdr.p_vaddr && Sec.sh_addr < Phdr.p_memsz);
4684
return CheckOffset && CheckVA;
4685
}
4686
4687
template <class ELFT>
4688
void GNUELFDumper<ELFT>::printProgramHeaders(
4689
bool PrintProgramHeaders, cl::boolOrDefault PrintSectionMapping) {
4690
const bool ShouldPrintSectionMapping = (PrintSectionMapping != cl::BOU_FALSE);
4691
// Exit early if no program header or section mapping details were requested.
4692
if (!PrintProgramHeaders && !ShouldPrintSectionMapping)
4693
return;
4694
4695
if (PrintProgramHeaders) {
4696
const Elf_Ehdr &Header = this->Obj.getHeader();
4697
if (Header.e_phnum == 0) {
4698
OS << "\nThere are no program headers in this file.\n";
4699
} else {
4700
printProgramHeaders();
4701
}
4702
}
4703
4704
if (ShouldPrintSectionMapping)
4705
printSectionMapping();
4706
}
4707
4708
template <class ELFT> void GNUELFDumper<ELFT>::printProgramHeaders() {
4709
unsigned Bias = ELFT::Is64Bits ? 8 : 0;
4710
const Elf_Ehdr &Header = this->Obj.getHeader();
4711
Field Fields[8] = {2, 17, 26, 37 + Bias,
4712
48 + Bias, 56 + Bias, 64 + Bias, 68 + Bias};
4713
OS << "\nElf file type is "
4714
<< enumToString(Header.e_type, ArrayRef(ElfObjectFileType)) << "\n"
4715
<< "Entry point " << format_hex(Header.e_entry, 3) << "\n"
4716
<< "There are " << Header.e_phnum << " program headers,"
4717
<< " starting at offset " << Header.e_phoff << "\n\n"
4718
<< "Program Headers:\n";
4719
if (ELFT::Is64Bits)
4720
OS << " Type Offset VirtAddr PhysAddr "
4721
<< " FileSiz MemSiz Flg Align\n";
4722
else
4723
OS << " Type Offset VirtAddr PhysAddr FileSiz "
4724
<< "MemSiz Flg Align\n";
4725
4726
unsigned Width = ELFT::Is64Bits ? 18 : 10;
4727
unsigned SizeWidth = ELFT::Is64Bits ? 8 : 7;
4728
4729
Expected<ArrayRef<Elf_Phdr>> PhdrsOrErr = this->Obj.program_headers();
4730
if (!PhdrsOrErr) {
4731
this->reportUniqueWarning("unable to dump program headers: " +
4732
toString(PhdrsOrErr.takeError()));
4733
return;
4734
}
4735
4736
for (const Elf_Phdr &Phdr : *PhdrsOrErr) {
4737
Fields[0].Str = getGNUPtType(Header.e_machine, Phdr.p_type);
4738
Fields[1].Str = to_string(format_hex(Phdr.p_offset, 8));
4739
Fields[2].Str = to_string(format_hex(Phdr.p_vaddr, Width));
4740
Fields[3].Str = to_string(format_hex(Phdr.p_paddr, Width));
4741
Fields[4].Str = to_string(format_hex(Phdr.p_filesz, SizeWidth));
4742
Fields[5].Str = to_string(format_hex(Phdr.p_memsz, SizeWidth));
4743
Fields[6].Str = printPhdrFlags(Phdr.p_flags);
4744
Fields[7].Str = to_string(format_hex(Phdr.p_align, 1));
4745
for (const Field &F : Fields)
4746
printField(F);
4747
if (Phdr.p_type == ELF::PT_INTERP) {
4748
OS << "\n";
4749
auto ReportBadInterp = [&](const Twine &Msg) {
4750
this->reportUniqueWarning(
4751
"unable to read program interpreter name at offset 0x" +
4752
Twine::utohexstr(Phdr.p_offset) + ": " + Msg);
4753
};
4754
4755
if (Phdr.p_offset >= this->Obj.getBufSize()) {
4756
ReportBadInterp("it goes past the end of the file (0x" +
4757
Twine::utohexstr(this->Obj.getBufSize()) + ")");
4758
continue;
4759
}
4760
4761
const char *Data =
4762
reinterpret_cast<const char *>(this->Obj.base()) + Phdr.p_offset;
4763
size_t MaxSize = this->Obj.getBufSize() - Phdr.p_offset;
4764
size_t Len = strnlen(Data, MaxSize);
4765
if (Len == MaxSize) {
4766
ReportBadInterp("it is not null-terminated");
4767
continue;
4768
}
4769
4770
OS << " [Requesting program interpreter: ";
4771
OS << StringRef(Data, Len) << "]";
4772
}
4773
OS << "\n";
4774
}
4775
}
4776
4777
template <class ELFT> void GNUELFDumper<ELFT>::printSectionMapping() {
4778
OS << "\n Section to Segment mapping:\n Segment Sections...\n";
4779
DenseSet<const Elf_Shdr *> BelongsToSegment;
4780
int Phnum = 0;
4781
4782
Expected<ArrayRef<Elf_Phdr>> PhdrsOrErr = this->Obj.program_headers();
4783
if (!PhdrsOrErr) {
4784
this->reportUniqueWarning(
4785
"can't read program headers to build section to segment mapping: " +
4786
toString(PhdrsOrErr.takeError()));
4787
return;
4788
}
4789
4790
for (const Elf_Phdr &Phdr : *PhdrsOrErr) {
4791
std::string Sections;
4792
OS << format(" %2.2d ", Phnum++);
4793
// Check if each section is in a segment and then print mapping.
4794
for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) {
4795
if (Sec.sh_type == ELF::SHT_NULL)
4796
continue;
4797
4798
// readelf additionally makes sure it does not print zero sized sections
4799
// at end of segments and for PT_DYNAMIC both start and end of section
4800
// .tbss must only be shown in PT_TLS section.
4801
if (isSectionInSegment<ELFT>(Phdr, Sec) &&
4802
checkTLSSections<ELFT>(Phdr, Sec) &&
4803
checkPTDynamic<ELFT>(Phdr, Sec)) {
4804
Sections +=
4805
unwrapOrError(this->FileName, this->Obj.getSectionName(Sec)).str() +
4806
" ";
4807
BelongsToSegment.insert(&Sec);
4808
}
4809
}
4810
OS << Sections << "\n";
4811
OS.flush();
4812
}
4813
4814
// Display sections that do not belong to a segment.
4815
std::string Sections;
4816
for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) {
4817
if (BelongsToSegment.find(&Sec) == BelongsToSegment.end())
4818
Sections +=
4819
unwrapOrError(this->FileName, this->Obj.getSectionName(Sec)).str() +
4820
' ';
4821
}
4822
if (!Sections.empty()) {
4823
OS << " None " << Sections << '\n';
4824
OS.flush();
4825
}
4826
}
4827
4828
namespace {
4829
4830
template <class ELFT>
4831
RelSymbol<ELFT> getSymbolForReloc(const ELFDumper<ELFT> &Dumper,
4832
const Relocation<ELFT> &Reloc) {
4833
using Elf_Sym = typename ELFT::Sym;
4834
auto WarnAndReturn = [&](const Elf_Sym *Sym,
4835
const Twine &Reason) -> RelSymbol<ELFT> {
4836
Dumper.reportUniqueWarning(
4837
"unable to get name of the dynamic symbol with index " +
4838
Twine(Reloc.Symbol) + ": " + Reason);
4839
return {Sym, "<corrupt>"};
4840
};
4841
4842
ArrayRef<Elf_Sym> Symbols = Dumper.dynamic_symbols();
4843
const Elf_Sym *FirstSym = Symbols.begin();
4844
if (!FirstSym)
4845
return WarnAndReturn(nullptr, "no dynamic symbol table found");
4846
4847
// We might have an object without a section header. In this case the size of
4848
// Symbols is zero, because there is no way to know the size of the dynamic
4849
// table. We should allow this case and not print a warning.
4850
if (!Symbols.empty() && Reloc.Symbol >= Symbols.size())
4851
return WarnAndReturn(
4852
nullptr,
4853
"index is greater than or equal to the number of dynamic symbols (" +
4854
Twine(Symbols.size()) + ")");
4855
4856
const ELFFile<ELFT> &Obj = Dumper.getElfObject().getELFFile();
4857
const uint64_t FileSize = Obj.getBufSize();
4858
const uint64_t SymOffset = ((const uint8_t *)FirstSym - Obj.base()) +
4859
(uint64_t)Reloc.Symbol * sizeof(Elf_Sym);
4860
if (SymOffset + sizeof(Elf_Sym) > FileSize)
4861
return WarnAndReturn(nullptr, "symbol at 0x" + Twine::utohexstr(SymOffset) +
4862
" goes past the end of the file (0x" +
4863
Twine::utohexstr(FileSize) + ")");
4864
4865
const Elf_Sym *Sym = FirstSym + Reloc.Symbol;
4866
Expected<StringRef> ErrOrName = Sym->getName(Dumper.getDynamicStringTable());
4867
if (!ErrOrName)
4868
return WarnAndReturn(Sym, toString(ErrOrName.takeError()));
4869
4870
return {Sym == FirstSym ? nullptr : Sym, maybeDemangle(*ErrOrName)};
4871
}
4872
} // namespace
4873
4874
template <class ELFT>
4875
static size_t getMaxDynamicTagSize(const ELFFile<ELFT> &Obj,
4876
typename ELFT::DynRange Tags) {
4877
size_t Max = 0;
4878
for (const typename ELFT::Dyn &Dyn : Tags)
4879
Max = std::max(Max, Obj.getDynamicTagAsString(Dyn.d_tag).size());
4880
return Max;
4881
}
4882
4883
template <class ELFT> void GNUELFDumper<ELFT>::printDynamicTable() {
4884
Elf_Dyn_Range Table = this->dynamic_table();
4885
if (Table.empty())
4886
return;
4887
4888
OS << "Dynamic section at offset "
4889
<< format_hex(reinterpret_cast<const uint8_t *>(this->DynamicTable.Addr) -
4890
this->Obj.base(),
4891
1)
4892
<< " contains " << Table.size() << " entries:\n";
4893
4894
// The type name is surrounded with round brackets, hence add 2.
4895
size_t MaxTagSize = getMaxDynamicTagSize(this->Obj, Table) + 2;
4896
// The "Name/Value" column should be indented from the "Type" column by N
4897
// spaces, where N = MaxTagSize - length of "Type" (4) + trailing
4898
// space (1) = 3.
4899
OS << " Tag" + std::string(ELFT::Is64Bits ? 16 : 8, ' ') + "Type"
4900
<< std::string(MaxTagSize - 3, ' ') << "Name/Value\n";
4901
4902
std::string ValueFmt = " %-" + std::to_string(MaxTagSize) + "s ";
4903
for (auto Entry : Table) {
4904
uintX_t Tag = Entry.getTag();
4905
std::string Type =
4906
std::string("(") + this->Obj.getDynamicTagAsString(Tag) + ")";
4907
std::string Value = this->getDynamicEntry(Tag, Entry.getVal());
4908
OS << " " << format_hex(Tag, ELFT::Is64Bits ? 18 : 10)
4909
<< format(ValueFmt.c_str(), Type.c_str()) << Value << "\n";
4910
}
4911
}
4912
4913
template <class ELFT> void GNUELFDumper<ELFT>::printDynamicRelocations() {
4914
this->printDynamicRelocationsHelper();
4915
}
4916
4917
template <class ELFT>
4918
void ELFDumper<ELFT>::printDynamicReloc(const Relocation<ELFT> &R) {
4919
printRelRelaReloc(R, getSymbolForReloc(*this, R));
4920
}
4921
4922
template <class ELFT>
4923
void ELFDumper<ELFT>::printRelocationsHelper(const Elf_Shdr &Sec) {
4924
this->forEachRelocationDo(
4925
Sec, [&](const Relocation<ELFT> &R, unsigned Ndx, const Elf_Shdr &Sec,
4926
const Elf_Shdr *SymTab) { printReloc(R, Ndx, Sec, SymTab); });
4927
}
4928
4929
template <class ELFT> void ELFDumper<ELFT>::printDynamicRelocationsHelper() {
4930
const bool IsMips64EL = this->Obj.isMips64EL();
4931
auto DumpCrelRegion = [&](DynRegionInfo &Region) {
4932
// While the size is unknown, a valid CREL has at least one byte. We can
4933
// check whether Addr is in bounds, and then decode CREL until the file
4934
// end.
4935
Region.Size = Region.EntSize = 1;
4936
if (!Region.template getAsArrayRef<uint8_t>().empty()) {
4937
const uint64_t Offset =
4938
Region.Addr - reinterpret_cast<const uint8_t *>(
4939
ObjF.getMemoryBufferRef().getBufferStart());
4940
const uint64_t ObjSize = ObjF.getMemoryBufferRef().getBufferSize();
4941
auto RelsOrRelas =
4942
Obj.decodeCrel(ArrayRef<uint8_t>(Region.Addr, ObjSize - Offset));
4943
if (!RelsOrRelas) {
4944
reportUniqueWarning(toString(RelsOrRelas.takeError()));
4945
} else {
4946
for (const Elf_Rel &R : RelsOrRelas->first)
4947
printDynamicReloc(Relocation<ELFT>(R, false));
4948
for (const Elf_Rela &R : RelsOrRelas->second)
4949
printDynamicReloc(Relocation<ELFT>(R, false));
4950
}
4951
}
4952
};
4953
4954
if (this->DynCrelRegion.Addr) {
4955
printDynamicRelocHeader(ELF::SHT_CREL, "CREL", this->DynCrelRegion);
4956
DumpCrelRegion(this->DynCrelRegion);
4957
}
4958
4959
if (this->DynRelaRegion.Size > 0) {
4960
printDynamicRelocHeader(ELF::SHT_RELA, "RELA", this->DynRelaRegion);
4961
for (const Elf_Rela &Rela :
4962
this->DynRelaRegion.template getAsArrayRef<Elf_Rela>())
4963
printDynamicReloc(Relocation<ELFT>(Rela, IsMips64EL));
4964
}
4965
4966
if (this->DynRelRegion.Size > 0) {
4967
printDynamicRelocHeader(ELF::SHT_REL, "REL", this->DynRelRegion);
4968
for (const Elf_Rel &Rel :
4969
this->DynRelRegion.template getAsArrayRef<Elf_Rel>())
4970
printDynamicReloc(Relocation<ELFT>(Rel, IsMips64EL));
4971
}
4972
4973
if (this->DynRelrRegion.Size > 0) {
4974
printDynamicRelocHeader(ELF::SHT_REL, "RELR", this->DynRelrRegion);
4975
Elf_Relr_Range Relrs =
4976
this->DynRelrRegion.template getAsArrayRef<Elf_Relr>();
4977
for (const Elf_Rel &Rel : Obj.decode_relrs(Relrs))
4978
printDynamicReloc(Relocation<ELFT>(Rel, IsMips64EL));
4979
}
4980
4981
if (this->DynPLTRelRegion.Size) {
4982
if (this->DynPLTRelRegion.EntSize == sizeof(Elf_Rela)) {
4983
printDynamicRelocHeader(ELF::SHT_RELA, "PLT", this->DynPLTRelRegion);
4984
for (const Elf_Rela &Rela :
4985
this->DynPLTRelRegion.template getAsArrayRef<Elf_Rela>())
4986
printDynamicReloc(Relocation<ELFT>(Rela, IsMips64EL));
4987
} else if (this->DynPLTRelRegion.EntSize == 1) {
4988
DumpCrelRegion(this->DynPLTRelRegion);
4989
} else {
4990
printDynamicRelocHeader(ELF::SHT_REL, "PLT", this->DynPLTRelRegion);
4991
for (const Elf_Rel &Rel :
4992
this->DynPLTRelRegion.template getAsArrayRef<Elf_Rel>())
4993
printDynamicReloc(Relocation<ELFT>(Rel, IsMips64EL));
4994
}
4995
}
4996
}
4997
4998
template <class ELFT>
4999
void GNUELFDumper<ELFT>::printGNUVersionSectionProlog(
5000
const typename ELFT::Shdr &Sec, const Twine &Label, unsigned EntriesNum) {
5001
// Don't inline the SecName, because it might report a warning to stderr and
5002
// corrupt the output.
5003
StringRef SecName = this->getPrintableSectionName(Sec);
5004
OS << Label << " section '" << SecName << "' "
5005
<< "contains " << EntriesNum << " entries:\n";
5006
5007
StringRef LinkedSecName = "<corrupt>";
5008
if (Expected<const typename ELFT::Shdr *> LinkedSecOrErr =
5009
this->Obj.getSection(Sec.sh_link))
5010
LinkedSecName = this->getPrintableSectionName(**LinkedSecOrErr);
5011
else
5012
this->reportUniqueWarning("invalid section linked to " +
5013
this->describe(Sec) + ": " +
5014
toString(LinkedSecOrErr.takeError()));
5015
5016
OS << " Addr: " << format_hex_no_prefix(Sec.sh_addr, 16)
5017
<< " Offset: " << format_hex(Sec.sh_offset, 8)
5018
<< " Link: " << Sec.sh_link << " (" << LinkedSecName << ")\n";
5019
}
5020
5021
template <class ELFT>
5022
void GNUELFDumper<ELFT>::printVersionSymbolSection(const Elf_Shdr *Sec) {
5023
if (!Sec)
5024
return;
5025
5026
printGNUVersionSectionProlog(*Sec, "Version symbols",
5027
Sec->sh_size / sizeof(Elf_Versym));
5028
Expected<ArrayRef<Elf_Versym>> VerTableOrErr =
5029
this->getVersionTable(*Sec, /*SymTab=*/nullptr,
5030
/*StrTab=*/nullptr, /*SymTabSec=*/nullptr);
5031
if (!VerTableOrErr) {
5032
this->reportUniqueWarning(VerTableOrErr.takeError());
5033
return;
5034
}
5035
5036
SmallVector<std::optional<VersionEntry>, 0> *VersionMap = nullptr;
5037
if (Expected<SmallVector<std::optional<VersionEntry>, 0> *> MapOrErr =
5038
this->getVersionMap())
5039
VersionMap = *MapOrErr;
5040
else
5041
this->reportUniqueWarning(MapOrErr.takeError());
5042
5043
ArrayRef<Elf_Versym> VerTable = *VerTableOrErr;
5044
std::vector<StringRef> Versions;
5045
for (size_t I = 0, E = VerTable.size(); I < E; ++I) {
5046
unsigned Ndx = VerTable[I].vs_index;
5047
if (Ndx == VER_NDX_LOCAL || Ndx == VER_NDX_GLOBAL) {
5048
Versions.emplace_back(Ndx == VER_NDX_LOCAL ? "*local*" : "*global*");
5049
continue;
5050
}
5051
5052
if (!VersionMap) {
5053
Versions.emplace_back("<corrupt>");
5054
continue;
5055
}
5056
5057
bool IsDefault;
5058
Expected<StringRef> NameOrErr = this->Obj.getSymbolVersionByIndex(
5059
Ndx, IsDefault, *VersionMap, /*IsSymHidden=*/std::nullopt);
5060
if (!NameOrErr) {
5061
this->reportUniqueWarning("unable to get a version for entry " +
5062
Twine(I) + " of " + this->describe(*Sec) +
5063
": " + toString(NameOrErr.takeError()));
5064
Versions.emplace_back("<corrupt>");
5065
continue;
5066
}
5067
Versions.emplace_back(*NameOrErr);
5068
}
5069
5070
// readelf prints 4 entries per line.
5071
uint64_t Entries = VerTable.size();
5072
for (uint64_t VersymRow = 0; VersymRow < Entries; VersymRow += 4) {
5073
OS << " " << format_hex_no_prefix(VersymRow, 3) << ":";
5074
for (uint64_t I = 0; (I < 4) && (I + VersymRow) < Entries; ++I) {
5075
unsigned Ndx = VerTable[VersymRow + I].vs_index;
5076
OS << format("%4x%c", Ndx & VERSYM_VERSION,
5077
Ndx & VERSYM_HIDDEN ? 'h' : ' ');
5078
OS << left_justify("(" + std::string(Versions[VersymRow + I]) + ")", 13);
5079
}
5080
OS << '\n';
5081
}
5082
OS << '\n';
5083
}
5084
5085
static std::string versionFlagToString(unsigned Flags) {
5086
if (Flags == 0)
5087
return "none";
5088
5089
std::string Ret;
5090
auto AddFlag = [&Ret, &Flags](unsigned Flag, StringRef Name) {
5091
if (!(Flags & Flag))
5092
return;
5093
if (!Ret.empty())
5094
Ret += " | ";
5095
Ret += Name;
5096
Flags &= ~Flag;
5097
};
5098
5099
AddFlag(VER_FLG_BASE, "BASE");
5100
AddFlag(VER_FLG_WEAK, "WEAK");
5101
AddFlag(VER_FLG_INFO, "INFO");
5102
AddFlag(~0, "<unknown>");
5103
return Ret;
5104
}
5105
5106
template <class ELFT>
5107
void GNUELFDumper<ELFT>::printVersionDefinitionSection(const Elf_Shdr *Sec) {
5108
if (!Sec)
5109
return;
5110
5111
printGNUVersionSectionProlog(*Sec, "Version definition", Sec->sh_info);
5112
5113
Expected<std::vector<VerDef>> V = this->Obj.getVersionDefinitions(*Sec);
5114
if (!V) {
5115
this->reportUniqueWarning(V.takeError());
5116
return;
5117
}
5118
5119
for (const VerDef &Def : *V) {
5120
OS << format(" 0x%04x: Rev: %u Flags: %s Index: %u Cnt: %u Name: %s\n",
5121
Def.Offset, Def.Version,
5122
versionFlagToString(Def.Flags).c_str(), Def.Ndx, Def.Cnt,
5123
Def.Name.data());
5124
unsigned I = 0;
5125
for (const VerdAux &Aux : Def.AuxV)
5126
OS << format(" 0x%04x: Parent %u: %s\n", Aux.Offset, ++I,
5127
Aux.Name.data());
5128
}
5129
5130
OS << '\n';
5131
}
5132
5133
template <class ELFT>
5134
void GNUELFDumper<ELFT>::printVersionDependencySection(const Elf_Shdr *Sec) {
5135
if (!Sec)
5136
return;
5137
5138
unsigned VerneedNum = Sec->sh_info;
5139
printGNUVersionSectionProlog(*Sec, "Version needs", VerneedNum);
5140
5141
Expected<std::vector<VerNeed>> V =
5142
this->Obj.getVersionDependencies(*Sec, this->WarningHandler);
5143
if (!V) {
5144
this->reportUniqueWarning(V.takeError());
5145
return;
5146
}
5147
5148
for (const VerNeed &VN : *V) {
5149
OS << format(" 0x%04x: Version: %u File: %s Cnt: %u\n", VN.Offset,
5150
VN.Version, VN.File.data(), VN.Cnt);
5151
for (const VernAux &Aux : VN.AuxV)
5152
OS << format(" 0x%04x: Name: %s Flags: %s Version: %u\n", Aux.Offset,
5153
Aux.Name.data(), versionFlagToString(Aux.Flags).c_str(),
5154
Aux.Other);
5155
}
5156
OS << '\n';
5157
}
5158
5159
template <class ELFT>
5160
void GNUELFDumper<ELFT>::printHashHistogramStats(size_t NBucket,
5161
size_t MaxChain,
5162
size_t TotalSyms,
5163
ArrayRef<size_t> Count,
5164
bool IsGnu) const {
5165
size_t CumulativeNonZero = 0;
5166
OS << "Histogram for" << (IsGnu ? " `.gnu.hash'" : "")
5167
<< " bucket list length (total of " << NBucket << " buckets)\n"
5168
<< " Length Number % of total Coverage\n";
5169
for (size_t I = 0; I < MaxChain; ++I) {
5170
CumulativeNonZero += Count[I] * I;
5171
OS << format("%7lu %-10lu (%5.1f%%) %5.1f%%\n", I, Count[I],
5172
(Count[I] * 100.0) / NBucket,
5173
(CumulativeNonZero * 100.0) / TotalSyms);
5174
}
5175
}
5176
5177
template <class ELFT> void GNUELFDumper<ELFT>::printCGProfile() {
5178
OS << "GNUStyle::printCGProfile not implemented\n";
5179
}
5180
5181
template <class ELFT>
5182
void GNUELFDumper<ELFT>::printBBAddrMaps(bool /*PrettyPGOAnalysis*/) {
5183
OS << "GNUStyle::printBBAddrMaps not implemented\n";
5184
}
5185
5186
static Expected<std::vector<uint64_t>> toULEB128Array(ArrayRef<uint8_t> Data) {
5187
std::vector<uint64_t> Ret;
5188
const uint8_t *Cur = Data.begin();
5189
const uint8_t *End = Data.end();
5190
while (Cur != End) {
5191
unsigned Size;
5192
const char *Err = nullptr;
5193
Ret.push_back(decodeULEB128(Cur, &Size, End, &Err));
5194
if (Err)
5195
return createError(Err);
5196
Cur += Size;
5197
}
5198
return Ret;
5199
}
5200
5201
template <class ELFT>
5202
static Expected<std::vector<uint64_t>>
5203
decodeAddrsigSection(const ELFFile<ELFT> &Obj, const typename ELFT::Shdr &Sec) {
5204
Expected<ArrayRef<uint8_t>> ContentsOrErr = Obj.getSectionContents(Sec);
5205
if (!ContentsOrErr)
5206
return ContentsOrErr.takeError();
5207
5208
if (Expected<std::vector<uint64_t>> SymsOrErr =
5209
toULEB128Array(*ContentsOrErr))
5210
return *SymsOrErr;
5211
else
5212
return createError("unable to decode " + describe(Obj, Sec) + ": " +
5213
toString(SymsOrErr.takeError()));
5214
}
5215
5216
template <class ELFT> void GNUELFDumper<ELFT>::printAddrsig() {
5217
if (!this->DotAddrsigSec)
5218
return;
5219
5220
Expected<std::vector<uint64_t>> SymsOrErr =
5221
decodeAddrsigSection(this->Obj, *this->DotAddrsigSec);
5222
if (!SymsOrErr) {
5223
this->reportUniqueWarning(SymsOrErr.takeError());
5224
return;
5225
}
5226
5227
StringRef Name = this->getPrintableSectionName(*this->DotAddrsigSec);
5228
OS << "\nAddress-significant symbols section '" << Name << "'"
5229
<< " contains " << SymsOrErr->size() << " entries:\n";
5230
OS << " Num: Name\n";
5231
5232
Field Fields[2] = {0, 8};
5233
size_t SymIndex = 0;
5234
for (uint64_t Sym : *SymsOrErr) {
5235
Fields[0].Str = to_string(format_decimal(++SymIndex, 6)) + ":";
5236
Fields[1].Str = this->getStaticSymbolName(Sym);
5237
for (const Field &Entry : Fields)
5238
printField(Entry);
5239
OS << "\n";
5240
}
5241
}
5242
5243
template <class ELFT>
5244
static bool printAArch64PAuthABICoreInfo(raw_ostream &OS, uint32_t DataSize,
5245
ArrayRef<uint8_t> Desc) {
5246
OS << " AArch64 PAuth ABI core info: ";
5247
// DataSize - size without padding, Desc.size() - size with padding
5248
if (DataSize != 16) {
5249
OS << format("<corrupted size: expected 16, got %d>", DataSize);
5250
return false;
5251
}
5252
5253
uint64_t Platform =
5254
support::endian::read64<ELFT::Endianness>(Desc.data() + 0);
5255
uint64_t Version = support::endian::read64<ELFT::Endianness>(Desc.data() + 8);
5256
5257
const char *PlatformDesc = [Platform]() {
5258
switch (Platform) {
5259
case AARCH64_PAUTH_PLATFORM_INVALID:
5260
return "invalid";
5261
case AARCH64_PAUTH_PLATFORM_BAREMETAL:
5262
return "baremetal";
5263
case AARCH64_PAUTH_PLATFORM_LLVM_LINUX:
5264
return "llvm_linux";
5265
default:
5266
return "unknown";
5267
}
5268
}();
5269
5270
std::string VersionDesc = [Platform, Version]() -> std::string {
5271
if (Platform != AARCH64_PAUTH_PLATFORM_LLVM_LINUX)
5272
return "";
5273
if (Version >= (1 << (AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_LAST + 1)))
5274
return "unknown";
5275
5276
std::array<StringRef, AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_LAST + 1>
5277
Flags;
5278
Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INTRINSICS] = "Intrinsics";
5279
Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_CALLS] = "Calls";
5280
Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_RETURNS] = "Returns";
5281
Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_AUTHTRAPS] = "AuthTraps";
5282
Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_VPTRADDRDISCR] =
5283
"VTPtrAddressDiscrimination";
5284
Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_VPTRTYPEDISCR] =
5285
"VTPtrTypeDiscrimination";
5286
Flags[AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INITFINI] = "InitFini";
5287
5288
static_assert(AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INITFINI ==
5289
AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_LAST,
5290
"Update when new enum items are defined");
5291
5292
std::string Desc;
5293
for (uint32_t I = 0, End = Flags.size(); I < End; ++I) {
5294
if (!(Version & (1ULL << I)))
5295
Desc += '!';
5296
Desc +=
5297
Twine("PointerAuth" + Flags[I] + (I == End - 1 ? "" : ", ")).str();
5298
}
5299
return Desc;
5300
}();
5301
5302
OS << format("platform 0x%" PRIx64 " (%s), version 0x%" PRIx64, Platform,
5303
PlatformDesc, Version);
5304
if (!VersionDesc.empty())
5305
OS << format(" (%s)", VersionDesc.c_str());
5306
5307
return true;
5308
}
5309
5310
template <typename ELFT>
5311
static std::string getGNUProperty(uint32_t Type, uint32_t DataSize,
5312
ArrayRef<uint8_t> Data) {
5313
std::string str;
5314
raw_string_ostream OS(str);
5315
uint32_t PrData;
5316
auto DumpBit = [&](uint32_t Flag, StringRef Name) {
5317
if (PrData & Flag) {
5318
PrData &= ~Flag;
5319
OS << Name;
5320
if (PrData)
5321
OS << ", ";
5322
}
5323
};
5324
5325
switch (Type) {
5326
default:
5327
OS << format("<application-specific type 0x%x>", Type);
5328
return OS.str();
5329
case GNU_PROPERTY_STACK_SIZE: {
5330
OS << "stack size: ";
5331
if (DataSize == sizeof(typename ELFT::uint))
5332
OS << formatv("{0:x}",
5333
(uint64_t)(*(const typename ELFT::Addr *)Data.data()));
5334
else
5335
OS << format("<corrupt length: 0x%x>", DataSize);
5336
return OS.str();
5337
}
5338
case GNU_PROPERTY_NO_COPY_ON_PROTECTED:
5339
OS << "no copy on protected";
5340
if (DataSize)
5341
OS << format(" <corrupt length: 0x%x>", DataSize);
5342
return OS.str();
5343
case GNU_PROPERTY_AARCH64_FEATURE_1_AND:
5344
case GNU_PROPERTY_X86_FEATURE_1_AND:
5345
OS << ((Type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) ? "aarch64 feature: "
5346
: "x86 feature: ");
5347
if (DataSize != 4) {
5348
OS << format("<corrupt length: 0x%x>", DataSize);
5349
return OS.str();
5350
}
5351
PrData = endian::read32<ELFT::Endianness>(Data.data());
5352
if (PrData == 0) {
5353
OS << "<None>";
5354
return OS.str();
5355
}
5356
if (Type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) {
5357
DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_BTI, "BTI");
5358
DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_PAC, "PAC");
5359
DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_GCS, "GCS");
5360
} else {
5361
DumpBit(GNU_PROPERTY_X86_FEATURE_1_IBT, "IBT");
5362
DumpBit(GNU_PROPERTY_X86_FEATURE_1_SHSTK, "SHSTK");
5363
}
5364
if (PrData)
5365
OS << format("<unknown flags: 0x%x>", PrData);
5366
return OS.str();
5367
case GNU_PROPERTY_AARCH64_FEATURE_PAUTH:
5368
printAArch64PAuthABICoreInfo<ELFT>(OS, DataSize, Data);
5369
return OS.str();
5370
case GNU_PROPERTY_X86_FEATURE_2_NEEDED:
5371
case GNU_PROPERTY_X86_FEATURE_2_USED:
5372
OS << "x86 feature "
5373
<< (Type == GNU_PROPERTY_X86_FEATURE_2_NEEDED ? "needed: " : "used: ");
5374
if (DataSize != 4) {
5375
OS << format("<corrupt length: 0x%x>", DataSize);
5376
return OS.str();
5377
}
5378
PrData = endian::read32<ELFT::Endianness>(Data.data());
5379
if (PrData == 0) {
5380
OS << "<None>";
5381
return OS.str();
5382
}
5383
DumpBit(GNU_PROPERTY_X86_FEATURE_2_X86, "x86");
5384
DumpBit(GNU_PROPERTY_X86_FEATURE_2_X87, "x87");
5385
DumpBit(GNU_PROPERTY_X86_FEATURE_2_MMX, "MMX");
5386
DumpBit(GNU_PROPERTY_X86_FEATURE_2_XMM, "XMM");
5387
DumpBit(GNU_PROPERTY_X86_FEATURE_2_YMM, "YMM");
5388
DumpBit(GNU_PROPERTY_X86_FEATURE_2_ZMM, "ZMM");
5389
DumpBit(GNU_PROPERTY_X86_FEATURE_2_FXSR, "FXSR");
5390
DumpBit(GNU_PROPERTY_X86_FEATURE_2_XSAVE, "XSAVE");
5391
DumpBit(GNU_PROPERTY_X86_FEATURE_2_XSAVEOPT, "XSAVEOPT");
5392
DumpBit(GNU_PROPERTY_X86_FEATURE_2_XSAVEC, "XSAVEC");
5393
if (PrData)
5394
OS << format("<unknown flags: 0x%x>", PrData);
5395
return OS.str();
5396
case GNU_PROPERTY_X86_ISA_1_NEEDED:
5397
case GNU_PROPERTY_X86_ISA_1_USED:
5398
OS << "x86 ISA "
5399
<< (Type == GNU_PROPERTY_X86_ISA_1_NEEDED ? "needed: " : "used: ");
5400
if (DataSize != 4) {
5401
OS << format("<corrupt length: 0x%x>", DataSize);
5402
return OS.str();
5403
}
5404
PrData = endian::read32<ELFT::Endianness>(Data.data());
5405
if (PrData == 0) {
5406
OS << "<None>";
5407
return OS.str();
5408
}
5409
DumpBit(GNU_PROPERTY_X86_ISA_1_BASELINE, "x86-64-baseline");
5410
DumpBit(GNU_PROPERTY_X86_ISA_1_V2, "x86-64-v2");
5411
DumpBit(GNU_PROPERTY_X86_ISA_1_V3, "x86-64-v3");
5412
DumpBit(GNU_PROPERTY_X86_ISA_1_V4, "x86-64-v4");
5413
if (PrData)
5414
OS << format("<unknown flags: 0x%x>", PrData);
5415
return OS.str();
5416
}
5417
}
5418
5419
template <typename ELFT>
5420
static SmallVector<std::string, 4> getGNUPropertyList(ArrayRef<uint8_t> Arr) {
5421
using Elf_Word = typename ELFT::Word;
5422
5423
SmallVector<std::string, 4> Properties;
5424
while (Arr.size() >= 8) {
5425
uint32_t Type = *reinterpret_cast<const Elf_Word *>(Arr.data());
5426
uint32_t DataSize = *reinterpret_cast<const Elf_Word *>(Arr.data() + 4);
5427
Arr = Arr.drop_front(8);
5428
5429
// Take padding size into account if present.
5430
uint64_t PaddedSize = alignTo(DataSize, sizeof(typename ELFT::uint));
5431
std::string str;
5432
raw_string_ostream OS(str);
5433
if (Arr.size() < PaddedSize) {
5434
OS << format("<corrupt type (0x%x) datasz: 0x%x>", Type, DataSize);
5435
Properties.push_back(OS.str());
5436
break;
5437
}
5438
Properties.push_back(
5439
getGNUProperty<ELFT>(Type, DataSize, Arr.take_front(PaddedSize)));
5440
Arr = Arr.drop_front(PaddedSize);
5441
}
5442
5443
if (!Arr.empty())
5444
Properties.push_back("<corrupted GNU_PROPERTY_TYPE_0>");
5445
5446
return Properties;
5447
}
5448
5449
struct GNUAbiTag {
5450
std::string OSName;
5451
std::string ABI;
5452
bool IsValid;
5453
};
5454
5455
template <typename ELFT> static GNUAbiTag getGNUAbiTag(ArrayRef<uint8_t> Desc) {
5456
typedef typename ELFT::Word Elf_Word;
5457
5458
ArrayRef<Elf_Word> Words(reinterpret_cast<const Elf_Word *>(Desc.begin()),
5459
reinterpret_cast<const Elf_Word *>(Desc.end()));
5460
5461
if (Words.size() < 4)
5462
return {"", "", /*IsValid=*/false};
5463
5464
static const char *OSNames[] = {
5465
"Linux", "Hurd", "Solaris", "FreeBSD", "NetBSD", "Syllable", "NaCl",
5466
};
5467
StringRef OSName = "Unknown";
5468
if (Words[0] < std::size(OSNames))
5469
OSName = OSNames[Words[0]];
5470
uint32_t Major = Words[1], Minor = Words[2], Patch = Words[3];
5471
std::string str;
5472
raw_string_ostream ABI(str);
5473
ABI << Major << "." << Minor << "." << Patch;
5474
return {std::string(OSName), ABI.str(), /*IsValid=*/true};
5475
}
5476
5477
static std::string getGNUBuildId(ArrayRef<uint8_t> Desc) {
5478
std::string str;
5479
raw_string_ostream OS(str);
5480
for (uint8_t B : Desc)
5481
OS << format_hex_no_prefix(B, 2);
5482
return OS.str();
5483
}
5484
5485
static StringRef getDescAsStringRef(ArrayRef<uint8_t> Desc) {
5486
return StringRef(reinterpret_cast<const char *>(Desc.data()), Desc.size());
5487
}
5488
5489
template <typename ELFT>
5490
static bool printGNUNote(raw_ostream &OS, uint32_t NoteType,
5491
ArrayRef<uint8_t> Desc) {
5492
// Return true if we were able to pretty-print the note, false otherwise.
5493
switch (NoteType) {
5494
default:
5495
return false;
5496
case ELF::NT_GNU_ABI_TAG: {
5497
const GNUAbiTag &AbiTag = getGNUAbiTag<ELFT>(Desc);
5498
if (!AbiTag.IsValid)
5499
OS << " <corrupt GNU_ABI_TAG>";
5500
else
5501
OS << " OS: " << AbiTag.OSName << ", ABI: " << AbiTag.ABI;
5502
break;
5503
}
5504
case ELF::NT_GNU_BUILD_ID: {
5505
OS << " Build ID: " << getGNUBuildId(Desc);
5506
break;
5507
}
5508
case ELF::NT_GNU_GOLD_VERSION:
5509
OS << " Version: " << getDescAsStringRef(Desc);
5510
break;
5511
case ELF::NT_GNU_PROPERTY_TYPE_0:
5512
OS << " Properties:";
5513
for (const std::string &Property : getGNUPropertyList<ELFT>(Desc))
5514
OS << " " << Property << "\n";
5515
break;
5516
}
5517
OS << '\n';
5518
return true;
5519
}
5520
5521
using AndroidNoteProperties = std::vector<std::pair<StringRef, std::string>>;
5522
static AndroidNoteProperties getAndroidNoteProperties(uint32_t NoteType,
5523
ArrayRef<uint8_t> Desc) {
5524
AndroidNoteProperties Props;
5525
switch (NoteType) {
5526
case ELF::NT_ANDROID_TYPE_MEMTAG:
5527
if (Desc.empty()) {
5528
Props.emplace_back("Invalid .note.android.memtag", "");
5529
return Props;
5530
}
5531
5532
switch (Desc[0] & NT_MEMTAG_LEVEL_MASK) {
5533
case NT_MEMTAG_LEVEL_NONE:
5534
Props.emplace_back("Tagging Mode", "NONE");
5535
break;
5536
case NT_MEMTAG_LEVEL_ASYNC:
5537
Props.emplace_back("Tagging Mode", "ASYNC");
5538
break;
5539
case NT_MEMTAG_LEVEL_SYNC:
5540
Props.emplace_back("Tagging Mode", "SYNC");
5541
break;
5542
default:
5543
Props.emplace_back(
5544
"Tagging Mode",
5545
("Unknown (" + Twine::utohexstr(Desc[0] & NT_MEMTAG_LEVEL_MASK) + ")")
5546
.str());
5547
break;
5548
}
5549
Props.emplace_back("Heap",
5550
(Desc[0] & NT_MEMTAG_HEAP) ? "Enabled" : "Disabled");
5551
Props.emplace_back("Stack",
5552
(Desc[0] & NT_MEMTAG_STACK) ? "Enabled" : "Disabled");
5553
break;
5554
default:
5555
return Props;
5556
}
5557
return Props;
5558
}
5559
5560
static bool printAndroidNote(raw_ostream &OS, uint32_t NoteType,
5561
ArrayRef<uint8_t> Desc) {
5562
// Return true if we were able to pretty-print the note, false otherwise.
5563
AndroidNoteProperties Props = getAndroidNoteProperties(NoteType, Desc);
5564
if (Props.empty())
5565
return false;
5566
for (const auto &KV : Props)
5567
OS << " " << KV.first << ": " << KV.second << '\n';
5568
return true;
5569
}
5570
5571
template <class ELFT>
5572
void GNUELFDumper<ELFT>::printMemtag(
5573
const ArrayRef<std::pair<std::string, std::string>> DynamicEntries,
5574
const ArrayRef<uint8_t> AndroidNoteDesc,
5575
const ArrayRef<std::pair<uint64_t, uint64_t>> Descriptors) {
5576
OS << "Memtag Dynamic Entries:\n";
5577
if (DynamicEntries.empty())
5578
OS << " < none found >\n";
5579
for (const auto &DynamicEntryKV : DynamicEntries)
5580
OS << " " << DynamicEntryKV.first << ": " << DynamicEntryKV.second
5581
<< "\n";
5582
5583
if (!AndroidNoteDesc.empty()) {
5584
OS << "Memtag Android Note:\n";
5585
printAndroidNote(OS, ELF::NT_ANDROID_TYPE_MEMTAG, AndroidNoteDesc);
5586
}
5587
5588
if (Descriptors.empty())
5589
return;
5590
5591
OS << "Memtag Global Descriptors:\n";
5592
for (const auto &[Addr, BytesToTag] : Descriptors) {
5593
OS << " 0x" << utohexstr(Addr, /*LowerCase=*/true) << ": 0x"
5594
<< utohexstr(BytesToTag, /*LowerCase=*/true) << "\n";
5595
}
5596
}
5597
5598
template <typename ELFT>
5599
static bool printLLVMOMPOFFLOADNote(raw_ostream &OS, uint32_t NoteType,
5600
ArrayRef<uint8_t> Desc) {
5601
switch (NoteType) {
5602
default:
5603
return false;
5604
case ELF::NT_LLVM_OPENMP_OFFLOAD_VERSION:
5605
OS << " Version: " << getDescAsStringRef(Desc);
5606
break;
5607
case ELF::NT_LLVM_OPENMP_OFFLOAD_PRODUCER:
5608
OS << " Producer: " << getDescAsStringRef(Desc);
5609
break;
5610
case ELF::NT_LLVM_OPENMP_OFFLOAD_PRODUCER_VERSION:
5611
OS << " Producer version: " << getDescAsStringRef(Desc);
5612
break;
5613
}
5614
OS << '\n';
5615
return true;
5616
}
5617
5618
const EnumEntry<unsigned> FreeBSDFeatureCtlFlags[] = {
5619
{"ASLR_DISABLE", NT_FREEBSD_FCTL_ASLR_DISABLE},
5620
{"PROTMAX_DISABLE", NT_FREEBSD_FCTL_PROTMAX_DISABLE},
5621
{"STKGAP_DISABLE", NT_FREEBSD_FCTL_STKGAP_DISABLE},
5622
{"WXNEEDED", NT_FREEBSD_FCTL_WXNEEDED},
5623
{"LA48", NT_FREEBSD_FCTL_LA48},
5624
{"ASG_DISABLE", NT_FREEBSD_FCTL_ASG_DISABLE},
5625
};
5626
5627
struct FreeBSDNote {
5628
std::string Type;
5629
std::string Value;
5630
};
5631
5632
template <typename ELFT>
5633
static std::optional<FreeBSDNote>
5634
getFreeBSDNote(uint32_t NoteType, ArrayRef<uint8_t> Desc, bool IsCore) {
5635
if (IsCore)
5636
return std::nullopt; // No pretty-printing yet.
5637
switch (NoteType) {
5638
case ELF::NT_FREEBSD_ABI_TAG:
5639
if (Desc.size() != 4)
5640
return std::nullopt;
5641
return FreeBSDNote{"ABI tag",
5642
utostr(endian::read32<ELFT::Endianness>(Desc.data()))};
5643
case ELF::NT_FREEBSD_ARCH_TAG:
5644
return FreeBSDNote{"Arch tag", toStringRef(Desc).str()};
5645
case ELF::NT_FREEBSD_FEATURE_CTL: {
5646
if (Desc.size() != 4)
5647
return std::nullopt;
5648
unsigned Value = endian::read32<ELFT::Endianness>(Desc.data());
5649
std::string FlagsStr;
5650
raw_string_ostream OS(FlagsStr);
5651
printFlags(Value, ArrayRef(FreeBSDFeatureCtlFlags), OS);
5652
if (OS.str().empty())
5653
OS << "0x" << utohexstr(Value);
5654
else
5655
OS << "(0x" << utohexstr(Value) << ")";
5656
return FreeBSDNote{"Feature flags", OS.str()};
5657
}
5658
default:
5659
return std::nullopt;
5660
}
5661
}
5662
5663
struct AMDNote {
5664
std::string Type;
5665
std::string Value;
5666
};
5667
5668
template <typename ELFT>
5669
static AMDNote getAMDNote(uint32_t NoteType, ArrayRef<uint8_t> Desc) {
5670
switch (NoteType) {
5671
default:
5672
return {"", ""};
5673
case ELF::NT_AMD_HSA_CODE_OBJECT_VERSION: {
5674
struct CodeObjectVersion {
5675
support::aligned_ulittle32_t MajorVersion;
5676
support::aligned_ulittle32_t MinorVersion;
5677
};
5678
if (Desc.size() != sizeof(CodeObjectVersion))
5679
return {"AMD HSA Code Object Version",
5680
"Invalid AMD HSA Code Object Version"};
5681
std::string VersionString;
5682
raw_string_ostream StrOS(VersionString);
5683
auto Version = reinterpret_cast<const CodeObjectVersion *>(Desc.data());
5684
StrOS << "[Major: " << Version->MajorVersion
5685
<< ", Minor: " << Version->MinorVersion << "]";
5686
return {"AMD HSA Code Object Version", VersionString};
5687
}
5688
case ELF::NT_AMD_HSA_HSAIL: {
5689
struct HSAILProperties {
5690
support::aligned_ulittle32_t HSAILMajorVersion;
5691
support::aligned_ulittle32_t HSAILMinorVersion;
5692
uint8_t Profile;
5693
uint8_t MachineModel;
5694
uint8_t DefaultFloatRound;
5695
};
5696
if (Desc.size() != sizeof(HSAILProperties))
5697
return {"AMD HSA HSAIL Properties", "Invalid AMD HSA HSAIL Properties"};
5698
auto Properties = reinterpret_cast<const HSAILProperties *>(Desc.data());
5699
std::string HSAILPropetiesString;
5700
raw_string_ostream StrOS(HSAILPropetiesString);
5701
StrOS << "[HSAIL Major: " << Properties->HSAILMajorVersion
5702
<< ", HSAIL Minor: " << Properties->HSAILMinorVersion
5703
<< ", Profile: " << uint32_t(Properties->Profile)
5704
<< ", Machine Model: " << uint32_t(Properties->MachineModel)
5705
<< ", Default Float Round: "
5706
<< uint32_t(Properties->DefaultFloatRound) << "]";
5707
return {"AMD HSA HSAIL Properties", HSAILPropetiesString};
5708
}
5709
case ELF::NT_AMD_HSA_ISA_VERSION: {
5710
struct IsaVersion {
5711
support::aligned_ulittle16_t VendorNameSize;
5712
support::aligned_ulittle16_t ArchitectureNameSize;
5713
support::aligned_ulittle32_t Major;
5714
support::aligned_ulittle32_t Minor;
5715
support::aligned_ulittle32_t Stepping;
5716
};
5717
if (Desc.size() < sizeof(IsaVersion))
5718
return {"AMD HSA ISA Version", "Invalid AMD HSA ISA Version"};
5719
auto Isa = reinterpret_cast<const IsaVersion *>(Desc.data());
5720
if (Desc.size() < sizeof(IsaVersion) +
5721
Isa->VendorNameSize + Isa->ArchitectureNameSize ||
5722
Isa->VendorNameSize == 0 || Isa->ArchitectureNameSize == 0)
5723
return {"AMD HSA ISA Version", "Invalid AMD HSA ISA Version"};
5724
std::string IsaString;
5725
raw_string_ostream StrOS(IsaString);
5726
StrOS << "[Vendor: "
5727
<< StringRef((const char*)Desc.data() + sizeof(IsaVersion), Isa->VendorNameSize - 1)
5728
<< ", Architecture: "
5729
<< StringRef((const char*)Desc.data() + sizeof(IsaVersion) + Isa->VendorNameSize,
5730
Isa->ArchitectureNameSize - 1)
5731
<< ", Major: " << Isa->Major << ", Minor: " << Isa->Minor
5732
<< ", Stepping: " << Isa->Stepping << "]";
5733
return {"AMD HSA ISA Version", IsaString};
5734
}
5735
case ELF::NT_AMD_HSA_METADATA: {
5736
if (Desc.size() == 0)
5737
return {"AMD HSA Metadata", ""};
5738
return {
5739
"AMD HSA Metadata",
5740
std::string(reinterpret_cast<const char *>(Desc.data()), Desc.size() - 1)};
5741
}
5742
case ELF::NT_AMD_HSA_ISA_NAME: {
5743
if (Desc.size() == 0)
5744
return {"AMD HSA ISA Name", ""};
5745
return {
5746
"AMD HSA ISA Name",
5747
std::string(reinterpret_cast<const char *>(Desc.data()), Desc.size())};
5748
}
5749
case ELF::NT_AMD_PAL_METADATA: {
5750
struct PALMetadata {
5751
support::aligned_ulittle32_t Key;
5752
support::aligned_ulittle32_t Value;
5753
};
5754
if (Desc.size() % sizeof(PALMetadata) != 0)
5755
return {"AMD PAL Metadata", "Invalid AMD PAL Metadata"};
5756
auto Isa = reinterpret_cast<const PALMetadata *>(Desc.data());
5757
std::string MetadataString;
5758
raw_string_ostream StrOS(MetadataString);
5759
for (size_t I = 0, E = Desc.size() / sizeof(PALMetadata); I < E; ++I) {
5760
StrOS << "[" << Isa[I].Key << ": " << Isa[I].Value << "]";
5761
}
5762
return {"AMD PAL Metadata", MetadataString};
5763
}
5764
}
5765
}
5766
5767
struct AMDGPUNote {
5768
std::string Type;
5769
std::string Value;
5770
};
5771
5772
template <typename ELFT>
5773
static AMDGPUNote getAMDGPUNote(uint32_t NoteType, ArrayRef<uint8_t> Desc) {
5774
switch (NoteType) {
5775
default:
5776
return {"", ""};
5777
case ELF::NT_AMDGPU_METADATA: {
5778
StringRef MsgPackString =
5779
StringRef(reinterpret_cast<const char *>(Desc.data()), Desc.size());
5780
msgpack::Document MsgPackDoc;
5781
if (!MsgPackDoc.readFromBlob(MsgPackString, /*Multi=*/false))
5782
return {"", ""};
5783
5784
std::string MetadataString;
5785
5786
// FIXME: Metadata Verifier only works with AMDHSA.
5787
// This is an ugly workaround to avoid the verifier for other MD
5788
// formats (e.g. amdpal)
5789
if (MsgPackString.contains("amdhsa.")) {
5790
AMDGPU::HSAMD::V3::MetadataVerifier Verifier(true);
5791
if (!Verifier.verify(MsgPackDoc.getRoot()))
5792
MetadataString = "Invalid AMDGPU Metadata\n";
5793
}
5794
5795
raw_string_ostream StrOS(MetadataString);
5796
if (MsgPackDoc.getRoot().isScalar()) {
5797
// TODO: passing a scalar root to toYAML() asserts:
5798
// (PolymorphicTraits<T>::getKind(Val) != NodeKind::Scalar &&
5799
// "plain scalar documents are not supported")
5800
// To avoid this crash we print the raw data instead.
5801
return {"", ""};
5802
}
5803
MsgPackDoc.toYAML(StrOS);
5804
return {"AMDGPU Metadata", StrOS.str()};
5805
}
5806
}
5807
}
5808
5809
struct CoreFileMapping {
5810
uint64_t Start, End, Offset;
5811
StringRef Filename;
5812
};
5813
5814
struct CoreNote {
5815
uint64_t PageSize;
5816
std::vector<CoreFileMapping> Mappings;
5817
};
5818
5819
static Expected<CoreNote> readCoreNote(DataExtractor Desc) {
5820
// Expected format of the NT_FILE note description:
5821
// 1. # of file mappings (call it N)
5822
// 2. Page size
5823
// 3. N (start, end, offset) triples
5824
// 4. N packed filenames (null delimited)
5825
// Each field is an Elf_Addr, except for filenames which are char* strings.
5826
5827
CoreNote Ret;
5828
const int Bytes = Desc.getAddressSize();
5829
5830
if (!Desc.isValidOffsetForAddress(2))
5831
return createError("the note of size 0x" + Twine::utohexstr(Desc.size()) +
5832
" is too short, expected at least 0x" +
5833
Twine::utohexstr(Bytes * 2));
5834
if (Desc.getData().back() != 0)
5835
return createError("the note is not NUL terminated");
5836
5837
uint64_t DescOffset = 0;
5838
uint64_t FileCount = Desc.getAddress(&DescOffset);
5839
Ret.PageSize = Desc.getAddress(&DescOffset);
5840
5841
if (!Desc.isValidOffsetForAddress(3 * FileCount * Bytes))
5842
return createError("unable to read file mappings (found " +
5843
Twine(FileCount) + "): the note of size 0x" +
5844
Twine::utohexstr(Desc.size()) + " is too short");
5845
5846
uint64_t FilenamesOffset = 0;
5847
DataExtractor Filenames(
5848
Desc.getData().drop_front(DescOffset + 3 * FileCount * Bytes),
5849
Desc.isLittleEndian(), Desc.getAddressSize());
5850
5851
Ret.Mappings.resize(FileCount);
5852
size_t I = 0;
5853
for (CoreFileMapping &Mapping : Ret.Mappings) {
5854
++I;
5855
if (!Filenames.isValidOffsetForDataOfSize(FilenamesOffset, 1))
5856
return createError(
5857
"unable to read the file name for the mapping with index " +
5858
Twine(I) + ": the note of size 0x" + Twine::utohexstr(Desc.size()) +
5859
" is truncated");
5860
Mapping.Start = Desc.getAddress(&DescOffset);
5861
Mapping.End = Desc.getAddress(&DescOffset);
5862
Mapping.Offset = Desc.getAddress(&DescOffset);
5863
Mapping.Filename = Filenames.getCStrRef(&FilenamesOffset);
5864
}
5865
5866
return Ret;
5867
}
5868
5869
template <typename ELFT>
5870
static void printCoreNote(raw_ostream &OS, const CoreNote &Note) {
5871
// Length of "0x<address>" string.
5872
const int FieldWidth = ELFT::Is64Bits ? 18 : 10;
5873
5874
OS << " Page size: " << format_decimal(Note.PageSize, 0) << '\n';
5875
OS << " " << right_justify("Start", FieldWidth) << " "
5876
<< right_justify("End", FieldWidth) << " "
5877
<< right_justify("Page Offset", FieldWidth) << '\n';
5878
for (const CoreFileMapping &Mapping : Note.Mappings) {
5879
OS << " " << format_hex(Mapping.Start, FieldWidth) << " "
5880
<< format_hex(Mapping.End, FieldWidth) << " "
5881
<< format_hex(Mapping.Offset, FieldWidth) << "\n "
5882
<< Mapping.Filename << '\n';
5883
}
5884
}
5885
5886
const NoteType GenericNoteTypes[] = {
5887
{ELF::NT_VERSION, "NT_VERSION (version)"},
5888
{ELF::NT_ARCH, "NT_ARCH (architecture)"},
5889
{ELF::NT_GNU_BUILD_ATTRIBUTE_OPEN, "OPEN"},
5890
{ELF::NT_GNU_BUILD_ATTRIBUTE_FUNC, "func"},
5891
};
5892
5893
const NoteType GNUNoteTypes[] = {
5894
{ELF::NT_GNU_ABI_TAG, "NT_GNU_ABI_TAG (ABI version tag)"},
5895
{ELF::NT_GNU_HWCAP, "NT_GNU_HWCAP (DSO-supplied software HWCAP info)"},
5896
{ELF::NT_GNU_BUILD_ID, "NT_GNU_BUILD_ID (unique build ID bitstring)"},
5897
{ELF::NT_GNU_GOLD_VERSION, "NT_GNU_GOLD_VERSION (gold version)"},
5898
{ELF::NT_GNU_PROPERTY_TYPE_0, "NT_GNU_PROPERTY_TYPE_0 (property note)"},
5899
};
5900
5901
const NoteType FreeBSDCoreNoteTypes[] = {
5902
{ELF::NT_FREEBSD_THRMISC, "NT_THRMISC (thrmisc structure)"},
5903
{ELF::NT_FREEBSD_PROCSTAT_PROC, "NT_PROCSTAT_PROC (proc data)"},
5904
{ELF::NT_FREEBSD_PROCSTAT_FILES, "NT_PROCSTAT_FILES (files data)"},
5905
{ELF::NT_FREEBSD_PROCSTAT_VMMAP, "NT_PROCSTAT_VMMAP (vmmap data)"},
5906
{ELF::NT_FREEBSD_PROCSTAT_GROUPS, "NT_PROCSTAT_GROUPS (groups data)"},
5907
{ELF::NT_FREEBSD_PROCSTAT_UMASK, "NT_PROCSTAT_UMASK (umask data)"},
5908
{ELF::NT_FREEBSD_PROCSTAT_RLIMIT, "NT_PROCSTAT_RLIMIT (rlimit data)"},
5909
{ELF::NT_FREEBSD_PROCSTAT_OSREL, "NT_PROCSTAT_OSREL (osreldate data)"},
5910
{ELF::NT_FREEBSD_PROCSTAT_PSSTRINGS,
5911
"NT_PROCSTAT_PSSTRINGS (ps_strings data)"},
5912
{ELF::NT_FREEBSD_PROCSTAT_AUXV, "NT_PROCSTAT_AUXV (auxv data)"},
5913
};
5914
5915
const NoteType FreeBSDNoteTypes[] = {
5916
{ELF::NT_FREEBSD_ABI_TAG, "NT_FREEBSD_ABI_TAG (ABI version tag)"},
5917
{ELF::NT_FREEBSD_NOINIT_TAG, "NT_FREEBSD_NOINIT_TAG (no .init tag)"},
5918
{ELF::NT_FREEBSD_ARCH_TAG, "NT_FREEBSD_ARCH_TAG (architecture tag)"},
5919
{ELF::NT_FREEBSD_FEATURE_CTL,
5920
"NT_FREEBSD_FEATURE_CTL (FreeBSD feature control)"},
5921
};
5922
5923
const NoteType NetBSDCoreNoteTypes[] = {
5924
{ELF::NT_NETBSDCORE_PROCINFO,
5925
"NT_NETBSDCORE_PROCINFO (procinfo structure)"},
5926
{ELF::NT_NETBSDCORE_AUXV, "NT_NETBSDCORE_AUXV (ELF auxiliary vector data)"},
5927
{ELF::NT_NETBSDCORE_LWPSTATUS, "PT_LWPSTATUS (ptrace_lwpstatus structure)"},
5928
};
5929
5930
const NoteType OpenBSDCoreNoteTypes[] = {
5931
{ELF::NT_OPENBSD_PROCINFO, "NT_OPENBSD_PROCINFO (procinfo structure)"},
5932
{ELF::NT_OPENBSD_AUXV, "NT_OPENBSD_AUXV (ELF auxiliary vector data)"},
5933
{ELF::NT_OPENBSD_REGS, "NT_OPENBSD_REGS (regular registers)"},
5934
{ELF::NT_OPENBSD_FPREGS, "NT_OPENBSD_FPREGS (floating point registers)"},
5935
{ELF::NT_OPENBSD_WCOOKIE, "NT_OPENBSD_WCOOKIE (window cookie)"},
5936
};
5937
5938
const NoteType AMDNoteTypes[] = {
5939
{ELF::NT_AMD_HSA_CODE_OBJECT_VERSION,
5940
"NT_AMD_HSA_CODE_OBJECT_VERSION (AMD HSA Code Object Version)"},
5941
{ELF::NT_AMD_HSA_HSAIL, "NT_AMD_HSA_HSAIL (AMD HSA HSAIL Properties)"},
5942
{ELF::NT_AMD_HSA_ISA_VERSION, "NT_AMD_HSA_ISA_VERSION (AMD HSA ISA Version)"},
5943
{ELF::NT_AMD_HSA_METADATA, "NT_AMD_HSA_METADATA (AMD HSA Metadata)"},
5944
{ELF::NT_AMD_HSA_ISA_NAME, "NT_AMD_HSA_ISA_NAME (AMD HSA ISA Name)"},
5945
{ELF::NT_AMD_PAL_METADATA, "NT_AMD_PAL_METADATA (AMD PAL Metadata)"},
5946
};
5947
5948
const NoteType AMDGPUNoteTypes[] = {
5949
{ELF::NT_AMDGPU_METADATA, "NT_AMDGPU_METADATA (AMDGPU Metadata)"},
5950
};
5951
5952
const NoteType LLVMOMPOFFLOADNoteTypes[] = {
5953
{ELF::NT_LLVM_OPENMP_OFFLOAD_VERSION,
5954
"NT_LLVM_OPENMP_OFFLOAD_VERSION (image format version)"},
5955
{ELF::NT_LLVM_OPENMP_OFFLOAD_PRODUCER,
5956
"NT_LLVM_OPENMP_OFFLOAD_PRODUCER (producing toolchain)"},
5957
{ELF::NT_LLVM_OPENMP_OFFLOAD_PRODUCER_VERSION,
5958
"NT_LLVM_OPENMP_OFFLOAD_PRODUCER_VERSION (producing toolchain version)"},
5959
};
5960
5961
const NoteType AndroidNoteTypes[] = {
5962
{ELF::NT_ANDROID_TYPE_IDENT, "NT_ANDROID_TYPE_IDENT"},
5963
{ELF::NT_ANDROID_TYPE_KUSER, "NT_ANDROID_TYPE_KUSER"},
5964
{ELF::NT_ANDROID_TYPE_MEMTAG,
5965
"NT_ANDROID_TYPE_MEMTAG (Android memory tagging information)"},
5966
};
5967
5968
const NoteType CoreNoteTypes[] = {
5969
{ELF::NT_PRSTATUS, "NT_PRSTATUS (prstatus structure)"},
5970
{ELF::NT_FPREGSET, "NT_FPREGSET (floating point registers)"},
5971
{ELF::NT_PRPSINFO, "NT_PRPSINFO (prpsinfo structure)"},
5972
{ELF::NT_TASKSTRUCT, "NT_TASKSTRUCT (task structure)"},
5973
{ELF::NT_AUXV, "NT_AUXV (auxiliary vector)"},
5974
{ELF::NT_PSTATUS, "NT_PSTATUS (pstatus structure)"},
5975
{ELF::NT_FPREGS, "NT_FPREGS (floating point registers)"},
5976
{ELF::NT_PSINFO, "NT_PSINFO (psinfo structure)"},
5977
{ELF::NT_LWPSTATUS, "NT_LWPSTATUS (lwpstatus_t structure)"},
5978
{ELF::NT_LWPSINFO, "NT_LWPSINFO (lwpsinfo_t structure)"},
5979
{ELF::NT_WIN32PSTATUS, "NT_WIN32PSTATUS (win32_pstatus structure)"},
5980
5981
{ELF::NT_PPC_VMX, "NT_PPC_VMX (ppc Altivec registers)"},
5982
{ELF::NT_PPC_VSX, "NT_PPC_VSX (ppc VSX registers)"},
5983
{ELF::NT_PPC_TAR, "NT_PPC_TAR (ppc TAR register)"},
5984
{ELF::NT_PPC_PPR, "NT_PPC_PPR (ppc PPR register)"},
5985
{ELF::NT_PPC_DSCR, "NT_PPC_DSCR (ppc DSCR register)"},
5986
{ELF::NT_PPC_EBB, "NT_PPC_EBB (ppc EBB registers)"},
5987
{ELF::NT_PPC_PMU, "NT_PPC_PMU (ppc PMU registers)"},
5988
{ELF::NT_PPC_TM_CGPR, "NT_PPC_TM_CGPR (ppc checkpointed GPR registers)"},
5989
{ELF::NT_PPC_TM_CFPR,
5990
"NT_PPC_TM_CFPR (ppc checkpointed floating point registers)"},
5991
{ELF::NT_PPC_TM_CVMX,
5992
"NT_PPC_TM_CVMX (ppc checkpointed Altivec registers)"},
5993
{ELF::NT_PPC_TM_CVSX, "NT_PPC_TM_CVSX (ppc checkpointed VSX registers)"},
5994
{ELF::NT_PPC_TM_SPR, "NT_PPC_TM_SPR (ppc TM special purpose registers)"},
5995
{ELF::NT_PPC_TM_CTAR, "NT_PPC_TM_CTAR (ppc checkpointed TAR register)"},
5996
{ELF::NT_PPC_TM_CPPR, "NT_PPC_TM_CPPR (ppc checkpointed PPR register)"},
5997
{ELF::NT_PPC_TM_CDSCR, "NT_PPC_TM_CDSCR (ppc checkpointed DSCR register)"},
5998
5999
{ELF::NT_386_TLS, "NT_386_TLS (x86 TLS information)"},
6000
{ELF::NT_386_IOPERM, "NT_386_IOPERM (x86 I/O permissions)"},
6001
{ELF::NT_X86_XSTATE, "NT_X86_XSTATE (x86 XSAVE extended state)"},
6002
6003
{ELF::NT_S390_HIGH_GPRS, "NT_S390_HIGH_GPRS (s390 upper register halves)"},
6004
{ELF::NT_S390_TIMER, "NT_S390_TIMER (s390 timer register)"},
6005
{ELF::NT_S390_TODCMP, "NT_S390_TODCMP (s390 TOD comparator register)"},
6006
{ELF::NT_S390_TODPREG, "NT_S390_TODPREG (s390 TOD programmable register)"},
6007
{ELF::NT_S390_CTRS, "NT_S390_CTRS (s390 control registers)"},
6008
{ELF::NT_S390_PREFIX, "NT_S390_PREFIX (s390 prefix register)"},
6009
{ELF::NT_S390_LAST_BREAK,
6010
"NT_S390_LAST_BREAK (s390 last breaking event address)"},
6011
{ELF::NT_S390_SYSTEM_CALL,
6012
"NT_S390_SYSTEM_CALL (s390 system call restart data)"},
6013
{ELF::NT_S390_TDB, "NT_S390_TDB (s390 transaction diagnostic block)"},
6014
{ELF::NT_S390_VXRS_LOW,
6015
"NT_S390_VXRS_LOW (s390 vector registers 0-15 upper half)"},
6016
{ELF::NT_S390_VXRS_HIGH, "NT_S390_VXRS_HIGH (s390 vector registers 16-31)"},
6017
{ELF::NT_S390_GS_CB, "NT_S390_GS_CB (s390 guarded-storage registers)"},
6018
{ELF::NT_S390_GS_BC,
6019
"NT_S390_GS_BC (s390 guarded-storage broadcast control)"},
6020
6021
{ELF::NT_ARM_VFP, "NT_ARM_VFP (arm VFP registers)"},
6022
{ELF::NT_ARM_TLS, "NT_ARM_TLS (AArch TLS registers)"},
6023
{ELF::NT_ARM_HW_BREAK,
6024
"NT_ARM_HW_BREAK (AArch hardware breakpoint registers)"},
6025
{ELF::NT_ARM_HW_WATCH,
6026
"NT_ARM_HW_WATCH (AArch hardware watchpoint registers)"},
6027
{ELF::NT_ARM_SVE, "NT_ARM_SVE (AArch64 SVE registers)"},
6028
{ELF::NT_ARM_PAC_MASK,
6029
"NT_ARM_PAC_MASK (AArch64 Pointer Authentication code masks)"},
6030
{ELF::NT_ARM_TAGGED_ADDR_CTRL,
6031
"NT_ARM_TAGGED_ADDR_CTRL (AArch64 Tagged Address Control)"},
6032
{ELF::NT_ARM_SSVE, "NT_ARM_SSVE (AArch64 Streaming SVE registers)"},
6033
{ELF::NT_ARM_ZA, "NT_ARM_ZA (AArch64 SME ZA registers)"},
6034
{ELF::NT_ARM_ZT, "NT_ARM_ZT (AArch64 SME ZT registers)"},
6035
6036
{ELF::NT_FILE, "NT_FILE (mapped files)"},
6037
{ELF::NT_PRXFPREG, "NT_PRXFPREG (user_xfpregs structure)"},
6038
{ELF::NT_SIGINFO, "NT_SIGINFO (siginfo_t data)"},
6039
};
6040
6041
template <class ELFT>
6042
StringRef getNoteTypeName(const typename ELFT::Note &Note, unsigned ELFType) {
6043
uint32_t Type = Note.getType();
6044
auto FindNote = [&](ArrayRef<NoteType> V) -> StringRef {
6045
for (const NoteType &N : V)
6046
if (N.ID == Type)
6047
return N.Name;
6048
return "";
6049
};
6050
6051
StringRef Name = Note.getName();
6052
if (Name == "GNU")
6053
return FindNote(GNUNoteTypes);
6054
if (Name == "FreeBSD") {
6055
if (ELFType == ELF::ET_CORE) {
6056
// FreeBSD also places the generic core notes in the FreeBSD namespace.
6057
StringRef Result = FindNote(FreeBSDCoreNoteTypes);
6058
if (!Result.empty())
6059
return Result;
6060
return FindNote(CoreNoteTypes);
6061
} else {
6062
return FindNote(FreeBSDNoteTypes);
6063
}
6064
}
6065
if (ELFType == ELF::ET_CORE && Name.starts_with("NetBSD-CORE")) {
6066
StringRef Result = FindNote(NetBSDCoreNoteTypes);
6067
if (!Result.empty())
6068
return Result;
6069
return FindNote(CoreNoteTypes);
6070
}
6071
if (ELFType == ELF::ET_CORE && Name.starts_with("OpenBSD")) {
6072
// OpenBSD also places the generic core notes in the OpenBSD namespace.
6073
StringRef Result = FindNote(OpenBSDCoreNoteTypes);
6074
if (!Result.empty())
6075
return Result;
6076
return FindNote(CoreNoteTypes);
6077
}
6078
if (Name == "AMD")
6079
return FindNote(AMDNoteTypes);
6080
if (Name == "AMDGPU")
6081
return FindNote(AMDGPUNoteTypes);
6082
if (Name == "LLVMOMPOFFLOAD")
6083
return FindNote(LLVMOMPOFFLOADNoteTypes);
6084
if (Name == "Android")
6085
return FindNote(AndroidNoteTypes);
6086
6087
if (ELFType == ELF::ET_CORE)
6088
return FindNote(CoreNoteTypes);
6089
return FindNote(GenericNoteTypes);
6090
}
6091
6092
template <class ELFT>
6093
static void processNotesHelper(
6094
const ELFDumper<ELFT> &Dumper,
6095
llvm::function_ref<void(std::optional<StringRef>, typename ELFT::Off,
6096
typename ELFT::Addr, size_t)>
6097
StartNotesFn,
6098
llvm::function_ref<Error(const typename ELFT::Note &, bool)> ProcessNoteFn,
6099
llvm::function_ref<void()> FinishNotesFn) {
6100
const ELFFile<ELFT> &Obj = Dumper.getElfObject().getELFFile();
6101
bool IsCoreFile = Obj.getHeader().e_type == ELF::ET_CORE;
6102
6103
ArrayRef<typename ELFT::Shdr> Sections = cantFail(Obj.sections());
6104
if (!IsCoreFile && !Sections.empty()) {
6105
for (const typename ELFT::Shdr &S : Sections) {
6106
if (S.sh_type != SHT_NOTE)
6107
continue;
6108
StartNotesFn(expectedToStdOptional(Obj.getSectionName(S)), S.sh_offset,
6109
S.sh_size, S.sh_addralign);
6110
Error Err = Error::success();
6111
size_t I = 0;
6112
for (const typename ELFT::Note Note : Obj.notes(S, Err)) {
6113
if (Error E = ProcessNoteFn(Note, IsCoreFile))
6114
Dumper.reportUniqueWarning(
6115
"unable to read note with index " + Twine(I) + " from the " +
6116
describe(Obj, S) + ": " + toString(std::move(E)));
6117
++I;
6118
}
6119
if (Err)
6120
Dumper.reportUniqueWarning("unable to read notes from the " +
6121
describe(Obj, S) + ": " +
6122
toString(std::move(Err)));
6123
FinishNotesFn();
6124
}
6125
return;
6126
}
6127
6128
Expected<ArrayRef<typename ELFT::Phdr>> PhdrsOrErr = Obj.program_headers();
6129
if (!PhdrsOrErr) {
6130
Dumper.reportUniqueWarning(
6131
"unable to read program headers to locate the PT_NOTE segment: " +
6132
toString(PhdrsOrErr.takeError()));
6133
return;
6134
}
6135
6136
for (size_t I = 0, E = (*PhdrsOrErr).size(); I != E; ++I) {
6137
const typename ELFT::Phdr &P = (*PhdrsOrErr)[I];
6138
if (P.p_type != PT_NOTE)
6139
continue;
6140
StartNotesFn(/*SecName=*/std::nullopt, P.p_offset, P.p_filesz, P.p_align);
6141
Error Err = Error::success();
6142
size_t Index = 0;
6143
for (const typename ELFT::Note Note : Obj.notes(P, Err)) {
6144
if (Error E = ProcessNoteFn(Note, IsCoreFile))
6145
Dumper.reportUniqueWarning("unable to read note with index " +
6146
Twine(Index) +
6147
" from the PT_NOTE segment with index " +
6148
Twine(I) + ": " + toString(std::move(E)));
6149
++Index;
6150
}
6151
if (Err)
6152
Dumper.reportUniqueWarning(
6153
"unable to read notes from the PT_NOTE segment with index " +
6154
Twine(I) + ": " + toString(std::move(Err)));
6155
FinishNotesFn();
6156
}
6157
}
6158
6159
template <class ELFT> void GNUELFDumper<ELFT>::printNotes() {
6160
size_t Align = 0;
6161
bool IsFirstHeader = true;
6162
auto PrintHeader = [&](std::optional<StringRef> SecName,
6163
const typename ELFT::Off Offset,
6164
const typename ELFT::Addr Size, size_t Al) {
6165
Align = std::max<size_t>(Al, 4);
6166
// Print a newline between notes sections to match GNU readelf.
6167
if (!IsFirstHeader) {
6168
OS << '\n';
6169
} else {
6170
IsFirstHeader = false;
6171
}
6172
6173
OS << "Displaying notes found ";
6174
6175
if (SecName)
6176
OS << "in: " << *SecName << "\n";
6177
else
6178
OS << "at file offset " << format_hex(Offset, 10) << " with length "
6179
<< format_hex(Size, 10) << ":\n";
6180
6181
OS << " Owner Data size \tDescription\n";
6182
};
6183
6184
auto ProcessNote = [&](const Elf_Note &Note, bool IsCore) -> Error {
6185
StringRef Name = Note.getName();
6186
ArrayRef<uint8_t> Descriptor = Note.getDesc(Align);
6187
Elf_Word Type = Note.getType();
6188
6189
// Print the note owner/type.
6190
OS << " " << left_justify(Name, 20) << ' '
6191
<< format_hex(Descriptor.size(), 10) << '\t';
6192
6193
StringRef NoteType =
6194
getNoteTypeName<ELFT>(Note, this->Obj.getHeader().e_type);
6195
if (!NoteType.empty())
6196
OS << NoteType << '\n';
6197
else
6198
OS << "Unknown note type: (" << format_hex(Type, 10) << ")\n";
6199
6200
// Print the description, or fallback to printing raw bytes for unknown
6201
// owners/if we fail to pretty-print the contents.
6202
if (Name == "GNU") {
6203
if (printGNUNote<ELFT>(OS, Type, Descriptor))
6204
return Error::success();
6205
} else if (Name == "FreeBSD") {
6206
if (std::optional<FreeBSDNote> N =
6207
getFreeBSDNote<ELFT>(Type, Descriptor, IsCore)) {
6208
OS << " " << N->Type << ": " << N->Value << '\n';
6209
return Error::success();
6210
}
6211
} else if (Name == "AMD") {
6212
const AMDNote N = getAMDNote<ELFT>(Type, Descriptor);
6213
if (!N.Type.empty()) {
6214
OS << " " << N.Type << ":\n " << N.Value << '\n';
6215
return Error::success();
6216
}
6217
} else if (Name == "AMDGPU") {
6218
const AMDGPUNote N = getAMDGPUNote<ELFT>(Type, Descriptor);
6219
if (!N.Type.empty()) {
6220
OS << " " << N.Type << ":\n " << N.Value << '\n';
6221
return Error::success();
6222
}
6223
} else if (Name == "LLVMOMPOFFLOAD") {
6224
if (printLLVMOMPOFFLOADNote<ELFT>(OS, Type, Descriptor))
6225
return Error::success();
6226
} else if (Name == "CORE") {
6227
if (Type == ELF::NT_FILE) {
6228
DataExtractor DescExtractor(
6229
Descriptor, ELFT::Endianness == llvm::endianness::little,
6230
sizeof(Elf_Addr));
6231
if (Expected<CoreNote> NoteOrErr = readCoreNote(DescExtractor)) {
6232
printCoreNote<ELFT>(OS, *NoteOrErr);
6233
return Error::success();
6234
} else {
6235
return NoteOrErr.takeError();
6236
}
6237
}
6238
} else if (Name == "Android") {
6239
if (printAndroidNote(OS, Type, Descriptor))
6240
return Error::success();
6241
}
6242
if (!Descriptor.empty()) {
6243
OS << " description data:";
6244
for (uint8_t B : Descriptor)
6245
OS << " " << format("%02x", B);
6246
OS << '\n';
6247
}
6248
return Error::success();
6249
};
6250
6251
processNotesHelper(*this, /*StartNotesFn=*/PrintHeader,
6252
/*ProcessNoteFn=*/ProcessNote, /*FinishNotesFn=*/[]() {});
6253
}
6254
6255
template <class ELFT>
6256
ArrayRef<uint8_t>
6257
ELFDumper<ELFT>::getMemtagGlobalsSectionContents(uint64_t ExpectedAddr) {
6258
for (const typename ELFT::Shdr &Sec : cantFail(Obj.sections())) {
6259
if (Sec.sh_type != SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC)
6260
continue;
6261
if (Sec.sh_addr != ExpectedAddr) {
6262
reportUniqueWarning(
6263
"SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC section was unexpectedly at 0x" +
6264
Twine::utohexstr(Sec.sh_addr) +
6265
", when DT_AARCH64_MEMTAG_GLOBALS says it should be at 0x" +
6266
Twine::utohexstr(ExpectedAddr));
6267
return ArrayRef<uint8_t>();
6268
}
6269
Expected<ArrayRef<uint8_t>> Contents = Obj.getSectionContents(Sec);
6270
if (auto E = Contents.takeError()) {
6271
reportUniqueWarning(
6272
"couldn't get SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC section contents: " +
6273
toString(std::move(E)));
6274
return ArrayRef<uint8_t>();
6275
}
6276
return Contents.get();
6277
}
6278
return ArrayRef<uint8_t>();
6279
}
6280
6281
// Reserve the lower three bits of the first byte of the step distance when
6282
// encoding the memtag descriptors. Found to be the best overall size tradeoff
6283
// when compiling Android T with full MTE globals enabled.
6284
constexpr uint64_t MemtagStepVarintReservedBits = 3;
6285
constexpr uint64_t MemtagGranuleSize = 16;
6286
6287
template <typename ELFT> void ELFDumper<ELFT>::printMemtag() {
6288
if (Obj.getHeader().e_machine != EM_AARCH64) return;
6289
std::vector<std::pair<std::string, std::string>> DynamicEntries;
6290
uint64_t MemtagGlobalsSz = 0;
6291
uint64_t MemtagGlobals = 0;
6292
for (const typename ELFT::Dyn &Entry : dynamic_table()) {
6293
uintX_t Tag = Entry.getTag();
6294
switch (Tag) {
6295
case DT_AARCH64_MEMTAG_GLOBALSSZ:
6296
MemtagGlobalsSz = Entry.getVal();
6297
DynamicEntries.emplace_back(Obj.getDynamicTagAsString(Tag),
6298
getDynamicEntry(Tag, Entry.getVal()));
6299
break;
6300
case DT_AARCH64_MEMTAG_GLOBALS:
6301
MemtagGlobals = Entry.getVal();
6302
DynamicEntries.emplace_back(Obj.getDynamicTagAsString(Tag),
6303
getDynamicEntry(Tag, Entry.getVal()));
6304
break;
6305
case DT_AARCH64_MEMTAG_MODE:
6306
case DT_AARCH64_MEMTAG_HEAP:
6307
case DT_AARCH64_MEMTAG_STACK:
6308
DynamicEntries.emplace_back(Obj.getDynamicTagAsString(Tag),
6309
getDynamicEntry(Tag, Entry.getVal()));
6310
break;
6311
}
6312
}
6313
6314
ArrayRef<uint8_t> AndroidNoteDesc;
6315
auto FindAndroidNote = [&](const Elf_Note &Note, bool IsCore) -> Error {
6316
if (Note.getName() == "Android" &&
6317
Note.getType() == ELF::NT_ANDROID_TYPE_MEMTAG)
6318
AndroidNoteDesc = Note.getDesc(4);
6319
return Error::success();
6320
};
6321
6322
processNotesHelper(
6323
*this,
6324
/*StartNotesFn=*/
6325
[](std::optional<StringRef>, const typename ELFT::Off,
6326
const typename ELFT::Addr, size_t) {},
6327
/*ProcessNoteFn=*/FindAndroidNote, /*FinishNotesFn=*/[]() {});
6328
6329
ArrayRef<uint8_t> Contents = getMemtagGlobalsSectionContents(MemtagGlobals);
6330
if (Contents.size() != MemtagGlobalsSz) {
6331
reportUniqueWarning(
6332
"mismatch between DT_AARCH64_MEMTAG_GLOBALSSZ (0x" +
6333
Twine::utohexstr(MemtagGlobalsSz) +
6334
") and SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC section size (0x" +
6335
Twine::utohexstr(Contents.size()) + ")");
6336
Contents = ArrayRef<uint8_t>();
6337
}
6338
6339
std::vector<std::pair<uint64_t, uint64_t>> GlobalDescriptors;
6340
uint64_t Address = 0;
6341
// See the AArch64 MemtagABI document for a description of encoding scheme:
6342
// https://github.com/ARM-software/abi-aa/blob/main/memtagabielf64/memtagabielf64.rst#83encoding-of-sht_aarch64_memtag_globals_dynamic
6343
for (size_t I = 0; I < Contents.size();) {
6344
const char *Error = nullptr;
6345
unsigned DecodedBytes = 0;
6346
uint64_t Value = decodeULEB128(Contents.data() + I, &DecodedBytes,
6347
Contents.end(), &Error);
6348
I += DecodedBytes;
6349
if (Error) {
6350
reportUniqueWarning(
6351
"error decoding distance uleb, " + Twine(DecodedBytes) +
6352
" byte(s) into SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC: " + Twine(Error));
6353
GlobalDescriptors.clear();
6354
break;
6355
}
6356
uint64_t Distance = Value >> MemtagStepVarintReservedBits;
6357
uint64_t GranulesToTag = Value & ((1 << MemtagStepVarintReservedBits) - 1);
6358
if (GranulesToTag == 0) {
6359
GranulesToTag = decodeULEB128(Contents.data() + I, &DecodedBytes,
6360
Contents.end(), &Error) +
6361
1;
6362
I += DecodedBytes;
6363
if (Error) {
6364
reportUniqueWarning(
6365
"error decoding size-only uleb, " + Twine(DecodedBytes) +
6366
" byte(s) into SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC: " + Twine(Error));
6367
GlobalDescriptors.clear();
6368
break;
6369
}
6370
}
6371
Address += Distance * MemtagGranuleSize;
6372
GlobalDescriptors.emplace_back(Address, GranulesToTag * MemtagGranuleSize);
6373
Address += GranulesToTag * MemtagGranuleSize;
6374
}
6375
6376
printMemtag(DynamicEntries, AndroidNoteDesc, GlobalDescriptors);
6377
}
6378
6379
template <class ELFT> void GNUELFDumper<ELFT>::printELFLinkerOptions() {
6380
OS << "printELFLinkerOptions not implemented!\n";
6381
}
6382
6383
template <class ELFT>
6384
void ELFDumper<ELFT>::printDependentLibsHelper(
6385
function_ref<void(const Elf_Shdr &)> OnSectionStart,
6386
function_ref<void(StringRef, uint64_t)> OnLibEntry) {
6387
auto Warn = [this](unsigned SecNdx, StringRef Msg) {
6388
this->reportUniqueWarning("SHT_LLVM_DEPENDENT_LIBRARIES section at index " +
6389
Twine(SecNdx) + " is broken: " + Msg);
6390
};
6391
6392
unsigned I = -1;
6393
for (const Elf_Shdr &Shdr : cantFail(Obj.sections())) {
6394
++I;
6395
if (Shdr.sh_type != ELF::SHT_LLVM_DEPENDENT_LIBRARIES)
6396
continue;
6397
6398
OnSectionStart(Shdr);
6399
6400
Expected<ArrayRef<uint8_t>> ContentsOrErr = Obj.getSectionContents(Shdr);
6401
if (!ContentsOrErr) {
6402
Warn(I, toString(ContentsOrErr.takeError()));
6403
continue;
6404
}
6405
6406
ArrayRef<uint8_t> Contents = *ContentsOrErr;
6407
if (!Contents.empty() && Contents.back() != 0) {
6408
Warn(I, "the content is not null-terminated");
6409
continue;
6410
}
6411
6412
for (const uint8_t *I = Contents.begin(), *E = Contents.end(); I < E;) {
6413
StringRef Lib((const char *)I);
6414
OnLibEntry(Lib, I - Contents.begin());
6415
I += Lib.size() + 1;
6416
}
6417
}
6418
}
6419
6420
template <class ELFT>
6421
void ELFDumper<ELFT>::forEachRelocationDo(
6422
const Elf_Shdr &Sec,
6423
llvm::function_ref<void(const Relocation<ELFT> &, unsigned,
6424
const Elf_Shdr &, const Elf_Shdr *)>
6425
RelRelaFn) {
6426
auto Warn = [&](Error &&E,
6427
const Twine &Prefix = "unable to read relocations from") {
6428
this->reportUniqueWarning(Prefix + " " + describe(Sec) + ": " +
6429
toString(std::move(E)));
6430
};
6431
6432
// SHT_RELR/SHT_ANDROID_RELR/SHT_AARCH64_AUTH_RELR sections do not have an
6433
// associated symbol table. For them we should not treat the value of the
6434
// sh_link field as an index of a symbol table.
6435
const Elf_Shdr *SymTab;
6436
if (Sec.sh_type != ELF::SHT_RELR && Sec.sh_type != ELF::SHT_ANDROID_RELR &&
6437
!(Obj.getHeader().e_machine == EM_AARCH64 &&
6438
Sec.sh_type == ELF::SHT_AARCH64_AUTH_RELR)) {
6439
Expected<const Elf_Shdr *> SymTabOrErr = Obj.getSection(Sec.sh_link);
6440
if (!SymTabOrErr) {
6441
Warn(SymTabOrErr.takeError(), "unable to locate a symbol table for");
6442
return;
6443
}
6444
SymTab = *SymTabOrErr;
6445
}
6446
6447
unsigned RelNdx = 0;
6448
const bool IsMips64EL = this->Obj.isMips64EL();
6449
switch (Sec.sh_type) {
6450
case ELF::SHT_REL:
6451
if (Expected<Elf_Rel_Range> RangeOrErr = Obj.rels(Sec)) {
6452
for (const Elf_Rel &R : *RangeOrErr)
6453
RelRelaFn(Relocation<ELFT>(R, IsMips64EL), RelNdx++, Sec, SymTab);
6454
} else {
6455
Warn(RangeOrErr.takeError());
6456
}
6457
break;
6458
case ELF::SHT_RELA:
6459
if (Expected<Elf_Rela_Range> RangeOrErr = Obj.relas(Sec)) {
6460
for (const Elf_Rela &R : *RangeOrErr)
6461
RelRelaFn(Relocation<ELFT>(R, IsMips64EL), RelNdx++, Sec, SymTab);
6462
} else {
6463
Warn(RangeOrErr.takeError());
6464
}
6465
break;
6466
case ELF::SHT_AARCH64_AUTH_RELR:
6467
if (Obj.getHeader().e_machine != EM_AARCH64)
6468
break;
6469
[[fallthrough]];
6470
case ELF::SHT_RELR:
6471
case ELF::SHT_ANDROID_RELR: {
6472
Expected<Elf_Relr_Range> RangeOrErr = Obj.relrs(Sec);
6473
if (!RangeOrErr) {
6474
Warn(RangeOrErr.takeError());
6475
break;
6476
}
6477
6478
for (const Elf_Rel &R : Obj.decode_relrs(*RangeOrErr))
6479
RelRelaFn(Relocation<ELFT>(R, IsMips64EL), RelNdx++, Sec,
6480
/*SymTab=*/nullptr);
6481
break;
6482
}
6483
case ELF::SHT_CREL: {
6484
if (auto RelsOrRelas = Obj.crels(Sec)) {
6485
for (const Elf_Rel &R : RelsOrRelas->first)
6486
RelRelaFn(Relocation<ELFT>(R, false), RelNdx++, Sec, SymTab);
6487
for (const Elf_Rela &R : RelsOrRelas->second)
6488
RelRelaFn(Relocation<ELFT>(R, false), RelNdx++, Sec, SymTab);
6489
} else {
6490
Warn(RelsOrRelas.takeError());
6491
}
6492
break;
6493
}
6494
case ELF::SHT_ANDROID_REL:
6495
case ELF::SHT_ANDROID_RELA:
6496
if (Expected<std::vector<Elf_Rela>> RelasOrErr = Obj.android_relas(Sec)) {
6497
for (const Elf_Rela &R : *RelasOrErr)
6498
RelRelaFn(Relocation<ELFT>(R, IsMips64EL), RelNdx++, Sec, SymTab);
6499
} else {
6500
Warn(RelasOrErr.takeError());
6501
}
6502
break;
6503
}
6504
}
6505
6506
template <class ELFT>
6507
StringRef ELFDumper<ELFT>::getPrintableSectionName(const Elf_Shdr &Sec) const {
6508
StringRef Name = "<?>";
6509
if (Expected<StringRef> SecNameOrErr =
6510
Obj.getSectionName(Sec, this->WarningHandler))
6511
Name = *SecNameOrErr;
6512
else
6513
this->reportUniqueWarning("unable to get the name of " + describe(Sec) +
6514
": " + toString(SecNameOrErr.takeError()));
6515
return Name;
6516
}
6517
6518
template <class ELFT> void GNUELFDumper<ELFT>::printDependentLibs() {
6519
bool SectionStarted = false;
6520
struct NameOffset {
6521
StringRef Name;
6522
uint64_t Offset;
6523
};
6524
std::vector<NameOffset> SecEntries;
6525
NameOffset Current;
6526
auto PrintSection = [&]() {
6527
OS << "Dependent libraries section " << Current.Name << " at offset "
6528
<< format_hex(Current.Offset, 1) << " contains " << SecEntries.size()
6529
<< " entries:\n";
6530
for (NameOffset Entry : SecEntries)
6531
OS << " [" << format("%6" PRIx64, Entry.Offset) << "] " << Entry.Name
6532
<< "\n";
6533
OS << "\n";
6534
SecEntries.clear();
6535
};
6536
6537
auto OnSectionStart = [&](const Elf_Shdr &Shdr) {
6538
if (SectionStarted)
6539
PrintSection();
6540
SectionStarted = true;
6541
Current.Offset = Shdr.sh_offset;
6542
Current.Name = this->getPrintableSectionName(Shdr);
6543
};
6544
auto OnLibEntry = [&](StringRef Lib, uint64_t Offset) {
6545
SecEntries.push_back(NameOffset{Lib, Offset});
6546
};
6547
6548
this->printDependentLibsHelper(OnSectionStart, OnLibEntry);
6549
if (SectionStarted)
6550
PrintSection();
6551
}
6552
6553
template <class ELFT>
6554
SmallVector<uint32_t> ELFDumper<ELFT>::getSymbolIndexesForFunctionAddress(
6555
uint64_t SymValue, std::optional<const Elf_Shdr *> FunctionSec) {
6556
SmallVector<uint32_t> SymbolIndexes;
6557
if (!this->AddressToIndexMap) {
6558
// Populate the address to index map upon the first invocation of this
6559
// function.
6560
this->AddressToIndexMap.emplace();
6561
if (this->DotSymtabSec) {
6562
if (Expected<Elf_Sym_Range> SymsOrError =
6563
Obj.symbols(this->DotSymtabSec)) {
6564
uint32_t Index = (uint32_t)-1;
6565
for (const Elf_Sym &Sym : *SymsOrError) {
6566
++Index;
6567
6568
if (Sym.st_shndx == ELF::SHN_UNDEF || Sym.getType() != ELF::STT_FUNC)
6569
continue;
6570
6571
Expected<uint64_t> SymAddrOrErr =
6572
ObjF.toSymbolRef(this->DotSymtabSec, Index).getAddress();
6573
if (!SymAddrOrErr) {
6574
std::string Name = this->getStaticSymbolName(Index);
6575
reportUniqueWarning("unable to get address of symbol '" + Name +
6576
"': " + toString(SymAddrOrErr.takeError()));
6577
return SymbolIndexes;
6578
}
6579
6580
(*this->AddressToIndexMap)[*SymAddrOrErr].push_back(Index);
6581
}
6582
} else {
6583
reportUniqueWarning("unable to read the symbol table: " +
6584
toString(SymsOrError.takeError()));
6585
}
6586
}
6587
}
6588
6589
auto Symbols = this->AddressToIndexMap->find(SymValue);
6590
if (Symbols == this->AddressToIndexMap->end())
6591
return SymbolIndexes;
6592
6593
for (uint32_t Index : Symbols->second) {
6594
// Check if the symbol is in the right section. FunctionSec == None
6595
// means "any section".
6596
if (FunctionSec) {
6597
const Elf_Sym &Sym = *cantFail(Obj.getSymbol(this->DotSymtabSec, Index));
6598
if (Expected<const Elf_Shdr *> SecOrErr =
6599
Obj.getSection(Sym, this->DotSymtabSec,
6600
this->getShndxTable(this->DotSymtabSec))) {
6601
if (*FunctionSec != *SecOrErr)
6602
continue;
6603
} else {
6604
std::string Name = this->getStaticSymbolName(Index);
6605
// Note: it is impossible to trigger this error currently, it is
6606
// untested.
6607
reportUniqueWarning("unable to get section of symbol '" + Name +
6608
"': " + toString(SecOrErr.takeError()));
6609
return SymbolIndexes;
6610
}
6611
}
6612
6613
SymbolIndexes.push_back(Index);
6614
}
6615
6616
return SymbolIndexes;
6617
}
6618
6619
template <class ELFT>
6620
bool ELFDumper<ELFT>::printFunctionStackSize(
6621
uint64_t SymValue, std::optional<const Elf_Shdr *> FunctionSec,
6622
const Elf_Shdr &StackSizeSec, DataExtractor Data, uint64_t *Offset) {
6623
SmallVector<uint32_t> FuncSymIndexes =
6624
this->getSymbolIndexesForFunctionAddress(SymValue, FunctionSec);
6625
if (FuncSymIndexes.empty())
6626
reportUniqueWarning(
6627
"could not identify function symbol for stack size entry in " +
6628
describe(StackSizeSec));
6629
6630
// Extract the size. The expectation is that Offset is pointing to the right
6631
// place, i.e. past the function address.
6632
Error Err = Error::success();
6633
uint64_t StackSize = Data.getULEB128(Offset, &Err);
6634
if (Err) {
6635
reportUniqueWarning("could not extract a valid stack size from " +
6636
describe(StackSizeSec) + ": " +
6637
toString(std::move(Err)));
6638
return false;
6639
}
6640
6641
if (FuncSymIndexes.empty()) {
6642
printStackSizeEntry(StackSize, {"?"});
6643
} else {
6644
SmallVector<std::string> FuncSymNames;
6645
for (uint32_t Index : FuncSymIndexes)
6646
FuncSymNames.push_back(this->getStaticSymbolName(Index));
6647
printStackSizeEntry(StackSize, FuncSymNames);
6648
}
6649
6650
return true;
6651
}
6652
6653
template <class ELFT>
6654
void GNUELFDumper<ELFT>::printStackSizeEntry(uint64_t Size,
6655
ArrayRef<std::string> FuncNames) {
6656
OS.PadToColumn(2);
6657
OS << format_decimal(Size, 11);
6658
OS.PadToColumn(18);
6659
6660
OS << join(FuncNames.begin(), FuncNames.end(), ", ") << "\n";
6661
}
6662
6663
template <class ELFT>
6664
void ELFDumper<ELFT>::printStackSize(const Relocation<ELFT> &R,
6665
const Elf_Shdr &RelocSec, unsigned Ndx,
6666
const Elf_Shdr *SymTab,
6667
const Elf_Shdr *FunctionSec,
6668
const Elf_Shdr &StackSizeSec,
6669
const RelocationResolver &Resolver,
6670
DataExtractor Data) {
6671
// This function ignores potentially erroneous input, unless it is directly
6672
// related to stack size reporting.
6673
const Elf_Sym *Sym = nullptr;
6674
Expected<RelSymbol<ELFT>> TargetOrErr = this->getRelocationTarget(R, SymTab);
6675
if (!TargetOrErr)
6676
reportUniqueWarning("unable to get the target of relocation with index " +
6677
Twine(Ndx) + " in " + describe(RelocSec) + ": " +
6678
toString(TargetOrErr.takeError()));
6679
else
6680
Sym = TargetOrErr->Sym;
6681
6682
uint64_t RelocSymValue = 0;
6683
if (Sym) {
6684
Expected<const Elf_Shdr *> SectionOrErr =
6685
this->Obj.getSection(*Sym, SymTab, this->getShndxTable(SymTab));
6686
if (!SectionOrErr) {
6687
reportUniqueWarning(
6688
"cannot identify the section for relocation symbol '" +
6689
(*TargetOrErr).Name + "': " + toString(SectionOrErr.takeError()));
6690
} else if (*SectionOrErr != FunctionSec) {
6691
reportUniqueWarning("relocation symbol '" + (*TargetOrErr).Name +
6692
"' is not in the expected section");
6693
// Pretend that the symbol is in the correct section and report its
6694
// stack size anyway.
6695
FunctionSec = *SectionOrErr;
6696
}
6697
6698
RelocSymValue = Sym->st_value;
6699
}
6700
6701
uint64_t Offset = R.Offset;
6702
if (!Data.isValidOffsetForDataOfSize(Offset, sizeof(Elf_Addr) + 1)) {
6703
reportUniqueWarning("found invalid relocation offset (0x" +
6704
Twine::utohexstr(Offset) + ") into " +
6705
describe(StackSizeSec) +
6706
" while trying to extract a stack size entry");
6707
return;
6708
}
6709
6710
uint64_t SymValue = Resolver(R.Type, Offset, RelocSymValue,
6711
Data.getAddress(&Offset), R.Addend.value_or(0));
6712
this->printFunctionStackSize(SymValue, FunctionSec, StackSizeSec, Data,
6713
&Offset);
6714
}
6715
6716
template <class ELFT>
6717
void ELFDumper<ELFT>::printNonRelocatableStackSizes(
6718
std::function<void()> PrintHeader) {
6719
// This function ignores potentially erroneous input, unless it is directly
6720
// related to stack size reporting.
6721
for (const Elf_Shdr &Sec : cantFail(Obj.sections())) {
6722
if (this->getPrintableSectionName(Sec) != ".stack_sizes")
6723
continue;
6724
PrintHeader();
6725
ArrayRef<uint8_t> Contents =
6726
unwrapOrError(this->FileName, Obj.getSectionContents(Sec));
6727
DataExtractor Data(Contents, Obj.isLE(), sizeof(Elf_Addr));
6728
uint64_t Offset = 0;
6729
while (Offset < Contents.size()) {
6730
// The function address is followed by a ULEB representing the stack
6731
// size. Check for an extra byte before we try to process the entry.
6732
if (!Data.isValidOffsetForDataOfSize(Offset, sizeof(Elf_Addr) + 1)) {
6733
reportUniqueWarning(
6734
describe(Sec) +
6735
" ended while trying to extract a stack size entry");
6736
break;
6737
}
6738
uint64_t SymValue = Data.getAddress(&Offset);
6739
if (!printFunctionStackSize(SymValue, /*FunctionSec=*/std::nullopt, Sec,
6740
Data, &Offset))
6741
break;
6742
}
6743
}
6744
}
6745
6746
template <class ELFT>
6747
void ELFDumper<ELFT>::printRelocatableStackSizes(
6748
std::function<void()> PrintHeader) {
6749
// Build a map between stack size sections and their corresponding relocation
6750
// sections.
6751
auto IsMatch = [&](const Elf_Shdr &Sec) -> bool {
6752
StringRef SectionName;
6753
if (Expected<StringRef> NameOrErr = Obj.getSectionName(Sec))
6754
SectionName = *NameOrErr;
6755
else
6756
consumeError(NameOrErr.takeError());
6757
6758
return SectionName == ".stack_sizes";
6759
};
6760
6761
Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>>
6762
StackSizeRelocMapOrErr = Obj.getSectionAndRelocations(IsMatch);
6763
if (!StackSizeRelocMapOrErr) {
6764
reportUniqueWarning("unable to get stack size map section(s): " +
6765
toString(StackSizeRelocMapOrErr.takeError()));
6766
return;
6767
}
6768
6769
for (const auto &StackSizeMapEntry : *StackSizeRelocMapOrErr) {
6770
PrintHeader();
6771
const Elf_Shdr *StackSizesELFSec = StackSizeMapEntry.first;
6772
const Elf_Shdr *RelocSec = StackSizeMapEntry.second;
6773
6774
// Warn about stack size sections without a relocation section.
6775
if (!RelocSec) {
6776
reportWarning(createError(".stack_sizes (" + describe(*StackSizesELFSec) +
6777
") does not have a corresponding "
6778
"relocation section"),
6779
FileName);
6780
continue;
6781
}
6782
6783
// A .stack_sizes section header's sh_link field is supposed to point
6784
// to the section that contains the functions whose stack sizes are
6785
// described in it.
6786
const Elf_Shdr *FunctionSec = unwrapOrError(
6787
this->FileName, Obj.getSection(StackSizesELFSec->sh_link));
6788
6789
SupportsRelocation IsSupportedFn;
6790
RelocationResolver Resolver;
6791
std::tie(IsSupportedFn, Resolver) = getRelocationResolver(this->ObjF);
6792
ArrayRef<uint8_t> Contents =
6793
unwrapOrError(this->FileName, Obj.getSectionContents(*StackSizesELFSec));
6794
DataExtractor Data(Contents, Obj.isLE(), sizeof(Elf_Addr));
6795
6796
forEachRelocationDo(
6797
*RelocSec, [&](const Relocation<ELFT> &R, unsigned Ndx,
6798
const Elf_Shdr &Sec, const Elf_Shdr *SymTab) {
6799
if (!IsSupportedFn || !IsSupportedFn(R.Type)) {
6800
reportUniqueWarning(
6801
describe(*RelocSec) +
6802
" contains an unsupported relocation with index " + Twine(Ndx) +
6803
": " + Obj.getRelocationTypeName(R.Type));
6804
return;
6805
}
6806
6807
this->printStackSize(R, *RelocSec, Ndx, SymTab, FunctionSec,
6808
*StackSizesELFSec, Resolver, Data);
6809
});
6810
}
6811
}
6812
6813
template <class ELFT>
6814
void GNUELFDumper<ELFT>::printStackSizes() {
6815
bool HeaderHasBeenPrinted = false;
6816
auto PrintHeader = [&]() {
6817
if (HeaderHasBeenPrinted)
6818
return;
6819
OS << "\nStack Sizes:\n";
6820
OS.PadToColumn(9);
6821
OS << "Size";
6822
OS.PadToColumn(18);
6823
OS << "Functions\n";
6824
HeaderHasBeenPrinted = true;
6825
};
6826
6827
// For non-relocatable objects, look directly for sections whose name starts
6828
// with .stack_sizes and process the contents.
6829
if (this->Obj.getHeader().e_type == ELF::ET_REL)
6830
this->printRelocatableStackSizes(PrintHeader);
6831
else
6832
this->printNonRelocatableStackSizes(PrintHeader);
6833
}
6834
6835
template <class ELFT>
6836
void GNUELFDumper<ELFT>::printMipsGOT(const MipsGOTParser<ELFT> &Parser) {
6837
size_t Bias = ELFT::Is64Bits ? 8 : 0;
6838
auto PrintEntry = [&](const Elf_Addr *E, StringRef Purpose) {
6839
OS.PadToColumn(2);
6840
OS << format_hex_no_prefix(Parser.getGotAddress(E), 8 + Bias);
6841
OS.PadToColumn(11 + Bias);
6842
OS << format_decimal(Parser.getGotOffset(E), 6) << "(gp)";
6843
OS.PadToColumn(22 + Bias);
6844
OS << format_hex_no_prefix(*E, 8 + Bias);
6845
OS.PadToColumn(31 + 2 * Bias);
6846
OS << Purpose << "\n";
6847
};
6848
6849
OS << (Parser.IsStatic ? "Static GOT:\n" : "Primary GOT:\n");
6850
OS << " Canonical gp value: "
6851
<< format_hex_no_prefix(Parser.getGp(), 8 + Bias) << "\n\n";
6852
6853
OS << " Reserved entries:\n";
6854
if (ELFT::Is64Bits)
6855
OS << " Address Access Initial Purpose\n";
6856
else
6857
OS << " Address Access Initial Purpose\n";
6858
PrintEntry(Parser.getGotLazyResolver(), "Lazy resolver");
6859
if (Parser.getGotModulePointer())
6860
PrintEntry(Parser.getGotModulePointer(), "Module pointer (GNU extension)");
6861
6862
if (!Parser.getLocalEntries().empty()) {
6863
OS << "\n";
6864
OS << " Local entries:\n";
6865
if (ELFT::Is64Bits)
6866
OS << " Address Access Initial\n";
6867
else
6868
OS << " Address Access Initial\n";
6869
for (auto &E : Parser.getLocalEntries())
6870
PrintEntry(&E, "");
6871
}
6872
6873
if (Parser.IsStatic)
6874
return;
6875
6876
if (!Parser.getGlobalEntries().empty()) {
6877
OS << "\n";
6878
OS << " Global entries:\n";
6879
if (ELFT::Is64Bits)
6880
OS << " Address Access Initial Sym.Val."
6881
<< " Type Ndx Name\n";
6882
else
6883
OS << " Address Access Initial Sym.Val. Type Ndx Name\n";
6884
6885
DataRegion<Elf_Word> ShndxTable(
6886
(const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end());
6887
for (auto &E : Parser.getGlobalEntries()) {
6888
const Elf_Sym &Sym = *Parser.getGotSym(&E);
6889
const Elf_Sym &FirstSym = this->dynamic_symbols()[0];
6890
std::string SymName = this->getFullSymbolName(
6891
Sym, &Sym - &FirstSym, ShndxTable, this->DynamicStringTable, false);
6892
6893
OS.PadToColumn(2);
6894
OS << to_string(format_hex_no_prefix(Parser.getGotAddress(&E), 8 + Bias));
6895
OS.PadToColumn(11 + Bias);
6896
OS << to_string(format_decimal(Parser.getGotOffset(&E), 6)) + "(gp)";
6897
OS.PadToColumn(22 + Bias);
6898
OS << to_string(format_hex_no_prefix(E, 8 + Bias));
6899
OS.PadToColumn(31 + 2 * Bias);
6900
OS << to_string(format_hex_no_prefix(Sym.st_value, 8 + Bias));
6901
OS.PadToColumn(40 + 3 * Bias);
6902
OS << enumToString(Sym.getType(), ArrayRef(ElfSymbolTypes));
6903
OS.PadToColumn(48 + 3 * Bias);
6904
OS << getSymbolSectionNdx(Sym, &Sym - this->dynamic_symbols().begin(),
6905
ShndxTable);
6906
OS.PadToColumn(52 + 3 * Bias);
6907
OS << SymName << "\n";
6908
}
6909
}
6910
6911
if (!Parser.getOtherEntries().empty())
6912
OS << "\n Number of TLS and multi-GOT entries "
6913
<< Parser.getOtherEntries().size() << "\n";
6914
}
6915
6916
template <class ELFT>
6917
void GNUELFDumper<ELFT>::printMipsPLT(const MipsGOTParser<ELFT> &Parser) {
6918
size_t Bias = ELFT::Is64Bits ? 8 : 0;
6919
auto PrintEntry = [&](const Elf_Addr *E, StringRef Purpose) {
6920
OS.PadToColumn(2);
6921
OS << format_hex_no_prefix(Parser.getPltAddress(E), 8 + Bias);
6922
OS.PadToColumn(11 + Bias);
6923
OS << format_hex_no_prefix(*E, 8 + Bias);
6924
OS.PadToColumn(20 + 2 * Bias);
6925
OS << Purpose << "\n";
6926
};
6927
6928
OS << "PLT GOT:\n\n";
6929
6930
OS << " Reserved entries:\n";
6931
OS << " Address Initial Purpose\n";
6932
PrintEntry(Parser.getPltLazyResolver(), "PLT lazy resolver");
6933
if (Parser.getPltModulePointer())
6934
PrintEntry(Parser.getPltModulePointer(), "Module pointer");
6935
6936
if (!Parser.getPltEntries().empty()) {
6937
OS << "\n";
6938
OS << " Entries:\n";
6939
OS << " Address Initial Sym.Val. Type Ndx Name\n";
6940
DataRegion<Elf_Word> ShndxTable(
6941
(const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end());
6942
for (auto &E : Parser.getPltEntries()) {
6943
const Elf_Sym &Sym = *Parser.getPltSym(&E);
6944
const Elf_Sym &FirstSym = *cantFail(
6945
this->Obj.template getEntry<Elf_Sym>(*Parser.getPltSymTable(), 0));
6946
std::string SymName = this->getFullSymbolName(
6947
Sym, &Sym - &FirstSym, ShndxTable, this->DynamicStringTable, false);
6948
6949
OS.PadToColumn(2);
6950
OS << to_string(format_hex_no_prefix(Parser.getPltAddress(&E), 8 + Bias));
6951
OS.PadToColumn(11 + Bias);
6952
OS << to_string(format_hex_no_prefix(E, 8 + Bias));
6953
OS.PadToColumn(20 + 2 * Bias);
6954
OS << to_string(format_hex_no_prefix(Sym.st_value, 8 + Bias));
6955
OS.PadToColumn(29 + 3 * Bias);
6956
OS << enumToString(Sym.getType(), ArrayRef(ElfSymbolTypes));
6957
OS.PadToColumn(37 + 3 * Bias);
6958
OS << getSymbolSectionNdx(Sym, &Sym - this->dynamic_symbols().begin(),
6959
ShndxTable);
6960
OS.PadToColumn(41 + 3 * Bias);
6961
OS << SymName << "\n";
6962
}
6963
}
6964
}
6965
6966
template <class ELFT>
6967
Expected<const Elf_Mips_ABIFlags<ELFT> *>
6968
getMipsAbiFlagsSection(const ELFDumper<ELFT> &Dumper) {
6969
const typename ELFT::Shdr *Sec = Dumper.findSectionByName(".MIPS.abiflags");
6970
if (Sec == nullptr)
6971
return nullptr;
6972
6973
constexpr StringRef ErrPrefix = "unable to read the .MIPS.abiflags section: ";
6974
Expected<ArrayRef<uint8_t>> DataOrErr =
6975
Dumper.getElfObject().getELFFile().getSectionContents(*Sec);
6976
if (!DataOrErr)
6977
return createError(ErrPrefix + toString(DataOrErr.takeError()));
6978
6979
if (DataOrErr->size() != sizeof(Elf_Mips_ABIFlags<ELFT>))
6980
return createError(ErrPrefix + "it has a wrong size (" +
6981
Twine(DataOrErr->size()) + ")");
6982
return reinterpret_cast<const Elf_Mips_ABIFlags<ELFT> *>(DataOrErr->data());
6983
}
6984
6985
template <class ELFT> void GNUELFDumper<ELFT>::printMipsABIFlags() {
6986
const Elf_Mips_ABIFlags<ELFT> *Flags = nullptr;
6987
if (Expected<const Elf_Mips_ABIFlags<ELFT> *> SecOrErr =
6988
getMipsAbiFlagsSection(*this))
6989
Flags = *SecOrErr;
6990
else
6991
this->reportUniqueWarning(SecOrErr.takeError());
6992
if (!Flags)
6993
return;
6994
6995
OS << "MIPS ABI Flags Version: " << Flags->version << "\n\n";
6996
OS << "ISA: MIPS" << int(Flags->isa_level);
6997
if (Flags->isa_rev > 1)
6998
OS << "r" << int(Flags->isa_rev);
6999
OS << "\n";
7000
OS << "GPR size: " << getMipsRegisterSize(Flags->gpr_size) << "\n";
7001
OS << "CPR1 size: " << getMipsRegisterSize(Flags->cpr1_size) << "\n";
7002
OS << "CPR2 size: " << getMipsRegisterSize(Flags->cpr2_size) << "\n";
7003
OS << "FP ABI: " << enumToString(Flags->fp_abi, ArrayRef(ElfMipsFpABIType))
7004
<< "\n";
7005
OS << "ISA Extension: "
7006
<< enumToString(Flags->isa_ext, ArrayRef(ElfMipsISAExtType)) << "\n";
7007
if (Flags->ases == 0)
7008
OS << "ASEs: None\n";
7009
else
7010
// FIXME: Print each flag on a separate line.
7011
OS << "ASEs: " << printFlags(Flags->ases, ArrayRef(ElfMipsASEFlags))
7012
<< "\n";
7013
OS << "FLAGS 1: " << format_hex_no_prefix(Flags->flags1, 8, false) << "\n";
7014
OS << "FLAGS 2: " << format_hex_no_prefix(Flags->flags2, 8, false) << "\n";
7015
OS << "\n";
7016
}
7017
7018
template <class ELFT> void LLVMELFDumper<ELFT>::printFileHeaders() {
7019
const Elf_Ehdr &E = this->Obj.getHeader();
7020
{
7021
DictScope D(W, "ElfHeader");
7022
{
7023
DictScope D(W, "Ident");
7024
W.printBinary("Magic",
7025
ArrayRef<unsigned char>(E.e_ident).slice(ELF::EI_MAG0, 4));
7026
W.printEnum("Class", E.e_ident[ELF::EI_CLASS], ArrayRef(ElfClass));
7027
W.printEnum("DataEncoding", E.e_ident[ELF::EI_DATA],
7028
ArrayRef(ElfDataEncoding));
7029
W.printNumber("FileVersion", E.e_ident[ELF::EI_VERSION]);
7030
7031
auto OSABI = ArrayRef(ElfOSABI);
7032
if (E.e_ident[ELF::EI_OSABI] >= ELF::ELFOSABI_FIRST_ARCH &&
7033
E.e_ident[ELF::EI_OSABI] <= ELF::ELFOSABI_LAST_ARCH) {
7034
switch (E.e_machine) {
7035
case ELF::EM_AMDGPU:
7036
OSABI = ArrayRef(AMDGPUElfOSABI);
7037
break;
7038
case ELF::EM_ARM:
7039
OSABI = ArrayRef(ARMElfOSABI);
7040
break;
7041
case ELF::EM_TI_C6000:
7042
OSABI = ArrayRef(C6000ElfOSABI);
7043
break;
7044
}
7045
}
7046
W.printEnum("OS/ABI", E.e_ident[ELF::EI_OSABI], OSABI);
7047
W.printNumber("ABIVersion", E.e_ident[ELF::EI_ABIVERSION]);
7048
W.printBinary("Unused",
7049
ArrayRef<unsigned char>(E.e_ident).slice(ELF::EI_PAD));
7050
}
7051
7052
std::string TypeStr;
7053
if (const EnumEntry<unsigned> *Ent = getObjectFileEnumEntry(E.e_type)) {
7054
TypeStr = Ent->Name.str();
7055
} else {
7056
if (E.e_type >= ET_LOPROC)
7057
TypeStr = "Processor Specific";
7058
else if (E.e_type >= ET_LOOS)
7059
TypeStr = "OS Specific";
7060
else
7061
TypeStr = "Unknown";
7062
}
7063
W.printString("Type", TypeStr + " (0x" + utohexstr(E.e_type) + ")");
7064
7065
W.printEnum("Machine", E.e_machine, ArrayRef(ElfMachineType));
7066
W.printNumber("Version", E.e_version);
7067
W.printHex("Entry", E.e_entry);
7068
W.printHex("ProgramHeaderOffset", E.e_phoff);
7069
W.printHex("SectionHeaderOffset", E.e_shoff);
7070
if (E.e_machine == EM_MIPS)
7071
W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderMipsFlags),
7072
unsigned(ELF::EF_MIPS_ARCH), unsigned(ELF::EF_MIPS_ABI),
7073
unsigned(ELF::EF_MIPS_MACH));
7074
else if (E.e_machine == EM_AMDGPU) {
7075
switch (E.e_ident[ELF::EI_ABIVERSION]) {
7076
default:
7077
W.printHex("Flags", E.e_flags);
7078
break;
7079
case 0:
7080
// ELFOSABI_AMDGPU_PAL, ELFOSABI_AMDGPU_MESA3D support *_V3 flags.
7081
[[fallthrough]];
7082
case ELF::ELFABIVERSION_AMDGPU_HSA_V3:
7083
W.printFlags("Flags", E.e_flags,
7084
ArrayRef(ElfHeaderAMDGPUFlagsABIVersion3),
7085
unsigned(ELF::EF_AMDGPU_MACH));
7086
break;
7087
case ELF::ELFABIVERSION_AMDGPU_HSA_V4:
7088
case ELF::ELFABIVERSION_AMDGPU_HSA_V5:
7089
W.printFlags("Flags", E.e_flags,
7090
ArrayRef(ElfHeaderAMDGPUFlagsABIVersion4),
7091
unsigned(ELF::EF_AMDGPU_MACH),
7092
unsigned(ELF::EF_AMDGPU_FEATURE_XNACK_V4),
7093
unsigned(ELF::EF_AMDGPU_FEATURE_SRAMECC_V4));
7094
break;
7095
case ELF::ELFABIVERSION_AMDGPU_HSA_V6: {
7096
std::optional<FlagEntry> VerFlagEntry;
7097
// The string needs to remain alive from the moment we create a
7098
// FlagEntry until printFlags is done.
7099
std::string FlagStr;
7100
if (auto VersionFlag = E.e_flags & ELF::EF_AMDGPU_GENERIC_VERSION) {
7101
unsigned Version =
7102
VersionFlag >> ELF::EF_AMDGPU_GENERIC_VERSION_OFFSET;
7103
FlagStr = "EF_AMDGPU_GENERIC_VERSION_V" + std::to_string(Version);
7104
VerFlagEntry = FlagEntry(FlagStr, VersionFlag);
7105
}
7106
W.printFlags(
7107
"Flags", E.e_flags, ArrayRef(ElfHeaderAMDGPUFlagsABIVersion4),
7108
unsigned(ELF::EF_AMDGPU_MACH),
7109
unsigned(ELF::EF_AMDGPU_FEATURE_XNACK_V4),
7110
unsigned(ELF::EF_AMDGPU_FEATURE_SRAMECC_V4),
7111
VerFlagEntry ? ArrayRef(*VerFlagEntry) : ArrayRef<FlagEntry>());
7112
break;
7113
}
7114
}
7115
} else if (E.e_machine == EM_RISCV)
7116
W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderRISCVFlags));
7117
else if (E.e_machine == EM_AVR)
7118
W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderAVRFlags),
7119
unsigned(ELF::EF_AVR_ARCH_MASK));
7120
else if (E.e_machine == EM_LOONGARCH)
7121
W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderLoongArchFlags),
7122
unsigned(ELF::EF_LOONGARCH_ABI_MODIFIER_MASK),
7123
unsigned(ELF::EF_LOONGARCH_OBJABI_MASK));
7124
else if (E.e_machine == EM_XTENSA)
7125
W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderXtensaFlags),
7126
unsigned(ELF::EF_XTENSA_MACH));
7127
else if (E.e_machine == EM_CUDA)
7128
W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderNVPTXFlags),
7129
unsigned(ELF::EF_CUDA_SM));
7130
else
7131
W.printFlags("Flags", E.e_flags);
7132
W.printNumber("HeaderSize", E.e_ehsize);
7133
W.printNumber("ProgramHeaderEntrySize", E.e_phentsize);
7134
W.printNumber("ProgramHeaderCount", E.e_phnum);
7135
W.printNumber("SectionHeaderEntrySize", E.e_shentsize);
7136
W.printString("SectionHeaderCount",
7137
getSectionHeadersNumString(this->Obj, this->FileName));
7138
W.printString("StringTableSectionIndex",
7139
getSectionHeaderTableIndexString(this->Obj, this->FileName));
7140
}
7141
}
7142
7143
template <class ELFT> void LLVMELFDumper<ELFT>::printGroupSections() {
7144
DictScope Lists(W, "Groups");
7145
std::vector<GroupSection> V = this->getGroups();
7146
DenseMap<uint64_t, const GroupSection *> Map = mapSectionsToGroups(V);
7147
for (const GroupSection &G : V) {
7148
DictScope D(W, "Group");
7149
W.printNumber("Name", G.Name, G.ShName);
7150
W.printNumber("Index", G.Index);
7151
W.printNumber("Link", G.Link);
7152
W.printNumber("Info", G.Info);
7153
W.printHex("Type", getGroupType(G.Type), G.Type);
7154
W.printString("Signature", G.Signature);
7155
7156
ListScope L(W, getGroupSectionHeaderName());
7157
for (const GroupMember &GM : G.Members) {
7158
const GroupSection *MainGroup = Map[GM.Index];
7159
if (MainGroup != &G)
7160
this->reportUniqueWarning(
7161
"section with index " + Twine(GM.Index) +
7162
", included in the group section with index " +
7163
Twine(MainGroup->Index) +
7164
", was also found in the group section with index " +
7165
Twine(G.Index));
7166
printSectionGroupMembers(GM.Name, GM.Index);
7167
}
7168
}
7169
7170
if (V.empty())
7171
printEmptyGroupMessage();
7172
}
7173
7174
template <class ELFT>
7175
std::string LLVMELFDumper<ELFT>::getGroupSectionHeaderName() const {
7176
return "Section(s) in group";
7177
}
7178
7179
template <class ELFT>
7180
void LLVMELFDumper<ELFT>::printSectionGroupMembers(StringRef Name,
7181
uint64_t Idx) const {
7182
W.startLine() << Name << " (" << Idx << ")\n";
7183
}
7184
7185
template <class ELFT> void LLVMELFDumper<ELFT>::printRelocations() {
7186
ListScope D(W, "Relocations");
7187
7188
for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) {
7189
if (!isRelocationSec<ELFT>(Sec, this->Obj.getHeader()))
7190
continue;
7191
7192
StringRef Name = this->getPrintableSectionName(Sec);
7193
unsigned SecNdx = &Sec - &cantFail(this->Obj.sections()).front();
7194
printRelocationSectionInfo(Sec, Name, SecNdx);
7195
}
7196
}
7197
7198
template <class ELFT>
7199
void LLVMELFDumper<ELFT>::printExpandedRelRelaReloc(const Relocation<ELFT> &R,
7200
StringRef SymbolName,
7201
StringRef RelocName) {
7202
DictScope Group(W, "Relocation");
7203
W.printHex("Offset", R.Offset);
7204
W.printNumber("Type", RelocName, R.Type);
7205
W.printNumber("Symbol", !SymbolName.empty() ? SymbolName : "-", R.Symbol);
7206
if (R.Addend)
7207
W.printHex("Addend", (uintX_t)*R.Addend);
7208
}
7209
7210
template <class ELFT>
7211
void LLVMELFDumper<ELFT>::printDefaultRelRelaReloc(const Relocation<ELFT> &R,
7212
StringRef SymbolName,
7213
StringRef RelocName) {
7214
raw_ostream &OS = W.startLine();
7215
OS << W.hex(R.Offset) << " " << RelocName << " "
7216
<< (!SymbolName.empty() ? SymbolName : "-");
7217
if (R.Addend)
7218
OS << " " << W.hex((uintX_t)*R.Addend);
7219
OS << "\n";
7220
}
7221
7222
template <class ELFT>
7223
void LLVMELFDumper<ELFT>::printRelocationSectionInfo(const Elf_Shdr &Sec,
7224
StringRef Name,
7225
const unsigned SecNdx) {
7226
DictScope D(W, (Twine("Section (") + Twine(SecNdx) + ") " + Name).str());
7227
this->printRelocationsHelper(Sec);
7228
}
7229
7230
template <class ELFT> void LLVMELFDumper<ELFT>::printEmptyGroupMessage() const {
7231
W.startLine() << "There are no group sections in the file.\n";
7232
}
7233
7234
template <class ELFT>
7235
void LLVMELFDumper<ELFT>::printRelRelaReloc(const Relocation<ELFT> &R,
7236
const RelSymbol<ELFT> &RelSym) {
7237
StringRef SymbolName = RelSym.Name;
7238
if (RelSym.Sym && RelSym.Name.empty())
7239
SymbolName = "<null>";
7240
SmallString<32> RelocName;
7241
this->Obj.getRelocationTypeName(R.Type, RelocName);
7242
7243
if (opts::ExpandRelocs) {
7244
printExpandedRelRelaReloc(R, SymbolName, RelocName);
7245
} else {
7246
printDefaultRelRelaReloc(R, SymbolName, RelocName);
7247
}
7248
}
7249
7250
template <class ELFT> void LLVMELFDumper<ELFT>::printSectionHeaders() {
7251
ListScope SectionsD(W, "Sections");
7252
7253
int SectionIndex = -1;
7254
std::vector<EnumEntry<unsigned>> FlagsList =
7255
getSectionFlagsForTarget(this->Obj.getHeader().e_ident[ELF::EI_OSABI],
7256
this->Obj.getHeader().e_machine);
7257
for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) {
7258
DictScope SectionD(W, "Section");
7259
W.printNumber("Index", ++SectionIndex);
7260
W.printNumber("Name", this->getPrintableSectionName(Sec), Sec.sh_name);
7261
W.printHex("Type",
7262
object::getELFSectionTypeName(this->Obj.getHeader().e_machine,
7263
Sec.sh_type),
7264
Sec.sh_type);
7265
W.printFlags("Flags", Sec.sh_flags, ArrayRef(FlagsList));
7266
W.printHex("Address", Sec.sh_addr);
7267
W.printHex("Offset", Sec.sh_offset);
7268
W.printNumber("Size", Sec.sh_size);
7269
W.printNumber("Link", Sec.sh_link);
7270
W.printNumber("Info", Sec.sh_info);
7271
W.printNumber("AddressAlignment", Sec.sh_addralign);
7272
W.printNumber("EntrySize", Sec.sh_entsize);
7273
7274
if (opts::SectionRelocations) {
7275
ListScope D(W, "Relocations");
7276
this->printRelocationsHelper(Sec);
7277
}
7278
7279
if (opts::SectionSymbols) {
7280
ListScope D(W, "Symbols");
7281
if (this->DotSymtabSec) {
7282
StringRef StrTable = unwrapOrError(
7283
this->FileName,
7284
this->Obj.getStringTableForSymtab(*this->DotSymtabSec));
7285
ArrayRef<Elf_Word> ShndxTable = this->getShndxTable(this->DotSymtabSec);
7286
7287
typename ELFT::SymRange Symbols = unwrapOrError(
7288
this->FileName, this->Obj.symbols(this->DotSymtabSec));
7289
for (const Elf_Sym &Sym : Symbols) {
7290
const Elf_Shdr *SymSec = unwrapOrError(
7291
this->FileName,
7292
this->Obj.getSection(Sym, this->DotSymtabSec, ShndxTable));
7293
if (SymSec == &Sec)
7294
printSymbol(Sym, &Sym - &Symbols[0], ShndxTable, StrTable, false,
7295
/*NonVisibilityBitsUsed=*/false,
7296
/*ExtraSymInfo=*/false);
7297
}
7298
}
7299
}
7300
7301
if (opts::SectionData && Sec.sh_type != ELF::SHT_NOBITS) {
7302
ArrayRef<uint8_t> Data =
7303
unwrapOrError(this->FileName, this->Obj.getSectionContents(Sec));
7304
W.printBinaryBlock(
7305
"SectionData",
7306
StringRef(reinterpret_cast<const char *>(Data.data()), Data.size()));
7307
}
7308
}
7309
}
7310
7311
template <class ELFT>
7312
void LLVMELFDumper<ELFT>::printSymbolSection(
7313
const Elf_Sym &Symbol, unsigned SymIndex,
7314
DataRegion<Elf_Word> ShndxTable) const {
7315
auto GetSectionSpecialType = [&]() -> std::optional<StringRef> {
7316
if (Symbol.isUndefined())
7317
return StringRef("Undefined");
7318
if (Symbol.isProcessorSpecific())
7319
return StringRef("Processor Specific");
7320
if (Symbol.isOSSpecific())
7321
return StringRef("Operating System Specific");
7322
if (Symbol.isAbsolute())
7323
return StringRef("Absolute");
7324
if (Symbol.isCommon())
7325
return StringRef("Common");
7326
if (Symbol.isReserved() && Symbol.st_shndx != SHN_XINDEX)
7327
return StringRef("Reserved");
7328
return std::nullopt;
7329
};
7330
7331
if (std::optional<StringRef> Type = GetSectionSpecialType()) {
7332
W.printHex("Section", *Type, Symbol.st_shndx);
7333
return;
7334
}
7335
7336
Expected<unsigned> SectionIndex =
7337
this->getSymbolSectionIndex(Symbol, SymIndex, ShndxTable);
7338
if (!SectionIndex) {
7339
assert(Symbol.st_shndx == SHN_XINDEX &&
7340
"getSymbolSectionIndex should only fail due to an invalid "
7341
"SHT_SYMTAB_SHNDX table/reference");
7342
this->reportUniqueWarning(SectionIndex.takeError());
7343
W.printHex("Section", "Reserved", SHN_XINDEX);
7344
return;
7345
}
7346
7347
Expected<StringRef> SectionName =
7348
this->getSymbolSectionName(Symbol, *SectionIndex);
7349
if (!SectionName) {
7350
// Don't report an invalid section name if the section headers are missing.
7351
// In such situations, all sections will be "invalid".
7352
if (!this->ObjF.sections().empty())
7353
this->reportUniqueWarning(SectionName.takeError());
7354
else
7355
consumeError(SectionName.takeError());
7356
W.printHex("Section", "<?>", *SectionIndex);
7357
} else {
7358
W.printHex("Section", *SectionName, *SectionIndex);
7359
}
7360
}
7361
7362
template <class ELFT>
7363
void LLVMELFDumper<ELFT>::printSymbolOtherField(const Elf_Sym &Symbol) const {
7364
std::vector<EnumEntry<unsigned>> SymOtherFlags =
7365
this->getOtherFlagsFromSymbol(this->Obj.getHeader(), Symbol);
7366
W.printFlags("Other", Symbol.st_other, ArrayRef(SymOtherFlags), 0x3u);
7367
}
7368
7369
template <class ELFT>
7370
void LLVMELFDumper<ELFT>::printZeroSymbolOtherField(
7371
const Elf_Sym &Symbol) const {
7372
assert(Symbol.st_other == 0 && "non-zero Other Field");
7373
// Usually st_other flag is zero. Do not pollute the output
7374
// by flags enumeration in that case.
7375
W.printNumber("Other", 0);
7376
}
7377
7378
template <class ELFT>
7379
void LLVMELFDumper<ELFT>::printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,
7380
DataRegion<Elf_Word> ShndxTable,
7381
std::optional<StringRef> StrTable,
7382
bool IsDynamic,
7383
bool /*NonVisibilityBitsUsed*/,
7384
bool /*ExtraSymInfo*/) const {
7385
std::string FullSymbolName = this->getFullSymbolName(
7386
Symbol, SymIndex, ShndxTable, StrTable, IsDynamic);
7387
unsigned char SymbolType = Symbol.getType();
7388
7389
DictScope D(W, "Symbol");
7390
W.printNumber("Name", FullSymbolName, Symbol.st_name);
7391
W.printHex("Value", Symbol.st_value);
7392
W.printNumber("Size", Symbol.st_size);
7393
W.printEnum("Binding", Symbol.getBinding(), ArrayRef(ElfSymbolBindings));
7394
if (this->Obj.getHeader().e_machine == ELF::EM_AMDGPU &&
7395
SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS)
7396
W.printEnum("Type", SymbolType, ArrayRef(AMDGPUSymbolTypes));
7397
else
7398
W.printEnum("Type", SymbolType, ArrayRef(ElfSymbolTypes));
7399
if (Symbol.st_other == 0)
7400
printZeroSymbolOtherField(Symbol);
7401
else
7402
printSymbolOtherField(Symbol);
7403
printSymbolSection(Symbol, SymIndex, ShndxTable);
7404
}
7405
7406
template <class ELFT>
7407
void LLVMELFDumper<ELFT>::printSymbols(bool PrintSymbols,
7408
bool PrintDynamicSymbols,
7409
bool ExtraSymInfo) {
7410
if (PrintSymbols) {
7411
ListScope Group(W, "Symbols");
7412
this->printSymbolsHelper(false, ExtraSymInfo);
7413
}
7414
if (PrintDynamicSymbols) {
7415
ListScope Group(W, "DynamicSymbols");
7416
this->printSymbolsHelper(true, ExtraSymInfo);
7417
}
7418
}
7419
7420
template <class ELFT> void LLVMELFDumper<ELFT>::printDynamicTable() {
7421
Elf_Dyn_Range Table = this->dynamic_table();
7422
if (Table.empty())
7423
return;
7424
7425
W.startLine() << "DynamicSection [ (" << Table.size() << " entries)\n";
7426
7427
size_t MaxTagSize = getMaxDynamicTagSize(this->Obj, Table);
7428
// The "Name/Value" column should be indented from the "Type" column by N
7429
// spaces, where N = MaxTagSize - length of "Type" (4) + trailing
7430
// space (1) = -3.
7431
W.startLine() << " Tag" << std::string(ELFT::Is64Bits ? 16 : 8, ' ')
7432
<< "Type" << std::string(MaxTagSize - 3, ' ') << "Name/Value\n";
7433
7434
std::string ValueFmt = "%-" + std::to_string(MaxTagSize) + "s ";
7435
for (auto Entry : Table) {
7436
uintX_t Tag = Entry.getTag();
7437
std::string Value = this->getDynamicEntry(Tag, Entry.getVal());
7438
W.startLine() << " " << format_hex(Tag, ELFT::Is64Bits ? 18 : 10, true)
7439
<< " "
7440
<< format(ValueFmt.c_str(),
7441
this->Obj.getDynamicTagAsString(Tag).c_str())
7442
<< Value << "\n";
7443
}
7444
W.startLine() << "]\n";
7445
}
7446
7447
template <class ELFT>
7448
void JSONELFDumper<ELFT>::printAuxillaryDynamicTableEntryInfo(
7449
const Elf_Dyn &Entry) {
7450
auto FormatFlags = [this, Value = Entry.getVal()](auto Flags) {
7451
ListScope L(this->W, "Flags");
7452
for (const auto &Flag : Flags) {
7453
if (Flag.Value != 0 && (Value & Flag.Value) == Flag.Value)
7454
this->W.printString(Flag.Name);
7455
}
7456
};
7457
switch (Entry.getTag()) {
7458
case DT_SONAME:
7459
this->W.printString("Name", this->getDynamicString(Entry.getVal()));
7460
break;
7461
case DT_AUXILIARY:
7462
case DT_FILTER:
7463
case DT_NEEDED:
7464
this->W.printString("Library", this->getDynamicString(Entry.getVal()));
7465
break;
7466
case DT_USED:
7467
this->W.printString("Object", this->getDynamicString(Entry.getVal()));
7468
break;
7469
case DT_RPATH:
7470
case DT_RUNPATH: {
7471
StringRef Value = this->getDynamicString(Entry.getVal());
7472
ListScope L(this->W, "Path");
7473
while (!Value.empty()) {
7474
auto [Front, Back] = Value.split(':');
7475
this->W.printString(Front);
7476
Value = Back;
7477
}
7478
break;
7479
}
7480
case DT_FLAGS:
7481
FormatFlags(ArrayRef(ElfDynamicDTFlags));
7482
break;
7483
case DT_FLAGS_1:
7484
FormatFlags(ArrayRef(ElfDynamicDTFlags1));
7485
break;
7486
default:
7487
return;
7488
}
7489
}
7490
7491
template <class ELFT> void JSONELFDumper<ELFT>::printDynamicTable() {
7492
Elf_Dyn_Range Table = this->dynamic_table();
7493
ListScope L(this->W, "DynamicSection");
7494
for (const auto &Entry : Table) {
7495
DictScope D(this->W);
7496
uintX_t Tag = Entry.getTag();
7497
this->W.printHex("Tag", Tag);
7498
this->W.printString("Type", this->Obj.getDynamicTagAsString(Tag));
7499
this->W.printHex("Value", Entry.getVal());
7500
this->printAuxillaryDynamicTableEntryInfo(Entry);
7501
}
7502
}
7503
7504
template <class ELFT> void LLVMELFDumper<ELFT>::printDynamicRelocations() {
7505
W.startLine() << "Dynamic Relocations {\n";
7506
W.indent();
7507
this->printDynamicRelocationsHelper();
7508
W.unindent();
7509
W.startLine() << "}\n";
7510
}
7511
7512
template <class ELFT>
7513
void LLVMELFDumper<ELFT>::printProgramHeaders(
7514
bool PrintProgramHeaders, cl::boolOrDefault PrintSectionMapping) {
7515
if (PrintProgramHeaders)
7516
printProgramHeaders();
7517
if (PrintSectionMapping == cl::BOU_TRUE)
7518
printSectionMapping();
7519
}
7520
7521
template <class ELFT> void LLVMELFDumper<ELFT>::printProgramHeaders() {
7522
ListScope L(W, "ProgramHeaders");
7523
7524
Expected<ArrayRef<Elf_Phdr>> PhdrsOrErr = this->Obj.program_headers();
7525
if (!PhdrsOrErr) {
7526
this->reportUniqueWarning("unable to dump program headers: " +
7527
toString(PhdrsOrErr.takeError()));
7528
return;
7529
}
7530
7531
for (const Elf_Phdr &Phdr : *PhdrsOrErr) {
7532
DictScope P(W, "ProgramHeader");
7533
StringRef Type =
7534
segmentTypeToString(this->Obj.getHeader().e_machine, Phdr.p_type);
7535
7536
W.printHex("Type", Type.empty() ? "Unknown" : Type, Phdr.p_type);
7537
W.printHex("Offset", Phdr.p_offset);
7538
W.printHex("VirtualAddress", Phdr.p_vaddr);
7539
W.printHex("PhysicalAddress", Phdr.p_paddr);
7540
W.printNumber("FileSize", Phdr.p_filesz);
7541
W.printNumber("MemSize", Phdr.p_memsz);
7542
W.printFlags("Flags", Phdr.p_flags, ArrayRef(ElfSegmentFlags));
7543
W.printNumber("Alignment", Phdr.p_align);
7544
}
7545
}
7546
7547
template <class ELFT>
7548
void LLVMELFDumper<ELFT>::printVersionSymbolSection(const Elf_Shdr *Sec) {
7549
ListScope SS(W, "VersionSymbols");
7550
if (!Sec)
7551
return;
7552
7553
StringRef StrTable;
7554
ArrayRef<Elf_Sym> Syms;
7555
const Elf_Shdr *SymTabSec;
7556
Expected<ArrayRef<Elf_Versym>> VerTableOrErr =
7557
this->getVersionTable(*Sec, &Syms, &StrTable, &SymTabSec);
7558
if (!VerTableOrErr) {
7559
this->reportUniqueWarning(VerTableOrErr.takeError());
7560
return;
7561
}
7562
7563
if (StrTable.empty() || Syms.empty() || Syms.size() != VerTableOrErr->size())
7564
return;
7565
7566
ArrayRef<Elf_Word> ShNdxTable = this->getShndxTable(SymTabSec);
7567
for (size_t I = 0, E = Syms.size(); I < E; ++I) {
7568
DictScope S(W, "Symbol");
7569
W.printNumber("Version", (*VerTableOrErr)[I].vs_index & VERSYM_VERSION);
7570
W.printString("Name",
7571
this->getFullSymbolName(Syms[I], I, ShNdxTable, StrTable,
7572
/*IsDynamic=*/true));
7573
}
7574
}
7575
7576
const EnumEntry<unsigned> SymVersionFlags[] = {
7577
{"Base", "BASE", VER_FLG_BASE},
7578
{"Weak", "WEAK", VER_FLG_WEAK},
7579
{"Info", "INFO", VER_FLG_INFO}};
7580
7581
template <class ELFT>
7582
void LLVMELFDumper<ELFT>::printVersionDefinitionSection(const Elf_Shdr *Sec) {
7583
ListScope SD(W, "VersionDefinitions");
7584
if (!Sec)
7585
return;
7586
7587
Expected<std::vector<VerDef>> V = this->Obj.getVersionDefinitions(*Sec);
7588
if (!V) {
7589
this->reportUniqueWarning(V.takeError());
7590
return;
7591
}
7592
7593
for (const VerDef &D : *V) {
7594
DictScope Def(W, "Definition");
7595
W.printNumber("Version", D.Version);
7596
W.printFlags("Flags", D.Flags, ArrayRef(SymVersionFlags));
7597
W.printNumber("Index", D.Ndx);
7598
W.printNumber("Hash", D.Hash);
7599
W.printString("Name", D.Name.c_str());
7600
W.printList(
7601
"Predecessors", D.AuxV,
7602
[](raw_ostream &OS, const VerdAux &Aux) { OS << Aux.Name.c_str(); });
7603
}
7604
}
7605
7606
template <class ELFT>
7607
void LLVMELFDumper<ELFT>::printVersionDependencySection(const Elf_Shdr *Sec) {
7608
ListScope SD(W, "VersionRequirements");
7609
if (!Sec)
7610
return;
7611
7612
Expected<std::vector<VerNeed>> V =
7613
this->Obj.getVersionDependencies(*Sec, this->WarningHandler);
7614
if (!V) {
7615
this->reportUniqueWarning(V.takeError());
7616
return;
7617
}
7618
7619
for (const VerNeed &VN : *V) {
7620
DictScope Entry(W, "Dependency");
7621
W.printNumber("Version", VN.Version);
7622
W.printNumber("Count", VN.Cnt);
7623
W.printString("FileName", VN.File.c_str());
7624
7625
ListScope L(W, "Entries");
7626
for (const VernAux &Aux : VN.AuxV) {
7627
DictScope Entry(W, "Entry");
7628
W.printNumber("Hash", Aux.Hash);
7629
W.printFlags("Flags", Aux.Flags, ArrayRef(SymVersionFlags));
7630
W.printNumber("Index", Aux.Other);
7631
W.printString("Name", Aux.Name.c_str());
7632
}
7633
}
7634
}
7635
7636
template <class ELFT>
7637
void LLVMELFDumper<ELFT>::printHashHistogramStats(size_t NBucket,
7638
size_t MaxChain,
7639
size_t TotalSyms,
7640
ArrayRef<size_t> Count,
7641
bool IsGnu) const {
7642
StringRef HistName = IsGnu ? "GnuHashHistogram" : "HashHistogram";
7643
StringRef BucketName = IsGnu ? "Bucket" : "Chain";
7644
StringRef ListName = IsGnu ? "Buckets" : "Chains";
7645
DictScope Outer(W, HistName);
7646
W.printNumber("TotalBuckets", NBucket);
7647
ListScope Buckets(W, ListName);
7648
size_t CumulativeNonZero = 0;
7649
for (size_t I = 0; I < MaxChain; ++I) {
7650
CumulativeNonZero += Count[I] * I;
7651
DictScope Bucket(W, BucketName);
7652
W.printNumber("Length", I);
7653
W.printNumber("Count", Count[I]);
7654
W.printNumber("Percentage", (float)(Count[I] * 100.0) / NBucket);
7655
W.printNumber("Coverage", (float)(CumulativeNonZero * 100.0) / TotalSyms);
7656
}
7657
}
7658
7659
// Returns true if rel/rela section exists, and populates SymbolIndices.
7660
// Otherwise returns false.
7661
template <class ELFT>
7662
static bool getSymbolIndices(const typename ELFT::Shdr *CGRelSection,
7663
const ELFFile<ELFT> &Obj,
7664
const LLVMELFDumper<ELFT> *Dumper,
7665
SmallVector<uint32_t, 128> &SymbolIndices) {
7666
if (!CGRelSection) {
7667
Dumper->reportUniqueWarning(
7668
"relocation section for a call graph section doesn't exist");
7669
return false;
7670
}
7671
7672
if (CGRelSection->sh_type == SHT_REL) {
7673
typename ELFT::RelRange CGProfileRel;
7674
Expected<typename ELFT::RelRange> CGProfileRelOrError =
7675
Obj.rels(*CGRelSection);
7676
if (!CGProfileRelOrError) {
7677
Dumper->reportUniqueWarning("unable to load relocations for "
7678
"SHT_LLVM_CALL_GRAPH_PROFILE section: " +
7679
toString(CGProfileRelOrError.takeError()));
7680
return false;
7681
}
7682
7683
CGProfileRel = *CGProfileRelOrError;
7684
for (const typename ELFT::Rel &Rel : CGProfileRel)
7685
SymbolIndices.push_back(Rel.getSymbol(Obj.isMips64EL()));
7686
} else {
7687
// MC unconditionally produces SHT_REL, but GNU strip/objcopy may convert
7688
// the format to SHT_RELA
7689
// (https://sourceware.org/bugzilla/show_bug.cgi?id=28035)
7690
typename ELFT::RelaRange CGProfileRela;
7691
Expected<typename ELFT::RelaRange> CGProfileRelaOrError =
7692
Obj.relas(*CGRelSection);
7693
if (!CGProfileRelaOrError) {
7694
Dumper->reportUniqueWarning("unable to load relocations for "
7695
"SHT_LLVM_CALL_GRAPH_PROFILE section: " +
7696
toString(CGProfileRelaOrError.takeError()));
7697
return false;
7698
}
7699
7700
CGProfileRela = *CGProfileRelaOrError;
7701
for (const typename ELFT::Rela &Rela : CGProfileRela)
7702
SymbolIndices.push_back(Rela.getSymbol(Obj.isMips64EL()));
7703
}
7704
7705
return true;
7706
}
7707
7708
template <class ELFT> void LLVMELFDumper<ELFT>::printCGProfile() {
7709
auto IsMatch = [](const Elf_Shdr &Sec) -> bool {
7710
return Sec.sh_type == ELF::SHT_LLVM_CALL_GRAPH_PROFILE;
7711
};
7712
7713
Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> SecToRelocMapOrErr =
7714
this->Obj.getSectionAndRelocations(IsMatch);
7715
if (!SecToRelocMapOrErr) {
7716
this->reportUniqueWarning("unable to get CG Profile section(s): " +
7717
toString(SecToRelocMapOrErr.takeError()));
7718
return;
7719
}
7720
7721
for (const auto &CGMapEntry : *SecToRelocMapOrErr) {
7722
const Elf_Shdr *CGSection = CGMapEntry.first;
7723
const Elf_Shdr *CGRelSection = CGMapEntry.second;
7724
7725
Expected<ArrayRef<Elf_CGProfile>> CGProfileOrErr =
7726
this->Obj.template getSectionContentsAsArray<Elf_CGProfile>(*CGSection);
7727
if (!CGProfileOrErr) {
7728
this->reportUniqueWarning(
7729
"unable to load the SHT_LLVM_CALL_GRAPH_PROFILE section: " +
7730
toString(CGProfileOrErr.takeError()));
7731
return;
7732
}
7733
7734
SmallVector<uint32_t, 128> SymbolIndices;
7735
bool UseReloc =
7736
getSymbolIndices<ELFT>(CGRelSection, this->Obj, this, SymbolIndices);
7737
if (UseReloc && SymbolIndices.size() != CGProfileOrErr->size() * 2) {
7738
this->reportUniqueWarning(
7739
"number of from/to pairs does not match number of frequencies");
7740
UseReloc = false;
7741
}
7742
7743
ListScope L(W, "CGProfile");
7744
for (uint32_t I = 0, Size = CGProfileOrErr->size(); I != Size; ++I) {
7745
const Elf_CGProfile &CGPE = (*CGProfileOrErr)[I];
7746
DictScope D(W, "CGProfileEntry");
7747
if (UseReloc) {
7748
uint32_t From = SymbolIndices[I * 2];
7749
uint32_t To = SymbolIndices[I * 2 + 1];
7750
W.printNumber("From", this->getStaticSymbolName(From), From);
7751
W.printNumber("To", this->getStaticSymbolName(To), To);
7752
}
7753
W.printNumber("Weight", CGPE.cgp_weight);
7754
}
7755
}
7756
}
7757
7758
template <class ELFT>
7759
void LLVMELFDumper<ELFT>::printBBAddrMaps(bool PrettyPGOAnalysis) {
7760
bool IsRelocatable = this->Obj.getHeader().e_type == ELF::ET_REL;
7761
using Elf_Shdr = typename ELFT::Shdr;
7762
auto IsMatch = [](const Elf_Shdr &Sec) -> bool {
7763
return Sec.sh_type == ELF::SHT_LLVM_BB_ADDR_MAP;
7764
};
7765
Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> SecRelocMapOrErr =
7766
this->Obj.getSectionAndRelocations(IsMatch);
7767
if (!SecRelocMapOrErr) {
7768
this->reportUniqueWarning(
7769
"failed to get SHT_LLVM_BB_ADDR_MAP section(s): " +
7770
toString(SecRelocMapOrErr.takeError()));
7771
return;
7772
}
7773
for (auto const &[Sec, RelocSec] : *SecRelocMapOrErr) {
7774
std::optional<const Elf_Shdr *> FunctionSec;
7775
if (IsRelocatable)
7776
FunctionSec =
7777
unwrapOrError(this->FileName, this->Obj.getSection(Sec->sh_link));
7778
ListScope L(W, "BBAddrMap");
7779
if (IsRelocatable && !RelocSec) {
7780
this->reportUniqueWarning("unable to get relocation section for " +
7781
this->describe(*Sec));
7782
continue;
7783
}
7784
std::vector<PGOAnalysisMap> PGOAnalyses;
7785
Expected<std::vector<BBAddrMap>> BBAddrMapOrErr =
7786
this->Obj.decodeBBAddrMap(*Sec, RelocSec, &PGOAnalyses);
7787
if (!BBAddrMapOrErr) {
7788
this->reportUniqueWarning("unable to dump " + this->describe(*Sec) +
7789
": " + toString(BBAddrMapOrErr.takeError()));
7790
continue;
7791
}
7792
for (const auto &[AM, PAM] : zip_equal(*BBAddrMapOrErr, PGOAnalyses)) {
7793
DictScope D(W, "Function");
7794
W.printHex("At", AM.getFunctionAddress());
7795
SmallVector<uint32_t> FuncSymIndex =
7796
this->getSymbolIndexesForFunctionAddress(AM.getFunctionAddress(),
7797
FunctionSec);
7798
std::string FuncName = "<?>";
7799
if (FuncSymIndex.empty())
7800
this->reportUniqueWarning(
7801
"could not identify function symbol for address (0x" +
7802
Twine::utohexstr(AM.getFunctionAddress()) + ") in " +
7803
this->describe(*Sec));
7804
else
7805
FuncName = this->getStaticSymbolName(FuncSymIndex.front());
7806
W.printString("Name", FuncName);
7807
{
7808
ListScope BBRL(W, "BB Ranges");
7809
for (const BBAddrMap::BBRangeEntry &BBR : AM.BBRanges) {
7810
DictScope BBRD(W);
7811
W.printHex("Base Address", BBR.BaseAddress);
7812
ListScope BBEL(W, "BB Entries");
7813
for (const BBAddrMap::BBEntry &BBE : BBR.BBEntries) {
7814
DictScope BBED(W);
7815
W.printNumber("ID", BBE.ID);
7816
W.printHex("Offset", BBE.Offset);
7817
W.printHex("Size", BBE.Size);
7818
W.printBoolean("HasReturn", BBE.hasReturn());
7819
W.printBoolean("HasTailCall", BBE.hasTailCall());
7820
W.printBoolean("IsEHPad", BBE.isEHPad());
7821
W.printBoolean("CanFallThrough", BBE.canFallThrough());
7822
W.printBoolean("HasIndirectBranch", BBE.hasIndirectBranch());
7823
}
7824
}
7825
}
7826
7827
if (PAM.FeatEnable.hasPGOAnalysis()) {
7828
DictScope PD(W, "PGO analyses");
7829
7830
if (PAM.FeatEnable.FuncEntryCount)
7831
W.printNumber("FuncEntryCount", PAM.FuncEntryCount);
7832
7833
if (PAM.FeatEnable.hasPGOAnalysisBBData()) {
7834
ListScope L(W, "PGO BB entries");
7835
for (const PGOAnalysisMap::PGOBBEntry &PBBE : PAM.BBEntries) {
7836
DictScope L(W);
7837
7838
if (PAM.FeatEnable.BBFreq) {
7839
if (PrettyPGOAnalysis) {
7840
std::string BlockFreqStr;
7841
raw_string_ostream SS(BlockFreqStr);
7842
printRelativeBlockFreq(SS, PAM.BBEntries.front().BlockFreq,
7843
PBBE.BlockFreq);
7844
W.printString("Frequency", BlockFreqStr);
7845
} else {
7846
W.printNumber("Frequency", PBBE.BlockFreq.getFrequency());
7847
}
7848
}
7849
7850
if (PAM.FeatEnable.BrProb) {
7851
ListScope L(W, "Successors");
7852
for (const auto &Succ : PBBE.Successors) {
7853
DictScope L(W);
7854
W.printNumber("ID", Succ.ID);
7855
if (PrettyPGOAnalysis) {
7856
W.printObject("Probability", Succ.Prob);
7857
} else {
7858
W.printHex("Probability", Succ.Prob.getNumerator());
7859
}
7860
}
7861
}
7862
}
7863
}
7864
}
7865
}
7866
}
7867
}
7868
7869
template <class ELFT> void LLVMELFDumper<ELFT>::printAddrsig() {
7870
ListScope L(W, "Addrsig");
7871
if (!this->DotAddrsigSec)
7872
return;
7873
7874
Expected<std::vector<uint64_t>> SymsOrErr =
7875
decodeAddrsigSection(this->Obj, *this->DotAddrsigSec);
7876
if (!SymsOrErr) {
7877
this->reportUniqueWarning(SymsOrErr.takeError());
7878
return;
7879
}
7880
7881
for (uint64_t Sym : *SymsOrErr)
7882
W.printNumber("Sym", this->getStaticSymbolName(Sym), Sym);
7883
}
7884
7885
template <typename ELFT>
7886
static bool printGNUNoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc,
7887
ScopedPrinter &W) {
7888
// Return true if we were able to pretty-print the note, false otherwise.
7889
switch (NoteType) {
7890
default:
7891
return false;
7892
case ELF::NT_GNU_ABI_TAG: {
7893
const GNUAbiTag &AbiTag = getGNUAbiTag<ELFT>(Desc);
7894
if (!AbiTag.IsValid) {
7895
W.printString("ABI", "<corrupt GNU_ABI_TAG>");
7896
return false;
7897
} else {
7898
W.printString("OS", AbiTag.OSName);
7899
W.printString("ABI", AbiTag.ABI);
7900
}
7901
break;
7902
}
7903
case ELF::NT_GNU_BUILD_ID: {
7904
W.printString("Build ID", getGNUBuildId(Desc));
7905
break;
7906
}
7907
case ELF::NT_GNU_GOLD_VERSION:
7908
W.printString("Version", getDescAsStringRef(Desc));
7909
break;
7910
case ELF::NT_GNU_PROPERTY_TYPE_0:
7911
ListScope D(W, "Property");
7912
for (const std::string &Property : getGNUPropertyList<ELFT>(Desc))
7913
W.printString(Property);
7914
break;
7915
}
7916
return true;
7917
}
7918
7919
static bool printAndroidNoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc,
7920
ScopedPrinter &W) {
7921
// Return true if we were able to pretty-print the note, false otherwise.
7922
AndroidNoteProperties Props = getAndroidNoteProperties(NoteType, Desc);
7923
if (Props.empty())
7924
return false;
7925
for (const auto &KV : Props)
7926
W.printString(KV.first, KV.second);
7927
return true;
7928
}
7929
7930
template <class ELFT>
7931
void LLVMELFDumper<ELFT>::printMemtag(
7932
const ArrayRef<std::pair<std::string, std::string>> DynamicEntries,
7933
const ArrayRef<uint8_t> AndroidNoteDesc,
7934
const ArrayRef<std::pair<uint64_t, uint64_t>> Descriptors) {
7935
{
7936
ListScope L(W, "Memtag Dynamic Entries:");
7937
if (DynamicEntries.empty())
7938
W.printString("< none found >");
7939
for (const auto &DynamicEntryKV : DynamicEntries)
7940
W.printString(DynamicEntryKV.first, DynamicEntryKV.second);
7941
}
7942
7943
if (!AndroidNoteDesc.empty()) {
7944
ListScope L(W, "Memtag Android Note:");
7945
printAndroidNoteLLVMStyle(ELF::NT_ANDROID_TYPE_MEMTAG, AndroidNoteDesc, W);
7946
}
7947
7948
if (Descriptors.empty())
7949
return;
7950
7951
{
7952
ListScope L(W, "Memtag Global Descriptors:");
7953
for (const auto &[Addr, BytesToTag] : Descriptors) {
7954
W.printHex("0x" + utohexstr(Addr), BytesToTag);
7955
}
7956
}
7957
}
7958
7959
template <typename ELFT>
7960
static bool printLLVMOMPOFFLOADNoteLLVMStyle(uint32_t NoteType,
7961
ArrayRef<uint8_t> Desc,
7962
ScopedPrinter &W) {
7963
switch (NoteType) {
7964
default:
7965
return false;
7966
case ELF::NT_LLVM_OPENMP_OFFLOAD_VERSION:
7967
W.printString("Version", getDescAsStringRef(Desc));
7968
break;
7969
case ELF::NT_LLVM_OPENMP_OFFLOAD_PRODUCER:
7970
W.printString("Producer", getDescAsStringRef(Desc));
7971
break;
7972
case ELF::NT_LLVM_OPENMP_OFFLOAD_PRODUCER_VERSION:
7973
W.printString("Producer version", getDescAsStringRef(Desc));
7974
break;
7975
}
7976
return true;
7977
}
7978
7979
static void printCoreNoteLLVMStyle(const CoreNote &Note, ScopedPrinter &W) {
7980
W.printNumber("Page Size", Note.PageSize);
7981
ListScope D(W, "Mappings");
7982
for (const CoreFileMapping &Mapping : Note.Mappings) {
7983
DictScope D(W);
7984
W.printHex("Start", Mapping.Start);
7985
W.printHex("End", Mapping.End);
7986
W.printHex("Offset", Mapping.Offset);
7987
W.printString("Filename", Mapping.Filename);
7988
}
7989
}
7990
7991
template <class ELFT> void LLVMELFDumper<ELFT>::printNotes() {
7992
ListScope L(W, "NoteSections");
7993
7994
std::unique_ptr<DictScope> NoteSectionScope;
7995
std::unique_ptr<ListScope> NotesScope;
7996
size_t Align = 0;
7997
auto StartNotes = [&](std::optional<StringRef> SecName,
7998
const typename ELFT::Off Offset,
7999
const typename ELFT::Addr Size, size_t Al) {
8000
Align = std::max<size_t>(Al, 4);
8001
NoteSectionScope = std::make_unique<DictScope>(W, "NoteSection");
8002
W.printString("Name", SecName ? *SecName : "<?>");
8003
W.printHex("Offset", Offset);
8004
W.printHex("Size", Size);
8005
NotesScope = std::make_unique<ListScope>(W, "Notes");
8006
};
8007
8008
auto EndNotes = [&] {
8009
NotesScope.reset();
8010
NoteSectionScope.reset();
8011
};
8012
8013
auto ProcessNote = [&](const Elf_Note &Note, bool IsCore) -> Error {
8014
DictScope D2(W);
8015
StringRef Name = Note.getName();
8016
ArrayRef<uint8_t> Descriptor = Note.getDesc(Align);
8017
Elf_Word Type = Note.getType();
8018
8019
// Print the note owner/type.
8020
W.printString("Owner", Name);
8021
W.printHex("Data size", Descriptor.size());
8022
8023
StringRef NoteType =
8024
getNoteTypeName<ELFT>(Note, this->Obj.getHeader().e_type);
8025
if (!NoteType.empty())
8026
W.printString("Type", NoteType);
8027
else
8028
W.printString("Type",
8029
"Unknown (" + to_string(format_hex(Type, 10)) + ")");
8030
8031
// Print the description, or fallback to printing raw bytes for unknown
8032
// owners/if we fail to pretty-print the contents.
8033
if (Name == "GNU") {
8034
if (printGNUNoteLLVMStyle<ELFT>(Type, Descriptor, W))
8035
return Error::success();
8036
} else if (Name == "FreeBSD") {
8037
if (std::optional<FreeBSDNote> N =
8038
getFreeBSDNote<ELFT>(Type, Descriptor, IsCore)) {
8039
W.printString(N->Type, N->Value);
8040
return Error::success();
8041
}
8042
} else if (Name == "AMD") {
8043
const AMDNote N = getAMDNote<ELFT>(Type, Descriptor);
8044
if (!N.Type.empty()) {
8045
W.printString(N.Type, N.Value);
8046
return Error::success();
8047
}
8048
} else if (Name == "AMDGPU") {
8049
const AMDGPUNote N = getAMDGPUNote<ELFT>(Type, Descriptor);
8050
if (!N.Type.empty()) {
8051
W.printString(N.Type, N.Value);
8052
return Error::success();
8053
}
8054
} else if (Name == "LLVMOMPOFFLOAD") {
8055
if (printLLVMOMPOFFLOADNoteLLVMStyle<ELFT>(Type, Descriptor, W))
8056
return Error::success();
8057
} else if (Name == "CORE") {
8058
if (Type == ELF::NT_FILE) {
8059
DataExtractor DescExtractor(
8060
Descriptor, ELFT::Endianness == llvm::endianness::little,
8061
sizeof(Elf_Addr));
8062
if (Expected<CoreNote> N = readCoreNote(DescExtractor)) {
8063
printCoreNoteLLVMStyle(*N, W);
8064
return Error::success();
8065
} else {
8066
return N.takeError();
8067
}
8068
}
8069
} else if (Name == "Android") {
8070
if (printAndroidNoteLLVMStyle(Type, Descriptor, W))
8071
return Error::success();
8072
}
8073
if (!Descriptor.empty()) {
8074
W.printBinaryBlock("Description data", Descriptor);
8075
}
8076
return Error::success();
8077
};
8078
8079
processNotesHelper(*this, /*StartNotesFn=*/StartNotes,
8080
/*ProcessNoteFn=*/ProcessNote, /*FinishNotesFn=*/EndNotes);
8081
}
8082
8083
template <class ELFT> void LLVMELFDumper<ELFT>::printELFLinkerOptions() {
8084
ListScope L(W, "LinkerOptions");
8085
8086
unsigned I = -1;
8087
for (const Elf_Shdr &Shdr : cantFail(this->Obj.sections())) {
8088
++I;
8089
if (Shdr.sh_type != ELF::SHT_LLVM_LINKER_OPTIONS)
8090
continue;
8091
8092
Expected<ArrayRef<uint8_t>> ContentsOrErr =
8093
this->Obj.getSectionContents(Shdr);
8094
if (!ContentsOrErr) {
8095
this->reportUniqueWarning("unable to read the content of the "
8096
"SHT_LLVM_LINKER_OPTIONS section: " +
8097
toString(ContentsOrErr.takeError()));
8098
continue;
8099
}
8100
if (ContentsOrErr->empty())
8101
continue;
8102
8103
if (ContentsOrErr->back() != 0) {
8104
this->reportUniqueWarning("SHT_LLVM_LINKER_OPTIONS section at index " +
8105
Twine(I) +
8106
" is broken: the "
8107
"content is not null-terminated");
8108
continue;
8109
}
8110
8111
SmallVector<StringRef, 16> Strings;
8112
toStringRef(ContentsOrErr->drop_back()).split(Strings, '\0');
8113
if (Strings.size() % 2 != 0) {
8114
this->reportUniqueWarning(
8115
"SHT_LLVM_LINKER_OPTIONS section at index " + Twine(I) +
8116
" is broken: an incomplete "
8117
"key-value pair was found. The last possible key was: \"" +
8118
Strings.back() + "\"");
8119
continue;
8120
}
8121
8122
for (size_t I = 0; I < Strings.size(); I += 2)
8123
W.printString(Strings[I], Strings[I + 1]);
8124
}
8125
}
8126
8127
template <class ELFT> void LLVMELFDumper<ELFT>::printDependentLibs() {
8128
ListScope L(W, "DependentLibs");
8129
this->printDependentLibsHelper(
8130
[](const Elf_Shdr &) {},
8131
[this](StringRef Lib, uint64_t) { W.printString(Lib); });
8132
}
8133
8134
template <class ELFT> void LLVMELFDumper<ELFT>::printStackSizes() {
8135
ListScope L(W, "StackSizes");
8136
if (this->Obj.getHeader().e_type == ELF::ET_REL)
8137
this->printRelocatableStackSizes([]() {});
8138
else
8139
this->printNonRelocatableStackSizes([]() {});
8140
}
8141
8142
template <class ELFT>
8143
void LLVMELFDumper<ELFT>::printStackSizeEntry(uint64_t Size,
8144
ArrayRef<std::string> FuncNames) {
8145
DictScope D(W, "Entry");
8146
W.printList("Functions", FuncNames);
8147
W.printHex("Size", Size);
8148
}
8149
8150
template <class ELFT>
8151
void LLVMELFDumper<ELFT>::printMipsGOT(const MipsGOTParser<ELFT> &Parser) {
8152
auto PrintEntry = [&](const Elf_Addr *E) {
8153
W.printHex("Address", Parser.getGotAddress(E));
8154
W.printNumber("Access", Parser.getGotOffset(E));
8155
W.printHex("Initial", *E);
8156
};
8157
8158
DictScope GS(W, Parser.IsStatic ? "Static GOT" : "Primary GOT");
8159
8160
W.printHex("Canonical gp value", Parser.getGp());
8161
{
8162
ListScope RS(W, "Reserved entries");
8163
{
8164
DictScope D(W, "Entry");
8165
PrintEntry(Parser.getGotLazyResolver());
8166
W.printString("Purpose", StringRef("Lazy resolver"));
8167
}
8168
8169
if (Parser.getGotModulePointer()) {
8170
DictScope D(W, "Entry");
8171
PrintEntry(Parser.getGotModulePointer());
8172
W.printString("Purpose", StringRef("Module pointer (GNU extension)"));
8173
}
8174
}
8175
{
8176
ListScope LS(W, "Local entries");
8177
for (auto &E : Parser.getLocalEntries()) {
8178
DictScope D(W, "Entry");
8179
PrintEntry(&E);
8180
}
8181
}
8182
8183
if (Parser.IsStatic)
8184
return;
8185
8186
{
8187
ListScope GS(W, "Global entries");
8188
for (auto &E : Parser.getGlobalEntries()) {
8189
DictScope D(W, "Entry");
8190
8191
PrintEntry(&E);
8192
8193
const Elf_Sym &Sym = *Parser.getGotSym(&E);
8194
W.printHex("Value", Sym.st_value);
8195
W.printEnum("Type", Sym.getType(), ArrayRef(ElfSymbolTypes));
8196
8197
const unsigned SymIndex = &Sym - this->dynamic_symbols().begin();
8198
DataRegion<Elf_Word> ShndxTable(
8199
(const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end());
8200
printSymbolSection(Sym, SymIndex, ShndxTable);
8201
8202
std::string SymName = this->getFullSymbolName(
8203
Sym, SymIndex, ShndxTable, this->DynamicStringTable, true);
8204
W.printNumber("Name", SymName, Sym.st_name);
8205
}
8206
}
8207
8208
W.printNumber("Number of TLS and multi-GOT entries",
8209
uint64_t(Parser.getOtherEntries().size()));
8210
}
8211
8212
template <class ELFT>
8213
void LLVMELFDumper<ELFT>::printMipsPLT(const MipsGOTParser<ELFT> &Parser) {
8214
auto PrintEntry = [&](const Elf_Addr *E) {
8215
W.printHex("Address", Parser.getPltAddress(E));
8216
W.printHex("Initial", *E);
8217
};
8218
8219
DictScope GS(W, "PLT GOT");
8220
8221
{
8222
ListScope RS(W, "Reserved entries");
8223
{
8224
DictScope D(W, "Entry");
8225
PrintEntry(Parser.getPltLazyResolver());
8226
W.printString("Purpose", StringRef("PLT lazy resolver"));
8227
}
8228
8229
if (auto E = Parser.getPltModulePointer()) {
8230
DictScope D(W, "Entry");
8231
PrintEntry(E);
8232
W.printString("Purpose", StringRef("Module pointer"));
8233
}
8234
}
8235
{
8236
ListScope LS(W, "Entries");
8237
DataRegion<Elf_Word> ShndxTable(
8238
(const Elf_Word *)this->DynSymTabShndxRegion.Addr, this->Obj.end());
8239
for (auto &E : Parser.getPltEntries()) {
8240
DictScope D(W, "Entry");
8241
PrintEntry(&E);
8242
8243
const Elf_Sym &Sym = *Parser.getPltSym(&E);
8244
W.printHex("Value", Sym.st_value);
8245
W.printEnum("Type", Sym.getType(), ArrayRef(ElfSymbolTypes));
8246
printSymbolSection(Sym, &Sym - this->dynamic_symbols().begin(),
8247
ShndxTable);
8248
8249
const Elf_Sym *FirstSym = cantFail(
8250
this->Obj.template getEntry<Elf_Sym>(*Parser.getPltSymTable(), 0));
8251
std::string SymName = this->getFullSymbolName(
8252
Sym, &Sym - FirstSym, ShndxTable, Parser.getPltStrTable(), true);
8253
W.printNumber("Name", SymName, Sym.st_name);
8254
}
8255
}
8256
}
8257
8258
template <class ELFT> void LLVMELFDumper<ELFT>::printMipsABIFlags() {
8259
const Elf_Mips_ABIFlags<ELFT> *Flags;
8260
if (Expected<const Elf_Mips_ABIFlags<ELFT> *> SecOrErr =
8261
getMipsAbiFlagsSection(*this)) {
8262
Flags = *SecOrErr;
8263
if (!Flags) {
8264
W.startLine() << "There is no .MIPS.abiflags section in the file.\n";
8265
return;
8266
}
8267
} else {
8268
this->reportUniqueWarning(SecOrErr.takeError());
8269
return;
8270
}
8271
8272
raw_ostream &OS = W.getOStream();
8273
DictScope GS(W, "MIPS ABI Flags");
8274
8275
W.printNumber("Version", Flags->version);
8276
W.startLine() << "ISA: ";
8277
if (Flags->isa_rev <= 1)
8278
OS << format("MIPS%u", Flags->isa_level);
8279
else
8280
OS << format("MIPS%ur%u", Flags->isa_level, Flags->isa_rev);
8281
OS << "\n";
8282
W.printEnum("ISA Extension", Flags->isa_ext, ArrayRef(ElfMipsISAExtType));
8283
W.printFlags("ASEs", Flags->ases, ArrayRef(ElfMipsASEFlags));
8284
W.printEnum("FP ABI", Flags->fp_abi, ArrayRef(ElfMipsFpABIType));
8285
W.printNumber("GPR size", getMipsRegisterSize(Flags->gpr_size));
8286
W.printNumber("CPR1 size", getMipsRegisterSize(Flags->cpr1_size));
8287
W.printNumber("CPR2 size", getMipsRegisterSize(Flags->cpr2_size));
8288
W.printFlags("Flags 1", Flags->flags1, ArrayRef(ElfMipsFlags1));
8289
W.printHex("Flags 2", Flags->flags2);
8290
}
8291
8292
template <class ELFT>
8293
void JSONELFDumper<ELFT>::printFileSummary(StringRef FileStr, ObjectFile &Obj,
8294
ArrayRef<std::string> InputFilenames,
8295
const Archive *A) {
8296
FileScope = std::make_unique<DictScope>(this->W);
8297
DictScope D(this->W, "FileSummary");
8298
this->W.printString("File", FileStr);
8299
this->W.printString("Format", Obj.getFileFormatName());
8300
this->W.printString("Arch", Triple::getArchTypeName(Obj.getArch()));
8301
this->W.printString(
8302
"AddressSize",
8303
std::string(formatv("{0}bit", 8 * Obj.getBytesInAddress())));
8304
this->printLoadName();
8305
}
8306
8307
template <class ELFT>
8308
void JSONELFDumper<ELFT>::printZeroSymbolOtherField(
8309
const Elf_Sym &Symbol) const {
8310
// We want the JSON format to be uniform, since it is machine readable, so
8311
// always print the `Other` field the same way.
8312
this->printSymbolOtherField(Symbol);
8313
}
8314
8315
template <class ELFT>
8316
void JSONELFDumper<ELFT>::printDefaultRelRelaReloc(const Relocation<ELFT> &R,
8317
StringRef SymbolName,
8318
StringRef RelocName) {
8319
this->printExpandedRelRelaReloc(R, SymbolName, RelocName);
8320
}
8321
8322
template <class ELFT>
8323
void JSONELFDumper<ELFT>::printRelocationSectionInfo(const Elf_Shdr &Sec,
8324
StringRef Name,
8325
const unsigned SecNdx) {
8326
DictScope Group(this->W);
8327
this->W.printNumber("SectionIndex", SecNdx);
8328
ListScope D(this->W, "Relocs");
8329
this->printRelocationsHelper(Sec);
8330
}
8331
8332
template <class ELFT>
8333
std::string JSONELFDumper<ELFT>::getGroupSectionHeaderName() const {
8334
return "GroupSections";
8335
}
8336
8337
template <class ELFT>
8338
void JSONELFDumper<ELFT>::printSectionGroupMembers(StringRef Name,
8339
uint64_t Idx) const {
8340
DictScope Grp(this->W);
8341
this->W.printString("Name", Name);
8342
this->W.printNumber("Index", Idx);
8343
}
8344
8345
template <class ELFT> void JSONELFDumper<ELFT>::printEmptyGroupMessage() const {
8346
// JSON output does not need to print anything for empty groups
8347
}
8348
8349