Support target program usgin Pthread.

ok mpi@
This commit is contained in:
asou 2019-12-23 23:26:32 +00:00
parent ef9779e25d
commit 23e0731616
9 changed files with 514 additions and 5 deletions

View File

@ -1,4 +1,4 @@
# $OpenBSD: Makefile,v 1.22 2019/11/06 05:25:13 asou Exp $
# $OpenBSD: Makefile,v 1.23 2019/12/23 23:26:32 asou Exp $
ONLY_FOR_ARCHS = amd64
@ -7,7 +7,7 @@ CATEGORIES = devel
V = 3.10.1
PV = 20160331
REVISION = 15
REVISION = 16
DISTNAME = valgrind-${V}
EXTRACT_SUFX = .tar.bz2

View File

@ -0,0 +1,21 @@
--- coregrind/m_libcsignal.c.orig
+++ coregrind/m_libcsignal.c
@@ -397,6 +397,7 @@
Int VG_(tkill)( Int lwpid, Int signo )
{
# if defined(__NR_tkill)
+ PRINT("sys___tfork ( %ld, %ld )",ARG1,ARG2);
SysRes res = VG_(mk_SysRes_Error)(VKI_ENOSYS);
res = VG_(do_syscall2)(__NR_tkill, lwpid, signo);
if (sr_isError(res) && sr_Err(res) == VKI_ENOSYS)
@@ -415,7 +416,9 @@
return sr_isError(res) ? -1 : 0;
# elif defined(VGO_openbsd)
- I_die_here;
+ SysRes res;
+ res = VG_(do_syscall3)(__NR_thrkill, lwpid, signo, NULL);
+ return sr_isError(res) ? -1 : 0;
# else
# error "Unsupported plat"

View File

@ -1,5 +1,14 @@
--- coregrind/m_syswrap/priv_syswrap-openbsd.h.orig
+++ coregrind/m_syswrap/priv_syswrap-openbsd.h
@@ -50,7 +50,7 @@
DECL_TEMPLATE(openbsd, sys_open);
DECL_TEMPLATE(openbsd, sys_close);
DECL_TEMPLATE(openbsd, sys_getentropy);
-DECL_TEMPLATE(openbsd, sys___tfork);
+DECL_TEMPLATE(openbsd, sys___tfork_thread);
DECL_TEMPLATE(openbsd, sys_link);
DECL_TEMPLATE(openbsd, sys_unlink);
DECL_TEMPLATE(openbsd, sys_wait4);
@@ -144,6 +144,7 @@
DECL_TEMPLATE(openbsd, sys_pledge);
DECL_TEMPLATE(openbsd, sys_ppoll);

View File

@ -0,0 +1,215 @@
--- coregrind/m_syswrap/syswrap-amd64-openbsd.c.orig
+++ coregrind/m_syswrap/syswrap-amd64-openbsd.c
@@ -120,6 +120,212 @@
#define PRE(name) DEFN_PRE_TEMPLATE(openbsd, name)
#define POST(name) DEFN_POST_TEMPLATE(openbsd, name)
+extern UWord do_syscall_tfork_amd64_openbsd (
+ Addr params,
+ UWord psize,
+ Addr startfunc,
+ Addr startarg);
+asm(
+".text\n"
+".globl do_syscall_tfork_amd64_openbsd\n"
+"do_syscall_tfork_amd64_openbsd:\n"
+ /* Copy %rdx to %r8 and %rcx to %r9. See:
+ - lib/libc/arch/amd64/sys/tfork_thread.S */
+" movq %rdx, %r8\n"
+" movq %rcx, %r9\n"
+" movq $8, %rax\n" /* syscall_no */
+" syscall\n"
+" jb 5f\n" /* error */
+ /*
+ * Check to see if we are in the parent or child
+ */
+" cmpl $0, %eax\n"
+" jz 4f\n" /* child */
+" jmp 5f\n" /* parent */
+ /* the retpoline we'll use to call the child's main */
+".align 16, 0xcc\n" /* _ALIGN_TRAPS */
+"1:\n" /* JMP_RETPOLINE(r8) --> */
+" call 3f\n"
+"2: pause\n"
+" lfence\n"
+" jmp 2b\n"
+".align 16, 0xcc\n" /* _ALIGN_TRAPS */
+"3: mov %r8,(%rsp)\n"
+" ret\n"
+ /* JMP_RETPOLINE(r8) <-- */
+ /*
+ * If we are in the child (new thread), then
+ * set-up the call to the internal subroutine. If it
+ * returns, then call __threxit.
+ */
+".align 16, 0xcc\n" /* _ALIGN_TRAPS */
+"4:\n"
+" movq %r9, %rdi\n"
+" call 1b\n"
+ /*
+ * Thread exit system call
+ */
+" movl $302, %eax\n" /* 302 == SYS___threxit */
+" xorl %edi, %edi\n"
+" syscall\n"
+ /*NOTREACHED*/
+"5:\n" /* parent or error */
+" ret\n"
+".previous\n"
+);
+
+static void setup_child ( ThreadArchState*, ThreadArchState* );
+
+void setup_child ( /*OUT*/ ThreadArchState *child,
+ /*IN*/ ThreadArchState *parent )
+{
+ /* We inherit our parent's guest state. */
+ child->vex = parent->vex;
+ child->vex_shadow1 = parent->vex_shadow1;
+ child->vex_shadow2 = parent->vex_shadow2;
+}
+
+/*
+ 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.
+
+ This function was implemented with reference to the syswrap-amd64-linux.c:
+ do_clone() function.
+ */
+static SysRes do_tfork_thread ( ThreadId ptid,
+ Addr params,
+ ULong psize,
+ Addr startfunc,
+ Addr startarg)
+{
+ ThreadId ctid = VG_(alloc_ThreadState)();
+ ThreadState* ptst = VG_(get_ThreadState)(ptid);
+ ThreadState* ctst = VG_(get_ThreadState)(ctid);
+ UWord* stack;
+ SysRes res;
+ Long rax;
+ vki_sigset_t blockall, savedmask;
+ struct __vki_tfork * tfork;
+
+ VG_(sigfillset)(&blockall);
+
+ vg_assert(params != 0);
+ vg_assert(psize > 0);
+ vg_assert(startfunc != 0);
+ 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 __tfork_thread 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 tfork->tf_stack for the new thread,
+ then it actually gets a copy of the parent's rsp.
+ */
+ setup_child( &ctst->arch, &ptst->arch );
+
+ /* Make sys___tfork appear to have returned Success(0) in the
+ child. */
+ ctst->arch.vex.guest_RAX = 0;
+
+ tfork = (struct __vki_tfork *)params;
+ vg_assert(tfork->tf_stack != 0);
+ ctst->arch.vex.guest_RSP = (ULong) tfork->tf_stack;
+ tfork->tf_stack = stack;
+
+ ctst->os_state.parent = ptid;
+
+ /* inherit signal mask */
+ ctst->sig_mask = ptst->sig_mask;
+ ctst->tmp_sig_mask = ptst->sig_mask;
+
+ /* Start the child with its threadgroup being the same as the
+ parent's. This is so that any exit_group calls that happen
+ after the child is created but before it sets its
+ os_state.threadgroup field for real (in thread_wrapper in
+ syswrap-linux.c), really kill the new thread. a.k.a this avoids
+ a race condition in which the thread is unkillable (via
+ exit_group) because its threadgroup is not set. The race window
+ is probably only a few hundred or a few thousand cycles long.
+ See #226116. */
+ ctst->os_state.threadgroup = ptst->os_state.threadgroup;
+
+ ML_(guess_and_register_stack) ((Addr)tfork->tf_stack, ctst);
+
+ /* 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_assert(VG_(owns_BigLock_LL)(ptid));
+ VG_TRACK ( pre_thread_ll_create, ptid, ctid );
+
+ /* start the thread with everything blocked */
+#if 1 /* for debug by asou */
+ VG_(sigdelset)(&blockall, VKI_SIGTRAP);
+#endif
+ VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask);
+
+ /* Create the new thread */
+ rax = do_syscall_tfork_amd64_openbsd(
+ params, psize, ML_(start_thread_NORETURN), &VG_(threads)[ctid]);
+ res = VG_(mk_SysRes_amd64_openbsd)( rax, ptst->arch.vex.guest_RDX,
+ (rax == -1) ? True : False );
+
+ VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
+
+ out:
+ 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 );
+ }
+
+ return res;
+}
+
+PRE(sys___tfork_thread)
+{
+ struct __vki_tfork * tfork;
+ PRINT("sys___tfork_thread ( %#lx, %ld, %#lx, %#lx )",ARG1,ARG2,ARG3,ARG4);
+ PRE_REG_READ4(long, "__tfork_thread", struct __tfork *, params, size_t, psize,
+ void (*)(void *), startfunc, void *, startarg);
+ PRE_MEM_READ( "__tfork_thread(params, psize)", ARG1, ARG2 );
+ tfork = (struct __vki_tfork *)ARG1;
+ if (tfork->tf_tid != NULL)
+ PRE_MEM_READ("__tfork_thread(params.tf_tid)", (Addr)tfork->tf_tid,
+ sizeof (pid_t));
+ SET_STATUS_from_SysRes(
+ do_tfork_thread(tid, (Addr)ARG1, (ULong)ARG2, (Addr)ARG3, (Addr)ARG4));
+
+ if (SUCCESS) {
+ POST_MEM_WRITE((Addr)tfork->tf_tcb, sizeof (void *));
+ POST_MEM_WRITE((Addr)tfork->tf_tid, sizeof (pid_t));
+
+ /* Thread creation was successful; let the child have the chance
+ to run */
+ *flags |= SfYieldAfter;
+ }
+}
+
#if 0
PRE(sys_thr_new)
{

View File

@ -0,0 +1,16 @@
--- coregrind/m_syswrap/syswrap-generic.c.orig
+++ coregrind/m_syswrap/syswrap-generic.c
@@ -2240,7 +2240,13 @@
/* Otherwise we're OK (so far). Install aspacem's choice of
address, and let the mmap go through. */
sres = VG_(am_do_mmap_NO_NOTIFY)(advised, arg2, arg3,
+#if defined(VGO_openbsd)
+ /* Could not specified VKI_MAP_STACK and VKI_MAP_FIXED at the same
+ time */
+ arg4,
+#else
arg4 | VKI_MAP_FIXED,
+#endif
arg5, arg6);
/* A refinement: it may be that the kernel refused aspacem's choice

View File

@ -1,6 +1,43 @@
--- coregrind/m_syswrap/syswrap-openbsd.c.orig
+++ coregrind/m_syswrap/syswrap-openbsd.c
@@ -575,6 +579,17 @@
@@ -210,21 +210,21 @@
/* : "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 */
+#if 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___threxit), "m" (tst->os_state.exitcode)
+ : "rax", "rdi"
+ );
+#else
+# error Unknown platform
+#endif
VG_(core_panic)("Thread exit failed?\n");
}
@@ -575,6 +575,17 @@
// XXXTBD
}
@ -18,7 +55,154 @@
PRE(sys_getsockname)
{
PRINT("sys_getsockname ( %ld, %#lx, %#lx )",ARG1,ARG2,ARG3);
@@ -4079,7 +4093,7 @@
@@ -791,15 +791,6 @@
SET_STATUS_Success(0);
}
-PRE(sys___tfork)
-{
-// XXXTBD
-}
-POST(sys___tfork)
-{
-// XXXTBD
-}
-
PRE(sys_getlogin)
{
PRINT("sys_getlogin ( %#lx, %ld )",ARG1,ARG2);
@@ -2787,17 +2778,40 @@
PRE(sys___thrsleep)
{
-// XXXTBD
+ *flags |= SfMayBlock;
+ PRINT("__thrsleep( %#lx, %ld, %#lx, %#lx, %#lx )", ARG1,ARG2,ARG3,ARG4,ARG5);
+ PRE_REG_READ5(int, "__thrsleep",
+ void *, id,
+ int, clock_id,
+ struct timespec *, abstime,
+ void *, lock,
+ int *, abort);
+ if (ARG3 != 0)
+ PRE_MEM_READ(" __thrsleep(abstime)", ARG3, sizeof(struct timespec));
+ if (ARG5 != 0)
+ PRE_MEM_READ(" __thrsleep(abort)", ARG5, sizeof (int));
}
PRE(sys___thrwakeup)
{
-// XXXTBD
+ PRINT("__thrwakeup( %#lx, %ld, %#lx, %#lx, %#lx )", ARG1,ARG2,ARG3,ARG4,ARG5);
+ PRE_REG_READ2(int, "__thrwakeup",
+ void *, id,
+ int, count);
}
PRE(sys___threxit)
{
-// XXXTBD
+ ThreadState* tst;
+ /* simple; just make this thread exit */
+ PRINT("__threxit( %#lx )", ARG1);
+ PRE_REG_READ1(void, "__threxit", void *, value_ptr);
+ tst = VG_(get_ThreadState)(tid);
+ /* Set the thread's status to be exiting, then claim that the
+ syscall succeeded. */
+ tst->exitreason = VgSrc_ExitThread;
+ /* tst->os_state.exitcode = ARG1; */
+ SET_STATUS_Success(0);
}
PRE(sys___thrsigdivert)
@@ -2830,6 +2843,68 @@
// XXXTBD
}
+PRE(sys_futex)
+{
+ /*
+ arg param used by ops
+
+ ARG1 - uint32_t *uaddr all
+ ARG2 - int op
+ ARG3 - int val WAIT,WAKE,REQUEUE
+ ARG4 - struct timespec *utime WAIT, REQUEUE
+ ARG5 - uint32_t *uaddr2 REQUEUE
+ */
+ PRINT("sys_futex ( %#lx, %ld, %ld, %#lx, %#lx )", ARG1,ARG2,ARG3,ARG4,ARG5);
+ switch(ARG2 & ~VKI_FUTEX_PRIVATE_FLAG) {
+ case VKI_FUTEX_WAIT:
+ PRE_REG_READ4(long, "futex",
+ vki_uint32_t *, uaddr, int, op, int, val,
+ struct timespec *, utime);
+ break;
+ case VKI_FUTEX_WAKE:
+ PRE_REG_READ3(long, "futex",
+ vki_uint32_t *, uaddr, int, op, int, val);
+ break;
+ case VKI_FUTEX_REQUEUE:
+ PRE_REG_READ5(long, "futex",
+ vki_uint32_t *, uaddr, int, op, int, val,
+ struct timespec *, utime, vki_uint32_t *, uaddr2);
+ break;
+ default:
+ PRE_REG_READ2(long, "futex", vki_uint32_t *, uaddr, int, op);
+ break;
+ }
+
+ *flags |= SfMayBlock;
+
+ switch(ARG2 & ~VKI_FUTEX_PRIVATE_FLAG) {
+ case VKI_FUTEX_WAIT:
+ PRE_MEM_READ( "futex(uaddr)", ARG1, sizeof(Int) );
+ if (ARG4 != 0)
+ PRE_MEM_READ( "futex(timeout)", ARG4, sizeof(struct vki_timespec) );
+ break;
+
+ case VKI_FUTEX_WAKE:
+ /* no additional pointers */
+ break;
+
+ case VKI_FUTEX_REQUEUE:
+ PRE_MEM_READ( "futex(uaddr)", ARG1, sizeof(Int) );
+ PRE_MEM_READ( "futex(val2)", ARG4, sizeof(Int) );
+ PRE_MEM_READ( "futex(uaddr2)", ARG5, sizeof(Int) );
+ break;
+
+ default:
+ SET_STATUS_Failure( VKI_ENOSYS ); // some futex function we don't understand
+ break;
+ }
+}
+POST(sys_futex)
+{
+ vg_assert(SUCCESS);
+ POST_MEM_WRITE( ARG1, sizeof(int) );
+}
+
PRE(sys_utimensat)
{
// XXXTBD
@@ -3961,7 +4036,7 @@
GENXY(__NR_close, sys_close), // 6
BSDXY(__NR_getentropy, sys_getentropy), // 7
- BSDXY(__NR___tfork, sys___tfork), // 8
+ BSDX_(__NR___tfork_thread, sys___tfork_thread), // 8
GENX_(__NR_link, sys_link), // 9
GENX_(__NR_unlink, sys_unlink), // 10
@@ -4053,7 +4128,7 @@
GENX_(__NR_getpgrp, sys_getpgrp), // 81
GENX_(__NR_setpgid, sys_setpgid), // 82
- BSDX_(__NR_osendsyslog, sys_sendsyslog), // 83
+ BSDXY(__NR_futex, sys_futex), // 83
BSDX_(__NR_utimensat, sys_utimensat), // 84
BSDX_(__NR_futimens, sys_futimens), // 85
@@ -4079,7 +4094,7 @@
BSDX_(__NR_sigsuspend, sys_sigsuspend), // 111
BSDX_(__NR_sendsyslog, sys_sendsyslog), // 112
// obsol orecvmsg // 113
@ -27,4 +211,3 @@
// obsol vtrace // 115
BSDX_(__NR_getsockopt, sys_getsockopt), // 118
Only in pobj/valgrind-3.10.1/valgrind-3.10.1/coregrind/m_syswrap: syswrap-openbsd.c.orig

View File

@ -0,0 +1,18 @@
--- coregrind/m_syswrap/syswrap-x86-openbsd.c.orig
+++ coregrind/m_syswrap/syswrap-x86-openbsd.c
@@ -525,6 +525,15 @@
#define PRE(name) DEFN_PRE_TEMPLATE(openbsd, name)
#define POST(name) DEFN_POST_TEMPLATE(openbsd, name)
+PRE(sys___tfork_thread)
+{
+// XXXTBD
+}
+POST(sys___tfork_thread)
+{
+// XXXTBD
+}
+
#if 0
struct thr_param {
void (*start_func)(void *); /* thread entry function. */

View File

@ -1,5 +1,21 @@
--- include/vki/vki-openbsd.h.orig
+++ include/vki/vki-openbsd.h
@@ -76,6 +76,15 @@
//----------------------------------------------------------------------
+// From linux-2.6.31-rc4/include/linux/futex.h
+//----------------------------------------------------------------------
+
+#define VKI_FUTEX_WAIT (1)
+#define VKI_FUTEX_WAKE (2)
+#define VKI_FUTEX_REQUEUE (3)
+#define VKI_FUTEX_PRIVATE_FLAG (128)
+
+//----------------------------------------------------------------------
// From sys/select.h
//----------------------------------------------------------------------
@@ -1544,9 +1544,9 @@
#define VKI_MAP_PRIVATE 0x02 /* Changes are private */
#define VKI_MAP_FIXED 0x10 /* Interpret addr exactly */
@ -11,3 +27,16 @@
//----------------------------------------------------------------------
// From sys/stat.h
@@ -1650,6 +1659,12 @@
#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 */
+
+struct __vki_tfork {
+ void *tf_tcb;
+ pid_t *tf_tid;
+ void *tf_stack;
+};
//----------------------------------------------------------------------
// From sys/msg.h

View File

@ -1,5 +1,23 @@
--- include/vki/vki-scnums-openbsd.h.orig
+++ include/vki/vki-scnums-openbsd.h
@@ -41,7 +41,7 @@
#define __NR_open 5
#define __NR_close 6
#define __NR_getentropy 7
-#define __NR___tfork 8
+#define __NR___tfork_thread 8
#define __NR_link 9
#define __NR_unlink 10
#define __NR_wait4 11
@@ -116,7 +116,7 @@
#define __NR_setgroups 80
#define __NR_getpgrp 81
#define __NR_setpgid 82
-#define __NR_osendsyslog 83
+#define __NR_futex 83
#define __NR_utimensat 84
#define __NR_futimens 85
#define __NR_kbind 86
@@ -146,6 +146,7 @@
#define __NR_pselect 110
#define __NR_sigsuspend 111