mirror of
https://github.com/kanjitalk755/macemu.git
synced 2025-01-12 16:30:44 +00:00
A few fixlets to the SIGSEGV library:
- Don't export transfer types definitions (formerly used by older API) - Handle ADD instructions in ix86_skip_instruction() (generated by icc 9.1) - Use "%p" format for EIP/RIP addresses
This commit is contained in:
parent
d1d7d5bd4c
commit
87e1518e96
@ -66,6 +66,13 @@ static bool sigsegv_do_install_handler(int sig);
|
||||
* Instruction decoding aids
|
||||
*/
|
||||
|
||||
// Transfer type
|
||||
enum transfer_type_t {
|
||||
SIGSEGV_TRANSFER_UNKNOWN = 0,
|
||||
SIGSEGV_TRANSFER_LOAD = 1,
|
||||
SIGSEGV_TRANSFER_STORE = 2,
|
||||
};
|
||||
|
||||
// Transfer size
|
||||
enum transfer_size_t {
|
||||
SIZE_UNKNOWN,
|
||||
@ -75,9 +82,6 @@ enum transfer_size_t {
|
||||
SIZE_QUAD, // 8 bytes
|
||||
};
|
||||
|
||||
// Transfer type
|
||||
typedef sigsegv_transfer_type_t transfer_type_t;
|
||||
|
||||
#if (defined(powerpc) || defined(__powerpc__) || defined(__ppc__))
|
||||
// Addressing mode
|
||||
enum addressing_mode_t {
|
||||
@ -859,8 +863,14 @@ static bool ix86_skip_instruction(unsigned long * regs)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
enum instruction_type_t {
|
||||
i_MOV,
|
||||
i_ADD
|
||||
};
|
||||
|
||||
transfer_type_t transfer_type = SIGSEGV_TRANSFER_UNKNOWN;
|
||||
transfer_size_t transfer_size = SIZE_LONG;
|
||||
instruction_type_t instruction_type = i_MOV;
|
||||
|
||||
int reg = -1;
|
||||
int len = 0;
|
||||
@ -911,6 +921,7 @@ static bool ix86_skip_instruction(unsigned long * regs)
|
||||
#endif
|
||||
|
||||
// Decode instruction
|
||||
int op_len = 1;
|
||||
int target_size = SIZE_UNKNOWN;
|
||||
switch (eip[0]) {
|
||||
case 0x0f:
|
||||
@ -925,24 +936,10 @@ static bool ix86_skip_instruction(unsigned long * regs)
|
||||
transfer_size = SIZE_WORD;
|
||||
goto do_mov_extend;
|
||||
do_mov_extend:
|
||||
switch (eip[2] & 0xc0) {
|
||||
case 0x80:
|
||||
reg = (eip[2] >> 3) & 7;
|
||||
transfer_type = SIGSEGV_TRANSFER_LOAD;
|
||||
break;
|
||||
case 0x40:
|
||||
reg = (eip[2] >> 3) & 7;
|
||||
transfer_type = SIGSEGV_TRANSFER_LOAD;
|
||||
break;
|
||||
case 0x00:
|
||||
reg = (eip[2] >> 3) & 7;
|
||||
transfer_type = SIGSEGV_TRANSFER_LOAD;
|
||||
break;
|
||||
}
|
||||
len += 3 + ix86_step_over_modrm(eip + 2);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
op_len = 2;
|
||||
goto do_transfer_load;
|
||||
}
|
||||
break;
|
||||
#if defined(__x86_64__)
|
||||
case 0x63: // MOVSXD r64, r/m32
|
||||
if (has_rex && rex.W) {
|
||||
@ -953,60 +950,57 @@ static bool ix86_skip_instruction(unsigned long * regs)
|
||||
transfer_size = SIZE_LONG;
|
||||
target_size = SIZE_QUAD;
|
||||
}
|
||||
switch (eip[1] & 0xc0) {
|
||||
case 0x80:
|
||||
reg = (eip[1] >> 3) & 7;
|
||||
transfer_type = SIGSEGV_TRANSFER_LOAD;
|
||||
break;
|
||||
case 0x40:
|
||||
reg = (eip[1] >> 3) & 7;
|
||||
transfer_type = SIGSEGV_TRANSFER_LOAD;
|
||||
break;
|
||||
case 0x00:
|
||||
reg = (eip[1] >> 3) & 7;
|
||||
transfer_type = SIGSEGV_TRANSFER_LOAD;
|
||||
break;
|
||||
}
|
||||
len += 2 + ix86_step_over_modrm(eip + 1);
|
||||
break;
|
||||
goto do_transfer_load;
|
||||
#endif
|
||||
case 0x02: // ADD r8, r/m8
|
||||
transfer_size = SIZE_BYTE;
|
||||
case 0x03: // ADD r32, r/m32
|
||||
instruction_type = i_ADD;
|
||||
goto do_transfer_load;
|
||||
case 0x8a: // MOV r8, r/m8
|
||||
transfer_size = SIZE_BYTE;
|
||||
case 0x8b: // MOV r32, r/m32 (or 16-bit operation)
|
||||
switch (eip[1] & 0xc0) {
|
||||
do_transfer_load:
|
||||
switch (eip[op_len] & 0xc0) {
|
||||
case 0x80:
|
||||
reg = (eip[1] >> 3) & 7;
|
||||
reg = (eip[op_len] >> 3) & 7;
|
||||
transfer_type = SIGSEGV_TRANSFER_LOAD;
|
||||
break;
|
||||
case 0x40:
|
||||
reg = (eip[1] >> 3) & 7;
|
||||
reg = (eip[op_len] >> 3) & 7;
|
||||
transfer_type = SIGSEGV_TRANSFER_LOAD;
|
||||
break;
|
||||
case 0x00:
|
||||
reg = (eip[1] >> 3) & 7;
|
||||
reg = (eip[op_len] >> 3) & 7;
|
||||
transfer_type = SIGSEGV_TRANSFER_LOAD;
|
||||
break;
|
||||
}
|
||||
len += 2 + ix86_step_over_modrm(eip + 1);
|
||||
len += 1 + op_len + ix86_step_over_modrm(eip + op_len);
|
||||
break;
|
||||
case 0x00: // ADD r/m8, r8
|
||||
transfer_size = SIZE_BYTE;
|
||||
case 0x01: // ADD r/m32, r32
|
||||
instruction_type = i_ADD;
|
||||
goto do_transfer_store;
|
||||
case 0x88: // MOV r/m8, r8
|
||||
transfer_size = SIZE_BYTE;
|
||||
case 0x89: // MOV r/m32, r32 (or 16-bit operation)
|
||||
switch (eip[1] & 0xc0) {
|
||||
do_transfer_store:
|
||||
switch (eip[op_len] & 0xc0) {
|
||||
case 0x80:
|
||||
reg = (eip[1] >> 3) & 7;
|
||||
reg = (eip[op_len] >> 3) & 7;
|
||||
transfer_type = SIGSEGV_TRANSFER_STORE;
|
||||
break;
|
||||
case 0x40:
|
||||
reg = (eip[1] >> 3) & 7;
|
||||
reg = (eip[op_len] >> 3) & 7;
|
||||
transfer_type = SIGSEGV_TRANSFER_STORE;
|
||||
break;
|
||||
case 0x00:
|
||||
reg = (eip[1] >> 3) & 7;
|
||||
reg = (eip[op_len] >> 3) & 7;
|
||||
transfer_type = SIGSEGV_TRANSFER_STORE;
|
||||
break;
|
||||
}
|
||||
len += 2 + ix86_step_over_modrm(eip + 1);
|
||||
len += 1 + op_len + ix86_step_over_modrm(eip + op_len);
|
||||
break;
|
||||
}
|
||||
if (target_size == SIZE_UNKNOWN)
|
||||
@ -1022,7 +1016,7 @@ static bool ix86_skip_instruction(unsigned long * regs)
|
||||
reg += 8;
|
||||
#endif
|
||||
|
||||
if (transfer_type == SIGSEGV_TRANSFER_LOAD && reg != -1) {
|
||||
if (instruction_type == i_MOV && transfer_type == SIGSEGV_TRANSFER_LOAD && reg != -1) {
|
||||
static const int x86_reg_map[] = {
|
||||
X86_REG_EAX, X86_REG_ECX, X86_REG_EDX, X86_REG_EBX,
|
||||
X86_REG_ESP, X86_REG_EBP, X86_REG_ESI, X86_REG_EDI,
|
||||
@ -1058,7 +1052,7 @@ static bool ix86_skip_instruction(unsigned long * regs)
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
printf("%08x: %s %s access", regs[X86_REG_EIP],
|
||||
printf("%p: %s %s access", (void *)regs[X86_REG_EIP],
|
||||
transfer_size == SIZE_BYTE ? "byte" :
|
||||
transfer_size == SIZE_WORD ? "word" :
|
||||
transfer_size == SIZE_LONG ? "long" :
|
||||
|
@ -27,13 +27,6 @@
|
||||
// Address type
|
||||
typedef char * sigsegv_address_t;
|
||||
|
||||
// Transfer type (intended to be used a mask for sigsegv_*_ignore_range())
|
||||
enum sigsegv_transfer_type_t {
|
||||
SIGSEGV_TRANSFER_UNKNOWN = 0,
|
||||
SIGSEGV_TRANSFER_LOAD = 1,
|
||||
SIGSEGV_TRANSFER_STORE = 2,
|
||||
};
|
||||
|
||||
// SIGSEGV handler return state
|
||||
enum sigsegv_return_t {
|
||||
SIGSEGV_RETURN_SUCCESS,
|
||||
|
Loading…
x
Reference in New Issue
Block a user