@@ -15,7 +15,9 @@ limitations under the License.
1515*/
1616
1717use hyperlight_common:: mem:: { PAGE_SIZE_USIZE , PAGES_IN_BLOCK } ;
18+ use termcolor:: { Color , ColorChoice , ColorSpec , StandardStream , WriteColor } ;
1819
20+ use super :: layout:: SandboxMemoryLayout ;
1921use 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) ]
97200mod tests {
98201 use hyperlight_common:: mem:: PAGE_SIZE_USIZE ;
0 commit comments