public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Masami Hiramatsu <mhiramat@kernel.org>
To: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
Cc: acme@kernel.org, linux-kernel@vger.kernel.org,
	peterz@infradead.org, mingo@redhat.com,
	alexander.shishkin@linux.intel.com, wangnan0@huawei.com,
	hemant@linux.vnet.ibm.com, naveen.n.rao@linux.vnet.ibm.com
Subject: Re: [PATCH v2] perf probe: Move dwarf specific functions to dwarf-aux.c
Date: Tue, 30 Aug 2016 23:10:34 +0900	[thread overview]
Message-ID: <20160830231034.0bb2ed73a12e04ef7892fd91@kernel.org> (raw)
In-Reply-To: <1472546377-25612-1-git-send-email-ravi.bangoria@linux.vnet.ibm.com>

On Tue, 30 Aug 2016 14:09:37 +0530
Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> wrote:

> Move generic dwarf related functions from util/probe-finder.c to
> util/dwarf-aux.c. Functions name and their prototype are also
> changed accordingly. No functionality changes.

Great! 
Looks good to me :)

Acked-by: Masami Hiramatsu <mhiramat@kernel.org>

Thanks!

> 
> Suggested-by: Masami Hiramatsu <mhiramat@kernel.org>
> Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
> ---
> Changes in v2:
>   - Add comments about functions prototype and their usage
>   - Replace function parameter names with more generic names
> 
>  tools/perf/util/dwarf-aux.c    | 179 +++++++++++++++++++++++++++++++++++++++++
>  tools/perf/util/dwarf-aux.h    |   8 ++
>  tools/perf/util/probe-finder.c | 136 +------------------------------
>  3 files changed, 189 insertions(+), 134 deletions(-)
> 
> diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c
> index a347b19..faec899 100644
> --- a/tools/perf/util/dwarf-aux.c
> +++ b/tools/perf/util/dwarf-aux.c
> @@ -1085,3 +1085,182 @@ int die_get_var_range(Dwarf_Die *sp_die __maybe_unused,
>  	return -ENOTSUP;
>  }
>  #endif
> +
> +/*
> + * die_has_loclist - Check if DW_AT_location of @vr_die is a location list
> + * @vr_die: a variable DIE
> + */
> +static bool die_has_loclist(Dwarf_Die *vr_die)
> +{
> +	Dwarf_Attribute loc;
> +	int tag = dwarf_tag(vr_die);
> +
> +	if (tag != DW_TAG_formal_parameter &&
> +	    tag != DW_TAG_variable)
> +		return false;
> +
> +	return (dwarf_attr_integrate(vr_die, DW_AT_location, &loc) &&
> +		dwarf_whatform(&loc) == DW_FORM_sec_offset);
> +}
> +
> +/*
> + * die_is_optimized_target - Check if target program is compiled with
> + * optimization
> + * @cu_die: a CU DIE
> + *
> + * For any object in given CU whose DW_AT_location is a location list,
> + * target program is compiled with optimization. This is applicable to
> + * clang as well.
> + */
> +bool die_is_optimized_target(Dwarf_Die *cu_die)
> +{
> +	Dwarf_Die tmp_die;
> +
> +	if (die_has_loclist(cu_die))
> +		return true;
> +
> +	if (!dwarf_child(cu_die, &tmp_die) &&
> +	    die_is_optimized_target(&tmp_die))
> +		return true;
> +
> +	if (!dwarf_siblingof(cu_die, &tmp_die) &&
> +	    die_is_optimized_target(&tmp_die))
> +		return true;
> +
> +	return false;
> +}
> +
> +/*
> + * die_search_idx - Search index of given line address
> + * @lines: Line records of single CU
> + * @nr_lines: Number of @lines
> + * @addr: address we are looking for
> + * @idx: index to be set by this function (return value)
> + *
> + * Search for @addr by looping over every lines of CU. If address
> + * matches, set index of that line in @idx. Note that single source
> + * line can have multiple line records. i.e. single source line can
> + * have multiple index.
> + */
> +static bool die_search_idx(Dwarf_Lines *lines, unsigned long nr_lines,
> +			   Dwarf_Addr addr, unsigned long *idx)
> +{
> +	unsigned long i;
> +	Dwarf_Addr tmp;
> +
> +	for (i = 0; i < nr_lines; i++) {
> +		if (dwarf_lineaddr(dwarf_onesrcline(lines, i), &tmp))
> +			return false;
> +
> +		if (tmp == addr) {
> +			*idx = i;
> +			return true;
> +		}
> +	}
> +	return false;
> +}
> +
> +/*
> + * die_get_postprologue_addr - Search next address after function prologue
> + * @entrypc_idx: entrypc index
> + * @lines: Line records of single CU
> + * @nr_lines: Number of @lines
> + * @hignpc: high PC address of function
> + * @postprologue_addr: Next address after function prologue (return value)
> + *
> + * Look for prologue-end marker. If there is no explicit marker, return
> + * address of next line record or next source line.
> + */
> +static bool die_get_postprologue_addr(unsigned long entrypc_idx,
> +				      Dwarf_Lines *lines,
> +				      unsigned long nr_lines,
> +				      Dwarf_Addr highpc,
> +				      Dwarf_Addr *postprologue_addr)
> +{
> +	unsigned long i;
> +	int entrypc_lno, lno;
> +	Dwarf_Line *line;
> +	Dwarf_Addr addr;
> +	bool p_end;
> +
> +	/* entrypc_lno is actual source line number */
> +	line = dwarf_onesrcline(lines, entrypc_idx);
> +	if (dwarf_lineno(line, &entrypc_lno))
> +		return false;
> +
> +	for (i = entrypc_idx; i < nr_lines; i++) {
> +		line = dwarf_onesrcline(lines, i);
> +
> +		if (dwarf_lineaddr(line, &addr) ||
> +		    dwarf_lineno(line, &lno)    ||
> +		    dwarf_lineprologueend(line, &p_end))
> +			return false;
> +
> +		/* highpc is exclusive. [entrypc,highpc) */
> +		if (addr >= highpc)
> +			break;
> +
> +		/* clang supports prologue-end marker */
> +		if (p_end)
> +			break;
> +
> +		/* Actual next line in source */
> +		if (lno != entrypc_lno)
> +			break;
> +
> +		/*
> +		 * Single source line can have multiple line records.
> +		 * For Example,
> +		 *     void foo() { printf("hello\n"); }
> +		 * contains two line records. One points to declaration and
> +		 * other points to printf() line. Variable 'lno' won't get
> +		 * incremented in this case but 'i' will.
> +		 */
> +		if (i != entrypc_idx)
> +			break;
> +	}
> +
> +	dwarf_lineaddr(line, postprologue_addr);
> +	if (*postprologue_addr >= highpc)
> +		dwarf_lineaddr(dwarf_onesrcline(lines, i - 1),
> +			       postprologue_addr);
> +
> +	return true;
> +}
> +
> +/*
> + * die_skip_prologue - Use next address after prologue as probe location
> + * @sp_die: a subprogram DIE
> + * @cu_die: a CU DIE
> + * @entrypc: entrypc of the function
> + *
> + * Function prologue prepares stack and registers before executing function
> + * logic. When target program is compiled without optimization, function
> + * parameter information is only valid after prologue. When we probe entrypc
> + * of the function, and try to record function parameter, it contains
> + * garbage value.
> + */
> +void die_skip_prologue(Dwarf_Die *sp_die, Dwarf_Die *cu_die,
> +		       Dwarf_Addr *entrypc)
> +{
> +	size_t nr_lines = 0;
> +	unsigned long entrypc_idx = 0;
> +	Dwarf_Lines *lines = NULL;
> +	Dwarf_Addr postprologue_addr;
> +	Dwarf_Addr highpc;
> +
> +	if (dwarf_highpc(sp_die, &highpc))
> +		return;
> +
> +	if (dwarf_getsrclines(cu_die, &lines, &nr_lines))
> +		return;
> +
> +	if (!die_search_idx(lines, nr_lines, *entrypc, &entrypc_idx))
> +		return;
> +
> +	if (!die_get_postprologue_addr(entrypc_idx, lines, nr_lines,
> +				       highpc, &postprologue_addr))
> +		return;
> +
> +	*entrypc = postprologue_addr;
> +}
> diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h
> index dc0ce1a..8b6d2f8 100644
> --- a/tools/perf/util/dwarf-aux.h
> +++ b/tools/perf/util/dwarf-aux.h
> @@ -125,4 +125,12 @@ int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf);
>  /* Get the name and type of given variable DIE, stored as "type\tname" */
>  int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf);
>  int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf);
> +
> +/* Check if target program is compiled with optimization */
> +bool die_is_optimized_target(Dwarf_Die *cu_die);
> +
> +/* Use next address after prologue as probe location */
> +void die_skip_prologue(Dwarf_Die *sp_die, Dwarf_Die *cu_die,
> +		       Dwarf_Addr *entrypc);
> +
>  #endif
> diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
> index 945cf7a..72f1152 100644
> --- a/tools/perf/util/probe-finder.c
> +++ b/tools/perf/util/probe-finder.c
> @@ -901,138 +901,6 @@ static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
>  	return die_walk_lines(sp_die, probe_point_lazy_walker, pf);
>  }
>  
> -static bool var_has_loclist(Dwarf_Die *cu_die)
> -{
> -	Dwarf_Attribute loc;
> -	int tag = dwarf_tag(cu_die);
> -
> -	if (tag != DW_TAG_formal_parameter &&
> -	    tag != DW_TAG_variable)
> -		return false;
> -
> -	return (dwarf_attr_integrate(cu_die, DW_AT_location, &loc) &&
> -		dwarf_whatform(&loc) == DW_FORM_sec_offset);
> -}
> -
> -/*
> - * For any object in given CU whose DW_AT_location is a location list,
> - * target program is compiled with optimization.
> - */
> -static bool optimized_target(Dwarf_Die *cu_die)
> -{
> -	Dwarf_Die tmp_die;
> -
> -	if (var_has_loclist(cu_die))
> -		return true;
> -
> -	if (!dwarf_child(cu_die, &tmp_die) && optimized_target(&tmp_die))
> -		return true;
> -
> -	if (!dwarf_siblingof(cu_die, &tmp_die) && optimized_target(&tmp_die))
> -		return true;
> -
> -	return false;
> -}
> -
> -static bool get_entrypc_idx(Dwarf_Lines *lines, unsigned long nr_lines,
> -			    Dwarf_Addr pf_addr, unsigned long *entrypc_idx)
> -{
> -	unsigned long i;
> -	Dwarf_Addr addr;
> -
> -	for (i = 0; i < nr_lines; i++) {
> -		if (dwarf_lineaddr(dwarf_onesrcline(lines, i), &addr))
> -			return false;
> -
> -		if (addr == pf_addr) {
> -			*entrypc_idx = i;
> -			return true;
> -		}
> -	}
> -	return false;
> -}
> -
> -static bool get_postprologue_addr(unsigned long entrypc_idx,
> -				  Dwarf_Lines *lines,
> -				  unsigned long nr_lines,
> -				  Dwarf_Addr highpc,
> -				  Dwarf_Addr *postprologue_addr)
> -{
> -	unsigned long i;
> -	int entrypc_lno, lno;
> -	Dwarf_Line *line;
> -	Dwarf_Addr addr;
> -	bool p_end;
> -
> -	/* entrypc_lno is actual source line number */
> -	line = dwarf_onesrcline(lines, entrypc_idx);
> -	if (dwarf_lineno(line, &entrypc_lno))
> -		return false;
> -
> -	for (i = entrypc_idx; i < nr_lines; i++) {
> -		line = dwarf_onesrcline(lines, i);
> -
> -		if (dwarf_lineaddr(line, &addr) ||
> -		    dwarf_lineno(line, &lno)    ||
> -		    dwarf_lineprologueend(line, &p_end))
> -			return false;
> -
> -		/* highpc is exclusive. [entrypc,highpc) */
> -		if (addr >= highpc)
> -			break;
> -
> -		/* clang supports prologue-end marker */
> -		if (p_end)
> -			break;
> -
> -		/* Actual next line in source */
> -		if (lno != entrypc_lno)
> -			break;
> -
> -		/*
> -		 * Single source line can have multiple line records.
> -		 * For Example,
> -		 *     void foo() { printf("hello\n"); }
> -		 * contains two line records. One points to declaration and
> -		 * other points to printf() line. Variable 'lno' won't get
> -		 * incremented in this case but 'i' will.
> -		 */
> -		if (i != entrypc_idx)
> -			break;
> -	}
> -
> -	dwarf_lineaddr(line, postprologue_addr);
> -	if (*postprologue_addr >= highpc)
> -		dwarf_lineaddr(dwarf_onesrcline(lines, i - 1),
> -			       postprologue_addr);
> -
> -	return true;
> -}
> -
> -static void __skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf)
> -{
> -	size_t nr_lines = 0;
> -	unsigned long entrypc_idx = 0;
> -	Dwarf_Lines *lines = NULL;
> -	Dwarf_Addr postprologue_addr;
> -	Dwarf_Addr highpc;
> -
> -	if (dwarf_highpc(sp_die, &highpc))
> -		return;
> -
> -	if (dwarf_getsrclines(&pf->cu_die, &lines, &nr_lines))
> -		return;
> -
> -	if (!get_entrypc_idx(lines, nr_lines, pf->addr, &entrypc_idx))
> -		return;
> -
> -	if (!get_postprologue_addr(entrypc_idx, lines, nr_lines,
> -				   highpc, &postprologue_addr))
> -		return;
> -
> -	pf->addr = postprologue_addr;
> -}
> -
>  static void skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf)
>  {
>  	struct perf_probe_point *pp = &pf->pev->point;
> @@ -1042,7 +910,7 @@ static void skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf)
>  		return;
>  
>  	/* Compiled with optimization? */
> -	if (optimized_target(&pf->cu_die))
> +	if (die_is_optimized_target(&pf->cu_die))
>  		return;
>  
>  	/* Don't know entrypc? */
> @@ -1062,7 +930,7 @@ static void skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf)
>  		"Probe on address 0x%" PRIx64 " to force probing at the function entry.\n\n",
>  		pf->addr);
>  
> -	__skip_prologue(sp_die, pf);
> +	die_skip_prologue(sp_die, &pf->cu_die, &pf->addr);
>  }
>  
>  static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
> -- 
> 2.5.5
> 


-- 
Masami Hiramatsu <mhiramat@kernel.org>

  reply	other threads:[~2016-08-30 14:21 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-08-03  8:58 [PATCH 1/2] perf probe: Helper function to check if probe with variable Ravi Bangoria
2016-08-03  8:58 ` [PATCH v2 2/2] perf uprobe: Skip prologue if program compiled without optimization Ravi Bangoria
2016-08-13 13:45   ` Ravi Bangoria
2016-08-25 12:30     ` Masami Hiramatsu
2016-08-18  9:17   ` Naveen N. Rao
2016-08-25 12:50   ` Masami Hiramatsu
2016-08-25 13:59     ` Jiri Olsa
2016-08-25 15:17       ` Arnaldo Carvalho de Melo
2016-08-25 15:44         ` Jiri Olsa
2016-08-26 19:30   ` Arnaldo Carvalho de Melo
2016-08-26 19:54     ` Arnaldo Carvalho de Melo
2016-08-27  0:27       ` Masami Hiramatsu
2016-08-29 15:10         ` [PATCH] perf probe: Move dwarf specific functions to dwarf-aux.c Ravi Bangoria
2016-08-29 22:53           ` Masami Hiramatsu
2016-08-30  8:39             ` [PATCH v2] " Ravi Bangoria
2016-08-30 14:10               ` Masami Hiramatsu [this message]
2016-09-05 13:27               ` [tip:perf/core] " tip-bot for Ravi Bangoria
2016-08-29  8:09       ` [PATCH v2 2/2] perf uprobe: Skip prologue if program compiled without optimization Ravi Bangoria
2016-08-29  8:08     ` Ravi Bangoria
2016-09-05 13:26   ` [tip:perf/core] " tip-bot for Ravi Bangoria
2016-08-25 12:32 ` [PATCH 1/2] perf probe: Helper function to check if probe with variable Masami Hiramatsu
2016-09-05 13:26 ` [tip:perf/core] perf probe: Add helper " tip-bot for Ravi Bangoria

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160830231034.0bb2ed73a12e04ef7892fd91@kernel.org \
    --to=mhiramat@kernel.org \
    --cc=acme@kernel.org \
    --cc=alexander.shishkin@linux.intel.com \
    --cc=hemant@linux.vnet.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=naveen.n.rao@linux.vnet.ibm.com \
    --cc=peterz@infradead.org \
    --cc=ravi.bangoria@linux.vnet.ibm.com \
    --cc=wangnan0@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox