Created
February 26, 2024 20:46
-
-
Save cjappl/7fd7fae5efd9b0798d91b1fd38ee5444 to your computer and use it in GitHub Desktop.
RADTrace - Dtrace script to capture realtime safety violations in "tagged" functions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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++; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Note the
inside_process
andrt_safe_depth
act as a kind of stack, keeping track of how many nested layers you are deep.