xref: /openbmc/linux/tools/perf/util/util.c (revision 1c2dd16a)
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/stat.h>
7 #include <sys/utsname.h>
8 #include <dirent.h>
9 #include <inttypes.h>
10 #include <signal.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <errno.h>
15 #include <limits.h>
16 #include <byteswap.h>
17 #include <linux/kernel.h>
18 #include <linux/log2.h>
19 #include <linux/time64.h>
20 #include <unistd.h>
21 #include "strlist.h"
22 
23 /*
24  * XXX We need to find a better place for these things...
25  */
26 unsigned int page_size;
27 int cacheline_size;
28 
29 int sysctl_perf_event_max_stack = PERF_MAX_STACK_DEPTH;
30 int sysctl_perf_event_max_contexts_per_stack = PERF_MAX_CONTEXTS_PER_STACK;
31 
32 bool test_attr__enabled;
33 
34 bool perf_host  = true;
35 bool perf_guest = false;
36 
37 void event_attr_init(struct perf_event_attr *attr)
38 {
39 	if (!perf_host)
40 		attr->exclude_host  = 1;
41 	if (!perf_guest)
42 		attr->exclude_guest = 1;
43 	/* to capture ABI version */
44 	attr->size = sizeof(*attr);
45 }
46 
47 int mkdir_p(char *path, mode_t mode)
48 {
49 	struct stat st;
50 	int err;
51 	char *d = path;
52 
53 	if (*d != '/')
54 		return -1;
55 
56 	if (stat(path, &st) == 0)
57 		return 0;
58 
59 	while (*++d == '/');
60 
61 	while ((d = strchr(d, '/'))) {
62 		*d = '\0';
63 		err = stat(path, &st) && mkdir(path, mode);
64 		*d++ = '/';
65 		if (err)
66 			return -1;
67 		while (*d == '/')
68 			++d;
69 	}
70 	return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0;
71 }
72 
73 int rm_rf(const char *path)
74 {
75 	DIR *dir;
76 	int ret = 0;
77 	struct dirent *d;
78 	char namebuf[PATH_MAX];
79 
80 	dir = opendir(path);
81 	if (dir == NULL)
82 		return 0;
83 
84 	while ((d = readdir(dir)) != NULL && !ret) {
85 		struct stat statbuf;
86 
87 		if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
88 			continue;
89 
90 		scnprintf(namebuf, sizeof(namebuf), "%s/%s",
91 			  path, d->d_name);
92 
93 		/* We have to check symbolic link itself */
94 		ret = lstat(namebuf, &statbuf);
95 		if (ret < 0) {
96 			pr_debug("stat failed: %s\n", namebuf);
97 			break;
98 		}
99 
100 		if (S_ISDIR(statbuf.st_mode))
101 			ret = rm_rf(namebuf);
102 		else
103 			ret = unlink(namebuf);
104 	}
105 	closedir(dir);
106 
107 	if (ret < 0)
108 		return ret;
109 
110 	return rmdir(path);
111 }
112 
113 /* A filter which removes dot files */
114 bool lsdir_no_dot_filter(const char *name __maybe_unused, struct dirent *d)
115 {
116 	return d->d_name[0] != '.';
117 }
118 
119 /* lsdir reads a directory and store it in strlist */
120 struct strlist *lsdir(const char *name,
121 		      bool (*filter)(const char *, struct dirent *))
122 {
123 	struct strlist *list = NULL;
124 	DIR *dir;
125 	struct dirent *d;
126 
127 	dir = opendir(name);
128 	if (!dir)
129 		return NULL;
130 
131 	list = strlist__new(NULL, NULL);
132 	if (!list) {
133 		errno = ENOMEM;
134 		goto out;
135 	}
136 
137 	while ((d = readdir(dir)) != NULL) {
138 		if (!filter || filter(name, d))
139 			strlist__add(list, d->d_name);
140 	}
141 
142 out:
143 	closedir(dir);
144 	return list;
145 }
146 
147 static int slow_copyfile(const char *from, const char *to)
148 {
149 	int err = -1;
150 	char *line = NULL;
151 	size_t n;
152 	FILE *from_fp = fopen(from, "r"), *to_fp;
153 
154 	if (from_fp == NULL)
155 		goto out;
156 
157 	to_fp = fopen(to, "w");
158 	if (to_fp == NULL)
159 		goto out_fclose_from;
160 
161 	while (getline(&line, &n, from_fp) > 0)
162 		if (fputs(line, to_fp) == EOF)
163 			goto out_fclose_to;
164 	err = 0;
165 out_fclose_to:
166 	fclose(to_fp);
167 	free(line);
168 out_fclose_from:
169 	fclose(from_fp);
170 out:
171 	return err;
172 }
173 
174 int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size)
175 {
176 	void *ptr;
177 	loff_t pgoff;
178 
179 	pgoff = off_in & ~(page_size - 1);
180 	off_in -= pgoff;
181 
182 	ptr = mmap(NULL, off_in + size, PROT_READ, MAP_PRIVATE, ifd, pgoff);
183 	if (ptr == MAP_FAILED)
184 		return -1;
185 
186 	while (size) {
187 		ssize_t ret = pwrite(ofd, ptr + off_in, size, off_out);
188 		if (ret < 0 && errno == EINTR)
189 			continue;
190 		if (ret <= 0)
191 			break;
192 
193 		size -= ret;
194 		off_in += ret;
195 		off_out -= ret;
196 	}
197 	munmap(ptr, off_in + size);
198 
199 	return size ? -1 : 0;
200 }
201 
202 int copyfile_mode(const char *from, const char *to, mode_t mode)
203 {
204 	int fromfd, tofd;
205 	struct stat st;
206 	int err = -1;
207 	char *tmp = NULL, *ptr = NULL;
208 
209 	if (stat(from, &st))
210 		goto out;
211 
212 	/* extra 'x' at the end is to reserve space for '.' */
213 	if (asprintf(&tmp, "%s.XXXXXXx", to) < 0) {
214 		tmp = NULL;
215 		goto out;
216 	}
217 	ptr = strrchr(tmp, '/');
218 	if (!ptr)
219 		goto out;
220 	ptr = memmove(ptr + 1, ptr, strlen(ptr) - 1);
221 	*ptr = '.';
222 
223 	tofd = mkstemp(tmp);
224 	if (tofd < 0)
225 		goto out;
226 
227 	if (fchmod(tofd, mode))
228 		goto out_close_to;
229 
230 	if (st.st_size == 0) { /* /proc? do it slowly... */
231 		err = slow_copyfile(from, tmp);
232 		goto out_close_to;
233 	}
234 
235 	fromfd = open(from, O_RDONLY);
236 	if (fromfd < 0)
237 		goto out_close_to;
238 
239 	err = copyfile_offset(fromfd, 0, tofd, 0, st.st_size);
240 
241 	close(fromfd);
242 out_close_to:
243 	close(tofd);
244 	if (!err)
245 		err = link(tmp, to);
246 	unlink(tmp);
247 out:
248 	free(tmp);
249 	return err;
250 }
251 
252 int copyfile(const char *from, const char *to)
253 {
254 	return copyfile_mode(from, to, 0755);
255 }
256 
257 static ssize_t ion(bool is_read, int fd, void *buf, size_t n)
258 {
259 	void *buf_start = buf;
260 	size_t left = n;
261 
262 	while (left) {
263 		ssize_t ret = is_read ? read(fd, buf, left) :
264 					write(fd, buf, left);
265 
266 		if (ret < 0 && errno == EINTR)
267 			continue;
268 		if (ret <= 0)
269 			return ret;
270 
271 		left -= ret;
272 		buf  += ret;
273 	}
274 
275 	BUG_ON((size_t)(buf - buf_start) != n);
276 	return n;
277 }
278 
279 /*
280  * Read exactly 'n' bytes or return an error.
281  */
282 ssize_t readn(int fd, void *buf, size_t n)
283 {
284 	return ion(true, fd, buf, n);
285 }
286 
287 /*
288  * Write exactly 'n' bytes or return an error.
289  */
290 ssize_t writen(int fd, void *buf, size_t n)
291 {
292 	return ion(false, fd, buf, n);
293 }
294 
295 size_t hex_width(u64 v)
296 {
297 	size_t n = 1;
298 
299 	while ((v >>= 4))
300 		++n;
301 
302 	return n;
303 }
304 
305 static int hex(char ch)
306 {
307 	if ((ch >= '0') && (ch <= '9'))
308 		return ch - '0';
309 	if ((ch >= 'a') && (ch <= 'f'))
310 		return ch - 'a' + 10;
311 	if ((ch >= 'A') && (ch <= 'F'))
312 		return ch - 'A' + 10;
313 	return -1;
314 }
315 
316 /*
317  * While we find nice hex chars, build a long_val.
318  * Return number of chars processed.
319  */
320 int hex2u64(const char *ptr, u64 *long_val)
321 {
322 	const char *p = ptr;
323 	*long_val = 0;
324 
325 	while (*p) {
326 		const int hex_val = hex(*p);
327 
328 		if (hex_val < 0)
329 			break;
330 
331 		*long_val = (*long_val << 4) | hex_val;
332 		p++;
333 	}
334 
335 	return p - ptr;
336 }
337 
338 unsigned long parse_tag_value(const char *str, struct parse_tag *tags)
339 {
340 	struct parse_tag *i = tags;
341 
342 	while (i->tag) {
343 		char *s;
344 
345 		s = strchr(str, i->tag);
346 		if (s) {
347 			unsigned long int value;
348 			char *endptr;
349 
350 			value = strtoul(str, &endptr, 10);
351 			if (s != endptr)
352 				break;
353 
354 			if (value > ULONG_MAX / i->mult)
355 				break;
356 			value *= i->mult;
357 			return value;
358 		}
359 		i++;
360 	}
361 
362 	return (unsigned long) -1;
363 }
364 
365 int perf_event_paranoid(void)
366 {
367 	int value;
368 
369 	if (sysctl__read_int("kernel/perf_event_paranoid", &value))
370 		return INT_MAX;
371 
372 	return value;
373 }
374 
375 void mem_bswap_32(void *src, int byte_size)
376 {
377 	u32 *m = src;
378 	while (byte_size > 0) {
379 		*m = bswap_32(*m);
380 		byte_size -= sizeof(u32);
381 		++m;
382 	}
383 }
384 
385 void mem_bswap_64(void *src, int byte_size)
386 {
387 	u64 *m = src;
388 
389 	while (byte_size > 0) {
390 		*m = bswap_64(*m);
391 		byte_size -= sizeof(u64);
392 		++m;
393 	}
394 }
395 
396 bool find_process(const char *name)
397 {
398 	size_t len = strlen(name);
399 	DIR *dir;
400 	struct dirent *d;
401 	int ret = -1;
402 
403 	dir = opendir(procfs__mountpoint());
404 	if (!dir)
405 		return false;
406 
407 	/* Walk through the directory. */
408 	while (ret && (d = readdir(dir)) != NULL) {
409 		char path[PATH_MAX];
410 		char *data;
411 		size_t size;
412 
413 		if ((d->d_type != DT_DIR) ||
414 		     !strcmp(".", d->d_name) ||
415 		     !strcmp("..", d->d_name))
416 			continue;
417 
418 		scnprintf(path, sizeof(path), "%s/%s/comm",
419 			  procfs__mountpoint(), d->d_name);
420 
421 		if (filename__read_str(path, &data, &size))
422 			continue;
423 
424 		ret = strncmp(name, data, len);
425 		free(data);
426 	}
427 
428 	closedir(dir);
429 	return ret ? false : true;
430 }
431 
432 static int
433 fetch_ubuntu_kernel_version(unsigned int *puint)
434 {
435 	ssize_t len;
436 	size_t line_len = 0;
437 	char *ptr, *line = NULL;
438 	int version, patchlevel, sublevel, err;
439 	FILE *vsig = fopen("/proc/version_signature", "r");
440 
441 	if (!vsig) {
442 		pr_debug("Open /proc/version_signature failed: %s\n",
443 			 strerror(errno));
444 		return -1;
445 	}
446 
447 	len = getline(&line, &line_len, vsig);
448 	fclose(vsig);
449 	err = -1;
450 	if (len <= 0) {
451 		pr_debug("Reading from /proc/version_signature failed: %s\n",
452 			 strerror(errno));
453 		goto errout;
454 	}
455 
456 	ptr = strrchr(line, ' ');
457 	if (!ptr) {
458 		pr_debug("Parsing /proc/version_signature failed: %s\n", line);
459 		goto errout;
460 	}
461 
462 	err = sscanf(ptr + 1, "%d.%d.%d",
463 		     &version, &patchlevel, &sublevel);
464 	if (err != 3) {
465 		pr_debug("Unable to get kernel version from /proc/version_signature '%s'\n",
466 			 line);
467 		goto errout;
468 	}
469 
470 	if (puint)
471 		*puint = (version << 16) + (patchlevel << 8) + sublevel;
472 	err = 0;
473 errout:
474 	free(line);
475 	return err;
476 }
477 
478 int
479 fetch_kernel_version(unsigned int *puint, char *str,
480 		     size_t str_size)
481 {
482 	struct utsname utsname;
483 	int version, patchlevel, sublevel, err;
484 	bool int_ver_ready = false;
485 
486 	if (access("/proc/version_signature", R_OK) == 0)
487 		if (!fetch_ubuntu_kernel_version(puint))
488 			int_ver_ready = true;
489 
490 	if (uname(&utsname))
491 		return -1;
492 
493 	if (str && str_size) {
494 		strncpy(str, utsname.release, str_size);
495 		str[str_size - 1] = '\0';
496 	}
497 
498 	err = sscanf(utsname.release, "%d.%d.%d",
499 		     &version, &patchlevel, &sublevel);
500 
501 	if (err != 3) {
502 		pr_debug("Unable to get kernel version from uname '%s'\n",
503 			 utsname.release);
504 		return -1;
505 	}
506 
507 	if (puint && !int_ver_ready)
508 		*puint = (version << 16) + (patchlevel << 8) + sublevel;
509 	return 0;
510 }
511 
512 const char *perf_tip(const char *dirpath)
513 {
514 	struct strlist *tips;
515 	struct str_node *node;
516 	char *tip = NULL;
517 	struct strlist_config conf = {
518 		.dirname = dirpath,
519 		.file_only = true,
520 	};
521 
522 	tips = strlist__new("tips.txt", &conf);
523 	if (tips == NULL)
524 		return errno == ENOENT ? NULL :
525 			"Tip: check path of tips.txt or get more memory! ;-p";
526 
527 	if (strlist__nr_entries(tips) == 0)
528 		goto out;
529 
530 	node = strlist__entry(tips, random() % strlist__nr_entries(tips));
531 	if (asprintf(&tip, "Tip: %s", node->s) < 0)
532 		tip = (char *)"Tip: get more memory! ;-)";
533 
534 out:
535 	strlist__delete(tips);
536 
537 	return tip;
538 }
539