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