-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
got it aligning the instructions from udis with asmjit, but asmjit is…
… choking on valid instructions like `push 0xfa(%rip)`
- Loading branch information
Showing
6 changed files
with
422 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,252 @@ | ||
#include "align_udis_asmjit.h" | ||
|
||
#include <iostream> | ||
using namespace std; | ||
|
||
using namespace redmagic; | ||
using namespace asmjit; | ||
|
||
|
||
struct aligned_instruction_info { | ||
enum ud_mnemonic_code ud_code; | ||
enum X86InstId asm_code; | ||
}; | ||
|
||
static aligned_instruction_info aligned_instructions[UD_MAX_MNEMONIC_CODE]; | ||
|
||
namespace { | ||
#define MANUAL_ALIGN(UD_I, ASM_I) \ | ||
aligned_instructions[UD_I].ud_code = UD_I ; \ | ||
aligned_instructions[UD_I].asm_code = ASM_I ; | ||
|
||
struct _do_alignment { | ||
_do_alignment() { | ||
for(int ud_i = 0; ud_i < UD_MAX_MNEMONIC_CODE; ud_i++) { | ||
enum ud_mnemonic_code ud_c = (enum ud_mnemonic_code)ud_i; | ||
const char *name = ud_lookup_mnemonic(ud_c); | ||
// if can't find instruction then returns kX86InstIdNone | ||
uint32_t asm_id = X86Util::getInstIdByName(name); | ||
aligned_instructions[ud_c].ud_code = ud_c; | ||
aligned_instructions[ud_c].asm_code = (enum X86InstId)asm_id; | ||
} | ||
|
||
MANUAL_ALIGN(UD_Ijcxz, kX86InstIdJecxz); | ||
MANUAL_ALIGN(UD_Ipopfd, kX86InstIdPopf); | ||
MANUAL_ALIGN(UD_Ipopfq, kX86InstIdPopf); | ||
MANUAL_ALIGN(UD_Ipopfw, kX86InstIdPopf); | ||
MANUAL_ALIGN(UD_Ipushfd, kX86InstIdPushf); | ||
MANUAL_ALIGN(UD_Ipushfq, kX86InstIdPushf); | ||
MANUAL_ALIGN(UD_Ipushfw, kX86InstIdPushf); | ||
} | ||
} _do_alignment_inst; | ||
} | ||
|
||
enum X86InstId AlignedInstructions::get_asm_mnem() { | ||
return aligned_instructions[ud_mnem].asm_code; | ||
} | ||
|
||
|
||
AlignedInstructions::AlignedInstructions(ud_t *disassm) { | ||
ud_mnem = ud_insn_mnemonic(disassm); | ||
pc = ud_insn_off(disassm); | ||
len = ud_insn_len(disassm); | ||
|
||
for(int i = 0;; i++) { | ||
const ud_operand_t *opr = ud_insn_opr(disassm, i); | ||
if(opr == NULL) | ||
break; | ||
number_operands = i + 1; | ||
operand_info *info = &operands[i]; | ||
info->type = opr->type; | ||
switch(opr->type) { | ||
case UD_OP_IMM: | ||
case UD_OP_CONST: | ||
switch(opr->size) { | ||
case 8: | ||
info->imm_value = opr->lval.sbyte; | ||
break; | ||
case 16: | ||
info->imm_value = opr->lval.sword; | ||
break; | ||
case 32: | ||
info->imm_value = opr->lval.sdword; | ||
break; | ||
case 64: | ||
info->imm_value = opr->lval.sqword; | ||
break; | ||
default: | ||
assert(0); | ||
} | ||
break; | ||
case UD_OP_JIMM: | ||
switch(opr->size) { | ||
case 8: | ||
info->address = pc + opr->lval.sbyte; | ||
break; | ||
case 16: | ||
info->address = pc + opr->lval.sword; | ||
break; | ||
case 32: | ||
info->address = pc + opr->lval.sdword; | ||
break; | ||
case 64: | ||
info->address = pc + opr->lval.sqword; | ||
break; | ||
default: | ||
assert(0); | ||
} | ||
break; | ||
case UD_OP_REG: { | ||
info->register_i = ud_register_to_sys(opr->base); | ||
break; | ||
} | ||
case UD_OP_MEM: { | ||
info->base_register = info->index_register = info->index_scale = -1; | ||
if(opr->base != UD_NONE) | ||
info->base_register = ud_register_to_sys(opr->base); | ||
if(opr->index != UD_NONE) { | ||
info->index_register = ud_register_to_sys(opr->index); | ||
info->index_scale = opr->scale; | ||
} | ||
switch(opr->offset) { | ||
case 8: | ||
info->offset = opr->lval.sbyte; | ||
break; | ||
case 16: | ||
info->offset = opr->lval.sword; | ||
break; | ||
case 32: | ||
info->offset = opr->lval.sdword; | ||
break; | ||
case 64: | ||
info->offset = opr->lval.sqword; | ||
break; | ||
default: | ||
assert(0); | ||
} | ||
break; | ||
} | ||
case UD_OP_PTR: | ||
assert(0); | ||
default: | ||
assert(0); | ||
} | ||
} | ||
} | ||
|
||
const asmjit::Operand AlignedInstructions::get_asm_op(unsigned int i) { | ||
assert(i < number_operands); | ||
operand_info *info = &operands[i]; | ||
|
||
switch(info->type) { | ||
case UD_OP_CONST: | ||
case UD_OP_IMM: | ||
return imm(info->imm_value); | ||
case UD_OP_JIMM: | ||
return imm_u(info->address); | ||
case UD_OP_REG: | ||
return get_asm_register_from_sys(info->register_i); | ||
case UD_OP_MEM: { | ||
assert(info->base_register != -1); | ||
if(info->index_register == -1) { | ||
return x86::ptr(get_asm_register_from_sys(info->base_register), info->offset); | ||
} | ||
int scale = 0; | ||
switch(info->index_scale) { | ||
case 0: scale = 0; break; | ||
case 8: scale = 1; break; | ||
case 16: scale = 2; break; | ||
case 32: scale = 3; break; | ||
case 64: scale = 4; break; | ||
default: assert(0); | ||
} | ||
return x86::ptr(get_asm_register_from_sys(info->base_register), get_asm_register_from_sys(info->index_register), scale, info->offset); | ||
} | ||
default: | ||
assert(0); | ||
} | ||
} | ||
|
||
uint64_t AlignedInstructions::registers_used() { | ||
uint64_t ret = 0; | ||
for(int i = 0; i < number_operands; i++) { | ||
operand_info *info = &operands[i]; | ||
switch(info->type) { | ||
case UD_OP_REG: { | ||
ret |= 1 << info->register_i; | ||
break; | ||
} | ||
case UD_OP_MEM: { | ||
if(info->base_register != -1) | ||
ret |= 1 << info->base_register; | ||
if(info->index_register != -1) | ||
ret |= 1 << info->index_register; | ||
break; | ||
} | ||
case UD_OP_CONST: | ||
case UD_OP_IMM: | ||
case UD_OP_JIMM: | ||
break; | ||
default: | ||
assert(0); | ||
} | ||
} | ||
return ret; | ||
} | ||
|
||
void AlignedInstructions::ReplaceReigster(int from, int to) { | ||
bool did_replace = false; | ||
|
||
for(int i = 0; i < number_operands; i++) { | ||
operand_info *info = &operands[i]; | ||
switch(info->type) { | ||
case UD_OP_REG: { | ||
if(info->register_i == from) { | ||
did_replace = true; | ||
info->register_i = to; | ||
} | ||
break; | ||
} | ||
case UD_OP_MEM: { | ||
if(info->base_register == from) { | ||
did_replace = true; | ||
info->base_register = to; | ||
} | ||
if(info->index_register == from) { | ||
did_replace = true; | ||
info->index_register = to; | ||
} | ||
break; | ||
} | ||
case UD_OP_CONST: | ||
case UD_OP_IMM: | ||
case UD_OP_JIMM: | ||
break; | ||
default: | ||
assert(0); | ||
} | ||
} | ||
|
||
assert(did_replace); | ||
} | ||
|
||
void AlignedInstructions::Emit(asmjit::Assembler *assem) { | ||
enum X86InstId inst = get_asm_mnem(); | ||
assert(inst != kX86InstIdNone); | ||
switch(number_operands) { | ||
case 0: | ||
assem->emit(inst); | ||
return; | ||
case 1: | ||
assem->emit(inst, get_asm_op(0)); | ||
return; | ||
case 2: | ||
assem->emit(inst, get_asm_op(0), get_asm_op(1)); | ||
return; | ||
case 3: | ||
assem->emit(inst, get_asm_op(0), get_asm_op(1), get_asm_op(2)); | ||
return; | ||
default: | ||
assert(0); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
#ifndef REDMAGIC_ALIGN_UDIS_ASMJIT_H_ | ||
#define REDMAGIC_ALIGN_UDIS_ASMJIT_H_ | ||
|
||
#include <asmjit/asmjit.h> | ||
#include <udis86.h> | ||
|
||
#include "jit_internal.h" | ||
|
||
|
||
/** | ||
* Attempt to align the instructions between udis86 and asmjit so that we can directly convert from a udis decompile to a asmjit instruction | ||
* this is helpful since we can use this to slightly modify one of the instructions | ||
*/ | ||
|
||
namespace redmagic { | ||
|
||
class AlignedInstructions { | ||
public: | ||
AlignedInstructions(ud_t *disassm); | ||
|
||
struct operand_info { | ||
// UD_OP_* | ||
enum ud_type type; | ||
|
||
int8_t base_register; | ||
int8_t index_register; | ||
int8_t index_scale; | ||
int64_t offset; | ||
|
||
int8_t register_i; | ||
|
||
int64_t imm_value; | ||
|
||
mem_loc_t address; | ||
}; | ||
|
||
inline size_t num_ops() { return number_operands; } | ||
inline operand_info* get_op(unsigned int i) { | ||
if(i >= number_operands) | ||
return nullptr; | ||
return &operands[i]; | ||
} | ||
|
||
inline enum ud_mnemonic_code get_ud_mnem() { return ud_mnem; } | ||
enum asmjit::X86InstId get_asm_mnem(); | ||
|
||
const asmjit::Operand get_asm_op(unsigned int i); | ||
|
||
uint64_t registers_used(); | ||
|
||
// replace all references to one register with another | ||
void ReplaceReigster(int from, int to); | ||
|
||
void Emit(asmjit::Assembler *assem); | ||
|
||
private: | ||
enum ud_mnemonic_code ud_mnem; | ||
int number_operands; | ||
operand_info operands[3]; | ||
mem_loc_t pc; | ||
size_t len; | ||
|
||
void findAlignedAsmjit(); | ||
}; | ||
|
||
static auto& get_asm_register_from_sys(int id) { | ||
// take the sys struct register id and convert it to asmjit | ||
using namespace asmjit::x86; | ||
switch(id) { | ||
case R15: return r15; | ||
case R14: return r14; | ||
case R13: return r13; | ||
case R12: return r12; | ||
case RBP: return rbp; | ||
case RBX: return rbx; | ||
case R11: return r11; | ||
case R10: return r10; | ||
case R9: return r9; | ||
case R8: return r8; | ||
case RAX: return rax; | ||
case RCX: return rcx; | ||
case RDX: return rdx; | ||
case RSI: return rsi; | ||
case RDI: return rdi; | ||
//case RIP: return rip; | ||
//case CS: return cs; | ||
// case RSP: return rsp; | ||
// case DS: return ds; | ||
// case ES: return es; | ||
// case FS: return fs; | ||
// case GS: return gs; | ||
} | ||
assert(0); | ||
} | ||
|
||
static int get_sys_register_from_asm(asmjit::X86GpReg& reg) { | ||
using namespace asmjit::x86; | ||
if(reg == r15) return R15; | ||
if(reg == r14) return R14; | ||
if(reg == r13) return R13; | ||
if(reg == r12) return R12; | ||
if(reg == rbp) return RBP; | ||
if(reg == rbx) return RBX; | ||
if(reg == r11) return R11; | ||
if(reg == r10) return R10; | ||
if(reg == r9 ) return R9; | ||
if(reg == r8 ) return R8; | ||
if(reg == rax) return RAX; | ||
if(reg == rcx) return RCX; | ||
if(reg == rdx) return RDX; | ||
if(reg == rsi) return RSI; | ||
if(reg == rdi) return RDI; | ||
|
||
assert(0); | ||
} | ||
|
||
|
||
} | ||
|
||
|
||
#endif // REDMAGIC_ALIGN_UDIS_ASMJIT_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,7 +26,7 @@ | |
#include <memory> | ||
|
||
|
||
#include "udis86.h" | ||
#include <udis86.h> | ||
|
||
namespace redmagic { | ||
|
||
|
Oops, something went wrong.