/* * libbinrec: a recompiling translator for machine code * Copyright (c) 2016 Andrew Church * * This software may be copied and redistributed under certain conditions; * see the file "COPYING" in the source code distribution for details. * NO WARRANTY is provided with this software. */ #ifndef BINRECXX_H #define BINRECXX_H #ifndef __cplusplus #error This header can only be used with C++. #endif #include "binrec.h" namespace binrec { /*************************************************************************/ /*************************************************************************/ /** * Arch: Enumeration of supported architectures. Wraps binrec_arch_t. */ using Arch = ::binrec_arch_t; /** * LogLevel: Enumeration of log message levels. Wraps binrec_loglevel_t. */ using LogLevel = ::binrec_loglevel_t; /** * Feature: Namespace wrapping architecture feature flags. */ namespace Feature { namespace X86 { const unsigned int FMA = BINREC_FEATURE_X86_FMA; const unsigned int MOVBE = BINREC_FEATURE_X86_MOVBE; const unsigned int LZCNT = BINREC_FEATURE_X86_LZCNT; const unsigned int BMI1 = BINREC_FEATURE_X86_BMI1; const unsigned int BMI2 = BINREC_FEATURE_X86_BMI2; } } /** * Optimize: Namespace wrapping optimization flags. */ namespace Optimize { const unsigned int BASIC = BINREC_OPT_BASIC; const unsigned int DECONDITION = BINREC_OPT_DECONDITION; const unsigned int DEEP_DATA_FLOW = BINREC_OPT_DEEP_DATA_FLOW; const unsigned int DSE = BINREC_OPT_DSE; const unsigned int DSE_FP = BINREC_OPT_DSE_FP; const unsigned int FOLD_CONSTANTS = BINREC_OPT_FOLD_CONSTANTS; const unsigned int FOLD_FP_CONSTANTS = BINREC_OPT_FOLD_FP_CONSTANTS; const unsigned int FOLD_VECTORS = BINREC_OPT_FOLD_VECTORS; const unsigned int NATIVE_IEEE_NAN = BINREC_OPT_NATIVE_IEEE_NAN; const unsigned int NATIVE_IEEE_UNDERFLOW = BINREC_OPT_NATIVE_IEEE_UNDERFLOW; namespace GuestPPC { const unsigned int ASSUME_NO_SNAN = BINREC_OPT_G_PPC_ASSUME_NO_SNAN; const unsigned int CONSTANT_GQRS = BINREC_OPT_G_PPC_CONSTANT_GQRS; const unsigned int DETECT_FCFI_EMUL = BINREC_OPT_G_PPC_DETECT_FCFI_EMUL; const unsigned int FAST_FCTIW = BINREC_OPT_G_PPC_FAST_FCTIW; const unsigned int FAST_FMADDS = BINREC_OPT_G_PPC_FAST_FMADDS; const unsigned int FAST_FMULS = BINREC_OPT_G_PPC_FAST_FMULS; const unsigned int FAST_STFS = BINREC_OPT_G_PPC_FAST_STFS; const unsigned int FNMADD_ZERO_SIGN = BINREC_OPT_G_PPC_FNMADD_ZERO_SIGN; const unsigned int FORWARD_LOADS = BINREC_OPT_G_PPC_FORWARD_LOADS; const unsigned int IGNORE_FPSCR_VXFOO = BINREC_OPT_G_PPC_IGNORE_FPSCR_VXFOO; const unsigned int NATIVE_RECIPROCAL = BINREC_OPT_G_PPC_NATIVE_RECIPROCAL; const unsigned int NO_FPSCR_STATE = BINREC_OPT_G_PPC_NO_FPSCR_STATE; const unsigned int PAIRED_LWARX_STWCX = BINREC_OPT_G_PPC_PAIRED_LWARX_STWCX; const unsigned int PS_STORE_DENORMALS = BINREC_OPT_G_PPC_PS_STORE_DENORMALS; const unsigned int SC_BLR = BINREC_OPT_G_PPC_SC_BLR; const unsigned int SINGLE_PREC_INPUTS = BINREC_OPT_G_PPC_SINGLE_PREC_INPUTS; const unsigned int TRIM_CR_STORES = BINREC_OPT_G_PPC_TRIM_CR_STORES; const unsigned int USE_SPLIT_FIELDS = BINREC_OPT_G_PPC_USE_SPLIT_FIELDS; } namespace HostX86 { const unsigned int ADDRESS_OPERANDS = BINREC_OPT_H_X86_ADDRESS_OPERANDS; const unsigned int BRANCH_ALIGNMENT = BINREC_OPT_H_X86_BRANCH_ALIGNMENT; const unsigned int CONDITION_CODES = BINREC_OPT_H_X86_CONDITION_CODES; const unsigned int FIXED_REGS = BINREC_OPT_H_X86_FIXED_REGS; const unsigned int FORWARD_CONDITIONS = BINREC_OPT_H_X86_FORWARD_CONDITIONS; const unsigned int MERGE_REGS = BINREC_OPT_H_X86_MERGE_REGS; const unsigned int STORE_IMMEDIATE = BINREC_OPT_H_X86_STORE_IMMEDIATE; } } /** * Setup: Parameter block for Handle::initialize(). Wraps binrec_setup_t. */ using Setup = ::binrec_setup_t; /** * Handle: Class representing a translation handle. Wraps binrec_t. * * Optionally, two template parameters can be provided to this class: * - StatePtrType: Pointer type for the processor state block. * - CodeType: Function pointer type for code blocks generated by * Handle::translate(). * Both types default to "void *", but setting them appropriately avoids * the need to explicitly cast to and from void * when calling into the * library. */ template class Handle { public: Handle(): handle(nullptr) {} ~Handle() {::binrec_destroy_handle(handle);} /** * initialize: Initialize the handle. Wraps binrec_create_handle(). * This method must be called before calling any other methods on the * handle, and must not be called again once it has succeeded. * * [Parameters] * setup: Handle parameters, as for binrec_create_handle(). * [Return value] * True if handle was successfully initialized, false if not. */ bool initialize(const Setup &setup) { handle = ::binrec_create_handle(&setup); return handle != nullptr; } /** * set_code_range: Set the range of addresses from which to read * source machine instructions. Wraps binrec_set_code_range(). */ void set_code_range(uint32_t start, uint32_t end) { ::binrec_set_code_range(handle, start, end); } /** * set_optimization_flags: Set which optimizations should be performed * on translated blocks. Wraps binrec_set_optimization_flags(). */ void set_optimization_flags(unsigned int common_opt, unsigned int guest_opt, unsigned int host_opt) { ::binrec_set_optimization_flags(handle, common_opt, guest_opt, host_opt); } /** * set_max_inline_length: Set the maximum length of subroutines to * inline. Wraps binrec_set_max_inline_length(). */ void set_max_inline_length(int length) { ::binrec_set_max_inline_length(handle, length); } /** * set_max_inline_depth: Set the maximum depth of subroutines to * inline. Wraps binrec_set_max_inline_depth(). */ void set_max_inline_depth(int depth) { ::binrec_set_max_inline_depth(handle, depth); } /** * add_readonly_region: Mark the given region of memory as read-only. * Wraps binrec_add_readonly_region(). */ bool add_readonly_region(uint32_t base, uint32_t size) { return bool(::binrec_add_readonly_region(handle, base, size)); } /** * clear_readonly_regions: Clear all read-only memory regions. * Wraps binrec_clear_readonly_regions(). */ void clear_readonly_regions() { ::binrec_clear_readonly_regions(handle); } /** * enable_chaining: Enable or disable chaining of translated code. * Wraps binrec_enable chaining(). */ void enable_chaining(bool enable) { ::binrec_enable_chaining(handle, enable); } /** * enable_branch_exit_test: Enable or disable the pre-branch exit test. * Wraps binrec_enable_branch_exit_test(). */ void enable_branch_exit_test(bool enable) { ::binrec_enable_branch_exit_test(handle, enable); } /** * set_pre_insn_callback: Set a function to be called immediately * before each instruction. Wraps binrec_set_pre_insn_callback(). */ void set_pre_insn_callback(void (*callback)(StatePtrType, uint32_t)) { ::binrec_set_pre_insn_callback( handle, reinterpret_cast(callback)); } /** * set_post_insn_callback: Set a function to be called immediately * after each instruction. Wraps binrec_set_post_insn_callback(). */ void set_post_insn_callback(void (*callback)(StatePtrType, uint32_t)) { ::binrec_set_post_insn_callback( handle, reinterpret_cast(callback)); } /** * enable_verify: Enable or disable verification of translated code. * Wraps binrec_enable_verify(). */ void enable_verify(bool enable) { ::binrec_enable_verify(handle, enable); } /** * translate: Translate a block of guest machine code into native * machine code. Wraps binrec_translate(). */ bool translate(StatePtrType state, uint32_t address, uint32_t limit, CodeType *code_ret, long *size_ret) { return bool(::binrec_translate( handle, state, address, limit, reinterpret_cast(code_ret), size_ret)); } private: binrec_t *handle; }; /** * version: Return the version number of the library as a string. * Wraps binrec_version(). */ static inline const char *version() {return ::binrec_version();} /** * native_arch: Return the architecture of the runtime environment. * Wraps binrec_native_arch(). */ static inline Arch native_arch() {return ::binrec_native_arch();} /** * native_features: Return a bitmask of architecture features available * in the runtime environment. Wraps binrec_native_features(). */ static inline unsigned int native_features() {return ::binrec_native_features();} /** * guest_supported: Return whether the given architecture is supported as * a guest architecure. Wraps binrec_guest_supported(). */ static inline bool guest_supported(Arch arch) {return ::binrec_guest_supported(arch);} /** * host_supported: Return whether the given architecture is supported as * a host architecure. Wraps binrec_host_supported(). */ static inline bool host_supported(Arch arch) {return ::binrec_host_supported(arch);} /*************************************************************************/ /*************************************************************************/ } // namespace binrec #endif // BINRECXX_H