1use super::registers::RegisterContext;
7use super::{MemoryReader, UnwindError};
8
9mod op {
11 pub const ADDR: u8 = 0x03;
12 pub const DEREF: u8 = 0x06;
13 pub const CONST1U: u8 = 0x08;
14 pub const CONST1S: u8 = 0x09;
15 pub const CONST2U: u8 = 0x0A;
16 pub const CONST2S: u8 = 0x0B;
17 pub const CONST4U: u8 = 0x0C;
18 pub const CONST4S: u8 = 0x0D;
19 pub const CONST8U: u8 = 0x0E;
20 pub const CONST8S: u8 = 0x0F;
21 pub const CONSTU: u8 = 0x10;
22 pub const CONSTS: u8 = 0x11;
23 pub const DUP: u8 = 0x12;
24 pub const DROP: u8 = 0x13;
25 pub const OVER: u8 = 0x14;
26 pub const PICK: u8 = 0x15;
27 pub const SWAP: u8 = 0x16;
28 pub const ROT: u8 = 0x17;
29 pub const ABS: u8 = 0x19;
30 pub const AND: u8 = 0x1A;
31 pub const DIV: u8 = 0x1B;
32 pub const MINUS: u8 = 0x1C;
33 pub const MOD: u8 = 0x1D;
34 pub const MUL: u8 = 0x1E;
35 pub const NEG: u8 = 0x1F;
36 pub const NOT: u8 = 0x20;
37 pub const OR: u8 = 0x21;
38 pub const PLUS: u8 = 0x22;
39 pub const PLUS_UCONST: u8 = 0x23;
40 pub const SHL: u8 = 0x24;
41 pub const SHR: u8 = 0x25;
42 pub const SHRA: u8 = 0x26;
43 pub const XOR: u8 = 0x27;
44 pub const LIT0: u8 = 0x30; pub const REG0: u8 = 0x50; pub const BREG0: u8 = 0x70; pub const REGX: u8 = 0x90;
48 pub const FBREG: u8 = 0x91;
49 pub const BREGX: u8 = 0x92;
50 pub const DEREF_SIZE: u8 = 0x94;
51 pub const NOP: u8 = 0x96;
52}
53
54pub fn evaluate(
62 expr: &[u8],
63 regs: &RegisterContext,
64 reader: &dyn MemoryReader,
65 is_64_bit: bool,
66) -> Result<u64, UnwindError> {
67 let mut stack: Vec<u64> = Vec::new();
68 let mut cursor = ExprCursor::new(expr);
69
70 while cursor.remaining() > 0 {
71 let opcode = cursor.read_u8()?;
72
73 match opcode {
74 op::LIT0..=0x4F => {
76 stack.push((opcode - op::LIT0) as u64);
77 }
78
79 op::REG0..=0x6F => {
81 let reg = (opcode - op::REG0) as u16;
82 let val = regs
83 .get(reg)
84 .ok_or_else(|| UnwindError::InvalidDwarf(format!("reg{reg} not set")))?;
85 stack.push(val);
86 }
87
88 op::BREG0..=0x8F => {
90 let reg = (opcode - op::BREG0) as u16;
91 let offset = cursor.read_sleb128()?;
92 let val = regs
93 .get(reg)
94 .ok_or_else(|| UnwindError::InvalidDwarf(format!("breg{reg} not set")))?;
95 stack.push(val.wrapping_add(offset as u64));
96 }
97
98 op::ADDR => {
99 let addr = if is_64_bit {
100 cursor.read_u64()?
101 } else {
102 cursor.read_u32()? as u64
103 };
104 stack.push(addr);
105 }
106
107 op::CONST1U => {
108 let val = cursor.read_u8()? as u64;
109 stack.push(val);
110 }
111 op::CONST1S => {
112 let val = cursor.read_u8()? as i8 as i64 as u64;
113 stack.push(val);
114 }
115 op::CONST2U => {
116 let val = cursor.read_u16()? as u64;
117 stack.push(val);
118 }
119 op::CONST2S => {
120 let val = cursor.read_u16()? as i16 as i64 as u64;
121 stack.push(val);
122 }
123 op::CONST4U => {
124 let val = cursor.read_u32()? as u64;
125 stack.push(val);
126 }
127 op::CONST4S => {
128 let val = cursor.read_u32()? as i32 as i64 as u64;
129 stack.push(val);
130 }
131 op::CONST8U => {
132 let val = cursor.read_u64()?;
133 stack.push(val);
134 }
135 op::CONST8S => {
136 let val = cursor.read_u64()?;
137 stack.push(val);
138 }
139 op::CONSTU => {
140 let val = cursor.read_uleb128()?;
141 stack.push(val);
142 }
143 op::CONSTS => {
144 let val = cursor.read_sleb128()? as u64;
145 stack.push(val);
146 }
147
148 op::DUP => {
150 let val = *stack
151 .last()
152 .ok_or(UnwindError::InvalidDwarf("DUP on empty stack".into()))?;
153 stack.push(val);
154 }
155 op::DROP => {
156 stack
157 .pop()
158 .ok_or(UnwindError::InvalidDwarf("DROP on empty stack".into()))?;
159 }
160 op::OVER => {
161 if stack.len() < 2 {
162 return Err(UnwindError::InvalidDwarf("OVER needs 2 values".into()));
163 }
164 let val = stack[stack.len() - 2];
165 stack.push(val);
166 }
167 op::PICK => {
168 let idx = cursor.read_u8()? as usize;
169 if idx >= stack.len() {
170 return Err(UnwindError::InvalidDwarf("PICK index out of range".into()));
171 }
172 let val = stack[stack.len() - 1 - idx];
173 stack.push(val);
174 }
175 op::SWAP => {
176 if stack.len() < 2 {
177 return Err(UnwindError::InvalidDwarf("SWAP needs 2 values".into()));
178 }
179 let len = stack.len();
180 stack.swap(len - 1, len - 2);
181 }
182 op::ROT => {
183 if stack.len() < 3 {
184 return Err(UnwindError::InvalidDwarf("ROT needs 3 values".into()));
185 }
186 let len = stack.len();
187 let top = stack[len - 1];
188 stack[len - 1] = stack[len - 2];
189 stack[len - 2] = stack[len - 3];
190 stack[len - 3] = top;
191 }
192
193 op::DEREF => {
195 let addr = stack
196 .pop()
197 .ok_or(UnwindError::InvalidDwarf("DEREF on empty stack".into()))?;
198 let val = reader
199 .read_pointer(addr, is_64_bit)
200 .ok_or(UnwindError::MemoryReadFailed(addr))?;
201 stack.push(val);
202 }
203 op::DEREF_SIZE => {
204 let size = cursor.read_u8()?;
205 let addr = stack.pop().ok_or(UnwindError::InvalidDwarf(
206 "DEREF_SIZE on empty stack".into(),
207 ))?;
208 let val = match size {
209 1 => reader.read_u8(addr).map(|v| v as u64),
210 2 => reader.read_u16(addr).map(|v| v as u64),
211 4 => reader.read_u32(addr).map(|v| v as u64),
212 8 => reader.read_u64(addr),
213 _ => None,
214 }
215 .ok_or(UnwindError::MemoryReadFailed(addr))?;
216 stack.push(val);
217 }
218
219 op::ABS => {
221 let val = stack
222 .pop()
223 .ok_or(UnwindError::InvalidDwarf("ABS on empty stack".into()))?;
224 stack.push((val as i64).unsigned_abs());
225 }
226 op::AND => {
227 let (b, a) = pop_two(&mut stack, "AND")?;
228 stack.push(a & b);
229 }
230 op::DIV => {
231 let (b, a) = pop_two(&mut stack, "DIV")?;
232 if b == 0 {
233 return Err(UnwindError::InvalidDwarf("DIV by zero".into()));
234 }
235 stack.push(((a as i64) / (b as i64)) as u64);
236 }
237 op::MINUS => {
238 let (b, a) = pop_two(&mut stack, "MINUS")?;
239 stack.push(a.wrapping_sub(b));
240 }
241 op::MOD => {
242 let (b, a) = pop_two(&mut stack, "MOD")?;
243 if b == 0 {
244 return Err(UnwindError::InvalidDwarf("MOD by zero".into()));
245 }
246 stack.push(a % b);
247 }
248 op::MUL => {
249 let (b, a) = pop_two(&mut stack, "MUL")?;
250 stack.push(a.wrapping_mul(b));
251 }
252 op::NEG => {
253 let val = stack
254 .pop()
255 .ok_or(UnwindError::InvalidDwarf("NEG on empty stack".into()))?;
256 stack.push((-(val as i64)) as u64);
257 }
258 op::NOT => {
259 let val = stack
260 .pop()
261 .ok_or(UnwindError::InvalidDwarf("NOT on empty stack".into()))?;
262 stack.push(!val);
263 }
264 op::OR => {
265 let (b, a) = pop_two(&mut stack, "OR")?;
266 stack.push(a | b);
267 }
268 op::PLUS => {
269 let (b, a) = pop_two(&mut stack, "PLUS")?;
270 stack.push(a.wrapping_add(b));
271 }
272 op::PLUS_UCONST => {
273 let val = stack.pop().ok_or(UnwindError::InvalidDwarf(
274 "PLUS_UCONST on empty stack".into(),
275 ))?;
276 let addend = cursor.read_uleb128()?;
277 stack.push(val.wrapping_add(addend));
278 }
279 op::SHL => {
280 let (b, a) = pop_two(&mut stack, "SHL")?;
281 stack.push(a.wrapping_shl(b as u32));
282 }
283 op::SHR => {
284 let (b, a) = pop_two(&mut stack, "SHR")?;
285 stack.push(a.wrapping_shr(b as u32));
286 }
287 op::SHRA => {
288 let (b, a) = pop_two(&mut stack, "SHRA")?;
289 stack.push(((a as i64).wrapping_shr(b as u32)) as u64);
290 }
291 op::XOR => {
292 let (b, a) = pop_two(&mut stack, "XOR")?;
293 stack.push(a ^ b);
294 }
295
296 op::REGX => {
298 let reg = cursor.read_uleb128()? as u16;
299 let val = regs
300 .get(reg)
301 .ok_or_else(|| UnwindError::InvalidDwarf(format!("regx({reg}) not set")))?;
302 stack.push(val);
303 }
304 op::BREGX => {
305 let reg = cursor.read_uleb128()? as u16;
306 let offset = cursor.read_sleb128()?;
307 let val = regs
308 .get(reg)
309 .ok_or_else(|| UnwindError::InvalidDwarf(format!("bregx({reg}) not set")))?;
310 stack.push(val.wrapping_add(offset as u64));
311 }
312 op::FBREG => {
313 let offset = cursor.read_sleb128()?;
315 let fp = regs
316 .fp()
317 .ok_or_else(|| UnwindError::InvalidDwarf("fbreg: no FP".into()))?;
318 stack.push(fp.wrapping_add(offset as u64));
319 }
320
321 op::NOP => {}
322
323 _ => {
324 return Err(UnwindError::InvalidDwarf(format!(
325 "unsupported DW_OP 0x{opcode:02x}"
326 )));
327 }
328 }
329 }
330
331 stack
332 .last()
333 .copied()
334 .ok_or_else(|| UnwindError::InvalidDwarf("expression produced empty stack".into()))
335}
336
337fn pop_two(stack: &mut Vec<u64>, op_name: &str) -> Result<(u64, u64), UnwindError> {
338 if stack.len() < 2 {
339 return Err(UnwindError::InvalidDwarf(format!(
340 "{op_name} needs 2 values"
341 )));
342 }
343 let b = stack.pop().unwrap();
344 let a = stack.pop().unwrap();
345 Ok((b, a))
346}
347
348struct ExprCursor<'a> {
350 data: &'a [u8],
351 pos: usize,
352}
353
354impl<'a> ExprCursor<'a> {
355 fn new(data: &'a [u8]) -> Self {
356 Self { data, pos: 0 }
357 }
358
359 fn remaining(&self) -> usize {
360 self.data.len() - self.pos
361 }
362
363 fn read_u8(&mut self) -> Result<u8, UnwindError> {
364 if self.pos >= self.data.len() {
365 return Err(UnwindError::InvalidDwarf(
366 "unexpected end of expression".into(),
367 ));
368 }
369 let val = self.data[self.pos];
370 self.pos += 1;
371 Ok(val)
372 }
373
374 fn read_u16(&mut self) -> Result<u16, UnwindError> {
375 if self.pos + 2 > self.data.len() {
376 return Err(UnwindError::InvalidDwarf(
377 "unexpected end of expression".into(),
378 ));
379 }
380 let val = u16::from_le_bytes([self.data[self.pos], self.data[self.pos + 1]]);
381 self.pos += 2;
382 Ok(val)
383 }
384
385 fn read_u32(&mut self) -> Result<u32, UnwindError> {
386 if self.pos + 4 > self.data.len() {
387 return Err(UnwindError::InvalidDwarf(
388 "unexpected end of expression".into(),
389 ));
390 }
391 let val = u32::from_le_bytes([
392 self.data[self.pos],
393 self.data[self.pos + 1],
394 self.data[self.pos + 2],
395 self.data[self.pos + 3],
396 ]);
397 self.pos += 4;
398 Ok(val)
399 }
400
401 fn read_u64(&mut self) -> Result<u64, UnwindError> {
402 if self.pos + 8 > self.data.len() {
403 return Err(UnwindError::InvalidDwarf(
404 "unexpected end of expression".into(),
405 ));
406 }
407 let val = u64::from_le_bytes([
408 self.data[self.pos],
409 self.data[self.pos + 1],
410 self.data[self.pos + 2],
411 self.data[self.pos + 3],
412 self.data[self.pos + 4],
413 self.data[self.pos + 5],
414 self.data[self.pos + 6],
415 self.data[self.pos + 7],
416 ]);
417 self.pos += 8;
418 Ok(val)
419 }
420
421 fn read_uleb128(&mut self) -> Result<u64, UnwindError> {
422 let mut result = 0u64;
423 let mut shift = 0;
424 loop {
425 let byte = self.read_u8()?;
426 result |= ((byte & 0x7F) as u64) << shift;
427 if byte & 0x80 == 0 {
428 return Ok(result);
429 }
430 shift += 7;
431 if shift >= 64 {
432 return Err(UnwindError::InvalidDwarf("ULEB128 overflow".into()));
433 }
434 }
435 }
436
437 fn read_sleb128(&mut self) -> Result<i64, UnwindError> {
438 let mut result = 0i64;
439 let mut shift = 0;
440 let mut byte;
441 loop {
442 byte = self.read_u8()?;
443 result |= ((byte & 0x7F) as i64) << shift;
444 shift += 7;
445 if byte & 0x80 == 0 {
446 break;
447 }
448 if shift >= 64 {
449 return Err(UnwindError::InvalidDwarf("SLEB128 overflow".into()));
450 }
451 }
452 if shift < 64 && (byte & 0x40) != 0 {
454 result |= !0i64 << shift;
455 }
456 Ok(result)
457 }
458}
459
460pub fn read_uleb128(data: &[u8], pos: &mut usize) -> Result<u64, UnwindError> {
462 let mut result = 0u64;
463 let mut shift = 0;
464 loop {
465 if *pos >= data.len() {
466 return Err(UnwindError::InvalidDwarf("ULEB128 past end".into()));
467 }
468 let byte = data[*pos];
469 *pos += 1;
470 result |= ((byte & 0x7F) as u64) << shift;
471 if byte & 0x80 == 0 {
472 return Ok(result);
473 }
474 shift += 7;
475 if shift >= 64 {
476 return Err(UnwindError::InvalidDwarf("ULEB128 overflow".into()));
477 }
478 }
479}
480
481pub fn read_sleb128(data: &[u8], pos: &mut usize) -> Result<i64, UnwindError> {
482 let mut result = 0i64;
483 let mut shift = 0;
484 let mut byte;
485 loop {
486 if *pos >= data.len() {
487 return Err(UnwindError::InvalidDwarf("SLEB128 past end".into()));
488 }
489 byte = data[*pos];
490 *pos += 1;
491 result |= ((byte & 0x7F) as i64) << shift;
492 shift += 7;
493 if byte & 0x80 == 0 {
494 break;
495 }
496 if shift >= 64 {
497 return Err(UnwindError::InvalidDwarf("SLEB128 overflow".into()));
498 }
499 }
500 if shift < 64 && (byte & 0x40) != 0 {
501 result |= !0i64 << shift;
502 }
503 Ok(result)
504}
505
506#[cfg(test)]
507mod tests {
508 use super::*;
509 use crate::types::CpuType;
510 use crate::unwind::SliceMemoryReader;
511
512 fn make_reader() -> SliceMemoryReader {
513 let mut data = vec![0u8; 256];
514 data[0x80..0x88].copy_from_slice(&0xDEAD_BEEF_CAFE_BABEu64.to_le_bytes());
516 SliceMemoryReader {
517 data,
518 base_address: 0x1000,
519 }
520 }
521
522 fn make_regs() -> RegisterContext {
523 let mut regs = RegisterContext::new(CpuType::ARM64);
524 regs.set(0, 100); regs.set(29, 0x1080); regs.set(31, 0x2000); regs
528 }
529
530 #[test]
531 fn lit_values() {
532 let reader = make_reader();
533 let regs = make_regs();
534 assert_eq!(evaluate(&[0x35], ®s, &reader, true).unwrap(), 5);
536 assert_eq!(evaluate(&[0x30], ®s, &reader, true).unwrap(), 0);
538 assert_eq!(evaluate(&[0x4F], ®s, &reader, true).unwrap(), 31);
540 }
541
542 #[test]
543 fn const_u_s() {
544 let reader = make_reader();
545 let regs = make_regs();
546 assert_eq!(evaluate(&[0x08, 42], ®s, &reader, true).unwrap(), 42);
548 assert_eq!(
550 evaluate(&[0x09, 0xFF], ®s, &reader, true).unwrap(),
551 (-1i64) as u64
552 );
553 }
554
555 #[test]
556 fn breg_fp_offset() {
557 let reader = make_reader();
558 let regs = make_regs();
559 assert_eq!(
562 evaluate(&[0x8D, 0x00], ®s, &reader, true).unwrap(),
563 0x1080
564 );
565 }
566
567 #[test]
568 fn deref() {
569 let reader = make_reader();
570 let regs = make_regs();
571 assert_eq!(
573 evaluate(&[0x8D, 0x00, op::DEREF], ®s, &reader, true).unwrap(),
574 0xDEAD_BEEF_CAFE_BABE
575 );
576 }
577
578 #[test]
579 fn arithmetic_plus() {
580 let reader = make_reader();
581 let regs = make_regs();
582 assert_eq!(
584 evaluate(&[0x35, 0x33, op::PLUS], ®s, &reader, true).unwrap(),
585 8
586 );
587 }
588
589 #[test]
590 fn plus_uconst() {
591 let reader = make_reader();
592 let regs = make_regs();
593 assert_eq!(
595 evaluate(&[0x3A, op::PLUS_UCONST, 20], ®s, &reader, true).unwrap(),
596 30
597 );
598 }
599
600 #[test]
601 fn stack_operations() {
602 let reader = make_reader();
603 let regs = make_regs();
604 assert_eq!(
607 evaluate(&[0x31, 0x32, op::SWAP], ®s, &reader, true).unwrap(),
608 1
609 );
610 }
611
612 #[test]
613 fn uleb128_encoding() {
614 let mut pos = 0;
616 let data = [0x80, 0x01]; assert_eq!(read_uleb128(&data, &mut pos).unwrap(), 128);
618 assert_eq!(pos, 2);
619 }
620
621 #[test]
622 fn sleb128_encoding() {
623 let mut pos = 0;
625 let data = [0x7F]; assert_eq!(read_sleb128(&data, &mut pos).unwrap(), -1);
627 }
628
629 #[test]
630 fn empty_expression_error() {
631 let reader = make_reader();
632 let regs = make_regs();
633 assert!(evaluate(&[], ®s, &reader, true).is_err());
634 }
635}