https://github.com/ydah/rptrace
Ruby wrapper for Linux `ptrace(2)` focused on building tracers and debugger-like tooling with a Ruby-friendly API.
https://github.com/ydah/rptrace
building debugger linux ptrace ruby tool tracer
Last synced: 3 months ago
JSON representation
Ruby wrapper for Linux `ptrace(2)` focused on building tracers and debugger-like tooling with a Ruby-friendly API.
- Host: GitHub
- URL: https://github.com/ydah/rptrace
- Owner: ydah
- License: mit
- Created: 2026-02-21T00:34:55.000Z (4 months ago)
- Default Branch: main
- Last Pushed: 2026-02-21T12:11:54.000Z (4 months ago)
- Last Synced: 2026-02-25T22:23:03.288Z (4 months ago)
- Topics: building, debugger, linux, ptrace, ruby, tool, tracer
- Language: Ruby
- Homepage:
- Size: 98.6 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE.txt
Awesome Lists containing this project
README
# rptrace [](https://badge.fury.io/rb/rptrace) [](https://github.com/ydah/rptrace/actions/workflows/main.yml)
`rptrace` is a Ruby wrapper for Linux `ptrace(2)` focused on building tracers and debugger-like tooling with a Ruby-friendly API.
## Overview and Motivation
Linux `ptrace(2)` is powerful but low-level. This gem wraps process control, register/memory access, and syscall decoding behind a small Ruby API so you can build:
- `strace`-like tools
- process instrumentation utilities
- debugger-oriented experiments
## Features
- Top-level namespace is `Rptrace` (no `Rptrace::Ruby` nesting)
- `Tracee` API for `spawn`, `attach`, `cont`, `syscall`, `detach`, and `wait`
- Register and memory wrappers (`Registers`, `Memory`)
- `/proc//maps` parser (`ProcMaps`, `Tracee#memory_maps`)
- Software breakpoints on x86_64 (`Tracee#set_breakpoint`, `remove_breakpoint`)
- Syscall lookup (`Rptrace::Syscall`) for `x86_64`/`aarch64`
- High-level tracing helper `Rptrace.strace` (`follow_children` / `yield_seccomp` supported)
- ptrace event helpers (`Tracee#event_message`, `Tracee#seccomp_data`, `Tracee#seccomp_metadata`, `Tracee#seccomp_filter`)
## Installation
Add this line to your application's Gemfile:
```ruby
gem "rptrace"
```
And then execute:
```bash
bundle install
```
## Quick Start
```ruby
require "rptrace"
Rptrace.strace("/bin/ls", "-la", "/tmp") do |event|
next unless event.exit?
puts event
end
```
Follow child processes/threads (clone/fork/vfork):
```ruby
Rptrace.strace("/usr/bin/ruby", "-e", "pid = fork { sleep 0.1 }; Process.wait(pid)", follow_children: true) do |event|
next unless event.enter?
puts "pid=#{event.tracee.pid} #{event.syscall.name}"
end
```
Include seccomp stop events in trace stream:
```ruby
Rptrace.strace("/bin/ls", "/tmp", yield_seccomp: true) do |event|
case event
when Rptrace::SyscallEvent
puts event if event.exit?
when Rptrace::SeccompEvent
warn event.to_s
end
end
```
Set and clear a software breakpoint (x86_64):
```ruby
tracee = Rptrace::Tracee.attach(target_pid)
bp = tracee.set_breakpoint(0x401000)
# ...
bp.restore
```
Inspect seccomp filter metadata and decoded BPF instructions:
```ruby
tracee = Rptrace::Tracee.attach(target_pid)
tracee.enable_seccomp_events!
supported = tracee.seccomp_supported?
available = tracee.seccomp_filter_available?(index: 0)
meta = tracee.seccomp_metadata(index: 0) # => { filter_off: 0, flags: ... }
flag_names = tracee.seccomp_metadata_flag_names(index: 0) # => [:tsync, :log, ...]
insns = tracee.seccomp_filter(index: 0) # => [{ code:, jt:, jf:, k: }, ...]
```
## Permission Guide
`ptrace` requires privilege on Linux:
- run as `root`, or
- run with `CAP_SYS_PTRACE`, and
- ensure Yama policy allows tracing (`/proc/sys/kernel/yama/ptrace_scope`)
Integration specs are opt-in and require:
```bash
PTRACE_RUN_INTEGRATION=1 bundle exec rspec spec/integration
```
You can inspect local ptrace capability setup from Ruby:
```ruby
diagnostics = Rptrace.ptrace_permissions
puts diagnostics # => { ptrace_privileged:, cap_sys_ptrace:, yama_ptrace_scope:, hints: [...] }
```
Fail fast with an actionable permission error:
```ruby
Rptrace.ensure_ptrace_privileged!(request: :attach)
```
## Examples
- `examples/simple_strace.rb`
- `examples/syscall_counter.rb`
- `examples/file_access_tracer.rb`
- `examples/memory_reader.rb`
## API Reference
- Generate docs: `bundle exec yard doc`
- Open index: `doc/index.html`
## Development
```bash
bundle exec rspec
```
Run specs with coverage threshold check:
```bash
COVERAGE=1 COVERAGE_MIN_LINE=95 bundle exec rspec spec/unit spec/rptrace_spec.rb
```
Generate syscall tables from Linux headers (`x86_64` / `aarch64`):
```bash
bundle exec rake syscall:generate
```
You can override header paths with:
- `PTRACE_SYSCALL_HEADER_X86_64`
- `PTRACE_SYSCALL_HEADER_AARCH64`
Optional task controls:
- `ARCH=x86_64` (or `ARCH=x86_64,aarch64`) to limit architectures
- `STRICT=1` to fail if any requested architecture header is missing
Generate YARD documentation:
```bash
bundle exec yard doc
```
## Release
- CI release workflow: `.github/workflows/release.yml`
- Trigger by pushing a tag (example: `v0.1.0`) or via `workflow_dispatch`
- Set repository secret `RUBYGEMS_API_KEY` to enable `gem push`
- Local preflight: `bundle exec rake release:preflight`
- Local credential check: `bundle exec rake release:check_credentials`
## Limitations
- Linux only
- Ruby 3.1+
- Architecture support: `x86_64` and `aarch64`
- Integration tests require ptrace permission (`root` or `CAP_SYS_PTRACE`)
## License
MIT