perf/core fixes and improvements.

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (GNU/Linux)
 
 iQIcBAABAgAGBQJPJzpzAAoJENZQFvNTUqpA5/oP/0MbKuDmK1f3zsD2tSMienp0
 OJ+2Dxm4A7FbOZ3YEyYbyUixALCjCsif/2RG5TcwRymXcimiIV4trShhl3DQzgKl
 t+6GsmWbTggne7lpb7DX5HrS/WjDcXUcPCA7ySgv12pruNB6xlqljdlsoIbOjYgl
 E2rOFf0+WwICw5+oCXrOXu2ux8y95vgx+7rTMoCJD3LeU+o9aky3YPy+IZdAoq1V
 aFdeyx3kgKojYgWUbK+xmwIvA+mxWpLa8f2OHbbyuRddsx6MMJ1bQd5k6XZSqRh9
 hjn7NFvppNSoNJbK6sykiyaTrWro629GEoxYNezbNDFRh++HFUvLFWfs4MU1xK1b
 GpY8RHU9YpcpuS79EZlFNXV+HFklyxFgsj8pSjUF8nNsUlgpcTm288AvLfzK/DZ7
 ZONVPkDc7/Y/kSpN8vs5Bq4iWKd4qLTNhGkNocEVHVuf1Kq0lkqweHTmEYoYMqG+
 ZPuZ7UE2ZyHNuK+Y6uLH+DQZ3o+8dwtJ95fZRynmGJ9yEEqdbwYq6nOjBXyuenGd
 GFO+4eq7j/QXP5ZFGYF7968Jwt34mcqSeREngHDrN2HUdJPQqclfoDk4ARf5MYM6
 jfRNmmEuT0+6w0rbTXzdMxKtMLqW7ktlnOcWS/Rsnztb2KAipq3DkOKcp7FAUmeo
 fOu26QzEVMflT4FJe1bH
 =4J3A
 -----END PGP SIGNATURE-----

Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core

perf/core fixes and improvements: perf script improvements and minor fixes.

Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
Ingo Molnar 2012-01-31 13:05:08 +01:00
commit 623ec991ce
20 changed files with 150 additions and 57 deletions

View file

@ -8,7 +8,7 @@ perf-lock - Analyze lock events
SYNOPSIS
--------
[verse]
'perf lock' {record|report|trace}
'perf lock' {record|report|script|info}
DESCRIPTION
-----------
@ -20,10 +20,13 @@ and statistics with this 'perf lock' command.
produces the file "perf.data" which contains tracing
results of lock events.
'perf lock trace' shows raw lock events.
'perf lock report' reports statistical data.
'perf lock script' shows raw lock events.
'perf lock info' shows metadata like threads or addresses
of lock instances.
COMMON OPTIONS
--------------
@ -47,6 +50,17 @@ REPORT OPTIONS
Sorting key. Possible values: acquired (default), contended,
wait_total, wait_max, wait_min.
INFO OPTIONS
------------
-t::
--threads::
dump thread list in perf.data
-m::
--map::
dump map of lock instances (address:name table)
SEE ALSO
--------
linkperf:perf[1]

View file

@ -115,7 +115,7 @@ OPTIONS
-f::
--fields::
Comma separated list of fields to print. Options are:
comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr.
comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff.
Field list can be prepended with the type, trace, sw or hw,
to indicate to which event type the field list applies.
e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace
@ -200,6 +200,9 @@ OPTIONS
It currently includes: cpu and numa topology of the host system.
It can only be used with the perf script report mode.
--show-kernel-path::
Try to resolve the path of [kernel.kallsyms]
SEE ALSO
--------
linkperf:perf-record[1], linkperf:perf-script-perl[1],

View file

@ -5,7 +5,6 @@
*
* Written by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
*/
#include <ctype.h>
#include "../perf.h"
#include "../util/util.h"

View file

@ -5,7 +5,6 @@
*
* Trivial clone of mem-memcpy.c.
*/
#include <ctype.h>
#include "../perf.h"
#include "../util/util.h"

View file

@ -922,12 +922,12 @@ static const struct option info_options[] = {
OPT_BOOLEAN('t', "threads", &info_threads,
"dump thread list in perf.data"),
OPT_BOOLEAN('m', "map", &info_map,
"map of lock instances (name:address table)"),
"map of lock instances (address:name table)"),
OPT_END()
};
static const char * const lock_usage[] = {
"perf lock [<options>] {record|trace|report}",
"perf lock [<options>] {record|report|script|info}",
NULL
};

View file

@ -40,6 +40,7 @@ enum perf_output_field {
PERF_OUTPUT_SYM = 1U << 8,
PERF_OUTPUT_DSO = 1U << 9,
PERF_OUTPUT_ADDR = 1U << 10,
PERF_OUTPUT_SYMOFFSET = 1U << 11,
};
struct output_option {
@ -57,6 +58,7 @@ struct output_option {
{.str = "sym", .field = PERF_OUTPUT_SYM},
{.str = "dso", .field = PERF_OUTPUT_DSO},
{.str = "addr", .field = PERF_OUTPUT_ADDR},
{.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET},
};
/* default set to maintain compatibility with current format */
@ -193,6 +195,11 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
"to symbols.\n");
return -EINVAL;
}
if (PRINT_FIELD(SYMOFFSET) && !PRINT_FIELD(SYM)) {
pr_err("Display of offsets requested but symbol is not"
"selected.\n");
return -EINVAL;
}
if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) {
pr_err("Display of DSO requested but neither sample IP nor "
"sample address\nis selected. Hence, no addresses to convert "
@ -300,10 +307,17 @@ static void print_sample_start(struct perf_sample *sample,
} else
evname = __event_name(attr->type, attr->config);
printf("%s: ", evname ? evname : "(unknown)");
printf("%s: ", evname ? evname : "[unknown]");
}
}
static bool is_bts_event(struct perf_event_attr *attr)
{
return ((attr->type == PERF_TYPE_HARDWARE) &&
(attr->config & PERF_COUNT_HW_BRANCH_INSTRUCTIONS) &&
(attr->sample_period == 1));
}
static bool sample_addr_correlates_sym(struct perf_event_attr *attr)
{
if ((attr->type == PERF_TYPE_SOFTWARE) &&
@ -312,6 +326,9 @@ static bool sample_addr_correlates_sym(struct perf_event_attr *attr)
(attr->config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)))
return true;
if (is_bts_event(attr))
return true;
return false;
}
@ -323,7 +340,6 @@ static void print_sample_addr(union perf_event *event,
{
struct addr_location al;
u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
const char *symname, *dsoname;
printf("%16" PRIx64, sample->addr);
@ -343,24 +359,48 @@ static void print_sample_addr(union perf_event *event,
al.sym = map__find_symbol(al.map, al.addr, NULL);
if (PRINT_FIELD(SYM)) {
if (al.sym && al.sym->name)
symname = al.sym->name;
printf(" ");
if (PRINT_FIELD(SYMOFFSET))
symbol__fprintf_symname_offs(al.sym, &al, stdout);
else
symname = "";
printf(" %16s", symname);
symbol__fprintf_symname(al.sym, stdout);
}
if (PRINT_FIELD(DSO)) {
if (al.map && al.map->dso && al.map->dso->name)
dsoname = al.map->dso->name;
else
dsoname = "";
printf(" (%s)", dsoname);
printf(" (");
map__fprintf_dsoname(al.map, stdout);
printf(")");
}
}
static void print_sample_bts(union perf_event *event,
struct perf_sample *sample,
struct perf_evsel *evsel,
struct machine *machine,
struct thread *thread)
{
struct perf_event_attr *attr = &evsel->attr;
/* print branch_from information */
if (PRINT_FIELD(IP)) {
if (!symbol_conf.use_callchain)
printf(" ");
else
printf("\n");
perf_event__print_ip(event, sample, machine, evsel,
PRINT_FIELD(SYM), PRINT_FIELD(DSO),
PRINT_FIELD(SYMOFFSET));
}
printf(" => ");
/* print branch_to information */
if (PRINT_FIELD(ADDR))
print_sample_addr(event, sample, machine, thread, attr);
printf("\n");
}
static void process_event(union perf_event *event __unused,
struct perf_sample *sample,
struct perf_evsel *evsel,
@ -374,6 +414,11 @@ static void process_event(union perf_event *event __unused,
print_sample_start(sample, thread, attr);
if (is_bts_event(attr)) {
print_sample_bts(event, sample, evsel, machine, thread);
return;
}
if (PRINT_FIELD(TRACE))
print_trace_event(sample->cpu, sample->raw_data,
sample->raw_size);
@ -387,7 +432,8 @@ static void process_event(union perf_event *event __unused,
else
printf("\n");
perf_event__print_ip(event, sample, machine, evsel,
PRINT_FIELD(SYM), PRINT_FIELD(DSO));
PRINT_FIELD(SYM), PRINT_FIELD(DSO),
PRINT_FIELD(SYMOFFSET));
}
printf("\n");
@ -1097,7 +1143,10 @@ static const struct option options[] = {
OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
"Look for files with symbols relative to this directory"),
OPT_CALLBACK('f', "fields", NULL, "str",
"comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,addr",
"comma separated output fields prepend with 'type:'. "
"Valid types: hw,sw,trace,raw. "
"Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
"addr,symoff",
parse_output_fields),
OPT_BOOLEAN('a', "all-cpus", &system_wide,
"system-wide collection from all CPUs"),
@ -1106,6 +1155,9 @@ static const struct option options[] = {
"only display events for these comms"),
OPT_BOOLEAN('I', "show-info", &show_full_info,
"display extended information from perf.data file"),
OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path,
"Show the path of [kernel.kallsyms]"),
OPT_END()
};

View file

@ -19,7 +19,7 @@ def main():
cpus = perf.cpu_map()
threads = perf.thread_map()
evsel = perf.evsel(task = 1, comm = 1, mmap = 0,
wakeup_events = 1, sample_period = 1,
wakeup_events = 1, watermark = 1,
sample_id_all = 1,
sample_type = perf.SAMPLE_PERIOD | perf.SAMPLE_TID | perf.SAMPLE_CPU | perf.SAMPLE_TID)
evsel.open(cpus = cpus, threads = threads);

View file

@ -535,7 +535,7 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
}
if (type & PERF_SAMPLE_READ) {
fprintf(stderr, "PERF_SAMPLE_READ is unsuported for now\n");
fprintf(stderr, "PERF_SAMPLE_READ is unsupported for now\n");
return -1;
}

View file

@ -212,6 +212,21 @@ size_t map__fprintf(struct map *self, FILE *fp)
self->start, self->end, self->pgoff, self->dso->name);
}
size_t map__fprintf_dsoname(struct map *map, FILE *fp)
{
const char *dsoname;
if (map && map->dso && (map->dso->name || map->dso->long_name)) {
if (symbol_conf.show_kernel_path && map->dso->long_name)
dsoname = map->dso->long_name;
else if (map->dso->name)
dsoname = map->dso->name;
} else
dsoname = "[unknown]";
return fprintf(fp, "%s", dsoname);
}
/*
* objdump wants/reports absolute IPs for ET_EXEC, and RIPs for ET_DYN.
* map->dso->adjust_symbols==1 for ET_EXEC-like cases.

View file

@ -118,6 +118,7 @@ void map__delete(struct map *self);
struct map *map__clone(struct map *self);
int map__overlap(struct map *l, struct map *r);
size_t map__fprintf(struct map *self, FILE *fp);
size_t map__fprintf_dsoname(struct map *map, FILE *fp);
int map__load(struct map *self, symbol_filter_t filter);
struct symbol *map__find_symbol(struct map *self,

View file

@ -30,7 +30,6 @@
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
#include <dwarf-regs.h>
#include <linux/bitops.h>

View file

@ -24,7 +24,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include "../../perf.h"

View file

@ -1293,10 +1293,9 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
struct machine *machine, struct perf_evsel *evsel,
int print_sym, int print_dso)
int print_sym, int print_dso, int print_symoffset)
{
struct addr_location al;
const char *symname, *dsoname;
struct callchain_cursor *cursor = &evsel->hists.callchain_cursor;
struct callchain_cursor_node *node;
@ -1324,20 +1323,13 @@ void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
printf("\t%16" PRIx64, node->ip);
if (print_sym) {
if (node->sym && node->sym->name)
symname = node->sym->name;
else
symname = "";
printf(" %s", symname);
printf(" ");
symbol__fprintf_symname(node->sym, stdout);
}
if (print_dso) {
if (node->map && node->map->dso && node->map->dso->name)
dsoname = node->map->dso->name;
else
dsoname = "";
printf(" (%s)", dsoname);
printf(" (");
map__fprintf_dsoname(al.map, stdout);
printf(")");
}
printf("\n");
@ -1347,21 +1339,18 @@ void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
} else {
printf("%16" PRIx64, sample->ip);
if (print_sym) {
if (al.sym && al.sym->name)
symname = al.sym->name;
printf(" ");
if (print_symoffset)
symbol__fprintf_symname_offs(al.sym, &al,
stdout);
else
symname = "";
printf(" %s", symname);
symbol__fprintf_symname(al.sym, stdout);
}
if (print_dso) {
if (al.map && al.map->dso && al.map->dso->name)
dsoname = al.map->dso->name;
else
dsoname = "";
printf(" (%s)", dsoname);
printf(" (");
map__fprintf_dsoname(al.map, stdout);
printf(")");
}
}
}

View file

@ -147,7 +147,7 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
struct machine *machine, struct perf_evsel *evsel,
int print_sym, int print_dso);
int print_sym, int print_dso, int print_symoffset);
int perf_session__cpu_bitmap(struct perf_session *session,
const char *cpu_list, unsigned long *cpu_bitmap);

View file

@ -263,6 +263,28 @@ static size_t symbol__fprintf(struct symbol *sym, FILE *fp)
sym->name);
}
size_t symbol__fprintf_symname_offs(const struct symbol *sym,
const struct addr_location *al, FILE *fp)
{
unsigned long offset;
size_t length;
if (sym && sym->name) {
length = fprintf(fp, "%s", sym->name);
if (al) {
offset = al->addr - sym->start;
length += fprintf(fp, "+0x%lx", offset);
}
return length;
} else
return fprintf(fp, "[unknown]");
}
size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp)
{
return symbol__fprintf_symname_offs(sym, NULL, fp);
}
void dso__set_long_name(struct dso *dso, char *name)
{
if (name == NULL)

View file

@ -70,6 +70,7 @@ struct symbol_conf {
unsigned short priv_size;
unsigned short nr_events;
bool try_vmlinux_path,
show_kernel_path,
use_modules,
sort_by_name,
show_nr_samples,
@ -241,6 +242,9 @@ void machines__destroy_guest_kernel_maps(struct rb_root *machines);
int symbol__init(void);
void symbol__exit(void);
size_t symbol__fprintf_symname_offs(const struct symbol *sym,
const struct addr_location *al, FILE *fp);
size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp);
bool symbol_type__is_a(char symbol_type, enum map_type map_type);
size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp);

View file

@ -25,7 +25,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include "../perf.h"

View file

@ -33,7 +33,6 @@
#include <pthread.h>
#include <fcntl.h>
#include <unistd.h>
#include <ctype.h>
#include <errno.h>
#include "../perf.h"

View file

@ -22,7 +22,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include "../perf.h"

View file

@ -3,9 +3,9 @@
#include <newt.h>
#include <inttypes.h>
#include <sys/ttydefaults.h>
#include <ctype.h>
#include <string.h>
#include <linux/bitops.h>
#include "../../util.h"
#include "../../debug.h"
#include "../../symbol.h"
#include "../browser.h"