@@ -16,7 +16,9 @@ limitations under the License.
16
16
use std:: cmp:: Ordering ;
17
17
18
18
use hyperlight_common:: mem:: { PAGE_SIZE_USIZE , PAGES_IN_BLOCK } ;
19
+ use termcolor:: { Color , ColorChoice , ColorSpec , StandardStream , WriteColor } ;
19
20
21
+ use super :: layout:: SandboxMemoryLayout ;
20
22
use crate :: { Result , log_then_return} ;
21
23
22
24
// Contains various helper functions for dealing with bitmaps.
@@ -103,6 +105,107 @@ impl Iterator for SetBitIndices<'_> {
103
105
}
104
106
}
105
107
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
+
106
209
#[ cfg( test) ]
107
210
mod tests {
108
211
use hyperlight_common:: mem:: PAGE_SIZE_USIZE ;
0 commit comments