aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/tools/llvm-objdump
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/llvm-objdump')
-rw-r--r--contrib/llvm/tools/llvm-objdump/COFFDump.cpp8
-rw-r--r--contrib/llvm/tools/llvm-objdump/MachODump.cpp103
-rw-r--r--contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp547
-rw-r--r--contrib/llvm/tools/llvm-objdump/llvm-objdump.h2
4 files changed, 535 insertions, 125 deletions
diff --git a/contrib/llvm/tools/llvm-objdump/COFFDump.cpp b/contrib/llvm/tools/llvm-objdump/COFFDump.cpp
index 4a20b91b71fb..976a92154bda 100644
--- a/contrib/llvm/tools/llvm-objdump/COFFDump.cpp
+++ b/contrib/llvm/tools/llvm-objdump/COFFDump.cpp
@@ -167,7 +167,7 @@ resolveSectionAndAddress(const COFFObjectFile *Obj, const SymbolRef &Sym,
if (std::error_code EC = Sym.getSection(iter))
return EC;
ResolvedSection = Obj->getCOFFSection(*iter);
- return object_error::success;
+ return std::error_code();
}
// Given a vector of relocations for a section and an offset into this section
@@ -182,7 +182,7 @@ static std::error_code resolveSymbol(const std::vector<RelocationRef> &Rels,
return EC;
if (Ofs == Offset) {
Sym = *I->getSymbol();
- return object_error::success;
+ return std::error_code();
}
}
return object_error::parse_failed;
@@ -204,7 +204,7 @@ getSectionContents(const COFFObjectFile *Obj,
return EC;
if (std::error_code EC = Obj->getSectionContents(Section, Contents))
return EC;
- return object_error::success;
+ return std::error_code();
}
// Given a vector of relocations for a section and an offset into this section
@@ -217,7 +217,7 @@ static std::error_code resolveSymbolName(const std::vector<RelocationRef> &Rels,
return EC;
if (std::error_code EC = Sym.getName(Name))
return EC;
- return object_error::success;
+ return std::error_code();
}
static void printCOFFSymbolAddress(llvm::raw_ostream &Out,
diff --git a/contrib/llvm/tools/llvm-objdump/MachODump.cpp b/contrib/llvm/tools/llvm-objdump/MachODump.cpp
index 84212c94bbb2..bf7451eb86d7 100644
--- a/contrib/llvm/tools/llvm-objdump/MachODump.cpp
+++ b/contrib/llvm/tools/llvm-objdump/MachODump.cpp
@@ -67,10 +67,6 @@ static cl::opt<bool> FullLeadingAddr("full-leading-addr",
static cl::opt<bool> NoLeadingAddr("no-leading-addr",
cl::desc("Print no leading address"));
-static cl::opt<bool>
- PrintImmHex("print-imm-hex",
- cl::desc("Use hex format for immediate values"));
-
cl::opt<bool> llvm::UniversalHeaders("universal-headers",
cl::desc("Print Mach-O universal headers "
"(requires -macho)"));
@@ -228,19 +224,19 @@ static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length,
case MachO::DICE_KIND_DATA:
if (Length >= 4) {
if (!NoShowRawInsn)
- DumpBytes(ArrayRef<uint8_t>(bytes, 4));
+ dumpBytes(ArrayRef<uint8_t>(bytes, 4), outs());
Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
outs() << "\t.long " << Value;
Size = 4;
} else if (Length >= 2) {
if (!NoShowRawInsn)
- DumpBytes(ArrayRef<uint8_t>(bytes, 2));
+ dumpBytes(ArrayRef<uint8_t>(bytes, 2), outs());
Value = bytes[1] << 8 | bytes[0];
outs() << "\t.short " << Value;
Size = 2;
} else {
if (!NoShowRawInsn)
- DumpBytes(ArrayRef<uint8_t>(bytes, 2));
+ dumpBytes(ArrayRef<uint8_t>(bytes, 2), outs());
Value = bytes[0];
outs() << "\t.byte " << Value;
Size = 1;
@@ -252,14 +248,14 @@ static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length,
break;
case MachO::DICE_KIND_JUMP_TABLE8:
if (!NoShowRawInsn)
- DumpBytes(ArrayRef<uint8_t>(bytes, 1));
+ dumpBytes(ArrayRef<uint8_t>(bytes, 1), outs());
Value = bytes[0];
outs() << "\t.byte " << format("%3u", Value) << "\t@ KIND_JUMP_TABLE8\n";
Size = 1;
break;
case MachO::DICE_KIND_JUMP_TABLE16:
if (!NoShowRawInsn)
- DumpBytes(ArrayRef<uint8_t>(bytes, 2));
+ dumpBytes(ArrayRef<uint8_t>(bytes, 2), outs());
Value = bytes[1] << 8 | bytes[0];
outs() << "\t.short " << format("%5u", Value & 0xffff)
<< "\t@ KIND_JUMP_TABLE16\n";
@@ -268,7 +264,7 @@ static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length,
case MachO::DICE_KIND_JUMP_TABLE32:
case MachO::DICE_KIND_ABS_JUMP_TABLE32:
if (!NoShowRawInsn)
- DumpBytes(ArrayRef<uint8_t>(bytes, 4));
+ dumpBytes(ArrayRef<uint8_t>(bytes, 4), outs());
Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
outs() << "\t.long " << Value;
if (Kind == MachO::DICE_KIND_JUMP_TABLE32)
@@ -281,8 +277,7 @@ static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length,
return Size;
}
-static void getSectionsAndSymbols(const MachO::mach_header Header,
- MachOObjectFile *MachOObj,
+static void getSectionsAndSymbols(MachOObjectFile *MachOObj,
std::vector<SectionRef> &Sections,
std::vector<SymbolRef> &Symbols,
SmallVectorImpl<uint64_t> &FoundFns,
@@ -300,10 +295,8 @@ static void getSectionsAndSymbols(const MachO::mach_header Header,
Sections.push_back(Section);
}
- MachOObjectFile::LoadCommandInfo Command =
- MachOObj->getFirstLoadCommandInfo();
bool BaseSegmentAddressSet = false;
- for (unsigned i = 0;; ++i) {
+ for (const auto &Command : MachOObj->load_commands()) {
if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) {
// We found a function starts segment, parse the addresses for later
// consumption.
@@ -319,11 +312,6 @@ static void getSectionsAndSymbols(const MachO::mach_header Header,
BaseSegmentAddress = SLC.vmaddr;
}
}
-
- if (i == Header.ncmds - 1)
- break;
- else
- Command = MachOObj->getNextLoadCommandInfo(Command);
}
}
@@ -386,9 +374,7 @@ static void PrintIndirectSymbolTable(MachOObjectFile *O, bool verbose,
}
static void PrintIndirectSymbols(MachOObjectFile *O, bool verbose) {
- uint32_t LoadCommandCount = O->getHeader().ncmds;
- MachOObjectFile::LoadCommandInfo Load = O->getFirstLoadCommandInfo();
- for (unsigned I = 0;; ++I) {
+ for (const auto &Load : O->load_commands()) {
if (Load.C.cmd == MachO::LC_SEGMENT_64) {
MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load);
for (unsigned J = 0; J < Seg.nsects; ++J) {
@@ -446,10 +432,6 @@ static void PrintIndirectSymbols(MachOObjectFile *O, bool verbose) {
}
}
}
- if (I == LoadCommandCount - 1)
- break;
- else
- Load = O->getNextLoadCommandInfo(Load);
}
}
@@ -553,9 +535,8 @@ static void PrintLinkOptHints(MachOObjectFile *O) {
}
static void PrintDylibs(MachOObjectFile *O, bool JustId) {
- uint32_t LoadCommandCount = O->getHeader().ncmds;
- MachOObjectFile::LoadCommandInfo Load = O->getFirstLoadCommandInfo();
- for (unsigned I = 0;; ++I) {
+ unsigned Index = 0;
+ for (const auto &Load : O->load_commands()) {
if ((JustId && Load.C.cmd == MachO::LC_ID_DYLIB) ||
(!JustId && (Load.C.cmd == MachO::LC_ID_DYLIB ||
Load.C.cmd == MachO::LC_LOAD_DYLIB ||
@@ -595,13 +576,9 @@ static void PrintDylibs(MachOObjectFile *O, bool JustId) {
outs() << "LC_LOAD_UPWARD_DYLIB ";
else
outs() << "LC_??? ";
- outs() << "command " << I << "\n";
+ outs() << "command " << Index++ << "\n";
}
}
- if (I == LoadCommandCount - 1)
- break;
- else
- Load = O->getNextLoadCommandInfo(Load);
}
}
@@ -2132,9 +2109,7 @@ static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
// it returns a pointer to that string. Else it returns nullptr.
static const char *GuessCstringPointer(uint64_t ReferenceValue,
struct DisassembleInfo *info) {
- uint32_t LoadCommandCount = info->O->getHeader().ncmds;
- MachOObjectFile::LoadCommandInfo Load = info->O->getFirstLoadCommandInfo();
- for (unsigned I = 0;; ++I) {
+ for (const auto &Load : info->O->load_commands()) {
if (Load.C.cmd == MachO::LC_SEGMENT_64) {
MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
for (unsigned J = 0; J < Seg.nsects; ++J) {
@@ -2178,10 +2153,6 @@ static const char *GuessCstringPointer(uint64_t ReferenceValue,
}
}
}
- if (I == LoadCommandCount - 1)
- break;
- else
- Load = info->O->getNextLoadCommandInfo(Load);
}
return nullptr;
}
@@ -2192,11 +2163,9 @@ static const char *GuessCstringPointer(uint64_t ReferenceValue,
// symbol name being referenced by the stub or pointer.
static const char *GuessIndirectSymbol(uint64_t ReferenceValue,
struct DisassembleInfo *info) {
- uint32_t LoadCommandCount = info->O->getHeader().ncmds;
- MachOObjectFile::LoadCommandInfo Load = info->O->getFirstLoadCommandInfo();
MachO::dysymtab_command Dysymtab = info->O->getDysymtabLoadCommand();
MachO::symtab_command Symtab = info->O->getSymtabLoadCommand();
- for (unsigned I = 0;; ++I) {
+ for (const auto &Load : info->O->load_commands()) {
if (Load.C.cmd == MachO::LC_SEGMENT_64) {
MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
for (unsigned J = 0; J < Seg.nsects; ++J) {
@@ -2266,10 +2235,6 @@ static const char *GuessIndirectSymbol(uint64_t ReferenceValue,
}
}
}
- if (I == LoadCommandCount - 1)
- break;
- else
- Load = info->O->getNextLoadCommandInfo(Load);
}
return nullptr;
}
@@ -2356,9 +2321,7 @@ static uint64_t GuessPointerPointer(uint64_t ReferenceValue,
selref = false;
msgref = false;
cfstring = false;
- uint32_t LoadCommandCount = info->O->getHeader().ncmds;
- MachOObjectFile::LoadCommandInfo Load = info->O->getFirstLoadCommandInfo();
- for (unsigned I = 0;; ++I) {
+ for (const auto &Load : info->O->load_commands()) {
if (Load.C.cmd == MachO::LC_SEGMENT_64) {
MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
for (unsigned J = 0; J < Seg.nsects; ++J) {
@@ -2403,10 +2366,6 @@ static uint64_t GuessPointerPointer(uint64_t ReferenceValue,
}
}
// TODO: Look for LC_SEGMENT for 32-bit Mach-O files.
- if (I == LoadCommandCount - 1)
- break;
- else
- Load = info->O->getNextLoadCommandInfo(Load);
}
return 0;
}
@@ -6075,7 +6034,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
SmallVector<uint64_t, 8> FoundFns;
uint64_t BaseSegmentAddress;
- getSectionsAndSymbols(Header, MachOOF, Sections, Symbols, FoundFns,
+ getSectionsAndSymbols(MachOOF, Sections, Symbols, FoundFns,
BaseSegmentAddress);
// Sort the symbols by address, just in case they didn't come in that way.
@@ -6313,7 +6272,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
DebugOut, Annotations);
if (gotInst) {
if (!NoShowRawInsn) {
- DumpBytes(ArrayRef<uint8_t>(Bytes.data() + Index, Size));
+ dumpBytes(ArrayRef<uint8_t>(Bytes.data() + Index, Size), outs());
}
formatted_raw_ostream FormattedOS(outs());
Annotations.flush();
@@ -6378,7 +6337,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
}
if (!NoShowRawInsn) {
outs() << "\t";
- DumpBytes(ArrayRef<uint8_t>(Bytes.data() + Index, InstSize));
+ dumpBytes(ArrayRef<uint8_t>(Bytes.data() + Index, InstSize), outs());
}
IP->printInst(&Inst, outs(), "", *STI);
outs() << "\n";
@@ -8367,15 +8326,12 @@ static void PrintLinkEditDataCommand(MachO::linkedit_data_command ld,
outs() << "\n";
}
-static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t ncmds,
- uint32_t filetype, uint32_t cputype,
- bool verbose) {
- if (ncmds == 0)
- return;
+static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t filetype,
+ uint32_t cputype, bool verbose) {
StringRef Buf = Obj->getData();
- MachOObjectFile::LoadCommandInfo Command = Obj->getFirstLoadCommandInfo();
- for (unsigned i = 0;; ++i) {
- outs() << "Load command " << i << "\n";
+ unsigned Index = 0;
+ for (const auto &Command : Obj->load_commands()) {
+ outs() << "Load command " << Index++ << "\n";
if (Command.C.cmd == MachO::LC_SEGMENT) {
MachO::segment_command SLC = Obj->getSegmentLoadCommand(Command);
const char *sg_segname = SLC.segname;
@@ -8494,14 +8450,10 @@ static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t ncmds,
// TODO: get and print the raw bytes of the load command.
}
// TODO: print all the other kinds of load commands.
- if (i == ncmds - 1)
- break;
- else
- Command = Obj->getNextLoadCommandInfo(Command);
}
}
-static void getAndPrintMachHeader(const MachOObjectFile *Obj, uint32_t &ncmds,
+static void getAndPrintMachHeader(const MachOObjectFile *Obj,
uint32_t &filetype, uint32_t &cputype,
bool verbose) {
if (Obj->is64Bit()) {
@@ -8509,7 +8461,6 @@ static void getAndPrintMachHeader(const MachOObjectFile *Obj, uint32_t &ncmds,
H_64 = Obj->getHeader64();
PrintMachHeader(H_64.magic, H_64.cputype, H_64.cpusubtype, H_64.filetype,
H_64.ncmds, H_64.sizeofcmds, H_64.flags, verbose);
- ncmds = H_64.ncmds;
filetype = H_64.filetype;
cputype = H_64.cputype;
} else {
@@ -8517,7 +8468,6 @@ static void getAndPrintMachHeader(const MachOObjectFile *Obj, uint32_t &ncmds,
H = Obj->getHeader();
PrintMachHeader(H.magic, H.cputype, H.cpusubtype, H.filetype, H.ncmds,
H.sizeofcmds, H.flags, verbose);
- ncmds = H.ncmds;
filetype = H.filetype;
cputype = H.cputype;
}
@@ -8525,11 +8475,10 @@ static void getAndPrintMachHeader(const MachOObjectFile *Obj, uint32_t &ncmds,
void llvm::printMachOFileHeader(const object::ObjectFile *Obj) {
const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj);
- uint32_t ncmds = 0;
uint32_t filetype = 0;
uint32_t cputype = 0;
- getAndPrintMachHeader(file, ncmds, filetype, cputype, !NonVerbose);
- PrintLoadCommands(file, ncmds, filetype, cputype, !NonVerbose);
+ getAndPrintMachHeader(file, filetype, cputype, !NonVerbose);
+ PrintLoadCommands(file, filetype, cputype, !NonVerbose);
}
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp b/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp
index e442ac050fce..1152a154b4db 100644
--- a/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp
+++ b/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp
@@ -32,12 +32,14 @@
#include "llvm/MC/MCRelocationInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Object/Archive.h"
+#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Object/COFF.h"
#include "llvm/Object/MachO.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/Errc.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/GraphWriter.h"
@@ -147,6 +149,10 @@ static cl::alias
PrivateHeadersShort("p", cl::desc("Alias for --private-headers"),
cl::aliasopt(PrivateHeaders));
+cl::opt<bool>
+ llvm::PrintImmHex("print-imm-hex",
+ cl::desc("Use hex format for immediate values"));
+
static StringRef ToolName;
static int ReturnValue = EXIT_SUCCESS;
@@ -160,6 +166,12 @@ bool llvm::error(std::error_code EC) {
return true;
}
+static void report_error(StringRef File, std::error_code EC) {
+ assert(EC);
+ errs() << ToolName << ": '" << File << "': " << EC.message() << ".\n";
+ ReturnValue = EXIT_FAILURE;
+}
+
static const Target *getTarget(const ObjectFile *Obj = nullptr) {
// Figure out the target triple.
llvm::Triple TheTriple("unknown-unknown-unknown");
@@ -194,19 +206,6 @@ static const Target *getTarget(const ObjectFile *Obj = nullptr) {
return TheTarget;
}
-void llvm::DumpBytes(ArrayRef<uint8_t> bytes) {
- static const char hex_rep[] = "0123456789abcdef";
- SmallString<64> output;
-
- for (char i: bytes) {
- output.push_back(hex_rep[(i & 0xF0) >> 4]);
- output.push_back(hex_rep[i & 0xF]);
- output.push_back(' ');
- }
-
- outs() << output.c_str();
-}
-
bool llvm::RelocAddressLess(RelocationRef a, RelocationRef b) {
uint64_t a_addr, b_addr;
if (error(a.getOffset(a_addr))) return false;
@@ -214,6 +213,474 @@ bool llvm::RelocAddressLess(RelocationRef a, RelocationRef b) {
return a_addr < b_addr;
}
+namespace {
+class PrettyPrinter {
+public:
+ virtual ~PrettyPrinter(){}
+ virtual void printInst(MCInstPrinter &IP, const MCInst *MI,
+ ArrayRef<uint8_t> Bytes, uint64_t Address,
+ raw_ostream &OS, StringRef Annot,
+ MCSubtargetInfo const &STI) {
+ outs() << format("%8" PRIx64 ":", Address);
+ if (!NoShowRawInsn) {
+ outs() << "\t";
+ dumpBytes(Bytes, outs());
+ }
+ IP.printInst(MI, outs(), "", STI);
+ }
+};
+PrettyPrinter PrettyPrinterInst;
+class HexagonPrettyPrinter : public PrettyPrinter {
+public:
+ void printLead(ArrayRef<uint8_t> Bytes, uint64_t Address,
+ raw_ostream &OS) {
+ uint32_t opcode =
+ (Bytes[3] << 24) | (Bytes[2] << 16) | (Bytes[1] << 8) | Bytes[0];
+ OS << format("%8" PRIx64 ":", Address);
+ if (!NoShowRawInsn) {
+ OS << "\t";
+ dumpBytes(Bytes.slice(0, 4), OS);
+ OS << format("%08" PRIx32, opcode);
+ }
+ }
+ void printInst(MCInstPrinter &IP, const MCInst *MI,
+ ArrayRef<uint8_t> Bytes, uint64_t Address,
+ raw_ostream &OS, StringRef Annot,
+ MCSubtargetInfo const &STI) override {
+ std::string Buffer;
+ {
+ raw_string_ostream TempStream(Buffer);
+ IP.printInst(MI, TempStream, "", STI);
+ }
+ StringRef Contents(Buffer);
+ // Split off bundle attributes
+ auto PacketBundle = Contents.rsplit('\n');
+ // Split off first instruction from the rest
+ auto HeadTail = PacketBundle.first.split('\n');
+ auto Preamble = " { ";
+ auto Separator = "";
+ while(!HeadTail.first.empty()) {
+ OS << Separator;
+ Separator = "\n";
+ printLead(Bytes, Address, OS);
+ OS << Preamble;
+ Preamble = " ";
+ StringRef Inst;
+ auto Duplex = HeadTail.first.split('\v');
+ if(!Duplex.second.empty()){
+ OS << Duplex.first;
+ OS << "; ";
+ Inst = Duplex.second;
+ }
+ else
+ Inst = HeadTail.first;
+ OS << Inst;
+ Bytes = Bytes.slice(4);
+ Address += 4;
+ HeadTail = HeadTail.second.split('\n');
+ }
+ OS << " } " << PacketBundle.second;
+ }
+};
+HexagonPrettyPrinter HexagonPrettyPrinterInst;
+PrettyPrinter &selectPrettyPrinter(Triple const &Triple) {
+ switch(Triple.getArch()) {
+ default:
+ return PrettyPrinterInst;
+ case Triple::hexagon:
+ return HexagonPrettyPrinterInst;
+ }
+}
+}
+
+template <class ELFT>
+static const typename ELFObjectFile<ELFT>::Elf_Rel *
+getRel(const ELFFile<ELFT> &EF, DataRefImpl Rel) {
+ typedef typename ELFObjectFile<ELFT>::Elf_Rel Elf_Rel;
+ return EF.template getEntry<Elf_Rel>(Rel.d.a, Rel.d.b);
+}
+
+template <class ELFT>
+static const typename ELFObjectFile<ELFT>::Elf_Rela *
+getRela(const ELFFile<ELFT> &EF, DataRefImpl Rela) {
+ typedef typename ELFObjectFile<ELFT>::Elf_Rela Elf_Rela;
+ return EF.template getEntry<Elf_Rela>(Rela.d.a, Rela.d.b);
+}
+
+template <class ELFT>
+static std::error_code getRelocationValueString(const ELFObjectFile<ELFT> *Obj,
+ DataRefImpl Rel,
+ SmallVectorImpl<char> &Result) {
+ typedef typename ELFObjectFile<ELFT>::Elf_Sym Elf_Sym;
+ typedef typename ELFObjectFile<ELFT>::Elf_Shdr Elf_Shdr;
+ const ELFFile<ELFT> &EF = *Obj->getELFFile();
+
+ const Elf_Shdr *sec = EF.getSection(Rel.d.a);
+ uint8_t type;
+ StringRef res;
+ int64_t addend = 0;
+ uint16_t symbol_index = 0;
+ switch (sec->sh_type) {
+ default:
+ return object_error::parse_failed;
+ case ELF::SHT_REL: {
+ type = getRel(EF, Rel)->getType(EF.isMips64EL());
+ symbol_index = getRel(EF, Rel)->getSymbol(EF.isMips64EL());
+ // TODO: Read implicit addend from section data.
+ break;
+ }
+ case ELF::SHT_RELA: {
+ type = getRela(EF, Rel)->getType(EF.isMips64EL());
+ symbol_index = getRela(EF, Rel)->getSymbol(EF.isMips64EL());
+ addend = getRela(EF, Rel)->r_addend;
+ break;
+ }
+ }
+ const Elf_Sym *symb =
+ EF.template getEntry<Elf_Sym>(sec->sh_link, symbol_index);
+ StringRef Target;
+ const Elf_Shdr *SymSec = EF.getSection(symb);
+ if (symb->getType() == ELF::STT_SECTION) {
+ ErrorOr<StringRef> SecName = EF.getSectionName(SymSec);
+ if (std::error_code EC = SecName.getError())
+ return EC;
+ Target = *SecName;
+ } else {
+ ErrorOr<StringRef> SymName =
+ EF.getSymbolName(EF.getSection(sec->sh_link), symb);
+ if (!SymName)
+ return SymName.getError();
+ Target = *SymName;
+ }
+ switch (EF.getHeader()->e_machine) {
+ case ELF::EM_X86_64:
+ switch (type) {
+ case ELF::R_X86_64_PC8:
+ case ELF::R_X86_64_PC16:
+ case ELF::R_X86_64_PC32: {
+ std::string fmtbuf;
+ raw_string_ostream fmt(fmtbuf);
+ fmt << Target << (addend < 0 ? "" : "+") << addend << "-P";
+ fmt.flush();
+ Result.append(fmtbuf.begin(), fmtbuf.end());
+ } break;
+ case ELF::R_X86_64_8:
+ case ELF::R_X86_64_16:
+ case ELF::R_X86_64_32:
+ case ELF::R_X86_64_32S:
+ case ELF::R_X86_64_64: {
+ std::string fmtbuf;
+ raw_string_ostream fmt(fmtbuf);
+ fmt << Target << (addend < 0 ? "" : "+") << addend;
+ fmt.flush();
+ Result.append(fmtbuf.begin(), fmtbuf.end());
+ } break;
+ default:
+ res = "Unknown";
+ }
+ break;
+ case ELF::EM_AARCH64: {
+ std::string fmtbuf;
+ raw_string_ostream fmt(fmtbuf);
+ fmt << Target;
+ if (addend != 0)
+ fmt << (addend < 0 ? "" : "+") << addend;
+ fmt.flush();
+ Result.append(fmtbuf.begin(), fmtbuf.end());
+ break;
+ }
+ case ELF::EM_386:
+ case ELF::EM_ARM:
+ case ELF::EM_HEXAGON:
+ case ELF::EM_MIPS:
+ res = Target;
+ break;
+ default:
+ res = "Unknown";
+ }
+ if (Result.empty())
+ Result.append(res.begin(), res.end());
+ return std::error_code();
+}
+
+static std::error_code getRelocationValueString(const ELFObjectFileBase *Obj,
+ const RelocationRef &RelRef,
+ SmallVectorImpl<char> &Result) {
+ DataRefImpl Rel = RelRef.getRawDataRefImpl();
+ if (auto *ELF32LE = dyn_cast<ELF32LEObjectFile>(Obj))
+ return getRelocationValueString(ELF32LE, Rel, Result);
+ if (auto *ELF64LE = dyn_cast<ELF64LEObjectFile>(Obj))
+ return getRelocationValueString(ELF64LE, Rel, Result);
+ if (auto *ELF32BE = dyn_cast<ELF32BEObjectFile>(Obj))
+ return getRelocationValueString(ELF32BE, Rel, Result);
+ auto *ELF64BE = cast<ELF64BEObjectFile>(Obj);
+ return getRelocationValueString(ELF64BE, Rel, Result);
+}
+
+static std::error_code getRelocationValueString(const COFFObjectFile *Obj,
+ const RelocationRef &Rel,
+ SmallVectorImpl<char> &Result) {
+ symbol_iterator SymI = Rel.getSymbol();
+ StringRef SymName;
+ if (std::error_code EC = SymI->getName(SymName))
+ return EC;
+ Result.append(SymName.begin(), SymName.end());
+ return std::error_code();
+}
+
+static void printRelocationTargetName(const MachOObjectFile *O,
+ const MachO::any_relocation_info &RE,
+ raw_string_ostream &fmt) {
+ bool IsScattered = O->isRelocationScattered(RE);
+
+ // Target of a scattered relocation is an address. In the interest of
+ // generating pretty output, scan through the symbol table looking for a
+ // symbol that aligns with that address. If we find one, print it.
+ // Otherwise, we just print the hex address of the target.
+ if (IsScattered) {
+ uint32_t Val = O->getPlainRelocationSymbolNum(RE);
+
+ for (const SymbolRef &Symbol : O->symbols()) {
+ std::error_code ec;
+ uint64_t Addr;
+ StringRef Name;
+
+ if ((ec = Symbol.getAddress(Addr)))
+ report_fatal_error(ec.message());
+ if (Addr != Val)
+ continue;
+ if ((ec = Symbol.getName(Name)))
+ report_fatal_error(ec.message());
+ fmt << Name;
+ return;
+ }
+
+ // If we couldn't find a symbol that this relocation refers to, try
+ // to find a section beginning instead.
+ for (const SectionRef &Section : O->sections()) {
+ std::error_code ec;
+
+ StringRef Name;
+ uint64_t Addr = Section.getAddress();
+ if (Addr != Val)
+ continue;
+ if ((ec = Section.getName(Name)))
+ report_fatal_error(ec.message());
+ fmt << Name;
+ return;
+ }
+
+ fmt << format("0x%x", Val);
+ return;
+ }
+
+ StringRef S;
+ bool isExtern = O->getPlainRelocationExternal(RE);
+ uint64_t Val = O->getPlainRelocationSymbolNum(RE);
+
+ if (isExtern) {
+ symbol_iterator SI = O->symbol_begin();
+ advance(SI, Val);
+ SI->getName(S);
+ } else {
+ section_iterator SI = O->section_begin();
+ // Adjust for the fact that sections are 1-indexed.
+ advance(SI, Val - 1);
+ SI->getName(S);
+ }
+
+ fmt << S;
+}
+
+static std::error_code getRelocationValueString(const MachOObjectFile *Obj,
+ const RelocationRef &RelRef,
+ SmallVectorImpl<char> &Result) {
+ DataRefImpl Rel = RelRef.getRawDataRefImpl();
+ MachO::any_relocation_info RE = Obj->getRelocation(Rel);
+
+ unsigned Arch = Obj->getArch();
+
+ std::string fmtbuf;
+ raw_string_ostream fmt(fmtbuf);
+ unsigned Type = Obj->getAnyRelocationType(RE);
+ bool IsPCRel = Obj->getAnyRelocationPCRel(RE);
+
+ // Determine any addends that should be displayed with the relocation.
+ // These require decoding the relocation type, which is triple-specific.
+
+ // X86_64 has entirely custom relocation types.
+ if (Arch == Triple::x86_64) {
+ bool isPCRel = Obj->getAnyRelocationPCRel(RE);
+
+ switch (Type) {
+ case MachO::X86_64_RELOC_GOT_LOAD:
+ case MachO::X86_64_RELOC_GOT: {
+ printRelocationTargetName(Obj, RE, fmt);
+ fmt << "@GOT";
+ if (isPCRel)
+ fmt << "PCREL";
+ break;
+ }
+ case MachO::X86_64_RELOC_SUBTRACTOR: {
+ DataRefImpl RelNext = Rel;
+ Obj->moveRelocationNext(RelNext);
+ MachO::any_relocation_info RENext = Obj->getRelocation(RelNext);
+
+ // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
+ // X86_64_RELOC_UNSIGNED.
+ // NOTE: Scattered relocations don't exist on x86_64.
+ unsigned RType = Obj->getAnyRelocationType(RENext);
+ if (RType != MachO::X86_64_RELOC_UNSIGNED)
+ report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
+ "X86_64_RELOC_SUBTRACTOR.");
+
+ // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
+ // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
+ printRelocationTargetName(Obj, RENext, fmt);
+ fmt << "-";
+ printRelocationTargetName(Obj, RE, fmt);
+ break;
+ }
+ case MachO::X86_64_RELOC_TLV:
+ printRelocationTargetName(Obj, RE, fmt);
+ fmt << "@TLV";
+ if (isPCRel)
+ fmt << "P";
+ break;
+ case MachO::X86_64_RELOC_SIGNED_1:
+ printRelocationTargetName(Obj, RE, fmt);
+ fmt << "-1";
+ break;
+ case MachO::X86_64_RELOC_SIGNED_2:
+ printRelocationTargetName(Obj, RE, fmt);
+ fmt << "-2";
+ break;
+ case MachO::X86_64_RELOC_SIGNED_4:
+ printRelocationTargetName(Obj, RE, fmt);
+ fmt << "-4";
+ break;
+ default:
+ printRelocationTargetName(Obj, RE, fmt);
+ break;
+ }
+ // X86 and ARM share some relocation types in common.
+ } else if (Arch == Triple::x86 || Arch == Triple::arm ||
+ Arch == Triple::ppc) {
+ // Generic relocation types...
+ switch (Type) {
+ case MachO::GENERIC_RELOC_PAIR: // prints no info
+ return std::error_code();
+ case MachO::GENERIC_RELOC_SECTDIFF: {
+ DataRefImpl RelNext = Rel;
+ Obj->moveRelocationNext(RelNext);
+ MachO::any_relocation_info RENext = Obj->getRelocation(RelNext);
+
+ // X86 sect diff's must be followed by a relocation of type
+ // GENERIC_RELOC_PAIR.
+ unsigned RType = Obj->getAnyRelocationType(RENext);
+
+ if (RType != MachO::GENERIC_RELOC_PAIR)
+ report_fatal_error("Expected GENERIC_RELOC_PAIR after "
+ "GENERIC_RELOC_SECTDIFF.");
+
+ printRelocationTargetName(Obj, RE, fmt);
+ fmt << "-";
+ printRelocationTargetName(Obj, RENext, fmt);
+ break;
+ }
+ }
+
+ if (Arch == Triple::x86 || Arch == Triple::ppc) {
+ switch (Type) {
+ case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
+ DataRefImpl RelNext = Rel;
+ Obj->moveRelocationNext(RelNext);
+ MachO::any_relocation_info RENext = Obj->getRelocation(RelNext);
+
+ // X86 sect diff's must be followed by a relocation of type
+ // GENERIC_RELOC_PAIR.
+ unsigned RType = Obj->getAnyRelocationType(RENext);
+ if (RType != MachO::GENERIC_RELOC_PAIR)
+ report_fatal_error("Expected GENERIC_RELOC_PAIR after "
+ "GENERIC_RELOC_LOCAL_SECTDIFF.");
+
+ printRelocationTargetName(Obj, RE, fmt);
+ fmt << "-";
+ printRelocationTargetName(Obj, RENext, fmt);
+ break;
+ }
+ case MachO::GENERIC_RELOC_TLV: {
+ printRelocationTargetName(Obj, RE, fmt);
+ fmt << "@TLV";
+ if (IsPCRel)
+ fmt << "P";
+ break;
+ }
+ default:
+ printRelocationTargetName(Obj, RE, fmt);
+ }
+ } else { // ARM-specific relocations
+ switch (Type) {
+ case MachO::ARM_RELOC_HALF:
+ case MachO::ARM_RELOC_HALF_SECTDIFF: {
+ // Half relocations steal a bit from the length field to encode
+ // whether this is an upper16 or a lower16 relocation.
+ bool isUpper = Obj->getAnyRelocationLength(RE) >> 1;
+
+ if (isUpper)
+ fmt << ":upper16:(";
+ else
+ fmt << ":lower16:(";
+ printRelocationTargetName(Obj, RE, fmt);
+
+ DataRefImpl RelNext = Rel;
+ Obj->moveRelocationNext(RelNext);
+ MachO::any_relocation_info RENext = Obj->getRelocation(RelNext);
+
+ // ARM half relocs must be followed by a relocation of type
+ // ARM_RELOC_PAIR.
+ unsigned RType = Obj->getAnyRelocationType(RENext);
+ if (RType != MachO::ARM_RELOC_PAIR)
+ report_fatal_error("Expected ARM_RELOC_PAIR after "
+ "ARM_RELOC_HALF");
+
+ // NOTE: The half of the target virtual address is stashed in the
+ // address field of the secondary relocation, but we can't reverse
+ // engineer the constant offset from it without decoding the movw/movt
+ // instruction to find the other half in its immediate field.
+
+ // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
+ // symbol/section pointer of the follow-on relocation.
+ if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
+ fmt << "-";
+ printRelocationTargetName(Obj, RENext, fmt);
+ }
+
+ fmt << ")";
+ break;
+ }
+ default: { printRelocationTargetName(Obj, RE, fmt); }
+ }
+ }
+ } else
+ printRelocationTargetName(Obj, RE, fmt);
+
+ fmt.flush();
+ Result.append(fmtbuf.begin(), fmtbuf.end());
+ return std::error_code();
+}
+
+static std::error_code getRelocationValueString(const RelocationRef &Rel,
+ SmallVectorImpl<char> &Result) {
+ const ObjectFile *Obj = Rel.getObjectFile();
+ if (auto *ELF = dyn_cast<ELFObjectFileBase>(Obj))
+ return getRelocationValueString(ELF, Rel, Result);
+ if (auto *COFF = dyn_cast<COFFObjectFile>(Obj))
+ return getRelocationValueString(COFF, Rel, Result);
+ auto *MachO = cast<MachOObjectFile>(Obj);
+ return getRelocationValueString(MachO, Rel, Result);
+}
+
static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
const Target *TheTarget = getTarget(Obj);
// getTarget() will have already issued a diagnostic if necessary, so
@@ -280,6 +747,8 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
<< '\n';
return;
}
+ IP->setPrintImmHex(PrintImmHex);
+ PrettyPrinter &PIP = selectPrettyPrinter(Triple(TripleName));
StringRef Fmt = Obj->getBytesInAddress() > 4 ? "\t\t%016" PRIx64 ": " :
"\t\t\t%08" PRIx64 ": ";
@@ -352,11 +821,9 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
outs() << SegmentName << ",";
outs() << name << ':';
- // If the section has no symbols just insert a dummy one and disassemble
- // the whole section.
- if (Symbols.empty())
- Symbols.push_back(std::make_pair(0, name));
-
+ // If the section has no symbol at the start, just insert a dummy one.
+ if (Symbols.empty() || Symbols[0].first != 0)
+ Symbols.insert(Symbols.begin(), std::make_pair(0, name));
SmallString<40> Comments;
raw_svector_ostream CommentStream(Comments);
@@ -396,12 +863,9 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
if (DisAsm->getInstruction(Inst, Size, Bytes.slice(Index),
SectionAddr + Index, DebugOut,
CommentStream)) {
- outs() << format("%8" PRIx64 ":", SectionAddr + Index);
- if (!NoShowRawInsn) {
- outs() << "\t";
- DumpBytes(ArrayRef<uint8_t>(Bytes.data() + Index, Size));
- }
- IP->printInst(&Inst, outs(), "", *STI);
+ PIP.printInst(*IP, &Inst,
+ Bytes.slice(Index, Size),
+ SectionAddr + Index, outs(), "", *STI);
outs() << CommentStream.str();
Comments.clear();
outs() << "\n";
@@ -426,8 +890,8 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
// Stop when rel_cur's address is past the current instruction.
if (addr >= Index + Size) break;
if (error(rel_cur->getTypeName(name))) goto skip_print_rel;
- if (error(rel_cur->getValueString(val))) goto skip_print_rel;
-
+ if (error(getRelocationValueString(*rel_cur, val)))
+ goto skip_print_rel;
outs() << format(Fmt.data(), SectionAddr + addr) << name
<< "\t" << val << "\n";
@@ -467,7 +931,7 @@ void llvm::PrintRelocations(const ObjectFile *Obj) {
continue;
if (error(Reloc.getOffset(address)))
continue;
- if (error(Reloc.getValueString(valuestr)))
+ if (error(getRelocationValueString(Reloc, valuestr)))
continue;
outs() << format(Fmt.data(), address) << " " << relocname << " "
<< valuestr << "\n";
@@ -608,22 +1072,23 @@ void llvm::PrintSymbolTable(const ObjectFile *o) {
return;
}
for (const SymbolRef &Symbol : o->symbols()) {
- StringRef Name;
uint64_t Address;
SymbolRef::Type Type;
- uint64_t Size;
uint32_t Flags = Symbol.getFlags();
section_iterator Section = o->section_end();
- if (error(Symbol.getName(Name)))
- continue;
if (error(Symbol.getAddress(Address)))
continue;
if (error(Symbol.getType(Type)))
continue;
- if (error(Symbol.getSize(Size)))
- continue;
+ uint64_t Size = Symbol.getSize();
if (error(Symbol.getSection(Section)))
continue;
+ StringRef Name;
+ if (Type == SymbolRef::ST_Debug && Section != o->section_end()) {
+ Section->getName(Name);
+ } else if (error(Symbol.getName(Name))) {
+ continue;
+ }
bool Global = Flags & SymbolRef::SF_Global;
bool Weak = Flags & SymbolRef::SF_Weak;
@@ -632,9 +1097,7 @@ void llvm::PrintSymbolTable(const ObjectFile *o) {
bool Hidden = Flags & SymbolRef::SF_Hidden;
if (Common) {
- uint32_t Alignment;
- if (error(Symbol.getAlignment(Alignment)))
- Alignment = 0;
+ uint32_t Alignment = Symbol.getAlignment();
Address = Size;
Size = Alignment;
}
@@ -812,15 +1275,13 @@ static void DumpArchive(const Archive *a) {
if (std::error_code EC = ChildOrErr.getError()) {
// Ignore non-object files.
if (EC != object_error::invalid_file_type)
- errs() << ToolName << ": '" << a->getFileName() << "': " << EC.message()
- << ".\n";
+ report_error(a->getFileName(), EC);
continue;
}
if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get()))
DumpObject(o);
else
- errs() << ToolName << ": '" << a->getFileName() << "': "
- << "Unrecognized file type.\n";
+ report_error(a->getFileName(), object_error::invalid_file_type);
}
}
@@ -828,7 +1289,7 @@ static void DumpArchive(const Archive *a) {
static void DumpInput(StringRef file) {
// If file isn't stdin, check that it exists.
if (file != "-" && !sys::fs::exists(file)) {
- errs() << ToolName << ": '" << file << "': " << "No such file\n";
+ report_error(file, errc::no_such_file_or_directory);
return;
}
@@ -843,7 +1304,7 @@ static void DumpInput(StringRef file) {
// Attempt to open the binary.
ErrorOr<OwningBinary<Binary>> BinaryOrErr = createBinary(file);
if (std::error_code EC = BinaryOrErr.getError()) {
- errs() << ToolName << ": '" << file << "': " << EC.message() << ".\n";
+ report_error(file, EC);
return;
}
Binary &Binary = *BinaryOrErr.get().getBinary();
@@ -853,7 +1314,7 @@ static void DumpInput(StringRef file) {
else if (ObjectFile *o = dyn_cast<ObjectFile>(&Binary))
DumpObject(o);
else
- errs() << ToolName << ": '" << file << "': " << "Unrecognized file type.\n";
+ report_error(file, object_error::invalid_file_type);
}
int main(int argc, char **argv) {
diff --git a/contrib/llvm/tools/llvm-objdump/llvm-objdump.h b/contrib/llvm/tools/llvm-objdump/llvm-objdump.h
index bde72e004a1f..b4d34f4033bc 100644
--- a/contrib/llvm/tools/llvm-objdump/llvm-objdump.h
+++ b/contrib/llvm/tools/llvm-objdump/llvm-objdump.h
@@ -51,11 +51,11 @@ extern cl::opt<bool> SectionHeaders;
extern cl::opt<bool> SectionContents;
extern cl::opt<bool> SymbolTable;
extern cl::opt<bool> UnwindInfo;
+extern cl::opt<bool> PrintImmHex;
// Various helper functions.
bool error(std::error_code ec);
bool RelocAddressLess(object::RelocationRef a, object::RelocationRef b);
-void DumpBytes(ArrayRef<uint8_t> bytes);
void ParseInputMachO(StringRef Filename);
void printCOFFUnwindInfo(const object::COFFObjectFile* o);
void printMachOUnwindInfo(const object::MachOObjectFile* o);