LCOV - code coverage report
Current view: top level - src/dwarf - compilation_unit.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 0.0 % 98 0
Test Date: 2024-11-30:00:00:00 Functions: 0.0 % 26 0

            Line data    Source code
       1              : //! This module wraps DWARF compilation unit
       2              : 
       3              : use lief_ffi as ffi;
       4              : 
       5              : use std::marker::PhantomData;
       6              : 
       7              : use crate::common::{into_optional, into_ranges, FromFFI};
       8              : use crate::declare_fwd_iterator;
       9              : use crate::Range;
      10              : 
      11              : use super::{Function, Variable};
      12              : use crate::dwarf::variable::CompilationUnitVariables;
      13              : use crate::dwarf::function::Functions;
      14              : use crate::dwarf::types::Types;
      15              : 
      16              : /// A DWARF compilation unit
      17              : pub struct CompilationUnit<'a> {
      18              :     ptr: cxx::UniquePtr<ffi::DWARF_CompilationUnit>,
      19              :     _owner: PhantomData<&'a ()>,
      20              : }
      21              : 
      22              : 
      23              : #[allow(non_camel_case_types)]
      24            0 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
      25              : pub enum Langs {
      26              :     C,
      27              :     CPP,
      28              :     RUST,
      29              :     DART,
      30              :     MODULA,
      31              :     FORTRAN,
      32              :     SWIFT,
      33              :     D,
      34              :     JAVA,
      35              :     COBOL,
      36              :     UNKNOWN(u32),
      37              : }
      38              : 
      39              : impl From<u32> for Langs {
      40            0 :     fn from(value: u32) -> Self {
      41            0 :         match value {
      42            0 :             0x00000001 => Langs::C,
      43            0 :             0x00000002 => Langs::CPP,
      44            0 :             0x00000003 => Langs::RUST,
      45            0 :             0x00000004 => Langs::DART,
      46            0 :             0x00000005 => Langs::MODULA,
      47            0 :             0x00000006 => Langs::FORTRAN,
      48            0 :             0x00000007 => Langs::SWIFT,
      49            0 :             0x00000008 => Langs::D,
      50            0 :             0x00000009 => Langs::JAVA,
      51            0 :             0x0000000A => Langs::COBOL,
      52            0 :             _ => Langs::UNKNOWN(value),
      53              : 
      54              :         }
      55            0 :     }
      56              : }
      57              : impl From<Langs> for u32 {
      58            0 :     fn from(value: Langs) -> u32 {
      59            0 :         match value {
      60            0 :             Langs::C => 0x00000001,
      61            0 :             Langs::CPP => 0x00000002,
      62            0 :             Langs::RUST => 0x00000003,
      63            0 :             Langs::DART => 0x00000004,
      64            0 :             Langs::MODULA => 0x00000005,
      65            0 :             Langs::FORTRAN => 0x00000006,
      66            0 :             Langs::SWIFT => 0x00000007,
      67            0 :             Langs::D => 0x00000008,
      68            0 :             Langs::JAVA => 0x00000009,
      69            0 :             Langs::COBOL => 0x0000000A,
      70            0 :             Langs::UNKNOWN(_) => 0,
      71              :         }
      72            0 :     }
      73              : }
      74              : 
      75              : /// Languages supported by the DWARF (v5) format.
      76              : /// See: <https://dwarfstd.org/languages.html>
      77              : ///
      78              : /// Some languages (like C++11, C++17, ..) have a version (11, 17, ...) which
      79              : /// is stored in a dedicated attribute: #version
      80            0 : #[derive(Debug)]
      81              : pub struct Language {
      82              :     /// The language itself
      83              :     pub lang: Langs,
      84              : 
      85              :     /// Version of the language (e.g. 17 for C++17)
      86              :     pub version: u32,
      87              : }
      88              : 
      89              : impl FromFFI<ffi::DWARF_CompilationUnit_Language> for Language {
      90            0 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::DWARF_CompilationUnit_Language>) -> Self {
      91            0 :         let lang_ref = ptr.as_ref().unwrap();
      92            0 :         Self {
      93            0 :             lang: Langs::from(lang_ref.lang),
      94            0 :             version: lang_ref.version,
      95            0 :         }
      96            0 :     }
      97              : }
      98              : 
      99              : impl FromFFI<ffi::DWARF_CompilationUnit> for CompilationUnit<'_> {
     100            0 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::DWARF_CompilationUnit>) -> Self {
     101            0 :         Self {
     102            0 :             ptr,
     103            0 :             _owner: PhantomData,
     104            0 :         }
     105            0 :     }
     106              : }
     107              : 
     108              : impl CompilationUnit<'_> {
     109              :     /// Name of the file associated with this compilation unit (e.g. `test.cpp`)
     110              :     /// Return an **empty** string if the name is not found or can't be resolved
     111              :     ///
     112              :     /// This value matches the `DW_AT_name` attribute
     113            0 :     pub fn name(&self) -> String {
     114            0 :         self.ptr.name().to_string()
     115            0 :     }
     116              : 
     117              :     /// Information about the program (or library) that generated this compilation
     118              :     /// unit. For instance, it can output: `Debian clang version 17.0.6`.
     119              :     ///
     120              :     /// It returns an **empty** string if the producer is not present or can't be
     121              :     /// resolved
     122              :     ///
     123              :     /// This value matches the `DW_AT_producer` attribute
     124            0 :     pub fn producer(&self) -> String {
     125            0 :         self.ptr.producer().to_string()
     126            0 :     }
     127              : 
     128              :     /// Return the path to the directory in which the compilation took place for
     129              :     /// compiling this compilation unit (e.g. `/workdir/build`)
     130              :     ///
     131              :     /// It returns an **empty** string if the entry is not present or can't be
     132              :     /// resolved
     133              :     ///
     134              :     /// This value matches the `DW_AT_comp_dir` attributeducer` attribute
     135            0 :     pub fn compilation_dir(&self) -> String {
     136            0 :         self.ptr.compilation_dir().to_string()
     137            0 :     }
     138              : 
     139              :     /// Original Language of this compilation unit.
     140              :     ///
     141              :     /// This value matches the `DW_AT_language` attribute
     142            0 :     pub fn language(&self) -> Language {
     143            0 :         Language::from_ffi(self.ptr.language())
     144            0 :     }
     145              : 
     146              :     /// Return the lowest virtual address owned by this compilation unit.
     147            0 :     pub fn low_address(&self) -> u64 {
     148            0 :         self.ptr.low_address()
     149            0 :     }
     150              : 
     151              :     /// Return the highest virtual address owned by this compilation unit.
     152            0 :     pub fn high_address(&self) -> u64 {
     153            0 :         self.ptr.high_address()
     154            0 :     }
     155              : 
     156              :     /// Return the size of the compilation unit according to its range of address.
     157              :     ///
     158              :     /// If the compilation is fragmented (i.e. there are some address ranges
     159              :     /// between the lowest address and the highest that are not owned by the CU),
     160              :     /// then it returns the sum of **all** the address ranges owned by this CU.
     161              :     ///
     162              :     /// If the compilation unit is **not** fragmented, then is basically returns
     163              :     /// `high_address - low_address`.
     164            0 :     pub fn size(&self) -> u64 {
     165            0 :         self.ptr.size()
     166            0 :     }
     167              : 
     168              :     /// Return a list of address ranges owned by this compilation unit.
     169              :     ///
     170              :     /// If the compilation unit owns a contiguous range, it should return
     171              :     /// **a single** range.
     172            0 :     pub fn ranges(&self) -> Vec<Range> {
     173            0 :         into_ranges(self.ptr.ranges())
     174            0 :     }
     175              : 
     176              :     /// Return an iterator over the functions [`Function`] implemented in this compilation
     177              :     /// unit.
     178              :     ///
     179              :     /// Note that this iterator only iterates over the functions that have a
     180              :     /// **concrete** implementation in the compilation unit.
     181              :     ///
     182              :     /// For instance with this code:
     183              :     ///
     184              :     /// ```cpp
     185              :     /// inline const char* get_secret_env() {
     186              :     ///   return getenv("MY_SECRET_ENV");
     187              :     /// }
     188              :     ///
     189              :     /// int main() {
     190              :     ///   printf("%s", get_secret_env());
     191              :     ///   return 0;
     192              :     /// }
     193              :     /// ```
     194              :     ///
     195              :     /// The iterator will only return **one function** for `main` since
     196              :     /// `get_secret_env` is inlined and thus, its implementation is located in
     197              :     /// `main`.
     198            0 :     pub fn functions(&self) -> Functions {
     199            0 :         Functions::new(self.ptr.functions())
     200            0 :     }
     201              : 
     202              :     /// Return an iterator over the functions **imported** in this compilation
     203              :     /// unit **but not** implemented.
     204              :     ///
     205              :     /// For instance with this code:
     206              :     ///
     207              :     /// ```cpp
     208              :     /// #include <cstdio>
     209              :     /// int main() {
     210              :     ///   printf("Hello\n");
     211              :     ///   return 0;
     212              :     /// }
     213              :     /// ```
     214              :     ///
     215              :     /// `printf` is imported from the standard libc so the function is returned by
     216              :     /// the iterator. On the other hand, `main()` is implemented in this
     217              :     /// compilation unit so it is not returned by [`CompilationUnit::imported_functions`] but
     218              :     /// [`CompilationUnit::functions`].
     219            0 :     pub fn imported_functions(&self) -> Functions {
     220            0 :         Functions::new(self.ptr.imported_functions())
     221            0 :     }
     222              : 
     223              :     /// Return an iterator over the variables defined in the **global** scope
     224              :     /// of this compilation unit:
     225              :     ///
     226              :     /// ```cpp
     227              :     /// static int A = 1; // Returned by the iterator
     228              :     /// static const char* B = "Hello"; // Returned by the iterator
     229              :     ///
     230              :     /// int get() {
     231              :     ///   static int C = 2; // Returned by the iterator
     232              :     ///   return C;
     233              :     /// }
     234              :     /// ```
     235            0 :     pub fn variables(&self) -> CompilationUnitVariables {
     236            0 :         CompilationUnitVariables::new(self.ptr.variables())
     237            0 :     }
     238              : 
     239            0 :     pub fn types(&self) -> Types {
     240            0 :         Types::new(self.ptr.types())
     241            0 :     }
     242              : 
     243              :     /// Try to find the function whose name is given in parameter.
     244              :     ///
     245              :     /// The provided name can be demangled.
     246            0 :     pub fn function_by_name(&self, name: &str) -> Option<Function> {
     247            0 :         into_optional(self.ptr.function_by_name(name))
     248            0 :     }
     249              : 
     250              :     /// Try to find the function at the given address
     251            0 :     pub fn function_by_addr(&self, address: u64) -> Option<Function> {
     252            0 :         into_optional(self.ptr.function_by_address(address))
     253            0 :     }
     254              : 
     255              :     /// Try to find the variable whose name is given in parameter.
     256            0 :     pub fn variable_by_name(&self, name: &str) -> Option<Variable> {
     257            0 :         into_optional(self.ptr.variable_by_name(name))
     258            0 :     }
     259              : 
     260              :     /// Try to find the variable at the given address
     261            0 :     pub fn variable_by_addr(&self, address: u64) -> Option<Variable> {
     262            0 :         into_optional(self.ptr.variable_by_address(address))
     263            0 :     }
     264              : }
     265              : 
     266            0 : declare_fwd_iterator!(
     267            0 :     CompilationUnits,
     268            0 :     CompilationUnit<'a>,
     269            0 :     ffi::DWARF_CompilationUnit,
     270            0 :     ffi::DWARF_DebugInfo,
     271            0 :     ffi::DWARF_DebugInfo_it_compilation_units
     272            0 : );
        

Generated by: LCOV version 2.1-1