blob: dd6467872f6081615bb1fae7a544e2e8bf201067 [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 Melo8d063672009-11-04 18:50:43 -020025#include "util/symbol.h"
Paul Mackerrasa12b51c2010-03-10 20:36:09 +110026#include "util/cpumap.h"
Arnaldo Carvalho de Melofd782602011-01-18 15:15:24 -020027#include "util/thread_map.h"
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020028
Peter Zijlstra97124d52009-06-02 15:52:24 +020029#include <unistd.h>
Peter Zijlstrade9ac072009-04-08 15:01:31 +020030#include <sched.h>
Arnaldo Carvalho de Meloa41794c2010-05-18 18:29:23 -030031#include <sys/mman.h>
Peter Zijlstrade9ac072009-04-08 15:01:31 +020032
Frederic Weisbecker7865e812010-04-14 19:42:07 +020033enum write_mode_t {
34 WRITE_FORCE,
35 WRITE_APPEND
36};
37
Stephane Eranian3de29ca2010-05-17 12:20:43 -030038static u64 user_interval = ULLONG_MAX;
39static u64 default_interval = 0;
Ingo Molnara21ca2c2009-06-06 09:58:57 +020040
Peter Zijlstrade9ac072009-04-08 15:01:31 +020041static unsigned int page_size;
Frederic Weisbecker800cd252011-03-31 03:35:24 +020042static unsigned int mmap_pages = UINT_MAX;
Frederic Weisbeckerf9212812010-04-14 22:09:02 +020043static unsigned int user_freq = UINT_MAX;
Ingo Molnar42e59d72009-10-06 15:14:21 +020044static int freq = 1000;
Peter Zijlstrade9ac072009-04-08 15:01:31 +020045static int output;
Tom Zanussi529870e2010-04-01 23:59:16 -050046static int pipe_output = 0;
Franck Bui-Huud7065ad2011-01-16 17:14:45 +010047static const char *output_name = NULL;
Lin Ming43bece72011-08-17 18:42:07 +080048static bool group = false;
Arnaldo Carvalho de Melo19679362010-05-17 15:39:16 -030049static int realtime_prio = 0;
Kirill Smelkovacac03f2011-01-12 17:59:36 +030050static bool nodelay = false;
Ian Munsiec0555642010-04-13 18:37:33 +100051static bool raw_samples = false;
Arnaldo Carvalho de Melo9c90a612010-12-02 10:25:28 -020052static bool sample_id_all_avail = true;
Ian Munsiec0555642010-04-13 18:37:33 +100053static bool system_wide = false;
Ingo Molnar42e59d72009-10-06 15:14:21 +020054static pid_t target_pid = -1;
Zhang, Yanmind6d901c2010-03-18 11:36:05 -030055static pid_t target_tid = -1;
Ingo Molnar42e59d72009-10-06 15:14:21 +020056static pid_t child_pid = -1;
Stephane Eranian2e6cdf92010-05-12 10:40:01 +020057static bool no_inherit = false;
Frederic Weisbecker7865e812010-04-14 19:42:07 +020058static enum write_mode_t write_mode = WRITE_FORCE;
Ian Munsiec0555642010-04-13 18:37:33 +100059static bool call_graph = false;
60static bool inherit_stat = false;
61static bool no_samples = false;
62static bool sample_address = false;
Arnaldo Carvalho de Melo9c90a612010-12-02 10:25:28 -020063static bool sample_time = false;
Stephane Eraniana1ac1d32010-06-17 11:39:01 +020064static bool no_buildid = false;
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -020065static bool no_buildid_cache = false;
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -020066static struct perf_evlist *evsel_list;
Peter Zijlstrade9ac072009-04-08 15:01:31 +020067
Ingo Molnar42e59d72009-10-06 15:14:21 +020068static long samples = 0;
Ingo Molnar42e59d72009-10-06 15:14:21 +020069static u64 bytes_written = 0;
Ingo Molnara21ca2c2009-06-06 09:58:57 +020070
Ingo Molnar42e59d72009-10-06 15:14:21 +020071static int file_new = 1;
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -020072static off_t post_processing_offset;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020073
Arnaldo Carvalho de Melo94c744b2009-12-11 21:24:02 -020074static struct perf_session *session;
Stephane Eranianc45c6ea2010-05-28 12:00:01 +020075static const char *cpu_list;
Andi Kleen33e49ea2011-09-15 14:31:40 -070076static const char *progname;
Peter Zijlstraf5970552009-06-18 23:22:55 +020077
Tom Zanussi92155452010-04-01 23:59:21 -050078static void advance_output(size_t size)
79{
80 bytes_written += size;
81}
82
Peter Zijlstraf5970552009-06-18 23:22:55 +020083static void write_output(void *buf, size_t size)
84{
85 while (size) {
86 int ret = write(output, buf, size);
87
88 if (ret < 0)
89 die("failed to write");
90
91 size -= ret;
92 buf += ret;
93
94 bytes_written += ret;
95 }
96}
97
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -020098static int process_synthesized_event(union perf_event *event,
Arnaldo Carvalho de Melo8d50e5b2011-01-29 13:02:00 -020099 struct perf_sample *sample __used,
Arnaldo Carvalho de Melod8f66242009-12-13 19:50:24 -0200100 struct perf_session *self __used)
Arnaldo Carvalho de Melo234fbbf2009-10-26 19:23:18 -0200101{
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -0200102 write_output(event, event->header.size);
Arnaldo Carvalho de Melo234fbbf2009-10-26 19:23:18 -0200103 return 0;
104}
105
Arnaldo Carvalho de Melo744bd8a2011-01-12 17:07:28 -0200106static void mmap_read(struct perf_mmap *md)
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200107{
Arnaldo Carvalho de Melo744bd8a2011-01-12 17:07:28 -0200108 unsigned int head = perf_mmap__read_head(md);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200109 unsigned int old = md->prev;
110 unsigned char *data = md->base + page_size;
111 unsigned long size;
112 void *buf;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200113
Arnaldo Carvalho de Melodc820092011-01-28 14:49:19 -0200114 if (old == head)
115 return;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200116
Arnaldo Carvalho de Melodc820092011-01-28 14:49:19 -0200117 samples++;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200118
119 size = head - old;
120
121 if ((old & md->mask) + size != (head & md->mask)) {
122 buf = &data[old & md->mask];
123 size = md->mask + 1 - (old & md->mask);
124 old += size;
Ingo Molnar021e9f42009-06-03 19:27:19 +0200125
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -0200126 write_output(buf, size);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200127 }
128
129 buf = &data[old & md->mask];
130 size = head - old;
131 old += size;
Ingo Molnar021e9f42009-06-03 19:27:19 +0200132
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -0200133 write_output(buf, size);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200134
135 md->prev = old;
Arnaldo Carvalho de Melo115d2d82011-01-12 17:11:53 -0200136 perf_mmap__write_tail(md, old);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200137}
138
139static volatile int done = 0;
Peter Zijlstraf7b7c262009-06-10 15:55:59 +0200140static volatile int signr = -1;
Andi Kleen33e49ea2011-09-15 14:31:40 -0700141static volatile int child_finished = 0;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200142
Peter Zijlstra16c8a102009-05-05 17:50:27 +0200143static void sig_handler(int sig)
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200144{
Andi Kleen33e49ea2011-09-15 14:31:40 -0700145 if (sig == SIGCHLD)
146 child_finished = 1;
147
Peter Zijlstra16c8a102009-05-05 17:50:27 +0200148 done = 1;
Peter Zijlstraf7b7c262009-06-10 15:55:59 +0200149 signr = sig;
150}
151
152static void sig_atexit(void)
153{
Andi Kleen33e49ea2011-09-15 14:31:40 -0700154 int status;
155
156 if (child_pid > 0) {
157 if (!child_finished)
158 kill(child_pid, SIGTERM);
159
160 wait(&status);
161 if (WIFSIGNALED(status))
162 psignal(WTERMSIG(status), progname);
163 }
Chris Wilson933da832009-10-04 01:35:01 +0100164
Arnaldo Carvalho de Melo18483b82010-12-06 15:13:38 -0200165 if (signr == -1 || signr == SIGUSR1)
Peter Zijlstraf7b7c262009-06-10 15:55:59 +0200166 return;
167
168 signal(signr, SIG_DFL);
169 kill(getpid(), signr);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200170}
171
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200172static void config_attr(struct perf_evsel *evsel, struct perf_evlist *evlist)
173{
174 struct perf_event_attr *attr = &evsel->attr;
175 int track = !evsel->idx; /* only the first counter needs these */
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +0200176
David Ahern764e16a2011-08-25 10:17:55 -0600177 attr->disabled = 1;
Arnaldo Carvalho de Melo5d2cd902011-04-14 11:20:14 -0300178 attr->inherit = !no_inherit;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +0200179 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
180 PERF_FORMAT_TOTAL_TIME_RUNNING |
181 PERF_FORMAT_ID;
Peter Zijlstra16c8a102009-05-05 17:50:27 +0200182
Frederic Weisbecker3a9f1312009-08-13 10:27:18 +0200183 attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
Ingo Molnar3efa1cc92009-06-14 15:04:15 +0200184
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200185 if (evlist->nr_entries > 1)
Eric B Munson8907fd62010-03-05 12:51:05 -0300186 attr->sample_type |= PERF_SAMPLE_ID;
187
Frederic Weisbeckerf9212812010-04-14 22:09:02 +0200188 /*
189 * We default some events to a 1 default interval. But keep
190 * it a weak assumption overridable by the user.
191 */
192 if (!attr->sample_period || (user_freq != UINT_MAX &&
Stephane Eranian3de29ca2010-05-17 12:20:43 -0300193 user_interval != ULLONG_MAX)) {
Frederic Weisbeckerf9212812010-04-14 22:09:02 +0200194 if (freq) {
195 attr->sample_type |= PERF_SAMPLE_PERIOD;
196 attr->freq = 1;
197 attr->sample_freq = freq;
198 } else {
199 attr->sample_period = default_interval;
200 }
Ingo Molnar1dba15e2009-06-05 18:37:22 +0200201 }
Ingo Molnar3efa1cc92009-06-14 15:04:15 +0200202
Peter Zijlstra649c48a2009-06-24 21:12:48 +0200203 if (no_samples)
204 attr->sample_freq = 0;
205
206 if (inherit_stat)
207 attr->inherit_stat = 1;
208
Eric B Munson3af9e852010-05-18 15:30:49 +0100209 if (sample_address) {
Anton Blanchard4bba8282009-07-16 15:44:29 +0200210 attr->sample_type |= PERF_SAMPLE_ADDR;
Eric B Munson3af9e852010-05-18 15:30:49 +0100211 attr->mmap_data = track;
212 }
Anton Blanchard4bba8282009-07-16 15:44:29 +0200213
Ingo Molnar3efa1cc92009-06-14 15:04:15 +0200214 if (call_graph)
215 attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
216
Arun Sharmaf60f3592010-06-04 11:27:10 -0300217 if (system_wide)
218 attr->sample_type |= PERF_SAMPLE_CPU;
219
Arnaldo Carvalho de Meloa43d3f02010-12-25 12:12:25 -0200220 if (sample_id_all_avail &&
221 (sample_time || system_wide || !no_inherit || cpu_list))
Arnaldo Carvalho de Melo9c90a612010-12-02 10:25:28 -0200222 attr->sample_type |= PERF_SAMPLE_TIME;
223
Ingo Molnarcd6feee2009-09-02 20:20:38 +0200224 if (raw_samples) {
Ingo Molnar6ddf2592009-09-03 12:00:22 +0200225 attr->sample_type |= PERF_SAMPLE_TIME;
Frederic Weisbeckerdaac07b2009-08-13 10:27:19 +0200226 attr->sample_type |= PERF_SAMPLE_RAW;
Ingo Molnarcd6feee2009-09-02 20:20:38 +0200227 attr->sample_type |= PERF_SAMPLE_CPU;
228 }
Frederic Weisbeckerf413cdb2009-08-07 01:25:54 +0200229
Kirill Smelkovacac03f2011-01-12 17:59:36 +0300230 if (nodelay) {
231 attr->watermark = 0;
232 attr->wakeup_events = 1;
233 }
234
Ingo Molnara21ca2c2009-06-06 09:58:57 +0200235 attr->mmap = track;
236 attr->comm = track;
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200237
Stephane Eranian2e6cdf92010-05-12 10:40:01 +0200238 if (target_pid == -1 && target_tid == -1 && !system_wide) {
Zhang, Yanmin46be6042010-03-18 11:36:04 -0300239 attr->disabled = 1;
Eric B Munsonbedbfde2010-03-15 11:46:57 -0300240 attr->enable_on_exec = 1;
Zhang, Yanmin46be6042010-03-18 11:36:04 -0300241 }
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200242}
243
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300244static bool perf_evlist__equal(struct perf_evlist *evlist,
245 struct perf_evlist *other)
246{
247 struct perf_evsel *pos, *pair;
248
249 if (evlist->nr_entries != other->nr_entries)
250 return false;
251
252 pair = list_entry(other->entries.next, struct perf_evsel, node);
253
254 list_for_each_entry(pos, &evlist->entries, node) {
255 if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0))
256 return false;
257 pair = list_entry(pair->node.next, struct perf_evsel, node);
258 }
259
260 return true;
261}
262
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200263static void open_counters(struct perf_evlist *evlist)
264{
265 struct perf_evsel *pos;
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200266
Arnaldo Carvalho de Melo5d2cd902011-04-14 11:20:14 -0300267 if (evlist->cpus->map[0] < 0)
268 no_inherit = true;
269
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200270 list_for_each_entry(pos, &evlist->entries, node) {
271 struct perf_event_attr *attr = &pos->attr;
272 /*
273 * Check if parse_single_tracepoint_event has already asked for
274 * PERF_SAMPLE_TIME.
275 *
276 * XXX this is kludgy but short term fix for problems introduced by
277 * eac23d1c that broke 'perf script' by having different sample_types
278 * when using multiple tracepoint events when we use a perf binary
279 * that tries to use sample_id_all on an older kernel.
280 *
281 * We need to move counter creation to perf_session, support
282 * different sample_types, etc.
283 */
284 bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
285
286 config_attr(pos, evlist);
Arnaldo Carvalho de Melo9c90a612010-12-02 10:25:28 -0200287retry_sample_id:
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200288 attr->sample_id_all = sample_id_all_avail ? 1 : 0;
Ingo Molnar3da297a2009-06-07 17:39:02 +0200289try_again:
Arnaldo Carvalho de Melo5d2cd902011-04-14 11:20:14 -0300290 if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group) < 0) {
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300291 int err = errno;
Ingo Molnarf250c0302009-06-05 13:18:41 +0200292
Arnaldo Carvalho de Meloc286c412011-03-28 09:50:11 -0300293 if (err == EPERM || err == EACCES) {
294 ui__warning_paranoid();
295 exit(EXIT_FAILURE);
296 } else if (err == ENODEV && cpu_list) {
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300297 die("No such device - did you specify"
298 " an out-of-range profile CPU?\n");
Arnaldo Carvalho de Melo9c90a612010-12-02 10:25:28 -0200299 } else if (err == EINVAL && sample_id_all_avail) {
300 /*
301 * Old kernel, no attr->sample_id_type_all field
302 */
303 sample_id_all_avail = false;
Arnaldo Carvalho de Meloa43d3f02010-12-25 12:12:25 -0200304 if (!sample_time && !raw_samples && !time_needed)
Ian Munsieeac23d12010-12-09 16:33:53 +1100305 attr->sample_type &= ~PERF_SAMPLE_TIME;
306
Arnaldo Carvalho de Melo9c90a612010-12-02 10:25:28 -0200307 goto retry_sample_id;
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300308 }
Ingo Molnar3da297a2009-06-07 17:39:02 +0200309
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300310 /*
311 * If it's cycles then fall back to hrtimer
312 * based cpu-clock-tick sw counter, which
313 * is always available even if no PMU support:
314 */
315 if (attr->type == PERF_TYPE_HARDWARE
316 && attr->config == PERF_COUNT_HW_CPU_CYCLES) {
Ingo Molnar3da297a2009-06-07 17:39:02 +0200317
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300318 if (verbose)
David Ahernca6a4252011-03-25 13:11:11 -0600319 ui__warning("The cycles event is not supported, "
320 "trying to fall back to cpu-clock-ticks\n");
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300321 attr->type = PERF_TYPE_SOFTWARE;
322 attr->config = PERF_COUNT_SW_CPU_CLOCK;
323 goto try_again;
324 }
David Ahernca6a4252011-03-25 13:11:11 -0600325
326 if (err == ENOENT) {
327 ui__warning("The %s event is not supported.\n",
328 event_name(pos));
329 exit(EXIT_FAILURE);
330 }
331
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300332 printf("\n");
Corey Ashfordd9cf8372010-11-19 17:37:24 -0800333 error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n",
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200334 err, strerror(err));
Simon Kaempfleinbfd45112009-11-16 15:25:53 +1000335
336#if defined(__i386__) || defined(__x86_64__)
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300337 if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP)
338 die("No hardware sampling interrupt available."
339 " No APIC? If so then you can boot the kernel"
340 " with the \"lapic\" boot parameter to"
341 " force-enable it.\n");
Simon Kaempfleinbfd45112009-11-16 15:25:53 +1000342#endif
343
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300344 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300345 }
Li Zefanc171b552009-10-15 11:22:07 +0800346 }
Arnaldo Carvalho de Meloa43d3f02010-12-25 12:12:25 -0200347
Frederic Weisbecker0a102472011-02-26 04:51:54 +0100348 if (perf_evlist__set_filters(evlist)) {
349 error("failed to set filter with %d (%s)\n", errno,
350 strerror(errno));
351 exit(-1);
352 }
353
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200354 if (perf_evlist__mmap(evlist, mmap_pages, false) < 0)
Arnaldo Carvalho de Melo0a27d7f2011-01-14 15:50:51 -0200355 die("failed to mmap with %d (%s)\n", errno, strerror(errno));
356
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300357 if (file_new)
358 session->evlist = evlist;
359 else {
360 if (!perf_evlist__equal(session->evlist, evlist)) {
361 fprintf(stderr, "incompatible append\n");
362 exit(-1);
363 }
364 }
365
366 perf_session__update_sample_type(session);
Peter Zijlstra16c8a102009-05-05 17:50:27 +0200367}
368
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -0200369static int process_buildids(void)
370{
371 u64 size = lseek(output, 0, SEEK_CUR);
372
Arnaldo Carvalho de Melo9f591fd2010-03-11 15:53:11 -0300373 if (size == 0)
374 return 0;
375
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -0200376 session->fd = output;
377 return __perf_session__process_events(session, post_processing_offset,
378 size - post_processing_offset,
379 size, &build_id__mark_dso_hit_ops);
380}
381
Peter Zijlstraf5970552009-06-18 23:22:55 +0200382static void atexit_header(void)
383{
Tom Zanussic7929e42010-04-01 23:59:22 -0500384 if (!pipe_output) {
385 session->header.data_size += bytes_written;
Peter Zijlstraf5970552009-06-18 23:22:55 +0200386
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -0200387 if (!no_buildid)
388 process_buildids();
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300389 perf_session__write_header(session, evsel_list, output, true);
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300390 perf_session__delete(session);
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200391 perf_evlist__delete(evsel_list);
Arnaldo Carvalho de Melod65a4582010-07-30 18:31:28 -0300392 symbol__exit();
Tom Zanussic7929e42010-04-01 23:59:22 -0500393 }
Peter Zijlstraf5970552009-06-18 23:22:55 +0200394}
395
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200396static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800397{
398 int err;
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -0300399 struct perf_session *psession = data;
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800400
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -0300401 if (machine__is_host(machine))
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800402 return;
403
404 /*
405 *As for guest kernel when processing subcommand record&report,
406 *we arrange module mmap prior to guest kernel mmap and trigger
407 *a preload dso because default guest module symbols are loaded
408 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
409 *method is used to avoid symbol missing when the first addr is
410 *in module instead of in guest kernel.
411 */
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200412 err = perf_event__synthesize_modules(process_synthesized_event,
413 psession, machine);
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800414 if (err < 0)
415 pr_err("Couldn't record guest kernel [%d]'s reference"
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -0300416 " relocation symbol.\n", machine->pid);
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800417
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800418 /*
419 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
420 * have no _text sometimes.
421 */
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200422 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
423 psession, machine, "_text");
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800424 if (err < 0)
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200425 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
426 psession, machine,
427 "_stext");
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800428 if (err < 0)
429 pr_err("Couldn't record guest kernel [%d]'s reference"
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -0300430 " relocation symbol.\n", machine->pid);
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800431}
432
Frederic Weisbecker98402802010-05-02 22:05:29 +0200433static struct perf_event_header finished_round_event = {
434 .size = sizeof(struct perf_event_header),
435 .type = PERF_RECORD_FINISHED_ROUND,
436};
437
438static void mmap_read_all(void)
439{
Peter Zijlstra0e2e63d2010-05-20 14:45:26 +0200440 int i;
Frederic Weisbecker98402802010-05-02 22:05:29 +0200441
Arnaldo Carvalho de Meloaece9482011-05-15 09:39:00 -0300442 for (i = 0; i < evsel_list->nr_mmaps; i++) {
Arnaldo Carvalho de Melo0a27d7f2011-01-14 15:50:51 -0200443 if (evsel_list->mmap[i].base)
444 mmap_read(&evsel_list->mmap[i]);
Frederic Weisbecker98402802010-05-02 22:05:29 +0200445 }
446
447 if (perf_header__has_feat(&session->header, HEADER_TRACE_INFO))
448 write_output(&finished_round_event, sizeof(finished_round_event));
449}
450
Arnaldo Carvalho de Melod4db3f12009-12-27 21:36:57 -0200451static int __cmd_record(int argc, const char **argv)
Peter Zijlstra16c8a102009-05-05 17:50:27 +0200452{
Peter Zijlstra97124d52009-06-02 15:52:24 +0200453 struct stat st;
Ingo Molnarabaff322009-06-02 22:59:57 +0200454 int flags;
Arnaldo Carvalho de Melo4dc0a042009-11-19 14:55:55 -0200455 int err;
Peter Zijlstra8b412662009-09-17 19:59:05 +0200456 unsigned long waking = 0;
Peter Zijlstra856e9662009-12-16 17:55:55 +0100457 int child_ready_pipe[2], go_pipe[2];
Zhang, Yanmin46be6042010-03-18 11:36:04 -0300458 const bool forks = argc > 0;
Peter Zijlstra856e9662009-12-16 17:55:55 +0100459 char buf;
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -0300460 struct machine *machine;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200461
Andi Kleen33e49ea2011-09-15 14:31:40 -0700462 progname = argv[0];
463
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200464 page_size = sysconf(_SC_PAGE_SIZE);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200465
Peter Zijlstraf5970552009-06-18 23:22:55 +0200466 atexit(sig_atexit);
467 signal(SIGCHLD, sig_handler);
468 signal(SIGINT, sig_handler);
Arnaldo Carvalho de Melo18483b82010-12-06 15:13:38 -0200469 signal(SIGUSR1, sig_handler);
Peter Zijlstraf5970552009-06-18 23:22:55 +0200470
Arnaldo Carvalho de Melod4db3f12009-12-27 21:36:57 -0200471 if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
Peter Zijlstra856e9662009-12-16 17:55:55 +0100472 perror("failed to create pipes");
473 exit(-1);
474 }
475
Franck Bui-Huud7065ad2011-01-16 17:14:45 +0100476 if (!output_name) {
477 if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
478 pipe_output = 1;
479 else
480 output_name = "perf.data";
481 }
482 if (output_name) {
483 if (!strcmp(output_name, "-"))
484 pipe_output = 1;
485 else if (!stat(output_name, &st) && st.st_size) {
486 if (write_mode == WRITE_FORCE) {
487 char oldname[PATH_MAX];
488 snprintf(oldname, sizeof(oldname), "%s.old",
489 output_name);
490 unlink(oldname);
491 rename(output_name, oldname);
492 }
493 } else if (write_mode == WRITE_APPEND) {
494 write_mode = WRITE_FORCE;
Pierre Habouzit266e0e22009-08-07 14:16:01 +0200495 }
Peter Zijlstra97124d52009-06-02 15:52:24 +0200496 }
497
Xiao Guangrongf887f302010-02-04 16:46:42 +0800498 flags = O_CREAT|O_RDWR;
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200499 if (write_mode == WRITE_APPEND)
Peter Zijlstraf5970552009-06-18 23:22:55 +0200500 file_new = 0;
Ingo Molnarabaff322009-06-02 22:59:57 +0200501 else
502 flags |= O_TRUNC;
503
Tom Zanussi529870e2010-04-01 23:59:16 -0500504 if (pipe_output)
505 output = STDOUT_FILENO;
506 else
507 output = open(output_name, flags, S_IRUSR | S_IWUSR);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200508 if (output < 0) {
509 perror("failed to create output file");
510 exit(-1);
511 }
512
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200513 session = perf_session__new(output_name, O_WRONLY,
Ian Munsie21ef97f2010-12-10 14:09:16 +1100514 write_mode == WRITE_FORCE, false, NULL);
Arnaldo Carvalho de Melo94c744b2009-12-11 21:24:02 -0200515 if (session == NULL) {
Arnaldo Carvalho de Meloa9a70bb2009-11-17 01:18:11 -0200516 pr_err("Not enough memory for reading perf file header\n");
517 return -1;
518 }
519
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -0200520 if (!no_buildid)
521 perf_header__set_feat(&session->header, HEADER_BUILD_ID);
522
Arnaldo Carvalho de Melo4dc0a042009-11-19 14:55:55 -0200523 if (!file_new) {
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300524 err = perf_session__read_header(session, output);
Arnaldo Carvalho de Melo4dc0a042009-11-19 14:55:55 -0200525 if (err < 0)
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300526 goto out_delete_session;
Arnaldo Carvalho de Melo4dc0a042009-11-19 14:55:55 -0200527 }
528
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200529 if (have_tracepoints(&evsel_list->entries))
Arnaldo Carvalho de Melo94c744b2009-12-11 21:24:02 -0200530 perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
Frederic Weisbecker03456a12009-10-06 23:36:47 +0200531
Frederic Weisbecker800cd252011-03-31 03:35:24 +0200532 /* 512 kiB: default amount of unprivileged mlocked memory */
533 if (mmap_pages == UINT_MAX)
534 mmap_pages = (512 * 1024) / page_size;
535
Arnaldo Carvalho de Melod4db3f12009-12-27 21:36:57 -0200536 if (forks) {
Zhang, Yanmin46be6042010-03-18 11:36:04 -0300537 child_pid = fork();
Borislav Petkov2fb750e2010-05-31 23:18:18 +0200538 if (child_pid < 0) {
Peter Zijlstra856e9662009-12-16 17:55:55 +0100539 perror("failed to fork");
540 exit(-1);
Jens Axboe0a5ac842009-08-12 11:18:01 +0200541 }
Peter Zijlstra856e9662009-12-16 17:55:55 +0100542
Zhang, Yanmin46be6042010-03-18 11:36:04 -0300543 if (!child_pid) {
Tom Zanussi529870e2010-04-01 23:59:16 -0500544 if (pipe_output)
545 dup2(2, 1);
Peter Zijlstra856e9662009-12-16 17:55:55 +0100546 close(child_ready_pipe[0]);
547 close(go_pipe[1]);
548 fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
549
550 /*
551 * Do a dummy execvp to get the PLT entry resolved,
552 * so we avoid the resolver overhead on the real
553 * execvp call.
554 */
555 execvp("", (char **)argv);
556
557 /*
558 * Tell the parent we're ready to go
559 */
560 close(child_ready_pipe[1]);
561
562 /*
563 * Wait until the parent tells us to go.
564 */
565 if (read(go_pipe[0], &buf, 1) == -1)
566 perror("unable to read pipe");
567
568 execvp(argv[0], (char **)argv);
569
570 perror(argv[0]);
Arnaldo Carvalho de Melo18483b82010-12-06 15:13:38 -0200571 kill(getppid(), SIGUSR1);
Peter Zijlstra856e9662009-12-16 17:55:55 +0100572 exit(-1);
573 }
574
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300575 if (!system_wide && target_tid == -1 && target_pid == -1)
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200576 evsel_list->threads->map[0] = child_pid;
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300577
Peter Zijlstra856e9662009-12-16 17:55:55 +0100578 close(child_ready_pipe[1]);
579 close(go_pipe[0]);
580 /*
581 * wait for child to settle
582 */
583 if (read(child_ready_pipe[0], &buf, 1) == -1) {
584 perror("unable to read pipe");
585 exit(-1);
586 }
587 close(child_ready_pipe[0]);
588 }
589
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200590 open_counters(evsel_list);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200591
Arnaldo Carvalho de Melo712a4b62011-02-17 12:18:42 -0200592 /*
593 * perf_session__delete(session) will be called at atexit_header()
594 */
595 atexit(atexit_header);
596
Tom Zanussi529870e2010-04-01 23:59:16 -0500597 if (pipe_output) {
598 err = perf_header__write_pipe(output);
599 if (err < 0)
600 return err;
601 } else if (file_new) {
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300602 err = perf_session__write_header(session, evsel_list,
603 output, false);
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -0200604 if (err < 0)
605 return err;
606 }
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +0200607
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -0200608 post_processing_offset = lseek(output, 0, SEEK_CUR);
609
Tom Zanussi2c46dbb2010-04-01 23:59:19 -0500610 if (pipe_output) {
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300611 err = perf_session__synthesize_attrs(session,
612 process_synthesized_event);
Tom Zanussi2c46dbb2010-04-01 23:59:19 -0500613 if (err < 0) {
614 pr_err("Couldn't synthesize attrs.\n");
615 return err;
616 }
Tom Zanussicd19a032010-04-01 23:59:20 -0500617
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200618 err = perf_event__synthesize_event_types(process_synthesized_event,
619 session);
Tom Zanussicd19a032010-04-01 23:59:20 -0500620 if (err < 0) {
621 pr_err("Couldn't synthesize event_types.\n");
622 return err;
623 }
Tom Zanussi92155452010-04-01 23:59:21 -0500624
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200625 if (have_tracepoints(&evsel_list->entries)) {
Tom Zanussi63e0c772010-05-03 00:14:48 -0500626 /*
627 * FIXME err <= 0 here actually means that
628 * there were no tracepoints so its not really
629 * an error, just that we don't need to
630 * synthesize anything. We really have to
631 * return this more properly and also
632 * propagate errors that now are calling die()
633 */
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200634 err = perf_event__synthesize_tracing_data(output, evsel_list,
635 process_synthesized_event,
636 session);
Tom Zanussi63e0c772010-05-03 00:14:48 -0500637 if (err <= 0) {
638 pr_err("Couldn't record tracing data.\n");
639 return err;
640 }
Arnaldo Carvalho de Melo2c9faa02010-05-02 13:37:24 -0300641 advance_output(err);
Tom Zanussi63e0c772010-05-03 00:14:48 -0500642 }
Tom Zanussi2c46dbb2010-04-01 23:59:19 -0500643 }
644
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -0300645 machine = perf_session__find_host_machine(session);
646 if (!machine) {
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800647 pr_err("Couldn't find native kernel information.\n");
648 return -1;
649 }
650
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200651 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
652 session, machine, "_text");
Arnaldo Carvalho de Melo70162132010-03-30 18:27:39 -0300653 if (err < 0)
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200654 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
655 session, machine, "_stext");
Arnaldo Carvalho de Meloc1a3a4b2010-11-22 14:01:55 -0200656 if (err < 0)
657 pr_err("Couldn't record kernel reference relocation symbol\n"
658 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
659 "Check /proc/kallsyms permission or run as root.\n");
Arnaldo Carvalho de Melo56b03f32010-01-05 16:50:31 -0200660
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200661 err = perf_event__synthesize_modules(process_synthesized_event,
662 session, machine);
Arnaldo Carvalho de Meloc1a3a4b2010-11-22 14:01:55 -0200663 if (err < 0)
664 pr_err("Couldn't record kernel module information.\n"
665 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
666 "Check /proc/modules permission or run as root.\n");
667
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800668 if (perf_guest)
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200669 perf_session__process_machines(session,
670 perf_event__synthesize_guest_os);
Arnaldo Carvalho de Melob7cece72010-01-13 13:22:17 -0200671
Stephane Eraniancf103a12010-06-16 20:59:01 +0200672 if (!system_wide)
Arnaldo Carvalho de Melo7c940c12011-02-11 11:45:54 -0200673 perf_event__synthesize_thread_map(evsel_list->threads,
674 process_synthesized_event,
675 session);
Arnaldo Carvalho de Melo234fbbf2009-10-26 19:23:18 -0200676 else
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200677 perf_event__synthesize_threads(process_synthesized_event,
678 session);
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +0200679
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200680 if (realtime_prio) {
681 struct sched_param param;
682
683 param.sched_priority = realtime_prio;
684 if (sched_setscheduler(0, SCHED_FIFO, &param)) {
Arnaldo Carvalho de Melo6beba7a2009-10-21 17:34:06 -0200685 pr_err("Could not set realtime priority.\n");
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200686 exit(-1);
687 }
688 }
689
David Ahern764e16a2011-08-25 10:17:55 -0600690 perf_evlist__enable(evsel_list);
691
Peter Zijlstra856e9662009-12-16 17:55:55 +0100692 /*
693 * Let the child rip
694 */
Arnaldo Carvalho de Melod4db3f12009-12-27 21:36:57 -0200695 if (forks)
696 close(go_pipe[1]);
Peter Zijlstra856e9662009-12-16 17:55:55 +0100697
Peter Zijlstra649c48a2009-06-24 21:12:48 +0200698 for (;;) {
Ingo Molnar2debbc82009-06-05 14:29:10 +0200699 int hits = samples;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200700
Frederic Weisbecker98402802010-05-02 22:05:29 +0200701 mmap_read_all();
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200702
Peter Zijlstra649c48a2009-06-24 21:12:48 +0200703 if (hits == samples) {
704 if (done)
705 break;
Arnaldo Carvalho de Melo5c581042011-01-11 22:30:02 -0200706 err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1);
Peter Zijlstra8b412662009-09-17 19:59:05 +0200707 waking++;
708 }
709
Arnaldo Carvalho de Melo4152ab32011-07-25 11:06:19 -0300710 if (done)
711 perf_evlist__disable(evsel_list);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200712 }
713
Arnaldo Carvalho de Melo18483b82010-12-06 15:13:38 -0200714 if (quiet || signr == SIGUSR1)
Arnaldo Carvalho de Melob44308f2010-10-26 15:20:09 -0200715 return 0;
716
Peter Zijlstra8b412662009-09-17 19:59:05 +0200717 fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
718
Ingo Molnar021e9f42009-06-03 19:27:19 +0200719 /*
720 * Approximate RIP event size: 24 bytes.
721 */
722 fprintf(stderr,
Arnaldo Carvalho de Melo9486aa32011-01-22 20:37:02 -0200723 "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
Ingo Molnar021e9f42009-06-03 19:27:19 +0200724 (double)bytes_written / 1024.0 / 1024.0,
725 output_name,
726 bytes_written / 24);
Ingo Molnaraddc2782009-06-02 23:43:11 +0200727
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200728 return 0;
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300729
730out_delete_session:
731 perf_session__delete(session);
732 return err;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200733}
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200734
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200735static const char * const record_usage[] = {
Mike Galbraith9e096752009-05-28 16:25:34 +0200736 "perf record [<options>] [<command>]",
737 "perf record [<options>] -- <command> [<options>]",
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200738 NULL
739};
740
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200741static bool force, append_file;
742
Tom Zanussibca647a2010-11-10 08:11:30 -0600743const struct option record_options[] = {
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200744 OPT_CALLBACK('e', "event", &evsel_list, "event",
Thomas Gleixner86847b62009-06-06 12:24:17 +0200745 "event selector. use 'perf list' to list available events",
Jiri Olsaf120f9d2011-07-14 11:25:32 +0200746 parse_events_option),
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200747 OPT_CALLBACK(0, "filter", &evsel_list, "filter",
Li Zefanc171b552009-10-15 11:22:07 +0800748 "event filter", parse_filter),
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200749 OPT_INTEGER('p', "pid", &target_pid,
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300750 "record events on existing process id"),
751 OPT_INTEGER('t', "tid", &target_tid,
752 "record events on existing thread id"),
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200753 OPT_INTEGER('r', "realtime", &realtime_prio,
754 "collect data with this RT SCHED_FIFO priority"),
Kirill Smelkovacac03f2011-01-12 17:59:36 +0300755 OPT_BOOLEAN('D', "no-delay", &nodelay,
756 "collect data without buffering"),
Frederic Weisbeckerdaac07b2009-08-13 10:27:19 +0200757 OPT_BOOLEAN('R', "raw-samples", &raw_samples,
758 "collect raw sample records from all opened counters"),
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200759 OPT_BOOLEAN('a', "all-cpus", &system_wide,
760 "system-wide collection from all CPUs"),
Ingo Molnarabaff322009-06-02 22:59:57 +0200761 OPT_BOOLEAN('A', "append", &append_file,
762 "append to the output file to do incremental profiling"),
Stephane Eranianc45c6ea2010-05-28 12:00:01 +0200763 OPT_STRING('C', "cpu", &cpu_list, "cpu",
764 "list of cpus to monitor"),
Peter Zijlstra97124d52009-06-02 15:52:24 +0200765 OPT_BOOLEAN('f', "force", &force,
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200766 "overwrite existing data file (deprecated)"),
Stephane Eranian3de29ca2010-05-17 12:20:43 -0300767 OPT_U64('c', "count", &user_interval, "event period to sample"),
Ingo Molnarabaff322009-06-02 22:59:57 +0200768 OPT_STRING('o', "output", &output_name, "file",
769 "output file name"),
Stephane Eranian2e6cdf92010-05-12 10:40:01 +0200770 OPT_BOOLEAN('i', "no-inherit", &no_inherit,
771 "child tasks do not inherit counters"),
Arnaldo Carvalho de Melo19679362010-05-17 15:39:16 -0300772 OPT_UINTEGER('F', "freq", &user_freq, "profile at this frequency"),
773 OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"),
Lin Ming43bece72011-08-17 18:42:07 +0800774 OPT_BOOLEAN(0, "group", &group,
775 "put the counters into a counter group"),
Ingo Molnar3efa1cc92009-06-14 15:04:15 +0200776 OPT_BOOLEAN('g', "call-graph", &call_graph,
777 "do call-graph (stack chain/backtrace) recording"),
Ian Munsiec0555642010-04-13 18:37:33 +1000778 OPT_INCR('v', "verbose", &verbose,
Ingo Molnar3da297a2009-06-07 17:39:02 +0200779 "be more verbose (show counter open errors, etc)"),
Arnaldo Carvalho de Melob44308f2010-10-26 15:20:09 -0200780 OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
Peter Zijlstra649c48a2009-06-24 21:12:48 +0200781 OPT_BOOLEAN('s', "stat", &inherit_stat,
782 "per thread counts"),
Anton Blanchard4bba8282009-07-16 15:44:29 +0200783 OPT_BOOLEAN('d', "data", &sample_address,
784 "Sample addresses"),
Arnaldo Carvalho de Melo9c90a612010-12-02 10:25:28 -0200785 OPT_BOOLEAN('T', "timestamp", &sample_time, "Sample timestamps"),
Peter Zijlstra649c48a2009-06-24 21:12:48 +0200786 OPT_BOOLEAN('n', "no-samples", &no_samples,
787 "don't sample"),
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -0200788 OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid_cache,
Stephane Eraniana1ac1d32010-06-17 11:39:01 +0200789 "do not update the buildid cache"),
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -0200790 OPT_BOOLEAN('B', "no-buildid", &no_buildid,
791 "do not collect buildids in perf.data"),
Stephane Eranian023695d2011-02-14 11:20:01 +0200792 OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
793 "monitor event in cgroup name only",
794 parse_cgroups),
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200795 OPT_END()
796};
797
Ingo Molnarf37a2912009-07-01 12:37:06 +0200798int cmd_record(int argc, const char **argv, const char *prefix __used)
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200799{
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200800 int err = -ENOMEM;
801 struct perf_evsel *pos;
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200802
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200803 evsel_list = perf_evlist__new(NULL, NULL);
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200804 if (evsel_list == NULL)
805 return -ENOMEM;
806
Tom Zanussibca647a2010-11-10 08:11:30 -0600807 argc = parse_options(argc, argv, record_options, record_usage,
Arnaldo Carvalho de Melo655000e2009-12-15 20:04:40 -0200808 PARSE_OPT_STOP_AT_NON_OPTION);
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300809 if (!argc && target_pid == -1 && target_tid == -1 &&
Stephane Eranianc45c6ea2010-05-28 12:00:01 +0200810 !system_wide && !cpu_list)
Tom Zanussibca647a2010-11-10 08:11:30 -0600811 usage_with_options(record_usage, record_options);
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200812
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200813 if (force && append_file) {
814 fprintf(stderr, "Can't overwrite and append at the same time."
815 " You need to choose between -f and -A");
Tom Zanussibca647a2010-11-10 08:11:30 -0600816 usage_with_options(record_usage, record_options);
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200817 } else if (append_file) {
818 write_mode = WRITE_APPEND;
819 } else {
820 write_mode = WRITE_FORCE;
821 }
822
Stephane Eranian023695d2011-02-14 11:20:01 +0200823 if (nr_cgroups && !system_wide) {
824 fprintf(stderr, "cgroup monitoring only available in"
825 " system-wide mode\n");
826 usage_with_options(record_usage, record_options);
827 }
828
Arnaldo Carvalho de Melo655000e2009-12-15 20:04:40 -0200829 symbol__init();
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -0200830
Arnaldo Carvalho de Meloec80fde2011-05-26 09:53:51 -0300831 if (symbol_conf.kptr_restrict)
Arnaldo Carvalho de Melo646aaea2011-05-27 11:00:41 -0300832 pr_warning(
833"WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
834"check /proc/sys/kernel/kptr_restrict.\n\n"
835"Samples in kernel functions may not be resolved if a suitable vmlinux\n"
836"file is not found in the buildid cache or in the vmlinux path.\n\n"
837"Samples in kernel modules won't be resolved at all.\n\n"
838"If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
839"even with a suitable vmlinux or kallsyms file.\n\n");
Arnaldo Carvalho de Meloec80fde2011-05-26 09:53:51 -0300840
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -0200841 if (no_buildid_cache || no_buildid)
Stephane Eraniana1ac1d32010-06-17 11:39:01 +0200842 disable_buildid_cache();
Arnaldo Carvalho de Melo655000e2009-12-15 20:04:40 -0200843
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200844 if (evsel_list->nr_entries == 0 &&
845 perf_evlist__add_default(evsel_list) < 0) {
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200846 pr_err("Not enough memory for event selector list\n");
847 goto out_symbol_exit;
Peter Zijlstrabbd36e52009-06-11 23:11:50 +0200848 }
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200849
Arnaldo Carvalho de Melo5c98d462011-01-03 17:53:33 -0200850 if (target_pid != -1)
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300851 target_tid = target_pid;
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300852
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200853 if (perf_evlist__create_maps(evsel_list, target_pid,
854 target_tid, cpu_list) < 0)
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200855 usage_with_options(record_usage, record_options);
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200856
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200857 list_for_each_entry(pos, &evsel_list->entries, node) {
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200858 if (perf_evsel__alloc_fd(pos, evsel_list->cpus->nr,
859 evsel_list->threads->nr) < 0)
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200860 goto out_free_fd;
Arnaldo Carvalho de Meload7f4e32011-01-17 18:28:13 -0200861 if (perf_header__push_event(pos->attr.config, event_name(pos)))
862 goto out_free_fd;
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300863 }
Arnaldo Carvalho de Melo5c581042011-01-11 22:30:02 -0200864
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200865 if (perf_evlist__alloc_pollfd(evsel_list) < 0)
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300866 goto out_free_fd;
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300867
Stephane Eranian3de29ca2010-05-17 12:20:43 -0300868 if (user_interval != ULLONG_MAX)
Frederic Weisbeckerf9212812010-04-14 22:09:02 +0200869 default_interval = user_interval;
870 if (user_freq != UINT_MAX)
871 freq = user_freq;
872
Mike Galbraith7e4ff9e2009-10-12 07:56:03 +0200873 /*
874 * User specified count overrides default frequency.
875 */
876 if (default_interval)
877 freq = 0;
878 else if (freq) {
879 default_interval = freq;
880 } else {
881 fprintf(stderr, "frequency and count are zero, aborting\n");
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300882 err = -EINVAL;
Arnaldo Carvalho de Melo5c581042011-01-11 22:30:02 -0200883 goto out_free_fd;
Mike Galbraith7e4ff9e2009-10-12 07:56:03 +0200884 }
885
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300886 err = __cmd_record(argc, argv);
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300887out_free_fd:
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200888 perf_evlist__delete_maps(evsel_list);
Arnaldo Carvalho de Melod65a4582010-07-30 18:31:28 -0300889out_symbol_exit:
890 symbol__exit();
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300891 return err;
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200892}