blob: c3bba883f5c3b347ebba815386e0916cdbda8cc2 [file] [log] [blame]
Steven Rostedt520509432009-08-17 16:18:05 +02001/*
2 * Copyright (C) 2008,2009, Steven Rostedt <srostedt@redhat.com>
3 *
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License (not later!)
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20 */
Arnaldo Carvalho de Meloc168fbf2011-11-16 12:55:59 -020021#include "util.h"
Steven Rostedt520509432009-08-17 16:18:05 +020022#include <dirent.h>
Ulrich Drepper659d8cf2009-12-19 16:40:28 -050023#include <mntent.h>
Steven Rostedt520509432009-08-17 16:18:05 +020024#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include <stdarg.h>
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <sys/wait.h>
31#include <pthread.h>
32#include <fcntl.h>
33#include <unistd.h>
Steven Rostedt520509432009-08-17 16:18:05 +020034#include <errno.h>
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +020035#include <stdbool.h>
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -020036#include <linux/list.h>
Arnaldo Carvalho de Meloe2561362009-11-21 14:31:26 -020037#include <linux/kernel.h>
Steven Rostedt520509432009-08-17 16:18:05 +020038
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +020039#include "../perf.h"
Steven Rostedt520509432009-08-17 16:18:05 +020040#include "trace-event.h"
Borislav Petkov553873e2013-12-09 17:14:23 +010041#include <api/fs/debugfs.h>
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -020042#include "evsel.h"
Steven Rostedt520509432009-08-17 16:18:05 +020043
Steven Rostedt520509432009-08-17 16:18:05 +020044#define VERSION "0.5"
45
Steven Rostedt520509432009-08-17 16:18:05 +020046static int output_fd;
47
Steven Rostedt520509432009-08-17 16:18:05 +020048
Steven Rostedt520509432009-08-17 16:18:05 +020049int bigendian(void)
50{
51 unsigned char str[] = { 0x1, 0x2, 0x3, 0x4, 0x0, 0x0, 0x0, 0x0};
52 unsigned int *ptr;
53
Ingo Molnar65014ab2009-09-02 14:55:55 +020054 ptr = (unsigned int *)(void *)str;
Steven Rostedt520509432009-08-17 16:18:05 +020055 return *ptr == 0x01020304;
56}
57
Sonny Rao259032b2011-07-14 13:34:43 +100058/* unfortunately, you can not stat debugfs or proc files for size */
Namhyung Kim8755d5e2013-03-21 16:18:46 +090059static int record_file(const char *file, ssize_t hdr_sz)
Steven Rostedt520509432009-08-17 16:18:05 +020060{
61 unsigned long long size = 0;
Sonny Rao259032b2011-07-14 13:34:43 +100062 char buf[BUFSIZ], *sizep;
63 off_t hdr_pos = lseek(output_fd, 0, SEEK_CUR);
64 int r, fd;
Namhyung Kim8755d5e2013-03-21 16:18:46 +090065 int err = -EIO;
Sonny Rao259032b2011-07-14 13:34:43 +100066
67 fd = open(file, O_RDONLY);
Namhyung Kim7f42b952013-03-21 16:18:47 +090068 if (fd < 0) {
69 pr_debug("Can't read '%s'", file);
70 return -errno;
71 }
Sonny Rao259032b2011-07-14 13:34:43 +100072
73 /* put in zeros for file size, then fill true size later */
Namhyung Kim8755d5e2013-03-21 16:18:46 +090074 if (hdr_sz) {
75 if (write(output_fd, &size, hdr_sz) != hdr_sz)
76 goto out;
77 }
Steven Rostedt520509432009-08-17 16:18:05 +020078
79 do {
80 r = read(fd, buf, BUFSIZ);
81 if (r > 0) {
82 size += r;
Namhyung Kim8755d5e2013-03-21 16:18:46 +090083 if (write(output_fd, buf, r) != r)
84 goto out;
Steven Rostedt520509432009-08-17 16:18:05 +020085 }
86 } while (r > 0);
Steven Rostedt520509432009-08-17 16:18:05 +020087
Sonny Rao259032b2011-07-14 13:34:43 +100088 /* ugh, handle big-endian hdr_size == 4 */
89 sizep = (char*)&size;
90 if (bigendian())
91 sizep += sizeof(u64) - hdr_sz;
Steven Rostedt520509432009-08-17 16:18:05 +020092
Namhyung Kim7f42b952013-03-21 16:18:47 +090093 if (hdr_sz && pwrite(output_fd, sizep, hdr_sz, hdr_pos) < 0) {
94 pr_debug("writing file size failed\n");
95 goto out;
96 }
Namhyung Kim8755d5e2013-03-21 16:18:46 +090097
98 err = 0;
99out:
100 close(fd);
101 return err;
Steven Rostedt520509432009-08-17 16:18:05 +0200102}
103
Namhyung Kim077f1592013-06-04 14:20:29 +0900104static int record_header_files(void)
Steven Rostedt520509432009-08-17 16:18:05 +0200105{
Steven Rostedt520509432009-08-17 16:18:05 +0200106 char *path;
Sonny Rao259032b2011-07-14 13:34:43 +1000107 struct stat st;
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900108 int err = -EIO;
Steven Rostedt520509432009-08-17 16:18:05 +0200109
110 path = get_tracing_file("events/header_page");
Namhyung Kim7f42b952013-03-21 16:18:47 +0900111 if (!path) {
112 pr_debug("can't get tracing/events/header_page");
113 return -ENOMEM;
114 }
Namhyung Kim454f8c72013-03-21 16:18:44 +0900115
Namhyung Kim7f42b952013-03-21 16:18:47 +0900116 if (stat(path, &st) < 0) {
117 pr_debug("can't read '%s'", path);
118 goto out;
119 }
Steven Rostedt520509432009-08-17 16:18:05 +0200120
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900121 if (write(output_fd, "header_page", 12) != 12) {
122 pr_debug("can't write header_page\n");
123 goto out;
124 }
125
126 if (record_file(path, 8) < 0) {
127 pr_debug("can't record header_page file\n");
128 goto out;
129 }
130
Steven Rostedt520509432009-08-17 16:18:05 +0200131 put_tracing_file(path);
132
133 path = get_tracing_file("events/header_event");
Namhyung Kim7f42b952013-03-21 16:18:47 +0900134 if (!path) {
135 pr_debug("can't get tracing/events/header_event");
136 err = -ENOMEM;
137 goto out;
138 }
Namhyung Kim454f8c72013-03-21 16:18:44 +0900139
Namhyung Kim7f42b952013-03-21 16:18:47 +0900140 if (stat(path, &st) < 0) {
141 pr_debug("can't read '%s'", path);
142 goto out;
143 }
Steven Rostedt520509432009-08-17 16:18:05 +0200144
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900145 if (write(output_fd, "header_event", 13) != 13) {
146 pr_debug("can't write header_event\n");
147 goto out;
148 }
149
150 if (record_file(path, 8) < 0) {
151 pr_debug("can't record header_event file\n");
152 goto out;
153 }
154
155 err = 0;
156out:
Steven Rostedt520509432009-08-17 16:18:05 +0200157 put_tracing_file(path);
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900158 return err;
Steven Rostedt520509432009-08-17 16:18:05 +0200159}
160
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +0200161static bool name_in_tp_list(char *sys, struct tracepoint_path *tps)
162{
163 while (tps) {
164 if (!strcmp(sys, tps->name))
165 return true;
166 tps = tps->next;
167 }
168
169 return false;
170}
171
Namhyung Kim5a6fd272013-03-21 16:18:45 +0900172static int copy_event_system(const char *sys, struct tracepoint_path *tps)
Steven Rostedt520509432009-08-17 16:18:05 +0200173{
Steven Rostedt520509432009-08-17 16:18:05 +0200174 struct dirent *dent;
175 struct stat st;
176 char *format;
177 DIR *dir;
178 int count = 0;
179 int ret;
Namhyung Kim5a6fd272013-03-21 16:18:45 +0900180 int err;
Steven Rostedt520509432009-08-17 16:18:05 +0200181
182 dir = opendir(sys);
Namhyung Kim7f42b952013-03-21 16:18:47 +0900183 if (!dir) {
184 pr_debug("can't read directory '%s'", sys);
185 return -errno;
186 }
Steven Rostedt520509432009-08-17 16:18:05 +0200187
188 while ((dent = readdir(dir))) {
Ulrich Drepper659d8cf2009-12-19 16:40:28 -0500189 if (dent->d_type != DT_DIR ||
190 strcmp(dent->d_name, ".") == 0 ||
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +0200191 strcmp(dent->d_name, "..") == 0 ||
192 !name_in_tp_list(dent->d_name, tps))
Steven Rostedt520509432009-08-17 16:18:05 +0200193 continue;
Andy Shevchenkod400a682014-07-04 14:43:48 +0300194 if (asprintf(&format, "%s/%s/format", sys, dent->d_name) < 0) {
Namhyung Kim5a6fd272013-03-21 16:18:45 +0900195 err = -ENOMEM;
196 goto out;
197 }
Steven Rostedt520509432009-08-17 16:18:05 +0200198 ret = stat(format, &st);
199 free(format);
200 if (ret < 0)
201 continue;
202 count++;
203 }
204
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900205 if (write(output_fd, &count, 4) != 4) {
206 err = -EIO;
207 pr_debug("can't write count\n");
208 goto out;
209 }
Steven Rostedt520509432009-08-17 16:18:05 +0200210
211 rewinddir(dir);
212 while ((dent = readdir(dir))) {
Ulrich Drepper659d8cf2009-12-19 16:40:28 -0500213 if (dent->d_type != DT_DIR ||
214 strcmp(dent->d_name, ".") == 0 ||
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +0200215 strcmp(dent->d_name, "..") == 0 ||
216 !name_in_tp_list(dent->d_name, tps))
Steven Rostedt520509432009-08-17 16:18:05 +0200217 continue;
Andy Shevchenkod400a682014-07-04 14:43:48 +0300218 if (asprintf(&format, "%s/%s/format", sys, dent->d_name) < 0) {
Namhyung Kim5a6fd272013-03-21 16:18:45 +0900219 err = -ENOMEM;
220 goto out;
221 }
Steven Rostedt520509432009-08-17 16:18:05 +0200222 ret = stat(format, &st);
223
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900224 if (ret >= 0) {
225 err = record_file(format, 8);
226 if (err) {
227 free(format);
228 goto out;
229 }
230 }
Steven Rostedt520509432009-08-17 16:18:05 +0200231 free(format);
232 }
Namhyung Kim5a6fd272013-03-21 16:18:45 +0900233 err = 0;
234out:
Xiao Guangrong99674112009-12-28 16:49:38 +0800235 closedir(dir);
Namhyung Kim5a6fd272013-03-21 16:18:45 +0900236 return err;
Steven Rostedt520509432009-08-17 16:18:05 +0200237}
238
Namhyung Kim077f1592013-06-04 14:20:29 +0900239static int record_ftrace_files(struct tracepoint_path *tps)
Steven Rostedt520509432009-08-17 16:18:05 +0200240{
241 char *path;
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900242 int ret;
Steven Rostedt520509432009-08-17 16:18:05 +0200243
244 path = get_tracing_file("events/ftrace");
Namhyung Kim7f42b952013-03-21 16:18:47 +0900245 if (!path) {
246 pr_debug("can't get tracing/events/ftrace");
247 return -ENOMEM;
248 }
Steven Rostedt520509432009-08-17 16:18:05 +0200249
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900250 ret = copy_event_system(path, tps);
Steven Rostedt520509432009-08-17 16:18:05 +0200251
252 put_tracing_file(path);
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900253
254 return ret;
Steven Rostedt520509432009-08-17 16:18:05 +0200255}
256
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +0200257static bool system_in_tp_list(char *sys, struct tracepoint_path *tps)
258{
259 while (tps) {
260 if (!strcmp(sys, tps->system))
261 return true;
262 tps = tps->next;
263 }
264
265 return false;
266}
267
Namhyung Kim077f1592013-06-04 14:20:29 +0900268static int record_event_files(struct tracepoint_path *tps)
Steven Rostedt520509432009-08-17 16:18:05 +0200269{
270 struct dirent *dent;
271 struct stat st;
272 char *path;
273 char *sys;
274 DIR *dir;
275 int count = 0;
276 int ret;
Namhyung Kim5a6fd272013-03-21 16:18:45 +0900277 int err;
Steven Rostedt520509432009-08-17 16:18:05 +0200278
279 path = get_tracing_file("events");
Namhyung Kim7f42b952013-03-21 16:18:47 +0900280 if (!path) {
281 pr_debug("can't get tracing/events");
282 return -ENOMEM;
283 }
Steven Rostedt520509432009-08-17 16:18:05 +0200284
285 dir = opendir(path);
Namhyung Kim7f42b952013-03-21 16:18:47 +0900286 if (!dir) {
287 err = -errno;
288 pr_debug("can't read directory '%s'", path);
289 goto out;
290 }
Steven Rostedt520509432009-08-17 16:18:05 +0200291
292 while ((dent = readdir(dir))) {
Ulrich Drepper659d8cf2009-12-19 16:40:28 -0500293 if (dent->d_type != DT_DIR ||
294 strcmp(dent->d_name, ".") == 0 ||
Steven Rostedt520509432009-08-17 16:18:05 +0200295 strcmp(dent->d_name, "..") == 0 ||
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +0200296 strcmp(dent->d_name, "ftrace") == 0 ||
297 !system_in_tp_list(dent->d_name, tps))
Steven Rostedt520509432009-08-17 16:18:05 +0200298 continue;
Ulrich Drepper659d8cf2009-12-19 16:40:28 -0500299 count++;
Steven Rostedt520509432009-08-17 16:18:05 +0200300 }
301
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900302 if (write(output_fd, &count, 4) != 4) {
303 err = -EIO;
304 pr_debug("can't write count\n");
305 goto out;
306 }
Steven Rostedt520509432009-08-17 16:18:05 +0200307
308 rewinddir(dir);
309 while ((dent = readdir(dir))) {
Ulrich Drepper659d8cf2009-12-19 16:40:28 -0500310 if (dent->d_type != DT_DIR ||
311 strcmp(dent->d_name, ".") == 0 ||
Steven Rostedt520509432009-08-17 16:18:05 +0200312 strcmp(dent->d_name, "..") == 0 ||
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +0200313 strcmp(dent->d_name, "ftrace") == 0 ||
314 !system_in_tp_list(dent->d_name, tps))
Steven Rostedt520509432009-08-17 16:18:05 +0200315 continue;
Andy Shevchenkod400a682014-07-04 14:43:48 +0300316 if (asprintf(&sys, "%s/%s", path, dent->d_name) < 0) {
Namhyung Kim5a6fd272013-03-21 16:18:45 +0900317 err = -ENOMEM;
318 goto out;
319 }
Steven Rostedt520509432009-08-17 16:18:05 +0200320 ret = stat(sys, &st);
321 if (ret >= 0) {
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900322 ssize_t size = strlen(dent->d_name) + 1;
323
324 if (write(output_fd, dent->d_name, size) != size ||
325 copy_event_system(sys, tps) < 0) {
326 err = -EIO;
327 free(sys);
328 goto out;
329 }
Steven Rostedt520509432009-08-17 16:18:05 +0200330 }
331 free(sys);
332 }
Namhyung Kim5a6fd272013-03-21 16:18:45 +0900333 err = 0;
334out:
Xiao Guangrong99674112009-12-28 16:49:38 +0800335 closedir(dir);
Steven Rostedt520509432009-08-17 16:18:05 +0200336 put_tracing_file(path);
Namhyung Kim5a6fd272013-03-21 16:18:45 +0900337
338 return err;
Steven Rostedt520509432009-08-17 16:18:05 +0200339}
340
Namhyung Kim077f1592013-06-04 14:20:29 +0900341static int record_proc_kallsyms(void)
Steven Rostedt520509432009-08-17 16:18:05 +0200342{
Sonny Rao259032b2011-07-14 13:34:43 +1000343 unsigned int size;
Steven Rostedt520509432009-08-17 16:18:05 +0200344 const char *path = "/proc/kallsyms";
345 struct stat st;
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900346 int ret, err = 0;
Steven Rostedt520509432009-08-17 16:18:05 +0200347
348 ret = stat(path, &st);
349 if (ret < 0) {
350 /* not found */
351 size = 0;
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900352 if (write(output_fd, &size, 4) != 4)
353 err = -EIO;
354 return err;
Steven Rostedt520509432009-08-17 16:18:05 +0200355 }
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900356 return record_file(path, 4);
Steven Rostedt520509432009-08-17 16:18:05 +0200357}
358
Namhyung Kim077f1592013-06-04 14:20:29 +0900359static int record_ftrace_printk(void)
Steven Rostedt520509432009-08-17 16:18:05 +0200360{
Sonny Rao259032b2011-07-14 13:34:43 +1000361 unsigned int size;
Li Zefan6706ccf2009-09-17 16:34:23 +0800362 char *path;
Steven Rostedt520509432009-08-17 16:18:05 +0200363 struct stat st;
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900364 int ret, err = 0;
Steven Rostedt520509432009-08-17 16:18:05 +0200365
366 path = get_tracing_file("printk_formats");
Namhyung Kim7f42b952013-03-21 16:18:47 +0900367 if (!path) {
368 pr_debug("can't get tracing/printk_formats");
369 return -ENOMEM;
370 }
Namhyung Kim454f8c72013-03-21 16:18:44 +0900371
Steven Rostedt520509432009-08-17 16:18:05 +0200372 ret = stat(path, &st);
373 if (ret < 0) {
374 /* not found */
375 size = 0;
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900376 if (write(output_fd, &size, 4) != 4)
377 err = -EIO;
Li Zefan6706ccf2009-09-17 16:34:23 +0800378 goto out;
Steven Rostedt520509432009-08-17 16:18:05 +0200379 }
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900380 err = record_file(path, 4);
Sonny Rao259032b2011-07-14 13:34:43 +1000381
Li Zefan6706ccf2009-09-17 16:34:23 +0800382out:
383 put_tracing_file(path);
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900384 return err;
Steven Rostedt520509432009-08-17 16:18:05 +0200385}
386
Namhyung Kim7f42b952013-03-21 16:18:47 +0900387static void
388put_tracepoints_path(struct tracepoint_path *tps)
389{
390 while (tps) {
391 struct tracepoint_path *t = tps;
392
393 tps = tps->next;
Arnaldo Carvalho de Melo74cf2492013-12-27 16:55:14 -0300394 zfree(&t->name);
395 zfree(&t->system);
Namhyung Kim7f42b952013-03-21 16:18:47 +0900396 free(t);
397 }
398}
399
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +0200400static struct tracepoint_path *
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200401get_tracepoints_path(struct list_head *pattrs)
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +0200402{
403 struct tracepoint_path path, *ppath = &path;
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200404 struct perf_evsel *pos;
405 int nr_tracepoints = 0;
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +0200406
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200407 list_for_each_entry(pos, pattrs, node) {
408 if (pos->attr.type != PERF_TYPE_TRACEPOINT)
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +0200409 continue;
Arnaldo Carvalho de Meloe2561362009-11-21 14:31:26 -0200410 ++nr_tracepoints;
Namhyung Kime7c93f02013-06-26 16:14:05 +0900411
412 if (pos->name) {
413 ppath->next = tracepoint_name_to_path(pos->name);
414 if (ppath->next)
415 goto next;
416
417 if (strchr(pos->name, ':') == NULL)
418 goto try_id;
419
420 goto error;
421 }
422
423try_id:
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200424 ppath->next = tracepoint_id_to_path(pos->attr.config);
Namhyung Kim7f42b952013-03-21 16:18:47 +0900425 if (!ppath->next) {
Namhyung Kime7c93f02013-06-26 16:14:05 +0900426error:
Namhyung Kim7f42b952013-03-21 16:18:47 +0900427 pr_debug("No memory to alloc tracepoints list\n");
428 put_tracepoints_path(&path);
429 return NULL;
430 }
Namhyung Kime7c93f02013-06-26 16:14:05 +0900431next:
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +0200432 ppath = ppath->next;
433 }
434
Arnaldo Carvalho de Meloe2561362009-11-21 14:31:26 -0200435 return nr_tracepoints > 0 ? path.next : NULL;
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +0200436}
Arnaldo Carvalho de Meloe2561362009-11-21 14:31:26 -0200437
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200438bool have_tracepoints(struct list_head *pattrs)
Tom Zanussi63e0c772010-05-03 00:14:48 -0500439{
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200440 struct perf_evsel *pos;
Tom Zanussidb620b12010-05-04 22:20:16 -0500441
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200442 list_for_each_entry(pos, pattrs, node)
443 if (pos->attr.type == PERF_TYPE_TRACEPOINT)
Tom Zanussidb620b12010-05-04 22:20:16 -0500444 return true;
445
446 return false;
Tom Zanussi63e0c772010-05-03 00:14:48 -0500447}
448
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900449static int tracing_data_header(void)
Steven Rostedt520509432009-08-17 16:18:05 +0200450{
Jiri Olsa29208e52011-10-20 15:59:43 +0200451 char buf[20];
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900452 ssize_t size;
Arnaldo Carvalho de Meloe2561362009-11-21 14:31:26 -0200453
Jiri Olsa29208e52011-10-20 15:59:43 +0200454 /* just guessing this is someone's birthday.. ;) */
Steven Rostedt520509432009-08-17 16:18:05 +0200455 buf[0] = 23;
456 buf[1] = 8;
457 buf[2] = 68;
458 memcpy(buf + 3, "tracing", 7);
459
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900460 if (write(output_fd, buf, 10) != 10)
461 return -1;
Steven Rostedt520509432009-08-17 16:18:05 +0200462
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900463 size = strlen(VERSION) + 1;
464 if (write(output_fd, VERSION, size) != size)
465 return -1;
Steven Rostedt520509432009-08-17 16:18:05 +0200466
467 /* save endian */
468 if (bigendian())
469 buf[0] = 1;
470 else
471 buf[0] = 0;
472
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900473 if (write(output_fd, buf, 1) != 1)
474 return -1;
Steven Rostedt520509432009-08-17 16:18:05 +0200475
476 /* save size of long */
477 buf[0] = sizeof(long);
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900478 if (write(output_fd, buf, 1) != 1)
479 return -1;
Steven Rostedt520509432009-08-17 16:18:05 +0200480
481 /* save page_size */
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900482 if (write(output_fd, &page_size, 4) != 4)
483 return -1;
484
485 return 0;
Jiri Olsa29208e52011-10-20 15:59:43 +0200486}
Steven Rostedt520509432009-08-17 16:18:05 +0200487
Jiri Olsa29208e52011-10-20 15:59:43 +0200488struct tracing_data *tracing_data_get(struct list_head *pattrs,
489 int fd, bool temp)
490{
491 struct tracepoint_path *tps;
492 struct tracing_data *tdata;
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900493 int err;
Jiri Olsa29208e52011-10-20 15:59:43 +0200494
495 output_fd = fd;
496
497 tps = get_tracepoints_path(pattrs);
498 if (!tps)
499 return NULL;
500
Namhyung Kim5a6fd272013-03-21 16:18:45 +0900501 tdata = malloc(sizeof(*tdata));
502 if (!tdata)
503 return NULL;
504
Jiri Olsa29208e52011-10-20 15:59:43 +0200505 tdata->temp = temp;
506 tdata->size = 0;
507
508 if (temp) {
509 int temp_fd;
510
511 snprintf(tdata->temp_file, sizeof(tdata->temp_file),
512 "/tmp/perf-XXXXXX");
Namhyung Kim7f42b952013-03-21 16:18:47 +0900513 if (!mkstemp(tdata->temp_file)) {
514 pr_debug("Can't make temp file");
515 return NULL;
516 }
Jiri Olsa29208e52011-10-20 15:59:43 +0200517
518 temp_fd = open(tdata->temp_file, O_RDWR);
Namhyung Kim7f42b952013-03-21 16:18:47 +0900519 if (temp_fd < 0) {
520 pr_debug("Can't read '%s'", tdata->temp_file);
521 return NULL;
522 }
Jiri Olsa29208e52011-10-20 15:59:43 +0200523
524 /*
525 * Set the temp file the default output, so all the
526 * tracing data are stored into it.
527 */
528 output_fd = temp_fd;
529 }
530
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900531 err = tracing_data_header();
532 if (err)
533 goto out;
Namhyung Kim077f1592013-06-04 14:20:29 +0900534 err = record_header_files();
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900535 if (err)
536 goto out;
Namhyung Kim077f1592013-06-04 14:20:29 +0900537 err = record_ftrace_files(tps);
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900538 if (err)
539 goto out;
Namhyung Kim077f1592013-06-04 14:20:29 +0900540 err = record_event_files(tps);
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900541 if (err)
542 goto out;
Namhyung Kim077f1592013-06-04 14:20:29 +0900543 err = record_proc_kallsyms();
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900544 if (err)
545 goto out;
Namhyung Kim077f1592013-06-04 14:20:29 +0900546 err = record_ftrace_printk();
Arnaldo Carvalho de Meloe2561362009-11-21 14:31:26 -0200547
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900548out:
Jiri Olsa29208e52011-10-20 15:59:43 +0200549 /*
550 * All tracing data are stored by now, we can restore
551 * the default output file in case we used temp file.
552 */
553 if (temp) {
554 tdata->size = lseek(output_fd, 0, SEEK_CUR);
555 close(output_fd);
556 output_fd = fd;
557 }
558
Arnaldo Carvalho de Melo04662522013-12-26 17:41:15 -0300559 if (err)
560 zfree(&tdata);
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900561
Jiri Olsa29208e52011-10-20 15:59:43 +0200562 put_tracepoints_path(tps);
563 return tdata;
Steven Rostedt520509432009-08-17 16:18:05 +0200564}
Tom Zanussi92155452010-04-01 23:59:21 -0500565
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900566int tracing_data_put(struct tracing_data *tdata)
Tom Zanussi92155452010-04-01 23:59:21 -0500567{
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900568 int err = 0;
569
Jiri Olsa29208e52011-10-20 15:59:43 +0200570 if (tdata->temp) {
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900571 err = record_file(tdata->temp_file, 0);
Jiri Olsa29208e52011-10-20 15:59:43 +0200572 unlink(tdata->temp_file);
573 }
Tom Zanussi92155452010-04-01 23:59:21 -0500574
Jiri Olsa29208e52011-10-20 15:59:43 +0200575 free(tdata);
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900576 return err;
Jiri Olsa29208e52011-10-20 15:59:43 +0200577}
Tom Zanussi92155452010-04-01 23:59:21 -0500578
Jiri Olsa29208e52011-10-20 15:59:43 +0200579int read_tracing_data(int fd, struct list_head *pattrs)
580{
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900581 int err;
Jiri Olsa29208e52011-10-20 15:59:43 +0200582 struct tracing_data *tdata;
Tom Zanussi92155452010-04-01 23:59:21 -0500583
Jiri Olsa29208e52011-10-20 15:59:43 +0200584 /*
585 * We work over the real file, so we can write data
586 * directly, no temp file is needed.
587 */
588 tdata = tracing_data_get(pattrs, fd, false);
589 if (!tdata)
590 return -ENOMEM;
591
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900592 err = tracing_data_put(tdata);
593 return err;
Tom Zanussi92155452010-04-01 23:59:21 -0500594}