aboutsummaryrefslogtreecommitdiff
path: root/llvm/tools/llvm-objdump/llvm-objdump.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/tools/llvm-objdump/llvm-objdump.cpp')
-rw-r--r--llvm/tools/llvm-objdump/llvm-objdump.cpp142
1 files changed, 111 insertions, 31 deletions
diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp
index 48ae92f734c7..6f6f543f2f47 100644
--- a/llvm/tools/llvm-objdump/llvm-objdump.cpp
+++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp
@@ -47,6 +47,7 @@
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCTargetOptions.h"
+#include "llvm/MC/TargetRegistry.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/COFF.h"
#include "llvm/Object/COFFImportFile.h"
@@ -71,7 +72,6 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/StringSaver.h"
-#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
@@ -297,16 +297,15 @@ void objdump::reportWarning(const Twine &Message, StringRef File) {
<< "'" << File << "': " << Message << "\n";
}
-LLVM_ATTRIBUTE_NORETURN void objdump::reportError(StringRef File,
- const Twine &Message) {
+[[noreturn]] void objdump::reportError(StringRef File, const Twine &Message) {
outs().flush();
WithColor::error(errs(), ToolName) << "'" << File << "': " << Message << "\n";
exit(1);
}
-LLVM_ATTRIBUTE_NORETURN void objdump::reportError(Error E, StringRef FileName,
- StringRef ArchiveName,
- StringRef ArchitectureName) {
+[[noreturn]] void objdump::reportError(Error E, StringRef FileName,
+ StringRef ArchiveName,
+ StringRef ArchitectureName) {
assert(E);
outs().flush();
WithColor::error(errs(), ToolName);
@@ -325,7 +324,7 @@ static void reportCmdLineWarning(const Twine &Message) {
WithColor::warning(errs(), ToolName) << Message << "\n";
}
-LLVM_ATTRIBUTE_NORETURN static void reportCmdLineError(const Twine &Message) {
+[[noreturn]] static void reportCmdLineError(const Twine &Message) {
WithColor::error(errs(), ToolName) << Message << "\n";
exit(1);
}
@@ -1286,6 +1285,10 @@ static void disassembleObject(const Target *TheTarget, const ObjectFile *Obj,
if (shouldAdjustVA(Section))
VMAAdjustment = AdjustVMA;
+ // In executable and shared objects, r_offset holds a virtual address.
+ // Subtract SectionAddr from the r_offset field of a relocation to get
+ // the section offset.
+ uint64_t RelAdjustment = Obj->isRelocatableObject() ? 0 : SectionAddr;
uint64_t Size;
uint64_t Index;
bool PrintedSection = false;
@@ -1432,7 +1435,8 @@ static void disassembleObject(const Target *TheTarget, const ObjectFile *Obj,
// For --reloc: print zero blocks patched by relocations, so that
// relocations can be shown in the dump.
if (RelCur != RelEnd)
- MaxOffset = RelCur->getOffset() - Index;
+ MaxOffset = std::min(RelCur->getOffset() - RelAdjustment - Index,
+ MaxOffset);
if (size_t N =
countSkippableZeroBytes(Bytes.slice(Index, MaxOffset))) {
@@ -1481,7 +1485,7 @@ static void disassembleObject(const Target *TheTarget, const ObjectFile *Obj,
if (!PrintTarget)
if (Optional<uint64_t> MaybeTarget =
MIA->evaluateMemoryOperandAddress(
- Inst, SectionAddr + Index, Size)) {
+ Inst, STI, SectionAddr + Index, Size)) {
Target = *MaybeTarget;
PrintTarget = true;
// Do not print real address when symbolizing.
@@ -1581,7 +1585,7 @@ static void disassembleObject(const Target *TheTarget, const ObjectFile *Obj,
if (Obj->getArch() != Triple::hexagon) {
// Print relocation for instruction and data.
while (RelCur != RelEnd) {
- uint64_t Offset = RelCur->getOffset();
+ uint64_t Offset = RelCur->getOffset() - RelAdjustment;
// If this relocation is hidden, skip it.
if (getHidden(*RelCur) || SectionAddr + Offset < StartAddress) {
++RelCur;
@@ -1770,7 +1774,9 @@ void objdump::printDynamicRelocations(const ObjectFile *Obj) {
return;
const auto *Elf = dyn_cast<ELFObjectFileBase>(Obj);
- if (!Elf || Elf->getEType() != ELF::ET_DYN) {
+ if (!Elf || !any_of(Elf->sections(), [](const ELFSectionRef Sec) {
+ return Sec.getType() == ELF::SHT_DYNAMIC;
+ })) {
reportError(Obj->getFileName(), "not a dynamic object");
return;
}
@@ -1779,7 +1785,12 @@ void objdump::printDynamicRelocations(const ObjectFile *Obj) {
if (DynRelSec.empty())
return;
- outs() << "DYNAMIC RELOCATION RECORDS\n";
+ outs() << "\nDYNAMIC RELOCATION RECORDS\n";
+ const uint32_t OffsetPadding = (Obj->getBytesInAddress() > 4 ? 16 : 8);
+ const uint32_t TypePadding = 24;
+ outs() << left_justify("OFFSET", OffsetPadding) << ' '
+ << left_justify("TYPE", TypePadding) << " VALUE\n";
+
StringRef Fmt = Obj->getBytesInAddress() > 4 ? "%016" PRIx64 : "%08" PRIx64;
for (const SectionRef &Section : DynRelSec)
for (const RelocationRef &Reloc : Section.relocations()) {
@@ -1789,8 +1800,8 @@ void objdump::printDynamicRelocations(const ObjectFile *Obj) {
Reloc.getTypeName(RelocName);
if (Error E = getRelocationValueString(Reloc, ValueStr))
reportError(std::move(E), Obj->getFileName());
- outs() << format(Fmt.data(), Address) << " " << RelocName << " "
- << ValueStr << "\n";
+ outs() << format(Fmt.data(), Address) << ' '
+ << left_justify(RelocName, TypePadding) << ' ' << ValueStr << '\n';
}
}
@@ -1922,7 +1933,8 @@ void objdump::printSymbolTable(const ObjectFile *O, StringRef ArchiveName,
if (!DumpDynamic) {
outs() << "\nSYMBOL TABLE:\n";
for (auto I = O->symbol_begin(); I != O->symbol_end(); ++I)
- printSymbol(O, *I, FileName, ArchiveName, ArchitectureName, DumpDynamic);
+ printSymbol(O, *I, {}, FileName, ArchiveName, ArchitectureName,
+ DumpDynamic);
return;
}
@@ -1935,12 +1947,21 @@ void objdump::printSymbolTable(const ObjectFile *O, StringRef ArchiveName,
}
const ELFObjectFileBase *ELF = cast<const ELFObjectFileBase>(O);
- for (auto I = ELF->getDynamicSymbolIterators().begin();
- I != ELF->getDynamicSymbolIterators().end(); ++I)
- printSymbol(O, *I, FileName, ArchiveName, ArchitectureName, DumpDynamic);
+ auto Symbols = ELF->getDynamicSymbolIterators();
+ Expected<std::vector<VersionEntry>> SymbolVersionsOrErr =
+ ELF->readDynsymVersions();
+ if (!SymbolVersionsOrErr) {
+ reportWarning(toString(SymbolVersionsOrErr.takeError()), FileName);
+ SymbolVersionsOrErr = std::vector<VersionEntry>();
+ (void)!SymbolVersionsOrErr;
+ }
+ for (auto &Sym : Symbols)
+ printSymbol(O, Sym, *SymbolVersionsOrErr, FileName, ArchiveName,
+ ArchitectureName, DumpDynamic);
}
void objdump::printSymbol(const ObjectFile *O, const SymbolRef &Symbol,
+ ArrayRef<VersionEntry> SymbolVersions,
StringRef FileName, StringRef ArchiveName,
StringRef ArchitectureName, bool DumpDynamic) {
const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(O);
@@ -2029,22 +2050,66 @@ void objdump::printSymbol(const ObjectFile *O, const SymbolRef &Symbol,
} else if (Common) {
outs() << "*COM*";
} else if (Section == O->section_end()) {
- outs() << "*UND*";
+ if (O->isXCOFF()) {
+ XCOFFSymbolRef XCOFFSym = dyn_cast<const XCOFFObjectFile>(O)->toSymbolRef(
+ Symbol.getRawDataRefImpl());
+ if (XCOFF::N_DEBUG == XCOFFSym.getSectionNumber())
+ outs() << "*DEBUG*";
+ else
+ outs() << "*UND*";
+ } else
+ outs() << "*UND*";
} else {
StringRef SegmentName = getSegmentName(MachO, *Section);
if (!SegmentName.empty())
outs() << SegmentName << ",";
StringRef SectionName = unwrapOrError(Section->getName(), FileName);
outs() << SectionName;
- }
+ if (O->isXCOFF()) {
+ Optional<SymbolRef> SymRef = getXCOFFSymbolContainingSymbolRef(
+ dyn_cast<const XCOFFObjectFile>(O), Symbol);
+ if (SymRef) {
- if (Common || O->isELF()) {
- uint64_t Val =
- Common ? Symbol.getAlignment() : ELFSymbolRef(Symbol).getSize();
- outs() << '\t' << format(Fmt, Val);
+ Expected<StringRef> NameOrErr = SymRef.getValue().getName();
+
+ if (NameOrErr) {
+ outs() << " (csect:";
+ std::string SymName(NameOrErr.get());
+
+ if (Demangle)
+ SymName = demangle(SymName);
+
+ if (SymbolDescription)
+ SymName = getXCOFFSymbolDescription(
+ createSymbolInfo(O, SymRef.getValue()), SymName);
+
+ outs() << ' ' << SymName;
+ outs() << ") ";
+ } else
+ reportWarning(toString(NameOrErr.takeError()), FileName);
+ }
+ }
}
+ if (Common)
+ outs() << '\t' << format(Fmt, static_cast<uint64_t>(Symbol.getAlignment()));
+ else if (O->isXCOFF())
+ outs() << '\t'
+ << format(Fmt, dyn_cast<const XCOFFObjectFile>(O)->getSymbolSize(
+ Symbol.getRawDataRefImpl()));
+ else if (O->isELF())
+ outs() << '\t' << format(Fmt, ELFSymbolRef(Symbol).getSize());
+
if (O->isELF()) {
+ if (!SymbolVersions.empty()) {
+ const VersionEntry &Ver =
+ SymbolVersions[Symbol.getRawDataRefImpl().d.b - 1];
+ std::string Str;
+ if (!Ver.Name.empty())
+ Str = Ver.IsVerDef ? ' ' + Ver.Name : '(' + Ver.Name + ')';
+ outs() << ' ' << left_justify(Str, 12);
+ }
+
uint8_t Other = ELFSymbolRef(Symbol).getOther();
switch (Other) {
case ELF::STV_DEFAULT:
@@ -2066,10 +2131,14 @@ void objdump::printSymbol(const ObjectFile *O, const SymbolRef &Symbol,
outs() << " .hidden";
}
+ std::string SymName(Name);
if (Demangle)
- outs() << ' ' << demangle(std::string(Name)) << '\n';
- else
- outs() << ' ' << Name << '\n';
+ SymName = demangle(SymName);
+
+ if (O->isXCOFF() && SymbolDescription)
+ SymName = getXCOFFSymbolDescription(createSymbolInfo(O, Symbol), SymName);
+
+ outs() << ' ' << SymName << '\n';
}
static void printUnwindInfo(const ObjectFile *O) {
@@ -2176,7 +2245,7 @@ static void printPrivateFileHeaders(const ObjectFile *O, bool OnlyFirst) {
return;
}
if (O->isCOFF())
- return printCOFFFileHeader(O);
+ return printCOFFFileHeader(cast<object::COFFObjectFile>(*O));
if (O->isWasm())
return printWasmFileHeader(O);
if (O->isMachO()) {
@@ -2431,6 +2500,11 @@ static void parseIntArg(const llvm::opt::InputArgList &InputArgs, int ID,
}
}
+static void invalidArgValue(const opt::Arg *A) {
+ reportCmdLineError("'" + StringRef(A->getValue()) +
+ "' is not a valid value for '" + A->getSpelling() + "'");
+}
+
static std::vector<std::string>
commaSeparatedValues(const llvm::opt::InputArgList &InputArgs, int ID) {
std::vector<std::string> Values;
@@ -2504,8 +2578,11 @@ static void parseObjdumpOptions(const llvm::opt::InputArgList &InputArgs) {
commaSeparatedValues(InputArgs, OBJDUMP_disassemble_symbols_EQ);
DisassembleZeroes = InputArgs.hasArg(OBJDUMP_disassemble_zeroes);
if (const opt::Arg *A = InputArgs.getLastArg(OBJDUMP_dwarf_EQ)) {
- DwarfDumpType =
- StringSwitch<DIDumpType>(A->getValue()).Case("frames", DIDT_DebugFrame);
+ DwarfDumpType = StringSwitch<DIDumpType>(A->getValue())
+ .Case("frames", DIDT_DebugFrame)
+ .Default(DIDT_Null);
+ if (DwarfDumpType == DIDT_Null)
+ invalidArgValue(A);
}
DynamicRelocations = InputArgs.hasArg(OBJDUMP_dynamic_reloc);
FaultMapSection = InputArgs.hasArg(OBJDUMP_fault_map_section);
@@ -2542,7 +2619,10 @@ static void parseObjdumpOptions(const llvm::opt::InputArgList &InputArgs) {
if (const opt::Arg *A = InputArgs.getLastArg(OBJDUMP_debug_vars_EQ)) {
DbgVariables = StringSwitch<DebugVarsFormat>(A->getValue())
.Case("ascii", DVASCII)
- .Case("unicode", DVUnicode);
+ .Case("unicode", DVUnicode)
+ .Default(DVInvalid);
+ if (DbgVariables == DVInvalid)
+ invalidArgValue(A);
}
parseIntArg(InputArgs, OBJDUMP_debug_vars_indent_EQ, DbgIndent);