blob: 090e80d743dbedd99802b492e038b13b1a4edc90 [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 Petkov85c66be2013-02-20 16:32:30 +010041#include <lk/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 const char *output_file = "trace.info";
47static int output_fd;
48
Steven Rostedt520509432009-08-17 16:18:05 +020049
Steven Rostedt520509432009-08-17 16:18:05 +020050static const char *find_debugfs(void)
51{
Borislav Petkov13559152013-02-20 16:32:31 +010052 const char *path = perf_debugfs_mount(NULL);
Steven Rostedt520509432009-08-17 16:18:05 +020053
Xiao Guangrong61be3e52009-12-28 16:48:30 +080054 if (!path)
Namhyung Kim454f8c72013-03-21 16:18:44 +090055 pr_debug("Your kernel does not support the debugfs filesystem");
Steven Rostedt520509432009-08-17 16:18:05 +020056
Xiao Guangrong61be3e52009-12-28 16:48:30 +080057 return path;
Steven Rostedt520509432009-08-17 16:18:05 +020058}
59
60/*
61 * Finds the path to the debugfs/tracing
62 * Allocates the string and stores it.
63 */
64static const char *find_tracing_dir(void)
65{
66 static char *tracing;
67 static int tracing_found;
68 const char *debugfs;
69
70 if (tracing_found)
71 return tracing;
72
73 debugfs = find_debugfs();
Namhyung Kim454f8c72013-03-21 16:18:44 +090074 if (!debugfs)
75 return NULL;
Steven Rostedt520509432009-08-17 16:18:05 +020076
Namhyung Kim454f8c72013-03-21 16:18:44 +090077 tracing = malloc(strlen(debugfs) + 9);
78 if (!tracing)
79 return NULL;
Steven Rostedt520509432009-08-17 16:18:05 +020080
81 sprintf(tracing, "%s/tracing", debugfs);
82
83 tracing_found = 1;
84 return tracing;
85}
86
87static char *get_tracing_file(const char *name)
88{
89 const char *tracing;
90 char *file;
91
92 tracing = find_tracing_dir();
93 if (!tracing)
94 return NULL;
95
Namhyung Kim454f8c72013-03-21 16:18:44 +090096 file = malloc(strlen(tracing) + strlen(name) + 2);
97 if (!file)
98 return NULL;
Steven Rostedt520509432009-08-17 16:18:05 +020099
100 sprintf(file, "%s/%s", tracing, name);
101 return file;
102}
103
104static void put_tracing_file(char *file)
105{
106 free(file);
107}
108
Steven Rostedt520509432009-08-17 16:18:05 +0200109int bigendian(void)
110{
111 unsigned char str[] = { 0x1, 0x2, 0x3, 0x4, 0x0, 0x0, 0x0, 0x0};
112 unsigned int *ptr;
113
Ingo Molnar65014ab2009-09-02 14:55:55 +0200114 ptr = (unsigned int *)(void *)str;
Steven Rostedt520509432009-08-17 16:18:05 +0200115 return *ptr == 0x01020304;
116}
117
Sonny Rao259032b2011-07-14 13:34:43 +1000118/* unfortunately, you can not stat debugfs or proc files for size */
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900119static int record_file(const char *file, ssize_t hdr_sz)
Steven Rostedt520509432009-08-17 16:18:05 +0200120{
121 unsigned long long size = 0;
Sonny Rao259032b2011-07-14 13:34:43 +1000122 char buf[BUFSIZ], *sizep;
123 off_t hdr_pos = lseek(output_fd, 0, SEEK_CUR);
124 int r, fd;
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900125 int err = -EIO;
Sonny Rao259032b2011-07-14 13:34:43 +1000126
127 fd = open(file, O_RDONLY);
128 if (fd < 0)
129 die("Can't read '%s'", file);
130
131 /* put in zeros for file size, then fill true size later */
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900132 if (hdr_sz) {
133 if (write(output_fd, &size, hdr_sz) != hdr_sz)
134 goto out;
135 }
Steven Rostedt520509432009-08-17 16:18:05 +0200136
137 do {
138 r = read(fd, buf, BUFSIZ);
139 if (r > 0) {
140 size += r;
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900141 if (write(output_fd, buf, r) != r)
142 goto out;
Steven Rostedt520509432009-08-17 16:18:05 +0200143 }
144 } while (r > 0);
Steven Rostedt520509432009-08-17 16:18:05 +0200145
Sonny Rao259032b2011-07-14 13:34:43 +1000146 /* ugh, handle big-endian hdr_size == 4 */
147 sizep = (char*)&size;
148 if (bigendian())
149 sizep += sizeof(u64) - hdr_sz;
Steven Rostedt520509432009-08-17 16:18:05 +0200150
Jiri Olsa29208e52011-10-20 15:59:43 +0200151 if (hdr_sz && pwrite(output_fd, sizep, hdr_sz, hdr_pos) < 0)
Sonny Rao259032b2011-07-14 13:34:43 +1000152 die("writing to %s", output_file);
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900153
154 err = 0;
155out:
156 close(fd);
157 return err;
Steven Rostedt520509432009-08-17 16:18:05 +0200158}
159
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900160static int read_header_files(void)
Steven Rostedt520509432009-08-17 16:18:05 +0200161{
Steven Rostedt520509432009-08-17 16:18:05 +0200162 char *path;
Sonny Rao259032b2011-07-14 13:34:43 +1000163 struct stat st;
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900164 int err = -EIO;
Steven Rostedt520509432009-08-17 16:18:05 +0200165
166 path = get_tracing_file("events/header_page");
Namhyung Kim454f8c72013-03-21 16:18:44 +0900167 if (!path)
168 die("can't get tracing/events/header_page");
169
Sonny Rao259032b2011-07-14 13:34:43 +1000170 if (stat(path, &st) < 0)
Steven Rostedt520509432009-08-17 16:18:05 +0200171 die("can't read '%s'", path);
172
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900173 if (write(output_fd, "header_page", 12) != 12) {
174 pr_debug("can't write header_page\n");
175 goto out;
176 }
177
178 if (record_file(path, 8) < 0) {
179 pr_debug("can't record header_page file\n");
180 goto out;
181 }
182
Steven Rostedt520509432009-08-17 16:18:05 +0200183 put_tracing_file(path);
184
185 path = get_tracing_file("events/header_event");
Namhyung Kim454f8c72013-03-21 16:18:44 +0900186 if (!path)
187 die("can't get tracing/events/header_event");
188
Sonny Rao259032b2011-07-14 13:34:43 +1000189 if (stat(path, &st) < 0)
Steven Rostedt520509432009-08-17 16:18:05 +0200190 die("can't read '%s'", path);
191
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900192 if (write(output_fd, "header_event", 13) != 13) {
193 pr_debug("can't write header_event\n");
194 goto out;
195 }
196
197 if (record_file(path, 8) < 0) {
198 pr_debug("can't record header_event file\n");
199 goto out;
200 }
201
202 err = 0;
203out:
Steven Rostedt520509432009-08-17 16:18:05 +0200204 put_tracing_file(path);
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900205 return err;
Steven Rostedt520509432009-08-17 16:18:05 +0200206}
207
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +0200208static bool name_in_tp_list(char *sys, struct tracepoint_path *tps)
209{
210 while (tps) {
211 if (!strcmp(sys, tps->name))
212 return true;
213 tps = tps->next;
214 }
215
216 return false;
217}
218
Namhyung Kim5a6fd272013-03-21 16:18:45 +0900219static int copy_event_system(const char *sys, struct tracepoint_path *tps)
Steven Rostedt520509432009-08-17 16:18:05 +0200220{
Steven Rostedt520509432009-08-17 16:18:05 +0200221 struct dirent *dent;
222 struct stat st;
223 char *format;
224 DIR *dir;
225 int count = 0;
226 int ret;
Namhyung Kim5a6fd272013-03-21 16:18:45 +0900227 int err;
Steven Rostedt520509432009-08-17 16:18:05 +0200228
229 dir = opendir(sys);
230 if (!dir)
231 die("can't read directory '%s'", sys);
232
233 while ((dent = readdir(dir))) {
Ulrich Drepper659d8cf2009-12-19 16:40:28 -0500234 if (dent->d_type != DT_DIR ||
235 strcmp(dent->d_name, ".") == 0 ||
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +0200236 strcmp(dent->d_name, "..") == 0 ||
237 !name_in_tp_list(dent->d_name, tps))
Steven Rostedt520509432009-08-17 16:18:05 +0200238 continue;
Namhyung Kim5a6fd272013-03-21 16:18:45 +0900239 format = malloc(strlen(sys) + strlen(dent->d_name) + 10);
240 if (!format) {
241 err = -ENOMEM;
242 goto out;
243 }
Steven Rostedt520509432009-08-17 16:18:05 +0200244 sprintf(format, "%s/%s/format", sys, dent->d_name);
245 ret = stat(format, &st);
246 free(format);
247 if (ret < 0)
248 continue;
249 count++;
250 }
251
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900252 if (write(output_fd, &count, 4) != 4) {
253 err = -EIO;
254 pr_debug("can't write count\n");
255 goto out;
256 }
Steven Rostedt520509432009-08-17 16:18:05 +0200257
258 rewinddir(dir);
259 while ((dent = readdir(dir))) {
Ulrich Drepper659d8cf2009-12-19 16:40:28 -0500260 if (dent->d_type != DT_DIR ||
261 strcmp(dent->d_name, ".") == 0 ||
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +0200262 strcmp(dent->d_name, "..") == 0 ||
263 !name_in_tp_list(dent->d_name, tps))
Steven Rostedt520509432009-08-17 16:18:05 +0200264 continue;
Namhyung Kim5a6fd272013-03-21 16:18:45 +0900265 format = malloc(strlen(sys) + strlen(dent->d_name) + 10);
266 if (!format) {
267 err = -ENOMEM;
268 goto out;
269 }
Steven Rostedt520509432009-08-17 16:18:05 +0200270 sprintf(format, "%s/%s/format", sys, dent->d_name);
271 ret = stat(format, &st);
272
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900273 if (ret >= 0) {
274 err = record_file(format, 8);
275 if (err) {
276 free(format);
277 goto out;
278 }
279 }
Steven Rostedt520509432009-08-17 16:18:05 +0200280 free(format);
281 }
Namhyung Kim5a6fd272013-03-21 16:18:45 +0900282 err = 0;
283out:
Xiao Guangrong99674112009-12-28 16:49:38 +0800284 closedir(dir);
Namhyung Kim5a6fd272013-03-21 16:18:45 +0900285 return err;
Steven Rostedt520509432009-08-17 16:18:05 +0200286}
287
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900288static int read_ftrace_files(struct tracepoint_path *tps)
Steven Rostedt520509432009-08-17 16:18:05 +0200289{
290 char *path;
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900291 int ret;
Steven Rostedt520509432009-08-17 16:18:05 +0200292
293 path = get_tracing_file("events/ftrace");
Namhyung Kim454f8c72013-03-21 16:18:44 +0900294 if (!path)
295 die("can't get tracing/events/ftrace");
Steven Rostedt520509432009-08-17 16:18:05 +0200296
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900297 ret = copy_event_system(path, tps);
Steven Rostedt520509432009-08-17 16:18:05 +0200298
299 put_tracing_file(path);
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900300
301 return ret;
Steven Rostedt520509432009-08-17 16:18:05 +0200302}
303
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +0200304static bool system_in_tp_list(char *sys, struct tracepoint_path *tps)
305{
306 while (tps) {
307 if (!strcmp(sys, tps->system))
308 return true;
309 tps = tps->next;
310 }
311
312 return false;
313}
314
Namhyung Kim5a6fd272013-03-21 16:18:45 +0900315static int read_event_files(struct tracepoint_path *tps)
Steven Rostedt520509432009-08-17 16:18:05 +0200316{
317 struct dirent *dent;
318 struct stat st;
319 char *path;
320 char *sys;
321 DIR *dir;
322 int count = 0;
323 int ret;
Namhyung Kim5a6fd272013-03-21 16:18:45 +0900324 int err;
Steven Rostedt520509432009-08-17 16:18:05 +0200325
326 path = get_tracing_file("events");
Namhyung Kim454f8c72013-03-21 16:18:44 +0900327 if (!path)
328 die("can't get tracing/events");
Steven Rostedt520509432009-08-17 16:18:05 +0200329
330 dir = opendir(path);
331 if (!dir)
332 die("can't read directory '%s'", path);
333
334 while ((dent = readdir(dir))) {
Ulrich Drepper659d8cf2009-12-19 16:40:28 -0500335 if (dent->d_type != DT_DIR ||
336 strcmp(dent->d_name, ".") == 0 ||
Steven Rostedt520509432009-08-17 16:18:05 +0200337 strcmp(dent->d_name, "..") == 0 ||
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +0200338 strcmp(dent->d_name, "ftrace") == 0 ||
339 !system_in_tp_list(dent->d_name, tps))
Steven Rostedt520509432009-08-17 16:18:05 +0200340 continue;
Ulrich Drepper659d8cf2009-12-19 16:40:28 -0500341 count++;
Steven Rostedt520509432009-08-17 16:18:05 +0200342 }
343
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900344 if (write(output_fd, &count, 4) != 4) {
345 err = -EIO;
346 pr_debug("can't write count\n");
347 goto out;
348 }
Steven Rostedt520509432009-08-17 16:18:05 +0200349
350 rewinddir(dir);
351 while ((dent = readdir(dir))) {
Ulrich Drepper659d8cf2009-12-19 16:40:28 -0500352 if (dent->d_type != DT_DIR ||
353 strcmp(dent->d_name, ".") == 0 ||
Steven Rostedt520509432009-08-17 16:18:05 +0200354 strcmp(dent->d_name, "..") == 0 ||
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +0200355 strcmp(dent->d_name, "ftrace") == 0 ||
356 !system_in_tp_list(dent->d_name, tps))
Steven Rostedt520509432009-08-17 16:18:05 +0200357 continue;
Namhyung Kim5a6fd272013-03-21 16:18:45 +0900358 sys = malloc(strlen(path) + strlen(dent->d_name) + 2);
359 if (!sys) {
360 err = -ENOMEM;
361 goto out;
362 }
Steven Rostedt520509432009-08-17 16:18:05 +0200363 sprintf(sys, "%s/%s", path, dent->d_name);
364 ret = stat(sys, &st);
365 if (ret >= 0) {
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900366 ssize_t size = strlen(dent->d_name) + 1;
367
368 if (write(output_fd, dent->d_name, size) != size ||
369 copy_event_system(sys, tps) < 0) {
370 err = -EIO;
371 free(sys);
372 goto out;
373 }
Steven Rostedt520509432009-08-17 16:18:05 +0200374 }
375 free(sys);
376 }
Namhyung Kim5a6fd272013-03-21 16:18:45 +0900377 err = 0;
378out:
Xiao Guangrong99674112009-12-28 16:49:38 +0800379 closedir(dir);
Steven Rostedt520509432009-08-17 16:18:05 +0200380 put_tracing_file(path);
Namhyung Kim5a6fd272013-03-21 16:18:45 +0900381
382 return err;
Steven Rostedt520509432009-08-17 16:18:05 +0200383}
384
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900385static int read_proc_kallsyms(void)
Steven Rostedt520509432009-08-17 16:18:05 +0200386{
Sonny Rao259032b2011-07-14 13:34:43 +1000387 unsigned int size;
Steven Rostedt520509432009-08-17 16:18:05 +0200388 const char *path = "/proc/kallsyms";
389 struct stat st;
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900390 int ret, err = 0;
Steven Rostedt520509432009-08-17 16:18:05 +0200391
392 ret = stat(path, &st);
393 if (ret < 0) {
394 /* not found */
395 size = 0;
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900396 if (write(output_fd, &size, 4) != 4)
397 err = -EIO;
398 return err;
Steven Rostedt520509432009-08-17 16:18:05 +0200399 }
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900400 return record_file(path, 4);
Steven Rostedt520509432009-08-17 16:18:05 +0200401}
402
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900403static int read_ftrace_printk(void)
Steven Rostedt520509432009-08-17 16:18:05 +0200404{
Sonny Rao259032b2011-07-14 13:34:43 +1000405 unsigned int size;
Li Zefan6706ccf2009-09-17 16:34:23 +0800406 char *path;
Steven Rostedt520509432009-08-17 16:18:05 +0200407 struct stat st;
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900408 int ret, err = 0;
Steven Rostedt520509432009-08-17 16:18:05 +0200409
410 path = get_tracing_file("printk_formats");
Namhyung Kim454f8c72013-03-21 16:18:44 +0900411 if (!path)
412 die("can't get tracing/printk_formats");
413
Steven Rostedt520509432009-08-17 16:18:05 +0200414 ret = stat(path, &st);
415 if (ret < 0) {
416 /* not found */
417 size = 0;
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900418 if (write(output_fd, &size, 4) != 4)
419 err = -EIO;
Li Zefan6706ccf2009-09-17 16:34:23 +0800420 goto out;
Steven Rostedt520509432009-08-17 16:18:05 +0200421 }
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900422 err = record_file(path, 4);
Sonny Rao259032b2011-07-14 13:34:43 +1000423
Li Zefan6706ccf2009-09-17 16:34:23 +0800424out:
425 put_tracing_file(path);
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900426 return err;
Steven Rostedt520509432009-08-17 16:18:05 +0200427}
428
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +0200429static struct tracepoint_path *
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200430get_tracepoints_path(struct list_head *pattrs)
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +0200431{
432 struct tracepoint_path path, *ppath = &path;
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200433 struct perf_evsel *pos;
434 int nr_tracepoints = 0;
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +0200435
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200436 list_for_each_entry(pos, pattrs, node) {
437 if (pos->attr.type != PERF_TYPE_TRACEPOINT)
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +0200438 continue;
Arnaldo Carvalho de Meloe2561362009-11-21 14:31:26 -0200439 ++nr_tracepoints;
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200440 ppath->next = tracepoint_id_to_path(pos->attr.config);
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +0200441 if (!ppath->next)
442 die("%s\n", "No memory to alloc tracepoints list");
443 ppath = ppath->next;
444 }
445
Arnaldo Carvalho de Meloe2561362009-11-21 14:31:26 -0200446 return nr_tracepoints > 0 ? path.next : NULL;
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +0200447}
Arnaldo Carvalho de Meloe2561362009-11-21 14:31:26 -0200448
Jiri Olsa29208e52011-10-20 15:59:43 +0200449static void
450put_tracepoints_path(struct tracepoint_path *tps)
451{
452 while (tps) {
453 struct tracepoint_path *t = tps;
454
455 tps = tps->next;
456 free(t->name);
457 free(t->system);
458 free(t);
459 }
460}
461
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200462bool have_tracepoints(struct list_head *pattrs)
Tom Zanussi63e0c772010-05-03 00:14:48 -0500463{
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200464 struct perf_evsel *pos;
Tom Zanussidb620b12010-05-04 22:20:16 -0500465
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200466 list_for_each_entry(pos, pattrs, node)
467 if (pos->attr.type == PERF_TYPE_TRACEPOINT)
Tom Zanussidb620b12010-05-04 22:20:16 -0500468 return true;
469
470 return false;
Tom Zanussi63e0c772010-05-03 00:14:48 -0500471}
472
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900473static int tracing_data_header(void)
Steven Rostedt520509432009-08-17 16:18:05 +0200474{
Jiri Olsa29208e52011-10-20 15:59:43 +0200475 char buf[20];
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900476 ssize_t size;
Arnaldo Carvalho de Meloe2561362009-11-21 14:31:26 -0200477
Jiri Olsa29208e52011-10-20 15:59:43 +0200478 /* just guessing this is someone's birthday.. ;) */
Steven Rostedt520509432009-08-17 16:18:05 +0200479 buf[0] = 23;
480 buf[1] = 8;
481 buf[2] = 68;
482 memcpy(buf + 3, "tracing", 7);
483
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900484 if (write(output_fd, buf, 10) != 10)
485 return -1;
Steven Rostedt520509432009-08-17 16:18:05 +0200486
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900487 size = strlen(VERSION) + 1;
488 if (write(output_fd, VERSION, size) != size)
489 return -1;
Steven Rostedt520509432009-08-17 16:18:05 +0200490
491 /* save endian */
492 if (bigendian())
493 buf[0] = 1;
494 else
495 buf[0] = 0;
496
Steven Rostedtaaf045f2012-04-06 00:47:56 +0200497 read_trace_init(buf[0], buf[0]);
498
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900499 if (write(output_fd, buf, 1) != 1)
500 return -1;
Steven Rostedt520509432009-08-17 16:18:05 +0200501
502 /* save size of long */
503 buf[0] = sizeof(long);
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900504 if (write(output_fd, buf, 1) != 1)
505 return -1;
Steven Rostedt520509432009-08-17 16:18:05 +0200506
507 /* save page_size */
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900508 if (write(output_fd, &page_size, 4) != 4)
509 return -1;
510
511 return 0;
Jiri Olsa29208e52011-10-20 15:59:43 +0200512}
Steven Rostedt520509432009-08-17 16:18:05 +0200513
Jiri Olsa29208e52011-10-20 15:59:43 +0200514struct tracing_data *tracing_data_get(struct list_head *pattrs,
515 int fd, bool temp)
516{
517 struct tracepoint_path *tps;
518 struct tracing_data *tdata;
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900519 int err;
Jiri Olsa29208e52011-10-20 15:59:43 +0200520
521 output_fd = fd;
522
523 tps = get_tracepoints_path(pattrs);
524 if (!tps)
525 return NULL;
526
Namhyung Kim5a6fd272013-03-21 16:18:45 +0900527 tdata = malloc(sizeof(*tdata));
528 if (!tdata)
529 return NULL;
530
Jiri Olsa29208e52011-10-20 15:59:43 +0200531 tdata->temp = temp;
532 tdata->size = 0;
533
534 if (temp) {
535 int temp_fd;
536
537 snprintf(tdata->temp_file, sizeof(tdata->temp_file),
538 "/tmp/perf-XXXXXX");
539 if (!mkstemp(tdata->temp_file))
540 die("Can't make temp file");
541
542 temp_fd = open(tdata->temp_file, O_RDWR);
543 if (temp_fd < 0)
544 die("Can't read '%s'", tdata->temp_file);
545
546 /*
547 * Set the temp file the default output, so all the
548 * tracing data are stored into it.
549 */
550 output_fd = temp_fd;
551 }
552
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900553 err = tracing_data_header();
554 if (err)
555 goto out;
556 err = read_header_files();
557 if (err)
558 goto out;
559 err = read_ftrace_files(tps);
560 if (err)
561 goto out;
562 err = read_event_files(tps);
563 if (err)
564 goto out;
565 err = read_proc_kallsyms();
566 if (err)
567 goto out;
568 err = read_ftrace_printk();
Arnaldo Carvalho de Meloe2561362009-11-21 14:31:26 -0200569
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900570out:
Jiri Olsa29208e52011-10-20 15:59:43 +0200571 /*
572 * All tracing data are stored by now, we can restore
573 * the default output file in case we used temp file.
574 */
575 if (temp) {
576 tdata->size = lseek(output_fd, 0, SEEK_CUR);
577 close(output_fd);
578 output_fd = fd;
579 }
580
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900581 if (err) {
582 free(tdata);
583 tdata = NULL;
584 }
585
Jiri Olsa29208e52011-10-20 15:59:43 +0200586 put_tracepoints_path(tps);
587 return tdata;
Steven Rostedt520509432009-08-17 16:18:05 +0200588}
Tom Zanussi92155452010-04-01 23:59:21 -0500589
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900590int tracing_data_put(struct tracing_data *tdata)
Tom Zanussi92155452010-04-01 23:59:21 -0500591{
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900592 int err = 0;
593
Jiri Olsa29208e52011-10-20 15:59:43 +0200594 if (tdata->temp) {
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900595 err = record_file(tdata->temp_file, 0);
Jiri Olsa29208e52011-10-20 15:59:43 +0200596 unlink(tdata->temp_file);
597 }
Tom Zanussi92155452010-04-01 23:59:21 -0500598
Jiri Olsa29208e52011-10-20 15:59:43 +0200599 free(tdata);
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900600 return err;
Jiri Olsa29208e52011-10-20 15:59:43 +0200601}
Tom Zanussi92155452010-04-01 23:59:21 -0500602
Jiri Olsa29208e52011-10-20 15:59:43 +0200603int read_tracing_data(int fd, struct list_head *pattrs)
604{
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900605 int err;
Jiri Olsa29208e52011-10-20 15:59:43 +0200606 struct tracing_data *tdata;
Tom Zanussi92155452010-04-01 23:59:21 -0500607
Jiri Olsa29208e52011-10-20 15:59:43 +0200608 /*
609 * We work over the real file, so we can write data
610 * directly, no temp file is needed.
611 */
612 tdata = tracing_data_get(pattrs, fd, false);
613 if (!tdata)
614 return -ENOMEM;
615
Namhyung Kim8755d5e2013-03-21 16:18:46 +0900616 err = tracing_data_put(tdata);
617 return err;
Tom Zanussi92155452010-04-01 23:59:21 -0500618}