xref: /linux/tools/perf/tests/code-reading.c (revision c1a604dff486399ae0be95e6396e0158df95ad5d)
1 // SPDX-License-Identifier: GPL-2.0
2 #include <errno.h>
3 #include <linux/kernel.h>
4 #include <linux/types.h>
5 #include <inttypes.h>
6 #include <stdlib.h>
7 #include <unistd.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <sys/param.h>
11 #include <perf/cpumap.h>
12 #include <perf/evlist.h>
13 
14 #include "parse-events.h"
15 #include "evlist.h"
16 #include "evsel.h"
17 #include "thread_map.h"
18 #include "cpumap.h"
19 #include "machine.h"
20 #include "map.h"
21 #include "symbol.h"
22 #include "event.h"
23 #include "record.h"
24 #include "thread.h"
25 
26 #include "tests.h"
27 
28 #include <linux/ctype.h>
29 
30 #define BUFSZ	1024
31 #define READLEN	128
32 
33 struct state {
34 	u64 done[1024];
35 	size_t done_cnt;
36 };
37 
38 static unsigned int hex(char c)
39 {
40 	if (c >= '0' && c <= '9')
41 		return c - '0';
42 	if (c >= 'a' && c <= 'f')
43 		return c - 'a' + 10;
44 	return c - 'A' + 10;
45 }
46 
47 static size_t read_objdump_chunk(const char **line, unsigned char **buf,
48 				 size_t *buf_len)
49 {
50 	size_t bytes_read = 0;
51 	unsigned char *chunk_start = *buf;
52 
53 	/* Read bytes */
54 	while (*buf_len > 0) {
55 		char c1, c2;
56 
57 		/* Get 2 hex digits */
58 		c1 = *(*line)++;
59 		if (!isxdigit(c1))
60 			break;
61 		c2 = *(*line)++;
62 		if (!isxdigit(c2))
63 			break;
64 
65 		/* Store byte and advance buf */
66 		**buf = (hex(c1) << 4) | hex(c2);
67 		(*buf)++;
68 		(*buf_len)--;
69 		bytes_read++;
70 
71 		/* End of chunk? */
72 		if (isspace(**line))
73 			break;
74 	}
75 
76 	/*
77 	 * objdump will display raw insn as LE if code endian
78 	 * is LE and bytes_per_chunk > 1. In that case reverse
79 	 * the chunk we just read.
80 	 *
81 	 * see disassemble_bytes() at binutils/objdump.c for details
82 	 * how objdump chooses display endian)
83 	 */
84 	if (bytes_read > 1 && !bigendian()) {
85 		unsigned char *chunk_end = chunk_start + bytes_read - 1;
86 		unsigned char tmp;
87 
88 		while (chunk_start < chunk_end) {
89 			tmp = *chunk_start;
90 			*chunk_start = *chunk_end;
91 			*chunk_end = tmp;
92 			chunk_start++;
93 			chunk_end--;
94 		}
95 	}
96 
97 	return bytes_read;
98 }
99 
100 static size_t read_objdump_line(const char *line, unsigned char *buf,
101 				size_t buf_len)
102 {
103 	const char *p;
104 	size_t ret, bytes_read = 0;
105 
106 	/* Skip to a colon */
107 	p = strchr(line, ':');
108 	if (!p)
109 		return 0;
110 	p++;
111 
112 	/* Skip initial spaces */
113 	while (*p) {
114 		if (!isspace(*p))
115 			break;
116 		p++;
117 	}
118 
119 	do {
120 		ret = read_objdump_chunk(&p, &buf, &buf_len);
121 		bytes_read += ret;
122 		p++;
123 	} while (ret > 0);
124 
125 	/* return number of successfully read bytes */
126 	return bytes_read;
127 }
128 
129 static int read_objdump_output(FILE *f, void *buf, size_t *len, u64 start_addr)
130 {
131 	char *line = NULL;
132 	size_t line_len, off_last = 0;
133 	ssize_t ret;
134 	int err = 0;
135 	u64 addr, last_addr = start_addr;
136 
137 	while (off_last < *len) {
138 		size_t off, read_bytes, written_bytes;
139 		unsigned char tmp[BUFSZ];
140 
141 		ret = getline(&line, &line_len, f);
142 		if (feof(f))
143 			break;
144 		if (ret < 0) {
145 			pr_debug("getline failed\n");
146 			err = -1;
147 			break;
148 		}
149 
150 		/* read objdump data into temporary buffer */
151 		read_bytes = read_objdump_line(line, tmp, sizeof(tmp));
152 		if (!read_bytes)
153 			continue;
154 
155 		if (sscanf(line, "%"PRIx64, &addr) != 1)
156 			continue;
157 		if (addr < last_addr) {
158 			pr_debug("addr going backwards, read beyond section?\n");
159 			break;
160 		}
161 		last_addr = addr;
162 
163 		/* copy it from temporary buffer to 'buf' according
164 		 * to address on current objdump line */
165 		off = addr - start_addr;
166 		if (off >= *len)
167 			break;
168 		written_bytes = MIN(read_bytes, *len - off);
169 		memcpy(buf + off, tmp, written_bytes);
170 		off_last = off + written_bytes;
171 	}
172 
173 	/* len returns number of bytes that could not be read */
174 	*len -= off_last;
175 
176 	free(line);
177 
178 	return err;
179 }
180 
181 static int read_via_objdump(const char *filename, u64 addr, void *buf,
182 			    size_t len)
183 {
184 	char cmd[PATH_MAX * 2];
185 	const char *fmt;
186 	FILE *f;
187 	int ret;
188 
189 	fmt = "%s -z -d --start-address=0x%"PRIx64" --stop-address=0x%"PRIx64" %s";
190 	ret = snprintf(cmd, sizeof(cmd), fmt, "objdump", addr, addr + len,
191 		       filename);
192 	if (ret <= 0 || (size_t)ret >= sizeof(cmd))
193 		return -1;
194 
195 	pr_debug("Objdump command is: %s\n", cmd);
196 
197 	/* Ignore objdump errors */
198 	strcat(cmd, " 2>/dev/null");
199 
200 	f = popen(cmd, "r");
201 	if (!f) {
202 		pr_debug("popen failed\n");
203 		return -1;
204 	}
205 
206 	ret = read_objdump_output(f, buf, &len, addr);
207 	if (len) {
208 		pr_debug("objdump read too few bytes: %zd\n", len);
209 		if (!ret)
210 			ret = len;
211 	}
212 
213 	pclose(f);
214 
215 	return ret;
216 }
217 
218 static void dump_buf(unsigned char *buf, size_t len)
219 {
220 	size_t i;
221 
222 	for (i = 0; i < len; i++) {
223 		pr_debug("0x%02x ", buf[i]);
224 		if (i % 16 == 15)
225 			pr_debug("\n");
226 	}
227 	pr_debug("\n");
228 }
229 
230 static int read_object_code(u64 addr, size_t len, u8 cpumode,
231 			    struct thread *thread, struct state *state)
232 {
233 	struct addr_location al;
234 	unsigned char buf1[BUFSZ];
235 	unsigned char buf2[BUFSZ];
236 	size_t ret_len;
237 	u64 objdump_addr;
238 	const char *objdump_name;
239 	char decomp_name[KMOD_DECOMP_LEN];
240 	bool decomp = false;
241 	int ret;
242 
243 	pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr);
244 
245 	if (!thread__find_map(thread, cpumode, addr, &al) || !al.map->dso) {
246 		if (cpumode == PERF_RECORD_MISC_HYPERVISOR) {
247 			pr_debug("Hypervisor address can not be resolved - skipping\n");
248 			return 0;
249 		}
250 
251 		pr_debug("thread__find_map failed\n");
252 		return -1;
253 	}
254 
255 	pr_debug("File is: %s\n", al.map->dso->long_name);
256 
257 	if (al.map->dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
258 	    !dso__is_kcore(al.map->dso)) {
259 		pr_debug("Unexpected kernel address - skipping\n");
260 		return 0;
261 	}
262 
263 	pr_debug("On file address is: %#"PRIx64"\n", al.addr);
264 
265 	if (len > BUFSZ)
266 		len = BUFSZ;
267 
268 	/* Do not go off the map */
269 	if (addr + len > al.map->end)
270 		len = al.map->end - addr;
271 
272 	/* Read the object code using perf */
273 	ret_len = dso__data_read_offset(al.map->dso, thread->mg->machine,
274 					al.addr, buf1, len);
275 	if (ret_len != len) {
276 		pr_debug("dso__data_read_offset failed\n");
277 		return -1;
278 	}
279 
280 	/*
281 	 * Converting addresses for use by objdump requires more information.
282 	 * map__load() does that.  See map__rip_2objdump() for details.
283 	 */
284 	if (map__load(al.map))
285 		return -1;
286 
287 	/* objdump struggles with kcore - try each map only once */
288 	if (dso__is_kcore(al.map->dso)) {
289 		size_t d;
290 
291 		for (d = 0; d < state->done_cnt; d++) {
292 			if (state->done[d] == al.map->start) {
293 				pr_debug("kcore map tested already");
294 				pr_debug(" - skipping\n");
295 				return 0;
296 			}
297 		}
298 		if (state->done_cnt >= ARRAY_SIZE(state->done)) {
299 			pr_debug("Too many kcore maps - skipping\n");
300 			return 0;
301 		}
302 		state->done[state->done_cnt++] = al.map->start;
303 	}
304 
305 	objdump_name = al.map->dso->long_name;
306 	if (dso__needs_decompress(al.map->dso)) {
307 		if (dso__decompress_kmodule_path(al.map->dso, objdump_name,
308 						 decomp_name,
309 						 sizeof(decomp_name)) < 0) {
310 			pr_debug("decompression failed\n");
311 			return -1;
312 		}
313 
314 		decomp = true;
315 		objdump_name = decomp_name;
316 	}
317 
318 	/* Read the object code using objdump */
319 	objdump_addr = map__rip_2objdump(al.map, al.addr);
320 	ret = read_via_objdump(objdump_name, objdump_addr, buf2, len);
321 
322 	if (decomp)
323 		unlink(objdump_name);
324 
325 	if (ret > 0) {
326 		/*
327 		 * The kernel maps are inaccurate - assume objdump is right in
328 		 * that case.
329 		 */
330 		if (cpumode == PERF_RECORD_MISC_KERNEL ||
331 		    cpumode == PERF_RECORD_MISC_GUEST_KERNEL) {
332 			len -= ret;
333 			if (len) {
334 				pr_debug("Reducing len to %zu\n", len);
335 			} else if (dso__is_kcore(al.map->dso)) {
336 				/*
337 				 * objdump cannot handle very large segments
338 				 * that may be found in kcore.
339 				 */
340 				pr_debug("objdump failed for kcore");
341 				pr_debug(" - skipping\n");
342 				return 0;
343 			} else {
344 				return -1;
345 			}
346 		}
347 	}
348 	if (ret < 0) {
349 		pr_debug("read_via_objdump failed\n");
350 		return -1;
351 	}
352 
353 	/* The results should be identical */
354 	if (memcmp(buf1, buf2, len)) {
355 		pr_debug("Bytes read differ from those read by objdump\n");
356 		pr_debug("buf1 (dso):\n");
357 		dump_buf(buf1, len);
358 		pr_debug("buf2 (objdump):\n");
359 		dump_buf(buf2, len);
360 		return -1;
361 	}
362 	pr_debug("Bytes read match those read by objdump\n");
363 
364 	return 0;
365 }
366 
367 static int process_sample_event(struct machine *machine,
368 				struct evlist *evlist,
369 				union perf_event *event, struct state *state)
370 {
371 	struct perf_sample sample;
372 	struct thread *thread;
373 	int ret;
374 
375 	if (perf_evlist__parse_sample(evlist, event, &sample)) {
376 		pr_debug("perf_evlist__parse_sample failed\n");
377 		return -1;
378 	}
379 
380 	thread = machine__findnew_thread(machine, sample.pid, sample.tid);
381 	if (!thread) {
382 		pr_debug("machine__findnew_thread failed\n");
383 		return -1;
384 	}
385 
386 	ret = read_object_code(sample.ip, READLEN, sample.cpumode, thread, state);
387 	thread__put(thread);
388 	return ret;
389 }
390 
391 static int process_event(struct machine *machine, struct evlist *evlist,
392 			 union perf_event *event, struct state *state)
393 {
394 	if (event->header.type == PERF_RECORD_SAMPLE)
395 		return process_sample_event(machine, evlist, event, state);
396 
397 	if (event->header.type == PERF_RECORD_THROTTLE ||
398 	    event->header.type == PERF_RECORD_UNTHROTTLE)
399 		return 0;
400 
401 	if (event->header.type < PERF_RECORD_MAX) {
402 		int ret;
403 
404 		ret = machine__process_event(machine, event, NULL);
405 		if (ret < 0)
406 			pr_debug("machine__process_event failed, event type %u\n",
407 				 event->header.type);
408 		return ret;
409 	}
410 
411 	return 0;
412 }
413 
414 static int process_events(struct machine *machine, struct evlist *evlist,
415 			  struct state *state)
416 {
417 	union perf_event *event;
418 	struct perf_mmap *md;
419 	int i, ret;
420 
421 	for (i = 0; i < evlist->nr_mmaps; i++) {
422 		md = &evlist->mmap[i];
423 		if (perf_mmap__read_init(md) < 0)
424 			continue;
425 
426 		while ((event = perf_mmap__read_event(md)) != NULL) {
427 			ret = process_event(machine, evlist, event, state);
428 			perf_mmap__consume(md);
429 			if (ret < 0)
430 				return ret;
431 		}
432 		perf_mmap__read_done(md);
433 	}
434 	return 0;
435 }
436 
437 static int comp(const void *a, const void *b)
438 {
439 	return *(int *)a - *(int *)b;
440 }
441 
442 static void do_sort_something(void)
443 {
444 	int buf[40960], i;
445 
446 	for (i = 0; i < (int)ARRAY_SIZE(buf); i++)
447 		buf[i] = ARRAY_SIZE(buf) - i - 1;
448 
449 	qsort(buf, ARRAY_SIZE(buf), sizeof(int), comp);
450 
451 	for (i = 0; i < (int)ARRAY_SIZE(buf); i++) {
452 		if (buf[i] != i) {
453 			pr_debug("qsort failed\n");
454 			break;
455 		}
456 	}
457 }
458 
459 static void sort_something(void)
460 {
461 	int i;
462 
463 	for (i = 0; i < 10; i++)
464 		do_sort_something();
465 }
466 
467 static void syscall_something(void)
468 {
469 	int pipefd[2];
470 	int i;
471 
472 	for (i = 0; i < 1000; i++) {
473 		if (pipe(pipefd) < 0) {
474 			pr_debug("pipe failed\n");
475 			break;
476 		}
477 		close(pipefd[1]);
478 		close(pipefd[0]);
479 	}
480 }
481 
482 static void fs_something(void)
483 {
484 	const char *test_file_name = "temp-perf-code-reading-test-file--";
485 	FILE *f;
486 	int i;
487 
488 	for (i = 0; i < 1000; i++) {
489 		f = fopen(test_file_name, "w+");
490 		if (f) {
491 			fclose(f);
492 			unlink(test_file_name);
493 		}
494 	}
495 }
496 
497 static const char *do_determine_event(bool excl_kernel)
498 {
499 	const char *event = excl_kernel ? "cycles:u" : "cycles";
500 
501 #ifdef __s390x__
502 	char cpuid[128], model[16], model_c[16], cpum_cf_v[16];
503 	unsigned int family;
504 	int ret, cpum_cf_a;
505 
506 	if (get_cpuid(cpuid, sizeof(cpuid)))
507 		goto out_clocks;
508 	ret = sscanf(cpuid, "%*[^,],%u,%[^,],%[^,],%[^,],%x", &family, model_c,
509 		     model, cpum_cf_v, &cpum_cf_a);
510 	if (ret != 5)		 /* Not available */
511 		goto out_clocks;
512 	if (excl_kernel && (cpum_cf_a & 4))
513 		return event;
514 	if (!excl_kernel && (cpum_cf_a & 2))
515 		return event;
516 
517 	/* Fall through: missing authorization */
518 out_clocks:
519 	event = excl_kernel ? "cpu-clock:u" : "cpu-clock";
520 
521 #endif
522 	return event;
523 }
524 
525 static void do_something(void)
526 {
527 	fs_something();
528 
529 	sort_something();
530 
531 	syscall_something();
532 }
533 
534 enum {
535 	TEST_CODE_READING_OK,
536 	TEST_CODE_READING_NO_VMLINUX,
537 	TEST_CODE_READING_NO_KCORE,
538 	TEST_CODE_READING_NO_ACCESS,
539 	TEST_CODE_READING_NO_KERNEL_OBJ,
540 };
541 
542 static int do_test_code_reading(bool try_kcore)
543 {
544 	struct machine *machine;
545 	struct thread *thread;
546 	struct record_opts opts = {
547 		.mmap_pages	     = UINT_MAX,
548 		.user_freq	     = UINT_MAX,
549 		.user_interval	     = ULLONG_MAX,
550 		.freq		     = 500,
551 		.target		     = {
552 			.uses_mmap   = true,
553 		},
554 	};
555 	struct state state = {
556 		.done_cnt = 0,
557 	};
558 	struct perf_thread_map *threads = NULL;
559 	struct perf_cpu_map *cpus = NULL;
560 	struct evlist *evlist = NULL;
561 	struct evsel *evsel = NULL;
562 	int err = -1, ret;
563 	pid_t pid;
564 	struct map *map;
565 	bool have_vmlinux, have_kcore, excl_kernel = false;
566 
567 	pid = getpid();
568 
569 	machine = machine__new_host();
570 	machine->env = &perf_env;
571 
572 	ret = machine__create_kernel_maps(machine);
573 	if (ret < 0) {
574 		pr_debug("machine__create_kernel_maps failed\n");
575 		goto out_err;
576 	}
577 
578 	/* Force the use of kallsyms instead of vmlinux to try kcore */
579 	if (try_kcore)
580 		symbol_conf.kallsyms_name = "/proc/kallsyms";
581 
582 	/* Load kernel map */
583 	map = machine__kernel_map(machine);
584 	ret = map__load(map);
585 	if (ret < 0) {
586 		pr_debug("map__load failed\n");
587 		goto out_err;
588 	}
589 	have_vmlinux = dso__is_vmlinux(map->dso);
590 	have_kcore = dso__is_kcore(map->dso);
591 
592 	/* 2nd time through we just try kcore */
593 	if (try_kcore && !have_kcore)
594 		return TEST_CODE_READING_NO_KCORE;
595 
596 	/* No point getting kernel events if there is no kernel object */
597 	if (!have_vmlinux && !have_kcore)
598 		excl_kernel = true;
599 
600 	threads = thread_map__new_by_tid(pid);
601 	if (!threads) {
602 		pr_debug("thread_map__new_by_tid failed\n");
603 		goto out_err;
604 	}
605 
606 	ret = perf_event__synthesize_thread_map(NULL, threads,
607 						perf_event__process, machine, false);
608 	if (ret < 0) {
609 		pr_debug("perf_event__synthesize_thread_map failed\n");
610 		goto out_err;
611 	}
612 
613 	thread = machine__findnew_thread(machine, pid, pid);
614 	if (!thread) {
615 		pr_debug("machine__findnew_thread failed\n");
616 		goto out_put;
617 	}
618 
619 	cpus = perf_cpu_map__new(NULL);
620 	if (!cpus) {
621 		pr_debug("perf_cpu_map__new failed\n");
622 		goto out_put;
623 	}
624 
625 	while (1) {
626 		const char *str;
627 
628 		evlist = evlist__new();
629 		if (!evlist) {
630 			pr_debug("perf_evlist__new failed\n");
631 			goto out_put;
632 		}
633 
634 		perf_evlist__set_maps(&evlist->core, cpus, threads);
635 
636 		str = do_determine_event(excl_kernel);
637 		pr_debug("Parsing event '%s'\n", str);
638 		ret = parse_events(evlist, str, NULL);
639 		if (ret < 0) {
640 			pr_debug("parse_events failed\n");
641 			goto out_put;
642 		}
643 
644 		perf_evlist__config(evlist, &opts, NULL);
645 
646 		evsel = perf_evlist__first(evlist);
647 
648 		evsel->core.attr.comm = 1;
649 		evsel->core.attr.disabled = 1;
650 		evsel->core.attr.enable_on_exec = 0;
651 
652 		ret = evlist__open(evlist);
653 		if (ret < 0) {
654 			if (!excl_kernel) {
655 				excl_kernel = true;
656 				/*
657 				 * Both cpus and threads are now owned by evlist
658 				 * and will be freed by following perf_evlist__set_maps
659 				 * call. Getting refference to keep them alive.
660 				 */
661 				perf_cpu_map__get(cpus);
662 				perf_thread_map__get(threads);
663 				perf_evlist__set_maps(&evlist->core, NULL, NULL);
664 				evlist__delete(evlist);
665 				evlist = NULL;
666 				continue;
667 			}
668 
669 			if (verbose > 0) {
670 				char errbuf[512];
671 				perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf));
672 				pr_debug("perf_evlist__open() failed!\n%s\n", errbuf);
673 			}
674 
675 			goto out_put;
676 		}
677 		break;
678 	}
679 
680 	ret = perf_evlist__mmap(evlist, UINT_MAX);
681 	if (ret < 0) {
682 		pr_debug("perf_evlist__mmap failed\n");
683 		goto out_put;
684 	}
685 
686 	evlist__enable(evlist);
687 
688 	do_something();
689 
690 	evlist__disable(evlist);
691 
692 	ret = process_events(machine, evlist, &state);
693 	if (ret < 0)
694 		goto out_put;
695 
696 	if (!have_vmlinux && !have_kcore && !try_kcore)
697 		err = TEST_CODE_READING_NO_KERNEL_OBJ;
698 	else if (!have_vmlinux && !try_kcore)
699 		err = TEST_CODE_READING_NO_VMLINUX;
700 	else if (excl_kernel)
701 		err = TEST_CODE_READING_NO_ACCESS;
702 	else
703 		err = TEST_CODE_READING_OK;
704 out_put:
705 	thread__put(thread);
706 out_err:
707 
708 	if (evlist) {
709 		evlist__delete(evlist);
710 	} else {
711 		perf_cpu_map__put(cpus);
712 		perf_thread_map__put(threads);
713 	}
714 	machine__delete_threads(machine);
715 	machine__delete(machine);
716 
717 	return err;
718 }
719 
720 int test__code_reading(struct test *test __maybe_unused, int subtest __maybe_unused)
721 {
722 	int ret;
723 
724 	ret = do_test_code_reading(false);
725 	if (!ret)
726 		ret = do_test_code_reading(true);
727 
728 	switch (ret) {
729 	case TEST_CODE_READING_OK:
730 		return 0;
731 	case TEST_CODE_READING_NO_VMLINUX:
732 		pr_debug("no vmlinux\n");
733 		return 0;
734 	case TEST_CODE_READING_NO_KCORE:
735 		pr_debug("no kcore\n");
736 		return 0;
737 	case TEST_CODE_READING_NO_ACCESS:
738 		pr_debug("no access\n");
739 		return 0;
740 	case TEST_CODE_READING_NO_KERNEL_OBJ:
741 		pr_debug("no kernel obj\n");
742 		return 0;
743 	default:
744 		return -1;
745 	};
746 }
747