Skip to content

ptrace

Partial in Antinomie 0.7.0 · Syscall list

long ptrace(long request, long pid, unsigned long addr, unsigned long data);
Number (x86-64) 101
ABI 64
Kernel entry point sys_ptrace

This is the raw kernel prototype from the pinned Linux 6.12.94 schema, not the libc wrapper.

Lets one process observe and control another: attach, read and write its memory and registers, and step it.

Name Type Meaning
request (arg0) long ptrace request code (PTRACE_PEEKDATA, PTRACE_ATTACH, …).
pid (arg1) long Thread id of the tracee.
addr (arg2) unsigned long Request-specific address or value; for PEEK/POKE requests an address in the tracee.
data (arg3) unsigned long Request-specific value or pointer, often in the tracer.

On success: a request-specific value.

In an Antinomie trace the Return column and the ret filter field show the raw kernel return value. On failure that is the negative errno, for example -2 for ENOENT, not the -1 plus errno that the libc wrapper gives. syscall.errno holds the positive errno and syscall.success is false.

Raw return Name Meaning
-16 EBUSY The resource is busy.
-5 EIO An input/output error occurred.
-1 EPERM The operation is not permitted for this process.
-3 ESRCH No such process or thread.

ptrace(2) on man7.org

Coverage mark: Partial. Requests decode what lies in the tracer’s memory. Addresses in the tracee (PEEK*/POKE*) are “address only” and never read, and an unknown request records a ptrace.unknown_selector “no decoder” gap.

Every call is recorded as an Entry record (the six argument words and the pointees copied at entry) and an Exit record (the return value and the pointees copied at exit).

Argument When How Recorded field key Condition
request (arg0) Entry raw scalar word args.0, args.request
pid (arg1) Entry raw scalar word args.1, args.pid
addr (arg2) Entry raw scalar word args.2, args.addr
data (arg3) Entry raw scalar word args.3, args.data
  • Selector: request. Fields live in the tracer’s memory and are copied: arg3.regs, arg3.fpregs, arg3.siginfo, arg3.sigmask, arg3.word, arg3.message, arg3.desc, arg3.config, register sets through arg3.iovec, and so on, input at entry and output at exit when the request succeeds.
  • Tracee addresses (PEEKTEXT, PEEKDATA, POKETEXT, POKEDATA) are recorded as arg2.tracee_address with the “address only” status and are never dereferenced.

arg2.tracee_address, arg3.word, arg3.regs, arg3.fpregs, arg3.siginfo, arg2.args, arg3.sigmask, arg3.message, arg3.desc, arg2.value, arg3.info, arg3.config, arg3.filter, arg3.filter_off, arg3.metadata, ptrace.unknown_selector, arg3.iovec, arg3.iovec.data, arg3.iov_len. When and how each is recorded: Not documented yet.

  • Result: ret, syscall.errno, syscall.success, syscall.duration_ns.
  • Argument words: args.request (arg0), args.pid (arg1), args.addr (arg2), args.data (arg3); args.0 to args.5 by position.
  • Structure ptrace_peeksiginfo_args behind addr (arg2): args.addr.<member> for flags, nr, off.
  • Structure user_regs_struct behind data (arg3): args.data.<member> for ax, bp, bx, cs, cx, di, ds, dx, es, flags, fs, fs_base, gs, gs_base, ip, orig_ax, r10, r11, r12, r13, r14, r15, r8, r9, si, sp, ss.

See Syscall Trace filter for the full syntax.

  • See the coverage mark above for the code paths that record a gap.

For what the capture statuses mean, see Capture statuses. For what is never recorded, see Known gaps.