Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
[cascardo/linux.git] / tools / perf / util / annotate.c
index 7dabde1..79999ce 100644 (file)
 #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;
 
        /*
@@ -1170,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: