@@ -135,8 +135,11 @@ def add_symbol(name, address=None, size=None):
135135 ram_start = symbols ["_srelocate" ][0 ]
136136 ram_end = symbols ["_estack" ][0 ]
137137 ram_length = ram_end - ram_start
138+ # print(ram_length, "ram length")
139+ # print(len(ram_dump) // ram_length, "snapshots")
138140 if analyze_snapshots == "all" :
139- snapshots = range (len (ram_dump ) // ram_length - 1 , - 1 , - 1 )
141+ #snapshots = range(len(ram_dump) // ram_length - 1, -1, -1)
142+ snapshots = range (4576 , - 1 , - 1 )
140143 elif analyze_snapshots == "last" :
141144 snapshots = range (len (ram_dump ) // ram_length - 1 , len (ram_dump ) // ram_length - 2 , - 1 )
142145 for snapshot_num in snapshots :
@@ -167,16 +170,16 @@ def load_pointer(address):
167170 mp_state_ctx = symbols ["mp_state_ctx" ][0 ]
168171 manual_symbol_map ["mp_state_ctx+20" ] = "mp_state_ctx.vm.last_pool"
169172 last_pool = load_pointer (mp_state_ctx + 20 ) # (gdb) p &mp_state_ctx.vm.last_pool
170- manual_symbol_map ["mp_state_ctx+88 " ] = "mp_state_ctx.vm.dict_main.map.table"
171- dict_main_table = load_pointer (mp_state_ctx + 88 ) # (gdb) p &mp_state_ctx.vm.dict_main.map.table
172- manual_symbol_map ["mp_state_ctx+68 " ] = "mp_state_ctx.vm.mp_loaded_modules_dict.map.table"
173- imports_table = load_pointer (mp_state_ctx + 68 ) # (gdb) p &mp_state_ctx.vm.mp_loaded_modules_dict.map.table
173+ manual_symbol_map ["mp_state_ctx+104 " ] = "mp_state_ctx.vm.dict_main.map.table"
174+ dict_main_table = load_pointer (mp_state_ctx + 104 ) # (gdb) p &mp_state_ctx.vm.dict_main.map.table
175+ manual_symbol_map ["mp_state_ctx+84 " ] = "mp_state_ctx.vm.mp_loaded_modules_dict.map.table"
176+ imports_table = load_pointer (mp_state_ctx + 84 ) # (gdb) p &mp_state_ctx.vm.mp_loaded_modules_dict.map.table
174177
175- manual_symbol_map ["mp_state_ctx+104 " ] = "mp_state_ctx.vm.mp_sys_path_obj.items"
176- manual_symbol_map ["mp_state_ctx+120 " ] = "mp_state_ctx.vm.mp_sys_argv_obj.items"
178+ manual_symbol_map ["mp_state_ctx+120 " ] = "mp_state_ctx.vm.mp_sys_path_obj.items"
179+ manual_symbol_map ["mp_state_ctx+136 " ] = "mp_state_ctx.vm.mp_sys_argv_obj.items"
177180
178181 for i in range (READLINE_HIST_SIZE ):
179- manual_symbol_map ["mp_state_ctx+{}" .format (128 + i * 4 )] = "mp_state_ctx.vm.readline_hist[{}]" .format (i )
182+ manual_symbol_map ["mp_state_ctx+{}" .format (144 + i * 4 )] = "mp_state_ctx.vm.readline_hist[{}]" .format (i )
180183
181184 tuple_type = symbols ["mp_type_tuple" ][0 ]
182185 type_type = symbols ["mp_type_type" ][0 ]
@@ -214,8 +217,8 @@ def load_pointer(address):
214217 pool_start = heap_start + total_byte_len - pool_length - pool_shift
215218 pool = heap [- pool_length - pool_shift :]
216219
217- total_height = 65 * 18
218- total_width = (pool_length // (64 * 16 )) * 90
220+ total_height = 128 * 18
221+ total_width = (pool_length // (128 * 16 )) * 85
219222
220223 map_element_blocks = [dict_main_table , imports_table ]
221224 string_blocks = []
@@ -255,7 +258,7 @@ def save_allocated_block(end, current_allocation):
255258 block_data [address ] = data
256259 for k in range (len (data ) // 4 ):
257260 word = struct .unpack_from ("<I" , data , offset = (k * 4 ))[0 ]
258- if word < 0x00040000 and k == 0 or address in qstr_pools :
261+ if word < len ( rom ) and k == 0 or address in qstr_pools :
259262 potential_type = word
260263 bgcolor = "gray"
261264 if address in qstr_pools :
@@ -292,11 +295,11 @@ def save_allocated_block(end, current_allocation):
292295 if potential_type == dynamic_type :
293296 if k == 0 :
294297 node .attr ["fillcolor" ] = "plum"
295- if k == 3 and 0x20000000 < word < 0x20040000 :
298+ if k == 3 and ram_start < word < ram_end :
296299 map_element_blocks .append (word )
297300
298301 if potential_type in function_types :
299- if k == 2 and 0x20000000 < word < 0x20040000 :
302+ if k == 2 and ram_start < word < ram_end :
300303 bytecode_blocks .append (word )
301304
302305
@@ -338,7 +341,12 @@ def find_qstr(qstr_index):
338341 pool_ptr = last_pool
339342 if not is_qstr (qstr_index ):
340343 return "object"
344+
345+ pool = block_data [pool_ptr ]
346+ prev , total_prev_len , alloc , length = struct .unpack_from ("<IIII" , pool )
341347 qstr_index >>= 3
348+ if qstr_index > total_prev_len + alloc :
349+ return "invalid"
342350 while pool_ptr != 0 :
343351 if pool_ptr > ram_start :
344352 if pool_ptr in block_data :
@@ -492,7 +500,10 @@ def format(obj):
492500 offset = len (data )
493501 continue
494502 offset += 2 + qstr_len + 1
495- qstrs_in_chunk += " " + data [offset - qstr_len - 1 : offset - 1 ].decode ("utf-8" )
503+ try :
504+ qstrs_in_chunk += " " + data [offset - qstr_len - 1 : offset - 1 ].decode ("utf-8" )
505+ except UnicodeDecodeError :
506+ qstrs_in_chunk += " " + "░" * qstr_len
496507 printable_qstrs = ""
497508 for i in range (len (qstrs_in_chunk )):
498509 c = qstrs_in_chunk [i ]
@@ -515,20 +526,28 @@ def format(obj):
515526 # First render the graph of objects on the heap.
516527 if draw_heap_ownership :
517528 ownership_graph .layout (prog = "dot" )
518- fn = os .path .join (output_directory , "heap_ownership{:04d}.png " .format (snapshot_num ))
529+ fn = os .path .join (output_directory , "heap_ownership{:04d}.svg " .format (snapshot_num ))
519530 print (fn )
520531 ownership_graph .draw (fn )
521532
533+ # Clear edge positioning from ownership graph layout.
534+ if draw_heap_ownership :
535+ for edge in ownership_graph .iteredges ():
536+ del edge .attr ["pos" ]
537+ else :
538+ for edge in ownership_graph .edges ():
539+ ownership_graph .delete_edge (edge )
540+
522541 # Second, render the heap layout in memory order.
523- for node in ownership_graph :
542+ for node in ownership_graph . nodes () :
524543 try :
525544 address = int (node .name )
526545 except ValueError :
527- ownership_graph .remove_node (node )
546+ ownership_graph .remove_node (node . name )
528547 continue
529548 block = (address - pool_start ) // 16
530- x = block // 64
531- y = 64 - block % 64
549+ x = block // 128
550+ y = 128 - block % 128
532551 try :
533552 height = float (node .attr ["height" ])
534553 except :
@@ -538,11 +557,6 @@ def format(obj):
538557 # print(hex(address), block, len(block_data[address]), x, y, height)
539558 node .attr ["pos" ] = "{},{}" .format (x * 80 , (y - (height - 0.25 ) * 2 ) * 18 ) # in inches
540559
541- # Clear edge positioning from ownership graph layout.
542- if draw_heap_ownership :
543- for edge in ownership_graph .iteredges ():
544- del edge .attr ["pos" ]
545-
546560 # Reformat block nodes so they are the correct size and do not have keys in them.
547561 for block in sorted (map_element_blocks ):
548562 try :
@@ -565,9 +579,9 @@ def format(obj):
565579 else :
566580 #print(" {}, {}".format(format(key), format(value)))
567581 cells .append ((key , "" ))
568- if value in block_data :
569- edge = ownership_graph .get_edge (block , value )
570- edge .attr ["tailport" ] = str (key )
582+ # if value in block_data:
583+ # edge = ownership_graph.get_edge(block, value)
584+ # edge.attr["tailport"] = str(key)
571585 rows = ""
572586 for i in range (len (cells ) // 2 ):
573587 rows += "<tr><td port=\" {}\" height=\" 18\" width=\" 40\" >{}</td><td port=\" {}\" height=\" 18\" width=\" 40\" >{}</td></tr>" .format (
@@ -586,6 +600,7 @@ def format(obj):
586600 if draw_heap_layout :
587601 fn = os .path .join (output_directory , "heap_layout{:04d}.png" .format (snapshot_num ))
588602 print (fn )
603+ #ownership_graph.write(fn+".dot")
589604 ownership_graph .draw (fn )
590605
591606if __name__ == "__main__" :
0 commit comments