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:
gbeauche 2006-07-19 21:31:10 +00:00
parent d1d7d5bd4c
commit 87e1518e96
2 changed files with 43 additions and 56 deletions

View File

@ -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" :

View File

@ -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,