10static int peek(pid_t pid, siginfo_t* info) {
11 int64_t now = tc_now(), end = now + INT64_C(10000000000);
12 while (now >= 0 && now < end) {
13 if (waitid(P_PID, pid, info, WSTOPPED | WNOWAIT | WNOHANG))
27 struct tc_child child = TC_CHILD_INIT;
33 struct user_regs_struct registers, saved;
34 CHECK(tc_spawn(&child, 1) == 0 && tc_send(&child,
'S', SIGUSR1) == 0);
35 for (
unsigned i = 0; i < 3; ++i) {
36 memset(&event, 0xa5,
sizeof(event));
37 CHECK(peek(child.pid, &event) == 0);
38 CHECK(event.si_signo == SIGCHLD && !event.si_errno && event.si_code == CLD_TRAPPED &&
39 event.si_pid == child.pid && event.si_uid == getuid() && event.si_status == SIGUSR1);
41 CHECK(tc_wait_stop(&child, SIGUSR1) == 0);
42 memset(&event, 0xa5,
sizeof(event));
43 CHECK(waitid(P_PID, child.pid, &event, WSTOPPED | WNOHANG) == 0);
44 CHECK(!event.si_signo && !event.si_errno && !event.si_code && !event.si_pid && !event.si_uid &&
47 memset(&first, 0xa5,
sizeof(first));
48 memset(&second, 0x5a,
sizeof(second));
49 CHECK(ptrace(PTRACE_GETSIGINFO, child.pid, (
void*)0, (
void*)&first.info) == 0);
50 CHECK(ptrace(PTRACE_GETSIGINFO, child.pid, (
void*)0, (
void*)&second.info) == 0);
51 CHECK(tc_signal_info(&first.info, SIGUSR1, SI_TKILL, child.pid, getuid()) == 0);
52 CHECK(memcmp(&first.info, &second.info,
sizeof(siginfo_t)) == 0);
53 CHECK(first.tail[0] == UINT64_C(0xa5a5a5a5a5a5a5a5) &&
54 first.tail[1] == UINT64_C(0xa5a5a5a5a5a5a5a5));
55 CHECK(second.tail[0] == UINT64_C(0x5a5a5a5a5a5a5a5a) &&
56 second.tail[1] == UINT64_C(0x5a5a5a5a5a5a5a5a));
57 CHECK(ptrace(PTRACE_GETREGS, child.pid, (
void*)0, (
void*)®isters) == 0);
59 const size_t lengths[] = {0, 8, TC_REG_SIZE, TC_REG_SIZE + 32, SIZE_MAX & ~(size_t)7};
60 for (
size_t i = 0; i <
sizeof(lengths) /
sizeof(lengths[0]); ++i) {
61 unsigned char data[TC_REG_SIZE + 32];
62 memset(data, 0xa5,
sizeof(data));
63 struct iovec vector = {.iov_base = lengths[i] ? data + 1 : NULL, .iov_len = lengths[i]};
64 void* original = vector.iov_base;
65 CHECK(ptrace(PTRACE_GETREGSET, child.pid, (
void*)(uintptr_t)NT_PRSTATUS, (
void*)&vector) == 0);
66 size_t copied = lengths[i] > TC_REG_SIZE ? TC_REG_SIZE : lengths[i];
67 CHECK(vector.iov_base == original && vector.iov_len == copied);
68 CHECK(memcmp(data + 1, ®isters, copied) == 0 && data[0] == 0xa5);
69 for (
size_t j = copied + 1; j <
sizeof(data); ++j)
70 CHECK(data[j] == 0xa5);
72 struct iovec vector = {.iov_base = ®isters, .iov_len = TC_REG_SIZE};
73 CHECK(ptrace(PTRACE_GETREGSET, child.pid, (
void*)(uintptr_t)(UINT64_C(0x100000000) | NT_PRSTATUS),
74 (
void*)&vector) == 0);
75 CHECK(memcmp(®isters, &saved, TC_REG_SIZE) == 0);
76 CHECK(tc_resume(child.pid, PTRACE_CONT, 0) == 0 && tc_receive(child.report,
'A', NULL) == 0);
77 CHECK(memcmp(®isters, &saved, TC_REG_SIZE) == 0);
78 CHECK(tc_finish(&child) == 0);