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

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

Version: ~ [ linux-5.2-rc5 ] ~ [ linux-5.1.12 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.53 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.128 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.182 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.182 ] ~ [ 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 #include "util.h"
 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 <errno.h>
 35 #include <stdbool.h>
 36 #include <linux/list.h>
 37 #include <linux/kernel.h>
 38 
 39 #include "../perf.h"
 40 #include "trace-event.h"
 41 #include <lk/debugfs.h>
 42 #include "evsel.h"
 43 
 44 #define VERSION "0.5"
 45 
 46 static int output_fd;
 47 
 48 
 49 int bigendian(void)
 50 {
 51         unsigned char str[] = { 0x1, 0x2, 0x3, 0x4, 0x0, 0x0, 0x0, 0x0};
 52         unsigned int *ptr;
 53 
 54         ptr = (unsigned int *)(void *)str;
 55         return *ptr == 0x01020304;
 56 }
 57 
 58 /* unfortunately, you can not stat debugfs or proc files for size */
 59 static int record_file(const char *file, ssize_t hdr_sz)
 60 {
 61         unsigned long long size = 0;
 62         char buf[BUFSIZ], *sizep;
 63         off_t hdr_pos = lseek(output_fd, 0, SEEK_CUR);
 64         int r, fd;
 65         int err = -EIO;
 66 
 67         fd = open(file, O_RDONLY);
 68         if (fd < 0) {
 69                 pr_debug("Can't read '%s'", file);
 70                 return -errno;
 71         }
 72 
 73         /* put in zeros for file size, then fill true size later */
 74         if (hdr_sz) {
 75                 if (write(output_fd, &size, hdr_sz) != hdr_sz)
 76                         goto out;
 77         }
 78 
 79         do {
 80                 r = read(fd, buf, BUFSIZ);
 81                 if (r > 0) {
 82                         size += r;
 83                         if (write(output_fd, buf, r) != r)
 84                                 goto out;
 85                 }
 86         } while (r > 0);
 87 
 88         /* ugh, handle big-endian hdr_size == 4 */
 89         sizep = (char*)&size;
 90         if (bigendian())
 91                 sizep += sizeof(u64) - hdr_sz;
 92 
 93         if (hdr_sz && pwrite(output_fd, sizep, hdr_sz, hdr_pos) < 0) {
 94                 pr_debug("writing file size failed\n");
 95                 goto out;
 96         }
 97 
 98         err = 0;
 99 out:
100         close(fd);
101         return err;
102 }
103 
104 static int record_header_files(void)
105 {
106         char *path;
107         struct stat st;
108         int err = -EIO;
109 
110         path = get_tracing_file("events/header_page");
111         if (!path) {
112                 pr_debug("can't get tracing/events/header_page");
113                 return -ENOMEM;
114         }
115 
116         if (stat(path, &st) < 0) {
117                 pr_debug("can't read '%s'", path);
118                 goto out;
119         }
120 
121         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 
131         put_tracing_file(path);
132 
133         path = get_tracing_file("events/header_event");
134         if (!path) {
135                 pr_debug("can't get tracing/events/header_event");
136                 err = -ENOMEM;
137                 goto out;
138         }
139 
140         if (stat(path, &st) < 0) {
141                 pr_debug("can't read '%s'", path);
142                 goto out;
143         }
144 
145         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;
156 out:
157         put_tracing_file(path);
158         return err;
159 }
160 
161 static 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 
172 static int copy_event_system(const char *sys, struct tracepoint_path *tps)
173 {
174         struct dirent *dent;
175         struct stat st;
176         char *format;
177         DIR *dir;
178         int count = 0;
179         int ret;
180         int err;
181 
182         dir = opendir(sys);
183         if (!dir) {
184                 pr_debug("can't read directory '%s'", sys);
185                 return -errno;
186         }
187 
188         while ((dent = readdir(dir))) {
189                 if (dent->d_type != DT_DIR ||
190                     strcmp(dent->d_name, ".") == 0 ||
191                     strcmp(dent->d_name, "..") == 0 ||
192                     !name_in_tp_list(dent->d_name, tps))
193                         continue;
194                 format = malloc(strlen(sys) + strlen(dent->d_name) + 10);
195                 if (!format) {
196                         err = -ENOMEM;
197                         goto out;
198                 }
199                 sprintf(format, "%s/%s/format", sys, dent->d_name);
200                 ret = stat(format, &st);
201                 free(format);
202                 if (ret < 0)
203                         continue;
204                 count++;
205         }
206 
207         if (write(output_fd, &count, 4) != 4) {
208                 err = -EIO;
209                 pr_debug("can't write count\n");
210                 goto out;
211         }
212 
213         rewinddir(dir);
214         while ((dent = readdir(dir))) {
215                 if (dent->d_type != DT_DIR ||
216                     strcmp(dent->d_name, ".") == 0 ||
217                     strcmp(dent->d_name, "..") == 0 ||
218                     !name_in_tp_list(dent->d_name, tps))
219                         continue;
220                 format = malloc(strlen(sys) + strlen(dent->d_name) + 10);
221                 if (!format) {
222                         err = -ENOMEM;
223                         goto out;
224                 }
225                 sprintf(format, "%s/%s/format", sys, dent->d_name);
226                 ret = stat(format, &st);
227 
228                 if (ret >= 0) {
229                         err = record_file(format, 8);
230                         if (err) {
231                                 free(format);
232                                 goto out;
233                         }
234                 }
235                 free(format);
236         }
237         err = 0;
238 out:
239         closedir(dir);
240         return err;
241 }
242 
243 static int record_ftrace_files(struct tracepoint_path *tps)
244 {
245         char *path;
246         int ret;
247 
248         path = get_tracing_file("events/ftrace");
249         if (!path) {
250                 pr_debug("can't get tracing/events/ftrace");
251                 return -ENOMEM;
252         }
253 
254         ret = copy_event_system(path, tps);
255 
256         put_tracing_file(path);
257 
258         return ret;
259 }
260 
261 static bool system_in_tp_list(char *sys, struct tracepoint_path *tps)
262 {
263         while (tps) {
264                 if (!strcmp(sys, tps->system))
265                         return true;
266                 tps = tps->next;
267         }
268 
269         return false;
270 }
271 
272 static int record_event_files(struct tracepoint_path *tps)
273 {
274         struct dirent *dent;
275         struct stat st;
276         char *path;
277         char *sys;
278         DIR *dir;
279         int count = 0;
280         int ret;
281         int err;
282 
283         path = get_tracing_file("events");
284         if (!path) {
285                 pr_debug("can't get tracing/events");
286                 return -ENOMEM;
287         }
288 
289         dir = opendir(path);
290         if (!dir) {
291                 err = -errno;
292                 pr_debug("can't read directory '%s'", path);
293                 goto out;
294         }
295 
296         while ((dent = readdir(dir))) {
297                 if (dent->d_type != DT_DIR ||
298                     strcmp(dent->d_name, ".") == 0 ||
299                     strcmp(dent->d_name, "..") == 0 ||
300                     strcmp(dent->d_name, "ftrace") == 0 ||
301                     !system_in_tp_list(dent->d_name, tps))
302                         continue;
303                 count++;
304         }
305 
306         if (write(output_fd, &count, 4) != 4) {
307                 err = -EIO;
308                 pr_debug("can't write count\n");
309                 goto out;
310         }
311 
312         rewinddir(dir);
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                     strcmp(dent->d_name, "ftrace") == 0 ||
318                     !system_in_tp_list(dent->d_name, tps))
319                         continue;
320                 sys = malloc(strlen(path) + strlen(dent->d_name) + 2);
321                 if (!sys) {
322                         err = -ENOMEM;
323                         goto out;
324                 }
325                 sprintf(sys, "%s/%s", path, dent->d_name);
326                 ret = stat(sys, &st);
327                 if (ret >= 0) {
328                         ssize_t size = strlen(dent->d_name) + 1;
329 
330                         if (write(output_fd, dent->d_name, size) != size ||
331                             copy_event_system(sys, tps) < 0) {
332                                 err = -EIO;
333                                 free(sys);
334                                 goto out;
335                         }
336                 }
337                 free(sys);
338         }
339         err = 0;
340 out:
341         closedir(dir);
342         put_tracing_file(path);
343 
344         return err;
345 }
346 
347 static int record_proc_kallsyms(void)
348 {
349         unsigned int size;
350         const char *path = "/proc/kallsyms";
351         struct stat st;
352         int ret, err = 0;
353 
354         ret = stat(path, &st);
355         if (ret < 0) {
356                 /* not found */
357                 size = 0;
358                 if (write(output_fd, &size, 4) != 4)
359                         err = -EIO;
360                 return err;
361         }
362         return record_file(path, 4);
363 }
364 
365 static int record_ftrace_printk(void)
366 {
367         unsigned int size;
368         char *path;
369         struct stat st;
370         int ret, err = 0;
371 
372         path = get_tracing_file("printk_formats");
373         if (!path) {
374                 pr_debug("can't get tracing/printk_formats");
375                 return -ENOMEM;
376         }
377 
378         ret = stat(path, &st);
379         if (ret < 0) {
380                 /* not found */
381                 size = 0;
382                 if (write(output_fd, &size, 4) != 4)
383                         err = -EIO;
384                 goto out;
385         }
386         err = record_file(path, 4);
387 
388 out:
389         put_tracing_file(path);
390         return err;
391 }
392 
393 static void
394 put_tracepoints_path(struct tracepoint_path *tps)
395 {
396         while (tps) {
397                 struct tracepoint_path *t = tps;
398 
399                 tps = tps->next;
400                 free(t->name);
401                 free(t->system);
402                 free(t);
403         }
404 }
405 
406 static struct tracepoint_path *
407 get_tracepoints_path(struct list_head *pattrs)
408 {
409         struct tracepoint_path path, *ppath = &path;
410         struct perf_evsel *pos;
411         int nr_tracepoints = 0;
412 
413         list_for_each_entry(pos, pattrs, node) {
414                 if (pos->attr.type != PERF_TYPE_TRACEPOINT)
415                         continue;
416                 ++nr_tracepoints;
417 
418                 if (pos->name) {
419                         ppath->next = tracepoint_name_to_path(pos->name);
420                         if (ppath->next)
421                                 goto next;
422 
423                         if (strchr(pos->name, ':') == NULL)
424                                 goto try_id;
425 
426                         goto error;
427                 }
428 
429 try_id:
430                 ppath->next = tracepoint_id_to_path(pos->attr.config);
431                 if (!ppath->next) {
432 error:
433                         pr_debug("No memory to alloc tracepoints list\n");
434                         put_tracepoints_path(&path);
435                         return NULL;
436                 }
437 next:
438                 ppath = ppath->next;
439         }
440 
441         return nr_tracepoints > 0 ? path.next : NULL;
442 }
443 
444 bool have_tracepoints(struct list_head *pattrs)
445 {
446         struct perf_evsel *pos;
447 
448         list_for_each_entry(pos, pattrs, node)
449                 if (pos->attr.type == PERF_TYPE_TRACEPOINT)
450                         return true;
451 
452         return false;
453 }
454 
455 static int tracing_data_header(void)
456 {
457         char buf[20];
458         ssize_t size;
459 
460         /* just guessing this is someone's birthday.. ;) */
461         buf[0] = 23;
462         buf[1] = 8;
463         buf[2] = 68;
464         memcpy(buf + 3, "tracing", 7);
465 
466         if (write(output_fd, buf, 10) != 10)
467                 return -1;
468 
469         size = strlen(VERSION) + 1;
470         if (write(output_fd, VERSION, size) != size)
471                 return -1;
472 
473         /* save endian */
474         if (bigendian())
475                 buf[0] = 1;
476         else
477                 buf[0] = 0;
478 
479         if (write(output_fd, buf, 1) != 1)
480                 return -1;
481 
482         /* save size of long */
483         buf[0] = sizeof(long);
484         if (write(output_fd, buf, 1) != 1)
485                 return -1;
486 
487         /* save page_size */
488         if (write(output_fd, &page_size, 4) != 4)
489                 return -1;
490 
491         return 0;
492 }
493 
494 struct tracing_data *tracing_data_get(struct list_head *pattrs,
495                                       int fd, bool temp)
496 {
497         struct tracepoint_path *tps;
498         struct tracing_data *tdata;
499         int err;
500 
501         output_fd = fd;
502 
503         tps = get_tracepoints_path(pattrs);
504         if (!tps)
505                 return NULL;
506 
507         tdata = malloc(sizeof(*tdata));
508         if (!tdata)
509                 return NULL;
510 
511         tdata->temp = temp;
512         tdata->size = 0;
513 
514         if (temp) {
515                 int temp_fd;
516 
517                 snprintf(tdata->temp_file, sizeof(tdata->temp_file),
518                          "/tmp/perf-XXXXXX");
519                 if (!mkstemp(tdata->temp_file)) {
520                         pr_debug("Can't make temp file");
521                         return NULL;
522                 }
523 
524                 temp_fd = open(tdata->temp_file, O_RDWR);
525                 if (temp_fd < 0) {
526                         pr_debug("Can't read '%s'", tdata->temp_file);
527                         return NULL;
528                 }
529 
530                 /*
531                  * Set the temp file the default output, so all the
532                  * tracing data are stored into it.
533                  */
534                 output_fd = temp_fd;
535         }
536 
537         err = tracing_data_header();
538         if (err)
539                 goto out;
540         err = record_header_files();
541         if (err)
542                 goto out;
543         err = record_ftrace_files(tps);
544         if (err)
545                 goto out;
546         err = record_event_files(tps);
547         if (err)
548                 goto out;
549         err = record_proc_kallsyms();
550         if (err)
551                 goto out;
552         err = record_ftrace_printk();
553 
554 out:
555         /*
556          * All tracing data are stored by now, we can restore
557          * the default output file in case we used temp file.
558          */
559         if (temp) {
560                 tdata->size = lseek(output_fd, 0, SEEK_CUR);
561                 close(output_fd);
562                 output_fd = fd;
563         }
564 
565         if (err) {
566                 free(tdata);
567                 tdata = NULL;
568         }
569 
570         put_tracepoints_path(tps);
571         return tdata;
572 }
573 
574 int tracing_data_put(struct tracing_data *tdata)
575 {
576         int err = 0;
577 
578         if (tdata->temp) {
579                 err = record_file(tdata->temp_file, 0);
580                 unlink(tdata->temp_file);
581         }
582 
583         free(tdata);
584         return err;
585 }
586 
587 int read_tracing_data(int fd, struct list_head *pattrs)
588 {
589         int err;
590         struct tracing_data *tdata;
591 
592         /*
593          * We work over the real file, so we can write data
594          * directly, no temp file is needed.
595          */
596         tdata = tracing_data_get(pattrs, fd, false);
597         if (!tdata)
598                 return -ENOMEM;
599 
600         err = tracing_data_put(tdata);
601         return err;
602 }
603 

~ [ 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