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