diff options
Diffstat (limited to 'llvm/tools/llvm-objdump/llvm-objdump.cpp')
-rw-r--r-- | llvm/tools/llvm-objdump/llvm-objdump.cpp | 142 |
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); |