blob: f4c3fbee4bad1f4e8be0427adcaa528044e1c9e8 [file] [log] [blame]
Ingo Molnarabaff322009-06-02 22:59:57 +02001/*
Ingo Molnarbf9e1872009-06-02 23:37:05 +02002 * builtin-record.c
3 *
4 * Builtin record command: Record the profile of a workload
5 * (or a CPU, or a PID) into the perf.data output file - for
6 * later analysis via perf report.
Ingo Molnarabaff322009-06-02 22:59:57 +02007 */
Xiao Guangrongb8f46c52010-02-03 11:53:14 +08008#define _FILE_OFFSET_BITS 64
9
Ingo Molnar16f762a2009-05-27 09:10:38 +020010#include "builtin.h"
Ingo Molnarbf9e1872009-06-02 23:37:05 +020011
12#include "perf.h"
13
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -020014#include "util/build-id.h"
Thomas Gleixner6eda5832009-05-01 18:29:57 +020015#include "util/util.h"
Ingo Molnar0e9b20b2009-05-26 09:17:18 +020016#include "util/parse-options.h"
Ingo Molnar8ad8db32009-05-26 11:10:09 +020017#include "util/parse-events.h"
Thomas Gleixner6eda5832009-05-01 18:29:57 +020018
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020019#include "util/header.h"
Frederic Weisbecker66e274f2009-08-12 11:07:25 +020020#include "util/event.h"
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -020021#include "util/evlist.h"
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -020022#include "util/evsel.h"
Frederic Weisbecker8f288272009-08-16 22:05:48 +020023#include "util/debug.h"
Arnaldo Carvalho de Melo94c744b2009-12-11 21:24:02 -020024#include "util/session.h"
Arnaldo Carvalho de Melo8d063672009-11-04 18:50:43 -020025#include "util/symbol.h"
Paul Mackerrasa12b51c2010-03-10 20:36:09 +110026#include "util/cpumap.h"
Arnaldo Carvalho de Melofd782602011-01-18 15:15:24 -020027#include "util/thread_map.h"
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020028
Peter Zijlstra97124d52009-06-02 15:52:24 +020029#include <unistd.h>
Peter Zijlstrade9ac072009-04-08 15:01:31 +020030#include <sched.h>
Arnaldo Carvalho de Meloa41794c2010-05-18 18:29:23 -030031#include <sys/mman.h>
Peter Zijlstrade9ac072009-04-08 15:01:31 +020032
Frederic Weisbecker7865e812010-04-14 19:42:07 +020033enum write_mode_t {
34 WRITE_FORCE,
35 WRITE_APPEND
36};
37
Stephane Eranian3de29ca2010-05-17 12:20:43 -030038static u64 user_interval = ULLONG_MAX;
39static u64 default_interval = 0;
Ingo Molnara21ca2c2009-06-06 09:58:57 +020040
Peter Zijlstrade9ac072009-04-08 15:01:31 +020041static unsigned int page_size;
Frederic Weisbecker800cd252011-03-31 03:35:24 +020042static unsigned int mmap_pages = UINT_MAX;
Frederic Weisbeckerf9212812010-04-14 22:09:02 +020043static unsigned int user_freq = UINT_MAX;
Ingo Molnar42e59d72009-10-06 15:14:21 +020044static int freq = 1000;
Peter Zijlstrade9ac072009-04-08 15:01:31 +020045static int output;
Tom Zanussi529870e2010-04-01 23:59:16 -050046static int pipe_output = 0;
Franck Bui-Huud7065ad2011-01-16 17:14:45 +010047static const char *output_name = NULL;
Lin Ming43bece72011-08-17 18:42:07 +080048static bool group = false;
Arnaldo Carvalho de Melo19679362010-05-17 15:39:16 -030049static int realtime_prio = 0;
Kirill Smelkovacac03f2011-01-12 17:59:36 +030050static bool nodelay = false;
Ian Munsiec0555642010-04-13 18:37:33 +100051static bool raw_samples = false;
Arnaldo Carvalho de Melo9c90a612010-12-02 10:25:28 -020052static bool sample_id_all_avail = true;
Ian Munsiec0555642010-04-13 18:37:33 +100053static bool system_wide = false;
Ingo Molnar42e59d72009-10-06 15:14:21 +020054static pid_t target_pid = -1;
Zhang, Yanmind6d901c2010-03-18 11:36:05 -030055static pid_t target_tid = -1;
Ingo Molnar42e59d72009-10-06 15:14:21 +020056static pid_t child_pid = -1;
Stephane Eranian2e6cdf92010-05-12 10:40:01 +020057static bool no_inherit = false;
Frederic Weisbecker7865e812010-04-14 19:42:07 +020058static enum write_mode_t write_mode = WRITE_FORCE;
Ian Munsiec0555642010-04-13 18:37:33 +100059static bool call_graph = false;
60static bool inherit_stat = false;
61static bool no_samples = false;
62static bool sample_address = false;
Arnaldo Carvalho de Melo9c90a612010-12-02 10:25:28 -020063static bool sample_time = false;
Stephane Eraniana1ac1d32010-06-17 11:39:01 +020064static bool no_buildid = false;
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -020065static bool no_buildid_cache = false;
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -020066static struct perf_evlist *evsel_list;
Peter Zijlstrade9ac072009-04-08 15:01:31 +020067
Ingo Molnar42e59d72009-10-06 15:14:21 +020068static long samples = 0;
Ingo Molnar42e59d72009-10-06 15:14:21 +020069static u64 bytes_written = 0;
Ingo Molnara21ca2c2009-06-06 09:58:57 +020070
Ingo Molnar42e59d72009-10-06 15:14:21 +020071static int file_new = 1;
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -020072static off_t post_processing_offset;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +020073
Arnaldo Carvalho de Melo94c744b2009-12-11 21:24:02 -020074static struct perf_session *session;
Stephane Eranianc45c6ea2010-05-28 12:00:01 +020075static const char *cpu_list;
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
David Ahern764e16a2011-08-25 10:17:55 -0600164 attr->disabled = 1;
Arnaldo Carvalho de Melo5d2cd902011-04-14 11:20:14 -0300165 attr->inherit = !no_inherit;
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +0200166 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
167 PERF_FORMAT_TOTAL_TIME_RUNNING |
168 PERF_FORMAT_ID;
Peter Zijlstra16c8a102009-05-05 17:50:27 +0200169
Frederic Weisbecker3a9f1312009-08-13 10:27:18 +0200170 attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
Ingo Molnar3efa1cc92009-06-14 15:04:15 +0200171
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200172 if (evlist->nr_entries > 1)
Eric B Munson8907fd62010-03-05 12:51:05 -0300173 attr->sample_type |= PERF_SAMPLE_ID;
174
Frederic Weisbeckerf9212812010-04-14 22:09:02 +0200175 /*
176 * We default some events to a 1 default interval. But keep
177 * it a weak assumption overridable by the user.
178 */
179 if (!attr->sample_period || (user_freq != UINT_MAX &&
Stephane Eranian3de29ca2010-05-17 12:20:43 -0300180 user_interval != ULLONG_MAX)) {
Frederic Weisbeckerf9212812010-04-14 22:09:02 +0200181 if (freq) {
182 attr->sample_type |= PERF_SAMPLE_PERIOD;
183 attr->freq = 1;
184 attr->sample_freq = freq;
185 } else {
186 attr->sample_period = default_interval;
187 }
Ingo Molnar1dba15e2009-06-05 18:37:22 +0200188 }
Ingo Molnar3efa1cc92009-06-14 15:04:15 +0200189
Peter Zijlstra649c48a2009-06-24 21:12:48 +0200190 if (no_samples)
191 attr->sample_freq = 0;
192
193 if (inherit_stat)
194 attr->inherit_stat = 1;
195
Eric B Munson3af9e852010-05-18 15:30:49 +0100196 if (sample_address) {
Anton Blanchard4bba8282009-07-16 15:44:29 +0200197 attr->sample_type |= PERF_SAMPLE_ADDR;
Eric B Munson3af9e852010-05-18 15:30:49 +0100198 attr->mmap_data = track;
199 }
Anton Blanchard4bba8282009-07-16 15:44:29 +0200200
Ingo Molnar3efa1cc92009-06-14 15:04:15 +0200201 if (call_graph)
202 attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
203
Arun Sharmaf60f3592010-06-04 11:27:10 -0300204 if (system_wide)
205 attr->sample_type |= PERF_SAMPLE_CPU;
206
Arnaldo Carvalho de Meloa43d3f02010-12-25 12:12:25 -0200207 if (sample_id_all_avail &&
208 (sample_time || system_wide || !no_inherit || cpu_list))
Arnaldo Carvalho de Melo9c90a612010-12-02 10:25:28 -0200209 attr->sample_type |= PERF_SAMPLE_TIME;
210
Ingo Molnarcd6feee2009-09-02 20:20:38 +0200211 if (raw_samples) {
Ingo Molnar6ddf2592009-09-03 12:00:22 +0200212 attr->sample_type |= PERF_SAMPLE_TIME;
Frederic Weisbeckerdaac07b2009-08-13 10:27:19 +0200213 attr->sample_type |= PERF_SAMPLE_RAW;
Ingo Molnarcd6feee2009-09-02 20:20:38 +0200214 attr->sample_type |= PERF_SAMPLE_CPU;
215 }
Frederic Weisbeckerf413cdb2009-08-07 01:25:54 +0200216
Kirill Smelkovacac03f2011-01-12 17:59:36 +0300217 if (nodelay) {
218 attr->watermark = 0;
219 attr->wakeup_events = 1;
220 }
221
Ingo Molnara21ca2c2009-06-06 09:58:57 +0200222 attr->mmap = track;
223 attr->comm = track;
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200224
Stephane Eranian2e6cdf92010-05-12 10:40:01 +0200225 if (target_pid == -1 && target_tid == -1 && !system_wide) {
Zhang, Yanmin46be6042010-03-18 11:36:04 -0300226 attr->disabled = 1;
Eric B Munsonbedbfde2010-03-15 11:46:57 -0300227 attr->enable_on_exec = 1;
Zhang, Yanmin46be6042010-03-18 11:36:04 -0300228 }
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200229}
230
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300231static bool perf_evlist__equal(struct perf_evlist *evlist,
232 struct perf_evlist *other)
233{
234 struct perf_evsel *pos, *pair;
235
236 if (evlist->nr_entries != other->nr_entries)
237 return false;
238
239 pair = list_entry(other->entries.next, struct perf_evsel, node);
240
241 list_for_each_entry(pos, &evlist->entries, node) {
242 if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0))
243 return false;
244 pair = list_entry(pair->node.next, struct perf_evsel, node);
245 }
246
247 return true;
248}
249
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200250static void open_counters(struct perf_evlist *evlist)
251{
252 struct perf_evsel *pos;
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200253
Arnaldo Carvalho de Melo5d2cd902011-04-14 11:20:14 -0300254 if (evlist->cpus->map[0] < 0)
255 no_inherit = true;
256
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200257 list_for_each_entry(pos, &evlist->entries, node) {
258 struct perf_event_attr *attr = &pos->attr;
259 /*
260 * Check if parse_single_tracepoint_event has already asked for
261 * PERF_SAMPLE_TIME.
262 *
263 * XXX this is kludgy but short term fix for problems introduced by
264 * eac23d1c that broke 'perf script' by having different sample_types
265 * when using multiple tracepoint events when we use a perf binary
266 * that tries to use sample_id_all on an older kernel.
267 *
268 * We need to move counter creation to perf_session, support
269 * different sample_types, etc.
270 */
271 bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
272
273 config_attr(pos, evlist);
Arnaldo Carvalho de Melo9c90a612010-12-02 10:25:28 -0200274retry_sample_id:
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200275 attr->sample_id_all = sample_id_all_avail ? 1 : 0;
Ingo Molnar3da297a2009-06-07 17:39:02 +0200276try_again:
Arnaldo Carvalho de Melo5d2cd902011-04-14 11:20:14 -0300277 if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group) < 0) {
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300278 int err = errno;
Ingo Molnarf250c0302009-06-05 13:18:41 +0200279
Arnaldo Carvalho de Meloc286c412011-03-28 09:50:11 -0300280 if (err == EPERM || err == EACCES) {
281 ui__warning_paranoid();
282 exit(EXIT_FAILURE);
283 } else if (err == ENODEV && cpu_list) {
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300284 die("No such device - did you specify"
285 " an out-of-range profile CPU?\n");
Arnaldo Carvalho de Melo9c90a612010-12-02 10:25:28 -0200286 } else if (err == EINVAL && sample_id_all_avail) {
287 /*
288 * Old kernel, no attr->sample_id_type_all field
289 */
290 sample_id_all_avail = false;
Arnaldo Carvalho de Meloa43d3f02010-12-25 12:12:25 -0200291 if (!sample_time && !raw_samples && !time_needed)
Ian Munsieeac23d12010-12-09 16:33:53 +1100292 attr->sample_type &= ~PERF_SAMPLE_TIME;
293
Arnaldo Carvalho de Melo9c90a612010-12-02 10:25:28 -0200294 goto retry_sample_id;
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300295 }
Ingo Molnar3da297a2009-06-07 17:39:02 +0200296
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300297 /*
298 * If it's cycles then fall back to hrtimer
299 * based cpu-clock-tick sw counter, which
300 * is always available even if no PMU support:
301 */
302 if (attr->type == PERF_TYPE_HARDWARE
303 && attr->config == PERF_COUNT_HW_CPU_CYCLES) {
Ingo Molnar3da297a2009-06-07 17:39:02 +0200304
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300305 if (verbose)
David Ahernca6a4252011-03-25 13:11:11 -0600306 ui__warning("The cycles event is not supported, "
307 "trying to fall back to cpu-clock-ticks\n");
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300308 attr->type = PERF_TYPE_SOFTWARE;
309 attr->config = PERF_COUNT_SW_CPU_CLOCK;
310 goto try_again;
311 }
David Ahernca6a4252011-03-25 13:11:11 -0600312
313 if (err == ENOENT) {
314 ui__warning("The %s event is not supported.\n",
315 event_name(pos));
316 exit(EXIT_FAILURE);
317 }
318
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300319 printf("\n");
Corey Ashfordd9cf8372010-11-19 17:37:24 -0800320 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 -0200321 err, strerror(err));
Simon Kaempfleinbfd45112009-11-16 15:25:53 +1000322
323#if defined(__i386__) || defined(__x86_64__)
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300324 if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP)
325 die("No hardware sampling interrupt available."
326 " No APIC? If so then you can boot the kernel"
327 " with the \"lapic\" boot parameter to"
328 " force-enable it.\n");
Simon Kaempfleinbfd45112009-11-16 15:25:53 +1000329#endif
330
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300331 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300332 }
Li Zefanc171b552009-10-15 11:22:07 +0800333 }
Arnaldo Carvalho de Meloa43d3f02010-12-25 12:12:25 -0200334
Frederic Weisbecker0a102472011-02-26 04:51:54 +0100335 if (perf_evlist__set_filters(evlist)) {
336 error("failed to set filter with %d (%s)\n", errno,
337 strerror(errno));
338 exit(-1);
339 }
340
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200341 if (perf_evlist__mmap(evlist, mmap_pages, false) < 0)
Arnaldo Carvalho de Melo0a27d7f2011-01-14 15:50:51 -0200342 die("failed to mmap with %d (%s)\n", errno, strerror(errno));
343
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300344 if (file_new)
345 session->evlist = evlist;
346 else {
347 if (!perf_evlist__equal(session->evlist, evlist)) {
348 fprintf(stderr, "incompatible append\n");
349 exit(-1);
350 }
351 }
352
353 perf_session__update_sample_type(session);
Peter Zijlstra16c8a102009-05-05 17:50:27 +0200354}
355
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -0200356static int process_buildids(void)
357{
358 u64 size = lseek(output, 0, SEEK_CUR);
359
Arnaldo Carvalho de Melo9f591fd2010-03-11 15:53:11 -0300360 if (size == 0)
361 return 0;
362
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -0200363 session->fd = output;
364 return __perf_session__process_events(session, post_processing_offset,
365 size - post_processing_offset,
366 size, &build_id__mark_dso_hit_ops);
367}
368
Peter Zijlstraf5970552009-06-18 23:22:55 +0200369static void atexit_header(void)
370{
Tom Zanussic7929e42010-04-01 23:59:22 -0500371 if (!pipe_output) {
372 session->header.data_size += bytes_written;
Peter Zijlstraf5970552009-06-18 23:22:55 +0200373
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -0200374 if (!no_buildid)
375 process_buildids();
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300376 perf_session__write_header(session, evsel_list, output, true);
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300377 perf_session__delete(session);
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200378 perf_evlist__delete(evsel_list);
Arnaldo Carvalho de Melod65a4582010-07-30 18:31:28 -0300379 symbol__exit();
Tom Zanussic7929e42010-04-01 23:59:22 -0500380 }
Peter Zijlstraf5970552009-06-18 23:22:55 +0200381}
382
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200383static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800384{
385 int err;
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -0300386 struct perf_session *psession = data;
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800387
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -0300388 if (machine__is_host(machine))
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800389 return;
390
391 /*
392 *As for guest kernel when processing subcommand record&report,
393 *we arrange module mmap prior to guest kernel mmap and trigger
394 *a preload dso because default guest module symbols are loaded
395 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
396 *method is used to avoid symbol missing when the first addr is
397 *in module instead of in guest kernel.
398 */
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200399 err = perf_event__synthesize_modules(process_synthesized_event,
400 psession, machine);
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800401 if (err < 0)
402 pr_err("Couldn't record guest kernel [%d]'s reference"
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -0300403 " relocation symbol.\n", machine->pid);
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800404
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800405 /*
406 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
407 * have no _text sometimes.
408 */
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200409 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
410 psession, machine, "_text");
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800411 if (err < 0)
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200412 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
413 psession, machine,
414 "_stext");
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800415 if (err < 0)
416 pr_err("Couldn't record guest kernel [%d]'s reference"
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -0300417 " relocation symbol.\n", machine->pid);
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800418}
419
Frederic Weisbecker98402802010-05-02 22:05:29 +0200420static struct perf_event_header finished_round_event = {
421 .size = sizeof(struct perf_event_header),
422 .type = PERF_RECORD_FINISHED_ROUND,
423};
424
425static void mmap_read_all(void)
426{
Peter Zijlstra0e2e63d2010-05-20 14:45:26 +0200427 int i;
Frederic Weisbecker98402802010-05-02 22:05:29 +0200428
Arnaldo Carvalho de Meloaece9482011-05-15 09:39:00 -0300429 for (i = 0; i < evsel_list->nr_mmaps; i++) {
Arnaldo Carvalho de Melo0a27d7f2011-01-14 15:50:51 -0200430 if (evsel_list->mmap[i].base)
431 mmap_read(&evsel_list->mmap[i]);
Frederic Weisbecker98402802010-05-02 22:05:29 +0200432 }
433
434 if (perf_header__has_feat(&session->header, HEADER_TRACE_INFO))
435 write_output(&finished_round_event, sizeof(finished_round_event));
436}
437
Arnaldo Carvalho de Melod4db3f12009-12-27 21:36:57 -0200438static int __cmd_record(int argc, const char **argv)
Peter Zijlstra16c8a102009-05-05 17:50:27 +0200439{
Peter Zijlstra97124d52009-06-02 15:52:24 +0200440 struct stat st;
Ingo Molnarabaff322009-06-02 22:59:57 +0200441 int flags;
Arnaldo Carvalho de Melo4dc0a042009-11-19 14:55:55 -0200442 int err;
Peter Zijlstra8b412662009-09-17 19:59:05 +0200443 unsigned long waking = 0;
Peter Zijlstra856e9662009-12-16 17:55:55 +0100444 int child_ready_pipe[2], go_pipe[2];
Zhang, Yanmin46be6042010-03-18 11:36:04 -0300445 const bool forks = argc > 0;
Peter Zijlstra856e9662009-12-16 17:55:55 +0100446 char buf;
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -0300447 struct machine *machine;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200448
449 page_size = sysconf(_SC_PAGE_SIZE);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200450
Peter Zijlstraf5970552009-06-18 23:22:55 +0200451 atexit(sig_atexit);
452 signal(SIGCHLD, sig_handler);
453 signal(SIGINT, sig_handler);
Arnaldo Carvalho de Melo18483b82010-12-06 15:13:38 -0200454 signal(SIGUSR1, sig_handler);
Peter Zijlstraf5970552009-06-18 23:22:55 +0200455
Arnaldo Carvalho de Melod4db3f12009-12-27 21:36:57 -0200456 if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
Peter Zijlstra856e9662009-12-16 17:55:55 +0100457 perror("failed to create pipes");
458 exit(-1);
459 }
460
Franck Bui-Huud7065ad2011-01-16 17:14:45 +0100461 if (!output_name) {
462 if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
463 pipe_output = 1;
464 else
465 output_name = "perf.data";
466 }
467 if (output_name) {
468 if (!strcmp(output_name, "-"))
469 pipe_output = 1;
470 else if (!stat(output_name, &st) && st.st_size) {
471 if (write_mode == WRITE_FORCE) {
472 char oldname[PATH_MAX];
473 snprintf(oldname, sizeof(oldname), "%s.old",
474 output_name);
475 unlink(oldname);
476 rename(output_name, oldname);
477 }
478 } else if (write_mode == WRITE_APPEND) {
479 write_mode = WRITE_FORCE;
Pierre Habouzit266e0e22009-08-07 14:16:01 +0200480 }
Peter Zijlstra97124d52009-06-02 15:52:24 +0200481 }
482
Xiao Guangrongf887f302010-02-04 16:46:42 +0800483 flags = O_CREAT|O_RDWR;
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200484 if (write_mode == WRITE_APPEND)
Peter Zijlstraf5970552009-06-18 23:22:55 +0200485 file_new = 0;
Ingo Molnarabaff322009-06-02 22:59:57 +0200486 else
487 flags |= O_TRUNC;
488
Tom Zanussi529870e2010-04-01 23:59:16 -0500489 if (pipe_output)
490 output = STDOUT_FILENO;
491 else
492 output = open(output_name, flags, S_IRUSR | S_IWUSR);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200493 if (output < 0) {
494 perror("failed to create output file");
495 exit(-1);
496 }
497
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200498 session = perf_session__new(output_name, O_WRONLY,
Ian Munsie21ef97f2010-12-10 14:09:16 +1100499 write_mode == WRITE_FORCE, false, NULL);
Arnaldo Carvalho de Melo94c744b2009-12-11 21:24:02 -0200500 if (session == NULL) {
Arnaldo Carvalho de Meloa9a70bb2009-11-17 01:18:11 -0200501 pr_err("Not enough memory for reading perf file header\n");
502 return -1;
503 }
504
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -0200505 if (!no_buildid)
506 perf_header__set_feat(&session->header, HEADER_BUILD_ID);
507
Arnaldo Carvalho de Melo4dc0a042009-11-19 14:55:55 -0200508 if (!file_new) {
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300509 err = perf_session__read_header(session, output);
Arnaldo Carvalho de Melo4dc0a042009-11-19 14:55:55 -0200510 if (err < 0)
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300511 goto out_delete_session;
Arnaldo Carvalho de Melo4dc0a042009-11-19 14:55:55 -0200512 }
513
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200514 if (have_tracepoints(&evsel_list->entries))
Arnaldo Carvalho de Melo94c744b2009-12-11 21:24:02 -0200515 perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
Frederic Weisbecker03456a12009-10-06 23:36:47 +0200516
Frederic Weisbecker800cd252011-03-31 03:35:24 +0200517 /* 512 kiB: default amount of unprivileged mlocked memory */
518 if (mmap_pages == UINT_MAX)
519 mmap_pages = (512 * 1024) / page_size;
520
Arnaldo Carvalho de Melod4db3f12009-12-27 21:36:57 -0200521 if (forks) {
Zhang, Yanmin46be6042010-03-18 11:36:04 -0300522 child_pid = fork();
Borislav Petkov2fb750e2010-05-31 23:18:18 +0200523 if (child_pid < 0) {
Peter Zijlstra856e9662009-12-16 17:55:55 +0100524 perror("failed to fork");
525 exit(-1);
Jens Axboe0a5ac842009-08-12 11:18:01 +0200526 }
Peter Zijlstra856e9662009-12-16 17:55:55 +0100527
Zhang, Yanmin46be6042010-03-18 11:36:04 -0300528 if (!child_pid) {
Tom Zanussi529870e2010-04-01 23:59:16 -0500529 if (pipe_output)
530 dup2(2, 1);
Peter Zijlstra856e9662009-12-16 17:55:55 +0100531 close(child_ready_pipe[0]);
532 close(go_pipe[1]);
533 fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
534
535 /*
536 * Do a dummy execvp to get the PLT entry resolved,
537 * so we avoid the resolver overhead on the real
538 * execvp call.
539 */
540 execvp("", (char **)argv);
541
542 /*
543 * Tell the parent we're ready to go
544 */
545 close(child_ready_pipe[1]);
546
547 /*
548 * Wait until the parent tells us to go.
549 */
550 if (read(go_pipe[0], &buf, 1) == -1)
551 perror("unable to read pipe");
552
553 execvp(argv[0], (char **)argv);
554
555 perror(argv[0]);
Arnaldo Carvalho de Melo18483b82010-12-06 15:13:38 -0200556 kill(getppid(), SIGUSR1);
Peter Zijlstra856e9662009-12-16 17:55:55 +0100557 exit(-1);
558 }
559
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300560 if (!system_wide && target_tid == -1 && target_pid == -1)
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200561 evsel_list->threads->map[0] = child_pid;
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300562
Peter Zijlstra856e9662009-12-16 17:55:55 +0100563 close(child_ready_pipe[1]);
564 close(go_pipe[0]);
565 /*
566 * wait for child to settle
567 */
568 if (read(child_ready_pipe[0], &buf, 1) == -1) {
569 perror("unable to read pipe");
570 exit(-1);
571 }
572 close(child_ready_pipe[0]);
573 }
574
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200575 open_counters(evsel_list);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200576
Arnaldo Carvalho de Melo712a4b62011-02-17 12:18:42 -0200577 /*
578 * perf_session__delete(session) will be called at atexit_header()
579 */
580 atexit(atexit_header);
581
Tom Zanussi529870e2010-04-01 23:59:16 -0500582 if (pipe_output) {
583 err = perf_header__write_pipe(output);
584 if (err < 0)
585 return err;
586 } else if (file_new) {
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300587 err = perf_session__write_header(session, evsel_list,
588 output, false);
Arnaldo Carvalho de Melod5eed902009-11-19 14:55:56 -0200589 if (err < 0)
590 return err;
591 }
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +0200592
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -0200593 post_processing_offset = lseek(output, 0, SEEK_CUR);
594
Tom Zanussi2c46dbb2010-04-01 23:59:19 -0500595 if (pipe_output) {
Arnaldo Carvalho de Meloa91e5432011-03-10 11:15:54 -0300596 err = perf_session__synthesize_attrs(session,
597 process_synthesized_event);
Tom Zanussi2c46dbb2010-04-01 23:59:19 -0500598 if (err < 0) {
599 pr_err("Couldn't synthesize attrs.\n");
600 return err;
601 }
Tom Zanussicd19a032010-04-01 23:59:20 -0500602
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200603 err = perf_event__synthesize_event_types(process_synthesized_event,
604 session);
Tom Zanussicd19a032010-04-01 23:59:20 -0500605 if (err < 0) {
606 pr_err("Couldn't synthesize event_types.\n");
607 return err;
608 }
Tom Zanussi92155452010-04-01 23:59:21 -0500609
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200610 if (have_tracepoints(&evsel_list->entries)) {
Tom Zanussi63e0c772010-05-03 00:14:48 -0500611 /*
612 * FIXME err <= 0 here actually means that
613 * there were no tracepoints so its not really
614 * an error, just that we don't need to
615 * synthesize anything. We really have to
616 * return this more properly and also
617 * propagate errors that now are calling die()
618 */
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200619 err = perf_event__synthesize_tracing_data(output, evsel_list,
620 process_synthesized_event,
621 session);
Tom Zanussi63e0c772010-05-03 00:14:48 -0500622 if (err <= 0) {
623 pr_err("Couldn't record tracing data.\n");
624 return err;
625 }
Arnaldo Carvalho de Melo2c9faa02010-05-02 13:37:24 -0300626 advance_output(err);
Tom Zanussi63e0c772010-05-03 00:14:48 -0500627 }
Tom Zanussi2c46dbb2010-04-01 23:59:19 -0500628 }
629
Arnaldo Carvalho de Melo23346f22010-04-27 21:17:50 -0300630 machine = perf_session__find_host_machine(session);
631 if (!machine) {
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800632 pr_err("Couldn't find native kernel information.\n");
633 return -1;
634 }
635
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200636 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
637 session, machine, "_text");
Arnaldo Carvalho de Melo70162132010-03-30 18:27:39 -0300638 if (err < 0)
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200639 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
640 session, machine, "_stext");
Arnaldo Carvalho de Meloc1a3a4b2010-11-22 14:01:55 -0200641 if (err < 0)
642 pr_err("Couldn't record kernel reference relocation symbol\n"
643 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
644 "Check /proc/kallsyms permission or run as root.\n");
Arnaldo Carvalho de Melo56b03f32010-01-05 16:50:31 -0200645
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200646 err = perf_event__synthesize_modules(process_synthesized_event,
647 session, machine);
Arnaldo Carvalho de Meloc1a3a4b2010-11-22 14:01:55 -0200648 if (err < 0)
649 pr_err("Couldn't record kernel module information.\n"
650 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
651 "Check /proc/modules permission or run as root.\n");
652
Zhang, Yanmina1645ce2010-04-19 13:32:50 +0800653 if (perf_guest)
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200654 perf_session__process_machines(session,
655 perf_event__synthesize_guest_os);
Arnaldo Carvalho de Melob7cece72010-01-13 13:22:17 -0200656
Stephane Eraniancf103a12010-06-16 20:59:01 +0200657 if (!system_wide)
Arnaldo Carvalho de Melo7c940c12011-02-11 11:45:54 -0200658 perf_event__synthesize_thread_map(evsel_list->threads,
659 process_synthesized_event,
660 session);
Arnaldo Carvalho de Melo234fbbf2009-10-26 19:23:18 -0200661 else
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -0200662 perf_event__synthesize_threads(process_synthesized_event,
663 session);
Peter Zijlstra7c6a1c62009-06-25 17:05:54 +0200664
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200665 if (realtime_prio) {
666 struct sched_param param;
667
668 param.sched_priority = realtime_prio;
669 if (sched_setscheduler(0, SCHED_FIFO, &param)) {
Arnaldo Carvalho de Melo6beba7a2009-10-21 17:34:06 -0200670 pr_err("Could not set realtime priority.\n");
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200671 exit(-1);
672 }
673 }
674
David Ahern764e16a2011-08-25 10:17:55 -0600675 perf_evlist__enable(evsel_list);
676
Peter Zijlstra856e9662009-12-16 17:55:55 +0100677 /*
678 * Let the child rip
679 */
Arnaldo Carvalho de Melod4db3f12009-12-27 21:36:57 -0200680 if (forks)
681 close(go_pipe[1]);
Peter Zijlstra856e9662009-12-16 17:55:55 +0100682
Peter Zijlstra649c48a2009-06-24 21:12:48 +0200683 for (;;) {
Ingo Molnar2debbc82009-06-05 14:29:10 +0200684 int hits = samples;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200685
Frederic Weisbecker98402802010-05-02 22:05:29 +0200686 mmap_read_all();
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200687
Peter Zijlstra649c48a2009-06-24 21:12:48 +0200688 if (hits == samples) {
689 if (done)
690 break;
Arnaldo Carvalho de Melo5c581042011-01-11 22:30:02 -0200691 err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1);
Peter Zijlstra8b412662009-09-17 19:59:05 +0200692 waking++;
693 }
694
Arnaldo Carvalho de Melo4152ab32011-07-25 11:06:19 -0300695 if (done)
696 perf_evlist__disable(evsel_list);
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200697 }
698
Arnaldo Carvalho de Melo18483b82010-12-06 15:13:38 -0200699 if (quiet || signr == SIGUSR1)
Arnaldo Carvalho de Melob44308f2010-10-26 15:20:09 -0200700 return 0;
701
Peter Zijlstra8b412662009-09-17 19:59:05 +0200702 fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
703
Ingo Molnar021e9f42009-06-03 19:27:19 +0200704 /*
705 * Approximate RIP event size: 24 bytes.
706 */
707 fprintf(stderr,
Arnaldo Carvalho de Melo9486aa32011-01-22 20:37:02 -0200708 "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
Ingo Molnar021e9f42009-06-03 19:27:19 +0200709 (double)bytes_written / 1024.0 / 1024.0,
710 output_name,
711 bytes_written / 24);
Ingo Molnaraddc2782009-06-02 23:43:11 +0200712
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200713 return 0;
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300714
715out_delete_session:
716 perf_session__delete(session);
717 return err;
Peter Zijlstrade9ac072009-04-08 15:01:31 +0200718}
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200719
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200720static const char * const record_usage[] = {
Mike Galbraith9e096752009-05-28 16:25:34 +0200721 "perf record [<options>] [<command>]",
722 "perf record [<options>] -- <command> [<options>]",
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200723 NULL
724};
725
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200726static bool force, append_file;
727
Tom Zanussibca647a2010-11-10 08:11:30 -0600728const struct option record_options[] = {
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200729 OPT_CALLBACK('e', "event", &evsel_list, "event",
Thomas Gleixner86847b62009-06-06 12:24:17 +0200730 "event selector. use 'perf list' to list available events",
Jiri Olsaf120f9d2011-07-14 11:25:32 +0200731 parse_events_option),
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200732 OPT_CALLBACK(0, "filter", &evsel_list, "filter",
Li Zefanc171b552009-10-15 11:22:07 +0800733 "event filter", parse_filter),
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200734 OPT_INTEGER('p', "pid", &target_pid,
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300735 "record events on existing process id"),
736 OPT_INTEGER('t', "tid", &target_tid,
737 "record events on existing thread id"),
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200738 OPT_INTEGER('r', "realtime", &realtime_prio,
739 "collect data with this RT SCHED_FIFO priority"),
Kirill Smelkovacac03f2011-01-12 17:59:36 +0300740 OPT_BOOLEAN('D', "no-delay", &nodelay,
741 "collect data without buffering"),
Frederic Weisbeckerdaac07b2009-08-13 10:27:19 +0200742 OPT_BOOLEAN('R', "raw-samples", &raw_samples,
743 "collect raw sample records from all opened counters"),
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200744 OPT_BOOLEAN('a', "all-cpus", &system_wide,
745 "system-wide collection from all CPUs"),
Ingo Molnarabaff322009-06-02 22:59:57 +0200746 OPT_BOOLEAN('A', "append", &append_file,
747 "append to the output file to do incremental profiling"),
Stephane Eranianc45c6ea2010-05-28 12:00:01 +0200748 OPT_STRING('C', "cpu", &cpu_list, "cpu",
749 "list of cpus to monitor"),
Peter Zijlstra97124d52009-06-02 15:52:24 +0200750 OPT_BOOLEAN('f', "force", &force,
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200751 "overwrite existing data file (deprecated)"),
Stephane Eranian3de29ca2010-05-17 12:20:43 -0300752 OPT_U64('c', "count", &user_interval, "event period to sample"),
Ingo Molnarabaff322009-06-02 22:59:57 +0200753 OPT_STRING('o', "output", &output_name, "file",
754 "output file name"),
Stephane Eranian2e6cdf92010-05-12 10:40:01 +0200755 OPT_BOOLEAN('i', "no-inherit", &no_inherit,
756 "child tasks do not inherit counters"),
Arnaldo Carvalho de Melo19679362010-05-17 15:39:16 -0300757 OPT_UINTEGER('F', "freq", &user_freq, "profile at this frequency"),
758 OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"),
Lin Ming43bece72011-08-17 18:42:07 +0800759 OPT_BOOLEAN(0, "group", &group,
760 "put the counters into a counter group"),
Ingo Molnar3efa1cc92009-06-14 15:04:15 +0200761 OPT_BOOLEAN('g', "call-graph", &call_graph,
762 "do call-graph (stack chain/backtrace) recording"),
Ian Munsiec0555642010-04-13 18:37:33 +1000763 OPT_INCR('v', "verbose", &verbose,
Ingo Molnar3da297a2009-06-07 17:39:02 +0200764 "be more verbose (show counter open errors, etc)"),
Arnaldo Carvalho de Melob44308f2010-10-26 15:20:09 -0200765 OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
Peter Zijlstra649c48a2009-06-24 21:12:48 +0200766 OPT_BOOLEAN('s', "stat", &inherit_stat,
767 "per thread counts"),
Anton Blanchard4bba8282009-07-16 15:44:29 +0200768 OPT_BOOLEAN('d', "data", &sample_address,
769 "Sample addresses"),
Arnaldo Carvalho de Melo9c90a612010-12-02 10:25:28 -0200770 OPT_BOOLEAN('T', "timestamp", &sample_time, "Sample timestamps"),
Peter Zijlstra649c48a2009-06-24 21:12:48 +0200771 OPT_BOOLEAN('n', "no-samples", &no_samples,
772 "don't sample"),
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -0200773 OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid_cache,
Stephane Eraniana1ac1d32010-06-17 11:39:01 +0200774 "do not update the buildid cache"),
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -0200775 OPT_BOOLEAN('B', "no-buildid", &no_buildid,
776 "do not collect buildids in perf.data"),
Stephane Eranian023695d2011-02-14 11:20:01 +0200777 OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
778 "monitor event in cgroup name only",
779 parse_cgroups),
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200780 OPT_END()
781};
782
Ingo Molnarf37a2912009-07-01 12:37:06 +0200783int cmd_record(int argc, const char **argv, const char *prefix __used)
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200784{
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200785 int err = -ENOMEM;
786 struct perf_evsel *pos;
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200787
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200788 evsel_list = perf_evlist__new(NULL, NULL);
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200789 if (evsel_list == NULL)
790 return -ENOMEM;
791
Tom Zanussibca647a2010-11-10 08:11:30 -0600792 argc = parse_options(argc, argv, record_options, record_usage,
Arnaldo Carvalho de Melo655000e2009-12-15 20:04:40 -0200793 PARSE_OPT_STOP_AT_NON_OPTION);
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300794 if (!argc && target_pid == -1 && target_tid == -1 &&
Stephane Eranianc45c6ea2010-05-28 12:00:01 +0200795 !system_wide && !cpu_list)
Tom Zanussibca647a2010-11-10 08:11:30 -0600796 usage_with_options(record_usage, record_options);
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200797
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200798 if (force && append_file) {
799 fprintf(stderr, "Can't overwrite and append at the same time."
800 " You need to choose between -f and -A");
Tom Zanussibca647a2010-11-10 08:11:30 -0600801 usage_with_options(record_usage, record_options);
Frederic Weisbecker7865e812010-04-14 19:42:07 +0200802 } else if (append_file) {
803 write_mode = WRITE_APPEND;
804 } else {
805 write_mode = WRITE_FORCE;
806 }
807
Stephane Eranian023695d2011-02-14 11:20:01 +0200808 if (nr_cgroups && !system_wide) {
809 fprintf(stderr, "cgroup monitoring only available in"
810 " system-wide mode\n");
811 usage_with_options(record_usage, record_options);
812 }
813
Arnaldo Carvalho de Melo655000e2009-12-15 20:04:40 -0200814 symbol__init();
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -0200815
Arnaldo Carvalho de Meloec80fde2011-05-26 09:53:51 -0300816 if (symbol_conf.kptr_restrict)
Arnaldo Carvalho de Melo646aaea2011-05-27 11:00:41 -0300817 pr_warning(
818"WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
819"check /proc/sys/kernel/kptr_restrict.\n\n"
820"Samples in kernel functions may not be resolved if a suitable vmlinux\n"
821"file is not found in the buildid cache or in the vmlinux path.\n\n"
822"Samples in kernel modules won't be resolved at all.\n\n"
823"If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
824"even with a suitable vmlinux or kallsyms file.\n\n");
Arnaldo Carvalho de Meloec80fde2011-05-26 09:53:51 -0300825
Arnaldo Carvalho de Melobaa2f6c2010-11-26 19:39:15 -0200826 if (no_buildid_cache || no_buildid)
Stephane Eraniana1ac1d32010-06-17 11:39:01 +0200827 disable_buildid_cache();
Arnaldo Carvalho de Melo655000e2009-12-15 20:04:40 -0200828
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200829 if (evsel_list->nr_entries == 0 &&
830 perf_evlist__add_default(evsel_list) < 0) {
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200831 pr_err("Not enough memory for event selector list\n");
832 goto out_symbol_exit;
Peter Zijlstrabbd36e52009-06-11 23:11:50 +0200833 }
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200834
Arnaldo Carvalho de Melo5c98d462011-01-03 17:53:33 -0200835 if (target_pid != -1)
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300836 target_tid = target_pid;
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300837
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200838 if (perf_evlist__create_maps(evsel_list, target_pid,
839 target_tid, cpu_list) < 0)
Arnaldo Carvalho de Melodd7927f2011-01-12 14:28:51 -0200840 usage_with_options(record_usage, record_options);
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200841
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200842 list_for_each_entry(pos, &evsel_list->entries, node) {
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200843 if (perf_evsel__alloc_fd(pos, evsel_list->cpus->nr,
844 evsel_list->threads->nr) < 0)
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200845 goto out_free_fd;
Arnaldo Carvalho de Meload7f4e32011-01-17 18:28:13 -0200846 if (perf_header__push_event(pos->attr.config, event_name(pos)))
847 goto out_free_fd;
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300848 }
Arnaldo Carvalho de Melo5c581042011-01-11 22:30:02 -0200849
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200850 if (perf_evlist__alloc_pollfd(evsel_list) < 0)
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300851 goto out_free_fd;
Zhang, Yanmind6d901c2010-03-18 11:36:05 -0300852
Stephane Eranian3de29ca2010-05-17 12:20:43 -0300853 if (user_interval != ULLONG_MAX)
Frederic Weisbeckerf9212812010-04-14 22:09:02 +0200854 default_interval = user_interval;
855 if (user_freq != UINT_MAX)
856 freq = user_freq;
857
Mike Galbraith7e4ff9e2009-10-12 07:56:03 +0200858 /*
859 * User specified count overrides default frequency.
860 */
861 if (default_interval)
862 freq = 0;
863 else if (freq) {
864 default_interval = freq;
865 } else {
866 fprintf(stderr, "frequency and count are zero, aborting\n");
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300867 err = -EINVAL;
Arnaldo Carvalho de Melo5c581042011-01-11 22:30:02 -0200868 goto out_free_fd;
Mike Galbraith7e4ff9e2009-10-12 07:56:03 +0200869 }
870
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300871 err = __cmd_record(argc, argv);
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300872out_free_fd:
Arnaldo Carvalho de Melo7e2ed092011-01-30 11:59:43 -0200873 perf_evlist__delete_maps(evsel_list);
Arnaldo Carvalho de Melod65a4582010-07-30 18:31:28 -0300874out_symbol_exit:
875 symbol__exit();
Arnaldo Carvalho de Melo39d17da2010-07-29 14:08:55 -0300876 return err;
Ingo Molnar0e9b20b2009-05-26 09:17:18 +0200877}