Skip to content

Instantly share code, notes, and snippets.

@mqudsi
Created May 30, 2024 17:01
Show Gist options
  • Save mqudsi/999fe72e7b7debf9864564b18b523c25 to your computer and use it in GitHub Desktop.
Save mqudsi/999fe72e7b7debf9864564b18b523c25 to your computer and use it in GitHub Desktop.
Check stack usage under rust
fn check_stack() {
let x = 17;
fn approximate_sp(var: *const i32) -> *const libc::c_void {
var.cast()
}
struct StackInfo {
size: usize,
start: * const core::ffi::c_void,
end: * const core::ffi::c_void,
}
fn stack_info() -> StackInfo {
#[cfg(target_os = "macos")]
{
extern "C" {
fn pthread_get_stackaddr_np(thread: libc::pthread_t) -> *const libc::c_void;
fn pthread_get_stacksize_np(thread: libc::pthread_t) -> libc::size_t;
}
let start = unsafe { pthread_get_stackaddr_np(libc::pthread_self()) };
let size = unsafe { pthread_get_stacksize_np(libc::pthread_self()) };
let end = start.wrapping_sub(size);
StackInfo {
size,
start,
end,
}
}
#[cfg(not(target_os = "macos"))]
{
extern "C" {
fn pthread_getattr_np(thread: libc::pthread_t, attr: *mut libc::pthread_attr_t) -> libc::c_int;
fn pthread_attr_getstack(attr: *const libc::pthread_attr_t, stackaddr: *mut *const libc::c_void, stacksize: *mut libc::size_t) -> libc::c_int;
fn pthread_attr_destroy(attr: *mut libc::pthread_attr_t) -> libc::c_int;
}
let mut attr: libc::pthread_attr_t = unsafe { std::mem::zeroed() };
let result = unsafe { pthread_getattr_np(libc::pthread_self(), &mut attr) };
assert_eq!(result, 0);
let mut stackaddr: *const libc::c_void = std::ptr::null();
let mut stacksize: libc::size_t = 0;
let result = unsafe { pthread_attr_getstack(&attr, &mut stackaddr, &mut stacksize) };
assert_eq!(result, 0);
let result = unsafe { pthread_attr_destroy(&mut attr) };
assert_eq!(result, 0);
StackInfo {
end: stackaddr,
size: stacksize,
start: stackaddr.wrapping_add(stacksize),
}
}
}
let sp = approximate_sp(&x as _);
let si = stack_info();
let start = si.start;
let size = si.size;
let end = si.end;
let safety_size = 10 * 1024.min(size as usize / 10);
let safe_end = end.wrapping_add(safety_size); // "relatively" safe stack bottom
let used = unsafe { start.offset_from(sp) };
eprintln!("top : {:?}", start);
eprintln!("SP : {:?} (approximate)", sp);
eprintln!("safe : {:?} (relatively safe bottom)", safe_end);
eprintln!("bottom : {:?}", end);
eprintln!("size : {:?} ({:#X?})", size, size);
eprintln!("used : {:?} [{}%]", used, 100 * (used as usize / size));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment