elf_arrows/src/elf_arrows.ml

121 lines
4.2 KiB
OCaml

(** Entry point file for elf_arrows *)
exception NotElf;;
exception NoDwarf;;
exception NoDwarfStatic;;
let (>>=) = Error.bind
let make_pp linksem_pp =
(fun fmt arg ->
linksem_pp arg
|> Format.fprintf fmt "%s")
type elf_path = string
type elf_handle =
ElfHandle of elf_path * Elf_file.elf_file * Dwarf.dwarf_static
* Asm_info.NoAnnot.asm_info_t
(** Open an ELF file and loads its dwarf_static infos. *)
let open_elf elf_path =
(Byte_sequence.acquire elf_path >>= fun elf_bs -> (
match Elf_file.read_elf64_file elf_bs with
| Error.Success elf64 -> Error.Success (Elf_file.ELF_File_64 elf64)
| Error.Fail _ -> (match Elf_file.read_elf32_file elf_bs with
| Error.Success elf32 -> Error.Success (Elf_file.ELF_File_32 elf32)
| Error.Fail _ -> raise NotElf)
))
>>= fun elf_file -> (
let asm_info = Asm_acquire.acquire_asm elf_path in
let static_info = (match Dwarf.extract_dwarf_static elf_file with
| Some static_info -> static_info
| None -> raise NoDwarfStatic) in
Error.Success (ElfHandle (elf_path, elf_file, static_info, asm_info)))
(** Add boxes according to DWARF info *)
let add_line_boxes render_data matcher_data dwarf_lines =
(* List.fold_left with two elements in scope at once. *)
let fold_ahead folder base lst =
let rec do_fold accu = function
| [] | _::[] -> accu
| hd1::hd2::tl -> do_fold (folder accu hd1 hd2) (hd2::tl)
in
do_fold base lst
in
List.fold_left (fun (cur_render_data, cur_matcher_data)
(reg_header, reg_list) ->
fold_ahead (fun (cur_render_data, cur_matcher_data) cur_reg reg_ahead ->
let box_start = Z.to_int @@ cur_reg.Dwarf.lnr_address in
let box_end = Z.to_int @@ reg_ahead.Dwarf.lnr_address in
(match box_start = box_end with
| true -> cur_render_data, cur_matcher_data
| false ->
Format.eprintf "Add box %x -- %x@." box_start box_end ;
let n_matcher_data, block_class_id =
Asm_matcher.add_block cur_matcher_data reg_header cur_reg in
let file_name = (
let file_id = cur_reg.lnr_file
|> Z.to_int in
Asm_matcher.extract_file_name file_id reg_header.lnh_file_names
) in
let n_render_data, _ = Renderer.add_box_excl
cur_render_data (box_start, box_end)
Renderer.(Some {
box_file = file_name ;
box_line = Z.to_int cur_reg.lnr_line;
box_col = Z.to_int cur_reg.lnr_column;
box_class_id = block_class_id;
})
in
(n_render_data, n_matcher_data))
)
(cur_render_data, cur_matcher_data) reg_list)
(render_data, matcher_data)
dwarf_lines
let elf_files = ref []
let speclist = []
let parse_anon_arg arg =
elf_files := arg :: (!elf_files)
let _ =
Arg.parse speclist parse_anon_arg "./test ELF_FILE" ;
let elf_handles = List.rev @@
List.map (fun path -> match open_elf path with
| Error.Success handle -> handle
| Error.Fail msg ->
raise (Failure ("Could not open " ^ path ^ ": " ^ msg)))
!elf_files
in
List.iter (fun (ElfHandle(path, _, static_info, _)) ->
let line_info = static_info.ds_evaluated_line_info in
Format.eprintf "Line infos <%s>:@. %a@."
path
(make_pp Dwarf.pp_evaluated_line_info)
line_info ;
) elf_handles ;
let map_with_state mapper initial_state lst =
List.fold_right (fun elt (cur_state, accu) ->
let n_state, mapped_elt = mapper cur_state elt in
n_state, mapped_elt::accu)
lst
(initial_state, [])
in
let _, multi_render_data = map_with_state
(fun matcher_state (ElfHandle(path, _, static_info, asm)) ->
let render_data = Renderer.init_render_data asm path in
let line_info = static_info.ds_evaluated_line_info in
let boxed_render_data, n_matcher_state =
add_line_boxes render_data matcher_state line_info in
n_matcher_state, boxed_render_data
) Asm_matcher.empty_state elf_handles in
Format.printf "%s@."
(Renderer.to_string Html_renderer.render multi_render_data)