blob: f6426b496f4aa0ee59c25a84622fc12c2dec32ff [file] [log] [blame]
Ingo Molnarabaff322009-06-02 22:59:57 +02001/*
Ingo Molnarbf9e1872009-06-02 23:37:05 +02002 * builtin-record.c
3 *
4 * Builtin record command: Record the profile of a workload
5 * (or a CPU, or a PID) into the perf.data output file - for
6 * later analysis via perf report.
Ingo Molnarabaff322009-06-02 22:59:57 +02007 */
Xiao Guangrongb8f46c52010-02-03 11:53:14 +08008#define _FILE_OFFSET_BITS 64
9
Ingo Molnar16f762a2009-05-27 09:10:38 +020010#include "builtin.h"
Ingo Molnarbf9e1872009-06-02 23:37:05 +020011
12#include "perf.h"
13
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -020014#include "util/build-id.h"
Thomas Gleixner6eda5832009-05-01 18:29:57 +020015#include "util/util.h"
Ingo Molnar0e9b20b2009-05-26 09:17:18 +020016#include "util/parse-options.h"
Ingo Molnar8ad8db32009-05-26 11:10:09 +020017#include "util/parse-events.h"
Thomas Gleixner6eda5832009-05-01 18:29:57 +020018
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020019#include "util/header.h"
Frederic Weisbecker66e274f2009-08-12 11:07:25 +020020#include "util/event.h"
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -020021#include "util/evlist.h"
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -020022#include "util/evsel.h"
Frederic Weisbecker8f288272009-08-16 22:05:48 +020023#include "util/debug.h"
Arnaldo Carvalho de Melo94c744b2009-12-11 21:24:02 -020024#include "util/session.h"
Arnaldo Carvalho de Melo8d063672009-11-04 18:50:43 -020025#include "util/symbol.h"
Paul Mackerrasa12b51c2010-03-10 20:36:09 +110026#include "util/cpumap.h"
Arnaldo Carvalho de Melofd782602011-01-18 15:15:24 -020027#include "util/thread_map.h"
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020028
Peter Zijlstra97124d52009-06-02 15:52:24 +020029#include <unistd.h>
Peter Zijlstrade9ac072009-04-08 15:01:31 +020030#include <sched.h>
Arnaldo Carvalho de Meloa41794c2010-05-18 18:29:23 -030031#include <sys/mman.h>
Peter Zijlstrade9ac072009-04-08 15:01:31 +020032
Frederic Weisbecker7865e812010-04-14 19:42:07 +020033enum write_mode_t {
34 WRITE_FORCE,
35 WRITE_APPEND
36};
37
Stephane Eranian3de29ca2010-05-17 12:20:43 -030038static u64 user_interval = ULLONG_MAX;
39static u64 default_interval = 0;
Ingo Molnara21ca2c2009-06-06 09:58:57 +020040
Peter Zijlstrade9ac072009-04-08 15:01:31 +020041static unsigned int page_size;
Frederic Weisbecker800cd252011-03-31 03:35:24 +020042static unsigned int mmap_pages = UINT_MAX;
Frederic Weisbeckerf9212812010-04-14 22:09:02 +020043static unsigned int user_freq = UINT_MAX;
Ingo Molnar42e59d72009-10-06 15:14:21 +020044static int freq = 1000;
Peter Zijlstrade9ac072009-04-08 15:01:31 +020045static int output;
Tom Zanussi529870e2010-04-01 23:59:16 -050046static int pipe_output = 0;
Franck Bui-Huud7065ad2011-01-16 17:14:45 +010047static const char *output_name = NULL;
Ingo Molnar42e59d72009-10-06 15:14:21 +020048static int group = 0;
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;
Peter Zijlstraf5970552009-06-18 23:22:55 +020076
Tom Zanussi92155452010-04-01 23:59:21 -050077static void advance_output(size_t size)
78{
79 bytes_written += size;
80}
81
Peter Zijlstraf5970552009-06-18 23:22:55 +020082static void write_output(void *buf, size_t size)
83{
84 while (size) {
85 int ret = write(output, buf, size);
86
87 if (ret < 0)
88 die("failed to write");
89
90 size -= ret;
91 buf += ret;
92
93 bytes_written += ret;
94 }
95}
96
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -020097static int process_synthesized_event(union perf_event *event,
Arnaldo Carvalho de Melo8d50e5b2011-01-29 13:02:00 -020098 struct perf_sample *sample __used,
Arnaldo Carvalho de Melod8f66242009-12-13 19:50:24 -020099 struct perf_session *self __used)
Arnaldo Carvalho de Melo234fbbf2009-10-26 19:23:18 -0200100{
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -0200101 write_output(event, event->header.size);
Arnaldo Carvalho de Melo234fbbf2009-10-26 19:23:18 -0200102 return 0;
103}
104
Arnaldo Carvalho de Melo744bd8a2011-01-12 17:07:28 -0200105static void mmap_read(struct perf_mmap *md)
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200106{
Arnaldo Carvalho de Melo744bd8a2011-01-12 17:07:28 -0200107 unsigned int head = perf_mmap__read_head(md);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200108 unsigned int old = md->prev;
109 unsigned char *data = md->base + page_size;
110 unsigned long size;
111 void *buf;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200112
Arnaldo Carvalho de Melodc820092011-01-28 14:49:19 -0200113 if (old == head)
114 return;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200115
Arnaldo Carvalho de Melodc820092011-01-28 14:49:19 -0200116 samples++;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200117
118 size = head - old;
119
120 if ((old & md->mask) + size != (head & md->mask)) {
121 buf = &data[old & md->mask];
122 size = md->mask + 1 - (old & md->mask);
123 old += size;
Ingo Molnar021e9f42009-06-03 19:27:19 +0200124
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -0200125 write_output(buf, size);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200126 }
127
128 buf = &data[old & md->mask];
129 size = head - old;
130 old += size;
Ingo Molnar021e9f42009-06-03 19:27:19 +0200131
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -0200132 write_output(buf, size);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200133
134 md->prev = old;
Arnaldo Carvalho de Melo115d2d82011-01-12 17:11:53 -0200135 perf_mmap__write_tail(md, old);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200136}
137
138static volatile int done = 0;
Peter Zijlstraf7b7c262009-06-10 15:55:59 +0200139static volatile int signr = -1;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200140
Peter Zijlstra16c8a102009-05-05 17:50:27 +0200141static void sig_handler(int sig)
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200142{
Peter Zijlstra16c8a102009-05-05 17:50:27 +0200143 done = 1;
Peter Zijlstraf7b7c262009-06-10 15:55:59 +0200144 signr = sig;
145}
146
147static void sig_atexit(void)
148{
Ian Munsie5ffc8882010-06-09 18:38:00 +1000149 if (child_pid > 0)
Chris Wilson933da832009-10-04 01:35:01 +0100150 kill(child_pid, SIGTERM);
151
Arnaldo Carvalho de Melo18483b82010-12-06 15:13:38 -0200152 if (signr == -1 || signr == SIGUSR1)
Peter Zijlstraf7b7c262009-06-10 15:55:59 +0200153 return;
154
155 signal(signr, SIG_DFL);
156 kill(getpid(), signr);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200157}
158
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200159static void config_attr(struct perf_evsel *evsel, struct perf_evlist *evlist)
160{
161 struct perf_event_attr *attr = &evsel->attr;
162 int track = !evsel->idx; /* only the first counter needs these */
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +0200163
Arnaldo Carvalho de Melo5d2cd902011-04-14 11:20:14 -0300164 attr->inherit = !no_inherit;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +0200165 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
166 PERF_FORMAT_TOTAL_TIME_RUNNING |
167 PERF_FORMAT_ID;
Peter Zijlstra16c8a102009-05-05 17:50:27 +0200168
Frederic Weisbecker3a9f1312009-08-13 10:27:18 +0200169 attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
Ingo Molnar3efa1cc92009-06-14 15:04:15 +0200170
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200171 if (evlist->nr_entries > 1)
Eric B Munson8907fd62010-03-05 12:51:05 -0300172 attr->sample_type |= PERF_SAMPLE_ID;
173
Frederic Weisbeckerf9212812010-04-14 22:09:02 +0200174 /*
175 * We default some events to a 1 default interval. But keep
176 * it a weak assumption overridable by the user.
177 */
178 if (!attr->sample_period || (user_freq != UINT_MAX &&
Stephane Eranian3de29ca2010-05-17 12:20:43 -0300179 user_interval != ULLONG_MAX)) {
Frederic Weisbeckerf9212812010-04-14 22:09:02 +0200180 if (freq) {
181 attr->sample_type |= PERF_SAMPLE_PERIOD;
182 attr->freq = 1;
183 attr->sample_freq = freq;
184 } else {
185 attr->sample_period = default_interval;
186 }
Ingo Molnar1dba15e2009-06-05 18:37:22 +0200187 }
Ingo Molnar3efa1cc92009-06-14 15:04:15 +0200188
Peter Zijlstra649c48a2009-06-24 21:12:48 +0200189 if (no_samples)
190 attr->sample_freq = 0;
191
192 if (inherit_stat)
193 attr->inherit_stat = 1;
194
Eric B Munson3af9e852010-05-18 15:30:49 +0100195 if (sample_address) {
Anton Blanchard4bba8282009-07-16 15:44:29 +0200196 attr->sample_type |= PERF_SAMPLE_ADDR;
Eric B Munson3af9e852010-05-18 15:30:49 +0100197 attr->mmap_data = track;
198 }
Anton Blanchard4bba8282009-07-16 15:44:29 +0200199
Ingo Molnar3efa1cc92009-06-14 15:04:15 +0200200 if (call_graph)
201 attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
202
Arun Sharmaf60f3592010-06-04 11:27:10 -0300203 if (system_wide)
204 attr->sample_type |= PERF_SAMPLE_CPU;
205
Arnaldo Carvalho de Meloa43d3f02010-12-25 12:12:25 -0200206 if (sample_id_all_avail &&
207 (sample_time || system_wide || !no_inherit || cpu_list))
Arnaldo Carvalho de Melo9c90a612010-12-02 10:25:28 -0200208 attr->sample_type |= PERF_SAMPLE_TIME;
209
Ingo Molnarcd6feee2009-09-02 20:20:38 +0200210 if (raw_samples) {
Ingo Molnar6ddf2592009-09-03 12:00:22 +0200211 attr->sample_type |= PERF_SAMPLE_TIME;
Frederic Weisbeckerdaac07b2009-08-13 10:27:19 +0200212 attr->sample_type |= PERF_SAMPLE_RAW;
Ingo Molnarcd6feee2009-09-02 20:20:38 +0200213 attr->sample_type |= PERF_SAMPLE_CPU;
214 }
Frederic Weisbeckerf413cdb2009-08-07 01:25:54 +0200215
Kirill Smelkovacac03f2011-01-12 17:59:36 +0300216 if (nodelay) {
217 attr->watermark = 0;
218 attr->wakeup_events = 1;
219 }
220
Ingo Molnara21ca2c2009-06-06 09:58:57 +0200221 attr->mmap = track;
222 attr->comm = track;
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200223
Stephane Eranian2e6cdf92010-05-12 10:40:01 +0200224 if (target_pid == -1 && target_tid == -1 && !system_wide) {
Zhang, Yanmin46be6042010-03-18 11:36:04 -0300225 attr->disabled = 1;
Eric B Munsonbedbfde2010-03-15 11:46:57 -0300226 attr->enable_on_exec = 1;
Zhang, Yanmin46be6042010-03-18 11:36:04 -0300227 }
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200228}
229
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300230static bool perf_evlist__equal(struct perf_evlist *evlist,
231 struct perf_evlist *other)
232{
233 struct perf_evsel *pos, *pair;
234
235 if (evlist->nr_entries != other->nr_entries)
236 return false;
237
238 pair = list_entry(other->entries.next, struct perf_evsel, node);
239
240 list_for_each_entry(pos, &evlist->entries, node) {
241 if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0))
242 return false;
243 pair = list_entry(pair->node.next, struct perf_evsel, node);
244 }
245
246 return true;
247}
248
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200249static void open_counters(struct perf_evlist *evlist)
250{
251 struct perf_evsel *pos;
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200252
Arnaldo Carvalho de Melo5d2cd902011-04-14 11:20:14 -0300253 if (evlist->cpus->map[0] < 0)
254 no_inherit = true;
255
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200256 list_for_each_entry(pos, &evlist->entries, node) {
257 struct perf_event_attr *attr = &pos->attr;
258 /*
259 * Check if parse_single_tracepoint_event has already asked for
260 * PERF_SAMPLE_TIME.
261 *
262 * XXX this is kludgy but short term fix for problems introduced by
263 * eac23d1c that broke 'perf script' by having different sample_types
264 * when using multiple tracepoint events when we use a perf binary
265 * that tries to use sample_id_all on an older kernel.
266 *
267 * We need to move counter creation to perf_session, support
268 * different sample_types, etc.
269 */
270 bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
271
272 config_attr(pos, evlist);
Arnaldo Carvalho de Melo9c90a612010-12-02 10:25:28 -0200273retry_sample_id:
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200274 attr->sample_id_all = sample_id_all_avail ? 1 : 0;
Ingo Molnar3da297a2009-06-07 17:39:02 +0200275try_again:
Arnaldo Carvalho de Melo5d2cd902011-04-14 11:20:14 -0300276 if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group) < 0) {
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300277 int err = errno;
Ingo Molnarf250c0302009-06-05 13:18:41 +0200278
Arnaldo Carvalho de Meloc286c412011-03-28 09:50:11 -0300279 if (err == EPERM || err == EACCES) {
280 ui__warning_paranoid();
281 exit(EXIT_FAILURE);
282 } else if (err == ENODEV && cpu_list) {
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300283 die("No such device - did you specify"
284 " an out-of-range profile CPU?\n");
Arnaldo Carvalho de Melo9c90a612010-12-02 10:25:28 -0200285 } else if (err == EINVAL && sample_id_all_avail) {
286 /*
287 * Old kernel, no attr->sample_id_type_all field
288 */
289 sample_id_all_avail = false;
Arnaldo Carvalho de Meloa43d3f02010-12-25 12:12:25 -0200290 if (!sample_time && !raw_samples && !time_needed)
Ian Munsieeac23d12010-12-09 16:33:53 +1100291 attr->sample_type &= ~PERF_SAMPLE_TIME;
292
Arnaldo Carvalho de Melo9c90a612010-12-02 10:25:28 -0200293 goto retry_sample_id;
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300294 }
Ingo Molnar3da297a2009-06-07 17:39:02 +0200295
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300296 /*
297 * If it's cycles then fall back to hrtimer
298 * based cpu-clock-tick sw counter, which
299 * is always available even if no PMU support:
300 */
301 if (attr->type == PERF_TYPE_HARDWARE
302 && attr->config == PERF_COUNT_HW_CPU_CYCLES) {
Ingo Molnar3da297a2009-06-07 17:39:02 +0200303
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300304 if (verbose)
David Ahernca6a4252011-03-25 13:11:11 -0600305 ui__warning("The cycles event is not supported, "
306 "trying to fall back to cpu-clock-ticks\n");
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300307 attr->type = PERF_TYPE_SOFTWARE;
308 attr->config = PERF_COUNT_SW_CPU_CLOCK;
309 goto try_again;
310 }
David Ahernca6a4252011-03-25 13:11:11 -0600311
312 if (err == ENOENT) {
313 ui__warning("The %s event is not supported.\n",
314 event_name(pos));
315 exit(EXIT_FAILURE);
316 }
317
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300318 printf("\n");
Corey Ashfordd9cf8372010-11-19 17:37:24 -0800319 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 -0200320 err, strerror(err));
Simon Kaempfleinbfd45112009-11-16 15:25:53 +1000321
322#if defined(__i386__) || defined(__x86_64__)
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300323 if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP)
324 die("No hardware sampling interrupt available."
325 " No APIC? If so then you can boot the kernel"
326 " with the \"lapic\" boot parameter to"
327 " force-enable it.\n");
Simon Kaempfleinbfd45112009-11-16 15:25:53 +1000328#endif
329
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300330 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300331 }
Li Zefanc171b552009-10-15 11:22:07 +0800332 }
Arnaldo Carvalho de Meloa43d3f02010-12-25 12:12:25 -0200333
Frederic Weisbecker0a102472011-02-26 04:51:54 +0100334 if (perf_evlist__set_filters(evlist)) {
335 error("failed to set filter with %d (%s)\n", errno,
336 strerror(errno));
337 exit(-1);
338 }
339
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200340 if (perf_evlist__mmap(evlist, mmap_pages, false) < 0)
Arnaldo Carvalho de Melo0a27d7f2011-01-14 15:50:51 -0200341 die("failed to mmap with %d (%s)\n", errno, strerror(errno));
342
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300343 if (file_new)
344 session->evlist = evlist;
345 else {
346 if (!perf_evlist__equal(session->evlist, evlist)) {
347 fprintf(stderr, "incompatible append\n");
348 exit(-1);
349 }
350 }
351
352 perf_session__update_sample_type(session);
Peter Zijlstra16c8a102009-05-05 17:50:27 +0200353}
354
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -0200355static int process_buildids(void)
356{
357 u64 size = lseek(output, 0, SEEK_CUR);
358
Arnaldo Carvalho de Melo9f591fd2010-03-11 15:53:11 -0300359 if (size == 0)
360 return 0;
361
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -0200362 session->fd = output;
363 return __perf_session__process_events(session, post_processing_offset,
364 size - post_processing_offset,
365 size, &build_id__mark_dso_hit_ops);
366}
367
Peter Zijlstraf5970552009-06-18 23:22:55 +0200368static void atexit_header(void)
369{
Tom Zanussic7929e42010-04-01 23:59:22 -0500370 if (!pipe_output) {
371 session->header.data_size += bytes_written;
Peter Zijlstraf5970552009-06-18 23:22:55 +0200372
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -0200373 if (!no_buildid)
374 process_buildids();
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300375 perf_session__write_header(session, evsel_list, output, true);
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300376 perf_session__delete(session);
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200377 perf_evlist__delete(evsel_list);
Arnaldo Carvalho de Melod65a4582010-07-30 18:31:28 -0300378 symbol__exit();
Tom Zanussic7929e42010-04-01 23:59:22 -0500379 }
Peter Zijlstraf5970552009-06-18 23:22:55 +0200380}
381
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200382static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800383{
384 int err;
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -0300385 struct perf_session *psession = data;
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800386
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -0300387 if (machine__is_host(machine))
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800388 return;
389
390 /*
391 *As for guest kernel when processing subcommand record&report,
392 *we arrange module mmap prior to guest kernel mmap and trigger
393 *a preload dso because default guest module symbols are loaded
394 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
395 *method is used to avoid symbol missing when the first addr is
396 *in module instead of in guest kernel.
397 */
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200398 err = perf_event__synthesize_modules(process_synthesized_event,
399 psession, machine);
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800400 if (err < 0)
401 pr_err("Couldn't record guest kernel [%d]'s reference"
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -0300402 " relocation symbol.\n", machine->pid);
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800403
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800404 /*
405 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
406 * have no _text sometimes.
407 */
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200408 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
409 psession, machine, "_text");
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800410 if (err < 0)
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200411 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
412 psession, machine,
413 "_stext");
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800414 if (err < 0)
415 pr_err("Couldn't record guest kernel [%d]'s reference"
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -0300416 " relocation symbol.\n", machine->pid);
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800417}
418
Frederic Weisbecker98402802010-05-02 22:05:29 +0200419static struct perf_event_header finished_round_event = {
420 .size = sizeof(struct perf_event_header),
421 .type = PERF_RECORD_FINISHED_ROUND,
422};
423
424static void mmap_read_all(void)
425{
Peter Zijlstra0e2e63d2010-05-20 14:45:26 +0200426 int i;
Frederic Weisbecker98402802010-05-02 22:05:29 +0200427
Arnaldo Carvalho de Meloaece9482011-05-15 09:39:00 -0300428 for (i = 0; i < evsel_list->nr_mmaps; i++) {
Arnaldo Carvalho de Melo0a27d7f2011-01-14 15:50:51 -0200429 if (evsel_list->mmap[i].base)
430 mmap_read(&evsel_list->mmap[i]);
Frederic Weisbecker98402802010-05-02 22:05:29 +0200431 }
432
433 if (perf_header__has_feat(&session->header, HEADER_TRACE_INFO))
434 write_output(&finished_round_event, sizeof(finished_round_event));
435}
436
Arnaldo Carvalho de Melod4db3f12009-12-27 21:36:57 -0200437static int __cmd_record(int argc, const char **argv)
Peter Zijlstra16c8a102009-05-05 17:50:27 +0200438{
Peter Zijlstra97124d52009-06-02 15:52:24 +0200439 struct stat st;
Ingo Molnarabaff322009-06-02 22:59:57 +0200440 int flags;
Arnaldo Carvalho de Melo4dc0a042009-11-19 14:55:55 -0200441 int err;
Peter Zijlstra8b412662009-09-17 19:59:05 +0200442 unsigned long waking = 0;
Peter Zijlstra856e9662009-12-16 17:55:55 +0100443 int child_ready_pipe[2], go_pipe[2];
Zhang, Yanmin46be6042010-03-18 11:36:04 -0300444 const bool forks = argc > 0;
Peter Zijlstra856e9662009-12-16 17:55:55 +0100445 char buf;
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -0300446 struct machine *machine;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200447
448 page_size = sysconf(_SC_PAGE_SIZE);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200449
Peter Zijlstraf5970552009-06-18 23:22:55 +0200450 atexit(sig_atexit);
451 signal(SIGCHLD, sig_handler);
452 signal(SIGINT, sig_handler);
Arnaldo Carvalho de Melo18483b82010-12-06 15:13:38 -0200453 signal(SIGUSR1, sig_handler);
Peter Zijlstraf5970552009-06-18 23:22:55 +0200454
Arnaldo Carvalho de Melod4db3f12009-12-27 21:36:57 -0200455 if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
Peter Zijlstra856e9662009-12-16 17:55:55 +0100456 perror("failed to create pipes");
457 exit(-1);
458 }
459
Franck Bui-Huud7065ad2011-01-16 17:14:45 +0100460 if (!output_name) {
461 if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
462 pipe_output = 1;
463 else
464 output_name = "perf.data";
465 }
466 if (output_name) {
467 if (!strcmp(output_name, "-"))
468 pipe_output = 1;
469 else if (!stat(output_name, &st) && st.st_size) {
470 if (write_mode == WRITE_FORCE) {
471 char oldname[PATH_MAX];
472 snprintf(oldname, sizeof(oldname), "%s.old",
473 output_name);
474 unlink(oldname);
475 rename(output_name, oldname);
476 }
477 } else if (write_mode == WRITE_APPEND) {
478 write_mode = WRITE_FORCE;
Pierre Habouzit266e0e22009-08-07 14:16:01 +0200479 }
Peter Zijlstra97124d52009-06-02 15:52:24 +0200480 }
481
Xiao Guangrongf887f302010-02-04 16:46:42 +0800482 flags = O_CREAT|O_RDWR;
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200483 if (write_mode == WRITE_APPEND)
Peter Zijlstraf5970552009-06-18 23:22:55 +0200484 file_new = 0;
Ingo Molnarabaff322009-06-02 22:59:57 +0200485 else
486 flags |= O_TRUNC;
487
Tom Zanussi529870e2010-04-01 23:59:16 -0500488 if (pipe_output)
489 output = STDOUT_FILENO;
490 else
491 output = open(output_name, flags, S_IRUSR | S_IWUSR);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200492 if (output < 0) {
493 perror("failed to create output file");
494 exit(-1);
495 }
496
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200497 session = perf_session__new(output_name, O_WRONLY,
Ian Munsie21ef97f2010-12-10 14:09:16 +1100498 write_mode == WRITE_FORCE, false, NULL);
Arnaldo Carvalho de Melo94c744b2009-12-11 21:24:02 -0200499 if (session == NULL) {
Arnaldo Carvalho de Meloa9a70bb2009-11-17 01:18:11 -0200500 pr_err("Not enough memory for reading perf file header\n");
501 return -1;
502 }
503
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -0200504 if (!no_buildid)
505 perf_header__set_feat(&session->header, HEADER_BUILD_ID);
506
Arnaldo Carvalho de Melo4dc0a042009-11-19 14:55:55 -0200507 if (!file_new) {
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300508 err = perf_session__read_header(session, output);
Arnaldo Carvalho de Melo4dc0a042009-11-19 14:55:55 -0200509 if (err < 0)
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300510 goto out_delete_session;
Arnaldo Carvalho de Melo4dc0a042009-11-19 14:55:55 -0200511 }
512
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200513 if (have_tracepoints(&evsel_list->entries))
Arnaldo Carvalho de Melo94c744b2009-12-11 21:24:02 -0200514 perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
Frederic Weisbecker03456a12009-10-06 23:36:47 +0200515
Frederic Weisbecker800cd252011-03-31 03:35:24 +0200516 /* 512 kiB: default amount of unprivileged mlocked memory */
517 if (mmap_pages == UINT_MAX)
518 mmap_pages = (512 * 1024) / page_size;
519
Arnaldo Carvalho de Melod4db3f12009-12-27 21:36:57 -0200520 if (forks) {
Zhang, Yanmin46be6042010-03-18 11:36:04 -0300521 child_pid = fork();
Borislav Petkov2fb750e2010-05-31 23:18:18 +0200522 if (child_pid < 0) {
Peter Zijlstra856e9662009-12-16 17:55:55 +0100523 perror("failed to fork");
524 exit(-1);
Jens Axboe0a5ac842009-08-12 11:18:01 +0200525 }
Peter Zijlstra856e9662009-12-16 17:55:55 +0100526
Zhang, Yanmin46be6042010-03-18 11:36:04 -0300527 if (!child_pid) {
Tom Zanussi529870e2010-04-01 23:59:16 -0500528 if (pipe_output)
529 dup2(2, 1);
Peter Zijlstra856e9662009-12-16 17:55:55 +0100530 close(child_ready_pipe[0]);
531 close(go_pipe[1]);
532 fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
533
534 /*
535 * Do a dummy execvp to get the PLT entry resolved,
536 * so we avoid the resolver overhead on the real
537 * execvp call.
538 */
539 execvp("", (char **)argv);
540
541 /*
542 * Tell the parent we're ready to go
543 */
544 close(child_ready_pipe[1]);
545
546 /*
547 * Wait until the parent tells us to go.
548 */
549 if (read(go_pipe[0], &buf, 1) == -1)
550 perror("unable to read pipe");
551
552 execvp(argv[0], (char **)argv);
553
554 perror(argv[0]);
Arnaldo Carvalho de Melo18483b82010-12-06 15:13:38 -0200555 kill(getppid(), SIGUSR1);
Peter Zijlstra856e9662009-12-16 17:55:55 +0100556 exit(-1);
557 }
558
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300559 if (!system_wide && target_tid == -1 && target_pid == -1)
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200560 evsel_list->threads->map[0] = child_pid;
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300561
Peter Zijlstra856e9662009-12-16 17:55:55 +0100562 close(child_ready_pipe[1]);
563 close(go_pipe[0]);
564 /*
565 * wait for child to settle
566 */
567 if (read(child_ready_pipe[0], &buf, 1) == -1) {
568 perror("unable to read pipe");
569 exit(-1);
570 }
571 close(child_ready_pipe[0]);
572 }
573
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200574 open_counters(evsel_list);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200575
Arnaldo Carvalho de Melo712a4b62011-02-17 12:18:42 -0200576 /*
577 * perf_session__delete(session) will be called at atexit_header()
578 */
579 atexit(atexit_header);
580
Tom Zanussi529870e2010-04-01 23:59:16 -0500581 if (pipe_output) {
582 err = perf_header__write_pipe(output);
583 if (err < 0)
584 return err;
585 } else if (file_new) {
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300586 err = perf_session__write_header(session, evsel_list,
587 output, false);
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -0200588 if (err < 0)
589 return err;
590 }
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +0200591
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -0200592 post_processing_offset = lseek(output, 0, SEEK_CUR);
593
Tom Zanussi2c46dbb2010-04-01 23:59:19 -0500594 if (pipe_output) {
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300595 err = perf_session__synthesize_attrs(session,
596 process_synthesized_event);
Tom Zanussi2c46dbb2010-04-01 23:59:19 -0500597 if (err < 0) {
598 pr_err("Couldn't synthesize attrs.\n");
599 return err;
600 }
Tom Zanussicd19a032010-04-01 23:59:20 -0500601
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200602 err = perf_event__synthesize_event_types(process_synthesized_event,
603 session);
Tom Zanussicd19a032010-04-01 23:59:20 -0500604 if (err < 0) {
605 pr_err("Couldn't synthesize event_types.\n");
606 return err;
607 }
Tom Zanussi92155452010-04-01 23:59:21 -0500608
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200609 if (have_tracepoints(&evsel_list->entries)) {
Tom Zanussi63e0c772010-05-03 00:14:48 -0500610 /*
611 * FIXME err <= 0 here actually means that
612 * there were no tracepoints so its not really
613 * an error, just that we don't need to
614 * synthesize anything. We really have to
615 * return this more properly and also
616 * propagate errors that now are calling die()
617 */
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200618 err = perf_event__synthesize_tracing_data(output, evsel_list,
619 process_synthesized_event,
620 session);
Tom Zanussi63e0c772010-05-03 00:14:48 -0500621 if (err <= 0) {
622 pr_err("Couldn't record tracing data.\n");
623 return err;
624 }
Arnaldo Carvalho de Melo2c9faa02010-05-02 13:37:24 -0300625 advance_output(err);
Tom Zanussi63e0c772010-05-03 00:14:48 -0500626 }
Tom Zanussi2c46dbb2010-04-01 23:59:19 -0500627 }
628
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -0300629 machine = perf_session__find_host_machine(session);
630 if (!machine) {
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800631 pr_err("Couldn't find native kernel information.\n");
632 return -1;
633 }
634
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200635 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
636 session, machine, "_text");
Arnaldo Carvalho de Melo70162132010-03-30 18:27:39 -0300637 if (err < 0)
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200638 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
639 session, machine, "_stext");
Arnaldo Carvalho de Meloc1a3a4b2010-11-22 14:01:55 -0200640 if (err < 0)
641 pr_err("Couldn't record kernel reference relocation symbol\n"
642 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
643 "Check /proc/kallsyms permission or run as root.\n");
Arnaldo Carvalho de Melo56b03f32010-01-05 16:50:31 -0200644
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200645 err = perf_event__synthesize_modules(process_synthesized_event,
646 session, machine);
Arnaldo Carvalho de Meloc1a3a4b2010-11-22 14:01:55 -0200647 if (err < 0)
648 pr_err("Couldn't record kernel module information.\n"
649 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
650 "Check /proc/modules permission or run as root.\n");
651
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800652 if (perf_guest)
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200653 perf_session__process_machines(session,
654 perf_event__synthesize_guest_os);
Arnaldo Carvalho de Melob7cece72010-01-13 13:22:17 -0200655
Stephane Eraniancf103a12010-06-16 20:59:01 +0200656 if (!system_wide)
Arnaldo Carvalho de Melo7c940c12011-02-11 11:45:54 -0200657 perf_event__synthesize_thread_map(evsel_list->threads,
658 process_synthesized_event,
659 session);
Arnaldo Carvalho de Melo234fbbf2009-10-26 19:23:18 -0200660 else
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200661 perf_event__synthesize_threads(process_synthesized_event,
662 session);
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +0200663
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200664 if (realtime_prio) {
665 struct sched_param param;
666
667 param.sched_priority = realtime_prio;
668 if (sched_setscheduler(0, SCHED_FIFO, &param)) {
Arnaldo Carvalho de Melo6beba7a2009-10-21 17:34:06 -0200669 pr_err("Could not set realtime priority.\n");
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200670 exit(-1);
671 }
672 }
673
Peter Zijlstra856e9662009-12-16 17:55:55 +0100674 /*
675 * Let the child rip
676 */
Arnaldo Carvalho de Melod4db3f12009-12-27 21:36:57 -0200677 if (forks)
678 close(go_pipe[1]);
Peter Zijlstra856e9662009-12-16 17:55:55 +0100679
Peter Zijlstra649c48a2009-06-24 21:12:48 +0200680 for (;;) {
Ingo Molnar2debbc82009-06-05 14:29:10 +0200681 int hits = samples;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200682
Frederic Weisbecker98402802010-05-02 22:05:29 +0200683 mmap_read_all();
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200684
Peter Zijlstra649c48a2009-06-24 21:12:48 +0200685 if (hits == samples) {
686 if (done)
687 break;
Arnaldo Carvalho de Melo5c581042011-01-11 22:30:02 -0200688 err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1);
Peter Zijlstra8b412662009-09-17 19:59:05 +0200689 waking++;
690 }
691
Arnaldo Carvalho de Melo4152ab32011-07-25 11:06:19 -0300692 if (done)
693 perf_evlist__disable(evsel_list);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200694 }
695
Arnaldo Carvalho de Melo18483b82010-12-06 15:13:38 -0200696 if (quiet || signr == SIGUSR1)
Arnaldo Carvalho de Melob44308f2010-10-26 15:20:09 -0200697 return 0;
698
Peter Zijlstra8b412662009-09-17 19:59:05 +0200699 fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
700
Ingo Molnar021e9f42009-06-03 19:27:19 +0200701 /*
702 * Approximate RIP event size: 24 bytes.
703 */
704 fprintf(stderr,
Arnaldo Carvalho de Melo9486aa32011-01-22 20:37:02 -0200705 "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
Ingo Molnar021e9f42009-06-03 19:27:19 +0200706 (double)bytes_written / 1024.0 / 1024.0,
707 output_name,
708 bytes_written / 24);
Ingo Molnaraddc2782009-06-02 23:43:11 +0200709
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200710 return 0;
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300711
712out_delete_session:
713 perf_session__delete(session);
714 return err;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200715}
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200716
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200717static const char * const record_usage[] = {
Mike Galbraith9e0967532009-05-28 16:25:34 +0200718 "perf record [<options>] [<command>]",
719 "perf record [<options>] -- <command> [<options>]",
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200720 NULL
721};
722
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200723static bool force, append_file;
724
Tom Zanussibca647a2010-11-10 08:11:30 -0600725const struct option record_options[] = {
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200726 OPT_CALLBACK('e', "event", &evsel_list, "event",
Thomas Gleixner86847b62009-06-06 12:24:17 +0200727 "event selector. use 'perf list' to list available events",
Jiri Olsaf120f9d2011-07-14 11:25:32 +0200728 parse_events_option),
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200729 OPT_CALLBACK(0, "filter", &evsel_list, "filter",
Li Zefanc171b552009-10-15 11:22:07 +0800730 "event filter", parse_filter),
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200731 OPT_INTEGER('p', "pid", &target_pid,
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300732 "record events on existing process id"),
733 OPT_INTEGER('t', "tid", &target_tid,
734 "record events on existing thread id"),
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200735 OPT_INTEGER('r', "realtime", &realtime_prio,
736 "collect data with this RT SCHED_FIFO priority"),
Kirill Smelkovacac03f2011-01-12 17:59:36 +0300737 OPT_BOOLEAN('D', "no-delay", &nodelay,
738 "collect data without buffering"),
Frederic Weisbeckerdaac07b2009-08-13 10:27:19 +0200739 OPT_BOOLEAN('R', "raw-samples", &raw_samples,
740 "collect raw sample records from all opened counters"),
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200741 OPT_BOOLEAN('a', "all-cpus", &system_wide,
742 "system-wide collection from all CPUs"),
Ingo Molnarabaff322009-06-02 22:59:57 +0200743 OPT_BOOLEAN('A', "append", &append_file,
744 "append to the output file to do incremental profiling"),
Stephane Eranianc45c6ea2010-05-28 12:00:01 +0200745 OPT_STRING('C', "cpu", &cpu_list, "cpu",
746 "list of cpus to monitor"),
Peter Zijlstra97124d52009-06-02 15:52:24 +0200747 OPT_BOOLEAN('f', "force", &force,
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200748 "overwrite existing data file (deprecated)"),
Stephane Eranian3de29ca2010-05-17 12:20:43 -0300749 OPT_U64('c', "count", &user_interval, "event period to sample"),
Ingo Molnarabaff322009-06-02 22:59:57 +0200750 OPT_STRING('o', "output", &output_name, "file",
751 "output file name"),
Stephane Eranian2e6cdf92010-05-12 10:40:01 +0200752 OPT_BOOLEAN('i', "no-inherit", &no_inherit,
753 "child tasks do not inherit counters"),
Arnaldo Carvalho de Melo19679362010-05-17 15:39:16 -0300754 OPT_UINTEGER('F', "freq", &user_freq, "profile at this frequency"),
755 OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"),
Ingo Molnar3efa1cc92009-06-14 15:04:15 +0200756 OPT_BOOLEAN('g', "call-graph", &call_graph,
757 "do call-graph (stack chain/backtrace) recording"),
Ian Munsiec0555642010-04-13 18:37:33 +1000758 OPT_INCR('v', "verbose", &verbose,
Ingo Molnar3da297a2009-06-07 17:39:02 +0200759 "be more verbose (show counter open errors, etc)"),
Arnaldo Carvalho de Melob44308f2010-10-26 15:20:09 -0200760 OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
Peter Zijlstra649c48a2009-06-24 21:12:48 +0200761 OPT_BOOLEAN('s', "stat", &inherit_stat,
762 "per thread counts"),
Anton Blanchard4bba8282009-07-16 15:44:29 +0200763 OPT_BOOLEAN('d', "data", &sample_address,
764 "Sample addresses"),
Arnaldo Carvalho de Melo9c90a612010-12-02 10:25:28 -0200765 OPT_BOOLEAN('T', "timestamp", &sample_time, "Sample timestamps"),
Peter Zijlstra649c48a2009-06-24 21:12:48 +0200766 OPT_BOOLEAN('n', "no-samples", &no_samples,
767 "don't sample"),
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -0200768 OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid_cache,
Stephane Eraniana1ac1d32010-06-17 11:39:01 +0200769 "do not update the buildid cache"),
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -0200770 OPT_BOOLEAN('B', "no-buildid", &no_buildid,
771 "do not collect buildids in perf.data"),
Stephane Eranian023695d2011-02-14 11:20:01 +0200772 OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
773 "monitor event in cgroup name only",
774 parse_cgroups),
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200775 OPT_END()
776};
777
Ingo Molnarf37a2912009-07-01 12:37:06 +0200778int cmd_record(int argc, const char **argv, const char *prefix __used)
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200779{
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200780 int err = -ENOMEM;
781 struct perf_evsel *pos;
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200782
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200783 evsel_list = perf_evlist__new(NULL, NULL);
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200784 if (evsel_list == NULL)
785 return -ENOMEM;
786
Tom Zanussibca647a2010-11-10 08:11:30 -0600787 argc = parse_options(argc, argv, record_options, record_usage,
Arnaldo Carvalho de Melo655000e2009-12-15 20:04:40 -0200788 PARSE_OPT_STOP_AT_NON_OPTION);
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300789 if (!argc && target_pid == -1 && target_tid == -1 &&
Stephane Eranianc45c6ea2010-05-28 12:00:01 +0200790 !system_wide && !cpu_list)
Tom Zanussibca647a2010-11-10 08:11:30 -0600791 usage_with_options(record_usage, record_options);
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200792
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200793 if (force && append_file) {
794 fprintf(stderr, "Can't overwrite and append at the same time."
795 " You need to choose between -f and -A");
Tom Zanussibca647a2010-11-10 08:11:30 -0600796 usage_with_options(record_usage, record_options);
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200797 } else if (append_file) {
798 write_mode = WRITE_APPEND;
799 } else {
800 write_mode = WRITE_FORCE;
801 }
802
Stephane Eranian023695d2011-02-14 11:20:01 +0200803 if (nr_cgroups && !system_wide) {
804 fprintf(stderr, "cgroup monitoring only available in"
805 " system-wide mode\n");
806 usage_with_options(record_usage, record_options);
807 }
808
Arnaldo Carvalho de Melo655000e2009-12-15 20:04:40 -0200809 symbol__init();
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -0200810
Arnaldo Carvalho de Meloec80fde2011-05-26 09:53:51 -0300811 if (symbol_conf.kptr_restrict)
Arnaldo Carvalho de Melo646aaea62011-05-27 11:00:41 -0300812 pr_warning(
813"WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
814"check /proc/sys/kernel/kptr_restrict.\n\n"
815"Samples in kernel functions may not be resolved if a suitable vmlinux\n"
816"file is not found in the buildid cache or in the vmlinux path.\n\n"
817"Samples in kernel modules won't be resolved at all.\n\n"
818"If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
819"even with a suitable vmlinux or kallsyms file.\n\n");
Arnaldo Carvalho de Meloec80fde2011-05-26 09:53:51 -0300820
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -0200821 if (no_buildid_cache || no_buildid)
Stephane Eraniana1ac1d32010-06-17 11:39:01 +0200822 disable_buildid_cache();
Arnaldo Carvalho de Melo655000e2009-12-15 20:04:40 -0200823
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200824 if (evsel_list->nr_entries == 0 &&
825 perf_evlist__add_default(evsel_list) < 0) {
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200826 pr_err("Not enough memory for event selector list\n");
827 goto out_symbol_exit;
Peter Zijlstrabbd36e52009-06-11 23:11:50 +0200828 }
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200829
Arnaldo Carvalho de Melo5c98d4662011-01-03 17:53:33 -0200830 if (target_pid != -1)
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300831 target_tid = target_pid;
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300832
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200833 if (perf_evlist__create_maps(evsel_list, target_pid,
834 target_tid, cpu_list) < 0)
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200835 usage_with_options(record_usage, record_options);
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200836
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200837 list_for_each_entry(pos, &evsel_list->entries, node) {
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200838 if (perf_evsel__alloc_fd(pos, evsel_list->cpus->nr,
839 evsel_list->threads->nr) < 0)
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200840 goto out_free_fd;
Arnaldo Carvalho de Meload7f4e32011-01-17 18:28:13 -0200841 if (perf_header__push_event(pos->attr.config, event_name(pos)))
842 goto out_free_fd;
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300843 }
Arnaldo Carvalho de Melo5c581042011-01-11 22:30:02 -0200844
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200845 if (perf_evlist__alloc_pollfd(evsel_list) < 0)
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300846 goto out_free_fd;
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300847
Stephane Eranian3de29ca2010-05-17 12:20:43 -0300848 if (user_interval != ULLONG_MAX)
Frederic Weisbeckerf9212812010-04-14 22:09:02 +0200849 default_interval = user_interval;
850 if (user_freq != UINT_MAX)
851 freq = user_freq;
852
Mike Galbraith7e4ff9e2009-10-12 07:56:03 +0200853 /*
854 * User specified count overrides default frequency.
855 */
856 if (default_interval)
857 freq = 0;
858 else if (freq) {
859 default_interval = freq;
860 } else {
861 fprintf(stderr, "frequency and count are zero, aborting\n");
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300862 err = -EINVAL;
Arnaldo Carvalho de Melo5c581042011-01-11 22:30:02 -0200863 goto out_free_fd;
Mike Galbraith7e4ff9e2009-10-12 07:56:03 +0200864 }
865
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300866 err = __cmd_record(argc, argv);
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300867out_free_fd:
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200868 perf_evlist__delete_maps(evsel_list);
Arnaldo Carvalho de Melod65a4582010-07-30 18:31:28 -0300869out_symbol_exit:
870 symbol__exit();
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300871 return err;
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200872}