Skip to content

Add fasttime debugger support#25654

Open
0verflowme wants to merge 5 commits intoradareorg:masterfrom
0verflowme:split/debug-fasttime
Open

Add fasttime debugger support#25654
0verflowme wants to merge 5 commits intoradareorg:masterfrom
0verflowme:split/debug-fasttime

Conversation

@0verflowme
Copy link
Copy Markdown
Member

This extracts the dbg.fasttime feature into its own branch.

Scope:

  • dbg.fasttime config
  • debugger fasttime state tracking
  • Linux native debugger timer-syscall virtualization
  • Linux r2r coverage for fasttime

Note:

  • local build is clean
  • the dbg_fasttime r2r still needs one more validation pass in this split branch before this should leave draft

@0verflowme 0verflowme marked this pull request as ready for review March 26, 2026 16:10
Copy link
Copy Markdown
Collaborator

@trufae trufae left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its unclear to me how this feature is used in contrast to the current dcs also whats “fast time” exactly meaning?

return false;
}
if (!thread_state->in_syscall) {
if (!r_debug_fasttime_prepare_syscall_entry (dbg, tid, syscall_num)) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use shorter function names

RListIter *it;
r_list_foreach (dbg->threads, it, th) {
ret = r_debug_ptrace (dbg, PTRACE_CONT, th->pid, 0, 0);
ret = r_debug_ptrace (dbg, ptrace_cmd, th->pid, 0, 0);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you see dcs command to continue until syscall? Isnt that feature the same thing?

@0verflowme
Copy link
Copy Markdown
Member Author

0verflowme commented Mar 27, 2026

Its unclear to me how this feature is used in contrast to the current dcs also whats “fast time” exactly meaning?

dbg.fasttime=true changes a different workflow, when the user just wants to continue execution, and the program spends a lot of time in nanosleep / clock_nanosleep, the debugger short-circuits those timer syscalls instead of waiting for real wall-clock time to pass.

@trufae
Copy link
Copy Markdown
Collaborator

trufae commented Mar 30, 2026

Ok so fasttime is just: replace sleep syscalls with return 0.

As long as this is linux specific, and adds lots of complexity and the usecase for this is nearly zero. I would suggest a different approach:

add cmd.syscall. Something that is executed when we hit a syscall . Like what cmd.esil.* does but for the debugger.

this way the feature is generic and can be used for a large variety or usecases because then you can use r2js to intercept syscall arguments and replace return values etc. this may result into 0 new apis and naybe q coupke of commands and one config var

@trufae
Copy link
Copy Markdown
Collaborator

trufae commented Mar 30, 2026

Unreviewed writeup from claude about my thoughts. Take it with care :

Proposal: Generic syscall interception via dbg.onsyscall

Instead of adding a dedicated dbg.fasttime feature with new APIs, we should
provide a generic syscall interception hook that lets users script any syscall
behavior change — including but not limited to skipping sleeps.

Design

Add a single config variable:

e dbg.onsyscall=<r2 command>

When set to a non-empty string, dc uses PTRACE_SYSCALL instead of
PTRACE_CONT (on Linux). On each syscall stop, the configured command is
evaluated. The command has access to registers via dr and can modify them
to alter syscall behavior. If the command is empty, normal PTRACE_CONT
is used (zero overhead when disabled).

The command runs twice per syscall (entry and exit), matching how
PTRACE_SYSCALL works. Users can distinguish entry vs exit by checking
register values or using a flag variable.

Usage examples

Skip nanosleep and clock_nanosleep (what fasttime does):

e dbg.onsyscall=?e `drn SN`;?$?{match `drn SN` 35 230}(dr SN=-1)

Or more readably via a script:

e dbg.onsyscall=. /path/to/skip-sleeps.r2

Where skip-sleeps.r2 contains:

sn=`drn SN`
?= $sn 35      # nanosleep
?!?e skipping nanosleep; dr SN=-1
?= $sn 230     # clock_nanosleep
?!?e skipping clock_nanosleep; dr SN=-1

Log all syscalls without stopping (like strace):

e dbg.onsyscall=?e syscall `drsn`

Skip specific syscalls by replacing them with getpid (harmless):

e dbg.onsyscall=?= `drn SN` 35;?!dr SN=`drn getpid`

Implementation

Changes required:

  1. libr/core/cconfig.c: Add dbg.onsyscall string config variable
    (just a SETPREF, no callback needed beyond storing the string).

  2. libr/debug/p/debug_native.c: In r_debug_native_continue(),
    check if dbg->onsyscall is non-empty. If so, use PTRACE_SYSCALL
    instead of PTRACE_CONT (same pattern this PR already uses).

  3. libr/debug/p/native/linux/linux_debug.c: In linux_dbg_wait(),
    when a syscall stop is detected (WSTOPSIG == SIGTRAP|0x80) and
    dbg->onsyscall is set, evaluate the command via dbg->coreb.cmd()
    then resume with PTRACE_SYSCALL. If the command is empty or unset,
    fall through to existing behavior.

  4. libr/include/r_debug.h: Add one field: char *onsyscall;

  5. libr/debug/debug.c: In r_debug_continue_syscalls(), temporarily
    clear dbg->onsyscall so explicit dcs tracing is not affected
    (same idea as the fasttime_suppress in this PR, but simpler).

What this does NOT add

  • No new public R_API functions
  • No new structs (no RDebugFasttimeThread)
  • No per-thread hashtable
  • No hardcoded syscall names
  • No platform-specific logic outside the linux debug plugin

Advantages over dbg.fasttime

  • Generic: skip any syscall, log syscalls, modify arguments, fake
    return values — whatever the user scripts
  • Zero new APIs: one config string, one struct field
  • Extensible: users solve their own use cases without core changes
  • Consistent: follows the same pattern as other r2 hooks
    (e.g. dbg.bpinmaps, cmd.hit, etc.)
  • Cross-platform potential: other debug backends could evaluate the
    same hook when they gain syscall interception support

@trufae
Copy link
Copy Markdown
Collaborator

trufae commented Mar 30, 2026

We may be able to intercept the syscall before its executed:

  • change parameters or access them
  • Decide if we want to execute the syscallnor not
  • Hook the syscall onreturn event to capture return values like in frida and be able to replace the value

@trufae
Copy link
Copy Markdown
Collaborator

trufae commented Mar 30, 2026

This feature should be possible to be implemented not only on linux but also on BSD with the PT_SYSCALL. Windows and macos are out

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants