You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

83 lines
2.7 KiB

open Ctypes
open Foreign
module B = Ffi_bindings.Bindings(Ffi_generated)
module Types = B.T
type encoded_result =
{
encoding: int array;
encoding_size : int;
stat_count : int;
}
let ks_arch_supported arch =
B.ks_arch_supported_ arch
let ks_version major minor =
let major = Unsigned.UInt.of_int major in
let minor = Unsigned.UInt.of_int minor in
let u = B.ks_version_ (allocate uint major) (allocate uint minor) in
Unsigned.UInt.to_int u
(* TODO: better handling of error value *)
let ks_option engine opttype optvalue =
match opttype with
| Types.KS_OPT_SYNTAX -> B.ks_option_ engine Types.KS_OPT_SYNTAX optvalue
let ks_strerror err =
B.ks_strerror_ err
let ks_open arch ?(endian=Types.KS_MODE_LITTLE_ENDIAN) mode =
let check_endian =
match endian with
| Types.KS_MODE_BIG_ENDIAN ->
begin
let m = Ffi_generated_types.constant (Types.string_of_ks_mode Types.KS_MODE_BIG_ENDIAN) int64_t in
let m' = Ffi_generated_types.constant (Types.string_of_ks_mode mode) int64_t in
Result.Ok(Int64.add m m')
end
| Types.KS_MODE_LITTLE_ENDIAN -> Result.Ok(Ffi_generated_types.constant (Types.string_of_ks_mode mode) int64_t)
| _ -> Result.Error("Non-endian mode passed to endian arg of ks_open: use KS_MODE_BIG_ENDIAN or KS_MODE_LITTLE_ENDIAN")
in
let mode =
match check_endian with
| Result.Ok a -> a
| Result.Error e -> failwith e
in
let engine = allocate_n ~count:1 ((ptr Types.ks_engine)) in
match (B.ks_open_ arch mode engine) with
| Types.KS_ERR_OK -> Result.Ok(!@ engine)
| _ as err -> Result.Error(ks_strerror err)
let ks_close engine = B.ks_close_ engine
let ks_errno engine = B.ks_err_ engine
let ks_asm engine str addr =
let addr' = Int64.of_int addr in
let encoding = allocate_n ~count:1 (ptr uchar) in
let encoding_size = allocate size_t (Unsigned.Size_t.of_int 0) in
let stat_count = allocate size_t (Unsigned.Size_t.of_int 0) in
match (B.ks_asm_ engine str addr' encoding encoding_size stat_count) with
| 0 -> begin
let iencoding_size = Unsigned.Size_t.to_int (!@ encoding_size) in
let istat_count = Unsigned.Size_t.to_int (!@ stat_count) in
let encodedasm =
CArray.from_ptr (!@ encoding) (Unsigned.Size_t.to_int (!@ encoding_size))
|> CArray.to_list |> Array.of_list (* No map in CArray *)
|> Array.map (fun c -> Unsigned.UChar.to_int c)
in
B.ks_free_ (to_voidp (!@ encoding));
Result.Ok({encoding = encodedasm; encoding_size = iencoding_size; stat_count = istat_count})
end
| _ -> let err = ks_errno engine |> ks_strerror in
Result.Error err
let asm_array_to_string a =
Array.fold_left (fun str c -> let t = Printf.sprintf "%02x " c in str^t) "" a