0001
0002 #include <inttypes.h>
0003 #include <stdio.h>
0004 #include <stdbool.h>
0005 #include <traceevent/event-parse.h>
0006 #include "evsel.h"
0007 #include "util/evsel_fprintf.h"
0008 #include "util/event.h"
0009 #include "callchain.h"
0010 #include "map.h"
0011 #include "strlist.h"
0012 #include "symbol.h"
0013 #include "srcline.h"
0014 #include "dso.h"
0015
0016 static int comma_fprintf(FILE *fp, bool *first, const char *fmt, ...)
0017 {
0018 va_list args;
0019 int ret = 0;
0020
0021 if (!*first) {
0022 ret += fprintf(fp, ",");
0023 } else {
0024 ret += fprintf(fp, ":");
0025 *first = false;
0026 }
0027
0028 va_start(args, fmt);
0029 ret += vfprintf(fp, fmt, args);
0030 va_end(args);
0031 return ret;
0032 }
0033
0034 static int __print_attr__fprintf(FILE *fp, const char *name, const char *val, void *priv)
0035 {
0036 return comma_fprintf(fp, (bool *)priv, " %s: %s", name, val);
0037 }
0038
0039 int evsel__fprintf(struct evsel *evsel, struct perf_attr_details *details, FILE *fp)
0040 {
0041 bool first = true;
0042 int printed = 0;
0043
0044 if (details->event_group) {
0045 struct evsel *pos;
0046
0047 if (!evsel__is_group_leader(evsel))
0048 return 0;
0049
0050 if (evsel->core.nr_members > 1)
0051 printed += fprintf(fp, "%s{", evsel->group_name ?: "");
0052
0053 printed += fprintf(fp, "%s", evsel__name(evsel));
0054 for_each_group_member(pos, evsel)
0055 printed += fprintf(fp, ",%s", evsel__name(pos));
0056
0057 if (evsel->core.nr_members > 1)
0058 printed += fprintf(fp, "}");
0059 goto out;
0060 }
0061
0062 printed += fprintf(fp, "%s", evsel__name(evsel));
0063
0064 if (details->verbose) {
0065 printed += perf_event_attr__fprintf(fp, &evsel->core.attr,
0066 __print_attr__fprintf, &first);
0067 } else if (details->freq) {
0068 const char *term = "sample_freq";
0069
0070 if (!evsel->core.attr.freq)
0071 term = "sample_period";
0072
0073 printed += comma_fprintf(fp, &first, " %s=%" PRIu64,
0074 term, (u64)evsel->core.attr.sample_freq);
0075 }
0076
0077 if (details->trace_fields) {
0078 struct tep_format_field *field;
0079
0080 if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) {
0081 printed += comma_fprintf(fp, &first, " (not a tracepoint)");
0082 goto out;
0083 }
0084
0085 field = evsel->tp_format->format.fields;
0086 if (field == NULL) {
0087 printed += comma_fprintf(fp, &first, " (no trace field)");
0088 goto out;
0089 }
0090
0091 printed += comma_fprintf(fp, &first, " trace_fields: %s", field->name);
0092
0093 field = field->next;
0094 while (field) {
0095 printed += comma_fprintf(fp, &first, "%s", field->name);
0096 field = field->next;
0097 }
0098 }
0099 out:
0100 fputc('\n', fp);
0101 return ++printed;
0102 }
0103
0104 #ifndef PYTHON_PERF
0105 int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
0106 unsigned int print_opts, struct callchain_cursor *cursor,
0107 struct strlist *bt_stop_list, FILE *fp)
0108 {
0109 int printed = 0;
0110 struct callchain_cursor_node *node;
0111 int print_ip = print_opts & EVSEL__PRINT_IP;
0112 int print_sym = print_opts & EVSEL__PRINT_SYM;
0113 int print_dso = print_opts & EVSEL__PRINT_DSO;
0114 int print_symoffset = print_opts & EVSEL__PRINT_SYMOFFSET;
0115 int print_oneline = print_opts & EVSEL__PRINT_ONELINE;
0116 int print_srcline = print_opts & EVSEL__PRINT_SRCLINE;
0117 int print_unknown_as_addr = print_opts & EVSEL__PRINT_UNKNOWN_AS_ADDR;
0118 int print_arrow = print_opts & EVSEL__PRINT_CALLCHAIN_ARROW;
0119 int print_skip_ignored = print_opts & EVSEL__PRINT_SKIP_IGNORED;
0120 char s = print_oneline ? ' ' : '\t';
0121 bool first = true;
0122
0123 if (sample->callchain) {
0124 struct addr_location node_al;
0125
0126 callchain_cursor_commit(cursor);
0127
0128 while (1) {
0129 struct symbol *sym;
0130 struct map *map;
0131 u64 addr = 0;
0132
0133 node = callchain_cursor_current(cursor);
0134 if (!node)
0135 break;
0136
0137 sym = node->ms.sym;
0138 map = node->ms.map;
0139
0140 if (sym && sym->ignore && print_skip_ignored)
0141 goto next;
0142
0143 printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " ");
0144
0145 if (print_arrow && !first)
0146 printed += fprintf(fp, " <-");
0147
0148 if (map)
0149 addr = map->map_ip(map, node->ip);
0150
0151 if (print_ip) {
0152
0153 if (map && !map->dso->kernel)
0154 printed += fprintf(fp, "%c%16" PRIx64, s, addr);
0155 else
0156 printed += fprintf(fp, "%c%16" PRIx64, s, node->ip);
0157 }
0158
0159 if (print_sym) {
0160 printed += fprintf(fp, " ");
0161 node_al.addr = addr;
0162 node_al.map = map;
0163
0164 if (print_symoffset) {
0165 printed += __symbol__fprintf_symname_offs(sym, &node_al,
0166 print_unknown_as_addr,
0167 true, fp);
0168 } else {
0169 printed += __symbol__fprintf_symname(sym, &node_al,
0170 print_unknown_as_addr, fp);
0171 }
0172 }
0173
0174 if (print_dso && (!sym || !sym->inlined)) {
0175 printed += fprintf(fp, " (");
0176 printed += map__fprintf_dsoname(map, fp);
0177 printed += fprintf(fp, ")");
0178 }
0179
0180 if (print_srcline)
0181 printed += map__fprintf_srcline(map, addr, "\n ", fp);
0182
0183 if (sym && sym->inlined)
0184 printed += fprintf(fp, " (inlined)");
0185
0186 if (!print_oneline)
0187 printed += fprintf(fp, "\n");
0188
0189
0190 if (bt_stop_list && sym &&
0191 strlist__has_entry(bt_stop_list, sym->name)) {
0192 break;
0193 }
0194
0195 first = false;
0196 next:
0197 callchain_cursor_advance(cursor);
0198 }
0199 }
0200
0201 return printed;
0202 }
0203
0204 int sample__fprintf_sym(struct perf_sample *sample, struct addr_location *al,
0205 int left_alignment, unsigned int print_opts,
0206 struct callchain_cursor *cursor, struct strlist *bt_stop_list, FILE *fp)
0207 {
0208 int printed = 0;
0209 int print_ip = print_opts & EVSEL__PRINT_IP;
0210 int print_sym = print_opts & EVSEL__PRINT_SYM;
0211 int print_dso = print_opts & EVSEL__PRINT_DSO;
0212 int print_symoffset = print_opts & EVSEL__PRINT_SYMOFFSET;
0213 int print_srcline = print_opts & EVSEL__PRINT_SRCLINE;
0214 int print_unknown_as_addr = print_opts & EVSEL__PRINT_UNKNOWN_AS_ADDR;
0215
0216 if (cursor != NULL) {
0217 printed += sample__fprintf_callchain(sample, left_alignment, print_opts,
0218 cursor, bt_stop_list, fp);
0219 } else {
0220 printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " ");
0221
0222 if (print_ip)
0223 printed += fprintf(fp, "%16" PRIx64, sample->ip);
0224
0225 if (print_sym) {
0226 printed += fprintf(fp, " ");
0227 if (print_symoffset) {
0228 printed += __symbol__fprintf_symname_offs(al->sym, al,
0229 print_unknown_as_addr,
0230 true, fp);
0231 } else {
0232 printed += __symbol__fprintf_symname(al->sym, al,
0233 print_unknown_as_addr, fp);
0234 }
0235 }
0236
0237 if (print_dso) {
0238 printed += fprintf(fp, " (");
0239 printed += map__fprintf_dsoname(al->map, fp);
0240 printed += fprintf(fp, ")");
0241 }
0242
0243 if (print_srcline)
0244 printed += map__fprintf_srcline(al->map, al->addr, "\n ", fp);
0245 }
0246
0247 return printed;
0248 }
0249 #endif