1+ from symbols import Syms , RAM_BASE
2+
3+ class ASMInstruction :
4+ def __init__ (self , line : str , sym : Syms ) -> None :
5+ self .failed_decoding = False
6+ try :
7+ self .return_address = int ("0x" + line [0 ][:8 ], 0 ) + 8
8+ except Exception :
9+ self .failed_decoding = True
10+ return
11+ self .sym = sym
12+ self .instruction = line [2 ]
13+ self .destination = line [3 ]
14+ switch = {
15+ "jal" : self .case_jal ,
16+ "jalr" : self .case_jalr ,
17+ "jr" : self .case_jr
18+ }
19+ self .symbol = None
20+ self .has_returned = False
21+ self .returning = False
22+ self .func_call = False
23+ if self .instruction in switch :
24+ switch [self .instruction ]()
25+ self .func_call = True
26+
27+ def case_jal (self ):
28+ self .destination = int (self .destination [:10 ], 0 )
29+ self .symbol = self .sym .get_symbol (self .destination )
30+ if self .symbol is None :
31+ name = str ()
32+ if self .destination < RAM_BASE :
33+ name = "0" + hex (self .destination + RAM_BASE )[3 :]
34+ else :
35+ name = hex (self .destination )[2 :]
36+ self .symbol = "FUN_" + name
37+
38+ def case_jalr (self ):
39+ self .destination = int ("0x" + self .destination [4 :12 ], 0 )
40+ self .symbol = self .sym .get_symbol (self .destination )
41+ if self .symbol is None :
42+ name = str ()
43+ if self .destination < RAM_BASE :
44+ name = "0" + hex (self .destination + RAM_BASE )[3 :]
45+ else :
46+ name = hex (self .destination )[2 :]
47+ self .symbol = "FUN_" + name
48+
49+ def case_jr (self ):
50+ self .destination = int ("0x" + self .destination [4 :12 ], 0 )
51+ self .returning = True
52+
53+ class ASMAnalyzer :
54+ def __init__ (self , sym : Syms , output : str , space_size : int ) -> None :
55+ self .sym = sym
56+ self .output = output
57+ self .space_size = space_size
58+
59+ def analyze_log (self , log : str , start_label : str ) -> None :
60+ output = open (self .output , "w" )
61+ buffer = start_label + "()\n "
62+ curr_spacing = self .space_size
63+ possible_func_calls = []
64+ with open (log , "r" ) as file :
65+ for line in file :
66+ line = line .split ()
67+ if len (line ) < 4 :
68+ continue
69+ instruction = ASMInstruction (line , self .sym )
70+ if instruction .failed_decoding :
71+ continue
72+ if instruction .returning :
73+ for i in range (len (possible_func_calls ) - 1 , - 1 , - 1 ):
74+ func_call = possible_func_calls [i ][0 ]
75+ if (not func_call .has_returned ) and (func_call .return_address == instruction .destination ):
76+ possible_func_calls [i ][0 ].has_returned = True
77+ curr_spacing = possible_func_calls [i ][1 ]
78+ elif instruction .func_call :
79+ possible_func_calls .append ([instruction , curr_spacing ])
80+ curr_spacing += self .space_size
81+
82+ for pfc in possible_func_calls :
83+ func_call = pfc [0 ]
84+ if func_call .has_returned :
85+ spacing = pfc [1 ]
86+ buffer += (" " * spacing ) + func_call .symbol + "()\n "
87+
88+ output .write (buffer )
89+ output .close ()
0 commit comments