Commit 4e6e311e authored by Ingo Molnar's avatar Ingo Molnar

Merge tag 'perf-core-for-mingo' of...

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: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents 2565711f a8480808
...@@ -2,6 +2,8 @@ PERF-CFLAGS ...@@ -2,6 +2,8 @@ PERF-CFLAGS
PERF-GUI-VARS PERF-GUI-VARS
PERF-VERSION-FILE PERF-VERSION-FILE
perf perf
perf-read-vdso32
perf-read-vdsox32
perf-help perf-help
perf-record perf-record
perf-report perf-report
......
...@@ -497,8 +497,6 @@ ifneq ($(OUTPUT),) ...@@ -497,8 +497,6 @@ ifneq ($(OUTPUT),)
endif endif
ifdef NO_LIBELF ifdef NO_LIBELF
EXTLIBS := $(filter-out -lelf,$(EXTLIBS))
# Remove ELF/DWARF dependent codes # Remove ELF/DWARF dependent codes
LIB_OBJS := $(filter-out $(OUTPUT)util/symbol-elf.o,$(LIB_OBJS)) LIB_OBJS := $(filter-out $(OUTPUT)util/symbol-elf.o,$(LIB_OBJS))
LIB_OBJS := $(filter-out $(OUTPUT)util/dwarf-aux.o,$(LIB_OBJS)) LIB_OBJS := $(filter-out $(OUTPUT)util/dwarf-aux.o,$(LIB_OBJS))
......
...@@ -357,6 +357,7 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused, ...@@ -357,6 +357,7 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
static struct perf_tool tool = { static struct perf_tool tool = {
.sample = diff__process_sample_event, .sample = diff__process_sample_event,
.mmap = perf_event__process_mmap, .mmap = perf_event__process_mmap,
.mmap2 = perf_event__process_mmap2,
.comm = perf_event__process_comm, .comm = perf_event__process_comm,
.exit = perf_event__process_exit, .exit = perf_event__process_exit,
.fork = perf_event__process_fork, .fork = perf_event__process_fork,
......
...@@ -150,7 +150,7 @@ CFLAGS += -std=gnu99 ...@@ -150,7 +150,7 @@ CFLAGS += -std=gnu99
# adding assembler files missing the .GNU-stack linker note. # adding assembler files missing the .GNU-stack linker note.
LDFLAGS += -Wl,-z,noexecstack LDFLAGS += -Wl,-z,noexecstack
EXTLIBS = -lelf -lpthread -lrt -lm -ldl EXTLIBS = -lpthread -lrt -lm -ldl
ifneq ($(OUTPUT),) ifneq ($(OUTPUT),)
OUTPUT_FEATURES = $(OUTPUT)config/feature-checks/ OUTPUT_FEATURES = $(OUTPUT)config/feature-checks/
...@@ -354,6 +354,7 @@ endif # NO_LIBELF ...@@ -354,6 +354,7 @@ endif # NO_LIBELF
ifndef NO_LIBELF ifndef NO_LIBELF
CFLAGS += -DHAVE_LIBELF_SUPPORT CFLAGS += -DHAVE_LIBELF_SUPPORT
EXTLIBS += -lelf
ifeq ($(feature-libelf-mmap), 1) ifeq ($(feature-libelf-mmap), 1)
CFLAGS += -DHAVE_LIBELF_MMAP_SUPPORT CFLAGS += -DHAVE_LIBELF_MMAP_SUPPORT
...@@ -373,7 +374,7 @@ ifndef NO_LIBELF ...@@ -373,7 +374,7 @@ ifndef NO_LIBELF
else else
CFLAGS += -DHAVE_DWARF_SUPPORT $(LIBDW_CFLAGS) CFLAGS += -DHAVE_DWARF_SUPPORT $(LIBDW_CFLAGS)
LDFLAGS += $(LIBDW_LDFLAGS) LDFLAGS += $(LIBDW_LDFLAGS)
EXTLIBS += -lelf -ldw EXTLIBS += -ldw
endif # PERF_HAVE_DWARF_REGS endif # PERF_HAVE_DWARF_REGS
endif # NO_DWARF endif # NO_DWARF
endif # NO_LIBELF endif # NO_LIBELF
......
...@@ -85,7 +85,7 @@ static struct test { ...@@ -85,7 +85,7 @@ static struct test {
.func = test__hists_link, .func = test__hists_link,
}, },
{ {
.desc = "Try 'use perf' in python, checking link problems", .desc = "Try 'import perf' in python, checking link problems",
.func = test__python_use, .func = test__python_use,
}, },
{ {
......
...@@ -27,6 +27,7 @@ static struct annotate_browser_opt { ...@@ -27,6 +27,7 @@ static struct annotate_browser_opt {
bool hide_src_code, bool hide_src_code,
use_offset, use_offset,
jump_arrows, jump_arrows,
show_linenr,
show_nr_jumps; show_nr_jumps;
} annotate_browser__opts = { } annotate_browser__opts = {
.use_offset = true, .use_offset = true,
...@@ -128,6 +129,10 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int ...@@ -128,6 +129,10 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
if (!*dl->line) if (!*dl->line)
slsmg_write_nstring(" ", width - pcnt_width); slsmg_write_nstring(" ", width - pcnt_width);
else if (dl->offset == -1) { else if (dl->offset == -1) {
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 ", printed = scnprintf(bf, sizeof(bf), "%*s ",
ab->addr_width, " "); ab->addr_width, " ");
slsmg_write_nstring(bf, printed); slsmg_write_nstring(bf, printed);
...@@ -733,6 +738,7 @@ static int annotate_browser__run(struct annotate_browser *browser, ...@@ -733,6 +738,7 @@ static int annotate_browser__run(struct annotate_browser *browser,
"o Toggle disassembler output/simplified view\n" "o Toggle disassembler output/simplified view\n"
"s Toggle source code view\n" "s Toggle source code view\n"
"/ Search string\n" "/ Search string\n"
"k Toggle line numbers\n"
"r Run available scripts\n" "r Run available scripts\n"
"? Search string backwards\n"); "? Search string backwards\n");
continue; continue;
...@@ -741,6 +747,10 @@ static int annotate_browser__run(struct annotate_browser *browser, ...@@ -741,6 +747,10 @@ static int annotate_browser__run(struct annotate_browser *browser,
script_browse(NULL); script_browse(NULL);
continue; continue;
} }
case 'k':
annotate_browser__opts.show_linenr =
!annotate_browser__opts.show_linenr;
break;
case 'H': case 'H':
nd = browser->curr_hot; nd = browser->curr_hot;
break; break;
...@@ -984,6 +994,7 @@ static struct annotate_config { ...@@ -984,6 +994,7 @@ static struct annotate_config {
} annotate__configs[] = { } annotate__configs[] = {
ANNOTATE_CFG(hide_src_code), ANNOTATE_CFG(hide_src_code),
ANNOTATE_CFG(jump_arrows), ANNOTATE_CFG(jump_arrows),
ANNOTATE_CFG(show_linenr),
ANNOTATE_CFG(show_nr_jumps), ANNOTATE_CFG(show_nr_jumps),
ANNOTATE_CFG(use_offset), ANNOTATE_CFG(use_offset),
}; };
......
...@@ -463,23 +463,6 @@ static int hist_browser__run(struct hist_browser *browser, ...@@ -463,23 +463,6 @@ static int hist_browser__run(struct hist_browser *browser,
return key; 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 { struct callchain_print_arg {
/* for hists browser */ /* for hists browser */
off_t row_offset; off_t row_offset;
......
...@@ -89,15 +89,6 @@ void perf_gtk__init_hpp(void) ...@@ -89,15 +89,6 @@ void perf_gtk__init_hpp(void)
perf_gtk__hpp_color_overhead_acc; 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, static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store,
GtkTreeIter *parent, int col, u64 total) GtkTreeIter *parent, int col, u64 total)
{ {
...@@ -128,7 +119,7 @@ static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store, ...@@ -128,7 +119,7 @@ static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store,
scnprintf(buf, sizeof(buf), "%5.2f%%", percent); scnprintf(buf, sizeof(buf), "%5.2f%%", percent);
gtk_tree_store_set(store, &iter, 0, buf, -1); 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); gtk_tree_store_set(store, &iter, col, buf, -1);
if (need_new_parent) { if (need_new_parent) {
......
...@@ -41,6 +41,7 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, ...@@ -41,6 +41,7 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain,
{ {
int i; int i;
size_t ret = 0; size_t ret = 0;
char bf[1024];
ret += callchain__fprintf_left_margin(fp, left_margin); ret += callchain__fprintf_left_margin(fp, left_margin);
for (i = 0; i < depth; i++) { for (i = 0; i < depth; i++) {
...@@ -56,11 +57,8 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, ...@@ -56,11 +57,8 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain,
} else } else
ret += fprintf(fp, "%s", " "); ret += fprintf(fp, "%s", " ");
} }
if (chain->ms.sym) fputs(callchain_list__sym_name(chain, bf, sizeof(bf), false), fp);
ret += fprintf(fp, "%s\n", chain->ms.sym->name); fputc('\n', fp);
else
ret += fprintf(fp, "0x%0" PRIx64 "\n", chain->ip);
return ret; return ret;
} }
...@@ -168,6 +166,7 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root, ...@@ -168,6 +166,7 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
struct rb_node *node; struct rb_node *node;
int i = 0; int i = 0;
int ret = 0; int ret = 0;
char bf[1024];
/* /*
* If have one single callchain root, don't bother printing * 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, ...@@ -196,10 +195,8 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
} else } else
ret += callchain__fprintf_left_margin(fp, left_margin); ret += callchain__fprintf_left_margin(fp, left_margin);
if (chain->ms.sym) ret += fprintf(fp, "%s\n", callchain_list__sym_name(chain, bf, sizeof(bf),
ret += fprintf(fp, " %s\n", chain->ms.sym->name); false));
else
ret += fprintf(fp, " %p\n", (void *)(long)chain->ip);
if (++entries_printed == callchain_param.print_limit) if (++entries_printed == callchain_param.print_limit)
break; break;
...@@ -219,6 +216,7 @@ static size_t __callchain__fprintf_flat(FILE *fp, struct callchain_node *node, ...@@ -219,6 +216,7 @@ static size_t __callchain__fprintf_flat(FILE *fp, struct callchain_node *node,
{ {
struct callchain_list *chain; struct callchain_list *chain;
size_t ret = 0; size_t ret = 0;
char bf[1024];
if (!node) if (!node)
return 0; return 0;
...@@ -229,11 +227,8 @@ static size_t __callchain__fprintf_flat(FILE *fp, struct callchain_node *node, ...@@ -229,11 +227,8 @@ static size_t __callchain__fprintf_flat(FILE *fp, struct callchain_node *node,
list_for_each_entry(chain, &node->val, list) { list_for_each_entry(chain, &node->val, list) {
if (chain->ip >= PERF_CONTEXT_MAX) if (chain->ip >= PERF_CONTEXT_MAX)
continue; continue;
if (chain->ms.sym) ret += fprintf(fp, " %s\n", callchain_list__sym_name(chain,
ret += fprintf(fp, " %s\n", chain->ms.sym->name); bf, sizeof(bf), false));
else
ret += fprintf(fp, " %p\n",
(void *)(long)chain->ip);
} }
return ret; return ret;
......
...@@ -17,11 +17,13 @@ ...@@ -17,11 +17,13 @@
#include "debug.h" #include "debug.h"
#include "annotate.h" #include "annotate.h"
#include "evsel.h" #include "evsel.h"
#include <regex.h>
#include <pthread.h> #include <pthread.h>
#include <linux/bitops.h> #include <linux/bitops.h>
const char *disassembler_style; const char *disassembler_style;
const char *objdump_path; const char *objdump_path;
static regex_t file_lineno;
static struct ins *ins__find(const char *name); static struct ins *ins__find(const char *name);
static int disasm_line__parse(char *line, char **namep, char **rawp); static int disasm_line__parse(char *line, char **namep, char **rawp);
...@@ -570,13 +572,15 @@ static int disasm_line__parse(char *line, char **namep, char **rawp) ...@@ -570,13 +572,15 @@ static int disasm_line__parse(char *line, char **namep, char **rawp)
return -1; 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); struct disasm_line *dl = zalloc(sizeof(*dl) + privsize);
if (dl != NULL) { if (dl != NULL) {
dl->offset = offset; dl->offset = offset;
dl->line = strdup(line); dl->line = strdup(line);
dl->line_nr = line_nr;
if (dl->line == NULL) if (dl->line == NULL)
goto out_delete; goto out_delete;
...@@ -788,13 +792,15 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st ...@@ -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. * 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, 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 annotation *notes = symbol__annotation(sym);
struct disasm_line *dl; struct disasm_line *dl;
char *line = NULL, *parsed_line, *tmp, *tmp2, *c; char *line = NULL, *parsed_line, *tmp, *tmp2, *c;
size_t line_len; size_t line_len;
s64 line_ip, offset = -1; s64 line_ip, offset = -1;
regmatch_t match[2];
if (getline(&line, &line_len, file) < 0) if (getline(&line, &line_len, file) < 0)
return -1; return -1;
...@@ -812,6 +818,12 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, ...@@ -812,6 +818,12 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
line_ip = -1; line_ip = -1;
parsed_line = line; 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: * Strip leading spaces:
*/ */
...@@ -842,8 +854,9 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, ...@@ -842,8 +854,9 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
parsed_line = tmp2 + 1; parsed_line = tmp2 + 1;
} }
dl = disasm_line__new(offset, parsed_line, privsize); dl = disasm_line__new(offset, parsed_line, privsize, *line_nr);
free(line); free(line);
(*line_nr)++;
if (dl == NULL) if (dl == NULL)
return -1; return -1;
...@@ -869,6 +882,11 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, ...@@ -869,6 +882,11 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
return 0; 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) static void delete_last_nop(struct symbol *sym)
{ {
struct annotation *notes = symbol__annotation(sym); struct annotation *notes = symbol__annotation(sym);
...@@ -904,6 +922,7 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize) ...@@ -904,6 +922,7 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
char symfs_filename[PATH_MAX]; char symfs_filename[PATH_MAX];
struct kcore_extract kce; struct kcore_extract kce;
bool delete_extract = false; bool delete_extract = false;
int lineno = 0;
if (filename) if (filename)
symbol__join_symfs(symfs_filename, filename); symbol__join_symfs(symfs_filename, filename);
...@@ -915,6 +934,8 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize) ...@@ -915,6 +934,8 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
return -ENOMEM; return -ENOMEM;
} }
goto fallback; goto fallback;
} else if (dso__is_kcore(dso)) {
goto fallback;
} else if (readlink(symfs_filename, command, sizeof(command)) < 0 || } else if (readlink(symfs_filename, command, sizeof(command)) < 0 ||
strstr(command, "[kernel.kallsyms]") || strstr(command, "[kernel.kallsyms]") ||
access(symfs_filename, R_OK)) { access(symfs_filename, R_OK)) {
...@@ -982,7 +1003,7 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize) ...@@ -982,7 +1003,7 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
snprintf(command, sizeof(command), snprintf(command, sizeof(command),
"%s %s%s --start-address=0x%016" PRIx64 "%s %s%s --start-address=0x%016" PRIx64
" --stop-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", objdump_path ? objdump_path : "objdump",
disassembler_style ? "-M " : "", disassembler_style ? "-M " : "",
disassembler_style ? disassembler_style : "", disassembler_style ? disassembler_style : "",
...@@ -999,7 +1020,8 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize) ...@@ -999,7 +1020,8 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
goto out_free_filename; goto out_free_filename;
while (!feof(file)) 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; break;
/* /*
......
...@@ -58,6 +58,7 @@ struct disasm_line { ...@@ -58,6 +58,7 @@ struct disasm_line {
char *line; char *line;
char *name; char *name;
struct ins *ins; struct ins *ins;
int line_nr;
struct ins_operands ops; struct ins_operands ops;
}; };
......
...@@ -18,6 +18,9 @@ ...@@ -18,6 +18,9 @@
#include "header.h" #include "header.h"
#include "vdso.h" #include "vdso.h"
static bool no_buildid_cache;
int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused, int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused,
union perf_event *event, union perf_event *event,
struct perf_sample *sample, struct perf_sample *sample,
...@@ -251,6 +254,11 @@ int dsos__hit_all(struct perf_session *session) ...@@ -251,6 +254,11 @@ int dsos__hit_all(struct perf_session *session)
return 0; return 0;
} }
void disable_buildid_cache(void)
{
no_buildid_cache = true;
}
int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
const char *name, bool is_kallsyms, bool is_vdso) const char *name, bool is_kallsyms, bool is_vdso)
{ {
...@@ -404,6 +412,9 @@ int perf_session__cache_build_ids(struct perf_session *session) ...@@ -404,6 +412,9 @@ int perf_session__cache_build_ids(struct perf_session *session)
int ret; int ret;
char debugdir[PATH_MAX]; char debugdir[PATH_MAX];
if (no_buildid_cache)
return 0;
snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir); snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir);
if (mkdir(debugdir, 0755) != 0 && errno != EEXIST) if (mkdir(debugdir, 0755) != 0 && errno != EEXIST)
......
...@@ -25,5 +25,6 @@ int perf_session__cache_build_ids(struct perf_session *session); ...@@ -25,5 +25,6 @@ int perf_session__cache_build_ids(struct perf_session *session);
int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
const char *name, bool is_kallsyms, bool is_vdso); const char *name, bool is_kallsyms, bool is_vdso);
int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir); int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir);
void disable_buildid_cache(void);
#endif #endif
...@@ -808,3 +808,22 @@ int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node * ...@@ -808,3 +808,22 @@ int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *
out: out:
return 1; 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;
}
...@@ -193,4 +193,7 @@ static inline int arch_skip_callchain_idx(struct thread *thread __maybe_unused, ...@@ -193,4 +193,7 @@ static inline int arch_skip_callchain_idx(struct thread *thread __maybe_unused,
} }
#endif #endif
char *callchain_list__sym_name(struct callchain_list *cl,
char *bf, size_t bfsize, bool show_dso);
#endif /* __PERF_CALLCHAIN_H */ #endif /* __PERF_CALLCHAIN_H */
...@@ -816,7 +816,15 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx, ...@@ -816,7 +816,15 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
perf_evlist__mmap_get(evlist, idx); perf_evlist__mmap_get(evlist, idx);
} }
if (__perf_evlist__add_pollfd(evlist, fd, idx) < 0) { /*
* The system_wide flag causes a selected event to be opened
* always without a pid. Consequently it will never get a
* POLLHUP, but it is used for tracking in combination with
* other events, so it should not need to be polled anyway.
* Therefore don't add it for polling.
*/
if (!evsel->system_wide &&
__perf_evlist__add_pollfd(evlist, fd, idx) < 0) {
perf_evlist__mmap_put(evlist, idx); perf_evlist__mmap_put(evlist, idx);
return -1; return -1;
} }
......
...@@ -658,6 +658,14 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts) ...@@ -658,6 +658,14 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
attr->mmap_data = track; attr->mmap_data = track;
} }
/*
* We don't allow user space callchains for function trace
* event, due to issues with page faults while tracing page
* fault handler and its overall trickiness nature.
*/
if (perf_evsel__is_function_event(evsel))
evsel->attr.exclude_callchain_user = 1;
if (callchain_param.enabled && !evsel->no_aux_samples) if (callchain_param.enabled && !evsel->no_aux_samples)
perf_evsel__config_callgraph(evsel); perf_evsel__config_callgraph(evsel);
......
...@@ -24,8 +24,6 @@ ...@@ -24,8 +24,6 @@
#include "build-id.h" #include "build-id.h"
#include "data.h" #include "data.h"
static bool no_buildid_cache = false;
static u32 header_argc; static u32 header_argc;
static const char **header_argv; static const char **header_argv;
...@@ -191,7 +189,6 @@ static int write_build_id(int fd, struct perf_header *h, ...@@ -191,7 +189,6 @@ static int write_build_id(int fd, struct perf_header *h,
pr_debug("failed to write buildid table\n"); pr_debug("failed to write buildid table\n");
return err; return err;
} }
if (!no_buildid_cache)
perf_session__cache_build_ids(session); perf_session__cache_build_ids(session);
return 0; return 0;
...@@ -2791,8 +2788,3 @@ int perf_event__process_build_id(struct perf_tool *tool __maybe_unused, ...@@ -2791,8 +2788,3 @@ int perf_event__process_build_id(struct perf_tool *tool __maybe_unused,
session); session);
return 0; return 0;
} }
void disable_buildid_cache(void)
{
no_buildid_cache = true;
}
...@@ -1381,6 +1381,34 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample, ...@@ -1381,6 +1381,34 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample,
return mi; 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, al.addr, al.map, al.sym);
}
struct branch_info *sample__resolve_bstack(struct perf_sample *sample, struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
struct addr_location *al) struct addr_location *al)
{ {
...@@ -1427,7 +1455,6 @@ static int thread__resolve_callchain_sample(struct thread *thread, ...@@ -1427,7 +1455,6 @@ static int thread__resolve_callchain_sample(struct thread *thread,
for (i = 0; i < chain_nr; i++) { for (i = 0; i < chain_nr; i++) {
u64 ip; u64 ip;
struct addr_location al;
if (callchain_param.order == ORDER_CALLEE) if (callchain_param.order == ORDER_CALLEE)
j = i; j = i;
...@@ -1464,24 +1491,10 @@ static int thread__resolve_callchain_sample(struct thread *thread, ...@@ -1464,24 +1491,10 @@ static int thread__resolve_callchain_sample(struct thread *thread,
continue; continue;
} }
al.filtered = 0; err = add_callchain_ip(thread, parent, root_al,
thread__find_addr_location(thread, cpumode, cpumode, ip);
MAP__FUNCTION, ip, &al); if (err == -EINVAL)
if (al.sym != NULL) { break;
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);
if (err) if (err)
return err; return err;
} }
......
...@@ -309,7 +309,7 @@ sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right) ...@@ -309,7 +309,7 @@ sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf, static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf,
size_t size, unsigned int width) size_t size, unsigned int width)
{ {
return repsep_snprintf(bf, size, "%*.*-s", width, width, he->srcline); return repsep_snprintf(bf, size, "%-*.*s", width, width, he->srcline);
} }
struct sort_entry sort_srcline = { struct sort_entry sort_srcline = {
......
...@@ -274,7 +274,7 @@ char *get_srcline(struct dso *dso, unsigned long addr) ...@@ -274,7 +274,7 @@ char *get_srcline(struct dso *dso, unsigned long addr)
if (!addr2line(dso_name, addr, &file, &line, dso)) if (!addr2line(dso_name, addr, &file, &line, dso))
goto out; goto out;
if (asprintf(&srcline, "%s:%u", file, line) < 0) { if (asprintf(&srcline, "%s:%u", basename(file), line) < 0) {
free(file); free(file);
goto out; goto out;
} }
......
...@@ -341,7 +341,6 @@ int dso__load_sym(struct dso *dso, struct map *map __maybe_unused, ...@@ -341,7 +341,6 @@ int dso__load_sym(struct dso *dso, struct map *map __maybe_unused,
if (filename__read_build_id(ss->name, build_id, BUILD_ID_SIZE) > 0) { if (filename__read_build_id(ss->name, build_id, BUILD_ID_SIZE) > 0) {
dso__set_build_id(dso, build_id); dso__set_build_id(dso, build_id);
return 1;
} }
return 0; return 0;
} }
......
...@@ -103,15 +103,14 @@ struct comm *thread__exec_comm(const struct thread *thread) ...@@ -103,15 +103,14 @@ struct comm *thread__exec_comm(const struct thread *thread)
return last; return last;
} }
/* CHECKME: time should always be 0 if event aren't ordered */
int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp, int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp,
bool exec) bool exec)
{ {
struct comm *new, *curr = thread__comm(thread); struct comm *new, *curr = thread__comm(thread);
int err; int err;
/* Override latest entry if it had no specific time coverage */ /* Override the default :tid entry */
if (!curr->start && !curr->exec) { if (!thread->comm_set) {
err = comm__override(curr, str, timestamp, exec); err = comm__override(curr, str, timestamp, exec);
if (err) if (err)
return err; return err;
......
...@@ -154,7 +154,6 @@ extern void set_die_routine(void (*routine)(const char *err, va_list params) NOR ...@@ -154,7 +154,6 @@ extern void set_die_routine(void (*routine)(const char *err, va_list params) NOR
extern int prefixcmp(const char *str, const char *prefix); extern int prefixcmp(const char *str, const char *prefix);
extern void set_buildid_dir(void); extern void set_buildid_dir(void);
extern void disable_buildid_cache(void);
static inline const char *skip_prefix(const char *str, const char *prefix) static inline const char *skip_prefix(const char *str, const char *prefix)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment