summaryrefslogtreecommitdiffstats
path: root/tools/perf/util/annotate.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2014-11-20 08:32:01 +0100
committerIngo Molnar <mingo@kernel.org>2014-11-20 08:32:01 +0100
commit4e6e311e596eadba30d4f56f64eae7d45611a01c (patch)
tree681fb4c9ae7320ab1192f92e1c153ab35c90bf8e /tools/perf/util/annotate.c
parent2565711fb7d7c28e0cd93c8971b520d1b10b857c (diff)
parenta84808083688d82d7f1e5786ccf5df0ff7d448cb (diff)
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: User visible fixes: - Fallback to kallsyms when using the minimal 'ELF' loader (Arnaldo Carvalho de Melo) - Fix annotation with kcore (Adrian Hunter) - Fix up srcline histogram key formatting (Arnaldo Carvalho de Melo) - Add missing handler for PERF_RECORD_MMAP2 events in 'perf diff' (Kan Liang) User visible changes/new features: - Only print base source file for srcline histogram sort key (Andi Kleen) - Support source line numbers in annotate using a hotkey (Andi Kleen) Infrastructure changes and fixes: - Do not poll events that use the system_wide flag (Adrian Hunter) - Add perf-read-vdso32 and perf-read-vdsox32 to .gitignore (Adrian Hunter) - Only override the default :tid comm entry (Adrian Hunter) - Factor out adding new call chain entries (Andi Kleen) - Use al.addr to set up call chain (Andi Kleen) - Use a common function to resolve symbol or name (Andi Kleen) - Fix ftrace:function event recording (Jiri Olsa) - Move disable_buildid_cache() to util/build-id.c (Namhyung Kim) - Clean up libelf feature support code (Namhyung Kim) - Fix typo in python 'perf test' (WANG Chao) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf/util/annotate.c')
-rw-r--r--tools/perf/util/annotate.c32
1 files changed, 27 insertions, 5 deletions
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 7dabde14ea5..e5670f1af73 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -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);
@@ -915,6 +934,8 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
return -ENOMEM;
}
goto fallback;
+ } else if (dso__is_kcore(dso)) {
+ goto fallback;
} else if (readlink(symfs_filename, command, sizeof(command)) < 0 ||
strstr(command, "[kernel.kallsyms]") ||
access(symfs_filename, R_OK)) {
@@ -982,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 : "",
@@ -999,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;
/*