2626 ============================================================================= *)
2727
2828(* chlib *)
29+ open CHNumerical
2930open CHPretty
3031
3132(* chutil *)
@@ -39,6 +40,7 @@ open BCHLibTypes
3940(* bchlibarm32 *)
4041open BCHARMAssemblyInstruction
4142open BCHARMAssemblyInstructions
43+ open BCHARMDisassemblyUtils
4244open BCHARMJumptable
4345open BCHARMTypes
4446open BCHDisassembleARMInstruction
@@ -61,6 +63,9 @@ let arm_aggregate_kind_to_string (k: arm_aggregate_kind_t) =
6163 | LDMSTMSequence s -> s#toString
6264 | PseudoLDRSB (i1 , _ , _ ) -> " Pseudo LDRSB at " ^ i1#get_address#to_hex_string
6365 | PseudoLDRSH (i1 , _ , _ ) -> " Pseudo LDRSH at " ^ i1#get_address#to_hex_string
66+ | ARMPredicateAssignment (inverse , op ) ->
67+ let inv = if inverse then " (inverse)" else " " in
68+ " predicate assignment to " ^ op#toString ^ inv
6469 | BXCall (_ , i2 ) -> " BXCall at " ^ i2#get_address#to_hex_string
6570
6671
@@ -130,6 +135,11 @@ object (self)
130135 | PseudoLDRSH _ -> true
131136 | _ -> false
132137
138+ method is_predicate_assign =
139+ match self#kind with
140+ | ARMPredicateAssignment _ -> true
141+ | _ -> false
142+
133143 method write_xml (_node : xml_element_int ) = ()
134144
135145 method toCHIF (_faddr : doubleword_int ) = []
@@ -232,6 +242,20 @@ let make_pseudo_ldrsb_aggregate
232242 ~anchor: asrinstr
233243
234244
245+ let make_predassign_aggregate
246+ (inverse : bool )
247+ (mov1 : arm_assembly_instruction_int )
248+ (mov2 : arm_assembly_instruction_int )
249+ (dstop : arm_operand_int ): arm_instruction_aggregate_int =
250+ let kind = ARMPredicateAssignment (inverse, dstop) in
251+ make_arm_instruction_aggregate
252+ ~kind
253+ ~instrs: [mov1; mov2]
254+ ~entry: mov1
255+ ~exitinstr: mov2
256+ ~anchor: mov2
257+
258+
235259let disassemble_arm_instructions
236260 (ch : pushback_stream_int ) (iaddr : doubleword_int ) (n : int ) =
237261 for _i = 1 to n do
@@ -393,7 +417,7 @@ let identify_pseudo_ldrsh
393417 ASR Rx, Rx, #0x18
394418 *)
395419let identify_pseudo_ldrsb
396- (ch : pushback_stream_int )
420+ (_ch : pushback_stream_int )
397421 (instr : arm_assembly_instruction_int ):
398422 (arm_assembly_instruction_int
399423 * arm_assembly_instruction_int
@@ -422,13 +446,51 @@ let identify_pseudo_ldrsb
422446 when rd2#get_register = rd#get_register -> true
423447 | _ -> false )
424448 then
425- Some (TR. tget_ok ldrbinstr_r, TR. tget_ok lslinstr_r , instr)
449+ Some (ldrbinstr, lslinstr , instr)
426450 else
427451 None
428452 | _ -> None )
429453 | _ -> None
430454
431455
456+ (* format of predicate assignment (in ARM): assigns the result of a test as a
457+ 0/1 value to a register
458+
459+ MOVNE Rx, #0
460+ MOVEQ Rx, #1
461+ *)
462+ let identify_predicate_assignment
463+ (_ch : pushback_stream_int )
464+ (instr : arm_assembly_instruction_int ):
465+ (bool
466+ * arm_assembly_instruction_int
467+ * arm_assembly_instruction_int
468+ * arm_operand_int ) option =
469+ let is_zero imm = imm#to_numerical#equal numerical_zero in
470+ let is_one imm = imm#to_numerical#equal numerical_one in
471+ let is_zero_or_one imm = (is_zero imm) || (is_one imm) in
472+ match instr#get_opcode with
473+ | Move (false , c2, rd, imm2, _, _)
474+ when imm2#is_immediate && (is_zero_or_one imm2) && (has_inverse_cc c2) ->
475+ let rdreg = rd#get_register in
476+ let addr = instr#get_address in
477+ let movinstr_r = get_arm_assembly_instruction (addr#add_int (- 4 )) in
478+ (match TR. to_option movinstr_r with
479+ | Some movinstr ->
480+ (match movinstr#get_opcode with
481+ | Move (false , c1, rd, imm1, _, _)
482+ when imm1#is_immediate
483+ && (is_zero_or_one imm1)
484+ && (rd#get_register = rdreg)
485+ && (not (imm1#to_numerical#equal imm2#to_numerical))
486+ && (has_inverse_cc c1)
487+ && ((Option. get (get_inverse_cc c1)) = c2) ->
488+ let inverse = is_zero imm2 in
489+ Some (inverse, movinstr, instr, rd)
490+ | _ -> None )
491+ | _ -> None )
492+ | _ -> None
493+
432494
433495let identify_arm_aggregate
434496 (ch : pushback_stream_int )
@@ -486,4 +548,12 @@ let identify_arm_aggregate
486548 | Some (ldrbinstr , lslinstr , asrinstr ) ->
487549 Some (make_pseudo_ldrsb_aggregate ldrbinstr lslinstr asrinstr)
488550 | _ -> None in
551+ let result =
552+ match result with
553+ | Some _ -> result
554+ | _ ->
555+ match identify_predicate_assignment ch instr with
556+ | Some (inverse , mov1 , mov2 , dstop ) ->
557+ Some (make_predassign_aggregate inverse mov1 mov2 dstop)
558+ | _ -> None in
489559 result
0 commit comments