@@ -127,12 +127,25 @@ def is_valid_insert_point(self, addr: int) -> bool:
127
127
128
128
def is_movable_instruction (self , addr : int ) -> bool :
129
129
is_thumb = self .p .binary_analyzer .is_thumb (addr )
130
- insn = self .p .binary_analyzer .get_instr_bytes_at (addr )
131
- asm = self .p .disassembler .disassemble (insn , addr , is_thumb = is_thumb )[0 ]
130
+ insn_bytes = self .p .binary_analyzer .get_instr_bytes_at (addr )
131
+ disassembled = self .p .disassembler .disassemble (
132
+ insn_bytes , addr , is_thumb = is_thumb
133
+ )[0 ]
132
134
# if instruction use PC as a base register, it's not movable
133
- tokens = re .split (r"\s|,|\[|\]" , asm ["op_str" ])
135
+ tokens = re .split (r"\s|,|\[|\]" , disassembled ["op_str" ])
134
136
tokens = list (filter (None , tokens ))
135
137
if list (set (self .p .archinfo .pc_reg_names ) & set (tokens )):
136
138
return False
137
- # TODO: is it safe to assume that the instruction is movable if it's not using PC as a base register?
139
+ # TODO: this assumes that keystone always gives abs addr when disassembling, but it might not be true
140
+ disassembled = self .p .disassembler .to_asm_string (disassembled )
141
+ for test_addr in [addr - 0x10000 , addr + 0x10000 ]:
142
+ re_assembled = self .p .assembler .assemble (
143
+ disassembled , test_addr , is_thumb = is_thumb
144
+ )
145
+ re_disassembled = self .p .disassembler .disassemble (
146
+ re_assembled , test_addr , is_thumb = is_thumb
147
+ )[0 ]
148
+ re_disassembled = self .p .disassembler .to_asm_string (re_disassembled )
149
+ if re_disassembled != disassembled :
150
+ return False
138
151
return True
0 commit comments