Line data Source code
1 : use lief_ffi as ffi;
2 :
3 : use crate::common::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 {
16 0 : ptr,
17 0 : }
18 0 : }
19 : }
20 :
21 : /// This structure defines an implementation range
22 : pub struct Range {
23 : start: u64,
24 : end: u64,
25 : }
26 :
27 :
28 : /// This structure represents a parameter of the current function (`DW_TAG_formal_parameter`)
29 : pub struct Parameter {
30 : ptr: cxx::UniquePtr<ffi::DWARF_editor_Function_Parameter>,
31 : }
32 :
33 : impl FromFFI<ffi::DWARF_editor_Function_Parameter> for Parameter {
34 0 : fn from_ffi(ptr: cxx::UniquePtr<ffi::DWARF_editor_Function_Parameter>) -> Self {
35 0 : Self {
36 0 : ptr,
37 0 : }
38 0 : }
39 : }
40 :
41 : /// This structure mirrors the `DW_TAG_lexical_block` DWARF tag
42 : pub struct LexicalBlock {
43 : ptr: cxx::UniquePtr<ffi::DWARF_editor_Function_LexicalBlock>,
44 : }
45 :
46 : impl FromFFI<ffi::DWARF_editor_Function_LexicalBlock> for LexicalBlock {
47 0 : fn from_ffi(ptr: cxx::UniquePtr<ffi::DWARF_editor_Function_LexicalBlock>) -> Self {
48 0 : Self {
49 0 : ptr,
50 0 : }
51 0 : }
52 : }
53 :
54 : /// This class mirrors the `DW_TAG_label` DWARF tag
55 : pub struct Label {
56 : ptr: cxx::UniquePtr<ffi::DWARF_editor_Function_Label>,
57 : }
58 :
59 : impl FromFFI<ffi::DWARF_editor_Function_Label> for Label {
60 0 : fn from_ffi(ptr: cxx::UniquePtr<ffi::DWARF_editor_Function_Label>) -> Self {
61 0 : Self {
62 0 : ptr,
63 0 : }
64 0 : }
65 : }
66 :
67 : impl Function {
68 : /// Set the address of this function by defining `DW_AT_entry_pc`
69 0 : pub fn set_address(&mut self, addr: u64) -> &mut Self {
70 0 : self.ptr.pin_mut().set_address(addr);
71 0 : self
72 0 : }
73 :
74 : /// Set the upper and lower bound addresses for this function. This assumes
75 : /// that the function is contiguous between `low` and `high`.
76 : ///
77 : /// Underneath, the function defines `DW_AT_low_pc` and `DW_AT_high_pc`
78 0 : pub fn set_low_high(&mut self, low: u64, high: u64) -> &mut Self {
79 0 : self.ptr.pin_mut().set_low_high(low, high);
80 0 : self
81 0 : }
82 :
83 : /// Set the ranges of addresses owned by the implementation of this function
84 : /// by setting the `DW_AT_ranges` attribute.
85 : ///
86 : /// This setter should be used for non-contiguous function.
87 0 : pub fn set_ranges(&mut self, ranges: &[Range]) -> &mut Self {
88 0 : let mut ffi_ranges = cxx::CxxVector::new();
89 0 : for range in ranges {
90 0 : let ffi_range = ffi::DWARF_editor_Function_Range {
91 0 : start: range.start,
92 0 : end: range.end,
93 0 : };
94 0 : ffi_ranges.as_mut().unwrap().push(ffi_range);
95 0 : }
96 0 : self.ptr.pin_mut().set_ranges(&ffi_ranges);
97 0 : self
98 0 : }
99 :
100 : /// Set the function as external by defining `DW_AT_external` to true.
101 : /// This means that the function is **imported** by the current compilation unit.
102 0 : pub fn set_external(&mut self) -> &mut Self {
103 0 : self.ptr.pin_mut().set_external();
104 0 : self
105 0 : }
106 :
107 : /// Set the return type of this function
108 0 : pub fn set_return_type(&mut self, ty: &dyn EditorType) -> &mut Self {
109 0 : self.ptr.pin_mut().set_return_type(ty.get_base());
110 0 : self
111 0 : }
112 :
113 : /// Add a parameter to the current function
114 0 : pub fn add_parameter(&mut self, name: &str, ty: &dyn EditorType) -> Parameter {
115 0 : Parameter::from_ffi(self.ptr.pin_mut().add_parameter(name, ty.get_base()))
116 0 : }
117 :
118 : /// Create a stack-based variable owned by the current function
119 0 : pub fn create_stack_variable(&mut self, name: &str) -> Variable {
120 0 : Variable::from_ffi(self.ptr.pin_mut().create_stack_variable(name))
121 0 : }
122 :
123 : /// Add a lexical block with the given range
124 0 : pub fn add_lexical_block(&mut self, start: u64, end: u64) -> LexicalBlock {
125 0 : LexicalBlock::from_ffi(self.ptr.pin_mut().add_lexical_block(start, end))
126 0 : }
127 :
128 : /// Add a label at the given address
129 0 : pub fn add_label(&mut self, addr: u64, name: &str) -> Label {
130 0 : Label::from_ffi(self.ptr.pin_mut().add_label(addr, name))
131 0 : }
132 : }
|