summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/MC/MCDisassembler.h57
-rw-r--r--include/llvm/MC/MCExternalSymbolizer.h58
-rw-r--r--include/llvm/MC/MCObjectSymbolizer.h74
-rw-r--r--include/llvm/MC/MCRelocationInfo.h55
-rw-r--r--include/llvm/MC/MCSymbolizer.h81
-rw-r--r--include/llvm/Support/TargetRegistry.h34
-rw-r--r--lib/MC/CMakeLists.txt4
-rw-r--r--lib/MC/MCDisassembler.cpp37
-rw-r--r--lib/MC/MCDisassembler/Disassembler.cpp10
-rw-r--r--lib/MC/MCExternalSymbolizer.cpp146
-rw-r--r--lib/MC/MCObjectSymbolizer.cpp175
-rw-r--r--lib/MC/MCRelocationInfo.cpp39
-rw-r--r--lib/MC/MCSymbolizer.cpp20
-rw-r--r--lib/Target/ARM/Disassembler/ARMDisassembler.cpp111
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp14
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h4
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMMachORelocationInfo.cpp43
-rw-r--r--lib/Target/ARM/MCTargetDesc/CMakeLists.txt1
-rw-r--r--lib/Target/X86/Disassembler/X86Disassembler.cpp100
-rw-r--r--lib/Target/X86/MCTargetDesc/CMakeLists.txt2
-rw-r--r--lib/Target/X86/MCTargetDesc/X86ELFRelocationInfo.cpp135
-rw-r--r--lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp16
-rw-r--r--lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h7
-rw-r--r--lib/Target/X86/MCTargetDesc/X86MachORelocationInfo.cpp117
-rw-r--r--test/Object/X86/objdump-disassembly-symbolic.test30
-rw-r--r--tools/llvm-objdump/llvm-objdump.cpp57
-rw-r--r--tools/llvm-objdump/llvm-objdump.h10
27 files changed, 1185 insertions, 252 deletions
diff --git a/include/llvm/MC/MCDisassembler.h b/include/llvm/MC/MCDisassembler.h
index 36fbcb02d9..5ad2d98019 100644
--- a/include/llvm/MC/MCDisassembler.h
+++ b/include/llvm/MC/MCDisassembler.h
@@ -10,6 +10,9 @@
#define LLVM_MC_MCDISASSEMBLER_H
#include "llvm-c/Disassembler.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/MC/MCSymbolizer.h"
+#include "llvm/MC/MCRelocationInfo.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
@@ -53,9 +56,8 @@ public:
};
/// Constructor - Performs initial setup for the disassembler.
- MCDisassembler(const MCSubtargetInfo &STI) : GetOpInfo(0), SymbolLookUp(0),
- DisInfo(0), Ctx(0),
- STI(STI), CommentStream(0) {}
+ MCDisassembler(const MCSubtargetInfo &STI) : STI(STI), Symbolizer(0),
+ CommentStream(0) {}
virtual ~MCDisassembler();
@@ -82,39 +84,32 @@ public:
raw_ostream &vStream,
raw_ostream &cStream) const = 0;
-private:
- //
- // Hooks for symbolic disassembly via the public 'C' interface.
- //
- // The function to get the symbolic information for operands.
- LLVMOpInfoCallback GetOpInfo;
- // The function to lookup a symbol name.
- LLVMSymbolLookupCallback SymbolLookUp;
- // The pointer to the block of symbolic information for above call back.
- void *DisInfo;
- // The assembly context for creating symbols and MCExprs in place of
- // immediate operands when there is symbolic information.
- MCContext *Ctx;
protected:
// Subtarget information, for instruction decoding predicates if required.
const MCSubtargetInfo &STI;
+private:
+ OwningPtr<MCSymbolizer> Symbolizer;
+
public:
- void setupForSymbolicDisassembly(LLVMOpInfoCallback getOpInfo,
- LLVMSymbolLookupCallback symbolLookUp,
- void *disInfo,
- MCContext *ctx) {
- GetOpInfo = getOpInfo;
- SymbolLookUp = symbolLookUp;
- DisInfo = disInfo;
- Ctx = ctx;
- }
- LLVMOpInfoCallback getLLVMOpInfoCallback() const { return GetOpInfo; }
- LLVMSymbolLookupCallback getLLVMSymbolLookupCallback() const {
- return SymbolLookUp;
- }
- void *getDisInfoBlock() const { return DisInfo; }
- MCContext *getMCContext() const { return Ctx; }
+ // Helpers around MCSymbolizer
+ bool tryAddingSymbolicOperand(MCInst &Inst,
+ int64_t Value,
+ uint64_t Address, bool IsBranch,
+ uint64_t Offset, uint64_t InstSize) const;
+
+ void tryAddingPcLoadReferenceComment(int64_t Value, uint64_t Address) const;
+
+ /// Set \p Symzer as the current symbolizer.
+ /// This takes ownership of \p Symzer, and deletes the previously set one.
+ void setSymbolizer(OwningPtr<MCSymbolizer> &Symzer);
+
+ /// Sets up an external symbolizer that uses the C API callbacks.
+ void setupForSymbolicDisassembly(LLVMOpInfoCallback GetOpInfo,
+ LLVMSymbolLookupCallback SymbolLookUp,
+ void *DisInfo,
+ MCContext *Ctx,
+ OwningPtr<MCRelocationInfo> &RelInfo);
// Marked mutable because we cache it inside the disassembler, rather than
// having to pass it around as an argument through all the autogenerated code.
diff --git a/include/llvm/MC/MCExternalSymbolizer.h b/include/llvm/MC/MCExternalSymbolizer.h
new file mode 100644
index 0000000000..c942adca3b
--- /dev/null
+++ b/include/llvm/MC/MCExternalSymbolizer.h
@@ -0,0 +1,58 @@
+//===-- llvm/MC/MCExternalSymbolizer.h - ------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the declaration of the MCExternalSymbolizer class, which
+// enables library users to provide callbacks (through the C API) to do the
+// symbolization externally.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_MC_MCEXTERNALSYMBOLIZER_H
+#define LLVM_MC_MCEXTERNALSYMBOLIZER_H
+
+#include "llvm-c/Disassembler.h"
+#include "llvm/MC/MCSymbolizer.h"
+
+namespace llvm {
+
+/// \brief Symbolize using user-provided, C API, callbacks.
+///
+/// See llvm-c/Disassembler.h.
+class MCExternalSymbolizer : public MCSymbolizer {
+
+ /// \name Hooks for symbolic disassembly via the public 'C' interface.
+ /// @{
+ /// The function to get the symbolic information for operands.
+ LLVMOpInfoCallback GetOpInfo;
+ /// The function to lookup a symbol name.
+ LLVMSymbolLookupCallback SymbolLookUp;
+ /// The pointer to the block of symbolic information for above call back.
+ void *DisInfo;
+ /// @}
+
+public:
+ MCExternalSymbolizer(MCContext &Ctx,
+ OwningPtr<MCRelocationInfo> &RelInfo,
+ LLVMOpInfoCallback getOpInfo,
+ LLVMSymbolLookupCallback symbolLookUp,
+ void *disInfo)
+ : MCSymbolizer(Ctx, RelInfo),
+ GetOpInfo(getOpInfo), SymbolLookUp(symbolLookUp), DisInfo(disInfo) {}
+
+ bool tryAddingSymbolicOperand(MCInst &MI, raw_ostream &CommentStream,
+ int64_t Value,
+ uint64_t Address, bool IsBranch,
+ uint64_t Offset, uint64_t InstSize);
+ void tryAddingPcLoadReferenceComment(raw_ostream &CommentStream,
+ int64_t Value, uint64_t Address);
+};
+
+}
+
+#endif
diff --git a/include/llvm/MC/MCObjectSymbolizer.h b/include/llvm/MC/MCObjectSymbolizer.h
new file mode 100644
index 0000000000..0e3a17b8f7
--- /dev/null
+++ b/include/llvm/MC/MCObjectSymbolizer.h
@@ -0,0 +1,74 @@
+//===-- llvm/MC/MCObjectSymbolizer.h --------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the MCObjectSymbolizer class, an MCSymbolizer that is
+// backed by an object::ObjectFile.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_MC_MCOBJECTSYMBOLIZER_H
+#define LLVM_MC_MCOBJECTSYMBOLIZER_H
+
+#include "llvm/ADT/IntervalMap.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/MC/MCSymbolizer.h"
+#include "llvm/Object/ObjectFile.h"
+
+namespace llvm {
+
+class MCExpr;
+class MCInst;
+class MCRelocationInfo;
+class raw_ostream;
+
+/// \brief An ObjectFile-backed symbolizer.
+class MCObjectSymbolizer : public MCSymbolizer {
+protected:
+ const object::ObjectFile *Obj;
+
+ typedef DenseMap<uint64_t, object::RelocationRef> AddrToRelocMap;
+ // FIXME: Working around a missing SectionRef operator!= by storing
+ // DataRefImpl.p instead of SectionRef. Feel free to improve!
+ typedef IntervalMap<uint64_t, uintptr_t> AddrToSectionMap;
+
+ AddrToSectionMap::Allocator AddrToSectionAllocator;
+ AddrToSectionMap AddrToSection;
+
+ // Map a load address to the first relocation that applies there. As far as I
+ // know, if there are several relocations at the exact same address, they are
+ // related and the others can be determined from the first that was found in
+ // the relocation table. For instance, on x86-64 mach-o, a SUBTRACTOR
+ // relocation (referencing the minuend symbol) is followed by an UNSIGNED
+ // relocation (referencing the subtrahend symbol).
+ AddrToRelocMap AddrToReloc;
+
+ MCObjectSymbolizer(MCContext &Ctx, OwningPtr<MCRelocationInfo> &RelInfo,
+ const object::ObjectFile *Obj);
+
+public:
+ /// \name Overridden MCSymbolizer methods:
+ /// @{
+ bool tryAddingSymbolicOperand(MCInst &MI, raw_ostream &cStream,
+ int64_t Value,
+ uint64_t Address, bool IsBranch,
+ uint64_t Offset, uint64_t InstSize);
+
+ void tryAddingPcLoadReferenceComment(raw_ostream &cStream,
+ int64_t Value, uint64_t Address);
+ /// @}
+
+ /// \brief Create an object symbolizer for \p Obj.
+ static MCObjectSymbolizer *
+ createObjectSymbolizer(MCContext &Ctx, OwningPtr<MCRelocationInfo> &RelInfo,
+ const object::ObjectFile *Obj);
+};
+
+}
+
+#endif
diff --git a/include/llvm/MC/MCRelocationInfo.h b/include/llvm/MC/MCRelocationInfo.h
new file mode 100644
index 0000000000..9dab90099b
--- /dev/null
+++ b/include/llvm/MC/MCRelocationInfo.h
@@ -0,0 +1,55 @@
+//==-- llvm/MC/MCRelocationInfo.h --------------------------------*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the MCRelocationInfo class, which provides methods to
+// create MCExprs from relocations, either found in an object::ObjectFile
+// (object::RelocationRef), or provided through the C API.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_MC_MCRELOCATIONINFO_H
+#define LLVM_MC_MCRELOCATIONINFO_H
+
+#include "llvm/Support/Compiler.h"
+
+namespace llvm {
+
+namespace object {
+class RelocationRef;
+}
+class MCExpr;
+class MCContext;
+
+/// \brief Create MCExprs from relocations found in an object file.
+class MCRelocationInfo {
+ MCRelocationInfo(const MCRelocationInfo &) LLVM_DELETED_FUNCTION;
+ void operator=(const MCRelocationInfo &) LLVM_DELETED_FUNCTION;
+
+protected:
+ MCContext &Ctx;
+
+public:
+ MCRelocationInfo(MCContext &Ctx);
+ virtual ~MCRelocationInfo();
+
+ /// \brief Create an MCExpr for the relocation \p Rel.
+ /// \returns If possible, an MCExpr corresponding to Rel, else 0.
+ virtual const MCExpr *createExprForRelocation(object::RelocationRef Rel);
+
+ /// \brief Create an MCExpr for the target-specific \p VariantKind.
+ /// The VariantKinds are defined in llvm-c/Disassembler.h.
+ /// Used by MCExternalSymbolizer.
+ /// \returns If possible, an MCExpr corresponding to VariantKind, else 0.
+ virtual const MCExpr *createExprForCAPIVariantKind(const MCExpr *SubExpr,
+ unsigned VariantKind);
+};
+
+}
+
+#endif
diff --git a/include/llvm/MC/MCSymbolizer.h b/include/llvm/MC/MCSymbolizer.h
new file mode 100644
index 0000000000..e42a2146dc
--- /dev/null
+++ b/include/llvm/MC/MCSymbolizer.h
@@ -0,0 +1,81 @@
+//===-- llvm/MC/MCSymbolizer.h - MCSymbolizer class -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the declaration of the MCSymbolizer class, which is used
+// to symbolize instructions decoded from an object, that is, transform their
+// immediate operands to MCExprs.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_MC_MCSYMBOLIZER_H
+#define LLVM_MC_MCSYMBOLIZER_H
+
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/MC/MCRelocationInfo.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/DataTypes.h"
+
+namespace llvm {
+
+class MCContext;
+class MCInst;
+class raw_ostream;
+
+/// \brief Symbolize and annotate disassembled instructions.
+///
+/// For now this mimics the old symbolization logic (from both ARM and x86), that
+/// relied on user-provided (C API) callbacks to do the actual symbol lookup in
+/// the object file. This was moved to MCExternalSymbolizer.
+/// A better API would not rely on actually calling the two methods here from
+/// inside each disassembler, but would use the instr info to determine what
+/// operands are actually symbolizable, and in what way. I don't think this
+/// information exists right now.
+class MCSymbolizer {
+ MCSymbolizer(const MCSymbolizer &) LLVM_DELETED_FUNCTION;
+ void operator=(const MCSymbolizer &) LLVM_DELETED_FUNCTION;
+
+protected:
+ MCContext &Ctx;
+ OwningPtr<MCRelocationInfo> RelInfo;
+
+public:
+ /// \brief Construct an MCSymbolizer, taking ownership of \p RelInfo.
+ MCSymbolizer(MCContext &Ctx, OwningPtr<MCRelocationInfo> &RelInfo);
+ virtual ~MCSymbolizer();
+
+ /// \brief Try to add a symbolic operand instead of \p Value to the MCInst.
+ ///
+ /// Instead of having a difficult to read immediate, a symbolic operand would
+ /// represent this immediate in a more understandable way, for instance as a
+ /// symbol or an offset from a symbol. Relocations can also be used to enrich
+ /// the symbolic expression.
+ /// @param Inst - The MCInst where to insert the symbolic operand.
+ /// @param cStream - Stream to print comments and annotations on.
+ /// @param Value - Operand value, pc-adjusted by the caller if necessary.
+ /// @param Address - Load address of the instruction.
+ /// @param IsBranch - Is the instruction a branch?
+ /// @param Offset - Byte offset of the operand inside the inst.
+ /// @param InstSize - Size of the instruction in bytes.
+ /// @return Whether a symbolic operand was added.
+ virtual bool tryAddingSymbolicOperand(MCInst &Inst, raw_ostream &cStream,
+ int64_t Value, uint64_t Address,
+ bool IsBranch, uint64_t Offset,
+ uint64_t InstSize) = 0;
+
+ /// \brief Try to add a comment on the PC-relative load.
+ /// For instance, in Mach-O, this is used to add annotations to instructions
+ /// that use C string literals, as found in __cstring.
+ virtual void tryAddingPcLoadReferenceComment(raw_ostream &cStream,
+ int64_t Value,
+ uint64_t Address) = 0;
+};
+
+}
+
+#endif
diff --git a/include/llvm/Support/TargetRegistry.h b/include/llvm/Support/TargetRegistry.h
index e1f6706618..b4e380b344 100644
--- a/include/llvm/Support/TargetRegistry.h
+++ b/include/llvm/Support/TargetRegistry.h
@@ -41,6 +41,7 @@ namespace llvm {
class MCRegisterInfo;
class MCStreamer;
class MCSubtargetInfo;
+ class MCRelocationInfo;
class MCTargetAsmParser;
class TargetMachine;
class TargetOptions;
@@ -56,6 +57,8 @@ namespace llvm {
MCAsmBackend *TAB,
bool ShowInst);
+ MCRelocationInfo *createMCRelocationInfo(MCContext &Ctx);
+
/// Target - Wrapper for Target specific information.
///
/// For registration purposes, this is a POD type so that targets can be
@@ -127,6 +130,8 @@ namespace llvm {
MCCodeEmitter *CE,
MCAsmBackend *TAB,
bool ShowInst);
+ typedef MCRelocationInfo *(*MCRelocationInfoCtorTy)(StringRef TT,
+ MCContext &Ctx);
private:
/// Next - The next registered target in the linked list, maintained by the
@@ -206,6 +211,10 @@ namespace llvm {
/// AsmStreamer, if registered (default = llvm::createAsmStreamer).
AsmStreamerCtorTy AsmStreamerCtorFn;
+ /// MCRelocationInfoCtorFn - Construction function for this target's
+ /// MCRelocationInfo, if registered (default = llvm::createMCRelocationInfo)
+ MCRelocationInfoCtorTy MCRelocationInfoCtorFn;
+
public:
Target() : AsmStreamerCtorFn(llvm::createAsmStreamer) {}
@@ -433,6 +442,16 @@ namespace llvm {
useDwarfDirectory, InstPrint, CE, TAB, ShowInst);
}
+ /// createMCRelocationInfo - Create a target specific MCRelocationInfo.
+ ///
+ /// \param TT The target triple.
+ /// \param Ctx The target context.
+ MCRelocationInfo *
+ createMCRelocationInfo(StringRef TT, MCContext &Ctx) const {
+ // MCRelocationInfoCtorFn defaults to createMCRelocationInfo
+ return MCRelocationInfoCtorFn(TT, Ctx);
+ }
+
/// @}
};
@@ -760,6 +779,21 @@ namespace llvm {
T.AsmStreamerCtorFn = Fn;
}
+ /// RegisterMCRelocationInfo - Register an MCRelocationInfo
+ /// implementation for the given target.
+ ///
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
+ ///
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct an MCRelocationInfo for the target.
+ static void RegisterMCRelocationInfo(Target &T,
+ Target::MCRelocationInfoCtorTy Fn) {
+ if (!T.MCRelocationInfoCtorFn)
+ T.MCRelocationInfoCtorFn = Fn;
+ }
+
/// @}
};
diff --git a/lib/MC/CMakeLists.txt b/lib/MC/CMakeLists.txt
index db882c020b..5377c5c8d8 100644
--- a/lib/MC/CMakeLists.txt
+++ b/lib/MC/CMakeLists.txt
@@ -16,6 +16,7 @@ add_llvm_library(LLVMMC
MCELFObjectTargetWriter.cpp
MCELFStreamer.cpp
MCExpr.cpp
+ MCExternalSymbolizer.cpp
MCInst.cpp
MCInstPrinter.cpp
MCInstrAnalysis.cpp
@@ -26,9 +27,11 @@ add_llvm_library(LLVMMC
MCNullStreamer.cpp
MCObjectFileInfo.cpp
MCObjectStreamer.cpp
+ MCObjectSymbolizer.cpp
MCObjectWriter.cpp
MCPureStreamer.cpp
MCRegisterInfo.cpp
+ MCRelocationInfo.cpp
MCSection.cpp
MCSectionCOFF.cpp
MCSectionELF.cpp
@@ -36,6 +39,7 @@ add_llvm_library(LLVMMC
MCStreamer.cpp
MCSubtargetInfo.cpp
MCSymbol.cpp
+ MCSymbolizer.cpp
MCValue.cpp
MCWin64EH.cpp
MachObjectWriter.cpp
diff --git a/lib/MC/MCDisassembler.cpp b/lib/MC/MCDisassembler.cpp
index 0809690646..c4cdbba26e 100644
--- a/lib/MC/MCDisassembler.cpp
+++ b/lib/MC/MCDisassembler.cpp
@@ -8,7 +8,44 @@
//===----------------------------------------------------------------------===//
#include "llvm/MC/MCDisassembler.h"
+#include "llvm/MC/MCExternalSymbolizer.h"
+#include "llvm/Support/raw_ostream.h"
+
using namespace llvm;
MCDisassembler::~MCDisassembler() {
}
+
+void
+MCDisassembler::setupForSymbolicDisassembly(
+ LLVMOpInfoCallback GetOpInfo,
+ LLVMSymbolLookupCallback SymbolLookUp,
+ void *DisInfo,
+ MCContext *Ctx,
+ OwningPtr<MCRelocationInfo> &RelInfo) {
+ assert(Ctx != 0 && "No MCContext given for symbolic disassembly");
+ Symbolizer.reset(new MCExternalSymbolizer(*Ctx, RelInfo, GetOpInfo,
+ SymbolLookUp, DisInfo));
+}
+
+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(OwningPtr<MCSymbolizer> &Symzer) {
+ Symbolizer.reset(Symzer.take());
+}
diff --git a/lib/MC/MCDisassembler/Disassembler.cpp b/lib/MC/MCDisassembler/Disassembler.cpp
index c80a167ace..ba76936961 100644
--- a/lib/MC/MCDisassembler/Disassembler.cpp
+++ b/lib/MC/MCDisassembler/Disassembler.cpp
@@ -16,6 +16,7 @@
#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/Support/ErrorHandling.h"
#include "llvm/Support/MemoryObject.h"
@@ -73,7 +74,14 @@ LLVMDisasmContextRef LLVMCreateDisasmCPU(const char *Triple, const char *CPU,
MCDisassembler *DisAsm = TheTarget->createMCDisassembler(*STI);
if (!DisAsm)
return 0;
- DisAsm->setupForSymbolicDisassembly(GetOpInfo, SymbolLookUp, DisInfo, Ctx);
+
+ OwningPtr<MCRelocationInfo> RelInfo(
+ TheTarget->createMCRelocationInfo(Triple, *Ctx));
+ if (!RelInfo)
+ return 0;
+
+ DisAsm->setupForSymbolicDisassembly(GetOpInfo, SymbolLookUp, DisInfo,
+ Ctx, RelInfo);
// Set up the instruction printer.
int AsmPrinterVariant = MAI->getAssemblerDialect();
diff --git a/lib/MC/MCExternalSymbolizer.cpp b/lib/MC/MCExternalSymbolizer.cpp
new file mode 100644
index 0000000000..5fb52b3bf6
--- /dev/null
+++ b/lib/MC/MCExternalSymbolizer.cpp
@@ -0,0 +1,146 @@
+//===-- lib/MC/MCExternalSymbolizer.cpp - External symbolizer ---*- C++ -*-===//
+//
+// 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));
+ if (!SymbolLookUp)
+ 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;
+ }
+ // 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;
+ if (!Name && !IsBranch)
+ return false;
+ }
+
+ const MCExpr *Add = NULL;
+ 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 = NULL;
+ 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 = NULL;
+ 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 != 0)
+ Expr = MCBinaryExpr::CreateAdd(LHS, Off, Ctx);
+ else
+ Expr = LHS;
+ } else if (Add) {
+ if (Off != 0)
+ Expr = MCBinaryExpr::CreateAdd(Add, Off, Ctx);
+ else
+ Expr = Add;
+ } else {
+ if (Off != 0)
+ 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.
+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 ||
+ ReferenceType == LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr)
+ cStream << "literal pool for: " << ReferenceName;
+ }
+}
diff --git a/lib/MC/MCObjectSymbolizer.cpp b/lib/MC/MCObjectSymbolizer.cpp
new file mode 100644
index 0000000000..e1d504ec8e
--- /dev/null
+++ b/lib/MC/MCObjectSymbolizer.cpp
@@ -0,0 +1,175 @@
+//===-- lib/MC/MCObjectSymbolizer.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/MCObjectSymbolizer.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCRelocationInfo.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Object/MachO.h"
+#include "llvm/Object/ELF.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+using namespace object;
+
+//===- MCMachObjectSymbolizer ---------------------------------------------===//
+
+namespace {
+class MCMachObjectSymbolizer : public MCObjectSymbolizer {
+public:
+ MCMachObjectSymbolizer(MCContext &Ctx, OwningPtr<MCRelocationInfo> &RelInfo,
+ const object::MachOObjectFile *MachOOF)
+ : MCObjectSymbolizer(Ctx, RelInfo, MachOOF)
+ {}
+
+ void tryAddingPcLoadReferenceComment(raw_ostream &cStream,
+ int64_t Value, uint64_t Address) {
+ AddrToRelocMap::iterator RI = AddrToReloc.find(Address);
+ if (RI != AddrToReloc.end()) {
+ const MCExpr *RelExpr = RelInfo->createExprForRelocation(RI->second);
+ if (!RelExpr || RelExpr->EvaluateAsAbsolute(Value) == false)
+ return;
+ }
+ uint64_t Addr = Value;
+ AddrToSectionMap::const_iterator SI = AddrToSection.find(Addr);
+ if (SI.valid()) {
+ DataRefImpl DRI; DRI.p = *SI;
+ SectionRef S(DRI, Obj);
+ StringRef Name; S.getName(Name);
+ if (Name == "__cstring") {
+ StringRef Contents;
+ S.getContents(Contents);
+ Contents = Contents.substr(Addr - SI.start());
+ cStream << " ## literal pool for: "
+ << Contents.substr(0, Contents.find_first_of(0));
+ }
+ }
+ }
+};
+} // End unnamed namespace
+
+//===- MCObjectSymbolizer -------------------------------------------------===//
+
+MCObjectSymbolizer::MCObjectSymbolizer(MCContext &Ctx,
+ OwningPtr<MCRelocationInfo> &RelInfo,
+ const ObjectFile *Obj)
+ : MCSymbolizer(Ctx, RelInfo), Obj(Obj),
+ AddrToSectionAllocator(), AddrToSection(AddrToSectionAllocator),
+ AddrToReloc() {
+ error_code ec;
+ for (section_iterator SI = Obj->begin_sections(),
+ SE = Obj->end_sections();
+ SI != SE;
+ SI.increment(ec)) {
+ if (ec) break;
+ uint64_t StartAddr; SI->getAddress(StartAddr);
+ uint64_t Size; SI->getSize(Size);
+ StringRef SecName; SI->getName(SecName);
+ bool RequiredForExec; SI->isRequiredForExecution(RequiredForExec);
+ if (RequiredForExec == false || Size == 0)
+ continue;
+ AddrToSection.insert(StartAddr, StartAddr + Size - 1,
+ SI->getRawDataRefImpl().p);
+ for (relocation_iterator RI = SI->begin_relocations(),
+ RE = SI->end_relocations();
+ RI != RE;
+ RI.increment(ec)) {
+ if (ec) break;
+ // FIXME: libObject is inconsistent regarding error handling. The
+ // overwhelming majority of methods always return object_error::success,
+ // and assert for simple errors.. Here, ELFObjectFile::getRelocationOffset
+ // asserts when the file type isn't ET_REL.
+ // This workaround handles x86-64 elf, the only one that has a relocinfo.
+ uint64_t Offset;
+ if (Obj->isELF()) {
+ const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj);
+ if (ELFObj == 0)
+ break;
+ if (ELFObj->getElfHeader()->e_type == ELF::ET_REL) {
+ RI->getOffset(Offset);
+ Offset += StartAddr;
+ } else {
+ RI->getAddress(Offset);
+ }
+ } else {
+ RI->getOffset(Offset);
+ Offset += StartAddr;
+ }
+ // At a specific address, only keep the first relocation.
+ if (AddrToReloc.find(Offset) == AddrToReloc.end())
+ AddrToReloc[Offset] = *RI;
+ }
+ }
+}
+
+bool MCObjectSymbolizer::
+tryAddingSymbolicOperand(MCInst &MI, raw_ostream &cStream,
+ int64_t Value, uint64_t Address, bool IsBranch,
+ uint64_t Offset, uint64_t InstSize) {
+ AddrToRelocMap::iterator RI = AddrToReloc.find(Address + Offset);
+ if (RI != AddrToReloc.end()) {
+ if (const MCExpr *RelExpr = RelInfo->createExprForRelocation(RI->second)) {
+ MI.addOperand(MCOperand::CreateExpr(RelExpr));
+ return true;
+ }
+ // Only try to create a symbol+offset expression if there is no relocation.
+ return false;
+ }
+
+ // Interpret Value as a branch target.
+ if (IsBranch == false)
+ return false;
+ uint64_t UValue = Value;
+ // FIXME: map instead of looping each time?
+ error_code ec;
+ for (symbol_iterator SI = Obj->begin_symbols(),
+ SE = Obj->end_symbols();
+ SI != SE;
+ SI.increment(ec)) {
+ if (ec) break;
+ uint64_t SymAddr; SI->getAddress(SymAddr);
+ uint64_t SymSize; SI->getSize(SymSize);
+ StringRef SymName; SI->getName(SymName);
+ SymbolRef::Type SymType; SI->getType(SymType);
+ if (SymAddr == UnknownAddressOrSize || SymSize == UnknownAddressOrSize
+ || SymName.empty() || SymType != SymbolRef::ST_Function)
+ continue;
+
+ if ( SymAddr == UValue ||
+ (SymAddr <= UValue && SymAddr + SymSize > UValue)) {
+ MCSymbol *Sym = Ctx.GetOrCreateSymbol(SymName);
+ const MCExpr *Expr = MCSymbolRefExpr::Create(Sym, Ctx);
+ if (SymAddr != UValue) {
+ const MCExpr *Off = MCConstantExpr::Create(UValue - SymAddr, Ctx);
+ Expr = MCBinaryExpr::CreateAdd(Expr, Off, Ctx);
+ }
+ MI.addOperand(MCOperand::CreateExpr(Expr));
+ return true;
+ }
+ }
+ return false;
+}
+
+void MCObjectSymbolizer::
+tryAddingPcLoadReferenceComment(raw_ostream &cStream,
+ int64_t Value, uint64_t Address) {
+}
+
+MCObjectSymbolizer *
+MCObjectSymbolizer::createObjectSymbolizer(MCContext &Ctx,
+ OwningPtr<MCRelocationInfo> &RelInfo,
+ const ObjectFile *Obj) {
+ if (const MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(Obj)) {
+ return new MCMachObjectSymbolizer(Ctx, RelInfo, MachOOF);
+ }
+ return new MCObjectSymbolizer(Ctx, RelInfo, Obj);
+}
diff --git a/lib/MC/MCRelocationInfo.cpp b/lib/MC/MCRelocationInfo.cpp
new file mode 100644
index 0000000000..a2a3174555
--- /dev/null
+++ b/lib/MC/MCRelocationInfo.cpp
@@ -0,0 +1,39 @@
+//==-- lib/MC/MCRelocationInfo.cpp -------------------------------*- C++ -*-==//
+//
+// 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/Object/ObjectFile.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm-c/Disassembler.h"
+
+using namespace llvm;
+
+MCRelocationInfo::MCRelocationInfo(MCContext &Ctx)
+ : Ctx(Ctx) {
+}
+
+MCRelocationInfo::~MCRelocationInfo() {
+}
+
+const MCExpr *
+MCRelocationInfo::createExprForRelocation(object::RelocationRef Rel) {
+ return 0;
+}
+
+const MCExpr *
+MCRelocationInfo::createExprForCAPIVariantKind(const MCExpr *SubExpr,
+ unsigned VariantKind) {
+ if (VariantKind != LLVMDisassembler_VariantKind_None)
+ return 0;
+ return SubExpr;
+}
+
+MCRelocationInfo *llvm::createMCRelocationInfo(MCContext &Ctx) {
+ return new MCRelocationInfo(Ctx);
+}
diff --git a/lib/MC/MCSymbolizer.cpp b/lib/MC/MCSymbolizer.cpp
new file mode 100644
index 0000000000..1020b74b34
--- /dev/null
+++ b/lib/MC/MCSymbolizer.cpp
@@ -0,0 +1,20 @@
+//===-- llvm/MC/MCSymbolizer.cpp - MCSymbolizer class -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCSymbolizer.h"
+#include "llvm/MC/MCRelocationInfo.h"
+
+using namespace llvm;
+
+MCSymbolizer::MCSymbolizer(MCContext &Ctx, OwningPtr<MCRelocationInfo> &RelInfo)
+ : Ctx(Ctx), RelInfo(RelInfo.take()) {
+}
+
+MCSymbolizer::~MCSymbolizer() {
+}
diff --git a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
index fb82945356..284761cf29 100644
--- a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
+++ b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
@@ -503,102 +503,9 @@ static bool tryAddingSymbolicOperand(uint64_t Address, int32_t Value,
bool isBranch, uint64_t InstSize,
MCInst &MI, const void *Decoder) {
const MCDisassembler *Dis = static_cast<const MCDisassembler*>(Decoder);
- LLVMOpInfoCallback getOpInfo = Dis->getLLVMOpInfoCallback();
- struct LLVMOpInfo1 SymbolicOp;
- memset(&SymbolicOp, '\0', sizeof(struct LLVMOpInfo1));
- SymbolicOp.Value = Value;
- void *DisInfo = Dis->getDisInfoBlock();
-
- if (!getOpInfo ||
- !getOpInfo(DisInfo, Address, 0 /* Offset */, InstSize, 1, &SymbolicOp)) {
- // Clear SymbolicOp.Value from above and also all other fields.
- memset(&SymbolicOp, '\0', sizeof(struct LLVMOpInfo1));
- LLVMSymbolLookupCallback SymbolLookUp = Dis->getLLVMSymbolLookupCallback();
- if (!SymbolLookUp)
- return false;
- uint64_t ReferenceType;
- if (isBranch)
- ReferenceType = LLVMDisassembler_ReferenceType_In_Branch;
- else
- ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
- const char *ReferenceName;
- uint64_t SymbolValue = 0x00000000ffffffffULL & Value;
- const char *Name = SymbolLookUp(DisInfo, SymbolValue, &ReferenceType,
- Address, &ReferenceName);
- if (Name) {
- SymbolicOp.AddSymbol.Name = Name;
- SymbolicOp.AddSymbol.Present = true;
- }
- // 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)
- (*Dis->CommentStream) << "symbol stub for: " << ReferenceName;
- if (!Name && !isBranch)
- return false;
- }
-
- MCContext *Ctx = Dis->getMCContext();
- const MCExpr *Add = NULL;
- 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(SymbolicOp.AddSymbol.Value, *Ctx);
- }
- }
-
- const MCExpr *Sub = NULL;
- 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(SymbolicOp.SubtractSymbol.Value, *Ctx);
- }
- }
-
- const MCExpr *Off = NULL;
- 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 != 0)
- Expr = MCBinaryExpr::CreateAdd(LHS, Off, *Ctx);
- else
- Expr = LHS;
- } else if (Add) {
- if (Off != 0)
- Expr = MCBinaryExpr::CreateAdd(Add, Off, *Ctx);
- else
- Expr = Add;
- } else {
- if (Off != 0)
- Expr = Off;
- else
- Expr = MCConstantExpr::Create(0, *Ctx);
- }
-
- if (SymbolicOp.VariantKind == LLVMDisassembler_VariantKind_ARM_HI16)
- MI.addOperand(MCOperand::CreateExpr(ARMMCExpr::CreateUpper16(Expr, *Ctx)));
- else if (SymbolicOp.VariantKind == LLVMDisassembler_VariantKind_ARM_LO16)
- MI.addOperand(MCOperand::CreateExpr(ARMMCExpr::CreateLower16(Expr, *Ctx)));
- else if (SymbolicOp.VariantKind == LLVMDisassembler_VariantKind_None)
- MI.addOperand(MCOperand::CreateExpr(Expr));
- else
- llvm_unreachable("bad SymbolicOp.VariantKind");
-
- return true;
+ // FIXME: Does it make sense for value to be negative?
+ return Dis->tryAddingSymbolicOperand(MI, (uint32_t)Value, Address, isBranch,
+ /* Offset */ 0, InstSize);
}
/// tryAddingPcLoadReferenceComment - trys to add a comment as to what is being
@@ -613,17 +520,7 @@ static bool tryAddingSymbolicOperand(uint64_t Address, int32_t Value,
static void tryAddingPcLoadReferenceComment(uint64_t Address, int Value,
const void *Decoder) {
const MCDisassembler *Dis = static_cast<const MCDisassembler*>(Decoder);
- LLVMSymbolLookupCallback SymbolLookUp = Dis->getLLVMSymbolLookupCallback();
- if (SymbolLookUp) {
- void *DisInfo = Dis->getDisInfoBlock();
- uint64_t ReferenceType;
- ReferenceType = LLVMDisassembler_ReferenceType_In_PCrel_Load;
- const char *ReferenceName;
- (void)SymbolLookUp(DisInfo, Value, &ReferenceType, Address, &ReferenceName);
- if(ReferenceType == LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr ||
- ReferenceType == LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr)
- (*Dis->CommentStream) << "literal pool for: " << ReferenceName;
- }
+ Dis->tryAddingPcLoadReferenceComment(Value, Address);
}
// Thumb1 instructions don't have explicit S bits. Rather, they
diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp
index b858fff546..52fc28d11d 100644
--- a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp
+++ b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp
@@ -212,6 +212,14 @@ static MCInstPrinter *createARMMCInstPrinter(const Target &T,
return 0;
}
+static MCRelocationInfo *createMCRelocationInfo(StringRef TT, MCContext &Ctx) {
+ Triple TheTriple(TT);
+ if (TheTriple.isEnvironmentMachO())
+ return createARMMachORelocationInfo(Ctx);
+ // Default to the stock relocation info.
+ return llvm::createMCRelocationInfo(Ctx);
+}
+
namespace {
class ARMMCInstrAnalysis : public MCInstrAnalysis {
@@ -295,4 +303,10 @@ extern "C" void LLVMInitializeARMTargetMC() {
// Register the MCInstPrinter.
TargetRegistry::RegisterMCInstPrinter(TheARMTarget, createARMMCInstPrinter);
TargetRegistry::RegisterMCInstPrinter(TheThumbTarget, createARMMCInstPrinter);
+
+ // Register the MC relocation info.
+ TargetRegistry::RegisterMCRelocationInfo(TheARMTarget,
+ createMCRelocationInfo);
+ TargetRegistry::RegisterMCRelocationInfo(TheThumbTarget,
+ createMCRelocationInfo);
}
diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h
index a89981e4f0..4e94c5341b 100644
--- a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h
+++ b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h
@@ -25,6 +25,7 @@ class MCInstrInfo;
class MCObjectWriter;
class MCRegisterInfo;
class MCSubtargetInfo;
+class MCRelocationInfo;
class StringRef;
class Target;
class raw_ostream;
@@ -58,6 +59,9 @@ MCObjectWriter *createARMMachObjectWriter(raw_ostream &OS,
uint32_t CPUType,
uint32_t CPUSubtype);
+
+/// createARMMachORelocationInfo - Construct ARM Mach-O relocation info.
+MCRelocationInfo *createARMMachORelocationInfo(MCContext &Ctx);
} // End llvm namespace
// Defines symbolic names for ARM registers. This defines a mapping from
diff --git a/lib/Target/ARM/MCTargetDesc/ARMMachORelocationInfo.cpp b/lib/Target/ARM/MCTargetDesc/ARMMachORelocationInfo.cpp
new file mode 100644
index 0000000000..807c9483bc
--- /dev/null
+++ b/lib/Target/ARM/MCTargetDesc/ARMMachORelocationInfo.cpp
@@ -0,0 +1,43 @@
+//===-- ARMMachORelocationInfo.cpp ----------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/ARMMCTargetDesc.h"
+#include "ARMMCExpr.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCRelocationInfo.h"
+#include "llvm-c/Disassembler.h"
+
+using namespace llvm;
+using namespace object;
+
+namespace {
+class ARMMachORelocationInfo : public MCRelocationInfo {
+public:
+ ARMMachORelocationInfo(MCContext &Ctx) : MCRelocationInfo(Ctx) {}
+
+ const MCExpr *createExprForCAPIVariantKind(const MCExpr *SubExpr,
+ unsigned VariantKind) {
+ switch(VariantKind) {
+ case LLVMDisassembler_VariantKind_ARM_HI16:
+ return ARMMCExpr::CreateUpper16(SubExpr, Ctx);
+ case LLVMDisassembler_VariantKind_ARM_LO16:
+ return ARMMCExpr::CreateLower16(SubExpr, Ctx);
+ default:
+ return MCRelocationInfo::createExprForCAPIVariantKind(SubExpr,
+ VariantKind);
+ }
+ }
+};
+} // End unnamed namespace
+
+/// createARMMachORelocationInfo - Construct an ARM Mach-O RelocationInfo.
+MCRelocationInfo *llvm::createARMMachORelocationInfo(MCContext &Ctx) {
+ return new ARMMachORelocationInfo(Ctx);
+}
diff --git a/lib/Target/ARM/MCTargetDesc/CMakeLists.txt b/lib/Target/ARM/MCTargetDesc/CMakeLists.txt
index a7ac5ca061..bab59f41c9 100644
--- a/lib/Target/ARM/MCTargetDesc/CMakeLists.txt
+++ b/lib/Target/ARM/MCTargetDesc/CMakeLists.txt
@@ -9,6 +9,7 @@ add_llvm_library(LLVMARMDesc
ARMMachObjectWriter.cpp
ARMELFObjectWriter.cpp
ARMUnwindOpAsm.cpp
+ ARMMachORelocationInfo.cpp
)
add_dependencies(LLVMARMDesc ARMCommonTableGen)
diff --git a/lib/Target/X86/Disassembler/X86Disassembler.cpp b/lib/Target/X86/Disassembler/X86Disassembler.cpp
index ca6f80ce3e..ca71c4f351 100644
--- a/lib/Target/X86/Disassembler/X86Disassembler.cpp
+++ b/lib/Target/X86/Disassembler/X86Disassembler.cpp
@@ -190,94 +190,8 @@ static bool tryAddingSymbolicOperand(int64_t Value, bool isBranch,
uint64_t Address, uint64_t Offset,
uint64_t Width, MCInst &MI,
const MCDisassembler *Dis) {
- LLVMOpInfoCallback getOpInfo = Dis->getLLVMOpInfoCallback();
- struct LLVMOpInfo1 SymbolicOp;
- memset(&SymbolicOp, '\0', sizeof(struct LLVMOpInfo1));
- SymbolicOp.Value = Value;
- void *DisInfo = Dis->getDisInfoBlock();
-
- if (!getOpInfo ||
- !getOpInfo(DisInfo, Address, Offset, Width, 1, &SymbolicOp)) {
- // Clear SymbolicOp.Value from above and also all other fields.
- memset(&SymbolicOp, '\0', sizeof(struct LLVMOpInfo1));
- LLVMSymbolLookupCallback SymbolLookUp = Dis->getLLVMSymbolLookupCallback();
- if (!SymbolLookUp)
- 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;
- }
- // 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)
- (*Dis->CommentStream) << "symbol stub for: " << ReferenceName;
- if (!Name && !isBranch)
- return false;
- }
-
- MCContext *Ctx = Dis->getMCContext();
- const MCExpr *Add = NULL;
- 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 = NULL;
- 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 = NULL;
- 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 != 0)
- Expr = MCBinaryExpr::CreateAdd(LHS, Off, *Ctx);
- else
- Expr = LHS;
- } else if (Add) {
- if (Off != 0)
- Expr = MCBinaryExpr::CreateAdd(Add, Off, *Ctx);
- else
- Expr = Add;
- } else {
- if (Off != 0)
- Expr = Off;
- else
- Expr = MCConstantExpr::Create(0, *Ctx);
- }
-
- MI.addOperand(MCOperand::CreateExpr(Expr));
-
- return true;
+ return Dis->tryAddingSymbolicOperand(MI, Value, Address, isBranch,
+ Offset, Width);
}
/// tryAddingPcLoadReferenceComment - trys to add a comment as to what is being
@@ -290,15 +204,7 @@ static bool tryAddingSymbolicOperand(int64_t Value, bool isBranch,
static void tryAddingPcLoadReferenceComment(uint64_t Address, uint64_t Value,
const void *Decoder) {
const MCDisassembler *Dis = static_cast<const MCDisassembler*>(Decoder);
- LLVMSymbolLookupCallback SymbolLookUp = Dis->getLLVMSymbolLookupCallback();
- if (SymbolLookUp) {
- void *DisInfo = Dis->getDisInfoBlock();
- uint64_t ReferenceType = LLVMDisassembler_ReferenceType_In_PCrel_Load;
- const char *ReferenceName;
- (void)SymbolLookUp(DisInfo, Value, &ReferenceType, Address, &ReferenceName);
- if(ReferenceType == LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr)
- (*Dis->CommentStream) << "literal pool for: " << ReferenceName;
- }
+ Dis->tryAddingPcLoadReferenceComment(Value, Address);
}
/// translateImmediate - Appends an immediate operand to an MCInst.
diff --git a/lib/Target/X86/MCTargetDesc/CMakeLists.txt b/lib/Target/X86/MCTargetDesc/CMakeLists.txt
index 1c240e52a3..2eb5f25ffd 100644
--- a/lib/Target/X86/MCTargetDesc/CMakeLists.txt
+++ b/lib/Target/X86/MCTargetDesc/CMakeLists.txt
@@ -6,6 +6,8 @@ add_llvm_library(LLVMX86Desc
X86MachObjectWriter.cpp
X86ELFObjectWriter.cpp
X86WinCOFFObjectWriter.cpp
+ X86MachORelocationInfo.cpp
+ X86ELFRelocationInfo.cpp
)
add_dependencies(LLVMX86Desc X86CommonTableGen)
diff --git a/lib/Target/X86/MCTargetDesc/X86ELFRelocationInfo.cpp b/lib/Target/X86/MCTargetDesc/X86ELFRelocationInfo.cpp
new file mode 100644
index 0000000000..917c37d2ca
--- /dev/null
+++ b/lib/Target/X86/MCTargetDesc/X86ELFRelocationInfo.cpp
@@ -0,0 +1,135 @@
+//===-- X86ELFRelocationInfo.cpp ----------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/X86MCTargetDesc.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCRelocationInfo.h"
+#include "llvm/Object/ELF.h"
+#include "llvm/Support/ELF.h"
+
+using namespace llvm;
+using namespace object;
+using namespace ELF;
+
+namespace {
+class X86_64ELFRelocationInfo : public MCRelocationInfo {
+public:
+ X86_64ELFRelocationInfo(MCContext &Ctx) : MCRelocationInfo(Ctx) {}
+
+ const MCExpr *createExprForRelocation(RelocationRef Rel) {
+ uint64_t RelType; Rel.getType(RelType);
+ SymbolRef SymRef; Rel.getSymbol(SymRef);
+
+ StringRef SymName; SymRef.getName(SymName);
+ uint64_t SymAddr; SymRef.getAddress(SymAddr);
+ uint64_t SymSize; SymRef.getSize(SymSize);
+ int64_t Addend; getELFRelocationAddend(Rel, Addend);
+
+ MCSymbol *Sym = Ctx.GetOrCreateSymbol(SymName);
+ // FIXME: check that the value is actually the same.
+ if (Sym->isVariable() == false)
+ Sym->setVariableValue(MCConstantExpr::Create(SymAddr, Ctx));
+
+ const MCExpr *Expr = 0;
+ // If hasAddend is true, then we need to add Addend (r_addend) to Expr.
+ bool hasAddend = false;
+
+ // The AMD64 SysV ABI says:
+ // A: the addend used to compute the value of the relocatable field.
+ // B: the base address at which a shared object has been loaded into memory
+ // during execution. Generally, a shared object is built with a 0 base
+ // virtual address, but the execution address will be different.
+ // G: the offset into the global offset table at which the relocation
+ // entry's symbol will reside during execution.
+ // GOT: the address of the global offset table.
+ // L: the place (section offset or address) of the Procedure Linkage Table
+ // entry for a symbol.
+ // P: the place (section offset or address) of the storage unit being
+ // relocated (computed using r_offset).
+ // S: the value of the symbol whose index resides in the relocation entry.
+ // Z: the size of the symbol whose index resides in the relocation entry.
+
+ switch(RelType) {
+ case R_X86_64_NONE:
+ case R_X86_64_COPY:
+ // none
+ break;
+ case R_X86_64_64:
+ case R_X86_64_16:
+ case R_X86_64_8:
+ // S + A
+ case R_X86_64_32:
+ case R_X86_64_32S:
+ // S + A (We don't care about the result not fitting in 32 bits.)
+ case R_X86_64_PC32:
+ case R_X86_64_PC16:
+ case R_X86_64_PC8:
+ case R_X86_64_PC64:
+ // S + A - P (P/pcrel is implicit)
+ hasAddend = true;
+ Expr = MCSymbolRefExpr::Create(Sym, Ctx);
+ break;
+ case R_X86_64_GOT32:
+ case R_X86_64_GOT64:
+ case R_X86_64_GOTPC32:
+ case R_X86_64_GOTPC64:
+ case R_X86_64_GOTPLT64:
+ // G + A
+ hasAddend = true;
+ Expr = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_GOT, Ctx);
+ break;
+ case R_X86_64_PLT32:
+ // L + A - P -> S@PLT + A
+ hasAddend = true;
+ Expr = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_PLT, Ctx);
+ break;
+ case R_X86_64_GLOB_DAT:
+ case R_X86_64_JUMP_SLOT:
+ // S
+ Expr = MCSymbolRefExpr::Create(Sym, Ctx);
+ break;
+ case R_X86_64_GOTPCREL:
+ case R_X86_64_GOTPCREL64:
+ // G + GOT + A - P -> S@GOTPCREL + A
+ hasAddend = true;
+ Expr = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_GOTPCREL, Ctx);
+ break;
+ case R_X86_64_GOTOFF64:
+ // S + A - GOT
+ Expr = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_GOTOFF, Ctx);
+ break;
+ case R_X86_64_PLTOFF64:
+ // L + A - GOT
+ break;
+ case R_X86_64_SIZE32:
+ case R_X86_64_SIZE64:
+ // Z + A
+ Expr = MCConstantExpr::Create(SymSize, Ctx);
+ break;
+ default:
+ Expr = MCSymbolRefExpr::Create(Sym, Ctx);
+ break;
+ }
+ if (Expr && hasAddend && Addend != 0)
+ Expr = MCBinaryExpr::CreateAdd(Expr,
+ MCConstantExpr::Create(Addend, Ctx),
+ Ctx);
+ return Expr;
+ }
+};
+} // End unnamed namespace
+
+/// createX86ELFRelocationInfo - Construct an X86 Mach-O RelocationInfo.
+MCRelocationInfo *llvm::createX86_64ELFRelocationInfo(MCContext &Ctx) {
+ // We only handle x86-64 for now.
+ return new X86_64ELFRelocationInfo(Ctx);
+}
diff --git a/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp b/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp
index d5aab8e0a2..6d23981d63 100644
--- a/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp
+++ b/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp
@@ -384,6 +384,16 @@ static MCInstPrinter *createX86MCInstPrinter(const Target &T,
return 0;
}
+static MCRelocationInfo *createMCRelocationInfo(StringRef TT, MCContext &Ctx) {
+ Triple TheTriple(TT);
+ if (TheTriple.isEnvironmentMachO() && TheTriple.getArch() == Triple::x86_64)
+ return createX86_64MachORelocationInfo(Ctx);
+ else if (TheTriple.isOSBinFormatELF())
+ return createX86_64ELFRelocationInfo(Ctx);
+ // Default to the stock relocation info.
+ return llvm::createMCRelocationInfo(Ctx);
+}
+
static MCInstrAnalysis *createX86MCInstrAnalysis(const MCInstrInfo *Info) {
return new MCInstrAnalysis(Info);
}
@@ -441,4 +451,10 @@ extern "C" void LLVMInitializeX86TargetMC() {
createX86MCInstPrinter);
TargetRegistry::RegisterMCInstPrinter(TheX86_64Target,
createX86MCInstPrinter);
+
+ // Register the MC relocation info.
+ TargetRegistry::RegisterMCRelocationInfo(TheX86_32Target,
+ createMCRelocationInfo);
+ TargetRegistry::RegisterMCRelocationInfo(TheX86_64Target,
+ createMCRelocationInfo);
}
diff --git a/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h b/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h
index 981aa1a2b9..2f459b4bc8 100644
--- a/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h
+++ b/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h
@@ -25,6 +25,7 @@ class MCInstrInfo;
class MCObjectWriter;
class MCRegisterInfo;
class MCSubtargetInfo;
+class MCRelocationInfo;
class Target;
class StringRef;
class raw_ostream;
@@ -94,6 +95,12 @@ MCObjectWriter *createX86ELFObjectWriter(raw_ostream &OS,
uint16_t EMachine);
/// createX86WinCOFFObjectWriter - Construct an X86 Win COFF object writer.
MCObjectWriter *createX86WinCOFFObjectWriter(raw_ostream &OS, bool Is64Bit);
+
+/// createX86_64MachORelocationInfo - Construct X86-64 Mach-O relocation info.
+MCRelocationInfo *createX86_64MachORelocationInfo(MCContext &Ctx);
+
+/// createX86_64ELFORelocationInfo - Construct X86-64 ELF relocation info.
+MCRelocationInfo *createX86_64ELFRelocationInfo(MCContext &Ctx);
} // End llvm namespace
diff --git a/lib/Target/X86/MCTargetDesc/X86MachORelocationInfo.cpp b/lib/Target/X86/MCTargetDesc/X86MachORelocationInfo.cpp
new file mode 100644
index 0000000000..a76cad555d
--- /dev/null
+++ b/lib/Target/X86/MCTargetDesc/X86MachORelocationInfo.cpp
@@ -0,0 +1,117 @@
+//===-- X86MachORelocationInfo.cpp ----------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/X86MCTargetDesc.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCRelocationInfo.h"
+#include "llvm/Object/MachO.h"
+
+using namespace llvm;
+using namespace object;
+using namespace macho;
+
+namespace {
+class X86_64MachORelocationInfo : public MCRelocationInfo {
+public:
+ X86_64MachORelocationInfo(MCContext &Ctx) : MCRelocationInfo(Ctx) {}
+
+ const MCExpr *createExprForRelocation(RelocationRef Rel) {
+ const MachOObjectFile *Obj = cast<MachOObjectFile>(Rel.getObjectFile());
+
+ uint64_t RelType; Rel.getType(RelType);
+ SymbolRef SymRef; Rel.getSymbol(SymRef);
+
+ StringRef SymName; SymRef.getName(SymName);
+ uint64_t SymAddr; SymRef.getAddress(SymAddr);
+
+ RelocationEntry RE = Obj->getRelocation(Rel.getRawDataRefImpl());
+ bool isPCRel = Obj->getAnyRelocationPCRel(RE);
+
+ MCSymbol *Sym = Ctx.GetOrCreateSymbol(SymName);
+ // FIXME: check that the value is actually the same.
+ if (Sym->isVariable() == false)
+ Sym->setVariableValue(MCConstantExpr::Create(SymAddr, Ctx));
+ const MCExpr *Expr = 0;
+
+ switch(RelType) {
+ case RIT_X86_64_TLV:
+ Expr = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_TLVP, Ctx);
+ break;
+ case RIT_X86_64_Signed4:
+ Expr = MCBinaryExpr::CreateAdd(MCSymbolRefExpr::Create(Sym, Ctx),
+ MCConstantExpr::Create(4, Ctx),
+ Ctx);
+ break;
+ case RIT_X86_64_Signed2:
+ Expr = MCBinaryExpr::CreateAdd(MCSymbolRefExpr::Create(Sym, Ctx),
+ MCConstantExpr::Create(2, Ctx),
+ Ctx);
+ break;
+ case RIT_X86_64_Signed1:
+ Expr = MCBinaryExpr::CreateAdd(MCSymbolRefExpr::Create(Sym, Ctx),
+ MCConstantExpr::Create(1, Ctx),
+ Ctx);
+ break;
+ case RIT_X86_64_GOTLoad:
+ Expr = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_GOTPCREL, Ctx);
+ break;
+ case RIT_X86_64_GOT:
+ Expr = MCSymbolRefExpr::Create(Sym, isPCRel ?
+ MCSymbolRefExpr::VK_GOTPCREL :
+ MCSymbolRefExpr::VK_GOT,
+ Ctx);
+ break;
+ case RIT_X86_64_Subtractor:
+ {
+ RelocationRef RelNext;
+ Obj->getRelocationNext(Rel.getRawDataRefImpl(), RelNext);
+ RelocationEntry RENext = Obj->getRelocation(RelNext.getRawDataRefImpl());
+
+ // X86_64_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 != RIT_X86_64_Unsigned)
+ report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
+ "X86_64_RELOC_SUBTRACTOR.");
+
+ const MCExpr *LHS = MCSymbolRefExpr::Create(Sym, Ctx);
+
+ SymbolRef RSymRef;
+ RelNext.getSymbol(RSymRef);
+ uint64_t RSymAddr;
+ RSymRef.getAddress(RSymAddr);
+ StringRef RSymName;
+ RSymRef.getName(RSymName);
+
+ MCSymbol *RSym = Ctx.GetOrCreateSymbol(RSymName);
+ if (RSym->isVariable() == false)
+ RSym->setVariableValue(MCConstantExpr::Create(RSymAddr, Ctx));
+
+ const MCExpr *RHS = MCSymbolRefExpr::Create(RSym, Ctx);
+
+ Expr = MCBinaryExpr::CreateSub(LHS, RHS, Ctx);
+ break;
+ }
+ default:
+ Expr = MCSymbolRefExpr::Create(Sym, Ctx);
+ break;
+ }
+ return Expr;
+ }
+};
+} // End unnamed namespace
+
+/// createX86_64MachORelocationInfo - Construct an X86-64 Mach-O RelocationInfo.
+MCRelocationInfo *llvm::createX86_64MachORelocationInfo(MCContext &Ctx) {
+ return new X86_64MachORelocationInfo(Ctx);
+}
diff --git a/test/Object/X86/objdump-disassembly-symbolic.test b/test/Object/X86/objdump-disassembly-symbolic.test
new file mode 100644
index 0000000000..667bce95f2
--- /dev/null
+++ b/test/Object/X86/objdump-disassembly-symbolic.test
@@ -0,0 +1,30 @@
+RUN: llvm-objdump -d -symbolize %p/../Inputs/trivial-object-test.elf-x86-64 \
+RUN: | FileCheck %s -check-prefix ELF-x86-64
+RUN: llvm-objdump -d -symbolize %p/../Inputs/trivial-object-test.macho-x86-64 \
+RUN: | FileCheck %s -check-prefix MACHO-x86-64
+
+ELF-x86-64: file format ELF64-x86-64
+ELF-x86-64: Disassembly of section .text:
+ELF-x86-64: main:
+ELF-x86-64: 0: 48 83 ec 08 subq $8, %rsp
+ELF-x86-64: 4: c7 44 24 04 00 00 00 00 movl $0, 4(%rsp)
+ELF-x86-64: c: bf 00 00 00 00 movl $.rodata.str1.1, %edi
+ELF-x86-64: 11: e8 00 00 00 00 callq puts-4
+ELF-x86-64: 16: 30 c0 xorb %al, %al
+ELF-x86-64: 18: e8 00 00 00 00 callq SomeOtherFunction-4
+ELF-x86-64: 1d: 8b 44 24 04 movl 4(%rsp), %eax
+ELF-x86-64: 21: 48 83 c4 08 addq $8, %rsp
+ELF-x86-64: 25: c3 ret
+
+MACHO-x86-64: file format Mach-O 64-bit x86-64
+MACHO-x86-64: Disassembly of section __TEXT,__text:
+MACHO-x86-64: _main:
+MACHO-x86-64: 0: 48 83 ec 08 subq $8, %rsp
+MACHO-x86-64: 4: c7 44 24 04 00 00 00 00 movl $0, 4(%rsp)
+MACHO-x86-64: c: 48 8d 3d 00 00 00 00 leaq L_.str(%rip), %rdi ## literal pool for: Hello World!
+MACHO-x86-64: 13: e8 00 00 00 00 callq _puts
+MACHO-x86-64: 18: 30 c0 xorb %al, %al
+MACHO-x86-64: 1a: e8 00 00 00 00 callq _SomeOtherFunction
+MACHO-x86-64: 1f: 8b 44 24 04 movl 4(%rsp), %eax
+MACHO-x86-64: 23: 48 83 c4 08 addq $8, %rsp
+MACHO-x86-64: 27: c3 ret
diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp
index b5a0488b00..570ec7ed6f 100644
--- a/tools/llvm-objdump/llvm-objdump.cpp
+++ b/tools/llvm-objdump/llvm-objdump.cpp
@@ -23,12 +23,16 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Triple.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/MCObjectFileInfo.h"
+#include "llvm/MC/MCObjectSymbolizer.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCRelocationInfo.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/COFF.h"
#include "llvm/Object/MachO.h"
@@ -123,6 +127,10 @@ static cl::alias
PrivateHeadersShort("p", cl::desc("Alias for --private-headers"),
cl::aliasopt(PrivateHeaders));
+static cl::opt<bool>
+Symbolize("symbolize", cl::desc("When disassembling instructions, "
+ "try to symbolize operands."));
+
static StringRef ToolName;
bool llvm::error(error_code ec) {
@@ -137,8 +145,13 @@ static const Target *getTarget(const ObjectFile *Obj = NULL) {
// Figure out the target triple.
llvm::Triple TheTriple("unknown-unknown-unknown");
if (TripleName.empty()) {
- if (Obj)
+ if (Obj) {
TheTriple.setArch(Triple::ArchType(Obj->getArch()));
+ // TheTriple defaults to ELF, and COFF doesn't have an environment:
+ // the best we can do here is indicate that it is mach-o.
+ if (Obj->isMachO())
+ TheTriple.setEnvironment(Triple::MachO);
+ }
} else
TheTriple.setTriple(Triple::normalize(TripleName));
@@ -216,7 +229,6 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
// Set up disassembler.
OwningPtr<const MCAsmInfo> AsmInfo(
TheTarget->createMCAsmInfo(*MRI, TripleName));
-
if (!AsmInfo) {
errs() << "error: no assembly info for target " << TripleName << "\n";
return;
@@ -224,23 +236,37 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
OwningPtr<const MCSubtargetInfo> STI(
TheTarget->createMCSubtargetInfo(TripleName, "", FeaturesStr));
-
if (!STI) {
errs() << "error: no subtarget info for target " << TripleName << "\n";
return;
}
- OwningPtr<const MCDisassembler> DisAsm(
- TheTarget->createMCDisassembler(*STI));
+ OwningPtr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo());
+ if (!MII) {
+ errs() << "error: no instruction info for target " << TripleName << "\n";
+ return;
+ }
+
+ OwningPtr<MCDisassembler> DisAsm(TheTarget->createMCDisassembler(*STI));
if (!DisAsm) {
errs() << "error: no disassembler for target " << TripleName << "\n";
return;
}
- OwningPtr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo());
- if (!MII) {
- errs() << "error: no instruction info for target " << TripleName << "\n";
- return;
+ OwningPtr<const MCObjectFileInfo> MOFI;
+ OwningPtr<MCContext> Ctx;
+
+ if (Symbolize) {
+ MOFI.reset(new MCObjectFileInfo);
+ Ctx.reset(new MCContext(*AsmInfo.get(), *MRI.get(), MOFI.get()));
+ OwningPtr<MCRelocationInfo> RelInfo(
+ TheTarget->createMCRelocationInfo(TripleName, *Ctx.get()));
+ if (RelInfo) {
+ OwningPtr<MCSymbolizer> Symzer(
+ MCObjectSymbolizer::createObjectSymbolizer(*Ctx.get(), RelInfo, Obj));
+ if (Symzer)
+ DisAsm->setSymbolizer(Symzer);
+ }
}
int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
@@ -317,9 +343,13 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
if (Symbols.empty())
Symbols.push_back(std::make_pair(0, name));
+
+ SmallString<40> Comments;
+ raw_svector_ostream CommentStream(Comments);
+
StringRef Bytes;
if (error(i->getContents(Bytes))) break;
- StringRefMemoryObject memoryObject(Bytes);
+ StringRefMemoryObject memoryObject(Bytes, SectionAddr);
uint64_t Size;
uint64_t Index;
uint64_t SectSize;
@@ -353,14 +383,17 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
for (Index = Start; Index < End; Index += Size) {
MCInst Inst;
- if (DisAsm->getInstruction(Inst, Size, memoryObject, Index,
- DebugOut, nulls())) {
+ if (DisAsm->getInstruction(Inst, Size, memoryObject,
+ SectionAddr + Index,
+ DebugOut, CommentStream)) {
outs() << format("%8" PRIx64 ":", SectionAddr + Index);
if (!NoShowRawInsn) {
outs() << "\t";
DumpBytes(StringRef(Bytes.data() + Index, Size));
}
IP->printInst(&Inst, outs(), "");
+ outs() << CommentStream.str();
+ Comments.clear();
outs() << "\n";
} else {
errs() << ToolName << ": warning: invalid instruction encoding\n";
diff --git a/tools/llvm-objdump/llvm-objdump.h b/tools/llvm-objdump/llvm-objdump.h
index ca7bced635..3c62240f8f 100644
--- a/tools/llvm-objdump/llvm-objdump.h
+++ b/tools/llvm-objdump/llvm-objdump.h
@@ -38,16 +38,18 @@ void printELFFileHeader(const object::ObjectFile *o);
class StringRefMemoryObject : public MemoryObject {
virtual void anchor();
StringRef Bytes;
+ uint64_t Base;
public:
- StringRefMemoryObject(StringRef bytes) : Bytes(bytes) {}
+ StringRefMemoryObject(StringRef bytes, uint64_t Base = 0)
+ : Bytes(bytes), Base(Base) {}
- uint64_t getBase() const { return 0; }
+ uint64_t getBase() const { return Base; }
uint64_t getExtent() const { return Bytes.size(); }
int readByte(uint64_t Addr, uint8_t *Byte) const {
- if (Addr >= getExtent())
+ if (Addr >= Base + getExtent() || Addr < Base)
return -1;
- *Byte = Bytes[Addr];
+ *Byte = Bytes[Addr - Base];
return 0;
}
};