@@ -42,7 +42,17 @@ def make_stack_variable(func_start, offset, name, size):
42
42
None , size ) == 0 :
43
43
return 1
44
44
else :
45
- return 0
45
+ raise ValueError ("failed to create stack frame member %s @ +0x%x in function @ 0x%x" % (name , offset , func_start ))
46
+
47
+ def get_stack_variable_name (func_start , offset ):
48
+ func = idaapi .get_func (func_start )
49
+ frame = idaapi .get_frame (func )
50
+ if frame is None :
51
+ raise ValueError ("couldn't get frame for function @ 0x%x" % func_start )
52
+
53
+ offset += func .frsize
54
+ member = idaapi .get_member (frame , offset )
55
+ return idaapi .get_member_name (member .id )
46
56
47
57
def is_latter_of_stack_sequential_instructions (prev_line , curr_line , op_num ):
48
58
other_op_num = 0
@@ -74,6 +84,9 @@ def operand_to_stack_variable(curr_line, op_num):
74
84
idc .OpStkvar (curr_line .ea , op_num )
75
85
return
76
86
87
+ def get_next_line (line ):
88
+ return sark .Line (line .ea + len (line .bytes ))
89
+
77
90
def create_stack_variable_from_operand (curr_line , op_num ):
78
91
try :
79
92
curr_insn = curr_line .insn
@@ -86,14 +99,19 @@ def create_stack_variable_from_operand(curr_line, op_num):
86
99
stack_offset = curr_insn .operands [op_num ].offset
87
100
this_function = sark .Function (curr_line .ea )
88
101
89
- next_line = sark . Line (curr_line . ea + len ( curr_line . bytes ) )
102
+ next_line = get_next_line (curr_line )
90
103
size = 2 if is_latter_of_stack_sequential_instructions (curr_line , next_line , op_num ) else 1
91
104
92
105
logger .info ("creating %d byte stack variable @ 0x%x based on %s && %s" % (size , stack_offset , curr_line , next_line ))
93
106
94
107
make_stack_variable (this_function .startEA , stack_offset , "var_%x" % stack_offset , size )
95
108
return
96
109
110
+ def is_sensible_instruction (insn ):
111
+ return (len (insn .operands ) == 2 and
112
+ str (insn .operands [0 ]) != '' and str (insn .operands [1 ]) != ''
113
+ )
114
+
97
115
def all_y_stack_vars_here ():
98
116
ea = idc .here ()
99
117
this_function = sark .Function (ea )
@@ -131,9 +149,43 @@ def all_y_stack_vars_here():
131
149
if not is_latter_of_stack_sequential_instructions (prev , line , 0 ): # avoid marking a stack var for the second part of a sequential load
132
150
create_stack_variable_from_operand (line , 0 )
133
151
134
- # TODO also for Y+ in operand 0
135
152
prev = line
136
153
154
+ for a1st_line in this_function .lines :
155
+ a2nd_line = get_next_line (a1st_line )
156
+ a3rd_line = get_next_line (a2nd_line )
157
+
158
+ if a2nd_line .ea > this_function .endEA or a3rd_line .ea > this_function .endEA :
159
+ continue
160
+
161
+ try :
162
+ a1st_insn = a1st_line .insn
163
+ a2nd_insn = a2nd_line .insn
164
+ a3rd_insn = a3rd_line .insn
165
+ except sark .exceptions .SarkNoInstruction :
166
+ logger .debug ("skipping %s && %s && %s" % (a1st_line , a2nd_line , a3rd_line ))
167
+ continue
168
+
169
+ if (not is_sensible_instruction (a1st_insn )) or (not is_sensible_instruction (a2nd_insn )) or (not is_sensible_instruction (a3rd_insn )):
170
+ logger .debug ("filtering %s && %s && %s" % (a1st_insn , a2nd_insn , a3rd_insn ))
171
+ continue
172
+
173
+ if (str (a1st_insn .mnem ) == 'movw' and (str (a1st_insn .operands [1 ]) == 'YL' or str (a1st_insn .operands [1 ].reg ) == 'r28' ) and
174
+ str (a1st_insn .operands [0 ]) == str (a2nd_insn .operands [0 ]) and a2nd_insn .operands [0 ].reg == avr_get_register_pairs ().get (a3rd_insn .operands [0 ].reg ) and
175
+ str (a2nd_insn .mnem ) == 'subi' and str (a3rd_insn .mnem ) == 'sbci'
176
+ ):
177
+ stack_offset = - 1 * int (a2nd_insn .operands [1 ].text , 0 )
178
+ this_function = sark .Function (a1st_line .ea )
179
+
180
+ # TODO: guess size of stack var
181
+ size = 1
182
+ logger .info ("creating %d byte stack variable @ 0x%x based on %s && %s && %s" % (size , stack_offset , a1st_line , a2nd_line , a3rd_line ))
183
+
184
+ make_stack_variable (this_function .startEA , stack_offset , "var_%x" % stack_offset , size )
185
+
186
+ name = get_stack_variable_name (this_function .startEA , stack_offset )
187
+ idc .OpAlt (a2nd_line .ea , 1 , name )
188
+
137
189
print ("some utility functions are defined:\n all_y_stack_vars_here()" )
138
190
139
191
except :
0 commit comments