(lines, get_instr, renderer)
| 129 | |
| 130 | |
| 131 | def apply_to_lines(lines, get_instr, renderer): |
| 132 | # So we don't process lines twice since we're iterating over a list as we modify it |
| 133 | skip_lines = [] |
| 134 | |
| 135 | # Tailcalls that don't return incorrectly mark the { Does not return } line as a call |
| 136 | ignore_calls = set() |
| 137 | |
| 138 | for i, line in enumerate(lines): |
| 139 | if len(line.tokens) == 0: |
| 140 | continue |
| 141 | if i in skip_lines: |
| 142 | continue |
| 143 | |
| 144 | llil_instr = get_instr(line) |
| 145 | if llil_instr is not None: |
| 146 | new_lines = [] |
| 147 | for (arg, call) in get_llil_arg(llil_instr): |
| 148 | if call.operation == MediumLevelILOperation.MLIL_TAILCALL_SSA: |
| 149 | comment = f"Argument '{arg}' for tailcall at {call.address:#x}" |
| 150 | else: |
| 151 | comment = f"Argument '{arg}' for call at {call.address:#x}" |
| 152 | renderer.wrap_comment(new_lines, line, comment, False, " ", "") |
| 153 | for j, token in enumerate(line.tokens): |
| 154 | if token.type == InstructionTextTokenType.AddressSeparatorToken: |
| 155 | line.tokens = line.tokens[:j] |
| 156 | break |
| 157 | |
| 158 | # Annotate calls too so we can see them easily next to their args |
| 159 | if llil_instr.address == line.address and llil_instr.address not in ignore_calls: |
| 160 | if llil_instr.operation in [ |
| 161 | LowLevelILOperation.LLIL_CALL, |
| 162 | LowLevelILOperation.LLIL_CALL_SSA, |
| 163 | LowLevelILOperation.LLIL_TAILCALL, |
| 164 | LowLevelILOperation.LLIL_TAILCALL_SSA |
| 165 | ]: |
| 166 | ignore_calls.add(llil_instr.address) |
| 167 | if llil_instr.operation in [ |
| 168 | LowLevelILOperation.LLIL_TAILCALL, |
| 169 | LowLevelILOperation.LLIL_TAILCALL_SSA |
| 170 | ]: |
| 171 | comment = f"Tailcall at {llil_instr.address:#x}" |
| 172 | else: |
| 173 | comment = f"Call at {llil_instr.address:#x}" |
| 174 | # Creating comments is a bit unwieldy at the moment |
| 175 | renderer.wrap_comment(new_lines, line, comment, False, " ", "") |
| 176 | for j, token in enumerate(line.tokens): |
| 177 | if token.type == InstructionTextTokenType.AddressSeparatorToken: |
| 178 | line.tokens = line.tokens[:j] |
| 179 | break |
| 180 | |
| 181 | # If any of our lines changed, swap out the existing lines with the new ones |
| 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) |
| 187 | return lines |
| 188 |
no test coverage detected