Disassembler.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. #include <disasm.h> // Bochs
  2. #if defined(HAS_LLVM)
  3. // PowerPC.h defines PC.
  4. // This conflicts with a function that has an argument named PC
  5. #undef PC
  6. #include <llvm-c/Disassembler.h>
  7. #include <llvm-c/Target.h>
  8. #endif
  9. #include "Common/StringUtil.h"
  10. #include "Core/PowerPC/JitInterface.h"
  11. #include "Core/PowerPC/JitCommon/JitBase.h"
  12. #include "Core/PowerPC/JitCommon/JitCache.h"
  13. #include "UICommon/Disassembler.h"
  14. class HostDisassemblerX86 : public HostDisassembler
  15. {
  16. public:
  17. HostDisassemblerX86();
  18. private:
  19. disassembler m_disasm;
  20. std::string DisassembleHostBlock(const u8* code_start, const u32 code_size, u32* host_instructions_count) override;
  21. };
  22. #if defined(HAS_LLVM)
  23. class HostDisassemblerLLVM : public HostDisassembler
  24. {
  25. public:
  26. HostDisassemblerLLVM(const std::string host_disasm, int inst_size = -1, const std::string cpu = "");
  27. ~HostDisassemblerLLVM()
  28. {
  29. if (m_can_disasm)
  30. LLVMDisasmDispose(m_llvm_context);
  31. }
  32. private:
  33. bool m_can_disasm;
  34. LLVMDisasmContextRef m_llvm_context;
  35. int m_instruction_size;
  36. std::string DisassembleHostBlock(const u8* code_start, const u32 code_size, u32* host_instructions_count) override;
  37. };
  38. HostDisassemblerLLVM::HostDisassemblerLLVM(const std::string host_disasm, int inst_size, const std::string cpu)
  39. : m_can_disasm(false), m_instruction_size(inst_size)
  40. {
  41. LLVMInitializeAllTargetInfos();
  42. LLVMInitializeAllTargetMCs();
  43. LLVMInitializeAllDisassemblers();
  44. m_llvm_context = LLVMCreateDisasmCPU(host_disasm.c_str(), cpu.c_str(), nullptr, 0, 0, nullptr);
  45. // Couldn't create llvm context
  46. if (!m_llvm_context)
  47. return;
  48. LLVMSetDisasmOptions(m_llvm_context,
  49. LLVMDisassembler_Option_AsmPrinterVariant |
  50. LLVMDisassembler_Option_PrintLatency);
  51. m_can_disasm = true;
  52. }
  53. std::string HostDisassemblerLLVM::DisassembleHostBlock(const u8* code_start, const u32 code_size, u32 *host_instructions_count)
  54. {
  55. if (!m_can_disasm)
  56. return "(No LLVM context)";
  57. u8* disasmPtr = (u8*)code_start;
  58. const u8 *end = code_start + code_size;
  59. std::ostringstream x86_disasm;
  60. while ((u8*)disasmPtr < end)
  61. {
  62. char inst_disasm[256];
  63. size_t inst_size = LLVMDisasmInstruction(m_llvm_context, disasmPtr, (u64)(end - disasmPtr), (u64)disasmPtr, inst_disasm, 256);
  64. if (!inst_size)
  65. {
  66. x86_disasm << "Invalid inst:";
  67. if (m_instruction_size != -1)
  68. {
  69. // If we are on an architecture that has a fixed instruction size
  70. // We can continue onward past this bad instruction.
  71. std::string inst_str = "";
  72. for (int i = 0; i < m_instruction_size; ++i)
  73. inst_str += StringFromFormat("%02x", disasmPtr[i]);
  74. x86_disasm << inst_str << std::endl;
  75. disasmPtr += m_instruction_size;
  76. }
  77. else
  78. {
  79. // We can't continue if we are on an architecture that has flexible instruction sizes
  80. // Dump the rest of the block instead
  81. std::string code_block = "";
  82. for (int i = 0; (disasmPtr + i) < end; ++i)
  83. code_block += StringFromFormat("%02x", disasmPtr[i]);
  84. x86_disasm << code_block << std::endl;
  85. break;
  86. }
  87. }
  88. else
  89. {
  90. x86_disasm << inst_disasm << std::endl;
  91. disasmPtr += inst_size;
  92. }
  93. (*host_instructions_count)++;
  94. }
  95. return x86_disasm.str();
  96. }
  97. #endif
  98. HostDisassemblerX86::HostDisassemblerX86()
  99. {
  100. m_disasm.set_syntax_intel();
  101. }
  102. std::string HostDisassemblerX86::DisassembleHostBlock(const u8* code_start, const u32 code_size, u32* host_instructions_count)
  103. {
  104. u64 disasmPtr = (u64)code_start;
  105. const u8* end = code_start + code_size;
  106. std::ostringstream x86_disasm;
  107. while ((u8*)disasmPtr < end)
  108. {
  109. char inst_disasm[256];
  110. disasmPtr += m_disasm.disasm64(disasmPtr, disasmPtr, (u8*)disasmPtr, inst_disasm);
  111. x86_disasm << inst_disasm << std::endl;
  112. (*host_instructions_count)++;
  113. }
  114. return x86_disasm.str();
  115. }
  116. HostDisassembler* GetNewDisassembler(const std::string& arch)
  117. {
  118. #if defined(HAS_LLVM)
  119. if (arch == "x86")
  120. return new HostDisassemblerLLVM("x86_64-none-unknown");
  121. else if (arch == "aarch64")
  122. return new HostDisassemblerLLVM("aarch64-none-unknown", 4, "cortex-a57");
  123. else if (arch == "armv7")
  124. return new HostDisassemblerLLVM("armv7-none-unknown", 4, "cortex-a15");
  125. #elif defined(_M_X86)
  126. if (arch == "x86")
  127. new HostDisassemblerX86();
  128. #endif
  129. return new HostDisassembler();
  130. }
  131. std::string DisassembleBlock(HostDisassembler* disasm, u32* address, u32* host_instructions_count, u32* code_size)
  132. {
  133. const u8* code;
  134. int res = JitInterface::GetHostCode(address, &code, code_size);
  135. if (res == 1)
  136. {
  137. *host_instructions_count = 0;
  138. return "(No JIT active)";
  139. }
  140. else if (res == 2)
  141. {
  142. host_instructions_count = 0;
  143. return "(No translation)";
  144. }
  145. return disasm->DisassembleHostBlock(code, *code_size, host_instructions_count);
  146. }