Line data Source code
1 : use lief_ffi as ffi;
2 :
3 :
4 : use crate::common::{FromFFI, into_optional};
5 :
6 : use crate::dwarf::editor::types::EditorType;
7 : use crate::dwarf::editor::Variable;
8 :
9 : /// This structure represents an **editable** DWARF function (`DW_TAG_subprogram`)
10 : pub struct Function {
11 : ptr: cxx::UniquePtr<ffi::DWARF_editor_Function>,
12 : }
13 :
14 : impl FromFFI<ffi::DWARF_editor_Function> for Function {
15 0 : fn from_ffi(ptr: cxx::UniquePtr<ffi::DWARF_editor_Function>) -> Self {
16 0 : Self {
17 0 : ptr,
18 0 : }
19 0 : }
20 : }
21 :
22 : /// This structure defines an implementation range
23 : pub struct Range {
24 : start: u64,
25 : end: u64,
26 : }
27 :
28 :
29 : /// This structure represents a parameter of the current function (`DW_TAG_formal_parameter`)
30 : pub struct Parameter {
31 : ptr: cxx::UniquePtr<ffi::DWARF_editor_Function_Parameter>,
32 : }
33 :
34 : impl Parameter {
35 : /// Assign this parameter to a specific named register.
36 0 : pub fn assign_register_by_name(&mut self, name: &str) -> &mut Self {
37 0 : self.ptr.pin_mut().assign_register_by_name(name);
38 0 : self
39 0 : }
40 :
41 : /// Assign this parameter to the given DWARF register id (e.g. `DW_OP_reg0`).
42 0 : pub fn assign_register_by_id(&mut self, id: u64) -> &mut Self {
43 0 : self.ptr.pin_mut().assign_register_by_id(id);
44 0 : self
45 0 : }
46 : }
47 :
48 : impl FromFFI<ffi::DWARF_editor_Function_Parameter> for Parameter {
49 0 : fn from_ffi(ptr: cxx::UniquePtr<ffi::DWARF_editor_Function_Parameter>) -> Self {
50 0 : Self {
51 0 : ptr,
52 0 : }
53 0 : }
54 : }
55 :
56 : /// This structure mirrors the `DW_TAG_lexical_block` DWARF tag
57 : pub struct LexicalBlock {
58 : ptr: cxx::UniquePtr<ffi::DWARF_editor_Function_LexicalBlock>,
59 : }
60 :
61 : impl FromFFI<ffi::DWARF_editor_Function_LexicalBlock> for LexicalBlock {
62 0 : fn from_ffi(ptr: cxx::UniquePtr<ffi::DWARF_editor_Function_LexicalBlock>) -> Self {
63 0 : Self {
64 0 : ptr,
65 0 : }
66 0 : }
67 : }
68 :
69 : impl LexicalBlock {
70 : /// Create a `DW_AT_name` entry to associate a name to this entry
71 0 : pub fn add_name(&mut self, name: &str) -> &mut Self {
72 0 : self.ptr.pin_mut().add_name(name);
73 0 : self
74 0 : }
75 :
76 : /// Create a `DW_AT_description` entry with the description
77 : /// provided in parameter.
78 0 : pub fn add_description(&mut self, description: &str) -> &mut Self {
79 0 : self.ptr.pin_mut().add_description(description);
80 0 : self
81 0 : }
82 :
83 : /// Create a sub-block with the given low/high addresses.
84 0 : pub fn add_block(&mut self, start: u64, end: u64) -> Option<LexicalBlock> {
85 0 : into_optional(self.ptr.pin_mut().add_block(start, end))
86 0 : }
87 :
88 : /// Create a sub-block with the given range of addresses.
89 0 : pub fn add_block_from_range(&mut self, ranges: &[Range]) -> Option<LexicalBlock> {
90 0 : let mut ffi_ranges = cxx::CxxVector::new();
91 0 : for range in ranges {
92 0 : let ffi_range = ffi::DWARF_editor_Function_Range {
93 0 : start: range.start,
94 0 : end: range.end,
95 0 : };
96 0 : ffi_ranges.as_mut().unwrap().push(ffi_range);
97 0 : }
98 0 : into_optional(self.ptr.pin_mut().add_block_from_range(&ffi_ranges))
99 0 : }
100 : }
101 :
102 : /// This class mirrors the `DW_TAG_label` DWARF tag
103 : #[allow(dead_code)]
104 : pub struct Label {
105 : ptr: cxx::UniquePtr<ffi::DWARF_editor_Function_Label>,
106 : }
107 :
108 : impl FromFFI<ffi::DWARF_editor_Function_Label> for Label {
109 0 : fn from_ffi(ptr: cxx::UniquePtr<ffi::DWARF_editor_Function_Label>) -> Self {
110 0 : Self {
111 0 : ptr,
112 0 : }
113 0 : }
114 : }
115 :
116 : impl Function {
117 : /// Set the address of this function by defining `DW_AT_entry_pc`
118 0 : pub fn set_address(&mut self, addr: u64) -> &mut Self {
119 0 : self.ptr.pin_mut().set_address(addr);
120 0 : self
121 0 : }
122 :
123 : /// Set the upper and lower bound addresses for this function. This assumes
124 : /// that the function is contiguous between `low` and `high`.
125 : ///
126 : /// Underneath, the function defines `DW_AT_low_pc` and `DW_AT_high_pc`
127 0 : pub fn set_low_high(&mut self, low: u64, high: u64) -> &mut Self {
128 0 : self.ptr.pin_mut().set_low_high(low, high);
129 0 : self
130 0 : }
131 :
132 : /// Set the ranges of addresses owned by the implementation of this function
133 : /// by setting the `DW_AT_ranges` attribute.
134 : ///
135 : /// This setter should be used for non-contiguous function.
136 0 : pub fn set_ranges(&mut self, ranges: &[Range]) -> &mut Self {
137 0 : let mut ffi_ranges = cxx::CxxVector::new();
138 0 : for range in ranges {
139 0 : let ffi_range = ffi::DWARF_editor_Function_Range {
140 0 : start: range.start,
141 0 : end: range.end,
142 0 : };
143 0 : ffi_ranges.as_mut().unwrap().push(ffi_range);
144 0 : }
145 0 : self.ptr.pin_mut().set_ranges(&ffi_ranges);
146 0 : self
147 0 : }
148 :
149 : /// Set the function as external by defining `DW_AT_external` to true.
150 : /// This means that the function is **imported** by the current compilation unit.
151 0 : pub fn set_external(&mut self) -> &mut Self {
152 0 : self.ptr.pin_mut().set_external();
153 0 : self
154 0 : }
155 :
156 : /// Set the return type of this function
157 0 : pub fn set_return_type(&mut self, ty: &dyn EditorType) -> &mut Self {
158 0 : self.ptr.pin_mut().set_return_type(ty.get_base());
159 0 : self
160 0 : }
161 :
162 : /// Add a parameter to the current function
163 0 : pub fn add_parameter(&mut self, name: &str, ty: &dyn EditorType) -> Parameter {
164 0 : Parameter::from_ffi(self.ptr.pin_mut().add_parameter(name, ty.get_base()))
165 0 : }
166 :
167 : /// Create a stack-based variable owned by the current function
168 0 : pub fn create_stack_variable(&mut self, name: &str) -> Variable {
169 0 : Variable::from_ffi(self.ptr.pin_mut().create_stack_variable(name))
170 0 : }
171 :
172 : /// Add a lexical block with the given range
173 0 : pub fn add_lexical_block(&mut self, start: u64, end: u64) -> LexicalBlock {
174 0 : LexicalBlock::from_ffi(self.ptr.pin_mut().add_lexical_block(start, end))
175 0 : }
176 :
177 : /// Add a label at the given address
178 0 : pub fn add_label(&mut self, addr: u64, name: &str) -> Label {
179 0 : Label::from_ffi(self.ptr.pin_mut().add_label(addr, name))
180 0 : }
181 :
182 : /// Create a `DW_AT_description` entry with the description
183 : /// provided in parameter.
184 0 : pub fn add_description(&mut self, description: &str) -> &mut Self {
185 0 : self.ptr.pin_mut().add_description(description);
186 0 : self
187 0 : }
188 : }
|