|
From: Eric P. <eri...@wa...> - 2006-02-07 20:56:36
|
Julian Seward wrote: > Eric > Uh ... where did you post these, exactly? Can you send a URL ? http://bugs.kde.org/show_bug.cgi?id=120728 http://bugs.kde.org/show_bug.cgi?id=120732 >>What doesn't currently work in valgrind is changing the EIP in the >>sigcontext. Current implementation of restore_sigcontext() in >>coregrind/m_sigframe/sigframe-x86-linux.c doesn't restore EIP into VEX: >>when we return from the signal handler, execution resumes at the opcode >>with first generated the signal. Back to square one :-/ > > > Sun's JVM also does nasty tricks like this, and I think Tom Hughes > got the same bad-opcode result when he tried restoring EIP into vex. > I would like to fix it for Java folks too. > > > >>I simply tried to set EIP back in the restore_sigcontext() function, but >>this leads to a crash in IR (about unsupported opcode). > > > Hmm. Doing that works OK at least for my simple test program > on SuSE 10 (x86): > yup, your 'simple' test program works I slightly changed your test program, to something that's closer to what we do in Wine... and it doesn't work under VG :-( I left in the test code for both forms for linux signal handlers (< 2.2 and >= 2.1.48), and both fail identically however the error I get is not the as the one with real Wine (but the test framework is not the same either) #include <string.h> #include <stdio.h> #include <stdlib.h> #include <signal.h> #include <assert.h> #include <setjmp.h> #include "valgrind/memcheck.h" #define __USE_GNU #include <sys/ucontext.h> jmp_buf my_je; void diversion( int i, char* ptr ) { printf("diversion %d %s!\n", i, ptr); longjmp(my_je, i); } typedef struct { unsigned short sc_gs, __gsh; unsigned short sc_fs, __fsh; unsigned short sc_es, __esh; unsigned short sc_ds, __dsh; unsigned long sc_edi; unsigned long sc_esi; unsigned long sc_ebp; unsigned long sc_esp; unsigned long sc_ebx; unsigned long sc_edx; unsigned long sc_ecx; unsigned long sc_eax; unsigned long sc_trapno; unsigned long sc_err; unsigned long sc_eip; unsigned short sc_cs, __csh; unsigned long sc_eflags; unsigned long esp_at_signal; unsigned short sc_ss, __ssh; unsigned long i387; unsigned long oldmask; unsigned long cr2; } volatile SIGCONTEXT; struct stack_layout { void *ret_addr; int i; char *str; char buf[16]; unsigned long ebp; unsigned long eip; } *stack; void handler_old ( int signo, SIGCONTEXT __context ) { printf("in handler2, setting EIP to %p\n", (void*)&diversion); stack = (struct stack_layout*)__context.sc_esp; stack--; /* push the stack_layout structure */ VALGRIND_MAKE_WRITABLE(stack, sizeof(*stack)); stack->ret_addr = (void *)0xdeadbabe; /* raise_func must not return */ /* setting this to a reasonable value doesn't help stack->ret_addr = (unsigned long)&diversion; */ stack->i = 12; stack->str = stack->buf; strcpy(stack->buf, "foo-bar"); __context.sc_eip = (unsigned long)&diversion; __context.sc_esp = (unsigned long)stack; } void handler_new( int signo, siginfo_t* xx, void* uc) { ucontext_t* ctx = (ucontext_t*)uc; printf("in handler2, setting EIP to %p\n", (void*)&diversion); stack = (struct stack_layout*)ctx->uc_mcontext.gregs[REG_ESP]; stack--; /* push the stack_layout structure */ VALGRIND_MAKE_WRITABLE(stack, sizeof(*stack)); stack->ret_addr = (void *)0xdeadbabe; /* raise_func must not return */ /* setting this to a reasonable value doesn't help stack->ret_addr = (unsigned long)&diversion; */ stack->i = 12; stack->str = stack->buf; strcpy(stack->buf, "foo-bar"); ctx->uc_mcontext.gregs[REG_EIP] = (unsigned long)&diversion; ctx->uc_mcontext.gregs[REG_ESP] = (unsigned long)stack; } int main ( void ) { int r; struct sigaction act; memset(&act, 0, sizeof(act)); #if 0 act.sa_handler = (void (*)())handler_old; act.sa_flags = SA_RESTART | SA_ONSTACK; #else act.sa_sigaction = (void (*)())handler_new; act.sa_flags = SA_RESTART | SA_ONSTACK | SA_SIGINFO; #endif sigemptyset(&act.sa_mask); r = sigaction(SIGSEGV, &act, NULL); assert(r == 0); if ((r = setjmp(my_je)) == 0) { printf("before\n"); *(int*)1 = 1; } printf("after %d\n", r); return 0; } -- Eric Pouech |