Open honggyukim opened 6 years ago
Why do you think DWARF is difficult for kernel than tag files?
i think sometimes it may be difficult to download debug information supported kernel depending on the environments. One more thing is that if the other user downloads already recorded data from somewhere else, they cannot find the symbol to jump to the source code unless the uftrace.data
is fully self-contained.
Did you mean 'self-contained' by having all source codes? Anyway source could be changed or not exist whether it uses debug info or tag file. So it's hard to guarantee the correctness of the source.
I've just pushed review/dwarf-line-v1 branch including source location info. The tui command shows the info for each graph node.
I mean that we also have to include source location of kernel functions in that case.
Even if we include the source location of kernel functions, the path may not be exactly the same, so I wanted to provide a way to jump to the source using the tags
file (in vim).
I'm not sure about emacs yet but in vim, the editor can open the source with vim -t (function_name)
.
Although it doesn't use the tag files, I implemented it to use debug info using O
key. It's based on the "review/dwarf-line-v3" branch. Please check below patch:
diff --git a/cmds/tui.c b/cmds/tui.c
index c27b3d94..90ef093f 100644
--- a/cmds/tui.c
+++ b/cmds/tui.c
@@ -7,6 +7,8 @@
#include <ncurses.h>
#include <locale.h>
#include <inttypes.h>
+#include <unistd.h>
+#include <sys/wait.h>
#include "uftrace.h"
#include "version.h"
@@ -68,6 +70,7 @@ struct tui_window_ops {
void (*display)(struct tui_window *win, void *node);
bool (*search)(struct tui_window *win, void *node, char *str);
bool (*longest_child)(struct tui_window *win, void *node);
+ struct debug_location * (*location)(struct tui_window *win, void *node);
};
struct tui_window {
@@ -1020,7 +1023,7 @@ static void win_footer_graph(struct tui_window *win,
else {
struct debug_location *dloc;
- dloc = find_file_line(&sess->symtabs, node->n.addr);
+ dloc = win->ops->location(win, win->curr);
if (dloc != NULL && dloc->file != NULL) {
snprintf(buf, COLS, "uftrace graph: %s [line:%d]",
@@ -1183,6 +1186,16 @@ static bool win_longest_child_graph(struct tui_window *win, void *node)
return true;
}
+static struct debug_location *win_location_graph(struct tui_window *win,
+ void *node)
+{
+ struct tui_graph *graph = (struct tui_graph *)win;
+ struct tui_graph_node *curr = node;
+ struct uftrace_session *sess = graph->ug.sess;
+
+ return find_file_line(&sess->symtabs, curr->n.addr);
+}
+
static const struct tui_window_ops graph_ops = {
.prev = win_prev_graph,
.next = win_next_graph,
@@ -1199,6 +1212,7 @@ static const struct tui_window_ops graph_ops = {
.display = win_display_graph,
.search = win_search_graph,
.longest_child = win_longest_child_graph,
+ .location = win_location_graph,
};
/* some default (no-op) window operations */
@@ -1325,6 +1339,24 @@ static void win_display_report(struct tui_window *win, void *node)
printw("%*s", COLS - width, "");
}
+static struct debug_location *win_location_report(struct tui_window *win,
+ void *node)
+{
+ struct tui_report_node *curr = node;
+ struct tui_graph_node *gnode;
+ struct uftrace_session *sess;
+ struct debug_location *dloc;
+
+ list_for_each_entry(gnode, &curr->head, link) {
+ sess = gnode->graph->sess;
+ dloc = find_file_line(&sess->symtabs, gnode->n.addr);
+
+ if (dloc != NULL && dloc->file != NULL)
+ return dloc;
+ }
+ return NULL;
+}
+
static const struct tui_window_ops report_ops = {
.prev = win_prev_report,
.next = win_next_report,
@@ -1337,6 +1369,7 @@ static const struct tui_window_ops report_ops = {
.footer = win_footer_report,
.display = win_display_report,
.search = win_search_report,
+ .location = win_location_report,
};
/* per-window operations for list window */
@@ -2101,6 +2134,52 @@ static bool tui_window_longest_child(struct tui_window *win)
return win->ops->longest_child(win, win->curr);
}
+static bool tui_window_open_editor(struct tui_window *win)
+{
+ struct debug_location *dloc;
+ const char *editor = getenv("EDITOR");
+ struct strv editor_strv;
+ int pid, status;
+
+ if (win->ops->location == NULL)
+ return false;
+
+ dloc = win->ops->location(win, win->curr);
+ if (dloc == NULL || dloc->file == NULL)
+ return false;
+
+ if (editor == NULL)
+ editor = "vi";
+
+ endwin();
+
+ strv_split(&editor_strv, editor, " ");
+ if (!strncmp(editor, "vi", 2) || !strncmp(editor, "emacs", 5)) {
+ char buf[16];
+
+ /* run 'vi +line file' */
+ snprintf(buf, sizeof(buf), "+%d", dloc->line);
+ strv_append(&editor_strv, buf);
+ strv_append(&editor_strv, dloc->file->name);
+ }
+ else {
+ /* I don't know what to do */
+ strv_append(&editor_strv, dloc->file->name);
+ }
+
+ pid = fork();
+ if (pid == 0) {
+ execvp(editor_strv.p[0], editor_strv.p);
+ exit(1);
+ }
+
+ waitpid(pid, &status, 0);
+ strv_free(&editor_strv);
+
+ refresh();
+ return true;
+}
+
static void tui_window_help(void)
{
WINDOW *win;
@@ -2254,6 +2333,9 @@ static void tui_main_loop(struct opts *opts, struct ftrace_file_handle *handle)
full_redraw = true;
}
break;
+ case 'O':
+ full_redraw = tui_window_open_editor(win);
+ break;
case 'c':
full_redraw = tui_window_collapse(win);
break;
Superb! This is what I expected. Thanks for this great work!
One minor concern is that I think vim
would be better than vi
. In some environments, vi
is used only the limited features than vim
as far as I remember.
That's a choice for safety. If you want to use vim, you'd be better set it as EDITOR
Okay. It's okay then. Thanks!
If it's possible, I think we better add -c 'normal z.'
as an option to vi
to make the focus to the center of editor.
z. | Center the screen on the cursor |
---|---|
zt | Scroll the screen so the cursor is at the top |
zb | Scroll the screen so the cursor is at the bottom |
Hmm.. thinking it again. Let's leave it now. I think normal vi
may be smart enough to place the cursor. I will tell you if it's really needed.
There is a bug in the below execution sequence.
O
keyCould you please check check/tui-fix branch?
The above problem is gone with it. Thanks!
It'd be very useful if
tui
mode can open an editor and jump to the definition of the currently pointing function just likevim
oremacs
.Since the source location is not supported yet, we can simply provide the list of tag files generated by
ctags
orglobal
for example.Even if the source location is supported by dwarf info, it may be difficult to use it for kernel functions. So I think using the tag information can also be very useful.