2009-09-25 00:02:18 +08:00
|
|
|
#ifndef __PERF_SYMBOL
|
|
|
|
#define __PERF_SYMBOL 1
|
2009-05-29 01:55:04 +08:00
|
|
|
|
|
|
|
#include <linux/types.h>
|
2009-10-21 00:25:40 +08:00
|
|
|
#include <stdbool.h>
|
2010-03-26 06:59:00 +08:00
|
|
|
#include <stdint.h>
|
|
|
|
#include "map.h"
|
2012-02-10 06:21:01 +08:00
|
|
|
#include "../perf.h"
|
2009-07-02 01:46:08 +08:00
|
|
|
#include <linux/list.h>
|
2009-07-01 23:28:37 +08:00
|
|
|
#include <linux/rbtree.h>
|
2010-03-26 06:59:00 +08:00
|
|
|
#include <stdio.h>
|
2012-05-30 20:23:42 +08:00
|
|
|
#include <byteswap.h>
|
2009-05-29 01:55:04 +08:00
|
|
|
|
2009-08-12 03:22:11 +08:00
|
|
|
#ifdef HAVE_CPLUS_DEMANGLE
|
|
|
|
extern char *cplus_demangle(const char *, int);
|
|
|
|
|
|
|
|
static inline char *bfd_demangle(void __used *v, const char *c, int i)
|
|
|
|
{
|
|
|
|
return cplus_demangle(c, i);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
#ifdef NO_DEMANGLE
|
|
|
|
static inline char *bfd_demangle(void __used *v, const char __used *c,
|
|
|
|
int __used i)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
#include <bfd.h>
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2010-03-26 06:59:00 +08:00
|
|
|
int hex2u64(const char *ptr, u64 *val);
|
|
|
|
char *strxfrchar(char *s, char from, char to);
|
|
|
|
|
2009-10-25 00:10:36 +08:00
|
|
|
/*
|
|
|
|
* libelf 0.8.x and earlier do not support ELF_C_READ_MMAP;
|
|
|
|
* for newer versions we can use mmap to reduce memory usage:
|
|
|
|
*/
|
|
|
|
#ifdef LIBELF_NO_MMAP
|
|
|
|
# define PERF_ELF_C_READ_MMAP ELF_C_READ
|
|
|
|
#else
|
|
|
|
# define PERF_ELF_C_READ_MMAP ELF_C_READ_MMAP
|
|
|
|
#endif
|
|
|
|
|
2009-08-12 03:22:11 +08:00
|
|
|
#ifndef DMGL_PARAMS
|
|
|
|
#define DMGL_PARAMS (1 << 0) /* Include function args */
|
|
|
|
#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */
|
|
|
|
#endif
|
|
|
|
|
2010-03-26 06:59:00 +08:00
|
|
|
#define BUILD_ID_SIZE 20
|
|
|
|
|
2011-03-12 00:36:01 +08:00
|
|
|
/** struct symbol - symtab entry
|
|
|
|
*
|
|
|
|
* @ignore - resolvable but tools ignore it (e.g. idle routines)
|
|
|
|
*/
|
2009-05-29 01:55:04 +08:00
|
|
|
struct symbol {
|
|
|
|
struct rb_node rb_node;
|
perf_counter tools: Define and use our own u64, s64 etc. definitions
On 64-bit powerpc, __u64 is defined to be unsigned long rather than
unsigned long long. This causes compiler warnings every time we
print a __u64 value with %Lx.
Rather than changing __u64, we define our own u64 to be unsigned long
long on all architectures, and similarly s64 as signed long long.
For consistency we also define u32, s32, u16, s16, u8 and s8. These
definitions are put in a new header, types.h, because these definitions
are needed in util/string.h and util/symbol.h.
The main change here is the mechanical change of __[us]{64,32,16,8}
to remove the "__". The other changes are:
* Create types.h
* Include types.h in perf.h, util/string.h and util/symbol.h
* Add types.h to the LIB_H definition in Makefile
* Added (u64) casts in process_overflow_event() and print_sym_table()
to kill two remaining warnings.
Signed-off-by: Paul Mackerras <paulus@samba.org>
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: benh@kernel.crashing.org
LKML-Reference: <19003.33494.495844.956580@cargo.ozlabs.ibm.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-06-19 20:21:42 +08:00
|
|
|
u64 start;
|
|
|
|
u64 end;
|
2010-05-11 00:57:51 +08:00
|
|
|
u16 namelen;
|
2010-08-05 23:59:47 +08:00
|
|
|
u8 binding;
|
2011-03-12 00:36:01 +08:00
|
|
|
bool ignore;
|
2009-05-29 01:55:04 +08:00
|
|
|
char name[0];
|
|
|
|
};
|
|
|
|
|
2011-03-31 21:56:28 +08:00
|
|
|
void symbol__delete(struct symbol *sym);
|
2010-02-25 23:57:40 +08:00
|
|
|
|
2012-04-19 21:57:06 +08:00
|
|
|
static inline size_t symbol__size(const struct symbol *sym)
|
|
|
|
{
|
|
|
|
return sym->end - sym->start + 1;
|
|
|
|
}
|
|
|
|
|
2009-12-16 06:04:40 +08:00
|
|
|
struct strlist;
|
|
|
|
|
2009-11-24 22:05:15 +08:00
|
|
|
struct symbol_conf {
|
|
|
|
unsigned short priv_size;
|
2011-11-12 08:17:32 +08:00
|
|
|
unsigned short nr_events;
|
2009-11-24 22:05:15 +08:00
|
|
|
bool try_vmlinux_path,
|
2012-01-30 12:43:20 +08:00
|
|
|
show_kernel_path,
|
perf symbols: Allow lookups by symbol name too
Configurable via symbol_conf.sort_by_name, so that the cost of an
extra rb_node on all 'struct symbol' instances is not paid by tools
that only want to decode addresses.
How to use it:
symbol_conf.sort_by_name = true;
symbol_init(&symbol_conf);
struct map *map = map_groups__find_by_name(kmaps, MAP__VARIABLE, "[kernel.kallsyms]");
if (map == NULL) {
pr_err("couldn't find map!\n");
kernel_maps__fprintf(stdout);
} else {
struct symbol *sym = map__find_symbol_by_name(map, sym_filter, NULL);
if (sym == NULL)
pr_err("couldn't find symbol %s!\n", sym_filter);
else
pr_info("symbol %s: %#Lx-%#Lx \n", sym_filter, sym->start, sym->end);
}
Looking over the vmlinux/kallsyms is common enough that I'll add a
variable to the upcoming struct perf_session to avoid the need to
use map_groups__find_by_name to get the main vmlinux/kallsyms map.
The above example looks on the 'variable' symtab, but it is just
like that for the functions one.
Also the sort operation is done when we first use
map__find_symbol_by_name, in a lazy way.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Masami Hiramatsu <mhiramat@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1260564622-12392-1-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-12-12 04:50:22 +08:00
|
|
|
use_modules,
|
2009-12-16 06:04:42 +08:00
|
|
|
sort_by_name,
|
|
|
|
show_nr_samples,
|
2011-10-06 03:10:06 +08:00
|
|
|
show_total_period,
|
2009-12-16 06:04:42 +08:00
|
|
|
use_callchain,
|
2009-12-28 07:37:04 +08:00
|
|
|
exclude_other,
|
2010-09-10 00:30:59 +08:00
|
|
|
show_cpu_utilization,
|
perf symbols: Handle /proc/sys/kernel/kptr_restrict
Perf uses /proc/modules to figure out where kernel modules are loaded.
With the advent of kptr_restrict, non root users get zeroes for all module
start addresses.
So check if kptr_restrict is non zero and don't generate the syntethic
PERF_RECORD_MMAP events for them.
Warn the user about it in perf record and in perf report.
In perf report the reference relocation symbol being zero means that
kptr_restrict was set, thus /proc/kallsyms has only zeroed addresses, so don't
use it to fixup symbol addresses when using a valid kallsyms (in the buildid
cache) or vmlinux (in the vmlinux path) build-id located automatically or
specified by the user.
Provide an explanation about it in 'perf report' if kernel samples were taken,
checking if a suitable vmlinux or kallsyms was found/specified.
Restricted /proc/kallsyms don't go to the buildid cache anymore.
Example:
[acme@emilia ~]$ perf record -F 100000 sleep 1
WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted, check
/proc/sys/kernel/kptr_restrict.
Samples in kernel functions may not be resolved if a suitable vmlinux file is
not found in the buildid cache or in the vmlinux path.
Samples in kernel modules won't be resolved at all.
If some relocation was applied (e.g. kexec) symbols may be misresolved even
with a suitable vmlinux or kallsyms file.
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.005 MB perf.data (~231 samples) ]
[acme@emilia ~]$
[acme@emilia ~]$ perf report --stdio
Kernel address maps (/proc/{kallsyms,modules}) were restricted,
check /proc/sys/kernel/kptr_restrict before running 'perf record'.
If some relocation was applied (e.g. kexec) symbols may be misresolved.
Samples in kernel modules can't be resolved as well.
# Events: 13 cycles
#
# Overhead Command Shared Object Symbol
# ........ ....... ................. .....................
#
20.24% sleep [kernel.kallsyms] [k] page_fault
20.04% sleep [kernel.kallsyms] [k] filemap_fault
19.78% sleep [kernel.kallsyms] [k] __lru_cache_add
19.69% sleep ld-2.12.so [.] memcpy
14.71% sleep [kernel.kallsyms] [k] dput
4.70% sleep [kernel.kallsyms] [k] flush_signal_handlers
0.73% sleep [kernel.kallsyms] [k] perf_event_comm
0.11% sleep [kernel.kallsyms] [k] native_write_msr_safe
#
# (For a higher level overview, try: perf report --sort comm,dso)
#
[acme@emilia ~]$
This is because it found a suitable vmlinux (build-id checked) in
/lib/modules/2.6.39-rc7+/build/vmlinux (use -v in perf report to see the long
file name).
If we remove that file from the vmlinux path:
[root@emilia ~]# mv /lib/modules/2.6.39-rc7+/build/vmlinux \
/lib/modules/2.6.39-rc7+/build/vmlinux.OFF
[acme@emilia ~]$ perf report --stdio
[kernel.kallsyms] with build id 57298cdbe0131f6871667ec0eaab4804dcf6f562
not found, continuing without symbols
Kernel address maps (/proc/{kallsyms,modules}) were restricted, check
/proc/sys/kernel/kptr_restrict before running 'perf record'.
As no suitable kallsyms nor vmlinux was found, kernel samples can't be
resolved.
Samples in kernel modules can't be resolved as well.
# Events: 13 cycles
#
# Overhead Command Shared Object Symbol
# ........ ....... ................. ......
#
80.31% sleep [kernel.kallsyms] [k] 0xffffffff8103425a
19.69% sleep ld-2.12.so [.] memcpy
#
# (For a higher level overview, try: perf report --sort comm,dso)
#
[acme@emilia ~]$
Reported-by: Stephane Eranian <eranian@google.com>
Suggested-by: David Miller <davem@davemloft.net>
Cc: Dave Jones <davej@redhat.com>
Cc: David Miller <davem@davemloft.net>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Kees Cook <kees.cook@canonical.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
Link: http://lkml.kernel.org/n/tip-mt512joaxxbhhp1odop04yit@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2011-05-26 20:53:51 +08:00
|
|
|
initialized,
|
2011-05-17 23:32:07 +08:00
|
|
|
kptr_restrict,
|
|
|
|
annotate_asm_raw,
|
|
|
|
annotate_src;
|
2009-12-16 06:04:41 +08:00
|
|
|
const char *vmlinux_name,
|
2010-12-08 10:39:46 +08:00
|
|
|
*kallsyms_name,
|
2010-06-15 03:26:30 +08:00
|
|
|
*source_prefix,
|
2009-12-16 06:04:41 +08:00
|
|
|
*field_sep;
|
2010-04-19 13:32:50 +08:00
|
|
|
const char *default_guest_vmlinux_name,
|
|
|
|
*default_guest_kallsyms,
|
|
|
|
*default_guest_modules;
|
|
|
|
const char *guestmount;
|
2010-05-18 03:22:41 +08:00
|
|
|
const char *dso_list_str,
|
2009-12-16 06:04:40 +08:00
|
|
|
*comm_list_str,
|
|
|
|
*sym_list_str,
|
|
|
|
*col_width_list_str;
|
|
|
|
struct strlist *dso_list,
|
|
|
|
*comm_list,
|
2012-03-09 06:47:48 +08:00
|
|
|
*sym_list,
|
|
|
|
*dso_from_list,
|
|
|
|
*dso_to_list,
|
|
|
|
*sym_from_list,
|
|
|
|
*sym_to_list;
|
2010-12-10 04:27:07 +08:00
|
|
|
const char *symfs;
|
2009-11-24 22:05:15 +08:00
|
|
|
};
|
|
|
|
|
2009-12-16 06:04:39 +08:00
|
|
|
extern struct symbol_conf symbol_conf;
|
2009-10-31 02:28:24 +08:00
|
|
|
|
2011-03-31 21:56:28 +08:00
|
|
|
static inline void *symbol__priv(struct symbol *sym)
|
2009-10-31 02:28:24 +08:00
|
|
|
{
|
2011-03-31 21:56:28 +08:00
|
|
|
return ((void *)sym) - symbol_conf.priv_size;
|
2009-10-31 02:28:24 +08:00
|
|
|
}
|
|
|
|
|
2010-02-04 02:52:00 +08:00
|
|
|
struct ref_reloc_sym {
|
|
|
|
const char *name;
|
|
|
|
u64 addr;
|
|
|
|
u64 unrelocated_addr;
|
|
|
|
};
|
|
|
|
|
2010-03-25 03:40:17 +08:00
|
|
|
struct map_symbol {
|
|
|
|
struct map *map;
|
|
|
|
struct symbol *sym;
|
2010-07-27 04:13:40 +08:00
|
|
|
bool unfolded;
|
|
|
|
bool has_children;
|
2010-03-25 03:40:17 +08:00
|
|
|
};
|
|
|
|
|
2012-02-10 06:21:01 +08:00
|
|
|
struct addr_map_symbol {
|
|
|
|
struct map *map;
|
|
|
|
struct symbol *sym;
|
|
|
|
u64 addr;
|
2012-03-09 06:47:48 +08:00
|
|
|
u64 al_addr;
|
2012-02-10 06:21:01 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
struct branch_info {
|
|
|
|
struct addr_map_symbol from;
|
|
|
|
struct addr_map_symbol to;
|
|
|
|
struct branch_flags flags;
|
|
|
|
};
|
|
|
|
|
perf tools: Consolidate symbol resolving across all tools
Now we have a very high level routine for simple tools to
process IP sample events:
int event__preprocess_sample(const event_t *self,
struct addr_location *al,
symbol_filter_t filter)
It receives the event itself and will insert new threads in the
global threads list and resolve the map and symbol, filling all
this info into the new addr_location struct, so that tools like
annotate and report can further process the event by creating
hist_entries in their specific way (with or without callgraphs,
etc).
It in turn uses the new next layer function:
void thread__find_addr_location(struct thread *self, u8 cpumode,
enum map_type type, u64 addr,
struct addr_location *al,
symbol_filter_t filter)
This one will, given a thread (userspace or the kernel kthread
one), will find the given type (MAP__FUNCTION now, MAP__VARIABLE
too in the near future) at the given cpumode, taking vdsos into
account (userspace hit, but kernel symbol) and will fill all
these details in the addr_location given.
Tools that need a more compact API for plain function
resolution, like 'kmem', can use this other one:
struct symbol *thread__find_function(struct thread *self, u64 addr,
symbol_filter_t filter)
So, to resolve a kernel symbol, that is all the 'kmem' tool
needs, its just a matter of calling:
sym = thread__find_function(kthread, addr, NULL);
The 'filter' parameter is needed because we do lazy
parsing/loading of ELF symtabs or /proc/kallsyms.
With this we remove more code duplication all around, which is
always good, huh? :-)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: John Kacur <jkacur@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1259346563-12568-12-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-11-28 02:29:23 +08:00
|
|
|
struct addr_location {
|
|
|
|
struct thread *thread;
|
|
|
|
struct map *map;
|
|
|
|
struct symbol *sym;
|
|
|
|
u64 addr;
|
|
|
|
char level;
|
2009-12-16 06:04:41 +08:00
|
|
|
bool filtered;
|
2010-06-04 22:27:10 +08:00
|
|
|
u8 cpumode;
|
|
|
|
s32 cpu;
|
2010-04-19 13:32:50 +08:00
|
|
|
};
|
|
|
|
|
2012-07-22 20:14:32 +08:00
|
|
|
enum dso_binary_type {
|
|
|
|
DSO_BINARY_TYPE__KALLSYMS = 0,
|
|
|
|
DSO_BINARY_TYPE__GUEST_KALLSYMS,
|
|
|
|
DSO_BINARY_TYPE__JAVA_JIT,
|
|
|
|
DSO_BINARY_TYPE__DEBUGLINK,
|
|
|
|
DSO_BINARY_TYPE__BUILD_ID_CACHE,
|
|
|
|
DSO_BINARY_TYPE__FEDORA_DEBUGINFO,
|
|
|
|
DSO_BINARY_TYPE__UBUNTU_DEBUGINFO,
|
|
|
|
DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
|
|
|
|
DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
|
|
|
|
DSO_BINARY_TYPE__GUEST_KMODULE,
|
|
|
|
DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
|
|
|
|
DSO_BINARY_TYPE__NOT_FOUND,
|
|
|
|
};
|
|
|
|
|
2010-04-19 13:32:50 +08:00
|
|
|
enum dso_kernel_type {
|
|
|
|
DSO_TYPE_USER = 0,
|
|
|
|
DSO_TYPE_KERNEL,
|
|
|
|
DSO_TYPE_GUEST_KERNEL
|
perf tools: Consolidate symbol resolving across all tools
Now we have a very high level routine for simple tools to
process IP sample events:
int event__preprocess_sample(const event_t *self,
struct addr_location *al,
symbol_filter_t filter)
It receives the event itself and will insert new threads in the
global threads list and resolve the map and symbol, filling all
this info into the new addr_location struct, so that tools like
annotate and report can further process the event by creating
hist_entries in their specific way (with or without callgraphs,
etc).
It in turn uses the new next layer function:
void thread__find_addr_location(struct thread *self, u8 cpumode,
enum map_type type, u64 addr,
struct addr_location *al,
symbol_filter_t filter)
This one will, given a thread (userspace or the kernel kthread
one), will find the given type (MAP__FUNCTION now, MAP__VARIABLE
too in the near future) at the given cpumode, taking vdsos into
account (userspace hit, but kernel symbol) and will fill all
these details in the addr_location given.
Tools that need a more compact API for plain function
resolution, like 'kmem', can use this other one:
struct symbol *thread__find_function(struct thread *self, u64 addr,
symbol_filter_t filter)
So, to resolve a kernel symbol, that is all the 'kmem' tool
needs, its just a matter of calling:
sym = thread__find_function(kthread, addr, NULL);
The 'filter' parameter is needed because we do lazy
parsing/loading of ELF symtabs or /proc/kallsyms.
With this we remove more code duplication all around, which is
always good, huh? :-)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: John Kacur <jkacur@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1259346563-12568-12-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-11-28 02:29:23 +08:00
|
|
|
};
|
|
|
|
|
2012-05-30 20:23:42 +08:00
|
|
|
enum dso_swap_type {
|
|
|
|
DSO_SWAP__UNSET,
|
|
|
|
DSO_SWAP__NO,
|
|
|
|
DSO_SWAP__YES,
|
|
|
|
};
|
|
|
|
|
2012-07-22 20:14:39 +08:00
|
|
|
#define DSO__DATA_CACHE_SIZE 4096
|
|
|
|
#define DSO__DATA_CACHE_MASK ~(DSO__DATA_CACHE_SIZE - 1)
|
|
|
|
|
|
|
|
struct dso_cache {
|
|
|
|
struct rb_node rb_node;
|
|
|
|
u64 offset;
|
|
|
|
u64 size;
|
|
|
|
char data[0];
|
|
|
|
};
|
|
|
|
|
2009-05-29 01:55:04 +08:00
|
|
|
struct dso {
|
|
|
|
struct list_head node;
|
2009-11-28 02:29:17 +08:00
|
|
|
struct rb_root symbols[MAP__NR_TYPES];
|
perf symbols: Allow lookups by symbol name too
Configurable via symbol_conf.sort_by_name, so that the cost of an
extra rb_node on all 'struct symbol' instances is not paid by tools
that only want to decode addresses.
How to use it:
symbol_conf.sort_by_name = true;
symbol_init(&symbol_conf);
struct map *map = map_groups__find_by_name(kmaps, MAP__VARIABLE, "[kernel.kallsyms]");
if (map == NULL) {
pr_err("couldn't find map!\n");
kernel_maps__fprintf(stdout);
} else {
struct symbol *sym = map__find_symbol_by_name(map, sym_filter, NULL);
if (sym == NULL)
pr_err("couldn't find symbol %s!\n", sym_filter);
else
pr_info("symbol %s: %#Lx-%#Lx \n", sym_filter, sym->start, sym->end);
}
Looking over the vmlinux/kallsyms is common enough that I'll add a
variable to the upcoming struct perf_session to avoid the need to
use map_groups__find_by_name to get the main vmlinux/kallsyms map.
The above example looks on the 'variable' symtab, but it is just
like that for the functions one.
Also the sort operation is done when we first use
map__find_symbol_by_name, in a lazy way.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Masami Hiramatsu <mhiramat@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1260564622-12392-1-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-12-12 04:50:22 +08:00
|
|
|
struct rb_root symbol_names[MAP__NR_TYPES];
|
2012-07-22 20:14:39 +08:00
|
|
|
struct rb_root cache;
|
2010-07-30 02:11:30 +08:00
|
|
|
enum dso_kernel_type kernel;
|
2012-05-30 20:23:42 +08:00
|
|
|
enum dso_swap_type needs_swap;
|
2012-07-22 20:14:32 +08:00
|
|
|
enum dso_binary_type symtab_type;
|
2012-07-22 20:14:33 +08:00
|
|
|
enum dso_binary_type data_type;
|
perf symbols: Use the buildids if present
With this change 'perf record' will intercept PERF_RECORD_MMAP
calls, creating a linked list of DSOs, then when the session
finishes, it will traverse this list and read the buildids,
stashing them at the end of the file and will set up a new
feature bit in the header bitmask.
'perf report' will then notice this feature and populate the
'dsos' list and set the build ids.
When reading the symtabs it will refuse to load from a file that
doesn't have the same build id. This improves the
reliability of the profiler output, as symbols and profiling
data is more guaranteed to match.
Example:
[root@doppio ~]# perf report | head
/home/acme/bin/perf with build id b1ea544ac3746e7538972548a09aadecc5753868 not found, continuing without symbols
# Samples: 2621434559
#
# Overhead Command Shared Object Symbol
# ........ ............... ............................. ......
#
7.91% init [kernel] [k] read_hpet
7.64% init [kernel] [k] mwait_idle_with_hints
7.60% swapper [kernel] [k] read_hpet
7.60% swapper [kernel] [k] mwait_idle_with_hints
3.65% init [kernel] [k] 0xffffffffa02339d9
[root@doppio ~]#
In this case the 'perf' binary was an older one, vanished,
so its symbols probably wouldn't match or would cause subtly
different (and misleading) output.
Next patches will support the kernel as well, reading the build
id notes for it and the modules from /sys.
Another patch should also introduce a new plumbing command:
'perf list-buildids'
that will then be used in porcelain that is distro specific to
fetch -debuginfo packages where such buildids are present. This
will in turn allow for one to run 'perf record' in one machine
and 'perf report' in another.
Future work on having the buildid sent directly from the kernel
in the PERF_RECORD_MMAP event is needed to close races, as the
DSO can be changed during a 'perf record' session, but this
patch at least helps with non-corner cases and current/older
kernels.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Frank Ch. Eigler <fche@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jason Baron <jbaron@redhat.com>
Cc: Jim Keniston <jkenisto@us.ibm.com>
Cc: K. Prasad <prasad@linux.vnet.ibm.com>
Cc: Masami Hiramatsu <mhiramat@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Roland McGrath <roland@redhat.com>
Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
LKML-Reference: <1257367843-26224-1-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-11-05 04:50:43 +08:00
|
|
|
u8 adjust_symbols:1;
|
|
|
|
u8 has_build_id:1;
|
2010-01-15 09:45:30 +08:00
|
|
|
u8 hit:1;
|
2010-03-16 00:04:33 +08:00
|
|
|
u8 annotate_warned:1;
|
2010-07-30 02:11:30 +08:00
|
|
|
u8 sname_alloc:1;
|
|
|
|
u8 lname_alloc:1;
|
perf symbols: Allow lookups by symbol name too
Configurable via symbol_conf.sort_by_name, so that the cost of an
extra rb_node on all 'struct symbol' instances is not paid by tools
that only want to decode addresses.
How to use it:
symbol_conf.sort_by_name = true;
symbol_init(&symbol_conf);
struct map *map = map_groups__find_by_name(kmaps, MAP__VARIABLE, "[kernel.kallsyms]");
if (map == NULL) {
pr_err("couldn't find map!\n");
kernel_maps__fprintf(stdout);
} else {
struct symbol *sym = map__find_symbol_by_name(map, sym_filter, NULL);
if (sym == NULL)
pr_err("couldn't find symbol %s!\n", sym_filter);
else
pr_info("symbol %s: %#Lx-%#Lx \n", sym_filter, sym->start, sym->end);
}
Looking over the vmlinux/kallsyms is common enough that I'll add a
variable to the upcoming struct perf_session to avoid the need to
use map_groups__find_by_name to get the main vmlinux/kallsyms map.
The above example looks on the 'variable' symtab, but it is just
like that for the functions one.
Also the sort operation is done when we first use
map__find_symbol_by_name, in a lazy way.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Masami Hiramatsu <mhiramat@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1260564622-12392-1-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-12-12 04:50:22 +08:00
|
|
|
u8 sorted_by_name;
|
2009-11-28 02:29:16 +08:00
|
|
|
u8 loaded;
|
perf symbols: Use the buildids if present
With this change 'perf record' will intercept PERF_RECORD_MMAP
calls, creating a linked list of DSOs, then when the session
finishes, it will traverse this list and read the buildids,
stashing them at the end of the file and will set up a new
feature bit in the header bitmask.
'perf report' will then notice this feature and populate the
'dsos' list and set the build ids.
When reading the symtabs it will refuse to load from a file that
doesn't have the same build id. This improves the
reliability of the profiler output, as symbols and profiling
data is more guaranteed to match.
Example:
[root@doppio ~]# perf report | head
/home/acme/bin/perf with build id b1ea544ac3746e7538972548a09aadecc5753868 not found, continuing without symbols
# Samples: 2621434559
#
# Overhead Command Shared Object Symbol
# ........ ............... ............................. ......
#
7.91% init [kernel] [k] read_hpet
7.64% init [kernel] [k] mwait_idle_with_hints
7.60% swapper [kernel] [k] read_hpet
7.60% swapper [kernel] [k] mwait_idle_with_hints
3.65% init [kernel] [k] 0xffffffffa02339d9
[root@doppio ~]#
In this case the 'perf' binary was an older one, vanished,
so its symbols probably wouldn't match or would cause subtly
different (and misleading) output.
Next patches will support the kernel as well, reading the build
id notes for it and the modules from /sys.
Another patch should also introduce a new plumbing command:
'perf list-buildids'
that will then be used in porcelain that is distro specific to
fetch -debuginfo packages where such buildids are present. This
will in turn allow for one to run 'perf record' in one machine
and 'perf report' in another.
Future work on having the buildid sent directly from the kernel
in the PERF_RECORD_MMAP event is needed to close races, as the
DSO can be changed during a 'perf record' session, but this
patch at least helps with non-corner cases and current/older
kernels.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Frank Ch. Eigler <fche@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jason Baron <jbaron@redhat.com>
Cc: Jim Keniston <jkenisto@us.ibm.com>
Cc: K. Prasad <prasad@linux.vnet.ibm.com>
Cc: Masami Hiramatsu <mhiramat@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Roland McGrath <roland@redhat.com>
Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
LKML-Reference: <1257367843-26224-1-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-11-05 04:50:43 +08:00
|
|
|
u8 build_id[BUILD_ID_SIZE];
|
2009-10-02 14:29:58 +08:00
|
|
|
const char *short_name;
|
|
|
|
char *long_name;
|
2010-03-16 02:03:50 +08:00
|
|
|
u16 long_name_len;
|
|
|
|
u16 short_name_len;
|
2009-05-29 01:55:04 +08:00
|
|
|
char name[0];
|
|
|
|
};
|
|
|
|
|
2012-05-30 20:23:42 +08:00
|
|
|
#define DSO__SWAP(dso, type, val) \
|
|
|
|
({ \
|
|
|
|
type ____r = val; \
|
|
|
|
BUG_ON(dso->needs_swap == DSO_SWAP__UNSET); \
|
|
|
|
if (dso->needs_swap == DSO_SWAP__YES) { \
|
|
|
|
switch (sizeof(____r)) { \
|
|
|
|
case 2: \
|
|
|
|
____r = bswap_16(val); \
|
|
|
|
break; \
|
|
|
|
case 4: \
|
|
|
|
____r = bswap_32(val); \
|
|
|
|
break; \
|
|
|
|
case 8: \
|
|
|
|
____r = bswap_64(val); \
|
|
|
|
break; \
|
|
|
|
default: \
|
|
|
|
BUG_ON(1); \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
____r; \
|
|
|
|
})
|
|
|
|
|
2009-10-31 02:28:24 +08:00
|
|
|
struct dso *dso__new(const char *name);
|
2011-03-31 21:56:28 +08:00
|
|
|
void dso__delete(struct dso *dso);
|
2009-05-29 01:55:04 +08:00
|
|
|
|
2011-03-31 21:56:28 +08:00
|
|
|
int dso__name_len(const struct dso *dso);
|
2010-07-21 01:42:52 +08:00
|
|
|
|
2011-03-31 21:56:28 +08:00
|
|
|
bool dso__loaded(const struct dso *dso, enum map_type type);
|
|
|
|
bool dso__sorted_by_name(const struct dso *dso, enum map_type type);
|
perf symbols: Allow lookups by symbol name too
Configurable via symbol_conf.sort_by_name, so that the cost of an
extra rb_node on all 'struct symbol' instances is not paid by tools
that only want to decode addresses.
How to use it:
symbol_conf.sort_by_name = true;
symbol_init(&symbol_conf);
struct map *map = map_groups__find_by_name(kmaps, MAP__VARIABLE, "[kernel.kallsyms]");
if (map == NULL) {
pr_err("couldn't find map!\n");
kernel_maps__fprintf(stdout);
} else {
struct symbol *sym = map__find_symbol_by_name(map, sym_filter, NULL);
if (sym == NULL)
pr_err("couldn't find symbol %s!\n", sym_filter);
else
pr_info("symbol %s: %#Lx-%#Lx \n", sym_filter, sym->start, sym->end);
}
Looking over the vmlinux/kallsyms is common enough that I'll add a
variable to the upcoming struct perf_session to avoid the need to
use map_groups__find_by_name to get the main vmlinux/kallsyms map.
The above example looks on the 'variable' symtab, but it is just
like that for the functions one.
Also the sort operation is done when we first use
map__find_symbol_by_name, in a lazy way.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Masami Hiramatsu <mhiramat@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1260564622-12392-1-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-12-12 04:50:22 +08:00
|
|
|
|
2011-03-31 21:56:28 +08:00
|
|
|
static inline void dso__set_loaded(struct dso *dso, enum map_type type)
|
2010-02-04 02:52:02 +08:00
|
|
|
{
|
2011-03-31 21:56:28 +08:00
|
|
|
dso->loaded |= (1 << type);
|
2010-02-04 02:52:02 +08:00
|
|
|
}
|
|
|
|
|
2011-03-31 21:56:28 +08:00
|
|
|
void dso__sort_by_name(struct dso *dso, enum map_type type);
|
2009-11-28 02:29:16 +08:00
|
|
|
|
2010-01-08 05:59:39 +08:00
|
|
|
struct dso *__dsos__findnew(struct list_head *head, const char *name);
|
|
|
|
|
2011-03-31 21:56:28 +08:00
|
|
|
int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter);
|
|
|
|
int dso__load_vmlinux(struct dso *dso, struct map *map,
|
2010-12-10 21:06:03 +08:00
|
|
|
const char *vmlinux, symbol_filter_t filter);
|
2011-03-31 21:56:28 +08:00
|
|
|
int dso__load_vmlinux_path(struct dso *dso, struct map *map,
|
2010-02-04 02:52:00 +08:00
|
|
|
symbol_filter_t filter);
|
2011-03-31 21:56:28 +08:00
|
|
|
int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map,
|
2010-02-04 02:52:00 +08:00
|
|
|
symbol_filter_t filter);
|
2011-03-31 21:56:28 +08:00
|
|
|
int machine__load_kallsyms(struct machine *machine, const char *filename,
|
2010-04-30 02:25:23 +08:00
|
|
|
enum map_type type, symbol_filter_t filter);
|
2011-03-31 21:56:28 +08:00
|
|
|
int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
|
2010-04-30 02:25:23 +08:00
|
|
|
symbol_filter_t filter);
|
|
|
|
|
2010-05-10 06:57:08 +08:00
|
|
|
size_t __dsos__fprintf(struct list_head *head, FILE *fp);
|
|
|
|
|
2011-03-31 21:56:28 +08:00
|
|
|
size_t machine__fprintf_dsos_buildid(struct machine *machine,
|
|
|
|
FILE *fp, bool with_hits);
|
|
|
|
size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp);
|
|
|
|
size_t machines__fprintf_dsos_buildid(struct rb_root *machines,
|
|
|
|
FILE *fp, bool with_hits);
|
|
|
|
size_t dso__fprintf_buildid(struct dso *dso, FILE *fp);
|
|
|
|
size_t dso__fprintf_symbols_by_name(struct dso *dso,
|
|
|
|
enum map_type type, FILE *fp);
|
|
|
|
size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp);
|
2010-03-15 22:46:58 +08:00
|
|
|
|
2011-03-31 21:56:28 +08:00
|
|
|
char dso__symtab_origin(const struct dso *dso);
|
|
|
|
void dso__set_long_name(struct dso *dso, char *name);
|
|
|
|
void dso__set_build_id(struct dso *dso, void *build_id);
|
|
|
|
void dso__read_running_kernel_build_id(struct dso *dso,
|
|
|
|
struct machine *machine);
|
2012-04-16 20:09:09 +08:00
|
|
|
struct map *dso__new_map(const char *name);
|
2011-03-31 21:56:28 +08:00
|
|
|
struct symbol *dso__find_symbol(struct dso *dso, enum map_type type,
|
|
|
|
u64 addr);
|
|
|
|
struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,
|
perf symbols: Allow lookups by symbol name too
Configurable via symbol_conf.sort_by_name, so that the cost of an
extra rb_node on all 'struct symbol' instances is not paid by tools
that only want to decode addresses.
How to use it:
symbol_conf.sort_by_name = true;
symbol_init(&symbol_conf);
struct map *map = map_groups__find_by_name(kmaps, MAP__VARIABLE, "[kernel.kallsyms]");
if (map == NULL) {
pr_err("couldn't find map!\n");
kernel_maps__fprintf(stdout);
} else {
struct symbol *sym = map__find_symbol_by_name(map, sym_filter, NULL);
if (sym == NULL)
pr_err("couldn't find symbol %s!\n", sym_filter);
else
pr_info("symbol %s: %#Lx-%#Lx \n", sym_filter, sym->start, sym->end);
}
Looking over the vmlinux/kallsyms is common enough that I'll add a
variable to the upcoming struct perf_session to avoid the need to
use map_groups__find_by_name to get the main vmlinux/kallsyms map.
The above example looks on the 'variable' symtab, but it is just
like that for the functions one.
Also the sort operation is done when we first use
map__find_symbol_by_name, in a lazy way.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Masami Hiramatsu <mhiramat@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1260564622-12392-1-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-12-12 04:50:22 +08:00
|
|
|
const char *name);
|
2009-05-29 01:55:04 +08:00
|
|
|
|
2009-11-04 07:46:10 +08:00
|
|
|
int filename__read_build_id(const char *filename, void *bf, size_t size);
|
2009-11-19 06:20:52 +08:00
|
|
|
int sysfs__read_build_id(const char *filename, void *bf, size_t size);
|
2010-04-19 13:32:50 +08:00
|
|
|
bool __dsos__read_build_ids(struct list_head *head, bool with_hits);
|
2011-03-31 21:56:28 +08:00
|
|
|
int build_id__sprintf(const u8 *build_id, int len, char *bf);
|
2010-01-15 04:30:06 +08:00
|
|
|
int kallsyms__parse(const char *filename, void *arg,
|
|
|
|
int (*process_symbol)(void *arg, const char *name,
|
2010-12-22 11:08:36 +08:00
|
|
|
char type, u64 start, u64 end));
|
2009-11-04 07:46:10 +08:00
|
|
|
|
2011-03-31 21:56:28 +08:00
|
|
|
void machine__destroy_kernel_maps(struct machine *machine);
|
|
|
|
int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel);
|
|
|
|
int machine__create_kernel_maps(struct machine *machine);
|
2010-04-30 02:25:23 +08:00
|
|
|
|
2011-03-31 21:56:28 +08:00
|
|
|
int machines__create_kernel_maps(struct rb_root *machines, pid_t pid);
|
|
|
|
int machines__create_guest_kernel_maps(struct rb_root *machines);
|
|
|
|
void machines__destroy_guest_kernel_maps(struct rb_root *machines);
|
2010-04-19 13:32:50 +08:00
|
|
|
|
2009-12-16 06:04:39 +08:00
|
|
|
int symbol__init(void);
|
2010-07-31 05:31:28 +08:00
|
|
|
void symbol__exit(void);
|
2012-01-30 12:43:15 +08:00
|
|
|
size_t symbol__fprintf_symname_offs(const struct symbol *sym,
|
|
|
|
const struct addr_location *al, FILE *fp);
|
2012-01-30 12:42:57 +08:00
|
|
|
size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp);
|
2010-01-05 02:19:27 +08:00
|
|
|
bool symbol_type__is_a(char symbol_type, enum map_type map_type);
|
|
|
|
|
2011-03-31 21:56:28 +08:00
|
|
|
size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp);
|
2010-03-15 22:46:58 +08:00
|
|
|
|
2012-07-22 20:14:32 +08:00
|
|
|
int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
|
|
|
|
char *root_dir, char *file, size_t size);
|
2012-07-22 20:14:33 +08:00
|
|
|
|
|
|
|
int dso__data_fd(struct dso *dso, struct machine *machine);
|
|
|
|
ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
|
|
|
|
u64 offset, u8 *data, ssize_t size);
|
|
|
|
ssize_t dso__data_read_addr(struct dso *dso, struct map *map,
|
|
|
|
struct machine *machine, u64 addr,
|
|
|
|
u8 *data, ssize_t size);
|
2009-09-25 00:02:18 +08:00
|
|
|
#endif /* __PERF_SYMBOL */
|