perf probe: Support comp_dir to find an absolute source path
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH 2/3 perf probe: Support comp_dir to find an absolute source path
Gcc generates DW_AT_comp_dir and stores relative source path if building kernel without O= option. In that case, perf probe --line sometimes doesn't work without --source option, because it tries to access relative source path.
This adds DW_AT_comp_dir support to perf probe for finding an absolute source path when no --source option.
---
tools/perf/util/probe-event.c | 34 ++++++++++++++++++++++------------ tools/perf/util/probe-event.h | 1 + tools/perf/util/probe-finder.c | 21 +++++++++++++++++++++ 3 files changed, 44 insertions(+), 12 deletions(-)
tools/perf/util/probe-event.c +22 -12
@@ -201,28 +201,38 @@ static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev,* a newly allocated path on success. * Return 0 if file was found and readable, -errno otherwise. */ -static int get_real_path (const char *raw_path,char **new_path) +static int get_real_path (const char *raw_path,const char *comp_dir, +char **new_path) { -if (!symbol_conf.source_prefix) { -if (access (raw_path,R_OK ) ==0 ) { - *new_path =strdup (raw_path); -return 0 ; - }else -return -errno; +const char *prefix = symbol_conf.source_prefix; + +if (!prefix) { +if (raw_path[0 ] !='/' && comp_dir) +/* If not an absolute path, try to use comp_dir */ + prefix = comp_dir; +else { +if (access (raw_path,R_OK ) ==0 ) { + *new_path =strdup (raw_path); +return 0 ; + }else +return -errno; + } } - *new_path =malloc ((strlen (symbol_conf.source_prefix) + -strlen (raw_path) +2 )); + *new_path =malloc ((strlen (prefix) +strlen (raw_path) +2 ));if (!*new_path)return -ENOMEM ;for (;;) { -sprintf (*new_path,"%s/%s" , symbol_conf.source_prefix, - raw_path); +sprintf (*new_path,"%s/%s" , prefix, raw_path);if (access (*new_path,R_OK ) ==0 )return 0 ; +if (!symbol_conf.source_prefix) +/* In case of searching comp_dir, don't retry */ +return -errno; +switch (errno) {case ENAMETOOLONG :case ENOENT :
@@ -318,7 +328,7 @@ int show_line_range(struct line_range *lr)/* Convert source file path */ tmp = lr->path; - ret =get_real_path (tmp, &lr->path); + ret =get_real_path (tmp, lr->comp_dir, &lr->path);free (tmp);/* Free old path */ if (ret <0 ) {pr_warning ("Failed to find source file. (%d)\n" , ret);
tools/perf/util/probe-event.h +1 -0
@@ -86,6 +86,7 @@ struct line_range {int end;/* End line number */ int offset;/* Start line offset */ char *path;/* Real path name */ +char *comp_dir;/* Compile directory */ struct list_head line_list;/* Visible lines */ };
tools/perf/util/probe-finder.c +21 -0
@@ -144,6 +144,15 @@ static const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname)return src; } +/* Get DW_AT_comp_dir (should be NULL with older gcc) */ +static const char *cu_get_comp_dir (Dwarf_Die *cu_die) +{ +Dwarf_Attribute attr; +if (dwarf_attr (cu_die, DW_AT_comp_dir, &attr) ==NULL ) +return NULL ; +return dwarf_formstring (&attr); +} +/* Compare diename and tname */ static bool die_compare_name (Dwarf_Die *dw_die,const char *tname) {
@@ -1374,6 +1383,7 @@ int find_line_range(int fd, struct line_range *lr)size_t cuhl;Dwarf_Die *diep;Dwarf *dbg; +const char *comp_dir; dbg =dwarf_begin (fd,DWARF_C_READ );if (!dbg) {
@@ -1409,6 +1419,17 @@ int find_line_range(int fd, struct line_range *lr) } off = noff; } + +/* Store comp_dir */ +if (lf.found) { + comp_dir =cu_get_comp_dir (&lf.cu_die); +if (comp_dir) { + lr->comp_dir =strdup (comp_dir); +if (!lr->comp_dir) + ret = -ENOMEM ; + } + } +pr_debug ("path: %s\n" , lr->path);dwarf_end (dbg);
Commit-ID: 6a330a3c8a648916b3c6bda79a78c38ac093af17 Gitweb: http://git.kernel.org/tip/6a330a3c8a648916b3c6bda79a78c38ac093af17 Author: Masami Hiramatsu <[email protected]> AuthorDate: Fri, 9 Jul 2010 18:29:11 +0900 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Fri, 16 Jul 2010 11:48:09 -0300
perf probe: Support comp_dir to find an absolute source path
Gcc generates DW_AT_comp_dir and stores relative source path if building kernel without O= option. In that case, perf probe --line sometimes doesn't work without --source option, because it tries to access relative source path.
This adds DW_AT_comp_dir support to perf probe for finding an absolute source path when no --source option.
LKML-Reference: <[email protected]>
--- tools/perf/util/probe-event.c | 34 ++++++++++++++++++++++------------ tools/perf/util/probe-event.h | 1 + tools/perf/util/probe-finder.c | 21 +++++++++++++++++++++ 3 files changed, 44 insertions(+), 12 deletions(-)
tools/perf/util/probe-event.c +22 -12
@@ -201,28 +201,38 @@ static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev,* a newly allocated path on success. * Return 0 if file was found and readable, -errno otherwise. */ -static int get_real_path (const char *raw_path,char **new_path) +static int get_real_path (const char *raw_path,const char *comp_dir, +char **new_path) { -if (!symbol_conf.source_prefix) { -if (access (raw_path,R_OK ) ==0 ) { - *new_path =strdup (raw_path); -return 0 ; - }else -return -errno; +const char *prefix = symbol_conf.source_prefix; + +if (!prefix) { +if (raw_path[0 ] !='/' && comp_dir) +/* If not an absolute path, try to use comp_dir */ + prefix = comp_dir; +else { +if (access (raw_path,R_OK ) ==0 ) { + *new_path =strdup (raw_path); +return 0 ; + }else +return -errno; + } } - *new_path =malloc ((strlen (symbol_conf.source_prefix) + -strlen (raw_path) +2 )); + *new_path =malloc ((strlen (prefix) +strlen (raw_path) +2 ));if (!*new_path)return -ENOMEM ;for (;;) { -sprintf (*new_path,"%s/%s" , symbol_conf.source_prefix, - raw_path); +sprintf (*new_path,"%s/%s" , prefix, raw_path);if (access (*new_path,R_OK ) ==0 )return 0 ; +if (!symbol_conf.source_prefix) +/* In case of searching comp_dir, don't retry */ +return -errno; +switch (errno) {case ENAMETOOLONG :case ENOENT :
@@ -318,7 +328,7 @@ int show_line_range(struct line_range *lr)/* Convert source file path */ tmp = lr->path; - ret =get_real_path (tmp, &lr->path); + ret =get_real_path (tmp, lr->comp_dir, &lr->path);free (tmp);/* Free old path */ if (ret <0 ) {pr_warning ("Failed to find source file. (%d)\n" , ret);
tools/perf/util/probe-event.h +1 -0
@@ -86,6 +86,7 @@ struct line_range {int end;/* End line number */ int offset;/* Start line offset */ char *path;/* Real path name */ +char *comp_dir;/* Compile directory */ struct list_head line_list;/* Visible lines */ };
tools/perf/util/probe-finder.c +21 -0
@@ -144,6 +144,15 @@ static const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname)return src; } +/* Get DW_AT_comp_dir (should be NULL with older gcc) */ +static const char *cu_get_comp_dir (Dwarf_Die *cu_die) +{ +Dwarf_Attribute attr; +if (dwarf_attr (cu_die, DW_AT_comp_dir, &attr) ==NULL ) +return NULL ; +return dwarf_formstring (&attr); +} +/* Compare diename and tname */ static bool die_compare_name (Dwarf_Die *dw_die,const char *tname) {
@@ -1374,6 +1383,7 @@ int find_line_range(int fd, struct line_range *lr)size_t cuhl;Dwarf_Die *diep;Dwarf *dbg; +const char *comp_dir; dbg =dwarf_begin (fd,DWARF_C_READ );if (!dbg) {
@@ -1409,6 +1419,17 @@ int find_line_range(int fd, struct line_range *lr) } off = noff; } + +/* Store comp_dir */ +if (lf.found) { + comp_dir =cu_get_comp_dir (&lf.cu_die); +if (comp_dir) { + lr->comp_dir =strdup (comp_dir); +if (!lr->comp_dir) + ret = -ENOMEM ; + } + } +pr_debug ("path: %s\n" , lr->path);dwarf_end (dbg);
PATCH 3/3 perf probe: Fix the logic of die_compare_name
In reply to a message not in the archiveInvert the return value of die_compare_name(), because it returns a 'bool' result which should be expeced true if the die's name is same as compared string.
---
tools/perf/util/probe-finder.c | 14 +++++++------- 1 files changed, 7 insertions(+), 7 deletions(-)
tools/perf/util/probe-finder.c +7 -7
@@ -158,7 +158,7 @@ static bool die_compare_name(Dwarf_Die *dw_die, const char *tname) {const char *name; name =dwarf_diename (dw_die); -return name ?strcmp (tname, name) :-1 ; +return name ? (strcmp (tname, name) ==0 ) : false; }/* Get type die, but skip qualifiers and typedef */
@@ -329,7 +329,7 @@ static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data) tag =dwarf_tag (die_mem);if ((tag == DW_TAG_formal_parameter || tag == DW_TAG_variable) && - (die_compare_name (die_mem, name) ==0 )) +die_compare_name (die_mem, name))return DIE_FIND_CB_FOUND ;return DIE_FIND_CB_CONTINUE ;
@@ -348,7 +348,7 @@ static int __die_find_member_cb(Dwarf_Die *die_mem, void *data)const char *name = data;if ((dwarf_tag (die_mem) == DW_TAG_member) && - (die_compare_name (die_mem, name) ==0 )) +die_compare_name (die_mem, name))return DIE_FIND_CB_FOUND ;return DIE_FIND_CB_SIBLING ;
@@ -506,8 +506,8 @@ static int convert_variable_type(Dwarf_Die *vr_die,return -ENOMEM ; } } -if (die_compare_name (&type,"char" ) !=0 && -die_compare_name (&type,"unsigned char" ) !=0 ) { +if (!die_compare_name (&type,"char" ) && + !die_compare_name (&type,"unsigned char" )) {pr_warning ("Failed to cast into string: " "%s is not (unsigned) char *." ,dwarf_diename (vr_die));
@@ -1017,7 +1017,7 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)/* Check tag and diename */ if (dwarf_tag (sp_die) != DW_TAG_subprogram || -die_compare_name (sp_die, pp->function) !=0 ) + !die_compare_name (sp_die, pp->function))return DWARF_CB_OK ; pf->fname =dwarf_decl_file (sp_die);
@@ -1340,7 +1340,7 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data)struct line_range *lr = lf->lr;if (dwarf_tag (sp_die) == DW_TAG_subprogram && -die_compare_name (sp_die, lr->function) ==0 ) { +die_compare_name (sp_die, lr->function)) { lf->fname =dwarf_decl_file (sp_die);dwarf_decl_line (sp_die, &lr->offset);pr_debug ("fname: %s, lineno:%d\n" , lf->fname, lr->offset);
[tip:perf/core] perf probe: Fix the logic of die_compare_name
Commit-ID: 8217563359878d11ef03cc76bc935ada89d73efd Gitweb: http://git.kernel.org/tip/8217563359878d11ef03cc76bc935ada89d73efd Author: Masami Hiramatsu <[email protected]> AuthorDate: Fri, 9 Jul 2010 18:29:17 +0900 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Fri, 16 Jul 2010 11:48:34 -0300
perf probe: Fix the logic of die_compare_name
Invert the return value of die_compare_name(), because it returns a 'bool' result which should be expeced true if the die's name is same as compared string.
LKML-Reference: <[email protected]>
--- tools/perf/util/probe-finder.c | 14 +++++++------- 1 files changed, 7 insertions(+), 7 deletions(-)
tools/perf/util/probe-finder.c +7 -7
@@ -158,7 +158,7 @@ static bool die_compare_name(Dwarf_Die *dw_die, const char *tname) {const char *name; name =dwarf_diename (dw_die); -return name ?strcmp (tname, name) :-1 ; +return name ? (strcmp (tname, name) ==0 ) : false; }/* Get type die, but skip qualifiers and typedef */
@@ -329,7 +329,7 @@ static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data) tag =dwarf_tag (die_mem);if ((tag == DW_TAG_formal_parameter || tag == DW_TAG_variable) && - (die_compare_name (die_mem, name) ==0 )) +die_compare_name (die_mem, name))return DIE_FIND_CB_FOUND ;return DIE_FIND_CB_CONTINUE ;
@@ -348,7 +348,7 @@ static int __die_find_member_cb(Dwarf_Die *die_mem, void *data)const char *name = data;if ((dwarf_tag (die_mem) == DW_TAG_member) && - (die_compare_name (die_mem, name) ==0 )) +die_compare_name (die_mem, name))return DIE_FIND_CB_FOUND ;return DIE_FIND_CB_SIBLING ;
@@ -506,8 +506,8 @@ static int convert_variable_type(Dwarf_Die *vr_die,return -ENOMEM ; } } -if (die_compare_name (&type,"char" ) !=0 && -die_compare_name (&type,"unsigned char" ) !=0 ) { +if (!die_compare_name (&type,"char" ) && + !die_compare_name (&type,"unsigned char" )) {pr_warning ("Failed to cast into string: " "%s is not (unsigned) char *." ,dwarf_diename (vr_die));
@@ -1017,7 +1017,7 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)/* Check tag and diename */ if (dwarf_tag (sp_die) != DW_TAG_subprogram || -die_compare_name (sp_die, pp->function) !=0 ) + !die_compare_name (sp_die, pp->function))return DWARF_CB_OK ; pf->fname =dwarf_decl_file (sp_die);
@@ -1340,7 +1340,7 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data)struct line_range *lr = lf->lr;if (dwarf_tag (sp_die) == DW_TAG_subprogram && -die_compare_name (sp_die, lr->function) ==0 ) { +die_compare_name (sp_die, lr->function)) { lf->fname =dwarf_decl_file (sp_die);dwarf_decl_line (sp_die, &lr->offset);pr_debug ("fname: %s, lineno:%d\n" , lf->fname, lr->offset);