Add asm annotated type
This commit is contained in:
parent
99adfcaa39
commit
5548c7d1c6
3 changed files with 58 additions and 39 deletions
|
@ -3,26 +3,10 @@
|
||||||
Uses `objdump -d` internally, and parses the output
|
Uses `objdump -d` internally, and parses the output
|
||||||
*)
|
*)
|
||||||
|
|
||||||
(** A memory address *)
|
|
||||||
type addr_t = int
|
|
||||||
|
|
||||||
(** A single asm instruction *)
|
|
||||||
type asm_instr_t = {
|
|
||||||
instr_addr: addr_t; (** Memory location of this instruction *)
|
|
||||||
instr_bytes: Bytes.t; (** Binary representation of the instruction *)
|
|
||||||
instr_asm: string; (** Asm for the instruction (eg `movq …`) *)
|
|
||||||
}
|
|
||||||
type asm_t = asm_instr_t list
|
|
||||||
type asm_sub_t = {
|
|
||||||
sub_section: string;
|
|
||||||
sub_name: string;
|
|
||||||
sub_addr: addr_t;
|
|
||||||
sub_asm: asm_t;
|
|
||||||
}
|
|
||||||
type asm_info_t = asm_sub_t list
|
|
||||||
|
|
||||||
exception ParseError of string
|
exception ParseError of string
|
||||||
|
|
||||||
|
module AsmTypes = Asm_info.NoAnnot
|
||||||
|
|
||||||
(** Pretty printers *)
|
(** Pretty printers *)
|
||||||
let pp_hex_bytes ppx bytes_array =
|
let pp_hex_bytes ppx bytes_array =
|
||||||
(* Number of lone spaces to be printed after the bytes. Objdump prints 21. *)
|
(* Number of lone spaces to be printed after the bytes. Objdump prints 21. *)
|
||||||
|
@ -32,19 +16,23 @@ let pp_hex_bytes ppx bytes_array =
|
||||||
Format.fprintf ppx "%s" (String.make remaining_spaces ' ')
|
Format.fprintf ppx "%s" (String.make remaining_spaces ' ')
|
||||||
|
|
||||||
let pp_asm_instr ppx asm_instr =
|
let pp_asm_instr ppx asm_instr =
|
||||||
Format.fprintf ppx " %04x:\t%a\t%s@."
|
AsmTypes.(
|
||||||
asm_instr.instr_addr
|
Format.fprintf ppx " %04x:\t%a\t%s@."
|
||||||
pp_hex_bytes asm_instr.instr_bytes
|
asm_instr.instr_addr
|
||||||
asm_instr.instr_asm
|
pp_hex_bytes asm_instr.instr_bytes
|
||||||
|
asm_instr.instr_asm
|
||||||
|
)
|
||||||
|
|
||||||
let pp_asm ppx asm_instrs = List.iter (pp_asm_instr ppx) asm_instrs
|
let pp_asm ppx asm_instrs = List.iter (pp_asm_instr ppx) asm_instrs
|
||||||
|
|
||||||
let pp_asm_sub ppx asm_sub =
|
let pp_asm_sub ppx asm_sub =
|
||||||
Format.fprintf ppx "%016x <%s> {%s}:@.@[%a@]@."
|
AsmTypes.(
|
||||||
asm_sub.sub_addr
|
Format.fprintf ppx "%016x <%s> {%s}:@.@[%a@]@."
|
||||||
asm_sub.sub_name
|
asm_sub.sub_addr
|
||||||
asm_sub.sub_section
|
asm_sub.sub_name
|
||||||
pp_asm asm_sub.sub_asm
|
asm_sub.sub_section
|
||||||
|
pp_asm asm_sub.sub_asm
|
||||||
|
)
|
||||||
|
|
||||||
let pp_asm_info ppx asm_info =
|
let pp_asm_info ppx asm_info =
|
||||||
List.iter (fun asm_sub -> Format.fprintf ppx "%a" pp_asm_sub asm_sub)
|
List.iter (fun asm_sub -> Format.fprintf ppx "%a" pp_asm_sub asm_sub)
|
||||||
|
@ -131,12 +119,14 @@ let get_objdump prog_path =
|
||||||
None if the previous subroutine was committed;
|
None if the previous subroutine was committed;
|
||||||
- the current subroutine's asm lines
|
- the current subroutine's asm lines
|
||||||
*)
|
*)
|
||||||
|
|
||||||
type interpret_objdump_accu =
|
type interpret_objdump_accu =
|
||||||
ObjdumpAccu of asm_info_t * string * asm_sub_t option * asm_t
|
ObjdumpAccu of AsmTypes.asm_info_t * string * AsmTypes.asm_sub_t option *
|
||||||
|
AsmTypes.asm_t
|
||||||
|
|
||||||
(** Interprets `objdump -d` output and yield a list of functions, alongside
|
(** Interprets `objdump -d` output and yield a list of functions, alongside
|
||||||
with their addresses, symbol names, asm, … *)
|
with their addresses, symbol names, asm, … *)
|
||||||
let interpret_objdump objdump_out : asm_info_t =
|
let interpret_objdump objdump_out : AsmTypes.asm_info_t =
|
||||||
|
|
||||||
(* Reads a string of bytes formatted like "01 23 ae 3f" and output a Bytes.t
|
(* Reads a string of bytes formatted like "01 23 ae 3f" and output a Bytes.t
|
||||||
object *)
|
object *)
|
||||||
|
@ -201,11 +191,12 @@ let interpret_objdump objdump_out : asm_info_t =
|
||||||
(Format.sprintf "Invalid subroutine line: \"%s\""
|
(Format.sprintf "Invalid subroutine line: \"%s\""
|
||||||
cur_line))
|
cur_line))
|
||||||
) in
|
) in
|
||||||
let line = {
|
let line = AsmTypes.({
|
||||||
instr_addr = addr;
|
instr_addr = addr;
|
||||||
instr_bytes = bytes_repr;
|
instr_bytes = bytes_repr;
|
||||||
instr_asm = asm_repr
|
instr_asm = asm_repr;
|
||||||
} in
|
instr_annot = ();
|
||||||
|
}) in
|
||||||
(match objdump_accu with
|
(match objdump_accu with
|
||||||
| ObjdumpAccu(cur_info, cur_section, Some in_flight, asm) ->
|
| ObjdumpAccu(cur_info, cur_section, Some in_flight, asm) ->
|
||||||
ObjdumpAccu(cur_info, cur_section, Some in_flight, line::asm)
|
ObjdumpAccu(cur_info, cur_section, Some in_flight, line::asm)
|
||||||
|
|
26
src/asm_info.ml
Normal file
26
src/asm_info.ml
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
module type Annot_type = sig
|
||||||
|
type instr_annot_t
|
||||||
|
end
|
||||||
|
|
||||||
|
module S (Annot: Annot_type) = struct
|
||||||
|
(** A memory address *)
|
||||||
|
type addr_t = int
|
||||||
|
|
||||||
|
(** A single asm instruction *)
|
||||||
|
type asm_instr_t = {
|
||||||
|
instr_addr: addr_t; (** Memory location of this instruction *)
|
||||||
|
instr_bytes: Bytes.t; (** Binary representation of the instruction *)
|
||||||
|
instr_asm: string; (** Asm for the instruction (eg `movq …`) *)
|
||||||
|
instr_annot: Annot.instr_annot_t; (** User-defined annotation *)
|
||||||
|
}
|
||||||
|
type asm_t = asm_instr_t list
|
||||||
|
type asm_sub_t = {
|
||||||
|
sub_section: string;
|
||||||
|
sub_name: string;
|
||||||
|
sub_addr: addr_t;
|
||||||
|
sub_asm: asm_t;
|
||||||
|
}
|
||||||
|
type asm_info_t = asm_sub_t list
|
||||||
|
end
|
||||||
|
|
||||||
|
module NoAnnot = S(struct type instr_annot_t = unit end)
|
|
@ -13,8 +13,11 @@ let read_all handle =
|
||||||
let len = in_channel_length handle in
|
let len = in_channel_length handle in
|
||||||
let buffer = Bytes.create len in
|
let buffer = Bytes.create len in
|
||||||
let bytes_read = input handle buffer 0 len in
|
let bytes_read = input handle buffer 0 len in
|
||||||
if bytes_read <> len then
|
if bytes_read <> len then (
|
||||||
|
Format.eprintf "Could not read whole file. Read %d, expected %d.@."
|
||||||
|
bytes_read len ;
|
||||||
raise (Failure "Could not read whole file")
|
raise (Failure "Could not read whole file")
|
||||||
|
)
|
||||||
else
|
else
|
||||||
Bytes.to_string buffer
|
Bytes.to_string buffer
|
||||||
|
|
||||||
|
@ -26,9 +29,8 @@ let _ =
|
||||||
let objdump_out = read_all in_handle in
|
let objdump_out = read_all in_handle in
|
||||||
close_in in_handle ;
|
close_in in_handle ;
|
||||||
let parsed = Asm_acquire.interpret_objdump objdump_out in
|
let parsed = Asm_acquire.interpret_objdump objdump_out in
|
||||||
Format.eprintf "%a" Asm_acquire.pp_asm_info parsed
|
|
||||||
(*
|
let render_data = Renderer.init_render_data parsed in
|
||||||
List.iter (fun asm_sub ->
|
let render_data, box1 = Renderer.add_box render_data (0x1004, 0x100f) in
|
||||||
Format.eprintf "%a" Asm_acquire.pp_asm_sub asm_sub)
|
ignore box1 ;
|
||||||
parsed
|
Format.printf "%s@." (Renderer.to_string Html_renderer.render render_data)
|
||||||
*)
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue