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
use alloc::vec::Vec;
use gimli::write::{Address, FrameDescriptionEntry};
use thiserror::Error;
#[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize};
type Register = u16;
#[allow(missing_docs)]
#[derive(Error, Debug, PartialEq, Eq)]
pub enum RegisterMappingError {
#[error("unable to find bank for register info")]
MissingBank,
#[error("register mapping is currently only implemented for x86_64")]
UnsupportedArchitecture,
#[error("unsupported register bank: {0}")]
UnsupportedRegisterBank(&'static str),
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub(crate) enum CallFrameInstruction {
Cfa(Register, i32),
CfaRegister(Register),
CfaOffset(i32),
Restore(Register),
Undefined(Register),
SameValue(Register),
Offset(Register, i32),
ValOffset(Register, i32),
Register(Register, Register),
RememberState,
RestoreState,
ArgsSize(u32),
}
impl From<gimli::write::CallFrameInstruction> for CallFrameInstruction {
fn from(cfi: gimli::write::CallFrameInstruction) -> Self {
use gimli::write::CallFrameInstruction;
match cfi {
CallFrameInstruction::Cfa(reg, offset) => Self::Cfa(reg.0, offset),
CallFrameInstruction::CfaRegister(reg) => Self::CfaRegister(reg.0),
CallFrameInstruction::CfaOffset(offset) => Self::CfaOffset(offset),
CallFrameInstruction::Restore(reg) => Self::Restore(reg.0),
CallFrameInstruction::Undefined(reg) => Self::Undefined(reg.0),
CallFrameInstruction::SameValue(reg) => Self::SameValue(reg.0),
CallFrameInstruction::Offset(reg, offset) => Self::Offset(reg.0, offset),
CallFrameInstruction::ValOffset(reg, offset) => Self::ValOffset(reg.0, offset),
CallFrameInstruction::Register(reg1, reg2) => Self::Register(reg1.0, reg2.0),
CallFrameInstruction::RememberState => Self::RememberState,
CallFrameInstruction::RestoreState => Self::RestoreState,
CallFrameInstruction::ArgsSize(size) => Self::ArgsSize(size),
_ => {
panic!("CallFrameInstruction with Expression not supported");
}
}
}
}
impl Into<gimli::write::CallFrameInstruction> for CallFrameInstruction {
fn into(self) -> gimli::write::CallFrameInstruction {
use gimli::{write::CallFrameInstruction, Register};
match self {
Self::Cfa(reg, offset) => CallFrameInstruction::Cfa(Register(reg), offset),
Self::CfaRegister(reg) => CallFrameInstruction::CfaRegister(Register(reg)),
Self::CfaOffset(offset) => CallFrameInstruction::CfaOffset(offset),
Self::Restore(reg) => CallFrameInstruction::Restore(Register(reg)),
Self::Undefined(reg) => CallFrameInstruction::Undefined(Register(reg)),
Self::SameValue(reg) => CallFrameInstruction::SameValue(Register(reg)),
Self::Offset(reg, offset) => CallFrameInstruction::Offset(Register(reg), offset),
Self::ValOffset(reg, offset) => CallFrameInstruction::ValOffset(Register(reg), offset),
Self::Register(reg1, reg2) => {
CallFrameInstruction::Register(Register(reg1), Register(reg2))
}
Self::RememberState => CallFrameInstruction::RememberState,
Self::RestoreState => CallFrameInstruction::RestoreState,
Self::ArgsSize(size) => CallFrameInstruction::ArgsSize(size),
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct UnwindInfo {
instructions: Vec<(u32, CallFrameInstruction)>,
len: u32,
}
impl UnwindInfo {
pub(crate) fn new(instructions: Vec<(u32, CallFrameInstruction)>, len: u32) -> Self {
Self { instructions, len }
}
pub fn to_fde(&self, address: Address) -> gimli::write::FrameDescriptionEntry {
let mut fde = FrameDescriptionEntry::new(address, self.len);
for (offset, inst) in &self.instructions {
fde.add_instruction(*offset, inst.clone().into());
}
fde
}
}