10_Thread_local
volatile uint64_t tc_image_tls = TC_IMAGE_TLS;
11static volatile sig_atomic_t handler_report = -1;
13static void caught(
int signal, siginfo_t* info,
void* context) {
18 .code = info->si_code,
21 ssize_t ignored = write(handler_report, &
message,
sizeof(
message));
27 atomic_uint ready, finish;
30static void* remain_alive(
void* argument) {
31 struct alive* state = argument;
32 atomic_store(&state->ready, 1);
33 tc_atomic_wait(&state->finish, 1);
37static long multithreaded_enrollment(
int* error) {
38 struct alive state = {0};
40 int result = pthread_create(&thread, NULL, remain_alive, &state);
46 if (!tc_atomic_wait(&state.ready, 1)) {
48 enrolled = ptrace(PTRACE_TRACEME, (pid_t)0, (
void*)0, (
void*)0);
51 atomic_store(&state.finish, 1);
52 if (pthread_join(thread, NULL))
57void tc_tracee(
int command,
int report,
int traced) {
61 struct sigaction action = {.sa_sigaction = caught, .sa_flags = SA_SIGINFO};
62 sigemptyset(&action.sa_mask);
63 handler_report = report;
64 if (sigprocmask(SIG_SETMASK, &empty, NULL) || sigaction(SIGUSR1, &action, NULL) ||
65 sigaction(SIGUSR2, &action, NULL))
70 ready.result = ptrace(PTRACE_TRACEME, (pid_t)0, (
void*)0, (
void*)0);
73 if (tc_write(report, &ready,
sizeof(ready)) || ready.result)
77 if (tc_read(command, &request,
sizeof(request)))
79 struct tc_message reply = {.kind = request.operation, .signal = request.signal};
81 switch (request.operation) {
84 reply.result = syscall(SYS_tgkill, getpid(), syscall(SYS_gettid), request.signal);
88 action.sa_handler = request.operation ==
'I' ? SIG_IGN : SIG_DFL;
90 reply.result = sigaction(request.signal, &action, NULL);
96 sigaddset(&mask, request.signal);
97 reply.result = sigprocmask(request.operation ==
'B' ? SIG_BLOCK : SIG_UNBLOCK, &mask, NULL);
101 reply.result = prctl(PR_SET_DUMPABLE, 0UL, 0UL, 0UL, 0UL);
105 ptrace(PTRACE_TRACEME, (pid_t)424242, (
void*)UINTPTR_MAX, (
void*)UINTPTR_MAX);
108 reply.result = multithreaded_enrollment(&reply.error);
113 sigaddset(&mask, request.signal);
114 struct timespec immediate = {0, 0};
115 for (
unsigned i = 0; i < 16; ++i) {
117 int signal = sigtimedwait(&mask, &info, &immediate);
118 if (signal != request.signal || info.si_code != SI_QUEUE ||
119 info.si_value.sival_int != (
int)i + 100) {
129 tc_image_tls ^= UINT64_C(0xffffffffffffffff);
131 snprintf(descriptor,
sizeof(descriptor),
"%d", report);
132 if (fcntl(report, F_SETFD, 0))
134 if (request.operation ==
'X')
135 execl(TC_EXECUTABLE, TC_EXECUTABLE,
"--exec-child", descriptor, (
char*)NULL);
137 execl(TC_ENTRY_EXECUTABLE, TC_ENTRY_EXECUTABLE, descriptor, (
char*)NULL);
147 if (request.operation !=
'M')
149 if (tc_write(report, &reply,
sizeof(reply)))
151 if (request.operation ==
'E')
156int tc_exec_child(
int report) {
158 struct tc_message message = {.kind =
'X', .pid = getpid(), .value = tc_image_tls};
159 if (tc_image_tls != TC_IMAGE_TLS || tc_write(report, &
message,
sizeof(
message)))