static void walk_instructions(unsigned char *pos, unsigned char *end, void (*cb)(unsigned char *pos, unsigned len, void *arg), void *arg) { unsigned char *cur = pos; while (cur < end) { /* FIXME: if our mapping includes some non-instructions, * and these accidentally decode into multi-byte instructions, * we might get misaligned here. We *will* catch this when * we do the paranoid second scan, but it would be better not * to rely on this. */ unsigned len = instr_len(cur, end); cb(cur, len, arg); cur += (len ? len : 1); } }
static int decode_segreg(struct sigcontext *scp) { unsigned cs, eip; unsigned char *csp, *orig_csp; int ret = -1; x86_ins x86; x86._32bit = dpmi_mhp_get_selector_size(_cs); cs = GetSegmentBase(_cs); eip = _eip + x86_handle_prefixes(scp, cs, &x86); csp = (unsigned char *)MEM_BASE32(cs + eip); orig_csp = (unsigned char *)MEM_BASE32(cs + _eip); switch(*csp) { case 0x8e: /* mov segreg,r/m16 */ ret = sreg_idx(*(unsigned char *)MEM_BASE32(cs + eip + 1) >> 3); _eip += instr_len(orig_csp, x86._32bit); break; case 0xca: /*retf imm 16*/ case 0xcb: /*retf*/ case 0xcf: /*iret*/ { unsigned tmp_eip = x86_pop(scp, &x86); x86_pop(scp, &x86); ret = cs_INDEX; switch (*(unsigned char *)MEM_BASE32(cs + eip)) { case 0xca: /*retf imm 16*/ _esp += ((unsigned short *) (MEM_BASE32(cs + eip + 1)))[0]; break; case 0xcf: /*iret*/ scp->eflags = x86_pop(scp, &x86); break; } _eip = tmp_eip; } break; case 0xea: /* jmp seg:off16/off32 */ { unsigned tmp_eip; tmp_eip = x86.operand_size == 4 ? READ_DWORDP(MEM_BASE32(cs + eip + 1)) : READ_WORDP(MEM_BASE32(cs + eip + 1)); ret = cs_INDEX; _eip = tmp_eip; } break; case 0xc4: /* les */ ret = es_INDEX; _eip += instr_len(orig_csp, x86._32bit); break; case 0xc5: /* lds */ ret = ds_INDEX; _eip += instr_len(orig_csp, x86._32bit); break; case 0x07: /* pop es */ case 0x17: /* pop ss */ case 0x1f: /* pop ds */ ret = sreg_idx(*(unsigned char *)MEM_BASE32(cs + eip) >> 3); x86_pop(scp, &x86); _eip = eip + 1; break; case 0x0f: eip++; switch (*(unsigned char *)MEM_BASE32(cs + eip)) { case 0xa1: /* pop fs */ case 0xa9: /* pop gs */ x86_pop(scp, &x86); ret = sreg_idx(*(unsigned char *)MEM_BASE32(cs + eip) >> 3); _eip = eip + 1; break; case 0xb2: /* lss */ ret = ss_INDEX; _eip += instr_len(orig_csp, x86._32bit); break; case 0xb4: /* lfs */ ret = fs_INDEX; _eip += instr_len(orig_csp, x86._32bit); break; case 0xb5: /* lgs */ ret = gs_INDEX; _eip += instr_len(orig_csp, x86._32bit); break; } break; } return ret; }