Commit 9de5e440b9f6a6c6305c0b81d1df4ddcc5a4b966

Authored by bellard
1 parent 66fb9763

better signal/exception support


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@42 c046a42c-6fe2-441c-8c8c-71466251a162
1 -- asynchronous signal interrupt / clear synchronous signal handling  
2 -- add eflags restore in emulator  
3 -- finish signal handing (fp87 state)  
4 -- verify thread support (clone() and various locks)  
5 - optimize translated cache chaining (DLL PLT-like system) 1 - optimize translated cache chaining (DLL PLT-like system)
  2 +- more syscalls (in particular all 64 bit ones, IPCs, fix 64 bit issues)
  3 +- finish signal handing (fp87 state, more siginfo conversions)
  4 +- verify thread support (clone() and various locks)
6 - vm86 syscall support 5 - vm86 syscall support
7 - overrides/16bit for string ops 6 - overrides/16bit for string ops
8 -- more syscalls (in particular all 64 bit ones)  
9 - make it self runnable (use same trick as ld.so : include its own relocator and libc) 7 - make it self runnable (use same trick as ld.so : include its own relocator and libc)
10 - improved 16 bit support 8 - improved 16 bit support
11 - fix FPU exceptions (in particular: gen_op_fpush not before mem load) 9 - fix FPU exceptions (in particular: gen_op_fpush not before mem load)
cpu-i386.h
@@ -68,7 +68,7 @@ @@ -68,7 +68,7 @@
68 #define EXCP11_ALGN 18 68 #define EXCP11_ALGN 18
69 #define EXCP12_MCHK 19 69 #define EXCP12_MCHK 19
70 70
71 -#define EXCP_SIGNAL 256 /* async signal */ 71 +#define EXCP_INTERRUPT 256 /* async interruption */
72 72
73 enum { 73 enum {
74 CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */ 74 CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */
@@ -170,9 +170,10 @@ typedef struct CPUX86State { @@ -170,9 +170,10 @@ typedef struct CPUX86State {
170 /* various CPU modes */ 170 /* various CPU modes */
171 int vm86; 171 int vm86;
172 172
173 - /* exception handling */ 173 + /* exception/interrupt handling */
174 jmp_buf jmp_env; 174 jmp_buf jmp_env;
175 int exception_index; 175 int exception_index;
  176 + int interrupt_request;
176 } CPUX86State; 177 } CPUX86State;
177 178
178 /* all CPU memory access use these macros */ 179 /* all CPU memory access use these macros */
@@ -383,11 +384,19 @@ int cpu_x86_inl(int addr); @@ -383,11 +384,19 @@ int cpu_x86_inl(int addr);
383 384
384 CPUX86State *cpu_x86_init(void); 385 CPUX86State *cpu_x86_init(void);
385 int cpu_x86_exec(CPUX86State *s); 386 int cpu_x86_exec(CPUX86State *s);
  387 +void cpu_x86_interrupt(CPUX86State *s);
386 void cpu_x86_close(CPUX86State *s); 388 void cpu_x86_close(CPUX86State *s);
387 389
388 /* needed to load some predefinied segment registers */ 390 /* needed to load some predefinied segment registers */
389 void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector); 391 void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector);
390 392
  393 +/* you can call these signal handler from you SIGBUS and SIGSEGV
  394 + signal handlers to inform the virtual CPU of exceptions. non zero
  395 + is returned if the signal was handled by the virtual CPU. */
  396 +struct siginfo;
  397 +int cpu_x86_signal_handler(int host_signum, struct siginfo *info,
  398 + void *puc);
  399 +
391 /* internal functions */ 400 /* internal functions */
392 401
393 #define GEN_FLAG_CODE32_SHIFT 0 402 #define GEN_FLAG_CODE32_SHIFT 0
exec-i386.c
@@ -21,6 +21,7 @@ @@ -21,6 +21,7 @@
21 21
22 //#define DEBUG_EXEC 22 //#define DEBUG_EXEC
23 #define DEBUG_FLUSH 23 #define DEBUG_FLUSH
  24 +//#define DEBUG_SIGNAL
24 25
25 /* main execution loop */ 26 /* main execution loop */
26 27
@@ -98,7 +99,41 @@ void cpu_unlock(void) @@ -98,7 +99,41 @@ void cpu_unlock(void)
98 global_cpu_lock = 0; 99 global_cpu_lock = 0;
99 } 100 }
100 101
101 -#ifdef DEBUG_EXEC 102 +/* exception support */
  103 +/* NOTE: not static to force relocation generation by GCC */
  104 +void raise_exception(int exception_index)
  105 +{
  106 + /* NOTE: the register at this point must be saved by hand because
  107 + longjmp restore them */
  108 +#ifdef reg_EAX
  109 + env->regs[R_EAX] = EAX;
  110 +#endif
  111 +#ifdef reg_ECX
  112 + env->regs[R_ECX] = ECX;
  113 +#endif
  114 +#ifdef reg_EDX
  115 + env->regs[R_EDX] = EDX;
  116 +#endif
  117 +#ifdef reg_EBX
  118 + env->regs[R_EBX] = EBX;
  119 +#endif
  120 +#ifdef reg_ESP
  121 + env->regs[R_ESP] = ESP;
  122 +#endif
  123 +#ifdef reg_EBP
  124 + env->regs[R_EBP] = EBP;
  125 +#endif
  126 +#ifdef reg_ESI
  127 + env->regs[R_ESI] = ESI;
  128 +#endif
  129 +#ifdef reg_EDI
  130 + env->regs[R_EDI] = EDI;
  131 +#endif
  132 + env->exception_index = exception_index;
  133 + longjmp(env->jmp_env, 1);
  134 +}
  135 +
  136 +#if defined(DEBUG_EXEC)
102 static const char *cc_op_str[] = { 137 static const char *cc_op_str[] = {
103 "DYNAMIC", 138 "DYNAMIC",
104 "EFLAGS", 139 "EFLAGS",
@@ -132,15 +167,16 @@ static const char *cc_op_str[] = { @@ -132,15 +167,16 @@ static const char *cc_op_str[] = {
132 "SARL", 167 "SARL",
133 }; 168 };
134 169
135 -static void cpu_x86_dump_state(void) 170 +static void cpu_x86_dump_state(FILE *f)
136 { 171 {
137 int eflags; 172 int eflags;
138 eflags = cc_table[CC_OP].compute_all(); 173 eflags = cc_table[CC_OP].compute_all();
139 eflags |= (DF & DIRECTION_FLAG); 174 eflags |= (DF & DIRECTION_FLAG);
140 - fprintf(logfile, 175 + fprintf(f,
141 "EAX=%08x EBX=%08X ECX=%08x EDX=%08x\n" 176 "EAX=%08x EBX=%08X ECX=%08x EDX=%08x\n"
142 "ESI=%08x EDI=%08X EBP=%08x ESP=%08x\n" 177 "ESI=%08x EDI=%08X EBP=%08x ESP=%08x\n"
143 - "CCS=%08x CCD=%08x CCO=%-8s EFL=%c%c%c%c%c%c%c\n", 178 + "CCS=%08x CCD=%08x CCO=%-8s EFL=%c%c%c%c%c%c%c\n"
  179 + "EIP=%08x\n",
144 env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX], 180 env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX],
145 env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP], 181 env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP],
146 env->cc_src, env->cc_dst, cc_op_str[env->cc_op], 182 env->cc_src, env->cc_dst, cc_op_str[env->cc_op],
@@ -150,10 +186,10 @@ static void cpu_x86_dump_state(void) @@ -150,10 +186,10 @@ static void cpu_x86_dump_state(void)
150 eflags & CC_Z ? 'Z' : '-', 186 eflags & CC_Z ? 'Z' : '-',
151 eflags & CC_A ? 'A' : '-', 187 eflags & CC_A ? 'A' : '-',
152 eflags & CC_P ? 'P' : '-', 188 eflags & CC_P ? 'P' : '-',
153 - eflags & CC_C ? 'C' : '-'  
154 - ); 189 + eflags & CC_C ? 'C' : '-',
  190 + env->eip);
155 #if 1 191 #if 1
156 - fprintf(logfile, "ST0=%f ST1=%f ST2=%f ST3=%f\n", 192 + fprintf(f, "ST0=%f ST1=%f ST2=%f ST3=%f\n",
157 (double)ST0, (double)ST1, (double)ST(2), (double)ST(3)); 193 (double)ST0, (double)ST1, (double)ST(2), (double)ST(3));
158 #endif 194 #endif
159 } 195 }
@@ -185,10 +221,11 @@ static void tb_flush(void) @@ -185,10 +221,11 @@ static void tb_flush(void)
185 } 221 }
186 222
187 /* find a translation block in the translation cache. If not found, 223 /* find a translation block in the translation cache. If not found,
188 - allocate a new one */  
189 -static inline TranslationBlock *tb_find_and_alloc(unsigned long pc,  
190 - unsigned long cs_base,  
191 - unsigned int flags) 224 + return NULL and the pointer to the last element of the list in pptb */
  225 +static inline TranslationBlock *tb_find(TranslationBlock ***pptb,
  226 + unsigned long pc,
  227 + unsigned long cs_base,
  228 + unsigned int flags)
192 { 229 {
193 TranslationBlock **ptb, *tb; 230 TranslationBlock **ptb, *tb;
194 unsigned int h; 231 unsigned int h;
@@ -203,16 +240,19 @@ static inline TranslationBlock *tb_find_and_alloc(unsigned long pc, @@ -203,16 +240,19 @@ static inline TranslationBlock *tb_find_and_alloc(unsigned long pc,
203 return tb; 240 return tb;
204 ptb = &tb->hash_next; 241 ptb = &tb->hash_next;
205 } 242 }
  243 + *pptb = ptb;
  244 + return NULL;
  245 +}
  246 +
  247 +/* allocate a new translation block. flush the translation buffer if
  248 + too many translation blocks or too much generated code */
  249 +static inline TranslationBlock *tb_alloc(void)
  250 +{
  251 + TranslationBlock *tb;
206 if (nb_tbs >= CODE_GEN_MAX_BLOCKS || 252 if (nb_tbs >= CODE_GEN_MAX_BLOCKS ||
207 (code_gen_ptr - code_gen_buffer) >= CODE_GEN_BUFFER_MAX_SIZE) 253 (code_gen_ptr - code_gen_buffer) >= CODE_GEN_BUFFER_MAX_SIZE)
208 tb_flush(); 254 tb_flush();
209 tb = &tbs[nb_tbs++]; 255 tb = &tbs[nb_tbs++];
210 - *ptb = tb;  
211 - tb->pc = pc;  
212 - tb->cs_base = cs_base;  
213 - tb->flags = flags;  
214 - tb->tc_ptr = NULL;  
215 - tb->hash_next = NULL;  
216 return tb; 256 return tb;
217 } 257 }
218 258
@@ -246,7 +286,7 @@ int cpu_x86_exec(CPUX86State *env1) @@ -246,7 +286,7 @@ int cpu_x86_exec(CPUX86State *env1)
246 #endif 286 #endif
247 int code_gen_size, ret; 287 int code_gen_size, ret;
248 void (*gen_func)(void); 288 void (*gen_func)(void);
249 - TranslationBlock *tb; 289 + TranslationBlock *tb, **ptb;
250 uint8_t *tc_ptr, *cs_base, *pc; 290 uint8_t *tc_ptr, *cs_base, *pc;
251 unsigned int flags; 291 unsigned int flags;
252 292
@@ -289,12 +329,21 @@ int cpu_x86_exec(CPUX86State *env1) @@ -289,12 +329,21 @@ int cpu_x86_exec(CPUX86State *env1)
289 EDI = env->regs[R_EDI]; 329 EDI = env->regs[R_EDI];
290 #endif 330 #endif
291 331
  332 + /* put eflags in CPU temporary format */
  333 + T0 = env->eflags;
  334 + op_movl_eflags_T0();
  335 + CC_OP = CC_OP_EFLAGS;
  336 + env->interrupt_request = 0;
  337 +
292 /* prepare setjmp context for exception handling */ 338 /* prepare setjmp context for exception handling */
293 if (setjmp(env->jmp_env) == 0) { 339 if (setjmp(env->jmp_env) == 0) {
294 for(;;) { 340 for(;;) {
  341 + if (env->interrupt_request) {
  342 + raise_exception(EXCP_INTERRUPT);
  343 + }
295 #ifdef DEBUG_EXEC 344 #ifdef DEBUG_EXEC
296 if (loglevel) { 345 if (loglevel) {
297 - cpu_x86_dump_state(); 346 + cpu_x86_dump_state(logfile);
298 } 347 }
299 #endif 348 #endif
300 /* we compute the CPU state. We assume it will not 349 /* we compute the CPU state. We assume it will not
@@ -307,28 +356,43 @@ int cpu_x86_exec(CPUX86State *env1) @@ -307,28 +356,43 @@ int cpu_x86_exec(CPUX86State *env1)
307 GEN_FLAG_ADDSEG_SHIFT; 356 GEN_FLAG_ADDSEG_SHIFT;
308 cs_base = env->seg_cache[R_CS].base; 357 cs_base = env->seg_cache[R_CS].base;
309 pc = cs_base + env->eip; 358 pc = cs_base + env->eip;
310 - tb = tb_find_and_alloc((unsigned long)pc, (unsigned long)cs_base,  
311 - flags);  
312 - tc_ptr = tb->tc_ptr;  
313 - if (!tb->tc_ptr) { 359 + tb = tb_find(&ptb, (unsigned long)pc, (unsigned long)cs_base,
  360 + flags);
  361 + if (!tb) {
314 /* if no translated code available, then translate it now */ 362 /* if no translated code available, then translate it now */
315 /* XXX: very inefficient: we lock all the cpus when 363 /* XXX: very inefficient: we lock all the cpus when
316 generating code */ 364 generating code */
317 cpu_lock(); 365 cpu_lock();
318 tc_ptr = code_gen_ptr; 366 tc_ptr = code_gen_ptr;
319 - cpu_x86_gen_code(code_gen_ptr, CODE_GEN_MAX_SIZE,  
320 - &code_gen_size, pc, cs_base, flags); 367 + ret = cpu_x86_gen_code(code_gen_ptr, CODE_GEN_MAX_SIZE,
  368 + &code_gen_size, pc, cs_base, flags);
  369 + /* if invalid instruction, signal it */
  370 + if (ret != 0) {
  371 + cpu_unlock();
  372 + raise_exception(EXCP06_ILLOP);
  373 + }
  374 + tb = tb_alloc();
  375 + *ptb = tb;
  376 + tb->pc = (unsigned long)pc;
  377 + tb->cs_base = (unsigned long)cs_base;
  378 + tb->flags = flags;
321 tb->tc_ptr = tc_ptr; 379 tb->tc_ptr = tc_ptr;
  380 + tb->hash_next = NULL;
322 code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1)); 381 code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
323 cpu_unlock(); 382 cpu_unlock();
324 } 383 }
325 /* execute the generated code */ 384 /* execute the generated code */
  385 + tc_ptr = tb->tc_ptr;
326 gen_func = (void *)tc_ptr; 386 gen_func = (void *)tc_ptr;
327 gen_func(); 387 gen_func();
328 } 388 }
329 } 389 }
330 ret = env->exception_index; 390 ret = env->exception_index;
331 391
  392 + /* restore flags in standard format */
  393 + op_movl_T0_eflags();
  394 + env->eflags = T0;
  395 +
332 /* restore global registers */ 396 /* restore global registers */
333 #ifdef reg_EAX 397 #ifdef reg_EAX
334 EAX = saved_EAX; 398 EAX = saved_EAX;
@@ -361,6 +425,12 @@ int cpu_x86_exec(CPUX86State *env1) @@ -361,6 +425,12 @@ int cpu_x86_exec(CPUX86State *env1)
361 return ret; 425 return ret;
362 } 426 }
363 427
  428 +void cpu_x86_interrupt(CPUX86State *s)
  429 +{
  430 + s->interrupt_request = 1;
  431 +}
  432 +
  433 +
364 void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector) 434 void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
365 { 435 {
366 CPUX86State *saved_env; 436 CPUX86State *saved_env;
@@ -370,3 +440,56 @@ void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector) @@ -370,3 +440,56 @@ void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
370 load_seg(seg_reg, selector); 440 load_seg(seg_reg, selector);
371 env = saved_env; 441 env = saved_env;
372 } 442 }
  443 +
  444 +#undef EAX
  445 +#undef ECX
  446 +#undef EDX
  447 +#undef EBX
  448 +#undef ESP
  449 +#undef EBP
  450 +#undef ESI
  451 +#undef EDI
  452 +#undef EIP
  453 +#include <signal.h>
  454 +#include <sys/ucontext.h>
  455 +
  456 +static inline int handle_cpu_signal(unsigned long pc,
  457 + sigset_t *old_set)
  458 +{
  459 +#ifdef DEBUG_SIGNAL
  460 + printf("gemu: SIGSEGV pc=0x%08lx oldset=0x%08lx\n",
  461 + pc, *(unsigned long *)old_set);
  462 +#endif
  463 + if (pc >= (unsigned long)code_gen_buffer &&
  464 + pc < (unsigned long)code_gen_buffer + CODE_GEN_BUFFER_SIZE) {
  465 + /* the PC is inside the translated code. It means that we have
  466 + a virtual CPU fault */
  467 + /* we restore the process signal mask as the sigreturn should
  468 + do it */
  469 + sigprocmask(SIG_SETMASK, old_set, NULL);
  470 + /* XXX: need to compute virtual pc position by retranslating
  471 + code. The rest of the CPU state should be correct. */
  472 + raise_exception(EXCP0D_GPF);
  473 + /* never comes here */
  474 + return 1;
  475 + } else {
  476 + return 0;
  477 + }
  478 +}
  479 +
  480 +int cpu_x86_signal_handler(int host_signum, struct siginfo *info,
  481 + void *puc)
  482 +{
  483 +#if defined(__i386__)
  484 + struct ucontext *uc = puc;
  485 + unsigned long pc;
  486 + sigset_t *pold_set;
  487 +
  488 + pc = uc->uc_mcontext.gregs[EIP];
  489 + pold_set = &uc->uc_sigmask;
  490 + return handle_cpu_signal(pc, pold_set);
  491 +#else
  492 +#warning No CPU specific signal handler: cannot handle target SIGSEGV events
  493 + return 0;
  494 +#endif
  495 +}
exec-i386.h
@@ -141,3 +141,7 @@ extern CCTable cc_table[]; @@ -141,3 +141,7 @@ extern CCTable cc_table[];
141 void load_seg(int seg_reg, int selector); 141 void load_seg(int seg_reg, int selector);
142 void cpu_lock(void); 142 void cpu_lock(void);
143 void cpu_unlock(void); 143 void cpu_unlock(void);
  144 +void raise_exception(int exception_index);
  145 +
  146 +void OPPROTO op_movl_eflags_T0(void);
  147 +void OPPROTO op_movl_T0_eflags(void);
linux-user/elfload.c
@@ -261,6 +261,9 @@ unsigned long setup_arg_pages(unsigned long p, struct linux_binprm * bprm, @@ -261,6 +261,9 @@ unsigned long setup_arg_pages(unsigned long p, struct linux_binprm * bprm,
261 /* Create enough stack to hold everything. If we don't use 261 /* Create enough stack to hold everything. If we don't use
262 * it for args, we'll use it for something else... 262 * it for args, we'll use it for something else...
263 */ 263 */
  264 + /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
  265 + we allocate a bigger stack. Need a better solution, for example
  266 + by remapping the process stack directly at the right place */
264 if(x86_stack_size > MAX_ARG_PAGES*X86_PAGE_SIZE) { 267 if(x86_stack_size > MAX_ARG_PAGES*X86_PAGE_SIZE) {
265 if((long)mmap4k((void *)(X86_STACK_TOP-x86_stack_size), x86_stack_size + X86_PAGE_SIZE, 268 if((long)mmap4k((void *)(X86_STACK_TOP-x86_stack_size), x86_stack_size + X86_PAGE_SIZE,
266 PROT_READ | PROT_WRITE, 269 PROT_READ | PROT_WRITE,
linux-user/ioctls.h
1 /* emulated ioctl list */ 1 /* emulated ioctl list */
2 2
3 IOCTL(TCGETS, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios))) 3 IOCTL(TCGETS, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios)))
4 - IOCTL(TCGETS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios))) 4 + IOCTL(TCSETS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
5 IOCTL(TCSETSF, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios))) 5 IOCTL(TCSETSF, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
6 IOCTL(TCSETSW, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios))) 6 IOCTL(TCSETSW, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
7 IOCTL(TIOCGWINSZ, IOC_R, MK_PTR(MK_STRUCT(STRUCT_winsize))) 7 IOCTL(TIOCGWINSZ, IOC_R, MK_PTR(MK_STRUCT(STRUCT_winsize)))
@@ -199,8 +199,12 @@ @@ -199,8 +199,12 @@
199 IOCTL(SNDCTL_TMR_METRONOME, IOC_W, MK_PTR(TYPE_INT)) 199 IOCTL(SNDCTL_TMR_METRONOME, IOC_W, MK_PTR(TYPE_INT))
200 IOCTL(SNDCTL_TMR_SELECT, IOC_W, MK_PTR(TYPE_INT)) 200 IOCTL(SNDCTL_TMR_SELECT, IOC_W, MK_PTR(TYPE_INT))
201 IOCTL(SNDCTL_TMR_SOURCE, IOC_RW, MK_PTR(TYPE_INT)) 201 IOCTL(SNDCTL_TMR_SOURCE, IOC_RW, MK_PTR(TYPE_INT))
  202 +#if 0
  203 + /* we invalidate these defines because they have a same number as
  204 + termios ioctls */
202 IOCTL(SNDCTL_TMR_START, 0, TYPE_NULL) 205 IOCTL(SNDCTL_TMR_START, 0, TYPE_NULL)
203 IOCTL(SNDCTL_TMR_STOP, 0, TYPE_NULL) 206 IOCTL(SNDCTL_TMR_STOP, 0, TYPE_NULL)
  207 +#endif
204 IOCTL(SNDCTL_TMR_TEMPO, IOC_RW, MK_PTR(TYPE_INT)) 208 IOCTL(SNDCTL_TMR_TEMPO, IOC_RW, MK_PTR(TYPE_INT))
205 IOCTL(SNDCTL_TMR_TIMEBASE, IOC_RW, MK_PTR(TYPE_INT)) 209 IOCTL(SNDCTL_TMR_TIMEBASE, IOC_RW, MK_PTR(TYPE_INT))
206 210
linux-user/main.c
@@ -33,7 +33,10 @@ @@ -33,7 +33,10 @@
33 FILE *logfile = NULL; 33 FILE *logfile = NULL;
34 int loglevel; 34 int loglevel;
35 35
36 -unsigned long x86_stack_size; 36 +/* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
  37 + we allocate a bigger stack. Need a better solution, for example
  38 + by remapping the process stack directly at the right place */
  39 +unsigned long x86_stack_size = 512 * 1024;
37 unsigned long stktop; 40 unsigned long stktop;
38 41
39 void gemu_log(const char *fmt, ...) 42 void gemu_log(const char *fmt, ...)
@@ -102,10 +105,11 @@ uint64_t gdt_table[6]; @@ -102,10 +105,11 @@ uint64_t gdt_table[6];
102 105
103 void cpu_loop(struct CPUX86State *env) 106 void cpu_loop(struct CPUX86State *env)
104 { 107 {
  108 + int err;
  109 + uint8_t *pc;
  110 + target_siginfo_t info;
  111 +
105 for(;;) { 112 for(;;) {
106 - int err;  
107 - uint8_t *pc;  
108 -  
109 err = cpu_x86_exec(env); 113 err = cpu_x86_exec(env);
110 pc = env->seg_cache[R_CS].base + env->eip; 114 pc = env->seg_cache[R_CS].base + env->eip;
111 switch(err) { 115 switch(err) {
@@ -122,12 +126,42 @@ void cpu_loop(struct CPUX86State *env) @@ -122,12 +126,42 @@ void cpu_loop(struct CPUX86State *env)
122 env->regs[R_EDI], 126 env->regs[R_EDI],
123 env->regs[R_EBP]); 127 env->regs[R_EBP]);
124 } else { 128 } else {
125 - goto trap_error; 129 + /* XXX: more precise info */
  130 + info.si_signo = SIGSEGV;
  131 + info.si_errno = 0;
  132 + info.si_code = 0;
  133 + info._sifields._sigfault._addr = 0;
  134 + queue_signal(info.si_signo, &info);
126 } 135 }
127 break; 136 break;
  137 + case EXCP00_DIVZ:
  138 + /* division by zero */
  139 + info.si_signo = SIGFPE;
  140 + info.si_errno = 0;
  141 + info.si_code = TARGET_FPE_INTDIV;
  142 + info._sifields._sigfault._addr = env->eip;
  143 + queue_signal(info.si_signo, &info);
  144 + break;
  145 + case EXCP04_INTO:
  146 + case EXCP05_BOUND:
  147 + info.si_signo = SIGSEGV;
  148 + info.si_errno = 0;
  149 + info.si_code = 0;
  150 + info._sifields._sigfault._addr = 0;
  151 + queue_signal(info.si_signo, &info);
  152 + break;
  153 + case EXCP06_ILLOP:
  154 + info.si_signo = SIGILL;
  155 + info.si_errno = 0;
  156 + info.si_code = TARGET_ILL_ILLOPN;
  157 + info._sifields._sigfault._addr = env->eip;
  158 + queue_signal(info.si_signo, &info);
  159 + break;
  160 + case EXCP_INTERRUPT:
  161 + /* just indicate that signals should be handled asap */
  162 + break;
128 default: 163 default:
129 - trap_error:  
130 - fprintf(stderr, "0x%08lx: Unknown exception %d, aborting\n", 164 + fprintf(stderr, "0x%08lx: Unknown exception CPU %d, aborting\n",
131 (long)pc, err); 165 (long)pc, err);
132 abort(); 166 abort();
133 } 167 }
@@ -144,6 +178,9 @@ void usage(void) @@ -144,6 +178,9 @@ void usage(void)
144 exit(1); 178 exit(1);
145 } 179 }
146 180
  181 +/* XXX: currently only used for async signals (see signal.c) */
  182 +CPUX86State *global_env;
  183 +
147 int main(int argc, char **argv) 184 int main(int argc, char **argv)
148 { 185 {
149 const char *filename; 186 const char *filename;
@@ -199,6 +236,7 @@ int main(int argc, char **argv) @@ -199,6 +236,7 @@ int main(int argc, char **argv)
199 signal_init(); 236 signal_init();
200 237
201 env = cpu_x86_init(); 238 env = cpu_x86_init();
  239 + global_env = env;
202 240
203 /* linux register setup */ 241 /* linux register setup */
204 env->regs[R_EAX] = regs->eax; 242 env->regs[R_EAX] = regs->eax;
linux-user/qemu.h
@@ -3,30 +3,12 @@ @@ -3,30 +3,12 @@
3 3
4 #include "thunk.h" 4 #include "thunk.h"
5 5
6 -#ifdef TARGET_I386  
7 -  
8 -/* default linux values for the selectors */  
9 -#define __USER_CS (0x23)  
10 -#define __USER_DS (0x2B)  
11 -  
12 -struct target_pt_regs {  
13 - long ebx;  
14 - long ecx;  
15 - long edx;  
16 - long esi;  
17 - long edi;  
18 - long ebp;  
19 - long eax;  
20 - int xds;  
21 - int xes;  
22 - long orig_eax;  
23 - long eip;  
24 - int xcs;  
25 - long eflags;  
26 - long esp;  
27 - int xss;  
28 -}; 6 +#include <signal.h>
  7 +#include "syscall_defs.h"
29 8
  9 +#ifdef TARGET_I386
  10 +#include "cpu-i386.h"
  11 +#include "syscall-i386.h"
30 #endif 12 #endif
31 13
32 /* This struct is used to hold certain information about the image. 14 /* This struct is used to hold certain information about the image.
@@ -59,9 +41,10 @@ void syscall_init(void); @@ -59,9 +41,10 @@ void syscall_init(void);
59 long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, 41 long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
60 long arg4, long arg5, long arg6); 42 long arg4, long arg5, long arg6);
61 void gemu_log(const char *fmt, ...) __attribute__((format(printf,1,2))); 43 void gemu_log(const char *fmt, ...) __attribute__((format(printf,1,2)));
62 -struct CPUX86State;  
63 -void cpu_loop(struct CPUX86State *env); 44 +extern CPUX86State *global_env;
  45 +void cpu_loop(CPUX86State *env);
64 void process_pending_signals(void *cpu_env); 46 void process_pending_signals(void *cpu_env);
65 void signal_init(void); 47 void signal_init(void);
  48 +int queue_signal(int sig, target_siginfo_t *info);
66 49
67 #endif 50 #endif
linux-user/signal.c
@@ -27,13 +27,6 @@ @@ -27,13 +27,6 @@
27 27
28 #include "gemu.h" 28 #include "gemu.h"
29 29
30 -#include "syscall_defs.h"  
31 -  
32 -#ifdef TARGET_I386  
33 -#include "cpu-i386.h"  
34 -#include "syscall-i386.h"  
35 -#endif  
36 -  
37 /* signal handling inspired from em86. */ 30 /* signal handling inspired from em86. */
38 31
39 //#define DEBUG_SIGNAL 32 //#define DEBUG_SIGNAL
@@ -42,7 +35,7 @@ @@ -42,7 +35,7 @@
42 35
43 struct sigqueue { 36 struct sigqueue {
44 struct sigqueue *next; 37 struct sigqueue *next;
45 - siginfo_t info; 38 + target_siginfo_t info;
46 }; 39 };
47 40
48 struct emulated_sigaction { 41 struct emulated_sigaction {
@@ -101,20 +94,66 @@ void target_to_host_old_sigset(sigset_t *sigset, @@ -101,20 +94,66 @@ void target_to_host_old_sigset(sigset_t *sigset,
101 *(unsigned long *)sigset = tswapl(*old_sigset); 94 *(unsigned long *)sigset = tswapl(*old_sigset);
102 } 95 }
103 96
104 -/* XXX: finish it */  
105 -void host_to_target_siginfo(target_siginfo_t *tinfo, siginfo_t *info) 97 +/* siginfo conversion */
  98 +
  99 +static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
  100 + const siginfo_t *info)
106 { 101 {
107 - tinfo->si_signo = tswap32(info->si_signo); 102 + int sig;
  103 + sig = host_to_target_signal(info->si_signo);
  104 + tinfo->si_signo = sig;
  105 + tinfo->si_errno = 0;
  106 + tinfo->si_code = 0;
  107 + if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV || sig == SIGBUS) {
  108 + /* should never come here, but who knows. The information for
  109 + the target is irrelevant */
  110 + tinfo->_sifields._sigfault._addr = 0;
  111 + } else if (sig >= TARGET_SIGRTMIN) {
  112 + tinfo->_sifields._rt._pid = info->si_pid;
  113 + tinfo->_sifields._rt._uid = info->si_uid;
  114 + /* XXX: potential problem if 64 bit */
  115 + tinfo->_sifields._rt._sigval.sival_ptr =
  116 + (target_ulong)info->si_value.sival_ptr;
  117 + }
  118 +}
  119 +
  120 +static void tswap_siginfo(target_siginfo_t *tinfo,
  121 + const target_siginfo_t *info)
  122 +{
  123 + int sig;
  124 + sig = info->si_signo;
  125 + tinfo->si_signo = tswap32(sig);
108 tinfo->si_errno = tswap32(info->si_errno); 126 tinfo->si_errno = tswap32(info->si_errno);
109 tinfo->si_code = tswap32(info->si_code); 127 tinfo->si_code = tswap32(info->si_code);
  128 + if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV || sig == SIGBUS) {
  129 + tinfo->_sifields._sigfault._addr =
  130 + tswapl(info->_sifields._sigfault._addr);
  131 + } else if (sig >= TARGET_SIGRTMIN) {
  132 + tinfo->_sifields._rt._pid = tswap32(info->_sifields._rt._pid);
  133 + tinfo->_sifields._rt._uid = tswap32(info->_sifields._rt._uid);
  134 + tinfo->_sifields._rt._sigval.sival_ptr =
  135 + tswapl(info->_sifields._rt._sigval.sival_ptr);
  136 + }
  137 +}
  138 +
  139 +
  140 +void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
  141 +{
  142 + host_to_target_siginfo_noswap(tinfo, info);
  143 + tswap_siginfo(tinfo, tinfo);
110 } 144 }
111 145
112 -/* XXX: finish it */  
113 -void target_to_host_siginfo(siginfo_t *info, target_siginfo_t *tinfo) 146 +/* XXX: we support only POSIX RT signals are used. */
  147 +/* XXX: find a solution for 64 bit (additionnal malloced data is needed) */
  148 +void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo)
114 { 149 {
115 info->si_signo = tswap32(tinfo->si_signo); 150 info->si_signo = tswap32(tinfo->si_signo);
116 info->si_errno = tswap32(tinfo->si_errno); 151 info->si_errno = tswap32(tinfo->si_errno);
117 info->si_code = tswap32(tinfo->si_code); 152 info->si_code = tswap32(tinfo->si_code);
  153 + info->si_pid = tswap32(tinfo->_sifields._rt._pid);
  154 + info->si_uid = tswap32(tinfo->_sifields._rt._uid);
  155 + info->si_value.sival_ptr =
  156 + (void *)tswapl(tinfo->_sifields._rt._sigval.sival_ptr);
118 } 157 }
119 158
120 void signal_init(void) 159 void signal_init(void)
@@ -122,8 +161,9 @@ void signal_init(void) @@ -122,8 +161,9 @@ void signal_init(void)
122 struct sigaction act; 161 struct sigaction act;
123 int i; 162 int i;
124 163
125 - /* set all host signal handlers */  
126 - sigemptyset(&act.sa_mask); 164 + /* set all host signal handlers. ALL signals are blocked during
  165 + the handlers to serialize them. */
  166 + sigfillset(&act.sa_mask);
127 act.sa_flags = SA_SIGINFO; 167 act.sa_flags = SA_SIGINFO;
128 act.sa_sigaction = host_signal_handler; 168 act.sa_sigaction = host_signal_handler;
129 for(i = 1; i < NSIG; i++) { 169 for(i = 1; i < NSIG; i++) {
@@ -155,56 +195,40 @@ static inline void free_sigqueue(struct sigqueue *q) @@ -155,56 +195,40 @@ static inline void free_sigqueue(struct sigqueue *q)
155 first_free = q; 195 first_free = q;
156 } 196 }
157 197
158 -static int queue_signal(struct emulated_sigaction *k, int sig, siginfo_t *info)  
159 -{  
160 - struct sigqueue *q, **pq;  
161 -  
162 - pq = &k->first;  
163 - if (!k->pending || sig < TARGET_SIGRTMIN) {  
164 - /* first signal or non real time signal */  
165 - q = &k->info;  
166 - } else {  
167 - q = alloc_sigqueue();  
168 - if (!q)  
169 - return -EAGAIN;  
170 - while (*pq != NULL)  
171 - pq = &(*pq)->next;  
172 - }  
173 - *pq = q;  
174 - q->info = *info;  
175 - q->next = NULL;  
176 - k->pending = 1;  
177 - /* signal that a new signal is pending */  
178 - signal_pending = 1;  
179 - return 0;  
180 -}  
181 -  
182 -void force_sig(int sig) 198 +/* abort execution with signal */
  199 +void __attribute((noreturn)) force_sig(int sig)
183 { 200 {
184 int host_sig; 201 int host_sig;
185 - /* abort execution with signal */  
186 host_sig = target_to_host_signal(sig); 202 host_sig = target_to_host_signal(sig);
187 fprintf(stderr, "gemu: uncaught target signal %d (%s) - exiting\n", 203 fprintf(stderr, "gemu: uncaught target signal %d (%s) - exiting\n",
188 sig, strsignal(host_sig)); 204 sig, strsignal(host_sig));
  205 +#if 1
189 _exit(-host_sig); 206 _exit(-host_sig);
  207 +#else
  208 + {
  209 + struct sigaction act;
  210 + sigemptyset(&act.sa_mask);
  211 + act.sa_flags = SA_SIGINFO;
  212 + act.sa_sigaction = SIG_DFL;
  213 + sigaction(SIGABRT, &act, NULL);
  214 + abort();
  215 + }
  216 +#endif
190 } 217 }
191 218
192 -  
193 -static void host_signal_handler(int host_signum, siginfo_t *info,  
194 - void *puc) 219 +/* queue a signal so that it will be send to the virtual CPU as soon
  220 + as possible */
  221 +int queue_signal(int sig, target_siginfo_t *info)
195 { 222 {
196 struct emulated_sigaction *k; 223 struct emulated_sigaction *k;
197 - int sig; 224 + struct sigqueue *q, **pq;
198 target_ulong handler; 225 target_ulong handler;
199 226
200 - /* get target signal number */  
201 - sig = host_to_target_signal(host_signum);  
202 - if (sig < 1 || sig > TARGET_NSIG)  
203 - return;  
204 - k = &sigact_table[sig - 1];  
205 -#ifdef DEBUG_SIGNAL  
206 - fprintf(stderr, "gemu: got signal %d\n", sig); 227 +#if defined(DEBUG_SIGNAL)
  228 + fprintf(stderr, "queue_sigal: sig=%d\n",
  229 + sig);
207 #endif 230 #endif
  231 + k = &sigact_table[sig - 1];
208 handler = k->sa._sa_handler; 232 handler = k->sa._sa_handler;
209 if (handler == TARGET_SIG_DFL) { 233 if (handler == TARGET_SIG_DFL) {
210 /* default handler : ignore some signal. The other are fatal */ 234 /* default handler : ignore some signal. The other are fatal */
@@ -212,13 +236,96 @@ static void host_signal_handler(int host_signum, siginfo_t *info, @@ -212,13 +236,96 @@ static void host_signal_handler(int host_signum, siginfo_t *info,
212 sig != TARGET_SIGURG && 236 sig != TARGET_SIGURG &&
213 sig != TARGET_SIGWINCH) { 237 sig != TARGET_SIGWINCH) {
214 force_sig(sig); 238 force_sig(sig);
  239 + } else {
  240 + return 0; /* indicate ignored */
215 } 241 }
216 } else if (handler == TARGET_SIG_IGN) { 242 } else if (handler == TARGET_SIG_IGN) {
217 /* ignore signal */ 243 /* ignore signal */
  244 + return 0;
218 } else if (handler == TARGET_SIG_ERR) { 245 } else if (handler == TARGET_SIG_ERR) {
219 force_sig(sig); 246 force_sig(sig);
220 } else { 247 } else {
221 - queue_signal(k, sig, info); 248 + pq = &k->first;
  249 + if (sig < TARGET_SIGRTMIN) {
  250 + /* if non real time signal, we queue exactly one signal */
  251 + if (!k->pending)
  252 + q = &k->info;
  253 + else
  254 + return 0;
  255 + } else {
  256 + if (!k->pending) {
  257 + /* first signal */
  258 + q = &k->info;
  259 + } else {
  260 + q = alloc_sigqueue();
  261 + if (!q)
  262 + return -EAGAIN;
  263 + while (*pq != NULL)
  264 + pq = &(*pq)->next;
  265 + }
  266 + }
  267 + *pq = q;
  268 + q->info = *info;
  269 + q->next = NULL;
  270 + k->pending = 1;
  271 + /* signal that a new signal is pending */
  272 + signal_pending = 1;
  273 + return 1; /* indicates that the signal was queued */
  274 + }
  275 +}
  276 +
  277 +#if defined(DEBUG_SIGNAL)
  278 +#ifdef __i386__
  279 +static void dump_regs(struct ucontext *uc)
  280 +{
  281 + fprintf(stderr,
  282 + "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
  283 + "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
  284 + "EFL=%08x EIP=%08x\n",
  285 + uc->uc_mcontext.gregs[EAX],
  286 + uc->uc_mcontext.gregs[EBX],
  287 + uc->uc_mcontext.gregs[ECX],
  288 + uc->uc_mcontext.gregs[EDX],
  289 + uc->uc_mcontext.gregs[ESI],
  290 + uc->uc_mcontext.gregs[EDI],
  291 + uc->uc_mcontext.gregs[EBP],
  292 + uc->uc_mcontext.gregs[ESP],
  293 + uc->uc_mcontext.gregs[EFL],
  294 + uc->uc_mcontext.gregs[EIP]);
  295 +}
  296 +#else
  297 +static void dump_regs(struct ucontext *uc)
  298 +{
  299 +}
  300 +#endif
  301 +
  302 +#endif
  303 +
  304 +static void host_signal_handler(int host_signum, siginfo_t *info,
  305 + void *puc)
  306 +{
  307 + int sig;
  308 + target_siginfo_t tinfo;
  309 +
  310 + /* the CPU emulator uses some host signals to detect exceptions,
  311 + we we forward to it some signals */
  312 + if (host_signum == SIGSEGV || host_signum == SIGBUS) {
  313 + if (cpu_x86_signal_handler(host_signum, info, puc))
  314 + return;
  315 + }
  316 +
  317 + /* get target signal number */
  318 + sig = host_to_target_signal(host_signum);
  319 + if (sig < 1 || sig > TARGET_NSIG)
  320 + return;
  321 +#if defined(DEBUG_SIGNAL)
  322 + fprintf(stderr, "gemu: got signal %d\n", sig);
  323 + dump_regs(puc);
  324 +#endif
  325 + host_to_target_siginfo_noswap(&tinfo, info);
  326 + if (queue_signal(sig, &tinfo) == 1) {
  327 + /* interrupt the virtual CPU as soon as possible */
  328 + cpu_x86_interrupt(global_env);
222 } 329 }
223 } 330 }
224 331
@@ -388,9 +495,10 @@ struct rt_sigframe @@ -388,9 +495,10 @@ struct rt_sigframe
388 0;\ 495 0;\
389 }) 496 })
390 497
391 -static inline int copy_siginfo_to_user(target_siginfo_t *tinfo, siginfo_t *info) 498 +static inline int copy_siginfo_to_user(target_siginfo_t *tinfo,
  499 + const target_siginfo_t *info)
392 { 500 {
393 - host_to_target_siginfo(tinfo, info); 501 + tswap_siginfo(tinfo, info);
394 return 0; 502 return 0;
395 } 503 }
396 504
@@ -531,7 +639,8 @@ give_sigsegv: @@ -531,7 +639,8 @@ give_sigsegv:
531 force_sig(TARGET_SIGSEGV /* , current */); 639 force_sig(TARGET_SIGSEGV /* , current */);
532 } 640 }
533 641
534 -static void setup_rt_frame(int sig, struct emulated_sigaction *ka, siginfo_t *info, 642 +static void setup_rt_frame(int sig, struct emulated_sigaction *ka,
  643 + target_siginfo_t *info,
535 target_sigset_t *set, CPUX86State *env) 644 target_sigset_t *set, CPUX86State *env)
536 { 645 {
537 struct rt_sigframe *frame; 646 struct rt_sigframe *frame;
@@ -734,7 +843,8 @@ void process_pending_signals(void *cpu_env) @@ -734,7 +843,8 @@ void process_pending_signals(void *cpu_env)
734 { 843 {
735 int sig; 844 int sig;
736 target_ulong handler; 845 target_ulong handler;
737 - target_sigset_t set; 846 + sigset_t set, old_set;
  847 + target_sigset_t target_old_set;
738 struct emulated_sigaction *k; 848 struct emulated_sigaction *k;
739 struct sigqueue *q; 849 struct sigqueue *q;
740 850
@@ -774,12 +884,24 @@ void process_pending_signals(void *cpu_env) @@ -774,12 +884,24 @@ void process_pending_signals(void *cpu_env)
774 } else if (handler == TARGET_SIG_ERR) { 884 } else if (handler == TARGET_SIG_ERR) {
775 force_sig(sig); 885 force_sig(sig);
776 } else { 886 } else {
777 - set = k->sa.sa_mask;  
778 - /* send the signal to the CPU */ 887 + /* compute the blocked signals during the handler execution */
  888 + target_to_host_sigset(&set, &k->sa.sa_mask);
  889 + /* SA_NODEFER indicates that the current signal should not be
  890 + blocked during the handler */
  891 + if (!(k->sa.sa_flags & TARGET_SA_NODEFER))
  892 + sigaddset(&set, target_to_host_signal(sig));
  893 +
  894 + /* block signals in the handler using Linux */
  895 + sigprocmask(SIG_BLOCK, &set, &old_set);
  896 + /* save the previous blocked signal state to restore it at the
  897 + end of the signal execution (see do_sigreturn) */
  898 + host_to_target_sigset(&target_old_set, &old_set);
  899 +
  900 + /* prepare the stack frame of the virtual CPU */
779 if (k->sa.sa_flags & TARGET_SA_SIGINFO) 901 if (k->sa.sa_flags & TARGET_SA_SIGINFO)
780 - setup_rt_frame(sig, k, &q->info, &set, cpu_env); 902 + setup_rt_frame(sig, k, &q->info, &target_old_set, cpu_env);
781 else 903 else
782 - setup_frame(sig, k, &set, cpu_env); 904 + setup_frame(sig, k, &target_old_set, cpu_env);
783 if (k->sa.sa_flags & TARGET_SA_RESETHAND) 905 if (k->sa.sa_flags & TARGET_SA_RESETHAND)
784 k->sa._sa_handler = TARGET_SIG_DFL; 906 k->sa._sa_handler = TARGET_SIG_DFL;
785 } 907 }
linux-user/syscall.c
@@ -38,6 +38,7 @@ @@ -38,6 +38,7 @@
38 #include <sched.h> 38 #include <sched.h>
39 #include <sys/socket.h> 39 #include <sys/socket.h>
40 #include <sys/uio.h> 40 #include <sys/uio.h>
  41 +#include <sys/poll.h>
41 //#include <sys/user.h> 42 //#include <sys/user.h>
42 43
43 #define termios host_termios 44 #define termios host_termios
@@ -68,15 +69,8 @@ @@ -68,15 +69,8 @@
68 #define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2]) 69 #define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2])
69 #define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct dirent [2]) 70 #define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct dirent [2])
70 71
71 -#include "syscall_defs.h"  
72 -  
73 -#ifdef TARGET_I386  
74 -#include "cpu-i386.h"  
75 -#include "syscall-i386.h"  
76 -#endif  
77 -  
78 -void host_to_target_siginfo(target_siginfo_t *tinfo, siginfo_t *info);  
79 -void target_to_host_siginfo(siginfo_t *info, target_siginfo_t *tinfo); 72 +void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info);
  73 +void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo);
80 long do_sigreturn(CPUX86State *env); 74 long do_sigreturn(CPUX86State *env);
81 long do_rt_sigreturn(CPUX86State *env); 75 long do_rt_sigreturn(CPUX86State *env);
82 76
@@ -106,6 +100,9 @@ _syscall2(int,sys_fstatfs,int,fd,struct kernel_statfs *,buf) @@ -106,6 +100,9 @@ _syscall2(int,sys_fstatfs,int,fd,struct kernel_statfs *,buf)
106 _syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo) 100 _syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
107 101
108 extern int personality(int); 102 extern int personality(int);
  103 +extern int flock(int, int);
  104 +extern int setfsuid(int);
  105 +extern int setfsgid(int);
109 106
110 static inline long get_errno(long ret) 107 static inline long get_errno(long ret)
111 { 108 {
@@ -437,7 +434,7 @@ static long do_ioctl(long fd, long cmd, long arg) @@ -437,7 +434,7 @@ static long do_ioctl(long fd, long cmd, long arg)
437 ie++; 434 ie++;
438 } 435 }
439 arg_type = ie->arg_type; 436 arg_type = ie->arg_type;
440 -#ifdef DEBUG 437 +#if defined(DEBUG)
441 gemu_log("ioctl: cmd=0x%04lx (%s)\n", cmd, ie->name); 438 gemu_log("ioctl: cmd=0x%04lx (%s)\n", cmd, ie->name);
442 #endif 439 #endif
443 switch(arg_type[0]) { 440 switch(arg_type[0]) {
@@ -1244,9 +1241,30 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, @@ -1244,9 +1241,30 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
1244 ret = get_errno(sethostname((const char *)arg1, arg2)); 1241 ret = get_errno(sethostname((const char *)arg1, arg2));
1245 break; 1242 break;
1246 case TARGET_NR_setrlimit: 1243 case TARGET_NR_setrlimit:
1247 - goto unimplemented; 1244 + {
  1245 + /* XXX: convert resource ? */
  1246 + int resource = arg1;
  1247 + struct target_rlimit *target_rlim = (void *)arg2;
  1248 + struct rlimit rlim;
  1249 + rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
  1250 + rlim.rlim_max = tswapl(target_rlim->rlim_max);
  1251 + ret = get_errno(setrlimit(resource, &rlim));
  1252 + }
  1253 + break;
1248 case TARGET_NR_getrlimit: 1254 case TARGET_NR_getrlimit:
1249 - goto unimplemented; 1255 + {
  1256 + /* XXX: convert resource ? */
  1257 + int resource = arg1;
  1258 + struct target_rlimit *target_rlim = (void *)arg2;
  1259 + struct rlimit rlim;
  1260 +
  1261 + ret = get_errno(getrlimit(resource, &rlim));
  1262 + if (!is_error(ret)) {
  1263 + target_rlim->rlim_cur = tswapl(rlim.rlim_cur);
  1264 + target_rlim->rlim_max = tswapl(rlim.rlim_max);
  1265 + }
  1266 + }
  1267 + break;
1250 case TARGET_NR_getrusage: 1268 case TARGET_NR_getrusage:
1251 goto unimplemented; 1269 goto unimplemented;
1252 case TARGET_NR_gettimeofday: 1270 case TARGET_NR_gettimeofday:
@@ -1317,6 +1335,27 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, @@ -1317,6 +1335,27 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
1317 case TARGET_NR_munmap: 1335 case TARGET_NR_munmap:
1318 ret = get_errno(munmap((void *)arg1, arg2)); 1336 ret = get_errno(munmap((void *)arg1, arg2));
1319 break; 1337 break;
  1338 + case TARGET_NR_mprotect:
  1339 + ret = get_errno(mprotect((void *)arg1, arg2, arg3));
  1340 + break;
  1341 + case TARGET_NR_mremap:
  1342 + ret = get_errno((long)mremap((void *)arg1, arg2, arg3, arg4));
  1343 + break;
  1344 + case TARGET_NR_msync:
  1345 + ret = get_errno(msync((void *)arg1, arg2, arg3));
  1346 + break;
  1347 + case TARGET_NR_mlock:
  1348 + ret = get_errno(mlock((void *)arg1, arg2));
  1349 + break;
  1350 + case TARGET_NR_munlock:
  1351 + ret = get_errno(munlock((void *)arg1, arg2));
  1352 + break;
  1353 + case TARGET_NR_mlockall:
  1354 + ret = get_errno(mlockall(arg1));
  1355 + break;
  1356 + case TARGET_NR_munlockall:
  1357 + ret = get_errno(munlockall());
  1358 + break;
1320 case TARGET_NR_truncate: 1359 case TARGET_NR_truncate:
1321 ret = get_errno(truncate((const char *)arg1, arg2)); 1360 ret = get_errno(truncate((const char *)arg1, arg2));
1322 break; 1361 break;
@@ -1506,9 +1545,6 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, @@ -1506,9 +1545,6 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
1506 #endif 1545 #endif
1507 case TARGET_NR_adjtimex: 1546 case TARGET_NR_adjtimex:
1508 goto unimplemented; 1547 goto unimplemented;
1509 - case TARGET_NR_mprotect:  
1510 - ret = get_errno(mprotect((void *)arg1, arg2, arg3));  
1511 - break;  
1512 case TARGET_NR_create_module: 1548 case TARGET_NR_create_module:
1513 case TARGET_NR_init_module: 1549 case TARGET_NR_init_module:
1514 case TARGET_NR_delete_module: 1550 case TARGET_NR_delete_module:
@@ -1532,9 +1568,11 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, @@ -1532,9 +1568,11 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
1532 case TARGET_NR_afs_syscall: 1568 case TARGET_NR_afs_syscall:
1533 goto unimplemented; 1569 goto unimplemented;
1534 case TARGET_NR_setfsuid: 1570 case TARGET_NR_setfsuid:
1535 - goto unimplemented; 1571 + ret = get_errno(setfsuid(arg1));
  1572 + break;
1536 case TARGET_NR_setfsgid: 1573 case TARGET_NR_setfsgid:
1537 - goto unimplemented; 1574 + ret = get_errno(setfsgid(arg1));
  1575 + break;
1538 case TARGET_NR__llseek: 1576 case TARGET_NR__llseek:
1539 { 1577 {
1540 int64_t res; 1578 int64_t res;
@@ -1596,10 +1634,31 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, @@ -1596,10 +1634,31 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
1596 ret = do_select(arg1, (void *)arg2, (void *)arg3, (void *)arg4, 1634 ret = do_select(arg1, (void *)arg2, (void *)arg3, (void *)arg4,
1597 (void *)arg5); 1635 (void *)arg5);
1598 break; 1636 break;
  1637 + case TARGET_NR_poll:
  1638 + {
  1639 + struct target_pollfd *target_pfd = (void *)arg1;
  1640 + unsigned int nfds = arg2;
  1641 + int timeout = arg3;
  1642 + struct pollfd *pfd;
  1643 + int i;
  1644 +
  1645 + pfd = alloca(sizeof(struct pollfd) * nfds);
  1646 + for(i = 0; i < nfds; i++) {
  1647 + pfd->fd = tswap32(target_pfd->fd);
  1648 + pfd->events = tswap16(target_pfd->events);
  1649 + }
  1650 + ret = get_errno(poll(pfd, nfds, timeout));
  1651 + if (!is_error(ret)) {
  1652 + for(i = 0; i < nfds; i++) {
  1653 + target_pfd->revents = tswap16(pfd->revents);
  1654 + }
  1655 + }
  1656 + }
  1657 + break;
1599 case TARGET_NR_flock: 1658 case TARGET_NR_flock:
1600 - goto unimplemented;  
1601 - case TARGET_NR_msync:  
1602 - ret = get_errno(msync((void *)arg1, arg2, arg3)); 1659 + /* NOTE: the flock constant seems to be the same for every
  1660 + Linux platform */
  1661 + ret = get_errno(flock(arg1, arg2));
1603 break; 1662 break;
1604 case TARGET_NR_readv: 1663 case TARGET_NR_readv:
1605 { 1664 {
@@ -1638,18 +1697,6 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, @@ -1638,18 +1697,6 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
1638 goto unimplemented; 1697 goto unimplemented;
1639 case TARGET_NR__sysctl: 1698 case TARGET_NR__sysctl:
1640 goto unimplemented; 1699 goto unimplemented;
1641 - case TARGET_NR_mlock:  
1642 - ret = get_errno(mlock((void *)arg1, arg2));  
1643 - break;  
1644 - case TARGET_NR_munlock:  
1645 - ret = get_errno(munlock((void *)arg1, arg2));  
1646 - break;  
1647 - case TARGET_NR_mlockall:  
1648 - ret = get_errno(mlockall(arg1));  
1649 - break;  
1650 - case TARGET_NR_munlockall:  
1651 - ret = get_errno(munlockall());  
1652 - break;  
1653 case TARGET_NR_sched_setparam: 1700 case TARGET_NR_sched_setparam:
1654 goto unimplemented; 1701 goto unimplemented;
1655 case TARGET_NR_sched_getparam: 1702 case TARGET_NR_sched_getparam:
@@ -1681,12 +1728,10 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, @@ -1681,12 +1728,10 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
1681 } 1728 }
1682 break; 1729 break;
1683 1730
1684 - case TARGET_NR_mremap:  
1685 case TARGET_NR_setresuid: 1731 case TARGET_NR_setresuid:
1686 case TARGET_NR_getresuid: 1732 case TARGET_NR_getresuid:
1687 case TARGET_NR_vm86: 1733 case TARGET_NR_vm86:
1688 case TARGET_NR_query_module: 1734 case TARGET_NR_query_module:
1689 - case TARGET_NR_poll:  
1690 case TARGET_NR_nfsservctl: 1735 case TARGET_NR_nfsservctl:
1691 case TARGET_NR_setresgid: 1736 case TARGET_NR_setresgid:
1692 case TARGET_NR_getresgid: 1737 case TARGET_NR_getresgid:
@@ -1800,7 +1845,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, @@ -1800,7 +1845,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
1800 goto unimplemented; 1845 goto unimplemented;
1801 default: 1846 default:
1802 unimplemented: 1847 unimplemented:
1803 - gemu_log("Unsupported syscall: %d\n", num); 1848 + gemu_log("gemu: Unsupported syscall: %d\n", num);
1804 ret = -ENOSYS; 1849 ret = -ENOSYS;
1805 break; 1850 break;
1806 } 1851 }
linux-user/syscall_defs.h
@@ -150,6 +150,17 @@ struct target_sigaction; @@ -150,6 +150,17 @@ struct target_sigaction;
150 int do_sigaction(int sig, const struct target_sigaction *act, 150 int do_sigaction(int sig, const struct target_sigaction *act,
151 struct target_sigaction *oact); 151 struct target_sigaction *oact);
152 152
  153 +struct target_rlimit {
  154 + target_ulong rlim_cur;
  155 + target_ulong rlim_max;
  156 +};
  157 +
  158 +struct target_pollfd {
  159 + int fd; /* file descriptor */
  160 + short events; /* requested events */
  161 + short revents; /* returned events */
  162 +};
  163 +
153 /* Networking ioctls */ 164 /* Networking ioctls */
154 #define TARGET_SIOCADDRT 0x890B /* add routing table entry */ 165 #define TARGET_SIOCADDRT 0x890B /* add routing table entry */
155 #define TARGET_SIOCDELRT 0x890C /* delete routing table entry */ 166 #define TARGET_SIOCDELRT 0x890C /* delete routing table entry */
op-i386.c
@@ -119,40 +119,6 @@ static inline int lshift(int x, int n) @@ -119,40 +119,6 @@ static inline int lshift(int x, int n)
119 return x >> (-n); 119 return x >> (-n);
120 } 120 }
121 121
122 -/* exception support */  
123 -/* NOTE: not static to force relocation generation by GCC */  
124 -void raise_exception(int exception_index)  
125 -{  
126 - /* NOTE: the register at this point must be saved by hand because  
127 - longjmp restore them */  
128 -#ifdef reg_EAX  
129 - env->regs[R_EAX] = EAX;  
130 -#endif  
131 -#ifdef reg_ECX  
132 - env->regs[R_ECX] = ECX;  
133 -#endif  
134 -#ifdef reg_EDX  
135 - env->regs[R_EDX] = EDX;  
136 -#endif  
137 -#ifdef reg_EBX  
138 - env->regs[R_EBX] = EBX;  
139 -#endif  
140 -#ifdef reg_ESP  
141 - env->regs[R_ESP] = ESP;  
142 -#endif  
143 -#ifdef reg_EBP  
144 - env->regs[R_EBP] = EBP;  
145 -#endif  
146 -#ifdef reg_ESI  
147 - env->regs[R_ESI] = ESI;  
148 -#endif  
149 -#ifdef reg_EDI  
150 - env->regs[R_EDI] = EDI;  
151 -#endif  
152 - env->exception_index = exception_index;  
153 - longjmp(env->jmp_env, 1);  
154 -}  
155 -  
156 /* we define the various pieces of code used by the JIT */ 122 /* we define the various pieces of code used by the JIT */
157 123
158 #define REG EAX 124 #define REG EAX
@@ -391,13 +357,15 @@ void OPPROTO op_imull_T0_T1(void) @@ -391,13 +357,15 @@ void OPPROTO op_imull_T0_T1(void)
391 } 357 }
392 358
393 /* division, flags are undefined */ 359 /* division, flags are undefined */
394 -/* XXX: add exceptions for overflow & div by zero */ 360 +/* XXX: add exceptions for overflow */
395 void OPPROTO op_divb_AL_T0(void) 361 void OPPROTO op_divb_AL_T0(void)
396 { 362 {
397 unsigned int num, den, q, r; 363 unsigned int num, den, q, r;
398 364
399 num = (EAX & 0xffff); 365 num = (EAX & 0xffff);
400 den = (T0 & 0xff); 366 den = (T0 & 0xff);
  367 + if (den == 0)
  368 + raise_exception(EXCP00_DIVZ);
401 q = (num / den) & 0xff; 369 q = (num / den) & 0xff;
402 r = (num % den) & 0xff; 370 r = (num % den) & 0xff;
403 EAX = (EAX & 0xffff0000) | (r << 8) | q; 371 EAX = (EAX & 0xffff0000) | (r << 8) | q;
@@ -409,6 +377,8 @@ void OPPROTO op_idivb_AL_T0(void) @@ -409,6 +377,8 @@ void OPPROTO op_idivb_AL_T0(void)
409 377
410 num = (int16_t)EAX; 378 num = (int16_t)EAX;
411 den = (int8_t)T0; 379 den = (int8_t)T0;
  380 + if (den == 0)
  381 + raise_exception(EXCP00_DIVZ);
412 q = (num / den) & 0xff; 382 q = (num / den) & 0xff;
413 r = (num % den) & 0xff; 383 r = (num % den) & 0xff;
414 EAX = (EAX & 0xffff0000) | (r << 8) | q; 384 EAX = (EAX & 0xffff0000) | (r << 8) | q;
@@ -420,6 +390,8 @@ void OPPROTO op_divw_AX_T0(void) @@ -420,6 +390,8 @@ void OPPROTO op_divw_AX_T0(void)
420 390
421 num = (EAX & 0xffff) | ((EDX & 0xffff) << 16); 391 num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
422 den = (T0 & 0xffff); 392 den = (T0 & 0xffff);
  393 + if (den == 0)
  394 + raise_exception(EXCP00_DIVZ);
423 q = (num / den) & 0xffff; 395 q = (num / den) & 0xffff;
424 r = (num % den) & 0xffff; 396 r = (num % den) & 0xffff;
425 EAX = (EAX & 0xffff0000) | q; 397 EAX = (EAX & 0xffff0000) | q;
@@ -432,6 +404,8 @@ void OPPROTO op_idivw_AX_T0(void) @@ -432,6 +404,8 @@ void OPPROTO op_idivw_AX_T0(void)
432 404
433 num = (EAX & 0xffff) | ((EDX & 0xffff) << 16); 405 num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
434 den = (int16_t)T0; 406 den = (int16_t)T0;
  407 + if (den == 0)
  408 + raise_exception(EXCP00_DIVZ);
435 q = (num / den) & 0xffff; 409 q = (num / den) & 0xffff;
436 r = (num % den) & 0xffff; 410 r = (num % den) & 0xffff;
437 EAX = (EAX & 0xffff0000) | q; 411 EAX = (EAX & 0xffff0000) | q;
@@ -445,6 +419,8 @@ void OPPROTO op_divl_EAX_T0(void) @@ -445,6 +419,8 @@ void OPPROTO op_divl_EAX_T0(void)
445 419
446 num = EAX | ((uint64_t)EDX << 32); 420 num = EAX | ((uint64_t)EDX << 32);
447 den = T0; 421 den = T0;
  422 + if (den == 0)
  423 + raise_exception(EXCP00_DIVZ);
448 q = (num / den); 424 q = (num / den);
449 r = (num % den); 425 r = (num % den);
450 EAX = q; 426 EAX = q;
@@ -458,6 +434,8 @@ void OPPROTO op_idivl_EAX_T0(void) @@ -458,6 +434,8 @@ void OPPROTO op_idivl_EAX_T0(void)
458 434
459 num = EAX | ((uint64_t)EDX << 32); 435 num = EAX | ((uint64_t)EDX << 32);
460 den = T0; 436 den = T0;
  437 + if (den == 0)
  438 + raise_exception(EXCP00_DIVZ);
461 q = (num / den); 439 q = (num / den);
462 r = (num % den); 440 r = (num % den);
463 EAX = q; 441 EAX = q;
syscall-i386.h
@@ -359,7 +359,7 @@ struct target_sigaction { @@ -359,7 +359,7 @@ struct target_sigaction {
359 359
360 typedef union target_sigval { 360 typedef union target_sigval {
361 int sival_int; 361 int sival_int;
362 - void *sival_ptr; 362 + target_ulong sival_ptr;
363 } target_sigval_t; 363 } target_sigval_t;
364 364
365 #define TARGET_SI_MAX_SIZE 128 365 #define TARGET_SI_MAX_SIZE 128
@@ -389,7 +389,7 @@ typedef struct target_siginfo { @@ -389,7 +389,7 @@ typedef struct target_siginfo {
389 struct { 389 struct {
390 pid_t _pid; /* sender's pid */ 390 pid_t _pid; /* sender's pid */
391 uid_t _uid; /* sender's uid */ 391 uid_t _uid; /* sender's uid */
392 - sigval_t _sigval; 392 + target_sigval_t _sigval;
393 } _rt; 393 } _rt;
394 394
395 /* SIGCHLD */ 395 /* SIGCHLD */
@@ -403,7 +403,7 @@ typedef struct target_siginfo { @@ -403,7 +403,7 @@ typedef struct target_siginfo {
403 403
404 /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */ 404 /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
405 struct { 405 struct {
406 - void *_addr; /* faulting insn/memory ref. */ 406 + target_ulong _addr; /* faulting insn/memory ref. */
407 } _sigfault; 407 } _sigfault;
408 408
409 /* SIGPOLL */ 409 /* SIGPOLL */
@@ -414,6 +414,46 @@ typedef struct target_siginfo { @@ -414,6 +414,46 @@ typedef struct target_siginfo {
414 } _sifields; 414 } _sifields;
415 } target_siginfo_t; 415 } target_siginfo_t;
416 416
  417 +/*
  418 + * SIGILL si_codes
  419 + */
  420 +#define TARGET_ILL_ILLOPN (2) /* illegal operand */
  421 +
  422 +/*
  423 + * SIGFPE si_codes
  424 + */
  425 +#define TARGET_FPE_INTDIV (1) /* integer divide by zero */
  426 +#define TARGET_FPE_INTOVF (2) /* integer overflow */
  427 +#define TARGET_FPE_FLTDIV (3) /* floating point divide by zero */
  428 +#define TARGET_FPE_FLTOVF (4) /* floating point overflow */
  429 +#define TARGET_FPE_FLTUND (5) /* floating point underflow */
  430 +#define TARGET_FPE_FLTRES (6) /* floating point inexact result */
  431 +#define TARGET_FPE_FLTINV (7) /* floating point invalid operation */
  432 +#define TARGET_FPE_FLTSUB (8) /* subscript out of range */
  433 +#define TARGET_NSIGFPE 8
  434 +
  435 +/* default linux values for the selectors */
  436 +#define __USER_CS (0x23)
  437 +#define __USER_DS (0x2B)
  438 +
  439 +struct target_pt_regs {
  440 + long ebx;
  441 + long ecx;
  442 + long edx;
  443 + long esi;
  444 + long edi;
  445 + long ebp;
  446 + long eax;
  447 + int xds;
  448 + int xes;
  449 + long orig_eax;
  450 + long eip;
  451 + int xcs;
  452 + long eflags;
  453 + long esp;
  454 + int xss;
  455 +};
  456 +
417 /* ioctls */ 457 /* ioctls */
418 458
419 /* 459 /*
tests/testsig.c
  1 +#define _GNU_SOURCE
1 #include <stdlib.h> 2 #include <stdlib.h>
2 #include <stdio.h> 3 #include <stdio.h>
  4 +#include <string.h>
3 #include <signal.h> 5 #include <signal.h>
4 #include <unistd.h> 6 #include <unistd.h>
  7 +#include <setjmp.h>
  8 +#include <sys/ucontext.h>
  9 +
  10 +jmp_buf jmp_env;
5 11
6 void alarm_handler(int sig) 12 void alarm_handler(int sig)
7 { 13 {
@@ -9,15 +15,82 @@ void alarm_handler(int sig) @@ -9,15 +15,82 @@ void alarm_handler(int sig)
9 alarm(1); 15 alarm(1);
10 } 16 }
11 17
  18 +void dump_regs(struct ucontext *uc)
  19 +{
  20 + printf("EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
  21 + "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
  22 + "EFL=%08x EIP=%08x\n",
  23 + uc->uc_mcontext.gregs[EAX],
  24 + uc->uc_mcontext.gregs[EBX],
  25 + uc->uc_mcontext.gregs[ECX],
  26 + uc->uc_mcontext.gregs[EDX],
  27 + uc->uc_mcontext.gregs[ESI],
  28 + uc->uc_mcontext.gregs[EDI],
  29 + uc->uc_mcontext.gregs[EBP],
  30 + uc->uc_mcontext.gregs[ESP],
  31 + uc->uc_mcontext.gregs[EFL],
  32 + uc->uc_mcontext.gregs[EIP]);
  33 +}
  34 +
  35 +void sig_handler(int sig, siginfo_t *info, void *puc)
  36 +{
  37 + struct ucontext *uc = puc;
  38 +
  39 + printf("%s: si_signo=%d si_errno=%d si_code=%d si_addr=0x%08lx\n",
  40 + strsignal(info->si_signo),
  41 + info->si_signo, info->si_errno, info->si_code,
  42 + (unsigned long)info->si_addr);
  43 + dump_regs(uc);
  44 + longjmp(jmp_env, 1);
  45 +}
  46 +
  47 +int v1;
  48 +
12 int main(int argc, char **argv) 49 int main(int argc, char **argv)
13 { 50 {
14 struct sigaction act; 51 struct sigaction act;
  52 + int i;
  53 +
  54 + /* test division by zero reporting */
  55 + if (setjmp(jmp_env) == 0) {
  56 + act.sa_sigaction = sig_handler;
  57 + sigemptyset(&act.sa_mask);
  58 + act.sa_flags = SA_SIGINFO | SA_ONESHOT;
  59 + sigaction(SIGFPE, &act, NULL);
  60 +
  61 + /* now divide by zero */
  62 + v1 = 0;
  63 + v1 = 2 / v1;
  64 + }
  65 +
  66 + /* test illegal instruction reporting */
  67 + if (setjmp(jmp_env) == 0) {
  68 + act.sa_sigaction = sig_handler;
  69 + sigemptyset(&act.sa_mask);
  70 + act.sa_flags = SA_SIGINFO | SA_ONESHOT;
  71 + sigaction(SIGILL, &act, NULL);
  72 +
  73 + /* now execute an invalid instruction */
  74 + asm volatile("ud2");
  75 + }
  76 +
  77 + /* test SEGV reporting */
  78 + if (setjmp(jmp_env) == 0) {
  79 + act.sa_sigaction = sig_handler;
  80 + sigemptyset(&act.sa_mask);
  81 + act.sa_flags = SA_SIGINFO | SA_ONESHOT;
  82 + sigaction(SIGSEGV, &act, NULL);
  83 +
  84 + /* now store in an invalid address */
  85 + *(char *)0x1234 = 1;
  86 + }
  87 +
15 act.sa_handler = alarm_handler; 88 act.sa_handler = alarm_handler;
16 sigemptyset(&act.sa_mask); 89 sigemptyset(&act.sa_mask);
17 act.sa_flags = 0; 90 act.sa_flags = 0;
18 sigaction(SIGALRM, &act, NULL); 91 sigaction(SIGALRM, &act, NULL);
19 alarm(1); 92 alarm(1);
20 - for(;;) { 93 + for(i = 0;i < 2; i++) {
21 sleep(1); 94 sleep(1);
22 } 95 }
23 return 0; 96 return 0;
translate-i386.c
@@ -22,6 +22,7 @@ @@ -22,6 +22,7 @@
22 #include <stdio.h> 22 #include <stdio.h>
23 #include <string.h> 23 #include <string.h>
24 #include <inttypes.h> 24 #include <inttypes.h>
  25 +#include <signal.h>
25 #include <assert.h> 26 #include <assert.h>
26 27
27 #define DEBUG_DISAS 28 #define DEBUG_DISAS
@@ -3487,7 +3488,8 @@ static void dump_ops(const uint16_t *opc_buf) @@ -3487,7 +3488,8 @@ static void dump_ops(const uint16_t *opc_buf)
3487 static uint16_t gen_opc_buf[OPC_BUF_SIZE]; 3488 static uint16_t gen_opc_buf[OPC_BUF_SIZE];
3488 static uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE]; 3489 static uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE];
3489 3490
3490 -/* return the next pc */ 3491 +/* return non zero if the very first instruction is invalid so that
  3492 + the virtual CPU can trigger an exception. */
3491 int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, 3493 int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size,
3492 int *gen_code_size_ptr, 3494 int *gen_code_size_ptr,
3493 uint8_t *pc_start, uint8_t *cs_base, int flags) 3495 uint8_t *pc_start, uint8_t *cs_base, int flags)
@@ -3519,9 +3521,13 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, @@ -3519,9 +3521,13 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size,
3519 do { 3521 do {
3520 ret = disas_insn(dc, pc_ptr); 3522 ret = disas_insn(dc, pc_ptr);
3521 if (ret == -1) { 3523 if (ret == -1) {
3522 - fprintf(stderr, "unknown instruction at PC=0x%08lx B=%02x %02x %02x",  
3523 - (long)pc_ptr, pc_ptr[0], pc_ptr[1], pc_ptr[2]);  
3524 - abort(); 3524 + /* we trigger an illegal instruction operation only if it
  3525 + is the first instruction. Otherwise, we simply stop
  3526 + generating the code just before it */
  3527 + if (pc_ptr == pc_start)
  3528 + return -1;
  3529 + else
  3530 + break;
3525 } 3531 }
3526 pc_ptr = (void *)ret; 3532 pc_ptr = (void *)ret;
3527 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end); 3533 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end);
@@ -3640,8 +3646,7 @@ CPUX86State *cpu_x86_init(void) @@ -3640,8 +3646,7 @@ CPUX86State *cpu_x86_init(void)
3640 env->fptags[i] = 1; 3646 env->fptags[i] = 1;
3641 env->fpuc = 0x37f; 3647 env->fpuc = 0x37f;
3642 /* flags setup */ 3648 /* flags setup */
3643 - env->cc_op = CC_OP_EFLAGS;  
3644 - env->df = 1; 3649 + env->eflags = 0;
3645 3650
3646 /* init various static tables */ 3651 /* init various static tables */
3647 if (!inited) { 3652 if (!inited) {