diff --git a/src/core/config/VariantConfig.hpp.in b/src/core/config/VariantConfig.hpp.in index 19cffea6..73c7efc0 100644 --- a/src/core/config/VariantConfig.hpp.in +++ b/src/core/config/VariantConfig.hpp.in @@ -12,6 +12,7 @@ #cmakedefine BUILD_ARM #cmakedefine BUILD_LLVM_DISASSEMBLER +#cmakedefine BUILD_CAPSTONE_DISASSEMBLER #define ARCH_TOOL_PREFIX "@ARCH_TOOL_PREFIX@" diff --git a/src/core/util/CMakeLists.txt b/src/core/util/CMakeLists.txt index a2ec8bf0..5d8e9492 100644 --- a/src/core/util/CMakeLists.txt +++ b/src/core/util/CMakeLists.txt @@ -81,12 +81,22 @@ endif(CONFIG_INJECTIONPOINT_HOPS) add_library(fail-util ${SRCS}) add_dependencies(fail-util fail-comm) -target_link_libraries(fail-util fail-comm ${ADDITIONAL_LIBS} ${PROTOBUF_LIBRARY} ${Boost_LIBRARIES} ${LibIberty_LIBRARIES} ${ZLIB_LIBRARIES} ${LIBDWARF_LIBRARIES} ${LIBELF_LIBRARIES}) +target_link_libraries(fail-util fail-comm fail-sal ${ADDITIONAL_LIBS} ${PROTOBUF_LIBRARY} ${Boost_LIBRARIES} ${LibIberty_LIBRARIES} ${ZLIB_LIBRARIES} ${LIBDWARF_LIBRARIES} ${LIBELF_LIBRARIES}) + +option(BUILD_CAPSTONE_DISASSEMBLER "Build the Capstone-based disassembler (Capstone 4.0.1 required, higher versions may not work)" OFF) +if (BUILD_CAPSTONE_DISASSEMBLER) + add_subdirectory(capstonedisassembler) +endif (BUILD_CAPSTONE_DISASSEMBLER) option(BUILD_LLVM_DISASSEMBLER "Build the LLVM-based disassembler (LLVM 3.9, 4.0, 5.0 or 6.0 preferred, other versions may not work)" OFF) if (BUILD_LLVM_DISASSEMBLER) add_subdirectory(llvmdisassembler) endif (BUILD_LLVM_DISASSEMBLER) + +if (BUILD_CAPSTONE_DISASSEMBLER AND BUILD_LLVM_DISASSEMBLER) + message(FATAL_ERROR "BUILD_CAPSTONE_DISASSEMBLER and BUILD_LLVM_DISASSEMBLER can't be on at the same time!") +endif (BUILD_CAPSTONE_DISASSEMBLER AND BUILD_LLVM_DISASSEMBLER) + ### Tests add_executable(memorymap-test testing/memorymap-test.cc) target_link_libraries(memorymap-test fail-util) diff --git a/src/core/util/capstonedisassembler/CMakeLists.txt b/src/core/util/capstonedisassembler/CMakeLists.txt new file mode 100644 index 00000000..390b6b18 --- /dev/null +++ b/src/core/util/capstonedisassembler/CMakeLists.txt @@ -0,0 +1,26 @@ +set(SRCS + CapstoneDisassembler.cpp + CapstoneDisassembler.hpp + CapstoneToFailBochs.cpp + CapstoneToFailBochs.hpp + CapstoneToFailGem5.hpp + CapstoneToFailGem5.cpp + CapstoneToFailTranslator.cpp + CapstoneToFailTranslator.hpp +) + +include(FindCapstone) + +add_library(fail-capstonedisassembler ${SRCS}) + +target_link_libraries(fail-capstonedisassembler ${CAPSTONE_LIBRARY}) +include_directories(${CAPSTONE_INCLUDE_DIR}) + +### Tests +add_executable(capstoneDisTest testing/capstoneDisTest.cc) +target_link_libraries(capstoneDisTest fail-capstonedisassembler fail-sal) + +add_test(NAME capstoneDisx86Test COMMAND capstoneDisTest ${CMAKE_CURRENT_SOURCE_DIR}/testing/x86 ) +add_test(NAME capstoneDisx86_64Test COMMAND capstoneDisTest ${CMAKE_CURRENT_SOURCE_DIR}/testing/x86_64 ) +add_test(NAME capstoneDisARMM3Test COMMAND capstoneDisTest ${CMAKE_CURRENT_SOURCE_DIR}/testing/armm3 ) +add_test(NAME capstoneDisARM9Test COMMAND capstoneDisTest ${CMAKE_CURRENT_SOURCE_DIR}/testing/arm9 ) \ No newline at end of file diff --git a/src/core/util/capstonedisassembler/CapstoneDisassembler.cpp b/src/core/util/capstonedisassembler/CapstoneDisassembler.cpp new file mode 100644 index 00000000..0b2a5da5 --- /dev/null +++ b/src/core/util/capstonedisassembler/CapstoneDisassembler.cpp @@ -0,0 +1,281 @@ +#include "CapstoneDisassembler.hpp" + +using namespace fail; + + +CapstoneToFailTranslator *CapstoneDisassembler::getTranslator() { + if (ctofail == 0) { + switch (m_elf->m_machine) { + case EM_386: + case EM_X86_64: + ctofail = new CapstoneToFailBochs(); + break; + case EM_ARM: + ctofail = new CapstoneToFailGem5(); + break; + default: + std::cerr << "ArchType " + << m_elf->m_machine + << " not supported\n"; + exit(1); + } + } + return ctofail; +} + +std::map CapstoneDisassembler::get_symtab_map(uint32_t sect_size) { + // Make a list of all the symbols in this section. + std::vector > symbols; + for (ElfReader::container_t::const_iterator it = m_elf->sym_begin(); it != m_elf->sym_end(); ++it) { + + if (it->getSymbolType() != 2 /*SST_FUNC*/) { + continue; + } + + symbols.push_back(std::make_pair(it->getAddress(), it->getSize())); +#if 0 + std::cout << std::hex << it->getAddress() << "\t" << it->getSymbolType() << "\t" << it->getName().c_str() << "\t" << it->getSize() << std::endl; +#endif + } + + // Sort the symbols by address, just in case they didn't come in that way. + std::sort(symbols.begin(), symbols.end()); + + std::map symtab_map; + uint64_t start; + uint64_t end; // exclusive + for (unsigned si = 0, se = symbols.size(); si != se; ++si) { + start = symbols[si].first; + if (symbols[si].second == 0) { + // The end is either the size of the section or the beginning of the next symbol. + if (si == se - 1) + end = sect_size; + // Make sure this symbol takes up space. + else if (symbols[si + 1].first != start) + end = symbols[si + 1].first; + else + // This symbol has the same address as the next symbol. Skip it. + continue; + + symbols[si].second = end - start; + } + symtab_map[symbols[si].first] = symbols[si].second; + } +#if 0 + for (std::map::iterator it=symtab_map.begin(); it!=symtab_map.end(); ++it) + std::cout << std::hex << it->first << " => " << it->second << std::endl; +#endif + return symtab_map; +} + +int CapstoneDisassembler::disassemble_section(Elf_Data *data, Elf32_Shdr *shdr32, Elf64_Shdr *shdr64, std::map symtab_map) { +#if 0 + std::cout << std::dec << "bit: " << m_elf->m_elfclass << " 32: "<< ELFCLASS32 << " 64: " << ELFCLASS64 << " arch: " << m_elf->m_machine << " arm:" << EM_ARM << " x86: " << EM_386 << " x86_64: "<< EM_X86_64 << std::endl; +#endif + csh handle; + cs_insn *insn; + size_t count, j; + cs_regs regs_read, regs_write; + uint8_t read_count, write_count, i; + + cs_opt_skipdata skipdata = { + .mnemonic = "db", + }; + + // Arm may not work, because thumb is a problem + if (m_elf->m_machine == EM_386) { + if (cs_open(CS_ARCH_X86, CS_MODE_32, &handle) != CS_ERR_OK) + return -1; + } else if(m_elf->m_machine == EM_X86_64) { + if (cs_open(CS_ARCH_X86, CS_MODE_64, &handle) != CS_ERR_OK) + return -1; + } else if (m_elf->m_machine == EM_ARM) { + if (m_elf->m_elfclass == ELFCLASS32) { + if (cs_open(CS_ARCH_ARM, CS_MODE_ARM, &handle) != CS_ERR_OK) + return -1; + } else { + if (cs_open(CS_ARCH_ARM64, CS_MODE_ARM, &handle) != CS_ERR_OK) + return -1; + } + } + + cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON); + cs_option(handle, CS_OPT_SKIPDATA, CS_OPT_ON); + cs_option(handle, CS_OPT_SKIPDATA_SETUP, (size_t)&skipdata); + + int global_count = 0; + + for (std::map::iterator it=symtab_map.begin(); it!=symtab_map.end(); ++it) { + + if (m_elf->m_elfclass == ELFCLASS32) { + count = cs_disasm(handle, + (uint8_t *) ((uint64_t) data->d_buf + (uint64_t) it->first - (uint64_t) shdr32->sh_addr), + it->second, it->first, 0, &insn); + } else { + count = cs_disasm(handle, + (uint8_t *) ((uint64_t) data->d_buf + (uint64_t) it->first - (uint64_t) shdr64->sh_addr), + it->second, it->first, 0, &insn); + } + + if (count > 0) { + for (j = 0; j < count; j++) { + unsigned int opcode = 0; + if (m_elf->m_machine == EM_386 || m_elf->m_machine == EM_X86_64) { + opcode = (insn[j].detail->x86.opcode[3] << 24) | (insn[j].detail->x86.opcode[2] << 16) | + (insn[j].detail->x86.opcode[1] << 8) | insn[j].detail->x86.opcode[0]; + } else if (m_elf->m_machine == EM_ARM) { + // placeholder + opcode = 0; + } + + // Print assembly +#if 0 + printf("%s\t%s\n", insn[j].mnemonic, insn[j].op_str); + printf("Opcode: %x\t Adress: %lx\t Size: %d\n", opcode, insn[j].address, insn[j].size); +#endif + // Print all registers accessed by this instruction. + if (cs_regs_access(handle, &insn[j], regs_read, &read_count, regs_write, &write_count) == 0) { + Instr instr; + instr.opcode = opcode; + instr.length = insn[j].size; + instr.address = insn[j].address; + // FIXME could not find a functionality in capstone + instr.conditional_branch = false; + + if (read_count > 0) { +// printf("\n\tRegisters read:"); + for (i = 0; i < read_count; i++) { + instr.reg_uses.push_back(regs_read[i]); +// printf(" %s, %d |", cs_reg_name(handle, regs_read[i]), regs_read[i]); + } +// printf("\n"); + } + + if (write_count > 0) { +// printf("\n\tRegisters modified:"); + for (i = 0; i < write_count; i++) { + instr.reg_defs.push_back(regs_write[i]); +// printf(" %s, %d |", cs_reg_name(handle, regs_write[i]), regs_write[i]); + } +// printf("\n"); + } + (*instrs)[instr.address] = instr; + } +// printf("________________________________________________\n"); + } + global_count += count; + + cs_free(insn, count); + } else + std::cerr << "ERROR: Failed to disassemble given code!" << std::endl; + } +// printf("len_instr_map: %d\n", instrs->size()); + cs_close(&handle); +// printf("%d instructions\n", global_count); + return 0; +} + +void CapstoneDisassembler::disassemble() { + int fd; // File descriptor for the executable ELF file + char *section_name; + size_t shstrndx; + Elf *e; // ELF struct + Elf_Data *data = 0; + Elf_Scn *scn; // Section index struct + Elf32_Shdr *shdr32 = 0; // Section struct 32 Bit + Elf64_Shdr *shdr64 = 0; // Section struct 64 Bit + + if (elf_version(EV_CURRENT) == EV_NONE) + std::cerr << "ELF library initialization failed" << std::endl; + + if ((fd = open(m_elf->getFilename().c_str(), O_RDONLY, 0)) < 0) + std::cerr << "open " << m_elf->getFilename().c_str() << " failed" << std::endl; + + if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) + std::cerr << "elf_begin() failed" << std::endl; + + if (elf_kind(e) != ELF_K_ELF) { + std::cerr << m_elf->getFilename().c_str() << " is not an Elf object" << std::endl; + } + + if (elf_getshdrstrndx(e, &shstrndx) != 0) + std::cerr << "elf_getshdrstrndx() failed" << std::endl; + scn = NULL; + + // Loop over all sections in the ELF object + + while ((scn = elf_nextscn(e, scn)) != NULL) { + // Given an Elf Scn pointer, retrieve the associated section header + if (m_elf->m_elfclass == ELFCLASS32) { + if ((shdr32 = elf32_getshdr(scn)) == NULL) + std::cerr << "getshdr() failed" << std::endl; + + // Retrieve the name of the section + if ((section_name = elf_strptr(e, shstrndx, shdr32->sh_name)) == NULL) + std::cerr << "elf_strptr() failed" << std::endl; + + if (!strcmp(section_name, ".text")) { + if ((data = elf_rawdata(scn, data)) == NULL) { + std::cerr << "No section data available" << std::endl; + } +#if 0 + printf("Section name: %s\n", section_name); + printf("sh_offset: %x\n", shdr32->sh_offset); + printf("sh_type: %x\n", shdr32->sh_type); + printf("sh_flags: %x\n", shdr32->sh_flags); + printf("sh_addr: %x\n", shdr32->sh_addr); + printf("sh_size: %x\n", shdr32->sh_size); + printf("sh_link: %x\n", shdr32->sh_link); + printf("sh_info: %x\n", shdr32->sh_info); + printf("sh_addralign: %x\n", shdr32->sh_addralign); + printf("sh_entsize: %x\n", shdr32->sh_entsize); + printf("data: %x\n", data); + printf("buf: %x\n", data->d_buf); + printf("size: %d\n", data->d_size); +#endif + break; + } + } + else { + if ((shdr64 = elf64_getshdr(scn)) == NULL) + std::cerr << "getshdr() failed" << std::endl; + + // Retrieve the name of the section + if ((section_name = elf_strptr(e, shstrndx, shdr64->sh_name)) == NULL) + std::cerr << "elf_strptr() failed" << std::endl; + + if (!strcmp(section_name, ".text")) { + if ((data = elf_rawdata(scn, data)) == NULL) { + std::cerr << "No section data availible" << std::endl; + } +#if 0 + printf("Section name: %s\n", section_name); + printf("sh_offset: %lx\n", shdr64->sh_offset); + printf("sh_type: %lx\n", shdr64->sh_type); + printf("sh_flags: %lx\n", shdr64->sh_flags); + printf("sh_addr: %lx\n", shdr64->sh_addr); + printf("sh_size: %lx\n", shdr64->sh_size); + printf("sh_link: %lx\n", shdr64->sh_link); + printf("sh_info: %lx\n", shdr64->sh_info); + printf("sh_addralign: %lx\n", shdr64->sh_addralign); + printf("sh_entsize: %lx\n", shdr64->sh_entsize); + printf("data: %lx\n", data); + printf("buf: %lx\n", data->d_buf); + printf("size: %d\n", data->d_size); +#endif + break; + } + } + } + std::map symtab_map; + if (m_elf->m_elfclass == ELFCLASS32) { + symtab_map = get_symtab_map(shdr32->sh_size); + } else if (m_elf->m_elfclass == ELFCLASS64) { + symtab_map = get_symtab_map(shdr64->sh_size); + } + + disassemble_section(data, shdr32, shdr64, symtab_map); + + elf_end(e); + close(fd); +} diff --git a/src/core/util/capstonedisassembler/CapstoneDisassembler.hpp b/src/core/util/capstonedisassembler/CapstoneDisassembler.hpp new file mode 100644 index 00000000..86dd7517 --- /dev/null +++ b/src/core/util/capstonedisassembler/CapstoneDisassembler.hpp @@ -0,0 +1,84 @@ +#ifndef __CAPSTONEDISASSEMBLER_HPP__ +#define __CAPSTONEDISASSEMBLER_HPP__ + +#include +#include +#include +#include +#include // unique_ptr +#include + +#include + +#include "CapstoneToFailTranslator.hpp" +#include "CapstoneToFailBochs.hpp" +#include "CapstoneToFailGem5.hpp" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "util/ElfReader.hpp" + +namespace fail { + +class CapstoneDisassembler { + +public: + typedef uint16_t register_t; + typedef unsigned int address_t; + struct Instr { + unsigned int opcode; + unsigned int address; + unsigned char length; + bool conditional_branch; + std::vector reg_uses; + std::vector reg_defs; + }; + + typedef std::map InstrMap; + +private: + std::unique_ptr instrs; + fail::CapstoneToFailTranslator *ctofail; + fail::ElfReader *m_elf; + + static bool error(std::error_code ec) { + if (!ec) return false; + + std::cerr << "DIS error: " << ec.message() << ".\n"; + return true; + } + +public: + CapstoneDisassembler(fail::ElfReader *elf) : ctofail(0) { + this->m_elf = elf; + this->instrs.reset(new InstrMap()); + } + + ~CapstoneDisassembler() { delete ctofail; }; + + InstrMap &getInstrMap() { return *instrs; }; + fail::CapstoneToFailTranslator *getTranslator(); + + void disassemble(); + +private: + int disassemble_section(Elf_Data *data, Elf32_Shdr *shdr, Elf64_Shdr *shdr64, std::map symtab_map); + std::map get_symtab_map(uint32_t sect_size); +}; + +} +#endif // __CAPSTONEDISASSEMBLER_HPP__ diff --git a/src/core/util/capstonedisassembler/CapstoneToFailBochs.cpp b/src/core/util/capstonedisassembler/CapstoneToFailBochs.cpp new file mode 100644 index 00000000..209fdca0 --- /dev/null +++ b/src/core/util/capstonedisassembler/CapstoneToFailBochs.cpp @@ -0,0 +1,103 @@ +#include +#include "CapstoneToFailBochs.hpp" +#include "sal/x86/X86Architecture.hpp" + +using namespace fail; + +CapstoneToFailBochs::CapstoneToFailBochs() { + capstone_to_fail_map[X86_REG_AH] = reginfo_t(RID_CAX, 8, 8); + capstone_to_fail_map[X86_REG_AL] = reginfo_t(RID_CAX, 8); + capstone_to_fail_map[X86_REG_AX] = reginfo_t(RID_CAX, 16); + capstone_to_fail_map[X86_REG_EAX] = reginfo_t(RID_CAX, 32); + capstone_to_fail_map[X86_REG_RAX] = reginfo_t(RID_CAX, 64); + + capstone_to_fail_map[X86_REG_BH] = reginfo_t(RID_CBX, 8, 8); + capstone_to_fail_map[X86_REG_BL] = reginfo_t(RID_CBX, 8); + capstone_to_fail_map[X86_REG_BX] = reginfo_t(RID_CBX, 16); + capstone_to_fail_map[X86_REG_EBX] = reginfo_t(RID_CBX, 32); + capstone_to_fail_map[X86_REG_RBX] = reginfo_t(RID_CBX, 64); + + capstone_to_fail_map[X86_REG_CH] = reginfo_t(RID_CCX, 8, 8); + capstone_to_fail_map[X86_REG_CL] = reginfo_t(RID_CCX, 8); + capstone_to_fail_map[X86_REG_CX] = reginfo_t(RID_CCX, 16); + capstone_to_fail_map[X86_REG_ECX] = reginfo_t(RID_CCX, 32); + capstone_to_fail_map[X86_REG_RCX] = reginfo_t(RID_CCX, 64); + + capstone_to_fail_map[X86_REG_DH] = reginfo_t(RID_CDX, 8, 8); + capstone_to_fail_map[X86_REG_DL] = reginfo_t(RID_CDX, 8); + capstone_to_fail_map[X86_REG_DX] = reginfo_t(RID_CDX, 16); + capstone_to_fail_map[X86_REG_EDX] = reginfo_t(RID_CDX, 32); + capstone_to_fail_map[X86_REG_RDX] = reginfo_t(RID_CDX, 64); + + capstone_to_fail_map[X86_REG_R8] = reginfo_t(RID_R8, 64); + capstone_to_fail_map[X86_REG_R8D] = reginfo_t(RID_R8, 32); + capstone_to_fail_map[X86_REG_R8W] = reginfo_t(RID_R8, 16); + capstone_to_fail_map[X86_REG_R8B] = reginfo_t(RID_R8, 8); + capstone_to_fail_map[X86_REG_R9] = reginfo_t(RID_R9, 64); + capstone_to_fail_map[X86_REG_R9D] = reginfo_t(RID_R9, 32); + capstone_to_fail_map[X86_REG_R9W] = reginfo_t(RID_R9, 16); + capstone_to_fail_map[X86_REG_R9B] = reginfo_t(RID_R9, 8); + capstone_to_fail_map[X86_REG_R10] = reginfo_t(RID_R10, 64); + capstone_to_fail_map[X86_REG_R10D] = reginfo_t(RID_R10, 32); + capstone_to_fail_map[X86_REG_R10W] = reginfo_t(RID_R10, 16); + capstone_to_fail_map[X86_REG_R10B] = reginfo_t(RID_R10, 8); + capstone_to_fail_map[X86_REG_R11] = reginfo_t(RID_R11, 64); + capstone_to_fail_map[X86_REG_R11D] = reginfo_t(RID_R11, 32); + capstone_to_fail_map[X86_REG_R11W] = reginfo_t(RID_R11, 16); + capstone_to_fail_map[X86_REG_R11B] = reginfo_t(RID_R11, 8); + capstone_to_fail_map[X86_REG_R12] = reginfo_t(RID_R12, 64); + capstone_to_fail_map[X86_REG_R12D] = reginfo_t(RID_R12, 32); + capstone_to_fail_map[X86_REG_R12W] = reginfo_t(RID_R12, 16); + capstone_to_fail_map[X86_REG_R12B] = reginfo_t(RID_R12, 8); + capstone_to_fail_map[X86_REG_R13] = reginfo_t(RID_R13, 64); + capstone_to_fail_map[X86_REG_R13D] = reginfo_t(RID_R13, 32); + capstone_to_fail_map[X86_REG_R13W] = reginfo_t(RID_R13, 16); + capstone_to_fail_map[X86_REG_R13B] = reginfo_t(RID_R13, 8); + capstone_to_fail_map[X86_REG_R14] = reginfo_t(RID_R14, 64); + capstone_to_fail_map[X86_REG_R14D] = reginfo_t(RID_R14, 32); + capstone_to_fail_map[X86_REG_R14W] = reginfo_t(RID_R14, 16); + capstone_to_fail_map[X86_REG_R14B] = reginfo_t(RID_R14, 8); + capstone_to_fail_map[X86_REG_R15] = reginfo_t(RID_R15, 64); + capstone_to_fail_map[X86_REG_R15D] = reginfo_t(RID_R15, 32); + capstone_to_fail_map[X86_REG_R15W] = reginfo_t(RID_R15, 16); + capstone_to_fail_map[X86_REG_R15B] = reginfo_t(RID_R15, 8); + + capstone_to_fail_map[X86_REG_DIL] = reginfo_t(RID_CDI, 8); + capstone_to_fail_map[X86_REG_DI] = reginfo_t(RID_CDI, 16); + capstone_to_fail_map[X86_REG_EDI] = reginfo_t(RID_CDI, 32); + capstone_to_fail_map[X86_REG_RDI] = reginfo_t(RID_CDI, 64); + + capstone_to_fail_map[X86_REG_BPL] = reginfo_t(RID_CBP, 8); + capstone_to_fail_map[X86_REG_BP] = reginfo_t(RID_CBP, 16); + capstone_to_fail_map[X86_REG_EBP] = reginfo_t(RID_CBP, 32); + capstone_to_fail_map[X86_REG_RBP] = reginfo_t(RID_CBP, 64); + + capstone_to_fail_map[X86_REG_EFLAGS] = reginfo_t(RID_FLAGS, 64); + // RFLAGS doesn't exist in the x86.h of capstone, therefore X86_REG_EFLAGS is set to 64bit + // capstone_to_fail_map[RFLAGS] = reginfo_t(RID_FLAGS, 64); + + capstone_to_fail_map[X86_REG_EIP] = reginfo_t(RID_PC, 32); + capstone_to_fail_map[X86_REG_RIP] = reginfo_t(RID_PC, 64); + + capstone_to_fail_map[X86_REG_SIL] = reginfo_t(RID_CSI, 8); + capstone_to_fail_map[X86_REG_SI] = reginfo_t(RID_CSI, 16); + capstone_to_fail_map[X86_REG_ESI] = reginfo_t(RID_CSI, 32); + capstone_to_fail_map[X86_REG_RSI] = reginfo_t(RID_CSI, 64); + + capstone_to_fail_map[X86_REG_SPL] = reginfo_t(RID_CSP, 8); + capstone_to_fail_map[X86_REG_SP] = reginfo_t(RID_CSP, 16); + capstone_to_fail_map[X86_REG_ESP] = reginfo_t(RID_CSP, 32); + capstone_to_fail_map[X86_REG_RSP] = reginfo_t(RID_CSP, 64); + + capstone_to_fail_map[X86_REG_CR0] = reginfo_t(RID_CR0); + capstone_to_fail_map[X86_REG_CR2] = reginfo_t(RID_CR2); + capstone_to_fail_map[X86_REG_CR3] = reginfo_t(RID_CR3); + capstone_to_fail_map[X86_REG_CR4] = reginfo_t(RID_CR4); + + capstone_to_fail_map[X86_REG_CS] = reginfo_t(RID_CS, 16); + capstone_to_fail_map[X86_REG_DS] = reginfo_t(RID_DS, 16); + capstone_to_fail_map[X86_REG_ES] = reginfo_t(RID_ES, 16); + capstone_to_fail_map[X86_REG_FS] = reginfo_t(RID_FS, 16); + capstone_to_fail_map[X86_REG_GS] = reginfo_t(RID_GS, 16); + capstone_to_fail_map[X86_REG_SS] = reginfo_t(RID_SS, 16); +} diff --git a/src/core/util/capstonedisassembler/CapstoneToFailBochs.hpp b/src/core/util/capstonedisassembler/CapstoneToFailBochs.hpp new file mode 100644 index 00000000..22763931 --- /dev/null +++ b/src/core/util/capstonedisassembler/CapstoneToFailBochs.hpp @@ -0,0 +1,14 @@ +#ifndef __CAPSTONETOFAILBOCHS_HPP_ +#define __CAPSTONETOFAILBOCHS_HPP_ + +#include "CapstoneToFailTranslator.hpp" + +namespace fail { + +class CapstoneToFailBochs : public CapstoneToFailTranslator { +public: + CapstoneToFailBochs(); +}; +} // end of namespace + +#endif diff --git a/src/core/util/capstonedisassembler/CapstoneToFailGem5.cpp b/src/core/util/capstonedisassembler/CapstoneToFailGem5.cpp new file mode 100644 index 00000000..15d8322c --- /dev/null +++ b/src/core/util/capstonedisassembler/CapstoneToFailGem5.cpp @@ -0,0 +1,24 @@ +#include +#include "CapstoneToFailGem5.hpp" +#include "sal/arm/ArmArchitecture.hpp" + +using namespace fail; + +CapstoneToFailGem5::CapstoneToFailGem5() { + capstone_to_fail_map[ARM_REG_R0] = reginfo_t(RI_R0); + capstone_to_fail_map[ARM_REG_R1] = reginfo_t(RI_R1); + capstone_to_fail_map[ARM_REG_R2] = reginfo_t(RI_R2); + capstone_to_fail_map[ARM_REG_R3] = reginfo_t(RI_R3); + capstone_to_fail_map[ARM_REG_R4] = reginfo_t(RI_R4); + capstone_to_fail_map[ARM_REG_R5] = reginfo_t(RI_R5); + capstone_to_fail_map[ARM_REG_R6] = reginfo_t(RI_R6); + capstone_to_fail_map[ARM_REG_R7] = reginfo_t(RI_R7); + capstone_to_fail_map[ARM_REG_R8] = reginfo_t(RI_R8); + capstone_to_fail_map[ARM_REG_R9] = reginfo_t(RI_R9); + capstone_to_fail_map[ARM_REG_R10] = reginfo_t(RI_R10); + capstone_to_fail_map[ARM_REG_R11] = reginfo_t(RI_R11); + capstone_to_fail_map[ARM_REG_R12] = reginfo_t(RI_R12); + capstone_to_fail_map[ARM_REG_SP] = reginfo_t(RI_SP); + capstone_to_fail_map[ARM_REG_LR] = reginfo_t(RI_LR); + capstone_to_fail_map[ARM_REG_PC] = reginfo_t(RI_IP); +} diff --git a/src/core/util/capstonedisassembler/CapstoneToFailGem5.hpp b/src/core/util/capstonedisassembler/CapstoneToFailGem5.hpp new file mode 100644 index 00000000..ebc9d973 --- /dev/null +++ b/src/core/util/capstonedisassembler/CapstoneToFailGem5.hpp @@ -0,0 +1,14 @@ +#ifndef __CAPSTONETOFAILGEM5_HPP_ +#define __CAPSTONETOFAILGEM5_HPP_ + +#include "CapstoneToFailTranslator.hpp" + +namespace fail { + +class CapstoneToFailGem5 : public CapstoneToFailTranslator { +public: + CapstoneToFailGem5(); +}; +} // end of namespace + +#endif // __CAPSTONETOFAILGEM5_HPP_ diff --git a/src/core/util/capstonedisassembler/CapstoneToFailTranslator.cpp b/src/core/util/capstonedisassembler/CapstoneToFailTranslator.cpp new file mode 100644 index 00000000..a406c0ea --- /dev/null +++ b/src/core/util/capstonedisassembler/CapstoneToFailTranslator.cpp @@ -0,0 +1,50 @@ +#include +#include "CapstoneToFailTranslator.hpp" +#include "sal/SALInst.hpp" + +using namespace fail; + +const CapstoneToFailTranslator::reginfo_t & CapstoneToFailTranslator::getFailRegisterInfo(unsigned int regid) { + ctof_map_t::iterator it = capstone_to_fail_map.find(regid); + if ( it != capstone_to_fail_map.end() ) {// found + return (*it).second; + } else { // not found +// std::cout << "Fail ID for Capstone Register id " << std::dec << regid << " not found :(" << std::endl; +// exit(EXIT_FAILURE); + return notfound; + } +} + +regdata_t CapstoneToFailTranslator::getRegisterContent(ConcreteCPU& cpu, const reginfo_t ®info){ + regdata_t result; + + Register* reg = cpu.getRegister(reginfo.id); + result = cpu.getRegisterContent(reg); + + result &= reginfo.mask; + result >>= reginfo.offset; + + return result; +} + +void CapstoneToFailTranslator::setRegisterContent(ConcreteCPU & cpu, const reginfo_t ®info, regdata_t value){ + Register* reg = cpu.getRegister(reginfo.id); + + regdata_t origval = cpu.getRegisterContent(reg); // Get register Value from fail + origval &= ~(reginfo.mask); // clear bits to write + + value <<= reginfo.offset; // shift value to write up to position + value &= reginfo.mask; // mask out trailing and leading bits + value |= origval; // set bits to write + + cpu.setRegisterContent( reg, value ); // write back register content +} + +int CapstoneToFailTranslator::getMaxFailRegisterID() +{ + auto max = std::max_element(capstone_to_fail_map.cbegin(), capstone_to_fail_map.cend(), + [] (const ctof_map_t::value_type& v1, const ctof_map_t::value_type& v2) { + return v1.second.id < v2.second.id; + }); + return max->second.id; +} diff --git a/src/core/util/capstonedisassembler/CapstoneToFailTranslator.hpp b/src/core/util/capstonedisassembler/CapstoneToFailTranslator.hpp new file mode 100644 index 00000000..e1e777fb --- /dev/null +++ b/src/core/util/capstonedisassembler/CapstoneToFailTranslator.hpp @@ -0,0 +1,93 @@ +#ifndef __CAPSTONETOFAILTRANSLATOR_HPP_ +#define __CAPSTONETOFAILTRANSLATOR_HPP_ + +#include "sal/SALConfig.hpp" +#include "sal/ConcreteCPU.hpp" +#include + +namespace fail { + +/** + * Translates Capstone disassembler ids + * to FAIL* SAL representations. + */ +class CapstoneToFailTranslator { +public: + /** + * Maps registers to/from linear addresses usable for def/use-pruning + * purposes and storage in the database. Takes care that the linear + * addresses of x86 subregisters (e.g., AX represents the lower 16 bits of + * EAX) overlap with their siblings. + */ + struct reginfo_t { + int id; + regwidth_t width; + regdata_t mask; + byte_t offset; + + int toDataAddress() const { + // .. 5 4 | 3 2 1 0 + // | + return (id << 4) | (offset / 8); + } + + static reginfo_t fromDataAddress(int addr, int width) { + int id = addr >> 4; + byte_t offset = (addr & 0xf) * 8; + return reginfo_t(id, width * 8, offset); + } + + reginfo_t(int id=-1, regwidth_t width = 32, byte_t offs = 0) + : id(id), width(width), mask((((regdata_t) 1 << width) - 1) << offs), offset(offs) + { + if (width >= sizeof(regdata_t) * 8) { // all ones, (1 << width) == 0! + mask = -1; + } +#if 0 + std::cerr << "constructing reginfo_t: " << std::dec << id << " " << width << " " << ((int)offs) << std::hex << " 0x" << mask << std::endl; +#endif + } + }; +protected: + + CapstoneToFailTranslator(){}; + + typedef std::map ctof_map_t; + ctof_map_t capstone_to_fail_map; + +public: + /** + * Translates a backend-specific register ID to a Fail register ID. + * @param regid A backend-specific register ID. + * @return A FAIL* register-info struct, or CapstonetoFailTranslator::notfound + * if no mapping was found. + */ + const reginfo_t & getFailRegisterInfo(unsigned int regid); + + static regdata_t getRegisterContent(ConcreteCPU & cpu, const reginfo_t & reg); + static void setRegisterContent(ConcreteCPU & cpu, const reginfo_t ®, regdata_t value); + regdata_t getRegisterContent(ConcreteCPU & cpu, unsigned int csid) { + return getRegisterContent(cpu, getFailRegisterInfo(csid)); + } + void setRegisterContent(ConcreteCPU & cpu, unsigned int csid, regdata_t value) { + setRegisterContent(cpu, getFailRegisterInfo(csid), value); + } + + /** + * Translates a backend-specific register ID to a Fail register ID. + * @param regid A backend-specific register ID. + * @return A FAIL* register ID. May do funny things if regid does not exist. + */ + int getFailRegisterID(unsigned int regid) { return this->getFailRegisterInfo(regid).id; }; + + int getMaxFailRegisterID(); + fail::address_t getMaxDataAddress() { reginfo_t r(getMaxFailRegisterID() + 1); return r.toDataAddress() - 1; } + + reginfo_t notfound; + +// static CapstoneToFailTranslator* createFromBinary(const std::string elf_path); +}; + +} // end of namespace + +#endif diff --git a/src/core/util/capstonedisassembler/testing/armm3 b/src/core/util/capstonedisassembler/testing/armm3 new file mode 100755 index 00000000..637f00bc Binary files /dev/null and b/src/core/util/capstonedisassembler/testing/armm3 differ diff --git a/src/core/util/capstonedisassembler/testing/armregs.txt b/src/core/util/capstonedisassembler/testing/armregs.txt new file mode 100644 index 00000000..3b6c21cb --- /dev/null +++ b/src/core/util/capstonedisassembler/testing/armregs.txt @@ -0,0 +1,281 @@ +Triple: arm-unknown-unknown + +Number of Registers: 278 +0 - NOREG +1 - APSR +2 - CPSR +3 - D0 +4 - D1 +5 - D2 +6 - D3 +7 - D4 +8 - D5 +9 - D6 +10 - D7 +11 - D8 +12 - D9 +13 - D10 +14 - D11 +15 - D12 +16 - D13 +17 - D14 +18 - D15 +19 - D16 +20 - D17 +21 - D18 +22 - D19 +23 - D20 +24 - D21 +25 - D22 +26 - D23 +27 - D24 +28 - D25 +29 - D26 +30 - D27 +31 - D28 +32 - D29 +33 - D30 +34 - D31 +35 - FPEXC +36 - FPSCR +37 - FPSCR_NZCV +38 - FPSID +39 - ITSTATE +40 - LR +41 - MVFR0 +42 - MVFR1 +43 - PC +44 - Q0 +45 - Q1 +46 - Q2 +47 - Q3 +48 - Q4 +49 - Q5 +50 - Q6 +51 - Q7 +52 - Q8 +53 - Q9 +54 - Q10 +55 - Q11 +56 - Q12 +57 - Q13 +58 - Q14 +59 - Q15 +60 - R0 +61 - R1 +62 - R2 +63 - R3 +64 - R4 +65 - R5 +66 - R6 +67 - R7 +68 - R8 +69 - R9 +70 - R10 +71 - R11 +72 - R12 +73 - S0 +74 - S1 +75 - S2 +76 - S3 +77 - S4 +78 - S5 +79 - S6 +80 - S7 +81 - S8 +82 - S9 +83 - S10 +84 - S11 +85 - S12 +86 - S13 +87 - S14 +88 - S15 +89 - S16 +90 - S17 +91 - S18 +92 - S19 +93 - S20 +94 - S21 +95 - S22 +96 - S23 +97 - S24 +98 - S25 +99 - S26 +100 - S27 +101 - S28 +102 - S29 +103 - S30 +104 - S31 +105 - SP +106 - SPSR +107 - D0_D2 +108 - D1_D3 +109 - D2_D4 +110 - D3_D5 +111 - D4_D6 +112 - D5_D7 +113 - D6_D8 +114 - D7_D9 +115 - D8_D10 +116 - D9_D11 +117 - D10_D12 +118 - D11_D13 +119 - D12_D14 +120 - D13_D15 +121 - D14_D16 +122 - D15_D17 +123 - D16_D18 +124 - D17_D19 +125 - D18_D20 +126 - D19_D21 +127 - D20_D22 +128 - D21_D23 +129 - D22_D24 +130 - D23_D25 +131 - D24_D26 +132 - D25_D27 +133 - D26_D28 +134 - D27_D29 +135 - D28_D30 +136 - D29_D31 +137 - Q0_Q1 +138 - Q1_Q2 +139 - Q2_Q3 +140 - Q3_Q4 +141 - Q4_Q5 +142 - Q5_Q6 +143 - Q6_Q7 +144 - Q7_Q8 +145 - Q8_Q9 +146 - Q9_Q10 +147 - Q10_Q11 +148 - Q11_Q12 +149 - Q12_Q13 +150 - Q13_Q14 +151 - Q14_Q15 +152 - Q0_Q1_Q2_Q3 +153 - Q1_Q2_Q3_Q4 +154 - Q2_Q3_Q4_Q5 +155 - Q3_Q4_Q5_Q6 +156 - Q4_Q5_Q6_Q7 +157 - Q5_Q6_Q7_Q8 +158 - Q6_Q7_Q8_Q9 +159 - Q7_Q8_Q9_Q10 +160 - Q8_Q9_Q10_Q11 +161 - Q9_Q10_Q11_Q12 +162 - Q10_Q11_Q12_Q13 +163 - Q11_Q12_Q13_Q14 +164 - Q12_Q13_Q14_Q15 +165 - D0_D1_D2 +166 - D1_D2_D3 +167 - D2_D3_D4 +168 - D3_D4_D5 +169 - D4_D5_D6 +170 - D5_D6_D7 +171 - D6_D7_D8 +172 - D7_D8_D9 +173 - D8_D9_D10 +174 - D9_D10_D11 +175 - D10_D11_D12 +176 - D11_D12_D13 +177 - D12_D13_D14 +178 - D13_D14_D15 +179 - D14_D15_D16 +180 - D15_D16_D17 +181 - D16_D17_D18 +182 - D17_D18_D19 +183 - D18_D19_D20 +184 - D19_D20_D21 +185 - D20_D21_D22 +186 - D21_D22_D23 +187 - D22_D23_D24 +188 - D23_D24_D25 +189 - D24_D25_D26 +190 - D25_D26_D27 +191 - D26_D27_D28 +192 - D27_D28_D29 +193 - D28_D29_D30 +194 - D29_D30_D31 +195 - D0_D2_D4 +196 - D1_D3_D5 +197 - D2_D4_D6 +198 - D3_D5_D7 +199 - D4_D6_D8 +200 - D5_D7_D9 +201 - D6_D8_D10 +202 - D7_D9_D11 +203 - D8_D10_D12 +204 - D9_D11_D13 +205 - D10_D12_D14 +206 - D11_D13_D15 +207 - D12_D14_D16 +208 - D13_D15_D17 +209 - D14_D16_D18 +210 - D15_D17_D19 +211 - D16_D18_D20 +212 - D17_D19_D21 +213 - D18_D20_D22 +214 - D19_D21_D23 +215 - D20_D22_D24 +216 - D21_D23_D25 +217 - D22_D24_D26 +218 - D23_D25_D27 +219 - D24_D26_D28 +220 - D25_D27_D29 +221 - D26_D28_D30 +222 - D27_D29_D31 +223 - D0_D2_D4_D6 +224 - D1_D3_D5_D7 +225 - D2_D4_D6_D8 +226 - D3_D5_D7_D9 +227 - D4_D6_D8_D10 +228 - D5_D7_D9_D11 +229 - D6_D8_D10_D12 +230 - D7_D9_D11_D13 +231 - D8_D10_D12_D14 +232 - D9_D11_D13_D15 +233 - D10_D12_D14_D16 +234 - D11_D13_D15_D17 +235 - D12_D14_D16_D18 +236 - D13_D15_D17_D19 +237 - D14_D16_D18_D20 +238 - D15_D17_D19_D21 +239 - D16_D18_D20_D22 +240 - D17_D19_D21_D23 +241 - D18_D20_D22_D24 +242 - D19_D21_D23_D25 +243 - D20_D22_D24_D26 +244 - D21_D23_D25_D27 +245 - D22_D24_D26_D28 +246 - D23_D25_D27_D29 +247 - D24_D26_D28_D30 +248 - D25_D27_D29_D31 +249 - D1_D2 +250 - D3_D4 +251 - D5_D6 +252 - D7_D8 +253 - D9_D10 +254 - D11_D12 +255 - D13_D14 +256 - D15_D16 +257 - D17_D18 +258 - D19_D20 +259 - D21_D22 +260 - D23_D24 +261 - D25_D26 +262 - D27_D28 +263 - D29_D30 +264 - D1_D2_D3_D4 +265 - D3_D4_D5_D6 +266 - D5_D6_D7_D8 +267 - D7_D8_D9_D10 +268 - D9_D10_D11_D12 +269 - D11_D12_D13_D14 +270 - D13_D14_D15_D16 +271 - D15_D16_D17_D18 +272 - D17_D18_D19_D20 +273 - D19_D20_D21_D22 +274 - D21_D22_D23_D24 +275 - D23_D24_D25_D26 +276 - D25_D26_D27_D28 +277 - D27_D28_D29_D30 diff --git a/src/core/util/capstonedisassembler/testing/bubble.cc b/src/core/util/capstonedisassembler/testing/bubble.cc new file mode 100644 index 00000000..c9685e33 --- /dev/null +++ b/src/core/util/capstonedisassembler/testing/bubble.cc @@ -0,0 +1,71 @@ +#include + +class random_generator_t +{ +private: + unsigned int a; // (sqrt(5)-1)/2 = 0.61803398875 + unsigned int b; + unsigned int last_val; + unsigned int sd; +public: + void forth() { + last_val = a*last_val + b; + } + + + random_generator_t(unsigned int seed = 1) + : a(2654435769), b(seed), last_val(1), sd(seed){ + forth(); + } + + unsigned int item() const { + return last_val; + } + + void reset() { + last_val = 1; + b = sd; + forth(); + } +}; + + + + +void sort(int len, int arr[] ) +{ + int tmp; + int again; + int i; + + for(again=1; again; ) + for( again=0, i=0; i < (len-1); ++i){ + assert(0<=i && i+1 arr[i+1] ){ + tmp = arr[i]; + arr[i] = arr[i+1]; + arr[i+1] = tmp; + again = 1; + } + } +} + + + + +int main() +{ + const unsigned int arr_size = 10000; //50000; + + int arr[arr_size]; + int i; + random_generator_t rand; + + for(i=0; i!=arr_size; ++i){ + arr[i] = rand.item(); + rand.forth(); + } + + sort(arr_size, arr); +} + diff --git a/src/core/util/capstonedisassembler/testing/capstoneDisTest.cc b/src/core/util/capstonedisassembler/testing/capstoneDisTest.cc new file mode 100644 index 00000000..ba3d9247 --- /dev/null +++ b/src/core/util/capstonedisassembler/testing/capstoneDisTest.cc @@ -0,0 +1,63 @@ +#include "util/ElfReader.hpp" +#include +#include "../CapstoneDisassembler.hpp" + +using namespace fail; + +bool show_mapping(fail::CapstoneToFailTranslator *ctof, unsigned llvmid) +{ + const CapstoneToFailTranslator::reginfo_t& failreg = ctof->getFailRegisterInfo(llvmid); + std::cout /*<< reg_info.getName(llvmid)*/ << "(" << std::dec << llvmid << "->"; + if (&failreg != &ctof->notfound) { + std::cout << failreg.id; + } else { + std::cout << "NOTFOUND!"; + } + std::cout << ") "; + return &failreg != &ctof->notfound; +} + +int main(int argc, char* argv[]) { + std::string file; + + if(argc > 1){ + std::cout << "Trying to disassemble: " << argv[1] << std::endl; + file = argv[1]; + } else { + std::cerr << "No file to disassemble :(" << std::endl; + return -1; + } + + ElfReader *m_elf = new ElfReader(file.c_str()); + + CapstoneDisassembler disas(m_elf); + disas.disassemble(); + + CapstoneDisassembler::InstrMap &instr_map = disas.getInstrMap(); + std::cout << "Map Size: " << instr_map.size() << std::endl; + + CapstoneDisassembler::InstrMap::const_iterator itr; + + fail::CapstoneToFailTranslator *ctof = disas.getTranslator(); + + for (itr = instr_map.begin(); itr != instr_map.end(); ++itr){ + const CapstoneDisassembler::Instr &instr = (*itr).second; + std::cout << std::hex << (*itr).first << " | " << instr.opcode << std::endl; + std::cout << std::dec << "USES: "; + for (std::vector::const_iterator it = instr.reg_uses.begin(); + it != instr.reg_uses.end(); ++it) { + show_mapping(ctof, *it); + } + + std::cout << " | DEFS: "; + for (std::vector::const_iterator it = instr.reg_defs.begin(); + it != instr.reg_defs.end(); ++it) { + show_mapping(ctof, *it); + } + + if (instr.conditional_branch) { + std::cout << "(conditional branch)"; + } + std::cout << std::endl; + } +} diff --git a/src/core/util/capstonedisassembler/testing/howtobuild.txt b/src/core/util/capstonedisassembler/testing/howtobuild.txt new file mode 100644 index 00000000..5b678fd1 --- /dev/null +++ b/src/core/util/capstonedisassembler/testing/howtobuild.txt @@ -0,0 +1,4 @@ +g++ -m32 bubble.cc -o x86 +g++ -m64 bubble.cc -o x86_64 +arm-none-eabi-g++ -mcpu=cortex-m3 bubble.cc -o armm3 +arm-none-eabi-g++ -mcpu=arm9 bubble.cc -o arm9 diff --git a/src/core/util/capstonedisassembler/testing/x86regs.txt b/src/core/util/capstonedisassembler/testing/x86regs.txt new file mode 100644 index 00000000..bc01c6c5 --- /dev/null +++ b/src/core/util/capstonedisassembler/testing/x86regs.txt @@ -0,0 +1,163 @@ +Triple: x86_64-unknown-unknown + +Number of Registers: 160 +0 - NOREG +1 - AH +2 - AL +3 - AX +4 - BH +5 - BL +6 - BP +7 - BPL +8 - BX +9 - CH +10 - CL +11 - CR0 +12 - CR1 +13 - CR2 +14 - CR3 +15 - CR4 +16 - CR5 +17 - CR6 +18 - CR7 +19 - CR8 +20 - CR9 +21 - CR10 +22 - CR11 +23 - CR12 +24 - CR13 +25 - CR14 +26 - CR15 +27 - CS +28 - CX +29 - DH +30 - DI +31 - DIL +32 - DL +33 - DR0 +34 - DR1 +35 - DR2 +36 - DR3 +37 - DR4 +38 - DR5 +39 - DR6 +40 - DR7 +41 - DS +42 - DX +43 - EAX +44 - EBP +45 - EBX +46 - ECX +47 - EDI +48 - EDX +49 - EFLAGS +50 - EIP +51 - EIZ +52 - ES +53 - ESI +54 - ESP +55 - FP0 +56 - FP1 +57 - FP2 +58 - FP3 +59 - FP4 +60 - FP5 +61 - FP6 +62 - FS +63 - GS +64 - IP +65 - MM0 +66 - MM1 +67 - MM2 +68 - MM3 +69 - MM4 +70 - MM5 +71 - MM6 +72 - MM7 +73 - R8 +74 - R8B +75 - R8D +76 - R8W +77 - R9 +78 - R9B +79 - R9D +80 - R9W +81 - R10 +82 - R10B +83 - R10D +84 - R10W +85 - R11 +86 - R11B +87 - R11D +88 - R11W +89 - R12 +90 - R12B +91 - R12D +92 - R12W +93 - R13 +94 - R13B +95 - R13D +96 - R13W +97 - R14 +98 - R14B +99 - R14D +100 - R14W +101 - R15 +102 - R15B +103 - R15D +104 - R15W +105 - RAX +106 - RBP +107 - RBX +108 - RCX +109 - RDI +110 - RDX +111 - RIP +112 - RIZ +113 - RSI +114 - RSP +115 - SI +116 - SIL +117 - SP +118 - SPL +119 - SS +120 - ST0 +121 - ST1 +122 - ST2 +123 - ST3 +124 - ST4 +125 - ST5 +126 - ST6 +127 - ST7 +128 - XMM0 +129 - XMM1 +130 - XMM2 +131 - XMM3 +132 - XMM4 +133 - XMM5 +134 - XMM6 +135 - XMM7 +136 - XMM8 +137 - XMM9 +138 - XMM10 +139 - XMM11 +140 - XMM12 +141 - XMM13 +142 - XMM14 +143 - XMM15 +144 - YMM0 +145 - YMM1 +146 - YMM2 +147 - YMM3 +148 - YMM4 +149 - YMM5 +150 - YMM6 +151 - YMM7 +152 - YMM8 +153 - YMM9 +154 - YMM10 +155 - YMM11 +156 - YMM12 +157 - YMM13 +158 - YMM14 +159 - YMM15