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