Skip to content

Commit a1ff511

Browse files
committed
Add debugging function for visualizing dirty pages in a specific layout
Signed-off-by: Ludvig Liljenberg <[email protected]>
1 parent cb6e57e commit a1ff511

File tree

2 files changed

+105
-2
lines changed

2 files changed

+105
-2
lines changed

src/hyperlight_host/src/mem/bitmap.rs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ limitations under the License.
1515
*/
1616

1717
use hyperlight_common::mem::{PAGE_SIZE_USIZE, PAGES_IN_BLOCK};
18+
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
1819

20+
use super::layout::SandboxMemoryLayout;
1921
use crate::{Result, log_then_return};
2022

2123
// Contains various helper functions for dealing with bitmaps.
@@ -93,6 +95,107 @@ impl Iterator for SetBitIndices<'_> {
9395
}
9496
}
9597

98+
// Unused but useful for debugging
99+
// Prints the dirty bitmap in a human-readable format, coloring each page according to its region
100+
// NOTE: Might need to be updated if the memory layout changes
101+
#[allow(dead_code)]
102+
pub(crate) fn print_dirty_bitmap(bitmap: &[u64], layout: &SandboxMemoryLayout) {
103+
let mut stdout = StandardStream::stdout(ColorChoice::Auto);
104+
105+
// Helper function to determine which memory region a page belongs to
106+
fn get_region_info(page_index: usize, layout: &SandboxMemoryLayout) -> (&'static str, Color) {
107+
let page_offset = page_index * PAGE_SIZE_USIZE;
108+
109+
// Check each memory region in order, using available methods and approximations
110+
if page_offset >= layout.init_data_offset {
111+
("INIT_DATA", Color::Ansi256(129)) // Purple
112+
} else if page_offset >= layout.get_top_of_user_stack_offset() {
113+
("STACK", Color::Ansi256(208)) // Orange
114+
} else if page_offset >= layout.get_guard_page_offset() {
115+
("GUARD_PAGE", Color::White)
116+
} else if page_offset >= layout.guest_heap_buffer_offset {
117+
("HEAP", Color::Red)
118+
} else if page_offset >= layout.output_data_buffer_offset {
119+
("OUTPUT_DATA", Color::Green)
120+
} else if page_offset >= layout.input_data_buffer_offset {
121+
("INPUT_DATA", Color::Blue)
122+
} else if page_offset >= layout.host_function_definitions_buffer_offset {
123+
("HOST_FUNC_DEF", Color::Cyan)
124+
} else if page_offset >= layout.peb_address {
125+
("PEB", Color::Magenta)
126+
} else if page_offset >= layout.get_guest_code_offset() {
127+
("CODE", Color::Yellow)
128+
} else {
129+
// Everything up to and including guest code should be PAGE_TABLES
130+
("PAGE_TABLES", Color::Ansi256(14)) // Bright cyan
131+
}
132+
}
133+
134+
let mut num_dirty_pages = 0;
135+
for &block in bitmap.iter() {
136+
num_dirty_pages += block.count_ones() as usize;
137+
}
138+
139+
for (i, &block) in bitmap.iter().enumerate() {
140+
if block != 0 {
141+
print!("Block {:3}: ", i);
142+
143+
// Print each bit in the block with appropriate color
144+
for bit_pos in 0..64 {
145+
let bit_mask = 1u64 << bit_pos;
146+
let page_index = i * 64 + bit_pos;
147+
let (_region_name, color) = get_region_info(page_index, layout);
148+
149+
let mut color_spec = ColorSpec::new();
150+
color_spec.set_fg(Some(color));
151+
152+
if block & bit_mask != 0 {
153+
// Make 1s bold with dark background to stand out from 0s
154+
color_spec.set_bold(true).set_bg(Some(Color::Black));
155+
let _ = stdout.set_color(&color_spec);
156+
print!("1");
157+
} else {
158+
// 0s are colored but not bold, no background
159+
let _ = stdout.set_color(&color_spec);
160+
print!("0");
161+
}
162+
let _ = stdout.reset();
163+
}
164+
165+
// Print a legend for this block showing which regions are represented
166+
let mut regions_in_block = std::collections::HashMap::new();
167+
for bit_pos in 0..64 {
168+
let bit_mask = 1u64 << bit_pos;
169+
if block & bit_mask != 0 {
170+
let page_index = i * 64 + bit_pos;
171+
let (region_name, color) = get_region_info(page_index, layout);
172+
regions_in_block.insert(region_name, color);
173+
}
174+
}
175+
176+
if !regions_in_block.is_empty() {
177+
print!(" [");
178+
let mut sorted_regions: Vec<_> = regions_in_block.iter().collect();
179+
sorted_regions.sort_by_key(|(name, _)| *name);
180+
for (i, (region_name, color)) in sorted_regions.iter().enumerate() {
181+
if i > 0 {
182+
print!(", ");
183+
}
184+
let mut color_spec = ColorSpec::new();
185+
color_spec.set_fg(Some(**color)).set_bold(true);
186+
let _ = stdout.set_color(&color_spec);
187+
print!("{}", region_name);
188+
let _ = stdout.reset();
189+
}
190+
print!("]");
191+
}
192+
println!();
193+
}
194+
}
195+
// Print the total number of dirty pages
196+
println!("Total dirty pages: {}", num_dirty_pages);
197+
}
198+
96199
#[cfg(test)]
97200
mod tests {
98201
use hyperlight_common::mem::PAGE_SIZE_USIZE;

src/hyperlight_host/src/mem/layout.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,10 @@ pub(crate) struct SandboxMemoryLayout {
111111
pub(crate) host_function_definitions_buffer_offset: usize,
112112
pub(super) input_data_buffer_offset: usize,
113113
pub(super) output_data_buffer_offset: usize,
114-
guest_heap_buffer_offset: usize,
114+
pub(super) guest_heap_buffer_offset: usize,
115115
guard_page_offset: usize,
116116
guest_user_stack_buffer_offset: usize, // the lowest address of the user stack
117-
init_data_offset: usize,
117+
pub(super) init_data_offset: usize,
118118

119119
// other
120120
pub(crate) peb_address: usize,

0 commit comments

Comments
 (0)