Line data Source code
1 : use lief_ffi as ffi;
2 :
3 : use super::Type;
4 : use crate::common::into_optional;
5 : use crate::common::FromFFI;
6 : use crate::DebugLocation;
7 : use crate::{declare_fwd_iterator, to_result, Error};
8 : use std::marker::PhantomData;
9 : use crate::dwarf::Scope;
10 :
11 : /// Return an iterator of the variable `DW_TAG_variable` defined within the
12 : /// scope of this function. This includes regular stack-based variables as
13 : /// well as static ones.
14 : pub struct Variable<'a> {
15 : ptr: cxx::UniquePtr<ffi::DWARF_Variable>,
16 : _owner: PhantomData<&'a ()>,
17 : }
18 :
19 : impl FromFFI<ffi::DWARF_Variable> for Variable<'_> {
20 0 : fn from_ffi(ptr: cxx::UniquePtr<ffi::DWARF_Variable>) -> Self {
21 0 : Self {
22 0 : ptr,
23 0 : _owner: PhantomData,
24 0 : }
25 0 : }
26 : }
27 :
28 : impl Variable<'_> {
29 : /// Name of the variable (usually demangled)
30 0 : pub fn name(&self) -> String {
31 0 : self.ptr.name().to_string()
32 0 : }
33 :
34 : /// The name of the variable which is used for linking (`DW_AT_linkage_name`).
35 : ///
36 : /// This name differs from [`Variable::name`] as it is usually mangled.
37 0 : pub fn linkage_name(&self) -> Option<String> {
38 0 : let name = self.ptr.name().to_string();
39 0 : if !name.is_empty() {
40 0 : return Some(name);
41 0 : }
42 0 : None
43 0 : }
44 :
45 : /// Address of the variable.
46 : ///
47 : /// If the variable is **static**, it returns the **virtual address**
48 : /// where it is defined.
49 : /// If the variable is stack-based, it returns the **relative offset** from
50 : /// the frame based register.
51 : ///
52 : /// If the address can't be resolved, it returns an [`Error`].
53 0 : pub fn address(&self) -> Result<i64, Error> {
54 0 : to_result!(ffi::DWARF_Variable::address, self);
55 0 : }
56 :
57 : /// Return the size of the variable (or an [`Error`] if it can't be
58 : /// resolved).
59 : ///
60 : /// This size is defined by its type.
61 0 : pub fn size(&self) -> Result<u64, Error> {
62 0 : to_result!(ffi::DWARF_Variable::size, self);
63 0 : }
64 :
65 : /// Whether it's a `constexpr` variable
66 0 : pub fn is_constexpr(&self) -> bool {
67 0 : self.ptr.is_constexpr()
68 0 : }
69 :
70 : /// The original source location where the variable is defined.
71 0 : pub fn debug_location(&self) -> DebugLocation {
72 0 : DebugLocation::from_ffi(self.ptr.debug_location())
73 0 : }
74 :
75 : /// Return the type of this variable
76 0 : pub fn get_type(&self) -> Option<Type> {
77 0 : into_optional(self.ptr.get_type())
78 0 : }
79 :
80 : /// The scope in which this variable is defined
81 0 : pub fn scope(&self) -> Option<Scope> {
82 0 : into_optional(self.ptr.scope())
83 0 : }
84 : }
85 :
86 0 : declare_fwd_iterator!(
87 0 : Variables,
88 0 : Variable<'a>,
89 0 : ffi::DWARF_Variable,
90 0 : ffi::DWARF_Function,
91 0 : ffi::DWARF_Function_it_variables
92 0 : );
93 :
94 0 : declare_fwd_iterator!(
95 0 : CompilationUnitVariables,
96 0 : Variable<'a>,
97 0 : ffi::DWARF_Variable,
98 0 : ffi::DWARF_CompilationUnit,
99 0 : ffi::DWARF_CompilationUnit_it_variables
100 0 : );
|