xref: /openbmc/linux/tools/perf/util/util.c (revision cd4d09ec)
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 #include "strlist.h"
20 
21 struct callchain_param	callchain_param = {
22 	.mode	= CHAIN_GRAPH_ABS,
23 	.min_percent = 0.5,
24 	.order  = ORDER_CALLEE,
25 	.key	= CCKEY_FUNCTION,
26 	.value	= CCVAL_PERCENT,
27 };
28 
29 /*
30  * XXX We need to find a better place for these things...
31  */
32 unsigned int page_size;
33 int cacheline_size;
34 
35 bool test_attr__enabled;
36 
37 bool perf_host  = true;
38 bool perf_guest = false;
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 	signal(sig, SIG_DFL);
357 	raise(sig);
358 }
359 
360 int parse_nsec_time(const char *str, u64 *ptime)
361 {
362 	u64 time_sec, time_nsec;
363 	char *end;
364 
365 	time_sec = strtoul(str, &end, 10);
366 	if (*end != '.' && *end != '\0')
367 		return -1;
368 
369 	if (*end == '.') {
370 		int i;
371 		char nsec_buf[10];
372 
373 		if (strlen(++end) > 9)
374 			return -1;
375 
376 		strncpy(nsec_buf, end, 9);
377 		nsec_buf[9] = '\0';
378 
379 		/* make it nsec precision */
380 		for (i = strlen(nsec_buf); i < 9; i++)
381 			nsec_buf[i] = '0';
382 
383 		time_nsec = strtoul(nsec_buf, &end, 10);
384 		if (*end != '\0')
385 			return -1;
386 	} else
387 		time_nsec = 0;
388 
389 	*ptime = time_sec * NSEC_PER_SEC + time_nsec;
390 	return 0;
391 }
392 
393 unsigned long parse_tag_value(const char *str, struct parse_tag *tags)
394 {
395 	struct parse_tag *i = tags;
396 
397 	while (i->tag) {
398 		char *s;
399 
400 		s = strchr(str, i->tag);
401 		if (s) {
402 			unsigned long int value;
403 			char *endptr;
404 
405 			value = strtoul(str, &endptr, 10);
406 			if (s != endptr)
407 				break;
408 
409 			if (value > ULONG_MAX / i->mult)
410 				break;
411 			value *= i->mult;
412 			return value;
413 		}
414 		i++;
415 	}
416 
417 	return (unsigned long) -1;
418 }
419 
420 int get_stack_size(const char *str, unsigned long *_size)
421 {
422 	char *endptr;
423 	unsigned long size;
424 	unsigned long max_size = round_down(USHRT_MAX, sizeof(u64));
425 
426 	size = strtoul(str, &endptr, 0);
427 
428 	do {
429 		if (*endptr)
430 			break;
431 
432 		size = round_up(size, sizeof(u64));
433 		if (!size || size > max_size)
434 			break;
435 
436 		*_size = size;
437 		return 0;
438 
439 	} while (0);
440 
441 	pr_err("callchain: Incorrect stack dump size (max %ld): %s\n",
442 	       max_size, str);
443 	return -1;
444 }
445 
446 int parse_callchain_record(const char *arg, struct callchain_param *param)
447 {
448 	char *tok, *name, *saveptr = NULL;
449 	char *buf;
450 	int ret = -1;
451 
452 	/* We need buffer that we know we can write to. */
453 	buf = malloc(strlen(arg) + 1);
454 	if (!buf)
455 		return -ENOMEM;
456 
457 	strcpy(buf, arg);
458 
459 	tok = strtok_r((char *)buf, ",", &saveptr);
460 	name = tok ? : (char *)buf;
461 
462 	do {
463 		/* Framepointer style */
464 		if (!strncmp(name, "fp", sizeof("fp"))) {
465 			if (!strtok_r(NULL, ",", &saveptr)) {
466 				param->record_mode = CALLCHAIN_FP;
467 				ret = 0;
468 			} else
469 				pr_err("callchain: No more arguments "
470 				       "needed for --call-graph fp\n");
471 			break;
472 
473 #ifdef HAVE_DWARF_UNWIND_SUPPORT
474 		/* Dwarf style */
475 		} else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
476 			const unsigned long default_stack_dump_size = 8192;
477 
478 			ret = 0;
479 			param->record_mode = CALLCHAIN_DWARF;
480 			param->dump_size = default_stack_dump_size;
481 
482 			tok = strtok_r(NULL, ",", &saveptr);
483 			if (tok) {
484 				unsigned long size = 0;
485 
486 				ret = get_stack_size(tok, &size);
487 				param->dump_size = size;
488 			}
489 #endif /* HAVE_DWARF_UNWIND_SUPPORT */
490 		} else if (!strncmp(name, "lbr", sizeof("lbr"))) {
491 			if (!strtok_r(NULL, ",", &saveptr)) {
492 				param->record_mode = CALLCHAIN_LBR;
493 				ret = 0;
494 			} else
495 				pr_err("callchain: No more arguments "
496 					"needed for --call-graph lbr\n");
497 			break;
498 		} else {
499 			pr_err("callchain: Unknown --call-graph option "
500 			       "value: %s\n", arg);
501 			break;
502 		}
503 
504 	} while (0);
505 
506 	free(buf);
507 	return ret;
508 }
509 
510 int filename__read_str(const char *filename, char **buf, size_t *sizep)
511 {
512 	size_t size = 0, alloc_size = 0;
513 	void *bf = NULL, *nbf;
514 	int fd, n, err = 0;
515 	char sbuf[STRERR_BUFSIZE];
516 
517 	fd = open(filename, O_RDONLY);
518 	if (fd < 0)
519 		return -errno;
520 
521 	do {
522 		if (size == alloc_size) {
523 			alloc_size += BUFSIZ;
524 			nbf = realloc(bf, alloc_size);
525 			if (!nbf) {
526 				err = -ENOMEM;
527 				break;
528 			}
529 
530 			bf = nbf;
531 		}
532 
533 		n = read(fd, bf + size, alloc_size - size);
534 		if (n < 0) {
535 			if (size) {
536 				pr_warning("read failed %d: %s\n", errno,
537 					 strerror_r(errno, sbuf, sizeof(sbuf)));
538 				err = 0;
539 			} else
540 				err = -errno;
541 
542 			break;
543 		}
544 
545 		size += n;
546 	} while (n > 0);
547 
548 	if (!err) {
549 		*sizep = size;
550 		*buf   = bf;
551 	} else
552 		free(bf);
553 
554 	close(fd);
555 	return err;
556 }
557 
558 const char *get_filename_for_perf_kvm(void)
559 {
560 	const char *filename;
561 
562 	if (perf_host && !perf_guest)
563 		filename = strdup("perf.data.host");
564 	else if (!perf_host && perf_guest)
565 		filename = strdup("perf.data.guest");
566 	else
567 		filename = strdup("perf.data.kvm");
568 
569 	return filename;
570 }
571 
572 int perf_event_paranoid(void)
573 {
574 	int value;
575 
576 	if (sysctl__read_int("kernel/perf_event_paranoid", &value))
577 		return INT_MAX;
578 
579 	return value;
580 }
581 
582 void mem_bswap_32(void *src, int byte_size)
583 {
584 	u32 *m = src;
585 	while (byte_size > 0) {
586 		*m = bswap_32(*m);
587 		byte_size -= sizeof(u32);
588 		++m;
589 	}
590 }
591 
592 void mem_bswap_64(void *src, int byte_size)
593 {
594 	u64 *m = src;
595 
596 	while (byte_size > 0) {
597 		*m = bswap_64(*m);
598 		byte_size -= sizeof(u64);
599 		++m;
600 	}
601 }
602 
603 bool find_process(const char *name)
604 {
605 	size_t len = strlen(name);
606 	DIR *dir;
607 	struct dirent *d;
608 	int ret = -1;
609 
610 	dir = opendir(procfs__mountpoint());
611 	if (!dir)
612 		return false;
613 
614 	/* Walk through the directory. */
615 	while (ret && (d = readdir(dir)) != NULL) {
616 		char path[PATH_MAX];
617 		char *data;
618 		size_t size;
619 
620 		if ((d->d_type != DT_DIR) ||
621 		     !strcmp(".", d->d_name) ||
622 		     !strcmp("..", d->d_name))
623 			continue;
624 
625 		scnprintf(path, sizeof(path), "%s/%s/comm",
626 			  procfs__mountpoint(), d->d_name);
627 
628 		if (filename__read_str(path, &data, &size))
629 			continue;
630 
631 		ret = strncmp(name, data, len);
632 		free(data);
633 	}
634 
635 	closedir(dir);
636 	return ret ? false : true;
637 }
638 
639 int
640 fetch_kernel_version(unsigned int *puint, char *str,
641 		     size_t str_size)
642 {
643 	struct utsname utsname;
644 	int version, patchlevel, sublevel, err;
645 
646 	if (uname(&utsname))
647 		return -1;
648 
649 	if (str && str_size) {
650 		strncpy(str, utsname.release, str_size);
651 		str[str_size - 1] = '\0';
652 	}
653 
654 	err = sscanf(utsname.release, "%d.%d.%d",
655 		     &version, &patchlevel, &sublevel);
656 
657 	if (err != 3) {
658 		pr_debug("Unablt to get kernel version from uname '%s'\n",
659 			 utsname.release);
660 		return -1;
661 	}
662 
663 	if (puint)
664 		*puint = (version << 16) + (patchlevel << 8) + sublevel;
665 	return 0;
666 }
667 
668 const char *perf_tip(const char *dirpath)
669 {
670 	struct strlist *tips;
671 	struct str_node *node;
672 	char *tip = NULL;
673 	struct strlist_config conf = {
674 		.dirname = dirpath,
675 		.file_only = true,
676 	};
677 
678 	tips = strlist__new("tips.txt", &conf);
679 	if (tips == NULL)
680 		return errno == ENOENT ? NULL : "Tip: get more memory! ;-p";
681 
682 	if (strlist__nr_entries(tips) == 0)
683 		goto out;
684 
685 	node = strlist__entry(tips, random() % strlist__nr_entries(tips));
686 	if (asprintf(&tip, "Tip: %s", node->s) < 0)
687 		tip = (char *)"Tip: get more memory! ;-)";
688 
689 out:
690 	strlist__delete(tips);
691 
692 	return tip;
693 }
694