xref: /linux/tools/perf/util/db-export.c (revision 36ec807b627b4c0a0a382f0ae48eac7187d14b2b)
12025cf9eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
20db15b1eSAdrian Hunter /*
30db15b1eSAdrian Hunter  * db-export.c: Support for exporting data suitable for import to a database
40db15b1eSAdrian Hunter  * Copyright (c) 2014, Intel Corporation.
50db15b1eSAdrian Hunter  */
60db15b1eSAdrian Hunter 
70db15b1eSAdrian Hunter #include <errno.h>
8215a0d30SArnaldo Carvalho de Melo #include <stdlib.h>
90db15b1eSAdrian Hunter 
104a3cec84SArnaldo Carvalho de Melo #include "dso.h"
110db15b1eSAdrian Hunter #include "evsel.h"
120db15b1eSAdrian Hunter #include "machine.h"
130db15b1eSAdrian Hunter #include "thread.h"
140db15b1eSAdrian Hunter #include "comm.h"
150db15b1eSAdrian Hunter #include "symbol.h"
161101f69aSArnaldo Carvalho de Melo #include "map.h"
170db15b1eSAdrian Hunter #include "event.h"
1888f50d60SAdrian Hunter #include "thread-stack.h"
190a3eba3aSChris Phlipot #include "callchain.h"
20451db126SChris Phlipot #include "call-path.h"
210db15b1eSAdrian Hunter #include "db-export.h"
227f7c536fSArnaldo Carvalho de Melo #include <linux/zalloc.h>
230db15b1eSAdrian Hunter 
240db15b1eSAdrian Hunter int db_export__init(struct db_export *dbe)
250db15b1eSAdrian Hunter {
260db15b1eSAdrian Hunter 	memset(dbe, 0, sizeof(struct db_export));
270db15b1eSAdrian Hunter 	return 0;
280db15b1eSAdrian Hunter }
290db15b1eSAdrian Hunter 
3088f50d60SAdrian Hunter void db_export__exit(struct db_export *dbe)
310db15b1eSAdrian Hunter {
3288f50d60SAdrian Hunter 	call_return_processor__free(dbe->crp);
3388f50d60SAdrian Hunter 	dbe->crp = NULL;
340db15b1eSAdrian Hunter }
350db15b1eSAdrian Hunter 
3632dcd021SJiri Olsa int db_export__evsel(struct db_export *dbe, struct evsel *evsel)
370db15b1eSAdrian Hunter {
380db15b1eSAdrian Hunter 	if (evsel->db_id)
390db15b1eSAdrian Hunter 		return 0;
400db15b1eSAdrian Hunter 
410db15b1eSAdrian Hunter 	evsel->db_id = ++dbe->evsel_last_db_id;
420db15b1eSAdrian Hunter 
430db15b1eSAdrian Hunter 	if (dbe->export_evsel)
440db15b1eSAdrian Hunter 		return dbe->export_evsel(dbe, evsel);
450db15b1eSAdrian Hunter 
460db15b1eSAdrian Hunter 	return 0;
470db15b1eSAdrian Hunter }
480db15b1eSAdrian Hunter 
490db15b1eSAdrian Hunter int db_export__machine(struct db_export *dbe, struct machine *machine)
500db15b1eSAdrian Hunter {
510db15b1eSAdrian Hunter 	if (machine->db_id)
520db15b1eSAdrian Hunter 		return 0;
530db15b1eSAdrian Hunter 
540db15b1eSAdrian Hunter 	machine->db_id = ++dbe->machine_last_db_id;
550db15b1eSAdrian Hunter 
560db15b1eSAdrian Hunter 	if (dbe->export_machine)
570db15b1eSAdrian Hunter 		return dbe->export_machine(dbe, machine);
580db15b1eSAdrian Hunter 
590db15b1eSAdrian Hunter 	return 0;
600db15b1eSAdrian Hunter }
610db15b1eSAdrian Hunter 
620db15b1eSAdrian Hunter int db_export__thread(struct db_export *dbe, struct thread *thread,
631ed11958SAdrian Hunter 		      struct machine *machine, struct thread *main_thread)
640db15b1eSAdrian Hunter {
650db15b1eSAdrian Hunter 	u64 main_thread_db_id = 0;
660db15b1eSAdrian Hunter 
67ee84a303SIan Rogers 	if (thread__db_id(thread))
680db15b1eSAdrian Hunter 		return 0;
690db15b1eSAdrian Hunter 
70ee84a303SIan Rogers 	thread__set_db_id(thread, ++dbe->thread_last_db_id);
710db15b1eSAdrian Hunter 
721ed11958SAdrian Hunter 	if (main_thread)
73ee84a303SIan Rogers 		main_thread_db_id = thread__db_id(main_thread);
740db15b1eSAdrian Hunter 
750db15b1eSAdrian Hunter 	if (dbe->export_thread)
760db15b1eSAdrian Hunter 		return dbe->export_thread(dbe, thread, main_thread_db_id,
770db15b1eSAdrian Hunter 					  machine);
780db15b1eSAdrian Hunter 
790db15b1eSAdrian Hunter 	return 0;
800db15b1eSAdrian Hunter }
810db15b1eSAdrian Hunter 
8280859c94SAdrian Hunter static int __db_export__comm(struct db_export *dbe, struct comm *comm,
8380859c94SAdrian Hunter 			     struct thread *thread)
8480859c94SAdrian Hunter {
8580859c94SAdrian Hunter 	comm->db_id = ++dbe->comm_last_db_id;
8680859c94SAdrian Hunter 
8780859c94SAdrian Hunter 	if (dbe->export_comm)
8880859c94SAdrian Hunter 		return dbe->export_comm(dbe, comm, thread);
8980859c94SAdrian Hunter 
9080859c94SAdrian Hunter 	return 0;
9180859c94SAdrian Hunter }
9280859c94SAdrian Hunter 
9380859c94SAdrian Hunter int db_export__comm(struct db_export *dbe, struct comm *comm,
9480859c94SAdrian Hunter 		    struct thread *thread)
9580859c94SAdrian Hunter {
9680859c94SAdrian Hunter 	if (comm->db_id)
9780859c94SAdrian Hunter 		return 0;
9880859c94SAdrian Hunter 
9980859c94SAdrian Hunter 	return __db_export__comm(dbe, comm, thread);
10080859c94SAdrian Hunter }
10180859c94SAdrian Hunter 
102208032feSAdrian Hunter /*
103208032feSAdrian Hunter  * Export the "exec" comm. The "exec" comm is the program / application command
104208032feSAdrian Hunter  * name at the time it first executes. It is used to group threads for the same
105208032feSAdrian Hunter  * program. Note that the main thread pid (or thread group id tgid) cannot be
106208032feSAdrian Hunter  * used because it does not change when a new program is exec'ed.
107208032feSAdrian Hunter  */
108208032feSAdrian Hunter int db_export__exec_comm(struct db_export *dbe, struct comm *comm,
1090db15b1eSAdrian Hunter 			 struct thread *main_thread)
1100db15b1eSAdrian Hunter {
1110db15b1eSAdrian Hunter 	int err;
1120db15b1eSAdrian Hunter 
1130db15b1eSAdrian Hunter 	if (comm->db_id)
1140db15b1eSAdrian Hunter 		return 0;
1150db15b1eSAdrian Hunter 
11680859c94SAdrian Hunter 	err = __db_export__comm(dbe, comm, main_thread);
1170db15b1eSAdrian Hunter 	if (err)
1180db15b1eSAdrian Hunter 		return err;
1190db15b1eSAdrian Hunter 
120208032feSAdrian Hunter 	/*
121208032feSAdrian Hunter 	 * Record the main thread for this comm. Note that the main thread can
122208032feSAdrian Hunter 	 * have many "exec" comms because there will be a new one every time it
123208032feSAdrian Hunter 	 * exec's. An "exec" comm however will only ever have 1 main thread.
124208032feSAdrian Hunter 	 * That is different to any other threads for that same program because
125208032feSAdrian Hunter 	 * exec() will effectively kill them, so the relationship between the
126208032feSAdrian Hunter 	 * "exec" comm and non-main threads is 1-to-1. That is why
127208032feSAdrian Hunter 	 * db_export__comm_thread() is called here for the main thread, but it
128208032feSAdrian Hunter 	 * is called for non-main threads when they are exported.
129208032feSAdrian Hunter 	 */
1300db15b1eSAdrian Hunter 	return db_export__comm_thread(dbe, comm, main_thread);
1310db15b1eSAdrian Hunter }
1320db15b1eSAdrian Hunter 
1330db15b1eSAdrian Hunter int db_export__comm_thread(struct db_export *dbe, struct comm *comm,
1340db15b1eSAdrian Hunter 			   struct thread *thread)
1350db15b1eSAdrian Hunter {
1360db15b1eSAdrian Hunter 	u64 db_id;
1370db15b1eSAdrian Hunter 
1380db15b1eSAdrian Hunter 	db_id = ++dbe->comm_thread_last_db_id;
1390db15b1eSAdrian Hunter 
1400db15b1eSAdrian Hunter 	if (dbe->export_comm_thread)
1410db15b1eSAdrian Hunter 		return dbe->export_comm_thread(dbe, db_id, comm, thread);
1420db15b1eSAdrian Hunter 
1430db15b1eSAdrian Hunter 	return 0;
1440db15b1eSAdrian Hunter }
1450db15b1eSAdrian Hunter 
1460db15b1eSAdrian Hunter int db_export__dso(struct db_export *dbe, struct dso *dso,
1470db15b1eSAdrian Hunter 		   struct machine *machine)
1480db15b1eSAdrian Hunter {
149*ee756ef7SIan Rogers 	if (dso__db_id(dso))
1500db15b1eSAdrian Hunter 		return 0;
1510db15b1eSAdrian Hunter 
152*ee756ef7SIan Rogers 	dso__set_db_id(dso, ++dbe->dso_last_db_id);
1530db15b1eSAdrian Hunter 
1540db15b1eSAdrian Hunter 	if (dbe->export_dso)
1550db15b1eSAdrian Hunter 		return dbe->export_dso(dbe, dso, machine);
1560db15b1eSAdrian Hunter 
1570db15b1eSAdrian Hunter 	return 0;
1580db15b1eSAdrian Hunter }
1590db15b1eSAdrian Hunter 
1600db15b1eSAdrian Hunter int db_export__symbol(struct db_export *dbe, struct symbol *sym,
1610db15b1eSAdrian Hunter 		      struct dso *dso)
1620db15b1eSAdrian Hunter {
1630db15b1eSAdrian Hunter 	u64 *sym_db_id = symbol__priv(sym);
1640db15b1eSAdrian Hunter 
1650db15b1eSAdrian Hunter 	if (*sym_db_id)
1660db15b1eSAdrian Hunter 		return 0;
1670db15b1eSAdrian Hunter 
1680db15b1eSAdrian Hunter 	*sym_db_id = ++dbe->symbol_last_db_id;
1690db15b1eSAdrian Hunter 
1700db15b1eSAdrian Hunter 	if (dbe->export_symbol)
1710db15b1eSAdrian Hunter 		return dbe->export_symbol(dbe, sym, dso);
1720db15b1eSAdrian Hunter 
1730db15b1eSAdrian Hunter 	return 0;
1740db15b1eSAdrian Hunter }
1750db15b1eSAdrian Hunter 
1760db15b1eSAdrian Hunter static int db_ids_from_al(struct db_export *dbe, struct addr_location *al,
1770db15b1eSAdrian Hunter 			  u64 *dso_db_id, u64 *sym_db_id, u64 *offset)
1780db15b1eSAdrian Hunter {
1790db15b1eSAdrian Hunter 	int err;
1800db15b1eSAdrian Hunter 
1810db15b1eSAdrian Hunter 	if (al->map) {
18263df0e4bSIan Rogers 		struct dso *dso = map__dso(al->map);
1830db15b1eSAdrian Hunter 
1845ab6d715SIan Rogers 		err = db_export__dso(dbe, dso, maps__machine(al->maps));
1850db15b1eSAdrian Hunter 		if (err)
1860db15b1eSAdrian Hunter 			return err;
187*ee756ef7SIan Rogers 		*dso_db_id = dso__db_id(dso);
1880db15b1eSAdrian Hunter 
1890db15b1eSAdrian Hunter 		if (!al->sym) {
190af30bffaSArnaldo Carvalho de Melo 			al->sym = symbol__new(al->addr, 0, 0, 0, "unknown");
1910db15b1eSAdrian Hunter 			if (al->sym)
1923183f8caSArnaldo Carvalho de Melo 				dso__insert_symbol(dso, al->sym);
1930db15b1eSAdrian Hunter 		}
1940db15b1eSAdrian Hunter 
1950db15b1eSAdrian Hunter 		if (al->sym) {
1960db15b1eSAdrian Hunter 			u64 *db_id = symbol__priv(al->sym);
1970db15b1eSAdrian Hunter 
1980db15b1eSAdrian Hunter 			err = db_export__symbol(dbe, al->sym, dso);
1990db15b1eSAdrian Hunter 			if (err)
2000db15b1eSAdrian Hunter 				return err;
2010db15b1eSAdrian Hunter 			*sym_db_id = *db_id;
2020db15b1eSAdrian Hunter 			*offset = al->addr - al->sym->start;
2030db15b1eSAdrian Hunter 		}
2040db15b1eSAdrian Hunter 	}
2050db15b1eSAdrian Hunter 
2060db15b1eSAdrian Hunter 	return 0;
2070db15b1eSAdrian Hunter }
2080db15b1eSAdrian Hunter 
2090a3eba3aSChris Phlipot static struct call_path *call_path_from_sample(struct db_export *dbe,
2100a3eba3aSChris Phlipot 					       struct machine *machine,
2110a3eba3aSChris Phlipot 					       struct thread *thread,
2120a3eba3aSChris Phlipot 					       struct perf_sample *sample,
21332dcd021SJiri Olsa 					       struct evsel *evsel)
2140a3eba3aSChris Phlipot {
2150a3eba3aSChris Phlipot 	u64 kernel_start = machine__kernel_start(machine);
2160a3eba3aSChris Phlipot 	struct call_path *current = &dbe->cpr->call_path;
2170a3eba3aSChris Phlipot 	enum chain_order saved_order = callchain_param.order;
2188ab12a20SIan Rogers 	struct callchain_cursor *cursor;
2190a3eba3aSChris Phlipot 	int err;
2200a3eba3aSChris Phlipot 
2210a3eba3aSChris Phlipot 	if (!symbol_conf.use_callchain || !sample->callchain)
2220a3eba3aSChris Phlipot 		return NULL;
2230a3eba3aSChris Phlipot 
2240a3eba3aSChris Phlipot 	/*
2250a3eba3aSChris Phlipot 	 * Since the call path tree must be built starting with the root, we
2260a3eba3aSChris Phlipot 	 * must use ORDER_CALL for call chain resolution, in order to process
2270a3eba3aSChris Phlipot 	 * the callchain starting with the root node and ending with the leaf.
2280a3eba3aSChris Phlipot 	 */
2290a3eba3aSChris Phlipot 	callchain_param.order = ORDER_CALLER;
2308ab12a20SIan Rogers 	cursor = get_tls_callchain_cursor();
2318ab12a20SIan Rogers 	err = thread__resolve_callchain(thread, cursor, evsel,
232fe176085SArnaldo Carvalho de Melo 					sample, NULL, NULL, PERF_MAX_STACK_DEPTH);
2330a3eba3aSChris Phlipot 	if (err) {
2340a3eba3aSChris Phlipot 		callchain_param.order = saved_order;
2350a3eba3aSChris Phlipot 		return NULL;
2360a3eba3aSChris Phlipot 	}
2378ab12a20SIan Rogers 	callchain_cursor_commit(cursor);
2380a3eba3aSChris Phlipot 
2390a3eba3aSChris Phlipot 	while (1) {
2400a3eba3aSChris Phlipot 		struct callchain_cursor_node *node;
2410a3eba3aSChris Phlipot 		struct addr_location al;
2420a3eba3aSChris Phlipot 		u64 dso_db_id = 0, sym_db_id = 0, offset = 0;
2430a3eba3aSChris Phlipot 
2440a3eba3aSChris Phlipot 
2458ab12a20SIan Rogers 		node = callchain_cursor_current(cursor);
2460a3eba3aSChris Phlipot 		if (!node)
2470a3eba3aSChris Phlipot 			break;
2480dd5041cSIan Rogers 
2490a3eba3aSChris Phlipot 		/*
2500a3eba3aSChris Phlipot 		 * Handle export of symbol and dso for this node by
2510a3eba3aSChris Phlipot 		 * constructing an addr_location struct and then passing it to
2520a3eba3aSChris Phlipot 		 * db_ids_from_al() to perform the export.
2530a3eba3aSChris Phlipot 		 */
2540dd5041cSIan Rogers 		addr_location__init(&al);
2555f0fef8aSArnaldo Carvalho de Melo 		al.sym = node->ms.sym;
2561e24ce40SBen Gainey 		al.map = map__get(node->ms.map);
2571e24ce40SBen Gainey 		al.maps = maps__get(thread__maps(thread));
2580a3eba3aSChris Phlipot 		al.addr = node->ip;
2590a3eba3aSChris Phlipot 
26083302e79SChris Phlipot 		if (al.map && !al.sym)
26163df0e4bSIan Rogers 			al.sym = dso__find_symbol(map__dso(al.map), al.addr);
26283302e79SChris Phlipot 
2630a3eba3aSChris Phlipot 		db_ids_from_al(dbe, &al, &dso_db_id, &sym_db_id, &offset);
2640a3eba3aSChris Phlipot 
2650a3eba3aSChris Phlipot 		/* add node to the call path tree if it doesn't exist */
2660a3eba3aSChris Phlipot 		current = call_path__findnew(dbe->cpr, current,
2670a3eba3aSChris Phlipot 					     al.sym, node->ip,
2680a3eba3aSChris Phlipot 					     kernel_start);
2690a3eba3aSChris Phlipot 
2708ab12a20SIan Rogers 		callchain_cursor_advance(cursor);
2710dd5041cSIan Rogers 		addr_location__exit(&al);
2720a3eba3aSChris Phlipot 	}
2730a3eba3aSChris Phlipot 
2740a3eba3aSChris Phlipot 	/* Reset the callchain order to its prior value. */
2750a3eba3aSChris Phlipot 	callchain_param.order = saved_order;
2760a3eba3aSChris Phlipot 
2770a3eba3aSChris Phlipot 	if (current == &dbe->cpr->call_path) {
2780a3eba3aSChris Phlipot 		/* Bail because the callchain was empty. */
2790a3eba3aSChris Phlipot 		return NULL;
2800a3eba3aSChris Phlipot 	}
2810a3eba3aSChris Phlipot 
2820a3eba3aSChris Phlipot 	return current;
2830a3eba3aSChris Phlipot }
2840a3eba3aSChris Phlipot 
285f2bff007SAdrian Hunter int db_export__branch_type(struct db_export *dbe, u32 branch_type,
286f2bff007SAdrian Hunter 			   const char *name)
287f2bff007SAdrian Hunter {
288f2bff007SAdrian Hunter 	if (dbe->export_branch_type)
289f2bff007SAdrian Hunter 		return dbe->export_branch_type(dbe, branch_type, name);
290f2bff007SAdrian Hunter 
291f2bff007SAdrian Hunter 	return 0;
292f2bff007SAdrian Hunter }
293f2bff007SAdrian Hunter 
294b3694e6cSAdrian Hunter static int db_export__threads(struct db_export *dbe, struct thread *thread,
295b3694e6cSAdrian Hunter 			      struct thread *main_thread,
296b3694e6cSAdrian Hunter 			      struct machine *machine, struct comm **comm_ptr)
297b3694e6cSAdrian Hunter {
298b3694e6cSAdrian Hunter 	struct comm *comm = NULL;
299b3694e6cSAdrian Hunter 	struct comm *curr_comm;
300b3694e6cSAdrian Hunter 	int err;
301b3694e6cSAdrian Hunter 
302b3694e6cSAdrian Hunter 	if (main_thread) {
303b3694e6cSAdrian Hunter 		/*
304b3694e6cSAdrian Hunter 		 * A thread has a reference to the main thread, so export the
305b3694e6cSAdrian Hunter 		 * main thread first.
306b3694e6cSAdrian Hunter 		 */
307b3694e6cSAdrian Hunter 		err = db_export__thread(dbe, main_thread, machine, main_thread);
308b3694e6cSAdrian Hunter 		if (err)
309b3694e6cSAdrian Hunter 			return err;
310b3694e6cSAdrian Hunter 		/*
311b3694e6cSAdrian Hunter 		 * Export comm before exporting the non-main thread because
312b3694e6cSAdrian Hunter 		 * db_export__comm_thread() can be called further below.
313b3694e6cSAdrian Hunter 		 */
314b3694e6cSAdrian Hunter 		comm = machine__thread_exec_comm(machine, main_thread);
315b3694e6cSAdrian Hunter 		if (comm) {
316b3694e6cSAdrian Hunter 			err = db_export__exec_comm(dbe, comm, main_thread);
317b3694e6cSAdrian Hunter 			if (err)
318b3694e6cSAdrian Hunter 				return err;
319b3694e6cSAdrian Hunter 			*comm_ptr = comm;
320b3694e6cSAdrian Hunter 		}
321b3694e6cSAdrian Hunter 	}
322b3694e6cSAdrian Hunter 
323b3694e6cSAdrian Hunter 	if (thread != main_thread) {
324b3694e6cSAdrian Hunter 		/*
325b3694e6cSAdrian Hunter 		 * For a non-main thread, db_export__comm_thread() must be
326b3694e6cSAdrian Hunter 		 * called only if thread has not previously been exported.
327b3694e6cSAdrian Hunter 		 */
328ee84a303SIan Rogers 		bool export_comm_thread = comm && !thread__db_id(thread);
329b3694e6cSAdrian Hunter 
330b3694e6cSAdrian Hunter 		err = db_export__thread(dbe, thread, machine, main_thread);
331b3694e6cSAdrian Hunter 		if (err)
332b3694e6cSAdrian Hunter 			return err;
333b3694e6cSAdrian Hunter 
334b3694e6cSAdrian Hunter 		if (export_comm_thread) {
335b3694e6cSAdrian Hunter 			err = db_export__comm_thread(dbe, comm, thread);
336b3694e6cSAdrian Hunter 			if (err)
337b3694e6cSAdrian Hunter 				return err;
338b3694e6cSAdrian Hunter 		}
339b3694e6cSAdrian Hunter 	}
340b3694e6cSAdrian Hunter 
341b3694e6cSAdrian Hunter 	curr_comm = thread__comm(thread);
342b3694e6cSAdrian Hunter 	if (curr_comm)
343b3694e6cSAdrian Hunter 		return db_export__comm(dbe, curr_comm, thread);
344b3694e6cSAdrian Hunter 
345b3694e6cSAdrian Hunter 	return 0;
346b3694e6cSAdrian Hunter }
347b3694e6cSAdrian Hunter 
3480db15b1eSAdrian Hunter int db_export__sample(struct db_export *dbe, union perf_event *event,
34932dcd021SJiri Olsa 		      struct perf_sample *sample, struct evsel *evsel,
3503f8e009eSAdrian Hunter 		      struct addr_location *al, struct addr_location *addr_al)
3510db15b1eSAdrian Hunter {
3527327259dSArnaldo Carvalho de Melo 	struct thread *thread = al->thread;
3530db15b1eSAdrian Hunter 	struct export_sample es = {
3540db15b1eSAdrian Hunter 		.event = event,
3550db15b1eSAdrian Hunter 		.sample = sample,
3560db15b1eSAdrian Hunter 		.evsel = evsel,
3570db15b1eSAdrian Hunter 		.al = al,
3580db15b1eSAdrian Hunter 	};
3590db15b1eSAdrian Hunter 	struct thread *main_thread;
3600db15b1eSAdrian Hunter 	struct comm *comm = NULL;
3615ab6d715SIan Rogers 	struct machine *machine;
3620db15b1eSAdrian Hunter 	int err;
3630db15b1eSAdrian Hunter 
3640db15b1eSAdrian Hunter 	err = db_export__evsel(dbe, evsel);
3650db15b1eSAdrian Hunter 	if (err)
3660db15b1eSAdrian Hunter 		return err;
3670db15b1eSAdrian Hunter 
3685ab6d715SIan Rogers 	machine = maps__machine(al->maps);
3695ab6d715SIan Rogers 	err = db_export__machine(dbe, machine);
3700db15b1eSAdrian Hunter 	if (err)
3710db15b1eSAdrian Hunter 		return err;
3720db15b1eSAdrian Hunter 
3735ab6d715SIan Rogers 	main_thread = thread__main_thread(machine, thread);
374b3694e6cSAdrian Hunter 
3755ab6d715SIan Rogers 	err = db_export__threads(dbe, thread, main_thread, machine, &comm);
3760db15b1eSAdrian Hunter 	if (err)
377427cde32SAdrian Hunter 		goto out_put;
378b3694e6cSAdrian Hunter 
379b3694e6cSAdrian Hunter 	if (comm)
3806319790bSAdrian Hunter 		es.comm_db_id = comm->db_id;
3814650c7beSAdrian Hunter 
3820db15b1eSAdrian Hunter 	es.db_id = ++dbe->sample_last_db_id;
3830db15b1eSAdrian Hunter 
3840db15b1eSAdrian Hunter 	err = db_ids_from_al(dbe, al, &es.dso_db_id, &es.sym_db_id, &es.offset);
3850db15b1eSAdrian Hunter 	if (err)
386427cde32SAdrian Hunter 		goto out_put;
3870db15b1eSAdrian Hunter 
3880a3eba3aSChris Phlipot 	if (dbe->cpr) {
3895ab6d715SIan Rogers 		struct call_path *cp = call_path_from_sample(dbe, machine,
3900a3eba3aSChris Phlipot 							     thread, sample,
3910a3eba3aSChris Phlipot 							     evsel);
392568850eaSChris Phlipot 		if (cp) {
3930a3eba3aSChris Phlipot 			db_export__call_path(dbe, cp);
394568850eaSChris Phlipot 			es.call_path_id = cp->db_id;
395568850eaSChris Phlipot 		}
3960a3eba3aSChris Phlipot 	}
3970a3eba3aSChris Phlipot 
3983f8e009eSAdrian Hunter 	if (addr_al) {
3993f8e009eSAdrian Hunter 		err = db_ids_from_al(dbe, addr_al, &es.addr_dso_db_id,
4000db15b1eSAdrian Hunter 				     &es.addr_sym_db_id, &es.addr_offset);
4010db15b1eSAdrian Hunter 		if (err)
402427cde32SAdrian Hunter 			goto out_put;
40388f50d60SAdrian Hunter 		if (dbe->crp) {
40488f50d60SAdrian Hunter 			err = thread_stack__process(thread, comm, sample, al,
4053f8e009eSAdrian Hunter 						    addr_al, es.db_id,
40688f50d60SAdrian Hunter 						    dbe->crp);
40788f50d60SAdrian Hunter 			if (err)
408427cde32SAdrian Hunter 				goto out_put;
40988f50d60SAdrian Hunter 		}
4100db15b1eSAdrian Hunter 	}
4110db15b1eSAdrian Hunter 
4120db15b1eSAdrian Hunter 	if (dbe->export_sample)
413427cde32SAdrian Hunter 		err = dbe->export_sample(dbe, &es);
4140db15b1eSAdrian Hunter 
415427cde32SAdrian Hunter out_put:
416427cde32SAdrian Hunter 	thread__put(main_thread);
417427cde32SAdrian Hunter 	return err;
4180db15b1eSAdrian Hunter }
419f2bff007SAdrian Hunter 
420f2bff007SAdrian Hunter static struct {
421f2bff007SAdrian Hunter 	u32 branch_type;
422f2bff007SAdrian Hunter 	const char *name;
423f2bff007SAdrian Hunter } branch_types[] = {
424f2bff007SAdrian Hunter 	{0, "no branch"},
425f2bff007SAdrian Hunter 	{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL, "call"},
426f2bff007SAdrian Hunter 	{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN, "return"},
427f2bff007SAdrian Hunter 	{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CONDITIONAL, "conditional jump"},
428f2bff007SAdrian Hunter 	{PERF_IP_FLAG_BRANCH, "unconditional jump"},
429f2bff007SAdrian Hunter 	{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_INTERRUPT,
430f2bff007SAdrian Hunter 	 "software interrupt"},
431f2bff007SAdrian Hunter 	{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_INTERRUPT,
432f2bff007SAdrian Hunter 	 "return from interrupt"},
433f2bff007SAdrian Hunter 	{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_SYSCALLRET,
434f2bff007SAdrian Hunter 	 "system call"},
435f2bff007SAdrian Hunter 	{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_SYSCALLRET,
436f2bff007SAdrian Hunter 	 "return from system call"},
437f2bff007SAdrian Hunter 	{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_ASYNC, "asynchronous branch"},
438f2bff007SAdrian Hunter 	{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_ASYNC |
439f2bff007SAdrian Hunter 	 PERF_IP_FLAG_INTERRUPT, "hardware interrupt"},
440f2bff007SAdrian Hunter 	{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TX_ABORT, "transaction abort"},
441f2bff007SAdrian Hunter 	{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_BEGIN, "trace begin"},
442f2bff007SAdrian Hunter 	{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_END, "trace end"},
443c025d46cSAdrian Hunter 	{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_VMENTRY, "vm entry"},
444c025d46cSAdrian Hunter 	{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_VMEXIT, "vm exit"},
445f2bff007SAdrian Hunter 	{0, NULL}
446f2bff007SAdrian Hunter };
447f2bff007SAdrian Hunter 
448f2bff007SAdrian Hunter int db_export__branch_types(struct db_export *dbe)
449f2bff007SAdrian Hunter {
450f2bff007SAdrian Hunter 	int i, err = 0;
451f2bff007SAdrian Hunter 
452f2bff007SAdrian Hunter 	for (i = 0; branch_types[i].name ; i++) {
453f2bff007SAdrian Hunter 		err = db_export__branch_type(dbe, branch_types[i].branch_type,
454f2bff007SAdrian Hunter 					     branch_types[i].name);
455f2bff007SAdrian Hunter 		if (err)
456f2bff007SAdrian Hunter 			break;
457f2bff007SAdrian Hunter 	}
458ff645dafSAdrian Hunter 
459ff645dafSAdrian Hunter 	/* Add trace begin / end variants */
460ff645dafSAdrian Hunter 	for (i = 0; branch_types[i].name ; i++) {
461ff645dafSAdrian Hunter 		const char *name = branch_types[i].name;
462ff645dafSAdrian Hunter 		u32 type = branch_types[i].branch_type;
463ff645dafSAdrian Hunter 		char buf[64];
464ff645dafSAdrian Hunter 
465ff645dafSAdrian Hunter 		if (type == PERF_IP_FLAG_BRANCH ||
466ff645dafSAdrian Hunter 		    (type & (PERF_IP_FLAG_TRACE_BEGIN | PERF_IP_FLAG_TRACE_END)))
467ff645dafSAdrian Hunter 			continue;
468ff645dafSAdrian Hunter 
469ff645dafSAdrian Hunter 		snprintf(buf, sizeof(buf), "trace begin / %s", name);
470ff645dafSAdrian Hunter 		err = db_export__branch_type(dbe, type | PERF_IP_FLAG_TRACE_BEGIN, buf);
471ff645dafSAdrian Hunter 		if (err)
472ff645dafSAdrian Hunter 			break;
473ff645dafSAdrian Hunter 
474ff645dafSAdrian Hunter 		snprintf(buf, sizeof(buf), "%s / trace end", name);
475ff645dafSAdrian Hunter 		err = db_export__branch_type(dbe, type | PERF_IP_FLAG_TRACE_END, buf);
476ff645dafSAdrian Hunter 		if (err)
477ff645dafSAdrian Hunter 			break;
478ff645dafSAdrian Hunter 	}
479ff645dafSAdrian Hunter 
480f2bff007SAdrian Hunter 	return err;
481f2bff007SAdrian Hunter }
48288f50d60SAdrian Hunter 
48388f50d60SAdrian Hunter int db_export__call_path(struct db_export *dbe, struct call_path *cp)
48488f50d60SAdrian Hunter {
48588f50d60SAdrian Hunter 	int err;
48688f50d60SAdrian Hunter 
48788f50d60SAdrian Hunter 	if (cp->db_id)
48888f50d60SAdrian Hunter 		return 0;
48988f50d60SAdrian Hunter 
49088f50d60SAdrian Hunter 	if (cp->parent) {
49188f50d60SAdrian Hunter 		err = db_export__call_path(dbe, cp->parent);
49288f50d60SAdrian Hunter 		if (err)
49388f50d60SAdrian Hunter 			return err;
49488f50d60SAdrian Hunter 	}
49588f50d60SAdrian Hunter 
49688f50d60SAdrian Hunter 	cp->db_id = ++dbe->call_path_last_db_id;
49788f50d60SAdrian Hunter 
49888f50d60SAdrian Hunter 	if (dbe->export_call_path)
49988f50d60SAdrian Hunter 		return dbe->export_call_path(dbe, cp);
50088f50d60SAdrian Hunter 
50188f50d60SAdrian Hunter 	return 0;
50288f50d60SAdrian Hunter }
50388f50d60SAdrian Hunter 
504f435887eSAdrian Hunter int db_export__call_return(struct db_export *dbe, struct call_return *cr,
505f435887eSAdrian Hunter 			   u64 *parent_db_id)
50688f50d60SAdrian Hunter {
50788f50d60SAdrian Hunter 	int err;
50888f50d60SAdrian Hunter 
50988f50d60SAdrian Hunter 	err = db_export__call_path(dbe, cr->cp);
51088f50d60SAdrian Hunter 	if (err)
51188f50d60SAdrian Hunter 		return err;
51288f50d60SAdrian Hunter 
513f435887eSAdrian Hunter 	if (!cr->db_id)
51488f50d60SAdrian Hunter 		cr->db_id = ++dbe->call_return_last_db_id;
51588f50d60SAdrian Hunter 
516f435887eSAdrian Hunter 	if (parent_db_id) {
517f435887eSAdrian Hunter 		if (!*parent_db_id)
518f435887eSAdrian Hunter 			*parent_db_id = ++dbe->call_return_last_db_id;
519f435887eSAdrian Hunter 		cr->parent_db_id = *parent_db_id;
520f435887eSAdrian Hunter 	}
521f435887eSAdrian Hunter 
52288f50d60SAdrian Hunter 	if (dbe->export_call_return)
52388f50d60SAdrian Hunter 		return dbe->export_call_return(dbe, cr);
52488f50d60SAdrian Hunter 
52588f50d60SAdrian Hunter 	return 0;
52688f50d60SAdrian Hunter }
527abde8722SAdrian Hunter 
528abde8722SAdrian Hunter static int db_export__pid_tid(struct db_export *dbe, struct machine *machine,
529abde8722SAdrian Hunter 			      pid_t pid, pid_t tid, u64 *db_id,
530abde8722SAdrian Hunter 			      struct comm **comm_ptr, bool *is_idle)
531abde8722SAdrian Hunter {
532abde8722SAdrian Hunter 	struct thread *thread = machine__find_thread(machine, pid, tid);
533abde8722SAdrian Hunter 	struct thread *main_thread;
534abde8722SAdrian Hunter 	int err = 0;
535abde8722SAdrian Hunter 
536ee84a303SIan Rogers 	if (!thread || !thread__comm_set(thread))
537abde8722SAdrian Hunter 		goto out_put;
538abde8722SAdrian Hunter 
539ee84a303SIan Rogers 	*is_idle = !thread__pid(thread) && !thread__tid(thread);
540abde8722SAdrian Hunter 
541abde8722SAdrian Hunter 	main_thread = thread__main_thread(machine, thread);
542abde8722SAdrian Hunter 
543abde8722SAdrian Hunter 	err = db_export__threads(dbe, thread, main_thread, machine, comm_ptr);
544abde8722SAdrian Hunter 
545ee84a303SIan Rogers 	*db_id = thread__db_id(thread);
546abde8722SAdrian Hunter 
547abde8722SAdrian Hunter 	thread__put(main_thread);
548abde8722SAdrian Hunter out_put:
549abde8722SAdrian Hunter 	thread__put(thread);
550abde8722SAdrian Hunter 
551abde8722SAdrian Hunter 	return err;
552abde8722SAdrian Hunter }
553abde8722SAdrian Hunter 
554abde8722SAdrian Hunter int db_export__switch(struct db_export *dbe, union perf_event *event,
555abde8722SAdrian Hunter 		      struct perf_sample *sample, struct machine *machine)
556abde8722SAdrian Hunter {
557abde8722SAdrian Hunter 	bool out = event->header.misc & PERF_RECORD_MISC_SWITCH_OUT;
558abde8722SAdrian Hunter 	bool out_preempt = out &&
559abde8722SAdrian Hunter 		(event->header.misc & PERF_RECORD_MISC_SWITCH_OUT_PREEMPT);
560abde8722SAdrian Hunter 	int flags = out | (out_preempt << 1);
561abde8722SAdrian Hunter 	bool is_idle_a = false, is_idle_b = false;
562abde8722SAdrian Hunter 	u64 th_a_id = 0, th_b_id = 0;
563abde8722SAdrian Hunter 	u64 comm_out_id, comm_in_id;
564abde8722SAdrian Hunter 	struct comm *comm_a = NULL;
565abde8722SAdrian Hunter 	struct comm *comm_b = NULL;
566abde8722SAdrian Hunter 	u64 th_out_id, th_in_id;
567abde8722SAdrian Hunter 	u64 db_id;
568abde8722SAdrian Hunter 	int err;
569abde8722SAdrian Hunter 
570abde8722SAdrian Hunter 	err = db_export__machine(dbe, machine);
571abde8722SAdrian Hunter 	if (err)
572abde8722SAdrian Hunter 		return err;
573abde8722SAdrian Hunter 
574abde8722SAdrian Hunter 	err = db_export__pid_tid(dbe, machine, sample->pid, sample->tid,
575abde8722SAdrian Hunter 				 &th_a_id, &comm_a, &is_idle_a);
576abde8722SAdrian Hunter 	if (err)
577abde8722SAdrian Hunter 		return err;
578abde8722SAdrian Hunter 
579abde8722SAdrian Hunter 	if (event->header.type == PERF_RECORD_SWITCH_CPU_WIDE) {
580abde8722SAdrian Hunter 		pid_t pid = event->context_switch.next_prev_pid;
581abde8722SAdrian Hunter 		pid_t tid = event->context_switch.next_prev_tid;
582abde8722SAdrian Hunter 
583abde8722SAdrian Hunter 		err = db_export__pid_tid(dbe, machine, pid, tid, &th_b_id,
584abde8722SAdrian Hunter 					 &comm_b, &is_idle_b);
585abde8722SAdrian Hunter 		if (err)
586abde8722SAdrian Hunter 			return err;
587abde8722SAdrian Hunter 	}
588abde8722SAdrian Hunter 
589abde8722SAdrian Hunter 	/*
590abde8722SAdrian Hunter 	 * Do not export if both threads are unknown (i.e. not being traced),
591abde8722SAdrian Hunter 	 * or one is unknown and the other is the idle task.
592abde8722SAdrian Hunter 	 */
593abde8722SAdrian Hunter 	if ((!th_a_id || is_idle_a) && (!th_b_id || is_idle_b))
594abde8722SAdrian Hunter 		return 0;
595abde8722SAdrian Hunter 
596abde8722SAdrian Hunter 	db_id = ++dbe->context_switch_last_db_id;
597abde8722SAdrian Hunter 
598abde8722SAdrian Hunter 	if (out) {
599abde8722SAdrian Hunter 		th_out_id   = th_a_id;
600abde8722SAdrian Hunter 		th_in_id    = th_b_id;
601abde8722SAdrian Hunter 		comm_out_id = comm_a ? comm_a->db_id : 0;
602abde8722SAdrian Hunter 		comm_in_id  = comm_b ? comm_b->db_id : 0;
603abde8722SAdrian Hunter 	} else {
604abde8722SAdrian Hunter 		th_out_id   = th_b_id;
605abde8722SAdrian Hunter 		th_in_id    = th_a_id;
606abde8722SAdrian Hunter 		comm_out_id = comm_b ? comm_b->db_id : 0;
607abde8722SAdrian Hunter 		comm_in_id  = comm_a ? comm_a->db_id : 0;
608abde8722SAdrian Hunter 	}
609abde8722SAdrian Hunter 
610abde8722SAdrian Hunter 	if (dbe->export_context_switch)
611abde8722SAdrian Hunter 		return dbe->export_context_switch(dbe, db_id, machine, sample,
612abde8722SAdrian Hunter 						  th_out_id, comm_out_id,
613abde8722SAdrian Hunter 						  th_in_id, comm_in_id, flags);
614abde8722SAdrian Hunter 	return 0;
615abde8722SAdrian Hunter }
616