Skip to content

Commit c196488

Browse files
author
George Rimar
committed
[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

Lines changed: 13 additions & 0 deletions
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

Lines changed: 82 additions & 0 deletions
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

Lines changed: 258 additions & 0 deletions
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) {

0 commit comments

Comments
 (0)