Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disassembly #170

Merged
merged 5 commits into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions CodeHawk/CHB/bchanalyze/bCHFileIO.ml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ open BCHMIPSDictionary
(* bchlibarm32 *)
open BCHARMAssemblyInstructions
open BCHARMDictionary
open BCHARMLoopStructure

(* bchlibpower32 *)
open BCHPowerAssemblyInstructions
Expand Down Expand Up @@ -92,6 +93,7 @@ let get_bch_root (info:string):xml_element_int =
end


(* applies to x86 only *)
let save_functions_list () =
let filename = get_functions_filename () in
let doc = xmlDocument () in
Expand Down Expand Up @@ -125,6 +127,67 @@ let save_functions_list () =
end


let save_arm_functions_list () =
let filename = get_functions_filename () in
let doc = xmlDocument () in
let root = get_bch_root "functions" in
let ffNode = xmlElement "functions" in
let subnodes = ref [] in
begin
BCHARMAssemblyFunctions.arm_assembly_functions#itera (fun faddr f ->
let fNode = xmlElement "fn" in
let jtc = f#get_jumptable_count in
let (translation, lc, ld, ujc) =
try
begin
BCHTranslateARMToCHIF.translate_arm_assembly_function f;
record_arm_loop_levels faddr;
("ok",
get_arm_loop_count_from_table f,
get_arm_loop_depth_from_table f,
(-1))
end
with
| BCH_failure p ->
let finfo = BCHFunctionInfo.get_function_info faddr in
let ujc = finfo#get_unknown_jumps_count in
(CHPrettyUtil.pretty_to_string p, (-1), (-1), ujc) in
let set = fNode#setAttribute in
let seti = fNode#setIntAttribute in
let setx t x = set t x#to_hex_string in
begin
(if functions_data#has_function_name faddr then
let name = (functions_data#get_function faddr)#get_function_name in
let name =
if has_control_characters name then
"__xx__" ^ (hex_string name)
else
name in
set "name" name);
setx "va" faddr;
seti "ic" f#get_instruction_count;
seti "bc" f#get_block_count;
(if jtc > 0 then seti "jtc" jtc);
(if translation = "ok" then
begin
(if lc > 0 then seti "lc" lc);
(if ld > 0 then seti "ld" ld);
end
else
begin
set "tr" "x";
seti "ujc" ujc
end);
subnodes := fNode :: !subnodes
end);
ffNode#appendChildren !subnodes;
doc#setNode root;
root#appendChildren [ffNode];
file_output#saveFile filename doc#toPretty
end



let save_global_state () =
let filename = get_global_state_filename () in
let doc = xmlDocument () in
Expand Down
6 changes: 5 additions & 1 deletion CodeHawk/CHB/bchanalyze/bCHFileIO.mli
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,12 @@ open BCHLibTypes
(* bchlibx86 *)
open BCHLibx86Types


(** save function cfg info (x86 only) *)
val save_functions_list: unit -> unit

(** save function cfg info for arm functions *)
val save_arm_functions_list: unit -> unit

val save_global_state: unit -> unit
val save_system_info: unit -> unit
val save_resultmetrics: xml_element_int -> unit
Expand Down
8 changes: 8 additions & 0 deletions CodeHawk/CHB/bchcmdline/bCHXBinaryAnalyzer.ml
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ let export_directory = ref ""
let savecfgs = ref false
let save_xml = ref false (* save disassembly status in xml *)
let save_asm = ref false
let save_asm_cfg_info = ref false (* save functions list with cfg info in xml *)
let set_datablocks = ref false (* only supported for arm *)
let construct_all_functions = ref false

Expand Down Expand Up @@ -204,6 +205,8 @@ let speclist =
"save disassembly status in xml for bulk evaluation");
("-save_asm", Arg.Unit (fun () -> save_asm := true),
"save assembly listing in the analysis directory");
("-save_asm_cfg_info", Arg.Unit (fun () -> save_asm_cfg_info := true),
"save list of functions with cfg info to xml file (may be slow)");
("-construct_all_functions",
Arg.Unit (fun () -> construct_all_functions := true),
"construct all functions even if analyzing only a few of them");
Expand Down Expand Up @@ -588,6 +591,11 @@ let main () =
(get_duplicate_coverage_filename ())
(STR (BCHARMAssemblyFunctions.arm_assembly_functions#duplicates_to_string));
pr_timing [STR "duplicates listing saved"];
(if !save_asm_cfg_info then
begin
save_arm_functions_list ();
pr_timing [STR "function cfg info saved"]
end);
save_system_info ();
pr_timing [STR "system_info saved"];
save_arm_dictionary ();
Expand Down
16 changes: 16 additions & 0 deletions CodeHawk/CHB/bchlib/bCHBCTypeUtil.ml
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,19 @@ let get_element_type (t: btype_t) =
raise (BCH_failure (LBLOCK [STR "Not an array type"]))


let get_array_length (t: btype_t): int traceresult =
match t with
| TArray (_, Some len, _) ->
(match len with
| Const (CInt (i64, _, _)) -> Ok (Int64.to_int i64)
| _ ->
Error ["Array does not have a constant length: " ^ (exp_to_string len)])
| TArray _ ->
Error ["Array does not have a length"]
| _ ->
Error ["get_array_length: not an array: " ^ (btype_to_string t)]


(* ======================================================= size and alignment *)

let resolve_type (btype: btype_t) = bcfiles#resolve_type btype
Expand Down Expand Up @@ -1177,6 +1190,7 @@ let struct_field_categories (ty: btype_t): string list =
| Error e -> e
| Ok ty ->
match ty with
| TArray (TComp (ckey, _), _, _)
| TPtr (TPtr (TComp (ckey, _), _), _)
| TPtr (TComp (ckey, _), _) ->
let compinfo = bcfiles#get_compinfo ckey in
Expand All @@ -1187,6 +1201,8 @@ let struct_field_categories (ty: btype_t): string list =
| TPtr (TFun _, _) -> "address"
| _ -> "unknown") compinfo.bcfields

| TArray ((TFun _ | TPtr (TFun _, _)), _, _) -> ["address"]

| rty -> [btype_to_string ty; btype_to_string rty]


Expand Down
6 changes: 6 additions & 0 deletions CodeHawk/CHB/bchlib/bCHBCTypeUtil.mli
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,12 @@ val size_of_int_ikind: ikind_t -> int

val size_of_float_fkind: fkind_t -> int

(** [get_array_length ty] returns the length (number of elements) of an array.

An error value is returned if the array does not have a constant length, or
does not have a length at all, of if the type is not an array. *)
val get_array_length: btype_t -> int traceresult

(** [size_of_btype ty] returns the size (in bytes) of type [ty].

An error value is returned if the size cannot be determined. This may
Expand Down
26 changes: 19 additions & 7 deletions CodeHawk/CHB/bchlib/bCHCallbackTables.ml
Original file line number Diff line number Diff line change
Expand Up @@ -192,12 +192,21 @@ object (self)
let compinfo = bcfiles#get_compinfo ckey in
List.iteri (fun i fld ->
H.add table (i * 4) fld.bfname) compinfo.bcfields
| TArray (TComp (ckey, _), _, _) ->
let compinfo = bcfiles#get_compinfo ckey in
List.iteri (fun i fld ->
H.add table (i * 4) fld.bfname) compinfo.bcfields
| TArray ((TFun _ | TPtr (TFun _, _)), _, _) ->
H.add table 0 ("cbp_" ^ cba)
| _ ->
raise
(BCH_failure
(LBLOCK [
STR "Unexpected type in creating callback table: ";
btype_to_pretty recty])) in
let msg =
LBLOCK [
STR "Unexpected type in creating callback table: ";
btype_to_pretty recty] in
begin
ch_error_log#add "call-back-table problem" msg;
raise (BCH_failure msg)
end in
table

val offsettypes =
Expand All @@ -214,9 +223,12 @@ object (self)
let _ =
match recty with
| TFun _ -> H.add table 0 ty
| TPtr (TFun (rty, args, b, attr), _) ->
| TPtr (TFun (rty, args, b, attr), _)
| TArray (TFun (rty, args, b, attr), _, _)
| TArray (TPtr (TFun (rty, args, b, attr), _), _, _) ->
H.add table 0 (TFun (rty, args, b, attr))
| TPtr (TComp (ckey, _), _) ->
| TArray (TComp (ckey, _), _, _)
| TPtr (TComp (ckey, _), _) ->
let compinfo = bcfiles#get_compinfo ckey in
List.iteri (fun i fld ->
let offset = i * 4 in
Expand Down
4 changes: 2 additions & 2 deletions CodeHawk/CHB/bchlib/bCHVersion.ml
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@ end


let version = new version_info_t
~version:"0.6.0_20241119"
~date:"2024-11-19"
~version:"0.6.0_20241127"
~date:"2024-11-27"
~licensee: None
~maxfilesize: None
()
2 changes: 2 additions & 0 deletions CodeHawk/CHB/bchlibarm32/bCHARMAssemblyFunction.ml
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ object (self)

method get_block_count = List.length blocks

method get_jumptable_count = List.length self#get_jumptables

method get_not_valid_instr_count =
let c = ref 0 in
let _ =
Expand Down
8 changes: 7 additions & 1 deletion CodeHawk/CHB/bchlibarm32/bCHARMAssemblyFunctions.ml
Original file line number Diff line number Diff line change
Expand Up @@ -915,14 +915,20 @@ let get_arm_disassembly_metrics () =
let loaded_imports = [] in
let imports = imported_imports @ loaded_imports in
let numunknown = !arm_assembly_instructions#get_num_unknown_instructions in
let jumptables =
List.fold_left (fun acc (va, _) ->
if arm_assembly_functions#includes_instruction_address va then
acc + 1
else
acc) 0 !arm_assembly_instructions#get_jumptables in
{ dm_unknown_instrs = numunknown;
dm_instrs = instrs;
dm_functions = arm_assembly_functions#get_num_functions;
dm_coverage = coverage;
dm_pcoverage = 100.0 *. (float_of_int coverage) /. (float_of_int instrs) ;
dm_overlap = overlap;
dm_alloverlap = alloverlap;
dm_jumptables = List.length system_info#get_jumptables;
dm_jumptables = jumptables;
dm_datablocks = List.length system_info#get_data_blocks;
dm_imports = imports;
dm_so_imports = system_info#dmso_metrics;
Expand Down
10 changes: 10 additions & 0 deletions CodeHawk/CHB/bchlibarm32/bCHARMAssemblyInstructions.ml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ open CHXmlDocument
(* bchlib *)
open BCHBasicTypes
open BCHByteUtilities
open BCHConstantDefinitions
open BCHDataBlock
open BCHDoubleword
open BCHFunctionData
Expand Down Expand Up @@ -702,6 +703,15 @@ object (self)
^ " Faddr:<"
^ v#to_hex_string
^ ">"
else if has_symbolic_address_name v then
let name = get_symbolic_address_name v in
" "
^ (fixed_length_string addr 10)
^ " Sym:<"
^ v#to_hex_string
^ ":"
^ name
^ ">"
else if elf_header#is_code_address v then
" "
^ (fixed_length_string addr 10)
Expand Down
70 changes: 69 additions & 1 deletion CodeHawk/CHB/bchlibarm32/bCHARMInstructionAggregate.ml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ let arm_aggregate_kind_to_string (k: arm_aggregate_kind_t) =
^ " target addresses"
| ThumbITSequence it -> it#toString
| LDMSTMSequence s -> s#toString
| BXCall (_, i2) -> "BXCall at " ^ i2#get_address#to_hex_string


class arm_instruction_aggregate_t
Expand Down Expand Up @@ -109,6 +110,11 @@ object (self)
| LDMSTMSequence _ -> true
| _ -> false

method is_bx_call =
match self#kind with
| BXCall _ -> true
| _ -> false

method write_xml (_node: xml_element_int) = ()

method toCHIF (_faddr: doubleword_int) = []
Expand Down Expand Up @@ -173,6 +179,18 @@ let make_ldm_stm_sequence_aggregate
~anchor:(List.hd (List.tl ldmstmseq#instrs))


let make_bx_call_aggregate
(movinstr: arm_assembly_instruction_int)
(bxinstr: arm_assembly_instruction_int): arm_instruction_aggregate_int =
let kind = BXCall (movinstr, bxinstr) in
make_arm_instruction_aggregate
~kind
~instrs:[movinstr; bxinstr]
~entry:movinstr
~exitinstr:bxinstr
~anchor:bxinstr


let disassemble_arm_instructions
(ch: pushback_stream_int) (iaddr: doubleword_int) (n: int) =
for _i = 1 to n do
Expand Down Expand Up @@ -232,6 +250,52 @@ let identify_ldmstm_sequence
| _ -> None


(* format of BX-Call (in ARM)

An indirect jump combined with a MOV of the PC into the LR converts
into an indirect call (because PC holds the instruction-address + 8)

MOV LR, PC
BX Rx
*)
let identify_bx_call
(ch: pushback_stream_int)
(instr: arm_assembly_instruction_int):
(arm_assembly_instruction_int * arm_assembly_instruction_int) option =
let disassemble (iaddr: doubleword_int) =
let instrpos = ch#pos in
let bytes = ch#read_doubleword in
let opcode =
try
disassemble_arm_instruction ch iaddr bytes
with
| _ ->
let _ =
chlog#add
"bx-call disassemble-instruction"
(LBLOCK [iaddr#toPretty]) in
OpInvalid in
let instrbytes = ch#sub instrpos 4 in
let instr = make_arm_assembly_instruction iaddr true opcode instrbytes in
begin
set_arm_assembly_instruction instr;
instr
end in
match instr#get_opcode with
| Move (_, ACCAlways, dst, src, _, _)
when src#is_register
&& dst#get_register = ARLR
&& src#get_register = ARPC ->
begin
let bxinstr = disassemble (instr#get_address#add_int 4) in
match bxinstr#get_opcode with
| BranchExchange (ACCAlways, op) when op#is_register ->
Some (instr, bxinstr)
| _ -> None
end
| _ -> None


let identify_arm_aggregate
(ch: pushback_stream_int)
(instr: arm_assembly_instruction_int):
Expand All @@ -254,4 +318,8 @@ let identify_arm_aggregate
match identify_ldmstm_sequence ch instr with
| Some ldmstmseq ->
Some (make_ldm_stm_sequence_aggregate ldmstmseq)
| _ -> None
| _ ->
match identify_bx_call ch instr with
| Some (movinstr, bxinstr) ->
Some (make_bx_call_aggregate movinstr bxinstr)
| _ -> None
Loading