Extract duplicated disassembler.

Change-Id: I6c607a0ed881dbd808ec43ec65e88f4ef06dea90
diff --git a/lib/Disassembler/Disassembler.cpp b/lib/Disassembler/Disassembler.cpp
new file mode 100644
index 0000000..29eecc7
--- /dev/null
+++ b/lib/Disassembler/Disassembler.cpp
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2011, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Disassembler.h"
+
+#include "Config.h"
+
+#include "ExecutionEngine/Compiler.h"
+
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCDisassembler.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstPrinter.h"
+
+#include "llvm/Support/MemoryObject.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
+#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Target/TargetSelect.h"
+
+#include "llvm/LLVMContext.h"
+
+#if USE_DISASSEMBLER
+
+namespace {
+
+class BufferMemoryObject : public llvm::MemoryObject {
+private:
+  const uint8_t *mBytes;
+  uint64_t mLength;
+
+public:
+  BufferMemoryObject(const uint8_t *Bytes, uint64_t Length)
+    : mBytes(Bytes), mLength(Length) {
+  }
+
+  virtual uint64_t getBase() const { return 0; }
+  virtual uint64_t getExtent() const { return mLength; }
+
+  virtual int readByte(uint64_t Addr, uint8_t *Byte) const {
+    if (Addr > getExtent())
+      return -1;
+    *Byte = mBytes[Addr];
+    return 0;
+  }
+};
+
+} // namespace anonymous
+
+namespace bcc {
+
+void InitializeDisassembler() {
+#if defined(DEFAULT_ARM_CODEGEN) || defined(PROVIDE_ARM_CODEGEN)
+  LLVMInitializeARMDisassembler();
+  LLVMInitializeARMAsmPrinter();
+#endif
+
+#if defined(DEFAULT_X86_CODEGEN) || defined(PROVIDE_X86_CODEGEN)
+  LLVMInitializeX86Disassembler();
+  LLVMInitializeX86AsmPrinter();
+#endif
+
+#if defined(DEFAULT_X64_CODEGEN) || defined(PROVIDE_X64_CODEGEN)
+  LLVMInitializeX86Disassembler();
+  LLVMInitializeX86AsmPrinter();
+#endif
+}
+
+void Disassemble(char const *OutputFileName,
+                 llvm::Target const *Target,
+                 llvm::TargetMachine *TM,
+                 std::string const &Name,
+                 unsigned char const *Func,
+                 size_t FuncSize) {
+  llvm::raw_ostream *OS;
+
+#if USE_DISASSEMBLER_FILE
+  std::string ErrorInfo;
+  OS = new llvm::raw_fd_ostream(OutputFileName, ErrorInfo,
+                                llvm::raw_fd_ostream::F_Append);
+
+  if (!ErrorInfo.empty()) {    // some errors occurred
+    // LOGE("Error in creating disassembly file");
+    delete OS;
+    return;
+  }
+#else
+  OS = &llvm::outs();
+#endif
+
+  *OS << "Disassembled code: " << Name << "\n";
+
+  const llvm::MCAsmInfo *AsmInfo;
+  const llvm::MCDisassembler *Disassmbler;
+  llvm::MCInstPrinter *IP;
+
+  AsmInfo = Target->createAsmInfo(Compiler::getTargetTriple());
+  Disassmbler = Target->createMCDisassembler();
+  IP = Target->createMCInstPrinter(*TM,
+                                   AsmInfo->getAssemblerDialect(),
+                                   *AsmInfo);
+
+  const BufferMemoryObject *BufferMObj = new BufferMemoryObject(Func, FuncSize);
+
+  uint64_t Size;
+  uint64_t Index;
+
+  for (Index = 0; Index < FuncSize; Index += Size) {
+    llvm::MCInst Inst;
+
+    if (Disassmbler->getInstruction(Inst, Size, *BufferMObj, Index,
+                                    /* REMOVED */ llvm::nulls())) {
+      OS->indent(4);
+      OS->write("0x", 2);
+      OS->write_hex((uint32_t)Func + Index);
+      OS->write(": 0x", 4);
+      OS->write_hex(*(uint32_t *)(Func + Index));
+      IP->printInst(&Inst, *OS);
+      *OS << "\n";
+    } else {
+      if (Size == 0)
+        Size = 1;  // skip illegible bytes
+    }
+  }
+
+  *OS << "\n";
+  delete BufferMObj;
+
+  delete AsmInfo;
+  delete Disassmbler;
+  delete IP;
+
+#if USE_DISASSEMBLER_FILE
+  ((llvm::raw_fd_ostream*)OS)->close();
+  delete OS;
+#endif
+}
+
+} // namespace bcc
+
+#endif // USE_DISASSEMBLER