00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
#include "ki.h"
00027
#include "ia32def.h"
00028
00029
NTSTATUS
00030
Ki386CheckDivideByZeroTrap (
00031 IN PKTRAP_FRAME UserFrame
00032 );
00033
00034
00035
#ifdef ALLOC_PRAGMA
00036
#pragma alloc_text(PAGE, Ki386CheckDivideByZeroTrap)
00037
#endif
00038
00039
00040 #define REG(field) ((ULONG_PTR)(&((KTRAP_FRAME *)0)->field))
00041 #define GETREG(frame,reg) ((PULONG) (((ULONG_PTR) frame)+reg))[0]
00042
00043
typedef struct {
00044 UCHAR RmDisplaceOnly;
00045 UCHAR RmSib;
00046 UCHAR RmDisplace;
00047 UCHAR Disp;
00048 }
KMOD, *
PKMOD;
00049
00050 static ULONG_PTR
RM32[] = {
00051
REG(IntV0),
00052
REG(IntT2),
00053
REG(IntT3),
00054
REG(IntT4),
00055
REG(IntSp),
00056
REG(IntTeb),
00057
REG(IntT5),
00058
REG(IntT6)
00059 };
00060
00061 static ULONG_PTR
RM8[] = {
00062
REG(IntV0),
00063
REG(IntT2),
00064
REG(IntT3),
00065
REG(IntT4),
00066
REG(IntV0) + 1,
00067
REG(IntT2) + 1,
00068
REG(IntT3) + 1,
00069
REG(IntT4) + 1
00070 };
00071
00072 static KMOD MOD32[] = {
00073 5, 4, 0x20, 4,
00074 0xff, 4, 0xff, 1,
00075 0xff, 4, 0xff, 4,
00076 0xff, 0xff, 0x00, 0
00077 } ;
00078
00079
static struct {
00080 UCHAR
Opcode1,
Opcode2;
00081 UCHAR
ModRm,
type;
00082 }
NoWaitNpxInstructions[] = {
00083 0xDB, 0xE3, 0, 1,
00084 0xDB, 0xE2, 0, 1,
00085 0xD9, 0x06, 1, 1,
00086 0xDD, 0x06, 1, 1,
00087 0xD9, 0x07, 1, 2,
00088 0xDD, 0x07, 1, 3,
00089 0xDF, 0xE0, 0, 4,
00090 0x00, 0x00, 0, 1
00091 };
00092
00093
00094
NTSTATUS
00095
Ki386CheckDivideByZeroTrap (
00096 IN PKTRAP_FRAME UserFrame
00097 )
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117 {
00118 ULONG operandsize, operandmask, i;
00119 ULONG_PTR accum;
00120 PUCHAR istream;
00121 ULONG_PTR *pRM;
00122 UCHAR ibyte, rm;
00123
PKMOD Mod;
00124 BOOLEAN fPrefix;
00125
NTSTATUS status;
00126
00127 status = STATUS_INTEGER_DIVIDE_BY_ZERO;
00128
00129
try {
00130
00131
00132
00133
00134
00135 fPrefix =
TRUE;
00136 pRM =
RM32;
00137 operandsize = 4;
00138 operandmask = 0xffffffff;
00139 istream = (PUCHAR)
EIP(UserFrame);
00140
while (fPrefix) {
00141 ibyte =
ProbeAndReadUchar(istream);
00142 istream++;
00143
switch (ibyte) {
00144
case 0x2e:
00145
case 0x36:
00146
case 0x3e:
00147
case 0x26:
00148
case 0x64:
00149
case 0x65:
00150
case 0xF3:
00151
case 0xF2:
00152
case 0xF0:
00153
break;
00154
00155
case 0x66:
00156
00157 operandsize = 2;
00158 operandmask = 0xffff;
00159
break;
00160
00161
case 0x67:
00162
00163
00164
goto try_exit;
00165
00166
default:
00167 fPrefix =
FALSE;
00168
break;
00169 }
00170 }
00171
00172
00173
00174
00175
00176
if (ibyte != 0xf7 && ibyte != 0xf6) {
00177
00178
goto try_exit;
00179 }
00180
00181
if (ibyte == 0xf6) {
00182
00183 operandsize = 1;
00184 operandmask = 0xff;
00185 }
00186
00187
00188
00189
00190
00191 ibyte =
ProbeAndReadUchar (istream);
00192 istream++;
00193 Mod =
MOD32 + (ibyte >> 6);
00194 rm = ibyte & 7;
00195
00196
00197
00198
00199
00200
if (operandsize == 1 && (ibyte & 0xc0) == 0xc0) {
00201 pRM =
RM8;
00202 }
00203
00204 accum = 0;
00205
if (rm != Mod->RmDisplaceOnly) {
00206
if (rm == Mod->RmSib) {
00207
00208 ibyte =
ProbeAndReadUchar(istream);
00209 istream++;
00210 i = (ibyte >> 3) & 7;
00211
if (i != 4) {
00212 accum =
GETREG(UserFrame, RM32[i]);
00213 accum = accum << (ibyte >> 6);
00214 }
00215 i = ibyte & 7;
00216 accum = accum +
GETREG(UserFrame, RM32[i]);
00217 }
else {
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 accum =
GETREG(UserFrame, pRM[rm]);
00228 }
00229 }
00230
00231
00232
00233
00234
00235
if (Mod->RmDisplace & (1 << rm)) {
00236
if (Mod->Disp == 4) {
00237 i =
ProbeAndReadUlong ((PULONG) istream);
00238 }
else {
00239 ibyte =
ProbeAndReadChar (istream);
00240 i = (
signed long) ((
signed char) ibyte);
00241 }
00242 accum += i;
00243 }
00244
00245
00246
00247
00248
00249
if (Mod->Disp) {
00250
switch (operandsize) {
00251
case 1: accum =
ProbeAndReadUchar((PUCHAR) accum);
break;
00252
case 2: accum =
ProbeAndReadUshort((PUSHORT) accum);
break;
00253
case 4: accum =
ProbeAndReadUlong((PULONG) accum);
break;
00254 }
00255 }
00256
00257
00258
00259
00260
00261
00262
if (accum & operandmask) {
00263
00264 status = STATUS_INTEGER_OVERFLOW;
00265 }
00266
00267 try_exit: ;
00268 } except (EXCEPTION_EXECUTE_HANDLER) {
00269
00270 }
00271
00272
return status;
00273 }