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 let box_end = Z.to_int @@ reg_ahead.Dwarf.lnr_address in
Format.eprintf "Add box %x -- %x@." box_start box_end ; Format.eprintf "Add box %x -- %x@." box_start box_end ;
let n_render_data, _ = Renderer.add_box_excl 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) n_render_data)
cur_render_data reg_list) cur_render_data reg_list)
render_data render_data
@ -80,10 +86,12 @@ let _ =
line_info ; line_info ;
) elf_handles ; ) 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 render_data = Renderer.init_render_data asm in
let line_info = static_info.ds_evaluated_line_info in let line_info = static_info.ds_evaluated_line_info in
let boxed_render_data = add_line_boxes render_data line_info in let boxed_render_data = add_line_boxes render_data line_info in
Format.printf "%s@." boxed_render_data
(Renderer.to_string Html_renderer.render boxed_render_data) ) elf_handles in
) elf_handles;
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_asm", box_string row.instr_asm);
("instr_events", (List.map (fun event -> ("instr_events", (List.map (fun event ->
let typ, id, bound = Renderer.(match event with let typ, id, bound, data = Renderer.(match event with
| BoxStart(id, bound) -> "start", id, bound | BoxStart(id, bound, data) -> "start", id, bound, data
| BoxEnd(id, bound) -> "end", id, bound | BoxEnd(id, bound, data) -> "end", id, bound, data
) in ) in
[ [
("typ", box_string typ); ("typ", box_string typ);
("id", box_int id); ("id", box_int id);
("bound", box_string @@ render_addr bound); ("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) ] |> box_obj)
row.instr_annot.Renderer.events) row.instr_annot.Renderer.events)
|> box_list); |> box_list);
@ -36,11 +39,16 @@ let render_prog_box annotated_prog = Jingoo.Jg_types.(Renderer.AnnotAsm.(
|> box_list |> box_list
)) ))
(** [render render_data] renders the given [render_data] to a string. *) let render_progs_box annotated_progs =
let render render_data = Jingoo.( List.map render_prog_box annotated_progs
let annotated_prog = Renderer.render_data_to_annotated_asm render_data in |> 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 = [ let models = [
("subroutines", render_prog_box annotated_prog); ("progs", render_progs_box annotated_progs);
] in ] in
Jg_template.from_file "src/render_html.jingoo" ~models:models Jg_template.from_file "src/render_html.jingoo" ~models:models
) )

View file

@ -6,6 +6,18 @@
body { body {
font-family: "mono"; font-family: "mono";
font-size: 12px; 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 { .subroutine {
@ -28,40 +40,48 @@
.instr_bytes { .instr_bytes {
color: grey; color: grey;
} }
.instr_box { .instr_box {
background-color: #ffffb4; background-color: #ffffb4;
} }
</style> </style>
</head> </head>
<body> <body>
{% for subroutine in subroutines %} <div class="prog_container">
<div class="subroutine"> {% for subroutines in progs %}
<div class="sub_headline"> <div class="prog">
<span class="addr">{{ subroutine.sub_addr }}</span> {% for subroutine in subroutines %}
<span class="sub_section">[{{ subroutine.sub_section }}]</span> <div class="subroutine">
<span class="sub_name">&lt;{{ subroutine.sub_name }}&gt;</span>: <div class="sub_headline">
</div> <span class="addr">{{ subroutine.sub_addr }}</span>
<div class="sub_body"> <span class="sub_section">[{{ subroutine.sub_section }}]</span>
{% for row in subroutine.sub_asm %} <span class="sub_name">&lt;{{ subroutine.sub_name }}&gt;</span>:
{% for event in row.instr_events %} </div>
{% if event.typ == "start" %} <div class="sub_body">
<div class="instr_box" id="instr_box_{{ event.id }}"> {% for row in subroutine.sub_asm %}
{% endif %} {% for event in row.instr_events %}
{% endfor %} {% if event.typ == "start" %}
<div class="sub_instr"> <div class="instr_box" id="instr_box_{{ event.id }}"
<span class="addr instr_addr">{{ row.instr_addr }}</span> title="{{ event.data }}"
<span class="instr_bytes"><pre>{{ row.instr_bytes }}</pre></span> >
<span class="instr_asm">{{ row.instr_asm }}</span> {% 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> </div>
{% for event in row.instr_events %}
{% if event.typ == "end" %}
</div> <!-- END instr_box_{{ event.id }} -->
{% endif %}
{% endfor %}
{% endfor %}
</div> </div>
{% endfor %}
</div> </div>
{% endfor %} {% endfor %}
</div>
</body> </body>
</html> </html>

View file

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