📄 disasm.c
字号:
case 2:
op->segment |= SEG_DISP32;
op->offset = getu32(data);
data += 4;
break;
}
return data;
}
}
/*
* Determine whether the instruction template in t corresponds to the data
* stream in data. Return the number of bytes matched if so.
*/
static int matches(const struct itemplate *t, uint8_t *data,
const struct prefix_info *prefix, int segsize, insn *ins)
{
uint8_t *r = (uint8_t *)(t->code);
uint8_t *origdata = data;
bool a_used = false, o_used = false;
enum prefixes drep = 0;
uint8_t lock = prefix->lock;
int osize = prefix->osize;
int asize = prefix->asize;
int i;
for (i = 0; i < MAX_OPERANDS; i++) {
ins->oprs[i].segment = ins->oprs[i].addr_size =
(segsize == 64 ? SEG_64BIT : segsize == 32 ? SEG_32BIT : 0);
}
ins->condition = -1;
ins->rex = prefix->rex;
if (t->flags & (segsize == 64 ? IF_NOLONG : IF_LONG))
return false;
if (prefix->rep == 0xF2)
drep = P_REPNE;
else if (prefix->rep == 0xF3)
drep = P_REP;
while (*r) {
int c = *r++;
/* FIX: change this into a switch */
if (c >= 01 && c <= 03) {
while (c--)
if (*r++ != *data++)
return false;
} else if (c == 04) {
switch (*data++) {
case 0x07:
ins->oprs[0].basereg = 0;
break;
case 0x17:
ins->oprs[0].basereg = 2;
break;
case 0x1F:
ins->oprs[0].basereg = 3;
break;
default:
return false;
}
} else if (c == 05) {
switch (*data++) {
case 0xA1:
ins->oprs[0].basereg = 4;
break;
case 0xA9:
ins->oprs[0].basereg = 5;
break;
default:
return false;
}
} else if (c == 06) {
switch (*data++) {
case 0x06:
ins->oprs[0].basereg = 0;
break;
case 0x0E:
ins->oprs[0].basereg = 1;
break;
case 0x16:
ins->oprs[0].basereg = 2;
break;
case 0x1E:
ins->oprs[0].basereg = 3;
break;
default:
return false;
}
} else if (c == 07) {
switch (*data++) {
case 0xA0:
ins->oprs[0].basereg = 4;
break;
case 0xA8:
ins->oprs[0].basereg = 5;
break;
default:
return false;
}
} else if (c >= 010 && c <= 013) {
int t = *r++, d = *data++;
if (d < t || d > t + 7)
return false;
else {
ins->oprs[c - 010].basereg = (d-t)+
(ins->rex & REX_B ? 8 : 0);
ins->oprs[c - 010].segment |= SEG_RMREG;
}
} else if (c >= 014 && c <= 017) {
ins->oprs[c - 014].offset = (int8_t)*data++;
ins->oprs[c - 014].segment |= SEG_SIGNED;
} else if (c >= 020 && c <= 023) {
ins->oprs[c - 020].offset = *data++;
} else if (c >= 024 && c <= 027) {
ins->oprs[c - 024].offset = *data++;
} else if (c >= 030 && c <= 033) {
ins->oprs[c - 030].offset = getu16(data);
data += 2;
} else if (c >= 034 && c <= 037) {
if (osize == 32) {
ins->oprs[c - 034].offset = getu32(data);
data += 4;
} else {
ins->oprs[c - 034].offset = getu16(data);
data += 2;
}
if (segsize != asize)
ins->oprs[c - 034].addr_size = asize;
} else if (c >= 040 && c <= 043) {
ins->oprs[c - 040].offset = getu32(data);
data += 4;
} else if (c >= 044 && c <= 047) {
switch (asize) {
case 16:
ins->oprs[c - 044].offset = getu16(data);
data += 2;
break;
case 32:
ins->oprs[c - 044].offset = getu32(data);
data += 4;
break;
case 64:
ins->oprs[c - 044].offset = getu64(data);
data += 8;
break;
}
if (segsize != asize)
ins->oprs[c - 044].addr_size = asize;
} else if (c >= 050 && c <= 053) {
ins->oprs[c - 050].offset = gets8(data++);
ins->oprs[c - 050].segment |= SEG_RELATIVE;
} else if (c >= 054 && c <= 057) {
ins->oprs[c - 054].offset = getu64(data);
data += 8;
} else if (c >= 060 && c <= 063) {
ins->oprs[c - 060].offset = gets16(data);
data += 2;
ins->oprs[c - 060].segment |= SEG_RELATIVE;
ins->oprs[c - 060].segment &= ~SEG_32BIT;
} else if (c >= 064 && c <= 067) {
if (osize == 16) {
ins->oprs[c - 064].offset = getu16(data);
data += 2;
ins->oprs[c - 064].segment &= ~(SEG_32BIT|SEG_64BIT);
} else if (osize == 32) {
ins->oprs[c - 064].offset = getu32(data);
data += 4;
ins->oprs[c - 064].segment &= ~SEG_64BIT;
ins->oprs[c - 064].segment |= SEG_32BIT;
}
if (segsize != osize) {
ins->oprs[c - 064].type =
(ins->oprs[c - 064].type & ~SIZE_MASK)
| ((osize == 16) ? BITS16 : BITS32);
}
} else if (c >= 070 && c <= 073) {
ins->oprs[c - 070].offset = getu32(data);
data += 4;
ins->oprs[c - 070].segment |= SEG_32BIT | SEG_RELATIVE;
} else if (c >= 0100 && c < 0140) {
int modrm = *data++;
ins->oprs[c & 07].segment |= SEG_RMREG;
data = do_ea(data, modrm, asize, segsize,
&ins->oprs[(c >> 3) & 07], ins);
if (!data)
return false;
ins->oprs[c & 07].basereg = ((modrm >> 3)&7)+
(ins->rex & REX_R ? 8 : 0);
} else if (c >= 0140 && c <= 0143) {
ins->oprs[c - 0140].offset = getu16(data);
data += 2;
} else if (c >= 0150 && c <= 0153) {
ins->oprs[c - 0150].offset = getu32(data);
data += 4;
} else if (c >= 0160 && c <= 0167) {
ins->rex |= (c & 4) ? REX_D|REX_OC : REX_D;
ins->drexdst = c & 3;
} else if (c == 0170) {
if (*data++)
return false;
} else if (c == 0171) {
data = do_drex(data, ins);
if (!data)
return false;
} else if (c >= 0200 && c <= 0277) {
int modrm = *data++;
if (((modrm >> 3) & 07) != (c & 07))
return false; /* spare field doesn't match up */
data = do_ea(data, modrm, asize, segsize,
&ins->oprs[(c >> 3) & 07], ins);
if (!data)
return false;
} else if (c == 0310) {
if (asize != 16)
return false;
else
a_used = true;
} else if (c == 0311) {
if (asize == 16)
return false;
else
a_used = true;
} else if (c == 0312) {
if (asize != segsize)
return false;
else
a_used = true;
} else if (c == 0313) {
if (asize != 64)
return false;
else
a_used = true;
} else if (c == 0320) {
if (osize != 16)
return false;
else
o_used = true;
} else if (c == 0321) {
if (osize != 32)
return false;
else
o_used = true;
} else if (c == 0322) {
if (osize != (segsize == 16) ? 16 : 32)
return false;
else
o_used = true;
} else if (c == 0323) {
ins->rex |= REX_W; /* 64-bit only instruction */
osize = 64;
} else if (c == 0324) {
if (!(ins->rex & (REX_P|REX_W)) || osize != 64)
return false;
} else if (c == 0330) {
int t = *r++, d = *data++;
if (d < t || d > t + 15)
return false;
else
ins->condition = d - t;
} else if (c == 0331) {
if (prefix->rep)
return false;
} else if (c == 0332) {
if (prefix->rep != 0xF2)
return false;
} else if (c == 0333) {
if (prefix->rep != 0xF3)
return false;
drep = 0;
} else if (c == 0334) {
if (lock) {
ins->rex |= REX_R;
lock = 0;
}
} else if (c == 0335) {
if (drep == P_REP)
drep = P_REPE;
} else if (c == 0364) {
if (prefix->osp)
return false;
} else if (c == 0365) {
if (prefix->asp)
return false;
} else if (c == 0366) {
if (!prefix->osp)
return false;
o_used = true;
} else if (c == 0367) {
if (!prefix->asp)
return false;
o_used = true;
}
}
/* REX cannot be combined with DREX */
if ((ins->rex & REX_D) && (prefix->rex))
return false;
/*
* Check for unused rep or a/o prefixes.
*/
for (i = 0; i < t->operands; i++) {
if (ins->oprs[i].segment != SEG_RMREG)
a_used = true;
}
ins->nprefix = 0;
if (lock)
ins->prefixes[ins->nprefix++] = P_LOCK;
if (drep)
ins->prefixes[ins->nprefix++] = drep;
if (!a_used && asize != segsize)
ins->prefixes[ins->nprefix++] = asize == 16 ? P_A16 : P_A32;
if (!o_used && osize == ((segsize == 16) ? 32 : 16))
ins->prefixes[ins->nprefix++] = osize == 16 ? P_O16 : P_O32;
/* Fix: check for redundant REX prefixes */
return data - origdata;
}
int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
int32_t offset, int autosync, uint32_t prefer)
{
const struct itemplate * const *p, * const *best_p;
const struct disasm_index *ix;
uint8_t *dp;
int length, best_length = 0;
char *segover;
int i, slen, colon, n;
uint8_t *origdata;
int works;
insn tmp_ins, ins;
uint32_t goodness, best;
int best_pref;
struct prefix_info prefix;
memset(&ins, 0, sizeof ins);
/*
* Scan for prefixes.
*/
memset(&prefix, 0, sizeof prefix);
prefix.asize = segsize;
prefix.osize = (segsize == 64) ? 32 : segsize;
segover = NULL;
origdata = data;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -