LCOV - code coverage report
Current view: top level - src/assembly/aarch64/operands - memory.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 0.0 % 45 0
Test Date: 2026-04-12:00:00:00 Functions: 0.0 % 15 0

            Line data    Source code
       1              : use lief_ffi as ffi;
       2              : 
       3              : use crate::{assembly::aarch64::registers::Reg, common::FromFFI};
       4              : 
       5              : use super::Operand;
       6              : 
       7              : /// This structure represents a memory operand.
       8              : ///
       9              : /// ```text
      10              : /// ldr     x0, [x1, x2, lsl #3]
      11              : ///              |   |    |
      12              : /// +------------+   |    +--------+
      13              : /// |                |             |
      14              : /// v                v             v
      15              : /// Base            Reg Offset    Shift
      16              : ///
      17              : /// ```
      18              : pub struct Memory {
      19              :     ptr: cxx::UniquePtr<ffi::asm_aarch64_operands_Memory>,
      20              : }
      21              : 
      22              : impl FromFFI<ffi::asm_aarch64_operands_Memory> for Memory {
      23            0 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::asm_aarch64_operands_Memory>) -> Self {
      24            0 :         Self { ptr }
      25            0 :     }
      26              : }
      27              : 
      28              : impl Operand for Memory {
      29              :     #[doc(hidden)]
      30            0 :     fn as_generic(&self) -> &ffi::asm_aarch64_Operand {
      31            0 :         self.ptr.as_ref().unwrap().as_ref()
      32            0 :     }
      33              : }
      34              : 
      35              : /// Wraps a memory offset as an integer offset or as a register offset
      36            0 : #[derive(Debug)]
      37              : pub enum Offset {
      38              :     /// Register offset
      39              :     Reg(Reg),
      40              :     /// Integer offset
      41              :     Displacement(i64),
      42              : }
      43              : 
      44              : #[allow(non_camel_case_types)]
      45            0 : #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
      46              : pub enum Shift {
      47              :     Unknown,
      48              :     Lsl,
      49              :     Uxtx,
      50              :     Uxtw,
      51              :     Sxtx,
      52              :     Sxtw,
      53              : }
      54              : 
      55              : impl From<i32> for Shift {
      56            0 :     fn from(value: i32) -> Self {
      57            0 :         match value {
      58            0 :             0 => Shift::Unknown,
      59            0 :             1 => Shift::Lsl,
      60            0 :             2 => Shift::Uxtx,
      61            0 :             3 => Shift::Uxtw,
      62            0 :             4 => Shift::Sxtx,
      63            0 :             5 => Shift::Sxtw,
      64            0 :             _ => Shift::Unknown,
      65              :         }
      66            0 :     }
      67              : }
      68              : 
      69              : /// This structure holds shift info (type + value)
      70            0 : #[derive(Debug)]
      71              : pub struct ShiftInfo {
      72              :     pub shift_type: Shift,
      73              :     pub value: i8,
      74              : }
      75              : 
      76              : impl ShiftInfo {
      77            0 :     pub fn new(shift: Shift, value: i8) -> Self {
      78            0 :         Self {
      79            0 :             shift_type: shift,
      80            0 :             value,
      81            0 :         }
      82            0 :     }
      83              : }
      84              : 
      85              : impl Memory {
      86              :     /// The base register.
      87              :     ///
      88              :     /// For `str x3, [x8, #8]` it would return `x8`
      89            0 :     pub fn base(&self) -> Reg {
      90            0 :         Reg::from(self.ptr.base())
      91            0 :     }
      92              : 
      93              :     /// The addressing offset.
      94              :     ///
      95              :     /// It can be either:
      96              :     /// - A register (e.g. `ldr x0, [x1, x3]`)
      97              :     /// - An offset (e.g. `ldr x0, [x1, #8]`)
      98            0 :     pub fn offset(&self) -> Option<Offset> {
      99            0 :         let ffi_offset = self.ptr.offset();
     100            0 :         match ffi_offset.enum_type {
     101            0 :             1 => Some(Offset::Reg(Reg::from(ffi_offset.value))),
     102            0 :             2 => Some(Offset::Displacement(ffi_offset.value as i64)),
     103            0 :             _ => None,
     104              :         }
     105            0 :     }
     106              : 
     107              :     /// Shift information.
     108              :     ///
     109              :     /// For instance, for `ldr x1, [x2, x3, lsl #3]` it would
     110              :     /// return a [`Shift::Lsl`] with a [`ShiftInfo::value`] set to `3`
     111            0 :     pub fn shift(&self) -> Option<ShiftInfo> {
     112            0 :         let ffi_shift = self.ptr.shift();
     113            0 :         if ffi_shift.value == 0 {
     114            0 :             return None;
     115            0 :         }
     116            0 :         Some(ShiftInfo::new(
     117            0 :             Shift::from(ffi_shift.enum_type),
     118            0 :             ffi_shift.value,
     119            0 :         ))
     120            0 :     }
     121              : }
        

Generated by: LCOV version 2.1-1