📄 gen.c
字号:
switch (get_sizeof(u.ll)) { case 1: e_buf[offset++] = u.byte; break; case 2: e_buf[offset++] = u.word[0]; e_buf[offset++] = u.word[1]; e_buf[offset++] = 0; e_buf[offset++] = 0; break; case 4: e_buf[offset++] = u.dword[0]; e_buf[offset++] = u.dword[1]; e_buf[offset++] = u.dword[2]; e_buf[offset++] = u.dword[3]; break; case 8: e_buf[offset++] = u.qdword[0]; e_buf[offset++] = u.qdword[1]; e_buf[offset++] = u.qdword[2]; e_buf[offset++] = u.qdword[3]; e_buf[offset++] = u.qdword[4]; e_buf[offset++] = u.qdword[5]; e_buf[offset++] = u.qdword[6]; e_buf[offset++] = u.qdword[7]; } }}/********************************************************* function: errno_t do_generate(char *e_buf, e_key_t *e_key) parameter: e_buf: this is encode memory buffer. e_key: this is instruction encode key word link.***********************************************************/errno_t do_generate(char *e_buf, e_key_t *e_key){ errno_t errno = 0; if (!e_buf || !e_key) return ERR_ERROR; unsigned long long priv_pc = current_pc; offset = 0; unsigned char rex = 0x40; int is_sib = 0; int set_disp = 0; /* must set disp */ int set_imme = 0; unsigned int to_attr = 0; unsigned int do_attr = 0; unsigned int so_attr = 0; unsigned int i_attr = 0; o_key_t *to_key = 0; o_key_t *so_key = 0; o_key_t *do_key = 0; ops_key_t *ops_key = e_key->ops_key; union { unsigned short opcode; /* two bytes opcode */ unsigned char code[2]; } u; if (e_key->i_key) { to_attr = e_key->i_key->to_attr; do_attr = e_key->i_key->do_attr; so_attr = e_key->i_key->so_attr; i_attr = e_key->i_key->i_attr; u.opcode = e_key->i_key->opcode; } if (ops_key) { to_key = ops_key->to_key; do_key = ops_key->do_key; so_key = ops_key->so_key; } mem_t *mem = so_key && so_key->mem ? so_key->mem : do_key && do_key->mem ? do_key->mem : 0; to_key && to_key->mem ? to_key->mem : 0; imme_t *imme = so_key && so_key->imme ? so_key->imme : do_key && do_key->imme ? do_key->imme : to_key && to_key->imme ? to_key->imme : 0; int oattr_size = 0; if (so_key) { oattr_size = SIZE(so_attr); } else if (do_key) { oattr_size = SIZE(do_attr); } else if (to_key) { oattr_size = SIZE(to_attr); } unsigned int ops_size = get_ops_size(ops_key); unsigned int addr_size = get_ops_addr(ops_key); if (is_FS(i_attr)) ops_size = get_FS_SIZE(i_attr);/************************************************************************/ prefix_t *i_prefix = e_key->i_prefix; if (i_prefix) { /* lock or rep prefix */ if (i_prefix->lock) e_buf[offset++] = i_prefix->lock; if (i_prefix->rep) e_buf[offset++] = i_prefix->rep; } /************************************* * size override prefix * address override prefix * segment override prefix *************************************/ /* segment override */ if (mem && mem->oseg) e_buf[offset++] = mem->oseg; /******************************************************* * TODO: reserved for check instruction's attribute * -> to check instruction fixed-operand size * -> to check instruction default operand size *******************************************************/ /* size override */ if (is_NO_CAST(i_attr)) { /* example: push es, push cs .... */ /* do nothing */ } else if (!so_key && !do_key && !to_key && !is_FS(i_attr)) { /*** no operands and no fix operand's size ***/ /* example: "nop", "ret", so that....*/ /* do nothing */ } else if (current_bits == 16) { /* CPU's current mode is 16-bit */ if ((addr_size == 32) && !is_NO_CAST_ADDR(i_attr)) e_buf[offset++] = 0x67; if ((ops_size == 32) && !is_NO_CAST_SIZE(i_attr)) e_buf[offset++] = 0x66; } else if (current_bits == 32) { /* CPU's current mode is 32-bit */ if ((addr_size == 16) && !is_NO_CAST_ADDR(i_attr)) e_buf[offset++] = 0x67; if ((ops_size == 16) && !is_NO_CAST_SIZE(i_attr)) e_buf[offset++] = 0x66; } else if (current_bits == 64) { /* CPU's current mode is 64-bit */ if ((addr_size == 32) && !is_NO_CAST_ADDR(i_attr)) e_buf[offset++] = 0x67; /* more instruct in 64-bit mode to default operand size is 32-bit so ops_size is 32-bit have not 0x66 byte */ if ((ops_size == 16) && !is_NO_CAST_SIZE(i_attr)) e_buf[offset++] = 0x66; /* 64-bit mode not support to 16-bit address size so addr_size is 16-bit have not 0x67 byte */ /******* set rex byte to get extern GPRs ***********/ if (ops_size == 64 || addr_size == 64 || ((so_key && (so_key->reg & 0x08)) || (do_key && (do_key->reg & 0x08)) || (to_key && (to_key->reg & 0x08)))) { /* set REX.W to extern 64-bit */ if (!is_DS_64(i_attr) && !is_FS_64(i_attr) && !is_FS_8(i_attr)) rex |= REX_W; switch (get_ops_type(ops_key)) { case S_R: /* register */ #if 0 if (is_GROUP(i_attr)) { /* example "inc rcx" it's GROUP,so set REX.B */ if (so_key->reg & 0x08) rex |= REX_B; } else { /* have not other insturction */ } #endif if (is_eGPR(so_key->reg)) rex |= REX_B; break; case S_M: /* it's a memory */ /* it's not to extern 64-bit address */ if (addr_size != 64) break; if (mem->base && !mem->index) { #if 0 if (is_GROUP(i_attr)) { /* example: call [rcx] */ /* it's a GROUP,so set REX.B */ if (so_key->mem->base & 0x08) rex |= REX_B; } else { /* have not other */ } #endif if (is_eGPR(so_key->mem->base)) rex |= REX_B; } else if (mem->index && !mem->base) { #if 0 if (is_GROUP(i_attr)) { if (mem->index & 0x08) rex |= REX_X; } else { /* have not oterh */} #endif if (is_eGPR(mem->index)) rex |= REX_X; } else if (mem->base && mem->index) { #if 0 if (is_GROUP(i_attr)) { if (mem->base & 0x08) rex |= REX_B; if (mem->index & 0x08) rex |= REX_X; } else { } #endif if (is_eGPR(mem->base)) rex |= REX_B; if (is_eGPR(mem->index)) rex |= REX_X; } else if (mem->disp) { /* example:call [0x1122334455667788] */ /* it's GROUP,so set REX.B */ if (is_GROUP(i_attr)) { rex |= REX_B; } else { /* have not other */ } } break; case S_I: break; /* have not REX.B */ case D_R|S_R: /* source is reg and dest is reg */ /* example: mov rax, rcx */ /* modrm: mod field = 11 reg field = REX_R + XXX r/m field = REX_B + XXX */ if (is_eGPR(so_key->reg)) rex |= REX_R; if (is_eGPR(do_key->reg)) rex |= REX_B; break; case D_R|S_M: case D_M|S_R: if (is_eGPR(so_key->reg) || is_eGPR(do_key->reg)) rex |= REX_R; if (addr_size != 64) { /* example: mov rax, [ecx] */ /* the ops_size is 64-bit, but the addr_size is 32-bit. so not set to REX_B */ break; } /* example: mov rax, [rcx*8+rbx+0xc] */ /* REX_B: set for base reg */ /* REX_X: set for index reg */ if (is_eGPR(mem->base)) rex |= REX_B; if (is_eGPR(mem->index)) rex |= REX_X; break; case D_R|S_I: /* dest is reg and source is imme */ /* example: mov rax, 0x0c */ /* register id in reg field of opcode byte so, REX_R & REX_X are not used */ /* is GROUP set REX_B too !!! example: mov ecx,0x00000001 if the opcode code is 0xC7/0... it's a GROUP, so set REX_B */ if (is_eGPR(do_key->reg)) rex |= REX_B; break; case D_M|S_I: /* ops_size is 64-bit,but addr_size isn't 64-bit, so skip set REX */ if (addr_size != 64) break; /* example: mov [rax+rcx], 0x0c it's GROUP */ /* set REX_B for base reg */ /* set REX_X for index reg */ if (is_eGPR(mem->base)) rex |= REX_B; if (is_eGPR(mem->index)) rex |= REX_X; break; default: break; /*********************************** * TODO: reserved for three operands ***********************************/ } e_buf[offset++] = rex; } } /*** prefix bytes ****/ /* opcode bytes */ if (u.code[1]) /* it's two bytes opcode */ e_buf[offset++] = u.code[1]; e_buf[offset++] = u.code[0]; /****************** modrm byte *******************/ /* example: inc eax * it has not modrm byte */ if (!is_NO_NEED_MODRM(i_attr)) { e_buf[offset++] = get_modrm(e_key, &is_sib, &set_disp); } else if (mem && !mem->base && !mem->index && mem->disp) { /* example: mov eax, [0x1122] */ set_disp = (current_bits >> 3) - get_sizeof(mem->disp); } /* sib byte */ if (is_sib) { e_buf[offset++] = get_sib(e_key, &set_disp); } /******** disp bytes *************/ union { long long ll; char byte[8]; } d; d.ll = mem ? mem->disp : 0; if (d.ll == 0) { /* do nothing */ } else switch (get_sizeof(d.ll)) { case 1: e_buf[offset++] = d.byte[0]; break; case 2: e_buf[offset++] = d.byte[0]; e_buf[offset++] = d.byte[1]; break; case 4: e_buf[offset++] = d.byte[0]; e_buf[offset++] = d.byte[1]; e_buf[offset++] = d.byte[2]; e_buf[offset++] = d.byte[3]; break; case 8: e_buf[offset++] = d.byte[0]; e_buf[offset++] = d.byte[1]; e_buf[offset++] = d.byte[2]; e_buf[offset++] = d.byte[3]; if (!is_SUPPORT_VALUE64(i_attr)) { fputs("warning: " "the instruction not support 64-bit value,", stderr); break; } e_buf[offset++] = d.byte[4]; e_buf[offset++] = d.byte[5]; e_buf[offset++] = d.byte[6]; e_buf[offset++] = d.byte[7]; } for (; set_disp; set_disp--) e_buf[offset++] = 0; /************* imme bytes ********************/ d.ll = imme ? imme->imme_value : 0; int imme_size = imme && imme->cast ? imme->cast >> 3 : d.ll ? get_sizeof(d.ll) : 0; if (OPTYPE(so_attr) == IMME_1) { /* example: shl eax,1 */ /* do nothing */ } else if (imme) { switch (imme_size) { case 0: /* imme operand is 0 */ if (imme->cast == 8) { e_buf[offset++] = d.byte[0]; imme_size = 1; } else if (imme->cast == 16) { e_buf[offset++] = d.byte[0]; e_buf[offset++] = d.byte[1]; imme_size = 2; } else if (imme->cast == 32) { e_buf[offset++] = d.byte[0]; e_buf[offset++] = d.byte[1]; e_buf[offset++] = d.byte[2]; e_buf[offset++] = d.byte[3]; imme_size = 4; } else if (imme->cast == 64) { e_buf[offset++] = d.byte[0]; e_buf[offset++] = d.byte[1]; e_buf[offset++] = d.byte[2]; e_buf[offset++] = d.byte[3]; if (!is_SUPPORT_VALUE64(i_attr)) break; e_buf[offset++] = d.byte[4]; e_buf[offset++] = d.byte[5]; e_buf[offset++] = d.byte[6]; e_buf[offset++] = d.byte[7]; imme_size = 8; } break; case 1: e_buf[offset++] = d.byte[0];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -