@@ -46,6 +46,9 @@ open BCHLoadStoreMultipleSequence
4646open BCHThumbITSequence
4747
4848
49+ module TR = CHTraceResult
50+
51+
4952let arm_aggregate_kind_to_string (k : arm_aggregate_kind_t ) =
5053 match k with
5154 | ARMJumptable jt ->
@@ -56,6 +59,8 @@ let arm_aggregate_kind_to_string (k: arm_aggregate_kind_t) =
5659 ^ " target addresses"
5760 | ThumbITSequence it -> it#toString
5861 | LDMSTMSequence s -> s#toString
62+ | PseudoLDRSB (i1 , _ , _ ) -> " Pseudo LDRSB at " ^ i1#get_address#to_hex_string
63+ | PseudoLDRSH (i1 , _ , _ ) -> " Pseudo LDRSH at " ^ i1#get_address#to_hex_string
5964 | BXCall (_ , i2 ) -> " BXCall at " ^ i2#get_address#to_hex_string
6065
6166
@@ -115,6 +120,16 @@ object (self)
115120 | BXCall _ -> true
116121 | _ -> false
117122
123+ method is_pseudo_ldrsh =
124+ match self#kind with
125+ | PseudoLDRSH _ -> true
126+ | _ -> false
127+
128+ method is_pseudo_ldrsb =
129+ match self#kind with
130+ | PseudoLDRSH _ -> true
131+ | _ -> false
132+
118133 method write_xml (_node : xml_element_int ) = ()
119134
120135 method toCHIF (_faddr : doubleword_int ) = []
@@ -191,6 +206,32 @@ let make_bx_call_aggregate
191206 ~anchor: bxinstr
192207
193208
209+ let make_pseudo_ldrsh_aggregate
210+ (ldrhinstr : arm_assembly_instruction_int )
211+ (lslinstr : arm_assembly_instruction_int )
212+ (asrinstr : arm_assembly_instruction_int ): arm_instruction_aggregate_int =
213+ let kind = PseudoLDRSH (ldrhinstr, lslinstr, asrinstr) in
214+ make_arm_instruction_aggregate
215+ ~kind
216+ ~instrs: [ldrhinstr; lslinstr; asrinstr]
217+ ~entry: ldrhinstr
218+ ~exitinstr: asrinstr
219+ ~anchor: asrinstr
220+
221+
222+ let make_pseudo_ldrsb_aggregate
223+ (ldrbinstr : arm_assembly_instruction_int )
224+ (lslinstr : arm_assembly_instruction_int )
225+ (asrinstr : arm_assembly_instruction_int ): arm_instruction_aggregate_int =
226+ let kind = PseudoLDRSB (ldrbinstr, lslinstr, asrinstr) in
227+ make_arm_instruction_aggregate
228+ ~kind
229+ ~instrs: [ldrbinstr; lslinstr; asrinstr]
230+ ~entry: ldrbinstr
231+ ~exitinstr: asrinstr
232+ ~anchor: asrinstr
233+
234+
194235let disassemble_arm_instructions
195236 (ch : pushback_stream_int ) (iaddr : doubleword_int ) (n : int ) =
196237 for _i = 1 to n do
@@ -296,30 +337,153 @@ let identify_bx_call
296337 | _ -> None
297338
298339
340+ (* format of pseudo LDRSH (in ARM)
341+
342+ An LDRH combined with LSL 16, ASR 16 converts into (effectively) an
343+ LDRSH:
344+
345+ LDRH Rx, mem
346+ LSL Rx, Rx, #0x10
347+ ASR Rx, Rx, #0x10
348+ *)
349+ let identify_pseudo_ldrsh
350+ (ch : pushback_stream_int )
351+ (instr : arm_assembly_instruction_int ):
352+ (arm_assembly_instruction_int
353+ * arm_assembly_instruction_int
354+ * arm_assembly_instruction_int ) option =
355+ let sixteen = CHNumerical. mkNumerical 16 in
356+ match instr#get_opcode with
357+ | ArithmeticShiftRight (_, ACCAlways , rd, rs, imm, _)
358+ when imm#is_immediate
359+ && imm#to_numerical#equal sixteen
360+ && (rd#get_register = rs#get_register) ->
361+ let addr = instr#get_address in
362+ let lslinstr_r = get_arm_assembly_instruction (addr#add_int (- 4 )) in
363+ let ldrhinstr_r = get_arm_assembly_instruction (addr#add_int (- 8 )) in
364+ (match (TR. to_option lslinstr_r, TR. to_option ldrhinstr_r) with
365+ | (Some lslinstr , Some ldrhinstr ) ->
366+ if
367+ (match lslinstr#get_opcode with
368+ | LogicalShiftLeft (_, ACCAlways , rd1, rs1, imm, _)
369+ when imm#is_immediate
370+ && imm#to_numerical#equal sixteen
371+ && (rd1#get_register = rd#get_register)
372+ && (rs1#get_register = rd#get_register) -> true
373+ | _ -> false )
374+ && (match ldrhinstr#get_opcode with
375+ | LoadRegisterHalfword (ACCAlways , rd2, _, _, _, _)
376+ when rd2#get_register = rd#get_register -> true
377+ | _ -> false )
378+ then
379+ Some (TR. tget_ok ldrhinstr_r, TR. tget_ok lslinstr_r, instr)
380+ else
381+ None
382+ | _ -> None )
383+ | _ -> None
384+
385+
386+ (* format of pseudo LDRSB (in ARM)
387+
388+ An LDRH combined with LSL 16, ASR 16 converts into (effectively) an
389+ LDRSH:
390+
391+ LDRB Rx, mem
392+ LSL Rx, Rx, #0x18
393+ ASR Rx, Rx, #0x18
394+ *)
395+ let identify_pseudo_ldrsb
396+ (ch : pushback_stream_int )
397+ (instr : arm_assembly_instruction_int ):
398+ (arm_assembly_instruction_int
399+ * arm_assembly_instruction_int
400+ * arm_assembly_instruction_int ) option =
401+ let twentyfour = CHNumerical. mkNumerical 24 in
402+ match instr#get_opcode with
403+ | ArithmeticShiftRight (_, ACCAlways , rd, rs, imm, _)
404+ when imm#is_immediate
405+ && imm#to_numerical#equal twentyfour
406+ && (rd#get_register = rs#get_register) ->
407+ let addr = instr#get_address in
408+ let lslinstr_r = get_arm_assembly_instruction (addr#add_int (- 4 )) in
409+ let ldrbinstr_r = get_arm_assembly_instruction (addr#add_int (- 8 )) in
410+ (match (TR. to_option lslinstr_r, TR. to_option ldrbinstr_r) with
411+ | (Some lslinstr , Some ldrbinstr ) ->
412+ if
413+ (match lslinstr#get_opcode with
414+ | LogicalShiftLeft (_, ACCAlways , rd1, rs1, imm, _)
415+ when imm#is_immediate
416+ && imm#to_numerical#equal twentyfour
417+ && (rd1#get_register = rd#get_register)
418+ && (rs1#get_register = rd#get_register) -> true
419+ | _ -> false )
420+ && (match ldrbinstr#get_opcode with
421+ | LoadRegisterByte (ACCAlways , rd2, _, _, _, _)
422+ when rd2#get_register = rd#get_register -> true
423+ | _ -> false )
424+ then
425+ Some (TR. tget_ok ldrbinstr_r, TR. tget_ok lslinstr_r, instr)
426+ else
427+ None
428+ | _ -> None )
429+ | _ -> None
430+
431+
432+
299433let identify_arm_aggregate
300434 (ch : pushback_stream_int )
301435 (instr : arm_assembly_instruction_int ):
302436 arm_instruction_aggregate_int option =
303- match identify_jumptable ch instr with
304- | Some (instrs , jt ) ->
305- let anchor = List. nth instrs ((List. length instrs) - 1 ) in
306- let entry = List. hd instrs in
307- let exitinstr = anchor in
308- Some (make_arm_jumptable_aggregate ~jt ~instrs ~entry ~exitinstr ~anchor )
309- | _ ->
310- match identify_it_sequence ch instr with
311- | Some its ->
312- let instrs = its#instrs in
313- let entry = List. hd instrs in
314- let exitinstr = List. hd (List. rev instrs) in
315- Some (make_it_sequence_aggregate
316- ~its ~instrs ~entry ~exitinstr ~anchor: entry)
317- | _ ->
318- match identify_ldmstm_sequence ch instr with
319- | Some ldmstmseq ->
320- Some (make_ldm_stm_sequence_aggregate ldmstmseq)
321- | _ ->
322- match identify_bx_call ch instr with
323- | Some (movinstr , bxinstr ) ->
324- Some (make_bx_call_aggregate movinstr bxinstr)
325- | _ -> None
437+ let result =
438+ match identify_jumptable ch instr with
439+ | Some (instrs , jt ) ->
440+ let anchor = List. nth instrs ((List. length instrs) - 1 ) in
441+ let entry = List. hd instrs in
442+ let exitinstr = anchor in
443+ Some (make_arm_jumptable_aggregate ~jt ~instrs ~entry ~exitinstr ~anchor )
444+ | _ -> None in
445+ let result =
446+ match result with
447+ | Some _ -> result
448+ | _ ->
449+ match identify_it_sequence ch instr with
450+ | Some its ->
451+ let instrs = its#instrs in
452+ let entry = List. hd instrs in
453+ let exitinstr = List. hd (List. rev instrs) in
454+ Some (make_it_sequence_aggregate
455+ ~its ~instrs ~entry ~exitinstr ~anchor: entry)
456+ | _ -> None in
457+ let result =
458+ match result with
459+ | Some _ -> result
460+ | _ ->
461+ match identify_ldmstm_sequence ch instr with
462+ | Some ldmstmseq ->
463+ Some (make_ldm_stm_sequence_aggregate ldmstmseq)
464+ | _ -> None in
465+ let result =
466+ match result with
467+ | Some _ -> result
468+ | _ ->
469+ match identify_bx_call ch instr with
470+ | Some (movinstr , bxinstr ) ->
471+ Some (make_bx_call_aggregate movinstr bxinstr)
472+ | _ -> None in
473+ let result =
474+ match result with
475+ | Some _ -> result
476+ | _ ->
477+ match identify_pseudo_ldrsh ch instr with
478+ | Some (ldrhinstr , lslinstr , asrinstr ) ->
479+ Some (make_pseudo_ldrsh_aggregate ldrhinstr lslinstr asrinstr)
480+ | _ -> None in
481+ let result =
482+ match result with
483+ | Some _ -> result
484+ | _ ->
485+ match identify_pseudo_ldrsb ch instr with
486+ | Some (ldrbinstr , lslinstr , asrinstr ) ->
487+ Some (make_pseudo_ldrsb_aggregate ldrbinstr lslinstr asrinstr)
488+ | _ -> None in
489+ result
0 commit comments