diff -r efb6377bb4b5 -r ae0a1b9f3c43 .hgignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,37 @@ +syntax: glob + +*.Po +*.a +*.o +*.so +*.xml +*~ +.dirstamp +Makefile +Makefile.in +Makefile.vex.in +VEX/pub/libvex_guest_offsets.h +aclocal.m4 +autom4te.cache +cachegrind/cg_annotate +cachegrind/cg_diff +callgrind/callgrind_annotate +callgrind/callgrind_control +compile +config.* +configure +coregrind/link_tool_exe_* +coregrind/valgrind +coregrind/vgdb +default.supp +depcomp +drd/scripts/download-and-build-splash2 +glibc-2.X.supp +install-sh +massif/ms_print +missing +perf/vg_perf +stamp-h1 +tests/vg_regtest +valgrind.pc +valgrind.spec diff -r efb6377bb4b5 -r ae0a1b9f3c43 .hgtags --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgtags Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,14 @@ +8d645defcfa983d9ad37e75e7c1057f7d1aaf979 VALGRIND_3_10_1_OPENBSD_0 +efb6377bb4b5b25d4c7c002373699578eb7133de VALGRIND_3_10_1 +98bd825ce0f37f8940bd0d3298c012fd8ade5b7e VALGRIND_3_10_0 +2ef87542159498df04fa6b00644ffbd7f4c36dee VALGRIND_3_9_0 +dd5820c7275354bbe8551049fb64102be1c50c10 VALGRIND_3_10_1_OPENBSD_1 +59971ca3a720ec4bf9503ee78810a8783f2c25a4 VALGRIND_3_10_1_OPENBSD_2 +8b81738f4b547b60121af90c17e609cf7d6bf532 VALGRIND_3_10_1_OPENBSD_3 +82a4fe83cb33ee5120bce064aded983fcc58f0e2 VALGRIND_3_10_1_OPENBSD_4 +98afb059f92c9c910fffbf24a0710f072962b63a VALGRIND_3_10_1_OPENBSD_5 +5d4879a66aedfd81fc629dc66a3e66761aa5e659 VALGRIND_3_10_1_OPENBSD_6 +1fa872d8796158bccde5fbc19f14389618f5c69b VALGRIND_3_10_1_OPENBSD_7 +ca7b71155c431c08526debfec78fde4b55368cf8 VALGRIND_3_10_1_OPENBSD_8 +3f6687ad27d32da28ca8444f206675f96c216828 VALGRIND_3_10_1_OPENBSD_20150731 +ab13c5202b8ca4e30c552d75fb62b6c06cc7a1f8 VALGRIND_3_10_1_OPENBSD_20160330 diff -r efb6377bb4b5 -r ae0a1b9f3c43 Makefile.all.am --- a/Makefile.all.am Mon Dec 01 23:44:20 2014 +0900 +++ b/Makefile.all.am Thu Mar 31 15:57:55 2016 +0900 @@ -153,8 +153,7 @@ endif AM_FLAG_M3264_X86_LINUX = @FLAG_M32@ -AM_CFLAGS_X86_LINUX = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \ - $(AM_CFLAGS_BASE) -fomit-frame-pointer +AM_CFLAGS_X86_LINUX = @FLAG_M32@ $(AM_CFLAGS_BASE) -fomit-frame-pointer AM_CFLAGS_PSO_X86_LINUX = @FLAG_M32@ $(AM_CFLAGS_BASE) $(AM_CFLAGS_PSO_BASE) AM_CCASFLAGS_X86_LINUX = @FLAG_M32@ -g @@ -179,6 +178,22 @@ AM_CFLAGS_PSO_PPC64LE_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) $(AM_CFLAGS_PSO_BASE) AM_CCASFLAGS_PPC64LE_LINUX = @FLAG_M64@ -g +AM_FLAG_M3264_X86_FREEBSD = @FLAG_M32@ +AM_CFLAGS_X86_FREEBSD = @FLAG_M32@ $(AM_CFLAGS_BASE) +AM_CCASFLAGS_X86_FREEBSD = $(AM_CPPFLAGS_X86_FREEBSD) @FLAG_M32@ -g + +AM_FLAG_M3264_X86_OPENBSD = @FLAG_M32@ +AM_CFLAGS_X86_OPENBSD = @FLAG_M32@ $(AM_CFLAGS_BASE) +AM_CCASFLAGS_X86_OPENBSD = $(AM_CPPFLAGS_X86_OPENBSD) @FLAG_M32@ -g + +AM_FLAG_M3264_AMD64_FREEBSD = @FLAG_M64@ +AM_CFLAGS_AMD64_FREEBSD = @FLAG_M64@ $(AM_CFLAGS_BASE) -fomit-frame-pointer +AM_CCASFLAGS_AMD64_FREEBSD = $(AM_CPPFLAGS_AMD64_FREEBSD) @FLAG_M64@ -g + +AM_FLAG_M3264_AMD64_OPENBSD = @FLAG_M64@ +AM_CFLAGS_AMD64_OPENBSD = @FLAG_M64@ $(AM_CFLAGS_BASE) -fomit-frame-pointer +AM_CCASFLAGS_AMD64_OPENBSD = $(AM_CPPFLAGS_AMD64_OPENBSD) @FLAG_M64@ -g + AM_FLAG_M3264_ARM_LINUX = @FLAG_M32@ AM_CFLAGS_ARM_LINUX = @FLAG_M32@ \ $(AM_CFLAGS_BASE) -marm -mcpu=cortex-a8 @@ -242,6 +257,8 @@ # Baseline link flags for making vgpreload shared objects. # PRELOAD_LDFLAGS_COMMON_LINUX = -nodefaultlibs -shared -Wl,-z,interpose,-z,initfirst +PRELOAD_LDFLAGS_COMMON_FREEBSD = -nodefaultlibs -shared -Wl,-z,interpose,-z,initfirst +PRELOAD_LDFLAGS_COMMON_OPENBSD = -nodefaultlibs -shared -Wl,-z,interpose,-z,initfirst PRELOAD_LDFLAGS_COMMON_DARWIN = -dynamic -dynamiclib -all_load if VGCONF_PLATVARIANT_IS_ANDROID @@ -256,6 +273,9 @@ PRELOAD_LDFLAGS_PPC32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@ PRELOAD_LDFLAGS_PPC64BE_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@ PRELOAD_LDFLAGS_PPC64LE_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@ +PRELOAD_LDFLAGS_X86_FREEBSD = $(PRELOAD_LDFLAGS_COMMON_FREEBSD) @FLAG_M32@ +PRELOAD_LDFLAGS_AMD64_FREEBSD = $(PRELOAD_LDFLAGS_COMMON_FREEBSD) @FLAG_M64@ +PRELOAD_LDFLAGS_AMD64_OPENBSD = $(PRELOAD_LDFLAGS_COMMON_OPENBSD) @FLAG_M64@ PRELOAD_LDFLAGS_ARM_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@ PRELOAD_LDFLAGS_ARM64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@ PRELOAD_LDFLAGS_X86_DARWIN = $(PRELOAD_LDFLAGS_COMMON_DARWIN) -arch i386 @@ -263,4 +283,3 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@ PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@ PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@ - diff -r efb6377bb4b5 -r ae0a1b9f3c43 Makefile.am --- a/Makefile.am Mon Dec 01 23:44:20 2014 +0900 +++ b/Makefile.am Thu Mar 31 15:57:55 2016 +0900 @@ -44,6 +44,7 @@ glibc-2.X-drd.supp \ exp-sgcheck.supp \ darwin9.supp darwin9-drd.supp \ + freebsd.supp openbsd.supp \ darwin10.supp darwin10-drd.supp \ darwin11.supp darwin12.supp darwin13.supp \ bionic.supp @@ -99,6 +100,7 @@ EXTRA_DIST = \ COPYING.DOCS \ README_DEVELOPERS \ + README_FREEBSD \ README_PACKAGERS \ README_MISSING_SYSCALL_OR_IOCTL \ README.s390 \ diff -r efb6377bb4b5 -r ae0a1b9f3c43 Makefile.tool.am --- a/Makefile.tool.am Mon Dec 01 23:44:20 2014 +0900 +++ b/Makefile.tool.am Thu Mar 31 15:57:55 2016 +0900 @@ -36,13 +36,29 @@ -static -nodefaultlibs -nostartfiles -u _start @FLAG_NO_BUILD_ID@ TOOL_LDFLAGS_COMMON_DARWIN = \ -nodefaultlibs -nostartfiles -Wl,-u,__start -Wl,-e,__start +TOOL_LDFLAGS_COMMON_FREEBSD = -static \ + -nodefaultlibs -nostartfiles -u _start @FLAG_NO_BUILD_ID@ +TOOL_LDFLAGS_COMMON_OPENBSD = -static \ + -nodefaultlibs -nostartfiles -u __start @FLAG_NO_BUILD_ID@ TOOL_LDFLAGS_X86_LINUX = \ $(TOOL_LDFLAGS_COMMON_LINUX) @FLAG_M32@ +TOOL_LDFLAGS_X86_FREEBSD = \ + $(TOOL_LDFLAGS_COMMON_FREEBSD) @FLAG_M32@ + +TOOL_LDFLAGS_X86_OPENBSD = \ + $(TOOL_LDFLAGS_COMMON_OPENBSD) @FLAG_M32@ + TOOL_LDFLAGS_AMD64_LINUX = \ $(TOOL_LDFLAGS_COMMON_LINUX) @FLAG_M64@ +TOOL_LDFLAGS_AMD64_FREEBSD = \ + $(TOOL_LDFLAGS_COMMON_FREEBSD) @FLAG_M64@ + +TOOL_LDFLAGS_AMD64_OPENBSD = \ + $(TOOL_LDFLAGS_COMMON_OPENBSD) @FLAG_M64@ + TOOL_LDFLAGS_PPC32_LINUX = \ $(TOOL_LDFLAGS_COMMON_LINUX) @FLAG_M32@ @@ -111,12 +127,24 @@ LIBREPLACEMALLOC_PPC64LE_LINUX = \ $(top_builddir)/coregrind/libreplacemalloc_toolpreload-ppc64le-linux.a +LIBREPLACEMALLOC_X86_FREEBSD = \ + $(top_builddir)/coregrind/libreplacemalloc_toolpreload-x86-freebsd.a + +LIBREPLACEMALLOC_X86_OPENBSD = \ + $(top_builddir)/coregrind/libreplacemalloc_toolpreload-x86-openbsd.a + LIBREPLACEMALLOC_ARM_LINUX = \ $(top_builddir)/coregrind/libreplacemalloc_toolpreload-arm-linux.a LIBREPLACEMALLOC_ARM64_LINUX = \ $(top_builddir)/coregrind/libreplacemalloc_toolpreload-arm64-linux.a +LIBREPLACEMALLOC_AMD64_FREEBSD = \ + $(top_builddir)/coregrind/libreplacemalloc_toolpreload-amd64-freebsd.a + +LIBREPLACEMALLOC_AMD64_OPENBSD = \ + $(top_builddir)/coregrind/libreplacemalloc_toolpreload-amd64-openbsd.a + LIBREPLACEMALLOC_X86_DARWIN = \ $(top_builddir)/coregrind/libreplacemalloc_toolpreload-x86-darwin.a @@ -167,6 +195,26 @@ $(LIBREPLACEMALLOC_ARM64_LINUX) \ -Wl,--no-whole-archive +LIBREPLACEMALLOC_LDFLAGS_X86_FREEBSD = \ + -Wl,--whole-archive \ + $(LIBREPLACEMALLOC_X86_FREEBSD) \ + -Wl,--no-whole-archive + +LIBREPLACEMALLOC_LDFLAGS_X86_OPENBSD = \ + -Wl,--whole-archive \ + $(LIBREPLACEMALLOC_X86_OPENBSD) \ + -Wl,--no-whole-archive + +LIBREPLACEMALLOC_LDFLAGS_AMD64_FREEBSD = \ + -Wl,--whole-archive \ + $(LIBREPLACEMALLOC_AMD64_FREEBSD) \ + -Wl,--no-whole-archive + +LIBREPLACEMALLOC_LDFLAGS_AMD64_OPENBSD = \ + -Wl,--whole-archive \ + $(LIBREPLACEMALLOC_AMD64_OPENBSD) \ + -Wl,--no-whole-archive + LIBREPLACEMALLOC_LDFLAGS_X86_DARWIN = \ $(LIBREPLACEMALLOC_X86_DARWIN) diff -r efb6377bb4b5 -r ae0a1b9f3c43 README_FREEBSD --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README_FREEBSD Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,14 @@ +So, install ports for autoconf, automake and gmake. +$ sh autogen.sh +$ ./configure --prefix=/where/ever +$ gmake +$ gmake install + +Sun Aug 19 20:26:48 UTC 2007 PS_STRINGS + Valgrind barfs all over the place on setproctitle. + + This also manifests itself in a corrupted environment in + children of child processes when --trace-children=yes is used. + + To cope correctly Valgrind must install the modified argv/envp + pointers in the ps-strings area, and mark it as accessible. diff -r efb6377bb4b5 -r ae0a1b9f3c43 README_OPENBSD --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README_OPENBSD Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,12 @@ +So, install ports for autoconf, automake and gmake. +$ sh autogen.sh +$ ./configure --prefix=/where/ever +$ gmake +$ gmake install + +o For the moment, you have to: + + o Need a comming KERN_PROC_VMMAP sysctl. + + o User have to belong to "kmem" group to read kernel memory via /dev/kmem + via kvm(3). diff -r efb6377bb4b5 -r ae0a1b9f3c43 VEX/priv/guest_amd64_helpers.c --- a/VEX/priv/guest_amd64_helpers.c Mon Dec 01 23:44:20 2014 +0900 +++ b/VEX/priv/guest_amd64_helpers.c Thu Mar 31 15:57:55 2016 +0900 @@ -2889,11 +2889,19 @@ void amd64g_dirtyhelper_RDTSCP ( VexGuestAMD64State* st ) { # if defined(__x86_64__) +// XXX +// XXX +// XXX +#if 0 UInt eax, ecx, edx; __asm__ __volatile__("rdtscp" : "=a" (eax), "=d" (edx), "=c" (ecx)); st->guest_RAX = (ULong)eax; st->guest_RCX = (ULong)ecx; st->guest_RDX = (ULong)edx; +#endif +// XXX +// XXX +// XXX # else /* Do nothing. */ # endif diff -r efb6377bb4b5 -r ae0a1b9f3c43 autogen.sh --- a/autogen.sh Mon Dec 01 23:44:20 2014 +0900 +++ b/autogen.sh Thu Mar 31 15:57:55 2016 +0900 @@ -13,5 +13,5 @@ run aclocal run autoheader -run automake -a +run automake -c -a run autoconf diff -r efb6377bb4b5 -r ae0a1b9f3c43 cachegrind/tests/Makefile.am --- a/cachegrind/tests/Makefile.am Mon Dec 01 23:44:20 2014 +0900 +++ b/cachegrind/tests/Makefile.am Thu Mar 31 15:57:55 2016 +0900 @@ -24,7 +24,9 @@ AM_CXXFLAGS += $(AM_FLAG_M3264_PRI) # C ones +if !VGCONF_OS_IS_FREEBSD dlclose_LDADD = -ldl +endif if VGCONF_OS_IS_DARWIN myprint_so_LDFLAGS = $(AM_CFLAGS) -dynamic -dynamiclib -all_load -fpic else diff -r efb6377bb4b5 -r ae0a1b9f3c43 callgrind/tests/Makefile.am --- a/callgrind/tests/Makefile.am Mon Dec 01 23:44:20 2014 +0900 +++ b/callgrind/tests/Makefile.am Thu Mar 31 15:57:55 2016 +0900 @@ -26,4 +26,4 @@ AM_CFLAGS += $(AM_FLAG_M3264_PRI) AM_CXXFLAGS += $(AM_FLAG_M3264_PRI) -threads_LDADD = -lpthread +threads_LDFLAGS = -pthread diff -r efb6377bb4b5 -r ae0a1b9f3c43 configure.ac --- a/configure.ac Mon Dec 01 23:44:20 2014 +0900 +++ b/configure.ac Thu Mar 31 15:57:55 2016 +0900 @@ -40,6 +40,7 @@ # AC_SUBST([OBJCFLAGS]) # ]) AC_PROG_RANLIB +AC_PROG_EGREP # provide a very basic definition for AC_PROG_SED if it's not provided by # autoconf (as e.g. in autoconf 2.59). m4_ifndef([AC_PROG_SED], @@ -63,6 +64,9 @@ # figure out where perl lives AC_PATH_PROG(PERL, perl) +# find sed +AC_PATH_PROG(SED, sed) + # figure out where gdb lives AC_PATH_PROG(GDB, gdb, "/no/gdb/was/found/at/configure/time") AC_DEFINE_UNQUOTED(GDB_PATH, "$GDB", [path to GDB]) @@ -184,7 +188,7 @@ ARCH_MAX="x86" ;; - x86_64) + x86_64|amd64) AC_MSG_RESULT([ok (${host_cpu})]) ARCH_MAX="amd64" ;; @@ -321,6 +325,18 @@ ;; + *freebsd*) + AC_MSG_RESULT([ok (${host_os})]) + VGCONF_OS="freebsd" + DEFAULT_SUPP="freebsd.supp ${DEFAULT_SUPP}" + ;; + + *openbsd*) + AC_MSG_RESULT([ok (${host_os})]) + VGCONF_OS="openbsd" + DEFAULT_SUPP="openbsd.supp ${DEFAULT_SUPP}" + ;; + *darwin*) AC_MSG_RESULT([ok (${host_os})]) VGCONF_OS="darwin" @@ -555,10 +571,64 @@ VGCONF_ARCH_SEC="" VGCONF_PLATFORM_PRI_CAPS="PPC64LE_LINUX" VGCONF_PLATFORM_SEC_CAPS="" + ;; + x86-freebsd) + VGCONF_ARCH_PRI="x86" + VGCONF_ARCH_SEC="" + VGCONF_PLATFORM_PRI_CAPS="X86_FREEBSD" + VGCONF_PLATFORM_SEC_CAPS="" valt_load_address_pri_norml="0x38000000" valt_load_address_pri_inner="0x28000000" + valt_load_address_sec_norml="0xUNSET" + valt_load_address_sec_inner="0xUNSET" AC_MSG_RESULT([ok (${ARCH_MAX}-${VGCONF_OS})]) - ;; + ;; + amd64-freebsd) + if test x$vg_cv_only64bit = xyes; then + VGCONF_ARCH_PRI="amd64" + VGCONF_ARCH_SEC="" + VGCONF_PLATFORM_PRI_CAPS="AMD64_FREEBSD" + VGCONF_PLATFORM_SEC_CAPS="" + elif test x$vg_cv_only32bit = xyes; then + VGCONF_ARCH_PRI="x86" + VGCONF_ARCH_SEC="" + VGCONF_PLATFORM_PRI_CAPS="X86_FREEBSD" + VGCONF_PLATFORM_SEC_CAPS="" + else + VGCONF_ARCH_PRI="amd64" + VGCONF_ARCH_SEC="x86" + VGCONF_PLATFORM_PRI_CAPS="AMD64_FREEBSD" + VGCONF_PLATFORM_SEC_CAPS="X86_FREEBSD" + fi + FLAG_32ON64="-B/usr/lib32" + valt_load_address_pri_norml="0x38000000" + valt_load_address_pri_inner="0x28000000" + valt_load_address_sec_norml="0x38000000" + valt_load_address_sec_inner="0x28000000" + AC_MSG_RESULT([ok (${ARCH_MAX}-${VGCONF_OS})]) + ;; + x86-openbsd) + VGCONF_ARCH_PRI="x86" + VGCONF_ARCH_SEC="" + VGCONF_PLATFORM_PRI_CAPS="X86_OPENBSD" + VGCONF_PLATFORM_SEC_CAPS="" + valt_load_address_pri_norml="0x38000000" + valt_load_address_pri_inner="0x28000000" + valt_load_address_sec_norml="0xUNSET" + valt_load_address_sec_inner="0xUNSET" + AC_MSG_RESULT([ok (${ARCH_MAX}-${VGCONF_OS})]) + ;; + amd64-openbsd) + VGCONF_ARCH_PRI="amd64" + VGCONF_ARCH_SEC="" + VGCONF_PLATFORM_PRI_CAPS="AMD64_OPENBSD" + VGCONF_PLATFORM_SEC_CAPS="" + valt_load_address_pri_norml="0x38000000" + valt_load_address_pri_inner="0x28000000" + valt_load_address_sec_norml="0xUNSET" + valt_load_address_sec_inner="0xUNSET" + AC_MSG_RESULT([ok (${ARCH_MAX}-${VGCONF_OS})]) + ;; # Darwin gets identified as 32-bit even when it supports 64-bit. # (Not sure why, possibly because 'uname' returns "i386"?) Just about # all Macs support both 32-bit and 64-bit, so we just build both. If @@ -688,10 +758,16 @@ AM_CONDITIONAL(VGCONF_ARCHS_INCLUDE_X86, test x$VGCONF_PLATFORM_PRI_CAPS = xX86_LINUX \ -o x$VGCONF_PLATFORM_SEC_CAPS = xX86_LINUX \ + -o x$VGCONF_PLATFORM_PRI_CAPS = xX86_FREEBSD \ + -o x$VGCONF_PLATFORM_SEC_CAPS = xX86_FREEBSD \ + -o x$VGCONF_PLATFORM_PRI_CAPS = xX86_OPENBSD \ + -o x$VGCONF_PLATFORM_SEC_CAPS = xX86_OPENBSD \ -o x$VGCONF_PLATFORM_PRI_CAPS = xX86_DARWIN \ -o x$VGCONF_PLATFORM_SEC_CAPS = xX86_DARWIN ) AM_CONDITIONAL(VGCONF_ARCHS_INCLUDE_AMD64, test x$VGCONF_PLATFORM_PRI_CAPS = xAMD64_LINUX \ + -o x$VGCONF_PLATFORM_PRI_CAPS = xAMD64_FREEBSD \ + -o x$VGCONF_PLATFORM_PRI_CAPS = xAMD64_OPENBSD \ -o x$VGCONF_PLATFORM_PRI_CAPS = xAMD64_DARWIN ) AM_CONDITIONAL(VGCONF_ARCHS_INCLUDE_PPC32, test x$VGCONF_PLATFORM_PRI_CAPS = xPPC32_LINUX \ @@ -730,6 +806,19 @@ -o x$VGCONF_PLATFORM_SEC_CAPS = xARM_LINUX) AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_ARM64_LINUX, test x$VGCONF_PLATFORM_PRI_CAPS = xARM64_LINUX) + +AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_X86_FREEBSD, + test x$VGCONF_PLATFORM_PRI_CAPS = xX86_FREEBSD \ + -o x$VGCONF_PLATFORM_SEC_CAPS = xX86_FREEBSD) +AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_AMD64_FREEBSD, + test x$VGCONF_PLATFORM_PRI_CAPS = xAMD64_FREEBSD) + +AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_X86_OPENBSD, + test x$VGCONF_PLATFORM_PRI_CAPS = xX86_OPENBSD \ + -o x$VGCONF_PLATFORM_SEC_CAPS = xX86_OPENBSD) +AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_AMD64_OPENBSD, + test x$VGCONF_PLATFORM_PRI_CAPS = xAMD64_OPENBSD) + AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_S390X_LINUX, test x$VGCONF_PLATFORM_PRI_CAPS = xS390X_LINUX \ -o x$VGCONF_PLATFORM_SEC_CAPS = xS390X_LINUX) @@ -758,6 +847,14 @@ -o x$VGCONF_PLATFORM_PRI_CAPS = xS390X_LINUX \ -o x$VGCONF_PLATFORM_PRI_CAPS = xMIPS32_LINUX \ -o x$VGCONF_PLATFORM_PRI_CAPS = xMIPS64_LINUX) +AM_CONDITIONAL(VGCONF_OS_IS_FREEBSD, + test x$VGCONF_PLATFORM_PRI_CAPS = xX86_FREEBSD \ + -o x$VGCONF_PLATFORM_PRI_CAPS = xAMD64_FREEBSD \ + -o x$VGCONF_PLATFORM_PRI_CAPS = xPPC32_FREEBSD \ + -o x$VGCONF_PLATFORM_PRI_CAPS = xPPC64_FREEBSD) +AM_CONDITIONAL(VGCONF_OS_IS_OPENBSD, + test x$VGCONF_PLATFORM_PRI_CAPS = xX86_OPENBSD \ + -o x$VGCONF_PLATFORM_PRI_CAPS = xAMD64_OPENBSD) AM_CONDITIONAL(VGCONF_OS_IS_DARWIN, test x$VGCONF_PLATFORM_PRI_CAPS = xX86_DARWIN \ -o x$VGCONF_PLATFORM_PRI_CAPS = xAMD64_DARWIN) @@ -870,6 +967,22 @@ ], GLIBC_VERSION="darwin") +AC_EGREP_CPP([FREEBSD_LIBC], [ +#include +#if defined(__FreeBSD__) + FREEBSD_LIBC +#endif +], +GLIBC_VERSION="freebsd") + +AC_EGREP_CPP([OPENBSD_LIBC], [ +#include +#if defined(__OpenBSD__) + OPENBSD_LIBC +#endif +], +GLIBC_VERSION="openbsd") + # not really a version check AC_EGREP_CPP([BIONIC_LIBC], [ #if defined(__ANDROID__) @@ -1023,6 +1136,16 @@ AC_DEFINE([DARWIN_LIBC], 1, [Define to 1 if you're using Darwin]) # DEFAULT_SUPP set by kernel version check above. ;; + freebsd) + AC_MSG_RESULT(FreeBSD) + AC_DEFINE([FREEBSD_LIBC], 1, [Define to 1 if you're using FreeBSD]) + # DEFAULT_SUPP set by kernel version check above. + ;; + openbsd) + AC_MSG_RESULT(OpenBSD) + AC_DEFINE([OPENBSD_LIBC], 1, [Define to 1 if you're using OpenBSD]) + # DEFAULT_SUPP set by kernel version check above. + ;; bionic) AC_MSG_RESULT(Bionic) AC_DEFINE([BIONIC_LIBC], 1, [Define to 1 if you're using Bionic]) @@ -1561,12 +1684,12 @@ AC_MSG_CHECKING([if gcc accepts -m32]) safe_CFLAGS=$CFLAGS -CFLAGS="-m32" +CFLAGS="${FLAG_32ON64} -m32" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[ return 0; ]])], [ -FLAG_M32="-m32" +FLAG_M32="${FLAG_32ON64} -m32" AC_MSG_RESULT([yes]) ], [ FLAG_M32="" @@ -2496,6 +2619,8 @@ AC_CHECK_LIB([pthread], [pthread_create]) AC_CHECK_LIB([rt], [clock_gettime]) +safe_CFLAGS=$CFLAGS +CFLAGS="${CFLAGS} -pthread" AC_CHECK_FUNCS([ \ clock_gettime\ epoll_create \ @@ -2529,6 +2654,7 @@ process_vm_readv \ process_vm_writev \ ]) +CFLAGS=$safe_CFLAGS # AC_CHECK_LIB adds any library found to the variable LIBS, and links these # libraries with any shared object and/or executable. This is NOT what we @@ -2563,12 +2689,16 @@ mflag_primary= if test x$VGCONF_PLATFORM_PRI_CAPS = xX86_LINUX \ + -o x$VGCONF_PLATFORM_PRI_CAPS = xX86_FREEBSD \ + -o x$VGCONF_PLATFORM_PRI_CAPS = xX86_OPENBSD \ -o x$VGCONF_PLATFORM_PRI_CAPS = xPPC32_LINUX \ -o x$VGCONF_PLATFORM_PRI_CAPS = xARM_LINUX \ -o x$VGCONF_PLATFORM_PRI_CAPS = xMIPS32_LINUX \ -o x$VGCONF_PLATFORM_PRI_CAPS = xMIPS64_LINUX ; then mflag_primary=$FLAG_M32 elif test x$VGCONF_PLATFORM_PRI_CAPS = xAMD64_LINUX \ + -o x$VGCONF_PLATFORM_PRI_CAPS = xAMD64_FREEBSD \ + -o x$VGCONF_PLATFORM_PRI_CAPS = xAMD64_OPENBSD \ -o x$VGCONF_PLATFORM_PRI_CAPS = xPPC64_LINUX \ -o x$VGCONF_PLATFORM_PRI_CAPS = xARM64_LINUX \ -o x$VGCONF_PLATFORM_PRI_CAPS = xS390X_LINUX ; then @@ -2581,7 +2711,9 @@ mflag_secondary= if test x$VGCONF_PLATFORM_SEC_CAPS = xX86_LINUX \ - -o x$VGCONF_PLATFORM_SEC_CAPS = xPPC32_LINUX ; then + -o x$VGCONF_PLATFORM_SEC_CAPS = xPPC32_LINUX \ + -o x$VGCONF_PLATFORM_SEC_CAPS = xX86_FREEBSD \ + -o x$VGCONF_PLATFORM_SEC_CAPS = xX86_OPENBSD ; then mflag_secondary=$FLAG_M32 elif test x$VGCONF_PLATFORM_SEC_CAPS = xX86_DARWIN ; then mflag_secondary="$FLAG_M32 -arch i386" @@ -2602,6 +2734,12 @@ AM_COND_IF([VGCONF_OS_IS_LINUX], [CFLAGS_MPI="-g -O -fno-omit-frame-pointer -Wall -fpic" LDFLAGS_MPI="-fpic -shared"]) +AM_COND_IF([VGCONF_OS_IS_FREEBSD], + [CFLAGS_MPI="-g -O -fno-omit-frame-pointer -Wall -fpic" + LDFLAGS_MPI="-fpic -shared"]) +AM_COND_IF([VGCONF_OS_IS_OPENBSD], + [CFLAGS_MPI="-g -O -fno-omit-frame-pointer -Wall -fpic" + LDFLAGS_MPI="-fpic -shared"]) AM_COND_IF([VGCONF_OS_IS_DARWIN], [CFLAGS_MPI="-g -O -fno-omit-frame-pointer -Wall -dynamic" LDFLAGS_MPI="-dynamic -dynamiclib -all_load"]) @@ -3038,6 +3176,10 @@ ]) AC_CONFIG_FILES([coregrind/link_tool_exe_linux], [chmod +x coregrind/link_tool_exe_linux]) +AC_CONFIG_FILES([coregrind/link_tool_exe_freebsd], + [chmod +x coregrind/link_tool_exe_freebsd]) +AC_CONFIG_FILES([coregrind/link_tool_exe_openbsd], + [chmod +x coregrind/link_tool_exe_openbsd]) AC_CONFIG_FILES([coregrind/link_tool_exe_darwin], [chmod +x coregrind/link_tool_exe_darwin]) AC_OUTPUT diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/Makefile.am --- a/coregrind/Makefile.am Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/Makefile.am Thu Mar 31 15:57:55 2016 +0900 @@ -45,6 +45,23 @@ launcher-darwin.c \ m_debuglog.c endif +if VGCONF_OS_IS_FREEBSD +valgrind_SOURCES = \ + launcher-freebsd.c \ + m_debuglog.c +endif +if VGCONF_OS_IS_OPENBSD +AM_CPPFLAGS_@VGCONF_PLATFORM_PRI_CAPS@ += \ + -fPIC \ + -I/usr/local/include +if VGCONF_HAVE_PLATFORM_SEC +AM_CPPFLAGS_@VGCONF_PLATFORM_SEC_CAPS@ += \ + -I/usr/local/include +endif +valgrind_SOURCES = \ + launcher-openbsd.c \ + m_debuglog.c +endif valgrind_CPPFLAGS = $(AM_CPPFLAGS_PRI) valgrind_CFLAGS = $(AM_CFLAGS_PRI) @@ -74,6 +91,12 @@ # having access to Darwin, 'none' implementation is used. vgdb_SOURCES += vgdb-invoker-none.c endif +if VGCONF_OS_IS_FREEBSD +vgdb_SOURCES += vgdb-invoker-none.c +endif +if VGCONF_OS_IS_OPENBSD +vgdb_SOURCES += vgdb-invoker-none.c +endif vgdb_CPPFLAGS = $(AM_CPPFLAGS_PRI) vgdb_CFLAGS = $(AM_CFLAGS_PRI) @@ -248,6 +271,8 @@ m_syswrap/priv_syswrap-generic.h \ m_syswrap/priv_syswrap-linux.h \ m_syswrap/priv_syswrap-linux-variants.h \ + m_syswrap/priv_syswrap-freebsd.h \ + m_syswrap/priv_syswrap-openbsd.h \ m_syswrap/priv_syswrap-darwin.h \ m_syswrap/priv_syswrap-main.h \ m_syswrap/priv_syswrap-xen.h \ @@ -338,6 +363,10 @@ m_dispatch/dispatch-ppc32-linux.S \ m_dispatch/dispatch-ppc64be-linux.S \ m_dispatch/dispatch-ppc64le-linux.S \ + m_dispatch/dispatch-x86-freebsd.S \ + m_dispatch/dispatch-amd64-freebsd.S \ + m_dispatch/dispatch-x86-openbsd.S \ + m_dispatch/dispatch-amd64-openbsd.S \ m_dispatch/dispatch-arm-linux.S \ m_dispatch/dispatch-arm64-linux.S \ m_dispatch/dispatch-s390x-linux.S \ @@ -364,6 +393,8 @@ m_gdbserver/valgrind-low-mips64.c \ m_gdbserver/version.c \ m_initimg/initimg-linux.c \ + m_initimg/initimg-freebsd.c \ + m_initimg/initimg-openbsd.c \ m_initimg/initimg-darwin.c \ m_initimg/initimg-pathscan.c \ m_mach/mach_basics.c \ @@ -377,6 +408,10 @@ m_scheduler/sched-lock-generic.c \ m_sigframe/sigframe-x86-linux.c \ m_sigframe/sigframe-amd64-linux.c \ + m_sigframe/sigframe-x86-freebsd.c \ + m_sigframe/sigframe-amd64-freebsd.c \ + m_sigframe/sigframe-x86-openbsd.c \ + m_sigframe/sigframe-amd64-openbsd.c \ m_sigframe/sigframe-ppc32-linux.c \ m_sigframe/sigframe-ppc64-linux.c \ m_sigframe/sigframe-arm-linux.c \ @@ -391,6 +426,10 @@ m_syswrap/syscall-ppc32-linux.S \ m_syswrap/syscall-ppc64be-linux.S \ m_syswrap/syscall-ppc64le-linux.S \ + m_syswrap/syscall-x86-freebsd.S \ + m_syswrap/syscall-amd64-freebsd.S \ + m_syswrap/syscall-x86-openbsd.S \ + m_syswrap/syscall-amd64-openbsd.S \ m_syswrap/syscall-arm-linux.S \ m_syswrap/syscall-arm64-linux.S \ m_syswrap/syscall-s390x-linux.S \ @@ -402,11 +441,19 @@ m_syswrap/syswrap-generic.c \ m_syswrap/syswrap-linux.c \ m_syswrap/syswrap-linux-variants.c \ + m_syswrap/syswrap-freebsd.c \ + m_syswrap/syswrap-freebsd-variants.c \ + m_syswrap/syswrap-openbsd.c \ + m_syswrap/syswrap-openbsd-variants.c \ m_syswrap/syswrap-darwin.c \ m_syswrap/syswrap-x86-linux.c \ m_syswrap/syswrap-amd64-linux.c \ m_syswrap/syswrap-ppc32-linux.c \ m_syswrap/syswrap-ppc64-linux.c \ + m_syswrap/syswrap-x86-freebsd.c \ + m_syswrap/syswrap-amd64-freebsd.c \ + m_syswrap/syswrap-x86-openbsd.c \ + m_syswrap/syswrap-amd64-openbsd.c \ m_syswrap/syswrap-arm-linux.c \ m_syswrap/syswrap-arm64-linux.c \ m_syswrap/syswrap-s390x-linux.c \ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/launcher-freebsd.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coregrind/launcher-freebsd.c Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,339 @@ + +/*--------------------------------------------------------------------*/ +/*--- Launching valgrind m_launcher.c ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2009 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +/* Note: this is a "normal" program and not part of Valgrind proper, + and so it doesn't have to conform to Valgrind's arcane rules on + no-glibc-usage etc. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* #include */ +#include + +#include "pub_core_debuglog.h" +#include "pub_core_vki.h" // Avoids warnings from + // pub_core_libcfile.h +#include "pub_core_libcproc.h" // For VALGRIND_LIB, VALGRIND_LAUNCHER +#include "pub_core_ume.h" + + + +#define PATH_MAX 4096 /* POSIX refers to this a lot but I dunno + where it is defined */ + +#ifndef EM_X86_64 +#define EM_X86_64 62 // elf.h doesn't define this on some older systems +#endif + +/* Report fatal errors */ +__attribute__((noreturn)) +static void barf ( const char *format, ... ) +{ + va_list vargs; + + va_start(vargs, format); + fprintf(stderr, "valgrind: Cannot continue: "); + vfprintf(stderr, format, vargs); + fprintf(stderr, "\n"); + va_end(vargs); + + exit(1); + /*NOTREACHED*/ + assert(0); +} + +/* Search the path for the client program */ +static const char *find_client(const char *clientname) +{ + static char fullname[PATH_MAX]; + const char *path = getenv("PATH"); + const char *colon; + + while (path) + { + if ((colon = strchr(path, ':')) == NULL) + { + strcpy(fullname, path); + path = NULL; + } + else + { + memcpy(fullname, path, colon - path); + fullname[colon - path] = '\0'; + path = colon + 1; + } + + strcat(fullname, "/"); + strcat(fullname, clientname); + + if (access(fullname, R_OK|X_OK) == 0) + return fullname; + } + + return clientname; +} + +/* Examine the client and work out which platform it is for */ +static const char *select_platform(const char *clientname) +{ + int fd; + uint8_t header[4096]; + ssize_t n_bytes; + const char *platform = NULL; + + if (strchr(clientname, '/') == NULL) + clientname = find_client(clientname); + + if ((fd = open(clientname, O_RDONLY)) < 0) + return NULL; + // barf("open(%s): %s", clientname, strerror(errno)); + + n_bytes = read(fd, header, sizeof(header)); + close(fd); + if (n_bytes < 2) { + return NULL; + } + + if (header[0] == '#' && header[1] == '!') { + int i = 2; + char *interp = (char *)header + 2; + + // Skip whitespace. + while (1) { + if (i == n_bytes) return NULL; + if (' ' != header[i] && '\t' == header[i]) break; + i++; + } + + // Get the interpreter name. + interp = &header[i]; + while (1) { + if (i == n_bytes) break; + if (isspace(header[i])) break; + i++; + } + if (i == n_bytes) return NULL; + header[i] = '\0'; + + platform = select_platform(interp); + + } else if (n_bytes >= SELFMAG && memcmp(header, ELFMAG, SELFMAG) == 0) { + + if (n_bytes >= sizeof(Elf32_Ehdr) && header[EI_CLASS] == ELFCLASS32) { + const Elf32_Ehdr *ehdr = (Elf32_Ehdr *)header; + + if (header[EI_DATA] == ELFDATA2LSB) { + if (ehdr->e_machine == EM_386 && + ehdr->e_ident[EI_OSABI] == ELFOSABI_FREEBSD) { + platform = "x86-freebsd"; + } + } + } else if (n_bytes >= sizeof(Elf64_Ehdr) && header[EI_CLASS] == ELFCLASS64) { + const Elf64_Ehdr *ehdr = (Elf64_Ehdr *)header; + + if (header[EI_DATA] == ELFDATA2LSB) { + if (ehdr->e_machine == EM_X86_64 && + ehdr->e_ident[EI_OSABI] == ELFOSABI_FREEBSD) { + platform = "amd64-freebsd"; + } + } + } + } + + return platform; +} + +/* Where we expect to find all our aux files */ +static const char *valgrind_lib = VG_LIBDIR; + +int main(int argc, char** argv, char** envp) +{ + int i, j, loglevel, r; + const char *toolname = NULL; + const char *clientname = NULL; + const char *platform; + const char *default_platform; + const char *cp; + char *toolfile; + char launcher_name[PATH_MAX+1]; + char* new_line; + char** new_env; +#if __FreeBSD__ >= 7 + int oid[4]; + vki_size_t len; +#endif + + /* Start the debugging-log system ASAP. First find out how many + "-d"s were specified. This is a pre-scan of the command line. + At the same time, look for the tool name. */ + loglevel = 0; + for (i = 1; i < argc; i++) { + if (argv[i][0] != '-') { + clientname = argv[i]; + break; + } + if (0 == strcmp(argv[i], "--")) { + if (i+1 < argc) + clientname = argv[i+1]; + break; + } + if (0 == strcmp(argv[i], "-d")) + loglevel++; + if (0 == strncmp(argv[i], "--tool=", 7)) + toolname = argv[i] + 7; + } + + /* ... and start the debug logger. Now we can safely emit logging + messages all through startup. */ + VG_(debugLog_startup)(loglevel, "Stage 1"); + + /* Make sure we know which tool we're using */ + if (toolname) { + VG_(debugLog)(1, "launcher", "tool '%s' requested\n", toolname); + } else { + VG_(debugLog)(1, "launcher", + "no tool requested, defaulting to 'memcheck'\n"); + toolname = "memcheck"; + } + + /* Select a platform to use if we can't decide that by looking at + the executable (eg because it's a shell script). Note that the + default_platform is not necessarily either the primary or + secondary build target. Instead it's chosen to maximise the + chances that /bin/sh will work on it. Hence for a primary + target of ppc64-linux we still choose ppc32-linux as the default + target, because on most ppc64-linux setups, the basic /bin, + /usr/bin, etc, stuff is built in 32-bit mode, not 64-bit + mode. */ + if (0==strcmp(VG_PLATFORM,"x86-freebsd")) + default_platform = "x86-freebsd"; + else if (0==strcmp(VG_PLATFORM,"amd64-freebsd")) + default_platform = "amd64-freebsd"; + else + barf("Unknown VG_PLATFORM '%s'", VG_PLATFORM); + + /* Work out what platform to use, or use the default platform if + not possible. */ + if (clientname == NULL) { + VG_(debugLog)(1, "launcher", + "no client specified, defaulting platform to '%s'\n", + default_platform); + platform = default_platform; + } else if ((platform = select_platform(clientname)) != NULL) { + VG_(debugLog)(1, "launcher", "selected platform '%s'\n", platform); + } else { + VG_(debugLog)(1, "launcher", + "no platform detected, defaulting platform to '%s'\n", + default_platform); + platform = default_platform; + } + + /* Figure out the name of this executable (viz, the launcher), so + we can tell stage2. stage2 will use the name for recursive + invocations of valgrind on child processes. */ + memset(launcher_name, 0, PATH_MAX+1); + +#if __FreeBSD__ >= 7 + oid[0] = CTL_KERN; + oid[1] = KERN_PROC; + oid[2] = KERN_PROC_PATHNAME; + oid[3] = getpid(); + len = PATH_MAX; + r = sysctl(oid, 4, launcher_name, &len, 0, 0); + if (r != 0) { + fprintf(stderr, "valgrind: warning (non-fatal): " + "sysctl(\"kern.proc.pathname\") failed.\n"); + fprintf(stderr, "valgrind: continuing, however --trace-children=yes " + "will not work.\n"); + } +#else + r = readlink("/proc/curproc/file", launcher_name, PATH_MAX); + if (r == -1) { + /* If /proc/self/exe can't be followed, don't give up. Instead + continue with an empty string for VALGRIND_LAUNCHER. In the + sys_execve wrapper, this is tested, and if found to be empty, + fail the execve. */ + fprintf(stderr, "valgrind: warning (non-fatal): " + "readlink(\"/proc/curproc/file\") failed.\n"); + fprintf(stderr, "valgrind: continuing, however --trace-children=yes " + "will not work.\n"); + } +#endif + + /* tediously augment the env: VALGRIND_LAUNCHER=launcher_name */ + new_line = malloc(strlen(VALGRIND_LAUNCHER) + 1 + + strlen(launcher_name) + 1); + if (new_line == NULL) + barf("malloc of new_line failed."); + strcpy(new_line, VALGRIND_LAUNCHER); + strcat(new_line, "="); + strcat(new_line, launcher_name); + + for (j = 0; envp[j]; j++) + ; + new_env = malloc((j+2) * sizeof(char*)); + if (new_env == NULL) + barf("malloc of new_env failed."); + for (i = 0; i < j; i++) + new_env[i] = envp[i]; + new_env[i++] = new_line; + new_env[i++] = NULL; + assert(i == j+2); + + /* Establish the correct VALGRIND_LIB. */ + cp = getenv(VALGRIND_LIB); + + if (cp != NULL) + valgrind_lib = cp; + + /* Build the stage2 invocation, and execve it. Bye! */ + toolfile = malloc(strlen(valgrind_lib) + strlen(toolname) + strlen(platform) + 3); + if (toolfile == NULL) + barf("malloc of toolfile failed."); + sprintf(toolfile, "%s/%s-%s", valgrind_lib, toolname, platform); + + VG_(debugLog)(1, "launcher", "launching %s\n", toolfile); + + execve(toolfile, argv, new_env); + + fprintf(stderr, "valgrind: failed to start tool '%s' for platform '%s': %s\n", + toolname, platform, strerror(errno)); + + exit(1); +} diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/launcher-openbsd.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coregrind/launcher-openbsd.c Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,341 @@ + +/*--------------------------------------------------------------------*/ +/*--- Launching valgrind m_launcher.c ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2009 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +/* Note: this is a "normal" program and not part of Valgrind proper, + and so it doesn't have to conform to Valgrind's arcane rules on + no-glibc-usage etc. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* #include */ +#include + +#include "pub_core_debuglog.h" +#include "pub_core_vki.h" // Avoids warnings from + // pub_core_libcfile.h +#include "pub_core_libcproc.h" // For VALGRIND_LIB, VALGRIND_LAUNCHER +#include "pub_core_ume.h" + + + +#define PATH_MAX 4096 /* POSIX refers to this a lot but I dunno + where it is defined */ + +#ifndef EM_X86_64 +#define EM_X86_64 62 // elf.h doesn't define this on some older systems +#endif + +/* Report fatal errors */ +__attribute__((noreturn)) +static void barf ( const char *format, ... ) +{ + va_list vargs; + + va_start(vargs, format); + fprintf(stderr, "valgrind: Cannot continue: "); + vfprintf(stderr, format, vargs); + fprintf(stderr, "\n"); + va_end(vargs); + + exit(1); + /*NOTREACHED*/ + assert(0); +} + +/* Search the path for the client program */ +static const char *find_client(const char *clientname) +{ + static char fullname[PATH_MAX]; + const char *path = getenv("PATH"); + const char *colon; + + while (path) + { + if ((colon = strchr(path, ':')) == NULL) + { + strcpy(fullname, path); + path = NULL; + } + else + { + memcpy(fullname, path, colon - path); + fullname[colon - path] = '\0'; + path = colon + 1; + } + + strcat(fullname, "/"); + strcat(fullname, clientname); + + if (access(fullname, R_OK|X_OK) == 0) + return fullname; + } + + return clientname; +} + +/* Examine the client and work out which platform it is for */ +static const char *select_platform(const char *clientname) +{ + int fd; + uint8_t header[4096]; + ssize_t n_bytes; + const char *platform = NULL; + + if (strchr(clientname, '/') == NULL) + clientname = find_client(clientname); + + if ((fd = open(clientname, O_RDONLY)) < 0) + return NULL; + // barf("open(%s): %s", clientname, strerror(errno)); + + n_bytes = read(fd, header, sizeof(header)); + close(fd); + if (n_bytes < 2) { + return NULL; + } + + if (header[0] == '#' && header[1] == '!') { + int i = 2; + char *interp = (char *)header + 2; + + // Skip whitespace. + while (1) { + if (i == n_bytes) return NULL; + if (' ' != header[i] && '\t' == header[i]) break; + i++; + } + + // Get the interpreter name. + interp = &header[i]; + while (1) { + if (i == n_bytes) break; + if (isspace(header[i])) break; + i++; + } + if (i == n_bytes) return NULL; + header[i] = '\0'; + + platform = select_platform(interp); + + } else if (n_bytes >= SELFMAG && memcmp(header, ELFMAG, SELFMAG) == 0) { + + if (n_bytes >= sizeof(Elf32_Ehdr) && header[EI_CLASS] == ELFCLASS32) { + const Elf32_Ehdr *ehdr = (Elf32_Ehdr *)header; + + if (header[EI_DATA] == ELFDATA2LSB) { + if (ehdr->e_machine == EM_386 && + ehdr->e_ident[EI_OSABI] == ELFOSABI_OPENBSD) { + platform = "x86-openbsd"; + } + } + } else if (n_bytes >= sizeof(Elf64_Ehdr) && header[EI_CLASS] == ELFCLASS64) { + const Elf64_Ehdr *ehdr = (Elf64_Ehdr *)header; + + if (header[EI_DATA] == ELFDATA2LSB) { + if (ehdr->e_machine == EM_X86_64 && + ehdr->e_ident[EI_OSABI] == ELFOSABI_OPENBSD) { + platform = "amd64-openbsd"; + } + } + } + } + + return platform; +} + +/* Where we expect to find all our aux files */ +static const char *valgrind_lib = VG_LIBDIR; + +int main(int argc, char** argv, char** envp) +{ + int i, j, loglevel, r; + const char *toolname = NULL; + const char *clientname = NULL; + const char *platform; + const char *default_platform; + const char *cp; + char *toolfile; + char launcher_name[PATH_MAX+1]; + char* new_line; + char** new_env; +/* #if __FreeBSD__ >= 7 */ + int oid[4]; +/* #endif */ + + /* Start the debugging-log system ASAP. First find out how many + "-d"s were specified. This is a pre-scan of the command line. + At the same time, look for the tool name. */ + loglevel = 0; + for (i = 1; i < argc; i++) { + if (argv[i][0] != '-') { + clientname = argv[i]; + break; + } + if (0 == strcmp(argv[i], "--")) { + if (i+1 < argc) + clientname = argv[i+1]; + break; + } + if (0 == strcmp(argv[i], "-d")) + loglevel++; + if (0 == strncmp(argv[i], "--tool=", 7)) + toolname = argv[i] + 7; + } + + /* ... and start the debug logger. Now we can safely emit logging + messages all through startup. */ + VG_(debugLog_startup)(loglevel, "Stage 1"); + + /* Make sure we know which tool we're using */ + if (toolname) { + VG_(debugLog)(1, "launcher", "tool '%s' requested\n", toolname); + } else { + VG_(debugLog)(1, "launcher", + "no tool requested, defaulting to 'memcheck'\n"); + toolname = "memcheck"; + } + + /* Select a platform to use if we can't decide that by looking at + the executable (eg because it's a shell script). Note that the + default_platform is not necessarily either the primary or + secondary build target. Instead it's chosen to maximise the + chances that /bin/sh will work on it. Hence for a primary + target of ppc64-linux we still choose ppc32-linux as the default + target, because on most ppc64-linux setups, the basic /bin, + /usr/bin, etc, stuff is built in 32-bit mode, not 64-bit + mode. */ + if (0==strcmp(VG_PLATFORM,"x86-openbsd")) + default_platform = "x86-openbsd"; + else if (0==strcmp(VG_PLATFORM,"amd64-openbsd")) + default_platform = "amd64-openbsd"; + else + barf("Unknown VG_PLATFORM '%s'", VG_PLATFORM); + + /* Work out what platform to use, or use the default platform if + not possible. */ + if (clientname == NULL) { + VG_(debugLog)(1, "launcher", + "no client specified, defaulting platform to '%s'\n", + default_platform); + platform = default_platform; + } else if ((platform = select_platform(clientname)) != NULL) { + VG_(debugLog)(1, "launcher", "selected platform '%s'\n", platform); + } else { + VG_(debugLog)(1, "launcher", + "no platform detected, defaulting platform to '%s'\n", + default_platform); + platform = default_platform; + } + + /* Figure out the name of this executable (viz, the launcher), so + we can tell stage2. stage2 will use the name for recursive + invocations of valgrind on child processes. */ + memset(launcher_name, 0, PATH_MAX+1); + +/* #if __FreeBSD__ >= 7 */ +// XXX kvm_getargv() + char *sysctl_buf[4096/*XXX*/]; + size_t sysctl_len = sizeof(sysctl_buf); + oid[0] = CTL_KERN; + oid[1] = KERN_PROC_ARGS; + oid[2] = getpid(); + oid[3] = KERN_PROC_ARGV; + r = sysctl(oid, 4, sysctl_buf, &sysctl_len, 0, 0); + if (r != 0) { + fprintf(stderr, "valgrind: warning (non-fatal): " + "sysctl(\"kern.proc.pathname\") failed.\n"); + fprintf(stderr, "valgrind: continuing, however --trace-children=yes " + "will not work.\n"); + } + strlcpy(launcher_name, sysctl_buf[0], PATH_MAX+1); +/* #else */ +/* r = readlink("/proc/curproc/file", launcher_name, PATH_MAX); */ +/* if (r == -1) { */ +/* /\* If /proc/self/exe can't be followed, don't give up. Instead */ +/* continue with an empty string for VALGRIND_LAUNCHER. In the */ +/* sys_execve wrapper, this is tested, and if found to be empty, */ +/* fail the execve. *\/ */ +/* fprintf(stderr, "valgrind: warning (non-fatal): " */ +/* "readlink(\"/proc/curproc/file\") failed.\n"); */ +/* fprintf(stderr, "valgrind: continuing, however --trace-children=yes " */ +/* "will not work.\n"); */ +/* } */ +/* #endif */ + + /* tediously augment the env: VALGRIND_LAUNCHER=launcher_name */ + new_line = malloc(strlen(VALGRIND_LAUNCHER) + 1 + + strlen(launcher_name) + 1); + if (new_line == NULL) + barf("malloc of new_line failed."); + strcpy(new_line, VALGRIND_LAUNCHER); + strcat(new_line, "="); + strcat(new_line, launcher_name); + + for (j = 0; envp[j]; j++) + ; + new_env = malloc((j+2) * sizeof(char*)); + if (new_env == NULL) + barf("malloc of new_env failed."); + for (i = 0; i < j; i++) + new_env[i] = envp[i]; + new_env[i++] = new_line; + new_env[i++] = NULL; + assert(i == j+2); + + /* Establish the correct VALGRIND_LIB. */ + cp = getenv(VALGRIND_LIB); + + if (cp != NULL) + valgrind_lib = cp; + + /* Build the stage2 invocation, and execve it. Bye! */ + toolfile = malloc(strlen(valgrind_lib) + strlen(toolname) + strlen(platform) + 3); + if (toolfile == NULL) + barf("malloc of toolfile failed."); + sprintf(toolfile, "%s/%s-%s", valgrind_lib, toolname, platform); + + VG_(debugLog)(1, "launcher", "launching %s\n", toolfile); + + execve(toolfile, argv, new_env); + + fprintf(stderr, "valgrind: failed to start tool '%s' for platform '%s': %s\n", + toolname, platform, strerror(errno)); + + exit(1); +} diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/link_tool_exe_freebsd.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coregrind/link_tool_exe_freebsd.in Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,88 @@ +#! @PERL@ + +# This script handles linking the tool executables on FreeBSD, +# statically and at an alternative load address. +# +# Linking statically sidesteps all sorts of complications to do with +# having two copies of the dynamic linker (valgrind's and the +# client's) coexisting in the same process. The alternative load +# address is needed because Valgrind itself will load the client at +# whatever address it specifies, which is almost invariably the +# default load address. Hence we can't allow Valgrind itself (viz, +# the tool executable) to be loaded at that address. +# +# Unfortunately there's no standard way to do 'static link at +# alternative address', so these link_tool_exe_*.in scripts handle +# the per-platform hoop-jumping. +# +# What we get passed here is: +# first arg +# the alternative load address +# all the rest of the args +# the gcc invokation to do the final link, that +# the build system would have done, left to itself +# +# We just let the script 'die' if something is wrong, rather than do +# proper error reporting. We don't expect the users to run this +# directly. It is only run as part of the build process, with +# carefully constrained inputs. +# +# Linux specific complications: +# +# - need to support both old GNU ld and gold: use -Ttext= to +# set the text segment address. +# +# - need to pass --build-id=none (that is, -Wl,--build-id=none to +# gcc) if it accepts it, to ensure the linker doesn't add a +# notes section which ends up at the default load address and +# so defeats our attempts to keep that address clear for the +# client. However, older linkers don't support this flag, so it +# is tested for by configure.in and is shipped to us as part of +# argv[2 ..]. +# +# +# So: what we actually do: +# +# pass the specified command to the linker as-is, except, add +# "-static" and "-Ttext=" to it. +# + +use warnings; +use strict; + +# expect at least: alt-load-address gcc -o foo bar.o +die "Not enough arguments" + if (($#ARGV + 1) < 5); + +my $ala = $ARGV[0]; + +# check for plausible-ish alt load address +die "Bogus alt-load address" + if (length($ala) < 3 || index($ala, "0x") != 0); + +# The cc invokation to do the final link +my $cc = $ARGV[1]; + +# and the 'restargs' are argv[2 ..] + +# so, build up the complete command here: +# 'cc' -static -Ttext='ala' 'restargs' + +my $cmd="$cc -static -Wl,-Ttext=$ala"; + +# Add the rest of the parameters +foreach my $n (2 .. $#ARGV) { + $cmd = "$cmd $ARGV[$n]"; +} + +#print "link_tool_exe_linux: $cmd\n"; + + +# Execute the command: +my $r = system("$cmd"); + +if ($r == 0) { + exit 0; +} else { + exit 1; +} diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/link_tool_exe_openbsd.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coregrind/link_tool_exe_openbsd.in Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,99 @@ +#! @PERL@ + +# This script handles linking the tool executables on OpenBSD, +# statically and at an alternative load address. +# +# Linking statically sidesteps all sorts of complications to do with +# having two copies of the dynamic linker (valgrind's and the +# client's) coexisting in the same process. The alternative load +# address is needed because Valgrind itself will load the client at +# whatever address it specifies, which is almost invariably the +# default load address. Hence we can't allow Valgrind itself (viz, +# the tool executable) to be loaded at that address. +# +# Unfortunately there's no standard way to do 'static link at +# alternative address', so these link_tool_exe_*.in scripts handle +# the per-platform hoop-jumping. +# +# What we get passed here is: +# first arg +# the alternative load address +# all the rest of the args +# the gcc invokation to do the final link, that +# the build system would have done, left to itself +# +# We just let the script 'die' if something is wrong, rather than do +# proper error reporting. We don't expect the users to run this +# directly. It is only run as part of the build process, with +# carefully constrained inputs. +# +# Linux specific complications: +# +# - need to support both old GNU ld and gold: use -Ttext= to +# set the text segment address. +# +# - need to pass --build-id=none (that is, -Wl,--build-id=none to +# gcc) if it accepts it, to ensure the linker doesn't add a +# notes section which ends up at the default load address and +# so defeats our attempts to keep that address clear for the +# client. However, older linkers don't support this flag, so it +# is tested for by configure.in and is shipped to us as part of +# argv[2 ..]. +# +# +# So: what we actually do: +# +# pass the specified command to the linker as-is, except, add +# "-static" and "-Ttext=" to it. +# + +use warnings; +use strict; + +# expect at least: alt-load-address gcc -o foo bar.o +die "Not enough arguments" + if (($#ARGV + 1) < 5); + +my $ala = $ARGV[0]; + +# check for plausible-ish alt load address +die "Bogus alt-load address" + if (length($ala) < 3 || index($ala, "0x") != 0); + +# The cc invokation to do the final link +my $cc = $ARGV[1]; + +# and the 'restargs' are argv[2 ..] + +# so, build up the complete command here: +# 'cc' -static -Ttext='ala' 'restargs' + +my $textbase = eval("$ala + 0x1000"); +my $notebase = eval("$ala"); + +my $ldscript = "/usr/libdata/ldscripts/elf_x86_64_obsd.x"; +my $temp = `mktemp /tmp/XXXXXX`; +chomp($temp); +my $origbase = 0x400000; +system(sprintf "sed -e 's|%x|%x|g' < $ldscript > $temp", $origbase, $notebase); + +my $cmd = sprintf "$cc -static -nopie -Wl,-Ttext=0x%x -Wl,-T,$temp", $textbase; + +# Add the rest of the parameters +foreach my $n (2 .. $#ARGV) { + $cmd = "$cmd $ARGV[$n]"; +} + +#print "link_tool_exe_linux: $cmd\n"; + + +# Execute the command: +my $r = system("$cmd"); + +unlink $temp; + +if ($r == 0) { + exit 0; +} else { + exit 1; +} diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_aspacemgr/aspacemgr-common.c --- a/coregrind/m_aspacemgr/aspacemgr-common.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_aspacemgr/aspacemgr-common.c Thu Mar 31 15:57:55 2016 +0900 @@ -37,6 +37,7 @@ ************************************************************* */ #include "priv_aspacemgr.h" +#include "pub_core_libcassert.h" #include "config.h" @@ -173,14 +174,28 @@ } res = VG_(do_syscall6)(__NR_mmap, (UWord)start, length, prot, flags, (UInt)fd, offset); +# elif defined(VGP_x86_freebsd) || defined(VGP_x86_openbsd) + if (flags & VKI_MAP_ANONYMOUS && fd == 0) + fd = -1; + res = VG_(do_syscall7)(__NR_mmap, (UWord)start, length, + prot, flags, fd, offset, offset >> 32ul); +# elif defined(VGP_amd64_freebsd) + if (flags & VKI_MAP_ANONYMOUS && fd == 0) + fd = -1; + res = VG_(do_syscall6)(__NR_mmap, (UWord)start, length, + prot, flags, fd, offset); +# elif defined(VGP_amd64_openbsd) + if (flags & VKI_MAP_ANONYMOUS && fd == 0) + fd = -1; + res = VG_(do_syscall7)(__NR_mmap, (UWord)start, length, + prot, flags, fd, 0, offset); # else # error Unknown platform # endif return res; } -static -SysRes local_do_mprotect_NO_NOTIFY(Addr start, SizeT length, UInt prot) +SysRes VG_(am_do_mprotect_NO_NOTIFY)(Addr start, SizeT length, UInt prot) { return VG_(do_syscall3)(__NR_mprotect, (UWord)start, length, prot ); } @@ -209,6 +224,16 @@ 0/*flags, meaning: must be at old_addr, else FAIL */, 0/*new_addr, is ignored*/ ); +# elif defined(VGO_freebsd) +#warning Not implemented + ML_(am_barf)("ML_(am_do_extend_mapping_NO_NOTIFY) on FreeBSD"); + /* NOTREACHED, but gcc doesn't understand that */ + return VG_(mk_SysRes_Error)(0); +# elif defined(VGO_openbsd) +#warning Not implemented + ML_(am_barf)("ML_(am_do_extend_mapping_NO_NOTIFY) on OpenBSD"); + /* NOTREACHED, but gcc doesn't understand that */ + return VG_(mk_SysRes_Error)(0); # else # error Unknown OS # endif @@ -230,6 +255,14 @@ VKI_MREMAP_MAYMOVE|VKI_MREMAP_FIXED/*move-or-fail*/, new_addr ); +# elif defined(VGO_freebsd) + ML_(am_barf)("ML_(am_do_relocate_nooverlap_mapping_NO_NOTIFY) on FreeBSD"); + /* NOTREACHED, but gcc doesn't understand that */ + return VG_(mk_SysRes_Error)(0); +# elif defined(VGO_openbsd) + ML_(am_barf)("ML_(am_do_relocate_nooverlap_mapping_NO_NOTIFY) on OpenBSD"); + /* NOTREACHED, but gcc doesn't understand that */ + return VG_(mk_SysRes_Error)(0); # else # error Unknown OS # endif @@ -276,7 +309,7 @@ Int ML_(am_fcntl) ( Int fd, Int cmd, Addr arg ) { -# if defined(VGO_linux) +# if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd) SysRes res = VG_(do_syscall3)(__NR_fcntl, fd, cmd, arg); # elif defined(VGO_darwin) SysRes res = VG_(do_syscall3)(__NR_fcntl_nocancel, fd, cmd, arg); @@ -317,6 +350,11 @@ return False; } +#if defined(VGO_freebsd) || defined(VGO_openbsd) +#define M_FILEDESC_BUF 1000000 +static Char filedesc_buf[M_FILEDESC_BUF]; +#endif + Bool ML_(am_resolve_filename) ( Int fd, /*OUT*/HChar* buf, Int nbuf ) { #if defined(VGO_linux) @@ -329,6 +367,42 @@ else return False; +#elif defined(VGO_freebsd) + Int mib[4]; + SysRes sres; + vki_size_t len; + Char *bp, *eb; + struct vki_kinfo_file *kf; + + mib[0] = VKI_CTL_KERN; + mib[1] = VKI_KERN_PROC; + mib[2] = VKI_KERN_PROC_FILEDESC; + mib[3] = sr_Res(VG_(do_syscall0)(__NR_getpid)); + len = sizeof(filedesc_buf); + sres = VG_(do_syscall6)(__NR___sysctl, (UWord)mib, 4, (UWord)filedesc_buf, + (UWord)&len, 0, 0); + if (sr_isError(sres)) { + VG_(debugLog)(0, "sysctl(kern.proc.filedesc)", "%s\n", VG_(strerror)(sr_Err(sres))); + ML_(am_exit)(1); + } + /* Walk though the list. */ + bp = filedesc_buf; + eb = filedesc_buf + len; + while (bp < eb) { + kf = (struct vki_kinfo_file *)bp; + if (kf->kf_fd == fd) + break; + bp += kf->kf_structsize; + } + if (bp >= eb || *kf->kf_path == '\0') + VG_(strncpy)( buf, "[unknown]", nbuf ); + else + VG_(strncpy)( buf, kf->kf_path, nbuf ); + return True; +#elif defined(VGO_aix5) + I_die_here; /* maybe just return False? */ + return False; + #elif defined(VGO_darwin) HChar tmp[VKI_MAXPATHLEN+1]; if (0 == ML_(am_fcntl)(fd, VKI_F_GETPATH, (UWord)tmp)) { @@ -340,6 +414,18 @@ } return False; +#elif defined(VGO_openbsd) + char *VG_(pathname_by_fd)(Int fd); + + HChar *p; + + p = VG_(pathname_by_fd)(fd); + if (p) { + VG_(strncpy_safely)(buf, p, nbuf); + return True; + } + return False; + # else # error Unknown OS # endif @@ -382,7 +468,7 @@ aspacem_assert(VG_IS_PAGE_ALIGNED(stack)); /* Protect the guard areas. */ - sres = local_do_mprotect_NO_NOTIFY( + sres = VG_(am_do_mprotect_NO_NOTIFY)( (Addr) &stack[0], VG_STACK_GUARD_SZB, VKI_PROT_NONE ); @@ -392,7 +478,7 @@ VG_STACK_GUARD_SZB, VKI_PROT_NONE ); - sres = local_do_mprotect_NO_NOTIFY( + sres = VG_(am_do_mprotect_NO_NOTIFY)( (Addr) &stack->bytes[VG_STACK_GUARD_SZB + VG_STACK_ACTIVE_SZB], VG_STACK_GUARD_SZB, VKI_PROT_NONE ); diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_aspacemgr/aspacemgr-linux.c --- a/coregrind/m_aspacemgr/aspacemgr-linux.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_aspacemgr/aspacemgr-linux.c Thu Mar 31 15:57:55 2016 +0900 @@ -3,7 +3,7 @@ /*--- The address space manager: segment initialisation and ---*/ /*--- tracking, stack operations ---*/ /*--- ---*/ -/*--- Implementation for Linux (and Darwin!) m_aspacemgr-linux.c ---*/ +/*--- Implementation for Linux, FreeBSD and Darwin ---*/ /*--------------------------------------------------------------------*/ /* @@ -31,7 +31,7 @@ The GNU General Public License is contained in the file COPYING. */ -#if defined(VGO_linux) || defined(VGO_darwin) +#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd) || defined(VGO_openbsd) /* ************************************************************* DO NOT INCLUDE ANY OTHER FILES HERE. @@ -40,6 +40,9 @@ ************************************************************* */ #include "priv_aspacemgr.h" +#if defined(VGO_freebsd) || defined(VGO_openbsd) +#include "pub_core_libcproc.h" // VG_(sysctl) +#endif #include "config.h" @@ -973,7 +976,7 @@ cmp_devino = False; #endif -#if defined(VGO_darwin) +#if defined(VGO_darwin) || defined(VGO_freebsd) || defined(VGO_openbsd) // GrP fixme kernel info doesn't have dev/inode cmp_devino = False; @@ -1582,7 +1585,7 @@ if (dev != 0 && ino != 0) seg.kind = SkFileV; -# if defined(VGO_darwin) +# if defined(VGO_darwin) || defined(VGO_openbsd) // GrP fixme no dev/ino on darwin if (offset != 0) seg.kind = SkFileV; @@ -1654,7 +1657,35 @@ suggested_clstack_end = -1; // ignored; Mach-O specifies its stack -#else /* !defined(VGO_darwin) */ +#elif defined(VGO_freebsd) + +# if VG_WORDSIZE == 4 + aspacem_minAddr = (Addr) 0x00010000; // 64K + aspacem_maxAddr = VG_PGROUNDDN( sp_at_startup ) - 1; +# else + aspacem_minAddr = (Addr) 0x00010000; // 64k + aspacem_maxAddr = (Addr) (Addr)0x800000000 - 1; // 32G +# ifdef ENABLE_INNER + { Addr cse = VG_PGROUNDDN( sp_at_startup ) - 1; + if (aspacem_maxAddr > cse) + aspacem_maxAddr = cse; + } +# endif +# endif + + aspacem_cStart = aspacem_minAddr; + aspacem_vStart = VG_PGROUNDUP((aspacem_minAddr + aspacem_maxAddr + 1) / 2); + +# ifdef ENABLE_INNER + aspacem_vStart -= 0x10000000; // 256M +# endif + +#if 0 + suggested_clstack_top = aspacem_maxAddr - 16*1024*1024ULL + + VKI_PAGE_SIZE; +#endif + +#else /* Establish address limits and block out unusable parts accordingly. */ @@ -1685,7 +1716,7 @@ suggested_clstack_end = aspacem_maxAddr - 16*1024*1024ULL + VKI_PAGE_SIZE; -#endif /* #else of 'defined(VGO_darwin)' */ +#endif /* #else of 'defined(VGO_freebsd)' */ aspacem_assert(VG_IS_PAGE_ALIGNED(aspacem_minAddr)); aspacem_assert(VG_IS_PAGE_ALIGNED(aspacem_maxAddr + 1)); @@ -2043,17 +2074,21 @@ aspacem_assert(VG_IS_PAGE_ALIGNED(len)); aspacem_assert(VG_IS_PAGE_ALIGNED(offset)); +#if !defined(VKI_MAP_STACK) +#define VKI_MAP_STACK 0 +#endif + /* Discard is needed if any of the just-trashed range had T. */ needDiscard = any_Ts_in_range( a, len ); init_nsegment( &seg ); - seg.kind = (flags & VKI_MAP_ANONYMOUS) ? SkAnonC : SkFileC; + seg.kind = (flags & (VKI_MAP_ANONYMOUS | VKI_MAP_STACK)) ? SkAnonC : SkFileC; seg.start = a; seg.end = a + len - 1; seg.hasR = toBool(prot & VKI_PROT_READ); seg.hasW = toBool(prot & VKI_PROT_WRITE); seg.hasX = toBool(prot & VKI_PROT_EXEC); - if (!(flags & VKI_MAP_ANONYMOUS)) { + if (!(flags & (VKI_MAP_ANONYMOUS | VKI_MAP_STACK))) { // Nb: We ignore offset requests in anonymous mmaps (see bug #126722) seg.offset = offset; if (ML_(am_get_fd_d_i_m)(fd, &dev, &ino, &mode)) { @@ -3661,11 +3696,140 @@ return !css_overflowed; } -#endif // defined(VGO_darwin) - -/*------END-procmaps-parser-for-Darwin---------------------------*/ - -#endif // defined(VGO_linux) || defined(VGO_darwin) +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + +#if defined(VGO_freebsd) + /* Size of a smallish table used to read /proc/self/map entries. */ + #define M_PROCMAP_BUF 10485760 /* 10M */ +#else + #define M_PROCMAP_BUF (sizeof(struct vki_kinfo_vmentry) * 64/* XXX */) +#endif + + /* static ... to keep it out of the stack frame. */ + static char procmap_buf[M_PROCMAP_BUF]; + +static void parse_procselfmaps ( + void (*record_mapping)( Addr addr, SizeT len, UInt prot, + ULong dev, ULong ino, Off64T offset, + const HChar* filename ), + void (*record_gap)( Addr addr, SizeT len ) + ) +{ +#if defined(VGO_freebsd) + Int i; + Addr start, endPlusOne, gapStart; + char* filename; + char *p; + UInt prot; + ULong foffset, dev, ino; + struct vki_kinfo_vmentry *kve; + vki_size_t len; + Int oid[4]; + SysRes sres; + + foffset = ino = 0; /* keep gcc-4.1.0 happy */ + + oid[0] = VKI_CTL_KERN; + oid[1] = VKI_KERN_PROC; + oid[2] = VKI_KERN_PROC_VMMAP; + oid[3] = sr_Res(VG_(do_syscall0)(__NR_getpid)); + len = sizeof(procmap_buf); + + sres = VG_(do_syscall6)(__NR___sysctl, (UWord)oid, 4, (UWord)procmap_buf, + (UWord)&len, 0, 0); + if (sr_isError(sres)) { + VG_(debugLog)(0, "procselfmaps", "sysctll %ld\n", sr_Err(sres)); + ML_(am_exit)(1); + } + gapStart = Addr_MIN; + i = 0; + p = procmap_buf; + while (p < (char *)procmap_buf + len) { + kve = (struct vki_kinfo_vmentry *)p; + start = (UWord)kve->kve_start; + endPlusOne = (UWord)kve->kve_end; + foffset = kve->kve_offset; + filename = kve->kve_path; + dev = kve->kve_fsid; + ino = kve->kve_fileid; + if (filename[0] != '/') { + filename = NULL; + foffset = 0; + } + + prot = 0; + if (kve->kve_protection & VKI_KVME_PROT_READ) prot |= VKI_PROT_READ; + if (kve->kve_protection & VKI_KVME_PROT_WRITE) prot |= VKI_PROT_WRITE; + if (kve->kve_protection & VKI_KVME_PROT_EXEC) prot |= VKI_PROT_EXEC; + + if (record_gap && gapStart < start) + (*record_gap) ( gapStart, start-gapStart ); + + if (record_mapping && start < endPlusOne) + (*record_mapping) ( start, endPlusOne-start, + prot, dev, ino, + foffset, filename ); + gapStart = endPlusOne; + p += kve->kve_structsize; + } + + if (record_gap && gapStart < Addr_MAX) + (*record_gap) ( gapStart, Addr_MAX - gapStart + 1 ); +#else +#define rounddown(x, y) (((x)/(y))*(y)) + Int mib[3]; + Int res; + struct vki_kinfo_vmentry *kve; + vki_size_t len; + char *p; + Addr gapStart; + + mib[0] = VKI_CTL_KERN; + mib[1] = VKI_KERN_PROC_VMMAP; + mib[2] = sr_Res(VG_(do_syscall0)(__NR_getpid)); + len = rounddown(M_PROCMAP_BUF, sizeof(struct vki_kinfo_vmentry)); + res = VG_(sysctl)(mib, 3, procmap_buf, &len, NULL, 0); + if (res) { + VG_(debugLog)(0, "procselfmaps", "sysctll %ld\n", res); + ML_(am_exit)(1); + } + + gapStart = Addr_MIN; + p = procmap_buf; + while (p < (char *)procmap_buf + len) { + Addr start, endPlusOne; + ULong foffset, dev, ino; + UInt prot; + + kve = (struct vki_kinfo_vmentry *)p; + start = (UWord)kve->vki_kve_start; + endPlusOne = (UWord)kve->vki_kve_end; + foffset = kve->vki_kve_offset; + dev = 0; // XXX kve->vki_kve_dev; + ino = 0; // XXX kve->vki_kve_ino; + + prot = 0; + if (kve->vki_kve_protection & VKI_KVE_PROT_READ) prot |= VKI_PROT_READ; + if (kve->vki_kve_protection & VKI_KVE_PROT_WRITE) prot |= VKI_PROT_WRITE; + if (kve->vki_kve_protection & VKI_KVE_PROT_EXEC) prot |= VKI_PROT_EXEC; + if (record_gap && gapStart < start) + (*record_gap) ( gapStart, start-gapStart ); + + if (record_mapping && start < endPlusOne) + (*record_mapping) ( start, endPlusOne-start, + prot, dev, ino, + foffset, NULL ); + gapStart = endPlusOne; + p += sizeof(*kve); + } + + if (record_gap && gapStart < Addr_MAX) + (*record_gap) ( gapStart, Addr_MAX - gapStart + 1 ); +#endif +} + +#endif +#endif /*--------------------------------------------------------------------*/ /*--- end ---*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_aspacemgr/priv_aspacemgr.h --- a/coregrind/m_aspacemgr/priv_aspacemgr.h Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_aspacemgr/priv_aspacemgr.h Thu Mar 31 15:57:55 2016 +0900 @@ -57,6 +57,10 @@ #include "pub_core_aspacemgr.h" // self +#if defined(VGO_openbsd) +#include "pub_core_proc.h" // kvm etc. +#endif + /* --------------- Implemented in aspacemgr-common.c ---------------*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_coredump/coredump-elf.c --- a/coregrind/m_coredump/coredump-elf.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_coredump/coredump-elf.c Thu Mar 31 15:57:55 2016 +0900 @@ -28,7 +28,7 @@ The GNU General Public License is contained in the file COPYING. */ -#if defined(VGO_linux) +#if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd) #include "pub_core_basics.h" #include "pub_core_vki.h" @@ -54,7 +54,11 @@ Generate a standard ELF core file corresponding to the client state at the time of a crash. */ +#if !defined(VGO_openbsd) #include +#else +#include +#endif #ifndef NT_PRXFPREG #define NT_PRXFPREG 0x46e62b7f /* copied from gdb5.1/include/elf/common.h */ #endif /* NT_PRXFPREG */ @@ -93,6 +97,9 @@ ehdr->e_ident[EI_CLASS] = VG_ELF_CLASS; ehdr->e_ident[EI_DATA] = VG_ELF_DATA2XXX; ehdr->e_ident[EI_VERSION] = EV_CURRENT; +#if defined(VGO_freebsd) + ehdr->e_ident[EI_OSABI] = ELFOSABI_FREEBSD; +#endif ehdr->e_type = ET_CORE; ehdr->e_machine = VG_ELF_MACHINE; @@ -112,7 +119,11 @@ static void fill_phdr(ESZ(Phdr) *phdr, const NSegment *seg, UInt off, Bool write) { +#if !defined(VGO_freebsd) && !defined(VGO_openbsd) + SizeT len = seg->end - seg->start; +#else SizeT len = seg->end - seg->start + 1; +#endif write = write && should_dump(seg); @@ -197,6 +208,7 @@ VG_(memset)(prpsinfo, 0, sizeof(*prpsinfo)); +#if !defined(VGO_freebsd) && !defined(VGO_openbsd) switch(tst->status) { case VgTs_Runnable: case VgTs_Yielding: @@ -219,7 +231,11 @@ prpsinfo->pr_uid = 0; prpsinfo->pr_gid = 0; - +#else + prpsinfo->pr_version = VKI_PRPSINFO_VERSION; + prpsinfo->pr_psinfosz = sizeof(struct vki_elf_prpsinfo); +#endif + if (VG_(resolve_filename)(VG_(cl_exec_fd), name, VKI_PATH_MAX)) { HChar *n = name+VG_(strlen)(name)-1; @@ -228,7 +244,12 @@ if (n != name) n++; +#if !defined(VGO_freebsd) && !defined(VGO_openbsd) VG_(strncpy)(prpsinfo->pr_fname, n, sizeof(prpsinfo->pr_fname)); +#else + VG_(strncpy)(prpsinfo->pr_fname, n, sizeof(prpsinfo->pr_fname) - 1); + VG_(strncpy)(prpsinfo->pr_psargs, n, sizeof(prpsinfo->pr_psargs) - 1); +#endif } } @@ -241,16 +262,25 @@ VG_(memset)(prs, 0, sizeof(*prs)); +#if !defined(VGO_freebsd) && !defined(VGO_openbsd) prs->pr_info.si_signo = si->si_signo; prs->pr_info.si_code = si->si_code; prs->pr_info.si_errno = 0; +#else + prs->pr_version = VKI_PRSTATUS_VERSION; + 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 = VG_(getosreldate)(); +#endif prs->pr_cursig = si->si_signo; - prs->pr_pid = tst->os_state.lwpid; +#if !defined(VGO_freebsd) && !defined(VGO_openbsd) prs->pr_ppid = 0; prs->pr_pgrp = VG_(getpgrp)(); prs->pr_sid = VG_(getpgrp)(); +#endif #if defined(VGP_s390x_linux) /* prs->pr_reg has struct type. Need to take address. */ @@ -387,6 +417,46 @@ (void)arch; I_die_here; +#elif defined(VGP_amd64_freebsd) || (VGP_amd64_openbsd) + regs->rflags = LibVEX_GuestAMD64_get_rflags( &((ThreadArchState*)arch)->vex ); + regs->rsp = arch->vex.guest_RSP; + regs->rip = arch->vex.guest_RIP; + regs->rbx = arch->vex.guest_RBX; + regs->rcx = arch->vex.guest_RCX; + regs->rdx = arch->vex.guest_RDX; + regs->rsi = arch->vex.guest_RSI; + regs->rdi = arch->vex.guest_RDI; + regs->rbp = arch->vex.guest_RBP; + regs->rax = arch->vex.guest_RAX; + regs->r8 = arch->vex.guest_R8; + regs->r9 = arch->vex.guest_R9; + regs->r10 = arch->vex.guest_R10; + regs->r11 = arch->vex.guest_R11; + regs->r12 = arch->vex.guest_R12; + regs->r13 = arch->vex.guest_R13; + regs->r14 = arch->vex.guest_R14; + regs->r15 = arch->vex.guest_R15; + +#elif defined(VGP_x86_freebsd) || defined(VGP_x86_openbsd) + regs->eflags = LibVEX_GuestX86_get_eflags( &arch->vex ); + regs->esp = arch->vex.guest_ESP; + regs->eip = arch->vex.guest_EIP; + + regs->ebx = arch->vex.guest_EBX; + regs->ecx = arch->vex.guest_ECX; + regs->edx = arch->vex.guest_EDX; + regs->esi = arch->vex.guest_ESI; + regs->edi = arch->vex.guest_EDI; + regs->ebp = arch->vex.guest_EBP; + regs->eax = arch->vex.guest_EAX; + + regs->cs = arch->vex.guest_CS; + regs->ds = arch->vex.guest_DS; + regs->ss = arch->vex.guest_SS; + regs->es = arch->vex.guest_ES; + regs->fs = arch->vex.guest_FS; + regs->gs = arch->vex.guest_GS; + #elif defined(VGP_s390x_linux) # define DO(n) regs->gprs[n] = arch->vex.guest_r##n DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); @@ -496,6 +566,16 @@ #elif defined(VGP_arm64_linux) I_die_here; +#elif defined(VGP_x86_freebsd) || defined(VGP_x86_openbsd) + +#elif defined(VGP_amd64_freebsd) || defined(VGP_amd64_openbsd) + +# define DO(n) VG_(memcpy)(fpu->xmm_space + n * 4, \ + &arch->vex.guest_YMM##n[0], 16) + DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); + DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); +# undef DO + #elif defined(VGP_s390x_linux) # define DO(n) fpu->fprs[n].ui = arch->vex.guest_f##n DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); @@ -560,15 +640,20 @@ fill_fpu(&VG_(threads)[tid], &fpu); # if !defined(VGPV_arm_linux_android) && !defined(VGPV_x86_linux_android) \ - && !defined(VGPV_mips32_linux_android) + && !defined(VGPV_mips32_linux_android) && !defined(VGO_openbsd) add_note(notelist, "CORE", NT_FPREGSET, &fpu, sizeof(fpu)); # endif fill_prstatus(&VG_(threads)[tid], &prstatus, si); +# if defined(VGO_freebsd) + add_note(¬elist, "FreeBSD", NT_FPREGSET, &fpu, sizeof(fpu)); + add_note(¬elist, "FreeBSD", NT_PRSTATUS, &prstatus, sizeof(prstatus)); +# else # if !defined(VGPV_arm_linux_android) && !defined(VGPV_x86_linux_android) \ - && !defined(VGPV_mips32_linux_android) + && !defined(VGPV_mips32_linux_android) && !defined(VGO_openbsd) add_note(notelist, "CORE", NT_PRSTATUS, &prstatus, sizeof(prstatus)); # endif +# endif } static @@ -670,8 +755,12 @@ dump_one_thread(¬elist, si, tid); fill_prpsinfo(&VG_(threads)[tid], &prpsinfo); +#if defined(VGO_freebsd) + /* gdb doesn't care about the order of these, but some freebsd tools do. */ + add_note(¬elist, "FreeBSD", NT_PRPSINFO, &prpsinfo, sizeof(prpsinfo)); +#endif # if !defined(VGPV_arm_linux_android) && !defined(VGPV_x86_linux_android) \ - && !defined(VGPV_mips32_linux_android) + && !defined(VGPV_mips32_linux_android) && !defined(VGO_freebsd) add_note(¬elist, "CORE", NT_PRPSINFO, &prpsinfo, sizeof(prpsinfo)); # endif diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_debugger.c --- a/coregrind/m_debugger.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_debugger.c Thu Mar 31 15:57:55 2016 +0900 @@ -276,6 +276,12 @@ #elif defined(VGP_x86_darwin) I_die_here; +#elif defined(VGP_x86_freebsd) || defined(VGP_x86_openbsd) + I_die_here; + +#elif defined(VGP_amd64_freebsd) || defined(VGP_amd64_openbsd) + I_die_here; + #elif defined(VGP_amd64_darwin) I_die_here; diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_debuginfo/d3basics.c --- a/coregrind/m_debuginfo/d3basics.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_debuginfo/d3basics.c Thu Mar 31 15:57:55 2016 +0900 @@ -398,10 +398,10 @@ static Bool get_Dwarf_Reg( /*OUT*/Addr* a, Word regno, RegSummary* regs ) { vg_assert(regs); -# if defined(VGP_x86_linux) || defined(VGP_x86_darwin) +# if defined(VGP_x86_linux) || defined(VGP_x86_darwin) || defined(VGP_x86_freebsd) || defined(VGP_x86_openbsd) if (regno == 5/*EBP*/) { *a = regs->fp; return True; } if (regno == 4/*ESP*/) { *a = regs->sp; return True; } -# elif defined(VGP_amd64_linux) || defined(VGP_amd64_darwin) +# elif defined(VGP_amd64_linux) || defined(VGP_amd64_darwin) || defined(VGP_amd64_freebsd) || defined(VGP_amd64_openbsd) if (regno == 6/*RBP*/) { *a = regs->fp; return True; } if (regno == 7/*RSP*/) { *a = regs->sp; return True; } # elif defined(VGP_ppc32_linux) diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_debuginfo/debuginfo.c --- a/coregrind/m_debuginfo/debuginfo.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_debuginfo/debuginfo.c Thu Mar 31 15:57:55 2016 +0900 @@ -58,7 +58,7 @@ #include "priv_storage.h" #include "priv_readdwarf.h" #include "priv_readstabs.h" -#if defined(VGO_linux) +#if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd) # include "priv_readelf.h" # include "priv_readdwarf3.h" # include "priv_readpdb.h" @@ -599,7 +599,7 @@ /*--- ---*/ /*--------------------------------------------------------------*/ -#if defined(VGO_linux) || defined(VGO_darwin) +#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd) || defined(VGO_openbsd) /* The debug info system is driven by notifications that a text segment has been mapped in, or unmapped, or when sections change @@ -637,7 +637,7 @@ discard_DebugInfos_which_overlap_with( di ); /* .. and acquire new info. */ -# if defined(VGO_linux) +# if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd) ok = ML_(read_elf_debug_info)( di ); # elif defined(VGO_darwin) ok = ML_(read_macho_debug_info)( di ); @@ -718,6 +718,16 @@ vg_assert(use_fd >= -1); +#if defined(VGO_openbsd) + HChar *pathname; + char *VG_(pathname_by_fd)(Int fd); + + pathname = VG_(pathname_by_fd)(use_fd); + if (debug) + if (pathname != NULL) + VG_(printf)("di-notify_mmap-0: fd=%d filename=%s\n", use_fd, pathname); +#endif + /* In short, figure out if this mapping is of interest to us, and if so, try to guess what ld.so is doing and when/if we should read debug info. */ @@ -741,6 +751,10 @@ return 0; /* If the file doesn't have a name, we're hosed. Give up. */ +#if defined(VGO_openbsd) + filename = pathname; + if (!filename) +#endif filename = VG_(am_get_filename)( seg ); if (!filename) return 0; @@ -842,6 +856,9 @@ || defined(VGA_arm) || defined(VGA_arm64) is_rx_map = seg->hasR && seg->hasX && !seg->hasW; is_rw_map = seg->hasR && seg->hasW && !seg->hasX; +#if defined(VGO_openbsd) + is_ro_map = seg->hasR && !seg->hasW && !seg->hasX; +#endif # elif defined(VGP_s390x_linux) is_rx_map = seg->hasR && seg->hasX && !seg->hasW; is_rw_map = seg->hasR && seg->hasW; @@ -904,7 +921,7 @@ vg_assert(sr_Res(preadres) > 0 && sr_Res(preadres) <= sizeof(buf1k) ); /* We're only interested in mappings of object files. */ -# if defined(VGO_linux) +# if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd) if (!ML_(is_elf_object_file)( buf1k, (SizeT)sr_Res(preadres), False )) return 0; # elif defined(VGO_darwin) @@ -1316,7 +1333,7 @@ if (pdbname) ML_(dinfo_free)(pdbname); } -#endif /* defined(VGO_linux) || defined(VGO_darwin) */ +#endif /* defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd) || defined(VGO_openbsd) */ /*------------------------------------------------------------*/ @@ -1806,6 +1823,8 @@ # if defined(VGO_linux) VG_STREQ("__libc_start_main", name) || // glibc glibness VG_STREQ("generic_start_main", name) || // Yellow Dog doggedness +# elif defined(VGO_freebsd) || defined(VGO_openbsd) + VG_STREQ("_start", name) || // FreeBSD libc # elif defined(VGO_darwin) // See readmacho.c for an explanation of this. VG_STREQ("start_according_to_valgrind", name) || // Darwin, darling diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_debuginfo/priv_readpdb.h --- a/coregrind/m_debuginfo/priv_readpdb.h Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_debuginfo/priv_readpdb.h Thu Mar 31 15:57:55 2016 +0900 @@ -32,7 +32,7 @@ The GNU General Public License is contained in the file COPYING. */ -#if defined(VGO_linux) || defined(VGO_darwin) +#if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd) || defined(VGO_darwin) #ifndef __PRIV_READPDB_H #define __PRIV_READPDB_H @@ -59,7 +59,7 @@ #endif /* ndef __PRIV_READPDB_H */ -#endif // defined(VGO_linux) || defined(VGO_darwin) +#endif // defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd) || defined(VGO_darwin) /*--------------------------------------------------------------------*/ /*--- end ---*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_debuginfo/readdwarf.c --- a/coregrind/m_debuginfo/readdwarf.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_debuginfo/readdwarf.c Thu Mar 31 15:57:55 2016 +0900 @@ -29,7 +29,7 @@ The GNU General Public License is contained in the file COPYING. */ -#if defined(VGO_linux) || defined(VGO_darwin) +#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd) || defined(VGO_openbsd) #include "pub_core_basics.h" #include "pub_core_debuginfo.h" @@ -1723,11 +1723,11 @@ /* --------------- Decls --------------- */ -#if defined(VGP_x86_linux) +#if defined(VGP_x86_linux) || defined(VGP_x86_freebsd) || defined(VGP_x86_openbsd) # define FP_REG 5 # define SP_REG 4 # define RA_REG_DEFAULT 8 -#elif defined(VGP_amd64_linux) +#elif defined(VGP_amd64_linux) || defined(VGP_amd64_freebsd) || defined(VGP_amd64_openbsd) # define FP_REG 6 # define SP_REG 7 # define RA_REG_DEFAULT 16 @@ -4168,7 +4168,7 @@ return; } -#endif // defined(VGO_linux) || defined(VGO_darwin) +#endif // defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd) || defined(VGO_openbsd) /*--------------------------------------------------------------------*/ /*--- end ---*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_debuginfo/readdwarf3.c --- a/coregrind/m_debuginfo/readdwarf3.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_debuginfo/readdwarf3.c Thu Mar 31 15:57:55 2016 +0900 @@ -35,7 +35,7 @@ without prior written permission. */ -#if defined(VGO_linux) || defined(VGO_darwin) +#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd) || defined(VGO_openbsd) /* REFERENCE (without which this code will not make much sense): @@ -5235,7 +5235,7 @@ TRACE_SYMTAB("\n"); #endif -#endif // defined(VGO_linux) || defined(VGO_darwin) +#endif // defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd) || defined(VGO_openbsd) /*--------------------------------------------------------------------*/ /*--- end ---*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_debuginfo/readelf.c --- a/coregrind/m_debuginfo/readelf.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_debuginfo/readelf.c Thu Mar 31 15:57:55 2016 +0900 @@ -29,7 +29,7 @@ The GNU General Public License is contained in the file COPYING. */ -#if defined(VGO_linux) +#if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd) #include "pub_core_basics.h" #include "pub_core_vki.h" @@ -54,7 +54,11 @@ #include "priv_readexidx.h" /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */ +#if !defined(VGO_openbsd) #include +#else +#include +#endif /* --- !!! --- EXTERNAL HEADERS end --- !!! --- */ /*------------------------------------------------------------*/ @@ -397,7 +401,11 @@ if (sym_name_ioff == DiOffT_INVALID || /* VG_(strlen)(sym_name) == 0 */ /* equivalent but cheaper ... */ +#if defined(VGO_freebsd) + sym_name[0] == 0) { +#else ML_(img_get_UChar)(escn_strtab->img, sym_name_ioff) == '\0') { +#endif if (TRACE_SYMTAB_ENABLED) { HChar* sym_name = ML_(img_strdup)(escn_strtab->img, "di.gesi.1", sym_name_ioff); @@ -1604,13 +1612,13 @@ struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i); if (map->rx) TRACE_SYMTAB("rx_map: avma %#lx size %lu foff %lu\n", - map->avma, map->size, map->foff); + map->avma, (unsigned long)map->size, (unsigned long)map->foff); } for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) { struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i); if (map->rw) TRACE_SYMTAB("rw_map: avma %#lx size %lu foff %lu\n", - map->avma, map->size, map->foff); + map->avma, (unsigned long)map->size, (unsigned long)map->foff); } if (phdr_mnent == 0 @@ -1692,11 +1700,17 @@ Bool loaded = False; for (j = 0; j < VG_(sizeXA)(di->fsm.maps); j++) { struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, j); - if ( (map->rx || map->rw) +#if defined(VGO_openbsd) + /* Skip .bss LOAD entry. */ + if ( map->rw && a_phdr.p_filesz == 0 ) { + loaded = True; + } +#endif + if ( (map->rx || map->rw || map->ro) && a_phdr.p_offset >= map->foff && a_phdr.p_offset < map->foff + map->size - && a_phdr.p_offset + a_phdr.p_filesz - <= map->foff + map->size) { + && ((a_phdr.p_offset + a_phdr.p_filesz) & ~(VKI_PAGE_SIZE - 1)) <= map->foff + + map->size) { RangeAndBias item; item.svma_base = a_phdr.p_vaddr; item.svma_limit = a_phdr.p_vaddr + a_phdr.p_memsz; @@ -1718,6 +1732,16 @@ TRACE_SYMTAB("PT_LOAD[%ld]: acquired as rx\n", i); loaded = True; } +#if defined(VGO_openbsd) + if (map->ro + && (a_phdr.p_flags & (PF_R | PF_W | PF_X)) + == (PF_R)) { + item.exec = True; + VG_(addToXA)(svma_ranges, &item); + TRACE_SYMTAB("PT_LOAD[%ld]: acquired as ro\n", i); + loaded = True; + } +#endif } } if (!loaded) { @@ -1735,7 +1759,8 @@ } } - /* Try to get the soname. If there isn't one, use "NONE". + /* Try to get the soname. If there isn't one, try to use last + component of filename instead in DSO case. Otherwise use "NONE". The seginfo needs to have some kind of soname in order to facilitate writing redirect functions, since all redirect specifications require a soname (pattern). */ @@ -1790,8 +1815,19 @@ /* TOPLEVEL */ - /* If, after looking at all the program headers, we still didn't - find a soname, add a fake one. */ + if (di->soname == NULL && ehdr_m.e_type == ET_DYN && di->fsm.filename != NULL) { + char *filename = di->fsm.filename; + char *p = filename + VG_(strlen)(filename); + /* Extract last component. */ + while (*p != '/' && p > filename) + p--; + if (*p == '/') + p++; + if (*p != '\0') { + TRACE_SYMTAB("No soname found; using filename instead\n"); + di->soname = ML_(dinfo_strdup)("di.redi.1", p); + } + } if (di->soname == NULL) { TRACE_SYMTAB("No soname found; using (fake) \"NONE\"\n"); di->soname = ML_(dinfo_strdup)("di.redi.2", "NONE"); @@ -1806,7 +1842,7 @@ struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i); if (map->rx) TRACE_SYMTAB("rx: at %#lx are mapped foffsets %ld .. %ld\n", - map->avma, map->foff, map->foff + map->size - 1 ); + map->avma, (long)map->foff, (long)(map->foff + map->size - 1 )); } TRACE_SYMTAB("rx: contains these svma regions:\n"); for (i = 0; i < VG_(sizeXA)(svma_ranges); i++) { @@ -1819,7 +1855,7 @@ struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i); if (map->rw) TRACE_SYMTAB("rw: at %#lx are mapped foffsets %ld .. %ld\n", - map->avma, map->foff, map->foff + map->size - 1 ); + map->avma, (long)map->foff, (long)(map->foff + map->size - 1 )); } TRACE_SYMTAB("rw: contains these svma regions:\n"); for (i = 0; i < VG_(sizeXA)(svma_ranges); i++) { @@ -1864,7 +1900,7 @@ TRACE_SYMTAB(" [sec %2ld] %s %s al%2u foff %6ld .. %6ld " " svma %p name \"%s\"\n", i, inrx ? "rx" : " ", inrw ? "rw" : " ", alyn, - foff, foff+size-1, (void*)svma, name); + (unsigned long)foff, (unsigned long)(foff+size-1), (void*)svma, name); /* Check for sane-sized segments. SHT_NOBITS sections have zero size in the file. */ @@ -2158,6 +2194,8 @@ # if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \ || defined(VGP_arm_linux) || defined (VGP_s390x_linux) \ || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \ + || defined(VGP_x86_freebsd) || defined(VGP_amd64_freebsd) \ + || defined(VGP_x86_openbsd) || defined(VGP_amd64_openbsd) \ || defined(VGP_arm64_linux) /* Accept .plt where mapped as rx (code) */ if (0 == VG_(strcmp)(name, ".plt")) { @@ -2583,8 +2621,8 @@ struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, j); if ( a_phdr.p_offset >= map->foff && a_phdr.p_offset < map->foff + map->size - && a_phdr.p_offset + a_phdr.p_filesz - < map->foff + map->size) { + && ((a_phdr.p_offset + a_phdr.p_filesz) & ~(VKI_PAGE_SIZE - 1)) < map->foff + + map->size) { if (map->rx && rx_dsvma_limit == 0) { rx_dsvma_limit = a_phdr.p_vaddr + a_phdr.p_memsz; rx_dbias = map->avma - map->foff + a_phdr.p_offset @@ -2897,6 +2935,7 @@ && !defined(VGP_s390x_linux) \ && !defined(VGP_ppc64be_linux) \ && !defined(VGP_ppc64le_linux) \ + && !defined(VGP_amd64_freebsd) \ && !defined(VGPV_arm_linux_android) \ && !defined(VGPV_x86_linux_android) \ && !defined(VGP_mips64_linux) @@ -3036,7 +3075,7 @@ /* NOTREACHED */ } -#endif // defined(VGO_linux) +#endif // defined(VGO_linux) || defined(VGO_freebsd) /*--------------------------------------------------------------------*/ /*--- end ---*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_debuginfo/readpdb.c --- a/coregrind/m_debuginfo/readpdb.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_debuginfo/readpdb.c Thu Mar 31 15:57:55 2016 +0900 @@ -35,7 +35,7 @@ The GNU General Public License is contained in the file COPYING. */ -#if defined(VGO_linux) || defined(VGO_darwin) +#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd) || defined(VGO_openbsd) #include "pub_core_basics.h" #include "pub_core_debuginfo.h" @@ -2523,7 +2523,7 @@ return res; } -#endif // defined(VGO_linux) || defined(VGO_darwin) +#endif // defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd) /*--------------------------------------------------------------------*/ /*--- end ---*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_debuginfo/readstabs.c --- a/coregrind/m_debuginfo/readstabs.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_debuginfo/readstabs.c Thu Mar 31 15:57:55 2016 +0900 @@ -38,7 +38,7 @@ #if (defined(VGO_linux) && \ !(defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \ || defined(VGPV_mips32_linux_android)) \ - || defined(VGO_darwin)) + || defined(VGO_darwin) || defined(VGO_freebsd)) #include "pub_core_basics.h" #include "pub_core_debuginfo.h" @@ -73,6 +73,9 @@ # if VG_WORDSIZE == 8 # define nlist nlist_64 # endif +#elif defined(VGO_freebsd) +# include +# include #else # error "Unknown OS" #endif @@ -416,7 +419,7 @@ } #endif /* (defined(VGO_linux) && !defined(VGPV_*_linux_android)) \ - || defined(VGO_darwin) */ + || defined(VGO_darwin) || defined(VGO_freebsd) */ /*--------------------------------------------------------------------*/ /*--- end ---*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_debuginfo/storage.c --- a/coregrind/m_debuginfo/storage.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_debuginfo/storage.c Thu Mar 31 15:57:55 2016 +0900 @@ -325,6 +325,11 @@ vg_assert(sym->pri_name != NULL); vg_assert(sym->sec_names == NULL); +#if defined(VGO_freebsd) || defined(VGO_openbsd) + if (sym->size == 0) + sym->size = 1; +#endif + /* Ignore zero-sized syms. */ if (sym->size == 0) return; @@ -1446,7 +1451,7 @@ vlena = VG_(strlen)(a_name); vlenb = VG_(strlen)(b_name); -# if defined(VGO_linux) +# if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd) # define VERSION_CHAR '@' # elif defined(VGO_darwin) # define VERSION_CHAR '$' diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_debuglog.c --- a/coregrind/m_debuglog.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_debuglog.c Thu Mar 31 15:57:55 2016 +0900 @@ -428,6 +428,81 @@ return (UInt)(__res); } +#elif defined(VGP_x86_freebsd) || defined(VGP_x86_openbsd) +static UInt local_sys_write_stderr ( HChar* buf, Int n ) +{ + Int result; + + __asm__ volatile ( + "pushl %%ebx\n" + "movl $"VG_STRINGIFY(__NR_write)", %%eax\n" /* %eax = __NR_write */ + "movl $2, %%ebx\n" /* %ebx = stderr */ + "int $0x80\n" /* write(stderr, buf, n) */ + "popl %%ebx\n" + : /*wr*/ "=a" (result) + : /*rd*/ "c" (buf), "d" (n) + : /*trash*/ "edi", "memory", "cc" + ); + + return result >= 0 ? result : -1; +} + +static UInt local_sys_getpid ( void ) +{ + UInt __res; + __asm__ volatile ( + "movl $20, %%eax\n" /* set %eax = __NR_getpid */ + "int $0x80\n" /* getpid() */ + "movl %%eax, %0\n" /* set __res = eax */ + : "=mr" (__res) + : + : "eax" ); + return __res; +} + +#elif defined(VGP_amd64_freebsd) || defined(VGP_amd64_openbsd) +__attribute__((noinline)) +static UInt local_sys_write_stderr ( HChar* buf, Int n ) +{ + volatile Long block[2]; + block[0] = (Long)buf; + block[1] = n; + __asm__ volatile ( + "subq $256, %%rsp\n" /* don't trash the stack redzone */ + "pushq %%r15\n" /* r15 is callee-save */ + "movq %0, %%r15\n" /* r15 = &block */ + "pushq %%r15\n" /* save &block */ + "movq $"VG_STRINGIFY(__NR_write)", %%rax\n" /* rax = __NR_write */ + "movq $2, %%rdi\n" /* rdi = stderr */ + "movq 0(%%r15), %%rsi\n" /* rsi = buf */ + "movq 8(%%r15), %%rdx\n" /* rdx = n */ + "syscall\n" /* write(stderr, buf, n) */ + "popq %%r15\n" /* reestablish &block */ + "movq %%rax, 0(%%r15)\n" /* block[0] = result */ + "popq %%r15\n" /* restore r15 */ + "addq $256, %%rsp\n" /* restore stack ptr */ + : /*wr*/ + : /*rd*/ "g" (block) + : /*trash*/ "rax", "rdi", "rsi", "rdx", "memory", "cc" + ); + if (block[0] < 0) + block[0] = -1; + return (UInt)block[0]; +} + +static UInt local_sys_getpid ( void ) +{ + UInt __res; + __asm__ volatile ( + "movq $20, %%rax\n" /* set %rax = __NR_getpid */ + "syscall\n" /* getpid() */ + "movl %%eax, %0\n" /* set __res = %eax */ + : "=mr" (__res) + : + : "rax" ); + return __res; +} + #elif defined(VGP_mips32_linux) static UInt local_sys_write_stderr ( const HChar* buf, Int n ) diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_dispatch/dispatch-amd64-freebsd.S --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coregrind/m_dispatch/dispatch-amd64-freebsd.S Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,259 @@ + +/*--------------------------------------------------------------------*/ +/*--- The core dispatch loop, for jumping to a code address. ---*/ +/*--- dispatch-amd64-linux.S ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2012 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#if defined(VGP_amd64_freebsd) + +#include "pub_core_basics_asm.h" +#include "pub_core_dispatch_asm.h" +#include "pub_core_transtab_asm.h" +#include "libvex_guest_offsets.h" /* for OFFSET_amd64_RIP */ + + +/*------------------------------------------------------------*/ +/*--- ---*/ +/*--- The dispatch loop. VG_(disp_run_translations) is ---*/ +/*--- used to run all translations, ---*/ +/*--- including no-redir ones. ---*/ +/*--- ---*/ +/*------------------------------------------------------------*/ + +/*----------------------------------------------------*/ +/*--- Entry and preamble (set everything up) ---*/ +/*----------------------------------------------------*/ + +/* signature: +void VG_(disp_run_translations)( UWord* two_words, + void* guest_state, + Addr host_addr ); +*/ +.text +.globl VG_(disp_run_translations) +.type VG_(disp_run_translations), @function +VG_(disp_run_translations): + /* %rdi holds two_words */ + /* %rsi holds guest_state */ + /* %rdx holds host_addr */ + + /* The preamble */ + + /* Save integer registers, since this is a pseudo-function. */ + pushq %rax + pushq %rbx + pushq %rcx + pushq %rdx + pushq %rsi + pushq %rbp + pushq %r8 + pushq %r9 + pushq %r10 + pushq %r11 + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + /* %rdi must be saved last */ + pushq %rdi + + /* Get the host CPU in the state expected by generated code. */ + + /* set host FPU control word to the default mode expected + by VEX-generated code. See comments in libvex.h for + more info. */ + finit + pushq $0x027F + fldcw (%rsp) + addq $8, %rsp + + /* set host SSE control word to the default mode expected + by VEX-generated code. */ + pushq $0x1F80 + ldmxcsr (%rsp) + addq $8, %rsp + + /* set dir flag to known value */ + cld + + /* Set up the guest state pointer */ + movq %rsi, %rbp + + /* and jump into the code cache. Chained translations in + the code cache run, until for whatever reason, they can't + continue. When that happens, the translation in question + will jump (or call) to one of the continuation points + VG_(cp_...) below. */ + jmpq *%rdx + /*NOTREACHED*/ + +/*----------------------------------------------------*/ +/*--- Postamble and exit. ---*/ +/*----------------------------------------------------*/ + +postamble: + /* At this point, %rax and %rdx contain two + words to be returned to the caller. %rax + holds a TRC value, and %rdx optionally may + hold another word (for CHAIN_ME exits, the + address of the place to patch.) */ + + /* We're leaving. Check that nobody messed with %mxcsr + or %fpucw. We can't mess with %rax or %rdx here as they + hold the tentative return values, but any others are OK. */ +#if !defined(ENABLE_INNER) + /* This check fails for self-hosting, so skip in that case */ + pushq $0 + fstcw (%rsp) + cmpl $0x027F, (%rsp) + popq %r15 /* get rid of the word without trashing %rflags */ + jnz invariant_violation +#endif + pushq $0 + stmxcsr (%rsp) + andl $0xFFFFFFC0, (%rsp) /* mask out status flags */ + cmpl $0x1F80, (%rsp) + popq %r15 + jnz invariant_violation + /* otherwise we're OK */ + jmp remove_frame +invariant_violation: + movq $VG_TRC_INVARIANT_FAILED, %rax + movq $0, %rdx + +remove_frame: + /* Pop %rdi, stash return values */ + popq %rdi + movq %rax, 0(%rdi) + movq %rdx, 8(%rdi) + /* Now pop everything else */ + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %r11 + popq %r10 + popq %r9 + popq %r8 + popq %rbp + popq %rsi + popq %rdx + popq %rcx + popq %rbx + popq %rax + ret + +/*----------------------------------------------------*/ +/*--- Continuation points ---*/ +/*----------------------------------------------------*/ + +/* ------ Chain me to slow entry point ------ */ +.global VG_(disp_cp_chain_me_to_slowEP) +VG_(disp_cp_chain_me_to_slowEP): + /* We got called. The return address indicates + where the patching needs to happen. Collect + the return address and, exit back to C land, + handing the caller the pair (Chain_me_S, RA) */ + movq $VG_TRC_CHAIN_ME_TO_SLOW_EP, %rax + popq %rdx + /* 10 = movabsq $VG_(disp_chain_me_to_slowEP), %r11; + 3 = call *%r11 */ + subq $10+3, %rdx + jmp postamble + +/* ------ Chain me to fast entry point ------ */ +.global VG_(disp_cp_chain_me_to_fastEP) +VG_(disp_cp_chain_me_to_fastEP): + /* We got called. The return address indicates + where the patching needs to happen. Collect + the return address and, exit back to C land, + handing the caller the pair (Chain_me_F, RA) */ + movq $VG_TRC_CHAIN_ME_TO_FAST_EP, %rax + popq %rdx + /* 10 = movabsq $VG_(disp_chain_me_to_fastEP), %r11; + 3 = call *%r11 */ + subq $10+3, %rdx + jmp postamble + +/* ------ Indirect but boring jump ------ */ +.global VG_(disp_cp_xindir) +VG_(disp_cp_xindir): + /* Where are we going? */ + movq OFFSET_amd64_RIP(%rbp), %rax + + /* stats only */ + addl $1, VG_(stats__n_xindirs_32) + + /* try a fast lookup in the translation cache */ + movabsq $VG_(tt_fast), %rcx + movq %rax, %rbx /* next guest addr */ + andq $VG_TT_FAST_MASK, %rbx /* entry# */ + shlq $4, %rbx /* entry# * sizeof(FastCacheEntry) */ + movq 0(%rcx,%rbx,1), %r10 /* .guest */ + movq 8(%rcx,%rbx,1), %r11 /* .host */ + cmpq %rax, %r10 + jnz fast_lookup_failed + + /* Found a match. Jump to .host. */ + jmp *%r11 + ud2 /* persuade insn decoders not to speculate past here */ + +fast_lookup_failed: + /* stats only */ + addl $1, VG_(stats__n_xindir_misses_32) + + movq $VG_TRC_INNER_FASTMISS, %rax + movq $0, %rdx + jmp postamble + +/* ------ Assisted jump ------ */ +.global VG_(disp_cp_xassisted) +VG_(disp_cp_xassisted): + /* %rbp contains the TRC */ + movq %rbp, %rax + movq $0, %rdx + jmp postamble + +/* ------ Event check failed ------ */ +.global VG_(disp_cp_evcheck_fail) +VG_(disp_cp_evcheck_fail): + movq $VG_TRC_INNER_COUNTERZERO, %rax + movq $0, %rdx + jmp postamble + + +.size VG_(disp_run_translations), .-VG_(disp_run_translations) + +/* Let the linker know we don't need an executable stack */ +.section .note.GNU-stack,"",@progbits + +#endif // defined(VGP_amd64_linux) + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_dispatch/dispatch-amd64-openbsd.S --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coregrind/m_dispatch/dispatch-amd64-openbsd.S Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,259 @@ + +/*--------------------------------------------------------------------*/ +/*--- The core dispatch loop, for jumping to a code address. ---*/ +/*--- dispatch-amd64-linux.S ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2012 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#if defined(VGP_amd64_openbsd) + +#include "pub_core_basics_asm.h" +#include "pub_core_dispatch_asm.h" +#include "pub_core_transtab_asm.h" +#include "libvex_guest_offsets.h" /* for OFFSET_amd64_RIP */ + + +/*------------------------------------------------------------*/ +/*--- ---*/ +/*--- The dispatch loop. VG_(disp_run_translations) is ---*/ +/*--- used to run all translations, ---*/ +/*--- including no-redir ones. ---*/ +/*--- ---*/ +/*------------------------------------------------------------*/ + +/*----------------------------------------------------*/ +/*--- Entry and preamble (set everything up) ---*/ +/*----------------------------------------------------*/ + +/* signature: +void VG_(disp_run_translations)( UWord* two_words, + void* guest_state, + Addr host_addr ); +*/ +.text +.globl VG_(disp_run_translations) +.type VG_(disp_run_translations), @function +VG_(disp_run_translations): + /* %rdi holds two_words */ + /* %rsi holds guest_state */ + /* %rdx holds host_addr */ + + /* The preamble */ + + /* Save integer registers, since this is a pseudo-function. */ + pushq %rax + pushq %rbx + pushq %rcx + pushq %rdx + pushq %rsi + pushq %rbp + pushq %r8 + pushq %r9 + pushq %r10 + pushq %r11 + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + /* %rdi must be saved last */ + pushq %rdi + + /* Get the host CPU in the state expected by generated code. */ + + /* set host FPU control word to the default mode expected + by VEX-generated code. See comments in libvex.h for + more info. */ + finit + pushq $0x027F + fldcw (%rsp) + addq $8, %rsp + + /* set host SSE control word to the default mode expected + by VEX-generated code. */ + pushq $0x1F80 + ldmxcsr (%rsp) + addq $8, %rsp + + /* set dir flag to known value */ + cld + + /* Set up the guest state pointer */ + movq %rsi, %rbp + + /* and jump into the code cache. Chained translations in + the code cache run, until for whatever reason, they can't + continue. When that happens, the translation in question + will jump (or call) to one of the continuation points + VG_(cp_...) below. */ + jmpq *%rdx + /*NOTREACHED*/ + +/*----------------------------------------------------*/ +/*--- Postamble and exit. ---*/ +/*----------------------------------------------------*/ + +postamble: + /* At this point, %rax and %rdx contain two + words to be returned to the caller. %rax + holds a TRC value, and %rdx optionally may + hold another word (for CHAIN_ME exits, the + address of the place to patch.) */ + + /* We're leaving. Check that nobody messed with %mxcsr + or %fpucw. We can't mess with %rax or %rdx here as they + hold the tentative return values, but any others are OK. */ +#if !defined(ENABLE_INNER) + /* This check fails for self-hosting, so skip in that case */ + pushq $0 + fstcw (%rsp) + cmpl $0x027F, (%rsp) + popq %r15 /* get rid of the word without trashing %rflags */ + jnz invariant_violation +#endif + pushq $0 + stmxcsr (%rsp) + andl $0xFFFFFFC0, (%rsp) /* mask out status flags */ + cmpl $0x1F80, (%rsp) + popq %r15 + jnz invariant_violation + /* otherwise we're OK */ + jmp remove_frame +invariant_violation: + movq $VG_TRC_INVARIANT_FAILED, %rax + movq $0, %rdx + +remove_frame: + /* Pop %rdi, stash return values */ + popq %rdi + movq %rax, 0(%rdi) + movq %rdx, 8(%rdi) + /* Now pop everything else */ + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %r11 + popq %r10 + popq %r9 + popq %r8 + popq %rbp + popq %rsi + popq %rdx + popq %rcx + popq %rbx + popq %rax + ret + +/*----------------------------------------------------*/ +/*--- Continuation points ---*/ +/*----------------------------------------------------*/ + +/* ------ Chain me to slow entry point ------ */ +.global VG_(disp_cp_chain_me_to_slowEP) +VG_(disp_cp_chain_me_to_slowEP): + /* We got called. The return address indicates + where the patching needs to happen. Collect + the return address and, exit back to C land, + handing the caller the pair (Chain_me_S, RA) */ + movq $VG_TRC_CHAIN_ME_TO_SLOW_EP, %rax + popq %rdx + /* 10 = movabsq $VG_(disp_chain_me_to_slowEP), %r11; + 3 = call *%r11 */ + subq $10+3, %rdx + jmp postamble + +/* ------ Chain me to fast entry point ------ */ +.global VG_(disp_cp_chain_me_to_fastEP) +VG_(disp_cp_chain_me_to_fastEP): + /* We got called. The return address indicates + where the patching needs to happen. Collect + the return address and, exit back to C land, + handing the caller the pair (Chain_me_F, RA) */ + movq $VG_TRC_CHAIN_ME_TO_FAST_EP, %rax + popq %rdx + /* 10 = movabsq $VG_(disp_chain_me_to_fastEP), %r11; + 3 = call *%r11 */ + subq $10+3, %rdx + jmp postamble + +/* ------ Indirect but boring jump ------ */ +.global VG_(disp_cp_xindir) +VG_(disp_cp_xindir): + /* Where are we going? */ + movq OFFSET_amd64_RIP(%rbp), %rax + + /* stats only */ + addl $1, VG_(stats__n_xindirs_32) + + /* try a fast lookup in the translation cache */ + movabsq $VG_(tt_fast), %rcx + movq %rax, %rbx /* next guest addr */ + andq $VG_TT_FAST_MASK, %rbx /* entry# */ + shlq $4, %rbx /* entry# * sizeof(FastCacheEntry) */ + movq 0(%rcx,%rbx,1), %r10 /* .guest */ + movq 8(%rcx,%rbx,1), %r11 /* .host */ + cmpq %rax, %r10 + jnz fast_lookup_failed + + /* Found a match. Jump to .host. */ + jmp *%r11 + ud2 /* persuade insn decoders not to speculate past here */ + +fast_lookup_failed: + /* stats only */ + addl $1, VG_(stats__n_xindir_misses_32) + + movq $VG_TRC_INNER_FASTMISS, %rax + movq $0, %rdx + jmp postamble + +/* ------ Assisted jump ------ */ +.global VG_(disp_cp_xassisted) +VG_(disp_cp_xassisted): + /* %rbp contains the TRC */ + movq %rbp, %rax + movq $0, %rdx + jmp postamble + +/* ------ Event check failed ------ */ +.global VG_(disp_cp_evcheck_fail) +VG_(disp_cp_evcheck_fail): + movq $VG_TRC_INNER_COUNTERZERO, %rax + movq $0, %rdx + jmp postamble + + +.size VG_(disp_run_translations), .-VG_(disp_run_translations) + +/* Let the linker know we don't need an executable stack */ +.section .note.GNU-stack,"",@progbits + +#endif // defined(VGP_amd64_linux) + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_dispatch/dispatch-x86-freebsd.S --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coregrind/m_dispatch/dispatch-x86-freebsd.S Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,250 @@ + +/*--------------------------------------------------------------------*/ +/*--- The core dispatch loop, for jumping to a code address. ---*/ +/*--- dispatch-x86-linux.S ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2012 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#if defined(VGP_x86_freebsd) + +#include "pub_core_basics_asm.h" +#include "pub_core_dispatch_asm.h" +#include "pub_core_transtab_asm.h" +#include "libvex_guest_offsets.h" /* for OFFSET_x86_EIP */ + + +/*------------------------------------------------------------*/ +/*--- ---*/ +/*--- The dispatch loop. VG_(disp_run_translations) is ---*/ +/*--- used to run all translations, ---*/ +/*--- including no-redir ones. ---*/ +/*--- ---*/ +/*------------------------------------------------------------*/ + +/*----------------------------------------------------*/ +/*--- Entry and preamble (set everything up) ---*/ +/*----------------------------------------------------*/ + +/* signature: +void VG_(disp_run_translations)( UWord* two_words, + void* guest_state, + Addr host_addr ); +*/ +.text +.globl VG_(disp_run_translations) +.type VG_(disp_run_translations), @function +VG_(disp_run_translations): + /* 0(%esp) holds our return address. */ + /* 4(%esp) holds two_words */ + /* 8(%esp) holds guest_state */ + /* 12(%esp) holds host_addr */ + + /* The preamble */ + + /* Save integer registers, since this is a pseudo-function. */ + pushl %eax + pushl %ebx + pushl %ecx + pushl %edx + pushl %esi + pushl %edi + pushl %ebp + + /* 28+4(%esp) holds two_words */ + /* 28+8(%esp) holds guest_state */ + /* 28+12(%esp) holds host_addr */ + + /* Get the host CPU in the state expected by generated code. */ + + /* set host FPU control word to the default mode expected + by VEX-generated code. See comments in libvex.h for + more info. */ + finit + pushl $0x027F + fldcw (%esp) + addl $4, %esp + + /* set host SSE control word to the default mode expected + by VEX-generated code. */ + cmpl $0, VG_(machine_x86_have_mxcsr) + jz L1 + pushl $0x1F80 + ldmxcsr (%esp) + addl $4, %esp +L1: + /* set dir flag to known value */ + cld + + /* Set up the guest state pointer */ + movl 28+8(%esp), %ebp + + /* and jump into the code cache. Chained translations in + the code cache run, until for whatever reason, they can't + continue. When that happens, the translation in question + will jump (or call) to one of the continuation points + VG_(cp_...) below. */ + jmpl *28+12(%esp) + /*NOTREACHED*/ + +/*----------------------------------------------------*/ +/*--- Postamble and exit. ---*/ +/*----------------------------------------------------*/ + +postamble: + /* At this point, %eax and %edx contain two + words to be returned to the caller. %eax + holds a TRC value, and %edx optionally may + hold another word (for CHAIN_ME exits, the + address of the place to patch.) */ + + /* We're leaving. Check that nobody messed with %mxcsr + or %fpucw. We can't mess with %eax or %edx here as they + holds the tentative return value, but any others are OK. */ +#if !defined(ENABLE_INNER) + /* This check fails for self-hosting, so skip in that case */ + pushl $0 + fstcw (%esp) + cmpl $0x027F, (%esp) + popl %esi /* get rid of the word without trashing %eflags */ + jnz invariant_violation +#endif +# cmpl $0, VG_(machine_x86_have_mxcsr) + jz L2 + pushl $0 + stmxcsr (%esp) + andl $0xFFFFFFC0, (%esp) /* mask out status flags */ + cmpl $0x1F80, (%esp) + popl %esi + jnz invariant_violation +L2: /* otherwise we're OK */ + jmp remove_frame +invariant_violation: + movl $VG_TRC_INVARIANT_FAILED, %eax + movl $0, %edx + +remove_frame: + /* Stash return values */ + movl 28+4(%esp), %edi /* two_words */ + movl %eax, 0(%edi) + movl %edx, 4(%edi) + /* Restore int regs and return. */ + popl %ebp + popl %edi + popl %esi + popl %edx + popl %ecx + popl %ebx + popl %eax + ret + +/*----------------------------------------------------*/ +/*--- Continuation points ---*/ +/*----------------------------------------------------*/ + +/* ------ Chain me to slow entry point ------ */ +.global VG_(disp_cp_chain_me_to_slowEP) +VG_(disp_cp_chain_me_to_slowEP): + /* We got called. The return address indicates + where the patching needs to happen. Collect + the return address and, exit back to C land, + handing the caller the pair (Chain_me_S, RA) */ + movl $VG_TRC_CHAIN_ME_TO_SLOW_EP, %eax + popl %edx + /* 5 = movl $VG_(disp_chain_me_to_slowEP), %edx; + 2 = call *%edx */ + subl $5+2, %edx + jmp postamble + +/* ------ Chain me to fast entry point ------ */ +.global VG_(disp_cp_chain_me_to_fastEP) +VG_(disp_cp_chain_me_to_fastEP): + /* We got called. The return address indicates + where the patching needs to happen. Collect + the return address and, exit back to C land, + handing the caller the pair (Chain_me_F, RA) */ + movl $VG_TRC_CHAIN_ME_TO_FAST_EP, %eax + popl %edx + /* 5 = movl $VG_(disp_chain_me_to_fastEP), %edx; + 2 = call *%edx */ + subl $5+2, %edx + jmp postamble + +/* ------ Indirect but boring jump ------ */ +.global VG_(disp_cp_xindir) +VG_(disp_cp_xindir): + /* Where are we going? */ + movl OFFSET_x86_EIP(%ebp), %eax + + /* stats only */ + addl $1, VG_(stats__n_xindirs_32) + + /* try a fast lookup in the translation cache */ + movl %eax, %ebx /* next guest addr */ + andl $VG_TT_FAST_MASK, %ebx /* entry# */ + movl 0+VG_(tt_fast)(,%ebx,8), %esi /* .guest */ + movl 4+VG_(tt_fast)(,%ebx,8), %edi /* .host */ + cmpl %eax, %esi + jnz fast_lookup_failed + + /* Found a match. Jump to .host. */ + jmp *%edi + ud2 /* persuade insn decoders not to speculate past here */ + +fast_lookup_failed: + /* stats only */ + addl $1, VG_(stats__n_xindir_misses_32) + + movl $VG_TRC_INNER_FASTMISS, %eax + movl $0, %edx + jmp postamble + +/* ------ Assisted jump ------ */ +.global VG_(disp_cp_xassisted) +VG_(disp_cp_xassisted): + /* %ebp contains the TRC */ + movl %ebp, %eax + movl $0, %edx + jmp postamble + +/* ------ Event check failed ------ */ +.global VG_(disp_cp_evcheck_fail) +VG_(disp_cp_evcheck_fail): + movl $VG_TRC_INNER_COUNTERZERO, %eax + movl $0, %edx + jmp postamble + + +.size VG_(disp_run_translations), .-VG_(disp_run_translations) + +/* Let the linker know we don't need an executable stack */ +.section .note.GNU-stack,"",@progbits + +#endif // defined(VGP_x86_linux) + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_dispatch/dispatch-x86-openbsd.S --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coregrind/m_dispatch/dispatch-x86-openbsd.S Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,250 @@ + +/*--------------------------------------------------------------------*/ +/*--- The core dispatch loop, for jumping to a code address. ---*/ +/*--- dispatch-x86-linux.S ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2012 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#if defined(VGP_x86_openbsd) + +#include "pub_core_basics_asm.h" +#include "pub_core_dispatch_asm.h" +#include "pub_core_transtab_asm.h" +#include "libvex_guest_offsets.h" /* for OFFSET_x86_EIP */ + + +/*------------------------------------------------------------*/ +/*--- ---*/ +/*--- The dispatch loop. VG_(disp_run_translations) is ---*/ +/*--- used to run all translations, ---*/ +/*--- including no-redir ones. ---*/ +/*--- ---*/ +/*------------------------------------------------------------*/ + +/*----------------------------------------------------*/ +/*--- Entry and preamble (set everything up) ---*/ +/*----------------------------------------------------*/ + +/* signature: +void VG_(disp_run_translations)( UWord* two_words, + void* guest_state, + Addr host_addr ); +*/ +.text +.globl VG_(disp_run_translations) +.type VG_(disp_run_translations), @function +VG_(disp_run_translations): + /* 0(%esp) holds our return address. */ + /* 4(%esp) holds two_words */ + /* 8(%esp) holds guest_state */ + /* 12(%esp) holds host_addr */ + + /* The preamble */ + + /* Save integer registers, since this is a pseudo-function. */ + pushl %eax + pushl %ebx + pushl %ecx + pushl %edx + pushl %esi + pushl %edi + pushl %ebp + + /* 28+4(%esp) holds two_words */ + /* 28+8(%esp) holds guest_state */ + /* 28+12(%esp) holds host_addr */ + + /* Get the host CPU in the state expected by generated code. */ + + /* set host FPU control word to the default mode expected + by VEX-generated code. See comments in libvex.h for + more info. */ + finit + pushl $0x027F + fldcw (%esp) + addl $4, %esp + + /* set host SSE control word to the default mode expected + by VEX-generated code. */ + cmpl $0, VG_(machine_x86_have_mxcsr) + jz L1 + pushl $0x1F80 + ldmxcsr (%esp) + addl $4, %esp +L1: + /* set dir flag to known value */ + cld + + /* Set up the guest state pointer */ + movl 28+8(%esp), %ebp + + /* and jump into the code cache. Chained translations in + the code cache run, until for whatever reason, they can't + continue. When that happens, the translation in question + will jump (or call) to one of the continuation points + VG_(cp_...) below. */ + jmpl *28+12(%esp) + /*NOTREACHED*/ + +/*----------------------------------------------------*/ +/*--- Postamble and exit. ---*/ +/*----------------------------------------------------*/ + +postamble: + /* At this point, %eax and %edx contain two + words to be returned to the caller. %eax + holds a TRC value, and %edx optionally may + hold another word (for CHAIN_ME exits, the + address of the place to patch.) */ + + /* We're leaving. Check that nobody messed with %mxcsr + or %fpucw. We can't mess with %eax or %edx here as they + holds the tentative return value, but any others are OK. */ +#if !defined(ENABLE_INNER) + /* This check fails for self-hosting, so skip in that case */ + pushl $0 + fstcw (%esp) + cmpl $0x027F, (%esp) + popl %esi /* get rid of the word without trashing %eflags */ + jnz invariant_violation +#endif +# cmpl $0, VG_(machine_x86_have_mxcsr) + jz L2 + pushl $0 + stmxcsr (%esp) + andl $0xFFFFFFC0, (%esp) /* mask out status flags */ + cmpl $0x1F80, (%esp) + popl %esi + jnz invariant_violation +L2: /* otherwise we're OK */ + jmp remove_frame +invariant_violation: + movl $VG_TRC_INVARIANT_FAILED, %eax + movl $0, %edx + +remove_frame: + /* Stash return values */ + movl 28+4(%esp), %edi /* two_words */ + movl %eax, 0(%edi) + movl %edx, 4(%edi) + /* Restore int regs and return. */ + popl %ebp + popl %edi + popl %esi + popl %edx + popl %ecx + popl %ebx + popl %eax + ret + +/*----------------------------------------------------*/ +/*--- Continuation points ---*/ +/*----------------------------------------------------*/ + +/* ------ Chain me to slow entry point ------ */ +.global VG_(disp_cp_chain_me_to_slowEP) +VG_(disp_cp_chain_me_to_slowEP): + /* We got called. The return address indicates + where the patching needs to happen. Collect + the return address and, exit back to C land, + handing the caller the pair (Chain_me_S, RA) */ + movl $VG_TRC_CHAIN_ME_TO_SLOW_EP, %eax + popl %edx + /* 5 = movl $VG_(disp_chain_me_to_slowEP), %edx; + 2 = call *%edx */ + subl $5+2, %edx + jmp postamble + +/* ------ Chain me to fast entry point ------ */ +.global VG_(disp_cp_chain_me_to_fastEP) +VG_(disp_cp_chain_me_to_fastEP): + /* We got called. The return address indicates + where the patching needs to happen. Collect + the return address and, exit back to C land, + handing the caller the pair (Chain_me_F, RA) */ + movl $VG_TRC_CHAIN_ME_TO_FAST_EP, %eax + popl %edx + /* 5 = movl $VG_(disp_chain_me_to_fastEP), %edx; + 2 = call *%edx */ + subl $5+2, %edx + jmp postamble + +/* ------ Indirect but boring jump ------ */ +.global VG_(disp_cp_xindir) +VG_(disp_cp_xindir): + /* Where are we going? */ + movl OFFSET_x86_EIP(%ebp), %eax + + /* stats only */ + addl $1, VG_(stats__n_xindirs_32) + + /* try a fast lookup in the translation cache */ + movl %eax, %ebx /* next guest addr */ + andl $VG_TT_FAST_MASK, %ebx /* entry# */ + movl 0+VG_(tt_fast)(,%ebx,8), %esi /* .guest */ + movl 4+VG_(tt_fast)(,%ebx,8), %edi /* .host */ + cmpl %eax, %esi + jnz fast_lookup_failed + + /* Found a match. Jump to .host. */ + jmp *%edi + ud2 /* persuade insn decoders not to speculate past here */ + +fast_lookup_failed: + /* stats only */ + addl $1, VG_(stats__n_xindir_misses_32) + + movl $VG_TRC_INNER_FASTMISS, %eax + movl $0, %edx + jmp postamble + +/* ------ Assisted jump ------ */ +.global VG_(disp_cp_xassisted) +VG_(disp_cp_xassisted): + /* %ebp contains the TRC */ + movl %ebp, %eax + movl $0, %edx + jmp postamble + +/* ------ Event check failed ------ */ +.global VG_(disp_cp_evcheck_fail) +VG_(disp_cp_evcheck_fail): + movl $VG_TRC_INNER_COUNTERZERO, %eax + movl $0, %edx + jmp postamble + + +.size VG_(disp_run_translations), .-VG_(disp_run_translations) + +/* Let the linker know we don't need an executable stack */ +.section .note.GNU-stack,"",@progbits + +#endif // defined(VGP_x86_linux) + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_gdbserver/remote-utils.c --- a/coregrind/m_gdbserver/remote-utils.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_gdbserver/remote-utils.c Thu Mar 31 15:57:55 2016 +0900 @@ -260,7 +260,11 @@ void safe_mknod (char *nod) { SysRes m; +#if defined(VGO_openbsd) || defined(VGO_netbsd) + m = VG_(mkfifo) (nod, 0600); +#else m = VG_(mknod) (nod, VKI_S_IFIFO|0600, 0); +#endif if (sr_isError (m)) { if (sr_Err (m) == VKI_EEXIST) { if (VG_(clo_verbosity) > 1) { diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_initimg/initimg-freebsd.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coregrind/m_initimg/initimg-freebsd.c Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,895 @@ + +/*--------------------------------------------------------------------*/ +/*--- Startup: create initial process image on Linux ---*/ +/*--- initimg-freebsd.c ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2009 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#if defined(VGO_freebsd) + +#include "pub_core_basics.h" +#include "pub_core_vki.h" +#include "pub_core_debuglog.h" +#include "pub_core_libcbase.h" +#include "pub_core_libcassert.h" +#include "pub_core_libcfile.h" +#include "pub_core_libcproc.h" +#include "pub_core_libcprint.h" +#include "pub_core_xarray.h" +#include "pub_core_clientstate.h" +#include "pub_core_aspacemgr.h" +#include "pub_core_mallocfree.h" +#include "pub_core_machine.h" +#include "pub_core_ume.h" +#include "pub_core_options.h" +#include "pub_core_syscall.h" +#include "pub_core_tooliface.h" /* VG_TRACK */ +#include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy +#include "pub_core_threadstate.h" /* ThreadArchState */ +#include "priv_initimg_pathscan.h" +#include "pub_core_initimg.h" /* self */ + +/* --- !!! --- EXTERNAL HEADERS start --- !!! --- */ +#define _GNU_SOURCE +#define _FILE_OFFSET_BITS 64 +/* This is for ELF types etc, and also the AT_ constants. */ +#include +/* --- !!! --- EXTERNAL HEADERS end --- !!! --- */ + + +/*====================================================================*/ +/*=== Loading the client ===*/ +/*====================================================================*/ + +/* Load the client whose name is VG_(argv_the_exename). */ + +static void load_client ( /*OUT*/ExeInfo* info, + /*OUT*/Addr* client_ip, + /*OUT*/Addr* client_toc) +{ + HChar* exe_name; + Int ret; + SysRes res; + + vg_assert( VG_(args_the_exename) != NULL); + exe_name = ML_(find_executable)( VG_(args_the_exename) ); + + if (!exe_name) { + VG_(printf)("valgrind: %s: command not found\n", VG_(args_the_exename)); + VG_(exit)(127); // 127 is Posix NOTFOUND + } + + VG_(memset)(info, 0, sizeof(*info)); + ret = VG_(do_exec)(exe_name, info); + if (ret < 0) { + VG_(printf)("valgrind: could not execute '%s'\n", exe_name); + VG_(exit)(1); + } + + // The client was successfully loaded! Continue. + + /* Get hold of a file descriptor which refers to the client + executable. This is needed for attaching to GDB. */ + res = VG_(open)(exe_name, VKI_O_RDONLY, VKI_S_IRUSR); + if (!sr_isError(res)) + VG_(cl_exec_fd) = sr_Res(res); + + /* Copy necessary bits of 'info' that were filled in */ + *client_ip = info->init_ip; + *client_toc = info->init_toc; + VG_(brk_base) = VG_(brk_limit) = VG_PGROUNDUP(info->brkbase); +} + + +/*====================================================================*/ +/*=== Setting up the client's environment ===*/ +/*====================================================================*/ + +/* Prepare the client's environment. This is basically a copy of our + environment, except: + + LD_PRELOAD=$VALGRIND_LIB/vgpreload_core-PLATFORM.so: + ($VALGRIND_LIB/vgpreload_TOOL-PLATFORM.so:)? + $LD_PRELOAD + + If this is missing, then it is added. + + Also, remove any binding for VALGRIND_LAUNCHER=. The client should + not be able to see this. + + If this needs to handle any more variables it should be hacked + into something table driven. The copy is VG_(malloc)'d space. +*/ +static HChar** setup_client_env ( HChar** origenv, const HChar* toolname) +{ + HChar* preload_core = "vgpreload_core"; + HChar* ld_preload = "LD_PRELOAD="; + HChar* v_launcher = VALGRIND_LAUNCHER "="; + Int ld_preload_len = VG_(strlen)( ld_preload ); + Int v_launcher_len = VG_(strlen)( v_launcher ); + Bool ld_preload_done = False; +#if defined(VGP_x86_freebsd) + HChar* ld_32_preload = "LD_32_PRELOAD="; + Int ld_32_preload_len = VG_(strlen)( ld_32_preload ); + Bool ld_32_preload_done = False; +#endif + Int vglib_len = VG_(strlen)(VG_(libdir)); + + HChar** cpp; + HChar** ret; + HChar* preload_tool_path; + Int envc, i; + + /* Alloc space for the vgpreload_core.so path and vgpreload_.so + paths. We might not need the space for vgpreload_.so, but it + doesn't hurt to over-allocate briefly. The 16s are just cautious + slop. */ + Int preload_core_path_len = vglib_len + sizeof(preload_core) + + sizeof(VG_PLATFORM) + 16; + Int preload_tool_path_len = vglib_len + VG_(strlen)(toolname) + + sizeof(VG_PLATFORM) + 16; + Int preload_string_len = preload_core_path_len + preload_tool_path_len; + HChar* preload_string = VG_(malloc)("initimg-freebsd.sce.1", + preload_string_len); + vg_assert(origenv); + vg_assert(toolname); + vg_assert(preload_string); + + /* Determine if there's a vgpreload__.so file, and setup + preload_string. */ + preload_tool_path = VG_(malloc)("initimg-freebsd.sce.2", preload_tool_path_len); + vg_assert(preload_tool_path); + VG_(snprintf)(preload_tool_path, preload_tool_path_len, + "%s/vgpreload_%s-%s.so", VG_(libdir), toolname, VG_PLATFORM); + if (VG_(access)(preload_tool_path, True/*r*/, False/*w*/, False/*x*/) == 0) { + VG_(snprintf)(preload_string, preload_string_len, "%s/%s-%s.so:%s", + VG_(libdir), preload_core, VG_PLATFORM, preload_tool_path); + } else { + VG_(snprintf)(preload_string, preload_string_len, "%s/%s-%s.so", + VG_(libdir), preload_core, VG_PLATFORM); + } + VG_(free)(preload_tool_path); + + VG_(debugLog)(2, "initimg", "preload_string:\n"); + VG_(debugLog)(2, "initimg", " \"%s\"\n", preload_string); + + /* Count the original size of the env */ + envc = 0; + for (cpp = origenv; cpp && *cpp; cpp++) + envc++; + + /* Allocate a new space */ + ret = VG_(malloc) ("initimg-freebsd.sce.3", + sizeof(HChar *) * (envc+2+1)); /* 2 new entry + NULL */ + vg_assert(ret); + + /* copy it over */ + for (cpp = ret; *origenv; ) + *cpp++ = *origenv++; + *cpp = NULL; + *(cpp + 1) = NULL; + + vg_assert(envc == (cpp - ret)); + + /* Walk over the new environment, mashing as we go */ + for (cpp = ret; cpp && *cpp; cpp++) { + if (VG_(memcmp)(*cpp, ld_preload, ld_preload_len) == 0) { + Int len = VG_(strlen)(*cpp) + preload_string_len; + HChar *cp = VG_(malloc)("initimg-freebsd.sce.4", len); + vg_assert(cp); + + VG_(snprintf)(cp, len, "%s%s:%s", + ld_preload, preload_string, (*cpp)+ld_preload_len); + + *cpp = cp; + + ld_preload_done = True; + } + } + + /* Add the missing bits */ + if (!ld_preload_done) { + Int len = ld_preload_len + preload_string_len; + HChar *cp = VG_(malloc) ("initimg-freebsd.sce.5", len); + vg_assert(cp); + + VG_(snprintf)(cp, len, "%s%s", ld_preload, preload_string); + + ret[envc++] = cp; + } + +#if defined(VGP_x86_freebsd) + /* If we're running a 32 bit binary, ld-elf32.so.1 may be looking for + * a different variable name. Or it might be a 32 bit ld-elf.so.1 in a + * chroot. Cover both cases. */ + if (VG_(is32on64)()) { + for (cpp = ret; cpp && *cpp; cpp++) { + if (VG_(memcmp)(*cpp, ld_32_preload, ld_32_preload_len) == 0) { + Int len = VG_(strlen)(*cpp) + preload_string_len; + HChar *cp = VG_(malloc)("initimg-freebsd.sce.4a", len); + vg_assert(cp); + + VG_(snprintf)(cp, len, "%s%s:%s", + ld_32_preload, preload_string, (*cpp)+ld_32_preload_len); + + *cpp = cp; + + ld_32_preload_done = True; + } + } + if (!ld_32_preload_done) { + Int len = ld_32_preload_len + preload_string_len; + HChar *cp = VG_(malloc) ("initimg-freebsd.sce.5a", len); + vg_assert(cp); + + VG_(snprintf)(cp, len, "%s%s", ld_32_preload, preload_string); + + ret[envc++] = cp; + } + } +#endif + + /* ret[0 .. envc-1] is live now. */ + /* Find and remove a binding for VALGRIND_LAUNCHER. */ + for (i = 0; i < envc; i++) + if (0 == VG_(memcmp(ret[i], v_launcher, v_launcher_len))) + break; + + if (i < envc) { + for (; i < envc-1; i++) + ret[i] = ret[i+1]; + envc--; + } + + VG_(free)(preload_string); + ret[envc] = NULL; + + return ret; +} + + +/*====================================================================*/ +/*=== Setting up the client's stack ===*/ +/*====================================================================*/ + +/* Add a string onto the string table, and return its address */ +static char *copy_str(char **tab, const char *str) +{ + char *cp = *tab; + char *orig = cp; + + while(*str) + *cp++ = *str++; + *cp++ = '\0'; + + if (0) + VG_(printf)("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig)); + + *tab = cp; + + return orig; +} + + +/* ---------------------------------------------------------------- + + This sets up the client's initial stack, containing the args, + environment and aux vector. + + The format of the stack is: + + higher address +-----------------+ <- clstack_end + | | + : string table : + | | + +-----------------+ + | AT_NULL | + - - + | auxv | + +-----------------+ + | NULL | + - - + | envp | + +-----------------+ + | NULL | + - - + | argv | + +-----------------+ + | argc | + lower address +-----------------+ <- sp + | undefined | + : : + + Allocate and create the initial client stack. It is allocated down + from clstack_end, which was previously determined by the address + space manager. The returned value is the SP value for the client. + + The client's auxv is created by copying and modifying our own one. + As a side effect of scanning our own auxv, some important bits of + info are collected: + + VG_(cache_line_size_ppc32) // ppc32 only -- cache line size + VG_(have_altivec_ppc32) // ppc32 only -- is Altivec supported? + + ---------------------------------------------------------------- */ + +struct auxv +{ + Word a_type; + union { + void *a_ptr; + Word a_val; + } u; +}; + +static +struct auxv *find_auxv(UWord* sp) +{ + sp++; // skip argc (Nb: is word-sized, not int-sized!) + + while (*sp != 0) // skip argv + sp++; + sp++; + + while (*sp != 0) // skip env + sp++; + sp++; + +#if defined(VGA_ppc32) || defined(VGA_ppc64) +# if defined AT_IGNOREPPC + while (*sp == AT_IGNOREPPC) // skip AT_IGNOREPPC entries + sp += 2; +# endif +#endif + + return (struct auxv *)sp; +} + +static +Addr setup_client_stack( void* init_sp, + char** orig_envp, + const ExeInfo* info, + UInt** client_auxv, + Addr clstack_end, + SizeT clstack_max_size ) +{ + SysRes res; + char **cpp; + char *strtab; /* string table */ + char *stringbase; + Addr *ptr; + struct auxv *auxv; + const struct auxv *orig_auxv; + const struct auxv *cauxv; + unsigned stringsize; /* total size of strings in bytes */ + unsigned auxsize; /* total size of auxv in bytes */ + Int argc; /* total argc */ + Int envc; /* total number of env vars */ + unsigned stacksize; /* total client stack size */ + Addr client_SP; /* client stack base (initial SP) */ + Addr clstack_start; + Int i; + Bool have_exename; + + vg_assert(VG_IS_PAGE_ALIGNED(clstack_end+1)); + vg_assert( VG_(args_for_client) ); + + /* use our own auxv as a prototype */ + orig_auxv = find_auxv(init_sp); + + /* ==================== compute sizes ==================== */ + + /* first of all, work out how big the client stack will be */ + stringsize = 0; + have_exename = VG_(args_the_exename) != NULL; + + /* paste on the extra args if the loader needs them (ie, the #! + interpreter and its argument) */ + argc = 0; + if (info->interp_name != NULL) { + argc++; + stringsize += VG_(strlen)(info->interp_name) + 1; + } + if (info->interp_args != NULL) { + argc++; + stringsize += VG_(strlen)(info->interp_args) + 1; + } + + /* now scan the args we're given... */ + if (have_exename) + stringsize += VG_(strlen)( VG_(args_the_exename) ) + 1; + + for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) { + argc++; + stringsize += VG_(strlen)( * (HChar**) + VG_(indexXA)( VG_(args_for_client), i )) + + 1; + } + + /* ...and the environment */ + envc = 0; + for (cpp = orig_envp; cpp && *cpp; cpp++) { + envc++; + stringsize += VG_(strlen)(*cpp) + 1; + } + + /* now, how big is the auxv? */ + auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */ + for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) { + auxsize += sizeof(*cauxv); + } + + /* OK, now we know how big the client stack is */ + stacksize = + sizeof(Word) + /* argc */ + (have_exename ? sizeof(char **) : 0) + /* argc[0] == exename */ + sizeof(char **)*argc + /* argv */ + sizeof(char **) + /* terminal NULL */ + sizeof(char **)*envc + /* envp */ + sizeof(char **) + /* terminal NULL */ + auxsize + /* auxv */ + VG_ROUNDUP(stringsize, sizeof(Word)); /* strings (aligned) */ + + if (0) VG_(printf)("stacksize = %d\n", stacksize); + + /* client_SP is the client's stack pointer */ + client_SP = clstack_end - stacksize; + client_SP = VG_ROUNDDN(client_SP, 16); /* make stack 16 byte aligned */ + + /* base of the string table (aligned) */ + stringbase = strtab = (char *)clstack_end + - VG_ROUNDUP(stringsize, sizeof(int)); + + clstack_start = VG_PGROUNDDN(client_SP); + + /* The max stack size */ + clstack_max_size = VG_PGROUNDUP(clstack_max_size); + + /* Record stack extent -- needed for stack-change code. */ + VG_(clstk_start_base) = clstack_start; + VG_(clstk_end) = clstack_end; + + if (0) + VG_(printf)("stringsize=%d auxsize=%d stacksize=%d maxsize=0x%x\n" + "clstack_start %p\n" + "clstack_end %p\n", + stringsize, auxsize, stacksize, (Int)clstack_max_size, + (void*)clstack_start, (void*)clstack_end); + + /* ==================== allocate space ==================== */ + + { SizeT anon_size = clstack_end - clstack_start + 1; + SizeT resvn_size = clstack_max_size - anon_size; + Addr anon_start = clstack_start; + Addr resvn_start = anon_start - resvn_size; + SizeT inner_HACK = 0; + Bool ok; + + /* So far we've only accounted for space requirements down to the + stack pointer. If this target's ABI requires a redzone below + the stack pointer, we need to allocate an extra page, to + handle the worst case in which the stack pointer is almost at + the bottom of a page, and so there is insufficient room left + over to put the redzone in. In this case the simple thing to + do is allocate an extra page, by shrinking the reservation by + one page and growing the anonymous area by a corresponding + page. */ + vg_assert(VG_STACK_REDZONE_SZB >= 0); + vg_assert(VG_STACK_REDZONE_SZB < VKI_PAGE_SIZE); + if (VG_STACK_REDZONE_SZB > 0) { + vg_assert(resvn_size > VKI_PAGE_SIZE); + resvn_size -= VKI_PAGE_SIZE; + anon_start -= VKI_PAGE_SIZE; + anon_size += VKI_PAGE_SIZE; + } + + vg_assert(VG_IS_PAGE_ALIGNED(anon_size)); + vg_assert(VG_IS_PAGE_ALIGNED(resvn_size)); + vg_assert(VG_IS_PAGE_ALIGNED(anon_start)); + vg_assert(VG_IS_PAGE_ALIGNED(resvn_start)); + vg_assert(resvn_start == clstack_end + 1 - clstack_max_size); + +# ifdef ENABLE_INNER + inner_HACK = 1024*1024; // create 1M non-fault-extending stack +# endif + + if (0) + VG_(printf)("%#lx 0x%lx %#lx 0x%lx\n", + resvn_start, resvn_size, anon_start, anon_size); + + /* Create a shrinkable reservation followed by an anonymous + segment. Together these constitute a growdown stack. */ + res = VG_(mk_SysRes_Error)(0); + ok = VG_(am_create_reservation)( + resvn_start, + resvn_size -inner_HACK, + SmUpper, + anon_size +inner_HACK + ); + if (ok) { + /* allocate a stack - mmap enough space for the stack */ + res = VG_(am_mmap_anon_fixed_client)( + anon_start -inner_HACK, + anon_size +inner_HACK, + VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC + ); + } + if ((!ok) || sr_isError(res)) { + /* Allocation of the stack failed. We have to stop. */ + VG_(printf)("valgrind: " + "I failed to allocate space for the application's stack.\n"); + VG_(printf)("valgrind: " + "This may be the result of a very large --main-stacksize=\n"); + VG_(printf)("valgrind: setting. Cannot continue. Sorry.\n\n"); + VG_(exit)(0); + } + + vg_assert(ok); + vg_assert(!sr_isError(res)); + } + + /* ==================== create client stack ==================== */ + + ptr = (Addr*)client_SP; + + /* --- client argc --- */ + *ptr++ = argc + (have_exename ? 1 : 0); + + /* --- client argv --- */ + if (info->interp_name) { + *ptr++ = (Addr)copy_str(&strtab, info->interp_name); + VG_(free)(info->interp_name); + } + if (info->interp_args) { + *ptr++ = (Addr)copy_str(&strtab, info->interp_args); + VG_(free)(info->interp_args); + } + + if (have_exename) + *ptr++ = (Addr)copy_str(&strtab, VG_(args_the_exename)); + + for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) { + *ptr++ = (Addr)copy_str( + &strtab, + * (HChar**) VG_(indexXA)( VG_(args_for_client), i ) + ); + } + *ptr++ = 0; + + /* --- envp --- */ + VG_(client_envp) = (Char **)ptr; + for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++) + *ptr = (Addr)copy_str(&strtab, *cpp); + *ptr++ = 0; + + /* --- auxv --- */ + auxv = (struct auxv *)ptr; + *client_auxv = (UInt *)auxv; + + for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) { + + /* copy the entry... */ + *auxv = *orig_auxv; + + /* ...and fix up / examine the copy */ + switch(auxv->a_type) { + + case AT_IGNORE: + case AT_PHENT: + case AT_PAGESZ: + case AT_FLAGS: + case AT_NOTELF: + case AT_UID: + case AT_EUID: + case AT_GID: + case AT_EGID: + /* All these are pointerless, so we don't need to do + anything about them. */ + break; + + case AT_PHDR: + if (info->phdr == 0) + auxv->a_type = AT_IGNORE; + else + auxv->u.a_val = info->phdr; + break; + + case AT_PHNUM: + if (info->phdr == 0) + auxv->a_type = AT_IGNORE; + else + auxv->u.a_val = info->phnum; + break; + + case AT_BASE: + auxv->u.a_val = info->interp_base; + break; + + case AT_ENTRY: + auxv->u.a_val = info->entry; + break; + + default: + /* stomp out anything we don't know about */ + VG_(debugLog)(2, "initimg", + "stomping auxv entry %lld\n", + (ULong)auxv->a_type); + auxv->a_type = AT_IGNORE; + break; + } + } + *auxv = *orig_auxv; + vg_assert(auxv->a_type == AT_NULL); + + vg_assert((strtab-stringbase) == stringsize); + + /* client_SP is pointing at client's argc/argv */ + + if (0) VG_(printf)("startup SP = %#lx\n", client_SP); + return client_SP; +} + + +/* Allocate the client data segment. It is an expandable anonymous + mapping abutting a shrinkable reservation of size max_dseg_size. + The data segment starts at VG_(brk_base), which is page-aligned, + and runs up to VG_(brk_limit), which isn't. */ + +static void setup_client_dataseg ( SizeT max_size ) +{ + Bool ok; + SysRes sres; + Addr anon_start = VG_(brk_base); + SizeT anon_size = VKI_PAGE_SIZE; + Addr resvn_start = anon_start + anon_size; + SizeT resvn_size = max_size - anon_size; + + vg_assert(VG_IS_PAGE_ALIGNED(anon_size)); + vg_assert(VG_IS_PAGE_ALIGNED(resvn_size)); + vg_assert(VG_IS_PAGE_ALIGNED(anon_start)); + vg_assert(VG_IS_PAGE_ALIGNED(resvn_start)); + + /* Because there's been no brk activity yet: */ + vg_assert(VG_(brk_base) == VG_(brk_limit)); + + /* Try to create the data seg and associated reservation where + VG_(brk_base) says. */ + ok = VG_(am_create_reservation)( + resvn_start, + resvn_size, + SmLower, + anon_size + ); + + if (!ok) { + /* Hmm, that didn't work. Well, let aspacem suggest an address + it likes better, and try again with that. */ + anon_start = VG_(am_get_advisory_client_simple) + ( 0/*floating*/, anon_size+resvn_size, &ok ); + if (ok) { + resvn_start = anon_start + anon_size; + ok = VG_(am_create_reservation)( + resvn_start, + resvn_size, + SmLower, + anon_size + ); + if (ok) + VG_(brk_base) = VG_(brk_limit) = anon_start; + } + /* that too might have failed, but if it has, we're hosed: there + is no Plan C. */ + } + vg_assert(ok); + + /* We make the data segment (heap) executable because LinuxThreads on + ppc32 creates trampolines in this area. Also, on x86/Linux the data + segment is RWX natively, at least according to /proc/self/maps. + Also, having a non-executable data seg would kill any program which + tried to create code in the data seg and then run it. */ + sres = VG_(am_mmap_anon_fixed_client)( + anon_start, + anon_size, + VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC + ); + vg_assert(!sr_isError(sres)); + vg_assert(sr_Res(sres) == anon_start); +} + + +/*====================================================================*/ +/*=== TOP-LEVEL: VG_(setup_client_initial_image) ===*/ +/*====================================================================*/ + +/* Create the client's initial memory image. */ +IIFinaliseImageInfo VG_(ii_create_image)( IICreateImageInfo iicii ) +{ + ExeInfo info; + HChar** env = NULL; + + IIFinaliseImageInfo iifii; + VG_(memset)( &iifii, 0, sizeof(iifii) ); + + //-------------------------------------------------------------- + // Load client executable, finding in $PATH if necessary + // p: get_helprequest_and_toolname() [for 'exec', 'need_help'] + // p: layout_remaining_space [so there's space] + //-------------------------------------------------------------- + VG_(debugLog)(1, "initimg", "Loading client\n"); + + if (VG_(args_the_exename) == NULL) + VG_(err_missing_prog)(); + + load_client(&info, &iifii.initial_client_IP, &iifii.initial_client_TOC); + + //-------------------------------------------------------------- + // Set up client's environment + // p: set-libdir [for VG_(libdir)] + // p: get_helprequest_and_toolname [for toolname] + //-------------------------------------------------------------- + VG_(debugLog)(1, "initimg", "Setup client env\n"); + env = setup_client_env(iicii.envp, iicii.toolname); + + //-------------------------------------------------------------- + // Setup client stack, eip, and VG_(client_arg[cv]) + // p: load_client() [for 'info'] + // p: fix_environment() [for 'env'] + //-------------------------------------------------------------- + { + /* When allocating space for the client stack on Linux, take + notice of the --main-stacksize value. This makes it possible + to run programs with very large (primary) stack requirements + simply by specifying --main-stacksize. */ + /* Logic is as follows: + - by default, use the client's current stack rlimit + - if that exceeds 16M, clamp to 16M + - if a larger --main-stacksize value is specified, use that instead + - in all situations, the minimum allowed stack size is 1M + */ + void* init_sp = iicii.argv - 1; + SizeT m1 = 1024 * 1024; + SizeT m16 = 16 * m1; + SizeT szB = (SizeT)VG_(client_rlimit_stack).rlim_cur; + if (szB < m1) szB = m1; + if (szB > m16) szB = m16; + if (VG_(clo_main_stacksize) > 0) szB = VG_(clo_main_stacksize); + if (szB < m1) szB = m1; + szB = VG_PGROUNDUP(szB); + VG_(debugLog)(1, "initimg", + "Setup client stack: size will be %ld\n", szB); + + iifii.clstack_max_size = szB; + + iifii.initial_client_SP + = setup_client_stack( init_sp, env, + &info, &iifii.client_auxv, + iicii.clstack_top, iifii.clstack_max_size ); + + VG_(free)(env); + + VG_(debugLog)(2, "initimg", + "Client info: " + "initial_IP=%p initial_TOC=%p brk_base=%p\n", + (void*)(iifii.initial_client_IP), + (void*)(iifii.initial_client_TOC), + (void*)VG_(brk_base) ); + VG_(debugLog)(2, "initimg", + "Client info: " + "initial_SP=%p max_stack_size=%ld\n", + (void*)(iifii.initial_client_SP), + (SizeT)iifii.clstack_max_size ); + } + + //-------------------------------------------------------------- + // Setup client data (brk) segment. Initially a 1-page segment + // which abuts a shrinkable reservation. + // p: load_client() [for 'info' and hence VG_(brk_base)] + //-------------------------------------------------------------- + { + SizeT m1 = 1024 * 1024; + SizeT m8 = 8 * m1; + SizeT dseg_max_size = (SizeT)VG_(client_rlimit_data).rlim_cur; + VG_(debugLog)(1, "initimg", "Setup client data (brk) segment\n"); + if (dseg_max_size < m1) dseg_max_size = m1; + if (dseg_max_size > m8) dseg_max_size = m8; + dseg_max_size = VG_PGROUNDUP(dseg_max_size); + + setup_client_dataseg( dseg_max_size ); + } + + return iifii; +} + + +/*====================================================================*/ +/*=== TOP-LEVEL: VG_(finalise_thread1state) ===*/ +/*====================================================================*/ + +/* Just before starting the client, we may need to make final + adjustments to its initial image. Also we need to set up the VEX + guest state for thread 1 (the root thread) and copy in essential + starting values. This is handed the IIFinaliseImageInfo created by + VG_(ii_create_image). +*/ +void VG_(ii_finalise_image)( IIFinaliseImageInfo iifii ) +{ + ThreadArchState* arch = &VG_(threads)[1].arch; + + /* On Linux we get client_{ip/sp/toc}, and start the client with + all other registers zeroed. */ + +# if defined(VGP_x86_freebsd) + vg_assert(0 == sizeof(VexGuestX86State) % 16); + + /* Zero out the initial state, and set up the simulated FPU in a + sane way. */ + LibVEX_GuestX86_initialise(&arch->vex); + + /* Zero out the shadow areas. */ + VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestX86State)); + VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestX86State)); + + /* Put essential stuff into the new state. */ + arch->vex.guest_ESP = iifii.initial_client_SP; + arch->vex.guest_EIP = iifii.initial_client_IP; + + /* initialise %cs, %ds and %ss to point at the operating systems + default code, data and stack segments */ + asm volatile("movw %%cs, %0" : : "m" (arch->vex.guest_CS)); + asm volatile("movw %%ds, %0" : : "m" (arch->vex.guest_DS)); + asm volatile("movw %%ss, %0" : : "m" (arch->vex.guest_SS)); + +# elif defined(VGP_amd64_freebsd) + vg_assert(0 == sizeof(VexGuestAMD64State) % 16); + + /* Zero out the initial state, and set up the simulated FPU in a + sane way. */ + LibVEX_GuestAMD64_initialise(&arch->vex); + + /* Zero out the shadow areas. */ + VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestAMD64State)); + VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestAMD64State)); + + /* Put essential stuff into the new state. */ + arch->vex.guest_RSP = ((iifii.initial_client_SP - 8) & ~0xFul) + 8; + arch->vex.guest_RDI = iifii.initial_client_SP; + arch->vex.guest_RIP = iifii.initial_client_IP; + +# else +# error Unknown platform +# endif + + /* Tell the tool that we just wrote to the registers. */ + VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0, + sizeof(VexGuestArchState)); +} + +#endif // defined(VGO_freebsd) + +/*--------------------------------------------------------------------*/ +/*--- ---*/ +/*--------------------------------------------------------------------*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_initimg/initimg-openbsd.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coregrind/m_initimg/initimg-openbsd.c Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,945 @@ + +/*--------------------------------------------------------------------*/ +/*--- Startup: create initial process image on Linux ---*/ +/*--- initimg-freebsd.c ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2009 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#if defined(VGO_openbsd) + +#include "pub_core_basics.h" +#include "pub_core_vki.h" +#include "pub_core_debuglog.h" +#include "pub_core_libcbase.h" +#include "pub_core_libcassert.h" +#include "pub_core_libcfile.h" +#include "pub_core_libcproc.h" +#include "pub_core_libcprint.h" +#include "pub_core_xarray.h" +#include "pub_core_clientstate.h" +#include "pub_core_aspacemgr.h" +#include "pub_core_mallocfree.h" +#include "pub_core_machine.h" +#include "pub_core_ume.h" +#include "pub_core_options.h" +#include "pub_core_syscall.h" +#include "pub_core_tooliface.h" /* VG_TRACK */ +#include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy +#include "pub_core_threadstate.h" /* ThreadArchState */ +#include "priv_initimg_pathscan.h" +#include "pub_core_initimg.h" /* self */ + +/* --- !!! --- EXTERNAL HEADERS start --- !!! --- */ +#define _GNU_SOURCE +#define _FILE_OFFSET_BITS 64 +/* This is for ELF types etc, and also the AT_ constants. */ +#include +/* --- !!! --- EXTERNAL HEADERS end --- !!! --- */ + + +/* --- !!! --- ELF COMPAT ABI start --- !!! --- */ + +#define AT_NULL 0 +#define AT_IGNORE 1 +#define AT_PHDR 3 +#define AT_PHENT 4 +#define AT_PHNUM 5 +#define AT_PAGESZ 6 +#define AT_BASE 7 +#define AT_FLAGS 8 +#define AT_ENTRY 9 +#define AT_NOTELF 10 +#define AT_UID 11 +#define AT_EUID 12 +#define AT_GID 13 +#define AT_EGID 14 + +/* --- !!! --- ELF COMPAT ABI end --- !!! --- */ + +/*====================================================================*/ +/*=== Loading the client ===*/ +/*====================================================================*/ + +/* Load the client whose name is VG_(argv_the_exename). */ + +static void load_client ( /*OUT*/ExeInfo* info, + /*OUT*/Addr* client_ip, + /*OUT*/Addr* client_toc) +{ + const HChar* exe_name; + Int ret; + SysRes res; + + vg_assert( VG_(args_the_exename) != NULL); + exe_name = ML_(find_executable)( VG_(args_the_exename) ); + + if (!exe_name) { + VG_(printf)("valgrind: %s: command not found\n", VG_(args_the_exename)); + VG_(exit)(127); // 127 is Posix NOTFOUND + } + + VG_(memset)(info, 0, sizeof(*info)); + ret = VG_(do_exec)(exe_name, info); + if (ret < 0) { + VG_(printf)("valgrind: could not execute '%s'\n", exe_name); + VG_(exit)(1); + } + + // The client was successfully loaded! Continue. + + /* Get hold of a file descriptor which refers to the client + executable. This is needed for attaching to GDB. */ + res = VG_(open)(exe_name, VKI_O_RDONLY, VKI_S_IRUSR); + if (!sr_isError(res)) + VG_(cl_exec_fd) = sr_Res(res); + + /* Copy necessary bits of 'info' that were filled in */ + *client_ip = info->init_ip; + *client_toc = info->init_toc; + VG_(brk_base) = VG_(brk_limit) = VG_PGROUNDUP(info->brkbase); +} + + +/*====================================================================*/ +/*=== Setting up the client's environment ===*/ +/*====================================================================*/ + +/* Prepare the client's environment. This is basically a copy of our + environment, except: + + LD_PRELOAD=$VALGRIND_LIB/vgpreload_core-PLATFORM.so: + ($VALGRIND_LIB/vgpreload_TOOL-PLATFORM.so:)? + $LD_PRELOAD + + If this is missing, then it is added. + + Also, remove any binding for VALGRIND_LAUNCHER=. The client should + not be able to see this. + + If this needs to handle any more variables it should be hacked + into something table driven. The copy is VG_(malloc)'d space. +*/ +static HChar** setup_client_env ( HChar** origenv, const HChar* toolname) +{ + const HChar* preload_core = "vgpreload_core"; + const HChar* ld_preload = "LD_PRELOAD="; + const HChar* v_launcher = VALGRIND_LAUNCHER "="; + Int ld_preload_len = VG_(strlen)( ld_preload ); + Int v_launcher_len = VG_(strlen)( v_launcher ); + Bool ld_preload_done = False; +#if defined(VGP_x86_openbsd) + HChar* ld_32_preload = "LD_32_PRELOAD="; + Int ld_32_preload_len = VG_(strlen)( ld_32_preload ); + Bool ld_32_preload_done = False; +#endif + Int vglib_len = VG_(strlen)(VG_(libdir)); + + HChar** cpp; + HChar** ret; + HChar* preload_tool_path; + Int envc, i; + + /* Alloc space for the vgpreload_core.so path and vgpreload_.so + paths. We might not need the space for vgpreload_.so, but it + doesn't hurt to over-allocate briefly. The 16s are just cautious + slop. */ + Int preload_core_path_len = vglib_len + sizeof(preload_core) + + sizeof(VG_PLATFORM) + 16; + Int preload_tool_path_len = vglib_len + VG_(strlen)(toolname) + + sizeof(VG_PLATFORM) + 16; + Int preload_string_len = preload_core_path_len + preload_tool_path_len; + HChar* preload_string = VG_(malloc)("initimg-openbsd.sce.1", + preload_string_len); + vg_assert(origenv); + vg_assert(toolname); + vg_assert(preload_string); + + /* Determine if there's a vgpreload__.so file, and setup + preload_string. */ + preload_tool_path = VG_(malloc)("initimg-openbsd.sce.2", preload_tool_path_len); + vg_assert(preload_tool_path); + VG_(snprintf)(preload_tool_path, preload_tool_path_len, + "%s/vgpreload_%s-%s.so", VG_(libdir), toolname, VG_PLATFORM); + if (VG_(access)(preload_tool_path, True/*r*/, False/*w*/, False/*x*/) == 0) { + VG_(snprintf)(preload_string, preload_string_len, "%s/%s-%s.so:%s", + VG_(libdir), preload_core, VG_PLATFORM, preload_tool_path); + } else { + VG_(snprintf)(preload_string, preload_string_len, "%s/%s-%s.so", + VG_(libdir), preload_core, VG_PLATFORM); + } + VG_(free)(preload_tool_path); + + VG_(debugLog)(2, "initimg", "preload_string:\n"); + VG_(debugLog)(2, "initimg", " \"%s\"\n", preload_string); + + /* Count the original size of the env */ + envc = 0; + for (cpp = origenv; cpp && *cpp; cpp++) + envc++; + + /* Allocate a new space */ + ret = VG_(malloc) ("initimg-openbsd.sce.3", + sizeof(HChar *) * (envc+2+1)); /* 2 new entry + NULL */ + vg_assert(ret); + + /* copy it over */ + for (cpp = ret; *origenv; ) + *cpp++ = *origenv++; + *cpp = NULL; + *(cpp + 1) = NULL; + + vg_assert(envc == (cpp - ret)); + + /* Walk over the new environment, mashing as we go */ + for (cpp = ret; cpp && *cpp; cpp++) { + if (VG_(memcmp)(*cpp, ld_preload, ld_preload_len) == 0) { + Int len = VG_(strlen)(*cpp) + preload_string_len; + HChar *cp = VG_(malloc)("initimg-openbsd.sce.4", len); + vg_assert(cp); + + VG_(snprintf)(cp, len, "%s%s:%s", + ld_preload, preload_string, (*cpp)+ld_preload_len); + + *cpp = cp; + + ld_preload_done = True; + } + } + + /* Add the missing bits */ + if (!ld_preload_done) { + Int len = ld_preload_len + preload_string_len; + HChar *cp = VG_(malloc) ("initimg-openbsd.sce.5", len); + vg_assert(cp); + + VG_(snprintf)(cp, len, "%s%s", ld_preload, preload_string); + + ret[envc++] = cp; + } + +#if defined(VGP_x86_openbsd) + /* If we're running a 32 bit binary, ld-elf32.so.1 may be looking for + * a different variable name. Or it might be a 32 bit ld-elf.so.1 in a + * chroot. Cover both cases. */ + if (VG_(is32on64)()) { + for (cpp = ret; cpp && *cpp; cpp++) { + if (VG_(memcmp)(*cpp, ld_32_preload, ld_32_preload_len) == 0) { + Int len = VG_(strlen)(*cpp) + preload_string_len; + HChar *cp = VG_(malloc)("initimg-openbsd.sce.4a", len); + vg_assert(cp); + + VG_(snprintf)(cp, len, "%s%s:%s", + ld_32_preload, preload_string, (*cpp)+ld_32_preload_len); + + *cpp = cp; + + ld_32_preload_done = True; + } + } + if (!ld_32_preload_done) { + Int len = ld_32_preload_len + preload_string_len; + HChar *cp = VG_(malloc) ("initimg-openbsd.sce.5a", len); + vg_assert(cp); + + VG_(snprintf)(cp, len, "%s%s", ld_32_preload, preload_string); + + ret[envc++] = cp; + } + } +#endif + + /* ret[0 .. envc-1] is live now. */ + /* Find and remove a binding for VALGRIND_LAUNCHER. */ + for (i = 0; i < envc; i++) + if (0 == VG_(memcmp(ret[i], v_launcher, v_launcher_len))) + break; + + if (i < envc) { + for (; i < envc-1; i++) + ret[i] = ret[i+1]; + envc--; + } + + VG_(free)(preload_string); + ret[envc] = NULL; + + return ret; +} + + +/*====================================================================*/ +/*=== Setting up the client's stack ===*/ +/*====================================================================*/ + +/* Add a string onto the string table, and return its address */ +static HChar *copy_str(HChar **tab, const HChar *str) +{ + HChar *cp = *tab; + HChar *orig = cp; + + while(*str) + *cp++ = *str++; + *cp++ = '\0'; + + if (0) + VG_(printf)("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig)); + + *tab = cp; + + return orig; +} + + +/* ---------------------------------------------------------------- + + This sets up the client's initial stack, containing the args, + environment and aux vector. + + The format of the stack is: + + higher address +-----------------+ <- clstack_end + | | + : string table : + | | + +-----------------+ + | AT_NULL | + - - + | auxv | + +-----------------+ + | NULL | + - - + | envp | + +-----------------+ + | NULL | + - - + | argv | + +-----------------+ + | argc | + lower address +-----------------+ <- sp + | undefined | + : : + + Allocate and create the initial client stack. It is allocated down + from clstack_end, which was previously determined by the address + space manager. The returned value is the SP value for the client. + + The client's auxv is created by copying and modifying our own one. + As a side effect of scanning our own auxv, some important bits of + info are collected: + + VG_(cache_line_size_ppc32) // ppc32 only -- cache line size + VG_(have_altivec_ppc32) // ppc32 only -- is Altivec supported? + + ---------------------------------------------------------------- */ + +struct auxv +{ + Word a_type; + union { + void *a_ptr; + Word a_val; + } u; +}; + +#if 0 +static +struct auxv *find_auxv(UWord* sp) +{ + sp++; // skip argc (Nb: is word-sized, not int-sized!) + + while (*sp != 0) // skip argv + sp++; + sp++; + + while (*sp != 0) // skip env + sp++; + sp++; + +#if defined(VGA_ppc32) || defined(VGA_ppc64) +# if defined AT_IGNOREPPC + while (*sp == AT_IGNOREPPC) // skip AT_IGNOREPPC entries + sp += 2; +# endif +#endif + + return (struct auxv *)sp; +} +#endif + +static +Addr setup_client_stack( void* init_sp, + char** orig_envp, + const ExeInfo* info, + UInt** client_auxv, + Addr clstack_end, + SizeT clstack_max_size ) +{ + SysRes res; + HChar **cpp; + HChar *strtab; /* string table */ + HChar *stringbase; + Addr *ptr; + struct auxv *auxv; +#if 1 + const struct auxv orig_auxv_dummy[] = { + { .a_type = AT_PHDR }, + { .a_type = AT_PHENT }, + { .a_type = AT_PHNUM }, + { .a_type = AT_PAGESZ }, + { .a_type = AT_BASE }, + { .a_type = AT_FLAGS }, + { .a_type = AT_ENTRY }, + { .a_type = AT_NULL }, + }; +#endif + const struct auxv *orig_auxv; + const struct auxv *cauxv; + unsigned stringsize; /* total size of strings in bytes */ + unsigned auxsize; /* total size of auxv in bytes */ + Int argc; /* total argc */ + Int envc; /* total number of env vars */ + unsigned stacksize; /* total client stack size */ + Addr client_SP; /* client stack base (initial SP) */ + Addr clstack_start; + Int i; + Bool have_exename; + + vg_assert(VG_IS_PAGE_ALIGNED(clstack_end+1)); + vg_assert( VG_(args_for_client) ); + +#if 0 + /* use our own auxv as a prototype */ + orig_auxv = find_auxv(init_sp); +#else + // XXX OpenBSD doesn't fill auxv for static binaries + // XXX memcheck is not given auxv as statically linked + // XXX Don't rely on orig_auxv but hard-code + orig_auxv = orig_auxv_dummy; +#endif + + /* ==================== compute sizes ==================== */ + + /* first of all, work out how big the client stack will be */ + stringsize = 0; + have_exename = VG_(args_the_exename) != NULL; + + /* paste on the extra args if the loader needs them (ie, the #! + interpreter and its argument) */ + argc = 0; + if (info->interp_name != NULL) { + argc++; + stringsize += VG_(strlen)(info->interp_name) + 1; + } + if (info->interp_args != NULL) { + argc++; + stringsize += VG_(strlen)(info->interp_args) + 1; + } + + /* now scan the args we're given... */ + if (have_exename) + stringsize += VG_(strlen)( VG_(args_the_exename) ) + 1; + + for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) { + argc++; + stringsize += VG_(strlen)( * (HChar**) + VG_(indexXA)( VG_(args_for_client), i )) + + 1; + } + + /* ...and the environment */ + envc = 0; + for (cpp = orig_envp; cpp && *cpp; cpp++) { + envc++; + stringsize += VG_(strlen)(*cpp) + 1; + } + + /* now, how big is the auxv? */ + auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */ + for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) { + auxsize += sizeof(*cauxv); + } + + /* OK, now we know how big the client stack is */ + stacksize = + sizeof(Word) + /* argc */ + (have_exename ? sizeof(HChar **) : 0) + /* argc[0] == exename */ + sizeof(HChar **)*argc + /* argv */ + sizeof(HChar **) + /* terminal NULL */ + sizeof(HChar **)*envc + /* envp */ + sizeof(HChar **) + /* terminal NULL */ + auxsize + /* auxv */ + VG_ROUNDUP(stringsize, sizeof(Word)); /* strings (aligned) */ + + if (0) VG_(printf)("stacksize = %d\n", stacksize); + + /* client_SP is the client's stack pointer */ + client_SP = clstack_end - stacksize; + client_SP = VG_ROUNDDN(client_SP, 16); /* make stack 16 byte aligned */ + + /* base of the string table (aligned) */ + stringbase = strtab = (HChar *)clstack_end + - VG_ROUNDUP(stringsize, sizeof(int)); + + clstack_start = VG_PGROUNDDN(client_SP); + + /* The max stack size */ + clstack_max_size = VG_PGROUNDUP(clstack_max_size); + + /* Record stack extent -- needed for stack-change code. */ + VG_(clstk_start_base) = clstack_start; + VG_(clstk_end) = clstack_end; + + if (0) + VG_(printf)("stringsize=%d auxsize=%d stacksize=%d maxsize=0x%x\n" + "clstack_start %p\n" + "clstack_end %p\n", + stringsize, auxsize, stacksize, (Int)clstack_max_size, + (void*)clstack_start, (void*)clstack_end); + + /* ==================== allocate space ==================== */ + + { SizeT anon_size = clstack_end - clstack_start + 1; + SizeT resvn_size = clstack_max_size - anon_size; + Addr anon_start = clstack_start; + Addr resvn_start = anon_start - resvn_size; + SizeT inner_HACK = 0; + Bool ok; + + /* So far we've only accounted for space requirements down to the + stack pointer. If this target's ABI requires a redzone below + the stack pointer, we need to allocate an extra page, to + handle the worst case in which the stack pointer is almost at + the bottom of a page, and so there is insufficient room left + over to put the redzone in. In this case the simple thing to + do is allocate an extra page, by shrinking the reservation by + one page and growing the anonymous area by a corresponding + page. */ + vg_assert(VG_STACK_REDZONE_SZB >= 0); + vg_assert(VG_STACK_REDZONE_SZB < VKI_PAGE_SIZE); + if (VG_STACK_REDZONE_SZB > 0) { + vg_assert(resvn_size > VKI_PAGE_SIZE); + resvn_size -= VKI_PAGE_SIZE; + anon_start -= VKI_PAGE_SIZE; + anon_size += VKI_PAGE_SIZE; + } + + vg_assert(VG_IS_PAGE_ALIGNED(anon_size)); + vg_assert(VG_IS_PAGE_ALIGNED(resvn_size)); + vg_assert(VG_IS_PAGE_ALIGNED(anon_start)); + vg_assert(VG_IS_PAGE_ALIGNED(resvn_start)); + vg_assert(resvn_start == clstack_end + 1 - clstack_max_size); + +# ifdef ENABLE_INNER + inner_HACK = 1024*1024; // create 1M non-fault-extending stack +# endif + + if (0) + VG_(printf)("%#lx 0x%lx %#lx 0x%lx\n", + resvn_start, resvn_size, anon_start, anon_size); + + /* Create a shrinkable reservation followed by an anonymous + segment. Together these constitute a growdown stack. */ + res = VG_(mk_SysRes_Error)(0); + ok = VG_(am_create_reservation)( + resvn_start, + resvn_size -inner_HACK, + SmUpper, + anon_size +inner_HACK + ); + if (ok) { + /* allocate a stack - mmap enough space for the stack */ + res = VG_(am_mmap_anon_fixed_client)( + anon_start -inner_HACK, + anon_size +inner_HACK, + VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC + ); + } + if ((!ok) || sr_isError(res)) { + /* Allocation of the stack failed. We have to stop. */ + VG_(printf)("valgrind: " + "I failed to allocate space for the application's stack.\n"); + VG_(printf)("valgrind: " + "This may be the result of a very large --main-stacksize=\n"); + VG_(printf)("valgrind: setting. Cannot continue. Sorry.\n\n"); + VG_(exit)(0); + } + + vg_assert(ok); + vg_assert(!sr_isError(res)); + } + + /* ==================== create client stack ==================== */ + + ptr = (Addr*)client_SP; + + /* --- client argc --- */ + *ptr++ = argc + (have_exename ? 1 : 0); + + /* --- client argv --- */ + if (info->interp_name) { + *ptr++ = (Addr)copy_str(&strtab, info->interp_name); + VG_(free)(info->interp_name); + } + if (info->interp_args) { + *ptr++ = (Addr)copy_str(&strtab, info->interp_args); + VG_(free)(info->interp_args); + } + + if (have_exename) + *ptr++ = (Addr)copy_str(&strtab, VG_(args_the_exename)); + + for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) { + *ptr++ = (Addr)copy_str( + &strtab, + * (HChar**) VG_(indexXA)( VG_(args_for_client), i ) + ); + } + *ptr++ = 0; + + /* --- envp --- */ + VG_(client_envp) = (HChar **)ptr; + for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++) + *ptr = (Addr)copy_str(&strtab, *cpp); + *ptr++ = 0; + + /* --- auxv --- */ + auxv = (struct auxv *)ptr; + *client_auxv = (UInt *)auxv; + + for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) { + + /* copy the entry... */ + *auxv = *orig_auxv; + + /* ...and fix up / examine the copy */ + switch(auxv->a_type) { + + case AT_IGNORE: + case AT_PHENT: + case AT_PAGESZ: + case AT_FLAGS: + case AT_NOTELF: + case AT_UID: + case AT_EUID: + case AT_GID: + case AT_EGID: + /* All these are pointerless, so we don't need to do + anything about them. */ + break; + + case AT_PHDR: + if (info->phdr == 0) + auxv->a_type = AT_IGNORE; + else + auxv->u.a_val = info->phdr; + break; + + case AT_PHNUM: + if (info->phdr == 0) + auxv->a_type = AT_IGNORE; + else + auxv->u.a_val = info->phnum; + break; + + case AT_BASE: + if (info->interp_offset != 0) + auxv->u.a_val = info->interp_offset; + else + /* Static PIE. */ + auxv->u.a_val = info->exe_base; + break; + + case AT_ENTRY: + auxv->u.a_val = info->entry; + break; + + default: + /* stomp out anything we don't know about */ + VG_(debugLog)(2, "initimg", + "stomping auxv entry %lld\n", + (ULong)auxv->a_type); + auxv->a_type = AT_IGNORE; + break; + } + } + *auxv = *orig_auxv; + vg_assert(auxv->a_type == AT_NULL); + + vg_assert((strtab-stringbase) == stringsize); + + /* client_SP is pointing at client's argc/argv */ + + if (0) VG_(printf)("startup SP = %#lx\n", client_SP); + return client_SP; +} + + +/* Allocate the client data segment. It is an expandable anonymous + mapping abutting a shrinkable reservation of size max_dseg_size. + The data segment starts at VG_(brk_base), which is page-aligned, + and runs up to VG_(brk_limit), which isn't. */ + +static void setup_client_dataseg ( SizeT max_size ) +{ + Bool ok; + SysRes sres; + Addr anon_start = VG_(brk_base); + SizeT anon_size = VKI_PAGE_SIZE; + Addr resvn_start = anon_start + anon_size; + SizeT resvn_size = max_size - anon_size; + + vg_assert(VG_IS_PAGE_ALIGNED(anon_size)); + vg_assert(VG_IS_PAGE_ALIGNED(resvn_size)); + vg_assert(VG_IS_PAGE_ALIGNED(anon_start)); + vg_assert(VG_IS_PAGE_ALIGNED(resvn_start)); + + /* Because there's been no brk activity yet: */ + vg_assert(VG_(brk_base) == VG_(brk_limit)); + + /* Try to create the data seg and associated reservation where + VG_(brk_base) says. */ + ok = VG_(am_create_reservation)( + resvn_start, + resvn_size, + SmLower, + anon_size + ); + + if (!ok) { + /* Hmm, that didn't work. Well, let aspacem suggest an address + it likes better, and try again with that. */ + anon_start = VG_(am_get_advisory_client_simple) + ( 0/*floating*/, anon_size+resvn_size, &ok ); + if (ok) { + resvn_start = anon_start + anon_size; + ok = VG_(am_create_reservation)( + resvn_start, + resvn_size, + SmLower, + anon_size + ); + if (ok) + VG_(brk_base) = VG_(brk_limit) = anon_start; + } + /* that too might have failed, but if it has, we're hosed: there + is no Plan C. */ + } + vg_assert(ok); + + /* We make the data segment (heap) executable because LinuxThreads on + ppc32 creates trampolines in this area. Also, on x86/Linux the data + segment is RWX natively, at least according to /proc/self/maps. + Also, having a non-executable data seg would kill any program which + tried to create code in the data seg and then run it. */ + sres = VG_(am_mmap_anon_fixed_client)( + anon_start, + anon_size, + VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC + ); + vg_assert(!sr_isError(sres)); + vg_assert(sr_Res(sres) == anon_start); +} + + +/*====================================================================*/ +/*=== TOP-LEVEL: VG_(setup_client_initial_image) ===*/ +/*====================================================================*/ + +/* Create the client's initial memory image. */ +IIFinaliseImageInfo VG_(ii_create_image)( IICreateImageInfo iicii ) +{ + ExeInfo info; + HChar** env = NULL; + + IIFinaliseImageInfo iifii; + VG_(memset)( &iifii, 0, sizeof(iifii) ); + + //-------------------------------------------------------------- + // Load client executable, finding in $PATH if necessary + // p: get_helprequest_and_toolname() [for 'exec', 'need_help'] + // p: layout_remaining_space [so there's space] + //-------------------------------------------------------------- + VG_(debugLog)(1, "initimg", "Loading client\n"); + + if (VG_(args_the_exename) == NULL) + VG_(err_missing_prog)(); + + load_client(&info, &iifii.initial_client_IP, &iifii.initial_client_TOC); + + //-------------------------------------------------------------- + // Set up client's environment + // p: set-libdir [for VG_(libdir)] + // p: get_helprequest_and_toolname [for toolname] + //-------------------------------------------------------------- + VG_(debugLog)(1, "initimg", "Setup client env\n"); + env = setup_client_env(iicii.envp, iicii.toolname); + + //-------------------------------------------------------------- + // Setup client stack, eip, and VG_(client_arg[cv]) + // p: load_client() [for 'info'] + // p: fix_environment() [for 'env'] + //-------------------------------------------------------------- + { + /* When allocating space for the client stack on Linux, take + notice of the --main-stacksize value. This makes it possible + to run programs with very large (primary) stack requirements + simply by specifying --main-stacksize. */ + /* Logic is as follows: + - by default, use the client's current stack rlimit + - if that exceeds 16M, clamp to 16M + - if a larger --main-stacksize value is specified, use that instead + - in all situations, the minimum allowed stack size is 1M + */ + void* init_sp = iicii.argv - 1; + SizeT m1 = 1024 * 1024; + SizeT m16 = 16 * m1; + SizeT szB = (SizeT)VG_(client_rlimit_stack).rlim_cur; + if (szB < m1) szB = m1; + if (szB > m16) szB = m16; + if (VG_(clo_main_stacksize) > 0) szB = VG_(clo_main_stacksize); + if (szB < m1) szB = m1; + szB = VG_PGROUNDUP(szB); + VG_(debugLog)(1, "initimg", + "Setup client stack: size will be %ld\n", szB); + + iifii.clstack_max_size = szB; + + iifii.initial_client_SP + = setup_client_stack( init_sp, env, + &info, &iifii.client_auxv, + iicii.clstack_end, iifii.clstack_max_size ); + + VG_(free)(env); + + VG_(debugLog)(2, "initimg", + "Client info: " + "initial_IP=%p initial_TOC=%p brk_base=%p\n", + (void*)(iifii.initial_client_IP), + (void*)(iifii.initial_client_TOC), + (void*)VG_(brk_base) ); + VG_(debugLog)(2, "initimg", + "Client info: " + "initial_SP=%p max_stack_size=%ld\n", + (void*)(iifii.initial_client_SP), + (SizeT)iifii.clstack_max_size ); + } + + //-------------------------------------------------------------- + // Setup client data (brk) segment. Initially a 1-page segment + // which abuts a shrinkable reservation. + // p: load_client() [for 'info' and hence VG_(brk_base)] + //-------------------------------------------------------------- + { + SizeT m1 = 1024 * 1024; + SizeT m8 = 8 * m1; + SizeT dseg_max_size = (SizeT)VG_(client_rlimit_data).rlim_cur; + VG_(debugLog)(1, "initimg", "Setup client data (brk) segment\n"); + if (dseg_max_size < m1) dseg_max_size = m1; + if (dseg_max_size > m8) dseg_max_size = m8; + dseg_max_size = VG_PGROUNDUP(dseg_max_size); + + setup_client_dataseg( dseg_max_size ); + } + + return iifii; +} + + +/*====================================================================*/ +/*=== TOP-LEVEL: VG_(finalise_thread1state) ===*/ +/*====================================================================*/ + +/* Just before starting the client, we may need to make final + adjustments to its initial image. Also we need to set up the VEX + guest state for thread 1 (the root thread) and copy in essential + starting values. This is handed the IIFinaliseImageInfo created by + VG_(ii_create_image). +*/ +void VG_(ii_finalise_image)( IIFinaliseImageInfo iifii ) +{ + ThreadArchState* arch = &VG_(threads)[1].arch; + + /* On Linux we get client_{ip/sp/toc}, and start the client with + all other registers zeroed. */ + +# if defined(VGP_x86_openbsd) + vg_assert(0 == sizeof(VexGuestX86State) % 16); + + /* Zero out the initial state, and set up the simulated FPU in a + sane way. */ + LibVEX_GuestX86_initialise(&arch->vex); + + /* Zero out the shadow areas. */ + VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestX86State)); + VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestX86State)); + + /* Put essential stuff into the new state. */ + arch->vex.guest_ESP = iifii.initial_client_SP; + arch->vex.guest_EIP = iifii.initial_client_IP; + + /* initialise %cs, %ds and %ss to point at the operating systems + default code, data and stack segments */ + asm volatile("movw %%cs, %0" : : "m" (arch->vex.guest_CS)); + asm volatile("movw %%ds, %0" : : "m" (arch->vex.guest_DS)); + asm volatile("movw %%ss, %0" : : "m" (arch->vex.guest_SS)); + +# elif defined(VGP_amd64_openbsd) + vg_assert(0 == sizeof(VexGuestAMD64State) % 16); + + /* Zero out the initial state, and set up the simulated FPU in a + sane way. */ + LibVEX_GuestAMD64_initialise(&arch->vex); + + /* Zero out the shadow areas. */ + VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestAMD64State)); + VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestAMD64State)); + + /* Put essential stuff into the new state. */ +#if 0 + arch->vex.guest_RSP = ((iifii.initial_client_SP - 8) & ~0xFul) + 8; + arch->vex.guest_RDI = iifii.initial_client_SP; +#else + /* OpenBSD/amd64 expects RSP pointing to the top of stack exactly. */ + arch->vex.guest_RSP = iifii.initial_client_SP; + /* OpenBSD/amd64 doesn't use RDI. */ +#endif + arch->vex.guest_RIP = iifii.initial_client_IP; + +# else +# error Unknown platform +# endif + + /* Tell the tool that we just wrote to the registers. */ + VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0, + sizeof(VexGuestArchState)); +} + +#endif // defined(VGO_openbsd) + +/*--------------------------------------------------------------------*/ +/*--- ---*/ +/*--------------------------------------------------------------------*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_libcassert.c --- a/coregrind/m_libcassert.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_libcassert.c Thu Mar 31 15:57:55 2016 +0900 @@ -50,7 +50,7 @@ Assertery. ------------------------------------------------------------------ */ -#if defined(VGP_x86_linux) || defined(VGP_x86_darwin) +#if defined(VGP_x86_linux) || defined(VGP_x86_darwin) || defined(VGP_x86_freebsd) || defined(VGP_x86_openbsd) # define GET_STARTREGS(srP) \ { UInt eip, esp, ebp; \ __asm__ __volatile__( \ @@ -66,7 +66,7 @@ (srP)->r_sp = (ULong)esp; \ (srP)->misc.X86.r_ebp = ebp; \ } -#elif defined(VGP_amd64_linux) || defined(VGP_amd64_darwin) +#elif defined(VGP_amd64_linux) || defined(VGP_amd64_darwin) || defined(VGP_amd64_freebsd) || defined(VGP_amd64_openbsd) # define GET_STARTREGS(srP) \ { ULong rip, rsp, rbp; \ __asm__ __volatile__( \ @@ -269,7 +269,7 @@ { #if defined(VGO_linux) (void)VG_(do_syscall1)(__NR_exit_group, status ); -#elif defined(VGO_darwin) +#elif defined(VGO_darwin) || defined(VGO_freebsd) || defined(VGO_openbsd) (void)VG_(do_syscall1)(__NR_exit, status ); #else # error Unknown OS diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_libcbase.c --- a/coregrind/m_libcbase.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_libcbase.c Thu Mar 31 15:57:55 2016 +0900 @@ -328,6 +328,26 @@ } } +// XXX Copied from OpenBSD's lib/libc/string/strlcpy.c +// XXX Copyright +SizeT VG_(strlcpy) ( HChar* dest, const HChar* src, SizeT siz ) +{ + HChar* d = dest; + const HChar* s = src; + SizeT n = siz; + + if (n > 0) { + while (--n > 0) { + if ((*d++ = *s++) == 0) break; + } + } + if (n == 0) { + if (siz > 0) *d = 0; + while (*s++) ; + } + return (s - src - 1); +} + Int VG_(strcmp) ( const HChar* s1, const HChar* s2 ) { while (True) { diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_libcfile.c --- a/coregrind/m_libcfile.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_libcfile.c Thu Mar 31 15:57:55 2016 +0900 @@ -68,6 +68,11 @@ return newfd; } +#if defined(VGO_freebsd) +#define M_FILEDESC_BUF 1000000 +static Char filedesc_buf[M_FILEDESC_BUF]; +#endif + /* Given a file descriptor, attempt to deduce its filename. To do this, we use /proc/self/fd/. If this doesn't point to a file, or if it doesn't exist, we return False. */ @@ -82,6 +87,43 @@ else return False; +#elif defined(VGO_freebsd) + Int mib[4]; + SysRes sres; + vki_size_t len; + Char *bp, *eb; + struct vki_kinfo_file *kf; + + mib[0] = VKI_CTL_KERN; + mib[1] = VKI_KERN_PROC; + mib[2] = VKI_KERN_PROC_FILEDESC; + mib[3] = sr_Res(VG_(do_syscall0)(__NR_getpid)); + len = sizeof(filedesc_buf); + sres = VG_(do_syscall6)(__NR___sysctl, (UWord)mib, 4, (UWord)filedesc_buf, + (UWord)&len, 0, 0); + if (sr_isError(sres)) { + VG_(debugLog)(0, "sysctl(kern.proc.filedesc)", "%s\n", VG_(strerror)(sr_Err(sres))); + return False; + } + /* Walk though the list. */ + bp = filedesc_buf; + eb = filedesc_buf + len; + while (bp < eb) { + kf = (struct vki_kinfo_file *)bp; + if (kf->kf_fd == fd) + break; + bp += kf->kf_structsize; + } + if (bp >= eb || *kf->kf_path == '\0') + VG_(strncpy)( buf, "[unknown]", n_buf ); + else + VG_(strncpy)( buf, kf->kf_path, n_buf ); + return True; + +# elif defined(VGO_aix5) + I_die_here; /* maybe just return False? */ + return False; + # elif defined(VGO_darwin) HChar tmp[VKI_MAXPATHLEN+1]; if (0 == VG_(fcntl)(fd, VKI_F_GETPATH, (UWord)tmp)) { @@ -93,18 +135,27 @@ } return False; +# elif defined(VGO_openbsd) + return False; + # else # error Unknown OS # endif } +#if defined(VGO_openbsd) || defined(VGO_netbsd) +SysRes VG_(mkfifo) ( const HChar* pathname, Int mode ) +{ + return VG_(do_syscall2)( __NR_mkfifo, (UWord)pathname, mode ); +} +#else SysRes VG_(mknod) ( const HChar* pathname, Int mode, UWord dev ) { # if defined(VGP_arm64_linux) /* ARM64 wants to use __NR_mknodat rather than __NR_mknod. */ SysRes res = VG_(do_syscall4)(__NR_mknodat, VKI_AT_FDCWD, (UWord)pathname, mode, dev); -# elif defined(VGO_linux) || defined(VGO_darwin) +# elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd) || defined(VGO_openbsd) SysRes res = VG_(do_syscall3)(__NR_mknod, (UWord)pathname, mode, dev); # else @@ -112,6 +163,7 @@ # endif return res; } +#endif SysRes VG_(open) ( const HChar* pathname, Int flags, Int mode ) { @@ -119,7 +171,7 @@ /* ARM64 wants to use __NR_openat rather than __NR_open. */ SysRes res = VG_(do_syscall4)(__NR_openat, VKI_AT_FDCWD, (UWord)pathname, flags, mode); -# elif defined(VGO_linux) +# elif defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd) SysRes res = VG_(do_syscall3)(__NR_open, (UWord)pathname, flags, mode); # elif defined(VGO_darwin) @@ -144,7 +196,7 @@ void VG_(close) ( Int fd ) { /* Hmm. Return value is not checked. That's uncool. */ -# if defined(VGO_linux) +# if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd) (void)VG_(do_syscall1)(__NR_close, fd); # elif defined(VGO_darwin) (void)VG_(do_syscall1)(__NR_close_nocancel, fd); @@ -156,7 +208,7 @@ Int VG_(read) ( Int fd, void* buf, Int count) { Int ret; -# if defined(VGO_linux) +# if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd) SysRes res = VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count); # elif defined(VGO_darwin) SysRes res = VG_(do_syscall3)(__NR_read_nocancel, fd, (UWord)buf, count); @@ -176,7 +228,7 @@ Int VG_(write) ( Int fd, const void* buf, Int count) { Int ret; -# if defined(VGO_linux) +# if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd) SysRes res = VG_(do_syscall3)(__NR_write, fd, (UWord)buf, count); # elif defined(VGO_darwin) SysRes res = VG_(do_syscall3)(__NR_write_nocancel, fd, (UWord)buf, count); @@ -209,9 +261,16 @@ # elif defined(VGP_arm64_linux) SysRes res = VG_(do_syscall2)(__NR_pipe2, (UWord)fd, 0); return sr_isError(res) ? -1 : 0; -# elif defined(VGO_linux) +# elif defined(VGO_linux) || defined(VGO_openbsd) SysRes res = VG_(do_syscall1)(__NR_pipe, (UWord)fd); return sr_isError(res) ? -1 : 0; +# elif defined(VGO_freebsd) + SysRes res = VG_(do_syscall0)(__NR_pipe); + if (!sr_isError(res)) { + fd[0] = sr_Res(res); + fd[1] = sr_ResHI(res); + } + return sr_isError(res) ? -1 : 0; # elif defined(VGO_darwin) /* __NR_pipe is UX64, so produces a double-word result */ SysRes res = VG_(do_syscall0)(__NR_pipe); @@ -227,7 +286,7 @@ Off64T VG_(lseek) ( Int fd, Off64T offset, Int whence ) { -# if defined(VGO_linux) || defined(VGP_amd64_darwin) +# if defined(VGO_linux) || defined(VGP_amd64_darwin) || defined(VGP_amd64_freebsd) || defined(VGP_amd64_openbsd) # if defined(__NR__llseek) Off64T result; SysRes res = VG_(do_syscall5)(__NR__llseek, fd, @@ -239,7 +298,7 @@ vg_assert(sizeof(Off64T) == sizeof(Word)); return sr_isError(res) ? (-1) : sr_Res(res); # endif -# elif defined(VGP_x86_darwin) +# elif defined(VGP_x86_darwin) || defined(VGP_x86_freebsd) || defined(VGP_x86_openbsd) SysRes res = VG_(do_syscall4)(__NR_lseek, fd, offset & 0xffffffff, offset >> 32, whence); return sr_isError(res) ? (-1) : sr_Res(res); @@ -280,7 +339,7 @@ SysRes res; VG_(memset)(vgbuf, 0, sizeof(*vgbuf)); -# if defined(VGO_linux) || defined(VGO_darwin) +# if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd) || defined(VGO_openbsd) /* First try with stat64. If that doesn't work out, fall back to the vanilla version. */ # if defined(__NR_stat64) @@ -317,7 +376,7 @@ SysRes res; VG_(memset)(vgbuf, 0, sizeof(*vgbuf)); -# if defined(VGO_linux) || defined(VGO_darwin) +# if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd) || defined(VGO_openbsd) /* First try with fstat64. If that doesn't work out, fall back to the vanilla version. */ # if defined(__NR_fstat64) @@ -380,7 +439,7 @@ SysRes VG_(dup2) ( Int oldfd, Int newfd ) { -# if defined(VGO_linux) || defined(VGO_darwin) +# if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd) || defined(VGO_openbsd) return VG_(do_syscall2)(__NR_dup2, oldfd, newfd); # else # error Unknown OS @@ -390,7 +449,7 @@ /* Returns -1 on error. */ Int VG_(fcntl) ( Int fd, Int cmd, Addr arg ) { -# if defined(VGO_linux) +# if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd) SysRes res = VG_(do_syscall3)(__NR_fcntl, fd, cmd, arg); # elif defined(VGO_darwin) SysRes res = VG_(do_syscall3)(__NR_fcntl_nocancel, fd, cmd, arg); @@ -467,6 +526,18 @@ startup_wd_acquired = True; return True; } +# elif defined(VGO_freebsd) || defined(VGO_openbsd) + /* Simple: just ask the kernel */ + { SysRes res + = VG_(do_syscall2)(__NR___getcwd, (UWord)startup_wd, szB-1); + vg_assert(startup_wd[szB-1] == 0); + if (sr_isError(res)) { + return False; + } else { + startup_wd_acquired = True; + return True; + } + } # else # error Unknown OS # endif @@ -500,6 +571,8 @@ (UWord)NULL); # elif defined(VGO_linux) res = VG_(do_syscall3)(__NR_poll, (UWord)fds, nfds, timeout); +# elif defined(VGO_freebsd) || defined(VGO_openbsd) + res = VG_(do_syscall3)(__NR_poll, (UWord)fds, nfds, timeout); # elif defined(VGO_darwin) res = VG_(do_syscall3)(__NR_poll_nocancel, (UWord)fds, nfds, timeout); # else @@ -522,7 +595,7 @@ return sr_isError(res) ? -1 : sr_Res(res); } -#if defined(VGO_linux) +#if defined(VGO_linux) || defined(VGO_freebsd) Int VG_(getdents64) (Int fd, struct vki_dirent64 *dirp, UInt count) { SysRes res; @@ -679,6 +752,15 @@ || defined(VGP_arm64_linux) res = VG_(do_syscall4)(__NR_pread64, fd, (UWord)buf, count, offset); return res; +# elif defined(VGP_amd64_freebsd) + vg_assert(sizeof(OffT) == 8); + res = VG_(do_syscall4)(__NR_pread, fd, (UWord)buf, count, offset); + return res; +# elif defined(VGP_x86_freebsd) + vg_assert(sizeof(OffT) == 8); + res = VG_(do_syscall5)(__NR_pread, fd, (UWord)buf, count, + offset & 0xffffffff, offset >> 32); + return res; # elif defined(VGP_amd64_darwin) vg_assert(sizeof(OffT) == 8); res = VG_(do_syscall4)(__NR_pread_nocancel, fd, (UWord)buf, count, offset); @@ -688,6 +770,10 @@ res = VG_(do_syscall5)(__NR_pread_nocancel, fd, (UWord)buf, count, offset & 0xffffffff, offset >> 32); return res; +# elif defined(VGP_amd64_openbsd) + vg_assert(sizeof(OffT) == 8); + res = VG_(do_syscall6)(__NR_pread, fd, (UWord)buf, count, 0, offset, 0); + return res; # else # error "Unknown platform" # endif @@ -825,7 +911,7 @@ */ Int VG_(connect_via_socket)( const HChar* str ) { -# if defined(VGO_linux) || defined(VGO_darwin) +# if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd) || defined(VGO_openbsd) Int sd, res; struct vki_sockaddr_in servAddr; UInt ip = 0; @@ -926,6 +1012,7 @@ # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \ || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \ + || defined(VGO_freebsd) || defined(VGO_openbsd) \ || defined(VGP_arm64_linux) SysRes res; res = VG_(do_syscall3)(__NR_socket, domain, type, protocol ); @@ -967,6 +1054,7 @@ # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \ || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \ + || defined(VGO_freebsd) || defined(VGO_openbsd) \ || defined(VGP_arm64_linux) SysRes res; res = VG_(do_syscall3)(__NR_connect, sockfd, (UWord)serv_addr, addrlen); @@ -1008,6 +1096,7 @@ # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \ || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \ + || defined(VGO_freebsd) || defined(VGO_openbsd) \ || defined(VGP_arm64_linux) SysRes res; res = VG_(do_syscall6)(__NR_sendto, sd, (UWord)msg, @@ -1039,6 +1128,7 @@ return sr_isError(res) ? -1 : sr_Res(res); # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \ + || defined(VGO_freebsd) || defined(VGO_openbsd) \ || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) SysRes res; res = VG_(do_syscall3)( __NR_getsockname, @@ -1071,6 +1161,7 @@ return sr_isError(res) ? -1 : sr_Res(res); # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \ + || defined(VGO_freebsd) || defined(VGO_openbsd) \ || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) SysRes res; res = VG_(do_syscall3)( __NR_getpeername, @@ -1106,6 +1197,7 @@ # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \ || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \ + || defined(VGO_freebsd) || defined(VGO_openbsd) \ || defined(VGP_arm64_linux) SysRes res; res = VG_(do_syscall5)( __NR_getsockopt, @@ -1151,7 +1243,7 @@ (UWord)optval, (UWord)optlen ); return sr_isError(res) ? -1 : sr_Res(res); -# elif defined(VGO_darwin) +# elif defined(VGO_darwin) || defined(VGO_freebsd) || defined(VGO_openbsd) SysRes res; res = VG_(do_syscall5)( __NR_setsockopt, (UWord)sd, (UWord)level, (UWord)optname, diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_libcproc.c --- a/coregrind/m_libcproc.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_libcproc.c Thu Mar 31 15:57:55 2016 +0900 @@ -66,7 +66,7 @@ const HChar *VG_(libdir) = VG_LIBDIR; const HChar *VG_(LD_PRELOAD_var_name) = -#if defined(VGO_linux) +#if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd) "LD_PRELOAD"; #elif defined(VGO_darwin) "DYLD_INSERT_LIBRARIES"; @@ -283,7 +283,7 @@ Int VG_(waitpid)(Int pid, Int *status, Int options) { -# if defined(VGO_linux) +# if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd) SysRes res = VG_(do_syscall4)(__NR_wait4, pid, (UWord)status, options, 0); return sr_isError(res) ? -1 : sr_Res(res); @@ -480,6 +480,18 @@ return sr_Res(res); +# elif defined(VGO_freebsd) + SysRes res; + long tid; + + res = VG_(do_syscall1)(__NR_thr_self, (UWord)&tid); + if (sr_isError(res)) + tid = sr_Res(VG_(do_syscall0)(__NR_getpid)); + return tid; + +# elif defined(VGO_openbsd) + return sr_Res( VG_(do_syscall0)(__NR_getthrid) ); + # elif defined(VGO_darwin) // Darwin's gettid syscall is something else. // Use Mach thread ports for lwpid instead. @@ -557,6 +569,7 @@ # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \ || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \ + || defined(VGO_freebsd) || defined(VGO_openbsd) \ || defined(VGO_darwin) || defined(VGP_s390x_linux) \ || defined(VGP_mips32_linux) || defined(VGP_arm64_linux) SysRes sres; @@ -597,7 +610,7 @@ return -1; return sr_Res(res); -# elif defined(VGO_linux) +# elif defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd) SysRes res; res = VG_(do_syscall0)(__NR_fork); if (sr_isError(res)) @@ -645,6 +658,13 @@ } } +# elif defined(VGO_freebsd) || defined(VGO_openbsd) + { SysRes res; + struct vki_timeval tv_now; + res = VG_(do_syscall2)(__NR_gettimeofday, (UWord)&tv_now, (UWord)NULL); + vg_assert(! sr_isError(res)); + now = tv_now.tv_sec * 1000000ULL + tv_now.tv_usec; + } # elif defined(VGO_darwin) // Weird: it seems that gettimeofday() doesn't fill in the timeval, but // rather returns the tv_sec as the low 32 bits of the result and the @@ -733,6 +753,90 @@ (*atforks[i].child)(tid); } +/* --------------------------------------------------------------------- + FreeBSD sysctl(), modfind(), etc + ------------------------------------------------------------------ */ + +#if defined(VGO_openbsd) +#define __NR___sysctl __NR_sysctl +#endif + +#if defined(VGO_freebsd) || defined(VGO_openbsd) +Int VG_(sysctl)(int *name, UInt namelen, void *oldp, vki_size_t *oldlenp, void *newp, vki_size_t newlen) +{ + SysRes res; + + res = VG_(do_syscall6)(__NR___sysctl, (UWord)name, namelen, (UWord)oldp, (UWord)oldlenp, (UWord)newp, newlen); + if (sr_isError(res)) + return -1; + return sr_Res(res); +} + +Int VG_(sysctlbyname)(const Char *name, void *oldp, vki_size_t *oldlenp, void *newp, vki_size_t newlen) +{ + Int oid[2]; + Int real_oid[10]; + vki_size_t oidlen; + int error; + + oid[0] = 0; /* magic */ + oid[1] = 3; /* undocumented */ + oidlen = sizeof(real_oid); + error = VG_(sysctl)(oid, 2, real_oid, &oidlen, (void *)name, VG_(strlen)(name)); + if (error < 0) + return error; + oidlen /= sizeof(int); + error = VG_(sysctl)(real_oid, oidlen, oldp, oldlenp, newp, newlen); + return error; +} + +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) +{ +#if defined(VGP_amd64_freebsd) || defined(VGP_amd64_openbsd) + return False; +#elif defined(VGP_x86_freebsd) || defined(VGP_x86_openbsd) + Int oid[2], error; + vki_size_t len; + char machbuf[32]; + static Int is32on64 = -1; + + 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 /* --------------------------------------------------------------------- icache invalidation diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_libcsetjmp.c --- a/coregrind/m_libcsetjmp.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_libcsetjmp.c Thu Mar 31 15:57:55 2016 +0900 @@ -379,13 +379,13 @@ /* ------------ amd64-{linux,darwin} ------------ */ -#if defined(VGP_amd64_linux) || defined(VGP_amd64_darwin) +#if defined(VGP_amd64_linux) || defined(VGP_amd64_darwin) || defined(VGP_amd64_freebsd) || defined(VGP_amd64_openbsd) __asm__( ".text" "\n" "" "\n" -#if defined(VGP_amd64_linux) +#if defined(VGP_amd64_linux) || defined(VGP_amd64_freebsd) || defined(VGP_amd64_openbsd) ".global VG_MINIMAL_SETJMP" "\n" // rdi = jmp_buf "VG_MINIMAL_SETJMP:" "\n" @@ -422,7 +422,7 @@ "" "\n" -#if defined(VGP_amd64_linux) +#if defined(VGP_amd64_linux) || defined(VGP_amd64_freebsd) || defined(VGP_amd64_openbsd) ".global VG_MINIMAL_LONGJMP" "\n" "VG_MINIMAL_LONGJMP:" "\n" // rdi = jmp_buf @@ -470,18 +470,18 @@ #endif ); -#endif /* VGP_amd64_linux || VGP_amd64_darwin */ +#endif /* VGP_amd64_linux || VGP_amd64_darwin || VGP_amd64_freebsd || VGP_amd64_openbsd */ /* ------------ x86-{linux,darwin} ------------ */ -#if defined(VGP_x86_linux) || defined(VGP_x86_darwin) +#if defined(VGP_x86_linux) || defined(VGP_x86_darwin) || defined(VGP_x86_freebsd) || defined(VGP_x86_openbsd) __asm__( ".text" "\n" "" "\n" -#if defined(VGP_x86_linux) +#if defined(VGP_x86_linux) || defined(VGP_x86_freebsd) || defined(VGP_x86_openbsd) ".global VG_MINIMAL_SETJMP" "\n" // eax = jmp_buf "VG_MINIMAL_SETJMP:" "\n" @@ -512,7 +512,7 @@ "" "\n" -#if defined(VGP_x86_linux) +#if defined(VGP_x86_linux) || defined(VGP_x86_freebsd) || defined(VGP_x86_openbsd) ".global VG_MINIMAL_LONGJMP" "\n" "VG_MINIMAL_LONGJMP:" "\n" // eax = jmp_buf @@ -546,7 +546,7 @@ #endif ); -#endif /* VGP_x86_linux || VGP_x86_darwin */ +#endif /* VGP_x86_linux || VGP_x86_darwin || VGP_x86_freebsd || VGP_x86_openbsd */ #if defined(VGP_mips32_linux) diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_libcsignal.c --- a/coregrind/m_libcsignal.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_libcsignal.c Thu Mar 31 15:57:55 2016 +0900 @@ -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" /* IMPORTANT: on Darwin it is essential to use the _nocancel versions of syscalls rather than the vanilla version, if a _nocancel version @@ -51,49 +52,69 @@ Int VG_(sigfillset)( vki_sigset_t* set ) { +#if 0 Int i; if (set == NULL) return -1; for (i = 0; i < _VKI_NSIG_WORDS; i++) set->sig[i] = ~0; +#else + *set = ~0U; +#endif return 0; } Int VG_(sigemptyset)( vki_sigset_t* set ) { +#if 0 Int i; if (set == NULL) return -1; for (i = 0; i < _VKI_NSIG_WORDS; i++) set->sig[i] = 0; +#else + *set = 0U; +#endif return 0; } Bool VG_(isemptysigset)( const vki_sigset_t* set ) { +#if 0 Int i; vg_assert(set != NULL); for (i = 0; i < _VKI_NSIG_WORDS; i++) if (set->sig[i] != 0) return False; return True; +#else + return (*set == 0U); +#endif } Bool VG_(isfullsigset)( const vki_sigset_t* set ) { +#if 0 Int i; vg_assert(set != NULL); for (i = 0; i < _VKI_NSIG_WORDS; i++) if (set->sig[i] != ~0) return False; return True; +#else + return (*set == ~0U); +#endif } Bool VG_(iseqsigset)( const vki_sigset_t* set1, const vki_sigset_t* set2 ) { +#if 0 Int i; vg_assert(set1 != NULL && set2 != NULL); for (i = 0; i < _VKI_NSIG_WORDS; i++) if (set1->sig[i] != set2->sig[i]) return False; return True; +#else + return *set1 == *set2; +#endif } @@ -104,7 +125,11 @@ if (signum < 1 || signum > _VKI_NSIG) return -1; signum--; +#if 0 set->sig[signum / _VKI_NSIG_BPW] |= (1ULL << (signum % _VKI_NSIG_BPW)); +#else + *set |= 1U << signum; +#endif return 0; } @@ -115,7 +140,11 @@ if (signum < 1 || signum > _VKI_NSIG) return -1; signum--; +#if 0 set->sig[signum / _VKI_NSIG_BPW] &= ~(1ULL << (signum % _VKI_NSIG_BPW)); +#else + *set &= ~(1U << signum); +#endif return 0; } @@ -126,46 +155,66 @@ if (signum < 1 || signum > _VKI_NSIG) return 0; signum--; +#if 0 if (1 & ((set->sig[signum / _VKI_NSIG_BPW]) >> (signum % _VKI_NSIG_BPW))) return 1; else return 0; +#else + return (*set & (1U << signum)) != 0; +#endif } /* Add all signals in src to dst. */ void VG_(sigaddset_from_set)( vki_sigset_t* dst, vki_sigset_t* src ) { +#if 0 Int i; vg_assert(dst != NULL && src != NULL); for (i = 0; i < _VKI_NSIG_WORDS; i++) dst->sig[i] |= src->sig[i]; +#else + *dst |= *src; +#endif } /* Remove all signals in src from dst. */ void VG_(sigdelset_from_set)( vki_sigset_t* dst, vki_sigset_t* src ) { +#if 0 Int i; vg_assert(dst != NULL && src != NULL); for (i = 0; i < _VKI_NSIG_WORDS; i++) dst->sig[i] &= ~(src->sig[i]); +#else + *dst &= ~*src; +#endif } /* dst = dst `intersect` src. */ void VG_(sigintersectset)( vki_sigset_t* dst, vki_sigset_t* src ) { +#if 0 Int i; vg_assert(dst != NULL && src != NULL); for (i = 0; i < _VKI_NSIG_WORDS; i++) dst->sig[i] &= src->sig[i]; +#else + *dst &= *src; +#endif } /* dst = ~src */ void VG_(sigcomplementset)( vki_sigset_t* dst, vki_sigset_t* src ) { +#if 0 Int i; vg_assert(dst != NULL && src != NULL); for (i = 0; i < _VKI_NSIG_WORDS; i++) dst->sig[i] = ~ src->sig[i]; +#else + *dst = ~*src; +#endif } @@ -174,7 +223,7 @@ */ Int VG_(sigprocmask)( Int how, const vki_sigset_t* set, vki_sigset_t* oldset) { -# if defined(VGO_linux) +# if defined(VGO_linux) || defined(VGO_freebsd) # if defined(__NR_rt_sigprocmask) SysRes res = VG_(do_syscall4)(__NR_rt_sigprocmask, how, (UWord)set, (UWord)oldset, @@ -190,12 +239,43 @@ __NR___pthread_sigmask instead. */ SysRes res = VG_(do_syscall3)(__NR___pthread_sigmask, how, (UWord)set, (UWord)oldset); +# elif defined(VGO_openbsd) + /* OpenBSD's sigprocmask(2) returns old mask as return value. */ + UWord v; + if (set == NULL) { + how = VKI_SIG_BLOCK; + v = 0; + } else { + v = *set; + } + SysRes res = VG_(do_syscall2)(__NR_sigprocmask, how, v); + if (!sr_isError(res)) { + if (oldset != NULL) { + *oldset = sr_Res(res); + } + } # else # error "Unknown OS" # endif return sr_isError(res) ? -1 : 0; } +#if defined(VGO_openbsd) +Int VG_(sigpending)( vki_sigset_t* set ) +{ + SysRes res = VG_(do_syscall0)(__NR_sigpending); + if (!sr_isError(res)) { + *set = sr_Res(res); + } + return 0; +} + +Int VG_(sigsuspend)( const vki_sigset_t* set ) +{ + (void)VG_(do_syscall1)(__NR_sigsuspend, *set); + return 0; +} +#endif #if defined(VGO_darwin) /* A helper function for sigaction on Darwin. */ @@ -272,6 +352,11 @@ } return sr_isError(res) ? -1 : 0; +# elif defined(VGO_freebsd) || defined(VGO_openbsd) + SysRes res = VG_(do_syscall3)(__NR_sigaction, + signum, (UWord)act, (UWord)oldact); + return sr_isError(res) ? -1 : 0; + # else # error "Unsupported OS" # endif @@ -283,7 +368,7 @@ VG_(convert_sigaction_fromK_to_toK)( vki_sigaction_fromK_t* fromK, /*OUT*/vki_sigaction_toK_t* toK ) { -# if defined(VGO_linux) +# if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd) *toK = *fromK; # elif defined(VGO_darwin) toK->ksa_handler = fromK->ksa_handler; @@ -298,9 +383,9 @@ Int VG_(kill)( Int pid, Int signo ) { -# if defined(VGO_linux) +# if defined(VGO_linux) || defined(VGO_openbsd) SysRes res = VG_(do_syscall2)(__NR_kill, pid, signo); -# elif defined(VGO_darwin) +# elif defined(VGO_darwin) || defined(VGO_freebsd) SysRes res = VG_(do_syscall3)(__NR_kill, pid, signo, 1/*posix-compliant*/); # else @@ -324,6 +409,14 @@ res = VG_(do_syscall2)(__NR___pthread_kill, lwpid, signo); return sr_isError(res) ? -1 : 0; +# elif defined(VGO_freebsd) + SysRes res; + res = VG_(do_syscall2)(__NR_thr_kill, lwpid, signo); + return sr_isError(res) ? -1 : 0; + +# elif defined(VGO_openbsd) + I_die_here; + # else # error "Unsupported plat" # endif @@ -477,6 +570,152 @@ return i; } +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + +/* + * 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 || defined(VGO_openbsd) +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 + +// XXX VGO_openbsd +#ifndef __NR_sigtimedwait +#define __NR_sigtimedwait 0 +#endif + +Int VG_(sigtimedwait_zero)( const vki_sigset_t *set, + vki_siginfo_t *info ) +{ +# if (defined(__FreeBSD__) && __FreeBSD__ < 7) || defined(VGO_openbsd) + Int i, ir; + SysRes sr; + vki_sigset_t pending, blocked, allbutone; + vki_sigaction_toK_t sa; + vki_sigaction_fromK_t saved_sa; +# if defined(VGP_x86_freebsd) + Int is32on64; +# endif + Bool have_sigtimedwait_zero = True; +# endif + static const struct vki_timespec zero = { 0, 0 }; + +# if defined(VGO_freebsd) && __FreeBSD__ < 7 + Int osreldate; + + 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 + if (have_sigtimedwait_zero) { +# elif defined(VGO_openbsd) + have_sigtimedwait_zero = False; + if (have_sigtimedwait_zero) { +# endif + SysRes res = VG_(do_syscall3)(__NR_sigtimedwait, (UWord)set, (UWord)info, + (UWord)&zero); + return sr_isError(res) ? -1 : sr_Res(res); +# if (defined(VGO_freebsd) && __FreeBSD__ < 7) || defined(VGO_openbsd) + } + + /* Find out what's pending: FreeBSD sigpending */ +#if !defined(VGO_openbsd) + sr = VG_(do_syscall1)(__NR_sigpending, (UWord)&pending); +#else + sr = VG_(do_syscall0)(__NR_sigpending); + pending = sr_Res(sr); +#endif + vg_assert(!sr_isError(sr)); + + /* don't try for signals not in 'set' */ + /* pending = pending `intersect` set */ +#if !defined(VGO_openbsd) + for (i = 0; i < _VKI_NSIG_WORDS; i++) + pending.sig[i] &= set->sig[i]; +#else + pending &= *set; +#endif + + /* 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 */ +#if !defined(VGO_openbsd) + for (i = 0; i < _VKI_NSIG_WORDS; i++) + pending.sig[i] &= blocked.sig[i]; +#else + pending &= blocked; +#endif + + /* 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. */ +#if !defined(VGO_openbsd) + sr = VG_(do_syscall1)(__NR_sigsuspend, (UWord)&allbutone); +#else + sr = VG_(do_syscall1)(__NR_sigsuspend, (UWord)allbutone); + /* OpenBSD's sigsuspend(2) libc wrapper overwrites %eax to -1 */ + /* OpenBSD's sigsuspend(2) always return -1 with errno == EINTR */ + /* EINTR -> rflags:PSL_C is set */ + sr._val = (UWord)-1; + sr._isError = 0; +#endif + vg_assert(!sr_isError(sr)); + if (0) + VG_(debugLog)(0, "libcsignal", + "sigtimedwait_zero: sigsuspend got res %ld err %ld\n", + sr_Res(sr), sr_Err(sr)); + vg_assert(sr_Res(sr) == (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" #endif diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_machine.c --- a/coregrind/m_machine.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_machine.c Thu Mar 31 15:57:55 2016 +0900 @@ -33,6 +33,7 @@ #include "pub_core_threadstate.h" #include "pub_core_libcassert.h" #include "pub_core_libcbase.h" +#include "pub_core_libcprint.h" #include "pub_core_libcfile.h" #include "pub_core_libcprint.h" #include "pub_core_mallocfree.h" @@ -132,6 +133,47 @@ # endif } +#if 0 +void VG_(set_syscall_return_shadows) ( ThreadId tid, + /* shadow vals for the result */ + UWord s1res, UWord s2res, + /* shadow vals for the error val */ + UWord s1err, UWord s2err ) +{ +# if defined(VGP_x86_linux) + VG_(threads)[tid].arch.vex_shadow1.guest_EAX = s1res; + VG_(threads)[tid].arch.vex_shadow2.guest_EAX = s2res; +# elif defined(VGP_amd64_linux) + VG_(threads)[tid].arch.vex_shadow1.guest_RAX = s1res; + VG_(threads)[tid].arch.vex_shadow2.guest_RAX = s2res; +# elif defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) + VG_(threads)[tid].arch.vex_shadow1.guest_GPR3 = s1res; + VG_(threads)[tid].arch.vex_shadow2.guest_GPR3 = s2res; +# elif defined(VGP_arm_linux) + VG_(threads)[tid].arch.vex_shadow1.guest_R0 = s1res; + VG_(threads)[tid].arch.vex_shadow2.guest_R0 = s2res; +# elif defined(VGO_darwin) + // GrP fixme darwin syscalls may return more values (2 registers plus error) +# elif defined(VGP_x86_freebsd) || defined(VGP_x86_openbsd) + VG_(threads)[tid].arch.vex_shadow1.guest_EAX = s1res; + VG_(threads)[tid].arch.vex_shadow2.guest_EAX = s2res; + /* QQQ: this is very incomplete. EDX and EFL are affected */ +# elif defined(VGP_amd64_freebsd) || defined(VGP_amd64_openbsd) + VG_(threads)[tid].arch.vex_shadow1.guest_RAX = s1res; + VG_(threads)[tid].arch.vex_shadow2.guest_RAX = s2res; + /* QQQ: this is very incomplete. EDX and EFL are affected */ +# elif defined(VGP_s390x_linux) + VG_(threads)[tid].arch.vex_shadow1.guest_r2 = s1res; + VG_(threads)[tid].arch.vex_shadow2.guest_r2 = s2res; +# elif defined(VGP_mips32_linux) || defined(VGP_mips64_linux) + VG_(threads)[tid].arch.vex_shadow1.guest_r2 = s1res; + VG_(threads)[tid].arch.vex_shadow2.guest_r2 = s2res; +# else +# error "Unknown plat" +# endif +} +#endif + void VG_(get_shadow_regs_area) ( ThreadId tid, /*DST*/UChar* dst, @@ -750,6 +792,20 @@ if (!have_cx8) return False; +#if defined(VGP_x86_freebsd) || defined(VGP_x86_openbsd) + if (have_sse1 || have_sse2) { + Int sc, error; + vki_size_t scl; + /* Regardless of whether cpuid says, the OS has to enable SSE first! */ + scl = sizeof(sc); + error = VG_(sysctlbyname)("hw.instruction_sse", &sc, &scl, 0, 0); + if (error == -1 || sc != 1) { + have_sse1 = 0; + have_sse2 = 0; + VG_(message)(Vg_UserMsg, "Warning: cpu has SSE, but the OS has not enabled it. Disabling in valgrind!"); + } + } +#endif /* Figure out if this is an AMD that can do MMXEXT. */ have_mmxext = False; if (0 == VG_(strcmp)(vstr, "AuthenticAMD") @@ -1750,6 +1806,8 @@ # if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \ || defined(VGP_arm_linux) || defined(VGO_darwin) \ || defined(VGP_ppc32_linux) || defined(VGP_ppc64le_linux) \ + || defined(VGP_x86_freebsd) || defined(VGP_amd64_freebsd) \ + || defined(VGP_x86_openbsd) || defined(VGP_amd64_openbsd) \ || defined(VGP_s390x_linux) || defined(VGP_mips32_linux) \ || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) return f; diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_main.c --- a/coregrind/m_main.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_main.c Thu Mar 31 15:57:55 2016 +0900 @@ -1363,7 +1363,9 @@ VG_(umsg)("\n"); if (VG_(clo_verbosity) > 1) { +#if !defined(VGO_freebsd) && !defined(VGO_openbsd) SysRes fd; +#endif VexArch vex_arch; VexArchInfo vex_archinfo; if (!logging_to_fd) @@ -1376,6 +1378,7 @@ } VG_(message)(Vg_DebugMsg, "Contents of /proc/version:\n"); +#if !defined(VGO_freebsd) && !defined(VGO_openbsd) fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 ); if (sr_isError(fd)) { VG_(message)(Vg_DebugMsg, " can't open /proc/version\n"); @@ -1393,6 +1396,7 @@ VG_(close)(sr_Res(fd)); # undef BUF_LEN } +#endif VG_(machine_get_VexArchInfo)( &vex_arch, &vex_archinfo ); VG_(message)( @@ -1419,7 +1423,7 @@ /* Number of file descriptors that Valgrind tries to reserve for it's own use - just a small constant. */ -#define N_RESERVED_FDS (10) +#define N_RESERVED_FDS (20) static void setup_file_descriptors(void) { @@ -1855,7 +1859,7 @@ if (!need_help) { VG_(debugLog)(1, "main", "Create initial image\n"); -# if defined(VGO_linux) || defined(VGO_darwin) +# if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)|| defined(VGO_openbsd) the_iicii.argv = argv; the_iicii.envp = envp; the_iicii.toolname = toolname; @@ -2057,10 +2061,12 @@ VG_(debugLog)(1, "main", "Wait for GDB\n"); VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)()); -# if defined(VGP_x86_linux) +# if defined(VGP_x86_linux) || defined(VGP_x86_freebsd) || defined(VGP_x86_openbsd) iters = 10; # elif defined(VGP_amd64_linux) || defined(VGP_ppc64be_linux) \ - || defined(VGP_ppc64le_linux) + || defined(VGP_ppc64le_linux) \ + || defined(VGP_amd64_freebsd) \ + || defined(VGP_amd64_openbsd) iters = 10; # elif defined(VGP_ppc32_linux) iters = 5; @@ -2117,7 +2123,7 @@ VG_(free), sizeof(Addr_n_ULong) ); tl_assert(addr2dihandle); -# if defined(VGO_linux) +# if defined(VGO_linux) || defined(VGO_freebsd) { Addr* seg_starts; Int n_seg_starts; Addr_n_ULong anu; @@ -2141,7 +2147,7 @@ VG_(free)( seg_starts ); } -# elif defined(VGO_darwin) +# elif defined(VGO_darwin) || defined(VGO_openbsd) { Addr* seg_starts; Int n_seg_starts; seg_starts = VG_(get_segment_starts)( &n_seg_starts ); @@ -2696,6 +2702,9 @@ VG_(set_default_handler)(VKI_SIGBUS); VG_(set_default_handler)(VKI_SIGILL); VG_(set_default_handler)(VKI_SIGFPE); +#if defined(VGO_freebsd) || defined(VGO_openbsd) + VG_(set_default_handler)(VKI_SIGSYS); +#endif // We were exiting, so assert that... vg_assert(VG_(is_exiting)(tid)); @@ -2715,7 +2724,7 @@ /*=== Getting to main() alive: LINUX ===*/ /*====================================================================*/ -#if defined(VGO_linux) +#if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd) /* If linking of the final executables is done with glibc present, then Valgrind starts at main() above as usual, and all of the @@ -3054,6 +3063,32 @@ "\tmov x0, x1\n" "\tb _start_in_C_linux\n" ); +#elif defined(VGP_x86_freebsd) || defined(VGP_x86_openbsd) +asm("\n" + ".text\n" +#if defined(VGP_x86_freebsd) + "\t.globl _start\n" + "\t.type _start,@function\n" + "_start:\n" +#else + "\t.globl __start\n" + "\t.type __start,@function\n" + "__start:\n" +#endif + /* set up the new stack in %eax */ + "\tmovl $vgPlain_interim_stack, %eax\n" + "\taddl $"VG_STRINGIFY(VG_STACK_GUARD_SZB)", %eax\n" + "\taddl $"VG_STRINGIFY(VG_STACK_ACTIVE_SZB)", %eax\n" + "\tsubl $16, %eax\n" + "\tandl $~15, %eax\n" + /* install it, and collect the original one */ + "\txchgl %eax, %esp\n" + /* call _start_in_C_linux, passing it the startup %esp */ + "\tpushl %eax\n" + "\tcall _start_in_C_linux\n" + "\thlt\n" + ".previous\n" +); #elif defined(VGP_mips32_linux) asm("\n" "\t.type _gp_disp,@object\n" @@ -3098,6 +3133,45 @@ "\tbreak 0x7\n" ".previous\n" ); +#elif defined(VGP_amd64_freebsd) +asm("\n" + ".text\n" + "\t.globl _start\n" + "\t.type _start,@function\n" + "_start:\n" + /* set up the new stack in %rsi */ + "\tmovq $vgPlain_interim_stack, %rsi\n" + "\taddq $"VG_STRINGIFY(VG_STACK_GUARD_SZB)", %rsi\n" + "\taddq $"VG_STRINGIFY(VG_STACK_ACTIVE_SZB)", %rsi\n" + "\tandq $~15, %rsi\n" + /* install it, and collect the original one */ + "\txchgq %rsi, %rsp\n" + /* call _start_in_C_amd64_freebsd, passing it the startup %rsp */ + "\tcall _start_in_C_amd64_freebsd\n" + "\thlt\n" + ".previous\n" +); +#elif defined(VGP_amd64_openbsd) +asm("\n" + ".text\n" + "\t.globl __start\n" + "\t.type __start,@function\n" + "__start:\n" + /* pass args (long argc, char **argv, ...) on stack */ + "\tmovq %rsp, %rdi\n" + /* set up the new stack in %rsi */ + "\tmovq $vgPlain_interim_stack, %rsi\n" + "\taddq $"VG_STRINGIFY(VG_STACK_GUARD_SZB)", %rsi\n" + "\taddq $"VG_STRINGIFY(VG_STACK_ACTIVE_SZB)", %rsi\n" + "\tandq $~15, %rsi\n" + /* install it, and collect the original one */ + "\txchgq %rsi, %rsp\n" + /* call _start_in_C_amd64_freebsd, passing it the startup %rsp */ + "\tcall _start_in_C_amd64_openbsd\n" + "\thlt\n" + ".size __start, . - __start\n" + ".previous\n" +); #elif defined(VGP_mips64_linux) asm( ".text\n" @@ -3138,16 +3212,70 @@ ".previous\n" ); #else -# error "Unknown linux platform" +# error "Unknown platform" +#endif + +#if defined(VGO_openbsd) +__asm(" .section \".note.openbsd.ident\", \"a\"\n" +" .p2align 2\n" +" .long 8\n" +" .long 4\n" +" .long 1\n" +" .ascii \"OpenBSD\\0\"\n" +" .long 0\n" +" .previous\n"); #endif /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */ #define _GNU_SOURCE #define _FILE_OFFSET_BITS 64 /* This is in order to get AT_NULL and AT_PAGESIZE. */ +#if !defined(VGO_openbsd) #include +#else +#include +#endif /* --- !!! --- EXTERNAL HEADERS end --- !!! --- */ +#if defined(VGP_amd64_freebsd) +void _start_in_C_amd64_freebsd ( UWord* pArgc, UWord *initial_sp ); +void _start_in_C_amd64_freebsd ( UWord* pArgc, UWord *initial_sp ) +{ + Int r; + Word argc = pArgc[0]; + HChar** argv = (HChar**)&pArgc[1]; + HChar** envp = (HChar**)&pArgc[1+argc+1]; + + VG_(memset)( &the_iicii, 0, sizeof(the_iicii) ); + VG_(memset)( &the_iifii, 0, sizeof(the_iifii) ); + + the_iicii.sp_at_startup = (Addr)initial_sp; + + r = valgrind_main( (Int)argc, argv, envp ); + /* NOTREACHED */ + VG_(exit)(r); +} + +#elif defined(VGP_amd64_openbsd) +void _start_in_C_amd64_openbsd ( UWord* pArgc, UWord *initial_sp ); +void _start_in_C_amd64_openbsd ( UWord* pArgc, UWord *initial_sp ) +{ + Int r; + Word argc = pArgc[0]; + HChar** argv = (HChar**)&pArgc[1]; + HChar** envp = (HChar**)&pArgc[1+argc+1]; + + VG_(memset)( &the_iicii, 0, sizeof(the_iicii) ); + VG_(memset)( &the_iifii, 0, sizeof(the_iifii) ); + + the_iicii.sp_at_startup = (Addr)initial_sp; + + r = valgrind_main( (Int)argc, argv, envp ); + /* NOTREACHED */ + VG_(exit)(r); +} + +#else /* Avoid compiler warnings: this fn _is_ used, but labelling it 'static' causes gcc to complain it isn't. attribute 'used' also ensures the code is not eliminated at link @@ -3203,6 +3331,7 @@ /* NOTREACHED */ VG_(exit)(r); } +#endif /*====================================================================*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_options.c --- a/coregrind/m_options.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_options.c Thu Mar 31 15:57:55 2016 +0900 @@ -120,7 +120,12 @@ const HChar* VG_(clo_req_tsyms)[VG_CLO_MAX_REQ_TSYMS]; HChar* VG_(clo_require_text_symbol) = NULL; Bool VG_(clo_run_libc_freeres) = True; +#if !defined(VGO_openbsd) Bool VG_(clo_track_fds) = False; +#else +/* To omit filename lookup via procfs or kvm */ +Bool VG_(clo_track_fds) = True; +#endif Bool VG_(clo_show_below_main)= False; Bool VG_(clo_show_emwarns) = False; Word VG_(clo_max_stackframe) = 2000000; diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_redir.c --- a/coregrind/m_redir.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_redir.c Thu Mar 31 15:57:55 2016 +0900 @@ -1427,6 +1427,9 @@ //); } +# elif defined(VGP_x86_freebsd) || defined(VGP_amd64_freebsd) \ + || defined(VGP_x86_openbsd) || defined(VGP_amd64_openbsd) +/* XXX do something real if needed */ # elif defined(VGP_x86_darwin) /* If we're using memcheck, use these intercepts right from the start, otherwise dyld makes a lot of noise. */ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_replacemalloc/vg_replace_malloc.c --- a/coregrind/m_replacemalloc/vg_replace_malloc.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_replacemalloc/vg_replace_malloc.c Thu Mar 31 15:57:55 2016 +0900 @@ -296,6 +296,10 @@ ALLOC_or_NULL(VG_Z_LIBC_SONAME, malloc, malloc); ALLOC_or_NULL(SO_SYN_MALLOC, malloc, malloc); +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + ALLOC_or_NULL(VG_Z_LIBC_SONAME, malloc, malloc); + ALLOC_or_NULL(SO_SYN_MALLOC, malloc, malloc); + #elif defined(VGO_darwin) ALLOC_or_NULL(VG_Z_LIBC_SONAME, malloc, malloc); ALLOC_or_NULL(SO_SYN_MALLOC, malloc, malloc); @@ -316,16 +320,32 @@ // operator new(unsigned int), GNU mangling #if VG_WORDSIZE == 4 ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znwj, __builtin_new); + ALLOC_or_BOMB(VG_Z_LIBSUPCXX_SONAME, _Znwj, __builtin_new); ALLOC_or_BOMB(VG_Z_LIBC_SONAME, _Znwj, __builtin_new); ALLOC_or_BOMB(SO_SYN_MALLOC, _Znwj, __builtin_new); #endif // operator new(unsigned long), GNU mangling #if VG_WORDSIZE == 8 ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znwm, __builtin_new); + ALLOC_or_BOMB(VG_Z_LIBSUPCXX_SONAME, _Znwm, __builtin_new); ALLOC_or_BOMB(VG_Z_LIBC_SONAME, _Znwm, __builtin_new); ALLOC_or_BOMB(SO_SYN_MALLOC, _Znwm, __builtin_new); #endif +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + // operator new(unsigned int), GNU mangling + #if VG_WORDSIZE == 4 + ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znwj, __builtin_new); + ALLOC_or_BOMB(VG_Z_LIBSUPCXX_SONAME, _Znwj, __builtin_new); + ALLOC_or_BOMB(SO_SYN_MALLOC, _Znwm, __builtin_new); + #endif + // operator new(unsigned long), GNU mangling + #if VG_WORDSIZE == 8 + ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znwm, __builtin_new); + ALLOC_or_BOMB(VG_Z_LIBSUPCXX_SONAME, _Znwm, __builtin_new); + ALLOC_or_BOMB(SO_SYN_MALLOC, _Znwm, __builtin_new); + #endif + #elif defined(VGO_darwin) // operator new(unsigned int), GNU mangling #if VG_WORDSIZE == 4 @@ -347,16 +367,32 @@ // operator new(unsigned, std::nothrow_t const&), GNU mangling #if VG_WORDSIZE == 4 ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnwjRKSt9nothrow_t, __builtin_new); + ALLOC_or_NULL(VG_Z_LIBSUPCXX_SONAME, _ZnwjRKSt9nothrow_t, __builtin_new); ALLOC_or_NULL(VG_Z_LIBC_SONAME, _ZnwjRKSt9nothrow_t, __builtin_new); ALLOC_or_NULL(SO_SYN_MALLOC, _ZnwjRKSt9nothrow_t, __builtin_new); #endif // operator new(unsigned long, std::nothrow_t const&), GNU mangling #if VG_WORDSIZE == 8 ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnwmRKSt9nothrow_t, __builtin_new); + ALLOC_or_NULL(VG_Z_LIBSUPCXX_SONAME, _ZnwmRKSt9nothrow_t, __builtin_new); ALLOC_or_NULL(VG_Z_LIBC_SONAME, _ZnwmRKSt9nothrow_t, __builtin_new); ALLOC_or_NULL(SO_SYN_MALLOC, _ZnwmRKSt9nothrow_t, __builtin_new); #endif +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + // operator new(unsigned, std::nothrow_t const&), GNU mangling + #if VG_WORDSIZE == 4 + ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnwjRKSt9nothrow_t, __builtin_new); + ALLOC_or_NULL(VG_Z_LIBSUPCXX_SONAME, _ZnwjRKSt9nothrow_t, __builtin_new); + ALLOC_or_NULL(SO_SYN_MALLOC, _ZnwjRKSt9nothrow_t, __builtin_new); + #endif + // operator new(unsigned long, std::nothrow_t const&), GNU mangling + #if VG_WORDSIZE == 8 + ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnwmRKSt9nothrow_t, __builtin_new); + ALLOC_or_NULL(VG_Z_LIBSUPCXX_SONAME, _ZnwmRKSt9nothrow_t, __builtin_new); + ALLOC_or_NULL(SO_SYN_MALLOC, _ZnwjRKSt9nothrow_t, __builtin_new); + #endif + #elif defined(VGO_darwin) // operator new(unsigned, std::nothrow_t const&), GNU mangling #if VG_WORDSIZE == 4 @@ -381,16 +417,32 @@ // operator new[](unsigned int), GNU mangling #if VG_WORDSIZE == 4 ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znaj, __builtin_vec_new ); + ALLOC_or_BOMB(VG_Z_LIBSUPCXX_SONAME, _Znaj, __builtin_vec_new ); ALLOC_or_BOMB(VG_Z_LIBC_SONAME, _Znaj, __builtin_vec_new ); ALLOC_or_BOMB(SO_SYN_MALLOC, _Znaj, __builtin_vec_new ); #endif // operator new[](unsigned long), GNU mangling #if VG_WORDSIZE == 8 ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znam, __builtin_vec_new ); + ALLOC_or_BOMB(VG_Z_LIBSUPCXX_SONAME, _Znam, __builtin_vec_new ); ALLOC_or_BOMB(VG_Z_LIBC_SONAME, _Znam, __builtin_vec_new ); ALLOC_or_BOMB(SO_SYN_MALLOC, _Znam, __builtin_vec_new ); #endif +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + // operator new[](unsigned int), GNU mangling + #if VG_WORDSIZE == 4 + ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znaj, __builtin_vec_new ); + ALLOC_or_BOMB(VG_Z_LIBSUPCXX_SONAME, _Znaj, __builtin_vec_new ); + ALLOC_or_BOMB(SO_SYN_MALLOC, _Znaj, __builtin_vec_new ); + #endif + // operator new[](unsigned long), GNU mangling + #if VG_WORDSIZE == 8 + ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znam, __builtin_vec_new ); + ALLOC_or_BOMB(VG_Z_LIBSUPCXX_SONAME, _Znam, __builtin_vec_new ); + ALLOC_or_BOMB(SO_SYN_MALLOC, _Znaj, __builtin_vec_new ); + #endif + #elif defined(VGO_darwin) // operator new[](unsigned int), GNU mangling #if VG_WORDSIZE == 4 @@ -412,16 +464,32 @@ // operator new[](unsigned, std::nothrow_t const&), GNU mangling #if VG_WORDSIZE == 4 ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnajRKSt9nothrow_t, __builtin_vec_new ); + ALLOC_or_NULL(VG_Z_LIBSUPCXX_SONAME, _ZnajRKSt9nothrow_t, __builtin_vec_new ); ALLOC_or_NULL(VG_Z_LIBC_SONAME, _ZnajRKSt9nothrow_t, __builtin_vec_new ); ALLOC_or_NULL(SO_SYN_MALLOC, _ZnajRKSt9nothrow_t, __builtin_vec_new ); #endif // operator new[](unsigned long, std::nothrow_t const&), GNU mangling #if VG_WORDSIZE == 8 ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnamRKSt9nothrow_t, __builtin_vec_new ); + ALLOC_or_NULL(VG_Z_LIBSUPCXX_SONAME, _ZnamRKSt9nothrow_t, __builtin_vec_new ); ALLOC_or_NULL(VG_Z_LIBC_SONAME, _ZnamRKSt9nothrow_t, __builtin_vec_new ); ALLOC_or_NULL(SO_SYN_MALLOC, _ZnamRKSt9nothrow_t, __builtin_vec_new ); #endif +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + // operator new[](unsigned, std::nothrow_t const&), GNU mangling + #if VG_WORDSIZE == 4 + ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnajRKSt9nothrow_t, __builtin_vec_new ); + ALLOC_or_NULL(VG_Z_LIBSUPCXX_SONAME, _ZnajRKSt9nothrow_t, __builtin_vec_new ); + ALLOC_or_NULL(SO_SYN_MALLOC, _ZnajRKSt9nothrow_t, __builtin_vec_new ); + #endif + // operator new[](unsigned long, std::nothrow_t const&), GNU mangling + #if VG_WORDSIZE == 8 + ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnamRKSt9nothrow_t, __builtin_vec_new ); + ALLOC_or_NULL(VG_Z_LIBSUPCXX_SONAME, _ZnamRKSt9nothrow_t, __builtin_vec_new ); + ALLOC_or_NULL(SO_SYN_MALLOC, _ZnajRKSt9nothrow_t, __builtin_vec_new ); + #endif + #elif defined(VGO_darwin) // operator new[](unsigned, std::nothrow_t const&), GNU mangling #if VG_WORDSIZE == 4 @@ -473,6 +541,10 @@ FREE(VG_Z_LIBC_SONAME, free, free ); FREE(SO_SYN_MALLOC, free, free ); +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + FREE(VG_Z_LIBC_SONAME, free, free ); + FREE(SO_SYN_MALLOC, free, free ); + #elif defined(VGO_darwin) FREE(VG_Z_LIBC_SONAME, free, free ); FREE(SO_SYN_MALLOC, free, free ); @@ -505,9 +577,15 @@ FREE(VG_Z_LIBC_SONAME, __builtin_delete, __builtin_delete ); // operator delete(void*), GNU mangling FREE(VG_Z_LIBSTDCXX_SONAME, _ZdlPv, __builtin_delete ); + FREE(VG_Z_LIBSUPCXX_SONAME, _ZdlPv, __builtin_delete ); FREE(VG_Z_LIBC_SONAME, _ZdlPv, __builtin_delete ); FREE(SO_SYN_MALLOC, _ZdlPv, __builtin_delete ); +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + FREE(VG_Z_LIBSTDCXX_SONAME, _ZdlPv, __builtin_delete ); + FREE(VG_Z_LIBSUPCXX_SONAME, _ZdlPv, __builtin_delete ); + FREE(SO_SYN_MALLOC, _ZdlPv, __builtin_delete ); + #elif defined(VGO_darwin) // operator delete(void*), GNU mangling //FREE(VG_Z_LIBSTDCXX_SONAME, _ZdlPv, __builtin_delete ); @@ -521,9 +599,16 @@ #if defined(VGO_linux) // operator delete(void*, std::nothrow_t const&), GNU mangling FREE(VG_Z_LIBSTDCXX_SONAME, _ZdlPvRKSt9nothrow_t, __builtin_delete ); + FREE(VG_Z_LIBSUPCXX_SONAME, _ZdlPvRKSt9nothrow_t, __builtin_delete ); FREE(VG_Z_LIBC_SONAME, _ZdlPvRKSt9nothrow_t, __builtin_delete ); FREE(SO_SYN_MALLOC, _ZdlPvRKSt9nothrow_t, __builtin_delete ); +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + // operator delete(void*, std::nothrow_t const&), GNU mangling + FREE(VG_Z_LIBSTDCXX_SONAME, _ZdlPvRKSt9nothrow_t, __builtin_delete ); + FREE(VG_Z_LIBSUPCXX_SONAME, _ZdlPvRKSt9nothrow_t, __builtin_delete ); + FREE(SO_SYN_MALLOC, _ZdlPvRKSt9nothrow_t, __builtin_delete ); + #elif defined(VGO_darwin) // operator delete(void*, std::nothrow_t const&), GNU mangling //FREE(VG_Z_LIBSTDCXX_SONAME, _ZdlPvRKSt9nothrow_t, __builtin_delete ); @@ -540,9 +625,16 @@ FREE(VG_Z_LIBC_SONAME, __builtin_vec_delete, __builtin_vec_delete ); // operator delete[](void*), GNU mangling FREE(VG_Z_LIBSTDCXX_SONAME, _ZdaPv, __builtin_vec_delete ); + FREE(VG_Z_LIBSUPCXX_SONAME, _ZdaPv, __builtin_vec_delete ); FREE(VG_Z_LIBC_SONAME, _ZdaPv, __builtin_vec_delete ); FREE(SO_SYN_MALLOC, _ZdaPv, __builtin_vec_delete ); +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + // operator delete[](void*), GNU mangling + FREE(VG_Z_LIBSTDCXX_SONAME, _ZdaPv, __builtin_vec_delete ); + FREE(VG_Z_LIBSUPCXX_SONAME, _ZdaPv, __builtin_vec_delete ); + FREE(SO_SYN_MALLOC, _ZdaPv, __builtin_vec_delete ); + #elif defined(VGO_darwin) // operator delete[](void*), not mangled (for gcc 2.96) //FREE(VG_Z_LIBSTDCXX_SONAME, __builtin_vec_delete, __builtin_vec_delete ); @@ -559,9 +651,16 @@ #if defined(VGO_linux) // operator delete[](void*, std::nothrow_t const&), GNU mangling FREE(VG_Z_LIBSTDCXX_SONAME, _ZdaPvRKSt9nothrow_t, __builtin_vec_delete ); + FREE(VG_Z_LIBSUPCXX_SONAME, _ZdaPvRKSt9nothrow_t, __builtin_vec_delete ); FREE(VG_Z_LIBC_SONAME, _ZdaPvRKSt9nothrow_t, __builtin_vec_delete ); FREE(SO_SYN_MALLOC, _ZdaPvRKSt9nothrow_t, __builtin_vec_delete ); +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + // operator delete[](void*, std::nothrow_t const&), GNU mangling + FREE(VG_Z_LIBSTDCXX_SONAME, _ZdaPvRKSt9nothrow_t, __builtin_vec_delete ); + FREE(VG_Z_LIBSUPCXX_SONAME, _ZdaPvRKSt9nothrow_t, __builtin_vec_delete ); + FREE(SO_SYN_MALLOC, _ZdaPvRKSt9nothrow_t, __builtin_vec_delete ); + #elif defined(VGO_darwin) // operator delete[](void*, std::nothrow_t const&), GNU mangling //FREE(VG_Z_LIBSTDCXX_SONAME, _ZdaPvRKSt9nothrow_t, __builtin_vec_delete ); @@ -623,6 +722,10 @@ CALLOC(VG_Z_LIBC_SONAME, calloc); CALLOC(SO_SYN_MALLOC, calloc); +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + CALLOC(VG_Z_LIBC_SONAME, calloc); + CALLOC(SO_SYN_MALLOC, calloc); + #elif defined(VGO_darwin) CALLOC(VG_Z_LIBC_SONAME, calloc); CALLOC(SO_SYN_MALLOC, calloc); @@ -688,10 +791,45 @@ return v; \ } +#define REALLOCF(soname, fnname) \ + \ + void* VG_REPLACE_FUNCTION_EZU(10091,soname,fnname) \ + ( void* ptrV, SizeT new_size );\ + void* VG_REPLACE_FUNCTION_EZU(10091,soname,fnname) \ + ( void* ptrV, SizeT new_size ) \ + { \ + void* v; \ + \ + if (!init_done) init(); \ + MALLOC_TRACE("reallocf(%p,%llu)", ptrV, (ULong)new_size ); \ + \ + if (ptrV == NULL) \ + /* We need to call a malloc-like function; so let's use \ + one which we know exists. */ \ + return VG_REPLACE_FUNCTION_EZU(10010,VG_Z_LIBC_SONAME,malloc) \ + (new_size); \ + if (new_size <= 0) { \ + VG_REPLACE_FUNCTION_EZU(10050,VG_Z_LIBC_SONAME,free)(ptrV); \ + MALLOC_TRACE(" = 0\n"); \ + return NULL; \ + } \ + v = (void*)VALGRIND_NON_SIMD_CALL2( info.tl_realloc, ptrV, new_size ); \ + MALLOC_TRACE(" = %p\n", v ); \ + if (v == NULL) \ + VG_REPLACE_FUNCTION_EZU(10050,VG_Z_LIBC_SONAME,free)(ptrV); \ + MALLOC_TRACE(" = %p\n", v ); \ + return v; \ + } + #if defined(VGO_linux) REALLOC(VG_Z_LIBC_SONAME, realloc); REALLOC(SO_SYN_MALLOC, realloc); +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + REALLOC(VG_Z_LIBC_SONAME, realloc); + REALLOC(SO_SYN_MALLOC, realloc); + REALLOCF(VG_Z_LIBC_SONAME, reallocf); + #elif defined(VGO_darwin) REALLOC(VG_Z_LIBC_SONAME, realloc); REALLOC(SO_SYN_MALLOC, realloc); @@ -760,6 +898,10 @@ MEMALIGN(VG_Z_LIBC_SONAME, memalign); MEMALIGN(SO_SYN_MALLOC, memalign); +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + MEMALIGN(VG_Z_LIBC_SONAME, memalign); + MEMALIGN(SO_SYN_MALLOC, memalign); + #elif defined(VGO_darwin) MEMALIGN(VG_Z_LIBC_SONAME, memalign); MEMALIGN(SO_SYN_MALLOC, memalign); @@ -802,6 +944,10 @@ VALLOC(VG_Z_LIBC_SONAME, valloc); VALLOC(SO_SYN_MALLOC, valloc); +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + VALLOC(VG_Z_LIBC_SONAME, valloc); + VALLOC(SO_SYN_MALLOC, valloc); + #elif defined(VGO_darwin) VALLOC(VG_Z_LIBC_SONAME, valloc); VALLOC(SO_SYN_MALLOC, valloc); @@ -913,6 +1059,10 @@ POSIX_MEMALIGN(VG_Z_LIBC_SONAME, posix_memalign); POSIX_MEMALIGN(SO_SYN_MALLOC, posix_memalign); +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + POSIX_MEMALIGN(VG_Z_LIBC_SONAME, posix_memalign); + POSIX_MEMALIGN(SO_SYN_MALLOC, posix_memalign); + #elif defined(VGO_darwin) //POSIX_MEMALIGN(VG_Z_LIBC_SONAME, posix_memalign); @@ -950,6 +1100,10 @@ MALLOC_USABLE_SIZE(SO_SYN_MALLOC, dlmalloc_usable_size); # endif +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + MALLOC_USABLE_SIZE(VG_Z_LIBC_SONAME, malloc_usable_size); + MALLOC_USABLE_SIZE(SO_SYN_MALLOC, malloc_usable_size); + #elif defined(VGO_darwin) //MALLOC_USABLE_SIZE(VG_Z_LIBC_SONAME, malloc_usable_size); MALLOC_USABLE_SIZE(VG_Z_LIBC_SONAME, malloc_size); diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_scheduler/scheduler.c --- a/coregrind/m_scheduler/scheduler.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_scheduler/scheduler.c Thu Mar 31 15:57:55 2016 +0900 @@ -472,6 +472,7 @@ VG_(sigdelset)(&mask, VKI_SIGFPE); VG_(sigdelset)(&mask, VKI_SIGILL); VG_(sigdelset)(&mask, VKI_SIGTRAP); + VG_(sigdelset)(&mask, VKI_SIGSYS); /* Can't block these anyway */ VG_(sigdelset)(&mask, VKI_SIGSTOP); @@ -486,6 +487,8 @@ tst->os_state.threadgroup = 0; # if defined(VGO_linux) /* no other fields to clear */ +# elif defined(VGO_freebsd) || defined(VGO_openbsd) + /* no other fields to clear */ # elif defined(VGO_darwin) tst->os_state.post_mach_trap_fn = NULL; tst->os_state.pthread = 0; diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_sigframe/sigframe-amd64-freebsd.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coregrind/m_sigframe/sigframe-amd64-freebsd.c Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,432 @@ + +/*--------------------------------------------------------------------*/ +/*--- Create/destroy signal delivery frames. ---*/ +/*--- sigframe-amd64-freebsd.c ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2009 Nicholas Nethercote + njn@valgrind.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#if defined(VGP_amd64_freebsd) + +#include "pub_core_basics.h" +#include "pub_core_vki.h" +#include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy +#include "pub_core_threadstate.h" +#include "pub_core_aspacemgr.h" +#include "pub_core_libcbase.h" +#include "pub_core_libcassert.h" +#include "pub_core_libcprint.h" +#include "pub_core_machine.h" +#include "pub_core_options.h" +#include "pub_core_signals.h" +#include "pub_core_tooliface.h" +#include "pub_core_trampoline.h" +#include "pub_core_sigframe.h" /* self */ + +/* This module creates and removes signal frames for signal deliveries + on amd64-freebsd. +*/ + + +/*------------------------------------------------------------*/ +/*--- Signal frame layouts ---*/ +/*------------------------------------------------------------*/ + +// A structure in which to save the application's registers +// during the execution of signal handlers. + +// In theory, so long as we get the arguments to the handler function +// right, it doesn't matter what the exact layout of the rest of the +// frame is. Unfortunately, things like gcc's exception unwinding +// make assumptions about the locations of various parts of the frame, +// so we need to duplicate it exactly. + +/* Valgrind-specific parts of the signal frame */ +struct vg_sigframe +{ + /* Sanity check word. */ + UInt magicPI; + + UInt handlerflags; /* flags for signal handler */ + + + /* Safely-saved version of sigNo, as described above. */ + Int sigNo_private; + + /* XXX This is wrong. Surely we should store the shadow values + into the shadow memory behind the actual values? */ + VexGuestAMD64State vex_shadow1; + VexGuestAMD64State vex_shadow2; + + /* HACK ALERT */ + VexGuestAMD64State vex; + /* end HACK ALERT */ + + /* saved signal mask to be restored when handler returns */ + vki_sigset_t mask; + + /* Sanity check word. Is the highest-addressed word; do not + move!*/ + 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. +*/ +static +void synth_ucontext(ThreadId tid, const vki_siginfo_t *si, + UWord trapno, UWord err, const vki_sigset_t *set, + struct vki_ucontext *uc, struct _vki_fpstate *fpstate) +{ + ThreadState *tst = VG_(get_ThreadState)(tid); + struct vki_mcontext *sc = &uc->uc_mcontext; + + VG_(memset)(uc, 0, sizeof(*uc)); + + uc->uc_flags = 0; + uc->uc_link = 0; + uc->uc_sigmask = *set; + uc->uc_stack = tst->altstack; + VG_(memcpy)(&sc->fpstate, fpstate, sizeof(*fpstate)); + +# define SC2(reg,REG) sc->reg = tst->arch.vex.guest_##REG + SC2(r8,R8); + SC2(r9,R9); + SC2(r10,R10); + SC2(r11,R11); + SC2(r12,R12); + SC2(r13,R13); + SC2(r14,R14); + SC2(r15,R15); + SC2(rdi,RDI); + SC2(rsi,RSI); + SC2(rbp,RBP); + SC2(rbx,RBX); + SC2(rdx,RDX); + 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); + sc->trapno = trapno; +# undef SC2 +} + + +/* Extend the stack segment downwards if needed so as to ensure the + new signal frames are mapped to something. Return a Bool + indicating whether or not the operation was successful. +*/ +static Bool extend ( ThreadState *tst, Addr addr, SizeT size ) +{ + ThreadId tid = tst->tid; + NSegment const* stackseg = NULL; + + if (VG_(extend_stack)(addr, tst->client_stack_szB)) { + stackseg = VG_(am_find_nsegment)(addr); + if (0 && stackseg) + VG_(printf)("frame=%#lx seg=%#lx-%#lx\n", + addr, stackseg->start, stackseg->end); + } + + if (stackseg == NULL || !stackseg->hasR || !stackseg->hasW) { + VG_(message)( + Vg_UserMsg, + "Can't extend stack to %#lx during signal delivery for thread %d:\n", + addr, tid); + if (stackseg == NULL) + VG_(message)(Vg_UserMsg, " no stack segment\n"); + else + VG_(message)(Vg_UserMsg, " too small or bad protection modes\n"); + + /* set SIGSEGV to default handler */ + VG_(set_default_handler)(VKI_SIGSEGV); + VG_(synth_fault_mapping)(tid, addr); + + /* The whole process should be about to die, since the default + action of SIGSEGV to kill the whole process. */ + return False; + } + + /* For tracking memory events, indicate the entire frame has been + allocated. */ + VG_TRACK( new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB, + size + VG_STACK_REDZONE_SZB, tid ); + + return True; +} + + +/* Build the Valgrind-specific part of a signal frame. */ + +static void build_vg_sigframe(struct vg_sigframe *frame, + ThreadState *tst, + const vki_sigset_t *mask, + UInt flags, + Int sigNo) +{ + frame->sigNo_private = sigNo; + frame->magicPI = 0x31415927; + frame->vex_shadow1 = tst->arch.vex_shadow1; + frame->vex_shadow2 = tst->arch.vex_shadow2; + /* HACK ALERT */ + frame->vex = tst->arch.vex; + /* end HACK ALERT */ + frame->mask = tst->sig_mask; + frame->handlerflags = flags; + 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)); + + if (siguc != NULL) { + trapno = siguc->uc_mcontext.trapno; + err = siguc->uc_mcontext.err; + } else { + trapno = 0; + err = 0; + } + + 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, + const struct vki_ucontext *siguc, + void *handler, + UInt flags, + const vki_sigset_t *mask, + void *restorer ) +{ + 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. */ +} + + +/*------------------------------------------------------------*/ +/*--- Destroying signal frames ---*/ +/*------------------------------------------------------------*/ + +/* Return False and don't do anything, just set the client to take a + segfault, if it looks like the frame is corrupted. */ +static +Bool restore_vg_sigframe ( ThreadState *tst, + struct vg_sigframe *frame, Int *sigNo ) +{ + if (frame->magicPI != 0x31415927 || + frame->magicE != 0x27182818) { + VG_(message)(Vg_UserMsg, "Thread %d return signal frame " + "corrupted. Killing process.\n", + tst->tid); + VG_(set_default_handler)(VKI_SIGSEGV); + VG_(synth_fault)(tst->tid); + *sigNo = VKI_SIGSEGV; + return False; + } + tst->sig_mask = frame->mask; + tst->tmp_sig_mask = frame->mask; + tst->arch.vex_shadow1 = frame->vex_shadow1; + tst->arch.vex_shadow2 = frame->vex_shadow2; + /* HACK ALERT */ + tst->arch.vex = frame->vex; + /* end HACK ALERT */ + *sigNo = frame->sigNo_private; + return True; +} + +static +void restore_sigcontext( ThreadState *tst, + struct vki_mcontext *sc, + struct _vki_fpstate *fpstate ) +{ + tst->arch.vex.guest_RAX = sc->rax; + tst->arch.vex.guest_RCX = sc->rcx; + tst->arch.vex.guest_RDX = sc->rdx; + tst->arch.vex.guest_RBX = sc->rbx; + tst->arch.vex.guest_RBP = sc->rbp; + tst->arch.vex.guest_RSP = sc->rsp; + tst->arch.vex.guest_RSI = sc->rsi; + tst->arch.vex.guest_RDI = sc->rdi; + tst->arch.vex.guest_R8 = sc->r8; + tst->arch.vex.guest_R9 = sc->r9; + tst->arch.vex.guest_R10 = sc->r10; + tst->arch.vex.guest_R11 = sc->r11; + tst->arch.vex.guest_R12 = sc->r12; + tst->arch.vex.guest_R13 = sc->r13; + tst->arch.vex.guest_R14 = sc->r14; + tst->arch.vex.guest_R15 = sc->r15; +/* + 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)); +} + +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); + + return sizeof(*frame); +} + +void VG_(sigframe_destroy)( ThreadId tid ) +{ + Addr rsp; + ThreadState* tst; + SizeT size; + Int sigNo; + + tst = VG_(get_ThreadState)(tid); + + /* Correctly reestablish the frame base address. */ + rsp = tst->arch.vex.guest_RSP; + + size = restore_sigframe(tst, (struct sigframe *)rsp, &sigNo); + + VG_TRACK( die_mem_stack_signal, rsp - VG_STACK_REDZONE_SZB, + size + VG_STACK_REDZONE_SZB ); + + if (VG_(clo_trace_signals)) + VG_(message)( + Vg_DebugMsg, + "VG_(signal_return) (thread %d): valid magic; RIP=%#llx\n", + tid, tst->arch.vex.guest_RIP); + + /* tell the tools */ + VG_TRACK( post_deliver_signal, tid, sigNo ); +} + +#endif // defined(VGP_amd64_freebsd) + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_sigframe/sigframe-amd64-openbsd.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coregrind/m_sigframe/sigframe-amd64-openbsd.c Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,432 @@ + +/*--------------------------------------------------------------------*/ +/*--- Create/destroy signal delivery frames. ---*/ +/*--- sigframe-amd64-freebsd.c ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2009 Nicholas Nethercote + njn@valgrind.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#if defined(VGP_amd64_openbsd) + +#include "pub_core_basics.h" +#include "pub_core_vki.h" +#include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy +#include "pub_core_threadstate.h" +#include "pub_core_aspacemgr.h" +#include "pub_core_libcbase.h" +#include "pub_core_libcassert.h" +#include "pub_core_libcprint.h" +#include "pub_core_machine.h" +#include "pub_core_options.h" +#include "pub_core_signals.h" +#include "pub_core_tooliface.h" +#include "pub_core_trampoline.h" +#include "pub_core_sigframe.h" /* self */ + +/* This module creates and removes signal frames for signal deliveries + on amd64-freebsd. +*/ + + +/*------------------------------------------------------------*/ +/*--- Signal frame layouts ---*/ +/*------------------------------------------------------------*/ + +// A structure in which to save the application's registers +// during the execution of signal handlers. + +// In theory, so long as we get the arguments to the handler function +// right, it doesn't matter what the exact layout of the rest of the +// frame is. Unfortunately, things like gcc's exception unwinding +// make assumptions about the locations of various parts of the frame, +// so we need to duplicate it exactly. + +/* Valgrind-specific parts of the signal frame */ +struct vg_sigframe +{ + /* Sanity check word. */ + UInt magicPI; + + UInt handlerflags; /* flags for signal handler */ + + + /* Safely-saved version of sigNo, as described above. */ + Int sigNo_private; + + /* XXX This is wrong. Surely we should store the shadow values + into the shadow memory behind the actual values? */ + VexGuestAMD64State vex_shadow1; + VexGuestAMD64State vex_shadow2; + + /* HACK ALERT */ + VexGuestAMD64State vex; + /* end HACK ALERT */ + + /* saved signal mask to be restored when handler returns */ + vki_sigset_t mask; + + /* Sanity check word. Is the highest-addressed word; do not + move!*/ + 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. +*/ +static +void synth_ucontext(ThreadId tid, const vki_siginfo_t *si, + UWord trapno, UWord err, const vki_sigset_t *set, + struct vki_ucontext *uc, struct _vki_fpstate *fpstate) +{ + ThreadState *tst = VG_(get_ThreadState)(tid); + struct vki_mcontext *sc = &uc->uc_mcontext; + + VG_(memset)(uc, 0, sizeof(*uc)); + + uc->uc_flags = 0; + uc->uc_link = 0; + uc->uc_sigmask = *set; + uc->uc_stack = tst->altstack; + VG_(memcpy)(&sc->fpstate, fpstate, sizeof(*fpstate)); + +# define SC2(reg,REG) sc->reg = tst->arch.vex.guest_##REG + SC2(r8,R8); + SC2(r9,R9); + SC2(r10,R10); + SC2(r11,R11); + SC2(r12,R12); + SC2(r13,R13); + SC2(r14,R14); + SC2(r15,R15); + SC2(rdi,RDI); + SC2(rsi,RSI); + SC2(rbp,RBP); + SC2(rbx,RBX); + SC2(rdx,RDX); + 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); + sc->trapno = trapno; +# undef SC2 +} + + +/* Extend the stack segment downwards if needed so as to ensure the + new signal frames are mapped to something. Return a Bool + indicating whether or not the operation was successful. +*/ +static Bool extend ( ThreadState *tst, Addr addr, SizeT size ) +{ + ThreadId tid = tst->tid; + NSegment const* stackseg = NULL; + + if (VG_(extend_stack)(addr, tst->client_stack_szB)) { + stackseg = VG_(am_find_nsegment)(addr); + if (0 && stackseg) + VG_(printf)("frame=%#lx seg=%#lx-%#lx\n", + addr, stackseg->start, stackseg->end); + } + + if (stackseg == NULL || !stackseg->hasR || !stackseg->hasW) { + VG_(message)( + Vg_UserMsg, + "Can't extend stack to %#lx during signal delivery for thread %d:\n", + addr, tid); + if (stackseg == NULL) + VG_(message)(Vg_UserMsg, " no stack segment\n"); + else + VG_(message)(Vg_UserMsg, " too small or bad protection modes\n"); + + /* set SIGSEGV to default handler */ + VG_(set_default_handler)(VKI_SIGSEGV); + VG_(synth_fault_mapping)(tid, addr); + + /* The whole process should be about to die, since the default + action of SIGSEGV to kill the whole process. */ + return False; + } + + /* For tracking memory events, indicate the entire frame has been + allocated. */ + VG_TRACK( new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB, + size + VG_STACK_REDZONE_SZB, tid ); + + return True; +} + + +/* Build the Valgrind-specific part of a signal frame. */ + +static void build_vg_sigframe(struct vg_sigframe *frame, + ThreadState *tst, + const vki_sigset_t *mask, + UInt flags, + Int sigNo) +{ + frame->sigNo_private = sigNo; + frame->magicPI = 0x31415927; + frame->vex_shadow1 = tst->arch.vex_shadow1; + frame->vex_shadow2 = tst->arch.vex_shadow2; + /* HACK ALERT */ + frame->vex = tst->arch.vex; + /* end HACK ALERT */ + frame->mask = tst->sig_mask; + frame->handlerflags = flags; + 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_openbsd_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)); + + if (siguc != NULL) { + trapno = siguc->uc_mcontext.trapno; + err = siguc->uc_mcontext.err; + } else { + trapno = 0; + err = 0; + } + + 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, + const struct vki_ucontext *siguc, + void *handler, + UInt flags, + const vki_sigset_t *mask, + void *restorer ) +{ + 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. */ +} + + +/*------------------------------------------------------------*/ +/*--- Destroying signal frames ---*/ +/*------------------------------------------------------------*/ + +/* Return False and don't do anything, just set the client to take a + segfault, if it looks like the frame is corrupted. */ +static +Bool restore_vg_sigframe ( ThreadState *tst, + struct vg_sigframe *frame, Int *sigNo ) +{ + if (frame->magicPI != 0x31415927 || + frame->magicE != 0x27182818) { + VG_(message)(Vg_UserMsg, "Thread %d return signal frame " + "corrupted. Killing process.\n", + tst->tid); + VG_(set_default_handler)(VKI_SIGSEGV); + VG_(synth_fault)(tst->tid); + *sigNo = VKI_SIGSEGV; + return False; + } + tst->sig_mask = frame->mask; + tst->tmp_sig_mask = frame->mask; + tst->arch.vex_shadow1 = frame->vex_shadow1; + tst->arch.vex_shadow2 = frame->vex_shadow2; + /* HACK ALERT */ + tst->arch.vex = frame->vex; + /* end HACK ALERT */ + *sigNo = frame->sigNo_private; + return True; +} + +static +void restore_sigcontext( ThreadState *tst, + struct vki_mcontext *sc, + struct _vki_fpstate *fpstate ) +{ + tst->arch.vex.guest_RAX = sc->rax; + tst->arch.vex.guest_RCX = sc->rcx; + tst->arch.vex.guest_RDX = sc->rdx; + tst->arch.vex.guest_RBX = sc->rbx; + tst->arch.vex.guest_RBP = sc->rbp; + tst->arch.vex.guest_RSP = sc->rsp; + tst->arch.vex.guest_RSI = sc->rsi; + tst->arch.vex.guest_RDI = sc->rdi; + tst->arch.vex.guest_R8 = sc->r8; + tst->arch.vex.guest_R9 = sc->r9; + tst->arch.vex.guest_R10 = sc->r10; + tst->arch.vex.guest_R11 = sc->r11; + tst->arch.vex.guest_R12 = sc->r12; + tst->arch.vex.guest_R13 = sc->r13; + tst->arch.vex.guest_R14 = sc->r14; + tst->arch.vex.guest_R15 = sc->r15; +/* + 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)); +} + +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); + + return sizeof(*frame); +} + +void VG_(sigframe_destroy)( ThreadId tid ) +{ + Addr rsp; + ThreadState* tst; + SizeT size; + Int sigNo; + + tst = VG_(get_ThreadState)(tid); + + /* Correctly reestablish the frame base address. */ + rsp = tst->arch.vex.guest_RSP; + + size = restore_sigframe(tst, (struct sigframe *)rsp, &sigNo); + + VG_TRACK( die_mem_stack_signal, rsp - VG_STACK_REDZONE_SZB, + size + VG_STACK_REDZONE_SZB ); + + if (VG_(clo_trace_signals)) + VG_(message)( + Vg_DebugMsg, + "VG_(signal_return) (thread %d): valid magic; RIP=%#llx\n", + tid, tst->arch.vex.guest_RIP); + + /* tell the tools */ + VG_TRACK( post_deliver_signal, tid, sigNo ); +} + +#endif // defined(VGP_amd64_openbsd) + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_sigframe/sigframe-x86-freebsd.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coregrind/m_sigframe/sigframe-x86-freebsd.c Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,423 @@ + +/*--------------------------------------------------------------------*/ +/*--- Create/destroy signal delivery frames. ---*/ +/*--- sigframe-x86-freebsd.c ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2009 Nicholas Nethercote + njn@valgrind.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#if defined(VGP_x86_freebsd) + +#include "pub_core_basics.h" +#include "pub_core_vki.h" +#include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy +#include "pub_core_threadstate.h" +#include "pub_core_aspacemgr.h" /* find_segment */ +#include "pub_core_libcbase.h" +#include "pub_core_libcassert.h" +#include "pub_core_libcprint.h" +#include "pub_core_machine.h" +#include "pub_core_options.h" +#include "pub_core_signals.h" +#include "pub_core_tooliface.h" +#include "pub_core_trampoline.h" +#include "pub_core_sigframe.h" /* self */ + + +/* This module creates and removes signal frames for signal deliveries + on x86-freebsd. +*/ + + +/*------------------------------------------------------------*/ +/*--- Signal frame layouts ---*/ +/*------------------------------------------------------------*/ + +// A structure in which to save the application's registers +// during the execution of signal handlers. + +// In theory, so long as we get the arguments to the handler function +// right, it doesn't matter what the exact layout of the rest of the +// frame is. Unfortunately, things like gcc's exception unwinding +// make assumptions about the locations of various parts of the frame, +// so we need to duplicate it exactly. + +/* Valgrind-specific parts of the signal frame */ +struct vg_sigframe +{ + /* Sanity check word. */ + UInt magicPI; + + UInt handlerflags; /* flags for signal handler */ + + + /* Safely-saved version of sigNo, as described above. */ + Int sigNo_private; + + /* XXX This is wrong. Surely we should store the shadow values + into the shadow memory behind the actual values? */ + VexGuestX86State vex_shadow1; + VexGuestX86State vex_shadow2; + + /* HACK ALERT */ + VexGuestX86State vex; + /* end HACK ALERT */ + + /* saved signal mask to be restored when handler returns */ + vki_sigset_t mask; + + /* Sanity check word. Is the highest-addressed word; do not + move!*/ + 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. +*/ +static +void synth_ucontext(ThreadId tid, const vki_siginfo_t *si, + UWord trapno, UWord err, const vki_sigset_t *set, + struct vki_ucontext *uc, struct _vki_fpstate *fpstate) +{ + ThreadState *tst = VG_(get_ThreadState)(tid); + struct vki_mcontext *sc = &uc->uc_mcontext; + + VG_(memset)(uc, 0, sizeof(*uc)); + + uc->uc_flags = 0; + uc->uc_link = 0; + uc->uc_sigmask = *set; + uc->uc_stack = tst->altstack; + VG_(memcpy)(&sc->fpstate, fpstate, sizeof(*fpstate)); + +# define SC2(reg,REG) sc->reg = tst->arch.vex.guest_##REG + SC2(gs,GS); + SC2(fs,FS); + SC2(es,ES); + SC2(ds,DS); + + SC2(edi,EDI); + SC2(esi,ESI); + SC2(ebp,EBP); + SC2(esp,ESP); + SC2(ebx,EBX); + SC2(edx,EDX); + SC2(ecx,ECX); + SC2(eax,EAX); + + SC2(eip,EIP); + SC2(cs,CS); + sc->eflags = LibVEX_GuestX86_get_eflags(&tst->arch.vex); + SC2(ss,SS); + sc->trapno = trapno; + sc->err = err; +// sc->addr = (UWord)si->si_addr; + sc->fpformat = VKI_FPFMT_NODEV; + sc->len = sizeof(*sc); + sc->ownedfp = VKI_FPOWNED_NONE; +# undef SC2 + +// sc->cr2 = (UInt)si->_sifields._sigfault._addr; +} + + +/* Extend the stack segment downwards if needed so as to ensure the + new signal frames are mapped to something. Return a Bool + indicating whether or not the operation was successful. +*/ +static Bool extend ( ThreadState *tst, Addr addr, SizeT size ) +{ + ThreadId tid = tst->tid; + NSegment const* stackseg = NULL; + + if (VG_(extend_stack)(addr, tst->client_stack_szB)) { + stackseg = VG_(am_find_nsegment)(addr); + if (0 && stackseg) + VG_(printf)("frame=%#lx seg=%#lx-%#lx\n", + addr, stackseg->start, stackseg->end); + } + + if (stackseg == NULL || !stackseg->hasR || !stackseg->hasW) { + VG_(message)( + Vg_UserMsg, + "Can't extend stack to %#lx during signal delivery for thread %d:\n", + addr, tid); + if (stackseg == NULL) + VG_(message)(Vg_UserMsg, " no stack segment\n"); + else + VG_(message)(Vg_UserMsg, " too small or bad protection modes\n"); + + /* set SIGSEGV to default handler */ + VG_(set_default_handler)(VKI_SIGSEGV); + VG_(synth_fault_mapping)(tid, addr); + + /* The whole process should be about to die, since the default + action of SIGSEGV to kill the whole process. */ + return False; + } + + /* For tracking memory events, indicate the entire frame has been + allocated. */ + VG_TRACK( new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB, + size + VG_STACK_REDZONE_SZB, tid ); + + return True; +} + + +/* Build the Valgrind-specific part of a signal frame. */ + +static void build_vg_sigframe(struct vg_sigframe *frame, + ThreadState *tst, + const vki_sigset_t *mask, + UInt flags, + Int sigNo) +{ + frame->sigNo_private = sigNo; + frame->magicPI = 0x31415927; + frame->vex_shadow1 = tst->arch.vex_shadow1; + frame->vex_shadow2 = tst->arch.vex_shadow2; + /* HACK ALERT */ + frame->vex = tst->arch.vex; + /* end HACK ALERT */ + frame->mask = tst->sig_mask; + frame->handlerflags = flags; + frame->magicE = 0x27182818; +} + +static Addr build_sigframe(ThreadState *tst, + Addr esp_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 esp = esp_top_of_frame; + Int sigNo = siginfo->si_signo; + UWord trapno; + UWord err; + + esp -= sizeof(*frame); + esp = VG_ROUNDDN(esp, 16); + frame = (struct sigframe *)esp; + + if (!extend(tst, esp, sizeof(*frame))) + return esp_top_of_frame; + + /* retaddr, siginfo, uContext fields are to be written */ + VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame", + esp, offsetof(struct sigframe, vg) ); + + frame->sigNo = sigNo; + frame->retaddr = (Addr)&VG_(x86_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)); + + if (siguc != NULL) { + trapno = siguc->uc_mcontext.trapno; + err = siguc->uc_mcontext.err; + } else { + trapno = 0; + err = 0; + } + + 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_EIP; + + VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid, + esp, offsetof(struct sigframe, vg) ); + + build_vg_sigframe(&frame->vg, tst, mask, flags, sigNo); + + return esp; +} + +/* EXPORTED */ +void VG_(sigframe_create)( ThreadId tid, + Addr esp_top_of_frame, + const vki_siginfo_t *siginfo, + const struct vki_ucontext *siguc, + void *handler, + UInt flags, + const vki_sigset_t *mask, + void *restorer ) +{ + Addr esp; + ThreadState* tst = VG_(get_ThreadState)(tid); + + esp = build_sigframe(tst, esp_top_of_frame, siginfo, siguc, handler, + flags, mask, restorer); + + /* Set the thread so it will next run the handler. */ + /* tst->m_esp = esp; also notify the tool we've updated ESP */ + VG_(set_SP)(tid, esp); + VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR, sizeof(Addr)); + + tst->arch.vex.guest_EIP = (Addr) handler; +// tst->arch.vex.guest_EDI = (ULong) siginfo->si_signo; + /* This thread needs to be marked runnable, but we leave that the + caller to do. */ + + if (0) + VG_(printf)("pushed signal frame; %%ESP now = %#lx, " + "next %%EIP = %#x, status=%d\n", + esp, tst->arch.vex.guest_EIP, tst->status); +} + + +/*------------------------------------------------------------*/ +/*--- Destroying signal frames ---*/ +/*------------------------------------------------------------*/ + +/* Return False and don't do anything, just set the client to take a + segfault, if it looks like the frame is corrupted. */ +static +Bool restore_vg_sigframe ( ThreadState *tst, + struct vg_sigframe *frame, Int *sigNo ) +{ + if (frame->magicPI != 0x31415927 || + frame->magicE != 0x27182818) { + VG_(message)(Vg_UserMsg, "Thread %d return signal frame " + "corrupted. Killing process.", tst->tid); + VG_(set_default_handler)(VKI_SIGSEGV); + VG_(synth_fault)(tst->tid); + *sigNo = VKI_SIGSEGV; + return False; + } + tst->sig_mask = frame->mask; + tst->tmp_sig_mask = frame->mask; + tst->arch.vex_shadow1 = frame->vex_shadow1; + tst->arch.vex_shadow2 = frame->vex_shadow2; + /* HACK ALERT */ + tst->arch.vex = frame->vex; + /* end HACK ALERT */ + *sigNo = frame->sigNo_private; + return True; +} + +static +void restore_sigcontext( ThreadState *tst, + struct vki_mcontext *sc, + struct _vki_fpstate *fpstate ) +{ + tst->arch.vex.guest_EAX = sc->eax; + tst->arch.vex.guest_ECX = sc->ecx; + tst->arch.vex.guest_EDX = sc->edx; + tst->arch.vex.guest_EBX = sc->ebx; + tst->arch.vex.guest_EBP = sc->ebp; + tst->arch.vex.guest_ESP = sc->esp; + tst->arch.vex.guest_ESI = sc->esi; + tst->arch.vex.guest_EDI = sc->edi; +//:: tst->arch.vex.guest_eflags = sc->eflags; + tst->arch.vex.guest_EIP = sc->eip; + tst->arch.vex.guest_CS = sc->cs; + tst->arch.vex.guest_SS = sc->ss; + tst->arch.vex.guest_DS = sc->ds; + tst->arch.vex.guest_ES = sc->es; + tst->arch.vex.guest_FS = sc->fs; + tst->arch.vex.guest_GS = sc->gs; + VG_(memcpy)(fpstate, &sc->fpstate, sizeof(*fpstate)); +} + + +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); + + return sizeof(*frame); +} + +/* EXPORTED */ +void VG_(sigframe_destroy)( ThreadId tid ) +{ + Addr esp; + ThreadState* tst; + SizeT size; + Int sigNo; + + tst = VG_(get_ThreadState)(tid); + + /* Correctly reestablish the frame base address. */ + esp = tst->arch.vex.guest_ESP; + esp += 8; /* Clean up stack from argument/ret passed to sigreturn(2) */ + + size = restore_sigframe(tst, (struct sigframe *)esp, &sigNo); + + VG_TRACK( die_mem_stack_signal, esp - VG_STACK_REDZONE_SZB, + size + VG_STACK_REDZONE_SZB ); + + if (VG_(clo_trace_signals)) + VG_(message)( + Vg_DebugMsg, + "VG_(signal_return) (thread %d): EIP=%#x\n", + tid, tst->arch.vex.guest_EIP); + + /* tell the tools */ + VG_TRACK( post_deliver_signal, tid, sigNo ); +} + +#endif // defined(VGP_x86_freebsd) + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_sigframe/sigframe-x86-openbsd.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coregrind/m_sigframe/sigframe-x86-openbsd.c Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,423 @@ + +/*--------------------------------------------------------------------*/ +/*--- Create/destroy signal delivery frames. ---*/ +/*--- sigframe-x86-freebsd.c ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2009 Nicholas Nethercote + njn@valgrind.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#if defined(VGP_x86_openbsd) + +#include "pub_core_basics.h" +#include "pub_core_vki.h" +#include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy +#include "pub_core_threadstate.h" +#include "pub_core_aspacemgr.h" /* find_segment */ +#include "pub_core_libcbase.h" +#include "pub_core_libcassert.h" +#include "pub_core_libcprint.h" +#include "pub_core_machine.h" +#include "pub_core_options.h" +#include "pub_core_signals.h" +#include "pub_core_tooliface.h" +#include "pub_core_trampoline.h" +#include "pub_core_sigframe.h" /* self */ + + +/* This module creates and removes signal frames for signal deliveries + on x86-freebsd. +*/ + + +/*------------------------------------------------------------*/ +/*--- Signal frame layouts ---*/ +/*------------------------------------------------------------*/ + +// A structure in which to save the application's registers +// during the execution of signal handlers. + +// In theory, so long as we get the arguments to the handler function +// right, it doesn't matter what the exact layout of the rest of the +// frame is. Unfortunately, things like gcc's exception unwinding +// make assumptions about the locations of various parts of the frame, +// so we need to duplicate it exactly. + +/* Valgrind-specific parts of the signal frame */ +struct vg_sigframe +{ + /* Sanity check word. */ + UInt magicPI; + + UInt handlerflags; /* flags for signal handler */ + + + /* Safely-saved version of sigNo, as described above. */ + Int sigNo_private; + + /* XXX This is wrong. Surely we should store the shadow values + into the shadow memory behind the actual values? */ + VexGuestX86State vex_shadow1; + VexGuestX86State vex_shadow2; + + /* HACK ALERT */ + VexGuestX86State vex; + /* end HACK ALERT */ + + /* saved signal mask to be restored when handler returns */ + vki_sigset_t mask; + + /* Sanity check word. Is the highest-addressed word; do not + move!*/ + 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. +*/ +static +void synth_ucontext(ThreadId tid, const vki_siginfo_t *si, + UWord trapno, UWord err, const vki_sigset_t *set, + struct vki_ucontext *uc, struct _vki_fpstate *fpstate) +{ + ThreadState *tst = VG_(get_ThreadState)(tid); + struct vki_mcontext *sc = &uc->uc_mcontext; + + VG_(memset)(uc, 0, sizeof(*uc)); + + uc->uc_flags = 0; + uc->uc_link = 0; + uc->uc_sigmask = *set; + uc->uc_stack = tst->altstack; + VG_(memcpy)(&sc->fpstate, fpstate, sizeof(*fpstate)); + +# define SC2(reg,REG) sc->reg = tst->arch.vex.guest_##REG + SC2(gs,GS); + SC2(fs,FS); + SC2(es,ES); + SC2(ds,DS); + + SC2(edi,EDI); + SC2(esi,ESI); + SC2(ebp,EBP); + SC2(esp,ESP); + SC2(ebx,EBX); + SC2(edx,EDX); + SC2(ecx,ECX); + SC2(eax,EAX); + + SC2(eip,EIP); + SC2(cs,CS); + sc->eflags = LibVEX_GuestX86_get_eflags(&tst->arch.vex); + SC2(ss,SS); + sc->trapno = trapno; + sc->err = err; +// sc->addr = (UWord)si->si_addr; + sc->fpformat = VKI_FPFMT_NODEV; + sc->len = sizeof(*sc); + sc->ownedfp = VKI_FPOWNED_NONE; +# undef SC2 + +// sc->cr2 = (UInt)si->_sifields._sigfault._addr; +} + + +/* Extend the stack segment downwards if needed so as to ensure the + new signal frames are mapped to something. Return a Bool + indicating whether or not the operation was successful. +*/ +static Bool extend ( ThreadState *tst, Addr addr, SizeT size ) +{ + ThreadId tid = tst->tid; + NSegment const* stackseg = NULL; + + if (VG_(extend_stack)(addr, tst->client_stack_szB)) { + stackseg = VG_(am_find_nsegment)(addr); + if (0 && stackseg) + VG_(printf)("frame=%#lx seg=%#lx-%#lx\n", + addr, stackseg->start, stackseg->end); + } + + if (stackseg == NULL || !stackseg->hasR || !stackseg->hasW) { + VG_(message)( + Vg_UserMsg, + "Can't extend stack to %#lx during signal delivery for thread %d:\n", + addr, tid); + if (stackseg == NULL) + VG_(message)(Vg_UserMsg, " no stack segment\n"); + else + VG_(message)(Vg_UserMsg, " too small or bad protection modes\n"); + + /* set SIGSEGV to default handler */ + VG_(set_default_handler)(VKI_SIGSEGV); + VG_(synth_fault_mapping)(tid, addr); + + /* The whole process should be about to die, since the default + action of SIGSEGV to kill the whole process. */ + return False; + } + + /* For tracking memory events, indicate the entire frame has been + allocated. */ + VG_TRACK( new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB, + size + VG_STACK_REDZONE_SZB, tid ); + + return True; +} + + +/* Build the Valgrind-specific part of a signal frame. */ + +static void build_vg_sigframe(struct vg_sigframe *frame, + ThreadState *tst, + const vki_sigset_t *mask, + UInt flags, + Int sigNo) +{ + frame->sigNo_private = sigNo; + frame->magicPI = 0x31415927; + frame->vex_shadow1 = tst->arch.vex_shadow1; + frame->vex_shadow2 = tst->arch.vex_shadow2; + /* HACK ALERT */ + frame->vex = tst->arch.vex; + /* end HACK ALERT */ + frame->mask = tst->sig_mask; + frame->handlerflags = flags; + frame->magicE = 0x27182818; +} + +static Addr build_sigframe(ThreadState *tst, + Addr esp_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 esp = esp_top_of_frame; + Int sigNo = siginfo->si_signo; + UWord trapno; + UWord err; + + esp -= sizeof(*frame); + esp = VG_ROUNDDN(esp, 16); + frame = (struct sigframe *)esp; + + if (!extend(tst, esp, sizeof(*frame))) + return esp_top_of_frame; + + /* retaddr, siginfo, uContext fields are to be written */ + VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame", + esp, offsetof(struct sigframe, vg) ); + + frame->sigNo = sigNo; + frame->retaddr = (Addr)&VG_(x86_openbsd_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)); + + if (siguc != NULL) { + trapno = siguc->uc_mcontext.trapno; + err = siguc->uc_mcontext.err; + } else { + trapno = 0; + err = 0; + } + + 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_EIP; + + VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid, + esp, offsetof(struct sigframe, vg) ); + + build_vg_sigframe(&frame->vg, tst, mask, flags, sigNo); + + return esp; +} + +/* EXPORTED */ +void VG_(sigframe_create)( ThreadId tid, + Addr esp_top_of_frame, + const vki_siginfo_t *siginfo, + const struct vki_ucontext *siguc, + void *handler, + UInt flags, + const vki_sigset_t *mask, + void *restorer ) +{ + Addr esp; + ThreadState* tst = VG_(get_ThreadState)(tid); + + esp = build_sigframe(tst, esp_top_of_frame, siginfo, siguc, handler, + flags, mask, restorer); + + /* Set the thread so it will next run the handler. */ + /* tst->m_esp = esp; also notify the tool we've updated ESP */ + VG_(set_SP)(tid, esp); + VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR, sizeof(Addr)); + + tst->arch.vex.guest_EIP = (Addr) handler; +// tst->arch.vex.guest_EDI = (ULong) siginfo->si_signo; + /* This thread needs to be marked runnable, but we leave that the + caller to do. */ + + if (0) + VG_(printf)("pushed signal frame; %%ESP now = %#lx, " + "next %%EIP = %#x, status=%d\n", + esp, tst->arch.vex.guest_EIP, tst->status); +} + + +/*------------------------------------------------------------*/ +/*--- Destroying signal frames ---*/ +/*------------------------------------------------------------*/ + +/* Return False and don't do anything, just set the client to take a + segfault, if it looks like the frame is corrupted. */ +static +Bool restore_vg_sigframe ( ThreadState *tst, + struct vg_sigframe *frame, Int *sigNo ) +{ + if (frame->magicPI != 0x31415927 || + frame->magicE != 0x27182818) { + VG_(message)(Vg_UserMsg, "Thread %d return signal frame " + "corrupted. Killing process.", tst->tid); + VG_(set_default_handler)(VKI_SIGSEGV); + VG_(synth_fault)(tst->tid); + *sigNo = VKI_SIGSEGV; + return False; + } + tst->sig_mask = frame->mask; + tst->tmp_sig_mask = frame->mask; + tst->arch.vex_shadow1 = frame->vex_shadow1; + tst->arch.vex_shadow2 = frame->vex_shadow2; + /* HACK ALERT */ + tst->arch.vex = frame->vex; + /* end HACK ALERT */ + *sigNo = frame->sigNo_private; + return True; +} + +static +void restore_sigcontext( ThreadState *tst, + struct vki_mcontext *sc, + struct _vki_fpstate *fpstate ) +{ + tst->arch.vex.guest_EAX = sc->eax; + tst->arch.vex.guest_ECX = sc->ecx; + tst->arch.vex.guest_EDX = sc->edx; + tst->arch.vex.guest_EBX = sc->ebx; + tst->arch.vex.guest_EBP = sc->ebp; + tst->arch.vex.guest_ESP = sc->esp; + tst->arch.vex.guest_ESI = sc->esi; + tst->arch.vex.guest_EDI = sc->edi; +//:: tst->arch.vex.guest_eflags = sc->eflags; + tst->arch.vex.guest_EIP = sc->eip; + tst->arch.vex.guest_CS = sc->cs; + tst->arch.vex.guest_SS = sc->ss; + tst->arch.vex.guest_DS = sc->ds; + tst->arch.vex.guest_ES = sc->es; + tst->arch.vex.guest_FS = sc->fs; + tst->arch.vex.guest_GS = sc->gs; + VG_(memcpy)(fpstate, &sc->fpstate, sizeof(*fpstate)); +} + + +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); + + return sizeof(*frame); +} + +/* EXPORTED */ +void VG_(sigframe_destroy)( ThreadId tid ) +{ + Addr esp; + ThreadState* tst; + SizeT size; + Int sigNo; + + tst = VG_(get_ThreadState)(tid); + + /* Correctly reestablish the frame base address. */ + esp = tst->arch.vex.guest_ESP; + esp += 8; /* Clean up stack from argument/ret passed to sigreturn(2) */ + + size = restore_sigframe(tst, (struct sigframe *)esp, &sigNo); + + VG_TRACK( die_mem_stack_signal, esp - VG_STACK_REDZONE_SZB, + size + VG_STACK_REDZONE_SZB ); + + if (VG_(clo_trace_signals)) + VG_(message)( + Vg_DebugMsg, + "VG_(signal_return) (thread %d): EIP=%#x\n", + tid, tst->arch.vex.guest_EIP); + + /* tell the tools */ + VG_TRACK( post_deliver_signal, tid, sigNo ); +} + +#endif // defined(VGP_x86_openbsd) + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_signals.c --- a/coregrind/m_signals.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_signals.c Thu Mar 31 15:57:55 2016 +0900 @@ -513,6 +513,38 @@ srP->misc.AMD64.r_rbp = (ULong)(ss->__rbp); } +#elif defined(VGP_x86_freebsd) +# define VG_UCONTEXT_INSTR_PTR(uc) ((UWord)(uc)->uc_mcontext.eip) +# define VG_UCONTEXT_STACK_PTR(uc) ((UWord)(uc)->uc_mcontext.esp) +# define VG_UCONTEXT_FRAME_PTR(uc) ((UWord)(uc)->uc_mcontext.ebp) +# define VG_UCONTEXT_SYSCALL_NUM(uc) ((UWord)(uc)->uc_mcontext.eax) +# define VG_UCONTEXT_SYSCALL_SYSRES(uc) \ + /* Convert the value in uc_mcontext.eax into a SysRes. */ \ + VG_(mk_SysRes_x86_freebsd)( (uc)->uc_mcontext.eax, \ + (uc)->uc_mcontext.edx, ((uc)->uc_mcontext.eflags & 1) != 0 ? True : False) +# define VG_UCONTEXT_LINK_REG(uc) 0 /* What is an LR for anyway? */ +# define VG_UCONTEXT_TO_UnwindStartRegs(srP, uc) \ + { (srP)->r_pc = (ULong)((uc)->uc_mcontext.eip); \ + (srP)->r_sp = (ULong)((uc)->uc_mcontext.esp); \ + (srP)->misc.X86.r_ebp = (uc)->uc_mcontext.ebp; \ + } + +#elif defined(VGP_x86_openbsd) +# define VG_UCONTEXT_INSTR_PTR(uc) ((UWord)(uc)->uc_mcontext.eip) +# define VG_UCONTEXT_STACK_PTR(uc) ((UWord)(uc)->uc_mcontext.esp) +# define VG_UCONTEXT_FRAME_PTR(uc) ((UWord)(uc)->uc_mcontext.ebp) +# define VG_UCONTEXT_SYSCALL_NUM(uc) ((UWord)(uc)->uc_mcontext.eax) +# define VG_UCONTEXT_SYSCALL_SYSRES(uc) \ + /* Convert the value in uc_mcontext.eax into a SysRes. */ \ + VG_(mk_SysRes_x86_openbsd)( (uc)->uc_mcontext.eax, \ + (uc)->uc_mcontext.edx, ((uc)->uc_mcontext.eflags & 1) != 0 ? True : False) +# define VG_UCONTEXT_LINK_REG(uc) 0 /* What is an LR for anyway? */ +# define VG_UCONTEXT_TO_UnwindStartRegs(srP, uc) \ + { (srP)->r_pc = (ULong)((uc)->uc_mcontext.eip); \ + (srP)->r_sp = (ULong)((uc)->uc_mcontext.esp); \ + (srP)->misc.X86.r_ebp = (uc)->uc_mcontext.ebp; \ + } + #elif defined(VGP_s390x_linux) # define VG_UCONTEXT_INSTR_PTR(uc) ((uc)->uc_mcontext.regs.psw.addr) @@ -521,7 +553,6 @@ # define VG_UCONTEXT_SYSCALL_SYSRES(uc) \ VG_(mk_SysRes_s390x_linux)((uc)->uc_mcontext.regs.gprs[2]) # define VG_UCONTEXT_LINK_REG(uc) ((uc)->uc_mcontext.regs.gprs[14]) - # define VG_UCONTEXT_TO_UnwindStartRegs(srP, uc) \ { (srP)->r_pc = (ULong)((uc)->uc_mcontext.regs.psw.addr); \ (srP)->r_sp = (ULong)((uc)->uc_mcontext.regs.gprs[15]); \ @@ -529,6 +560,37 @@ (srP)->misc.S390X.r_lr = (uc)->uc_mcontext.regs.gprs[14]; \ } +#elif defined(VGP_amd64_freebsd) +# define VG_UCONTEXT_INSTR_PTR(uc) ((uc)->uc_mcontext.rip) +# define VG_UCONTEXT_STACK_PTR(uc) ((uc)->uc_mcontext.rsp) +# define VG_UCONTEXT_FRAME_PTR(uc) ((uc)->uc_mcontext.rbp) +# define VG_UCONTEXT_SYSCALL_NUM(uc) ((uc)->uc_mcontext.rax) +# define VG_UCONTEXT_SYSCALL_SYSRES(uc) \ + /* Convert the value in uc_mcontext.rax into a SysRes. */ \ + VG_(mk_SysRes_amd64_freebsd)( (uc)->uc_mcontext.rax, \ + (uc)->uc_mcontext.rdx, ((uc)->uc_mcontext.rflags & 1) != 0 ? True : False ) +# define VG_UCONTEXT_LINK_REG(uc) 0 /* No LR on amd64 either */ +# define VG_UCONTEXT_TO_UnwindStartRegs(srP, uc) \ + { (srP)->r_pc = (uc)->uc_mcontext.rip; \ + (srP)->r_sp = (uc)->uc_mcontext.rsp; \ + (srP)->misc.AMD64.r_rbp = (uc)->uc_mcontext.rbp; \ + } + +#elif defined(VGP_amd64_openbsd) +# define VG_UCONTEXT_INSTR_PTR(uc) ((uc)->uc_mcontext.rip) +# define VG_UCONTEXT_STACK_PTR(uc) ((uc)->uc_mcontext.rsp) +# define VG_UCONTEXT_FRAME_PTR(uc) ((uc)->uc_mcontext.rbp) +# define VG_UCONTEXT_SYSCALL_NUM(uc) ((uc)->uc_mcontext.rax) +# define VG_UCONTEXT_SYSCALL_SYSRES(uc) \ + /* Convert the value in uc_mcontext.rax into a SysRes. */ \ + VG_(mk_SysRes_amd64_openbsd)( (uc)->uc_mcontext.rax, \ + (uc)->uc_mcontext.rdx, ((uc)->uc_mcontext.rflags & 1) != 0 ? True : False ) +# define VG_UCONTEXT_LINK_REG(uc) 0 /* No LR on amd64 either */ +# define VG_UCONTEXT_TO_UnwindStartRegs(srP, uc) \ + { (srP)->r_pc = (uc)->uc_mcontext.rip; \ + (srP)->r_sp = (uc)->uc_mcontext.rsp; \ + (srP)->misc.AMD64.r_rbp = (uc)->uc_mcontext.rbp; \ + } #elif defined(VGP_mips32_linux) # define VG_UCONTEXT_INSTR_PTR(uc) ((UWord)(((uc)->uc_mcontext.sc_pc))) # define VG_UCONTEXT_STACK_PTR(uc) ((UWord)((uc)->uc_mcontext.sc_regs[29])) @@ -579,7 +641,7 @@ #if defined(VGO_linux) # define VKI_SIGINFO_si_addr _sifields._sigfault._addr # define VKI_SIGINFO_si_pid _sifields._kill._pid -#elif defined(VGO_darwin) +#elif defined(VGO_darwin) || defined(VGO_freebsd) || defined(VGO_openbsd) # define VKI_SIGINFO_si_addr si_addr # define VKI_SIGINFO_si_pid si_pid #else @@ -734,6 +796,7 @@ case VKI_SIGFPE: case VKI_SIGILL: case VKI_SIGTRAP: + case VKI_SIGSYS: /* For these, we always want to catch them and report, even if the client code doesn't. */ skss_handler = sync_signalhandler; @@ -793,10 +856,13 @@ /* We don't set a signal stack, so ignore */ /* always ask for SA_SIGINFO */ - skss_flags |= VKI_SA_SIGINFO; - + if (skss_handler != VKI_SIG_IGN && skss_handler != VKI_SIG_DFL) + skss_flags |= VKI_SA_SIGINFO; + +#ifdef VGO_linux /* use our own restorer */ skss_flags |= VKI_SA_RESTORER; +#endif /* Create SKSS entry for this signal. */ if (sig != VKI_SIGKILL && sig != VKI_SIGSTOP) @@ -820,6 +886,7 @@ After a possible SCSS change, update SKSS and the kernel itself. ------------------------------------------------------------------ */ +#ifdef VGO_linux // We need two levels of macro-expansion here to convert __NR_rt_sigreturn // to a number before converting it to a string... sigh. extern void my_sigreturn(void); @@ -949,6 +1016,7 @@ asm( MY_SIGRETURN(__NR_rt_sigreturn) ); +#endif static void handle_SCSS_change ( Bool force_update ) @@ -984,6 +1052,8 @@ ksa.sa_flags = skss.skss_per_sig[sig].skss_flags; # if !defined(VGP_ppc32_linux) && \ !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) && \ + !defined(VGP_x86_freebsd) && !defined(VGP_amd64_freebsd) && \ + !defined(VGP_x86_openbsd) && !defined(VGP_amd64_openbsd) && \ !defined(VGP_mips32_linux) ksa.sa_restorer = my_sigreturn; # endif @@ -999,12 +1069,20 @@ VG_(sigdelset)( &ksa.sa_mask, VKI_SIGSTOP ); if (VG_(clo_trace_signals) && VG_(clo_verbosity) > 2) +#if 0 VG_(dmsg)("setting ksig %d to: hdlr %p, flags 0x%lx, " "mask(msb..lsb) 0x%llx 0x%llx\n", sig, ksa.ksa_handler, (UWord)ksa.sa_flags, _VKI_NSIG_WORDS > 1 ? (ULong)ksa.sa_mask.sig[1] : 0, (ULong)ksa.sa_mask.sig[0]); +#else + VG_(dmsg)("setting ksig %d to: hdlr %p, flags 0x%lx, " + "mask(msb..lsb) 0x%x\n", + sig, ksa.ksa_handler, + (UWord)ksa.sa_flags, + ksa.sa_mask); +#endif res = VG_(sigaction)( sig, &ksa, &ksa_old ); vg_assert(res == 0); @@ -1014,16 +1092,22 @@ if (!force_update) { vg_assert(ksa_old.ksa_handler == skss_old.skss_per_sig[sig].skss_handler); +#if !defined(VGO_openbsd) vg_assert(ksa_old.sa_flags == skss_old.skss_per_sig[sig].skss_flags); +#endif # if !defined(VGP_ppc32_linux) && \ !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) && \ + !defined(VGP_x86_freebsd) && !defined(VGP_amd64_freebsd) && \ + !defined(VGP_x86_openbsd) && !defined(VGP_amd64_openbsd) && \ !defined(VGP_mips32_linux) && !defined(VGP_mips64_linux) vg_assert(ksa_old.sa_restorer == my_sigreturn); # endif VG_(sigaddset)( &ksa_old.sa_mask, VKI_SIGKILL ); VG_(sigaddset)( &ksa_old.sa_mask, VKI_SIGSTOP ); +#if !defined(VGO_openbsd) vg_assert(VG_(isfullsigset)( &ksa_old.sa_mask )); +#endif } } } @@ -1138,7 +1222,9 @@ old_act->ksa_handler = scss.scss_per_sig[signo].scss_handler; old_act->sa_flags = scss.scss_per_sig[signo].scss_flags; old_act->sa_mask = scss.scss_per_sig[signo].scss_mask; -# if !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) +# if !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) && \ + !defined(VGP_x86_freebsd) && !defined(VGP_amd64_freebsd) && \ + !defined(VGP_x86_openbsd) && !defined(VGP_amd64_openbsd) old_act->sa_restorer = scss.scss_per_sig[signo].scss_restorer; # endif } @@ -1150,7 +1236,9 @@ scss.scss_per_sig[signo].scss_mask = new_act->sa_mask; scss.scss_per_sig[signo].scss_restorer = NULL; -# if !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) +# if !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) && \ + !defined(VGP_x86_freebsd) && !defined(VGP_amd64_freebsd) && \ + !defined(VGP_x86_openbsd) && !defined(VGP_amd64_openbsd) scss.scss_per_sig[signo].scss_restorer = new_act->sa_restorer; # endif @@ -1220,10 +1308,13 @@ HChar* format_sigset ( const vki_sigset_t* set ) { static HChar buf[128]; +#if 0 int w; +#endif VG_(strcpy)(buf, ""); +#if 0 for (w = _VKI_NSIG_WORDS - 1; w >= 0; w--) { # if _VKI_NSIG_BPW == 32 @@ -1236,6 +1327,9 @@ # error "Unsupported value for _VKI_NSIG_BPW" # endif } +#else + VG_(sprintf)(buf + VG_(strlen)(buf), "%032x", *set); +#endif return buf; } @@ -1338,7 +1432,6 @@ The signal simulation proper. A simplified version of what the Linux kernel does. ------------------------------------------------------------------ */ - /* Set up a stack frame (VgSigContext) for the client's signal handler. */ static @@ -1440,6 +1533,9 @@ # if defined(VKI_SIGUNUSED) case VKI_SIGUNUSED: return "SIGUNUSED"; # endif +# if defined(VKI_SIGINFO) + case VKI_SIGINFO: return "SIGINFO"; +# endif # if defined(VKI_SIGRTMIN) && defined(VKI_SIGRTMAX) case VKI_SIGRTMIN ... VKI_SIGRTMAX: @@ -1463,7 +1559,9 @@ sa.ksa_handler = VKI_SIG_DFL; sa.sa_flags = 0; -# if !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) +# if !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) && \ + !defined(VGP_x86_freebsd) && !defined(VGP_amd64_freebsd) && \ + !defined(VGP_x86_openbsd) && !defined(VGP_amd64_openbsd) sa.sa_restorer = 0; # endif VG_(sigemptyset)(&sa.sa_mask); @@ -1499,7 +1597,12 @@ // macros but we don't use them here because other platforms don't have // them. return ( si_code > VKI_SI_USER ? True : False ); - +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + // It looks like there's no reliable way to say where the signal came from + if (VG_(threads)[tid].status == VgTs_WaitSys) { + return False; + } else + return True; # elif defined(VGO_darwin) // On Darwin 9.6.0, the si_code is completely unreliable. It should be the // case that 0 means "user", and >0 means "kernel". But: @@ -1567,6 +1670,7 @@ case VKI_SIGTRAP: /* core */ case VKI_SIGXCPU: /* core */ case VKI_SIGXFSZ: /* core */ + case VKI_SIGSYS: /* core */ terminate = True; core = True; break; @@ -1583,7 +1687,6 @@ # if defined(VKI_SIGPWR) case VKI_SIGPWR: /* term */ # endif - case VKI_SIGSYS: /* term */ case VKI_SIGPROF: /* term */ case VKI_SIGVTALRM: /* term */ # if defined(VKI_SIGRTMIN) && defined(VKI_SIGRTMAX) @@ -2131,7 +2234,7 @@ mask them off) sign extends them when exporting to user space so we do the same thing here. */ return (Short)si_code; -#elif defined(VGO_darwin) +#elif defined(VGO_darwin) || defined(VGO_freebsd) || defined(VGO_openbsd) return si_code; #else # error Unknown OS @@ -2622,7 +2725,9 @@ VG_(printf)("pp_ksigaction: handler %p, flags 0x%x, restorer %p\n", sa->ksa_handler, (UInt)sa->sa_flags, -# if !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) +# if !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) && \ + !defined(VGP_x86_freebsd) && !defined(VGP_amd64_freebsd) && \ + !defined(VGP_x86_openbsd) && !defined(VGP_amd64_openbsd) sa->sa_restorer # else (void*)0 @@ -2644,7 +2749,9 @@ sa.ksa_handler = VKI_SIG_DFL; sa.sa_flags = 0; -# if !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) +# if !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) && \ + !defined(VGP_x86_freebsd) && !defined(VGP_amd64_freebsd) && \ + !defined(VGP_x86_openbsd) && !defined(VGP_amd64_openbsd) sa.sa_restorer = 0; # endif VG_(sigemptyset)(&sa.sa_mask); @@ -2746,7 +2853,9 @@ tsa.ksa_handler = (void *)sync_signalhandler; tsa.sa_flags = VKI_SA_SIGINFO; -# if !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) +# if !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) && \ + !defined(VGP_x86_freebsd) && !defined(VGP_amd64_freebsd) && \ + !defined(VGP_x86_openbsd) && !defined(VGP_amd64_openbsd) tsa.sa_restorer = 0; # endif VG_(sigfillset)(&tsa.sa_mask); @@ -2773,7 +2882,9 @@ scss.scss_per_sig[i].scss_mask = sa.sa_mask; scss.scss_per_sig[i].scss_restorer = NULL; -# if !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) +# if !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) && \ + !defined(VGP_x86_freebsd) && !defined(VGP_amd64_freebsd) && \ + !defined(VGP_x86_openbsd) && !defined(VGP_amd64_openbsd) scss.scss_per_sig[i].scss_restorer = sa.sa_restorer; # endif diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_stacktrace.c --- a/coregrind/m_stacktrace.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_stacktrace.c Thu Mar 31 15:57:55 2016 +0900 @@ -79,7 +79,7 @@ /* ------------------------ x86 ------------------------- */ -#if defined(VGP_x86_linux) || defined(VGP_x86_darwin) +#if defined(VGP_x86_linux) || defined(VGP_x86_darwin) || defined(VGP_x86_freebsd) || defined(VGP_x86_openbsd) #define N_FP_CF_VERIF 1021 // prime number so that size of fp_CF_verif is just below 4K or 8K @@ -452,7 +452,7 @@ /* ----------------------- amd64 ------------------------ */ -#if defined(VGP_amd64_linux) || defined(VGP_amd64_darwin) +#if defined(VGP_amd64_linux) || defined(VGP_amd64_darwin) || defined(VGP_amd64_freebsd) || defined(VGP_amd64_openbsd) UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known, /*OUT*/Addr* ips, UInt max_n_ips, @@ -551,6 +551,34 @@ continue; } +#if defined(VGO_freebsd) || defined(VGO_openbsd) + const NSegment *seg; + const HChar *filename = NULL; + int match = 0; + + seg = VG_(am_find_nsegment)(uregs.xip); + if (seg != NULL) { + filename = VG_(am_get_filename)(seg); + } + if (filename != NULL && VG_(strstr)(filename, "/libc.so")) { + match = 1; + } + if (match == 1 && fp_min <= uregs.xsp && + uregs.xsp <= fp_max - 1 * sizeof(UWord)) { + /* fp looks sane, so use it. */ + uregs.xip = (((UWord*)uregs.xsp)[0]); + if (0 == uregs.xip || 1 == uregs.xip) break; + if (fps) fps[i] = uregs.xsp; + uregs.xsp = uregs.xsp + sizeof(Addr) /*ra*/; + if (sps) sps[i] = uregs.xsp; + ips[i++] = uregs.xip - 1; /* -1: refer to calling insn, not the RA */ + if (debug) + VG_(printf)(" ipsFF[%d]=%#08lx\n", i-1, ips[i-1]); + uregs.xip = uregs.xip - 1; /* as per comment at the head of this loop */ + continue; + } +#endif + /* If VG_(use_CF_info) fails, it won't modify ip/sp/fp, so we can safely try the old-fashioned method. */ /* This bit is supposed to deal with frames resulting from diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_syscall.c --- a/coregrind/m_syscall.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_syscall.c Thu Mar 31 15:57:55 2016 +0900 @@ -265,6 +265,81 @@ } +#elif defined(VGO_freebsd) + +SysRes VG_(mk_SysRes_x86_freebsd) ( UInt val, UInt val2, Bool err ) { + SysRes r; + r._isError = err; + r._val = val; + r._val2 = val2; + return r; +} + +SysRes VG_(mk_SysRes_amd64_freebsd) ( ULong val, ULong val2, Bool err ) { + SysRes r; + r._isError = err; + r._val = val; + r._val2 = val2; + return r; +} + +/* Generic constructors. */ +SysRes VG_(mk_SysRes_Error) ( UWord err ) { + SysRes r; + r._val = err; + r._val2 = 0; + r._isError = True; + return r; +} + +SysRes VG_(mk_SysRes_Success) ( UWord res ) { + SysRes r; + r._val = res; + r._val2 = 0; + r._isError = False; + return r; +} + + +#elif defined(VGO_openbsd) + +SysRes VG_(mk_SysRes_x86_openbsd) ( UInt val, UInt val2, Bool err ) { + SysRes r; + r._hasVal2 = False; + r._isError = err; + r._val = val; + r._val2 = val2; + return r; +} + +SysRes VG_(mk_SysRes_amd64_openbsd) ( ULong val, ULong val2, Bool err ) { + SysRes r; + r._hasVal2 = True; + r._isError = err; + r._val = val; + r._val2 = val2; + return r; +} + +/* Generic constructors. */ +SysRes VG_(mk_SysRes_Error) ( UWord err ) { + SysRes r; + r._val = err; + r._val2 = 0; + r._isError = True; + r._hasVal2 = False; + return r; +} + +SysRes VG_(mk_SysRes_Success) ( UWord res ) { + SysRes r; + r._val = res; + r._val2 = 0; + r._isError = False; + r._hasVal2 = False; + return r; +} + #else # error "Unknown OS" #endif @@ -461,6 +536,33 @@ " .size do_syscall_WRK, .-do_syscall_WRK\n" ); +#elif defined(VGP_x86_freebsd) || defined(VGP_x86_openbsd) +/* Incoming args (syscall number + up to 8 args) are on the stack. + FreeBSD has a syscall called 'syscall' that takes all args (including + the syscall number) off the stack. Since we're called, the return + address is on the stack as expected, so we can just call syscall(2) + and it Just Works. Error is when carry is set. +*/ +extern ULong do_syscall_WRK ( + UWord syscall_no, + UWord a1, UWord a2, UWord a3, + UWord a4, UWord a5, UWord a6, + UWord a7, UWord a8, UInt *flags + ); +asm( +".text\n" +"do_syscall_WRK:\n" +" movl $0,%eax\n" /* syscall number = "syscall" (0) to avoid stack frobbing +*/ +" int $0x80\n" +" jb 1f\n" +" ret\n" +"1: movl 40(%esp),%ecx\n" /* store carry in *flags */ +" movl $1,(%ecx)\n" +" ret\n" +".previous\n" +); + #elif defined(VGP_arm_linux) /* I think the conventions are: args in r0 r1 r2 r3 r4 r5 @@ -516,6 +618,87 @@ ".previous\n" ); +#elif defined(VGP_amd64_freebsd) +extern UWord do_syscall_WRK ( + UWord syscall_no, /* %rdi */ + UWord a1, /* %rsi */ + UWord a2, /* %rdx */ + UWord a3, /* %rcx */ + UWord a4, /* %r8 */ + UWord a5, /* %r9 */ + UWord a6, /* 8(%rsp) */ + UWord a7, /* 16(%rsp) */ + UWord a8, /* 24(%rsp) */ + UInt *flags, /* 32(%rsp) */ + UWord *rv2 /* 40(%rsp) */ + ); +asm( +".text\n" +"do_syscall_WRK:\n" + /* Convert function calling convention --> syscall calling + convention */ +" pushq %rbp\n" +" movq %rsp, %rbp\n" +" movq %rdi, %rax\n" /* syscall_no */ +" movq %rsi, %rdi\n" /* a1 */ +" movq %rdx, %rsi\n" /* a2 */ +" movq %rcx, %rdx\n" /* a3 */ +" movq %r8, %r10\n" /* a4 */ +" movq %r9, %r8\n" /* a5 */ +" movq 16(%rbp), %r9\n" /* a6 last arg from stack, account for %rbp */ +" movq 24(%rbp), %r11\n" /* a7 from stack */ +" pushq %r11\n" +" movq 32(%rbp), %r11\n" /* a8 from stack */ +" pushq %r11\n" +" subq $8,%rsp\n" /* fake return addr */ +" syscall\n" +" jb 1f\n" +" movq 48(%rbp),%rsi\n" +" movq %rdx, (%rsi)\n" +" movq %rbp, %rsp\n" +" popq %rbp\n" +" ret\n" +"1:\n" +" movq 40(%rbp), %rsi\n" +" movl $1,(%rsi)\n" +" movq %rbp, %rsp\n" +" popq %rbp\n" +" ret\n" +".previous\n" +); + +#elif defined(VGP_amd64_openbsd) +extern UWord do_syscall_WRK ( + UWord a1, UWord a2, UWord a3, + UWord a4, UWord a5, UWord a6, + UWord a7, /* sp + 8 */ + UWord a8, /* sp + 16 */ + UWord syscall_no, /* sp + 24 */ + UWord *val1, /* sp + 32 */ + UWord *err); /* sp + 40 */ +asm( +".text\n" +".globl do_syscall_WRK\n" +"do_syscall_WRK:\n" + /* Convert function calling convention --> syscall calling + convention */ + /* Copy %rcx to %r10. See: + - sys/arch/x86/x86/syscall.c + - lib/libc/arch/x86_64/SYS.h */ + /* XXX Actually this is pretty much x86-64 SysV ABI */ +" movq %rcx, %r10\n" +" movq 24(%rsp), %rax\n" /* syscall_no */ +" syscall\n" +" jnc 1f\n" +" movq 40(%rsp), %rcx\n" /* err */ +" movq $1, (%rcx)\n" /* *err = 1 */ +"1:\n" +" movq 32(%rsp), %rcx\n" /* val1 */ +" movq %rdx, (%rcx)\n" /* *val1 = %rdx; */ +" ret\n" +".previous\n" +); + #elif defined(VGP_x86_darwin) /* Incoming args (syscall number + up to 8 args) come in on the stack @@ -753,6 +936,33 @@ UWord val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6); return VG_(mk_SysRes_amd64_linux)( val ); +# elif defined(VGP_x86_freebsd) + ULong val; + UInt err = 0; + val = do_syscall_WRK(sysno, a1, a2, a3, a4, a5, + a6, a7, a8, &err); + return VG_(mk_SysRes_x86_freebsd)( (UInt)val, (UInt)(val>>32), (err & 1) != 0 ? True : False); + +# elif defined(VGP_amd64_freebsd) + UWord val; + UWord val2 = 0; + UInt err = 0; + val = do_syscall_WRK(sysno, a1, a2, a3, a4, a5, + a6, a7, a8, &err, &val2); + return VG_(mk_SysRes_amd64_freebsd)( val, val2, (err & 1) != 0 ? True : False); + +# elif defined(VGP_x86_openbsd) + ULong val; + UInt err = 0; + val = do_syscall_WRK(sysno, a1, a2, a3, a4, a5, + a6, a7, a8, &err); + return VG_(mk_SysRes_x86_openbsd)( (UInt)val, (UInt)(val>>32), (err & 1) != 0 ? True : False); + +# elif defined(VGP_amd64_openbsd) + UWord val0, val1, err = 0; + val0 = do_syscall_WRK(a1, a2, a3, a4, a5, a6, a7, a8, sysno, &val1, &err); + return VG_(mk_SysRes_amd64_openbsd)(val0, val1, (err & 1) != 0 ? True : False); + # elif defined(VGP_ppc32_linux) ULong ret = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6); UInt val = (UInt)(ret>>32); @@ -918,6 +1128,9 @@ # if defined(VKI_ERESTARTSYS) case VKI_ERESTARTSYS: return "ERESTARTSYS"; # endif +# if defined(VKI_ERESTART) + case VKI_ERESTART: return "ERESTART"; +# endif default: return "VG_(strerror): unknown error"; } } diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_syswrap/priv_syswrap-freebsd.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coregrind/m_syswrap/priv_syswrap-freebsd.h Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,276 @@ + +/*--------------------------------------------------------------------*/ +/*--- FreeBSD-specific syscalls stuff. priv_syswrap-freebsd.h ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2008 Nicholas Nethercote + njn@valgrind.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#ifndef __PRIV_SYSWRAP_FREEBSD_H +#define __PRIV_SYSWRAP_FREEBSD_H + +/* requires #include "priv_types_n_macros.h" */ + +// Clone-related functions +extern Word ML_(start_thread_NORETURN) ( void* arg ); +extern Addr ML_(allocstack) ( ThreadId tid ); +extern void ML_(call_on_new_stack_0_1) ( Addr stack, Addr retaddr, + void (*f)(Word), Word arg1 ); +extern SysRes ML_(do_fork) ( ThreadId tid ); +extern SysRes ML_(do_vfork) ( ThreadId tid ); +extern SysRes ML_(do_rfork) ( ThreadId tid, Int flags ); + + +DECL_TEMPLATE(freebsd, sys_syscall); +DECL_TEMPLATE(freebsd, sys_exit); +DECL_TEMPLATE(freebsd, sys_getfsstat4); +DECL_TEMPLATE(freebsd, sys_getfsstat); +DECL_TEMPLATE(freebsd, sys_mount); +DECL_TEMPLATE(freebsd, sys_unmount); +DECL_TEMPLATE(freebsd, sys_ptrace); +DECL_TEMPLATE(freebsd, sys_recvmsg); +DECL_TEMPLATE(freebsd, sys_sendmsg); +DECL_TEMPLATE(freebsd, sys_recvfrom); +DECL_TEMPLATE(freebsd, sys_accept); +DECL_TEMPLATE(freebsd, sys_getpeername); +DECL_TEMPLATE(freebsd, sys_getsockname); +DECL_TEMPLATE(freebsd, sys_chflags); +DECL_TEMPLATE(freebsd, sys_fchflags); +DECL_TEMPLATE(freebsd, sys_pipe); +DECL_TEMPLATE(freebsd, sys_ktrace); +DECL_TEMPLATE(freebsd, sys_getlogin); +DECL_TEMPLATE(freebsd, sys_setlogin); +DECL_TEMPLATE(freebsd, sys_reboot); +DECL_TEMPLATE(freebsd, sys_revoke); +DECL_TEMPLATE(freebsd, sys_sbrk); +DECL_TEMPLATE(freebsd, sys_sstk); +DECL_TEMPLATE(freebsd, sys_swapon); +DECL_TEMPLATE(freebsd, sys_getdtablesize); +DECL_TEMPLATE(freebsd, sys_socket); +DECL_TEMPLATE(freebsd, sys_connect); +DECL_TEMPLATE(freebsd, sys_bind); +DECL_TEMPLATE(freebsd, sys_setsockopt); +DECL_TEMPLATE(freebsd, sys_listen); +DECL_TEMPLATE(freebsd, sys_getsockopt); +DECL_TEMPLATE(freebsd, sys_mkfifo); +DECL_TEMPLATE(freebsd, sys_sendto); +DECL_TEMPLATE(freebsd, sys_shutdown); +DECL_TEMPLATE(freebsd, sys_socketpair); +DECL_TEMPLATE(freebsd, sys_adjtime); +DECL_TEMPLATE(freebsd, sys_quotactl); +DECL_TEMPLATE(freebsd, sys_nfssvc); +DECL_TEMPLATE(freebsd, sys_getfh); +DECL_TEMPLATE(freebsd, sys_getdomainname); +DECL_TEMPLATE(freebsd, sys_setdomainname); +DECL_TEMPLATE(freebsd, sys_uname); +DECL_TEMPLATE(freebsd, sys_sysarch); +DECL_TEMPLATE(freebsd, sys_rtprio); +DECL_TEMPLATE(freebsd, sys_semsys); +DECL_TEMPLATE(freebsd, sys_msgsys); +DECL_TEMPLATE(freebsd, sys_shmsys); +DECL_TEMPLATE(freebsd, sys_pread); +DECL_TEMPLATE(freebsd, sys_pwrite); +DECL_TEMPLATE(freebsd, sys_ntp_adjtime); +DECL_TEMPLATE(freebsd, sys_setegid); +DECL_TEMPLATE(freebsd, sys_seteuid); +DECL_TEMPLATE(freebsd, sys_stat); +DECL_TEMPLATE(freebsd, sys_fstat); +DECL_TEMPLATE(freebsd, sys_lstat); +DECL_TEMPLATE(freebsd, sys_pathconf); +DECL_TEMPLATE(freebsd, sys_fpathconf); +DECL_TEMPLATE(freebsd, sys_getdirentries); +DECL_TEMPLATE(freebsd, sys_mmap); +DECL_TEMPLATE(freebsd, sys___syscall); +DECL_TEMPLATE(freebsd, sys_lseek); +DECL_TEMPLATE(freebsd, sys_truncate); +DECL_TEMPLATE(freebsd, sys_ftruncate); +DECL_TEMPLATE(freebsd, sys___sysctl); +DECL_TEMPLATE(freebsd, sys_undelete); +DECL_TEMPLATE(freebsd, sys_futimes); +DECL_TEMPLATE(freebsd, sys_nfs_fhopen); +DECL_TEMPLATE(freebsd, sys___semctl7); +DECL_TEMPLATE(freebsd, sys___semctl); +DECL_TEMPLATE(freebsd, sys_semget); +DECL_TEMPLATE(freebsd, sys_semop); +DECL_TEMPLATE(freebsd, sys_msgctl); +DECL_TEMPLATE(freebsd, sys_msgget); +DECL_TEMPLATE(freebsd, sys_msgsnd); +DECL_TEMPLATE(freebsd, sys_msgrcv); +DECL_TEMPLATE(freebsd, sys_shmat); +DECL_TEMPLATE(freebsd, sys_shmctl); +DECL_TEMPLATE(freebsd, sys_shmctl7); +DECL_TEMPLATE(freebsd, sys_shmdt); +DECL_TEMPLATE(freebsd, sys_shmget); +DECL_TEMPLATE(freebsd, sys_clock_gettime); +DECL_TEMPLATE(freebsd, sys_clock_settime); +DECL_TEMPLATE(freebsd, sys_clock_getres); +DECL_TEMPLATE(freebsd, sys_minherit); +DECL_TEMPLATE(freebsd, sys_rfork); +DECL_TEMPLATE(freebsd, sys_issetugid); +DECL_TEMPLATE(freebsd, sys_lchmod); +DECL_TEMPLATE(freebsd, sys_lutimes); +DECL_TEMPLATE(freebsd, sys_netbsd_msync); +DECL_TEMPLATE(freebsd, sys_nstat); +DECL_TEMPLATE(freebsd, sys_nfstat); +DECL_TEMPLATE(freebsd, sys_nlstat); +DECL_TEMPLATE(freebsd, sys_fhstatfs); +DECL_TEMPLATE(freebsd, sys_fhopen); +DECL_TEMPLATE(freebsd, sys_fhstat); +DECL_TEMPLATE(freebsd, sys_modnext); +DECL_TEMPLATE(freebsd, sys_modstat); +DECL_TEMPLATE(freebsd, sys_modfnext); +DECL_TEMPLATE(freebsd, sys_modfind); +DECL_TEMPLATE(freebsd, sys_kldload); +DECL_TEMPLATE(freebsd, sys_kldunload); +DECL_TEMPLATE(freebsd, sys_kldfind); +DECL_TEMPLATE(freebsd, sys_kldnext); +DECL_TEMPLATE(freebsd, sys_kldstat); +DECL_TEMPLATE(freebsd, sys_kldfirstmod); +DECL_TEMPLATE(freebsd, sys_setresuid); +DECL_TEMPLATE(freebsd, sys_setresgid); +DECL_TEMPLATE(freebsd, sys_aio_return); +DECL_TEMPLATE(freebsd, sys_aio_suspend); +DECL_TEMPLATE(freebsd, sys_aio_cancel); +DECL_TEMPLATE(freebsd, sys_aio_error); +DECL_TEMPLATE(freebsd, sys_aio_read); +DECL_TEMPLATE(freebsd, sys_aio_write); +DECL_TEMPLATE(freebsd, sys_lio_listio); +DECL_TEMPLATE(freebsd, sys_yield); +DECL_TEMPLATE(freebsd, sys_thr_sleep); +DECL_TEMPLATE(freebsd, sys_thr_wakeup); +DECL_TEMPLATE(freebsd, sys_munlockall); +DECL_TEMPLATE(freebsd, sys___getcwd); +DECL_TEMPLATE(freebsd, sys_sched_setparam); +DECL_TEMPLATE(freebsd, sys_sched_getparam); +DECL_TEMPLATE(freebsd, sys_sched_setscheduler); +DECL_TEMPLATE(freebsd, sys_sched_getscheduler); +DECL_TEMPLATE(freebsd, sys_sched_yield); +DECL_TEMPLATE(freebsd, sys_sched_get_priority_max); +DECL_TEMPLATE(freebsd, sys_sched_get_priority_min); +DECL_TEMPLATE(freebsd, sys_sched_rr_get_interval); +DECL_TEMPLATE(freebsd, sys_utrace); +DECL_TEMPLATE(freebsd, sys_kldsym); +DECL_TEMPLATE(freebsd, sys_jail); +DECL_TEMPLATE(freebsd, sys_sigprocmask); +DECL_TEMPLATE(freebsd, sys_sigsuspend); +DECL_TEMPLATE(freebsd, sys_sigaction); +DECL_TEMPLATE(freebsd, sys_sigpending); +DECL_TEMPLATE(freebsd, sys_sigreturn); +DECL_TEMPLATE(freebsd, sys_fake_sigreturn); +DECL_TEMPLATE(freebsd, sys_sigtimedwait); +DECL_TEMPLATE(freebsd, sys_sigwaitinfo); +DECL_TEMPLATE(freebsd, sys_getcontext); +DECL_TEMPLATE(freebsd, sys_setcontext); +DECL_TEMPLATE(freebsd, sys_swapcontext); +DECL_TEMPLATE(freebsd, sys___acl_get_file); +DECL_TEMPLATE(freebsd, sys___acl_set_file); +DECL_TEMPLATE(freebsd, sys___acl_get_fd); +DECL_TEMPLATE(freebsd, sys___acl_set_fd); +DECL_TEMPLATE(freebsd, sys___acl_delete_file); +DECL_TEMPLATE(freebsd, sys___acl_delete_fd); +DECL_TEMPLATE(freebsd, sys___acl_aclcheck_file); +DECL_TEMPLATE(freebsd, sys___acl_aclcheck_fd); +DECL_TEMPLATE(freebsd, sys___acl_get_link); +DECL_TEMPLATE(freebsd, sys___acl_set_link); +DECL_TEMPLATE(freebsd, sys___acl_delete_link); +DECL_TEMPLATE(freebsd, sys___acl_aclcheck_link); +DECL_TEMPLATE(freebsd, sys_extattrctl); +DECL_TEMPLATE(freebsd, sys_extattr_set_file); +DECL_TEMPLATE(freebsd, sys_extattr_get_file); +DECL_TEMPLATE(freebsd, sys_extattr_delete_file); +DECL_TEMPLATE(freebsd, sys_aio_waitcomplete); +DECL_TEMPLATE(freebsd, sys_getresuid); +DECL_TEMPLATE(freebsd, sys_getresgid); +DECL_TEMPLATE(freebsd, sys_kqueue); +DECL_TEMPLATE(freebsd, sys_kevent); +DECL_TEMPLATE(freebsd, sys_sendfile); +DECL_TEMPLATE(freebsd, sys_statfs6); +DECL_TEMPLATE(freebsd, sys_fstatfs6); +DECL_TEMPLATE(freebsd, sys_fhstatfs6); +DECL_TEMPLATE(freebsd, sys_thr_exit); +DECL_TEMPLATE(freebsd, sys_thr_self); +DECL_TEMPLATE(freebsd, sys_thr_set_name); +DECL_TEMPLATE(freebsd, sys_rtprio_thread); +DECL_TEMPLATE(freebsd, sys_fork); +DECL_TEMPLATE(freebsd, sys_vfork); +DECL_TEMPLATE(freebsd, sys_modfind); +DECL_TEMPLATE(freebsd, sys_modstat); +DECL_TEMPLATE(freebsd, sys_lkmnosys0); +DECL_TEMPLATE(freebsd, sys_lkmnosys1); +DECL_TEMPLATE(freebsd, sys_lkmnosys2); +DECL_TEMPLATE(freebsd, sys_lkmnosys3); +DECL_TEMPLATE(freebsd, sys_lkmnosys4); +DECL_TEMPLATE(freebsd, sys_lkmnosys5); +DECL_TEMPLATE(freebsd, sys_lkmnosys6); +DECL_TEMPLATE(freebsd, sys_lkmnosys7); +DECL_TEMPLATE(freebsd, sys_lkmnosys8); +DECL_TEMPLATE(freebsd, sys_sigaction4); +DECL_TEMPLATE(freebsd, sys_mmap7); +DECL_TEMPLATE(freebsd, sys_lseek7); +DECL_TEMPLATE(freebsd, sys_truncate7); +DECL_TEMPLATE(freebsd, sys_ftruncate7); +DECL_TEMPLATE(freebsd, sys_pread7); +DECL_TEMPLATE(freebsd, sys_pwrite7); +DECL_TEMPLATE(freebsd, sys__umtx_op); +DECL_TEMPLATE(freebsd, sys__umtx_lock); +DECL_TEMPLATE(freebsd, sys__umtx_unlock); +DECL_TEMPLATE(freebsd, sys_thr_kill2); +DECL_TEMPLATE(freebsd, sys_thr_wake); +DECL_TEMPLATE(freebsd, sys_shm_open); +DECL_TEMPLATE(freebsd, sys_shm_unlink); +DECL_TEMPLATE(freebsd, sys_eaccess); +DECL_TEMPLATE(freebsd, sys_cpuset); +DECL_TEMPLATE(freebsd, sys_cpuset_setid); +DECL_TEMPLATE(freebsd, sys_cpuset_getid); +DECL_TEMPLATE(freebsd, sys_cpuset_getaffinity); +DECL_TEMPLATE(freebsd, sys_cpuset_setaffinity); +DECL_TEMPLATE(freebsd, sys_faccessat); +DECL_TEMPLATE(freebsd, sys_fchmodat); +DECL_TEMPLATE(freebsd, sys_fchownat); +DECL_TEMPLATE(freebsd, sys_fexecve); +DECL_TEMPLATE(freebsd, sys_fstatat); +DECL_TEMPLATE(freebsd, sys_futimesat); +DECL_TEMPLATE(freebsd, sys_linkat); +DECL_TEMPLATE(freebsd, sys_mkdirat); +DECL_TEMPLATE(freebsd, sys_mkfifoat); +DECL_TEMPLATE(freebsd, sys_mknodat); +DECL_TEMPLATE(freebsd, sys_openat); +DECL_TEMPLATE(freebsd, sys_readlinkat); +DECL_TEMPLATE(freebsd, sys_renameat); +DECL_TEMPLATE(freebsd, sys_symlinkat); +DECL_TEMPLATE(freebsd, sys_unlinkat); +DECL_TEMPLATE(freebsd, sys_posix_openpt); +DECL_TEMPLATE(freebsd, sys_kenv); +DECL_TEMPLATE(freebsd, sys_uuidgen); +DECL_TEMPLATE(freebsd, sys_thr_new); +DECL_TEMPLATE(freebsd, sys_thr_kill); +DECL_TEMPLATE(freebsd, sys_thr_kill2); +DECL_TEMPLATE(freebsd, sys_fcntl); +DECL_TEMPLATE(freebsd, sys_ioctl); +#endif // __PRIV_SYSWRAP_FREEBSD_H + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_syswrap/priv_syswrap-generic.h --- a/coregrind/m_syswrap/priv_syswrap-generic.h Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_syswrap/priv_syswrap-generic.h Thu Mar 31 15:57:55 2016 +0900 @@ -65,6 +65,7 @@ extern void ML_(record_fd_open_nameless) (ThreadId tid, Int fd); extern void ML_(record_fd_open_with_given_name)(ThreadId tid, Int fd, char *pathname); +extern void ML_(mark_fd_as_internal)(ThreadId tid, Int fd); // Used when killing threads -- we must not kill a thread if it's the thread // that would do Valgrind's final cleanup and output. @@ -94,6 +95,8 @@ extern void ML_(POST_unknown_ioctl)(ThreadId tid, UInt res, UWord request, UWord arg); +char *VG_(pathname_by_fd)(Int fd); + DECL_TEMPLATE(generic, sys_ni_syscall); // * P -- unimplemented DECL_TEMPLATE(generic, sys_exit); @@ -161,7 +164,9 @@ // These ones aren't POSIX, but are in some standard and look reasonably // generic, and are the same for all architectures under Linux. +#ifdef VGO_linux DECL_TEMPLATE(generic, sys_nice); // SVr4, SVID EXT, AT&T, X/OPEN, BSD 4.3 +#endif DECL_TEMPLATE(generic, sys_sync); // SVr4, SVID, X/OPEN, BSD 4.3 DECL_TEMPLATE(generic, sys_brk); // 4.3BSD DECL_TEMPLATE(generic, sys_acct); // SVR4, non-POSIX @@ -173,7 +178,9 @@ DECL_TEMPLATE(generic, sys_flock); // 4.4BSD DECL_TEMPLATE(generic, sys_poll); // XPG4-UNIX DECL_TEMPLATE(generic, sys_getrusage); // SVr4, 4.3BSD +#ifdef VGO_linux DECL_TEMPLATE(generic, sys_stime); // SVr4, SVID, X/OPEN +#endif DECL_TEMPLATE(generic, sys_settimeofday); // SVr4, 4.3BSD (non-POSIX) DECL_TEMPLATE(generic, sys_getpriority); // SVr4, 4.4BSD DECL_TEMPLATE(generic, sys_setpriority); // SVr4, 4.4BSD @@ -189,31 +196,43 @@ DECL_TEMPLATE(generic, sys_sigaction); // (x86) P // Funny names, not sure... +#ifdef VGO_linux DECL_TEMPLATE(generic, sys_newstat); // * P DECL_TEMPLATE(generic, sys_newlstat); // * DECL_TEMPLATE(generic, sys_newfstat); // * P (SVr4,BSD4.3) +#endif // For the remainder, not really sure yet DECL_TEMPLATE(generic, sys_ptrace); // (x86?) (almost-P) DECL_TEMPLATE(generic, sys_setrlimit); // SVr4, 4.3BSD +#ifdef VGO_linux DECL_TEMPLATE(generic, sys_old_getrlimit); // SVr4, 4.3BSD L? +#endif DECL_TEMPLATE(generic, sys_statfs); // * L? DECL_TEMPLATE(generic, sys_fstatfs); // * L? +#ifdef VGO_linux DECL_TEMPLATE(generic, sys_iopl); // (x86/amd64) L DECL_TEMPLATE(generic, sys_newuname); // * P DECL_TEMPLATE(generic, sys_pread64); // * (Unix98?) DECL_TEMPLATE(generic, sys_pwrite64); // * (Unix98?) +#endif DECL_TEMPLATE(generic, sys_sigaltstack); // (x86) (XPG4-UNIX) +#ifdef VGO_linux DECL_TEMPLATE(generic, sys_getpmsg); // (?) (?) DECL_TEMPLATE(generic, sys_putpmsg); // (?) (?) +#endif DECL_TEMPLATE(generic, sys_getrlimit); // * (?) +#ifdef VGO_linux DECL_TEMPLATE(generic, sys_truncate64); // %% (P?) DECL_TEMPLATE(generic, sys_ftruncate64); // %% (P?) +#endif DECL_TEMPLATE(generic, sys_lchown); // * (L?) DECL_TEMPLATE(generic, sys_mincore); // * L? +#ifdef VGO_linux DECL_TEMPLATE(generic, sys_getdents64); // * (SVr4,SVID?) DECL_TEMPLATE(generic, sys_statfs64); // * (?) DECL_TEMPLATE(generic, sys_fstatfs64); // * (?) +#endif /* --------------------------------------------------------------------- diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_syswrap/priv_syswrap-openbsd.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coregrind/m_syswrap/priv_syswrap-openbsd.h Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,299 @@ + +/*--------------------------------------------------------------------*/ +/*--- FreeBSD-specific syscalls stuff. priv_syswrap-freebsd.h ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2008 Nicholas Nethercote + njn@valgrind.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#ifndef __PRIV_SYSWRAP_OPENBSD_H +#define __PRIV_SYSWRAP_OPENBSD_H + +/* requires #include "priv_types_n_macros.h" */ + +// Clone-related functions +extern Word ML_(start_thread_NORETURN) ( void* arg ); +extern Addr ML_(allocstack) ( ThreadId tid ); +extern void ML_(call_on_new_stack_0_1) ( Addr stack, Addr retaddr, + void (*f)(Word), Word arg1 ); +extern SysRes ML_(do_fork) ( ThreadId tid ); +extern SysRes ML_(do_vfork) ( ThreadId tid ); +extern SysRes ML_(do_rfork) ( ThreadId tid, Int flags ); + +DECL_TEMPLATE(openbsd, sys_syscall); +DECL_TEMPLATE(openbsd, sys_exit); +DECL_TEMPLATE(openbsd, sys_fork); +DECL_TEMPLATE(openbsd, sys_read); +DECL_TEMPLATE(openbsd, sys_write); +DECL_TEMPLATE(openbsd, sys_open); +DECL_TEMPLATE(openbsd, sys_close); +DECL_TEMPLATE(openbsd, sys_getentropy); +DECL_TEMPLATE(openbsd, sys___tfork); +DECL_TEMPLATE(openbsd, sys_link); +DECL_TEMPLATE(openbsd, sys_unlink); +DECL_TEMPLATE(openbsd, sys_wait4); +DECL_TEMPLATE(openbsd, sys_chdir); +DECL_TEMPLATE(openbsd, sys_fchdir); +DECL_TEMPLATE(openbsd, sys_mknod); +DECL_TEMPLATE(openbsd, sys_chmod); +DECL_TEMPLATE(openbsd, sys_chown); +DECL_TEMPLATE(openbsd, sys_break); +DECL_TEMPLATE(openbsd, sys_getdtablecount); +DECL_TEMPLATE(openbsd, sys_getpid); +DECL_TEMPLATE(openbsd, sys_mount); +DECL_TEMPLATE(openbsd, sys_unmount); +DECL_TEMPLATE(openbsd, sys_setuid); +DECL_TEMPLATE(openbsd, sys_getuid); +DECL_TEMPLATE(openbsd, sys_geteuid); +DECL_TEMPLATE(openbsd, sys_ptrace); +DECL_TEMPLATE(openbsd, sys_recvmsg); +DECL_TEMPLATE(openbsd, sys_sendmsg); +DECL_TEMPLATE(openbsd, sys_recvfrom); +DECL_TEMPLATE(openbsd, sys_accept); +DECL_TEMPLATE(openbsd, sys_accept4); +DECL_TEMPLATE(openbsd, sys_getpeername); +DECL_TEMPLATE(openbsd, sys_getsockname); +DECL_TEMPLATE(openbsd, sys_access); +DECL_TEMPLATE(openbsd, sys_chflags); +DECL_TEMPLATE(openbsd, sys_chflagsat); +DECL_TEMPLATE(openbsd, sys_fchflags); +DECL_TEMPLATE(openbsd, sys_sync); +DECL_TEMPLATE(openbsd, sys_kill); +DECL_TEMPLATE(openbsd, sys_getppid); +DECL_TEMPLATE(openbsd, sys_dup); +DECL_TEMPLATE(openbsd, sys_dup3); +DECL_TEMPLATE(openbsd, sys_getegid); +DECL_TEMPLATE(openbsd, sys_profil); +DECL_TEMPLATE(openbsd, sys_ktrace); +DECL_TEMPLATE(openbsd, sys_sigaction); +DECL_TEMPLATE(openbsd, sys_sigaction4); +DECL_TEMPLATE(openbsd, sys_getgid); +DECL_TEMPLATE(openbsd, sys_sigprocmask); +DECL_TEMPLATE(openbsd, sys_sigtimedwait); +DECL_TEMPLATE(openbsd, sys_sigwaitinfo); +DECL_TEMPLATE(openbsd, sys_getlogin); +DECL_TEMPLATE(openbsd, sys_setlogin); +DECL_TEMPLATE(openbsd, sys_acct); +DECL_TEMPLATE(openbsd, sys_sigpending); +DECL_TEMPLATE(openbsd, sys_ioctl); +DECL_TEMPLATE(openbsd, sys_reboot); +DECL_TEMPLATE(openbsd, sys_revoke); +DECL_TEMPLATE(openbsd, sys_undelete); +DECL_TEMPLATE(openbsd, sys_yield); +DECL_TEMPLATE(openbsd, sys_symlink); +DECL_TEMPLATE(openbsd, sys_readlink); +DECL_TEMPLATE(openbsd, sys_execve); +DECL_TEMPLATE(openbsd, sys_umask); +DECL_TEMPLATE(openbsd, sys_chroot); +DECL_TEMPLATE(openbsd, sys_getfsstat); +DECL_TEMPLATE(openbsd, sys_statfs); +DECL_TEMPLATE(openbsd, sys_statfs6); +DECL_TEMPLATE(openbsd, sys_fstatfs); +DECL_TEMPLATE(openbsd, sys_fstatfs6); +DECL_TEMPLATE(openbsd, sys_fhstatfs); +DECL_TEMPLATE(openbsd, sys_fhstatfs6); +DECL_TEMPLATE(openbsd, sys_vfork); +DECL_TEMPLATE(openbsd, sys_munmap); +DECL_TEMPLATE(openbsd, sys_mprotect); +DECL_TEMPLATE(openbsd, sys_madvise); +DECL_TEMPLATE(openbsd, sys_mincore); +DECL_TEMPLATE(openbsd, sys_getgroups); +DECL_TEMPLATE(openbsd, sys_setgroups); +DECL_TEMPLATE(openbsd, sys_getpgrp); +DECL_TEMPLATE(openbsd, sys_setpgid); +DECL_TEMPLATE(openbsd, sys_sendsyslog); +DECL_TEMPLATE(openbsd, sys_setitimer); +DECL_TEMPLATE(openbsd, sys_getitimer); +DECL_TEMPLATE(openbsd, sys_dup2); +DECL_TEMPLATE(openbsd, sys_getcontext); +DECL_TEMPLATE(openbsd, sys_setcontext); +DECL_TEMPLATE(openbsd, sys_swapcontext); +DECL_TEMPLATE(openbsd, sys_fcntl); +DECL_TEMPLATE(openbsd, sys_select); +DECL_TEMPLATE(openbsd, sys_fsync); +DECL_TEMPLATE(openbsd, sys_setpriority); +DECL_TEMPLATE(openbsd, sys_socket); +DECL_TEMPLATE(openbsd, sys_connect); +DECL_TEMPLATE(openbsd, sys_getpriority); +DECL_TEMPLATE(openbsd, sys_sigreturn); +DECL_TEMPLATE(openbsd, sys_bind); +DECL_TEMPLATE(openbsd, sys_setsockopt); +DECL_TEMPLATE(openbsd, sys_listen); +DECL_TEMPLATE(openbsd, sys_pledge); +DECL_TEMPLATE(openbsd, sys_ppoll); +DECL_TEMPLATE(openbsd, sys_pselect); +DECL_TEMPLATE(openbsd, sys_sigsuspend); +DECL_TEMPLATE(openbsd, sys_gettimeofday); +DECL_TEMPLATE(openbsd, sys_getrusage); +DECL_TEMPLATE(openbsd, sys_getsockopt); +DECL_TEMPLATE(openbsd, sys_readv); +DECL_TEMPLATE(openbsd, sys_writev); +DECL_TEMPLATE(openbsd, sys_settimeofday); +DECL_TEMPLATE(openbsd, sys_fchown); +DECL_TEMPLATE(openbsd, sys_fchmod); +DECL_TEMPLATE(openbsd, sys_setreuid); +DECL_TEMPLATE(openbsd, sys_setregid); +DECL_TEMPLATE(openbsd, sys_rename); +DECL_TEMPLATE(openbsd, sys_flock); +DECL_TEMPLATE(openbsd, sys_mkfifo); +DECL_TEMPLATE(openbsd, sys_sendto); +DECL_TEMPLATE(openbsd, sys_shutdown); +DECL_TEMPLATE(openbsd, sys_socketpair); +DECL_TEMPLATE(openbsd, sys_mkdir); +DECL_TEMPLATE(openbsd, sys_rmdir); +DECL_TEMPLATE(openbsd, sys_utimes); +DECL_TEMPLATE(openbsd, sys_adjtime); +DECL_TEMPLATE(openbsd, sys_setsid); +DECL_TEMPLATE(openbsd, sys_quotactl); +DECL_TEMPLATE(openbsd, sys_nfssvc); +DECL_TEMPLATE(openbsd, sys_getdomainname); +DECL_TEMPLATE(openbsd, sys_setdomainname); +DECL_TEMPLATE(openbsd, sys_getfh); +DECL_TEMPLATE(openbsd, sys_sysarch); +DECL_TEMPLATE(openbsd, sys_pread); +DECL_TEMPLATE(openbsd, sys_pwrite); +DECL_TEMPLATE(openbsd, sys_setgid); +DECL_TEMPLATE(openbsd, sys_setegid); +DECL_TEMPLATE(openbsd, sys_lutimes); +DECL_TEMPLATE(openbsd, sys_seteuid); +DECL_TEMPLATE(openbsd, sys_pathconf); +DECL_TEMPLATE(openbsd, sys_fpathconf); +DECL_TEMPLATE(openbsd, sys_lchmod); +DECL_TEMPLATE(openbsd, sys_swapctl); +DECL_TEMPLATE(openbsd, sys_getrlimit); +DECL_TEMPLATE(openbsd, sys_setrlimit); +DECL_TEMPLATE(openbsd, sys_mmap); +DECL_TEMPLATE(openbsd, sys___syscall); +DECL_TEMPLATE(openbsd, sys_lseek); +DECL_TEMPLATE(openbsd, sys_truncate); +DECL_TEMPLATE(openbsd, sys_ftruncate); +DECL_TEMPLATE(openbsd, sys___sysctl); +DECL_TEMPLATE(openbsd, sys_sendfile); +DECL_TEMPLATE(openbsd, sys_mlock); +DECL_TEMPLATE(openbsd, sys_munlock); +DECL_TEMPLATE(openbsd, sys_futimes); +DECL_TEMPLATE(openbsd, sys_getpgid); +DECL_TEMPLATE(openbsd, sys_utrace); +DECL_TEMPLATE(openbsd, sys_semget); +DECL_TEMPLATE(openbsd, sys_shm_open); +DECL_TEMPLATE(openbsd, sys_shm_unlink); +DECL_TEMPLATE(openbsd, sys_msgget); +DECL_TEMPLATE(openbsd, sys_msgsnd); +DECL_TEMPLATE(openbsd, sys_msgrcv); +DECL_TEMPLATE(openbsd, sys_shmat); +DECL_TEMPLATE(openbsd, sys_shmdt); +DECL_TEMPLATE(openbsd, sys_kbind); +DECL_TEMPLATE(openbsd, sys_clock_gettime); +DECL_TEMPLATE(openbsd, sys_clock_settime); +DECL_TEMPLATE(openbsd, sys_clock_getres); +DECL_TEMPLATE(openbsd, sys_nanosleep); +DECL_TEMPLATE(openbsd, sys_minherit); +DECL_TEMPLATE(openbsd, sys_poll); +DECL_TEMPLATE(openbsd, sys_issetugid); +DECL_TEMPLATE(openbsd, sys_lchown); +DECL_TEMPLATE(openbsd, sys_getsid); +DECL_TEMPLATE(openbsd, sys_msync); +DECL_TEMPLATE(openbsd, sys_pipe); +DECL_TEMPLATE(openbsd, sys_pipe2); +DECL_TEMPLATE(openbsd, sys_fhopen); +DECL_TEMPLATE(openbsd, sys_preadv); +DECL_TEMPLATE(openbsd, sys_pwritev); +DECL_TEMPLATE(openbsd, sys_kqueue); +DECL_TEMPLATE(openbsd, sys_kevent); +DECL_TEMPLATE(openbsd, sys_mlockall); +DECL_TEMPLATE(openbsd, sys_munlockall); +DECL_TEMPLATE(openbsd, sys_getresuid); +DECL_TEMPLATE(openbsd, sys_setresuid); +DECL_TEMPLATE(openbsd, sys_getresgid); +DECL_TEMPLATE(openbsd, sys_setresgid); +DECL_TEMPLATE(openbsd, sys_mquery); +DECL_TEMPLATE(openbsd, sys_closefrom); +DECL_TEMPLATE(openbsd, sys_sigaltstack); +DECL_TEMPLATE(openbsd, sys_shmget); +DECL_TEMPLATE(openbsd, sys_semop); +DECL_TEMPLATE(openbsd, sys_stat); +DECL_TEMPLATE(openbsd, sys_fstat); +DECL_TEMPLATE(openbsd, sys_lstat); +DECL_TEMPLATE(openbsd, sys_fhstat); +DECL_TEMPLATE(openbsd, sys___semctl); +DECL_TEMPLATE(openbsd, sys_shmctl); +DECL_TEMPLATE(openbsd, sys_msgctl); +DECL_TEMPLATE(openbsd, sys_sched_yield); +DECL_TEMPLATE(openbsd, sys_sched_get_priority_max); +DECL_TEMPLATE(openbsd, sys_sched_get_priority_min); +DECL_TEMPLATE(openbsd, sys_getthrid); +DECL_TEMPLATE(openbsd, sys___thrsleep); +DECL_TEMPLATE(openbsd, sys___thrwakeup); +DECL_TEMPLATE(openbsd, sys___threxit); +DECL_TEMPLATE(openbsd, sys___thrsigdivert); +DECL_TEMPLATE(openbsd, sys___getcwd); +DECL_TEMPLATE(openbsd, sys_getfsstat4); +DECL_TEMPLATE(openbsd, sys_adjfreq); +DECL_TEMPLATE(openbsd, sys_setrtable); +DECL_TEMPLATE(openbsd, sys_getrtable); +DECL_TEMPLATE(openbsd, sys_getdirentries); +DECL_TEMPLATE(openbsd, sys_faccessat); +DECL_TEMPLATE(openbsd, sys_fchmodat); +DECL_TEMPLATE(openbsd, sys_fchownat); +DECL_TEMPLATE(openbsd, sys_fstatat); +DECL_TEMPLATE(openbsd, sys_linkat); +DECL_TEMPLATE(openbsd, sys_mkdirat); +DECL_TEMPLATE(openbsd, sys_mkfifoat); +DECL_TEMPLATE(openbsd, sys_mknodat); +DECL_TEMPLATE(openbsd, sys_openat); +DECL_TEMPLATE(openbsd, sys_readlinkat); +DECL_TEMPLATE(openbsd, sys_renameat); +DECL_TEMPLATE(openbsd, sys_symlinkat); +DECL_TEMPLATE(openbsd, sys_unlinkat); +DECL_TEMPLATE(openbsd, sys_utimensat); +DECL_TEMPLATE(openbsd, sys_futimens); +DECL_TEMPLATE(openbsd, sys___set_tcb); +DECL_TEMPLATE(openbsd, sys___get_tcb); +DECL_TEMPLATE(openbsd, sys_lkmnosys0); +DECL_TEMPLATE(openbsd, sys_lkmnosys1); +DECL_TEMPLATE(openbsd, sys_lkmnosys2); +DECL_TEMPLATE(openbsd, sys_lkmnosys3); +DECL_TEMPLATE(openbsd, sys_lkmnosys4); +DECL_TEMPLATE(openbsd, sys_lkmnosys5); +DECL_TEMPLATE(openbsd, sys_lkmnosys6); +DECL_TEMPLATE(openbsd, sys_lkmnosys7); +DECL_TEMPLATE(openbsd, sys_lkmnosys8); +DECL_TEMPLATE(openbsd, sys_thr_self); +DECL_TEMPLATE(openbsd, sys_thr_exit); +DECL_TEMPLATE(openbsd, sys_thr_set_name); +DECL_TEMPLATE(openbsd, sys_thr_kill); +DECL_TEMPLATE(openbsd, sys_thr_kill2); +DECL_TEMPLATE(openbsd, sys_thr_wake); +DECL_TEMPLATE(openbsd, sys__umtx_op); +DECL_TEMPLATE(openbsd, sys__umtx_lock); +DECL_TEMPLATE(openbsd, sys__umtx_unlock); +DECL_TEMPLATE(openbsd, sys_rtprio_thread); +DECL_TEMPLATE(openbsd, sys_sigpending); +DECL_TEMPLATE(openbsd, sys_fake_sigreturn); +#endif // __PRIV_SYSWRAP_OPENBSD_H + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_syswrap/priv_types_n_macros.h --- a/coregrind/m_syswrap/priv_types_n_macros.h Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_syswrap/priv_types_n_macros.h Thu Mar 31 15:57:55 2016 +0900 @@ -52,6 +52,7 @@ /* Arguments for a syscall. */ typedef struct SyscallArgs { + Word class; Word sysno; UWord arg1; UWord arg2; @@ -102,6 +103,24 @@ Int o_arg6; Int uu_arg7; Int uu_arg8; +# elif defined(VGP_x86_freebsd) || defined(VGP_x86_openbsd) + Int s_arg1; + Int s_arg2; + Int s_arg3; + Int s_arg4; + Int s_arg5; + Int s_arg6; + Int s_arg7; + Int s_arg8; +# elif defined(VGP_amd64_freebsd) || defined(VGP_amd64_openbsd) + Int o_arg1; + Int o_arg2; + Int o_arg3; + Int o_arg4; + Int o_arg5; + Int o_arg6; + Int s_arg7; + Int s_arg8; # elif defined(VGP_mips32_linux) Int o_arg1; Int o_arg2; @@ -194,7 +213,7 @@ extern SyscallTableEntry* ML_(get_linux_syscall_entry)( UInt sysno ); -#elif defined(VGO_darwin) +#elif defined(VGO_darwin) || defined(VGO_freebsd) || defined(VGO_openbsd) /* XXX: Darwin still uses the old scheme of exposing the table array(s) and size(s) directly to syswrap-main.c. This should be fixed. */ @@ -280,7 +299,8 @@ vgSysWrap_##auxstr##_##name##_after /* Add a generic wrapper to a syscall table. */ -#if defined(VGO_linux) +#if defined(VGO_linux) || \ + defined(VGO_freebsd) || defined(VGO_openbsd) # define GENX_(sysno, name) WRAPPER_ENTRY_X_(generic, sysno, name) # define GENXY(sysno, name) WRAPPER_ENTRY_XY(generic, sysno, name) #elif defined(VGO_darwin) @@ -295,6 +315,19 @@ #define LINX_(sysno, name) WRAPPER_ENTRY_X_(linux, sysno, name) #define LINXY(sysno, name) WRAPPER_ENTRY_XY(linux, sysno, name) +#if defined(VGO_freebsd) +/* Add a FreeBSD-specific, arch-independent wrapper to a syscall + table. */ +#define BSDX_(sysno, name) WRAPPER_ENTRY_X_(freebsd, sysno, name) +#define BSDXY(sysno, name) WRAPPER_ENTRY_XY(freebsd, sysno, name) + +#elif defined(VGO_openbsd) +/* Add a OpenBSD-specific, arch-independent wrapper to a syscall + table. */ +#define BSDX_(sysno, name) WRAPPER_ENTRY_X_(openbsd, sysno, name) +#define BSDXY(sysno, name) WRAPPER_ENTRY_XY(openbsd, sysno, name) + +#endif /* --------------------------------------------------------------------- Macros useful for writing wrappers concisely. These refer to the @@ -314,6 +347,7 @@ #define ARG6 (arrghs->arg6) #define ARG7 (arrghs->arg7) #define ARG8 (arrghs->arg8) +#define RETVAL2 (arrghs->retval2) /* Reference to the syscall's current result status/value. General paranoia all round. */ @@ -349,6 +383,21 @@ status->sres = VG_(mk_SysRes_Success)(zzz); \ } while (0) +#ifdef VGO_freebsd +#define SET_STATUS_Success2(zzz, zzz2) \ + do { status->what = SsComplete; \ + status->sres = VG_(mk_SysRes_amd64_freebsd)(zzz, zzz2, False); \ + } while (0) +#endif + +#ifdef VGO_openbsd +#define SET_STATUS_Success2(zzz, zzz2) \ + do { status->what = SsComplete; \ + status->sres = VG_(mk_SysRes_amd64_openbsd)(zzz, zzz2, False); \ + status->sres._hasVal2 = True; \ + } while (0) +#endif + #define SET_STATUS_Failure(zzz) \ do { Word wzz = (Word)(zzz); \ /* Catch out wildly bogus error values. */ \ @@ -400,6 +449,28 @@ # define PRA5(s,t,a) PRRAn(5,s,t,a) # define PRA6(s,t,a) PRRAn(6,s,t,a) +#elif defined(VGP_x86_freebsd) || defined(VGP_x86_openbsd) + /* Up to 8 parameters, all on the stack. */ +# define PRA1(s,t,a) PSRAn(1,s,t,a) +# define PRA2(s,t,a) PSRAn(2,s,t,a) +# define PRA3(s,t,a) PSRAn(3,s,t,a) +# define PRA4(s,t,a) PSRAn(4,s,t,a) +# define PRA5(s,t,a) PSRAn(5,s,t,a) +# define PRA6(s,t,a) PSRAn(6,s,t,a) +# define PRA7(s,t,a) PSRAn(7,s,t,a) +# define PRA8(s,t,a) PSRAn(8,s,t,a) + +#elif defined(VGP_amd64_freebsd) || defined(VGP_amd64_openbsd) + /* Up to 8 parameters, 6 in registers, 2 on the stack. */ +# define PRA1(s,t,a) PRRAn(1,s,t,a) +# define PRA2(s,t,a) PRRAn(2,s,t,a) +# define PRA3(s,t,a) PRRAn(3,s,t,a) +# define PRA4(s,t,a) PRRAn(4,s,t,a) +# define PRA5(s,t,a) PRRAn(5,s,t,a) +# define PRA6(s,t,a) PRRAn(6,s,t,a) +# define PRA7(s,t,a) PSRAn(7,s,t,a) +# define PRA8(s,t,a) PSRAn(8,s,t,a) + #elif defined(VGP_x86_darwin) /* Up to 8 parameters, all on the stack. */ # define PRA1(s,t,a) PSRAn(1,s,t,a) diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_syswrap/syscall-amd64-freebsd.S --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coregrind/m_syswrap/syscall-amd64-freebsd.S Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,203 @@ + +/*--------------------------------------------------------------------*/ +/*--- Support for doing system calls. syscall-amd64-freebsd.S ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2008 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#if defined(VGP_amd64_freebsd) + +#include "pub_core_basics_asm.h" +#include "pub_core_vkiscnums_asm.h" +#include "libvex_guest_offsets.h" + + +/*----------------------------------------------------------------*/ +/* + Perform a syscall for the client. This will run a syscall + with the client's specific per-thread signal mask. + + The structure of this function is such that, if the syscall is + interrupted by a signal, we can determine exactly what + execution state we were in with respect to the execution of + the syscall by examining the value of %eip in the signal + handler. This means that we can always do the appropriate + thing to precisely emulate the kernel's signal/syscall + interactions. + + The syscall number is taken from the argument, even though it + should also be in guest_state->guest_RAX. The syscall result + is written back to guest_state->guest_RAX on completion. + + Returns 0 if the syscall was successfully called (even if the + syscall itself failed), or a -ve error code if one of the + sigprocmasks failed (there's no way to determine which one + failed). + + VG_(fixup_guest_state_after_syscall_interrupted) does the + thread state fixup in the case where we were interrupted by a + signal. + + Prototype: + + Int ML_(do_syscall_for_client_WRK( + Int syscallno, // rdi + void* guest_state, // rsi + const vki_sigset_t *sysmask, // rdx + const vki_sigset_t *postmask, // rcx + Int sigsetSzB) // r8 +*/ + +/* from vki_arch.h */ +#define VKI_SIG_SETMASK 3 + +.globl ML_(do_syscall_for_client_WRK) +ML_(do_syscall_for_client_WRK): + /* save callee-saved regs */ + pushq %rbp + movq %rsp, %rbp + pushq %rdi // -8(%rbp) syscallno + pushq %rsi // -16(%rbp) guest_state + pushq %rdx // -24(%rbp) sysmask + pushq %rcx // -32(%rbp) postmask + pushq %r8 // -40(%rbp) sigsetSzB + +1: /* Even though we can't take a signal until the sigprocmask completes, + start the range early. + If eip is in the range [1,2), the syscall hasn't been started yet */ + + /* Set the signal mask which should be current during the syscall. */ + /* Save and restore all 5 arg regs round the call. This is easier + than figuring out the minimal set to save/restore. */ + + movq $__NR_sigprocmask, %rax // syscall # + movq $VKI_SIG_SETMASK, %rdi // how + movq %rdx, %rsi // sysmask + movq %rcx, %rdx // postmask + syscall + + jb 7f /* sigprocmask failed */ + + /* OK, that worked. Now do the syscall proper. */ + + /* 6 register parameters */ + movq -16(%rbp), %r11 /* r11 = VexGuestAMD64State * */ + movq OFFSET_amd64_RDI(%r11), %rdi + movq OFFSET_amd64_RSI(%r11), %rsi + movq OFFSET_amd64_RDX(%r11), %rdx + movq OFFSET_amd64_R10(%r11), %r10 + movq OFFSET_amd64_R8(%r11), %r8 + movq OFFSET_amd64_R9(%r11), %r9 + /* 2 stack parameters plus return address (ignored by syscall) */ + movq OFFSET_amd64_RSP(%r11), %r11 /* r11 = simulated RSP */ + movq 16(%r11), %rax + pushq %rax + movq 8(%r11), %rax + pushq %rax + /* (fake) return address. */ + movq 0(%r11), %rax + pushq %rax + /* syscallno */ + movq -8(%rbp), %rax + + /* If rip==2, then the syscall was either just about + to start, or was interrupted and the kernel was + restarting it. */ +2: syscall +3: /* In the range [3, 4), the syscall result is in %rax, + but hasn't been committed to RAX. */ + + /* stack contents: 3 words for syscall above, plus our prologue */ + setc 0(%rsp) /* stash returned carry flag */ + + movq -16(%rbp), %r11 /* r11 = VexGuestAMD64State * */ + movq %rax, OFFSET_amd64_RAX(%r11) /* save back to RAX */ + movq %rdx, OFFSET_amd64_RDX(%r11) /* save back to RDX */ + + /* save carry flag to VEX */ + xorq %rax, %rax + movb 0(%rsp), %al + movq %rax, %rdi /* arg1 = new flag */ + movq %r11, %rsi /* arg2 = vex state */ + addq $24, %rsp /* remove syscall parameters */ + call LibVEX_GuestAMD64_put_rflag_c + +4: /* Re-block signals. If eip is in [4,5), then the syscall + is complete and we needn't worry about it. */ + + movq $__NR_sigprocmask, %rax // syscall # + movq $VKI_SIG_SETMASK, %rdi // how + movq -32(%rbp), %rsi // postmask + xorq %rdx, %rdx // NULL + syscall + + jb 7f /* sigprocmask failed */ + +5: /* now safe from signals */ + + xorq %rax,%rax + movq -8(%rbp), %rdi + movq -16(%rbp), %rsi + movq -24(%rbp), %rdx + movq -32(%rbp), %rcx + movq -40(%rbp), %r8 + movq %rbp, %rsp + popq %rbp + ret + +7: /* failure: return 0x8000 | error code */ + orq $0x8000, %rax + movq -8(%rbp), %rdi + movq -16(%rbp), %rsi + movq -24(%rbp), %rdx + movq -32(%rbp), %rcx + movq -40(%rbp), %r8 + movq %rbp, %rsp + popq %rbp + ret + +.section .rodata +/* export the ranges so that + VG_(fixup_guest_state_after_syscall_interrupted) can do the + right thing */ + +.globl ML_(blksys_setup) +.globl ML_(blksys_restart) +.globl ML_(blksys_complete) +.globl ML_(blksys_committed) +.globl ML_(blksys_finished) +ML_(blksys_setup): .quad 1b +ML_(blksys_restart): .quad 2b +ML_(blksys_complete): .quad 3b +ML_(blksys_committed): .quad 4b +ML_(blksys_finished): .quad 5b +.previous + +#endif /* defined(VGP_amd64_freebsd) */ + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_syswrap/syscall-amd64-openbsd.S --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coregrind/m_syswrap/syscall-amd64-openbsd.S Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,210 @@ + +/*--------------------------------------------------------------------*/ +/*--- Support for doing system calls. syscall-amd64-freebsd.S ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2008 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#if defined(VGP_amd64_openbsd) + +#include "pub_core_basics_asm.h" +#include "pub_core_vkiscnums_asm.h" +#include "libvex_guest_offsets.h" + + +/*----------------------------------------------------------------*/ +/* + Perform a syscall for the client. This will run a syscall + with the client's specific per-thread signal mask. + + The structure of this function is such that, if the syscall is + interrupted by a signal, we can determine exactly what + execution state we were in with respect to the execution of + the syscall by examining the value of %eip in the signal + handler. This means that we can always do the appropriate + thing to precisely emulate the kernel's signal/syscall + interactions. + + The syscall number is taken from the argument, even though it + should also be in guest_state->guest_RAX. The syscall result + is written back to guest_state->guest_RAX on completion. + + Returns 0 if the syscall was successfully called (even if the + syscall itself failed), or a -ve error code if one of the + sigprocmasks failed (there's no way to determine which one + failed). + + VG_(fixup_guest_state_after_syscall_interrupted) does the + thread state fixup in the case where we were interrupted by a + signal. + + Prototype: + + Int ML_(do_syscall_for_client_WRK( + Int syscallno, // rdi + void* guest_state, // rsi + const vki_sigset_t *sysmask, // rdx + const vki_sigset_t *postmask, // rcx + Int sigsetSzB) // r8 +*/ + +/* from vki_arch.h */ +#define VKI_SIG_SETMASK 3 + +.globl ML_(do_syscall_for_client_WRK) +ML_(do_syscall_for_client_WRK): + /* save callee-saved regs */ + pushq %rbp + movq %rsp, %rbp + pushq %rdi // -8(%rbp) syscallno + pushq %rsi // -16(%rbp) guest_state + pushq %rdx // -24(%rbp) sysmask + pushq %rcx // -32(%rbp) postmask + pushq %r8 // -40(%rbp) sigsetSzB + +1: /* Even though we can't take a signal until the sigprocmask completes, + start the range early. + If eip is in the range [1,2), the syscall hasn't been started yet */ + + /* Set the signal mask which should be current during the syscall. */ + /* Save and restore all 5 arg regs round the call. This is easier + than figuring out the minimal set to save/restore. */ + + movq $__NR_sigprocmask, %rax // syscall # + movq $VKI_SIG_SETMASK, %rdi // how + movq (%rdx), %rsi // sysmask + syscall + + jb 7f /* sigprocmask failed */ + + movq -32(%rbp), %rdx + testq %rdx, %rdx + jz 10f + movl %eax, (%rdx) // postmask +10: + + /* OK, that worked. Now do the syscall proper. */ + + /* 6 register parameters */ + movq -16(%rbp), %r11 /* r11 = VexGuestAMD64State * */ + movq OFFSET_amd64_RDI(%r11), %rdi + movq OFFSET_amd64_RSI(%r11), %rsi + movq OFFSET_amd64_RDX(%r11), %rdx + movq OFFSET_amd64_R10(%r11), %r10 + movq OFFSET_amd64_R8(%r11), %r8 + movq OFFSET_amd64_R9(%r11), %r9 + /* 2 stack parameters plus return address (ignored by syscall) */ + movq OFFSET_amd64_RSP(%r11), %r11 /* r11 = simulated RSP */ + movq 16(%r11), %rax + pushq %rax + movq 8(%r11), %rax + pushq %rax + /* (fake) return address. */ + movq 0(%r11), %rax + pushq %rax + /* syscallno */ + movq -8(%rbp), %rax + + /* If rip==2, then the syscall was either just about + to start, or was interrupted and the kernel was + restarting it. */ +2: syscall +3: /* In the range [3, 4), the syscall result is in %rax, + but hasn't been committed to RAX. */ + + /* stack contents: 3 words for syscall above, plus our prologue */ + setc 0(%rsp) /* stash returned carry flag */ + + movq -16(%rbp), %r11 /* r11 = VexGuestAMD64State * */ + movq %rax, OFFSET_amd64_RAX(%r11) /* save back to RAX */ + movq %rdx, OFFSET_amd64_RDX(%r11) /* save back to RDX */ + + /* save carry flag to VEX */ + xorq %rax, %rax + movb 0(%rsp), %al + movq %rax, %rdi /* arg1 = new flag */ + movq %r11, %rsi /* arg2 = vex state */ + addq $24, %rsp /* remove syscall parameters */ + call LibVEX_GuestAMD64_put_rflag_c + +4: /* Re-block signals. If eip is in [4,5), then the syscall + is complete and we needn't worry about it. */ + + movq $__NR_sigprocmask, %rax // syscall # + movq $VKI_SIG_SETMASK, %rdi // how + movq -32(%rbp), %rsi // postmask + movl (%rsi), %esi + syscall + + jb 7f /* sigprocmask failed */ + + /* don't bother oldmask */ + +5: /* now safe from signals */ + + xorq %rax,%rax + movq -8(%rbp), %rdi + movq -16(%rbp), %rsi + movq -24(%rbp), %rdx + movq -32(%rbp), %rcx + movq -40(%rbp), %r8 + movq %rbp, %rsp + popq %rbp + ret + +7: /* failure: return 0x8000 | error code */ + orq $0x8000, %rax + movq -8(%rbp), %rdi + movq -16(%rbp), %rsi + movq -24(%rbp), %rdx + movq -32(%rbp), %rcx + movq -40(%rbp), %r8 + movq %rbp, %rsp + popq %rbp + ret + +.section .rodata +/* export the ranges so that + VG_(fixup_guest_state_after_syscall_interrupted) can do the + right thing */ + +.globl ML_(blksys_setup) +.globl ML_(blksys_restart) +.globl ML_(blksys_complete) +.globl ML_(blksys_committed) +.globl ML_(blksys_finished) +ML_(blksys_setup): .quad 1b +ML_(blksys_restart): .quad 2b +ML_(blksys_complete): .quad 3b +ML_(blksys_committed): .quad 4b +ML_(blksys_finished): .quad 5b +.previous + +#endif /* defined(VGP_amd64_openbsd) */ + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_syswrap/syscall-x86-freebsd.S --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coregrind/m_syswrap/syscall-x86-freebsd.S Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,197 @@ + +/*--------------------------------------------------------------------*/ +/*--- Support for doing system calls. syscall-x86-freebsd.S ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2007 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#if defined(VGP_x86_freebsd) + +#include "pub_core_basics_asm.h" +#include "pub_core_vkiscnums_asm.h" +#include "libvex_guest_offsets.h" + + +/*----------------------------------------------------------------*/ +/* + Perform a syscall for the client. This will run a syscall + with the client's specific per-thread signal mask. + + The structure of this function is such that, if the syscall is + interrupted by a signal, we can determine exactly what + execution state we were in with respect to the execution of + the syscall by examining the value of %eip in the signal + handler. This means that we can always do the appropriate + thing to precisely emulate the kernel's signal/syscall + interactions. + + The syscall number is taken from the argument, even though it + should also be in regs->m_eax. The syscall result is written + back to regs->m_eax on completion. + + Returns 0 if the syscall was successfully called (even if the + syscall itself failed), or a -ve error code if one of the + sigprocmasks failed (there's no way to determine which one + failed). + + VG_(fixup_guest_state_after_syscall_interrupted) does the + thread state fixup in the case where we were interrupted by a + signal. + + Prototype: + + Int ML_(do_syscall_for_client_WRK)( + Int syscallno, // ebp+8 + void* guest_state, // ebp+12 + const vki_sigset_t *sysmask, // ebp+16 + const vki_sigset_t *postmask, // ebp+20 + Int sigsetSzB) // ebp+24 + + Note that sigsetSzB is totally ignored (and irrelevant). +*/ + +/* from vki-darwin.h, checked at startup by m_vki.c */ +#define VKI_SIG_SETMASK 3 + +.globl ML_(do_syscall_for_client_WRK) +ML_(do_syscall_for_client_WRK): + /* establish stack frame */ + push %ebp + mov %esp, %ebp + subl $8, %esp /* 16-byte align stack */ + +1: /* Even though we can't take a signal until the + sigprocmask completes, start the range early. + If eip is in the range [1,2), the syscall hasn't been started yet */ + + /* Set the signal mask which should be current during the syscall. */ + pushl 20(%ebp) + pushl 16(%ebp) + pushl $VKI_SIG_SETMASK + pushl $0xcafebabe /* totally fake return address */ + movl $__NR_sigprocmask, %eax + int $0x80 + jc 7f /* sigprocmask failed */ + addl $16,%esp + + /* Copy syscall parameters to the stack - assume no more than 8 + * plus the return address */ + /* do_syscall8 */ + /* stack is currently aligned assuming 8 parameters */ + movl 12(%ebp), %edx + movl OFFSET_x86_ESP(%edx), %edx /* edx = simulated ESP */ + movl 28+4(%edx), %eax + pushl %eax + movl 24+4(%edx), %eax + pushl %eax + movl 20+4(%edx), %eax + pushl %eax + movl 16+4(%edx), %eax + pushl %eax + movl 12+4(%edx), %eax + pushl %eax + movl 8+4(%edx), %eax + pushl %eax + movl 4+4(%edx), %eax + pushl %eax + movl 0+4(%edx), %eax + pushl %eax + /* return address */ + movl 0(%edx), %eax + pushl %eax + + /* Put syscall number in eax */ + movl 8(%ebp), %eax + + /* If eip==2, then the syscall was either just about to start, + or was interrupted and the kernel was restarting it. */ +2: int $0x80 /* UNIX (GrP fixme should be sysenter?) */ + +3: /* In the range [3, 4), the syscall result is in %eax and %edx and C, + but hasn't been committed to the thread state. */ + setc 0(%esp) /* stash returned carry flag */ + movl 12(%ebp), %ecx + movl %eax, OFFSET_x86_EAX(%ecx) /* save EAX to vex */ + movl %edx, OFFSET_x86_EDX(%ecx) /* save EDX to vex */ + /* save carry flag to vex */ + subl $12, %esp + movl %ecx, 4(%esp) + movl $0, 0(%esp) + movb 12(%esp), %al + movb %al, 0(%esp) + call LibVEX_GuestX86_put_eflag_c + addl $12, %esp + +4: /* Re-block signals. If eip is in [4,5), then the syscall is + complete and we needn't worry about it. */ + /* Set up for __pthread_sigmask(SIG_SETMASK, postmask, NULL) */ + pushl $0 + pushl 20(%ebp) + pushl $VKI_SIG_SETMASK + pushl $0xcafef00d /* totally fake return address */ + movl $__NR_sigprocmask, %eax + int $0x80 /* should be sysenter? */ + jc 7f /* sigprocmask failed */ + addl $16,%esp + +5: /* now safe from signals */ + movl $0, %eax /* SUCCESS */ + movl %ebp, %esp + popl %ebp + ret + +7: /* failure: return 0x8000 | error code */ + /* Note that we enter here with %esp being 16 too low + (4 extra words on the stack). But because we're nuking + the stack frame now, that doesn't matter. */ + andl $0x7FFF, %eax + orl $0x8000, %eax + movl %ebp, %esp + popl %ebp + ret + +.section .rodata +/* export the ranges so that + VG_(fixup_guest_state_after_syscall_interrupted) can do the + right thing */ + +.globl ML_(blksys_setup) +.globl ML_(blksys_restart) +.globl ML_(blksys_complete) +.globl ML_(blksys_committed) +.globl ML_(blksys_finished) +ML_(blksys_setup): .long 1b +ML_(blksys_restart): .long 2b +ML_(blksys_complete): .long 3b +ML_(blksys_committed): .long 4b +ML_(blksys_finished): .long 5b +.previous + +#endif // defined(VGP_x86_freebsd) + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_syswrap/syscall-x86-openbsd.S --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coregrind/m_syswrap/syscall-x86-openbsd.S Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,197 @@ + +/*--------------------------------------------------------------------*/ +/*--- Support for doing system calls. syscall-x86-freebsd.S ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2007 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#if defined(VGP_x86_openbsd) + +#include "pub_core_basics_asm.h" +#include "pub_core_vkiscnums_asm.h" +#include "libvex_guest_offsets.h" + + +/*----------------------------------------------------------------*/ +/* + Perform a syscall for the client. This will run a syscall + with the client's specific per-thread signal mask. + + The structure of this function is such that, if the syscall is + interrupted by a signal, we can determine exactly what + execution state we were in with respect to the execution of + the syscall by examining the value of %eip in the signal + handler. This means that we can always do the appropriate + thing to precisely emulate the kernel's signal/syscall + interactions. + + The syscall number is taken from the argument, even though it + should also be in regs->m_eax. The syscall result is written + back to regs->m_eax on completion. + + Returns 0 if the syscall was successfully called (even if the + syscall itself failed), or a -ve error code if one of the + sigprocmasks failed (there's no way to determine which one + failed). + + VG_(fixup_guest_state_after_syscall_interrupted) does the + thread state fixup in the case where we were interrupted by a + signal. + + Prototype: + + Int ML_(do_syscall_for_client_WRK)( + Int syscallno, // ebp+8 + void* guest_state, // ebp+12 + const vki_sigset_t *sysmask, // ebp+16 + const vki_sigset_t *postmask, // ebp+20 + Int sigsetSzB) // ebp+24 + + Note that sigsetSzB is totally ignored (and irrelevant). +*/ + +/* from vki-darwin.h, checked at startup by m_vki.c */ +#define VKI_SIG_SETMASK 3 + +.globl ML_(do_syscall_for_client_WRK) +ML_(do_syscall_for_client_WRK): + /* establish stack frame */ + push %ebp + mov %esp, %ebp + subl $8, %esp /* 16-byte align stack */ + +1: /* Even though we can't take a signal until the + sigprocmask completes, start the range early. + If eip is in the range [1,2), the syscall hasn't been started yet */ + + /* Set the signal mask which should be current during the syscall. */ + pushl 20(%ebp) + pushl 16(%ebp) + pushl $VKI_SIG_SETMASK + pushl $0xcafebabe /* totally fake return address */ + movl $__NR_sigprocmask, %eax + int $0x80 + jc 7f /* sigprocmask failed */ + addl $16,%esp + + /* Copy syscall parameters to the stack - assume no more than 8 + * plus the return address */ + /* do_syscall8 */ + /* stack is currently aligned assuming 8 parameters */ + movl 12(%ebp), %edx + movl OFFSET_x86_ESP(%edx), %edx /* edx = simulated ESP */ + movl 28+4(%edx), %eax + pushl %eax + movl 24+4(%edx), %eax + pushl %eax + movl 20+4(%edx), %eax + pushl %eax + movl 16+4(%edx), %eax + pushl %eax + movl 12+4(%edx), %eax + pushl %eax + movl 8+4(%edx), %eax + pushl %eax + movl 4+4(%edx), %eax + pushl %eax + movl 0+4(%edx), %eax + pushl %eax + /* return address */ + movl 0(%edx), %eax + pushl %eax + + /* Put syscall number in eax */ + movl 8(%ebp), %eax + + /* If eip==2, then the syscall was either just about to start, + or was interrupted and the kernel was restarting it. */ +2: int $0x80 /* UNIX (GrP fixme should be sysenter?) */ + +3: /* In the range [3, 4), the syscall result is in %eax and %edx and C, + but hasn't been committed to the thread state. */ + setc 0(%esp) /* stash returned carry flag */ + movl 12(%ebp), %ecx + movl %eax, OFFSET_x86_EAX(%ecx) /* save EAX to vex */ + movl %edx, OFFSET_x86_EDX(%ecx) /* save EDX to vex */ + /* save carry flag to vex */ + subl $12, %esp + movl %ecx, 4(%esp) + movl $0, 0(%esp) + movb 12(%esp), %al + movb %al, 0(%esp) + call LibVEX_GuestX86_put_eflag_c + addl $12, %esp + +4: /* Re-block signals. If eip is in [4,5), then the syscall is + complete and we needn't worry about it. */ + /* Set up for __pthread_sigmask(SIG_SETMASK, postmask, NULL) */ + pushl $0 + pushl 20(%ebp) + pushl $VKI_SIG_SETMASK + pushl $0xcafef00d /* totally fake return address */ + movl $__NR_sigprocmask, %eax + int $0x80 /* should be sysenter? */ + jc 7f /* sigprocmask failed */ + addl $16,%esp + +5: /* now safe from signals */ + movl $0, %eax /* SUCCESS */ + movl %ebp, %esp + popl %ebp + ret + +7: /* failure: return 0x8000 | error code */ + /* Note that we enter here with %esp being 16 too low + (4 extra words on the stack). But because we're nuking + the stack frame now, that doesn't matter. */ + andl $0x7FFF, %eax + orl $0x8000, %eax + movl %ebp, %esp + popl %ebp + ret + +.section .rodata +/* export the ranges so that + VG_(fixup_guest_state_after_syscall_interrupted) can do the + right thing */ + +.globl ML_(blksys_setup) +.globl ML_(blksys_restart) +.globl ML_(blksys_complete) +.globl ML_(blksys_committed) +.globl ML_(blksys_finished) +ML_(blksys_setup): .long 1b +ML_(blksys_restart): .long 2b +ML_(blksys_complete): .long 3b +ML_(blksys_committed): .long 4b +ML_(blksys_finished): .long 5b +.previous + +#endif // defined(VGP_x86_openbsd) + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_syswrap/syswrap-amd64-freebsd.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coregrind/m_syswrap/syswrap-amd64-freebsd.c Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,708 @@ + +/*--------------------------------------------------------------------*/ +/*--- Platform-specific syscalls stuff. syswrap-amd64-freebsd.c ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2005 Nicholas Nethercote + njn@valgrind.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#if defined(VGP_amd64_freebsd) + +#include "pub_core_basics.h" +#include "pub_core_vki.h" +#include "pub_core_vkiscnums.h" +#include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy +#include "pub_core_threadstate.h" +#include "pub_core_aspacemgr.h" +#include "pub_core_debuglog.h" +#include "pub_core_libcbase.h" +#include "pub_core_libcassert.h" +#include "pub_core_libcprint.h" +#include "pub_core_libcproc.h" +#include "pub_core_libcsignal.h" +#include "pub_core_machine.h" +#include "pub_core_options.h" +#include "pub_core_scheduler.h" +#include "pub_core_sigframe.h" +#include "pub_core_signals.h" +#include "pub_core_syscall.h" +#include "pub_core_syswrap.h" +#include "pub_core_tooliface.h" +#include "pub_core_stacks.h" // VG_(register_stack) + +#include "priv_types_n_macros.h" +#include "priv_syswrap-generic.h" /* for decls of generic wrappers */ +#include "priv_syswrap-freebsd.h" /* for decls of freebsd-ish wrappers */ +#include "priv_syswrap-main.h" + +/* --------------------------------------------------------------------- + clone() handling + ------------------------------------------------------------------ */ + +/* 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. */ +__attribute__((noreturn)) +void ML_(call_on_new_stack_0_1) ( Addr stack, + Addr retaddr, + void (*f)(Word), + Word arg1 ); +// %rdi == stack +// %rsi == retaddr +// %rdx == f +// %rcx == arg1 +asm( +".text\n" +".globl vgModuleLocal_call_on_new_stack_0_1\n" +"vgModuleLocal_call_on_new_stack_0_1:\n" +" movq %rdi, %rsp\n" // set stack +" pushq %rsi\n" // retaddr to stack +" pushq %rdx\n" // f to stack +" pushq %rcx\n" // arg1 to stack +" movq $0, %rax\n" // zero all GP regs +" movq $0, %rbx\n" +" movq $0, %rcx\n" +" movq $0, %rdx\n" +" movq $0, %rsi\n" +" movq $0, %rdi\n" +" movq $0, %rbp\n" +" movq $0, %r8\n" +" movq $0, %r9\n" +" movq $0, %r10\n" +" movq $0, %r11\n" +" movq $0, %r12\n" +" movq $0, %r13\n" +" movq $0, %r14\n" +" movq $0, %r15\n" +" popq %rdi\n" // arg1 to correct arg reg +" ret\n" // jump to f +" ud2\n" // should never get here +".previous\n" +); + + +/* --------------------------------------------------------------------- + More thread stuff + ------------------------------------------------------------------ */ + +void VG_(cleanup_thread) ( ThreadArchState *arch ) +{ +} + +/* --------------------------------------------------------------------- + PRE/POST wrappers for amd64/FreeBSD-specific syscalls + ------------------------------------------------------------------ */ + +#define PRE(name) DEFN_PRE_TEMPLATE(freebsd, name) +#define POST(name) DEFN_POST_TEMPLATE(freebsd, name) + +PRE(sys_thr_new) +{ + static const Bool debug = False; + + ThreadId ctid = VG_(alloc_ThreadState)(); + ThreadState* ptst = VG_(get_ThreadState)(tid); + ThreadState* ctst = VG_(get_ThreadState)(ctid); + SysRes res; + vki_sigset_t blockall, savedmask; + struct vki_thr_param tp; + Addr stk; + + PRINT("thr_new ( %#lx, %ld )",ARG1,ARG2); + PRE_REG_READ2(int, "thr_new", + struct thr_param *, param, + int, param_size); + + PRE_MEM_READ( "thr_new(param)", ARG1, offsetof(struct vki_thr_param, spare)); + if (!ML_(safe_to_deref)( (void*)ARG1, offsetof(struct vki_thr_param, spare))) { + SET_STATUS_Failure( VKI_EFAULT ); + return; + } + VG_(memset)(&tp, 0, sizeof(tp)); + VG_(memcpy)(&tp, (void *)ARG1, offsetof(struct vki_thr_param, spare)); + 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); + + vg_assert(VG_(is_running_thread)(tid)); + vg_assert(VG_(is_valid_tid)(ctid)); + + /* Copy register state + + On linux, both parent and child return to the same place, and the code + following the clone syscall works out which is which, so we + don't need to worry about it. + On FreeBSD, thr_new arranges a direct call. We don't actually need any + of this gunk. + + The parent gets the child's new tid returned from clone, but the + child gets 0. + + If the clone call specifies a NULL rsp for the new thread, then + it actually gets a copy of the parent's rsp. + */ + /* We inherit our parent's guest state. */ + ctst->arch.vex = ptst->arch.vex; + ctst->arch.vex_shadow1 = ptst->arch.vex_shadow1; + ctst->arch.vex_shadow2 = ptst->arch.vex_shadow2; + + /* Make thr_new appear to have returned Success(0) in the + child. */ + ctst->arch.vex.guest_RAX = 0; + ctst->arch.vex.guest_RDX = 0; + LibVEX_GuestAMD64_put_rflag_c(0, &ctst->arch.vex); + + ctst->os_state.parent = tid; + + /* inherit signal mask */ + ctst->sig_mask = ptst->sig_mask; + ctst->tmp_sig_mask = ptst->sig_mask; + + /* Linux has to guess, we don't */ + ctst->client_stack_highest_word = (Addr)tp.stack_base + tp.stack_size; + ctst->client_stack_szB = tp.stack_size; + VG_(register_stack)((Addr)tp.stack_base, (Addr)tp.stack_base + tp.stack_size); + + /* 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 ); + + if (debug) + VG_(printf)("clone child has SETTLS: tls at %#lx\n", (Addr)tp.tls_base); + ctst->arch.vex.guest_FS_ZERO = (UWord)tp.tls_base; + tp.tls_base = 0; /* Don't have the kernel do it too */ + + /* start the thread with everything blocked */ + VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask); + + /* 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; + + /* But this is for thr_new() to run valgrind's trampoline */ + tp.start_func = (void *)ML_(start_thread_NORETURN); + tp.arg = &VG_(threads)[ctid]; + + /* 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; + + /* Create the new thread */ + res = VG_(do_syscall2)(__NR_thr_new, (UWord)&tp, sizeof(tp)); + + VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL); + +fail: + if (sr_isError(res)) { + /* thr_new failed */ + VG_(cleanup_thread)(&ctst->arch); + ctst->status = VgTs_Empty; + /* oops. Better tell the tool the thread exited in a hurry :-) */ + VG_TRACK( pre_thread_ll_exit, ctid ); + } else { + + POST_MEM_WRITE((Addr)tp.parent_tid, sizeof(long)); + POST_MEM_WRITE((Addr)tp.child_tid, sizeof(long)); + + /* Thread creation was successful; let the child have the chance + to run */ + *flags |= SfYieldAfter; + } + + /* "Complete" the syscall so that the wrapper doesn't call the kernel again. */ + SET_STATUS_from_SysRes(res); +} + +PRE(sys_rfork) +{ + PRINT("sys_rfork ( %#lx )", ARG1 ); + PRE_REG_READ1(long, "rfork", int, flags); + + VG_(message)(Vg_UserMsg, "rfork() not implemented"); + VG_(unimplemented)("Valgrind does not support rfork()."); + + SET_STATUS_Failure(VKI_ENOSYS); +} + +PRE(sys_sigreturn) +{ + PRINT("sys_sigreturn ( %#lx )", ARG1); + PRE_REG_READ1(long, "sigreturn", + struct vki_ucontext *, ucp); + + PRE_MEM_READ( "sigreturn(ucp)", ARG1, sizeof(struct vki_ucontext) ); + PRE_MEM_WRITE( "sigreturn(ucp)", ARG1, sizeof(struct vki_ucontext) ); +} + +PRE(sys_fake_sigreturn) +{ + ThreadState* tst; + struct vki_ucontext *uc; + int rflags; + + PRINT("sys_sigreturn ( %#lx )", ARG1); + PRE_REG_READ1(long, "sigreturn", + struct vki_ucontext *, ucp); + + PRE_MEM_READ( "sigreturn(ucp)", ARG1, sizeof(struct vki_ucontext) ); + PRE_MEM_WRITE( "sigreturn(ucp)", ARG1, sizeof(struct vki_ucontext) ); + + 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_RSP -= sizeof(Addr); + + uc = (struct vki_ucontext *)ARG1; + if (uc == NULL || uc->uc_mcontext.len != sizeof(uc->uc_mcontext)) { + SET_STATUS_Failure(VKI_EINVAL); + return; + } + + /* 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); + + /* 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). */ + 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) ); + + /* + * Signal handler might have changed the signal mask. Respect that. + */ + tst->sig_mask = uc->uc_sigmask; + tst->tmp_sig_mask = uc->uc_sigmask; + + /* 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); + + /* Check to see if some any signals arose as a result of this. */ + *flags |= SfPollAfter; +} + +static void restore_mcontext(ThreadState *tst, struct vki_mcontext *sc) +{ + tst->arch.vex.guest_RAX = sc->rax; + tst->arch.vex.guest_RCX = sc->rcx; + tst->arch.vex.guest_RDX = sc->rdx; + tst->arch.vex.guest_RBX = sc->rbx; + tst->arch.vex.guest_RBP = sc->rbp; + tst->arch.vex.guest_RSP = sc->rsp; + tst->arch.vex.guest_RSI = sc->rsi; + tst->arch.vex.guest_RDI = sc->rdi; + tst->arch.vex.guest_R8 = sc->r8; + tst->arch.vex.guest_R9 = sc->r9; + tst->arch.vex.guest_R10 = sc->r10; + tst->arch.vex.guest_R11 = sc->r11; + tst->arch.vex.guest_R12 = sc->r12; + 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_RIP = sc->rip; + /* + * XXX: missing support for other flags. + */ + if (sc->rflags & 0x0001) + LibVEX_GuestAMD64_put_rflag_c(1, &tst->arch.vex); + else + LibVEX_GuestAMD64_put_rflag_c(0, &tst->arch.vex); +} + +static void fill_mcontext(ThreadState *tst, struct vki_mcontext *sc) +{ + sc->rax = tst->arch.vex.guest_RAX; + sc->rcx = tst->arch.vex.guest_RCX; + sc->rdx = tst->arch.vex.guest_RDX; + sc->rbx = tst->arch.vex.guest_RBX; + sc->rbp = tst->arch.vex.guest_RBP; + sc->rsp = tst->arch.vex.guest_RSP; + sc->rsi = tst->arch.vex.guest_RSI; + sc->rdi = tst->arch.vex.guest_RDI; + sc->r8 = tst->arch.vex.guest_R8; + sc->r9 = tst->arch.vex.guest_R9; + sc->r10 = tst->arch.vex.guest_R10; + sc->r11 = tst->arch.vex.guest_R11; + sc->r12 = tst->arch.vex.guest_R12; + sc->r13 = tst->arch.vex.guest_R13; + sc->r14 = tst->arch.vex.guest_R14; + sc->r15 = tst->arch.vex.guest_R15; + sc->rip = tst->arch.vex.guest_RIP; +/* + Not supported by VEX. + sc->cs = tst->arch.vex.guest_CS; + sc->ss = tst->arch.vex.guest_SS; + sc->ds = tst->arch.vex.guest_DS; + sc->es = tst->arch.vex.guest_ES; + sc->fs = tst->arch.vex.guest_FS; + sc->gs = tst->arch.vex.guest_GS; +*/ + sc->rflags = LibVEX_GuestAMD64_get_rflags(&tst->arch.vex); +/* + not yet. + VG_(memcpy)(&sc->fpstate, fpstate, sizeof(*fpstate)); +*/ + sc->fpformat = VKI_FPFMT_NODEV; + sc->ownedfp = VKI_FPOWNED_NONE; + sc->len = sizeof(*sc); + VG_(memset)(sc->spare2, 0, sizeof(sc->spare2)); +} + +PRE(sys_getcontext) +{ + ThreadState* tst; + struct vki_ucontext *uc; + + PRINT("sys_getcontext ( %#lx )", ARG1); + PRE_REG_READ1(long, "getcontext", + struct vki_ucontext *, ucp); + PRE_MEM_WRITE( "getcontext(ucp)", ARG1, sizeof(struct vki_ucontext) ); + uc = (struct vki_ucontext *)ARG1; + if (uc == NULL) { + SET_STATUS_Failure(VKI_EINVAL); + return; + } + tst = VG_(get_ThreadState)(tid); + fill_mcontext(tst, &uc->uc_mcontext); + uc->uc_mcontext.rax = 0; + uc->uc_mcontext.rdx = 0; + uc->uc_mcontext.rflags &= ~0x0001; /* PSL_C */ + uc->uc_sigmask = tst->sig_mask; + VG_(memset)(uc->__spare__, 0, sizeof(uc->__spare__)); + SET_STATUS_Success(0); +} + +PRE(sys_setcontext) +{ + ThreadState* tst; + struct vki_ucontext *uc; + + PRINT("sys_setcontext ( %#lx )", ARG1); + PRE_REG_READ1(long, "setcontext", + struct vki_ucontext *, ucp); + + PRE_MEM_READ( "setcontext(ucp)", ARG1, sizeof(struct vki_ucontext) ); + PRE_MEM_WRITE( "setcontext(ucp)", ARG1, sizeof(struct vki_ucontext) ); + + vg_assert(VG_(is_valid_tid)(tid)); + vg_assert(tid >= 1 && tid < VG_N_THREADS); + vg_assert(VG_(is_running_thread)(tid)); + + tst = VG_(get_ThreadState)(tid); + uc = (struct vki_ucontext *)ARG1; + if (uc == NULL || uc->uc_mcontext.len != sizeof(uc->uc_mcontext)) { + SET_STATUS_Failure(VKI_EINVAL); + return; + } + + restore_mcontext(tst, &uc->uc_mcontext); + tst->sig_mask = uc->uc_sigmask; + + /* 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); + + /* Check to see if some any signals arose as a result of this. */ + *flags |= SfPollAfter; +} + +PRE(sys_swapcontext) +{ + struct vki_ucontext *ucp, *oucp; + ThreadState* tst; + + PRINT("sys_swapcontext ( %#lx, %#lx )", ARG1, ARG2); + PRE_REG_READ2(long, "swapcontext", + struct vki_ucontext *, oucp, struct vki_ucontext *, ucp); + + PRE_MEM_READ( "swapcontext(ucp)", ARG2, sizeof(struct vki_ucontext) ); + PRE_MEM_WRITE( "swapcontext(oucp)", ARG1, sizeof(struct vki_ucontext) ); + + oucp = (struct vki_ucontext *)ARG1; + ucp = (struct vki_ucontext *)ARG2; + if (oucp == NULL || ucp == NULL || ucp->uc_mcontext.len != sizeof(ucp->uc_mcontext)) { + SET_STATUS_Failure(VKI_EINVAL); + return; + } + tst = VG_(get_ThreadState)(tid); + + /* + * Save the context. + */ + fill_mcontext(tst, &oucp->uc_mcontext); + oucp->uc_mcontext.rax = 0; + oucp->uc_mcontext.rdx = 0; + oucp->uc_mcontext.rflags &= ~0x0001; /* PSL_C */ + oucp->uc_sigmask = tst->sig_mask; + VG_(memset)(oucp->__spare__, 0, sizeof(oucp->__spare__)); + + /* + * Switch to new one. + */ + restore_mcontext(tst, &ucp->uc_mcontext); + tst->sig_mask = ucp->uc_sigmask; + + /* 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); + + /* Check to see if some any signals arose as a result of this. */ + *flags |= SfPollAfter; +} + + +/* This is here because on x86 the off_t is passed in 2 regs. Don't ask about pad. */ + +/* caddr_t mmap(caddr_t addr, size_t len, int prot, int flags, int fd, int pad, off_t pos); */ +/* ARG1 ARG2 ARG3 ARG4 ARG5 ARG6 ARG7 */ + +PRE(sys_mmap) +{ + SysRes r; + + PRINT("sys_mmap ( %#lx, %lu, %ld, %ld, %ld, pad%ld, 0x%lx)", + ARG1, (UWord)ARG2, ARG3, ARG4, ARG5, ARG6, ARG7 ); + PRE_REG_READ7(long, "mmap", + char *, addr, unsigned long, len, int, prot, int, flags, + int, fd, int, pad, unsigned long, pos); + + r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG7 ); + SET_STATUS_from_SysRes(r); +} + +/* FreeBSD-7 introduces a "regular" version of mmap etc. */ +PRE(sys_mmap7) +{ + SysRes r; + + PRINT("sys_mmap ( %#lx, %lu, %ld, %ld, %ld, 0x%lx)", + ARG1, (UWord)ARG2, ARG3, ARG4, ARG5, ARG6 ); + PRE_REG_READ6(long, "mmap", + char *, addr, unsigned long, len, int, prot, int, flags, + int, fd, unsigned long, pos); + + r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 ); + SET_STATUS_from_SysRes(r); +} + +PRE(sys_lseek) +{ + PRINT("sys_lseek ( %ld, 0x%lx, %#lx, %ld )", ARG1,ARG2,ARG3,ARG4); + PRE_REG_READ4(long, "lseek", + unsigned int, fd, int, pad, unsigned long, offset, + unsigned int, whence); +} + +PRE(sys_lseek7) +{ + PRINT("sys_lseek ( %ld, 0x%lx, %ld )", ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "lseek", + unsigned int, fd, unsigned long, offset, + unsigned int, whence); +} + +PRE(sys_pread) +{ + *flags |= SfMayBlock; + PRINT("sys_read ( %ld, %#lx, %lu, %lu, %lu )", ARG1, ARG2, ARG3, ARG4, ARG5); + PRE_REG_READ5(ssize_t, "read", + unsigned int, fd, char *, buf, vki_size_t, count, + int, pad, unsigned long, off); + + if (!ML_(fd_allowed)(ARG1, "read", tid, False)) + SET_STATUS_Failure( VKI_EBADF ); + else + PRE_MEM_WRITE( "read(buf)", ARG2, ARG3 ); +} + +POST(sys_pread) +{ + vg_assert(SUCCESS); + POST_MEM_WRITE( ARG2, RES ); +} + +PRE(sys_pread7) +{ + *flags |= SfMayBlock; + PRINT("sys_read ( %ld, %#lx, %lu, %lu )", ARG1, ARG2, ARG3, ARG4); + PRE_REG_READ4(ssize_t, "read", + unsigned int, fd, char *, buf, vki_size_t, count, + unsigned long, off); + + if (!ML_(fd_allowed)(ARG1, "read", tid, False)) + SET_STATUS_Failure( VKI_EBADF ); + else + PRE_MEM_WRITE( "read(buf)", ARG2, ARG3 ); +} + +POST(sys_pread7) +{ + vg_assert(SUCCESS); + POST_MEM_WRITE( ARG2, RES ); +} + +PRE(sys_pwrite) +{ + Bool ok; + *flags |= SfMayBlock; + PRINT("sys_write ( %ld, %#lx, %lu, %lu, %lu )", ARG1, ARG2, ARG3, ARG4, ARG5); + PRE_REG_READ5(ssize_t, "write", + unsigned int, fd, const char *, buf, vki_size_t, count, + int, pad, unsigned long, off); + /* check to see if it is allowed. If not, try for an exemption from + --sim-hints=enable-outer (used for self hosting). */ + ok = ML_(fd_allowed)(ARG1, "write", tid, False); + if (!ok && ARG1 == 2/*stderr*/ + && SimHintiS(SimHint_enable_outer, VG_(clo_sim_hints))) + ok = True; + if (!ok) + SET_STATUS_Failure( VKI_EBADF ); + else + PRE_MEM_READ( "write(buf)", ARG2, ARG3 ); +} + +PRE(sys_pwrite7) +{ + Bool ok; + *flags |= SfMayBlock; + PRINT("sys_write ( %ld, %#lx, %lu, %lu )", ARG1, ARG2, ARG3, ARG4); + PRE_REG_READ4(ssize_t, "write", + unsigned int, fd, const char *, buf, vki_size_t, count, + unsigned long, off); + /* check to see if it is allowed. If not, try for an exemption from + --sim-hints=enable-outer (used for self hosting). */ + ok = ML_(fd_allowed)(ARG1, "write", tid, False); + if (!ok && ARG1 == 2/*stderr*/ + && SimHintiS(SimHint_enable_outer, VG_(clo_sim_hints))) + ok = True; + if (!ok) + SET_STATUS_Failure( VKI_EBADF ); + else + PRE_MEM_READ( "write(buf)", ARG2, ARG3 ); +} + +PRE(sys_ftruncate) +{ + *flags |= SfMayBlock; + PRINT("sys_ftruncate ( %ld, %lu )", ARG1,ARG3); + PRE_REG_READ3(long, "ftruncate", unsigned int, fd, int, pad, + unsigned int, length); +} + +PRE(sys_ftruncate7) +{ + *flags |= SfMayBlock; + PRINT("sys_ftruncate ( %ld, %lu )", ARG1,ARG2); + PRE_REG_READ2(long, "ftruncate", unsigned int, fd, + unsigned long, length); +} + +PRE(sys_truncate) +{ + *flags |= SfMayBlock; + PRINT("sys_truncate ( %#lx(%s), %lu )", ARG1,(char *)ARG1,ARG3); + PRE_REG_READ3(long, "truncate", + const char *, path, int, pad, unsigned int, length); + PRE_MEM_RASCIIZ( "truncate(path)", ARG1 ); +} + +PRE(sys_truncate7) +{ + *flags |= SfMayBlock; + PRINT("sys_truncate ( %#lx(%s), %lu )", ARG1,(char *)ARG1,ARG2); + PRE_REG_READ2(long, "truncate", + const char *, path, unsigned long, length); + PRE_MEM_RASCIIZ( "truncate(path)", ARG1 ); +} + +PRE(sys_sysarch) +{ + ThreadState *tst; + void **p; + + PRINT("sys_sysarch ( %ld, %#lx )", ARG1, ARG2); + PRE_REG_READ2(int, "sysarch", + int, number, void *, args); + switch (ARG1) { + case VKI_AMD64_SET_FSBASE: + PRINT("sys_amd64_set_fsbase ( %#lx )", ARG2); + PRE_REG_READ1(long, "amd64_set_fsbase", void *, base) + + /* On FreeBSD, the syscall loads the %gs selector for us, so do it now. */ + tst = VG_(get_ThreadState)(tid); + p = (void**)ARG2; + tst->arch.vex.guest_FS_ZERO = (UWord)*p; + /* "do" the syscall ourselves; the kernel never sees it */ + SET_STATUS_Success2((ULong)*p, tst->arch.vex.guest_RDX ); + + break; + case VKI_AMD64_GET_FSBASE: + PRINT("sys_amd64_get_fsbase ( %#lx )", ARG2); + PRE_REG_READ1(int, "amd64_get_fsbase", void *, basep) + PRE_MEM_WRITE( "amd64_get_fsbase(basep)", ARG2, sizeof(void *) ); + + /* "do" the syscall ourselves; the kernel never sees it */ + tst = VG_(get_ThreadState)(tid); + SET_STATUS_Success2( tst->arch.vex.guest_FS_ZERO, tst->arch.vex.guest_RDX ); + POST_MEM_WRITE( ARG2, sizeof(void *) ); + break; + default: + VG_(message) (Vg_UserMsg, "unhandled sysarch cmd %ld", ARG1); + VG_(unimplemented) ("unhandled sysarch cmd"); + break; + } +} + +#undef PRE +#undef POST + +#endif /* defined(VGP_amd64_freebsd) */ + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_syswrap/syswrap-amd64-openbsd.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coregrind/m_syswrap/syswrap-amd64-openbsd.c Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,769 @@ + +/*--------------------------------------------------------------------*/ +/*--- Platform-specific syscalls stuff. syswrap-amd64-freebsd.c ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2005 Nicholas Nethercote + njn@valgrind.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#if defined(VGP_amd64_openbsd) + +#include "pub_core_basics.h" +#include "pub_core_vki.h" +#include "pub_core_vkiscnums.h" +#include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy +#include "pub_core_threadstate.h" +#include "pub_core_aspacemgr.h" +#include "pub_core_debuglog.h" +#include "pub_core_libcbase.h" +#include "pub_core_libcassert.h" +#include "pub_core_libcprint.h" +#include "pub_core_libcproc.h" +#include "pub_core_libcsignal.h" +#include "pub_core_machine.h" +#include "pub_core_options.h" +#include "pub_core_scheduler.h" +#include "pub_core_sigframe.h" +#include "pub_core_signals.h" +#include "pub_core_syscall.h" +#include "pub_core_syswrap.h" +#include "pub_core_tooliface.h" +#include "pub_core_stacks.h" // VG_(register_stack) + +#include "pub_tool_libcbase.h" + +#include "priv_types_n_macros.h" +#include "priv_syswrap-generic.h" /* for decls of generic wrappers */ +#include "priv_syswrap-openbsd.h" /* for decls of freebsd-ish wrappers */ +#include "priv_syswrap-main.h" + +/* --------------------------------------------------------------------- + clone() handling + ------------------------------------------------------------------ */ + +/* 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. */ +__attribute__((noreturn)) +void ML_(call_on_new_stack_0_1) ( Addr stack, + Addr retaddr, + void (*f)(Word), + Word arg1 ); +// %rdi == stack +// %rsi == retaddr +// %rdx == f +// %rcx == arg1 +asm( +".text\n" +".globl vgModuleLocal_call_on_new_stack_0_1\n" +"vgModuleLocal_call_on_new_stack_0_1:\n" +" movq %rdi, %rsp\n" // set stack +" pushq %rsi\n" // retaddr to stack +" pushq %rdx\n" // f to stack +" pushq %rcx\n" // arg1 to stack +" movq $0, %rax\n" // zero all GP regs +" movq $0, %rbx\n" +" movq $0, %rcx\n" +" movq $0, %rdx\n" +" movq $0, %rsi\n" +" movq $0, %rdi\n" +" movq $0, %rbp\n" +" movq $0, %r8\n" +" movq $0, %r9\n" +" movq $0, %r10\n" +" movq $0, %r11\n" +" movq $0, %r12\n" +" movq $0, %r13\n" +" movq $0, %r14\n" +" movq $0, %r15\n" +" popq %rdi\n" // arg1 to correct arg reg +" ret\n" // jump to f +" ud2\n" // should never get here +".previous\n" +); + + +/* --------------------------------------------------------------------- + More thread stuff + ------------------------------------------------------------------ */ + +void VG_(cleanup_thread) ( ThreadArchState *arch ) +{ +} + +/* --------------------------------------------------------------------- + PRE/POST wrappers for amd64/FreeBSD-specific syscalls + ------------------------------------------------------------------ */ + +#define PRE(name) DEFN_PRE_TEMPLATE(openbsd, name) +#define POST(name) DEFN_POST_TEMPLATE(openbsd, name) + +#if 0 +PRE(sys_thr_new) +{ + static const Bool debug = False; + + ThreadId ctid = VG_(alloc_ThreadState)(); + ThreadState* ptst = VG_(get_ThreadState)(tid); + ThreadState* ctst = VG_(get_ThreadState)(ctid); + SysRes res; + vki_sigset_t blockall, savedmask; + struct vki_thr_param tp; + Addr stk; + + PRINT("thr_new ( %#lx, %ld )",ARG1,ARG2); + PRE_REG_READ2(int, "thr_new", + struct thr_param *, param, + int, param_size); + + PRE_MEM_READ( "thr_new(param)", ARG1, offsetof(struct vki_thr_param, spare)); + if (!ML_(safe_to_deref)( (void*)ARG1, offsetof(struct vki_thr_param, spare))) { + SET_STATUS_Failure( VKI_EFAULT ); + return; + } + VG_(memset)(&tp, 0, sizeof(tp)); + VG_(memcpy)(&tp, (void *)ARG1, offsetof(struct vki_thr_param, spare)); + 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); + + vg_assert(VG_(is_running_thread)(tid)); + vg_assert(VG_(is_valid_tid)(ctid)); + + /* Copy register state + + On linux, both parent and child return to the same place, and the code + following the clone syscall works out which is which, so we + don't need to worry about it. + On FreeBSD, thr_new arranges a direct call. We don't actually need any + of this gunk. + + The parent gets the child's new tid returned from clone, but the + child gets 0. + + If the clone call specifies a NULL rsp for the new thread, then + it actually gets a copy of the parent's rsp. + */ + /* We inherit our parent's guest state. */ + ctst->arch.vex = ptst->arch.vex; + ctst->arch.vex_shadow1 = ptst->arch.vex_shadow1; + ctst->arch.vex_shadow2 = ptst->arch.vex_shadow2; + + /* Make thr_new appear to have returned Success(0) in the + child. */ + ctst->arch.vex.guest_RAX = 0; + ctst->arch.vex.guest_RDX = 0; + LibVEX_GuestAMD64_put_rflag_c(0, &ctst->arch.vex); + + ctst->os_state.parent = tid; + + /* inherit signal mask */ + ctst->sig_mask = ptst->sig_mask; + ctst->tmp_sig_mask = ptst->sig_mask; + + /* Linux has to guess, we don't */ + ctst->client_stack_highest_word = (Addr)tp.stack_base + tp.stack_size; + ctst->client_stack_szB = tp.stack_size; + VG_(register_stack)((Addr)tp.stack_base, (Addr)tp.stack_base + tp.stack_size); + + /* 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 ); + + if (debug) + VG_(printf)("clone child has SETTLS: tls at %#lx\n", (Addr)tp.tls_base); + ctst->arch.vex.guest_FS_ZERO = (UWord)tp.tls_base; + tp.tls_base = 0; /* Don't have the kernel do it too */ + + /* start the thread with everything blocked */ + VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask); + + /* 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; + + /* But this is for thr_new() to run valgrind's trampoline */ + tp.start_func = (void *)ML_(start_thread_NORETURN); + tp.arg = &VG_(threads)[ctid]; + + /* 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; + + /* Create the new thread */ + // XXX: Find solution for libthr + // res = VG_(do_syscall2)(__NR_thr_new, (UWord)&tp, sizeof(tp)); + + VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL); + +fail: + if (sr_isError(res)) { + /* thr_new failed */ + VG_(cleanup_thread)(&ctst->arch); + ctst->status = VgTs_Empty; + /* oops. Better tell the tool the thread exited in a hurry :-) */ + VG_TRACK( pre_thread_ll_exit, ctid ); + } else { + + POST_MEM_WRITE((Addr)tp.parent_tid, sizeof(long)); + POST_MEM_WRITE((Addr)tp.child_tid, sizeof(long)); + + /* Thread creation was successful; let the child have the chance + to run */ + *flags |= SfYieldAfter; + } + + /* "Complete" the syscall so that the wrapper doesn't call the kernel again. */ + SET_STATUS_from_SysRes(res); +} +#endif + +#if 0 +PRE(sys_rfork) +{ + PRINT("sys_rfork ( %#lx )", ARG1 ); + PRE_REG_READ1(long, "rfork", int, flags); + + VG_(message)(Vg_UserMsg, "rfork() not implemented"); + VG_(unimplemented)("Valgrind does not support rfork()."); + + SET_STATUS_Failure(VKI_ENOSYS); +} +#endif + +PRE(sys_sigreturn) +{ + PRINT("sys_sigreturn ( %#lx )", ARG1); + PRE_REG_READ1(long, "sigreturn", + struct vki_ucontext *, ucp); + + PRE_MEM_READ( "sigreturn(ucp)", ARG1, sizeof(struct vki_ucontext) ); + PRE_MEM_WRITE( "sigreturn(ucp)", ARG1, sizeof(struct vki_ucontext) ); +} + +PRE(sys_fake_sigreturn) +{ + ThreadState* tst; + struct vki_ucontext *uc; + int rflags; + + PRINT("sys_sigreturn ( %#lx )", ARG1); + PRE_REG_READ1(long, "sigreturn", + struct vki_ucontext *, ucp); + + PRE_MEM_READ( "sigreturn(ucp)", ARG1, sizeof(struct vki_ucontext) ); + PRE_MEM_WRITE( "sigreturn(ucp)", ARG1, sizeof(struct vki_ucontext) ); + + 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_RSP -= sizeof(Addr); + + uc = (struct vki_ucontext *)ARG1; + if (uc == NULL || uc->uc_mcontext.len != sizeof(uc->uc_mcontext)) { + SET_STATUS_Failure(VKI_EINVAL); + return; + } + + /* 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); + + /* 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). */ + rflags = LibVEX_GuestAMD64_get_rflags(&tst->arch.vex); + SET_STATUS_from_SysRes( VG_(mk_SysRes_amd64_openbsd)( tst->arch.vex.guest_RAX, + tst->arch.vex.guest_RDX, (rflags & 1) != 0 ? True : False) ); + + /* + * Signal handler might have changed the signal mask. Respect that. + */ + tst->sig_mask = uc->uc_sigmask; + tst->tmp_sig_mask = uc->uc_sigmask; + + /* 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); + + /* Check to see if some any signals arose as a result of this. */ + *flags |= SfPollAfter; +} + +static void restore_mcontext(ThreadState *tst, struct vki_mcontext *sc) +{ + tst->arch.vex.guest_RAX = sc->rax; + tst->arch.vex.guest_RCX = sc->rcx; + tst->arch.vex.guest_RDX = sc->rdx; + tst->arch.vex.guest_RBX = sc->rbx; + tst->arch.vex.guest_RBP = sc->rbp; + tst->arch.vex.guest_RSP = sc->rsp; + tst->arch.vex.guest_RSI = sc->rsi; + tst->arch.vex.guest_RDI = sc->rdi; + tst->arch.vex.guest_R8 = sc->r8; + tst->arch.vex.guest_R9 = sc->r9; + tst->arch.vex.guest_R10 = sc->r10; + tst->arch.vex.guest_R11 = sc->r11; + tst->arch.vex.guest_R12 = sc->r12; + 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_RIP = sc->rip; + /* + * XXX: missing support for other flags. + */ + if (sc->rflags & 0x0001) + LibVEX_GuestAMD64_put_rflag_c(1, &tst->arch.vex); + else + LibVEX_GuestAMD64_put_rflag_c(0, &tst->arch.vex); +} + +static void fill_mcontext(ThreadState *tst, struct vki_mcontext *sc) +{ + sc->rax = tst->arch.vex.guest_RAX; + sc->rcx = tst->arch.vex.guest_RCX; + sc->rdx = tst->arch.vex.guest_RDX; + sc->rbx = tst->arch.vex.guest_RBX; + sc->rbp = tst->arch.vex.guest_RBP; + sc->rsp = tst->arch.vex.guest_RSP; + sc->rsi = tst->arch.vex.guest_RSI; + sc->rdi = tst->arch.vex.guest_RDI; + sc->r8 = tst->arch.vex.guest_R8; + sc->r9 = tst->arch.vex.guest_R9; + sc->r10 = tst->arch.vex.guest_R10; + sc->r11 = tst->arch.vex.guest_R11; + sc->r12 = tst->arch.vex.guest_R12; + sc->r13 = tst->arch.vex.guest_R13; + sc->r14 = tst->arch.vex.guest_R14; + sc->r15 = tst->arch.vex.guest_R15; + sc->rip = tst->arch.vex.guest_RIP; +/* + Not supported by VEX. + sc->cs = tst->arch.vex.guest_CS; + sc->ss = tst->arch.vex.guest_SS; + sc->ds = tst->arch.vex.guest_DS; + sc->es = tst->arch.vex.guest_ES; + sc->fs = tst->arch.vex.guest_FS; + sc->gs = tst->arch.vex.guest_GS; +*/ + sc->rflags = LibVEX_GuestAMD64_get_rflags(&tst->arch.vex); +/* + not yet. + VG_(memcpy)(&sc->fpstate, fpstate, sizeof(*fpstate)); +*/ + sc->fpformat = VKI_FPFMT_NODEV; + sc->ownedfp = VKI_FPOWNED_NONE; + sc->len = sizeof(*sc); + VG_(memset)(sc->spare2, 0, sizeof(sc->spare2)); +} + +PRE(sys_getcontext) +{ + ThreadState* tst; + struct vki_ucontext *uc; + + PRINT("sys_getcontext ( %#lx )", ARG1); + PRE_REG_READ1(long, "getcontext", + struct vki_ucontext *, ucp); + PRE_MEM_WRITE( "getcontext(ucp)", ARG1, sizeof(struct vki_ucontext) ); + uc = (struct vki_ucontext *)ARG1; + if (uc == NULL) { + SET_STATUS_Failure(VKI_EINVAL); + return; + } + tst = VG_(get_ThreadState)(tid); + fill_mcontext(tst, &uc->uc_mcontext); + uc->uc_mcontext.rax = 0; + uc->uc_mcontext.rdx = 0; + uc->uc_mcontext.rflags &= ~0x0001; /* PSL_C */ + uc->uc_sigmask = tst->sig_mask; + VG_(memset)(uc->__spare__, 0, sizeof(uc->__spare__)); + SET_STATUS_Success(0); +} + +PRE(sys_setcontext) +{ + ThreadState* tst; + struct vki_ucontext *uc; + + PRINT("sys_setcontext ( %#lx )", ARG1); + PRE_REG_READ1(long, "setcontext", + struct vki_ucontext *, ucp); + + PRE_MEM_READ( "setcontext(ucp)", ARG1, sizeof(struct vki_ucontext) ); + PRE_MEM_WRITE( "setcontext(ucp)", ARG1, sizeof(struct vki_ucontext) ); + + vg_assert(VG_(is_valid_tid)(tid)); + vg_assert(tid >= 1 && tid < VG_N_THREADS); + vg_assert(VG_(is_running_thread)(tid)); + + tst = VG_(get_ThreadState)(tid); + uc = (struct vki_ucontext *)ARG1; + if (uc == NULL || uc->uc_mcontext.len != sizeof(uc->uc_mcontext)) { + SET_STATUS_Failure(VKI_EINVAL); + return; + } + + restore_mcontext(tst, &uc->uc_mcontext); + tst->sig_mask = uc->uc_sigmask; + + /* 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); + + /* Check to see if some any signals arose as a result of this. */ + *flags |= SfPollAfter; +} + +PRE(sys_swapcontext) +{ + struct vki_ucontext *ucp, *oucp; + ThreadState* tst; + + PRINT("sys_swapcontext ( %#lx, %#lx )", ARG1, ARG2); + PRE_REG_READ2(long, "swapcontext", + struct vki_ucontext *, oucp, struct vki_ucontext *, ucp); + + PRE_MEM_READ( "swapcontext(ucp)", ARG2, sizeof(struct vki_ucontext) ); + PRE_MEM_WRITE( "swapcontext(oucp)", ARG1, sizeof(struct vki_ucontext) ); + + oucp = (struct vki_ucontext *)ARG1; + ucp = (struct vki_ucontext *)ARG2; + if (oucp == NULL || ucp == NULL || ucp->uc_mcontext.len != sizeof(ucp->uc_mcontext)) { + SET_STATUS_Failure(VKI_EINVAL); + return; + } + tst = VG_(get_ThreadState)(tid); + + /* + * Save the context. + */ + fill_mcontext(tst, &oucp->uc_mcontext); + oucp->uc_mcontext.rax = 0; + oucp->uc_mcontext.rdx = 0; + oucp->uc_mcontext.rflags &= ~0x0001; /* PSL_C */ + oucp->uc_sigmask = tst->sig_mask; + VG_(memset)(oucp->__spare__, 0, sizeof(oucp->__spare__)); + + /* + * Switch to new one. + */ + restore_mcontext(tst, &ucp->uc_mcontext); + tst->sig_mask = ucp->uc_sigmask; + + /* 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); + + /* Check to see if some any signals arose as a result of this. */ + *flags |= SfPollAfter; +} + + +/* This is here because on x86 the off_t is passed in 2 regs. Don't ask about pad. */ + +/* caddr_t mmap(caddr_t addr, size_t len, int prot, int flags, int fd, int pad, off_t pos); */ +/* ARG1 ARG2 ARG3 ARG4 ARG5 ARG6 ARG7 */ + +PRE(sys_mmap) +{ + SysRes r; + + PRINT("sys_mmap ( %#lx, %lu, %ld, %ld, %ld, pad%ld, 0x%lx)", + ARG1, (UWord)ARG2, ARG3, ARG4, ARG5, ARG6, ARG7 ); +#if !defined(VGO_openbsd) + PRE_REG_READ7(long, "mmap", + char *, addr, unsigned long, len, int, prot, int, flags, + int, fd, int, pad, unsigned long, pos); +#else + /* Take account of __syscall sysno (arg1). */ + PRE_REG_READ8(long, "mmap", + long, sysno, + char *, addr, unsigned long, len, int, prot, int, flags, + int, fd, int, pad, unsigned long, pos); + // XXX XXX XXX Check all other __syscall users too +#endif + + r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG7 ); + SET_STATUS_from_SysRes(r); +} + +#if 0 +/* FreeBSD-7 introduces a "regular" version of mmap etc. */ +PRE(sys_mmap7) +{ + SysRes r; + + PRINT("sys_mmap ( %#lx, %lu, %ld, %ld, %ld, 0x%lx)", + ARG1, (UWord)ARG2, ARG3, ARG4, ARG5, ARG6 ); + PRE_REG_READ6(long, "mmap", + char *, addr, unsigned long, len, int, prot, int, flags, + int, fd, unsigned long, pos); + + r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 ); + SET_STATUS_from_SysRes(r); +} +#endif + +PRE(sys_lseek) +{ + PRINT("sys_lseek ( %ld, 0x%lx, %#lx, %ld )", ARG1,ARG2,ARG3,ARG4); + +#if !defined(VGO_openbsd) + PRE_REG_READ4(long, "lseek", + unsigned int, fd, int, pad, unsigned long, offset, + unsigned int, whence); +#else + PRE_REG_READ5(long, "lseek", + long, sysno, + unsigned int, fd, int, pad, unsigned long, offset, + unsigned int, whence); +#endif +} + +#if 0 +PRE(sys_lseek7) +{ + PRINT("sys_lseek ( %ld, 0x%lx, %ld )", ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "lseek", + unsigned int, fd, unsigned long, offset, + unsigned int, whence); +} +#endif + +PRE(sys_pread) +{ + *flags |= SfMayBlock; + PRINT("sys_read ( %ld, %#lx, %lu, %lu, %lu )", ARG1, ARG2, ARG3, ARG4, ARG5); +#if !defined(VGO_openbsd) + PRE_REG_READ5(ssize_t, "read", + unsigned int, fd, char *, buf, vki_size_t, count, + int, pad, unsigned long, off); +#else + PRE_REG_READ6(ssize_t, "read", + long, sysno, + unsigned int, fd, char *, buf, vki_size_t, count, + int, pad, unsigned long, off); +#endif + + if (!ML_(fd_allowed)(ARG1, "read", tid, False)) + SET_STATUS_Failure( VKI_EBADF ); + else + PRE_MEM_WRITE( "read(buf)", ARG2, ARG3 ); +} + +POST(sys_pread) +{ + vg_assert(SUCCESS); + POST_MEM_WRITE( ARG2, RES ); +} + +#if 0 +PRE(sys_pread7) +{ + *flags |= SfMayBlock; + PRINT("sys_read ( %ld, %#lx, %lu, %lu )", ARG1, ARG2, ARG3, ARG4); + PRE_REG_READ4(ssize_t, "read", + unsigned int, fd, char *, buf, vki_size_t, count, + unsigned long, off); + + if (!ML_(fd_allowed)(ARG1, "read", tid, False)) + SET_STATUS_Failure( VKI_EBADF ); + else + PRE_MEM_WRITE( "read(buf)", ARG2, ARG3 ); +} + +POST(sys_pread7) +{ + vg_assert(SUCCESS); + POST_MEM_WRITE( ARG2, RES ); +} +#endif + +PRE(sys_pwrite) +{ + Bool ok; + *flags |= SfMayBlock; + PRINT("sys_write ( %ld, %#lx, %lu, %lu, %lu )", ARG1, ARG2, ARG3, ARG4, ARG5); +#if !defined(VGO_openbsd) + PRE_REG_READ5(ssize_t, "write", + unsigned int, fd, const char *, buf, vki_size_t, count, + int, pad, unsigned long, off); +#else + PRE_REG_READ6(ssize_t, "write", + long, sysno, + unsigned int, fd, const char *, buf, vki_size_t, count, + int, pad, unsigned long, off); +#endif + /* check to see if it is allowed. If not, try for an exemption from + --sim-hints=enable-outer (used for self hosting). */ + ok = ML_(fd_allowed)(ARG1, "write", tid, False); + if (!ok && ARG1 == 2/*stderr*/ + && SimHintiS(SimHint_enable_outer, VG_(clo_sim_hints))) + ok = True; + if (!ok) + SET_STATUS_Failure( VKI_EBADF ); + else + PRE_MEM_READ( "write(buf)", ARG2, ARG3 ); +} + +#if 0 +PRE(sys_pwrite7) +{ + Bool ok; + *flags |= SfMayBlock; + PRINT("sys_write ( %ld, %#lx, %lu, %lu )", ARG1, ARG2, ARG3, ARG4); + PRE_REG_READ4(ssize_t, "write", + unsigned int, fd, const char *, buf, vki_size_t, count, + unsigned long, off); + /* check to see if it is allowed. If not, try for an exemption from + --sim-hints=enable-outer (used for self hosting). */ + ok = ML_(fd_allowed)(ARG1, "write", tid, False); + if (!ok && ARG1 == 2/*stderr*/ + && SimHintiS(SimHint_enable_outer, VG_(clo_sim_hints))) + ok = True; + if (!ok) + SET_STATUS_Failure( VKI_EBADF ); + else + PRE_MEM_READ( "write(buf)", ARG2, ARG3 ); +} +#endif + +PRE(sys_ftruncate) +{ + *flags |= SfMayBlock; + PRINT("sys_ftruncate ( %ld, %lu )", ARG1,ARG3); +#if !defined(VGO_openbsd) + PRE_REG_READ3(long, "ftruncate", unsigned int, fd, int, pad, + unsigned int, length); +#else + PRE_REG_READ4(long, "ftruncate", long, sysno, unsigned int, fd, int, pad, + unsigned int, length); +#endif +} + +#if 0 +PRE(sys_ftruncate7) +{ + *flags |= SfMayBlock; + PRINT("sys_ftruncate ( %ld, %lu )", ARG1,ARG2); + PRE_REG_READ2(long, "ftruncate", unsigned int, fd, + unsigned long, length); +} +#endif + +PRE(sys_truncate) +{ + *flags |= SfMayBlock; + PRINT("sys_truncate ( %#lx(%s), %lu )", ARG1,(char *)ARG1,ARG3); +#if !defined(VGO_openbsd) + PRE_REG_READ3(long, "truncate", + const char *, path, int, pad, unsigned int, length); +#else + PRE_REG_READ4(long, "truncate", + long, sysno, + const char *, path, int, pad, unsigned int, length); +#endif + PRE_MEM_RASCIIZ( "truncate(path)", ARG1 ); +} + +#if 0 +PRE(sys_truncate7) +{ + *flags |= SfMayBlock; + PRINT("sys_truncate ( %#lx(%s), %lu )", ARG1,(char *)ARG1,ARG2); + PRE_REG_READ2(long, "truncate", + const char *, path, unsigned long, length); + PRE_MEM_RASCIIZ( "truncate(path)", ARG1 ); +} +#endif + +PRE(sys_sysarch) +{ + ThreadState *tst; + void **p; + + PRINT("sys_sysarch ( %ld, %#lx )", ARG1, ARG2); + PRE_REG_READ2(int, "sysarch", + int, number, void *, args); + switch (ARG1) { + case VKI_AMD64_SET_FSBASE: + PRINT("sys_amd64_set_fsbase ( %#lx )", ARG2); + PRE_REG_READ1(long, "amd64_set_fsbase", void *, base) + + /* On FreeBSD, the syscall loads the %gs selector for us, so do it now. */ + tst = VG_(get_ThreadState)(tid); + p = (void**)ARG2; + tst->arch.vex.guest_FS_ZERO = (UWord)*p; + /* "do" the syscall ourselves; the kernel never sees it */ + SET_STATUS_Success2((ULong)*p, tst->arch.vex.guest_RDX ); + + break; + case VKI_AMD64_GET_FSBASE: + PRINT("sys_amd64_get_fsbase ( %#lx )", ARG2); + PRE_REG_READ1(int, "amd64_get_fsbase", void *, basep) + PRE_MEM_WRITE( "amd64_get_fsbase(basep)", ARG2, sizeof(void *) ); + + /* "do" the syscall ourselves; the kernel never sees it */ + tst = VG_(get_ThreadState)(tid); + SET_STATUS_Success2( tst->arch.vex.guest_FS_ZERO, tst->arch.vex.guest_RDX ); + POST_MEM_WRITE( ARG2, sizeof(void *) ); + break; + default: + VG_(message) (Vg_UserMsg, "unhandled sysarch cmd %ld", ARG1); + VG_(unimplemented) ("unhandled sysarch cmd"); + break; + } +} + +#undef PRE +#undef POST + +#endif /* defined(VGP_amd64_openbsd) */ + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_syswrap/syswrap-freebsd-variants.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coregrind/m_syswrap/syswrap-freebsd-variants.c Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,95 @@ + +/*--------------------------------------------------------------------*/ +/*--- Handlers for syscalls on minor variants of Linux kernels. ---*/ +/*--- syswrap-linux-variants.c ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2008 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +/* The files syswrap-generic.c, syswrap-linux.c, syswrap-x86-linux.c, + syswrap-amd64-linux.c and syswrap-ppc32-linux.c, and associated + vki*.h header files, constitute Valgrind's model of how a vanilla + Linux kernel behaves with respect to syscalls. + + On a few occasions, it is useful to run with a kernel that has some + (minor) extensions to the vanilla model, either due to running on a + hacked kernel, or using a vanilla kernel which has incorporated a + custom kernel module. Rather than clutter the standard model, all + such variant handlers are placed in here. + + Unlike the C files for the standard model, this file should also + contain all constants/types needed for said wrappers. The vki*.h + headers should not be polluted with non-vanilla info. */ + + +#include "pub_core_basics.h" +#include "pub_core_vki.h" +#include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy +#include "pub_core_threadstate.h" +#include "pub_core_aspacemgr.h" +#include "pub_core_debuginfo.h" // VG_(di_notify_*) +#include "pub_core_transtab.h" // VG_(discard_translations) +#include "pub_core_debuglog.h" +#include "pub_core_libcbase.h" +#include "pub_core_libcassert.h" +#include "pub_core_libcfile.h" +#include "pub_core_libcprint.h" +#include "pub_core_libcproc.h" +#include "pub_core_mallocfree.h" +#include "pub_core_tooliface.h" +#include "pub_core_options.h" +#include "pub_core_scheduler.h" +#include "pub_core_signals.h" +#include "pub_core_syscall.h" + +#include "priv_types_n_macros.h" +#include "priv_syswrap-freebsd.h" + + +#if 0 /* think about ylock syscall etc */ +/* --------------------------------------------------------------- + BProc wrappers + ------------------------------------------------------------ */ + +/* Return 0 means hand to kernel, non-0 means fail w/ that value. */ +Int ML_(linux_variant_PRE_sys_bproc)( UWord arg1, UWord arg2, + UWord arg3, UWord arg4, + UWord arg5, UWord arg6 ) +{ + return 0; +} + +void ML_(linux_variant_POST_sys_bproc)( UWord arg1, UWord arg2, + UWord arg3, UWord arg4, + UWord arg5, UWord arg6 ) +{ +} +#endif + + +/*--------------------------------------------------------------------*/ +/*--- end syswrap-linux-variants.c ---*/ +/*--------------------------------------------------------------------*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_syswrap/syswrap-freebsd.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coregrind/m_syswrap/syswrap-freebsd.c Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,4277 @@ + +/*--------------------------------------------------------------------*/ +/*--- FreeBSD-specific syscalls, etc. syswrap-freebsd.c ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2008 Nicholas Nethercote + njn@valgrind.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#if defined(VGO_freebsd) + +#include "pub_core_basics.h" +#include "pub_core_vki.h" +#include "pub_core_vkiscnums.h" +#include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy +#include "pub_core_threadstate.h" +#include "pub_core_aspacemgr.h" +#include "pub_core_debuginfo.h" // VG_(di_notify_*) +#include "pub_core_transtab.h" // VG_(discard_translations) +#include "pub_core_xarray.h" +#include "pub_core_clientstate.h" +#include "pub_core_debuglog.h" +#include "pub_core_libcbase.h" +#include "pub_core_libcassert.h" +#include "pub_core_libcfile.h" +#include "pub_core_libcprint.h" +#include "pub_core_libcproc.h" +#include "pub_core_libcsignal.h" +#include "pub_core_machine.h" +#include "pub_core_mallocfree.h" +#include "pub_core_tooliface.h" +#include "pub_core_options.h" +#include "pub_core_scheduler.h" +#include "pub_core_signals.h" +#include "pub_core_syscall.h" +#include "pub_core_syswrap.h" + +#include "priv_types_n_macros.h" +#include "priv_syswrap-generic.h" +#include "priv_syswrap-freebsd.h" + + +// Run a thread from beginning to end and return the thread's +// scheduler-return-code. +static VgSchedReturnCode thread_wrapper(Word /*ThreadId*/ tidW) +{ + VgSchedReturnCode ret; + ThreadId tid = (ThreadId)tidW; + ThreadState* tst = VG_(get_ThreadState)(tid); + + VG_(debugLog)(1, "syswrap-freebsd", + "thread_wrapper(tid=%lld): entry\n", + (ULong)tidW); + + vg_assert(tst->status == VgTs_Init); + + /* make sure we get the CPU lock before doing anything significant */ + VG_(acquire_BigLock)(tid, "thread_wrapper(starting new thread)"); + + if (0) + VG_(printf)("thread tid %d started: stack = %p\n", + tid, &tid); + + /* Make sure error reporting is enabled in the new thread. */ + tst->err_disablement_level = 0; + + VG_TRACK(pre_thread_first_insn, tid); + + tst->os_state.lwpid = VG_(gettid)(); + tst->os_state.threadgroup = VG_(getpid)(); + + /* Thread created with all signals blocked; scheduler will set the + appropriate mask */ + + ret = VG_(scheduler)(tid); + + vg_assert(VG_(is_exiting)(tid)); + + vg_assert(tst->status == VgTs_Runnable); + vg_assert(VG_(is_running_thread)(tid)); + + VG_(debugLog)(1, "syswrap-freebsd", + "thread_wrapper(tid=%lld): exit\n", + (ULong)tidW); + + /* Return to caller, still holding the lock. */ + return ret; +} + + +/* --------------------------------------------------------------------- + clone-related stuff + ------------------------------------------------------------------ */ + +/* Run a thread all the way to the end, then do appropriate exit actions + (this is the last-one-out-turn-off-the-lights bit). */ +static void run_a_thread_NORETURN ( Word tidW ) +{ + ThreadId tid = (ThreadId)tidW; + VgSchedReturnCode src; + Int c; + ThreadState* tst; + + VG_(debugLog)(1, "syswrap-freebsd", + "run_a_thread_NORETURN(tid=%lld): pre-thread_wrapper\n", + (ULong)tidW); + + tst = VG_(get_ThreadState)(tid); + vg_assert(tst); + + /* Run the thread all the way through. */ + src = thread_wrapper(tid); + + VG_(debugLog)(1, "syswrap-freebsd", + "run_a_thread_NORETURN(tid=%lld): post-thread_wrapper\n", + (ULong)tidW); + + c = VG_(count_living_threads)(); + vg_assert(c >= 1); /* stay sane */ + + // Tell the tool this thread is exiting + VG_TRACK( pre_thread_ll_exit, tid ); + + /* If the thread is exiting with errors disabled, complain loudly; + doing so is bad (does the user know this has happened?) Also, + in all cases, be paranoid and clear the flag anyway so that the + thread slot is safe in this respect if later reallocated. This + should be unnecessary since the flag should be cleared when the + slot is reallocated, in thread_wrapper(). */ + if (tst->err_disablement_level > 0) { + VG_(umsg)( + "WARNING: exiting thread has error reporting disabled.\n" + "WARNING: possibly as a result of some mistake in the use\n" + "WARNING: of the VALGRIND_DISABLE_ERROR_REPORTING macros.\n" + ); + VG_(debugLog)( + 1, "syswrap-freebsd", + "run_a_thread_NORETURN(tid=%lld): " + "WARNING: exiting thread has err_disablement_level = %u\n", + (ULong)tidW, tst->err_disablement_level + ); + } + tst->err_disablement_level = 0; + + if (c == 1) { + + VG_(debugLog)(1, "syswrap-freebsd", + "run_a_thread_NORETURN(tid=%lld): " + "last one standing\n", + (ULong)tidW); + + /* We are the last one standing. Keep hold of the lock and + carry on to show final tool results, then exit the entire system. + Use the continuation pointer set at startup in m_main. */ + ( * VG_(address_of_m_main_shutdown_actions_NORETURN) ) (tid, src); + + } else { + + VG_(debugLog)(1, "syswrap-freebsd", + "run_a_thread_NORETURN(tid=%lld): " + "not last one standing\n", + (ULong)tidW); + + /* OK, thread is dead, but others still exist. Just exit. */ + + /* This releases the run lock */ + VG_(exit_thread)(tid); + vg_assert(tst->status == VgTs_Zombie); + + /* We have to use this sequence to terminate the thread to + prevent a subtle race. If VG_(exit_thread)() had left the + ThreadState as Empty, then it could have been reallocated, + reusing the stack while we're doing these last cleanups. + Instead, VG_(exit_thread) leaves it as Zombie to prevent + reallocation. We need to make sure we don't touch the stack + between marking it Empty and exiting. Hence the + assembler. */ +#if defined(VGP_x86_freebsd) /* FreeBSD has args on the stack */ + asm volatile ( + "movl %1, %0\n" /* set tst->status = VgTs_Empty */ + "movl %2, %%eax\n" /* set %eax = __NR_thr_exit */ + "movl %3, %%ebx\n" /* set %ebx = tst->os_state.exitcode */ + "pushl %%ebx\n" /* arg on stack */ + "pushl %%ebx\n" /* fake return address */ + "int $0x80\n" /* thr_exit(tst->os_state.exitcode) */ + "popl %%ebx\n" /* fake return address */ + "popl %%ebx\n" /* arg off stack */ + : "=m" (tst->status) + : "n" (VgTs_Empty), "n" (__NR_thr_exit), "m" (tst->os_state.exitcode) + : "eax", "ebx" + ); +#elif defined(VGP_amd64_freebsd) + asm volatile ( + "movl %1, %0\n" /* set tst->status = VgTs_Empty */ + "movq %2, %%rax\n" /* set %rax = __NR_thr_exit */ + "movq %3, %%rdi\n" /* set %rdi = tst->os_state.exitcode */ + "pushq %%rdi\n" /* fake return address */ + "syscall\n" /* thr_exit(tst->os_state.exitcode) */ + "popq %%rdi\n" /* fake return address */ + : "=m" (tst->status) + : "n" (VgTs_Empty), "n" (__NR_thr_exit), "m" (tst->os_state.exitcode) + : "rax", "rdi" + ); +#else +# error Unknown platform +#endif + + VG_(core_panic)("Thread exit failed?\n"); + } + + /*NOTREACHED*/ + vg_assert(0); +} + +Word ML_(start_thread_NORETURN) ( void* arg ) +{ + ThreadState* tst = (ThreadState*)arg; + ThreadId tid = tst->tid; + + run_a_thread_NORETURN ( (Word)tid ); + /*NOTREACHED*/ + vg_assert(0); +} + +/* Allocate a stack for this thread, if it doesn't already have one. + They're allocated lazily, and never freed. Returns the initial stack + pointer value to use, or 0 if allocation failed. */ +Addr ML_(allocstack)(ThreadId tid) +{ + ThreadState* tst = VG_(get_ThreadState)(tid); + VgStack* stack; + Addr initial_SP; + + /* Either the stack_base and stack_init_SP are both zero (in which + case a stack hasn't been allocated) or they are both non-zero, + in which case it has. */ + + if (tst->os_state.valgrind_stack_base == 0) + vg_assert(tst->os_state.valgrind_stack_init_SP == 0); + + if (tst->os_state.valgrind_stack_base != 0) + vg_assert(tst->os_state.valgrind_stack_init_SP != 0); + + /* If no stack is present, allocate one. */ + + if (tst->os_state.valgrind_stack_base == 0) { + stack = VG_(am_alloc_VgStack)( &initial_SP ); + if (stack) { + tst->os_state.valgrind_stack_base = (Addr)stack; + tst->os_state.valgrind_stack_init_SP = initial_SP; + } + } + + if (0) + VG_(printf)( "stack for tid %d at %p; init_SP=%p\n", + tid, + (void*)tst->os_state.valgrind_stack_base, + (void*)tst->os_state.valgrind_stack_init_SP ); + + return tst->os_state.valgrind_stack_init_SP; +} + +/* Allocate a stack for the main thread, and run it all the way to the + end. Although we already have a working VgStack + (VG_(interim_stack)) it's better to allocate a new one, so that + overflow detection works uniformly for all threads. +*/ +void VG_(main_thread_wrapper_NORETURN)(ThreadId tid) +{ + Addr sp; + VG_(debugLog)(1, "syswrap-freebsd", + "entering VG_(main_thread_wrapper_NORETURN)\n"); + + sp = ML_(allocstack)(tid); + +/* QQQ keep for amd64 redzone stuff */ +#if defined(VGP_ppc32_linux) + /* make a stack frame */ + sp -= 16; + sp &= ~0xF; + *(UWord *)sp = 0; +#elif defined(VGP_ppc64_linux) + /* make a stack frame */ + sp -= 112; + sp &= ~((Addr)0xF); + *(UWord *)sp = 0; +#endif + + /* If we can't even allocate the first thread's stack, we're hosed. + Give up. */ + vg_assert2(sp != 0, "Cannot allocate main thread's stack."); + + /* shouldn't be any other threads around yet */ + vg_assert( VG_(count_living_threads)() == 1 ); + + ML_(call_on_new_stack_0_1)( + (Addr)sp, /* stack */ + 0, /* bogus return address */ + run_a_thread_NORETURN, /* fn to call */ + (Word)tid /* arg to give it */ + ); + + /*NOTREACHED*/ + vg_assert(0); +} + + +/* Do a fork() */ +SysRes ML_(do_fork) ( ThreadId tid ) +{ + vki_sigset_t fork_saved_mask; + vki_sigset_t mask; + SysRes res; + + /* Block all signals during fork, so that we can fix things up in + the child without being interrupted. */ + VG_(sigfillset)(&mask); + VG_(sigprocmask)(VKI_SIG_SETMASK, &mask, &fork_saved_mask); + + VG_(do_atfork_pre)(tid); + + res = VG_(do_syscall0)( __NR_fork ); + + if (!sr_isError(res)) { + if (sr_Res(res) == 0) { + /* child */ + VG_(do_atfork_child)(tid); + + /* restore signal mask */ + VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL); + + } + else { + /* parent */ + VG_(do_atfork_parent)(tid); + + if (VG_(clo_trace_syscalls)) + VG_(printf)(" clone(fork): process %d created child %ld\n", + VG_(getpid)(), sr_Res(res)); + + /* restore signal mask */ + VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL); + } + } + + return res; +} + + +/* --------------------------------------------------------------------- + PRE/POST wrappers for arch-generic, Linux-specific syscalls + ------------------------------------------------------------------ */ + +// Nb: See the comment above the generic PRE/POST wrappers in +// m_syswrap/syswrap-generic.c for notes about how they work. + +#define PRE(name) DEFN_PRE_TEMPLATE(freebsd, name) +#define POST(name) DEFN_POST_TEMPLATE(freebsd, name) + +// Combine two 32-bit values into a 64-bit value +#define LOHI64(lo,hi) ( (lo) | ((ULong)(hi) << 32) ) + +PRE(sys_fork) +{ + PRINT("sys_fork ()"); + PRE_REG_READ0(int, "fork"); + + SET_STATUS_from_SysRes( ML_(do_fork)(tid) ); + if (SUCCESS) { + /* Thread creation was successful; let the child have the chance + to run */ + *flags |= SfYieldAfter; + } +} + +PRE(sys_vfork) +{ + PRINT("sys_vfork ()"); + PRE_REG_READ0(int, "vfork"); + + /* Pretend vfork == fork. Not true, but will have to do. */ + SET_STATUS_from_SysRes( ML_(do_fork)(tid) ); + if (SUCCESS) { + /* Thread creation was successful; let the child have the chance + to run */ + *flags |= SfYieldAfter; + } +} + +PRE(sys_socket) +{ + PRINT("sys_socket ( %ld, %ld, %ld )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "socket", int, domain, int, type, int, protocol); +} +POST(sys_socket) +{ + SysRes r; + vg_assert(SUCCESS); + r = ML_(generic_POST_sys_socket)(tid, VG_(mk_SysRes_Success)(RES)); + SET_STATUS_from_SysRes(r); +} + +PRE(sys_setsockopt) +{ + PRINT("sys_setsockopt ( %ld, %ld, %ld, %#lx, %ld )",ARG1,ARG2,ARG3,ARG4,ARG5); + PRE_REG_READ5(long, "setsockopt", + int, s, int, level, int, optname, + const void *, optval, int, optlen); + ML_(generic_PRE_sys_setsockopt)(tid, ARG1,ARG2,ARG3,ARG4,ARG5); +} + +PRE(sys_getsockopt) +{ + PRINT("sys_getsockopt ( %ld, %ld, %ld, %#lx, %#lx )",ARG1,ARG2,ARG3,ARG4,ARG5); + PRE_REG_READ5(long, "getsockopt", + int, s, int, level, int, optname, + void *, optval, int, *optlen); +// XXX: ML_(generic_PRE_sys_getsockopt)(tid, ARG1,ARG2,ARG3,ARG4,ARG5); +} +POST(sys_getsockopt) +{ + vg_assert(SUCCESS); +// ML_(generic_POST_sys_getsockopt)(tid, VG_(mk_SysRes_Success)(RES), +//XXX: ARG1,ARG2,ARG3,ARG4,ARG5); +} + +PRE(sys_connect) +{ + *flags |= SfMayBlock; + PRINT("sys_connect ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "connect", + int, sockfd, struct sockaddr *, serv_addr, int, addrlen); + ML_(generic_PRE_sys_connect)(tid, ARG1,ARG2,ARG3); +} + +PRE(sys_accept) +{ + *flags |= SfMayBlock; + PRINT("sys_accept ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "accept", + int, s, struct sockaddr *, addr, int, *addrlen); + ML_(generic_PRE_sys_accept)(tid, ARG1,ARG2,ARG3); +} +POST(sys_accept) +{ + SysRes r; + vg_assert(SUCCESS); + r = ML_(generic_POST_sys_accept)(tid, VG_(mk_SysRes_Success)(RES), + ARG1,ARG2,ARG3); + SET_STATUS_from_SysRes(r); +} + +PRE(sys_sendto) +{ + *flags |= SfMayBlock; + PRINT("sys_sendto ( %ld, %#lx, %ld, %lu, %#lx, %ld )",ARG1,ARG2,ARG3,ARG4,ARG5,ARG6); + PRE_REG_READ6(long, "sendto", + int, s, const void *, msg, int, len, + unsigned int, flags, + const struct sockaddr *, to, int, tolen); + ML_(generic_PRE_sys_sendto)(tid, ARG1,ARG2,ARG3,ARG4,ARG5,ARG6); +} + +PRE(sys_recvfrom) +{ + *flags |= SfMayBlock; + PRINT("sys_recvfrom ( %ld, %#lx, %ld, %lu, %#lx, %#lx )",ARG1,ARG2,ARG3,ARG4,ARG5,ARG6); + PRE_REG_READ6(long, "recvfrom", + int, s, void *, buf, int, len, unsigned int, flags, + struct sockaddr *, from, int *, fromlen); + ML_(generic_PRE_sys_recvfrom)(tid, ARG1,ARG2,ARG3,ARG4,ARG5,ARG6); +} +POST(sys_recvfrom) +{ + vg_assert(SUCCESS); + ML_(generic_POST_sys_recvfrom)(tid, VG_(mk_SysRes_Success)(RES), + ARG1,ARG2,ARG3,ARG4,ARG5,ARG6); +} + +PRE(sys_sendmsg) +{ + *flags |= SfMayBlock; + PRINT("sys_sendmsg ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "sendmsg", + int, s, const struct msghdr *, msg, int, flags); + ML_(generic_PRE_sys_sendmsg)(tid, "sendmsg", (struct vki_msghdr *)ARG2); +} + +PRE(sys_recvmsg) +{ + *flags |= SfMayBlock; + PRINT("sys_recvmsg ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "recvmsg", int, s, struct msghdr *, msg, int, flags); + ML_(generic_PRE_sys_recvmsg)(tid, "recvmsg", (struct vki_msghdr *)ARG2); +} +POST(sys_recvmsg) +{ + + ML_(generic_POST_sys_recvmsg)(tid, "recvmsg", (struct vki_msghdr *)ARG2, RES); +} + +PRE(sys_shutdown) +{ + *flags |= SfMayBlock; + PRINT("sys_shutdown ( %ld, %ld )",ARG1,ARG2); + PRE_REG_READ2(int, "shutdown", int, s, int, how); +} + +PRE(sys_bind) +{ + PRINT("sys_bind ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "bind", + int, sockfd, struct sockaddr *, my_addr, int, addrlen); + ML_(generic_PRE_sys_bind)(tid, ARG1,ARG2,ARG3); +} + +PRE(sys_listen) +{ + PRINT("sys_listen ( %ld, %ld )",ARG1,ARG2); + PRE_REG_READ2(long, "listen", int, s, int, backlog); +} + +PRE(sys_getsockname) +{ + PRINT("sys_getsockname ( %ld, %#lx, %#lx )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "getsockname", + int, s, struct sockaddr *, name, int *, namelen); + ML_(generic_PRE_sys_getsockname)(tid, ARG1,ARG2,ARG3); +} +POST(sys_getsockname) +{ + vg_assert(SUCCESS); + ML_(generic_POST_sys_getsockname)(tid, VG_(mk_SysRes_Success)(RES), + ARG1,ARG2,ARG3); +} + +PRE(sys_getpeername) +{ + PRINT("sys_getpeername ( %ld, %#lx, %#lx )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "getpeername", + int, s, struct sockaddr *, name, int *, namelen); + ML_(generic_PRE_sys_getpeername)(tid, ARG1,ARG2,ARG3); +} +POST(sys_getpeername) +{ + vg_assert(SUCCESS); + ML_(generic_POST_sys_getpeername)(tid, VG_(mk_SysRes_Success)(RES), + ARG1,ARG2,ARG3); +} + +PRE(sys_socketpair) +{ + PRINT("sys_socketpair ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4); + PRE_REG_READ4(long, "socketpair", + int, d, int, type, int, protocol, int *, sv); + ML_(generic_PRE_sys_socketpair)(tid, ARG1,ARG2,ARG3,ARG4); +} +POST(sys_socketpair) +{ + vg_assert(SUCCESS); + ML_(generic_POST_sys_socketpair)(tid, VG_(mk_SysRes_Success)(RES), + ARG1,ARG2,ARG3,ARG4); +} + +/* --------------------------------------------------------------------- + *mount wrappers + ------------------------------------------------------------------ */ + +PRE(sys_mount) +{ + // Nb: depending on 'flags', the 'type' and 'data' args may be ignored. + // We are conservative and check everything, except the memory pointed to + // by 'data'. + *flags |= SfMayBlock; + PRINT( "sys_mount( %#lx, %#lx, %ld, %#lx )" ,ARG1,ARG2,ARG3,ARG4); + PRE_REG_READ4(long, "mount", + char *, type, char *, path, int, flags, + void *, data); + PRE_MEM_RASCIIZ( "mount(type)", ARG1); + PRE_MEM_RASCIIZ( "mount(path)", ARG2); +} + +PRE(sys_unmount) +{ + PRINT("sys_umount( %#lx, %ld )", ARG1, ARG2); + PRE_REG_READ2(long, "unmount", char *, path, int, flags); + PRE_MEM_RASCIIZ( "unmount(path)", ARG1); +} + +/* --------------------------------------------------------------------- + 16- and 32-bit uid/gid wrappers + ------------------------------------------------------------------ */ + +#if 0 +PRE(sys_setfsuid) +{ + PRINT("sys_setfsuid ( %ld )", ARG1); + PRE_REG_READ1(long, "setfsuid", vki_uid_t, uid); +} + +PRE(sys_setfsgid) +{ + PRINT("sys_setfsgid ( %ld )", ARG1); + PRE_REG_READ1(long, "setfsgid", vki_gid_t, gid); +} +#endif + +PRE(sys_setresuid) +{ + PRINT("sys_setresuid ( %ld, %ld, %ld )", ARG1, ARG2, ARG3); + PRE_REG_READ3(long, "setresuid", + vki_uid_t, ruid, vki_uid_t, euid, vki_uid_t, suid); +} + +PRE(sys_getresuid) +{ + PRINT("sys_getresuid ( %#lx, %#lx, %#lx )", ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "getresuid", + vki_uid_t *, ruid, vki_uid_t *, euid, vki_uid_t *, suid); + PRE_MEM_WRITE( "getresuid(ruid)", ARG1, sizeof(vki_uid_t) ); + PRE_MEM_WRITE( "getresuid(euid)", ARG2, sizeof(vki_uid_t) ); + PRE_MEM_WRITE( "getresuid(suid)", ARG3, sizeof(vki_uid_t) ); +} + +POST(sys_getresuid) +{ + vg_assert(SUCCESS); + if (RES == 0) { + POST_MEM_WRITE( ARG1, sizeof(vki_uid_t) ); + POST_MEM_WRITE( ARG2, sizeof(vki_uid_t) ); + POST_MEM_WRITE( ARG3, sizeof(vki_uid_t) ); + } +} + +PRE(sys_setresgid) +{ + PRINT("sys_setresgid ( %ld, %ld, %ld )", ARG1, ARG2, ARG3); + PRE_REG_READ3(long, "setresgid", + vki_gid_t, rgid, vki_gid_t, egid, vki_gid_t, sgid); +} + +PRE(sys_getresgid) +{ + PRINT("sys_getresgid ( %#lx, %#lx, %#lx )", ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "getresgid", + vki_gid_t *, rgid, vki_gid_t *, egid, vki_gid_t *, sgid); + PRE_MEM_WRITE( "getresgid(rgid)", ARG1, sizeof(vki_gid_t) ); + PRE_MEM_WRITE( "getresgid(egid)", ARG2, sizeof(vki_gid_t) ); + PRE_MEM_WRITE( "getresgid(sgid)", ARG3, sizeof(vki_gid_t) ); +} + +POST(sys_getresgid) +{ + vg_assert(SUCCESS); + if (RES == 0) { + POST_MEM_WRITE( ARG1, sizeof(vki_gid_t) ); + POST_MEM_WRITE( ARG2, sizeof(vki_gid_t) ); + POST_MEM_WRITE( ARG3, sizeof(vki_gid_t) ); + } +} + +/* --------------------------------------------------------------------- + miscellaneous wrappers + ------------------------------------------------------------------ */ + +#if 0 +PRE(sys_exit_group) +{ + ThreadId t; + ThreadState* tst; + + PRINT("exit_group( %ld )", ARG1); + PRE_REG_READ1(void, "exit_group", int, exit_code); + + tst = VG_(get_ThreadState)(tid); + + /* A little complex; find all the threads with the same threadgroup + as this one (including this one), and mark them to exit */ + for (t = 1; t < VG_N_THREADS; t++) { + if ( /* not alive */ + VG_(threads)[t].status == VgTs_Empty + || + /* not our group */ + VG_(threads)[t].os_state.threadgroup != tst->os_state.threadgroup + ) + continue; + + VG_(threads)[t].exitreason = VgSrc_ExitSyscall; + VG_(threads)[t].os_state.exitcode = ARG1; + + if (t != tid) + VG_(get_thread_out_of_syscall)(t); /* unblock it, if blocked */ + } + + /* We have to claim the syscall already succeeded. */ + SET_STATUS_Success(0); +} +#endif + +/* On FreeBSD, if any thread calls exit(2), then they are all shut down, pretty + * much like linux's exit_group(). + */ +PRE(sys_exit) +{ + ThreadId t; + ThreadState* tst; + + PRINT("exit( %ld )", ARG1); + PRE_REG_READ1(void, "exit", int, status); + tst = VG_(get_ThreadState)(tid); + + /* Mark all threads (including this one) to exit. */ + for (t = 1; t < VG_N_THREADS; t++) { + if ( /* not alive */ VG_(threads)[t].status == VgTs_Empty ) + continue; + + VG_(threads)[t].exitreason = VgSrc_ExitThread; + VG_(threads)[t].os_state.exitcode = ARG1; + + if (t != tid) + VG_(get_thread_out_of_syscall)(t); /* unblock it, if blocked */ + } + + /* We have to claim the syscall already succeeded. */ + SET_STATUS_Success(0); +} + + +PRE(sys_getlogin) +{ + PRINT("sys_getlogin ( %#lx, %ld )",ARG1,ARG2); + PRE_REG_READ2(long, "getlogin", + char *, buf, int, len); + PRE_MEM_WRITE( "getlogin(buf, len)", ARG1, ARG2 ); +} +POST(sys_getlogin) +{ + if (ARG1 != 0) { + POST_MEM_WRITE( ARG1, ARG2 ); + } +} +PRE(sys_setlogin) +{ + PRINT("sys_setlogin ( %#lx )",ARG1); + PRE_REG_READ1(long, "setlogin", char *, buf); + PRE_MEM_RASCIIZ( "setlogin(buf)", ARG1 ); +} +PRE(sys_mkfifo) +{ + PRINT("sys_mkfifo ( %#lx(%s), 0x%lx, 0x%lx )", ARG1, (char *)ARG1, ARG2, ARG3 ); + PRE_REG_READ2(long, "mkfifo", const char *, pathname, int, mode); + PRE_MEM_RASCIIZ( "mkfifo(pathname)", ARG1 ); +} + +/* int quotactl(const char *path, int cmd, int id, void *addr); */ + +PRE(sys_quotactl) +{ + PRINT("sys_quotactl (%#lx, %ld, %ld, %#lx )", ARG1,ARG2,ARG3, ARG4); + PRE_REG_READ4(long, "quotactl", + const char *, path, int, cmd, int, id, + void *, addr); + PRE_MEM_RASCIIZ( "quotactl(path)", ARG1 ); +} + +/* int getdomainname(char *domainname, int len); */ +PRE(sys_getdomainname) +{ + PRINT("sys_getdomainname ( %#lx, %ld )",ARG1,ARG2); + PRE_REG_READ2(long, "getdomainname", + char *, buf, int, len); + PRE_MEM_WRITE( "getdomainname(buf, len)", ARG1, ARG2 ); +} +POST(sys_getdomainname) +{ + if (ARG1 != 0) { + POST_MEM_WRITE( ARG1, ARG2 ); + } +} +/* int setdomainname(char *domainname, int len); */ +PRE(sys_setdomainname) +{ + PRINT("sys_setdomainname ( %#lx )",ARG1); + PRE_REG_READ1(long, "setdomainname", char *, buf); + PRE_MEM_RASCIIZ( "setdomainname(buf)", ARG1 ); +} + +PRE(sys_uname) +{ + PRINT("sys_uname ( %#lx )", ARG1); + PRE_REG_READ1(long, "uname", struct utsname *, buf); + PRE_MEM_WRITE( "uname(buf)", ARG1, sizeof(struct vki_utsname) ); +} + +POST(sys_uname) +{ + if (ARG1 != 0) { + POST_MEM_WRITE( ARG1, sizeof(struct vki_utsname) ); + } +} + +PRE(sys_lstat) +{ + PRINT("sys_lstat ( %#lx(%s), %#lx )",ARG1,(char *)ARG1,ARG2); + PRE_REG_READ2(long, "lstat", char *, file_name, struct stat *, buf); + PRE_MEM_RASCIIZ( "lstat(file_name)", ARG1 ); + PRE_MEM_WRITE( "lstat(buf)", ARG2, sizeof(struct vki_stat) ); +} + +POST(sys_lstat) +{ + vg_assert(SUCCESS); + if (RES == 0) { + POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) ); + } +} + +PRE(sys_stat) +{ + PRINT("sys_stat ( %#lx(%s), %#lx )",ARG1,(char *)ARG1,ARG2); + PRE_REG_READ2(long, "stat", char *, file_name, struct stat *, buf); + PRE_MEM_RASCIIZ( "stat(file_name)", ARG1 ); + PRE_MEM_WRITE( "stat(buf)", ARG2, sizeof(struct vki_stat) ); +} + +POST(sys_stat) +{ + POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) ); +} + +PRE(sys_fstat) +{ + PRINT("sys_fstat ( %ld, %#lx )",ARG1,ARG2); + PRE_REG_READ2(long, "fstat", unsigned long, fd, struct stat *, buf); + PRE_MEM_WRITE( "fstat(buf)", ARG2, sizeof(struct vki_stat) ); +} + +POST(sys_fstat) +{ + POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) ); +} + +PRE(sys_pathconf) +{ + PRINT("sys_pathconf ( %#lx(%s), %ld )",ARG1,(char *)ARG1,ARG2); + PRE_REG_READ2(long, "pathconf", char *, file_name, int, name); + PRE_MEM_RASCIIZ( "pathconf(file_name)", ARG1 ); +} + +PRE(sys_fpathconf) +{ + PRINT("sys_fpathconf ( %ld, %ld )",ARG1,ARG2); + PRE_REG_READ2(long, "fpathconf", int, fd, int, name); +} + +PRE(sys_lchmod) +{ + PRINT("sys_lchmod ( %#lx(%s), %ld )", ARG1,(char *)ARG1,ARG2); + PRE_REG_READ2(long, "lchmod", const char *, path, vki_mode_t, mode); + PRE_MEM_RASCIIZ( "lchmod(path)", ARG1 ); +} + +PRE(sys_issetugid) +{ + PRINT("sys_issetugid ()"); + PRE_REG_READ0(long, "issetugid"); +} + +PRE(sys_revoke) +{ + PRINT("sys_vhangup ( )"); + PRE_REG_READ0(long, "vhangup"); +} +PRE(sys_undelete) +{ + *flags |= SfMayBlock; + PRINT("sys_undelete ( %#lx(%s) )", ARG1,(char *)ARG1); + PRE_REG_READ1(long, "undelete", const char *, pathname); + PRE_MEM_RASCIIZ( "undelete(pathname)", ARG1 ); +} +PRE(sys_yield) +{ + *flags |= SfMayBlock; + PRINT("yield()"); + PRE_REG_READ0(long, "yield"); +} + +PRE(sys_sched_yield) +{ + *flags |= SfMayBlock; + PRINT("sched_yield()"); +} + +#if 0 +PRE(sys_sysinfo) +{ + PRINT("sys_sysinfo ( %#lx )",ARG1); + PRE_REG_READ1(long, "sysinfo", struct sysinfo *, info); + PRE_MEM_WRITE( "sysinfo(info)", ARG1, sizeof(struct vki_sysinfo) ); +} + +POST(sys_sysinfo) +{ + POST_MEM_WRITE( ARG1, sizeof(struct vki_sysinfo) ); +} +#endif + +/* int __sysctl(int *name, u_int namelen, void *old, size_t *oldlenp, void *new, size_t newlen); */ +/* ARG1 ARG2 ARG3 ARG4 ARG5 ARG6 */ + +PRE(sys___sysctl) +{ + PRINT("sys_sysctl ( %#lx, %ld, %#lx, %#lx, %#lx, %ld )", ARG1,ARG2,ARG3,ARG4,ARG5,ARG6 ); + PRE_REG_READ6(long, "__sysctl", int *, name, unsigned int, namelen, void *, old, + vki_size_t *, oldlenp, void *, new, vki_size_t, newlen); + PRE_MEM_READ("sysctl(name)", ARG1, ARG2 * sizeof(int)); + if (ARG5 != (UWord)NULL) + PRE_MEM_READ("sysctl(new)", (Addr)ARG5, ARG6); + if (ARG4 != (UWord)NULL) { + if (ARG3 != (UWord)NULL) { + PRE_MEM_READ("sysctl(oldlenp)", (Addr)ARG4, sizeof(vki_size_t)); + PRE_MEM_WRITE("sysctl(oldval)", (Addr)ARG3, *(vki_size_t *)ARG4); + } + PRE_MEM_WRITE("sysctl(oldlenp)", (Addr)ARG4, sizeof(vki_size_t)); + } +} +POST(sys___sysctl) +{ + if (ARG4 != (UWord)NULL) { + POST_MEM_WRITE((Addr)ARG4, sizeof(vki_size_t)); + if (ARG3 != (UWord)NULL) + POST_MEM_WRITE((Addr)ARG3, *(vki_size_t *)ARG4); + } +} + +PRE(sys_sendfile) +{ + *flags |= SfMayBlock; +#if defined(VGP_x86_freebsd) + PRINT("sys_sendfile ( %ld, %ld, %llu, %ld, %#lx, %#lx, %lu )", ARG1,ARG2,LOHI64(ARG3,ARG4),ARG5,ARG6,ARG7,ARG8); +#elif defined(VGP_amd64_freebsd) + PRINT("sys_sendfile ( %ld, %ld, %lu, %ld, %#lx, %#lx, %lu )", ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7); +#else +# error Unknown platform +#endif + PRE_REG_READ7(ssize_t, "sendfile", + int, fd, int, s, unsigned int, offset_low, + unsigned int, offset_high, + void *, hdtr, vki_off_t *, sbytes, int, flags); + if (ARG3 != 0) + PRE_MEM_WRITE( "sendfile(offset)", ARG3, sizeof(vki_off_t) ); +} +POST(sys_sendfile) +{ + if (ARG3 != 0 ) { + POST_MEM_WRITE( ARG3, sizeof( vki_off_t ) ); + } +} + +/* int getdirentries(int fd, char *buf, u_int count, long *basep); */ +PRE(sys_getdirentries) +{ + *flags |= SfMayBlock; + PRINT("sys_getdents ( %ld, %#lx, %ld )", ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "getdirentries", + unsigned int, fd, struct dirent *, dirp, + unsigned int, count); + PRE_MEM_WRITE( "getdirentries(dirp)", ARG2, ARG3 ); +} + +POST(sys_getdirentries) +{ + vg_assert(SUCCESS); + if (RES > 0) { + POST_MEM_WRITE( ARG2, RES ); + if ( ARG4 != 0 ) + POST_MEM_WRITE( ARG4, sizeof (long)); + } +} + +PRE(sys_seteuid) +{ + PRINT("sys_seteuid ( %ld )", ARG1); + PRE_REG_READ1(long, "seteuid", vki_uid_t, uid); +} + +PRE(sys_setegid) +{ + PRINT("sys_setegid ( %ld )", ARG1); + PRE_REG_READ1(long, "setegid", vki_gid_t, gid); +} + +PRE(sys_lutimes) +{ + PRINT("sys_lutimes ( %#lx(%s), %#lx )", ARG1,(char *)ARG1,ARG2); + PRE_REG_READ2(long, "lutimes", char *, filename, struct timeval *, tvp); + PRE_MEM_RASCIIZ( "lutimes(filename)", ARG1 ); + if (ARG2 != 0) + PRE_MEM_READ( "lutimes(tvp)", ARG2, sizeof(struct vki_timeval) ); +} + +PRE(sys_futimes) +{ + PRINT("sys_lutimes ( %ld, %#lx )", ARG1,ARG2); + PRE_REG_READ2(long, "futimes", int, fd, struct timeval *, tvp); + if (ARG2 != 0) + PRE_MEM_READ( "futimes(tvp)", ARG2, sizeof(struct vki_timeval) ); +} + +PRE(sys_utrace) +{ + PRINT("sys_utrace ( %#lx, %lu )", ARG1, ARG2); + PRE_REG_READ2(long, "utrace", const void *, buf, vki_size_t, len); + PRE_MEM_READ( "utrace(buf,len)", ARG2, ARG3 ); +} + +PRE(sys_getdtablesize) +{ + PRINT("sys_getdtablesize ( )"); + PRE_REG_READ0(long, "getdtablesize"); +} + +PRE(sys_kqueue) +{ + PRINT("sys_kqueue ()"); +} +POST(sys_kqueue) +{ + if (!ML_(fd_allowed)(RES, "kqueue", tid, True)) { + VG_(close)(RES); + SET_STATUS_Failure( VKI_EMFILE ); + } else { + if (VG_(clo_track_fds)) { + ML_(record_fd_open_nameless)(tid, RES); + } + } +} + +PRE(sys_kevent) +{ + /* struct kevent { + uintptr_t ident; -- identifier for this event + short filter; -- filter for event + u_short flags; -- action flags for kqueue + u_int fflags; -- filter flag value + intptr_t data; -- filter data value + void *udata; -- opaque user data identifier + }; + int kevent(int kq, const struct kevent *changelist, int nchanges, + struct kevent *eventlist, int nevents, + const struct timespec *timeout); + */ + *flags |= SfMayBlock; + PRINT("sys_kevent ( %ld, %#lx, %ld, %#lx, %ld, %#lx )\n", ARG1,ARG2,ARG3,ARG4,ARG5,ARG6); + PRE_REG_READ6(long, "kevent", + int, fd, struct vki_kevent *, newev, int, num_newev, + struct vki_kevent *, ret_ev, int, num_retev, + struct timespec *, timeout); + if (ARG2 != 0 && ARG3 != 0) + PRE_MEM_READ( "kevent(changeevent)", ARG2, sizeof(struct vki_kevent)*ARG3 ); + if (ARG4 != 0 && ARG5 != 0) + PRE_MEM_WRITE( "kevent(events)", ARG4, sizeof(struct vki_kevent)*ARG5); + if (ARG6 != 0) + PRE_MEM_READ( "kevent(timeout)", + ARG6, sizeof(struct vki_timespec)); +} + +POST(sys_kevent) +{ + vg_assert(SUCCESS); + if (RES > 0) { + if (ARG4 != 0) + POST_MEM_WRITE( ARG4, sizeof(struct vki_kevent)*RES) ; + } +} + +PRE(sys___getcwd) +{ + PRINT("sys___getcwd ( %#lx, %lu )", ARG1,ARG2); + PRE_REG_READ2(long, "__getcwd", char *, buf, unsigned int, size); + PRE_MEM_WRITE( "__getcwd(buf)", ARG1, ARG2 ); +} + +POST(sys___getcwd) +{ + vg_assert(SUCCESS); + if (RES == 0) { + // QQQ it is unclear if this is legal or not, but the + // QQQ kernel just wrote it there... + // QQQ Why oh why didn't phk return the length from __getcwd()? + UInt len = VG_(strlen) ( (char *)ARG1 ) + 1; + POST_MEM_WRITE( ARG1, len ); + } +} + +// getfsstat() takes a length in bytes, but returns the number of structures +// returned, not a length. +PRE(sys_getfsstat4) +{ + PRINT("sys_getfsstat ( %#lx, %ld, %ld )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "getfsstat", struct vki_statfs4 *, buf, long, len, int, flags); + PRE_MEM_WRITE( "getfsstat(buf)", ARG1, ARG2 ); +} +POST(sys_getfsstat4) +{ + vg_assert(SUCCESS); + if (RES > 0) { + POST_MEM_WRITE( ARG1, RES * sizeof(struct vki_statfs4) ); + } +} + +PRE(sys_getfsstat) +{ + PRINT("sys_getfsstat ( %#lx, %ld, %ld )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "getfsstat", struct vki_statfs *, buf, long, len, int, flags); + PRE_MEM_WRITE( "getfsstat(buf)", ARG1, ARG2 ); +} +POST(sys_getfsstat) +{ + vg_assert(SUCCESS); + if (RES > 0) { + POST_MEM_WRITE( ARG1, RES * sizeof(struct vki_statfs) ); + } +} + +PRE(sys_fhopen) +{ + PRINT("sys_open ( %#lx, %ld )",ARG1,ARG2); + PRE_REG_READ2(long, "open", + struct fhandle *, fhp, int, flags); + PRE_MEM_READ( "fhopen(fhp)", ARG1, sizeof(struct vki_fhandle) ); + + /* Otherwise handle normally */ + *flags |= SfMayBlock; +} + +POST(sys_fhopen) +{ + vg_assert(SUCCESS); + if (!ML_(fd_allowed)(RES, "fhopen", tid, True)) { + VG_(close)(RES); + SET_STATUS_Failure( VKI_EMFILE ); + } else { + if (VG_(clo_track_fds)) + ML_(record_fd_open_nameless)(tid, RES); + } +} + +PRE(sys_fhstat) +{ + PRINT("sys_fhstat ( %#lx, %#lx )",ARG1,ARG2); + PRE_REG_READ2(long, "fhstat", struct fhandle *, fhp, struct stat *, buf); + PRE_MEM_READ( "fhstat(fhp)", ARG1, sizeof(struct vki_fhandle) ); + PRE_MEM_WRITE( "fhstat(buf)", ARG2, sizeof(struct vki_stat) ); +} + +POST(sys_fhstat) +{ + POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) ); +} + +PRE(sys_fhstatfs) +{ + PRINT("sys_fstatfs ( %#lx, %#lx )",ARG1,ARG2); + PRE_REG_READ2(long, "fhstatfs", + struct fhandle *, fhp, struct statfs *, buf); + PRE_MEM_READ( "fhstatfs(fhp)", ARG1, sizeof(struct vki_fhandle) ); + PRE_MEM_WRITE( "fhstatfs(buf)", ARG2, sizeof(struct vki_statfs) ); +} + +POST(sys_fhstatfs) +{ + POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs) ); +} + +PRE(sys_fhstatfs6) +{ + PRINT("sys_fstatfs6 ( %#lx, %#lx )",ARG1,ARG2); + PRE_REG_READ2(long, "fhstatfs6", + struct fhandle *, fhp, struct statfs *, buf); + PRE_MEM_READ( "fhstatfs6(fhp)", ARG1, sizeof(struct vki_fhandle) ); + PRE_MEM_WRITE( "fhstatfs6(buf)", ARG2, sizeof(struct vki_statfs6) ); +} + +POST(sys_fhstatfs6) +{ + POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs6) ); +} + +PRE(sys_fstatfs6) +{ + PRINT("sys_fstatfs6 ( %ld, %#lx )",ARG1,ARG2); + PRE_REG_READ2(long, "fstatfs6", + unsigned int, fd, struct statfs *, buf); + PRE_MEM_WRITE( "fstatfs6(buf)", ARG2, sizeof(struct vki_statfs6) ); +} + +POST(sys_fstatfs6) +{ + POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs6) ); +} + +PRE(sys_statfs6) +{ + PRINT("sys_statfs6 ( %#lx(%s), %#lx )",ARG1,(char *)ARG1,ARG2); + PRE_REG_READ2(long, "statfs6", const char *, path, struct statfs *, buf); + PRE_MEM_RASCIIZ( "statfs6(path)", ARG1 ); + PRE_MEM_WRITE( "statfs(buf)", ARG2, sizeof(struct vki_statfs6) ); +} +POST(sys_statfs6) +{ + POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs6) ); +} + + +#if 0 +/* --------------------------------------------------------------------- + aio_* wrappers + ------------------------------------------------------------------ */ + +// Nb: this wrapper has to pad/unpad memory around the syscall itself, +// and this allows us to control exactly the code that gets run while +// the padding is in place. + +PRE(sys_io_setup) +{ + PRINT("sys_io_setup ( %lu, %#lx )", ARG1,ARG2); + PRE_REG_READ2(long, "io_setup", + unsigned, nr_events, vki_aio_context_t *, ctxp); + PRE_MEM_WRITE( "io_setup(ctxp)", ARG2, sizeof(vki_aio_context_t) ); +} + +POST(sys_io_setup) +{ + SizeT size; + struct vki_aio_ring *r; + + size = VG_PGROUNDUP(sizeof(struct vki_aio_ring) + + ARG1*sizeof(struct vki_io_event)); + r = *(struct vki_aio_ring **)ARG2; + vg_assert(ML_(valid_client_addr)((Addr)r, size, tid, "io_setup")); + + ML_(notify_aspacem_and_tool_of_mmap)( (Addr)r, size, + VKI_PROT_READ | VKI_PROT_WRITE, + VKI_MAP_ANONYMOUS, -1, 0 ); + + POST_MEM_WRITE( ARG2, sizeof(vki_aio_context_t) ); +} + +// Nb: This wrapper is "Special" because we need 'size' to do the unmap +// after the syscall. We must get 'size' from the aio_ring structure, +// before the syscall, while the aio_ring structure still exists. (And we +// know that we must look at the aio_ring structure because Tom inspected the +// kernel and glibc sources to see what they do, yuk.) +// +// XXX This segment can be implicitly unmapped when aio +// file-descriptors are closed... +PRE(sys_io_destroy) +{ + struct vki_aio_ring *r; + SizeT size; + + PRINT("sys_io_destroy ( %llu )", (ULong)ARG1); + PRE_REG_READ1(long, "io_destroy", vki_aio_context_t, ctx); + + // If we are going to seg fault (due to a bogus ARG1) do it as late as + // possible... + r = (struct vki_aio_ring *)ARG1; + size = VG_PGROUNDUP(sizeof(struct vki_aio_ring) + + r->nr*sizeof(struct vki_io_event)); + + SET_STATUS_from_SysRes( VG_(do_syscall1)(SYSNO, ARG1) ); + + if (SUCCESS && RES == 0) { + Bool d = VG_(am_notify_munmap)( ARG1, size ); + VG_TRACK( die_mem_munmap, ARG1, size ); + if (d) + VG_(discard_translations)( (Addr64)ARG1, (ULong)size, + "PRE(sys_io_destroy)" ); + } +} + +PRE(sys_io_getevents) +{ + *flags |= SfMayBlock; + PRINT("sys_io_getevents ( %llu, %lld, %lld, %#lx, %#lx )", + (ULong)ARG1,(Long)ARG2,(Long)ARG3,ARG4,ARG5); + PRE_REG_READ5(long, "io_getevents", + vki_aio_context_t, ctx_id, long, min_nr, long, nr, + struct io_event *, events, + struct timespec *, timeout); + if (ARG3 > 0) + PRE_MEM_WRITE( "io_getevents(events)", + ARG4, sizeof(struct vki_io_event)*ARG3 ); + if (ARG5 != 0) + PRE_MEM_READ( "io_getevents(timeout)", + ARG5, sizeof(struct vki_timespec)); +} +POST(sys_io_getevents) +{ + Int i; + vg_assert(SUCCESS); + if (RES > 0) { + POST_MEM_WRITE( ARG4, sizeof(struct vki_io_event)*RES ); + for (i = 0; i < RES; i++) { + const struct vki_io_event *vev = ((struct vki_io_event *)ARG4) + i; + const struct vki_iocb *cb = (struct vki_iocb *)(Addr)vev->obj; + + switch (cb->aio_lio_opcode) { + case VKI_IOCB_CMD_PREAD: + if (vev->result > 0) + POST_MEM_WRITE( cb->aio_buf, vev->result ); + break; + + case VKI_IOCB_CMD_PWRITE: + break; + + default: + VG_(message)(Vg_DebugMsg, + "Warning: unhandled io_getevents opcode: %u\n", + cb->aio_lio_opcode); + break; + } + } + } +} + +PRE(sys_io_submit) +{ + Int i; + + PRINT("sys_io_submit ( %llu, %ld, %#lx )", (ULong)ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "io_submit", + vki_aio_context_t, ctx_id, long, nr, + struct iocb **, iocbpp); + PRE_MEM_READ( "io_submit(iocbpp)", ARG3, ARG2*sizeof(struct vki_iocb *) ); + if (ARG3 != 0) { + for (i = 0; i < ARG2; i++) { + struct vki_iocb *cb = ((struct vki_iocb **)ARG3)[i]; + PRE_MEM_READ( "io_submit(iocb)", (Addr)cb, sizeof(struct vki_iocb) ); + switch (cb->aio_lio_opcode) { + case VKI_IOCB_CMD_PREAD: + PRE_MEM_WRITE( "io_submit(PREAD)", cb->aio_buf, cb->aio_nbytes ); + break; + + case VKI_IOCB_CMD_PWRITE: + PRE_MEM_READ( "io_submit(PWRITE)", cb->aio_buf, cb->aio_nbytes ); + break; + + default: + VG_(message)(Vg_DebugMsg,"Warning: unhandled io_submit opcode: %u\n", + cb->aio_lio_opcode); + break; + } + } + } +} + +PRE(sys_io_cancel) +{ + PRINT("sys_io_cancel ( %llu, %#lx, %#lx )", (ULong)ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "io_cancel", + vki_aio_context_t, ctx_id, struct iocb *, iocb, + struct io_event *, result); + PRE_MEM_READ( "io_cancel(iocb)", ARG2, sizeof(struct vki_iocb) ); + PRE_MEM_WRITE( "io_cancel(result)", ARG3, sizeof(struct vki_io_event) ); +} +POST(sys_io_cancel) +{ + POST_MEM_WRITE( ARG3, sizeof(struct vki_io_event) ); +} + +/* --------------------------------------------------------------------- + inotify_* wrappers + ------------------------------------------------------------------ */ + +PRE(sys_inotify_init) +{ + PRINT("sys_inotify_init ( )"); + PRE_REG_READ0(long, "inotify_init"); +} +POST(sys_inotify_init) +{ + vg_assert(SUCCESS); + if (!ML_(fd_allowed)(RES, "inotify_init", tid, True)) { + VG_(close)(RES); + SET_STATUS_Failure( VKI_EMFILE ); + } else { + if (VG_(clo_track_fds)) + ML_(record_fd_open_nameless) (tid, RES); + } +} + +PRE(sys_inotify_add_watch) +{ + PRINT( "sys_inotify_add_watch ( %ld, %#lx, %lx )", ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "inotify_add_watch", int, fd, char *, path, int, mask); + PRE_MEM_RASCIIZ( "inotify_add_watch(path)", ARG2 ); +} + +PRE(sys_inotify_rm_watch) +{ + PRINT( "sys_inotify_rm_watch ( %ld, %lx )", ARG1,ARG2); + PRE_REG_READ2(long, "inotify_rm_watch", int, fd, int, wd); +} + +/* --------------------------------------------------------------------- + mq_* wrappers + ------------------------------------------------------------------ */ + +PRE(sys_mq_open) +{ + PRINT("sys_mq_open( %#lx(%s), %ld, %lld, %#lx )", + ARG1,(char *)ARG1,ARG2,(ULong)ARG3,ARG4); + PRE_REG_READ4(long, "mq_open", + const char *, name, int, oflag, vki_mode_t, mode, + struct mq_attr *, attr); + PRE_MEM_RASCIIZ( "mq_open(name)", ARG1 ); + if ((ARG2 & VKI_O_CREAT) != 0 && ARG4 != 0) { + const struct vki_mq_attr *attr = (struct vki_mq_attr *)ARG4; + PRE_MEM_READ( "mq_open(attr->mq_maxmsg)", + (Addr)&attr->mq_maxmsg, sizeof(attr->mq_maxmsg) ); + PRE_MEM_READ( "mq_open(attr->mq_msgsize)", + (Addr)&attr->mq_msgsize, sizeof(attr->mq_msgsize) ); + } +} +POST(sys_mq_open) +{ + vg_assert(SUCCESS); + if (!ML_(fd_allowed)(RES, "mq_open", tid, True)) { + VG_(close)(RES); + SET_STATUS_Failure( VKI_EMFILE ); + } else { + if (VG_(clo_track_fds)) + ML_(record_fd_open_with_given_name)(tid, RES, (Char*)ARG1); + } +} + +PRE(sys_mq_unlink) +{ + PRINT("sys_mq_unlink ( %#lx(%s) )", ARG1,(char *)ARG1); + PRE_REG_READ1(long, "mq_unlink", const char *, name); + PRE_MEM_RASCIIZ( "mq_unlink(name)", ARG1 ); +} + +PRE(sys_mq_timedsend) +{ + *flags |= SfMayBlock; + PRINT("sys_mq_timedsend ( %ld, %#lx, %llu, %ld, %#lx )", + ARG1,ARG2,(ULong)ARG3,ARG4,ARG5); + PRE_REG_READ5(long, "mq_timedsend", + vki_mqd_t, mqdes, const char *, msg_ptr, vki_size_t, msg_len, + unsigned int, msg_prio, const struct timespec *, abs_timeout); + if (!ML_(fd_allowed)(ARG1, "mq_timedsend", tid, False)) { + SET_STATUS_Failure( VKI_EBADF ); + } else { + PRE_MEM_READ( "mq_timedsend(msg_ptr)", ARG2, ARG3 ); + if (ARG5 != 0) + PRE_MEM_READ( "mq_timedsend(abs_timeout)", ARG5, + sizeof(struct vki_timespec) ); + } +} + +PRE(sys_mq_timedreceive) +{ + *flags |= SfMayBlock; + PRINT("sys_mq_timedreceive( %ld, %#lx, %llu, %#lx, %#lx )", + ARG1,ARG2,(ULong)ARG3,ARG4,ARG5); + PRE_REG_READ5(ssize_t, "mq_timedreceive", + vki_mqd_t, mqdes, char *, msg_ptr, vki_size_t, msg_len, + unsigned int *, msg_prio, + const struct timespec *, abs_timeout); + if (!ML_(fd_allowed)(ARG1, "mq_timedreceive", tid, False)) { + SET_STATUS_Failure( VKI_EBADF ); + } else { + PRE_MEM_WRITE( "mq_timedreceive(msg_ptr)", ARG2, ARG3 ); + if (ARG4 != 0) + PRE_MEM_WRITE( "mq_timedreceive(msg_prio)", + ARG4, sizeof(unsigned int) ); + if (ARG5 != 0) + PRE_MEM_READ( "mq_timedreceive(abs_timeout)", + ARG5, sizeof(struct vki_timespec) ); + } +} +POST(sys_mq_timedreceive) +{ + POST_MEM_WRITE( ARG2, ARG3 ); + if (ARG4 != 0) + POST_MEM_WRITE( ARG4, sizeof(unsigned int) ); +} + +PRE(sys_mq_notify) +{ + PRINT("sys_mq_notify( %ld, %#lx )", ARG1,ARG2 ); + PRE_REG_READ2(long, "mq_notify", + vki_mqd_t, mqdes, const struct sigevent *, notification); + if (!ML_(fd_allowed)(ARG1, "mq_notify", tid, False)) + SET_STATUS_Failure( VKI_EBADF ); + else if (ARG2 != 0) + PRE_MEM_READ( "mq_notify(notification)", + ARG2, sizeof(struct vki_sigevent) ); +} + +PRE(sys_mq_getsetattr) +{ + PRINT("sys_mq_getsetattr( %ld, %#lx, %#lx )", ARG1,ARG2,ARG3 ); + PRE_REG_READ3(long, "mq_getsetattr", + vki_mqd_t, mqdes, const struct mq_attr *, mqstat, + struct mq_attr *, omqstat); + if (!ML_(fd_allowed)(ARG1, "mq_getsetattr", tid, False)) { + SET_STATUS_Failure( VKI_EBADF ); + } else { + if (ARG2 != 0) { + const struct vki_mq_attr *attr = (struct vki_mq_attr *)ARG2; + PRE_MEM_READ( "mq_getsetattr(mqstat->mq_flags)", + (Addr)&attr->mq_flags, sizeof(attr->mq_flags) ); + } + if (ARG3 != 0) + PRE_MEM_WRITE( "mq_getsetattr(omqstat)", ARG3, + sizeof(struct vki_mq_attr) ); + } +} +POST(sys_mq_getsetattr) +{ + if (ARG3 != 0) + POST_MEM_WRITE( ARG3, sizeof(struct vki_mq_attr) ); +} + +#endif + +/* --------------------------------------------------------------------- + clock_* wrappers + ------------------------------------------------------------------ */ + +PRE(sys_clock_settime) +{ + PRINT("sys_clock_settime( %ld, %#lx )", ARG1,ARG2); + PRE_REG_READ2(long, "clock_settime", + vki_clockid_t, clk_id, const struct timespec *, tp); + PRE_MEM_READ( "clock_settime(tp)", ARG2, sizeof(struct vki_timespec) ); +} + +PRE(sys_clock_gettime) +{ + PRINT("sys_clock_gettime( %ld, %#lx )" , ARG1,ARG2); + PRE_REG_READ2(long, "clock_gettime", + vki_clockid_t, clk_id, struct timespec *, tp); + PRE_MEM_WRITE( "clock_gettime(tp)", ARG2, sizeof(struct vki_timespec) ); +} +POST(sys_clock_gettime) +{ + POST_MEM_WRITE( ARG2, sizeof(struct vki_timespec) ); +} + +PRE(sys_clock_getres) +{ + PRINT("sys_clock_getres( %ld, %#lx )" , ARG1,ARG2); + // Nb: we can't use "RES" as the param name because that's a macro + // defined above! + PRE_REG_READ2(long, "clock_getres", + vki_clockid_t, clk_id, struct timespec *, res); + if (ARG2 != 0) + PRE_MEM_WRITE( "clock_getres(res)", ARG2, sizeof(struct vki_timespec) ); +} +POST(sys_clock_getres) +{ + if (ARG2 != 0) + POST_MEM_WRITE( ARG2, sizeof(struct vki_timespec) ); +} + +#if 0 +PRE(sys_clock_nanosleep) +{ + *flags |= SfMayBlock|SfPostOnFail; + PRINT("sys_clock_nanosleep( %ld, %ld, %#lx, %#lx )", ARG1,ARG2,ARG3,ARG4); + PRE_REG_READ4(int32_t, "clock_nanosleep", + vki_clockid_t, clkid, int, flags, + const struct timespec *, rqtp, struct timespec *, rmtp); + PRE_MEM_READ( "clock_nanosleep(rqtp)", ARG3, sizeof(struct vki_timespec) ); + if (ARG4 != 0) + PRE_MEM_WRITE( "clock_nanosleep(rmtp)", ARG4, sizeof(struct vki_timespec) ); +} +POST(sys_clock_nanosleep) +{ + if (ARG4 != 0 && FAILURE && RES_unchecked == VKI_EINTR) + POST_MEM_WRITE( ARG4, sizeof(struct vki_timespec) ); +} + +/* --------------------------------------------------------------------- + timer_* wrappers + ------------------------------------------------------------------ */ + +PRE(sys_timer_create) +{ + PRINT("sys_timer_create( %ld, %#lx, %#lx )", ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "timer_create", + vki_clockid_t, clockid, struct sigevent *, evp, + vki_timer_t *, timerid); + if (ARG2 != 0) + PRE_MEM_READ( "timer_create(evp)", ARG2, sizeof(struct vki_sigevent) ); + PRE_MEM_WRITE( "timer_create(timerid)", ARG3, sizeof(vki_timer_t) ); +} +POST(sys_timer_create) +{ + POST_MEM_WRITE( ARG3, sizeof(vki_timer_t) ); +} + +PRE(sys_timer_settime) +{ + PRINT("sys_timer_settime( %lld, %ld, %#lx, %#lx )", (ULong)ARG1,ARG2,ARG3,ARG4); + PRE_REG_READ4(long, "timer_settime", + vki_timer_t, timerid, int, flags, + const struct itimerspec *, value, + struct itimerspec *, ovalue); + PRE_MEM_READ( "timer_settime(value)", ARG3, + sizeof(struct vki_itimerspec) ); + if (ARG4 != 0) + PRE_MEM_WRITE( "timer_settime(ovalue)", ARG4, + sizeof(struct vki_itimerspec) ); +} +POST(sys_timer_settime) +{ + if (ARG4 != 0) + POST_MEM_WRITE( ARG4, sizeof(struct vki_itimerspec) ); +} + +PRE(sys_timer_gettime) +{ + PRINT("sys_timer_gettime( %lld, %#lx )", (ULong)ARG1,ARG2); + PRE_REG_READ2(long, "timer_gettime", + vki_timer_t, timerid, struct itimerspec *, value); + PRE_MEM_WRITE( "timer_gettime(value)", ARG2, + sizeof(struct vki_itimerspec)); +} +POST(sys_timer_gettime) +{ + POST_MEM_WRITE( ARG2, sizeof(struct vki_itimerspec) ); +} + +PRE(sys_timer_getoverrun) +{ + PRINT("sys_timer_getoverrun( %#lx )", ARG1); + PRE_REG_READ1(long, "timer_getoverrun", vki_timer_t, timerid); +} + +PRE(sys_timer_delete) +{ + PRINT("sys_timer_delete( %#lx )", ARG1); + PRE_REG_READ1(long, "timer_delete", vki_timer_t, timerid); +} + +/* --------------------------------------------------------------------- + sched_* wrappers + ------------------------------------------------------------------ */ + +PRE(sys_sched_setparam) +{ + PRINT("sched_setparam ( %ld, %#lx )", ARG1, ARG2 ); + PRE_REG_READ2(long, "sched_setparam", + vki_pid_t, pid, struct sched_param *, p); + PRE_MEM_READ( "sched_setparam(p)", ARG2, sizeof(struct vki_sched_param) ); +} +POST(sys_sched_setparam) +{ + POST_MEM_WRITE( ARG2, sizeof(struct vki_sched_param) ); +} + +PRE(sys_sched_getparam) +{ + PRINT("sched_getparam ( %ld, %#lx )", ARG1, ARG2 ); + PRE_REG_READ2(long, "sched_getparam", + vki_pid_t, pid, struct sched_param *, p); + PRE_MEM_WRITE( "sched_getparam(p)", ARG2, sizeof(struct vki_sched_param) ); +} +POST(sys_sched_getparam) +{ + POST_MEM_WRITE( ARG2, sizeof(struct vki_sched_param) ); +} + +PRE(sys_sched_getscheduler) +{ + PRINT("sys_sched_getscheduler ( %ld )", ARG1); + PRE_REG_READ1(long, "sched_getscheduler", vki_pid_t, pid); +} + +PRE(sys_sched_setscheduler) +{ + PRINT("sys_sched_setscheduler ( %ld, %ld, %#lx )", ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "sched_setscheduler", + vki_pid_t, pid, int, policy, struct sched_param *, p); + if (ARG3 != 0) + PRE_MEM_READ( "sched_setscheduler(p)", + ARG3, sizeof(struct vki_sched_param)); +} + +PRE(sys_sched_yield) +{ + *flags |= SfMayBlock; + PRINT("sched_yield()"); + PRE_REG_READ0(long, "sched_yield"); +} +#endif + +PRE(sys_sched_get_priority_max) +{ + PRINT("sched_get_priority_max ( %ld )", ARG1); + PRE_REG_READ1(long, "sched_get_priority_max", int, policy); +} + +PRE(sys_sched_get_priority_min) +{ + PRINT("sched_get_priority_min ( %ld )", ARG1); + PRE_REG_READ1(long, "sched_get_priority_min", int, policy); +} + +#if 0 +PRE(sys_sched_setaffinity) +{ + PRINT("sched_setaffinity ( %ld, %ld, %#lx )", ARG1, ARG2, ARG3); + PRE_REG_READ3(long, "sched_setaffinity", + vki_pid_t, pid, unsigned int, len, unsigned long *, mask); + PRE_MEM_READ( "sched_setaffinity(mask)", ARG3, ARG2); +} + +PRE(sys_sched_getaffinity) +{ + PRINT("sched_getaffinity ( %ld, %ld, %#lx )", ARG1, ARG2, ARG3); + PRE_REG_READ3(long, "sched_getaffinity", + vki_pid_t, pid, unsigned int, len, unsigned long *, mask); + PRE_MEM_WRITE( "sched_getaffinity(mask)", ARG3, ARG2); +} +POST(sys_sched_getaffinity) +{ + POST_MEM_WRITE(ARG3, ARG2); +} + +#endif + +/* --------------------------------------------------------------------- + miscellaneous wrappers + ------------------------------------------------------------------ */ + +PRE(sys_munlockall) +{ + *flags |= SfMayBlock; + PRINT("sys_munlockall ( )"); + PRE_REG_READ0(long, "munlockall"); +} + +// Pipe on freebsd doesn't have args, and uses dual returns! +PRE(sys_pipe) +{ + PRINT("sys_pipe ()"); +} +POST(sys_pipe) +{ + if (!ML_(fd_allowed)(RES, "pipe", tid, True) || + !ML_(fd_allowed)(RESHI, "pipe", tid, True)) { + VG_(close)(RES); + VG_(close)(RESHI); + SET_STATUS_Failure( VKI_EMFILE ); + } else { + if (VG_(clo_track_fds)) { + ML_(record_fd_open_nameless)(tid, RES); + ML_(record_fd_open_nameless)(tid, RESHI); + } + } +} + +#if 0 +PRE(sys_quotactl) +{ + PRINT("sys_quotactl (0x%lx, %#lx, 0x%lx, 0x%lx )", ARG1,ARG2,ARG3, ARG4); + PRE_REG_READ4(long, "quotactl", + unsigned int, cmd, const char *, special, vki_qid_t, id, + void *, addr); + PRE_MEM_RASCIIZ( "quotactl(special)", ARG2 ); +} + +PRE(sys_waitid) +{ + *flags |= SfMayBlock; + PRINT("sys_waitid( %ld, %ld, %#lx, %ld, %#lx )", ARG1,ARG2,ARG3,ARG4,ARG5); + PRE_REG_READ5(int32_t, "sys_waitid", + int, which, vki_pid_t, pid, struct vki_siginfo *, infop, + int, options, struct vki_rusage *, ru); + PRE_MEM_WRITE( "waitid(infop)", ARG3, sizeof(struct vki_siginfo) ); + if (ARG5 != 0) + PRE_MEM_WRITE( "waitid(ru)", ARG5, sizeof(struct vki_rusage) ); +} +POST(sys_waitid) +{ + POST_MEM_WRITE( ARG3, sizeof(struct vki_siginfo) ); + if (ARG5 != 0) + POST_MEM_WRITE( ARG5, sizeof(struct vki_rusage) ); +} + +/* --------------------------------------------------------------------- + utime wrapper + ------------------------------------------------------------------ */ + +PRE(sys_utime) +{ + *flags |= SfMayBlock; + PRINT("sys_utime ( %#lx, %#lx )", ARG1,ARG2); + PRE_REG_READ2(long, "utime", char *, filename, struct utimbuf *, buf); + PRE_MEM_RASCIIZ( "utime(filename)", ARG1 ); + if (ARG2 != 0) + PRE_MEM_READ( "utime(buf)", ARG2, sizeof(struct vki_utimbuf) ); +} + +#endif + +/* --------------------------------------------------------------------- + thr* wrappers + ------------------------------------------------------------------ */ + +PRE(sys_thr_self) +{ + PRINT( "sys_thr_self ( %#lx )", ARG1 ); + PRE_REG_READ1(long, "thr_self", long *, "id"); + PRE_MEM_WRITE( "thr_self()", ARG1, sizeof(long)); +} +POST(sys_thr_self) +{ + POST_MEM_WRITE( ARG1, sizeof(long)); +} + +PRE(sys_thr_exit) +{ + ThreadState *tst; + + PRINT( "sys_thr_exit ( %#lx )", ARG1 ); + PRE_REG_READ1(long, "thr_exit", long *, "status"); + + if (ARG1) + PRE_MEM_WRITE( "thr_exit(status)", ARG1, sizeof(long) ); + tst = VG_(get_ThreadState)(tid); + tst->exitreason = VgSrc_ExitThread; + tst->os_state.exitcode = ARG1; + SET_STATUS_Success(0); +} + +PRE(sys_thr_set_name) +{ + PRINT( "sys_thr_set_name ( %ld, %#lx )", ARG1, ARG2 ); + PRE_REG_READ2(long, "thr_set_name", long, "id", const char *, "name"); + PRE_MEM_RASCIIZ( "sys_thr_set_name(threadname)", ARG2); +} + +PRE(sys_thr_kill) +{ + PRINT("sys_thr_kill ( %ld, %ld )", ARG1,ARG2); + PRE_REG_READ2(long, "thr_kill", long, id, int, sig); + if (!ML_(client_signal_OK)(ARG2)) { + SET_STATUS_Failure( VKI_EINVAL ); + return; + } + + /* Check to see if this kill gave us a pending signal */ + *flags |= SfPollAfter; + + if (VG_(clo_trace_signals)) + VG_(message)(Vg_DebugMsg, "thr_kill: sending signal %ld to tid %ld\n", + ARG2, ARG1); + + /* If we're sending SIGKILL, check to see if the target is one of + our threads and handle it specially. */ + if (ARG2 == VKI_SIGKILL && ML_(do_sigkill)(ARG1, -1)) { + SET_STATUS_Success(0); + return; + } + + /* Ask to handle this syscall via the slow route, since that's the + only one that sets tst->status to VgTs_WaitSys. If the result + of doing the syscall is an immediate run of + async_signalhandler() in m_signals, then we need the thread to + be properly tidied away. I have the impression the previous + version of this wrapper worked on x86/amd64 only because the + kernel did not immediately deliver the async signal to this + thread (on ppc it did, which broke the assertion re tst->status + at the top of async_signalhandler()). */ + *flags |= SfMayBlock; +} +POST(sys_thr_kill) +{ + if (VG_(clo_trace_signals)) + VG_(message)(Vg_DebugMsg, "thr_kill: sent signal %ld to tid %ld\n", + ARG2, ARG1); +} +PRE(sys_thr_kill2) +{ + PRINT("sys_thr_kill2 ( %ld, %ld, %ld )", ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "tgkill", int, pid, long, tid, int, sig); + if (!ML_(client_signal_OK)(ARG3)) { + SET_STATUS_Failure( VKI_EINVAL ); + return; + } + + /* Check to see if this kill gave us a pending signal */ + *flags |= SfPollAfter; + + if (VG_(clo_trace_signals)) + VG_(message)(Vg_DebugMsg, "thr_kill2: sending signal %ld to pid %ld/%ld\n", + ARG3, ARG1, ARG2); + + /* If we're sending SIGKILL, check to see if the target is one of + our threads and handle it specially. */ + if (ARG3 == VKI_SIGKILL && ML_(do_sigkill)(ARG2, ARG1)) { + SET_STATUS_Success(0); + return; + } + + /* Ask to handle this syscall via the slow route, since that's the + only one that sets tst->status to VgTs_WaitSys. If the result + of doing the syscall is an immediate run of + async_signalhandler() in m_signals, then we need the thread to + be properly tidied away. I have the impression the previous + version of this wrapper worked on x86/amd64 only because the + kernel did not immediately deliver the async signal to this + thread (on ppc it did, which broke the assertion re tst->status + at the top of async_signalhandler()). */ + *flags |= SfMayBlock; +} +POST(sys_thr_kill2) +{ + if (VG_(clo_trace_signals)) + VG_(message)(Vg_DebugMsg, "thr_kill2: sent signal %ld to pid %ld/%ld\n", + ARG3, ARG1, ARG2); +} + +PRE(sys_thr_wake) +{ + PRINT("sys_thr_wake ( %ld )", ARG1); + PRE_REG_READ1(long, "thr_wake", long, id); +} + +/* --------------------------------------------------------------------- + umtx* wrappers + ------------------------------------------------------------------ */ + +PRE(sys__umtx_op) +{ +// ThreadState *tst; + + /* 5 args are always passed through. The last two can vary, but + they're always pointers. They may not be used though. */ + switch(ARG2) { + case VKI_UMTX_OP_LOCK: + PRINT( "sys__umtx_op ( %#lx, LOCK, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5); + PRE_REG_READ5(long, "_umtx_op_lock", + struct umtx *, obj, int, op, unsigned long, id, + void *, zero, struct vki_timespec *, timeout); + PRE_MEM_READ( "_umtx_op_lock(mtx)", ARG1, sizeof(struct vki_umtx) ); + if (ARG5) + PRE_MEM_READ( "_umtx_op_lock(timespec)", ARG5, sizeof(struct vki_timespec) ); + PRE_MEM_WRITE( "_umtx_op_lock(mtx)", ARG1, sizeof(struct vki_umtx) ); + *flags |= SfMayBlock; + break; + case VKI_UMTX_OP_UNLOCK: + PRINT( "sys__umtx_op ( %#lx, UNLOCK, %ld)", ARG1, ARG3); + PRE_REG_READ3(long, "_umtx_op_unlock", + struct umtx *, obj, int, op, unsigned long, id); + PRE_MEM_READ( "_umtx_op_unlock(mtx)", ARG1, sizeof(struct vki_umtx) ); + PRE_MEM_WRITE( "_umtx_op_unlock(mtx)", ARG1, sizeof(struct vki_umtx) ); + break; + case VKI_UMTX_OP_WAIT: + PRINT( "sys__umtx_op ( %#lx, WAIT, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5); + PRE_REG_READ5(long, "_umtx_op_wait", + struct umtx *, obj, int, op, unsigned long, id, + void *, zero, struct vki_timespec *, timeout); + PRE_MEM_READ( "_umtx_op_wait(mtx)", ARG1, sizeof(struct vki_umtx) ); + if (ARG5) + PRE_MEM_READ( "_umtx_op_wait(timespec)", ARG5, sizeof(struct vki_timespec) ); + *flags |= SfMayBlock; + break; + case VKI_UMTX_OP_WAKE: + PRINT( "sys__umtx_op ( %#lx, WAKE, %ld)", ARG1, ARG3); + PRE_REG_READ3(long, "_umtx_op_wake", + struct umtx *, obj, int, op, unsigned long, id); + PRE_MEM_READ( "_umtx_op_wake(mtx)", ARG1, sizeof(struct vki_umtx) ); + break; + case VKI_UMTX_OP_MUTEX_TRYLOCK: + PRINT( "sys__umtx_op ( %#lx, MUTEX_TRYLOCK, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5); + PRE_REG_READ5(long, "_umtx_op_mutex_trylock", + struct umutex *, obj, int, op, unsigned long, noid, + void *, zero, struct vki_timespec *, timeout); + PRE_MEM_READ( "_umtx_op_mutex_trylock(mutex)", ARG1, sizeof(struct vki_umutex) ); + if (ARG5) + PRE_MEM_READ( "_umtx_op_mutex_trylock(timespec)", ARG5, sizeof(struct vki_timespec) ); + PRE_MEM_WRITE( "_umtx_op_mutex_trylock(mutex)", ARG1, sizeof(struct vki_umutex) ); + break; + case VKI_UMTX_OP_MUTEX_LOCK: + PRINT( "sys__umtx_op ( %#lx, MUTEX_LOCK, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5); + PRE_REG_READ5(long, "_umtx_op_mutex_lock", + struct umutex *, obj, int, op, unsigned long, noid, + void *, zero, struct vki_timespec *, timeout); + PRE_MEM_READ( "_umtx_op_mutex_lock(mutex)", ARG1, sizeof(struct vki_umutex) ); + if (ARG5) + PRE_MEM_READ( "_umtx_op_mutex_lock(timespec)", ARG5, sizeof(struct vki_timespec) ); + PRE_MEM_WRITE( "_umtx_op_mutex_lock(mutex)", ARG1, sizeof(struct vki_umutex) ); + *flags |= SfMayBlock; + break; + case VKI_UMTX_OP_MUTEX_UNLOCK: + PRINT( "sys__umtx_op ( %#lx, MUTEX_UNLOCK)", ARG1); + PRE_REG_READ2(long, "_umtx_op_mutex_unlock", + struct umutex *, obj, int, op); + PRE_MEM_READ( "_umtx_op_mutex_unlock(mutex)", ARG1, sizeof(struct vki_umutex) ); + PRE_MEM_WRITE( "_umtx_op_mutex_unlock(mutex)", ARG1, sizeof(struct vki_umutex) ); + break; + case VKI_UMTX_OP_SET_CEILING: + PRINT( "sys__umtx_op ( %#lx, SET_CEILING, %ld, %#lx)", ARG1, ARG3, ARG4); + PRE_REG_READ4(long, "_umtx_op_set_ceiling", + struct umutex *, obj, int, op, unsigned int, ceiling, + unsigned int *, old_ceiling); + PRE_MEM_READ( "_umtx_op_set_ceiling(mutex)", ARG1, sizeof(struct vki_umutex) ); + PRE_MEM_WRITE( "_umtx_op_set_ceiling(mutex)", ARG1, sizeof(struct vki_umutex) ); + if (ARG4) + PRE_MEM_WRITE( "_umtx_op_set_ceiling(old_ceiling)", ARG4, sizeof(vki_uint32_t) ); + break; + case VKI_UMTX_OP_CV_WAIT: + PRINT( "sys__umtx_op ( %#lx, CV_WAIT, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5); + PRE_REG_READ5(long, "_umtx_op_cv_wait", + struct ucond *, obj, int, op, unsigned long, wflags, + struct umutex *, umtx, struct vki_timespec *, timeout); + PRE_MEM_READ( "_umtx_op_cv_wait(cond)", ARG1, sizeof(struct vki_ucond) ); + PRE_MEM_WRITE( "_umtx_op_cv_wait(cond)", ARG1, sizeof(struct vki_ucond) ); + PRE_MEM_READ( "_umtx_op_cv_wait(mutex)", ARG4, sizeof(struct vki_umutex) ); + PRE_MEM_WRITE( "_umtx_op_cv_wait(mutex)", ARG4, sizeof(struct vki_umutex) ); + if (ARG5) + PRE_MEM_READ( "_umtx_op_cv_wait(timespec)", ARG5, sizeof(struct vki_timespec) ); + *flags |= SfMayBlock; + break; + case VKI_UMTX_OP_CV_SIGNAL: + PRINT( "sys__umtx_op ( %#lx, CV_SIGNAL)", ARG1); + PRE_REG_READ2(long, "_umtx_op_cv_signal", + struct ucond *, obj, int, op); + PRE_MEM_READ( "_umtx_op_cv_signal(cond)", ARG1, sizeof(struct vki_ucond) ); + PRE_MEM_WRITE( "_umtx_op_cv_signal(cond)", ARG1, sizeof(struct vki_ucond) ); + break; + case VKI_UMTX_OP_CV_BROADCAST: + PRINT( "sys__umtx_op ( %#lx, CV_BROADCAST, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5); + PRE_REG_READ2(long, "_umtx_op_cv_broadcast", + struct ucond *, obj, int, op); + PRE_MEM_READ( "_umtx_op_cv_broadcast(cond)", ARG1, sizeof(struct vki_ucond) ); + PRE_MEM_WRITE( "_umtx_op_cv_broadcast(cond)", ARG1, sizeof(struct vki_ucond) ); + break; + case VKI_UMTX_OP_WAIT_UINT: + PRINT( "sys__umtx_op ( %#lx, CV_WAIT_UINT, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5); + PRE_REG_READ5(long, "_umtx_op_wait_uint", + int *, obj, int, op, unsigned long, id, + void *, zero, struct vki_timespec *, timeout); + PRE_MEM_READ( "_umtx_op_wait(uint)", ARG1, sizeof(int) ); + if (ARG5) + PRE_MEM_READ( "_umtx_op_wait(timespec)", ARG5, sizeof(struct vki_timespec) ); + *flags |= SfMayBlock; + break; + case VKI_UMTX_OP_RW_RDLOCK: + PRINT( "sys__umtx_op ( %#lx, RW_RDLOCK, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5); + PRE_REG_READ5(long, "_umtx_op_rw_rdlock", + struct urwlock *, obj, int, op, unsigned long, noid, + void *, zero, struct vki_timespec *, timeout); + PRE_MEM_READ( "_umtx_op_rw_rdlock(rw)", ARG1, sizeof(struct vki_urwlock) ); + PRE_MEM_WRITE( "_umtx_op_rw_rdlock(rw)", ARG1, sizeof(struct vki_urwlock) ); + *flags |= SfMayBlock; + break; + case VKI_UMTX_OP_RW_WRLOCK: + PRINT( "sys__umtx_op ( %#lx, RW_WRLOCK, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5); + PRE_REG_READ5(long, "_umtx_op_rw_wrlock", + struct urwlock *, obj, int, op, unsigned long, noid, + void *, zero, struct vki_timespec *, timeout); + PRE_MEM_READ( "_umtx_op_rw_wrlock(rw)", ARG1, sizeof(struct vki_urwlock) ); + PRE_MEM_WRITE( "_umtx_op_rw_wrlock(rw)", ARG1, sizeof(struct vki_urwlock) ); + *flags |= SfMayBlock; + break; + case VKI_UMTX_OP_RW_UNLOCK: + PRINT( "sys__umtx_op ( %#lx, RW_UNLOCK, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5); + PRE_REG_READ2(long, "_umtx_op_rw_unlock", + struct urwlock *, obj, int, op); + PRE_MEM_READ( "_umtx_op_rw_unlock(rw)", ARG1, sizeof(struct vki_urwlock) ); + PRE_MEM_WRITE( "_umtx_op_rw_unlock(rw)", ARG1, sizeof(struct vki_urwlock) ); + break; + case VKI_UMTX_OP_WAIT_UINT_PRIVATE: + PRINT( "sys__umtx_op ( %#lx, CV_WAIT_UINT_PRIVATE, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5); + PRE_REG_READ5(long, "_umtx_op_wait_uint_private", + int *, obj, int, op, unsigned long, id, + void *, zero, struct vki_timespec *, timeout); + PRE_MEM_READ( "_umtx_op_wait_private(uint)", ARG1, sizeof(int) ); + if (ARG5) + PRE_MEM_READ( "_umtx_op_wait_private(umtx_time)", ARG5, sizeof(struct vki_umtx_time) ); + *flags |= SfMayBlock; + break; + case VKI_UMTX_OP_WAKE_PRIVATE: + PRINT( "sys__umtx_op ( %#lx, CV_WAKE_PRIVATE, %ld)", ARG1, ARG3); + PRE_REG_READ3(long, "_umtx_op_wake_private", + struct umtx *, obj, int, op, unsigned long, id); + PRE_MEM_READ( "_umtx_op_wake_private(mtx)", ARG1, sizeof(struct vki_umtx) ); + break; + case VKI_UMTX_OP_MUTEX_WAIT: + PRINT( "sys__umtx_op ( %#lx, MUTEX_WAIT, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5); + PRE_REG_READ2(long, "_umtx_op_mutex_wait", + struct umutex *, obj, int, op); + PRE_MEM_READ( "_umtx_op_mutex_wait(mutex)", ARG1, sizeof(struct vki_umutex) ); + PRE_MEM_WRITE( "_umtx_op_mutex_wait(mutex)", ARG1, sizeof(struct vki_umutex) ); + *flags |= SfMayBlock; + break; + case VKI_UMTX_OP_MUTEX_WAKE: + PRINT( "sys__umtx_op ( %#lx, MUTEX_WAKE, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5); + PRE_REG_READ2(long, "_umtx_op_mutex_wake", + struct umutex *, obj, int, op); + PRE_MEM_READ( "_umtx_op_mutex_wake(mutex)", ARG1, sizeof(struct vki_umutex) ); + PRE_MEM_WRITE( "_umtx_op_mutex_wake(mutex)", ARG1, sizeof(struct vki_umutex) ); + break; + case VKI_UMTX_OP_SEM_WAIT: + PRINT( "sys__umtx_op ( %#lx, SEM_WAIT, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5); + PRE_REG_READ5(long, "_umtx_op_sem_wait", + struct usem *, obj, int, op, unsigned long, id, + void *, zero, struct vki_timespec *, timeout); + PRE_MEM_READ( "_umtx_op_sem_wait(usem)", ARG1, sizeof(struct vki_usem) ); + PRE_MEM_WRITE( "_umtx_op_sem_wait(usem)", ARG1, sizeof(struct vki_usem) ); + if (ARG5) + PRE_MEM_READ( "_umtx_op_sem_wait(umtx_time)", ARG5, sizeof(struct vki_umtx_time) ); + *flags |= SfMayBlock; + break; + case VKI_UMTX_OP_SEM_WAKE: + PRINT( "sys__umtx_op ( %#lx, SEM_WAKE, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5); + PRE_REG_READ2(long, "_umtx_op_sem_wake", + struct umutex *, obj, int, op); + PRE_MEM_READ( "_umtx_op_sem_wake(mutex)", ARG1, sizeof(struct vki_usem) ); + PRE_MEM_WRITE( "_umtx_op_sem_wake(mutex)", ARG1, sizeof(struct vki_usem) ); + break; + case VKI_UMTX_OP_NWAKE_PRIVATE: + PRINT( "sys__umtx_op ( %#lx, NWAKE_PRIVATE, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5); + PRE_REG_READ3(long, "_umtx_op_nwake_private", + struct umutex *, obj, int, op, int, count); + PRE_MEM_READ( "_umtx_op_nwake_private(mtxs)", ARG1, ARG3 * sizeof(void *) ); + PRE_MEM_WRITE( "_umtx_op_mutex_wake(mtxs)", ARG1, sizeof(struct vki_umutex) ); + break; + case VKI_UMTX_OP_MUTEX_WAKE2: + PRINT( "sys__umtx_op ( %#lx, MUTEX_WAKE2, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5); + PRE_REG_READ3(long, "_umtx_op_mutex_wake2", + struct umutex *, obj, int, op, unsigned long, flags); + PRE_MEM_READ( "_umtx_op_mutex_wake(mutex)", ARG1, sizeof(struct vki_umutex) ); + PRE_MEM_WRITE( "_umtx_op_mutex_wake(mutex)", ARG1, sizeof(struct vki_umutex) ); + break; + default: + PRINT( "sys__umtx_op ( %#lx, %ld(UNKNOWN), %ld, %#lx, %#lx )", ARG1, ARG2, ARG3, ARG4, ARG5); + break; + } +// tst = VG_(get_ThreadState)(tid); +//PRINT(" [[ UMTX_OP %d: me=%d arg1 %#lx = %#lx (%ld) ]]", ARG2, tst->os_state.lwpid, ARG1, *(UWord *)ARG1, *(UWord *)ARG1 & 0x7fffffff); +} + +POST(sys__umtx_op) +{ +//PRINT("[[ POST_UMTX_OP %d: arg1 %#lx = %#lx (%ld) ]]\n", ARG2, ARG1, *(UWord *)ARG1, *(UWord *)ARG1 & 0x7fffffff); + switch(ARG2) { + case VKI_UMTX_OP_LOCK: + if (SUCCESS) + POST_MEM_WRITE( ARG1, sizeof(struct vki_umtx) ); + break; + case VKI_UMTX_OP_UNLOCK: + if (SUCCESS) + POST_MEM_WRITE( ARG1, sizeof(struct vki_umtx) ); + break; + case VKI_UMTX_OP_WAIT: + case VKI_UMTX_OP_WAKE: + case VKI_UMTX_OP_WAIT_UINT: + case VKI_UMTX_OP_WAIT_UINT_PRIVATE: + case VKI_UMTX_OP_WAKE_PRIVATE: + break; + case VKI_UMTX_OP_MUTEX_TRYLOCK: + case VKI_UMTX_OP_MUTEX_LOCK: + case VKI_UMTX_OP_MUTEX_UNLOCK: + case VKI_UMTX_OP_MUTEX_WAIT: /* Sets/clears contested bits */ + case VKI_UMTX_OP_MUTEX_WAKE: /* Sets/clears contested bits */ + if (SUCCESS) + POST_MEM_WRITE( ARG1, sizeof(struct vki_umutex) ); + break; + case VKI_UMTX_OP_SET_CEILING: + if (SUCCESS) { + POST_MEM_WRITE( ARG1, sizeof(struct vki_umutex) ); + if (ARG4) + POST_MEM_WRITE( ARG4, sizeof(vki_uint32_t) ); + } + break; + case VKI_UMTX_OP_CV_WAIT: + if (SUCCESS) { + POST_MEM_WRITE( ARG1, sizeof(struct vki_ucond) ); + POST_MEM_WRITE( ARG4, sizeof(struct vki_umutex) ); + } + break; + case VKI_UMTX_OP_CV_SIGNAL: + if (SUCCESS) { + POST_MEM_WRITE( ARG1, sizeof(struct vki_ucond) ); + } + break; + case VKI_UMTX_OP_CV_BROADCAST: + if (SUCCESS) { + POST_MEM_WRITE( ARG1, sizeof(struct vki_ucond) ); + } + break; + case VKI_UMTX_OP_RW_RDLOCK: + case VKI_UMTX_OP_RW_WRLOCK: + case VKI_UMTX_OP_RW_UNLOCK: + if (SUCCESS) { + POST_MEM_WRITE( ARG1, sizeof(struct vki_urwlock) ); + } + break; + default: + break; + } +} + +PRE(sys__umtx_lock) +{ + PRINT( "sys__umtx_lock ( %#lx )", ARG1); + PRE_REG_READ1(long, "_umtx_lock", struct vki_umtx *, umtx); + PRE_MEM_READ( "_umtx_lock(mtx)", ARG1, sizeof(struct vki_umtx) ); + PRE_MEM_WRITE( "_umtx_lock(mtx)", ARG1, sizeof(struct vki_umtx) ); +} + +POST(sys__umtx_lock) +{ + if (SUCCESS) + POST_MEM_WRITE(ARG1, sizeof(struct vki_umtx)); +} + +PRE(sys__umtx_unlock) +{ + PRINT( "sys__umtx_unlock ( %#lx )", ARG1); + PRE_REG_READ1(long, "_umtx_unlock", struct vki_umtx *, umtx); + PRE_MEM_READ( "_umtx_unlock(mtx)", ARG1, sizeof(struct vki_umtx) ); + PRE_MEM_WRITE( "_umtx_unlock(mtx)", ARG1, sizeof(struct vki_umtx) ); +} + +POST(sys__umtx_unlock) +{ + if (SUCCESS) + POST_MEM_WRITE(ARG1, sizeof(struct vki_umtx)); +} + +PRE(sys_rtprio_thread) +{ + PRINT( "sys_rtprio_thread ( %ld, %ld, %#lx )", ARG1, ARG2, ARG3 ); + PRE_REG_READ3(long, "rtprio_thread", + int, "function", __vki_lwpid_t, "lwpid", struct vki_rtprio *, "rtp"); + if (ARG1 == VKI_RTP_SET) { + PRE_MEM_READ( "rtprio_thread(set)", ARG3, sizeof(struct vki_rtprio)); + } else if (ARG1 == VKI_RTP_LOOKUP) { + PRE_MEM_WRITE( "rtprio_thread(lookup)", ARG3, sizeof(struct vki_rtprio)); + } else { + /* PHK ?? */ + } +} +POST(sys_rtprio_thread) +{ + if (ARG1 == VKI_RTP_LOOKUP && RES == 0) + POST_MEM_WRITE( ARG3, sizeof(struct vki_rtprio)); +} + +/* --------------------------------------------------------------------- + sig* wrappers + ------------------------------------------------------------------ */ + +PRE(sys_sigpending) +{ + PRINT( "sys_sigpending ( %#lx )", ARG1 ); + PRE_REG_READ1(long, "sigpending", vki_sigset_t *, set); + PRE_MEM_WRITE( "sigpending(set)", ARG1, sizeof(vki_sigset_t)); +} +POST(sys_sigpending) +{ + POST_MEM_WRITE( ARG1, sizeof(vki_sigset_t) ) ; +} + +/* --------------------------------------------------------------------- + rt_sig* wrappers + ------------------------------------------------------------------ */ + +static int sigformat[_VKI_NSIG]; + +PRE(sys_sigaction4) +{ + PRINT("sys_sigaction ( %ld, %#lx, %#lx )", ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "sigaction", + int, signum, const struct sigaction *, act, + struct sigaction *, oldact); + + if (ARG2 != 0) { + struct vki_sigaction *sa = (struct vki_sigaction *)ARG2; + PRE_MEM_READ( "sigaction(act->sa_handler)", (Addr)&sa->ksa_handler, sizeof(sa->ksa_handler)); + PRE_MEM_READ( "sigaction(act->sa_mask)", (Addr)&sa->sa_mask, sizeof(sa->sa_mask)); + PRE_MEM_READ( "sigaction(act->sa_flags)", (Addr)&sa->sa_flags, sizeof(sa->sa_flags)); + if (ARG1 < _VKI_NSIG) + sigformat[ARG1] = 4; + } + if (ARG3 != 0) + PRE_MEM_WRITE( "sigaction(oldact)", ARG3, sizeof(struct vki_sigaction)); + + /* process the signal immediately. */ + SET_STATUS_from_SysRes( + VG_(do_sys_sigaction)(ARG1, (const vki_sigaction_toK_t *)ARG2, + (vki_sigaction_fromK_t *)ARG3) + ); +} +POST(sys_sigaction4) +{ + vg_assert(SUCCESS); + if (RES == 0 && ARG3 != 0) + POST_MEM_WRITE( ARG3, sizeof(struct vki_sigaction)); +} + +/* Identical, but warns the signal handler to expect the different sigframe */ +PRE(sys_sigaction) +{ + PRINT("sys_sigaction6 ( %ld, %#lx, %#lx )", ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "sigaction6", + int, signum, const struct sigaction *, act, + struct sigaction *, oldact); + + if (ARG2 != 0) { + struct vki_sigaction *sa = (struct vki_sigaction *)ARG2; + PRE_MEM_READ( "sigaction6(act->sa_handler)", (Addr)&sa->ksa_handler, sizeof(sa->ksa_handler)); + PRE_MEM_READ( "sigaction6(act->sa_mask)", (Addr)&sa->sa_mask, sizeof(sa->sa_mask)); + PRE_MEM_READ( "sigaction6(act->sa_flags)", (Addr)&sa->sa_flags, sizeof(sa->sa_flags)); + if (ARG1 < _VKI_NSIG) + sigformat[ARG1] = 6; + } + if (ARG3 != 0) + PRE_MEM_WRITE( "sigaction6(oldact)", ARG3, sizeof(struct vki_sigaction)); + + SET_STATUS_from_SysRes( + VG_(do_sys_sigaction)(ARG1, (const vki_sigaction_toK_t *)ARG2, + (vki_sigaction_fromK_t *)ARG3) + ); +} +POST(sys_sigaction) +{ + vg_assert(SUCCESS); + if (RES == 0 && ARG3 != 0) + POST_MEM_WRITE( ARG3, sizeof(struct vki_sigaction)); +} + + +PRE(sys_sigprocmask) +{ + PRINT("sys_sigprocmask ( %ld, %#lx, %#lx )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "sigprocmask", + int, how, vki_sigset_t *, set, vki_sigset_t *, oldset); + if (ARG2 != 0) + PRE_MEM_READ( "sigprocmask(set)", ARG2, sizeof(vki_sigset_t)); + if (ARG3 != 0) + PRE_MEM_WRITE( "sigprocmask(oldset)", ARG3, sizeof(vki_sigset_t)); + + SET_STATUS_from_SysRes( + VG_(do_sys_sigprocmask) ( tid, ARG1 /*how*/, + (vki_sigset_t*) ARG2, + (vki_sigset_t*) ARG3 ) + ); + + if (SUCCESS) + *flags |= SfPollAfter; +} +POST(sys_sigprocmask) +{ + vg_assert(SUCCESS); + if (RES == 0 && ARG3 != 0) + POST_MEM_WRITE( ARG3, sizeof(vki_sigset_t)); +} + +/* Not in 4.x */ +PRE(sys_sigtimedwait) +{ + *flags |= SfMayBlock; + PRINT("sys_sigtimedwait ( %#lx, %#lx, %#lx )", + ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "sigtimedwait", + const vki_sigset_t *, set, vki_siginfo_t *, info, + const struct timespec *, timeout); + if (ARG1 != 0) + PRE_MEM_READ( "sigtimedwait(set)", ARG1, sizeof(vki_sigset_t)); + if (ARG2 != 0) + PRE_MEM_WRITE( "sigtimedwait(info)", ARG2, sizeof(vki_siginfo_t) ); + if (ARG3 != 0) + PRE_MEM_READ( "sigtimedwait(timeout)", + ARG3, sizeof(struct vki_timespec) ); +} +POST(sys_sigtimedwait) +{ + if (ARG2 != 0) + POST_MEM_WRITE( ARG2, sizeof(vki_siginfo_t) ); +} + +/* Not in 4.x */ +PRE(sys_sigwaitinfo) +{ + *flags |= SfMayBlock; + PRINT("sys_sigwaitinfo ( %#lx, %#lx )", + ARG1,ARG2); + PRE_REG_READ2(long, "sigwaitinfo", + const vki_sigset_t *, set, vki_siginfo_t *, info); + if (ARG1 != 0) + PRE_MEM_READ( "sigwaitinfo(set)", ARG1, sizeof(vki_sigset_t)); + if (ARG2 != 0) + PRE_MEM_WRITE( "sigwaitinfo(info)", ARG2, sizeof(vki_siginfo_t) ); +} +POST(sys_sigwaitinfo) +{ + if (ARG2 != 0) + POST_MEM_WRITE( ARG2, sizeof(vki_siginfo_t) ); +} + +#if 0 /* not on freebsd 4.x */ +PRE(sys_rt_sigqueueinfo) +{ + PRINT("sys_rt_sigqueueinfo(%ld, %ld, %#lx)", ARG1, ARG2, ARG3); + PRE_REG_READ3(long, "rt_sigqueueinfo", + int, pid, int, sig, vki_siginfo_t *, uinfo); + if (ARG2 != 0) + PRE_MEM_READ( "rt_sigqueueinfo(uinfo)", ARG3, sizeof(vki_siginfo_t) ); +} +POST(sys_rt_sigqueueinfo) +{ + if (!ML_(client_signal_OK)(ARG2)) + SET_STATUS_Failure( VKI_EINVAL ); +} +#endif + +PRE(sys_sigsuspend) +{ + *flags |= SfMayBlock; + PRINT("sys_sigsuspend ( %#lx )", ARG1 ); + PRE_REG_READ1(int, "rt_sigsuspend", vki_sigset_t *, mask) + if (ARG1 != (Addr)NULL) { + PRE_MEM_READ( "rt_sigsuspend(mask)", ARG1, sizeof(vki_sigset_t) ); + } +} + +#if 0 +/* --------------------------------------------------------------------- + linux msg* wrapper helpers + ------------------------------------------------------------------ */ + +void +ML_(linux_PRE_sys_msgsnd) ( ThreadId tid, + UWord arg0, UWord arg1, UWord arg2, UWord arg3 ) +{ + /* int msgsnd(int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg); */ + struct vki_msgbuf *msgp = (struct vki_msgbuf *)arg1; + PRE_MEM_READ( "msgsnd(msgp->mtype)", (Addr)&msgp->mtype, sizeof(msgp->mtype) ); + PRE_MEM_READ( "msgsnd(msgp->mtext)", (Addr)&msgp->mtext, arg2 ); +} + +void +ML_(linux_PRE_sys_msgrcv) ( ThreadId tid, + UWord arg0, UWord arg1, UWord arg2, + UWord arg3, UWord arg4 ) +{ + /* ssize_t msgrcv(int msqid, struct msgbuf *msgp, size_t msgsz, + long msgtyp, int msgflg); */ + struct vki_msgbuf *msgp = (struct vki_msgbuf *)arg1; + PRE_MEM_WRITE( "msgrcv(msgp->mtype)", (Addr)&msgp->mtype, sizeof(msgp->mtype) ); + PRE_MEM_WRITE( "msgrcv(msgp->mtext)", (Addr)&msgp->mtext, arg2 ); +} +void +ML_(linux_POST_sys_msgrcv) ( ThreadId tid, + UWord res, + UWord arg0, UWord arg1, UWord arg2, + UWord arg3, UWord arg4 ) +{ + struct vki_msgbuf *msgp = (struct vki_msgbuf *)arg1; + POST_MEM_WRITE( (Addr)&msgp->mtype, sizeof(msgp->mtype) ); + POST_MEM_WRITE( (Addr)&msgp->mtext, res ); +} + +void +ML_(linux_PRE_sys_msgctl) ( ThreadId tid, + UWord arg0, UWord arg1, UWord arg2 ) +{ + /* int msgctl(int msqid, int cmd, struct msqid_ds *buf); */ + switch (arg1 /* cmd */) { + case VKI_IPC_INFO: + case VKI_MSG_INFO: + case VKI_IPC_INFO|VKI_IPC_64: + case VKI_MSG_INFO|VKI_IPC_64: + PRE_MEM_WRITE( "msgctl(IPC_INFO, buf)", + arg2, sizeof(struct vki_msginfo) ); + break; + case VKI_IPC_STAT: + case VKI_MSG_STAT: + PRE_MEM_WRITE( "msgctl(IPC_STAT, buf)", + arg2, sizeof(struct vki_msqid_ds) ); + break; + case VKI_IPC_STAT|VKI_IPC_64: + case VKI_MSG_STAT|VKI_IPC_64: + PRE_MEM_WRITE( "msgctl(IPC_STAT, arg.buf)", + arg2, sizeof(struct vki_msqid64_ds) ); + break; + case VKI_IPC_SET: + PRE_MEM_READ( "msgctl(IPC_SET, arg.buf)", + arg2, sizeof(struct vki_msqid_ds) ); + break; + case VKI_IPC_SET|VKI_IPC_64: + PRE_MEM_READ( "msgctl(IPC_SET, arg.buf)", + arg2, sizeof(struct vki_msqid64_ds) ); + break; + } +} +void +ML_(linux_POST_sys_msgctl) ( ThreadId tid, + UWord res, + UWord arg0, UWord arg1, UWord arg2 ) +{ + switch (arg1 /* cmd */) { + case VKI_IPC_INFO: + case VKI_MSG_INFO: + case VKI_IPC_INFO|VKI_IPC_64: + case VKI_MSG_INFO|VKI_IPC_64: + POST_MEM_WRITE( arg2, sizeof(struct vki_msginfo) ); + break; + case VKI_IPC_STAT: + case VKI_MSG_STAT: + POST_MEM_WRITE( arg2, sizeof(struct vki_msqid_ds) ); + break; + case VKI_IPC_STAT|VKI_IPC_64: + case VKI_MSG_STAT|VKI_IPC_64: + POST_MEM_WRITE( arg2, sizeof(struct vki_msqid64_ds) ); + break; + } +} + +#endif + +PRE(sys_chflags) +{ + PRINT("sys_chflags ( %#lx(%s), 0x%lx )", ARG1,(char *)ARG1,ARG2); + PRE_REG_READ2(long, "chown", + const char *, path, vki_int32_t, flags); + PRE_MEM_RASCIIZ( "chflags(path)", ARG1 ); +} + +PRE(sys_fchflags) +{ + PRINT("sys_fchflags ( %ld, %ld )", ARG1,ARG2); + PRE_REG_READ2(long, "fchflags", unsigned int, fildes, vki_int32_t, flags); +} + + +PRE(sys_modfind) +{ + PRINT("sys_modfind ( %#lx )",ARG1); + PRE_REG_READ1(long, "modfind", char *, modname); + PRE_MEM_RASCIIZ( "modfind(modname)", ARG1 ); +} + +PRE(sys_modstat) +{ + PRINT("sys_modstat ( %ld, %#lx )",ARG1,ARG2); + PRE_REG_READ2(long, "modstat", int, modid, struct module_stat *, buf); + PRE_MEM_WRITE( "modstat(buf)", ARG2, sizeof(struct vki_module_stat) ); +} + +POST(sys_modstat) +{ + POST_MEM_WRITE( ARG2, sizeof(struct vki_module_stat) ); +} + +PRE(sys_lkmnosys0) +{ + PRINT("sys_lkmnosys0 ()"); + PRE_REG_READ0(long, "lkmnosys0"); +} + +PRE(sys_lkmnosys1) +{ + PRINT("sys_lkmnosys1 ()"); + PRE_REG_READ0(long, "lkmnosys1"); +} + +PRE(sys_lkmnosys2) +{ + PRINT("sys_lkmnosys2 ()"); + PRE_REG_READ0(long, "lkmnosys2"); +} + +PRE(sys_lkmnosys3) +{ + PRINT("sys_lkmnosys3 ()"); + PRE_REG_READ0(long, "lkmnosys3"); +} + +PRE(sys_lkmnosys4) +{ + PRINT("sys_lkmnosys4 ()"); + PRE_REG_READ0(long, "lkmnosys4"); +} + +PRE(sys_lkmnosys5) +{ + PRINT("sys_lkmnosys5 ()"); + PRE_REG_READ0(long, "lkmnosys5"); +} + +PRE(sys_lkmnosys6) +{ + PRINT("sys_lkmnosys6 ()"); + PRE_REG_READ0(long, "lkmnosys6"); +} + +PRE(sys_lkmnosys7) +{ + PRINT("sys_lkmnosys7 ()"); + PRE_REG_READ0(long, "lkmnosys7"); +} + +PRE(sys_lkmnosys8) +{ + PRINT("sys_lkmnosys8 ()"); + PRE_REG_READ0(long, "lkmnosys8"); +} + +PRE(sys_kenv) +{ + PRINT("sys_kenv ( %ld, %#lx, %#lx, %ld )", ARG1,ARG2,ARG3,ARG4); + PRE_REG_READ4(long, "kenv", + int, action, const char *, name, char *, value, int, len); + switch (ARG1) { + case VKI_KENV_GET: + case VKI_KENV_SET: + case VKI_KENV_UNSET: + PRE_MEM_RASCIIZ("kenv(name)", ARG2); + /* FALLTHROUGH */ + case VKI_KENV_DUMP: + break; + default: + I_die_here; + } +} + +POST(sys_kenv) +{ + if (SUCCESS) { + switch (ARG1) { + case VKI_KENV_GET: + POST_MEM_WRITE(ARG3, ARG4); + break; + case VKI_KENV_DUMP: + if (ARG3 != (Addr)NULL) + POST_MEM_WRITE(ARG3, ARG4); + break; + } + } +} + +PRE(sys_uuidgen) +{ + PRINT("sys_uuidgen ( %#lx, %ld )", ARG1,ARG2); + PRE_REG_READ2(long, "uuidgen", + struct vki_uuid *, store, int, count); + PRE_MEM_WRITE( "uuidgen(store)", ARG1, ARG2 * sizeof(struct vki_uuid)); +} + +POST(sys_uuidgen) +{ + if (SUCCESS) + POST_MEM_WRITE( ARG1, ARG2 * sizeof(struct vki_uuid) ); +} + + +PRE(sys_shmget) +{ + PRINT("sys_shmget ( %ld, %ld, %ld )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "shmget", vki_key_t, key, vki_size_t, size, int, shmflg); +} + +PRE(sys_shmat) +{ + UWord arg2tmp; + PRINT("sys_shmat ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "shmat", + int, shmid, const void *, shmaddr, int, shmflg); + arg2tmp = ML_(generic_PRE_sys_shmat)(tid, ARG1,ARG2,ARG3); + if (arg2tmp == 0) + SET_STATUS_Failure( VKI_EINVAL ); + else + ARG2 = arg2tmp; +} + +POST(sys_shmat) +{ + ML_(generic_POST_sys_shmat)(tid, RES,ARG1,ARG2,ARG3); +} + +PRE(sys_shmdt) +{ + PRINT("sys_shmdt ( %#lx )",ARG1); + PRE_REG_READ1(long, "shmdt", const void *, shmaddr); + if (!ML_(generic_PRE_sys_shmdt)(tid, ARG1)) + SET_STATUS_Failure( VKI_EINVAL ); +} + +POST(sys_shmdt) +{ + ML_(generic_POST_sys_shmdt)(tid, RES,ARG1); +} + +PRE(sys_shmctl) +{ + PRINT("sys_shmctl ( %ld, %ld, %#lx )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "shmctl", + int, shmid, int, cmd, struct vki_shmid_ds *, buf); + switch (ARG2 /* cmd */) { + case VKI_IPC_STAT: + PRE_MEM_WRITE( "shmctl(IPC_STAT, buf)", + ARG3, sizeof(struct vki_shmid_ds) ); + break; + case VKI_IPC_SET: + PRE_MEM_READ( "shmctl(IPC_SET, buf)", + ARG3, sizeof(struct vki_shmid_ds) ); + break; + } +} + +PRE(sys_shmctl7) +{ + PRINT("sys_shmctl7 ( %ld, %ld, %#lx )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "shmctl", + int, shmid, int, cmd, struct vki_shmid_ds7 *, buf); + switch (ARG2 /* cmd */) { + case VKI_IPC_STAT: + PRE_MEM_WRITE( "shmctl7(IPC_STAT, buf)", + ARG3, sizeof(struct vki_shmid_ds7) ); + break; + case VKI_IPC_SET: + PRE_MEM_READ( "shmctl7(IPC_SET, buf)", + ARG3, sizeof(struct vki_shmid_ds7) ); + break; + } +} + +POST(sys_shmctl) +{ + if (ARG2 == VKI_IPC_STAT) { + POST_MEM_WRITE( ARG3, sizeof(struct vki_shmid_ds) ); + } +} + +POST(sys_shmctl7) +{ + if (ARG2 == VKI_IPC_STAT) { + POST_MEM_WRITE( ARG3, sizeof(struct vki_shmid_ds7) ); + } +} + +PRE(sys_semget) +{ + PRINT("sys_semget ( %ld, %ld, %ld )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "semget", vki_key_t, key, int, nsems, int, semflg); +} + +PRE(sys_shm_open) +{ + PRE_REG_READ3(long, "shm_open", + const char *, "name", int, "flags", vki_mode_t, "mode"); + if (ARG1 == VKI_SHM_ANON) { + PRINT("sys_shm_open(%#lx(SHM_ANON), %ld, %ld)", ARG1, ARG2, ARG3); + } else { + PRINT("sys_shm_open(%#lx(%s), %ld, %ld)", ARG1, (char *)ARG1, ARG2, ARG3); + PRE_MEM_RASCIIZ( "shm_open(filename)", ARG1 ); + } + *flags |= SfMayBlock; +} + +POST(sys_shm_open) +{ + vg_assert(SUCCESS); + if (!ML_(fd_allowed)(RES, "shm_open", tid, True)) { + VG_(close)(RES); + SET_STATUS_Failure( VKI_EMFILE ); + } else { + if (VG_(clo_track_fds)) + ML_(record_fd_open_with_given_name)(tid, RES, (HChar*)ARG1); + } +} + +PRE(sys_shm_unlink) +{ + PRINT("sys_shm_unlink(%#lx(%s))", ARG1, (char *)ARG1); + PRE_REG_READ1(long, "shm_unlink", + const char *, "name"); + + PRE_MEM_RASCIIZ( "shm_unlink(filename)", ARG1 ); + + *flags |= SfMayBlock; +} + +PRE(sys_semop) +{ + *flags |= SfMayBlock; + PRINT("sys_semop ( %ld, %#lx, %lu )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "semop", + int, semid, struct sembuf *, sops, unsigned, nsoops); + ML_(generic_PRE_sys_semop)(tid, ARG1,ARG2,ARG3); +} + +struct ipc_perm7 { + unsigned short cuid; /* creator user id */ + unsigned short cgid; /* creator group id */ + unsigned short uid; /* user id */ + unsigned short gid; /* group id */ + unsigned short mode; /* r/w permission */ + unsigned short seq; /* sequence # (to generate unique ipcid) */ + vki_key_t key; /* user specified msg/sem/shm key */ +}; + +struct semid_ds7 { + struct ipc_perm7 sem_perm; /* operation permission struct */ + struct sem *sem_base; /* pointer to first semaphore in set */ + unsigned short sem_nsems; /* number of sems in set */ + vki_time_t sem_otime; /* last operation time */ + long sem_pad1; /* SVABI/386 says I need this here */ + vki_time_t sem_ctime; /* last change time */ + /* Times measured in secs since */ + /* 00:00:00 GMT, Jan. 1, 1970 */ + long sem_pad2; /* SVABI/386 says I need this here */ + long sem_pad3[4]; /* SVABI/386 says I need this here */ +}; + +PRE(sys___semctl7) +{ + switch (ARG3) { + case VKI_IPC_INFO: + case VKI_SEM_INFO: + PRINT("sys_semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4); + PRE_REG_READ4(long, "semctl", + int, semid, int, semnum, int, cmd, struct seminfo *, arg); + break; + case VKI_IPC_STAT: + case VKI_SEM_STAT: + case VKI_IPC_SET: + PRINT("sys_semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4); + PRE_REG_READ4(long, "semctl", + int, semid, int, semnum, int, cmd, struct semid_ds7 *, arg); + break; + case VKI_GETALL: + case VKI_SETALL: + PRINT("sys_semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4); + PRE_REG_READ4(long, "semctl", + int, semid, int, semnum, int, cmd, unsigned short *, arg); + break; + default: + PRINT("sys_semctl ( %ld, %ld, %ld )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "semctl", + int, semid, int, semnum, int, cmd); + break; + } + ML_(generic_PRE_sys_semctl)(tid, ARG1,ARG2,ARG3,ARG4); +} + +POST(sys___semctl7) +{ + ML_(generic_POST_sys_semctl)(tid, RES,ARG1,ARG2,ARG3,ARG4); +} + +PRE(sys___semctl) +{ + switch (ARG3) { + case VKI_IPC_INFO: + case VKI_SEM_INFO: + PRINT("sys_semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4); + PRE_REG_READ4(long, "semctl", + int, semid, int, semnum, int, cmd, struct seminfo *, arg); + break; + case VKI_IPC_STAT: + case VKI_SEM_STAT: + case VKI_IPC_SET: + PRINT("sys_semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4); + PRE_REG_READ4(long, "semctl", + int, semid, int, semnum, int, cmd, struct semid_ds *, arg); + break; + case VKI_GETALL: + case VKI_SETALL: + PRINT("sys_semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4); + PRE_REG_READ4(long, "semctl", + int, semid, int, semnum, int, cmd, unsigned short *, arg); + break; + default: + PRINT("sys_semctl ( %ld, %ld, %ld )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "semctl", + int, semid, int, semnum, int, cmd); + break; + } + ML_(generic_PRE_sys_semctl)(tid, ARG1,ARG2,ARG3,ARG4); +} + +POST(sys___semctl) +{ + ML_(generic_POST_sys_semctl)(tid, RES,ARG1,ARG2,ARG3,ARG4); +} + +PRE(sys_eaccess) +{ + PRINT("sys_eaccess ( %#lx(%s), %ld )", ARG1,(char*)ARG1,ARG2); + PRE_REG_READ2(long, "eaccess", const char *, pathname, int, mode); + PRE_MEM_RASCIIZ( "eaccess(pathname)", ARG1 ); +} + + +/* --------------------------------------------------------------------- + *at wrappers + ------------------------------------------------------------------ */ + +PRE(sys_openat) +{ + HChar name[30]; + SysRes sres; + + if (ARG3 & VKI_O_CREAT) { + // 4-arg version + PRINT("sys_openat ( %ld, %#lx(%s), %ld, %ld )",ARG1,ARG2,(char*)ARG2,ARG3,ARG4); + PRE_REG_READ4(long, "openat", + int, dfd, const char *, filename, int, flags, int, mode); + } else { + // 3-arg version + PRINT("sys_openat ( %ld, %#lx(%s), %ld )",ARG1,ARG2,(char*)ARG2,ARG3); + PRE_REG_READ3(long, "openat", + int, dfd, const char *, filename, int, flags); + } + + if (ARG1 != VKI_AT_FDCWD && !ML_(fd_allowed)(ARG1, "openat", tid, False)) + SET_STATUS_Failure( VKI_EBADF ); + else + PRE_MEM_RASCIIZ( "openat(filename)", ARG2 ); + + /* Handle the case where the open is of /proc/curproc/cmdline or + /proc//cmdline, and just give it a copy of the fd for the + fake file we cooked up at startup (in m_main). Also, seek the + cloned fd back to the start. */ + + VG_(sprintf)(name, "/proc/%d/cmdline", VG_(getpid)()); + if (ML_(safe_to_deref)( (void*)ARG2, 1 ) + && (VG_(strcmp)((HChar *)ARG2, name) == 0 + || VG_(strcmp)((HChar *)ARG2, "/proc/curproc/cmdline") == 0)) { + sres = VG_(dup)( VG_(cl_cmdline_fd) ); + SET_STATUS_from_SysRes( sres ); + if (!sr_isError(sres)) { + OffT off = VG_(lseek)( sr_Res(sres), 0, VKI_SEEK_SET ); + if (off < 0) + SET_STATUS_Failure( VKI_EMFILE ); + } + return; + } + + /* Otherwise handle normally */ + *flags |= SfMayBlock; +} + +POST(sys_openat) +{ + vg_assert(SUCCESS); + if (!ML_(fd_allowed)(RES, "openat", tid, True)) { + VG_(close)(RES); + SET_STATUS_Failure( VKI_EMFILE ); + } else { + if (VG_(clo_track_fds)) + ML_(record_fd_open_with_given_name)(tid, RES, (HChar*)ARG2); + } +} + +PRE(sys_mkdirat) +{ + *flags |= SfMayBlock; + PRINT("sys_mkdirat ( %ld, %#lx(%s), %ld )", ARG1,ARG2,(char*)ARG2,ARG3); + PRE_REG_READ3(long, "mkdirat", + int, dfd, const char *, pathname, int, mode); + PRE_MEM_RASCIIZ( "mkdirat(pathname)", ARG2 ); +} + +PRE(sys_mkfifoat) +{ + PRINT("sys_mkfifoat ( %ld, %#lx(%s), 0x%lx )", ARG1,ARG2,(char*)ARG2,ARG3 ); + PRE_REG_READ3(long, "mkfifoat", + int, dfd, const char *, pathname, int, mode); + PRE_MEM_RASCIIZ( "mkfifoat(pathname)", ARG2 ); +} + +PRE(sys_mknodat) +{ + PRINT("sys_mknodat ( %ld, %#lx(%s), 0x%lx, 0x%lx )", ARG1,ARG2,(char*)ARG2,ARG3,ARG4 ); + PRE_REG_READ4(long, "mknodat", + int, dfd, const char *, pathname, int, mode, unsigned, dev); + PRE_MEM_RASCIIZ( "mknodat(pathname)", ARG2 ); +} + +PRE(sys_fchownat) +{ + PRINT("sys_fchownat ( %ld, %#lx(%s), 0x%lx, 0x%lx )", ARG1,ARG2,(char*)ARG2,ARG3,ARG4); + PRE_REG_READ4(long, "fchownat", + int, dfd, const char *, path, + vki_uid_t, owner, vki_gid_t, group); + PRE_MEM_RASCIIZ( "fchownat(path)", ARG2 ); +} + +PRE(sys_futimesat) +{ + PRINT("sys_futimesat ( %ld, %#lx(%s), %#lx )", ARG1,ARG2,(char*)ARG2,ARG3); + PRE_REG_READ3(long, "futimesat", + int, dfd, char *, filename, struct timeval *, tvp); + if (ARG2 != 0) + PRE_MEM_RASCIIZ( "futimesat(filename)", ARG2 ); + if (ARG3 != 0) + PRE_MEM_READ( "futimesat(tvp)", ARG3, 2 * sizeof(struct vki_timeval) ); +} + +PRE(sys_fstatat) +{ + PRINT("sys_fstatat ( %ld, %#lx(%s), %#lx )", ARG1,ARG2,(char*)ARG2,ARG3); + PRE_REG_READ3(long, "fstatat", + int, dfd, char *, file_name, struct stat *, buf); + PRE_MEM_RASCIIZ( "fstatat(file_name)", ARG2 ); + PRE_MEM_WRITE( "fstatat(buf)", ARG3, sizeof(struct vki_stat) ); +} + +POST(sys_fstatat) +{ + POST_MEM_WRITE( ARG3, sizeof(struct vki_stat) ); +} + +PRE(sys_unlinkat) +{ + *flags |= SfMayBlock; + PRINT("sys_unlinkat ( %ld, %#lx(%s) )", ARG1,ARG2,(char*)ARG2); + PRE_REG_READ2(long, "unlinkat", int, dfd, const char *, pathname); + PRE_MEM_RASCIIZ( "unlinkat(pathname)", ARG2 ); +} + +PRE(sys_renameat) +{ + PRINT("sys_renameat ( %ld, %#lx(%s), %ld, %#lx(%s) )", ARG1,ARG2,(char*)ARG2,ARG3,ARG4,(char*)ARG4); + PRE_REG_READ4(long, "renameat", + int, olddfd, const char *, oldpath, + int, newdfd, const char *, newpath); + PRE_MEM_RASCIIZ( "renameat(oldpath)", ARG2 ); + PRE_MEM_RASCIIZ( "renameat(newpath)", ARG4 ); +} + +PRE(sys_linkat) +{ + *flags |= SfMayBlock; + PRINT("sys_linkat ( %ld, %#lx(%s), %ld, %#lx(%s), %ld )",ARG1,ARG2,(char*)ARG2,ARG3,ARG4,(char*)ARG4,ARG5); + PRE_REG_READ5(long, "linkat", + int, olddfd, const char *, oldpath, + int, newdfd, const char *, newpath, + int, flags); + PRE_MEM_RASCIIZ( "linkat(oldpath)", ARG2); + PRE_MEM_RASCIIZ( "linkat(newpath)", ARG4); +} + +PRE(sys_symlinkat) +{ + *flags |= SfMayBlock; + PRINT("sys_symlinkat ( %#lx(%s), %ld, %#lx(%s) )",ARG1,(char*)ARG1,ARG2,ARG3,(char*)ARG3); + PRE_REG_READ3(long, "symlinkat", + const char *, oldpath, int, newdfd, const char *, newpath); + PRE_MEM_RASCIIZ( "symlinkat(oldpath)", ARG1 ); + PRE_MEM_RASCIIZ( "symlinkat(newpath)", ARG3 ); +} + +PRE(sys_readlinkat) +{ + HChar name[25]; + Word saved = SYSNO; + + PRINT("sys_readlinkat ( %ld, %#lx(%s), %#lx, %llu )", ARG1,ARG2,(char*)ARG2,ARG3,(ULong)ARG4); + PRE_REG_READ4(long, "readlinkat", + int, dfd, const char *, path, char *, buf, int, bufsiz); + PRE_MEM_RASCIIZ( "readlinkat(path)", ARG2 ); + PRE_MEM_WRITE( "readlinkat(buf)", ARG3,ARG4 ); + + /* + * Handle the case where readlinkat is looking at /proc/curproc/file or + * /proc//file. + */ + VG_(sprintf)(name, "/proc/%d/file", VG_(getpid)()); + if (ML_(safe_to_deref)((void*)ARG2, 1) + && (VG_(strcmp)((HChar *)ARG2, name) == 0 + || VG_(strcmp)((HChar *)ARG2, "/proc/curproc/file") == 0)) { + VG_(sprintf)(name, "/proc/self/fd/%d", VG_(cl_exec_fd)); + SET_STATUS_from_SysRes( VG_(do_syscall4)(saved, ARG1, (UWord)name, + ARG3, ARG4)); + } else { + /* Normal case */ + SET_STATUS_from_SysRes( VG_(do_syscall4)(saved, ARG1, ARG2, ARG3, ARG4)); + } + + if (SUCCESS && RES > 0) + POST_MEM_WRITE( ARG3, RES ); +} + +PRE(sys_fchmodat) +{ + PRINT("sys_fchmodat ( %ld, %#lx(%s), %ld )", ARG1,ARG2,(char*)ARG2,ARG3); + PRE_REG_READ3(long, "fchmodat", + int, dfd, const char *, path, vki_mode_t, mode); + PRE_MEM_RASCIIZ( "fchmodat(path)", ARG2 ); +} + +PRE(sys_faccessat) +{ + PRINT("sys_faccessat ( %ld, %#lx(%s), %ld )", ARG1,ARG2,(char*)ARG2,ARG3); + PRE_REG_READ3(long, "faccessat", + int, dfd, const char *, pathname, int, mode); + PRE_MEM_RASCIIZ( "faccessat(pathname)", ARG2 ); +} + +/* --------------------------------------------------------------------- + __acl* wrappers + ------------------------------------------------------------------ */ + +PRE(sys___acl_get_file) +{ + PRINT("sys___acl_get_file ( %#lx(%s), %ld, %#lx )", ARG1,(char *)ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "__acl_get_file", + const char *, path, int, acltype, struct vki_acl *, aclp); + PRE_MEM_WRITE( "__acl_get_file(aclp)", ARG3, sizeof(struct vki_acl) ); +} + +POST(sys___acl_get_file) +{ + vg_assert(SUCCESS); + if (RES == 0) { + POST_MEM_WRITE( ARG3, sizeof(struct vki_acl) ); + } +} + +PRE(sys___acl_set_file) +{ + PRINT("sys___acl_set_file ( %#lx(%s), %ld, %#lx )", ARG1,(char *)ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "__acl_set_file", + const char *, path, int, acltype, struct vki_acl *, aclp); + PRE_MEM_READ( "__acl_set_file(aclp)", ARG3, sizeof(struct vki_acl) ); +} + +PRE(sys___acl_get_fd) +{ + PRINT("sys___acl_get_fd ( %ld, %ld, %#lx )", ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "__acl_get_fd", + int, fd, int, acltype, struct vki_acl *, aclp); + PRE_MEM_WRITE( "__acl_get_file(aclp)", ARG3, sizeof(struct vki_acl) ); +} + +POST(sys___acl_get_fd) +{ + vg_assert(SUCCESS); + if (RES == 0) { + POST_MEM_WRITE( ARG3, sizeof(struct vki_acl) ); + } +} + +PRE(sys___acl_set_fd) +{ + PRINT("sys___acl_set_fd ( %ld, %ld, %#lx )", ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "__acl_set_fd", + int, fd, int, acltype, struct vki_acl *, aclp); + PRE_MEM_READ( "__acl_get_file(aclp)", ARG3, sizeof(struct vki_acl) ); +} + +PRE(sys___acl_delete_file) +{ + PRINT("sys___acl_delete_file ( %#lx(%s), %ld )", ARG1,(char *)ARG1,ARG2); + PRE_REG_READ2(long, "__acl_delete_file", + const char *, path, int, acltype); +} + +PRE(sys___acl_delete_fd) +{ + PRINT("sys___acl_delete_fd ( %ld, %ld )", ARG1,ARG2); + PRE_REG_READ2(long, "__acl_delete_fd", + int, fd, int, acltype); +} + +PRE(sys___acl_aclcheck_file) +{ + PRINT("sys___acl_aclcheck_file ( %#lx(%s), %ld, %#lx )", ARG1,(char *)ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "__acl_aclcheck_file", + const char *, path, int, acltype, struct vki_acl *, aclp); + PRE_MEM_READ( "__acl_aclcheck_file(aclp)", ARG3, sizeof(struct vki_acl) ); +} + +PRE(sys___acl_aclcheck_fd) +{ + PRINT("sys___acl_aclcheck_fd ( %ld, %ld, %#lx )", ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "__acl_aclcheck_fd", + int, fd, int, acltype, struct vki_acl *, aclp); + PRE_MEM_READ( "__acl_aclcheck_fd(aclp)", ARG3, sizeof(struct vki_acl) ); +} + +PRE(sys___acl_get_link) +{ + PRINT("sys___acl_get_link ( %#lx(%s), %ld, %#lx )", ARG1,(char *)ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "__acl_get_link", + const char *, path, int, acltype, struct vki_acl *, aclp); + PRE_MEM_WRITE( "__acl_get_link(aclp)", ARG3, sizeof(struct vki_acl) ); +} + +POST(sys___acl_get_link) +{ + vg_assert(SUCCESS); + if (RES == 0) { + POST_MEM_WRITE( ARG3, sizeof(struct vki_acl) ); + } +} + +PRE(sys___acl_set_link) +{ + PRINT("sys___acl_set_link ( %#lx(%s), %ld, %#lx )", ARG1,(char *)ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "__acl_set_link", + const char *, path, int, acltype, struct vki_acl *, aclp); + PRE_MEM_READ( "__acl_set_link(aclp)", ARG3, sizeof(struct vki_acl) ); +} + +PRE(sys___acl_delete_link) +{ + PRINT("sys___acl_delete_link ( %#lx(%s), %ld )", ARG1,(char *)ARG1,ARG2); + PRE_REG_READ2(long, "__acl_delete_link", + const char *, path, int, acltype); +} + +PRE(sys___acl_aclcheck_link) +{ + PRINT("sys___acl_aclcheck_link ( %#lx(%s), %ld, %#lx )", ARG1,(char *)ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "__acl_aclcheck_link", + const char *, path, int, acltype, struct vki_acl *, aclp); + PRE_MEM_READ( "__acl_aclcheck_link(aclp)", ARG3, sizeof(struct vki_acl) ); +} + +POST(sys_getcontext) +{ + POST_MEM_WRITE( ARG1, sizeof(struct vki_ucontext) ); +} + +POST(sys_swapcontext) +{ + if (SUCCESS) + POST_MEM_WRITE( ARG1, sizeof(struct vki_ucontext) ); +} + +PRE(sys_fcntl) +{ + switch (ARG2) { + // These ones ignore ARG3. + case VKI_F_GETFD: + case VKI_F_GETFL: + case VKI_F_GETOWN: + PRINT("sys_fcntl ( %ld, %ld )", ARG1,ARG2); + PRE_REG_READ2(long, "fcntl", unsigned int, fd, unsigned int, cmd); + break; + + // These ones use ARG3 as "arg". + case VKI_F_DUPFD: + case VKI_F_SETFD: + case VKI_F_SETFL: + case VKI_F_SETOWN: + PRINT("sys_fcntl[ARG3=='arg'] ( %ld, %ld, %ld )", ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "fcntl", + unsigned int, fd, unsigned int, cmd, unsigned long, arg); + break; + + // These ones use ARG3 as "lock" - obsolete. + case VKI_F_OSETLKW: + *flags |= SfMayBlock; + /* FALLTHROUGH */ + case VKI_F_OGETLK: + case VKI_F_OSETLK: + PRINT("sys_fcntl[ARG3=='lock'] ( %ld, %ld, %#lx )", ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "fcntl", + unsigned int, fd, unsigned int, cmd, + struct oflock *, lock); + break; + + // This one uses ARG3 as "oldd" and ARG4 as "newd". + case VKI_F_DUP2FD: + PRINT("sys_fcntl[ARG3=='oldd', ARG4=='newd'] ( %ld, %ld, %ld, %ld )", + ARG1,ARG2,ARG3,ARG4); + PRE_REG_READ4(long, "fcntl", + unsigned int, fd, unsigned int, cmd, + unsigned long, oldd, unsigned long, newd); + break; + + // These ones use ARG3 as "lock". + case VKI_F_SETLKW: + *flags |= SfMayBlock; + /* FALLTHROUGH */ + case VKI_F_GETLK: + case VKI_F_SETLK: + case VKI_F_SETLK_REMOTE: + PRINT("sys_fcntl[ARG3=='lock'] ( %ld, %ld, %#lx )", ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "fcntl", + unsigned int, fd, unsigned int, cmd, + struct flock *, lock); + break; + + default: + PRINT("sys_fcntl[UNKNOWN] ( %ld, %ld, %ld )", ARG1,ARG2,ARG3); + I_die_here; + break; + } +} + +POST(sys_fcntl) +{ + vg_assert(SUCCESS); + if (ARG2 == VKI_F_DUPFD) { + if (!ML_(fd_allowed)(RES, "fcntl(DUPFD)", tid, True)) { + VG_(close)(RES); + SET_STATUS_Failure( VKI_EMFILE ); + } else { + if (VG_(clo_track_fds)) + ML_(record_fd_open_named)(tid, RES); + } + } +} + +PRE(sys_ioctl) +{ + UInt dir = _VKI_IOC_DIR(ARG2); + UInt size = _VKI_IOC_SIZE(ARG2); + *flags |= SfMayBlock; + PRINT("sys_ioctl ( %ld, 0x%lx, %#lx )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "ioctl", + unsigned int, fd, unsigned int, request, unsigned long, arg); + +/* On FreeBSD, ALL ioctl's are IOR/IOW encoded. Just use the default decoder */ + if (SimHintiS(SimHint_lax_ioctls, VG_(clo_sim_hints))) { + /* + * Be very lax about ioctl handling; the only + * assumption is that the size is correct. Doesn't + * require the full buffer to be initialized when + * writing. Without this, using some device + * drivers with a large number of strange ioctl + * commands becomes very tiresome. + */ + } else if (/* size == 0 || */ dir == _VKI_IOC_NONE) { + static Int moans = 3; + if (moans > 0 && !VG_(clo_xml)) { + moans--; + VG_(message)(Vg_UserMsg, + "Warning: noted but unhandled ioctl 0x%lx" + " with no size/direction hints", + ARG2); + VG_(message)(Vg_UserMsg, + " This could cause spurious value errors" + " to appear."); + VG_(message)(Vg_UserMsg, + " See README_MISSING_SYSCALL_OR_IOCTL for " + "guidance on writing a proper wrapper." ); + } + } else { + if ((dir & _VKI_IOC_WRITE) && size > 0) + PRE_MEM_READ( "ioctl(generic)", ARG3, size); + if ((dir & _VKI_IOC_READ) && size > 0) + PRE_MEM_WRITE( "ioctl(generic)", ARG3, size); + } +} + +POST(sys_ioctl) +{ + UInt dir = _VKI_IOC_DIR(ARG2); + UInt size = _VKI_IOC_SIZE(ARG2); + vg_assert(SUCCESS); + if (size > 0 && (dir & _VKI_IOC_READ) + && RES == 0 && ARG3 != (Addr)NULL) + POST_MEM_WRITE(ARG3, size); +} + +PRE(sys_ptrace) +{ + struct vki_ptrace_io_desc *io_desc; + PRINT("sys_ptrace ( %ld, %ld, 0x%lx, %ld)", ARG1, ARG2, ARG3, ARG4); + + PRE_REG_READ4(int, "ptrace", int, request, int, pid, char *, addr, int, data); + + switch (ARG1) { + case VKI_PTRACE_TRACEME: + break; + case VKI_PTRACE_READ_I: + case VKI_PTRACE_READ_D: + break; + + case VKI_PTRACE_WRITE_I: + case VKI_PTRACE_WRITE_D: + break; + + case VKI_PTRACE_IO: + PRE_MEM_READ("ptrace", ARG3, sizeof(struct vki_ptrace_io_desc)); + io_desc = (struct vki_ptrace_io_desc *)ARG3; + switch (io_desc->piod_op) { + case VKI_PIOD_READ_D: + case VKI_PIOD_READ_I: + PRE_MEM_WRITE( "ptrace", (UWord)io_desc->piod_addr, io_desc->piod_len); + break; + case VKI_PIOD_WRITE_D: + case VKI_PIOD_WRITE_I: + PRE_MEM_READ( "ptrace", (UWord)io_desc->piod_addr, io_desc->piod_len); + break; + } + break; + + case VKI_PTRACE_CONTINUE: + break; + + case VKI_PTRACE_STEP: + break; + + case VKI_PTRACE_KILL: + break; + + case VKI_PTRACE_ATTACH: + break; + + case VKI_PTRACE_DETACH: + break; + + case VKI_PTRACE_GETREGS: + PRE_MEM_WRITE( "ptrace", ARG3, sizeof(struct vki_reg_struct)); + break; + + case VKI_PTRACE_SETREGS: + PRE_MEM_READ( "ptrace", ARG3, sizeof(struct vki_reg_struct)); + break; + + case VKI_PTRACE_GETFPREGS: + PRE_MEM_WRITE( "ptrace", ARG3, sizeof(struct vki_fpreg)); + break; + + case VKI_PTRACE_SETFPREGS: + PRE_MEM_READ( "ptrace", ARG3, sizeof(struct vki_fpreg)); + break; + + case VKI_PTRACE_GETDBREGS: + PRE_MEM_WRITE( "ptrace", ARG3, sizeof(struct vki_dbreg)); + break; + + case VKI_PTRACE_SETDBREGS: + PRE_MEM_READ( "ptrace", ARG3, sizeof(struct vki_dbreg)); + break; + + case VKI_PTRACE_LWPINFO: + PRE_MEM_WRITE( "ptrace", ARG3, sizeof(struct vki_ptrace_lwpinfo)); + break; + + case VKI_PTRACE_GETNUMLWPS: + break; + + case VKI_PTRACE_GETLWPLIST: + PRE_MEM_WRITE( "ptrace", ARG3, sizeof(vki_lwpid_t) * ARG4); + break; + + case VKI_PTRACE_SETSTEP: + break; + + case VKI_PTRACE_CLEARSTEP: + break; + + case VKI_PTRACE_SUSPEND: + break; + + case VKI_PTRACE_RESUME: + break; + + case VKI_PTRACE_TO_SCE: + break; + + case VKI_PTRACE_TO_SCX: + break; + + case VKI_PTRACE_SYSCALL: + break; + + case VKI_PTRACE_VM_TIMESTAMP: + break; + + case VKI_PTRACE_VM_ENTRY: + PRE_MEM_WRITE( "ptrace", ARG3, sizeof(struct vki_ptrace_vm_entry)); + break; + } +} + +POST(sys_ptrace) +{ + struct vki_ptrace_io_desc *io_desc; + + switch (ARG1) { + case VKI_PTRACE_TRACEME: + break; + case VKI_PTRACE_READ_I: + case VKI_PTRACE_READ_D: + break; + + case VKI_PTRACE_WRITE_I: + case VKI_PTRACE_WRITE_D: + break; + + case VKI_PTRACE_IO: + io_desc = (struct vki_ptrace_io_desc *)ARG3; + switch (io_desc->piod_op) { + case VKI_PIOD_READ_D: + case VKI_PIOD_READ_I: + if (RES != -1) + POST_MEM_WRITE((UWord)io_desc->piod_addr, io_desc->piod_len); + break; + case VKI_PIOD_WRITE_D: + case VKI_PIOD_WRITE_I: + break; + } + break; + + case VKI_PTRACE_CONTINUE: + break; + + case VKI_PTRACE_STEP: + break; + + case VKI_PTRACE_KILL: + break; + + case VKI_PTRACE_ATTACH: + break; + + case VKI_PTRACE_DETACH: + break; + + case VKI_PTRACE_GETREGS: + if (RES != -1) + POST_MEM_WRITE(ARG3, sizeof(struct vki_reg_struct)); + break; + + case VKI_PTRACE_SETREGS: + break; + + case VKI_PTRACE_GETFPREGS: + if (RES != -1) + POST_MEM_WRITE(ARG3, sizeof(struct vki_fpreg)); + break; + + case VKI_PTRACE_SETFPREGS: + break; + + case VKI_PTRACE_GETDBREGS: + if (RES != -1) + POST_MEM_WRITE(ARG3, sizeof(struct vki_dbreg)); + break; + + case VKI_PTRACE_SETDBREGS: + break; + + case VKI_PTRACE_LWPINFO: + if (RES != -1) + POST_MEM_WRITE(ARG3, sizeof(struct vki_ptrace_lwpinfo)); + break; + + case VKI_PTRACE_GETNUMLWPS: + break; + + case VKI_PTRACE_GETLWPLIST: + if (RES != -1) + POST_MEM_WRITE(ARG3, sizeof(vki_lwpid_t) * RES); + break; + + case VKI_PTRACE_SETSTEP: + break; + + case VKI_PTRACE_CLEARSTEP: + break; + + case VKI_PTRACE_SUSPEND: + break; + + case VKI_PTRACE_RESUME: + break; + + case VKI_PTRACE_TO_SCE: + break; + + case VKI_PTRACE_TO_SCX: + break; + + case VKI_PTRACE_SYSCALL: + break; + + case VKI_PTRACE_VM_TIMESTAMP: + break; + + case VKI_PTRACE_VM_ENTRY: + if (RES != -1) + POST_MEM_WRITE(ARG3, sizeof(struct vki_ptrace_vm_entry)); + break; + } +} + +PRE(sys_cpuset_setaffinity) +{ + PRE_MEM_READ("cpuset_setaffinity", ARG5, ARG4); +} + +#undef PRE +#undef POST + +const SyscallTableEntry ML_(syscall_table)[] = { + // syscall (handled specially) // 0 + BSDX_(__NR_exit, sys_exit), // 1 + BSDX_(__NR_fork, sys_fork), // 2 + GENXY(__NR_read, sys_read), // 3 + + GENX_(__NR_write, sys_write), // 4 + GENXY(__NR_open, sys_open), // 5 + GENXY(__NR_close, sys_close), // 6 + GENXY(__NR_wait4, sys_wait4), // 7 + + // 4.3 creat 8 + GENX_(__NR_link, sys_link), // 9 + GENX_(__NR_unlink, sys_unlink), // 10 + // obsol execv 11 + + GENX_(__NR_chdir, sys_chdir), // 12 + GENX_(__NR_fchdir, sys_fchdir), // 13 + GENX_(__NR_mknod, sys_mknod), // 14 + GENX_(__NR_chmod, sys_chmod), // 15 + + GENX_(__NR_chown, sys_chown), // 16 + GENX_(__NR_break, sys_brk), // 17 + BSDXY(__NR_getfsstat4, sys_getfsstat4), // 18 + // 4.3 lseek 19 + + GENX_(__NR_getpid, sys_getpid), // 20 + BSDX_(__NR_mount, sys_mount), // 21 + BSDX_(__NR_unmount, sys_unmount), // 22 + GENX_(__NR_setuid, sys_setuid), // 23 + + GENX_(__NR_getuid, sys_getuid), // 24 + GENX_(__NR_geteuid, sys_geteuid), // 25 + BSDXY(__NR_ptrace, sys_ptrace), // 26 + BSDXY(__NR_recvmsg, sys_recvmsg), // 27 + + BSDX_(__NR_sendmsg, sys_sendmsg), // 28 + BSDXY(__NR_recvfrom, sys_recvfrom), // 29 + BSDXY(__NR_accept, sys_accept), // 30 + BSDXY(__NR_getpeername, sys_getpeername), // 31 + + BSDXY(__NR_getsockname, sys_getsockname), // 32 + GENX_(__NR_access, sys_access), // 33 + BSDX_(__NR_chflags, sys_chflags), // 34 + BSDX_(__NR_fchflags, sys_fchflags), // 35 + + GENX_(__NR_sync, sys_sync), // 36 + GENX_(__NR_kill, sys_kill), // 37 + // 4.3 stat 38 + GENX_(__NR_getppid, sys_getppid), // 39 + + // 4.3 lstat 40 + GENXY(__NR_dup, sys_dup), // 41 + BSDXY(__NR_pipe, sys_pipe), // 42 + GENX_(__NR_getegid, sys_getegid), // 43 + + // GENX_(__NR_profil, sys_profil), // 44 +// BSDX_(__NR_ktrace, sys_ktrace), // 45 + // 4.3 sigaction 46 + GENX_(__NR_getgid, sys_getgid), // 47 + + // 4.3 sigaction (int sigset) 48 + BSDXY(__NR_getlogin, sys_getlogin), // 49 + BSDX_(__NR_setlogin, sys_setlogin), // 50 + GENX_(__NR_acct, sys_acct), // 51 + + // 4.3 sigpending 52 + GENXY(__NR_sigaltstack, sys_sigaltstack), // 53 + BSDXY(__NR_ioctl, sys_ioctl), // 54 +// BSDX_(__NR_reboot, sys_reboot), // 55 + + BSDX_(__NR_revoke, sys_revoke), // 56 + GENX_(__NR_symlink, sys_symlink), // 57 + GENX_(__NR_readlink, sys_readlink), // 58 + GENX_(__NR_execve, sys_execve), // 59 + + GENX_(__NR_umask, sys_umask), // 60 + GENX_(__NR_chroot, sys_chroot), // 61 + // 4.3 fstat 62 + // 4.3 getgerninfo 63 + + // 4.3 getpagesize 64 + GENX_(__NR_msync, sys_msync), // 65 + BSDX_(__NR_vfork, sys_fork), // 66 + // obsol vread 67 + + // obsol vwrite 68 + // BSDX_(__NR_sbrk, sys_sbrk), // 69 + // BSDX_(__NR_sstk, sys_sstk), // 70 + // 4.3 mmap 71 + + // 4.2 vadvise 72 + GENXY(__NR_munmap, sys_munmap), // 73 + GENXY(__NR_mprotect, sys_mprotect), // 74 + GENX_(__NR_madvise, sys_madvise), // 75 + + // obsol vhangup 76 + // obsol vlimit 77 + GENXY(__NR_mincore, sys_mincore), // 78 + GENXY(__NR_getgroups, sys_getgroups), // 79 + + GENX_(__NR_setgroups, sys_setgroups), // 80 + GENX_(__NR_getpgrp, sys_getpgrp), // 81 + GENX_(__NR_setpgid, sys_setpgid), // 82 + GENXY(__NR_setitimer, sys_setitimer), // 83 + + // 4.3 wait 84 +// BSDX_(__NR_swapon, sys_swapon), // 85 + GENXY(__NR_getitimer, sys_getitimer), // 86 + // 4.3 gethostname 87 + + // 4.3 sethostname 88 + BSDX_(__NR_getdtablesize, sys_getdtablesize), // 89 + GENXY(__NR_dup2, sys_dup2), // 90 + // unimpl getdopt 91 + + BSDXY(__NR_fcntl, sys_fcntl), // 92 + GENX_(__NR_select, sys_select), // 93 + // unimpl setdopt 94 + GENX_(__NR_fsync, sys_fsync), // 95 + + GENX_(__NR_setpriority, sys_setpriority), // 96 + BSDXY(__NR_socket, sys_socket), // 97 + BSDX_(__NR_connect, sys_connect), // 98 + // 4.3 accept 99 + + GENX_(__NR_getpriority, sys_getpriority), // 100 + // 4.3 send 101 + // 4.3 recv 102 + // 4.3 sigreturn 103 + + BSDX_(__NR_bind, sys_bind), // 104 + BSDX_(__NR_setsockopt, sys_setsockopt), // 105 + BSDX_(__NR_listen, sys_listen), // 106 + // obsol vtimes 107 + + // 4.3 sigvec 108 + // 4.3 sigblock 109 + // 4.3 sigsetmask 110 + // 4.3 sigsuspend 111 + + // 4.3 sigstack 112 + // 4.3 recvmsg 113 + // 4.3 sendmsg 114 + // 4.3 vtrace 115 + + GENXY(__NR_gettimeofday, sys_gettimeofday), // 116 + GENXY(__NR_getrusage, sys_getrusage), // 117 + BSDXY(__NR_getsockopt, sys_getsockopt), // 118 + // unimpl resuba 119 + + GENXY(__NR_readv, sys_readv), // 120 + GENX_(__NR_writev, sys_writev), // 121 + GENX_(__NR_settimeofday, sys_settimeofday), // 122 + GENX_(__NR_fchown, sys_fchown), // 123 + + GENX_(__NR_fchmod, sys_fchmod), // 124 + // 4.3 recvfrom 125 + GENX_(__NR_setreuid, sys_setreuid), // 126 + GENX_(__NR_setregid, sys_setregid), // 127 + + GENX_(__NR_rename, sys_rename), // 128 + // 4.3 truncate 129 + // 4.3 ftruncate 130 + GENX_(__NR_flock, sys_flock), // 131 + + BSDX_(__NR_mkfifo, sys_mkfifo), // 132 + BSDX_(__NR_sendto, sys_sendto), // 133 + BSDX_(__NR_shutdown, sys_shutdown), // 134 + BSDXY(__NR_socketpair, sys_socketpair), // 135 + + GENX_(__NR_mkdir, sys_mkdir), // 136 + GENX_(__NR_rmdir, sys_rmdir), // 137 + GENX_(__NR_utimes, sys_utimes), // 138 + // 4.2 sigreturn 139 + +// BSDXY(__NR_adjtime, sys_adjtime), // 140 + // 4.3 getpeername 141 + // 4.3 gethostid 142 + // 4.3 sethostid 143 + + // 4.3 getrlimit 144 + // 4.3 setrlimit 145 + // 4.3 killpg 146 + GENX_(__NR_setsid, sys_setsid), // 147 + + BSDX_(__NR_quotactl, sys_quotactl), // 148 + // 4.3 quota 149 + // 4.3 getsockname 150 + // bsd/os sem_lock 151 + + // bsd/os sem_wakeup 152 + // bsd/os asyncdaemon 153 + // nosys 154 + // BSDXY(__NR_nfssvc, sys_nfssvc), // 155 + + // 4.3 getdirentries 156 + GENXY(__NR_statfs, sys_statfs), // 157 + GENXY(__NR_fstatfs, sys_fstatfs), // 158 + // nosys 159 + +// BSDXY(__NR_lgetfh, sys_lgetfh), // 160 +// BSDXY(__NR_getfh, sys_getfh), // 161 + BSDXY(__NR_getdomainname, sys_getdomainname), // 162 + BSDX_(__NR_setdomainname, sys_setdomainname), // 163 + + BSDXY(__NR_uname, sys_uname), // 164 + BSDX_(__NR_sysarch, sys_sysarch), // 165 +// BSDXY(__NR_rtprio, sys_rtprio), // 166 + // nosys 167 + + // nosys 168 +// BSDXY(__NR_semsys, sys_semsys), // 169 +// BSDXY(__NR_msgsys, sys_msgsys), // 170 +// BSDXY(__NR_shmsys, sys_shmsys), // 171 + + // nosys 172 + BSDXY(__NR_pread6, sys_pread), // 173 + BSDX_(__NR_pwrite6, sys_pwrite), // 174 + // nosys 175 + +// BSDXY(__NR_ntp_adjtime, sys_ntp_adjtime), // 176 + // bsd/os sfork 177 + // bsd/os getdescriptor 178 + // bsd/os setdescriptor 179 + + // nosys 180 + GENX_(__NR_setgid, sys_setgid), // 181 + BSDX_(__NR_setegid, sys_setegid), // 182 + BSDX_(__NR_seteuid, sys_seteuid), // 183 + + // unimpl lfs_bmapv 184 + // unimpl lfs_markv 185 + // unimpl lfs_segclean 186 + // unimpl lfs_segwait 187 + + BSDXY(__NR_stat, sys_stat), // 188 + BSDXY(__NR_fstat, sys_fstat), // 189 + BSDXY(__NR_lstat, sys_lstat), // 190 + BSDX_(__NR_pathconf, sys_pathconf), // 191 + + BSDX_(__NR_fpathconf, sys_fpathconf), // 192 + // nosys 193 + GENXY(__NR_getrlimit, sys_getrlimit), // 194 + GENX_(__NR_setrlimit, sys_setrlimit), // 195 + + BSDXY(__NR_getdirentries, sys_getdirentries), // 196 + BSDX_(__NR_mmap, sys_mmap7), // 197 + // __syscall (handled specially) // 198 + BSDX_(__NR_lseek6, sys_lseek), // 199 + + BSDX_(__NR_truncate, sys_truncate), // 200 + BSDX_(__NR_ftruncate, sys_ftruncate), // 201 + BSDXY(__NR___sysctl, sys___sysctl), // 202 + GENX_(__NR_mlock, sys_mlock), // 203 + + GENX_(__NR_munlock, sys_munlock), // 204 + BSDX_(__NR_undelete, sys_undelete), // 205 + BSDX_(__NR_futimes, sys_futimes), // 206 + GENX_(__NR_getpgid, sys_getpgid), // 207 + + // netbsd newreboot 208 + GENXY(__NR_poll, sys_poll), // 209 + BSDX_(__NR_lkmnosys0, sys_lkmnosys0), // 210 + BSDX_(__NR_lkmnosys1, sys_lkmnosys1), // 211 + + BSDX_(__NR_lkmnosys2, sys_lkmnosys2), // 212 + BSDX_(__NR_lkmnosys3, sys_lkmnosys3), // 213 + BSDX_(__NR_lkmnosys4, sys_lkmnosys4), // 214 + BSDX_(__NR_lkmnosys5, sys_lkmnosys5), // 215 + + BSDX_(__NR_lkmnosys6, sys_lkmnosys6), // 216 + BSDX_(__NR_lkmnosys7, sys_lkmnosys7), // 217 + BSDX_(__NR_lkmnosys8, sys_lkmnosys8), // 218 +// BSDXY(__NR_nfs_fhopen, sys_nfs_fhopen), // 219 + + BSDXY(__NR___semctl7, sys___semctl7), // 220 + BSDX_(__NR_semget, sys_semget), // 221 + BSDX_(__NR_semop, sys_semop), // 222 + // unimpl semconfig 223 + +// BSDXY(__NR_msgctl, sys_msgctl), // 224 +// BSDX_(__NR_msgget, sys_msgget), // 225 +// BSDX_(__NR_msgsnd, sys_msgsnd), // 226 +// BSDXY(__NR_msgrcv, sys_msgrcv), // 227 + + BSDXY(__NR_shmat, sys_shmat), // 228 + BSDXY(__NR_shmctl7, sys_shmctl7), // 229 + BSDXY(__NR_shmdt, sys_shmdt), // 230 + BSDX_(__NR_shmget, sys_shmget), // 231 + + BSDXY(__NR_clock_gettime, sys_clock_gettime), // 232 + BSDX_(__NR_clock_settime, sys_clock_settime), // 233 + BSDXY(__NR_clock_getres, sys_clock_getres), // 234 + // unimpl timer_create 235 + + // unimpl timer_delete 236 + // unimpl timer_settime 237 + // unimpl timer_gettime 238 + // unimpl timer_getoverrun 239 + + GENXY(__NR_nanosleep, sys_nanosleep), // 240 + // nosys 241 + // nosys 242 + // nosys 243 + + // nosys 244 + // nosys 245 + // nosys 246 + // nosys 247 + +// BSDXY(__NR_ntp_gettime, sys_ntp_gettime), // 248 + // nosys 249 +// BSDXY(__NR_minherit, sys_minherit), // 250 + BSDX_(__NR_rfork, sys_rfork), // 251 + + GENXY(__NR_openbsd_poll, sys_poll), // 252 + BSDX_(__NR_issetugid, sys_issetugid), // 253 + GENX_(__NR_lchown, sys_lchown), // 254 + // nosys 255 + + // nosys 256 + // nosys 257 + // nosys 258 + // nosys 259 + + // nosys 260 + // nosys 261 + // nosys 262 + // nosys 263 + + // nosys 264 + // nosys 265 + // nosys 266 + // nosys 267 + + // nosys 268 + // nosys 269 + // nosys 270 + // nosys 271 + + GENXY(__NR_getdents, sys_getdents), // 272 + // nosys 273 + BSDX_(__NR_lchmod, sys_lchmod), // 274 + GENX_(__NR_netbsd_lchown, sys_lchown), // 275 + + BSDX_(__NR_lutimes, sys_lutimes), // 276 + // netbsd msync 277 + // netbsd stat 278 + // netbsd fstat 279 + + // netbsd lstat 280 + // nosys 281 + // nosys 282 + // nosys 283 + + // nosys 284 + // nosys 285 + // nosys 286 + // nosys 287 + + // nosys 288 + // nosys 289 + // nosys 290 + // nosys 291 + + // nosys 292 + // nosys 293 + // nosys 294 + // nosys 295 + + // nosys 296 + BSDXY(__NR_fhstatfs, sys_fhstatfs), // 297 + BSDXY(__NR_fhopen, sys_fhopen), // 298 + BSDXY(__NR_fhstat, sys_fhstat), // 299 + +// BSDX_(__NR_modnext, sys_modnext), // 300 + BSDXY(__NR_modstat, sys_modstat), // 301 +// BSDX_(__NR_modfnext, sys_modfnext), // 302 + BSDX_(__NR_modfind, sys_modfind), // 303 + +// BSDX_(__NR_kldload, sys_kldload), // 304 +// BSDX_(__NR_kldunload, sys_kldunload), // 305 +// BSDX_(__NR_kldfind, sys_kldfind), // 306 +// BSDX_(__NR_kldnext, sys_kldnext), // 307 + +// BSDXY(__NR_kldstat, sys_kldstat), // 308 +// BSDX_(__NR_kldfirstmod, sys_kldfirstmod), // 309 + GENX_(__NR_getsid, sys_getsid), // 310 + BSDX_(__NR_setresuid, sys_setresuid), // 311 + + BSDX_(__NR_setresgid, sys_setresgid), // 312 + // obsol signanosleep 313 + // BSDXY(__NR_aio_return, sys_aio_return), // 314 + // BSDXY(__NR_aio_suspend, sys_aio_suspend), // 315 + + // BSDXY(__NR_aio_cancel, sys_aio_cancel), // 316 + // BSDXY(__NR_aio_error, sys_aio_error), // 317 + // BSDXY(__NR_aio_read, sys_aio_read), // 318 + // BSDXY(__NR_aio_write, sys_aio_write), // 319 + + // BSDXY(__NR_lio_listio, sys_lio_listio), // 320 + BSDX_(__NR_yield, sys_yield), // 321 + // nosys 322 + // nosys 323 + + GENX_(__NR_mlockall, sys_mlockall), // 324 + BSDX_(__NR_munlockall, sys_munlockall), // 325 + BSDXY(__NR___getcwd, sys___getcwd), // 326 +// BSDXY(__NR_sched_setparam, sys_sched_setparam), // 327 + +// BSDXY(__NR_sched_getparam, sys_sched_getparam), // 328 +// BSDX_(__NR_sched_setscheduler, sys_sched_setscheduler), // 329 +// BSDX_(__NR_sched_getscheduler, sys_sched_getscheduler), // 330 + BSDX_(__NR_sched_yield, sys_sched_yield), // 331 + + BSDX_(__NR_sched_get_priority_max, sys_sched_get_priority_max), // 332 + BSDX_(__NR_sched_get_priority_min, sys_sched_get_priority_min), // 333 +// BSDXY(__NR_sched_rr_get_interval, sys_sched_rr_get_interval), // 334 + BSDX_(__NR_utrace, sys_utrace), // 335 + + // compat3 sendfile 336 +// BSDXY(__NR_kldsym, sys_kldsym), // 337 +// BSDX_(__NR_jail, sys_jail), // 338 + // unimpl pioctl 339 + + BSDXY(__NR_sigprocmask, sys_sigprocmask), // 340 + BSDX_(__NR_sigsuspend, sys_sigsuspend), // 341 + BSDXY(__NR_sigaction4, sys_sigaction4), // 342 + BSDXY(__NR_sigpending, sys_sigpending), // 343 + +// BSDX_(__NR_sigreturn4, sys_sigreturn4), // 344 + BSDXY(__NR_sigtimedwait, sys_sigtimedwait), // 345 + BSDXY(__NR_sigwaitinfo, sys_sigwaitinfo), // 346 + BSDXY(__NR___acl_get_file, sys___acl_get_file), // 347 + + BSDX_(__NR___acl_set_file, sys___acl_set_file), // 348 + BSDXY(__NR___acl_get_fd, sys___acl_get_fd), // 349 + BSDX_(__NR___acl_set_fd, sys___acl_set_fd), // 350 + BSDX_(__NR___acl_delete_file, sys___acl_delete_file), // 351 + + BSDX_(__NR___acl_delete_fd, sys___acl_delete_fd), // 352 + BSDX_(__NR___acl_aclcheck_file, sys___acl_aclcheck_file), // 353 + BSDX_(__NR___acl_aclcheck_fd, sys___acl_aclcheck_fd), // 354 + // BSDXY(__NR_extattrctl, sys_extattrctl), // 355 + + // BSDXY(__NR_extattr_set_file, sys_extattr_set_file), // 356 + // BSDXY(__NR_extattr_get_file, sys_extattr_get_file), // 357 + // BSDXY(__NR_extattr_delete_file, sys_extattr_delete_file), // 358 + // BSDXY(__NR_aio_waitcomplete, sys_aio_waitcomplete), // 359 + + BSDXY(__NR_getresuid, sys_getresuid), // 360 + BSDXY(__NR_getresgid, sys_getresgid), // 361 + BSDX_(__NR_kqueue, sys_kqueue), // 362 + BSDXY(__NR_kevent, sys_kevent), // 363 + + // nosys 364 + // nosys 365 + // nosys 366 + // nosys 367 + + // nosys 368 + // nosys 369 + // lkmressys 370 + // extattr_set_fd 371 + + // extattr_get_fd 372 + // extattr_delete_fd 373 + // __setugid 374 + // nfsclnt 375 + + BSDX_(__NR_eaccess, sys_eaccess), // 376 + // afs_syscall 377 + // nmount 378 + // kse_exit 379 + + // kse_wakeup 380 + // kse_create 381 + // kse_thr_interrupt 382 + // kse_release 383 + + // __mac_get_proc 384 + // __mac_set_proc 385 + // __mac_get_fd 386 + // __mac_get_file 387 + + // __mac_set_fd 388 + // __mac_set_file 389 + BSDXY(__NR_kenv, sys_kenv), // 390 + // lchflags 391 + + BSDXY(__NR_uuidgen, sys_uuidgen), // 392 + BSDXY(__NR_sendfile, sys_sendfile), // 393 + // mac_syscall 394 + BSDXY(__NR_getfsstat, sys_getfsstat), // 395 + + BSDXY(__NR_statfs6, sys_statfs6), // 396 + BSDXY(__NR_fstatfs6, sys_fstatfs6), // 397 + BSDXY(__NR_fhstatfs6, sys_fhstatfs6), // 398 + // nosys 399 + + // ksem_close 400 + // ksem_post 401 + // ksem_wait 402 + // ksem_trywait 403 + + // ksem_init 404 + // ksem_open 405 + // ksem_unlink 406 + // ksem_getvalue 407 + + // ksem_destroy 408 + // __mac_get_pid 409 + // __mac_get_link 410 + // __mac_set_link 411 + + // extattr_set_link 412 + // extattr_get_link 413 + // extattr_delete_link 414 + // __mac_execve 415 + + BSDXY(__NR_sigaction, sys_sigaction), // 416 + BSDX_(__NR_sigreturn, sys_sigreturn), // 417 + // __xstat 418 + // __xfstat 419 + + // __xlstat 420 + BSDXY(__NR_getcontext, sys_getcontext), // 421 + BSDX_(__NR_setcontext, sys_setcontext), // 422 + BSDXY(__NR_swapcontext, sys_swapcontext), // 423 + + // swapoff 424 + BSDXY(__NR___acl_get_link, sys___acl_get_link), // 425 + BSDX_(__NR___acl_set_link, sys___acl_set_link), // 426 + BSDX_(__NR___acl_delete_link, sys___acl_delete_link), // 427 + + BSDX_(__NR___acl_aclcheck_link, sys___acl_aclcheck_link), // 428 + //!sigwait 429 + // thr_create 430 + BSDX_(__NR_thr_exit, sys_thr_exit), // 431 + + BSDXY(__NR_thr_self, sys_thr_self), // 432 + BSDXY(__NR_thr_kill, sys_thr_kill), // 433 + BSDXY(__NR__umtx_lock, sys__umtx_lock), // 434 + BSDXY(__NR__umtx_unlock, sys__umtx_unlock), // 435 + + // jail_attach 436 + // extattr_list_fd 437 + // extattr_list_file 438 + // extattr_list_link 439 + + // kse_switchin 440 + // ksem_timedwait 441 + // thr_suspend 442 + BSDX_(__NR_thr_wake, sys_thr_wake), // 443 + // kldunloadf 444 + // audit 445 + // auditon 446 + // getauid 447 + + // setauid 448 + // getaudit 449 + // setaudit 450 + // getaudit_addr 451 + + // setaudit_addr 452 + // auditctl 453 + BSDXY(__NR__umtx_op, sys__umtx_op), // 454 + BSDX_(__NR_thr_new, sys_thr_new), // 455 + + // sigqueue 456 + // kmq_open 457 + // kmq_setattr 458 + // kmq_timedreceive 459 + + // kmq_timedsend 460 + // kmq_notify 461 + // kmq_unlink 462 + // abort2 463 + + BSDX_(__NR_thr_set_name, sys_thr_set_name), // 464 + // aio_fsync 465 + BSDXY(__NR_rtprio_thread, sys_rtprio_thread), // 466 + // nosys 467 + + // nosys 468 + // __getpath_fromfd 469 + // __getpath_fromaddr 470 + // sctp_peeloff 471 + + // sctp_generic_sendmsg 472 + // sctp_generic_sendmsg_iov 473 + // sctp_generic_recvmsg 474 + BSDXY(__NR_pread, sys_pread7), // 475 + + BSDX_(__NR_pwrite, sys_pwrite7), // 476 + BSDX_(__NR_mmap, sys_mmap7), // 477 + BSDX_(__NR_lseek, sys_lseek7), // 478 + BSDX_(__NR_truncate7, sys_truncate7), // 479 + + BSDX_(__NR_ftruncate7, sys_ftruncate7), // 480 + BSDXY(__NR_thr_kill2, sys_thr_kill2), // 481 + BSDXY(__NR_shm_open, sys_shm_open), // 482 + BSDX_(__NR_shm_unlink, sys_shm_unlink), // 483 + + // cpuset 484 + // cpuset_setid 485 + // cpuset_getid 486 + // cpuset_getaffinity 487 + + BSDX_(__NR_cpuset_setaffinity, sys_cpuset_setaffinity), // 488 + BSDX_(__NR_faccessat, sys_faccessat), // 489 + BSDX_(__NR_fchmodat, sys_fchmodat), // 490 + BSDX_(__NR_fchownat, sys_fchownat), // 491 + + // fexecve 492 + BSDXY(__NR_fstatat, sys_fstatat), // 493 + BSDX_(__NR_futimesat, sys_futimesat), // 494 + BSDX_(__NR_linkat, sys_linkat), // 495 + + BSDX_(__NR_mkdirat, sys_mkdirat), // 496 + BSDX_(__NR_mkfifoat, sys_mkfifoat), // 497 + BSDX_(__NR_mknodat, sys_mknodat), // 498 + BSDXY(__NR_openat, sys_openat), // 499 + + BSDX_(__NR_readlinkat, sys_readlinkat), // 500 + BSDX_(__NR_renameat, sys_renameat), // 501 + BSDX_(__NR_symlinkat, sys_symlinkat), // 502 + BSDX_(__NR_unlinkat, sys_unlinkat), // 503 + + // posix_openpt 504 + + BSDXY(__NR___semctl, sys___semctl), // 510 + BSDXY(__NR_shmctl, sys_shmctl), // 512 + + BSDX_(__NR_fake_sigreturn, sys_fake_sigreturn), // 1000, fake sigreturn + +}; + +const UInt ML_(syscall_table_size) = + sizeof(ML_(syscall_table)) / sizeof(ML_(syscall_table)[0]); + +#endif // defined(VGO_freebsd) + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_syswrap/syswrap-generic.c --- a/coregrind/m_syswrap/syswrap-generic.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_syswrap/syswrap-generic.c Thu Mar 31 15:57:55 2016 +0900 @@ -29,7 +29,7 @@ The GNU General Public License is contained in the file COPYING. */ -#if defined(VGO_linux) || defined(VGO_darwin) +#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd) || defined(VGO_openbsd) #include "pub_core_basics.h" #include "pub_core_vki.h" @@ -543,6 +543,7 @@ HChar *pathname; /* NULL if not a regular file or unknown */ ExeContext *where; /* NULL if inherited from parent */ struct OpenFd *next, *prev; + Int internal; } OpenFd; /* List of allocated file descriptors. */ @@ -616,6 +617,23 @@ i->fd = fd; i->pathname = VG_(arena_strdup)(VG_AR_CORE, "syswrap.rfdowgn.2", pathname); i->where = (tid == -1) ? NULL : VG_(record_ExeContext)(tid, 0/*first_ip_delta*/); + i->internal = 0; +} + +void ML_(mark_fd_as_internal)(ThreadId tid, Int fd) +{ + OpenFd *i = allocated_fds; + + if (fd >= VG_(fd_hard_limit)) + return; /* Valgrind internal */ + + while(i) { + if(i->fd == fd) { + i->internal = 1; + break; + } + i = i->next; + } } // Record opening of an fd, and find its name. @@ -805,6 +823,9 @@ VG_(message)(Vg_UserMsg, "FILE DESCRIPTORS: %d open %s.\n", fd_count, when); while (i) { + if (i->internal) { + /* skip */ + } else if (i->pathname) { VG_(message)(Vg_UserMsg, "Open file descriptor %d: %s\n", i->fd, i->pathname); @@ -820,6 +841,9 @@ } } + if (i->internal) { + /* skip */ + } else if(i->where) { VG_(pp_ExeContext)(i->where); VG_(message)(Vg_UserMsg, "\n"); @@ -900,7 +924,7 @@ out: VG_(close)(sr_Res(f)); -#elif defined(VGO_darwin) +#elif defined(VGO_darwin) || defined(VGO_freebsd) || defined(VGO_openbsd) init_preopened_fds_without_proc_self_fd(); #else @@ -1066,6 +1090,10 @@ VG_(sprintf) ( outmsg, description, "sa_family" ); PRE_MEM_READ( outmsg, (Addr) &sa->sa_family, sizeof(vki_sa_family_t)); +#if defined(VGO_freebsd) + VG_(sprintf) ( outmsg, description, ".sa_len" ); + PRE_MEM_READ( outmsg, (Addr) &sa->sa_len, sizeof(char)); +#endif switch (sa->sa_family) { @@ -1728,6 +1756,8 @@ # ifdef __NR_semctl res = VG_(do_syscall4)(__NR_semctl, semid, 0, VKI_IPC_STAT, *(UWord *)&arg); +# elif defined(__NR___semctl) + res = VG_(do_syscall4)(__NR___semctl, semid, 0, VKI_IPC_STAT, *(UWord *)&arg); # else res = VG_(do_syscall5)(__NR_ipc, 3 /* IPCOP_semctl */, semid, 0, VKI_IPC_STAT, (UWord)&arg); @@ -1750,10 +1780,12 @@ #if defined(VKI_IPC_INFO) case VKI_IPC_INFO: case VKI_SEM_INFO: +#if defined(VKI_IPC_64) case VKI_IPC_INFO|VKI_IPC_64: case VKI_SEM_INFO|VKI_IPC_64: +#endif PRE_MEM_WRITE( "semctl(IPC_INFO, arg.buf)", - (Addr)arg.buf, sizeof(struct vki_seminfo) ); + (Addr)arg.buf, sizeof(arg.buf) ); break; #endif @@ -1819,9 +1851,11 @@ #if defined(VKI_IPC_INFO) case VKI_IPC_INFO: case VKI_SEM_INFO: +#if defined(VKI_IPC_64) case VKI_IPC_INFO|VKI_IPC_64: case VKI_SEM_INFO|VKI_IPC_64: - POST_MEM_WRITE( (Addr)arg.buf, sizeof(struct vki_seminfo) ); +#endif + POST_MEM_WRITE( (Addr)arg.buf, sizeof(arg.buf) ); break; #endif @@ -1993,8 +2027,15 @@ switch (arg1 /* cmd */) { #if defined(VKI_IPC_INFO) case VKI_IPC_INFO: +# if defined(VGO_linux) PRE_MEM_WRITE( "shmctl(IPC_INFO, buf)", arg2, sizeof(struct vki_shminfo) ); +# elif defined(VGO_freebsd) || defined(VGO_openbsd) + PRE_MEM_WRITE( "shmctl(IPC_INFO, buf)", + arg2, sizeof(struct vki_shmid_ds) ); +# else +# error "Unknown OS!" +# endif break; #if defined(VKI_IPC_64) case VKI_IPC_INFO|VKI_IPC_64: @@ -2052,12 +2093,20 @@ switch (arg1 /* cmd */) { #if defined(VKI_IPC_INFO) case VKI_IPC_INFO: +# if defined(VGO_linux) POST_MEM_WRITE( arg2, sizeof(struct vki_shminfo) ); +# elif defined(VGO_freebsd) || defined(VGO_openbsd) + POST_MEM_WRITE( arg2, sizeof(struct vki_shmid_ds) ); +# else +# error "Unknown OS!" +# endif break; +#if defined(VKI_IPC_64) case VKI_IPC_INFO|VKI_IPC_64: POST_MEM_WRITE( arg2, sizeof(struct vki_shminfo64) ); break; #endif +#endif #if defined(VKI_SHM_INFO) case VKI_SHM_INFO: @@ -2295,6 +2344,7 @@ #error Unknown endianness #endif +#if !defined(VGO_freebsd) /* On freebsd, exit(2) is all-threads shutdown */ PRE(sys_exit) { ThreadState* tst; @@ -2308,6 +2358,7 @@ tst->os_state.exitcode = ARG1; SET_STATUS_Success(0); } +#endif PRE(sys_ni_syscall) { @@ -2317,11 +2368,13 @@ SET_STATUS_Failure( VKI_ENOSYS ); } +#if defined(VGO_linux) PRE(sys_iopl) { PRINT("sys_iopl ( %ld )", ARG1); PRE_REG_READ1(long, "iopl", unsigned long, level); } +#endif PRE(sys_fsync) { @@ -2346,6 +2399,7 @@ PRE_MEM_READ( "msync(start)", ARG1, ARG2 ); } +#if defined(VGO_linux) // Nb: getpmsg() and putpmsg() are special additional syscalls used in early // versions of LiS (Linux Streams). They are not part of the kernel. // Therefore, we have to provide this type ourself, rather than getting it @@ -2408,6 +2462,7 @@ if (data && data->len > 0) PRE_MEM_READ( "putpmsg(data)", (Addr)data->buf, data->len); } +#endif PRE(sys_getitimer) { @@ -2499,11 +2554,13 @@ } #endif /* HAVE_MREMAP */ +#if defined(VGO_linux) PRE(sys_nice) { PRINT("sys_nice ( %ld )", ARG1); PRE_REG_READ1(long, "nice", int, inc); } +#endif PRE(sys_mlock) { @@ -2538,6 +2595,7 @@ PRE_REG_READ2(long, "getpriority", int, which, int, who); } +#if defined(VGO_linux) PRE(sys_pwrite64) { *flags |= SfMayBlock; @@ -2558,6 +2616,7 @@ #endif PRE_MEM_READ( "pwrite64(buf)", ARG2, ARG3 ); } +#endif PRE(sys_sync) { @@ -2580,6 +2639,7 @@ POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs) ); } +#if defined(VGO_linux) PRE(sys_fstatfs64) { FUSE_COMPATIBLE_MAY_BLOCK(); @@ -2592,6 +2652,7 @@ { POST_MEM_WRITE( ARG3, ARG2 ); } +#endif PRE(sys_getsid) { @@ -2599,6 +2660,7 @@ PRE_REG_READ1(long, "getsid", vki_pid_t, pid); } +#if defined(VGO_linux) PRE(sys_pread64) { *flags |= SfMayBlock; @@ -2626,6 +2688,7 @@ POST_MEM_WRITE( ARG2, RES ); } } +#endif PRE(sys_mknod) { @@ -3114,6 +3177,7 @@ PRE_REG_READ2(long, "fchmod", unsigned int, fildes, vki_mode_t, mode); } +#if defined (VGO_linux) PRE(sys_newfstat) { FUSE_COMPATIBLE_MAY_BLOCK(); @@ -3126,6 +3190,7 @@ { POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) ); } +#endif static vki_sigset_t fork_saved_mask; @@ -3149,7 +3214,7 @@ if (!SUCCESS) return; -#if defined(VGO_linux) +#if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd) // RES is 0 for child, non-0 (the child's PID) for parent. is_child = ( RES == 0 ? True : False ); child_pid = ( is_child ? -1 : RES ); @@ -3190,12 +3255,15 @@ } } +// ftruncate/truncate have padded arguments on FreeBSD. +#if !defined(VGO_freebsd) PRE(sys_ftruncate) { *flags |= SfMayBlock; PRINT("sys_ftruncate ( %ld, %ld )", ARG1,ARG2); PRE_REG_READ2(long, "ftruncate", unsigned int, fd, unsigned long, length); } +#endif PRE(sys_truncate) { @@ -3206,6 +3274,7 @@ PRE_MEM_RASCIIZ( "truncate(path)", ARG1 ); } +#if defined(VGO_linux) PRE(sys_ftruncate64) { *flags |= SfMayBlock; @@ -3236,6 +3305,7 @@ #endif PRE_MEM_RASCIIZ( "truncate64(path)", ARG1 ); } +#endif PRE(sys_getdents) { @@ -3254,6 +3324,7 @@ POST_MEM_WRITE( ARG2, RES ); } +#if defined(VGO_linux) PRE(sys_getdents64) { *flags |= SfMayBlock; @@ -3270,6 +3341,7 @@ if (RES > 0) POST_MEM_WRITE( ARG2, RES ); } +#endif PRE(sys_getgroups) { @@ -3374,6 +3446,7 @@ } } +#if defined(VGO_linux) PRE(sys_old_getrlimit) { PRINT("sys_old_getrlimit ( %ld, %#lx )", ARG1,ARG2); @@ -3386,6 +3459,7 @@ { common_post_getrlimit(tid, ARG1, ARG2); } +#endif PRE(sys_getrlimit) { @@ -3622,6 +3696,7 @@ PRE_MEM_RASCIIZ( "link(newpath)", ARG2); } +#if defined(VGO_linux) PRE(sys_newlstat) { PRINT("sys_newlstat ( %#lx(%s), %#lx )", ARG1,(char*)ARG1,ARG2); @@ -3635,6 +3710,7 @@ vg_assert(SUCCESS); POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) ); } +#endif PRE(sys_mkdir) { @@ -4158,6 +4234,7 @@ PRE_REG_READ1(long, "setuid", vki_uid_t, uid); } +#if defined(VGO_linux) PRE(sys_newstat) { PRINT("sys_newstat ( %#lx(%s), %#lx )", ARG1,(char*)ARG1,ARG2); @@ -4170,6 +4247,7 @@ { POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) ); } +#endif PRE(sys_statfs) { @@ -4183,6 +4261,7 @@ POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs) ); } +#if defined(VGO_linux) PRE(sys_statfs64) { PRINT("sys_statfs64 ( %#lx(%s), %llu, %#lx )",ARG1,(char*)ARG1,(ULong)ARG2,ARG3); @@ -4195,6 +4274,7 @@ { POST_MEM_WRITE( ARG3, ARG2 ); } +#endif PRE(sys_symlink) { @@ -4252,6 +4332,7 @@ PRE_MEM_RASCIIZ( "unlink(pathname)", ARG1 ); } +#if defined(VGO_linux) PRE(sys_newuname) { PRINT("sys_newuname ( %#lx )", ARG1); @@ -4265,6 +4346,7 @@ POST_MEM_WRITE( ARG1, sizeof(struct vki_new_utsname) ); } } +#endif PRE(sys_waitpid) { @@ -4392,7 +4474,22 @@ #undef PRE #undef POST -#endif // defined(VGO_linux) || defined(VGO_darwin) +#if defined(VGO_openbsd) + +char * +VG_(pathname_by_fd)(Int fd) +{ + OpenFd *a; + + for (a = allocated_fds; a; a = a->next) { + if (a->fd == fd && a->pathname) + return a->pathname; + } + return NULL; +} +#endif + +#endif // defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd) || defined(VGO_openbsd) /*--------------------------------------------------------------------*/ /*--- end ---*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_syswrap/syswrap-main.c --- a/coregrind/m_syswrap/syswrap-main.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_syswrap/syswrap-main.c Thu Mar 31 15:57:55 2016 +0900 @@ -51,6 +51,8 @@ #include "pub_core_machine.h" #include "pub_core_syswrap.h" +#include "pub_tool_vkiscnums.h" + #include "priv_types_n_macros.h" #include "priv_syswrap-main.h" @@ -72,6 +74,10 @@ mips64 v0 a0 a1 a2 a3 a4 a5 a6 a7 v0 (== NUM) arm64 x8 x0 x1 x2 x3 x4 x5 n/a n/a x0 ?? (== ARG1??) + FreeBSD: + x86 eax +4 +8 +12 +16 +20 +24 +28 +32 edx:eax, eflags.c + amd64 rax rdi rsi rdx rcx r8 r9 +8 +16 rdx:rax, rflags.c + On s390x the svc instruction is used for system calls. The system call number is encoded in the instruction (8 bit immediate field). Since Linux 2.6 it is also allowed to use svc 0 with the system call number in r1. @@ -85,8 +91,8 @@ x86 eax +4 +8 +12 +16 +20 +24 +28 +32 edx:eax, eflags.c amd64 rax rdi rsi rdx rcx r8 r9 +8 +16 rdx:rax, rflags.c - For x86-darwin, "+N" denotes "in memory at N(%esp)"; ditto - amd64-darwin. Apparently 0(%esp) is some kind of return address + For x86-darwin and x86-freebsd, "+N" denotes "in memory at N(%esp)"; + ditto amd64-darwin/amd64-freebsd. Apparently 0(%esp) is some kind of return address (perhaps for syscalls done with "sysenter"?) I don't think it is relevant for syscalls done with "int $0x80/1/2". */ @@ -165,6 +171,12 @@ ppc32: Success(N) ==> r3 = N, CR0.SO = 0 Fail(N) ==> r3 = N, CR0.SO = 1 + FreeBSD: + x86: Success(N) ==> edx:eax = N, cc = 0 + Fail(N) ==> edx:eax = N, cc = 1 + + ditto amd64 + Darwin: x86: Success(N) ==> edx:eax = N, cc = 0 Fail(N) ==> edx:eax = N, cc = 1 @@ -278,6 +290,13 @@ const vki_sigset_t *syscall_mask, const vki_sigset_t *restore_mask, Word sigsetSzB ); +#elif defined(VGO_freebsd) || defined(VGO_openbsd) +extern +UWord ML_(do_syscall_for_client_WRK)( Word syscallno, + void* guest_state, + const vki_sigset_t *syscall_mask, + const vki_sigset_t *restore_mask, + Word sigsetSzB ); #elif defined(VGO_darwin) extern UWord ML_(do_syscall_for_client_unix_WRK)( Word syscallno, @@ -309,11 +328,36 @@ { vki_sigset_t saved; UWord err; +# if defined(VGO_freebsd) || defined(VGO_openbsd) + Int real_syscallno; +# endif # if defined(VGO_linux) err = ML_(do_syscall_for_client_WRK)( syscallno, &tst->arch.vex, syscall_mask, &saved, sizeof(vki_sigset_t) ); +# elif defined(VGO_freebsd) + if (tst->arch.vex.guest_SC_CLASS == VG_FREEBSD_SYSCALL0) + real_syscallno = __NR_syscall; + else if (tst->arch.vex.guest_SC_CLASS == VG_FREEBSD_SYSCALL198) + real_syscallno = __NR___syscall; + else + real_syscallno = syscallno; + err = ML_(do_syscall_for_client_WRK)( + real_syscallno, &tst->arch.vex, + syscall_mask, &saved, sizeof(vki_sigset_t) + ); +# elif defined(VGO_openbsd) + if (tst->arch.vex.guest_SC_CLASS == VG_OPENBSD_SYSCALL0) + real_syscallno = __NR_syscall; + else if (tst->arch.vex.guest_SC_CLASS == VG_OPENBSD_SYSCALL198) + real_syscallno = __NR___syscall; + else + real_syscallno = syscallno; + err = ML_(do_syscall_for_client_WRK)( + real_syscallno, &tst->arch.vex, + syscall_mask, &saved, sizeof(vki_sigset_t) + ); # elif defined(VGO_darwin) switch (VG_DARWIN_SYSNO_CLASS(syscallno)) { case VG_DARWIN_SYSCALL_CLASS_UNIX: @@ -454,6 +498,152 @@ canonical->arg7 = 0; canonical->arg8 = 0; +#elif defined(VGP_x86_freebsd) + VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla; + UWord *stack = (UWord *)gst->guest_ESP; + + // FreeBSD supports different calling conventions + switch (gst->guest_EAX) { + case __NR_syscall: + canonical->class = VG_FREEBSD_SYSCALL0; + canonical->sysno = stack[1]; + stack += 1; + break; + case __NR___syscall: + canonical->class = VG_FREEBSD_SYSCALL198; + canonical->sysno = stack[1]; + stack += 2; + break; + default: + canonical->class = 0; + canonical->sysno = gst->guest_EAX; + break; + } + // stack[0] is a (fake) return address + canonical->arg1 = stack[1]; + canonical->arg2 = stack[2]; + canonical->arg3 = stack[3]; + canonical->arg4 = stack[4]; + canonical->arg5 = stack[5]; + canonical->arg6 = stack[6]; + canonical->arg7 = stack[7]; + canonical->arg8 = stack[8]; + +#elif defined(VGP_amd64_freebsd) + VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla; + UWord *stack = (UWord *)gst->guest_RSP; + + // FreeBSD supports different calling conventions + switch (gst->guest_RAX) { + case __NR_syscall: + canonical->class = VG_FREEBSD_SYSCALL0; + canonical->sysno = gst->guest_RDI; + break; + case __NR___syscall: + canonical->class = VG_FREEBSD_SYSCALL198; + canonical->sysno = gst->guest_RDI; + break; + default: + canonical->class = 0; + canonical->sysno = gst->guest_RAX; + break; + } + // stack[0] is a (fake) return address + if (canonical->class != VG_FREEBSD_SYSCALL0 && canonical->class != VG_FREEBSD_SYSCALL198) { + // stack[0] is return address + canonical->arg1 = gst->guest_RDI; + canonical->arg2 = gst->guest_RSI; + canonical->arg3 = gst->guest_RDX; + canonical->arg4 = gst->guest_R10; + canonical->arg5 = gst->guest_R8; + canonical->arg6 = gst->guest_R9; + canonical->arg7 = stack[1]; + canonical->arg8 = stack[2]; + } else { + // stack[0] is return address + canonical->arg1 = gst->guest_RSI; + canonical->arg2 = gst->guest_RDX; + canonical->arg3 = gst->guest_R10; + canonical->arg4 = gst->guest_R8; + canonical->arg5 = gst->guest_R9; + canonical->arg6 = stack[1]; + canonical->arg7 = stack[2]; + canonical->arg8 = stack[3]; + } + +#elif defined(VGP_x86_openbsd) + VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla; + UWord *stack = (UWord *)gst->guest_ESP; + + // OpenBSD supports different calling conventions + switch (gst->guest_EAX) { + case __NR_syscall: + canonical->class = VG_OPENBSD_SYSCALL0; + canonical->sysno = stack[1]; + stack += 1; + break; + case __NR___syscall: + canonical->class = VG_OPENBSD_SYSCALL198; + canonical->sysno = stack[1]; + stack += 2; + break; + default: + canonical->class = 0; + canonical->sysno = gst->guest_EAX; + break; + } + // stack[0] is a (fake) return address + canonical->arg1 = stack[1]; + canonical->arg2 = stack[2]; + canonical->arg3 = stack[3]; + canonical->arg4 = stack[4]; + canonical->arg5 = stack[5]; + canonical->arg6 = stack[6]; + canonical->arg7 = stack[7]; + canonical->arg8 = stack[8]; + +#elif defined(VGP_amd64_openbsd) + VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla; + UWord *stack = (UWord *)gst->guest_RSP; + + // OpenBSD supports different calling conventions + switch (gst->guest_RAX) { + case __NR_syscall: + canonical->class = VG_OPENBSD_SYSCALL0; + canonical->sysno = gst->guest_RDI; + break; + case __NR___syscall: + canonical->class = VG_OPENBSD_SYSCALL198; + canonical->sysno = gst->guest_RDI; + break; + default: + canonical->class = 0; + canonical->sysno = gst->guest_RAX; + break; + } + // stack[0] is a (fake) return address + if (canonical->class != VG_OPENBSD_SYSCALL0 && canonical->class != VG_OPENBSD_SYSCALL198) { + // stack[0] is return address + canonical->arg1 = gst->guest_RDI; + canonical->arg2 = gst->guest_RSI; + canonical->arg3 = gst->guest_RDX; + canonical->arg4 = gst->guest_R10; + canonical->arg5 = gst->guest_R8; + canonical->arg6 = gst->guest_R9; + canonical->arg7 = stack[1]; + canonical->arg8 = stack[2]; + } else { + // stack[0] is return address + canonical->arg1 = gst->guest_RSI; + canonical->arg2 = gst->guest_RDX; + canonical->arg3 = gst->guest_R10; + canonical->arg4 = gst->guest_R8; + canonical->arg5 = gst->guest_R9; + canonical->arg6 = stack[1]; + canonical->arg7 = stack[2]; + canonical->arg8 = stack[3]; + } + #elif defined(VGP_arm_linux) VexGuestARMState* gst = (VexGuestARMState*)gst_vanilla; canonical->sysno = gst->guest_R7; @@ -698,6 +888,150 @@ gst->guest_GPR7 = canonical->arg5; gst->guest_GPR8 = canonical->arg6; +#elif defined(VGP_x86_freebsd) + VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla; + UWord *stack = (UWord *)gst->guest_ESP; + + // stack[0] is a (fake) return address + switch (canonical->class) { + case VG_FREEBSD_SYSCALL0: + gst->guest_EAX = __NR_syscall; + stack[1] = canonical->sysno; + stack++; + break; + case VG_FREEBSD_SYSCALL198: + gst->guest_EAX = __NR___syscall; + stack[1] = canonical->sysno; + stack += 2; + break; + default: + gst->guest_EAX = canonical->sysno; + break; + } + stack[1] = canonical->arg1; + stack[2] = canonical->arg2; + stack[3] = canonical->arg3; + stack[4] = canonical->arg4; + stack[5] = canonical->arg5; + stack[6] = canonical->arg6; + stack[7] = canonical->arg7; + stack[8] = canonical->arg8; + +#elif defined(VGP_amd64_freebsd) + VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla; + UWord *stack = (UWord *)gst->guest_RSP; + + // stack[0] is a (fake) return address + switch (canonical->class) { + case VG_FREEBSD_SYSCALL0: + gst->guest_RAX = __NR_syscall; + gst->guest_RDI = canonical->sysno; + gst->guest_RSI = canonical->arg1; + gst->guest_RDX = canonical->arg2; + gst->guest_R10 = canonical->arg3; + gst->guest_R8 = canonical->arg4; + gst->guest_R9 = canonical->arg5; + stack[1] = canonical->arg6; + stack[2] = canonical->arg7; + stack[3] = canonical->arg8; + break; + case VG_FREEBSD_SYSCALL198: + gst->guest_RAX = __NR___syscall; + gst->guest_RDI = canonical->sysno; + gst->guest_RSI = canonical->arg1; + gst->guest_RDX = canonical->arg2; + gst->guest_R10 = canonical->arg3; + gst->guest_R8 = canonical->arg4; + gst->guest_R9 = canonical->arg5; + stack[1] = canonical->arg6; + stack[2] = canonical->arg7; + stack[3] = canonical->arg8; + break; + default: + gst->guest_RAX = canonical->sysno; + gst->guest_RDI = canonical->arg1; + gst->guest_RSI = canonical->arg2; + gst->guest_RDX = canonical->arg3; + gst->guest_R10 = canonical->arg4; + gst->guest_R8 = canonical->arg5; + gst->guest_R9 = canonical->arg6; + stack[1] = canonical->arg7; + stack[2] = canonical->arg8; + break; + } + +#elif defined(VGP_x86_openbsd) + VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla; + UWord *stack = (UWord *)gst->guest_ESP; + + // stack[0] is a (fake) return address + switch (canonical->class) { + case VG_OPENBSD_SYSCALL0: + gst->guest_EAX = __NR_syscall; + stack[1] = canonical->sysno; + stack++; + break; + case VG_OPENBSD_SYSCALL198: + gst->guest_EAX = __NR___syscall; + stack[1] = canonical->sysno; + stack += 2; + break; + default: + gst->guest_EAX = canonical->sysno; + break; + } + stack[1] = canonical->arg1; + stack[2] = canonical->arg2; + stack[3] = canonical->arg3; + stack[4] = canonical->arg4; + stack[5] = canonical->arg5; + stack[6] = canonical->arg6; + stack[7] = canonical->arg7; + stack[8] = canonical->arg8; + +#elif defined(VGP_amd64_openbsd) + VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla; + UWord *stack = (UWord *)gst->guest_RSP; + + // stack[0] is a (fake) return address + switch (canonical->class) { + case VG_OPENBSD_SYSCALL0: + gst->guest_RAX = __NR_syscall; + gst->guest_RDI = canonical->sysno; + gst->guest_RSI = canonical->arg1; + gst->guest_RDX = canonical->arg2; + gst->guest_R10 = canonical->arg3; + gst->guest_R8 = canonical->arg4; + gst->guest_R9 = canonical->arg5; + stack[1] = canonical->arg6; + stack[2] = canonical->arg7; + stack[3] = canonical->arg8; + break; + case VG_OPENBSD_SYSCALL198: + gst->guest_RAX = __NR___syscall; + gst->guest_RDI = canonical->sysno; + gst->guest_RSI = canonical->arg1; + gst->guest_RDX = canonical->arg2; + gst->guest_R10 = canonical->arg3; + gst->guest_R8 = canonical->arg4; + gst->guest_R9 = canonical->arg5; + stack[1] = canonical->arg6; + stack[2] = canonical->arg7; + stack[3] = canonical->arg8; + break; + default: + gst->guest_RAX = canonical->sysno; + gst->guest_RDI = canonical->arg1; + gst->guest_RSI = canonical->arg2; + gst->guest_RDX = canonical->arg3; + gst->guest_R10 = canonical->arg4; + gst->guest_R8 = canonical->arg5; + gst->guest_R9 = canonical->arg6; + stack[1] = canonical->arg7; + stack[2] = canonical->arg8; + break; + } + #elif defined(VGP_arm_linux) VexGuestARMState* gst = (VexGuestARMState*)gst_vanilla; gst->guest_R7 = canonical->sysno; @@ -826,6 +1160,24 @@ canonical->sres = VG_(mk_SysRes_ppc64_linux)( gst->guest_GPR3, cr0so ); canonical->what = SsComplete; +# elif defined(VGP_x86_freebsd) + /* duplicates logic in m_signals.VG_UCONTEXT_SYSCALL_SYSRES */ + VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla; + UInt flags = LibVEX_GuestX86_get_eflags(gst); + + canonical->sres = VG_(mk_SysRes_x86_freebsd)(gst->guest_EAX, gst->guest_EDX, + (flags & 1) != 0 ? True : False); + canonical->what = SsComplete; + +# elif defined(VGP_x86_openbsd) + /* duplicates logic in m_signals.VG_UCONTEXT_SYSCALL_SYSRES */ + VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla; + UInt flags = LibVEX_GuestX86_get_eflags(gst); + + canonical->sres = VG_(mk_SysRes_x86_openbsd)(gst->guest_EAX, gst->guest_EDX, + (flags & 1) != 0 ? True : False); + canonical->what = SsComplete; + # elif defined(VGP_arm_linux) VexGuestARMState* gst = (VexGuestARMState*)gst_vanilla; canonical->sres = VG_(mk_SysRes_arm_linux)( gst->guest_R0 ); @@ -836,6 +1188,22 @@ canonical->sres = VG_(mk_SysRes_arm64_linux)( gst->guest_X0 ); canonical->what = SsComplete; +# elif defined(VGP_amd64_freebsd) + /* duplicates logic in m_signals.VG_UCONTEXT_SYSCALL_SYSRES */ + VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla; + ULong flags = LibVEX_GuestAMD64_get_rflags(gst); + canonical->sres = VG_(mk_SysRes_amd64_freebsd)(gst->guest_RAX, gst->guest_RDX, + (flags & 1) != 0 ? True : False); + canonical->what = SsComplete; + +# elif defined(VGP_amd64_openbsd) + /* duplicates logic in m_signals.VG_UCONTEXT_SYSCALL_SYSRES */ + VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla; + ULong flags = LibVEX_GuestAMD64_get_rflags(gst); + canonical->sres = VG_(mk_SysRes_amd64_openbsd)(gst->guest_RAX, gst->guest_RDX, + (flags & 1) != 0 ? True : False); + canonical->what = SsComplete; + # elif defined(VGP_mips32_linux) VexGuestMIPS32State* gst = (VexGuestMIPS32State*)gst_vanilla; UInt v0 = gst->guest_r2; // v0 @@ -1023,6 +1391,51 @@ VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, OFFSET_arm64_X0, sizeof(UWord) ); +# elif defined(VGP_x86_freebsd) || defined(VGP_x86_openbsd) + VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla; + vg_assert(canonical->what == SsComplete); + if (sr_isError(canonical->sres)) { + gst->guest_EAX = sr_Err(canonical->sres); + LibVEX_GuestX86_put_eflag_c(1, gst); + } else { + gst->guest_EAX = sr_Res(canonical->sres); + gst->guest_EDX = sr_ResHI(canonical->sres); + LibVEX_GuestX86_put_eflag_c(0, gst); + } + VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, + OFFSET_x86_EAX, sizeof(UInt) ); + VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, + OFFSET_x86_EDX, sizeof(UInt) ); + // GrP fixme sets defined for entire eflags, not just bit c + // DDD: this breaks exp-ptrcheck. + VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, + offsetof(VexGuestX86State, guest_CC_DEP1), sizeof(UInt) ); + +#elif defined(VGP_amd64_freebsd) || defined(VGP_amd64_openbsd) + VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla; + vg_assert(canonical->what == SsComplete); + if (sr_isError(canonical->sres)) { + gst->guest_RAX = sr_Err(canonical->sres); + LibVEX_GuestAMD64_put_rflag_c(1, gst); + } else { +#if defined(VGP_amd64_openbsd) + if (!canonical->sres._hasVal2) { + canonical->sres._val2 = gst->guest_RDX; + } +#endif + gst->guest_RAX = sr_Res(canonical->sres); + gst->guest_RDX = sr_ResHI(canonical->sres); + LibVEX_GuestAMD64_put_rflag_c(0, gst); + } + VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, + OFFSET_amd64_RAX, sizeof(ULong) ); + VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, + OFFSET_amd64_RDX, sizeof(ULong) ); + // GrP fixme sets defined for entire eflags, not just bit c + // DDD: this breaks exp-ptrcheck. + VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, + offsetof(VexGuestAMD64State, guest_CC_DEP1), sizeof(ULong) ); + #elif defined(VGP_x86_darwin) VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla; SysRes sres = canonical->sres; @@ -1193,6 +1606,29 @@ layout->uu_arg7 = -1; /* impossible value */ layout->uu_arg8 = -1; /* impossible value */ +#elif defined(VGP_x86_freebsd) || defined(VGP_x86_openbsd) + layout->o_sysno = OFFSET_x86_EAX; + // syscall parameters are on stack in C convention + layout->s_arg1 = sizeof(UWord) * 1; + layout->s_arg2 = sizeof(UWord) * 2; + layout->s_arg3 = sizeof(UWord) * 3; + layout->s_arg4 = sizeof(UWord) * 4; + layout->s_arg5 = sizeof(UWord) * 5; + layout->s_arg6 = sizeof(UWord) * 6; + layout->s_arg7 = sizeof(UWord) * 7; + layout->s_arg8 = sizeof(UWord) * 8; + +#elif defined(VGP_amd64_freebsd) || defined(VGP_amd64_openbsd) + layout->o_sysno = OFFSET_amd64_RAX; + layout->o_arg1 = OFFSET_amd64_RDI; + layout->o_arg2 = OFFSET_amd64_RSI; + layout->o_arg3 = OFFSET_amd64_RDX; + layout->o_arg4 = OFFSET_amd64_R10; + layout->o_arg5 = OFFSET_amd64_R8; + layout->o_arg6 = OFFSET_amd64_R9; + layout->s_arg7 = sizeof(UWord) * 1; + layout->s_arg8 = sizeof(UWord) * 2; + #elif defined(VGP_arm_linux) layout->o_sysno = OFFSET_arm_R7; layout->o_arg1 = OFFSET_arm_R0; @@ -1313,6 +1749,11 @@ # if defined(VGO_linux) sys = ML_(get_linux_syscall_entry)( syscallno ); +# elif defined(VGO_freebsd) || defined(VGO_openbsd) + if (syscallno >= 0 && syscallno < ML_(syscall_table_size) && + ML_(syscall_table)[syscallno].before != NULL) + sys = &ML_(syscall_table)[syscallno]; + # elif defined(VGO_darwin) Int idx = VG_DARWIN_SYSNO_INDEX(syscallno); @@ -1509,6 +1950,9 @@ is interrupted by a signal. */ sysno = sci->orig_args.sysno; +# if defined(VGO_freebsd) || defined(VGO_openbsd) + tst->arch.vex.guest_SC_CLASS = sci->orig_args.class; +# endif /* It's sometimes useful, as a crude debugging hack, to get a stack trace at each (or selected) syscalls. */ if (0 && sysno == __NR_ioctl) { @@ -1918,7 +2362,7 @@ /* These are addresses within ML_(do_syscall_for_client_WRK). See syscall-$PLAT.S for details. */ -#if defined(VGO_linux) +#if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd) extern const Addr ML_(blksys_setup); extern const Addr ML_(blksys_restart); extern const Addr ML_(blksys_complete); @@ -2086,6 +2530,46 @@ vg_assert(p[0] == 0x01 && p[1] == 0x00 && p[2] == 0x00 && p[3] == 0xD4); } +#elif defined(VGP_x86_freebsd) || defined(VGP_x86_openbsd) + /* XXX: we support different syscall methods. */ + arch->vex.guest_EIP -= 2; // sizeof(int $0x80) + + /* Make sure our caller is actually sane, and we're really backing + back over a syscall. + + int $0x80 == CD 80 + */ + { + UChar *p = (UChar *)arch->vex.guest_EIP; + + if (p[0] != 0xcd || p[1] != 0x80) + VG_(message)(Vg_DebugMsg, + "?! restarting over syscall at %#x %02x %02x\n", + arch->vex.guest_EIP, p[0], p[1]); + + vg_assert(p[0] == 0xcd && p[1] == 0x80); + } + +#elif defined(VGP_amd64_freebsd) || defined(VGP_amd64_openbsd) + /* XXX: we support different syscall methods. */ + arch->vex.guest_RIP -= 2; // sizeof(syscall) + + /* Make sure our caller is actually sane, and we're really backing + back over a syscall. + + syscall == 0F 05 + */ + { + UChar *p = (UChar *)arch->vex.guest_RIP; + + if (p[0] != 0x0F || p[1] != 0x05) + VG_(message)(Vg_DebugMsg, + "?! restarting over syscall at %#llx %02x %02x\n", + arch->vex.guest_RIP, p[0], p[1]); + + vg_assert(p[0] == 0x0F && p[1] == 0x05); + } + #elif defined(VGP_x86_darwin) arch->vex.guest_EIP = arch->vex.guest_IP_AT_SYSCALL; @@ -2229,15 +2713,25 @@ in_complete_to_committed, // [3,4) in the .S files in_committed_to_finished; // [4,5) in the .S files -# if defined(VGO_linux) +# if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd) outside_range = ip < ML_(blksys_setup) || ip >= ML_(blksys_finished); in_setup_to_restart = ip >= ML_(blksys_setup) && ip < ML_(blksys_restart); +# if !defined(VGO_openbsd) at_restart = ip == ML_(blksys_restart); in_complete_to_committed = ip >= ML_(blksys_complete) && ip < ML_(blksys_committed); +# else +// XXX At least on OpenBSD/amd64, if a blocking syscall is interrupted +// XXX by SIGINT, IP points to right after the `syscall' instruction in +// XXX `ML_(do_syscall_for_client_WRK)()'. + at_restart + = ip == ML_(blksys_restart) || ip == ML_(blksys_complete); + in_complete_to_committed + = ip > ML_(blksys_complete) && ip < ML_(blksys_committed); +# endif in_committed_to_finished = ip >= ML_(blksys_committed) && ip < ML_(blksys_finished); # elif defined(VGO_darwin) @@ -2353,6 +2847,24 @@ /* Result committed, but the signal mask has not been restored; we expect our caller (the signal handler) will have fixed this up. */ +/* XXX: needed? */ +#if defined(VGP_x86_freebsd) || defined(VGP_x86_openbsd) + /* On FreeBSD, the success/fail status is returned to the caller + and still has to be fixed up here. */ + if (!(sci->flags & SfNoWriteResult)) { + if (sr_isError(sres)) + LibVEX_GuestX86_put_eflag_c(1, &th_regs->vex); + else + LibVEX_GuestX86_put_eflag_c(0, &th_regs->vex); + } +#elif defined(VGP_amd64_freebsd) || defined(VGP_amd64_openbsd) + if (!(sci->flags & SfNoWriteResult)) { + if (sr_isError(sres)) + LibVEX_GuestAMD64_put_rflag_c(1, &th_regs->vex); + else + LibVEX_GuestAMD64_put_rflag_c(0, &th_regs->vex); + } +#endif if (VG_(clo_trace_signals)) VG_(message)( Vg_DebugMsg, " completed and committed: nothing to do\n"); diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_syswrap/syswrap-openbsd-variants.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coregrind/m_syswrap/syswrap-openbsd-variants.c Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,95 @@ + +/*--------------------------------------------------------------------*/ +/*--- Handlers for syscalls on minor variants of Linux kernels. ---*/ +/*--- syswrap-linux-variants.c ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2008 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +/* The files syswrap-generic.c, syswrap-linux.c, syswrap-x86-linux.c, + syswrap-amd64-linux.c and syswrap-ppc32-linux.c, and associated + vki*.h header files, constitute Valgrind's model of how a vanilla + Linux kernel behaves with respect to syscalls. + + On a few occasions, it is useful to run with a kernel that has some + (minor) extensions to the vanilla model, either due to running on a + hacked kernel, or using a vanilla kernel which has incorporated a + custom kernel module. Rather than clutter the standard model, all + such variant handlers are placed in here. + + Unlike the C files for the standard model, this file should also + contain all constants/types needed for said wrappers. The vki*.h + headers should not be polluted with non-vanilla info. */ + + +#include "pub_core_basics.h" +#include "pub_core_vki.h" +#include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy +#include "pub_core_threadstate.h" +#include "pub_core_aspacemgr.h" +#include "pub_core_debuginfo.h" // VG_(di_notify_*) +#include "pub_core_transtab.h" // VG_(discard_translations) +#include "pub_core_debuglog.h" +#include "pub_core_libcbase.h" +#include "pub_core_libcassert.h" +#include "pub_core_libcfile.h" +#include "pub_core_libcprint.h" +#include "pub_core_libcproc.h" +#include "pub_core_mallocfree.h" +#include "pub_core_tooliface.h" +#include "pub_core_options.h" +#include "pub_core_scheduler.h" +#include "pub_core_signals.h" +#include "pub_core_syscall.h" + +#include "priv_types_n_macros.h" +#include "priv_syswrap-openbsd.h" + + +#if 0 /* think about ylock syscall etc */ +/* --------------------------------------------------------------- + BProc wrappers + ------------------------------------------------------------ */ + +/* Return 0 means hand to kernel, non-0 means fail w/ that value. */ +Int ML_(linux_variant_PRE_sys_bproc)( UWord arg1, UWord arg2, + UWord arg3, UWord arg4, + UWord arg5, UWord arg6 ) +{ + return 0; +} + +void ML_(linux_variant_POST_sys_bproc)( UWord arg1, UWord arg2, + UWord arg3, UWord arg4, + UWord arg5, UWord arg6 ) +{ +} +#endif + + +/*--------------------------------------------------------------------*/ +/*--- end syswrap-linux-variants.c ---*/ +/*--------------------------------------------------------------------*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_syswrap/syswrap-openbsd.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coregrind/m_syswrap/syswrap-openbsd.c Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,4325 @@ + +/*--------------------------------------------------------------------*/ +/*--- FreeBSD-specific syscalls, etc. syswrap-freebsd.c ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2008 Nicholas Nethercote + njn@valgrind.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#if defined(VGO_openbsd) + +#include "pub_core_basics.h" +#include "pub_core_vki.h" +#include "pub_core_vkiscnums.h" +#include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy +#include "pub_core_threadstate.h" +#include "pub_core_aspacemgr.h" +#include "pub_core_debuginfo.h" // VG_(di_notify_*) +#include "pub_core_transtab.h" // VG_(discard_translations) +#include "pub_core_xarray.h" +#include "pub_core_clientstate.h" +#include "pub_core_debuglog.h" +#include "pub_core_libcbase.h" +#include "pub_core_libcassert.h" +#include "pub_core_libcfile.h" +#include "pub_core_libcprint.h" +#include "pub_core_libcproc.h" +#include "pub_core_libcsignal.h" +#include "pub_core_machine.h" +#include "pub_core_mallocfree.h" +#include "pub_core_tooliface.h" +#include "pub_core_options.h" +#include "pub_core_scheduler.h" +#include "pub_core_signals.h" +#include "pub_core_syscall.h" +#include "pub_core_syswrap.h" + +#include "priv_types_n_macros.h" +#include "priv_syswrap-generic.h" +#include "priv_syswrap-openbsd.h" + + +// Run a thread from beginning to end and return the thread's +// scheduler-return-code. +static VgSchedReturnCode thread_wrapper(Word /*ThreadId*/ tidW) +{ + VgSchedReturnCode ret; + ThreadId tid = (ThreadId)tidW; + ThreadState* tst = VG_(get_ThreadState)(tid); + + VG_(debugLog)(1, "syswrap-openbsd", + "thread_wrapper(tid=%lld): entry\n", + (ULong)tidW); + + vg_assert(tst->status == VgTs_Init); + + /* make sure we get the CPU lock before doing anything significant */ + VG_(acquire_BigLock)(tid, "thread_wrapper(starting new thread)"); + + if (0) + VG_(printf)("thread tid %d started: stack = %p\n", + tid, &tid); + + /* Make sure error reporting is enabled in the new thread. */ + tst->err_disablement_level = 0; + + VG_TRACK(pre_thread_first_insn, tid); + + tst->os_state.lwpid = VG_(gettid)(); + tst->os_state.threadgroup = VG_(getpid)(); + + /* Thread created with all signals blocked; scheduler will set the + appropriate mask */ + + ret = VG_(scheduler)(tid); + + vg_assert(VG_(is_exiting)(tid)); + + vg_assert(tst->status == VgTs_Runnable); + vg_assert(VG_(is_running_thread)(tid)); + + VG_(debugLog)(1, "syswrap-openbsd", + "thread_wrapper(tid=%lld): exit\n", + (ULong)tidW); + + /* Return to caller, still holding the lock. */ + return ret; +} + + +/* --------------------------------------------------------------------- + clone-related stuff + ------------------------------------------------------------------ */ + +/* Run a thread all the way to the end, then do appropriate exit actions + (this is the last-one-out-turn-off-the-lights bit). */ +static void run_a_thread_NORETURN ( Word tidW ) +{ + ThreadId tid = (ThreadId)tidW; + VgSchedReturnCode src; + Int c; + ThreadState* tst; + + VG_(debugLog)(1, "syswrap-openbsd", + "run_a_thread_NORETURN(tid=%lld): pre-thread_wrapper\n", + (ULong)tidW); + + tst = VG_(get_ThreadState)(tid); + vg_assert(tst); + + /* Run the thread all the way through. */ + src = thread_wrapper(tid); + + VG_(debugLog)(1, "syswrap-openbsd", + "run_a_thread_NORETURN(tid=%lld): post-thread_wrapper\n", + (ULong)tidW); + + c = VG_(count_living_threads)(); + vg_assert(c >= 1); /* stay sane */ + + // Tell the tool this thread is exiting + VG_TRACK( pre_thread_ll_exit, tid ); + + /* If the thread is exiting with errors disabled, complain loudly; + doing so is bad (does the user know this has happened?) Also, + in all cases, be paranoid and clear the flag anyway so that the + thread slot is safe in this respect if later reallocated. This + should be unnecessary since the flag should be cleared when the + slot is reallocated, in thread_wrapper(). */ + if (tst->err_disablement_level > 0) { + VG_(umsg)( + "WARNING: exiting thread has error reporting disabled.\n" + "WARNING: possibly as a result of some mistake in the use\n" + "WARNING: of the VALGRIND_DISABLE_ERROR_REPORTING macros.\n" + ); + VG_(debugLog)( + 1, "syswrap-openbsd", + "run_a_thread_NORETURN(tid=%lld): " + "WARNING: exiting thread has err_disablement_level = %u\n", + (ULong)tidW, tst->err_disablement_level + ); + } + tst->err_disablement_level = 0; + + if (c == 1) { + + VG_(debugLog)(1, "syswrap-openbsd", + "run_a_thread_NORETURN(tid=%lld): " + "last one standing\n", + (ULong)tidW); + + /* We are the last one standing. Keep hold of the lock and + carry on to show final tool results, then exit the entire system. + Use the continuation pointer set at startup in m_main. */ + ( * VG_(address_of_m_main_shutdown_actions_NORETURN) ) (tid, src); + + } else { + + VG_(debugLog)(1, "syswrap-openbsd", + "run_a_thread_NORETURN(tid=%lld): " + "not last one standing\n", + (ULong)tidW); + + /* OK, thread is dead, but others still exist. Just exit. */ + + /* This releases the run lock */ + VG_(exit_thread)(tid); + vg_assert(tst->status == VgTs_Zombie); + + /* We have to use this sequence to terminate the thread to + prevent a subtle race. If VG_(exit_thread)() had left the + ThreadState as Empty, then it could have been reallocated, + reusing the stack while we're doing these last cleanups. + Instead, VG_(exit_thread) leaves it as Zombie to prevent + reallocation. We need to make sure we don't touch the stack + between marking it Empty and exiting. Hence the + assembler. */ +/* #if defined(VGP_x86_openbsd) /\* FreeBSD has args on the stack *\/ */ + /* asm volatile ( */ + /* "movl %1, %0\n" /\* set tst->status = VgTs_Empty *\/ */ + /* "movl %2, %%eax\n" /\* set %eax = __NR_thr_exit *\/ */ + /* "movl %3, %%ebx\n" /\* set %ebx = tst->os_state.exitcode *\/ */ + /* "pushl %%ebx\n" /\* arg on stack *\/ */ + /* "pushl %%ebx\n" /\* fake return address *\/ */ + /* "int $0x80\n" /\* thr_exit(tst->os_state.exitcode) *\/ */ + /* "popl %%ebx\n" /\* fake return address *\/ */ + /* "popl %%ebx\n" /\* arg off stack *\/ */ + /* : "=m" (tst->status) */ + /* : "n" (VgTs_Empty), "n" (__NR_thr_exit), "m" (tst->os_state.exitcode) */ + /* : "eax", "ebx" */ + /* ); */ +/* #elif defined(VGP_amd64_openbsd) */ + /* asm volatile ( */ + /* "movl %1, %0\n" /\* set tst->status = VgTs_Empty *\/ */ + /* "movq %2, %%rax\n" /\* set %rax = __NR_thr_exit *\/ */ + /* "movq %3, %%rdi\n" /\* set %rdi = tst->os_state.exitcode *\/ */ + /* "pushq %%rdi\n" /\* fake return address *\/ */ + /* "syscall\n" /\* thr_exit(tst->os_state.exitcode) *\/ */ + /* "popq %%rdi\n" /\* fake return address *\/ */ + /* : "=m" (tst->status) */ + /* : "n" (VgTs_Empty), "n" (__NR_thr_exit), "m" (tst->os_state.exitcode) */ + /* : "rax", "rdi" */ + /* ); */ +/* #else */ +/* # error Unknown platform */ +/* #endif */ + + VG_(core_panic)("Thread exit failed?\n"); + } + + /*NOTREACHED*/ + vg_assert(0); +} + +Word ML_(start_thread_NORETURN) ( void* arg ) +{ + ThreadState* tst = (ThreadState*)arg; + ThreadId tid = tst->tid; + + run_a_thread_NORETURN ( (Word)tid ); + /*NOTREACHED*/ + vg_assert(0); +} + +/* Allocate a stack for this thread, if it doesn't already have one. + They're allocated lazily, and never freed. Returns the initial stack + pointer value to use, or 0 if allocation failed. */ +Addr ML_(allocstack)(ThreadId tid) +{ + ThreadState* tst = VG_(get_ThreadState)(tid); + VgStack* stack; + Addr initial_SP; + + /* Either the stack_base and stack_init_SP are both zero (in which + case a stack hasn't been allocated) or they are both non-zero, + in which case it has. */ + + if (tst->os_state.valgrind_stack_base == 0) + vg_assert(tst->os_state.valgrind_stack_init_SP == 0); + + if (tst->os_state.valgrind_stack_base != 0) + vg_assert(tst->os_state.valgrind_stack_init_SP != 0); + + /* If no stack is present, allocate one. */ + + if (tst->os_state.valgrind_stack_base == 0) { + stack = VG_(am_alloc_VgStack)( &initial_SP ); + if (stack) { + tst->os_state.valgrind_stack_base = (Addr)stack; + tst->os_state.valgrind_stack_init_SP = initial_SP; + } + } + + if (0) + VG_(printf)( "stack for tid %d at %p; init_SP=%p\n", + tid, + (void*)tst->os_state.valgrind_stack_base, + (void*)tst->os_state.valgrind_stack_init_SP ); + + return tst->os_state.valgrind_stack_init_SP; +} + +/* Allocate a stack for the main thread, and run it all the way to the + end. Although we already have a working VgStack + (VG_(interim_stack)) it's better to allocate a new one, so that + overflow detection works uniformly for all threads. +*/ +void VG_(main_thread_wrapper_NORETURN)(ThreadId tid) +{ + Addr sp; + VG_(debugLog)(1, "syswrap-openbsd", + "entering VG_(main_thread_wrapper_NORETURN)\n"); + + sp = ML_(allocstack)(tid); + +/* QQQ keep for amd64 redzone stuff */ +#if defined(VGP_ppc32_linux) + /* make a stack frame */ + sp -= 16; + sp &= ~0xF; + *(UWord *)sp = 0; +#elif defined(VGP_ppc64_linux) + /* make a stack frame */ + sp -= 112; + sp &= ~((Addr)0xF); + *(UWord *)sp = 0; +#endif + + /* If we can't even allocate the first thread's stack, we're hosed. + Give up. */ + vg_assert2(sp != 0, "Cannot allocate main thread's stack."); + + /* shouldn't be any other threads around yet */ + vg_assert( VG_(count_living_threads)() == 1 ); + + ML_(call_on_new_stack_0_1)( + (Addr)sp, /* stack */ + 0, /* bogus return address */ + run_a_thread_NORETURN, /* fn to call */ + (Word)tid /* arg to give it */ + ); + + /*NOTREACHED*/ + vg_assert(0); +} + + +/* Do a fork() */ +SysRes ML_(do_fork) ( ThreadId tid ) +{ + vki_sigset_t fork_saved_mask; + vki_sigset_t mask; + SysRes res; + + /* Block all signals during fork, so that we can fix things up in + the child without being interrupted. */ + VG_(sigfillset)(&mask); + VG_(sigprocmask)(VKI_SIG_SETMASK, &mask, &fork_saved_mask); + + VG_(do_atfork_pre)(tid); + + res = VG_(do_syscall0)( __NR_fork ); + + if (!sr_isError(res)) { + if (sr_Res(res) == 0) { + /* child */ + VG_(do_atfork_child)(tid); + + /* restore signal mask */ + VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL); + + } + else { + /* parent */ + VG_(do_atfork_parent)(tid); + + if (VG_(clo_trace_syscalls)) + VG_(printf)(" clone(fork): process %d created child %ld\n", + VG_(getpid)(), sr_Res(res)); + + /* restore signal mask */ + VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL); + } + } + + return res; +} + + +/* --------------------------------------------------------------------- + PRE/POST wrappers for arch-generic, Linux-specific syscalls + ------------------------------------------------------------------ */ + +// Nb: See the comment above the generic PRE/POST wrappers in +// m_syswrap/syswrap-generic.c for notes about how they work. + +#define PRE(name) DEFN_PRE_TEMPLATE(openbsd, name) +#define POST(name) DEFN_POST_TEMPLATE(openbsd, name) + +// Combine two 32-bit values into a 64-bit value +#define LOHI64(lo,hi) ( (lo) | ((ULong)(hi) << 32) ) + +PRE(sys_fork) +{ + PRINT("sys_fork ()"); + PRE_REG_READ0(int, "fork"); + + SET_STATUS_from_SysRes( ML_(do_fork)(tid) ); + if (SUCCESS) { + /* Thread creation was successful; let the child have the chance + to run */ + *flags |= SfYieldAfter; + } +} + +PRE(sys_vfork) +{ + PRINT("sys_vfork ()"); + PRE_REG_READ0(int, "vfork"); + + /* Pretend vfork == fork. Not true, but will have to do. */ + SET_STATUS_from_SysRes( ML_(do_fork)(tid) ); + if (SUCCESS) { + /* Thread creation was successful; let the child have the chance + to run */ + *flags |= SfYieldAfter; + } +} + +PRE(sys_socket) +{ + PRINT("sys_socket ( %ld, %ld, %ld )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "socket", int, domain, int, type, int, protocol); +} +POST(sys_socket) +{ + SysRes r; + vg_assert(SUCCESS); + r = ML_(generic_POST_sys_socket)(tid, VG_(mk_SysRes_Success)(RES)); + SET_STATUS_from_SysRes(r); +} + +PRE(sys_setsockopt) +{ + PRINT("sys_setsockopt ( %ld, %ld, %ld, %#lx, %ld )",ARG1,ARG2,ARG3,ARG4,ARG5); + PRE_REG_READ5(long, "setsockopt", + int, s, int, level, int, optname, + const void *, optval, int, optlen); + ML_(generic_PRE_sys_setsockopt)(tid, ARG1,ARG2,ARG3,ARG4,ARG5); +} + +PRE(sys_getsockopt) +{ + PRINT("sys_getsockopt ( %ld, %ld, %ld, %#lx, %#lx )",ARG1,ARG2,ARG3,ARG4,ARG5); + PRE_REG_READ5(long, "getsockopt", + int, s, int, level, int, optname, + void *, optval, int, *optlen); +// XXX: ML_(generic_PRE_sys_getsockopt)(tid, ARG1,ARG2,ARG3,ARG4,ARG5); +} +POST(sys_getsockopt) +{ + vg_assert(SUCCESS); +// ML_(generic_POST_sys_getsockopt)(tid, VG_(mk_SysRes_Success)(RES), +//XXX: ARG1,ARG2,ARG3,ARG4,ARG5); +} + +PRE(sys_connect) +{ + *flags |= SfMayBlock; + PRINT("sys_connect ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "connect", + int, sockfd, struct sockaddr *, serv_addr, int, addrlen); + ML_(generic_PRE_sys_connect)(tid, ARG1,ARG2,ARG3); +} + +PRE(sys_accept) +{ + *flags |= SfMayBlock; + PRINT("sys_accept ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "accept", + int, s, struct sockaddr *, addr, int, *addrlen); + ML_(generic_PRE_sys_accept)(tid, ARG1,ARG2,ARG3); +} +POST(sys_accept) +{ + SysRes r; + vg_assert(SUCCESS); + r = ML_(generic_POST_sys_accept)(tid, VG_(mk_SysRes_Success)(RES), + ARG1,ARG2,ARG3); + SET_STATUS_from_SysRes(r); +} + +/* XXX copied from syswrap-linux.c */ +PRE(sys_accept4) +{ + *flags |= SfMayBlock; + PRINT("sys_accept4 ( %ld, %#lx, %ld, %ld )",ARG1,ARG2,ARG3,ARG4); + PRE_REG_READ4(long, "accept4", + int, s, struct sockaddr *, addr, int, *addrlen, int, flags); + ML_(generic_PRE_sys_accept)(tid, ARG1,ARG2,ARG3); +} +POST(sys_accept4) +{ + SysRes r; + vg_assert(SUCCESS); + r = ML_(generic_POST_sys_accept)(tid, VG_(mk_SysRes_Success)(RES), + ARG1,ARG2,ARG3); + SET_STATUS_from_SysRes(r); +} + +PRE(sys_sendto) +{ + *flags |= SfMayBlock; + PRINT("sys_sendto ( %ld, %#lx, %ld, %lu, %#lx, %ld )",ARG1,ARG2,ARG3,ARG4,ARG5,ARG6); + PRE_REG_READ6(long, "sendto", + int, s, const void *, msg, int, len, + unsigned int, flags, + const struct sockaddr *, to, int, tolen); + ML_(generic_PRE_sys_sendto)(tid, ARG1,ARG2,ARG3,ARG4,ARG5,ARG6); +} + +PRE(sys_recvfrom) +{ + *flags |= SfMayBlock; + PRINT("sys_recvfrom ( %ld, %#lx, %ld, %lu, %#lx, %#lx )",ARG1,ARG2,ARG3,ARG4,ARG5,ARG6); + PRE_REG_READ6(long, "recvfrom", + int, s, void *, buf, int, len, unsigned int, flags, + struct sockaddr *, from, int *, fromlen); + ML_(generic_PRE_sys_recvfrom)(tid, ARG1,ARG2,ARG3,ARG4,ARG5,ARG6); +} +POST(sys_recvfrom) +{ + vg_assert(SUCCESS); + ML_(generic_POST_sys_recvfrom)(tid, VG_(mk_SysRes_Success)(RES), + ARG1,ARG2,ARG3,ARG4,ARG5,ARG6); +} + +PRE(sys_sendmsg) +{ + *flags |= SfMayBlock; + PRINT("sys_sendmsg ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "sendmsg", + int, s, const struct msghdr *, msg, int, flags); + ML_(generic_PRE_sys_sendmsg)(tid, "sendmsg", (struct vki_msghdr *)ARG2); +} + +PRE(sys_recvmsg) +{ + *flags |= SfMayBlock; + PRINT("sys_recvmsg ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "recvmsg", int, s, struct msghdr *, msg, int, flags); + ML_(generic_PRE_sys_recvmsg)(tid, "recvmsg", (struct vki_msghdr *)ARG2); +} +POST(sys_recvmsg) +{ + + ML_(generic_POST_sys_recvmsg)(tid, "recvmsg", (struct vki_msghdr *)ARG2, RES); +} + +PRE(sys_shutdown) +{ + *flags |= SfMayBlock; + PRINT("sys_shutdown ( %ld, %ld )",ARG1,ARG2); + PRE_REG_READ2(int, "shutdown", int, s, int, how); +} + +PRE(sys_bind) +{ + PRINT("sys_bind ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "bind", + int, sockfd, struct sockaddr *, my_addr, int, addrlen); + ML_(generic_PRE_sys_bind)(tid, ARG1,ARG2,ARG3); +} + +PRE(sys_listen) +{ + PRINT("sys_listen ( %ld, %ld )",ARG1,ARG2); + PRE_REG_READ2(long, "listen", int, s, int, backlog); +} + +PRE(sys_pledge) +{ + /* Force success to prevent client from actually calling pledge(2). */ + SET_STATUS_Success(0); +} + +PRE(sys_ppoll) +{ +// XXXTBD +} + +PRE(sys_pselect) +{ +// XXXTBD +} + +PRE(sys_getsockname) +{ + PRINT("sys_getsockname ( %ld, %#lx, %#lx )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "getsockname", + int, s, struct sockaddr *, name, int *, namelen); + ML_(generic_PRE_sys_getsockname)(tid, ARG1,ARG2,ARG3); +} +POST(sys_getsockname) +{ + vg_assert(SUCCESS); + ML_(generic_POST_sys_getsockname)(tid, VG_(mk_SysRes_Success)(RES), + ARG1,ARG2,ARG3); +} + +PRE(sys_getpeername) +{ + PRINT("sys_getpeername ( %ld, %#lx, %#lx )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "getpeername", + int, s, struct sockaddr *, name, int *, namelen); + ML_(generic_PRE_sys_getpeername)(tid, ARG1,ARG2,ARG3); +} +POST(sys_getpeername) +{ + vg_assert(SUCCESS); + ML_(generic_POST_sys_getpeername)(tid, VG_(mk_SysRes_Success)(RES), + ARG1,ARG2,ARG3); +} + +PRE(sys_socketpair) +{ + PRINT("sys_socketpair ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4); + PRE_REG_READ4(long, "socketpair", + int, d, int, type, int, protocol, int *, sv); + ML_(generic_PRE_sys_socketpair)(tid, ARG1,ARG2,ARG3,ARG4); +} +POST(sys_socketpair) +{ + vg_assert(SUCCESS); + ML_(generic_POST_sys_socketpair)(tid, VG_(mk_SysRes_Success)(RES), + ARG1,ARG2,ARG3,ARG4); +} + +/* --------------------------------------------------------------------- + *mount wrappers + ------------------------------------------------------------------ */ + +PRE(sys_mount) +{ + // Nb: depending on 'flags', the 'type' and 'data' args may be ignored. + // We are conservative and check everything, except the memory pointed to + // by 'data'. + *flags |= SfMayBlock; + PRINT( "sys_mount( %#lx, %#lx, %ld, %#lx )" ,ARG1,ARG2,ARG3,ARG4); + PRE_REG_READ4(long, "mount", + char *, type, char *, path, int, flags, + void *, data); + PRE_MEM_RASCIIZ( "mount(type)", ARG1); + PRE_MEM_RASCIIZ( "mount(path)", ARG2); +} + +PRE(sys_unmount) +{ + PRINT("sys_umount( %#lx, %ld )", ARG1, ARG2); + PRE_REG_READ2(long, "unmount", char *, path, int, flags); + PRE_MEM_RASCIIZ( "unmount(path)", ARG1); +} + +/* --------------------------------------------------------------------- + 16- and 32-bit uid/gid wrappers + ------------------------------------------------------------------ */ + +#if 0 +PRE(sys_setfsuid) +{ + PRINT("sys_setfsuid ( %ld )", ARG1); + PRE_REG_READ1(long, "setfsuid", vki_uid_t, uid); +} + +PRE(sys_setfsgid) +{ + PRINT("sys_setfsgid ( %ld )", ARG1); + PRE_REG_READ1(long, "setfsgid", vki_gid_t, gid); +} +#endif + +PRE(sys_setresuid) +{ + PRINT("sys_setresuid ( %ld, %ld, %ld )", ARG1, ARG2, ARG3); + PRE_REG_READ3(long, "setresuid", + vki_uid_t, ruid, vki_uid_t, euid, vki_uid_t, suid); +} + +PRE(sys_getresuid) +{ + PRINT("sys_getresuid ( %#lx, %#lx, %#lx )", ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "getresuid", + vki_uid_t *, ruid, vki_uid_t *, euid, vki_uid_t *, suid); + PRE_MEM_WRITE( "getresuid(ruid)", ARG1, sizeof(vki_uid_t) ); + PRE_MEM_WRITE( "getresuid(euid)", ARG2, sizeof(vki_uid_t) ); + PRE_MEM_WRITE( "getresuid(suid)", ARG3, sizeof(vki_uid_t) ); +} + +POST(sys_getresuid) +{ + vg_assert(SUCCESS); + if (RES == 0) { + POST_MEM_WRITE( ARG1, sizeof(vki_uid_t) ); + POST_MEM_WRITE( ARG2, sizeof(vki_uid_t) ); + POST_MEM_WRITE( ARG3, sizeof(vki_uid_t) ); + } +} + +PRE(sys_setresgid) +{ + PRINT("sys_setresgid ( %ld, %ld, %ld )", ARG1, ARG2, ARG3); + PRE_REG_READ3(long, "setresgid", + vki_gid_t, rgid, vki_gid_t, egid, vki_gid_t, sgid); +} + +PRE(sys_getresgid) +{ + PRINT("sys_getresgid ( %#lx, %#lx, %#lx )", ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "getresgid", + vki_gid_t *, rgid, vki_gid_t *, egid, vki_gid_t *, sgid); + PRE_MEM_WRITE( "getresgid(rgid)", ARG1, sizeof(vki_gid_t) ); + PRE_MEM_WRITE( "getresgid(egid)", ARG2, sizeof(vki_gid_t) ); + PRE_MEM_WRITE( "getresgid(sgid)", ARG3, sizeof(vki_gid_t) ); +} + +POST(sys_getresgid) +{ + vg_assert(SUCCESS); + if (RES == 0) { + POST_MEM_WRITE( ARG1, sizeof(vki_gid_t) ); + POST_MEM_WRITE( ARG2, sizeof(vki_gid_t) ); + POST_MEM_WRITE( ARG3, sizeof(vki_gid_t) ); + } +} + +/* --------------------------------------------------------------------- + miscellaneous wrappers + ------------------------------------------------------------------ */ + +#if 0 +PRE(sys_exit_group) +{ + ThreadId t; + ThreadState* tst; + + PRINT("exit_group( %ld )", ARG1); + PRE_REG_READ1(void, "exit_group", int, exit_code); + + tst = VG_(get_ThreadState)(tid); + + /* A little complex; find all the threads with the same threadgroup + as this one (including this one), and mark them to exit */ + for (t = 1; t < VG_N_THREADS; t++) { + if ( /* not alive */ + VG_(threads)[t].status == VgTs_Empty + || + /* not our group */ + VG_(threads)[t].os_state.threadgroup != tst->os_state.threadgroup + ) + continue; + + VG_(threads)[t].exitreason = VgSrc_ExitSyscall; + VG_(threads)[t].os_state.exitcode = ARG1; + + if (t != tid) + VG_(get_thread_out_of_syscall)(t); /* unblock it, if blocked */ + } + + /* We have to claim the syscall already succeeded. */ + SET_STATUS_Success(0); +} +#endif + +/* On FreeBSD, if any thread calls exit(2), then they are all shut down, pretty + * much like linux's exit_group(). + */ +PRE(sys_exit) +{ + ThreadId t; + ThreadState* tst; + + PRINT("exit( %ld )", ARG1); + PRE_REG_READ1(void, "exit", int, status); + tst = VG_(get_ThreadState)(tid); + + /* Mark all threads (including this one) to exit. */ + for (t = 1; t < VG_N_THREADS; t++) { + if ( /* not alive */ VG_(threads)[t].status == VgTs_Empty ) + continue; + + VG_(threads)[t].exitreason = VgSrc_ExitThread; + VG_(threads)[t].os_state.exitcode = ARG1; + + if (t != tid) + VG_(get_thread_out_of_syscall)(t); /* unblock it, if blocked */ + } + + /* We have to claim the syscall already succeeded. */ + SET_STATUS_Success(0); +} + +PRE(sys___tfork) +{ +// XXXTBD +} +POST(sys___tfork) +{ +// XXXTBD +} + +PRE(sys_getlogin) +{ + PRINT("sys_getlogin ( %#lx, %ld )",ARG1,ARG2); + PRE_REG_READ2(long, "getlogin", + char *, buf, int, len); + PRE_MEM_WRITE( "getlogin(buf, len)", ARG1, ARG2 ); +} +POST(sys_getlogin) +{ + if (ARG1 != 0) { + POST_MEM_WRITE( ARG1, ARG2 ); + } +} +PRE(sys_setlogin) +{ + PRINT("sys_setlogin ( %#lx )",ARG1); + PRE_REG_READ1(long, "setlogin", char *, buf); + PRE_MEM_RASCIIZ( "setlogin(buf)", ARG1 ); +} +PRE(sys_mkfifo) +{ + PRINT("sys_mkfifo ( %#lx(%s), 0x%lx, 0x%lx )", ARG1, (char *)ARG1, ARG2, ARG3 ); + PRE_REG_READ2(long, "mkfifo", const char *, pathname, int, mode); + PRE_MEM_RASCIIZ( "mkfifo(pathname)", ARG1 ); +} + +/* int quotactl(const char *path, int cmd, int id, void *addr); */ + +PRE(sys_adjtime) +{ +// XXXTBD +} + +PRE(sys_quotactl) +{ + PRINT("sys_quotactl (%#lx, %ld, %ld, %#lx )", ARG1,ARG2,ARG3, ARG4); + PRE_REG_READ4(long, "quotactl", + const char *, path, int, cmd, int, id, + void *, addr); + PRE_MEM_RASCIIZ( "quotactl(path)", ARG1 ); +} + +PRE(sys_nfssvc) +{ +// XXXTBD +} + +/* int getdomainname(char *domainname, int len); */ +PRE(sys_getdomainname) +{ + PRINT("sys_getdomainname ( %#lx, %ld )",ARG1,ARG2); + PRE_REG_READ2(long, "getdomainname", + char *, buf, int, len); + PRE_MEM_WRITE( "getdomainname(buf, len)", ARG1, ARG2 ); +} +POST(sys_getdomainname) +{ + if (ARG1 != 0) { + POST_MEM_WRITE( ARG1, ARG2 ); + } +} +/* int setdomainname(char *domainname, int len); */ +PRE(sys_setdomainname) +{ + PRINT("sys_setdomainname ( %#lx )",ARG1); + PRE_REG_READ1(long, "setdomainname", char *, buf); + PRE_MEM_RASCIIZ( "setdomainname(buf)", ARG1 ); +} + +#if 0 +PRE(sys_uname) +{ + PRINT("sys_uname ( %#lx )", ARG1); + PRE_REG_READ1(long, "uname", struct utsname *, buf); + PRE_MEM_WRITE( "uname(buf)", ARG1, sizeof(struct vki_utsname) ); +} + +POST(sys_uname) +{ + if (ARG1 != 0) { + POST_MEM_WRITE( ARG1, sizeof(struct vki_utsname) ); + } +} +#endif + +PRE(sys_lstat) +{ + PRINT("sys_lstat ( %#lx(%s), %#lx )",ARG1,(char *)ARG1,ARG2); + PRE_REG_READ2(long, "lstat", char *, file_name, struct stat *, buf); + PRE_MEM_RASCIIZ( "lstat(file_name)", ARG1 ); + PRE_MEM_WRITE( "lstat(buf)", ARG2, sizeof(struct vki_stat) ); +} + +POST(sys_lstat) +{ + vg_assert(SUCCESS); + if (RES == 0) { + POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) ); + } +} + +PRE(sys_stat) +{ + PRINT("sys_stat ( %#lx(%s), %#lx )",ARG1,(char *)ARG1,ARG2); + PRE_REG_READ2(long, "stat", char *, file_name, struct stat *, buf); + PRE_MEM_RASCIIZ( "stat(file_name)", ARG1 ); + PRE_MEM_WRITE( "stat(buf)", ARG2, sizeof(struct vki_stat) ); +} + +POST(sys_stat) +{ + POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) ); +} + +PRE(sys_fstat) +{ + PRINT("sys_fstat ( %ld, %#lx )",ARG1,ARG2); + PRE_REG_READ2(long, "fstat", unsigned long, fd, struct stat *, buf); + PRE_MEM_WRITE( "fstat(buf)", ARG2, sizeof(struct vki_stat) ); +} + +POST(sys_fstat) +{ + POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) ); +} + +PRE(sys_pathconf) +{ + PRINT("sys_pathconf ( %#lx(%s), %ld )",ARG1,(char *)ARG1,ARG2); + PRE_REG_READ2(long, "pathconf", char *, file_name, int, name); + PRE_MEM_RASCIIZ( "pathconf(file_name)", ARG1 ); +} + +PRE(sys_fpathconf) +{ + PRINT("sys_fpathconf ( %ld, %ld )",ARG1,ARG2); + PRE_REG_READ2(long, "fpathconf", int, fd, int, name); +} + +PRE(sys_lchmod) +{ + PRINT("sys_lchmod ( %#lx(%s), %ld )", ARG1,(char *)ARG1,ARG2); + PRE_REG_READ2(long, "lchmod", const char *, path, vki_mode_t, mode); + PRE_MEM_RASCIIZ( "lchmod(path)", ARG1 ); +} + +PRE(sys_issetugid) +{ + PRINT("sys_issetugid ()"); + PRE_REG_READ0(long, "issetugid"); +} + +PRE(sys_revoke) +{ + PRINT("sys_vhangup ( )"); + PRE_REG_READ0(long, "vhangup"); +} +PRE(sys_undelete) +{ + *flags |= SfMayBlock; + PRINT("sys_undelete ( %#lx(%s) )", ARG1,(char *)ARG1); + PRE_REG_READ1(long, "undelete", const char *, pathname); + PRE_MEM_RASCIIZ( "undelete(pathname)", ARG1 ); +} +PRE(sys_yield) +{ + *flags |= SfMayBlock; + PRINT("yield()"); + PRE_REG_READ0(long, "yield"); +} + +PRE(sys_sched_yield) +{ + *flags |= SfMayBlock; + PRINT("sched_yield()"); +} + +#if 0 +PRE(sys_sysinfo) +{ + PRINT("sys_sysinfo ( %#lx )",ARG1); + PRE_REG_READ1(long, "sysinfo", struct sysinfo *, info); + PRE_MEM_WRITE( "sysinfo(info)", ARG1, sizeof(struct vki_sysinfo) ); +} + +POST(sys_sysinfo) +{ + POST_MEM_WRITE( ARG1, sizeof(struct vki_sysinfo) ); +} +#endif + +/* int __sysctl(int *name, u_int namelen, void *old, size_t *oldlenp, void *new, size_t newlen); */ +/* ARG1 ARG2 ARG3 ARG4 ARG5 ARG6 */ + +PRE(sys___sysctl) +{ + PRINT("sys_sysctl ( %#lx, %ld, %#lx, %#lx, %#lx, %ld )", ARG1,ARG2,ARG3,ARG4,ARG5,ARG6 ); + PRE_REG_READ6(long, "__sysctl", int *, name, unsigned int, namelen, void *, old, + vki_size_t *, oldlenp, void *, new, vki_size_t, newlen); + PRE_MEM_READ("sysctl(name)", ARG1, ARG2 * sizeof(int)); + if (ARG5 != (UWord)NULL) + PRE_MEM_READ("sysctl(new)", (Addr)ARG5, ARG6); + if (ARG4 != (UWord)NULL) { + if (ARG3 != (UWord)NULL) { + PRE_MEM_READ("sysctl(oldlenp)", (Addr)ARG4, sizeof(vki_size_t)); + PRE_MEM_WRITE("sysctl(oldval)", (Addr)ARG3, *(vki_size_t *)ARG4); + } + PRE_MEM_WRITE("sysctl(oldlenp)", (Addr)ARG4, sizeof(vki_size_t)); + } +} +POST(sys___sysctl) +{ + if (ARG4 != (UWord)NULL) { + POST_MEM_WRITE((Addr)ARG4, sizeof(vki_size_t)); + if (ARG3 != (UWord)NULL) + POST_MEM_WRITE((Addr)ARG3, *(vki_size_t *)ARG4); + } +} + +PRE(sys_sendfile) +{ + *flags |= SfMayBlock; +#if defined(VGP_x86_openbsd) + PRINT("sys_sendfile ( %ld, %ld, %llu, %ld, %#lx, %#lx, %lu )", ARG1,ARG2,LOHI64(ARG3,ARG4),ARG5,ARG6,ARG7,ARG8); +#elif defined(VGP_amd64_openbsd) + PRINT("sys_sendfile ( %ld, %ld, %lu, %ld, %#lx, %#lx, %lu )", ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7); +#else +# error Unknown platform +#endif + PRE_REG_READ7(ssize_t, "sendfile", + int, fd, int, s, unsigned int, offset_low, + unsigned int, offset_high, + void *, hdtr, vki_off_t *, sbytes, int, flags); + if (ARG3 != 0) + PRE_MEM_WRITE( "sendfile(offset)", ARG3, sizeof(vki_off_t) ); +} +POST(sys_sendfile) +{ + if (ARG3 != 0 ) { + POST_MEM_WRITE( ARG3, sizeof( vki_off_t ) ); + } +} + +PRE(sys_seteuid) +{ + PRINT("sys_seteuid ( %ld )", ARG1); + PRE_REG_READ1(long, "seteuid", vki_uid_t, uid); +} + +PRE(sys_setegid) +{ + PRINT("sys_setegid ( %ld )", ARG1); + PRE_REG_READ1(long, "setegid", vki_gid_t, gid); +} + +PRE(sys_lutimes) +{ + PRINT("sys_lutimes ( %#lx(%s), %#lx )", ARG1,(char *)ARG1,ARG2); + PRE_REG_READ2(long, "lutimes", char *, filename, struct timeval *, tvp); + PRE_MEM_RASCIIZ( "lutimes(filename)", ARG1 ); + if (ARG2 != 0) + PRE_MEM_READ( "lutimes(tvp)", ARG2, sizeof(struct vki_timeval) ); +} + +PRE(sys_futimes) +{ + PRINT("sys_lutimes ( %ld, %#lx )", ARG1,ARG2); + PRE_REG_READ2(long, "futimes", int, fd, struct timeval *, tvp); + if (ARG2 != 0) + PRE_MEM_READ( "futimes(tvp)", ARG2, sizeof(struct vki_timeval) ); +} + +PRE(sys_utrace) +{ + PRINT("sys_utrace ( %#lx, %lu )", ARG1, ARG2); + PRE_REG_READ2(long, "utrace", const void *, buf, vki_size_t, len); + PRE_MEM_READ( "utrace(buf,len)", ARG2, ARG3 ); +} + +PRE(sys_getdtablecount) +{ + PRINT("sys_getdtablecount ( )"); + PRE_REG_READ0(long, "getdtablecount"); +} + +PRE(sys_kqueue) +{ + PRINT("sys_kqueue ()"); +} +POST(sys_kqueue) +{ + if (!ML_(fd_allowed)(RES, "kqueue", tid, True)) { + VG_(close)(RES); + SET_STATUS_Failure( VKI_EMFILE ); + } else { + if (VG_(clo_track_fds)) { + ML_(record_fd_open_nameless)(tid, RES); + } + } +} + +PRE(sys_kevent) +{ + /* struct kevent { + uintptr_t ident; -- identifier for this event + short filter; -- filter for event + u_short flags; -- action flags for kqueue + u_int fflags; -- filter flag value + intptr_t data; -- filter data value + void *udata; -- opaque user data identifier + }; + int kevent(int kq, const struct kevent *changelist, int nchanges, + struct kevent *eventlist, int nevents, + const struct timespec *timeout); + */ + *flags |= SfMayBlock; + PRINT("sys_kevent ( %ld, %#lx, %ld, %#lx, %ld, %#lx )\n", ARG1,ARG2,ARG3,ARG4,ARG5,ARG6); + PRE_REG_READ6(long, "kevent", + int, fd, struct vki_kevent *, newev, int, num_newev, + struct vki_kevent *, ret_ev, int, num_retev, + struct timespec *, timeout); + if (ARG2 != 0 && ARG3 != 0) + PRE_MEM_READ( "kevent(changeevent)", ARG2, sizeof(struct vki_kevent)*ARG3 ); + if (ARG4 != 0 && ARG5 != 0) + PRE_MEM_WRITE( "kevent(events)", ARG4, sizeof(struct vki_kevent)*ARG5); + if (ARG6 != 0) + PRE_MEM_READ( "kevent(timeout)", + ARG6, sizeof(struct vki_timespec)); +} + +POST(sys_kevent) +{ + vg_assert(SUCCESS); + if (RES > 0) { + if (ARG4 != 0) + POST_MEM_WRITE( ARG4, sizeof(struct vki_kevent)*RES) ; + } +} + +PRE(sys___getcwd) +{ + PRINT("sys___getcwd ( %#lx, %lu )", ARG1,ARG2); + PRE_REG_READ2(long, "__getcwd", char *, buf, unsigned int, size); + PRE_MEM_WRITE( "__getcwd(buf)", ARG1, ARG2 ); +} + +POST(sys___getcwd) +{ + vg_assert(SUCCESS); + if (RES == 0) { + // QQQ it is unclear if this is legal or not, but the + // QQQ kernel just wrote it there... + // QQQ Why oh why didn't phk return the length from __getcwd()? + UInt len = VG_(strlen) ( (char *)ARG1 ) + 1; + POST_MEM_WRITE( ARG1, len ); + } +} + +// getfsstat() takes a length in bytes, but returns the number of structures +// returned, not a length. +PRE(sys_getfsstat4) +{ + PRINT("sys_getfsstat ( %#lx, %ld, %ld )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "getfsstat", struct vki_statfs4 *, buf, long, len, int, flags); + PRE_MEM_WRITE( "getfsstat(buf)", ARG1, ARG2 ); +} +POST(sys_getfsstat4) +{ + vg_assert(SUCCESS); + if (RES > 0) { + POST_MEM_WRITE( ARG1, RES * sizeof(struct vki_statfs4) ); + } +} + +PRE(sys_getfsstat) +{ + PRINT("sys_getfsstat ( %#lx, %ld, %ld )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "getfsstat", struct vki_statfs *, buf, long, len, int, flags); + PRE_MEM_WRITE( "getfsstat(buf)", ARG1, ARG2 ); +} +POST(sys_getfsstat) +{ + vg_assert(SUCCESS); + if (RES > 0) { + POST_MEM_WRITE( ARG1, RES * sizeof(struct vki_statfs) ); + } +} + +PRE(sys_fhopen) +{ + PRINT("sys_open ( %#lx, %ld )",ARG1,ARG2); + PRE_REG_READ2(long, "open", + struct fhandle *, fhp, int, flags); + PRE_MEM_READ( "fhopen(fhp)", ARG1, sizeof(struct vki_fhandle) ); + + /* Otherwise handle normally */ + *flags |= SfMayBlock; +} + +POST(sys_fhopen) +{ + vg_assert(SUCCESS); + if (!ML_(fd_allowed)(RES, "fhopen", tid, True)) { + VG_(close)(RES); + SET_STATUS_Failure( VKI_EMFILE ); + } else { + if (VG_(clo_track_fds)) + ML_(record_fd_open_nameless)(tid, RES); + } +} + +PRE(sys_fhstat) +{ + PRINT("sys_fhstat ( %#lx, %#lx )",ARG1,ARG2); + PRE_REG_READ2(long, "fhstat", struct fhandle *, fhp, struct stat *, buf); + PRE_MEM_READ( "fhstat(fhp)", ARG1, sizeof(struct vki_fhandle) ); + PRE_MEM_WRITE( "fhstat(buf)", ARG2, sizeof(struct vki_stat) ); +} + +POST(sys_fhstat) +{ + POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) ); +} + +PRE(sys_fhstatfs) +{ + PRINT("sys_fstatfs ( %#lx, %#lx )",ARG1,ARG2); + PRE_REG_READ2(long, "fhstatfs", + struct fhandle *, fhp, struct statfs *, buf); + PRE_MEM_READ( "fhstatfs(fhp)", ARG1, sizeof(struct vki_fhandle) ); + PRE_MEM_WRITE( "fhstatfs(buf)", ARG2, sizeof(struct vki_statfs) ); +} + +POST(sys_fhstatfs) +{ + POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs) ); +} + +PRE(sys_fhstatfs6) +{ + PRINT("sys_fstatfs6 ( %#lx, %#lx )",ARG1,ARG2); + PRE_REG_READ2(long, "fhstatfs6", + struct fhandle *, fhp, struct statfs *, buf); + PRE_MEM_READ( "fhstatfs6(fhp)", ARG1, sizeof(struct vki_fhandle) ); + PRE_MEM_WRITE( "fhstatfs6(buf)", ARG2, sizeof(struct vki_statfs6) ); +} + +POST(sys_fhstatfs6) +{ + POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs6) ); +} + +PRE(sys_fstatfs6) +{ + PRINT("sys_fstatfs6 ( %ld, %#lx )",ARG1,ARG2); + PRE_REG_READ2(long, "fstatfs6", + unsigned int, fd, struct statfs *, buf); + PRE_MEM_WRITE( "fstatfs6(buf)", ARG2, sizeof(struct vki_statfs6) ); +} + +POST(sys_fstatfs6) +{ + POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs6) ); +} + +PRE(sys_statfs6) +{ + PRINT("sys_statfs6 ( %#lx(%s), %#lx )",ARG1,(char *)ARG1,ARG2); + PRE_REG_READ2(long, "statfs6", const char *, path, struct statfs *, buf); + PRE_MEM_RASCIIZ( "statfs6(path)", ARG1 ); + PRE_MEM_WRITE( "statfs(buf)", ARG2, sizeof(struct vki_statfs6) ); +} +POST(sys_statfs6) +{ + POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs6) ); +} + + +#if 0 +/* --------------------------------------------------------------------- + aio_* wrappers + ------------------------------------------------------------------ */ + +// Nb: this wrapper has to pad/unpad memory around the syscall itself, +// and this allows us to control exactly the code that gets run while +// the padding is in place. + +PRE(sys_io_setup) +{ + PRINT("sys_io_setup ( %lu, %#lx )", ARG1,ARG2); + PRE_REG_READ2(long, "io_setup", + unsigned, nr_events, vki_aio_context_t *, ctxp); + PRE_MEM_WRITE( "io_setup(ctxp)", ARG2, sizeof(vki_aio_context_t) ); +} + +POST(sys_io_setup) +{ + SizeT size; + struct vki_aio_ring *r; + + size = VG_PGROUNDUP(sizeof(struct vki_aio_ring) + + ARG1*sizeof(struct vki_io_event)); + r = *(struct vki_aio_ring **)ARG2; + vg_assert(ML_(valid_client_addr)((Addr)r, size, tid, "io_setup")); + + ML_(notify_aspacem_and_tool_of_mmap)( (Addr)r, size, + VKI_PROT_READ | VKI_PROT_WRITE, + VKI_MAP_ANONYMOUS, -1, 0 ); + + POST_MEM_WRITE( ARG2, sizeof(vki_aio_context_t) ); +} + +// Nb: This wrapper is "Special" because we need 'size' to do the unmap +// after the syscall. We must get 'size' from the aio_ring structure, +// before the syscall, while the aio_ring structure still exists. (And we +// know that we must look at the aio_ring structure because Tom inspected the +// kernel and glibc sources to see what they do, yuk.) +// +// XXX This segment can be implicitly unmapped when aio +// file-descriptors are closed... +PRE(sys_io_destroy) +{ + struct vki_aio_ring *r; + SizeT size; + + PRINT("sys_io_destroy ( %llu )", (ULong)ARG1); + PRE_REG_READ1(long, "io_destroy", vki_aio_context_t, ctx); + + // If we are going to seg fault (due to a bogus ARG1) do it as late as + // possible... + r = (struct vki_aio_ring *)ARG1; + size = VG_PGROUNDUP(sizeof(struct vki_aio_ring) + + r->nr*sizeof(struct vki_io_event)); + + SET_STATUS_from_SysRes( VG_(do_syscall1)(SYSNO, ARG1) ); + + if (SUCCESS && RES == 0) { + Bool d = VG_(am_notify_munmap)( ARG1, size ); + VG_TRACK( die_mem_munmap, ARG1, size ); + if (d) + VG_(discard_translations)( (Addr64)ARG1, (ULong)size, + "PRE(sys_io_destroy)" ); + } +} + +PRE(sys_io_getevents) +{ + *flags |= SfMayBlock; + PRINT("sys_io_getevents ( %llu, %lld, %lld, %#lx, %#lx )", + (ULong)ARG1,(Long)ARG2,(Long)ARG3,ARG4,ARG5); + PRE_REG_READ5(long, "io_getevents", + vki_aio_context_t, ctx_id, long, min_nr, long, nr, + struct io_event *, events, + struct timespec *, timeout); + if (ARG3 > 0) + PRE_MEM_WRITE( "io_getevents(events)", + ARG4, sizeof(struct vki_io_event)*ARG3 ); + if (ARG5 != 0) + PRE_MEM_READ( "io_getevents(timeout)", + ARG5, sizeof(struct vki_timespec)); +} +POST(sys_io_getevents) +{ + Int i; + vg_assert(SUCCESS); + if (RES > 0) { + POST_MEM_WRITE( ARG4, sizeof(struct vki_io_event)*RES ); + for (i = 0; i < RES; i++) { + const struct vki_io_event *vev = ((struct vki_io_event *)ARG4) + i; + const struct vki_iocb *cb = (struct vki_iocb *)(Addr)vev->obj; + + switch (cb->aio_lio_opcode) { + case VKI_IOCB_CMD_PREAD: + if (vev->result > 0) + POST_MEM_WRITE( cb->aio_buf, vev->result ); + break; + + case VKI_IOCB_CMD_PWRITE: + break; + + default: + VG_(message)(Vg_DebugMsg, + "Warning: unhandled io_getevents opcode: %u\n", + cb->aio_lio_opcode); + break; + } + } + } +} + +PRE(sys_io_submit) +{ + Int i; + + PRINT("sys_io_submit ( %llu, %ld, %#lx )", (ULong)ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "io_submit", + vki_aio_context_t, ctx_id, long, nr, + struct iocb **, iocbpp); + PRE_MEM_READ( "io_submit(iocbpp)", ARG3, ARG2*sizeof(struct vki_iocb *) ); + if (ARG3 != 0) { + for (i = 0; i < ARG2; i++) { + struct vki_iocb *cb = ((struct vki_iocb **)ARG3)[i]; + PRE_MEM_READ( "io_submit(iocb)", (Addr)cb, sizeof(struct vki_iocb) ); + switch (cb->aio_lio_opcode) { + case VKI_IOCB_CMD_PREAD: + PRE_MEM_WRITE( "io_submit(PREAD)", cb->aio_buf, cb->aio_nbytes ); + break; + + case VKI_IOCB_CMD_PWRITE: + PRE_MEM_READ( "io_submit(PWRITE)", cb->aio_buf, cb->aio_nbytes ); + break; + + default: + VG_(message)(Vg_DebugMsg,"Warning: unhandled io_submit opcode: %u\n", + cb->aio_lio_opcode); + break; + } + } + } +} + +PRE(sys_io_cancel) +{ + PRINT("sys_io_cancel ( %llu, %#lx, %#lx )", (ULong)ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "io_cancel", + vki_aio_context_t, ctx_id, struct iocb *, iocb, + struct io_event *, result); + PRE_MEM_READ( "io_cancel(iocb)", ARG2, sizeof(struct vki_iocb) ); + PRE_MEM_WRITE( "io_cancel(result)", ARG3, sizeof(struct vki_io_event) ); +} +POST(sys_io_cancel) +{ + POST_MEM_WRITE( ARG3, sizeof(struct vki_io_event) ); +} + +/* --------------------------------------------------------------------- + inotify_* wrappers + ------------------------------------------------------------------ */ + +PRE(sys_inotify_init) +{ + PRINT("sys_inotify_init ( )"); + PRE_REG_READ0(long, "inotify_init"); +} +POST(sys_inotify_init) +{ + vg_assert(SUCCESS); + if (!ML_(fd_allowed)(RES, "inotify_init", tid, True)) { + VG_(close)(RES); + SET_STATUS_Failure( VKI_EMFILE ); + } else { + if (VG_(clo_track_fds)) + ML_(record_fd_open_nameless) (tid, RES); + } +} + +PRE(sys_inotify_add_watch) +{ + PRINT( "sys_inotify_add_watch ( %ld, %#lx, %lx )", ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "inotify_add_watch", int, fd, char *, path, int, mask); + PRE_MEM_RASCIIZ( "inotify_add_watch(path)", ARG2 ); +} + +PRE(sys_inotify_rm_watch) +{ + PRINT( "sys_inotify_rm_watch ( %ld, %lx )", ARG1,ARG2); + PRE_REG_READ2(long, "inotify_rm_watch", int, fd, int, wd); +} + +/* --------------------------------------------------------------------- + mq_* wrappers + ------------------------------------------------------------------ */ + +PRE(sys_mq_open) +{ + PRINT("sys_mq_open( %#lx(%s), %ld, %lld, %#lx )", + ARG1,(char *)ARG1,ARG2,(ULong)ARG3,ARG4); + PRE_REG_READ4(long, "mq_open", + const char *, name, int, oflag, vki_mode_t, mode, + struct mq_attr *, attr); + PRE_MEM_RASCIIZ( "mq_open(name)", ARG1 ); + if ((ARG2 & VKI_O_CREAT) != 0 && ARG4 != 0) { + const struct vki_mq_attr *attr = (struct vki_mq_attr *)ARG4; + PRE_MEM_READ( "mq_open(attr->mq_maxmsg)", + (Addr)&attr->mq_maxmsg, sizeof(attr->mq_maxmsg) ); + PRE_MEM_READ( "mq_open(attr->mq_msgsize)", + (Addr)&attr->mq_msgsize, sizeof(attr->mq_msgsize) ); + } +} +POST(sys_mq_open) +{ + vg_assert(SUCCESS); + if (!ML_(fd_allowed)(RES, "mq_open", tid, True)) { + VG_(close)(RES); + SET_STATUS_Failure( VKI_EMFILE ); + } else { + if (VG_(clo_track_fds)) + ML_(record_fd_open_with_given_name)(tid, RES, (Char*)ARG1); + } +} + +PRE(sys_mq_unlink) +{ + PRINT("sys_mq_unlink ( %#lx(%s) )", ARG1,(char *)ARG1); + PRE_REG_READ1(long, "mq_unlink", const char *, name); + PRE_MEM_RASCIIZ( "mq_unlink(name)", ARG1 ); +} + +PRE(sys_mq_timedsend) +{ + *flags |= SfMayBlock; + PRINT("sys_mq_timedsend ( %ld, %#lx, %llu, %ld, %#lx )", + ARG1,ARG2,(ULong)ARG3,ARG4,ARG5); + PRE_REG_READ5(long, "mq_timedsend", + vki_mqd_t, mqdes, const char *, msg_ptr, vki_size_t, msg_len, + unsigned int, msg_prio, const struct timespec *, abs_timeout); + if (!ML_(fd_allowed)(ARG1, "mq_timedsend", tid, False)) { + SET_STATUS_Failure( VKI_EBADF ); + } else { + PRE_MEM_READ( "mq_timedsend(msg_ptr)", ARG2, ARG3 ); + if (ARG5 != 0) + PRE_MEM_READ( "mq_timedsend(abs_timeout)", ARG5, + sizeof(struct vki_timespec) ); + } +} + +PRE(sys_mq_timedreceive) +{ + *flags |= SfMayBlock; + PRINT("sys_mq_timedreceive( %ld, %#lx, %llu, %#lx, %#lx )", + ARG1,ARG2,(ULong)ARG3,ARG4,ARG5); + PRE_REG_READ5(ssize_t, "mq_timedreceive", + vki_mqd_t, mqdes, char *, msg_ptr, vki_size_t, msg_len, + unsigned int *, msg_prio, + const struct timespec *, abs_timeout); + if (!ML_(fd_allowed)(ARG1, "mq_timedreceive", tid, False)) { + SET_STATUS_Failure( VKI_EBADF ); + } else { + PRE_MEM_WRITE( "mq_timedreceive(msg_ptr)", ARG2, ARG3 ); + if (ARG4 != 0) + PRE_MEM_WRITE( "mq_timedreceive(msg_prio)", + ARG4, sizeof(unsigned int) ); + if (ARG5 != 0) + PRE_MEM_READ( "mq_timedreceive(abs_timeout)", + ARG5, sizeof(struct vki_timespec) ); + } +} +POST(sys_mq_timedreceive) +{ + POST_MEM_WRITE( ARG2, ARG3 ); + if (ARG4 != 0) + POST_MEM_WRITE( ARG4, sizeof(unsigned int) ); +} + +PRE(sys_mq_notify) +{ + PRINT("sys_mq_notify( %ld, %#lx )", ARG1,ARG2 ); + PRE_REG_READ2(long, "mq_notify", + vki_mqd_t, mqdes, const struct sigevent *, notification); + if (!ML_(fd_allowed)(ARG1, "mq_notify", tid, False)) + SET_STATUS_Failure( VKI_EBADF ); + else if (ARG2 != 0) + PRE_MEM_READ( "mq_notify(notification)", + ARG2, sizeof(struct vki_sigevent) ); +} + +PRE(sys_mq_getsetattr) +{ + PRINT("sys_mq_getsetattr( %ld, %#lx, %#lx )", ARG1,ARG2,ARG3 ); + PRE_REG_READ3(long, "mq_getsetattr", + vki_mqd_t, mqdes, const struct mq_attr *, mqstat, + struct mq_attr *, omqstat); + if (!ML_(fd_allowed)(ARG1, "mq_getsetattr", tid, False)) { + SET_STATUS_Failure( VKI_EBADF ); + } else { + if (ARG2 != 0) { + const struct vki_mq_attr *attr = (struct vki_mq_attr *)ARG2; + PRE_MEM_READ( "mq_getsetattr(mqstat->mq_flags)", + (Addr)&attr->mq_flags, sizeof(attr->mq_flags) ); + } + if (ARG3 != 0) + PRE_MEM_WRITE( "mq_getsetattr(omqstat)", ARG3, + sizeof(struct vki_mq_attr) ); + } +} +POST(sys_mq_getsetattr) +{ + if (ARG3 != 0) + POST_MEM_WRITE( ARG3, sizeof(struct vki_mq_attr) ); +} + +#endif + +/* --------------------------------------------------------------------- + clock_* wrappers + ------------------------------------------------------------------ */ + +PRE(sys_clock_settime) +{ + PRINT("sys_clock_settime( %ld, %#lx )", ARG1,ARG2); + PRE_REG_READ2(long, "clock_settime", + vki_clockid_t, clk_id, const struct timespec *, tp); + PRE_MEM_READ( "clock_settime(tp)", ARG2, sizeof(struct vki_timespec) ); +} + +PRE(sys_clock_gettime) +{ + PRINT("sys_clock_gettime( %ld, %#lx )" , ARG1,ARG2); + PRE_REG_READ2(long, "clock_gettime", + vki_clockid_t, clk_id, struct timespec *, tp); + PRE_MEM_WRITE( "clock_gettime(tp)", ARG2, sizeof(struct vki_timespec) ); +} +POST(sys_clock_gettime) +{ + POST_MEM_WRITE( ARG2, sizeof(struct vki_timespec) ); +} + +PRE(sys_clock_getres) +{ + PRINT("sys_clock_getres( %ld, %#lx )" , ARG1,ARG2); + // Nb: we can't use "RES" as the param name because that's a macro + // defined above! + PRE_REG_READ2(long, "clock_getres", + vki_clockid_t, clk_id, struct timespec *, res); + if (ARG2 != 0) + PRE_MEM_WRITE( "clock_getres(res)", ARG2, sizeof(struct vki_timespec) ); +} +POST(sys_clock_getres) +{ + if (ARG2 != 0) + POST_MEM_WRITE( ARG2, sizeof(struct vki_timespec) ); +} + +#if 0 +PRE(sys_clock_nanosleep) +{ + *flags |= SfMayBlock|SfPostOnFail; + PRINT("sys_clock_nanosleep( %ld, %ld, %#lx, %#lx )", ARG1,ARG2,ARG3,ARG4); + PRE_REG_READ4(int32_t, "clock_nanosleep", + vki_clockid_t, clkid, int, flags, + const struct timespec *, rqtp, struct timespec *, rmtp); + PRE_MEM_READ( "clock_nanosleep(rqtp)", ARG3, sizeof(struct vki_timespec) ); + if (ARG4 != 0) + PRE_MEM_WRITE( "clock_nanosleep(rmtp)", ARG4, sizeof(struct vki_timespec) ); +} +POST(sys_clock_nanosleep) +{ + if (ARG4 != 0 && FAILURE && RES_unchecked == VKI_EINTR) + POST_MEM_WRITE( ARG4, sizeof(struct vki_timespec) ); +} + +/* --------------------------------------------------------------------- + timer_* wrappers + ------------------------------------------------------------------ */ + +PRE(sys_timer_create) +{ + PRINT("sys_timer_create( %ld, %#lx, %#lx )", ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "timer_create", + vki_clockid_t, clockid, struct sigevent *, evp, + vki_timer_t *, timerid); + if (ARG2 != 0) + PRE_MEM_READ( "timer_create(evp)", ARG2, sizeof(struct vki_sigevent) ); + PRE_MEM_WRITE( "timer_create(timerid)", ARG3, sizeof(vki_timer_t) ); +} +POST(sys_timer_create) +{ + POST_MEM_WRITE( ARG3, sizeof(vki_timer_t) ); +} + +PRE(sys_timer_settime) +{ + PRINT("sys_timer_settime( %lld, %ld, %#lx, %#lx )", (ULong)ARG1,ARG2,ARG3,ARG4); + PRE_REG_READ4(long, "timer_settime", + vki_timer_t, timerid, int, flags, + const struct itimerspec *, value, + struct itimerspec *, ovalue); + PRE_MEM_READ( "timer_settime(value)", ARG3, + sizeof(struct vki_itimerspec) ); + if (ARG4 != 0) + PRE_MEM_WRITE( "timer_settime(ovalue)", ARG4, + sizeof(struct vki_itimerspec) ); +} +POST(sys_timer_settime) +{ + if (ARG4 != 0) + POST_MEM_WRITE( ARG4, sizeof(struct vki_itimerspec) ); +} + +PRE(sys_timer_gettime) +{ + PRINT("sys_timer_gettime( %lld, %#lx )", (ULong)ARG1,ARG2); + PRE_REG_READ2(long, "timer_gettime", + vki_timer_t, timerid, struct itimerspec *, value); + PRE_MEM_WRITE( "timer_gettime(value)", ARG2, + sizeof(struct vki_itimerspec)); +} +POST(sys_timer_gettime) +{ + POST_MEM_WRITE( ARG2, sizeof(struct vki_itimerspec) ); +} + +PRE(sys_timer_getoverrun) +{ + PRINT("sys_timer_getoverrun( %#lx )", ARG1); + PRE_REG_READ1(long, "timer_getoverrun", vki_timer_t, timerid); +} + +PRE(sys_timer_delete) +{ + PRINT("sys_timer_delete( %#lx )", ARG1); + PRE_REG_READ1(long, "timer_delete", vki_timer_t, timerid); +} + +/* --------------------------------------------------------------------- + sched_* wrappers + ------------------------------------------------------------------ */ + +PRE(sys_sched_setparam) +{ + PRINT("sched_setparam ( %ld, %#lx )", ARG1, ARG2 ); + PRE_REG_READ2(long, "sched_setparam", + vki_pid_t, pid, struct sched_param *, p); + PRE_MEM_READ( "sched_setparam(p)", ARG2, sizeof(struct vki_sched_param) ); +} +POST(sys_sched_setparam) +{ + POST_MEM_WRITE( ARG2, sizeof(struct vki_sched_param) ); +} + +PRE(sys_sched_getparam) +{ + PRINT("sched_getparam ( %ld, %#lx )", ARG1, ARG2 ); + PRE_REG_READ2(long, "sched_getparam", + vki_pid_t, pid, struct sched_param *, p); + PRE_MEM_WRITE( "sched_getparam(p)", ARG2, sizeof(struct vki_sched_param) ); +} +POST(sys_sched_getparam) +{ + POST_MEM_WRITE( ARG2, sizeof(struct vki_sched_param) ); +} + +PRE(sys_sched_getscheduler) +{ + PRINT("sys_sched_getscheduler ( %ld )", ARG1); + PRE_REG_READ1(long, "sched_getscheduler", vki_pid_t, pid); +} + +PRE(sys_sched_setscheduler) +{ + PRINT("sys_sched_setscheduler ( %ld, %ld, %#lx )", ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "sched_setscheduler", + vki_pid_t, pid, int, policy, struct sched_param *, p); + if (ARG3 != 0) + PRE_MEM_READ( "sched_setscheduler(p)", + ARG3, sizeof(struct vki_sched_param)); +} + +PRE(sys_sched_yield) +{ + *flags |= SfMayBlock; + PRINT("sched_yield()"); + PRE_REG_READ0(long, "sched_yield"); +} +#endif + +PRE(sys_sched_get_priority_max) +{ + PRINT("sched_get_priority_max ( %ld )", ARG1); + PRE_REG_READ1(long, "sched_get_priority_max", int, policy); +} + +PRE(sys_sched_get_priority_min) +{ + PRINT("sched_get_priority_min ( %ld )", ARG1); + PRE_REG_READ1(long, "sched_get_priority_min", int, policy); +} + +#if 0 +PRE(sys_sched_setaffinity) +{ + PRINT("sched_setaffinity ( %ld, %ld, %#lx )", ARG1, ARG2, ARG3); + PRE_REG_READ3(long, "sched_setaffinity", + vki_pid_t, pid, unsigned int, len, unsigned long *, mask); + PRE_MEM_READ( "sched_setaffinity(mask)", ARG3, ARG2); +} + +PRE(sys_sched_getaffinity) +{ + PRINT("sched_getaffinity ( %ld, %ld, %#lx )", ARG1, ARG2, ARG3); + PRE_REG_READ3(long, "sched_getaffinity", + vki_pid_t, pid, unsigned int, len, unsigned long *, mask); + PRE_MEM_WRITE( "sched_getaffinity(mask)", ARG3, ARG2); +} +POST(sys_sched_getaffinity) +{ + POST_MEM_WRITE(ARG3, ARG2); +} + +#endif + +/* --------------------------------------------------------------------- + miscellaneous wrappers + ------------------------------------------------------------------ */ + +PRE(sys_munlockall) +{ + *flags |= SfMayBlock; + PRINT("sys_munlockall ( )"); + PRE_REG_READ0(long, "munlockall"); +} + +// Pipe on freebsd doesn't have args, and uses dual returns! +PRE(sys_pipe) +{ + PRINT("sys_pipe ( %#lx )", ARG1); + PRE_REG_READ1(int, "pipe", int *, filedes); + PRE_MEM_WRITE( "pipe(filedes)", ARG1, 2*sizeof(int) ); +} +POST(sys_pipe) +{ + Int *p = (Int *)ARG1; + if (!ML_(fd_allowed)(p[0], "pipe", tid, True) || + !ML_(fd_allowed)(p[1], "pipe", tid, True)) { + VG_(close)(p[0]); + VG_(close)(p[1]); + SET_STATUS_Failure( VKI_EMFILE ); + } else { + POST_MEM_WRITE( ARG1, 2*sizeof(int) ); + if (VG_(clo_track_fds)) { + ML_(record_fd_open_nameless)(tid, p[0]); + ML_(record_fd_open_nameless)(tid, p[1]); + } + } +} + +/* XXX copied from syswrap-linux.c */ +/* pipe2 (a kernel 2.6.twentysomething invention) is like pipe, except + there's a second arg containing flags to be applied to the new file + descriptors. It hardly seems worth the effort to factor out the + duplicated code, hence: */ +PRE(sys_pipe2) +{ + PRINT("sys_pipe2 ( %#lx, %#lx )", ARG1, ARG2); + PRE_REG_READ2(int, "pipe", int *, filedes, long, flags); + PRE_MEM_WRITE( "pipe2(filedes)", ARG1, 2*sizeof(int) ); +} +POST(sys_pipe2) +{ + Int *p = (Int *)ARG1; + if (!ML_(fd_allowed)(p[0], "pipe2", tid, True) || + !ML_(fd_allowed)(p[1], "pipe2", tid, True)) { + VG_(close)(p[0]); + VG_(close)(p[1]); + SET_STATUS_Failure( VKI_EMFILE ); + } else { + POST_MEM_WRITE( ARG1, 2*sizeof(int) ); + if (VG_(clo_track_fds)) { + ML_(record_fd_open_nameless)(tid, p[0]); + ML_(record_fd_open_nameless)(tid, p[1]); + } + } +} + +/* XXX copied from syswrap-linux.c */ +PRE(sys_dup3) +{ + PRINT("sys_dup3 ( %ld, %ld, %ld )", ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "dup3", unsigned int, oldfd, unsigned int, newfd, int, flags); + if (!ML_(fd_allowed)(ARG2, "dup3", tid, True)) + SET_STATUS_Failure( VKI_EBADF ); +} + +POST(sys_dup3) +{ + vg_assert(SUCCESS); + if (VG_(clo_track_fds)) + ML_(record_fd_open_named)(tid, RES); +} +#if 0 +PRE(sys_quotactl) +{ + PRINT("sys_quotactl (0x%lx, %#lx, 0x%lx, 0x%lx )", ARG1,ARG2,ARG3, ARG4); + PRE_REG_READ4(long, "quotactl", + unsigned int, cmd, const char *, special, vki_qid_t, id, + void *, addr); + PRE_MEM_RASCIIZ( "quotactl(special)", ARG2 ); +} + +PRE(sys_waitid) +{ + *flags |= SfMayBlock; + PRINT("sys_waitid( %ld, %ld, %#lx, %ld, %#lx )", ARG1,ARG2,ARG3,ARG4,ARG5); + PRE_REG_READ5(int32_t, "sys_waitid", + int, which, vki_pid_t, pid, struct vki_siginfo *, infop, + int, options, struct vki_rusage *, ru); + PRE_MEM_WRITE( "waitid(infop)", ARG3, sizeof(struct vki_siginfo) ); + if (ARG5 != 0) + PRE_MEM_WRITE( "waitid(ru)", ARG5, sizeof(struct vki_rusage) ); +} +POST(sys_waitid) +{ + POST_MEM_WRITE( ARG3, sizeof(struct vki_siginfo) ); + if (ARG5 != 0) + POST_MEM_WRITE( ARG5, sizeof(struct vki_rusage) ); +} + +/* --------------------------------------------------------------------- + utime wrapper + ------------------------------------------------------------------ */ + +PRE(sys_utime) +{ + *flags |= SfMayBlock; + PRINT("sys_utime ( %#lx, %#lx )", ARG1,ARG2); + PRE_REG_READ2(long, "utime", char *, filename, struct utimbuf *, buf); + PRE_MEM_RASCIIZ( "utime(filename)", ARG1 ); + if (ARG2 != 0) + PRE_MEM_READ( "utime(buf)", ARG2, sizeof(struct vki_utimbuf) ); +} + +#endif + +/* --------------------------------------------------------------------- + thr* wrappers + ------------------------------------------------------------------ */ + +PRE(sys_thr_self) +{ + PRINT( "sys_thr_self ( %#lx )", ARG1 ); + PRE_REG_READ1(long, "thr_self", long *, "id"); + PRE_MEM_WRITE( "thr_self()", ARG1, sizeof(long)); +} +POST(sys_thr_self) +{ + POST_MEM_WRITE( ARG1, sizeof(long)); +} + +PRE(sys_thr_exit) +{ + ThreadState *tst; + + PRINT( "sys_thr_exit ( %#lx )", ARG1 ); + PRE_REG_READ1(long, "thr_exit", long *, "status"); + + if (ARG1) + PRE_MEM_WRITE( "thr_exit(status)", ARG1, sizeof(long) ); + tst = VG_(get_ThreadState)(tid); + tst->exitreason = VgSrc_ExitThread; + tst->os_state.exitcode = ARG1; + SET_STATUS_Success(0); +} + +PRE(sys_thr_set_name) +{ + PRINT( "sys_thr_set_name ( %ld, %#lx )", ARG1, ARG2 ); + PRE_REG_READ2(long, "thr_set_name", long, "id", const char *, "name"); + PRE_MEM_RASCIIZ( "sys_thr_set_name(threadname)", ARG2); +} + +PRE(sys_thr_kill) +{ + PRINT("sys_thr_kill ( %ld, %ld )", ARG1,ARG2); + PRE_REG_READ2(long, "thr_kill", long, id, int, sig); + if (!ML_(client_signal_OK)(ARG2)) { + SET_STATUS_Failure( VKI_EINVAL ); + return; + } + + /* Check to see if this kill gave us a pending signal */ + *flags |= SfPollAfter; + + if (VG_(clo_trace_signals)) + VG_(message)(Vg_DebugMsg, "thr_kill: sending signal %ld to tid %ld\n", + ARG2, ARG1); + + /* If we're sending SIGKILL, check to see if the target is one of + our threads and handle it specially. */ + if (ARG2 == VKI_SIGKILL && ML_(do_sigkill)(ARG1, -1)) { + SET_STATUS_Success(0); + return; + } + + /* Ask to handle this syscall via the slow route, since that's the + only one that sets tst->status to VgTs_WaitSys. If the result + of doing the syscall is an immediate run of + async_signalhandler() in m_signals, then we need the thread to + be properly tidied away. I have the impression the previous + version of this wrapper worked on x86/amd64 only because the + kernel did not immediately deliver the async signal to this + thread (on ppc it did, which broke the assertion re tst->status + at the top of async_signalhandler()). */ + *flags |= SfMayBlock; +} +POST(sys_thr_kill) +{ + if (VG_(clo_trace_signals)) + VG_(message)(Vg_DebugMsg, "thr_kill: sent signal %ld to tid %ld\n", + ARG2, ARG1); +} +PRE(sys_thr_kill2) +{ + PRINT("sys_thr_kill2 ( %ld, %ld, %ld )", ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "tgkill", int, pid, long, tid, int, sig); + if (!ML_(client_signal_OK)(ARG3)) { + SET_STATUS_Failure( VKI_EINVAL ); + return; + } + + /* Check to see if this kill gave us a pending signal */ + *flags |= SfPollAfter; + + if (VG_(clo_trace_signals)) + VG_(message)(Vg_DebugMsg, "thr_kill2: sending signal %ld to pid %ld/%ld\n", + ARG3, ARG1, ARG2); + + /* If we're sending SIGKILL, check to see if the target is one of + our threads and handle it specially. */ + if (ARG3 == VKI_SIGKILL && ML_(do_sigkill)(ARG2, ARG1)) { + SET_STATUS_Success(0); + return; + } + + /* Ask to handle this syscall via the slow route, since that's the + only one that sets tst->status to VgTs_WaitSys. If the result + of doing the syscall is an immediate run of + async_signalhandler() in m_signals, then we need the thread to + be properly tidied away. I have the impression the previous + version of this wrapper worked on x86/amd64 only because the + kernel did not immediately deliver the async signal to this + thread (on ppc it did, which broke the assertion re tst->status + at the top of async_signalhandler()). */ + *flags |= SfMayBlock; +} +POST(sys_thr_kill2) +{ + if (VG_(clo_trace_signals)) + VG_(message)(Vg_DebugMsg, "thr_kill2: sent signal %ld to pid %ld/%ld\n", + ARG3, ARG1, ARG2); +} + +PRE(sys_thr_wake) +{ + PRINT("sys_thr_wake ( %ld )", ARG1); + PRE_REG_READ1(long, "thr_wake", long, id); +} + +/* --------------------------------------------------------------------- + umtx* wrappers + ------------------------------------------------------------------ */ + +PRE(sys__umtx_op) +{ +// ThreadState *tst; + + /* 5 args are always passed through. The last two can vary, but + they're always pointers. They may not be used though. */ + switch(ARG2) { + case VKI_UMTX_OP_LOCK: + PRINT( "sys__umtx_op ( %#lx, LOCK, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5); + PRE_REG_READ5(long, "_umtx_op_lock", + struct umtx *, obj, int, op, unsigned long, id, + void *, zero, struct vki_timespec *, timeout); + PRE_MEM_READ( "_umtx_op_lock(mtx)", ARG1, sizeof(struct vki_umtx) ); + if (ARG5) + PRE_MEM_READ( "_umtx_op_lock(timespec)", ARG5, sizeof(struct vki_timespec) ); + PRE_MEM_WRITE( "_umtx_op_lock(mtx)", ARG1, sizeof(struct vki_umtx) ); + *flags |= SfMayBlock; + break; + case VKI_UMTX_OP_UNLOCK: + PRINT( "sys__umtx_op ( %#lx, UNLOCK, %ld)", ARG1, ARG3); + PRE_REG_READ3(long, "_umtx_op_unlock", + struct umtx *, obj, int, op, unsigned long, id); + PRE_MEM_READ( "_umtx_op_unlock(mtx)", ARG1, sizeof(struct vki_umtx) ); + PRE_MEM_WRITE( "_umtx_op_unlock(mtx)", ARG1, sizeof(struct vki_umtx) ); + break; + case VKI_UMTX_OP_WAIT: + PRINT( "sys__umtx_op ( %#lx, WAIT, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5); + PRE_REG_READ5(long, "_umtx_op_wait", + struct umtx *, obj, int, op, unsigned long, id, + void *, zero, struct vki_timespec *, timeout); + PRE_MEM_READ( "_umtx_op_wait(mtx)", ARG1, sizeof(struct vki_umtx) ); + if (ARG5) + PRE_MEM_READ( "_umtx_op_wait(timespec)", ARG5, sizeof(struct vki_timespec) ); + *flags |= SfMayBlock; + break; + case VKI_UMTX_OP_WAKE: + PRINT( "sys__umtx_op ( %#lx, WAKE, %ld)", ARG1, ARG3); + PRE_REG_READ3(long, "_umtx_op_wake", + struct umtx *, obj, int, op, unsigned long, id); + PRE_MEM_READ( "_umtx_op_wake(mtx)", ARG1, sizeof(struct vki_umtx) ); + break; + case VKI_UMTX_OP_MUTEX_TRYLOCK: + PRINT( "sys__umtx_op ( %#lx, MUTEX_TRYLOCK, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5); + PRE_REG_READ5(long, "_umtx_op_mutex_trylock", + struct umutex *, obj, int, op, unsigned long, noid, + void *, zero, struct vki_timespec *, timeout); + PRE_MEM_READ( "_umtx_op_mutex_trylock(mutex)", ARG1, sizeof(struct vki_umutex) ); + if (ARG5) + PRE_MEM_READ( "_umtx_op_mutex_trylock(timespec)", ARG5, sizeof(struct vki_timespec) ); + PRE_MEM_WRITE( "_umtx_op_mutex_trylock(mutex)", ARG1, sizeof(struct vki_umutex) ); + break; + case VKI_UMTX_OP_MUTEX_LOCK: + PRINT( "sys__umtx_op ( %#lx, MUTEX_LOCK, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5); + PRE_REG_READ5(long, "_umtx_op_mutex_lock", + struct umutex *, obj, int, op, unsigned long, noid, + void *, zero, struct vki_timespec *, timeout); + PRE_MEM_READ( "_umtx_op_mutex_lock(mutex)", ARG1, sizeof(struct vki_umutex) ); + if (ARG5) + PRE_MEM_READ( "_umtx_op_mutex_lock(timespec)", ARG5, sizeof(struct vki_timespec) ); + PRE_MEM_WRITE( "_umtx_op_mutex_lock(mutex)", ARG1, sizeof(struct vki_umutex) ); + *flags |= SfMayBlock; + break; + case VKI_UMTX_OP_MUTEX_UNLOCK: + PRINT( "sys__umtx_op ( %#lx, MUTEX_UNLOCK)", ARG1); + PRE_REG_READ2(long, "_umtx_op_mutex_unlock", + struct umutex *, obj, int, op); + PRE_MEM_READ( "_umtx_op_mutex_unlock(mutex)", ARG1, sizeof(struct vki_umutex) ); + PRE_MEM_WRITE( "_umtx_op_mutex_unlock(mutex)", ARG1, sizeof(struct vki_umutex) ); + break; + case VKI_UMTX_OP_SET_CEILING: + PRINT( "sys__umtx_op ( %#lx, SET_CEILING, %ld, %#lx)", ARG1, ARG3, ARG4); + PRE_REG_READ4(long, "_umtx_op_set_ceiling", + struct umutex *, obj, int, op, unsigned int, ceiling, + unsigned int *, old_ceiling); + PRE_MEM_READ( "_umtx_op_set_ceiling(mutex)", ARG1, sizeof(struct vki_umutex) ); + PRE_MEM_WRITE( "_umtx_op_set_ceiling(mutex)", ARG1, sizeof(struct vki_umutex) ); + if (ARG4) + PRE_MEM_WRITE( "_umtx_op_set_ceiling(old_ceiling)", ARG4, sizeof(vki_uint32_t) ); + break; + case VKI_UMTX_OP_CV_WAIT: + PRINT( "sys__umtx_op ( %#lx, CV_WAIT, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5); + PRE_REG_READ5(long, "_umtx_op_cv_wait", + struct ucond *, obj, int, op, unsigned long, wflags, + struct umutex *, umtx, struct vki_timespec *, timeout); + PRE_MEM_READ( "_umtx_op_cv_wait(cond)", ARG1, sizeof(struct vki_ucond) ); + PRE_MEM_WRITE( "_umtx_op_cv_wait(cond)", ARG1, sizeof(struct vki_ucond) ); + PRE_MEM_READ( "_umtx_op_cv_wait(mutex)", ARG4, sizeof(struct vki_umutex) ); + PRE_MEM_WRITE( "_umtx_op_cv_wait(mutex)", ARG4, sizeof(struct vki_umutex) ); + if (ARG5) + PRE_MEM_READ( "_umtx_op_cv_wait(timespec)", ARG5, sizeof(struct vki_timespec) ); + *flags |= SfMayBlock; + break; + case VKI_UMTX_OP_CV_SIGNAL: + PRINT( "sys__umtx_op ( %#lx, CV_SIGNAL)", ARG1); + PRE_REG_READ2(long, "_umtx_op_cv_signal", + struct ucond *, obj, int, op); + PRE_MEM_READ( "_umtx_op_cv_signal(cond)", ARG1, sizeof(struct vki_ucond) ); + PRE_MEM_WRITE( "_umtx_op_cv_signal(cond)", ARG1, sizeof(struct vki_ucond) ); + break; + case VKI_UMTX_OP_CV_BROADCAST: + PRINT( "sys__umtx_op ( %#lx, CV_BROADCAST, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5); + PRE_REG_READ2(long, "_umtx_op_cv_broadcast", + struct ucond *, obj, int, op); + PRE_MEM_READ( "_umtx_op_cv_broadcast(cond)", ARG1, sizeof(struct vki_ucond) ); + PRE_MEM_WRITE( "_umtx_op_cv_broadcast(cond)", ARG1, sizeof(struct vki_ucond) ); + break; + case VKI_UMTX_OP_WAIT_UINT: + PRINT( "sys__umtx_op ( %#lx, CV_WAIT_UINT, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5); + PRE_REG_READ5(long, "_umtx_op_wait_uint", + int *, obj, int, op, unsigned long, id, + void *, zero, struct vki_timespec *, timeout); + PRE_MEM_READ( "_umtx_op_wait(uint)", ARG1, sizeof(int) ); + if (ARG5) + PRE_MEM_READ( "_umtx_op_wait(timespec)", ARG5, sizeof(struct vki_timespec) ); + *flags |= SfMayBlock; + break; + case VKI_UMTX_OP_RW_RDLOCK: + PRINT( "sys__umtx_op ( %#lx, RW_RDLOCK, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5); + PRE_REG_READ5(long, "_umtx_op_rw_rdlock", + struct urwlock *, obj, int, op, unsigned long, noid, + void *, zero, struct vki_timespec *, timeout); + PRE_MEM_READ( "_umtx_op_rw_rdlock(rw)", ARG1, sizeof(struct vki_urwlock) ); + PRE_MEM_WRITE( "_umtx_op_rw_rdlock(rw)", ARG1, sizeof(struct vki_urwlock) ); + *flags |= SfMayBlock; + break; + case VKI_UMTX_OP_RW_WRLOCK: + PRINT( "sys__umtx_op ( %#lx, RW_WRLOCK, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5); + PRE_REG_READ5(long, "_umtx_op_rw_wrlock", + struct urwlock *, obj, int, op, unsigned long, noid, + void *, zero, struct vki_timespec *, timeout); + PRE_MEM_READ( "_umtx_op_rw_wrlock(rw)", ARG1, sizeof(struct vki_urwlock) ); + PRE_MEM_WRITE( "_umtx_op_rw_wrlock(rw)", ARG1, sizeof(struct vki_urwlock) ); + *flags |= SfMayBlock; + break; + case VKI_UMTX_OP_RW_UNLOCK: + PRINT( "sys__umtx_op ( %#lx, RW_UNLOCK, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5); + PRE_REG_READ2(long, "_umtx_op_rw_unlock", + struct urwlock *, obj, int, op); + PRE_MEM_READ( "_umtx_op_rw_unlock(rw)", ARG1, sizeof(struct vki_urwlock) ); + PRE_MEM_WRITE( "_umtx_op_rw_unlock(rw)", ARG1, sizeof(struct vki_urwlock) ); + break; + case VKI_UMTX_OP_WAIT_UINT_PRIVATE: + PRINT( "sys__umtx_op ( %#lx, CV_WAIT_UINT_PRIVATE, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5); + PRE_REG_READ5(long, "_umtx_op_wait_uint_private", + int *, obj, int, op, unsigned long, id, + void *, zero, struct vki_timespec *, timeout); + PRE_MEM_READ( "_umtx_op_wait_private(uint)", ARG1, sizeof(int) ); + if (ARG5) + PRE_MEM_READ( "_umtx_op_wait_private(umtx_time)", ARG5, sizeof(struct vki_umtx_time) ); + *flags |= SfMayBlock; + break; + case VKI_UMTX_OP_WAKE_PRIVATE: + PRINT( "sys__umtx_op ( %#lx, CV_WAKE_PRIVATE, %ld)", ARG1, ARG3); + PRE_REG_READ3(long, "_umtx_op_wake_private", + struct umtx *, obj, int, op, unsigned long, id); + PRE_MEM_READ( "_umtx_op_wake_private(mtx)", ARG1, sizeof(struct vki_umtx) ); + break; + case VKI_UMTX_OP_MUTEX_WAIT: + PRINT( "sys__umtx_op ( %#lx, MUTEX_WAIT, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5); + PRE_REG_READ2(long, "_umtx_op_mutex_wait", + struct umutex *, obj, int, op); + PRE_MEM_READ( "_umtx_op_mutex_wait(mutex)", ARG1, sizeof(struct vki_umutex) ); + PRE_MEM_WRITE( "_umtx_op_mutex_wait(mutex)", ARG1, sizeof(struct vki_umutex) ); + *flags |= SfMayBlock; + break; + case VKI_UMTX_OP_MUTEX_WAKE: + PRINT( "sys__umtx_op ( %#lx, MUTEX_WAKE, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5); + PRE_REG_READ2(long, "_umtx_op_mutex_wake", + struct umutex *, obj, int, op); + PRE_MEM_READ( "_umtx_op_mutex_wake(mutex)", ARG1, sizeof(struct vki_umutex) ); + PRE_MEM_WRITE( "_umtx_op_mutex_wake(mutex)", ARG1, sizeof(struct vki_umutex) ); + break; + case VKI_UMTX_OP_SEM_WAIT: + PRINT( "sys__umtx_op ( %#lx, SEM_WAIT, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5); + PRE_REG_READ5(long, "_umtx_op_sem_wait", + struct usem *, obj, int, op, unsigned long, id, + void *, zero, struct vki_timespec *, timeout); + PRE_MEM_READ( "_umtx_op_sem_wait(usem)", ARG1, sizeof(struct vki_usem) ); + PRE_MEM_WRITE( "_umtx_op_sem_wait(usem)", ARG1, sizeof(struct vki_usem) ); + if (ARG5) + PRE_MEM_READ( "_umtx_op_sem_wait(umtx_time)", ARG5, sizeof(struct vki_umtx_time) ); + *flags |= SfMayBlock; + break; + case VKI_UMTX_OP_SEM_WAKE: + PRINT( "sys__umtx_op ( %#lx, SEM_WAKE, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5); + PRE_REG_READ2(long, "_umtx_op_sem_wake", + struct umutex *, obj, int, op); + PRE_MEM_READ( "_umtx_op_sem_wake(mutex)", ARG1, sizeof(struct vki_usem) ); + PRE_MEM_WRITE( "_umtx_op_sem_wake(mutex)", ARG1, sizeof(struct vki_usem) ); + break; + case VKI_UMTX_OP_NWAKE_PRIVATE: + PRINT( "sys__umtx_op ( %#lx, NWAKE_PRIVATE, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5); + PRE_REG_READ3(long, "_umtx_op_nwake_private", + struct umutex *, obj, int, op, int, count); + PRE_MEM_READ( "_umtx_op_nwake_private(mtxs)", ARG1, ARG3 * sizeof(void *) ); + PRE_MEM_WRITE( "_umtx_op_mutex_wake(mtxs)", ARG1, sizeof(struct vki_umutex) ); + break; + case VKI_UMTX_OP_MUTEX_WAKE2: + PRINT( "sys__umtx_op ( %#lx, MUTEX_WAKE2, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5); + PRE_REG_READ3(long, "_umtx_op_mutex_wake2", + struct umutex *, obj, int, op, unsigned long, flags); + PRE_MEM_READ( "_umtx_op_mutex_wake(mutex)", ARG1, sizeof(struct vki_umutex) ); + PRE_MEM_WRITE( "_umtx_op_mutex_wake(mutex)", ARG1, sizeof(struct vki_umutex) ); + break; + default: + PRINT( "sys__umtx_op ( %#lx, %ld(UNKNOWN), %ld, %#lx, %#lx )", ARG1, ARG2, ARG3, ARG4, ARG5); + break; + } +// tst = VG_(get_ThreadState)(tid); +//PRINT(" [[ UMTX_OP %d: me=%d arg1 %#lx = %#lx (%ld) ]]", ARG2, tst->os_state.lwpid, ARG1, *(UWord *)ARG1, *(UWord *)ARG1 & 0x7fffffff); +} + +POST(sys__umtx_op) +{ +//PRINT("[[ POST_UMTX_OP %d: arg1 %#lx = %#lx (%ld) ]]\n", ARG2, ARG1, *(UWord *)ARG1, *(UWord *)ARG1 & 0x7fffffff); + switch(ARG2) { + case VKI_UMTX_OP_LOCK: + if (SUCCESS) + POST_MEM_WRITE( ARG1, sizeof(struct vki_umtx) ); + break; + case VKI_UMTX_OP_UNLOCK: + if (SUCCESS) + POST_MEM_WRITE( ARG1, sizeof(struct vki_umtx) ); + break; + case VKI_UMTX_OP_WAIT: + case VKI_UMTX_OP_WAKE: + case VKI_UMTX_OP_WAIT_UINT: + case VKI_UMTX_OP_WAIT_UINT_PRIVATE: + case VKI_UMTX_OP_WAKE_PRIVATE: + break; + case VKI_UMTX_OP_MUTEX_TRYLOCK: + case VKI_UMTX_OP_MUTEX_LOCK: + case VKI_UMTX_OP_MUTEX_UNLOCK: + case VKI_UMTX_OP_MUTEX_WAIT: /* Sets/clears contested bits */ + case VKI_UMTX_OP_MUTEX_WAKE: /* Sets/clears contested bits */ + if (SUCCESS) + POST_MEM_WRITE( ARG1, sizeof(struct vki_umutex) ); + break; + case VKI_UMTX_OP_SET_CEILING: + if (SUCCESS) { + POST_MEM_WRITE( ARG1, sizeof(struct vki_umutex) ); + if (ARG4) + POST_MEM_WRITE( ARG4, sizeof(vki_uint32_t) ); + } + break; + case VKI_UMTX_OP_CV_WAIT: + if (SUCCESS) { + POST_MEM_WRITE( ARG1, sizeof(struct vki_ucond) ); + POST_MEM_WRITE( ARG4, sizeof(struct vki_umutex) ); + } + break; + case VKI_UMTX_OP_CV_SIGNAL: + if (SUCCESS) { + POST_MEM_WRITE( ARG1, sizeof(struct vki_ucond) ); + } + break; + case VKI_UMTX_OP_CV_BROADCAST: + if (SUCCESS) { + POST_MEM_WRITE( ARG1, sizeof(struct vki_ucond) ); + } + break; + case VKI_UMTX_OP_RW_RDLOCK: + case VKI_UMTX_OP_RW_WRLOCK: + case VKI_UMTX_OP_RW_UNLOCK: + if (SUCCESS) { + POST_MEM_WRITE( ARG1, sizeof(struct vki_urwlock) ); + } + break; + default: + break; + } +} + +PRE(sys__umtx_lock) +{ + PRINT( "sys__umtx_lock ( %#lx )", ARG1); + PRE_REG_READ1(long, "_umtx_lock", struct vki_umtx *, umtx); + PRE_MEM_READ( "_umtx_lock(mtx)", ARG1, sizeof(struct vki_umtx) ); + PRE_MEM_WRITE( "_umtx_lock(mtx)", ARG1, sizeof(struct vki_umtx) ); +} + +POST(sys__umtx_lock) +{ + if (SUCCESS) + POST_MEM_WRITE(ARG1, sizeof(struct vki_umtx)); +} + +PRE(sys__umtx_unlock) +{ + PRINT( "sys__umtx_unlock ( %#lx )", ARG1); + PRE_REG_READ1(long, "_umtx_unlock", struct vki_umtx *, umtx); + PRE_MEM_READ( "_umtx_unlock(mtx)", ARG1, sizeof(struct vki_umtx) ); + PRE_MEM_WRITE( "_umtx_unlock(mtx)", ARG1, sizeof(struct vki_umtx) ); +} + +POST(sys__umtx_unlock) +{ + if (SUCCESS) + POST_MEM_WRITE(ARG1, sizeof(struct vki_umtx)); +} + +PRE(sys_rtprio_thread) +{ + PRINT( "sys_rtprio_thread ( %ld, %ld, %#lx )", ARG1, ARG2, ARG3 ); + PRE_REG_READ3(long, "rtprio_thread", + int, "function", __vki_lwpid_t, "lwpid", struct vki_rtprio *, "rtp"); + if (ARG1 == VKI_RTP_SET) { + PRE_MEM_READ( "rtprio_thread(set)", ARG3, sizeof(struct vki_rtprio)); + } else if (ARG1 == VKI_RTP_LOOKUP) { + PRE_MEM_WRITE( "rtprio_thread(lookup)", ARG3, sizeof(struct vki_rtprio)); + } else { + /* PHK ?? */ + } +} +POST(sys_rtprio_thread) +{ + if (ARG1 == VKI_RTP_LOOKUP && RES == 0) + POST_MEM_WRITE( ARG3, sizeof(struct vki_rtprio)); +} + +/* --------------------------------------------------------------------- + sig* wrappers + ------------------------------------------------------------------ */ + +PRE(sys_sigpending) +{ + vki_sigset_t tmp; + + PRINT( "sys_sigpending ( )" ); + + (void)VG_(sigpending)( &tmp ); + SET_STATUS_Success(tmp); +} + +/* --------------------------------------------------------------------- + rt_sig* wrappers + ------------------------------------------------------------------ */ + +static int sigformat[_VKI_NSIG]; + +PRE(sys_sigaction4) +{ + PRINT("sys_sigaction ( %ld, %#lx, %#lx )", ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "sigaction", + int, signum, const struct sigaction *, act, + struct sigaction *, oldact); + + if (ARG2 != 0) { + struct vki_sigaction *sa = (struct vki_sigaction *)ARG2; + PRE_MEM_READ( "sigaction(act->sa_handler)", (Addr)&sa->ksa_handler, sizeof(sa->ksa_handler)); + PRE_MEM_READ( "sigaction(act->sa_mask)", (Addr)&sa->sa_mask, sizeof(sa->sa_mask)); + PRE_MEM_READ( "sigaction(act->sa_flags)", (Addr)&sa->sa_flags, sizeof(sa->sa_flags)); + if (ARG1 < _VKI_NSIG) + sigformat[ARG1] = 4; + } + if (ARG3 != 0) + PRE_MEM_WRITE( "sigaction(oldact)", ARG3, sizeof(struct vki_sigaction)); + + /* process the signal immediately. */ + SET_STATUS_from_SysRes( + VG_(do_sys_sigaction)(ARG1, (const vki_sigaction_toK_t *)ARG2, + (vki_sigaction_fromK_t *)ARG3) + ); +} +POST(sys_sigaction4) +{ + vg_assert(SUCCESS); + if (RES == 0 && ARG3 != 0) + POST_MEM_WRITE( ARG3, sizeof(struct vki_sigaction)); +} + +/* Identical, but warns the signal handler to expect the different sigframe */ +PRE(sys_sigaction) +{ + PRINT("sys_sigaction6 ( %ld, %#lx, %#lx )", ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "sigaction6", + int, signum, const struct sigaction *, act, + struct sigaction *, oldact); + + if (ARG2 != 0) { + struct vki_sigaction *sa = (struct vki_sigaction *)ARG2; + PRE_MEM_READ( "sigaction6(act->sa_handler)", (Addr)&sa->ksa_handler, sizeof(sa->ksa_handler)); + PRE_MEM_READ( "sigaction6(act->sa_mask)", (Addr)&sa->sa_mask, sizeof(sa->sa_mask)); + PRE_MEM_READ( "sigaction6(act->sa_flags)", (Addr)&sa->sa_flags, sizeof(sa->sa_flags)); + if (ARG1 < _VKI_NSIG) + sigformat[ARG1] = 6; + } + if (ARG3 != 0) + PRE_MEM_WRITE( "sigaction6(oldact)", ARG3, sizeof(struct vki_sigaction)); + + SET_STATUS_from_SysRes( + VG_(do_sys_sigaction)(ARG1, (const vki_sigaction_toK_t *)ARG2, + (vki_sigaction_fromK_t *)ARG3) + ); +} +POST(sys_sigaction) +{ + vg_assert(SUCCESS); + if (RES == 0 && ARG3 != 0) + POST_MEM_WRITE( ARG3, sizeof(struct vki_sigaction)); +} + + +PRE(sys_sigprocmask) +{ + PRINT("sys_sigprocmask ( %ld, %#lx )",ARG1,ARG2); + PRE_REG_READ2(long, "sigprocmask", + int, how, vki_sigset_t, set); + + vki_sigset_t set, oldset; + set = (vki_sigset_t)ARG2; + oldset = 0; + (void) VG_(do_sys_sigprocmask) ( tid, ARG1 /*how*/, + (vki_sigset_t*) &set, + (vki_sigset_t*) &oldset ); + + /* Fill SysRes with oldset. */ + SET_STATUS_Success(oldset); + + if (SUCCESS) + *flags |= SfPollAfter; +} +#if 0 +POST(sys_sigprocmask) +{ + vg_assert(SUCCESS); +} +#endif + +/* Not in 4.x */ +PRE(sys_sigtimedwait) +{ + *flags |= SfMayBlock; + PRINT("sys_sigtimedwait ( %#lx, %#lx, %#lx )", + ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "sigtimedwait", + const vki_sigset_t *, set, vki_siginfo_t *, info, + const struct timespec *, timeout); + if (ARG1 != 0) + PRE_MEM_READ( "sigtimedwait(set)", ARG1, sizeof(vki_sigset_t)); + if (ARG2 != 0) + PRE_MEM_WRITE( "sigtimedwait(info)", ARG2, sizeof(vki_siginfo_t) ); + if (ARG3 != 0) + PRE_MEM_READ( "sigtimedwait(timeout)", + ARG3, sizeof(struct vki_timespec) ); +} +POST(sys_sigtimedwait) +{ + if (ARG2 != 0) + POST_MEM_WRITE( ARG2, sizeof(vki_siginfo_t) ); +} + +/* Not in 4.x */ +PRE(sys_sigwaitinfo) +{ + *flags |= SfMayBlock; + PRINT("sys_sigwaitinfo ( %#lx, %#lx )", + ARG1,ARG2); + PRE_REG_READ2(long, "sigwaitinfo", + const vki_sigset_t *, set, vki_siginfo_t *, info); + if (ARG1 != 0) + PRE_MEM_READ( "sigwaitinfo(set)", ARG1, sizeof(vki_sigset_t)); + if (ARG2 != 0) + PRE_MEM_WRITE( "sigwaitinfo(info)", ARG2, sizeof(vki_siginfo_t) ); +} +POST(sys_sigwaitinfo) +{ + if (ARG2 != 0) + POST_MEM_WRITE( ARG2, sizeof(vki_siginfo_t) ); +} + +#if 0 /* not on freebsd 4.x */ +PRE(sys_rt_sigqueueinfo) +{ + PRINT("sys_rt_sigqueueinfo(%ld, %ld, %#lx)", ARG1, ARG2, ARG3); + PRE_REG_READ3(long, "rt_sigqueueinfo", + int, pid, int, sig, vki_siginfo_t *, uinfo); + if (ARG2 != 0) + PRE_MEM_READ( "rt_sigqueueinfo(uinfo)", ARG3, sizeof(vki_siginfo_t) ); +} +POST(sys_rt_sigqueueinfo) +{ + if (!ML_(client_signal_OK)(ARG2)) + SET_STATUS_Failure( VKI_EINVAL ); +} +#endif + +PRE(sys_sigsuspend) +{ + *flags |= SfMayBlock; + PRINT("sys_sigsuspend ( %#lx )", ARG1 ); + PRE_REG_READ1(int, "rt_sigsuspend", vki_sigset_t *, mask) + if (ARG1 != (Addr)NULL) { + PRE_MEM_READ( "rt_sigsuspend(mask)", ARG1, sizeof(vki_sigset_t) ); + } +} + +#if 0 +/* --------------------------------------------------------------------- + linux msg* wrapper helpers + ------------------------------------------------------------------ */ + +void +ML_(linux_PRE_sys_msgsnd) ( ThreadId tid, + UWord arg0, UWord arg1, UWord arg2, UWord arg3 ) +{ + /* int msgsnd(int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg); */ + struct vki_msgbuf *msgp = (struct vki_msgbuf *)arg1; + PRE_MEM_READ( "msgsnd(msgp->mtype)", (Addr)&msgp->mtype, sizeof(msgp->mtype) ); + PRE_MEM_READ( "msgsnd(msgp->mtext)", (Addr)&msgp->mtext, arg2 ); +} + +void +ML_(linux_PRE_sys_msgrcv) ( ThreadId tid, + UWord arg0, UWord arg1, UWord arg2, + UWord arg3, UWord arg4 ) +{ + /* ssize_t msgrcv(int msqid, struct msgbuf *msgp, size_t msgsz, + long msgtyp, int msgflg); */ + struct vki_msgbuf *msgp = (struct vki_msgbuf *)arg1; + PRE_MEM_WRITE( "msgrcv(msgp->mtype)", (Addr)&msgp->mtype, sizeof(msgp->mtype) ); + PRE_MEM_WRITE( "msgrcv(msgp->mtext)", (Addr)&msgp->mtext, arg2 ); +} +void +ML_(linux_POST_sys_msgrcv) ( ThreadId tid, + UWord res, + UWord arg0, UWord arg1, UWord arg2, + UWord arg3, UWord arg4 ) +{ + struct vki_msgbuf *msgp = (struct vki_msgbuf *)arg1; + POST_MEM_WRITE( (Addr)&msgp->mtype, sizeof(msgp->mtype) ); + POST_MEM_WRITE( (Addr)&msgp->mtext, res ); +} + +void +ML_(linux_PRE_sys_msgctl) ( ThreadId tid, + UWord arg0, UWord arg1, UWord arg2 ) +{ + /* int msgctl(int msqid, int cmd, struct msqid_ds *buf); */ + switch (arg1 /* cmd */) { + case VKI_IPC_INFO: + case VKI_MSG_INFO: + case VKI_IPC_INFO|VKI_IPC_64: + case VKI_MSG_INFO|VKI_IPC_64: + PRE_MEM_WRITE( "msgctl(IPC_INFO, buf)", + arg2, sizeof(struct vki_msginfo) ); + break; + case VKI_IPC_STAT: + case VKI_MSG_STAT: + PRE_MEM_WRITE( "msgctl(IPC_STAT, buf)", + arg2, sizeof(struct vki_msqid_ds) ); + break; + case VKI_IPC_STAT|VKI_IPC_64: + case VKI_MSG_STAT|VKI_IPC_64: + PRE_MEM_WRITE( "msgctl(IPC_STAT, arg.buf)", + arg2, sizeof(struct vki_msqid64_ds) ); + break; + case VKI_IPC_SET: + PRE_MEM_READ( "msgctl(IPC_SET, arg.buf)", + arg2, sizeof(struct vki_msqid_ds) ); + break; + case VKI_IPC_SET|VKI_IPC_64: + PRE_MEM_READ( "msgctl(IPC_SET, arg.buf)", + arg2, sizeof(struct vki_msqid64_ds) ); + break; + } +} +void +ML_(linux_POST_sys_msgctl) ( ThreadId tid, + UWord res, + UWord arg0, UWord arg1, UWord arg2 ) +{ + switch (arg1 /* cmd */) { + case VKI_IPC_INFO: + case VKI_MSG_INFO: + case VKI_IPC_INFO|VKI_IPC_64: + case VKI_MSG_INFO|VKI_IPC_64: + POST_MEM_WRITE( arg2, sizeof(struct vki_msginfo) ); + break; + case VKI_IPC_STAT: + case VKI_MSG_STAT: + POST_MEM_WRITE( arg2, sizeof(struct vki_msqid_ds) ); + break; + case VKI_IPC_STAT|VKI_IPC_64: + case VKI_MSG_STAT|VKI_IPC_64: + POST_MEM_WRITE( arg2, sizeof(struct vki_msqid64_ds) ); + break; + } +} + +#endif + +PRE(sys_chflags) +{ + PRINT("sys_chflags ( %#lx(%s), 0x%lx )", ARG1,(char *)ARG1,ARG2); + PRE_REG_READ2(long, "chown", + const char *, path, vki_int32_t, flags); + PRE_MEM_RASCIIZ( "chflags(path)", ARG1 ); +} + +PRE(sys_chflagsat) +{ +// XXXTBD +} + +PRE(sys_fchflags) +{ + PRINT("sys_fchflags ( %ld, %ld )", ARG1,ARG2); + PRE_REG_READ2(long, "fchflags", unsigned int, fildes, vki_int32_t, flags); +} + +PRE(sys_profil) +{ +// XXXTBD +} + +PRE(sys_ktrace) +{ +// XXXTBD +} + +PRE(sys_acct) +{ +// XXXTBD +} + +PRE(sys_reboot) +{ +// XXXTBD +} + +PRE(sys_getfh) +{ +// XXXTBD +} +POST(sys_getfh) +{ +// XXXTBD +} + +PRE(sys_swapctl) +{ +// XXXTBD +} + +PRE(sys_setrlimit) +{ +// XXXTBD +} + +PRE(sys_getpgid) +{ +// XXXTBD +} + +PRE(sys_msgget) +{ +// XXXTBD +} + +PRE(sys_msgsnd) +{ +// XXXTBD +} + +PRE(sys_msgrcv) +{ +// XXXTBD +} + +PRE(sys_nanosleep) +{ +// XXXTBD +} + +PRE(sys_minherit) +{ +// XXXTBD +} + +PRE(sys_lchown) +{ +// XXXTBD +} + +PRE(sys_getsid) +{ +// XXXTBD +} + +PRE(sys_msync) +{ +// XXXTBD +} + +PRE(sys_preadv) +{ +// XXXTBD +} +POST(sys_preadv) +{ +// XXXTBD +} + +PRE(sys_pwritev) +{ +// XXXTBD +} + +PRE(sys_mquery) +{ +// XXXTBD +} + +PRE(sys_closefrom) +{ +// XXXTBD +} + +PRE(sys_sigaltstack) +{ +// XXXTBD +} + +PRE(sys_msgctl) +{ +// XXXTBD +} + +PRE(sys_getthrid) +{ +// XXXTBD +} + +PRE(sys___thrsleep) +{ +// XXXTBD +} + +PRE(sys___thrwakeup) +{ +// XXXTBD +} + +PRE(sys___threxit) +{ +// XXXTBD +} + +PRE(sys___thrsigdivert) +{ +// XXXTBD +} + +PRE(sys_thrkill) +{ +// XXXTBD +} + +PRE(sys_adjfreq) +{ +// XXXTBD +} + +PRE(sys_setrtable) +{ +// XXXTBD +} + +PRE(sys_getrtable) +{ +// XXXTBD +} + +PRE(sys_sendsyslog) +{ +// XXXTBD +} + +PRE(sys_utimensat) +{ +// XXXTBD +} + +PRE(sys_futimens) +{ +// XXXTBD +} + +PRE(sys_kbind) +{ +// XXXTBD +} + +PRE(sys___set_tcb) +{ +// XXXTBD +} + +PRE(sys___get_tcb) +{ +// XXXTBD +} + + +#if 0 +PRE(sys_modfind) +{ + PRINT("sys_modfind ( %#lx )",ARG1); + PRE_REG_READ1(long, "modfind", char *, modname); + PRE_MEM_RASCIIZ( "modfind(modname)", ARG1 ); +} + +PRE(sys_modstat) +{ + PRINT("sys_modstat ( %ld, %#lx )",ARG1,ARG2); + PRE_REG_READ2(long, "modstat", int, modid, struct module_stat *, buf); + PRE_MEM_WRITE( "modstat(buf)", ARG2, sizeof(struct vki_module_stat) ); +} + +POST(sys_modstat) +{ + POST_MEM_WRITE( ARG2, sizeof(struct vki_module_stat) ); +} +#endif + +PRE(sys_lkmnosys0) +{ + PRINT("sys_lkmnosys0 ()"); + PRE_REG_READ0(long, "lkmnosys0"); +} + +PRE(sys_lkmnosys1) +{ + PRINT("sys_lkmnosys1 ()"); + PRE_REG_READ0(long, "lkmnosys1"); +} + +PRE(sys_lkmnosys2) +{ + PRINT("sys_lkmnosys2 ()"); + PRE_REG_READ0(long, "lkmnosys2"); +} + +PRE(sys_lkmnosys3) +{ + PRINT("sys_lkmnosys3 ()"); + PRE_REG_READ0(long, "lkmnosys3"); +} + +PRE(sys_lkmnosys4) +{ + PRINT("sys_lkmnosys4 ()"); + PRE_REG_READ0(long, "lkmnosys4"); +} + +PRE(sys_lkmnosys5) +{ + PRINT("sys_lkmnosys5 ()"); + PRE_REG_READ0(long, "lkmnosys5"); +} + +PRE(sys_lkmnosys6) +{ + PRINT("sys_lkmnosys6 ()"); + PRE_REG_READ0(long, "lkmnosys6"); +} + +PRE(sys_lkmnosys7) +{ + PRINT("sys_lkmnosys7 ()"); + PRE_REG_READ0(long, "lkmnosys7"); +} + +PRE(sys_lkmnosys8) +{ + PRINT("sys_lkmnosys8 ()"); + PRE_REG_READ0(long, "lkmnosys8"); +} + +#if 0 +PRE(sys_kenv) +{ + PRINT("sys_kenv ( %ld, %#lx, %#lx, %ld )", ARG1,ARG2,ARG3,ARG4); + PRE_REG_READ4(long, "kenv", + int, action, const char *, name, char *, value, int, len); + switch (ARG1) { + case VKI_KENV_GET: + case VKI_KENV_SET: + case VKI_KENV_UNSET: + PRE_MEM_RASCIIZ("kenv(name)", ARG2); + /* FALLTHROUGH */ + case VKI_KENV_DUMP: + break; + default: + I_die_here; + } +} + +POST(sys_kenv) +{ + if (SUCCESS) { + switch (ARG1) { + case VKI_KENV_GET: + POST_MEM_WRITE(ARG3, ARG4); + break; + case VKI_KENV_DUMP: + if (ARG3 != (Addr)NULL) + POST_MEM_WRITE(ARG3, ARG4); + break; + } + } +} +#endif + +#if 0 +PRE(sys_uuidgen) +{ + PRINT("sys_uuidgen ( %#lx, %ld )", ARG1,ARG2); + PRE_REG_READ2(long, "uuidgen", + struct vki_uuid *, store, int, count); + PRE_MEM_WRITE( "uuidgen(store)", ARG1, ARG2 * sizeof(struct vki_uuid)); +} + +POST(sys_uuidgen) +{ + if (SUCCESS) + POST_MEM_WRITE( ARG1, ARG2 * sizeof(struct vki_uuid) ); +} +#endif + + +PRE(sys_shmget) +{ + PRINT("sys_shmget ( %ld, %ld, %ld )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "shmget", vki_key_t, key, vki_size_t, size, int, shmflg); +} + +PRE(sys_shmat) +{ + UWord arg2tmp; + PRINT("sys_shmat ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "shmat", + int, shmid, const void *, shmaddr, int, shmflg); + arg2tmp = ML_(generic_PRE_sys_shmat)(tid, ARG1,ARG2,ARG3); + if (arg2tmp == 0) + SET_STATUS_Failure( VKI_EINVAL ); + else + ARG2 = arg2tmp; +} + +POST(sys_shmat) +{ + ML_(generic_POST_sys_shmat)(tid, RES,ARG1,ARG2,ARG3); +} + +PRE(sys_shmdt) +{ + PRINT("sys_shmdt ( %#lx )",ARG1); + PRE_REG_READ1(long, "shmdt", const void *, shmaddr); + if (!ML_(generic_PRE_sys_shmdt)(tid, ARG1)) + SET_STATUS_Failure( VKI_EINVAL ); +} + +POST(sys_shmdt) +{ + ML_(generic_POST_sys_shmdt)(tid, RES,ARG1); +} + +PRE(sys_shmctl) +{ + PRINT("sys_shmctl ( %ld, %ld, %#lx )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "shmctl", + int, shmid, int, cmd, struct vki_shmid_ds *, buf); + switch (ARG2 /* cmd */) { + case VKI_IPC_STAT: + PRE_MEM_WRITE( "shmctl(IPC_STAT, buf)", + ARG3, sizeof(struct vki_shmid_ds) ); + break; + case VKI_IPC_SET: + PRE_MEM_READ( "shmctl(IPC_SET, buf)", + ARG3, sizeof(struct vki_shmid_ds) ); + break; + } +} + +#if 0 +PRE(sys_shmctl7) +{ + PRINT("sys_shmctl7 ( %ld, %ld, %#lx )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "shmctl", + int, shmid, int, cmd, struct vki_shmid_ds7 *, buf); + switch (ARG2 /* cmd */) { + case VKI_IPC_STAT: + PRE_MEM_WRITE( "shmctl7(IPC_STAT, buf)", + ARG3, sizeof(struct vki_shmid_ds7) ); + break; + case VKI_IPC_SET: + PRE_MEM_READ( "shmctl7(IPC_SET, buf)", + ARG3, sizeof(struct vki_shmid_ds7) ); + break; + } +} +#endif + +POST(sys_shmctl) +{ + if (ARG2 == VKI_IPC_STAT) { + POST_MEM_WRITE( ARG3, sizeof(struct vki_shmid_ds) ); + } +} + +#if 0 +POST(sys_shmctl7) +{ + if (ARG2 == VKI_IPC_STAT) { + POST_MEM_WRITE( ARG3, sizeof(struct vki_shmid_ds7) ); + } +} +#endif + +PRE(sys_semget) +{ + PRINT("sys_semget ( %ld, %ld, %ld )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "semget", vki_key_t, key, int, nsems, int, semflg); +} + +PRE(sys_shm_open) +{ + PRE_REG_READ3(long, "shm_open", + const char *, "name", int, "flags", vki_mode_t, "mode"); + if (ARG1 == VKI_SHM_ANON) { + PRINT("sys_shm_open(%#lx(SHM_ANON), %ld, %ld)", ARG1, ARG2, ARG3); + } else { + PRINT("sys_shm_open(%#lx(%s), %ld, %ld)", ARG1, (char *)ARG1, ARG2, ARG3); + PRE_MEM_RASCIIZ( "shm_open(filename)", ARG1 ); + } + *flags |= SfMayBlock; +} + +POST(sys_shm_open) +{ + vg_assert(SUCCESS); + if (!ML_(fd_allowed)(RES, "shm_open", tid, True)) { + VG_(close)(RES); + SET_STATUS_Failure( VKI_EMFILE ); + } else { + if (VG_(clo_track_fds)) + ML_(record_fd_open_with_given_name)(tid, RES, (HChar*)ARG1); + } +} + +PRE(sys_shm_unlink) +{ + PRINT("sys_shm_unlink(%#lx(%s))", ARG1, (char *)ARG1); + PRE_REG_READ1(long, "shm_unlink", + const char *, "name"); + + PRE_MEM_RASCIIZ( "shm_unlink(filename)", ARG1 ); + + *flags |= SfMayBlock; +} + +PRE(sys_semop) +{ + *flags |= SfMayBlock; + PRINT("sys_semop ( %ld, %#lx, %lu )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "semop", + int, semid, struct sembuf *, sops, unsigned, nsoops); + ML_(generic_PRE_sys_semop)(tid, ARG1,ARG2,ARG3); +} + +struct ipc_perm7 { + unsigned short cuid; /* creator user id */ + unsigned short cgid; /* creator group id */ + unsigned short uid; /* user id */ + unsigned short gid; /* group id */ + unsigned short mode; /* r/w permission */ + unsigned short seq; /* sequence # (to generate unique ipcid) */ + vki_key_t key; /* user specified msg/sem/shm key */ +}; + +struct semid_ds7 { + struct ipc_perm7 sem_perm; /* operation permission struct */ + struct sem *sem_base; /* pointer to first semaphore in set */ + unsigned short sem_nsems; /* number of sems in set */ + vki_time_t sem_otime; /* last operation time */ + long sem_pad1; /* SVABI/386 says I need this here */ + vki_time_t sem_ctime; /* last change time */ + /* Times measured in secs since */ + /* 00:00:00 GMT, Jan. 1, 1970 */ + long sem_pad2; /* SVABI/386 says I need this here */ + long sem_pad3[4]; /* SVABI/386 says I need this here */ +}; + +#if 0 +PRE(sys___semctl7) +{ + switch (ARG3) { + case VKI_IPC_INFO: + case VKI_SEM_INFO: + PRINT("sys_semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4); + PRE_REG_READ4(long, "semctl", + int, semid, int, semnum, int, cmd, struct seminfo *, arg); + break; + case VKI_IPC_STAT: + case VKI_SEM_STAT: + case VKI_IPC_SET: + PRINT("sys_semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4); + PRE_REG_READ4(long, "semctl", + int, semid, int, semnum, int, cmd, struct semid_ds7 *, arg); + break; + case VKI_GETALL: + case VKI_SETALL: + PRINT("sys_semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4); + PRE_REG_READ4(long, "semctl", + int, semid, int, semnum, int, cmd, unsigned short *, arg); + break; + default: + PRINT("sys_semctl ( %ld, %ld, %ld )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "semctl", + int, semid, int, semnum, int, cmd); + break; + } + ML_(generic_PRE_sys_semctl)(tid, ARG1,ARG2,ARG3,ARG4); +} + +POST(sys___semctl7) +{ + ML_(generic_POST_sys_semctl)(tid, RES,ARG1,ARG2,ARG3,ARG4); +} +#endif + +PRE(sys___semctl) +{ + switch (ARG3) { + case VKI_IPC_INFO: + case VKI_SEM_INFO: + PRINT("sys_semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4); + PRE_REG_READ4(long, "semctl", + int, semid, int, semnum, int, cmd, struct seminfo *, arg); + break; + case VKI_IPC_STAT: + case VKI_SEM_STAT: + case VKI_IPC_SET: + PRINT("sys_semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4); + PRE_REG_READ4(long, "semctl", + int, semid, int, semnum, int, cmd, struct semid_ds *, arg); + break; + case VKI_GETALL: + case VKI_SETALL: + PRINT("sys_semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4); + PRE_REG_READ4(long, "semctl", + int, semid, int, semnum, int, cmd, unsigned short *, arg); + break; + default: + PRINT("sys_semctl ( %ld, %ld, %ld )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "semctl", + int, semid, int, semnum, int, cmd); + break; + } + ML_(generic_PRE_sys_semctl)(tid, ARG1,ARG2,ARG3,ARG4); +} + +POST(sys___semctl) +{ + ML_(generic_POST_sys_semctl)(tid, RES,ARG1,ARG2,ARG3,ARG4); +} + +#if 0 +PRE(sys_eaccess) +{ + PRINT("sys_eaccess ( %#lx(%s), %ld )", ARG1,(char*)ARG1,ARG2); + PRE_REG_READ2(long, "eaccess", const char *, pathname, int, mode); + PRE_MEM_RASCIIZ( "eaccess(pathname)", ARG1 ); +} +#endif + + +/* --------------------------------------------------------------------- + *at wrappers + ------------------------------------------------------------------ */ + +PRE(sys_openat) +{ + HChar name[30]; + SysRes sres; + + if (ARG3 & VKI_O_CREAT) { + // 4-arg version + PRINT("sys_openat ( %ld, %#lx(%s), %ld, %ld )",ARG1,ARG2,(char*)ARG2,ARG3,ARG4); + PRE_REG_READ4(long, "openat", + int, dfd, const char *, filename, int, flags, int, mode); + } else { + // 3-arg version + PRINT("sys_openat ( %ld, %#lx(%s), %ld )",ARG1,ARG2,(char*)ARG2,ARG3); + PRE_REG_READ3(long, "openat", + int, dfd, const char *, filename, int, flags); + } + + if (ARG1 != VKI_AT_FDCWD && !ML_(fd_allowed)(ARG1, "openat", tid, False)) + SET_STATUS_Failure( VKI_EBADF ); + else + PRE_MEM_RASCIIZ( "openat(filename)", ARG2 ); + + /* Handle the case where the open is of /proc/curproc/cmdline or + /proc//cmdline, and just give it a copy of the fd for the + fake file we cooked up at startup (in m_main). Also, seek the + cloned fd back to the start. */ + + VG_(sprintf)(name, "/proc/%d/cmdline", VG_(getpid)()); + if (ML_(safe_to_deref)( (void*)ARG2, 1 ) + && (VG_(strcmp)((HChar *)ARG2, name) == 0 + || VG_(strcmp)((HChar *)ARG2, "/proc/curproc/cmdline") == 0)) { + sres = VG_(dup)( VG_(cl_cmdline_fd) ); + SET_STATUS_from_SysRes( sres ); + if (!sr_isError(sres)) { + OffT off = VG_(lseek)( sr_Res(sres), 0, VKI_SEEK_SET ); + if (off < 0) + SET_STATUS_Failure( VKI_EMFILE ); + } + return; + } + + /* Otherwise handle normally */ + *flags |= SfMayBlock; +} + +POST(sys_openat) +{ + vg_assert(SUCCESS); + if (!ML_(fd_allowed)(RES, "openat", tid, True)) { + VG_(close)(RES); + SET_STATUS_Failure( VKI_EMFILE ); + } else { + if (VG_(clo_track_fds)) + ML_(record_fd_open_with_given_name)(tid, RES, (HChar*)ARG2); + } +} + +PRE(sys_mkdirat) +{ + *flags |= SfMayBlock; + PRINT("sys_mkdirat ( %ld, %#lx(%s), %ld )", ARG1,ARG2,(char*)ARG2,ARG3); + PRE_REG_READ3(long, "mkdirat", + int, dfd, const char *, pathname, int, mode); + PRE_MEM_RASCIIZ( "mkdirat(pathname)", ARG2 ); +} + +PRE(sys_mkfifoat) +{ + PRINT("sys_mkfifoat ( %ld, %#lx(%s), 0x%lx )", ARG1,ARG2,(char*)ARG2,ARG3 ); + PRE_REG_READ3(long, "mkfifoat", + int, dfd, const char *, pathname, int, mode); + PRE_MEM_RASCIIZ( "mkfifoat(pathname)", ARG2 ); +} + +PRE(sys_mknodat) +{ + PRINT("sys_mknodat ( %ld, %#lx(%s), 0x%lx, 0x%lx )", ARG1,ARG2,(char*)ARG2,ARG3,ARG4 ); + PRE_REG_READ4(long, "mknodat", + int, dfd, const char *, pathname, int, mode, unsigned, dev); + PRE_MEM_RASCIIZ( "mknodat(pathname)", ARG2 ); +} + +PRE(sys_fchownat) +{ + PRINT("sys_fchownat ( %ld, %#lx(%s), 0x%lx, 0x%lx )", ARG1,ARG2,(char*)ARG2,ARG3,ARG4); + PRE_REG_READ4(long, "fchownat", + int, dfd, const char *, path, + vki_uid_t, owner, vki_gid_t, group); + PRE_MEM_RASCIIZ( "fchownat(path)", ARG2 ); +} + +#if 0 +PRE(sys_futimesat) +{ + PRINT("sys_futimesat ( %ld, %#lx(%s), %#lx )", ARG1,ARG2,(char*)ARG2,ARG3); + PRE_REG_READ3(long, "futimesat", + int, dfd, char *, filename, struct timeval *, tvp); + if (ARG2 != 0) + PRE_MEM_RASCIIZ( "futimesat(filename)", ARG2 ); + if (ARG3 != 0) + PRE_MEM_READ( "futimesat(tvp)", ARG3, 2 * sizeof(struct vki_timeval) ); +} +#endif + +PRE(sys_fstatat) +{ + PRINT("sys_fstatat ( %ld, %#lx(%s), %#lx )", ARG1,ARG2,(char*)ARG2,ARG3); + PRE_REG_READ3(long, "fstatat", + int, dfd, char *, file_name, struct stat *, buf); + PRE_MEM_RASCIIZ( "fstatat(file_name)", ARG2 ); + PRE_MEM_WRITE( "fstatat(buf)", ARG3, sizeof(struct vki_stat) ); +} + +POST(sys_fstatat) +{ + POST_MEM_WRITE( ARG3, sizeof(struct vki_stat) ); +} + +PRE(sys_unlinkat) +{ + *flags |= SfMayBlock; + PRINT("sys_unlinkat ( %ld, %#lx(%s) )", ARG1,ARG2,(char*)ARG2); + PRE_REG_READ2(long, "unlinkat", int, dfd, const char *, pathname); + PRE_MEM_RASCIIZ( "unlinkat(pathname)", ARG2 ); +} + +PRE(sys_renameat) +{ + PRINT("sys_renameat ( %ld, %#lx(%s), %ld, %#lx(%s) )", ARG1,ARG2,(char*)ARG2,ARG3,ARG4,(char*)ARG4); + PRE_REG_READ4(long, "renameat", + int, olddfd, const char *, oldpath, + int, newdfd, const char *, newpath); + PRE_MEM_RASCIIZ( "renameat(oldpath)", ARG2 ); + PRE_MEM_RASCIIZ( "renameat(newpath)", ARG4 ); +} + +PRE(sys_linkat) +{ + *flags |= SfMayBlock; + PRINT("sys_linkat ( %ld, %#lx(%s), %ld, %#lx(%s), %ld )",ARG1,ARG2,(char*)ARG2,ARG3,ARG4,(char*)ARG4,ARG5); + PRE_REG_READ5(long, "linkat", + int, olddfd, const char *, oldpath, + int, newdfd, const char *, newpath, + int, flags); + PRE_MEM_RASCIIZ( "linkat(oldpath)", ARG2); + PRE_MEM_RASCIIZ( "linkat(newpath)", ARG4); +} + +PRE(sys_symlinkat) +{ + *flags |= SfMayBlock; + PRINT("sys_symlinkat ( %#lx(%s), %ld, %#lx(%s) )",ARG1,(char*)ARG1,ARG2,ARG3,(char*)ARG3); + PRE_REG_READ3(long, "symlinkat", + const char *, oldpath, int, newdfd, const char *, newpath); + PRE_MEM_RASCIIZ( "symlinkat(oldpath)", ARG1 ); + PRE_MEM_RASCIIZ( "symlinkat(newpath)", ARG3 ); +} + +PRE(sys_readlinkat) +{ + HChar name[25]; + Word saved = SYSNO; + + PRINT("sys_readlinkat ( %ld, %#lx(%s), %#lx, %llu )", ARG1,ARG2,(char*)ARG2,ARG3,(ULong)ARG4); + PRE_REG_READ4(long, "readlinkat", + int, dfd, const char *, path, char *, buf, int, bufsiz); + PRE_MEM_RASCIIZ( "readlinkat(path)", ARG2 ); + PRE_MEM_WRITE( "readlinkat(buf)", ARG3,ARG4 ); + + /* + * Handle the case where readlinkat is looking at /proc/curproc/file or + * /proc//file. + */ + VG_(sprintf)(name, "/proc/%d/file", VG_(getpid)()); + if (ML_(safe_to_deref)((void*)ARG2, 1) + && (VG_(strcmp)((HChar *)ARG2, name) == 0 + || VG_(strcmp)((HChar *)ARG2, "/proc/curproc/file") == 0)) { + VG_(sprintf)(name, "/proc/self/fd/%d", VG_(cl_exec_fd)); + SET_STATUS_from_SysRes( VG_(do_syscall4)(saved, ARG1, (UWord)name, + ARG3, ARG4)); + } else { + /* Normal case */ + SET_STATUS_from_SysRes( VG_(do_syscall4)(saved, ARG1, ARG2, ARG3, ARG4)); + } + + if (SUCCESS && RES > 0) + POST_MEM_WRITE( ARG3, RES ); +} + +PRE(sys_fchmodat) +{ + PRINT("sys_fchmodat ( %ld, %#lx(%s), %ld )", ARG1,ARG2,(char*)ARG2,ARG3); + PRE_REG_READ3(long, "fchmodat", + int, dfd, const char *, path, vki_mode_t, mode); + PRE_MEM_RASCIIZ( "fchmodat(path)", ARG2 ); +} + +PRE(sys_faccessat) +{ + PRINT("sys_faccessat ( %ld, %#lx(%s), %ld )", ARG1,ARG2,(char*)ARG2,ARG3); + PRE_REG_READ3(long, "faccessat", + int, dfd, const char *, pathname, int, mode); + PRE_MEM_RASCIIZ( "faccessat(pathname)", ARG2 ); +} + +/* --------------------------------------------------------------------- + __acl* wrappers + ------------------------------------------------------------------ */ + +#if 0 +PRE(sys___acl_get_file) +{ + PRINT("sys___acl_get_file ( %#lx(%s), %ld, %#lx )", ARG1,(char *)ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "__acl_get_file", + const char *, path, int, acltype, struct vki_acl *, aclp); + PRE_MEM_WRITE( "__acl_get_file(aclp)", ARG3, sizeof(struct vki_acl) ); +} + +POST(sys___acl_get_file) +{ + vg_assert(SUCCESS); + if (RES == 0) { + POST_MEM_WRITE( ARG3, sizeof(struct vki_acl) ); + } +} + +PRE(sys___acl_set_file) +{ + PRINT("sys___acl_set_file ( %#lx(%s), %ld, %#lx )", ARG1,(char *)ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "__acl_set_file", + const char *, path, int, acltype, struct vki_acl *, aclp); + PRE_MEM_READ( "__acl_set_file(aclp)", ARG3, sizeof(struct vki_acl) ); +} + +PRE(sys___acl_get_fd) +{ + PRINT("sys___acl_get_fd ( %ld, %ld, %#lx )", ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "__acl_get_fd", + int, fd, int, acltype, struct vki_acl *, aclp); + PRE_MEM_WRITE( "__acl_get_file(aclp)", ARG3, sizeof(struct vki_acl) ); +} + +POST(sys___acl_get_fd) +{ + vg_assert(SUCCESS); + if (RES == 0) { + POST_MEM_WRITE( ARG3, sizeof(struct vki_acl) ); + } +} + +PRE(sys___acl_set_fd) +{ + PRINT("sys___acl_set_fd ( %ld, %ld, %#lx )", ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "__acl_set_fd", + int, fd, int, acltype, struct vki_acl *, aclp); + PRE_MEM_READ( "__acl_get_file(aclp)", ARG3, sizeof(struct vki_acl) ); +} + +PRE(sys___acl_delete_file) +{ + PRINT("sys___acl_delete_file ( %#lx(%s), %ld )", ARG1,(char *)ARG1,ARG2); + PRE_REG_READ2(long, "__acl_delete_file", + const char *, path, int, acltype); +} + +PRE(sys___acl_delete_fd) +{ + PRINT("sys___acl_delete_fd ( %ld, %ld )", ARG1,ARG2); + PRE_REG_READ2(long, "__acl_delete_fd", + int, fd, int, acltype); +} + +PRE(sys___acl_aclcheck_file) +{ + PRINT("sys___acl_aclcheck_file ( %#lx(%s), %ld, %#lx )", ARG1,(char *)ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "__acl_aclcheck_file", + const char *, path, int, acltype, struct vki_acl *, aclp); + PRE_MEM_READ( "__acl_aclcheck_file(aclp)", ARG3, sizeof(struct vki_acl) ); +} + +PRE(sys___acl_aclcheck_fd) +{ + PRINT("sys___acl_aclcheck_fd ( %ld, %ld, %#lx )", ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "__acl_aclcheck_fd", + int, fd, int, acltype, struct vki_acl *, aclp); + PRE_MEM_READ( "__acl_aclcheck_fd(aclp)", ARG3, sizeof(struct vki_acl) ); +} + +PRE(sys___acl_get_link) +{ + PRINT("sys___acl_get_link ( %#lx(%s), %ld, %#lx )", ARG1,(char *)ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "__acl_get_link", + const char *, path, int, acltype, struct vki_acl *, aclp); + PRE_MEM_WRITE( "__acl_get_link(aclp)", ARG3, sizeof(struct vki_acl) ); +} + +POST(sys___acl_get_link) +{ + vg_assert(SUCCESS); + if (RES == 0) { + POST_MEM_WRITE( ARG3, sizeof(struct vki_acl) ); + } +} + +PRE(sys___acl_set_link) +{ + PRINT("sys___acl_set_link ( %#lx(%s), %ld, %#lx )", ARG1,(char *)ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "__acl_set_link", + const char *, path, int, acltype, struct vki_acl *, aclp); + PRE_MEM_READ( "__acl_set_link(aclp)", ARG3, sizeof(struct vki_acl) ); +} + +PRE(sys___acl_delete_link) +{ + PRINT("sys___acl_delete_link ( %#lx(%s), %ld )", ARG1,(char *)ARG1,ARG2); + PRE_REG_READ2(long, "__acl_delete_link", + const char *, path, int, acltype); +} + +PRE(sys___acl_aclcheck_link) +{ + PRINT("sys___acl_aclcheck_link ( %#lx(%s), %ld, %#lx )", ARG1,(char *)ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "__acl_aclcheck_link", + const char *, path, int, acltype, struct vki_acl *, aclp); + PRE_MEM_READ( "__acl_aclcheck_link(aclp)", ARG3, sizeof(struct vki_acl) ); +} +#endif + +POST(sys_getcontext) +{ + POST_MEM_WRITE( ARG1, sizeof(struct vki_ucontext) ); +} + +POST(sys_swapcontext) +{ + if (SUCCESS) + POST_MEM_WRITE( ARG1, sizeof(struct vki_ucontext) ); +} + +PRE(sys_fcntl) +{ + switch (ARG2) { + // These ones ignore ARG3. + case VKI_F_GETFD: + case VKI_F_GETFL: + case VKI_F_GETOWN: + PRINT("sys_fcntl ( %ld, %ld )", ARG1,ARG2); + PRE_REG_READ2(long, "fcntl", unsigned int, fd, unsigned int, cmd); + break; + + // These ones use ARG3 as "arg". + case VKI_F_DUPFD: + case VKI_F_SETFD: + case VKI_F_SETFL: + case VKI_F_SETOWN: + PRINT("sys_fcntl[ARG3=='arg'] ( %ld, %ld, %ld )", ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "fcntl", + unsigned int, fd, unsigned int, cmd, unsigned long, arg); + break; + + // These ones use ARG3 as "lock" - obsolete. + case VKI_F_OSETLKW: + *flags |= SfMayBlock; + /* FALLTHROUGH */ + case VKI_F_OGETLK: + case VKI_F_OSETLK: + PRINT("sys_fcntl[ARG3=='lock'] ( %ld, %ld, %#lx )", ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "fcntl", + unsigned int, fd, unsigned int, cmd, + struct oflock *, lock); + break; + + // This one uses ARG3 as "oldd" and ARG4 as "newd". + case VKI_F_DUP2FD: + PRINT("sys_fcntl[ARG3=='oldd', ARG4=='newd'] ( %ld, %ld, %ld, %ld )", + ARG1,ARG2,ARG3,ARG4); + PRE_REG_READ4(long, "fcntl", + unsigned int, fd, unsigned int, cmd, + unsigned long, oldd, unsigned long, newd); + break; + + // These ones use ARG3 as "lock". + case VKI_F_SETLKW: + *flags |= SfMayBlock; + /* FALLTHROUGH */ + case VKI_F_GETLK: + case VKI_F_SETLK: + case VKI_F_SETLK_REMOTE: + PRINT("sys_fcntl[ARG3=='lock'] ( %ld, %ld, %#lx )", ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "fcntl", + unsigned int, fd, unsigned int, cmd, + struct flock *, lock); + break; + + default: + PRINT("sys_fcntl[UNKNOWN] ( %ld, %ld, %ld )", ARG1,ARG2,ARG3); + I_die_here; + break; + } +} + +POST(sys_fcntl) +{ + vg_assert(SUCCESS); + if (ARG2 == VKI_F_DUPFD) { + if (!ML_(fd_allowed)(RES, "fcntl(DUPFD)", tid, True)) { + VG_(close)(RES); + SET_STATUS_Failure( VKI_EMFILE ); + } else { + if (VG_(clo_track_fds)) + ML_(record_fd_open_named)(tid, RES); + } + } +} + +PRE(sys_ioctl) +{ + UInt dir = _VKI_IOC_DIR(ARG2); + UInt size = _VKI_IOC_SIZE(ARG2); + *flags |= SfMayBlock; + PRINT("sys_ioctl ( %ld, 0x%lx, %#lx )",ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "ioctl", + unsigned int, fd, unsigned int, request, unsigned long, arg); + +/* On FreeBSD, ALL ioctl's are IOR/IOW encoded. Just use the default decoder */ + if (SimHintiS(SimHint_lax_ioctls, VG_(clo_sim_hints))) { + /* + * Be very lax about ioctl handling; the only + * assumption is that the size is correct. Doesn't + * require the full buffer to be initialized when + * writing. Without this, using some device + * drivers with a large number of strange ioctl + * commands becomes very tiresome. + */ + } else if (/* size == 0 || */ dir == _VKI_IOC_NONE) { + static Int moans = 3; + if (moans > 0 && !VG_(clo_xml)) { + moans--; + VG_(message)(Vg_UserMsg, + "Warning: noted but unhandled ioctl 0x%lx" + " with no size/direction hints", + ARG2); + VG_(message)(Vg_UserMsg, + " This could cause spurious value errors" + " to appear."); + VG_(message)(Vg_UserMsg, + " See README_MISSING_SYSCALL_OR_IOCTL for " + "guidance on writing a proper wrapper." ); + } + } else { + if ((dir & _VKI_IOC_WRITE) && size > 0) + PRE_MEM_READ( "ioctl(generic)", ARG3, size); + if ((dir & _VKI_IOC_READ) && size > 0) + PRE_MEM_WRITE( "ioctl(generic)", ARG3, size); + } +} + +POST(sys_ioctl) +{ + UInt dir = _VKI_IOC_DIR(ARG2); + UInt size = _VKI_IOC_SIZE(ARG2); + vg_assert(SUCCESS); + if (size > 0 && (dir & _VKI_IOC_READ) + && RES == 0 && ARG3 != (Addr)NULL) + POST_MEM_WRITE(ARG3, size); +} + +PRE(sys_ptrace) +{ + struct vki_ptrace_io_desc *io_desc; + PRINT("sys_ptrace ( %ld, %ld, 0x%lx, %ld)", ARG1, ARG2, ARG3, ARG4); + + PRE_REG_READ4(int, "ptrace", int, request, int, pid, char *, addr, int, data); + + switch (ARG1) { + case VKI_PTRACE_TRACEME: + break; + case VKI_PTRACE_READ_I: + case VKI_PTRACE_READ_D: + break; + + case VKI_PTRACE_WRITE_I: + case VKI_PTRACE_WRITE_D: + break; + + case VKI_PTRACE_IO: + PRE_MEM_READ("ptrace", ARG3, sizeof(struct vki_ptrace_io_desc)); + io_desc = (struct vki_ptrace_io_desc *)ARG3; + switch (io_desc->piod_op) { + case VKI_PIOD_READ_D: + case VKI_PIOD_READ_I: + PRE_MEM_WRITE( "ptrace", (UWord)io_desc->piod_addr, io_desc->piod_len); + break; + case VKI_PIOD_WRITE_D: + case VKI_PIOD_WRITE_I: + PRE_MEM_READ( "ptrace", (UWord)io_desc->piod_addr, io_desc->piod_len); + break; + } + break; + + case VKI_PTRACE_CONTINUE: + break; + + case VKI_PTRACE_STEP: + break; + + case VKI_PTRACE_KILL: + break; + + case VKI_PTRACE_ATTACH: + break; + + case VKI_PTRACE_DETACH: + break; + + case VKI_PTRACE_GETREGS: + PRE_MEM_WRITE( "ptrace", ARG3, sizeof(struct vki_reg_struct)); + break; + + case VKI_PTRACE_SETREGS: + PRE_MEM_READ( "ptrace", ARG3, sizeof(struct vki_reg_struct)); + break; + + case VKI_PTRACE_GETFPREGS: + PRE_MEM_WRITE( "ptrace", ARG3, sizeof(struct vki_fpreg)); + break; + + case VKI_PTRACE_SETFPREGS: + PRE_MEM_READ( "ptrace", ARG3, sizeof(struct vki_fpreg)); + break; + + case VKI_PTRACE_GETDBREGS: + PRE_MEM_WRITE( "ptrace", ARG3, sizeof(struct vki_dbreg)); + break; + + case VKI_PTRACE_SETDBREGS: + PRE_MEM_READ( "ptrace", ARG3, sizeof(struct vki_dbreg)); + break; + + case VKI_PTRACE_LWPINFO: + PRE_MEM_WRITE( "ptrace", ARG3, sizeof(struct vki_ptrace_lwpinfo)); + break; + + case VKI_PTRACE_GETNUMLWPS: + break; + + case VKI_PTRACE_GETLWPLIST: + PRE_MEM_WRITE( "ptrace", ARG3, sizeof(vki_lwpid_t) * ARG4); + break; + + case VKI_PTRACE_SETSTEP: + break; + + case VKI_PTRACE_CLEARSTEP: + break; + + case VKI_PTRACE_SUSPEND: + break; + + case VKI_PTRACE_RESUME: + break; + + case VKI_PTRACE_TO_SCE: + break; + + case VKI_PTRACE_TO_SCX: + break; + + case VKI_PTRACE_SYSCALL: + break; + + case VKI_PTRACE_VM_TIMESTAMP: + break; + + case VKI_PTRACE_VM_ENTRY: + PRE_MEM_WRITE( "ptrace", ARG3, sizeof(struct vki_ptrace_vm_entry)); + break; + } +} + +POST(sys_ptrace) +{ + struct vki_ptrace_io_desc *io_desc; + + switch (ARG1) { + case VKI_PTRACE_TRACEME: + break; + case VKI_PTRACE_READ_I: + case VKI_PTRACE_READ_D: + break; + + case VKI_PTRACE_WRITE_I: + case VKI_PTRACE_WRITE_D: + break; + + case VKI_PTRACE_IO: + io_desc = (struct vki_ptrace_io_desc *)ARG3; + switch (io_desc->piod_op) { + case VKI_PIOD_READ_D: + case VKI_PIOD_READ_I: + if (RES != -1) + POST_MEM_WRITE((UWord)io_desc->piod_addr, io_desc->piod_len); + break; + case VKI_PIOD_WRITE_D: + case VKI_PIOD_WRITE_I: + break; + } + break; + + case VKI_PTRACE_CONTINUE: + break; + + case VKI_PTRACE_STEP: + break; + + case VKI_PTRACE_KILL: + break; + + case VKI_PTRACE_ATTACH: + break; + + case VKI_PTRACE_DETACH: + break; + + case VKI_PTRACE_GETREGS: + if (RES != -1) + POST_MEM_WRITE(ARG3, sizeof(struct vki_reg_struct)); + break; + + case VKI_PTRACE_SETREGS: + break; + + case VKI_PTRACE_GETFPREGS: + if (RES != -1) + POST_MEM_WRITE(ARG3, sizeof(struct vki_fpreg)); + break; + + case VKI_PTRACE_SETFPREGS: + break; + + case VKI_PTRACE_GETDBREGS: + if (RES != -1) + POST_MEM_WRITE(ARG3, sizeof(struct vki_dbreg)); + break; + + case VKI_PTRACE_SETDBREGS: + break; + + case VKI_PTRACE_LWPINFO: + if (RES != -1) + POST_MEM_WRITE(ARG3, sizeof(struct vki_ptrace_lwpinfo)); + break; + + case VKI_PTRACE_GETNUMLWPS: + break; + + case VKI_PTRACE_GETLWPLIST: + if (RES != -1) + POST_MEM_WRITE(ARG3, sizeof(vki_lwpid_t) * RES); + break; + + case VKI_PTRACE_SETSTEP: + break; + + case VKI_PTRACE_CLEARSTEP: + break; + + case VKI_PTRACE_SUSPEND: + break; + + case VKI_PTRACE_RESUME: + break; + + case VKI_PTRACE_TO_SCE: + break; + + case VKI_PTRACE_TO_SCX: + break; + + case VKI_PTRACE_SYSCALL: + break; + + case VKI_PTRACE_VM_TIMESTAMP: + break; + + case VKI_PTRACE_VM_ENTRY: + if (RES != -1) + POST_MEM_WRITE(ARG3, sizeof(struct vki_ptrace_vm_entry)); + break; + } +} + +#if 0 +PRE(sys_cpuset_setaffinity) +{ + PRE_MEM_READ("cpuset_setaffinity", ARG5, ARG4); +} +#endif + +PRE(sys_getentropy) +{ + PRINT("sys_getentropy ()"); + PRE_REG_READ2(int, "getentropy", void *, buf, vki_size_t, buflen); + PRE_MEM_WRITE("getentropy(buf)", ARG1, ARG2); +} + +POST(sys_getentropy) +{ + if (SUCCESS) { + POST_MEM_WRITE(ARG1, ARG2); + } +} + +#undef PRE +#undef POST + +const SyscallTableEntry ML_(syscall_table)[] = { + // syscall (handled specially) // 0 + + BSDX_(__NR_exit, sys_exit), // 1 + BSDX_(__NR_fork, sys_fork), // 2 + GENXY(__NR_read, sys_read), // 3 + GENX_(__NR_write, sys_write), // 4 + GENXY(__NR_open, sys_open), // 5 + + GENXY(__NR_close, sys_close), // 6 + BSDXY(__NR_getentropy, sys_getentropy), // 7 + BSDXY(__NR___tfork, sys___tfork), // 8 + GENX_(__NR_link, sys_link), // 9 + GENX_(__NR_unlink, sys_unlink), // 10 + + GENXY(__NR_wait4, sys_wait4), // 11 + GENX_(__NR_chdir, sys_chdir), // 12 + GENX_(__NR_fchdir, sys_fchdir), // 13 + GENX_(__NR_mknod, sys_mknod), // 14 + GENX_(__NR_chmod, sys_chmod), // 15 + + GENX_(__NR_chown, sys_chown), // 16 + //BSDX_(__NR_break, sys_obreak), // 17 + BSDX_(__NR_getdtablecount, sys_getdtablecount), // 18 + GENXY(__NR_getrusage, sys_getrusage), // 19 + GENX_(__NR_getpid, sys_getpid), // 20 + + BSDX_(__NR_mount, sys_mount), // 21 + BSDX_(__NR_unmount, sys_unmount), // 22 + GENX_(__NR_setuid, sys_setuid), // 23 + GENX_(__NR_getuid, sys_getuid), // 24 + GENX_(__NR_geteuid, sys_geteuid), // 25 + + BSDX_(__NR_ptrace, sys_ptrace), // 26 + // unimpl ptrace // 26 + BSDX_(__NR_recvmsg, sys_recvmsg), // 27 + BSDX_(__NR_sendmsg, sys_sendmsg), // 28 + BSDXY(__NR_recvfrom, sys_recvfrom), // 29 + BSDXY(__NR_accept, sys_accept), // 30 + + BSDX_(__NR_getpeername, sys_getpeername), // 31 + BSDX_(__NR_getsockname, sys_getsockname), // 32 + GENX_(__NR_access, sys_access), // 33 + BSDX_(__NR_chflags, sys_chflags), // 34 + BSDX_(__NR_fchflags, sys_fchflags), // 35 + + GENX_(__NR_sync, sys_sync), // 36 + GENX_(__NR_o58_kill, sys_kill), // 37 + BSDXY(__NR_stat, sys_stat), // 38 + GENX_(__NR_getppid, sys_getppid), // 39 + BSDXY(__NR_lstat, sys_lstat), // 40 + + GENX_(__NR_dup, sys_dup), // 41 + BSDXY(__NR_fstatat, sys_fstatat), // 42 + GENX_(__NR_getegid, sys_getegid), // 43 + BSDX_(__NR_profil, sys_profil), // 44 + BSDX_(__NR_ktrace, sys_ktrace), // 45 + + BSDXY(__NR_sigaction, sys_sigaction), // 46 + GENX_(__NR_getgid, sys_getgid), // 47 + BSDX_(__NR_sigprocmask, sys_sigprocmask), // 48 + BSDX_(__NR_getlogin, sys_getlogin), // 49 + BSDX_(__NR_setlogin, sys_setlogin), // 50 + + BSDX_(__NR_acct, sys_acct), // 51 + // unimpl acct // 51 + BSDX_(__NR_sigpending, sys_sigpending), // 52 + BSDXY(__NR_fstat, sys_fstat), // 53 + BSDXY(__NR_ioctl, sys_ioctl), // 54 + BSDX_(__NR_reboot, sys_reboot), // 55 + + BSDX_(__NR_revoke, sys_revoke), // 56 + GENX_(__NR_symlink, sys_symlink), // 57 + GENX_(__NR_readlink, sys_readlink), // 58 + GENX_(__NR_execve, sys_execve), // 59 + GENX_(__NR_umask, sys_umask), // 60 + + GENX_(__NR_chroot, sys_chroot), // 61 + BSDXY(__NR_getfsstat, sys_getfsstat), // 62 + GENXY(__NR_statfs, sys_statfs), // 63 + GENXY(__NR_fstatfs, sys_fstatfs), // 64 + BSDXY(__NR_fhstatfs, sys_fhstatfs), // 65 + + BSDX_(__NR_vfork, sys_vfork), // 66 + GENXY(__NR_gettimeofday, sys_gettimeofday), // 67 + GENX_(__NR_settimeofday, sys_settimeofday), // 68 + GENX_(__NR_setitimer, sys_setitimer), // 69 + GENXY(__NR_getitimer, sys_getitimer), // 70 + + GENX_(__NR_select, sys_select), // 71 + BSDXY(__NR_kevent, sys_kevent), // 72 + GENX_(__NR_munmap, sys_munmap), // 73 + GENX_(__NR_mprotect, sys_mprotect), // 74 + GENX_(__NR_madvise, sys_madvise), // 75 + + GENX_(__NR_utimes, sys_utimes), // 76 + BSDX_(__NR_futimes, sys_futimes), // 77 + GENX_(__NR_mincore, sys_mincore), // 78 + GENXY(__NR_getgroups, sys_getgroups), // 79 + GENX_(__NR_setgroups, sys_setgroups), // 80 + + GENX_(__NR_getpgrp, sys_getpgrp), // 81 + GENX_(__NR_setpgid, sys_setpgid), // 82 + BSDX_(__NR_osendsyslog, sys_sendsyslog), // 83 + BSDX_(__NR_utimensat, sys_utimensat), // 84 + BSDX_(__NR_futimens, sys_futimens), // 85 + + BSDX_(__NR_kbind, sys_kbind), // 86 + BSDXY(__NR_clock_gettime, sys_clock_gettime), // 87 + BSDX_(__NR_clock_settime, sys_clock_settime), // 88 + BSDXY(__NR_clock_getres, sys_clock_getres), // 89 + GENXY(__NR_dup2, sys_dup2), // 90 + + GENX_(__NR_nanosleep, sys_nanosleep), // 91 + BSDXY(__NR_fcntl, sys_fcntl), // 92 + BSDXY(__NR_accept4, sys_accept4), // 93 + BSDX_(__NR___thrsleep, sys___thrsleep), // 94 + GENX_(__NR_fsync, sys_fsync), // 95 + + GENX_(__NR_setpriority, sys_setpriority), // 96 + BSDX_(__NR_socket, sys_socket), // 97 + BSDX_(__NR_connect, sys_connect), // 98 + GENXY(__NR_getdents, sys_getdents), // 99 + GENX_(__NR_getpriority, sys_getpriority), // 100 + + BSDXY(__NR_pipe2, sys_pipe2), // 101 + BSDXY(__NR_dup3, sys_dup3), // 102 + BSDX_(__NR_sigreturn, sys_sigreturn), // 103 + BSDX_(__NR_bind, sys_bind), // 104 + BSDX_(__NR_setsockopt, sys_setsockopt), // 105 + + BSDX_(__NR_listen, sys_listen), // 106 + BSDX_(__NR_chflagsat, sys_chflagsat), // 107 + BSDX_(__NR_pledge, sys_pledge), // 108 + BSDX_(__NR_ppoll, sys_ppoll), // 109 + BSDX_(__NR_pselect, sys_pselect), // 110 + + BSDX_(__NR_sigsuspend, sys_sigsuspend), // 111 + BSDX_(__NR_sendsyslog, sys_sendsyslog), // 112 + // obsol orecvmsg // 113 + // obsol osendmsg // 114 + // obsol vtrace // 115 + + BSDX_(__NR_getsockopt, sys_getsockopt), // 118 + BSDX_(__NR_thrkill, sys_thrkill), // 119 + GENXY(__NR_readv, sys_readv), // 120 + + GENX_(__NR_writev, sys_writev), // 121 + GENX_(__NR_kill, sys_kill), // 122 + GENX_(__NR_fchown, sys_fchown), // 123 + GENX_(__NR_fchmod, sys_fchmod), // 124 + // obsol orecvfrom // 125 + + GENX_(__NR_setreuid, sys_setreuid), // 126 + GENX_(__NR_setregid, sys_setregid), // 127 + GENX_(__NR_rename, sys_rename), // 128 + // obsol otruncate // 129 + // obsol oftruncate // 130 + + GENX_(__NR_flock, sys_flock), // 131 + BSDX_(__NR_mkfifo, sys_mkfifo), // 132 + BSDX_(__NR_sendto, sys_sendto), // 133 + BSDX_(__NR_shutdown, sys_shutdown), // 134 + BSDXY(__NR_socketpair, sys_socketpair), // 135 + + GENX_(__NR_mkdir, sys_mkdir), // 136 + GENX_(__NR_rmdir, sys_rmdir), // 137 + // obsol 4.2 sigreturn // 139 + BSDX_(__NR_adjtime, sys_adjtime), // 140 + + // obsol ogetpeername // 141 + // obsol ogethostid // 142 + // obsol osethostid // 143 + // obsol ogetrlimit // 144 + // obsol osetrlimit // 145 + + // obsol okillpg // 146 + GENX_(__NR_setsid, sys_setsid), // 147 + BSDX_(__NR_quotactl, sys_quotactl), // 148 + // obsol oquota // 149 + // obsol ogetsockname // 150 + + // unimpl // 151 + // unimpl // 152 + // unimpl // 153 + // unimpl // 154 + BSDX_(__NR_nfssvc, sys_nfssvc), // 155 + + // obsol ogetdirentries // 156 + // obsol statfs25 // 157 + // obsol fstatfs25 // 158 + // unimpl // 159 + // unimpl // 160 + + BSDXY(__NR_getfh, sys_getfh), // 161 + // obsol ogetdomainname // 162 + // obsol osetdomainname // 163 + // unimpl ouname // 164 + BSDX_(__NR_sysarch, sys_sysarch), // 165 + + // unimpl // 166 + // unimpl // 167 + // unimpl // 168 + // obsol semsys10 // 169 + // obsol msgsys10 // 170 + + // obsol shmsys10 // 171 + // unimpl // 172 + BSDXY(__NR_pread, sys_pread), // 173 + BSDX_(__NR_pwrite, sys_pwrite), // 174 + // unimpl ntp_gettime // 175 + + // unimpl ntp_adjtime // 176 + // unimpl // 177 + // unimpl // 178 + // unimpl // 179 + // unimpl // 180 + + GENX_(__NR_setgid, sys_setgid), // 181 + BSDX_(__NR_setegid, sys_setegid), // 182 + BSDX_(__NR_seteuid, sys_seteuid), // 183 + // obsol lfs_bmapv // 184 + // obsol lfs_markv // 185 + + // obsol lfs_segclean // 186 + // obsol lfs_segwait // 187 + // obsol stat35 // 188 + // obsol fstat35 // 189 + // obsol lstat35 // 190 + + BSDX_(__NR_pathconf, sys_pathconf), // 191 + BSDX_(__NR_fpathconf, sys_fpathconf), // 192 + BSDX_(__NR_swapctl, sys_swapctl), // 193 + GENX_(__NR_getrlimit, sys_getrlimit), // 194 + BSDX_(__NR_setrlimit, sys_setrlimit), // 195 + + // obsol ogetdirentries48 // 196 + BSDX_(__NR_mmap, sys_mmap), // 197 + // BSDX_(__NR___syscall, sys___syscall), // 198 + BSDX_(__NR_lseek, sys_lseek), // 199 + BSDX_(__NR_truncate, sys_truncate), // 200 + + BSDX_(__NR_ftruncate, sys_ftruncate), // 201 + BSDXY(__NR_sysctl, sys___sysctl), // 202 + GENX_(__NR_mlock, sys_mlock), // 203 + GENX_(__NR_munlock, sys_munlock), // 204 + // unimpl sys_undelete // 205 + + BSDX_(__NR_getpgid, sys_getpgid), // 207 + // obsol nnpfspioctl // 208 + BSDX_(__NR_utrace, sys_utrace), // 209 + + // unimpl // 220 + + BSDX_(__NR_semget, sys_semget), // 221 + // obsol semop35 // 222 + // obsol semconfig35 // 223 + // unimpl // 224 + BSDX_(__NR_msgget, sys_msgget), // 225 + + BSDX_(__NR_msgsnd, sys_msgsnd), // 226 + BSDX_(__NR_msgrcv, sys_msgrcv), // 227 + // unimpl msgctl // 224 + // unimpl msgget // 225 + + // unimpl msgsnd // 226 + // unimpl msgrcv // 227 + BSDX_(__NR_shmat, sys_shmat), // 228 + // unimpl // 229 + BSDX_(__NR_shmdt, sys_shmdt), // 230 + + // obsol shmget35 // 231 + // unimpl timer_create // 235 + + // unimpl timer_delete // 236 + // unimpl timer_settime // 237 + // unimpl timer_gettime // 238 + // unimpl timer_getoverrun // 239 + + // unimpl // 241 + // unimpl // 242 + // unimpl // 243 + // unimpl // 244 + // unimpl // 245 + + // unimpl // 246 + // unimpl // 247 + // unimpl // 248 + // unimpl // 249 + BSDX_(__NR_minherit, sys_minherit), // 250 + + // obsol rfork // 251 + GENX_(__NR_poll, sys_poll), // 252 + BSDX_(__NR_issetugid, sys_issetugid), // 253 + BSDX_(__NR_lchown, sys_lchown), // 254 + BSDX_(__NR_getsid, sys_getsid), // 255 + + BSDX_(__NR_msync, sys_msync), // 256 + // obsol semctl35 // 257 + // obsol shmctl35 // 258 + // obsol msgctl35 // 259 + // unimpl // 260 + + // unimpl // 261 + // unimpl // 262 + BSDXY(__NR_pipe, sys_pipe), // 263 + BSDX_(__NR_fhopen, sys_fhopen), // 264 + // unimpl // 265 + + // unimpl // 266 + BSDXY(__NR_preadv, sys_preadv), // 267 + BSDX_(__NR_pwritev, sys_pwritev), // 268 + BSDX_(__NR_kqueue, sys_kqueue), // 269 + + GENX_(__NR_mlockall, sys_mlockall), // 271 + BSDX_(__NR_munlockall, sys_munlockall), // 272 + // unimpl sys_getpeereid // 273 + // unimpl sys_extattrctl // 274 + // unimpl sys_extattr_set_file // 275 + + // unimpl sys_extattr_get_file // 276 + // unimpl sys_extattr_delete_file // 277 + // unimpl sys_extattr_set_fd // 278 + // unimpl sys_extattr_get_fd // 279 + // unimpl sys_extattr_delete_fd // 280 + + BSDXY(__NR_getresuid, sys_getresuid), // 281 + BSDX_(__NR_setresuid, sys_setresuid), // 282 + BSDXY(__NR_getresgid, sys_getresgid), // 283 + BSDX_(__NR_setresgid, sys_setresgid), // 284 + // obsol sys_omquery // 285 + + BSDX_(__NR_mquery, sys_mquery), // 286 + BSDX_(__NR_closefrom, sys_closefrom), // 287 + BSDX_(__NR_sigaltstack, sys_sigaltstack), // 288 + BSDX_(__NR_shmget, sys_shmget), // 289 + // unimpl shmget // 289 + BSDX_(__NR_semop, sys_semop), // 290 + + BSDXY(__NR_fhstat, sys_fhstat), // 294 + BSDX_(__NR___semctl, sys___semctl), // 295 + + BSDX_(__NR_shmctl, sys_shmctl), // 296 + BSDX_(__NR_msgctl, sys_msgctl), // 297 + BSDX_(__NR_sched_yield, sys_sched_yield), // 298 + BSDX_(__NR_getthrid, sys_getthrid), // 299 + + BSDX_(__NR___thrwakeup, sys___thrwakeup), // 301 + BSDX_(__NR___threxit, sys___threxit), // 302 + BSDX_(__NR___thrsigdivert, sys___thrsigdivert), // 303 + BSDXY(__NR___getcwd, sys___getcwd), // 304 + BSDX_(__NR_adjfreq, sys_adjfreq), // 305 + + BSDX_(__NR_setrtable, sys_setrtable), // 310 + BSDX_(__NR_getrtable, sys_getrtable), // 311 + BSDX_(__NR_faccessat, sys_faccessat), // 313 + BSDX_(__NR_fchmodat, sys_fchmodat), // 314 + BSDX_(__NR_fchownat, sys_fchownat), // 315 + + BSDX_(__NR_linkat, sys_linkat), // 317 + BSDX_(__NR_mkdirat, sys_mkdirat), // 318 + BSDX_(__NR_mkfifoat, sys_mkfifoat), // 319 + BSDX_(__NR_mknodat, sys_mknodat), // 320 + + BSDX_(__NR_openat, sys_openat), // 321 + BSDX_(__NR_readlinkat, sys_readlinkat), // 322 + BSDX_(__NR_renameat, sys_renameat), // 323 + BSDX_(__NR_symlinkat, sys_symlinkat), // 324 + BSDX_(__NR_unlinkat, sys_unlinkat), // 325 + + BSDX_(__NR___set_tcb, sys___set_tcb), // 329 + BSDX_(__NR___get_tcb, sys___get_tcb), // 330 + + BSDX_(__NR_fake_sigreturn, sys_fake_sigreturn), // 1000, fake sigreturn +}; + +const UInt ML_(syscall_table_size) = + sizeof(ML_(syscall_table)) / sizeof(ML_(syscall_table)[0]); + +#endif // defined(VGO_openbsd) + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_syswrap/syswrap-x86-freebsd.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coregrind/m_syswrap/syswrap-x86-freebsd.c Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,1160 @@ + +/*--------------------------------------------------------------------*/ +/*--- Platform-specific syscalls stuff. syswrap-x86-linux.c ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2008 Nicholas Nethercote + njn@valgrind.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#if defined(VGP_x86_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_libcsetjmp.h" // to keep _threadstate.h happy +#include "pub_core_threadstate.h" +#include "pub_core_aspacemgr.h" +#include "pub_core_debuglog.h" +#include "pub_core_libcbase.h" +#include "pub_core_libcassert.h" +#include "pub_core_libcprint.h" +#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_signals.h" +#include "pub_core_syscall.h" +#include "pub_core_syswrap.h" +#include "pub_core_tooliface.h" +#include "pub_core_stacks.h" // VG_(register_stack) + +#include "priv_types_n_macros.h" +#include "priv_syswrap-generic.h" /* for decls of generic wrappers */ +#include "priv_syswrap-freebsd.h" /* for decls of linux-ish wrappers */ +#include "priv_syswrap-main.h" + +/* --------------------------------------------------------------------- + clone() handling + ------------------------------------------------------------------ */ + +/* 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.*/ +__attribute__((noreturn)) +void ML_(call_on_new_stack_0_1) ( Addr stack, + Addr retaddr, + void (*f)(Word), + Word arg1 ); +// 4(%esp) == stack +// 8(%esp) == retaddr +// 12(%esp) == f +// 16(%esp) == arg1 +asm( +".text\n" +".globl vgModuleLocal_call_on_new_stack_0_1\n" +"vgModuleLocal_call_on_new_stack_0_1:\n" +" movl %esp, %esi\n" // remember old stack pointer +" movl 4(%esi), %esp\n" // set stack +" pushl 16(%esi)\n" // arg1 to stack +" pushl 8(%esi)\n" // retaddr to stack +" pushl 12(%esi)\n" // f to stack +" movl $0, %eax\n" // zero all GP regs +" movl $0, %ebx\n" +" movl $0, %ecx\n" +" movl $0, %edx\n" +" movl $0, %esi\n" +" movl $0, %edi\n" +" movl $0, %ebp\n" +" ret\n" // jump to f +" ud2\n" // should never get here +".previous\n" +); + + +#if 0 +/* + Perform a rfork system call. rfork is strange because it has + fork()-like return-twice semantics, so it needs special + handling here. + + Upon entry, we have: + + int (fn)(void*) in 0+FSZ(%esp) + void* child_stack in 4+FSZ(%esp) + int flags in 8+FSZ(%esp) + void* arg in 12+FSZ(%esp) + pid_t* child_tid in 16+FSZ(%esp) + pid_t* parent_tid in 20+FSZ(%esp) + void* tls_ptr in 24+FSZ(%esp) + + System call requires: + + int $__NR_clone in %eax + int flags in %ebx + void* child_stack in %ecx + pid_t* parent_tid in %edx + pid_t* child_tid in %edi + void* tls_ptr in %esi + + Returns an Int encoded in the linux-x86 way, not a SysRes. + */ +#define FSZ "4+4+4+4" /* frame size = retaddr+ebx+edi+esi */ +#define __NR_CLONE VG_STRINGIFY(__NR_clone) +#define __NR_EXIT VG_STRINGIFY(__NR_exit) + +extern +Int do_syscall_clone_x86_freebsd ( Word (*fn)(void *), + void* stack, + Int flags, + void* arg, + Int* child_tid, + Int* parent_tid, + vki_modify_ldt_t * ); +asm( +".text\n" +"do_syscall_clone_x86_freebsd:\n" +" push %ebx\n" +" push %edi\n" +" push %esi\n" + + /* set up child stack with function and arg */ +" movl 4+"FSZ"(%esp), %ecx\n" /* syscall arg2: child stack */ +" movl 12+"FSZ"(%esp), %ebx\n" /* fn arg */ +" movl 0+"FSZ"(%esp), %eax\n" /* fn */ +" lea -8(%ecx), %ecx\n" /* make space on stack */ +" movl %ebx, 4(%ecx)\n" /* fn arg */ +" movl %eax, 0(%ecx)\n" /* fn */ + + /* get other args to clone */ +" movl 8+"FSZ"(%esp), %ebx\n" /* syscall arg1: flags */ +" movl 20+"FSZ"(%esp), %edx\n" /* syscall arg3: parent tid * */ +" movl 16+"FSZ"(%esp), %edi\n" /* syscall arg5: child tid * */ +" movl 24+"FSZ"(%esp), %esi\n" /* syscall arg4: tls_ptr * */ +" movl $"__NR_CLONE", %eax\n" +" int $0x80\n" /* clone() */ +" testl %eax, %eax\n" /* child if retval == 0 */ +" jnz 1f\n" + + /* CHILD - call thread function */ +" popl %eax\n" +" call *%eax\n" /* call fn */ + + /* exit with result */ +" movl %eax, %ebx\n" /* arg1: return value from fn */ +" movl $"__NR_EXIT", %eax\n" +" int $0x80\n" + + /* Hm, exit returned */ +" ud2\n" + +"1:\n" /* PARENT or ERROR */ +" pop %esi\n" +" pop %edi\n" +" pop %ebx\n" +" ret\n" +".previous\n" +); + +#undef FSZ +#undef __NR_CLONE +#undef __NR_EXIT + + +// forward declarations +static void setup_child ( ThreadArchState*, ThreadArchState*, Bool ); + +/* + When a client clones, we need to keep track of the new thread. This means: + 1. allocate a ThreadId+ThreadState+stack for the the thread + + 2. initialize the thread's new VCPU state + + 3. create the thread using the same args as the client requested, + but using the scheduler entrypoint for EIP, and a separate stack + for ESP. + */ +static SysRes do_rfork ( ThreadId ptid, + UInt flags) +{ + static const Bool debug = False; + + Addr esp; + ThreadId ctid = VG_(alloc_ThreadState)(); + ThreadState* ptst = VG_(get_ThreadState)(ptid); + ThreadState* ctst = VG_(get_ThreadState)(ctid); + UWord* stack; + NSegment const* seg; + SysRes res; + Int eax; + vki_sigset_t blockall, savedmask; + + VG_(sigfillset)(&blockall); + + vg_assert(VG_(is_running_thread)(ptid)); + vg_assert(VG_(is_valid_tid)(ctid)); + + stack = (UWord*)ML_(allocstack)(ctid); + if (stack == NULL) { + res = VG_(mk_SysRes_Error)( VKI_ENOMEM ); + goto out; + } + + /* Copy register state + + Both parent and child return to the same place, and the code + following the clone syscall works out which is which, so we + don't need to worry about it. + + The parent gets the child's new tid returned from clone, but the + child gets 0. + + If the clone call specifies a NULL esp for the new thread, then + it actually gets a copy of the parent's esp. + */ + /* Note: the clone call done by the Quadrics Elan3 driver specifies + clone flags of 0xF00, and it seems to rely on the assumption + that the child inherits a copy of the parent's GDT. + setup_child takes care of setting that up. */ + setup_child( &ctst->arch, &ptst->arch, True ); + + /* Make sys_clone appear to have returned Success(0) in the + child. */ + ctst->arch.vex.guest_EAX = 0; + + /* Assume linuxthreads port storing its intended stack in %esi */ + esp = ctst->arch.vex.guest_ESI; + + ctst->os_state.parent = ptid; + + /* inherit signal mask */ + ctst->sig_mask = ptst->sig_mask; + ctst->tmp_sig_mask = ptst->sig_mask; + + /* We don't really know where the client stack is, because its + allocated by the client. The best we can do is look at the + memory mappings and try to derive some useful information. We + assume that esp starts near its highest possible value, and can + only go down to the start of the mmaped segment. */ + seg = VG_(am_find_nsegment)((Addr)esp); + if (seg && seg->kind != SkResvn) { + ctst->client_stack_highest_word = (Addr)VG_PGROUNDUP(esp); + ctst->client_stack_szB = ctst->client_stack_highest_word - seg->start; + + VG_(register_stack)(seg->start, ctst->client_stack_highest_word); + + if (debug) + VG_(printf)("tid %d: guessed client stack range %#lx-%#lx\n", + ctid, seg->start, VG_PGROUNDUP(esp)); + } else { + VG_(message)(Vg_UserMsg, "!? New thread %d starts with ESP(%#lx) unmapped\n", + ctid, esp); + ctst->client_stack_szB = 0; + } + + /* Assume the clone will succeed, and tell any tool that wants to + know that this thread has come into existence. We cannot defer + it beyond this point because sys_set_thread_area, just below, + causes tCheck to assert by making references to the new ThreadId + if we don't state the new thread exists prior to that point. + If the clone 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, ptid, ctid ); + + /* start the thread with everything blocked */ + VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask); + + /* Create the new thread */ + /* XXX need to see what happens with tids etc with rfork */ + eax = do_syscall_clone_x86_freebsd( + ML_(start_thread_NORETURN), stack, flags /*, &VG_(threads)[ctid], NULL*/ ); + res = VG_(mk_SysRes_x86_freebsd)( eax ); /* XXX edx returns too! */ + + VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL); + + out: + if (res.isError) { + /* clone failed */ + VG_(cleanup_thread)(&ctst->arch); + ctst->status = VgTs_Empty; + /* oops. Better tell the tool the thread exited in a hurry :-) */ + VG_TRACK( pre_thread_ll_exit, ctid ); + } + + return res; +} +#endif + +/* Translate a struct modify_ldt_ldt_s to a VexGuestX86SegDescr */ + +static +void translate_to_hw_format ( /* IN */ void* base, + /* OUT */ VexGuestX86SegDescr* out) +{ + UInt entry_1, entry_2; + UInt base_addr = (UInt) base; + vg_assert(8 == sizeof(VexGuestX86SegDescr)); + + if (0) + VG_(printf)("translate_to_hw_format: base %p\n", base ); + + /* Allow LDTs to be cleared by the user. */ + if (base == 0) { + entry_1 = 0; + entry_2 = 0; + goto install; + } + /* base as specified, no limit, read/write/accessed etc */ + entry_1 = ((base_addr & 0x0000ffff) << 16) | 0x0ffff; + entry_2 = (base_addr & 0xff000000) | + ((base_addr & 0x00ff0000) >> 16) | 0x00cff300; + + /* Install the new entry ... */ + install: + out->LdtEnt.Words.word1 = entry_1; + out->LdtEnt.Words.word2 = entry_2; +} + +/* Create a zeroed-out GDT. */ +static VexGuestX86SegDescr* alloc_zeroed_x86_GDT ( void ) +{ + Int nbytes = VEX_GUEST_X86_GDT_NENT * sizeof(VexGuestX86SegDescr); + return VG_(arena_calloc)(VG_AR_CORE, "di.syswrap-x86.azxG.1", nbytes, 1); +} + +#if 0 +/* Create a zeroed-out LDT. */ +static VexGuestX86SegDescr* alloc_zeroed_x86_LDT ( void ) +{ + Int nbytes = VEX_GUEST_X86_LDT_NENT * sizeof(VexGuestX86SegDescr); + return VG_(arena_calloc)(VG_AR_CORE, "di.syswrap-x86.azxL.1", nbytes, 1); +} + +/* Free up an LDT or GDT allocated by the above fns. */ +static void free_LDT_or_GDT ( VexGuestX86SegDescr* dt ) +{ + vg_assert(dt); + VG_(arena_free)(VG_AR_CORE, (void*)dt); +} + +/* Copy contents between two existing LDTs. */ +static void copy_LDT_from_to ( VexGuestX86SegDescr* src, + VexGuestX86SegDescr* dst ) +{ + Int i; + vg_assert(src); + vg_assert(dst); + for (i = 0; i < VEX_GUEST_X86_LDT_NENT; i++) + dst[i] = src[i]; +} + +/* Copy contents between two existing GDTs. */ +static void copy_GDT_from_to ( VexGuestX86SegDescr* src, + VexGuestX86SegDescr* dst ) +{ + Int i; + vg_assert(src); + vg_assert(dst); + for (i = 0; i < VEX_GUEST_X86_GDT_NENT; i++) + dst[i] = src[i]; +} + +/* Free this thread's DTs, if it has any. */ +static void deallocate_LGDTs_for_thread ( VexGuestX86State* vex ) +{ + vg_assert(sizeof(HWord) == sizeof(void*)); + + if (0) + VG_(printf)("deallocate_LGDTs_for_thread: " + "ldt = 0x%x, gdt = 0x%x\n", + vex->guest_LDT, vex->guest_GDT ); + + if (vex->guest_LDT != (HWord)NULL) { + free_LDT_or_GDT( (VexGuestX86SegDescr*)vex->guest_LDT ); + vex->guest_LDT = (HWord)NULL; + } + + if (vex->guest_GDT != (HWord)NULL) { + free_LDT_or_GDT( (VexGuestX86SegDescr*)vex->guest_GDT ); + vex->guest_GDT = (HWord)NULL; + } +} +#endif + +static SysRes sys_set_thread_area ( ThreadId tid, Int *idxptr, void *base) +{ + VexGuestX86SegDescr* gdt; + Int idx; + + vg_assert(8 == sizeof(VexGuestX86SegDescr)); + vg_assert(sizeof(HWord) == sizeof(VexGuestX86SegDescr*)); + + gdt = (VexGuestX86SegDescr*)VG_(threads)[tid].arch.vex.guest_GDT; + + /* If the thread doesn't have a GDT, allocate it now. */ + if (!gdt) { + gdt = alloc_zeroed_x86_GDT(); + VG_(threads)[tid].arch.vex.guest_GDT = (HWord)gdt; + } + + idx = *idxptr; + if (idx == -1) { + /* Find and use the first free entry. Don't allocate entry + zero, because the hardware will never do that, and apparently + doing so confuses some code (perhaps stuff running on + Wine). */ + for (idx = 1; idx < VEX_GUEST_X86_GDT_NENT; idx++) { + if (gdt[idx].LdtEnt.Words.word1 == 0 + && gdt[idx].LdtEnt.Words.word2 == 0) + break; + } + + if (idx == VEX_GUEST_X86_GDT_NENT) + return VG_(mk_SysRes_Error)( VKI_ESRCH ); + } else if (idx < 0 || idx == 0 || idx >= VEX_GUEST_X86_GDT_NENT) { + /* Similarly, reject attempts to use GDT[0]. */ + return VG_(mk_SysRes_Error)( VKI_EINVAL ); + } + + translate_to_hw_format(base, &gdt[idx]); + + *idxptr = idx; + return VG_(mk_SysRes_Success)( 0 ); +} + +static SysRes sys_get_thread_area ( ThreadId tid, Int idx, void ** basep ) +{ + VexGuestX86SegDescr* gdt; + UInt base; + + vg_assert(sizeof(HWord) == sizeof(VexGuestX86SegDescr*)); + vg_assert(8 == sizeof(VexGuestX86SegDescr)); + + gdt = (VexGuestX86SegDescr*)VG_(threads)[tid].arch.vex.guest_GDT; + + /* If the thread doesn't have a GDT, allocate it now. */ + if (!gdt) { + gdt = alloc_zeroed_x86_GDT(); + VG_(threads)[tid].arch.vex.guest_GDT = (HWord)gdt; + } + + base = ( gdt[idx].LdtEnt.Bits.BaseHi << 24 ) | + ( gdt[idx].LdtEnt.Bits.BaseMid << 16 ) | + gdt[idx].LdtEnt.Bits.BaseLow; + *basep = (void *)base; + + return VG_(mk_SysRes_Success)( 0 ); +} + +/* --------------------------------------------------------------------- + More thread stuff + ------------------------------------------------------------------ */ + +void VG_(cleanup_thread) ( ThreadArchState* arch ) +{ +} + + +#if 0 +static void setup_child ( /*OUT*/ ThreadArchState *child, + /*IN*/ ThreadArchState *parent, + Bool inherit_parents_GDT ) +{ + /* We inherit our parent's guest state. */ + child->vex = parent->vex; + child->vex_shadow1 = parent->vex_shadow1; + child->vex_shadow2 = parent->vex_shadow2; + + /* We inherit our parent's LDT. */ + if (parent->vex.guest_LDT == (HWord)NULL) { + /* We hope this is the common case. */ + child->vex.guest_LDT = (HWord)NULL; + } else { + /* No luck .. we have to take a copy of the parent's. */ + child->vex.guest_LDT = (HWord)alloc_zeroed_x86_LDT(); + copy_LDT_from_to( (VexGuestX86SegDescr*)parent->vex.guest_LDT, + (VexGuestX86SegDescr*)child->vex.guest_LDT ); + } + + /* Either we start with an empty GDT (the usual case) or inherit a + copy of our parents' one (Quadrics Elan3 driver -style clone + only). */ + child->vex.guest_GDT = (HWord)NULL; + + if (inherit_parents_GDT && parent->vex.guest_GDT != (HWord)NULL) { + child->vex.guest_GDT = (HWord)alloc_zeroed_x86_GDT(); + copy_GDT_from_to( (VexGuestX86SegDescr*)parent->vex.guest_GDT, + (VexGuestX86SegDescr*)child->vex.guest_GDT ); + } +} +#endif + +/* --------------------------------------------------------------------- + PRE/POST wrappers for x86/Linux-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; + + ThreadId ctid = VG_(alloc_ThreadState)(); + ThreadState* ptst = VG_(get_ThreadState)(tid); + ThreadState* ctst = VG_(get_ThreadState)(ctid); + SysRes res; + vki_sigset_t blockall, savedmask; + struct vki_thr_param tp; + Int idx = -1; + Addr stk; + + PRINT("thr_new ( %#lx, %ld )",ARG1,ARG2); + PRE_REG_READ2(int, "thr_new", + struct thr_param *, param, + int, param_size); + + PRE_MEM_READ( "thr_new(param)", ARG1, offsetof(struct vki_thr_param, spare)); + if (!ML_(safe_to_deref)( (void*)ARG1, offsetof(struct vki_thr_param, spare))) { + SET_STATUS_Failure( VKI_EFAULT ); + return; + } + 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)); + + VG_(sigfillset)(&blockall); + + vg_assert(VG_(is_running_thread)(tid)); + vg_assert(VG_(is_valid_tid)(ctid)); + + /* Copy register state + + On linux, both parent and child return to the same place, and the code + following the clone syscall works out which is which, so we + don't need to worry about it. + On FreeBSD, thr_new arranges a direct call. We don't actually need any + of this gunk. + + The parent gets the child's new tid returned from clone, but the + child gets 0. + + If the clone call specifies a NULL rsp for the new thread, then + it actually gets a copy of the parent's rsp. + */ + /* We inherit our parent's guest state. */ + ctst->arch.vex = ptst->arch.vex; + 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 + child. */ + ctst->arch.vex.guest_EAX = 0; + ctst->arch.vex.guest_EDX = 0; + LibVEX_GuestX86_put_eflag_c(0, &ctst->arch.vex); + + ctst->os_state.parent = tid; + + /* inherit signal mask */ + ctst->sig_mask = ptst->sig_mask; + ctst->tmp_sig_mask = ptst->sig_mask; + + /* 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 + 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 ); + + if (debug) + VG_(printf)("clone child has SETTLS: tls at %#lx\n", (Addr)tp.tls_base); + sys_set_thread_area( ctid, &idx, tp.tls_base ); + ctst->arch.vex.guest_GS = (idx << 3) | 3; /* GSEL(GUGS_SEL, SEL_UPL) */ + tp.tls_base = 0; /* Don't have the kernel do it too */ + + /* start the thread with everything blocked */ + VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask); + + /* Set the client state for scheduler to run libthr's trampoline */ + ctst->arch.vex.guest_ESP = (Addr)tp.stack_base + tp.stack_size - 8; + ctst->arch.vex.guest_EIP = (Addr)tp.start_func; + *(UWord *)(ctst->arch.vex.guest_ESP + 4) = (UWord)tp.arg; /* Client arg */ + *(UWord *)(ctst->arch.vex.guest_ESP + 0) = 0; /* fake return addr */ + + /* Set up valgrind's trampoline on its own stack */ + stk = ML_(allocstack)(ctid); + tp.stack_base = (void *)ctst->os_state.valgrind_stack_base; + tp.stack_size = (Addr)stk - (Addr)tp.stack_base; + /* This is for thr_new() to run valgrind's trampoline */ + tp.start_func = (void *)ML_(start_thread_NORETURN); + tp.arg = &VG_(threads)[ctid]; + + /* Create the new thread */ + res = VG_(do_syscall2)(__NR_thr_new, (UWord)&tp, sizeof(tp)); + + VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL); + + if (sr_isError(res)) { + /* clone failed */ + VG_(cleanup_thread)(&ctst->arch); + ctst->status = VgTs_Empty; + /* oops. Better tell the tool the thread exited in a hurry :-) */ + VG_TRACK( pre_thread_ll_exit, ctid ); + } else { + + POST_MEM_WRITE((Addr)tp.parent_tid, sizeof(long)); + POST_MEM_WRITE((Addr)tp.child_tid, sizeof(long)); + POST_MEM_WRITE((Addr)ctst->arch.vex.guest_ESP, 8); + + /* Thread creation was successful; let the child have the chance + to run */ + *flags |= SfYieldAfter; + } + + /* "Complete" the syscall so that the wrapper doesn't call the kernel again. */ + SET_STATUS_from_SysRes(res); +} + + +PRE(sys_rfork) +{ + PRINT("sys_rfork ( %lx )",ARG1); + PRE_REG_READ1(int, "rfork", + unsigned int, flags); + +#if 0 + cloneflags = ARG1; + + if (!ML_(client_signal_OK)(ARG1 & VKI_CSIGNAL)) { + SET_STATUS_Failure( VKI_EINVAL ); + return; + } + + SET_STATUS_from_SysRes( do_clone(tid, ARG1)); + + if (SUCCESS) { + *flags |= SfYieldAfter; + } +#else + VG_(message)(Vg_UserMsg, "No rfork for you!"); + VG_(unimplemented) + ("Valgrind does not support rfork() yet."); + SET_STATUS_Failure( VKI_ENOSYS ); +#endif +} + +PRE(sys_sigreturn) +{ + PRINT("sys_sigreturn ( %#lx )", ARG1); + PRE_REG_READ1(long, "sigreturn", + struct vki_ucontext *, ucp); + + PRE_MEM_READ( "sigreturn(ucp)", ARG1, sizeof(struct vki_ucontext) ); + PRE_MEM_WRITE( "sigreturn(ucp)", ARG1, sizeof(struct vki_ucontext) ); +} + +PRE(sys_fake_sigreturn) +{ + /* See comments on PRE(sys_rt_sigreturn) in syswrap-amd64-linux.c for + an explanation of what follows. */ + + ThreadState* tst; + struct vki_ucontext *uc; + PRINT("sys_sigreturn ( )"); + + 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); /* QQQ should be redundant */ + + uc = (struct vki_ucontext *)ARG1; + if (uc == NULL || uc->uc_mcontext.len != sizeof(uc->uc_mcontext)) { + SET_STATUS_Failure(VKI_EINVAL); + return; + } + + /* 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); + + /* Restore register state from frame and remove it */ + VG_(sigframe_destroy)(tid); + + /* + * Signal handler might have changed the signal mask. Respect that. + */ + tst->sig_mask = uc->uc_sigmask; + tst->tmp_sig_mask = uc->uc_sigmask; + + /* 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); + + /* Check to see if any signals arose as a result of this. */ + *flags |= SfPollAfter; +} + +#if 0 /* QQQ keep for 6.x signals */ +PRE(sys_rt_sigreturn) +{ + /* See comments on PRE(sys_rt_sigreturn) in syswrap-amd64-linux.c for + an explanation of what follows. */ + + ThreadState* tst; + PRINT("sys_rt_sigreturn ( )"); + + 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); + + /* Restore register state from frame and remove it */ + VG_(sigframe_destroy)(tid, True); + + /* 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); + + /* Check to see if any signals arose as a result of this. */ + *flags |= SfPollAfter; +} +#endif + +static void restore_mcontext(ThreadState *tst, struct vki_mcontext *sc) +{ + tst->arch.vex.guest_EAX = sc->eax; + tst->arch.vex.guest_ECX = sc->ecx; + tst->arch.vex.guest_EDX = sc->edx; + tst->arch.vex.guest_EBX = sc->ebx; + tst->arch.vex.guest_EBP = sc->ebp; + tst->arch.vex.guest_ESP = sc->esp; + tst->arch.vex.guest_ESI = sc->esi; + tst->arch.vex.guest_EDI = sc->edi; + tst->arch.vex.guest_EIP = sc->eip; + tst->arch.vex.guest_CS = sc->cs; + tst->arch.vex.guest_SS = sc->ss; + tst->arch.vex.guest_DS = sc->ds; + tst->arch.vex.guest_ES = sc->es; + tst->arch.vex.guest_FS = sc->fs; + tst->arch.vex.guest_GS = sc->gs; + /* + * XXX: missing support for other flags. + */ + if (sc->eflags & 0x0001) + LibVEX_GuestX86_put_eflag_c(1, &tst->arch.vex); + else + LibVEX_GuestX86_put_eflag_c(0, &tst->arch.vex); +} + +static void fill_mcontext(ThreadState *tst, struct vki_mcontext *sc) +{ + sc->eax = tst->arch.vex.guest_EAX; + sc->ecx = tst->arch.vex.guest_ECX; + sc->edx = tst->arch.vex.guest_EDX; + sc->ebx = tst->arch.vex.guest_EBX; + sc->ebp = tst->arch.vex.guest_EBP; + sc->esp = tst->arch.vex.guest_ESP; + sc->esi = tst->arch.vex.guest_ESI; + sc->edi = tst->arch.vex.guest_EDI; + sc->eip = tst->arch.vex.guest_EIP; + sc->cs = tst->arch.vex.guest_CS; + sc->ss = tst->arch.vex.guest_SS; + sc->ds = tst->arch.vex.guest_DS; + sc->es = tst->arch.vex.guest_ES; + sc->fs = tst->arch.vex.guest_FS; + sc->gs = tst->arch.vex.guest_GS; + sc->eflags = LibVEX_GuestX86_get_eflags(&tst->arch.vex); +/* + not yet. + VG_(memcpy)(&sc->fpstate, fpstate, sizeof(*fpstate)); +*/ + sc->fpformat = VKI_FPFMT_NODEV; + sc->ownedfp = VKI_FPOWNED_NONE; + sc->len = sizeof(*sc); + VG_(memset)(sc->spare2, 0, sizeof(sc->spare2)); +} + + +PRE(sys_getcontext) +{ + ThreadState* tst; + struct vki_ucontext *uc; + + PRINT("sys_getcontext ( %#lx )", ARG1); + PRE_REG_READ1(long, "getcontext", + struct vki_ucontext *, ucp); + PRE_MEM_WRITE( "getcontext(ucp)", ARG1, sizeof(struct vki_ucontext) ); + uc = (struct vki_ucontext *)ARG1; + if (uc == NULL) { + SET_STATUS_Failure(VKI_EINVAL); + return; + } + tst = VG_(get_ThreadState)(tid); + fill_mcontext(tst, &uc->uc_mcontext); + uc->uc_mcontext.eax = 0; + uc->uc_mcontext.edx = 0; + uc->uc_mcontext.eflags &= ~0x0001; /* PSL_C */ + uc->uc_sigmask = tst->sig_mask; + VG_(memset)(uc->__spare__, 0, sizeof(uc->__spare__)); + SET_STATUS_Success(0); +} + +PRE(sys_setcontext) +{ + ThreadState* tst; + struct vki_ucontext *uc; + + PRINT("sys_setcontext ( %#lx )", ARG1); + PRE_REG_READ1(long, "setcontext", + struct vki_ucontext *, ucp); + + PRE_MEM_READ( "setcontext(ucp)", ARG1, sizeof(struct vki_ucontext) ); + PRE_MEM_WRITE( "setcontext(ucp)", ARG1, sizeof(struct vki_ucontext) ); + + vg_assert(VG_(is_valid_tid)(tid)); + vg_assert(tid >= 1 && tid < VG_N_THREADS); + vg_assert(VG_(is_running_thread)(tid)); + + tst = VG_(get_ThreadState)(tid); + uc = (struct vki_ucontext *)ARG1; + if (uc == NULL || uc->uc_mcontext.len != sizeof(uc->uc_mcontext)) { + SET_STATUS_Failure(VKI_EINVAL); + return; + } + + restore_mcontext(tst, &uc->uc_mcontext); + tst->sig_mask = uc->uc_sigmask; + + /* 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); + + /* Check to see if some any signals arose as a result of this. */ + *flags |= SfPollAfter; +} + +PRE(sys_swapcontext) +{ + struct vki_ucontext *ucp, *oucp; + ThreadState* tst; + + PRINT("sys_swapcontext ( %#lx, %#lx )", ARG1, ARG2); + PRE_REG_READ2(long, "swapcontext", + struct vki_ucontext *, oucp, struct vki_ucontext *, ucp); + + PRE_MEM_READ( "swapcontext(ucp)", ARG2, sizeof(struct vki_ucontext) ); + PRE_MEM_WRITE( "swapcontext(oucp)", ARG1, sizeof(struct vki_ucontext) ); + + oucp = (struct vki_ucontext *)ARG1; + ucp = (struct vki_ucontext *)ARG2; + if (oucp == NULL || ucp == NULL || ucp->uc_mcontext.len != sizeof(ucp->uc_mcontext)) { + SET_STATUS_Failure(VKI_EINVAL); + return; + } + tst = VG_(get_ThreadState)(tid); + + /* + * Save the context. + */ + fill_mcontext(tst, &oucp->uc_mcontext); + oucp->uc_mcontext.eax = 0; + oucp->uc_mcontext.edx = 0; + oucp->uc_mcontext.eflags &= ~0x0001; /* PSL_C */ + oucp->uc_sigmask = tst->sig_mask; + VG_(memset)(oucp->__spare__, 0, sizeof(oucp->__spare__)); + + /* + * Switch to new one. + */ + restore_mcontext(tst, &ucp->uc_mcontext); + tst->sig_mask = ucp->uc_sigmask; + + /* 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); + + /* Check to see if some any signals arose as a result of this. */ + *flags |= SfPollAfter; +} + +/* This is here because on x86 the off_t is passed in 2 regs. Don't ask about pad. */ + +/* caddr_t mmap(caddr_t addr, size_t len, int prot, int flags, int fd, int pad, off_t pos); */ +/* ARG1 ARG2 ARG3 ARG4 ARG5 ARG6 ARG7+ARG8 */ + +PRE(sys_mmap) +{ + SysRes r; + + PRINT("sys_mmap ( %#lx, %lu, %ld, %ld, %ld, pad%ld, lo0x%lx hi0x%lx)", + ARG1, (UWord)ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8 ); + PRE_REG_READ8(long, "mmap", + char *, addr, unsigned long, len, int, prot, int, flags, + int, fd, int, pad, unsigned long, lo, unsigned long, hi); + + r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG7 + ((Off64T)ARG8 << 32) ); + SET_STATUS_from_SysRes(r); +} + +PRE(sys_mmap7) +{ + SysRes r; + + PRINT("sys_mmap ( %#lx, %lu, %ld, %ld, %ld, lo0x%lx hi0x%lx)", + ARG1, (UWord)ARG2, ARG3, ARG4, ARG5, ARG6, ARG7 ); + PRE_REG_READ7(long, "mmap", + char *, addr, unsigned long, len, int, prot, int, flags, + int, fd, unsigned long, lo, unsigned long, hi); + + r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 + ((Off64T)ARG7 << 32) ); + SET_STATUS_from_SysRes(r); +} + +PRE(sys_lseek) +{ + PRINT("sys_lseek ( %ld, 0x%lx, 0x%lx, %ld )", ARG1,ARG3,ARG4,ARG5); + PRE_REG_READ5(long, "lseek", + unsigned int, fd, int, pad, unsigned int, offset_low, + unsigned int, offset_high, unsigned int, whence); +} + +PRE(sys_lseek7) +{ + PRINT("sys_lseek ( %ld, 0x%lx, 0x%lx, %ld )", ARG1,ARG2,ARG3,ARG4); + PRE_REG_READ4(long, "lseek", + unsigned int, fd, unsigned int, offset_low, + unsigned int, offset_high, unsigned int, whence); +} + +PRE(sys_pread) +{ + *flags |= SfMayBlock; + PRINT("sys_read ( %ld, %#lx, %lu, %lu, %lu )", ARG1, ARG2, ARG3, ARG5, ARG6); + PRE_REG_READ6(ssize_t, "read", + unsigned int, fd, char *, buf, vki_size_t, count, + int, pad, unsigned int, off_low, unsigned int, off_high); + + if (!ML_(fd_allowed)(ARG1, "read", tid, False)) + SET_STATUS_Failure( VKI_EBADF ); + else + PRE_MEM_WRITE( "read(buf)", ARG2, ARG3 ); +} + +POST(sys_pread) +{ + vg_assert(SUCCESS); + POST_MEM_WRITE( ARG2, RES ); +} + +PRE(sys_pread7) +{ + *flags |= SfMayBlock; + PRINT("sys_read ( %ld, %#lx, %lu, %lu, %lu )", ARG1, ARG2, ARG3, ARG4, ARG5); + PRE_REG_READ5(ssize_t, "read", + unsigned int, fd, char *, buf, vki_size_t, count, + unsigned int, off_low, unsigned int, off_high); + + if (!ML_(fd_allowed)(ARG1, "read", tid, False)) + SET_STATUS_Failure( VKI_EBADF ); + else + PRE_MEM_WRITE( "read(buf)", ARG2, ARG3 ); +} + +POST(sys_pread7) +{ + vg_assert(SUCCESS); + POST_MEM_WRITE( ARG2, RES ); +} + +PRE(sys_pwrite) +{ + Bool ok; + *flags |= SfMayBlock; + PRINT("sys_write ( %ld, %#lx, %lu, %lu, %lu )", ARG1, ARG2, ARG3, ARG5, ARG6); + PRE_REG_READ6(ssize_t, "write", + unsigned int, fd, const char *, buf, vki_size_t, count, + int, pad, unsigned int, off_low, unsigned int, off_high); + /* check to see if it is allowed. If not, try for an exemption from + --sim-hints=enable-outer (used for self hosting). */ + ok = ML_(fd_allowed)(ARG1, "write", tid, False); + if (!ok && ARG1 == 2/*stderr*/ + && SimHintiS(SimHint_enable_outer, VG_(clo_sim_hints))) + ok = True; + if (!ok) + SET_STATUS_Failure( VKI_EBADF ); + else + PRE_MEM_READ( "write(buf)", ARG2, ARG3 ); +} + +PRE(sys_pwrite7) +{ + Bool ok; + *flags |= SfMayBlock; + PRINT("sys_write ( %ld, %#lx, %lu, %lu, %lu )", ARG1, ARG2, ARG3, ARG4, ARG5); + PRE_REG_READ5(ssize_t, "write", + unsigned int, fd, const char *, buf, vki_size_t, count, + unsigned int, off_low, unsigned int, off_high); + /* check to see if it is allowed. If not, try for an exemption from + --sim-hints=enable-outer (used for self hosting). */ + ok = ML_(fd_allowed)(ARG1, "write", tid, False); + if (!ok && ARG1 == 2/*stderr*/ + && SimHintiS(SimHint_enable_outer, VG_(clo_sim_hints))) + ok = True; + if (!ok) + SET_STATUS_Failure( VKI_EBADF ); + else + PRE_MEM_READ( "write(buf)", ARG2, ARG3 ); +} + +PRE(sys_ftruncate) +{ + *flags |= SfMayBlock; + PRINT("sys_ftruncate ( %ld, %lu, %lu )", ARG1,ARG3,ARG4); + PRE_REG_READ4(long, "ftruncate", unsigned int, fd, int, pad, + unsigned int, length_low, unsigned int, length_high); +} + +PRE(sys_ftruncate7) +{ + *flags |= SfMayBlock; + PRINT("sys_ftruncate ( %ld, %lu, %lu )", ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "ftruncate", unsigned int, fd, + unsigned int, length_low, unsigned int, length_high); +} + +PRE(sys_truncate) +{ + *flags |= SfMayBlock; + PRINT("sys_truncate ( %#lx(%s), %lu, %lu )", ARG1,(char *)ARG1,ARG3,ARG4); + PRE_REG_READ4(long, "truncate", + const char *, path, int, pad, + unsigned int, length_low, unsigned int, length_high); + PRE_MEM_RASCIIZ( "truncate(path)", ARG1 ); +} + +PRE(sys_truncate7) +{ + *flags |= SfMayBlock; + PRINT("sys_truncate ( %#lx(%s), %lu, %lu )", ARG1,(char *)ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "truncate", + const char *, path, + unsigned int, length_low, unsigned int, length_high); + PRE_MEM_RASCIIZ( "truncate(path)", ARG1 ); +} + +PRE(sys_sysarch) +{ + ThreadState *tst; + Int idx; + void **p; + + PRINT("sys_sysarch ( %ld, %#lx )", ARG1, ARG2); + PRE_REG_READ2(int, "sysarch", + int, number, void *, args); + switch (ARG1) { + case VKI_I386_SET_GSBASE: + PRINT("sys_i386_set_gsbase ( %#lx )", ARG2); + PRE_REG_READ1(int, "i386_set_gsbase", void *, base) + + /* On FreeBSD, the syscall loads the %gs selector for us, so do it now. */ + tst = VG_(get_ThreadState)(tid); + p = (void**)ARG2; + tst->arch.vex.guest_GS = (1 << 3) | 3; /* GSEL(GUGS_SEL, SEL_UPL) */ + /* "do" the syscall ourselves; the kernel never sees it */ + idx = 1; + SET_STATUS_from_SysRes( sys_set_thread_area( tid, &idx, *p ) ); + + break; + case VKI_I386_GET_GSBASE: + PRINT("sys_i386_get_gsbase ( %#lx )", ARG2); + PRE_REG_READ1(int, "i386_get_gsbase", void *, basep) + PRE_MEM_WRITE( "i386_get_gsbase(basep)", ARG2, sizeof(void *) ); + + /* "do" the syscall ourselves; the kernel never sees it */ + SET_STATUS_from_SysRes( sys_get_thread_area( tid, 2, (void **)ARG2 ) ); + + if (SUCCESS) { + POST_MEM_WRITE( ARG2, sizeof(void *) ); + } + break; + default: + VG_(message) (Vg_UserMsg, "unhandled sysarch cmd %ld", ARG1); + VG_(unimplemented) ("unhandled sysarch cmd"); + break; + } +} + +#undef PRE +#undef POST + +#endif /* defined(VGP_x86_linux) */ + + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_syswrap/syswrap-x86-openbsd.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coregrind/m_syswrap/syswrap-x86-openbsd.c Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,1160 @@ + +/*--------------------------------------------------------------------*/ +/*--- Platform-specific syscalls stuff. syswrap-x86-linux.c ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2008 Nicholas Nethercote + njn@valgrind.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#if defined(VGP_x86_openbsd) + +/* 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_libcsetjmp.h" // to keep _threadstate.h happy +#include "pub_core_threadstate.h" +#include "pub_core_aspacemgr.h" +#include "pub_core_debuglog.h" +#include "pub_core_libcbase.h" +#include "pub_core_libcassert.h" +#include "pub_core_libcprint.h" +#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_signals.h" +#include "pub_core_syscall.h" +#include "pub_core_syswrap.h" +#include "pub_core_tooliface.h" +#include "pub_core_stacks.h" // VG_(register_stack) + +#include "priv_types_n_macros.h" +#include "priv_syswrap-generic.h" /* for decls of generic wrappers */ +#include "priv_syswrap-openbsd.h" /* for decls of linux-ish wrappers */ +#include "priv_syswrap-main.h" + +/* --------------------------------------------------------------------- + clone() handling + ------------------------------------------------------------------ */ + +/* 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.*/ +__attribute__((noreturn)) +void ML_(call_on_new_stack_0_1) ( Addr stack, + Addr retaddr, + void (*f)(Word), + Word arg1 ); +// 4(%esp) == stack +// 8(%esp) == retaddr +// 12(%esp) == f +// 16(%esp) == arg1 +asm( +".text\n" +".globl vgModuleLocal_call_on_new_stack_0_1\n" +"vgModuleLocal_call_on_new_stack_0_1:\n" +" movl %esp, %esi\n" // remember old stack pointer +" movl 4(%esi), %esp\n" // set stack +" pushl 16(%esi)\n" // arg1 to stack +" pushl 8(%esi)\n" // retaddr to stack +" pushl 12(%esi)\n" // f to stack +" movl $0, %eax\n" // zero all GP regs +" movl $0, %ebx\n" +" movl $0, %ecx\n" +" movl $0, %edx\n" +" movl $0, %esi\n" +" movl $0, %edi\n" +" movl $0, %ebp\n" +" ret\n" // jump to f +" ud2\n" // should never get here +".previous\n" +); + + +#if 0 +/* + Perform a rfork system call. rfork is strange because it has + fork()-like return-twice semantics, so it needs special + handling here. + + Upon entry, we have: + + int (fn)(void*) in 0+FSZ(%esp) + void* child_stack in 4+FSZ(%esp) + int flags in 8+FSZ(%esp) + void* arg in 12+FSZ(%esp) + pid_t* child_tid in 16+FSZ(%esp) + pid_t* parent_tid in 20+FSZ(%esp) + void* tls_ptr in 24+FSZ(%esp) + + System call requires: + + int $__NR_clone in %eax + int flags in %ebx + void* child_stack in %ecx + pid_t* parent_tid in %edx + pid_t* child_tid in %edi + void* tls_ptr in %esi + + Returns an Int encoded in the linux-x86 way, not a SysRes. + */ +#define FSZ "4+4+4+4" /* frame size = retaddr+ebx+edi+esi */ +#define __NR_CLONE VG_STRINGIFY(__NR_clone) +#define __NR_EXIT VG_STRINGIFY(__NR_exit) + +extern +Int do_syscall_clone_x86_openbsd ( Word (*fn)(void *), + void* stack, + Int flags, + void* arg, + Int* child_tid, + Int* parent_tid, + vki_modify_ldt_t * ); +asm( +".text\n" +"do_syscall_clone_x86_openbsd:\n" +" push %ebx\n" +" push %edi\n" +" push %esi\n" + + /* set up child stack with function and arg */ +" movl 4+"FSZ"(%esp), %ecx\n" /* syscall arg2: child stack */ +" movl 12+"FSZ"(%esp), %ebx\n" /* fn arg */ +" movl 0+"FSZ"(%esp), %eax\n" /* fn */ +" lea -8(%ecx), %ecx\n" /* make space on stack */ +" movl %ebx, 4(%ecx)\n" /* fn arg */ +" movl %eax, 0(%ecx)\n" /* fn */ + + /* get other args to clone */ +" movl 8+"FSZ"(%esp), %ebx\n" /* syscall arg1: flags */ +" movl 20+"FSZ"(%esp), %edx\n" /* syscall arg3: parent tid * */ +" movl 16+"FSZ"(%esp), %edi\n" /* syscall arg5: child tid * */ +" movl 24+"FSZ"(%esp), %esi\n" /* syscall arg4: tls_ptr * */ +" movl $"__NR_CLONE", %eax\n" +" int $0x80\n" /* clone() */ +" testl %eax, %eax\n" /* child if retval == 0 */ +" jnz 1f\n" + + /* CHILD - call thread function */ +" popl %eax\n" +" call *%eax\n" /* call fn */ + + /* exit with result */ +" movl %eax, %ebx\n" /* arg1: return value from fn */ +" movl $"__NR_EXIT", %eax\n" +" int $0x80\n" + + /* Hm, exit returned */ +" ud2\n" + +"1:\n" /* PARENT or ERROR */ +" pop %esi\n" +" pop %edi\n" +" pop %ebx\n" +" ret\n" +".previous\n" +); + +#undef FSZ +#undef __NR_CLONE +#undef __NR_EXIT + + +// forward declarations +static void setup_child ( ThreadArchState*, ThreadArchState*, Bool ); + +/* + When a client clones, we need to keep track of the new thread. This means: + 1. allocate a ThreadId+ThreadState+stack for the the thread + + 2. initialize the thread's new VCPU state + + 3. create the thread using the same args as the client requested, + but using the scheduler entrypoint for EIP, and a separate stack + for ESP. + */ +static SysRes do_rfork ( ThreadId ptid, + UInt flags) +{ + static const Bool debug = False; + + Addr esp; + ThreadId ctid = VG_(alloc_ThreadState)(); + ThreadState* ptst = VG_(get_ThreadState)(ptid); + ThreadState* ctst = VG_(get_ThreadState)(ctid); + UWord* stack; + NSegment const* seg; + SysRes res; + Int eax; + vki_sigset_t blockall, savedmask; + + VG_(sigfillset)(&blockall); + + vg_assert(VG_(is_running_thread)(ptid)); + vg_assert(VG_(is_valid_tid)(ctid)); + + stack = (UWord*)ML_(allocstack)(ctid); + if (stack == NULL) { + res = VG_(mk_SysRes_Error)( VKI_ENOMEM ); + goto out; + } + + /* Copy register state + + Both parent and child return to the same place, and the code + following the clone syscall works out which is which, so we + don't need to worry about it. + + The parent gets the child's new tid returned from clone, but the + child gets 0. + + If the clone call specifies a NULL esp for the new thread, then + it actually gets a copy of the parent's esp. + */ + /* Note: the clone call done by the Quadrics Elan3 driver specifies + clone flags of 0xF00, and it seems to rely on the assumption + that the child inherits a copy of the parent's GDT. + setup_child takes care of setting that up. */ + setup_child( &ctst->arch, &ptst->arch, True ); + + /* Make sys_clone appear to have returned Success(0) in the + child. */ + ctst->arch.vex.guest_EAX = 0; + + /* Assume linuxthreads port storing its intended stack in %esi */ + esp = ctst->arch.vex.guest_ESI; + + ctst->os_state.parent = ptid; + + /* inherit signal mask */ + ctst->sig_mask = ptst->sig_mask; + ctst->tmp_sig_mask = ptst->sig_mask; + + /* We don't really know where the client stack is, because its + allocated by the client. The best we can do is look at the + memory mappings and try to derive some useful information. We + assume that esp starts near its highest possible value, and can + only go down to the start of the mmaped segment. */ + seg = VG_(am_find_nsegment)((Addr)esp); + if (seg && seg->kind != SkResvn) { + ctst->client_stack_highest_word = (Addr)VG_PGROUNDUP(esp); + ctst->client_stack_szB = ctst->client_stack_highest_word - seg->start; + + VG_(register_stack)(seg->start, ctst->client_stack_highest_word); + + if (debug) + VG_(printf)("tid %d: guessed client stack range %#lx-%#lx\n", + ctid, seg->start, VG_PGROUNDUP(esp)); + } else { + VG_(message)(Vg_UserMsg, "!? New thread %d starts with ESP(%#lx) unmapped\n", + ctid, esp); + ctst->client_stack_szB = 0; + } + + /* Assume the clone will succeed, and tell any tool that wants to + know that this thread has come into existence. We cannot defer + it beyond this point because sys_set_thread_area, just below, + causes tCheck to assert by making references to the new ThreadId + if we don't state the new thread exists prior to that point. + If the clone 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, ptid, ctid ); + + /* start the thread with everything blocked */ + VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask); + + /* Create the new thread */ + /* XXX need to see what happens with tids etc with rfork */ + eax = do_syscall_clone_x86_openbsd( + ML_(start_thread_NORETURN), stack, flags /*, &VG_(threads)[ctid], NULL*/ ); + res = VG_(mk_SysRes_x86_openbsd)( eax ); /* XXX edx returns too! */ + + VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL); + + out: + if (res.isError) { + /* clone failed */ + VG_(cleanup_thread)(&ctst->arch); + ctst->status = VgTs_Empty; + /* oops. Better tell the tool the thread exited in a hurry :-) */ + VG_TRACK( pre_thread_ll_exit, ctid ); + } + + return res; +} +#endif + +/* Translate a struct modify_ldt_ldt_s to a VexGuestX86SegDescr */ + +static +void translate_to_hw_format ( /* IN */ void* base, + /* OUT */ VexGuestX86SegDescr* out) +{ + UInt entry_1, entry_2; + UInt base_addr = (UInt) base; + vg_assert(8 == sizeof(VexGuestX86SegDescr)); + + if (0) + VG_(printf)("translate_to_hw_format: base %p\n", base ); + + /* Allow LDTs to be cleared by the user. */ + if (base == 0) { + entry_1 = 0; + entry_2 = 0; + goto install; + } + /* base as specified, no limit, read/write/accessed etc */ + entry_1 = ((base_addr & 0x0000ffff) << 16) | 0x0ffff; + entry_2 = (base_addr & 0xff000000) | + ((base_addr & 0x00ff0000) >> 16) | 0x00cff300; + + /* Install the new entry ... */ + install: + out->LdtEnt.Words.word1 = entry_1; + out->LdtEnt.Words.word2 = entry_2; +} + +/* Create a zeroed-out GDT. */ +static VexGuestX86SegDescr* alloc_zeroed_x86_GDT ( void ) +{ + Int nbytes = VEX_GUEST_X86_GDT_NENT * sizeof(VexGuestX86SegDescr); + return VG_(arena_calloc)(VG_AR_CORE, "di.syswrap-x86.azxG.1", nbytes, 1); +} + +#if 0 +/* Create a zeroed-out LDT. */ +static VexGuestX86SegDescr* alloc_zeroed_x86_LDT ( void ) +{ + Int nbytes = VEX_GUEST_X86_LDT_NENT * sizeof(VexGuestX86SegDescr); + return VG_(arena_calloc)(VG_AR_CORE, "di.syswrap-x86.azxL.1", nbytes, 1); +} + +/* Free up an LDT or GDT allocated by the above fns. */ +static void free_LDT_or_GDT ( VexGuestX86SegDescr* dt ) +{ + vg_assert(dt); + VG_(arena_free)(VG_AR_CORE, (void*)dt); +} + +/* Copy contents between two existing LDTs. */ +static void copy_LDT_from_to ( VexGuestX86SegDescr* src, + VexGuestX86SegDescr* dst ) +{ + Int i; + vg_assert(src); + vg_assert(dst); + for (i = 0; i < VEX_GUEST_X86_LDT_NENT; i++) + dst[i] = src[i]; +} + +/* Copy contents between two existing GDTs. */ +static void copy_GDT_from_to ( VexGuestX86SegDescr* src, + VexGuestX86SegDescr* dst ) +{ + Int i; + vg_assert(src); + vg_assert(dst); + for (i = 0; i < VEX_GUEST_X86_GDT_NENT; i++) + dst[i] = src[i]; +} + +/* Free this thread's DTs, if it has any. */ +static void deallocate_LGDTs_for_thread ( VexGuestX86State* vex ) +{ + vg_assert(sizeof(HWord) == sizeof(void*)); + + if (0) + VG_(printf)("deallocate_LGDTs_for_thread: " + "ldt = 0x%x, gdt = 0x%x\n", + vex->guest_LDT, vex->guest_GDT ); + + if (vex->guest_LDT != (HWord)NULL) { + free_LDT_or_GDT( (VexGuestX86SegDescr*)vex->guest_LDT ); + vex->guest_LDT = (HWord)NULL; + } + + if (vex->guest_GDT != (HWord)NULL) { + free_LDT_or_GDT( (VexGuestX86SegDescr*)vex->guest_GDT ); + vex->guest_GDT = (HWord)NULL; + } +} +#endif + +static SysRes sys_set_thread_area ( ThreadId tid, Int *idxptr, void *base) +{ + VexGuestX86SegDescr* gdt; + Int idx; + + vg_assert(8 == sizeof(VexGuestX86SegDescr)); + vg_assert(sizeof(HWord) == sizeof(VexGuestX86SegDescr*)); + + gdt = (VexGuestX86SegDescr*)VG_(threads)[tid].arch.vex.guest_GDT; + + /* If the thread doesn't have a GDT, allocate it now. */ + if (!gdt) { + gdt = alloc_zeroed_x86_GDT(); + VG_(threads)[tid].arch.vex.guest_GDT = (HWord)gdt; + } + + idx = *idxptr; + if (idx == -1) { + /* Find and use the first free entry. Don't allocate entry + zero, because the hardware will never do that, and apparently + doing so confuses some code (perhaps stuff running on + Wine). */ + for (idx = 1; idx < VEX_GUEST_X86_GDT_NENT; idx++) { + if (gdt[idx].LdtEnt.Words.word1 == 0 + && gdt[idx].LdtEnt.Words.word2 == 0) + break; + } + + if (idx == VEX_GUEST_X86_GDT_NENT) + return VG_(mk_SysRes_Error)( VKI_ESRCH ); + } else if (idx < 0 || idx == 0 || idx >= VEX_GUEST_X86_GDT_NENT) { + /* Similarly, reject attempts to use GDT[0]. */ + return VG_(mk_SysRes_Error)( VKI_EINVAL ); + } + + translate_to_hw_format(base, &gdt[idx]); + + *idxptr = idx; + return VG_(mk_SysRes_Success)( 0 ); +} + +static SysRes sys_get_thread_area ( ThreadId tid, Int idx, void ** basep ) +{ + VexGuestX86SegDescr* gdt; + UInt base; + + vg_assert(sizeof(HWord) == sizeof(VexGuestX86SegDescr*)); + vg_assert(8 == sizeof(VexGuestX86SegDescr)); + + gdt = (VexGuestX86SegDescr*)VG_(threads)[tid].arch.vex.guest_GDT; + + /* If the thread doesn't have a GDT, allocate it now. */ + if (!gdt) { + gdt = alloc_zeroed_x86_GDT(); + VG_(threads)[tid].arch.vex.guest_GDT = (HWord)gdt; + } + + base = ( gdt[idx].LdtEnt.Bits.BaseHi << 24 ) | + ( gdt[idx].LdtEnt.Bits.BaseMid << 16 ) | + gdt[idx].LdtEnt.Bits.BaseLow; + *basep = (void *)base; + + return VG_(mk_SysRes_Success)( 0 ); +} + +/* --------------------------------------------------------------------- + More thread stuff + ------------------------------------------------------------------ */ + +void VG_(cleanup_thread) ( ThreadArchState* arch ) +{ +} + + +#if 0 +static void setup_child ( /*OUT*/ ThreadArchState *child, + /*IN*/ ThreadArchState *parent, + Bool inherit_parents_GDT ) +{ + /* We inherit our parent's guest state. */ + child->vex = parent->vex; + child->vex_shadow1 = parent->vex_shadow1; + child->vex_shadow2 = parent->vex_shadow2; + + /* We inherit our parent's LDT. */ + if (parent->vex.guest_LDT == (HWord)NULL) { + /* We hope this is the common case. */ + child->vex.guest_LDT = (HWord)NULL; + } else { + /* No luck .. we have to take a copy of the parent's. */ + child->vex.guest_LDT = (HWord)alloc_zeroed_x86_LDT(); + copy_LDT_from_to( (VexGuestX86SegDescr*)parent->vex.guest_LDT, + (VexGuestX86SegDescr*)child->vex.guest_LDT ); + } + + /* Either we start with an empty GDT (the usual case) or inherit a + copy of our parents' one (Quadrics Elan3 driver -style clone + only). */ + child->vex.guest_GDT = (HWord)NULL; + + if (inherit_parents_GDT && parent->vex.guest_GDT != (HWord)NULL) { + child->vex.guest_GDT = (HWord)alloc_zeroed_x86_GDT(); + copy_GDT_from_to( (VexGuestX86SegDescr*)parent->vex.guest_GDT, + (VexGuestX86SegDescr*)child->vex.guest_GDT ); + } +} +#endif + +/* --------------------------------------------------------------------- + PRE/POST wrappers for x86/Linux-specific syscalls + ------------------------------------------------------------------ */ + +#define PRE(name) DEFN_PRE_TEMPLATE(openbsd, name) +#define POST(name) DEFN_POST_TEMPLATE(openbsd, 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; + + ThreadId ctid = VG_(alloc_ThreadState)(); + ThreadState* ptst = VG_(get_ThreadState)(tid); + ThreadState* ctst = VG_(get_ThreadState)(ctid); + SysRes res; + vki_sigset_t blockall, savedmask; + struct vki_thr_param tp; + Int idx = -1; + Addr stk; + + PRINT("thr_new ( %#lx, %ld )",ARG1,ARG2); + PRE_REG_READ2(int, "thr_new", + struct thr_param *, param, + int, param_size); + + PRE_MEM_READ( "thr_new(param)", ARG1, offsetof(struct vki_thr_param, spare)); + if (!ML_(safe_to_deref)( (void*)ARG1, offsetof(struct vki_thr_param, spare))) { + SET_STATUS_Failure( VKI_EFAULT ); + return; + } + 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)); + + VG_(sigfillset)(&blockall); + + vg_assert(VG_(is_running_thread)(tid)); + vg_assert(VG_(is_valid_tid)(ctid)); + + /* Copy register state + + On linux, both parent and child return to the same place, and the code + following the clone syscall works out which is which, so we + don't need to worry about it. + On FreeBSD, thr_new arranges a direct call. We don't actually need any + of this gunk. + + The parent gets the child's new tid returned from clone, but the + child gets 0. + + If the clone call specifies a NULL rsp for the new thread, then + it actually gets a copy of the parent's rsp. + */ + /* We inherit our parent's guest state. */ + ctst->arch.vex = ptst->arch.vex; + 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 + child. */ + ctst->arch.vex.guest_EAX = 0; + ctst->arch.vex.guest_EDX = 0; + LibVEX_GuestX86_put_eflag_c(0, &ctst->arch.vex); + + ctst->os_state.parent = tid; + + /* inherit signal mask */ + ctst->sig_mask = ptst->sig_mask; + ctst->tmp_sig_mask = ptst->sig_mask; + + /* 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 + 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 ); + + if (debug) + VG_(printf)("clone child has SETTLS: tls at %#lx\n", (Addr)tp.tls_base); + sys_set_thread_area( ctid, &idx, tp.tls_base ); + ctst->arch.vex.guest_GS = (idx << 3) | 3; /* GSEL(GUGS_SEL, SEL_UPL) */ + tp.tls_base = 0; /* Don't have the kernel do it too */ + + /* start the thread with everything blocked */ + VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask); + + /* Set the client state for scheduler to run libthr's trampoline */ + ctst->arch.vex.guest_ESP = (Addr)tp.stack_base + tp.stack_size - 8; + ctst->arch.vex.guest_EIP = (Addr)tp.start_func; + *(UWord *)(ctst->arch.vex.guest_ESP + 4) = (UWord)tp.arg; /* Client arg */ + *(UWord *)(ctst->arch.vex.guest_ESP + 0) = 0; /* fake return addr */ + + /* Set up valgrind's trampoline on its own stack */ + stk = ML_(allocstack)(ctid); + tp.stack_base = (void *)ctst->os_state.valgrind_stack_base; + tp.stack_size = (Addr)stk - (Addr)tp.stack_base; + /* This is for thr_new() to run valgrind's trampoline */ + tp.start_func = (void *)ML_(start_thread_NORETURN); + tp.arg = &VG_(threads)[ctid]; + + /* Create the new thread */ + res = VG_(do_syscall2)(__NR_thr_new, (UWord)&tp, sizeof(tp)); + + VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL); + + if (sr_isError(res)) { + /* clone failed */ + VG_(cleanup_thread)(&ctst->arch); + ctst->status = VgTs_Empty; + /* oops. Better tell the tool the thread exited in a hurry :-) */ + VG_TRACK( pre_thread_ll_exit, ctid ); + } else { + + POST_MEM_WRITE((Addr)tp.parent_tid, sizeof(long)); + POST_MEM_WRITE((Addr)tp.child_tid, sizeof(long)); + POST_MEM_WRITE((Addr)ctst->arch.vex.guest_ESP, 8); + + /* Thread creation was successful; let the child have the chance + to run */ + *flags |= SfYieldAfter; + } + + /* "Complete" the syscall so that the wrapper doesn't call the kernel again. */ + SET_STATUS_from_SysRes(res); +} + + +PRE(sys_rfork) +{ + PRINT("sys_rfork ( %lx )",ARG1); + PRE_REG_READ1(int, "rfork", + unsigned int, flags); + +#if 0 + cloneflags = ARG1; + + if (!ML_(client_signal_OK)(ARG1 & VKI_CSIGNAL)) { + SET_STATUS_Failure( VKI_EINVAL ); + return; + } + + SET_STATUS_from_SysRes( do_clone(tid, ARG1)); + + if (SUCCESS) { + *flags |= SfYieldAfter; + } +#else + VG_(message)(Vg_UserMsg, "No rfork for you!"); + VG_(unimplemented) + ("Valgrind does not support rfork() yet."); + SET_STATUS_Failure( VKI_ENOSYS ); +#endif +} + +PRE(sys_sigreturn) +{ + PRINT("sys_sigreturn ( %#lx )", ARG1); + PRE_REG_READ1(long, "sigreturn", + struct vki_ucontext *, ucp); + + PRE_MEM_READ( "sigreturn(ucp)", ARG1, sizeof(struct vki_ucontext) ); + PRE_MEM_WRITE( "sigreturn(ucp)", ARG1, sizeof(struct vki_ucontext) ); +} + +PRE(sys_fake_sigreturn) +{ + /* See comments on PRE(sys_rt_sigreturn) in syswrap-amd64-linux.c for + an explanation of what follows. */ + + ThreadState* tst; + struct vki_ucontext *uc; + PRINT("sys_sigreturn ( )"); + + 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); /* QQQ should be redundant */ + + uc = (struct vki_ucontext *)ARG1; + if (uc == NULL || uc->uc_mcontext.len != sizeof(uc->uc_mcontext)) { + SET_STATUS_Failure(VKI_EINVAL); + return; + } + + /* 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); + + /* Restore register state from frame and remove it */ + VG_(sigframe_destroy)(tid); + + /* + * Signal handler might have changed the signal mask. Respect that. + */ + tst->sig_mask = uc->uc_sigmask; + tst->tmp_sig_mask = uc->uc_sigmask; + + /* 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); + + /* Check to see if any signals arose as a result of this. */ + *flags |= SfPollAfter; +} + +#if 0 /* QQQ keep for 6.x signals */ +PRE(sys_rt_sigreturn) +{ + /* See comments on PRE(sys_rt_sigreturn) in syswrap-amd64-linux.c for + an explanation of what follows. */ + + ThreadState* tst; + PRINT("sys_rt_sigreturn ( )"); + + 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); + + /* Restore register state from frame and remove it */ + VG_(sigframe_destroy)(tid, True); + + /* 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); + + /* Check to see if any signals arose as a result of this. */ + *flags |= SfPollAfter; +} +#endif + +static void restore_mcontext(ThreadState *tst, struct vki_mcontext *sc) +{ + tst->arch.vex.guest_EAX = sc->eax; + tst->arch.vex.guest_ECX = sc->ecx; + tst->arch.vex.guest_EDX = sc->edx; + tst->arch.vex.guest_EBX = sc->ebx; + tst->arch.vex.guest_EBP = sc->ebp; + tst->arch.vex.guest_ESP = sc->esp; + tst->arch.vex.guest_ESI = sc->esi; + tst->arch.vex.guest_EDI = sc->edi; + tst->arch.vex.guest_EIP = sc->eip; + tst->arch.vex.guest_CS = sc->cs; + tst->arch.vex.guest_SS = sc->ss; + tst->arch.vex.guest_DS = sc->ds; + tst->arch.vex.guest_ES = sc->es; + tst->arch.vex.guest_FS = sc->fs; + tst->arch.vex.guest_GS = sc->gs; + /* + * XXX: missing support for other flags. + */ + if (sc->eflags & 0x0001) + LibVEX_GuestX86_put_eflag_c(1, &tst->arch.vex); + else + LibVEX_GuestX86_put_eflag_c(0, &tst->arch.vex); +} + +static void fill_mcontext(ThreadState *tst, struct vki_mcontext *sc) +{ + sc->eax = tst->arch.vex.guest_EAX; + sc->ecx = tst->arch.vex.guest_ECX; + sc->edx = tst->arch.vex.guest_EDX; + sc->ebx = tst->arch.vex.guest_EBX; + sc->ebp = tst->arch.vex.guest_EBP; + sc->esp = tst->arch.vex.guest_ESP; + sc->esi = tst->arch.vex.guest_ESI; + sc->edi = tst->arch.vex.guest_EDI; + sc->eip = tst->arch.vex.guest_EIP; + sc->cs = tst->arch.vex.guest_CS; + sc->ss = tst->arch.vex.guest_SS; + sc->ds = tst->arch.vex.guest_DS; + sc->es = tst->arch.vex.guest_ES; + sc->fs = tst->arch.vex.guest_FS; + sc->gs = tst->arch.vex.guest_GS; + sc->eflags = LibVEX_GuestX86_get_eflags(&tst->arch.vex); +/* + not yet. + VG_(memcpy)(&sc->fpstate, fpstate, sizeof(*fpstate)); +*/ + sc->fpformat = VKI_FPFMT_NODEV; + sc->ownedfp = VKI_FPOWNED_NONE; + sc->len = sizeof(*sc); + VG_(memset)(sc->spare2, 0, sizeof(sc->spare2)); +} + + +PRE(sys_getcontext) +{ + ThreadState* tst; + struct vki_ucontext *uc; + + PRINT("sys_getcontext ( %#lx )", ARG1); + PRE_REG_READ1(long, "getcontext", + struct vki_ucontext *, ucp); + PRE_MEM_WRITE( "getcontext(ucp)", ARG1, sizeof(struct vki_ucontext) ); + uc = (struct vki_ucontext *)ARG1; + if (uc == NULL) { + SET_STATUS_Failure(VKI_EINVAL); + return; + } + tst = VG_(get_ThreadState)(tid); + fill_mcontext(tst, &uc->uc_mcontext); + uc->uc_mcontext.eax = 0; + uc->uc_mcontext.edx = 0; + uc->uc_mcontext.eflags &= ~0x0001; /* PSL_C */ + uc->uc_sigmask = tst->sig_mask; + VG_(memset)(uc->__spare__, 0, sizeof(uc->__spare__)); + SET_STATUS_Success(0); +} + +PRE(sys_setcontext) +{ + ThreadState* tst; + struct vki_ucontext *uc; + + PRINT("sys_setcontext ( %#lx )", ARG1); + PRE_REG_READ1(long, "setcontext", + struct vki_ucontext *, ucp); + + PRE_MEM_READ( "setcontext(ucp)", ARG1, sizeof(struct vki_ucontext) ); + PRE_MEM_WRITE( "setcontext(ucp)", ARG1, sizeof(struct vki_ucontext) ); + + vg_assert(VG_(is_valid_tid)(tid)); + vg_assert(tid >= 1 && tid < VG_N_THREADS); + vg_assert(VG_(is_running_thread)(tid)); + + tst = VG_(get_ThreadState)(tid); + uc = (struct vki_ucontext *)ARG1; + if (uc == NULL || uc->uc_mcontext.len != sizeof(uc->uc_mcontext)) { + SET_STATUS_Failure(VKI_EINVAL); + return; + } + + restore_mcontext(tst, &uc->uc_mcontext); + tst->sig_mask = uc->uc_sigmask; + + /* 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); + + /* Check to see if some any signals arose as a result of this. */ + *flags |= SfPollAfter; +} + +PRE(sys_swapcontext) +{ + struct vki_ucontext *ucp, *oucp; + ThreadState* tst; + + PRINT("sys_swapcontext ( %#lx, %#lx )", ARG1, ARG2); + PRE_REG_READ2(long, "swapcontext", + struct vki_ucontext *, oucp, struct vki_ucontext *, ucp); + + PRE_MEM_READ( "swapcontext(ucp)", ARG2, sizeof(struct vki_ucontext) ); + PRE_MEM_WRITE( "swapcontext(oucp)", ARG1, sizeof(struct vki_ucontext) ); + + oucp = (struct vki_ucontext *)ARG1; + ucp = (struct vki_ucontext *)ARG2; + if (oucp == NULL || ucp == NULL || ucp->uc_mcontext.len != sizeof(ucp->uc_mcontext)) { + SET_STATUS_Failure(VKI_EINVAL); + return; + } + tst = VG_(get_ThreadState)(tid); + + /* + * Save the context. + */ + fill_mcontext(tst, &oucp->uc_mcontext); + oucp->uc_mcontext.eax = 0; + oucp->uc_mcontext.edx = 0; + oucp->uc_mcontext.eflags &= ~0x0001; /* PSL_C */ + oucp->uc_sigmask = tst->sig_mask; + VG_(memset)(oucp->__spare__, 0, sizeof(oucp->__spare__)); + + /* + * Switch to new one. + */ + restore_mcontext(tst, &ucp->uc_mcontext); + tst->sig_mask = ucp->uc_sigmask; + + /* 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); + + /* Check to see if some any signals arose as a result of this. */ + *flags |= SfPollAfter; +} + +/* This is here because on x86 the off_t is passed in 2 regs. Don't ask about pad. */ + +/* caddr_t mmap(caddr_t addr, size_t len, int prot, int flags, int fd, int pad, off_t pos); */ +/* ARG1 ARG2 ARG3 ARG4 ARG5 ARG6 ARG7+ARG8 */ + +PRE(sys_mmap) +{ + SysRes r; + + PRINT("sys_mmap ( %#lx, %lu, %ld, %ld, %ld, pad%ld, lo0x%lx hi0x%lx)", + ARG1, (UWord)ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8 ); + PRE_REG_READ8(long, "mmap", + char *, addr, unsigned long, len, int, prot, int, flags, + int, fd, int, pad, unsigned long, lo, unsigned long, hi); + + r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG7 + ((Off64T)ARG8 << 32) ); + SET_STATUS_from_SysRes(r); +} + +PRE(sys_mmap7) +{ + SysRes r; + + PRINT("sys_mmap ( %#lx, %lu, %ld, %ld, %ld, lo0x%lx hi0x%lx)", + ARG1, (UWord)ARG2, ARG3, ARG4, ARG5, ARG6, ARG7 ); + PRE_REG_READ7(long, "mmap", + char *, addr, unsigned long, len, int, prot, int, flags, + int, fd, unsigned long, lo, unsigned long, hi); + + r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 + ((Off64T)ARG7 << 32) ); + SET_STATUS_from_SysRes(r); +} + +PRE(sys_lseek) +{ + PRINT("sys_lseek ( %ld, 0x%lx, 0x%lx, %ld )", ARG1,ARG3,ARG4,ARG5); + PRE_REG_READ5(long, "lseek", + unsigned int, fd, int, pad, unsigned int, offset_low, + unsigned int, offset_high, unsigned int, whence); +} + +PRE(sys_lseek7) +{ + PRINT("sys_lseek ( %ld, 0x%lx, 0x%lx, %ld )", ARG1,ARG2,ARG3,ARG4); + PRE_REG_READ4(long, "lseek", + unsigned int, fd, unsigned int, offset_low, + unsigned int, offset_high, unsigned int, whence); +} + +PRE(sys_pread) +{ + *flags |= SfMayBlock; + PRINT("sys_read ( %ld, %#lx, %lu, %lu, %lu )", ARG1, ARG2, ARG3, ARG5, ARG6); + PRE_REG_READ6(ssize_t, "read", + unsigned int, fd, char *, buf, vki_size_t, count, + int, pad, unsigned int, off_low, unsigned int, off_high); + + if (!ML_(fd_allowed)(ARG1, "read", tid, False)) + SET_STATUS_Failure( VKI_EBADF ); + else + PRE_MEM_WRITE( "read(buf)", ARG2, ARG3 ); +} + +POST(sys_pread) +{ + vg_assert(SUCCESS); + POST_MEM_WRITE( ARG2, RES ); +} + +PRE(sys_pread7) +{ + *flags |= SfMayBlock; + PRINT("sys_read ( %ld, %#lx, %lu, %lu, %lu )", ARG1, ARG2, ARG3, ARG4, ARG5); + PRE_REG_READ5(ssize_t, "read", + unsigned int, fd, char *, buf, vki_size_t, count, + unsigned int, off_low, unsigned int, off_high); + + if (!ML_(fd_allowed)(ARG1, "read", tid, False)) + SET_STATUS_Failure( VKI_EBADF ); + else + PRE_MEM_WRITE( "read(buf)", ARG2, ARG3 ); +} + +POST(sys_pread7) +{ + vg_assert(SUCCESS); + POST_MEM_WRITE( ARG2, RES ); +} + +PRE(sys_pwrite) +{ + Bool ok; + *flags |= SfMayBlock; + PRINT("sys_write ( %ld, %#lx, %lu, %lu, %lu )", ARG1, ARG2, ARG3, ARG5, ARG6); + PRE_REG_READ6(ssize_t, "write", + unsigned int, fd, const char *, buf, vki_size_t, count, + int, pad, unsigned int, off_low, unsigned int, off_high); + /* check to see if it is allowed. If not, try for an exemption from + --sim-hints=enable-outer (used for self hosting). */ + ok = ML_(fd_allowed)(ARG1, "write", tid, False); + if (!ok && ARG1 == 2/*stderr*/ + && SimHintiS(SimHint_enable_outer, VG_(clo_sim_hints))) + ok = True; + if (!ok) + SET_STATUS_Failure( VKI_EBADF ); + else + PRE_MEM_READ( "write(buf)", ARG2, ARG3 ); +} + +PRE(sys_pwrite7) +{ + Bool ok; + *flags |= SfMayBlock; + PRINT("sys_write ( %ld, %#lx, %lu, %lu, %lu )", ARG1, ARG2, ARG3, ARG4, ARG5); + PRE_REG_READ5(ssize_t, "write", + unsigned int, fd, const char *, buf, vki_size_t, count, + unsigned int, off_low, unsigned int, off_high); + /* check to see if it is allowed. If not, try for an exemption from + --sim-hints=enable-outer (used for self hosting). */ + ok = ML_(fd_allowed)(ARG1, "write", tid, False); + if (!ok && ARG1 == 2/*stderr*/ + && SimHintiS(SimHint_enable_outer, VG_(clo_sim_hints))) + ok = True; + if (!ok) + SET_STATUS_Failure( VKI_EBADF ); + else + PRE_MEM_READ( "write(buf)", ARG2, ARG3 ); +} + +PRE(sys_ftruncate) +{ + *flags |= SfMayBlock; + PRINT("sys_ftruncate ( %ld, %lu, %lu )", ARG1,ARG3,ARG4); + PRE_REG_READ4(long, "ftruncate", unsigned int, fd, int, pad, + unsigned int, length_low, unsigned int, length_high); +} + +PRE(sys_ftruncate7) +{ + *flags |= SfMayBlock; + PRINT("sys_ftruncate ( %ld, %lu, %lu )", ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "ftruncate", unsigned int, fd, + unsigned int, length_low, unsigned int, length_high); +} + +PRE(sys_truncate) +{ + *flags |= SfMayBlock; + PRINT("sys_truncate ( %#lx(%s), %lu, %lu )", ARG1,(char *)ARG1,ARG3,ARG4); + PRE_REG_READ4(long, "truncate", + const char *, path, int, pad, + unsigned int, length_low, unsigned int, length_high); + PRE_MEM_RASCIIZ( "truncate(path)", ARG1 ); +} + +PRE(sys_truncate7) +{ + *flags |= SfMayBlock; + PRINT("sys_truncate ( %#lx(%s), %lu, %lu )", ARG1,(char *)ARG1,ARG2,ARG3); + PRE_REG_READ3(long, "truncate", + const char *, path, + unsigned int, length_low, unsigned int, length_high); + PRE_MEM_RASCIIZ( "truncate(path)", ARG1 ); +} + +PRE(sys_sysarch) +{ + ThreadState *tst; + Int idx; + void **p; + + PRINT("sys_sysarch ( %ld, %#lx )", ARG1, ARG2); + PRE_REG_READ2(int, "sysarch", + int, number, void *, args); + switch (ARG1) { + case VKI_I386_SET_GSBASE: + PRINT("sys_i386_set_gsbase ( %#lx )", ARG2); + PRE_REG_READ1(int, "i386_set_gsbase", void *, base) + + /* On FreeBSD, the syscall loads the %gs selector for us, so do it now. */ + tst = VG_(get_ThreadState)(tid); + p = (void**)ARG2; + tst->arch.vex.guest_GS = (1 << 3) | 3; /* GSEL(GUGS_SEL, SEL_UPL) */ + /* "do" the syscall ourselves; the kernel never sees it */ + idx = 1; + SET_STATUS_from_SysRes( sys_set_thread_area( tid, &idx, *p ) ); + + break; + case VKI_I386_GET_GSBASE: + PRINT("sys_i386_get_gsbase ( %#lx )", ARG2); + PRE_REG_READ1(int, "i386_get_gsbase", void *, basep) + PRE_MEM_WRITE( "i386_get_gsbase(basep)", ARG2, sizeof(void *) ); + + /* "do" the syscall ourselves; the kernel never sees it */ + SET_STATUS_from_SysRes( sys_get_thread_area( tid, 2, (void **)ARG2 ) ); + + if (SUCCESS) { + POST_MEM_WRITE( ARG2, sizeof(void *) ); + } + break; + default: + VG_(message) (Vg_UserMsg, "unhandled sysarch cmd %ld", ARG1); + VG_(unimplemented) ("unhandled sysarch cmd"); + break; + } +} + +#undef PRE +#undef POST + +#endif /* defined(VGP_x86_linux) */ + + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_trampoline.S --- a/coregrind/m_trampoline.S Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_trampoline.S Thu Mar 31 15:57:55 2016 +0900 @@ -829,6 +829,120 @@ # undef UD2_1024 # undef UD2_PAGE +/*---------------- x86-freebsd ----------------*/ +#else +#if defined(VGP_x86_freebsd) + +.global VG_(trampoline_stuff_start) +VG_(trampoline_stuff_start): + +.global VG_(x86_freebsd_SUBST_FOR_sigreturn) +VG_(x86_freebsd_SUBST_FOR_sigreturn): + lea 0x14(%esp), %eax /* args to sigreturn(ucontext_t *) */ + pushl %eax + pushl %eax /* fake return addr */ +/* movl 0x44(%eax), %gs ; restore %gs, not done by sigreturn */ + movl $__NR_fake_sigreturn, %eax + int $0x80 + ud2 + +.global VG_(trampoline_stuff_end) +VG_(trampoline_stuff_end): + +#else +#if defined(VGP_amd64_freebsd) + +# define UD2_16 ud2 ; ud2 ; ud2 ; ud2 ;ud2 ; ud2 ; ud2 ; ud2 +# define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16 +# define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64 +# define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256 +# define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024 + + /* a leading page of unexecutable code */ + UD2_PAGE + +.global VG_(trampoline_stuff_start) +VG_(trampoline_stuff_start): + +.global VG_(amd64_freebsd_SUBST_FOR_sigreturn) +VG_(amd64_freebsd_SUBST_FOR_sigreturn): + /* This is a very specific sequence which GDB uses to + recognize signal handler frames. */ + movq $__NR_fake_sigreturn, %rax + movq %rsp, %rdi + addq $40,%rdi + syscall + ud2 + +.global VG_(trampoline_stuff_end) +VG_(trampoline_stuff_end): + + /* and a trailing page of unexecutable code */ + UD2_PAGE + +# undef UD2_16 +# undef UD2_64 +# undef UD2_256 +# undef UD2_1024 +# undef UD2_PAGE + +/*---------------- x86-openbsd ----------------*/ +#else +#if defined(VGP_x86_openbsd) + +.global VG_(trampoline_stuff_start) +VG_(trampoline_stuff_start): + +.global VG_(x86_openbsd_SUBST_FOR_sigreturn) +VG_(x86_openbsd_SUBST_FOR_sigreturn): + lea 0x14(%esp), %eax /* args to sigreturn(ucontext_t *) */ + pushl %eax + pushl %eax /* fake return addr */ +/* movl 0x44(%eax), %gs ; restore %gs, not done by sigreturn */ + movl $__NR_fake_sigreturn, %eax + int $0x80 + ud2 + +.global VG_(trampoline_stuff_end) +VG_(trampoline_stuff_end): + +#else +#if defined(VGP_amd64_openbsd) + +# define UD2_16 ud2 ; ud2 ; ud2 ; ud2 ;ud2 ; ud2 ; ud2 ; ud2 +# define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16 +# define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64 +# define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256 +# define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024 + + /* a leading page of unexecutable code */ + UD2_PAGE + +.global VG_(trampoline_stuff_start) +VG_(trampoline_stuff_start): + +.global VG_(amd64_openbsd_SUBST_FOR_sigreturn) +VG_(amd64_openbsd_SUBST_FOR_sigreturn): + /* This is a very specific sequence which GDB uses to + recognize signal handler frames. */ + movq $__NR_fake_sigreturn, %rax + movq %rsp, %rdi + addq $40, %rdi + syscall + ud2 + +.global VG_(trampoline_stuff_end) +VG_(trampoline_stuff_end): + + /* and a trailing page of unexecutable code */ + UD2_PAGE + +# undef UD2_16 +# undef UD2_64 +# undef UD2_256 +# undef UD2_1024 +# undef UD2_PAGE + /*---------------- x86-darwin ----------------*/ #else #if defined(VGP_x86_darwin) @@ -1344,6 +1458,10 @@ #endif #endif #endif +#endif +#endif +#endif +#endif #if defined(VGO_linux) /* Let the linker know we don't need an executable stack */ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_translate.c --- a/coregrind/m_translate.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_translate.c Thu Mar 31 15:57:55 2016 +0900 @@ -1579,6 +1579,9 @@ # if defined(VGP_amd64_linux) vex_abiinfo.guest_amd64_assume_fs_is_zero = True; # endif +# if defined(VGP_amd64_freebsd) || defined(VGP_amd64_openbsd) + vex_abiinfo.guest_amd64_assume_fs_is_zero = True; +# endif # if defined(VGP_amd64_darwin) vex_abiinfo.guest_amd64_assume_gs_is_0x60 = True; # endif diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_ume/elf.c --- a/coregrind/m_ume/elf.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_ume/elf.c Thu Mar 31 15:57:55 2016 +0900 @@ -28,7 +28,7 @@ The GNU General Public License is contained in the file COPYING. */ -#if defined(VGO_linux) +#if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd) #include "pub_core_basics.h" #include "pub_core_vki.h" @@ -41,6 +41,7 @@ #include "pub_core_libcfile.h" // VG_(open) et al #include "pub_core_machine.h" // VG_ELF_CLASS (XXX: which should be moved) #include "pub_core_mallocfree.h" // VG_(malloc), VG_(free) +#include "pub_core_vkiscnums.h" #include "pub_core_syscall.h" // VG_(strerror) #include "pub_core_ume.h" // self @@ -50,7 +51,11 @@ #define _GNU_SOURCE #define _FILE_OFFSET_BITS 64 /* This is for ELF types etc, and also the AT_ constants. */ +#if !defined(VGO_openbsd) #include +#else +#include +#endif /* --- !!! --- EXTERNAL HEADERS end --- !!! --- */ @@ -160,22 +165,38 @@ Int i; SysRes res; ESZ(Addr) elfbrk = 0; + ESZ(Word) mapsize; + ESZ(Addr) base_offset, base_vaddr, base_vlimit, baseaddr; + ESZ(Phdr) *ph0, *phlast; - for (i = 0; i < e->e.e_phnum; i++) { + if (e->e.e_phnum < 1) { + VG_(printf)("valgrind: m_ume.c: too few sections\n"); + return 1; + } + + /* Map the entire address space of the object. */ + ph0 = NULL; + phlast = NULL; + for (i = 1; i < e->e.e_phnum; i++) { ESZ(Phdr) *ph = &e->p[i]; - ESZ(Addr) addr, brkaddr; - ESZ(Word) memsz; - if (ph->p_type != PT_LOAD) continue; - - addr = ph->p_vaddr+base; - memsz = ph->p_memsz; - brkaddr = addr+memsz; - - if (brkaddr > elfbrk) - elfbrk = brkaddr; + if (ph0 == NULL) + ph0 = ph; + if (phlast == NULL || ph->p_vaddr > phlast->p_vaddr) + phlast = &e->p[i]; } + if (ph0 == NULL || phlast == NULL) { + VG_(printf)("valgrind: m_ume.c: too few loadable sections\n"); + return 1; + } + base_offset = VG_PGROUNDDN(ph0->p_offset); + base_vaddr = VG_PGROUNDDN(ph0->p_vaddr); + base_vlimit = VG_PGROUNDUP(phlast->p_vaddr + phlast->p_memsz); + mapsize = base_vlimit - base_vaddr; + baseaddr = VG_PGROUNDDN(ph0->p_vaddr + base); + res = VG_(am_mmap_anon_fixed_client)(baseaddr, mapsize, VKI_PROT_NONE); + check_mmap(res, baseaddr, mapsize); for (i = 0; i < e->e.e_phnum; i++) { ESZ(Phdr) *ph = &e->p[i]; @@ -199,12 +220,9 @@ memsz = ph->p_memsz; brkaddr = addr+memsz; - // Tom says: In the following, do what the Linux kernel does and only - // map the pages that are required instead of rounding everything to - // the specified alignment (ph->p_align). (AMD64 doesn't work if you - // use ph->p_align -- part of stage2's memory gets trashed somehow.) - // - // The condition handles the case of a zero-length segment. + if (brkaddr > elfbrk) + elfbrk = brkaddr; + if (VG_PGROUNDUP(bss)-VG_PGROUNDDN(addr) > 0) { if (0) VG_(debugLog)(0,"ume","mmap_file_fixed_client #1\n"); res = VG_(am_mmap_file_fixed_client)( @@ -222,23 +240,38 @@ if (memsz > filesz) { UInt bytes; - bytes = VG_PGROUNDUP(brkaddr)-VG_PGROUNDUP(bss); + bytes = VG_PGROUNDUP(bss) - bss; if (bytes > 0) { - if (0) VG_(debugLog)(0,"ume","mmap_anon_fixed_client #2\n"); - res = VG_(am_mmap_anon_fixed_client)( - VG_PGROUNDUP(bss), bytes, - prot - ); - if (0) VG_(am_show_nsegments)(0,"after #2"); - check_mmap(res, VG_PGROUNDUP(bss), bytes); + /* Make sure the end of the segment is writable */ + if ((prot & VKI_PROT_WRITE) == 0) { + res = VG_(am_do_mprotect_NO_NOTIFY)((UWord)VG_PGROUNDDN(bss), VKI_PAGE_SIZE, + prot|VKI_PROT_WRITE); + if (sr_isError(res)) { + VG_(printf)("valgrind: m_ume.c: mprotect failed\n"); + return (1); + } + } + VG_(memset)((char *)bss, 0, bytes); + /* Reset the data protection back */ + if ((prot & VKI_PROT_WRITE) == 0) { + res = VG_(am_do_mprotect_NO_NOTIFY)((UWord)VG_PGROUNDDN(bss), VKI_PAGE_SIZE, + prot); + if (sr_isError(res)) { + VG_(printf)("valgrind: m_ume.c: mprotect failed\n"); + return (1); + } + } } - bytes = bss & (VKI_PAGE_SIZE - 1); - - // The 'prot' condition allows for a read-only bss - if ((prot & VKI_PROT_WRITE) && (bytes > 0)) { - bytes = VKI_PAGE_SIZE - bytes; - VG_(memset)((void *)bss, 0, bytes); + /* Overlay the BSS segment onto the proper region. */ + if (VG_PGROUNDUP(brkaddr) > VG_PGROUNDUP(bss)) { + res = VG_(am_do_mprotect_NO_NOTIFY)((UWord)VG_PGROUNDUP(bss), + VG_PGROUNDUP(brkaddr) - VG_PGROUNDUP(bss), prot); + if (sr_isError(res)) { + VG_(printf)("valgrind: m_ume.c: mprotect failed\n"); + return (1); + } + VG_(am_notify_mprotect)((Addr)VG_PGROUNDUP(bss), VG_PGROUNDUP(brkaddr) - VG_PGROUNDUP(bss), prot); } } } @@ -376,6 +409,15 @@ VG_(pread)(fd, buf, ph->p_filesz, ph->p_offset); buf[ph->p_filesz] = '\0'; +#if defined(VGP_x86_freebsd) + sres._isError = True; + /* Hack. FreeBSD's kernel overloads the interpreter name. */ + if (VG_(strcmp)(buf, "/libexec/ld-elf.so.1") == 0 || + VG_(strcmp)(buf, "/usr/libexec/ld-elf.so.1") == 0) { + sres = VG_(open)("/libexec/ld-elf32.so.1", VKI_O_RDONLY, 0); + } + if (sr_isError(sres)) +#endif sres = VG_(open)(buf, VKI_O_RDONLY, 0); if (sr_isError(sres)) { VG_(printf)("valgrind: m_ume.c: can't open interpreter\n"); @@ -529,7 +571,7 @@ return 0; } -#endif // defined(VGO_linux) +#endif // defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd) /*--------------------------------------------------------------------*/ /*--- end ---*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_ume/main.c --- a/coregrind/m_ume/main.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_ume/main.c Thu Mar 31 15:57:55 2016 +0900 @@ -51,7 +51,7 @@ } ExeHandler; static ExeHandler exe_handlers[] = { -# if defined(VGO_linux) +# if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd) { VG_(match_ELF), VG_(load_ELF) }, # elif defined(VGO_darwin) { VG_(match_macho), VG_(load_macho) }, @@ -80,6 +80,20 @@ } fd = sr_Res(res); +#if defined(VGO_openbsd) + extern Int VG_(fd_hard_limit); + void ML_(record_fd_open_with_given_name)(ThreadId tid, Int fd, char *pathname); + + // Track opened files by Valgrind so that we can look up filenames for mapped + // vnodes via the recorded table, instead of relying on procfs or kvm. This is + // possible as all executables and related files (dynamic linkder etc.) are all + // opened by host (Valgrind). + VG_(fd_hard_limit) = 10; + ML_(record_fd_open_with_given_name)(-1, fd, exe_name); + ML_(mark_fd_as_internal)(-1, fd); + VG_(fd_hard_limit) = -1; +#endif + // Check we have execute permissions ret = VG_(check_executable)(&is_setuid, exe_name, allow_setuid); if (0 != ret) { diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_ume/priv_ume.h --- a/coregrind/m_ume/priv_ume.h Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_ume/priv_ume.h Thu Mar 31 15:57:55 2016 +0900 @@ -27,7 +27,7 @@ The GNU General Public License is contained in the file COPYING. */ -#if defined(VGO_linux) || defined(VGO_darwin) +#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd) || defined(VGO_openbsd) #ifndef __PRIV_UME_H #define __PRIV_UME_H @@ -36,7 +36,7 @@ extern int VG_(do_exec_inner)(const HChar *exe, ExeInfo *info); -#if defined(VGO_linux) +#if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd) extern Bool VG_(match_ELF) ( const void *hdr, Int len ); extern Int VG_(load_ELF) ( Int fd, const HChar *name, ExeInfo *info ); #elif defined(VGO_darwin) diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_vki.c --- a/coregrind/m_vki.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_vki.c Thu Mar 31 15:57:55 2016 +0900 @@ -69,14 +69,16 @@ vki_sigset_t set; // Set's size must agree with _VKI_NSIG vg_assert( 8 * sizeof(set) == _VKI_NSIG ); +#if 0 // Set's word size must agree with _VKI_NSIG_BPW vg_assert( 8 * sizeof(set.sig[0]) == _VKI_NSIG_BPW ); // The set elements are 32- or 64-bit vg_assert( _VKI_NSIG_BPW == 32 || _VKI_NSIG_BPW == 64 ); +#endif /* --- Platform-specific checks on signal sets --- */ -# if defined(VGO_linux) +# if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd) /* nothing to check */ # elif defined(VGP_x86_darwin) || defined(VGP_amd64_darwin) vg_assert(_VKI_NSIG == NSIG); @@ -90,7 +92,7 @@ /* --- Platform-specific checks on sigactions --- */ -# if defined(VGO_linux) +# if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd) /* the toK- and fromK- forms are identical */ vg_assert( sizeof(vki_sigaction_toK_t) == sizeof(vki_sigaction_fromK_t) ); diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/m_vkiscnums.c --- a/coregrind/m_vkiscnums.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/m_vkiscnums.c Thu Mar 31 15:57:55 2016 +0900 @@ -53,6 +53,26 @@ } //--------------------------------------------------------------------------- +#elif defined(VGO_freebsd) || defined(VGO_openbsd) +//--------------------------------------------------------------------------- + +const HChar* VG_(sysnum_string)(Word sysnum, SizeT n_buf, HChar* buf) +{ + if (buf == NULL) { + static HChar _buf[20+1]; // large enough + buf = _buf; + n_buf = 20+1; + } + VG_(snprintf)(buf, n_buf, "%3ld", sysnum); + return buf; +} + +const HChar* VG_(sysnum_string_extra)(Word sysnum, SizeT n_buf, HChar* buf) +{ + return VG_(sysnum_string)(sysnum, n_buf, buf); +} + +//--------------------------------------------------------------------------- #elif defined(VGO_darwin) //--------------------------------------------------------------------------- diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/pub_core_aspacemgr.h --- a/coregrind/pub_core_aspacemgr.h Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/pub_core_aspacemgr.h Thu Mar 31 15:57:55 2016 +0900 @@ -182,6 +182,9 @@ specified address range. */ extern Bool VG_(am_notify_client_shmat)( Addr a, SizeT len, UInt prot ); +extern SysRes VG_(am_do_mprotect_NO_NOTIFY) + ( Addr start, SizeT length, UInt prot); + /* Notifies aspacem that an mprotect was completed successfully. The segment array is updated accordingly. Note, as with VG_(am_notify_munmap), it is not the job of this function to reject diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/pub_core_debuginfo.h --- a/coregrind/pub_core_debuginfo.h Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/pub_core_debuginfo.h Thu Mar 31 15:57:55 2016 +0900 @@ -62,7 +62,7 @@ released by simply re-opening and closing the same file (even via different fd!). */ -#if defined(VGO_linux) || defined(VGO_darwin) +#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd) || defined(VGO_openbsd) extern ULong VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV, Int use_fd ); extern void VG_(di_notify_munmap)( Addr a, SizeT len ); diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/pub_core_initimg.h --- a/coregrind/pub_core_initimg.h Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/pub_core_initimg.h Thu Mar 31 15:57:55 2016 +0900 @@ -40,25 +40,6 @@ // lot of work on Linux (ELF). //-------------------------------------------------------------------- -/* These are OS-specific and defined below. */ -typedef struct _IICreateImageInfo IICreateImageInfo; -typedef struct _IIFinaliseImageInfo IIFinaliseImageInfo; - -/* This is a two stage process. The first stage, which is most of the - work, creates the initial image in memory to the extent possible. - To do this it takes a bundle of information in an IICreateImageInfo - structure, which is gathered in an OS-specific way at startup. - This returns an IIFinaliseImageInfo structure: */ -extern -IIFinaliseImageInfo VG_(ii_create_image)( IICreateImageInfo ); - -/* Just before starting the client, we may need to make final - adjustments to its initial image. Also we need to set up the VEX - guest state for thread 1 (the root thread) and copy in essential - starting values. This is handed the IIFinaliseImageInfo created by - VG_(ii_create_image). */ -extern -void VG_(ii_finalise_image)( IIFinaliseImageInfo ); /* Note that both IICreateImageInfo and IIFinaliseImageInfo are OS-specific. We now go on to give instantiations of them @@ -66,7 +47,7 @@ /* ------------------------- Linux ------------------------- */ -#if defined(VGO_linux) +#if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd) struct _IICreateImageInfo { /* ------ Mandatory fields ------ */ @@ -123,6 +104,25 @@ #endif +typedef struct _IICreateImageInfo IICreateImageInfo; +typedef struct _IIFinaliseImageInfo IIFinaliseImageInfo; + +/* This is a two stage process. The first stage, which is most of the + work, creates the initial image in memory to the extent possible. + To do this it takes a bundle of information in an IICreateImageInfo + structure, which is gathered in an OS-specific way at startup. + This returns an IIFinaliseImageInfo structure: */ +extern +IIFinaliseImageInfo VG_(ii_create_image)( IICreateImageInfo ); + +/* Just before starting the client, we may need to make final + adjustments to its initial image. Also we need to set up the VEX + guest state for thread 1 (the root thread) and copy in essential + starting values. This is handed the IIFinaliseImageInfo created by + VG_(ii_create_image). */ +extern +void VG_(ii_finalise_image)( IIFinaliseImageInfo ); + #endif // __PUB_CORE_INITIMG_H /*--------------------------------------------------------------------*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/pub_core_libcproc.h --- a/coregrind/pub_core_libcproc.h Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/pub_core_libcproc.h Thu Mar 31 15:57:55 2016 +0900 @@ -84,6 +84,14 @@ extern void VG_(do_atfork_parent) ( ThreadId tid ); extern void VG_(do_atfork_child) ( ThreadId tid ); +#if defined(VGO_freebsd) || defined(VGO_openbsd) +// 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_(getosreldate)(void); +extern Bool VG_(is32on64)(void); +#endif + // icache invalidation extern void VG_(invalidate_icache) ( void *ptr, SizeT nbytes ); diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/pub_core_machine.h --- a/coregrind/pub_core_machine.h Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/pub_core_machine.h Thu Mar 31 15:57:55 2016 +0900 @@ -41,12 +41,12 @@ #include "pub_core_basics.h" // UnwindStartRegs // XXX: this is *really* the wrong spot for these things -#if defined(VGP_x86_linux) +#if defined(VGP_x86_linux) || defined(VGP_x86_freebsd) || defined(VGP_x86_openbsd) # define VG_ELF_DATA2XXX ELFDATA2LSB # define VG_ELF_MACHINE EM_386 # define VG_ELF_CLASS ELFCLASS32 # undef VG_PLAT_USES_PPCTOC -#elif defined(VGP_amd64_linux) +#elif defined(VGP_amd64_linux) || defined(VGP_amd64_freebsd) || defined(VGP_amd64_openbsd) # define VG_ELF_DATA2XXX ELFDATA2LSB # define VG_ELF_MACHINE EM_X86_64 # define VG_ELF_CLASS ELFCLASS64 diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/pub_core_mallocfree.h --- a/coregrind/pub_core_mallocfree.h Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/pub_core_mallocfree.h Thu Mar 31 15:57:55 2016 +0900 @@ -79,6 +79,10 @@ defined(VGP_mips64_linux) || \ defined(VGP_x86_darwin) || \ defined(VGP_amd64_darwin) || \ + defined(VGP_x86_freebsd) || \ + defined(VGP_amd64_freebsd) || \ + defined(VGP_x86_openbsd) || \ + defined(VGP_amd64_openbsd) || \ defined(VGP_arm64_linux) # define VG_MIN_MALLOC_SZB 16 #else diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/pub_core_proc.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/coregrind/pub_core_proc.h Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,19 @@ +#ifndef __PUB_CORE_PROC_H +#define __PUB_CORE_PROC_H + +extern void VG_(procmap)( char *, int * ); + +// XXX Move these to coregrind/m_proc/priv_proc.h? +extern vki_kvm_t *VG_(kvm_open) ( const char *uf, const char *mf, const char *sf, int flag, const char *program ); +extern vki_kvm_t *VG_(kvm_openfiles) ( const char *uf, const char *mf, const char *sf, int flag, char *errout ); +extern ssize_t VG_(kvm_read) ( vki_kvm_t *, unsigned long, void *, SizeT ); +extern char *VG_(kvm_geterr)( vki_kvm_t * ); +extern struct vki_kinfo_proc *VG_(kvm_getprocs) ( vki_kvm_t *, int, int, SizeT, int * ); +extern int VG_(kvm_nlist) ( vki_kvm_t *, struct vki_nlist * ); +extern int VG_(kvm_close) ( vki_kvm_t * ); + +extern int VG_(__fdnlist) ( int, struct vki_nlist * ); + +#define kvm_t vki_kvm_t + +#endif /* __PUB_CORE_PROC_H */ diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/pub_core_sigframe.h --- a/coregrind/pub_core_sigframe.h Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/pub_core_sigframe.h Thu Mar 31 15:57:55 2016 +0900 @@ -54,8 +54,13 @@ /* Remove a signal frame from thread 'tid's stack, and restore the CPU state from it. */ +#if defined(VGO_freebsd) || defined(VGO_openbsd) +extern +void VG_(sigframe_destroy)( ThreadId tid ); +#else extern void VG_(sigframe_destroy)( ThreadId tid, Bool isRT ); +#endif #endif // __PUB_CORE_SIGFRAME_H diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/pub_core_syscall.h --- a/coregrind/pub_core_syscall.h Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/pub_core_syscall.h Thu Mar 31 15:57:55 2016 +0900 @@ -75,6 +75,10 @@ extern SysRes VG_(mk_SysRes_amd64_linux) ( Long val ); extern SysRes VG_(mk_SysRes_ppc32_linux) ( UInt val, UInt cr0so ); extern SysRes VG_(mk_SysRes_ppc64_linux) ( ULong val, ULong cr0so ); +extern SysRes VG_(mk_SysRes_x86_freebsd) ( UInt val, UInt val2, Bool err); +extern SysRes VG_(mk_SysRes_amd64_freebsd)( ULong val, ULong val2, Bool err ); +extern SysRes VG_(mk_SysRes_x86_openbsd) ( UInt val, UInt val2, Bool err); +extern SysRes VG_(mk_SysRes_amd64_openbsd)( ULong val, ULong val2, Bool err ); extern SysRes VG_(mk_SysRes_arm_linux) ( Int val ); extern SysRes VG_(mk_SysRes_arm64_linux) ( Long val ); extern SysRes VG_(mk_SysRes_x86_darwin) ( UChar scclass, Bool isErr, diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/pub_core_trampoline.h --- a/coregrind/pub_core_trampoline.h Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/pub_core_trampoline.h Thu Mar 31 15:57:55 2016 +0900 @@ -58,6 +58,22 @@ extern Addr VG_(trampoline_stuff_start); extern Addr VG_(trampoline_stuff_end); +#if defined(VGP_x86_freebsd) +extern void VG_(x86_freebsd_SUBST_FOR_sigreturn); +#endif + +#if defined(VGP_amd64_freebsd) +extern void VG_(amd64_freebsd_SUBST_FOR_sigreturn); +#endif + +#if defined(VGP_x86_openbsd) +extern void VG_(x86_openbsd_SUBST_FOR_sigreturn); +#endif + +#if defined(VGP_amd64_openbsd) +extern void VG_(amd64_openbsd_SUBST_FOR_sigreturn); +#endif + #if defined(VGP_x86_linux) extern Addr VG_(x86_linux_SUBST_FOR_sigreturn); extern Addr VG_(x86_linux_SUBST_FOR_rt_sigreturn); diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/vg_preloaded.c --- a/coregrind/vg_preloaded.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/vg_preloaded.c Thu Mar 31 15:57:55 2016 +0900 @@ -190,6 +190,8 @@ // but don't care if it's initialized } +#elif defined(VGO_freebsd) || defined(VGO_openbsd) +# warning "Do something!" #else # error Unknown OS diff -r efb6377bb4b5 -r ae0a1b9f3c43 coregrind/vgdb.c --- a/coregrind/vgdb.c Mon Dec 01 23:44:20 2014 +0900 +++ b/coregrind/vgdb.c Thu Mar 31 15:57:55 2016 +0900 @@ -70,6 +70,72 @@ int debuglevel; struct timeval dbgtv; + +#if 0 +/* define PTRACEINVOKER to compile the ptrace related code + which ensures a valgrind process blocked in a system call + can be "waken up". PTRACEINVOKER implies some architecture + specific code and/or some OS specific code. */ +#if defined(VGA_arm) || defined(VGA_x86) || defined(VGA_amd64) \ + || defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_s390x) \ + || defined(VGA_mips32) || defined(VGA_mips64) +#define PTRACEINVOKER +#else +I_die_here : (PTRACEINVOKER) architecture missing in vgdb.c +#endif + +/* Some darwin specific stuff is needed as ptrace is not + fully supported on MacOS. Till we find someone courageous + having access to Darwin, there is no PTRACEINVOKER. */ +#if defined(VGO_darwin) +#undef PTRACEINVOKER +#endif + +#if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) +#undef PTRACEINVOKER +#endif + +#if defined(PTRACEINVOKER) +#include +#endif + +#if defined(VGO_freebsd) || defined(VGO_openbsd) +#warning Fix me +#undef PTRACEINVOKER +#endif + + +// Outputs information for the user about ptrace not working. +static void ptrace_restrictions_msg(void); + +static int debuglevel; +static struct timeval dbgtv; +/* if level <= debuglevel, print timestamp, then print provided by debug info */ +#define DEBUG(level, ...) (level <= debuglevel ? \ + gettimeofday(&dbgtv, NULL), \ + fprintf(stderr, "%ld.%6.6ld ", \ + (long int)dbgtv.tv_sec, \ + (long int)dbgtv.tv_usec), \ + fprintf(stderr, __VA_ARGS__),fflush(stderr) \ + : 0) + +/* same as DEBUG but does not print time stamp info */ +#define PDEBUG(level, ...) (level <= debuglevel ? \ + fprintf(stderr, __VA_ARGS__),fflush(stderr) \ + : 0) + +/* if errno != 0, + report the errno and fprintf the ... varargs on stderr. */ +#define ERROR(errno, ...) ((errno == 0 ? 0 : perror("syscall failed")), \ + fprintf(stderr, __VA_ARGS__), \ + fflush(stderr)) +/* same as ERROR, but also exits with status 1 */ +#define XERROR(errno, ...) ((errno == 0 ? 0 : perror("syscall failed")), \ + fprintf(stderr, __VA_ARGS__), \ + fflush(stderr), \ + exit(1)) +#endif + static char *vgdb_prefix = NULL; /* Will be set to True when any condition indicating we have to shutdown diff -r efb6377bb4b5 -r ae0a1b9f3c43 docs/Makefile.am --- a/docs/Makefile.am Mon Dec 01 23:44:20 2014 +0900 +++ b/docs/Makefile.am Thu Mar 31 15:57:55 2016 +0900 @@ -97,7 +97,11 @@ downloadsdir = $(top_builddir)/docs/downloads vgdir = $(top_builddir)/docs/valgrind +if VGCONF_OS_IS_LINUX XML_CATALOG_FILES = /etc/xml/catalog +else +XML_CATALOG_FILES = /usr/local/share/xml/catalog +endif # file to log print output to LOGFILE = print.log @@ -119,6 +123,7 @@ XSL_TEXT_STYLE = $(mylibdir)/vg-faq2txt.xsl XSL_WEBSITE_STYLE = $(mylibdir)/vg-html-website.xsl XSL_MAN_STYLES = \ + /usr/local/share/xsl/docbook/manpages/docbook.xsl \ /usr/share/sgml/docbook/xsl-stylesheets/manpages/docbook.xsl \ /usr/share/xml/docbook/stylesheet/nwalsh/current/manpages/docbook.xsl \ /usr/share/xml/docbook/stylesheet/nwalsh/manpages/docbook.xsl diff -r efb6377bb4b5 -r ae0a1b9f3c43 drd/drd_main.c --- a/drd/drd_main.c Mon Dec 01 23:44:20 2014 +0900 +++ b/drd/drd_main.c Thu Mar 31 15:57:55 2016 +0900 @@ -736,7 +736,7 @@ static void DRD_(post_clo_init)(void) { -#if defined(VGO_linux) || defined(VGO_darwin) +#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd) /* fine */ #else VG_(printf)("\nWARNING: DRD has not yet been tested on this operating system.\n\n"); diff -r efb6377bb4b5 -r ae0a1b9f3c43 drd/tests/Makefile.am --- a/drd/tests/Makefile.am Mon Dec 01 23:44:20 2014 +0900 +++ b/drd/tests/Makefile.am Thu Mar 31 15:57:55 2016 +0900 @@ -394,8 +394,11 @@ if HAVE_BUILTIN_ATOMIC_CXX check_PROGRAMS += \ - annotate_smart_pointer \ - tsan_unittest + annotate_smart_pointer +endif + +if !VGCONF_OS_IS_FREEBSD +check_PROGRAMS += tsan_unittest endif # clang 3.3 will generate errors about libstdc++ headers from diff -r efb6377bb4b5 -r ae0a1b9f3c43 drd/tests/pth_detached3.c --- a/drd/tests/pth_detached3.c Mon Dec 01 23:44:20 2014 +0900 +++ b/drd/tests/pth_detached3.c Thu Mar 31 15:57:55 2016 +0900 @@ -5,6 +5,10 @@ #include #include +#if defined(VGO_freebsd) +#include +#endif + static void* thread_func(void* arg) { return 0; @@ -21,7 +25,11 @@ pthread_detach(thread); /* Invoke pthread_detach() with an invalid thread ID. */ - pthread_detach(thread + 8); +#ifdef VGO_freebsd + pthread_detach((pthread_t)12345); +#else + pthread_detach(thread + 0); +#endif fprintf(stderr, "Finished.\n"); diff -r efb6377bb4b5 -r ae0a1b9f3c43 exp-sgcheck/tests/Makefile.am --- a/exp-sgcheck/tests/Makefile.am Mon Dec 01 23:44:20 2014 +0900 +++ b/exp-sgcheck/tests/Makefile.am Thu Mar 31 15:57:55 2016 +0900 @@ -53,7 +53,9 @@ preen_invars_LDADD = -ldl preen_invars_LDFLAGS = $(AM_FLAG_M3264_PRI) else +if !VGCONF_OS_IS_FREEBSD preen_invars_LDADD = -ldl +endif preen_invars_LDFLAGS = $(AM_FLAG_M3264_PRI) \ -Wl,-rpath,$(top_builddir)/memcheck/tests endif diff -r efb6377bb4b5 -r ae0a1b9f3c43 freebsd.supp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/freebsd.supp Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,93 @@ +# Suppressions for FreeBSD + +##----------------------------------------------------------------------## +# Memcheck +##----------------------------------------------------------------------## + +{ + rtld-1 + Memcheck:Cond + obj:/libexec/ld-elf*.so.1 +} +{ + libc puts leak + Memcheck:Leak + fun:malloc + obj:/lib/libc.so.7 + obj:/lib/libc.so.7 + obj:/lib/libc.so.7 + fun:puts + fun:main +} +{ + DRD-1 + drd:ConflictingAccess + obj:/lib/libthr.so.3 + fun:pthread_create + fun:pthread_create + fun:main +} +{ + DRD-2 + drd:ConflictingAccess + fun:pthread_exit +} +{ + HELGRIND-PTHREAD-EXIT1 + Helgrind:Race + fun:_pthread_exit_mask + fun:pthread_exit + obj:/lib/libthr.so.3 +} +{ + HELGRIND-PTHREAD-EXIT2 + Helgrind:Race + fun:__sys_thr_exit + fun:_pthread_exit_mask + fun:pthread_exit + obj:/lib/libthr.so.3 +} +{ + HELGRIND-PTHREAD-EXIT3 + Helgrind:Race + obj:/lib/libthr.so.3 + fun:pthread_join_WRK + fun:pthread_join +} +{ + HELGRIND-PTHREAD-EXIT4 + Helgrind:Race + fun:_thr_try_gc + obj:/lib/libthr.so.3 + fun:pthread_join_WRK + fun:pthread_join +} +{ + HELGRIND-PTHREAD-EXIT5 + Helgrind:Race + fun:__sys_thr_exit + obj:/lib/libthr.so.3 + fun:_pthread_exit_mask + fun:pthread_exit + obj:/lib/libthr.so.3 +} +{ + HELGRIND-PTHREAD-BARRIER1 + Helgrind:Race + fun:pthread_barrier_init + fun:pthread_barrier_init + fun:main +} +{ + HELGRIND-PTHREAD-BARRIER2 + Helgrind:Race + fun:pthread_barrier_destroy + fun:pthread_barrier_destroy + fun:main +} +{ + HELGRIND-PTHREAD-CANCEL + Helgrind:Race + fun:pthread_cancel + fun:main +} diff -r efb6377bb4b5 -r ae0a1b9f3c43 getpath/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/getpath/Makefile Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,6 @@ +KMOD= getpath +SRCS= getpath_fromfd.c getpath_fromaddr.c \ + vnode_if.h + +.include + diff -r efb6377bb4b5 -r ae0a1b9f3c43 getpath/getpath_fromaddr.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/getpath/getpath_fromaddr.c Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,121 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +#if __FreeBSD_version < 500000 +#define VM_OBJECT_LOCK(x) do { } while (0) +#define VM_OBJECT_UNLOCK(x) do { } while (0) +#define PROCP(td) (td) +#define RETVAL p_retval +#define thread proc +#else +#define PROCP(td) (td)->td_proc +#define RETVAL td_retval +#endif + +struct getpath_fromaddr_args { + void *addr; + char *buf; + int len; +}; + +static int getpath_fromaddr_num = NO_SYSCALL; +SYSCTL_INT(_machdep, OID_AUTO, getpath_fromaddr_num, CTLFLAG_RD, &getpath_fromaddr_num, 0, + "syscall number for __getpath_fromaddr()"); + +static int +getpath_fromaddr_syscall(struct thread *td, void *args) +{ + struct getpath_fromaddr_args *uap = (struct getpath_fromaddr_args *)args; + int len; + int error; + vm_map_t map; + vm_map_entry_t entry; + vm_object_t obj, bobj; + struct vnode *vp; + char *path, *freebuf; + + map = &PROCP(td)->p_vmspace->vm_map; + + error = 0; + /* vm_map_lock_read(map); procfs says not needed for curthread's map */ + for (entry = map->header.next; entry != &map->header; entry = entry->next) { + if (entry->eflags & MAP_ENTRY_IS_SUB_MAP) + continue; + if ((vm_offset_t)uap->addr < entry->start || + (vm_offset_t)uap->addr >= entry->end) + continue; + obj = entry->object.vm_object; + VM_OBJECT_LOCK(obj); + while (obj->backing_object) { + bobj = obj->backing_object; + VM_OBJECT_LOCK(bobj); + VM_OBJECT_UNLOCK(obj); + obj = bobj; + } + if (obj == NULL || obj->type != OBJT_VNODE) + continue; + vp = (struct vnode *)obj->handle; + if (vp == NULL) + continue; /* XXX should panic */ + /* vref(vp); procfs says no, imgact_elf says maybe */ + error = vn_fullpath(td, vp, &path, &freebuf); + /* vrele(vp); procfs says no, imgact_elf says maybe */ + if (error == 0) { + len = strlen(path); + if ((len + 1) > uap->len) + error = ENOMEM; + else + error = copyout(path, uap->buf, len + 1); + free(freebuf, M_TEMP); + td->RETVAL[0] = len; + break; + } + } + /* vm_map_unlock_read(map); */ + return (error); +} + +static struct sysent getpath_fromaddr_sysent = { + sizeof(struct getpath_fromaddr_args) / sizeof(register_t), + getpath_fromaddr_syscall, +}; + +static int +getpath_fromaddr_dispatch(struct module *module, int cmd, void *arg) +{ + int error = 0; + + switch (cmd) { + case MOD_LOAD: + case MOD_UNLOAD: + break; + + default: + error = EOPNOTSUPP; + break; + } + return (error); +} + +SYSCALL_MODULE(getpath_fromaddr, &getpath_fromaddr_num, &getpath_fromaddr_sysent, getpath_fromaddr_dispatch, NULL); + diff -r efb6377bb4b5 -r ae0a1b9f3c43 getpath/getpath_fromfd.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/getpath/getpath_fromfd.c Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,98 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if __FreeBSD_version < 500000 +#define PROCP(td) (td) +#define RETVAL p_retval +#define thread proc +#define FDROP(td, fd) do { } while (0) +#define VNODE(fp) (struct vnode *)(fp)->f_data +#else +#define PROCP(td) (td)->td_proc +#define RETVAL td_retval +#define FDROP(td, fd) fdrop(td, fd) +#define VNODE(fp) (fp)->f_vnode +#endif +struct getpath_fromfd_args { + int fd; + char *buf; + int len; +}; + +static int getpath_fromfd_num = NO_SYSCALL; +SYSCTL_INT(_machdep, OID_AUTO, getpath_fromfd_num, CTLFLAG_RD, &getpath_fromfd_num, 0, + "syscall number for __getpath_fromfd()"); + +static int +getpath_fromfd_syscall(struct thread *td, void *args) +{ + struct getpath_fromfd_args *uap = (struct getpath_fromfd_args *)args; + struct filedesc *fdp = PROCP(td)->p_fd; + struct file *fp; + struct vnode *vp; + int len, error; + char *path, *freebuf = NULL; + + /* getvnode does internal filedesc locking (on 6.x) and returns a reference to fp */ + error = getvnode(fdp, uap->fd, &fp); + if (error) + return (error); + if (fp->f_type != DTYPE_VNODE) { + FDROP(fp, td); /* 6.x getvnode returns with an fd hold */ + return (EOPNOTSUPP); + } + /* On 4,x depend on not sleeping before this point */ + vp = VNODE(fp); + vref(vp); /* as per kern_proc.c use of vn_fullpath */ + error = vn_fullpath(td, vp, &path, &freebuf); + vrele(vp); + FDROP(fp, td); + if (error == 0) { + len = strlen(path); + if ((len + 1) > uap->len) + error = ENOMEM; + else + error = copyout(path, uap->buf, len + 1); + free(freebuf, M_TEMP); + td->RETVAL[0] = len; + } + return (error); +} + +static struct sysent getpath_fromfd_sysent = { + sizeof(struct getpath_fromfd_args) / sizeof(register_t), + getpath_fromfd_syscall, +}; + +static int +getpath_fromfd_dispatch(struct module *module, int cmd, void *arg) +{ + int error = 0; + + switch (cmd) { + case MOD_LOAD: + case MOD_UNLOAD: + break; + + default: + error = EOPNOTSUPP; + break; + } + return (error); +} + +SYSCALL_MODULE(getpath_fromfd, &getpath_fromfd_num, &getpath_fromfd_sysent, getpath_fromfd_dispatch, NULL); + diff -r efb6377bb4b5 -r ae0a1b9f3c43 getpath/gp_README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/getpath/gp_README Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,9 @@ +On Linux, procfs has a process map file that contains both a file descriptor number and a pathname +that corresponds to a chunk of a given process's mmap space. + +FreeBSD4's /proc/curproc/map file does not have either. This kernel module allows valgrind to identify +which file some random mmap segment came from or the filename that corresponds to a random fd. + +This package works on both FreeBSD-4.x and 6.x. + +-Peter diff -r efb6377bb4b5 -r ae0a1b9f3c43 helgrind/hg_intercepts.c --- a/helgrind/hg_intercepts.c Mon Dec 01 23:44:20 2014 +0900 +++ b/helgrind/hg_intercepts.c Thu Mar 31 15:57:55 2016 +0900 @@ -300,6 +300,12 @@ void *(*start) (void *), void *arg) { return pthread_create_WRK(thread, attr, start, arg); } +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + PTH_FUNC(int, pthreadZucreate, // pthread_create + pthread_t *thread, const pthread_attr_t *attr, + void *(*start) (void *), void *arg) { + return pthread_create_WRK(thread, attr, start, arg); + } #elif defined(VGO_darwin) PTH_FUNC(int, pthreadZucreate, // pthread_create pthread_t *thread, const pthread_attr_t *attr, @@ -353,6 +359,11 @@ pthread_t thread, void** value_pointer) { return pthread_join_WRK(thread, value_pointer); } +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + PTH_FUNC(int, pthreadZujoin, // pthread_join + pthread_t thread, void** value_pointer) { + return pthread_join_WRK(thread, value_pointer); + } #elif defined(VGO_darwin) PTH_FUNC(int, pthreadZujoinZa, // pthread_join* pthread_t thread, void** value_pointer) { @@ -802,6 +813,11 @@ pthread_cond_t* cond, pthread_mutex_t* mutex) { return pthread_cond_wait_WRK(cond, mutex); } +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + PTH_FUNC(int, pthreadZucondZuwait, // pthread_cond_wait + pthread_cond_t* cond, pthread_mutex_t* mutex) { + return pthread_cond_wait_WRK(cond, mutex); + } #elif defined(VGO_darwin) PTH_FUNC(int, pthreadZucondZuwaitZa, // pthread_cond_wait* pthread_cond_t* cond, pthread_mutex_t* mutex) { @@ -893,6 +909,12 @@ struct timespec* abstime) { return pthread_cond_timedwait_WRK(cond, mutex, abstime); } +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + PTH_FUNC(int, pthreadZucondZutimedwait, // pthread_cond_timedwait + pthread_cond_t* cond, pthread_mutex_t* mutex, + struct timespec* abstime) { + return pthread_cond_timedwait_WRK(cond, mutex, abstime); + } #elif defined(VGO_darwin) PTH_FUNC(int, pthreadZucondZutimedwait, // pthread_cond_timedwait pthread_cond_t* cond, pthread_mutex_t* mutex, @@ -953,6 +975,11 @@ pthread_cond_t* cond) { return pthread_cond_signal_WRK(cond); } +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + PTH_FUNC(int, pthreadZucondZusignal, // pthread_cond_signal + pthread_cond_t* cond) { + return pthread_cond_signal_WRK(cond); + } #elif defined(VGO_darwin) PTH_FUNC(int, pthreadZucondZusignal, // pthread_cond_signal pthread_cond_t* cond) { @@ -1005,6 +1032,11 @@ pthread_cond_t* cond) { return pthread_cond_broadcast_WRK(cond); } +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + PTH_FUNC(int, pthreadZucondZubroadcast, // pthread_cond_broadcast + pthread_cond_t* cond) { + return pthread_cond_broadcast_WRK(cond); + } #elif defined(VGO_darwin) PTH_FUNC(int, pthreadZucondZubroadcast, // pthread_cond_broadcast pthread_cond_t* cond) { @@ -1054,6 +1086,11 @@ pthread_cond_t* cond, pthread_condattr_t* cond_attr) { return pthread_cond_init_WRK(cond, cond_attr); } +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + PTH_FUNC(int, pthreadZucondZuinitZAZa, // pthread_cond_init@* + pthread_cond_t* cond, pthread_condattr_t* cond_attr) { + return pthread_cond_init_WRK(cond, cond_attr); + } #elif defined(VGO_darwin) PTH_FUNC(int, pthreadZucondZuinit, // pthread_cond_init pthread_cond_t* cond, pthread_condattr_t * cond_attr) { @@ -1111,6 +1148,11 @@ pthread_cond_t* cond) { return pthread_cond_destroy_WRK(cond); } +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + PTH_FUNC(int, pthreadZucondZudestroy, // pthread_cond_destroy + pthread_cond_t* cond) { + return pthread_cond_destroy_WRK(cond); + } #elif defined(VGO_darwin) PTH_FUNC(int, pthreadZucondZudestroy, // pthread_cond_destroy pthread_cond_t* cond) { @@ -1305,6 +1347,16 @@ /* this is never actually called */ return pthread_spin_init_or_unlock_WRK(lock, 0/*pshared*/); } +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + PTH_FUNC(int, pthreadZuspinZuinit, // pthread_spin_init + pthread_spinlock_t* lock, int pshared) { + return pthread_spin_init_or_unlock_WRK(lock, pshared); + } + PTH_FUNC(int, pthreadZuspinZuunlockZAZa, // pthread_spin_unlock@* + pthread_spinlock_t* lock) { + /* this is never actually called */ + return pthread_spin_init_or_unlock_WRK(lock, 0/*pshared*/); + } #elif defined(VGO_darwin) #else # error "Unsupported OS" @@ -1314,7 +1366,7 @@ //----------------------------------------------------------- // glibc: pthread_spin_destroy // darwin: (doesn't appear to exist) -#if defined(VGO_linux) +#if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd) PTH_FUNC(int, pthreadZuspinZudestroy, // pthread_spin_destroy pthread_spinlock_t* lock) @@ -1351,7 +1403,7 @@ //----------------------------------------------------------- // glibc: pthread_spin_lock // darwin: (doesn't appear to exist) -#if defined(VGO_linux) +#if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd) PTH_FUNC(int, pthreadZuspinZulock, // pthread_spin_lock pthread_spinlock_t* lock) @@ -1396,7 +1448,7 @@ //----------------------------------------------------------- // glibc: pthread_spin_trylock // darwin: (doesn't appear to exist) -#if defined(VGO_linux) +#if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd) PTH_FUNC(int, pthreadZuspinZutrylock, // pthread_spin_trylock pthread_spinlock_t* lock) @@ -1496,6 +1548,12 @@ pthread_rwlockattr_t* attr) { return pthread_rwlock_init_WRK(rwl, attr); } +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + PTH_FUNC(int, pthreadZurwlockZuinit, // pthread_rwlock_init + pthread_rwlock_t *rwl, + pthread_rwlockattr_t* attr) { + return pthread_rwlock_init_WRK(rwl, attr); + } #elif defined(VGO_darwin) PTH_FUNC(int, pthreadZurwlockZuinitZa, // pthread_rwlock_init* pthread_rwlock_t *rwl, @@ -1541,6 +1599,11 @@ pthread_rwlock_t *rwl) { return pthread_rwlock_destroy_WRK(rwl); } +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + PTH_FUNC(int, pthreadZurwlockZudestroy, // pthread_rwlock_destroy + pthread_rwlock_t *rwl) { + return pthread_rwlock_destroy_WRK(rwl); + } #elif defined(VGO_darwin) PTH_FUNC(int, pthreadZurwlockZudestroyZa, // pthread_rwlock_destroy* pthread_rwlock_t *rwl) { @@ -1589,6 +1652,11 @@ pthread_rwlock_t* rwlock) { return pthread_rwlock_wrlock_WRK(rwlock); } +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + PTH_FUNC(int, pthreadZurwlockZuwrlock, // pthread_rwlock_wrlock + pthread_rwlock_t* rwlock) { + return pthread_rwlock_wrlock_WRK(rwlock); + } #elif defined(VGO_darwin) PTH_FUNC(int, pthreadZurwlockZuwrlockZa, // pthread_rwlock_wrlock* pthread_rwlock_t* rwlock) { @@ -1637,6 +1705,11 @@ pthread_rwlock_t* rwlock) { return pthread_rwlock_rdlock_WRK(rwlock); } +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + PTH_FUNC(int, pthreadZurwlockZurdlock, // pthread_rwlock_rdlock + pthread_rwlock_t* rwlock) { + return pthread_rwlock_rdlock_WRK(rwlock); + } #elif defined(VGO_darwin) PTH_FUNC(int, pthreadZurwlockZurdlockZa, // pthread_rwlock_rdlock* pthread_rwlock_t* rwlock) { @@ -1691,6 +1764,11 @@ pthread_rwlock_t* rwlock) { return pthread_rwlock_trywrlock_WRK(rwlock); } +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + PTH_FUNC(int, pthreadZurwlockZutrywrlock, // pthread_rwlock_trywrlock + pthread_rwlock_t* rwlock) { + return pthread_rwlock_trywrlock_WRK(rwlock); + } #elif defined(VGO_darwin) PTH_FUNC(int, pthreadZurwlockZutrywrlockZa, // pthread_rwlock_trywrlock* pthread_rwlock_t* rwlock) { @@ -1745,6 +1823,11 @@ pthread_rwlock_t* rwlock) { return pthread_rwlock_tryrdlock_WRK(rwlock); } +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + PTH_FUNC(int, pthreadZurwlockZutryrdlock, // pthread_rwlock_tryrdlock + pthread_rwlock_t* rwlock) { + return pthread_rwlock_tryrdlock_WRK(rwlock); + } #elif defined(VGO_darwin) PTH_FUNC(int, pthreadZurwlockZutryrdlockZa, // pthread_rwlock_tryrdlock* pthread_rwlock_t* rwlock) { @@ -1791,6 +1874,11 @@ pthread_rwlock_t* rwlock) { return pthread_rwlock_unlock_WRK(rwlock); } +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + PTH_FUNC(int, pthreadZurwlockZuunlock, // pthread_rwlock_unlock + pthread_rwlock_t* rwlock) { + return pthread_rwlock_unlock_WRK(rwlock); + } #elif defined(VGO_darwin) PTH_FUNC(int, pthreadZurwlockZuunlockZa, // pthread_rwlock_unlock* pthread_rwlock_t* rwlock) { @@ -1867,6 +1955,11 @@ sem_t* sem, int pshared, unsigned long value) { return sem_init_WRK(sem, pshared, value); } +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + PTH_FUNC(int, semZuinit, // sem_init + sem_t* sem, int pshared, unsigned long value) { + return sem_init_WRK(sem, pshared, value); + } #elif defined(VGO_darwin) PTH_FUNC(int, semZuinit, // sem_init sem_t* sem, int pshared, unsigned long value) { @@ -1914,6 +2007,11 @@ sem_t* sem) { return sem_destroy_WRK(sem); } +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + PTH_FUNC(int, semZudestroy, // sem_destroy + sem_t* sem) { + return sem_destroy_WRK(sem); + } #elif defined(VGO_darwin) PTH_FUNC(int, semZudestroy, // sem_destroy sem_t* sem) { @@ -1967,6 +2065,10 @@ PTH_FUNC(int, semZuwaitZAZa, sem_t* sem) { /* sem_wait@* */ return sem_wait_WRK(sem); } +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + PTH_FUNC(int, semZuwait, sem_t* sem) { /* sem_wait */ + return sem_wait_WRK(sem); + } #elif defined(VGO_darwin) PTH_FUNC(int, semZuwait, sem_t* sem) { /* sem_wait */ return sem_wait_WRK(sem); @@ -2021,6 +2123,10 @@ PTH_FUNC(int, semZupostZAZa, sem_t* sem) { /* sem_post@* */ return sem_post_WRK(sem); } +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + PTH_FUNC(int, semZupost, sem_t* sem) { /* sem_post */ + return sem_post_WRK(sem); + } #elif defined(VGO_darwin) PTH_FUNC(int, semZupost, sem_t* sem) { /* sem_post */ return sem_post_WRK(sem); diff -r efb6377bb4b5 -r ae0a1b9f3c43 helgrind/hg_main.c --- a/helgrind/hg_main.c Mon Dec 01 23:44:20 2014 +0900 +++ b/helgrind/hg_main.c Thu Mar 31 15:57:55 2016 +0900 @@ -4479,6 +4479,11 @@ if (VG_STREQ(soname, VG_U_LD_LINUX_ARMHF_SO_3)) return True; # elif defined(VGO_darwin) if (VG_STREQ(soname, VG_U_DYLD)) return True; +# elif defined(VGO_freebsd) + if (VG_STREQ(soname, VG_U_LD_ELF_SO_1)) return True; + if (VG_STREQ(soname, VG_U_LD_ELF32_SO_1)) return True; +# elif defined(VGO_openbsd) + if (VG_STREQ(soname, VG_U_LD_ELF_SO_1)) return True; # else # error "Unsupported OS" # endif diff -r efb6377bb4b5 -r ae0a1b9f3c43 helgrind/tests/Makefile.am --- a/helgrind/tests/Makefile.am Mon Dec 01 23:44:20 2014 +0900 +++ b/helgrind/tests/Makefile.am Thu Mar 31 15:57:55 2016 +0900 @@ -9,7 +9,7 @@ annotate_hbefore.vgtest annotate_hbefore.stdout.exp \ annotate_hbefore.stderr.exp \ annotate_rwlock.vgtest annotate_rwlock.stdout.exp \ - annotate_rwlock.stderr.exp \ + annotate_rwlock.stderr.exp annotate_rwlock.stderr.exp-freebsd \ annotate_smart_pointer.vgtest annotate_smart_pointer.stdout.exp \ annotate_smart_pointer.stderr.exp \ cond_init_destroy.vgtest cond_init_destroy.stderr.exp \ @@ -20,7 +20,7 @@ bar_bad.vgtest bar_bad.stdout.exp bar_bad.stderr.exp \ bar_trivial.vgtest bar_trivial.stdout.exp bar_trivial.stderr.exp \ free_is_write.vgtest free_is_write.stdout.exp \ - free_is_write.stderr.exp \ + free_is_write.stderr.exp free_is_write.stderr.exp-freebsd \ hg01_all_ok.vgtest hg01_all_ok.stdout.exp hg01_all_ok.stderr.exp \ hg02_deadlock.vgtest hg02_deadlock.stdout.exp hg02_deadlock.stderr.exp \ hg03_inherit.vgtest hg03_inherit.stdout.exp hg03_inherit.stderr.exp \ diff -r efb6377bb4b5 -r ae0a1b9f3c43 helgrind/tests/annotate_rwlock.stderr.exp-freebsd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/helgrind/tests/annotate_rwlock.stderr.exp-freebsd Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,117 @@ +---Thread-Announcement------------------------------------------ + +Thread #x was created + ... + by 0x........: pthread_create_WRK (hg_intercepts.c:...) + by 0x........: pthread_create (hg_intercepts.c:...) + by 0x........: main (annotate_rwlock.c:164) + +---Thread-Announcement------------------------------------------ + +Thread #x was created + ... + by 0x........: pthread_create_WRK (hg_intercepts.c:...) + by 0x........: pthread_create (hg_intercepts.c:...) + by 0x........: main (annotate_rwlock.c:164) + +---------------------------------------------------------------- + +Possible data race during read of size 4 at 0x........ by thread #x +Locks held: none + at 0x........: rwlock_rdlock (annotate_rwlock.c:71) + by 0x........: thread_func (annotate_rwlock.c:144) + by 0x........: mythread_wrapper (hg_intercepts.c:...) + ... + +This conflicts with a previous write of size 4 by thread #x +Locks held: none + at 0x........: rwlock_wrlock (annotate_rwlock.c:106) + by 0x........: thread_func (annotate_rwlock.c:147) + by 0x........: mythread_wrapper (hg_intercepts.c:...) + ... + +---------------------------------------------------------------- + +Possible data race during read of size 4 at 0x........ by thread #x +Locks held: none + at 0x........: rwlock_rdlock (annotate_rwlock.c:81) + by 0x........: thread_func (annotate_rwlock.c:144) + by 0x........: mythread_wrapper (hg_intercepts.c:...) + ... + +This conflicts with a previous write of size 4 by thread #x +Locks held: none + at 0x........: rwlock_rdlock (annotate_rwlock.c:81) + by 0x........: thread_func (annotate_rwlock.c:144) + by 0x........: mythread_wrapper (hg_intercepts.c:...) + ... + +---------------------------------------------------------------- + +Possible data race during write of size 4 at 0x........ by thread #x +Locks held: none + at 0x........: rwlock_rdlock (annotate_rwlock.c:81) + by 0x........: thread_func (annotate_rwlock.c:144) + by 0x........: mythread_wrapper (hg_intercepts.c:...) + ... + +This conflicts with a previous read of size 4 by thread #x +Locks held: none + at 0x........: rwlock_unlock (annotate_rwlock.c:131) + by 0x........: thread_func (annotate_rwlock.c:149) + by 0x........: mythread_wrapper (hg_intercepts.c:...) + ... + +---------------------------------------------------------------- + +Possible data race during write of size 4 at 0x........ by thread #x +Locks held: none + at 0x........: rwlock_unlock (annotate_rwlock.c:121) + by 0x........: thread_func (annotate_rwlock.c:146) + by 0x........: mythread_wrapper (hg_intercepts.c:...) + ... + +This conflicts with a previous read of size 4 by thread #x +Locks held: none + at 0x........: rwlock_unlock (annotate_rwlock.c:131) + by 0x........: thread_func (annotate_rwlock.c:149) + by 0x........: mythread_wrapper (hg_intercepts.c:...) + ... + +---------------------------------------------------------------- + +Possible data race during write of size 4 at 0x........ by thread #x +Locks held: none + at 0x........: rwlock_wrlock (annotate_rwlock.c:106) + by 0x........: thread_func (annotate_rwlock.c:147) + by 0x........: mythread_wrapper (hg_intercepts.c:...) + ... + +This conflicts with a previous read of size 4 by thread #x +Locks held: none + at 0x........: rwlock_unlock (annotate_rwlock.c:132) + by 0x........: thread_func (annotate_rwlock.c:149) + by 0x........: mythread_wrapper (hg_intercepts.c:...) + ... + +---------------------------------------------------------------- + +Lock at 0x........ was first observed + at 0x........: rwlock_init (annotate_rwlock.c:54) + by 0x........: main (annotate_rwlock.c:161) + +Possible data race during write of size 4 at 0x........ by thread #x +Locks held: 1, at address 0x........ + at 0x........: rwlock_unlock (annotate_rwlock.c:127) + by 0x........: thread_func (annotate_rwlock.c:149) + by 0x........: mythread_wrapper (hg_intercepts.c:...) + ... + +This conflicts with a previous read of size 4 by thread #x +Locks held: none + at 0x........: rwlock_unlock (annotate_rwlock.c:132) + by 0x........: thread_func (annotate_rwlock.c:149) + by 0x........: mythread_wrapper (hg_intercepts.c:...) + ... + +Finished. diff -r efb6377bb4b5 -r ae0a1b9f3c43 helgrind/tests/free_is_write.stderr.exp-freebsd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/helgrind/tests/free_is_write.stderr.exp-freebsd Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,30 @@ + +Start. +---Thread-Announcement------------------------------------------ + +Thread #x was created + ... + by 0x........: pthread_create_WRK (hg_intercepts.c:...) + by 0x........: pthread_create (hg_intercepts.c:...) + by 0x........: main (free_is_write.c:32) + +---Thread-Announcement------------------------------------------ + +Thread #x is the program's root thread + +---------------------------------------------------------------- + +Possible data race during write of size 1 at 0x........ by thread #x +Locks held: none + at 0x........: free (vg_replace_malloc.c:...) + by 0x........: thread_func (free_is_write.c:15) + by 0x........: mythread_wrapper (hg_intercepts.c:...) + ... + +This conflicts with a previous read of size 1 by thread #x +Locks held: none + at 0x........: main (free_is_write.c:36) + +Done. + +ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0) diff -r efb6377bb4b5 -r ae0a1b9f3c43 helgrind/tests/tc07_hbl1.c --- a/helgrind/tests/tc07_hbl1.c Mon Dec 01 23:44:20 2014 +0900 +++ b/helgrind/tests/tc07_hbl1.c Thu Mar 31 15:57:55 2016 +0900 @@ -8,6 +8,10 @@ #undef PLAT_x86_darwin #undef PLAT_amd64_darwin +#undef PLAT_x86_freebsd +#undef PLAT_amd64_freebsd +#undef PLAT_x86_openbsd +#undef PLAT_amd64_openbsd #undef PLAT_x86_linux #undef PLAT_amd64_linux #undef PLAT_ppc32_linux @@ -21,6 +25,14 @@ # define PLAT_x86_darwin 1 #elif defined(__APPLE__) && defined(__x86_64__) # define PLAT_amd64_darwin 1 +#elif defined(__FreeBSD__) && defined(__i386__) +# define PLAT_x86_freebsd 1 +#elif defined(__FreeBSD__) && defined(__amd64__) +# define PLAT_amd64_freebsd 1 +#elif defined(__OpenBSD__) && defined(__i386__) +# define PLAT_x86_openbsd 1 +#elif defined(__OpenBSD__) && defined(__amd64__) +# define PLAT_amd64_openbsd 1 #elif defined(__linux__) && defined(__i386__) # define PLAT_x86_linux 1 #elif defined(__linux__) && defined(__x86_64__) @@ -40,7 +52,9 @@ #endif #if defined(PLAT_amd64_linux) || defined(PLAT_x86_linux) \ - || defined(PLAT_amd64_darwin) || defined(PLAT_x86_darwin) + || defined(PLAT_amd64_darwin) || defined(PLAT_x86_darwin) \ + || defined(PLAT_amd64_freebsd) || defined(PLAT_x86_freebsd) \ + || defined(PLAT_amd64_openbsd) || defined(PLAT_x86_openbsd) # define INC(_lval,_lqual) \ __asm__ __volatile__ ( \ "lock ; incl (%0)" : /*out*/ : /*in*/"r"(&(_lval)) : "memory", "cc" ) diff -r efb6377bb4b5 -r ae0a1b9f3c43 helgrind/tests/tc08_hbl2.c --- a/helgrind/tests/tc08_hbl2.c Mon Dec 01 23:44:20 2014 +0900 +++ b/helgrind/tests/tc08_hbl2.c Thu Mar 31 15:57:55 2016 +0900 @@ -24,6 +24,10 @@ #undef PLAT_x86_darwin #undef PLAT_amd64_darwin +#undef PLAT_x86_freebsd +#undef PLAT_amd64_freebsd +#undef PLAT_x86_openbsd +#undef PLAT_amd64_openbsd #undef PLAT_x86_linux #undef PLAT_amd64_linux #undef PLAT_ppc32_linux @@ -38,6 +42,14 @@ # define PLAT_x86_darwin 1 #elif defined(__APPLE__) && defined(__x86_64__) # define PLAT_amd64_darwin 1 +#elif defined(__FreeBSD__) && defined(__i386__) +# define PLAT_x86_freebsd 1 +#elif defined(__FreeBSD__) && defined(__amd64__) +# define PLAT_amd64_freebsd 1 +#elif defined(__OpenBSD__) && defined(__i386__) +# define PLAT_x86_openbsd 1 +#elif defined(__OpenBSD__) && defined(__amd64__) +# define PLAT_amd64_openbsd 1 #elif defined(__linux__) && defined(__i386__) # define PLAT_x86_linux 1 #elif defined(__linux__) && defined(__x86_64__) @@ -62,7 +74,9 @@ #if defined(PLAT_amd64_linux) || defined(PLAT_x86_linux) \ - || defined(PLAT_amd64_darwin) || defined(PLAT_x86_darwin) + || defined(PLAT_amd64_darwin) || defined(PLAT_x86_darwin) \ + || defined(PLAT_amd64_freebsd) || defined(PLAT_x86_freebsd) \ + || defined(PLAT_amd64_openbsd) || defined(PLAT_x86_openbsd) # define INC(_lval,_lqual) \ __asm__ __volatile__ ( \ "lock ; incl (%0)" : /*out*/ : /*in*/"r"(&(_lval)) : "memory", "cc" ) diff -r efb6377bb4b5 -r ae0a1b9f3c43 helgrind/tests/tc11_XCHG.c --- a/helgrind/tests/tc11_XCHG.c Mon Dec 01 23:44:20 2014 +0900 +++ b/helgrind/tests/tc11_XCHG.c Thu Mar 31 15:57:55 2016 +0900 @@ -11,6 +11,10 @@ #undef PLAT_x86_darwin #undef PLAT_amd64_darwin +#undef PLAT_x86_freebsd +#undef PLAT_amd64_freebsd +#undef PLAT_x86_openbsd +#undef PLAT_amd64_openbsd #undef PLAT_x86_linux #undef PLAT_amd64_linux #undef PLAT_ppc32_linux @@ -23,6 +27,14 @@ # define PLAT_x86_darwin 1 #elif defined(__APPLE__) && defined(__x86_64__) # define PLAT_amd64_darwin 1 +#elif defined(__FreeBSD__) && defined(__i386__) +# define PLAT_x86_freebsd 1 +#elif defined(__FreeBSD__) && defined(__amd64__) +# define PLAT_amd64_freebsd 1 +#elif defined(__OpenBSD__) && defined(__i386__) +# define PLAT_x86_openbsd 1 +#elif defined(__OpenBSD__) && defined(__amd64__) +# define PLAT_amd64_openbsd 1 #elif defined(__linux__) && defined(__i386__) # define PLAT_x86_linux 1 #elif defined(__linux__) && defined(__x86_64__) @@ -43,7 +55,9 @@ #if defined(PLAT_amd64_linux) || defined(PLAT_x86_linux) \ - || defined(PLAT_amd64_darwin) || defined(PLAT_x86_darwin) + || defined(PLAT_amd64_darwin) || defined(PLAT_x86_darwin) \ + || defined(PLAT_amd64_freebsd) || defined(PLAT_x86_freebsd) \ + || defined(PLAT_amd64_openbsd) || defined(PLAT_x86_openbsd) # define XCHG_M_R(_addr,_lval) \ __asm__ __volatile__( \ "xchgl %0, %1" \ diff -r efb6377bb4b5 -r ae0a1b9f3c43 helgrind/tests/tc17_sembar.c --- a/helgrind/tests/tc17_sembar.c Mon Dec 01 23:44:20 2014 +0900 +++ b/helgrind/tests/tc17_sembar.c Thu Mar 31 15:57:55 2016 +0900 @@ -4,6 +4,9 @@ #include #include #include +#if defined(VGO_freebsd) || defined(VGO_openbsd) +# include +#endif /* This is really a test of semaphore handling (sem_{init,destroy,post,wait}). Using semaphores a barrier function is created. Helgrind-3.3 (p.k.a Thrcheck) does understand @@ -231,7 +234,7 @@ s = NULL; } } -#elif defined(VGO_darwin) +#elif defined(VGO_darwin) || defined(VGO_freebsd) || defined(VGO_openbsd) char name[100]; sprintf(name, "anonsem_%s_pid%d", identity, (int)getpid()); name[ sizeof(name)-1 ] = 0; diff -r efb6377bb4b5 -r ae0a1b9f3c43 helgrind/tests/tc20_verifywrap.c --- a/helgrind/tests/tc20_verifywrap.c Mon Dec 01 23:44:20 2014 +0900 +++ b/helgrind/tests/tc20_verifywrap.c Thu Mar 31 15:57:55 2016 +0900 @@ -18,7 +18,7 @@ #include #include -#if !defined(__APPLE__) +#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) #if !defined(__GLIBC_PREREQ) # error "This program needs __GLIBC_PREREQ (in /usr/include/features.h)" diff -r efb6377bb4b5 -r ae0a1b9f3c43 helgrind/tests/tc23_bogus_condwait.c --- a/helgrind/tests/tc23_bogus_condwait.c Mon Dec 01 23:44:20 2014 +0900 +++ b/helgrind/tests/tc23_bogus_condwait.c Thu Mar 31 15:57:55 2016 +0900 @@ -7,6 +7,9 @@ #include #include #include +#if defined(VGO_freebsd) +#include +#endif pthread_mutex_t mx[4]; pthread_cond_t cv; pthread_rwlock_t rwl; sem_t* quit_now; @@ -107,7 +110,7 @@ s = NULL; } } -#elif defined(VGO_darwin) +#elif defined(VGO_darwin) || defined(VGO_freebsd) || defined(VGO_openbsd) char name[100]; sprintf(name, "anonsem_%s_pid%d", identity, (int)getpid()); name[ sizeof(name)-1 ] = 0; diff -r efb6377bb4b5 -r ae0a1b9f3c43 helgrind/tests/tc24_nonzero_sem.c --- a/helgrind/tests/tc24_nonzero_sem.c Mon Dec 01 23:44:20 2014 +0900 +++ b/helgrind/tests/tc24_nonzero_sem.c Thu Mar 31 15:57:55 2016 +0900 @@ -9,6 +9,9 @@ #include #include #include +#if defined(VGO_freebsd) || defined(VGO_openbsd) +# include +#endif #define N_THREADS 3 @@ -59,7 +62,7 @@ s = NULL; } } -#elif defined(VGO_darwin) +#elif defined(VGO_darwin) || defined(VGO_freebsd) || defined(VGO_openbsd) char name[100]; sprintf(name, "anonsem_%s_pid%d", identity, (int)getpid()); name[ sizeof(name)-1 ] = 0; diff -r efb6377bb4b5 -r ae0a1b9f3c43 include/Makefile.am --- a/include/Makefile.am Mon Dec 01 23:44:20 2014 +0900 +++ b/include/Makefile.am Thu Mar 31 15:57:55 2016 +0900 @@ -43,7 +43,13 @@ pub_tool_xarray.h \ valgrind.h \ vki/vki-linux.h \ + vki/vki-freebsd.h \ + vki/vki-openbsd.h \ vki/vki-darwin.h \ + vki/vki-machine-types-amd64-freebsd.h \ + vki/vki-machine-types-x86-freebsd.h \ + vki/vki-machine-types-amd64-openbsd.h \ + vki/vki-machine-types-x86-openbsd.h \ vki/vki-posixtypes-amd64-linux.h \ vki/vki-posixtypes-arm64-linux.h \ vki/vki-posixtypes-ppc32-linux.h \ @@ -58,6 +64,10 @@ vki/vki-ppc32-linux.h \ vki/vki-ppc64-linux.h \ vki/vki-x86-linux.h \ + vki/vki-amd64-freebsd.h \ + vki/vki-x86-freebsd.h \ + vki/vki-amd64-openbsd.h \ + vki/vki-x86-openbsd.h \ vki/vki-arm-linux.h \ vki/vki-s390x-linux.h \ vki/vki-mips32-linux.h \ @@ -67,6 +77,8 @@ vki/vki-scnums-ppc32-linux.h \ vki/vki-scnums-ppc64-linux.h \ vki/vki-scnums-x86-linux.h \ + vki/vki-scnums-freebsd.h \ + vki/vki-scnums-openbsd.h \ vki/vki-scnums-arm-linux.h \ vki/vki-scnums-s390x-linux.h \ vki/vki-scnums-mips32-linux.h \ diff -r efb6377bb4b5 -r ae0a1b9f3c43 include/pub_tool_basics.h --- a/include/pub_tool_basics.h Mon Dec 01 23:44:20 2014 +0900 +++ b/include/pub_tool_basics.h Thu Mar 31 15:57:55 2016 +0900 @@ -113,6 +113,8 @@ // always a signed 64-bit int. So we defined our own Off64T as well. #if defined(VGO_linux) typedef Word OffT; // 32 64 +#elif defined(VGO_freebsd) || defined(VGO_openbsd) +typedef Long OffT; // 64 64 #elif defined(VGO_darwin) typedef Long OffT; // 64 64 #else @@ -183,11 +185,21 @@ SysResMode _mode; } SysRes; +#elif defined(VGO_freebsd) || defined(VGO_openbsd) +typedef + struct { + UWord _val; + UWord _val2; + Bool _isError; +#if defined(VGO_openbsd) + Bool _hasVal2; +#endif + } + SysRes; #else # error "Unknown OS" #endif - /* ---- And now some basic accessor functions for it. ---- */ #if defined(VGO_linux) @@ -213,6 +225,27 @@ || (!sr1._isError && !sr2._isError)); } +#elif defined(VGO_freebsd) || defined(VGO_openbsd) + +static inline Bool sr_isError ( SysRes sr ) { + return sr._isError; +} +static inline UWord sr_Res ( SysRes sr ) { + return sr._isError ? 0 : sr._val; +} +static inline UWord sr_ResHI ( SysRes sr ) { + return sr._isError ? 0 : sr._val2; +} +static inline UWord sr_Err ( SysRes sr ) { + return sr._isError ? sr._val : 0; +} +static inline Bool sr_EQ ( SysRes sr1, SysRes sr2 ) { + return sr_Res(sr1) == sr_Res(sr2) + && sr_ResHI(sr1) == sr_ResHI(sr2) + && ((sr_isError(sr1) && sr_isError(sr2)) + || (!sr_isError(sr1) && !sr_isError(sr2))); +} + #elif defined(VGO_darwin) static inline Bool sr_isError ( SysRes sr ) { diff -r efb6377bb4b5 -r ae0a1b9f3c43 include/pub_tool_basics_asm.h --- a/include/pub_tool_basics_asm.h Mon Dec 01 23:44:20 2014 +0900 +++ b/include/pub_tool_basics_asm.h Thu Mar 31 15:57:55 2016 +0900 @@ -48,7 +48,7 @@ #define VGAPPEND(str1,str2) str1##str2 -#if defined(VGO_linux) +#if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd) # define VG_(str) VGAPPEND( vgPlain_, str) # define ML_(str) VGAPPEND( vgModuleLocal_, str) #elif defined(VGO_darwin) diff -r efb6377bb4b5 -r ae0a1b9f3c43 include/pub_tool_libcbase.h --- a/include/pub_tool_libcbase.h Mon Dec 01 23:44:20 2014 +0900 +++ b/include/pub_tool_libcbase.h Thu Mar 31 15:57:55 2016 +0900 @@ -90,6 +90,7 @@ extern HChar* VG_(strpbrk) ( const HChar* s, const HChar* accpt ); extern HChar* VG_(strcpy) ( HChar* dest, const HChar* src ); extern HChar* VG_(strncpy) ( HChar* dest, const HChar* src, SizeT ndest ); +extern SizeT VG_(strlcpy) ( HChar* dest, const HChar* src, SizeT ndest ); extern Int VG_(strcmp) ( const HChar* s1, const HChar* s2 ); extern Int VG_(strcasecmp) ( const HChar* s1, const HChar* s2 ); extern Int VG_(strncmp) ( const HChar* s1, const HChar* s2, SizeT nmax ); diff -r efb6377bb4b5 -r ae0a1b9f3c43 include/pub_tool_libcfile.h --- a/include/pub_tool_libcfile.h Mon Dec 01 23:44:20 2014 +0900 +++ b/include/pub_tool_libcfile.h Thu Mar 31 15:57:55 2016 +0900 @@ -71,6 +71,7 @@ ULong ctime_nsec; }; +extern SysRes VG_(mkfifo) ( const HChar* pathname, Int mode ); extern SysRes VG_(mknod) ( const HChar* pathname, Int mode, UWord dev ); extern SysRes VG_(open) ( const HChar* pathname, Int flags, Int mode ); /* fd_open words like the open(2) system call: diff -r efb6377bb4b5 -r ae0a1b9f3c43 include/pub_tool_libcsetjmp.h --- a/include/pub_tool_libcsetjmp.h Mon Dec 01 23:44:20 2014 +0900 +++ b/include/pub_tool_libcsetjmp.h Thu Mar 31 15:57:55 2016 +0900 @@ -91,7 +91,7 @@ void VG_MINIMAL_LONGJMP(VG_MINIMAL_JMP_BUF(_env)); -#elif defined(VGP_amd64_linux) || defined(VGP_amd64_darwin) +#elif defined(VGP_amd64_linux) || defined(VGP_amd64_darwin) || defined(VGP_amd64_freebsd) || defined(VGP_amd64_openbsd) #define VG_MINIMAL_JMP_BUF(_name) ULong _name [16+1] __attribute__((returns_twice)) @@ -100,7 +100,7 @@ void VG_MINIMAL_LONGJMP(VG_MINIMAL_JMP_BUF(_env)); -#elif defined(VGP_x86_linux) || defined(VGP_x86_darwin) +#elif defined(VGP_x86_linux) || defined(VGP_x86_darwin) || defined(VGP_x86_freebsd) || defined(VGP_x86_openbsd) #define VG_MINIMAL_JMP_BUF(_name) UInt _name [8+1] __attribute__((returns_twice)) diff -r efb6377bb4b5 -r ae0a1b9f3c43 include/pub_tool_libcsignal.h --- a/include/pub_tool_libcsignal.h Mon Dec 01 23:44:20 2014 +0900 +++ b/include/pub_tool_libcsignal.h Thu Mar 31 15:57:55 2016 +0900 @@ -42,6 +42,8 @@ /* --- Mess with the kernel's sig state --- */ extern Int VG_(sigprocmask) ( Int how, const vki_sigset_t* set, vki_sigset_t* oldset ); +extern Int VG_(sigpending) ( vki_sigset_t* set ); +extern Int VG_(sigsuspend) ( const vki_sigset_t* set ); #endif // __PUB_TOOL_LIBCBSIGNAL_H diff -r efb6377bb4b5 -r ae0a1b9f3c43 include/pub_tool_machine.h --- a/include/pub_tool_machine.h Mon Dec 01 23:44:20 2014 +0900 +++ b/include/pub_tool_machine.h Thu Mar 31 15:57:55 2016 +0900 @@ -34,14 +34,14 @@ #include "pub_tool_basics.h" // ThreadID #include "libvex.h" // VexArchInfo -#if defined(VGP_x86_linux) +#if defined(VGP_x86_linux) || defined(VGP_x86_freebsd) || defined(VGP_x86_openbsd) # define VG_MIN_INSTR_SZB 1 // min length of native instruction # define VG_MAX_INSTR_SZB 16 // max length of native instruction # define VG_CLREQ_SZB 14 // length of a client request, may // be larger than VG_MAX_INSTR_SZB # define VG_STACK_REDZONE_SZB 0 // number of addressable bytes below %RSP -#elif defined(VGP_amd64_linux) +#elif defined(VGP_amd64_linux) || defined(VGP_amd64_freebsd) || defined(VGP_amd64_openbsd) # define VG_MIN_INSTR_SZB 1 # define VG_MAX_INSTR_SZB 16 # define VG_CLREQ_SZB 19 diff -r efb6377bb4b5 -r ae0a1b9f3c43 include/pub_tool_redir.h --- a/include/pub_tool_redir.h Mon Dec 01 23:44:20 2014 +0900 +++ b/include/pub_tool_redir.h Thu Mar 31 15:57:55 2016 +0900 @@ -240,7 +240,7 @@ /* --- Soname of the standard C library. --- */ -#if defined(VGO_linux) +#if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd) # define VG_Z_LIBC_SONAME libcZdsoZa // libc.so* #elif defined(VGO_darwin) && (DARWIN_VERS <= DARWIN_10_6) @@ -265,15 +265,20 @@ #endif -/* --- Soname of the GNU C++ library. --- */ +/* --- Sonames of the GNU C++ library. --- */ // Valid on all platforms(?) #define VG_Z_LIBSTDCXX_SONAME libstdcZpZpZa // libstdc++* +#define VG_Z_LIBSUPCXX_SONAME libsupcZpZpZa // libsupc++* /* --- Soname of the pthreads library. --- */ #if defined(VGO_linux) # define VG_Z_LIBPTHREAD_SONAME libpthreadZdsoZd0 // libpthread.so.0 +#elif defined(VGO_freebsd) +# define VG_Z_LIBPTHREAD_SONAME libthrZdsoZa // libthr.so* +#elif defined(VGO_openbsd) +# define VG_Z_LIBPTHREAD_SONAME libpthreadZdsoZa #elif defined(VGO_darwin) # define VG_Z_LIBPTHREAD_SONAME libSystemZdZaZddylib // libSystem.*.dylib #else @@ -306,6 +311,27 @@ #endif +/* --- Sonames for FreeBSD ELF linkers, plus unencoded versions. --- */ + +#if defined(VGO_freebsd) + +#define VG_Z_LD_ELF_SO_1 ldZhelfZdsoZd1 // ld-elf.so.1 +#define VG_U_LD_ELF_SO_1 "ld-elf.so.1" + +#define VG_Z_LD_ELF32_SO_1 ldZhelf32ZdsoZd1 // ld-elf32.so.1 +#define VG_U_LD_ELF32_SO_1 "ld-elf32.so.1" + +#endif + +/* --- Sonames for OpenBSD ELF linkers, plus unencoded versions. --- */ + +#if defined(VGO_openbsd) + +#define VG_Z_LD_ELF_SO_1 ldZdsoZd // ld-elf.so.1 +#define VG_U_LD_ELF_SO_1 "ld.so" + +#endif + /* --- Executable name for Darwin Mach-O linker. --- */ #if defined(VGO_darwin) diff -r efb6377bb4b5 -r ae0a1b9f3c43 include/pub_tool_vki.h --- a/include/pub_tool_vki.h Mon Dec 01 23:44:20 2014 +0900 +++ b/include/pub_tool_vki.h Thu Mar 31 15:57:55 2016 +0900 @@ -50,6 +50,10 @@ # include "vki/vki-linux-drm.h" #elif defined(VGO_darwin) # include "vki/vki-darwin.h" +#elif defined(VGO_freebsd) +# include "vki/vki-freebsd.h" +#elif defined(VGO_openbsd) +# include "vki/vki-openbsd.h" #else # error Unknown Plat/OS #endif diff -r efb6377bb4b5 -r ae0a1b9f3c43 include/pub_tool_vkiscnums.h --- a/include/pub_tool_vkiscnums.h Mon Dec 01 23:44:20 2014 +0900 +++ b/include/pub_tool_vkiscnums.h Thu Mar 31 15:57:55 2016 +0900 @@ -37,6 +37,8 @@ #include "pub_tool_basics.h" // Word +#if !defined(VGO_freebsd) && !defined(VGO_openbsd) + // This converts a syscall number into a string, suitable for printing. It is // needed because some platforms (Darwin) munge sysnums in various ways. // The string is allocated in a static buffer and will be overwritten in the @@ -46,6 +48,27 @@ // Macro provided for backward compatibility purposes. #define VG_SYSNUM_STRING(sysnum) VG_(sysnum_string)(sysnum) +#else + +const HChar* VG_(sysnum_string)(Word sysnum, SizeT n_buf, HChar* buf); +const HChar* VG_(sysnum_string_extra)(Word sysnum, SizeT n_buf, HChar* buf); + +// Macro provided for backward compatibility purposes. +#define VG_SYSNUM_STRING(sysnum) VG_(sysnum_string)(sysnum, 0, NULL) + +#endif + + +#if defined(VGO_freebsd) + // See the FreeBSD-specific case in pub_tool_vkiscnums_asm.h for an + // explanation of why we include this here rather than there. +# include "vki/vki-scnums-freebsd.h" + +#elif defined(VGO_openbsd) + // See the OpenBSD-specific case in pub_tool_vkiscnums_asm.h for an + // explanation of why we include this here rather than there. +# include "vki/vki-scnums-openbsd.h" +#endif #endif // __PUB_TOOL_VKISCNUMS_H diff -r efb6377bb4b5 -r ae0a1b9f3c43 include/pub_tool_vkiscnums_asm.h --- a/include/pub_tool_vkiscnums_asm.h Mon Dec 01 23:44:20 2014 +0900 +++ b/include/pub_tool_vkiscnums_asm.h Thu Mar 31 15:57:55 2016 +0900 @@ -60,6 +60,12 @@ #elif defined(VGP_mips64_linux) # include "vki/vki-scnums-mips64-linux.h" +#elif defined(VGP_x86_freebsd) || defined(VGP_amd64_freebsd) +# include "vki/vki-scnums-freebsd.h" + +#elif defined(VGP_x86_openbsd) || defined(VGP_amd64_openbsd) +# include "vki/vki-scnums-openbsd.h" + #elif defined(VGP_x86_darwin) || defined(VGP_amd64_darwin) # include "vki/vki-scnums-darwin.h" diff -r efb6377bb4b5 -r ae0a1b9f3c43 include/valgrind.h --- a/include/valgrind.h Mon Dec 01 23:44:20 2014 +0900 +++ b/include/valgrind.h Thu Mar 31 15:57:55 2016 +0900 @@ -110,6 +110,10 @@ */ #undef PLAT_x86_darwin #undef PLAT_amd64_darwin +#undef PLAT_x86_freebsd +#undef PLAT_amd64_freebsd +#undef PLAT_x86_openbsd +#undef PLAT_amd64_openbsd #undef PLAT_x86_win32 #undef PLAT_amd64_win64 #undef PLAT_x86_linux @@ -128,6 +132,14 @@ # define PLAT_x86_darwin 1 #elif defined(__APPLE__) && defined(__x86_64__) # define PLAT_amd64_darwin 1 +#elif defined(__FreeBSD__) && defined(__i386__) +# define PLAT_x86_freebsd 1 +#elif defined(__FreeBSD__) && defined(__amd64__) +# define PLAT_amd64_freebsd 1 +#elif defined(__OpenBSD__) && defined(__i386__) +# define PLAT_x86_openbsd 1 +#elif defined(__OpenBSD__) && defined(__amd64__) +# define PLAT_amd64_openbsd 1 #elif (defined(__MINGW32__) && !defined(__MINGW64__)) \ || defined(__CYGWIN32__) \ || (defined(_WIN32) && defined(_M_IX86)) @@ -247,7 +259,8 @@ /* ------------------------- x86-{linux,darwin} ---------------- */ #if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) \ - || (defined(PLAT_x86_win32) && defined(__GNUC__)) + || (defined(PLAT_x86_win32) && defined(__GNUC__)) \ + || defined(PLAT_x86_freebsd) || defined(PLAT_x86_openbsd) typedef struct { @@ -385,7 +398,9 @@ /* ------------------------ amd64-{linux,darwin} --------------- */ #if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) \ - || (defined(PLAT_amd64_win64) && defined(__GNUC__)) + || defined(PLAT_amd64_freebsd) || defined(PLAT_amd64_openbsd) \ + || (defined(PLAT_amd64_win64) && defined(__GNUC__)) \ + || defined(PLAT_amd64_freebsd) typedef struct { @@ -1134,7 +1149,7 @@ /* ------------------------- x86-{linux,darwin} ---------------- */ -#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) +#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) || defined(PLAT_x86_freebsd) || defined(PLAT_x86_openbsd) /* These regs are trashed by the hidden call. No need to mention eax as gcc can already see that, plus causes gcc to bomb. */ @@ -1565,7 +1580,7 @@ /* ------------------------ amd64-{linux,darwin} --------------- */ -#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) +#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) || defined(PLAT_amd64_freebsd) || defined(PLAT_amd64_openbsd) /* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */ diff -r efb6377bb4b5 -r ae0a1b9f3c43 include/vki/vki-amd64-freebsd.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/vki/vki-amd64-freebsd.h Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,224 @@ +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2005 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#ifndef __VKI_AMD64_FREEBSD_H +#define __VKI_AMD64_FREEBSD_H + +/* PAGE_SHIFT determines the page size. */ +#define VKI_PAGE_SHIFT 12 +#define VKI_PAGE_SIZE (1UL << VKI_PAGE_SHIFT) +#define VKI_MAX_PAGE_SHIFT VKI_PAGE_SHIFT +#define VKI_MAX_PAGE_SIZE VKI_PAGE_SIZE + +#define VKI_MINSIGSTKSZ 2048 + +//---------------------------------------------------------------------- +// sys/_sigset.h +//---------------------------------------------------------------------- +#define _VKI_NSIG 128 +#define _VKI_NSIG_WORDS 4 +#define _VKI_NSIG_BPW ((_VKI_NSIG) / (_VKI_NSIG_WORDS)) + +typedef struct { + vki_uint32_t sig[_VKI_NSIG_WORDS]; +} vki_sigset_t; + +struct _vki_fpstate { + unsigned short cwd; + unsigned short swd; + unsigned short twd; + unsigned short fop; + unsigned long rip; + unsigned long rdp; + unsigned int mxcsr; + unsigned int mxcsr_mask; + unsigned int st_space[32]; /* 8*16 bytes for each FP-reg */ + unsigned int xmm_space[64]; /* 16*16 bytes for each XMM-reg */ + unsigned int reserved2[24]; +}; + +struct vki_sigcontext { + vki_sigset_t mask; + long onstack; + long rdi; + long rsi; + long rdx; + long rcx; + long r8; + long r9; + long rax; + long rbx; + long rbp; + long r10; + long r11; + long r12; + long r13; + long r14; + long r15; + long trapno; + long addr; + long flags; + long err; + long rip; + long cs; + long rflags; + long rsp; + long ss; + long len; /* sizeof(mcontext_t) */ + long fpformat; + long ownedfp; + struct _vki_fpstate fpstate; + long spare2[8]; +}; + +/* + * Retrieved from src/sys/amd64/include/reg.h + * Note that on 8.x trapno and err are no-more meaningful, but we + * don't set them anyway. + */ +struct vki_user_regs_struct { + vki_register_t r15; + vki_register_t r14; + vki_register_t r13; + vki_register_t r12; + vki_register_t r11; + vki_register_t r10; + vki_register_t r9; + vki_register_t r8; + vki_register_t rdi; + vki_register_t rsi; + vki_register_t rbp; + vki_register_t rbx; + vki_register_t rdx; + vki_register_t rcx; + vki_register_t rax; + vki_register_t trapno; + vki_register_t err; + vki_register_t rip; + vki_register_t cs; + vki_register_t rflags; + vki_register_t rsp; + vki_register_t ss; +}; + +struct vki_reg_struct { + vki_register_t r_r15; + vki_register_t r_r14; + vki_register_t r_r13; + vki_register_t r_r12; + vki_register_t r_r11; + vki_register_t r_r10; + vki_register_t r_r9; + vki_register_t r_r8; + vki_register_t r_rdi; + vki_register_t r_rsi; + vki_register_t r_rbp; + vki_register_t r_rbx; + vki_register_t r_rdx; + vki_register_t r_rcx; + vki_register_t r_rax; + vki_uint32_t r_trapno; + vki_uint16_t r_fs; + vki_uint16_t r_gs; + vki_uint32_t r_err; + vki_uint16_t r_es; + vki_uint16_t r_ds; + vki_register_t r_rip; + vki_register_t r_cs; + vki_register_t r_rflags; + vki_register_t r_rsp; + vki_register_t r_ss; +}; + +struct vki_fpreg { + unsigned long fpr_env[4]; + unsigned char fpr_acc[8][16]; + unsigned char fpr_xacc[16][16]; + unsigned long fpr_spare[12]; +}; + +struct vki_dbreg { + unsigned long dr[16]; +}; + +typedef vki_register_t vki_elf_greg_t; +typedef struct _vki_fpstate vki_elf_fpregset_t; + +#define VKI_AT_SYSINFO 32 +#define VKI_ELF_NGREG \ + (sizeof (struct vki_user_regs_struct) / sizeof(vki_elf_greg_t)) + +typedef vki_elf_greg_t vki_elf_gregset_t[VKI_ELF_NGREG]; + +struct vki_mcontext { + vki_register_t onstack; /* XXX - sigcontext compat. */ + vki_register_t rdi; /* machine state (struct trapframe) */ + vki_register_t rsi; + vki_register_t rdx; + vki_register_t rcx; + vki_register_t r8; + vki_register_t r9; + vki_register_t rax; + vki_register_t rbx; + vki_register_t rbp; + vki_register_t r10; + vki_register_t r11; + vki_register_t r12; + vki_register_t r13; + vki_register_t r14; + vki_register_t r15; + vki_register_t trapno; + vki_register_t addr; + vki_register_t flags; + vki_register_t err; + vki_register_t rip; + vki_register_t cs; + vki_register_t rflags; + vki_register_t rsp; + vki_register_t ss; + + long len; + long fpformat; + long ownedfp; + struct _vki_fpstate fpstate; + long spare2[8]; +}; + +#define VKI_FPFMT_NODEV 0x10000 +#define VKI_FPFMT_XMM 0x10002 + +#define VKI_FPOWNED_NONE 0x20000 +#define VKI_FPOWNED_FPU 0x20001 +#define VKI_FPOWNED_PCB 0x20002 + +struct vki_sigaction_base { + void (*ksa_handler)(int); + int sa_flags; + vki_sigset_t sa_mask; /* mask last for extensibility */ +}; +typedef struct vki_sigaction_base vki_sigaction_toK_t; +typedef struct vki_sigaction_base vki_sigaction_fromK_t; + +#endif /* __VKI_AMD64_FREEBSD_H */ diff -r efb6377bb4b5 -r ae0a1b9f3c43 include/vki/vki-amd64-openbsd.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/vki/vki-amd64-openbsd.h Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,228 @@ +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2005 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#ifndef __VKI_AMD64_OPENBSD_H +#define __VKI_AMD64_OPENBSD_H + +/* PAGE_SHIFT determines the page size. */ +#define VKI_PAGE_SHIFT 12 +#define VKI_PAGE_SIZE (1UL << VKI_PAGE_SHIFT) +#define VKI_MAX_PAGE_SHIFT VKI_PAGE_SHIFT +#define VKI_MAX_PAGE_SIZE VKI_PAGE_SIZE + +#define VKI_MINSIGSTKSZ 2048 + +//---------------------------------------------------------------------- +// sys/_sigset.h +//---------------------------------------------------------------------- +#define _VKI_NSIG 32 +#if 0 +#define _VKI_NSIG_WORDS 4 +#define _VKI_NSIG_BPW ((_VKI_NSIG) / (_VKI_NSIG_WORDS)) + +typedef struct { + vki_uint32_t sig[_VKI_NSIG_WORDS]; +} vki_sigset_t; +#else +typedef unsigned int vki_sigset_t; +#endif + +struct _vki_fpstate { + unsigned short cwd; + unsigned short swd; + unsigned short twd; + unsigned short fop; + unsigned long rip; + unsigned long rdp; + unsigned int mxcsr; + unsigned int mxcsr_mask; + unsigned int st_space[32]; /* 8*16 bytes for each FP-reg */ + unsigned int xmm_space[64]; /* 16*16 bytes for each XMM-reg */ + unsigned int reserved2[24]; +}; + +struct vki_sigcontext { + vki_sigset_t mask; + long onstack; + long rdi; + long rsi; + long rdx; + long rcx; + long r8; + long r9; + long rax; + long rbx; + long rbp; + long r10; + long r11; + long r12; + long r13; + long r14; + long r15; + long trapno; + long addr; + long flags; + long err; + long rip; + long cs; + long rflags; + long rsp; + long ss; + long len; /* sizeof(mcontext_t) */ + long fpformat; + long ownedfp; + struct _vki_fpstate fpstate; + long spare2[8]; +}; + +/* + * Retrieved from src/sys/amd64/include/reg.h + * Note that on 8.x trapno and err are no-more meaningful, but we + * don't set them anyway. + */ +struct vki_user_regs_struct { + vki_register_t r15; + vki_register_t r14; + vki_register_t r13; + vki_register_t r12; + vki_register_t r11; + vki_register_t r10; + vki_register_t r9; + vki_register_t r8; + vki_register_t rdi; + vki_register_t rsi; + vki_register_t rbp; + vki_register_t rbx; + vki_register_t rdx; + vki_register_t rcx; + vki_register_t rax; + vki_register_t trapno; + vki_register_t err; + vki_register_t rip; + vki_register_t cs; + vki_register_t rflags; + vki_register_t rsp; + vki_register_t ss; +}; + +struct vki_reg_struct { + vki_register_t r_r15; + vki_register_t r_r14; + vki_register_t r_r13; + vki_register_t r_r12; + vki_register_t r_r11; + vki_register_t r_r10; + vki_register_t r_r9; + vki_register_t r_r8; + vki_register_t r_rdi; + vki_register_t r_rsi; + vki_register_t r_rbp; + vki_register_t r_rbx; + vki_register_t r_rdx; + vki_register_t r_rcx; + vki_register_t r_rax; + vki_uint32_t r_trapno; + vki_uint16_t r_fs; + vki_uint16_t r_gs; + vki_uint32_t r_err; + vki_uint16_t r_es; + vki_uint16_t r_ds; + vki_register_t r_rip; + vki_register_t r_cs; + vki_register_t r_rflags; + vki_register_t r_rsp; + vki_register_t r_ss; +}; + +struct vki_fpreg { + unsigned long fpr_env[4]; + unsigned char fpr_acc[8][16]; + unsigned char fpr_xacc[16][16]; + unsigned long fpr_spare[12]; +}; + +struct vki_dbreg { + unsigned long dr[16]; +}; + +typedef vki_register_t vki_elf_greg_t; +typedef struct _vki_fpstate vki_elf_fpregset_t; + +#define VKI_AT_SYSINFO 32 +#define VKI_ELF_NGREG \ + (sizeof (struct vki_user_regs_struct) / sizeof(vki_elf_greg_t)) + +typedef vki_elf_greg_t vki_elf_gregset_t[VKI_ELF_NGREG]; + +struct vki_mcontext { + vki_register_t onstack; /* XXX - sigcontext compat. */ + vki_register_t rdi; /* machine state (struct trapframe) */ + vki_register_t rsi; + vki_register_t rdx; + vki_register_t rcx; + vki_register_t r8; + vki_register_t r9; + vki_register_t rax; + vki_register_t rbx; + vki_register_t rbp; + vki_register_t r10; + vki_register_t r11; + vki_register_t r12; + vki_register_t r13; + vki_register_t r14; + vki_register_t r15; + vki_register_t trapno; + vki_register_t addr; + vki_register_t flags; + vki_register_t err; + vki_register_t rip; + vki_register_t cs; + vki_register_t rflags; + vki_register_t rsp; + vki_register_t ss; + + long len; + long fpformat; + long ownedfp; + struct _vki_fpstate fpstate; + long spare2[8]; +}; + +#define VKI_FPFMT_NODEV 0x10000 +#define VKI_FPFMT_XMM 0x10002 + +#define VKI_FPOWNED_NONE 0x20000 +#define VKI_FPOWNED_FPU 0x20001 +#define VKI_FPOWNED_PCB 0x20002 + +struct vki_sigaction_base { + void (*ksa_handler)(int); + vki_sigset_t sa_mask; /* mask last for extensibility */ + int sa_flags; +}; +typedef struct vki_sigaction_base vki_sigaction_toK_t; +typedef struct vki_sigaction_base vki_sigaction_fromK_t; + +#endif /* __VKI_AMD64_OPENBSD_H */ diff -r efb6377bb4b5 -r ae0a1b9f3c43 include/vki/vki-freebsd.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/vki/vki-freebsd.h Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,2133 @@ + +/*--------------------------------------------------------------------*/ +/*--- FreeBSD-specific kernel interface. vki-freebsd.h ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2005 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +/* This file defines types and constants for the kernel interface, and to + make that clear everything is prefixed VKI_/vki_. + + All code is copied verbatim from kernel source files, except that: + - VKI_/vki_ prefixes are added + - some extra explanatory comments are included; they are all within + "[[ ]]" + - for some types, we only care about the size; for a few of them (big + ones that are painful to fully drag in here), a VKI_SIZEOF_* constant + is used. + + The files the code is taken from is indicated. + + Note especially that the types are not the glibc versions, many of which + are different to those in here. + + Also note that this file contains all the generic header info, ie. that + from linux/include/linux/ *.h. The arch-specific header info, eg. that + from linux/include/asm-i386/ *.h, is in vki-$PLATFORM.h and + vki_posixtypes-$PLATFORM.h. (Two files are required to avoid + circular dependencies between the generic VKI header and the + arch-specific VKI header. It's possible in the future, as more stuff + gets pulled in, that we might have to split files up some more to avoid + further circular dependencies.) + + Finally, note that it is assumed that __KERNEL__ is set for all these + definitions, which affects some of them. +*/ + +#ifndef __VKI_FREEBSD_H +#define __VKI_FREEBSD_H + +//---------------------------------------------------------------------- +// Arch-specific POSIX types +//---------------------------------------------------------------------- + +#if defined(VGA_x86) +# include "vki-machine-types-x86-freebsd.h" +#elif defined(VGA_amd64) +# include "vki-machine-types-amd64-freebsd.h" +#else +# error Unknown platform +#endif + +#include + + +//---------------------------------------------------------------------- +// From sys/select.h +//---------------------------------------------------------------------- + +typedef unsigned long __vki_fd_mask; + +#undef __VKI_NFDBITS +#define __VKI_NFDBITS (8 * sizeof(__vki_fd_mask)) + +#undef __VKI_FD_SETSIZE +#define __VKI_FD_SETSIZE 1024U + +#undef __VKI_FDSET_LONGS +#define __VKI_FDSET_LONGS (__VKI_FD_SETSIZE/__VKI_NFDBITS) + +#undef __VKI_FDELT +#define __VKI_FDELT(d) ((d) / __VKI_NFDBITS) + +#undef __VKI_FDMASK +#define __VKI_FDMASK(d) (1UL << ((d) % __VKI_NFDBITS)) + +typedef struct { + unsigned long fds_bits [__VKI_FDSET_LONGS]; +} __vki_fd_set; + +//---------------------------------------------------------------------- +// sys/_types.h +//---------------------------------------------------------------------- +/* MD QQQ 32 on 64 */ +typedef long __vki_key_t; +typedef long __vki_suseconds_t; +typedef struct __timer *__vki_timer_t; +typedef struct __mq *__vki_mqd_t; + +/* MI */ +typedef vki_uint32_t __vki_blksize_t; +typedef vki_int64_t __vki_blkcnt_t; +typedef vki_int32_t __vki_clockid_t; +typedef vki_int32_t __vki_ct_rune_t; +typedef vki_uint32_t __vki_fflags_t; +typedef vki_uint64_t __vki_fsblkcnt_t; +typedef vki_uint64_t __vki_fsfilcnt_t; +typedef vki_uint32_t __vki_gid_t; +typedef vki_int64_t __vki_id_t; +typedef vki_uint32_t __vki_ino_t; +typedef vki_int32_t __vki_lwpid_t; +typedef vki_uint16_t __vki_mode_t; +typedef vki_uint16_t __vki_nlink_t; +typedef vki_int64_t __vki_off_t; +typedef vki_int32_t __vki_pid_t; +typedef vki_int64_t __vki_rlim_t; +typedef vki_uint8_t __vki_sa_family_t; +typedef vki_uint32_t __vki_socklen_t; +typedef vki_uint32_t __vki_uid_t; +typedef vki_int32_t __vki_useconds_t; +typedef __vki_ct_rune_t __vki_rune_t; +typedef __vki_ct_rune_t __vki_wchar_t; +typedef __vki_ct_rune_t __vki_wint_t; +typedef vki_uint32_t __vki_dev_t; +typedef vki_uint32_t __vki_fixpt_t; + + +//---------------------------------------------------------------------- +// sys/types.h +//---------------------------------------------------------------------- + +typedef vki_uint8_t vki_u_int8_t; +typedef vki_uint16_t vki_u_int16_t; +typedef vki_uint32_t vki_u_int32_t; +typedef vki_uint64_t vki_u_int64_t; + +typedef vki_uint64_t vki_u_quad_t; +typedef vki_int64_t vki_quad_t; +typedef __vki_caddr_t vki_caddr_t; +typedef __const __vki_caddr_t vki_c_caddr_t; +typedef __volatile __vki_caddr_t vki_v_caddr_t; + +typedef __vki_blksize_t vki_blksize_t; +typedef __vki_blkcnt_t vki_blkcnt_t; +typedef __vki_clock_t vki_clock_t; +typedef __vki_clockid_t vki_clockid_t; +typedef __vki_dev_t vki_dev_t; +typedef __vki_fflags_t vki_fflags_t; +typedef __vki_fixpt_t vki_fixpt_t; +typedef __vki_fsblkcnt_t vki_fsblkcnt_t; +typedef __vki_fsfilcnt_t vki_fsfilcnt_t; +typedef __vki_gid_t vki_gid_t; +typedef vki_uint32_t vki_in_addr_t; +typedef vki_uint16_t vki_in_port_t; +typedef __vki_id_t vki_id_t; +typedef __vki_ino_t vki_ino_t; +typedef __vki_key_t vki_key_t; +typedef __vki_lwpid_t vki_lwpid_t; +typedef __vki_mode_t vki_mode_t; +typedef __vki_nlink_t vki_nlink_t; +typedef __vki_off_t vki_off_t; +typedef __vki_pid_t vki_pid_t; +typedef __vki_register_t vki_register_t; +typedef __vki_rlim_t vki_rlim_t; +typedef __vki_segsz_t vki_segsz_t; +typedef __vki_size_t vki_size_t; +typedef __vki_ssize_t vki_ssize_t; +typedef __vki_suseconds_t vki_suseconds_t; +typedef __vki_time_t vki_time_t; +typedef __vki_timer_t vki_timer_t; +typedef __vki_mqd_t vki_mqd_t; +typedef __vki_u_register_t vki_u_register_t; +typedef __vki_uid_t vki_uid_t; +typedef __vki_useconds_t vki_useconds_t; + +typedef __vki_vm_offset_t vki_vm_offset_t; +typedef __vki_vm_ooffset_t vki_vm_ooffset_t; +typedef __vki_vm_paddr_t vki_vm_paddr_t; +typedef __vki_vm_pindex_t vki_vm_pindex_t; +typedef __vki_vm_size_t vki_vm_size_t; + +//---------------------------------------------------------------------- +// sys/select.h +//---------------------------------------------------------------------- + +typedef __vki_fd_set vki_fd_set; + +//---------------------------------------------------------------------- +// Now the rest of the arch-specific stuff +//---------------------------------------------------------------------- + +#if defined(VGA_x86) +# include "vki-x86-freebsd.h" +#elif defined(VGA_amd64) +# include "vki-amd64-freebsd.h" +#elif defined(VGA_ppc32) +# include "vki-ppc32-freebsd.h" +#elif defined(VGA_ppc64) +# include "vki-ppc64-freebsd.h" +#else +# error Unknown platform +#endif + +//---------------------------------------------------------------------- +// linux and freebsd version hacks +//---------------------------------------------------------------------- +#ifndef ELFMAG +#define ELFMAG "\177ELF" /* magic string */ +#endif +#ifndef SELFMAG +#define SELFMAG 4 /* magic string size */ +#endif + +//---------------------------------------------------------------------- +// From sys/syslimits.h +//---------------------------------------------------------------------- + +#define VKI_PATH_MAX 1024 + + +//---------------------------------------------------------------------- +// From sys/timespec.h +//---------------------------------------------------------------------- + +struct vki_timespec { + vki_time_t tv_sec; /* seconds */ + long tv_nsec; /* nanoseconds */ +}; + +struct vki_itimerspec { + struct vki_timespec it_interval; /* timer period */ + struct vki_timespec it_value; /* timer expiration */ +}; + +//---------------------------------------------------------------------- +// From sys/_time.h +//---------------------------------------------------------------------- + +struct vki_timeval { + vki_time_t tv_sec; /* seconds */ + vki_suseconds_t tv_usec; /* microseconds */ +}; + +//---------------------------------------------------------------------- +// From sys/time.h +//---------------------------------------------------------------------- + +#define VKI_CLOCK_REALTIME 0 +#define VKI_CLOCK_MONOTONIC 1 +#define VKI_CLOCK_PROCESS_CPUTIME_ID 2 +#define VKI_CLOCK_THREAD_CPUTIME_ID 3 + +struct vki_timezone { + int tz_minuteswest; /* minutes west of Greenwich */ + int tz_dsttime; /* type of dst correction */ +}; + +struct vki_itimerval { + struct vki_timeval it_interval; /* timer interval */ + struct vki_timeval it_value; /* current value */ +}; + +//---------------------------------------------------------------------- +// From sys/timex.h +//---------------------------------------------------------------------- + +struct vki_ntptimeval { + struct vki_timespec time; + long maxerror; + long esterror; + long tai; + int time_state; +}; + +struct vki_timex { + unsigned int modes; /* mode selector */ + long offset; /* time offset (usec) */ + long freq; /* frequency offset (scaled ppm) */ + long maxerror; /* maximum error (usec) */ + long esterror; /* estimated error (usec) */ + int status; /* clock command/status */ + long constant; /* pll time constant */ + long precision; /* clock precision (usec) (read only) */ + long tolerance; /* clock frequency tolerance (ppm) + * (read only) + */ + long ppsfreq; /* pps frequency (scaled ppm) (ro) */ + long jitter; /* pps jitter (us) (ro) */ + int shift; /* interval duration (s) (shift) (ro) */ + long stabil; /* pps stability (scaled ppm) (ro) */ + long jitcnt; /* jitter limit exceeded (ro) */ + long calcnt; /* calibration intervals (ro) */ + long errcnt; /* calibration errors (ro) */ + long stbcnt; /* stability limit exceeded (ro) */ +}; + +#define MOD_OFFSET 0x0001 /* time offset */ +#define MOD_FREQUENCY 0x0002 /* frequency offset */ +#define MOD_MAXERROR 0x0004 /* maximum time error */ +#define MOD_ESTERROR 0x0008 /* estimated time error */ +#define MOD_STATUS 0x0010 /* clock status */ +#define MOD_TIMECONST 0x0020 /* pll time constant */ +#define MOD_PPSMAX 0x0040 +#define MOD_TAI 0x0080 +#define MOD_MICRO 0x1000 +#define MOD_NANO 0x2000 +#define MOD_CLKB 0x4000 +#define MOD_CLKA 0x8000 + +//---------------------------------------------------------------------- +// From sys/times.h +//---------------------------------------------------------------------- + +struct vki_tms { + vki_clock_t tms_utime; + vki_clock_t tms_stime; + vki_clock_t tms_cutime; + vki_clock_t tms_cstime; +}; + +//---------------------------------------------------------------------- +// From sys/stat.h +//---------------------------------------------------------------------- + +/* QQQ 4.x stat layout */ +struct vki_stat { + vki_dev_t st_dev; + vki_ino_t st_ino; + vki_mode_t st_mode; + vki_nlink_t st_nlink; + vki_uid_t st_uid; + vki_gid_t st_gid; + vki_dev_t st_rdev; +#if 0 + struct vki_timespec st_atimespec; + struct vki_timespec st_mtimespec; + struct vki_timespec st_ctimespec; +#else + vki_time_t st_atime; + long st_atime_nsec; + vki_time_t st_mtime; + long st_mtime_nsec; + vki_time_t st_ctime; + long st_ctime_nsec; +#endif + vki_off_t st_size; + vki_blkcnt_t st_blocks; + vki_blksize_t st_blksize; + vki_fflags_t st_flags; + vki_uint32_t st_gen; + vki_int32_t st_lspare; + struct vki_timespec st_birthtimespec; + unsigned int :(8 / 2) * (16 - (int)sizeof(struct vki_timespec)); + unsigned int :(8 / 2) * (16 - (int)sizeof(struct vki_timespec)); +}; + + +//---------------------------------------------------------------------- +// From linux-2.6.8.1/include/linux/sched.h +//---------------------------------------------------------------------- + +struct vki_sched_param { + int sched_priority; +}; + +//---------------------------------------------------------------------- +// From sys/signal.h +//---------------------------------------------------------------------- + +#define VKI_SIG_BLOCK 1 /* block specified signal set */ +#define VKI_SIG_UNBLOCK 2 /* unblock specified signal set */ +#define VKI_SIG_SETMASK 3 /* set specified signal set */ + +#define VKI_SIG_DFL ((__vki_sighandler_t)0) +#define VKI_SIG_IGN ((__vki_sighandler_t)1) +#define VKI_SIG_ERR ((__vki_sighandler_t)-1) + +typedef void __vki_signalfn_t(int); +typedef __vki_signalfn_t *__vki_sighandler_t; + +#define VKI_SIGHUP 1 +#define VKI_SIGINT 2 +#define VKI_SIGQUIT 3 +#define VKI_SIGILL 4 +#define VKI_SIGTRAP 5 +#define VKI_SIGABRT 6 +#define VKI_SIGEMT 7 +#define VKI_SIGFPE 8 +#define VKI_SIGKILL 9 +#define VKI_SIGBUS 10 +#define VKI_SIGSEGV 11 +#define VKI_SIGSYS 12 +#define VKI_SIGPIPE 13 +#define VKI_SIGALRM 14 +#define VKI_SIGTERM 15 +#define VKI_SIGURG 16 +#define VKI_SIGSTOP 17 +#define VKI_SIGTSTP 18 +#define VKI_SIGCONT 19 +#define VKI_SIGCHLD 20 +#define VKI_SIGTTIN 21 +#define VKI_SIGTTOU 22 +#define VKI_SIGIO 23 +#define VKI_SIGXCPU 24 +#define VKI_SIGXFSZ 25 +#define VKI_SIGVTALRM 26 +#define VKI_SIGPROF 27 +#define VKI_SIGWINCH 28 +#define VKI_SIGINFO 29 +#define VKI_SIGUSR1 30 +#define VKI_SIGUSR2 31 +#define VKI_SIGTHR 32 + +#define VKI_SIGRTMIN 65 +#define VKI_SIGRTMAX 126 + +#define VKI_SA_ONSTACK 0x0001 +#define VKI_SA_RESTART 0x0002 +#define VKI_SA_RESETHAND 0x0004 +#define VKI_SA_NOCLDSTOP 0x0008 +#define VKI_SA_NODEFER 0x0010 +#define VKI_SA_NOCLDWAIT 0x0020 +#define VKI_SA_SIGINFO 0x0040 + +#define VKI_SS_ONSTACK 0x0001 +#define VKI_SS_DISABLE 0x0004 + +#define VKI_SA_ONESHOT VKI_SA_RESETHAND +#define VKI_SA_NOMASK VKI_SA_NODEFER + +struct vki_sigaction { + __vki_sighandler_t ksa_handler; + int sa_flags; + vki_sigset_t sa_mask; +}; + +typedef struct vki_sigaltstack { + void *ss_sp; + vki_size_t ss_size; + int ss_flags; +} vki_stack_t; + +typedef union vki_sigval { + int sival_int; + void *sival_ptr; +} vki_sigval_t; + +#if 0 /* freebsd6 */ +typedef struct vki_siginfo { + int si_signo; + int si_errno; + int si_code; + vki_pid_t si_pid; + vki_uid_t si_uid; + int si_status; + void *si_addr; + vki_sigval_t si_value; + + union { + + /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */ + struct { + int _trapno; /* TRAP # which caused the signal */ + } _sigfault; + + /* POSIX.1b timers */ + struct { + int _timerid; /* timer id */ + int _overrun; /* overrun count */ + } _timer; + + struct { + int _mqd; + } _mesgq; + + /* SIGPOLL */ + struct { + long _band; /* POLL_IN, POLL_OUT, POLL_MSG */ + } _sigpoll; + + struct { + long __spare1__; + int __spare2[7]; + } __spare__; + } _sifields; +} vki_siginfo_t; +#endif +typedef struct vki_siginfo { + int si_signo; + int si_errno; + int si_code; + vki_pid_t si_pid; + vki_uid_t si_uid; + int si_status; + void *si_addr; + vki_sigval_t si_value; +// 666: not valid. switch to above def +#ifdef si_band +#undef si_band +#endif + long si_band; + int __spare__[7]; +} vki_siginfo_t; + +/* + * si_code values + */ +#define VKI_SI_USER 0x10001 /* sent by kill, sigsend, raise */ +#define VKI_SI_QUEUE 0x10002 +#define VKI_SI_TIMER 0x10003 +#define VKI_SI_ASYNCIO 0x10004 +#define VKI_SI_MESGQ 0x10005 + +/* + * SIGILL si_codes + */ +#define VKI_ILL_ILLOPC 1 /* illegal opcode */ +#define VKI_ILL_ILLOPN 2 /* illegal operand */ +#define VKI_ILL_ILLADR 3 /* illegal addressing mode */ +#define VKI_ILL_ILLTRP 4 /* illegal trap */ +#define VKI_ILL_PRVOPC 5 /* privileged opcode */ +#define VKI_ILL_PRVREG 6 /* privileged register */ +#define VKI_ILL_COPROC 7 /* coprocessor error */ +#define VKI_ILL_BADSTK 8 /* internal stack error */ + +/* + * SIGFPE si_codes + */ +#define VKI_FPE_INTOVF 1 /* integer overflow */ +#define VKI_FPE_INTDIV 2 /* integer divide by zero */ +#define VKI_FPE_FLTDIV 3 /* floating point divide by zero */ +#define VKI_FPE_FLTOVF 4 /* floating point overflow */ +#define VKI_FPE_FLTUND 5 /* floating point underflow */ +#define VKI_FPE_FLTRES 6 /* floating point inexact result */ +#define VKI_FPE_FLTINV 7 /* floating point invalid operation */ +#define VKI_FPE_FLTSUB 8 /* subscript out of range */ + +/* + * SIGSEGV si_codes + */ +#define VKI_SEGV_MAPERR 1 /* address not mapped to object */ +#define VKI_SEGV_ACCERR 2 /* invalid permissions for mapped object */ +/* XXX i386 and amd64 specific */ +#define VKI_SEGV_PAGE_FAULT 12 + +/* + * SIGBUS si_codes + */ +#define VKI_BUS_ADRALN 1 /* invalid address alignment */ +#define VKI_BUS_ADRERR 2 /* non-existant physical address */ +#define VKI_BUS_OBJERR 3 /* object specific hardware error */ + +/* + * SIGTRAP si_codes + */ +#define VKI_TRAP_BRKPT 1 /* process breakpoint */ +#define VKI_TRAP_TRACE 2 /* process trace trap */ + + +#if 0 /* freebsd-6 */ +typedef struct vki_sigevent { + int sigev_notify; + int sigev_signo; + vki_sigval_t sigev_value; + union { + int _threadid; + + struct { + void (*_function)(vki_sigval_t); + void *_attribute; /* really pthread_attr_t */ + } _sigev_thread; + long __spare__[8]; + } _sigev_un; +} vki_sigevent_t; +#endif + +struct vki_sigevent { + int sigev_notify; /* Notification type */ + union { + int __sigev_signo; /* Signal number */ + int __sigev_notify_kqueue; + } __sigev_u; + vki_sigval_t sigev_value; /* Signal value */ +}; +#if 0 +#define sigev_signo __sigev_u.__sigev_signo +#define sigev_notify_kqueue __sigev_u.__sigev_notify_kqueue +#endif + +//---------------------------------------------------------------------- +// From sys/_iovec.h +//---------------------------------------------------------------------- + +struct vki_iovec +{ + void *iov_base; + __vki_size_t iov_len; +}; + +//---------------------------------------------------------------------- +// From sys/socket.h +//---------------------------------------------------------------------- + +typedef __vki_sa_family_t vki_sa_family_t; +typedef __vki_socklen_t vki_socklen_t; + +struct vki_sockaddr { + vki_uint8_t sa_len; + vki_sa_family_t sa_family; /* address family, AF_xxx */ + char sa_data[14]; /* 14 bytes of protocol address */ +}; + +struct vki_msghdr { + void * msg_name; /* Socket name */ + vki_socklen_t msg_namelen; /* Length of name */ + struct vki_iovec * msg_iov; /* Data blocks */ + int msg_iovlen; /* Number of blocks */ + void * msg_control; /* Per protocol magic (eg BSD file descriptor passing) */ + vki_socklen_t msg_controllen; /* Length of cmsg list */ + int msg_flags; +}; + +struct vki_cmsghdr { + vki_socklen_t cmsg_len; /* data byte count, including hdr */ + int cmsg_level; /* originating protocol */ + int cmsg_type; /* protocol-specific type */ +}; + +#define __VKI_CMSG_NXTHDR(ctl, len, cmsg) __vki_cmsg_nxthdr((ctl),(len),(cmsg)) +#define VKI_CMSG_NXTHDR(mhdr, cmsg) vki_cmsg_nxthdr((mhdr), (cmsg)) + +#define VKI_CMSG_ALIGN(len) ( ((len)+sizeof(long)-1) & ~(sizeof(long)-1) ) + +#define VKI_CMSG_DATA(cmsg) ((void *)((char *)(cmsg) + VKI_CMSG_ALIGN(sizeof(struct vki_cmsghdr)))) + +#define __VKI_CMSG_FIRSTHDR(ctl,len) ((len) >= sizeof(struct vki_cmsghdr) ? \ + (struct vki_cmsghdr *)(ctl) : \ + (struct vki_cmsghdr *)NULL) +#define VKI_CMSG_FIRSTHDR(msg) __VKI_CMSG_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen) + +// [[Urgh, this is revolting...] +// QQQ check +static __inline struct vki_cmsghdr * __vki_cmsg_nxthdr(void *__ctl, vki_socklen_t __size, + struct vki_cmsghdr *__cmsg) +{ + struct vki_cmsghdr * __ptr; + + __ptr = (struct vki_cmsghdr*)(((unsigned char *) __cmsg) + VKI_CMSG_ALIGN(__cmsg->cmsg_len)); + if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size) + return (struct vki_cmsghdr *)0; + + return __ptr; +} + +static __inline struct vki_cmsghdr * vki_cmsg_nxthdr (struct vki_msghdr *__msg, struct vki_cmsghdr *__cmsg) +{ + return __vki_cmsg_nxthdr(__msg->msg_control, __msg->msg_controllen, __cmsg); +} + +#define VKI_SCM_RIGHTS 0x01 /* rw: access rights (array of int) */ + +#define VKI_AF_UNIX 1 /* Unix domain sockets */ +#define VKI_AF_INET 2 /* Internet IP Protocol */ +#define VKI_AF_INET6 28 /* IP version 6 */ + +#define VKI_MSG_NOSIGNAL 0x20000 /* Do not generate SIGPIPE */ + +#define VKI_SOL_SOCKET 0xffff + +#define VKI_SO_TYPE 0x1008 + +#define VKI_SOCK_STREAM 1 + +#include + +#define VKI_TCP_NODELAY TCP_NODELAY + +#include + +#define VKI_IPPROTO_TCP IPPROTO_TCP + +//---------------------------------------------------------------------- +// From netinet/in.h +//---------------------------------------------------------------------- + +struct vki_in_addr { + vki_in_addr_t s_addr; +}; + +/* Structure describing an Internet (IP) socket address. */ +#define __VKI_SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */ +struct vki_sockaddr_in { + vki_uint8_t sin_len; + vki_sa_family_t sin_family; /* Address family */ + vki_in_port_t sin_port; /* Port number */ + struct vki_in_addr sin_addr; /* Internet address */ + char sin_zero[8]; +}; + +//---------------------------------------------------------------------- +// From netinet6/in6.h +//---------------------------------------------------------------------- + +struct vki_in6_addr +{ + union + { + vki_uint8_t u6_addr8[16]; + vki_uint16_t u6_addr16[8]; + vki_uint32_t u6_addr32[4]; + } vki_in6_u; +#define vki_s6_addr vki_in6_u.u6_addr8 +#define vki_s6_addr16 vki_in6_u.u6_addr16 +#define vki_s6_addr32 vki_in6_u.u6_addr32 +}; + +struct vki_sockaddr_in6 { + vki_uint8_t sin6_len; + vki_sa_family_t sin6_family; /* AF_INET6 */ + vki_uint16_t sin6_port; /* Transport layer port # */ + vki_uint32_t sin6_flowinfo; /* IPv6 flow information */ + struct vki_in6_addr sin6_addr; /* IPv6 address */ + vki_uint32_t sin6_scope_id; /* scope id (new in RFC2553) */ +}; + +//---------------------------------------------------------------------- +// From sys/un.h +//---------------------------------------------------------------------- + +#define VKI_UNIX_PATH_MAX 104 /* QQQ overridden by sun_len */ + +struct vki_sockaddr_un { + unsigned char sun_len; + vki_sa_family_t sun_family; /* AF_UNIX */ + char sun_path[VKI_UNIX_PATH_MAX]; /* pathname */ +}; + +#if 0 +//---------------------------------------------------------------------- +// From linux-2.6.8.1/include/linux/if.h +//---------------------------------------------------------------------- + +#define VKI_IFNAMSIZ 16 + +struct vki_ifmap +{ + unsigned long mem_start; + unsigned long mem_end; + unsigned short base_addr; + unsigned char irq; + unsigned char dma; + unsigned char port; + /* 3 bytes spare */ +}; + +struct vki_if_settings +{ + unsigned int type; /* Type of physical device or protocol */ + unsigned int size; /* Size of the data allocated by the caller */ + union { + // [[Nb: converted these all to void* to avoid pulling in + // unnecessary headers]]] + /* {atm/eth/dsl}_settings anyone ? */ + void /*raw_hdlc_proto */__user *raw_hdlc; + void /*cisco_proto */__user *cisco; + void /*fr_proto */__user *fr; + void /*fr_proto_pvc */__user *fr_pvc; + void /*fr_proto_pvc_info */__user *fr_pvc_info; + + /* interface settings */ + void /*sync_serial_settings */__user *sync; + void /*te1_settings */__user *te1; + } ifs_ifsu; +}; + +struct vki_ifreq +{ +#define VKI_IFHWADDRLEN 6 + union + { + char ifrn_name[VKI_IFNAMSIZ]; /* if name, e.g. "en0" */ + } ifr_ifrn; + + union { + struct vki_sockaddr ifru_addr; + struct vki_sockaddr ifru_dstaddr; + struct vki_sockaddr ifru_broadaddr; + struct vki_sockaddr ifru_netmask; + struct vki_sockaddr ifru_hwaddr; + short ifru_flags; + int ifru_ivalue; + int ifru_mtu; + struct vki_ifmap ifru_map; + char ifru_slave[VKI_IFNAMSIZ]; /* Just fits the size */ + char ifru_newname[VKI_IFNAMSIZ]; + void __user * ifru_data; + struct vki_if_settings ifru_settings; + } ifr_ifru; +}; + +#define vki_ifr_name ifr_ifrn.ifrn_name /* interface name */ +#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */ +#define ifr_addr ifr_ifru.ifru_addr /* address */ +#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */ +#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ +#define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */ +#define vki_ifr_flags ifr_ifru.ifru_flags /* flags */ +#define vki_ifr_metric ifr_ifru.ifru_ivalue /* metric */ +#define vki_ifr_mtu ifr_ifru.ifru_mtu /* mtu */ +#define ifr_map ifr_ifru.ifru_map /* device map */ +#define ifr_slave ifr_ifru.ifru_slave /* slave device */ +#define vki_ifr_data ifr_ifru.ifru_data /* for use by interface */ +#define vki_ifr_ifindex ifr_ifru.ifru_ivalue /* interface index */ +#define ifr_bandwidth ifr_ifru.ifru_ivalue /* link bandwidth */ +#define ifr_qlen ifr_ifru.ifru_ivalue /* Queue length */ +#define ifr_newname ifr_ifru.ifru_newname /* New name */ +#define ifr_settings ifr_ifru.ifru_settings /* Device/proto settings*/ + +struct vki_ifconf +{ + int ifc_len; /* size of buffer */ + union + { + char __user *ifcu_buf; + struct vki_ifreq __user *ifcu_req; + } ifc_ifcu; +}; +#define vki_ifc_buf ifc_ifcu.ifcu_buf /* buffer address */ + +//---------------------------------------------------------------------- +// From linux-2.6.8.1/include/linux/if_arp.h +//---------------------------------------------------------------------- + +struct vki_arpreq { + struct vki_sockaddr arp_pa; /* protocol address */ + struct vki_sockaddr arp_ha; /* hardware address */ + int arp_flags; /* flags */ + struct vki_sockaddr arp_netmask; /* netmask (only for proxy arps) */ + char arp_dev[16]; +}; + +//---------------------------------------------------------------------- +// From linux-2.6.8.1/include/linux/route.h +//---------------------------------------------------------------------- + +struct vki_rtentry +{ + unsigned long rt_pad1; + struct vki_sockaddr rt_dst; /* target address */ + struct vki_sockaddr rt_gateway; /* gateway addr (RTF_GATEWAY) */ + struct vki_sockaddr rt_genmask; /* target network mask (IP) */ + unsigned short rt_flags; + short rt_pad2; + unsigned long rt_pad3; + void *rt_pad4; + short rt_metric; /* +1 for binary compatibility! */ + char __user *rt_dev; /* forcing the device at add */ + unsigned long rt_mtu; /* per route MTU/Window */ +// [[Not important for Valgrind]] +//#ifndef __KERNEL__ +//#define rt_mss rt_mtu /* Compatibility :-( */ +//#endif + unsigned long rt_window; /* Window clamping */ + unsigned short rt_irtt; /* Initial RTT */ +}; +#endif + +// QQQ sort + +//---------------------------------------------------------------------- +// From sys/mount.h +//---------------------------------------------------------------------- + +typedef struct vki_fsid { vki_int32_t val[2]; } vki_fsid_t; +#define VKI_OMFSNAMELEN 16 +#define VKI_OMNAMELEN (88 - 2 * sizeof(long)) +#define VKI_MFSNAMELEN 16 +#define VKI_MNAMELEN 88 + +struct vki_statfs4 { + long f_spare2; + long f_bsize; + long f_iosize; + long f_blocks; + long f_bfree; + long f_bavail; + long f_files; + long f_ffree; + vki_fsid_t f_fsid; + vki_uid_t f_owner; + vki_int32_t f_type; + vki_int32_t f_flags; + long f_syncwrites; + long f_asyncwrites; + char f_fstypename[VKI_OMFSNAMELEN]; + char f_mntonname[VKI_OMNAMELEN]; + long f_syncreads; + long f_asyncreads; + vki_int16_t f_spares1; + char f_mntfromnname[VKI_OMNAMELEN]; + vki_int16_t f_spares2; + long f_spare[2]; +}; + +struct vki_statfs { + vki_uint32_t f_version; + vki_uint32_t f_type; + vki_uint64_t f_flags; + vki_uint64_t f_bsize; + vki_uint64_t f_iosize; + vki_uint64_t f_blocks; + vki_uint64_t f_bfree; + vki_int64_t f_bavail; + vki_uint64_t f_files; + vki_int64_t f_ffree; + vki_uint64_t f_syncwrites; + vki_uint64_t f_asyncwrites; + vki_uint64_t f_syncreads; + vki_uint64_t f_asyncreads; + vki_uint64_t f_spare[10]; + vki_uint32_t f_namemax; + vki_uid_t f_owner; + vki_fsid_t f_fsid; + char f_charspare[80]; + char f_fstypename[VKI_MFSNAMELEN]; + char f_mntfromnname[VKI_MNAMELEN]; + char f_mntonname[VKI_MNAMELEN]; +}; + +#define MAXFIDSZ 16 + +struct vki_fid { + vki_uint16_t fid_len; + vki_uint16_t fid_reserved; + char fid_data[MAXFIDSZ]; +}; + +struct vki_fhandle { + vki_fsid_t fh_fsid; + struct vki_fid fh_fid; +}; + +#define VKI_MNAMELEN6 88 +struct vki_statfs6 { + vki_uint32_t f_version; + vki_uint32_t f_type; + vki_uint64_t f_flags; + vki_uint64_t f_bsize; + vki_uint64_t f_iosize; + vki_uint64_t f_blocks; + vki_uint64_t f_bfree; + vki_int64_t f_bavail; + vki_uint64_t f_files; + vki_int64_t f_ffree; + vki_int64_t f_syncwrites; + vki_int64_t f_asyncwrites; + vki_int64_t f_syncreads; + vki_int64_t f_asyncreads; + vki_uint64_t f_spare[10]; + vki_uint32_t f_namemax; + vki_uid_t f_owner; + vki_fsid_t f_fsid; + char f_charspare[80]; + char f_fstypename[VKI_MFSNAMELEN]; + char f_mntfromnname[VKI_MNAMELEN6]; + char f_mntonname[VKI_MNAMELEN6]; +}; + +//---------------------------------------------------------------------- +// From sys/ttycom.h +//---------------------------------------------------------------------- + +struct vki_winsize { + unsigned short ws_row; + unsigned short ws_col; + unsigned short ws_xpixel; + unsigned short ws_ypixel; +}; + + +//---------------------------------------------------------------------- +// From sys/termios.h +//---------------------------------------------------------------------- + +typedef unsigned int vki_tcflag_t; +typedef unsigned char vki_cc_t; +typedef unsigned int vki_speed_t; + +#define VKI_NCCS 20 +struct vki_termios { + vki_tcflag_t c_iflag; /* input mode flags */ + vki_tcflag_t c_oflag; /* output mode flags */ + vki_tcflag_t c_cflag; /* control mode flags */ + vki_tcflag_t c_lflag; /* local mode flags */ + vki_cc_t c_cc[VKI_NCCS]; /* control characters */ + vki_speed_t c_ispeed; + vki_speed_t c_ospeed; +}; + +//---------------------------------------------------------------------- +// From sys/ioccom.h +//---------------------------------------------------------------------- + +/* QQQ keep linux's naming, but use our layout */ + +/* + * We actually have a 16 bit "base" ioctl, which may or may not be decoded + * into number/group + */ +#define _VKI_IOC_BASEBITS 16 +#define _VKI_IOC_NRBITS 8 /* "num" on freebsd */ +#define _VKI_IOC_TYPEBITS 8 /* "group" on freebsd */ + +#define _VKI_IOC_SIZEBITS 13 +#define _VKI_IOC_DIRBITS 3 + +#define _VKI_IOC_BASEMASK ((1ul << _VKI_IOC_BASEBITS)-1) +#define _VKI_IOC_NRMASK ((1ul << _VKI_IOC_NRBITS)-1) +#define _VKI_IOC_TYPEMASK ((1ul << _VKI_IOC_TYPEBITS)-1) +#define _VKI_IOC_SIZEMASK ((1ul << _VKI_IOC_SIZEBITS)-1) +#define _VKI_IOC_DIRMASK ((1ul << _VKI_IOC_DIRBITS)-1) + +#define _VKI_IOC_BASESHIFT 0 +#define _VKI_IOC_NRSHIFT 0 +#define _VKI_IOC_TYPESHIFT (_VKI_IOC_NRSHIFT+_VKI_IOC_NRBITS) +#define _VKI_IOC_SIZESHIFT (_VKI_IOC_TYPESHIFT+_VKI_IOC_TYPEBITS) +#define _VKI_IOC_DIRSHIFT (_VKI_IOC_SIZESHIFT+_VKI_IOC_SIZEBITS) + +#define _VKI_IOC_NONE 1U /* "void" on freebsd, as a specific mode */ +#define _VKI_IOC_READ 2U /* "out", copyout in reversed linux terminology */ +#define _VKI_IOC_WRITE 4U /* "in", copyin in reversed linux terminology */ +#define _VKI_IOC_RDWR 6U /* "inout", copyin and copyout */ + +#define _VKI_IOC(dir,type,nr,size) \ + (((dir) << _VKI_IOC_DIRSHIFT) | \ + ((type) << _VKI_IOC_TYPESHIFT) | \ + ((nr) << _VKI_IOC_NRSHIFT) | \ + ((size) << _VKI_IOC_SIZESHIFT)) + +/* provoke compile error for invalid uses of size argument */ +extern unsigned int __vki_invalid_size_argument_for_IOC; +#define _VKI_IOC_TYPECHECK(t) \ + ((sizeof(t) == sizeof(t[1]) && \ + sizeof(t) < (1 << _VKI_IOC_SIZEBITS)) ? \ + sizeof(t) : __vki_invalid_size_argument_for_IOC) + +/* used to create numbers */ +#define _VKI_IO(type,nr) _VKI_IOC(_VKI_IOC_NONE,(type),(nr),0) +#define _VKI_IOR(type,nr,size) _VKI_IOC(_VKI_IOC_READ,(type),(nr),(_VKI_IOC_TYPECHECK(size))) +#define _VKI_IOW(type,nr,size) _VKI_IOC(_VKI_IOC_WRITE,(type),(nr),(_VKI_IOC_TYPECHECK(size))) +#define _VKI_IOWR(type,nr,size) _VKI_IOC(_VKI_IOC_READ|_VKI_IOC_WRITE,(type),(nr),(_VKI_IOC_TYPECHECK(size))) + +/* used to decode ioctl numbers.. */ +#define _VKI_IOC_DIR(nr) (((nr) >> _VKI_IOC_DIRSHIFT) & _VKI_IOC_DIRMASK) +#define _VKI_IOC_TYPE(nr) (((nr) >> _VKI_IOC_TYPESHIFT) & _VKI_IOC_TYPEMASK) +#define _VKI_IOC_NR(nr) (((nr) >> _VKI_IOC_NRSHIFT) & _VKI_IOC_NRMASK) +#define _VKI_IOC_SIZE(nr) (((nr) >> _VKI_IOC_SIZESHIFT) & _VKI_IOC_SIZEMASK) +#define _VKI_IOC_BASE(nr) (((nr) >> _VKI_IOC_BASESHIFT) & _VKI_IOC_BASEMASK) + + +//---------------------------------------------------------------------- +// From sys/termios.h +//---------------------------------------------------------------------- + +#if 0 +#define VKI_TCGETS 0x5401 +#define VKI_TCSETS 0x5402 /* Clashes with SNDCTL_TMR_START sound ioctl */ +#define VKI_TCSETSW 0x5403 +#define VKI_TCSETSF 0x5404 +#define VKI_TCGETA 0x5405 y +#define VKI_TCSETA 0x5406 y +#define VKI_TCSETAW 0x5407 y +#define VKI_TCSETAF 0x5408 y +#define VKI_TCSBRK 0x5409 +#define VKI_TCXONC 0x540A +#define VKI_TCFLSH 0x540B y +#define VKI_TIOCSCTTY 0x540E +#define VKI_TIOCGPGRP 0x540F y +#define VKI_TIOCSPGRP 0x5410 y +#define VKI_TIOCOUTQ 0x5411 +#define VKI_TIOCGWINSZ 0x5413 y +#define VKI_TIOCSWINSZ 0x5414 y +#define VKI_TIOCMGET 0x5415 y +#define VKI_TIOCMBIS 0x5416 y +#define VKI_TIOCMBIC 0x5417 y +#define VKI_TIOCMSET 0x5418 y +#define VKI_FIONREAD 0x541B +#define VKI_TIOCLINUX 0x541C +#define VKI_FIONBIO 0x5421 +#define VKI_TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ +#define VKI_TIOCGPTN _VKI_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ +#define VKI_TIOCSPTLCK _VKI_IOW('T',0x31, int) /* Lock/unlock Pty */ + +#define VKI_FIOASYNC 0x5452 +#define VKI_TIOCSERGETLSR 0x5459 /* Get line status register */ + +#define VKI_TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ +#endif + +#define VKI_TIOCFLUSH _VKI_IOW('t', 16, int); +#define VKI_TIOCGETA _VKI_IOR('t', 19, struct vki_termios) /* get termios */ +#define VKI_TIOCSETA _VKI_IOR('t', 20, struct vki_termios) /* set termios */ +#define VKI_TIOCSETAW _VKI_IOR('t', 21, struct vki_termios) /* drain,set */ +#define VKI_TIOCSETAF _VKI_IOR('t', 22, struct vki_termios) /* flush,set */ + +#define VKI_TIOCSBRK _VKI_IO('t', 123) +#define VKI_TIOCCBRK _VKI_IO('t', 122) +#define VKI_TIOCGPGRP _VKI_IOR('t', 119, int) /* get pgrp */ +#define VKI_TIOCSPGRP _VKI_IOW('t', 118, int) /* set pgrp */ + +#define VKI_TIOCGWINSZ _VKI_IOR('t', 104, struct vki_winsize) /* get window size */ +#define VKI_TIOCSWINSZ _VKI_IOW('t', 103, struct vki_winsize) /* set window size */ + +#define VKI_TIOCMGET _VKI_IOR('t', 106, int) /* get all modem bits */ +#define VKI_TIOCMBIS _VKI_IOW('t', 108, int) /* bis modem bits */ +#define VKI_TIOCMBIC _VKI_IOW('t', 107, int) /* bic modem bits */ +#define VKI_TIOCMSET _VKI_IOW('t', 109, int) /* set all modem bits */ + + +//---------------------------------------------------------------------- +// From sys/filio.h +//---------------------------------------------------------------------- + +#define VKI_FIOCLEX _VKI_IO('f', 1) /* close on exec */ +#define VKI_FIONCLEX _VKI_IO('f', 2) /* no close on exec */ +#define VKI_FIONREAD _VKI_IOR('f', 127, int) +#define VKI_FIONBIO _VKI_IOW('f', 126, int) +#define VKI_FIOASYNC _VKI_IOW('f', 125, int) +#define VKI_FIOSETOWN _VKI_IOW('f', 124, int) +#define VKI_FIOGETOWN _VKI_IOW('f', 123, int) + +//---------------------------------------------------------------------- +// From sys/poll.h +//---------------------------------------------------------------------- + +#define VKI_POLLIN 0x0001 + +struct vki_pollfd { + int fd; + short events; + short revents; +}; + +//---------------------------------------------------------------------- +// From sys/kevent.h +//---------------------------------------------------------------------- +struct vki_kevent { + vki_uintptr_t ident; + vki_int16_t filter; + vki_uint16_t flags; + vki_uint32_t fflags; + vki_intptr_t data; + void *udata; +}; + + +// QQQ sort + +//---------------------------------------------------------------------- +// From sys/resource.h +//---------------------------------------------------------------------- + +struct vki_rusage { + struct vki_timeval ru_utime; /* user time used */ + struct vki_timeval ru_stime; /* system time used */ + long ru_maxrss; /* maximum resident set size */ + long ru_ixrss; /* integral shared memory size */ + long ru_idrss; /* integral unshared data size */ + long ru_isrss; /* integral unshared stack size */ + long ru_minflt; /* page reclaims */ + long ru_majflt; /* page faults */ + long ru_nswap; /* swaps */ + long ru_inblock; /* block input operations */ + long ru_oublock; /* block output operations */ + long ru_msgsnd; /* messages sent */ + long ru_msgrcv; /* messages received */ + long ru_nsignals; /* signals received */ + long ru_nvcsw; /* voluntary context switches */ + long ru_nivcsw; /* involuntary " */ +}; + +struct vki_rlimit { + vki_rlim_t rlim_cur; + vki_rlim_t rlim_max; +}; + +#define VKI_RLIMIT_DATA 2 /* max data size */ +#define VKI_RLIMIT_STACK 3 /* max stack size */ +#define VKI_RLIMIT_CORE 4 /* max core file size */ +#define VKI_RLIMIT_NOFILE 8 /* max number of open files */ + +//---------------------------------------------------------------------- +// From sys/procfs.h +//---------------------------------------------------------------------- + +#define VKI_PRSTATUS_VERSION 1 +struct vki_elf_prstatus +{ + int pr_version; /* version of struct - PRSTATUS_VERSION */ + vki_size_t pr_statussz; + vki_size_t pr_gregsetsz; + vki_size_t pr_fpregsetsz; + int pr_osreldate; + short pr_cursig; /* Current signal */ + vki_pid_t pr_pid; + vki_elf_gregset_t pr_reg; /* GP registers */ +}; + +#define VKI_ELF_PRARGSZ (80) /* Number of chars for args */ +#define VKI_MAXCOMLEN (16) + +#define VKI_PRPSINFO_VERSION 1 +struct vki_elf_prpsinfo +{ + int pr_version; /* version of struct - PRPSINFO_VERSION */ + vki_size_t pr_psinfosz; + char pr_fname[VKI_MAXCOMLEN+1]; /* filename of executable */ + char pr_psargs[VKI_ELF_PRARGSZ]; /* initial part of arg list */ +}; + +//---------------------------------------------------------------------- +// From posix4/mqueue.h +//---------------------------------------------------------------------- + +struct vki_mq_attr { + long mq_flags; /* message queue flags */ + long mq_maxmsg; /* maximum number of messages */ + long mq_msgsize; /* maximum message size */ + long mq_curmsgs; /* number of messages currently queued */ +}; + +//---------------------------------------------------------------------- +// From sys/ucontext.h +//---------------------------------------------------------------------- + +#define VKI_UCF_SWAPPED 1 + +struct vki_ucontext { + vki_sigset_t uc_sigmask; + struct vki_mcontext uc_mcontext; + struct vki_ucontext *uc_link; + vki_stack_t uc_stack; + int uc_flags; + unsigned int __spare__[4]; +}; + +//---------------------------------------------------------------------- +// From sys/utsname.h +//---------------------------------------------------------------------- + +#define VKI_SYS_NMLN 32 + +struct vki_utsname { + char sysname[VKI_SYS_NMLN]; /* Name of this OS. */ + char nodename[VKI_SYS_NMLN]; /* Name of this network node. */ + char release[VKI_SYS_NMLN]; /* Release level. */ + char version[VKI_SYS_NMLN]; /* Version level. */ + char machine[VKI_SYS_NMLN]; /* Hardware type. */ +}; + +#define VKI_IPC_CREAT 00001000 /* create if key is nonexistent */ +#define VKI_IPC_EXCL 00002000 /* fail if key exists */ +#define VKI_IPC_NOWAIT 00004000 /* return error on wait */ + +#define VKI_IPC_RMID 0 /* remove resource */ +#define VKI_IPC_SET 1 /* set ipc_perm options */ +#define VKI_IPC_STAT 2 /* get ipc_perm options */ +#define VKI_IPC_INFO 3 /* see ipcs */ + +struct vki_ipc_perm +{ + vki_uid_t cuid; + vki_gid_t cgid; + vki_uid_t uid; + vki_gid_t gid; + vki_mode_t mode; + unsigned short seq; + vki_key_t key; +}; + +struct vki_ipc_perm7 +{ + unsigned short cuid; + unsigned short cgid; + unsigned short uid; + unsigned short gid; + unsigned short mode; + unsigned short seq; + vki_key_t key; +}; + +//---------------------------------------------------------------------- +// From sys/sem.h +//---------------------------------------------------------------------- + +#if 0 +#define VKI_SEMOP 1 +#define VKI_SEMGET 2 +#define VKI_SEMCTL 3 +#define VKI_SEMTIMEDOP 4 +#endif + +#define VKI_GETALL 6 /* get all semval's */ +#define VKI_SETVAL 8 /* set semval */ +#define VKI_SETALL 9 /* set all semval's */ +#define VKI_SEM_STAT 10 +#define VKI_SEM_INFO 11 + +/* Obsolete, used only for backwards compatibility and libc5 compiles */ +struct vki_semid_ds { + struct vki_ipc_perm sem_perm; /* permissions .. see ipc.h */ + // [[Use void* to avoid excess header copying]] + void/*struct sem */*sem_base; /* ptr to first semaphore in array */ + unsigned short sem_nsems; /* no. of semaphores in array */ + vki_time_t sem_otime; /* last semop time */ + vki_time_t sem_ctime; /* last change time */ + long sem_pad2; + long sem_pad3[4]; +}; + +struct vki_sembuf { + vki_uint16_t sem_num; /* semaphore index in array */ + vki_int16_t sem_op; /* semaphore operation */ + vki_int16_t sem_flg; /* operation flags */ +}; + +union vki_semun { + int val; /* value for SETVAL */ + struct vki_semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */ + vki_uint16_t *array; /* array for GETALL & SETALL */ +}; + + +//---------------------------------------------------------------------- +// From sys/errno.h +//---------------------------------------------------------------------- + +#define VKI_ERESTART -1 +#define VKI_EPERM 1 /* Operation not permitted */ +#define VKI_ENOENT 2 /* No such file or directory */ +#define VKI_ESRCH 3 /* No such process */ +#define VKI_EINTR 4 /* Interrupted system call */ +#define VKI_EIO 5 /* Input/output error */ +#define VKI_ENXIO 6 /* Device not configured */ +#define VKI_E2BIG 7 /* Argument list too long */ +#define VKI_ENOEXEC 8 /* Exec format error */ +#define VKI_EBADF 9 /* Bad file descriptor */ +#define VKI_ECHILD 10 /* No child processes */ +#define VKI_EDEADLK 11 /* Resource deadlock avoided */ +#define VKI_ENOMEM 12 /* Cannot allocate memory */ +#define VKI_EACCES 13 /* Permission denied */ +#define VKI_EFAULT 14 /* Bad address */ +#define VKI_ENOTBLK 15 /* Block device required */ +#define VKI_EBUSY 16 /* Device busy */ +#define VKI_EEXIST 17 /* File exists */ +#define VKI_EXDEV 18 /* Cross-device link */ +#define VKI_ENODEV 19 /* Operation not supported by device */ +#define VKI_ENOTDIR 20 /* Not a directory */ +#define VKI_EISDIR 21 /* Is a directory */ +#define VKI_EINVAL 22 /* Invalid argument */ +#define VKI_ENFILE 23 /* Too many open files in system */ +#define VKI_EMFILE 24 /* Too many open files */ +#define VKI_ENOTTY 25 /* Inappropriate ioctl for device */ +#define VKI_ETXTBSY 26 /* Text file busy */ +#define VKI_EFBIG 27 /* File too large */ +#define VKI_ENOSPC 28 /* No space left on device */ +#define VKI_ESPIPE 29 /* Illegal seek */ +#define VKI_EROFS 30 /* Read-only filesystem */ +#define VKI_EMLINK 31 /* Too many links */ +#define VKI_EPIPE 32 /* Broken pipe */ +#define VKI_EDOM 33 /* Numerical argument out of domain */ +#define VKI_ERANGE 34 /* Result too large */ +#define VKI_EAGAIN 35 /* Resource temporarily unavailable */ +#define VKI_EWOULDBLOCK VKI_EAGAIN /* Operation would block */ +#define VKI_EINPROGRESS 36 /* Operation now in progress */ +#define VKI_EALREADY 37 /* Operation already in progress */ +#define VKI_ENOTSOCK 38 /* Socket operation on non-socket */ +#define VKI_EDESTADDRREQ 39 /* Destination address required */ +#define VKI_EMSGSIZE 40 /* Message too long */ +#define VKI_EPROTOTYPE 41 /* Protocol wrong type for socket */ +#define VKI_ENOPROTOOPT 42 /* Protocol not available */ +#define VKI_EPROTONOSUPPORT 43 /* Protocol not supported */ +#define VKI_ESOCKTNOSUPPORT 44 /* Socket type not supported */ +#define VKI_EOPNOTSUPP 45 /* Operation not supported */ +#define VKI_ENOTSUP VKI_EOPNOTSUPP /* Operation not supported */ +#define VKI_EPFNOSUPPORT 46 /* Protocol family not supported */ +#define VKI_EAFNOSUPPORT 47 /* Address family not supported by protocol family */ +#define VKI_EADDRINUSE 48 /* Address already in use */ +#define VKI_EADDRNOTAVAIL 49 +#define VKI_ENETDOWN 50 /* Network is down */ +#define VKI_ENETUNREACH 51 /* Network is unreachable */ +#define VKI_ENETRESET 52 /* Network dropped connection on reset */ +#define VKI_ECONNABORTED 53 /* Software caused connection abort */ +#define VKI_ECONNRESET 54 /* Connection reset by peer */ +#define VKI_ENOBUFS 55 /* No buffer space available */ +#define VKI_EISCONN 56 /* Socket is already connected */ +#define VKI_ENOTCONN 57 /* Socket is not connected */ +#define VKI_ESHUTDOWN 58 /* Can't send after socket shutdown */ +#define VKI_ETOOMANYREFS 59 /* Too many references: can't splice */ +#define VKI_ETIMEDOUT 60 /* Operation timed out */ +#define VKI_ECONNREFUSED 61 /* Connection refused */ +#define VKI_ELOOP 62 /* Too many levels of symbolic links */ +#define VKI_ENAMETOOLONG 63 /* File name too long */ +#define VKI_EHOSTDOWN 64 /* Host is down */ +#define VKI_EHOSTUNREACH 65 /* No route to host */ +#define VKI_ENOTEMPTY 66 /* Directory not empty */ +#define VKI_EPROCLIM 67 /* Too many processes */ +#define VKI_EUSERS 68 /* Too many users */ +#define VKI_EDQUOT 69 /* Disc quota exceeded */ +#define VKI_ESTALE 70 /* Stale NFS file handle */ +#define VKI_EREMOTE 71 /* Too many levels of remote in path */ +#define VKI_EBADRPC 72 /* RPC struct is bad */ +#define VKI_ERPCMISMATCH 73 /* RPC version wrong */ +#define VKI_EPROGUNAVAIL 74 /* RPC prog. not avail */ +#define VKI_EPROGMISMATCH 75 /* Program version wrong */ +#define VKI_EPROCUNAVAIL 76 /* Bad procedure for program */ +#define VKI_ENOLCK 77 /* No locks available */ +#define VKI_ENOSYS 78 /* Function not implemented */ +#define VKI_EFTYPE 79 /* Inappropriate file type or format */ +#define VKI_EAUTH 80 /* Authentication error */ +#define VKI_ENEEDAUTH 81 /* Need authenticator */ +#define VKI_EIDRM 82 /* Identifier removed */ +#define VKI_ENOMSG 83 /* No message of desired type */ +#define VKI_EOVERFLOW 84 /* Value too large to be stored in data type */ +#define VKI_ECANCELED 85 /* Operation canceled */ +#define VKI_EILSEQ 86 /* Illegal byte sequence */ +#define VKI_ENOATTR 87 /* Attribute not found */ +#define VKI_EDOOFUS 88 /* Programming error */ +#define VKI_EBADMSG 89 /* Bad message */ +#define VKI_EMULTIHOP 90 /* Multihop attempted */ +#define VKI_ENOLINK 91 /* Link has been severed */ +#define VKI_EPROTO 92 /* Protocol error */ +#define VKI_ENOTCAPABLE 93 /* Capabilities insufficient */ +#define VKI_ECAPMODE 94 /* Not permitted in capability mode */ + +//---------------------------------------------------------------------- +// From sys/wait.h +//---------------------------------------------------------------------- + +#define VKI_WNOHANG 0x00000001 + +//---------------------------------------------------------------------- +// From sys/mman.h +//---------------------------------------------------------------------- + +#define VKI_PROT_NONE 0x00 /* No page permissions */ +#define VKI_PROT_READ 0x01 /* page can be read */ +#define VKI_PROT_WRITE 0x02 /* page can be written */ +#define VKI_PROT_EXEC 0x04 /* page can be executed */ + +#define VKI_MAP_SHARED 0x01 /* Share changes */ +#define VKI_MAP_PRIVATE 0x02 /* Changes are private */ +#define VKI_MAP_FIXED 0x10 /* Interpret addr exactly */ +#define VKI_MAP_NORESERVE 0x0040 /* don't check for reservations */ +#define VKI_MAP_STACK 0x400 +#define VKI_MAP_ANON 0x1000 /* don't use a file */ +#define VKI_MAP_ANONYMOUS VKI_MAP_ANON + +//---------------------------------------------------------------------- +// From sys/stat.h +//---------------------------------------------------------------------- + +#define VKI_S_IFMT 00170000 + +#define VKI_S_IFWHT 0160000 +#define VKI_S_IFSOCK 0140000 +#define VKI_S_IFLNK 0120000 +#define VKI_S_IFREG 0100000 +#define VKI_S_IFBLK 0060000 +#define VKI_S_IFDIR 0040000 +#define VKI_S_IFCHR 0020000 +#define VKI_S_IFIFO 0010000 +#define VKI_S_ISUID 0004000 +#define VKI_S_ISGID 0002000 +#define VKI_S_ISTXT 0001000 + +#define VKI_S_ISLNK(m) (((m) & VKI_S_IFMT) == VKI_S_IFLNK) +#define VKI_S_ISREG(m) (((m) & VKI_S_IFMT) == VKI_S_IFREG) +#define VKI_S_ISDIR(m) (((m) & VKI_S_IFMT) == VKI_S_IFDIR) +#define VKI_S_ISCHR(m) (((m) & VKI_S_IFMT) == VKI_S_IFCHR) +#define VKI_S_ISBLK(m) (((m) & VKI_S_IFMT) == VKI_S_IFBLK) +#define VKI_S_ISFIFO(m) (((m) & VKI_S_IFMT) == VKI_S_IFIFO) +#define VKI_S_ISSOCK(m) (((m) & VKI_S_IFMT) == VKI_S_IFSOCK) +#define VKI_S_ISWHT(m) (((m) & VKI_S_IFMT) == VKI_S_IFWHT) + +#define VKI_S_IRWXU 00700 +#define VKI_S_IRUSR 00400 +#define VKI_S_IWUSR 00200 +#define VKI_S_IXUSR 00100 + +#define VKI_S_IRWXG 00070 +#define VKI_S_IRGRP 00040 +#define VKI_S_IWGRP 00020 +#define VKI_S_IXGRP 00010 + +#define VKI_S_IRWXO 00007 +#define VKI_S_IROTH 00004 +#define VKI_S_IWOTH 00002 +#define VKI_S_IXOTH 00001 + + +//---------------------------------------------------------------------- +// From sys/dirent.h +//---------------------------------------------------------------------- + +struct vki_dirent { + vki_uint32_t d_fileno; + vki_uint16_t d_reclen; + vki_uint8_t d_type; + vki_uint8_t d_namelen; + char d_name[256]; /* We must not include limits.h! */ +}; + +//---------------------------------------------------------------------- +// From sys/fcntl.h +//---------------------------------------------------------------------- + +#define VKI_O_RDONLY 0x0000 +#define VKI_O_WRONLY 0x0001 +#define VKI_O_RDWR 0x0002 + +#define VKI_O_NONBLOCK 0x0004 +#define VKI_O_APPEND 0x0008 +#define VKI_O_CREAT 0x0200 /* not fcntl */ +#define VKI_O_TRUNC 0x0400 /* not fcntl */ +#define VKI_O_EXCL 0x0800 /* not fcntl */ + +#define VKI_AT_FDCWD -100 + +#define VKI_F_DUPFD 0 /* dup */ +#define VKI_F_GETFD 1 /* get close_on_exec */ +#define VKI_F_SETFD 2 /* set/clear close_on_exec */ +#define VKI_F_GETFL 3 /* get file->f_flags */ +#define VKI_F_SETFL 4 /* set file->f_flags */ +#define VKI_F_SETOWN 5 /* for sockets. */ +#define VKI_F_GETOWN 6 /* for sockets. */ +#define VKI_F_OGETLK 7 /* get record locking information */ +#define VKI_F_OSETLK 8 /* set record locking information */ +#define VKI_F_OSETLKW 9 /* F_SETLK; wait if blocked */ +#define VKI_F_DUP2FD 10 /* duplicate file descriptor to arg */ +#define VKI_F_GETLK 11 /* get record locking information */ +#define VKI_F_SETLK 12 /* set record locking information */ +#define VKI_F_SETLKW 13 /* F_SETLK; wait if blocked */ +#define VKI_F_SETLK_REMOTE 14 /* debugging support for remote locks */ + +/* for F_[GET|SET]FL */ +#define VKI_FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +//---------------------------------------------------------------------- +// From sys/unistd.h +//---------------------------------------------------------------------- + +#define VKI_SEEK_SET 0 +#define VKI_SEEK_CUR 1 +#define VKI_SEEK_END 2 + +#define VKI_F_OK 0 /* test for existence of file */ +#define VKI_X_OK 0x01 /* test for execute or search permission */ +#define VKI_W_OK 0x02 /* test for write permission */ +#define VKI_R_OK 0x04 /* test for read permission */ + +//---------------------------------------------------------------------- +// From sys/msg.h +//---------------------------------------------------------------------- + +#if 0 /* not in freebsd */ +#define VKI_MSGSND 11 +#define VKI_MSGRCV 12 +#define VKI_MSGGET 13 +#define VKI_MSGCTL 14 +#endif + +struct vki_msqid_ds { + struct vki_ipc_perm msg_perm; + struct vki_msg *msg_first; /* first message on queue,unused */ + struct vki_msg *msg_last; /* last message in queue,unused */ + vki_uint32_t msg_cbytes; /* current number of bytes on queue */ + vki_uint32_t msg_qnum; /* number of messages in queue */ + vki_uint32_t msg_qbytes; /* max number of bytes on queue */ + vki_pid_t msg_lspid; /* pid of last msgsnd */ + vki_pid_t msg_lrpid; /* last receive pid */ + vki_time_t msg_stime; /* last msgsnd time */ + vki_uint32_t msg_pad1; + vki_time_t msg_rtime; /* last msgrcv time */ + vki_uint32_t msg_pad2; + vki_time_t msg_ctime; /* last change time */ + vki_uint32_t msg_pad3; + vki_uint32_t msg_pad4[4]; +}; + +struct vki_msgbuf { + long mtype; /* type of message */ + char mtext[1]; /* message text */ +}; + + +//---------------------------------------------------------------------- +// From sys/shm.h +//---------------------------------------------------------------------- + +struct vki_shmid_ds { + struct vki_ipc_perm shm_perm; /* operation perms */ + vki_size_t shm_segsz; /* size of segment (bytes) */ + vki_pid_t shm_lpid; /* pid of last operator */ + vki_pid_t shm_cpid; /* pid of creator */ + int shm_nattch; /* no. of current attaches */ + vki_time_t shm_atime; /* last attach time */ + vki_time_t shm_dtime; /* last detach time */ + vki_time_t shm_ctime; /* last change time */ +}; + +struct vki_shmid_ds7 { + struct vki_ipc_perm7 shm_perm; /* operation perms */ + int shm_segsz; /* size of segment (bytes) */ + vki_pid_t shm_lpid; /* pid of last operator */ + vki_pid_t shm_cpid; /* pid of creator */ + short shm_nattch; /* no. of current attaches */ + vki_time_t shm_atime; /* last attach time */ + vki_time_t shm_dtime; /* last detach time */ + vki_time_t shm_ctime; /* last change time */ + void *shm_internal; /* sysv stupidity */ +}; + +#define VKI_SHMLBA VKI_PAGE_SIZE +#define VKI_SHM_RDONLY 010000 /* read-only access */ +#define VKI_SHM_ANON (1UL) + +#if 0 /* not in freebsd abi */ +#define VKI_SHMAT 21 +#define VKI_SHMDT 22 +#define VKI_SHMGET 23 +#define VKI_SHMCTL 24 +#endif + +#if 0 +//---------------------------------------------------------------------- +// From linux-2.6.8.1/include/linux/sockios.h +//---------------------------------------------------------------------- + +#define VKI_SIOCOUTQ VKI_TIOCOUTQ + +#define VKI_SIOCADDRT 0x890B /* add routing table entry */ +#define VKI_SIOCDELRT 0x890C /* delete routing table entry */ + +#define VKI_SIOCGIFNAME 0x8910 /* get iface name */ +#define VKI_SIOCGIFCONF 0x8912 /* get iface list */ +#define VKI_SIOCGIFFLAGS 0x8913 /* get flags */ +#define VKI_SIOCSIFFLAGS 0x8914 /* set flags */ +#define VKI_SIOCGIFADDR 0x8915 /* get PA address */ +#define VKI_SIOCSIFADDR 0x8916 /* set PA address */ +#define VKI_SIOCGIFDSTADDR 0x8917 /* get remote PA address */ +#define VKI_SIOCSIFDSTADDR 0x8918 /* set remote PA address */ +#define VKI_SIOCGIFBRDADDR 0x8919 /* get broadcast PA address */ +#define VKI_SIOCSIFBRDADDR 0x891a /* set broadcast PA address */ +#define VKI_SIOCGIFNETMASK 0x891b /* get network PA mask */ +#define VKI_SIOCSIFNETMASK 0x891c /* set network PA mask */ +#define VKI_SIOCGIFMETRIC 0x891d /* get metric */ +#define VKI_SIOCSIFMETRIC 0x891e /* set metric */ +#define VKI_SIOCGIFMTU 0x8921 /* get MTU size */ +#define VKI_SIOCSIFMTU 0x8922 /* set MTU size */ +#define VKI_SIOCSIFHWADDR 0x8924 /* set hardware address */ +#define VKI_SIOCGIFHWADDR 0x8927 /* Get hardware address */ +#define VKI_SIOCGIFINDEX 0x8933 /* name -> if_index mapping */ + +#define VKI_SIOCGIFTXQLEN 0x8942 /* Get the tx queue length */ +#define VKI_SIOCSIFTXQLEN 0x8943 /* Set the tx queue length */ + +#define VKI_SIOCGMIIPHY 0x8947 /* Get address of MII PHY in use. */ +#define VKI_SIOCGMIIREG 0x8948 /* Read MII PHY register. */ +#define VKI_SIOCSMIIREG 0x8949 /* Write MII PHY register. */ + +#define VKI_SIOCDARP 0x8953 /* delete ARP table entry */ +#define VKI_SIOCGARP 0x8954 /* get ARP table entry */ +#define VKI_SIOCSARP 0x8955 /* set ARP table entry */ + +#define VKI_SIOCDRARP 0x8960 /* delete RARP table entry */ +#define VKI_SIOCGRARP 0x8961 /* get RARP table entry */ +#define VKI_SIOCSRARP 0x8962 /* set RARP table entry */ + +#define VKI_SIOCGIFMAP 0x8970 /* Get device parameters */ +#define VKI_SIOCSIFMAP 0x8971 /* Set device parameters */ + +//---------------------------------------------------------------------- +// From linux-2.6.9/include/linux/kb.h +//---------------------------------------------------------------------- + +#define VKI_GIO_FONT 0x4B60 /* gets font in expanded form */ +#define VKI_PIO_FONT 0x4B61 /* use font in expanded form */ + +#define VKI_GIO_FONTX 0x4B6B /* get font using struct consolefontdesc */ +#define VKI_PIO_FONTX 0x4B6C /* set font using struct consolefontdesc */ +struct vki_consolefontdesc { + unsigned short charcount; /* characters in font (256 or 512) */ + unsigned short charheight; /* scan lines per character (1-32) */ + char __user *chardata; /* font data in expanded form */ +}; + +#define VKI_PIO_FONTRESET 0x4B6D /* reset to default font */ + +#define VKI_GIO_CMAP 0x4B70 /* gets colour palette on VGA+ */ +#define VKI_PIO_CMAP 0x4B71 /* sets colour palette on VGA+ */ + +#define VKI_KIOCSOUND 0x4B2F /* start sound generation (0 for off) */ +#define VKI_KDMKTONE 0x4B30 /* generate tone */ + +#define VKI_KDGETLED 0x4B31 /* return current led state */ +#define VKI_KDSETLED 0x4B32 /* set led state [lights, not flags] */ + +#define VKI_KDGKBTYPE 0x4B33 /* get keyboard type */ + +#define VKI_KDADDIO 0x4B34 /* add i/o port as valid */ +#define VKI_KDDELIO 0x4B35 /* del i/o port as valid */ +#define VKI_KDENABIO 0x4B36 /* enable i/o to video board */ +#define VKI_KDDISABIO 0x4B37 /* disable i/o to video board */ + +#define VKI_KDSETMODE 0x4B3A /* set text/graphics mode */ +#define VKI_KDGETMODE 0x4B3B /* get current mode */ + +#define VKI_KDMAPDISP 0x4B3C /* map display into address space */ +#define VKI_KDUNMAPDISP 0x4B3D /* unmap display from address space */ + +#define VKI_E_TABSZ 256 +#define VKI_GIO_SCRNMAP 0x4B40 /* get screen mapping from kernel */ +#define VKI_PIO_SCRNMAP 0x4B41 /* put screen mapping table in kernel */ +#define VKI_GIO_UNISCRNMAP 0x4B69 /* get full Unicode screen mapping */ +#define VKI_PIO_UNISCRNMAP 0x4B6A /* set full Unicode screen mapping */ + +#define VKI_GIO_UNIMAP 0x4B66 /* get unicode-to-font mapping from kernel */ +#define VKI_PIO_UNIMAP 0x4B67 /* put unicode-to-font mapping in kernel */ +#define VKI_PIO_UNIMAPCLR 0x4B68 /* clear table, possibly advise hash algorithm */ + +#define VKI_KDGKBMODE 0x4B44 /* gets current keyboard mode */ +#define VKI_KDSKBMODE 0x4B45 /* sets current keyboard mode */ + +#define VKI_KDGKBMETA 0x4B62 /* gets meta key handling mode */ +#define VKI_KDSKBMETA 0x4B63 /* sets meta key handling mode */ + +#define VKI_KDGKBLED 0x4B64 /* get led flags (not lights) */ +#define VKI_KDSKBLED 0x4B65 /* set led flags (not lights) */ + +struct vki_kbentry { + unsigned char kb_table; + unsigned char kb_index; + unsigned short kb_value; +}; +#define VKI_KDGKBENT 0x4B46 /* gets one entry in translation table */ +#define VKI_KDSKBENT 0x4B47 /* sets one entry in translation table */ + +struct vki_kbsentry { + unsigned char kb_func; + unsigned char kb_string[512]; +}; +#define VKI_KDGKBSENT 0x4B48 /* gets one function key string entry */ +#define VKI_KDSKBSENT 0x4B49 /* sets one function key string entry */ + +struct vki_kbdiacr { + unsigned char diacr, base, result; +}; +struct vki_kbdiacrs { + unsigned int kb_cnt; /* number of entries in following array */ + struct vki_kbdiacr kbdiacr[256]; /* MAX_DIACR from keyboard.h */ +}; +#define VKI_KDGKBDIACR 0x4B4A /* read kernel accent table */ +#define VKI_KDSKBDIACR 0x4B4B /* write kernel accent table */ + +struct vki_kbkeycode { + unsigned int scancode, keycode; +}; +#define VKI_KDGETKEYCODE 0x4B4C /* read kernel keycode table entry */ +#define VKI_KDSETKEYCODE 0x4B4D /* write kernel keycode table entry */ + +#define VKI_KDSIGACCEPT 0x4B4E /* accept kbd generated signals */ + +struct vki_kbd_repeat { + int delay; /* in msec; <= 0: don't change */ + int period; /* in msec; <= 0: don't change */ + /* earlier this field was misnamed "rate" */ +}; +#define VKI_KDKBDREP 0x4B52 /* set keyboard delay/repeat rate; + * actually used values are returned */ + +#define VKI_KDFONTOP 0x4B72 /* font operations */ + +//---------------------------------------------------------------------- +// From linux-2.6.9/include/linux/kb.h +//---------------------------------------------------------------------- + +typedef __vki_kernel_uid32_t vki_qid_t; /* Type in which we store ids in memory */ + +#endif + +//---------------------------------------------------------------------- +// From sys/ptrace.h +//---------------------------------------------------------------------- + +#define VKI_PTRACE_TRACEME 0 +#define VKI_PTRACE_READ_I 1 +#define VKI_PTRACE_READ_D 2 +/* 3 - read user struct */ +#define VKI_PTRACE_WRITE_I 4 +#define VKI_PTRACE_WRITE_D 5 +/* 6 - write user struct */ +#define VKI_PTRACE_CONTINUE 7 +#define VKI_PTRACE_KILL 8 +#define VKI_PTRACE_STEP 9 +#define VKI_PTRACE_ATTACH 10 +#define VKI_PTRACE_DETACH 11 +#define VKI_PTRACE_IO 12 +#define VKI_PTRACE_LWPINFO 13 +#define VKI_PTRACE_GETNUMLWPS 14 +#define VKI_PTRACE_GETLWPLIST 15 +#define VKI_PTRACE_CLEARSTEP 16 +#define VKI_PTRACE_SETSTEP 17 +#define VKI_PTRACE_SUSPEND 18 +#define VKI_PTRACE_RESUME 19 +#define VKI_PTRACE_TO_SCE 20 +#define VKI_PTRACE_TO_SCX 21 +#define VKI_PTRACE_SYSCALL 22 +/* md */ +#define VKI_PTRACE_GETREGS 33 +#define VKI_PTRACE_SETREGS 34 +#define VKI_PTRACE_GETFPREGS 35 +#define VKI_PTRACE_SETFPREGS 36 +#define VKI_PTRACE_GETDBREGS 37 +#define VKI_PTRACE_SETDBREGS 38 + +#define VKI_PTRACE_VM_TIMESTAMP 40 +#define VKI_PTRACE_VM_ENTRY 41 + +#define VKI_PTRACE_FIRSTMACH 64 + +struct vki_ptrace_io_desc { + int piod_op; + void * piod_offs; + void * piod_addr; + vki_size_t piod_len; +}; +#define VKI_PIOD_READ_D 1 +#define VKI_PIOD_WRITE_D 2 +#define VKI_PIOD_READ_I 3 +#define VKI_PIOD_WRITE_I 4 + +struct vki_ptrace_lwpinfo { + vki_lwpid_t pl_lwpid; + int pl_event; +#define VKI_PL_EVENT_NONE 0 +#define VKI_PL_EVENT_SIGNAL 1 + int pl_flags; +#define VKI_FLAG_SA 0x01 +#define VKI_FLAG_BOUND 0x02 + vki_sigset_t pl_sigmask; + vki_sigset_t pl_siglist; +}; + +struct vki_ptrace_vm_entry { + int pve_entry; /* Entry number used for iteration. */ + int pve_timestamp; /* Generation number of VM map. */ + unsigned long pve_start; /* Start VA of range. */ + unsigned long pve_end; /* End VA of range (incl). */ + unsigned long pve_offset; /* Offset in backing object. */ + unsigned int pve_prot; /* Protection of memory range. */ + unsigned int pve_pathlen; /* Size of path. */ + long pve_fileid; /* File ID. */ + vki_uint32_t pve_fsid; /* File system ID. */ + char *pve_path; /* Path name of object. */ +}; + +#endif // __VKI_FREEBSD_H + +//---------------------------------------------------------------------- +// From i386/include/sysarch.h and amd64/include/sysarch.h (interchangeable) +//---------------------------------------------------------------------- + +#define VKI_I386_GET_FSBASE 7 +#define VKI_I386_SET_FSBASE 8 +#define VKI_I386_GET_GSBASE 9 +#define VKI_I386_SET_GSBASE 10 + +#define VKI_AMD64_GET_FSBASE 128 +#define VKI_AMD64_SET_FSBASE 129 +#define VKI_AMD64_GET_GSBASE 130 +#define VKI_AMD64_SET_GSBASE 131 + +//---------------------------------------------------------------------- +// From sys/module.h +//---------------------------------------------------------------------- + +#define VKI_MAXMODNAME 32 + +typedef union vki_modspecific { + vki_int32_t intval; + vki_uint32_t u_intval; +#if defined(VGP_x86_freebsd) + vki_int32_t longval; + vki_uint32_t u_longval; +#elif defined(VGP_amd64_freebsd) + vki_int64_t longval; + vki_uint64_t u_longval; +#else +#error Unknown platform +#endif +} vki_modspecific_t; + +struct vki_module_stat { + int version; + char name[VKI_MAXMODNAME]; + int refs; + int id; + vki_modspecific_t data; +}; + +//---------------------------------------------------------------------- +// From sys/rtprio.h +//---------------------------------------------------------------------- + +struct vki_rtprio { + vki_uint16_t type; + vki_uint16_t prio; +}; + +#define VKI_RTP_LOOKUP 0 +#define VKI_RTP_SET 1 + +//---------------------------------------------------------------------- +// From sys/umtx.h +//---------------------------------------------------------------------- + +struct vki_umtx { + unsigned long u_owner; +}; + +struct vki_umutex { + vki_lwpid_t m_owner; + vki_uint32_t m_flags; + vki_uint32_t m_ceilings[2]; + vki_uint32_t m_spare[4]; +}; + +struct vki_ucond { + vki_uint32_t c_has_waiters; + vki_uint32_t c_flags; + vki_uint32_t c_spare[2]; +}; + +struct vki_urwlock { + vki_uint32_t rw_state; + vki_uint32_t rw_flags; + vki_uint32_t rw_blocked_readers; + vki_uint32_t rw_blocked_writers; + vki_uint32_t rw_spare[4]; +}; + +struct vki_usem { + vki_uint32_t has_waiters; + vki_uint32_t count; + vki_uint32_t flags; +}; + +struct vki_umtx_time { + struct vki_timespec timeout; + vki_uint32_t flags; + vki_uint32_t clockid; +}; + +#define VKI_UMTX_OP_LOCK 0 +#define VKI_UMTX_OP_UNLOCK 1 +#define VKI_UMTX_OP_WAIT 2 +#define VKI_UMTX_OP_WAKE 3 +#define VKI_UMTX_OP_MUTEX_TRYLOCK 4 +#define VKI_UMTX_OP_MUTEX_LOCK 5 +#define VKI_UMTX_OP_MUTEX_UNLOCK 6 +#define VKI_UMTX_OP_SET_CEILING 7 +#define VKI_UMTX_OP_CV_WAIT 8 +#define VKI_UMTX_OP_CV_SIGNAL 9 +#define VKI_UMTX_OP_CV_BROADCAST 10 +#define VKI_UMTX_OP_WAIT_UINT 11 +#define VKI_UMTX_OP_RW_RDLOCK 12 +#define VKI_UMTX_OP_RW_WRLOCK 13 +#define VKI_UMTX_OP_RW_UNLOCK 14 +#define VKI_UMTX_OP_WAIT_UINT_PRIVATE 15 +#define VKI_UMTX_OP_WAKE_PRIVATE 16 +#define VKI_UMTX_OP_MUTEX_WAIT 17 +#define VKI_UMTX_OP_MUTEX_WAKE 18 /* deprecated */ +#define VKI_UMTX_OP_SEM_WAIT 19 +#define VKI_UMTX_OP_SEM_WAKE 20 +#define VKI_UMTX_OP_NWAKE_PRIVATE 21 +#define VKI_UMTX_OP_MUTEX_WAKE2 22 +#define VKI_UMTX_OP_MAX 23 + + +//---------------------------------------------------------------------- +// From sys/acl.h +//---------------------------------------------------------------------- + +struct vki_acl_entry { + int ae_tag; + vki_uid_t ae_uid; + vki_mode_t ae_perm; +}; + +#define VKI_ACL_MAX_ENTRIES 32 +struct vki_acl { + int acl_cnt; + struct vki_acl_entry acl_entry[VKI_ACL_MAX_ENTRIES]; +}; + + +//---------------------------------------------------------------------- +// From sys/uuid.h +//---------------------------------------------------------------------- + +struct vki_uuid { + vki_uint32_t time_low; + vki_uint16_t time_mid; + vki_uint16_t time_hi_and_version; + vki_uint8_t clock_seq_hi_and_reserved; + vki_uint8_t clock_seq_low; + vki_uint8_t node[6]; +}; + +//---------------------------------------------------------------------- +// From sys/user.h +//---------------------------------------------------------------------- + +#define VKI_KVME_TYPE_NONE 0 +#define VKI_KVME_TYPE_DEFAULT 1 +#define VKI_KVME_TYPE_VNODE 2 +#define VKI_KVME_TYPE_SWAP 3 +#define VKI_KVME_TYPE_DEVICE 4 +#define VKI_KVME_TYPE_PHYS 5 +#define VKI_KVME_TYPE_DEAD 6 +#define VKI_KVME_TYPE_UNKNOWN 255 + +#define VKI_KVME_PROT_READ 0x00000001 +#define VKI_KVME_PROT_WRITE 0x00000002 +#define VKI_KVME_PROT_EXEC 0x00000004 + +#define VKI_KVME_FLAG_COW 0x00000001 +#define VKI_KVME_FLAG_NEEDS_COPY 0x00000002 + +struct vki_kinfo_vmentry { + int kve_structsize; + int kve_type; + ULong kve_start; + ULong kve_end; + Off64T kve_offset; + ULong kve_fileid; + UInt kve_fsid; + int kve_flags; + int kve_resident; + int kve_private_resident; + int kve_protection; + int kve_ref_count; + int kve_shadow_count; + int _kve_pad0; + int kve_ispare[16]; + char kve_path[VKI_PATH_MAX]; +}; + +struct vki_kinfo_file { + int kf_structsize; /* Variable size of record. */ + int kf_type; /* Descriptor type. */ + int kf_fd; /* Array index. */ + int kf_ref_count; /* Reference count. */ + int kf_flags; /* Flags. */ + int _kf_pad0; /* Round to 64 bit alignment */ + Off64T kf_offset; /* Seek location. */ + int kf_vnode_type; /* Vnode type. */ + int kf_sock_domain; /* Socket domain. */ + int kf_sock_type; /* Socket type. */ + int kf_sock_protocol; /* Socket protocol. */ + char kf_sa_local[128]; /* Socket address. */ + char kf_sa_peer[128]; /* Peer address. */ + int _kf_ispare[16]; /* Space for more stuff. */ + /* Truncated before copyout in sysctl */ + char kf_path[VKI_PATH_MAX]; /* Path to file, if any. */ +}; + +//---------------------------------------------------------------------- +// From sys/kenv.h +//---------------------------------------------------------------------- +#define VKI_KENV_GET 0 +#define VKI_KENV_SET 1 +#define VKI_KENV_UNSET 2 +#define VKI_KENV_DUMP 3 + +//---------------------------------------------------------------------- +// From sys/sysctl.h (and related) +//---------------------------------------------------------------------- + +#include +#include + +#define VKI_CTL_KERN CTL_KERN +#define VKI_CTL_HW CTL_HW +#define VKI_KERN_PROC KERN_PROC +#define VKI_KERN_PROC_VMMAP KERN_PROC_VMMAP +#define VKI_KERN_PROC_FILEDESC KERN_PROC_FILEDESC +#define VKI_HW_MACHINE HW_MACHINE + +//---------------------------------------------------------------------- +// From sys/thr.h +//---------------------------------------------------------------------- + +struct vki_thr_param { + void (*start_func)(void *); + void *arg; + char *stack_base; + vki_size_t stack_size; + char *tls_base; + vki_size_t tls_size; + long *child_tid; + long *parent_tid; + int flags; + struct vki_rtprio *rtp; + void *spare[3]; +}; + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 include/vki/vki-machine-types-amd64-freebsd.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/vki/vki-machine-types-amd64-freebsd.h Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,77 @@ + +/*--------------------------------------------------------------------*/ +/*--- x86/Linux-specific kernel interface: posix types. ---*/ +/*--- vki_posixtypes-x86-linux.h ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2005 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#ifndef __VKI_MACHINE_TYPES_AMD64_FREEBSD_H +#define __VKI_MACHINE_TYPES_AMD64_FREEBSD_H + +//---------------------------------------------------------------------- +// From sys/i386/include/_types.h +//---------------------------------------------------------------------- + +typedef __signed char vki_int8_t; +typedef unsigned char vki_uint8_t; +typedef short vki_int16_t; +typedef unsigned short vki_uint16_t; +typedef int vki_int32_t; +typedef unsigned int vki_uint32_t; +typedef long vki_int64_t; +typedef unsigned long vki_uint64_t; +typedef unsigned long vki_uintptr_t; +typedef long vki_intptr_t; + + +typedef unsigned int __vki_clock_t; +typedef unsigned int __vki_cpumask_t; +typedef char * __vki_caddr_t; /* QQQ 32 on 64 */ +typedef double __vki_double_t; +typedef double __vki_float_t; +typedef vki_int64_t __vki_intfptr_t; +typedef vki_int64_t __vki_intmax_t; +typedef vki_int64_t __vki_ptrdiff_t; +typedef vki_int64_t __vki_register_t; +typedef vki_int64_t __vki_segsz_t; +typedef vki_uint64_t __vki_size_t; +typedef vki_int64_t __vki_ssize_t; +typedef vki_int64_t __vki_time_t; +typedef vki_uint64_t __vki_uintfptr_t; +typedef vki_uint64_t __vki_uintmax_t; +typedef vki_uint64_t __vki_u_register_t; +typedef vki_uint64_t __vki_vm_offset_t; +typedef vki_int64_t __vki_vm_ooffset_t; +typedef vki_uint64_t __vki_vm_paddr_t; /* QQQ int64 for PAE */ +typedef vki_uint64_t __vki_vm_pindex_t; +typedef vki_uint64_t __vki_vm_size_t; + +#endif // __VKI_MACHINE_TYPES_AMD64_FREEBSD_H + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 include/vki/vki-machine-types-amd64-openbsd.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/vki/vki-machine-types-amd64-openbsd.h Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,77 @@ + +/*--------------------------------------------------------------------*/ +/*--- x86/Linux-specific kernel interface: posix types. ---*/ +/*--- vki_posixtypes-x86-linux.h ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2005 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#ifndef __VKI_MACHINE_TYPES_AMD64_OPENBSD_H +#define __VKI_MACHINE_TYPES_AMD64_OPENBSD_H + +//---------------------------------------------------------------------- +// From sys/i386/include/_types.h +//---------------------------------------------------------------------- + +typedef __signed char vki_int8_t; +typedef unsigned char vki_uint8_t; +typedef short vki_int16_t; +typedef unsigned short vki_uint16_t; +typedef int vki_int32_t; +typedef unsigned int vki_uint32_t; +typedef long vki_int64_t; +typedef unsigned long vki_uint64_t; +typedef unsigned long vki_uintptr_t; +typedef long vki_intptr_t; + + +typedef unsigned int __vki_clock_t; +typedef unsigned int __vki_cpumask_t; +typedef char * __vki_caddr_t; /* QQQ 32 on 64 */ +typedef double __vki_double_t; +typedef double __vki_float_t; +typedef vki_int64_t __vki_intfptr_t; +typedef vki_int64_t __vki_intmax_t; +typedef vki_int64_t __vki_ptrdiff_t; +typedef vki_int64_t __vki_register_t; +typedef vki_int64_t __vki_segsz_t; +typedef vki_uint64_t __vki_size_t; +typedef vki_int64_t __vki_ssize_t; +typedef vki_int64_t __vki_time_t; +typedef vki_uint64_t __vki_uintfptr_t; +typedef vki_uint64_t __vki_uintmax_t; +typedef vki_uint64_t __vki_u_register_t; +typedef vki_uint64_t __vki_vm_offset_t; +typedef vki_int64_t __vki_vm_ooffset_t; +typedef vki_uint64_t __vki_vm_paddr_t; /* QQQ int64 for PAE */ +typedef vki_uint64_t __vki_vm_pindex_t; +typedef vki_uint64_t __vki_vm_size_t; + +#endif // __VKI_MACHINE_TYPES_AMD64_OPENBSD_H + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 include/vki/vki-machine-types-x86-freebsd.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/vki/vki-machine-types-x86-freebsd.h Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,77 @@ + +/*--------------------------------------------------------------------*/ +/*--- x86/Linux-specific kernel interface: posix types. ---*/ +/*--- vki_posixtypes-x86-linux.h ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2005 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#ifndef __VKI_MACHINE_TYPES_X86_FREEBSD_H +#define __VKI_MACHINE_TYPES_X86_FREEBSD_H + +//---------------------------------------------------------------------- +// From sys/i386/include/_types.h +//---------------------------------------------------------------------- + +typedef __signed char vki_int8_t; +typedef unsigned char vki_uint8_t; +typedef short vki_int16_t; +typedef unsigned short vki_uint16_t; +typedef int vki_int32_t; +typedef unsigned int vki_uint32_t; +typedef long long vki_int64_t; +typedef unsigned long long vki_uint64_t; +typedef unsigned int vki_uintptr_t; +typedef int vki_intptr_t; + + +typedef unsigned long __vki_clock_t; +typedef unsigned int __vki_cpumask_t; +typedef char * __vki_caddr_t; /* QQQ 32 on 64 */ +typedef double __vki_double_t; +typedef double __vki_float_t; +typedef vki_int32_t __vki_intfptr_t; +typedef vki_int64_t __vki_intmax_t; +typedef vki_int32_t __vki_ptrdiff_t; +typedef vki_int32_t __vki_register_t; +typedef vki_int32_t __vki_segsz_t; +typedef vki_uint32_t __vki_size_t; +typedef vki_int32_t __vki_ssize_t; +typedef vki_int32_t __vki_time_t; +typedef vki_uint32_t __vki_uintfptr_t; +typedef vki_uint64_t __vki_uintmax_t; +typedef vki_uint32_t __vki_u_register_t; +typedef vki_uint32_t __vki_vm_offset_t; +typedef vki_int64_t __vki_vm_ooffset_t; +typedef vki_uint32_t __vki_vm_paddr_t; /* QQQ int64 for PAE */ +typedef vki_uint64_t __vki_vm_pindex_t; +typedef vki_uint32_t __vki_vm_size_t; + +#endif // __VKI_MACHINE_TYPES_X86_FREEBSD_H + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 include/vki/vki-machine-types-x86-openbsd.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/vki/vki-machine-types-x86-openbsd.h Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,77 @@ + +/*--------------------------------------------------------------------*/ +/*--- x86/Linux-specific kernel interface: posix types. ---*/ +/*--- vki_posixtypes-x86-linux.h ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2005 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#ifndef __VKI_MACHINE_TYPES_X86_OEPNBSD_H +#define __VKI_MACHINE_TYPES_X86_OPENBSD_H + +//---------------------------------------------------------------------- +// From sys/i386/include/_types.h +//---------------------------------------------------------------------- + +typedef __signed char vki_int8_t; +typedef unsigned char vki_uint8_t; +typedef short vki_int16_t; +typedef unsigned short vki_uint16_t; +typedef int vki_int32_t; +typedef unsigned int vki_uint32_t; +typedef long long vki_int64_t; +typedef unsigned long long vki_uint64_t; +typedef unsigned int vki_uintptr_t; +typedef int vki_intptr_t; + + +typedef unsigned long __vki_clock_t; +typedef unsigned int __vki_cpumask_t; +typedef char * __vki_caddr_t; /* QQQ 32 on 64 */ +typedef double __vki_double_t; +typedef double __vki_float_t; +typedef vki_int32_t __vki_intfptr_t; +typedef vki_int64_t __vki_intmax_t; +typedef vki_int32_t __vki_ptrdiff_t; +typedef vki_int32_t __vki_register_t; +typedef vki_int32_t __vki_segsz_t; +typedef vki_uint32_t __vki_size_t; +typedef vki_int32_t __vki_ssize_t; +typedef vki_int32_t __vki_time_t; +typedef vki_uint32_t __vki_uintfptr_t; +typedef vki_uint64_t __vki_uintmax_t; +typedef vki_uint32_t __vki_u_register_t; +typedef vki_uint32_t __vki_vm_offset_t; +typedef vki_int64_t __vki_vm_ooffset_t; +typedef vki_uint32_t __vki_vm_paddr_t; /* QQQ int64 for PAE */ +typedef vki_uint64_t __vki_vm_pindex_t; +typedef vki_uint32_t __vki_vm_size_t; + +#endif // __VKI_MACHINE_TYPES_X86_OPENBSD_H + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 include/vki/vki-openbsd.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/vki/vki-openbsd.h Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,2374 @@ + +/*--------------------------------------------------------------------*/ +/*--- FreeBSD-specific kernel interface. vki-freebsd.h ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2005 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +/* This file defines types and constants for the kernel interface, and to + make that clear everything is prefixed VKI_/vki_. + + All code is copied verbatim from kernel source files, except that: + - VKI_/vki_ prefixes are added + - some extra explanatory comments are included; they are all within + "[[ ]]" + - for some types, we only care about the size; for a few of them (big + ones that are painful to fully drag in here), a VKI_SIZEOF_* constant + is used. + + The files the code is taken from is indicated. + + Note especially that the types are not the glibc versions, many of which + are different to those in here. + + Also note that this file contains all the generic header info, ie. that + from linux/include/linux/ *.h. The arch-specific header info, eg. that + from linux/include/asm-i386/ *.h, is in vki-$PLATFORM.h and + vki_posixtypes-$PLATFORM.h. (Two files are required to avoid + circular dependencies between the generic VKI header and the + arch-specific VKI header. It's possible in the future, as more stuff + gets pulled in, that we might have to split files up some more to avoid + further circular dependencies.) + + Finally, note that it is assumed that __KERNEL__ is set for all these + definitions, which affects some of them. +*/ + +#ifndef __VKI_OPENBSD_H +#define __VKI_OPENBSD_H + +//---------------------------------------------------------------------- +// Arch-specific POSIX types +//---------------------------------------------------------------------- + +#if defined(VGA_x86) +# include "vki-machine-types-x86-openbsd.h" +#elif defined(VGA_amd64) +# include "vki-machine-types-amd64-openbsd.h" +#else +# error Unknown platform +#endif + +#include + + +//---------------------------------------------------------------------- +// From sys/select.h +//---------------------------------------------------------------------- + +typedef unsigned long __vki_fd_mask; + +#undef __VKI_NFDBITS +#define __VKI_NFDBITS (8 * sizeof(__vki_fd_mask)) + +#undef __VKI_FD_SETSIZE +#define __VKI_FD_SETSIZE 1024U + +#undef __VKI_FDSET_LONGS +#define __VKI_FDSET_LONGS (__VKI_FD_SETSIZE/__VKI_NFDBITS) + +#undef __VKI_FDELT +#define __VKI_FDELT(d) ((d) / __VKI_NFDBITS) + +#undef __VKI_FDMASK +#define __VKI_FDMASK(d) (1UL << ((d) % __VKI_NFDBITS)) + +typedef struct { + unsigned long fds_bits [__VKI_FDSET_LONGS]; +} __vki_fd_set; + +//---------------------------------------------------------------------- +// sys/_types.h +//---------------------------------------------------------------------- +/* MD QQQ 32 on 64 */ +typedef long __vki_key_t; +typedef long __vki_suseconds_t; +typedef struct __timer *__vki_timer_t; +typedef struct __mq *__vki_mqd_t; + +/* MI */ +typedef vki_uint32_t __vki_blksize_t; +typedef vki_int64_t __vki_blkcnt_t; +typedef vki_int32_t __vki_clockid_t; +typedef vki_int32_t __vki_ct_rune_t; +typedef vki_uint32_t __vki_fflags_t; +typedef vki_uint64_t __vki_fsblkcnt_t; +typedef vki_uint64_t __vki_fsfilcnt_t; +typedef vki_uint32_t __vki_gid_t; +typedef vki_int64_t __vki_id_t; +typedef vki_uint64_t __vki_ino_t; +typedef vki_int32_t __vki_lwpid_t; +typedef vki_uint32_t __vki_mode_t; +typedef vki_uint32_t __vki_nlink_t; +typedef vki_int64_t __vki_off_t; +typedef vki_int32_t __vki_pid_t; +typedef vki_int64_t __vki_rlim_t; +typedef vki_uint8_t __vki_sa_family_t; +typedef vki_uint32_t __vki_socklen_t; +typedef vki_uint32_t __vki_uid_t; +typedef vki_int32_t __vki_useconds_t; +typedef __vki_ct_rune_t __vki_rune_t; +typedef __vki_ct_rune_t __vki_wchar_t; +typedef __vki_ct_rune_t __vki_wint_t; +typedef vki_uint32_t __vki_dev_t; +typedef vki_uint32_t __vki_fixpt_t; + + +//---------------------------------------------------------------------- +// sys/types.h +//---------------------------------------------------------------------- + +typedef vki_uint8_t vki_u_int8_t; +typedef vki_uint16_t vki_u_int16_t; +typedef vki_uint32_t vki_u_int32_t; +typedef vki_uint64_t vki_u_int64_t; + +typedef vki_uint64_t vki_u_quad_t; +typedef vki_int64_t vki_quad_t; +typedef __vki_caddr_t vki_caddr_t; +typedef __const __vki_caddr_t vki_c_caddr_t; +typedef __volatile __vki_caddr_t vki_v_caddr_t; + +typedef __vki_blksize_t vki_blksize_t; +typedef __vki_blkcnt_t vki_blkcnt_t; +typedef __vki_clock_t vki_clock_t; +typedef __vki_clockid_t vki_clockid_t; +typedef __vki_dev_t vki_dev_t; +typedef __vki_fflags_t vki_fflags_t; +typedef __vki_fixpt_t vki_fixpt_t; +typedef __vki_fsblkcnt_t vki_fsblkcnt_t; +typedef __vki_fsfilcnt_t vki_fsfilcnt_t; +typedef __vki_gid_t vki_gid_t; +typedef vki_uint32_t vki_in_addr_t; +typedef vki_uint16_t vki_in_port_t; +typedef __vki_id_t vki_id_t; +typedef __vki_ino_t vki_ino_t; +typedef __vki_key_t vki_key_t; +typedef __vki_lwpid_t vki_lwpid_t; +typedef __vki_mode_t vki_mode_t; +typedef __vki_nlink_t vki_nlink_t; +typedef __vki_off_t vki_off_t; +typedef __vki_pid_t vki_pid_t; +typedef __vki_register_t vki_register_t; +typedef __vki_rlim_t vki_rlim_t; +typedef __vki_segsz_t vki_segsz_t; +typedef __vki_size_t vki_size_t; +typedef __vki_ssize_t vki_ssize_t; +typedef __vki_suseconds_t vki_suseconds_t; +typedef __vki_time_t vki_time_t; +typedef __vki_timer_t vki_timer_t; +typedef __vki_mqd_t vki_mqd_t; +typedef __vki_u_register_t vki_u_register_t; +typedef __vki_uid_t vki_uid_t; +typedef __vki_useconds_t vki_useconds_t; + +typedef __vki_vm_offset_t vki_vm_offset_t; +typedef __vki_vm_ooffset_t vki_vm_ooffset_t; +typedef __vki_vm_paddr_t vki_vm_paddr_t; +typedef __vki_vm_pindex_t vki_vm_pindex_t; +typedef __vki_vm_size_t vki_vm_size_t; + +//---------------------------------------------------------------------- +// sys/select.h +//---------------------------------------------------------------------- + +typedef __vki_fd_set vki_fd_set; + +//---------------------------------------------------------------------- +// Now the rest of the arch-specific stuff +//---------------------------------------------------------------------- + +#if defined(VGA_x86) +# include "vki-x86-openbsd.h" +#elif defined(VGA_amd64) +# include "vki-amd64-openbsd.h" +#elif defined(VGA_ppc32) +# include "vki-ppc32-openbsd.h" +#elif defined(VGA_ppc64) +# include "vki-ppc64-openbsd.h" +#else +# error Unknown platform +#endif + +//---------------------------------------------------------------------- +// linux and openbsd version hacks +//---------------------------------------------------------------------- +#ifndef ELFMAG +#define ELFMAG "\177ELF" /* magic string */ +#endif +#ifndef SELFMAG +#define SELFMAG 4 /* magic string size */ +#endif + +//---------------------------------------------------------------------- +// From sys/syslimits.h +//---------------------------------------------------------------------- + +#define VKI_PATH_MAX 1024 + + +//---------------------------------------------------------------------- +// From sys/timespec.h +//---------------------------------------------------------------------- + +struct vki_timespec { + vki_time_t tv_sec; /* seconds */ + long tv_nsec; /* nanoseconds */ +}; + +struct vki_itimerspec { + struct vki_timespec it_interval; /* timer period */ + struct vki_timespec it_value; /* timer expiration */ +}; + +//---------------------------------------------------------------------- +// From sys/_time.h +//---------------------------------------------------------------------- + +struct vki_timeval { + vki_time_t tv_sec; /* seconds */ + vki_suseconds_t tv_usec; /* microseconds */ +}; + +//---------------------------------------------------------------------- +// From sys/time.h +//---------------------------------------------------------------------- + +#define VKI_CLOCK_REALTIME 0 +#define VKI_CLOCK_MONOTONIC 1 +#define VKI_CLOCK_PROCESS_CPUTIME_ID 2 +#define VKI_CLOCK_THREAD_CPUTIME_ID 3 + +struct vki_timezone { + int tz_minuteswest; /* minutes west of Greenwich */ + int tz_dsttime; /* type of dst correction */ +}; + +struct vki_itimerval { + struct vki_timeval it_interval; /* timer interval */ + struct vki_timeval it_value; /* current value */ +}; + +//---------------------------------------------------------------------- +// From sys/timex.h +//---------------------------------------------------------------------- + +struct vki_ntptimeval { + struct vki_timespec time; + long maxerror; + long esterror; + long tai; + int time_state; +}; + +struct vki_timex { + unsigned int modes; /* mode selector */ + long offset; /* time offset (usec) */ + long freq; /* frequency offset (scaled ppm) */ + long maxerror; /* maximum error (usec) */ + long esterror; /* estimated error (usec) */ + int status; /* clock command/status */ + long constant; /* pll time constant */ + long precision; /* clock precision (usec) (read only) */ + long tolerance; /* clock frequency tolerance (ppm) + * (read only) + */ + long ppsfreq; /* pps frequency (scaled ppm) (ro) */ + long jitter; /* pps jitter (us) (ro) */ + int shift; /* interval duration (s) (shift) (ro) */ + long stabil; /* pps stability (scaled ppm) (ro) */ + long jitcnt; /* jitter limit exceeded (ro) */ + long calcnt; /* calibration intervals (ro) */ + long errcnt; /* calibration errors (ro) */ + long stbcnt; /* stability limit exceeded (ro) */ +}; + +#define MOD_OFFSET 0x0001 /* time offset */ +#define MOD_FREQUENCY 0x0002 /* frequency offset */ +#define MOD_MAXERROR 0x0004 /* maximum time error */ +#define MOD_ESTERROR 0x0008 /* estimated time error */ +#define MOD_STATUS 0x0010 /* clock status */ +#define MOD_TIMECONST 0x0020 /* pll time constant */ +#define MOD_PPSMAX 0x0040 +#define MOD_TAI 0x0080 +#define MOD_MICRO 0x1000 +#define MOD_NANO 0x2000 +#define MOD_CLKB 0x4000 +#define MOD_CLKA 0x8000 + +//---------------------------------------------------------------------- +// From sys/times.h +//---------------------------------------------------------------------- + +struct vki_tms { + vki_clock_t tms_utime; + vki_clock_t tms_stime; + vki_clock_t tms_cutime; + vki_clock_t tms_cstime; +}; + +//---------------------------------------------------------------------- +// From sys/stat.h +//---------------------------------------------------------------------- + +struct vki_stat { + vki_mode_t st_mode; + vki_dev_t st_dev; + vki_ino_t st_ino; + vki_nlink_t st_nlink; + vki_uid_t st_uid; + vki_gid_t st_gid; + vki_dev_t st_rdev; +#if 0 + struct vki_timespec st_atimespec; + struct vki_timespec st_mtimespec; + struct vki_timespec st_ctimespec; +#else + vki_time_t st_atime; + long st_atime_nsec; + vki_time_t st_mtime; + long st_mtime_nsec; + vki_time_t st_ctime; + long st_ctime_nsec; +#endif + vki_off_t st_size; + vki_blkcnt_t st_blocks; + vki_blksize_t st_blksize; + vki_fflags_t st_flags; + vki_uint32_t st_gen; + struct vki_timespec st_birthtimespec; +#if 0 + unsigned int :(8 / 2) * (16 - (int)sizeof(struct vki_timespec)); + unsigned int :(8 / 2) * (16 - (int)sizeof(struct vki_timespec)); +#endif +}; + + +//---------------------------------------------------------------------- +// From linux-2.6.8.1/include/linux/sched.h +//---------------------------------------------------------------------- + +struct vki_sched_param { + int sched_priority; +}; + +//---------------------------------------------------------------------- +// From sys/signal.h +//---------------------------------------------------------------------- + +#define VKI_SIG_BLOCK 1 /* block specified signal set */ +#define VKI_SIG_UNBLOCK 2 /* unblock specified signal set */ +#define VKI_SIG_SETMASK 3 /* set specified signal set */ + +#define VKI_SIG_DFL ((__vki_sighandler_t)0) +#define VKI_SIG_IGN ((__vki_sighandler_t)1) +#define VKI_SIG_ERR ((__vki_sighandler_t)-1) + +typedef void __vki_signalfn_t(int); +typedef __vki_signalfn_t *__vki_sighandler_t; + +#define VKI_SIGHUP 1 +#define VKI_SIGINT 2 +#define VKI_SIGQUIT 3 +#define VKI_SIGILL 4 +#define VKI_SIGTRAP 5 +#define VKI_SIGABRT 6 +#define VKI_SIGEMT 7 +#define VKI_SIGFPE 8 +#define VKI_SIGKILL 9 +#define VKI_SIGBUS 10 +#define VKI_SIGSEGV 11 +#define VKI_SIGSYS 12 +#define VKI_SIGPIPE 13 +#define VKI_SIGALRM 14 +#define VKI_SIGTERM 15 +#define VKI_SIGURG 16 +#define VKI_SIGSTOP 17 +#define VKI_SIGTSTP 18 +#define VKI_SIGCONT 19 +#define VKI_SIGCHLD 20 +#define VKI_SIGTTIN 21 +#define VKI_SIGTTOU 22 +#define VKI_SIGIO 23 +#define VKI_SIGXCPU 24 +#define VKI_SIGXFSZ 25 +#define VKI_SIGVTALRM 26 +#define VKI_SIGPROF 27 +#define VKI_SIGWINCH 28 +#define VKI_SIGINFO 29 +#define VKI_SIGUSR1 30 +#define VKI_SIGUSR2 31 +#define VKI_SIGTHR 32 + +#define VKI_SIGRTMIN 65 +#define VKI_SIGRTMAX 126 + +#define VKI_SA_ONSTACK 0x0001 +#define VKI_SA_RESTART 0x0002 +#define VKI_SA_RESETHAND 0x0004 +#define VKI_SA_NOCLDSTOP 0x0008 +#define VKI_SA_NODEFER 0x0010 +#define VKI_SA_NOCLDWAIT 0x0020 +#define VKI_SA_SIGINFO 0x0040 + +#define VKI_SS_ONSTACK 0x0001 +#define VKI_SS_DISABLE 0x0004 + +#define VKI_SA_ONESHOT VKI_SA_RESETHAND +#define VKI_SA_NOMASK VKI_SA_NODEFER + +struct vki_sigaction { + __vki_sighandler_t ksa_handler; + vki_sigset_t sa_mask; + int sa_flags; +}; + +typedef struct vki_sigaltstack { + void *ss_sp; + vki_size_t ss_size; + int ss_flags; +} vki_stack_t; + +typedef union vki_sigval { + int sival_int; + void *sival_ptr; +} vki_sigval_t; + +#if 0 /* freebsd6 */ +typedef struct vki_siginfo { + int si_signo; + int si_errno; + int si_code; + vki_pid_t si_pid; + vki_uid_t si_uid; + int si_status; + void *si_addr; + vki_sigval_t si_value; + + union { + + /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */ + struct { + int _trapno; /* TRAP # which caused the signal */ + } _sigfault; + + /* POSIX.1b timers */ + struct { + int _timerid; /* timer id */ + int _overrun; /* overrun count */ + } _timer; + + struct { + int _mqd; + } _mesgq; + + /* SIGPOLL */ + struct { + long _band; /* POLL_IN, POLL_OUT, POLL_MSG */ + } _sigpoll; + + struct { + long __spare1__; + int __spare2[7]; + } __spare__; + } _sifields; +} vki_siginfo_t; +#endif +#if 0 +typedef struct vki_siginfo { + int si_signo; + int si_errno; + int si_code; +#ifdef si_pid // conflict with si_pid in +#undef si_pid +#endif + vki_pid_t si_pid; +#ifdef si_uid // conflict with si_uid in +#undef si_uid +#endif + vki_uid_t si_uid; +#ifdef si_status // conflict with si_status in +#undef si_status +#endif + int si_status; +#ifdef si_addr // conflict with si_addr in +#undef si_addr +#endif + void *si_addr; +#ifdef si_value // conflict with si_value in +#undef si_value +#endif + vki_sigval_t si_value; +// 666: not valid. switch to above def +#ifdef si_band // conflict with si_band in +#undef si_band +#endif + long si_band; + int __spare__[7]; +} vki_siginfo_t; +#endif +// XXX OpenBSD sys/sys/siginfo.h +typedef struct { + int si_signo; /* signal from signal.h */ + int si_code; /* code from above */ + int si_errno; /* error from errno.h */ + union { + int _pad[SI_PAD]; /* for future growth */ + struct { /* kill(), SIGCLD, siqqueue() */ + pid_t _pid; /* process ID */ + union { + struct { + uid_t _uid; + union sigval _value; + } _kill; + struct { + clock_t _utime; + clock_t _stime; + int _status; + } _cld; + } _pdata; + } _proc; + struct { /* SIGSEGV, SIGBUS, SIGILL and SIGFPE */ + caddr_t _addr; /* faulting address */ + int _trapno; /* illegal trap number */ + } _fault; +#if 0 + struct { /* SIGPOLL, SIGXFSZ */ + /* fd not currently available for SIGPOLL */ + int _fd; /* file descriptor */ + long _band; + } _file; + struct { /* SIGPROF */ + caddr_t _faddr; /* last fault address */ + timespec _tstamp; /* real time stamp */ + short _syscall; /* current syscall */ + char _nsysarg; /* number of arguments */ + char _fault; /* last fault type */ + long _sysarg[8]; /* syscall arguments */ + long _mstate[17]; /* exactly fills struct*/ + } _prof; +#endif + } _data; +} vki_siginfo_t; + +#define si_pid _data._proc._pid + +#define si_status _data._proc._pdata._cld._status +#define si_stime _data._proc._pdata._cld._stime +#define si_utime _data._proc._pdata._cld._utime +#define si_uid _data._proc._pdata._kill._uid +#define si_value _data._proc._pdata._kill._value +#define si_addr _data._fault._addr +#define si_trapno _data._fault._trapno +#define si_fd _data._file._fd +#define si_band _data._file._band + +#define si_tstamp _data._prof._tstamp +#define si_syscall _data._prof._syscall +#define si_nsysarg _data._prof._nsysarg +#define si_sysarg _data._prof._sysarg +#define si_fault _data._prof._fault +#define si_faddr _data._prof._faddr +#define si_mstate _data._prof._mstate + +/* + * si_code values + */ +#define VKI_SI_USER 0x10001 /* sent by kill, sigsend, raise */ +#define VKI_SI_QUEUE 0x10002 +#define VKI_SI_TIMER 0x10003 +#define VKI_SI_ASYNCIO 0x10004 +#define VKI_SI_MESGQ 0x10005 + +/* + * SIGILL si_codes + */ +#define VKI_ILL_ILLOPC 1 /* illegal opcode */ +#define VKI_ILL_ILLOPN 2 /* illegal operand */ +#define VKI_ILL_ILLADR 3 /* illegal addressing mode */ +#define VKI_ILL_ILLTRP 4 /* illegal trap */ +#define VKI_ILL_PRVOPC 5 /* privileged opcode */ +#define VKI_ILL_PRVREG 6 /* privileged register */ +#define VKI_ILL_COPROC 7 /* coprocessor error */ +#define VKI_ILL_BADSTK 8 /* internal stack error */ + +/* + * SIGFPE si_codes + */ +#define VKI_FPE_INTOVF 1 /* integer overflow */ +#define VKI_FPE_INTDIV 2 /* integer divide by zero */ +#define VKI_FPE_FLTDIV 3 /* floating point divide by zero */ +#define VKI_FPE_FLTOVF 4 /* floating point overflow */ +#define VKI_FPE_FLTUND 5 /* floating point underflow */ +#define VKI_FPE_FLTRES 6 /* floating point inexact result */ +#define VKI_FPE_FLTINV 7 /* floating point invalid operation */ +#define VKI_FPE_FLTSUB 8 /* subscript out of range */ + +/* + * SIGSEGV si_codes + */ +#define VKI_SEGV_MAPERR 1 /* address not mapped to object */ +#define VKI_SEGV_ACCERR 2 /* invalid permissions for mapped object */ +/* XXX i386 and amd64 specific */ +#define VKI_SEGV_PAGE_FAULT 12 + +/* + * SIGBUS si_codes + */ +#define VKI_BUS_ADRALN 1 /* invalid address alignment */ +#define VKI_BUS_ADRERR 2 /* non-existant physical address */ +#define VKI_BUS_OBJERR 3 /* object specific hardware error */ + +/* + * SIGTRAP si_codes + */ +#define VKI_TRAP_BRKPT 1 /* process breakpoint */ +#define VKI_TRAP_TRACE 2 /* process trace trap */ + + +#if 0 /* freebsd-6 */ +typedef struct vki_sigevent { + int sigev_notify; + int sigev_signo; + vki_sigval_t sigev_value; + union { + int _threadid; + + struct { + void (*_function)(vki_sigval_t); + void *_attribute; /* really pthread_attr_t */ + } _sigev_thread; + long __spare__[8]; + } _sigev_un; +} vki_sigevent_t; +#endif + +struct vki_sigevent { + int sigev_notify; /* Notification type */ + union { + int __sigev_signo; /* Signal number */ + int __sigev_notify_kqueue; + } __sigev_u; + vki_sigval_t sigev_value; /* Signal value */ +}; +#if 0 +#define sigev_signo __sigev_u.__sigev_signo +#define sigev_notify_kqueue __sigev_u.__sigev_notify_kqueue +#endif + +//---------------------------------------------------------------------- +// From sys/_iovec.h +//---------------------------------------------------------------------- + +struct vki_iovec +{ + void *iov_base; + __vki_size_t iov_len; +}; + +//---------------------------------------------------------------------- +// From sys/socket.h +//---------------------------------------------------------------------- + +typedef __vki_sa_family_t vki_sa_family_t; +typedef __vki_socklen_t vki_socklen_t; + +struct vki_sockaddr { + vki_uint8_t sa_len; + vki_sa_family_t sa_family; /* address family, AF_xxx */ + char sa_data[14]; /* 14 bytes of protocol address */ +}; + +struct vki_msghdr { + void * msg_name; /* Socket name */ + vki_socklen_t msg_namelen; /* Length of name */ + struct vki_iovec * msg_iov; /* Data blocks */ + int msg_iovlen; /* Number of blocks */ + void * msg_control; /* Per protocol magic (eg BSD file descriptor passing) */ + vki_socklen_t msg_controllen; /* Length of cmsg list */ + int msg_flags; +}; + +struct vki_cmsghdr { + vki_socklen_t cmsg_len; /* data byte count, including hdr */ + int cmsg_level; /* originating protocol */ + int cmsg_type; /* protocol-specific type */ +}; + +#define __VKI_CMSG_NXTHDR(ctl, len, cmsg) __vki_cmsg_nxthdr((ctl),(len),(cmsg)) +#define VKI_CMSG_NXTHDR(mhdr, cmsg) vki_cmsg_nxthdr((mhdr), (cmsg)) + +#define VKI_CMSG_ALIGN(len) ( ((len)+sizeof(long)-1) & ~(sizeof(long)-1) ) + +#define VKI_CMSG_DATA(cmsg) ((void *)((char *)(cmsg) + VKI_CMSG_ALIGN(sizeof(struct vki_cmsghdr)))) + +#define __VKI_CMSG_FIRSTHDR(ctl,len) ((len) >= sizeof(struct vki_cmsghdr) ? \ + (struct vki_cmsghdr *)(ctl) : \ + (struct vki_cmsghdr *)NULL) +#define VKI_CMSG_FIRSTHDR(msg) __VKI_CMSG_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen) + +// [[Urgh, this is revolting...] +// QQQ check +static __inline struct vki_cmsghdr * __vki_cmsg_nxthdr(void *__ctl, vki_socklen_t __size, + struct vki_cmsghdr *__cmsg) +{ + struct vki_cmsghdr * __ptr; + + __ptr = (struct vki_cmsghdr*)(((unsigned char *) __cmsg) + VKI_CMSG_ALIGN(__cmsg->cmsg_len)); + if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size) + return (struct vki_cmsghdr *)0; + + return __ptr; +} + +static __inline struct vki_cmsghdr * vki_cmsg_nxthdr (struct vki_msghdr *__msg, struct vki_cmsghdr *__cmsg) +{ + return __vki_cmsg_nxthdr(__msg->msg_control, __msg->msg_controllen, __cmsg); +} + +#define VKI_SCM_RIGHTS 0x01 /* rw: access rights (array of int) */ + +#define VKI_AF_UNIX 1 /* Unix domain sockets */ +#define VKI_AF_INET 2 /* Internet IP Protocol */ +#define VKI_AF_INET6 28 /* IP version 6 */ + +#define VKI_MSG_NOSIGNAL 0x20000 /* Do not generate SIGPIPE */ + +#define VKI_SOL_SOCKET 0xffff + +#define VKI_SO_TYPE 0x1008 + +#define VKI_SOCK_STREAM 1 + +#include + +#define VKI_TCP_NODELAY TCP_NODELAY + +#include + +#define VKI_IPPROTO_TCP IPPROTO_TCP + +//---------------------------------------------------------------------- +// From netinet/in.h +//---------------------------------------------------------------------- + +struct vki_in_addr { + vki_in_addr_t s_addr; +}; + +/* Structure describing an Internet (IP) socket address. */ +#define __VKI_SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */ +struct vki_sockaddr_in { + vki_uint8_t sin_len; + vki_sa_family_t sin_family; /* Address family */ + vki_in_port_t sin_port; /* Port number */ + struct vki_in_addr sin_addr; /* Internet address */ + char sin_zero[8]; +}; + +//---------------------------------------------------------------------- +// From netinet6/in6.h +//---------------------------------------------------------------------- + +struct vki_in6_addr +{ + union + { + vki_uint8_t u6_addr8[16]; + vki_uint16_t u6_addr16[8]; + vki_uint32_t u6_addr32[4]; + } vki_in6_u; +#define vki_s6_addr vki_in6_u.u6_addr8 +#define vki_s6_addr16 vki_in6_u.u6_addr16 +#define vki_s6_addr32 vki_in6_u.u6_addr32 +}; + +struct vki_sockaddr_in6 { + vki_uint8_t sin6_len; + vki_sa_family_t sin6_family; /* AF_INET6 */ + vki_uint16_t sin6_port; /* Transport layer port # */ + vki_uint32_t sin6_flowinfo; /* IPv6 flow information */ + struct vki_in6_addr sin6_addr; /* IPv6 address */ + vki_uint32_t sin6_scope_id; /* scope id (new in RFC2553) */ +}; + +//---------------------------------------------------------------------- +// From sys/un.h +//---------------------------------------------------------------------- + +#define VKI_UNIX_PATH_MAX 104 /* QQQ overridden by sun_len */ + +struct vki_sockaddr_un { + unsigned char sun_len; + vki_sa_family_t sun_family; /* AF_UNIX */ + char sun_path[VKI_UNIX_PATH_MAX]; /* pathname */ +}; + +#if 0 +//---------------------------------------------------------------------- +// From linux-2.6.8.1/include/linux/if.h +//---------------------------------------------------------------------- + +#define VKI_IFNAMSIZ 16 + +struct vki_ifmap +{ + unsigned long mem_start; + unsigned long mem_end; + unsigned short base_addr; + unsigned char irq; + unsigned char dma; + unsigned char port; + /* 3 bytes spare */ +}; + +struct vki_if_settings +{ + unsigned int type; /* Type of physical device or protocol */ + unsigned int size; /* Size of the data allocated by the caller */ + union { + // [[Nb: converted these all to void* to avoid pulling in + // unnecessary headers]]] + /* {atm/eth/dsl}_settings anyone ? */ + void /*raw_hdlc_proto */__user *raw_hdlc; + void /*cisco_proto */__user *cisco; + void /*fr_proto */__user *fr; + void /*fr_proto_pvc */__user *fr_pvc; + void /*fr_proto_pvc_info */__user *fr_pvc_info; + + /* interface settings */ + void /*sync_serial_settings */__user *sync; + void /*te1_settings */__user *te1; + } ifs_ifsu; +}; + +struct vki_ifreq +{ +#define VKI_IFHWADDRLEN 6 + union + { + char ifrn_name[VKI_IFNAMSIZ]; /* if name, e.g. "en0" */ + } ifr_ifrn; + + union { + struct vki_sockaddr ifru_addr; + struct vki_sockaddr ifru_dstaddr; + struct vki_sockaddr ifru_broadaddr; + struct vki_sockaddr ifru_netmask; + struct vki_sockaddr ifru_hwaddr; + short ifru_flags; + int ifru_ivalue; + int ifru_mtu; + struct vki_ifmap ifru_map; + char ifru_slave[VKI_IFNAMSIZ]; /* Just fits the size */ + char ifru_newname[VKI_IFNAMSIZ]; + void __user * ifru_data; + struct vki_if_settings ifru_settings; + } ifr_ifru; +}; + +#define vki_ifr_name ifr_ifrn.ifrn_name /* interface name */ +#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */ +#define ifr_addr ifr_ifru.ifru_addr /* address */ +#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */ +#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ +#define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */ +#define vki_ifr_flags ifr_ifru.ifru_flags /* flags */ +#define vki_ifr_metric ifr_ifru.ifru_ivalue /* metric */ +#define vki_ifr_mtu ifr_ifru.ifru_mtu /* mtu */ +#define ifr_map ifr_ifru.ifru_map /* device map */ +#define ifr_slave ifr_ifru.ifru_slave /* slave device */ +#define vki_ifr_data ifr_ifru.ifru_data /* for use by interface */ +#define vki_ifr_ifindex ifr_ifru.ifru_ivalue /* interface index */ +#define ifr_bandwidth ifr_ifru.ifru_ivalue /* link bandwidth */ +#define ifr_qlen ifr_ifru.ifru_ivalue /* Queue length */ +#define ifr_newname ifr_ifru.ifru_newname /* New name */ +#define ifr_settings ifr_ifru.ifru_settings /* Device/proto settings*/ + +struct vki_ifconf +{ + int ifc_len; /* size of buffer */ + union + { + char __user *ifcu_buf; + struct vki_ifreq __user *ifcu_req; + } ifc_ifcu; +}; +#define vki_ifc_buf ifc_ifcu.ifcu_buf /* buffer address */ + +//---------------------------------------------------------------------- +// From linux-2.6.8.1/include/linux/if_arp.h +//---------------------------------------------------------------------- + +struct vki_arpreq { + struct vki_sockaddr arp_pa; /* protocol address */ + struct vki_sockaddr arp_ha; /* hardware address */ + int arp_flags; /* flags */ + struct vki_sockaddr arp_netmask; /* netmask (only for proxy arps) */ + char arp_dev[16]; +}; + +//---------------------------------------------------------------------- +// From linux-2.6.8.1/include/linux/route.h +//---------------------------------------------------------------------- + +struct vki_rtentry +{ + unsigned long rt_pad1; + struct vki_sockaddr rt_dst; /* target address */ + struct vki_sockaddr rt_gateway; /* gateway addr (RTF_GATEWAY) */ + struct vki_sockaddr rt_genmask; /* target network mask (IP) */ + unsigned short rt_flags; + short rt_pad2; + unsigned long rt_pad3; + void *rt_pad4; + short rt_metric; /* +1 for binary compatibility! */ + char __user *rt_dev; /* forcing the device at add */ + unsigned long rt_mtu; /* per route MTU/Window */ +// [[Not important for Valgrind]] +//#ifndef __KERNEL__ +//#define rt_mss rt_mtu /* Compatibility :-( */ +//#endif + unsigned long rt_window; /* Window clamping */ + unsigned short rt_irtt; /* Initial RTT */ +}; +#endif + +// QQQ sort + +//---------------------------------------------------------------------- +// From sys/mount.h +//---------------------------------------------------------------------- + +typedef struct vki_fsid { vki_int32_t val[2]; } vki_fsid_t; +#define VKI_OMFSNAMELEN 16 +#define VKI_OMNAMELEN (88 - 2 * sizeof(long)) +#define VKI_MFSNAMELEN 16 +#define VKI_MNAMELEN 88 + +struct vki_statfs4 { + long f_spare2; + long f_bsize; + long f_iosize; + long f_blocks; + long f_bfree; + long f_bavail; + long f_files; + long f_ffree; + vki_fsid_t f_fsid; + vki_uid_t f_owner; + vki_int32_t f_type; + vki_int32_t f_flags; + long f_syncwrites; + long f_asyncwrites; + char f_fstypename[VKI_OMFSNAMELEN]; + char f_mntonname[VKI_OMNAMELEN]; + long f_syncreads; + long f_asyncreads; + vki_int16_t f_spares1; + char f_mntfromnname[VKI_OMNAMELEN]; + vki_int16_t f_spares2; + long f_spare[2]; +}; + +struct vki_statfs { + vki_uint32_t f_version; + vki_uint32_t f_type; + vki_uint64_t f_flags; + vki_uint64_t f_bsize; + vki_uint64_t f_iosize; + vki_uint64_t f_blocks; + vki_uint64_t f_bfree; + vki_int64_t f_bavail; + vki_uint64_t f_files; + vki_int64_t f_ffree; + vki_uint64_t f_syncwrites; + vki_uint64_t f_asyncwrites; + vki_uint64_t f_syncreads; + vki_uint64_t f_asyncreads; + vki_uint64_t f_spare[10]; + vki_uint32_t f_namemax; + vki_uid_t f_owner; + vki_fsid_t f_fsid; + char f_charspare[80]; + char f_fstypename[VKI_MFSNAMELEN]; + char f_mntfromnname[VKI_MNAMELEN]; + char f_mntonname[VKI_MNAMELEN]; +}; + +#define MAXFIDSZ 16 + +struct vki_fid { + vki_uint16_t fid_len; + vki_uint16_t fid_reserved; + char fid_data[MAXFIDSZ]; +}; + +struct vki_fhandle { + vki_fsid_t fh_fsid; + struct vki_fid fh_fid; +}; + +#define VKI_MNAMELEN6 88 +struct vki_statfs6 { + vki_uint32_t f_version; + vki_uint32_t f_type; + vki_uint64_t f_flags; + vki_uint64_t f_bsize; + vki_uint64_t f_iosize; + vki_uint64_t f_blocks; + vki_uint64_t f_bfree; + vki_int64_t f_bavail; + vki_uint64_t f_files; + vki_int64_t f_ffree; + vki_int64_t f_syncwrites; + vki_int64_t f_asyncwrites; + vki_int64_t f_syncreads; + vki_int64_t f_asyncreads; + vki_uint64_t f_spare[10]; + vki_uint32_t f_namemax; + vki_uid_t f_owner; + vki_fsid_t f_fsid; + char f_charspare[80]; + char f_fstypename[VKI_MFSNAMELEN]; + char f_mntfromnname[VKI_MNAMELEN6]; + char f_mntonname[VKI_MNAMELEN6]; +}; + +//---------------------------------------------------------------------- +// From sys/ttycom.h +//---------------------------------------------------------------------- + +struct vki_winsize { + unsigned short ws_row; + unsigned short ws_col; + unsigned short ws_xpixel; + unsigned short ws_ypixel; +}; + + +//---------------------------------------------------------------------- +// From sys/termios.h +//---------------------------------------------------------------------- + +typedef unsigned int vki_tcflag_t; +typedef unsigned char vki_cc_t; +typedef unsigned int vki_speed_t; + +#define VKI_NCCS 20 +struct vki_termios { + vki_tcflag_t c_iflag; /* input mode flags */ + vki_tcflag_t c_oflag; /* output mode flags */ + vki_tcflag_t c_cflag; /* control mode flags */ + vki_tcflag_t c_lflag; /* local mode flags */ + vki_cc_t c_cc[VKI_NCCS]; /* control characters */ + vki_speed_t c_ispeed; + vki_speed_t c_ospeed; +}; + +//---------------------------------------------------------------------- +// From sys/ioccom.h +//---------------------------------------------------------------------- + +/* QQQ keep linux's naming, but use our layout */ + +/* + * We actually have a 16 bit "base" ioctl, which may or may not be decoded + * into number/group + */ +#define _VKI_IOC_BASEBITS 16 +#define _VKI_IOC_NRBITS 8 /* "num" on freebsd */ +#define _VKI_IOC_TYPEBITS 8 /* "group" on freebsd */ + +#define _VKI_IOC_SIZEBITS 13 +#define _VKI_IOC_DIRBITS 3 + +#define _VKI_IOC_BASEMASK ((1ul << _VKI_IOC_BASEBITS)-1) +#define _VKI_IOC_NRMASK ((1ul << _VKI_IOC_NRBITS)-1) +#define _VKI_IOC_TYPEMASK ((1ul << _VKI_IOC_TYPEBITS)-1) +#define _VKI_IOC_SIZEMASK ((1ul << _VKI_IOC_SIZEBITS)-1) +#define _VKI_IOC_DIRMASK ((1ul << _VKI_IOC_DIRBITS)-1) + +#define _VKI_IOC_BASESHIFT 0 +#define _VKI_IOC_NRSHIFT 0 +#define _VKI_IOC_TYPESHIFT (_VKI_IOC_NRSHIFT+_VKI_IOC_NRBITS) +#define _VKI_IOC_SIZESHIFT (_VKI_IOC_TYPESHIFT+_VKI_IOC_TYPEBITS) +#define _VKI_IOC_DIRSHIFT (_VKI_IOC_SIZESHIFT+_VKI_IOC_SIZEBITS) + +#define _VKI_IOC_NONE 1U /* "void" on freebsd, as a specific mode */ +#define _VKI_IOC_READ 2U /* "out", copyout in reversed linux terminology */ +#define _VKI_IOC_WRITE 4U /* "in", copyin in reversed linux terminology */ +#define _VKI_IOC_RDWR 6U /* "inout", copyin and copyout */ + +#define _VKI_IOC(dir,type,nr,size) \ + (((dir) << _VKI_IOC_DIRSHIFT) | \ + ((type) << _VKI_IOC_TYPESHIFT) | \ + ((nr) << _VKI_IOC_NRSHIFT) | \ + ((size) << _VKI_IOC_SIZESHIFT)) + +/* provoke compile error for invalid uses of size argument */ +extern unsigned int __vki_invalid_size_argument_for_IOC; +#define _VKI_IOC_TYPECHECK(t) \ + ((sizeof(t) == sizeof(t[1]) && \ + sizeof(t) < (1 << _VKI_IOC_SIZEBITS)) ? \ + sizeof(t) : __vki_invalid_size_argument_for_IOC) + +/* used to create numbers */ +#define _VKI_IO(type,nr) _VKI_IOC(_VKI_IOC_NONE,(type),(nr),0) +#define _VKI_IOR(type,nr,size) _VKI_IOC(_VKI_IOC_READ,(type),(nr),(_VKI_IOC_TYPECHECK(size))) +#define _VKI_IOW(type,nr,size) _VKI_IOC(_VKI_IOC_WRITE,(type),(nr),(_VKI_IOC_TYPECHECK(size))) +#define _VKI_IOWR(type,nr,size) _VKI_IOC(_VKI_IOC_READ|_VKI_IOC_WRITE,(type),(nr),(_VKI_IOC_TYPECHECK(size))) + +/* used to decode ioctl numbers.. */ +#define _VKI_IOC_DIR(nr) (((nr) >> _VKI_IOC_DIRSHIFT) & _VKI_IOC_DIRMASK) +#define _VKI_IOC_TYPE(nr) (((nr) >> _VKI_IOC_TYPESHIFT) & _VKI_IOC_TYPEMASK) +#define _VKI_IOC_NR(nr) (((nr) >> _VKI_IOC_NRSHIFT) & _VKI_IOC_NRMASK) +#define _VKI_IOC_SIZE(nr) (((nr) >> _VKI_IOC_SIZESHIFT) & _VKI_IOC_SIZEMASK) +#define _VKI_IOC_BASE(nr) (((nr) >> _VKI_IOC_BASESHIFT) & _VKI_IOC_BASEMASK) + + +//---------------------------------------------------------------------- +// From sys/termios.h +//---------------------------------------------------------------------- + +#if 0 +#define VKI_TCGETS 0x5401 +#define VKI_TCSETS 0x5402 /* Clashes with SNDCTL_TMR_START sound ioctl */ +#define VKI_TCSETSW 0x5403 +#define VKI_TCSETSF 0x5404 +#define VKI_TCGETA 0x5405 y +#define VKI_TCSETA 0x5406 y +#define VKI_TCSETAW 0x5407 y +#define VKI_TCSETAF 0x5408 y +#define VKI_TCSBRK 0x5409 +#define VKI_TCXONC 0x540A +#define VKI_TCFLSH 0x540B y +#define VKI_TIOCSCTTY 0x540E +#define VKI_TIOCGPGRP 0x540F y +#define VKI_TIOCSPGRP 0x5410 y +#define VKI_TIOCOUTQ 0x5411 +#define VKI_TIOCGWINSZ 0x5413 y +#define VKI_TIOCSWINSZ 0x5414 y +#define VKI_TIOCMGET 0x5415 y +#define VKI_TIOCMBIS 0x5416 y +#define VKI_TIOCMBIC 0x5417 y +#define VKI_TIOCMSET 0x5418 y +#define VKI_FIONREAD 0x541B +#define VKI_TIOCLINUX 0x541C +#define VKI_FIONBIO 0x5421 +#define VKI_TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ +#define VKI_TIOCGPTN _VKI_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ +#define VKI_TIOCSPTLCK _VKI_IOW('T',0x31, int) /* Lock/unlock Pty */ + +#define VKI_FIOASYNC 0x5452 +#define VKI_TIOCSERGETLSR 0x5459 /* Get line status register */ + +#define VKI_TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ +#endif + +#define VKI_TIOCFLUSH _VKI_IOW('t', 16, int); +#define VKI_TIOCGETA _VKI_IOR('t', 19, struct vki_termios) /* get termios */ +#define VKI_TIOCSETA _VKI_IOR('t', 20, struct vki_termios) /* set termios */ +#define VKI_TIOCSETAW _VKI_IOR('t', 21, struct vki_termios) /* drain,set */ +#define VKI_TIOCSETAF _VKI_IOR('t', 22, struct vki_termios) /* flush,set */ + +#define VKI_TIOCSBRK _VKI_IO('t', 123) +#define VKI_TIOCCBRK _VKI_IO('t', 122) +#define VKI_TIOCGPGRP _VKI_IOR('t', 119, int) /* get pgrp */ +#define VKI_TIOCSPGRP _VKI_IOW('t', 118, int) /* set pgrp */ + +#define VKI_TIOCGWINSZ _VKI_IOR('t', 104, struct vki_winsize) /* get window size */ +#define VKI_TIOCSWINSZ _VKI_IOW('t', 103, struct vki_winsize) /* set window size */ + +#define VKI_TIOCMGET _VKI_IOR('t', 106, int) /* get all modem bits */ +#define VKI_TIOCMBIS _VKI_IOW('t', 108, int) /* bis modem bits */ +#define VKI_TIOCMBIC _VKI_IOW('t', 107, int) /* bic modem bits */ +#define VKI_TIOCMSET _VKI_IOW('t', 109, int) /* set all modem bits */ + + +//---------------------------------------------------------------------- +// From sys/filio.h +//---------------------------------------------------------------------- + +#define VKI_FIOCLEX _VKI_IO('f', 1) /* close on exec */ +#define VKI_FIONCLEX _VKI_IO('f', 2) /* no close on exec */ +#define VKI_FIONREAD _VKI_IOR('f', 127, int) +#define VKI_FIONBIO _VKI_IOW('f', 126, int) +#define VKI_FIOASYNC _VKI_IOW('f', 125, int) +#define VKI_FIOSETOWN _VKI_IOW('f', 124, int) +#define VKI_FIOGETOWN _VKI_IOW('f', 123, int) + +//---------------------------------------------------------------------- +// From sys/poll.h +//---------------------------------------------------------------------- + +#define VKI_POLLIN 0x0001 + +struct vki_pollfd { + int fd; + short events; + short revents; +}; + +//---------------------------------------------------------------------- +// From sys/kevent.h +//---------------------------------------------------------------------- +struct vki_kevent { + vki_uintptr_t ident; + vki_int16_t filter; + vki_uint16_t flags; + vki_uint32_t fflags; + vki_intptr_t data; + void *udata; +}; + + +// QQQ sort + +//---------------------------------------------------------------------- +// From sys/resource.h +//---------------------------------------------------------------------- + +struct vki_rusage { + struct vki_timeval ru_utime; /* user time used */ + struct vki_timeval ru_stime; /* system time used */ + long ru_maxrss; /* maximum resident set size */ + long ru_ixrss; /* integral shared memory size */ + long ru_idrss; /* integral unshared data size */ + long ru_isrss; /* integral unshared stack size */ + long ru_minflt; /* page reclaims */ + long ru_majflt; /* page faults */ + long ru_nswap; /* swaps */ + long ru_inblock; /* block input operations */ + long ru_oublock; /* block output operations */ + long ru_msgsnd; /* messages sent */ + long ru_msgrcv; /* messages received */ + long ru_nsignals; /* signals received */ + long ru_nvcsw; /* voluntary context switches */ + long ru_nivcsw; /* involuntary " */ +}; + +struct vki_rlimit { + vki_rlim_t rlim_cur; + vki_rlim_t rlim_max; +}; + +#define VKI_RLIMIT_DATA 2 /* max data size */ +#define VKI_RLIMIT_STACK 3 /* max stack size */ +#define VKI_RLIMIT_CORE 4 /* max core file size */ +#define VKI_RLIMIT_NOFILE 8 /* max number of open files */ + +//---------------------------------------------------------------------- +// From sys/procfs.h +//---------------------------------------------------------------------- + +#define VKI_PRSTATUS_VERSION 1 +struct vki_elf_prstatus +{ + int pr_version; /* version of struct - PRSTATUS_VERSION */ + vki_size_t pr_statussz; + vki_size_t pr_gregsetsz; + vki_size_t pr_fpregsetsz; + int pr_osreldate; + short pr_cursig; /* Current signal */ + vki_pid_t pr_pid; + vki_elf_gregset_t pr_reg; /* GP registers */ +}; + +#define VKI_ELF_PRARGSZ (80) /* Number of chars for args */ +#define VKI_MAXCOMLEN (16) + +#define VKI_PRPSINFO_VERSION 1 +struct vki_elf_prpsinfo +{ + int pr_version; /* version of struct - PRPSINFO_VERSION */ + vki_size_t pr_psinfosz; + char pr_fname[VKI_MAXCOMLEN+1]; /* filename of executable */ + char pr_psargs[VKI_ELF_PRARGSZ]; /* initial part of arg list */ +}; + +//---------------------------------------------------------------------- +// From posix4/mqueue.h +//---------------------------------------------------------------------- + +struct vki_mq_attr { + long mq_flags; /* message queue flags */ + long mq_maxmsg; /* maximum number of messages */ + long mq_msgsize; /* maximum message size */ + long mq_curmsgs; /* number of messages currently queued */ +}; + +//---------------------------------------------------------------------- +// From sys/ucontext.h +//---------------------------------------------------------------------- + +#define VKI_UCF_SWAPPED 1 + +struct vki_ucontext { + vki_sigset_t uc_sigmask; + struct vki_mcontext uc_mcontext; + struct vki_ucontext *uc_link; + vki_stack_t uc_stack; + int uc_flags; + unsigned int __spare__[4]; +}; + +//---------------------------------------------------------------------- +// From sys/utsname.h +//---------------------------------------------------------------------- + +#define VKI_SYS_NMLN 32 + +struct vki_utsname { + char sysname[VKI_SYS_NMLN]; /* Name of this OS. */ + char nodename[VKI_SYS_NMLN]; /* Name of this network node. */ + char release[VKI_SYS_NMLN]; /* Release level. */ + char version[VKI_SYS_NMLN]; /* Version level. */ + char machine[VKI_SYS_NMLN]; /* Hardware type. */ +}; + +#define VKI_IPC_CREAT 00001000 /* create if key is nonexistent */ +#define VKI_IPC_EXCL 00002000 /* fail if key exists */ +#define VKI_IPC_NOWAIT 00004000 /* return error on wait */ + +#define VKI_IPC_RMID 0 /* remove resource */ +#define VKI_IPC_SET 1 /* set ipc_perm options */ +#define VKI_IPC_STAT 2 /* get ipc_perm options */ +#define VKI_IPC_INFO 3 /* see ipcs */ + +struct vki_ipc_perm +{ + vki_uid_t cuid; + vki_gid_t cgid; + vki_uid_t uid; + vki_gid_t gid; + vki_mode_t mode; + unsigned short seq; + vki_key_t key; +}; + +struct vki_ipc_perm7 +{ + unsigned short cuid; + unsigned short cgid; + unsigned short uid; + unsigned short gid; + unsigned short mode; + unsigned short seq; + vki_key_t key; +}; + +//---------------------------------------------------------------------- +// From sys/sem.h +//---------------------------------------------------------------------- + +#if 0 +#define VKI_SEMOP 1 +#define VKI_SEMGET 2 +#define VKI_SEMCTL 3 +#define VKI_SEMTIMEDOP 4 +#endif + +#define VKI_GETALL 6 /* get all semval's */ +#define VKI_SETVAL 8 /* set semval */ +#define VKI_SETALL 9 /* set all semval's */ +#define VKI_SEM_STAT 10 +#define VKI_SEM_INFO 11 + +/* Obsolete, used only for backwards compatibility and libc5 compiles */ +struct vki_semid_ds { + struct vki_ipc_perm sem_perm; /* permissions .. see ipc.h */ + // [[Use void* to avoid excess header copying]] + void/*struct sem */*sem_base; /* ptr to first semaphore in array */ + unsigned short sem_nsems; /* no. of semaphores in array */ + vki_time_t sem_otime; /* last semop time */ + vki_time_t sem_ctime; /* last change time */ + long sem_pad2; + long sem_pad3[4]; +}; + +struct vki_sembuf { + vki_uint16_t sem_num; /* semaphore index in array */ + vki_int16_t sem_op; /* semaphore operation */ + vki_int16_t sem_flg; /* operation flags */ +}; + +union vki_semun { + int val; /* value for SETVAL */ + struct vki_semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */ + vki_uint16_t *array; /* array for GETALL & SETALL */ +}; + + +//---------------------------------------------------------------------- +// From sys/errno.h +//---------------------------------------------------------------------- + +#define VKI_ERESTART -1 +#define VKI_EPERM 1 /* Operation not permitted */ +#define VKI_ENOENT 2 /* No such file or directory */ +#define VKI_ESRCH 3 /* No such process */ +#define VKI_EINTR 4 /* Interrupted system call */ +#define VKI_EIO 5 /* Input/output error */ +#define VKI_ENXIO 6 /* Device not configured */ +#define VKI_E2BIG 7 /* Argument list too long */ +#define VKI_ENOEXEC 8 /* Exec format error */ +#define VKI_EBADF 9 /* Bad file descriptor */ +#define VKI_ECHILD 10 /* No child processes */ +#define VKI_EDEADLK 11 /* Resource deadlock avoided */ +#define VKI_ENOMEM 12 /* Cannot allocate memory */ +#define VKI_EACCES 13 /* Permission denied */ +#define VKI_EFAULT 14 /* Bad address */ +#define VKI_ENOTBLK 15 /* Block device required */ +#define VKI_EBUSY 16 /* Device busy */ +#define VKI_EEXIST 17 /* File exists */ +#define VKI_EXDEV 18 /* Cross-device link */ +#define VKI_ENODEV 19 /* Operation not supported by device */ +#define VKI_ENOTDIR 20 /* Not a directory */ +#define VKI_EISDIR 21 /* Is a directory */ +#define VKI_EINVAL 22 /* Invalid argument */ +#define VKI_ENFILE 23 /* Too many open files in system */ +#define VKI_EMFILE 24 /* Too many open files */ +#define VKI_ENOTTY 25 /* Inappropriate ioctl for device */ +#define VKI_ETXTBSY 26 /* Text file busy */ +#define VKI_EFBIG 27 /* File too large */ +#define VKI_ENOSPC 28 /* No space left on device */ +#define VKI_ESPIPE 29 /* Illegal seek */ +#define VKI_EROFS 30 /* Read-only filesystem */ +#define VKI_EMLINK 31 /* Too many links */ +#define VKI_EPIPE 32 /* Broken pipe */ +#define VKI_EDOM 33 /* Numerical argument out of domain */ +#define VKI_ERANGE 34 /* Result too large */ +#define VKI_EAGAIN 35 /* Resource temporarily unavailable */ +#define VKI_EWOULDBLOCK VKI_EAGAIN /* Operation would block */ +#define VKI_EINPROGRESS 36 /* Operation now in progress */ +#define VKI_EALREADY 37 /* Operation already in progress */ +#define VKI_ENOTSOCK 38 /* Socket operation on non-socket */ +#define VKI_EDESTADDRREQ 39 /* Destination address required */ +#define VKI_EMSGSIZE 40 /* Message too long */ +#define VKI_EPROTOTYPE 41 /* Protocol wrong type for socket */ +#define VKI_ENOPROTOOPT 42 /* Protocol not available */ +#define VKI_EPROTONOSUPPORT 43 /* Protocol not supported */ +#define VKI_ESOCKTNOSUPPORT 44 /* Socket type not supported */ +#define VKI_EOPNOTSUPP 45 /* Operation not supported */ +#define VKI_ENOTSUP VKI_EOPNOTSUPP /* Operation not supported */ +#define VKI_EPFNOSUPPORT 46 /* Protocol family not supported */ +#define VKI_EAFNOSUPPORT 47 /* Address family not supported by protocol family */ +#define VKI_EADDRINUSE 48 /* Address already in use */ +#define VKI_EADDRNOTAVAIL 49 +#define VKI_ENETDOWN 50 /* Network is down */ +#define VKI_ENETUNREACH 51 /* Network is unreachable */ +#define VKI_ENETRESET 52 /* Network dropped connection on reset */ +#define VKI_ECONNABORTED 53 /* Software caused connection abort */ +#define VKI_ECONNRESET 54 /* Connection reset by peer */ +#define VKI_ENOBUFS 55 /* No buffer space available */ +#define VKI_EISCONN 56 /* Socket is already connected */ +#define VKI_ENOTCONN 57 /* Socket is not connected */ +#define VKI_ESHUTDOWN 58 /* Can't send after socket shutdown */ +#define VKI_ETOOMANYREFS 59 /* Too many references: can't splice */ +#define VKI_ETIMEDOUT 60 /* Operation timed out */ +#define VKI_ECONNREFUSED 61 /* Connection refused */ +#define VKI_ELOOP 62 /* Too many levels of symbolic links */ +#define VKI_ENAMETOOLONG 63 /* File name too long */ +#define VKI_EHOSTDOWN 64 /* Host is down */ +#define VKI_EHOSTUNREACH 65 /* No route to host */ +#define VKI_ENOTEMPTY 66 /* Directory not empty */ +#define VKI_EPROCLIM 67 /* Too many processes */ +#define VKI_EUSERS 68 /* Too many users */ +#define VKI_EDQUOT 69 /* Disc quota exceeded */ +#define VKI_ESTALE 70 /* Stale NFS file handle */ +#define VKI_EREMOTE 71 /* Too many levels of remote in path */ +#define VKI_EBADRPC 72 /* RPC struct is bad */ +#define VKI_ERPCMISMATCH 73 /* RPC version wrong */ +#define VKI_EPROGUNAVAIL 74 /* RPC prog. not avail */ +#define VKI_EPROGMISMATCH 75 /* Program version wrong */ +#define VKI_EPROCUNAVAIL 76 /* Bad procedure for program */ +#define VKI_ENOLCK 77 /* No locks available */ +#define VKI_ENOSYS 78 /* Function not implemented */ +#define VKI_EFTYPE 79 /* Inappropriate file type or format */ +#define VKI_EAUTH 80 /* Authentication error */ +#define VKI_ENEEDAUTH 81 /* Need authenticator */ +#define VKI_EIDRM 82 /* Identifier removed */ +#define VKI_ENOMSG 83 /* No message of desired type */ +#define VKI_EOVERFLOW 84 /* Value too large to be stored in data type */ +#define VKI_ECANCELED 85 /* Operation canceled */ +#define VKI_EILSEQ 86 /* Illegal byte sequence */ +#define VKI_ENOATTR 87 /* Attribute not found */ +#define VKI_EDOOFUS 88 /* Programming error */ +#define VKI_EBADMSG 89 /* Bad message */ +#define VKI_EMULTIHOP 90 /* Multihop attempted */ +#define VKI_ENOLINK 91 /* Link has been severed */ +#define VKI_EPROTO 92 /* Protocol error */ +#define VKI_ENOTCAPABLE 93 /* Capabilities insufficient */ +#define VKI_ECAPMODE 94 /* Not permitted in capability mode */ + +//---------------------------------------------------------------------- +// From sys/wait.h +//---------------------------------------------------------------------- + +#define VKI_WNOHANG 0x00000001 + +//---------------------------------------------------------------------- +// From sys/mman.h +//---------------------------------------------------------------------- + +#define VKI_PROT_NONE 0x00 /* No page permissions */ +#define VKI_PROT_READ 0x01 /* page can be read */ +#define VKI_PROT_WRITE 0x02 /* page can be written */ +#define VKI_PROT_EXEC 0x04 /* page can be executed */ + +#define VKI_MAP_SHARED 0x01 /* Share changes */ +#define VKI_MAP_PRIVATE 0x02 /* Changes are private */ +#define VKI_MAP_FIXED 0x10 /* Interpret addr exactly */ +#define VKI_MAP_NORESERVE 0x0040 /* don't check for reservations */ +#define VKI_MAP_STACK 0x400 +#define VKI_MAP_ANON 0x1000 /* don't use a file */ +#define VKI_MAP_ANONYMOUS VKI_MAP_ANON + +//---------------------------------------------------------------------- +// From sys/stat.h +//---------------------------------------------------------------------- + +#define VKI_S_IFMT 00170000 + +#define VKI_S_IFWHT 0160000 +#define VKI_S_IFSOCK 0140000 +#define VKI_S_IFLNK 0120000 +#define VKI_S_IFREG 0100000 +#define VKI_S_IFBLK 0060000 +#define VKI_S_IFDIR 0040000 +#define VKI_S_IFCHR 0020000 +#define VKI_S_IFIFO 0010000 +#define VKI_S_ISUID 0004000 +#define VKI_S_ISGID 0002000 +#define VKI_S_ISTXT 0001000 + +#define VKI_S_ISLNK(m) (((m) & VKI_S_IFMT) == VKI_S_IFLNK) +#define VKI_S_ISREG(m) (((m) & VKI_S_IFMT) == VKI_S_IFREG) +#define VKI_S_ISDIR(m) (((m) & VKI_S_IFMT) == VKI_S_IFDIR) +#define VKI_S_ISCHR(m) (((m) & VKI_S_IFMT) == VKI_S_IFCHR) +#define VKI_S_ISBLK(m) (((m) & VKI_S_IFMT) == VKI_S_IFBLK) +#define VKI_S_ISFIFO(m) (((m) & VKI_S_IFMT) == VKI_S_IFIFO) +#define VKI_S_ISSOCK(m) (((m) & VKI_S_IFMT) == VKI_S_IFSOCK) +#define VKI_S_ISWHT(m) (((m) & VKI_S_IFMT) == VKI_S_IFWHT) + +#define VKI_S_IRWXU 00700 +#define VKI_S_IRUSR 00400 +#define VKI_S_IWUSR 00200 +#define VKI_S_IXUSR 00100 + +#define VKI_S_IRWXG 00070 +#define VKI_S_IRGRP 00040 +#define VKI_S_IWGRP 00020 +#define VKI_S_IXGRP 00010 + +#define VKI_S_IRWXO 00007 +#define VKI_S_IROTH 00004 +#define VKI_S_IWOTH 00002 +#define VKI_S_IXOTH 00001 + + +//---------------------------------------------------------------------- +// From sys/dirent.h +//---------------------------------------------------------------------- + +struct vki_dirent { + vki_uint32_t d_fileno; + vki_uint16_t d_reclen; + vki_uint8_t d_type; + vki_uint8_t d_namelen; + char d_name[256]; /* We must not include limits.h! */ +}; + +//---------------------------------------------------------------------- +// From sys/fcntl.h +//---------------------------------------------------------------------- + +#define VKI_O_RDONLY 0x0000 +#define VKI_O_WRONLY 0x0001 +#define VKI_O_RDWR 0x0002 + +#define VKI_O_NONBLOCK 0x0004 +#define VKI_O_APPEND 0x0008 +#define VKI_O_CREAT 0x0200 /* not fcntl */ +#define VKI_O_TRUNC 0x0400 /* not fcntl */ +#define VKI_O_EXCL 0x0800 /* not fcntl */ + +#define VKI_AT_FDCWD -100 + +#define VKI_F_DUPFD 0 /* dup */ +#define VKI_F_GETFD 1 /* get close_on_exec */ +#define VKI_F_SETFD 2 /* set/clear close_on_exec */ +#define VKI_F_GETFL 3 /* get file->f_flags */ +#define VKI_F_SETFL 4 /* set file->f_flags */ +#define VKI_F_SETOWN 5 /* for sockets. */ +#define VKI_F_GETOWN 6 /* for sockets. */ +#define VKI_F_OGETLK 7 /* get record locking information */ +#define VKI_F_OSETLK 8 /* set record locking information */ +#define VKI_F_OSETLKW 9 /* F_SETLK; wait if blocked */ +#define VKI_F_DUP2FD 10 /* duplicate file descriptor to arg */ +#define VKI_F_GETLK 11 /* get record locking information */ +#define VKI_F_SETLK 12 /* set record locking information */ +#define VKI_F_SETLKW 13 /* F_SETLK; wait if blocked */ +#define VKI_F_SETLK_REMOTE 14 /* debugging support for remote locks */ + +/* for F_[GET|SET]FL */ +#define VKI_FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +//---------------------------------------------------------------------- +// From sys/unistd.h +//---------------------------------------------------------------------- + +#define VKI_SEEK_SET 0 +#define VKI_SEEK_CUR 1 +#define VKI_SEEK_END 2 + +#define VKI_F_OK 0 /* test for existence of file */ +#define VKI_X_OK 0x01 /* test for execute or search permission */ +#define VKI_W_OK 0x02 /* test for write permission */ +#define VKI_R_OK 0x04 /* test for read permission */ + +//---------------------------------------------------------------------- +// From sys/msg.h +//---------------------------------------------------------------------- + +#if 0 /* not in freebsd */ +#define VKI_MSGSND 11 +#define VKI_MSGRCV 12 +#define VKI_MSGGET 13 +#define VKI_MSGCTL 14 +#endif + +struct vki_msqid_ds { + struct vki_ipc_perm msg_perm; + struct vki_msg *msg_first; /* first message on queue,unused */ + struct vki_msg *msg_last; /* last message in queue,unused */ + vki_uint32_t msg_cbytes; /* current number of bytes on queue */ + vki_uint32_t msg_qnum; /* number of messages in queue */ + vki_uint32_t msg_qbytes; /* max number of bytes on queue */ + vki_pid_t msg_lspid; /* pid of last msgsnd */ + vki_pid_t msg_lrpid; /* last receive pid */ + vki_time_t msg_stime; /* last msgsnd time */ + vki_uint32_t msg_pad1; + vki_time_t msg_rtime; /* last msgrcv time */ + vki_uint32_t msg_pad2; + vki_time_t msg_ctime; /* last change time */ + vki_uint32_t msg_pad3; + vki_uint32_t msg_pad4[4]; +}; + +struct vki_msgbuf { + long mtype; /* type of message */ + char mtext[1]; /* message text */ +}; + + +//---------------------------------------------------------------------- +// From sys/shm.h +//---------------------------------------------------------------------- + +struct vki_shmid_ds { + struct vki_ipc_perm shm_perm; /* operation perms */ + vki_size_t shm_segsz; /* size of segment (bytes) */ + vki_pid_t shm_lpid; /* pid of last operator */ + vki_pid_t shm_cpid; /* pid of creator */ + int shm_nattch; /* no. of current attaches */ + vki_time_t shm_atime; /* last attach time */ + vki_time_t shm_dtime; /* last detach time */ + vki_time_t shm_ctime; /* last change time */ +}; + +struct vki_shmid_ds7 { + struct vki_ipc_perm7 shm_perm; /* operation perms */ + int shm_segsz; /* size of segment (bytes) */ + vki_pid_t shm_lpid; /* pid of last operator */ + vki_pid_t shm_cpid; /* pid of creator */ + short shm_nattch; /* no. of current attaches */ + vki_time_t shm_atime; /* last attach time */ + vki_time_t shm_dtime; /* last detach time */ + vki_time_t shm_ctime; /* last change time */ + void *shm_internal; /* sysv stupidity */ +}; + +#define VKI_SHMLBA VKI_PAGE_SIZE +#define VKI_SHM_RDONLY 010000 /* read-only access */ +#define VKI_SHM_ANON (1UL) + +#if 0 /* not in freebsd abi */ +#define VKI_SHMAT 21 +#define VKI_SHMDT 22 +#define VKI_SHMGET 23 +#define VKI_SHMCTL 24 +#endif + +#if 0 +//---------------------------------------------------------------------- +// From linux-2.6.8.1/include/linux/sockios.h +//---------------------------------------------------------------------- + +#define VKI_SIOCOUTQ VKI_TIOCOUTQ + +#define VKI_SIOCADDRT 0x890B /* add routing table entry */ +#define VKI_SIOCDELRT 0x890C /* delete routing table entry */ + +#define VKI_SIOCGIFNAME 0x8910 /* get iface name */ +#define VKI_SIOCGIFCONF 0x8912 /* get iface list */ +#define VKI_SIOCGIFFLAGS 0x8913 /* get flags */ +#define VKI_SIOCSIFFLAGS 0x8914 /* set flags */ +#define VKI_SIOCGIFADDR 0x8915 /* get PA address */ +#define VKI_SIOCSIFADDR 0x8916 /* set PA address */ +#define VKI_SIOCGIFDSTADDR 0x8917 /* get remote PA address */ +#define VKI_SIOCSIFDSTADDR 0x8918 /* set remote PA address */ +#define VKI_SIOCGIFBRDADDR 0x8919 /* get broadcast PA address */ +#define VKI_SIOCSIFBRDADDR 0x891a /* set broadcast PA address */ +#define VKI_SIOCGIFNETMASK 0x891b /* get network PA mask */ +#define VKI_SIOCSIFNETMASK 0x891c /* set network PA mask */ +#define VKI_SIOCGIFMETRIC 0x891d /* get metric */ +#define VKI_SIOCSIFMETRIC 0x891e /* set metric */ +#define VKI_SIOCGIFMTU 0x8921 /* get MTU size */ +#define VKI_SIOCSIFMTU 0x8922 /* set MTU size */ +#define VKI_SIOCSIFHWADDR 0x8924 /* set hardware address */ +#define VKI_SIOCGIFHWADDR 0x8927 /* Get hardware address */ +#define VKI_SIOCGIFINDEX 0x8933 /* name -> if_index mapping */ + +#define VKI_SIOCGIFTXQLEN 0x8942 /* Get the tx queue length */ +#define VKI_SIOCSIFTXQLEN 0x8943 /* Set the tx queue length */ + +#define VKI_SIOCGMIIPHY 0x8947 /* Get address of MII PHY in use. */ +#define VKI_SIOCGMIIREG 0x8948 /* Read MII PHY register. */ +#define VKI_SIOCSMIIREG 0x8949 /* Write MII PHY register. */ + +#define VKI_SIOCDARP 0x8953 /* delete ARP table entry */ +#define VKI_SIOCGARP 0x8954 /* get ARP table entry */ +#define VKI_SIOCSARP 0x8955 /* set ARP table entry */ + +#define VKI_SIOCDRARP 0x8960 /* delete RARP table entry */ +#define VKI_SIOCGRARP 0x8961 /* get RARP table entry */ +#define VKI_SIOCSRARP 0x8962 /* set RARP table entry */ + +#define VKI_SIOCGIFMAP 0x8970 /* Get device parameters */ +#define VKI_SIOCSIFMAP 0x8971 /* Set device parameters */ + +//---------------------------------------------------------------------- +// From linux-2.6.9/include/linux/kb.h +//---------------------------------------------------------------------- + +#define VKI_GIO_FONT 0x4B60 /* gets font in expanded form */ +#define VKI_PIO_FONT 0x4B61 /* use font in expanded form */ + +#define VKI_GIO_FONTX 0x4B6B /* get font using struct consolefontdesc */ +#define VKI_PIO_FONTX 0x4B6C /* set font using struct consolefontdesc */ +struct vki_consolefontdesc { + unsigned short charcount; /* characters in font (256 or 512) */ + unsigned short charheight; /* scan lines per character (1-32) */ + char __user *chardata; /* font data in expanded form */ +}; + +#define VKI_PIO_FONTRESET 0x4B6D /* reset to default font */ + +#define VKI_GIO_CMAP 0x4B70 /* gets colour palette on VGA+ */ +#define VKI_PIO_CMAP 0x4B71 /* sets colour palette on VGA+ */ + +#define VKI_KIOCSOUND 0x4B2F /* start sound generation (0 for off) */ +#define VKI_KDMKTONE 0x4B30 /* generate tone */ + +#define VKI_KDGETLED 0x4B31 /* return current led state */ +#define VKI_KDSETLED 0x4B32 /* set led state [lights, not flags] */ + +#define VKI_KDGKBTYPE 0x4B33 /* get keyboard type */ + +#define VKI_KDADDIO 0x4B34 /* add i/o port as valid */ +#define VKI_KDDELIO 0x4B35 /* del i/o port as valid */ +#define VKI_KDENABIO 0x4B36 /* enable i/o to video board */ +#define VKI_KDDISABIO 0x4B37 /* disable i/o to video board */ + +#define VKI_KDSETMODE 0x4B3A /* set text/graphics mode */ +#define VKI_KDGETMODE 0x4B3B /* get current mode */ + +#define VKI_KDMAPDISP 0x4B3C /* map display into address space */ +#define VKI_KDUNMAPDISP 0x4B3D /* unmap display from address space */ + +#define VKI_E_TABSZ 256 +#define VKI_GIO_SCRNMAP 0x4B40 /* get screen mapping from kernel */ +#define VKI_PIO_SCRNMAP 0x4B41 /* put screen mapping table in kernel */ +#define VKI_GIO_UNISCRNMAP 0x4B69 /* get full Unicode screen mapping */ +#define VKI_PIO_UNISCRNMAP 0x4B6A /* set full Unicode screen mapping */ + +#define VKI_GIO_UNIMAP 0x4B66 /* get unicode-to-font mapping from kernel */ +#define VKI_PIO_UNIMAP 0x4B67 /* put unicode-to-font mapping in kernel */ +#define VKI_PIO_UNIMAPCLR 0x4B68 /* clear table, possibly advise hash algorithm */ + +#define VKI_KDGKBMODE 0x4B44 /* gets current keyboard mode */ +#define VKI_KDSKBMODE 0x4B45 /* sets current keyboard mode */ + +#define VKI_KDGKBMETA 0x4B62 /* gets meta key handling mode */ +#define VKI_KDSKBMETA 0x4B63 /* sets meta key handling mode */ + +#define VKI_KDGKBLED 0x4B64 /* get led flags (not lights) */ +#define VKI_KDSKBLED 0x4B65 /* set led flags (not lights) */ + +struct vki_kbentry { + unsigned char kb_table; + unsigned char kb_index; + unsigned short kb_value; +}; +#define VKI_KDGKBENT 0x4B46 /* gets one entry in translation table */ +#define VKI_KDSKBENT 0x4B47 /* sets one entry in translation table */ + +struct vki_kbsentry { + unsigned char kb_func; + unsigned char kb_string[512]; +}; +#define VKI_KDGKBSENT 0x4B48 /* gets one function key string entry */ +#define VKI_KDSKBSENT 0x4B49 /* sets one function key string entry */ + +struct vki_kbdiacr { + unsigned char diacr, base, result; +}; +struct vki_kbdiacrs { + unsigned int kb_cnt; /* number of entries in following array */ + struct vki_kbdiacr kbdiacr[256]; /* MAX_DIACR from keyboard.h */ +}; +#define VKI_KDGKBDIACR 0x4B4A /* read kernel accent table */ +#define VKI_KDSKBDIACR 0x4B4B /* write kernel accent table */ + +struct vki_kbkeycode { + unsigned int scancode, keycode; +}; +#define VKI_KDGETKEYCODE 0x4B4C /* read kernel keycode table entry */ +#define VKI_KDSETKEYCODE 0x4B4D /* write kernel keycode table entry */ + +#define VKI_KDSIGACCEPT 0x4B4E /* accept kbd generated signals */ + +struct vki_kbd_repeat { + int delay; /* in msec; <= 0: don't change */ + int period; /* in msec; <= 0: don't change */ + /* earlier this field was misnamed "rate" */ +}; +#define VKI_KDKBDREP 0x4B52 /* set keyboard delay/repeat rate; + * actually used values are returned */ + +#define VKI_KDFONTOP 0x4B72 /* font operations */ + +//---------------------------------------------------------------------- +// From linux-2.6.9/include/linux/kb.h +//---------------------------------------------------------------------- + +typedef __vki_kernel_uid32_t vki_qid_t; /* Type in which we store ids in memory */ + +#endif + +//---------------------------------------------------------------------- +// From sys/ptrace.h +//---------------------------------------------------------------------- + +#define VKI_PTRACE_TRACEME 0 +#define VKI_PTRACE_READ_I 1 +#define VKI_PTRACE_READ_D 2 +/* 3 - read user struct */ +#define VKI_PTRACE_WRITE_I 4 +#define VKI_PTRACE_WRITE_D 5 +/* 6 - write user struct */ +#define VKI_PTRACE_CONTINUE 7 +#define VKI_PTRACE_KILL 8 +#define VKI_PTRACE_STEP 9 +#define VKI_PTRACE_ATTACH 10 +#define VKI_PTRACE_DETACH 11 +#define VKI_PTRACE_IO 12 +#define VKI_PTRACE_LWPINFO 13 +#define VKI_PTRACE_GETNUMLWPS 14 +#define VKI_PTRACE_GETLWPLIST 15 +#define VKI_PTRACE_CLEARSTEP 16 +#define VKI_PTRACE_SETSTEP 17 +#define VKI_PTRACE_SUSPEND 18 +#define VKI_PTRACE_RESUME 19 +#define VKI_PTRACE_TO_SCE 20 +#define VKI_PTRACE_TO_SCX 21 +#define VKI_PTRACE_SYSCALL 22 +/* md */ +#define VKI_PTRACE_GETREGS 33 +#define VKI_PTRACE_SETREGS 34 +#define VKI_PTRACE_GETFPREGS 35 +#define VKI_PTRACE_SETFPREGS 36 +#define VKI_PTRACE_GETDBREGS 37 +#define VKI_PTRACE_SETDBREGS 38 + +#define VKI_PTRACE_VM_TIMESTAMP 40 +#define VKI_PTRACE_VM_ENTRY 41 + +#define VKI_PTRACE_FIRSTMACH 64 + +struct vki_ptrace_io_desc { + int piod_op; + void * piod_offs; + void * piod_addr; + vki_size_t piod_len; +}; +#define VKI_PIOD_READ_D 1 +#define VKI_PIOD_WRITE_D 2 +#define VKI_PIOD_READ_I 3 +#define VKI_PIOD_WRITE_I 4 + +struct vki_ptrace_lwpinfo { + vki_lwpid_t pl_lwpid; + int pl_event; +#define VKI_PL_EVENT_NONE 0 +#define VKI_PL_EVENT_SIGNAL 1 + int pl_flags; +#define VKI_FLAG_SA 0x01 +#define VKI_FLAG_BOUND 0x02 + vki_sigset_t pl_sigmask; + vki_sigset_t pl_siglist; +}; + +struct vki_ptrace_vm_entry { + int pve_entry; /* Entry number used for iteration. */ + int pve_timestamp; /* Generation number of VM map. */ + unsigned long pve_start; /* Start VA of range. */ + unsigned long pve_end; /* End VA of range (incl). */ + unsigned long pve_offset; /* Offset in backing object. */ + unsigned int pve_prot; /* Protection of memory range. */ + unsigned int pve_pathlen; /* Size of path. */ + long pve_fileid; /* File ID. */ + vki_uint32_t pve_fsid; /* File system ID. */ + char *pve_path; /* Path name of object. */ +}; + +#endif // __VKI_OPENBSD_H + +//---------------------------------------------------------------------- +// From i386/include/sysarch.h and amd64/include/sysarch.h (interchangeable) +//---------------------------------------------------------------------- + +#define VKI_I386_GET_FSBASE 7 +#define VKI_I386_SET_FSBASE 8 +#define VKI_I386_GET_GSBASE 9 +#define VKI_I386_SET_GSBASE 10 + +#define VKI_AMD64_GET_FSBASE 128 +#define VKI_AMD64_SET_FSBASE 129 +#define VKI_AMD64_GET_GSBASE 130 +#define VKI_AMD64_SET_GSBASE 131 + +//---------------------------------------------------------------------- +// From sys/module.h +//---------------------------------------------------------------------- + +#define VKI_MAXMODNAME 32 + +typedef union vki_modspecific { + vki_int32_t intval; + vki_uint32_t u_intval; +#if defined(VGP_x86_openbsd) + vki_int32_t longval; + vki_uint32_t u_longval; +#elif defined(VGP_amd64_openbsd) + vki_int64_t longval; + vki_uint64_t u_longval; +#else +#error Unknown platform +#endif +} vki_modspecific_t; + +struct vki_module_stat { + int version; + char name[VKI_MAXMODNAME]; + int refs; + int id; + vki_modspecific_t data; +}; + +//---------------------------------------------------------------------- +// From sys/rtprio.h +//---------------------------------------------------------------------- + +struct vki_rtprio { + vki_uint16_t type; + vki_uint16_t prio; +}; + +#define VKI_RTP_LOOKUP 0 +#define VKI_RTP_SET 1 + +//---------------------------------------------------------------------- +// From sys/umtx.h +//---------------------------------------------------------------------- + +struct vki_umtx { + unsigned long u_owner; +}; + +struct vki_umutex { + vki_lwpid_t m_owner; + vki_uint32_t m_flags; + vki_uint32_t m_ceilings[2]; + vki_uint32_t m_spare[4]; +}; + +struct vki_ucond { + vki_uint32_t c_has_waiters; + vki_uint32_t c_flags; + vki_uint32_t c_spare[2]; +}; + +struct vki_urwlock { + vki_uint32_t rw_state; + vki_uint32_t rw_flags; + vki_uint32_t rw_blocked_readers; + vki_uint32_t rw_blocked_writers; + vki_uint32_t rw_spare[4]; +}; + +struct vki_usem { + vki_uint32_t has_waiters; + vki_uint32_t count; + vki_uint32_t flags; +}; + +struct vki_umtx_time { + struct vki_timespec timeout; + vki_uint32_t flags; + vki_uint32_t clockid; +}; + +#define VKI_UMTX_OP_LOCK 0 +#define VKI_UMTX_OP_UNLOCK 1 +#define VKI_UMTX_OP_WAIT 2 +#define VKI_UMTX_OP_WAKE 3 +#define VKI_UMTX_OP_MUTEX_TRYLOCK 4 +#define VKI_UMTX_OP_MUTEX_LOCK 5 +#define VKI_UMTX_OP_MUTEX_UNLOCK 6 +#define VKI_UMTX_OP_SET_CEILING 7 +#define VKI_UMTX_OP_CV_WAIT 8 +#define VKI_UMTX_OP_CV_SIGNAL 9 +#define VKI_UMTX_OP_CV_BROADCAST 10 +#define VKI_UMTX_OP_WAIT_UINT 11 +#define VKI_UMTX_OP_RW_RDLOCK 12 +#define VKI_UMTX_OP_RW_WRLOCK 13 +#define VKI_UMTX_OP_RW_UNLOCK 14 +#define VKI_UMTX_OP_WAIT_UINT_PRIVATE 15 +#define VKI_UMTX_OP_WAKE_PRIVATE 16 +#define VKI_UMTX_OP_MUTEX_WAIT 17 +#define VKI_UMTX_OP_MUTEX_WAKE 18 /* deprecated */ +#define VKI_UMTX_OP_SEM_WAIT 19 +#define VKI_UMTX_OP_SEM_WAKE 20 +#define VKI_UMTX_OP_NWAKE_PRIVATE 21 +#define VKI_UMTX_OP_MUTEX_WAKE2 22 +#define VKI_UMTX_OP_MAX 23 + + +//---------------------------------------------------------------------- +// From sys/acl.h +//---------------------------------------------------------------------- + +struct vki_acl_entry { + int ae_tag; + vki_uid_t ae_uid; + vki_mode_t ae_perm; +}; + +#define VKI_ACL_MAX_ENTRIES 32 +struct vki_acl { + int acl_cnt; + struct vki_acl_entry acl_entry[VKI_ACL_MAX_ENTRIES]; +}; + + +//---------------------------------------------------------------------- +// From sys/uuid.h +//---------------------------------------------------------------------- + +struct vki_uuid { + vki_uint32_t time_low; + vki_uint16_t time_mid; + vki_uint16_t time_hi_and_version; + vki_uint8_t clock_seq_hi_and_reserved; + vki_uint8_t clock_seq_low; + vki_uint8_t node[6]; +}; + +//---------------------------------------------------------------------- +// From sys/user.h +//---------------------------------------------------------------------- + +#define VKI_KVE_ET_OBJ 0x00000001 +#define VKI_KVE_ET_SUBMAP 0x00000002 +#define VKI_KVE_ET_COPYONWRITE 0x00000004 +#define VKI_KVE_ET_NEEDSCOPY 0x00000008 +#define VKI_KVE_ET_HOLE 0x00000010 +#define VKI_KVE_ET_NOFAULT 0x00000020 +#define VKI_KVE_ET_FREEMAPPED 0x00000080 +#define VKI_KVE_PROT_READ 0x00000001 +#define VKI_KVE_PROT_WRITE 0x00000002 +#define VKI_KVE_PROT_EXEC 0x00000004 +#define VKI_KVE_ADV_NORMAL 0x00000000 +#define VKI_KVE_ADV_RANDOM 0x00000001 +#define VKI_KVE_ADV_SEQUENTIAL 0x00000002 +#define VKI_KVE_INH_SHARE 0x00000000 +#define VKI_KVE_INH_COPY 0x00000010 +#define VKI_KVE_INH_NONE 0x00000020 +#define VKI_KVE_INH_ZERO 0x00000030 +#define VKI_KVE_F_STATIC 0x01 +#define VKI_KVE_F_KMEM 0x02 + +struct vki_kinfo_vmentry { + unsigned long vki_kve_start; + unsigned long vki_kve_end; + unsigned long vki_kve_guard; + unsigned long vki_kve_fspace; + unsigned long vki_kve_fspace_augment; + u_int64_t vki_kve_offset; + int vki_kve_wired_count; + int vki_kve_etype; + int vki_kve_protection; + int vki_kve_max_protection; + int vki_kve_advice; + int vki_kve_inheritance; + u_int8_t vki_kve_flags; +}; + +struct vki_kinfo_file { + int kf_structsize; /* Variable size of record. */ + int kf_type; /* Descriptor type. */ + int kf_fd; /* Array index. */ + int kf_ref_count; /* Reference count. */ + int kf_flags; /* Flags. */ + int _kf_pad0; /* Round to 64 bit alignment */ + Off64T kf_offset; /* Seek location. */ + int kf_vnode_type; /* Vnode type. */ + int kf_sock_domain; /* Socket domain. */ + int kf_sock_type; /* Socket type. */ + int kf_sock_protocol; /* Socket protocol. */ + char kf_sa_local[128]; /* Socket address. */ + char kf_sa_peer[128]; /* Peer address. */ + int _kf_ispare[16]; /* Space for more stuff. */ + /* Truncated before copyout in sysctl */ + char kf_path[VKI_PATH_MAX]; /* Path to file, if any. */ +}; + +//---------------------------------------------------------------------- +// From sys/kenv.h +//---------------------------------------------------------------------- +#define VKI_KENV_GET 0 +#define VKI_KENV_SET 1 +#define VKI_KENV_UNSET 2 +#define VKI_KENV_DUMP 3 + +//---------------------------------------------------------------------- +// From sys/sysctl.h (and related) +//---------------------------------------------------------------------- + +#include +#include + +#define VKI_CTL_KERN CTL_KERN +#define VKI_CTL_HW CTL_HW +#define VKI_KERN_PROC KERN_PROC +#define VKI_KERN_PROC_VMMAP KERN_PROC_VMMAP +#define VKI_KERN_PROC_FILEDESC KERN_PROC_FILEDESC +#define VKI_HW_MACHINE HW_MACHINE + +//---------------------------------------------------------------------- +// From sys/thr.h +//---------------------------------------------------------------------- + +struct vki_thr_param { + void (*start_func)(void *); + void *arg; + char *stack_base; + vki_size_t stack_size; + char *tls_base; + vki_size_t tls_size; + long *child_tid; + long *parent_tid; + int flags; + struct vki_rtprio *rtp; + void *spare[3]; +}; + +//---------------------------------------------------------------------- +// From kvm.h +//---------------------------------------------------------------------- + +struct vki___kvm; +typedef struct vki___kvm vki_kvm_t; + +#define int32_t vki_int32_t +#define int64_t vki_int64_t +#define u_int32_t vki_uint32_t +#define u_int64_t vki_uint64_t + +struct vki_kinfo_proc { + u_int64_t p_forw; /* PTR: linked run/sleep queue. */ + u_int64_t p_back; + u_int64_t p_paddr; /* PTR: address of proc */ + + u_int64_t p_addr; /* PTR: Kernel virtual addr of u-area */ + u_int64_t p_fd; /* PTR: Ptr to open files structure. */ + u_int64_t p_stats; /* unused, always zero. */ + u_int64_t p_limit; /* PTR: Process limits. */ + u_int64_t p_vmspace; /* PTR: Address space. */ + u_int64_t p_sigacts; /* PTR: Signal actions, state */ + u_int64_t p_sess; /* PTR: session pointer */ + u_int64_t p_tsess; /* PTR: tty session pointer */ + u_int64_t p_ru; /* PTR: Exit information. XXX */ + + int32_t p_eflag; /* LONG: extra kinfo_proc flags */ +#define EPROC_CTTY 0x01 /* controlling tty vnode active */ +#define EPROC_SLEADER 0x02 /* session leader */ + int32_t p_exitsig; /* unused, always zero. */ + int32_t p_flag; /* INT: P_* flags. */ + + int32_t p_pid; /* PID_T: Process identifier. */ + int32_t p_ppid; /* PID_T: Parent process id */ + int32_t p_sid; /* PID_T: session id */ + int32_t p__pgid; /* PID_T: process group id */ + /* XXX: hijacks p_pgid */ + int32_t p_tpgid; /* PID_T: tty process group id */ + + u_int32_t p_uid; /* UID_T: effective user id */ + u_int32_t p_ruid; /* UID_T: real user id */ + u_int32_t p_gid; /* GID_T: effective group id */ + u_int32_t p_rgid; /* GID_T: real group id */ + + u_int32_t p_groups[KI_NGROUPS]; /* GID_T: groups */ + int16_t p_ngroups; /* SHORT: number of groups */ + + int16_t p_jobc; /* SHORT: job control counter */ + u_int32_t p_tdev; /* DEV_T: controlling tty dev */ + + u_int32_t p_estcpu; /* U_INT: Time averaged value of p_cpticks. */ + u_int32_t p_rtime_sec; /* STRUCT TIMEVAL: Real time. */ + u_int32_t p_rtime_usec; /* STRUCT TIMEVAL: Real time. */ + int32_t p_cpticks; /* INT: Ticks of cpu time. */ + u_int32_t p_pctcpu; /* FIXPT_T: %cpu for this process */ + u_int32_t p_swtime; /* unused, always zero */ + u_int32_t p_slptime; /* U_INT: Time since last blocked. */ + int32_t p_schedflags; /* INT: PSCHED_* flags */ + + u_int64_t p_uticks; /* U_QUAD_T: Statclock hits in user mode. */ + u_int64_t p_sticks; /* U_QUAD_T: Statclock hits in system mode. */ + u_int64_t p_iticks; /* U_QUAD_T: Statclock hits processing intr. */ + + u_int64_t p_tracep; /* PTR: Trace to vnode or file */ + int32_t p_traceflag; /* INT: Kernel trace points. */ + + int32_t p_holdcnt; /* INT: If non-zero, don't swap. */ + + int32_t p_siglist; /* INT: Signals arrived but not delivered. */ + u_int32_t p_sigmask; /* SIGSET_T: Current signal mask. */ + u_int32_t p_sigignore; /* SIGSET_T: Signals being ignored. */ + u_int32_t p_sigcatch; /* SIGSET_T: Signals being caught by user. */ + + int8_t p_stat; /* CHAR: S* process status (from LWP). */ + u_int8_t p_priority; /* U_CHAR: Process priority. */ + u_int8_t p_usrpri; /* U_CHAR: User-priority based on p_cpu and ps_nice. */ + u_int8_t p_nice; /* U_CHAR: Process "nice" value. */ + + u_int16_t p_xstat; /* U_SHORT: Exit status for wait; also stop signal. */ + u_int16_t p_acflag; /* U_SHORT: Accounting flags. */ + + char p_comm[KI_MAXCOMLEN]; + + char p_wmesg[KI_WMESGLEN]; /* wchan message */ + u_int64_t p_wchan; /* PTR: sleep address. */ + + char p_login[KI_MAXLOGNAME]; /* setlogin() name */ + + int32_t p_vm_rssize; /* SEGSZ_T: current resident set size in pages */ + int32_t p_vm_tsize; /* SEGSZ_T: text size (pages) */ + int32_t p_vm_dsize; /* SEGSZ_T: data size (pages) */ + int32_t p_vm_ssize; /* SEGSZ_T: stack size (pages) */ + + int64_t p_uvalid; /* CHAR: following p_u* members from struct user are valid */ + /* XXX 64 bits for alignment */ + u_int64_t p_ustart_sec; /* STRUCT TIMEVAL: starting time. */ + u_int32_t p_ustart_usec; /* STRUCT TIMEVAL: starting time. */ + + u_int32_t p_uutime_sec; /* STRUCT TIMEVAL: user time. */ + u_int32_t p_uutime_usec; /* STRUCT TIMEVAL: user time. */ + u_int32_t p_ustime_sec; /* STRUCT TIMEVAL: system time. */ + u_int32_t p_ustime_usec; /* STRUCT TIMEVAL: system time. */ + + u_int64_t p_uru_maxrss; /* LONG: max resident set size. */ + u_int64_t p_uru_ixrss; /* LONG: integral shared memory size. */ + u_int64_t p_uru_idrss; /* LONG: integral unshared data ". */ + u_int64_t p_uru_isrss; /* LONG: integral unshared stack ". */ + u_int64_t p_uru_minflt; /* LONG: page reclaims. */ + u_int64_t p_uru_majflt; /* LONG: page faults. */ + u_int64_t p_uru_nswap; /* LONG: swaps. */ + u_int64_t p_uru_inblock; /* LONG: block input operations. */ + u_int64_t p_uru_oublock; /* LONG: block output operations. */ + u_int64_t p_uru_msgsnd; /* LONG: messages sent. */ + u_int64_t p_uru_msgrcv; /* LONG: messages received. */ + u_int64_t p_uru_nsignals; /* LONG: signals received. */ + u_int64_t p_uru_nvcsw; /* LONG: voluntary context switches. */ + u_int64_t p_uru_nivcsw; /* LONG: involuntary ". */ + + u_int32_t p_uctime_sec; /* STRUCT TIMEVAL: child u+s time. */ + u_int32_t p_uctime_usec; /* STRUCT TIMEVAL: child u+s time. */ + int32_t p_psflags; /* INT: PS_* flags on the process. */ + int32_t p_spare; /* INT: unused. */ + u_int32_t p_svuid; /* UID_T: saved user id */ + u_int32_t p_svgid; /* GID_T: saved group id */ + char p_emul[KI_EMULNAMELEN]; /* syscall emulation name */ + u_int64_t p_rlim_rss_cur; /* RLIM_T: soft limit for rss */ + u_int64_t p_cpuid; /* LONG: CPU id */ + u_int64_t p_vm_map_size; /* VSIZE_T: virtual size */ + int32_t p_tid; /* PID_T: Thread identifier. */ + u_int32_t p_rtableid; /* U_INT: Routing table identifier. */ +}; + +//---------------------------------------------------------------------- +// From nlist.h +//---------------------------------------------------------------------- + +struct vki_nlist { + char *n_name; + unsigned char n_type; + char n_other; + short n_desc; + unsigned long n_value; +}; + +#define N_UNDF 0x00 +#define N_ABS 0x02 +#define N_TEXT 0x04 +#define N_DATA 0x06 +#define N_BSS 0x08 +#define N_INDR 0x0a +#define N_SIZE 0x0c +#define N_COMM 0x12 +#define N_FN 0x1e +#define N_WARN 0x1e + +#define N_EXT 0x01 +#define N_TYPE 0x1e + + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 include/vki/vki-scnums-freebsd.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/vki/vki-scnums-freebsd.h Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,413 @@ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2005 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#ifndef __VKI_UNISTD_FREEBSD_H +#define __VKI_UNISTD_FREEBSD_H + +#define VG_FREEBSD_SYSCALL_STD 0 +#define VG_FREEBSD_SYSCALL0 1 +#define VG_FREEBSD_SYSCALL198 2 + +// From sys/syscall.h + +#define __NR_syscall 0 +#define __NR_exit 1 +#define __NR_fork 2 +#define __NR_read 3 +#define __NR_write 4 +#define __NR_open 5 +#define __NR_close 6 +#define __NR_wait4 7 +#define __NR_link 9 +#define __NR_unlink 10 +#define __NR_chdir 12 +#define __NR_fchdir 13 +#define __NR_mknod 14 +#define __NR_chmod 15 +#define __NR_chown 16 +#define __NR_break 17 +#define __NR_getfsstat4 18 +#define __NR_getpid 20 +#define __NR_mount 21 +#define __NR_unmount 22 +#define __NR_setuid 23 +#define __NR_getuid 24 +#define __NR_geteuid 25 +#define __NR_ptrace 26 +#define __NR_recvmsg 27 +#define __NR_sendmsg 28 +#define __NR_recvfrom 29 +#define __NR_accept 30 +#define __NR_getpeername 31 +#define __NR_getsockname 32 +#define __NR_access 33 +#define __NR_chflags 34 +#define __NR_fchflags 35 +#define __NR_sync 36 +#define __NR_kill 37 +#define __NR_getppid 39 +#define __NR_dup 41 +#define __NR_pipe 42 +#define __NR_getegid 43 +#define __NR_profil 44 +#define __NR_ktrace 45 +#define __NR_getgid 47 +#define __NR_getlogin 49 +#define __NR_setlogin 50 +#define __NR_acct 51 +#define __NR_sigaltstack 53 +#define __NR_ioctl 54 +#define __NR_reboot 55 +#define __NR_revoke 56 +#define __NR_symlink 57 +#define __NR_readlink 58 +#define __NR_execve 59 +#define __NR_umask 60 +#define __NR_chroot 61 +#define __NR_msync 65 +#define __NR_vfork 66 +#define __NR_sbrk 69 +#define __NR_sstk 70 +#define __NR_vadvise 72 +#define __NR_munmap 73 +#define __NR_mprotect 74 +#define __NR_madvise 75 +#define __NR_mincore 78 +#define __NR_getgroups 79 +#define __NR_setgroups 80 +#define __NR_getpgrp 81 +#define __NR_setpgid 82 +#define __NR_setitimer 83 +#define __NR_swapon 85 +#define __NR_getitimer 86 +#define __NR_getdtablesize 89 +#define __NR_dup2 90 +#define __NR_fcntl 92 +#define __NR_select 93 +#define __NR_fsync 95 +#define __NR_setpriority 96 +#define __NR_socket 97 +#define __NR_connect 98 +#define __NR_getpriority 100 +#define __NR_bind 104 +#define __NR_setsockopt 105 +#define __NR_listen 106 +#define __NR_gettimeofday 116 +#define __NR_getrusage 117 +#define __NR_getsockopt 118 +#define __NR_readv 120 +#define __NR_writev 121 +#define __NR_settimeofday 122 +#define __NR_fchown 123 +#define __NR_fchmod 124 +#define __NR_setreuid 126 +#define __NR_setregid 127 +#define __NR_rename 128 +#define __NR_flock 131 +#define __NR_mkfifo 132 +#define __NR_sendto 133 +#define __NR_shutdown 134 +#define __NR_socketpair 135 +#define __NR_mkdir 136 +#define __NR_rmdir 137 +#define __NR_utimes 138 +#define __NR_adjtime 140 +#define __NR_setsid 147 +#define __NR_quotactl 148 +#define __NR_nfssvc 155 +#define __NR_statfs 157 +#define __NR_fstatfs 158 +#define __NR_lgetfh 160 +#define __NR_getfh 161 +#define __NR_getdomainname 162 +#define __NR_setdomainname 163 +#define __NR_uname 164 +#define __NR_sysarch 165 +#define __NR_rtprio 166 +#define __NR_semsys 169 +#define __NR_msgsys 170 +#define __NR_shmsys 171 +#define __NR_pread6 173 +#define __NR_pwrite6 174 +#define __NR_ntp_adjtime 176 +#define __NR_setgid 181 +#define __NR_setegid 182 +#define __NR_seteuid 183 +#define __NR_stat 188 +#define __NR_fstat 189 +#define __NR_lstat 190 +#define __NR_pathconf 191 +#define __NR_fpathconf 192 +#define __NR_getrlimit 194 +#define __NR_setrlimit 195 +#define __NR_getdirentries 196 +#define __NR_mmap6 197 +#define __NR___syscall 198 +#define __NR_lseek6 199 +#define __NR_truncate 200 +#define __NR_ftruncate 201 +#define __NR___sysctl 202 +#define __NR_mlock 203 +#define __NR_munlock 204 +#define __NR_undelete 205 +#define __NR_futimes 206 +#define __NR_getpgid 207 +#define __NR_poll 209 +#define __NR_lkmnosys0 210 +#define __NR_lkmnosys1 211 +#define __NR_lkmnosys2 212 +#define __NR_lkmnosys3 213 +#define __NR_lkmnosys4 214 +#define __NR_lkmnosys5 215 +#define __NR_lkmnosys6 216 +#define __NR_lkmnosys7 217 +#define __NR_lkmnosys8 218 +#define __NR_nfs_fhopen 219 +#define __NR___semctl7 220 +#define __NR_semget 221 +#define __NR_semop 222 +#define __NR_msgctl 224 +#define __NR_msgget 225 +#define __NR_msgsnd 226 +#define __NR_msgrcv 227 +#define __NR_shmat 228 +#define __NR_shmctl7 229 +#define __NR_shmdt 230 +#define __NR_shmget 231 +#define __NR_clock_gettime 232 +#define __NR_clock_settime 233 +#define __NR_clock_getres 234 +#define __NR_nanosleep 240 +#define __NR_minherit 250 +#define __NR_rfork 251 +#define __NR_openbsd_poll 252 +#define __NR_issetugid 253 +#define __NR_lchown 254 +#define __NR_getdents 272 +#define __NR_lchmod 274 +#define __NR_netbsd_lchown 275 +#define __NR_lutimes 276 +#define __NR_netbsd_msync 277 +#define __NR_nstat 278 +#define __NR_nfstat 279 +#define __NR_nlstat 280 +#define __NR_fhstatfs 297 +#define __NR_fhopen 298 +#define __NR_fhstat 299 +#define __NR_modnext 300 +#define __NR_modstat 301 +#define __NR_modfnext 302 +#define __NR_modfind 303 +#define __NR_kldload 304 +#define __NR_kldunload 305 +#define __NR_kldfind 306 +#define __NR_kldnext 307 +#define __NR_kldstat 308 +#define __NR_kldfirstmod 309 +#define __NR_getsid 310 +#define __NR_setresuid 311 +#define __NR_setresgid 312 +#define __NR_aio_return 314 +#define __NR_aio_suspend 315 +#define __NR_aio_cancel 316 +#define __NR_aio_error 317 +#define __NR_aio_read 318 +#define __NR_aio_write 319 +#define __NR_lio_listio 320 +#define __NR_yield 321 +#define __NR_mlockall 324 +#define __NR_munlockall 325 +#define __NR___getcwd 326 +#define __NR_sched_setparam 327 +#define __NR_sched_getparam 328 +#define __NR_sched_setscheduler 329 +#define __NR_sched_getscheduler 330 +#define __NR_sched_yield 331 +#define __NR_sched_get_priority_max 332 +#define __NR_sched_get_priority_min 333 +#define __NR_sched_rr_get_interval 334 +#define __NR_utrace 335 +#define __NR_kldsym 337 +#define __NR_jail 338 +#define __NR_sigprocmask 340 +#define __NR_sigsuspend 341 +#define __NR_sigaction4 342 +#define __NR_sigpending 343 +#define __NR_sigreturn4 344 +#define __NR_sigtimedwait 345 +#define __NR_sigwaitinfo 346 +#define __NR___acl_get_file 347 +#define __NR___acl_set_file 348 +#define __NR___acl_get_fd 349 +#define __NR___acl_set_fd 350 +#define __NR___acl_delete_file 351 +#define __NR___acl_delete_fd 352 +#define __NR___acl_aclcheck_file 353 +#define __NR___acl_aclcheck_fd 354 +#define __NR_extattrctl 355 +#define __NR_extattr_set_file 356 +#define __NR_extattr_get_file 357 +#define __NR_extattr_delete_file 358 +#define __NR_aio_waitcomplete 359 +#define __NR_getresuid 360 +#define __NR_getresgid 361 +#define __NR_kqueue 362 +#define __NR_kevent 363 +#define __NR_extattr_set_fd 371 +#define __NR_extattr_get_fd 372 +#define __NR_extattr_delete_fd 373 +#define __NR___setugid 374 +#define __NR_nfsclnt 375 +#define __NR_eaccess 376 +#define __NR_nmount 378 +#define __NR_kse_exit 379 +#define __NR_kse_wakeup 380 +#define __NR_kse_create 381 +#define __NR_kse_thr_interrupt 382 +#define __NR_kse_release 383 +#define __NR___mac_get_proc 384 +#define __NR___mac_set_proc 385 +#define __NR___mac_get_fd 386 +#define __NR___mac_get_file 387 +#define __NR___mac_set_fd 388 +#define __NR___mac_set_file 389 +#define __NR_kenv 390 +#define __NR_lchflags 391 +#define __NR_uuidgen 392 +#define __NR_sendfile 393 +#define __NR_mac_syscall 394 +#define __NR_getfsstat 395 +#define __NR_statfs6 396 +#define __NR_fstatfs6 397 +#define __NR_fhstatfs6 398 +#define __NR_ksem_close 400 +#define __NR_ksem_post 401 +#define __NR_ksem_wait 402 +#define __NR_ksem_trywait 403 +#define __NR_ksem_init 404 +#define __NR_ksem_open 405 +#define __NR_ksem_unlink 406 +#define __NR_ksem_getvalue 407 +#define __NR_ksem_destroy 408 +#define __NR___mac_get_pid 409 +#define __NR___mac_get_link 410 +#define __NR___mac_set_link 411 +#define __NR_extattr_set_link 412 +#define __NR_extattr_get_link 413 +#define __NR_extattr_delete_link 414 +#define __NR___mac_execve 415 +#define __NR_sigaction 416 +#define __NR_sigreturn 417 +#define __NR_getcontext 421 +#define __NR_setcontext 422 +#define __NR_swapcontext 423 +#define __NR_swapoff 424 +#define __NR___acl_get_link 425 +#define __NR___acl_set_link 426 +#define __NR___acl_delete_link 427 +#define __NR___acl_aclcheck_link 428 +#define __NR_sigwait 429 +#define __NR_thr_create 430 +#define __NR_thr_exit 431 +#define __NR_thr_self 432 +#define __NR_thr_kill 433 +#define __NR__umtx_lock 434 +#define __NR__umtx_unlock 435 +#define __NR_jail_attach 436 +#define __NR_extattr_list_fd 437 +#define __NR_extattr_list_file 438 +#define __NR_extattr_list_link 439 +#define __NR_kse_switchin 440 +#define __NR_ksem_timedwait 441 +#define __NR_thr_suspend 442 +#define __NR_thr_wake 443 +#define __NR_kldunloadf 444 +#define __NR_audit 445 +#define __NR_auditon 446 +#define __NR_getauid 447 +#define __NR_setauid 448 +#define __NR_getaudit 449 +#define __NR_setaudit 450 +#define __NR_getaudit_addr 451 +#define __NR_setaudit_addr 452 +#define __NR_auditctl 453 +#define __NR__umtx_op 454 +#define __NR_thr_new 455 +#define __NR_sigqueue 456 +#define __NR_kmq_open 457 +#define __NR_kmq_setattr 458 +#define __NR_kmq_timedreceive 459 +#define __NR_kmq_timedsend 460 +#define __NR_kmq_notify 461 +#define __NR_kmq_unlink 462 +#define __NR_abort2 463 +#define __NR_thr_set_name 464 +#define __NR_aio_fsync 465 +#define __NR_rtprio_thread 466 +#define __NR_nosys467 467 +#define __NR_nosys468 468 +#define __NR___getpath_fromfd 469 +#define __NR___getpath_fromaddr 470 +#define __NR_sctp_peeloff 471 +#define __NR_sctp_generic_sendmsg 472 +#define __NR_sctp_generic_sendmsg_iov 473 +#define __NR_sctp_generic_recvmsg 474 +#define __NR_pread 475 +#define __NR_pwrite 476 +#define __NR_mmap 477 +#define __NR_lseek 478 +#define __NR_truncate7 479 +#define __NR_ftruncate7 480 +#define __NR_thr_kill2 481 +#define __NR_shm_open 482 +#define __NR_shm_unlink 483 +#define __NR_cpuset 484 +#define __NR_cpuset_setid 485 +#define __NR_cpuset_getid 486 +#define __NR_cpuset_getaffinity 487 +#define __NR_cpuset_setaffinity 488 +#define __NR_faccessat 489 +#define __NR_fchmodat 490 +#define __NR_fchownat 491 +#define __NR_fexecve 492 +#define __NR_fstatat 493 +#define __NR_futimesat 494 +#define __NR_linkat 495 +#define __NR_mkdirat 496 +#define __NR_mkfifoat 497 +#define __NR_mknodat 498 +#define __NR_openat 499 +#define __NR_readlinkat 500 +#define __NR_renameat 501 +#define __NR_symlinkat 502 +#define __NR_unlinkat 503 +#define __NR_posix_openpt 504 +#define __NR___semctl 510 +#define __NR_shmctl 512 + +#define __NR_fake_sigreturn 1000 + +#endif /* __VKI_UNISTD_FREEBSD_H */ diff -r efb6377bb4b5 -r ae0a1b9f3c43 include/vki/vki-scnums-openbsd.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/vki/vki-scnums-openbsd.h Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,252 @@ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2005 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#ifndef __VKI_UNISTD_OPENBSD_H +#define __VKI_UNISTD_OPENBSD_H + +#define VG_OPENBSD_SYSCALL_STD 0 +#define VG_OPENBSD_SYSCALL0 1 +#define VG_OPENBSD_SYSCALL198 2 + +// From sys/syscall.h + +#define __NR_syscall 0 +#define __NR_exit 1 +#define __NR_fork 2 +#define __NR_read 3 +#define __NR_write 4 +#define __NR_open 5 +#define __NR_close 6 +#define __NR_getentropy 7 +#define __NR___tfork 8 +#define __NR_link 9 +#define __NR_unlink 10 +#define __NR_wait4 11 +#define __NR_chdir 12 +#define __NR_fchdir 13 +#define __NR_mknod 14 +#define __NR_chmod 15 +#define __NR_chown 16 +#define __NR_break 17 +#define __NR_getdtablecount 18 +#define __NR_getrusage 19 +#define __NR_getpid 20 +#define __NR_mount 21 +#define __NR_unmount 22 +#define __NR_setuid 23 +#define __NR_getuid 24 +#define __NR_geteuid 25 +#define __NR_ptrace 26 +#define __NR_recvmsg 27 +#define __NR_sendmsg 28 +#define __NR_recvfrom 29 +#define __NR_accept 30 +#define __NR_getpeername 31 +#define __NR_getsockname 32 +#define __NR_access 33 +#define __NR_chflags 34 +#define __NR_fchflags 35 +#define __NR_sync 36 +#define __NR_o58_kill 37 +#define __NR_stat 38 +#define __NR_getppid 39 +#define __NR_lstat 40 +#define __NR_dup 41 +#define __NR_fstatat 42 +#define __NR_getegid 43 +#define __NR_profil 44 +#define __NR_ktrace 45 +#define __NR_sigaction 46 +#define __NR_getgid 47 +#define __NR_sigprocmask 48 +#define __NR_getlogin 49 +#define __NR_setlogin 50 +#define __NR_acct 51 +#define __NR_sigpending 52 +#define __NR_fstat 53 +#define __NR_ioctl 54 +#define __NR_reboot 55 +#define __NR_revoke 56 +#define __NR_symlink 57 +#define __NR_readlink 58 +#define __NR_execve 59 +#define __NR_umask 60 +#define __NR_chroot 61 +#define __NR_getfsstat 62 +#define __NR_statfs 63 +#define __NR_fstatfs 64 +#define __NR_fhstatfs 65 +#define __NR_vfork 66 +#define __NR_gettimeofday 67 +#define __NR_settimeofday 68 +#define __NR_setitimer 69 +#define __NR_getitimer 70 +#define __NR_select 71 +#define __NR_kevent 72 +#define __NR_munmap 73 +#define __NR_mprotect 74 +#define __NR_madvise 75 +#define __NR_utimes 76 +#define __NR_futimes 77 +#define __NR_mincore 78 +#define __NR_getgroups 79 +#define __NR_setgroups 80 +#define __NR_getpgrp 81 +#define __NR_setpgid 82 +#define __NR_osendsyslog 83 +#define __NR_utimensat 84 +#define __NR_futimens 85 +#define __NR_kbind 86 +#define __NR_clock_gettime 87 +#define __NR_clock_settime 88 +#define __NR_clock_getres 89 +#define __NR_dup2 90 +#define __NR_nanosleep 91 +#define __NR_fcntl 92 +#define __NR_accept4 93 +#define __NR___thrsleep 94 +#define __NR_fsync 95 +#define __NR_setpriority 96 +#define __NR_socket 97 +#define __NR_connect 98 +#define __NR_getdents 99 +#define __NR_getpriority 100 +#define __NR_pipe2 101 +#define __NR_dup3 102 +#define __NR_sigreturn 103 +#define __NR_bind 104 +#define __NR_setsockopt 105 +#define __NR_listen 106 +#define __NR_chflagsat 107 +#define __NR_pledge 108 +#define __NR_ppoll 109 +#define __NR_pselect 110 +#define __NR_sigsuspend 111 +#define __NR_sendsyslog 112 +#define __NR_getsockopt 118 +#define __NR_thrkill 119 +#define __NR_readv 120 +#define __NR_writev 121 +#define __NR_kill 122 +#define __NR_fchown 123 +#define __NR_fchmod 124 +#define __NR_setreuid 126 +#define __NR_setregid 127 +#define __NR_rename 128 +#define __NR_flock 131 +#define __NR_mkfifo 132 +#define __NR_sendto 133 +#define __NR_shutdown 134 +#define __NR_socketpair 135 +#define __NR_mkdir 136 +#define __NR_rmdir 137 +#define __NR_adjtime 140 +#define __NR_setsid 147 +#define __NR_quotactl 148 +#define __NR_nfssvc 155 +#define __NR_getfh 161 +#define __NR_sysarch 165 +#define __NR_pread 173 +#define __NR_pwrite 174 +#define __NR_setgid 181 +#define __NR_setegid 182 +#define __NR_seteuid 183 +#define __NR_pathconf 191 +#define __NR_fpathconf 192 +#define __NR_swapctl 193 +#define __NR_getrlimit 194 +#define __NR_setrlimit 195 +#define __NR_mmap 197 +#define __NR___syscall 198 +#define __NR_lseek 199 +#define __NR_truncate 200 +#define __NR_ftruncate 201 +#define __NR_sysctl 202 +#define __NR_mlock 203 +#define __NR_munlock 204 +#define __NR_getpgid 207 +#define __NR_utrace 209 +#define __NR_semget 221 +#define __NR_msgget 225 +#define __NR_msgsnd 226 +#define __NR_msgrcv 227 +#define __NR_shmat 228 +#define __NR_shmdt 230 +#define __NR_minherit 250 +#define __NR_poll 252 +#define __NR_issetugid 253 +#define __NR_lchown 254 +#define __NR_getsid 255 +#define __NR_msync 256 +#define __NR_pipe 263 +#define __NR_fhopen 264 +#define __NR_preadv 267 +#define __NR_pwritev 268 +#define __NR_kqueue 269 +#define __NR_mlockall 271 +#define __NR_munlockall 272 +#define __NR_getresuid 281 +#define __NR_setresuid 282 +#define __NR_getresgid 283 +#define __NR_setresgid 284 +#define __NR_mquery 286 +#define __NR_closefrom 287 +#define __NR_sigaltstack 288 +#define __NR_shmget 289 +#define __NR_semop 290 +#define __NR_fhstat 294 +#define __NR___semctl 295 +#define __NR_shmctl 296 +#define __NR_msgctl 297 +#define __NR_sched_yield 298 +#define __NR_getthrid 299 +#define __NR___thrwakeup 301 +#define __NR___threxit 302 +#define __NR___thrsigdivert 303 +#define __NR___getcwd 304 +#define __NR_adjfreq 305 +#define __NR_setrtable 310 +#define __NR_getrtable 311 +#define __NR_faccessat 313 +#define __NR_fchmodat 314 +#define __NR_fchownat 315 +#define __NR_linkat 317 +#define __NR_mkdirat 318 +#define __NR_mkfifoat 319 +#define __NR_mknodat 320 +#define __NR_openat 321 +#define __NR_readlinkat 322 +#define __NR_renameat 323 +#define __NR_symlinkat 324 +#define __NR_unlinkat 325 +#define __NR___set_tcb 329 +#define __NR___get_tcb 330 + +#define __NR_MAXSYSCALL 331 + +#define __NR_fake_sigreturn 1000 + +#endif /* __VKI_UNISTD_OPENBSD_H */ diff -r efb6377bb4b5 -r ae0a1b9f3c43 include/vki/vki-x86-freebsd.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/vki/vki-x86-freebsd.h Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,269 @@ + +/*--------------------------------------------------------------------*/ +/*--- x86/FreeBSD-specific kernel interface. vki-x86-freebsd.h ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2009 Stanislav Sedov + Copyright (C) 2000-2005 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#ifndef __VKI_X86_FREEBSD_H +#define __VKI_X86_FREEBSD_H + +//---------------------------------------------------------------------- +// From somewhere +//---------------------------------------------------------------------- + +/* PAGE_SHIFT determines the page size */ +#define VKI_PAGE_SHIFT 12 +#define VKI_PAGE_SIZE (1UL << VKI_PAGE_SHIFT) +#define VKI_MAX_PAGE_SHIFT VKI_PAGE_SHIFT +#define VKI_MAX_PAGE_SIZE VKI_PAGE_SIZE + +//---------------------------------------------------------------------- +// From sys/i386/include/_limits.h and sys/sys/_sigset.h +//---------------------------------------------------------------------- + +#define VKI_MINSIGSTKSZ (512 * 4) + +#define _VKI_NSIG 128 +#define _VKI_NSIG_WORDS 4 +#define _VKI_NSIG_BPW ((_VKI_NSIG) / (_VKI_NSIG_WORDS)) + +typedef struct { + vki_uint32_t sig[_VKI_NSIG_WORDS]; +} vki_sigset_t; + + +//---------------------------------------------------------------------- +// From sys/i386/include/npx.h +//---------------------------------------------------------------------- + +struct _vki_env87 { + long en_cw; + long en_sw; + long en_tw; + long en_fip; + unsigned short en_fcs; + unsigned short en_opcode; + long en_foo; + long en_fos; +}; + +struct _vki_fpacc87 { + unsigned char fp_bytes[10]; +}; + +struct _vki_save87 { + struct _vki_env87 sv_env; + struct _vki_fpacc87 sv_ac[8]; + unsigned char sv_pad0[4]; + unsigned char sv_pad[64]; +}; + +struct _vki_xmmacc { + unsigned char xmm_bytes[16]; +}; + +struct _vki_envxmm { + unsigned short en_cw; + unsigned short en_sw; + unsigned short en_tw; + unsigned short en_opcode; + unsigned int en_fip; + unsigned short en_fcs; + unsigned short en_pad0; + unsigned int en_foo; + unsigned short en_fos; + unsigned short en_pad1; + unsigned int en_mxcsr; + unsigned int en_mxcsr_mask; +}; + +struct _vki_savexmm { + struct _vki_envxmm sv_env; + struct { + struct _vki_fpacc87 fp_acc; + unsigned char fp_pad[6]; + } sv_fp[8]; + struct _vki_xmmacc sv_xmm[8]; + unsigned char sv_pad[224]; +}; + +struct _vki_fpstate { + union { + struct _vki_save87 sv_87; + struct _vki_savexmm sv_xmm; + }; +}; + +struct vki_sigcontext { + vki_sigset_t sc_mask; + int onstack; + int gs; + int fs; + int es; + int ds; + int edi; + int esi; + int ebp; + int isp; + int ebx; + int edx; + int ecx; + int eax; + int trapno; + int err; + int eip; + int cs; + int eflags; + int esp; + int ss; + int len; + int fpformat; + int ownedfp; + int spare1[1]; + struct _vki_fpstate fpstate __attribute__((aligned(16))); + int fsbase; + int gsbase; + int spare2[6]; +}; + +struct vki_user_regs_struct { + unsigned int fs; + unsigned int es; + unsigned int ds; + unsigned int edi; + unsigned int esi; + unsigned int ebp; + unsigned int isp; + unsigned int ebx; + unsigned int edx; + unsigned int ecx; + unsigned int eax; + unsigned int trapno; + unsigned int err; + unsigned int eip; + unsigned int cs; + unsigned int eflags; + unsigned int esp; + unsigned int ss; + unsigned int gs; +}; + +struct vki_reg_struct { + unsigned int r_fs; + unsigned int r_es; + unsigned int r_ds; + unsigned int r_edi; + unsigned int r_esi; + unsigned int r_ebp; + unsigned int r_isp; + unsigned int r_ebx; + unsigned int r_edx; + unsigned int r_ecx; + unsigned int r_eax; + unsigned int r_trapno; + unsigned int r_err; + unsigned int r_eip; + unsigned int r_cs; + unsigned int r_eflags; + unsigned int r_esp; + unsigned int r_ss; + unsigned int r_gs; +}; + +struct vki_fpreg { + unsigned long fpr_env[7]; + unsigned char fpr_acc[8][10]; + unsigned long fpr_ex_sw; + unsigned char fpr_pad[64]; +}; + +struct vki_dbreg { + unsigned int dr[8]; +}; + +typedef unsigned int vki_elf_greg_t; +typedef struct _vki_fpstate vki_elf_fpregset_t; +typedef struct _vki_fpstate vki_elf_fpxregset_t; + +#define VKI_AT_SYSINFO 32 +#define VKI_ELF_NGREG (sizeof (struct vki_user_regs_struct) / sizeof(vki_elf_greg_t)) +typedef vki_elf_greg_t vki_elf_gregset_t[VKI_ELF_NGREG]; + +#define VKI_FPFMT_NODEV 0x10000 +#define VKI_FPFMT_387 0x10001 +#define VKI_FPFMT_XMM 0x10002 + +#define VKI_FPOWNED_NONE 0x20000 +#define VKI_FPOWNED_FPU 0x20001 +#define VKI_FPOWNED_PCB 0x20002 + +struct vki_mcontext { + int onstack; + int gs; + int fs; + int es; + int ds; + int edi; + int esi; + int ebp; + int isp; + int ebx; + int edx; + int ecx; + int eax; + int trapno; + int err; + int eip; + int cs; + int eflags; + int esp; + int ss; + + int len; + int fpformat; + int ownedfp; + int spare1[1]; + struct _vki_fpstate fpstate __attribute__((aligned(16))); + int fsbase; + int gsbase; + int spare2[6]; +}; + +struct vki_sigaction_base { + void (*ksa_handler)(int); + int sa_flags; + vki_sigset_t sa_mask; /* mask last for extensibility */ +}; +typedef struct vki_sigaction_base vki_sigaction_toK_t; +typedef struct vki_sigaction_base vki_sigaction_fromK_t; + +#endif // __VKI_X86_FREEBSD_H + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 include/vki/vki-x86-openbsd.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/vki/vki-x86-openbsd.h Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,269 @@ + +/*--------------------------------------------------------------------*/ +/*--- x86/FreeBSD-specific kernel interface. vki-x86-freebsd.h ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2009 Stanislav Sedov + Copyright (C) 2000-2005 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#ifndef __VKI_X86_OPENBSD_H +#define __VKI_X86_OPENBSD_H + +//---------------------------------------------------------------------- +// From somewhere +//---------------------------------------------------------------------- + +/* PAGE_SHIFT determines the page size */ +#define VKI_PAGE_SHIFT 12 +#define VKI_PAGE_SIZE (1UL << VKI_PAGE_SHIFT) +#define VKI_MAX_PAGE_SHIFT VKI_PAGE_SHIFT +#define VKI_MAX_PAGE_SIZE VKI_PAGE_SIZE + +//---------------------------------------------------------------------- +// From sys/i386/include/_limits.h and sys/sys/_sigset.h +//---------------------------------------------------------------------- + +#define VKI_MINSIGSTKSZ (512 * 4) + +#define _VKI_NSIG 128 +#define _VKI_NSIG_WORDS 4 +#define _VKI_NSIG_BPW ((_VKI_NSIG) / (_VKI_NSIG_WORDS)) + +typedef struct { + vki_uint32_t sig[_VKI_NSIG_WORDS]; +} vki_sigset_t; + + +//---------------------------------------------------------------------- +// From sys/i386/include/npx.h +//---------------------------------------------------------------------- + +struct _vki_env87 { + long en_cw; + long en_sw; + long en_tw; + long en_fip; + unsigned short en_fcs; + unsigned short en_opcode; + long en_foo; + long en_fos; +}; + +struct _vki_fpacc87 { + unsigned char fp_bytes[10]; +}; + +struct _vki_save87 { + struct _vki_env87 sv_env; + struct _vki_fpacc87 sv_ac[8]; + unsigned char sv_pad0[4]; + unsigned char sv_pad[64]; +}; + +struct _vki_xmmacc { + unsigned char xmm_bytes[16]; +}; + +struct _vki_envxmm { + unsigned short en_cw; + unsigned short en_sw; + unsigned short en_tw; + unsigned short en_opcode; + unsigned int en_fip; + unsigned short en_fcs; + unsigned short en_pad0; + unsigned int en_foo; + unsigned short en_fos; + unsigned short en_pad1; + unsigned int en_mxcsr; + unsigned int en_mxcsr_mask; +}; + +struct _vki_savexmm { + struct _vki_envxmm sv_env; + struct { + struct _vki_fpacc87 fp_acc; + unsigned char fp_pad[6]; + } sv_fp[8]; + struct _vki_xmmacc sv_xmm[8]; + unsigned char sv_pad[224]; +}; + +struct _vki_fpstate { + union { + struct _vki_save87 sv_87; + struct _vki_savexmm sv_xmm; + }; +}; + +struct vki_sigcontext { + vki_sigset_t sc_mask; + int onstack; + int gs; + int fs; + int es; + int ds; + int edi; + int esi; + int ebp; + int isp; + int ebx; + int edx; + int ecx; + int eax; + int trapno; + int err; + int eip; + int cs; + int eflags; + int esp; + int ss; + int len; + int fpformat; + int ownedfp; + int spare1[1]; + struct _vki_fpstate fpstate __attribute__((aligned(16))); + int fsbase; + int gsbase; + int spare2[6]; +}; + +struct vki_user_regs_struct { + unsigned int fs; + unsigned int es; + unsigned int ds; + unsigned int edi; + unsigned int esi; + unsigned int ebp; + unsigned int isp; + unsigned int ebx; + unsigned int edx; + unsigned int ecx; + unsigned int eax; + unsigned int trapno; + unsigned int err; + unsigned int eip; + unsigned int cs; + unsigned int eflags; + unsigned int esp; + unsigned int ss; + unsigned int gs; +}; + +struct vki_reg_struct { + unsigned int r_fs; + unsigned int r_es; + unsigned int r_ds; + unsigned int r_edi; + unsigned int r_esi; + unsigned int r_ebp; + unsigned int r_isp; + unsigned int r_ebx; + unsigned int r_edx; + unsigned int r_ecx; + unsigned int r_eax; + unsigned int r_trapno; + unsigned int r_err; + unsigned int r_eip; + unsigned int r_cs; + unsigned int r_eflags; + unsigned int r_esp; + unsigned int r_ss; + unsigned int r_gs; +}; + +struct vki_fpreg { + unsigned long fpr_env[7]; + unsigned char fpr_acc[8][10]; + unsigned long fpr_ex_sw; + unsigned char fpr_pad[64]; +}; + +struct vki_dbreg { + unsigned int dr[8]; +}; + +typedef unsigned int vki_elf_greg_t; +typedef struct _vki_fpstate vki_elf_fpregset_t; +typedef struct _vki_fpstate vki_elf_fpxregset_t; + +#define VKI_AT_SYSINFO 32 +#define VKI_ELF_NGREG (sizeof (struct vki_user_regs_struct) / sizeof(vki_elf_greg_t)) +typedef vki_elf_greg_t vki_elf_gregset_t[VKI_ELF_NGREG]; + +#define VKI_FPFMT_NODEV 0x10000 +#define VKI_FPFMT_387 0x10001 +#define VKI_FPFMT_XMM 0x10002 + +#define VKI_FPOWNED_NONE 0x20000 +#define VKI_FPOWNED_FPU 0x20001 +#define VKI_FPOWNED_PCB 0x20002 + +struct vki_mcontext { + int onstack; + int gs; + int fs; + int es; + int ds; + int edi; + int esi; + int ebp; + int isp; + int ebx; + int edx; + int ecx; + int eax; + int trapno; + int err; + int eip; + int cs; + int eflags; + int esp; + int ss; + + int len; + int fpformat; + int ownedfp; + int spare1[1]; + struct _vki_fpstate fpstate __attribute__((aligned(16))); + int fsbase; + int gsbase; + int spare2[6]; +}; + +struct vki_sigaction_base { + void (*ksa_handler)(int); + int sa_flags; + vki_sigset_t sa_mask; /* mask last for extensibility */ +}; +typedef struct vki_sigaction_base vki_sigaction_toK_t; +typedef struct vki_sigaction_base vki_sigaction_fromK_t; + +#endif // __VKI_X86_OPENBSD_H + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff -r efb6377bb4b5 -r ae0a1b9f3c43 lackey/Makefile.am --- a/lackey/Makefile.am Mon Dec 01 23:44:20 2014 +0900 +++ b/lackey/Makefile.am Thu Mar 31 15:57:55 2016 +0900 @@ -52,4 +52,3 @@ $(lackey_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) \ $(lackey_@VGCONF_ARCH_SEC@_@VGCONF_OS@_LDFLAGS) endif - diff -r efb6377bb4b5 -r ae0a1b9f3c43 memcheck/Makefile.am --- a/memcheck/Makefile.am Mon Dec 01 23:44:20 2014 +0900 +++ b/memcheck/Makefile.am Thu Mar 31 15:57:55 2016 +0900 @@ -122,3 +122,12 @@ # sometimes fragile. mc_replace_strmem.o: CFLAGS += -fno-omit-frame-pointer +install-exec-hook: + cd $(DESTDIR)$(pkglibdir) && \ + chown root:kmem $(noinst_PROGRAMS) && \ + chmod g+s $(noinst_PROGRAMS) +if VGCONF_OS_IS_OPENBSD + cd $(DESTDIR)$(pkglibdir) && \ + chown root:wheel $(noinst_PROGRAMS) && \ + chmod g-s $(noinst_PROGRAMS) +endif diff -r efb6377bb4b5 -r ae0a1b9f3c43 memcheck/mc_replace_strmem.c --- a/memcheck/mc_replace_strmem.c Mon Dec 01 23:44:20 2014 +0900 +++ b/memcheck/mc_replace_strmem.c Thu Mar 31 15:57:55 2016 +0900 @@ -46,3 +46,1794 @@ s, src, dst, len, 0) #include "../shared/vg_replace_strmem.c" + +#if 0 +/*---------------------- strrchr ----------------------*/ + +#define STRRCHR(soname, fnname) \ + char* VG_REPLACE_FUNCTION_EZU(20010,soname,fnname)( const char* s, int c ); \ + char* VG_REPLACE_FUNCTION_EZU(20010,soname,fnname)( const char* s, int c ) \ + { \ + HChar ch = (HChar)c; \ + const HChar* p = s; \ + const HChar* last = NULL; \ + while (True) { \ + if (*p == ch) last = p; \ + if (*p == 0) return (HChar *)last; \ + p++; \ + } \ + } + +// Apparently rindex() is the same thing as strrchr() +#if defined(VGO_linux) + STRRCHR(VG_Z_LIBC_SONAME, strrchr) + STRRCHR(VG_Z_LIBC_SONAME, rindex) + STRRCHR(VG_Z_LIBC_SONAME, __GI_strrchr) + STRRCHR(VG_Z_LD_LINUX_SO_2, rindex) +#if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) + STRRCHR(NONE, __dl_strrchr); /* in /system/bin/linker */ +#endif + +#elif defined(VGO_freebsd) + STRRCHR(VG_Z_LIBC_SONAME, strrchr) + STRRCHR(VG_Z_LIBC_SONAME, rindex) + STRRCHR(VG_Z_LD_ELF_SO_1, strrchr) + STRRCHR(VG_Z_LD_ELF32_SO_1, strrchr) + +#elif defined(VGO_openbsd) + STRRCHR(VG_Z_LIBC_SONAME, strrchr) + STRRCHR(VG_Z_LIBC_SONAME, rindex) + +#elif defined(VGO_darwin) + //STRRCHR(VG_Z_LIBC_SONAME, strrchr) + //STRRCHR(VG_Z_LIBC_SONAME, rindex) + //STRRCHR(VG_Z_DYLD, strrchr) + //STRRCHR(VG_Z_DYLD, rindex) + STRRCHR(VG_Z_LIBC_SONAME, strrchr) + +#endif + + +/*---------------------- strchr ----------------------*/ + +#define STRCHR(soname, fnname) \ + char* VG_REPLACE_FUNCTION_EZU(20020,soname,fnname) ( const char* s, int c ); \ + char* VG_REPLACE_FUNCTION_EZU(20020,soname,fnname) ( const char* s, int c ) \ + { \ + HChar ch = (HChar)c ; \ + const HChar* p = s; \ + while (True) { \ + if (*p == ch) return (HChar *)p; \ + if (*p == 0) return NULL; \ + p++; \ + } \ + } + +// Apparently index() is the same thing as strchr() +#if defined(VGO_linux) + STRCHR(VG_Z_LIBC_SONAME, strchr) + STRCHR(VG_Z_LIBC_SONAME, index) + STRCHR(VG_Z_LIBC_SONAME, __GI_strchr) +# if !defined(VGP_x86_linux) + STRCHR(VG_Z_LD_LINUX_SO_2, strchr) + STRCHR(VG_Z_LD_LINUX_SO_2, index) + STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, strchr) + STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, index) +# endif + +#elif defined(VGO_freebsd) + STRCHR(VG_Z_LIBC_SONAME, strchr) + STRCHR(VG_Z_LIBC_SONAME, index) + STRCHR(VG_Z_LD_ELF_SO_1, strchr) + STRCHR(VG_Z_LD_ELF32_SO_1, strchr) + +#elif defined(VGO_openbsd) + STRCHR(VG_Z_LIBC_SONAME, strchr) + STRCHR(VG_Z_LIBC_SONAME, index) + +#elif defined(VGO_darwin) + //STRCHR(VG_Z_LIBC_SONAME, strchr) + //STRCHR(VG_Z_LIBC_SONAME, index) + //STRCHR(VG_Z_DYLD, strchr) + //STRCHR(VG_Z_DYLD, index) + STRCHR(VG_Z_LIBC_SONAME, strchr) + +#endif + + +/*---------------------- strcat ----------------------*/ + +#define STRCAT(soname, fnname) \ + char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \ + ( char* dst, const char* src ); \ + char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \ + ( char* dst, const char* src ) \ + { \ + const HChar* src_orig = src; \ + HChar* dst_orig = dst; \ + while (*dst) dst++; \ + while (*src) *dst++ = *src++; \ + *dst = 0; \ + \ + /* This is a bit redundant, I think; any overlap and the strcat will */ \ + /* go forever... or until a seg fault occurs. */ \ + if (is_overlap(dst_orig, \ + src_orig, \ + (Addr)dst-(Addr)dst_orig+1, \ + (Addr)src-(Addr)src_orig+1)) \ + RECORD_OVERLAP_ERROR("strcat", dst_orig, src_orig, 0); \ + \ + return dst_orig; \ + } + +#if defined(VGO_linux) + STRCAT(VG_Z_LIBC_SONAME, strcat) + STRCAT(VG_Z_LIBC_SONAME, __GI_strcat) + +#elif defined(VGO_freebsd) + STRCAT(VG_Z_LIBC_SONAME, strcat) + STRCAT(VG_Z_LD_ELF_SO_1, strcat) + STRCAT(VG_Z_LD_ELF32_SO_1, strcat) + +#elif defined(VGO_openbsd) + STRCAT(VG_Z_LIBC_SONAME, strcat) + +#elif defined(VGO_darwin) + //STRCAT(VG_Z_LIBC_SONAME, strcat) + +#endif + + +/*---------------------- strncat ----------------------*/ + +#define STRNCAT(soname, fnname) \ + char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \ + ( char* dst, const char* src, SizeT n ); \ + char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \ + ( char* dst, const char* src, SizeT n ) \ + { \ + const HChar* src_orig = src; \ + HChar* dst_orig = dst; \ + SizeT m = 0; \ + \ + while (*dst) dst++; \ + while (m < n && *src) { m++; *dst++ = *src++; } /* concat <= n chars */ \ + *dst = 0; /* always add null */ \ + \ + /* This checks for overlap after copying, unavoidable without */ \ + /* pre-counting lengths... should be ok */ \ + if (is_overlap(dst_orig, \ + src_orig, \ + (Addr)dst-(Addr)dst_orig+1, \ + (Addr)src-(Addr)src_orig+1)) \ + RECORD_OVERLAP_ERROR("strncat", dst_orig, src_orig, n); \ + \ + return dst_orig; \ + } + +#if defined(VGO_linux) + STRNCAT(VG_Z_LIBC_SONAME, strncat) + +#elif defined(VGO_freebsd) + STRNCAT(VG_Z_LIBC_SONAME, strncat) + +#elif defined(VGO_openbsd) + STRNCAT(VG_Z_LIBC_SONAME, strncat) + +#elif defined(VGO_darwin) + //STRNCAT(VG_Z_LIBC_SONAME, strncat) + //STRNCAT(VG_Z_DYLD, strncat) + +#endif + + +/*---------------------- strlcat ----------------------*/ + +/* Append src to dst. n is the size of dst's buffer. dst is guaranteed + to be nul-terminated after the copy, unless n <= strlen(dst_orig). + Returns min(n, strlen(dst_orig)) + strlen(src_orig). + Truncation occurred if retval >= n. +*/ +#define STRLCAT(soname, fnname) \ + SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \ + ( char* dst, const char* src, SizeT n ); \ + SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \ + ( char* dst, const char* src, SizeT n ) \ + { \ + const HChar* src_orig = src; \ + HChar* dst_orig = dst; \ + SizeT m = 0; \ + \ + while (m < n && *dst) { m++; dst++; } \ + if (m < n) { \ + /* Fill as far as dst_orig[n-2], then nul-terminate. */ \ + while (m < n-1 && *src) { m++; *dst++ = *src++; } \ + *dst = 0; \ + } else { \ + /* No space to copy anything to dst. m == n */ \ + } \ + /* Finish counting min(n, strlen(dst_orig)) + strlen(src_orig) */ \ + while (*src) { m++; src++; } \ + /* This checks for overlap after copying, unavoidable without */ \ + /* pre-counting lengths... should be ok */ \ + if (is_overlap(dst_orig, \ + src_orig, \ + (Addr)dst-(Addr)dst_orig+1, \ + (Addr)src-(Addr)src_orig+1)) \ + RECORD_OVERLAP_ERROR("strlcat", dst_orig, src_orig, n); \ + \ + return m; \ + } + +#if defined(VGO_linux) + +#elif defined(VGO_freebsd) + STRLCAT(VG_Z_LD_ELF_SO_1, strlcat) + STRLCAT(VG_Z_LIBC_SONAME, strlcat) + STRLCAT(VG_Z_LD_ELF32_SO_1, strlcat) + +#elif defined(VGO_openbsd) + STRLCAT(VG_Z_LIBC_SONAME, strlcat) + +#elif defined(VGO_darwin) + //STRLCAT(VG_Z_LIBC_SONAME, strlcat) + //STRLCAT(VG_Z_DYLD, strlcat) + STRLCAT(VG_Z_LIBC_SONAME, strlcat) + +#endif + + +/*---------------------- strnlen ----------------------*/ + +#define STRNLEN(soname, fnname) \ + SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \ + ( const char* str, SizeT n ); \ + SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \ + ( const char* str, SizeT n ) \ + { \ + SizeT i = 0; \ + while (i < n && str[i] != 0) i++; \ + return i; \ + } + +#if defined(VGO_linux) + STRNLEN(VG_Z_LIBC_SONAME, strnlen) + STRNLEN(VG_Z_LIBC_SONAME, __GI_strnlen) + +#elif defined(VGO_darwin) + //STRNLEN(VG_Z_LIBC_SONAME, strnlen) + +#endif + + +/*---------------------- strlen ----------------------*/ + +// Note that this replacement often doesn't get used because gcc inlines +// calls to strlen() with its own built-in version. This can be very +// confusing if you aren't expecting it. Other small functions in +// this file may also be inline by gcc. + +#define STRLEN(soname, fnname) \ + SizeT VG_REPLACE_FUNCTION_EZU(20070,soname,fnname) \ + ( const char* str ); \ + SizeT VG_REPLACE_FUNCTION_EZU(20070,soname,fnname) \ + ( const char* str ) \ + { \ + SizeT i = 0; \ + while (str[i] != 0) i++; \ + return i; \ + } + +#if defined(VGO_linux) + STRLEN(VG_Z_LIBC_SONAME, strlen) + STRLEN(VG_Z_LIBC_SONAME, __GI_strlen) +# if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) + STRLEN(NONE, __dl_strlen); /* in /system/bin/linker */ +# endif + +#elif defined(VGO_freebsd) + STRLEN(VG_Z_LIBC_SONAME, strlen) + STRLEN(VG_Z_LD_ELF_SO_1, strlen) + STRLEN(VG_Z_LD_ELF32_SO_1, strlen) + +#elif defined(VGO_openbsd) + STRLEN(VG_Z_LIBC_SONAME, strlen) + +#elif defined(VGO_darwin) + //STRLEN(VG_Z_LIBC_SONAME, strlen) + STRLEN(VG_Z_LIBC_SONAME, strlen) + +#endif + + +/*---------------------- strcpy ----------------------*/ + +#define STRCPY(soname, fnname) \ + char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \ + ( char* dst, const char* src ); \ + char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \ + ( char* dst, const char* src ) \ + { \ + const HChar* src_orig = src; \ + HChar* dst_orig = dst; \ + \ + while (*src) *dst++ = *src++; \ + *dst = 0; \ + \ + /* This checks for overlap after copying, unavoidable without */ \ + /* pre-counting length... should be ok */ \ + if (is_overlap(dst_orig, \ + src_orig, \ + (Addr)dst-(Addr)dst_orig+1, \ + (Addr)src-(Addr)src_orig+1)) \ + RECORD_OVERLAP_ERROR("strcpy", dst_orig, src_orig, 0); \ + \ + return dst_orig; \ + } + +#if defined(VGO_linux) + STRCPY(VG_Z_LIBC_SONAME, strcpy) + STRCPY(VG_Z_LIBC_SONAME, __GI_strcpy) + +#elif defined(VGO_freebsd) + STRCPY(VG_Z_LIBC_SONAME, strcpy) + STRCPY(VG_Z_LD_ELF_SO_1, strcpy) + STRCPY(VG_Z_LD_ELF32_SO_1, strcpy) + +#elif defined(VGO_openbsd) + STRCPY(VG_Z_LIBC_SONAME, strcpy) + +#elif defined(VGO_darwin) + //STRCPY(VG_Z_LIBC_SONAME, strcpy) + //STRCPY(VG_Z_DYLD, strcpy) + STRCPY(VG_Z_LIBC_SONAME, strcpy) + +#endif + + +/*---------------------- strncpy ----------------------*/ + +#define STRNCPY(soname, fnname) \ + char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \ + ( char* dst, const char* src, SizeT n ); \ + char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \ + ( char* dst, const char* src, SizeT n ) \ + { \ + const HChar* src_orig = src; \ + HChar* dst_orig = dst; \ + SizeT m = 0; \ + \ + while (m < n && *src) { m++; *dst++ = *src++; } \ + /* Check for overlap after copying; all n bytes of dst are relevant, */ \ + /* but only m+1 bytes of src if terminator was found */ \ + if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \ + RECORD_OVERLAP_ERROR("strncpy", dst, src, n); \ + while (m++ < n) *dst++ = 0; /* must pad remainder with nulls */ \ + \ + return dst_orig; \ + } + +#if defined(VGO_linux) + STRNCPY(VG_Z_LIBC_SONAME, strncpy) + STRNCPY(VG_Z_LIBC_SONAME, __GI_strncpy) + +#elif defined(VGO_freebsd) + STRNCPY(VG_Z_LIBC_SONAME, strncpy) + STRNCPY(VG_Z_LD_ELF_SO_1, strncpy) + STRNCPY(VG_Z_LD_ELF32_SO_1, strncpy) + +#elif defined(VGO_darwin) + //STRNCPY(VG_Z_LIBC_SONAME, strncpy) + //STRNCPY(VG_Z_DYLD, strncpy) + STRNCPY(VG_Z_LIBC_SONAME, strncpy) + +#endif + + +/*---------------------- strlcpy ----------------------*/ + +/* Copy up to n-1 bytes from src to dst. Then nul-terminate dst if n > 0. + Returns strlen(src). Does not zero-fill the remainder of dst. */ +#define STRLCPY(soname, fnname) \ + SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \ + ( char* dst, const char* src, SizeT n ); \ + SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \ + ( char* dst, const char* src, SizeT n ) \ + { \ + const HChar* src_orig = src; \ + HChar* dst_orig = dst; \ + SizeT m = 0; \ + \ + while (m < n-1 && *src) { m++; *dst++ = *src++; } \ + /* m non-nul bytes have now been copied, and m <= n-1. */ \ + /* Check for overlap after copying; all n bytes of dst are relevant, */ \ + /* but only m+1 bytes of src if terminator was found */ \ + if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \ + RECORD_OVERLAP_ERROR("strlcpy", dst, src, n); \ + /* Nul-terminate dst. */ \ + if (n > 0) *dst = 0; \ + /* Finish counting strlen(src). */ \ + while (*src) src++; \ + return src - src_orig; \ + } + +#if defined(VGO_linux) + +#if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) + STRLCPY(VG_Z_LIBC_SONAME, strlcpy); +#endif + +#elif defined(VGO_freebsd) + STRLCPY(VG_Z_LD_ELF_SO_1, strlcpy) + STRLCPY(VG_Z_LD_ELF32_SO_1, strlcpy) + STRLCPY(VG_Z_LIBC_SONAME, strlcpy) + +#elif defined(VGO_openbsd) + STRLCPY(VG_Z_LIBC_SONAME, strlcpy) + +#elif defined(VGO_darwin) + //STRLCPY(VG_Z_LIBC_SONAME, strlcpy) + //STRLCPY(VG_Z_DYLD, strlcpy) + STRLCPY(VG_Z_LIBC_SONAME, strlcpy) + +#endif + + +/*---------------------- strncmp ----------------------*/ + +#define STRNCMP(soname, fnname) \ + int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \ + ( const char* s1, const char* s2, SizeT nmax ); \ + int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \ + ( const char* s1, const char* s2, SizeT nmax ) \ + { \ + SizeT n = 0; \ + while (True) { \ + if (n >= nmax) return 0; \ + if (*s1 == 0 && *s2 == 0) return 0; \ + if (*s1 == 0) return -1; \ + if (*s2 == 0) return 1; \ + \ + if (*(const UChar*)s1 < *(const UChar*)s2) return -1; \ + if (*(const UChar*)s1 > *(const UChar*)s2) return 1; \ + \ + s1++; s2++; n++; \ + } \ + } + +#if defined(VGO_linux) + STRNCMP(VG_Z_LIBC_SONAME, strncmp) + STRNCMP(VG_Z_LIBC_SONAME, __GI_strncmp) + +#elif defined(VGO_freebsd) + STRNCMP(VG_Z_LIBC_SONAME, strncmp) + STRNCMP(VG_Z_LD_ELF_SO_1, strncmp) + STRNCMP(VG_Z_LD_ELF32_SO_1, strncmp) + +#elif defined(VGO_openbsd) + STRNCMP(VG_Z_LIBC_SONAME, strncmp) + +#elif defined(VGO_darwin) + //STRNCMP(VG_Z_LIBC_SONAME, strncmp) + //STRNCMP(VG_Z_DYLD, strncmp) + STRNCMP(VG_Z_LIBC_SONAME, strncmp) + +#endif + + +/*---------------------- strcasecmp ----------------------*/ + +#define STRCASECMP(soname, fnname) \ + int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \ + ( const char* s1, const char* s2 ); \ + int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \ + ( const char* s1, const char* s2 ) \ + { \ + extern int tolower(int); \ + register UChar c1; \ + register UChar c2; \ + while (True) { \ + c1 = tolower(*(const UChar *)s1); \ + c2 = tolower(*(const UChar *)s2); \ + if (c1 != c2) break; \ + if (c1 == 0) break; \ + s1++; s2++; \ + } \ + if ((UChar)c1 < (UChar)c2) return -1; \ + if ((UChar)c1 > (UChar)c2) return 1; \ + return 0; \ + } + +#if defined(VGO_linux) +# if !defined(VGPV_arm_linux_android) && !defined(VGPV_x86_linux_android) + STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp) + STRCASECMP(VG_Z_LIBC_SONAME, __GI_strcasecmp) +# endif + +#elif defined(VGO_darwin) + //STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp) + +#endif + + +/*---------------------- strncasecmp ----------------------*/ + +#define STRNCASECMP(soname, fnname) \ + int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \ + ( const char* s1, const char* s2, SizeT nmax ); \ + int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \ + ( const char* s1, const char* s2, SizeT nmax ) \ + { \ + extern int tolower(int); \ + SizeT n = 0; \ + while (True) { \ + if (n >= nmax) return 0; \ + if (*s1 == 0 && *s2 == 0) return 0; \ + if (*s1 == 0) return -1; \ + if (*s2 == 0) return 1; \ + \ + if (tolower(*(const UChar *)s1) \ + < tolower(*(const UChar*)s2)) return -1; \ + if (tolower(*(const UChar *)s1) \ + > tolower(*(const UChar *)s2)) return 1; \ + \ + s1++; s2++; n++; \ + } \ + } + +#if defined(VGO_linux) +# if !defined(VGPV_arm_linux_android) && !defined(VGPV_x86_linux_android) + STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp) + STRNCASECMP(VG_Z_LIBC_SONAME, __GI_strncasecmp) +# endif + +#elif defined(VGO_darwin) + //STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp) + //STRNCASECMP(VG_Z_DYLD, strncasecmp) + +#endif + + +/*---------------------- strcasecmp_l ----------------------*/ + +#define STRCASECMP_L(soname, fnname) \ + int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \ + ( const char* s1, const char* s2, void* locale ); \ + int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \ + ( const char* s1, const char* s2, void* locale ) \ + { \ + extern int tolower_l(int, void*) __attribute__((weak)); \ + register UChar c1; \ + register UChar c2; \ + while (True) { \ + c1 = tolower_l(*(const UChar *)s1, locale); \ + c2 = tolower_l(*(const UChar *)s2, locale); \ + if (c1 != c2) break; \ + if (c1 == 0) break; \ + s1++; s2++; \ + } \ + if ((UChar)c1 < (UChar)c2) return -1; \ + if ((UChar)c1 > (UChar)c2) return 1; \ + return 0; \ + } + +#if defined(VGO_linux) + STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l) + STRCASECMP_L(VG_Z_LIBC_SONAME, __GI_strcasecmp_l) + STRCASECMP_L(VG_Z_LIBC_SONAME, __GI___strcasecmp_l) + +#elif defined(VGO_darwin) + //STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l) + +#endif + + +/*---------------------- strncasecmp_l ----------------------*/ + +#define STRNCASECMP_L(soname, fnname) \ + int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \ + ( const char* s1, const char* s2, SizeT nmax, void* locale ); \ + int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \ + ( const char* s1, const char* s2, SizeT nmax, void* locale ) \ + { \ + extern int tolower_l(int, void*) __attribute__((weak)); \ + SizeT n = 0; \ + while (True) { \ + if (n >= nmax) return 0; \ + if (*s1 == 0 && *s2 == 0) return 0; \ + if (*s1 == 0) return -1; \ + if (*s2 == 0) return 1; \ + \ + if (tolower_l(*(const UChar *)s1, locale) \ + < tolower_l(*(const UChar *)s2, locale)) return -1; \ + if (tolower_l(*(const UChar *)s1, locale) \ + > tolower_l(*(const UChar *)s2, locale)) return 1; \ + \ + s1++; s2++; n++; \ + } \ + } + +#if defined(VGO_linux) + STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l) + STRNCASECMP_L(VG_Z_LIBC_SONAME, __GI_strncasecmp_l) + STRNCASECMP_L(VG_Z_LIBC_SONAME, __GI___strncasecmp_l) + +#elif defined(VGO_darwin) + //STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l) + //STRNCASECMP_L(VG_Z_DYLD, strncasecmp_l) + +#endif + + +/*---------------------- strcmp ----------------------*/ + +#define STRCMP(soname, fnname) \ + int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \ + ( const char* s1, const char* s2 ); \ + int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \ + ( const char* s1, const char* s2 ) \ + { \ + register UChar c1; \ + register UChar c2; \ + while (True) { \ + c1 = *(const UChar *)s1; \ + c2 = *(const UChar *)s2; \ + if (c1 != c2) break; \ + if (c1 == 0) break; \ + s1++; s2++; \ + } \ + if ((UChar)c1 < (UChar)c2) return -1; \ + if ((UChar)c1 > (UChar)c2) return 1; \ + return 0; \ + } + +#if defined(VGO_linux) + STRCMP(VG_Z_LIBC_SONAME, strcmp) + STRCMP(VG_Z_LIBC_SONAME, __GI_strcmp) + STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp) + STRCMP(VG_Z_LD64_SO_1, strcmp) +#elif defined(VGO_freebsd) + STRCMP(VG_Z_LIBC_SONAME, strcmp) + STRCMP(VG_Z_LD_ELF_SO_1, strcmp) + STRCMP(VG_Z_LD_ELF32_SO_1, strcmp) + +#elif defined(VGO_openbsd) + STRCMP(VG_Z_LIBC_SONAME, strcmp) + +# if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) + STRCMP(NONE, __dl_strcmp); /* in /system/bin/linker */ +# endif + +#elif defined(VGO_darwin) + //STRCMP(VG_Z_LIBC_SONAME, strcmp) + STRCMP(VG_Z_LIBC_SONAME, strcmp) + +#endif + + +/*---------------------- memchr ----------------------*/ + +#define MEMCHR(soname, fnname) \ + void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \ + (const void *s, int c, SizeT n); \ + void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \ + (const void *s, int c, SizeT n) \ + { \ + SizeT i; \ + UChar c0 = (UChar)c; \ + UChar* p = (UChar*)s; \ + for (i = 0; i < n; i++) \ + if (p[i] == c0) return (void*)(&p[i]); \ + return NULL; \ + } + +#if defined(VGO_linux) + MEMCHR(VG_Z_LIBC_SONAME, memchr) + +#elif defined(VGO_freebsd) + MEMCHR(VG_Z_LIBC_SONAME, memchr) + MEMCHR(VG_Z_LD_ELF_SO_1, memchr) + MEMCHR(VG_Z_LD_ELF32_SO_1, memchr) + +#elif defined(VGO_openbsd) + MEMCHR(VG_Z_LIBC_SONAME, memchr) + +#elif defined(VGO_darwin) + //MEMCHR(VG_Z_LIBC_SONAME, memchr) + //MEMCHR(VG_Z_DYLD, memchr) + +#endif + + +/*---------------------- memrchr ----------------------*/ + +#define MEMRCHR(soname, fnname) \ + void* VG_REPLACE_FUNCTION_EZU(20360,soname,fnname) \ + (const void *s, int c, SizeT n); \ + void* VG_REPLACE_FUNCTION_EZU(20360,soname,fnname) \ + (const void *s, int c, SizeT n) \ + { \ + SizeT i; \ + UChar c0 = (UChar)c; \ + UChar* p = (UChar*)s; \ + for (i = 0; i < n; i++) \ + if (p[n-1-i] == c0) return (void*)(&p[n-1-i]); \ + return NULL; \ + } + +#if defined(VGO_linux) + MEMRCHR(VG_Z_LIBC_SONAME, memrchr) + +#elif defined(VGO_freebsd) + MEMRCHR(VG_Z_LIBC_SONAME, memrchr) + +#elif defined(VGO_openbsd) + MEMRCHR(VG_Z_LIBC_SONAME, memrchr) + +#elif defined(VGO_darwin) + //MEMRCHR(VG_Z_LIBC_SONAME, memrchr) + //MEMRCHR(VG_Z_DYLD, memrchr) + +#endif + + +/*---------------------- memcpy ----------------------*/ + +#define MEMMOVE_OR_MEMCPY(becTag, soname, fnname, do_ol_check) \ + void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \ + ( void *dst, const void *src, SizeT len ); \ + void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \ + ( void *dst, const void *src, SizeT len ) \ + { \ + if (do_ol_check && is_overlap(dst, src, len, len)) \ + RECORD_OVERLAP_ERROR("memcpy", dst, src, len); \ + \ + const Addr WS = sizeof(UWord); /* 8 or 4 */ \ + const Addr WM = WS - 1; /* 7 or 3 */ \ + \ + if (len > 0) { \ + if (dst < src) { \ + \ + /* Copying backwards. */ \ + SizeT n = len; \ + Addr d = (Addr)dst; \ + Addr s = (Addr)src; \ + \ + if (((s^d) & WM) == 0) { \ + /* s and d have same UWord alignment. */ \ + /* Pull up to a UWord boundary. */ \ + while ((s & WM) != 0 && n >= 1) \ + { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \ + /* Copy UWords. */ \ + while (n >= WS) \ + { *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; } \ + if (n == 0) \ + return dst; \ + } \ + if (((s|d) & 1) == 0) { \ + /* Both are 16-aligned; copy what we can thusly. */ \ + while (n >= 2) \ + { *(UShort*)d = *(UShort*)s; s += 2; d += 2; n -= 2; } \ + } \ + /* Copy leftovers, or everything if misaligned. */ \ + while (n >= 1) \ + { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \ + \ + } else if (dst > src) { \ + \ + SizeT n = len; \ + Addr d = ((Addr)dst) + n; \ + Addr s = ((Addr)src) + n; \ + \ + /* Copying forwards. */ \ + if (((s^d) & WM) == 0) { \ + /* s and d have same UWord alignment. */ \ + /* Back down to a UWord boundary. */ \ + while ((s & WM) != 0 && n >= 1) \ + { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \ + /* Copy UWords. */ \ + while (n >= WS) \ + { s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; } \ + if (n == 0) \ + return dst; \ + } \ + if (((s|d) & 1) == 0) { \ + /* Both are 16-aligned; copy what we can thusly. */ \ + while (n >= 2) \ + { s -= 2; d -= 2; *(UShort*)d = *(UShort*)s; n -= 2; } \ + } \ + /* Copy leftovers, or everything if misaligned. */ \ + while (n >= 1) \ + { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \ + \ + } \ + } \ + \ + return dst; \ + } + +#define MEMMOVE(soname, fnname) \ + MEMMOVE_OR_MEMCPY(20181, soname, fnname, 0) + +#define MEMCPY(soname, fnname) \ + MEMMOVE_OR_MEMCPY(20180, soname, fnname, 1) + +#if defined(VGO_linux) + /* For older memcpy we have to use memmove-like semantics and skip + the overlap check; sigh; see #275284. */ + MEMMOVE(VG_Z_LIBC_SONAME, memcpyZAGLIBCZu2Zd2Zd5) /* memcpy@GLIBC_2.2.5 */ + MEMCPY(VG_Z_LIBC_SONAME, memcpyZAZAGLIBCZu2Zd14) /* memcpy@@GLIBC_2.14 */ + MEMCPY(VG_Z_LIBC_SONAME, memcpy) /* fallback case */ + MEMCPY(VG_Z_LD_SO_1, memcpy) /* ld.so.1 */ + MEMCPY(VG_Z_LD64_SO_1, memcpy) /* ld64.so.1 */ + /* icc9 blats these around all over the place. Not only in the main + executable but various .so's. They are highly tuned and read + memory beyond the source boundary (although work correctly and + never go across page boundaries), so give errors when run + natively, at least for misaligned source arg. Just intercepting + in the exe only until we understand more about the problem. See + http://bugs.kde.org/show_bug.cgi?id=139776 + */ + MEMCPY(NONE, ZuintelZufastZumemcpy) + +#elif defined(VGO_freebsd) + MEMCPY(VG_Z_LIBC_SONAME, memcpy) + MEMCPY(VG_Z_LD_ELF_SO_1, memcpy) + MEMCPY(VG_Z_LD_ELF32_SO_1, memcpy) + +#elif defined(VGO_openbsd) + MEMCPY(VG_Z_LIBC_SONAME, memcpy) + +#elif defined(VGO_darwin) +# if DARWIN_VERS <= DARWIN_10_6 + MEMCPY(VG_Z_LIBC_SONAME, memcpy) +# endif + MEMCPY(VG_Z_LIBC_SONAME, memcpyZDVARIANTZDsse3x) /* memcpy$VARIANT$sse3x */ + MEMCPY(VG_Z_LIBC_SONAME, memcpyZDVARIANTZDsse42) /* memcpy$VARIANT$sse42 */ + +#endif + + +/*---------------------- memcmp ----------------------*/ + +#define MEMCMP(soname, fnname) \ + int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \ + ( const void *s1V, const void *s2V, SizeT n ); \ + int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \ + ( const void *s1V, const void *s2V, SizeT n ) \ + { \ + int res; \ + UChar a0; \ + UChar b0; \ + const UChar* s1 = s1V; \ + const UChar* s2 = s2V; \ + \ + while (n != 0) { \ + a0 = s1[0]; \ + b0 = s2[0]; \ + s1 += 1; \ + s2 += 1; \ + res = ((int)a0) - ((int)b0); \ + if (res != 0) \ + return res; \ + n -= 1; \ + } \ + return 0; \ + } + +#if defined(VGO_linux) + MEMCMP(VG_Z_LIBC_SONAME, memcmp) + MEMCMP(VG_Z_LIBC_SONAME, bcmp) + MEMCMP(VG_Z_LD_SO_1, bcmp) + +#elif defined(VGO_freebsd) + MEMCMP(VG_Z_LIBC_SONAME, memcmp) + MEMCMP(VG_Z_LIBC_SONAME, bcmp) + +#elif defined(VGO_openbsd) + MEMCMP(VG_Z_LIBC_SONAME, memcmp) + +#elif defined(VGO_darwin) + //MEMCMP(VG_Z_LIBC_SONAME, memcmp) + //MEMCMP(VG_Z_LIBC_SONAME, bcmp) + //MEMCMP(VG_Z_DYLD, memcmp) + //MEMCMP(VG_Z_DYLD, bcmp) + +#endif + + +/*---------------------- stpcpy ----------------------*/ + +/* Copy SRC to DEST, returning the address of the terminating '\0' in + DEST. (minor variant of strcpy) */ +#define STPCPY(soname, fnname) \ + char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \ + ( char* dst, const char* src ); \ + char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \ + ( char* dst, const char* src ) \ + { \ + const HChar* src_orig = src; \ + HChar* dst_orig = dst; \ + \ + while (*src) *dst++ = *src++; \ + *dst = 0; \ + \ + /* This checks for overlap after copying, unavoidable without */ \ + /* pre-counting length... should be ok */ \ + if (is_overlap(dst_orig, \ + src_orig, \ + (Addr)dst-(Addr)dst_orig+1, \ + (Addr)src-(Addr)src_orig+1)) \ + RECORD_OVERLAP_ERROR("stpcpy", dst_orig, src_orig, 0); \ + \ + return dst; \ + } + +#if defined(VGO_linux) + STPCPY(VG_Z_LIBC_SONAME, stpcpy) + STPCPY(VG_Z_LIBC_SONAME, __GI_stpcpy) + STPCPY(VG_Z_LD_LINUX_SO_2, stpcpy) + STPCPY(VG_Z_LD_LINUX_X86_64_SO_2, stpcpy) + +#elif defined(VGO_freebsd) + STPCPY(VG_Z_LD_ELF_SO_1, stpcpy) + STPCPY(VG_Z_LD_ELF32_SO_1, stpcpy) + STPCPY(VG_Z_LIBC_SONAME, stpcpy) + +#elif defined(VGO_openbsd) + STPCPY(VG_Z_LIBC_SONAME, stpcpy) + +#elif defined(VGO_darwin) + //STPCPY(VG_Z_LIBC_SONAME, stpcpy) + //STPCPY(VG_Z_DYLD, stpcpy) + +#endif + + +/*---------------------- stpncpy ----------------------*/ + +#define STPNCPY(soname, fnname) \ + char* VG_REPLACE_FUNCTION_EZU(20420,soname,fnname) \ + ( char* dst, const char* src, SizeT n ); \ + char* VG_REPLACE_FUNCTION_EZU(20420,soname,fnname) \ + ( char* dst, const char* src, SizeT n ) \ + { \ + const HChar* src_orig = src; \ + HChar* dst_str = dst; \ + SizeT m = 0; \ + \ + while (m < n && *src) { m++; *dst++ = *src++; } \ + /* Check for overlap after copying; all n bytes of dst are relevant, */ \ + /* but only m+1 bytes of src if terminator was found */ \ + if (is_overlap(dst_str, src_orig, n, (m < n) ? m+1 : n)) \ + RECORD_OVERLAP_ERROR("stpncpy", dst, src, n); \ + dst_str = dst; \ + while (m++ < n) *dst++ = 0; /* must pad remainder with nulls */ \ + \ + return dst_str; \ + } + +#if defined(VGO_linux) + STPNCPY(VG_Z_LIBC_SONAME, stpncpy) +#endif + + +/*---------------------- memset ----------------------*/ + +/* Why are we bothering to intercept this? It seems entirely + pointless. */ + +#define MEMSET(soname, fnname) \ + void* VG_REPLACE_FUNCTION_EZU(20210,soname,fnname) \ + (void *s, Int c, SizeT n); \ + void* VG_REPLACE_FUNCTION_EZU(20210,soname,fnname) \ + (void *s, Int c, SizeT n) \ + { \ + if (sizeof(void*) == 8) { \ + Addr a = (Addr)s; \ + ULong c8 = (c & 0xFF); \ + c8 = (c8 << 8) | c8; \ + c8 = (c8 << 16) | c8; \ + c8 = (c8 << 32) | c8; \ + while ((a & 7) != 0 && n >= 1) \ + { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \ + while (n >= 8) \ + { *(ULong*)a = c8; a += 8; n -= 8; } \ + while (n >= 1) \ + { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \ + return s; \ + } else { \ + Addr a = (Addr)s; \ + UInt c4 = (c & 0xFF); \ + c4 = (c4 << 8) | c4; \ + c4 = (c4 << 16) | c4; \ + while ((a & 3) != 0 && n >= 1) \ + { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \ + while (n >= 4) \ + { *(UInt*)a = c4; a += 4; n -= 4; } \ + while (n >= 1) \ + { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \ + return s; \ + } \ + } + +#if defined(VGO_linux) + MEMSET(VG_Z_LIBC_SONAME, memset) + +#elif defined(VGO_freebsd) + MEMSET(VG_Z_LIBC_SONAME, memset) + MEMSET(VG_Z_LD_ELF_SO_1, memset) + MEMSET(VG_Z_LD_ELF32_SO_1, memset) + +#elif defined(VGO_openbsd) + MEMSET(VG_Z_LIBC_SONAME, memset) + +#elif defined(VGO_darwin) + //MEMSET(VG_Z_LIBC_SONAME, memset) + //MEMSET(VG_Z_DYLD, memset) + MEMSET(VG_Z_LIBC_SONAME, memset) + +#endif + + +/*---------------------- memmove ----------------------*/ + +/* memmove -- use the MEMMOVE defn above. */ + +#if defined(VGO_linux) + MEMMOVE(VG_Z_LIBC_SONAME, memmove) + MEMMOVE(VG_Z_LIBC_SONAME, __GI_memmove) + +#elif defined(VGO_freebsd) + MEMMOVE(VG_Z_LD_ELF_SO_1, memmove) + MEMMOVE(VG_Z_LD_ELF32_SO_1, memmove) + MEMMOVE(VG_Z_LIBC_SONAME, memmove) + +#elif defined(VGO_openbsd) + MEMMOVE(VG_Z_LIBC_SONAME, memmove) + +#elif defined(VGO_darwin) +# if DARWIN_VERS <= DARWIN_10_6 + MEMMOVE(VG_Z_LIBC_SONAME, memmove) +# endif + MEMMOVE(VG_Z_LIBC_SONAME, memmoveZDVARIANTZDsse3x) /* memmove$VARIANT$sse3x */ + MEMMOVE(VG_Z_LIBC_SONAME, memmoveZDVARIANTZDsse42) /* memmove$VARIANT$sse42 */ + +#endif + + +/*---------------------- bcopy ----------------------*/ + +#define BCOPY(soname, fnname) \ + void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \ + (const void *srcV, void *dstV, SizeT n); \ + void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \ + (const void *srcV, void *dstV, SizeT n) \ + { \ + SizeT i; \ + HChar* dst = dstV; \ + const HChar* src = srcV; \ + if (dst < src) { \ + for (i = 0; i < n; i++) \ + dst[i] = src[i]; \ + } \ + else \ + if (dst > src) { \ + for (i = 0; i < n; i++) \ + dst[n-i-1] = src[n-i-1]; \ + } \ + } + +#if defined(VGO_linux) + BCOPY(VG_Z_LIBC_SONAME, bcopy) + +#elif defined(VGO_freebsd) + BCOPY(VG_Z_LIBC_SONAME, bcopy) + BCOPY(VG_Z_LD_ELF_SO_1, bcopy) + BCOPY(VG_Z_LD_ELF32_SO_1, bcopy) + +#elif defined(VGO_openbsd) + BCOPY(VG_Z_LIBC_SONAME, bcopy) + +#elif defined(VGO_darwin) + //BCOPY(VG_Z_LIBC_SONAME, bcopy) + //BCOPY(VG_Z_DYLD, bcopy) + +#endif + + +/*-------------------- memmove_chk --------------------*/ + +/* glibc 2.5 variant of memmove which checks the dest is big enough. + There is no specific part of glibc that this is copied from. */ +#define GLIBC25___MEMMOVE_CHK(soname, fnname) \ + void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \ + (void *dstV, const void *srcV, SizeT n, SizeT destlen); \ + void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \ + (void *dstV, const void *srcV, SizeT n, SizeT destlen) \ + { \ + SizeT i; \ + HChar* dst = dstV; \ + const HChar* src = srcV; \ + if (destlen < n) \ + goto badness; \ + if (dst < src) { \ + for (i = 0; i < n; i++) \ + dst[i] = src[i]; \ + } \ + else \ + if (dst > src) { \ + for (i = 0; i < n; i++) \ + dst[n-i-1] = src[n-i-1]; \ + } \ + return dst; \ + badness: \ + VALGRIND_PRINTF_BACKTRACE( \ + "*** memmove_chk: buffer overflow detected ***: " \ + "program terminated\n"); \ + my_exit(127); \ + /*NOTREACHED*/ \ + return NULL; \ + } + +#if defined(VGO_linux) + GLIBC25___MEMMOVE_CHK(VG_Z_LIBC_SONAME, __memmove_chk) + +#elif defined(VGO_darwin) + +#endif + + +/*-------------------- strchrnul --------------------*/ + +/* Find the first occurrence of C in S or the final NUL byte. */ +#define GLIBC232_STRCHRNUL(soname, fnname) \ + char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \ + (const char* s, int c_in); \ + char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \ + (const char* s, int c_in) \ + { \ + UChar c = (UChar) c_in; \ + UChar* char_ptr = (UChar *)s; \ + while (1) { \ + if (*char_ptr == 0) return (HChar *)char_ptr; \ + if (*char_ptr == c) return (HChar *)char_ptr; \ + char_ptr++; \ + } \ + } + +#if defined(VGO_linux) + GLIBC232_STRCHRNUL(VG_Z_LIBC_SONAME, strchrnul) + +#elif defined(VGO_darwin) + +#endif + + +/*---------------------- rawmemchr ----------------------*/ + +/* Find the first occurrence of C in S. */ +#define GLIBC232_RAWMEMCHR(soname, fnname) \ + char* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \ + (const char* s, int c_in); \ + char* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \ + (const char* s, int c_in) \ + { \ + UChar c = (UChar) c_in; \ + UChar* char_ptr = (UChar *)s; \ + while (1) { \ + if (*char_ptr == c) return (HChar *)char_ptr; \ + char_ptr++; \ + } \ + } + +#if defined (VGO_linux) + GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, rawmemchr) + GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, __GI___rawmemchr) + +#elif defined(VGO_darwin) + +#endif + + +/*---------------------- strcpy_chk ----------------------*/ + +/* glibc variant of strcpy that checks the dest is big enough. + Copied from glibc-2.5/debug/test-strcpy_chk.c. */ +#define GLIBC25___STRCPY_CHK(soname,fnname) \ + char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \ + (char* dst, const char* src, SizeT len); \ + char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \ + (char* dst, const char* src, SizeT len) \ + { \ + HChar* ret = dst; \ + if (! len) \ + goto badness; \ + while ((*dst++ = *src++) != '\0') \ + if (--len == 0) \ + goto badness; \ + return ret; \ + badness: \ + VALGRIND_PRINTF_BACKTRACE( \ + "*** strcpy_chk: buffer overflow detected ***: " \ + "program terminated\n"); \ + my_exit(127); \ + /*NOTREACHED*/ \ + return NULL; \ + } + +#if defined(VGO_linux) + GLIBC25___STRCPY_CHK(VG_Z_LIBC_SONAME, __strcpy_chk) + +#elif defined(VGO_darwin) + +#endif + + +/*---------------------- stpcpy_chk ----------------------*/ + +/* glibc variant of stpcpy that checks the dest is big enough. + Copied from glibc-2.5/debug/test-stpcpy_chk.c. */ +#define GLIBC25___STPCPY_CHK(soname,fnname) \ + char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \ + (char* dst, const char* src, SizeT len); \ + char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \ + (char* dst, const char* src, SizeT len) \ + { \ + if (! len) \ + goto badness; \ + while ((*dst++ = *src++) != '\0') \ + if (--len == 0) \ + goto badness; \ + return dst - 1; \ + badness: \ + VALGRIND_PRINTF_BACKTRACE( \ + "*** stpcpy_chk: buffer overflow detected ***: " \ + "program terminated\n"); \ + my_exit(127); \ + /*NOTREACHED*/ \ + return NULL; \ + } + +#if defined(VGO_linux) + GLIBC25___STPCPY_CHK(VG_Z_LIBC_SONAME, __stpcpy_chk) + +#elif defined(VGO_darwin) + +#endif + + +/*---------------------- mempcpy ----------------------*/ + +/* mempcpy */ +#define GLIBC25_MEMPCPY(soname, fnname) \ + void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \ + ( void *dst, const void *src, SizeT len ); \ + void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \ + ( void *dst, const void *src, SizeT len ) \ + { \ + register HChar *d; \ + register HChar *s; \ + SizeT len_saved = len; \ + \ + if (len == 0) \ + return dst; \ + \ + if (is_overlap(dst, src, len, len)) \ + RECORD_OVERLAP_ERROR("mempcpy", dst, src, len); \ + \ + if ( dst > src ) { \ + d = (char *)dst + len - 1; \ + s = (char *)src + len - 1; \ + while ( len-- ) { \ + *d-- = *s--; \ + } \ + } else if ( dst < src ) { \ + d = (char *)dst; \ + s = (char *)src; \ + while ( len-- ) { \ + *d++ = *s++; \ + } \ + } \ + return (void*)( ((char*)dst) + len_saved ); \ + } + +#if defined(VGO_linux) + GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy) + GLIBC25_MEMPCPY(VG_Z_LD_SO_1, mempcpy) /* ld.so.1 */ + +#elif defined(VGO_darwin) + //GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy) + +#endif + + +/*-------------------- memcpy_chk --------------------*/ + +#define GLIBC26___MEMCPY_CHK(soname, fnname) \ + void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \ + (void* dst, const void* src, SizeT len, SizeT dstlen ); \ + void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \ + (void* dst, const void* src, SizeT len, SizeT dstlen ) \ + { \ + register HChar *d; \ + register const HChar *s; \ + \ + if (dstlen < len) goto badness; \ + \ + if (len == 0) \ + return dst; \ + \ + if (is_overlap(dst, src, len, len)) \ + RECORD_OVERLAP_ERROR("memcpy_chk", dst, src, len); \ + \ + if ( dst > src ) { \ + d = (HChar *)dst + len - 1; \ + s = (const HChar *)src + len - 1; \ + while ( len-- ) { \ + *d-- = *s--; \ + } \ + } else if ( dst < src ) { \ + d = (HChar *)dst; \ + s = (const HChar *)src; \ + while ( len-- ) { \ + *d++ = *s++; \ + } \ + } \ + return dst; \ + badness: \ + VALGRIND_PRINTF_BACKTRACE( \ + "*** memcpy_chk: buffer overflow detected ***: " \ + "program terminated\n"); \ + my_exit(127); \ + /*NOTREACHED*/ \ + return NULL; \ + } + +#if defined(VGO_linux) + GLIBC26___MEMCPY_CHK(VG_Z_LIBC_SONAME, __memcpy_chk) + +#elif defined(VGO_darwin) + +#endif + + +/*---------------------- strstr ----------------------*/ + +#define STRSTR(soname, fnname) \ + char* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \ + (const char* haystack, const char* needle); \ + char* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \ + (const char* haystack, const char* needle) \ + { \ + const HChar* h = haystack; \ + const HChar* n = needle; \ + \ + /* find the length of n, not including terminating zero */ \ + UWord nlen = 0; \ + while (n[nlen]) nlen++; \ + \ + /* if n is the empty string, match immediately. */ \ + if (nlen == 0) return (HChar *)h; \ + \ + /* assert(nlen >= 1); */ \ + HChar n0 = n[0]; \ + \ + while (1) { \ + const HChar hh = *h; \ + if (hh == 0) return NULL; \ + if (hh != n0) { h++; continue; } \ + \ + UWord i; \ + for (i = 0; i < nlen; i++) { \ + if (n[i] != h[i]) \ + break; \ + } \ + /* assert(i >= 0 && i <= nlen); */ \ + if (i == nlen) \ + return (HChar *)h; \ + \ + h++; \ + } \ + } + +#if defined(VGO_linux) + STRSTR(VG_Z_LIBC_SONAME, strstr) + +#elif defined(VGO_darwin) + +#endif + + +/*---------------------- strpbrk ----------------------*/ + +#define STRPBRK(soname, fnname) \ + char* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \ + (const char* sV, const char* acceptV); \ + char* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \ + (const char* sV, const char* acceptV) \ + { \ + const HChar* s = sV; \ + const HChar* accept = acceptV; \ + \ + /* find the length of 'accept', not including terminating zero */ \ + UWord nacc = 0; \ + while (accept[nacc]) nacc++; \ + \ + /* if n is the empty string, fail immediately. */ \ + if (nacc == 0) return NULL; \ + \ + /* assert(nacc >= 1); */ \ + while (1) { \ + UWord i; \ + HChar sc = *s; \ + if (sc == 0) \ + break; \ + for (i = 0; i < nacc; i++) { \ + if (sc == accept[i]) \ + return (HChar *)s; \ + } \ + s++; \ + } \ + \ + return NULL; \ + } + +#if defined(VGO_linux) + STRPBRK(VG_Z_LIBC_SONAME, strpbrk) + +#elif defined(VGO_darwin) + +#endif + + +/*---------------------- strcspn ----------------------*/ + +#define STRCSPN(soname, fnname) \ + SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \ + (const char* sV, const char* rejectV); \ + SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \ + (const char* sV, const char* rejectV) \ + { \ + const HChar* s = sV; \ + const HChar* reject = rejectV; \ + \ + /* find the length of 'reject', not including terminating zero */ \ + UWord nrej = 0; \ + while (reject[nrej]) nrej++; \ + \ + UWord len = 0; \ + while (1) { \ + UWord i; \ + HChar sc = *s; \ + if (sc == 0) \ + break; \ + for (i = 0; i < nrej; i++) { \ + if (sc == reject[i]) \ + break; \ + } \ + /* assert(i >= 0 && i <= nrej); */ \ + if (i < nrej) \ + break; \ + s++; \ + len++; \ + } \ + \ + return len; \ + } + +#if defined(VGO_linux) + STRCSPN(VG_Z_LIBC_SONAME, strcspn) + +#elif defined(VGO_darwin) + +#endif + + +/*---------------------- strspn ----------------------*/ + +#define STRSPN(soname, fnname) \ + SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \ + (const char* sV, const char* acceptV); \ + SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \ + (const char* sV, const char* acceptV) \ + { \ + const UChar* s = (const UChar *)sV; \ + const UChar* accept = (const UChar *)acceptV; \ + \ + /* find the length of 'accept', not including terminating zero */ \ + UWord nacc = 0; \ + while (accept[nacc]) nacc++; \ + if (nacc == 0) return 0; \ + \ + UWord len = 0; \ + while (1) { \ + UWord i; \ + HChar sc = *s; \ + if (sc == 0) \ + break; \ + for (i = 0; i < nacc; i++) { \ + if (sc == accept[i]) \ + break; \ + } \ + /* assert(i >= 0 && i <= nacc); */ \ + if (i == nacc) \ + break; \ + s++; \ + len++; \ + } \ + \ + return len; \ + } + +#if defined(VGO_linux) + STRSPN(VG_Z_LIBC_SONAME, strspn) + +#elif defined(VGO_darwin) + +#endif + + +/*---------------------- strcasestr ----------------------*/ + +#define STRCASESTR(soname, fnname) \ + char* VG_REPLACE_FUNCTION_EZU(20350,soname,fnname) \ + (const char* haystack, const char* needle); \ + char* VG_REPLACE_FUNCTION_EZU(20350,soname,fnname) \ + (const char* haystack, const char* needle) \ + { \ + extern int tolower(int); \ + const HChar* h = haystack; \ + const HChar* n = needle; \ + \ + /* find the length of n, not including terminating zero */ \ + UWord nlen = 0; \ + while (n[nlen]) nlen++; \ + \ + /* if n is the empty string, match immediately. */ \ + if (nlen == 0) return (HChar *)h; \ + \ + /* assert(nlen >= 1); */ \ + UChar n0 = tolower(n[0]); \ + \ + while (1) { \ + UChar hh = tolower(*h); \ + if (hh == 0) return NULL; \ + if (hh != n0) { h++; continue; } \ + \ + UWord i; \ + for (i = 0; i < nlen; i++) { \ + if (tolower(n[i]) != tolower(h[i])) \ + break; \ + } \ + /* assert(i >= 0 && i <= nlen); */ \ + if (i == nlen) \ + return (HChar *)h; \ + \ + h++; \ + } \ + } + +#if defined(VGO_linux) +# if !defined(VGPV_arm_linux_android) && !defined(VGPV_x86_linux_android) + STRCASESTR(VG_Z_LIBC_SONAME, strcasestr) +# endif + +#elif defined(VGO_darwin) + +#endif + + +/*---------------------- wcslen ----------------------*/ + +// This is a wchar_t equivalent to strlen. Unfortunately +// we don't have wchar_t available here, but it looks like +// a 32 bit int on Linux. I don't know if that is also +// valid on MacOSX. + +#define WCSLEN(soname, fnname) \ + SizeT VG_REPLACE_FUNCTION_EZU(20370,soname,fnname) \ + ( const UInt* str ); \ + SizeT VG_REPLACE_FUNCTION_EZU(20370,soname,fnname) \ + ( const UInt* str ) \ + { \ + SizeT i = 0; \ + while (str[i] != 0) i++; \ + return i; \ + } + +#if defined(VGO_linux) + WCSLEN(VG_Z_LIBC_SONAME, wcslen) + +#elif defined(VGO_darwin) + +#endif + +/*---------------------- wcscmp ----------------------*/ + +// This is a wchar_t equivalent to strcmp. We don't +// have wchar_t available here, but in the GNU C Library +// wchar_t is always 32 bits wide and wcscmp uses signed +// comparison, not unsigned as in strcmp function. + +#define WCSCMP(soname, fnname) \ + int VG_REPLACE_FUNCTION_EZU(20380,soname,fnname) \ + ( const Int* s1, const Int* s2 ); \ + int VG_REPLACE_FUNCTION_EZU(20380,soname,fnname) \ + ( const Int* s1, const Int* s2 ) \ + { \ + register Int c1; \ + register Int c2; \ + while (True) { \ + c1 = *s1; \ + c2 = *s2; \ + if (c1 != c2) break; \ + if (c1 == 0) break; \ + s1++; s2++; \ + } \ + if (c1 < c2) return -1; \ + if (c1 > c2) return 1; \ + return 0; \ + } + +#if defined(VGO_linux) + WCSCMP(VG_Z_LIBC_SONAME, wcscmp) +#endif + +/*---------------------- wcscpy ----------------------*/ + +// This is a wchar_t equivalent to strcpy. We don't +// have wchar_t available here, but in the GNU C Library +// wchar_t is always 32 bits wide. + +#define WCSCPY(soname, fnname) \ + Int* VG_REPLACE_FUNCTION_EZU(20390,soname,fnname) \ + ( Int* dst, const Int* src ); \ + Int* VG_REPLACE_FUNCTION_EZU(20390,soname,fnname) \ + ( Int* dst, const Int* src ) \ + { \ + const Int* src_orig = src; \ + Int* dst_orig = dst; \ + \ + while (*src) *dst++ = *src++; \ + *dst = 0; \ + \ + /* This checks for overlap after copying, unavoidable without */ \ + /* pre-counting length... should be ok */ \ + if (is_overlap(dst_orig, \ + src_orig, \ + (Addr)dst-(Addr)dst_orig+1, \ + (Addr)src-(Addr)src_orig+1)) \ + RECORD_OVERLAP_ERROR("wcscpy", dst_orig, src_orig, 0); \ + \ + return dst_orig; \ + } + +#if defined(VGO_linux) + WCSCPY(VG_Z_LIBC_SONAME, wcscpy) +#endif + + +/*---------------------- wcschr ----------------------*/ + +// This is a wchar_t equivalent to strchr. We don't +// have wchar_t available here, but in the GNU C Library +// wchar_t is always 32 bits wide. + +#define WCSCHR(soname, fnname) \ + Int* VG_REPLACE_FUNCTION_EZU(20400,soname,fnname) ( const Int* s, Int c ); \ + Int* VG_REPLACE_FUNCTION_EZU(20400,soname,fnname) ( const Int* s, Int c ) \ + { \ + Int* p = (Int*)s; \ + while (True) { \ + if (*p == c) return p; \ + if (*p == 0) return NULL; \ + p++; \ + } \ + } + +#if defined(VGO_linux) + WCSCHR(VG_Z_LIBC_SONAME, wcschr) +#endif +/*---------------------- wcsrchr ----------------------*/ + +// This is a wchar_t equivalent to strrchr. We don't +// have wchar_t available here, but in the GNU C Library +// wchar_t is always 32 bits wide. + +#define WCSRCHR(soname, fnname) \ + Int* VG_REPLACE_FUNCTION_EZU(20410,soname,fnname)( const Int* s, Int c ); \ + Int* VG_REPLACE_FUNCTION_EZU(20410,soname,fnname)( const Int* s, Int c ) \ + { \ + Int* p = (Int*) s; \ + Int* last = NULL; \ + while (True) { \ + if (*p == c) last = p; \ + if (*p == 0) return last; \ + p++; \ + } \ + } + +#if defined(VGO_linux) + WCSRCHR(VG_Z_LIBC_SONAME, wcsrchr) +#endif + +/*------------------------------------------------------------*/ +/*--- Improve definedness checking of process environment ---*/ +/*------------------------------------------------------------*/ + +#if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd) + +/* If these wind up getting generated via a macro, so that multiple + versions of each function exist (as above), use the _EZU variants + to assign equivalance class tags. */ + +/*---------------------- putenv ----------------------*/ + +int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string); +int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string) +{ + OrigFn fn; + Word result; + const HChar* p = string; + VALGRIND_GET_ORIG_FN(fn); + /* Now by walking over the string we magically produce + traces when hitting undefined memory. */ + if (p) + while (*p++) + __asm__ __volatile__("" ::: "memory"); + CALL_FN_W_W(result, fn, string); + return result; +} + + +/*---------------------- unsetenv ----------------------*/ + +int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name); +int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name) +{ + OrigFn fn; + Word result; + const HChar* p = name; + VALGRIND_GET_ORIG_FN(fn); + /* Now by walking over the string we magically produce + traces when hitting undefined memory. */ + if (p) + while (*p++) + __asm__ __volatile__("" ::: "memory"); + CALL_FN_W_W(result, fn, name); + return result; +} + + +/*---------------------- setenv ----------------------*/ + +/* setenv */ +int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv) + (const char* name, const char* value, int overwrite); +int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv) + (const char* name, const char* value, int overwrite) +{ + OrigFn fn; + Word result; + const HChar* p; + VALGRIND_GET_ORIG_FN(fn); + /* Now by walking over the string we magically produce + traces when hitting undefined memory. */ + if (name) + for (p = name; *p; p++) + __asm__ __volatile__("" ::: "memory"); + if (value) + for (p = value; *p; p++) + __asm__ __volatile__("" ::: "memory"); + (void) VALGRIND_CHECK_VALUE_IS_DEFINED (overwrite); + CALL_FN_W_WWW(result, fn, name, value, overwrite); + return result; +} + +#endif /* defined(VGO_linux) */ + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ +#endif diff -r efb6377bb4b5 -r ae0a1b9f3c43 memcheck/tests/Makefile.am --- a/memcheck/tests/Makefile.am Mon Dec 01 23:44:20 2014 +0900 +++ b/memcheck/tests/Makefile.am Thu Mar 31 15:57:55 2016 +0900 @@ -113,6 +113,7 @@ execve2.stderr.exp execve2.vgtest execve2.stderr.exp-kfail \ file_locking.stderr.exp file_locking.vgtest \ fprw.stderr.exp fprw.stderr.exp-mips32-be fprw.stderr.exp-mips32-le \ + fprw.stderr.exp-freebsd \ fprw.vgtest \ fwrite.stderr.exp fwrite.vgtest fwrite.stderr.exp-kfail \ holey_buffer_too_small.vgtest holey_buffer_too_small.stdout.exp \ @@ -188,6 +189,7 @@ origin5-bz2.stderr.exp-glibc212-s390x \ origin5-bz2.stderr.exp-glibc234-s390x \ origin5-bz2.stderr.exp-glibc218-mips32 \ + origin5-bz2.stderr.exp-freebsd \ origin6-fp.vgtest origin6-fp.stdout.exp \ origin6-fp.stderr.exp-glibc25-amd64 \ origin6-fp.stderr.exp-glibc27-ppc64 \ @@ -222,7 +224,7 @@ sh-mem-random.stderr.exp sh-mem-random.stdout.exp64 \ sh-mem-random.stdout.exp sh-mem-random.vgtest \ sigaltstack.stderr.exp sigaltstack.vgtest \ - sigkill.stderr.exp sigkill.stderr.exp-darwin sigkill.stderr.exp-mips32 \ + sigkill.stderr.exp sigkill.stderr.exp-darwin sigkill.stderr.exp-freebsd sigkill.stderr.exp-mips32 \ sigkill.vgtest \ signal2.stderr.exp signal2.stdout.exp signal2.vgtest \ sigprocmask.stderr.exp sigprocmask.stderr.exp2 sigprocmask.vgtest \ diff -r efb6377bb4b5 -r ae0a1b9f3c43 memcheck/tests/addressable.c --- a/memcheck/tests/addressable.c Mon Dec 01 23:44:20 2014 +0900 +++ b/memcheck/tests/addressable.c Thu Mar 31 15:57:55 2016 +0900 @@ -2,6 +2,7 @@ #include "../memcheck.h" #include "tests/sys_mman.h" #include +#include #include #include #include @@ -9,12 +10,13 @@ #include #include #include +#include static int pgsz; static char *mm(char *addr, int size, int prot) { - int flags = MAP_PRIVATE | MAP_ANONYMOUS; + int flags = MAP_PRIVATE | MAP_ANON; char *ret; if (addr) diff -r efb6377bb4b5 -r ae0a1b9f3c43 memcheck/tests/addressable.stderr.exp --- a/memcheck/tests/addressable.stderr.exp Mon Dec 01 23:44:20 2014 +0900 +++ b/memcheck/tests/addressable.stderr.exp Thu Mar 31 15:57:55 2016 +0900 @@ -9,49 +9,16 @@ For counts of detected and suppressed errors, rerun with: -v ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) Unaddressable byte(s) found during client check request - at 0x........: test2 (addressable.c:48) - by 0x........: main (addressable.c:125) + at 0x........: test2 (addressable.c:50) + by 0x........: main (addressable.c:127) Address 0x........ is not stack'd, malloc'd or (recently) free'd Invalid write of size 1 - at 0x........: test2 (addressable.c:51) - by 0x........: main (addressable.c:125) + at 0x........: test2 (addressable.c:53) + by 0x........: main (addressable.c:127) Address 0x........ is not stack'd, malloc'd or (recently) free'd -Process terminating with default action of signal N (SIGSEGV or SIGBUS) - Bad memory (SIGSEGV or SIGBUS) at address 0x........ - at 0x........: test2 (addressable.c:51) - by 0x........: main (addressable.c:125) - If you believe this happened as a result of a stack - overflow in your program's main thread (unlikely but - possible), you can try to increase the size of the - main thread stack using the --main-stacksize= flag. - The main thread stack size used in this run was .... - -HEAP SUMMARY: - in use at exit: ... bytes in ... blocks - total heap usage: ... allocs, ... frees, ... bytes allocated - -For a detailed leak analysis, rerun with: --leak-check=full - -For counts of detected and suppressed errors, rerun with: -v -ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) - -HEAP SUMMARY: - in use at exit: ... bytes in ... blocks - total heap usage: ... allocs, ... frees, ... bytes allocated - -For a detailed leak analysis, rerun with: --leak-check=full - -For counts of detected and suppressed errors, rerun with: -v -ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) - -Process terminating with default action of signal N (SIGSEGV or SIGBUS) - Bad memory (SIGSEGV or SIGBUS) at address 0x........ - at 0x........: test4 (addressable.c:74) - by 0x........: main (addressable.c:125) - HEAP SUMMARY: in use at exit: ... bytes in ... blocks total heap usage: ... allocs, ... frees, ... bytes allocated @@ -61,13 +28,13 @@ For counts of detected and suppressed errors, rerun with: -v ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) Uninitialised byte(s) found during client check request - at 0x........: test5 (addressable.c:85) - by 0x........: main (addressable.c:125) + at 0x........: test5 (addressable.c:87) + by 0x........: main (addressable.c:127) Address 0x........ is not stack'd, malloc'd or (recently) free'd Uninitialised byte(s) found during client check request - at 0x........: test5 (addressable.c:91) - by 0x........: main (addressable.c:125) + at 0x........: test5 (addressable.c:93) + by 0x........: main (addressable.c:127) Address 0x........ is not stack'd, malloc'd or (recently) free'd diff -r efb6377bb4b5 -r ae0a1b9f3c43 memcheck/tests/amd64/Makefile.am --- a/memcheck/tests/amd64/Makefile.am Mon Dec 01 23:44:20 2014 +0900 +++ b/memcheck/tests/amd64/Makefile.am Thu Mar 31 15:57:55 2016 +0900 @@ -32,7 +32,7 @@ sh-mem-vec256-plo-yes.stdout.exp \ sse_memory.stderr.exp sse_memory.stdout.exp sse_memory.vgtest \ xor-undef-amd64.stderr.exp xor-undef-amd64.stdout.exp \ - xor-undef-amd64.vgtest + xor-undef-amd64.stderr.exp-freebsd xor-undef-amd64.vgtest check_PROGRAMS = \ bt_everything \ diff -r efb6377bb4b5 -r ae0a1b9f3c43 memcheck/tests/amd64/xor-undef-amd64.stderr.exp-freebsd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memcheck/tests/amd64/xor-undef-amd64.stderr.exp-freebsd Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,26 @@ + +Conditional jump or move depends on uninitialised value(s) + at 0x........: main (xor-undef-amd64.c:17) + +Conditional jump or move depends on uninitialised value(s) + at 0x........: main (xor-undef-amd64.c:38) + +Conditional jump or move depends on uninitialised value(s) + at 0x........: main (xor-undef-amd64.c:65) + +Conditional jump or move depends on uninitialised value(s) + at 0x........: main (xor-undef-amd64.c:92) + +Conditional jump or move depends on uninitialised value(s) + at 0x........: main (xor-undef-amd64.c:117) + + +HEAP SUMMARY: + in use at exit: 4,096 bytes in 1 blocks + total heap usage: 2 allocs, 1 frees, 4,144 bytes allocated + +For a detailed leak analysis, rerun with: --leak-check=full + +For counts of detected and suppressed errors, rerun with: -v +Use --track-origins=yes to see where uninitialised values come from +ERROR SUMMARY: 5 errors from 5 contexts (suppressed: 0 from 0) diff -r efb6377bb4b5 -r ae0a1b9f3c43 memcheck/tests/badjump2.c --- a/memcheck/tests/badjump2.c Mon Dec 01 23:44:20 2014 +0900 +++ b/memcheck/tests/badjump2.c Thu Mar 31 15:57:55 2016 +0900 @@ -22,9 +22,10 @@ int res; /* Install own SIGSEGV handler */ + memset(&sigsegv_new, 0, sizeof(sigsegv_new)); sigsegv_new.sa_handler = SIGSEGV_handler; sigsegv_new.sa_flags = 0; -#if !defined(__APPLE__) +#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) sigsegv_new.sa_restorer = NULL; #endif res = sigemptyset( &sigsegv_new.sa_mask ); diff -r efb6377bb4b5 -r ae0a1b9f3c43 memcheck/tests/badjump2.stderr.exp --- a/memcheck/tests/badjump2.stderr.exp Mon Dec 01 23:44:20 2014 +0900 +++ b/memcheck/tests/badjump2.stderr.exp Thu Mar 31 15:57:55 2016 +0900 @@ -1,6 +1,6 @@ Jump to the invalid address stated on the next line ... - by 0x........: main (badjump2.c:46) + by 0x........: main (badjump2.c:47) Address 0x........ is not stack'd, malloc'd or (recently) free'd Signal caught, as expected diff -r efb6377bb4b5 -r ae0a1b9f3c43 memcheck/tests/buflen_check.c --- a/memcheck/tests/buflen_check.c Mon Dec 01 23:44:20 2014 +0900 +++ b/memcheck/tests/buflen_check.c Thu Mar 31 15:57:55 2016 +0900 @@ -1,3 +1,4 @@ +#include #include #include #include diff -r efb6377bb4b5 -r ae0a1b9f3c43 memcheck/tests/buflen_check.stderr.exp --- a/memcheck/tests/buflen_check.stderr.exp Mon Dec 01 23:44:20 2014 +0900 +++ b/memcheck/tests/buflen_check.stderr.exp Thu Mar 31 15:57:55 2016 +0900 @@ -1,11 +1,11 @@ Syscall param socketcall.getsockname(name) points to unaddressable byte(s) ... - by 0x........: main (buflen_check.c:18) + by 0x........: main (buflen_check.c:19) Address 0x........ is not stack'd, malloc'd or (recently) free'd Syscall param socketcall.getsockname(namelen_in) points to unaddressable byte(s) ... - by 0x........: main (buflen_check.c:19) + by 0x........: main (buflen_check.c:20) Address 0x........ is not stack'd, malloc'd or (recently) free'd getsockname(1) failed diff -r efb6377bb4b5 -r ae0a1b9f3c43 memcheck/tests/fprw.stderr.exp-freebsd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memcheck/tests/fprw.stderr.exp-freebsd Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,41 @@ +Conditional jump or move depends on uninitialised value(s) + at 0x........: main (fprw.c:16) + +Conditional jump or move depends on uninitialised value(s) + at 0x........: main (fprw.c:17) + +Invalid read of size 8 + at 0x........: main (fprw.c:20) + Address 0x........ is 0 bytes inside a block of size 8 free'd + at 0x........: free (vg_replace_malloc.c:...) + by 0x........: main (fprw.c:18) + +Invalid write of size 8 + at 0x........: main (fprw.c:20) + Address 0x........ is 0 bytes inside a block of size 8 free'd + at 0x........: free (vg_replace_malloc.c:...) + by 0x........: main (fprw.c:18) + +Invalid read of size 4 + at 0x........: main (fprw.c:21) + Address 0x........ is 0 bytes inside a block of size 4 free'd + at 0x........: free (vg_replace_malloc.c:...) + by 0x........: main (fprw.c:19) + +Invalid write of size 4 + at 0x........: main (fprw.c:21) + Address 0x........ is 0 bytes inside a block of size 4 free'd + at 0x........: free (vg_replace_malloc.c:...) + by 0x........: main (fprw.c:19) + +Invalid free() / delete / delete[] / realloc() + at 0x........: free (vg_replace_malloc.c:...) + by 0x........: main (fprw.c:22) + Address 0x........ is in the PLT segment of /lib/libc.so.7 + +Invalid write of size 8 + at 0x........: main (fprw.c:24) + Address 0x........ is 0 bytes inside a block of size 4 alloc'd + at 0x........: malloc (vg_replace_malloc.c:...) + by 0x........: main (fprw.c:23) + diff -r efb6377bb4b5 -r ae0a1b9f3c43 memcheck/tests/memalign2.c --- a/memcheck/tests/memalign2.c Mon Dec 01 23:44:20 2014 +0900 +++ b/memcheck/tests/memalign2.c Thu Mar 31 15:57:55 2016 +0900 @@ -30,6 +30,7 @@ int res; assert(sizeof(long int) == sizeof(void*)); +#if !defined(__FreeBSD__) // Check behaviour of memalign/free for big alignment. // In particular, the below aims at checking that a // superblock with a big size is not marked as reclaimable @@ -78,11 +79,13 @@ p = memalign(4 * 1024 * 1024, 100); assert(0 == (long)p % (4 * 1024 * 1024)); p = memalign(16 * 1024 * 1024, 100); assert(0 == (long)p % (16 * 1024 * 1024)); +#endif # define PM(a,b,c) posix_memalign((void**)a, b, c) +#if !defined(__FreeBSD__) || __FreeBSD__ >= 6 res = PM(&p, -1,100); assert(EINVAL == res); - res = PM(&p, 0, 100); assert(0 == res && 0 == (long)p % 8); +// res = PM(&p, 0, 100); assert(EINVAL == res); res = PM(&p, 1, 100); assert(EINVAL == res); res = PM(&p, 2, 100); assert(EINVAL == res); res = PM(&p, 3, 100); assert(EINVAL == res); @@ -101,6 +104,7 @@ && 0 == (long)p % (4 * 1024 * 1024)); res = PM(&p, 16 * 1024 * 1024, 100); assert(0 == res && 0 == (long)p % (16 * 1024 * 1024)); +#endif # endif return 0; diff -r efb6377bb4b5 -r ae0a1b9f3c43 memcheck/tests/mempool.c --- a/memcheck/tests/mempool.c Mon Dec 01 23:44:20 2014 +0900 +++ b/memcheck/tests/mempool.c Thu Mar 31 15:57:55 2016 +0900 @@ -35,10 +35,10 @@ if(USE_MMAP) { p = (pool *)mmap(0, sizeof(pool), PROT_READ|PROT_WRITE|PROT_EXEC, - MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); + MAP_PRIVATE|MAP_ANON, -1, 0); p->where = p->mem = (char *)mmap(NULL, SUPERBLOCK_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, - MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); + MAP_PRIVATE|MAP_ANON, -1, 0); } else { p = (pool *)malloc(sizeof(pool)); p->where = p->mem = (char *)malloc(SUPERBLOCK_SIZE); @@ -57,7 +57,7 @@ if(USE_MMAP) l = (level_list *)mmap(0, sizeof(level_list), PROT_READ|PROT_WRITE|PROT_EXEC, - MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); + MAP_PRIVATE|MAP_ANON, -1, 0); else l = (level_list *)malloc(sizeof(level_list)); diff -r efb6377bb4b5 -r ae0a1b9f3c43 memcheck/tests/noisy_child.stderr.exp --- a/memcheck/tests/noisy_child.stderr.exp Mon Dec 01 23:44:20 2014 +0900 +++ b/memcheck/tests/noisy_child.stderr.exp Thu Mar 31 15:57:55 2016 +0900 @@ -12,6 +12,14 @@ at 0x........: free (vg_replace_malloc.c:...) by 0x........: main (noisy_child.c:24) +Invalid free() / delete / delete[] / realloc() + at 0x........: free (vg_replace_malloc.c:...) + by 0x........: do_child_badness (noisy_child.c:10) + by 0x........: main (noisy_child.c:34) + Address 0x........ is 0 bytes inside a block of size 10 free'd + at 0x........: free (vg_replace_malloc.c:...) + by 0x........: main (noisy_child.c:24) + HEAP SUMMARY: in use at exit: ... bytes in ... blocks @@ -21,3 +29,12 @@ For counts of detected and suppressed errors, rerun with: -v ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) + +HEAP SUMMARY: + in use at exit: ... bytes in ... blocks + total heap usage: ... allocs, ... frees, ... bytes allocated + +For a detailed leak analysis, rerun with: --leak-check=full + +For counts of detected and suppressed errors, rerun with: -v +ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) diff -r efb6377bb4b5 -r ae0a1b9f3c43 memcheck/tests/origin5-bz2.stderr.exp-freebsd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memcheck/tests/origin5-bz2.stderr.exp-freebsd Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,131 @@ +Conditional jump or move depends on uninitialised value(s) + at 0x........: main (origin5-bz2.c:6481) + Uninitialised value was created by a client request + at 0x........: main (origin5-bz2.c:6479) + +Conditional jump or move depends on uninitialised value(s) + at 0x........: copy_input_until_stop (origin5-bz2.c:4686) + by 0x........: handle_compress (origin5-bz2.c:4750) + by 0x........: BZ2_bzCompress (origin5-bz2.c:4822) + by 0x........: BZ2_bzBuffToBuffCompress (origin5-bz2.c:5630) + by 0x........: main (origin5-bz2.c:6484) + Uninitialised value was created by a client request + at 0x........: main (origin5-bz2.c:6479) + +Use of uninitialised value of size 8 + at 0x........: copy_input_until_stop (origin5-bz2.c:4686) + by 0x........: handle_compress (origin5-bz2.c:4750) + by 0x........: BZ2_bzCompress (origin5-bz2.c:4822) + by 0x........: BZ2_bzBuffToBuffCompress (origin5-bz2.c:5630) + by 0x........: main (origin5-bz2.c:6484) + Uninitialised value was created by a client request + at 0x........: main (origin5-bz2.c:6479) + +Use of uninitialised value of size 8 + at 0x........: copy_input_until_stop (origin5-bz2.c:4686) + by 0x........: handle_compress (origin5-bz2.c:4750) + by 0x........: BZ2_bzCompress (origin5-bz2.c:4822) + by 0x........: BZ2_bzBuffToBuffCompress (origin5-bz2.c:5630) + by 0x........: main (origin5-bz2.c:6484) + Uninitialised value was created by a client request + at 0x........: main (origin5-bz2.c:6479) + +Use of uninitialised value of size 8 + at 0x........: mainSort (origin5-bz2.c:2820) + by 0x........: BZ2_blockSort (origin5-bz2.c:3105) + by 0x........: BZ2_compressBlock (origin5-bz2.c:4034) + by 0x........: handle_compress (origin5-bz2.c:4753) + by 0x........: BZ2_bzCompress (origin5-bz2.c:4822) + by 0x........: BZ2_bzBuffToBuffCompress (origin5-bz2.c:5630) + by 0x........: main (origin5-bz2.c:6484) + Uninitialised value was created by a client request + at 0x........: main (origin5-bz2.c:6479) + +Use of uninitialised value of size 8 + at 0x........: mainSort (origin5-bz2.c:2823) + by 0x........: BZ2_blockSort (origin5-bz2.c:3105) + by 0x........: BZ2_compressBlock (origin5-bz2.c:4034) + by 0x........: handle_compress (origin5-bz2.c:4753) + by 0x........: BZ2_bzCompress (origin5-bz2.c:4822) + by 0x........: BZ2_bzBuffToBuffCompress (origin5-bz2.c:5630) + by 0x........: main (origin5-bz2.c:6484) + Uninitialised value was created by a client request + at 0x........: main (origin5-bz2.c:6479) + +Use of uninitialised value of size 8 + at 0x........: mainSort (origin5-bz2.c:2854) + by 0x........: BZ2_blockSort (origin5-bz2.c:3105) + by 0x........: BZ2_compressBlock (origin5-bz2.c:4034) + by 0x........: handle_compress (origin5-bz2.c:4753) + by 0x........: BZ2_bzCompress (origin5-bz2.c:4822) + by 0x........: BZ2_bzBuffToBuffCompress (origin5-bz2.c:5630) + by 0x........: main (origin5-bz2.c:6484) + Uninitialised value was created by a client request + at 0x........: main (origin5-bz2.c:6479) + +Use of uninitialised value of size 8 + at 0x........: mainSort (origin5-bz2.c:2858) + by 0x........: BZ2_blockSort (origin5-bz2.c:3105) + by 0x........: BZ2_compressBlock (origin5-bz2.c:4034) + by 0x........: handle_compress (origin5-bz2.c:4753) + by 0x........: BZ2_bzCompress (origin5-bz2.c:4822) + by 0x........: BZ2_bzBuffToBuffCompress (origin5-bz2.c:5630) + by 0x........: main (origin5-bz2.c:6484) + Uninitialised value was created by a client request + at 0x........: main (origin5-bz2.c:6479) + +Use of uninitialised value of size 8 + at 0x........: mainSort (origin5-bz2.c:2963) + by 0x........: BZ2_blockSort (origin5-bz2.c:3105) + by 0x........: BZ2_compressBlock (origin5-bz2.c:4034) + by 0x........: handle_compress (origin5-bz2.c:4753) + by 0x........: BZ2_bzCompress (origin5-bz2.c:4822) + by 0x........: BZ2_bzBuffToBuffCompress (origin5-bz2.c:5630) + by 0x........: main (origin5-bz2.c:6484) + Uninitialised value was created by a client request + at 0x........: main (origin5-bz2.c:6479) + +Use of uninitialised value of size 8 + at 0x........: mainSort (origin5-bz2.c:2964) + by 0x........: BZ2_blockSort (origin5-bz2.c:3105) + by 0x........: BZ2_compressBlock (origin5-bz2.c:4034) + by 0x........: handle_compress (origin5-bz2.c:4753) + by 0x........: BZ2_bzCompress (origin5-bz2.c:4822) + by 0x........: BZ2_bzBuffToBuffCompress (origin5-bz2.c:5630) + by 0x........: main (origin5-bz2.c:6484) + Uninitialised value was created by a client request + at 0x........: main (origin5-bz2.c:6479) + +Use of uninitialised value of size 8 + at 0x........: fallbackSort (origin5-bz2.c:2269) + by 0x........: BZ2_blockSort (origin5-bz2.c:3116) + by 0x........: BZ2_compressBlock (origin5-bz2.c:4034) + by 0x........: handle_compress (origin5-bz2.c:4753) + by 0x........: BZ2_bzCompress (origin5-bz2.c:4822) + by 0x........: BZ2_bzBuffToBuffCompress (origin5-bz2.c:5630) + by 0x........: main (origin5-bz2.c:6484) + Uninitialised value was created by a client request + at 0x........: main (origin5-bz2.c:6479) + +Use of uninitialised value of size 8 + at 0x........: fallbackSort (origin5-bz2.c:2275) + by 0x........: BZ2_blockSort (origin5-bz2.c:3116) + by 0x........: BZ2_compressBlock (origin5-bz2.c:4034) + by 0x........: handle_compress (origin5-bz2.c:4753) + by 0x........: BZ2_bzCompress (origin5-bz2.c:4822) + by 0x........: BZ2_bzBuffToBuffCompress (origin5-bz2.c:5630) + by 0x........: main (origin5-bz2.c:6484) + Uninitialised value was created by a client request + at 0x........: main (origin5-bz2.c:6479) + +Conditional jump or move depends on uninitialised value(s) + at 0x........: main (origin5-bz2.c:6512) + Uninitialised value was created by a heap allocation + at 0x........: malloc (vg_replace_malloc.c:...) + by 0x........: g_serviceFn (origin5-bz2.c:6429) + by 0x........: default_bzalloc (origin5-bz2.c:4470) + by 0x........: BZ2_decompress (origin5-bz2.c:1578) + by 0x........: BZ2_bzDecompress (origin5-bz2.c:5192) + by 0x........: BZ2_bzBuffToBuffDecompress (origin5-bz2.c:5678) + by 0x........: main (origin5-bz2.c:6498) + diff -r efb6377bb4b5 -r ae0a1b9f3c43 memcheck/tests/pointer-trace.c --- a/memcheck/tests/pointer-trace.c Mon Dec 01 23:44:20 2014 +0900 +++ b/memcheck/tests/pointer-trace.c Thu Mar 31 15:57:55 2016 +0900 @@ -14,6 +14,10 @@ # define MAP_NORESERVE 0 #endif +#if !defined(MAP_ANONYMOUS) +# define MAP_ANONYMOUS MAP_ANON +#endif + int main() { char **volatile ptrs; diff -r efb6377bb4b5 -r ae0a1b9f3c43 memcheck/tests/pointer-trace.stderr.exp --- a/memcheck/tests/pointer-trace.stderr.exp Mon Dec 01 23:44:20 2014 +0900 +++ b/memcheck/tests/pointer-trace.stderr.exp Thu Mar 31 15:57:55 2016 +0900 @@ -1,4 +1,4 @@ 1,000 bytes in 1 blocks are definitely lost in loss record ... of ... at 0x........: malloc (vg_replace_malloc.c:...) - by 0x........: main (pointer-trace.c:86) + by 0x........: main (pointer-trace.c:90) diff -r efb6377bb4b5 -r ae0a1b9f3c43 memcheck/tests/sendmsg.c --- a/memcheck/tests/sendmsg.c Mon Dec 01 23:44:20 2014 +0900 +++ b/memcheck/tests/sendmsg.c Thu Mar 31 15:57:55 2016 +0900 @@ -1,10 +1,12 @@ -#include #include #include #include #include #include +#include +#include + #define PORT 12345 int diff -r efb6377bb4b5 -r ae0a1b9f3c43 memcheck/tests/sendmsg.stderr.exp-freebsd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memcheck/tests/sendmsg.stderr.exp-freebsd Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,16 @@ +Syscall param socketcall.connect(serv_addr..sa_len) points to uninitialised byte(s) + ... + by 0x........: main (sendmsg.c:30) + Address 0x........ is on thread 1's stack + +Syscall param sendmsg(sendmsg) points to uninitialised byte(s) + at 0x........: sendmsg (in /...libc...) + by 0x........: main (sendmsg.c:47) + Address 0x........ is on thread 1's stack + +Syscall param socketcall.connect(serv_addr..sa_len) points to uninitialised byte(s) + ... + by 0x........: main (sendmsg.c:60) + Address 0x........ is on thread 1's stack + +sendmsg: 6 diff -r efb6377bb4b5 -r ae0a1b9f3c43 memcheck/tests/sh-mem-random.c --- a/memcheck/tests/sh-mem-random.c Mon Dec 01 23:44:20 2014 +0900 +++ b/memcheck/tests/sh-mem-random.c Thu Mar 31 15:57:55 2016 +0900 @@ -244,7 +244,7 @@ for (tries = 0; tries < 10; tries++) { arr = mmap(huge_addr, nbytes_p, PROT_READ|PROT_WRITE, - MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1,0); + MAP_FIXED|MAP_PRIVATE|MAP_ANON, -1,0); if (arr != MAP_FAILED) break; // hmm. fudge the address and try again. diff -r efb6377bb4b5 -r ae0a1b9f3c43 memcheck/tests/sigkill.stderr.exp-freebsd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memcheck/tests/sigkill.stderr.exp-freebsd Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,197 @@ + +setting signal 1: Success +getting signal 1: Success + +setting signal 2: Success +getting signal 2: Success + +setting signal 3: Success +getting signal 3: Success + +setting signal 4: Success +getting signal 4: Success + +setting signal 5: Success +getting signal 5: Success + +setting signal 6: Success +getting signal 6: Success + +setting signal 7: Success +getting signal 7: Success + +setting signal 8: Success +getting signal 8: Success + +setting signal 9: Warning: ignored attempt to set SIGKILL handler in sigaction(); + the SIGKILL signal is uncatchable +Invalid argument +getting signal 9: Success + +setting signal 10: Success +getting signal 10: Success + +setting signal 11: Success +getting signal 11: Success + +setting signal 12: Success +getting signal 12: Success + +setting signal 13: Success +getting signal 13: Success + +setting signal 14: Success +getting signal 14: Success + +setting signal 15: Success +getting signal 15: Success + +setting signal 16: Success +getting signal 16: Success + +setting signal 17: Warning: ignored attempt to set SIGSTOP handler in sigaction(); + the SIGSTOP signal is uncatchable +Invalid argument +getting signal 17: Success + +setting signal 18: Success +getting signal 18: Success + +setting signal 19: Success +getting signal 19: Success + +setting signal 20: Success +getting signal 20: Success + +setting signal 21: Success +getting signal 21: Success + +setting signal 22: Success +getting signal 22: Success + +setting signal 23: Success +getting signal 23: Success + +setting signal 24: Success +getting signal 24: Success + +setting signal 25: Success +getting signal 25: Success + +setting signal 26: Success +getting signal 26: Success + +setting signal 27: Success +getting signal 27: Success + +setting signal 28: Success +getting signal 28: Success + +setting signal 29: Success +getting signal 29: Success + +setting signal 30: Success +getting signal 30: Success + +setting signal 31: Success +getting signal 31: Success + +setting signal 34: Success +getting signal 34: Success + +setting signal 35: Success +getting signal 35: Success + +setting signal 36: Success +getting signal 36: Success + +setting signal 37: Success +getting signal 37: Success + +setting signal 38: Success +getting signal 38: Success + +setting signal 39: Success +getting signal 39: Success + +setting signal 40: Success +getting signal 40: Success + +setting signal 41: Success +getting signal 41: Success + +setting signal 42: Success +getting signal 42: Success + +setting signal 43: Success +getting signal 43: Success + +setting signal 44: Success +getting signal 44: Success + +setting signal 45: Success +getting signal 45: Success + +setting signal 46: Success +getting signal 46: Success + +setting signal 47: Success +getting signal 47: Success + +setting signal 48: Success +getting signal 48: Success + +setting signal 49: Success +getting signal 49: Success + +setting signal 50: Success +getting signal 50: Success + +setting signal 51: Success +getting signal 51: Success + +setting signal 52: Success +getting signal 52: Success + +setting signal 53: Success +getting signal 53: Success + +setting signal 54: Success +getting signal 54: Success + +setting signal 55: Success +getting signal 55: Success + +setting signal 56: Success +getting signal 56: Success + +setting signal 57: Success +getting signal 57: Success + +setting signal 58: Success +getting signal 58: Success + +setting signal 59: Success +getting signal 59: Success + +setting signal 60: Success +getting signal 60: Success + +setting signal 61: Success +getting signal 61: Success + +setting signal 62: Success +getting signal 62: Success + +setting signal 65: Success +getting signal 65: Success + + +HEAP SUMMARY: + in use at exit: ... bytes in ... blocks + total heap usage: ... allocs, ... frees, ... bytes allocated + +For a detailed leak analysis, rerun with: --leak-check=full + +For counts of detected and suppressed errors, rerun with: -v +ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) diff -r efb6377bb4b5 -r ae0a1b9f3c43 memcheck/tests/str_tester.c --- a/memcheck/tests/str_tester.c Mon Dec 01 23:44:20 2014 +0900 +++ b/memcheck/tests/str_tester.c Thu Mar 31 15:57:55 2016 +0900 @@ -265,7 +265,7 @@ } // DDD: better done by testing for the function. -#if !defined(__APPLE__) +#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) static void test_stpncpy (void) { @@ -467,7 +467,7 @@ } // DDD: better done by testing for the function. -#if !defined(__APPLE__) +#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) static void test_strchrnul (void) { @@ -504,7 +504,7 @@ #endif // DDD: better done by testing for the function. -#if !defined(__APPLE__) +#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) static void test_rawmemchr (void) { @@ -580,7 +580,7 @@ } // DDD: better done by testing for the function. -#if !defined(__APPLE__) +#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) static void test_memrchr (void) { @@ -902,7 +902,7 @@ equal(one+4, "c", 50); { -# if !defined(__APPLE__) +# if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) char text[] = "This,is,a,test"; char *list = strdupa (text); equal (strsep (&list, ","), "This", 51); @@ -1063,7 +1063,7 @@ } } -#if !defined(__APPLE__) +#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) static void test_mempcpy (void) { @@ -1279,7 +1279,7 @@ equal(one, "abcdef", 4); /* Zero-length copy. */ } -#if !defined(__APPLE__) +#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) static void test_strndup (void) { @@ -1414,7 +1414,7 @@ /* A closely related function is stpcpy. */ test_stpcpy (); -#if !defined(__APPLE__) +#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) /* stpncpy. */ test_stpncpy (); #endif @@ -1437,12 +1437,12 @@ /* strchr. */ test_strchr (); -# if !defined(__APPLE__) +# if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) /* strchrnul. */ test_strchrnul (); # endif -# if !defined(__APPLE__) +# if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) /* rawmemchr. */ test_rawmemchr (); # endif @@ -1453,7 +1453,7 @@ /* strrchr. */ test_strrchr (); -# if !defined(__APPLE__) +# if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) /* memrchr. */ test_memrchr (); # endif @@ -1494,7 +1494,7 @@ /* memmove - must work on overlap. */ test_memmove (); -# if !defined(__APPLE__) +# if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) /* mempcpy */ test_mempcpy (); # endif @@ -1514,7 +1514,7 @@ /* bcmp - somewhat like memcmp. */ test_bcmp (); -#if !defined(__APPLE__) +#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) /* strndup. */ test_strndup (); #endif diff -r efb6377bb4b5 -r ae0a1b9f3c43 memcheck/tests/test-plo-no.stderr.exp-le32-freebsd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memcheck/tests/test-plo-no.stderr.exp-le32-freebsd Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,18 @@ +Invalid read of size 4 + ... + Address 0x........ is 4 bytes inside a block of size 5 alloc'd + at 0x........: malloc (vg_replace_malloc.c:...) + ... + +Invalid read of size 4 + ... + Address 0x........ is 4 bytes inside a block of size 5 alloc'd + at 0x........: malloc (vg_replace_malloc.c:...) + ... + +Invalid read of size 4 + ... + Address 0x........ is 4 bytes inside a block of size 12 free'd + at 0x........: free (vg_replace_malloc.c:...) + ... + diff -r efb6377bb4b5 -r ae0a1b9f3c43 memcheck/tests/test-plo-no.stderr.exp-le64-freebsd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memcheck/tests/test-plo-no.stderr.exp-le64-freebsd Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,18 @@ +Invalid read of size 8 + ... + Address 0x........ is 0 bytes inside a block of size 5 alloc'd + at 0x........: malloc (vg_replace_malloc.c:...) + ... + +Invalid read of size 8 + ... + Address 0x........ is 0 bytes inside a block of size 5 alloc'd + at 0x........: malloc (vg_replace_malloc.c:...) + ... + +Invalid read of size 8 + ... + Address 0x........ is 8 bytes inside a block of size 24 free'd + at 0x........: free (vg_replace_malloc.c:...) + ... + diff -r efb6377bb4b5 -r ae0a1b9f3c43 memcheck/tests/thread_alloca.c --- a/memcheck/tests/thread_alloca.c Mon Dec 01 23:44:20 2014 +0900 +++ b/memcheck/tests/thread_alloca.c Thu Mar 31 15:57:55 2016 +0900 @@ -7,7 +7,9 @@ Also, a high nr of threads in thr[] is needed to get the problem. */ #include +#if defined(__linux__) #include +#endif #include #include #include diff -r efb6377bb4b5 -r ae0a1b9f3c43 memcheck/tests/vbit-test/util.c --- a/memcheck/tests/vbit-test/util.c Mon Dec 01 23:44:20 2014 +0900 +++ b/memcheck/tests/vbit-test/util.c Thu Mar 31 15:57:55 2016 +0900 @@ -7,8 +7,12 @@ #include #define __BYTE_ORDER BYTE_ORDER #define __LITTLE_ENDIAN LITTLE_ENDIAN +#elif defined(__linux__) +#include #else -#include +#define __BYTE_ORDER BYTE_ORDER +#define __LITTLE_ENDIAN LITTLE_ENDIAN +#include #endif #include #include "vtest.h" diff -r efb6377bb4b5 -r ae0a1b9f3c43 memcheck/tests/vbit-test/vbits.c --- a/memcheck/tests/vbit-test/vbits.c Mon Dec 01 23:44:20 2014 +0900 +++ b/memcheck/tests/vbit-test/vbits.c Thu Mar 31 15:57:55 2016 +0900 @@ -6,8 +6,12 @@ #include #define __BYTE_ORDER BYTE_ORDER #define __LITTLE_ENDIAN LITTLE_ENDIAN +#elif defined(__linux__) +#include #else -#include +#include +#define __BYTE_ORDER BYTE_ORDER +#define __LITTLE_ENDIAN LITTLE_ENDIAN #endif #include #include "vbits.h" diff -r efb6377bb4b5 -r ae0a1b9f3c43 memcheck/tests/x86/more_x86_fp.c --- a/memcheck/tests/x86/more_x86_fp.c Mon Dec 01 23:44:20 2014 +0900 +++ b/memcheck/tests/x86/more_x86_fp.c Thu Mar 31 15:57:55 2016 +0900 @@ -87,7 +87,7 @@ long double la; int16_t fpuc; int i; - int64_t lla; + long long int lla; int ia; int16_t wa; double ra; diff -r efb6377bb4b5 -r ae0a1b9f3c43 mpi/Makefile.am --- a/mpi/Makefile.am Mon Dec 01 23:44:20 2014 +0900 +++ b/mpi/Makefile.am Thu Mar 31 15:57:55 2016 +0900 @@ -38,6 +38,10 @@ MPI_FLAG_M3264_PRI = $(AM_FLAG_M3264_PRI) MPI_FLAG_M3264_SEC = $(AM_FLAG_M3264_SEC) endif +if VGCONF_OS_IS_FREEBSD + MPI_FLAG_M3264_PRI = $(AM_FLAG_M3264_PRI) + MPI_FLAG_M3264_SEC = $(AM_FLAG_M3264_SEC) +endif if VGCONF_OS_IS_DARWIN MPI_FLAG_M3264_PRI = $(AM_FLAG_M3264_PRI) MPI_FLAG_M3264_SEC = $(AM_FLAG_M3264_SEC) diff -r efb6377bb4b5 -r ae0a1b9f3c43 none/tests/Makefile.am --- a/none/tests/Makefile.am Mon Dec 01 23:44:20 2014 +0900 +++ b/none/tests/Makefile.am Thu Mar 31 15:57:55 2016 +0900 @@ -141,6 +141,7 @@ require-text-symbol-1.stderr.exp \ require-text-symbol-2.vgtest \ require-text-symbol-2.stderr.exp-libcso6 \ + require-text-symbol-2.stderr.exp-freebsd \ res_search.stderr.exp res_search.stdout.exp res_search.vgtest \ resolv.stderr.exp resolv.stdout.exp resolv.vgtest \ rlimit_nofile.stderr.exp rlimit_nofile.stdout.exp rlimit_nofile.vgtest \ @@ -150,6 +151,8 @@ semlimit.stderr.exp semlimit.stdout.exp semlimit.vgtest \ shell shell.vgtest shell.stderr.exp shell.stderr.exp-dash \ shell.stdout.exp shell.stderr.exp-dash2 \ + shell.stderr.exp-freebsd shell.stdout.exp-freebsd \ + shell_dir.stderr.exp-freebsd \ shell_badinterp shell_badinterp.vgtest shell_badinterp.stderr.exp \ shell_binaryfile shell_binaryfile.vgtest shell_binaryfile.stderr.exp \ shell_dir.vgtest shell_dir.stderr.exp \ @@ -237,7 +240,7 @@ thread-exits endif # This doesn't appear to be compilable on Darwin. -if ! VGCONF_OS_IS_DARWIN +if VGCONF_OS_IS_LINUX check_PROGRAMS += rlimit64_nofile endif @@ -272,8 +275,12 @@ pth_once_LDADD = -lpthread pth_rwlock_LDADD = -lpthread pth_stackalign_LDADD = -lpthread -res_search_LDADD = -lresolv -lpthread -resolv_LDADD = -lresolv -lpthread +if VGCONF_OS_IS_FREEBSD + res_search_LDADD = -lpthread +else + res_search_LDADD = -lresolv -lpthread + resolv_LDADD = -lresolv -lpthread +endif semlimit_LDADD = -lpthread thread_exits_LDADD = -lpthread threaded_fork_LDADD = -lpthread diff -r efb6377bb4b5 -r ae0a1b9f3c43 none/tests/amd64/avx-1.c --- a/none/tests/amd64/avx-1.c Mon Dec 01 23:44:20 2014 +0900 +++ b/none/tests/amd64/avx-1.c Thu Mar 31 15:57:55 2016 +0900 @@ -2,7 +2,11 @@ #include #include #include +#if defined(__linux__) #include +#else +#include +#endif typedef unsigned char UChar; typedef unsigned int UInt; @@ -62,7 +66,8 @@ \ __attribute__ ((noinline)) static void test_##_name ( void ) \ { \ - Block* b = memalign(32, sizeof(Block)); \ + Block* b; \ + posix_memalign(&b, 32, sizeof(Block)); \ randBlock(b); \ printf("%s(reg)\n", #_name); \ showBlock("before", b); \ diff -r efb6377bb4b5 -r ae0a1b9f3c43 none/tests/amd64/avx2-1.c --- a/none/tests/amd64/avx2-1.c Mon Dec 01 23:44:20 2014 +0900 +++ b/none/tests/amd64/avx2-1.c Thu Mar 31 15:57:55 2016 +0900 @@ -2,7 +2,11 @@ #include #include #include +#if defined(__linux__) #include +#else +#include +#endif typedef unsigned char UChar; typedef unsigned int UInt; @@ -64,7 +68,8 @@ \ __attribute__ ((noinline)) static void test_##_name ( void ) \ { \ - Block* b = memalign(32, sizeof(Block)); \ + Block* b; \ + posix_memalign(&b, 32, sizeof(Block)); \ randBlock(b); \ printf("%s(reg)\n", #_name); \ showBlock("before", b); \ diff -r efb6377bb4b5 -r ae0a1b9f3c43 none/tests/amd64/bug156404-amd64.c --- a/none/tests/amd64/bug156404-amd64.c Mon Dec 01 23:44:20 2014 +0900 +++ b/none/tests/amd64/bug156404-amd64.c Thu Mar 31 15:57:55 2016 +0900 @@ -14,6 +14,10 @@ #define VG_STRINGIFZ(__str) #__str #define VG_STRINGIFY(__str) VG_STRINGIFZ(__str) +#if defined(__FreeBSD__) +# define __NR_readlink 58 +#endif + #define __NR_READLINK VG_STRINGIFY(__NR_readlink) extern long my_readlink ( const char* path ); diff -r efb6377bb4b5 -r ae0a1b9f3c43 none/tests/amd64/insn_ssse3.vgtest --- a/none/tests/amd64/insn_ssse3.vgtest Mon Dec 01 23:44:20 2014 +0900 +++ b/none/tests/amd64/insn_ssse3.vgtest Thu Mar 31 15:57:55 2016 +0900 @@ -1,3 +1,3 @@ prog: ../../../none/tests/amd64/insn_ssse3 -prereq: ../../../tests/x86_amd64_features amd64-ssse3 +prereq: ../../../tests/x86_amd64_features amd64-ssse3 && test -e insn_ssse3 vgopts: -q diff -r efb6377bb4b5 -r ae0a1b9f3c43 none/tests/amd64/movbe.c --- a/none/tests/amd64/movbe.c Mon Dec 01 23:44:20 2014 +0900 +++ b/none/tests/amd64/movbe.c Thu Mar 31 15:57:55 2016 +0900 @@ -2,7 +2,11 @@ #include #include #include +#if defined(__linux__) #include +#else +#include +#endif typedef unsigned char UChar; typedef unsigned int UInt; @@ -43,7 +47,8 @@ \ __attribute__ ((noinline)) static void test_##_name ( void ) \ { \ - Block* b = memalign(32, sizeof(Block)); \ + Block* b; \ + posix_memalign(&b, 32, sizeof(Block)); \ randBlock(b); \ printf("%s\n", #_name); \ showBlock("before", b); \ diff -r efb6377bb4b5 -r ae0a1b9f3c43 none/tests/amd64/sse4-64.c --- a/none/tests/amd64/sse4-64.c Mon Dec 01 23:44:20 2014 +0900 +++ b/none/tests/amd64/sse4-64.c Thu Mar 31 15:57:55 2016 +0900 @@ -19,7 +19,7 @@ // rmme when reintegrated // Allocates a 16-aligned block. Asserts if the allocation fails. -#ifdef VGO_darwin +#if defined(VGO_darwin) || defined(VGO_freebsd) #include #else #include @@ -31,6 +31,10 @@ #if defined(VGO_darwin) // Darwin lacks memalign, but its malloc is always 16-aligned anyway. x = malloc(szB); +#elif defined(VGO_freebsd) + int error = posix_memalign(&x, 16, szB); + if (error != 0) + x = NULL; #else x = memalign(16, szB); #endif diff -r efb6377bb4b5 -r ae0a1b9f3c43 none/tests/amd64/ssse3_misaligned.vgtest --- a/none/tests/amd64/ssse3_misaligned.vgtest Mon Dec 01 23:44:20 2014 +0900 +++ b/none/tests/amd64/ssse3_misaligned.vgtest Thu Mar 31 15:57:55 2016 +0900 @@ -1,3 +1,3 @@ prog: ssse3_misaligned -prereq: ../../../tests/x86_amd64_features amd64-ssse3 +prereq: ../../../tests/x86_amd64_features amd64-ssse3 && test -e ssse3_misaligned vgopts: -q diff -r efb6377bb4b5 -r ae0a1b9f3c43 none/tests/closeall.c --- a/none/tests/closeall.c Mon Dec 01 23:44:20 2014 +0900 +++ b/none/tests/closeall.c Thu Mar 31 15:57:55 2016 +0900 @@ -1,5 +1,7 @@ #include #include +#include +#include #include #include diff -r efb6377bb4b5 -r ae0a1b9f3c43 none/tests/execve.stderr.exp --- a/none/tests/execve.stderr.exp Mon Dec 01 23:44:20 2014 +0900 +++ b/none/tests/execve.stderr.exp Thu Mar 31 15:57:55 2016 +0900 @@ -1,1 +1,4 @@ +execve(0x........(./execve), 0x........, 0x........) failed, errno 14 +EXEC FAILED: I can't recover from execve() failing, so I'm dying. +Add more stringent tests in PRE(sys_execve), or work out how to recover. diff -r efb6377bb4b5 -r ae0a1b9f3c43 none/tests/fdleak_cmsg.c --- a/none/tests/fdleak_cmsg.c Mon Dec 01 23:44:20 2014 +0900 +++ b/none/tests/fdleak_cmsg.c Thu Mar 31 15:57:55 2016 +0900 @@ -28,6 +28,9 @@ #include #include #include "fdleak.h" +#if defined(__FreeBSD__) +#include +#endif char filea[24]; char fileb[24]; diff -r efb6377bb4b5 -r ae0a1b9f3c43 none/tests/fdleak_socketpair.c --- a/none/tests/fdleak_socketpair.c Mon Dec 01 23:44:20 2014 +0900 +++ b/none/tests/fdleak_socketpair.c Thu Mar 31 15:57:55 2016 +0900 @@ -1,3 +1,6 @@ +#if defined(__FreeBSD__) +#include +#endif #include #include #include "fdleak.h" diff -r efb6377bb4b5 -r ae0a1b9f3c43 none/tests/map_unaligned.c --- a/none/tests/map_unaligned.c Mon Dec 01 23:44:20 2014 +0900 +++ b/none/tests/map_unaligned.c Thu Mar 31 15:57:55 2016 +0900 @@ -2,6 +2,10 @@ #include #include "tests/sys_mman.h" +#ifndef MAP_ANONYMOUS +# define MAP_ANONYMOUS MAP_ANON +#endif + int main(int argc, char **argv) { void *p1; diff -r efb6377bb4b5 -r ae0a1b9f3c43 none/tests/mq.c --- a/none/tests/mq.c Mon Dec 01 23:44:20 2014 +0900 +++ b/none/tests/mq.c Thu Mar 31 15:57:55 2016 +0900 @@ -1,3 +1,6 @@ +#if defined(__FreeBSD__) +#include +#endif #include #include #include diff -r efb6377bb4b5 -r ae0a1b9f3c43 none/tests/pth_atfork1.c --- a/none/tests/pth_atfork1.c Mon Dec 01 23:44:20 2014 +0900 +++ b/none/tests/pth_atfork1.c Thu Mar 31 15:57:55 2016 +0900 @@ -18,7 +18,7 @@ Boston, MA 02111-1307, USA. */ #include -#if !defined(__APPLE__) +#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) # include #endif #include @@ -27,7 +27,7 @@ #include #include -#if defined(__APPLE__) +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) #include /* strerror */ static void error (int status, int errnum, char* msg) { diff -r efb6377bb4b5 -r ae0a1b9f3c43 none/tests/require-text-symbol-2.stderr.exp-freebsd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/none/tests/require-text-symbol-2.stderr.exp-freebsd Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,9 @@ + +valgrind: Fatal error at when loading library with soname +valgrind: libc.so.7 +valgrind: Cannot find any text symbol with a name that matches the pattern +valgrind: doesntexist +valgrind: as required by a --require-text-symbol= specification. + +valgrind: Cannot continue -- exiting now. + diff -r efb6377bb4b5 -r ae0a1b9f3c43 none/tests/resolv.c --- a/none/tests/resolv.c Mon Dec 01 23:44:20 2014 +0900 +++ b/none/tests/resolv.c Thu Mar 31 15:57:55 2016 +0900 @@ -1,4 +1,7 @@ +#if defined(__FreeBSD__) +#include +#endif #include #include #include diff -r efb6377bb4b5 -r ae0a1b9f3c43 none/tests/rlimit_nofile.c --- a/none/tests/rlimit_nofile.c Mon Dec 01 23:44:20 2014 +0900 +++ b/none/tests/rlimit_nofile.c Thu Mar 31 15:57:55 2016 +0900 @@ -2,6 +2,9 @@ #include #include #include +#if defined(__FreeBSD__) +#include +#endif #include #include #include "fdleak.h" diff -r efb6377bb4b5 -r ae0a1b9f3c43 none/tests/sem.c --- a/none/tests/sem.c Mon Dec 01 23:44:20 2014 +0900 +++ b/none/tests/sem.c Thu Mar 31 15:57:55 2016 +0900 @@ -4,6 +4,9 @@ #include #include #include +#if defined(__FreeBSD__) +#include +#endif #include #include #include diff -r efb6377bb4b5 -r ae0a1b9f3c43 none/tests/shell --- a/none/tests/shell Mon Dec 01 23:44:20 2014 +0900 +++ b/none/tests/shell Thu Mar 31 15:57:55 2016 +0900 @@ -5,9 +5,13 @@ #---------------------------------------------------------------------------- # Shell scripts that should fail #---------------------------------------------------------------------------- + LC_ALL=C -echo "Execute a directory" -./x86/ +os=$(uname -s) +if [ "${os}" != "FreeBSD" ]; then + echo "Execute a directory" + ./x86/ +fi echo "Execute a non-executable file" ./shell.vgtest diff -r efb6377bb4b5 -r ae0a1b9f3c43 none/tests/shell.stderr.exp-freebsd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/none/tests/shell.stderr.exp-freebsd Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,7 @@ +./shell: ./shell.vgtest: Permission denied +execve(0x........(./shell_badinterp), 0x........, 0x........) failed, errno 2 +EXEC FAILED: I can't recover from execve() failing, so I'm dying. +Add more stringent tests in PRE(sys_execve), or work out how to recover. +./shell: ./shell_binaryfile: Exec format error +./shell: ./shell_nosuchfile: not found +./shell: shell_nosuchfile: not found diff -r efb6377bb4b5 -r ae0a1b9f3c43 none/tests/shell.stdout.exp-freebsd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/none/tests/shell.stdout.exp-freebsd Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,9 @@ +Execute a non-executable file +Execute a script with a bad interpreter name +Execute a binary file +Execute a non-existent file +Execute a non-existent file (2) +Execute a valid script with a #! line +Execute a valid script without a #! line +Execute a valid script with #! but no interpname +Execute a zero-length file diff -r efb6377bb4b5 -r ae0a1b9f3c43 none/tests/shell_dir.stderr.exp-freebsd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/none/tests/shell_dir.stderr.exp-freebsd Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,1 @@ +valgrind: ./x86/: cannot execute binary file diff -r efb6377bb4b5 -r ae0a1b9f3c43 none/tests/sigstackgrowth.c --- a/none/tests/sigstackgrowth.c Mon Dec 01 23:44:20 2014 +0900 +++ b/none/tests/sigstackgrowth.c Thu Mar 31 15:57:55 2016 +0900 @@ -48,7 +48,9 @@ deep = &here - SIZE; sa.sa_handler = handler; +#if defined(SA_NODEFER) sa.sa_flags = SA_NODEFER; +#endif sigemptyset(&sa.sa_mask); sigaction(SIGUSR1, &sa, NULL); diff -r efb6377bb4b5 -r ae0a1b9f3c43 none/tests/x86/faultstatus.c --- a/none/tests/x86/faultstatus.c Mon Dec 01 23:44:20 2014 +0900 +++ b/none/tests/x86/faultstatus.c Thu Mar 31 15:57:55 2016 +0900 @@ -21,7 +21,7 @@ -static jmp_buf escape; +static sigjmp_buf escape; #define BADADDR ((int *)0x1234) @@ -132,7 +132,9 @@ { const struct test tests[] = { #define T(n, sig, code, addr) { test##n, sig, code, addr } +#if !defined(__FreeBSD__) || __FreeBSD__ >= 5 T(1, SIGILL, ILL_ILLOPN, &test1_ill), +#endif T(2, SIGTRAP, 128, 0), /* TRAP_BRKPT? */ T(3, SIGSEGV, 128, 0), diff -r efb6377bb4b5 -r ae0a1b9f3c43 none/tests/x86/movbe.c --- a/none/tests/x86/movbe.c Mon Dec 01 23:44:20 2014 +0900 +++ b/none/tests/x86/movbe.c Thu Mar 31 15:57:55 2016 +0900 @@ -2,7 +2,11 @@ #include #include #include +#ifdef (__linux__) #include +#else +#include +#endif typedef unsigned char UChar; typedef unsigned int UInt; @@ -43,7 +47,8 @@ \ __attribute__ ((noinline)) static void test_##_name ( void ) \ { \ - Block* b = memalign(32, sizeof(Block)); \ + Block* b; \ + posix_memalign(&b, 32, sizeof(Block)); \ randBlock(b); \ printf("%s\n", #_name); \ showBlock("before", b); \ diff -r efb6377bb4b5 -r ae0a1b9f3c43 openbsd-chesk.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/openbsd-chesk.sh Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,28 @@ +# Script to check OpenBSD related definitions + +# OpenBSD src directory +o=$1 + +tmp=$(mktemp /tmp/XXXXXX) + +# Syscalls in Valgrind +sed -ne ' + /^#define.*__NR_/ { + s/^#define.*__NR_\([^ ]*\) *\([^ ]*\)$/\2 \1/ + p + } +' < include/vki/vki-scnums-openbsd.h | +egrep -v 'MAXSYSCALL|fake_sigreturn' >$tmp.v + +# Syscalls in OpenBSD +sed -ne ' + /^#define.*SYS_/ { + s/^#define.*SYS_\([^ ]*\) *\([^ ]*\)$/\2 \1/ + p + } +' < $o/sys/sys/syscall.h | +egrep -v 'MAXSYSCALL' >$tmp.o + +diff -u $tmp.o $tmp.v + +rm -f $tmp $tmp.* diff -r efb6377bb4b5 -r ae0a1b9f3c43 openbsd.supp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/openbsd.supp Thu Mar 31 15:57:55 2016 +0900 @@ -0,0 +1,93 @@ +# Suppressions for OpenBSD + +##----------------------------------------------------------------------## +# Memcheck +##----------------------------------------------------------------------## + +{ + rtld-1 + Memcheck:Cond + obj:/usr/libexec/ld-elf.so +} +{ + libc puts leak + Memcheck:Leak + fun:malloc + obj:/usr/lib/libc.so.69.0 + obj:/usr/lib/libc.so.69.0 + obj:/usr/lib/libc.so.69.0 + fun:puts + fun:main +} +{ + DRD-1 + drd:ConflictingAccess + obj:/usr/lib/libpthread.so.17.3 + fun:pthread_create + fun:pthread_create + fun:main +} +{ + DRD-2 + drd:ConflictingAccess + fun:pthread_exit +} +{ + HELGRIND-PTHREAD-EXIT1 + Helgrind:Race + fun:_pthread_exit_mask + fun:pthread_exit + obj:/usr/lib/libpthread.so.17.3 +} +{ + HELGRIND-PTHREAD-EXIT2 + Helgrind:Race + fun:__sys_thr_exit + fun:_pthread_exit_mask + fun:pthread_exit + obj:/usr/lib/libpthread.so.17.3 +} +{ + HELGRIND-PTHREAD-EXIT3 + Helgrind:Race + obj:/usr/lib/libpthread.so.17.3 + fun:pthread_join_WRK + fun:pthread_join +} +{ + HELGRIND-PTHREAD-EXIT4 + Helgrind:Race + fun:_thr_try_gc + obj:/usr/lib/libpthread.so.17.3 + fun:pthread_join_WRK + fun:pthread_join +} +{ + HELGRIND-PTHREAD-EXIT5 + Helgrind:Race + fun:__sys_thr_exit + obj:/usr/lib/libpthread.so.17.3 + fun:_pthread_exit_mask + fun:pthread_exit + obj:/usr/lib/libpthread.so.17.3 +} +{ + HELGRIND-PTHREAD-BARRIER1 + Helgrind:Race + fun:pthread_barrier_init + fun:pthread_barrier_init + fun:main +} +{ + HELGRIND-PTHREAD-BARRIER2 + Helgrind:Race + fun:pthread_barrier_destroy + fun:pthread_barrier_destroy + fun:main +} +{ + HELGRIND-PTHREAD-CANCEL + Helgrind:Race + fun:pthread_cancel + fun:main +} diff -r efb6377bb4b5 -r ae0a1b9f3c43 perf/bigcode.c --- a/perf/bigcode.c Mon Dec 01 23:44:20 2014 +0900 +++ b/perf/bigcode.c Thu Mar 31 15:57:55 2016 +0900 @@ -60,7 +60,7 @@ char* a = mmap(0, FN_SIZE * n_fns, PROT_EXEC|PROT_WRITE, - MAP_PRIVATE|MAP_ANONYMOUS, -1,0); + MAP_PRIVATE|MAP_ANON, -1,0); assert(a != (char*)MAP_FAILED); // Make a whole lot of copies of f(). FN_SIZE is much bigger than f() diff -r efb6377bb4b5 -r ae0a1b9f3c43 perf/tinycc.c --- a/perf/tinycc.c Mon Dec 01 23:44:20 2014 +0900 +++ b/perf/tinycc.c Thu Mar 31 15:57:55 2016 +0900 @@ -21790,7 +21790,7 @@ // zero here (as required by vg_perf). int main(int argc, char **argv) { - #define REPS 30 + #define REPS 1 int i; for (i = 0; i < REPS; i++) { main2(argc, argv); diff -r efb6377bb4b5 -r ae0a1b9f3c43 shared/vg_replace_strmem.c --- a/shared/vg_replace_strmem.c Mon Dec 01 23:44:20 2014 +0900 +++ b/shared/vg_replace_strmem.c Thu Mar 31 15:57:55 2016 +0900 @@ -198,6 +198,16 @@ STRRCHR(NONE, __dl_strrchr); /* in /system/bin/linker */ #endif +#elif defined(VGO_freebsd) + STRRCHR(VG_Z_LIBC_SONAME, strrchr) + STRRCHR(VG_Z_LIBC_SONAME, rindex) + STRRCHR(VG_Z_LD_ELF_SO_1, strrchr) + STRRCHR(VG_Z_LD_ELF32_SO_1, strrchr) + +#elif defined(VGO_openbsd) + STRRCHR(VG_Z_LIBC_SONAME, strrchr) + STRRCHR(VG_Z_LIBC_SONAME, rindex) + #elif defined(VGO_darwin) //STRRCHR(VG_Z_LIBC_SONAME, strrchr) //STRRCHR(VG_Z_LIBC_SONAME, rindex) @@ -237,6 +247,16 @@ STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, index) # endif +#elif defined(VGO_freebsd) + STRCHR(VG_Z_LIBC_SONAME, strchr) + STRCHR(VG_Z_LIBC_SONAME, index) + STRCHR(VG_Z_LD_ELF_SO_1, strchr) + STRCHR(VG_Z_LD_ELF32_SO_1, strchr) + +#elif defined(VGO_openbsd) + STRCHR(VG_Z_LIBC_SONAME, strchr) + STRCHR(VG_Z_LIBC_SONAME, index) + #elif defined(VGO_darwin) STRCHR(VG_Z_LIBC_SONAME, strchr) # if DARWIN_VERS == DARWIN_10_9 @@ -274,6 +294,14 @@ STRCAT(VG_Z_LIBC_SONAME, strcat) STRCAT(VG_Z_LIBC_SONAME, __GI_strcat) +#elif defined(VGO_freebsd) + STRCAT(VG_Z_LIBC_SONAME, strcat) + STRCAT(VG_Z_LD_ELF_SO_1, strcat) + STRCAT(VG_Z_LD_ELF32_SO_1, strcat) + +#elif defined(VGO_openbsd) + STRCAT(VG_Z_LIBC_SONAME, strcat) + #elif defined(VGO_darwin) //STRCAT(VG_Z_LIBC_SONAME, strcat) @@ -310,6 +338,12 @@ #if defined(VGO_linux) STRNCAT(VG_Z_LIBC_SONAME, strncat) +#elif defined(VGO_freebsd) + STRNCAT(VG_Z_LIBC_SONAME, strncat) + +#elif defined(VGO_openbsd) + STRNCAT(VG_Z_LIBC_SONAME, strncat) + #elif defined(VGO_darwin) //STRNCAT(VG_Z_LIBC_SONAME, strncat) //STRNCAT(VG_Z_DYLD, strncat) @@ -357,6 +391,14 @@ #if defined(VGO_linux) +#elif defined(VGO_freebsd) + STRLCAT(VG_Z_LD_ELF_SO_1, strlcat) + STRLCAT(VG_Z_LIBC_SONAME, strlcat) + STRLCAT(VG_Z_LD_ELF32_SO_1, strlcat) + +#elif defined(VGO_openbsd) + STRLCAT(VG_Z_LD_ELF_SO_1, strlcat) + #elif defined(VGO_darwin) //STRLCAT(VG_Z_LIBC_SONAME, strlcat) //STRLCAT(VG_Z_DYLD, strlcat) @@ -421,6 +463,14 @@ STRLEN(NONE, __dl_strlen); /* in /system/bin/linker */ # endif +#elif defined(VGO_freebsd) + STRLEN(VG_Z_LIBC_SONAME, strlen) + STRLEN(VG_Z_LD_ELF_SO_1, strlen) + STRLEN(VG_Z_LD_ELF32_SO_1, strlen) + +#elif defined(VGO_openbsd) + STRLEN(VG_Z_LIBC_SONAME, strlen) + #elif defined(VGO_darwin) STRLEN(VG_Z_LIBC_SONAME, strlen) # if DARWIN_VERS == DARWIN_10_9 @@ -458,6 +508,14 @@ STRCPY(VG_Z_LIBC_SONAME, strcpy) STRCPY(VG_Z_LIBC_SONAME, __GI_strcpy) +#elif defined(VGO_freebsd) + STRCPY(VG_Z_LIBC_SONAME, strcpy) + STRCPY(VG_Z_LD_ELF_SO_1, strcpy) + STRCPY(VG_Z_LD_ELF32_SO_1, strcpy) + +#elif defined(VGO_openbsd) + STRCPY(VG_Z_LIBC_SONAME, strcpy) + #elif defined(VGO_darwin) STRCPY(VG_Z_LIBC_SONAME, strcpy) # if DARWIN_VERS == DARWIN_10_9 @@ -495,6 +553,14 @@ STRNCPY(VG_Z_LIBC_SONAME, __strncpy_sse2) STRNCPY(VG_Z_LIBC_SONAME, __strncpy_sse2_unaligned) +#elif defined(VGO_freebsd) + STRNCPY(VG_Z_LIBC_SONAME, strncpy) + STRNCPY(VG_Z_LD_ELF_SO_1, strncpy) + STRNCPY(VG_Z_LD_ELF32_SO_1, strncpy) + +#elif defined(VGO_openbsd) + STRNCPY(VG_Z_LIBC_SONAME, strncpy) + #elif defined(VGO_darwin) STRNCPY(VG_Z_LIBC_SONAME, strncpy) # if DARWIN_VERS == DARWIN_10_9 @@ -538,6 +604,14 @@ STRLCPY(VG_Z_LIBC_SONAME, strlcpy); #endif +#elif defined(VGO_freebsd) + STRLCPY(VG_Z_LD_ELF_SO_1, strlcpy) + STRLCPY(VG_Z_LD_ELF32_SO_1, strlcpy) + STRLCPY(VG_Z_LIBC_SONAME, strlcpy) + +#elif defined(VGO_openbsd) + STRLCPY(VG_Z_LD_ELF_SO_1, strlcpy) + #elif defined(VGO_darwin) //STRLCPY(VG_Z_LIBC_SONAME, strlcpy) //STRLCPY(VG_Z_DYLD, strlcpy) @@ -574,6 +648,14 @@ STRNCMP(VG_Z_LIBC_SONAME, __strncmp_sse2) STRNCMP(VG_Z_LIBC_SONAME, __strncmp_sse42) +#elif defined(VGO_freebsd) + STRNCMP(VG_Z_LIBC_SONAME, strncmp) + STRNCMP(VG_Z_LD_ELF_SO_1, strncmp) + STRNCMP(VG_Z_LD_ELF32_SO_1, strncmp) + +#elif defined(VGO_openbsd) + STRNCMP(VG_Z_LIBC_SONAME, strncmp) + #elif defined(VGO_darwin) STRNCMP(VG_Z_LIBC_SONAME, strncmp) # if DARWIN_VERS == DARWIN_10_9 @@ -763,6 +845,14 @@ STRCMP(NONE, __dl_strcmp); /* in /system/bin/linker */ # endif +#elif defined(VGO_freebsd) + STRCMP(VG_Z_LIBC_SONAME, strcmp) + STRCMP(VG_Z_LD_ELF_SO_1, strcmp) + STRCMP(VG_Z_LD_ELF32_SO_1, strcmp) + +#elif defined(VGO_openbsd) + STRCMP(VG_Z_LIBC_SONAME, strcmp) + #elif defined(VGO_darwin) STRCMP(VG_Z_LIBC_SONAME, strcmp) # if DARWIN_VERS == DARWIN_10_9 @@ -792,6 +882,14 @@ MEMCHR(VG_Z_LIBC_SONAME, memchr) MEMCHR(VG_Z_LIBC_SONAME, __GI_memchr) +#elif defined(VGO_freebsd) + MEMCHR(VG_Z_LIBC_SONAME, memchr) + MEMCHR(VG_Z_LD_ELF_SO_1, memchr) + MEMCHR(VG_Z_LD_ELF32_SO_1, memchr) + +#elif defined(VGO_openbsd) + MEMCHR(VG_Z_LIBC_SONAME, memchr) + #elif defined(VGO_darwin) # if DARWIN_VERS == DARWIN_10_9 MEMCHR(VG_Z_DYLD, memchr) @@ -820,6 +918,12 @@ #if defined(VGO_linux) MEMRCHR(VG_Z_LIBC_SONAME, memrchr) +#elif defined(VGO_freebsd) + MEMRCHR(VG_Z_LIBC_SONAME, memrchr) + +#elif defined(VGO_openbsd) + MEMRCHR(VG_Z_LIBC_SONAME, memrchr) + #elif defined(VGO_darwin) //MEMRCHR(VG_Z_LIBC_SONAME, memrchr) //MEMRCHR(VG_Z_DYLD, memrchr) @@ -928,6 +1032,14 @@ */ MEMCPY(NONE, ZuintelZufastZumemcpy) +#elif defined(VGO_freebsd) + MEMCPY(VG_Z_LIBC_SONAME, memcpy) + MEMCPY(VG_Z_LD_ELF_SO_1, memcpy) + MEMCPY(VG_Z_LD_ELF32_SO_1, memcpy) + +#elif defined(VGO_openbsd) + MEMCPY(VG_Z_LIBC_SONAME, memcpy) + #elif defined(VGO_darwin) # if DARWIN_VERS <= DARWIN_10_6 MEMCPY(VG_Z_LIBC_SONAME, memcpy) @@ -973,6 +1085,14 @@ MEMCMP(VG_Z_LIBC_SONAME, bcmp) MEMCMP(VG_Z_LD_SO_1, bcmp) +#elif defined(VGO_freebsd) + MEMCMP(VG_Z_LIBC_SONAME, memcmp) + MEMCMP(VG_Z_LIBC_SONAME, bcmp) + +#elif defined(VGO_openbsd) + MEMCMP(VG_Z_LIBC_SONAME, memcmp) + MEMCMP(VG_Z_LIBC_SONAME, bcmp) + #elif defined(VGO_darwin) # if DARWIN_VERS == DARWIN_10_9 MEMCMP(libsystemZuplatformZddylib, _platform_memcmp) @@ -1016,6 +1136,14 @@ STPCPY(VG_Z_LD_LINUX_SO_2, stpcpy) STPCPY(VG_Z_LD_LINUX_X86_64_SO_2, stpcpy) +#elif defined(VGO_freebsd) + STPCPY(VG_Z_LD_ELF_SO_1, stpcpy) + STPCPY(VG_Z_LD_ELF32_SO_1, stpcpy) + STPCPY(VG_Z_LIBC_SONAME, stpcpy) + +#elif defined(VGO_openbsd) + STPCPY(VG_Z_LD_ELF_SO_1, stpcpy) + #elif defined(VGO_darwin) //STPCPY(VG_Z_LIBC_SONAME, stpcpy) //STPCPY(VG_Z_DYLD, stpcpy) @@ -1093,6 +1221,14 @@ #if defined(VGO_linux) MEMSET(VG_Z_LIBC_SONAME, memset) +#elif defined(VGO_freebsd) + MEMSET(VG_Z_LIBC_SONAME, memset) + MEMSET(VG_Z_LD_ELF_SO_1, memset) + MEMSET(VG_Z_LD_ELF32_SO_1, memset) + +#elif defined(VGO_openbsd) + MEMSET(VG_Z_LIBC_SONAME, memset) + #elif defined(VGO_darwin) //MEMSET(VG_Z_LIBC_SONAME, memset) //MEMSET(VG_Z_DYLD, memset) @@ -1109,6 +1245,14 @@ MEMMOVE(VG_Z_LIBC_SONAME, memmove) MEMMOVE(VG_Z_LIBC_SONAME, __GI_memmove) +#elif defined(VGO_freebsd) + MEMMOVE(VG_Z_LD_ELF_SO_1, memmove) + MEMMOVE(VG_Z_LD_ELF32_SO_1, memmove) + MEMMOVE(VG_Z_LIBC_SONAME, memmove) + +#elif defined(VGO_openbsd) + MEMMOVE(VG_Z_LD_ELF_SO_1, memmove) + #elif defined(VGO_darwin) # if DARWIN_VERS <= DARWIN_10_6 MEMMOVE(VG_Z_LIBC_SONAME, memmove) @@ -1144,6 +1288,14 @@ #if defined(VGO_linux) BCOPY(VG_Z_LIBC_SONAME, bcopy) +#elif defined(VGO_freebsd) + BCOPY(VG_Z_LIBC_SONAME, bcopy) + BCOPY(VG_Z_LD_ELF_SO_1, bcopy) + BCOPY(VG_Z_LD_ELF32_SO_1, bcopy) + +#elif defined(VGO_openbsd) + BCOPY(VG_Z_LIBC_SONAME, bcopy) + #elif defined(VGO_darwin) //BCOPY(VG_Z_LIBC_SONAME, bcopy) //BCOPY(VG_Z_DYLD, bcopy) diff -r efb6377bb4b5 -r ae0a1b9f3c43 tests/arch_test.c --- a/tests/arch_test.c Mon Dec 01 23:44:20 2014 +0900 +++ b/tests/arch_test.c Thu Mar 31 15:57:55 2016 +0900 @@ -38,10 +38,10 @@ static Bool go(char* arch) { -#if defined(VGP_x86_linux) || defined(VGP_x86_darwin) +#if defined(VGP_x86_linux) || defined(VGP_x86_darwin) || defined(VGP_x86_freebsd) || defined(VGP_x86_openbsd) if ( 0 == strcmp( arch, "x86" ) ) return True; -#elif defined(VGP_amd64_linux) || defined(VGP_amd64_darwin) +#elif defined(VGP_amd64_linux) || defined(VGP_amd64_darwin) || defined(VGP_amd64_freebsd) || defined(VGP_amd64_openbsd) #if defined(VGA_SEC_x86) if ( 0 == strcmp( arch, "x86" ) ) return True; #endif diff -r efb6377bb4b5 -r ae0a1b9f3c43 tests/filter_discards --- a/tests/filter_discards Mon Dec 01 23:44:20 2014 +0900 +++ b/tests/filter_discards Thu Mar 31 15:57:55 2016 +0900 @@ -3,6 +3,6 @@ dir=`dirname $0` # Remove number and position of discards -sed "s/discard [0-9]\+ ([0-9]\+ -> [0-9]\+) translations in range/discard ... (... -> ...) translations in range/" | +sed -E "s/discard [0-9]+ ([0-9]+ -> [0-9]+) translations in range/discard ... (... -> ...) translations in range/" | $dir/filter_addresses diff -r efb6377bb4b5 -r ae0a1b9f3c43 tests/malloc.h --- a/tests/malloc.h Mon Dec 01 23:44:20 2014 +0900 +++ b/tests/malloc.h Thu Mar 31 15:57:55 2016 +0900 @@ -3,6 +3,8 @@ #include #if defined(VGO_darwin) # include +#elif defined(VGO_freebsd) || defined(VGO_openbsd) +# include #else # include #endif @@ -14,7 +16,7 @@ static void* memalign16(size_t szB) { void* x; -#if defined(VGO_darwin) +#if defined(VGO_darwin) || defined(VGO_freebsd) || defined(VGO_openbsd) // Darwin lacks memalign, but its malloc is always 16-aligned anyway. x = malloc(szB); #else diff -r efb6377bb4b5 -r ae0a1b9f3c43 tests/os_test.c --- a/tests/os_test.c Mon Dec 01 23:44:20 2014 +0900 +++ b/tests/os_test.c Thu Mar 31 15:57:55 2016 +0900 @@ -23,6 +23,8 @@ char* all_OSes[] = { "linux", "darwin", + "freebsd", + "openbsd", NULL }; @@ -62,6 +64,12 @@ #elif defined(VGO_darwin) if ( 0 == strcmp( OS, "darwin" ) ) return True; +#elif defined(VGO_freebsd) + if ( 0 == strcmp( OS, "freebsd" ) ) return True; + +#elif defined(VGO_openbsd) + if ( 0 == strcmp( OS, "openbsd" ) ) return True; + #else # error Unknown OS #endif // VGO_* diff -r efb6377bb4b5 -r ae0a1b9f3c43 tests/sys_mman.h --- a/tests/sys_mman.h Mon Dec 01 23:44:20 2014 +0900 +++ b/tests/sys_mman.h Thu Mar 31 15:57:55 2016 +0900 @@ -2,7 +2,7 @@ #include -#if defined(VGO_darwin) +#if defined(VGO_darwin) || defined(VGO_freebsd) || defined(VGO_openbsd) # define MAP_ANONYMOUS MAP_ANON #endif