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