An open API service indexing awesome lists of open source software.

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.

Awesome Lists containing this project

README

          

# rptrace [![Gem Version](https://badge.fury.io/rb/rptrace.svg)](https://badge.fury.io/rb/rptrace) [![CI](https://github.com/ydah/rptrace/actions/workflows/main.yml/badge.svg)](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