Revision b56dad1c exec-i386.c
b/exec-i386.c | ||
---|---|---|
149 | 149 |
|
150 | 150 |
/* exception support */ |
151 | 151 |
/* NOTE: not static to force relocation generation by GCC */ |
152 |
void raise_exception(int exception_index)
|
|
152 |
void raise_exception_err(int exception_index, int error_code)
|
|
153 | 153 |
{ |
154 | 154 |
/* NOTE: the register at this point must be saved by hand because |
155 | 155 |
longjmp restore them */ |
... | ... | |
178 | 178 |
env->regs[R_EDI] = EDI; |
179 | 179 |
#endif |
180 | 180 |
env->exception_index = exception_index; |
181 |
env->error_code = error_code; |
|
181 | 182 |
longjmp(env->jmp_env, 1); |
182 | 183 |
} |
183 | 184 |
|
185 |
/* short cut if error_code is 0 or not present */ |
|
186 |
void raise_exception(int exception_index) |
|
187 |
{ |
|
188 |
raise_exception_err(exception_index, 0); |
|
189 |
} |
|
190 |
|
|
184 | 191 |
#if defined(DEBUG_EXEC) |
185 | 192 |
static const char *cc_op_str[] = { |
186 | 193 |
"DYNAMIC", |
... | ... | |
218 | 225 |
static void cpu_x86_dump_state(FILE *f) |
219 | 226 |
{ |
220 | 227 |
int eflags; |
228 |
char cc_op_name[32]; |
|
221 | 229 |
eflags = cc_table[CC_OP].compute_all(); |
222 | 230 |
eflags |= (DF & DF_MASK); |
231 |
if ((unsigned)env->cc_op < CC_OP_NB) |
|
232 |
strcpy(cc_op_name, cc_op_str[env->cc_op]); |
|
233 |
else |
|
234 |
snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op); |
|
223 | 235 |
fprintf(f, |
224 | 236 |
"EAX=%08x EBX=%08X ECX=%08x EDX=%08x\n" |
225 | 237 |
"ESI=%08x EDI=%08X EBP=%08x ESP=%08x\n" |
... | ... | |
227 | 239 |
"EIP=%08x\n", |
228 | 240 |
env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX], |
229 | 241 |
env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP], |
230 |
env->cc_src, env->cc_dst, cc_op_str[env->cc_op],
|
|
242 |
env->cc_src, env->cc_dst, cc_op_name,
|
|
231 | 243 |
eflags & DF_MASK ? 'D' : '-', |
232 | 244 |
eflags & CC_O ? 'O' : '-', |
233 | 245 |
eflags & CC_S ? 'S' : '-', |
... | ... | |
280 | 292 |
|
281 | 293 |
h = pc & (CODE_GEN_HASH_SIZE - 1); |
282 | 294 |
ptb = &tb_hash[h]; |
283 |
for(;;) { |
|
284 |
tb = *ptb; |
|
285 |
if (!tb) |
|
286 |
break; |
|
287 |
if (tb->pc == pc && tb->cs_base == cs_base && tb->flags == flags) |
|
295 |
#if 0 |
|
296 |
/* XXX: hack to handle 16 bit modyfing code */ |
|
297 |
if (flags & (1 << GEN_FLAG_CODE32_SHIFT)) |
|
298 |
#endif |
|
299 |
for(;;) { |
|
300 |
tb = *ptb; |
|
301 |
if (!tb) |
|
302 |
break; |
|
303 |
if (tb->pc == pc && tb->cs_base == cs_base && tb->flags == flags) |
|
288 | 304 |
return tb; |
289 |
ptb = &tb->hash_next; |
|
290 |
} |
|
305 |
ptb = &tb->hash_next;
|
|
306 |
}
|
|
291 | 307 |
*pptb = ptb; |
292 | 308 |
return NULL; |
293 | 309 |
} |
... | ... | |
404 | 420 |
(unsigned long)env->seg_cache[R_SS].base) != 0) << |
405 | 421 |
GEN_FLAG_ADDSEG_SHIFT; |
406 | 422 |
flags |= (env->eflags & VM_MASK) >> (17 - GEN_FLAG_VM_SHIFT); |
423 |
flags |= (env->eflags & IOPL_MASK) >> (12 - GEN_FLAG_IOPL_SHIFT); |
|
424 |
flags |= (env->segs[R_CS] & 3) << GEN_FLAG_CPL_SHIFT; |
|
407 | 425 |
cs_base = env->seg_cache[R_CS].base; |
408 | 426 |
pc = cs_base + env->eip; |
409 | 427 |
tb = tb_find(&ptb, (unsigned long)pc, (unsigned long)cs_base, |
... | ... | |
508 | 526 |
#include <signal.h> |
509 | 527 |
#include <sys/ucontext.h> |
510 | 528 |
|
529 |
/* 'pc' is the host PC at which the exception was raised. 'address' is |
|
530 |
the effective address of the memory exception */ |
|
511 | 531 |
static inline int handle_cpu_signal(unsigned long pc, |
532 |
unsigned long address, |
|
512 | 533 |
sigset_t *old_set) |
513 | 534 |
{ |
514 | 535 |
#ifdef DEBUG_SIGNAL |
... | ... | |
524 | 545 |
sigprocmask(SIG_SETMASK, old_set, NULL); |
525 | 546 |
/* XXX: need to compute virtual pc position by retranslating |
526 | 547 |
code. The rest of the CPU state should be correct. */ |
527 |
raise_exception(EXCP0D_GPF); |
|
548 |
env->cr2 = address; |
|
549 |
/* XXX: more precise exception code */ |
|
550 |
raise_exception_err(EXCP0E_PAGE, 4); |
|
528 | 551 |
/* never comes here */ |
529 | 552 |
return 1; |
530 | 553 |
} else { |
... | ... | |
546 | 569 |
#endif |
547 | 570 |
pc = uc->uc_mcontext.gregs[REG_EIP]; |
548 | 571 |
pold_set = &uc->uc_sigmask; |
549 |
return handle_cpu_signal(pc, pold_set); |
|
572 |
return handle_cpu_signal(pc, (unsigned long)info->si_addr, pold_set);
|
|
550 | 573 |
#else |
551 | 574 |
#warning No CPU specific signal handler: cannot handle target SIGSEGV events |
552 | 575 |
return 0; |
Also available in: Unified diff