Date: Fri, 7 Nov 2008 22:36:49 GMT From: Peter Wemm <peter@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 152635 for review Message-ID: <200811072236.mA7Mano2058175@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=152635 Change 152635 by peter@peter_hammer on 2008/11/07 22:36:07 Ugh. FreeBSD-6 had sigtimedwait(), but it was missing from compat32. Add a detection for running under 32 bit emulation so we can emulate it on 6.x under compat32. (This is also needed for other things too) Affected files ... .. //depot/projects/valgrind/coregrind/m_coredump/coredump-elf.c#5 edit .. //depot/projects/valgrind/coregrind/m_libcproc.c#7 edit .. //depot/projects/valgrind/coregrind/m_libcsignal.c#9 edit .. //depot/projects/valgrind/coregrind/m_main.c#11 edit .. //depot/projects/valgrind/coregrind/pub_core_libcproc.h#4 edit .. //depot/projects/valgrind/include/vki/vki-freebsd.h#12 edit Differences ... ==== //depot/projects/valgrind/coregrind/m_coredump/coredump-elf.c#5 (text+ko) ==== @@ -240,12 +240,6 @@ const vki_siginfo_t *si) { struct vki_user_regs_struct *regs; - Int error, osreldate; - vki_size_t osreldatel; - - osreldate = 0; - osreldatel = sizeof(osreldate); - error = VG_(sysctlbyname)("kern.osreldate", &osreldate, &osreldatel, 0, 0); VG_(memset)(prs, 0, sizeof(*prs)); @@ -253,7 +247,7 @@ prs->pr_statussz = sizeof(struct vki_elf_prstatus); prs->pr_gregsetsz = sizeof(vki_elf_gregset_t); prs->pr_fpregsetsz = sizeof(vki_elf_fpregset_t); - prs->pr_osreldate = osreldate; + prs->pr_osreldate = VG_(getosreldate)(); prs->pr_cursig = si->si_signo; prs->pr_pid = tst->os_state.lwpid; ==== //depot/projects/valgrind/coregrind/m_libcproc.c#7 (text+ko) ==== @@ -675,14 +675,51 @@ return error; } -Int VG_(modfind)(const Char *modname) +Int VG_(getosreldate)(void) +{ + static Int osreldate = 0; + vki_size_t osreldatel; + + if (osreldate == 0) { + osreldatel = sizeof(osreldate); + VG_(sysctlbyname)("kern.osreldate", &osreldate, &osreldatel, 0, 0); + } + return (osreldate); +} + +Bool VG_(is32on64)(void) { - SysRes res; +#if defined(VGP_amd64_freebsd) + return False; +#elif defined(VGP_x86_freebsd) + Int oid[2], error; + vki_size_t len; + char machbuf[32]; + static Int is32on64 = -1; - res = VG_(do_syscall1)(__NR_modfind, (UWord)modname); - if (res.isError) - return -1; - return res.res; + if (is32on64 == -1) { + oid[0] = VKI_CTL_HW; + oid[1] = VKI_HW_MACHINE; + len = sizeof(machbuf); + error = VG_(sysctl)(oid, 2, machbuf, &len, NULL, 0); + if (error == 0) { + machbuf[31] = '\0'; + if (VG_(strcmp)(machbuf, "amd64") == 0) + is32on64 = 1; + else + is32on64 = 0; + } else { + is32on64 = -2; + } + } + if (is32on64 == 1) { + return True; + } else { + return False; + } +#else +# error Unknown platform +#endif } #endif ==== //depot/projects/valgrind/coregrind/m_libcsignal.c#9 (text+ko) ==== @@ -36,6 +36,7 @@ #include "pub_core_libcassert.h" #include "pub_core_syscall.h" #include "pub_core_libcsignal.h" /* self */ +#include "pub_core_libcproc.h" /* sigemptyset, sigfullset, sigaddset and sigdelset return 0 on success and -1 on error. */ @@ -227,21 +228,7 @@ return res.isError ? -1 : res.res; } -#elif defined(VGO_freebsd) && __FreeBSD__ >= 7 -Int VG_(sigtimedwait_zero)( const vki_sigset_t *set, - vki_siginfo_t *info ) -{ - static const struct vki_timespec zero = { 0, 0 }; - /* only on freebsd6.x and higher */ - SysRes res = VG_(do_syscall3)(__NR_sigtimedwait, (UWord)set, (UWord)info, - (UWord)&zero); - return res.isError ? -1 : res.res; -} -#elif defined(VGO_aix5) || (defined(VGO_freebsd) && __FreeBSD__ < 7) -#if defined(VGO_freebsd) -#define __NR__sigpending __NR_sigpending -#define __NR__sigsuspend __NR_sigsuspend -#endif +#elif defined(VGO_aix5) /* The general idea is: - use sigpending to find out which signals are pending - choose one @@ -332,10 +319,119 @@ return i; } -#if defined(VGO_freebsd) -#undef __NR__sigpending -#undef __NR__sigsuspend +#elif defined(VGO_freebsd) + +/* + * This is a mess. sigtimedwait() was added in FreeBSD-6. However, + * there was no 32 bit syscall version until FreeBSD-7. So on older + * platforms we have to check. + */ +#if __FreeBSD__ < 7 +static void sigtimedwait_zero_handler ( Int sig ) +{ + vg_assert(sig != VKI_SIGILL); + vg_assert(sig != VKI_SIGSEGV); + vg_assert(sig != VKI_SIGBUS); + vg_assert(sig != VKI_SIGTRAP); + vg_assert(sig != VKI_SIGSYS); + /* do nothing */ +} +#endif + +Int VG_(sigtimedwait_zero)( const vki_sigset_t *set, + vki_siginfo_t *info ) +{ +#if __FreeBSD__ < 7 + Int i, ir; + SysRes sr; + vki_sigset_t pending, blocked, allbutone; + struct vki_sigaction sa, saved_sa; + Int osreldate; +#if defined(VGP_x86_freebsd) + Int is32on64; +#endif +#endif + Bool have_sigtimedwait_zero = True; + static const struct vki_timespec zero = { 0, 0 }; + +#if __FreeBSD__ < 7 + osreldate = VG_(getosreldate)(); + if (osreldate < 600000) + have_sigtimedwait_zero = False; +#if defined(VGP_x86_freebsd) + /* 32 bit emulation is busted, no sigtimedwait even though the kernel has it */ + is32on64 = VG_(is32on64)(); + if (is32on64 && osreldate < 700000) + have_sigtimedwait_zero = False; +#endif +#endif + if (have_sigtimedwait_zero) { + SysRes res = VG_(do_syscall3)(__NR_sigtimedwait, (UWord)set, (UWord)info, + (UWord)&zero); + return res.isError ? -1 : res.res; + } + +#if __FreeBSD__ < 7 + /* Find out what's pending: FreeBSD sigpending */ + sr = VG_(do_syscall1)(__NR_sigpending, (UWord)&pending); + vg_assert(!sr.isError); + + /* don't try for signals not in 'set' */ + /* pending = pending `intersect` set */ + for (i = 0; i < _VKI_NSIG_WORDS; i++) + pending.sig[i] &= set->sig[i]; + + /* don't try for signals not blocked at the moment */ + ir = VG_(sigprocmask)(VKI_SIG_SETMASK, NULL, &blocked); + vg_assert(ir == 0); + + /* pending = pending `intersect` blocked */ + for (i = 0; i < _VKI_NSIG_WORDS; i++) + pending.sig[i] &= blocked.sig[i]; + + /* decide which signal we're going to snarf */ + for (i = 1; i < _VKI_NSIG; i++) + if (VG_(sigismember)(&pending,i)) + break; + + if (i == _VKI_NSIG) + return 0; + + /* fetch signal i. + pre: i is blocked and pending + pre: we are the only thread running + */ + /* Set up alternative signal handler */ + VG_(sigfillset)(&allbutone); + VG_(sigdelset)(&allbutone, i); + sa.sa_mask = allbutone; + sa.ksa_handler = &sigtimedwait_zero_handler; + sa.sa_flags = 0; + ir = VG_(sigaction)(i, &sa, &saved_sa); + vg_assert(ir == 0); + + /* Switch signal masks and wait for the signal. This should happen + immediately, since we've already established it is pending and + blocked. */ + sr = VG_(do_syscall1)(__NR_sigsuspend, (UWord)&allbutone); + vg_assert(sr.isError); + if (0) + VG_(debugLog)(0, "libcsignal", + "sigtimedwait_zero: sigsuspend got res %ld err %ld\n", + sr.res, sr.err); + vg_assert(sr.res == (UWord)-1); + + /* Restore signal's handler to whatever it was before */ + ir = VG_(sigaction)(i, &saved_sa, NULL); + vg_assert(ir == 0); + + /* This is bogus - we could get more info from the sighandler. */ + VG_(memset)( info, 0, sizeof(*info) ); + info->si_signo = i; + + return i; #endif +} #else # error Unknown OS ==== //depot/projects/valgrind/coregrind/m_main.c#11 (text+ko) ==== @@ -324,25 +324,6 @@ /* log to stderr by default, but usage message goes to stdout */ tmp_log_fd = 2; -#if defined(VGO_freebsd) && 0 - { - Int modid; - - modid = VG_(modfind)("getpath_fromfd"); - if (modid < 0) { - struct vki_timespec ts = { 2, 0 }; - VG_(message)(Vg_UserMsg, ""); - VG_(message)(Vg_UserMsg, "*** WARNING! Functionality SEVERELY LIMITED without getpath_kern module!! ***"); -#if defined(for_yahoo) - VG_(message)(Vg_UserMsg, "Please yinst install getpath_kern"); -#else - VG_(message)(Vg_UserMsg, "There is a copy in valgrind/getpath/*"); -#endif - VG_(message)(Vg_UserMsg, ""); - VG_(do_syscall2)(__NR_nanosleep, (UWord)&ts, (UWord)NULL); - } - } -#endif /* Check for sane path in ./configure --prefix=... */ if (VG_LIBDIR[0] != '/') VG_(err_config_error)("Please use absolute paths in " ==== //depot/projects/valgrind/coregrind/pub_core_libcproc.h#4 (text+ko) ==== @@ -88,7 +88,8 @@ // sysctl, modfind extern Int VG_(sysctl)(Int *oid, UInt oidlen, void *oldp, vki_size_t *oldlenp, void *newp, vki_size_t newlen); extern Int VG_(sysctlbyname)(const Char *name, void *oldp, vki_size_t *oldlenp, void *newp, vki_size_t newlen); -extern Int VG_(modfind)(const Char *name); +extern Int VG_(getosreldate)(void); +extern Bool VG_(is32on64)(void); #endif #endif // __PUB_CORE_LIBCPROC_H ==== //depot/projects/valgrind/include/vki/vki-freebsd.h#12 (text+ko) ==== @@ -1815,8 +1815,10 @@ //---------------------------------------------------------------------- #define VKI_CTL_KERN 1 +#define VKI_CTL_HW 6 #define VKI_KERN_PROC 14 #define VKI_KERN_PROC_VMMAP 13 +#define VKI_HW_MACHINE 1 //---------------------------------------------------------------------- // From sys/thr.h
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200811072236.mA7Mano2058175>