2023-03-24 20:05 UTC-0700 ~ Stanislav Fomichev <sdf@xxxxxxxxxx> > On 03/24, Quentin Monnet wrote: >> We support dumping the control flow graph of loaded programs to the DOT >> format with bpftool, but so far this feature wouldn't display the source >> code lines available through BTF along with the eBPF bytecode. Let's add >> support for these annotations, to make it easier to read the graph. > >> In prog.c, we move the call to dump_xlated_cfg() in order to pass and >> use the full struct dump_data, instead of creating a minimal one in >> draw_bb_node(). > >> We pass the pointer to this struct down to dump_xlated_for_graph() in >> xlated_dumper.c, where most of the logics is added. We deal with BTF >> mostly like we do for plain or JSON output, except that we cannot use a >> "nr_skip" value to skip a given number of linfo records (we don't >> process the BPF instructions linearly, and apart from the root of the >> graph we don't know how many records we should skip, so we just store >> the last linfo and make sure the new one we find is different before >> printing it). > >> When printing the source instructions to the label of a DOT graph node, >> there are a few subtleties to address. We want some special newline >> markers, and there are some characters that we must escape. To deal with >> them, we introduce a new dedicated function btf_dump_linfo_dotlabel() in >> btf_dumper.c. We'll reuse this function in a later commit to format the >> filepath, line, and column references as well. > >> Signed-off-by: Quentin Monnet <quentin@xxxxxxxxxxxxx> >> --- >> tools/bpf/bpftool/btf_dumper.c | 34 +++++++++++++++++++++++++++++++ >> tools/bpf/bpftool/cfg.c | 23 +++++++++------------ >> tools/bpf/bpftool/cfg.h | 4 +++- >> tools/bpf/bpftool/main.h | 2 ++ >> tools/bpf/bpftool/prog.c | 17 +++++++--------- >> tools/bpf/bpftool/xlated_dumper.c | 32 ++++++++++++++++++++++++++++- >> 6 files changed, 87 insertions(+), 25 deletions(-) > >> diff --git a/tools/bpf/bpftool/btf_dumper.c >> b/tools/bpf/bpftool/btf_dumper.c >> index e7f6ec3a8f35..504d7c75cc27 100644 >> --- a/tools/bpf/bpftool/btf_dumper.c >> +++ b/tools/bpf/bpftool/btf_dumper.c >> @@ -821,3 +821,37 @@ void btf_dump_linfo_json(const struct btf *btf, >> BPF_LINE_INFO_LINE_COL(linfo->line_col)); >> } >> } >> + >> +static void dotlabel_puts(const char *s) >> +{ >> + FILE *stream = stdout; >> + >> + for (; *s; ++s) { >> + switch (*s) { >> + case '\\': >> + case '"': >> + case '{': >> + case '}': >> + case '>': >> + case '|': >> + fputc('\\', stream); >> + __fallthrough; >> + default: >> + fputc(*s, stream); >> + } > > nit: optionally, if you're going to respin, maybe do putchar instead > of fputc + stdout? (not sure why you're doing fputs) Right, no particular reason, I'll switch to putchar() and respin. Thanks for the review! Quentin