aha_misc/common/
mem.rs

1//! Memory tools
2
3use libafl_bolts::{
4    AsSlice, AsSliceMut,
5    shmem::{ShMemDescription, ShMemProvider, UnixShMem, UnixShMemProvider},
6};
7use std::alloc::{Layout, alloc};
8
9unsafe extern "C" {
10    /// Compare two memory maps to detect new bits.
11    ///
12    /// # Arguments
13    /// * `virgin_map` - Pointer to the virgin (baseline) map.
14    /// * `shm_map` - Pointer to the shared memory map to compare against.
15    /// * `map_size` - Size of the map in bytes.
16    ///
17    /// # Returns
18    /// A byte value indicating if new bits were found:
19    /// - 0: No new bits found
20    /// - 1: New hitcount found
21    /// - 2: New tuples found
22    pub fn has_new_bits(virgin_map: *mut u8, shm_map: *mut u8, map_size: u32) -> u8;
23}
24
25/// Allocate memory with the specified size and alignment.
26///
27/// # Arguments
28/// * `size` - The size of the memory to allocate.
29/// * `align` - The alignment requirement for the memory.
30///
31/// # Returns
32/// A pointer to the allocated memory.
33#[inline]
34pub fn get_layout(size: usize, align: usize) -> *mut u8 {
35    let layout = Layout::from_size_align(size, align).unwrap();
36    let layout = unsafe { alloc(layout) as *mut u8 };
37    if layout.is_null() {
38        panic!("Failed to alloc layout");
39    }
40    layout
41}
42
43/// Read a value of type T from shared memory at the specified offset.
44///
45/// # Arguments
46/// * `shm` - Reference to the Unix shared memory.
47/// * `offset` - Offset in bytes from the start of the shared memory.
48///
49/// # Returns
50/// The value of type T at the specified offset.
51///
52/// # Type Parameters
53/// * `T` - The type of value to read, which must be `Copy`.
54#[inline]
55pub fn read_from_mem<T>(shm: &UnixShMem, offset: usize) -> T
56where
57    T: Copy,
58{
59    let slice = shm.as_slice();
60    unsafe { *(slice.as_ptr().add(offset) as *const T) }
61}
62
63/// Write a value of type T to shared memory at the specified offset.
64///
65/// # Arguments
66/// * `shm` - Mutable reference to the Unix shared memory.
67/// * `value` - The value to write.
68/// * `offset` - Offset in bytes from the start of the shared memory.
69///
70/// # Type Parameters
71/// * `T` - The type of value to write, which must be `Copy`.
72#[inline]
73pub fn write_to_mem<T>(shm: &mut UnixShMem, value: T, offset: usize)
74where
75    T: Copy,
76{
77    let slice = shm.as_slice_mut();
78    unsafe {
79        *(slice.as_mut_ptr().add(offset) as *mut T) = value;
80    }
81}
82
83/// Read a value of type T from a raw pointer at the specified offset.
84///
85/// # Arguments
86/// * `ptr` - Raw pointer to the memory region.
87/// * `offset` - Offset in bytes from the start of the memory region.
88///
89/// # Returns
90/// The value of type T at the specified offset.
91///
92/// # Type Parameters
93/// * `T` - The type of value to read, which must be `Copy`.
94#[inline]
95pub fn read_from_ptr<T>(ptr: *const u8, offset: usize) -> T
96where
97    T: Copy,
98{
99    unsafe { *(ptr.add(offset) as *const T) }
100}
101
102/// Write a value of type T to a raw pointer at the specified offset.
103///
104/// # Arguments
105/// * `ptr` - Raw pointer to the memory region.
106/// * `offset` - Offset in bytes from the start of the memory region.
107/// * `value` - The value to write.
108///
109/// # Type Parameters
110/// * `T` - The type of value to write, which must be `Copy`.
111#[inline]
112pub fn write_to_ptr<T>(ptr: *mut u8, offset: usize, value: T)
113where
114    T: Copy,
115{
116    unsafe {
117        *(ptr.add(offset) as *mut T) = value;
118    }
119}
120
121/// Display the memory layout of a shared memory segment.
122///
123/// # Arguments
124/// * `id_str` - The identifier string for the shared memory.
125/// * `size` - The size of the shared memory to display.
126///
127/// # Description
128/// This function opens a shared memory segment by its identifier and
129/// displays its contents in a hexadecimal and ASCII format.
130pub fn show_shm_mem_layout(id_str: &str, size: usize) {
131    let mut shm_provider = UnixShMemProvider::new().unwrap();
132    let mut shmem = shm_provider
133        .shmem_from_description(ShMemDescription::from_string_and_size(id_str, size))
134        .unwrap();
135    let shmem_ptr = shmem.as_slice_mut().as_mut_ptr();
136    show_shm_ptr_layout(shmem_ptr, size);
137}
138
139/// Display the memory layout at a specific memory pointer.
140///
141/// # Arguments
142/// * `ptr` - Pointer to the memory region to display.
143/// * `size` - The size of the memory region to display.
144///
145/// # Description
146/// This function displays the contents of a memory region in both
147/// hexadecimal and ASCII format, with 8 bytes per line. Non-printable
148/// ASCII characters are displayed as periods.
149pub fn show_shm_ptr_layout(ptr: *mut u8, size: usize) {
150    println!("shm_addr: {:p}", ptr);
151    println!("Memory contents (showing {} bytes):", size);
152
153    // Print hexadecimal values
154    for i in 0..size {
155        unsafe {
156            // Print hexadecimal value
157            print!("{:02x} ", *ptr.add(i));
158
159            // Line break every 8 bytes
160            if (i + 1) % 8 == 0 {
161                print!("  ");
162
163                // Print corresponding ASCII characters (if printable)
164                for j in (i - 7)..=i {
165                    let c = *ptr.add(j);
166                    print!("{}", if c >= 32 && c <= 126 { c as char } else { '.' });
167                }
168
169                println!();
170            }
171        }
172    }
173
174    // If the last line is not complete (less than 8 bytes), pad and print ASCII
175    if size % 8 != 0 {
176        // Calculate padding spaces needed
177        let padding = (8 - (size % 8)) * 3;
178        for _ in 0..padding {
179            print!(" ");
180        }
181
182        print!("  ");
183
184        // Print ASCII for the last line
185        let start = size - (size % 8);
186        for j in start..size {
187            unsafe {
188                let c = *ptr.add(j);
189                print!("{}", if c >= 32 && c <= 126 { c as char } else { '.' });
190            }
191        }
192
193        println!();
194    }
195}