xref: /openbmc/linux/tools/perf/util/util.c (revision d7a3d85e)
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_events_path[PATH_MAX + 1] = "/sys/kernel/debug/tracing/events";
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, mode_t mode)
119 {
120 	int err = -1;
121 	char *line = NULL;
122 	size_t n;
123 	FILE *from_fp = fopen(from, "r"), *to_fp;
124 	mode_t old_umask;
125 
126 	if (from_fp == NULL)
127 		goto out;
128 
129 	old_umask = umask(mode ^ 0777);
130 	to_fp = fopen(to, "w");
131 	umask(old_umask);
132 	if (to_fp == NULL)
133 		goto out_fclose_from;
134 
135 	while (getline(&line, &n, from_fp) > 0)
136 		if (fputs(line, to_fp) == EOF)
137 			goto out_fclose_to;
138 	err = 0;
139 out_fclose_to:
140 	fclose(to_fp);
141 	free(line);
142 out_fclose_from:
143 	fclose(from_fp);
144 out:
145 	return err;
146 }
147 
148 int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size)
149 {
150 	void *ptr;
151 	loff_t pgoff;
152 
153 	pgoff = off_in & ~(page_size - 1);
154 	off_in -= pgoff;
155 
156 	ptr = mmap(NULL, off_in + size, PROT_READ, MAP_PRIVATE, ifd, pgoff);
157 	if (ptr == MAP_FAILED)
158 		return -1;
159 
160 	while (size) {
161 		ssize_t ret = pwrite(ofd, ptr + off_in, size, off_out);
162 		if (ret < 0 && errno == EINTR)
163 			continue;
164 		if (ret <= 0)
165 			break;
166 
167 		size -= ret;
168 		off_in += ret;
169 		off_out -= ret;
170 	}
171 	munmap(ptr, off_in + size);
172 
173 	return size ? -1 : 0;
174 }
175 
176 int copyfile_mode(const char *from, const char *to, mode_t mode)
177 {
178 	int fromfd, tofd;
179 	struct stat st;
180 	int err = -1;
181 
182 	if (stat(from, &st))
183 		goto out;
184 
185 	if (st.st_size == 0) /* /proc? do it slowly... */
186 		return slow_copyfile(from, to, mode);
187 
188 	fromfd = open(from, O_RDONLY);
189 	if (fromfd < 0)
190 		goto out;
191 
192 	tofd = creat(to, mode);
193 	if (tofd < 0)
194 		goto out_close_from;
195 
196 	err = copyfile_offset(fromfd, 0, tofd, 0, st.st_size);
197 
198 	close(tofd);
199 	if (err)
200 		unlink(to);
201 out_close_from:
202 	close(fromfd);
203 out:
204 	return err;
205 }
206 
207 int copyfile(const char *from, const char *to)
208 {
209 	return copyfile_mode(from, to, 0755);
210 }
211 
212 unsigned long convert_unit(unsigned long value, char *unit)
213 {
214 	*unit = ' ';
215 
216 	if (value > 1000) {
217 		value /= 1000;
218 		*unit = 'K';
219 	}
220 
221 	if (value > 1000) {
222 		value /= 1000;
223 		*unit = 'M';
224 	}
225 
226 	if (value > 1000) {
227 		value /= 1000;
228 		*unit = 'G';
229 	}
230 
231 	return value;
232 }
233 
234 static ssize_t ion(bool is_read, int fd, void *buf, size_t n)
235 {
236 	void *buf_start = buf;
237 	size_t left = n;
238 
239 	while (left) {
240 		ssize_t ret = is_read ? read(fd, buf, left) :
241 					write(fd, buf, left);
242 
243 		if (ret < 0 && errno == EINTR)
244 			continue;
245 		if (ret <= 0)
246 			return ret;
247 
248 		left -= ret;
249 		buf  += ret;
250 	}
251 
252 	BUG_ON((size_t)(buf - buf_start) != n);
253 	return n;
254 }
255 
256 /*
257  * Read exactly 'n' bytes or return an error.
258  */
259 ssize_t readn(int fd, void *buf, size_t n)
260 {
261 	return ion(true, fd, buf, n);
262 }
263 
264 /*
265  * Write exactly 'n' bytes or return an error.
266  */
267 ssize_t writen(int fd, void *buf, size_t n)
268 {
269 	return ion(false, fd, buf, n);
270 }
271 
272 size_t hex_width(u64 v)
273 {
274 	size_t n = 1;
275 
276 	while ((v >>= 4))
277 		++n;
278 
279 	return n;
280 }
281 
282 static int hex(char ch)
283 {
284 	if ((ch >= '0') && (ch <= '9'))
285 		return ch - '0';
286 	if ((ch >= 'a') && (ch <= 'f'))
287 		return ch - 'a' + 10;
288 	if ((ch >= 'A') && (ch <= 'F'))
289 		return ch - 'A' + 10;
290 	return -1;
291 }
292 
293 /*
294  * While we find nice hex chars, build a long_val.
295  * Return number of chars processed.
296  */
297 int hex2u64(const char *ptr, u64 *long_val)
298 {
299 	const char *p = ptr;
300 	*long_val = 0;
301 
302 	while (*p) {
303 		const int hex_val = hex(*p);
304 
305 		if (hex_val < 0)
306 			break;
307 
308 		*long_val = (*long_val << 4) | hex_val;
309 		p++;
310 	}
311 
312 	return p - ptr;
313 }
314 
315 /* Obtain a backtrace and print it to stdout. */
316 #ifdef HAVE_BACKTRACE_SUPPORT
317 void dump_stack(void)
318 {
319 	void *array[16];
320 	size_t size = backtrace(array, ARRAY_SIZE(array));
321 	char **strings = backtrace_symbols(array, size);
322 	size_t i;
323 
324 	printf("Obtained %zd stack frames.\n", size);
325 
326 	for (i = 0; i < size; i++)
327 		printf("%s\n", strings[i]);
328 
329 	free(strings);
330 }
331 #else
332 void dump_stack(void) {}
333 #endif
334 
335 void sighandler_dump_stack(int sig)
336 {
337 	psignal(sig, "perf");
338 	dump_stack();
339 	exit(sig);
340 }
341 
342 void get_term_dimensions(struct winsize *ws)
343 {
344 	char *s = getenv("LINES");
345 
346 	if (s != NULL) {
347 		ws->ws_row = atoi(s);
348 		s = getenv("COLUMNS");
349 		if (s != NULL) {
350 			ws->ws_col = atoi(s);
351 			if (ws->ws_row && ws->ws_col)
352 				return;
353 		}
354 	}
355 #ifdef TIOCGWINSZ
356 	if (ioctl(1, TIOCGWINSZ, ws) == 0 &&
357 	    ws->ws_row && ws->ws_col)
358 		return;
359 #endif
360 	ws->ws_row = 25;
361 	ws->ws_col = 80;
362 }
363 
364 void set_term_quiet_input(struct termios *old)
365 {
366 	struct termios tc;
367 
368 	tcgetattr(0, old);
369 	tc = *old;
370 	tc.c_lflag &= ~(ICANON | ECHO);
371 	tc.c_cc[VMIN] = 0;
372 	tc.c_cc[VTIME] = 0;
373 	tcsetattr(0, TCSANOW, &tc);
374 }
375 
376 static void set_tracing_events_path(const char *tracing, const char *mountpoint)
377 {
378 	snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s%s",
379 		 mountpoint, tracing, "events");
380 }
381 
382 static const char *__perf_tracefs_mount(const char *mountpoint)
383 {
384 	const char *mnt;
385 
386 	mnt = tracefs_mount(mountpoint);
387 	if (!mnt)
388 		return NULL;
389 
390 	set_tracing_events_path("", mnt);
391 
392 	return mnt;
393 }
394 
395 static const char *__perf_debugfs_mount(const char *mountpoint)
396 {
397 	const char *mnt;
398 
399 	mnt = debugfs_mount(mountpoint);
400 	if (!mnt)
401 		return NULL;
402 
403 	set_tracing_events_path("tracing/", mnt);
404 
405 	return mnt;
406 }
407 
408 const char *perf_debugfs_mount(const char *mountpoint)
409 {
410 	const char *mnt;
411 
412 	mnt = __perf_tracefs_mount(mountpoint);
413 	if (mnt)
414 		return mnt;
415 
416 	mnt = __perf_debugfs_mount(mountpoint);
417 
418 	return mnt;
419 }
420 
421 void perf_debugfs_set_path(const char *mntpt)
422 {
423 	snprintf(debugfs_mountpoint, strlen(debugfs_mountpoint), "%s", mntpt);
424 	set_tracing_events_path("tracing/", mntpt);
425 }
426 
427 static const char *find_tracefs(void)
428 {
429 	const char *path = __perf_tracefs_mount(NULL);
430 
431 	return path;
432 }
433 
434 static const char *find_debugfs(void)
435 {
436 	const char *path = __perf_debugfs_mount(NULL);
437 
438 	if (!path)
439 		fprintf(stderr, "Your kernel does not support the debugfs filesystem");
440 
441 	return path;
442 }
443 
444 /*
445  * Finds the path to the debugfs/tracing
446  * Allocates the string and stores it.
447  */
448 const char *find_tracing_dir(void)
449 {
450 	const char *tracing_dir = "";
451 	static char *tracing;
452 	static int tracing_found;
453 	const char *debugfs;
454 
455 	if (tracing_found)
456 		return tracing;
457 
458 	debugfs = find_tracefs();
459 	if (!debugfs) {
460 		tracing_dir = "/tracing";
461 		debugfs = find_debugfs();
462 		if (!debugfs)
463 			return NULL;
464 	}
465 
466 	if (asprintf(&tracing, "%s%s", debugfs, tracing_dir) < 0)
467 		return NULL;
468 
469 	tracing_found = 1;
470 	return tracing;
471 }
472 
473 char *get_tracing_file(const char *name)
474 {
475 	const char *tracing;
476 	char *file;
477 
478 	tracing = find_tracing_dir();
479 	if (!tracing)
480 		return NULL;
481 
482 	if (asprintf(&file, "%s/%s", tracing, name) < 0)
483 		return NULL;
484 
485 	return file;
486 }
487 
488 void put_tracing_file(char *file)
489 {
490 	free(file);
491 }
492 
493 int parse_nsec_time(const char *str, u64 *ptime)
494 {
495 	u64 time_sec, time_nsec;
496 	char *end;
497 
498 	time_sec = strtoul(str, &end, 10);
499 	if (*end != '.' && *end != '\0')
500 		return -1;
501 
502 	if (*end == '.') {
503 		int i;
504 		char nsec_buf[10];
505 
506 		if (strlen(++end) > 9)
507 			return -1;
508 
509 		strncpy(nsec_buf, end, 9);
510 		nsec_buf[9] = '\0';
511 
512 		/* make it nsec precision */
513 		for (i = strlen(nsec_buf); i < 9; i++)
514 			nsec_buf[i] = '0';
515 
516 		time_nsec = strtoul(nsec_buf, &end, 10);
517 		if (*end != '\0')
518 			return -1;
519 	} else
520 		time_nsec = 0;
521 
522 	*ptime = time_sec * NSEC_PER_SEC + time_nsec;
523 	return 0;
524 }
525 
526 unsigned long parse_tag_value(const char *str, struct parse_tag *tags)
527 {
528 	struct parse_tag *i = tags;
529 
530 	while (i->tag) {
531 		char *s;
532 
533 		s = strchr(str, i->tag);
534 		if (s) {
535 			unsigned long int value;
536 			char *endptr;
537 
538 			value = strtoul(str, &endptr, 10);
539 			if (s != endptr)
540 				break;
541 
542 			if (value > ULONG_MAX / i->mult)
543 				break;
544 			value *= i->mult;
545 			return value;
546 		}
547 		i++;
548 	}
549 
550 	return (unsigned long) -1;
551 }
552 
553 int filename__read_str(const char *filename, char **buf, size_t *sizep)
554 {
555 	size_t size = 0, alloc_size = 0;
556 	void *bf = NULL, *nbf;
557 	int fd, n, err = 0;
558 	char sbuf[STRERR_BUFSIZE];
559 
560 	fd = open(filename, O_RDONLY);
561 	if (fd < 0)
562 		return -errno;
563 
564 	do {
565 		if (size == alloc_size) {
566 			alloc_size += BUFSIZ;
567 			nbf = realloc(bf, alloc_size);
568 			if (!nbf) {
569 				err = -ENOMEM;
570 				break;
571 			}
572 
573 			bf = nbf;
574 		}
575 
576 		n = read(fd, bf + size, alloc_size - size);
577 		if (n < 0) {
578 			if (size) {
579 				pr_warning("read failed %d: %s\n", errno,
580 					 strerror_r(errno, sbuf, sizeof(sbuf)));
581 				err = 0;
582 			} else
583 				err = -errno;
584 
585 			break;
586 		}
587 
588 		size += n;
589 	} while (n > 0);
590 
591 	if (!err) {
592 		*sizep = size;
593 		*buf   = bf;
594 	} else
595 		free(bf);
596 
597 	close(fd);
598 	return err;
599 }
600 
601 const char *get_filename_for_perf_kvm(void)
602 {
603 	const char *filename;
604 
605 	if (perf_host && !perf_guest)
606 		filename = strdup("perf.data.host");
607 	else if (!perf_host && perf_guest)
608 		filename = strdup("perf.data.guest");
609 	else
610 		filename = strdup("perf.data.kvm");
611 
612 	return filename;
613 }
614 
615 int perf_event_paranoid(void)
616 {
617 	int value;
618 
619 	if (sysctl__read_int("kernel/perf_event_paranoid", &value))
620 		return INT_MAX;
621 
622 	return value;
623 }
624 
625 void mem_bswap_32(void *src, int byte_size)
626 {
627 	u32 *m = src;
628 	while (byte_size > 0) {
629 		*m = bswap_32(*m);
630 		byte_size -= sizeof(u32);
631 		++m;
632 	}
633 }
634 
635 void mem_bswap_64(void *src, int byte_size)
636 {
637 	u64 *m = src;
638 
639 	while (byte_size > 0) {
640 		*m = bswap_64(*m);
641 		byte_size -= sizeof(u64);
642 		++m;
643 	}
644 }
645 
646 bool find_process(const char *name)
647 {
648 	size_t len = strlen(name);
649 	DIR *dir;
650 	struct dirent *d;
651 	int ret = -1;
652 
653 	dir = opendir(procfs__mountpoint());
654 	if (!dir)
655 		return -1;
656 
657 	/* Walk through the directory. */
658 	while (ret && (d = readdir(dir)) != NULL) {
659 		char path[PATH_MAX];
660 		char *data;
661 		size_t size;
662 
663 		if ((d->d_type != DT_DIR) ||
664 		     !strcmp(".", d->d_name) ||
665 		     !strcmp("..", d->d_name))
666 			continue;
667 
668 		scnprintf(path, sizeof(path), "%s/%s/comm",
669 			  procfs__mountpoint(), d->d_name);
670 
671 		if (filename__read_str(path, &data, &size))
672 			continue;
673 
674 		ret = strncmp(name, data, len);
675 		free(data);
676 	}
677 
678 	closedir(dir);
679 	return ret ? false : true;
680 }
681