package bap-std
Basic disassembler.
This is a target agnostic basic low-level machine code disassembler.
predicate to drive the disassembler
val sexp_of_pred : pred -> Ppx_sexp_conv_lib.Sexp.t
val pred_of_sexp : Ppx_sexp_conv_lib.Sexp.t -> pred
val __pred_of_sexp__ : Ppx_sexp_conv_lib.Sexp.t -> pred
Basic types
insns
is a list of pairs, where each pair consists of a memory region occupied by an instruction, and the instruction itself.
val sexp_of_full_insn : full_insn -> Ppx_sexp_conv_lib.Sexp.t
Disassembler.
The 'a
and 'k
type variables specify disassembler modes of operation. In a process of disassembly it can store extra information that might be useful. Although, since storing it takes extra time and space, it is disabled by default.
The first type variable specifies whether storing assembly strings is enabled. It can be switched using store_asm
, drop_asm
functions. When it is enabled, then this type variable will be set to asm
, and it will give an access to functions that returns this information. Otherwise, this type variable will be set to empty
, thus stopping you from accessing assembler information.
The second type variable stands for kinds
, i.e. to store or not to store extra information about instruction kind.
Note: at some points you can have an access to this information even if you don't enable it explicitly.
Disassembler state.
Words of precaution: this state is valid only inside handlers functions of the run
function. It shouldn't be stored anywhere. First two type variables are bound correspondingly to two variables of the disassmbler ('a,'k) t
type. The last pair of type variables are bounded to input and output types of user functions. They are made different, so that a function can be run in an arbitrary monad. For simple cases, the can be made the same.
val register :
Bap_core_theory.Theory.language ->
(Bap_core_theory.Theory.target -> (empty, empty) t Core_kernel.Or_error.t) ->
unit
register encoding constructor
registers a disassembler constructor
for the given encoding
.
The constructor receives the target
value that further specifies the details of the target system, e.g., a cpu model, limitiations on the instruction set, etc.
The constructor commonly uses create
and passes the backend and target specific options to it. It can also use the custom
function to create its own backend. Alternatively, the lookup
function could be used to delegate the decoding to another encoder.
val lookup :
Bap_core_theory.Theory.target ->
Bap_core_theory.Theory.language ->
(empty, empty) t Core_kernel.Or_error.t
lookup target encoding
returns the disassembler for the specified target
and encoding
, creates one if necessary.
Returns an error if there is no constructor for the given encoding registered (via the register
function) or if the constructor itself fails to create a disassembler.
val create :
?debug_level:int ->
?cpu:string ->
?attrs:string ->
?backend:string ->
string ->
(empty, empty) t Core_kernel.Or_error.t
create ?debug_level ?cpu ~backend target
creates the disassmbler from one of the C-level backends.
The parameters are backend-specific and are commonly set by the target support plugins via the register
function, therefore the create
function should only be used to register a new target. Use lookup
to get an appropriate disassembler for your target/encoding.
val custom :
Bap_core_theory.Theory.target ->
Bap_core_theory.Theory.language ->
(module Backend.S with type t = 'a) ->
'a ->
(empty, empty) t
custom target encoding backend disassembler
creates a custom backend for the given target
and encoding
.
This function is commonly called by the constructor function registered with the register
function.
val with_disasm :
?debug_level:int ->
?cpu:string ->
?backend:string ->
string ->
f:((empty, empty) t -> 'a Core_kernel.Or_error.t) ->
'a Core_kernel.Or_error.t
with_disasm ?debug_level ?cpu ~backend ~f target
creates a disassembler passing all options to create
function and applies function f
to it. Once f
is evaluated the disassembler is closed with close
function.
val close : (_, _) t -> unit
close d
closes a disassembler d
.
val run :
?backlog:int ->
?stop_on:pred list ->
?invalid:(('a, 'k, 's, 'r) state -> mem -> 's -> 'r) ->
?stopped:(('a, 'k, 's, 'r) state -> 's -> 'r) ->
?hit:(('a, 'k, 's, 'r) state -> mem -> (asm, kinds) insn -> 's -> 'r) ->
('a, 'k) t ->
return:('s -> 'r) ->
init:'s ->
mem ->
'r
run ?stop_on ?invalid ?stopped dis mem ~init ~return ~hit
performs the recursive disassembly of the specified chunk of memory mem
. The process of disassembly can be driven using the stop
, step
, back
and jump
functions, described later.
val insn_of_mem :
(_, _) t ->
mem ->
(mem * (asm, kinds) insn option * [ `left of mem | `finished ])
Core_kernel.Or_error.t
insn_of_mem dis mem
performs a disassembly of one instruction from the a given memory region mem
. Returns a tuple imem,insn,`left over
where imem
stands for a piece of memory consumed in a process of disassembly, insn
can be Some ins
if disassembly was successful, and None
otherwise. `left over
complements imem
to original mem
.
updates the set of predicates, that rules the stop condition.
last s n
returns last n
instructions disassembled in this step. If there are less then n
instructions, then returns a smaller list
val stop : (_, _, 's, 'r) state -> 's -> 'r
stop the disassembly and return the provided value.
val step : (_, _, 's, 'r) state -> 's -> 'r
continue disassembling from the current point. You can change a a set of predicates, before stepping next. If you want to continue from a different address, use jump
jump to the specified memory and continue disassembly in it.
For example, if you want to jump to a specified address, and you're working in a Or_error
monad, then you can:
view ~from:addr (mem state) >>= fun mem -> jump mem data
val back : (_, _, 's, 'r) state -> 's -> 'r
restarts last step.
module Insn : sig ... end
Basic instruction aka machine-specific instruction.
module Trie : sig ... end
Trie maps over instructions