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}