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
db_export__init(struct db_export * dbe)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
db_export__exit(struct db_export * dbe)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
db_export__evsel(struct db_export * dbe,struct evsel * evsel)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
db_export__machine(struct db_export * dbe,struct machine * machine)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
db_export__thread(struct db_export * dbe,struct thread * thread,struct machine * machine,struct thread * main_thread)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
__db_export__comm(struct db_export * dbe,struct comm * comm,struct thread * thread)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
db_export__comm(struct db_export * dbe,struct comm * comm,struct thread * thread)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 */
db_export__exec_comm(struct db_export * dbe,struct comm * comm,struct thread * main_thread)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
db_export__comm_thread(struct db_export * dbe,struct comm * comm,struct thread * thread)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
db_export__dso(struct db_export * dbe,struct dso * dso,struct machine * machine)1460db15b1eSAdrian Hunter int db_export__dso(struct db_export *dbe, struct dso *dso,
1470db15b1eSAdrian Hunter struct machine *machine)
1480db15b1eSAdrian Hunter {
1490db15b1eSAdrian Hunter if (dso->db_id)
1500db15b1eSAdrian Hunter return 0;
1510db15b1eSAdrian Hunter
1520db15b1eSAdrian Hunter dso->db_id = ++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
db_export__symbol(struct db_export * dbe,struct symbol * sym,struct dso * dso)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
db_ids_from_al(struct db_export * dbe,struct addr_location * al,u64 * dso_db_id,u64 * sym_db_id,u64 * offset)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;
1870db15b1eSAdrian Hunter *dso_db_id = dso->db_id;
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
call_path_from_sample(struct db_export * dbe,struct machine * machine,struct thread * thread,struct perf_sample * sample,struct evsel * evsel)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;
256*4e0d6791SBen Gainey al.map = map__get(node->ms.map);
257*4e0d6791SBen 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
db_export__branch_type(struct db_export * dbe,u32 branch_type,const char * name)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
db_export__threads(struct db_export * dbe,struct thread * thread,struct thread * main_thread,struct machine * machine,struct comm ** comm_ptr)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
db_export__sample(struct db_export * dbe,union perf_event * event,struct perf_sample * sample,struct evsel * evsel,struct addr_location * al,struct addr_location * addr_al)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
db_export__branch_types(struct db_export * dbe)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
db_export__call_path(struct db_export * dbe,struct call_path * cp)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
db_export__call_return(struct db_export * dbe,struct call_return * cr,u64 * parent_db_id)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
db_export__pid_tid(struct db_export * dbe,struct machine * machine,pid_t pid,pid_t tid,u64 * db_id,struct comm ** comm_ptr,bool * is_idle)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
db_export__switch(struct db_export * dbe,union perf_event * event,struct perf_sample * sample,struct machine * machine)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