From owner-p4-projects@FreeBSD.ORG Tue Aug 25 17:54:00 2009 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 6BDB5106568F; Tue, 25 Aug 2009 17:54:00 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 3010B106568D for ; Tue, 25 Aug 2009 17:54:00 +0000 (UTC) (envelope-from stas@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 1E01D8FC29 for ; Tue, 25 Aug 2009 17:54:00 +0000 (UTC) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id n7PHs0g9092995 for ; Tue, 25 Aug 2009 17:54:00 GMT (envelope-from stas@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id n7PHs0kE092993 for perforce@freebsd.org; Tue, 25 Aug 2009 17:54:00 GMT (envelope-from stas@freebsd.org) Date: Tue, 25 Aug 2009 17:54:00 GMT Message-Id: <200908251754.n7PHs0kE092993@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to stas@freebsd.org using -f From: Stanislav Sedov To: Perforce Change Reviews Cc: Subject: PERFORCE change 167794 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 25 Aug 2009 17:54:00 -0000 http://perforce.freebsd.org/chv.cgi?CH=167794 Change 167794 by stas@stas_yandex on 2009/08/25 17:53:23 - Signal related improvements. Affected files ... .. //depot/projects/valgrind/coregrind/m_sigframe/sigframe-amd64-freebsd.c#6 edit .. //depot/projects/valgrind/coregrind/m_syswrap/syswrap-amd64-freebsd.c#12 edit .. //depot/projects/valgrind/coregrind/pub_core_sigframe.h#5 edit Differences ... ==== //depot/projects/valgrind/coregrind/m_sigframe/sigframe-amd64-freebsd.c#6 (text+ko) ==== @@ -31,8 +31,6 @@ #if defined(VGP_amd64_freebsd) -#warning Needs love! - #include "pub_core_basics.h" #include "pub_core_vki.h" #include "pub_core_threadstate.h" @@ -49,15 +47,6 @@ /* This module creates and removes signal frames for signal deliveries on amd64-freebsd. - - FIXME: sigcontexting is basically broken for the moment. When - delivering a signal, the integer registers and %rflags are - correctly written into the sigcontext, however the FP and SSE state - is not. When returning from a signal, only the integer registers - are restored from the sigcontext; the rest of the CPU state is - restored to what it was before the signal. - - This should be fixed. */ @@ -103,13 +92,33 @@ UInt magicE; }; +struct sigframe +{ + /* Sig handler's return address */ + Addr retaddr; + + Int sigNo; + Addr psigInfo; /* code or pointer to sigContext */ + Addr puContext; /* points to uContext */ + Addr addr; /* "secret" 4th argument */ + Addr phandler; /* "action" or "handler" */ + + /* pointed to by puContext */ + struct vki_ucontext uContext; + + vki_siginfo_t sigInfo; + + struct _vki_fpstate fpstate; + + struct vg_sigframe vg; +}; + /*------------------------------------------------------------*/ /*--- Creating signal frames ---*/ /*------------------------------------------------------------*/ /* Create a plausible-looking sigcontext from the thread's - Vex guest state. NOTE: does not fill in the FP or SSE - bits of sigcontext at the moment. + Vex guest state. */ static void synth_ucontext(ThreadId tid, const vki_siginfo_t *si, @@ -127,8 +136,6 @@ uc->uc_stack = tst->altstack; VG_(memcpy)(&sc->fpstate, fpstate, sizeof(*fpstate)); - // FIXME: save_i387(&tst->arch, fpstate); - # define SC2(reg,REG) sc->reg = tst->arch.vex.guest_##REG SC2(r8,R8); SC2(r9,R9); @@ -146,17 +153,20 @@ SC2(rax,RAX); SC2(rcx,RCX); SC2(rsp,RSP); - +/* + SC2(cs,CS); + SC2(gs,SS); + XXX +*/ SC2(rip,RIP); + sc->addr = (UWord)si->si_addr; + sc->err = err; + sc->fpformat = VKI_FPFMT_NODEV; + sc->len = sizeof(*sc); + sc->ownedfp = VKI_FPOWNED_NONE; sc->rflags = LibVEX_GuestAMD64_get_rflags(&tst->arch.vex); - // FIXME: SC2(cs,CS); - // FIXME: SC2(gs,GS); - // FIXME: SC2(fs,FS); sc->trapno = trapno; - sc->err = err; # undef SC2 - -// sc->cr2 = (UWord)si->_sifields._sigfault._addr; } @@ -224,7 +234,57 @@ frame->magicE = 0x27182818; } +static Addr build_sigframe(ThreadState *tst, + Addr rsp_top_of_frame, + const vki_siginfo_t *siginfo, + const struct vki_ucontext *siguc, + void *handler, UInt flags, + const vki_sigset_t *mask, + void *restorer) +{ + struct sigframe *frame; + Addr rsp = rsp_top_of_frame; + Int sigNo = siginfo->si_signo; + UWord trapno; + UWord err; + + rsp -= sizeof(*frame); + rsp = VG_ROUNDDN(rsp, 16); + frame = (struct sigframe *)rsp; + + if (!extend(tst, rsp, sizeof(*frame))) + return rsp_top_of_frame; + + /* retaddr, siginfo, uContext fields are to be written */ + VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame", + rsp, offsetof(struct sigframe, vg) ); + + frame->sigNo = sigNo; + frame->retaddr = (Addr)&VG_(amd64_freebsd_SUBST_FOR_sigreturn); + if ((flags & VKI_SA_SIGINFO) == 0) + frame->psigInfo = (Addr)siginfo->si_code; + else + frame->psigInfo = (Addr)&frame->sigInfo; + VG_(memcpy)(&frame->sigInfo, siginfo, sizeof(vki_siginfo_t)); + + trapno = siguc->uc_mcontext.trapno; + err = siguc->uc_mcontext.err; + synth_ucontext(tst->tid, siginfo, trapno, err, mask, + &frame->uContext, &frame->fpstate); + + if (sigNo == VKI_SIGILL && siginfo->si_code > 0) + frame->sigInfo.si_addr = (void*)tst->arch.vex.guest_RIP; + + VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid, + rsp, offsetof(struct sigframe, vg) ); + + build_vg_sigframe(&frame->vg, tst, mask, flags, sigNo); + + return rsp; +} + + void VG_(sigframe_create)( ThreadId tid, Addr rsp_top_of_frame, const vki_siginfo_t *siginfo, @@ -234,32 +294,26 @@ const vki_sigset_t *mask, void *restorer ) { -// Addr rsp; -// struct sigframe *frame; -// ThreadState* tst = VG_(get_ThreadState)(tid); -// -// rsp = build_vg_sigframe(frame, tst, mask, flags, -// handler, flags, mask, restorer); -// frame = (struct sigframe *)rsp; -// -// /* Set the thread so it will next run the handler. */ -// /* tst->m_rsp = rsp; also notify the tool we've updated RSP */ -// VG_(set_SP)(tid, rsp); -// VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR, sizeof(Addr)); -// -// //VG_(printf)("handler = %p\n", handler); - // tst->arch.vex.guest_RIP = (Addr) handler; -// tst->arch.vex.guest_RDI = (ULong) siginfo->si_signo; -// tst->arch.vex.guest_RSI = (Addr) &frame->sigInfo; -// tst->arch.vex.guest_RDX = (Addr) &frame->uContext; -// /* This thread needs to be marked runnable, but we leave that the -// caller to do. */ -// -// if (0) -// VG_(printf)("pushed signal frame; %%RSP now = %#lx, " -// "next %%RIP = %#llx, status=%d\n", -// rsp, tst->arch.vex.guest_RIP, tst->status); -I_die_here; + Addr rsp; + struct sigframe *frame; + ThreadState* tst = VG_(get_ThreadState)(tid); + + rsp = build_sigframe(tst, rsp_top_of_frame, siginfo, siguc, handler, + flags, mask, restorer); + frame = (struct sigframe *)rsp; + + /* Set the thread so it will next run the handler. */ + /* tst->m_rsp = rsp; also notify the tool we've updated RSP */ + VG_(set_SP)(tid, rsp); + VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR, sizeof(Addr)); + + //VG_(printf)("handler = %p\n", handler); + tst->arch.vex.guest_RIP = (Addr) handler; + tst->arch.vex.guest_RDI = (ULong) siginfo->si_signo; + tst->arch.vex.guest_RSI = (Addr) &frame->sigInfo; + tst->arch.vex.guest_RDX = (Addr) &frame->uContext; + /* This thread needs to be marked runnable, but we leave that the + caller to do. */ } @@ -296,7 +350,7 @@ static void restore_sigcontext( ThreadState *tst, - struct vki_sigcontext *sc, + struct vki_mcontext *sc, struct _vki_fpstate *fpstate ) { tst->arch.vex.guest_RAX = sc->rax; @@ -315,14 +369,27 @@ tst->arch.vex.guest_R13 = sc->r13; tst->arch.vex.guest_R14 = sc->r14; tst->arch.vex.guest_R15 = sc->r15; -//:: tst->arch.vex.guest_rflags = sc->rflags; +/* + XXX: + tst->arch.vex.guest_rflags = sc->rflags; +*/ tst->arch.vex.guest_RIP = sc->rip; +/* + XXX + tst->arch.vex.guest_CS = sc->cs; + tst->arch.vex.guest_SS = sc->ss; +*/ + VG_(memcpy)(fpstate, &sc->fpstate, sizeof(*fpstate)); +} -//:: tst->arch.vex.guest_CS = sc->cs; -//:: tst->arch.vex.guest_FS = sc->fs; -//:: tst->arch.vex.guest_GS = sc->gs; +static +SizeT restore_sigframe ( ThreadState *tst, + struct sigframe *frame, Int *sigNo ) +{ + if (restore_vg_sigframe(tst, &frame->vg, sigNo)) + restore_sigcontext(tst, &frame->uContext.uc_mcontext, &frame->fpstate); -//:: restore_i387(&tst->arch, fpstate); + return sizeof(*frame); } void VG_(sigframe_destroy)( ThreadId tid ) @@ -337,7 +404,7 @@ /* Correctly reestablish the frame base address. */ rsp = tst->arch.vex.guest_RSP; - size = restore_vg_sigframe(tst, (struct sigframe *)rsp, &sigNo); + size = restore_sigframe(tst, (struct sigframe *)rsp, &sigNo); VG_TRACK( die_mem_stack_signal, rsp - VG_STACK_REDZONE_SZB, size + VG_STACK_REDZONE_SZB ); ==== //depot/projects/valgrind/coregrind/m_syswrap/syswrap-amd64-freebsd.c#12 (text+ko) ==== @@ -1,6 +1,6 @@ /*--------------------------------------------------------------------*/ -/*--- Platform-specific syscalls stuff. syswrap-x86-linux.c ---*/ +/*--- Platform-specific syscalls stuff. syswrap-amd64-freebsd.c ---*/ /*--------------------------------------------------------------------*/ /* @@ -30,16 +30,10 @@ #if defined(VGP_amd64_freebsd) -/* TODO/FIXME jrs 20050207: assignments to the syscall return result - in interrupted_syscall() need to be reviewed. They don't seem - to assign the shadow state. -*/ - #include "pub_core_basics.h" #include "pub_core_vki.h" #include "pub_core_vkiscnums.h" #include "pub_core_threadstate.h" -#include "pub_core_debuginfo.h" // VG_(di_notify_mmap) #include "pub_core_aspacemgr.h" #include "pub_core_debuglog.h" #include "pub_core_libcbase.h" @@ -48,10 +42,9 @@ #include "pub_core_libcproc.h" #include "pub_core_libcsignal.h" #include "pub_core_machine.h" -#include "pub_core_mallocfree.h" #include "pub_core_options.h" #include "pub_core_scheduler.h" -#include "pub_core_sigframe.h" // For VG_(sigframe_destroy)() +#include "pub_core_sigframe.h" #include "pub_core_signals.h" #include "pub_core_syscall.h" #include "pub_core_syswrap.h" @@ -69,7 +62,7 @@ /* Call f(arg1), but first switch stacks, using 'stack' as the new stack, and use 'retaddr' as f's return-to address. Also, clear all - the integer registers before entering f.*/ + the integer registers before entering f. */ __attribute__((noreturn)) void ML_(call_on_new_stack_0_1) ( Addr stack, Addr retaddr, @@ -118,29 +111,12 @@ } /* --------------------------------------------------------------------- - PRE/POST wrappers for x86/Linux-specific syscalls + PRE/POST wrappers for amd64/FreeBSD-specific syscalls ------------------------------------------------------------------ */ #define PRE(name) DEFN_PRE_TEMPLATE(freebsd, name) #define POST(name) DEFN_POST_TEMPLATE(freebsd, name) -#if 0 -struct thr_param { - void (*start_func)(void *); /* thread entry function. */ - void *arg; /* argument for entry function. */ - char *stack_base; /* stack base address. */ - size_t stack_size; /* stack size. */ - char *tls_base; /* tls base address. */ - size_t tls_size; /* tls size. */ - long *child_tid; /* address to store new TID. */ - long *parent_tid; /* parent accesses the new TID here. */ - int flags; /* thread flags. */ - struct rtprio *rtp; /* Real-time scheduling priority */ - void *spare[3]; /* TODO: cpu affinity mask etc. */ -}; -int thr_new(struct thr_param *param, int param_size); -#endif - PRE(sys_thr_new) { static const Bool debug = False; @@ -165,8 +141,8 @@ } VG_(memset)(&tp, 0, sizeof(tp)); VG_(memcpy)(&tp, (void *)ARG1, offsetof(struct vki_thr_param, spare)); - PRE_MEM_WRITE("clone(parent_tidptr)", (Addr)tp.parent_tid, sizeof(long)); - PRE_MEM_WRITE("clone(child_tidptr)", (Addr)tp.child_tid, sizeof(long)); + PRE_MEM_WRITE("thr_new(parent_tidptr)", (Addr)tp.parent_tid, sizeof(long)); + PRE_MEM_WRITE("thr_new(child_tidptr)", (Addr)tp.child_tid, sizeof(long)); VG_(sigfillset)(&blockall); @@ -192,7 +168,7 @@ ctst->arch.vex_shadow1 = ptst->arch.vex_shadow1; ctst->arch.vex_shadow2 = ptst->arch.vex_shadow2; - /* Make sys_clone appear to have returned Success(0) in the + /* Make thr_new appear to have returned Success(0) in the child. */ ctst->arch.vex.guest_RAX = 0; ctst->arch.vex.guest_RDX = 0; @@ -207,8 +183,8 @@ /* Linux has to guess, we don't */ VG_(register_stack)((Addr)tp.stack_base, (Addr)tp.stack_base + tp.stack_size); - /* Assume the clone will succeed, and tell any tool that wants to - know that this thread has come into existence. If the clone + /* Assume the thr_new will succeed, and tell any tool that wants to + know that this thread has come into existence. If the thr_new fails, we'll send out a ll_exit notification for it at the out: label below, to clean up. */ VG_TRACK ( pre_thread_ll_create, tid, ctid ); @@ -223,6 +199,7 @@ /* Set the client state for scheduler to run libthr's trampoline */ ctst->arch.vex.guest_RDI = (Addr)tp.arg; + /* XXX: align on 16-byte boundary? */ ctst->arch.vex.guest_RSP = (Addr)tp.stack_base + tp.stack_size - 8; ctst->arch.vex.guest_RIP = (Addr)tp.start_func; @@ -232,6 +209,10 @@ /* And valgrind's trampoline on its own stack */ stk = ML_(allocstack)(ctid); + if (stk == (Addr)NULL) { + res = VG_(mk_SysRes_Error)( VKI_ENOMEM ); + goto fail; + } tp.stack_base = (void *)ctst->os_state.valgrind_stack_base; tp.stack_size = (Addr)stk - (Addr)tp.stack_base; @@ -240,8 +221,9 @@ VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL); +fail: if (sr_isError(res)) { - /* clone failed */ + /* thr_new failed */ VG_(cleanup_thread)(&ctst->arch); ctst->status = VgTs_Empty; /* oops. Better tell the tool the thread exited in a hurry :-) */ @@ -284,13 +266,12 @@ /* Adjust esp to point to start of frame; skip back up over handler ret addr */ tst = VG_(get_ThreadState)(tid); - tst->arch.vex.guest_RSP -= sizeof(Addr); /* QQQ should be redundant */ + tst->arch.vex.guest_RSP -= sizeof(Addr); /* This is only so that the EIP is (might be) useful to report if something goes wrong in the sigreturn */ ML_(fixup_guest_state_to_restart_syscall)(&tst->arch); -// VG_(sigframe_destroy)((struct vki_ucontext *)ARG1, tid, False); VG_(sigframe_destroy)(tid); /* For unclear reasons, it appears we need the syscall to return @@ -299,44 +280,17 @@ driver logic copies it back unchanged. Also, note %EAX is of the guest registers written by VG_(sigframe_destroy). */ rflags = LibVEX_GuestAMD64_get_rflags(&tst->arch.vex); - SET_STATUS_from_SysRes( VG_(mk_SysRes_amd64_freebsd)( tst->arch.vex.guest_RAX, tst->arch.vex.guest_RDX, (rflags & 1) != 0 ? True : False) ); + SET_STATUS_from_SysRes( VG_(mk_SysRes_amd64_freebsd)( tst->arch.vex.guest_RAX, + tst->arch.vex.guest_RDX, (rflags & 1) != 0 ? True : False) ); - /* Check to see if some any signals arose as a result of this. */ - *flags |= SfPollAfter; -} - -#if 0 /* QQQ keep for 6.x signals */ -PRE(sys_rt_sigreturn) -{ - ThreadState* tst; - PRINT("rt_sigreturn ( )"); + /* Tell the driver not to update the guest state with the "result", + and set a bogus result to keep it happy. */ + *flags |= SfNoWriteResult; + SET_STATUS_Success(0); - vg_assert(VG_(is_valid_tid)(tid)); - vg_assert(tid >= 1 && tid < VG_N_THREADS); - vg_assert(VG_(is_running_thread)(tid)); - - /* Adjust esp to point to start of frame; skip back up over handler - ret addr */ - tst = VG_(get_ThreadState)(tid); - tst->arch.vex.guest_ESP -= sizeof(Addr); - - /* This is only so that the EIP is (might be) useful to report if - something goes wrong in the sigreturn */ - ML_(fixup_guest_state_to_restart_syscall)(&tst->arch); - - VG_(sigframe_destroy)(tid, True); - - /* For unclear reasons, it appears we need the syscall to return - without changing %EAX. Since %EAX is the return value, and can - denote either success or failure, we must set up so that the - driver logic copies it back unchanged. Also, note %EAX is of - the guest registers written by VG_(sigframe_destroy). */ - SET_STATUS_from_SysRes( VG_(mk_SysRes_x86_linux)( tst->arch.vex.guest_EAX ) ); - /* Check to see if some any signals arose as a result of this. */ *flags |= SfPollAfter; } -#endif /* This is here because on x86 the off_t is passed in 2 regs. Don't ask about pad. */ ==== //depot/projects/valgrind/coregrind/pub_core_sigframe.h#5 (text+ko) ==== @@ -57,7 +57,6 @@ restore the CPU state from it. */ #ifdef VGO_freebsd extern -#warning DANGER!! void VG_(sigframe_destroy)( ThreadId tid ); #else extern