FreeBSD Bugzilla – Attachment 219487 Details for
Bug 250954
ptrace(): weird ordering between inheriting debug registers and reporting a new thread
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
print the list of threads on each stop
thread-dbreg-test-pt2.c (text/plain), 3.60 KB, created by
Konstantin Belousov
on 2020-11-09 11:50:07 UTC
(
hide
)
Description:
print the list of threads on each stop
Filename:
MIME Type:
Creator:
Konstantin Belousov
Created:
2020-11-09 11:50:07 UTC
Size:
3.60 KB
patch
obsolete
>/* $Id: thread-dbreg-test-pt2.c,v 1.7 2020/11/09 11:42:26 kostik Exp kostik $ */ > >#include <sys/types.h> >#include <sys/ptrace.h> >#include <sys/wait.h> >#include <machine/reg.h> >#include <assert.h> >#include <err.h> >#include <pthread.h> >#include <signal.h> >#include <stdint.h> >#include <stdio.h> >#include <unistd.h> > >volatile int g_val; >volatile int g_val2; > >static void * >thread_func(void* foo __unused) { > return (NULL); >} > >static void >waitdbg(pid_t pid, int sig) >{ > pid_t waited; > int nthr, ret; > > waited = waitpid(pid, &ret, 0); > printf("wait: pid=%d, waited=%d, ret=%x\n", pid, waited, ret); > assert(waited == pid); > if (sig < 0) { > assert(WIFEXITED(ret)); > return; > } > > assert(WSTOPSIG(ret) == sig); > > nthr = ptrace(PT_GETNUMLWPS, pid, NULL, 0); > if (nthr == -1) > err(1, "PT_GETNUMLWPS"); > lwpid_t ids[nthr]; > ret = ptrace(PT_GETLWPLIST, pid, (caddr_t)&ids, nthr); > if (ret == -1) > err(1, "PT_GETLWPLIST"); > printf("threads:"); > for (int i = 0; i < nthr; i++) > printf(" %d", ids[i]); > printf("\n"); >} > >int >main(void) >{ > int ret; > int pid = fork(); > assert(pid != -1); > if (pid == 0) { > pthread_t t2; > > ret = ptrace(PT_TRACE_ME, 0, NULL, 0); > assert(ret != -1); > // 2. wait for parent to set dbregs > raise(SIGSTOP); > > // 4. start new thread and stop immediately afterwards > ret = pthread_create(&t2, NULL, thread_func, NULL); > assert(ret == 0); > raise(SIGSTOP); > printf("thread started\n"); > > ret = pthread_join(t2, NULL); > assert(ret == 0); > printf("thread joined\n"); > _exit(0); > } > > // 1. wait for the child to start > waitdbg(pid, SIGSTOP); > > struct ptrace_lwpinfo info; > ret = ptrace(PT_LWPINFO, pid, (caddr_t)&info, sizeof(info)); > assert(ret != -1); > assert(info.pl_flags == PL_FLAG_SI); > printf("tid = %d, SIGSTOP\n", info.pl_lwpid); > > // 3. set event mask & dbregs > int ev = PTRACE_LWP; > ret = ptrace(PT_SET_EVENT_MASK, pid, (caddr_t)&ev, sizeof(ev)); > assert(ret != -1); > > struct dbreg db; > ret = ptrace(PT_GETDBREGS, info.pl_lwpid, (caddr_t)&db, 0); > assert(ret != -1); > > db.dr[0] = (uintptr_t)&g_val; > db.dr[7] = 0x303; > ret = ptrace(PT_SETDBREGS, info.pl_lwpid, (caddr_t)&db, 0); > assert(ret != -1); > printf("set DR0=%p (&g_val) on tid=%d\n", (void*)db.dr[0], info.pl_lwpid); > > ret = ptrace(PT_CONTINUE, pid, (caddr_t)1, 0); > assert(ret != -1); > > // 5. we should get SIGSTOP first, change dbregs > waitdbg(pid, SIGSTOP); > > ret = ptrace(PT_LWPINFO, pid, (caddr_t)&info, sizeof(info)); > assert(ret != -1); > assert(info.pl_flags == PL_FLAG_SI); > printf("tid = %d, SIGSTOP\n", info.pl_lwpid); > > ret = ptrace(PT_GETDBREGS, info.pl_lwpid, (caddr_t)&db, 0); > assert(ret != -1); > > db.dr[0] = (uintptr_t)&g_val2; > db.dr[7] = 0x303; > ret = ptrace(PT_SETDBREGS, info.pl_lwpid, (caddr_t)&db, 0); > assert(ret != -1); > printf("set DR0=%p (&g_val2) on tid=%d\n", (void*)db.dr[0], info.pl_lwpid); > > ret = ptrace(PT_CONTINUE, pid, (caddr_t)1, 0); > assert(ret != -1); > > // 6. now we should get the new thread event > waitdbg(pid, SIGTRAP); > > ret = ptrace(PT_LWPINFO, pid, (caddr_t)&info, sizeof(info)); > assert(ret != -1); > assert(info.pl_flags & PL_FLAG_BORN); > printf("tid = %d, SIGTRAP w/ PL_FLAG_BORN\n", info.pl_lwpid); > > ret = ptrace(PT_GETDBREGS, info.pl_lwpid, (caddr_t)&db, 0); > assert(ret != -1); > printf("dr0=%p, g_val=%p, g_val2=%p\n", (void*)db.dr[0], &g_val, &g_val2); > > ret = ptrace(PT_CONTINUE, pid, (caddr_t)1, 0); > assert(ret != -1); > > // thread exited > waitdbg(pid, SIGTRAP); > > ret = ptrace(PT_LWPINFO, pid, (caddr_t)&info, sizeof(info)); > assert(ret != -1); > assert(info.pl_flags & PL_FLAG_EXITED); > printf("tid = %d, SIGTRAP w/ PL_FLAG_EXITED\n", info.pl_lwpid); > > ret = ptrace(PT_CONTINUE, pid, (caddr_t)1, 0); > assert(ret != -1); > > waitdbg(pid, -1); >}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 250954
:
219458
|
219480
| 219487