aboutsummaryrefslogtreecommitdiff
path: root/tools/perf/util
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/annotate.c60
-rw-r--r--tools/perf/util/build-id.c11
-rw-r--r--tools/perf/util/callchain.c15
-rw-r--r--tools/perf/util/callchain.h11
-rw-r--r--tools/perf/util/cpumap.h2
-rw-r--r--tools/perf/util/dso.c10
-rw-r--r--tools/perf/util/dso.h17
-rw-r--r--tools/perf/util/event.c31
-rw-r--r--tools/perf/util/event.h41
-rw-r--r--tools/perf/util/evlist.c294
-rw-r--r--tools/perf/util/evlist.h21
-rw-r--r--tools/perf/util/evsel.c581
-rw-r--r--tools/perf/util/evsel.h19
-rw-r--r--tools/perf/util/header.c161
-rw-r--r--tools/perf/util/header.h40
-rw-r--r--tools/perf/util/hist.c4
-rw-r--r--tools/perf/util/hist.h26
-rw-r--r--tools/perf/util/include/linux/string.h1
-rw-r--r--tools/perf/util/machine.c155
-rw-r--r--tools/perf/util/machine.h14
-rw-r--r--tools/perf/util/map.c67
-rw-r--r--tools/perf/util/map.h13
-rw-r--r--tools/perf/util/parse-events.c174
-rw-r--r--tools/perf/util/parse-events.h11
-rw-r--r--tools/perf/util/parse-events.l4
-rw-r--r--tools/perf/util/parse-events.y62
-rw-r--r--tools/perf/util/pmu.c87
-rw-r--r--tools/perf/util/pmu.h5
-rw-r--r--tools/perf/util/python.c21
-rw-r--r--tools/perf/util/record.c108
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c14
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c9
-rw-r--r--tools/perf/util/session.c241
-rw-r--r--tools/perf/util/session.h14
-rw-r--r--tools/perf/util/sort.c12
-rw-r--r--tools/perf/util/sort.h13
-rw-r--r--tools/perf/util/stat.c6
-rw-r--r--tools/perf/util/stat.h9
-rw-r--r--tools/perf/util/string.c24
-rw-r--r--tools/perf/util/symbol-elf.c174
-rw-r--r--tools/perf/util/symbol-minimal.c7
-rw-r--r--tools/perf/util/symbol.c285
-rw-r--r--tools/perf/util/symbol.h5
-rw-r--r--tools/perf/util/thread.c11
-rw-r--r--tools/perf/util/thread.h23
-rw-r--r--tools/perf/util/tool.h10
-rw-r--r--tools/perf/util/top.h2
-rw-r--r--tools/perf/util/trace-event-info.c96
-rw-r--r--tools/perf/util/trace-event-parse.c6
-rw-r--r--tools/perf/util/trace-event-read.c52
-rw-r--r--tools/perf/util/trace-event-scripting.c3
-rw-r--r--tools/perf/util/trace-event.h21
-rw-r--r--tools/perf/util/unwind.c2
-rw-r--r--tools/perf/util/util.c92
-rw-r--r--tools/perf/util/util.h5
55 files changed, 2436 insertions, 766 deletions
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index d102716c43a..bfc5a27597d 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -110,10 +110,10 @@ static int jump__parse(struct ins_operands *ops)
{
const char *s = strchr(ops->raw, '+');
- ops->target.addr = strtoll(ops->raw, NULL, 16);
+ ops->target.addr = strtoull(ops->raw, NULL, 16);
if (s++ != NULL)
- ops->target.offset = strtoll(s, NULL, 16);
+ ops->target.offset = strtoull(s, NULL, 16);
else
ops->target.offset = UINT64_MAX;
@@ -821,11 +821,55 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
if (dl == NULL)
return -1;
+ if (dl->ops.target.offset == UINT64_MAX)
+ dl->ops.target.offset = dl->ops.target.addr -
+ map__rip_2objdump(map, sym->start);
+
+ /*
+ * kcore has no symbols, so add the call target name if it is on the
+ * same map.
+ */
+ if (dl->ins && ins__is_call(dl->ins) && !dl->ops.target.name) {
+ struct symbol *s;
+ u64 ip = dl->ops.target.addr;
+
+ if (ip >= map->start && ip <= map->end) {
+ ip = map->map_ip(map, ip);
+ s = map__find_symbol(map, ip, NULL);
+ if (s && s->start == ip)
+ dl->ops.target.name = strdup(s->name);
+ }
+ }
+
disasm__add(&notes->src->source, dl);
return 0;
}
+static void delete_last_nop(struct symbol *sym)
+{
+ struct annotation *notes = symbol__annotation(sym);
+ struct list_head *list = &notes->src->source;
+ struct disasm_line *dl;
+
+ while (!list_empty(list)) {
+ dl = list_entry(list->prev, struct disasm_line, node);
+
+ if (dl->ins && dl->ins->ops) {
+ if (dl->ins->ops != &nop_ops)
+ return;
+ } else {
+ if (!strstr(dl->line, " nop ") &&
+ !strstr(dl->line, " nopl ") &&
+ !strstr(dl->line, " nopw "))
+ return;
+ }
+
+ list_del(&dl->node);
+ disasm_line__free(dl);
+ }
+}
+
int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
{
struct dso *dso = map->dso;
@@ -864,7 +908,8 @@ fallback:
free_filename = false;
}
- if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS) {
+ if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
+ !dso__is_kcore(dso)) {
char bf[BUILD_ID_SIZE * 2 + 16] = " with build id ";
char *build_id_msg = NULL;
@@ -898,7 +943,7 @@ fallback:
snprintf(command, sizeof(command),
"%s %s%s --start-address=0x%016" PRIx64
" --stop-address=0x%016" PRIx64
- " -d %s %s -C %s|grep -v %s|expand",
+ " -d %s %s -C %s 2>/dev/null|grep -v %s|expand",
objdump_path ? objdump_path : "objdump",
disassembler_style ? "-M " : "",
disassembler_style ? disassembler_style : "",
@@ -918,6 +963,13 @@ fallback:
if (symbol__parse_objdump_line(sym, map, file, privsize) < 0)
break;
+ /*
+ * kallsyms does not have symbol sizes so there may a nop at the end.
+ * Remove it.
+ */
+ if (dso__is_kcore(dso))
+ delete_last_nop(sym);
+
pclose(file);
out_free_filename:
if (free_filename)
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 5295625c0c0..fb584092eb8 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -18,13 +18,14 @@
int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused,
union perf_event *event,
- struct perf_sample *sample __maybe_unused,
+ struct perf_sample *sample,
struct perf_evsel *evsel __maybe_unused,
struct machine *machine)
{
struct addr_location al;
u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
- struct thread *thread = machine__findnew_thread(machine, event->ip.pid);
+ struct thread *thread = machine__findnew_thread(machine, sample->pid,
+ sample->pid);
if (thread == NULL) {
pr_err("problem processing %d event, skipping it.\n",
@@ -33,7 +34,7 @@ int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused,
}
thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
- event->ip.ip, &al);
+ sample->ip, &al);
if (al.map != NULL)
al.map->dso->hit = 1;
@@ -47,7 +48,9 @@ static int perf_event__exit_del_thread(struct perf_tool *tool __maybe_unused,
__maybe_unused,
struct machine *machine)
{
- struct thread *thread = machine__findnew_thread(machine, event->fork.tid);
+ struct thread *thread = machine__findnew_thread(machine,
+ event->fork.pid,
+ event->fork.tid);
dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid,
event->fork.ppid, event->fork.ptid);
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 42b6a632fe7..482f68081cd 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -15,19 +15,12 @@
#include <errno.h>
#include <math.h>
+#include "hist.h"
#include "util.h"
#include "callchain.h"
__thread struct callchain_cursor callchain_cursor;
-bool ip_callchain__valid(struct ip_callchain *chain,
- const union perf_event *event)
-{
- unsigned int chain_size = event->header.size;
- chain_size -= (unsigned long)&event->ip.__more_data - (unsigned long)event;
- return chain->nr * sizeof(u64) <= chain_size;
-}
-
#define chain_for_each_child(child, parent) \
list_for_each_entry(child, &parent->children, siblings)
@@ -327,7 +320,8 @@ append_chain(struct callchain_node *root,
/*
* Lookup in the current node
* If we have a symbol, then compare the start to match
- * anywhere inside a function.
+ * anywhere inside a function, unless function
+ * mode is disabled.
*/
list_for_each_entry(cnode, &root->val, list) {
struct callchain_cursor_node *node;
@@ -339,7 +333,8 @@ append_chain(struct callchain_node *root,
sym = node->sym;
- if (cnode->ms.sym && sym) {
+ if (cnode->ms.sym && sym &&
+ callchain_param.key == CCKEY_FUNCTION) {
if (cnode->ms.sym->start != sym->start)
break;
} else if (cnode->ip != node->ip)
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 3ee9f67d5af..2b585bc308c 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -41,12 +41,18 @@ struct callchain_param;
typedef void (*sort_chain_func_t)(struct rb_root *, struct callchain_root *,
u64, struct callchain_param *);
+enum chain_key {
+ CCKEY_FUNCTION,
+ CCKEY_ADDRESS
+};
+
struct callchain_param {
enum chain_mode mode;
u32 print_limit;
double min_percent;
sort_chain_func_t sort;
enum chain_order order;
+ enum chain_key key;
};
struct callchain_list {
@@ -103,11 +109,6 @@ int callchain_append(struct callchain_root *root,
int callchain_merge(struct callchain_cursor *cursor,
struct callchain_root *dst, struct callchain_root *src);
-struct ip_callchain;
-union perf_event;
-
-bool ip_callchain__valid(struct ip_callchain *chain,
- const union perf_event *event);
/*
* Initialize a cursor before adding entries inside, but keep
* the previously allocated entries as a cache.
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index 9bed02e5fb3..b123bb9d6f5 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -41,7 +41,7 @@ static inline int cpu_map__nr(const struct cpu_map *map)
return map ? map->nr : 1;
}
-static inline bool cpu_map__all(const struct cpu_map *map)
+static inline bool cpu_map__empty(const struct cpu_map *map)
{
return map ? map->map[0] == -1 : true;
}
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index c4374f07603..e3c1ff8512c 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -78,6 +78,8 @@ int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
symbol_conf.symfs, build_id_hex, build_id_hex + 2);
break;
+ case DSO_BINARY_TYPE__VMLINUX:
+ case DSO_BINARY_TYPE__GUEST_VMLINUX:
case DSO_BINARY_TYPE__SYSTEM_PATH_DSO:
snprintf(file, size, "%s%s",
symbol_conf.symfs, dso->long_name);
@@ -93,11 +95,14 @@ int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
dso->long_name);
break;
+ case DSO_BINARY_TYPE__KCORE:
+ case DSO_BINARY_TYPE__GUEST_KCORE:
+ snprintf(file, size, "%s", dso->long_name);
+ break;
+
default:
case DSO_BINARY_TYPE__KALLSYMS:
- case DSO_BINARY_TYPE__VMLINUX:
case DSO_BINARY_TYPE__GUEST_KALLSYMS:
- case DSO_BINARY_TYPE__GUEST_VMLINUX:
case DSO_BINARY_TYPE__JAVA_JIT:
case DSO_BINARY_TYPE__NOT_FOUND:
ret = -1;
@@ -419,6 +424,7 @@ struct dso *dso__new(const char *name)
dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND;
dso->data_type = DSO_BINARY_TYPE__NOT_FOUND;
dso->loaded = 0;
+ dso->rel = 0;
dso->sorted_by_name = 0;
dso->has_build_id = 0;
dso->kernel = DSO_TYPE_USER;
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index d51aaf272c6..b793053335d 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -3,6 +3,7 @@
#include <linux/types.h>
#include <linux/rbtree.h>
+#include <stdbool.h>
#include "types.h"
#include "map.h"
@@ -20,6 +21,8 @@ enum dso_binary_type {
DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
DSO_BINARY_TYPE__GUEST_KMODULE,
DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
+ DSO_BINARY_TYPE__KCORE,
+ DSO_BINARY_TYPE__GUEST_KCORE,
DSO_BINARY_TYPE__NOT_FOUND,
};
@@ -84,6 +87,7 @@ struct dso {
u8 lname_alloc:1;
u8 sorted_by_name;
u8 loaded;
+ u8 rel;
u8 build_id[BUILD_ID_SIZE];
const char *short_name;
char *long_name;
@@ -146,4 +150,17 @@ 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);
+
+static inline bool dso__is_vmlinux(struct dso *dso)
+{
+ return dso->data_type == DSO_BINARY_TYPE__VMLINUX ||
+ dso->data_type == DSO_BINARY_TYPE__GUEST_VMLINUX;
+}
+
+static inline bool dso__is_kcore(struct dso *dso)
+{
+ return dso->data_type == DSO_BINARY_TYPE__KCORE ||
+ dso->data_type == DSO_BINARY_TYPE__GUEST_KCORE;
+}
+
#endif /* __PERF_DSO */
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 5cd13d768ce..8d51f21107a 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -595,6 +595,7 @@ void thread__find_addr_map(struct thread *self,
struct addr_location *al)
{
struct map_groups *mg = &self->mg;
+ bool load_map = false;
al->thread = self;
al->addr = addr;
@@ -609,11 +610,13 @@ void thread__find_addr_map(struct thread *self,
if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) {
al->level = 'k';
mg = &machine->kmaps;
+ load_map = true;
} else if (cpumode == PERF_RECORD_MISC_USER && perf_host) {
al->level = '.';
} else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) {
al->level = 'g';
mg = &machine->kmaps;
+ load_map = true;
} else {
/*
* 'u' means guest os user space.
@@ -654,18 +657,25 @@ try_again:
mg = &machine->kmaps;
goto try_again;
}
- } else
+ } else {
+ /*
+ * Kernel maps might be changed when loading symbols so loading
+ * must be done prior to using kernel maps.
+ */
+ if (load_map)
+ map__load(al->map, machine->symbol_filter);
al->addr = al->map->map_ip(al->map, al->addr);
+ }
}
void thread__find_addr_location(struct thread *thread, struct machine *machine,
u8 cpumode, enum map_type type, u64 addr,
- struct addr_location *al,
- symbol_filter_t filter)
+ struct addr_location *al)
{
thread__find_addr_map(thread, machine, cpumode, type, addr, al);
if (al->map != NULL)
- al->sym = map__find_symbol(al->map, al->addr, filter);
+ al->sym = map__find_symbol(al->map, al->addr,
+ machine->symbol_filter);
else
al->sym = NULL;
}
@@ -673,11 +683,11 @@ void thread__find_addr_location(struct thread *thread, struct machine *machine,
int perf_event__preprocess_sample(const union perf_event *event,
struct machine *machine,
struct addr_location *al,
- struct perf_sample *sample,
- symbol_filter_t filter)
+ struct perf_sample *sample)
{
u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
- struct thread *thread = machine__findnew_thread(machine, event->ip.pid);
+ struct thread *thread = machine__findnew_thread(machine, sample->pid,
+ sample->pid);
if (thread == NULL)
return -1;
@@ -686,7 +696,7 @@ int perf_event__preprocess_sample(const union perf_event *event,
!strlist__has_entry(symbol_conf.comm_list, thread->comm))
goto out_filtered;
- dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
+ dump_printf(" ... thread: %s:%d\n", thread->comm, thread->tid);
/*
* Have we already created the kernel maps for this machine?
*
@@ -699,7 +709,7 @@ int perf_event__preprocess_sample(const union perf_event *event,
machine__create_kernel_maps(machine);
thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
- event->ip.ip, al);
+ sample->ip, al);
dump_printf(" ...... dso: %s\n",
al->map ? al->map->dso->long_name :
al->level == 'H' ? "[hypervisor]" : "<not found>");
@@ -717,7 +727,8 @@ int perf_event__preprocess_sample(const union perf_event *event,
dso->long_name)))))
goto out_filtered;
- al->sym = map__find_symbol(al->map, al->addr, filter);
+ al->sym = map__find_symbol(al->map, al->addr,
+ machine->symbol_filter);
}
if (symbol_conf.sym_list &&
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 181389535c0..93130d856bf 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -8,16 +8,6 @@
#include "map.h"
#include "build-id.h"
-/*
- * PERF_SAMPLE_IP | PERF_SAMPLE_TID | *
- */
-struct ip_event {
- struct perf_event_header header;
- u64 ip;
- u32 pid, tid;
- unsigned char __more_data[];
-};
-
struct mmap_event {
struct perf_event_header header;
u32 pid, tid;
@@ -63,7 +53,8 @@ struct read_event {
(PERF_SAMPLE_IP | PERF_SAMPLE_TID | \
PERF_SAMPLE_TIME | PERF_SAMPLE_ADDR | \
PERF_SAMPLE_ID | PERF_SAMPLE_STREAM_ID | \
- PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD)
+ PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD | \
+ PERF_SAMPLE_IDENTIFIER)
struct sample_event {
struct perf_event_header header;
@@ -71,6 +62,7 @@ struct sample_event {
};
struct regs_dump {
+ u64 abi;
u64 *regs;
};
@@ -80,6 +72,23 @@ struct stack_dump {
char *data;
};
+struct sample_read_value {
+ u64 value;
+ u64 id;
+};
+
+struct sample_read {
+ u64 time_enabled;
+ u64 time_running;
+ union {
+ struct {
+ u64 nr;
+ struct sample_read_value *values;
+ } group;
+ struct sample_read_value one;
+ };
+};
+
struct perf_sample {
u64 ip;
u32 pid, tid;
@@ -97,6 +106,7 @@ struct perf_sample {
struct branch_stack *branch_stack;
struct regs_dump user_regs;
struct stack_dump user_stack;
+ struct sample_read read;
};
#define PERF_MEM_DATA_SRC_NONE \
@@ -116,7 +126,7 @@ struct build_id_event {
enum perf_user_event_type { /* above any possible kernel type */
PERF_RECORD_USER_TYPE_START = 64,
PERF_RECORD_HEADER_ATTR = 64,
- PERF_RECORD_HEADER_EVENT_TYPE = 65,
+ PERF_RECORD_HEADER_EVENT_TYPE = 65, /* depreceated */
PERF_RECORD_HEADER_TRACING_DATA = 66,
PERF_RECORD_HEADER_BUILD_ID = 67,
PERF_RECORD_FINISHED_ROUND = 68,
@@ -148,7 +158,6 @@ struct tracing_data_event {
union perf_event {
struct perf_event_header header;
- struct ip_event ip;
struct mmap_event mmap;
struct comm_event comm;
struct fork_event fork;
@@ -216,12 +225,14 @@ struct addr_location;
int perf_event__preprocess_sample(const union perf_event *self,
struct machine *machine,
struct addr_location *al,
- struct perf_sample *sample,
- symbol_filter_t filter);
+ struct perf_sample *sample);
const char *perf_event__name(unsigned int id);
+size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
+ u64 sample_regs_user, u64 read_format);
int perf_event__synthesize_sample(union perf_event *event, u64 type,
+ u64 sample_regs_user, u64 read_format,
const struct perf_sample *sample,
bool swapped);
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 8065ce8fa9a..b8727ae45e3 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -14,6 +14,7 @@
#include "target.h"
#include "evlist.h"
#include "evsel.h"
+#include "debug.h"
#include <unistd.h>
#include "parse-events.h"
@@ -48,26 +49,19 @@ struct perf_evlist *perf_evlist__new(void)
return evlist;
}
-void perf_evlist__config(struct perf_evlist *evlist,
- struct perf_record_opts *opts)
+/**
+ * perf_evlist__set_id_pos - set the positions of event ids.
+ * @evlist: selected event list
+ *
+ * Events with compatible sample types all have the same id_pos
+ * and is_pos. For convenience, put a copy on evlist.
+ */
+void perf_evlist__set_id_pos(struct perf_evlist *evlist)
{
- struct perf_evsel *evsel;
- /*
- * Set the evsel leader links before we configure attributes,
- * since some might depend on this info.
- */
- if (opts->group)
- perf_evlist__set_leader(evlist);
-
- if (evlist->cpus->map[0] < 0)
- opts->no_inherit = true;
-
- list_for_each_entry(evsel, &evlist->entries, node) {
- perf_evsel__config(evsel, opts);
+ struct perf_evsel *first = perf_evlist__first(evlist);
- if (evlist->nr_entries > 1)
- perf_evsel__set_sample_id(evsel);
- }
+ evlist->id_pos = first->id_pos;
+ evlist->is_pos = first->is_pos;
}
static void perf_evlist__purge(struct perf_evlist *evlist)
@@ -100,15 +94,20 @@ void perf_evlist__delete(struct perf_evlist *evlist)
void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
{
list_add_tail(&entry->node, &evlist->entries);
- ++evlist->nr_entries;
+ if (!evlist->nr_entries++)
+ perf_evlist__set_id_pos(evlist);
}
void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
struct list_head *list,
int nr_entries)
{
+ bool set_id_pos = !evlist->nr_entries;
+
list_splice_tail(list, &evlist->entries);
evlist->nr_entries += nr_entries;
+ if (set_id_pos)
+ perf_evlist__set_id_pos(evlist);
}
void __perf_evlist__set_leader(struct list_head *list)
@@ -209,6 +208,21 @@ perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
return NULL;
}
+struct perf_evsel *
+perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist,
+ const char *name)
+{
+ struct perf_evsel *evsel;
+
+ list_for_each_entry(evsel, &evlist->entries, node) {
+ if ((evsel->attr.type == PERF_TYPE_TRACEPOINT) &&
+ (strcmp(evsel->name, name) == 0))
+ return evsel;
+ }
+
+ return NULL;
+}
+
int perf_evlist__add_newtp(struct perf_evlist *evlist,
const char *sys, const char *name, void *handler)
{
@@ -232,7 +246,7 @@ void perf_evlist__disable(struct perf_evlist *evlist)
for (cpu = 0; cpu < nr_cpus; cpu++) {
list_for_each_entry(pos, &evlist->entries, node) {
- if (!perf_evsel__is_group_leader(pos))
+ if (!perf_evsel__is_group_leader(pos) || !pos->fd)
continue;
for (thread = 0; thread < nr_threads; thread++)
ioctl(FD(pos, cpu, thread),
@@ -250,7 +264,7 @@ void perf_evlist__enable(struct perf_evlist *evlist)