db-export.c 5.6 KB

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