~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/perf/util/trace-event-info.c

Version: ~ [ linux-5.2-rc4 ] ~ [ linux-5.1.9 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.50 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.125 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.181 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.181 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.68 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.39.4 ] ~ [ linux-2.6.38.8 ] ~ [ linux-2.6.37.6 ] ~ [ linux-2.6.36.4 ] ~ [ linux-2.6.35.14 ] ~ [ linux-2.6.34.15 ] ~ [ linux-2.6.33.20 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  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  */
 21 #define _GNU_SOURCE
 22 #include <dirent.h>
 23 #include <mntent.h>
 24 #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>
 34 #include <ctype.h>
 35 #include <errno.h>
 36 #include <stdbool.h>
 37 #include <linux/list.h>
 38 #include <linux/kernel.h>
 39 
 40 #include "../perf.h"
 41 #include "trace-event.h"
 42 #include "debugfs.h"
 43 #include "evsel.h"
 44 
 45 #define VERSION "0.5"
 46 
 47 #define _STR(x) #x
 48 #define STR(x) _STR(x)
 49 #define MAX_PATH 256
 50 
 51 #define TRACE_CTRL      "tracing_on"
 52 #define TRACE           "trace"
 53 #define AVAILABLE       "available_tracers"
 54 #define CURRENT         "current_tracer"
 55 #define ITER_CTRL       "trace_options"
 56 #define MAX_LATENCY     "tracing_max_latency"
 57 
 58 unsigned int page_size;
 59 
 60 static const char *output_file = "trace.info";
 61 static int output_fd;
 62 
 63 struct event_list {
 64         struct event_list *next;
 65         const char *event;
 66 };
 67 
 68 struct events {
 69         struct events *sibling;
 70         struct events *children;
 71         struct events *next;
 72         char *name;
 73 };
 74 
 75 
 76 
 77 static void die(const char *fmt, ...)
 78 {
 79         va_list ap;
 80         int ret = errno;
 81 
 82         if (errno)
 83                 perror("trace-cmd");
 84         else
 85                 ret = -1;
 86 
 87         va_start(ap, fmt);
 88         fprintf(stderr, "  ");
 89         vfprintf(stderr, fmt, ap);
 90         va_end(ap);
 91 
 92         fprintf(stderr, "\n");
 93         exit(ret);
 94 }
 95 
 96 void *malloc_or_die(unsigned int size)
 97 {
 98         void *data;
 99 
100         data = malloc(size);
101         if (!data)
102                 die("malloc");
103         return data;
104 }
105 
106 static const char *find_debugfs(void)
107 {
108         const char *path = debugfs_mount(NULL);
109 
110         if (!path)
111                 die("Your kernel not support debugfs filesystem");
112 
113         return path;
114 }
115 
116 /*
117  * Finds the path to the debugfs/tracing
118  * Allocates the string and stores it.
119  */
120 static const char *find_tracing_dir(void)
121 {
122         static char *tracing;
123         static int tracing_found;
124         const char *debugfs;
125 
126         if (tracing_found)
127                 return tracing;
128 
129         debugfs = find_debugfs();
130 
131         tracing = malloc_or_die(strlen(debugfs) + 9);
132 
133         sprintf(tracing, "%s/tracing", debugfs);
134 
135         tracing_found = 1;
136         return tracing;
137 }
138 
139 static char *get_tracing_file(const char *name)
140 {
141         const char *tracing;
142         char *file;
143 
144         tracing = find_tracing_dir();
145         if (!tracing)
146                 return NULL;
147 
148         file = malloc_or_die(strlen(tracing) + strlen(name) + 2);
149 
150         sprintf(file, "%s/%s", tracing, name);
151         return file;
152 }
153 
154 static void put_tracing_file(char *file)
155 {
156         free(file);
157 }
158 
159 static ssize_t calc_data_size;
160 
161 static ssize_t write_or_die(const void *buf, size_t len)
162 {
163         int ret;
164 
165         if (calc_data_size) {
166                 calc_data_size += len;
167                 return len;
168         }
169 
170         ret = write(output_fd, buf, len);
171         if (ret < 0)
172                 die("writing to '%s'", output_file);
173 
174         return ret;
175 }
176 
177 int bigendian(void)
178 {
179         unsigned char str[] = { 0x1, 0x2, 0x3, 0x4, 0x0, 0x0, 0x0, 0x0};
180         unsigned int *ptr;
181 
182         ptr = (unsigned int *)(void *)str;
183         return *ptr == 0x01020304;
184 }
185 
186 static unsigned long long copy_file_fd(int fd)
187 {
188         unsigned long long size = 0;
189         char buf[BUFSIZ];
190         int r;
191 
192         do {
193                 r = read(fd, buf, BUFSIZ);
194                 if (r > 0) {
195                         size += r;
196                         write_or_die(buf, r);
197                 }
198         } while (r > 0);
199 
200         return size;
201 }
202 
203 static unsigned long long copy_file(const char *file)
204 {
205         unsigned long long size = 0;
206         int fd;
207 
208         fd = open(file, O_RDONLY);
209         if (fd < 0)
210                 die("Can't read '%s'", file);
211         size = copy_file_fd(fd);
212         close(fd);
213 
214         return size;
215 }
216 
217 static unsigned long get_size_fd(int fd)
218 {
219         unsigned long long size = 0;
220         char buf[BUFSIZ];
221         int r;
222 
223         do {
224                 r = read(fd, buf, BUFSIZ);
225                 if (r > 0)
226                         size += r;
227         } while (r > 0);
228 
229         lseek(fd, 0, SEEK_SET);
230 
231         return size;
232 }
233 
234 static unsigned long get_size(const char *file)
235 {
236         unsigned long long size = 0;
237         int fd;
238 
239         fd = open(file, O_RDONLY);
240         if (fd < 0)
241                 die("Can't read '%s'", file);
242         size = get_size_fd(fd);
243         close(fd);
244 
245         return size;
246 }
247 
248 static void read_header_files(void)
249 {
250         unsigned long long size, check_size;
251         char *path;
252         int fd;
253 
254         path = get_tracing_file("events/header_page");
255         fd = open(path, O_RDONLY);
256         if (fd < 0)
257                 die("can't read '%s'", path);
258 
259         /* unfortunately, you can not stat debugfs files for size */
260         size = get_size_fd(fd);
261 
262         write_or_die("header_page", 12);
263         write_or_die(&size, 8);
264         check_size = copy_file_fd(fd);
265         close(fd);
266 
267         if (size != check_size)
268                 die("wrong size for '%s' size=%lld read=%lld",
269                     path, size, check_size);
270         put_tracing_file(path);
271 
272         path = get_tracing_file("events/header_event");
273         fd = open(path, O_RDONLY);
274         if (fd < 0)
275                 die("can't read '%s'", path);
276 
277         size = get_size_fd(fd);
278 
279         write_or_die("header_event", 13);
280         write_or_die(&size, 8);
281         check_size = copy_file_fd(fd);
282         if (size != check_size)
283                 die("wrong size for '%s'", path);
284         put_tracing_file(path);
285         close(fd);
286 }
287 
288 static bool name_in_tp_list(char *sys, struct tracepoint_path *tps)
289 {
290         while (tps) {
291                 if (!strcmp(sys, tps->name))
292                         return true;
293                 tps = tps->next;
294         }
295 
296         return false;
297 }
298 
299 static void copy_event_system(const char *sys, struct tracepoint_path *tps)
300 {
301         unsigned long long size, check_size;
302         struct dirent *dent;
303         struct stat st;
304         char *format;
305         DIR *dir;
306         int count = 0;
307         int ret;
308 
309         dir = opendir(sys);
310         if (!dir)
311                 die("can't read directory '%s'", sys);
312 
313         while ((dent = readdir(dir))) {
314                 if (dent->d_type != DT_DIR ||
315                     strcmp(dent->d_name, ".") == 0 ||
316                     strcmp(dent->d_name, "..") == 0 ||
317                     !name_in_tp_list(dent->d_name, tps))
318                         continue;
319                 format = malloc_or_die(strlen(sys) + strlen(dent->d_name) + 10);
320                 sprintf(format, "%s/%s/format", sys, dent->d_name);
321                 ret = stat(format, &st);
322                 free(format);
323                 if (ret < 0)
324                         continue;
325                 count++;
326         }
327 
328         write_or_die(&count, 4);
329 
330         rewinddir(dir);
331         while ((dent = readdir(dir))) {
332                 if (dent->d_type != DT_DIR ||
333                     strcmp(dent->d_name, ".") == 0 ||
334                     strcmp(dent->d_name, "..") == 0 ||
335                     !name_in_tp_list(dent->d_name, tps))
336                         continue;
337                 format = malloc_or_die(strlen(sys) + strlen(dent->d_name) + 10);
338                 sprintf(format, "%s/%s/format", sys, dent->d_name);
339                 ret = stat(format, &st);
340 
341                 if (ret >= 0) {
342                         /* unfortunately, you can not stat debugfs files for size */
343                         size = get_size(format);
344                         write_or_die(&size, 8);
345                         check_size = copy_file(format);
346                         if (size != check_size)
347                                 die("error in size of file '%s'", format);
348                 }
349 
350                 free(format);
351         }
352         closedir(dir);
353 }
354 
355 static void read_ftrace_files(struct tracepoint_path *tps)
356 {
357         char *path;
358 
359         path = get_tracing_file("events/ftrace");
360 
361         copy_event_system(path, tps);
362 
363         put_tracing_file(path);
364 }
365 
366 static bool system_in_tp_list(char *sys, struct tracepoint_path *tps)
367 {
368         while (tps) {
369                 if (!strcmp(sys, tps->system))
370                         return true;
371                 tps = tps->next;
372         }
373 
374         return false;
375 }
376 
377 static void read_event_files(struct tracepoint_path *tps)
378 {
379         struct dirent *dent;
380         struct stat st;
381         char *path;
382         char *sys;
383         DIR *dir;
384         int count = 0;
385         int ret;
386 
387         path = get_tracing_file("events");
388 
389         dir = opendir(path);
390         if (!dir)
391                 die("can't read directory '%s'", path);
392 
393         while ((dent = readdir(dir))) {
394                 if (dent->d_type != DT_DIR ||
395                     strcmp(dent->d_name, ".") == 0 ||
396                     strcmp(dent->d_name, "..") == 0 ||
397                     strcmp(dent->d_name, "ftrace") == 0 ||
398                     !system_in_tp_list(dent->d_name, tps))
399                         continue;
400                 count++;
401         }
402 
403         write_or_die(&count, 4);
404 
405         rewinddir(dir);
406         while ((dent = readdir(dir))) {
407                 if (dent->d_type != DT_DIR ||
408                     strcmp(dent->d_name, ".") == 0 ||
409                     strcmp(dent->d_name, "..") == 0 ||
410                     strcmp(dent->d_name, "ftrace") == 0 ||
411                     !system_in_tp_list(dent->d_name, tps))
412                         continue;
413                 sys = malloc_or_die(strlen(path) + strlen(dent->d_name) + 2);
414                 sprintf(sys, "%s/%s", path, dent->d_name);
415                 ret = stat(sys, &st);
416                 if (ret >= 0) {
417                         write_or_die(dent->d_name, strlen(dent->d_name) + 1);
418                         copy_event_system(sys, tps);
419                 }
420                 free(sys);
421         }
422 
423         closedir(dir);
424         put_tracing_file(path);
425 }
426 
427 static void read_proc_kallsyms(void)
428 {
429         unsigned int size, check_size;
430         const char *path = "/proc/kallsyms";
431         struct stat st;
432         int ret;
433 
434         ret = stat(path, &st);
435         if (ret < 0) {
436                 /* not found */
437                 size = 0;
438                 write_or_die(&size, 4);
439                 return;
440         }
441         size = get_size(path);
442         write_or_die(&size, 4);
443         check_size = copy_file(path);
444         if (size != check_size)
445                 die("error in size of file '%s'", path);
446 
447 }
448 
449 static void read_ftrace_printk(void)
450 {
451         unsigned int size, check_size;
452         char *path;
453         struct stat st;
454         int ret;
455 
456         path = get_tracing_file("printk_formats");
457         ret = stat(path, &st);
458         if (ret < 0) {
459                 /* not found */
460                 size = 0;
461                 write_or_die(&size, 4);
462                 goto out;
463         }
464         size = get_size(path);
465         write_or_die(&size, 4);
466         check_size = copy_file(path);
467         if (size != check_size)
468                 die("error in size of file '%s'", path);
469 out:
470         put_tracing_file(path);
471 }
472 
473 static struct tracepoint_path *
474 get_tracepoints_path(struct list_head *pattrs)
475 {
476         struct tracepoint_path path, *ppath = &path;
477         struct perf_evsel *pos;
478         int nr_tracepoints = 0;
479 
480         list_for_each_entry(pos, pattrs, node) {
481                 if (pos->attr.type != PERF_TYPE_TRACEPOINT)
482                         continue;
483                 ++nr_tracepoints;
484                 ppath->next = tracepoint_id_to_path(pos->attr.config);
485                 if (!ppath->next)
486                         die("%s\n", "No memory to alloc tracepoints list");
487                 ppath = ppath->next;
488         }
489 
490         return nr_tracepoints > 0 ? path.next : NULL;
491 }
492 
493 bool have_tracepoints(struct list_head *pattrs)
494 {
495         struct perf_evsel *pos;
496 
497         list_for_each_entry(pos, pattrs, node)
498                 if (pos->attr.type == PERF_TYPE_TRACEPOINT)
499                         return true;
500 
501         return false;
502 }
503 
504 int read_tracing_data(int fd, struct list_head *pattrs)
505 {
506         char buf[BUFSIZ];
507         struct tracepoint_path *tps = get_tracepoints_path(pattrs);
508 
509         /*
510          * What? No tracepoints? No sense writing anything here, bail out.
511          */
512         if (tps == NULL)
513                 return -1;
514 
515         output_fd = fd;
516 
517         buf[0] = 23;
518         buf[1] = 8;
519         buf[2] = 68;
520         memcpy(buf + 3, "tracing", 7);
521 
522         write_or_die(buf, 10);
523 
524         write_or_die(VERSION, strlen(VERSION) + 1);
525 
526         /* save endian */
527         if (bigendian())
528                 buf[0] = 1;
529         else
530                 buf[0] = 0;
531 
532         write_or_die(buf, 1);
533 
534         /* save size of long */
535         buf[0] = sizeof(long);
536         write_or_die(buf, 1);
537 
538         /* save page_size */
539         page_size = sysconf(_SC_PAGESIZE);
540         write_or_die(&page_size, 4);
541 
542         read_header_files();
543         read_ftrace_files(tps);
544         read_event_files(tps);
545         read_proc_kallsyms();
546         read_ftrace_printk();
547 
548         return 0;
549 }
550 
551 ssize_t read_tracing_data_size(int fd, struct list_head *pattrs)
552 {
553         ssize_t size;
554         int err = 0;
555 
556         calc_data_size = 1;
557         err = read_tracing_data(fd, pattrs);
558         size = calc_data_size - 1;
559         calc_data_size = 0;
560 
561         if (err < 0)
562                 return err;
563 
564         return size;
565 }
566 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp