libdd_libunwind_sys/
lib.rs1#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
5mod libunwind_x86_64;
6
7#[cfg(all(target_os = "linux", target_arch = "aarch64"))]
8mod libunwind_aarch64;
9
10#[cfg(all(target_os = "linux", target_arch = "aarch64"))]
11pub use libunwind_aarch64::*;
12#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
13pub use libunwind_x86_64::*;
14
15#[cfg(all(test, target_os = "linux"))]
16mod tests {
17 use super::*;
18
19 #[test]
20 #[cfg_attr(miri, ignore)] fn test_basic_unwind() {
22 unsafe {
23 let mut context: UnwContext = std::mem::zeroed();
24 let mut cursor: UnwCursor = std::mem::zeroed();
25
26 let ret = getcontext(&mut context);
27 assert_eq!(ret, 0, "getcontext failed");
28
29 let ret = unw_init_local2(&mut cursor, &mut context, 0);
31 assert_eq!(ret, 0, "unw_init_local2 failed");
32
33 let mut frames = 0;
35 loop {
36 let ret = unw_step(&mut cursor);
37 if ret <= 0 {
38 break;
39 }
40 frames += 1;
41
42 if frames > 100 {
44 break;
45 }
46 }
47
48 assert!(frames > 0, "Expected at least one stack frame");
50 }
51 }
52
53 #[test]
54 #[cfg_attr(miri, ignore)] fn test_get_register() {
56 unsafe {
57 let mut context: UnwContext = std::mem::zeroed();
58 let mut cursor: UnwCursor = std::mem::zeroed();
59
60 assert_eq!(getcontext(&mut context), 0);
61 assert_eq!(unw_init_local2(&mut cursor, &mut context, 0), 0);
62
63 let mut ip: UnwWord = 0;
65 let ret = unw_get_reg(&mut cursor, UNW_REG_IP, &mut ip);
66 assert_eq!(ret, 0, "Failed to get IP register");
67 assert_ne!(ip, 0, "IP should not be zero");
68
69 let mut sp: UnwWord = 0;
71 let ret = unw_get_reg(&mut cursor, UNW_REG_SP, &mut sp);
72 assert_eq!(ret, 0, "Failed to get SP register");
73 assert_ne!(sp, 0, "SP should not be zero");
74 }
75 }
76
77 #[test]
78 #[cfg_attr(miri, ignore)] fn test_backtrace2() {
80 unsafe {
81 let mut context: UnwContext = std::mem::zeroed();
82 assert_eq!(getcontext(&mut context), 0);
83
84 let mut frames: [*mut ::std::os::raw::c_void; 100] = [std::ptr::null_mut(); 100];
86 let ret = unw_backtrace2(frames.as_mut_ptr(), 100, &mut context, 0);
87
88 assert!(ret >= 0, "unw_backtrace2 failed with error: {}", ret);
90
91 let frame_count = ret as usize;
92 assert!(frame_count > 0, "Expected at least one frame");
93
94 for (i, &frame) in frames.iter().enumerate().take(frame_count) {
96 let frame_ptr = frame as usize;
97 println!("Frame {}: 0x{:016x}", i, frame_ptr);
98 }
99 }
100 }
101
102 #[test]
103 #[cfg_attr(miri, ignore)] fn test_get_proc_name() {
105 unsafe {
106 let mut context: UnwContext = std::mem::zeroed();
107 let mut cursor: UnwCursor = std::mem::zeroed();
108
109 assert_eq!(getcontext(&mut context), 0);
110 assert_eq!(
111 unw_init_local2(&mut cursor, &mut context, UNW_INIT_LOCAL_ONLY_IP),
112 0
113 );
114
115 let mut name: [libc::c_char; 100] = [0; 100];
116 let ret = unw_get_proc_name(&mut cursor, name.as_mut_ptr(), 100, std::ptr::null_mut());
117 assert_eq!(ret, 0, "unw_get_proc_name failed");
118 let fn_name = std::ffi::CStr::from_ptr(name.as_ptr()).to_string_lossy();
119 assert!(!fn_name.is_empty(), "Name should not be empty");
120 assert!(
123 fn_name.contains("test_get_proc_name"),
124 "Name should contain 'test_get_proc_name'"
125 );
126 }
127 }
128}