summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/MC/MCDisassembler
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/MC/MCDisassembler')
-rw-r--r--contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp337
-rw-r--r--contrib/llvm/lib/MC/MCDisassembler/Disassembler.h129
-rw-r--r--contrib/llvm/lib/MC/MCDisassembler/MCDisassembler.cpp39
-rw-r--r--contrib/llvm/lib/MC/MCDisassembler/MCExternalSymbolizer.cpp196
-rw-r--r--contrib/llvm/lib/MC/MCDisassembler/MCRelocationInfo.cpp40
5 files changed, 741 insertions, 0 deletions
diff --git a/contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp b/contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp
new file mode 100644
index 0000000..716d76a
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp
@@ -0,0 +1,337 @@
+//===-- lib/MC/Disassembler.cpp - Disassembler Public C Interface ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Disassembler.h"
+#include "llvm-c/Disassembler.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDisassembler.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCRelocationInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCSymbolizer.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/TargetRegistry.h"
+
+using namespace llvm;
+
+// LLVMCreateDisasm() creates a disassembler for the TripleName. Symbolic
+// disassembly is supported by passing a block of information in the DisInfo
+// parameter and specifying the TagType and callback functions as described in
+// the header llvm-c/Disassembler.h . The pointer to the block and the
+// functions can all be passed as NULL. If successful, this returns a
+// disassembler context. If not, it returns NULL.
+//
+LLVMDisasmContextRef
+LLVMCreateDisasmCPUFeatures(const char *TT, const char *CPU,
+ const char *Features, void *DisInfo, int TagType,
+ LLVMOpInfoCallback GetOpInfo,
+ LLVMSymbolLookupCallback SymbolLookUp) {
+ // Get the target.
+ std::string Error;
+ const Target *TheTarget = TargetRegistry::lookupTarget(TT, Error);
+ if (!TheTarget)
+ return nullptr;
+
+ const MCRegisterInfo *MRI = TheTarget->createMCRegInfo(TT);
+ if (!MRI)
+ return nullptr;
+
+ // Get the assembler info needed to setup the MCContext.
+ const MCAsmInfo *MAI = TheTarget->createMCAsmInfo(*MRI, TT);
+ if (!MAI)
+ return nullptr;
+
+ const MCInstrInfo *MII = TheTarget->createMCInstrInfo();
+ if (!MII)
+ return nullptr;
+
+ const MCSubtargetInfo *STI =
+ TheTarget->createMCSubtargetInfo(TT, CPU, Features);
+ if (!STI)
+ return nullptr;
+
+ // Set up the MCContext for creating symbols and MCExpr's.
+ MCContext *Ctx = new MCContext(MAI, MRI, nullptr);
+ if (!Ctx)
+ return nullptr;
+
+ // Set up disassembler.
+ MCDisassembler *DisAsm = TheTarget->createMCDisassembler(*STI, *Ctx);
+ if (!DisAsm)
+ return nullptr;
+
+ std::unique_ptr<MCRelocationInfo> RelInfo(
+ TheTarget->createMCRelocationInfo(TT, *Ctx));
+ if (!RelInfo)
+ return nullptr;
+
+ std::unique_ptr<MCSymbolizer> Symbolizer(TheTarget->createMCSymbolizer(
+ TT, GetOpInfo, SymbolLookUp, DisInfo, Ctx, std::move(RelInfo)));
+ DisAsm->setSymbolizer(std::move(Symbolizer));
+
+ // Set up the instruction printer.
+ int AsmPrinterVariant = MAI->getAssemblerDialect();
+ MCInstPrinter *IP = TheTarget->createMCInstPrinter(
+ Triple(TT), AsmPrinterVariant, *MAI, *MII, *MRI);
+ if (!IP)
+ return nullptr;
+
+ LLVMDisasmContext *DC =
+ new LLVMDisasmContext(TT, DisInfo, TagType, GetOpInfo, SymbolLookUp,
+ TheTarget, MAI, MRI, STI, MII, Ctx, DisAsm, IP);
+ if (!DC)
+ return nullptr;
+
+ DC->setCPU(CPU);
+ return DC;
+}
+
+LLVMDisasmContextRef
+LLVMCreateDisasmCPU(const char *TT, const char *CPU, void *DisInfo, int TagType,
+ LLVMOpInfoCallback GetOpInfo,
+ LLVMSymbolLookupCallback SymbolLookUp) {
+ return LLVMCreateDisasmCPUFeatures(TT, CPU, "", DisInfo, TagType, GetOpInfo,
+ SymbolLookUp);
+}
+
+LLVMDisasmContextRef LLVMCreateDisasm(const char *TT, void *DisInfo,
+ int TagType, LLVMOpInfoCallback GetOpInfo,
+ LLVMSymbolLookupCallback SymbolLookUp) {
+ return LLVMCreateDisasmCPUFeatures(TT, "", "", DisInfo, TagType, GetOpInfo,
+ SymbolLookUp);
+}
+
+//
+// LLVMDisasmDispose() disposes of the disassembler specified by the context.
+//
+void LLVMDisasmDispose(LLVMDisasmContextRef DCR){
+ LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
+ delete DC;
+}
+
+/// \brief Emits the comments that are stored in \p DC comment stream.
+/// Each comment in the comment stream must end with a newline.
+static void emitComments(LLVMDisasmContext *DC,
+ formatted_raw_ostream &FormattedOS) {
+ // Flush the stream before taking its content.
+ DC->CommentStream.flush();
+ StringRef Comments = DC->CommentsToEmit.str();
+ // Get the default information for printing a comment.
+ const MCAsmInfo *MAI = DC->getAsmInfo();
+ const char *CommentBegin = MAI->getCommentString();
+ unsigned CommentColumn = MAI->getCommentColumn();
+ bool IsFirst = true;
+ while (!Comments.empty()) {
+ if (!IsFirst)
+ FormattedOS << '\n';
+ // Emit a line of comments.
+ FormattedOS.PadToColumn(CommentColumn);
+ size_t Position = Comments.find('\n');
+ FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position);
+ // Move after the newline character.
+ Comments = Comments.substr(Position+1);
+ IsFirst = false;
+ }
+ FormattedOS.flush();
+
+ // Tell the comment stream that the vector changed underneath it.
+ DC->CommentsToEmit.clear();
+ DC->CommentStream.resync();
+}
+
+/// \brief Gets latency information for \p Inst from the itinerary
+/// scheduling model, based on \p DC information.
+/// \return The maximum expected latency over all the operands or -1
+/// if no information is available.
+static int getItineraryLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
+ const int NoInformationAvailable = -1;
+
+ // Check if we have a CPU to get the itinerary information.
+ if (DC->getCPU().empty())
+ return NoInformationAvailable;
+
+ // Get itinerary information.
+ const MCSubtargetInfo *STI = DC->getSubtargetInfo();
+ InstrItineraryData IID = STI->getInstrItineraryForCPU(DC->getCPU());
+ // Get the scheduling class of the requested instruction.
+ const MCInstrDesc& Desc = DC->getInstrInfo()->get(Inst.getOpcode());
+ unsigned SCClass = Desc.getSchedClass();
+
+ int Latency = 0;
+ for (unsigned OpIdx = 0, OpIdxEnd = Inst.getNumOperands(); OpIdx != OpIdxEnd;
+ ++OpIdx)
+ Latency = std::max(Latency, IID.getOperandCycle(SCClass, OpIdx));
+
+ return Latency;
+}
+
+/// \brief Gets latency information for \p Inst, based on \p DC information.
+/// \return The maximum expected latency over all the definitions or -1
+/// if no information is available.
+static int getLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
+ // Try to compute scheduling information.
+ const MCSubtargetInfo *STI = DC->getSubtargetInfo();
+ const MCSchedModel SCModel = STI->getSchedModel();
+ const int NoInformationAvailable = -1;
+
+ // Check if we have a scheduling model for instructions.
+ if (!SCModel.hasInstrSchedModel())
+ // Try to fall back to the itinerary model if the scheduling model doesn't
+ // have a scheduling table. Note the default does not have a table.
+ return getItineraryLatency(DC, Inst);
+
+ // Get the scheduling class of the requested instruction.
+ const MCInstrDesc& Desc = DC->getInstrInfo()->get(Inst.getOpcode());
+ unsigned SCClass = Desc.getSchedClass();
+ const MCSchedClassDesc *SCDesc = SCModel.getSchedClassDesc(SCClass);
+ // Resolving the variant SchedClass requires an MI to pass to
+ // SubTargetInfo::resolveSchedClass.
+ if (!SCDesc || !SCDesc->isValid() || SCDesc->isVariant())
+ return NoInformationAvailable;
+
+ // Compute output latency.
+ int Latency = 0;
+ for (unsigned DefIdx = 0, DefEnd = SCDesc->NumWriteLatencyEntries;
+ DefIdx != DefEnd; ++DefIdx) {
+ // Lookup the definition's write latency in SubtargetInfo.
+ const MCWriteLatencyEntry *WLEntry = STI->getWriteLatencyEntry(SCDesc,
+ DefIdx);
+ Latency = std::max(Latency, WLEntry->Cycles);
+ }
+
+ return Latency;
+}
+
+
+/// \brief Emits latency information in DC->CommentStream for \p Inst, based
+/// on the information available in \p DC.
+static void emitLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
+ int Latency = getLatency(DC, Inst);
+
+ // Report only interesting latencies.
+ if (Latency < 2)
+ return;
+
+ DC->CommentStream << "Latency: " << Latency << '\n';
+}
+
+//
+// LLVMDisasmInstruction() disassembles a single instruction using the
+// disassembler context specified in the parameter DC. The bytes of the
+// instruction are specified in the parameter Bytes, and contains at least
+// BytesSize number of bytes. The instruction is at the address specified by
+// the PC parameter. If a valid instruction can be disassembled its string is
+// returned indirectly in OutString which whos size is specified in the
+// parameter OutStringSize. This function returns the number of bytes in the
+// instruction or zero if there was no valid instruction. If this function
+// returns zero the caller will have to pick how many bytes they want to step
+// over by printing a .byte, .long etc. to continue.
+//
+size_t LLVMDisasmInstruction(LLVMDisasmContextRef DCR, uint8_t *Bytes,
+ uint64_t BytesSize, uint64_t PC, char *OutString,
+ size_t OutStringSize){
+ LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
+ // Wrap the pointer to the Bytes, BytesSize and PC in a MemoryObject.
+ ArrayRef<uint8_t> Data(Bytes, BytesSize);
+
+ uint64_t Size;
+ MCInst Inst;
+ const MCDisassembler *DisAsm = DC->getDisAsm();
+ MCInstPrinter *IP = DC->getIP();
+ MCDisassembler::DecodeStatus S;
+ SmallVector<char, 64> InsnStr;
+ raw_svector_ostream Annotations(InsnStr);
+ S = DisAsm->getInstruction(Inst, Size, Data, PC,
+ /*REMOVE*/ nulls(), Annotations);
+ switch (S) {
+ case MCDisassembler::Fail:
+ case MCDisassembler::SoftFail:
+ // FIXME: Do something different for soft failure modes?
+ return 0;
+
+ case MCDisassembler::Success: {
+ Annotations.flush();
+ StringRef AnnotationsStr = Annotations.str();
+
+ SmallVector<char, 64> InsnStr;
+ raw_svector_ostream OS(InsnStr);
+ formatted_raw_ostream FormattedOS(OS);
+ IP->printInst(&Inst, FormattedOS, AnnotationsStr, *DC->getSubtargetInfo());
+
+ if (DC->getOptions() & LLVMDisassembler_Option_PrintLatency)
+ emitLatency(DC, Inst);
+
+ emitComments(DC, FormattedOS);
+ OS.flush();
+
+ assert(OutStringSize != 0 && "Output buffer cannot be zero size");
+ size_t OutputSize = std::min(OutStringSize-1, InsnStr.size());
+ std::memcpy(OutString, InsnStr.data(), OutputSize);
+ OutString[OutputSize] = '\0'; // Terminate string.
+
+ return Size;
+ }
+ }
+ llvm_unreachable("Invalid DecodeStatus!");
+}
+
+//
+// LLVMSetDisasmOptions() sets the disassembler's options. It returns 1 if it
+// can set all the Options and 0 otherwise.
+//
+int LLVMSetDisasmOptions(LLVMDisasmContextRef DCR, uint64_t Options){
+ if (Options & LLVMDisassembler_Option_UseMarkup){
+ LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
+ MCInstPrinter *IP = DC->getIP();
+ IP->setUseMarkup(1);
+ DC->addOptions(LLVMDisassembler_Option_UseMarkup);
+ Options &= ~LLVMDisassembler_Option_UseMarkup;
+ }
+ if (Options & LLVMDisassembler_Option_PrintImmHex){
+ LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
+ MCInstPrinter *IP = DC->getIP();
+ IP->setPrintImmHex(1);
+ DC->addOptions(LLVMDisassembler_Option_PrintImmHex);
+ Options &= ~LLVMDisassembler_Option_PrintImmHex;
+ }
+ if (Options & LLVMDisassembler_Option_AsmPrinterVariant){
+ LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
+ // Try to set up the new instruction printer.
+ const MCAsmInfo *MAI = DC->getAsmInfo();
+ const MCInstrInfo *MII = DC->getInstrInfo();
+ const MCRegisterInfo *MRI = DC->getRegisterInfo();
+ int AsmPrinterVariant = MAI->getAssemblerDialect();
+ AsmPrinterVariant = AsmPrinterVariant == 0 ? 1 : 0;
+ MCInstPrinter *IP = DC->getTarget()->createMCInstPrinter(
+ Triple(DC->getTripleName()), AsmPrinterVariant, *MAI, *MII, *MRI);
+ if (IP) {
+ DC->setIP(IP);
+ DC->addOptions(LLVMDisassembler_Option_AsmPrinterVariant);
+ Options &= ~LLVMDisassembler_Option_AsmPrinterVariant;
+ }
+ }
+ if (Options & LLVMDisassembler_Option_SetInstrComments) {
+ LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
+ MCInstPrinter *IP = DC->getIP();
+ IP->setCommentStream(DC->CommentStream);
+ DC->addOptions(LLVMDisassembler_Option_SetInstrComments);
+ Options &= ~LLVMDisassembler_Option_SetInstrComments;
+ }
+ if (Options & LLVMDisassembler_Option_PrintLatency) {
+ LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
+ DC->addOptions(LLVMDisassembler_Option_PrintLatency);
+ Options &= ~LLVMDisassembler_Option_PrintLatency;
+ }
+ return (Options == 0);
+}
diff --git a/contrib/llvm/lib/MC/MCDisassembler/Disassembler.h b/contrib/llvm/lib/MC/MCDisassembler/Disassembler.h
new file mode 100644
index 0000000..46d0c4c
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCDisassembler/Disassembler.h
@@ -0,0 +1,129 @@
+//===------------- Disassembler.h - LLVM Disassembler -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interface for the Disassembly library's disassembler
+// context. The disassembler is responsible for producing strings for
+// individual instructions according to a given architecture and disassembly
+// syntax.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_MC_MCDISASSEMBLER_DISASSEMBLER_H
+#define LLVM_LIB_MC_MCDISASSEMBLER_DISASSEMBLER_H
+
+#include "llvm-c/Disassembler.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/raw_ostream.h"
+#include <string>
+
+namespace llvm {
+class MCContext;
+class MCAsmInfo;
+class MCDisassembler;
+class MCInstPrinter;
+class MCInstrInfo;
+class MCRegisterInfo;
+class MCSubtargetInfo;
+class Target;
+
+//
+// This is the disassembler context returned by LLVMCreateDisasm().
+//
+class LLVMDisasmContext {
+private:
+ //
+ // The passed parameters when the disassembler context is created.
+ //
+ // The TripleName for this disassembler.
+ std::string TripleName;
+ // The pointer to the caller's block of symbolic information.
+ void *DisInfo;
+ // The Triple specific symbolic information type returned by GetOpInfo.
+ int TagType;
+ // The function to get the symbolic information for operands.
+ LLVMOpInfoCallback GetOpInfo;
+ // The function to look up a symbol name.
+ LLVMSymbolLookupCallback SymbolLookUp;
+ //
+ // The objects created and saved by LLVMCreateDisasm() then used by
+ // LLVMDisasmInstruction().
+ //
+ // The LLVM target corresponding to the disassembler.
+ // FIXME: using std::unique_ptr<const llvm::Target> causes a malloc error
+ // when this LLVMDisasmContext is deleted.
+ const Target *TheTarget;
+ // The assembly information for the target architecture.
+ std::unique_ptr<const llvm::MCAsmInfo> MAI;
+ // The register information for the target architecture.
+ std::unique_ptr<const llvm::MCRegisterInfo> MRI;
+ // The subtarget information for the target architecture.
+ std::unique_ptr<const llvm::MCSubtargetInfo> MSI;
+ // The instruction information for the target architecture.
+ std::unique_ptr<const llvm::MCInstrInfo> MII;
+ // The assembly context for creating symbols and MCExprs.
+ std::unique_ptr<const llvm::MCContext> Ctx;
+ // The disassembler for the target architecture.
+ std::unique_ptr<const llvm::MCDisassembler> DisAsm;
+ // The instruction printer for the target architecture.
+ std::unique_ptr<llvm::MCInstPrinter> IP;
+ // The options used to set up the disassembler.
+ uint64_t Options;
+ // The CPU string.
+ std::string CPU;
+
+public:
+ // Comment stream and backing vector.
+ SmallString<128> CommentsToEmit;
+ raw_svector_ostream CommentStream;
+
+ LLVMDisasmContext(std::string tripleName, void *disInfo, int tagType,
+ LLVMOpInfoCallback getOpInfo,
+ LLVMSymbolLookupCallback symbolLookUp,
+ const Target *theTarget, const MCAsmInfo *mAI,
+ const MCRegisterInfo *mRI,
+ const MCSubtargetInfo *mSI,
+ const MCInstrInfo *mII,
+ llvm::MCContext *ctx, const MCDisassembler *disAsm,
+ MCInstPrinter *iP) : TripleName(tripleName),
+ DisInfo(disInfo), TagType(tagType), GetOpInfo(getOpInfo),
+ SymbolLookUp(symbolLookUp), TheTarget(theTarget),
+ Options(0),
+ CommentStream(CommentsToEmit) {
+ MAI.reset(mAI);
+ MRI.reset(mRI);
+ MSI.reset(mSI);
+ MII.reset(mII);
+ Ctx.reset(ctx);
+ DisAsm.reset(disAsm);
+ IP.reset(iP);
+ }
+ const std::string &getTripleName() const { return TripleName; }
+ void *getDisInfo() const { return DisInfo; }
+ int getTagType() const { return TagType; }
+ LLVMOpInfoCallback getGetOpInfo() const { return GetOpInfo; }
+ LLVMSymbolLookupCallback getSymbolLookupCallback() const {
+ return SymbolLookUp;
+ }
+ const Target *getTarget() const { return TheTarget; }
+ const MCDisassembler *getDisAsm() const { return DisAsm.get(); }
+ const MCAsmInfo *getAsmInfo() const { return MAI.get(); }
+ const MCInstrInfo *getInstrInfo() const { return MII.get(); }
+ const MCRegisterInfo *getRegisterInfo() const { return MRI.get(); }
+ const MCSubtargetInfo *getSubtargetInfo() const { return MSI.get(); }
+ MCInstPrinter *getIP() { return IP.get(); }
+ void setIP(MCInstPrinter *NewIP) { IP.reset(NewIP); }
+ uint64_t getOptions() const { return Options; }
+ void addOptions(uint64_t Options) { this->Options |= Options; }
+ StringRef getCPU() const { return CPU; }
+ void setCPU(const char *CPU) { this->CPU = CPU; }
+};
+
+} // namespace llvm
+
+#endif
diff --git a/contrib/llvm/lib/MC/MCDisassembler/MCDisassembler.cpp b/contrib/llvm/lib/MC/MCDisassembler/MCDisassembler.cpp
new file mode 100644
index 0000000..1084e5e
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCDisassembler/MCDisassembler.cpp
@@ -0,0 +1,39 @@
+//===-- MCDisassembler.cpp - Disassembler interface -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCDisassembler.h"
+#include "llvm/MC/MCExternalSymbolizer.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+MCDisassembler::~MCDisassembler() {
+}
+
+bool MCDisassembler::tryAddingSymbolicOperand(MCInst &Inst, int64_t Value,
+ uint64_t Address, bool IsBranch,
+ uint64_t Offset,
+ uint64_t InstSize) const {
+ raw_ostream &cStream = CommentStream ? *CommentStream : nulls();
+ if (Symbolizer)
+ return Symbolizer->tryAddingSymbolicOperand(Inst, cStream, Value, Address,
+ IsBranch, Offset, InstSize);
+ return false;
+}
+
+void MCDisassembler::tryAddingPcLoadReferenceComment(int64_t Value,
+ uint64_t Address) const {
+ raw_ostream &cStream = CommentStream ? *CommentStream : nulls();
+ if (Symbolizer)
+ Symbolizer->tryAddingPcLoadReferenceComment(cStream, Value, Address);
+}
+
+void MCDisassembler::setSymbolizer(std::unique_ptr<MCSymbolizer> Symzer) {
+ Symbolizer = std::move(Symzer);
+}
diff --git a/contrib/llvm/lib/MC/MCDisassembler/MCExternalSymbolizer.cpp b/contrib/llvm/lib/MC/MCDisassembler/MCExternalSymbolizer.cpp
new file mode 100644
index 0000000..68948d3
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCDisassembler/MCExternalSymbolizer.cpp
@@ -0,0 +1,196 @@
+//===-- MCExternalSymbolizer.cpp - External symbolizer --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCExternalSymbolizer.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstring>
+
+using namespace llvm;
+
+// This function tries to add a symbolic operand in place of the immediate
+// Value in the MCInst. The immediate Value has had any PC adjustment made by
+// the caller. If the instruction is a branch instruction then IsBranch is true,
+// else false. If the getOpInfo() function was set as part of the
+// setupForSymbolicDisassembly() call then that function is called to get any
+// symbolic information at the Address for this instruction. If that returns
+// non-zero then the symbolic information it returns is used to create an MCExpr
+// and that is added as an operand to the MCInst. If getOpInfo() returns zero
+// and IsBranch is true then a symbol look up for Value is done and if a symbol
+// is found an MCExpr is created with that, else an MCExpr with Value is
+// created. This function returns true if it adds an operand to the MCInst and
+// false otherwise.
+bool MCExternalSymbolizer::tryAddingSymbolicOperand(MCInst &MI,
+ raw_ostream &cStream,
+ int64_t Value,
+ uint64_t Address,
+ bool IsBranch,
+ uint64_t Offset,
+ uint64_t InstSize) {
+ struct LLVMOpInfo1 SymbolicOp;
+ std::memset(&SymbolicOp, '\0', sizeof(struct LLVMOpInfo1));
+ SymbolicOp.Value = Value;
+
+ if (!GetOpInfo ||
+ !GetOpInfo(DisInfo, Address, Offset, InstSize, 1, &SymbolicOp)) {
+ // Clear SymbolicOp.Value from above and also all other fields.
+ std::memset(&SymbolicOp, '\0', sizeof(struct LLVMOpInfo1));
+
+ // At this point, GetOpInfo() did not find any relocation information about
+ // this operand and we are left to use the SymbolLookUp() call back to guess
+ // if the Value is the address of a symbol. In the case this is a branch
+ // that always makes sense to guess. But in the case of an immediate it is
+ // a bit more questionable if it is an address of a symbol or some other
+ // reference. So if the immediate Value comes from a width of 1 byte,
+ // InstSize, we will not guess it is an address of a symbol. Because in
+ // object files assembled starting at address 0 this usually leads to
+ // incorrect symbolication.
+ if (!SymbolLookUp || (InstSize == 1 && !IsBranch))
+ return false;
+
+ uint64_t ReferenceType;
+ if (IsBranch)
+ ReferenceType = LLVMDisassembler_ReferenceType_In_Branch;
+ else
+ ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
+ const char *ReferenceName;
+ const char *Name = SymbolLookUp(DisInfo, Value, &ReferenceType, Address,
+ &ReferenceName);
+ if (Name) {
+ SymbolicOp.AddSymbol.Name = Name;
+ SymbolicOp.AddSymbol.Present = true;
+ // If Name is a C++ symbol name put the human readable name in a comment.
+ if(ReferenceType == LLVMDisassembler_ReferenceType_DeMangled_Name)
+ cStream << ReferenceName;
+ }
+ // For branches always create an MCExpr so it gets printed as hex address.
+ else if (IsBranch) {
+ SymbolicOp.Value = Value;
+ }
+ if(ReferenceType == LLVMDisassembler_ReferenceType_Out_SymbolStub)
+ cStream << "symbol stub for: " << ReferenceName;
+ else if(ReferenceType == LLVMDisassembler_ReferenceType_Out_Objc_Message)
+ cStream << "Objc message: " << ReferenceName;
+ if (!Name && !IsBranch)
+ return false;
+ }
+
+ const MCExpr *Add = nullptr;
+ if (SymbolicOp.AddSymbol.Present) {
+ if (SymbolicOp.AddSymbol.Name) {
+ StringRef Name(SymbolicOp.AddSymbol.Name);
+ MCSymbol *Sym = Ctx.getOrCreateSymbol(Name);
+ Add = MCSymbolRefExpr::create(Sym, Ctx);
+ } else {
+ Add = MCConstantExpr::create((int)SymbolicOp.AddSymbol.Value, Ctx);
+ }
+ }
+
+ const MCExpr *Sub = nullptr;
+ if (SymbolicOp.SubtractSymbol.Present) {
+ if (SymbolicOp.SubtractSymbol.Name) {
+ StringRef Name(SymbolicOp.SubtractSymbol.Name);
+ MCSymbol *Sym = Ctx.getOrCreateSymbol(Name);
+ Sub = MCSymbolRefExpr::create(Sym, Ctx);
+ } else {
+ Sub = MCConstantExpr::create((int)SymbolicOp.SubtractSymbol.Value, Ctx);
+ }
+ }
+
+ const MCExpr *Off = nullptr;
+ if (SymbolicOp.Value != 0)
+ Off = MCConstantExpr::create(SymbolicOp.Value, Ctx);
+
+ const MCExpr *Expr;
+ if (Sub) {
+ const MCExpr *LHS;
+ if (Add)
+ LHS = MCBinaryExpr::createSub(Add, Sub, Ctx);
+ else
+ LHS = MCUnaryExpr::createMinus(Sub, Ctx);
+ if (Off)
+ Expr = MCBinaryExpr::createAdd(LHS, Off, Ctx);
+ else
+ Expr = LHS;
+ } else if (Add) {
+ if (Off)
+ Expr = MCBinaryExpr::createAdd(Add, Off, Ctx);
+ else
+ Expr = Add;
+ } else {
+ if (Off)
+ Expr = Off;
+ else
+ Expr = MCConstantExpr::create(0, Ctx);
+ }
+
+ Expr = RelInfo->createExprForCAPIVariantKind(Expr, SymbolicOp.VariantKind);
+ if (!Expr)
+ return false;
+
+ MI.addOperand(MCOperand::createExpr(Expr));
+ return true;
+}
+
+// This function tries to add a comment as to what is being referenced by a load
+// instruction with the base register that is the Pc. These can often be values
+// in a literal pool near the Address of the instruction. The Address of the
+// instruction and its immediate Value are used as a possible literal pool entry.
+// The SymbolLookUp call back will return the name of a symbol referenced by the
+// literal pool's entry if the referenced address is that of a symbol. Or it
+// will return a pointer to a literal 'C' string if the referenced address of
+// the literal pool's entry is an address into a section with C string literals.
+// Or if the reference is to an Objective-C data structure it will return a
+// specific reference type for it and a string.
+void MCExternalSymbolizer::tryAddingPcLoadReferenceComment(raw_ostream &cStream,
+ int64_t Value,
+ uint64_t Address) {
+ if (SymbolLookUp) {
+ uint64_t ReferenceType = LLVMDisassembler_ReferenceType_In_PCrel_Load;
+ const char *ReferenceName;
+ (void)SymbolLookUp(DisInfo, Value, &ReferenceType, Address, &ReferenceName);
+ if(ReferenceType == LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr)
+ cStream << "literal pool symbol address: " << ReferenceName;
+ else if(ReferenceType ==
+ LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr) {
+ cStream << "literal pool for: \"";
+ cStream.write_escaped(ReferenceName);
+ cStream << "\"";
+ }
+ else if(ReferenceType ==
+ LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref)
+ cStream << "Objc cfstring ref: @\"" << ReferenceName << "\"";
+ else if(ReferenceType ==
+ LLVMDisassembler_ReferenceType_Out_Objc_Message)
+ cStream << "Objc message: " << ReferenceName;
+ else if(ReferenceType ==
+ LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref)
+ cStream << "Objc message ref: " << ReferenceName;
+ else if(ReferenceType ==
+ LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref)
+ cStream << "Objc selector ref: " << ReferenceName;
+ else if(ReferenceType ==
+ LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref)
+ cStream << "Objc class ref: " << ReferenceName;
+ }
+}
+
+namespace llvm {
+MCSymbolizer *createMCSymbolizer(StringRef TT, LLVMOpInfoCallback GetOpInfo,
+ LLVMSymbolLookupCallback SymbolLookUp,
+ void *DisInfo, MCContext *Ctx,
+ std::unique_ptr<MCRelocationInfo> &&RelInfo) {
+ assert(Ctx && "No MCContext given for symbolic disassembly");
+
+ return new MCExternalSymbolizer(*Ctx, std::move(RelInfo), GetOpInfo,
+ SymbolLookUp, DisInfo);
+}
+}
diff --git a/contrib/llvm/lib/MC/MCDisassembler/MCRelocationInfo.cpp b/contrib/llvm/lib/MC/MCDisassembler/MCRelocationInfo.cpp
new file mode 100644
index 0000000..43005e7
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCDisassembler/MCRelocationInfo.cpp
@@ -0,0 +1,40 @@
+//==-- MCRelocationInfo.cpp ------------------------------------------------==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCRelocationInfo.h"
+#include "llvm-c/Disassembler.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/TargetRegistry.h"
+
+using namespace llvm;
+
+MCRelocationInfo::MCRelocationInfo(MCContext &Ctx)
+ : Ctx(Ctx) {
+}
+
+MCRelocationInfo::~MCRelocationInfo() {
+}
+
+const MCExpr *
+MCRelocationInfo::createExprForRelocation(object::RelocationRef Rel) {
+ return nullptr;
+}
+
+const MCExpr *
+MCRelocationInfo::createExprForCAPIVariantKind(const MCExpr *SubExpr,
+ unsigned VariantKind) {
+ if (VariantKind != LLVMDisassembler_VariantKind_None)
+ return nullptr;
+ return SubExpr;
+}
+
+MCRelocationInfo *llvm::createMCRelocationInfo(const Triple &TT,
+ MCContext &Ctx) {
+ return new MCRelocationInfo(Ctx);
+}
OpenPOWER on IntegriCloud