static int perf_session__list_build_ids(bool force, bool with_hits) { struct perf_session *session; symbol__elf_init(); /* * See if this is an ELF file first: */ if (filename__fprintf_build_id(input_name, stdout)) goto out; session = perf_session__new(input_name, O_RDONLY, force, false, &build_id__mark_dso_hit_ops); if (session == NULL) return -1; /* * in pipe-mode, the only way to get the buildids is to parse * the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID */ if (with_hits || session->fd_pipe) perf_session__process_events(session, &build_id__mark_dso_hit_ops); perf_session__fprintf_dsos_buildid(session, stdout, dso__skip_buildid, with_hits); perf_session__delete(session); out: return 0; }
static int __cmd_diff(void) { int ret, i; struct perf_session *session[2]; session[0] = perf_session__new(input_old, O_RDONLY, force, false); session[1] = perf_session__new(input_new, O_RDONLY, force, false); if (session[0] == NULL || session[1] == NULL) return -ENOMEM; for (i = 0; i < 2; ++i) { ret = perf_session__process_events(session[i], &event_ops); if (ret) goto out_delete; } hists__output_resort(&session[1]->hists); if (show_displacement) hists__set_positions(&session[0]->hists); hists__match(&session[0]->hists, &session[1]->hists); hists__fprintf(&session[1]->hists, &session[0]->hists, show_displacement, stdout); out_delete: for (i = 0; i < 2; ++i) perf_session__delete(session[i]); return ret; }
static int __cmd_annotate(void) { int ret; struct perf_session *session; session = perf_session__new(input_name, O_RDONLY, force); if (session == NULL) return -ENOMEM; ret = perf_session__process_events(session, &event_ops); if (ret) goto out_delete; if (dump_trace) { event__print_totals(); goto out_delete; } if (verbose > 3) perf_session__fprintf(session, stdout); if (verbose > 2) dsos__fprintf(stdout); perf_session__collapse_resort(session); perf_session__output_resort(session, session->event_total[0]); perf_session__find_annotations(session); out_delete: perf_session__delete(session); return ret; }
static int __cmd_diff(void) { int ret, i; struct perf_session *session[2]; session[0] = perf_session__new(input_old, O_RDONLY, force); session[1] = perf_session__new(input_new, O_RDONLY, force); if (session[0] == NULL || session[1] == NULL) return -ENOMEM; for (i = 0; i < 2; ++i) { ret = perf_session__process_events(session[i], &event_ops); if (ret) goto out_delete; perf_session__output_resort(session[i], session[i]->events_stats.total); } perf_session__match_hists(session[0], session[1]); perf_session__fprintf_hists(session[1], session[0], show_displacement, stdout); out_delete: for (i = 0; i < 2; ++i) perf_session__delete(session[i]); return ret; }
static int __cmd_timechart(void) { struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0); int ret; if (session == NULL) return -ENOMEM; register_perf_file_handler(&file_handler); ret = perf_session__process_events(session, 0, &event__cwdlen, &event__cwd); if (ret) goto out_delete; process_samples(); end_sample_processing(); sort_pids(); write_svg_file(output_name); pr_info("Written %2.1f seconds of trace to %s.\n", (last_time - first_time) / 1000000000.0, output_name); out_delete: perf_session__delete(session); return ret; }
static int perf_session__list_build_ids(void) { struct perf_session *session; elf_version(EV_CURRENT); session = perf_session__new(input_name, O_RDONLY, force, false, &build_id__mark_dso_hit_ops); if (session == NULL) return -1; /* * See if this is an ELF file first: */ if (filename__fprintf_build_id(session->filename, stdout)) goto out; if (with_hits) perf_session__process_events(session, &build_id__mark_dso_hit_ops); perf_session__fprintf_dsos_buildid(session, stdout, with_hits); out: perf_session__delete(session); return 0; }
struct perf_session *perf_session__new(const char *filename, int mode, bool force, bool repipe, struct perf_tool *tool) { struct perf_session *self; struct stat st; size_t len; if (!filename || !strlen(filename)) { if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode)) filename = "-"; else filename = "perf.data"; } len = strlen(filename); self = zalloc(sizeof(*self) + len); if (self == NULL) goto out; memcpy(self->filename, filename, len); self->repipe = repipe; INIT_LIST_HEAD(&self->ordered_samples.samples); INIT_LIST_HEAD(&self->ordered_samples.sample_cache); INIT_LIST_HEAD(&self->ordered_samples.to_free); machines__init(&self->machines); if (mode == O_RDONLY) { if (perf_session__open(self, force) < 0) goto out_delete; perf_session__set_id_hdr_size(self); } else if (mode == O_WRONLY) { /* * In O_RDONLY mode this will be performed when reading the * kernel MMAP event, in perf_event__process_mmap(). */ if (perf_session__create_kernel_maps(self) < 0) goto out_delete; } if (tool && tool->ordering_requires_timestamps && tool->ordered_samples && !perf_evlist__sample_id_all(self->evlist)) { dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); tool->ordered_samples = false; } out: return self; out_delete: perf_session__delete(self); return NULL; }
struct perf_session *perf_session__new(struct perf_data_file *file, bool repipe, struct perf_tool *tool) { struct perf_session *session = zalloc(sizeof(*session)); if (!session) goto out; session->repipe = repipe; INIT_LIST_HEAD(&session->ordered_samples.samples); INIT_LIST_HEAD(&session->ordered_samples.sample_cache); INIT_LIST_HEAD(&session->ordered_samples.to_free); machines__init(&session->machines); if (file) { if (perf_data_file__open(file)) goto out_delete; session->file = file; if (perf_data_file__is_read(file)) { if (perf_session__open(session) < 0) goto out_close; perf_session__set_id_hdr_size(session); } } if (!file || perf_data_file__is_write(file)) { /* * In O_RDONLY mode this will be performed when reading the * kernel MMAP event, in perf_event__process_mmap(). */ if (perf_session__create_kernel_maps(session) < 0) goto out_delete; } if (tool && tool->ordering_requires_timestamps && tool->ordered_samples && !perf_evlist__sample_id_all(session->evlist)) { dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); tool->ordered_samples = false; } return session; out_close: perf_data_file__close(file); out_delete: perf_session__delete(session); out: return NULL; }
static int __cmd_evlist(const char *file_name, struct perf_attr_details *details) { struct perf_session *session; struct perf_evsel *pos; struct perf_data_file file = { .path = file_name, .mode = PERF_DATA_MODE_READ, .force = details->force, }; session = perf_session__new(&file, 0, NULL); if (session == NULL) return -1; evlist__for_each(session->evlist, pos) perf_evsel__fprintf(pos, details, stdout); perf_session__delete(session); return 0; } int cmd_evlist(int argc, const char **argv, const char *prefix __maybe_unused) { struct perf_attr_details details = { .verbose = false, }; const struct option options[] = { OPT_STRING('i', "input", &input_name, "file", "Input file name"), OPT_BOOLEAN('F', "freq", &details.freq, "Show the sample frequency"), OPT_BOOLEAN('v', "verbose", &details.verbose, "Show all event attr details"), OPT_BOOLEAN('g', "group", &details.event_group, "Show event group information"), OPT_BOOLEAN('f', "force", &details.force, "don't complain, do it"), OPT_END() }; const char * const evlist_usage[] = { "perf evlist [<options>]", NULL }; argc = parse_options(argc, argv, options, evlist_usage, 0); if (argc) usage_with_options(evlist_usage, options); if (details.event_group && (details.verbose || details.freq)) { usage_with_options_msg(evlist_usage, options, "--group option is not compatible with other options\n"); } return __cmd_evlist(input_name, &details); }
static int __cmd_evlist(void) { struct perf_session *session; struct perf_evsel *pos; session = perf_session__new(input_name, O_RDONLY, 0, false, NULL); if (session == NULL) return -ENOMEM; list_for_each_entry(pos, &session->evlist->entries, node) printf("%s\n", event_name(pos)); perf_session__delete(session); return 0; }
static int build_id_cache__fprintf_missing(const char *filename, bool force, FILE *fp) { struct perf_data_file file = { .path = filename, .mode = PERF_DATA_MODE_READ, .force = force, }; struct perf_session *session = perf_session__new(&file, false, NULL); if (session == NULL) return -1; perf_session__fprintf_dsos_buildid(session, fp, dso__missing_buildid_cache, 0); perf_session__delete(session); return 0; }
static int __cmd_buildid_list(void) { int err = -1; struct perf_session *session = perf_session__new(input_name, O_RDONLY, force); if (session == NULL) return -1; err = perf_header__process_sections(&session->header, session->fd, perf_file_section__process_buildids); if (err >= 0) dsos__fprintf_buildid(stdout); perf_session__delete(session); return err; }
static int __cmd_buildid_list(void) { int err = -1; struct perf_session *session; session = perf_session__new(input_name, O_RDONLY, force); if (session == NULL) return -1; if (with_hits) perf_session__process_events(session, &build_id__mark_dso_hit_ops); dsos__fprintf_buildid(stdout, with_hits); perf_session__delete(session); return err; }
static int perf_session__list_build_ids(void) { struct perf_session *session; session = perf_session__new(input_name, O_RDONLY, force, false, &build_id__mark_dso_hit_ops); if (session == NULL) return -1; if (with_hits) perf_session__process_events(session, &build_id__mark_dso_hit_ops); perf_session__fprintf_dsos_buildid(session, stdout, with_hits); perf_session__delete(session); return 0; }
struct perf_session *perf_session__new(const char *filename, int mode, bool force) { size_t len = filename ? strlen(filename) + 1 : 0; struct perf_session *self = zalloc(sizeof(*self) + len); if (self == NULL) goto out; if (perf_header__init(&self->header) < 0) goto out_free; memcpy(self->filename, filename, len); self->threads = RB_ROOT; self->last_match = NULL; self->mmap_window = 32; self->cwd = NULL; self->cwdlen = 0; self->unknown_events = 0; map_groups__init(&self->kmaps); if (mode == O_RDONLY) { if (perf_session__open(self, force) < 0) goto out_delete; } else if (mode == O_WRONLY) { /* * In O_RDONLY mode this will be performed when reading the * kernel MMAP event, in event__process_mmap(). */ if (perf_session__create_kernel_maps(self) < 0) goto out_delete; } self->sample_type = perf_header__sample_type(&self->header); out: return self; out_free: free(self); return NULL; out_delete: perf_session__delete(self); return NULL; }
static int perf_session__list_build_ids(bool force, bool with_hits) { struct perf_session *session; struct perf_data_file file = { .path = input_name, .mode = PERF_DATA_MODE_READ, .force = force, }; symbol__elf_init(); /* * See if this is an ELF file first: */ if (filename__fprintf_build_id(input_name, stdout) > 0) goto out; session = perf_session__new(&file, false, &build_id__mark_dso_hit_ops); if (session == NULL) return -1; /* * We take all buildids when the file contains AUX area tracing data * because we do not decode the trace because it would take too long. */ if (!perf_data_file__is_pipe(&file) && perf_header__has_feat(&session->header, HEADER_AUXTRACE)) with_hits = false; /* * in pipe-mode, the only way to get the buildids is to parse * the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID */ if (with_hits || perf_data_file__is_pipe(&file)) perf_session__process_events(session); perf_session__fprintf_dsos_buildid(session, stdout, dso__skip_buildid, with_hits); perf_session__delete(session); out: return 0; }
struct perf_session *perf_session__new(const char *filename, int mode, bool force) { size_t len = strlen(filename) + 1; struct perf_session *self = zalloc(sizeof(*self) + len); if (self == NULL) goto out; if (perf_header__init(&self->header) < 0) goto out_delete; memcpy(self->filename, filename, len); if (mode == O_RDONLY && perf_session__open(self, force) < 0) { perf_session__delete(self); self = NULL; } out: return self; out_delete: free(self); return NULL; }
int cmd_buildid_cache(int argc, const char **argv) { struct strlist *list; struct str_node *pos; int ret = 0; int ns_id = -1; bool force = false; char const *add_name_list_str = NULL, *remove_name_list_str = NULL, *purge_name_list_str = NULL, *missing_filename = NULL, *update_name_list_str = NULL, *kcore_filename = NULL; char sbuf[STRERR_BUFSIZE]; struct perf_data data = { .mode = PERF_DATA_MODE_READ, }; struct perf_session *session = NULL; struct nsinfo *nsi = NULL; const struct option buildid_cache_options[] = { OPT_STRING('a', "add", &add_name_list_str, "file list", "file(s) to add"), OPT_STRING('k', "kcore", &kcore_filename, "file", "kcore file to add"), OPT_STRING('r', "remove", &remove_name_list_str, "file list", "file(s) to remove"), OPT_STRING('p', "purge", &purge_name_list_str, "path list", "path(s) to remove (remove old caches too)"), OPT_STRING('M', "missing", &missing_filename, "file", "to find missing build ids in the cache"), OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), OPT_STRING('u', "update", &update_name_list_str, "file list", "file(s) to update"), OPT_INCR('v', "verbose", &verbose, "be more verbose"), OPT_INTEGER(0, "target-ns", &ns_id, "target pid for namespace context"), OPT_END() }; const char * const buildid_cache_usage[] = { "perf buildid-cache [<options>]", NULL }; argc = parse_options(argc, argv, buildid_cache_options, buildid_cache_usage, 0); if (argc || (!add_name_list_str && !kcore_filename && !remove_name_list_str && !purge_name_list_str && !missing_filename && !update_name_list_str)) usage_with_options(buildid_cache_usage, buildid_cache_options); if (ns_id > 0) nsi = nsinfo__new(ns_id); if (missing_filename) { data.file.path = missing_filename; data.force = force; session = perf_session__new(&data, false, NULL); if (session == NULL) return -1; } if (symbol__init(session ? &session->header.env : NULL) < 0) goto out; setup_pager(); if (add_name_list_str) { list = strlist__new(add_name_list_str, NULL); if (list) { strlist__for_each_entry(pos, list) if (build_id_cache__add_file(pos->s, nsi)) { if (errno == EEXIST) { pr_debug("%s already in the cache\n", pos->s); continue; } pr_warning("Couldn't add %s: %s\n", pos->s, str_error_r(errno, sbuf, sizeof(sbuf))); } strlist__delete(list); } } if (remove_name_list_str) { list = strlist__new(remove_name_list_str, NULL); if (list) { strlist__for_each_entry(pos, list) if (build_id_cache__remove_file(pos->s, nsi)) { if (errno == ENOENT) { pr_debug("%s wasn't in the cache\n", pos->s); continue; } pr_warning("Couldn't remove %s: %s\n", pos->s, str_error_r(errno, sbuf, sizeof(sbuf))); } strlist__delete(list); } } if (purge_name_list_str) { list = strlist__new(purge_name_list_str, NULL); if (list) { strlist__for_each_entry(pos, list) if (build_id_cache__purge_path(pos->s, nsi)) { if (errno == ENOENT) { pr_debug("%s wasn't in the cache\n", pos->s); continue; } pr_warning("Couldn't remove %s: %s\n", pos->s, str_error_r(errno, sbuf, sizeof(sbuf))); } strlist__delete(list); } } if (missing_filename) ret = build_id_cache__fprintf_missing(session, stdout); if (update_name_list_str) { list = strlist__new(update_name_list_str, NULL); if (list) { strlist__for_each_entry(pos, list) if (build_id_cache__update_file(pos->s, nsi)) { if (errno == ENOENT) { pr_debug("%s wasn't in the cache\n", pos->s); continue; } pr_warning("Couldn't update %s: %s\n", pos->s, str_error_r(errno, sbuf, sizeof(sbuf))); } strlist__delete(list); } } if (kcore_filename && build_id_cache__add_kcore(kcore_filename, force)) pr_warning("Couldn't add %s\n", kcore_filename); out: perf_session__delete(session); nsinfo__zput(nsi); return ret; }