Something went wrong. Try again.
Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259// SPDX-License-Identifier: GPL-2.0#include <inttypes.h>#include <stdio.h>#include <stdbool.h>#include "util/evlist.h"#include "evsel.h"#include "util/evsel_fprintf.h"#include "util/event.h"#include "callchain.h"#include "map.h"#include "strlist.h"#include "symbol.h"#include "srcline.h"#include "dso.h"
#ifdef HAVE_LIBTRACEEVENT#include <event-parse.h>#endif
static int comma_fprintf(FILE *fp, bool *first, const char *fmt, ...){ va_list args; int ret = 0;
if (!*first) { ret += fprintf(fp, ","); } else { ret += fprintf(fp, ":"); *first = false; }
va_start(args, fmt); ret += vfprintf(fp, fmt, args); va_end(args); return ret;}
static int __print_attr__fprintf(FILE *fp, const char *name, const char *val, void *priv){ return comma_fprintf(fp, (bool *)priv, " %s: %s", name, val);}
int evsel__fprintf(struct evsel *evsel, struct perf_attr_details *details, FILE *fp){ bool first = true; int printed = 0;
if (details->event_group) { struct evsel *pos;
if (!evsel__is_group_leader(evsel)) return 0;
if (evsel->core.nr_members > 1) printed += fprintf(fp, "%s{", evsel->group_name ?: "");
printed += fprintf(fp, "%s", evsel__name(evsel)); for_each_group_member(pos, evsel) printed += fprintf(fp, ",%s", evsel__name(pos));
if (evsel->core.nr_members > 1) printed += fprintf(fp, "}"); goto out; }
printed += fprintf(fp, "%s", evsel__name(evsel));
if (details->verbose) { printed += perf_event_attr__fprintf(fp, &evsel->core.attr, __print_attr__fprintf, &first); } else if (details->freq) { const char *term = "sample_freq";
if (!evsel->core.attr.freq) term = "sample_period";
printed += comma_fprintf(fp, &first, " %s=%" PRIu64, term, (u64)evsel->core.attr.sample_freq); }
#ifdef HAVE_LIBTRACEEVENT if (details->trace_fields) { struct tep_format_field *field; const struct tep_event *tp_format;
if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) { printed += comma_fprintf(fp, &first, " (not a tracepoint)"); goto out; }
tp_format = evsel__tp_format(evsel); field = tp_format ? tp_format->format.fields : NULL; if (field == NULL) { printed += comma_fprintf(fp, &first, " (no trace field)"); goto out; }
printed += comma_fprintf(fp, &first, " trace_fields: %s", field->name);
field = field->next; while (field) { printed += comma_fprintf(fp, &first, "%s", field->name); field = field->next; } }#endifout: fputc('\n', fp); return ++printed;}
int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment, unsigned int print_opts, struct callchain_cursor *cursor, struct strlist *bt_stop_list, FILE *fp){ int printed = 0; struct callchain_cursor_node *node; int print_ip = print_opts & EVSEL__PRINT_IP; int print_sym = print_opts & EVSEL__PRINT_SYM; int print_dso = print_opts & EVSEL__PRINT_DSO; int print_dsoff = print_opts & EVSEL__PRINT_DSOFF; int print_symoffset = print_opts & EVSEL__PRINT_SYMOFFSET; int print_oneline = print_opts & EVSEL__PRINT_ONELINE; int print_srcline = print_opts & EVSEL__PRINT_SRCLINE; int print_unknown_as_addr = print_opts & EVSEL__PRINT_UNKNOWN_AS_ADDR; int print_arrow = print_opts & EVSEL__PRINT_CALLCHAIN_ARROW; int print_skip_ignored = print_opts & EVSEL__PRINT_SKIP_IGNORED; char s = print_oneline ? ' ' : '\t'; bool first = true;
if (cursor == NULL) return fprintf(fp, "<not enough memory for the callchain cursor>%s", print_oneline ? "" : "\n");
if (sample->callchain) { callchain_cursor_commit(cursor);
while (1) { struct symbol *sym; struct map *map; u64 addr = 0;
node = callchain_cursor_current(cursor); if (!node) break;
sym = node->ms.sym; map = node->ms.map;
if (sym && symbol__ignore(sym) && print_skip_ignored) goto next;
printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " ");
if (print_arrow && !first) printed += fprintf(fp, " <-");
if (map) addr = map__map_ip(map, node->ip);
if (print_ip) printed += fprintf(fp, "%c%16" PRIx64, s, node->ip);
if (print_sym) { struct addr_location node_al;
addr_location__init(&node_al); printed += fprintf(fp, " "); node_al.addr = addr; node_al.map = map__get(map);
if (sample->deferred_callchain && sample->deferred_cookie == node->ip) { printed += fprintf(fp, "(cookie)"); } else if (print_symoffset) { printed += __symbol__fprintf_symname_offs(sym, &node_al, print_unknown_as_addr, true, fp); } else { printed += __symbol__fprintf_symname(sym, &node_al, print_unknown_as_addr, fp); } addr_location__exit(&node_al); }
if (print_dso && (!sym || !symbol__inlined(sym))) printed += map__fprintf_dsoname_dsoff(map, print_dsoff, addr, fp);
if (print_srcline) { if (node->srcline) printed += fprintf(fp, "\n %s", node->srcline); else printed += map__fprintf_srcline(map, addr, "\n ", fp); }
if (sym && symbol__inlined(sym)) printed += fprintf(fp, " (inlined)");
if (!print_oneline) printed += fprintf(fp, "\n");
/* Add srccode here too? */ if (bt_stop_list && sym && strlist__has_entry(bt_stop_list, sym->name)) { break; }
first = false;next: callchain_cursor_advance(cursor); } }
return printed;}
int sample__fprintf_sym(struct perf_sample *sample, struct addr_location *al, int left_alignment, unsigned int print_opts, struct callchain_cursor *cursor, struct strlist *bt_stop_list, FILE *fp){ int printed = 0; int print_ip = print_opts & EVSEL__PRINT_IP; int print_sym = print_opts & EVSEL__PRINT_SYM; int print_dso = print_opts & EVSEL__PRINT_DSO; int print_dsoff = print_opts & EVSEL__PRINT_DSOFF; int print_symoffset = print_opts & EVSEL__PRINT_SYMOFFSET; int print_srcline = print_opts & EVSEL__PRINT_SRCLINE; int print_unknown_as_addr = print_opts & EVSEL__PRINT_UNKNOWN_AS_ADDR;
if (cursor != NULL) { printed += sample__fprintf_callchain(sample, left_alignment, print_opts, cursor, bt_stop_list, fp); } else { printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " ");
if (print_ip) printed += fprintf(fp, "%16" PRIx64, sample->ip);
if (print_sym) { printed += fprintf(fp, " "); if (print_symoffset) { printed += __symbol__fprintf_symname_offs(al->sym, al, print_unknown_as_addr, true, fp); } else { printed += __symbol__fprintf_symname(al->sym, al, print_unknown_as_addr, fp); } }
if (print_dso) printed += map__fprintf_dsoname_dsoff(al->map, print_dsoff, al->addr, fp);
if (print_srcline) printed += map__fprintf_srcline(al->map, al->addr, "\n ", fp); }
return printed;}