1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
//! # Stack Unwinding Module
//!
//! Provides functionality for generating backtraces of the debuggee's call stack.
//!
//! This module utilizes the [mod@unwind] crate to walk through the stack frames of
//! a debugged process, generating a backtrace with information about function
//! calls, addresses, and names. Stack unwinding is essential for understanding
//! the execution context of a program at a particular point in time.
//!
//! The implementation is inspired by the `BugStalker` debugger project:
//! <https://github.com/godzie44/BugStalker> (MIT Licensed)
use crateResult;
use crateAddr;
use Pid;
use Serialize;
use ;
/// Represents a backtrace of the call stack
///
/// [`Backtrace`] contains a list of stack frames, ordered from top (most recent call)
/// to bottom (earliest call), providing a view of the call chain that led to the
/// current execution point.
///
/// # Examples
///
/// ```no_run
/// use coreminer::unwind::unwind;
/// use nix::unistd::Pid;
///
/// // Generate a backtrace for process with PID 1234
/// let backtrace = unwind(Pid::from_raw(1234)).unwrap();
///
/// // Print the backtrace
/// for (i, frame) in backtrace.frames.iter().enumerate() {
/// println!("#{} {} at {:?}", i, frame.name.as_deref().unwrap_or("??"), frame.addr);
/// }
/// ```
/// Represents a single frame in a backtrace
///
/// [`BacktraceFrame`] contains information about a function call in the backtrace,
/// including the current instruction address, function start address, and function name.
///
/// # Examples
///
/// ```
/// use coreminer::unwind::BacktraceFrame;
/// use coreminer::addr::Addr;
///
/// // Create a backtrace frame
/// let frame = BacktraceFrame {
/// addr: Addr::from(0x1000usize),
/// start_addr: Some(Addr::from(0x0F80usize)),
/// name: Some("main".to_string()),
/// };
///
/// // Access frame information
/// println!("Function: {} at {}", frame.name.as_deref().unwrap_or("??"), frame.addr);
/// ```
/// Generates a [Backtrace] for the specified process
///
/// This function walks the call stack of the target process, collecting
/// information about each stack frame to generate a complete backtrace.
///
/// # Parameters
///
/// * `pid` - The process ID of the target process
///
/// # Returns
///
/// * `Ok(Backtrace)` - The generated backtrace
/// * `Err(DebuggerError)` - If unwinding failed
///
/// # Errors
///
/// This function can fail if:
/// - The process cannot be accessed
/// - The stack is corrupted or cannot be unwound
/// - Register access fails
///
/// # Examples
///
/// ```no_run
/// use coreminer::unwind::unwind;
/// use nix::unistd::Pid;
///
/// // Generate a backtrace for process with PID 1234
/// match unwind(Pid::from_raw(1234)) {
/// Ok(backtrace) => {
/// for frame in backtrace.frames {
/// println!("{:?} - {}", frame.addr, frame.name.unwrap_or_else(|| "??".to_string()));
/// }
/// },
/// Err(e) => println!("Failed to generate backtrace: {}", e),
/// }
/// ```