blob: f82480fa7f27988c48ba90e80e014b43de745f0e [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 Ahern764e16a32011-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
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200532 perf_header__set_feat(&session->header, HEADER_HOSTNAME);
533 perf_header__set_feat(&session->header, HEADER_OSRELEASE);
534 perf_header__set_feat(&session->header, HEADER_ARCH);
535 perf_header__set_feat(&session->header, HEADER_CPUDESC);
536 perf_header__set_feat(&session->header, HEADER_NRCPUS);
537 perf_header__set_feat(&session->header, HEADER_EVENT_DESC);
538 perf_header__set_feat(&session->header, HEADER_CMDLINE);
539 perf_header__set_feat(&session->header, HEADER_VERSION);
540 perf_header__set_feat(&session->header, HEADER_CPU_TOPOLOGY);
541 perf_header__set_feat(&session->header, HEADER_TOTAL_MEM);
542 perf_header__set_feat(&session->header, HEADER_NUMA_TOPOLOGY);
543 perf_header__set_feat(&session->header, HEADER_CPUID);
544
Frederic Weisbecker800cd252011-03-31 03:35:24 +0200545 /* 512 kiB: default amount of unprivileged mlocked memory */
546 if (mmap_pages == UINT_MAX)
547 mmap_pages = (512 * 1024) / page_size;
548
Arnaldo Carvalho de Melod4db3f12009-12-27 21:36:57 -0200549 if (forks) {
Zhang, Yanmin46be6042010-03-18 11:36:04 -0300550 child_pid = fork();
Borislav Petkov2fb750e2010-05-31 23:18:18 +0200551 if (child_pid < 0) {
Peter Zijlstra856e9662009-12-16 17:55:55 +0100552 perror("failed to fork");
553 exit(-1);
Jens Axboe0a5ac842009-08-12 11:18:01 +0200554 }
Peter Zijlstra856e9662009-12-16 17:55:55 +0100555
Zhang, Yanmin46be6042010-03-18 11:36:04 -0300556 if (!child_pid) {
Tom Zanussi529870e2010-04-01 23:59:16 -0500557 if (pipe_output)
558 dup2(2, 1);
Peter Zijlstra856e9662009-12-16 17:55:55 +0100559 close(child_ready_pipe[0]);
560 close(go_pipe[1]);
561 fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
562
563 /*
564 * Do a dummy execvp to get the PLT entry resolved,
565 * so we avoid the resolver overhead on the real
566 * execvp call.
567 */
568 execvp("", (char **)argv);
569
570 /*
571 * Tell the parent we're ready to go
572 */
573 close(child_ready_pipe[1]);
574
575 /*
576 * Wait until the parent tells us to go.
577 */
578 if (read(go_pipe[0], &buf, 1) == -1)
579 perror("unable to read pipe");
580
581 execvp(argv[0], (char **)argv);
582
583 perror(argv[0]);
Arnaldo Carvalho de Melo18483b82010-12-06 15:13:38 -0200584 kill(getppid(), SIGUSR1);
Peter Zijlstra856e9662009-12-16 17:55:55 +0100585 exit(-1);
586 }
587
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300588 if (!system_wide && target_tid == -1 && target_pid == -1)
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200589 evsel_list->threads->map[0] = child_pid;
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300590
Peter Zijlstra856e9662009-12-16 17:55:55 +0100591 close(child_ready_pipe[1]);
592 close(go_pipe[0]);
593 /*
594 * wait for child to settle
595 */
596 if (read(child_ready_pipe[0], &buf, 1) == -1) {
597 perror("unable to read pipe");
598 exit(-1);
599 }
600 close(child_ready_pipe[0]);
601 }
602
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200603 open_counters(evsel_list);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200604
Arnaldo Carvalho de Melo712a4b62011-02-17 12:18:42 -0200605 /*
606 * perf_session__delete(session) will be called at atexit_header()
607 */
608 atexit(atexit_header);
609
Tom Zanussi529870e2010-04-01 23:59:16 -0500610 if (pipe_output) {
611 err = perf_header__write_pipe(output);
612 if (err < 0)
613 return err;
614 } else if (file_new) {
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300615 err = perf_session__write_header(session, evsel_list,
616 output, false);
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -0200617 if (err < 0)
618 return err;
619 }
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +0200620
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -0200621 post_processing_offset = lseek(output, 0, SEEK_CUR);
622
Tom Zanussi2c46dbb2010-04-01 23:59:19 -0500623 if (pipe_output) {
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300624 err = perf_session__synthesize_attrs(session,
625 process_synthesized_event);
Tom Zanussi2c46dbb2010-04-01 23:59:19 -0500626 if (err < 0) {
627 pr_err("Couldn't synthesize attrs.\n");
628 return err;
629 }
Tom Zanussicd19a032010-04-01 23:59:20 -0500630
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200631 err = perf_event__synthesize_event_types(process_synthesized_event,
632 session);
Tom Zanussicd19a032010-04-01 23:59:20 -0500633 if (err < 0) {
634 pr_err("Couldn't synthesize event_types.\n");
635 return err;
636 }
Tom Zanussi92155452010-04-01 23:59:21 -0500637
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200638 if (have_tracepoints(&evsel_list->entries)) {
Tom Zanussi63e0c772010-05-03 00:14:48 -0500639 /*
640 * FIXME err <= 0 here actually means that
641 * there were no tracepoints so its not really
642 * an error, just that we don't need to
643 * synthesize anything. We really have to
644 * return this more properly and also
645 * propagate errors that now are calling die()
646 */
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200647 err = perf_event__synthesize_tracing_data(output, evsel_list,
648 process_synthesized_event,
649 session);
Tom Zanussi63e0c772010-05-03 00:14:48 -0500650 if (err <= 0) {
651 pr_err("Couldn't record tracing data.\n");
652 return err;
653 }
Arnaldo Carvalho de Melo2c9faa02010-05-02 13:37:24 -0300654 advance_output(err);
Tom Zanussi63e0c772010-05-03 00:14:48 -0500655 }
Tom Zanussi2c46dbb2010-04-01 23:59:19 -0500656 }
657
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -0300658 machine = perf_session__find_host_machine(session);
659 if (!machine) {
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800660 pr_err("Couldn't find native kernel information.\n");
661 return -1;
662 }
663
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200664 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
665 session, machine, "_text");
Arnaldo Carvalho de Melo70162132010-03-30 18:27:39 -0300666 if (err < 0)
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200667 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
668 session, machine, "_stext");
Arnaldo Carvalho de Meloc1a3a4b2010-11-22 14:01:55 -0200669 if (err < 0)
670 pr_err("Couldn't record kernel reference relocation symbol\n"
671 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
672 "Check /proc/kallsyms permission or run as root.\n");
Arnaldo Carvalho de Melo56b03f32010-01-05 16:50:31 -0200673
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200674 err = perf_event__synthesize_modules(process_synthesized_event,
675 session, machine);
Arnaldo Carvalho de Meloc1a3a4b2010-11-22 14:01:55 -0200676 if (err < 0)
677 pr_err("Couldn't record kernel module information.\n"
678 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
679 "Check /proc/modules permission or run as root.\n");
680
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800681 if (perf_guest)
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200682 perf_session__process_machines(session,
683 perf_event__synthesize_guest_os);
Arnaldo Carvalho de Melob7cece72010-01-13 13:22:17 -0200684
Stephane Eraniancf103a12010-06-16 20:59:01 +0200685 if (!system_wide)
Arnaldo Carvalho de Melo7c940c12011-02-11 11:45:54 -0200686 perf_event__synthesize_thread_map(evsel_list->threads,
687 process_synthesized_event,
688 session);
Arnaldo Carvalho de Melo234fbbf2009-10-26 19:23:18 -0200689 else
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200690 perf_event__synthesize_threads(process_synthesized_event,
691 session);
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +0200692
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200693 if (realtime_prio) {
694 struct sched_param param;
695
696 param.sched_priority = realtime_prio;
697 if (sched_setscheduler(0, SCHED_FIFO, &param)) {
Arnaldo Carvalho de Melo6beba7a2009-10-21 17:34:06 -0200698 pr_err("Could not set realtime priority.\n");
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200699 exit(-1);
700 }
701 }
702
David Ahern764e16a32011-08-25 10:17:55 -0600703 perf_evlist__enable(evsel_list);
704
Peter Zijlstra856e9662009-12-16 17:55:55 +0100705 /*
706 * Let the child rip
707 */
Arnaldo Carvalho de Melod4db3f12009-12-27 21:36:57 -0200708 if (forks)
709 close(go_pipe[1]);
Peter Zijlstra856e9662009-12-16 17:55:55 +0100710
Peter Zijlstra649c48a2009-06-24 21:12:48 +0200711 for (;;) {
Ingo Molnar2debbc82009-06-05 14:29:10 +0200712 int hits = samples;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200713
Frederic Weisbecker98402802010-05-02 22:05:29 +0200714 mmap_read_all();
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200715
Peter Zijlstra649c48a2009-06-24 21:12:48 +0200716 if (hits == samples) {
717 if (done)
718 break;
Arnaldo Carvalho de Melo5c581042011-01-11 22:30:02 -0200719 err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1);
Peter Zijlstra8b412662009-09-17 19:59:05 +0200720 waking++;
721 }
722
Arnaldo Carvalho de Melo4152ab32011-07-25 11:06:19 -0300723 if (done)
724 perf_evlist__disable(evsel_list);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200725 }
726
Arnaldo Carvalho de Melo18483b82010-12-06 15:13:38 -0200727 if (quiet || signr == SIGUSR1)
Arnaldo Carvalho de Melob44308f2010-10-26 15:20:09 -0200728 return 0;
729
Peter Zijlstra8b412662009-09-17 19:59:05 +0200730 fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
731
Ingo Molnar021e9f42009-06-03 19:27:19 +0200732 /*
733 * Approximate RIP event size: 24 bytes.
734 */
735 fprintf(stderr,
Arnaldo Carvalho de Melo9486aa32011-01-22 20:37:02 -0200736 "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
Ingo Molnar021e9f42009-06-03 19:27:19 +0200737 (double)bytes_written / 1024.0 / 1024.0,
738 output_name,
739 bytes_written / 24);
Ingo Molnaraddc2782009-06-02 23:43:11 +0200740
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200741 return 0;
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300742
743out_delete_session:
744 perf_session__delete(session);
745 return err;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200746}
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200747
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200748static const char * const record_usage[] = {
Mike Galbraith9e0967532009-05-28 16:25:34 +0200749 "perf record [<options>] [<command>]",
750 "perf record [<options>] -- <command> [<options>]",
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200751 NULL
752};
753
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200754static bool force, append_file;
755
Tom Zanussibca647a2010-11-10 08:11:30 -0600756const struct option record_options[] = {
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200757 OPT_CALLBACK('e', "event", &evsel_list, "event",
Thomas Gleixner86847b62009-06-06 12:24:17 +0200758 "event selector. use 'perf list' to list available events",
Jiri Olsaf120f9d2011-07-14 11:25:32 +0200759 parse_events_option),
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200760 OPT_CALLBACK(0, "filter", &evsel_list, "filter",
Li Zefanc171b552009-10-15 11:22:07 +0800761 "event filter", parse_filter),
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200762 OPT_INTEGER('p', "pid", &target_pid,
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300763 "record events on existing process id"),
764 OPT_INTEGER('t', "tid", &target_tid,
765 "record events on existing thread id"),
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200766 OPT_INTEGER('r', "realtime", &realtime_prio,
767 "collect data with this RT SCHED_FIFO priority"),
Kirill Smelkovacac03f2011-01-12 17:59:36 +0300768 OPT_BOOLEAN('D', "no-delay", &nodelay,
769 "collect data without buffering"),
Frederic Weisbeckerdaac07b2009-08-13 10:27:19 +0200770 OPT_BOOLEAN('R', "raw-samples", &raw_samples,
771 "collect raw sample records from all opened counters"),
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200772 OPT_BOOLEAN('a', "all-cpus", &system_wide,
773 "system-wide collection from all CPUs"),
Ingo Molnarabaff322009-06-02 22:59:57 +0200774 OPT_BOOLEAN('A', "append", &append_file,
775 "append to the output file to do incremental profiling"),
Stephane Eranianc45c6ea2010-05-28 12:00:01 +0200776 OPT_STRING('C', "cpu", &cpu_list, "cpu",
777 "list of cpus to monitor"),
Peter Zijlstra97124d52009-06-02 15:52:24 +0200778 OPT_BOOLEAN('f', "force", &force,
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200779 "overwrite existing data file (deprecated)"),
Stephane Eranian3de29ca2010-05-17 12:20:43 -0300780 OPT_U64('c', "count", &user_interval, "event period to sample"),
Ingo Molnarabaff322009-06-02 22:59:57 +0200781 OPT_STRING('o', "output", &output_name, "file",
782 "output file name"),
Stephane Eranian2e6cdf92010-05-12 10:40:01 +0200783 OPT_BOOLEAN('i', "no-inherit", &no_inherit,
784 "child tasks do not inherit counters"),
Arnaldo Carvalho de Melo19679362010-05-17 15:39:16 -0300785 OPT_UINTEGER('F', "freq", &user_freq, "profile at this frequency"),
786 OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"),
Lin Ming43bece72011-08-17 18:42:07 +0800787 OPT_BOOLEAN(0, "group", &group,
788 "put the counters into a counter group"),
Ingo Molnar3efa1cc92009-06-14 15:04:15 +0200789 OPT_BOOLEAN('g', "call-graph", &call_graph,
790 "do call-graph (stack chain/backtrace) recording"),
Ian Munsiec0555642010-04-13 18:37:33 +1000791 OPT_INCR('v', "verbose", &verbose,
Ingo Molnar3da297a2009-06-07 17:39:02 +0200792 "be more verbose (show counter open errors, etc)"),
Arnaldo Carvalho de Melob44308f2010-10-26 15:20:09 -0200793 OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
Peter Zijlstra649c48a2009-06-24 21:12:48 +0200794 OPT_BOOLEAN('s', "stat", &inherit_stat,
795 "per thread counts"),
Anton Blanchard4bba8282009-07-16 15:44:29 +0200796 OPT_BOOLEAN('d', "data", &sample_address,
797 "Sample addresses"),
Arnaldo Carvalho de Melo9c90a612010-12-02 10:25:28 -0200798 OPT_BOOLEAN('T', "timestamp", &sample_time, "Sample timestamps"),
Peter Zijlstra649c48a2009-06-24 21:12:48 +0200799 OPT_BOOLEAN('n', "no-samples", &no_samples,
800 "don't sample"),
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -0200801 OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid_cache,
Stephane Eraniana1ac1d32010-06-17 11:39:01 +0200802 "do not update the buildid cache"),
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -0200803 OPT_BOOLEAN('B', "no-buildid", &no_buildid,
804 "do not collect buildids in perf.data"),
Stephane Eranian023695d2011-02-14 11:20:01 +0200805 OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
806 "monitor event in cgroup name only",
807 parse_cgroups),
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200808 OPT_END()
809};
810
Ingo Molnarf37a2912009-07-01 12:37:06 +0200811int cmd_record(int argc, const char **argv, const char *prefix __used)
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200812{
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200813 int err = -ENOMEM;
814 struct perf_evsel *pos;
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200815
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200816 perf_header__set_cmdline(argc, argv);
817
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200818 evsel_list = perf_evlist__new(NULL, NULL);
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200819 if (evsel_list == NULL)
820 return -ENOMEM;
821
Tom Zanussibca647a2010-11-10 08:11:30 -0600822 argc = parse_options(argc, argv, record_options, record_usage,
Arnaldo Carvalho de Melo655000e2009-12-15 20:04:40 -0200823 PARSE_OPT_STOP_AT_NON_OPTION);
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300824 if (!argc && target_pid == -1 && target_tid == -1 &&
Stephane Eranianc45c6ea2010-05-28 12:00:01 +0200825 !system_wide && !cpu_list)
Tom Zanussibca647a2010-11-10 08:11:30 -0600826 usage_with_options(record_usage, record_options);
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200827
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200828 if (force && append_file) {
829 fprintf(stderr, "Can't overwrite and append at the same time."
830 " You need to choose between -f and -A");
Tom Zanussibca647a2010-11-10 08:11:30 -0600831 usage_with_options(record_usage, record_options);
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200832 } else if (append_file) {
833 write_mode = WRITE_APPEND;
834 } else {
835 write_mode = WRITE_FORCE;
836 }
837
Stephane Eranian023695d2011-02-14 11:20:01 +0200838 if (nr_cgroups && !system_wide) {
839 fprintf(stderr, "cgroup monitoring only available in"
840 " system-wide mode\n");
841 usage_with_options(record_usage, record_options);
842 }
843
Arnaldo Carvalho de Melo655000e2009-12-15 20:04:40 -0200844 symbol__init();
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -0200845
Arnaldo Carvalho de Meloec80fde2011-05-26 09:53:51 -0300846 if (symbol_conf.kptr_restrict)
Arnaldo Carvalho de Melo646aaea2011-05-27 11:00:41 -0300847 pr_warning(
848"WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
849"check /proc/sys/kernel/kptr_restrict.\n\n"
850"Samples in kernel functions may not be resolved if a suitable vmlinux\n"
851"file is not found in the buildid cache or in the vmlinux path.\n\n"
852"Samples in kernel modules won't be resolved at all.\n\n"
853"If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
854"even with a suitable vmlinux or kallsyms file.\n\n");
Arnaldo Carvalho de Meloec80fde2011-05-26 09:53:51 -0300855
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -0200856 if (no_buildid_cache || no_buildid)
Stephane Eraniana1ac1d32010-06-17 11:39:01 +0200857 disable_buildid_cache();
Arnaldo Carvalho de Melo655000e2009-12-15 20:04:40 -0200858
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200859 if (evsel_list->nr_entries == 0 &&
860 perf_evlist__add_default(evsel_list) < 0) {
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200861 pr_err("Not enough memory for event selector list\n");
862 goto out_symbol_exit;
Peter Zijlstrabbd36e52009-06-11 23:11:50 +0200863 }
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200864
Arnaldo Carvalho de Melo5c98d4662011-01-03 17:53:33 -0200865 if (target_pid != -1)
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300866 target_tid = target_pid;
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300867
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200868 if (perf_evlist__create_maps(evsel_list, target_pid,
869 target_tid, cpu_list) < 0)
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200870 usage_with_options(record_usage, record_options);
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200871
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200872 list_for_each_entry(pos, &evsel_list->entries, node) {
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200873 if (perf_evsel__alloc_fd(pos, evsel_list->cpus->nr,
874 evsel_list->threads->nr) < 0)
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200875 goto out_free_fd;
Arnaldo Carvalho de Meload7f4e32011-01-17 18:28:13 -0200876 if (perf_header__push_event(pos->attr.config, event_name(pos)))
877 goto out_free_fd;
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300878 }
Arnaldo Carvalho de Melo5c581042011-01-11 22:30:02 -0200879
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200880 if (perf_evlist__alloc_pollfd(evsel_list) < 0)
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300881 goto out_free_fd;
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300882
Stephane Eranian3de29ca2010-05-17 12:20:43 -0300883 if (user_interval != ULLONG_MAX)
Frederic Weisbeckerf9212812010-04-14 22:09:02 +0200884 default_interval = user_interval;
885 if (user_freq != UINT_MAX)
886 freq = user_freq;
887
Mike Galbraith7e4ff9e2009-10-12 07:56:03 +0200888 /*
889 * User specified count overrides default frequency.
890 */
891 if (default_interval)
892 freq = 0;
893 else if (freq) {
894 default_interval = freq;
895 } else {
896 fprintf(stderr, "frequency and count are zero, aborting\n");
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300897 err = -EINVAL;
Arnaldo Carvalho de Melo5c581042011-01-11 22:30:02 -0200898 goto out_free_fd;
Mike Galbraith7e4ff9e2009-10-12 07:56:03 +0200899 }
900
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300901 err = __cmd_record(argc, argv);
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300902out_free_fd:
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200903 perf_evlist__delete_maps(evsel_list);
Arnaldo Carvalho de Melod65a4582010-07-30 18:31:28 -0300904out_symbol_exit:
905 symbol__exit();
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300906 return err;
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200907}