Implement lbr-as-callgraph v10
[Reworks to address all the review feedback. Rebased to latest tree] [Just a repost after a rebase]
[Even more review feedback and some bugs addressed.] [Only port to changes in perf/core. No other changes.] [Rebase to latest perf/core]
[Another rebase. No changes]
This patchkit implements lbr-as-callgraphs in per freport, as an alternative way to present LBR information.
Current perf report does a histogram over the branch edges, which is useful to look at basic blocks, but doesn't tell you anything about the larger control flow behaviour.
This patchkit adds a new option --branch-history that adds the branch paths to the callgraph history instead.
This allows to reason about individual branch paths leading to specific samples.
Also available atgit://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-misc perf/lbr-callgraph8
v2:
- rebased on perf/core
- fix various issues
- rename the option to --branch-history
- various fixes to display the information more concise v3:
- White space changes
- Consolidate some patches
- Update some descriptions
v4:
- Fix various display problems
- Unknown srcline is now printed as symbol+offset
- Refactor some code to address review feedback
- Merge with latest tip
- Fix missing srcline display in stdio hist output. v5:
- Rename functions
- Fix gtk build problem
- Fix crash without -g
- Improve error messages
- Improve srcline display in various ways
v6:
- Port to latest perf/core
v7:
- Really port to latest perf/core
v8:
- Rebased on 3.16-rc1
v9:
- Rebase on 3.17-rc* tip/perf/core
v10:
- Rebase to latest tree.
- Address review feedback (except where commented). See the individual patches for changelog. I dropped the -v option support.
Example output:
% perf record -b -g ./tsrc/tcall
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.044 MB perf.data (~1923 samples) ] % perf report --branch-history
...
54.91% tcall.c:6 [.] f2 tcall
|
|--65.53%-- f2 tcall.c:5
| |
| |--70.83%-- f1 tcall.c:11
| | f1 tcall.c:10
| | main tcall.c:18
| | main tcall.c:18
| | main tcall.c:17
| | main tcall.c:17
| | f1 tcall.c:13
| | f1 tcall.c:13
| | f2 tcall.c:7
| | f2 tcall.c:5
| | f1 tcall.c:12
| | f1 tcall.c:12
| | f2 tcall.c:7
| | f2 tcall.c:5
| | f1 tcall.c:11
PATCH 1/10 perf, tools: Factor out adding new call chain entries
From: Andi Kleen <[email protected]>
Move the code to resolve and add a new callchain entry into a new add_callchain_ip function. This will be used in the next patches to add LBRs too.
No change in behavior.
--- tools/perf/util/machine.c | 51 +++++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 19 deletions(-)
tools/perf/util/machine.c +32 -19
@@ -1381,6 +1381,34 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample,return mi; } +static int add_callchain_ip (struct thread *thread, +struct symbol **parent, +struct addr_location *root_al, +int cpumode, +u64 ip) +{ +struct addr_location al; + + al.filtered =0 ; + al.sym =NULL ; +thread__find_addr_location (thread, cpumode,MAP__FUNCTION , + ip, &al); +if (al.sym !=NULL ) { +if (sort__has_parent && !*parent && +symbol__match_regex (al.sym, &parent_regex)) + *parent = al.sym; +else if (have_ignore_callees && root_al && +symbol__match_regex (al.sym, &ignore_callees_regex)) { +/* Treat this symbol as the root, +forgetting its callees. */ + *root_al = al; +callchain_cursor_reset (&callchain_cursor); + } + } + +return callchain_cursor_append (&callchain_cursor, ip, al.map, al.sym); +} +struct branch_info *sample__resolve_bstack (struct perf_sample *sample,struct addr_location *al) {
@@ -1427,7 +1455,6 @@ static int thread__resolve_callchain_sample(struct thread *thread,for (i =0 ; i < chain_nr; i++) {u64 ip; -struct addr_location al;if (callchain_param.order ==ORDER_CALLEE ) j = i;
@@ -1464,24 +1491,10 @@ static int thread__resolve_callchain_sample(struct thread *thread,continue ; } - al.filtered =0 ; -thread__find_addr_location (thread, cpumode, -MAP__FUNCTION , ip, &al); -if (al.sym !=NULL ) { -if (sort__has_parent && !*parent && -symbol__match_regex (al.sym, &parent_regex)) - *parent = al.sym; -else if (have_ignore_callees && root_al && -symbol__match_regex (al.sym, &ignore_callees_regex)) { -/* Treat this symbol as the root, -forgetting its callees. */ - *root_al = al; -callchain_cursor_reset (&callchain_cursor); - } - } - - err =callchain_cursor_append (&callchain_cursor, - ip, al.map, al.sym); + err =add_callchain_ip (thread, parent, root_al, + cpumode, ip); +if (err == -EINVAL ) +break ;if (err)return err; }
Signature · 1 line
1.9.3
Re: [PATCH 01/10] perf, tools: Factor out adding new call chain entries
Em Wed, Nov 12, 2014 at 06:05:19PM -0800, Andi Kleen escreveu:
Quoted 7 lines
From: Andi Kleen <[email protected]>
Move the code to resolve and add a new callchain entry into a new
add_callchain_ipfunction. This will be used in the next patches to add LBRs too.No change in behavior.
Applied.
- Arnaldo
tip-bot for Andi Kleen
merge bot[tip:perf/core] perf callchain: Factor out adding new call chain entries
In reply to Andi Kleenperf callchain: Factor out adding new call chain entries
Commit-ID: 37592b8afb7151994e760d1727c264329d9c13c8 Gitweb: http://git.kernel.org/tip/37592b8afb7151994e760d1727c264329d9c13c8 Author: Andi Kleen <[email protected]> AuthorDate: Wed, 12 Nov 2014 18:05:19 -0800 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Wed, 19 Nov 2014 12:33:47 -0300
perf callchain: Factor out adding new call chain entries
Move the code to resolve and add a new callchain entry into a new add_callchain_ip function. This will be used in the next patches to add LBRs too.
No change in behavior.
--- tools/perf/util/machine.c | 51 +++++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 19 deletions(-)
tools/perf/util/machine.c +32 -19
@@ -1381,6 +1381,34 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample,return mi; } +static int add_callchain_ip (struct thread *thread, +struct symbol **parent, +struct addr_location *root_al, +int cpumode, +u64 ip) +{ +struct addr_location al; + + al.filtered =0 ; + al.sym =NULL ; +thread__find_addr_location (thread, cpumode,MAP__FUNCTION , + ip, &al); +if (al.sym !=NULL ) { +if (sort__has_parent && !*parent && +symbol__match_regex (al.sym, &parent_regex)) + *parent = al.sym; +else if (have_ignore_callees && root_al && +symbol__match_regex (al.sym, &ignore_callees_regex)) { +/* Treat this symbol as the root, +forgetting its callees. */ + *root_al = al; +callchain_cursor_reset (&callchain_cursor); + } + } + +return callchain_cursor_append (&callchain_cursor, ip, al.map, al.sym); +} +struct branch_info *sample__resolve_bstack (struct perf_sample *sample,struct addr_location *al) {
@@ -1427,7 +1455,6 @@ static int thread__resolve_callchain_sample(struct thread *thread,for (i =0 ; i < chain_nr; i++) {u64 ip; -struct addr_location al;if (callchain_param.order ==ORDER_CALLEE ) j = i;
@@ -1464,24 +1491,10 @@ static int thread__resolve_callchain_sample(struct thread *thread,continue ; } - al.filtered =0 ; -thread__find_addr_location (thread, cpumode, -MAP__FUNCTION , ip, &al); -if (al.sym !=NULL ) { -if (sort__has_parent && !*parent && -symbol__match_regex (al.sym, &parent_regex)) - *parent = al.sym; -else if (have_ignore_callees && root_al && -symbol__match_regex (al.sym, &ignore_callees_regex)) { -/* Treat this symbol as the root, -forgetting its callees. */ - *root_al = al; -callchain_cursor_reset (&callchain_cursor); - } - } - - err =callchain_cursor_append (&callchain_cursor, - ip, al.map, al.sym); + err =add_callchain_ip (thread, parent, root_al, + cpumode, ip); +if (err == -EINVAL ) +break ;if (err)return err; }
PATCH 2/10 perf, tools: Support handling complete branch stacks as histograms
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
Currently branch stacks can be only shown as edge histograms for individual branches. I never found this display particularly useful.
This implements an alternative mode that creates histograms over complete branch traces, instead of individual branches, similar to how normal callgraphs are handled. This is done by putting it in
front of the normal callgraph and then using the normal callgraph histogram infrastructure to unify them.
This way in complex functions we can understand the control flow that lead to a particular sample, and may even see some control flow in the caller for short functions.
Example (simplified, of course for such simple code this is usually not needed):
tcall.c:
volatile a = 10000, b = 100000, c;
__attribute__((noinline)) f2()
{
c = a / b;
}__attribute__((noinline)) f1()
{
f2();
f2();
}
main()
{
int i;
for (i = 0; i < 1000000; i++)
f1();
}% perf record -b -g ./tsrc/tcall
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.044 MB perf.data (~1923 samples) ] % perf report --branch-history
...
54.91% tcall.c:6 [.] f2 tcall
|
|--65.53%-- f2 tcall.c:5
| |
| |--70.83%-- f1 tcall.c:11
| | f1 tcall.c:10
| | main tcall.c:18
| | main tcall.c:18
| | main tcall.c:17
| | main tcall.c:17
| | f1 tcall.c:13
| | f1 tcall.c:13
| | f2 tcall.c:7
| | f2 tcall.c:5
| | f1 tcall.c:12
| | f1 tcall.c:12
| | f2 tcall.c:7
| | f2 tcall.c:5
| | f1 tcall.c:11
| |
| --29.17%-- f1 tcall.c:12
| f1 tcall.c:12
| f2 tcall.c:7
| f2 tcall.c:5
| f1 tcall.c:11
| f1 tcall.c:10
| main tcall.c:18
| main tcall.c:18
| main tcall.c:17
| main tcall.c:17
| f1 tcall.c:13
| f1 tcall.c:13
| f2 tcall.c:7
| f2 tcall.c:5
| f1 tcall.c:12The default output is unchanged.
This is only implemented in perf report, no change to record or anywhere else.
This adds the basic code to report:
- add a new "branch" option to the -g option parser to enable this mode
- when the flag is set include the LBR into the callstack in machine.c. The rest of the history code is unchanged and doesn't know the difference between LBR entry and normal call entry.
- detect overlaps with the callchain
- remove small loop duplicates in the LBR
Current limitations:
- The LBR flags (mispredict etc.) are not shown in the history and LBR entries have no special marker.
- It would be nice if annotate marked the LBR entries somehow (e.g. with arrows)
v2: Various fixes.
v3: Merge further patches into this one. Fix white space.
v4: Improve manpage. Address review feedback.
v5: Rename functions. Better error message without -g. Fix crash without
-b.
v6: Rebase
v7: Rebase. Use NO_ENTRY in memset.
v8: Port to latest tip. Move add_callchain_ip to separate
patch. Skip initial entries in callchain. Minor cleanups.
--- tools/perf/Documentation/perf-report.txt | 7 +- tools/perf/builtin-report.c | 4 +- tools/perf/util/callchain.c | 4 + tools/perf/util/callchain.h | 1 + tools/perf/util/machine.c | 125 ++++++++++++++++++++++++++++--- tools/perf/util/symbol.h | 3 +- 6 files changed, 131 insertions(+), 13 deletions(-)
tools/perf/Documentation/perf-report.txt +6 -1
@@ -159,7 +159,7 @@ OPTIONS --dump-raw-trace:: Dump raw trace in ASCII. --g [type,min[,limit],order[,key]]:: +-g [type,min[,limit],order[,key][,branch]]:: --call-graph:: Display call chains using type, min percent threshold, optional print limit and order.
@@ -177,6 +177,11 @@ OPTIONS - function: compare on functions - address: compare on individual code addresses + branch can be: + - branch: include last branch information in callgraph + when available. Usually more convenient to use --branch-history + for this. + Default: fractal,0.5,callee,function. --children::
tools/perf/builtin-report.c +2 -2
@@ -637,8 +637,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) "regex filter to identify parent, see: '--sort parent'"),OPT_BOOLEAN ('x' ,"exclude-other" , &symbol_conf.exclude_other,"Only display entries with parent-match" ), -OPT_CALLBACK_DEFAULT ('g' ,"call-graph" , &report,"output_type,min_percent[,print_limit],call_order" , -"Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit, callchain order, key (function or address). " +OPT_CALLBACK_DEFAULT ('g' ,"call-graph" , &report,"output_type,min_percent[,print_limit],call_order[,branch]" , +"Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit, callchain order, key (function or address), add branches. " "Default: fractal,0.5,callee,function" , &report_parse_callchain_opt, callchain_default_opt),OPT_BOOLEAN (0 ,"children" , &symbol_conf.cumulate_callchain, "Accumulate callchains of children and show total overhead as well"),
tools/perf/util/callchain.c +4 -0
@@ -149,6 +149,10 @@ static int parse_callchain_sort_key(const char *value) callchain_param.key =CCKEY_ADDRESS ;return 0 ; } +if (!strncmp (value,"branch" ,strlen (value))) { + callchain_param.branch_callstack =1 ; +return 0 ; + }return -1 ; }
tools/perf/util/callchain.h +1 -0
@@ -63,6 +63,7 @@ struct callchain_param {sort_chain_func_t sort;enum chain_order order;enum chain_key key; +bool branch_callstack; };extern struct callchain_param callchain_param;
tools/perf/util/machine.c +116 -9
165 lines not on this page · raw message
tools/perf/util/symbol.h +2 -1
@@ -123,7 +123,8 @@ struct symbol_conf { demangle, demangle_kernel, filter_relative, - show_hist_headers; + show_hist_headers, + branch_callstack;const char *vmlinux_name, *kallsyms_name, *source_prefix,
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 02/10] perf, tools: Support handling complete branch stacks as histograms
Em Wed, Nov 12, 2014 at 06:05:20PM -0800, Andi Kleen escreveu:
tools/perf/util/machine.c struct branch_info *sample__resolve_bstack(struct perf_sample *sample, · line 1449
Quoted 8 lines
tools/perf/util/machine.c +8
-0+static int remove_loops (struct branch_entry *l,int nr) +{ +int i, j, off; +unsigned char chash[CHASHSZ ]; + +memset (chash,NO_ENTRY ,sizeof (chash)); + +BUG_ON (nr >=256 );
What is wrong with return -1 and propagating the error, so that the user is informed if the data being processed is bogus, stop processing with a warning or continue processing if finding the next valid record is possible?
In general just aborting (and this only does that when NDEBUG is set) should be avoided...
I can go on and help you and do that for you, but why introduce it in the first place?
- Arnaldo
Quoted 146 lines
tools/perf/util/machine.c +95
-8+for (i =0 ; i < nr; i++) { +int h =hash_64 (l[i].from,CHASHBITS ) %CHASHSZ ; + +/* no collision handling for now */ +if (chash[h] ==NO_ENTRY ) { + chash[h] = i; + }else if (l[chash[h]].from == l[i].from) { +bool is_loop = true; +/* check if it is a real loop */ + off =0 ; +for (j = chash[h]; j < i && i + off < nr; j++, off++) +if (l[j].from != l[i + off].from) { + is_loop = false; +break ; + } +if (is_loop) { +memmove (l + i, l + i + off, + (nr - (i + off)) *sizeof (*l)); + nr -= off; + } + } + } +return nr; +} +static int thread__resolve_callchain_sample (struct thread *thread,struct ip_callchain *chain, +struct branch_stack *branch,struct symbol **parent,struct addr_location *root_al,int max_stack)@@ -1438,22 +1484,82 @@ static int thread__resolve_callchain_sample(struct thread *thread,int i;int j;int err; -int skip_idx__maybe_unused ; +int skip_idx =-1 ; +int first_call =0 ; + +/* +* Based on DWARF debug information, some architectures skip +* a callchain entry saved by the kernel. +*/ +if (chain->nr <PERF_MAX_STACK_DEPTH ) + skip_idx =arch_skip_callchain_idx (thread, chain);callchain_cursor_reset (&callchain_cursor); +/* +* Add branches to call stack for easier browsing. This gives +* more context for a sample than just the callers. +* +* This uses individual histograms of paths compared to the +* aggregated histograms the normal LBR mode uses. +* +* Limitations for now: +* - No extra filters +* - No annotations (should annotate somehow) +*/ + +if (branch && callchain_param.branch_callstack) { +int nr =min (max_stack, (int )branch->nr); +struct branch_entry be[nr]; + +if (branch->nr >PERF_MAX_BRANCH_DEPTH ) { +pr_warning ("corrupted branch chain. skipping...\n" ); + goto check_calls; + } + +for (i =0 ; i < nr; i++) { +if (callchain_param.order ==ORDER_CALLEE ) { + be[i] = branch->entries[i]; +/* +* Check for overlap into the callchain. +* The return address is one off compared to +* the branch entry. To adjust for this +* assume the calling instruction is not longer +* than 8 bytes. +*/ +if (i == skip_idx || + chain->ips[first_call] >=PERF_CONTEXT_MAX ) + first_call++; +else if (be[i].from < chain->ips[first_call] && + be[i].from >= chain->ips[first_call] -8 ) + first_call++; + }else + be[i] = branch->entries[branch->nr - i -1 ]; + } + + nr =remove_loops (be, nr); + +for (i =0 ; i < nr; i++) { + err =add_callchain_ip (thread, parent, root_al, +-1 , be[i].to); +if (!err) + err =add_callchain_ip (thread, parent, root_al, +-1 , be[i].from); +if (err == -EINVAL ) +break ; +if (err) +return err; + } + chain_nr -= nr; + } + +check_calls:if (chain->nr >PERF_MAX_STACK_DEPTH ) {pr_warning ("corrupted callchain. skipping...\n" );return 0 ; } -/* -* Based on DWARF debug information, some architectures skip -* a callchain entry saved by the kernel. -*/ - skip_idx =arch_skip_callchain_idx (thread, chain); - -for (i =0 ; i < chain_nr; i++) { +for (i = first_call; i < chain_nr; i++) {u64 ip;if (callchain_param.order ==ORDER_CALLEE )@@ -1517,6 +1623,7 @@ int thread__resolve_callchain(struct thread *thread, int max_stack) {int ret =thread__resolve_callchain_sample (thread, sample->callchain, + sample->branch_stack, parent, root_al, max_stack);if (ret)return ret;tools/perf/util/symbol.h +2
-1@@ -123,7 +123,8 @@ struct symbol_conf { demangle, demangle_kernel, filter_relative, - show_hist_headers; + show_hist_headers, + branch_callstack;const char *vmlinux_name, *kallsyms_name, *source_prefix,Signature · 1 line
1.9.3
Re: [PATCH 02/10] perf, tools: Support handling complete branch stacks as histograms
Quoted 14 lines · Arnaldo Carvalho de Melo
Em Wed, Nov 12, 2014 at 06:05:20PM -0800, Andi Kleen escreveu:
tools/perf/util/machine.c struct branch_info *sample__resolve_bstack(struct perf_sample *sample, · line 1449
Quoted 8 lines
tools/perf/util/machine.c +8
-0+static int remove_loops (struct branch_entry *l,int nr) +{ +int i, j, off; +unsigned char chash[CHASHSZ ]; + +memset (chash,NO_ENTRY ,sizeof (chash)); + +BUG_ON (nr >=256 );What is wrong with return -1 and propagating the error, so that the user is informed if the data being processed is bogus, stop processing with a warning or continue processing if finding the next valid record is possible?
The error doesn't depend on the record. There is a check for the record being < 127 in front of this. This is merely to catch that if someone increases PERF_MAX_BRANCH_DEPTH to below 255 they need to increase the type of the hash table from u8.
-Andi
Signature · 1 line
[email protected] -- Speaking for myself only.
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 02/10] perf, tools: Support handling complete branch stacks as histograms
Em Thu, Nov 13, 2014 at 08:52:08PM +0100, Andi Kleen escreveu:
Quoted 16 lines · Arnaldo Carvalho de Melo
Quoted 14 lines
Em Wed, Nov 12, 2014 at 06:05:20PM -0800, Andi Kleen escreveu:
tools/perf/util/machine.c struct branch_info *sample__resolve_bstack(struct perf_sample *sample, · line 1449
Quoted 8 lines
tools/perf/util/machine.c +8
-0+static int remove_loops (struct branch_entry *l,int nr) +{ +int i, j, off; +unsigned char chash[CHASHSZ ]; + +memset (chash,NO_ENTRY ,sizeof (chash)); + +BUG_ON (nr >=256 );What is wrong with return -1 and propagating the error, so that the user is informed if the data being processed is bogus, stop processing with a warning or continue processing if finding the next valid record is possible?
Quoted 4 lines
The error doesn't depend on the record. There is a check for the record being < 127 in front of this. This is merely to catch that if someone increases
PERF_MAX_BRANCH_DEPTHto below 255 they need to increase the type of the hash table from u8.
Ok, so this would be better as a BUILD_BUG_ON?
Like:
#define CHASHSZ 127
#define CHASHBITS 7
#define NO_ENTRY 0xff
#define PERF_MAX_BRANCH_DEPTH 127
/* Remove loops. */
static int remove_loops(struct branch_entry *l, int nr)
{
int i, j, off;
unsigned char chash[CHASHSZ];
memset(chash, NO_ENTRY, sizeof(chash));
/* Change the type of the chash table, u8 is not enough now */
BUILD_BUG_ON(PERF_MAX_BRANCH_DEPTH >= 256);
for (i = 0; i < nr; i++) {
int h = hash_64(l[i].from, CHASHBITS) % CHASHSZ;-------------------------------------
- Arnaldo
Re: [PATCH 02/10] perf, tools: Support handling complete branch stacks as histograms
Quoted 17 lines · Arnaldo Carvalho de Melo
Em Thu, Nov 13, 2014 at 08:52:08PM +0100, Andi Kleen escreveu:
Quoted 16 lines · Arnaldo Carvalho de Melo
Quoted 14 lines
Em Wed, Nov 12, 2014 at 06:05:20PM -0800, Andi Kleen escreveu:
tools/perf/util/machine.c struct branch_info *sample__resolve_bstack(struct perf_sample *sample, · line 1449
Quoted 8 lines
tools/perf/util/machine.c +8
-0+static int remove_loops (struct branch_entry *l,int nr) +{ +int i, j, off; +unsigned char chash[CHASHSZ ]; + +memset (chash,NO_ENTRY ,sizeof (chash)); + +BUG_ON (nr >=256 );What is wrong with return -1 and propagating the error, so that the user is informed if the data being processed is bogus, stop processing with a warning or continue processing if finding the next valid record is possible?
Quoted 6 lines
Quoted 4 lines
The error doesn't depend on the record. There is a check for the record being < 127 in front of this. This is merely to catch that if someone increases
PERF_MAX_BRANCH_DEPTHto below 255 they need to increase the type of the hash table from u8.Ok, so this would be better as a
BUILD_BUG_ON?
Yes that should work.
-Andi
Quoted 26 lines
Like:
#define CHASHSZ 127
#define CHASHBITS 7
#defineNO_ENTRY0xff#define
PERF_MAX_BRANCH_DEPTH127/* Remove loops. */
static intremove_loops(struct branch_entry *l, int nr){ int i, j, off; unsigned char chash[CHASHSZ]; memset(chash, NO_ENTRY, sizeof(chash)); /* Change the type of the chash table, u8 is not enough now */ BUILD_BUG_ON(PERF_MAX_BRANCH_DEPTH >= 256); for (i = 0; i < nr; i++) { int h = hash_64(l[i].from, CHASHBITS) % CHASHSZ;-------------------------------------
- Arnaldo
Signature · 1 line
[email protected] -- Speaking for myself only.
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 02/10] perf, tools: Support handling complete branch stacks as histograms
Em Thu, Nov 13, 2014 at 09:15:24PM +0100, Andi Kleen escreveu:
Quoted 18 lines · Arnaldo Carvalho de Melo
Quoted 17 lines
Em Thu, Nov 13, 2014 at 08:52:08PM +0100, Andi Kleen escreveu:
Quoted 16 lines · Arnaldo Carvalho de Melo
Quoted 14 lines
Em Wed, Nov 12, 2014 at 06:05:20PM -0800, Andi Kleen escreveu:
tools/perf/util/machine.c struct branch_info *sample__resolve_bstack(struct perf_sample *sample, · line 1449
Quoted 8 lines
tools/perf/util/machine.c +8
-0+static int remove_loops (struct branch_entry *l,int nr) +{ +int i, j, off; +unsigned char chash[CHASHSZ ]; + +memset (chash,NO_ENTRY ,sizeof (chash)); + +BUG_ON (nr >=256 );What is wrong with return -1 and propagating the error, so that the user is informed if the data being processed is bogus, stop processing with a warning or continue processing if finding the next valid record is possible?
Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
The error doesn't depend on the record. There is a check for the record being < 127 in front of this. This is merely to catch that if someone increases
PERF_MAX_BRANCH_DEPTHto below 255 they need to increase the type of the hash table from u8.Ok, so this would be better as a
BUILD_BUG_ON?Yes that should work.
Ok, I'll do that, test by bumping it to 256, etc and merge the resulting patch, thanks for checking.
- Arnaldo
Quoted 31 lines
-Andi
Quoted 26 lines
Like:
#define CHASHSZ 127
#define CHASHBITS 7
#defineNO_ENTRY0xff#define
PERF_MAX_BRANCH_DEPTH127/* Remove loops. */
static intremove_loops(struct branch_entry *l, int nr){ int i, j, off; unsigned char chash[CHASHSZ]; memset(chash, NO_ENTRY, sizeof(chash)); /* Change the type of the chash table, u8 is not enough now */ BUILD_BUG_ON(PERF_MAX_BRANCH_DEPTH >= 256); for (i = 0; i < nr; i++) { int h = hash_64(l[i].from, CHASHBITS) % CHASHSZ;-------------------------------------
- Arnaldo
Signature · 1 line
[email protected] -- Speaking for myself only.
tip-bot for Andi Kleen
merge bot[tip:perf/core] perf callchain: Support handling complete branch stacks as histograms
In reply to Andi Kleenperf callchain: Support handling complete branch stacks as histograms
Commit-ID: 8b7bad58efb7e3aaff60f7c1fa4361fb8c23181d Gitweb: http://git.kernel.org/tip/8b7bad58efb7e3aaff60f7c1fa4361fb8c23181d Author: Andi Kleen <[email protected]> AuthorDate: Wed, 12 Nov 2014 18:05:20 -0800 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Mon, 1 Dec 2014 20:00:31 -0300
perf callchain: Support handling complete branch stacks as histograms
Currently branch stacks can be only shown as edge histograms for individual branches. I never found this display particularly useful.
This implements an alternative mode that creates histograms over complete branch traces, instead of individual branches, similar to how normal callgraphs are handled. This is done by putting it in front of the normal callgraph and then using the normal callgraph histogram infrastructure to unify them.
This way in complex functions we can understand the control flow that lead to a particular sample, and may even see some control flow in the caller for short functions.
Example (simplified, of course for such simple code this is usually not needed), please run this after the whole patchkit is in, as at this point in the patch order there is no --branch-history, that will be added in a patch after this one:
tcall.c:
volatile a = 10000, b = 100000, c;
__attribute__((noinline)) f2()
{
c = a / b;
}__attribute__((noinline)) f1()
{
f2();
f2();
}
main()
{
int i;
for (i = 0; i < 1000000; i++)
f1();
}% perf record -b -g ./tsrc/tcall
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.044 MB perf.data (~1923 samples) ] % perf report --no-children --branch-history
...
54.91% tcall.c:6 [.] f2 tcall
|
|--65.53%-- f2 tcall.c:5
| |
| |--70.83%-- f1 tcall.c:11
| | f1 tcall.c:10
| | main tcall.c:18
| | main tcall.c:18
| | main tcall.c:17
| | main tcall.c:17
| | f1 tcall.c:13
| | f1 tcall.c:13
| | f2 tcall.c:7
| | f2 tcall.c:5
| | f1 tcall.c:12
| | f1 tcall.c:12
| | f2 tcall.c:7
| | f2 tcall.c:5
| | f1 tcall.c:11
| |
| --29.17%-- f1 tcall.c:12
| f1 tcall.c:12
| f2 tcall.c:7
| f2 tcall.c:5
| f1 tcall.c:11
| f1 tcall.c:10
| main tcall.c:18
| main tcall.c:18
| main tcall.c:17
| main tcall.c:17
| f1 tcall.c:13
| f1 tcall.c:13
| f2 tcall.c:7
| f2 tcall.c:5
| f1 tcall.c:12The default output is unchanged.
This is only implemented in perf report, no change to record or anywhere else.
This adds the basic code to report:
- add a new "branch" option to the -g option parser to enable this mode
- when the flag is set include the LBR into the callstack in machine.c.
The rest of the history code is unchanged and doesn't know the difference between LBR entry and normal call entry.
- detect overlaps with the callchain
- remove small loop duplicates in the LBR
Current limitations:
- The LBR flags (mispredict etc.) are not shown in the history and LBR entries have no special marker.
- It would be nice if annotate marked the LBR entries somehow (e.g. with arrows)
v2: Various fixes.
v3: Merge further patches into this one. Fix white space.
v4: Improve manpage. Address review feedback.
v5: Rename functions. Better error message without -g. Fix crash without
-b.
v6: Rebase
v7: Rebase. Use NO_ENTRY in memset.
v8: Port to latest tip. Move add_callchain_ip to separate
patch. Skip initial entries in callchain. Minor cleanups.
--- tools/perf/Documentation/perf-report.txt | 7 +- tools/perf/builtin-report.c | 4 +- tools/perf/util/callchain.c | 4 + tools/perf/util/callchain.h | 1 + tools/perf/util/machine.c | 126 ++++++++++++++++++++++++++++--- tools/perf/util/symbol.h | 3 +- 6 files changed, 132 insertions(+), 13 deletions(-)
tools/perf/Documentation/perf-report.txt +6 -1
@@ -159,7 +159,7 @@ OPTIONS --dump-raw-trace:: Dump raw trace in ASCII. --g [type,min[,limit],order[,key]]:: +-g [type,min[,limit],order[,key][,branch]]:: --call-graph:: Display call chains using type, min percent threshold, optional print limit and order.
@@ -177,6 +177,11 @@ OPTIONS - function: compare on functions - address: compare on individual code addresses + branch can be: + - branch: include last branch information in callgraph + when available. Usually more convenient to use --branch-history + for this. + Default: fractal,0.5,callee,function. --children::
tools/perf/builtin-report.c +2 -2
@@ -637,8 +637,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) "regex filter to identify parent, see: '--sort parent'"),OPT_BOOLEAN ('x' ,"exclude-other" , &symbol_conf.exclude_other,"Only display entries with parent-match" ), -OPT_CALLBACK_DEFAULT ('g' ,"call-graph" , &report,"output_type,min_percent[,print_limit],call_order" , -"Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit, callchain order, key (function or address). " +OPT_CALLBACK_DEFAULT ('g' ,"call-graph" , &report,"output_type,min_percent[,print_limit],call_order[,branch]" , +"Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit, callchain order, key (function or address), add branches. " "Default: fractal,0.5,callee,function" , &report_parse_callchain_opt, callchain_default_opt),OPT_BOOLEAN (0 ,"children" , &symbol_conf.cumulate_callchain, "Accumulate callchains of children and show total overhead as well"),
tools/perf/util/callchain.c +4 -0
@@ -149,6 +149,10 @@ static int parse_callchain_sort_key(const char *value) callchain_param.key =CCKEY_ADDRESS ;return 0 ; } +if (!strncmp (value,"branch" ,strlen (value))) { + callchain_param.branch_callstack =1 ; +return 0 ; + }return -1 ; }
tools/perf/util/callchain.h +1 -0
@@ -63,6 +63,7 @@ struct callchain_param {sort_chain_func_t sort;enum chain_order order;enum chain_key key; +bool branch_callstack; };extern struct callchain_param callchain_param;
tools/perf/util/machine.c +117 -9
166 lines not on this page · raw message
tools/perf/util/symbol.h +2 -1
@@ -102,7 +102,8 @@ struct symbol_conf { demangle, demangle_kernel, filter_relative, - show_hist_headers; + show_hist_headers, + branch_callstack;const char *vmlinux_name, *kallsyms_name, *source_prefix,
PATCH 3/10 perf, tools: Use al.addr to set up call chain
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
Use the relative address, this makes get_srcline work correctly in the end.
--- tools/perf/util/machine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/util/machine.c +1 -1
@@ -1411,7 +1411,7 @@ static int add_callchain_ip(struct thread *thread, } } -return callchain_cursor_append (&callchain_cursor, ip, al.map, al.sym); +return callchain_cursor_append (&callchain_cursor, al.addr, al.map, al.sym); } struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
Signature · 1 line
1.9.3
Re: [PATCH 03/10] perf, tools: Use al.addr to set up call chain
Em Wed, Nov 12, 2014 at 06:05:21PM -0800, Andi Kleen escreveu:
Quoted 4 lines
From: Andi Kleen <[email protected]>
Use the relative address, this makes
get_srclinework correctly in the end.
Applied.
Quoted 20 lines
Signed-off-by Andi Kleen <[email protected]>--- tools/perf/util/machine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)tools/perf/util/machine.c +1
-1@@ -1411,7 +1411,7 @@ static int add_callchain_ip(struct thread *thread, } } -return callchain_cursor_append (&callchain_cursor, ip, al.map, al.sym); +return callchain_cursor_append (&callchain_cursor, al.addr, al.map, al.sym); } struct branch_info *sample__resolve_bstack(struct perf_sample *sample,Signature · 1 line
1.9.3
Re: [PATCH 03/10] perf, tools: Use al.addr to set up call chain
Quoted 21 lines · Arnaldo Carvalho de Melo
Em Wed, Nov 12, 2014 at 06:05:21PM -0800, Andi Kleen escreveu:
Quoted 4 lines
From: Andi Kleen <[email protected]>
Use the relative address, this makes
get_srclinework correctly in the end.Applied.
Quoted 13 lines
Signed-off-by Andi Kleen <[email protected]>--- tools/perf/util/machine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)tools/perf/util/machine.c +0
-0@@ -1411,7 +1411,7 @@ static int add_callchain_ip(struct thread *thread, } }
Quoted 7 lines
Quoted 7 lines
tools/perf/util/machine.c +1
-1-return callchain_cursor_append (&callchain_cursor, ip, al.map, al.sym); +return callchain_cursor_append (&callchain_cursor, al.addr, al.map, al.sym); } struct branch_info *sample__resolve_bstack(struct perf_sample *sample,Signature · 1 line
1.9.3
hi,
this patch also changed the output of callchain entries with 'map' but with no symbol, like in following diff:
---
---get_next_seq
|
- |--70.16%-- 0x40e1cf
+ |--70.16%-- 0xe1cf
| 0x841f0f
|
- |--25.83%-- 0x40e153
+ |--25.83%-- 0xe153
| 0x841f0f
|- --4.00%-- 0x40e27f
+ --4.00%-- 0xe27f
--
I'm guessing this change was unintentional..? in case we have a map but no symbol seeing full address is more clear than relative at least for binary, not sure about DSOs..
thoughts?
thanks,
jirka
---
tools/perf/util/callchain.c +14 -6
@@ -816,22 +816,30 @@ out:char *callchain_list__sym_name (struct callchain_list *cl,char *bf,size_t bfsize,bool show_dso) { +struct map *map = cl->ms.map;int printed;if (cl->ms.sym) {if (callchain_param.key ==CCKEY_ADDRESS && - cl->ms.map && !cl->srcline) - cl->srcline =get_srcline (cl->ms.map->dso, -map__rip_2objdump (cl->ms.map, - cl->ip), + map && !cl->srcline) { + cl->srcline =get_srcline (map->dso, +map__rip_2objdump (map, cl->ip), cl->ms.sym, false); + }if (cl->srcline) printed =scnprintf (bf, bfsize,"%s %s" , cl->ms.sym->name, cl->srcline);else printed =scnprintf (bf, bfsize,"%s" , cl->ms.sym->name); - }else - printed =scnprintf (bf, bfsize,"%#" PRIx64, cl->ip); + }else { +/* +* The cl->ip value is unbased ip (applied map->map_ip). +* Display the unmap ip in case we have no symbol. +*/ +u64 addr = map ? map->unmap_ip (map, cl->ip) : cl->ip; + + printed =scnprintf (bf, bfsize,"%#" PRIx64, addr); + }if (show_dso) scnprintf(bf + printed, bfsize - printed, " %s",
Re: [PATCH 03/10] perf, tools: Use al.addr to set up call chain
Quoted 2 lines
this patch also changed the output of callchain entries with 'map' but with no symbol, like in following diff:
Was unintentional. Patch looks good. thanks.
-Andi
Quoted 69 lines
---
---get_next_seq |(quoted diff) +3
-4- |--70.16%-- 0x40e1cf + |--70.16%-- 0xe1cf | 0x841f0f | - |--25.83%-- 0x40e153 + |--25.83%-- 0xe153 | 0x841f0f | - --4.00%-- 0x40e27f + --4.00%-- 0xe27f --I'm guessing this change was unintentional..? in case we have a map but no symbol seeing full address is more clear than relative at least for binary, not sure about DSOs..
thoughts?
thanks,
jirka---
tools/perf/util/callchain.c +14
-6@@ -816,22 +816,30 @@ out:char *callchain_list__sym_name (struct callchain_list *cl,char *bf,size_t bfsize,bool show_dso) { +struct map *map = cl->ms.map;int printed;if (cl->ms.sym) {if (callchain_param.key ==CCKEY_ADDRESS && - cl->ms.map && !cl->srcline) - cl->srcline =get_srcline (cl->ms.map->dso, -map__rip_2objdump (cl->ms.map, - cl->ip), + map && !cl->srcline) { + cl->srcline =get_srcline (map->dso, +map__rip_2objdump (map, cl->ip), cl->ms.sym, false); + }if (cl->srcline) printed =scnprintf (bf, bfsize,"%s %s" , cl->ms.sym->name, cl->srcline);else printed =scnprintf (bf, bfsize,"%s" , cl->ms.sym->name); - }else - printed =scnprintf (bf, bfsize,"%#" PRIx64, cl->ip); + }else { +/* +* The cl->ip value is unbased ip (applied map->map_ip). +* Display the unmap ip in case we have no symbol. +*/ +u64 addr = map ? map->unmap_ip (map, cl->ip) : cl->ip; + + printed =scnprintf (bf, bfsize,"%#" PRIx64, addr); + }if (show_dso) scnprintf(bf + printed, bfsize - printed, " %s",
Signature · 1 line
[email protected] -- Speaking for myself only
tip-bot for Andi Kleen
merge bot[tip:perf/core] perf callchain: Use al.addr to set up call chain
In reply to Andi Kleenperf callchain: Use al.addr to set up call chain
Commit-ID: 5550171b2a9f8df26ff483051d060db06376b26d Gitweb: http://git.kernel.org/tip/5550171b2a9f8df26ff483051d060db06376b26d Author: Andi Kleen <[email protected]> AuthorDate: Wed, 12 Nov 2014 18:05:21 -0800 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Wed, 19 Nov 2014 12:33:47 -0300
perf callchain: Use al.addr to set up call chain
Use the relative address, this makes get_srcline work correctly in the end.
--- tools/perf/util/machine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/util/machine.c +1 -1
@@ -1406,7 +1406,7 @@ static int add_callchain_ip(struct thread *thread, } } -return callchain_cursor_append (&callchain_cursor, ip, al.map, al.sym); +return callchain_cursor_append (&callchain_cursor, al.addr, al.map, al.sym); } struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
PATCH 4/10 perf, tools: Add --branch-history option to report
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
Add a --branch-history option to perf report that changes all the settings necessary for using the branches in callstacks.
This is just a short cut to make this nicer to use, it does not enable any functionality by itself.
v2: Change sort order. Rename option to --branch-history to be less confusing.
v3: Updates
v4: Fix conflict with newer perf base
v5: Port to latest tip
v6: Add more comments. Remove CCKEY_ADDRESS setting. Remove unnecessary branch_mode setting. Use a boolean.
--- tools/perf/Documentation/perf-report.txt | 5 +++++ tools/perf/builtin-report.c | 26 ++++++++++++++++++++++---- 2 files changed, 27 insertions(+), 4 deletions(-)
tools/perf/Documentation/perf-report.txt +5 -0
@@ -271,6 +271,11 @@ OPTIONS branch stacks and it will automatically switch to the branch view mode, unless --no-branch-stack is used. +--branch-history:: + Add the addresses of sampled taken branches to the callstack. + This allows to examine the path the program took to each sample. + The data collection must have used -b (or -j) and -g. + --objdump=<path>:: Path to objdump binary.
tools/perf/builtin-report.c +22 -4
@@ -226,8 +226,9 @@ static int report__setup_sample_type(struct report *rep)return -EINVAL ; }if (symbol_conf.use_callchain) { -ui__error ("Selected -g but no callchain data. Did " -"you call 'perf record' without -g?\n" ); +ui__error ("Selected -g or --branch-history but no " +"callchain data. Did\n" +"you call 'perf record' without -g?\n" );return -1 ; } } else if (!rep->dont_use_callchains &&
@@ -575,6 +576,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)struct stat st;bool has_br_stack = false;int branch_mode =-1 ; +bool branch_call_mode = false;char callchain_default_opt[] ="fractal,0.5,callee" ;const char *const report_usage[] = {"perf report [<options>]" ,
@@ -684,7 +686,10 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)OPT_BOOLEAN (0 ,"group" , &symbol_conf.event_group,"Show event group information together" ),OPT_CALLBACK_NOOPT ('b' ,"branch-stack" , &branch_mode,"" , -"use branch records for histogram filling" , parse_branch_mode), +"use branch records for per branch histogram filling" , + parse_branch_mode), +OPT_BOOLEAN (0 ,"branch-history" , &branch_call_mode, +"add last branch records to call history" ),OPT_STRING (0 ,"objdump" , &objdump_path,"path" ,"objdump binary to use for disassembly and annotations" ), OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
@@ -745,10 +750,23 @@ repeat: has_br_stack =perf_header__has_feat (&session->header,HEADER_BRANCH_STACK ); -if ((branch_mode ==-1 && has_br_stack) || branch_mode ==1 ) { +/* +* Branch mode is a tristate: +* -1 means default, so decide based on the file having branch data. +* 0/1 means the user chose a mode. +*/ +if (((branch_mode ==-1 && has_br_stack) || branch_mode ==1 ) && + branch_call_mode ==-1 ) { sort__mode =SORT_MODE__BRANCH ; symbol_conf.cumulate_callchain = false; } +if (branch_call_mode) { + callchain_param.branch_callstack =1 ; + symbol_conf.use_callchain = true; +callchain_register_param (&callchain_param); +if (sort_order ==NULL ) + sort_order ="srcline,symbol,dso" ; + }if (report.mem_mode) {if (sort__mode ==SORT_MODE__BRANCH ) {
Signature · 1 line
1.9.3
tip-bot for Andi Kleen
merge bot[tip:perf/core] perf report: Add --branch-history option
perf report: Add --branch-history option
Commit-ID: fa94c36c29ed8bb4749b5fd7ea51a593f673dcef Gitweb: http://git.kernel.org/tip/fa94c36c29ed8bb4749b5fd7ea51a593f673dcef Author: Andi Kleen <[email protected]> AuthorDate: Wed, 12 Nov 2014 18:05:22 -0800 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Mon, 1 Dec 2014 20:00:31 -0300
perf report: Add --branch-history option
Add a --branch-history option to perf report that changes all the settings necessary for using the branches in callstacks.
This is just a short cut to make this nicer to use, it does not enable any functionality by itself.
v2: Change sort order. Rename option to --branch-history to
be less confusing.
v3: Updates
v4: Fix conflict with newer perf base
v5: Port to latest tip
v6: Add more comments. Remove CCKEY_ADDRESS setting. Remove
unnecessary branch_mode setting. Use a boolean.
--- tools/perf/Documentation/perf-report.txt | 5 +++++ tools/perf/builtin-report.c | 26 ++++++++++++++++++++++---- 2 files changed, 27 insertions(+), 4 deletions(-)
tools/perf/Documentation/perf-report.txt +5 -0
@@ -271,6 +271,11 @@ OPTIONS branch stacks and it will automatically switch to the branch view mode, unless --no-branch-stack is used. +--branch-history:: + Add the addresses of sampled taken branches to the callstack. + This allows to examine the path the program took to each sample. + The data collection must have used -b (or -j) and -g. + --objdump=<path>:: Path to objdump binary.
tools/perf/builtin-report.c +22 -4
@@ -226,8 +226,9 @@ static int report__setup_sample_type(struct report *rep)return -EINVAL ; }if (symbol_conf.use_callchain) { -ui__error ("Selected -g but no callchain data. Did " -"you call 'perf record' without -g?\n" ); +ui__error ("Selected -g or --branch-history but no " +"callchain data. Did\n" +"you call 'perf record' without -g?\n" );return -1 ; } } else if (!rep->dont_use_callchains &&
@@ -575,6 +576,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)struct stat st;bool has_br_stack = false;int branch_mode =-1 ; +bool branch_call_mode = false;char callchain_default_opt[] ="fractal,0.5,callee" ;const char *const report_usage[] = {"perf report [<options>]" ,
@@ -684,7 +686,10 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)OPT_BOOLEAN (0 ,"group" , &symbol_conf.event_group,"Show event group information together" ),OPT_CALLBACK_NOOPT ('b' ,"branch-stack" , &branch_mode,"" , -"use branch records for histogram filling" , parse_branch_mode), +"use branch records for per branch histogram filling" , + parse_branch_mode), +OPT_BOOLEAN (0 ,"branch-history" , &branch_call_mode, +"add last branch records to call history" ),OPT_STRING (0 ,"objdump" , &objdump_path,"path" ,"objdump binary to use for disassembly and annotations" ), OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
@@ -745,10 +750,23 @@ repeat: has_br_stack =perf_header__has_feat (&session->header,HEADER_BRANCH_STACK ); -if ((branch_mode ==-1 && has_br_stack) || branch_mode ==1 ) { +/* +* Branch mode is a tristate: +* -1 means default, so decide based on the file having branch data. +* 0/1 means the user chose a mode. +*/ +if (((branch_mode ==-1 && has_br_stack) || branch_mode ==1 ) && + branch_call_mode ==-1 ) { sort__mode =SORT_MODE__BRANCH ; symbol_conf.cumulate_callchain = false; } +if (branch_call_mode) { + callchain_param.branch_callstack =1 ; + symbol_conf.use_callchain = true; +callchain_register_param (&callchain_param); +if (sort_order ==NULL ) + sort_order ="srcline,symbol,dso" ; + }if (report.mem_mode) {if (sort__mode ==SORT_MODE__BRANCH ) {
PATCH 5/10 perf, tools: Use a common function to resolve symbol or name
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
Refactor the duplicated code to resolve the symbol name or the address of a symbol into a single function.
Used in next patch to add common functionality.
--- tools/perf/ui/browsers/hists.c | 17 ----------------- tools/perf/ui/gtk/hists.c | 11 +---------- tools/perf/ui/stdio/hist.c | 23 +++++++++-------------- tools/perf/util/callchain.c | 19 +++++++++++++++++++ tools/perf/util/callchain.h | 3 +++ 5 files changed, 32 insertions(+), 41 deletions(-)
tools/perf/ui/browsers/hists.c +0 -17
@@ -463,23 +463,6 @@ out:return key; } -static char *callchain_list__sym_name (struct callchain_list *cl, -char *bf,size_t bfsize,bool show_dso) -{ -int printed; - -if (cl->ms.sym) - printed =scnprintf (bf, bfsize,"%s" , cl->ms.sym->name); -else - printed =scnprintf (bf, bfsize,"%#" PRIx64, cl->ip); - -if (show_dso) -scnprintf (bf + printed, bfsize - printed," %s" , - cl->ms.map ? cl->ms.map->dso->short_name :"unknown" ); - -return bf; -} -struct callchain_print_arg {/* for hists browser */ off_t row_offset;
tools/perf/ui/gtk/hists.c +1 -10
@@ -89,15 +89,6 @@ void perf_gtk__init_hpp(void) perf_gtk__hpp_color_overhead_acc; } -static void callchain_list__sym_name (struct callchain_list *cl, -char *bf,size_t bfsize) -{ -if (cl->ms.sym) -scnprintf (bf, bfsize,"%s" , cl->ms.sym->name); -else -scnprintf (bf, bfsize,"%#" PRIx64, cl->ip); -} -static void perf_gtk__add_callchain (struct rb_root *root,GtkTreeStore *store,GtkTreeIter *parent,int col,u64 total) {
@@ -128,7 +119,7 @@ static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store,scnprintf (buf,sizeof (buf),"%5.2f%%" , percent);gtk_tree_store_set (store, &iter,0 , buf,-1 ); -callchain_list__sym_name (chain, buf,sizeof (buf)); +callchain_list__sym_name (chain, buf,sizeof (buf), false);gtk_tree_store_set (store, &iter, col, buf,-1 );if (need_new_parent) {
tools/perf/ui/stdio/hist.c +9 -14
@@ -41,6 +41,7 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, {int i;size_t ret =0 ; +char bf[1024 ]; ret +=callchain__fprintf_left_margin (fp, left_margin);for (i =0 ; i < depth; i++) {
@@ -56,11 +57,8 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, }else ret +=fprintf (fp,"%s" ," " ); } -if (chain->ms.sym) - ret +=fprintf (fp,"%s\n" , chain->ms.sym->name); -else - ret +=fprintf (fp,"0x%0" PRIx64"\n" , chain->ip); - +fputs (callchain_list__sym_name (chain, bf,sizeof (bf), false), fp); +fputc ('\n' , fp);return ret; }
@@ -168,6 +166,7 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,struct rb_node *node;int i =0 ;int ret =0 ; +char bf[1024 ];/* * If have one single callchain root, don't bother printing
@@ -196,10 +195,8 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root, }else ret +=callchain__fprintf_left_margin (fp, left_margin); -if (chain->ms.sym) - ret +=fprintf (fp," %s\n" , chain->ms.sym->name); -else - ret +=fprintf (fp," %p\n" , (void *)(long )chain->ip); + ret +=fprintf (fp,"%s\n" ,callchain_list__sym_name (chain, bf,sizeof (bf), + false));if (++entries_printed == callchain_param.print_limit)break ;
@@ -219,6 +216,7 @@ static size_t __callchain__fprintf_flat(FILE *fp, struct callchain_node *node, {struct callchain_list *chain;size_t ret =0 ; +char bf[1024 ];if (!node)return 0 ;
@@ -229,11 +227,8 @@ static size_t __callchain__fprintf_flat(FILE *fp, struct callchain_node *node,list_for_each_entry (chain, &node->val, list) {if (chain->ip >=PERF_CONTEXT_MAX )continue ; -if (chain->ms.sym) - ret +=fprintf (fp," %s\n" , chain->ms.sym->name); -else - ret +=fprintf (fp," %p\n" , - (void *)(long )chain->ip); + ret +=fprintf (fp," %s\n" ,callchain_list__sym_name (chain, + bf,sizeof (bf), false)); }return ret;
tools/perf/util/callchain.c +19 -0
@@ -812,3 +812,22 @@ int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node * out:return 1 ; } + +char *callchain_list__sym_name (struct callchain_list *cl, +char *bf,size_t bfsize,bool show_dso) +{ +int printed; + +if (cl->ms.sym) { + printed =scnprintf (bf, bfsize,"%s" , cl->ms.sym->name); + }else + printed =scnprintf (bf, bfsize,"%#" PRIx64, cl->ip); + +if (show_dso) +scnprintf (bf + printed, bfsize - printed," %s" , + cl->ms.map ? + cl->ms.map->dso->short_name : +"unknown" ); + +return bf; +}
tools/perf/util/callchain.h +3 -0
@@ -194,4 +194,7 @@ static inline int arch_skip_callchain_idx(struct thread *thread __maybe_unused, }#endif +char *callchain_list__sym_name (struct callchain_list *cl, +char *bf,size_t bfsize,bool show_dso); +#endif /* __PERF_CALLCHAIN_H */
Signature · 1 line
1.9.3
Re: [PATCH 05/10] perf, tools: Use a common function to resolve symbol or name
Em Wed, Nov 12, 2014 at 06:05:23PM -0800, Andi Kleen escreveu:
Quoted 6 lines
From: Andi Kleen <[email protected]>
Refactor the duplicated code to resolve the symbol name or the address of a symbol into a single function.
Used in next patch to add common functionality.
Applied.
tip-bot for Andi Kleen
merge bot[tip:perf/core] perf callchain: Use a common function to resolve symbol or name
In reply to Andi Kleenperf callchain: Use a common function to resolve symbol or name
Commit-ID: 2989ccaac48f8c3da7f77101bbf98e0ea8773d83 Gitweb: http://git.kernel.org/tip/2989ccaac48f8c3da7f77101bbf98e0ea8773d83 Author: Andi Kleen <[email protected]> AuthorDate: Wed, 12 Nov 2014 18:05:23 -0800 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Wed, 19 Nov 2014 12:33:47 -0300
perf callchain: Use a common function to resolve symbol or name
Refactor the duplicated code to resolve the symbol name or the address of a symbol into a single function.
Used in next patch to add common functionality.
--- tools/perf/ui/browsers/hists.c | 17 ----------------- tools/perf/ui/gtk/hists.c | 11 +---------- tools/perf/ui/stdio/hist.c | 23 +++++++++-------------- tools/perf/util/callchain.c | 19 +++++++++++++++++++ tools/perf/util/callchain.h | 3 +++ 5 files changed, 32 insertions(+), 41 deletions(-)
tools/perf/ui/browsers/hists.c +0 -17
@@ -463,23 +463,6 @@ out:return key; } -static char *callchain_list__sym_name (struct callchain_list *cl, -char *bf,size_t bfsize,bool show_dso) -{ -int printed; - -if (cl->ms.sym) - printed =scnprintf (bf, bfsize,"%s" , cl->ms.sym->name); -else - printed =scnprintf (bf, bfsize,"%#" PRIx64, cl->ip); - -if (show_dso) -scnprintf (bf + printed, bfsize - printed," %s" , - cl->ms.map ? cl->ms.map->dso->short_name :"unknown" ); - -return bf; -} -struct callchain_print_arg {/* for hists browser */ off_t row_offset;
tools/perf/ui/gtk/hists.c +1 -10
@@ -89,15 +89,6 @@ void perf_gtk__init_hpp(void) perf_gtk__hpp_color_overhead_acc; } -static void callchain_list__sym_name (struct callchain_list *cl, -char *bf,size_t bfsize) -{ -if (cl->ms.sym) -scnprintf (bf, bfsize,"%s" , cl->ms.sym->name); -else -scnprintf (bf, bfsize,"%#" PRIx64, cl->ip); -} -static void perf_gtk__add_callchain (struct rb_root *root,GtkTreeStore *store,GtkTreeIter *parent,int col,u64 total) {
@@ -128,7 +119,7 @@ static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store,scnprintf (buf,sizeof (buf),"%5.2f%%" , percent);gtk_tree_store_set (store, &iter,0 , buf,-1 ); -callchain_list__sym_name (chain, buf,sizeof (buf)); +callchain_list__sym_name (chain, buf,sizeof (buf), false);gtk_tree_store_set (store, &iter, col, buf,-1 );if (need_new_parent) {
tools/perf/ui/stdio/hist.c +9 -14
@@ -41,6 +41,7 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, {int i;size_t ret =0 ; +char bf[1024 ]; ret +=callchain__fprintf_left_margin (fp, left_margin);for (i =0 ; i < depth; i++) {
@@ -56,11 +57,8 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, }else ret +=fprintf (fp,"%s" ," " ); } -if (chain->ms.sym) - ret +=fprintf (fp,"%s\n" , chain->ms.sym->name); -else - ret +=fprintf (fp,"0x%0" PRIx64"\n" , chain->ip); - +fputs (callchain_list__sym_name (chain, bf,sizeof (bf), false), fp); +fputc ('\n' , fp);return ret; }
@@ -168,6 +166,7 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,struct rb_node *node;int i =0 ;int ret =0 ; +char bf[1024 ];/* * If have one single callchain root, don't bother printing
@@ -196,10 +195,8 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root, }else ret +=callchain__fprintf_left_margin (fp, left_margin); -if (chain->ms.sym) - ret +=fprintf (fp," %s\n" , chain->ms.sym->name); -else - ret +=fprintf (fp," %p\n" , (void *)(long )chain->ip); + ret +=fprintf (fp,"%s\n" ,callchain_list__sym_name (chain, bf,sizeof (bf), + false));if (++entries_printed == callchain_param.print_limit)break ;
@@ -219,6 +216,7 @@ static size_t __callchain__fprintf_flat(FILE *fp, struct callchain_node *node, {struct callchain_list *chain;size_t ret =0 ; +char bf[1024 ];if (!node)return 0 ;
@@ -229,11 +227,8 @@ static size_t __callchain__fprintf_flat(FILE *fp, struct callchain_node *node,list_for_each_entry (chain, &node->val, list) {if (chain->ip >=PERF_CONTEXT_MAX )continue ; -if (chain->ms.sym) - ret +=fprintf (fp," %s\n" , chain->ms.sym->name); -else - ret +=fprintf (fp," %p\n" , - (void *)(long )chain->ip); + ret +=fprintf (fp," %s\n" ,callchain_list__sym_name (chain, + bf,sizeof (bf), false)); }return ret;
tools/perf/util/callchain.c +19 -0
@@ -808,3 +808,22 @@ int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node * out:return 1 ; } + +char *callchain_list__sym_name (struct callchain_list *cl, +char *bf,size_t bfsize,bool show_dso) +{ +int printed; + +if (cl->ms.sym) { + printed =scnprintf (bf, bfsize,"%s" , cl->ms.sym->name); + }else + printed =scnprintf (bf, bfsize,"%#" PRIx64, cl->ip); + +if (show_dso) +scnprintf (bf + printed, bfsize - printed," %s" , + cl->ms.map ? + cl->ms.map->dso->short_name : +"unknown" ); + +return bf; +}
tools/perf/util/callchain.h +3 -0
@@ -193,4 +193,7 @@ static inline int arch_skip_callchain_idx(struct thread *thread __maybe_unused, }#endif +char *callchain_list__sym_name (struct callchain_list *cl, +char *bf,size_t bfsize,bool show_dso); +#endif /* __PERF_CALLCHAIN_H */
PATCH 6/10 perf, tools: Enable printing the srcline in the history
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
For lbr-as-callgraph we need to see the line number in the history, because many LBR entries can be in a single function, and just showing the same function name many times is not useful.
When the history code is configured to sort by address, also try to resolve the address to a file:srcline and display this in the browser. If that doesn't work still display the address.
This can be also useful without LBRs for understanding which call in a large function (or in which inlined function) called something else.
Contains fixes from Namhyung Kim
v2: Refactor code into common function
v3: Fix GTK build
v4: Rebase
--- tools/perf/util/callchain.c | 11 ++++++++++- tools/perf/util/callchain.h | 1 + tools/perf/util/srcline.c | 6 ++++-- 3 files changed, 15 insertions(+), 3 deletions(-)
tools/perf/util/callchain.c +10 -1
@@ -819,7 +819,16 @@ char *callchain_list__sym_name(struct callchain_list *cl,int printed;if (cl->ms.sym) { - printed =scnprintf (bf, bfsize,"%s" , cl->ms.sym->name); +if (callchain_param.key ==CCKEY_ADDRESS && + cl->ms.map && !cl->srcline) + cl->srcline =get_srcline (cl->ms.map->dso, +map__rip_2objdump (cl->ms.map, + cl->ip)); +if (cl->srcline) + printed =scnprintf (bf, bfsize,"%s %s" , + cl->ms.sym->name, cl->srcline); +else + printed =scnprintf (bf, bfsize,"%s" , cl->ms.sym->name); }else printed =scnprintf (bf, bfsize,"%#" PRIx64, cl->ip);
tools/perf/util/callchain.h +1 -0
@@ -71,6 +71,7 @@ extern struct callchain_param callchain_param;struct callchain_list {u64 ip;struct map_symbol ms; +char *srcline;struct list_head list; };
tools/perf/util/srcline.c +4 -2
@@ -258,7 +258,7 @@ char *get_srcline(struct dso *dso, unsigned long addr)const char *dso_name;if (!dso->has_srcline) -return SRCLINE_UNKNOWN ; + goto out;if (dso->symsrc_filename) dso_name = dso->symsrc_filename;
@@ -289,7 +289,9 @@ out: dso->has_srcline =0 ;dso__free_a2l (dso); } -return SRCLINE_UNKNOWN ; +if (asprintf (&srcline,"%s[%lx]" , dso->short_name, addr) <0 ) +return SRCLINE_UNKNOWN ; +return srcline; }void free_srcline (char *srcline)
Signature · 1 line
1.9.3
Re: [PATCH 06/10] perf, tools: Enable printing the srcline in the history
Em Wed, Nov 12, 2014 at 06:05:24PM -0800, Andi Kleen escreveu:
Quoted 6 lines
From: Andi Kleen <[email protected]>
For lbr-as-callgraph we need to see the line number in the history, because many LBR entries can be in a single function, and just showing the same function name many times is not useful.
Quoted 8 lines
When the history code is configured to sort by address, also try to resolve the address to a file:srcline and display this in the browser. If that doesn't work still display the address.
This can be also useful without LBRs for understanding which call in a large function (or in which inlined function) called something else.
Contains fixes from Namhyung Kim
Applied.
- Arnaldo
tip-bot for Andi Kleen
merge bot[tip:perf/core] perf callchain: Enable printing the srcline in the history
In reply to Andi Kleenperf callchain: Enable printing the srcline in the history
Commit-ID: 23f0981bbd89fcc1496d0490ec39ca7c91599e32 Gitweb: http://git.kernel.org/tip/23f0981bbd89fcc1496d0490ec39ca7c91599e32 Author: Andi Kleen <[email protected]> AuthorDate: Wed, 12 Nov 2014 18:05:24 -0800 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Mon, 24 Nov 2014 18:03:46 -0300
perf callchain: Enable printing the srcline in the history
For lbr-as-callgraph we need to see the line number in the history, because many LBR entries can be in a single function, and just showing the same function name many times is not useful.
When the history code is configured to sort by address, also try to resolve the address to a file:srcline and display this in the browser. If that doesn't work still display the address.
This can be also useful without LBRs for understanding which call in a large function (or in which inlined function) called something else.
Contains fixes from Namhyung Kim
v2: Refactor code into common function
v3: Fix GTK build
v4: Rebase
--- tools/perf/util/callchain.c | 11 ++++++++++- tools/perf/util/callchain.h | 1 + tools/perf/util/srcline.c | 6 ++++-- 3 files changed, 15 insertions(+), 3 deletions(-)
tools/perf/util/callchain.c +10 -1
@@ -815,7 +815,16 @@ char *callchain_list__sym_name(struct callchain_list *cl,int printed;if (cl->ms.sym) { - printed =scnprintf (bf, bfsize,"%s" , cl->ms.sym->name); +if (callchain_param.key ==CCKEY_ADDRESS && + cl->ms.map && !cl->srcline) + cl->srcline =get_srcline (cl->ms.map->dso, +map__rip_2objdump (cl->ms.map, + cl->ip)); +if (cl->srcline) + printed =scnprintf (bf, bfsize,"%s %s" , + cl->ms.sym->name, cl->srcline); +else + printed =scnprintf (bf, bfsize,"%s" , cl->ms.sym->name); }else printed =scnprintf (bf, bfsize,"%#" PRIx64, cl->ip);
tools/perf/util/callchain.h +1 -0
@@ -70,6 +70,7 @@ extern struct callchain_param callchain_param;struct callchain_list {u64 ip;struct map_symbol ms; +char *srcline;struct list_head list; };
tools/perf/util/srcline.c +4 -2
@@ -258,7 +258,7 @@ char *get_srcline(struct dso *dso, unsigned long addr)const char *dso_name;if (!dso->has_srcline) -return SRCLINE_UNKNOWN ; + goto out;if (dso->symsrc_filename) dso_name = dso->symsrc_filename;
@@ -289,7 +289,9 @@ out: dso->has_srcline =0 ;dso__free_a2l (dso); } -return SRCLINE_UNKNOWN ; +if (asprintf (&srcline,"%s[%lx]" , dso->short_name, addr) <0 ) +return SRCLINE_UNKNOWN ; +return srcline; }void free_srcline (char *srcline)
PATCH 7/10 perf, tools: Only print base source file for srcline
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
For perf report with --sort srcline only print the base source file name. This makes the results generally fit much better to the screen. The path is usually not that useful anyways because it is often from different systems.
--- tools/perf/util/srcline.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/util/srcline.c +1 -1
@@ -274,7 +274,7 @@ char *get_srcline(struct dso *dso, unsigned long addr)if (!addr2line (dso_name, addr, &file, &line, dso)) goto out; -if (asprintf (&srcline,"%s:%u" , file, line) <0 ) { +if (asprintf (&srcline,"%s:%u" ,basename (file), line) <0 ) {free (file); goto out; }
Signature · 1 line
1.9.3
Re: [PATCH 07/10] perf, tools: Only print base source file for srcline
Em Wed, Nov 12, 2014 at 06:05:25PM -0800, Andi Kleen escreveu:
Quoted 6 lines
From: Andi Kleen <[email protected]>
For perf report with --sort srcline only print the base source file name. This makes the results generally fit much better to the screen. The path is usually not that useful anyways because it is often from different systems.
Applied
Quoted 20 lines
Signed-off-by Andi Kleen <[email protected]>--- tools/perf/util/srcline.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)tools/perf/util/srcline.c +1
-1@@ -274,7 +274,7 @@ char *get_srcline(struct dso *dso, unsigned long addr)if (!addr2line (dso_name, addr, &file, &line, dso)) goto out; -if (asprintf (&srcline,"%s:%u" , file, line) <0 ) { +if (asprintf (&srcline,"%s:%u" ,basename (file), line) <0 ) {free (file); goto out; }Signature · 1 line
1.9.3
tip-bot for Andi Kleen
merge bot[tip:perf/core] perf tools: Only print base source file for srcline
In reply to Andi Kleenperf tools: Only print base source file for srcline
Commit-ID: 2de217688e8f086bf6d920d530401b56fcbc6eff Gitweb: http://git.kernel.org/tip/2de217688e8f086bf6d920d530401b56fcbc6eff Author: Andi Kleen <[email protected]> AuthorDate: Wed, 12 Nov 2014 18:05:25 -0800 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Wed, 19 Nov 2014 12:33:47 -0300
perf tools: Only print base source file for srcline
For perf report with --sort srcline only print the base source file name. This makes the results generally fit much better to the screen. The path is usually not that useful anyways because it is often from different systems.
--- tools/perf/util/srcline.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/util/srcline.c +1 -1
@@ -274,7 +274,7 @@ char *get_srcline(struct dso *dso, unsigned long addr)if (!addr2line (dso_name, addr, &file, &line, dso)) goto out; -if (asprintf (&srcline,"%s:%u" , file, line) <0 ) { +if (asprintf (&srcline,"%s:%u" ,basename (file), line) <0 ) {free (file); goto out; }
PATCH 8/10 perf, tools: Support source line numbers in annotate
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
With srcline key/sort'ing it's useful to have line numbers in the annotate window. This patch implements this.
Use objdump -l to request the line numbers and
save them in the line structure. Then the browser
displays them for source lines.
The line numbers are not displayed by default, but can be toggled on with 'k'
There is one unfortunate problem with this setup. For lines not containing source and which are outside functions objdump -l reports line numbers off by a few: it always reports the first line number in the next function even for lines that are outside the function.
I haven't found a nice way to detect/correct this. Probably objdump has to be fixed.
See https://sourceware.org/bugzilla/show_bug.cgi?id=16433
The line numbers are still useful even with these problems, as most are correct and the ones which are not are nearby.
v2: Fix help text. Handle (discriminator...) output in objdump. Left align the line numbers.
--- tools/perf/ui/browsers/annotate.c | 13 ++++++++++++- tools/perf/util/annotate.c | 30 +++++++++++++++++++++++++----- tools/perf/util/annotate.h | 1 + 3 files changed, 38 insertions(+), 6 deletions(-)
tools/perf/ui/browsers/annotate.c +12 -1
@@ -27,6 +27,7 @@ static struct annotate_browser_opt {bool hide_src_code, use_offset, jump_arrows, + show_linenr, show_nr_jumps; } annotate_browser__opts = { .use_offset = true,
@@ -128,7 +129,11 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, intif (!*dl->line)slsmg_write_nstring (" " , width - pcnt_width);else if (dl->offset ==-1 ) { - printed =scnprintf (bf,sizeof (bf),"%*s " , +if (dl->line_nr && annotate_browser__opts.show_linenr) + printed =scnprintf (bf,sizeof (bf),"%-*d " , + ab->addr_width +1 , dl->line_nr); +else + printed =scnprintf (bf,sizeof (bf),"%*s " , ab->addr_width," " );slsmg_write_nstring (bf, printed);slsmg_write_nstring (dl->line, width - printed - pcnt_width +1 );
@@ -733,6 +738,7 @@ static int annotate_browser__run(struct annotate_browser *browser,"o Toggle disassembler output/simplified view\n" "s Toggle source code view\n" "/ Search string\n" +"k Toggle line numbers\n" "r Run available scripts\n" "? Search string backwards\n");continue ;
@@ -741,6 +747,10 @@ static int annotate_browser__run(struct annotate_browser *browser,script_browse (NULL );continue ; } +case 'k' : + annotate_browser__opts.show_linenr = + !annotate_browser__opts.show_linenr; +break ;case 'H' : nd = browser->curr_hot;break ;
@@ -984,6 +994,7 @@ static struct annotate_config { } annotate__configs[] = {ANNOTATE_CFG (hide_src_code),ANNOTATE_CFG (jump_arrows), +ANNOTATE_CFG (show_linenr),ANNOTATE_CFG (show_nr_jumps), ANNOTATE_CFG(use_offset), };
tools/perf/util/annotate.c +25 -5
@@ -17,11 +17,13 @@#include "debug.h" #include "annotate.h" #include "evsel.h" +#include <regex.h> #include <pthread.h> #include <linux/bitops.h> const char *disassembler_style;const char *objdump_path; +static regex_t file_lineno;static struct ins *ins__find (const char *name);static int disasm_line__parse (char *line,char **namep,char **rawp);
@@ -570,13 +572,15 @@ out_free_name:return -1 ; } -static struct disasm_line *disasm_line__new (s64 offset,char *line,size_t privsize) +static struct disasm_line *disasm_line__new (s64 offset,char *line, +size_t privsize,int line_nr) {struct disasm_line *dl =zalloc (sizeof (*dl) + privsize);if (dl !=NULL ) { dl->offset = offset; dl->line =strdup (line); + dl->line_nr = line_nr;if (dl->line ==NULL ) goto out_delete;
@@ -788,13 +792,15 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st* The ops.raw part will be parsed further according to type of the instruction. */ static int symbol__parse_objdump_line (struct symbol *sym,struct map *map, -FILE *file,size_t privsize) +FILE *file,size_t privsize, +int *line_nr) {struct annotation *notes =symbol__annotation (sym);struct disasm_line *dl;char *line =NULL , *parsed_line, *tmp, *tmp2, *c;size_t line_len;s64 line_ip, offset =-1 ; +regmatch_t match[2 ];if (getline (&line, &line_len, file) <0 )return -1 ;
@@ -812,6 +818,12 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, line_ip =-1 ; parsed_line = line; +/* /filename:linenr ? Save line number and ignore. */ +if (regexec (&file_lineno, line,2 , match,0 ) ==0 ) { + *line_nr =atoi (line + match[1 ].rm_so); +return 0 ; + } +/* * Strip leading spaces: */
@@ -842,8 +854,9 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, parsed_line = tmp2 +1 ; } - dl =disasm_line__new (offset, parsed_line, privsize); + dl =disasm_line__new (offset, parsed_line, privsize, *line_nr);free (line); + (*line_nr)++;if (dl ==NULL )return -1 ;
@@ -869,6 +882,11 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,return 0 ; } +static __attribute__((constructor))void symbol__init_regexpr (void ) +{ +regcomp (&file_lineno,"^/[^:]+:([0-9]+)" ,REG_EXTENDED ); +} +static void delete_last_nop (struct symbol *sym) {struct annotation *notes =symbol__annotation (sym);
@@ -904,6 +922,7 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)char symfs_filename[PATH_MAX ];struct kcore_extract kce;bool delete_extract = false; +int lineno =0 ;if (filename)symbol__join_symfs (symfs_filename, filename);
@@ -982,7 +1001,7 @@ fallback: snprintf(command, sizeof(command), "%s %s%s --start-address=0x%016" PRIx64 " --stop-address=0x%016" PRIx64 - " -d %s %s -C %s 2>/dev/null|grep -v %s|expand", + " -l -d %s %s -C %s 2>/dev/null|grep -v %s|expand", objdump_path ? objdump_path : "objdump", disassembler_style ? "-M " : "", disassembler_style ? disassembler_style : "",
@@ -999,7 +1018,8 @@ fallback: goto out_free_filename;while (!feof (file)) -if (symbol__parse_objdump_line (sym, map, file, privsize) <0 ) +if (symbol__parse_objdump_line (sym, map, file, privsize, + &lineno) <0 )break ;/*
tools/perf/util/annotate.h +1 -0
@@ -58,6 +58,7 @@ struct disasm_line {char *line;char *name;struct ins *ins; +int line_nr;struct ins_operands ops; };
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 08/10] perf, tools: Support source line numbers in annotate
Em Wed, Nov 12, 2014 at 06:05:26PM -0800, Andi Kleen escreveu:
Quoted 11 lines
From: Andi Kleen <[email protected]>
With srcline key/sort'ing it's useful to have line numbers in the annotate window. This patch implements this.
Use objdump -l to request the line numbers and
save them in the line structure. Then the browser
displays them for source lines.The line numbers are not displayed by default, but can be toggled on with 'k'
Ok, I tested this, cool stuff, I'll apply after some more testing, issues:
it is right now left justified, I did a perf top -> annotate cpu_idle_loop() and I see up to 3 digits __LINE__, would be nice to figure out the max number of digits and right justify as the jump target labels are.
Also the numbers sometimes change dramatically, that is because at those places we see inlined stuff, so another toogle for the basename source code would be as well nice.
Also it is on the same column as the jump target labels, which is kinda OK because it makes it more compact, and one can figure out one from the other because labels are colon suffixed.
Anyway, I think it is good to go now, we can improve these things later.
- Arnaldo
Quoted 202 lines
There is one unfortunate problem with this setup. For lines not containing source and which are outside functions objdump -l reports line numbers off by a few: it always reports the first line number in the next function even for lines that are outside the function.
I haven't found a nice way to detect/correct this. Probably objdump has to be fixed.
See https://sourceware.org/bugzilla/show_bug.cgi?id=16433The line numbers are still useful even with these problems, as most are correct and the ones which are not are nearby.
v2: Fix help text. Handle (discriminator...) output in objdump. Left align the line numbers.
Signed-off-by Andi Kleen <[email protected]>--- tools/perf/ui/browsers/annotate.c | 13 ++++++++++++- tools/perf/util/annotate.c | 30 +++++++++++++++++++++++++----- tools/perf/util/annotate.h | 1 + 3 files changed, 38 insertions(+), 6 deletions(-)tools/perf/ui/browsers/annotate.c +12
-1@@ -27,6 +27,7 @@ static struct annotate_browser_opt {bool hide_src_code, use_offset, jump_arrows, + show_linenr, show_nr_jumps; } annotate_browser__opts = { .use_offset = true,@@ -128,7 +129,11 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, intif (!*dl->line)slsmg_write_nstring (" " , width - pcnt_width);else if (dl->offset ==-1 ) { - printed =scnprintf (bf,sizeof (bf),"%*s " , +if (dl->line_nr && annotate_browser__opts.show_linenr) + printed =scnprintf (bf,sizeof (bf),"%-*d " , + ab->addr_width +1 , dl->line_nr); +else + printed =scnprintf (bf,sizeof (bf),"%*s " , ab->addr_width," " );slsmg_write_nstring (bf, printed);slsmg_write_nstring (dl->line, width - printed - pcnt_width +1 );@@ -733,6 +738,7 @@ static int annotate_browser__run(struct annotate_browser *browser,"o Toggle disassembler output/simplified view\n" "s Toggle source code view\n" "/ Search string\n" +"k Toggle line numbers\n" "r Run available scripts\n" "? Search string backwards\n");continue ;@@ -741,6 +747,10 @@ static int annotate_browser__run(struct annotate_browser *browser,script_browse (NULL );continue ; } +case 'k' : + annotate_browser__opts.show_linenr = + !annotate_browser__opts.show_linenr; +break ;case 'H' : nd = browser->curr_hot;break ;@@ -984,6 +994,7 @@ static struct annotate_config { } annotate__configs[] = {ANNOTATE_CFG (hide_src_code),ANNOTATE_CFG (jump_arrows), +ANNOTATE_CFG (show_linenr),ANNOTATE_CFG (show_nr_jumps), ANNOTATE_CFG(use_offset), };tools/perf/util/annotate.c +25
-5@@ -17,11 +17,13 @@#include "debug.h" #include "annotate.h" #include "evsel.h" +#include <regex.h> #include <pthread.h> #include <linux/bitops.h> const char *disassembler_style;const char *objdump_path; +static regex_t file_lineno;static struct ins *ins__find (const char *name);static int disasm_line__parse (char *line,char **namep,char **rawp);@@ -570,13 +572,15 @@ out_free_name:return -1 ; } -static struct disasm_line *disasm_line__new (s64 offset,char *line,size_t privsize) +static struct disasm_line *disasm_line__new (s64 offset,char *line, +size_t privsize,int line_nr) {struct disasm_line *dl =zalloc (sizeof (*dl) + privsize);if (dl !=NULL ) { dl->offset = offset; dl->line =strdup (line); + dl->line_nr = line_nr;if (dl->line ==NULL ) goto out_delete;@@ -788,13 +792,15 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st* The ops.raw part will be parsed further according to type of the instruction. */ static int symbol__parse_objdump_line (struct symbol *sym,struct map *map, -FILE *file,size_t privsize) +FILE *file,size_t privsize, +int *line_nr) {struct annotation *notes =symbol__annotation (sym);struct disasm_line *dl;char *line =NULL , *parsed_line, *tmp, *tmp2, *c;size_t line_len;s64 line_ip, offset =-1 ; +regmatch_t match[2 ];if (getline (&line, &line_len, file) <0 )return -1 ;@@ -812,6 +818,12 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, line_ip =-1 ; parsed_line = line; +/* /filename:linenr ? Save line number and ignore. */ +if (regexec (&file_lineno, line,2 , match,0 ) ==0 ) { + *line_nr =atoi (line + match[1 ].rm_so); +return 0 ; + } +/* * Strip leading spaces: */ @@ -842,8 +854,9 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, parsed_line = tmp2 +1 ; } - dl =disasm_line__new (offset, parsed_line, privsize); + dl =disasm_line__new (offset, parsed_line, privsize, *line_nr);free (line); + (*line_nr)++;if (dl ==NULL )return -1 ;@@ -869,6 +882,11 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,return 0 ; } +static __attribute__((constructor))void symbol__init_regexpr (void ) +{ +regcomp (&file_lineno,"^/[^:]+:([0-9]+)" ,REG_EXTENDED ); +} +static void delete_last_nop (struct symbol *sym) {struct annotation *notes =symbol__annotation (sym);@@ -904,6 +922,7 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)char symfs_filename[PATH_MAX ];struct kcore_extract kce;bool delete_extract = false; +int lineno =0 ;if (filename)symbol__join_symfs (symfs_filename, filename);@@ -982,7 +1001,7 @@ fallback: snprintf(command, sizeof(command), "%s %s%s --start-address=0x%016" PRIx64 " --stop-address=0x%016" PRIx64 - " -d %s %s -C %s 2>/dev/null|grep -v %s|expand", + " -l -d %s %s -C %s 2>/dev/null|grep -v %s|expand", objdump_path ? objdump_path : "objdump", disassembler_style ? "-M " : "", disassembler_style ? disassembler_style : "",@@ -999,7 +1018,8 @@ fallback: goto out_free_filename;while (!feof (file)) -if (symbol__parse_objdump_line (sym, map, file, privsize) <0 ) +if (symbol__parse_objdump_line (sym, map, file, privsize, + &lineno) <0 )break ;/* tools/perf/util/annotate.h +1
-0@@ -58,6 +58,7 @@ struct disasm_line {char *line;char *name;struct ins *ins; +int line_nr;struct ins_operands ops; };Signature · 1 line
1.9.3
tip-bot for Andi Kleen
merge bot[tip:perf/core] perf annotate: Support source line numbers in annotate
In reply to Andi Kleenperf annotate: Support source line numbers in annotate
Commit-ID: e592488c01d51763de847fcecb3d969231a483a9 Gitweb: http://git.kernel.org/tip/e592488c01d51763de847fcecb3d969231a483a9 Author: Andi Kleen <[email protected]> AuthorDate: Wed, 12 Nov 2014 18:05:26 -0800 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Wed, 19 Nov 2014 12:33:48 -0300
perf annotate: Support source line numbers in annotate
With srcline key/sort'ing it's useful to have line numbers in the annotate window. This patch implements this.
Use objdump -l to request the line numbers and save them in the line structure. Then the browser displays them for source lines.
The line numbers are not displayed by default, but can be toggled on with 'k'
There is one unfortunate problem with this setup. For lines not containing source and which are outside functions objdump -l reports line numbers off by a few: it always reports the first line number in the next function even for lines that are outside the function.
I haven't found a nice way to detect/correct this. Probably objdump has to be fixed.
See https://sourceware.org/bugzilla/show_bug.cgi?id=16433
The line numbers are still useful even with these problems, as most are correct and the ones which are not are nearby.
v2: Fix help text. Handle (discriminator...) output in objdump. Left align the line numbers.
--- tools/perf/ui/browsers/annotate.c | 13 ++++++++++++- tools/perf/util/annotate.c | 30 +++++++++++++++++++++++++----- tools/perf/util/annotate.h | 1 + 3 files changed, 38 insertions(+), 6 deletions(-)
tools/perf/ui/browsers/annotate.c +12 -1
@@ -27,6 +27,7 @@ static struct annotate_browser_opt {bool hide_src_code, use_offset, jump_arrows, + show_linenr, show_nr_jumps; } annotate_browser__opts = { .use_offset = true,
@@ -128,7 +129,11 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, intif (!*dl->line)slsmg_write_nstring (" " , width - pcnt_width);else if (dl->offset ==-1 ) { - printed =scnprintf (bf,sizeof (bf),"%*s " , +if (dl->line_nr && annotate_browser__opts.show_linenr) + printed =scnprintf (bf,sizeof (bf),"%-*d " , + ab->addr_width +1 , dl->line_nr); +else + printed =scnprintf (bf,sizeof (bf),"%*s " , ab->addr_width," " );slsmg_write_nstring (bf, printed);slsmg_write_nstring (dl->line, width - printed - pcnt_width +1 );
@@ -733,6 +738,7 @@ static int annotate_browser__run(struct annotate_browser *browser,"o Toggle disassembler output/simplified view\n" "s Toggle source code view\n" "/ Search string\n" +"k Toggle line numbers\n" "r Run available scripts\n" "? Search string backwards\n");continue ;
@@ -741,6 +747,10 @@ static int annotate_browser__run(struct annotate_browser *browser,script_browse (NULL );continue ; } +case 'k' : + annotate_browser__opts.show_linenr = + !annotate_browser__opts.show_linenr; +break ;case 'H' : nd = browser->curr_hot;break ;
@@ -984,6 +994,7 @@ static struct annotate_config { } annotate__configs[] = {ANNOTATE_CFG (hide_src_code),ANNOTATE_CFG (jump_arrows), +ANNOTATE_CFG (show_linenr),ANNOTATE_CFG (show_nr_jumps), ANNOTATE_CFG(use_offset), };
tools/perf/util/annotate.c +25 -5
@@ -17,11 +17,13 @@#include "debug.h" #include "annotate.h" #include "evsel.h" +#include <regex.h> #include <pthread.h> #include <linux/bitops.h> const char *disassembler_style;const char *objdump_path; +static regex_t file_lineno;static struct ins *ins__find (const char *name);static int disasm_line__parse (char *line,char **namep,char **rawp);
@@ -570,13 +572,15 @@ out_free_name:return -1 ; } -static struct disasm_line *disasm_line__new (s64 offset,char *line,size_t privsize) +static struct disasm_line *disasm_line__new (s64 offset,char *line, +size_t privsize,int line_nr) {struct disasm_line *dl =zalloc (sizeof (*dl) + privsize);if (dl !=NULL ) { dl->offset = offset; dl->line =strdup (line); + dl->line_nr = line_nr;if (dl->line ==NULL ) goto out_delete;
@@ -788,13 +792,15 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st* The ops.raw part will be parsed further according to type of the instruction. */ static int symbol__parse_objdump_line (struct symbol *sym,struct map *map, -FILE *file,size_t privsize) +FILE *file,size_t privsize, +int *line_nr) {struct annotation *notes =symbol__annotation (sym);struct disasm_line *dl;char *line =NULL , *parsed_line, *tmp, *tmp2, *c;size_t line_len;s64 line_ip, offset =-1 ; +regmatch_t match[2 ];if (getline (&line, &line_len, file) <0 )return -1 ;
@@ -812,6 +818,12 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, line_ip =-1 ; parsed_line = line; +/* /filename:linenr ? Save line number and ignore. */ +if (regexec (&file_lineno, line,2 , match,0 ) ==0 ) { + *line_nr =atoi (line + match[1 ].rm_so); +return 0 ; + } +/* * Strip leading spaces: */
@@ -842,8 +854,9 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, parsed_line = tmp2 +1 ; } - dl =disasm_line__new (offset, parsed_line, privsize); + dl =disasm_line__new (offset, parsed_line, privsize, *line_nr);free (line); + (*line_nr)++;if (dl ==NULL )return -1 ;
@@ -869,6 +882,11 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,return 0 ; } +static __attribute__((constructor))void symbol__init_regexpr (void ) +{ +regcomp (&file_lineno,"^/[^:]+:([0-9]+)" ,REG_EXTENDED ); +} +static void delete_last_nop (struct symbol *sym) {struct annotation *notes =symbol__annotation (sym);
@@ -904,6 +922,7 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)char symfs_filename[PATH_MAX ];struct kcore_extract kce;bool delete_extract = false; +int lineno =0 ;if (filename)symbol__join_symfs (symfs_filename, filename);
@@ -984,7 +1003,7 @@ fallback: snprintf(command, sizeof(command), "%s %s%s --start-address=0x%016" PRIx64 " --stop-address=0x%016" PRIx64 - " -d %s %s -C %s 2>/dev/null|grep -v %s|expand", + " -l -d %s %s -C %s 2>/dev/null|grep -v %s|expand", objdump_path ? objdump_path : "objdump", disassembler_style ? "-M " : "", disassembler_style ? disassembler_style : "",
@@ -1001,7 +1020,8 @@ fallback: goto out_free_filename;while (!feof (file)) -if (symbol__parse_objdump_line (sym, map, file, privsize) <0 ) +if (symbol__parse_objdump_line (sym, map, file, privsize, + &lineno) <0 )break ;/*
tools/perf/util/annotate.h +1 -0
@@ -58,6 +58,7 @@ struct disasm_line {char *line;char *name;struct ins *ins; +int line_nr;struct ins_operands ops; };
PATCH 9/10 tools, perf: Make get_srcline fall back to sym+offset
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
When the source line is not found fall back to sym + offset. This is generally much more useful than a raw address. For this we need to pass in the symbol from the caller. For some callers it's awkward to compute, so we stay at the old behaviour.
--- tools/perf/util/annotate.c | 2 +- tools/perf/util/callchain.c | 3 ++- tools/perf/util/map.c | 2 +- tools/perf/util/sort.c | 6 ++++-- tools/perf/util/srcline.c | 12 +++++++++--- tools/perf/util/util.h | 4 +++- 6 files changed, 20 insertions(+), 9 deletions(-)
tools/perf/util/annotate.c +1 -1
@@ -1190,7 +1190,7 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map, goto next; offset = start + i; - src_line->path =get_srcline (map->dso, offset); + src_line->path =get_srcline (map->dso, offset,NULL , false);insert_source_line (&tmp_root, src_line); next:
tools/perf/util/callchain.c +2 -1
@@ -823,7 +823,8 @@ char *callchain_list__sym_name(struct callchain_list *cl, cl->ms.map && !cl->srcline) cl->srcline =get_srcline (cl->ms.map->dso,map__rip_2objdump (cl->ms.map, - cl->ip)); + cl->ip), + cl->ms.sym, false);if (cl->srcline) printed =scnprintf (bf, bfsize,"%s %s" , cl->ms.sym->name, cl->srcline);
tools/perf/util/map.c +1 -1
@@ -360,7 +360,7 @@ int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix,if (map && map->dso) { srcline =get_srcline (map->dso, -map__rip_2objdump (map, addr)); +map__rip_2objdump (map, addr),NULL , true);if (srcline !=SRCLINE_UNKNOWN ) ret =fprintf (fp,"%s%s" , prefix, srcline);free_srcline (srcline);
tools/perf/util/sort.c +4 -2
@@ -291,7 +291,8 @@ sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)else {struct map *map = left->ms.map; left->srcline =get_srcline (map->dso, -map__rip_2objdump (map, left->ip)); +map__rip_2objdump (map, left->ip), + left->ms.sym, true); } }if (!right->srcline) {
@@ -300,7 +301,8 @@ sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)else {struct map *map = right->ms.map; right->srcline =get_srcline (map->dso, -map__rip_2objdump (map, right->ip)); +map__rip_2objdump (map, right->ip), + right->ms.sym, true); } }return strcmp (right->srcline, left->srcline);
tools/perf/util/srcline.c +9 -3
@@ -8,12 +8,13 @@#include "util/util.h" #include "util/debug.h" +#include "symbol.h" +#ifdef HAVE_LIBBFD_SUPPORT /* * Implement addr2line using libbfd. */ -#define PACKAGE "perf"#include <bfd.h> struct a2l_data {
@@ -250,7 +251,8 @@ void dso__free_a2l(struct dso *dso __maybe_unused)*/ #define A2L_FAIL_LIMIT 123 -char *get_srcline (struct dso *dso,unsigned long addr) +char *get_srcline (struct dso *dso,unsigned long addr,struct symbol *sym, +bool show_sym) {char *file =NULL ;unsigned line =0 ;
@@ -289,7 +291,11 @@ out: dso->has_srcline =0 ;dso__free_a2l (dso); } -if (asprintf (&srcline,"%s[%lx]" , dso->short_name, addr) <0 ) +if (sym) { +if (asprintf (&srcline,"%s+%ld" , show_sym ? sym->name :"" , + addr - sym->start) <0 ) +return SRCLINE_UNKNOWN ; + }else if (asprintf (&srcline,"%s[%lx]" , dso->short_name, addr) <0 )return SRCLINE_UNKNOWN ;return srcline; }
tools/perf/util/util.h +3 -1
@@ -338,8 +338,10 @@ static inline int path__join3(char *bf, size_t size, }struct dso ; +struct symbol ; -char *get_srcline (struct dso *dso,unsigned long addr); +char *get_srcline (struct dso *dso,unsigned long addr,struct symbol *sym, +bool show_sym);void free_srcline (char *srcline);int filename__read_int (const char *filename,int *value);
Signature · 1 line
1.9.3
tip-bot for Andi Kleen
merge bot[tip:perf/core] perf callchain: Make get_srcline fall back to sym+offset
perf callchain: Make get_srcline fall back to sym+offset
Commit-ID: 85c116a6cb91a5c09b7a6c95ffc6a6cbd32cd237 Gitweb: http://git.kernel.org/tip/85c116a6cb91a5c09b7a6c95ffc6a6cbd32cd237 Author: Andi Kleen <[email protected]> AuthorDate: Wed, 12 Nov 2014 18:05:27 -0800 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Mon, 24 Nov 2014 18:03:47 -0300
perf callchain: Make get_srcline fall back to sym+offset
When the source line is not found fall back to sym + offset. This is generally much more useful than a raw address.
For this we need to pass in the symbol from the caller.
For some callers it's awkward to compute, so we stay at the old behaviour.
--- tools/perf/util/annotate.c | 2 +- tools/perf/util/callchain.c | 3 ++- tools/perf/util/map.c | 2 +- tools/perf/util/sort.c | 6 ++++-- tools/perf/util/srcline.c | 11 +++++++++-- tools/perf/util/util.h | 4 +++- 6 files changed, 20 insertions(+), 8 deletions(-)
tools/perf/util/annotate.c +1 -1
@@ -1192,7 +1192,7 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map, goto next; offset = start + i; - src_line->path =get_srcline (map->dso, offset); + src_line->path =get_srcline (map->dso, offset,NULL , false);insert_source_line (&tmp_root, src_line); next:
tools/perf/util/callchain.c +2 -1
@@ -819,7 +819,8 @@ char *callchain_list__sym_name(struct callchain_list *cl, cl->ms.map && !cl->srcline) cl->srcline =get_srcline (cl->ms.map->dso,map__rip_2objdump (cl->ms.map, - cl->ip)); + cl->ip), + cl->ms.sym, false);if (cl->srcline) printed =scnprintf (bf, bfsize,"%s %s" , cl->ms.sym->name, cl->srcline);
tools/perf/util/map.c +1 -1
@@ -360,7 +360,7 @@ int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix,if (map && map->dso) { srcline =get_srcline (map->dso, -map__rip_2objdump (map, addr)); +map__rip_2objdump (map, addr),NULL , true);if (srcline !=SRCLINE_UNKNOWN ) ret =fprintf (fp,"%s%s" , prefix, srcline);free_srcline (srcline);
tools/perf/util/sort.c +4 -2
@@ -291,7 +291,8 @@ sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)else {struct map *map = left->ms.map; left->srcline =get_srcline (map->dso, -map__rip_2objdump (map, left->ip)); +map__rip_2objdump (map, left->ip), + left->ms.sym, true); } }if (!right->srcline) {
@@ -300,7 +301,8 @@ sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)else {struct map *map = right->ms.map; right->srcline =get_srcline (map->dso, -map__rip_2objdump (map, right->ip)); +map__rip_2objdump (map, right->ip), + right->ms.sym, true); } }return strcmp (right->srcline, left->srcline);
tools/perf/util/srcline.c +9 -2
@@ -8,6 +8,8 @@#include "util/util.h" #include "util/debug.h" +#include "symbol.h" +#ifdef HAVE_LIBBFD_SUPPORT /*
@@ -250,7 +252,8 @@ void dso__free_a2l(struct dso *dso __maybe_unused)*/ #define A2L_FAIL_LIMIT 123 -char *get_srcline (struct dso *dso,unsigned long addr) +char *get_srcline (struct dso *dso,unsigned long addr,struct symbol *sym, +bool show_sym) {char *file =NULL ;unsigned line =0 ;
@@ -289,7 +292,11 @@ out: dso->has_srcline =0 ;dso__free_a2l (dso); } -if (asprintf (&srcline,"%s[%lx]" , dso->short_name, addr) <0 ) +if (sym) { +if (asprintf (&srcline,"%s+%ld" , show_sym ? sym->name :"" , + addr - sym->start) <0 ) +return SRCLINE_UNKNOWN ; + }else if (asprintf (&srcline,"%s[%lx]" , dso->short_name, addr) <0 )return SRCLINE_UNKNOWN ;return srcline; }
tools/perf/util/util.h +3 -1
@@ -337,8 +337,10 @@ static inline int path__join3(char *bf, size_t size, }struct dso ; +struct symbol ; -char *get_srcline (struct dso *dso,unsigned long addr); +char *get_srcline (struct dso *dso,unsigned long addr,struct symbol *sym, +bool show_sym);void free_srcline (char *srcline);int filename__read_int (const char *filename,int *value);
PATCH 10/10 tools, perf: Add asprintf replacement
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
asprintf corrupts memory on some older glibc versions. Provide a replacement. This fixes various segfaults with --branch-history on older Fedoras.
v2: Remove bogus hunk.
Support arbitrary size (Geert Uytterhoeven)
--- tools/perf/Makefile.perf | 1 + tools/perf/builtin-report.c | 1 + tools/perf/util/asprintf.c | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 tools/perf/util/asprintf.c
tools/perf/Makefile.perf +1 -0
@@ -395,6 +395,7 @@ LIB_OBJS += $(OUTPUT)util/vdso.o LIB_OBJS += $(OUTPUT)util/stat.o LIB_OBJS += $(OUTPUT)util/record.o LIB_OBJS += $(OUTPUT)util/srcline.o +LIB_OBJS += $(OUTPUT)util/asprintf.o LIB_OBJS += $(OUTPUT)util/data.o LIB_OBJS += $(OUTPUT)util/tsc.o LIB_OBJS += $(OUTPUT)util/cloexec.o
tools/perf/builtin-report.c +1 -0
@@ -762,6 +762,7 @@ repeat: }if (branch_call_mode) { callchain_param.branch_callstack =1 ; + callchain_param.key =CCKEY_ADDRESS ; symbol_conf.use_callchain = true;callchain_register_param (&callchain_param);if (sort_order ==NULL )
tools/perf/util/asprintf.c new file +34 -0
@@ -0,0 +1,34 @@ +/* Replacement for asprintf as it's buggy in older glibc versions */ +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> + +int vasprintf (char **str,const char *fmt,va_list ap) +{ +va_list ao; +char buf[1024 ]; +int len; + +va_copy (ao, ap); + len =vsnprintf (buf,sizeof (buf), fmt, ap); + *str =malloc (len +1 ); +if (!*str) +return -1 ; +if ((size_t )len <sizeof (buf)) { +strcpy (*str, buf); +return len; + } +return vsnprintf (*str, len +1 , fmt, ao); +} + +int asprintf (char **str,const char *fmt, ...) +{ +va_list ap; +int ret; + +va_start (ap, fmt); + ret =vasprintf (str, fmt, ap); +va_end (ap); +return ret; +}
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 10/10] tools, perf: Add asprintf replacement
Em Wed, Nov 12, 2014 at 06:05:28PM -0800, Andi Kleen escreveu:
Quoted 33 lines
From: Andi Kleen <[email protected]>
asprintf corrupts memory on some older glibc versions. Provide a replacement. This fixes various segfaults with --branch-history on older Fedoras.
v2: Remove bogus hunk.
Support arbitrary size (Geert Uytterhoeven)Signed-off-by Andi Kleen <[email protected]>--- tools/perf/Makefile.perf | 1 + tools/perf/builtin-report.c | 1 + tools/perf/util/asprintf.c | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 tools/perf/util/asprintf.ctools/perf/Makefile.perf +1
-0@@ -395,6 +395,7 @@ LIB_OBJS += $(OUTPUT)util/vdso.o LIB_OBJS += $(OUTPUT)util/stat.o LIB_OBJS += $(OUTPUT)util/record.o LIB_OBJS += $(OUTPUT)util/srcline.o +LIB_OBJS += $(OUTPUT)util/asprintf.o LIB_OBJS += $(OUTPUT)util/data.o LIB_OBJS += $(OUTPUT)util/tsc.o LIB_OBJS += $(OUTPUT)util/cloexec.otools/perf/builtin-report.c +0
-0
tools/perf/builtin-report.c repeat: · line 765
Quoted 4 lines
tools/perf/builtin-report.c +1
-0@@ -762,6 +762,7 @@ repeat: }if (branch_call_mode) { callchain_param.branch_callstack =1 ; + callchain_param.key =CCKEY_ADDRESS ;
unrelated hunk?
- Arnaldo
Quoted 45 lines
tools/perf/builtin-report.c +0
-0symbol_conf.use_callchain = true;callchain_register_param (&callchain_param);if (sort_order ==NULL )tools/perf/util/asprintf.c new file +34
-0@@ -0,0 +1,34 @@ +/* Replacement for asprintf as it's buggy in older glibc versions */ +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> + +int vasprintf (char **str,const char *fmt,va_list ap) +{ +va_list ao; +char buf[1024 ]; +int len; + +va_copy (ao, ap); + len =vsnprintf (buf,sizeof (buf), fmt, ap); + *str =malloc (len +1 ); +if (!*str) +return -1 ; +if ((size_t )len <sizeof (buf)) { +strcpy (*str, buf); +return len; + } +return vsnprintf (*str, len +1 , fmt, ao); +} + +int asprintf (char **str,const char *fmt, ...) +{ +va_list ap; +int ret; + +va_start (ap, fmt); + ret =vasprintf (str, fmt, ap); +va_end (ap); +return ret; +}Signature · 1 line
1.9.3
Re: [PATCH 10/10] tools, perf: Add asprintf replacement
Quoted 11 lines
tools/perf/builtin-report.c repeat: · line 765
Quoted 9 lines
tools/perf/builtin-report.c +1
-0@@ -762,6 +762,7 @@ repeat: }if (branch_call_mode) { callchain_param.branch_callstack =1 ; + callchain_param.key =CCKEY_ADDRESS ;unrelated hunk?
Yes. Please remove.
Arnaldo Carvalho de Melo
maintainerEm Wed, Nov 12, 2014 at 06:05:18PM -0800, Andi Kleen escreveu:
Quoted 9 lines
[Reworks to address all the review feedback. Rebased to latest tree] [Just a repost after a rebase]
[Even more review feedback and some bugs addressed.] [Only port to changes in perf/core. No other changes.] [Rebase to latest perf/core]
[Another rebase. No changes]This patchkit implements lbr-as-callgraphs in per freport, as an alternative way to present LBR information.
Ok, I have this in my perf/core branch, but I need to test it further, as I couldn't get the output that appears on some of the changelogs.
If you could take a look at
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux perf/core
To see if I made some mistake, that would be of help,
Thanks
- Arnaldo
Quoted 75 lines
Current perf report does a histogram over the branch edges, which is useful to look at basic blocks, but doesn't tell you anything about the larger control flow behaviour.
This patchkit adds a new option --branch-history that adds the branch paths to the callgraph history instead.
This allows to reason about individual branch paths leading to specific samples.
Also available at
git://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-miscperf/lbr-callgraph8v2:
- rebased on perf/core
- fix various issues
- rename the option to --branch-history
- various fixes to display the information more concise v3:
- White space changes
- Consolidate some patches
- Update some descriptions
v4:
- Fix various display problems
- Unknown srcline is now printed as symbol+offset
- Refactor some code to address review feedback
- Merge with latest tip
- Fix missing srcline display in stdio hist output. v5:
- Rename functions
- Fix gtk build problem
- Fix crash without -g
- Improve error messages
- Improve srcline display in various ways
v6:
- Port to latest perf/core
v7:
- Really port to latest perf/core
v8:
- Rebased on 3.16-rc1
v9:
- Rebase on 3.17-rc* tip/perf/core
v10:
- Rebase to latest tree.
- Address review feedback (except where commented). See the individual patches for changelog. I dropped the -v option support.Example output:
% perf record -b -g ./tsrc/tcall
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.044 MB perf.data (~1923 samples) ] % perf report --branch-history
...
54.91% tcall.c:6 [.] f2 tcall
|
|--65.53%-- f2 tcall.c:5
| |
| |--70.83%-- f1 tcall.c:11
| | f1 tcall.c:10
| | main tcall.c:18
| | main tcall.c:18
| | main tcall.c:17
| | main tcall.c:17
| | f1 tcall.c:13
| | f1 tcall.c:13
| | f2 tcall.c:7
| | f2 tcall.c:5
| | f1 tcall.c:12
| | f1 tcall.c:12
| | f2 tcall.c:7
| | f2 tcall.c:5
| | f1 tcall.c:11
Quoted 11 lines · Arnaldo Carvalho de Melo
Em Wed, Nov 12, 2014 at 06:05:18PM -0800, Andi Kleen escreveu:
Quoted 9 lines
[Reworks to address all the review feedback. Rebased to latest tree] [Just a repost after a rebase]
[Even more review feedback and some bugs addressed.] [Only port to changes in perf/core. No other changes.] [Rebase to latest perf/core]
[Another rebase. No changes]This patchkit implements lbr-as-callgraphs in per freport, as an alternative way to present LBR information.
Quoted 8 lines
Ok, I have this in my perf/core branch, but I need to test it further, as I couldn't get the output that appears on some of the changelogs.
If you could take a look at
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linuxperf/coreTo see if I made some mistake, that would be of help,
Sorry the CCKEY_ADDRESS hunk was actually needed. With that I get the srclines as expected.
Also the BUILD_BUG_ON change breaks the compilation with optimization off (DEBUG=1). I'll send patches for both.
Also please consider the adding the symbol offset fix patch I sent Friday.
-Andi
Quoted 11 lines · Arnaldo Carvalho de Melo
Em Wed, Nov 12, 2014 at 06:05:18PM -0800, Andi Kleen escreveu:
Quoted 9 lines
[Reworks to address all the review feedback. Rebased to latest tree] [Just a repost after a rebase]
[Even more review feedback and some bugs addressed.] [Only port to changes in perf/core. No other changes.] [Rebase to latest perf/core]
[Another rebase. No changes]This patchkit implements lbr-as-callgraphs in per freport, as an alternative way to present LBR information.
Quoted 9 lines
Ok, I have this in my perf/core branch, but I need to test it further, as I couldn't get the output that appears on some of the changelogs.
If you could take a look at
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linuxperf/coreTo see if I made some mistake, that would be of help,
I'm getting compile error for DEBUG=1
jirka
[jolsa@krava perf]$ make DEBUG=1 JOBS=1
BUILD: Doing 'make -j1' parallel build
CC util/machine.o
In file included from /home/jolsa/kernel.org/linux-perf/tools/perf/util/include/../../../../include/uapi/linux/swab.h:5:0,
from /home/jolsa/kernel.org/linux-perf/tools/perf/util/include/asm/byteorder.h:2,
from /home/jolsa/kernel.org/linux-perf/include/uapi/linux/perf_event.h:19,
from util/../perf.h:7,
from util/callchain.h:4,
from util/machine.c:1:
util/machine.c: In function ‘remove_loops’:
/home/jolsa/kernel.org/linux-perf/tools/include/linux/compiler.h:64:20: error: call to ‘__compiletime_assert_1450’ declared with attribute error: Please upgrade the type of the hash table from unsigned char
prefix ## suffix(); \
^/home/jolsa/kernel.org/linux-perf/tools/include/linux/compiler.h:69:2: note: in expansion of macro ‘__compiletime_assert’
__compiletime_assert(condition, msg, prefix, suffix)
^/home/jolsa/kernel.org/linux-perf/tools/include/linux/compiler.h:81:2: note: in expansion of macro ‘_compiletime_assert’
_compiletime_assert(condition, msg, __compiletime_assert_, __LINE__)
^/home/jolsa/kernel.org/linux-perf/tools/include/linux/bug.h:13:37: note: in expansion of macro ‘compiletime_assert’
#define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
^util/machine.c:1449:2: note: in expansion of macro ‘BUILD_BUG_ON_MSG’
BUILD_BUG_ON_MSG(PERF_MAX_BRANCH_DEPTH > 127,
^
make[1]: *** [util/machine.o] Error 1
make: *** [all] Error 2
Quoted 15 lines · Jiri Olsa
Quoted 14 lines · Arnaldo Carvalho de Melo
Em Wed, Nov 12, 2014 at 06:05:18PM -0800, Andi Kleen escreveu:
Quoted 9 lines
[Reworks to address all the review feedback. Rebased to latest tree] [Just a repost after a rebase]
[Even more review feedback and some bugs addressed.] [Only port to changes in perf/core. No other changes.] [Rebase to latest perf/core]
[Another rebase. No changes]This patchkit implements lbr-as-callgraphs in per freport, as an alternative way to present LBR information.
Ok, I have this in my perf/core branch, but I need to test it further, as I couldn't get the output that appears on some of the changelogs.
Quoted 8 lines
Quoted 6 lines
If you could take a look at
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linuxperf/coreTo see if I made some mistake, that would be of help,
I'm getting compile error for DEBUG=1
looks like the BUILD_BUG_ON_MSG does not work correctly with -O6 we use
jirka
Quoted 31 lines
jirka
[jolsa@krava perf]$ make DEBUG=1 JOBS=1
BUILD: Doing 'make -j1' parallel build
CCutil/machine.o
In file included from/home/jolsa/kernel.org/linux-perf/tools/perf/util/include/../../../../include/uapi/linux/swab.h:5:0,from /home/jolsa/kernel.org/linux-perf/tools/perf/util/include/asm/byteorder.h:2, from /home/jolsa/kernel.org/linux-perf/include/uapi/linux/perf_event.h:19, from util/../perf.h:7, from util/callchain.h:4, from util/machine.c:1: util/machine.c: In function ‘remove_loops’: /home/jolsa/kernel.org/linux-perf/tools/include/linux/compiler.h:64:20: error: call to ‘__compiletime_assert_1450’ declared with attribute error: Please upgrade the type of the hash table from unsigned char prefix ## suffix(); \ ^
/home/jolsa/kernel.org/linux-perf/tools/include/linux/compiler.h:69:2: note: in expansion of macro ‘__compiletime_assert’
__compiletime_assert(condition, msg, prefix, suffix)
^/home/jolsa/kernel.org/linux-perf/tools/include/linux/compiler.h:81:2: note: in expansion of macro ‘_compiletime_assert’
_compiletime_assert(condition, msg, __compiletime_assert_, __LINE__)
^/home/jolsa/kernel.org/linux-perf/tools/include/linux/bug.h:13:37: note: in expansion of macro ‘compiletime_assert’#define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) ^
util/machine.c:1449:2: note: in expansion of macro ‘BUILD_BUG_ON_MSG’
BUILD_BUG_ON_MSG(PERF_MAX_BRANCH_DEPTH > 127,
^
make[1]: *** [util/machine.o] Error 1
make: *** [all] Error 2
Namhyung Kim
maintainerHi Jiri,
Quoted 18 lines · Jiri Olsa
Quoted 17 lines · Jiri Olsa
Quoted 16 lines · Arnaldo Carvalho de Melo
Em Wed, Nov 12, 2014 at 06:05:18PM -0800, Andi Kleen escreveu:
Quoted 9 lines
[Reworks to address all the review feedback. Rebased to latest tree] [Just a repost after a rebase]
[Even more review feedback and some bugs addressed.] [Only port to changes in perf/core. No other changes.] [Rebase to latest perf/core]
[Another rebase. No changes]This patchkit implements lbr-as-callgraphs in per freport, as an alternative way to present LBR information.
Ok, I have this in my perf/core branch, but I need to test it further, as I couldn't get the output that appears on some of the changelogs.
If you could take a look at
Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linuxperf/coreTo see if I made some mistake, that would be of help,
I'm getting compile error for DEBUG=1
looks like the
BUILD_BUG_ON_MSGdoes not work correctly with -O6 we use
Nope, DEBUG=1 prevents -O6 from applied. we have below in config/Makefile:
ifndef DEBUG
DEBUG := 0
endif
ifeq ($(DEBUG),0)
CFLAGS += -O6
endifLooking at include/linux/bug.h, BUILD_BUG_ON is guarded under __OPTIMIZE__ but BUILD_BUG_ON_MSG is not. What about changing it to BUILD_BUG_ON then?
Thanks,
Namhyung
Quoted 23 lines · Namhyung Kim
Hi Jiri,
Quoted 20 lines · Jiri Olsa
Quoted 19 lines · Jiri Olsa
Quoted 18 lines · Arnaldo Carvalho de Melo
Em Wed, Nov 12, 2014 at 06:05:18PM -0800, Andi Kleen escreveu:
Quoted 9 lines
[Reworks to address all the review feedback. Rebased to latest tree] [Just a repost after a rebase]
[Even more review feedback and some bugs addressed.] [Only port to changes in perf/core. No other changes.] [Rebase to latest perf/core]
[Another rebase. No changes]This patchkit implements lbr-as-callgraphs in per freport, as an alternative way to present LBR information.
Ok, I have this in my perf/core branch, but I need to test it further, as I couldn't get the output that appears on some of the changelogs.
If you could take a look at
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linuxperf/core
Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
Quoted 2 lines
To see if I made some mistake, that would be of help,
I'm getting compile error for DEBUG=1
looks like the
BUILD_BUG_ON_MSGdoes not work correctly with -O6 we useNope, DEBUG=1 prevents -O6 from applied. we have below in config/Makefile:
right.. the other way around ;))
Quoted 5 lines
ifndef DEBUG
DEBUG := 0endif
Quoted 8 lines
ifeq ($(DEBUG),0) CFLAGS += -O6 endifLooking at
include/linux/bug.h,BUILD_BUG_ONis guarded under__OPTIMIZE__butBUILD_BUG_ON_MSGis not. What about changing it toBUILD_BUG_ONthen?
sounds gut
jirka
Quoted 45 lines · Jiri Olsa
Quoted 23 lines · Namhyung Kim
Hi Jiri,
Quoted 20 lines · Jiri Olsa
Quoted 19 lines · Jiri Olsa
Quoted 18 lines · Arnaldo Carvalho de Melo
Em Wed, Nov 12, 2014 at 06:05:18PM -0800, Andi Kleen escreveu:
Quoted 9 lines
[Reworks to address all the review feedback. Rebased to latest tree] [Just a repost after a rebase]
[Even more review feedback and some bugs addressed.] [Only port to changes in perf/core. No other changes.] [Rebase to latest perf/core]
[Another rebase. No changes]This patchkit implements lbr-as-callgraphs in per freport, as an alternative way to present LBR information.
Ok, I have this in my perf/core branch, but I need to test it further, as I couldn't get the output that appears on some of the changelogs.
If you could take a look at
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linuxperf/coreQuoted 8 lines
Quoted 6 lines
Quoted 4 lines
Quoted 2 lines
To see if I made some mistake, that would be of help,
I'm getting compile error for DEBUG=1
looks like the
BUILD_BUG_ON_MSGdoes not work correctly with -O6 we useNope, DEBUG=1 prevents -O6 from applied. we have below in config/Makefile:
right.. the other way around ;))
Quoted 10 lines
ifndef DEBUG
DEBUG := 0endif
ifeq ($(DEBUG),0) CFLAGS += -O6 endif
Quoted 5 lines
Quoted 3 lines
Looking at
include/linux/bug.h,BUILD_BUG_ONis guarded under__OPTIMIZE__butBUILD_BUG_ON_MSGis not. What about changing it toBUILD_BUG_ONthen?sounds gut
hum, acme/perf/core changed and so has the compile error ;-) we dont overload the <linux/bug.h>, so the kernel one got included, which is wrong.. attached patch fixes that
jirka
[jolsa@krava perf]$ make JOBS=1
BUILD: Doing 'make -j1' parallel build CC perf.o CC builtin-annotate.o
In file included from util/machine.h:5:0,
from util/session.h:7,
from builtin-annotate.c:29:/home/jolsa/kernel.org/linux-perf/include/linux/bug.h: In function ‘report_bug’:/home/jolsa/kernel.org/linux-perf/include/linux/bug.h:105:59: error: unused parameter ‘bug_addr’ [-Werror=unused-parameter]
static inline enum bug_trap_type report_bug(unsigned long bug_addr,
^
/home/jolsa/kernel.org/linux-perf/include/linux/bug.h:106:26: error: unused parameter ‘regs’ [-Werror=unused-parameter]
struct pt_regs *regs)
^
cc1: all warnings being treated as errors
make[1]: *** [builtin-annotate.o] Error 1
make: *** [all] Error 2
---
tools/perf/util/machine.h +0 -1
@@ -2,7 +2,6 @@#define __PERF_MACHINE_H#include <sys/types.h> -#include <linux/bug.h> #include <linux/rbtree.h> #include "map.h" #include "dso.h"
Arnaldo Carvalho de Melo
maintainerEm Wed, Nov 19, 2014 at 11:54:50AM +0100, Jiri Olsa escreveu:
Quoted 7 lines
Quoted 3 lines
Quoted 1 line
BUILD_BUG_ONthen?sounds gut
hum, acme/perf/core changed and so has the compile error ;-) we dont overload the <
linux/bug.h>, so the kernel one got included, which is wrong.. attached patch fixes that
I had fixed this but not force pushed out, sorry.
Now I mistakenly tried running:
perf report --stdio --no-children --branch-history
on a file that has no BRANCH_STACK, i.e. a perf.data file on a wrong directory since I'm comparing the output of --stdio, --tui and --gtk, since it looks --gtk is wrong, still unsure about what the problem is in that case, but stumbled on:
--branch-history works with this perf.data:
[acme@zoo ~]$ perf evlist --verbose
cycles: sample_freq=4000, size: 96, sample_type:
IP|TID|TIME|CALLCHAIN|PERIOD|BRANCH_STACK, disabled: 1, inherit: 1,
mmap: 1, mmap2: 1, comm: 1, comm_exec: 1, freq: 1, enable_on_exec: 1,sample_id_all: 1, exclude_guest: 1, branch_sample_type: 8 [acme@zoo ~]$
But not with this one:
[root@zoo ~]# perf evlist --verbose
cycles: sample_freq=4000, size: 96, sample_type:
IP|TID|TIME|CALLCHAIN|CPU|PERIOD, disabled: 1, inherit: 1, mmap: 1,
mmap2: 1, comm: 1, comm_exec: 1, freq: 1, sample_id_all: 1,exclude_guest: 1
[root@zoo ~]#
Where I get tons of:
[root@zoo ~]# perf report --stdio --no-children --branch-history
# To display the perf.data header info, please use --header/--header-only options. #
BFD: Dwarf Error: Offset (994443) greater than or equal to .debug_str size (156124).
BFD: Dwarf Error: Offset (1162200) greater than or equal to .debug_str size (156124).
BFD: Dwarf Error: Offset (1929446660) greater than or equal to .debug_str size (1940537).
BFD: Dwarf Error: Offset (465055236) greater than or equal to .debug_str size (156124).
BFD: Dwarf Error: Could not find abbrev number 736412.
BFD: Dwarf Error: Offset (470186753) greater than or equal to .debug_str size (1940537). <SNIP>
BFD: Dwarf Error: Offset (3525378816) greater than or equal to .debug_str size (156124).
BFD: Dwarf Error: Offset (1483770) greater than or equal to .debug_str size (156124).
BFD: Dwarf Error: Could not find abbrev number 127.
^C^C^C^C^C^C
^C^C^C^Z
and finally a:
Segmentation fault (core dumped)
[root@zoo ~]#
Rebuilding with DEBUG=1 I get this backtrace:
Using host libthread_db library "/lib64/libthread_db.so.1".
Core was generated by `perf report --stdio --no-children --branch-history'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x000000000053ab10 in read_unsigned_leb128 ()
Missing separate debuginfos, use: debuginfo-install bzip2-libs-1.0.6-9.fc20.x86_64 elfutils-libelf-0.160-1.fc20.x86_64 elfutils-libs-0.160-1.fc20.x86_64 libunwind-1.1-3.fc20.x86_64 nss-softokn-freebl-3.17.2-1.fc20.x86_64 numactl-libs-2.0.9-2.fc20.x86_64 slang-2.2.4-11.fc20.x86_64 xz-libs-5.1.2-12alpha.fc20.x86_64 (gdb) bt
#0 0x000000000053ab10 in read_unsigned_leb128 () #1 0x00000000005485d7 in find_abstract_instance_name.isra () #2 0x0000000000548756 in find_abstract_instance_name.isra () #3 0x0000000000548756 in find_abstract_instance_name.isra () #4 0x0000000000548d31 in scan_unit_for_symbols () #5 0x00000000005496c9 in comp_unit_find_nearest_line () #6 0x000000000054a6ca in find_line.part () #7 0x00000000005606ca in _bfd_elf_find_nearest_line_discriminator () #8 0x00000000005607db in _bfd_elf_find_nearest_line () #9 0x00000000004dabf1 in find_address_in_section (abfd=0xfd522f0, section=0xe8be528, data=0xfa50c30) at util/srcline.c:100
#10 0x000000000053cbdc in bfd_map_over_sections ()
#11 0x00000000004dae84 in addr2line (dso_name=0xe89fe70 "/usr/lib/debug/usr/lib64/firefox/libxul.so.debug", addr=24667432, file=0x7fff3981f9c0, line=0x7fff3981f9bc, dso=0x22a0b50) at util/srcline.c:168 #12 0x00000000004db017 in get_srcline (dso=0x22a0b50, addr=24667432, sym=0xf6b93f0, show_sym=true) at util/srcline.c:276
#13 0x00000000004c5a31 in sort__srcline_cmp (left=0x39494a0, right=0x7fff3981fb80) at util/sort.c:303
#14 0x00000000004cbe96 in hist_entry__cmp (left=0x39494a0, right=0x7fff3981fb80) at util/hist.c:916
#15 0x00000000004caa97 in add_hist_entry (hists=0x229e688, entry=0x7fff3981fb80, al=0x7fff3981fe00, sample_self=true) at util/hist.c:397
#16 0x00000000004cae19 in __hists__add_entry (hists=0x229e688, al=0x7fff3981fe00, sym_parent=0x0, bi=0x0, mi=0x0, period=770586, weight=0, transaction=0, sample_self=true) at util/hist.c:477 #17 0x00000000004cb585 in iter_add_single_normal_entry (iter=0x7fff3981fe30, al=0x7fff3981fe00) at util/hist.c:668
#18 0x00000000004cbcfe in hist_entry_iter__add (iter=0x7fff3981fe30, al=0x7fff3981fe00, evsel=0x229e570, sample=0x7fff39820020, max_stack_depth=127, arg=0x7fff39820510) at util/hist.c:876 #19 0x000000000043206c in process_sample_event (tool=0x7fff39820510, event=0x7fcb0c4d8040, sample=0x7fff39820020, evsel=0x229e570, machine=0x229c9d0) at builtin-report.c:182 #20 0x00000000004afe4e in perf_session__deliver_sample (session=0x229c910, tool=0x7fff39820510, event=0x7fcb0c4d8040, sample=0x7fff39820020, evsel=0x229e570, machine=0x229c9d0) at util/session.c:805 #21 0x00000000004affeb in perf_session__deliver_event (session=0x229c910, event=0x7fcb0c4d8040, sample=0x7fff39820020, tool=0x7fff39820510, file_offset=1146944) at util/session.c:842 #22 0x00000000004b2ee4 in __ordered_events__flush (s=0x229c910, tool=0x7fff39820510) at util/ordered-events.c:186
#23 0x00000000004b31e6 in ordered_events__flush (s=0x229c910, tool=0x7fff39820510, how=OE_FLUSH__FINAL) at util/ordered-events.c:251
#24 0x00000000004b1236 in __perf_session__process_events (session=0x229c910, data_offset=216, data_size=1220024, file_size=1220240, tool=0x7fff39820510) at util/session.c:1318 #25 0x00000000004b132e in perf_session__process_events (session=0x229c910, tool=0x7fff39820510) at util/session.c:1337
#26 0x0000000000432d5b in __cmd_report (rep=0x7fff39820510) at builtin-report.c:483
#27 0x00000000004341ca in cmd_report (argc=0, argv=0x7fff39821950, prefix=0x0) at builtin-report.c:851
#28 0x000000000041c8bc in run_builtin (p=0x857ec8 <commands+168>, argc=4, argv=0x7fff39821950) at perf.c:331
#29 0x000000000041cb1b in handle_internal_command (argc=4, argv=0x7fff39821950) at perf.c:390
#30 0x000000000041cc67 in run_argv (argcp=0x7fff398217ac, argv=0x7fff398217a0) at perf.c:434
#31 0x000000000041cfbe in main (argc=4, argv=0x7fff39821950) at perf.c:549
(gdb)
Haven't checked yet, but I guess we need to check, when --branch-history is passed, if the sample_type has BRANCH_STACK, etc.
Now back to checking why the --gtk output doesn't match, then I go back to this other bug.
- Arnaldo
Arnaldo Carvalho de Melo
maintainerEm Wed, Nov 19, 2014 at 11:10:27AM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 11 lines
Em Wed, Nov 19, 2014 at 11:54:50AM +0100, Jiri Olsa escreveu:
Quoted 7 lines
Quoted 3 lines
Quoted 1 line
BUILD_BUG_ONthen?sounds gut
hum, acme/perf/core changed and so has the compile error ;-) we dont overload the <
linux/bug.h>, so the kernel one got included, which is wrong.. attached patch fixes thatI had fixed this but not force pushed out, sorry.
Quoted 9 lines
Now I mistakenly tried running:
perf report --stdio --no-children --branch-history
on a file that has no
BRANCH_STACK, i.e. a perf.data file on a wrong directory since I'm comparing the output of --stdio, --tui and --gtk, since it looks --gtk is wrong, still unsure about what the problem is in that case, but stumbled on:
I need to investigate this further, so I created a perf/branch-history branch that has the patches I need to test more rebased on top of my perf/core branch I just pushed out to Ingo.
- Arnaldo
Quoted 17 lines · Arnaldo Carvalho de Melo
Em Wed, Nov 19, 2014 at 11:10:27AM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 16 lines
Em Wed, Nov 19, 2014 at 11:54:50AM +0100, Jiri Olsa escreveu:
Quoted 7 lines
Quoted 3 lines
Quoted 1 line
BUILD_BUG_ONthen?sounds gut
hum, acme/perf/core changed and so has the compile error ;-) we dont overload the <
linux/bug.h>, so the kernel one got included, which is wrong.. attached patch fixes thatI had fixed this but not force pushed out, sorry.
Now I mistakenly tried running:
perf report --stdio --no-children --branch-history
on a file that has no
BRANCH_STACK, i.e. a perf.data file on a wrong
It works with -g.
Without -g it will just give an error message. I think that is ok, isn't it?
Quoted 8 lines
Quoted 4 lines
directory since I'm comparing the output of --stdio, --tui and --gtk, since it looks --gtk is wrong, still unsure about what the problem is in that case, but stumbled on:
I need to investigate this further, so I created a perf/branch-history branch that has the patches I need to test more rebased on top of my perf/core branch I just pushed out to Ingo.
I tested --gtk and I don't see any differences to the console mode with --branch-history. What problem do you see?
-Andi
Arnaldo Carvalho de Melo
maintainerEm Wed, Nov 19, 2014 at 10:48:22PM +0100, Andi Kleen escreveu:
Quoted 13 lines · Arnaldo Carvalho de Melo
Quoted 12 lines
Em Wed, Nov 19, 2014 at 11:10:27AM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 11 lines
Em Wed, Nov 19, 2014 at 11:54:50AM +0100, Jiri Olsa escreveu:
Quoted 7 lines
Quoted 3 lines
Quoted 1 line
BUILD_BUG_ONthen?sounds gut
hum, acme/perf/core changed and so has the compile error ;-) we dont overload the <
linux/bug.h>, so the kernel one got included, which is wrong.. attached patch fixes thatI had fixed this but not force pushed out, sorry.
Quoted 7 lines
Quoted 5 lines
Quoted 5 lines
Now I mistakenly tried running:
perf report --stdio --no-children --branch-history
on a file that has no
BRANCH_STACK, i.e. a perf.data file on a wrongIt works with -g.
What works with -g? perf report?
Quoted 7 lines
Without -g it will just give an error message. I think that is ok, isn't it?
Quoted 5 lines
Quoted 4 lines
directory since I'm comparing the output of --stdio, --tui and --gtk, since it looks --gtk is wrong, still unsure about what the problem is in that case, but stumbled on:
Quoted 7 lines
Quoted 3 lines
I need to investigate this further, so I created a perf/branch-history branch that has the patches I need to test more rebased on top of my perf/core branch I just pushed out to Ingo.
I tested --gtk and I don't see any differences to the console mode with --branch-history. What problem do you see?
The difference is with --tui, but I haven't checked if this is a problem introduced by your patchkit or if this is something that was there before it was applied.
- Arnaldo
Quoted 16 lines · Arnaldo Carvalho de Melo
Em Wed, Nov 19, 2014 at 10:48:22PM +0100, Andi Kleen escreveu:
Quoted 15 lines · Arnaldo Carvalho de Melo
Quoted 14 lines
Em Wed, Nov 19, 2014 at 11:10:27AM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 13 lines
Em Wed, Nov 19, 2014 at 11:54:50AM +0100, Jiri Olsa escreveu:
Quoted 7 lines
Quoted 3 lines
Quoted 1 line
BUILD_BUG_ONthen?sounds gut
hum, acme/perf/core changed and so has the compile error ;-) we dont overload the <
linux/bug.h>, so the kernel one got included, which is wrong.. attached patch fixes thatI had fixed this but not force pushed out, sorry.
Now I mistakenly tried running:
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
Quoted 3 lines
perf report --stdio --no-children --branch-history
on a file that has no
BRANCH_STACK, i.e. a perf.data file on a wrongIt works with -g.
What works with -g? perf report?
--branch-history needs perf record -g.
If there is no -g in the record it will error out.
That's what you did and see, right?
Quoted 14 lines
Quoted 14 lines
Without -g it will just give an error message. I think that is ok, isn't it?
Quoted 8 lines
Quoted 4 lines
directory since I'm comparing the output of --stdio, --tui and --gtk, since it looks --gtk is wrong, still unsure about what the problem is in that case, but stumbled on:
I need to investigate this further, so I created a perf/branch-history branch that has the patches I need to test more rebased on top of my perf/core branch I just pushed out to Ingo.
Quoted 6 lines
Quoted 2 lines
I tested --gtk and I don't see any differences to the console mode with --branch-history. What problem do you see?
The difference is with --tui, but I haven't checked if this is a problem introduced by your patchkit or if this is something that was there before it was applied.
What difference do you see?
For me all of --stdio, --gtk, --tui look similar.
-Andi
Arnaldo Carvalho de Melo
maintainerEm Thu, Nov 20, 2014 at 04:33:47PM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 9 lines
Em Wed, Nov 19, 2014 at 10:48:22PM +0100, Andi Kleen escreveu:
Quoted 7 lines
Quoted 7 lines
Quoted 3 lines
directory since I'm comparing the output of --stdio, --tui and --gtk, since it looks --gtk is wrong, still unsure about what the problem is in that case, but stumbled on:
I need to investigate this further, so I created a perf/branch-history branch that has the patches I need to test more rebased on top of my perf/core branch I just pushed out to Ingo.
Quoted 6 lines
Quoted 2 lines
I tested --gtk and I don't see any differences to the console mode with --branch-history. What problem do you see?
The difference is with --tui, but I haven't checked if this is a problem introduced by your patchkit or if this is something that was there before it was applied.
So, here it is, --gtk looks like --stdio:
$ perf report --no-children --branch-history --stdio
# Samples: 43 of event 'cycles'
# Event count (approx.): 26843162
#
# Overhead Source:Line Symbol Shared Object
# ........ ........... ......................... ................
#
68.42% tcall.c:5 [.] f2 tcall
|
|--87.65%-- f2 tcall.c:4
| |
| |--67.41%-- f1 tcall.c:10
| | f1 tcall.c:9
| | main tcall.c:17
| | main tcall.c:17
| | main tcall.c:16
| | main tcall.c:16
| | f1 tcall.c:12
| | f1 tcall.c:12
| | f2 tcall.c:6
| | f2 tcall.c:4
| | f1 tcall.c:11
| | f1 tcall.c:11
| | f2 tcall.c:6
| | f2 tcall.c:4
| | f1 tcall.c:10
| |
| --32.59%-- f1 tcall.c:11
| f1 tcall.c:11
| f1 tcall.c:11
| f2 tcall.c:6
| f2 tcall.c:4
| f1 tcall.c:10
| f1 tcall.c:9
| main tcall.c:17
| main tcall.c:17
| main tcall.c:16
| main tcall.c:16
| f1 tcall.c:12
| f1 tcall.c:12
| f2 tcall.c:6
| f2 tcall.c:4
| f1 tcall.c:11
|
--12.35%-- f1 tcall.c:9
main tcall.c:17
main tcall.c:17
main tcall.c:16
main tcall.c:16
f1 tcall.c:12
f1 tcall.c:12
f2 tcall.c:6
f2 tcall.c:4
f1 tcall.c:11
f1 tcall.c:11
f2 tcall.c:6
f2 tcall.c:4
f1 tcall.c:10
f1 tcall.c:9
main tcall.c:17<SNIP>
But:
$ perf report --no-children --branch-history --tui
# Then expand a few callchains and press 'P' to generate a perf.hist.0
# file:
- 68.42% tcall.c:5 [.] f2 tcall
- f2 tcall.c:4
- 67.41% f1 tcall.c:10
f1 tcall.c:9
main tcall.c:17
main tcall.c:17
main tcall.c:16
main tcall.c:16
f1 tcall.c:12
f1 tcall.c:12
f2 tcall.c:6
f2 tcall.c:4
f1 tcall.c:11
f1 tcall.c:11
f2 tcall.c:6
f2 tcall.c:4
f1 tcall.c:10
- 32.59% f1 tcall.c:11
f1 tcall.c:11
f2 tcall.c:6
f2 tcall.c:4
f1 tcall.c:10
f1 tcall.c:9
main tcall.c:17
main tcall.c:17
main tcall.c:16
main tcall.c:16
f1 tcall.c:12
f1 tcall.c:12
f2 tcall.c:6
f2 tcall.c:4
f1 tcall.c:11
f1 tcall.c:9
main tcall.c:17
main tcall.c:17
main tcall.c:16
main tcall.c:16
f1 tcall.c:12
f1 tcall.c:12
f2 tcall.c:6
f2 tcall.c:4
f1 tcall.c:11
f1 tcall.c:11
f2 tcall.c:6
f2 tcall.c:4
f1 tcall.c:10
f1 tcall.c:9
main tcall.c:17
<SNIP>Do you see the diff? The 87.65% and 12.35% doesn't appear on the --tui output.
But I don't know if this is due to your patchkit, trying to check.
- Arnaldo
Quoted 16 lines
f1 tcall.c:9
main tcall.c:17
main tcall.c:17
main tcall.c:16
main tcall.c:16
f1 tcall.c:12
f1 tcall.c:12
f2 tcall.c:6
f2 tcall.c:4
f1 tcall.c:11
f1 tcall.c:11
f2 tcall.c:6
f2 tcall.c:4
f1 tcall.c:10
f1 tcall.c:9
main tcall.c:17Quoted 5 lines
<SNIP>
Do you see the diff? The 87.65% and 12.35% doesn't appear on the --tui output.
I see the problem. It's some issue in hist_browser__show_callchain. --stdio doesn't show it because it doesn't seem to use that (?)
With this patch it shows percent for the first entry
@@ -791,7 +791,7 @@ static int hist_browser__show_entry(struct hist_browser *browser,
};
printed += hist_browser__show_callchain(browser,
- &entry->sorted_chain, 1, row, total,
+ &entry->sorted_chain, 2, row, total,
hist_browser__show_callchain_entry, &arg,
hist_browser__check_output_full);But the numbers are still different from what --stdio outputs, so there are some deeper issues.
I doubt I caused this, probably some latent bug that just got triggered.
Namhyung?
-Andi
Namhyung Kim
maintainerHi Andi and Arnaldo,
Quoted 39 lines · Andi Kleen
Quoted 16 lines
f1 tcall.c:9 main tcall.c:17 main tcall.c:17 main tcall.c:16 main tcall.c:16 f1 tcall.c:12 f1 tcall.c:12 f2 tcall.c:6 f2 tcall.c:4 f1 tcall.c:11 f1 tcall.c:11 f2 tcall.c:6 f2 tcall.c:4 f1 tcall.c:10 f1 tcall.c:9 main tcall.c:17Quoted 5 lines
<SNIP>
Do you see the diff? The 87.65% and 12.35% doesn't appear on the --tui output.
I see the problem. It's some issue in
hist_browser__show_callchain. --stdio doesn't show it because it doesn't seem to use that (?)With this patch it shows percent for the first entry
(quoted diff) +1
-1@@ -791,7 +791,7 @@ static int hist_browser__show_entry(struct hist_browser *browser, }; printed += hist_browser__show_callchain(browser, - &entry->sorted_chain, 1, row, total, + &entry->sorted_chain, 2, row, total, hist_browser__show_callchain_entry, &arg, hist_browser__check_output_full);But the numbers are still different from what --stdio outputs, so there are some deeper issues.
Quoted 3 lines
I doubt I caused this, probably some latent bug that just got triggered.
Namhyung?
I think it's an old bug even before my callchain cleanup patch series. It only prints percent if the level is greater than 1 which I guess it assumes there's only a single callchain path for the first level.
I'll post a patch for that soon.
Thanks,
Namhyung
Quoted 4 lines
Segmentation fault (core dumped)
[root@zoo ~]#Rebuilding with DEBUG=1 I get this backtrace:
Ok it crashes inside libbfd while resolving the line. Not much I can do about it.
Could file a bug with the binutils people, if you have a test case?
Quoted 20 lines
Using host
libthread_dblibrary "/lib64/libthread_db.so.1".
Core was generated by `perf report --stdio --no-children --branch-history'.
Program terminated with signal SIGSEGV, Segmentation fault.
#00x000000000053ab10inread_unsigned_leb128()
Missing separate debuginfos, use: debuginfo-install bzip2-libs-1.0.6-9.fc20.x86_64 elfutils-libelf-0.160-1.fc20.x86_64 elfutils-libs-0.160-1.fc20.x86_64 libunwind-1.1-3.fc20.x86_64 nss-softokn-freebl-3.17.2-1.fc20.x86_64 numactl-libs-2.0.9-2.fc20.x86_64 slang-2.2.4-11.fc20.x86_64 xz-libs-5.1.2-12alpha.fc20.x86_64 (gdb) bt#0 0x000000000053ab10 in read_unsigned_leb128 () #1 0x00000000005485d7 in find_abstract_instance_name.isra () #2 0x0000000000548756 in find_abstract_instance_name.isra () #3 0x0000000000548756 in find_abstract_instance_name.isra () #4 0x0000000000548d31 in scan_unit_for_symbols () #5 0x00000000005496c9 in comp_unit_find_nearest_line () #6 0x000000000054a6ca in find_line.part () #7 0x00000000005606ca in _bfd_elf_find_nearest_line_discriminator () #8 0x00000000005607db in _bfd_elf_find_nearest_line () #9 0x00000000004dabf1 in find_address_in_section (abfd=0xfd522f0, section=0xe8be528, data=0xfa50c30) at util/srcline.c:100#10
0x000000000053cbdcinbfd_map_over_sections()
#110x00000000004dae84in addr2line (dso_name=0xe89fe70 "/usr/lib/debug/usr/lib64/firefox/libxul.so.debug", addr=24667432, file=0x7fff3981f9c0, line=0x7fff3981f9bc, dso=0x22a0b50) atutil/srcline.c:168#120x00000000004db017inget_srcline(dso=0x22a0b50, addr=24667432, sym=0xf6b93f0, show_sym=true) atutil/srcline.c:276
Arnaldo Carvalho de Melo
maintainerEm Wed, Nov 19, 2014 at 10:50:41PM +0100, Andi Kleen escreveu:
Quoted 9 lines
Quoted 4 lines
Segmentation fault (core dumped)
[root@zoo ~]#Rebuilding with DEBUG=1 I get this backtrace:
Ok it crashes inside libbfd while resolving the line. Not much I can do about it.
Could file a bug with the binutils people, if you have a test case?
The file I have is:
[root@zoo ~]# perf report --stdio --header-only # ======== # captured on: Tue Nov 18 17:42:26 2014 # hostname : zoo.ghostprotocols.net # os release : 3.17.2-200.fc20.x86_64 # perf version : 3.18.rc1.g5a0227 # arch : x86_64 # nrcpus online : 4 # nrcpus avail : 4 # cpudesc : Intel(R) Core(TM) i7-3667U CPU @ 2.00GHz # cpuid : GenuineIntel,6,58,9 # total memory : 8080676 kB # cmdline : /home/acme/bin/perf record -a -g # event : name = cycles, type = 0, config = 0x0, config1 = 0x0, config2 = 0x0, excl_usr = 0, excl_kern = 0, excl_host = 0, excl_guest = 1, precise_ip = 0, attr_mmap2 = 1, attr_mmap = 1, attr_mmap_data = 0 # HEADER_CPU_TOPOLOGY info available, use -I to display # HEADER_NUMA_TOPOLOGY info available, use -I to display # pmu mappings: cpu = 4, software = 1, power = 9, uncore_imc = 8, tracepoint = 2, uncore_cbox_0 = 6, uncore_cbox_1 = 7, breakpoint = 5 # ======== # [root@zoo ~]#
So the command line used was:
perf record -a -g
And the perf tool was one built when HEAD was:
[acme@zoo linux]$ git show 5a0227
commit 5a0227c085cbee8af4ce228da80a99cdc124329e
Author: Andi Kleen <[email protected]>
Date: Mon Nov 17 17:58:54 2014 -0800
perf report: In branch stack mode use address history sorting
Which, due to rebases, in my perf/branch-history is:
commit aef48d981d85f996a47715d44111220843999a4e
Author: Andi Kleen <[email protected]>
Date: Mon Nov 17 17:58:54 2014 -0800
perf report: In branch stack mode use address history sorting
So let me try to reproduce it again...
Yeah, reproduced, so, what lead me to send this report to you was:
1. yes, it has -g in the 'perf record' command line generating the perf.data file that when fed to perf report --branch-history causes a segfault
2. no, it doesn't have -b, so, it ends up with PERF_SAMPLE_BRANCH_STACK:
[root@zoo ~]# perf evlist -v
cycles: sample_freq=4000, size: 104,
sample_type: IP|TID|TIME|CALLCHAIN|CPU|PERIOD, disabled: 1,
inherit: 1, mmap: 1, mmap2: 1, comm: 1, comm_exec: 1,
freq: 1, sample_id_all: 1, exclude_guest: 1 [root@zoo ~]#
3. When I then pass it to 'perf report' telling that I want --branch-history, it segfaults
What I thought this patch should do is to check if the perf.data sample_type has PERF_SAMPLE_BRANCH_STACK and if not, tell the user that such mode can't be chosen since there is no branch stack.
This is all without looking at the code to see what kind of data is being fed to libbfd, I fear it is bogus data that will then cause that segfault, no?
If I add that '-b' to the 'perf record -a -g' command line, I get:
[root@zoo ~]# perf record -a -g -b
^C[ perf record: Woken up 3 times to write data ]
[ perf record: Captured and wrote 2.422 MB perf.data (~105832 samples) ]
[root@zoo ~]# perf evlist -v
cycles: sample_freq=4000, size: 104,
sample_type: IP|TID|TIME|CALLCHAIN|CPU|PERIOD|BRANCH_STACK, disabled: 1,
inherit: 1, mmap: 1, mmap2: 1, comm: 1, comm_exec: 1, freq: 1,
sample_id_all: 1, exclude_guest: 1, branch_sample_type: 8 [root@zoo ~]#
And then, specifying --branch-history to perf report is no problem it is happy finding whatever info it needs to properly spoon into libbfd...
No, that is not the case, when I passed the above perf.data to 'perf report --stdio --branch-history' it happily exploded with double frees and segfaults...
So please try, as root:
perf record -a -g -b
then interrupt with control+C and try:
perf report --stdio --branch-history
On my perf/branch-history branch.
- Arnaldo
Quoted 20 lines
Quoted 20 lines
Using host
libthread_dblibrary "/lib64/libthread_db.so.1".
Core was generated by `perf report --stdio --no-children --branch-history'.
Program terminated with signal SIGSEGV, Segmentation fault.
#00x000000000053ab10inread_unsigned_leb128()
Missing separate debuginfos, use: debuginfo-install bzip2-libs-1.0.6-9.fc20.x86_64 elfutils-libelf-0.160-1.fc20.x86_64 elfutils-libs-0.160-1.fc20.x86_64 libunwind-1.1-3.fc20.x86_64 nss-softokn-freebl-3.17.2-1.fc20.x86_64 numactl-libs-2.0.9-2.fc20.x86_64 slang-2.2.4-11.fc20.x86_64 xz-libs-5.1.2-12alpha.fc20.x86_64 (gdb) bt#0 0x000000000053ab10 in read_unsigned_leb128 () #1 0x00000000005485d7 in find_abstract_instance_name.isra () #2 0x0000000000548756 in find_abstract_instance_name.isra () #3 0x0000000000548756 in find_abstract_instance_name.isra () #4 0x0000000000548d31 in scan_unit_for_symbols () #5 0x00000000005496c9 in comp_unit_find_nearest_line () #6 0x000000000054a6ca in find_line.part () #7 0x00000000005606ca in _bfd_elf_find_nearest_line_discriminator () #8 0x00000000005607db in _bfd_elf_find_nearest_line () #9 0x00000000004dabf1 in find_address_in_section (abfd=0xfd522f0, section=0xe8be528, data=0xfa50c30) at util/srcline.c:100#10
0x000000000053cbdcinbfd_map_over_sections()
#110x00000000004dae84in addr2line (dso_name=0xe89fe70 "/usr/lib/debug/usr/lib64/firefox/libxul.so.debug", addr=24667432, file=0x7fff3981f9c0, line=0x7fff3981f9bc, dso=0x22a0b50) atutil/srcline.c:168#120x00000000004db017inget_srcline(dso=0x22a0b50, addr=24667432, sym=0xf6b93f0, show_sym=true) atutil/srcline.c:276
Arnaldo Carvalho de Melo
maintainerEm Tue, Nov 18, 2014 at 12:00:07PM +0100, Jiri Olsa escreveu:
Quoted 18 lines · Jiri Olsa
Quoted 16 lines · Arnaldo Carvalho de Melo
Quoted 15 lines
Em Wed, Nov 12, 2014 at 06:05:18PM -0800, Andi Kleen escreveu:
Quoted 9 lines
[Reworks to address all the review feedback. Rebased to latest tree] [Just a repost after a rebase]
[Even more review feedback and some bugs addressed.] [Only port to changes in perf/core. No other changes.] [Rebase to latest perf/core]
[Another rebase. No changes]This patchkit implements lbr-as-callgraphs in per freport, as an alternative way to present LBR information.
Ok, I have this in my perf/core branch, but I need to test it further, as I couldn't get the output that appears on some of the changelogs.
If you could take a look at
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linuxperf/coreTo see if I made some mistake, that would be of help,
I'm getting compile error for DEBUG=1
looks like the
BUILD_BUG_ON_MSGdoes not work correctly with -O6 we use
Yeah, I'll probably just take the brute force approach Andi originally used and switch to BUILD_BUG_ON_MSG once we get it working in the tools/ environment, i.e. using -O6, etc.
- Arnaldo
Quoted 7 lines
Quoted 3 lines
Quoted 1 line
I'm getting compile error for DEBUG=1
looks like the
BUILD_BUG_ON_MSGdoes not work correctly with -O6 we useYeah, I'll probably just take the brute force approach Andi originally used and switch to
BUILD_BUG_ON_MSGonce we get it working in thetools/environment, i.e. using -O6, etc.
For new enough gcc you could use _Static_assert()
-Andi