blob: 042117f8fffa3a3ef949237bf7ebcbebc974386a [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
Arnaldo Carvalho de Melo5d2cd902011-04-14 11:20:14 -0300177 attr->inherit = !no_inherit;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +0200178 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
179 PERF_FORMAT_TOTAL_TIME_RUNNING |
180 PERF_FORMAT_ID;
Peter Zijlstra16c8a102009-05-05 17:50:27 +0200181
Frederic Weisbecker3a9f1312009-08-13 10:27:18 +0200182 attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
Ingo Molnar3efa1cc92009-06-14 15:04:15 +0200183
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200184 if (evlist->nr_entries > 1)
Eric B Munson8907fd62010-03-05 12:51:05 -0300185 attr->sample_type |= PERF_SAMPLE_ID;
186
Frederic Weisbeckerf9212812010-04-14 22:09:02 +0200187 /*
188 * We default some events to a 1 default interval. But keep
189 * it a weak assumption overridable by the user.
190 */
191 if (!attr->sample_period || (user_freq != UINT_MAX &&
Stephane Eranian3de29ca2010-05-17 12:20:43 -0300192 user_interval != ULLONG_MAX)) {
Frederic Weisbeckerf9212812010-04-14 22:09:02 +0200193 if (freq) {
194 attr->sample_type |= PERF_SAMPLE_PERIOD;
195 attr->freq = 1;
196 attr->sample_freq = freq;
197 } else {
198 attr->sample_period = default_interval;
199 }
Ingo Molnar1dba15e2009-06-05 18:37:22 +0200200 }
Ingo Molnar3efa1cc92009-06-14 15:04:15 +0200201
Peter Zijlstra649c48a2009-06-24 21:12:48 +0200202 if (no_samples)
203 attr->sample_freq = 0;
204
205 if (inherit_stat)
206 attr->inherit_stat = 1;
207
Eric B Munson3af9e852010-05-18 15:30:49 +0100208 if (sample_address) {
Anton Blanchard4bba8282009-07-16 15:44:29 +0200209 attr->sample_type |= PERF_SAMPLE_ADDR;
Eric B Munson3af9e852010-05-18 15:30:49 +0100210 attr->mmap_data = track;
211 }
Anton Blanchard4bba8282009-07-16 15:44:29 +0200212
Ingo Molnar3efa1cc92009-06-14 15:04:15 +0200213 if (call_graph)
214 attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
215
Arun Sharmaf60f3592010-06-04 11:27:10 -0300216 if (system_wide)
217 attr->sample_type |= PERF_SAMPLE_CPU;
218
Arnaldo Carvalho de Meloa43d3f02010-12-25 12:12:25 -0200219 if (sample_id_all_avail &&
220 (sample_time || system_wide || !no_inherit || cpu_list))
Arnaldo Carvalho de Melo9c90a612010-12-02 10:25:28 -0200221 attr->sample_type |= PERF_SAMPLE_TIME;
222
Ingo Molnarcd6feee2009-09-02 20:20:38 +0200223 if (raw_samples) {
Ingo Molnar6ddf2592009-09-03 12:00:22 +0200224 attr->sample_type |= PERF_SAMPLE_TIME;
Frederic Weisbeckerdaac07b2009-08-13 10:27:19 +0200225 attr->sample_type |= PERF_SAMPLE_RAW;
Ingo Molnarcd6feee2009-09-02 20:20:38 +0200226 attr->sample_type |= PERF_SAMPLE_CPU;
227 }
Frederic Weisbeckerf413cdb2009-08-07 01:25:54 +0200228
Kirill Smelkovacac03f2011-01-12 17:59:36 +0300229 if (nodelay) {
230 attr->watermark = 0;
231 attr->wakeup_events = 1;
232 }
233
Ingo Molnara21ca2c2009-06-06 09:58:57 +0200234 attr->mmap = track;
235 attr->comm = track;
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200236
Stephane Eranian2e6cdf92010-05-12 10:40:01 +0200237 if (target_pid == -1 && target_tid == -1 && !system_wide) {
Zhang, Yanmin46be6042010-03-18 11:36:04 -0300238 attr->disabled = 1;
Eric B Munsonbedbfde2010-03-15 11:46:57 -0300239 attr->enable_on_exec = 1;
Zhang, Yanmin46be6042010-03-18 11:36:04 -0300240 }
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200241}
242
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300243static bool perf_evlist__equal(struct perf_evlist *evlist,
244 struct perf_evlist *other)
245{
246 struct perf_evsel *pos, *pair;
247
248 if (evlist->nr_entries != other->nr_entries)
249 return false;
250
251 pair = list_entry(other->entries.next, struct perf_evsel, node);
252
253 list_for_each_entry(pos, &evlist->entries, node) {
254 if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0))
255 return false;
256 pair = list_entry(pair->node.next, struct perf_evsel, node);
257 }
258
259 return true;
260}
261
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200262static void open_counters(struct perf_evlist *evlist)
263{
264 struct perf_evsel *pos;
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200265
Arnaldo Carvalho de Melo5d2cd902011-04-14 11:20:14 -0300266 if (evlist->cpus->map[0] < 0)
267 no_inherit = true;
268
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200269 list_for_each_entry(pos, &evlist->entries, node) {
270 struct perf_event_attr *attr = &pos->attr;
271 /*
272 * Check if parse_single_tracepoint_event has already asked for
273 * PERF_SAMPLE_TIME.
274 *
275 * XXX this is kludgy but short term fix for problems introduced by
276 * eac23d1c that broke 'perf script' by having different sample_types
277 * when using multiple tracepoint events when we use a perf binary
278 * that tries to use sample_id_all on an older kernel.
279 *
280 * We need to move counter creation to perf_session, support
281 * different sample_types, etc.
282 */
283 bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
284
285 config_attr(pos, evlist);
Arnaldo Carvalho de Melo9c90a612010-12-02 10:25:28 -0200286retry_sample_id:
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200287 attr->sample_id_all = sample_id_all_avail ? 1 : 0;
Ingo Molnar3da297a2009-06-07 17:39:02 +0200288try_again:
Arnaldo Carvalho de Melo5d2cd902011-04-14 11:20:14 -0300289 if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group) < 0) {
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300290 int err = errno;
Ingo Molnarf250c0302009-06-05 13:18:41 +0200291
Arnaldo Carvalho de Meloc286c412011-03-28 09:50:11 -0300292 if (err == EPERM || err == EACCES) {
293 ui__warning_paranoid();
294 exit(EXIT_FAILURE);
295 } else if (err == ENODEV && cpu_list) {
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300296 die("No such device - did you specify"
297 " an out-of-range profile CPU?\n");
Arnaldo Carvalho de Melo9c90a612010-12-02 10:25:28 -0200298 } else if (err == EINVAL && sample_id_all_avail) {
299 /*
300 * Old kernel, no attr->sample_id_type_all field
301 */
302 sample_id_all_avail = false;
Arnaldo Carvalho de Meloa43d3f02010-12-25 12:12:25 -0200303 if (!sample_time && !raw_samples && !time_needed)
Ian Munsieeac23d12010-12-09 16:33:53 +1100304 attr->sample_type &= ~PERF_SAMPLE_TIME;
305
Arnaldo Carvalho de Melo9c90a612010-12-02 10:25:28 -0200306 goto retry_sample_id;
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300307 }
Ingo Molnar3da297a2009-06-07 17:39:02 +0200308
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300309 /*
310 * If it's cycles then fall back to hrtimer
311 * based cpu-clock-tick sw counter, which
312 * is always available even if no PMU support:
313 */
314 if (attr->type == PERF_TYPE_HARDWARE
315 && attr->config == PERF_COUNT_HW_CPU_CYCLES) {
Ingo Molnar3da297a2009-06-07 17:39:02 +0200316
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300317 if (verbose)
David Ahernca6a4252011-03-25 13:11:11 -0600318 ui__warning("The cycles event is not supported, "
319 "trying to fall back to cpu-clock-ticks\n");
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300320 attr->type = PERF_TYPE_SOFTWARE;
321 attr->config = PERF_COUNT_SW_CPU_CLOCK;
322 goto try_again;
323 }
David Ahernca6a4252011-03-25 13:11:11 -0600324
325 if (err == ENOENT) {
326 ui__warning("The %s event is not supported.\n",
327 event_name(pos));
328 exit(EXIT_FAILURE);
329 }
330
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300331 printf("\n");
Corey Ashfordd9cf8372010-11-19 17:37:24 -0800332 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 -0200333 err, strerror(err));
Simon Kaempfleinbfd45112009-11-16 15:25:53 +1000334
335#if defined(__i386__) || defined(__x86_64__)
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300336 if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP)
337 die("No hardware sampling interrupt available."
338 " No APIC? If so then you can boot the kernel"
339 " with the \"lapic\" boot parameter to"
340 " force-enable it.\n");
Simon Kaempfleinbfd45112009-11-16 15:25:53 +1000341#endif
342
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300343 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300344 }
Li Zefanc171b552009-10-15 11:22:07 +0800345 }
Arnaldo Carvalho de Meloa43d3f02010-12-25 12:12:25 -0200346
Frederic Weisbecker0a102472011-02-26 04:51:54 +0100347 if (perf_evlist__set_filters(evlist)) {
348 error("failed to set filter with %d (%s)\n", errno,
349 strerror(errno));
350 exit(-1);
351 }
352
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200353 if (perf_evlist__mmap(evlist, mmap_pages, false) < 0)
Arnaldo Carvalho de Melo0a27d7f2011-01-14 15:50:51 -0200354 die("failed to mmap with %d (%s)\n", errno, strerror(errno));
355
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300356 if (file_new)
357 session->evlist = evlist;
358 else {
359 if (!perf_evlist__equal(session->evlist, evlist)) {
360 fprintf(stderr, "incompatible append\n");
361 exit(-1);
362 }
363 }
364
365 perf_session__update_sample_type(session);
Peter Zijlstra16c8a102009-05-05 17:50:27 +0200366}
367
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -0200368static int process_buildids(void)
369{
370 u64 size = lseek(output, 0, SEEK_CUR);
371
Arnaldo Carvalho de Melo9f591fd2010-03-11 15:53:11 -0300372 if (size == 0)
373 return 0;
374
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -0200375 session->fd = output;
376 return __perf_session__process_events(session, post_processing_offset,
377 size - post_processing_offset,
378 size, &build_id__mark_dso_hit_ops);
379}
380
Peter Zijlstraf5970552009-06-18 23:22:55 +0200381static void atexit_header(void)
382{
Tom Zanussic7929e42010-04-01 23:59:22 -0500383 if (!pipe_output) {
384 session->header.data_size += bytes_written;
Peter Zijlstraf5970552009-06-18 23:22:55 +0200385
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -0200386 if (!no_buildid)
387 process_buildids();
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300388 perf_session__write_header(session, evsel_list, output, true);
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300389 perf_session__delete(session);
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200390 perf_evlist__delete(evsel_list);
Arnaldo Carvalho de Melod65a4582010-07-30 18:31:28 -0300391 symbol__exit();
Tom Zanussic7929e42010-04-01 23:59:22 -0500392 }
Peter Zijlstraf5970552009-06-18 23:22:55 +0200393}
394
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200395static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800396{
397 int err;
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -0300398 struct perf_session *psession = data;
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800399
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -0300400 if (machine__is_host(machine))
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800401 return;
402
403 /*
404 *As for guest kernel when processing subcommand record&report,
405 *we arrange module mmap prior to guest kernel mmap and trigger
406 *a preload dso because default guest module symbols are loaded
407 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
408 *method is used to avoid symbol missing when the first addr is
409 *in module instead of in guest kernel.
410 */
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200411 err = perf_event__synthesize_modules(process_synthesized_event,
412 psession, machine);
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800413 if (err < 0)
414 pr_err("Couldn't record guest kernel [%d]'s reference"
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -0300415 " relocation symbol.\n", machine->pid);
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800416
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800417 /*
418 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
419 * have no _text sometimes.
420 */
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200421 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
422 psession, machine, "_text");
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800423 if (err < 0)
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200424 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
425 psession, machine,
426 "_stext");
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800427 if (err < 0)
428 pr_err("Couldn't record guest kernel [%d]'s reference"
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -0300429 " relocation symbol.\n", machine->pid);
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800430}
431
Frederic Weisbecker98402802010-05-02 22:05:29 +0200432static struct perf_event_header finished_round_event = {
433 .size = sizeof(struct perf_event_header),
434 .type = PERF_RECORD_FINISHED_ROUND,
435};
436
437static void mmap_read_all(void)
438{
Peter Zijlstra0e2e63d2010-05-20 14:45:26 +0200439 int i;
Frederic Weisbecker98402802010-05-02 22:05:29 +0200440
Arnaldo Carvalho de Meloaece9482011-05-15 09:39:00 -0300441 for (i = 0; i < evsel_list->nr_mmaps; i++) {
Arnaldo Carvalho de Melo0a27d7f2011-01-14 15:50:51 -0200442 if (evsel_list->mmap[i].base)
443 mmap_read(&evsel_list->mmap[i]);
Frederic Weisbecker98402802010-05-02 22:05:29 +0200444 }
445
446 if (perf_header__has_feat(&session->header, HEADER_TRACE_INFO))
447 write_output(&finished_round_event, sizeof(finished_round_event));
448}
449
Arnaldo Carvalho de Melod4db3f12009-12-27 21:36:57 -0200450static int __cmd_record(int argc, const char **argv)
Peter Zijlstra16c8a102009-05-05 17:50:27 +0200451{
Peter Zijlstra97124d52009-06-02 15:52:24 +0200452 struct stat st;
Ingo Molnarabaff322009-06-02 22:59:57 +0200453 int flags;
Arnaldo Carvalho de Melo4dc0a042009-11-19 14:55:55 -0200454 int err;
Peter Zijlstra8b412662009-09-17 19:59:05 +0200455 unsigned long waking = 0;
Peter Zijlstra856e9662009-12-16 17:55:55 +0100456 int child_ready_pipe[2], go_pipe[2];
Zhang, Yanmin46be6042010-03-18 11:36:04 -0300457 const bool forks = argc > 0;
Peter Zijlstra856e9662009-12-16 17:55:55 +0100458 char buf;
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -0300459 struct machine *machine;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200460
Andi Kleen33e49ea2011-09-15 14:31:40 -0700461 progname = argv[0];
462
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200463 page_size = sysconf(_SC_PAGE_SIZE);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200464
Peter Zijlstraf5970552009-06-18 23:22:55 +0200465 atexit(sig_atexit);
466 signal(SIGCHLD, sig_handler);
467 signal(SIGINT, sig_handler);
Arnaldo Carvalho de Melo18483b82010-12-06 15:13:38 -0200468 signal(SIGUSR1, sig_handler);
Peter Zijlstraf5970552009-06-18 23:22:55 +0200469
Arnaldo Carvalho de Melod4db3f12009-12-27 21:36:57 -0200470 if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
Peter Zijlstra856e9662009-12-16 17:55:55 +0100471 perror("failed to create pipes");
472 exit(-1);
473 }
474
Franck Bui-Huud7065ad2011-01-16 17:14:45 +0100475 if (!output_name) {
476 if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
477 pipe_output = 1;
478 else
479 output_name = "perf.data";
480 }
481 if (output_name) {
482 if (!strcmp(output_name, "-"))
483 pipe_output = 1;
484 else if (!stat(output_name, &st) && st.st_size) {
485 if (write_mode == WRITE_FORCE) {
486 char oldname[PATH_MAX];
487 snprintf(oldname, sizeof(oldname), "%s.old",
488 output_name);
489 unlink(oldname);
490 rename(output_name, oldname);
491 }
492 } else if (write_mode == WRITE_APPEND) {
493 write_mode = WRITE_FORCE;
Pierre Habouzit266e0e22009-08-07 14:16:01 +0200494 }
Peter Zijlstra97124d52009-06-02 15:52:24 +0200495 }
496
Xiao Guangrongf887f302010-02-04 16:46:42 +0800497 flags = O_CREAT|O_RDWR;
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200498 if (write_mode == WRITE_APPEND)
Peter Zijlstraf5970552009-06-18 23:22:55 +0200499 file_new = 0;
Ingo Molnarabaff322009-06-02 22:59:57 +0200500 else
501 flags |= O_TRUNC;
502
Tom Zanussi529870e2010-04-01 23:59:16 -0500503 if (pipe_output)
504 output = STDOUT_FILENO;
505 else
506 output = open(output_name, flags, S_IRUSR | S_IWUSR);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200507 if (output < 0) {
508 perror("failed to create output file");
509 exit(-1);
510 }
511
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200512 session = perf_session__new(output_name, O_WRONLY,
Ian Munsie21ef97f2010-12-10 14:09:16 +1100513 write_mode == WRITE_FORCE, false, NULL);
Arnaldo Carvalho de Melo94c744b2009-12-11 21:24:02 -0200514 if (session == NULL) {
Arnaldo Carvalho de Meloa9a70bb2009-11-17 01:18:11 -0200515 pr_err("Not enough memory for reading perf file header\n");
516 return -1;
517 }
518
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -0200519 if (!no_buildid)
520 perf_header__set_feat(&session->header, HEADER_BUILD_ID);
521
Arnaldo Carvalho de Melo4dc0a042009-11-19 14:55:55 -0200522 if (!file_new) {
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300523 err = perf_session__read_header(session, output);
Arnaldo Carvalho de Melo4dc0a042009-11-19 14:55:55 -0200524 if (err < 0)
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300525 goto out_delete_session;
Arnaldo Carvalho de Melo4dc0a042009-11-19 14:55:55 -0200526 }
527
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200528 if (have_tracepoints(&evsel_list->entries))
Arnaldo Carvalho de Melo94c744b2009-12-11 21:24:02 -0200529 perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
Frederic Weisbecker03456a12009-10-06 23:36:47 +0200530
Frederic Weisbecker800cd252011-03-31 03:35:24 +0200531 /* 512 kiB: default amount of unprivileged mlocked memory */
532 if (mmap_pages == UINT_MAX)
533 mmap_pages = (512 * 1024) / page_size;
534
Arnaldo Carvalho de Melod4db3f12009-12-27 21:36:57 -0200535 if (forks) {
Zhang, Yanmin46be6042010-03-18 11:36:04 -0300536 child_pid = fork();
Borislav Petkov2fb750e2010-05-31 23:18:18 +0200537 if (child_pid < 0) {
Peter Zijlstra856e9662009-12-16 17:55:55 +0100538 perror("failed to fork");
539 exit(-1);
Jens Axboe0a5ac842009-08-12 11:18:01 +0200540 }
Peter Zijlstra856e9662009-12-16 17:55:55 +0100541
Zhang, Yanmin46be6042010-03-18 11:36:04 -0300542 if (!child_pid) {
Tom Zanussi529870e2010-04-01 23:59:16 -0500543 if (pipe_output)
544 dup2(2, 1);
Peter Zijlstra856e9662009-12-16 17:55:55 +0100545 close(child_ready_pipe[0]);
546 close(go_pipe[1]);
547 fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
548
549 /*
550 * Do a dummy execvp to get the PLT entry resolved,
551 * so we avoid the resolver overhead on the real
552 * execvp call.
553 */
554 execvp("", (char **)argv);
555
556 /*
557 * Tell the parent we're ready to go
558 */
559 close(child_ready_pipe[1]);
560
561 /*
562 * Wait until the parent tells us to go.
563 */
564 if (read(go_pipe[0], &buf, 1) == -1)
565 perror("unable to read pipe");
566
567 execvp(argv[0], (char **)argv);
568
569 perror(argv[0]);
Arnaldo Carvalho de Melo18483b82010-12-06 15:13:38 -0200570 kill(getppid(), SIGUSR1);
Peter Zijlstra856e9662009-12-16 17:55:55 +0100571 exit(-1);
572 }
573
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300574 if (!system_wide && target_tid == -1 && target_pid == -1)
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200575 evsel_list->threads->map[0] = child_pid;
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300576
Peter Zijlstra856e9662009-12-16 17:55:55 +0100577 close(child_ready_pipe[1]);
578 close(go_pipe[0]);
579 /*
580 * wait for child to settle
581 */
582 if (read(child_ready_pipe[0], &buf, 1) == -1) {
583 perror("unable to read pipe");
584 exit(-1);
585 }
586 close(child_ready_pipe[0]);
587 }
588
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200589 open_counters(evsel_list);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200590
Arnaldo Carvalho de Melo712a4b62011-02-17 12:18:42 -0200591 /*
592 * perf_session__delete(session) will be called at atexit_header()
593 */
594 atexit(atexit_header);
595
Tom Zanussi529870e2010-04-01 23:59:16 -0500596 if (pipe_output) {
597 err = perf_header__write_pipe(output);
598 if (err < 0)
599 return err;
600 } else if (file_new) {
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300601 err = perf_session__write_header(session, evsel_list,
602 output, false);
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -0200603 if (err < 0)
604 return err;
605 }
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +0200606
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -0200607 post_processing_offset = lseek(output, 0, SEEK_CUR);
608
Tom Zanussi2c46dbb2010-04-01 23:59:19 -0500609 if (pipe_output) {
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300610 err = perf_session__synthesize_attrs(session,
611 process_synthesized_event);
Tom Zanussi2c46dbb2010-04-01 23:59:19 -0500612 if (err < 0) {
613 pr_err("Couldn't synthesize attrs.\n");
614 return err;
615 }
Tom Zanussicd19a032010-04-01 23:59:20 -0500616
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200617 err = perf_event__synthesize_event_types(process_synthesized_event,
618 session);
Tom Zanussicd19a032010-04-01 23:59:20 -0500619 if (err < 0) {
620 pr_err("Couldn't synthesize event_types.\n");
621 return err;
622 }
Tom Zanussi92155452010-04-01 23:59:21 -0500623
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200624 if (have_tracepoints(&evsel_list->entries)) {
Tom Zanussi63e0c772010-05-03 00:14:48 -0500625 /*
626 * FIXME err <= 0 here actually means that
627 * there were no tracepoints so its not really
628 * an error, just that we don't need to
629 * synthesize anything. We really have to
630 * return this more properly and also
631 * propagate errors that now are calling die()
632 */
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200633 err = perf_event__synthesize_tracing_data(output, evsel_list,
634 process_synthesized_event,
635 session);
Tom Zanussi63e0c772010-05-03 00:14:48 -0500636 if (err <= 0) {
637 pr_err("Couldn't record tracing data.\n");
638 return err;
639 }
Arnaldo Carvalho de Melo2c9faa02010-05-02 13:37:24 -0300640 advance_output(err);
Tom Zanussi63e0c772010-05-03 00:14:48 -0500641 }
Tom Zanussi2c46dbb2010-04-01 23:59:19 -0500642 }
643
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -0300644 machine = perf_session__find_host_machine(session);
645 if (!machine) {
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800646 pr_err("Couldn't find native kernel information.\n");
647 return -1;
648 }
649
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200650 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
651 session, machine, "_text");
Arnaldo Carvalho de Melo70162132010-03-30 18:27:39 -0300652 if (err < 0)
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200653 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
654 session, machine, "_stext");
Arnaldo Carvalho de Meloc1a3a4b2010-11-22 14:01:55 -0200655 if (err < 0)
656 pr_err("Couldn't record kernel reference relocation symbol\n"
657 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
658 "Check /proc/kallsyms permission or run as root.\n");
Arnaldo Carvalho de Melo56b03f32010-01-05 16:50:31 -0200659
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200660 err = perf_event__synthesize_modules(process_synthesized_event,
661 session, machine);
Arnaldo Carvalho de Meloc1a3a4b2010-11-22 14:01:55 -0200662 if (err < 0)
663 pr_err("Couldn't record kernel module information.\n"
664 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
665 "Check /proc/modules permission or run as root.\n");
666
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800667 if (perf_guest)
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200668 perf_session__process_machines(session,
669 perf_event__synthesize_guest_os);
Arnaldo Carvalho de Melob7cece72010-01-13 13:22:17 -0200670
Stephane Eraniancf103a12010-06-16 20:59:01 +0200671 if (!system_wide)
Arnaldo Carvalho de Melo7c940c12011-02-11 11:45:54 -0200672 perf_event__synthesize_thread_map(evsel_list->threads,
673 process_synthesized_event,
674 session);
Arnaldo Carvalho de Melo234fbbf2009-10-26 19:23:18 -0200675 else
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200676 perf_event__synthesize_threads(process_synthesized_event,
677 session);
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +0200678
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200679 if (realtime_prio) {
680 struct sched_param param;
681
682 param.sched_priority = realtime_prio;
683 if (sched_setscheduler(0, SCHED_FIFO, &param)) {
Arnaldo Carvalho de Melo6beba7a2009-10-21 17:34:06 -0200684 pr_err("Could not set realtime priority.\n");
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200685 exit(-1);
686 }
687 }
688
Peter Zijlstra856e9662009-12-16 17:55:55 +0100689 /*
690 * Let the child rip
691 */
Arnaldo Carvalho de Melod4db3f12009-12-27 21:36:57 -0200692 if (forks)
693 close(go_pipe[1]);
Peter Zijlstra856e9662009-12-16 17:55:55 +0100694
Peter Zijlstra649c48a2009-06-24 21:12:48 +0200695 for (;;) {
Ingo Molnar2debbc82009-06-05 14:29:10 +0200696 int hits = samples;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200697
Frederic Weisbecker98402802010-05-02 22:05:29 +0200698 mmap_read_all();
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200699
Peter Zijlstra649c48a2009-06-24 21:12:48 +0200700 if (hits == samples) {
701 if (done)
702 break;
Arnaldo Carvalho de Melo5c581042011-01-11 22:30:02 -0200703 err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1);
Peter Zijlstra8b412662009-09-17 19:59:05 +0200704 waking++;
705 }
706
Arnaldo Carvalho de Melo4152ab32011-07-25 11:06:19 -0300707 if (done)
708 perf_evlist__disable(evsel_list);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200709 }
710
Arnaldo Carvalho de Melo18483b82010-12-06 15:13:38 -0200711 if (quiet || signr == SIGUSR1)
Arnaldo Carvalho de Melob44308f2010-10-26 15:20:09 -0200712 return 0;
713
Peter Zijlstra8b412662009-09-17 19:59:05 +0200714 fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
715
Ingo Molnar021e9f42009-06-03 19:27:19 +0200716 /*
717 * Approximate RIP event size: 24 bytes.
718 */
719 fprintf(stderr,
Arnaldo Carvalho de Melo9486aa32011-01-22 20:37:02 -0200720 "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
Ingo Molnar021e9f42009-06-03 19:27:19 +0200721 (double)bytes_written / 1024.0 / 1024.0,
722 output_name,
723 bytes_written / 24);
Ingo Molnaraddc2782009-06-02 23:43:11 +0200724
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200725 return 0;
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300726
727out_delete_session:
728 perf_session__delete(session);
729 return err;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200730}
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200731
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200732static const char * const record_usage[] = {
Mike Galbraith9e0967532009-05-28 16:25:34 +0200733 "perf record [<options>] [<command>]",
734 "perf record [<options>] -- <command> [<options>]",
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200735 NULL
736};
737
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200738static bool force, append_file;
739
Tom Zanussibca647a2010-11-10 08:11:30 -0600740const struct option record_options[] = {
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200741 OPT_CALLBACK('e', "event", &evsel_list, "event",
Thomas Gleixner86847b62009-06-06 12:24:17 +0200742 "event selector. use 'perf list' to list available events",
Jiri Olsaf120f9d2011-07-14 11:25:32 +0200743 parse_events_option),
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200744 OPT_CALLBACK(0, "filter", &evsel_list, "filter",
Li Zefanc171b552009-10-15 11:22:07 +0800745 "event filter", parse_filter),
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200746 OPT_INTEGER('p', "pid", &target_pid,
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300747 "record events on existing process id"),
748 OPT_INTEGER('t', "tid", &target_tid,
749 "record events on existing thread id"),
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200750 OPT_INTEGER('r', "realtime", &realtime_prio,
751 "collect data with this RT SCHED_FIFO priority"),
Kirill Smelkovacac03f2011-01-12 17:59:36 +0300752 OPT_BOOLEAN('D', "no-delay", &nodelay,
753 "collect data without buffering"),
Frederic Weisbeckerdaac07b2009-08-13 10:27:19 +0200754 OPT_BOOLEAN('R', "raw-samples", &raw_samples,
755 "collect raw sample records from all opened counters"),
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200756 OPT_BOOLEAN('a', "all-cpus", &system_wide,
757 "system-wide collection from all CPUs"),
Ingo Molnarabaff322009-06-02 22:59:57 +0200758 OPT_BOOLEAN('A', "append", &append_file,
759 "append to the output file to do incremental profiling"),
Stephane Eranianc45c6ea2010-05-28 12:00:01 +0200760 OPT_STRING('C', "cpu", &cpu_list, "cpu",
761 "list of cpus to monitor"),
Peter Zijlstra97124d52009-06-02 15:52:24 +0200762 OPT_BOOLEAN('f', "force", &force,
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200763 "overwrite existing data file (deprecated)"),
Stephane Eranian3de29ca2010-05-17 12:20:43 -0300764 OPT_U64('c', "count", &user_interval, "event period to sample"),
Ingo Molnarabaff322009-06-02 22:59:57 +0200765 OPT_STRING('o', "output", &output_name, "file",
766 "output file name"),
Stephane Eranian2e6cdf92010-05-12 10:40:01 +0200767 OPT_BOOLEAN('i', "no-inherit", &no_inherit,
768 "child tasks do not inherit counters"),
Arnaldo Carvalho de Melo19679362010-05-17 15:39:16 -0300769 OPT_UINTEGER('F', "freq", &user_freq, "profile at this frequency"),
770 OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"),
Lin Ming43bece72011-08-17 18:42:07 +0800771 OPT_BOOLEAN(0, "group", &group,
772 "put the counters into a counter group"),
Ingo Molnar3efa1cc92009-06-14 15:04:15 +0200773 OPT_BOOLEAN('g', "call-graph", &call_graph,
774 "do call-graph (stack chain/backtrace) recording"),
Ian Munsiec0555642010-04-13 18:37:33 +1000775 OPT_INCR('v', "verbose", &verbose,
Ingo Molnar3da297a2009-06-07 17:39:02 +0200776 "be more verbose (show counter open errors, etc)"),
Arnaldo Carvalho de Melob44308f2010-10-26 15:20:09 -0200777 OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
Peter Zijlstra649c48a2009-06-24 21:12:48 +0200778 OPT_BOOLEAN('s', "stat", &inherit_stat,
779 "per thread counts"),
Anton Blanchard4bba8282009-07-16 15:44:29 +0200780 OPT_BOOLEAN('d', "data", &sample_address,
781 "Sample addresses"),
Arnaldo Carvalho de Melo9c90a612010-12-02 10:25:28 -0200782 OPT_BOOLEAN('T', "timestamp", &sample_time, "Sample timestamps"),
Peter Zijlstra649c48a2009-06-24 21:12:48 +0200783 OPT_BOOLEAN('n', "no-samples", &no_samples,
784 "don't sample"),
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -0200785 OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid_cache,
Stephane Eraniana1ac1d32010-06-17 11:39:01 +0200786 "do not update the buildid cache"),
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -0200787 OPT_BOOLEAN('B', "no-buildid", &no_buildid,
788 "do not collect buildids in perf.data"),
Stephane Eranian023695d2011-02-14 11:20:01 +0200789 OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
790 "monitor event in cgroup name only",
791 parse_cgroups),
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200792 OPT_END()
793};
794
Ingo Molnarf37a2912009-07-01 12:37:06 +0200795int cmd_record(int argc, const char **argv, const char *prefix __used)
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200796{
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200797 int err = -ENOMEM;
798 struct perf_evsel *pos;
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200799
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200800 evsel_list = perf_evlist__new(NULL, NULL);
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200801 if (evsel_list == NULL)
802 return -ENOMEM;
803
Tom Zanussibca647a2010-11-10 08:11:30 -0600804 argc = parse_options(argc, argv, record_options, record_usage,
Arnaldo Carvalho de Melo655000e2009-12-15 20:04:40 -0200805 PARSE_OPT_STOP_AT_NON_OPTION);
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300806 if (!argc && target_pid == -1 && target_tid == -1 &&
Stephane Eranianc45c6ea2010-05-28 12:00:01 +0200807 !system_wide && !cpu_list)
Tom Zanussibca647a2010-11-10 08:11:30 -0600808 usage_with_options(record_usage, record_options);
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200809
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200810 if (force && append_file) {
811 fprintf(stderr, "Can't overwrite and append at the same time."
812 " You need to choose between -f and -A");
Tom Zanussibca647a2010-11-10 08:11:30 -0600813 usage_with_options(record_usage, record_options);
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200814 } else if (append_file) {
815 write_mode = WRITE_APPEND;
816 } else {
817 write_mode = WRITE_FORCE;
818 }
819
Stephane Eranian023695d2011-02-14 11:20:01 +0200820 if (nr_cgroups && !system_wide) {
821 fprintf(stderr, "cgroup monitoring only available in"
822 " system-wide mode\n");
823 usage_with_options(record_usage, record_options);
824 }
825
Arnaldo Carvalho de Melo655000e2009-12-15 20:04:40 -0200826 symbol__init();
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -0200827
Arnaldo Carvalho de Meloec80fde2011-05-26 09:53:51 -0300828 if (symbol_conf.kptr_restrict)
Arnaldo Carvalho de Melo646aaea2011-05-27 11:00:41 -0300829 pr_warning(
830"WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
831"check /proc/sys/kernel/kptr_restrict.\n\n"
832"Samples in kernel functions may not be resolved if a suitable vmlinux\n"
833"file is not found in the buildid cache or in the vmlinux path.\n\n"
834"Samples in kernel modules won't be resolved at all.\n\n"
835"If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
836"even with a suitable vmlinux or kallsyms file.\n\n");
Arnaldo Carvalho de Meloec80fde2011-05-26 09:53:51 -0300837
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -0200838 if (no_buildid_cache || no_buildid)
Stephane Eraniana1ac1d32010-06-17 11:39:01 +0200839 disable_buildid_cache();
Arnaldo Carvalho de Melo655000e2009-12-15 20:04:40 -0200840
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200841 if (evsel_list->nr_entries == 0 &&
842 perf_evlist__add_default(evsel_list) < 0) {
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200843 pr_err("Not enough memory for event selector list\n");
844 goto out_symbol_exit;
Peter Zijlstrabbd36e52009-06-11 23:11:50 +0200845 }
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200846
Arnaldo Carvalho de Melo5c98d4662011-01-03 17:53:33 -0200847 if (target_pid != -1)
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300848 target_tid = target_pid;
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300849
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200850 if (perf_evlist__create_maps(evsel_list, target_pid,
851 target_tid, cpu_list) < 0)
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200852 usage_with_options(record_usage, record_options);
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200853
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200854 list_for_each_entry(pos, &evsel_list->entries, node) {
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200855 if (perf_evsel__alloc_fd(pos, evsel_list->cpus->nr,
856 evsel_list->threads->nr) < 0)
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200857 goto out_free_fd;
Arnaldo Carvalho de Meload7f4e32011-01-17 18:28:13 -0200858 if (perf_header__push_event(pos->attr.config, event_name(pos)))
859 goto out_free_fd;
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300860 }
Arnaldo Carvalho de Melo5c581042011-01-11 22:30:02 -0200861
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200862 if (perf_evlist__alloc_pollfd(evsel_list) < 0)
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300863 goto out_free_fd;
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300864
Stephane Eranian3de29ca2010-05-17 12:20:43 -0300865 if (user_interval != ULLONG_MAX)
Frederic Weisbeckerf9212812010-04-14 22:09:02 +0200866 default_interval = user_interval;
867 if (user_freq != UINT_MAX)
868 freq = user_freq;
869
Mike Galbraith7e4ff9e2009-10-12 07:56:03 +0200870 /*
871 * User specified count overrides default frequency.
872 */
873 if (default_interval)
874 freq = 0;
875 else if (freq) {
876 default_interval = freq;
877 } else {
878 fprintf(stderr, "frequency and count are zero, aborting\n");
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300879 err = -EINVAL;
Arnaldo Carvalho de Melo5c581042011-01-11 22:30:02 -0200880 goto out_free_fd;
Mike Galbraith7e4ff9e2009-10-12 07:56:03 +0200881 }
882
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300883 err = __cmd_record(argc, argv);
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300884out_free_fd:
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200885 perf_evlist__delete_maps(evsel_list);
Arnaldo Carvalho de Melod65a4582010-07-30 18:31:28 -0300886out_symbol_exit:
887 symbol__exit();
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300888 return err;
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200889}