X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=tools%2Fllvm-objdump%2Fllvm-objdump.cpp;h=81deefe651dede41a8761e79ca4d37d0db980a18;hp=365d2ff5e37ea85de5a6d847634540e66c816b76;hb=a46a5bf8ab9441304f9e9670ce8b1be93710782c;hpb=aecb4b465d4dd848ca7efb30339ef223a16f65a6 diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp index 365d2ff5e37..81deefe651d 100644 --- a/tools/llvm-objdump/llvm-objdump.cpp +++ b/tools/llvm-objdump/llvm-objdump.cpp @@ -17,9 +17,11 @@ //===----------------------------------------------------------------------===// #include "llvm-objdump.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Triple.h" +#include "llvm/CodeGen/FaultMaps.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCDisassembler.h" @@ -32,12 +34,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 +151,13 @@ static cl::alias PrivateHeadersShort("p", cl::desc("Alias for --private-headers"), cl::aliasopt(PrivateHeaders)); +cl::opt + llvm::PrintImmHex("print-imm-hex", + cl::desc("Use hex format for immediate values")); + +cl::opt PrintFaultMaps("fault-map-section", + cl::desc("Display contents of faultmap section")); + static StringRef ToolName; static int ReturnValue = EXIT_SUCCESS; @@ -160,6 +171,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,24 +211,519 @@ static const Target *getTarget(const ObjectFile *Obj = nullptr) { return TheTarget; } -void llvm::DumpBytes(StringRef bytes) { - static const char hex_rep[] = "0123456789abcdef"; - SmallString<64> output; +bool llvm::RelocAddressLess(RelocationRef a, RelocationRef b) { + return a.getOffset() < b.getOffset(); +} + +namespace { +class PrettyPrinter { +public: + virtual ~PrettyPrinter(){} + virtual void printInst(MCInstPrinter &IP, const MCInst *MI, + ArrayRef 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 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 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; + } +} +} - for (char i: bytes) { - output.push_back(hex_rep[(i & 0xF0) >> 4]); - output.push_back(hex_rep[i & 0xF]); - output.push_back(' '); +template +static std::error_code getRelocationValueString(const ELFObjectFile *Obj, + DataRefImpl Rel, + SmallVectorImpl &Result) { + typedef typename ELFObjectFile::Elf_Sym Elf_Sym; + typedef typename ELFObjectFile::Elf_Shdr Elf_Shdr; + typedef typename ELFObjectFile::Elf_Rel Elf_Rel; + typedef typename ELFObjectFile::Elf_Rela Elf_Rela; + + const ELFFile &EF = *Obj->getELFFile(); + + ErrorOr SecOrErr = EF.getSection(Rel.d.a); + if (std::error_code EC = SecOrErr.getError()) + return EC; + const Elf_Shdr *Sec = *SecOrErr; + ErrorOr SymTabOrErr = EF.getSection(Sec->sh_link); + if (std::error_code EC = SymTabOrErr.getError()) + return EC; + const Elf_Shdr *SymTab = *SymTabOrErr; + assert(SymTab->sh_type == ELF::SHT_SYMTAB || + SymTab->sh_type == ELF::SHT_DYNSYM); + ErrorOr StrTabSec = EF.getSection(SymTab->sh_link); + if (std::error_code EC = StrTabSec.getError()) + return EC; + ErrorOr StrTabOrErr = EF.getStringTable(*StrTabSec); + if (std::error_code EC = StrTabOrErr.getError()) + return EC; + StringRef StrTab = *StrTabOrErr; + 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: { + const Elf_Rel *ERel = Obj->getRel(Rel); + type = ERel->getType(EF.isMips64EL()); + symbol_index = ERel->getSymbol(EF.isMips64EL()); + // TODO: Read implicit addend from section data. + break; + } + case ELF::SHT_RELA: { + const Elf_Rela *ERela = Obj->getRela(Rel); + type = ERela->getType(EF.isMips64EL()); + symbol_index = ERela->getSymbol(EF.isMips64EL()); + addend = ERela->r_addend; + break; + } + } + const Elf_Sym *symb = + EF.template getEntry(Sec->sh_link, symbol_index); + StringRef Target; + ErrorOr SymSec = EF.getSection(symb); + if (std::error_code EC = SymSec.getError()) + return EC; + if (symb->getType() == ELF::STT_SECTION) { + ErrorOr SecName = EF.getSectionName(*SymSec); + if (std::error_code EC = SecName.getError()) + return EC; + Target = *SecName; + } else { + ErrorOr SymName = symb->getName(StrTab); + 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(); +} - outs() << output.c_str(); +static std::error_code getRelocationValueString(const ELFObjectFileBase *Obj, + const RelocationRef &RelRef, + SmallVectorImpl &Result) { + DataRefImpl Rel = RelRef.getRawDataRefImpl(); + if (auto *ELF32LE = dyn_cast(Obj)) + return getRelocationValueString(ELF32LE, Rel, Result); + if (auto *ELF64LE = dyn_cast(Obj)) + return getRelocationValueString(ELF64LE, Rel, Result); + if (auto *ELF32BE = dyn_cast(Obj)) + return getRelocationValueString(ELF32BE, Rel, Result); + auto *ELF64BE = cast(Obj); + return getRelocationValueString(ELF64BE, Rel, Result); } -bool llvm::RelocAddressLess(RelocationRef a, RelocationRef b) { - uint64_t a_addr, b_addr; - if (error(a.getOffset(a_addr))) return false; - if (error(b.getOffset(b_addr))) return false; - return a_addr < b_addr; +static std::error_code getRelocationValueString(const COFFObjectFile *Obj, + const RelocationRef &Rel, + SmallVectorImpl &Result) { + symbol_iterator SymI = Rel.getSymbol(); + ErrorOr SymNameOrErr = SymI->getName(); + if (std::error_code EC = SymNameOrErr.getError()) + return EC; + StringRef SymName = *SymNameOrErr; + 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; + ErrorOr Addr = Symbol.getAddress(); + if ((ec = Addr.getError())) + report_fatal_error(ec.message()); + if (*Addr != Val) + continue; + ErrorOr Name = Symbol.getName(); + if (std::error_code EC = Name.getError()) + 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); + ErrorOr SOrErr = SI->getName(); + if (!error(SOrErr.getError())) + S = *SOrErr; + } 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 &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 &Result) { + const ObjectFile *Obj = Rel.getObject(); + if (auto *ELF = dyn_cast(Obj)) + return getRelocationValueString(ELF, Rel, Result); + if (auto *COFF = dyn_cast(Obj)) + return getRelocationValueString(COFF, Rel, Result); + auto *MachO = cast(Obj); + return getRelocationValueString(MachO, Rel, Result); +} + +/// @brief Indicates whether this relocation should hidden when listing +/// relocations, usually because it is the trailing part of a multipart +/// relocation that will be printed as part of the leading relocation. +static bool getHidden(RelocationRef RelRef) { + const ObjectFile *Obj = RelRef.getObject(); + auto *MachO = dyn_cast(Obj); + if (!MachO) + return false; + + unsigned Arch = MachO->getArch(); + DataRefImpl Rel = RelRef.getRawDataRefImpl(); + uint64_t Type = MachO->getRelocationType(Rel); + + // On arches that use the generic relocations, GENERIC_RELOC_PAIR + // is always hidden. + if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) { + if (Type == MachO::GENERIC_RELOC_PAIR) + return true; + } else if (Arch == Triple::x86_64) { + // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows + // an X86_64_RELOC_SUBTRACTOR. + if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) { + DataRefImpl RelPrev = Rel; + RelPrev.d.a--; + uint64_t PrevType = MachO->getRelocationType(RelPrev); + if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR) + return true; + } + } + + return false; } static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { @@ -274,12 +786,14 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); std::unique_ptr IP(TheTarget->createMCInstPrinter( - AsmPrinterVariant, *AsmInfo, *MII, *MRI, *STI)); + Triple(TripleName), AsmPrinterVariant, *AsmInfo, *MII, *MRI)); if (!IP) { errs() << "error: no instruction printer for target " << TripleName << '\n'; return; } + IP->setPrintImmHex(PrintImmHex); + PrettyPrinter &PIP = selectPrettyPrinter(Triple(TripleName)); StringRef Fmt = Obj->getBytesInAddress() > 4 ? "\t\t%016" PRIx64 ": " : "\t\t\t%08" PRIx64 ": "; @@ -307,19 +821,20 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { std::vector> Symbols; for (const SymbolRef &Symbol : Obj->symbols()) { if (Section.containsSymbol(Symbol)) { - uint64_t Address; - if (error(Symbol.getAddress(Address))) + ErrorOr AddressOrErr = Symbol.getAddress(); + if (error(AddressOrErr.getError())) break; - if (Address == UnknownAddressOrSize) + uint64_t Address = *AddressOrErr; + if (Address == UnknownAddress) continue; Address -= SectionAddr; if (Address >= SectSize) continue; - StringRef Name; - if (error(Symbol.getName(Name))) + ErrorOr Name = Symbol.getName(); + if (error(Name.getError())) break; - Symbols.push_back(std::make_pair(Address, Name)); + Symbols.push_back(std::make_pair(Address, *Name)); } } @@ -352,11 +867,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,13 +909,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(StringRef( - reinterpret_cast(Bytes.data()) + Index, Size)); - } - IP->printInst(&Inst, outs(), ""); + PIP.printInst(*IP, &Inst, + Bytes.slice(Index, Size), + SectionAddr + Index, outs(), "", *STI); outs() << CommentStream.str(); Comments.clear(); outs() << "\n"; @@ -414,21 +923,19 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { // Print relocation for instruction. while (rel_cur != rel_end) { - bool hidden = false; - uint64_t addr; + bool hidden = getHidden(*rel_cur); + uint64_t addr = rel_cur->getOffset(); SmallString<16> name; SmallString<32> val; // If this relocation is hidden, skip it. - if (error(rel_cur->getHidden(hidden))) goto skip_print_rel; if (hidden) goto skip_print_rel; - if (error(rel_cur->getOffset(addr))) goto skip_print_rel; // 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; - + rel_cur->getTypeName(name); + if (error(getRelocationValueString(*rel_cur, val))) + goto skip_print_rel; outs() << format(Fmt.data(), SectionAddr + addr) << name << "\t" << val << "\n"; @@ -456,19 +963,14 @@ void llvm::PrintRelocations(const ObjectFile *Obj) { continue; outs() << "RELOCATION RECORDS FOR [" << secname << "]:\n"; for (const RelocationRef &Reloc : Section.relocations()) { - bool hidden; - uint64_t address; + bool hidden = getHidden(Reloc); + uint64_t address = Reloc.getOffset(); SmallString<32> relocname; SmallString<32> valuestr; - if (error(Reloc.getHidden(hidden))) - continue; if (hidden) continue; - if (error(Reloc.getTypeName(relocname))) - continue; - if (error(Reloc.getOffset(address))) - continue; - if (error(Reloc.getValueString(valuestr))) + Reloc.getTypeName(relocname); + if (error(getRelocationValueString(Reloc, valuestr))) continue; outs() << format(Fmt.data(), address) << " " << relocname << " " << valuestr << "\n"; @@ -609,39 +1111,36 @@ void llvm::PrintSymbolTable(const ObjectFile *o) { return; } for (const SymbolRef &Symbol : o->symbols()) { - StringRef Name; - uint64_t Address; - SymbolRef::Type Type; - uint64_t Size; + ErrorOr AddressOrError = Symbol.getAddress(); + if (error(AddressOrError.getError())) + continue; + uint64_t Address = *AddressOrError; + SymbolRef::Type Type = Symbol.getType(); 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; if (error(Symbol.getSection(Section))) continue; + StringRef Name; + if (Type == SymbolRef::ST_Debug && Section != o->section_end()) { + Section->getName(Name); + } else { + ErrorOr NameOrErr = Symbol.getName(); + if (error(NameOrErr.getError())) + continue; + Name = *NameOrErr; + } bool Global = Flags & SymbolRef::SF_Global; bool Weak = Flags & SymbolRef::SF_Weak; bool Absolute = Flags & SymbolRef::SF_Absolute; bool Common = Flags & SymbolRef::SF_Common; + bool Hidden = Flags & SymbolRef::SF_Hidden; - if (Common) { - uint32_t Alignment; - if (error(Symbol.getAlignment(Alignment))) - Alignment = 0; - Address = Size; - Size = Alignment; - } - if (Address == UnknownAddressOrSize) + if (Common) + Address = Symbol.getCommonSize(); + + if (Address == UnknownAddress) Address = 0; - if (Size == UnknownAddressOrSize) - Size = 0; char GlobLoc = ' '; if (Type != SymbolRef::ST_Unknown) GlobLoc = Global ? 'g' : 'l'; @@ -683,9 +1182,18 @@ void llvm::PrintSymbolTable(const ObjectFile *o) { SectionName = ""; outs() << SectionName; } - outs() << '\t' - << format("%08" PRIx64 " ", Size) - << Name + + outs() << '\t'; + if (Common || isa(o)) { + uint64_t Val = + Common ? Symbol.getAlignment() : ELFSymbolRef(Symbol).getSize(); + outs() << format("\t %08" PRIx64 " ", Val); + } + + if (Hidden) { + outs() << ".hidden "; + } + outs() << Name << '\n'; } } @@ -760,6 +1268,49 @@ void llvm::printWeakBindTable(const ObjectFile *o) { } } +static void printFaultMaps(const ObjectFile *Obj) { + const char *FaultMapSectionName = nullptr; + + if (isa(Obj)) { + FaultMapSectionName = ".llvm_faultmaps"; + } else if (isa(Obj)) { + FaultMapSectionName = "__llvm_faultmaps"; + } else { + errs() << "This operation is only currently supported " + "for ELF and Mach-O executable files.\n"; + return; + } + + Optional FaultMapSection; + + for (auto Sec : Obj->sections()) { + StringRef Name; + Sec.getName(Name); + if (Name == FaultMapSectionName) { + FaultMapSection = Sec; + break; + } + } + + outs() << "FaultMap table:\n"; + + if (!FaultMapSection.hasValue()) { + outs() << "\n"; + return; + } + + StringRef FaultMapContents; + if (error(FaultMapSection.getValue().getContents(FaultMapContents))) { + errs() << "Could not read the " << FaultMapContents << " section!\n"; + return; + } + + FaultMapParser FMP(FaultMapContents.bytes_begin(), + FaultMapContents.bytes_end()); + + outs() << FMP; +} + static void printPrivateFileHeader(const ObjectFile *o) { if (o->isELF()) { printELFFileHeader(o); @@ -799,6 +1350,8 @@ static void DumpObject(const ObjectFile *o) { printLazyBindTable(o); if (WeakBind) printWeakBindTable(o); + if (PrintFaultMaps) + printFaultMaps(o); } /// @brief Dump each object file in \a a; @@ -809,15 +1362,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(&*ChildOrErr.get())) DumpObject(o); else - errs() << ToolName << ": '" << a->getFileName() << "': " - << "Unrecognized file type.\n"; + report_error(a->getFileName(), object_error::invalid_file_type); } } @@ -825,7 +1376,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; } @@ -840,7 +1391,7 @@ static void DumpInput(StringRef file) { // Attempt to open the binary. ErrorOr> 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(); @@ -850,7 +1401,7 @@ static void DumpInput(StringRef file) { else if (ObjectFile *o = dyn_cast(&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) { @@ -897,7 +1448,9 @@ int main(int argc, char **argv) { && !(InfoPlist && MachOOpt) && !(DylibsUsed && MachOOpt) && !(DylibId && MachOOpt) - && !(DumpSections.size() != 0 && MachOOpt)) { + && !(ObjcMetaData && MachOOpt) + && !(DumpSections.size() != 0 && MachOOpt) + && !PrintFaultMaps) { cl::PrintHelpMessage(); return 2; }