]> git.karo-electronics.de Git - karo-tx-linux.git/blob - tools/perf/util/db-export.c
be128b075a3201320825d5601589283fe03a6f98
[karo-tx-linux.git] / tools / perf / util / db-export.c
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
26 int db_export__init(struct db_export *dbe)
27 {
28         memset(dbe, 0, sizeof(struct db_export));
29         return 0;
30 }
31
32 void db_export__exit(struct db_export *dbe __maybe_unused)
33 {
34 }
35
36 int 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
49 int 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
62 int 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
104 int 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
123 int 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
136 int 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
150 int 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
166 static 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
177 static 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
211 int 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 }