2929 - Thunks are unhandled
3030"""
3131
32+
3233@functools .lru_cache (maxsize = 64 )
3334def get_param_sites (mlil : MediumLevelILFunction ) -> Mapping [LowLevelILInstruction , List [Tuple [MediumLevelILInstruction , int ]]]:
3435 """
@@ -123,6 +124,63 @@ def get_llil_arg(llil: LowLevelILInstruction) -> Iterator[Tuple[str, MediumLevel
123124 return
124125
125126
127+ def apply_to_lines (lines , get_instr , renderer ):
128+ # So we don't process lines twice since we're iterating over a list as we modify it
129+ skip_lines = []
130+
131+ # Tailcalls that don't return incorrectly mark the { Does not return } line as a call
132+ ignore_calls = set ()
133+
134+ for i , line in enumerate (lines ):
135+ if len (line .tokens ) == 0 :
136+ continue
137+ if i in skip_lines :
138+ continue
139+
140+ llil_instr = get_instr (line )
141+ if llil_instr is not None :
142+ new_lines = []
143+ for (arg , call ) in get_llil_arg (llil_instr ):
144+ if call .operation == MediumLevelILOperation .MLIL_TAILCALL_SSA :
145+ comment = f"Argument '{ arg } ' for tailcall at { call .address :#x} "
146+ else :
147+ comment = f"Argument '{ arg } ' for call at { call .address :#x} "
148+ renderer .wrap_comment (new_lines , line , comment , False , " " , "" )
149+ for j , token in enumerate (line .tokens ):
150+ if token .type == InstructionTextTokenType .AddressSeparatorToken :
151+ line .tokens = line .tokens [:j ]
152+ break
153+
154+ # Annotate calls too so we can see them easily next to their args
155+ if llil_instr .address == line .address and llil_instr .address not in ignore_calls :
156+ if llil_instr .operation in [
157+ LowLevelILOperation .LLIL_CALL ,
158+ LowLevelILOperation .LLIL_CALL_SSA ,
159+ LowLevelILOperation .LLIL_TAILCALL ,
160+ LowLevelILOperation .LLIL_TAILCALL_SSA
161+ ]:
162+ ignore_calls .add (llil_instr .address )
163+ if llil_instr .operation in [
164+ LowLevelILOperation .LLIL_TAILCALL ,
165+ LowLevelILOperation .LLIL_TAILCALL_SSA
166+ ]:
167+ comment = f"Tailcall at { llil_instr .address :#x} "
168+ else :
169+ comment = f"Call at { llil_instr .address :#x} "
170+ renderer .wrap_comment (new_lines , line , comment , False , " " , "" )
171+ for j , token in enumerate (line .tokens ):
172+ if token .type == InstructionTextTokenType .AddressSeparatorToken :
173+ line .tokens = line .tokens [:j ]
174+ break
175+
176+ # If any of our lines changed, swap out the existing lines with the new ones
177+ if len (new_lines ) > 0 :
178+ lines .pop (i )
179+ for j , new_line in enumerate (new_lines ):
180+ lines .insert (i + j , new_line )
181+ skip_lines .append (i + j )
182+
183+
126184class ArgumentsRenderLayer (RenderLayer ):
127185 name = "Annotate Call Parameters"
128186
@@ -132,116 +190,15 @@ def apply_to_disassembly_block(
132190 lines : List ['DisassemblyTextLine' ]
133191 ):
134192 renderer = DisassemblyTextRenderer (block .function )
135-
136- # So we don't process lines twice since we're iterating over a list as we modify it
137- skip_lines = []
138-
139- # Tailcalls that don't return incorrectly mark the { Does not return } line as a call
140- ignore_calls = set ()
141-
142- for i , line in enumerate (lines ):
143- if len (line .tokens ) == 0 :
144- continue
145- if i in skip_lines :
146- continue
147- llil_instr = block .function .get_llil_at (line .address )
148- if llil_instr is not None :
149- new_lines = []
150- for (arg , call ) in get_llil_arg (llil_instr ):
151- if call .operation == MediumLevelILOperation .MLIL_TAILCALL_SSA :
152- comment = f"Argument '{ arg } ' for tailcall at { call .address :#x} "
153- else :
154- comment = f"Argument '{ arg } ' for call at { call .address :#x} "
155- renderer .wrap_comment (new_lines , line , comment , False , " " , "" )
156- for j , token in enumerate (line .tokens ):
157- if token .type == InstructionTextTokenType .AddressSeparatorToken :
158- line .tokens = line .tokens [:j ]
159- break
160-
161- if llil_instr .address == line .address and llil_instr .address not in ignore_calls :
162- if llil_instr .operation in [
163- LowLevelILOperation .LLIL_CALL ,
164- LowLevelILOperation .LLIL_CALL_SSA ,
165- LowLevelILOperation .LLIL_TAILCALL ,
166- LowLevelILOperation .LLIL_TAILCALL_SSA
167- ]:
168- ignore_calls .add (llil_instr .address )
169- if llil_instr .operation in [
170- LowLevelILOperation .LLIL_TAILCALL ,
171- LowLevelILOperation .LLIL_TAILCALL_SSA
172- ]:
173- comment = f"Tailcall at { llil_instr .address :#x} "
174- else :
175- comment = f"Call at { llil_instr .address :#x} "
176- renderer .wrap_comment (new_lines , line , comment , False , " " , "" )
177- for j , token in enumerate (line .tokens ):
178- if token .type == InstructionTextTokenType .AddressSeparatorToken :
179- line .tokens = line .tokens [:j ]
180- break
181-
182- if len (new_lines ) > 0 :
183- lines .pop (i )
184- for j , new_line in enumerate (new_lines ):
185- lines .insert (i + j , new_line )
186- skip_lines .append (i + j )
193+ apply_to_lines (lines , lambda line : block .function .get_llil_at (line .address ), renderer )
187194
188195 def apply_to_low_level_il_block (
189196 self ,
190197 block : BasicBlock ,
191198 lines : List ['DisassemblyTextLine' ]
192199 ):
193200 renderer = DisassemblyTextRenderer (block .function )
194-
195- # So we don't process lines twice since we're iterating over a list as we modify it
196- skip_lines = []
197-
198- # Tailcalls that don't return incorrectly mark the { Does not return } line as a call
199- ignore_calls = set ()
200-
201- for i , line in enumerate (lines ):
202- if len (line .tokens ) == 0 :
203- continue
204- if i in skip_lines :
205- continue
206- if line .il_instruction is not None :
207- new_lines = []
208- for (arg , call ) in get_llil_arg (line .il_instruction ):
209- if call .operation == MediumLevelILOperation .MLIL_TAILCALL_SSA :
210- comment = f"Argument '{ arg } ' for tailcall at { call .address :#x} "
211- else :
212- comment = f"Argument '{ arg } ' for call at { call .address :#x} "
213- renderer .wrap_comment (new_lines , line , comment , False , " " , "" )
214- for j , token in enumerate (line .tokens ):
215- if token .type == InstructionTextTokenType .AddressSeparatorToken :
216- line .tokens = line .tokens [:j ]
217- break
218-
219- if line .il_instruction .address == line .address and line .il_instruction .address not in ignore_calls :
220- if line .il_instruction .operation in [
221- LowLevelILOperation .LLIL_CALL ,
222- LowLevelILOperation .LLIL_CALL_SSA ,
223- LowLevelILOperation .LLIL_TAILCALL ,
224- LowLevelILOperation .LLIL_TAILCALL_SSA
225- ]:
226- ignore_calls .add (line .il_instruction .address )
227- if line .il_instruction .operation in [
228- LowLevelILOperation .LLIL_TAILCALL ,
229- LowLevelILOperation .LLIL_TAILCALL_SSA
230- ]:
231- comment = f"Tailcall at { line .il_instruction .address :#x} "
232- else :
233- comment = f"Call at { line .il_instruction .address :#x} "
234- renderer .wrap_comment (new_lines , line , comment , False , " " , "" )
235- for j , token in enumerate (line .tokens ):
236- if token .type == InstructionTextTokenType .AddressSeparatorToken :
237- line .tokens = line .tokens [:j ]
238- break
239-
240- if len (new_lines ) > 0 :
241- lines .pop (i )
242- for j , new_line in enumerate (new_lines ):
243- lines .insert (i + j , new_line )
244- skip_lines .append (i + j )
201+ apply_to_lines (lines , lambda line : line .il_instruction , renderer )
245202
246203
247204ArgumentsRenderLayer .register ()
0 commit comments