You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
perf probe: Fix finder to find lines of given function
The commit ba28c59bc9 fixed a declaration
entry bug in probe_point_search_cb(). There are same bugs in line
finder and call_probe_finder(). This introduces a new dwarf utility
function to determine given DIE is a function definition, not
declaration.
Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Prashanth Nageshappa <prashanth@linux.vnet.ibm.com>
Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: yrl.pp-manager.tt@hitachi.com
Link: http://lkml.kernel.org/r/20120423032435.8737.80064.stgit@localhost.localdomain
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
committed by
Arnaldo Carvalho de Melo
parent
33e940a25d
commit
0dbb1cac1d
@@ -262,6 +262,21 @@ bool die_is_signed_type(Dwarf_Die *tp_die)
|
|||||||
ret == DW_ATE_signed_fixed);
|
ret == DW_ATE_signed_fixed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* die_is_func_def - Ensure that this DIE is a subprogram and definition
|
||||||
|
* @dw_die: a DIE
|
||||||
|
*
|
||||||
|
* Ensure that this DIE is a subprogram and NOT a declaration. This
|
||||||
|
* returns true if @dw_die is a function definition.
|
||||||
|
**/
|
||||||
|
bool die_is_func_def(Dwarf_Die *dw_die)
|
||||||
|
{
|
||||||
|
Dwarf_Attribute attr;
|
||||||
|
|
||||||
|
return (dwarf_tag(dw_die) == DW_TAG_subprogram &&
|
||||||
|
dwarf_attr(dw_die, DW_AT_declaration, &attr) == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* die_get_data_member_location - Get the data-member offset
|
* die_get_data_member_location - Get the data-member offset
|
||||||
* @mb_die: a DIE of a member of a data structure
|
* @mb_die: a DIE of a member of a data structure
|
||||||
@@ -392,6 +407,10 @@ static int __die_search_func_cb(Dwarf_Die *fn_die, void *data)
|
|||||||
{
|
{
|
||||||
struct __addr_die_search_param *ad = data;
|
struct __addr_die_search_param *ad = data;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Since a declaration entry doesn't has given pc, this always returns
|
||||||
|
* function definition entry.
|
||||||
|
*/
|
||||||
if (dwarf_tag(fn_die) == DW_TAG_subprogram &&
|
if (dwarf_tag(fn_die) == DW_TAG_subprogram &&
|
||||||
dwarf_haspc(fn_die, ad->addr)) {
|
dwarf_haspc(fn_die, ad->addr)) {
|
||||||
memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die));
|
memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die));
|
||||||
|
|||||||
@@ -38,6 +38,9 @@ extern int cu_find_lineinfo(Dwarf_Die *cudie, unsigned long addr,
|
|||||||
extern int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr,
|
extern int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr,
|
||||||
int (*callback)(Dwarf_Die *, void *), void *data);
|
int (*callback)(Dwarf_Die *, void *), void *data);
|
||||||
|
|
||||||
|
/* Ensure that this DIE is a subprogram and definition (not declaration) */
|
||||||
|
extern bool die_is_func_def(Dwarf_Die *dw_die);
|
||||||
|
|
||||||
/* Compare diename and tname */
|
/* Compare diename and tname */
|
||||||
extern bool die_compare_name(Dwarf_Die *dw_die, const char *tname);
|
extern bool die_compare_name(Dwarf_Die *dw_die, const char *tname);
|
||||||
|
|
||||||
|
|||||||
@@ -734,7 +734,7 @@ static int call_probe_finder(Dwarf_Die *sc_die, struct probe_finder *pf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* If not a real subprogram, find a real one */
|
/* If not a real subprogram, find a real one */
|
||||||
if (dwarf_tag(sc_die) != DW_TAG_subprogram) {
|
if (!die_is_func_def(sc_die)) {
|
||||||
if (!die_find_realfunc(&pf->cu_die, pf->addr, &pf->sp_die)) {
|
if (!die_find_realfunc(&pf->cu_die, pf->addr, &pf->sp_die)) {
|
||||||
pr_warning("Failed to find probe point in any "
|
pr_warning("Failed to find probe point in any "
|
||||||
"functions.\n");
|
"functions.\n");
|
||||||
@@ -980,12 +980,10 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
|
|||||||
struct dwarf_callback_param *param = data;
|
struct dwarf_callback_param *param = data;
|
||||||
struct probe_finder *pf = param->data;
|
struct probe_finder *pf = param->data;
|
||||||
struct perf_probe_point *pp = &pf->pev->point;
|
struct perf_probe_point *pp = &pf->pev->point;
|
||||||
Dwarf_Attribute attr;
|
|
||||||
|
|
||||||
/* Check tag and diename */
|
/* Check tag and diename */
|
||||||
if (dwarf_tag(sp_die) != DW_TAG_subprogram ||
|
if (!die_is_func_def(sp_die) ||
|
||||||
!die_compare_name(sp_die, pp->function) ||
|
!die_compare_name(sp_die, pp->function))
|
||||||
dwarf_attr(sp_die, DW_AT_declaration, &attr))
|
|
||||||
return DWARF_CB_OK;
|
return DWARF_CB_OK;
|
||||||
|
|
||||||
/* Check declared file */
|
/* Check declared file */
|
||||||
@@ -1474,7 +1472,7 @@ static int line_range_inline_cb(Dwarf_Die *in_die, void *data)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Search function from function name */
|
/* Search function definition from function name */
|
||||||
static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
|
static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
|
||||||
{
|
{
|
||||||
struct dwarf_callback_param *param = data;
|
struct dwarf_callback_param *param = data;
|
||||||
@@ -1485,7 +1483,7 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
|
|||||||
if (lr->file && strtailcmp(lr->file, dwarf_decl_file(sp_die)))
|
if (lr->file && strtailcmp(lr->file, dwarf_decl_file(sp_die)))
|
||||||
return DWARF_CB_OK;
|
return DWARF_CB_OK;
|
||||||
|
|
||||||
if (dwarf_tag(sp_die) == DW_TAG_subprogram &&
|
if (die_is_func_def(sp_die) &&
|
||||||
die_compare_name(sp_die, lr->function)) {
|
die_compare_name(sp_die, lr->function)) {
|
||||||
lf->fname = dwarf_decl_file(sp_die);
|
lf->fname = dwarf_decl_file(sp_die);
|
||||||
dwarf_decl_line(sp_die, &lr->offset);
|
dwarf_decl_line(sp_die, &lr->offset);
|
||||||
|
|||||||
Reference in New Issue
Block a user