2009-09-24 10:02:18 -06:00
|
|
|
#ifndef __PERF_SYMBOL
|
|
|
|
#define __PERF_SYMBOL 1
|
2009-05-28 11:55:04 -06:00
|
|
|
|
|
|
|
#include <linux/types.h>
|
2009-10-20 10:25:40 -06:00
|
|
|
#include <stdbool.h>
|
2010-03-25 16:59:00 -06:00
|
|
|
#include <stdint.h>
|
|
|
|
#include "map.h"
|
2009-07-01 11:46:08 -06:00
|
|
|
#include <linux/list.h>
|
2009-07-01 09:28:37 -06:00
|
|
|
#include <linux/rbtree.h>
|
2010-03-25 16:59:00 -06:00
|
|
|
#include <stdio.h>
|
2009-05-28 11:55:04 -06:00
|
|
|
|
perf record: Introduce a symtab cache
Now a cache will be created in a ~/.debug debuginfo like
hierarchy, so that at the end of a 'perf record' session all the
binaries (with build-ids) involved get collected and indexed by
their build-ids, so that perf report can find them.
This is interesting when developing software where you want to
do a 'perf diff' with the previous build and opens avenues for
lots more interesting tools, like a 'perf diff --graph' that
takes more than two binaries into account.
Tunables for collecting just the symtabs can be added if one
doesn't want to have the full binary, but having the full binary
allows things like 'perf rerecord' or other tools that can
re-run the tests by having access to the exact binary in some
perf.data file, so it may well be interesting to keep the full
binary there.
Space consumption is minimised by trying to use hard links, a
'perf cache' tool to manage the space used, a la ccache is
required to purge older entries.
With this in place it will be possible also to introduce new
commands, 'perf archive' and 'perf restore' (or some more
suitable and future proof names) to create a cpio/tar file with
the perf data and the files in the cache that _had_ perf hits of
interest.
There are more aspects to polish, like finding the right vmlinux
file to cache, etc, but this is enough for a first step.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1261957026-15580-10-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-12-27 16:37:06 -07:00
|
|
|
#define DEBUG_CACHE_DIR ".debug"
|
|
|
|
|
2009-08-11 13:22:11 -06: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-25 16:59:00 -06:00
|
|
|
int hex2u64(const char *ptr, u64 *val);
|
|
|
|
char *strxfrchar(char *s, char from, char to);
|
|
|
|
|
2009-10-24 10:10:36 -06: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-11 13:22:11 -06:00
|
|
|
#ifndef DMGL_PARAMS
|
|
|
|
#define DMGL_PARAMS (1 << 0) /* Include function args */
|
|
|
|
#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */
|
|
|
|
#endif
|
|
|
|
|
2010-03-25 16:59:00 -06:00
|
|
|
#define BUILD_ID_SIZE 20
|
|
|
|
|
2009-05-28 11:55:04 -06: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 06:21:42 -06:00
|
|
|
u64 start;
|
|
|
|
u64 end;
|
2009-05-28 11:55:04 -06:00
|
|
|
char name[0];
|
|
|
|
};
|
|
|
|
|
2010-02-25 08:57:40 -07:00
|
|
|
void symbol__delete(struct symbol *self);
|
|
|
|
|
2009-12-15 15:04:40 -07:00
|
|
|
struct strlist;
|
|
|
|
|
2009-11-24 07:05:15 -07:00
|
|
|
struct symbol_conf {
|
|
|
|
unsigned short priv_size;
|
|
|
|
bool try_vmlinux_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-11 13:50:22 -07:00
|
|
|
use_modules,
|
2009-12-15 15:04:42 -07:00
|
|
|
sort_by_name,
|
|
|
|
show_nr_samples,
|
|
|
|
use_callchain,
|
2009-12-27 16:37:04 -07:00
|
|
|
exclude_other,
|
2010-04-18 23:32:50 -06:00
|
|
|
full_paths,
|
|
|
|
show_cpu_utilization;
|
2009-12-15 15:04:41 -07:00
|
|
|
const char *vmlinux_name,
|
|
|
|
*field_sep;
|
2010-04-18 23:32:50 -06:00
|
|
|
const char *default_guest_vmlinux_name,
|
|
|
|
*default_guest_kallsyms,
|
|
|
|
*default_guest_modules;
|
|
|
|
const char *guestmount;
|
|
|
|
char *dso_list_str,
|
2009-12-15 15:04:40 -07:00
|
|
|
*comm_list_str,
|
|
|
|
*sym_list_str,
|
|
|
|
*col_width_list_str;
|
|
|
|
struct strlist *dso_list,
|
|
|
|
*comm_list,
|
|
|
|
*sym_list;
|
2009-11-24 07:05:15 -07:00
|
|
|
};
|
|
|
|
|
2009-12-15 15:04:39 -07:00
|
|
|
extern struct symbol_conf symbol_conf;
|
2009-10-30 12:28:24 -06:00
|
|
|
|
|
|
|
static inline void *symbol__priv(struct symbol *self)
|
|
|
|
{
|
2009-12-15 15:04:39 -07:00
|
|
|
return ((void *)self) - symbol_conf.priv_size;
|
2009-10-30 12:28:24 -06:00
|
|
|
}
|
|
|
|
|
2010-02-03 11:52:00 -07:00
|
|
|
struct ref_reloc_sym {
|
|
|
|
const char *name;
|
|
|
|
u64 addr;
|
|
|
|
u64 unrelocated_addr;
|
|
|
|
};
|
|
|
|
|
2010-03-24 13:40:17 -06:00
|
|
|
struct map_symbol {
|
|
|
|
struct map *map;
|
|
|
|
struct symbol *sym;
|
|
|
|
};
|
|
|
|
|
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-27 11:29:23 -07:00
|
|
|
struct addr_location {
|
|
|
|
struct thread *thread;
|
|
|
|
struct map *map;
|
|
|
|
struct symbol *sym;
|
|
|
|
u64 addr;
|
|
|
|
char level;
|
2009-12-15 15:04:41 -07:00
|
|
|
bool filtered;
|
2010-04-18 23:32:50 -06:00
|
|
|
unsigned int cpumode;
|
|
|
|
};
|
|
|
|
|
|
|
|
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-27 11:29:23 -07:00
|
|
|
};
|
|
|
|
|
2009-05-28 11:55:04 -06:00
|
|
|
struct dso {
|
|
|
|
struct list_head node;
|
2009-11-27 11:29:17 -07: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-11 13:50:22 -07:00
|
|
|
struct rb_root symbol_names[MAP__NR_TYPES];
|
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-04 13:50:43 -07:00
|
|
|
u8 adjust_symbols:1;
|
|
|
|
u8 slen_calculated:1;
|
|
|
|
u8 has_build_id:1;
|
2010-04-18 23:32:50 -06:00
|
|
|
enum dso_kernel_type kernel;
|
2010-01-14 18:45:30 -07:00
|
|
|
u8 hit:1;
|
2010-03-15 10:04:33 -06:00
|
|
|
u8 annotate_warned:1;
|
2009-08-06 11:43:17 -06:00
|
|
|
unsigned char origin;
|
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-11 13:50:22 -07:00
|
|
|
u8 sorted_by_name;
|
2009-11-27 11:29:16 -07: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-04 13:50:43 -07:00
|
|
|
u8 build_id[BUILD_ID_SIZE];
|
2009-10-02 00:29:58 -06:00
|
|
|
const char *short_name;
|
|
|
|
char *long_name;
|
2010-03-15 12:03:50 -06:00
|
|
|
u16 long_name_len;
|
|
|
|
u16 short_name_len;
|
2009-05-28 11:55:04 -06:00
|
|
|
char name[0];
|
|
|
|
};
|
|
|
|
|
2009-10-30 12:28:24 -06:00
|
|
|
struct dso *dso__new(const char *name);
|
2010-01-27 16:05:51 -07:00
|
|
|
struct dso *dso__new_kernel(const char *name);
|
2009-05-28 11:55:04 -06:00
|
|
|
void dso__delete(struct dso *self);
|
|
|
|
|
2009-11-27 11:29:16 -07:00
|
|
|
bool dso__loaded(const struct dso *self, 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-11 13:50:22 -07:00
|
|
|
bool dso__sorted_by_name(const struct dso *self, enum map_type type);
|
|
|
|
|
2010-02-03 11:52:02 -07:00
|
|
|
static inline void dso__set_loaded(struct dso *self, enum map_type type)
|
|
|
|
{
|
|
|
|
self->loaded |= (1 << 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-11 13:50:22 -07:00
|
|
|
void dso__sort_by_name(struct dso *self, enum map_type type);
|
2009-11-27 11:29:16 -07:00
|
|
|
|
2010-01-07 14:59:39 -07:00
|
|
|
struct dso *__dsos__findnew(struct list_head *head, const char *name);
|
|
|
|
|
2010-02-03 11:52:00 -07:00
|
|
|
int dso__load(struct dso *self, struct map *map, symbol_filter_t filter);
|
2010-01-27 16:05:50 -07:00
|
|
|
int dso__load_vmlinux_path(struct dso *self, struct map *map,
|
2010-02-03 11:52:00 -07:00
|
|
|
symbol_filter_t filter);
|
|
|
|
int dso__load_kallsyms(struct dso *self, const char *filename, struct map *map,
|
|
|
|
symbol_filter_t filter);
|
2010-04-29 12:25:23 -06:00
|
|
|
int machine__load_kallsyms(struct machine *self, const char *filename,
|
|
|
|
enum map_type type, symbol_filter_t filter);
|
|
|
|
int machine__load_vmlinux_path(struct machine *self, enum map_type type,
|
|
|
|
symbol_filter_t filter);
|
|
|
|
|
2010-04-27 18:22:44 -06:00
|
|
|
size_t machines__fprintf_dsos(struct rb_root *self, FILE *fp);
|
|
|
|
size_t machines__fprintf_dsos_buildid(struct rb_root *self, FILE *fp, bool with_hits);
|
2009-05-28 11:55:04 -06:00
|
|
|
|
2009-11-16 11:32:44 -07:00
|
|
|
size_t dso__fprintf_buildid(struct dso *self, FILE *fp);
|
2009-11-27 11:29:20 -07:00
|
|
|
size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp);
|
2010-03-15 08:46:58 -06:00
|
|
|
|
|
|
|
enum dso_origin {
|
|
|
|
DSO__ORIG_KERNEL = 0,
|
2010-04-18 23:32:50 -06:00
|
|
|
DSO__ORIG_GUEST_KERNEL,
|
2010-03-15 08:46:58 -06:00
|
|
|
DSO__ORIG_JAVA_JIT,
|
|
|
|
DSO__ORIG_BUILD_ID_CACHE,
|
|
|
|
DSO__ORIG_FEDORA,
|
|
|
|
DSO__ORIG_UBUNTU,
|
|
|
|
DSO__ORIG_BUILDID,
|
|
|
|
DSO__ORIG_DSO,
|
2010-04-18 23:32:50 -06:00
|
|
|
DSO__ORIG_GUEST_KMODULE,
|
2010-03-15 08:46:58 -06:00
|
|
|
DSO__ORIG_KMODULE,
|
|
|
|
DSO__ORIG_NOT_FOUND,
|
|
|
|
};
|
|
|
|
|
2009-08-06 11:43:17 -06:00
|
|
|
char dso__symtab_origin(const struct dso *self);
|
perf tools: Encode kernel module mappings in perf.data
We were always looking at the running machine /proc/modules,
even when processing a perf.data file, which only makes sense
when we're doing 'perf record' and 'perf report' on the same
machine, and in close sucession, or if we don't use modules at
all, right Peter? ;-)
Now, at 'perf record' time we read /proc/modules, find the long
path for modules, and put them as PERF_MMAP events, just like we
did to encode the reloc reference symbol for vmlinux. Talking
about that now it is encoded in .pgoff, so that we can use
.{start,len} to store the address boundaries for the kernel so
that when we reconstruct the kmaps tree we can do lookups right
away, without having to fixup the end of the kernel maps like we
did in the past (and now only in perf record).
One more step in the 'perf archive' direction when we'll finally
be able to collect data in one machine and analyse in another.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1263396139-4798-1-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2010-01-13 08:22:17 -07:00
|
|
|
void dso__set_long_name(struct dso *self, char *name);
|
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-04 13:50:43 -07:00
|
|
|
void dso__set_build_id(struct dso *self, void *build_id);
|
2010-04-27 18:17:50 -06:00
|
|
|
void dso__read_running_kernel_build_id(struct dso *self, struct machine *machine);
|
2009-12-11 13:56:39 -07:00
|
|
|
struct symbol *dso__find_symbol(struct dso *self, enum map_type type, u64 addr);
|
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-11 13:50:22 -07:00
|
|
|
struct symbol *dso__find_symbol_by_name(struct dso *self, enum map_type type,
|
|
|
|
const char *name);
|
2009-05-28 11:55:04 -06:00
|
|
|
|
2009-11-03 16:46:10 -07:00
|
|
|
int filename__read_build_id(const char *filename, void *bf, size_t size);
|
2009-11-18 15:20:52 -07:00
|
|
|
int sysfs__read_build_id(const char *filename, void *bf, size_t size);
|
2010-04-18 23:32:50 -06:00
|
|
|
bool __dsos__read_build_ids(struct list_head *head, bool with_hits);
|
2010-01-20 10:28:45 -07:00
|
|
|
int build_id__sprintf(const u8 *self, int len, char *bf);
|
2010-01-14 13:30:06 -07:00
|
|
|
int kallsyms__parse(const char *filename, void *arg,
|
|
|
|
int (*process_symbol)(void *arg, const char *name,
|
|
|
|
char type, u64 start));
|
2009-11-03 16:46:10 -07:00
|
|
|
|
2010-04-27 18:20:43 -06:00
|
|
|
int __machine__create_kernel_maps(struct machine *self, struct dso *kernel);
|
2010-04-29 12:25:23 -06:00
|
|
|
int machine__create_kernel_maps(struct machine *self);
|
|
|
|
|
2010-04-27 18:20:43 -06:00
|
|
|
int machines__create_kernel_maps(struct rb_root *self, pid_t pid);
|
|
|
|
int machines__create_guest_kernel_maps(struct rb_root *self);
|
2010-04-18 23:32:50 -06:00
|
|
|
|
2009-12-15 15:04:39 -07:00
|
|
|
int symbol__init(void);
|
2010-01-04 11:19:27 -07:00
|
|
|
bool symbol_type__is_a(char symbol_type, enum map_type map_type);
|
|
|
|
|
2010-03-15 08:46:58 -06:00
|
|
|
size_t vmlinux_path__fprintf(FILE *fp);
|
|
|
|
|
2009-09-24 10:02:18 -06:00
|
|
|
#endif /* __PERF_SYMBOL */
|