Allow rendering of multiple files side by side
This commit is contained in:
parent
4583ad6a92
commit
caac87e70a
4 changed files with 111 additions and 58 deletions
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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"><{{ subroutine.sub_name }}></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"><{{ subroutine.sub_name }}></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>
|
||||
|
|
|
@ -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
|
||||
)
|
||||
[]
|
||||
|
|
Loading…
Reference in a new issue