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