blob: a4b97269cfc6220d8f0470fd41bad9aedd3f60fc [file] [log] [blame]
Ingo Molnarabaff322009-06-02 22:59:57 +02001/*
Ingo Molnarbf9e1872009-06-02 23:37:05 +02002 * builtin-record.c
3 *
4 * Builtin record command: Record the profile of a workload
5 * (or a CPU, or a PID) into the perf.data output file - for
6 * later analysis via perf report.
Ingo Molnarabaff322009-06-02 22:59:57 +02007 */
Xiao Guangrongb8f46c52010-02-03 11:53:14 +08008#define _FILE_OFFSET_BITS 64
9
Ingo Molnar16f762a2009-05-27 09:10:38 +020010#include "builtin.h"
Ingo Molnarbf9e1872009-06-02 23:37:05 +020011
12#include "perf.h"
13
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -020014#include "util/build-id.h"
Thomas Gleixner6eda5832009-05-01 18:29:57 +020015#include "util/util.h"
Ingo Molnar0e9b20b2009-05-26 09:17:18 +020016#include "util/parse-options.h"
Ingo Molnar8ad8db32009-05-26 11:10:09 +020017#include "util/parse-events.h"
Thomas Gleixner6eda5832009-05-01 18:29:57 +020018
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020019#include "util/header.h"
Frederic Weisbecker66e274f2009-08-12 11:07:25 +020020#include "util/event.h"
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -020021#include "util/evlist.h"
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -020022#include "util/evsel.h"
Frederic Weisbecker8f288272009-08-16 22:05:48 +020023#include "util/debug.h"
Arnaldo Carvalho de Melo94c744b2009-12-11 21:24:02 -020024#include "util/session.h"
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -020025#include "util/tool.h"
Arnaldo Carvalho de Melo8d063672009-11-04 18:50:43 -020026#include "util/symbol.h"
Paul Mackerrasa12b51c2010-03-10 20:36:09 +110027#include "util/cpumap.h"
Arnaldo Carvalho de Melofd782602011-01-18 15:15:24 -020028#include "util/thread_map.h"
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020029
Peter Zijlstra97124d5e2009-06-02 15:52:24 +020030#include <unistd.h>
Peter Zijlstrade9ac072009-04-08 15:01:31 +020031#include <sched.h>
Arnaldo Carvalho de Meloa41794c2010-05-18 18:29:23 -030032#include <sys/mman.h>
Peter Zijlstrade9ac072009-04-08 15:01:31 +020033
Bernhard Rosenkraenzer78da39f2012-10-08 09:43:26 +030034#ifndef HAVE_ON_EXIT
35#ifndef ATEXIT_MAX
36#define ATEXIT_MAX 32
37#endif
38static int __on_exit_count = 0;
39typedef void (*on_exit_func_t) (int, void *);
40static on_exit_func_t __on_exit_funcs[ATEXIT_MAX];
41static void *__on_exit_args[ATEXIT_MAX];
42static int __exitcode = 0;
43static void __handle_on_exit_funcs(void);
44static int on_exit(on_exit_func_t function, void *arg);
45#define exit(x) (exit)(__exitcode = (x))
46
47static int on_exit(on_exit_func_t function, void *arg)
48{
49 if (__on_exit_count == ATEXIT_MAX)
50 return -ENOMEM;
51 else if (__on_exit_count == 0)
52 atexit(__handle_on_exit_funcs);
53 __on_exit_funcs[__on_exit_count] = function;
54 __on_exit_args[__on_exit_count++] = arg;
55 return 0;
56}
57
58static void __handle_on_exit_funcs(void)
59{
60 int i;
61 for (i = 0; i < __on_exit_count; i++)
62 __on_exit_funcs[i] (__exitcode, __on_exit_args[i]);
63}
64#endif
65
Frederic Weisbecker7865e812010-04-14 19:42:07 +020066enum write_mode_t {
67 WRITE_FORCE,
68 WRITE_APPEND
69};
70
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -020071struct perf_record {
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -020072 struct perf_tool tool;
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -020073 struct perf_record_opts opts;
74 u64 bytes_written;
75 const char *output_name;
76 struct perf_evlist *evlist;
77 struct perf_session *session;
78 const char *progname;
79 int output;
80 unsigned int page_size;
81 int realtime_prio;
82 enum write_mode_t write_mode;
83 bool no_buildid;
84 bool no_buildid_cache;
85 bool force;
86 bool file_new;
87 bool append_file;
88 long samples;
89 off_t post_processing_offset;
Arnaldo Carvalho de Melo0f82ebc2011-11-08 14:41:57 -020090};
Ingo Molnara21ca2c2009-06-06 09:58:57 +020091
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -020092static void advance_output(struct perf_record *rec, size_t size)
Tom Zanussi92155452010-04-01 23:59:21 -050093{
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -020094 rec->bytes_written += size;
Tom Zanussi92155452010-04-01 23:59:21 -050095}
96
David Ahern8d3eca22012-08-26 12:24:47 -060097static int write_output(struct perf_record *rec, void *buf, size_t size)
Peter Zijlstraf5970552009-06-18 23:22:55 +020098{
99 while (size) {
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200100 int ret = write(rec->output, buf, size);
Peter Zijlstraf5970552009-06-18 23:22:55 +0200101
David Ahern8d3eca22012-08-26 12:24:47 -0600102 if (ret < 0) {
103 pr_err("failed to write\n");
104 return -1;
105 }
Peter Zijlstraf5970552009-06-18 23:22:55 +0200106
107 size -= ret;
108 buf += ret;
109
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200110 rec->bytes_written += ret;
Peter Zijlstraf5970552009-06-18 23:22:55 +0200111 }
David Ahern8d3eca22012-08-26 12:24:47 -0600112
113 return 0;
Peter Zijlstraf5970552009-06-18 23:22:55 +0200114}
115
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -0200116static int process_synthesized_event(struct perf_tool *tool,
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200117 union perf_event *event,
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300118 struct perf_sample *sample __maybe_unused,
119 struct machine *machine __maybe_unused)
Arnaldo Carvalho de Melo234fbbf2009-10-26 19:23:18 -0200120{
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -0200121 struct perf_record *rec = container_of(tool, struct perf_record, tool);
David Ahern8d3eca22012-08-26 12:24:47 -0600122 if (write_output(rec, event, event->header.size) < 0)
123 return -1;
124
Arnaldo Carvalho de Melo234fbbf2009-10-26 19:23:18 -0200125 return 0;
126}
127
David Ahern8d3eca22012-08-26 12:24:47 -0600128static int perf_record__mmap_read(struct perf_record *rec,
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200129 struct perf_mmap *md)
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200130{
Arnaldo Carvalho de Melo744bd8a2011-01-12 17:07:28 -0200131 unsigned int head = perf_mmap__read_head(md);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200132 unsigned int old = md->prev;
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200133 unsigned char *data = md->base + rec->page_size;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200134 unsigned long size;
135 void *buf;
David Ahern8d3eca22012-08-26 12:24:47 -0600136 int rc = 0;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200137
Arnaldo Carvalho de Melodc820092011-01-28 14:49:19 -0200138 if (old == head)
David Ahern8d3eca22012-08-26 12:24:47 -0600139 return 0;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200140
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200141 rec->samples++;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200142
143 size = head - old;
144
145 if ((old & md->mask) + size != (head & md->mask)) {
146 buf = &data[old & md->mask];
147 size = md->mask + 1 - (old & md->mask);
148 old += size;
Ingo Molnar021e9f42009-06-03 19:27:19 +0200149
David Ahern8d3eca22012-08-26 12:24:47 -0600150 if (write_output(rec, buf, size) < 0) {
151 rc = -1;
152 goto out;
153 }
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200154 }
155
156 buf = &data[old & md->mask];
157 size = head - old;
158 old += size;
Ingo Molnar021e9f42009-06-03 19:27:19 +0200159
David Ahern8d3eca22012-08-26 12:24:47 -0600160 if (write_output(rec, buf, size) < 0) {
161 rc = -1;
162 goto out;
163 }
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200164
165 md->prev = old;
Arnaldo Carvalho de Melo115d2d82011-01-12 17:11:53 -0200166 perf_mmap__write_tail(md, old);
David Ahern8d3eca22012-08-26 12:24:47 -0600167
168out:
169 return rc;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200170}
171
172static volatile int done = 0;
Peter Zijlstraf7b7c262009-06-10 15:55:59 +0200173static volatile int signr = -1;
Andi Kleen33e49ea2011-09-15 14:31:40 -0700174static volatile int child_finished = 0;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200175
Peter Zijlstra16c8a102009-05-05 17:50:27 +0200176static void sig_handler(int sig)
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200177{
Andi Kleen33e49ea2011-09-15 14:31:40 -0700178 if (sig == SIGCHLD)
179 child_finished = 1;
180
Peter Zijlstra16c8a102009-05-05 17:50:27 +0200181 done = 1;
Peter Zijlstraf7b7c262009-06-10 15:55:59 +0200182 signr = sig;
183}
184
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300185static void perf_record__sig_exit(int exit_status __maybe_unused, void *arg)
Peter Zijlstraf7b7c262009-06-10 15:55:59 +0200186{
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200187 struct perf_record *rec = arg;
Andi Kleen33e49ea2011-09-15 14:31:40 -0700188 int status;
189
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200190 if (rec->evlist->workload.pid > 0) {
Andi Kleen33e49ea2011-09-15 14:31:40 -0700191 if (!child_finished)
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200192 kill(rec->evlist->workload.pid, SIGTERM);
Andi Kleen33e49ea2011-09-15 14:31:40 -0700193
194 wait(&status);
195 if (WIFSIGNALED(status))
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200196 psignal(WTERMSIG(status), rec->progname);
Andi Kleen33e49ea2011-09-15 14:31:40 -0700197 }
Chris Wilson933da832009-10-04 01:35:01 +0100198
Arnaldo Carvalho de Melo18483b82010-12-06 15:13:38 -0200199 if (signr == -1 || signr == SIGUSR1)
Peter Zijlstraf7b7c262009-06-10 15:55:59 +0200200 return;
201
202 signal(signr, SIG_DFL);
203 kill(getpid(), signr);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200204}
205
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300206static bool perf_evlist__equal(struct perf_evlist *evlist,
207 struct perf_evlist *other)
208{
209 struct perf_evsel *pos, *pair;
210
211 if (evlist->nr_entries != other->nr_entries)
212 return false;
213
Arnaldo Carvalho de Melo0c21f732012-08-14 16:42:15 -0300214 pair = perf_evlist__first(other);
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300215
216 list_for_each_entry(pos, &evlist->entries, node) {
217 if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0))
218 return false;
Arnaldo Carvalho de Melo0c21f732012-08-14 16:42:15 -0300219 pair = perf_evsel__next(pair);
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300220 }
221
222 return true;
223}
224
David Ahern8d3eca22012-08-26 12:24:47 -0600225static int perf_record__open(struct perf_record *rec)
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200226{
Jiri Olsa6a4bb042012-08-08 12:22:36 +0200227 struct perf_evsel *pos;
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200228 struct perf_evlist *evlist = rec->evlist;
229 struct perf_session *session = rec->session;
230 struct perf_record_opts *opts = &rec->opts;
David Ahern8d3eca22012-08-26 12:24:47 -0600231 int rc = 0;
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200232
Arnaldo Carvalho de Melof77a9512012-12-10 16:41:31 -0300233 perf_evlist__config(evlist, opts);
Jiri Olsacac21422012-11-12 18:34:00 +0100234
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200235 list_for_each_entry(pos, &evlist->entries, node) {
236 struct perf_event_attr *attr = &pos->attr;
Ingo Molnar3da297a2009-06-07 17:39:02 +0200237try_again:
Jiri Olsa6a4bb042012-08-08 12:22:36 +0200238 if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) {
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300239 int err = errno;
Ingo Molnarf250c0302009-06-05 13:18:41 +0200240
Arnaldo Carvalho de Meloc286c412011-03-28 09:50:11 -0300241 if (err == EPERM || err == EACCES) {
Arnaldo Carvalho de Melob8631e62011-10-26 08:02:55 -0200242 ui__error_paranoid();
David Ahern8d3eca22012-08-26 12:24:47 -0600243 rc = -err;
244 goto out;
Namhyung Kimbea03402012-04-26 14:15:15 +0900245 } else if (err == ENODEV && opts->target.cpu_list) {
David Ahern8d3eca22012-08-26 12:24:47 -0600246 pr_err("No such device - did you specify"
247 " an out-of-range profile CPU?\n");
248 rc = -err;
249 goto out;
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300250 }
Ingo Molnar3da297a2009-06-07 17:39:02 +0200251
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300252 /*
253 * If it's cycles then fall back to hrtimer
254 * based cpu-clock-tick sw counter, which
David Ahern028d4552012-05-08 09:28:57 -0600255 * is always available even if no PMU support.
256 *
257 * PPC returns ENXIO until 2.6.37 (behavior changed
258 * with commit b0a873e).
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300259 */
David Ahern028d4552012-05-08 09:28:57 -0600260 if ((err == ENOENT || err == ENXIO)
261 && attr->type == PERF_TYPE_HARDWARE
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300262 && attr->config == PERF_COUNT_HW_CPU_CYCLES) {
Ingo Molnar3da297a2009-06-07 17:39:02 +0200263
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300264 if (verbose)
David Ahernca6a4252011-03-25 13:11:11 -0600265 ui__warning("The cycles event is not supported, "
266 "trying to fall back to cpu-clock-ticks\n");
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300267 attr->type = PERF_TYPE_SOFTWARE;
268 attr->config = PERF_COUNT_SW_CPU_CLOCK;
David Ahernd1cae342012-05-08 10:50:11 -0600269 if (pos->name) {
270 free(pos->name);
271 pos->name = NULL;
272 }
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300273 goto try_again;
274 }
David Ahernca6a4252011-03-25 13:11:11 -0600275
276 if (err == ENOENT) {
Namhyung Kim3780f482012-05-29 13:22:57 +0900277 ui__error("The %s event is not supported.\n",
Arnaldo Carvalho de Melo7289f832012-06-12 12:34:58 -0300278 perf_evsel__name(pos));
David Ahern8d3eca22012-08-26 12:24:47 -0600279 rc = -err;
280 goto out;
David Ahern2305c822012-09-13 14:59:15 -0600281 } else if ((err == EOPNOTSUPP) && (attr->precise_ip)) {
282 ui__error("\'precise\' request may not be supported. "
283 "Try removing 'p' modifier\n");
284 rc = -err;
285 goto out;
David Ahernca6a4252011-03-25 13:11:11 -0600286 }
287
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300288 printf("\n");
Stephane Eranian1863fbb2012-09-20 18:19:45 +0200289 error("sys_perf_event_open() syscall returned with %d "
290 "(%s) for event %s. /bin/dmesg may provide "
291 "additional information.\n",
292 err, strerror(err), perf_evsel__name(pos));
Simon Kaempfleinbfd45112009-11-16 15:25:53 +1000293
294#if defined(__i386__) || defined(__x86_64__)
David Ahern8d3eca22012-08-26 12:24:47 -0600295 if (attr->type == PERF_TYPE_HARDWARE &&
296 err == EOPNOTSUPP) {
297 pr_err("No hardware sampling interrupt available."
298 " No APIC? If so then you can boot the kernel"
299 " with the \"lapic\" boot parameter to"
300 " force-enable it.\n");
301 rc = -err;
302 goto out;
303 }
Simon Kaempfleinbfd45112009-11-16 15:25:53 +1000304#endif
305
David Ahern8d3eca22012-08-26 12:24:47 -0600306 pr_err("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
307 rc = -err;
308 goto out;
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300309 }
Li Zefanc171b552009-10-15 11:22:07 +0800310 }
Arnaldo Carvalho de Meloa43d3f02010-12-25 12:12:25 -0200311
Arnaldo Carvalho de Melo1491a632012-09-26 14:43:13 -0300312 if (perf_evlist__apply_filters(evlist)) {
Frederic Weisbecker0a102472011-02-26 04:51:54 +0100313 error("failed to set filter with %d (%s)\n", errno,
314 strerror(errno));
David Ahern8d3eca22012-08-26 12:24:47 -0600315 rc = -1;
316 goto out;
Frederic Weisbecker0a102472011-02-26 04:51:54 +0100317 }
318
Nelson Elhage18e60932011-12-19 08:39:31 -0500319 if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) {
David Ahern8d3eca22012-08-26 12:24:47 -0600320 if (errno == EPERM) {
321 pr_err("Permission error mapping pages.\n"
322 "Consider increasing "
323 "/proc/sys/kernel/perf_event_mlock_kb,\n"
324 "or try again with a smaller value of -m/--mmap_pages.\n"
325 "(current value: %d)\n", opts->mmap_pages);
326 rc = -errno;
Jiri Olsa0089fa92012-10-20 16:33:19 +0200327 } else if (!is_power_of_2(opts->mmap_pages) &&
328 (opts->mmap_pages != UINT_MAX)) {
David Ahern8d3eca22012-08-26 12:24:47 -0600329 pr_err("--mmap_pages/-m value must be a power of two.");
330 rc = -EINVAL;
331 } else {
332 pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno));
333 rc = -errno;
334 }
335 goto out;
Nelson Elhage18e60932011-12-19 08:39:31 -0500336 }
Arnaldo Carvalho de Melo0a27d7f2011-01-14 15:50:51 -0200337
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200338 if (rec->file_new)
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300339 session->evlist = evlist;
340 else {
341 if (!perf_evlist__equal(session->evlist, evlist)) {
342 fprintf(stderr, "incompatible append\n");
David Ahern8d3eca22012-08-26 12:24:47 -0600343 rc = -1;
344 goto out;
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300345 }
346 }
347
Arnaldo Carvalho de Melo7b56cce2012-08-01 19:31:00 -0300348 perf_session__set_id_hdr_size(session);
David Ahern8d3eca22012-08-26 12:24:47 -0600349out:
350 return rc;
Peter Zijlstra16c8a102009-05-05 17:50:27 +0200351}
352
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200353static int process_buildids(struct perf_record *rec)
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -0200354{
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200355 u64 size = lseek(rec->output, 0, SEEK_CUR);
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -0200356
Arnaldo Carvalho de Melo9f591fd2010-03-11 15:53:11 -0300357 if (size == 0)
358 return 0;
359
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200360 rec->session->fd = rec->output;
361 return __perf_session__process_events(rec->session, rec->post_processing_offset,
362 size - rec->post_processing_offset,
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -0200363 size, &build_id__mark_dso_hit_ops);
364}
365
David Ahern8d3eca22012-08-26 12:24:47 -0600366static void perf_record__exit(int status, void *arg)
Peter Zijlstraf5970552009-06-18 23:22:55 +0200367{
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200368 struct perf_record *rec = arg;
Peter Zijlstraf5970552009-06-18 23:22:55 +0200369
David Ahern8d3eca22012-08-26 12:24:47 -0600370 if (status != 0)
371 return;
372
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200373 if (!rec->opts.pipe_output) {
374 rec->session->header.data_size += rec->bytes_written;
375
376 if (!rec->no_buildid)
377 process_buildids(rec);
378 perf_session__write_header(rec->session, rec->evlist,
379 rec->output, true);
380 perf_session__delete(rec->session);
381 perf_evlist__delete(rec->evlist);
Arnaldo Carvalho de Melod65a4582010-07-30 18:31:28 -0300382 symbol__exit();
Tom Zanussic7929e42010-04-01 23:59:22 -0500383 }
Peter Zijlstraf5970552009-06-18 23:22:55 +0200384}
385
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200386static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800387{
388 int err;
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -0200389 struct perf_tool *tool = data;
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800390
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -0300391 if (machine__is_host(machine))
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800392 return;
393
394 /*
395 *As for guest kernel when processing subcommand record&report,
396 *we arrange module mmap prior to guest kernel mmap and trigger
397 *a preload dso because default guest module symbols are loaded
398 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
399 *method is used to avoid symbol missing when the first addr is
400 *in module instead of in guest kernel.
401 */
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -0200402 err = perf_event__synthesize_modules(tool, process_synthesized_event,
Arnaldo Carvalho de Melo743eb862011-11-28 07:56:39 -0200403 machine);
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800404 if (err < 0)
405 pr_err("Couldn't record guest kernel [%d]'s reference"
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -0300406 " relocation symbol.\n", machine->pid);
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800407
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800408 /*
409 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
410 * have no _text sometimes.
411 */
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -0200412 err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
Arnaldo Carvalho de Melo743eb862011-11-28 07:56:39 -0200413 machine, "_text");
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800414 if (err < 0)
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -0200415 err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
Arnaldo Carvalho de Melo743eb862011-11-28 07:56:39 -0200416 machine, "_stext");
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800417 if (err < 0)
418 pr_err("Couldn't record guest kernel [%d]'s reference"
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -0300419 " relocation symbol.\n", machine->pid);
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800420}
421
Frederic Weisbecker98402802010-05-02 22:05:29 +0200422static struct perf_event_header finished_round_event = {
423 .size = sizeof(struct perf_event_header),
424 .type = PERF_RECORD_FINISHED_ROUND,
425};
426
David Ahern8d3eca22012-08-26 12:24:47 -0600427static int perf_record__mmap_read_all(struct perf_record *rec)
Frederic Weisbecker98402802010-05-02 22:05:29 +0200428{
Peter Zijlstra0e2e63d2010-05-20 14:45:26 +0200429 int i;
David Ahern8d3eca22012-08-26 12:24:47 -0600430 int rc = 0;
Frederic Weisbecker98402802010-05-02 22:05:29 +0200431
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200432 for (i = 0; i < rec->evlist->nr_mmaps; i++) {
David Ahern8d3eca22012-08-26 12:24:47 -0600433 if (rec->evlist->mmap[i].base) {
434 if (perf_record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) {
435 rc = -1;
436 goto out;
437 }
438 }
Frederic Weisbecker98402802010-05-02 22:05:29 +0200439 }
440
Stephane Eranian2eeaaa02012-05-15 13:28:13 +0200441 if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA))
David Ahern8d3eca22012-08-26 12:24:47 -0600442 rc = write_output(rec, &finished_round_event,
443 sizeof(finished_round_event));
444
445out:
446 return rc;
Frederic Weisbecker98402802010-05-02 22:05:29 +0200447}
448
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200449static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
Peter Zijlstra16c8a102009-05-05 17:50:27 +0200450{
Peter Zijlstra97124d5e2009-06-02 15:52:24 +0200451 struct stat st;
Ingo Molnarabaff322009-06-02 22:59:57 +0200452 int flags;
Robert Richter781ba9d2011-12-15 17:32:40 +0100453 int err, output, feat;
Peter Zijlstra8b412662009-09-17 19:59:05 +0200454 unsigned long waking = 0;
Zhang, Yanmin46be6042010-03-18 11:36:04 -0300455 const bool forks = argc > 0;
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -0300456 struct machine *machine;
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -0200457 struct perf_tool *tool = &rec->tool;
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200458 struct perf_record_opts *opts = &rec->opts;
459 struct perf_evlist *evsel_list = rec->evlist;
460 const char *output_name = rec->output_name;
461 struct perf_session *session;
Jiri Olsa27119262012-11-12 18:34:02 +0100462 bool disabled = false;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200463
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200464 rec->progname = argv[0];
Andi Kleen33e49ea2011-09-15 14:31:40 -0700465
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200466 rec->page_size = sysconf(_SC_PAGE_SIZE);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200467
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200468 on_exit(perf_record__sig_exit, rec);
Peter Zijlstraf5970552009-06-18 23:22:55 +0200469 signal(SIGCHLD, sig_handler);
470 signal(SIGINT, sig_handler);
Arnaldo Carvalho de Melo18483b82010-12-06 15:13:38 -0200471 signal(SIGUSR1, sig_handler);
Peter Zijlstraf5970552009-06-18 23:22:55 +0200472
Franck Bui-Huud7065ad2011-01-16 17:14:45 +0100473 if (!output_name) {
474 if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200475 opts->pipe_output = true;
Franck Bui-Huud7065ad2011-01-16 17:14:45 +0100476 else
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200477 rec->output_name = output_name = "perf.data";
Franck Bui-Huud7065ad2011-01-16 17:14:45 +0100478 }
479 if (output_name) {
480 if (!strcmp(output_name, "-"))
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200481 opts->pipe_output = true;
Franck Bui-Huud7065ad2011-01-16 17:14:45 +0100482 else if (!stat(output_name, &st) && st.st_size) {
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200483 if (rec->write_mode == WRITE_FORCE) {
Franck Bui-Huud7065ad2011-01-16 17:14:45 +0100484 char oldname[PATH_MAX];
485 snprintf(oldname, sizeof(oldname), "%s.old",
486 output_name);
487 unlink(oldname);
488 rename(output_name, oldname);
489 }
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200490 } else if (rec->write_mode == WRITE_APPEND) {
491 rec->write_mode = WRITE_FORCE;
Pierre Habouzit266e0e22009-08-07 14:16:01 +0200492 }
Peter Zijlstra97124d5e2009-06-02 15:52:24 +0200493 }
494
Xiao Guangrongf887f302010-02-04 16:46:42 +0800495 flags = O_CREAT|O_RDWR;
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200496 if (rec->write_mode == WRITE_APPEND)
497 rec->file_new = 0;
Ingo Molnarabaff322009-06-02 22:59:57 +0200498 else
499 flags |= O_TRUNC;
500
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200501 if (opts->pipe_output)
Tom Zanussi529870e2010-04-01 23:59:16 -0500502 output = STDOUT_FILENO;
503 else
504 output = open(output_name, flags, S_IRUSR | S_IWUSR);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200505 if (output < 0) {
506 perror("failed to create output file");
David Ahern8d3eca22012-08-26 12:24:47 -0600507 return -1;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200508 }
509
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200510 rec->output = output;
511
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200512 session = perf_session__new(output_name, O_WRONLY,
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200513 rec->write_mode == WRITE_FORCE, false, NULL);
Arnaldo Carvalho de Melo94c744b2009-12-11 21:24:02 -0200514 if (session == NULL) {
Arnaldo Carvalho de Meloa9a70bb2009-11-17 01:18:11 -0200515 pr_err("Not enough memory for reading perf file header\n");
516 return -1;
517 }
518
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200519 rec->session = session;
520
Robert Richter781ba9d2011-12-15 17:32:40 +0100521 for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
522 perf_header__set_feat(&session->header, feat);
523
524 if (rec->no_buildid)
525 perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
526
527 if (!have_tracepoints(&evsel_list->entries))
Stephane Eranian2eeaaa02012-05-15 13:28:13 +0200528 perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -0200529
Stephane Eranian330aa672012-03-08 23:47:46 +0100530 if (!rec->opts.branch_stack)
531 perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
532
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200533 if (!rec->file_new) {
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300534 err = perf_session__read_header(session, output);
Arnaldo Carvalho de Melo4dc0a042009-11-19 14:55:55 -0200535 if (err < 0)
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300536 goto out_delete_session;
Arnaldo Carvalho de Melo4dc0a042009-11-19 14:55:55 -0200537 }
538
Arnaldo Carvalho de Melod4db3f12009-12-27 21:36:57 -0200539 if (forks) {
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200540 err = perf_evlist__prepare_workload(evsel_list, opts, argv);
Arnaldo Carvalho de Melo35b9d882011-11-09 08:47:15 -0200541 if (err < 0) {
542 pr_err("Couldn't run the workload!\n");
543 goto out_delete_session;
Jens Axboe0a5ac842009-08-12 11:18:01 +0200544 }
Peter Zijlstra856e9662009-12-16 17:55:55 +0100545 }
546
David Ahern8d3eca22012-08-26 12:24:47 -0600547 if (perf_record__open(rec) != 0) {
548 err = -1;
549 goto out_delete_session;
550 }
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200551
Arnaldo Carvalho de Melo712a4b62011-02-17 12:18:42 -0200552 /*
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200553 * perf_session__delete(session) will be called at perf_record__exit()
Arnaldo Carvalho de Melo712a4b62011-02-17 12:18:42 -0200554 */
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200555 on_exit(perf_record__exit, rec);
Arnaldo Carvalho de Melo712a4b62011-02-17 12:18:42 -0200556
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200557 if (opts->pipe_output) {
Tom Zanussi529870e2010-04-01 23:59:16 -0500558 err = perf_header__write_pipe(output);
559 if (err < 0)
David Ahern8d3eca22012-08-26 12:24:47 -0600560 goto out_delete_session;
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200561 } else if (rec->file_new) {
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300562 err = perf_session__write_header(session, evsel_list,
563 output, false);
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -0200564 if (err < 0)
David Ahern8d3eca22012-08-26 12:24:47 -0600565 goto out_delete_session;
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -0200566 }
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +0200567
David Ahernd3665492012-02-06 15:27:52 -0700568 if (!rec->no_buildid
Robert Richtere20960c2011-12-07 10:02:55 +0100569 && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
David Ahernd3665492012-02-06 15:27:52 -0700570 pr_err("Couldn't generate buildids. "
Robert Richtere20960c2011-12-07 10:02:55 +0100571 "Use --no-buildid to profile anyway.\n");
David Ahern8d3eca22012-08-26 12:24:47 -0600572 err = -1;
573 goto out_delete_session;
Robert Richtere20960c2011-12-07 10:02:55 +0100574 }
575
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200576 rec->post_processing_offset = lseek(output, 0, SEEK_CUR);
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -0200577
Arnaldo Carvalho de Melo743eb862011-11-28 07:56:39 -0200578 machine = perf_session__find_host_machine(session);
579 if (!machine) {
580 pr_err("Couldn't find native kernel information.\n");
David Ahern8d3eca22012-08-26 12:24:47 -0600581 err = -1;
582 goto out_delete_session;
Arnaldo Carvalho de Melo743eb862011-11-28 07:56:39 -0200583 }
584
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200585 if (opts->pipe_output) {
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -0200586 err = perf_event__synthesize_attrs(tool, session,
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200587 process_synthesized_event);
Tom Zanussi2c46dbb2010-04-01 23:59:19 -0500588 if (err < 0) {
589 pr_err("Couldn't synthesize attrs.\n");
David Ahern8d3eca22012-08-26 12:24:47 -0600590 goto out_delete_session;
Tom Zanussi2c46dbb2010-04-01 23:59:19 -0500591 }
Tom Zanussicd19a032010-04-01 23:59:20 -0500592
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -0200593 err = perf_event__synthesize_event_types(tool, process_synthesized_event,
Arnaldo Carvalho de Melo743eb862011-11-28 07:56:39 -0200594 machine);
Tom Zanussicd19a032010-04-01 23:59:20 -0500595 if (err < 0) {
596 pr_err("Couldn't synthesize event_types.\n");
David Ahern8d3eca22012-08-26 12:24:47 -0600597 goto out_delete_session;
Tom Zanussicd19a032010-04-01 23:59:20 -0500598 }
Tom Zanussi92155452010-04-01 23:59:21 -0500599
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200600 if (have_tracepoints(&evsel_list->entries)) {
Tom Zanussi63e0c772010-05-03 00:14:48 -0500601 /*
602 * FIXME err <= 0 here actually means that
603 * there were no tracepoints so its not really
604 * an error, just that we don't need to
605 * synthesize anything. We really have to
606 * return this more properly and also
607 * propagate errors that now are calling die()
608 */
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -0200609 err = perf_event__synthesize_tracing_data(tool, output, evsel_list,
Arnaldo Carvalho de Melo743eb862011-11-28 07:56:39 -0200610 process_synthesized_event);
Tom Zanussi63e0c772010-05-03 00:14:48 -0500611 if (err <= 0) {
612 pr_err("Couldn't record tracing data.\n");
David Ahern8d3eca22012-08-26 12:24:47 -0600613 goto out_delete_session;
Tom Zanussi63e0c772010-05-03 00:14:48 -0500614 }
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200615 advance_output(rec, err);
Tom Zanussi63e0c772010-05-03 00:14:48 -0500616 }
Tom Zanussi2c46dbb2010-04-01 23:59:19 -0500617 }
618
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -0200619 err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
Arnaldo Carvalho de Melo743eb862011-11-28 07:56:39 -0200620 machine, "_text");
Arnaldo Carvalho de Melo70162132010-03-30 18:27:39 -0300621 if (err < 0)
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -0200622 err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
Arnaldo Carvalho de Melo743eb862011-11-28 07:56:39 -0200623 machine, "_stext");
Arnaldo Carvalho de Meloc1a3a4b2010-11-22 14:01:55 -0200624 if (err < 0)
625 pr_err("Couldn't record kernel reference relocation symbol\n"
626 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
627 "Check /proc/kallsyms permission or run as root.\n");
Arnaldo Carvalho de Melo56b03f32010-01-05 16:50:31 -0200628
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -0200629 err = perf_event__synthesize_modules(tool, process_synthesized_event,
Arnaldo Carvalho de Melo743eb862011-11-28 07:56:39 -0200630 machine);
Arnaldo Carvalho de Meloc1a3a4b2010-11-22 14:01:55 -0200631 if (err < 0)
632 pr_err("Couldn't record kernel module information.\n"
633 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
634 "Check /proc/modules permission or run as root.\n");
635
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800636 if (perf_guest)
Arnaldo Carvalho de Melo45694aa2011-11-28 08:30:20 -0200637 perf_session__process_machines(session, tool,
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200638 perf_event__synthesize_guest_os);
Arnaldo Carvalho de Melob7cece762010-01-13 13:22:17 -0200639
Namhyung Kimbea03402012-04-26 14:15:15 +0900640 if (!opts->target.system_wide)
David Ahern8d3eca22012-08-26 12:24:47 -0600641 err = perf_event__synthesize_thread_map(tool, evsel_list->threads,
Arnaldo Carvalho de Melo7c940c12011-02-11 11:45:54 -0200642 process_synthesized_event,
Arnaldo Carvalho de Melo743eb862011-11-28 07:56:39 -0200643 machine);
Arnaldo Carvalho de Melo234fbbf2009-10-26 19:23:18 -0200644 else
David Ahern8d3eca22012-08-26 12:24:47 -0600645 err = perf_event__synthesize_threads(tool, process_synthesized_event,
Arnaldo Carvalho de Melo743eb862011-11-28 07:56:39 -0200646 machine);
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +0200647
David Ahern8d3eca22012-08-26 12:24:47 -0600648 if (err != 0)
649 goto out_delete_session;
650
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200651 if (rec->realtime_prio) {
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200652 struct sched_param param;
653
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200654 param.sched_priority = rec->realtime_prio;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200655 if (sched_setscheduler(0, SCHED_FIFO, &param)) {
Arnaldo Carvalho de Melo6beba7a2009-10-21 17:34:06 -0200656 pr_err("Could not set realtime priority.\n");
David Ahern8d3eca22012-08-26 12:24:47 -0600657 err = -1;
658 goto out_delete_session;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200659 }
660 }
661
Jiri Olsa774cb492012-11-12 18:34:01 +0100662 /*
663 * When perf is starting the traced process, all the events
664 * (apart from group members) have enable_on_exec=1 set,
665 * so don't spoil it by prematurely enabling them.
666 */
667 if (!perf_target__none(&opts->target))
668 perf_evlist__enable(evsel_list);
David Ahern764e16a32011-08-25 10:17:55 -0600669
Peter Zijlstra856e9662009-12-16 17:55:55 +0100670 /*
671 * Let the child rip
672 */
Arnaldo Carvalho de Melod4db3f12009-12-27 21:36:57 -0200673 if (forks)
Arnaldo Carvalho de Melo35b9d882011-11-09 08:47:15 -0200674 perf_evlist__start_workload(evsel_list);
Peter Zijlstra856e9662009-12-16 17:55:55 +0100675
Peter Zijlstra649c48a2009-06-24 21:12:48 +0200676 for (;;) {
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200677 int hits = rec->samples;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200678
David Ahern8d3eca22012-08-26 12:24:47 -0600679 if (perf_record__mmap_read_all(rec) < 0) {
680 err = -1;
681 goto out_delete_session;
682 }
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200683
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200684 if (hits == rec->samples) {
Peter Zijlstra649c48a2009-06-24 21:12:48 +0200685 if (done)
686 break;
Arnaldo Carvalho de Melo5c581042011-01-11 22:30:02 -0200687 err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1);
Peter Zijlstra8b412662009-09-17 19:59:05 +0200688 waking++;
689 }
690
Jiri Olsa774cb492012-11-12 18:34:01 +0100691 /*
692 * When perf is starting the traced process, at the end events
693 * die with the process and we wait for that. Thus no need to
694 * disable events in this case.
695 */
Jiri Olsa27119262012-11-12 18:34:02 +0100696 if (done && !disabled && !perf_target__none(&opts->target)) {
Arnaldo Carvalho de Melo4152ab32011-07-25 11:06:19 -0300697 perf_evlist__disable(evsel_list);
Jiri Olsa27119262012-11-12 18:34:02 +0100698 disabled = true;
699 }
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200700 }
701
Arnaldo Carvalho de Melo18483b82010-12-06 15:13:38 -0200702 if (quiet || signr == SIGUSR1)
Arnaldo Carvalho de Melob44308f2010-10-26 15:20:09 -0200703 return 0;
704
Peter Zijlstra8b412662009-09-17 19:59:05 +0200705 fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
706
Ingo Molnar021e9f42009-06-03 19:27:19 +0200707 /*
708 * Approximate RIP event size: 24 bytes.
709 */
710 fprintf(stderr,
Arnaldo Carvalho de Melo9486aa32011-01-22 20:37:02 -0200711 "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200712 (double)rec->bytes_written / 1024.0 / 1024.0,
Ingo Molnar021e9f42009-06-03 19:27:19 +0200713 output_name,
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200714 rec->bytes_written / 24);
Ingo Molnaraddc2782009-06-02 23:43:11 +0200715
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200716 return 0;
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300717
718out_delete_session:
719 perf_session__delete(session);
720 return err;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200721}
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200722
Roberto Agostino Vitillobdfebd82012-02-09 23:21:02 +0100723#define BRANCH_OPT(n, m) \
724 { .name = n, .mode = (m) }
725
726#define BRANCH_END { .name = NULL }
727
728struct branch_mode {
729 const char *name;
730 int mode;
731};
732
733static const struct branch_mode branch_modes[] = {
734 BRANCH_OPT("u", PERF_SAMPLE_BRANCH_USER),
735 BRANCH_OPT("k", PERF_SAMPLE_BRANCH_KERNEL),
736 BRANCH_OPT("hv", PERF_SAMPLE_BRANCH_HV),
737 BRANCH_OPT("any", PERF_SAMPLE_BRANCH_ANY),
738 BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL),
739 BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN),
740 BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL),
741 BRANCH_END
742};
743
744static int
Stephane Eraniana5aabda2012-03-08 23:47:45 +0100745parse_branch_stack(const struct option *opt, const char *str, int unset)
Roberto Agostino Vitillobdfebd82012-02-09 23:21:02 +0100746{
747#define ONLY_PLM \
748 (PERF_SAMPLE_BRANCH_USER |\
749 PERF_SAMPLE_BRANCH_KERNEL |\
750 PERF_SAMPLE_BRANCH_HV)
751
752 uint64_t *mode = (uint64_t *)opt->value;
753 const struct branch_mode *br;
Stephane Eraniana5aabda2012-03-08 23:47:45 +0100754 char *s, *os = NULL, *p;
Roberto Agostino Vitillobdfebd82012-02-09 23:21:02 +0100755 int ret = -1;
756
Stephane Eraniana5aabda2012-03-08 23:47:45 +0100757 if (unset)
758 return 0;
Roberto Agostino Vitillobdfebd82012-02-09 23:21:02 +0100759
Stephane Eraniana5aabda2012-03-08 23:47:45 +0100760 /*
761 * cannot set it twice, -b + --branch-filter for instance
762 */
763 if (*mode)
Roberto Agostino Vitillobdfebd82012-02-09 23:21:02 +0100764 return -1;
765
Stephane Eraniana5aabda2012-03-08 23:47:45 +0100766 /* str may be NULL in case no arg is passed to -b */
767 if (str) {
768 /* because str is read-only */
769 s = os = strdup(str);
770 if (!s)
771 return -1;
Roberto Agostino Vitillobdfebd82012-02-09 23:21:02 +0100772
Stephane Eraniana5aabda2012-03-08 23:47:45 +0100773 for (;;) {
774 p = strchr(s, ',');
775 if (p)
776 *p = '\0';
777
778 for (br = branch_modes; br->name; br++) {
779 if (!strcasecmp(s, br->name))
780 break;
781 }
782 if (!br->name) {
783 ui__warning("unknown branch filter %s,"
784 " check man page\n", s);
785 goto error;
786 }
787
788 *mode |= br->mode;
789
790 if (!p)
Roberto Agostino Vitillobdfebd82012-02-09 23:21:02 +0100791 break;
Stephane Eraniana5aabda2012-03-08 23:47:45 +0100792
793 s = p + 1;
Roberto Agostino Vitillobdfebd82012-02-09 23:21:02 +0100794 }
Roberto Agostino Vitillobdfebd82012-02-09 23:21:02 +0100795 }
796 ret = 0;
797
Stephane Eraniana5aabda2012-03-08 23:47:45 +0100798 /* default to any branch */
Roberto Agostino Vitillobdfebd82012-02-09 23:21:02 +0100799 if ((*mode & ~ONLY_PLM) == 0) {
Stephane Eraniana5aabda2012-03-08 23:47:45 +0100800 *mode = PERF_SAMPLE_BRANCH_ANY;
Roberto Agostino Vitillobdfebd82012-02-09 23:21:02 +0100801 }
802error:
803 free(os);
804 return ret;
805}
806
Namhyung Kim95485b12012-09-28 18:32:00 +0900807#ifdef LIBUNWIND_SUPPORT
Jiri Olsa26d33022012-08-07 15:20:47 +0200808static int get_stack_size(char *str, unsigned long *_size)
809{
810 char *endptr;
811 unsigned long size;
812 unsigned long max_size = round_down(USHRT_MAX, sizeof(u64));
813
814 size = strtoul(str, &endptr, 0);
815
816 do {
817 if (*endptr)
818 break;
819
820 size = round_up(size, sizeof(u64));
821 if (!size || size > max_size)
822 break;
823
824 *_size = size;
825 return 0;
826
827 } while (0);
828
829 pr_err("callchain: Incorrect stack dump size (max %ld): %s\n",
830 max_size, str);
831 return -1;
832}
Namhyung Kim95485b12012-09-28 18:32:00 +0900833#endif /* LIBUNWIND_SUPPORT */
Jiri Olsa26d33022012-08-07 15:20:47 +0200834
Arnaldo Carvalho de Melo75d9a1082012-12-11 16:46:05 -0300835int record_parse_callchain_opt(const struct option *opt,
836 const char *arg, int unset)
Jiri Olsa26d33022012-08-07 15:20:47 +0200837{
Arnaldo Carvalho de Meloc5ff78c2012-12-11 16:16:47 -0300838 struct perf_record_opts *opts = opt->value;
Jiri Olsa26d33022012-08-07 15:20:47 +0200839 char *tok, *name, *saveptr = NULL;
840 char *buf;
841 int ret = -1;
842
843 /* --no-call-graph */
844 if (unset)
845 return 0;
846
847 /* We specified default option if none is provided. */
848 BUG_ON(!arg);
849
850 /* We need buffer that we know we can write to. */
851 buf = malloc(strlen(arg) + 1);
852 if (!buf)
853 return -ENOMEM;
854
855 strcpy(buf, arg);
856
857 tok = strtok_r((char *)buf, ",", &saveptr);
858 name = tok ? : (char *)buf;
859
860 do {
861 /* Framepointer style */
862 if (!strncmp(name, "fp", sizeof("fp"))) {
863 if (!strtok_r(NULL, ",", &saveptr)) {
Arnaldo Carvalho de Meloc5ff78c2012-12-11 16:16:47 -0300864 opts->call_graph = CALLCHAIN_FP;
Jiri Olsa26d33022012-08-07 15:20:47 +0200865 ret = 0;
866 } else
867 pr_err("callchain: No more arguments "
868 "needed for -g fp\n");
869 break;
870
Namhyung Kim95485b12012-09-28 18:32:00 +0900871#ifdef LIBUNWIND_SUPPORT
Jiri Olsa26d33022012-08-07 15:20:47 +0200872 /* Dwarf style */
873 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
Arnaldo Carvalho de Melo61eaa3b2012-10-01 15:20:58 -0300874 const unsigned long default_stack_dump_size = 8192;
875
Jiri Olsa26d33022012-08-07 15:20:47 +0200876 ret = 0;
Arnaldo Carvalho de Meloc5ff78c2012-12-11 16:16:47 -0300877 opts->call_graph = CALLCHAIN_DWARF;
878 opts->stack_dump_size = default_stack_dump_size;
Jiri Olsa26d33022012-08-07 15:20:47 +0200879
880 tok = strtok_r(NULL, ",", &saveptr);
881 if (tok) {
882 unsigned long size = 0;
883
884 ret = get_stack_size(tok, &size);
Arnaldo Carvalho de Meloc5ff78c2012-12-11 16:16:47 -0300885 opts->stack_dump_size = size;
Jiri Olsa26d33022012-08-07 15:20:47 +0200886 }
887
888 if (!ret)
889 pr_debug("callchain: stack dump size %d\n",
Arnaldo Carvalho de Meloc5ff78c2012-12-11 16:16:47 -0300890 opts->stack_dump_size);
Namhyung Kim95485b12012-09-28 18:32:00 +0900891#endif /* LIBUNWIND_SUPPORT */
Jiri Olsa26d33022012-08-07 15:20:47 +0200892 } else {
893 pr_err("callchain: Unknown -g option "
894 "value: %s\n", arg);
895 break;
896 }
897
898 } while (0);
899
900 free(buf);
901
902 if (!ret)
Arnaldo Carvalho de Meloc5ff78c2012-12-11 16:16:47 -0300903 pr_debug("callchain: type %d\n", opts->call_graph);
Jiri Olsa26d33022012-08-07 15:20:47 +0200904
905 return ret;
906}
907
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200908static const char * const record_usage[] = {
Mike Galbraith9e0967532009-05-28 16:25:34 +0200909 "perf record [<options>] [<command>]",
910 "perf record [<options>] -- <command> [<options>]",
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200911 NULL
912};
913
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200914/*
915 * XXX Ideally would be local to cmd_record() and passed to a perf_record__new
916 * because we need to have access to it in perf_record__exit, that is called
917 * after cmd_record() exits, but since record_options need to be accessible to
918 * builtin-script, leave it here.
919 *
920 * At least we don't ouch it in all the other functions here directly.
921 *
922 * Just say no to tons of global variables, sigh.
923 */
924static struct perf_record record = {
925 .opts = {
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200926 .mmap_pages = UINT_MAX,
927 .user_freq = UINT_MAX,
928 .user_interval = ULLONG_MAX,
Arnaldo Carvalho de Melo447a6012012-05-22 13:14:18 -0300929 .freq = 4000,
Namhyung Kimd1cb9fc2012-05-16 18:45:49 +0900930 .target = {
931 .uses_mmap = true,
932 },
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200933 },
934 .write_mode = WRITE_FORCE,
935 .file_new = true,
936};
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200937
Arnaldo Carvalho de Melo61eaa3b2012-10-01 15:20:58 -0300938#define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: "
939
940#ifdef LIBUNWIND_SUPPORT
Arnaldo Carvalho de Melo75d9a1082012-12-11 16:46:05 -0300941const char record_callchain_help[] = CALLCHAIN_HELP "[fp] dwarf";
Arnaldo Carvalho de Melo61eaa3b2012-10-01 15:20:58 -0300942#else
Arnaldo Carvalho de Melo75d9a1082012-12-11 16:46:05 -0300943const char record_callchain_help[] = CALLCHAIN_HELP "[fp]";
Arnaldo Carvalho de Melo61eaa3b2012-10-01 15:20:58 -0300944#endif
945
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200946/*
947 * XXX Will stay a global variable till we fix builtin-script.c to stop messing
948 * with it and switch to use the library functions in perf_evlist that came
949 * from builtin-record.c, i.e. use perf_record_opts,
950 * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
951 * using pipes, etc.
952 */
Tom Zanussibca647a2010-11-10 08:11:30 -0600953const struct option record_options[] = {
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200954 OPT_CALLBACK('e', "event", &record.evlist, "event",
Thomas Gleixner86847b62009-06-06 12:24:17 +0200955 "event selector. use 'perf list' to list available events",
Jiri Olsaf120f9d2011-07-14 11:25:32 +0200956 parse_events_option),
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200957 OPT_CALLBACK(0, "filter", &record.evlist, "filter",
Li Zefanc171b552009-10-15 11:22:07 +0800958 "event filter", parse_filter),
Namhyung Kimbea03402012-04-26 14:15:15 +0900959 OPT_STRING('p', "pid", &record.opts.target.pid, "pid",
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300960 "record events on existing process id"),
Namhyung Kimbea03402012-04-26 14:15:15 +0900961 OPT_STRING('t', "tid", &record.opts.target.tid, "tid",
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300962 "record events on existing thread id"),
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200963 OPT_INTEGER('r', "realtime", &record.realtime_prio,
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200964 "collect data with this RT SCHED_FIFO priority"),
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200965 OPT_BOOLEAN('D', "no-delay", &record.opts.no_delay,
Kirill Smelkovacac03f2011-01-12 17:59:36 +0300966 "collect data without buffering"),
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200967 OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
Frederic Weisbeckerdaac07b2009-08-13 10:27:19 +0200968 "collect raw sample records from all opened counters"),
Namhyung Kimbea03402012-04-26 14:15:15 +0900969 OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide,
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200970 "system-wide collection from all CPUs"),
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200971 OPT_BOOLEAN('A', "append", &record.append_file,
Ingo Molnarabaff322009-06-02 22:59:57 +0200972 "append to the output file to do incremental profiling"),
Namhyung Kimbea03402012-04-26 14:15:15 +0900973 OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
Stephane Eranianc45c6ea2010-05-28 12:00:01 +0200974 "list of cpus to monitor"),
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200975 OPT_BOOLEAN('f', "force", &record.force,
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200976 "overwrite existing data file (deprecated)"),
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200977 OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
978 OPT_STRING('o', "output", &record.output_name, "file",
Ingo Molnarabaff322009-06-02 22:59:57 +0200979 "output file name"),
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200980 OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit,
Stephane Eranian2e6cdf92010-05-12 10:40:01 +0200981 "child tasks do not inherit counters"),
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200982 OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
983 OPT_UINTEGER('m', "mmap-pages", &record.opts.mmap_pages,
Arnaldo Carvalho de Melo01c2d992011-11-09 09:16:26 -0200984 "number of mmap data pages"),
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200985 OPT_BOOLEAN(0, "group", &record.opts.group,
Lin Ming43bece72011-08-17 18:42:07 +0800986 "put the counters into a counter group"),
Arnaldo Carvalho de Meloc5ff78c2012-12-11 16:16:47 -0300987 OPT_CALLBACK_DEFAULT('g', "call-graph", &record.opts,
Arnaldo Carvalho de Melo75d9a1082012-12-11 16:46:05 -0300988 "mode[,dump_size]", record_callchain_help,
989 &record_parse_callchain_opt, "fp"),
Ian Munsiec0555642010-04-13 18:37:33 +1000990 OPT_INCR('v', "verbose", &verbose,
Ingo Molnar3da297a2009-06-07 17:39:02 +0200991 "be more verbose (show counter open errors, etc)"),
Arnaldo Carvalho de Melob44308f2010-10-26 15:20:09 -0200992 OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200993 OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
Peter Zijlstra649c48a2009-06-24 21:12:48 +0200994 "per thread counts"),
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200995 OPT_BOOLEAN('d', "data", &record.opts.sample_address,
Anton Blanchard4bba8282009-07-16 15:44:29 +0200996 "Sample addresses"),
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200997 OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"),
Andrew Vagin3e76ac72011-12-20 17:32:45 +0300998 OPT_BOOLEAN('P', "period", &record.opts.period, "Sample period"),
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -0200999 OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
Peter Zijlstra649c48a2009-06-24 21:12:48 +02001000 "don't sample"),
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -02001001 OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache,
Stephane Eraniana1ac1d32010-06-17 11:39:01 +02001002 "do not update the buildid cache"),
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -02001003 OPT_BOOLEAN('B', "no-buildid", &record.no_buildid,
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -02001004 "do not collect buildids in perf.data"),
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -02001005 OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
Stephane Eranian023695d2011-02-14 11:20:01 +02001006 "monitor event in cgroup name only",
1007 parse_cgroups),
Namhyung Kimbea03402012-04-26 14:15:15 +09001008 OPT_STRING('u', "uid", &record.opts.target.uid_str, "user",
1009 "user to profile"),
Stephane Eraniana5aabda2012-03-08 23:47:45 +01001010
1011 OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack,
1012 "branch any", "sample any taken branches",
1013 parse_branch_stack),
1014
1015 OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack,
1016 "branch filter mask", "branch stack filter modes",
Roberto Agostino Vitillobdfebd82012-02-09 23:21:02 +01001017 parse_branch_stack),
Ingo Molnar0e9b20b2009-05-26 09:17:18 +02001018 OPT_END()
1019};
1020
Irina Tirdea1d037ca2012-09-11 01:15:03 +03001021int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
Ingo Molnar0e9b20b2009-05-26 09:17:18 +02001022{
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -02001023 int err = -ENOMEM;
1024 struct perf_evsel *pos;
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -02001025 struct perf_evlist *evsel_list;
1026 struct perf_record *rec = &record;
Namhyung Kim16ad2ff2012-05-07 14:09:02 +09001027 char errbuf[BUFSIZ];
Ingo Molnar0e9b20b2009-05-26 09:17:18 +02001028
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -02001029 evsel_list = perf_evlist__new(NULL, NULL);
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -02001030 if (evsel_list == NULL)
1031 return -ENOMEM;
1032
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -02001033 rec->evlist = evsel_list;
1034
Tom Zanussibca647a2010-11-10 08:11:30 -06001035 argc = parse_options(argc, argv, record_options, record_usage,
Arnaldo Carvalho de Melo655000e2009-12-15 20:04:40 -02001036 PARSE_OPT_STOP_AT_NON_OPTION);
Namhyung Kimd67356e2012-05-07 14:09:03 +09001037 if (!argc && perf_target__none(&rec->opts.target))
Tom Zanussibca647a2010-11-10 08:11:30 -06001038 usage_with_options(record_usage, record_options);
Ingo Molnar0e9b20b2009-05-26 09:17:18 +02001039
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -02001040 if (rec->force && rec->append_file) {
Namhyung Kim3780f482012-05-29 13:22:57 +09001041 ui__error("Can't overwrite and append at the same time."
1042 " You need to choose between -f and -A");
Tom Zanussibca647a2010-11-10 08:11:30 -06001043 usage_with_options(record_usage, record_options);
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -02001044 } else if (rec->append_file) {
1045 rec->write_mode = WRITE_APPEND;
Frederic Weisbecker7865e812010-04-14 19:42:07 +02001046 } else {
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -02001047 rec->write_mode = WRITE_FORCE;
Frederic Weisbecker7865e812010-04-14 19:42:07 +02001048 }
1049
Namhyung Kimbea03402012-04-26 14:15:15 +09001050 if (nr_cgroups && !rec->opts.target.system_wide) {
Namhyung Kim3780f482012-05-29 13:22:57 +09001051 ui__error("cgroup monitoring only available in"
1052 " system-wide mode\n");
Stephane Eranian023695d2011-02-14 11:20:01 +02001053 usage_with_options(record_usage, record_options);
1054 }
1055
Arnaldo Carvalho de Melo655000e2009-12-15 20:04:40 -02001056 symbol__init();
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -02001057
Arnaldo Carvalho de Meloec80fde2011-05-26 09:53:51 -03001058 if (symbol_conf.kptr_restrict)
Arnaldo Carvalho de Melo646aaea2011-05-27 11:00:41 -03001059 pr_warning(
1060"WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
1061"check /proc/sys/kernel/kptr_restrict.\n\n"
1062"Samples in kernel functions may not be resolved if a suitable vmlinux\n"
1063"file is not found in the buildid cache or in the vmlinux path.\n\n"
1064"Samples in kernel modules won't be resolved at all.\n\n"
1065"If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
1066"even with a suitable vmlinux or kallsyms file.\n\n");
Arnaldo Carvalho de Meloec80fde2011-05-26 09:53:51 -03001067
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -02001068 if (rec->no_buildid_cache || rec->no_buildid)
Stephane Eraniana1ac1d32010-06-17 11:39:01 +02001069 disable_buildid_cache();
Arnaldo Carvalho de Melo655000e2009-12-15 20:04:40 -02001070
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -02001071 if (evsel_list->nr_entries == 0 &&
1072 perf_evlist__add_default(evsel_list) < 0) {
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -02001073 pr_err("Not enough memory for event selector list\n");
1074 goto out_symbol_exit;
Peter Zijlstrabbd36e52009-06-11 23:11:50 +02001075 }
Ingo Molnar0e9b20b2009-05-26 09:17:18 +02001076
Namhyung Kim16ad2ff2012-05-07 14:09:02 +09001077 err = perf_target__validate(&rec->opts.target);
1078 if (err) {
1079 perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
1080 ui__warning("%s", errbuf);
1081 }
Namhyung Kim4bd0f2d2012-04-26 14:15:18 +09001082
Namhyung Kim16ad2ff2012-05-07 14:09:02 +09001083 err = perf_target__parse_uid(&rec->opts.target);
1084 if (err) {
1085 int saved_errno = errno;
1086
1087 perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
Namhyung Kim3780f482012-05-29 13:22:57 +09001088 ui__error("%s", errbuf);
Namhyung Kim16ad2ff2012-05-07 14:09:02 +09001089
1090 err = -saved_errno;
Arnaldo Carvalho de Melo0d37aa32012-01-19 14:08:15 -02001091 goto out_free_fd;
Namhyung Kim16ad2ff2012-05-07 14:09:02 +09001092 }
Arnaldo Carvalho de Melo0d37aa32012-01-19 14:08:15 -02001093
Namhyung Kim16ad2ff2012-05-07 14:09:02 +09001094 err = -ENOMEM;
Namhyung Kimb809ac12012-04-26 14:15:19 +09001095 if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0)
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -02001096 usage_with_options(record_usage, record_options);
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -02001097
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -02001098 list_for_each_entry(pos, &evsel_list->entries, node) {
Arnaldo Carvalho de Melo7289f832012-06-12 12:34:58 -03001099 if (perf_header__push_event(pos->attr.config, perf_evsel__name(pos)))
Arnaldo Carvalho de Meload7f4e32011-01-17 18:28:13 -02001100 goto out_free_fd;
Zhang, Yanmind6d901c2010-03-18 11:36:05 -03001101 }
Arnaldo Carvalho de Melo5c581042011-01-11 22:30:02 -02001102
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -02001103 if (rec->opts.user_interval != ULLONG_MAX)
1104 rec->opts.default_interval = rec->opts.user_interval;
1105 if (rec->opts.user_freq != UINT_MAX)
1106 rec->opts.freq = rec->opts.user_freq;
Frederic Weisbeckerf9212812010-04-14 22:09:02 +02001107
Mike Galbraith7e4ff9e2009-10-12 07:56:03 +02001108 /*
1109 * User specified count overrides default frequency.
1110 */
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -02001111 if (rec->opts.default_interval)
1112 rec->opts.freq = 0;
1113 else if (rec->opts.freq) {
1114 rec->opts.default_interval = rec->opts.freq;
Mike Galbraith7e4ff9e2009-10-12 07:56:03 +02001115 } else {
Namhyung Kim3780f482012-05-29 13:22:57 +09001116 ui__error("frequency and count are zero, aborting\n");
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -03001117 err = -EINVAL;
Arnaldo Carvalho de Melo5c581042011-01-11 22:30:02 -02001118 goto out_free_fd;
Mike Galbraith7e4ff9e2009-10-12 07:56:03 +02001119 }
1120
Arnaldo Carvalho de Melod20deb62011-11-25 08:19:45 -02001121 err = __cmd_record(&record, argc, argv);
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -03001122out_free_fd:
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -02001123 perf_evlist__delete_maps(evsel_list);
Arnaldo Carvalho de Melod65a4582010-07-30 18:31:28 -03001124out_symbol_exit:
1125 symbol__exit();
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -03001126 return err;
Ingo Molnar0e9b20b2009-05-26 09:17:18 +02001127}