PageRenderTime 65ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/tools/perf/util/evsel_fprintf.c

http://github.com/torvalds/linux
C | 242 lines | 194 code | 46 blank | 2 comment | 47 complexity | 6bb392c6bf70d1cc20d750a3688a6373 MD5 | raw file
Possible License(s): LGPL-2.0, AGPL-1.0, GPL-2.0
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <inttypes.h>
  3. #include <stdio.h>
  4. #include <stdbool.h>
  5. #include <traceevent/event-parse.h>
  6. #include "evsel.h"
  7. #include "util/evsel_fprintf.h"
  8. #include "util/event.h"
  9. #include "callchain.h"
  10. #include "map.h"
  11. #include "strlist.h"
  12. #include "symbol.h"
  13. #include "srcline.h"
  14. static int comma_fprintf(FILE *fp, bool *first, const char *fmt, ...)
  15. {
  16. va_list args;
  17. int ret = 0;
  18. if (!*first) {
  19. ret += fprintf(fp, ",");
  20. } else {
  21. ret += fprintf(fp, ":");
  22. *first = false;
  23. }
  24. va_start(args, fmt);
  25. ret += vfprintf(fp, fmt, args);
  26. va_end(args);
  27. return ret;
  28. }
  29. static int __print_attr__fprintf(FILE *fp, const char *name, const char *val, void *priv)
  30. {
  31. return comma_fprintf(fp, (bool *)priv, " %s: %s", name, val);
  32. }
  33. int perf_evsel__fprintf(struct evsel *evsel,
  34. struct perf_attr_details *details, FILE *fp)
  35. {
  36. bool first = true;
  37. int printed = 0;
  38. if (details->event_group) {
  39. struct evsel *pos;
  40. if (!perf_evsel__is_group_leader(evsel))
  41. return 0;
  42. if (evsel->core.nr_members > 1)
  43. printed += fprintf(fp, "%s{", evsel->group_name ?: "");
  44. printed += fprintf(fp, "%s", perf_evsel__name(evsel));
  45. for_each_group_member(pos, evsel)
  46. printed += fprintf(fp, ",%s", perf_evsel__name(pos));
  47. if (evsel->core.nr_members > 1)
  48. printed += fprintf(fp, "}");
  49. goto out;
  50. }
  51. printed += fprintf(fp, "%s", perf_evsel__name(evsel));
  52. if (details->verbose) {
  53. printed += perf_event_attr__fprintf(fp, &evsel->core.attr,
  54. __print_attr__fprintf, &first);
  55. } else if (details->freq) {
  56. const char *term = "sample_freq";
  57. if (!evsel->core.attr.freq)
  58. term = "sample_period";
  59. printed += comma_fprintf(fp, &first, " %s=%" PRIu64,
  60. term, (u64)evsel->core.attr.sample_freq);
  61. }
  62. if (details->trace_fields) {
  63. struct tep_format_field *field;
  64. if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) {
  65. printed += comma_fprintf(fp, &first, " (not a tracepoint)");
  66. goto out;
  67. }
  68. field = evsel->tp_format->format.fields;
  69. if (field == NULL) {
  70. printed += comma_fprintf(fp, &first, " (no trace field)");
  71. goto out;
  72. }
  73. printed += comma_fprintf(fp, &first, " trace_fields: %s", field->name);
  74. field = field->next;
  75. while (field) {
  76. printed += comma_fprintf(fp, &first, "%s", field->name);
  77. field = field->next;
  78. }
  79. }
  80. out:
  81. fputc('\n', fp);
  82. return ++printed;
  83. }
  84. int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
  85. unsigned int print_opts, struct callchain_cursor *cursor,
  86. struct strlist *bt_stop_list, FILE *fp)
  87. {
  88. int printed = 0;
  89. struct callchain_cursor_node *node;
  90. int print_ip = print_opts & EVSEL__PRINT_IP;
  91. int print_sym = print_opts & EVSEL__PRINT_SYM;
  92. int print_dso = print_opts & EVSEL__PRINT_DSO;
  93. int print_symoffset = print_opts & EVSEL__PRINT_SYMOFFSET;
  94. int print_oneline = print_opts & EVSEL__PRINT_ONELINE;
  95. int print_srcline = print_opts & EVSEL__PRINT_SRCLINE;
  96. int print_unknown_as_addr = print_opts & EVSEL__PRINT_UNKNOWN_AS_ADDR;
  97. int print_arrow = print_opts & EVSEL__PRINT_CALLCHAIN_ARROW;
  98. int print_skip_ignored = print_opts & EVSEL__PRINT_SKIP_IGNORED;
  99. char s = print_oneline ? ' ' : '\t';
  100. bool first = true;
  101. if (sample->callchain) {
  102. struct addr_location node_al;
  103. callchain_cursor_commit(cursor);
  104. while (1) {
  105. struct symbol *sym;
  106. struct map *map;
  107. u64 addr = 0;
  108. node = callchain_cursor_current(cursor);
  109. if (!node)
  110. break;
  111. sym = node->ms.sym;
  112. map = node->ms.map;
  113. if (sym && sym->ignore && print_skip_ignored)
  114. goto next;
  115. printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " ");
  116. if (print_arrow && !first)
  117. printed += fprintf(fp, " <-");
  118. if (print_ip)
  119. printed += fprintf(fp, "%c%16" PRIx64, s, node->ip);
  120. if (map)
  121. addr = map->map_ip(map, node->ip);
  122. if (print_sym) {
  123. printed += fprintf(fp, " ");
  124. node_al.addr = addr;
  125. node_al.map = map;
  126. if (print_symoffset) {
  127. printed += __symbol__fprintf_symname_offs(sym, &node_al,
  128. print_unknown_as_addr,
  129. true, fp);
  130. } else {
  131. printed += __symbol__fprintf_symname(sym, &node_al,
  132. print_unknown_as_addr, fp);
  133. }
  134. }
  135. if (print_dso && (!sym || !sym->inlined)) {
  136. printed += fprintf(fp, " (");
  137. printed += map__fprintf_dsoname(map, fp);
  138. printed += fprintf(fp, ")");
  139. }
  140. if (print_srcline)
  141. printed += map__fprintf_srcline(map, addr, "\n ", fp);
  142. if (sym && sym->inlined)
  143. printed += fprintf(fp, " (inlined)");
  144. if (!print_oneline)
  145. printed += fprintf(fp, "\n");
  146. /* Add srccode here too? */
  147. if (bt_stop_list && sym &&
  148. strlist__has_entry(bt_stop_list, sym->name)) {
  149. break;
  150. }
  151. first = false;
  152. next:
  153. callchain_cursor_advance(cursor);
  154. }
  155. }
  156. return printed;
  157. }
  158. int sample__fprintf_sym(struct perf_sample *sample, struct addr_location *al,
  159. int left_alignment, unsigned int print_opts,
  160. struct callchain_cursor *cursor, struct strlist *bt_stop_list, FILE *fp)
  161. {
  162. int printed = 0;
  163. int print_ip = print_opts & EVSEL__PRINT_IP;
  164. int print_sym = print_opts & EVSEL__PRINT_SYM;
  165. int print_dso = print_opts & EVSEL__PRINT_DSO;
  166. int print_symoffset = print_opts & EVSEL__PRINT_SYMOFFSET;
  167. int print_srcline = print_opts & EVSEL__PRINT_SRCLINE;
  168. int print_unknown_as_addr = print_opts & EVSEL__PRINT_UNKNOWN_AS_ADDR;
  169. if (cursor != NULL) {
  170. printed += sample__fprintf_callchain(sample, left_alignment, print_opts,
  171. cursor, bt_stop_list, fp);
  172. } else {
  173. printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " ");
  174. if (print_ip)
  175. printed += fprintf(fp, "%16" PRIx64, sample->ip);
  176. if (print_sym) {
  177. printed += fprintf(fp, " ");
  178. if (print_symoffset) {
  179. printed += __symbol__fprintf_symname_offs(al->sym, al,
  180. print_unknown_as_addr,
  181. true, fp);
  182. } else {
  183. printed += __symbol__fprintf_symname(al->sym, al,
  184. print_unknown_as_addr, fp);
  185. }
  186. }
  187. if (print_dso) {
  188. printed += fprintf(fp, " (");
  189. printed += map__fprintf_dsoname(al->map, fp);
  190. printed += fprintf(fp, ")");
  191. }
  192. if (print_srcline)
  193. printed += map__fprintf_srcline(al->map, al->addr, "\n ", fp);
  194. }
  195. return printed;
  196. }