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