blob: 40088a5848d6d487c7eaff35af7062c69df0162c [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 Weisbecker8f28827a2009-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{
Arnaldo Carvalho de Melo727ab042011-10-25 10:42:19 -0200265 struct perf_evsel *pos, *first;
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 Melo727ab042011-10-25 10:42:19 -0200270 first = list_entry(evlist->entries.next, struct perf_evsel, node);
271
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200272 list_for_each_entry(pos, &evlist->entries, node) {
273 struct perf_event_attr *attr = &pos->attr;
Arnaldo Carvalho de Melo727ab042011-10-25 10:42:19 -0200274 struct xyarray *group_fd = NULL;
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200275 /*
276 * Check if parse_single_tracepoint_event has already asked for
277 * PERF_SAMPLE_TIME.
278 *
279 * XXX this is kludgy but short term fix for problems introduced by
280 * eac23d1c that broke 'perf script' by having different sample_types
281 * when using multiple tracepoint events when we use a perf binary
282 * that tries to use sample_id_all on an older kernel.
283 *
284 * We need to move counter creation to perf_session, support
285 * different sample_types, etc.
286 */
287 bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
288
Arnaldo Carvalho de Melo727ab042011-10-25 10:42:19 -0200289 if (group && pos != first)
290 group_fd = first->fd;
291
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200292 config_attr(pos, evlist);
Arnaldo Carvalho de Melo9c90a612010-12-02 10:25:28 -0200293retry_sample_id:
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200294 attr->sample_id_all = sample_id_all_avail ? 1 : 0;
Ingo Molnar3da297a2009-06-07 17:39:02 +0200295try_again:
Arnaldo Carvalho de Melo727ab042011-10-25 10:42:19 -0200296 if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group,
297 group_fd) < 0) {
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300298 int err = errno;
Ingo Molnarf250c0302009-06-05 13:18:41 +0200299
Arnaldo Carvalho de Meloc286c412011-03-28 09:50:11 -0300300 if (err == EPERM || err == EACCES) {
301 ui__warning_paranoid();
302 exit(EXIT_FAILURE);
303 } else if (err == ENODEV && cpu_list) {
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300304 die("No such device - did you specify"
305 " an out-of-range profile CPU?\n");
Arnaldo Carvalho de Melo9c90a612010-12-02 10:25:28 -0200306 } else if (err == EINVAL && sample_id_all_avail) {
307 /*
308 * Old kernel, no attr->sample_id_type_all field
309 */
310 sample_id_all_avail = false;
Arnaldo Carvalho de Meloa43d3f02010-12-25 12:12:25 -0200311 if (!sample_time && !raw_samples && !time_needed)
Ian Munsieeac23d12010-12-09 16:33:53 +1100312 attr->sample_type &= ~PERF_SAMPLE_TIME;
313
Arnaldo Carvalho de Melo9c90a612010-12-02 10:25:28 -0200314 goto retry_sample_id;
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300315 }
Ingo Molnar3da297a2009-06-07 17:39:02 +0200316
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300317 /*
318 * If it's cycles then fall back to hrtimer
319 * based cpu-clock-tick sw counter, which
320 * is always available even if no PMU support:
321 */
322 if (attr->type == PERF_TYPE_HARDWARE
323 && attr->config == PERF_COUNT_HW_CPU_CYCLES) {
Ingo Molnar3da297a2009-06-07 17:39:02 +0200324
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300325 if (verbose)
David Ahernca6a4252011-03-25 13:11:11 -0600326 ui__warning("The cycles event is not supported, "
327 "trying to fall back to cpu-clock-ticks\n");
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300328 attr->type = PERF_TYPE_SOFTWARE;
329 attr->config = PERF_COUNT_SW_CPU_CLOCK;
330 goto try_again;
331 }
David Ahernca6a4252011-03-25 13:11:11 -0600332
333 if (err == ENOENT) {
334 ui__warning("The %s event is not supported.\n",
335 event_name(pos));
336 exit(EXIT_FAILURE);
337 }
338
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300339 printf("\n");
Corey Ashfordd9cf8372010-11-19 17:37:24 -0800340 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 -0200341 err, strerror(err));
Simon Kaempfleinbfd45112009-11-16 15:25:53 +1000342
343#if defined(__i386__) || defined(__x86_64__)
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300344 if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP)
345 die("No hardware sampling interrupt available."
346 " No APIC? If so then you can boot the kernel"
347 " with the \"lapic\" boot parameter to"
348 " force-enable it.\n");
Simon Kaempfleinbfd45112009-11-16 15:25:53 +1000349#endif
350
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300351 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300352 }
Li Zefanc171b552009-10-15 11:22:07 +0800353 }
Arnaldo Carvalho de Meloa43d3f02010-12-25 12:12:25 -0200354
Frederic Weisbecker0a102472011-02-26 04:51:54 +0100355 if (perf_evlist__set_filters(evlist)) {
356 error("failed to set filter with %d (%s)\n", errno,
357 strerror(errno));
358 exit(-1);
359 }
360
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200361 if (perf_evlist__mmap(evlist, mmap_pages, false) < 0)
Arnaldo Carvalho de Melo0a27d7f2011-01-14 15:50:51 -0200362 die("failed to mmap with %d (%s)\n", errno, strerror(errno));
363
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300364 if (file_new)
365 session->evlist = evlist;
366 else {
367 if (!perf_evlist__equal(session->evlist, evlist)) {
368 fprintf(stderr, "incompatible append\n");
369 exit(-1);
370 }
371 }
372
373 perf_session__update_sample_type(session);
Peter Zijlstra16c8a102009-05-05 17:50:27 +0200374}
375
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -0200376static int process_buildids(void)
377{
378 u64 size = lseek(output, 0, SEEK_CUR);
379
Arnaldo Carvalho de Melo9f591fd2010-03-11 15:53:11 -0300380 if (size == 0)
381 return 0;
382
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -0200383 session->fd = output;
384 return __perf_session__process_events(session, post_processing_offset,
385 size - post_processing_offset,
386 size, &build_id__mark_dso_hit_ops);
387}
388
Peter Zijlstraf5970552009-06-18 23:22:55 +0200389static void atexit_header(void)
390{
Tom Zanussic7929e42010-04-01 23:59:22 -0500391 if (!pipe_output) {
392 session->header.data_size += bytes_written;
Peter Zijlstraf5970552009-06-18 23:22:55 +0200393
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -0200394 if (!no_buildid)
395 process_buildids();
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300396 perf_session__write_header(session, evsel_list, output, true);
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300397 perf_session__delete(session);
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200398 perf_evlist__delete(evsel_list);
Arnaldo Carvalho de Melod65a4582010-07-30 18:31:28 -0300399 symbol__exit();
Tom Zanussic7929e42010-04-01 23:59:22 -0500400 }
Peter Zijlstraf5970552009-06-18 23:22:55 +0200401}
402
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200403static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800404{
405 int err;
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -0300406 struct perf_session *psession = data;
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800407
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -0300408 if (machine__is_host(machine))
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800409 return;
410
411 /*
412 *As for guest kernel when processing subcommand record&report,
413 *we arrange module mmap prior to guest kernel mmap and trigger
414 *a preload dso because default guest module symbols are loaded
415 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
416 *method is used to avoid symbol missing when the first addr is
417 *in module instead of in guest kernel.
418 */
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200419 err = perf_event__synthesize_modules(process_synthesized_event,
420 psession, machine);
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800421 if (err < 0)
422 pr_err("Couldn't record guest kernel [%d]'s reference"
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -0300423 " relocation symbol.\n", machine->pid);
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800424
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800425 /*
426 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
427 * have no _text sometimes.
428 */
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200429 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
430 psession, machine, "_text");
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800431 if (err < 0)
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200432 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
433 psession, machine,
434 "_stext");
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800435 if (err < 0)
436 pr_err("Couldn't record guest kernel [%d]'s reference"
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -0300437 " relocation symbol.\n", machine->pid);
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800438}
439
Frederic Weisbecker98402802010-05-02 22:05:29 +0200440static struct perf_event_header finished_round_event = {
441 .size = sizeof(struct perf_event_header),
442 .type = PERF_RECORD_FINISHED_ROUND,
443};
444
445static void mmap_read_all(void)
446{
Peter Zijlstra0e2e63d2010-05-20 14:45:26 +0200447 int i;
Frederic Weisbecker98402802010-05-02 22:05:29 +0200448
Arnaldo Carvalho de Meloaece9482011-05-15 09:39:00 -0300449 for (i = 0; i < evsel_list->nr_mmaps; i++) {
Arnaldo Carvalho de Melo0a27d7f2011-01-14 15:50:51 -0200450 if (evsel_list->mmap[i].base)
451 mmap_read(&evsel_list->mmap[i]);
Frederic Weisbecker98402802010-05-02 22:05:29 +0200452 }
453
454 if (perf_header__has_feat(&session->header, HEADER_TRACE_INFO))
455 write_output(&finished_round_event, sizeof(finished_round_event));
456}
457
Arnaldo Carvalho de Melod4db3f12009-12-27 21:36:57 -0200458static int __cmd_record(int argc, const char **argv)
Peter Zijlstra16c8a102009-05-05 17:50:27 +0200459{
Peter Zijlstra97124d52009-06-02 15:52:24 +0200460 struct stat st;
Ingo Molnarabaff322009-06-02 22:59:57 +0200461 int flags;
Arnaldo Carvalho de Melo4dc0a042009-11-19 14:55:55 -0200462 int err;
Peter Zijlstra8b412662009-09-17 19:59:05 +0200463 unsigned long waking = 0;
Peter Zijlstra856e9662009-12-16 17:55:55 +0100464 int child_ready_pipe[2], go_pipe[2];
Zhang, Yanmin46be6042010-03-18 11:36:04 -0300465 const bool forks = argc > 0;
Peter Zijlstra856e9662009-12-16 17:55:55 +0100466 char buf;
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -0300467 struct machine *machine;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200468
Andi Kleen33e49ea2011-09-15 14:31:40 -0700469 progname = argv[0];
470
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200471 page_size = sysconf(_SC_PAGE_SIZE);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200472
Peter Zijlstraf5970552009-06-18 23:22:55 +0200473 atexit(sig_atexit);
474 signal(SIGCHLD, sig_handler);
475 signal(SIGINT, sig_handler);
Arnaldo Carvalho de Melo18483b82010-12-06 15:13:38 -0200476 signal(SIGUSR1, sig_handler);
Peter Zijlstraf5970552009-06-18 23:22:55 +0200477
Arnaldo Carvalho de Melod4db3f12009-12-27 21:36:57 -0200478 if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
Peter Zijlstra856e9662009-12-16 17:55:55 +0100479 perror("failed to create pipes");
480 exit(-1);
481 }
482
Franck Bui-Huud7065ad2011-01-16 17:14:45 +0100483 if (!output_name) {
484 if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
485 pipe_output = 1;
486 else
487 output_name = "perf.data";
488 }
489 if (output_name) {
490 if (!strcmp(output_name, "-"))
491 pipe_output = 1;
492 else if (!stat(output_name, &st) && st.st_size) {
493 if (write_mode == WRITE_FORCE) {
494 char oldname[PATH_MAX];
495 snprintf(oldname, sizeof(oldname), "%s.old",
496 output_name);
497 unlink(oldname);
498 rename(output_name, oldname);
499 }
500 } else if (write_mode == WRITE_APPEND) {
501 write_mode = WRITE_FORCE;
Pierre Habouzit266e0e22009-08-07 14:16:01 +0200502 }
Peter Zijlstra97124d52009-06-02 15:52:24 +0200503 }
504
Xiao Guangrongf887f302010-02-04 16:46:42 +0800505 flags = O_CREAT|O_RDWR;
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200506 if (write_mode == WRITE_APPEND)
Peter Zijlstraf5970552009-06-18 23:22:55 +0200507 file_new = 0;
Ingo Molnarabaff322009-06-02 22:59:57 +0200508 else
509 flags |= O_TRUNC;
510
Tom Zanussi529870e2010-04-01 23:59:16 -0500511 if (pipe_output)
512 output = STDOUT_FILENO;
513 else
514 output = open(output_name, flags, S_IRUSR | S_IWUSR);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200515 if (output < 0) {
516 perror("failed to create output file");
517 exit(-1);
518 }
519
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200520 session = perf_session__new(output_name, O_WRONLY,
Ian Munsie21ef97f2010-12-10 14:09:16 +1100521 write_mode == WRITE_FORCE, false, NULL);
Arnaldo Carvalho de Melo94c744b2009-12-11 21:24:02 -0200522 if (session == NULL) {
Arnaldo Carvalho de Meloa9a70bb2009-11-17 01:18:11 -0200523 pr_err("Not enough memory for reading perf file header\n");
524 return -1;
525 }
526
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -0200527 if (!no_buildid)
528 perf_header__set_feat(&session->header, HEADER_BUILD_ID);
529
Arnaldo Carvalho de Melo4dc0a042009-11-19 14:55:55 -0200530 if (!file_new) {
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300531 err = perf_session__read_header(session, output);
Arnaldo Carvalho de Melo4dc0a042009-11-19 14:55:55 -0200532 if (err < 0)
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300533 goto out_delete_session;
Arnaldo Carvalho de Melo4dc0a042009-11-19 14:55:55 -0200534 }
535
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200536 if (have_tracepoints(&evsel_list->entries))
Arnaldo Carvalho de Melo94c744b2009-12-11 21:24:02 -0200537 perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
Frederic Weisbecker03456a12009-10-06 23:36:47 +0200538
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200539 perf_header__set_feat(&session->header, HEADER_HOSTNAME);
540 perf_header__set_feat(&session->header, HEADER_OSRELEASE);
541 perf_header__set_feat(&session->header, HEADER_ARCH);
542 perf_header__set_feat(&session->header, HEADER_CPUDESC);
543 perf_header__set_feat(&session->header, HEADER_NRCPUS);
544 perf_header__set_feat(&session->header, HEADER_EVENT_DESC);
545 perf_header__set_feat(&session->header, HEADER_CMDLINE);
546 perf_header__set_feat(&session->header, HEADER_VERSION);
547 perf_header__set_feat(&session->header, HEADER_CPU_TOPOLOGY);
548 perf_header__set_feat(&session->header, HEADER_TOTAL_MEM);
549 perf_header__set_feat(&session->header, HEADER_NUMA_TOPOLOGY);
550 perf_header__set_feat(&session->header, HEADER_CPUID);
551
Frederic Weisbecker800cd252011-03-31 03:35:24 +0200552 /* 512 kiB: default amount of unprivileged mlocked memory */
553 if (mmap_pages == UINT_MAX)
554 mmap_pages = (512 * 1024) / page_size;
555
Arnaldo Carvalho de Melod4db3f12009-12-27 21:36:57 -0200556 if (forks) {
Zhang, Yanmin46be6042010-03-18 11:36:04 -0300557 child_pid = fork();
Borislav Petkov2fb750e2010-05-31 23:18:18 +0200558 if (child_pid < 0) {
Peter Zijlstra856e9662009-12-16 17:55:55 +0100559 perror("failed to fork");
560 exit(-1);
Jens Axboe0a5ac842009-08-12 11:18:01 +0200561 }
Peter Zijlstra856e9662009-12-16 17:55:55 +0100562
Zhang, Yanmin46be6042010-03-18 11:36:04 -0300563 if (!child_pid) {
Tom Zanussi529870e2010-04-01 23:59:16 -0500564 if (pipe_output)
565 dup2(2, 1);
Peter Zijlstra856e9662009-12-16 17:55:55 +0100566 close(child_ready_pipe[0]);
567 close(go_pipe[1]);
568 fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
569
570 /*
571 * Do a dummy execvp to get the PLT entry resolved,
572 * so we avoid the resolver overhead on the real
573 * execvp call.
574 */
575 execvp("", (char **)argv);
576
577 /*
578 * Tell the parent we're ready to go
579 */
580 close(child_ready_pipe[1]);
581
582 /*
583 * Wait until the parent tells us to go.
584 */
585 if (read(go_pipe[0], &buf, 1) == -1)
586 perror("unable to read pipe");
587
588 execvp(argv[0], (char **)argv);
589
590 perror(argv[0]);
Arnaldo Carvalho de Melo18483b82010-12-06 15:13:38 -0200591 kill(getppid(), SIGUSR1);
Peter Zijlstra856e9662009-12-16 17:55:55 +0100592 exit(-1);
593 }
594
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300595 if (!system_wide && target_tid == -1 && target_pid == -1)
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200596 evsel_list->threads->map[0] = child_pid;
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300597
Peter Zijlstra856e9662009-12-16 17:55:55 +0100598 close(child_ready_pipe[1]);
599 close(go_pipe[0]);
600 /*
601 * wait for child to settle
602 */
603 if (read(child_ready_pipe[0], &buf, 1) == -1) {
604 perror("unable to read pipe");
605 exit(-1);
606 }
607 close(child_ready_pipe[0]);
608 }
609
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200610 open_counters(evsel_list);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200611
Arnaldo Carvalho de Melo712a4b62011-02-17 12:18:42 -0200612 /*
613 * perf_session__delete(session) will be called at atexit_header()
614 */
615 atexit(atexit_header);
616
Tom Zanussi529870e2010-04-01 23:59:16 -0500617 if (pipe_output) {
618 err = perf_header__write_pipe(output);
619 if (err < 0)
620 return err;
621 } else if (file_new) {
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300622 err = perf_session__write_header(session, evsel_list,
623 output, false);
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -0200624 if (err < 0)
625 return err;
626 }
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +0200627
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -0200628 post_processing_offset = lseek(output, 0, SEEK_CUR);
629
Tom Zanussi2c46dbb2010-04-01 23:59:19 -0500630 if (pipe_output) {
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300631 err = perf_session__synthesize_attrs(session,
632 process_synthesized_event);
Tom Zanussi2c46dbb2010-04-01 23:59:19 -0500633 if (err < 0) {
634 pr_err("Couldn't synthesize attrs.\n");
635 return err;
636 }
Tom Zanussicd19a032010-04-01 23:59:20 -0500637
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200638 err = perf_event__synthesize_event_types(process_synthesized_event,
639 session);
Tom Zanussicd19a032010-04-01 23:59:20 -0500640 if (err < 0) {
641 pr_err("Couldn't synthesize event_types.\n");
642 return err;
643 }
Tom Zanussi92155452010-04-01 23:59:21 -0500644
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200645 if (have_tracepoints(&evsel_list->entries)) {
Tom Zanussi63e0c772010-05-03 00:14:48 -0500646 /*
647 * FIXME err <= 0 here actually means that
648 * there were no tracepoints so its not really
649 * an error, just that we don't need to
650 * synthesize anything. We really have to
651 * return this more properly and also
652 * propagate errors that now are calling die()
653 */
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200654 err = perf_event__synthesize_tracing_data(output, evsel_list,
655 process_synthesized_event,
656 session);
Tom Zanussi63e0c772010-05-03 00:14:48 -0500657 if (err <= 0) {
658 pr_err("Couldn't record tracing data.\n");
659 return err;
660 }
Arnaldo Carvalho de Melo2c9faa02010-05-02 13:37:24 -0300661 advance_output(err);
Tom Zanussi63e0c772010-05-03 00:14:48 -0500662 }
Tom Zanussi2c46dbb2010-04-01 23:59:19 -0500663 }
664
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -0300665 machine = perf_session__find_host_machine(session);
666 if (!machine) {
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800667 pr_err("Couldn't find native kernel information.\n");
668 return -1;
669 }
670
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200671 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
672 session, machine, "_text");
Arnaldo Carvalho de Melo70162132010-03-30 18:27:39 -0300673 if (err < 0)
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200674 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
675 session, machine, "_stext");
Arnaldo Carvalho de Meloc1a3a4b2010-11-22 14:01:55 -0200676 if (err < 0)
677 pr_err("Couldn't record kernel reference relocation symbol\n"
678 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
679 "Check /proc/kallsyms permission or run as root.\n");
Arnaldo Carvalho de Melo56b03f32010-01-05 16:50:31 -0200680
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200681 err = perf_event__synthesize_modules(process_synthesized_event,
682 session, machine);
Arnaldo Carvalho de Meloc1a3a4b2010-11-22 14:01:55 -0200683 if (err < 0)
684 pr_err("Couldn't record kernel module information.\n"
685 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
686 "Check /proc/modules permission or run as root.\n");
687
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800688 if (perf_guest)
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200689 perf_session__process_machines(session,
690 perf_event__synthesize_guest_os);
Arnaldo Carvalho de Melob7cece72010-01-13 13:22:17 -0200691
Stephane Eraniancf103a12010-06-16 20:59:01 +0200692 if (!system_wide)
Arnaldo Carvalho de Melo7c940c12011-02-11 11:45:54 -0200693 perf_event__synthesize_thread_map(evsel_list->threads,
694 process_synthesized_event,
695 session);
Arnaldo Carvalho de Melo234fbbf2009-10-26 19:23:18 -0200696 else
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200697 perf_event__synthesize_threads(process_synthesized_event,
698 session);
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +0200699
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200700 if (realtime_prio) {
701 struct sched_param param;
702
703 param.sched_priority = realtime_prio;
704 if (sched_setscheduler(0, SCHED_FIFO, &param)) {
Arnaldo Carvalho de Melo6beba7a2009-10-21 17:34:06 -0200705 pr_err("Could not set realtime priority.\n");
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200706 exit(-1);
707 }
708 }
709
David Ahern764e16a32011-08-25 10:17:55 -0600710 perf_evlist__enable(evsel_list);
711
Peter Zijlstra856e9662009-12-16 17:55:55 +0100712 /*
713 * Let the child rip
714 */
Arnaldo Carvalho de Melod4db3f12009-12-27 21:36:57 -0200715 if (forks)
716 close(go_pipe[1]);
Peter Zijlstra856e9662009-12-16 17:55:55 +0100717
Peter Zijlstra649c48a2009-06-24 21:12:48 +0200718 for (;;) {
Ingo Molnar2debbc82009-06-05 14:29:10 +0200719 int hits = samples;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200720
Frederic Weisbecker98402802010-05-02 22:05:29 +0200721 mmap_read_all();
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200722
Peter Zijlstra649c48a2009-06-24 21:12:48 +0200723 if (hits == samples) {
724 if (done)
725 break;
Arnaldo Carvalho de Melo5c581042011-01-11 22:30:02 -0200726 err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1);
Peter Zijlstra8b412662009-09-17 19:59:05 +0200727 waking++;
728 }
729
Arnaldo Carvalho de Melo4152ab32011-07-25 11:06:19 -0300730 if (done)
731 perf_evlist__disable(evsel_list);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200732 }
733
Arnaldo Carvalho de Melo18483b82010-12-06 15:13:38 -0200734 if (quiet || signr == SIGUSR1)
Arnaldo Carvalho de Melob44308f2010-10-26 15:20:09 -0200735 return 0;
736
Peter Zijlstra8b412662009-09-17 19:59:05 +0200737 fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
738
Ingo Molnar021e9f42009-06-03 19:27:19 +0200739 /*
740 * Approximate RIP event size: 24 bytes.
741 */
742 fprintf(stderr,
Arnaldo Carvalho de Melo9486aa32011-01-22 20:37:02 -0200743 "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
Ingo Molnar021e9f42009-06-03 19:27:19 +0200744 (double)bytes_written / 1024.0 / 1024.0,
745 output_name,
746 bytes_written / 24);
Ingo Molnaraddc2782009-06-02 23:43:11 +0200747
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200748 return 0;
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300749
750out_delete_session:
751 perf_session__delete(session);
752 return err;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200753}
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200754
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200755static const char * const record_usage[] = {
Mike Galbraith9e0967532009-05-28 16:25:34 +0200756 "perf record [<options>] [<command>]",
757 "perf record [<options>] -- <command> [<options>]",
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200758 NULL
759};
760
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200761static bool force, append_file;
762
Tom Zanussibca647a2010-11-10 08:11:30 -0600763const struct option record_options[] = {
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200764 OPT_CALLBACK('e', "event", &evsel_list, "event",
Thomas Gleixner86847b62009-06-06 12:24:17 +0200765 "event selector. use 'perf list' to list available events",
Jiri Olsaf120f9d2011-07-14 11:25:32 +0200766 parse_events_option),
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200767 OPT_CALLBACK(0, "filter", &evsel_list, "filter",
Li Zefanc171b552009-10-15 11:22:07 +0800768 "event filter", parse_filter),
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200769 OPT_INTEGER('p', "pid", &target_pid,
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300770 "record events on existing process id"),
771 OPT_INTEGER('t', "tid", &target_tid,
772 "record events on existing thread id"),
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200773 OPT_INTEGER('r', "realtime", &realtime_prio,
774 "collect data with this RT SCHED_FIFO priority"),
Kirill Smelkovacac03f2011-01-12 17:59:36 +0300775 OPT_BOOLEAN('D', "no-delay", &nodelay,
776 "collect data without buffering"),
Frederic Weisbeckerdaac07b2009-08-13 10:27:19 +0200777 OPT_BOOLEAN('R', "raw-samples", &raw_samples,
778 "collect raw sample records from all opened counters"),
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200779 OPT_BOOLEAN('a', "all-cpus", &system_wide,
780 "system-wide collection from all CPUs"),
Ingo Molnarabaff322009-06-02 22:59:57 +0200781 OPT_BOOLEAN('A', "append", &append_file,
782 "append to the output file to do incremental profiling"),
Stephane Eranianc45c6ea2010-05-28 12:00:01 +0200783 OPT_STRING('C', "cpu", &cpu_list, "cpu",
784 "list of cpus to monitor"),
Peter Zijlstra97124d52009-06-02 15:52:24 +0200785 OPT_BOOLEAN('f', "force", &force,
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200786 "overwrite existing data file (deprecated)"),
Stephane Eranian3de29ca2010-05-17 12:20:43 -0300787 OPT_U64('c', "count", &user_interval, "event period to sample"),
Ingo Molnarabaff322009-06-02 22:59:57 +0200788 OPT_STRING('o', "output", &output_name, "file",
789 "output file name"),
Stephane Eranian2e6cdf92010-05-12 10:40:01 +0200790 OPT_BOOLEAN('i', "no-inherit", &no_inherit,
791 "child tasks do not inherit counters"),
Arnaldo Carvalho de Melo19679362010-05-17 15:39:16 -0300792 OPT_UINTEGER('F', "freq", &user_freq, "profile at this frequency"),
793 OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"),
Lin Ming43bece72011-08-17 18:42:07 +0800794 OPT_BOOLEAN(0, "group", &group,
795 "put the counters into a counter group"),
Ingo Molnar3efa1cc92009-06-14 15:04:15 +0200796 OPT_BOOLEAN('g', "call-graph", &call_graph,
797 "do call-graph (stack chain/backtrace) recording"),
Ian Munsiec0555642010-04-13 18:37:33 +1000798 OPT_INCR('v', "verbose", &verbose,
Ingo Molnar3da297a2009-06-07 17:39:02 +0200799 "be more verbose (show counter open errors, etc)"),
Arnaldo Carvalho de Melob44308f2010-10-26 15:20:09 -0200800 OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
Peter Zijlstra649c48a2009-06-24 21:12:48 +0200801 OPT_BOOLEAN('s', "stat", &inherit_stat,
802 "per thread counts"),
Anton Blanchard4bba8282009-07-16 15:44:29 +0200803 OPT_BOOLEAN('d', "data", &sample_address,
804 "Sample addresses"),
Arnaldo Carvalho de Melo9c90a612010-12-02 10:25:28 -0200805 OPT_BOOLEAN('T', "timestamp", &sample_time, "Sample timestamps"),
Peter Zijlstra649c48a2009-06-24 21:12:48 +0200806 OPT_BOOLEAN('n', "no-samples", &no_samples,
807 "don't sample"),
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -0200808 OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid_cache,
Stephane Eraniana1ac1d32010-06-17 11:39:01 +0200809 "do not update the buildid cache"),
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -0200810 OPT_BOOLEAN('B', "no-buildid", &no_buildid,
811 "do not collect buildids in perf.data"),
Stephane Eranian023695d2011-02-14 11:20:01 +0200812 OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
813 "monitor event in cgroup name only",
814 parse_cgroups),
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200815 OPT_END()
816};
817
Ingo Molnarf37a2912009-07-01 12:37:06 +0200818int cmd_record(int argc, const char **argv, const char *prefix __used)
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200819{
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200820 int err = -ENOMEM;
821 struct perf_evsel *pos;
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200822
Stephane Eranianfbe96f22011-09-30 15:40:40 +0200823 perf_header__set_cmdline(argc, argv);
824
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200825 evsel_list = perf_evlist__new(NULL, NULL);
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200826 if (evsel_list == NULL)
827 return -ENOMEM;
828
Tom Zanussibca647a2010-11-10 08:11:30 -0600829 argc = parse_options(argc, argv, record_options, record_usage,
Arnaldo Carvalho de Melo655000e2009-12-15 20:04:40 -0200830 PARSE_OPT_STOP_AT_NON_OPTION);
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300831 if (!argc && target_pid == -1 && target_tid == -1 &&
Stephane Eranianc45c6ea2010-05-28 12:00:01 +0200832 !system_wide && !cpu_list)
Tom Zanussibca647a2010-11-10 08:11:30 -0600833 usage_with_options(record_usage, record_options);
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200834
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200835 if (force && append_file) {
836 fprintf(stderr, "Can't overwrite and append at the same time."
837 " You need to choose between -f and -A");
Tom Zanussibca647a2010-11-10 08:11:30 -0600838 usage_with_options(record_usage, record_options);
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200839 } else if (append_file) {
840 write_mode = WRITE_APPEND;
841 } else {
842 write_mode = WRITE_FORCE;
843 }
844
Stephane Eranian023695d2011-02-14 11:20:01 +0200845 if (nr_cgroups && !system_wide) {
846 fprintf(stderr, "cgroup monitoring only available in"
847 " system-wide mode\n");
848 usage_with_options(record_usage, record_options);
849 }
850
Arnaldo Carvalho de Melo655000e2009-12-15 20:04:40 -0200851 symbol__init();
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -0200852
Arnaldo Carvalho de Meloec80fde2011-05-26 09:53:51 -0300853 if (symbol_conf.kptr_restrict)
Arnaldo Carvalho de Melo646aaea2011-05-27 11:00:41 -0300854 pr_warning(
855"WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
856"check /proc/sys/kernel/kptr_restrict.\n\n"
857"Samples in kernel functions may not be resolved if a suitable vmlinux\n"
858"file is not found in the buildid cache or in the vmlinux path.\n\n"
859"Samples in kernel modules won't be resolved at all.\n\n"
860"If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
861"even with a suitable vmlinux or kallsyms file.\n\n");
Arnaldo Carvalho de Meloec80fde2011-05-26 09:53:51 -0300862
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -0200863 if (no_buildid_cache || no_buildid)
Stephane Eraniana1ac1d32010-06-17 11:39:01 +0200864 disable_buildid_cache();
Arnaldo Carvalho de Melo655000e2009-12-15 20:04:40 -0200865
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200866 if (evsel_list->nr_entries == 0 &&
867 perf_evlist__add_default(evsel_list) < 0) {
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200868 pr_err("Not enough memory for event selector list\n");
869 goto out_symbol_exit;
Peter Zijlstrabbd36e52009-06-11 23:11:50 +0200870 }
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200871
Arnaldo Carvalho de Melo5c98d4662011-01-03 17:53:33 -0200872 if (target_pid != -1)
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300873 target_tid = target_pid;
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300874
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200875 if (perf_evlist__create_maps(evsel_list, target_pid,
876 target_tid, cpu_list) < 0)
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200877 usage_with_options(record_usage, record_options);
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200878
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200879 list_for_each_entry(pos, &evsel_list->entries, node) {
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200880 if (perf_evsel__alloc_fd(pos, evsel_list->cpus->nr,
881 evsel_list->threads->nr) < 0)
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200882 goto out_free_fd;
Arnaldo Carvalho de Meload7f4e32011-01-17 18:28:13 -0200883 if (perf_header__push_event(pos->attr.config, event_name(pos)))
884 goto out_free_fd;
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300885 }
Arnaldo Carvalho de Melo5c581042011-01-11 22:30:02 -0200886
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200887 if (perf_evlist__alloc_pollfd(evsel_list) < 0)
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300888 goto out_free_fd;
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300889
Stephane Eranian3de29ca2010-05-17 12:20:43 -0300890 if (user_interval != ULLONG_MAX)
Frederic Weisbeckerf9212812010-04-14 22:09:02 +0200891 default_interval = user_interval;
892 if (user_freq != UINT_MAX)
893 freq = user_freq;
894
Mike Galbraith7e4ff9e2009-10-12 07:56:03 +0200895 /*
896 * User specified count overrides default frequency.
897 */
898 if (default_interval)
899 freq = 0;
900 else if (freq) {
901 default_interval = freq;
902 } else {
903 fprintf(stderr, "frequency and count are zero, aborting\n");
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300904 err = -EINVAL;
Arnaldo Carvalho de Melo5c581042011-01-11 22:30:02 -0200905 goto out_free_fd;
Mike Galbraith7e4ff9e2009-10-12 07:56:03 +0200906 }
907
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300908 err = __cmd_record(argc, argv);
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300909out_free_fd:
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200910 perf_evlist__delete_maps(evsel_list);
Arnaldo Carvalho de Melod65a4582010-07-30 18:31:28 -0300911out_symbol_exit:
912 symbol__exit();
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300913 return err;
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200914}