Skip to content

Commit c196488

Browse files
author
George Rimar
committedJan 18, 2019
[llvm-objdump] - Move getRelocationValueString and dependenices out of the llvm-objdump.cpp
getRelocationValueString is a dispatcher function that calls the corresponding ELF/COFF/Wasm/MachO implementations that currently live in the llvm-objdump.cpp file. These implementations better be moved to ELFDump.cpp, COFFDump.cpp and other corresponding files, to move platform specific implementation out from the common logic. The patch does that. Also, I had to move ToolSectionFilter helper and SectionFilterIterator, SectionFilter to a header to make them available across the objdump code. Differential revision: https://reviews.llvm.org/D56842 llvm-svn: 351545
1 parent 77364be commit c196488

File tree

6 files changed

+459
-433
lines changed

6 files changed

+459
-433
lines changed
 

‎llvm/tools/llvm-objdump/COFFDump.cpp

+13
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,19 @@ static bool getPDataSection(const COFFObjectFile *Obj,
469469
return false;
470470
}
471471

472+
std::error_code
473+
llvm::getCOFFRelocationValueString(const COFFObjectFile *Obj,
474+
const RelocationRef &Rel,
475+
SmallVectorImpl<char> &Result) {
476+
symbol_iterator SymI = Rel.getSymbol();
477+
Expected<StringRef> SymNameOrErr = SymI->getName();
478+
if (!SymNameOrErr)
479+
return errorToErrorCode(SymNameOrErr.takeError());
480+
StringRef SymName = *SymNameOrErr;
481+
Result.append(SymName.begin(), SymName.end());
482+
return std::error_code();
483+
}
484+
472485
static void printWin64EHUnwindInfo(const Win64EH::UnwindInfo *UI) {
473486
// The casts to int are required in order to output the value as number.
474487
// Without the casts the value would be interpreted as char data (which

‎llvm/tools/llvm-objdump/ELFDump.cpp

+82
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
//===----------------------------------------------------------------------===//
1414

1515
#include "llvm-objdump.h"
16+
#include "llvm/Demangle/Demangle.h"
1617
#include "llvm/Object/ELFObjectFile.h"
1718
#include "llvm/Support/Format.h"
1819
#include "llvm/Support/MathExtras.h"
@@ -51,6 +52,87 @@ Expected<StringRef> getDynamicStrTab(const ELFFile<ELFT> *Elf) {
5152
return createError("dynamic string table not found");
5253
}
5354

55+
template <class ELFT>
56+
static std::error_code getRelocationValueString(const ELFObjectFile<ELFT> *Obj,
57+
const RelocationRef &RelRef,
58+
SmallVectorImpl<char> &Result) {
59+
typedef typename ELFObjectFile<ELFT>::Elf_Sym Elf_Sym;
60+
typedef typename ELFObjectFile<ELFT>::Elf_Shdr Elf_Shdr;
61+
typedef typename ELFObjectFile<ELFT>::Elf_Rela Elf_Rela;
62+
63+
const ELFFile<ELFT> &EF = *Obj->getELFFile();
64+
DataRefImpl Rel = RelRef.getRawDataRefImpl();
65+
auto SecOrErr = EF.getSection(Rel.d.a);
66+
if (!SecOrErr)
67+
return errorToErrorCode(SecOrErr.takeError());
68+
69+
int64_t Addend = 0;
70+
// If there is no Symbol associated with the relocation, we set the undef
71+
// boolean value to 'true'. This will prevent us from calling functions that
72+
// requires the relocation to be associated with a symbol.
73+
//
74+
// In SHT_REL case we would need to read the addend from section data.
75+
// GNU objdump does not do that and we just follow for simplicity atm.
76+
bool Undef = false;
77+
if ((*SecOrErr)->sh_type == ELF::SHT_RELA) {
78+
const Elf_Rela *ERela = Obj->getRela(Rel);
79+
Addend = ERela->r_addend;
80+
Undef = ERela->getSymbol(false) == 0;
81+
} else if ((*SecOrErr)->sh_type != ELF::SHT_REL) {
82+
return object_error::parse_failed;
83+
}
84+
85+
// Default scheme is to print Target, as well as "+ <addend>" for nonzero
86+
// addend. Should be acceptable for all normal purposes.
87+
std::string FmtBuf;
88+
raw_string_ostream Fmt(FmtBuf);
89+
90+
if (!Undef) {
91+
symbol_iterator SI = RelRef.getSymbol();
92+
const Elf_Sym *Sym = Obj->getSymbol(SI->getRawDataRefImpl());
93+
if (Sym->getType() == ELF::STT_SECTION) {
94+
Expected<section_iterator> SymSI = SI->getSection();
95+
if (!SymSI)
96+
return errorToErrorCode(SymSI.takeError());
97+
const Elf_Shdr *SymSec = Obj->getSection((*SymSI)->getRawDataRefImpl());
98+
auto SecName = EF.getSectionName(SymSec);
99+
if (!SecName)
100+
return errorToErrorCode(SecName.takeError());
101+
Fmt << *SecName;
102+
} else {
103+
Expected<StringRef> SymName = SI->getName();
104+
if (!SymName)
105+
return errorToErrorCode(SymName.takeError());
106+
if (Demangle)
107+
Fmt << demangle(*SymName);
108+
else
109+
Fmt << *SymName;
110+
}
111+
} else {
112+
Fmt << "*ABS*";
113+
}
114+
115+
if (Addend != 0)
116+
Fmt << (Addend < 0 ? "" : "+") << Addend;
117+
Fmt.flush();
118+
Result.append(FmtBuf.begin(), FmtBuf.end());
119+
return std::error_code();
120+
}
121+
122+
std::error_code
123+
llvm::getELFRelocationValueString(const ELFObjectFileBase *Obj,
124+
const RelocationRef &Rel,
125+
SmallVectorImpl<char> &Result) {
126+
if (auto *ELF32LE = dyn_cast<ELF32LEObjectFile>(Obj))
127+
return getRelocationValueString(ELF32LE, Rel, Result);
128+
if (auto *ELF64LE = dyn_cast<ELF64LEObjectFile>(Obj))
129+
return getRelocationValueString(ELF64LE, Rel, Result);
130+
if (auto *ELF32BE = dyn_cast<ELF32BEObjectFile>(Obj))
131+
return getRelocationValueString(ELF32BE, Rel, Result);
132+
auto *ELF64BE = cast<ELF64BEObjectFile>(Obj);
133+
return getRelocationValueString(ELF64BE, Rel, Result);
134+
}
135+
54136
template <class ELFT>
55137
void printDynamicSection(const ELFFile<ELFT> *Elf, StringRef Filename) {
56138
auto ProgramHeaderOrError = Elf->program_headers();

‎llvm/tools/llvm-objdump/MachODump.cpp

+258
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,264 @@ static void getSectionsAndSymbols(MachOObjectFile *MachOObj,
342342
}
343343
}
344344

345+
static void printRelocationTargetName(const MachOObjectFile *O,
346+
const MachO::any_relocation_info &RE,
347+
raw_string_ostream &Fmt) {
348+
// Target of a scattered relocation is an address. In the interest of
349+
// generating pretty output, scan through the symbol table looking for a
350+
// symbol that aligns with that address. If we find one, print it.
351+
// Otherwise, we just print the hex address of the target.
352+
if (O->isRelocationScattered(RE)) {
353+
uint32_t Val = O->getPlainRelocationSymbolNum(RE);
354+
355+
for (const SymbolRef &Symbol : O->symbols()) {
356+
Expected<uint64_t> Addr = Symbol.getAddress();
357+
if (!Addr)
358+
report_error(O->getFileName(), Addr.takeError());
359+
if (*Addr != Val)
360+
continue;
361+
Expected<StringRef> Name = Symbol.getName();
362+
if (!Name)
363+
report_error(O->getFileName(), Name.takeError());
364+
Fmt << *Name;
365+
return;
366+
}
367+
368+
// If we couldn't find a symbol that this relocation refers to, try
369+
// to find a section beginning instead.
370+
for (const SectionRef &Section : ToolSectionFilter(*O)) {
371+
std::error_code ec;
372+
373+
StringRef Name;
374+
uint64_t Addr = Section.getAddress();
375+
if (Addr != Val)
376+
continue;
377+
if ((ec = Section.getName(Name)))
378+
report_error(O->getFileName(), ec);
379+
Fmt << Name;
380+
return;
381+
}
382+
383+
Fmt << format("0x%x", Val);
384+
return;
385+
}
386+
387+
StringRef S;
388+
bool isExtern = O->getPlainRelocationExternal(RE);
389+
uint64_t Val = O->getPlainRelocationSymbolNum(RE);
390+
391+
if (O->getAnyRelocationType(RE) == MachO::ARM64_RELOC_ADDEND) {
392+
Fmt << format("0x%0" PRIx64, Val);
393+
return;
394+
}
395+
396+
if (isExtern) {
397+
symbol_iterator SI = O->symbol_begin();
398+
advance(SI, Val);
399+
Expected<StringRef> SOrErr = SI->getName();
400+
if (!SOrErr)
401+
report_error(O->getFileName(), SOrErr.takeError());
402+
S = *SOrErr;
403+
} else {
404+
section_iterator SI = O->section_begin();
405+
// Adjust for the fact that sections are 1-indexed.
406+
if (Val == 0) {
407+
Fmt << "0 (?,?)";
408+
return;
409+
}
410+
uint32_t I = Val - 1;
411+
while (I != 0 && SI != O->section_end()) {
412+
--I;
413+
advance(SI, 1);
414+
}
415+
if (SI == O->section_end())
416+
Fmt << Val << " (?,?)";
417+
else
418+
SI->getName(S);
419+
}
420+
421+
Fmt << S;
422+
}
423+
424+
std::error_code
425+
llvm::getMachORelocationValueString(const MachOObjectFile *Obj,
426+
const RelocationRef &RelRef,
427+
SmallVectorImpl<char> &Result) {
428+
DataRefImpl Rel = RelRef.getRawDataRefImpl();
429+
MachO::any_relocation_info RE = Obj->getRelocation(Rel);
430+
431+
unsigned Arch = Obj->getArch();
432+
433+
std::string FmtBuf;
434+
raw_string_ostream Fmt(FmtBuf);
435+
unsigned Type = Obj->getAnyRelocationType(RE);
436+
bool IsPCRel = Obj->getAnyRelocationPCRel(RE);
437+
438+
// Determine any addends that should be displayed with the relocation.
439+
// These require decoding the relocation type, which is triple-specific.
440+
441+
// X86_64 has entirely custom relocation types.
442+
if (Arch == Triple::x86_64) {
443+
switch (Type) {
444+
case MachO::X86_64_RELOC_GOT_LOAD:
445+
case MachO::X86_64_RELOC_GOT: {
446+
printRelocationTargetName(Obj, RE, Fmt);
447+
Fmt << "@GOT";
448+
if (IsPCRel)
449+
Fmt << "PCREL";
450+
break;
451+
}
452+
case MachO::X86_64_RELOC_SUBTRACTOR: {
453+
DataRefImpl RelNext = Rel;
454+
Obj->moveRelocationNext(RelNext);
455+
MachO::any_relocation_info RENext = Obj->getRelocation(RelNext);
456+
457+
// X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
458+
// X86_64_RELOC_UNSIGNED.
459+
// NOTE: Scattered relocations don't exist on x86_64.
460+
unsigned RType = Obj->getAnyRelocationType(RENext);
461+
if (RType != MachO::X86_64_RELOC_UNSIGNED)
462+
report_error(Obj->getFileName(), "Expected X86_64_RELOC_UNSIGNED after "
463+
"X86_64_RELOC_SUBTRACTOR.");
464+
465+
// The X86_64_RELOC_UNSIGNED contains the minuend symbol;
466+
// X86_64_RELOC_SUBTRACTOR contains the subtrahend.
467+
printRelocationTargetName(Obj, RENext, Fmt);
468+
Fmt << "-";
469+
printRelocationTargetName(Obj, RE, Fmt);
470+
break;
471+
}
472+
case MachO::X86_64_RELOC_TLV:
473+
printRelocationTargetName(Obj, RE, Fmt);
474+
Fmt << "@TLV";
475+
if (IsPCRel)
476+
Fmt << "P";
477+
break;
478+
case MachO::X86_64_RELOC_SIGNED_1:
479+
printRelocationTargetName(Obj, RE, Fmt);
480+
Fmt << "-1";
481+
break;
482+
case MachO::X86_64_RELOC_SIGNED_2:
483+
printRelocationTargetName(Obj, RE, Fmt);
484+
Fmt << "-2";
485+
break;
486+
case MachO::X86_64_RELOC_SIGNED_4:
487+
printRelocationTargetName(Obj, RE, Fmt);
488+
Fmt << "-4";
489+
break;
490+
default:
491+
printRelocationTargetName(Obj, RE, Fmt);
492+
break;
493+
}
494+
// X86 and ARM share some relocation types in common.
495+
} else if (Arch == Triple::x86 || Arch == Triple::arm ||
496+
Arch == Triple::ppc) {
497+
// Generic relocation types...
498+
switch (Type) {
499+
case MachO::GENERIC_RELOC_PAIR: // prints no info
500+
return std::error_code();
501+
case MachO::GENERIC_RELOC_SECTDIFF: {
502+
DataRefImpl RelNext = Rel;
503+
Obj->moveRelocationNext(RelNext);
504+
MachO::any_relocation_info RENext = Obj->getRelocation(RelNext);
505+
506+
// X86 sect diff's must be followed by a relocation of type
507+
// GENERIC_RELOC_PAIR.
508+
unsigned RType = Obj->getAnyRelocationType(RENext);
509+
510+
if (RType != MachO::GENERIC_RELOC_PAIR)
511+
report_error(Obj->getFileName(), "Expected GENERIC_RELOC_PAIR after "
512+
"GENERIC_RELOC_SECTDIFF.");
513+
514+
printRelocationTargetName(Obj, RE, Fmt);
515+
Fmt << "-";
516+
printRelocationTargetName(Obj, RENext, Fmt);
517+
break;
518+
}
519+
}
520+
521+
if (Arch == Triple::x86 || Arch == Triple::ppc) {
522+
switch (Type) {
523+
case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
524+
DataRefImpl RelNext = Rel;
525+
Obj->moveRelocationNext(RelNext);
526+
MachO::any_relocation_info RENext = Obj->getRelocation(RelNext);
527+
528+
// X86 sect diff's must be followed by a relocation of type
529+
// GENERIC_RELOC_PAIR.
530+
unsigned RType = Obj->getAnyRelocationType(RENext);
531+
if (RType != MachO::GENERIC_RELOC_PAIR)
532+
report_error(Obj->getFileName(), "Expected GENERIC_RELOC_PAIR after "
533+
"GENERIC_RELOC_LOCAL_SECTDIFF.");
534+
535+
printRelocationTargetName(Obj, RE, Fmt);
536+
Fmt << "-";
537+
printRelocationTargetName(Obj, RENext, Fmt);
538+
break;
539+
}
540+
case MachO::GENERIC_RELOC_TLV: {
541+
printRelocationTargetName(Obj, RE, Fmt);
542+
Fmt << "@TLV";
543+
if (IsPCRel)
544+
Fmt << "P";
545+
break;
546+
}
547+
default:
548+
printRelocationTargetName(Obj, RE, Fmt);
549+
}
550+
} else { // ARM-specific relocations
551+
switch (Type) {
552+
case MachO::ARM_RELOC_HALF:
553+
case MachO::ARM_RELOC_HALF_SECTDIFF: {
554+
// Half relocations steal a bit from the length field to encode
555+
// whether this is an upper16 or a lower16 relocation.
556+
bool isUpper = (Obj->getAnyRelocationLength(RE) & 0x1) == 1;
557+
558+
if (isUpper)
559+
Fmt << ":upper16:(";
560+
else
561+
Fmt << ":lower16:(";
562+
printRelocationTargetName(Obj, RE, Fmt);
563+
564+
DataRefImpl RelNext = Rel;
565+
Obj->moveRelocationNext(RelNext);
566+
MachO::any_relocation_info RENext = Obj->getRelocation(RelNext);
567+
568+
// ARM half relocs must be followed by a relocation of type
569+
// ARM_RELOC_PAIR.
570+
unsigned RType = Obj->getAnyRelocationType(RENext);
571+
if (RType != MachO::ARM_RELOC_PAIR)
572+
report_error(Obj->getFileName(), "Expected ARM_RELOC_PAIR after "
573+
"ARM_RELOC_HALF");
574+
575+
// NOTE: The half of the target virtual address is stashed in the
576+
// address field of the secondary relocation, but we can't reverse
577+
// engineer the constant offset from it without decoding the movw/movt
578+
// instruction to find the other half in its immediate field.
579+
580+
// ARM_RELOC_HALF_SECTDIFF encodes the second section in the
581+
// symbol/section pointer of the follow-on relocation.
582+
if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
583+
Fmt << "-";
584+
printRelocationTargetName(Obj, RENext, Fmt);
585+
}
586+
587+
Fmt << ")";
588+
break;
589+
}
590+
default: {
591+
printRelocationTargetName(Obj, RE, Fmt);
592+
}
593+
}
594+
}
595+
} else
596+
printRelocationTargetName(Obj, RE, Fmt);
597+
598+
Fmt.flush();
599+
Result.append(FmtBuf.begin(), FmtBuf.end());
600+
return std::error_code();
601+
}
602+
345603
static void PrintIndirectSymbolTable(MachOObjectFile *O, bool verbose,
346604
uint32_t n, uint32_t count,
347605
uint32_t stride, uint64_t addr) {

‎llvm/tools/llvm-objdump/WasmDump.cpp

+25
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,28 @@ void llvm::printWasmFileHeader(const object::ObjectFile *Obj) {
2626
outs().write_hex(File->getHeader().Version);
2727
outs() << "\n";
2828
}
29+
30+
std::error_code
31+
llvm::getWasmRelocationValueString(const WasmObjectFile *Obj,
32+
const RelocationRef &RelRef,
33+
SmallVectorImpl<char> &Result) {
34+
const wasm::WasmRelocation &Rel = Obj->getWasmRelocation(RelRef);
35+
symbol_iterator SI = RelRef.getSymbol();
36+
std::string FmtBuf;
37+
raw_string_ostream Fmt(FmtBuf);
38+
if (SI == Obj->symbol_end()) {
39+
// Not all wasm relocations have symbols associated with them.
40+
// In particular R_WEBASSEMBLY_TYPE_INDEX_LEB.
41+
Fmt << Rel.Index;
42+
} else {
43+
Expected<StringRef> SymNameOrErr = SI->getName();
44+
if (!SymNameOrErr)
45+
return errorToErrorCode(SymNameOrErr.takeError());
46+
StringRef SymName = *SymNameOrErr;
47+
Result.append(SymName.begin(), SymName.end());
48+
}
49+
Fmt << (Rel.Addend < 0 ? "" : "+") << Rel.Addend;
50+
Fmt.flush();
51+
Result.append(FmtBuf.begin(), FmtBuf.end());
52+
return std::error_code();
53+
}

‎llvm/tools/llvm-objdump/llvm-objdump.cpp

+5-426
Original file line numberDiff line numberDiff line change
@@ -281,56 +281,7 @@ static StringRef ToolName;
281281

282282
typedef std::vector<std::tuple<uint64_t, StringRef, uint8_t>> SectionSymbolsTy;
283283

284-
namespace {
285-
typedef std::function<bool(llvm::object::SectionRef const &)> FilterPredicate;
286-
287-
class SectionFilterIterator {
288-
public:
289-
SectionFilterIterator(FilterPredicate P,
290-
llvm::object::section_iterator const &I,
291-
llvm::object::section_iterator const &E)
292-
: Predicate(std::move(P)), Iterator(I), End(E) {
293-
ScanPredicate();
294-
}
295-
const llvm::object::SectionRef &operator*() const { return *Iterator; }
296-
SectionFilterIterator &operator++() {
297-
++Iterator;
298-
ScanPredicate();
299-
return *this;
300-
}
301-
bool operator!=(SectionFilterIterator const &Other) const {
302-
return Iterator != Other.Iterator;
303-
}
304-
305-
private:
306-
void ScanPredicate() {
307-
while (Iterator != End && !Predicate(*Iterator)) {
308-
++Iterator;
309-
}
310-
}
311-
FilterPredicate Predicate;
312-
llvm::object::section_iterator Iterator;
313-
llvm::object::section_iterator End;
314-
};
315-
316-
class SectionFilter {
317-
public:
318-
SectionFilter(FilterPredicate P, llvm::object::ObjectFile const &O)
319-
: Predicate(std::move(P)), Object(O) {}
320-
SectionFilterIterator begin() {
321-
return SectionFilterIterator(Predicate, Object.section_begin(),
322-
Object.section_end());
323-
}
324-
SectionFilterIterator end() {
325-
return SectionFilterIterator(Predicate, Object.section_end(),
326-
Object.section_end());
327-
}
328-
329-
private:
330-
FilterPredicate Predicate;
331-
llvm::object::ObjectFile const &Object;
332-
};
333-
SectionFilter ToolSectionFilter(llvm::object::ObjectFile const &O) {
284+
SectionFilter llvm::ToolSectionFilter(llvm::object::ObjectFile const &O) {
334285
return SectionFilter(
335286
[](llvm::object::SectionRef const &S) {
336287
if (FilterSections.empty())
@@ -343,7 +294,6 @@ SectionFilter ToolSectionFilter(llvm::object::ObjectFile const &O) {
343294
},
344295
O);
345296
}
346-
}
347297

348298
void llvm::error(std::error_code EC) {
349299
if (!EC)
@@ -464,388 +414,17 @@ bool llvm::isRelocAddressLess(RelocationRef A, RelocationRef B) {
464414
return A.getOffset() < B.getOffset();
465415
}
466416

467-
template <class ELFT>
468-
static std::error_code getRelocationValueString(const ELFObjectFile<ELFT> *Obj,
469-
const RelocationRef &RelRef,
470-
SmallVectorImpl<char> &Result) {
471-
typedef typename ELFObjectFile<ELFT>::Elf_Sym Elf_Sym;
472-
typedef typename ELFObjectFile<ELFT>::Elf_Shdr Elf_Shdr;
473-
typedef typename ELFObjectFile<ELFT>::Elf_Rela Elf_Rela;
474-
475-
const ELFFile<ELFT> &EF = *Obj->getELFFile();
476-
DataRefImpl Rel = RelRef.getRawDataRefImpl();
477-
auto SecOrErr = EF.getSection(Rel.d.a);
478-
if (!SecOrErr)
479-
return errorToErrorCode(SecOrErr.takeError());
480-
481-
int64_t Addend = 0;
482-
// If there is no Symbol associated with the relocation, we set the undef
483-
// boolean value to 'true'. This will prevent us from calling functions that
484-
// requires the relocation to be associated with a symbol.
485-
//
486-
// In SHT_REL case we would need to read the addend from section data.
487-
// GNU objdump does not do that and we just follow for simplicity.
488-
bool Undef = false;
489-
if ((*SecOrErr)->sh_type == ELF::SHT_RELA) {
490-
const Elf_Rela *ERela = Obj->getRela(Rel);
491-
Addend = ERela->r_addend;
492-
Undef = ERela->getSymbol(false) == 0;
493-
} else if ((*SecOrErr)->sh_type != ELF::SHT_REL) {
494-
return object_error::parse_failed;
495-
}
496-
497-
// Default scheme is to print Target, as well as "+ <addend>" for nonzero
498-
// addend. Should be acceptable for all normal purposes.
499-
std::string FmtBuf;
500-
raw_string_ostream Fmt(FmtBuf);
501-
502-
if (!Undef) {
503-
symbol_iterator SI = RelRef.getSymbol();
504-
const Elf_Sym *Sym = Obj->getSymbol(SI->getRawDataRefImpl());
505-
if (Sym->getType() == ELF::STT_SECTION) {
506-
Expected<section_iterator> SymSI = SI->getSection();
507-
if (!SymSI)
508-
return errorToErrorCode(SymSI.takeError());
509-
const Elf_Shdr *SymSec = Obj->getSection((*SymSI)->getRawDataRefImpl());
510-
auto SecName = EF.getSectionName(SymSec);
511-
if (!SecName)
512-
return errorToErrorCode(SecName.takeError());
513-
Fmt << *SecName;
514-
} else {
515-
Expected<StringRef> SymName = SI->getName();
516-
if (!SymName)
517-
return errorToErrorCode(SymName.takeError());
518-
if (Demangle)
519-
Fmt << demangle(*SymName);
520-
else
521-
Fmt << *SymName;
522-
}
523-
} else {
524-
Fmt << "*ABS*";
525-
}
526-
527-
if (Addend != 0)
528-
Fmt << (Addend < 0 ? "" : "+") << Addend;
529-
Fmt.flush();
530-
Result.append(FmtBuf.begin(), FmtBuf.end());
531-
return std::error_code();
532-
}
533-
534-
static std::error_code getRelocationValueString(const ELFObjectFileBase *Obj,
535-
const RelocationRef &Rel,
536-
SmallVectorImpl<char> &Result) {
537-
if (auto *ELF32LE = dyn_cast<ELF32LEObjectFile>(Obj))
538-
return getRelocationValueString(ELF32LE, Rel, Result);
539-
if (auto *ELF64LE = dyn_cast<ELF64LEObjectFile>(Obj))
540-
return getRelocationValueString(ELF64LE, Rel, Result);
541-
if (auto *ELF32BE = dyn_cast<ELF32BEObjectFile>(Obj))
542-
return getRelocationValueString(ELF32BE, Rel, Result);
543-
auto *ELF64BE = cast<ELF64BEObjectFile>(Obj);
544-
return getRelocationValueString(ELF64BE, Rel, Result);
545-
}
546-
547-
static std::error_code getRelocationValueString(const COFFObjectFile *Obj,
548-
const RelocationRef &Rel,
549-
SmallVectorImpl<char> &Result) {
550-
symbol_iterator SymI = Rel.getSymbol();
551-
Expected<StringRef> SymNameOrErr = SymI->getName();
552-
if (!SymNameOrErr)
553-
return errorToErrorCode(SymNameOrErr.takeError());
554-
StringRef SymName = *SymNameOrErr;
555-
Result.append(SymName.begin(), SymName.end());
556-
return std::error_code();
557-
}
558-
559-
static void printRelocationTargetName(const MachOObjectFile *O,
560-
const MachO::any_relocation_info &RE,
561-
raw_string_ostream &Fmt) {
562-
// Target of a scattered relocation is an address. In the interest of
563-
// generating pretty output, scan through the symbol table looking for a
564-
// symbol that aligns with that address. If we find one, print it.
565-
// Otherwise, we just print the hex address of the target.
566-
if (O->isRelocationScattered(RE)) {
567-
uint32_t Val = O->getPlainRelocationSymbolNum(RE);
568-
569-
for (const SymbolRef &Symbol : O->symbols()) {
570-
Expected<uint64_t> Addr = Symbol.getAddress();
571-
if (!Addr)
572-
report_error(O->getFileName(), Addr.takeError());
573-
if (*Addr != Val)
574-
continue;
575-
Expected<StringRef> Name = Symbol.getName();
576-
if (!Name)
577-
report_error(O->getFileName(), Name.takeError());
578-
Fmt << *Name;
579-
return;
580-
}
581-
582-
// If we couldn't find a symbol that this relocation refers to, try
583-
// to find a section beginning instead.
584-
for (const SectionRef &Section : ToolSectionFilter(*O)) {
585-
std::error_code ec;
586-
587-
StringRef Name;
588-
uint64_t Addr = Section.getAddress();
589-
if (Addr != Val)
590-
continue;
591-
if ((ec = Section.getName(Name)))
592-
report_error(O->getFileName(), ec);
593-
Fmt << Name;
594-
return;
595-
}
596-
597-
Fmt << format("0x%x", Val);
598-
return;
599-
}
600-
601-
StringRef S;
602-
bool isExtern = O->getPlainRelocationExternal(RE);
603-
uint64_t Val = O->getPlainRelocationSymbolNum(RE);
604-
605-
if (O->getAnyRelocationType(RE) == MachO::ARM64_RELOC_ADDEND) {
606-
Fmt << format("0x%0" PRIx64, Val);
607-
return;
608-
}
609-
610-
if (isExtern) {
611-
symbol_iterator SI = O->symbol_begin();
612-
advance(SI, Val);
613-
Expected<StringRef> SOrErr = SI->getName();
614-
if (!SOrErr)
615-
report_error(O->getFileName(), SOrErr.takeError());
616-
S = *SOrErr;
617-
} else {
618-
section_iterator SI = O->section_begin();
619-
// Adjust for the fact that sections are 1-indexed.
620-
if (Val == 0) {
621-
Fmt << "0 (?,?)";
622-
return;
623-
}
624-
uint32_t I = Val - 1;
625-
while (I != 0 && SI != O->section_end()) {
626-
--I;
627-
advance(SI, 1);
628-
}
629-
if (SI == O->section_end())
630-
Fmt << Val << " (?,?)";
631-
else
632-
SI->getName(S);
633-
}
634-
635-
Fmt << S;
636-
}
637-
638-
static std::error_code getRelocationValueString(const WasmObjectFile *Obj,
639-
const RelocationRef &RelRef,
640-
SmallVectorImpl<char> &Result) {
641-
const wasm::WasmRelocation& Rel = Obj->getWasmRelocation(RelRef);
642-
symbol_iterator SI = RelRef.getSymbol();
643-
std::string FmtBuf;
644-
raw_string_ostream Fmt(FmtBuf);
645-
if (SI == Obj->symbol_end()) {
646-
// Not all wasm relocations have symbols associated with them.
647-
// In particular R_WEBASSEMBLY_TYPE_INDEX_LEB.
648-
Fmt << Rel.Index;
649-
} else {
650-
Expected<StringRef> SymNameOrErr = SI->getName();
651-
if (!SymNameOrErr)
652-
return errorToErrorCode(SymNameOrErr.takeError());
653-
StringRef SymName = *SymNameOrErr;
654-
Result.append(SymName.begin(), SymName.end());
655-
}
656-
Fmt << (Rel.Addend < 0 ? "" : "+") << Rel.Addend;
657-
Fmt.flush();
658-
Result.append(FmtBuf.begin(), FmtBuf.end());
659-
return std::error_code();
660-
}
661-
662-
static std::error_code getRelocationValueString(const MachOObjectFile *Obj,
663-
const RelocationRef &RelRef,
664-
SmallVectorImpl<char> &Result) {
665-
DataRefImpl Rel = RelRef.getRawDataRefImpl();
666-
MachO::any_relocation_info RE = Obj->getRelocation(Rel);
667-
668-
unsigned Arch = Obj->getArch();
669-
670-
std::string FmtBuf;
671-
raw_string_ostream Fmt(FmtBuf);
672-
unsigned Type = Obj->getAnyRelocationType(RE);
673-
bool IsPCRel = Obj->getAnyRelocationPCRel(RE);
674-
675-
// Determine any addends that should be displayed with the relocation.
676-
// These require decoding the relocation type, which is triple-specific.
677-
678-
// X86_64 has entirely custom relocation types.
679-
if (Arch == Triple::x86_64) {
680-
switch (Type) {
681-
case MachO::X86_64_RELOC_GOT_LOAD:
682-
case MachO::X86_64_RELOC_GOT: {
683-
printRelocationTargetName(Obj, RE, Fmt);
684-
Fmt << "@GOT";
685-
if (IsPCRel)
686-
Fmt << "PCREL";
687-
break;
688-
}
689-
case MachO::X86_64_RELOC_SUBTRACTOR: {
690-
DataRefImpl RelNext = Rel;
691-
Obj->moveRelocationNext(RelNext);
692-
MachO::any_relocation_info RENext = Obj->getRelocation(RelNext);
693-
694-
// X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
695-
// X86_64_RELOC_UNSIGNED.
696-
// NOTE: Scattered relocations don't exist on x86_64.
697-
unsigned RType = Obj->getAnyRelocationType(RENext);
698-
if (RType != MachO::X86_64_RELOC_UNSIGNED)
699-
report_error(Obj->getFileName(), "Expected X86_64_RELOC_UNSIGNED after "
700-
"X86_64_RELOC_SUBTRACTOR.");
701-
702-
// The X86_64_RELOC_UNSIGNED contains the minuend symbol;
703-
// X86_64_RELOC_SUBTRACTOR contains the subtrahend.
704-
printRelocationTargetName(Obj, RENext, Fmt);
705-
Fmt << "-";
706-
printRelocationTargetName(Obj, RE, Fmt);
707-
break;
708-
}
709-
case MachO::X86_64_RELOC_TLV:
710-
printRelocationTargetName(Obj, RE, Fmt);
711-
Fmt << "@TLV";
712-
if (IsPCRel)
713-
Fmt << "P";
714-
break;
715-
case MachO::X86_64_RELOC_SIGNED_1:
716-
printRelocationTargetName(Obj, RE, Fmt);
717-
Fmt << "-1";
718-
break;
719-
case MachO::X86_64_RELOC_SIGNED_2:
720-
printRelocationTargetName(Obj, RE, Fmt);
721-
Fmt << "-2";
722-
break;
723-
case MachO::X86_64_RELOC_SIGNED_4:
724-
printRelocationTargetName(Obj, RE, Fmt);
725-
Fmt << "-4";
726-
break;
727-
default:
728-
printRelocationTargetName(Obj, RE, Fmt);
729-
break;
730-
}
731-
// X86 and ARM share some relocation types in common.
732-
} else if (Arch == Triple::x86 || Arch == Triple::arm ||
733-
Arch == Triple::ppc) {
734-
// Generic relocation types...
735-
switch (Type) {
736-
case MachO::GENERIC_RELOC_PAIR: // prints no info
737-
return std::error_code();
738-
case MachO::GENERIC_RELOC_SECTDIFF: {
739-
DataRefImpl RelNext = Rel;
740-
Obj->moveRelocationNext(RelNext);
741-
MachO::any_relocation_info RENext = Obj->getRelocation(RelNext);
742-
743-
// X86 sect diff's must be followed by a relocation of type
744-
// GENERIC_RELOC_PAIR.
745-
unsigned RType = Obj->getAnyRelocationType(RENext);
746-
747-
if (RType != MachO::GENERIC_RELOC_PAIR)
748-
report_error(Obj->getFileName(), "Expected GENERIC_RELOC_PAIR after "
749-
"GENERIC_RELOC_SECTDIFF.");
750-
751-
printRelocationTargetName(Obj, RE, Fmt);
752-
Fmt << "-";
753-
printRelocationTargetName(Obj, RENext, Fmt);
754-
break;
755-
}
756-
}
757-
758-
if (Arch == Triple::x86 || Arch == Triple::ppc) {
759-
switch (Type) {
760-
case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
761-
DataRefImpl RelNext = Rel;
762-
Obj->moveRelocationNext(RelNext);
763-
MachO::any_relocation_info RENext = Obj->getRelocation(RelNext);
764-
765-
// X86 sect diff's must be followed by a relocation of type
766-
// GENERIC_RELOC_PAIR.
767-
unsigned RType = Obj->getAnyRelocationType(RENext);
768-
if (RType != MachO::GENERIC_RELOC_PAIR)
769-
report_error(Obj->getFileName(), "Expected GENERIC_RELOC_PAIR after "
770-
"GENERIC_RELOC_LOCAL_SECTDIFF.");
771-
772-
printRelocationTargetName(Obj, RE, Fmt);
773-
Fmt << "-";
774-
printRelocationTargetName(Obj, RENext, Fmt);
775-
break;
776-
}
777-
case MachO::GENERIC_RELOC_TLV: {
778-
printRelocationTargetName(Obj, RE, Fmt);
779-
Fmt << "@TLV";
780-
if (IsPCRel)
781-
Fmt << "P";
782-
break;
783-
}
784-
default:
785-
printRelocationTargetName(Obj, RE, Fmt);
786-
}
787-
} else { // ARM-specific relocations
788-
switch (Type) {
789-
case MachO::ARM_RELOC_HALF:
790-
case MachO::ARM_RELOC_HALF_SECTDIFF: {
791-
// Half relocations steal a bit from the length field to encode
792-
// whether this is an upper16 or a lower16 relocation.
793-
bool isUpper = (Obj->getAnyRelocationLength(RE) & 0x1) == 1;
794-
795-
if (isUpper)
796-
Fmt << ":upper16:(";
797-
else
798-
Fmt << ":lower16:(";
799-
printRelocationTargetName(Obj, RE, Fmt);
800-
801-
DataRefImpl RelNext = Rel;
802-
Obj->moveRelocationNext(RelNext);
803-
MachO::any_relocation_info RENext = Obj->getRelocation(RelNext);
804-
805-
// ARM half relocs must be followed by a relocation of type
806-
// ARM_RELOC_PAIR.
807-
unsigned RType = Obj->getAnyRelocationType(RENext);
808-
if (RType != MachO::ARM_RELOC_PAIR)
809-
report_error(Obj->getFileName(), "Expected ARM_RELOC_PAIR after "
810-
"ARM_RELOC_HALF");
811-
812-
// NOTE: The half of the target virtual address is stashed in the
813-
// address field of the secondary relocation, but we can't reverse
814-
// engineer the constant offset from it without decoding the movw/movt
815-
// instruction to find the other half in its immediate field.
816-
817-
// ARM_RELOC_HALF_SECTDIFF encodes the second section in the
818-
// symbol/section pointer of the follow-on relocation.
819-
if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
820-
Fmt << "-";
821-
printRelocationTargetName(Obj, RENext, Fmt);
822-
}
823-
824-
Fmt << ")";
825-
break;
826-
}
827-
default: { printRelocationTargetName(Obj, RE, Fmt); }
828-
}
829-
}
830-
} else
831-
printRelocationTargetName(Obj, RE, Fmt);
832-
833-
Fmt.flush();
834-
Result.append(FmtBuf.begin(), FmtBuf.end());
835-
return std::error_code();
836-
}
837-
838417
static std::error_code getRelocationValueString(const RelocationRef &Rel,
839418
SmallVectorImpl<char> &Result) {
840419
const ObjectFile *Obj = Rel.getObject();
841420
if (auto *ELF = dyn_cast<ELFObjectFileBase>(Obj))
842-
return getRelocationValueString(ELF, Rel, Result);
421+
return getELFRelocationValueString(ELF, Rel, Result);
843422
if (auto *COFF = dyn_cast<COFFObjectFile>(Obj))
844-
return getRelocationValueString(COFF, Rel, Result);
423+
return getCOFFRelocationValueString(COFF, Rel, Result);
845424
if (auto *Wasm = dyn_cast<WasmObjectFile>(Obj))
846-
return getRelocationValueString(Wasm, Rel, Result);
425+
return getWasmRelocationValueString(Wasm, Rel, Result);
847426
if (auto *MachO = dyn_cast<MachOObjectFile>(Obj))
848-
return getRelocationValueString(MachO, Rel, Result);
427+
return getMachORelocationValueString(MachO, Rel, Result);
849428
llvm_unreachable("unknown object file format");
850429
}
851430

‎llvm/tools/llvm-objdump/llvm-objdump.h

+76-7
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,14 @@ namespace llvm {
1919
class StringRef;
2020

2121
namespace object {
22-
class COFFObjectFile;
23-
class COFFImportFile;
24-
class MachOObjectFile;
25-
class MachOUniversalBinary;
26-
class ObjectFile;
27-
class Archive;
28-
class RelocationRef;
22+
class COFFObjectFile;
23+
class COFFImportFile;
24+
class ELFObjectFileBase;
25+
class MachOObjectFile;
26+
class MachOUniversalBinary;
27+
class ObjectFile;
28+
class Archive;
29+
class RelocationRef;
2930
}
3031

3132
extern cl::opt<std::string> TripleName;
@@ -68,7 +69,75 @@ extern cl::opt<bool> UnwindInfo;
6869
extern cl::opt<bool> PrintImmHex;
6970
extern cl::opt<DIDumpType> DwarfDumpType;
7071

72+
typedef std::function<bool(llvm::object::SectionRef const &)> FilterPredicate;
73+
74+
class SectionFilterIterator {
75+
public:
76+
SectionFilterIterator(FilterPredicate P,
77+
llvm::object::section_iterator const &I,
78+
llvm::object::section_iterator const &E)
79+
: Predicate(std::move(P)), Iterator(I), End(E) {
80+
ScanPredicate();
81+
}
82+
const llvm::object::SectionRef &operator*() const { return *Iterator; }
83+
SectionFilterIterator &operator++() {
84+
++Iterator;
85+
ScanPredicate();
86+
return *this;
87+
}
88+
bool operator!=(SectionFilterIterator const &Other) const {
89+
return Iterator != Other.Iterator;
90+
}
91+
92+
private:
93+
void ScanPredicate() {
94+
while (Iterator != End && !Predicate(*Iterator)) {
95+
++Iterator;
96+
}
97+
}
98+
FilterPredicate Predicate;
99+
llvm::object::section_iterator Iterator;
100+
llvm::object::section_iterator End;
101+
};
102+
103+
class SectionFilter {
104+
public:
105+
SectionFilter(FilterPredicate P, llvm::object::ObjectFile const &O)
106+
: Predicate(std::move(P)), Object(O) {}
107+
SectionFilterIterator begin() {
108+
return SectionFilterIterator(Predicate, Object.section_begin(),
109+
Object.section_end());
110+
}
111+
SectionFilterIterator end() {
112+
return SectionFilterIterator(Predicate, Object.section_end(),
113+
Object.section_end());
114+
}
115+
116+
private:
117+
FilterPredicate Predicate;
118+
llvm::object::ObjectFile const &Object;
119+
};
120+
71121
// Various helper functions.
122+
SectionFilter ToolSectionFilter(llvm::object::ObjectFile const &O);
123+
124+
std::error_code
125+
getELFRelocationValueString(const object::ELFObjectFileBase *Obj,
126+
const object::RelocationRef &Rel,
127+
llvm::SmallVectorImpl<char> &Result);
128+
std::error_code
129+
getCOFFRelocationValueString(const object::COFFObjectFile *Obj,
130+
const object::RelocationRef &Rel,
131+
llvm::SmallVectorImpl<char> &Result);
132+
std::error_code
133+
getWasmRelocationValueString(const object::WasmObjectFile *Obj,
134+
const object::RelocationRef &RelRef,
135+
llvm::SmallVectorImpl<char> &Result);
136+
std::error_code
137+
getMachORelocationValueString(const object::MachOObjectFile *Obj,
138+
const object::RelocationRef &RelRef,
139+
llvm::SmallVectorImpl<char> &Result);
140+
72141
void error(std::error_code ec);
73142
bool isRelocAddressLess(object::RelocationRef A, object::RelocationRef B);
74143
void parseInputMachO(StringRef Filename);

0 commit comments

Comments
 (0)
Please sign in to comment.