Line data Source code
1 : use lief_ffi as ffi;
2 :
3 : use super::variable::Variables;
4 : use super::lexical_block::LexicalBlock;
5 : use super::{Scope, Type, Parameters};
6 : use crate::common::{into_optional, into_ranges, FromFFI};
7 : use crate::declare_fwd_iterator;
8 : use crate::to_result;
9 : use crate::DebugLocation;
10 : use crate::Error;
11 : use crate::Range;
12 : use crate::assembly;
13 : use std::marker::PhantomData;
14 :
15 : /// This structure represents a DWARF function which can be associated with either:
16 : /// `DW_TAG_subprogram` or `DW_TAG_inlined_subroutine`.
17 : pub struct Function<'a> {
18 : ptr: cxx::UniquePtr<ffi::DWARF_Function>,
19 : _owner: PhantomData<&'a ()>,
20 : }
21 :
22 : impl FromFFI<ffi::DWARF_Function> for Function<'_> {
23 0 : fn from_ffi(ptr: cxx::UniquePtr<ffi::DWARF_Function>) -> Self {
24 0 : Self {
25 0 : ptr,
26 0 : _owner: PhantomData,
27 0 : }
28 0 : }
29 : }
30 :
31 : impl Function<'_> {
32 : /// The name of the function (`DW_AT_name`)
33 0 : pub fn name(&self) -> String {
34 0 : self.ptr.name().to_string()
35 0 : }
36 :
37 : /// The name of the function which is used for linking (`DW_AT_linkage_name`).
38 : ///
39 : /// This name differs from [`Function::name`] as it is usually mangled. The function
40 : /// return an empty string if the linkage name is not available.
41 0 : pub fn linkage_name(&self) -> String {
42 0 : self.ptr.linkage_name().to_string()
43 0 : }
44 :
45 : /// Return the address of the function (`DW_AT_entry_pc` or `DW_AT_low_pc`).
46 0 : pub fn address(&self) -> Result<u64, Error> {
47 0 : to_result!(ffi::DWARF_Function::address, self);
48 0 : }
49 :
50 : /// Return an iterator of variables (`DW_TAG_variable`) defined within the
51 : /// scope of this function. This includes regular stack-based variables as
52 : /// well as static ones.
53 0 : pub fn variables(&self) -> Variables {
54 0 : Variables::new(self.ptr.variables())
55 0 : }
56 :
57 : /// Whether this function is created by the compiler and not
58 : /// present in the original source code
59 0 : pub fn is_artificial(&self) -> bool {
60 0 : self.ptr.is_artificial()
61 0 : }
62 :
63 : /// Whether the function is defined **outside** the compilation unit (`DW_AT_external`)
64 0 : pub fn is_external(&self) -> bool {
65 0 : self.ptr.is_external()
66 0 : }
67 :
68 : /// Return the size taken by this function in the binary
69 0 : pub fn size(&self) -> u64 {
70 0 : self.ptr.size()
71 0 : }
72 :
73 : /// Ranges of virtual addresses owned by this function
74 0 : pub fn ranges(&self) -> Vec<Range> {
75 0 : into_ranges(self.ptr.ranges())
76 0 : }
77 :
78 : /// Original source code location
79 0 : pub fn debug_location(&self) -> DebugLocation {
80 0 : DebugLocation::from_ffi(self.ptr.debug_location())
81 0 : }
82 :
83 : /// Return the [`Type`] associated with the **return type** of this function.
84 0 : pub fn return_type(&self) -> Option<Type> {
85 0 : into_optional(self.ptr.get_type())
86 0 : }
87 :
88 : /// Return an iterator over the [`Parameters`] of this function
89 0 : pub fn parameters(&self) -> ParametersIt {
90 0 : ParametersIt::new(self.ptr.parameters())
91 0 : }
92 :
93 : /// List of exceptions (types) that can be thrown by the function.
94 : ///
95 : /// For instance, given this Swift code:
96 : ///
97 : /// ```swift
98 : /// func summarize(_ ratings: [Int]) throws(StatisticsError) {
99 : /// // ...
100 : /// }
101 : /// ```
102 : ///
103 : /// [`Function::thrown_types`] returns one element associated with the [`Type`]:
104 : /// `StatisticsError`.
105 0 : pub fn thrown_types(&self) -> ThrownTypes {
106 0 : ThrownTypes::new(self.ptr.thrown_types())
107 0 : }
108 :
109 : /// The scope in which this function is defined
110 0 : pub fn scope(&self) -> Option<Scope> {
111 0 : into_optional(self.ptr.scope())
112 0 : }
113 :
114 : /// Disassemble the current function by returning an iterator over
115 : /// the [`assembly::Instructions`]
116 0 : pub fn instructions(&self) -> Instructions {
117 0 : Instructions::new(self.ptr.instructions())
118 0 : }
119 :
120 : /// Description (`DW_AT_description`) of this function or an empty string
121 0 : pub fn description(&self) -> String {
122 0 : self.ptr.description().to_string()
123 0 : }
124 :
125 : /// Iterator over the [`crate::dwarf::LexicalBlock`] owned by this function
126 0 : pub fn lexical_blocks(&self) -> LexicalBlocks {
127 0 : LexicalBlocks::new(self.ptr.lexical_blocks())
128 0 : }
129 : }
130 :
131 0 : declare_fwd_iterator!(
132 0 : Functions,
133 0 : Function<'a>,
134 0 : ffi::DWARF_Function,
135 0 : ffi::DWARF_CompilationUnit,
136 0 : ffi::DWARF_CompilationUnit_it_functions
137 0 : );
138 :
139 0 : declare_fwd_iterator!(
140 0 : ParametersIt,
141 0 : Parameters<'a>,
142 0 : ffi::DWARF_Parameter,
143 0 : ffi::DWARF_Function,
144 0 : ffi::DWARF_Function_it_parameters
145 0 : );
146 :
147 0 : declare_fwd_iterator!(
148 0 : ThrownTypes,
149 0 : Type<'a>,
150 0 : ffi::DWARF_Type,
151 0 : ffi::DWARF_Function,
152 0 : ffi::DWARF_Function_it_thrown_types
153 0 : );
154 :
155 :
156 0 : declare_fwd_iterator!(
157 0 : Instructions,
158 0 : assembly::Instructions,
159 0 : ffi::asm_Instruction,
160 0 : ffi::DWARF_Function,
161 0 : ffi::DWARF_Function_it_instructions
162 0 : );
163 :
164 :
165 0 : declare_fwd_iterator!(
166 0 : LexicalBlocks,
167 0 : LexicalBlock<'a>,
168 0 : ffi::DWARF_LexicalBlock,
169 0 : ffi::DWARF_Function,
170 0 : ffi::DWARF_Function_it_lexical_blocks
171 0 : );
|