Bindings to Intel XED from OCaml.
Warning: This binding doesn't perfectly ensure safety of underlying XED function calls, e.g. calling Xed.Inst.operand x 99999999
has no bounds check and will crash.
Run xed-build.sh
before building with dune build --ignore-promoted-rules
.
Building without --ignore-promoted-rules
requires that Python bindings for Clang be installed.
This binding is mostly a direct mapping to underlying XED functions, but names have been reorganized to be more idiomatic to OCaml.
XED structures are handled as opaque types, e.g. xed_decoded_inst_t
is Xed.DecodedInst.t
. XED functions that resemble methods on a struct have been sorted into modules, e.g. xed_decoded_inst_get_length
is Xed.DecodedInst.get_length
. As with their XED counterparts, these structures are generally mutable. You'll see [<`Read|`Write]
as parameters to the OCaml opaque types; these are to prevent attempted modification of const struct pointers and should't get in your way unless you're breaking const-correctness in the XED API (which isn't necessarily unsafe).
XED enums are exposed as OCaml constructors in Xed.Enum
. XED functions that concern only enums are in that module. The enum–string conversion functions are there too and have been renamed, e.g. xed_reg_enum_t2str
and str2xed_reg_enum_t
are now reg_to_string
and reg_of_string
respectively. There are also foo_to_int
& foo_of_int
functions for each enum type, but you typically shouldn't need those.
Many XED functions that initialize a particular XED structure have been modified to both allocate and initialize; e.g. xed_decode
is Xed.decode : 'a XedStructs.State.t -> string -> ('b DecodedInst.t, Enum.error) result
, instead of taking an uninitialized DecodedInst.t
as a argument.
Much of the code in this library is automatically generated by a bespoke Python script that parses XED's header files. The generated code is a ocaml-ctypes "low-level" binding (function_desc.ml
& type_desc.ml
), and a "high-level" binding (bind.ml
& XBEnums.ml
) that is built on top of the low-level binding. The high-level binding is exposed via the manually written xed.ml
, that adds some convenience functions and shadows some of the auto-generated bindings with more ergonomic replacements.
#require "xedbindings";;
open Xedbindings.Xed;;
(* state64 is convenience; you could make one yourself with State.init2 Enum.LONG_64 Enum.A64b *)
let xedd = decode state64 "\x55" |> ok_exn;;
let () = DecodedInst.get_reg xedd Enum.REG0 |> Enum.reg_to_string |> print_endline;; (* "RBP" *)
let () = DecodedInst.inst xedd |> Inst.iform_enum |> Enum.iform_to_iclass_string_att |> print_endline;; (* "PUSH" *)
(* DecodedInst.format is a special wrapper for xed_format_generic. *)
let () = DecodedInst.format ~syntax:Enum.ATT xedd 0xdeadbeefL |> print_endline;; (* "pushq %rbp" *)
Also see test/test.ml
.
This library may slightly break backwards-compatibility of its API on any minor version update. For example, these incompatibilities may include:
- Minor type changes or function renames for better OCaml ergonomics
- Upstream XED updates (that don't broadly break stuff)
- Optional bindings for the "enc2" encoder.
- Custom high-level OCaml to mirror XED's high-level encoding API (which is not currently exposed by this binding).
- Determine what further parts of XED are excluded from the binding, and possibly complete the binding.