Line data Source code
1 : use lief_ffi as ffi;
2 :
3 : use crate::{common::FromFFI, Error};
4 :
5 : use crate::to_conv_result;
6 : use std::marker::PhantomData;
7 : use crate::debug_location::DebugLocation;
8 : use crate::dwarf::Scope;
9 : use crate::common::into_optional;
10 : use crate::declare_fwd_iterator;
11 :
12 : pub mod classlike;
13 : pub mod pointer;
14 : pub mod const_ty;
15 : pub mod base;
16 : pub mod array;
17 :
18 : #[doc(inline)]
19 : pub use classlike::Structure;
20 :
21 : #[doc(inline)]
22 : pub use classlike::Class;
23 :
24 : #[doc(inline)]
25 : pub use classlike::Union;
26 :
27 : #[doc(inline)]
28 : pub use classlike::ClassLike;
29 :
30 : #[doc(inline)]
31 : pub use pointer::Pointer;
32 :
33 : #[doc(inline)]
34 : pub use const_ty::Const;
35 :
36 : #[doc(inline)]
37 : pub use base::Base;
38 :
39 : #[doc(inline)]
40 : pub use array::Array;
41 :
42 : /// This class represents a DWARF Type which includes:
43 : ///
44 : /// - `DW_TAG_array_type`
45 : /// - `DW_TAG_const_type`
46 : /// - `DW_TAG_pointer_type`
47 : /// - `DW_TAG_structure_type`
48 : /// - `DW_TAG_base_type`
49 : /// - `DW_TAG_class_type`
50 : /// - `DW_TAG_enumeration_type`
51 : /// - `DW_TAG_string_type`
52 : /// - `DW_TAG_union_type`
53 : /// - `DW_TAG_volatile_type`
54 : /// - `DW_TAG_unspecified_type`
55 : pub enum Type<'a> {
56 : /// Interface over `DW_TAG_structure_type`
57 : Structure(Structure<'a>),
58 :
59 : /// Interface over `DW_TAG_class_type`
60 : Class(Class<'a>),
61 :
62 : /// Interface over `DW_TAG_union_type`
63 : Union(Union<'a>),
64 :
65 : /// Interface over `DW_TAG_pointer_type`
66 : Pointer(Pointer<'a>),
67 :
68 : /// Interface over `DW_TAG_const_type`
69 : Const(Const<'a>),
70 :
71 : /// Interface over `DW_TAG_base_type`
72 : Base(Base<'a>),
73 :
74 : /// Interface over `DW_TAG_array_type`
75 : Array(Array<'a>),
76 :
77 : /// Generic type (fallback value)
78 : Generic(Generic<'a>),
79 : }
80 :
81 : impl FromFFI<ffi::DWARF_Type> for Type<'_> {
82 0 : fn from_ffi(ffi_entry: cxx::UniquePtr<ffi::DWARF_Type>) -> Self {
83 0 : unsafe {
84 0 : let type_ref = ffi_entry.as_ref().unwrap();
85 0 :
86 0 : if ffi::DWARF_types_Structure::classof(type_ref) {
87 0 : let raw = {
88 0 : type From = cxx::UniquePtr<ffi::DWARF_Type>;
89 0 : type To = cxx::UniquePtr<ffi::DWARF_types_Structure>;
90 0 : std::mem::transmute::<From, To>(ffi_entry)
91 0 : };
92 0 : Type::Structure(Structure::from_ffi(raw))
93 0 : } else if ffi::DWARF_types_Class::classof(type_ref) {
94 0 : let raw = {
95 0 : type From = cxx::UniquePtr<ffi::DWARF_Type>;
96 0 : type To = cxx::UniquePtr<ffi::DWARF_types_Class>;
97 0 : std::mem::transmute::<From, To>(ffi_entry)
98 0 : };
99 0 : Type::Class(Class::from_ffi(raw))
100 0 : } else if ffi::DWARF_types_Union::classof(type_ref) {
101 0 : let raw = {
102 0 : type From = cxx::UniquePtr<ffi::DWARF_Type>;
103 0 : type To = cxx::UniquePtr<ffi::DWARF_types_Union>;
104 0 : std::mem::transmute::<From, To>(ffi_entry)
105 0 : };
106 0 : Type::Union(Union::from_ffi(raw))
107 0 : } else if ffi::DWARF_types_Pointer::classof(type_ref) {
108 0 : let raw = {
109 0 : type From = cxx::UniquePtr<ffi::DWARF_Type>;
110 0 : type To = cxx::UniquePtr<ffi::DWARF_types_Pointer>;
111 0 : std::mem::transmute::<From, To>(ffi_entry)
112 0 : };
113 0 : Type::Pointer(Pointer::from_ffi(raw))
114 0 : } else if ffi::DWARF_types_Const::classof(type_ref) {
115 0 : let raw = {
116 0 : type From = cxx::UniquePtr<ffi::DWARF_Type>;
117 0 : type To = cxx::UniquePtr<ffi::DWARF_types_Const>;
118 0 : std::mem::transmute::<From, To>(ffi_entry)
119 0 : };
120 0 : Type::Const(Const::from_ffi(raw))
121 0 : } else if ffi::DWARF_types_Base::classof(type_ref) {
122 0 : let raw = {
123 0 : type From = cxx::UniquePtr<ffi::DWARF_Type>;
124 0 : type To = cxx::UniquePtr<ffi::DWARF_types_Base>;
125 0 : std::mem::transmute::<From, To>(ffi_entry)
126 0 : };
127 0 : Type::Base(Base::from_ffi(raw))
128 0 : } else if ffi::DWARF_types_Array::classof(type_ref) {
129 0 : let raw = {
130 0 : type From = cxx::UniquePtr<ffi::DWARF_Type>;
131 0 : type To = cxx::UniquePtr<ffi::DWARF_types_Array>;
132 0 : std::mem::transmute::<From, To>(ffi_entry)
133 0 : };
134 0 : Type::Array(Array::from_ffi(raw))
135 : } else {
136 0 : Type::Generic(Generic::from_ffi(ffi_entry))
137 : }
138 : }
139 0 : }
140 : }
141 :
142 : /// Generic structure for types that do not required a dedicated interface
143 : pub struct Generic<'a> {
144 : ptr: cxx::UniquePtr<ffi::DWARF_Type>,
145 : _owner: PhantomData<&'a ()>,
146 : }
147 :
148 : impl FromFFI<ffi::DWARF_Type> for Generic<'_> {
149 0 : fn from_ffi(cmd: cxx::UniquePtr<ffi::DWARF_Type>) -> Self {
150 0 : Self {
151 0 : ptr: cmd,
152 0 : _owner: PhantomData,
153 0 : }
154 0 : }
155 : }
156 :
157 : /// Generic trait shared by all DWARF types
158 : pub trait DwarfType {
159 : #[doc(hidden)]
160 : fn get_base(&self) -> &ffi::DWARF_Type;
161 :
162 : /// Return the type's name (if any)
163 0 : fn name(&self) -> Result<String, Error> {
164 0 : to_conv_result!(
165 0 : ffi::DWARF_Type::name,
166 0 : self.get_base(),
167 0 : |e: cxx::UniquePtr<cxx::String>| { e.to_string() }
168 : );
169 0 : }
170 :
171 : /// Return the size of the type or an error if it can't be computed.
172 : ///
173 : /// This size should match the equivalent of `sizeof(Type)`.
174 0 : fn size(&self) -> Result<u64, Error> {
175 0 : to_conv_result!(
176 0 : ffi::DWARF_Type::size,
177 0 : self.get_base(),
178 0 : |e| e
179 : );
180 0 : }
181 :
182 : /// Return the debug location where this type is defined.
183 0 : fn location(&self) -> DebugLocation {
184 0 : DebugLocation::from_ffi(self.get_base().location())
185 0 : }
186 :
187 : /// Whether this type is a `DW_TAG_unspecified_type`.
188 0 : fn is_unspecified(&self) -> bool {
189 0 : self.get_base().is_unspecified()
190 0 : }
191 :
192 : /// The scope in which this function is defined
193 0 : fn scope(&self) -> Option<Scope> {
194 0 : into_optional(self.get_base().scope())
195 0 : }
196 : }
197 :
198 : impl DwarfType for Generic<'_> {
199 0 : fn get_base(&self) -> &ffi::DWARF_Type {
200 0 : self.ptr.as_ref().unwrap()
201 0 : }
202 : }
203 :
204 : impl DwarfType for Type<'_> {
205 0 : fn get_base(&self) -> &ffi::DWARF_Type {
206 0 : match &self {
207 0 : Type::Structure(s) => {
208 0 : s.get_base()
209 : }
210 0 : Type::Class(s) => {
211 0 : s.get_base()
212 : }
213 0 : Type::Union(s) => {
214 0 : s.get_base()
215 : }
216 0 : Type::Pointer(s) => {
217 0 : s.get_base()
218 : }
219 0 : Type::Const(s) => {
220 0 : s.get_base()
221 : }
222 0 : Type::Base(s) => {
223 0 : s.get_base()
224 : }
225 0 : Type::Array(s) => {
226 0 : s.get_base()
227 : }
228 0 : Type::Generic(s) => {
229 0 : s.get_base()
230 : }
231 : }
232 0 : }
233 : }
234 :
235 0 : declare_fwd_iterator!(
236 0 : Types,
237 0 : Type<'a>,
238 0 : ffi::DWARF_Type,
239 0 : ffi::DWARF_CompilationUnit,
240 0 : ffi::DWARF_CompilationUnit_it_types
241 0 : );
242 :
|