Line data Source code
1 : use lief_ffi as ffi;
2 : use std::marker::PhantomData;
3 : use std::time::Duration;
4 :
5 : use crate::common::FromFFI;
6 : use crate::elf::header::Arch;
7 : use crate::elf::note::NoteBase;
8 : use crate::{to_result, Error};
9 :
10 : #[allow(non_camel_case_types)]
11 0 : #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
12 : /// Register for the x86 architecture
13 : pub enum RegX86 {
14 : EBX,
15 : ECX,
16 : EDX,
17 : ESI,
18 : EDI,
19 : EBP,
20 : EAX,
21 : DS,
22 : ES,
23 : FS,
24 : GS,
25 : ORIG_EAX,
26 : EIP,
27 : CS,
28 : EFLAGS,
29 : ESP,
30 : SS,
31 : UNKNOWN(u32),
32 : }
33 :
34 : impl From<u32> for RegX86 {
35 0 : fn from(value: u32) -> Self {
36 0 : match value {
37 0 : 0 => RegX86::EBX,
38 0 : 1 => RegX86::ECX,
39 0 : 2 => RegX86::EDX,
40 0 : 3 => RegX86::ESI,
41 0 : 4 => RegX86::EDI,
42 0 : 5 => RegX86::EBP,
43 0 : 6 => RegX86::EAX,
44 0 : 7 => RegX86::DS,
45 0 : 8 => RegX86::ES,
46 0 : 9 => RegX86::FS,
47 0 : 10 => RegX86::GS,
48 0 : 11 => RegX86::ORIG_EAX,
49 0 : 12 => RegX86::EIP,
50 0 : 13 => RegX86::CS,
51 0 : 14 => RegX86::EFLAGS,
52 0 : 15 => RegX86::ESP,
53 0 : 16 => RegX86::SS,
54 0 : _ => RegX86::UNKNOWN(value),
55 : }
56 0 : }
57 : }
58 :
59 : #[allow(non_camel_case_types)]
60 0 : #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
61 : /// Register for the x86-64 architecture
62 : pub enum RegX86_64 {
63 : R15,
64 : R14,
65 : R13,
66 : R12,
67 : RBP,
68 : RBX,
69 : R11,
70 : R10,
71 : R9,
72 : R8,
73 : RAX,
74 : RCX,
75 : RDX,
76 : RSI,
77 : RDI,
78 : ORIG_RAX,
79 : RIP,
80 : CS,
81 : EFLAGS,
82 : RSP,
83 : SS,
84 : FS_BASE,
85 : GS_BASE,
86 : DS,
87 : ES,
88 : UNKNOWN(u32),
89 : }
90 :
91 : impl From<u32> for RegX86_64 {
92 0 : fn from(value: u32) -> Self {
93 0 : match value {
94 0 : 0 => RegX86_64::R15,
95 0 : 1 => RegX86_64::R14,
96 0 : 2 => RegX86_64::R13,
97 0 : 3 => RegX86_64::R12,
98 0 : 4 => RegX86_64::RBP,
99 0 : 5 => RegX86_64::RBX,
100 0 : 6 => RegX86_64::R11,
101 0 : 7 => RegX86_64::R10,
102 0 : 8 => RegX86_64::R9,
103 0 : 9 => RegX86_64::R8,
104 0 : 10 => RegX86_64::RAX,
105 0 : 11 => RegX86_64::RCX,
106 0 : 12 => RegX86_64::RDX,
107 0 : 13 => RegX86_64::RSI,
108 0 : 14 => RegX86_64::RDI,
109 0 : 15 => RegX86_64::ORIG_RAX,
110 0 : 16 => RegX86_64::RIP,
111 0 : 17 => RegX86_64::CS,
112 0 : 18 => RegX86_64::EFLAGS,
113 0 : 19 => RegX86_64::RSP,
114 0 : 20 => RegX86_64::SS,
115 0 : 21 => RegX86_64::FS_BASE,
116 0 : 22 => RegX86_64::GS_BASE,
117 0 : 23 => RegX86_64::DS,
118 0 : 24 => RegX86_64::ES,
119 0 : _ => RegX86_64::UNKNOWN(value),
120 : }
121 0 : }
122 : }
123 :
124 : #[allow(non_camel_case_types)]
125 0 : #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
126 : /// Register for the ARM architecture
127 : pub enum RegARM {
128 : R0,
129 : R1,
130 : R2,
131 : R3,
132 : R4,
133 : R5,
134 : R6,
135 : R7,
136 : R8,
137 : R9,
138 : R10,
139 : R11,
140 : R12,
141 : R13,
142 : R14,
143 : R15,
144 : CPSR,
145 : UNKNOWN(u32),
146 : }
147 :
148 : impl From<u32> for RegARM {
149 0 : fn from(value: u32) -> Self {
150 0 : match value {
151 0 : 0 => RegARM::R0,
152 0 : 1 => RegARM::R1,
153 0 : 2 => RegARM::R2,
154 0 : 3 => RegARM::R3,
155 0 : 4 => RegARM::R4,
156 0 : 5 => RegARM::R5,
157 0 : 6 => RegARM::R6,
158 0 : 7 => RegARM::R7,
159 0 : 8 => RegARM::R8,
160 0 : 9 => RegARM::R9,
161 0 : 10 => RegARM::R10,
162 0 : 11 => RegARM::R11,
163 0 : 12 => RegARM::R12,
164 0 : 13 => RegARM::R13,
165 0 : 14 => RegARM::R14,
166 0 : 15 => RegARM::R15,
167 0 : 16 => RegARM::CPSR,
168 0 : _ => RegARM::UNKNOWN(value),
169 : }
170 0 : }
171 : }
172 :
173 : #[allow(non_camel_case_types)]
174 0 : #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
175 : /// Register for the AArch64 architecture
176 : pub enum RegAArch64 {
177 : X0,
178 : X1,
179 : X2,
180 : X3,
181 : X4,
182 : X5,
183 : X6,
184 : X7,
185 : X8,
186 : X9,
187 : X10,
188 : X11,
189 : X12,
190 : X13,
191 : X14,
192 : X15,
193 : X16,
194 : X17,
195 : X18,
196 : X19,
197 : X20,
198 : X21,
199 : X22,
200 : X23,
201 : X24,
202 : X25,
203 : X26,
204 : X27,
205 : X28,
206 : X29,
207 : X30,
208 : X31,
209 : PC,
210 : PSTATE,
211 : UNKNOWN(u32),
212 : }
213 :
214 : impl From<u32> for RegAArch64 {
215 0 : fn from(value: u32) -> Self {
216 0 : match value {
217 0 : 0 => RegAArch64::X0,
218 0 : 1 => RegAArch64::X1,
219 0 : 2 => RegAArch64::X2,
220 0 : 3 => RegAArch64::X3,
221 0 : 4 => RegAArch64::X4,
222 0 : 5 => RegAArch64::X5,
223 0 : 6 => RegAArch64::X6,
224 0 : 7 => RegAArch64::X7,
225 0 : 8 => RegAArch64::X8,
226 0 : 9 => RegAArch64::X9,
227 0 : 10 => RegAArch64::X10,
228 0 : 11 => RegAArch64::X11,
229 0 : 12 => RegAArch64::X12,
230 0 : 13 => RegAArch64::X13,
231 0 : 14 => RegAArch64::X14,
232 0 : 15 => RegAArch64::X15,
233 0 : 16 => RegAArch64::X16,
234 0 : 17 => RegAArch64::X17,
235 0 : 18 => RegAArch64::X18,
236 0 : 19 => RegAArch64::X19,
237 0 : 20 => RegAArch64::X20,
238 0 : 21 => RegAArch64::X21,
239 0 : 22 => RegAArch64::X22,
240 0 : 23 => RegAArch64::X23,
241 0 : 24 => RegAArch64::X24,
242 0 : 25 => RegAArch64::X25,
243 0 : 26 => RegAArch64::X26,
244 0 : 27 => RegAArch64::X27,
245 0 : 28 => RegAArch64::X28,
246 0 : 29 => RegAArch64::X29,
247 0 : 30 => RegAArch64::X30,
248 0 : 31 => RegAArch64::X31,
249 0 : 32 => RegAArch64::PC,
250 0 : 33 => RegAArch64::PSTATE,
251 0 : _ => RegAArch64::UNKNOWN(value),
252 : }
253 0 : }
254 : }
255 :
256 : /// Status information from a core dump
257 : ///
258 : /// This structure mirrors the kernel's `prstatus` data embedded in
259 : /// `NT_PRSTATUS` core-dump notes and exposes signal state, process
260 : /// identifiers, and CPU-time accounting.
261 0 : #[derive(Debug)]
262 : pub struct Status {
263 : /// Current signal number being delivered
264 : pub cursig: u16,
265 : /// Set of pending signals (bitmask)
266 : pub sigpend: u64,
267 : /// Set of held (blocked) signals (bitmask)
268 : pub sighold: u64,
269 : /// Process ID
270 : pub pid: i32,
271 : /// Parent process ID
272 : pub ppid: i32,
273 : /// Process group ID
274 : pub pgrp: i32,
275 : /// Session ID
276 : pub sid: i32,
277 : /// Signal number that caused the core dump
278 : pub signo: i32,
279 : /// Signal code providing additional detail
280 : pub sigcode: i32,
281 : /// Error number associated with the signal
282 : pub sigerr: i32,
283 :
284 : /// Reserved field for alignment
285 : pub reserved: u16,
286 :
287 : /// User CPU time consumed by the process
288 : pub utime: Duration,
289 : /// System CPU time consumed by the process
290 : pub stime: Duration,
291 : /// User CPU time consumed by waited-for children
292 : pub cutime: Duration,
293 : /// System CPU time consumed by waited-for children
294 : pub cstime: Duration,
295 : }
296 :
297 : /// Note representing core process status (`NT_PRSTATUS`)
298 : pub struct PrStatus<'a> {
299 : ptr: cxx::UniquePtr<ffi::ELF_CorePrStatus>,
300 : _owner: PhantomData<&'a ffi::ELF_Binary>,
301 : }
302 :
303 : impl PrStatus<'_> {
304 : /// The architecture
305 26 : pub fn architecture(&self) -> Arch {
306 26 : Arch::from(self.ptr.architecture())
307 26 : }
308 :
309 : /// Status information
310 26 : pub fn status(&self) -> Status {
311 26 : let status_ffi = self.ptr.status();
312 26 : Status {
313 26 : cursig: status_ffi.cursig,
314 26 : sigpend: status_ffi.sigpend,
315 26 : sighold: status_ffi.sighold,
316 26 : pid: status_ffi.pid,
317 26 : ppid: status_ffi.ppid,
318 26 : pgrp: status_ffi.pgrp,
319 26 : sid: status_ffi.sid,
320 26 : signo: status_ffi.signo,
321 26 : sigcode: status_ffi.code,
322 26 : sigerr: status_ffi.err,
323 26 : reserved: status_ffi.reserved,
324 26 : utime: Duration::new(status_ffi.utime_sec, status_ffi.utime_usec as u32),
325 26 : stime: Duration::new(status_ffi.stime_sec, status_ffi.stime_usec as u32),
326 26 : cutime: Duration::new(status_ffi.cutime_sec, status_ffi.cutime_usec as u32),
327 26 : cstime: Duration::new(status_ffi.cstime_sec, status_ffi.cstime_usec as u32),
328 26 : }
329 26 : }
330 :
331 : /// The program counter
332 26 : pub fn pc(&self) -> Result<u64, Error> {
333 26 : to_result!(ffi::ELF_CorePrStatus::pc, &self);
334 26 : }
335 :
336 : //// The stack pointer value
337 13 : pub fn sp(&self) -> Result<u64, Error> {
338 13 : to_result!(ffi::ELF_CorePrStatus::sp, &self);
339 13 : }
340 :
341 : /// The return value register
342 13 : pub fn return_value(&self) -> Result<u64, Error> {
343 13 : to_result!(ffi::ELF_CorePrStatus::return_value, &self);
344 13 : }
345 :
346 : /// Get all register values
347 26 : pub fn register_values(&self) -> Vec<u64> {
348 26 : Vec::from(self.ptr.register_values().as_slice())
349 26 : }
350 : }
351 :
352 : impl NoteBase for PrStatus<'_> {
353 299 : fn get_base(&self) -> &ffi::ELF_Note {
354 299 : self.ptr.as_ref().unwrap().as_ref()
355 299 : }
356 : }
357 :
358 : impl FromFFI<ffi::ELF_CorePrStatus> for PrStatus<'_> {
359 104 : fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_CorePrStatus>) -> Self {
360 104 : Self {
361 104 : ptr,
362 104 : _owner: PhantomData,
363 104 : }
364 104 : }
365 : }
366 :
367 : impl std::fmt::Debug for PrStatus<'_> {
368 78 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
369 78 : let base = self as &dyn NoteBase;
370 78 : f.debug_struct("CorePrStatus")
371 78 : .field("base", &base)
372 78 : //.field("architecture", &self.architecture())
373 78 : //.field("status", &self.status())
374 78 : .finish()
375 78 : }
376 : }
|