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