]> git.karo-electronics.de Git - karo-tx-linux.git/blob - tools/perf/util/util.c
perf tools: Move term functions out of util.c
[karo-tx-linux.git] / tools / perf / util / util.c
1 #include "../perf.h"
2 #include "util.h"
3 #include "debug.h"
4 #include <api/fs/fs.h>
5 #include <sys/mman.h>
6 #include <sys/utsname.h>
7 #ifdef HAVE_BACKTRACE_SUPPORT
8 #include <execinfo.h>
9 #endif
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <errno.h>
14 #include <limits.h>
15 #include <byteswap.h>
16 #include <linux/kernel.h>
17 #include <unistd.h>
18 #include "callchain.h"
19
20 struct callchain_param  callchain_param = {
21         .mode   = CHAIN_GRAPH_ABS,
22         .min_percent = 0.5,
23         .order  = ORDER_CALLEE,
24         .key    = CCKEY_FUNCTION,
25         .value  = CCVAL_PERCENT,
26 };
27
28 /*
29  * XXX We need to find a better place for these things...
30  */
31 unsigned int page_size;
32 int cacheline_size;
33
34 bool test_attr__enabled;
35
36 bool perf_host  = true;
37 bool perf_guest = false;
38
39 void event_attr_init(struct perf_event_attr *attr)
40 {
41         if (!perf_host)
42                 attr->exclude_host  = 1;
43         if (!perf_guest)
44                 attr->exclude_guest = 1;
45         /* to capture ABI version */
46         attr->size = sizeof(*attr);
47 }
48
49 int mkdir_p(char *path, mode_t mode)
50 {
51         struct stat st;
52         int err;
53         char *d = path;
54
55         if (*d != '/')
56                 return -1;
57
58         if (stat(path, &st) == 0)
59                 return 0;
60
61         while (*++d == '/');
62
63         while ((d = strchr(d, '/'))) {
64                 *d = '\0';
65                 err = stat(path, &st) && mkdir(path, mode);
66                 *d++ = '/';
67                 if (err)
68                         return -1;
69                 while (*d == '/')
70                         ++d;
71         }
72         return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0;
73 }
74
75 int rm_rf(char *path)
76 {
77         DIR *dir;
78         int ret = 0;
79         struct dirent *d;
80         char namebuf[PATH_MAX];
81
82         dir = opendir(path);
83         if (dir == NULL)
84                 return 0;
85
86         while ((d = readdir(dir)) != NULL && !ret) {
87                 struct stat statbuf;
88
89                 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
90                         continue;
91
92                 scnprintf(namebuf, sizeof(namebuf), "%s/%s",
93                           path, d->d_name);
94
95                 ret = stat(namebuf, &statbuf);
96                 if (ret < 0) {
97                         pr_debug("stat failed: %s\n", namebuf);
98                         break;
99                 }
100
101                 if (S_ISREG(statbuf.st_mode))
102                         ret = unlink(namebuf);
103                 else if (S_ISDIR(statbuf.st_mode))
104                         ret = rm_rf(namebuf);
105                 else {
106                         pr_debug("unknown file: %s\n", namebuf);
107                         ret = -1;
108                 }
109         }
110         closedir(dir);
111
112         if (ret < 0)
113                 return ret;
114
115         return rmdir(path);
116 }
117
118 static int slow_copyfile(const char *from, const char *to)
119 {
120         int err = -1;
121         char *line = NULL;
122         size_t n;
123         FILE *from_fp = fopen(from, "r"), *to_fp;
124
125         if (from_fp == NULL)
126                 goto out;
127
128         to_fp = fopen(to, "w");
129         if (to_fp == NULL)
130                 goto out_fclose_from;
131
132         while (getline(&line, &n, from_fp) > 0)
133                 if (fputs(line, to_fp) == EOF)
134                         goto out_fclose_to;
135         err = 0;
136 out_fclose_to:
137         fclose(to_fp);
138         free(line);
139 out_fclose_from:
140         fclose(from_fp);
141 out:
142         return err;
143 }
144
145 int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size)
146 {
147         void *ptr;
148         loff_t pgoff;
149
150         pgoff = off_in & ~(page_size - 1);
151         off_in -= pgoff;
152
153         ptr = mmap(NULL, off_in + size, PROT_READ, MAP_PRIVATE, ifd, pgoff);
154         if (ptr == MAP_FAILED)
155                 return -1;
156
157         while (size) {
158                 ssize_t ret = pwrite(ofd, ptr + off_in, size, off_out);
159                 if (ret < 0 && errno == EINTR)
160                         continue;
161                 if (ret <= 0)
162                         break;
163
164                 size -= ret;
165                 off_in += ret;
166                 off_out -= ret;
167         }
168         munmap(ptr, off_in + size);
169
170         return size ? -1 : 0;
171 }
172
173 int copyfile_mode(const char *from, const char *to, mode_t mode)
174 {
175         int fromfd, tofd;
176         struct stat st;
177         int err = -1;
178         char *tmp = NULL, *ptr = NULL;
179
180         if (stat(from, &st))
181                 goto out;
182
183         /* extra 'x' at the end is to reserve space for '.' */
184         if (asprintf(&tmp, "%s.XXXXXXx", to) < 0) {
185                 tmp = NULL;
186                 goto out;
187         }
188         ptr = strrchr(tmp, '/');
189         if (!ptr)
190                 goto out;
191         ptr = memmove(ptr + 1, ptr, strlen(ptr) - 1);
192         *ptr = '.';
193
194         tofd = mkstemp(tmp);
195         if (tofd < 0)
196                 goto out;
197
198         if (fchmod(tofd, mode))
199                 goto out_close_to;
200
201         if (st.st_size == 0) { /* /proc? do it slowly... */
202                 err = slow_copyfile(from, tmp);
203                 goto out_close_to;
204         }
205
206         fromfd = open(from, O_RDONLY);
207         if (fromfd < 0)
208                 goto out_close_to;
209
210         err = copyfile_offset(fromfd, 0, tofd, 0, st.st_size);
211
212         close(fromfd);
213 out_close_to:
214         close(tofd);
215         if (!err)
216                 err = link(tmp, to);
217         unlink(tmp);
218 out:
219         free(tmp);
220         return err;
221 }
222
223 int copyfile(const char *from, const char *to)
224 {
225         return copyfile_mode(from, to, 0755);
226 }
227
228 unsigned long convert_unit(unsigned long value, char *unit)
229 {
230         *unit = ' ';
231
232         if (value > 1000) {
233                 value /= 1000;
234                 *unit = 'K';
235         }
236
237         if (value > 1000) {
238                 value /= 1000;
239                 *unit = 'M';
240         }
241
242         if (value > 1000) {
243                 value /= 1000;
244                 *unit = 'G';
245         }
246
247         return value;
248 }
249
250 static ssize_t ion(bool is_read, int fd, void *buf, size_t n)
251 {
252         void *buf_start = buf;
253         size_t left = n;
254
255         while (left) {
256                 ssize_t ret = is_read ? read(fd, buf, left) :
257                                         write(fd, buf, left);
258
259                 if (ret < 0 && errno == EINTR)
260                         continue;
261                 if (ret <= 0)
262                         return ret;
263
264                 left -= ret;
265                 buf  += ret;
266         }
267
268         BUG_ON((size_t)(buf - buf_start) != n);
269         return n;
270 }
271
272 /*
273  * Read exactly 'n' bytes or return an error.
274  */
275 ssize_t readn(int fd, void *buf, size_t n)
276 {
277         return ion(true, fd, buf, n);
278 }
279
280 /*
281  * Write exactly 'n' bytes or return an error.
282  */
283 ssize_t writen(int fd, void *buf, size_t n)
284 {
285         return ion(false, fd, buf, n);
286 }
287
288 size_t hex_width(u64 v)
289 {
290         size_t n = 1;
291
292         while ((v >>= 4))
293                 ++n;
294
295         return n;
296 }
297
298 static int hex(char ch)
299 {
300         if ((ch >= '0') && (ch <= '9'))
301                 return ch - '0';
302         if ((ch >= 'a') && (ch <= 'f'))
303                 return ch - 'a' + 10;
304         if ((ch >= 'A') && (ch <= 'F'))
305                 return ch - 'A' + 10;
306         return -1;
307 }
308
309 /*
310  * While we find nice hex chars, build a long_val.
311  * Return number of chars processed.
312  */
313 int hex2u64(const char *ptr, u64 *long_val)
314 {
315         const char *p = ptr;
316         *long_val = 0;
317
318         while (*p) {
319                 const int hex_val = hex(*p);
320
321                 if (hex_val < 0)
322                         break;
323
324                 *long_val = (*long_val << 4) | hex_val;
325                 p++;
326         }
327
328         return p - ptr;
329 }
330
331 /* Obtain a backtrace and print it to stdout. */
332 #ifdef HAVE_BACKTRACE_SUPPORT
333 void dump_stack(void)
334 {
335         void *array[16];
336         size_t size = backtrace(array, ARRAY_SIZE(array));
337         char **strings = backtrace_symbols(array, size);
338         size_t i;
339
340         printf("Obtained %zd stack frames.\n", size);
341
342         for (i = 0; i < size; i++)
343                 printf("%s\n", strings[i]);
344
345         free(strings);
346 }
347 #else
348 void dump_stack(void) {}
349 #endif
350
351 void sighandler_dump_stack(int sig)
352 {
353         psignal(sig, "perf");
354         dump_stack();
355         exit(sig);
356 }
357
358 int parse_nsec_time(const char *str, u64 *ptime)
359 {
360         u64 time_sec, time_nsec;
361         char *end;
362
363         time_sec = strtoul(str, &end, 10);
364         if (*end != '.' && *end != '\0')
365                 return -1;
366
367         if (*end == '.') {
368                 int i;
369                 char nsec_buf[10];
370
371                 if (strlen(++end) > 9)
372                         return -1;
373
374                 strncpy(nsec_buf, end, 9);
375                 nsec_buf[9] = '\0';
376
377                 /* make it nsec precision */
378                 for (i = strlen(nsec_buf); i < 9; i++)
379                         nsec_buf[i] = '0';
380
381                 time_nsec = strtoul(nsec_buf, &end, 10);
382                 if (*end != '\0')
383                         return -1;
384         } else
385                 time_nsec = 0;
386
387         *ptime = time_sec * NSEC_PER_SEC + time_nsec;
388         return 0;
389 }
390
391 unsigned long parse_tag_value(const char *str, struct parse_tag *tags)
392 {
393         struct parse_tag *i = tags;
394
395         while (i->tag) {
396                 char *s;
397
398                 s = strchr(str, i->tag);
399                 if (s) {
400                         unsigned long int value;
401                         char *endptr;
402
403                         value = strtoul(str, &endptr, 10);
404                         if (s != endptr)
405                                 break;
406
407                         if (value > ULONG_MAX / i->mult)
408                                 break;
409                         value *= i->mult;
410                         return value;
411                 }
412                 i++;
413         }
414
415         return (unsigned long) -1;
416 }
417
418 int get_stack_size(const char *str, unsigned long *_size)
419 {
420         char *endptr;
421         unsigned long size;
422         unsigned long max_size = round_down(USHRT_MAX, sizeof(u64));
423
424         size = strtoul(str, &endptr, 0);
425
426         do {
427                 if (*endptr)
428                         break;
429
430                 size = round_up(size, sizeof(u64));
431                 if (!size || size > max_size)
432                         break;
433
434                 *_size = size;
435                 return 0;
436
437         } while (0);
438
439         pr_err("callchain: Incorrect stack dump size (max %ld): %s\n",
440                max_size, str);
441         return -1;
442 }
443
444 int parse_callchain_record(const char *arg, struct callchain_param *param)
445 {
446         char *tok, *name, *saveptr = NULL;
447         char *buf;
448         int ret = -1;
449
450         /* We need buffer that we know we can write to. */
451         buf = malloc(strlen(arg) + 1);
452         if (!buf)
453                 return -ENOMEM;
454
455         strcpy(buf, arg);
456
457         tok = strtok_r((char *)buf, ",", &saveptr);
458         name = tok ? : (char *)buf;
459
460         do {
461                 /* Framepointer style */
462                 if (!strncmp(name, "fp", sizeof("fp"))) {
463                         if (!strtok_r(NULL, ",", &saveptr)) {
464                                 param->record_mode = CALLCHAIN_FP;
465                                 ret = 0;
466                         } else
467                                 pr_err("callchain: No more arguments "
468                                        "needed for --call-graph fp\n");
469                         break;
470
471 #ifdef HAVE_DWARF_UNWIND_SUPPORT
472                 /* Dwarf style */
473                 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
474                         const unsigned long default_stack_dump_size = 8192;
475
476                         ret = 0;
477                         param->record_mode = CALLCHAIN_DWARF;
478                         param->dump_size = default_stack_dump_size;
479
480                         tok = strtok_r(NULL, ",", &saveptr);
481                         if (tok) {
482                                 unsigned long size = 0;
483
484                                 ret = get_stack_size(tok, &size);
485                                 param->dump_size = size;
486                         }
487 #endif /* HAVE_DWARF_UNWIND_SUPPORT */
488                 } else if (!strncmp(name, "lbr", sizeof("lbr"))) {
489                         if (!strtok_r(NULL, ",", &saveptr)) {
490                                 param->record_mode = CALLCHAIN_LBR;
491                                 ret = 0;
492                         } else
493                                 pr_err("callchain: No more arguments "
494                                         "needed for --call-graph lbr\n");
495                         break;
496                 } else {
497                         pr_err("callchain: Unknown --call-graph option "
498                                "value: %s\n", arg);
499                         break;
500                 }
501
502         } while (0);
503
504         free(buf);
505         return ret;
506 }
507
508 int filename__read_str(const char *filename, char **buf, size_t *sizep)
509 {
510         size_t size = 0, alloc_size = 0;
511         void *bf = NULL, *nbf;
512         int fd, n, err = 0;
513         char sbuf[STRERR_BUFSIZE];
514
515         fd = open(filename, O_RDONLY);
516         if (fd < 0)
517                 return -errno;
518
519         do {
520                 if (size == alloc_size) {
521                         alloc_size += BUFSIZ;
522                         nbf = realloc(bf, alloc_size);
523                         if (!nbf) {
524                                 err = -ENOMEM;
525                                 break;
526                         }
527
528                         bf = nbf;
529                 }
530
531                 n = read(fd, bf + size, alloc_size - size);
532                 if (n < 0) {
533                         if (size) {
534                                 pr_warning("read failed %d: %s\n", errno,
535                                          strerror_r(errno, sbuf, sizeof(sbuf)));
536                                 err = 0;
537                         } else
538                                 err = -errno;
539
540                         break;
541                 }
542
543                 size += n;
544         } while (n > 0);
545
546         if (!err) {
547                 *sizep = size;
548                 *buf   = bf;
549         } else
550                 free(bf);
551
552         close(fd);
553         return err;
554 }
555
556 const char *get_filename_for_perf_kvm(void)
557 {
558         const char *filename;
559
560         if (perf_host && !perf_guest)
561                 filename = strdup("perf.data.host");
562         else if (!perf_host && perf_guest)
563                 filename = strdup("perf.data.guest");
564         else
565                 filename = strdup("perf.data.kvm");
566
567         return filename;
568 }
569
570 int perf_event_paranoid(void)
571 {
572         int value;
573
574         if (sysctl__read_int("kernel/perf_event_paranoid", &value))
575                 return INT_MAX;
576
577         return value;
578 }
579
580 void mem_bswap_32(void *src, int byte_size)
581 {
582         u32 *m = src;
583         while (byte_size > 0) {
584                 *m = bswap_32(*m);
585                 byte_size -= sizeof(u32);
586                 ++m;
587         }
588 }
589
590 void mem_bswap_64(void *src, int byte_size)
591 {
592         u64 *m = src;
593
594         while (byte_size > 0) {
595                 *m = bswap_64(*m);
596                 byte_size -= sizeof(u64);
597                 ++m;
598         }
599 }
600
601 bool find_process(const char *name)
602 {
603         size_t len = strlen(name);
604         DIR *dir;
605         struct dirent *d;
606         int ret = -1;
607
608         dir = opendir(procfs__mountpoint());
609         if (!dir)
610                 return false;
611
612         /* Walk through the directory. */
613         while (ret && (d = readdir(dir)) != NULL) {
614                 char path[PATH_MAX];
615                 char *data;
616                 size_t size;
617
618                 if ((d->d_type != DT_DIR) ||
619                      !strcmp(".", d->d_name) ||
620                      !strcmp("..", d->d_name))
621                         continue;
622
623                 scnprintf(path, sizeof(path), "%s/%s/comm",
624                           procfs__mountpoint(), d->d_name);
625
626                 if (filename__read_str(path, &data, &size))
627                         continue;
628
629                 ret = strncmp(name, data, len);
630                 free(data);
631         }
632
633         closedir(dir);
634         return ret ? false : true;
635 }
636
637 int
638 fetch_kernel_version(unsigned int *puint, char *str,
639                      size_t str_size)
640 {
641         struct utsname utsname;
642         int version, patchlevel, sublevel, err;
643
644         if (uname(&utsname))
645                 return -1;
646
647         if (str && str_size) {
648                 strncpy(str, utsname.release, str_size);
649                 str[str_size - 1] = '\0';
650         }
651
652         err = sscanf(utsname.release, "%d.%d.%d",
653                      &version, &patchlevel, &sublevel);
654
655         if (err != 3) {
656                 pr_debug("Unablt to get kernel version from uname '%s'\n",
657                          utsname.release);
658                 return -1;
659         }
660
661         if (puint)
662                 *puint = (version << 16) + (patchlevel << 8) + sublevel;
663         return 0;
664 }