1#ifndef PTRACE_CONTRACT_H
2#define PTRACE_CONTRACT_H
12#include "entry-layout.h"
13#include "sentinel-layout.h"
14#include <sys/ptrace.h>
15#include <sys/syscall.h>
20#if !defined(__x86_64__) || defined(__ILP32__)
21#error This draft requires the musl amd64 ABI.
24#define TC_ARCH_GET_FS 0x1003
25#define TC_STOP_SIGNAL SIGUSR1
26#define TC_EXECUTABLE "/applications/ptrace-contract-test"
27#define TC_ENTRY_EXECUTABLE "/applications/ptrace-entry-test"
28#define TC_EXIT_CODE 17
29#define TC_IMAGE_TLS UINT64_C(0x1938574629183746)
30#define CHECK(condition) \
33 fprintf(stderr, "%s:%d: %s (errno=%d)\n", __FILE__, __LINE__, #condition, errno); \
40 uint64_t pid, tid, fs_base, stack, label, cs, ss, ds, es, fs, gs;
46 struct user_regs_struct resumed;
51 struct user_regs_struct registers;
55#define TC_OFFSET(type, field, offset) \
56 _Static_assert(offsetof(type, field) == (offset), "assembly offset: " #field)
57TC_OFFSET(
struct tc_setup, pid, TC_PID);
58TC_OFFSET(
struct tc_setup, tid, TC_TID);
59TC_OFFSET(
struct tc_setup, fs_base, TC_FS_BASE);
60TC_OFFSET(
struct tc_setup, stack, TC_STACK);
61TC_OFFSET(
struct tc_setup, label, TC_LABEL);
62TC_OFFSET(
struct tc_setup, cs, TC_CS);
63TC_OFFSET(
struct tc_setup, ss, TC_SS);
64TC_OFFSET(
struct tc_setup, ds, TC_DS);
65TC_OFFSET(
struct tc_setup, es, TC_ES);
66TC_OFFSET(
struct tc_setup, fs, TC_FS);
67TC_OFFSET(
struct tc_setup, gs, TC_GS);
68TC_OFFSET(
struct tc_capture, entry_flags, TC_ENTRY_FLAGS);
69TC_OFFSET(
struct tc_capture, resumed, TC_RESUMED);
73TC_OFFSET(
struct user_regs_struct, r15, TC_R15);
74TC_OFFSET(
struct user_regs_struct, r14, TC_R14);
75TC_OFFSET(
struct user_regs_struct, r13, TC_R13);
76TC_OFFSET(
struct user_regs_struct, r12, TC_R12);
77TC_OFFSET(
struct user_regs_struct, rbp, TC_RBP);
78TC_OFFSET(
struct user_regs_struct, rbx, TC_RBX);
79TC_OFFSET(
struct user_regs_struct, r11, TC_R11);
80TC_OFFSET(
struct user_regs_struct, r10, TC_R10);
81TC_OFFSET(
struct user_regs_struct, r9, TC_R9);
82TC_OFFSET(
struct user_regs_struct, r8, TC_R8);
83TC_OFFSET(
struct user_regs_struct, rax, TC_RAX);
84TC_OFFSET(
struct user_regs_struct, rcx, TC_RCX);
85TC_OFFSET(
struct user_regs_struct, rdx, TC_RDX);
86TC_OFFSET(
struct user_regs_struct, rsi, TC_RSI);
87TC_OFFSET(
struct user_regs_struct, rdi, TC_RDI);
88TC_OFFSET(
struct user_regs_struct, orig_rax, TC_ORIG_RAX);
89TC_OFFSET(
struct user_regs_struct, rip, TC_RIP);
90TC_OFFSET(
struct user_regs_struct, cs, TC_REG_CS);
91TC_OFFSET(
struct user_regs_struct, eflags, TC_EFLAGS);
92TC_OFFSET(
struct user_regs_struct, rsp, TC_RSP);
93TC_OFFSET(
struct user_regs_struct, ss, TC_REG_SS);
94TC_OFFSET(
struct user_regs_struct, fs_base, TC_REG_FS_BASE);
95TC_OFFSET(
struct user_regs_struct, gs_base, TC_REG_GS_BASE);
96TC_OFFSET(
struct user_regs_struct, ds, TC_REG_DS);
97TC_OFFSET(
struct user_regs_struct, es, TC_REG_ES);
98TC_OFFSET(
struct user_regs_struct, fs, TC_REG_FS);
99TC_OFFSET(
struct user_regs_struct, gs, TC_REG_GS);
102_Static_assert(
sizeof(
struct tc_setup) == TC_SETUP_SIZE,
"setup size");
103_Static_assert(
sizeof(
struct user_regs_struct) == TC_REG_SIZE,
"musl register ABI changed");
104_Static_assert(
sizeof(siginfo_t) == 128,
"musl siginfo ABI changed");
105_Static_assert(
sizeof(
struct tc_capture) == TC_CAPTURE_SIZE,
"capture size");
106_Static_assert(
sizeof(
struct tc_entry_record) == TC_ENTRY_SIZE,
"entry record size");
107_Static_assert(SYS_arch_prctl == 158 && SYS_exit == 60,
"entry syscall ABI");
108_Static_assert(SYS_write == 1 && SYS_getpid == 39 && SYS_tgkill == 234,
"asm syscall ABI");
109_Static_assert(TC_STOP_SIGNAL == 10,
"asm signal ABI");
112int tc_read(
int fd,
void* data,
size_t size);
113int tc_write(
int fd,
const void* data,
size_t size);
114int tc_wait(pid_t pid,
int* status,
int milliseconds);
115void tc_cleanup(pid_t* pid);
116int tc_probe(
int report_fd,
struct tc_capture* capture);
117int tc_registers(
void);
123#define TC_CHILD_INIT {.pid = -1, .command = -1, .report = -1}
125 int operation, signal;
128 int kind, signal, code, error;
134extern size_t tc_page;
135extern _Thread_local
volatile uint64_t tc_image_tls;
136int tc_atomic_wait(atomic_uint* value,
unsigned expected);
137int tc_spawn(
struct tc_child* child,
int traced);
138void tc_tracee(
int command,
int report,
int traced);
139void tc_close(
struct tc_child* child);
140int tc_send(
const struct tc_child* child,
int operation,
int signal);
142int tc_stop(
struct tc_child* child,
int signal);
143int tc_wait_stop(
struct tc_child* child,
int signal);
144int tc_finish(
struct tc_child* child);
145int tc_resume(pid_t child,
int request,
int signal);
146int tc_signal_info(
const siginfo_t* info,
int signal,
int code, pid_t pid, uid_t uid);
149int tc_ownership(
void);
150int tc_lifecycle(
void);
152int tc_exec_child(
int report);
153int tc_exec_tracer(pid_t child,
int command,
int report);