Skip to content

Instantly share code, notes, and snippets.

@cjappl
Created February 26, 2024 20:46
Show Gist options
  • Save cjappl/7fd7fae5efd9b0798d91b1fd38ee5444 to your computer and use it in GitHub Desktop.
Save cjappl/7fd7fae5efd9b0798d91b1fd38ee5444 to your computer and use it in GitHub Desktop.
RADTrace - Dtrace script to capture realtime safety violations in "tagged" functions
dtrace:::BEGIN
{
printf("Starting trace\n");
errors = 0;
}
dtrace:::END
{
printf("Total errors: %d", errors);
exit(errors);
}
// Function names prepended by cja_realtime are considered to be realtime functions
pid$target::cja_realtime*:entry
{
if (!self->inside_process)
self->inside_process = 1;
else
self->inside_process++;
}
pid$target::cja_realtime*:return
{
self->inside_process--;
}
// Function names prepended by cja_safe_realtime are considered to be safe realtime functions
// this will ensure that you have an 'escape hatch'
pid$target::cja_safe_realtime*:entry
{
if (!self->rt_safe_depth)
self->rt_safe_depth = 1;
else
self->rt_safe_depth++;
}
pid$target::cja_safe_realtime*:return
{
self->rt_safe_depth--;
}
// Function names prepended by cja_blocking are considered to be blocking functions
// they should not be called in a realtime context
pid$target::cja_blocking*:entry
/ self->inside_process && self->inside_process > 0 && self->rt_safe_depth == 0 /
{
printf("User defined blocking function called in rt context : %s\n", probefunc);
printf("\nRealtime-safety violation:");
ustack();
errors++;
}
pid$target::malloc:entry,
pid$target::calloc:entry,
pid$target::realloc:entry,
pid$target::free:entry,
pid$target::mmap:entry,
pid$target::vm_allocate:entry,
pid$target::vm_deallocate:entry,
pid$target::pthread_mutex_lock:entry,
pid$target::pthread_mutex_unlock:entry,
pid$target::pthread_rwlock_wrlock:entry,
pid$target::pthread_rwlock_rdlock:entry,
pid$target::dispatch_async:entry,
pid$target::dispatch_async_f:entry,
pid$target::dispatch_sync:entry,
pid$target::dispatch_sync_f:entry,
pid$target::dispatch_after:entry,
pid$target::dispatch_after_f:entry,
pid$target::dispatch_barrier_async:entry,
pid$target::dispatch_barrier_async_f:entry,
pid$target::dispatch_barrier_sync:entry,
pid$target::dispatch_barrier_sync_f:entry,
pid$target::os_lock_lock:entry,
pid$target::os_lock_unlock:entry,
pid$target::os_unfair_lock_lock:entry,
pid$target::os_unfair_lock_lock_no_tsd:entry,
pid$target::os_unfair_lock_lock_with_options:entry,
pid$target::os_unfair_lock_unlock:entry,
pid$target::os_unfair_lock_unlock_no_tsd:entry,
pid$target::_os_log_impl:entry,
pid$target::objc_sync_enter:entry,
pid$target::objc_msgSend:entry,
pid$target::send:entry,
pid$target::sendto:entry,
pid$target::recv:entry,
pid$target::fopen:entry,
pid$target::fclose:entry,
pid$target::fread:entry,
pid$target::fwrite:entry,
pid$target::fgets:entry,
pid$target::open:entry,
pid$target::read:entry,
pid$target::pread:entry,
pid$target::write:entry,
pid$target::pwrite:entry /
self->inside_process && self->inside_process > 0 && self->rt_safe_depth == 0
/
{
printf("\nRealtime-safety violation - %s:", probefunc);
ustack();
errors++;
}
@cjappl
Copy link
Author

cjappl commented Feb 26, 2024

Note the inside_process and rt_safe_depth act as a kind of stack, keeping track of how many nested layers you are deep.

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