aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/Makefile.perf2
-rw-r--r--tools/perf/util/comm.h4
-rw-r--r--tools/perf/util/db-export.c270
-rw-r--r--tools/perf/util/db-export.h86
-rw-r--r--tools/perf/util/dso.h5
-rw-r--r--tools/perf/util/evsel.h2
-rw-r--r--tools/perf/util/machine.h4
-rw-r--r--tools/perf/util/thread.h1
8 files changed, 374 insertions, 0 deletions
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 9c4ced0fc845..3caf7dab50e8 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -258,6 +258,7 @@ LIB_H += util/annotate.h
258LIB_H += util/cache.h 258LIB_H += util/cache.h
259LIB_H += util/callchain.h 259LIB_H += util/callchain.h
260LIB_H += util/build-id.h 260LIB_H += util/build-id.h
261LIB_H += util/db-export.h
261LIB_H += util/debug.h 262LIB_H += util/debug.h
262LIB_H += util/pmu.h 263LIB_H += util/pmu.h
263LIB_H += util/event.h 264LIB_H += util/event.h
@@ -323,6 +324,7 @@ LIB_OBJS += $(OUTPUT)util/annotate.o
323LIB_OBJS += $(OUTPUT)util/build-id.o 324LIB_OBJS += $(OUTPUT)util/build-id.o
324LIB_OBJS += $(OUTPUT)util/config.o 325LIB_OBJS += $(OUTPUT)util/config.o
325LIB_OBJS += $(OUTPUT)util/ctype.o 326LIB_OBJS += $(OUTPUT)util/ctype.o
327LIB_OBJS += $(OUTPUT)util/db-export.o
326LIB_OBJS += $(OUTPUT)util/pmu.o 328LIB_OBJS += $(OUTPUT)util/pmu.o
327LIB_OBJS += $(OUTPUT)util/environment.o 329LIB_OBJS += $(OUTPUT)util/environment.o
328LIB_OBJS += $(OUTPUT)util/event.o 330LIB_OBJS += $(OUTPUT)util/event.o
diff --git a/tools/perf/util/comm.h b/tools/perf/util/comm.h
index 51c10ab257f8..71c9c39340d4 100644
--- a/tools/perf/util/comm.h
+++ b/tools/perf/util/comm.h
@@ -12,6 +12,10 @@ struct comm {
12 u64 start; 12 u64 start;
13 struct list_head list; 13 struct list_head list;
14 bool exec; 14 bool exec;
15 union { /* Tool specific area */
16 void *priv;
17 u64 db_id;
18 };
15}; 19};
16 20
17void comm__free(struct comm *comm); 21void comm__free(struct comm *comm);
diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c
new file mode 100644
index 000000000000..be128b075a32
--- /dev/null
+++ b/tools/perf/util/db-export.c
@@ -0,0 +1,270 @@
1/*
2 * db-export.c: Support for exporting data suitable for import to a database
3 * Copyright (c) 2014, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 */
15
16#include <errno.h>
17
18#include "evsel.h"
19#include "machine.h"
20#include "thread.h"
21#include "comm.h"
22#include "symbol.h"
23#include "event.h"
24#include "db-export.h"
25
26int db_export__init(struct db_export *dbe)
27{
28 memset(dbe, 0, sizeof(struct db_export));
29 return 0;
30}
31
32void db_export__exit(struct db_export *dbe __maybe_unused)
33{
34}
35
36int db_export__evsel(struct db_export *dbe, struct perf_evsel *evsel)
37{
38 if (evsel->db_id)
39 return 0;
40
41 evsel->db_id = ++dbe->evsel_last_db_id;
42
43 if (dbe->export_evsel)
44 return dbe->export_evsel(dbe, evsel);
45
46 return 0;
47}
48
49int db_export__machine(struct db_export *dbe, struct machine *machine)
50{
51 if (machine->db_id)
52 return 0;
53
54 machine->db_id = ++dbe->machine_last_db_id;
55
56 if (dbe->export_machine)
57 return dbe->export_machine(dbe, machine);
58
59 return 0;
60}
61
62int db_export__thread(struct db_export *dbe, struct thread *thread,
63 struct machine *machine, struct comm *comm)
64{
65 u64 main_thread_db_id = 0;
66 int err;
67
68 if (thread->db_id)
69 return 0;
70
71 thread->db_id = ++dbe->thread_last_db_id;
72
73 if (thread->pid_ != -1) {
74 struct thread *main_thread;
75
76 if (thread->pid_ == thread->tid) {
77 main_thread = thread;
78 } else {
79 main_thread = machine__findnew_thread(machine,
80 thread->pid_,
81 thread->pid_);
82 if (!main_thread)
83 return -ENOMEM;
84 err = db_export__thread(dbe, main_thread, machine,
85 comm);
86 if (err)
87 return err;
88 if (comm) {
89 err = db_export__comm_thread(dbe, comm, thread);
90 if (err)
91 return err;
92 }
93 }
94 main_thread_db_id = main_thread->db_id;
95 }
96
97 if (dbe->export_thread)
98 return dbe->export_thread(dbe, thread, main_thread_db_id,
99 machine);
100
101 return 0;
102}
103
104int db_export__comm(struct db_export *dbe, struct comm *comm,
105 struct thread *main_thread)
106{
107 int err;
108
109 if (comm->db_id)
110 return 0;
111
112 comm->db_id = ++dbe->comm_last_db_id;
113
114 if (dbe->export_comm) {
115 err = dbe->export_comm(dbe, comm);
116 if (err)
117 return err;
118 }
119
120 return db_export__comm_thread(dbe, comm, main_thread);
121}
122
123int db_export__comm_thread(struct db_export *dbe, struct comm *comm,
124 struct thread *thread)
125{
126 u64 db_id;
127
128 db_id = ++dbe->comm_thread_last_db_id;
129
130 if (dbe->export_comm_thread)
131 return dbe->export_comm_thread(dbe, db_id, comm, thread);
132
133 return 0;
134}
135
136int db_export__dso(struct db_export *dbe, struct dso *dso,
137 struct machine *machine)
138{
139 if (dso->db_id)
140 return 0;
141
142 dso->db_id = ++dbe->dso_last_db_id;
143
144 if (dbe->export_dso)
145 return dbe->export_dso(dbe, dso, machine);
146
147 return 0;
148}
149
150int db_export__symbol(struct db_export *dbe, struct symbol *sym,
151 struct dso *dso)
152{
153 u64 *sym_db_id = symbol__priv(sym);
154
155 if (*sym_db_id)
156 return 0;
157
158 *sym_db_id = ++dbe->symbol_last_db_id;
159
160 if (dbe->export_symbol)
161 return dbe->export_symbol(dbe, sym, dso);
162
163 return 0;
164}
165
166static struct thread *get_main_thread(struct machine *machine, struct thread *thread)
167{
168 if (thread->pid_ == thread->tid)
169 return thread;
170
171 if (thread->pid_ == -1)
172 return NULL;
173
174 return machine__find_thread(machine, thread->pid_, thread->pid_);
175}
176
177static int db_ids_from_al(struct db_export *dbe, struct addr_location *al,
178 u64 *dso_db_id, u64 *sym_db_id, u64 *offset)
179{
180 int err;
181
182 if (al->map) {
183 struct dso *dso = al->map->dso;
184
185 err = db_export__dso(dbe, dso, al->machine);
186 if (err)
187 return err;
188 *dso_db_id = dso->db_id;
189
190 if (!al->sym) {
191 al->sym = symbol__new(al->addr, 0, 0, "unknown");
192 if (al->sym)
193 symbols__insert(&dso->symbols[al->map->type],
194 al->sym);
195 }
196
197 if (al->sym) {
198 u64 *db_id = symbol__priv(al->sym);
199
200 err = db_export__symbol(dbe, al->sym, dso);
201 if (err)
202 return err;
203 *sym_db_id = *db_id;
204 *offset = al->addr - al->sym->start;
205 }
206 }
207
208 return 0;
209}
210
211int db_export__sample(struct db_export *dbe, union perf_event *event,
212 struct perf_sample *sample, struct perf_evsel *evsel,
213 struct thread *thread, struct addr_location *al)
214{
215 struct export_sample es = {
216 .event = event,
217 .sample = sample,
218 .evsel = evsel,
219 .thread = thread,
220 .al = al,
221 };
222 struct thread *main_thread;
223 struct comm *comm = NULL;
224 int err;
225
226 err = db_export__evsel(dbe, evsel);
227 if (err)
228 return err;
229
230 err = db_export__machine(dbe, al->machine);
231 if (err)
232 return err;
233
234 main_thread = get_main_thread(al->machine, thread);
235 if (main_thread)
236 comm = machine__thread_exec_comm(al->machine, main_thread);
237
238 err = db_export__thread(dbe, thread, al->machine, comm);
239 if (err)
240 return err;
241
242 if (comm) {
243 err = db_export__comm(dbe, comm, main_thread);
244 if (err)
245 return err;
246 es.comm_db_id = comm->db_id;
247 }
248
249 es.db_id = ++dbe->sample_last_db_id;
250
251 err = db_ids_from_al(dbe, al, &es.dso_db_id, &es.sym_db_id, &es.offset);
252 if (err)
253 return err;
254
255 if ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
256 sample_addr_correlates_sym(&evsel->attr)) {
257 struct addr_location addr_al;
258
259 perf_event__preprocess_sample_addr(event, sample, thread, &addr_al);
260 err = db_ids_from_al(dbe, &addr_al, &es.addr_dso_db_id,
261 &es.addr_sym_db_id, &es.addr_offset);
262 if (err)
263 return err;
264 }
265
266 if (dbe->export_sample)
267 return dbe->export_sample(dbe, &es);
268
269 return 0;
270}
diff --git a/tools/perf/util/db-export.h b/tools/perf/util/db-export.h
new file mode 100644
index 000000000000..b3643e8e5750
--- /dev/null
+++ b/tools/perf/util/db-export.h
@@ -0,0 +1,86 @@
1/*
2 * db-export.h: Support for exporting data suitable for import to a database
3 * Copyright (c) 2014, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 */
15
16#ifndef __PERF_DB_EXPORT_H
17#define __PERF_DB_EXPORT_H
18
19#include <linux/types.h>
20
21struct perf_evsel;
22struct machine;
23struct thread;
24struct comm;
25struct dso;
26struct perf_sample;
27struct addr_location;
28
29struct export_sample {
30 union perf_event *event;
31 struct perf_sample *sample;
32 struct perf_evsel *evsel;
33 struct thread *thread;
34 struct addr_location *al;
35 u64 db_id;
36 u64 comm_db_id;
37 u64 dso_db_id;
38 u64 sym_db_id;
39 u64 offset; /* ip offset from symbol start */
40 u64 addr_dso_db_id;
41 u64 addr_sym_db_id;
42 u64 addr_offset; /* addr offset from symbol start */
43};
44
45struct db_export {
46 int (*export_evsel)(struct db_export *dbe, struct perf_evsel *evsel);
47 int (*export_machine)(struct db_export *dbe, struct machine *machine);
48 int (*export_thread)(struct db_export *dbe, struct thread *thread,
49 u64 main_thread_db_id, struct machine *machine);
50 int (*export_comm)(struct db_export *dbe, struct comm *comm);
51 int (*export_comm_thread)(struct db_export *dbe, u64 db_id,
52 struct comm *comm, struct thread *thread);
53 int (*export_dso)(struct db_export *dbe, struct dso *dso,
54 struct machine *machine);
55 int (*export_symbol)(struct db_export *dbe, struct symbol *sym,
56 struct dso *dso);
57 int (*export_sample)(struct db_export *dbe, struct export_sample *es);
58 u64 evsel_last_db_id;
59 u64 machine_last_db_id;
60 u64 thread_last_db_id;
61 u64 comm_last_db_id;
62 u64 comm_thread_last_db_id;
63 u64 dso_last_db_id;
64 u64 symbol_last_db_id;
65 u64 sample_last_db_id;
66};
67
68int db_export__init(struct db_export *dbe);
69void db_export__exit(struct db_export *dbe);
70int db_export__evsel(struct db_export *dbe, struct perf_evsel *evsel);
71int db_export__machine(struct db_export *dbe, struct machine *machine);
72int db_export__thread(struct db_export *dbe, struct thread *thread,
73 struct machine *machine, struct comm *comm);
74int db_export__comm(struct db_export *dbe, struct comm *comm,
75 struct thread *main_thread);
76int db_export__comm_thread(struct db_export *dbe, struct comm *comm,
77 struct thread *thread);
78int db_export__dso(struct db_export *dbe, struct dso *dso,
79 struct machine *machine);
80int db_export__symbol(struct db_export *dbe, struct symbol *sym,
81 struct dso *dso);
82int db_export__sample(struct db_export *dbe, union perf_event *event,
83 struct perf_sample *sample, struct perf_evsel *evsel,
84 struct thread *thread, struct addr_location *al);
85
86#endif
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 3c9b391493f9..a316e4af321f 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -139,6 +139,11 @@ struct dso {
139 struct list_head open_entry; 139 struct list_head open_entry;
140 } data; 140 } data;
141 141
142 union { /* Tool specific area */
143 void *priv;
144 u64 db_id;
145 };
146
142 char name[0]; 147 char name[0];
143}; 148};
144 149
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 163c5604e5d1..d3854c4f52e1 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -54,6 +54,7 @@ struct cgroup_sel;
54 * @is_pos: the position (counting backwards) of the event id (PERF_SAMPLE_ID or 54 * @is_pos: the position (counting backwards) of the event id (PERF_SAMPLE_ID or
55 * PERF_SAMPLE_IDENTIFIER) in a non-sample event i.e. if sample_id_all 55 * PERF_SAMPLE_IDENTIFIER) in a non-sample event i.e. if sample_id_all
56 * is used there is an id sample appended to non-sample events 56 * is used there is an id sample appended to non-sample events
57 * @priv: And what is in its containing unnamed union are tool specific
57 */ 58 */
58struct perf_evsel { 59struct perf_evsel {
59 struct list_head node; 60 struct list_head node;
@@ -73,6 +74,7 @@ struct perf_evsel {
73 union { 74 union {
74 void *priv; 75 void *priv;
75 off_t id_offset; 76 off_t id_offset;
77 u64 db_id;
76 }; 78 };
77 struct cgroup_sel *cgrp; 79 struct cgroup_sel *cgrp;
78 void *handler; 80 void *handler;
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 88ec74e18cbf..e8b7779a0a3f 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -40,6 +40,10 @@ struct machine {
40 u64 kernel_start; 40 u64 kernel_start;
41 symbol_filter_t symbol_filter; 41 symbol_filter_t symbol_filter;
42 pid_t *current_tid; 42 pid_t *current_tid;
43 union { /* Tool specific area */
44 void *priv;
45 u64 db_id;
46 };
43}; 47};
44 48
45static inline 49static inline
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 6ef9fe6ff8da..d34cf5c0d0d9 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -23,6 +23,7 @@ struct thread {
23 bool dead; /* if set thread has exited */ 23 bool dead; /* if set thread has exited */
24 struct list_head comm_list; 24 struct list_head comm_list;
25 int comm_len; 25 int comm_len;
26 u64 db_id;
26 27
27 void *priv; 28 void *priv;
28}; 29};