Home | History | Annotate | Download | only in tests
      1 #include <sys/types.h>
      2 #include <stdlib.h>
      3 #include <unistd.h>
      4 #include <stdio.h>
      5 #include <inttypes.h>
      6 #include <ctype.h>
      7 #include <string.h>
      8 
      9 #include "parse-events.h"
     10 #include "evlist.h"
     11 #include "evsel.h"
     12 #include "thread_map.h"
     13 #include "cpumap.h"
     14 #include "machine.h"
     15 #include "event.h"
     16 #include "thread.h"
     17 
     18 #include "tests.h"
     19 
     20 #define BUFSZ	1024
     21 #define READLEN	128
     22 
     23 struct state {
     24 	u64 done[1024];
     25 	size_t done_cnt;
     26 };
     27 
     28 static unsigned int hex(char c)
     29 {
     30 	if (c >= '0' && c <= '9')
     31 		return c - '0';
     32 	if (c >= 'a' && c <= 'f')
     33 		return c - 'a' + 10;
     34 	return c - 'A' + 10;
     35 }
     36 
     37 static void read_objdump_line(const char *line, size_t line_len, void **buf,
     38 			      size_t *len)
     39 {
     40 	const char *p;
     41 	size_t i;
     42 
     43 	/* Skip to a colon */
     44 	p = strchr(line, ':');
     45 	if (!p)
     46 		return;
     47 	i = p + 1 - line;
     48 
     49 	/* Read bytes */
     50 	while (*len) {
     51 		char c1, c2;
     52 
     53 		/* Skip spaces */
     54 		for (; i < line_len; i++) {
     55 			if (!isspace(line[i]))
     56 				break;
     57 		}
     58 		/* Get 2 hex digits */
     59 		if (i >= line_len || !isxdigit(line[i]))
     60 			break;
     61 		c1 = line[i++];
     62 		if (i >= line_len || !isxdigit(line[i]))
     63 			break;
     64 		c2 = line[i++];
     65 		/* Followed by a space */
     66 		if (i < line_len && line[i] && !isspace(line[i]))
     67 			break;
     68 		/* Store byte */
     69 		*(unsigned char *)*buf = (hex(c1) << 4) | hex(c2);
     70 		*buf += 1;
     71 		*len -= 1;
     72 	}
     73 }
     74 
     75 static int read_objdump_output(FILE *f, void **buf, size_t *len)
     76 {
     77 	char *line = NULL;
     78 	size_t line_len;
     79 	ssize_t ret;
     80 	int err = 0;
     81 
     82 	while (1) {
     83 		ret = getline(&line, &line_len, f);
     84 		if (feof(f))
     85 			break;
     86 		if (ret < 0) {
     87 			pr_debug("getline failed\n");
     88 			err = -1;
     89 			break;
     90 		}
     91 		read_objdump_line(line, ret, buf, len);
     92 	}
     93 
     94 	free(line);
     95 
     96 	return err;
     97 }
     98 
     99 static int read_via_objdump(const char *filename, u64 addr, void *buf,
    100 			    size_t len)
    101 {
    102 	char cmd[PATH_MAX * 2];
    103 	const char *fmt;
    104 	FILE *f;
    105 	int ret;
    106 
    107 	fmt = "%s -d --start-address=0x%"PRIx64" --stop-address=0x%"PRIx64" %s";
    108 	ret = snprintf(cmd, sizeof(cmd), fmt, "objdump", addr, addr + len,
    109 		       filename);
    110 	if (ret <= 0 || (size_t)ret >= sizeof(cmd))
    111 		return -1;
    112 
    113 	pr_debug("Objdump command is: %s\n", cmd);
    114 
    115 	/* Ignore objdump errors */
    116 	strcat(cmd, " 2>/dev/null");
    117 
    118 	f = popen(cmd, "r");
    119 	if (!f) {
    120 		pr_debug("popen failed\n");
    121 		return -1;
    122 	}
    123 
    124 	ret = read_objdump_output(f, &buf, &len);
    125 	if (len) {
    126 		pr_debug("objdump read too few bytes\n");
    127 		if (!ret)
    128 			ret = len;
    129 	}
    130 
    131 	pclose(f);
    132 
    133 	return ret;
    134 }
    135 
    136 static int read_object_code(u64 addr, size_t len, u8 cpumode,
    137 			    struct thread *thread, struct machine *machine,
    138 			    struct state *state)
    139 {
    140 	struct addr_location al;
    141 	unsigned char buf1[BUFSZ];
    142 	unsigned char buf2[BUFSZ];
    143 	size_t ret_len;
    144 	u64 objdump_addr;
    145 	int ret;
    146 
    147 	pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr);
    148 
    149 	thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, addr,
    150 			      &al);
    151 	if (!al.map || !al.map->dso) {
    152 		pr_debug("thread__find_addr_map failed\n");
    153 		return -1;
    154 	}
    155 
    156 	pr_debug("File is: %s\n", al.map->dso->long_name);
    157 
    158 	if (al.map->dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
    159 	    !dso__is_kcore(al.map->dso)) {
    160 		pr_debug("Unexpected kernel address - skipping\n");
    161 		return 0;
    162 	}
    163 
    164 	pr_debug("On file address is: %#"PRIx64"\n", al.addr);
    165 
    166 	if (len > BUFSZ)
    167 		len = BUFSZ;
    168 
    169 	/* Do not go off the map */
    170 	if (addr + len > al.map->end)
    171 		len = al.map->end - addr;
    172 
    173 	/* Read the object code using perf */
    174 	ret_len = dso__data_read_offset(al.map->dso, machine, al.addr, buf1,
    175 					len);
    176 	if (ret_len != len) {
    177 		pr_debug("dso__data_read_offset failed\n");
    178 		return -1;
    179 	}
    180 
    181 	/*
    182 	 * Converting addresses for use by objdump requires more information.
    183 	 * map__load() does that.  See map__rip_2objdump() for details.
    184 	 */
    185 	if (map__load(al.map, NULL))
    186 		return -1;
    187 
    188 	/* objdump struggles with kcore - try each map only once */
    189 	if (dso__is_kcore(al.map->dso)) {
    190 		size_t d;
    191 
    192 		for (d = 0; d < state->done_cnt; d++) {
    193 			if (state->done[d] == al.map->start) {
    194 				pr_debug("kcore map tested already");
    195 				pr_debug(" - skipping\n");
    196 				return 0;
    197 			}
    198 		}
    199 		if (state->done_cnt >= ARRAY_SIZE(state->done)) {
    200 			pr_debug("Too many kcore maps - skipping\n");
    201 			return 0;
    202 		}
    203 		state->done[state->done_cnt++] = al.map->start;
    204 	}
    205 
    206 	/* Read the object code using objdump */
    207 	objdump_addr = map__rip_2objdump(al.map, al.addr);
    208 	ret = read_via_objdump(al.map->dso->long_name, objdump_addr, buf2, len);
    209 	if (ret > 0) {
    210 		/*
    211 		 * The kernel maps are inaccurate - assume objdump is right in
    212 		 * that case.
    213 		 */
    214 		if (cpumode == PERF_RECORD_MISC_KERNEL ||
    215 		    cpumode == PERF_RECORD_MISC_GUEST_KERNEL) {
    216 			len -= ret;
    217 			if (len) {
    218 				pr_debug("Reducing len to %zu\n", len);
    219 			} else if (dso__is_kcore(al.map->dso)) {
    220 				/*
    221 				 * objdump cannot handle very large segments
    222 				 * that may be found in kcore.
    223 				 */
    224 				pr_debug("objdump failed for kcore");
    225 				pr_debug(" - skipping\n");
    226 				return 0;
    227 			} else {
    228 				return -1;
    229 			}
    230 		}
    231 	}
    232 	if (ret < 0) {
    233 		pr_debug("read_via_objdump failed\n");
    234 		return -1;
    235 	}
    236 
    237 	/* The results should be identical */
    238 	if (memcmp(buf1, buf2, len)) {
    239 		pr_debug("Bytes read differ from those read by objdump\n");
    240 		return -1;
    241 	}
    242 	pr_debug("Bytes read match those read by objdump\n");
    243 
    244 	return 0;
    245 }
    246 
    247 static int process_sample_event(struct machine *machine,
    248 				struct perf_evlist *evlist,
    249 				union perf_event *event, struct state *state)
    250 {
    251 	struct perf_sample sample;
    252 	struct thread *thread;
    253 	u8 cpumode;
    254 
    255 	if (perf_evlist__parse_sample(evlist, event, &sample)) {
    256 		pr_debug("perf_evlist__parse_sample failed\n");
    257 		return -1;
    258 	}
    259 
    260 	thread = machine__findnew_thread(machine, sample.pid, sample.pid);
    261 	if (!thread) {
    262 		pr_debug("machine__findnew_thread failed\n");
    263 		return -1;
    264 	}
    265 
    266 	cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
    267 
    268 	return read_object_code(sample.ip, READLEN, cpumode, thread, machine,
    269 				state);
    270 }
    271 
    272 static int process_event(struct machine *machine, struct perf_evlist *evlist,
    273 			 union perf_event *event, struct state *state)
    274 {
    275 	if (event->header.type == PERF_RECORD_SAMPLE)
    276 		return process_sample_event(machine, evlist, event, state);
    277 
    278 	if (event->header.type < PERF_RECORD_MAX)
    279 		return machine__process_event(machine, event);
    280 
    281 	return 0;
    282 }
    283 
    284 static int process_events(struct machine *machine, struct perf_evlist *evlist,
    285 			  struct state *state)
    286 {
    287 	union perf_event *event;
    288 	int i, ret;
    289 
    290 	for (i = 0; i < evlist->nr_mmaps; i++) {
    291 		while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
    292 			ret = process_event(machine, evlist, event, state);
    293 			perf_evlist__mmap_consume(evlist, i);
    294 			if (ret < 0)
    295 				return ret;
    296 		}
    297 	}
    298 	return 0;
    299 }
    300 
    301 static int comp(const void *a, const void *b)
    302 {
    303 	return *(int *)a - *(int *)b;
    304 }
    305 
    306 static void do_sort_something(void)
    307 {
    308 	int buf[40960], i;
    309 
    310 	for (i = 0; i < (int)ARRAY_SIZE(buf); i++)
    311 		buf[i] = ARRAY_SIZE(buf) - i - 1;
    312 
    313 	qsort(buf, ARRAY_SIZE(buf), sizeof(int), comp);
    314 
    315 	for (i = 0; i < (int)ARRAY_SIZE(buf); i++) {
    316 		if (buf[i] != i) {
    317 			pr_debug("qsort failed\n");
    318 			break;
    319 		}
    320 	}
    321 }
    322 
    323 static void sort_something(void)
    324 {
    325 	int i;
    326 
    327 	for (i = 0; i < 10; i++)
    328 		do_sort_something();
    329 }
    330 
    331 static void syscall_something(void)
    332 {
    333 	int pipefd[2];
    334 	int i;
    335 
    336 	for (i = 0; i < 1000; i++) {
    337 		if (pipe(pipefd) < 0) {
    338 			pr_debug("pipe failed\n");
    339 			break;
    340 		}
    341 		close(pipefd[1]);
    342 		close(pipefd[0]);
    343 	}
    344 }
    345 
    346 static void fs_something(void)
    347 {
    348 	const char *test_file_name = "temp-perf-code-reading-test-file--";
    349 	FILE *f;
    350 	int i;
    351 
    352 	for (i = 0; i < 1000; i++) {
    353 		f = fopen(test_file_name, "w+");
    354 		if (f) {
    355 			fclose(f);
    356 			unlink(test_file_name);
    357 		}
    358 	}
    359 }
    360 
    361 static void do_something(void)
    362 {
    363 	fs_something();
    364 
    365 	sort_something();
    366 
    367 	syscall_something();
    368 }
    369 
    370 enum {
    371 	TEST_CODE_READING_OK,
    372 	TEST_CODE_READING_NO_VMLINUX,
    373 	TEST_CODE_READING_NO_KCORE,
    374 	TEST_CODE_READING_NO_ACCESS,
    375 	TEST_CODE_READING_NO_KERNEL_OBJ,
    376 };
    377 
    378 static int do_test_code_reading(bool try_kcore)
    379 {
    380 	struct machines machines;
    381 	struct machine *machine;
    382 	struct thread *thread;
    383 	struct perf_record_opts opts = {
    384 		.mmap_pages	     = UINT_MAX,
    385 		.user_freq	     = UINT_MAX,
    386 		.user_interval	     = ULLONG_MAX,
    387 		.freq		     = 4000,
    388 		.target		     = {
    389 			.uses_mmap   = true,
    390 		},
    391 	};
    392 	struct state state = {
    393 		.done_cnt = 0,
    394 	};
    395 	struct thread_map *threads = NULL;
    396 	struct cpu_map *cpus = NULL;
    397 	struct perf_evlist *evlist = NULL;
    398 	struct perf_evsel *evsel = NULL;
    399 	int err = -1, ret;
    400 	pid_t pid;
    401 	struct map *map;
    402 	bool have_vmlinux, have_kcore, excl_kernel = false;
    403 
    404 	pid = getpid();
    405 
    406 	machines__init(&machines);
    407 	machine = &machines.host;
    408 
    409 	ret = machine__create_kernel_maps(machine);
    410 	if (ret < 0) {
    411 		pr_debug("machine__create_kernel_maps failed\n");
    412 		goto out_err;
    413 	}
    414 
    415 	/* Force the use of kallsyms instead of vmlinux to try kcore */
    416 	if (try_kcore)
    417 		symbol_conf.kallsyms_name = "/proc/kallsyms";
    418 
    419 	/* Load kernel map */
    420 	map = machine->vmlinux_maps[MAP__FUNCTION];
    421 	ret = map__load(map, NULL);
    422 	if (ret < 0) {
    423 		pr_debug("map__load failed\n");
    424 		goto out_err;
    425 	}
    426 	have_vmlinux = dso__is_vmlinux(map->dso);
    427 	have_kcore = dso__is_kcore(map->dso);
    428 
    429 	/* 2nd time through we just try kcore */
    430 	if (try_kcore && !have_kcore)
    431 		return TEST_CODE_READING_NO_KCORE;
    432 
    433 	/* No point getting kernel events if there is no kernel object */
    434 	if (!have_vmlinux && !have_kcore)
    435 		excl_kernel = true;
    436 
    437 	threads = thread_map__new_by_tid(pid);
    438 	if (!threads) {
    439 		pr_debug("thread_map__new_by_tid failed\n");
    440 		goto out_err;
    441 	}
    442 
    443 	ret = perf_event__synthesize_thread_map(NULL, threads,
    444 						perf_event__process, machine);
    445 	if (ret < 0) {
    446 		pr_debug("perf_event__synthesize_thread_map failed\n");
    447 		goto out_err;
    448 	}
    449 
    450 	thread = machine__findnew_thread(machine, pid, pid);
    451 	if (!thread) {
    452 		pr_debug("machine__findnew_thread failed\n");
    453 		goto out_err;
    454 	}
    455 
    456 	cpus = cpu_map__new(NULL);
    457 	if (!cpus) {
    458 		pr_debug("cpu_map__new failed\n");
    459 		goto out_err;
    460 	}
    461 
    462 	while (1) {
    463 		const char *str;
    464 
    465 		evlist = perf_evlist__new();
    466 		if (!evlist) {
    467 			pr_debug("perf_evlist__new failed\n");
    468 			goto out_err;
    469 		}
    470 
    471 		perf_evlist__set_maps(evlist, cpus, threads);
    472 
    473 		if (excl_kernel)
    474 			str = "cycles:u";
    475 		else
    476 			str = "cycles";
    477 		pr_debug("Parsing event '%s'\n", str);
    478 		ret = parse_events(evlist, str);
    479 		if (ret < 0) {
    480 			pr_debug("parse_events failed\n");
    481 			goto out_err;
    482 		}
    483 
    484 		perf_evlist__config(evlist, &opts);
    485 
    486 		evsel = perf_evlist__first(evlist);
    487 
    488 		evsel->attr.comm = 1;
    489 		evsel->attr.disabled = 1;
    490 		evsel->attr.enable_on_exec = 0;
    491 
    492 		ret = perf_evlist__open(evlist);
    493 		if (ret < 0) {
    494 			if (!excl_kernel) {
    495 				excl_kernel = true;
    496 				perf_evlist__delete(evlist);
    497 				evlist = NULL;
    498 				continue;
    499 			}
    500 			pr_debug("perf_evlist__open failed\n");
    501 			goto out_err;
    502 		}
    503 		break;
    504 	}
    505 
    506 	ret = perf_evlist__mmap(evlist, UINT_MAX, false);
    507 	if (ret < 0) {
    508 		pr_debug("perf_evlist__mmap failed\n");
    509 		goto out_err;
    510 	}
    511 
    512 	perf_evlist__enable(evlist);
    513 
    514 	do_something();
    515 
    516 	perf_evlist__disable(evlist);
    517 
    518 	ret = process_events(machine, evlist, &state);
    519 	if (ret < 0)
    520 		goto out_err;
    521 
    522 	if (!have_vmlinux && !have_kcore && !try_kcore)
    523 		err = TEST_CODE_READING_NO_KERNEL_OBJ;
    524 	else if (!have_vmlinux && !try_kcore)
    525 		err = TEST_CODE_READING_NO_VMLINUX;
    526 	else if (excl_kernel)
    527 		err = TEST_CODE_READING_NO_ACCESS;
    528 	else
    529 		err = TEST_CODE_READING_OK;
    530 out_err:
    531 	if (evlist) {
    532 		perf_evlist__munmap(evlist);
    533 		perf_evlist__close(evlist);
    534 		perf_evlist__delete(evlist);
    535 	}
    536 	if (cpus)
    537 		cpu_map__delete(cpus);
    538 	if (threads)
    539 		thread_map__delete(threads);
    540 	machines__destroy_kernel_maps(&machines);
    541 	machine__delete_threads(machine);
    542 	machines__exit(&machines);
    543 
    544 	return err;
    545 }
    546 
    547 int test__code_reading(void)
    548 {
    549 	int ret;
    550 
    551 	ret = do_test_code_reading(false);
    552 	if (!ret)
    553 		ret = do_test_code_reading(true);
    554 
    555 	switch (ret) {
    556 	case TEST_CODE_READING_OK:
    557 		return 0;
    558 	case TEST_CODE_READING_NO_VMLINUX:
    559 		fprintf(stderr, " (no vmlinux)");
    560 		return 0;
    561 	case TEST_CODE_READING_NO_KCORE:
    562 		fprintf(stderr, " (no kcore)");
    563 		return 0;
    564 	case TEST_CODE_READING_NO_ACCESS:
    565 		fprintf(stderr, " (no access)");
    566 		return 0;
    567 	case TEST_CODE_READING_NO_KERNEL_OBJ:
    568 		fprintf(stderr, " (no kernel obj)");
    569 		return 0;
    570 	default:
    571 		return -1;
    572 	};
    573 }
    574