Made INSTR_EmulateInstruction return the exception code.
Don't allow intXX instructions from 32-bit code (based on a patch by Jukka Heinonen).
This commit is contained in:
parent
28b64db6d5
commit
0b34697abb
|
@ -776,8 +776,7 @@ static void do_segv( CONTEXT *context, int trap_code, void *cr2, int err_code )
|
||||||
case T_SEGNPFLT: /* Segment not present exception */
|
case T_SEGNPFLT: /* Segment not present exception */
|
||||||
case T_PROTFLT: /* General protection fault */
|
case T_PROTFLT: /* General protection fault */
|
||||||
case T_UNKNOWN: /* Unknown fault code */
|
case T_UNKNOWN: /* Unknown fault code */
|
||||||
if (INSTR_EmulateInstruction( context )) return;
|
if (!(rec.ExceptionCode = INSTR_EmulateInstruction( context ))) return;
|
||||||
rec.ExceptionCode = EXCEPTION_PRIV_INSTRUCTION;
|
|
||||||
break;
|
break;
|
||||||
case T_PAGEFLT: /* Page fault */
|
case T_PAGEFLT: /* Page fault */
|
||||||
#ifdef FAULT_ADDRESS
|
#ifdef FAULT_ADDRESS
|
||||||
|
|
|
@ -105,7 +105,7 @@ extern LPVOID DOSMEM_MapDosToLinear(UINT); /* linear DOS to Wine */
|
||||||
extern UINT DOSMEM_MapLinearToDos(LPVOID); /* linear Wine to DOS */
|
extern UINT DOSMEM_MapLinearToDos(LPVOID); /* linear Wine to DOS */
|
||||||
|
|
||||||
/* memory/instr.c */
|
/* memory/instr.c */
|
||||||
extern BOOL INSTR_EmulateInstruction( CONTEXT86 *context );
|
extern DWORD INSTR_EmulateInstruction( CONTEXT86 *context );
|
||||||
|
|
||||||
/* msdos/ioports.c */
|
/* msdos/ioports.c */
|
||||||
extern DWORD IO_inport( int port, int count );
|
extern DWORD IO_inport( int port, int count );
|
||||||
|
|
107
memory/instr.c
107
memory/instr.c
|
@ -396,17 +396,18 @@ static void INSTR_outport( WORD port, int size, DWORD val, CONTEXT86 *context )
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* INSTR_EmulateInstruction
|
* INSTR_EmulateInstruction
|
||||||
*
|
*
|
||||||
* Emulate a privileged instruction. Returns TRUE if emulation successful.
|
* Emulate a privileged instruction.
|
||||||
|
* Returns exception code, or 0 if emulation successful.
|
||||||
*/
|
*/
|
||||||
BOOL INSTR_EmulateInstruction( CONTEXT86 *context )
|
DWORD INSTR_EmulateInstruction( CONTEXT86 *context )
|
||||||
{
|
{
|
||||||
int prefix, segprefix, prefixlen, len, repX, long_op, long_addr;
|
int prefix, segprefix, prefixlen, len, repX, long_op, long_addr;
|
||||||
SEGPTR gpHandler;
|
|
||||||
BYTE *instr;
|
BYTE *instr;
|
||||||
|
DWORD ret = EXCEPTION_PRIV_INSTRUCTION;
|
||||||
|
|
||||||
long_op = long_addr = (!ISV86(context) && IS_SELECTOR_32BIT(context->SegCs));
|
long_op = long_addr = (!ISV86(context) && IS_SELECTOR_32BIT(context->SegCs));
|
||||||
instr = make_ptr( context, context->SegCs, context->Eip, TRUE );
|
instr = make_ptr( context, context->SegCs, context->Eip, TRUE );
|
||||||
if (!instr) return FALSE;
|
if (!instr) return ret;
|
||||||
|
|
||||||
/* First handle any possible prefix */
|
/* First handle any possible prefix */
|
||||||
|
|
||||||
|
@ -480,7 +481,7 @@ BOOL INSTR_EmulateInstruction( CONTEXT86 *context )
|
||||||
}
|
}
|
||||||
add_stack(context, long_op ? 4 : 2);
|
add_stack(context, long_op ? 4 : 2);
|
||||||
context->Eip += prefixlen + 1;
|
context->Eip += prefixlen + 1;
|
||||||
return TRUE;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break; /* Unable to emulate it */
|
break; /* Unable to emulate it */
|
||||||
|
@ -494,7 +495,7 @@ BOOL INSTR_EmulateInstruction( CONTEXT86 *context )
|
||||||
ERR("mov eax,cr0 at 0x%08lx, EAX=0x%08lx\n",
|
ERR("mov eax,cr0 at 0x%08lx, EAX=0x%08lx\n",
|
||||||
context->Eip,context->Eax );
|
context->Eip,context->Eax );
|
||||||
context->Eip += prefixlen+3;
|
context->Eip += prefixlen+3;
|
||||||
return TRUE;
|
return 0;
|
||||||
default:
|
default:
|
||||||
break; /*fallthrough to bad instruction handling */
|
break; /*fallthrough to bad instruction handling */
|
||||||
}
|
}
|
||||||
|
@ -516,12 +517,12 @@ BOOL INSTR_EmulateInstruction( CONTEXT86 *context )
|
||||||
ERR("mov cr4,eax at 0x%08lx\n",context->Eip);
|
ERR("mov cr4,eax at 0x%08lx\n",context->Eip);
|
||||||
context->Eax = 0;
|
context->Eax = 0;
|
||||||
context->Eip += prefixlen+3;
|
context->Eip += prefixlen+3;
|
||||||
return TRUE;
|
return 0;
|
||||||
case 0xc0: /* mov cr0, eax */
|
case 0xc0: /* mov cr0, eax */
|
||||||
ERR("mov cr0,eax at 0x%08lx\n",context->Eip);
|
ERR("mov cr0,eax at 0x%08lx\n",context->Eip);
|
||||||
context->Eax = 0x10; /* FIXME: set more bits ? */
|
context->Eax = 0x10; /* FIXME: set more bits ? */
|
||||||
context->Eip += prefixlen+3;
|
context->Eip += prefixlen+3;
|
||||||
return TRUE;
|
return 0;
|
||||||
default: /* fallthrough to illegal instruction */
|
default: /* fallthrough to illegal instruction */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -535,7 +536,7 @@ BOOL INSTR_EmulateInstruction( CONTEXT86 *context )
|
||||||
context->SegFs = seg;
|
context->SegFs = seg;
|
||||||
add_stack(context, long_op ? 4 : 2);
|
add_stack(context, long_op ? 4 : 2);
|
||||||
context->Eip += prefixlen + 2;
|
context->Eip += prefixlen + 2;
|
||||||
return TRUE;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -547,7 +548,7 @@ BOOL INSTR_EmulateInstruction( CONTEXT86 *context )
|
||||||
context->SegGs = seg;
|
context->SegGs = seg;
|
||||||
add_stack(context, long_op ? 4 : 2);
|
add_stack(context, long_op ? 4 : 2);
|
||||||
context->Eip += prefixlen + 2;
|
context->Eip += prefixlen + 2;
|
||||||
return TRUE;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -558,7 +559,7 @@ BOOL INSTR_EmulateInstruction( CONTEXT86 *context )
|
||||||
long_addr, segprefix, &len ))
|
long_addr, segprefix, &len ))
|
||||||
{
|
{
|
||||||
context->Eip += prefixlen + len;
|
context->Eip += prefixlen + len;
|
||||||
return TRUE;
|
return 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -631,7 +632,7 @@ BOOL INSTR_EmulateInstruction( CONTEXT86 *context )
|
||||||
}
|
}
|
||||||
context->Eip += prefixlen + 1;
|
context->Eip += prefixlen + 1;
|
||||||
}
|
}
|
||||||
return TRUE;
|
return 0;
|
||||||
|
|
||||||
case 0x8e: /* mov XX,segment_reg */
|
case 0x8e: /* mov XX,segment_reg */
|
||||||
{
|
{
|
||||||
|
@ -649,25 +650,25 @@ BOOL INSTR_EmulateInstruction( CONTEXT86 *context )
|
||||||
case 0:
|
case 0:
|
||||||
context->SegEs = seg;
|
context->SegEs = seg;
|
||||||
context->Eip += prefixlen + len + 1;
|
context->Eip += prefixlen + len + 1;
|
||||||
return TRUE;
|
return 0;
|
||||||
case 1: /* cs */
|
case 1: /* cs */
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
context->SegSs = seg;
|
context->SegSs = seg;
|
||||||
context->Eip += prefixlen + len + 1;
|
context->Eip += prefixlen + len + 1;
|
||||||
return TRUE;
|
return 0;
|
||||||
case 3:
|
case 3:
|
||||||
context->SegDs = seg;
|
context->SegDs = seg;
|
||||||
context->Eip += prefixlen + len + 1;
|
context->Eip += prefixlen + len + 1;
|
||||||
return TRUE;
|
return 0;
|
||||||
case 4:
|
case 4:
|
||||||
context->SegFs = seg;
|
context->SegFs = seg;
|
||||||
context->Eip += prefixlen + len + 1;
|
context->Eip += prefixlen + len + 1;
|
||||||
return TRUE;
|
return 0;
|
||||||
case 5:
|
case 5:
|
||||||
context->SegGs = seg;
|
context->SegGs = seg;
|
||||||
context->Eip += prefixlen + len + 1;
|
context->Eip += prefixlen + len + 1;
|
||||||
return TRUE;
|
return 0;
|
||||||
case 6: /* unused */
|
case 6: /* unused */
|
||||||
case 7: /* unused */
|
case 7: /* unused */
|
||||||
break;
|
break;
|
||||||
|
@ -681,19 +682,28 @@ BOOL INSTR_EmulateInstruction( CONTEXT86 *context )
|
||||||
long_addr, segprefix, &len ))
|
long_addr, segprefix, &len ))
|
||||||
{
|
{
|
||||||
context->Eip += prefixlen + len;
|
context->Eip += prefixlen + len;
|
||||||
return TRUE;
|
return 0;
|
||||||
}
|
}
|
||||||
break; /* Unable to emulate it */
|
break; /* Unable to emulate it */
|
||||||
|
|
||||||
case 0xcd: /* int <XX> */
|
case 0xcd: /* int <XX> */
|
||||||
if(!Dosvm.EmulateInterruptPM && !DPMI_LoadDosSystem())
|
if (IS_SELECTOR_SYSTEM(context->SegCs))
|
||||||
ERR("could not initialize interrupt handling\n");
|
{
|
||||||
else {
|
/* Win32 applications cannot use interrupts */
|
||||||
context->Eip += prefixlen + 2;
|
ret = EXCEPTION_ACCESS_VIOLATION;
|
||||||
Dosvm.EmulateInterruptPM( context, instr[1] );
|
break;
|
||||||
return TRUE;
|
}
|
||||||
}
|
else if (!Dosvm.EmulateInterruptPM && !DPMI_LoadDosSystem())
|
||||||
break; /* Unable to emulate it */
|
{
|
||||||
|
ERR("could not initialize interrupt handling\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
context->Eip += prefixlen + 2;
|
||||||
|
Dosvm.EmulateInterruptPM( context, instr[1] );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break; /* Unable to emulate it */
|
||||||
|
|
||||||
case 0xcf: /* iret */
|
case 0xcf: /* iret */
|
||||||
if (long_op)
|
if (long_op)
|
||||||
|
@ -712,12 +722,12 @@ BOOL INSTR_EmulateInstruction( CONTEXT86 *context )
|
||||||
SET_LOWORD(context->EFlags,*stack);
|
SET_LOWORD(context->EFlags,*stack);
|
||||||
add_stack(context, 3*sizeof(WORD)); /* Pop the return address and flags */
|
add_stack(context, 3*sizeof(WORD)); /* Pop the return address and flags */
|
||||||
}
|
}
|
||||||
return TRUE;
|
return 0;
|
||||||
|
|
||||||
case 0xe4: /* inb al,XX */
|
case 0xe4: /* inb al,XX */
|
||||||
SET_LOBYTE(context->Eax,INSTR_inport( instr[1], 1, context ));
|
SET_LOBYTE(context->Eax,INSTR_inport( instr[1], 1, context ));
|
||||||
context->Eip += prefixlen + 2;
|
context->Eip += prefixlen + 2;
|
||||||
return TRUE;
|
return 0;
|
||||||
|
|
||||||
case 0xe5: /* in (e)ax,XX */
|
case 0xe5: /* in (e)ax,XX */
|
||||||
if (long_op)
|
if (long_op)
|
||||||
|
@ -725,12 +735,12 @@ BOOL INSTR_EmulateInstruction( CONTEXT86 *context )
|
||||||
else
|
else
|
||||||
SET_LOWORD(context->Eax, INSTR_inport( instr[1], 2, context ));
|
SET_LOWORD(context->Eax, INSTR_inport( instr[1], 2, context ));
|
||||||
context->Eip += prefixlen + 2;
|
context->Eip += prefixlen + 2;
|
||||||
return TRUE;
|
return 0;
|
||||||
|
|
||||||
case 0xe6: /* outb XX,al */
|
case 0xe6: /* outb XX,al */
|
||||||
INSTR_outport( instr[1], 1, LOBYTE(context->Eax), context );
|
INSTR_outport( instr[1], 1, LOBYTE(context->Eax), context );
|
||||||
context->Eip += prefixlen + 2;
|
context->Eip += prefixlen + 2;
|
||||||
return TRUE;
|
return 0;
|
||||||
|
|
||||||
case 0xe7: /* out XX,(e)ax */
|
case 0xe7: /* out XX,(e)ax */
|
||||||
if (long_op)
|
if (long_op)
|
||||||
|
@ -738,12 +748,12 @@ BOOL INSTR_EmulateInstruction( CONTEXT86 *context )
|
||||||
else
|
else
|
||||||
INSTR_outport( instr[1], 2, LOWORD(context->Eax), context );
|
INSTR_outport( instr[1], 2, LOWORD(context->Eax), context );
|
||||||
context->Eip += prefixlen + 2;
|
context->Eip += prefixlen + 2;
|
||||||
return TRUE;
|
return 0;
|
||||||
|
|
||||||
case 0xec: /* inb al,dx */
|
case 0xec: /* inb al,dx */
|
||||||
SET_LOBYTE(context->Eax, INSTR_inport( LOWORD(context->Edx), 1, context ) );
|
SET_LOBYTE(context->Eax, INSTR_inport( LOWORD(context->Edx), 1, context ) );
|
||||||
context->Eip += prefixlen + 1;
|
context->Eip += prefixlen + 1;
|
||||||
return TRUE;
|
return 0;
|
||||||
|
|
||||||
case 0xed: /* in (e)ax,dx */
|
case 0xed: /* in (e)ax,dx */
|
||||||
if (long_op)
|
if (long_op)
|
||||||
|
@ -751,12 +761,12 @@ BOOL INSTR_EmulateInstruction( CONTEXT86 *context )
|
||||||
else
|
else
|
||||||
SET_LOWORD(context->Eax, INSTR_inport( LOWORD(context->Edx), 2, context ));
|
SET_LOWORD(context->Eax, INSTR_inport( LOWORD(context->Edx), 2, context ));
|
||||||
context->Eip += prefixlen + 1;
|
context->Eip += prefixlen + 1;
|
||||||
return TRUE;
|
return 0;
|
||||||
|
|
||||||
case 0xee: /* outb dx,al */
|
case 0xee: /* outb dx,al */
|
||||||
INSTR_outport( LOWORD(context->Edx), 1, LOBYTE(context->Eax), context );
|
INSTR_outport( LOWORD(context->Edx), 1, LOBYTE(context->Eax), context );
|
||||||
context->Eip += prefixlen + 1;
|
context->Eip += prefixlen + 1;
|
||||||
return TRUE;
|
return 0;
|
||||||
|
|
||||||
case 0xef: /* out dx,(e)ax */
|
case 0xef: /* out dx,(e)ax */
|
||||||
if (long_op)
|
if (long_op)
|
||||||
|
@ -764,32 +774,35 @@ BOOL INSTR_EmulateInstruction( CONTEXT86 *context )
|
||||||
else
|
else
|
||||||
INSTR_outport( LOWORD(context->Edx), 2, LOWORD(context->Eax), context );
|
INSTR_outport( LOWORD(context->Edx), 2, LOWORD(context->Eax), context );
|
||||||
context->Eip += prefixlen + 1;
|
context->Eip += prefixlen + 1;
|
||||||
return TRUE;
|
return 0;
|
||||||
|
|
||||||
case 0xfa: /* cli, ignored */
|
case 0xfa: /* cli, ignored */
|
||||||
context->Eip += prefixlen + 1;
|
context->Eip += prefixlen + 1;
|
||||||
return TRUE;
|
return 0;
|
||||||
|
|
||||||
case 0xfb: /* sti, ignored */
|
case 0xfb: /* sti, ignored */
|
||||||
context->Eip += prefixlen + 1;
|
context->Eip += prefixlen + 1;
|
||||||
return TRUE;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Check for Win16 __GP handler */
|
/* Check for Win16 __GP handler */
|
||||||
gpHandler = HasGPHandler16( MAKESEGPTR( context->SegCs, context->Eip ) );
|
if (!IS_SELECTOR_SYSTEM(context->SegCs))
|
||||||
if (gpHandler)
|
|
||||||
{
|
{
|
||||||
WORD *stack = get_stack( context );
|
SEGPTR gpHandler = HasGPHandler16( MAKESEGPTR( context->SegCs, context->Eip ) );
|
||||||
*--stack = context->SegCs;
|
if (gpHandler)
|
||||||
*--stack = context->Eip;
|
{
|
||||||
add_stack(context, -2*sizeof(WORD));
|
WORD *stack = get_stack( context );
|
||||||
|
*--stack = context->SegCs;
|
||||||
|
*--stack = context->Eip;
|
||||||
|
add_stack(context, -2*sizeof(WORD));
|
||||||
|
|
||||||
context->SegCs = SELECTOROF( gpHandler );
|
context->SegCs = SELECTOROF( gpHandler );
|
||||||
context->Eip = OFFSETOF( gpHandler );
|
context->Eip = OFFSETOF( gpHandler );
|
||||||
return TRUE;
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return FALSE; /* Unable to emulate it */
|
return ret; /* Unable to emulate it */
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* __i386__ */
|
#endif /* __i386__ */
|
||||||
|
|
Loading…
Reference in New Issue