xref: /linux/tools/perf/util/db-export.c (revision 0db15b1e84a59e6e1da5fe6e74c35fe52fa29d92)
1*0db15b1eSAdrian Hunter /*
2*0db15b1eSAdrian Hunter  * db-export.c: Support for exporting data suitable for import to a database
3*0db15b1eSAdrian Hunter  * Copyright (c) 2014, Intel Corporation.
4*0db15b1eSAdrian Hunter  *
5*0db15b1eSAdrian Hunter  * This program is free software; you can redistribute it and/or modify it
6*0db15b1eSAdrian Hunter  * under the terms and conditions of the GNU General Public License,
7*0db15b1eSAdrian Hunter  * version 2, as published by the Free Software Foundation.
8*0db15b1eSAdrian Hunter  *
9*0db15b1eSAdrian Hunter  * This program is distributed in the hope it will be useful, but WITHOUT
10*0db15b1eSAdrian Hunter  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11*0db15b1eSAdrian Hunter  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12*0db15b1eSAdrian Hunter  * more details.
13*0db15b1eSAdrian Hunter  *
14*0db15b1eSAdrian Hunter  */
15*0db15b1eSAdrian Hunter 
16*0db15b1eSAdrian Hunter #include <errno.h>
17*0db15b1eSAdrian Hunter 
18*0db15b1eSAdrian Hunter #include "evsel.h"
19*0db15b1eSAdrian Hunter #include "machine.h"
20*0db15b1eSAdrian Hunter #include "thread.h"
21*0db15b1eSAdrian Hunter #include "comm.h"
22*0db15b1eSAdrian Hunter #include "symbol.h"
23*0db15b1eSAdrian Hunter #include "event.h"
24*0db15b1eSAdrian Hunter #include "db-export.h"
25*0db15b1eSAdrian Hunter 
26*0db15b1eSAdrian Hunter int db_export__init(struct db_export *dbe)
27*0db15b1eSAdrian Hunter {
28*0db15b1eSAdrian Hunter 	memset(dbe, 0, sizeof(struct db_export));
29*0db15b1eSAdrian Hunter 	return 0;
30*0db15b1eSAdrian Hunter }
31*0db15b1eSAdrian Hunter 
32*0db15b1eSAdrian Hunter void db_export__exit(struct db_export *dbe __maybe_unused)
33*0db15b1eSAdrian Hunter {
34*0db15b1eSAdrian Hunter }
35*0db15b1eSAdrian Hunter 
36*0db15b1eSAdrian Hunter int db_export__evsel(struct db_export *dbe, struct perf_evsel *evsel)
37*0db15b1eSAdrian Hunter {
38*0db15b1eSAdrian Hunter 	if (evsel->db_id)
39*0db15b1eSAdrian Hunter 		return 0;
40*0db15b1eSAdrian Hunter 
41*0db15b1eSAdrian Hunter 	evsel->db_id = ++dbe->evsel_last_db_id;
42*0db15b1eSAdrian Hunter 
43*0db15b1eSAdrian Hunter 	if (dbe->export_evsel)
44*0db15b1eSAdrian Hunter 		return dbe->export_evsel(dbe, evsel);
45*0db15b1eSAdrian Hunter 
46*0db15b1eSAdrian Hunter 	return 0;
47*0db15b1eSAdrian Hunter }
48*0db15b1eSAdrian Hunter 
49*0db15b1eSAdrian Hunter int db_export__machine(struct db_export *dbe, struct machine *machine)
50*0db15b1eSAdrian Hunter {
51*0db15b1eSAdrian Hunter 	if (machine->db_id)
52*0db15b1eSAdrian Hunter 		return 0;
53*0db15b1eSAdrian Hunter 
54*0db15b1eSAdrian Hunter 	machine->db_id = ++dbe->machine_last_db_id;
55*0db15b1eSAdrian Hunter 
56*0db15b1eSAdrian Hunter 	if (dbe->export_machine)
57*0db15b1eSAdrian Hunter 		return dbe->export_machine(dbe, machine);
58*0db15b1eSAdrian Hunter 
59*0db15b1eSAdrian Hunter 	return 0;
60*0db15b1eSAdrian Hunter }
61*0db15b1eSAdrian Hunter 
62*0db15b1eSAdrian Hunter int db_export__thread(struct db_export *dbe, struct thread *thread,
63*0db15b1eSAdrian Hunter 		      struct machine *machine, struct comm *comm)
64*0db15b1eSAdrian Hunter {
65*0db15b1eSAdrian Hunter 	u64 main_thread_db_id = 0;
66*0db15b1eSAdrian Hunter 	int err;
67*0db15b1eSAdrian Hunter 
68*0db15b1eSAdrian Hunter 	if (thread->db_id)
69*0db15b1eSAdrian Hunter 		return 0;
70*0db15b1eSAdrian Hunter 
71*0db15b1eSAdrian Hunter 	thread->db_id = ++dbe->thread_last_db_id;
72*0db15b1eSAdrian Hunter 
73*0db15b1eSAdrian Hunter 	if (thread->pid_ != -1) {
74*0db15b1eSAdrian Hunter 		struct thread *main_thread;
75*0db15b1eSAdrian Hunter 
76*0db15b1eSAdrian Hunter 		if (thread->pid_ == thread->tid) {
77*0db15b1eSAdrian Hunter 			main_thread = thread;
78*0db15b1eSAdrian Hunter 		} else {
79*0db15b1eSAdrian Hunter 			main_thread = machine__findnew_thread(machine,
80*0db15b1eSAdrian Hunter 							      thread->pid_,
81*0db15b1eSAdrian Hunter 							      thread->pid_);
82*0db15b1eSAdrian Hunter 			if (!main_thread)
83*0db15b1eSAdrian Hunter 				return -ENOMEM;
84*0db15b1eSAdrian Hunter 			err = db_export__thread(dbe, main_thread, machine,
85*0db15b1eSAdrian Hunter 						comm);
86*0db15b1eSAdrian Hunter 			if (err)
87*0db15b1eSAdrian Hunter 				return err;
88*0db15b1eSAdrian Hunter 			if (comm) {
89*0db15b1eSAdrian Hunter 				err = db_export__comm_thread(dbe, comm, thread);
90*0db15b1eSAdrian Hunter 				if (err)
91*0db15b1eSAdrian Hunter 					return err;
92*0db15b1eSAdrian Hunter 			}
93*0db15b1eSAdrian Hunter 		}
94*0db15b1eSAdrian Hunter 		main_thread_db_id = main_thread->db_id;
95*0db15b1eSAdrian Hunter 	}
96*0db15b1eSAdrian Hunter 
97*0db15b1eSAdrian Hunter 	if (dbe->export_thread)
98*0db15b1eSAdrian Hunter 		return dbe->export_thread(dbe, thread, main_thread_db_id,
99*0db15b1eSAdrian Hunter 					  machine);
100*0db15b1eSAdrian Hunter 
101*0db15b1eSAdrian Hunter 	return 0;
102*0db15b1eSAdrian Hunter }
103*0db15b1eSAdrian Hunter 
104*0db15b1eSAdrian Hunter int db_export__comm(struct db_export *dbe, struct comm *comm,
105*0db15b1eSAdrian Hunter 		    struct thread *main_thread)
106*0db15b1eSAdrian Hunter {
107*0db15b1eSAdrian Hunter 	int err;
108*0db15b1eSAdrian Hunter 
109*0db15b1eSAdrian Hunter 	if (comm->db_id)
110*0db15b1eSAdrian Hunter 		return 0;
111*0db15b1eSAdrian Hunter 
112*0db15b1eSAdrian Hunter 	comm->db_id = ++dbe->comm_last_db_id;
113*0db15b1eSAdrian Hunter 
114*0db15b1eSAdrian Hunter 	if (dbe->export_comm) {
115*0db15b1eSAdrian Hunter 		err = dbe->export_comm(dbe, comm);
116*0db15b1eSAdrian Hunter 		if (err)
117*0db15b1eSAdrian Hunter 			return err;
118*0db15b1eSAdrian Hunter 	}
119*0db15b1eSAdrian Hunter 
120*0db15b1eSAdrian Hunter 	return db_export__comm_thread(dbe, comm, main_thread);
121*0db15b1eSAdrian Hunter }
122*0db15b1eSAdrian Hunter 
123*0db15b1eSAdrian Hunter int db_export__comm_thread(struct db_export *dbe, struct comm *comm,
124*0db15b1eSAdrian Hunter 			   struct thread *thread)
125*0db15b1eSAdrian Hunter {
126*0db15b1eSAdrian Hunter 	u64 db_id;
127*0db15b1eSAdrian Hunter 
128*0db15b1eSAdrian Hunter 	db_id = ++dbe->comm_thread_last_db_id;
129*0db15b1eSAdrian Hunter 
130*0db15b1eSAdrian Hunter 	if (dbe->export_comm_thread)
131*0db15b1eSAdrian Hunter 		return dbe->export_comm_thread(dbe, db_id, comm, thread);
132*0db15b1eSAdrian Hunter 
133*0db15b1eSAdrian Hunter 	return 0;
134*0db15b1eSAdrian Hunter }
135*0db15b1eSAdrian Hunter 
136*0db15b1eSAdrian Hunter int db_export__dso(struct db_export *dbe, struct dso *dso,
137*0db15b1eSAdrian Hunter 		   struct machine *machine)
138*0db15b1eSAdrian Hunter {
139*0db15b1eSAdrian Hunter 	if (dso->db_id)
140*0db15b1eSAdrian Hunter 		return 0;
141*0db15b1eSAdrian Hunter 
142*0db15b1eSAdrian Hunter 	dso->db_id = ++dbe->dso_last_db_id;
143*0db15b1eSAdrian Hunter 
144*0db15b1eSAdrian Hunter 	if (dbe->export_dso)
145*0db15b1eSAdrian Hunter 		return dbe->export_dso(dbe, dso, machine);
146*0db15b1eSAdrian Hunter 
147*0db15b1eSAdrian Hunter 	return 0;
148*0db15b1eSAdrian Hunter }
149*0db15b1eSAdrian Hunter 
150*0db15b1eSAdrian Hunter int db_export__symbol(struct db_export *dbe, struct symbol *sym,
151*0db15b1eSAdrian Hunter 		      struct dso *dso)
152*0db15b1eSAdrian Hunter {
153*0db15b1eSAdrian Hunter 	u64 *sym_db_id = symbol__priv(sym);
154*0db15b1eSAdrian Hunter 
155*0db15b1eSAdrian Hunter 	if (*sym_db_id)
156*0db15b1eSAdrian Hunter 		return 0;
157*0db15b1eSAdrian Hunter 
158*0db15b1eSAdrian Hunter 	*sym_db_id = ++dbe->symbol_last_db_id;
159*0db15b1eSAdrian Hunter 
160*0db15b1eSAdrian Hunter 	if (dbe->export_symbol)
161*0db15b1eSAdrian Hunter 		return dbe->export_symbol(dbe, sym, dso);
162*0db15b1eSAdrian Hunter 
163*0db15b1eSAdrian Hunter 	return 0;
164*0db15b1eSAdrian Hunter }
165*0db15b1eSAdrian Hunter 
166*0db15b1eSAdrian Hunter static struct thread *get_main_thread(struct machine *machine, struct thread *thread)
167*0db15b1eSAdrian Hunter {
168*0db15b1eSAdrian Hunter 	if (thread->pid_ == thread->tid)
169*0db15b1eSAdrian Hunter 		return thread;
170*0db15b1eSAdrian Hunter 
171*0db15b1eSAdrian Hunter 	if (thread->pid_ == -1)
172*0db15b1eSAdrian Hunter 		return NULL;
173*0db15b1eSAdrian Hunter 
174*0db15b1eSAdrian Hunter 	return machine__find_thread(machine, thread->pid_, thread->pid_);
175*0db15b1eSAdrian Hunter }
176*0db15b1eSAdrian Hunter 
177*0db15b1eSAdrian Hunter static int db_ids_from_al(struct db_export *dbe, struct addr_location *al,
178*0db15b1eSAdrian Hunter 			  u64 *dso_db_id, u64 *sym_db_id, u64 *offset)
179*0db15b1eSAdrian Hunter {
180*0db15b1eSAdrian Hunter 	int err;
181*0db15b1eSAdrian Hunter 
182*0db15b1eSAdrian Hunter 	if (al->map) {
183*0db15b1eSAdrian Hunter 		struct dso *dso = al->map->dso;
184*0db15b1eSAdrian Hunter 
185*0db15b1eSAdrian Hunter 		err = db_export__dso(dbe, dso, al->machine);
186*0db15b1eSAdrian Hunter 		if (err)
187*0db15b1eSAdrian Hunter 			return err;
188*0db15b1eSAdrian Hunter 		*dso_db_id = dso->db_id;
189*0db15b1eSAdrian Hunter 
190*0db15b1eSAdrian Hunter 		if (!al->sym) {
191*0db15b1eSAdrian Hunter 			al->sym = symbol__new(al->addr, 0, 0, "unknown");
192*0db15b1eSAdrian Hunter 			if (al->sym)
193*0db15b1eSAdrian Hunter 				symbols__insert(&dso->symbols[al->map->type],
194*0db15b1eSAdrian Hunter 						al->sym);
195*0db15b1eSAdrian Hunter 		}
196*0db15b1eSAdrian Hunter 
197*0db15b1eSAdrian Hunter 		if (al->sym) {
198*0db15b1eSAdrian Hunter 			u64 *db_id = symbol__priv(al->sym);
199*0db15b1eSAdrian Hunter 
200*0db15b1eSAdrian Hunter 			err = db_export__symbol(dbe, al->sym, dso);
201*0db15b1eSAdrian Hunter 			if (err)
202*0db15b1eSAdrian Hunter 				return err;
203*0db15b1eSAdrian Hunter 			*sym_db_id = *db_id;
204*0db15b1eSAdrian Hunter 			*offset = al->addr - al->sym->start;
205*0db15b1eSAdrian Hunter 		}
206*0db15b1eSAdrian Hunter 	}
207*0db15b1eSAdrian Hunter 
208*0db15b1eSAdrian Hunter 	return 0;
209*0db15b1eSAdrian Hunter }
210*0db15b1eSAdrian Hunter 
211*0db15b1eSAdrian Hunter int db_export__sample(struct db_export *dbe, union perf_event *event,
212*0db15b1eSAdrian Hunter 		      struct perf_sample *sample, struct perf_evsel *evsel,
213*0db15b1eSAdrian Hunter 		      struct thread *thread, struct addr_location *al)
214*0db15b1eSAdrian Hunter {
215*0db15b1eSAdrian Hunter 	struct export_sample es = {
216*0db15b1eSAdrian Hunter 		.event = event,
217*0db15b1eSAdrian Hunter 		.sample = sample,
218*0db15b1eSAdrian Hunter 		.evsel = evsel,
219*0db15b1eSAdrian Hunter 		.thread = thread,
220*0db15b1eSAdrian Hunter 		.al = al,
221*0db15b1eSAdrian Hunter 	};
222*0db15b1eSAdrian Hunter 	struct thread *main_thread;
223*0db15b1eSAdrian Hunter 	struct comm *comm = NULL;
224*0db15b1eSAdrian Hunter 	int err;
225*0db15b1eSAdrian Hunter 
226*0db15b1eSAdrian Hunter 	err = db_export__evsel(dbe, evsel);
227*0db15b1eSAdrian Hunter 	if (err)
228*0db15b1eSAdrian Hunter 		return err;
229*0db15b1eSAdrian Hunter 
230*0db15b1eSAdrian Hunter 	err = db_export__machine(dbe, al->machine);
231*0db15b1eSAdrian Hunter 	if (err)
232*0db15b1eSAdrian Hunter 		return err;
233*0db15b1eSAdrian Hunter 
234*0db15b1eSAdrian Hunter 	main_thread = get_main_thread(al->machine, thread);
235*0db15b1eSAdrian Hunter 	if (main_thread)
236*0db15b1eSAdrian Hunter 		comm = machine__thread_exec_comm(al->machine, main_thread);
237*0db15b1eSAdrian Hunter 
238*0db15b1eSAdrian Hunter 	err = db_export__thread(dbe, thread, al->machine, comm);
239*0db15b1eSAdrian Hunter 	if (err)
240*0db15b1eSAdrian Hunter 		return err;
241*0db15b1eSAdrian Hunter 
242*0db15b1eSAdrian Hunter 	if (comm) {
243*0db15b1eSAdrian Hunter 		err = db_export__comm(dbe, comm, main_thread);
244*0db15b1eSAdrian Hunter 		if (err)
245*0db15b1eSAdrian Hunter 			return err;
246*0db15b1eSAdrian Hunter 		es.comm_db_id = comm->db_id;
247*0db15b1eSAdrian Hunter 	}
248*0db15b1eSAdrian Hunter 
249*0db15b1eSAdrian Hunter 	es.db_id = ++dbe->sample_last_db_id;
250*0db15b1eSAdrian Hunter 
251*0db15b1eSAdrian Hunter 	err = db_ids_from_al(dbe, al, &es.dso_db_id, &es.sym_db_id, &es.offset);
252*0db15b1eSAdrian Hunter 	if (err)
253*0db15b1eSAdrian Hunter 		return err;
254*0db15b1eSAdrian Hunter 
255*0db15b1eSAdrian Hunter 	if ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
256*0db15b1eSAdrian Hunter 	    sample_addr_correlates_sym(&evsel->attr)) {
257*0db15b1eSAdrian Hunter 		struct addr_location addr_al;
258*0db15b1eSAdrian Hunter 
259*0db15b1eSAdrian Hunter 		perf_event__preprocess_sample_addr(event, sample, thread, &addr_al);
260*0db15b1eSAdrian Hunter 		err = db_ids_from_al(dbe, &addr_al, &es.addr_dso_db_id,
261*0db15b1eSAdrian Hunter 				     &es.addr_sym_db_id, &es.addr_offset);
262*0db15b1eSAdrian Hunter 		if (err)
263*0db15b1eSAdrian Hunter 			return err;
264*0db15b1eSAdrian Hunter 	}
265*0db15b1eSAdrian Hunter 
266*0db15b1eSAdrian Hunter 	if (dbe->export_sample)
267*0db15b1eSAdrian Hunter 		return dbe->export_sample(dbe, &es);
268*0db15b1eSAdrian Hunter 
269*0db15b1eSAdrian Hunter 	return 0;
270*0db15b1eSAdrian Hunter }
271