Index: test/CodeGen/Hexagon/relax.ll =================================================================== --- test/CodeGen/Hexagon/relax.ll +++ test/CodeGen/Hexagon/relax.ll @@ -8,6 +8,6 @@ } ; CHECK: { call 0 -; CHECK: allocframe(#0) ; CHECK: 00000000: R_HEX_B22_PCREL +; CHECK: allocframe(#0) ; CHECK: { dealloc_return } Index: test/MC/Hexagon/packetrelo.s =================================================================== --- /dev/null +++ test/MC/Hexagon/packetrelo.s @@ -0,0 +1,15 @@ +# RUN: llvm-mc -filetype=obj -triple=hexagon %s | llvm-objdump -r -d - | FileCheck %s +{ + call ##foo + memw(##a) = r0 +} +#CHECK: { immext(#0) +#CHECK: : R_HEX_B32_PCREL_X foo +#CHECK: call +#CHECK: R_HEX_B22_PCREL_X foo +#CHECK: immext(#0) +#CHECK: R_HEX_32_6_X a +#CHECK: memw(##0) = r0 } +#CHECK: R_HEX_16_X a + + Index: test/MC/Hexagon/plt-rel.s =================================================================== --- test/MC/Hexagon/plt-rel.s +++ test/MC/Hexagon/plt-rel.s @@ -4,10 +4,10 @@ # CHECK: R_HEX_GD_PLT_B22_PCREL call ##foo@GDPLT # CHECK: R_HEX_GD_PLT_B32_PCREL_X -# CHECK-NEXT: R_HEX_GD_PLT_B22_PCREL_X +# CHECK: R_HEX_GD_PLT_B22_PCREL_X call foo@LDPLT # CHECK: R_HEX_LD_PLT_B22_PCREL call ##foo@LDPLT # CHECK: R_HEX_LD_PLT_B32_PCREL_X -# CHECK-NEXT: R_HEX_LD_PLT_B22_PCREL_X +# CHECK: R_HEX_LD_PLT_B22_PCREL_X Index: tools/llvm-objdump/llvm-objdump.cpp =================================================================== --- tools/llvm-objdump/llvm-objdump.cpp +++ tools/llvm-objdump/llvm-objdump.cpp @@ -401,277 +401,6 @@ return a.getOffset() < b.getOffset(); } -namespace { -class SourcePrinter { -protected: - DILineInfo OldLineInfo; - const ObjectFile *Obj = nullptr; - std::unique_ptr Symbolizer; - // File name to file contents of source - std::unordered_map> SourceCache; - // Mark the line endings of the cached source - std::unordered_map> LineCache; - -private: - bool cacheSource(const DILineInfo& LineInfoFile); - -public: - SourcePrinter() = default; - SourcePrinter(const ObjectFile *Obj, StringRef DefaultArch) : Obj(Obj) { - symbolize::LLVMSymbolizer::Options SymbolizerOpts( - DILineInfoSpecifier::FunctionNameKind::None, true, false, false, - DefaultArch); - Symbolizer.reset(new symbolize::LLVMSymbolizer(SymbolizerOpts)); - } - virtual ~SourcePrinter() = default; - virtual void printSourceLine(raw_ostream &OS, uint64_t Address, - StringRef Delimiter = "; "); -}; - -bool SourcePrinter::cacheSource(const DILineInfo &LineInfo) { - std::unique_ptr Buffer; - if (LineInfo.Source) { - Buffer = MemoryBuffer::getMemBuffer(*LineInfo.Source); - } else { - auto BufferOrError = MemoryBuffer::getFile(LineInfo.FileName); - if (!BufferOrError) - return false; - Buffer = std::move(*BufferOrError); - } - // Chomp the file to get lines - size_t BufferSize = Buffer->getBufferSize(); - const char *BufferStart = Buffer->getBufferStart(); - for (const char *Start = BufferStart, *End = BufferStart; - End < BufferStart + BufferSize; End++) - if (*End == '\n' || End == BufferStart + BufferSize - 1 || - (*End == '\r' && *(End + 1) == '\n')) { - LineCache[LineInfo.FileName].push_back(StringRef(Start, End - Start)); - if (*End == '\r') - End++; - Start = End + 1; - } - SourceCache[LineInfo.FileName] = std::move(Buffer); - return true; -} - -void SourcePrinter::printSourceLine(raw_ostream &OS, uint64_t Address, - StringRef Delimiter) { - if (!Symbolizer) - return; - DILineInfo LineInfo = DILineInfo(); - auto ExpectecLineInfo = - Symbolizer->symbolizeCode(Obj->getFileName(), Address); - if (!ExpectecLineInfo) - consumeError(ExpectecLineInfo.takeError()); - else - LineInfo = *ExpectecLineInfo; - - if ((LineInfo.FileName == "") || OldLineInfo.Line == LineInfo.Line || - LineInfo.Line == 0) - return; - - if (PrintLines) - OS << Delimiter << LineInfo.FileName << ":" << LineInfo.Line << "\n"; - if (PrintSource) { - if (SourceCache.find(LineInfo.FileName) == SourceCache.end()) - if (!cacheSource(LineInfo)) - return; - auto FileBuffer = SourceCache.find(LineInfo.FileName); - if (FileBuffer != SourceCache.end()) { - auto LineBuffer = LineCache.find(LineInfo.FileName); - if (LineBuffer != LineCache.end()) { - if (LineInfo.Line > LineBuffer->second.size()) - return; - // Vector begins at 0, line numbers are non-zero - OS << Delimiter << LineBuffer->second[LineInfo.Line - 1].ltrim() - << "\n"; - } - } - } - OldLineInfo = LineInfo; -} - -static bool isArmElf(const ObjectFile *Obj) { - return (Obj->isELF() && - (Obj->getArch() == Triple::aarch64 || - Obj->getArch() == Triple::aarch64_be || - Obj->getArch() == Triple::arm || Obj->getArch() == Triple::armeb || - Obj->getArch() == Triple::thumb || - Obj->getArch() == Triple::thumbeb)); -} - -class PrettyPrinter { -public: - virtual ~PrettyPrinter() = default; - virtual void printInst(MCInstPrinter &IP, const MCInst *MI, - ArrayRef Bytes, uint64_t Address, - raw_ostream &OS, StringRef Annot, - MCSubtargetInfo const &STI, SourcePrinter *SP) { - if (SP && (PrintSource || PrintLines)) - SP->printSourceLine(OS, Address); - if (!NoLeadingAddr) - OS << format("%8" PRIx64 ":", Address); - if (!NoShowRawInsn) { - OS << "\t"; - dumpBytes(Bytes, OS); - } - if (MI) - IP.printInst(MI, OS, "", STI); - else - OS << " "; - } -}; -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]; - if (!NoLeadingAddr) - 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, SourcePrinter *SP) override { - if (SP && (PrintSource || PrintLines)) - SP->printSourceLine(OS, Address, ""); - if (!MI) { - printLead(Bytes, Address, OS); - OS << " "; - return; - } - 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"; - if (SP && (PrintSource || PrintLines)) - SP->printSourceLine(OS, Address, ""); - 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; - -class AMDGCNPrettyPrinter : public PrettyPrinter { -public: - void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef Bytes, - uint64_t Address, raw_ostream &OS, StringRef Annot, - MCSubtargetInfo const &STI, SourcePrinter *SP) override { - if (SP && (PrintSource || PrintLines)) - SP->printSourceLine(OS, Address); - - typedef support::ulittle32_t U32; - - if (MI) { - SmallString<40> InstStr; - raw_svector_ostream IS(InstStr); - - IP.printInst(MI, IS, "", STI); - - OS << left_justify(IS.str(), 60); - } else { - // an unrecognized encoding - this is probably data so represent it - // using the .long directive, or .byte directive if fewer than 4 bytes - // remaining - if (Bytes.size() >= 4) { - OS << format("\t.long 0x%08" PRIx32 " ", - static_cast(*reinterpret_cast(Bytes.data()))); - OS.indent(42); - } else { - OS << format("\t.byte 0x%02" PRIx8, Bytes[0]); - for (unsigned int i = 1; i < Bytes.size(); i++) - OS << format(", 0x%02" PRIx8, Bytes[i]); - OS.indent(55 - (6 * Bytes.size())); - } - } - - OS << format("// %012" PRIX64 ": ", Address); - if (Bytes.size() >=4) { - for (auto D : makeArrayRef(reinterpret_cast(Bytes.data()), - Bytes.size() / sizeof(U32))) - // D should be explicitly casted to uint32_t here as it is passed - // by format to snprintf as vararg. - OS << format("%08" PRIX32 " ", static_cast(D)); - } else { - for (unsigned int i = 0; i < Bytes.size(); i++) - OS << format("%02" PRIX8 " ", Bytes[i]); - } - - if (!Annot.empty()) - OS << "// " << Annot; - } -}; -AMDGCNPrettyPrinter AMDGCNPrettyPrinterInst; - -class BPFPrettyPrinter : public PrettyPrinter { -public: - void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef Bytes, - uint64_t Address, raw_ostream &OS, StringRef Annot, - MCSubtargetInfo const &STI, SourcePrinter *SP) override { - if (SP && (PrintSource || PrintLines)) - SP->printSourceLine(OS, Address); - if (!NoLeadingAddr) - OS << format("%8" PRId64 ":", Address / 8); - if (!NoShowRawInsn) { - OS << "\t"; - dumpBytes(Bytes, OS); - } - if (MI) - IP.printInst(MI, OS, "", STI); - else - OS << " "; - } -}; -BPFPrettyPrinter BPFPrettyPrinterInst; - -PrettyPrinter &selectPrettyPrinter(Triple const &Triple) { - switch(Triple.getArch()) { - default: - return PrettyPrinterInst; - case Triple::hexagon: - return HexagonPrettyPrinterInst; - case Triple::amdgcn: - return AMDGCNPrettyPrinterInst; - case Triple::bpfel: - case Triple::bpfeb: - return BPFPrettyPrinterInst; - } -} -} - template static std::error_code getRelocationValueString(const ELFObjectFile *Obj, const RelocationRef &RelRef, @@ -1034,132 +763,430 @@ 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_error(Obj->getFileName(), "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); + + 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_error(Obj->getFileName(), "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) & 0x1) == 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_error(Obj->getFileName(), "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); + if (auto *Wasm = dyn_cast(Obj)) + return getRelocationValueString(Wasm, Rel, Result); + if (auto *MachO = dyn_cast(Obj)) + return getRelocationValueString(MachO, Rel, Result); + llvm_unreachable("unknown object file format"); +} + +/// 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; +} + +namespace { +class SourcePrinter { +protected: + DILineInfo OldLineInfo; + const ObjectFile *Obj = nullptr; + std::unique_ptr Symbolizer; + // File name to file contents of source + std::unordered_map> SourceCache; + // Mark the line endings of the cached source + std::unordered_map> LineCache; + +private: + bool cacheSource(const DILineInfo& LineInfoFile); + +public: + SourcePrinter() = default; + SourcePrinter(const ObjectFile *Obj, StringRef DefaultArch) : Obj(Obj) { + symbolize::LLVMSymbolizer::Options SymbolizerOpts( + DILineInfoSpecifier::FunctionNameKind::None, true, false, false, + DefaultArch); + Symbolizer.reset(new symbolize::LLVMSymbolizer(SymbolizerOpts)); + } + virtual ~SourcePrinter() = default; + virtual void printSourceLine(raw_ostream &OS, uint64_t Address, + StringRef Delimiter = "; "); +}; + +bool SourcePrinter::cacheSource(const DILineInfo &LineInfo) { + std::unique_ptr Buffer; + if (LineInfo.Source) { + Buffer = MemoryBuffer::getMemBuffer(*LineInfo.Source); + } else { + auto BufferOrError = MemoryBuffer::getFile(LineInfo.FileName); + if (!BufferOrError) + return false; + Buffer = std::move(*BufferOrError); + } + // Chomp the file to get lines + size_t BufferSize = Buffer->getBufferSize(); + const char *BufferStart = Buffer->getBufferStart(); + for (const char *Start = BufferStart, *End = BufferStart; + End < BufferStart + BufferSize; End++) + if (*End == '\n' || End == BufferStart + BufferSize - 1 || + (*End == '\r' && *(End + 1) == '\n')) { + LineCache[LineInfo.FileName].push_back(StringRef(Start, End - Start)); + if (*End == '\r') + End++; + Start = End + 1; + } + SourceCache[LineInfo.FileName] = std::move(Buffer); + return true; +} + +void SourcePrinter::printSourceLine(raw_ostream &OS, uint64_t Address, + StringRef Delimiter) { + if (!Symbolizer) + return; + DILineInfo LineInfo = DILineInfo(); + auto ExpectecLineInfo = + Symbolizer->symbolizeCode(Obj->getFileName(), Address); + if (!ExpectecLineInfo) + consumeError(ExpectecLineInfo.takeError()); + else + LineInfo = *ExpectecLineInfo; + + if ((LineInfo.FileName == "") || OldLineInfo.Line == LineInfo.Line || + LineInfo.Line == 0) + return; + + if (PrintLines) + OS << Delimiter << LineInfo.FileName << ":" << LineInfo.Line << "\n"; + if (PrintSource) { + if (SourceCache.find(LineInfo.FileName) == SourceCache.end()) + if (!cacheSource(LineInfo)) + return; + auto FileBuffer = SourceCache.find(LineInfo.FileName); + if (FileBuffer != SourceCache.end()) { + auto LineBuffer = LineCache.find(LineInfo.FileName); + if (LineBuffer != LineCache.end()) { + if (LineInfo.Line > LineBuffer->second.size()) + return; + // Vector begins at 0, line numbers are non-zero + OS << Delimiter << LineBuffer->second[LineInfo.Line - 1].ltrim() + << "\n"; + } + } + } + OldLineInfo = LineInfo; +} + +static bool isArmElf(const ObjectFile *Obj) { + return (Obj->isELF() && + (Obj->getArch() == Triple::aarch64 || + Obj->getArch() == Triple::aarch64_be || + Obj->getArch() == Triple::arm || Obj->getArch() == Triple::armeb || + Obj->getArch() == Triple::thumb || + Obj->getArch() == Triple::thumbeb)); +} + +class PrettyPrinter { +public: + virtual ~PrettyPrinter() = default; + virtual void printInst(MCInstPrinter &IP, const MCInst *MI, + ArrayRef Bytes, uint64_t Address, + raw_ostream &OS, StringRef Annot, + MCSubtargetInfo const &STI, SourcePrinter *SP, + std::vector *Rels = nullptr) { + if (SP && (PrintSource || PrintLines)) + SP->printSourceLine(OS, Address); + if (!NoLeadingAddr) + OS << format("%8" PRIx64 ":", Address); + if (!NoShowRawInsn) { + OS << "\t"; + dumpBytes(Bytes, OS); + } + if (MI) + IP.printInst(MI, OS, "", STI); + else + OS << " "; + } +}; +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]; + if (!NoLeadingAddr) + 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, SourcePrinter *SP, + std::vector *Rels) override { + if (SP && (PrintSource || PrintLines)) + SP->printSourceLine(OS, Address, ""); + if (!MI) { + printLead(Bytes, Address, OS); + OS << " "; + return; + } + 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 = ""; + StringRef Fmt = "\t\t\t%08" PRIx64 ": "; + std::vector::const_iterator rel_cur = Rels->begin(); + std::vector::const_iterator rel_end = Rels->end(); + + // Hexagon's packets require relocations to be inline rather than + // clustered at the end of the packet. + auto PrintReloc = [&]() -> void { + while ((rel_cur != rel_end) && (rel_cur->getOffset() <= Address)) { + if (rel_cur->getOffset() == Address) { + SmallString<16> name; + SmallString<32> val; + rel_cur->getTypeName(name); + error(getRelocationValueString(*rel_cur, val)); + OS << Separator << format(Fmt.data(), Address) << name << "\t" << val + << "\n"; + return; + } + rel_cur++; } - } 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) & 0x1) == 1; + }; - if (isUpper) - fmt << ":upper16:("; - else - fmt << ":lower16:("; - printRelocationTargetName(Obj, RE, fmt); + while(!HeadTail.first.empty()) { + OS << Separator; + Separator = "\n"; + if (SP && (PrintSource || PrintLines)) + SP->printSourceLine(OS, Address, ""); + 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; + HeadTail = HeadTail.second.split('\n'); + if (HeadTail.first.empty()) + OS << " } " << PacketBundle.second; + PrintReloc(); + Bytes = Bytes.slice(4); + Address += 4; + } + } +}; +HexagonPrettyPrinter HexagonPrettyPrinterInst; - DataRefImpl RelNext = Rel; - Obj->moveRelocationNext(RelNext); - MachO::any_relocation_info RENext = Obj->getRelocation(RelNext); +class AMDGCNPrettyPrinter : public PrettyPrinter { +public: + void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef Bytes, + uint64_t Address, raw_ostream &OS, StringRef Annot, + MCSubtargetInfo const &STI, SourcePrinter *SP, + std::vector *Rels) override { + if (SP && (PrintSource || PrintLines)) + SP->printSourceLine(OS, Address); - // 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_error(Obj->getFileName(), "Expected ARM_RELOC_PAIR after " - "ARM_RELOC_HALF"); + typedef support::ulittle32_t U32; - // 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. + if (MI) { + SmallString<40> InstStr; + raw_svector_ostream IS(InstStr); - // 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); - } + IP.printInst(MI, IS, "", STI); - fmt << ")"; - break; - } - default: { printRelocationTargetName(Obj, RE, fmt); } + OS << left_justify(IS.str(), 60); + } else { + // an unrecognized encoding - this is probably data so represent it + // using the .long directive, or .byte directive if fewer than 4 bytes + // remaining + if (Bytes.size() >= 4) { + OS << format("\t.long 0x%08" PRIx32 " ", + static_cast(*reinterpret_cast(Bytes.data()))); + OS.indent(42); + } else { + OS << format("\t.byte 0x%02" PRIx8, Bytes[0]); + for (unsigned int i = 1; i < Bytes.size(); i++) + OS << format(", 0x%02" PRIx8, Bytes[i]); + OS.indent(55 - (6 * Bytes.size())); } } - } 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); - if (auto *Wasm = dyn_cast(Obj)) - return getRelocationValueString(Wasm, Rel, Result); - if (auto *MachO = dyn_cast(Obj)) - return getRelocationValueString(MachO, Rel, Result); - llvm_unreachable("unknown object file format"); -} -/// 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; + OS << format("// %012" PRIX64 ": ", Address); + if (Bytes.size() >=4) { + for (auto D : makeArrayRef(reinterpret_cast(Bytes.data()), + Bytes.size() / sizeof(U32))) + // D should be explicitly casted to uint32_t here as it is passed + // by format to snprintf as vararg. + OS << format("%08" PRIX32 " ", static_cast(D)); + } else { + for (unsigned int i = 0; i < Bytes.size(); i++) + OS << format("%02" PRIX8 " ", Bytes[i]); + } - unsigned Arch = MachO->getArch(); - DataRefImpl Rel = RelRef.getRawDataRefImpl(); - uint64_t Type = MachO->getRelocationType(Rel); + if (!Annot.empty()) + OS << "// " << Annot; + } +}; +AMDGCNPrettyPrinter AMDGCNPrettyPrinterInst; - // 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; +class BPFPrettyPrinter : public PrettyPrinter { +public: + void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef Bytes, + uint64_t Address, raw_ostream &OS, StringRef Annot, + MCSubtargetInfo const &STI, SourcePrinter *SP, + std::vector *Rels) override { + if (SP && (PrintSource || PrintLines)) + SP->printSourceLine(OS, Address); + if (!NoLeadingAddr) + OS << format("%8" PRId64 ":", Address / 8); + if (!NoShowRawInsn) { + OS << "\t"; + dumpBytes(Bytes, OS); } + if (MI) + IP.printInst(MI, OS, "", STI); + else + OS << " "; } +}; +BPFPrettyPrinter BPFPrettyPrinterInst; - return false; +PrettyPrinter &selectPrettyPrinter(Triple const &Triple) { + switch(Triple.getArch()) { + default: + return PrettyPrinterInst; + case Triple::hexagon: + return HexagonPrettyPrinterInst; + case Triple::amdgcn: + return AMDGCNPrettyPrinterInst; + case Triple::bpfel: + case Triple::bpfeb: + return BPFPrettyPrinterInst; + } +} } static uint8_t getElfSymbolType(const ObjectFile *Obj, const SymbolRef &Sym) { @@ -1647,7 +1674,7 @@ PIP.printInst(*IP, Disassembled ? &Inst : nullptr, Bytes.slice(Index, Size), SectionAddr + Index, outs(), "", - *STI, &SP); + *STI, &SP, &Rels); outs() << CommentStream.str(); Comments.clear(); @@ -1704,27 +1731,29 @@ } outs() << "\n"; - // Print relocation for instruction. - while (rel_cur != rel_end) { - bool hidden = getHidden(*rel_cur); - uint64_t addr = rel_cur->getOffset(); - SmallString<16> name; - SmallString<32> val; + // Hexagon does this in pretty printer + if (Obj->getArch() != Triple::hexagon) + // Print relocation for instruction. + while (rel_cur != rel_end) { + 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 (hidden || ((SectionAddr + addr) < StartAddress)) { + ++rel_cur; + continue; + } - // If this relocation is hidden, skip it. - if (hidden || ((SectionAddr + addr) < StartAddress)) { + // Stop when rel_cur's address is past the current instruction. + if (addr >= Index + Size) break; + rel_cur->getTypeName(name); + error(getRelocationValueString(*rel_cur, val)); + outs() << format(Fmt.data(), SectionAddr + addr) << name + << "\t" << val << "\n"; ++rel_cur; - continue; } - - // Stop when rel_cur's address is past the current instruction. - if (addr >= Index + Size) break; - rel_cur->getTypeName(name); - error(getRelocationValueString(*rel_cur, val)); - outs() << format(Fmt.data(), SectionAddr + addr) << name - << "\t" << val << "\n"; - ++rel_cur; - } } } }