@@ -56,6 +56,7 @@ let arm_aggregate_kind_to_string (k: arm_aggregate_kind_t) =
5656 ^ " target addresses"
5757 | ThumbITSequence it -> it#toString
5858 | LDMSTMSequence s -> s#toString
59+ | BXCall (_ , i2 ) -> " BXCall at " ^ i2#get_address#to_hex_string
5960
6061
6162class arm_instruction_aggregate_t
@@ -109,6 +110,11 @@ object (self)
109110 | LDMSTMSequence _ -> true
110111 | _ -> false
111112
113+ method is_bx_call =
114+ match self#kind with
115+ | BXCall _ -> true
116+ | _ -> false
117+
112118 method write_xml (_node : xml_element_int ) = ()
113119
114120 method toCHIF (_faddr : doubleword_int ) = []
@@ -173,6 +179,18 @@ let make_ldm_stm_sequence_aggregate
173179 ~anchor: (List. hd (List. tl ldmstmseq#instrs))
174180
175181
182+ let make_bx_call_aggregate
183+ (movinstr : arm_assembly_instruction_int )
184+ (bxinstr : arm_assembly_instruction_int ): arm_instruction_aggregate_int =
185+ let kind = BXCall (movinstr, bxinstr) in
186+ make_arm_instruction_aggregate
187+ ~kind
188+ ~instrs: [movinstr; bxinstr]
189+ ~entry: movinstr
190+ ~exitinstr: bxinstr
191+ ~anchor: bxinstr
192+
193+
176194let disassemble_arm_instructions
177195 (ch : pushback_stream_int ) (iaddr : doubleword_int ) (n : int ) =
178196 for _i = 1 to n do
@@ -232,6 +250,52 @@ let identify_ldmstm_sequence
232250 | _ -> None
233251
234252
253+ (* format of BX-Call (in ARM)
254+
255+ An indirect jump combined with a MOV of the PC into the LR converts
256+ into an indirect call (because PC holds the instruction-address + 8)
257+
258+ MOV LR, PC
259+ BX Rx
260+ *)
261+ let identify_bx_call
262+ (ch : pushback_stream_int )
263+ (instr : arm_assembly_instruction_int ):
264+ (arm_assembly_instruction_int * arm_assembly_instruction_int ) option =
265+ let disassemble (iaddr : doubleword_int ) =
266+ let instrpos = ch#pos in
267+ let bytes = ch#read_doubleword in
268+ let opcode =
269+ try
270+ disassemble_arm_instruction ch iaddr bytes
271+ with
272+ | _ ->
273+ let _ =
274+ chlog#add
275+ " bx-call disassemble-instruction"
276+ (LBLOCK [iaddr#toPretty]) in
277+ OpInvalid in
278+ let instrbytes = ch#sub instrpos 4 in
279+ let instr = make_arm_assembly_instruction iaddr true opcode instrbytes in
280+ begin
281+ set_arm_assembly_instruction instr;
282+ instr
283+ end in
284+ match instr#get_opcode with
285+ | Move (_, ACCAlways , dst, src, _, _)
286+ when src#is_register
287+ && dst#get_register = ARLR
288+ && src#get_register = ARPC ->
289+ begin
290+ let bxinstr = disassemble (instr#get_address#add_int 4 ) in
291+ match bxinstr#get_opcode with
292+ | BranchExchange (ACCAlways, op ) when op#is_register ->
293+ Some (instr, bxinstr)
294+ | _ -> None
295+ end
296+ | _ -> None
297+
298+
235299let identify_arm_aggregate
236300 (ch : pushback_stream_int )
237301 (instr : arm_assembly_instruction_int ):
@@ -254,4 +318,8 @@ let identify_arm_aggregate
254318 match identify_ldmstm_sequence ch instr with
255319 | Some ldmstmseq ->
256320 Some (make_ldm_stm_sequence_aggregate ldmstmseq)
257- | _ -> None
321+ | _ ->
322+ match identify_bx_call ch instr with
323+ | Some (movinstr , bxinstr ) ->
324+ Some (make_bx_call_aggregate movinstr bxinstr)
325+ | _ -> None
0 commit comments