Merge commit 'v2.6.31-rc9' into tracing/core
Merge reason: move from -rc5 to -rc9. Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
@@ -35,7 +35,7 @@ man7dir=$(mandir)/man7
|
||||
# DESTDIR=
|
||||
|
||||
ASCIIDOC=asciidoc
|
||||
ASCIIDOC_EXTRA =
|
||||
ASCIIDOC_EXTRA = --unsafe
|
||||
MANPAGE_XSL = manpage-normal.xsl
|
||||
XMLTO_EXTRA =
|
||||
INSTALL?=install
|
||||
|
@@ -382,22 +382,29 @@ endif
|
||||
ifdef NO_DEMANGLE
|
||||
BASIC_CFLAGS += -DNO_DEMANGLE
|
||||
else
|
||||
|
||||
has_bfd := $(shell sh -c "(echo '\#include <bfd.h>'; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o /dev/null $(ALL_LDFLAGS) -lbfd > /dev/null 2>&1 && echo y")
|
||||
|
||||
has_bfd_iberty := $(shell sh -c "(echo '\#include <bfd.h>'; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o /dev/null $(ALL_LDFLAGS) -lbfd -liberty > /dev/null 2>&1 && echo y")
|
||||
|
||||
has_bfd_iberty_z := $(shell sh -c "(echo '\#include <bfd.h>'; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o /dev/null $(ALL_LDFLAGS) -lbfd -liberty -lz > /dev/null 2>&1 && echo y")
|
||||
|
||||
ifeq ($(has_bfd),y)
|
||||
EXTLIBS += -lbfd
|
||||
else ifeq ($(has_bfd_iberty),y)
|
||||
EXTLIBS += -lbfd -liberty
|
||||
else ifeq ($(has_bfd_iberty_z),y)
|
||||
EXTLIBS += -lbfd -liberty -lz
|
||||
else
|
||||
msg := $(warning No bfd.h/libbfd found, install binutils-dev[el] to gain symbol demangling)
|
||||
BASIC_CFLAGS += -DNO_DEMANGLE
|
||||
has_bfd_iberty := $(shell sh -c "(echo '\#include <bfd.h>'; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o /dev/null $(ALL_LDFLAGS) -lbfd -liberty > /dev/null 2>&1 && echo y")
|
||||
ifeq ($(has_bfd_iberty),y)
|
||||
EXTLIBS += -lbfd -liberty
|
||||
else
|
||||
has_bfd_iberty_z := $(shell sh -c "(echo '\#include <bfd.h>'; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o /dev/null $(ALL_LDFLAGS) -lbfd -liberty -lz > /dev/null 2>&1 && echo y")
|
||||
ifeq ($(has_bfd_iberty_z),y)
|
||||
EXTLIBS += -lbfd -liberty -lz
|
||||
else
|
||||
has_cplus_demangle := $(shell sh -c "(echo 'extern char *cplus_demangle(const char *, int);'; echo 'int main(void) { cplus_demangle(0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o /dev/null $(ALL_LDFLAGS) -liberty > /dev/null 2>&1 && echo y")
|
||||
ifeq ($(has_cplus_demangle),y)
|
||||
EXTLIBS += -liberty
|
||||
BASIC_CFLAGS += -DHAVE_CPLUS_DEMANGLE
|
||||
else
|
||||
msg := $(warning No bfd.h/libbfd found, install binutils-dev[el] to gain symbol demangling)
|
||||
BASIC_CFLAGS += -DNO_DEMANGLE
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
|
@@ -31,6 +31,7 @@ static char *vmlinux = "vmlinux";
|
||||
static char default_sort_order[] = "comm,symbol";
|
||||
static char *sort_order = default_sort_order;
|
||||
|
||||
static int force;
|
||||
static int input;
|
||||
static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
|
||||
|
||||
@@ -980,6 +981,13 @@ process_fork_event(event_t *event, unsigned long offset, unsigned long head)
|
||||
(void *)(long)(event->header.size),
|
||||
event->fork.pid, event->fork.ppid);
|
||||
|
||||
/*
|
||||
* A thread clone will have the same PID for both
|
||||
* parent and child.
|
||||
*/
|
||||
if (thread == parent)
|
||||
return 0;
|
||||
|
||||
if (!thread || !parent || thread__fork(thread, parent)) {
|
||||
dprintf("problem processing PERF_EVENT_FORK, skipping event.\n");
|
||||
return -1;
|
||||
@@ -1327,6 +1335,11 @@ static int __cmd_annotate(void)
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (!force && (stat.st_uid != geteuid())) {
|
||||
fprintf(stderr, "file: %s not owned by current user\n", input_name);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (!stat.st_size) {
|
||||
fprintf(stderr, "zero-sized file, nothing to do!\n");
|
||||
exit(0);
|
||||
@@ -1432,6 +1445,7 @@ static const struct option options[] = {
|
||||
"input file name"),
|
||||
OPT_STRING('s', "symbol", &sym_hist_filter, "symbol",
|
||||
"symbol to annotate"),
|
||||
OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
|
||||
OPT_BOOLEAN('v', "verbose", &verbose,
|
||||
"be more verbose (show symbol address, etc)"),
|
||||
OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
|
||||
|
@@ -10,11 +10,12 @@
|
||||
|
||||
#include "perf.h"
|
||||
|
||||
#include "util/parse-options.h"
|
||||
#include "util/parse-events.h"
|
||||
#include "util/cache.h"
|
||||
|
||||
int cmd_list(int argc __used, const char **argv __used, const char *prefix __used)
|
||||
{
|
||||
setup_pager();
|
||||
print_events();
|
||||
return 0;
|
||||
}
|
||||
|
@@ -34,7 +34,9 @@ static int output;
|
||||
static const char *output_name = "perf.data";
|
||||
static int group = 0;
|
||||
static unsigned int realtime_prio = 0;
|
||||
static int raw_samples = 0;
|
||||
static int system_wide = 0;
|
||||
static int profile_cpu = -1;
|
||||
static pid_t target_pid = -1;
|
||||
static int inherit = 1;
|
||||
static int force = 0;
|
||||
@@ -203,46 +205,48 @@ static void sig_atexit(void)
|
||||
kill(getpid(), signr);
|
||||
}
|
||||
|
||||
static void pid_synthesize_comm_event(pid_t pid, int full)
|
||||
static pid_t pid_synthesize_comm_event(pid_t pid, int full)
|
||||
{
|
||||
struct comm_event comm_ev;
|
||||
char filename[PATH_MAX];
|
||||
char bf[BUFSIZ];
|
||||
int fd;
|
||||
size_t size;
|
||||
char *field, *sep;
|
||||
FILE *fp;
|
||||
size_t size = 0;
|
||||
DIR *tasks;
|
||||
struct dirent dirent, *next;
|
||||
pid_t tgid = 0;
|
||||
|
||||
snprintf(filename, sizeof(filename), "/proc/%d/stat", pid);
|
||||
snprintf(filename, sizeof(filename), "/proc/%d/status", pid);
|
||||
|
||||
fd = open(filename, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
fp = fopen(filename, "r");
|
||||
if (fp == NULL) {
|
||||
/*
|
||||
* We raced with a task exiting - just return:
|
||||
*/
|
||||
if (verbose)
|
||||
fprintf(stderr, "couldn't open %s\n", filename);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
if (read(fd, bf, sizeof(bf)) < 0) {
|
||||
fprintf(stderr, "couldn't read %s\n", filename);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
close(fd);
|
||||
|
||||
/* 9027 (cat) R 6747 9027 6747 34816 9027 ... */
|
||||
memset(&comm_ev, 0, sizeof(comm_ev));
|
||||
field = strchr(bf, '(');
|
||||
if (field == NULL)
|
||||
goto out_failure;
|
||||
sep = strchr(++field, ')');
|
||||
if (sep == NULL)
|
||||
goto out_failure;
|
||||
size = sep - field;
|
||||
memcpy(comm_ev.comm, field, size++);
|
||||
while (!comm_ev.comm[0] || !comm_ev.pid) {
|
||||
if (fgets(bf, sizeof(bf), fp) == NULL)
|
||||
goto out_failure;
|
||||
|
||||
if (memcmp(bf, "Name:", 5) == 0) {
|
||||
char *name = bf + 5;
|
||||
while (*name && isspace(*name))
|
||||
++name;
|
||||
size = strlen(name) - 1;
|
||||
memcpy(comm_ev.comm, name, size++);
|
||||
} else if (memcmp(bf, "Tgid:", 5) == 0) {
|
||||
char *tgids = bf + 5;
|
||||
while (*tgids && isspace(*tgids))
|
||||
++tgids;
|
||||
tgid = comm_ev.pid = atoi(tgids);
|
||||
}
|
||||
}
|
||||
|
||||
comm_ev.pid = pid;
|
||||
comm_ev.header.type = PERF_EVENT_COMM;
|
||||
size = ALIGN(size, sizeof(u64));
|
||||
comm_ev.header.size = sizeof(comm_ev) - (sizeof(comm_ev.comm) - size);
|
||||
@@ -251,7 +255,7 @@ static void pid_synthesize_comm_event(pid_t pid, int full)
|
||||
comm_ev.tid = pid;
|
||||
|
||||
write_output(&comm_ev, comm_ev.header.size);
|
||||
return;
|
||||
goto out_fclose;
|
||||
}
|
||||
|
||||
snprintf(filename, sizeof(filename), "/proc/%d/task", pid);
|
||||
@@ -268,7 +272,10 @@ static void pid_synthesize_comm_event(pid_t pid, int full)
|
||||
write_output(&comm_ev, comm_ev.header.size);
|
||||
}
|
||||
closedir(tasks);
|
||||
return;
|
||||
|
||||
out_fclose:
|
||||
fclose(fp);
|
||||
return tgid;
|
||||
|
||||
out_failure:
|
||||
fprintf(stderr, "couldn't get COMM and pgid, malformed %s\n",
|
||||
@@ -276,7 +283,7 @@ out_failure:
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void pid_synthesize_mmap_samples(pid_t pid)
|
||||
static void pid_synthesize_mmap_samples(pid_t pid, pid_t tgid)
|
||||
{
|
||||
char filename[PATH_MAX];
|
||||
FILE *fp;
|
||||
@@ -328,7 +335,7 @@ static void pid_synthesize_mmap_samples(pid_t pid)
|
||||
mmap_ev.len -= mmap_ev.start;
|
||||
mmap_ev.header.size = (sizeof(mmap_ev) -
|
||||
(sizeof(mmap_ev.filename) - size));
|
||||
mmap_ev.pid = pid;
|
||||
mmap_ev.pid = tgid;
|
||||
mmap_ev.tid = pid;
|
||||
|
||||
write_output(&mmap_ev, mmap_ev.header.size);
|
||||
@@ -347,14 +354,14 @@ static void synthesize_all(void)
|
||||
|
||||
while (!readdir_r(proc, &dirent, &next) && next) {
|
||||
char *end;
|
||||
pid_t pid;
|
||||
pid_t pid, tgid;
|
||||
|
||||
pid = strtol(dirent.d_name, &end, 10);
|
||||
if (*end) /* only interested in proper numerical dirents */
|
||||
continue;
|
||||
|
||||
pid_synthesize_comm_event(pid, 1);
|
||||
pid_synthesize_mmap_samples(pid);
|
||||
tgid = pid_synthesize_comm_event(pid, 1);
|
||||
pid_synthesize_mmap_samples(pid, tgid);
|
||||
}
|
||||
|
||||
closedir(proc);
|
||||
@@ -392,7 +399,7 @@ static void create_counter(int counter, int cpu, pid_t pid)
|
||||
PERF_FORMAT_TOTAL_TIME_RUNNING |
|
||||
PERF_FORMAT_ID;
|
||||
|
||||
attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
|
||||
attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
|
||||
|
||||
if (freq) {
|
||||
attr->sample_type |= PERF_SAMPLE_PERIOD;
|
||||
@@ -412,6 +419,8 @@ static void create_counter(int counter, int cpu, pid_t pid)
|
||||
if (call_graph)
|
||||
attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
|
||||
|
||||
if (raw_samples)
|
||||
attr->sample_type |= PERF_SAMPLE_RAW;
|
||||
|
||||
attr->mmap = track;
|
||||
attr->comm = track;
|
||||
@@ -426,6 +435,8 @@ try_again:
|
||||
|
||||
if (err == EPERM)
|
||||
die("Permission error - are you root?\n");
|
||||
else if (err == ENODEV && profile_cpu != -1)
|
||||
die("No such device - did you specify an out-of-range profile CPU?\n");
|
||||
|
||||
/*
|
||||
* If it's cycles then fall back to hrtimer
|
||||
@@ -559,16 +570,22 @@ static int __cmd_record(int argc, const char **argv)
|
||||
if (pid == -1)
|
||||
pid = getpid();
|
||||
|
||||
open_counters(-1, pid);
|
||||
} else for (i = 0; i < nr_cpus; i++)
|
||||
open_counters(i, target_pid);
|
||||
open_counters(profile_cpu, pid);
|
||||
} else {
|
||||
if (profile_cpu != -1) {
|
||||
open_counters(profile_cpu, target_pid);
|
||||
} else {
|
||||
for (i = 0; i < nr_cpus; i++)
|
||||
open_counters(i, target_pid);
|
||||
}
|
||||
}
|
||||
|
||||
if (file_new)
|
||||
perf_header__write(header, output);
|
||||
|
||||
if (!system_wide) {
|
||||
pid_synthesize_comm_event(pid, 0);
|
||||
pid_synthesize_mmap_samples(pid);
|
||||
pid_t tgid = pid_synthesize_comm_event(pid, 0);
|
||||
pid_synthesize_mmap_samples(pid, tgid);
|
||||
} else
|
||||
synthesize_all();
|
||||
|
||||
@@ -636,10 +653,14 @@ static const struct option options[] = {
|
||||
"record events on existing pid"),
|
||||
OPT_INTEGER('r', "realtime", &realtime_prio,
|
||||
"collect data with this RT SCHED_FIFO priority"),
|
||||
OPT_BOOLEAN('R', "raw-samples", &raw_samples,
|
||||
"collect raw sample records from all opened counters"),
|
||||
OPT_BOOLEAN('a', "all-cpus", &system_wide,
|
||||
"system-wide collection from all CPUs"),
|
||||
OPT_BOOLEAN('A', "append", &append_file,
|
||||
"append to the output file to do incremental profiling"),
|
||||
OPT_INTEGER('C', "profile_cpu", &profile_cpu,
|
||||
"CPU to profile on"),
|
||||
OPT_BOOLEAN('f', "force", &force,
|
||||
"overwrite existing data file"),
|
||||
OPT_LONG('c', "count", &default_interval,
|
||||
|
@@ -38,6 +38,7 @@ static char *dso_list_str, *comm_list_str, *sym_list_str,
|
||||
static struct strlist *dso_list, *comm_list, *sym_list;
|
||||
static char *field_sep;
|
||||
|
||||
static int force;
|
||||
static int input;
|
||||
static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
|
||||
|
||||
@@ -1526,11 +1527,11 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
|
||||
more_data += sizeof(u64);
|
||||
}
|
||||
|
||||
dprintf("%p [%p]: PERF_EVENT_SAMPLE (IP, %d): %d: %p period: %Ld\n",
|
||||
dprintf("%p [%p]: PERF_EVENT_SAMPLE (IP, %d): %d/%d: %p period: %Ld\n",
|
||||
(void *)(offset + head),
|
||||
(void *)(long)(event->header.size),
|
||||
event->header.misc,
|
||||
event->ip.pid,
|
||||
event->ip.pid, event->ip.tid,
|
||||
(void *)(long)ip,
|
||||
(long long)period);
|
||||
|
||||
@@ -1590,10 +1591,11 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
|
||||
if (show & show_mask) {
|
||||
struct symbol *sym = resolve_symbol(thread, &map, &dso, &ip);
|
||||
|
||||
if (dso_list && dso && dso->name && !strlist__has_entry(dso_list, dso->name))
|
||||
if (dso_list && (!dso || !dso->name ||
|
||||
!strlist__has_entry(dso_list, dso->name)))
|
||||
return 0;
|
||||
|
||||
if (sym_list && sym && !strlist__has_entry(sym_list, sym->name))
|
||||
if (sym_list && (!sym || !strlist__has_entry(sym_list, sym->name)))
|
||||
return 0;
|
||||
|
||||
if (hist_entry__add(thread, map, dso, sym, ip, chain, level, period)) {
|
||||
@@ -1612,10 +1614,11 @@ process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
|
||||
struct thread *thread = threads__findnew(event->mmap.pid);
|
||||
struct map *map = map__new(&event->mmap);
|
||||
|
||||
dprintf("%p [%p]: PERF_EVENT_MMAP %d: [%p(%p) @ %p]: %s\n",
|
||||
dprintf("%p [%p]: PERF_EVENT_MMAP %d/%d: [%p(%p) @ %p]: %s\n",
|
||||
(void *)(offset + head),
|
||||
(void *)(long)(event->header.size),
|
||||
event->mmap.pid,
|
||||
event->mmap.tid,
|
||||
(void *)(long)event->mmap.start,
|
||||
(void *)(long)event->mmap.len,
|
||||
(void *)(long)event->mmap.pgoff,
|
||||
@@ -1854,6 +1857,11 @@ static int __cmd_report(void)
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (!force && (stat.st_uid != geteuid())) {
|
||||
fprintf(stderr, "file: %s not owned by current user\n", input_name);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (!stat.st_size) {
|
||||
fprintf(stderr, "zero-sized file, nothing to do!\n");
|
||||
exit(0);
|
||||
@@ -2062,6 +2070,7 @@ static const struct option options[] = {
|
||||
OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
|
||||
"dump raw trace in ASCII"),
|
||||
OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
|
||||
OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
|
||||
OPT_BOOLEAN('m', "modules", &modules,
|
||||
"load module symbols - WARNING: use only with -k and LIVE kernel"),
|
||||
OPT_BOOLEAN('n', "show-nr-samples", &show_nr_samples,
|
||||
|
@@ -379,6 +379,7 @@ static int parse_tracepoint_event(const char **strp,
|
||||
struct perf_counter_attr *attr)
|
||||
{
|
||||
const char *evt_name;
|
||||
char *flags;
|
||||
char sys_name[MAX_EVENT_LENGTH];
|
||||
char id_buf[4];
|
||||
int fd;
|
||||
@@ -400,6 +401,15 @@ static int parse_tracepoint_event(const char **strp,
|
||||
strncpy(sys_name, *strp, sys_length);
|
||||
sys_name[sys_length] = '\0';
|
||||
evt_name = evt_name + 1;
|
||||
|
||||
flags = strchr(evt_name, ':');
|
||||
if (flags) {
|
||||
*flags = '\0';
|
||||
flags++;
|
||||
if (!strncmp(flags, "record", strlen(flags)))
|
||||
attr->sample_type |= PERF_SAMPLE_RAW;
|
||||
}
|
||||
|
||||
evt_length = strlen(evt_name);
|
||||
if (evt_length >= MAX_EVENT_LENGTH)
|
||||
return 0;
|
||||
|
@@ -7,23 +7,8 @@
|
||||
#include <gelf.h>
|
||||
#include <elf.h>
|
||||
|
||||
#ifndef NO_DEMANGLE
|
||||
#include <bfd.h>
|
||||
#else
|
||||
static inline
|
||||
char *bfd_demangle(void __used *v, const char __used *c, int __used i)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
const char *sym_hist_filter;
|
||||
|
||||
#ifndef DMGL_PARAMS
|
||||
#define DMGL_PARAMS (1 << 0) /* Include function args */
|
||||
#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */
|
||||
#endif
|
||||
|
||||
enum dso_origin {
|
||||
DSO__ORIG_KERNEL = 0,
|
||||
DSO__ORIG_JAVA_JIT,
|
||||
@@ -816,6 +801,8 @@ more:
|
||||
}
|
||||
out:
|
||||
free(name);
|
||||
if (ret < 0 && strstr(self->name, " (deleted)") != NULL)
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@@ -7,6 +7,30 @@
|
||||
#include <linux/rbtree.h>
|
||||
#include "module.h"
|
||||
|
||||
#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
|
||||
|
||||
#ifndef DMGL_PARAMS
|
||||
#define DMGL_PARAMS (1 << 0) /* Include function args */
|
||||
#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */
|
||||
#endif
|
||||
|
||||
struct symbol {
|
||||
struct rb_node rb_node;
|
||||
u64 start;
|
||||
|
Reference in New Issue
Block a user