Allow rendering of multiple files side by side

This commit is contained in:
Théophile Bastian 2019-11-18 13:48:20 +01:00
parent 4583ad6a92
commit caac87e70a
4 changed files with 111 additions and 58 deletions

View File

@ -51,7 +51,13 @@ let add_line_boxes render_data dwarf_lines =
let box_end = Z.to_int @@ reg_ahead.Dwarf.lnr_address in
Format.eprintf "Add box %x -- %x@." box_start box_end ;
let n_render_data, _ = Renderer.add_box_excl
cur_render_data (box_start, box_end) in
cur_render_data (box_start, box_end)
Renderer.(Some {
box_file = Z.to_int cur_reg.lnr_file;
box_line = Z.to_int cur_reg.lnr_line;
box_col = Z.to_int cur_reg.lnr_column;
})
in
n_render_data)
cur_render_data reg_list)
render_data
@ -80,10 +86,12 @@ let _ =
line_info ;
) elf_handles ;
List.iter (fun (ElfHandle(_, _, static_info, asm)) ->
let multi_render_data = List.map (fun (ElfHandle(_, _, static_info, asm)) ->
let render_data = Renderer.init_render_data asm in
let line_info = static_info.ds_evaluated_line_info in
let boxed_render_data = add_line_boxes render_data line_info in
Format.printf "%s@."
(Renderer.to_string Html_renderer.render boxed_render_data)
) elf_handles;
boxed_render_data
) elf_handles in
Format.printf "%s@."
(Renderer.to_string Html_renderer.render multi_render_data)

View File

@ -18,14 +18,17 @@ let render_prog_box annotated_prog = Jingoo.Jg_types.(Renderer.AnnotAsm.(
));
("instr_asm", box_string row.instr_asm);
("instr_events", (List.map (fun event ->
let typ, id, bound = Renderer.(match event with
| BoxStart(id, bound) -> "start", id, bound
| BoxEnd(id, bound) -> "end", id, bound
let typ, id, bound, data = Renderer.(match event with
| BoxStart(id, bound, data) -> "start", id, bound, data
| BoxEnd(id, bound, data) -> "end", id, bound, data
) in
[
("typ", box_string typ);
("id", box_int id);
("bound", box_string @@ render_addr bound);
("data", box_string @@ Format.sprintf "File %d, %d:%d"
data.box_file data.box_line data.box_col);
] |> box_obj)
row.instr_annot.Renderer.events)
|> box_list);
@ -36,11 +39,16 @@ let render_prog_box annotated_prog = Jingoo.Jg_types.(Renderer.AnnotAsm.(
|> box_list
))
(** [render render_data] renders the given [render_data] to a string. *)
let render render_data = Jingoo.(
let annotated_prog = Renderer.render_data_to_annotated_asm render_data in
let render_progs_box annotated_progs =
List.map render_prog_box annotated_progs
|> Jingoo.Jg_types.box_list
(** [render multi_render_data] renders the given [render_data] to a string. *)
let render multi_render_data = Jingoo.(
let annotated_progs = List.map (fun render_data ->
Renderer.render_data_to_annotated_asm render_data) multi_render_data in
let models = [
("subroutines", render_prog_box annotated_prog);
("progs", render_progs_box annotated_progs);
] in
Jg_template.from_file "src/render_html.jingoo" ~models:models
)

View File

@ -6,6 +6,18 @@
body {
font-family: "mono";
font-size: 12px;
background-color: #f7f6fd;
}
.prog_container {
display: flex;
justify-content: space-around;
}
.prog {
background-color: white;
padding: 15px;
border: 1px solid #9584ff;
}
.subroutine {
@ -28,40 +40,48 @@
.instr_bytes {
color: grey;
}
.instr_box {
background-color: #ffffb4;
}
</style>
</head>
<body>
{% for subroutine in subroutines %}
<div class="subroutine">
<div class="sub_headline">
<span class="addr">{{ subroutine.sub_addr }}</span>
<span class="sub_section">[{{ subroutine.sub_section }}]</span>
<span class="sub_name">&lt;{{ subroutine.sub_name }}&gt;</span>:
</div>
<div class="sub_body">
{% for row in subroutine.sub_asm %}
{% for event in row.instr_events %}
{% if event.typ == "start" %}
<div class="instr_box" id="instr_box_{{ event.id }}">
{% endif %}
{% endfor %}
<div class="sub_instr">
<span class="addr instr_addr">{{ row.instr_addr }}</span>
<span class="instr_bytes"><pre>{{ row.instr_bytes }}</pre></span>
<span class="instr_asm">{{ row.instr_asm }}</span>
<div class="prog_container">
{% for subroutines in progs %}
<div class="prog">
{% for subroutine in subroutines %}
<div class="subroutine">
<div class="sub_headline">
<span class="addr">{{ subroutine.sub_addr }}</span>
<span class="sub_section">[{{ subroutine.sub_section }}]</span>
<span class="sub_name">&lt;{{ subroutine.sub_name }}&gt;</span>:
</div>
<div class="sub_body">
{% for row in subroutine.sub_asm %}
{% for event in row.instr_events %}
{% if event.typ == "start" %}
<div class="instr_box" id="instr_box_{{ event.id }}"
title="{{ event.data }}"
>
{% endif %}
{% endfor %}
<div class="sub_instr">
<span class="addr instr_addr">{{ row.instr_addr }}</span>
<span class="instr_bytes"><pre>{{ row.instr_bytes }}</pre></span>
<span class="instr_asm">{{ row.instr_asm }}</span>
</div>
{% for event in row.instr_events %}
{% if event.typ == "end" %}
</div> <!-- END instr_box_{{ event.id }} -->
{% endif %}
{% endfor %}
{% endfor %}
</div>
{% for event in row.instr_events %}
{% if event.typ == "end" %}
</div> <!-- END instr_box_{{ event.id }} -->
{% endif %}
{% endfor %}
{% endfor %}
</div>
{% endfor %}
</div>
{% endfor %}
</div>
</body>
</html>

View File

@ -7,8 +7,14 @@
module RawAsm = Asm_info.NoAnnot
type addr_range_t = RawAsm.addr_t * RawAsm.addr_t
type box_data_t = {
box_file : int;
box_line : int;
box_col : int;
}
type addr_range_tag_t = int
type tag_addr_range_t = TaggedRange of addr_range_tag_t * addr_range_t
type tag_addr_range_t = TaggedRange of addr_range_tag_t * addr_range_t *
box_data_t
type render_data_t = {
render_prog : RawAsm.asm_info_t ;
@ -16,9 +22,11 @@ type render_data_t = {
render_prev_address : RawAsm.addr_t RawAsm.AddrMap.t
}
type multi_render_data_t = render_data_t list
type render_box_event_t =
BoxStart of addr_range_tag_t * RawAsm.addr_t
| BoxEnd of addr_range_tag_t * RawAsm.addr_t
BoxStart of addr_range_tag_t * RawAsm.addr_t * box_data_t
| BoxEnd of addr_range_tag_t * RawAsm.addr_t * box_data_t
type asm_annot_type = {
events : render_box_event_t list
@ -52,24 +60,33 @@ let init_render_data prog =
(** [add_box render_data range] adds a box around an address range, inclusive
of both bounds, in [render_data] and returns the new render data and the
newly inserted element's id *)
let add_box render_data range : render_data_t * int =
let add_box render_data range opt_data : render_data_t * int =
let elt_id = (match render_data.render_boxes with
| [] -> 0
| TaggedRange(prev_id, _)::_ -> prev_id + 1) in
| TaggedRange(prev_id, _, _)::_ -> prev_id + 1) in
let data = (match opt_data with
| Some data -> data
| None -> {
box_file = 0;
box_line = 0;
box_col = 0
})
in
{
render_data with
render_boxes = (TaggedRange(elt_id, range)) :: render_data.render_boxes
render_boxes =
(TaggedRange(elt_id, range, data)) :: render_data.render_boxes
}, elt_id
(** Same as [add_box], with an included start, excluded end for range. *)
let add_box_excl render_data (addr_beg, addr_end) =
let add_box_excl render_data (addr_beg, addr_end) opt_data =
(match RawAsm.AddrMap.find_opt addr_end render_data.render_prev_address with
| None -> Format.eprintf "Box end address %x not found, ignoring box."
addr_end ;
raise Not_found
| Some end_bound -> add_box render_data (addr_beg, end_bound)
| Some end_bound -> add_box render_data (addr_beg, end_bound) opt_data
)
(** [to_file renderer render_data path] renders the given [render_data] to a
@ -81,17 +98,17 @@ let to_file renderer render_data path =
|> output_string handle ;
close_out handle
(** [to_string renderer render_data] renders the given [render_data] to a
returned string using the provided specific renderer.
This function is provided for unification and clarity, but is an alias for
[renderer].
(** [to_string renderer multi_render_data] renders the given
[multi_render_data] to a returned string using the provided specific
renderer. This function is provided for unification and clarity, but is an
alias for [renderer].
*)
let to_string renderer render_data =
renderer render_data
let to_string renderer multi_render_data =
renderer multi_render_data
let extract_event_addr box_event = match box_event with
| BoxStart(_, addr) -> addr
| BoxEnd(_, addr) -> addr
| BoxStart(_, addr, _) -> addr
| BoxEnd(_, addr, _) -> addr
(** [boxes_to_events render_data] converts the list of boxes of `render_data`
to a list of events, that is, an address-ordered list of
@ -103,16 +120,16 @@ let boxes_to_events render_data =
| 0 -> (match e1, e2 with
| BoxEnd(_), BoxStart(_) -> -1
| BoxStart(_), BoxEnd(_) -> 1
| BoxStart(id1, _), BoxStart(id2, _) -> compare id1 id2
| BoxEnd(id1, _), BoxEnd(id2, _) -> compare id1 id2
| BoxStart(id1, _, _), BoxStart(id2, _, _) -> compare id1 id2
| BoxEnd(id1, _, _), BoxEnd(id2, _, _) -> compare id1 id2
)
| n -> n
in
let unordered_events = List.fold_left
(fun accu (TaggedRange(elt_id, (range_beg, range_end))) ->
(BoxStart(elt_id, range_beg))
:: (BoxEnd(elt_id, range_end))
(fun accu (TaggedRange(elt_id, (range_beg, range_end), data)) ->
(BoxStart(elt_id, range_beg, data))
:: (BoxEnd(elt_id, range_end, data))
:: accu
)
[]