Add disassembler
Change-Id: I0b7aa48ee758f9a9ccf3db63c647fb339d0dc35b
diff --git a/Android.mk b/Android.mk
index 655745a..a9f8794 100644
--- a/Android.mk
+++ b/Android.mk
@@ -3,6 +3,8 @@
LOCAL_PATH := $(call my-dir)
LLVM_ROOT_PATH := external/llvm/llvm
+USE_DISASSEMBLER := true
+
# Shared library for target
# ========================================================
include $(CLEAR_VARS)
@@ -44,9 +46,7 @@
runtime/lib/arm/subsf3vfp.S \
runtime/lib/arm/truncdfsf2vfp.S \
runtime/lib/arm/unorddf2vfp.S \
- runtime/lib/arm/unordsf2vfp.S #\
-# disassembler/arm-dis.c \
-# disassembler/dis-asm.c
+ runtime/lib/arm/unordsf2vfp.S
LOCAL_STATIC_LIBRARIES := \
libLLVMARMCodeGen \
@@ -68,9 +68,16 @@
LOCAL_SHARED_LIBRARIES := libdl libcutils libstlport
LOCAL_C_INCLUDES := \
- $(LOCAL_PATH)/include $(LOCAL_PATH)/disassembler
+ $(LOCAL_PATH)/include
-#LOCAL_CFLAGS := -DUSE_DISASSEMBLER
+ifeq ($(USE_DISASSEMBLER),true)
+LOCAL_CFLAGS += -DUSE_DISASSEMBLER
+LOCAL_STATIC_LIBRARIES := \
+ libLLVMARMDisassembler \
+ libLLVMARMAsmPrinter \
+ libLLVMMCParser \
+ $(LOCAL_STATIC_LIBRARIES)
+endif
include $(LLVM_ROOT_PATH)/llvm-device-build.mk
include $(BUILD_SHARED_LIBRARY)
@@ -89,6 +96,7 @@
libLLVMBitReader \
libLLVMSelectionDAG \
libLLVMAsmPrinter \
+ libLLVMMCParser \
libLLVMCodeGen \
libLLVMJIT \
libLLVMTarget \
@@ -105,6 +113,14 @@
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/include
+ifeq ($(USE_DISASSEMBLER),true)
+LOCAL_CFLAGS += -DUSE_DISASSEMBLER
+LOCAL_STATIC_LIBRARIES := \
+ libLLVMX86Disassembler \
+ libLLVMX86AsmPrinter \
+ $(LOCAL_STATIC_LIBRARIES)
+endif
+
include $(LLVM_ROOT_PATH)/llvm-host-build.mk
include $(BUILD_HOST_SHARED_LIBRARY)
diff --git a/bcc.cpp b/bcc.cpp
index 6d1660c..be11021 100644
--- a/bcc.cpp
+++ b/bcc.cpp
@@ -81,8 +81,10 @@
// #define PROVIDE_TRACE_CODEGEN
#if defined(USE_DISASSEMBLER)
-# include "disassembler/dis-asm.h"
-# include <cstdio>
+# include "llvm/MC/MCInst.h" /* for class llvm::MCInst */
+# include "llvm/MC/MCAsmInfo.h" /* for class llvm::MCAsmInfo */
+# include "llvm/MC/MCInstPrinter.h" /* for class llvm::MCInstPrinter */
+# include "llvm/MC/MCDisassembler.h" /* for class llvm::MCDisassembler */
#endif
#include <set>
@@ -135,7 +137,8 @@
#include "llvm/Target/TargetData.h" /* for class llvm::TargetData */
#include "llvm/Target/TargetSelect.h" /* for function
* LLVMInitialize[ARM|X86]
- * [TargetInfo|Target]()
+ * [TargetInfo|Target|Disassembler|
+ * AsmPrinter]()
*/
#include "llvm/Target/TargetOptions.h" /* for
* variable bool llvm::UseSoftFloat
@@ -157,9 +160,10 @@
*/
#include "llvm/Support/ValueHandle.h" /* for class AssertingVH<> */
#include "llvm/Support/MemoryBuffer.h" /* for class llvm::MemoryBuffer */
+#include "llvm/Support/MemoryObject.h" /* for class llvm::MemoryObject */
#include "llvm/Support/ManagedStatic.h" /* for class llvm::llvm_shutdown */
#include "llvm/Support/ErrorHandling.h" /* for function
- * llvm::llvm_install_error_handler()
+ * llvm::install_fatal_error_handler()
* and macro llvm_unreachable()
*/
#include "llvm/Support/StandardPasses.h"/* for function
@@ -275,16 +279,28 @@
#if defined(DEFAULT_ARM_CODEGEN) || defined(PROVIDE_ARM_CODEGEN)
LLVMInitializeARMTargetInfo();
LLVMInitializeARMTarget();
+#if defined(USE_DISASSEMBLER)
+ LLVMInitializeARMDisassembler();
+ LLVMInitializeARMAsmPrinter();
+#endif
#endif
#if defined(DEFAULT_X86_CODEGEN) || defined(PROVIDE_X86_CODEGEN)
LLVMInitializeX86TargetInfo();
LLVMInitializeX86Target();
+#if defined(USE_DISASSEMBLER)
+ LLVMInitializeX86Disassembler();
+ LLVMInitializeX86AsmPrinter();
+#endif
#endif
#if defined(DEFAULT_X64_CODEGEN) || defined(PROVIDE_X64_CODEGEN)
LLVMInitializeX86TargetInfo();
LLVMInitializeX86Target();
+#if defined(USE_DISASSEMBLER)
+ LLVMInitializeX86Disassembler();
+ LLVMInitializeX86AsmPrinter();
+#endif
#endif
/*
@@ -318,7 +334,7 @@
*/
llvm::TargetMachine::setRelocationModel(llvm::Reloc::Static);
-#ifdef DEFAULT_X64_CODEGEN
+#if defined(DEFAULT_X64_CODEGEN)
/* Data address in X86_64 architecture may reside in a far-away place */
llvm::TargetMachine::setCodeModel(llvm::CodeModel::Medium);
#else
@@ -729,6 +745,8 @@
CodeMemoryManager* mpMemMgr;
/* The JITInfo for the target we are compiling to */
+ const llvm::Target* mpTarget;
+
llvm::TargetJITInfo* mpTJI;
const llvm::TargetData* mpTD;
@@ -1721,8 +1739,7 @@
if(!Actual)
PendingFunctions.insert(F);
else
- Disassembler(F->getNameStr() + " (stub)",
- (uint8_t*) Stub, SL.Size, (uintptr_t) Stub);
+ Disassemble(F->getName(), (uint8_t*) Stub, SL.Size, true);
return Stub;
}
@@ -1919,61 +1936,109 @@
return Stub;
}
-
- void Disassembler(const std::string& Name, uint8_t* Start,
- size_t Length, uintptr_t PC) {
#if defined(USE_DISASSEMBLER)
- FILE* out = stdout;
+ const llvm::MCAsmInfo* mpAsmInfo;
+ const llvm::MCDisassembler* mpDisassmbler;
+ llvm::MCInstPrinter* mpIP;
- fprintf(out, "JIT: Disassembled code: %s\n", Name.c_str());
+ class BufferMemoryObject : public llvm::MemoryObject {
+ private:
+ const uint8_t* mBytes;
+ uint64_t mLength;
- disassemble_info disasm_info;
- int (*print_insn)(bfd_vma pc, disassemble_info *info);
+ public:
+ BufferMemoryObject(const uint8_t *Bytes, uint64_t Length) :
+ mBytes(Bytes), mLength(Length) { }
- INIT_DISASSEMBLE_INFO(disasm_info, out, fprintf);
+ uint64_t getBase() const { return 0; }
+ uint64_t getExtent() const { return mLength; }
- disasm_info.buffer = Start;
- disasm_info.buffer_vma = (bfd_vma) (uintptr_t) Start;
- disasm_info.buffer_length = Length;
- disasm_info.endian = BFD_ENDIAN_LITTLE;
+ int readByte(uint64_t Addr, uint8_t *Byte) const {
+ if(Addr > getExtent())
+ return -1;
+ *Byte = mBytes[Addr];
+ return 0;
+ }
+ };
-#if defined(DEFAULT_X86_CODEGEN)
- disasm_info.mach = bfd_mach_i386_i386;
- print_insn = print_insn_i386;
-#elif defined(DEFAULT_ARM_CODEGEN)
- print_insn = print_insn_arm;
-#elif defined(DEFAULT_X64_CODEGEN)
- disasm_info.mach = bfd_mach_x86_64;
- print_insn = print_insn_i386;
-#else
-#error "Unknown target for disassembler"
+ void Disassemble(const llvm::StringRef& Name, uint8_t* Start,
+ size_t Length, bool IsStub) {
+
+ llvm::raw_ostream* OS = &llvm::outs();
+
+#if 0
+ /* If you want the disassemble results write to file, uncomment this */
+ std::string ErrorInfo;
+ llvm::raw_fd_ostream* OS = new llvm::raw_fd_ostream(
+ <const char* FileName>, ErrorInfo, llvm::raw_fd_ostream::F_Append);
+ if(!ErrorInfo.empty()) { // some errors occurred
+ delete OS;
+ return;
+ }
#endif
-#if defined(DEFAULT_X64_CODEGEN)
-# define TARGET_FMT_lx "%llx"
-#else
-# define TARGET_FMT_lx "%08x"
-#endif
- int Count;
- for( ; Length > 0; PC += Count, Length -= Count) {
- fprintf(out, "\t0x" TARGET_FMT_lx ": ", (bfd_vma) PC);
- Count = print_insn(PC, &disasm_info);
- fprintf(out, "\n");
+ *OS << "JIT: Disassembled code: " << Name
+ << ((IsStub) ? " (stub)" : "") << "\n";
+
+ if(mpAsmInfo == NULL)
+ mpAsmInfo = mpTarget->createAsmInfo(Triple);
+ if(mpDisassmbler == NULL)
+ mpDisassmbler = mpTarget->createMCDisassembler();
+ if(mpIP == NULL)
+ mpIP = mpTarget->createMCInstPrinter(
+ mpAsmInfo->getAssemblerDialect(), *mpAsmInfo);
+
+ const BufferMemoryObject* BufferMObj =
+ new BufferMemoryObject(Start, Length);
+ uint64_t Size;
+ uint64_t Index;
+
+ for(Index=0;Index<Length;Index+=Size) {
+ llvm::MCInst Inst;
+
+ if(mpDisassmbler->getInstruction(Inst, Size, *BufferMObj, Index,
+ /* REMOVED */ llvm::nulls()))
+ {
+ OS->indent(4).write("0x", 2).
+ write_hex((uint64_t) Start + Index).write(':');
+ mpIP->printInst(&Inst, *OS);
+ *OS << "\n";
+ } else {
+ if (Size == 0)
+ Size = 1; // skip illegible bytes
+ }
}
- fprintf(out, "\n");
-#undef TARGET_FMT_lx
+ *OS << "\n";
+ delete BufferMObj;
-#endif /* USE_DISASSEMBLER */
+#if 0
+ /* If you want the disassemble results write to file, uncomment this */
+ OS->close();
+ delete OS;
+#endif
+
return;
}
+#else
+ void Disassemble(const std::string& Name, uint8_t* Start,
+ size_t Length, bool IsStub) {
+ return;
+ }
+#endif /* defined(USE_DISASSEMBLER) */
public:
/* Will take the ownership of @MemMgr */
CodeEmitter(CodeMemoryManager* pMemMgr) :
mpMemMgr(pMemMgr),
+ mpTarget(NULL),
mpTJI(NULL),
mpTD(NULL),
+#if defined(USE_DISASSEMBLER)
+ mpAsmInfo(NULL),
+ mpDisassmbler(NULL),
+ mpIP(NULL),
+#endif
mpCurEmitFunction(NULL),
mpConstantPool(NULL),
mpJumpTable(NULL),
@@ -1998,6 +2063,8 @@
}
void setTargetMachine(llvm::TargetMachine& TM) {
+ /* set Target */
+ mpTarget = &TM.getTarget();
/* set TargetJITInfo */
mpTJI = TM.getJITInfo();
/* set TargetData */
@@ -2159,8 +2226,7 @@
/* Mark code region readable and executable if it's not so already. */
mpMemMgr->setMemoryExecutable();
- Disassembler(F.getFunction()->getNameStr(),
- FnStart, FnEnd - FnStart, (uintptr_t) FnStart);
+ Disassemble(F.getFunction()->getName(), FnStart, FnEnd - FnStart, false);
if(mpMMI)
mpMMI->EndFunction();
@@ -2339,8 +2405,7 @@
mpTJI->emitFunctionStub(F, Addr, *this);
finishGVStub();
- Disassembler(F->getNameStr() + " (stub)", (uint8_t*) Stub,
- SL.Size, (uintptr_t) Stub);
+ Disassemble(F->getName(), (uint8_t*) Stub, SL.Size, true);
PendingFunctions.erase(I);
@@ -2433,6 +2498,14 @@
~CodeEmitter() {
if(mpMemMgr)
delete mpMemMgr;
+#if defined(USE_DISASSEMBLER)
+ if(mpAsmInfo)
+ delete mpAsmInfo;
+ if(mpDisassmbler)
+ delete mpDisassmbler;
+ if(mpIP)
+ delete mpIP;
+#endif
return;
}
/* }}} */
@@ -2478,7 +2551,6 @@
SB = llvm::MemoryBuffer::getMemBuffer(
llvm::StringRef(bitcode, bitcodeSize));
if(SB == NULL) {
- //printf("ccc\n");
setError("Error reading input Bitcode into memory");
goto on_bcc_load_module_error;
}