1 // SPDX-License-Identifier: GPL-2.0 2 #include <errno.h> 3 #include <linux/kconfig.h> 4 #include <linux/kernel.h> 5 #include <linux/rbtree.h> 6 #include <linux/types.h> 7 #include <linux/zalloc.h> 8 #include <inttypes.h> 9 #include <stdlib.h> 10 #include <unistd.h> 11 #include <stdio.h> 12 #include <string.h> 13 #include <sys/param.h> 14 #include <sys/utsname.h> 15 #include <perf/cpumap.h> 16 #include <perf/evlist.h> 17 #include <perf/mmap.h> 18 19 #include "debug.h" 20 #include "dso.h" 21 #include "env.h" 22 #include "parse-events.h" 23 #include "evlist.h" 24 #include "evsel.h" 25 #include "thread_map.h" 26 #include "machine.h" 27 #include "map.h" 28 #include "symbol.h" 29 #include "event.h" 30 #include "record.h" 31 #include "util/mmap.h" 32 #include "util/string2.h" 33 #include "util/synthetic-events.h" 34 #include "util/util.h" 35 #include "thread.h" 36 37 #include "tests.h" 38 39 #include <linux/ctype.h> 40 41 #define BUFSZ 1024 42 #define READLEN 128 43 44 struct tested_section { 45 struct rb_node rb_node; 46 u64 addr; 47 char *path; 48 }; 49 50 static bool tested_code_insert_or_exists(const char *path, u64 addr, 51 struct rb_root *tested_sections) 52 { 53 struct rb_node **node = &tested_sections->rb_node; 54 struct rb_node *parent = NULL; 55 struct tested_section *data; 56 57 while (*node) { 58 int cmp; 59 60 parent = *node; 61 data = rb_entry(*node, struct tested_section, rb_node); 62 cmp = strcmp(path, data->path); 63 if (!cmp) { 64 if (addr < data->addr) 65 cmp = -1; 66 else if (addr > data->addr) 67 cmp = 1; 68 else 69 return true; /* already tested */ 70 } 71 72 if (cmp < 0) 73 node = &(*node)->rb_left; 74 else 75 node = &(*node)->rb_right; 76 } 77 78 data = zalloc(sizeof(*data)); 79 if (!data) 80 return true; 81 82 data->addr = addr; 83 data->path = strdup(path); 84 if (!data->path) { 85 free(data); 86 return true; 87 } 88 rb_link_node(&data->rb_node, parent, node); 89 rb_insert_color(&data->rb_node, tested_sections); 90 return false; 91 } 92 93 static void tested_sections__free(struct rb_root *root) 94 { 95 while (!RB_EMPTY_ROOT(root)) { 96 struct rb_node *node = rb_first(root); 97 struct tested_section *ts = rb_entry(node, 98 struct tested_section, 99 rb_node); 100 101 rb_erase(node, root); 102 free(ts->path); 103 free(ts); 104 } 105 } 106 107 static size_t read_objdump_chunk(const char **line, unsigned char **buf, 108 size_t *buf_len) 109 { 110 size_t bytes_read = 0; 111 unsigned char *chunk_start = *buf; 112 113 /* Read bytes */ 114 while (*buf_len > 0) { 115 char c1, c2; 116 117 /* Get 2 hex digits */ 118 c1 = *(*line)++; 119 if (!isxdigit(c1)) 120 break; 121 c2 = *(*line)++; 122 if (!isxdigit(c2)) 123 break; 124 125 /* Store byte and advance buf */ 126 **buf = (hex(c1) << 4) | hex(c2); 127 (*buf)++; 128 (*buf_len)--; 129 bytes_read++; 130 131 /* End of chunk? */ 132 if (isspace(**line)) 133 break; 134 } 135 136 /* 137 * objdump will display raw insn as LE if code endian 138 * is LE and bytes_per_chunk > 1. In that case reverse 139 * the chunk we just read. 140 * 141 * see disassemble_bytes() at binutils/objdump.c for details 142 * how objdump chooses display endian) 143 */ 144 if (bytes_read > 1 && !host_is_bigendian()) { 145 unsigned char *chunk_end = chunk_start + bytes_read - 1; 146 unsigned char tmp; 147 148 while (chunk_start < chunk_end) { 149 tmp = *chunk_start; 150 *chunk_start = *chunk_end; 151 *chunk_end = tmp; 152 chunk_start++; 153 chunk_end--; 154 } 155 } 156 157 return bytes_read; 158 } 159 160 static size_t read_objdump_line(const char *line, unsigned char *buf, 161 size_t buf_len) 162 { 163 const char *p; 164 size_t ret, bytes_read = 0; 165 166 /* Skip to a colon */ 167 p = strchr(line, ':'); 168 if (!p) 169 return 0; 170 p++; 171 172 /* Skip initial spaces */ 173 while (*p) { 174 if (!isspace(*p)) 175 break; 176 p++; 177 } 178 179 do { 180 ret = read_objdump_chunk(&p, &buf, &buf_len); 181 bytes_read += ret; 182 p++; 183 } while (ret > 0); 184 185 /* return number of successfully read bytes */ 186 return bytes_read; 187 } 188 189 static int read_objdump_output(FILE *f, void *buf, size_t *len, u64 start_addr) 190 { 191 char *line = NULL; 192 size_t line_len, off_last = 0; 193 ssize_t ret; 194 int err = 0; 195 u64 addr, last_addr = start_addr; 196 197 while (off_last < *len) { 198 size_t off, read_bytes, written_bytes; 199 unsigned char tmp[BUFSZ]; 200 201 ret = getline(&line, &line_len, f); 202 if (feof(f)) 203 break; 204 if (ret < 0) { 205 pr_debug("getline failed\n"); 206 err = -1; 207 break; 208 } 209 210 /* read objdump data into temporary buffer */ 211 read_bytes = read_objdump_line(line, tmp, sizeof(tmp)); 212 if (!read_bytes) 213 continue; 214 215 if (sscanf(line, "%"PRIx64, &addr) != 1) 216 continue; 217 if (addr < last_addr) { 218 pr_debug("addr going backwards, read beyond section?\n"); 219 break; 220 } 221 last_addr = addr; 222 223 /* copy it from temporary buffer to 'buf' according 224 * to address on current objdump line */ 225 off = addr - start_addr; 226 if (off >= *len) 227 break; 228 written_bytes = MIN(read_bytes, *len - off); 229 memcpy(buf + off, tmp, written_bytes); 230 off_last = off + written_bytes; 231 } 232 233 /* len returns number of bytes that could not be read */ 234 *len -= off_last; 235 236 free(line); 237 238 return err; 239 } 240 241 /* 242 * Only gets GNU objdump version. Returns 0 for llvm-objdump. 243 */ 244 static int objdump_version(void) 245 { 246 size_t line_len; 247 char cmd[PATH_MAX * 2]; 248 char *line = NULL; 249 const char *fmt; 250 FILE *f; 251 int ret; 252 253 int version_tmp, version_num = 0; 254 char *version = 0, *token; 255 256 fmt = "%s --version"; 257 ret = snprintf(cmd, sizeof(cmd), fmt, test_objdump_path); 258 if (ret <= 0 || (size_t)ret >= sizeof(cmd)) 259 return -1; 260 /* Ignore objdump errors */ 261 strcat(cmd, " 2>/dev/null"); 262 f = popen(cmd, "r"); 263 if (!f) { 264 pr_debug("popen failed\n"); 265 return -1; 266 } 267 /* Get first line of objdump --version output */ 268 ret = getline(&line, &line_len, f); 269 pclose(f); 270 if (ret < 0) { 271 pr_debug("getline failed\n"); 272 return -1; 273 } 274 275 token = strsep(&line, " "); 276 if (token != NULL && !strcmp(token, "GNU")) { 277 // version is last part of first line of objdump --version output. 278 while ((token = strsep(&line, " "))) 279 version = token; 280 281 // Convert version into a format we can compare with 282 token = strsep(&version, "."); 283 version_num = atoi(token); 284 if (version_num) 285 version_num *= 10000; 286 287 token = strsep(&version, "."); 288 version_tmp = atoi(token); 289 if (token) 290 version_num += version_tmp * 100; 291 292 token = strsep(&version, "."); 293 version_tmp = atoi(token); 294 if (token) 295 version_num += version_tmp; 296 } 297 298 return version_num; 299 } 300 301 static int read_via_objdump(const char *filename, u64 addr, void *buf, 302 size_t len) 303 { 304 u64 stop_address = addr + len; 305 struct utsname uname_buf; 306 char cmd[PATH_MAX * 2]; 307 const char *fmt; 308 FILE *f; 309 int ret; 310 311 ret = uname(&uname_buf); 312 if (ret) { 313 pr_debug("uname failed\n"); 314 return -1; 315 } 316 317 if (!strncmp(uname_buf.machine, "riscv", 5)) { 318 int version = objdump_version(); 319 320 /* Default to this workaround if version parsing fails */ 321 if (version < 0 || version > 24100) { 322 /* 323 * Starting at riscv objdump version 2.41, dumping in 324 * the middle of an instruction is not supported. riscv 325 * instructions are aligned along 2-byte intervals and 326 * can be either 2-bytes or 4-bytes. This makes it 327 * possible that the stop-address lands in the middle of 328 * a 4-byte instruction. Increase the stop_address by 329 * two to ensure an instruction is not cut in half, but 330 * leave the len as-is so only the expected number of 331 * bytes are collected. 332 */ 333 stop_address += 2; 334 } 335 } 336 337 fmt = "%s -z -d --start-address=0x%"PRIx64" --stop-address=0x%"PRIx64" %s"; 338 ret = snprintf(cmd, sizeof(cmd), fmt, test_objdump_path, addr, stop_address, 339 filename); 340 if (ret <= 0 || (size_t)ret >= sizeof(cmd)) 341 return -1; 342 343 pr_debug("Objdump command is: %s\n", cmd); 344 345 /* Ignore objdump errors */ 346 strcat(cmd, " 2>/dev/null"); 347 348 f = popen(cmd, "r"); 349 if (!f) { 350 pr_debug("popen failed\n"); 351 return -1; 352 } 353 354 ret = read_objdump_output(f, buf, &len, addr); 355 if (len) { 356 pr_debug("objdump read too few bytes: %zd\n", len); 357 if (!ret) 358 ret = len; 359 } 360 361 pclose(f); 362 363 return ret; 364 } 365 366 static void dump_buf(unsigned char *buf, size_t len) 367 { 368 size_t i; 369 370 for (i = 0; i < len; i++) { 371 pr_debug("0x%02x ", buf[i]); 372 if (i % 16 == 15) 373 pr_debug("\n"); 374 } 375 pr_debug("\n"); 376 } 377 378 static int read_object_code(u64 addr, size_t len, u8 cpumode, 379 struct thread *thread, 380 struct rb_root *tested_sections) 381 { 382 struct addr_location al; 383 unsigned char buf1[BUFSZ] = {0}; 384 unsigned char buf2[BUFSZ] = {0}; 385 size_t ret_len; 386 u64 objdump_addr; 387 u64 skip_addr; 388 const char *objdump_name; 389 char decomp_name[KMOD_DECOMP_LEN]; 390 bool decomp = false; 391 int ret, err = 0; 392 struct dso *dso; 393 394 pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr); 395 396 addr_location__init(&al); 397 if (!thread__find_map(thread, cpumode, addr, &al) || !map__dso(al.map)) { 398 if (cpumode == PERF_RECORD_MISC_HYPERVISOR) { 399 pr_debug("Hypervisor address can not be resolved - skipping\n"); 400 goto out; 401 } 402 403 pr_debug("thread__find_map failed\n"); 404 err = -1; 405 goto out; 406 } 407 dso = map__dso(al.map); 408 pr_debug("File is: %s\n", dso__long_name(dso)); 409 410 if (dso__symtab_type(dso) == DSO_BINARY_TYPE__KALLSYMS && !dso__is_kcore(dso)) { 411 pr_debug("Unexpected kernel address - skipping\n"); 412 goto out; 413 } 414 415 /* 416 * Don't retest the same addresses. objdump struggles with kcore - try 417 * each map only once even if the address is different. 418 */ 419 skip_addr = dso__is_kcore(dso) ? map__start(al.map) : al.addr; 420 if (tested_code_insert_or_exists(dso__long_name(dso), skip_addr, 421 tested_sections)) { 422 pr_debug("Already tested %s @ %#"PRIx64" - skipping\n", 423 dso__long_name(dso), skip_addr); 424 goto out; 425 } 426 427 pr_debug("On file address is: %#"PRIx64"\n", al.addr); 428 429 if (len > BUFSZ) 430 len = BUFSZ; 431 432 /* Do not go off the map */ 433 if (addr + len > map__end(al.map)) 434 len = map__end(al.map) - addr; 435 436 /* 437 * Some architectures (ex: powerpc) have stubs (trampolines) in kernel 438 * modules to manage long jumps. Check if the ip offset falls in stubs 439 * sections for kernel modules. And skip module address after text end 440 */ 441 if (dso__is_kmod(dso) && al.addr > dso__text_end(dso)) { 442 pr_debug("skipping the module address %#"PRIx64" after text end\n", al.addr); 443 goto out; 444 } 445 446 /* Read the object code using perf */ 447 ret_len = dso__data_read_offset(dso, maps__machine(thread__maps(thread)), 448 al.addr, buf1, len); 449 if (ret_len != len) { 450 pr_debug("dso__data_read_offset failed\n"); 451 err = -1; 452 goto out; 453 } 454 455 /* 456 * Converting addresses for use by objdump requires more information. 457 * map__load() does that. See map__rip_2objdump() for details. 458 */ 459 if (map__load(al.map)) { 460 err = -1; 461 goto out; 462 } 463 464 objdump_name = dso__long_name(dso); 465 if (dso__needs_decompress(dso)) { 466 if (dso__decompress_kmodule_path(dso, objdump_name, 467 decomp_name, 468 sizeof(decomp_name)) < 0) { 469 pr_debug("decompression failed\n"); 470 err = -1; 471 goto out; 472 } 473 474 /* empty pathname means file wasn't actually compressed */ 475 if (decomp_name[0] != '\0') { 476 decomp = true; 477 objdump_name = decomp_name; 478 } 479 } 480 481 /* Read the object code using objdump */ 482 objdump_addr = map__rip_2objdump(al.map, al.addr); 483 ret = read_via_objdump(objdump_name, objdump_addr, buf2, len); 484 485 if (decomp) 486 unlink(objdump_name); 487 488 if (ret > 0) { 489 /* 490 * The kernel maps are inaccurate - assume objdump is right in 491 * that case. 492 */ 493 if (cpumode == PERF_RECORD_MISC_KERNEL || 494 cpumode == PERF_RECORD_MISC_GUEST_KERNEL) { 495 len -= ret; 496 if (len) { 497 pr_debug("Reducing len to %zu\n", len); 498 } else if (dso__is_kcore(dso)) { 499 /* 500 * objdump cannot handle very large segments 501 * that may be found in kcore. 502 */ 503 pr_debug("objdump failed for kcore"); 504 pr_debug(" - skipping\n"); 505 } else { 506 err = -1; 507 } 508 goto out; 509 } 510 } 511 if (ret < 0) { 512 pr_debug("read_via_objdump failed\n"); 513 err = -1; 514 goto out; 515 } 516 517 /* The results should be identical */ 518 if (memcmp(buf1, buf2, len)) { 519 pr_debug("Bytes read differ from those read by objdump\n"); 520 pr_debug("buf1 (dso):\n"); 521 dump_buf(buf1, len); 522 pr_debug("buf2 (objdump):\n"); 523 dump_buf(buf2, len); 524 err = -1; 525 goto out; 526 } 527 pr_debug("Bytes read match those read by objdump\n"); 528 out: 529 addr_location__exit(&al); 530 return err; 531 } 532 533 static int process_sample_event(struct machine *machine, struct evlist *evlist, 534 union perf_event *event, 535 struct rb_root *tested_sections) 536 { 537 struct perf_sample sample; 538 struct thread *thread; 539 int ret; 540 541 perf_sample__init(&sample, /*all=*/false); 542 ret = evlist__parse_sample(evlist, event, &sample); 543 if (ret) { 544 pr_debug("evlist__parse_sample failed\n"); 545 ret = -1; 546 goto out; 547 } 548 549 thread = machine__findnew_thread(machine, sample.pid, sample.tid); 550 if (!thread) { 551 pr_debug("machine__findnew_thread failed\n"); 552 ret = -1; 553 goto out; 554 } 555 556 ret = read_object_code(sample.ip, READLEN, sample.cpumode, thread, 557 tested_sections); 558 thread__put(thread); 559 out: 560 perf_sample__exit(&sample); 561 return ret; 562 } 563 564 static int process_event(struct machine *machine, struct evlist *evlist, 565 union perf_event *event, struct rb_root *tested_sections) 566 { 567 if (event->header.type == PERF_RECORD_SAMPLE) 568 return process_sample_event(machine, evlist, event, 569 tested_sections); 570 571 if (event->header.type == PERF_RECORD_THROTTLE || 572 event->header.type == PERF_RECORD_UNTHROTTLE) 573 return 0; 574 575 if (event->header.type < PERF_RECORD_MAX) { 576 int ret; 577 578 ret = machine__process_event(machine, event, NULL); 579 if (ret < 0) 580 pr_debug("machine__process_event failed, event type %u\n", 581 event->header.type); 582 return ret; 583 } 584 585 return 0; 586 } 587 588 static int process_events(struct machine *machine, struct evlist *evlist, 589 struct rb_root *tested_sections) 590 { 591 union perf_event *event; 592 struct mmap *md; 593 int i, ret; 594 595 for (i = 0; i < evlist->core.nr_mmaps; i++) { 596 md = &evlist->mmap[i]; 597 if (perf_mmap__read_init(&md->core) < 0) 598 continue; 599 600 while ((event = perf_mmap__read_event(&md->core)) != NULL) { 601 ret = process_event(machine, evlist, event, tested_sections); 602 perf_mmap__consume(&md->core); 603 if (ret < 0) 604 return ret; 605 } 606 perf_mmap__read_done(&md->core); 607 } 608 return 0; 609 } 610 611 static int comp(const void *a, const void *b) 612 { 613 return *(int *)a - *(int *)b; 614 } 615 616 static void do_sort_something(void) 617 { 618 int buf[40960], i; 619 620 for (i = 0; i < (int)ARRAY_SIZE(buf); i++) 621 buf[i] = ARRAY_SIZE(buf) - i - 1; 622 623 qsort(buf, ARRAY_SIZE(buf), sizeof(int), comp); 624 625 for (i = 0; i < (int)ARRAY_SIZE(buf); i++) { 626 if (buf[i] != i) { 627 pr_debug("qsort failed\n"); 628 break; 629 } 630 } 631 } 632 633 static void sort_something(void) 634 { 635 int i; 636 637 for (i = 0; i < 10; i++) 638 do_sort_something(); 639 } 640 641 static void syscall_something(void) 642 { 643 int pipefd[2]; 644 int i; 645 646 for (i = 0; i < 1000; i++) { 647 if (pipe(pipefd) < 0) { 648 pr_debug("pipe failed\n"); 649 break; 650 } 651 close(pipefd[1]); 652 close(pipefd[0]); 653 } 654 } 655 656 static void fs_something(void) 657 { 658 const char *test_file_name = "temp-perf-code-reading-test-file--"; 659 FILE *f; 660 int i; 661 662 for (i = 0; i < 1000; i++) { 663 f = fopen(test_file_name, "w+"); 664 if (f) { 665 fclose(f); 666 unlink(test_file_name); 667 } 668 } 669 } 670 671 static void do_something(void) 672 { 673 fs_something(); 674 675 sort_something(); 676 677 syscall_something(); 678 } 679 680 enum { 681 TEST_CODE_READING_OK, 682 TEST_CODE_READING_NO_VMLINUX, 683 TEST_CODE_READING_NO_KCORE, 684 TEST_CODE_READING_NO_ACCESS, 685 TEST_CODE_READING_NO_KERNEL_OBJ, 686 }; 687 688 static int do_test_code_reading(bool try_kcore) 689 { 690 struct machine *machine; 691 struct thread *thread; 692 struct record_opts opts = { 693 .mmap_pages = UINT_MAX, 694 .user_freq = UINT_MAX, 695 .user_interval = ULLONG_MAX, 696 .freq = 500, 697 .target = { 698 .uses_mmap = true, 699 }, 700 }; 701 struct rb_root tested_sections = RB_ROOT; 702 struct perf_thread_map *threads = NULL; 703 struct perf_cpu_map *cpus = NULL; 704 struct evlist *evlist = NULL; 705 struct evsel *evsel = NULL; 706 int err = -1, ret; 707 pid_t pid; 708 struct map *map; 709 bool have_vmlinux, have_kcore; 710 struct dso *dso; 711 const char *events[] = { "cpu-cycles", "cpu-cycles:u", "cpu-clock", "cpu-clock:u", NULL }; 712 int evidx = 0; 713 struct perf_env host_env; 714 715 pid = getpid(); 716 717 perf_env__init(&host_env); 718 machine = machine__new_host(&host_env); 719 720 ret = machine__create_kernel_maps(machine); 721 if (ret < 0) { 722 pr_debug("machine__create_kernel_maps failed\n"); 723 goto out_err; 724 } 725 726 /* Force the use of kallsyms instead of vmlinux to try kcore */ 727 if (try_kcore) 728 symbol_conf.kallsyms_name = "/proc/kallsyms"; 729 730 /* Load kernel map */ 731 map = machine__kernel_map(machine); 732 ret = map__load(map); 733 if (ret < 0) { 734 pr_debug("map__load failed\n"); 735 goto out_err; 736 } 737 dso = map__dso(map); 738 have_vmlinux = dso__is_vmlinux(dso); 739 have_kcore = dso__is_kcore(dso); 740 741 /* 2nd time through we just try kcore */ 742 if (try_kcore && !have_kcore) 743 return TEST_CODE_READING_NO_KCORE; 744 745 /* No point getting kernel events if there is no kernel object */ 746 if (!have_vmlinux && !have_kcore) 747 evidx++; 748 749 threads = thread_map__new_by_tid(pid); 750 if (!threads) { 751 pr_debug("thread_map__new_by_tid failed\n"); 752 goto out_err; 753 } 754 755 ret = perf_event__synthesize_thread_map(NULL, threads, 756 perf_event__process, machine, 757 true, false); 758 if (ret < 0) { 759 pr_debug("perf_event__synthesize_thread_map failed\n"); 760 goto out_err; 761 } 762 763 thread = machine__findnew_thread(machine, pid, pid); 764 if (!thread) { 765 pr_debug("machine__findnew_thread failed\n"); 766 goto out_put; 767 } 768 769 cpus = perf_cpu_map__new_online_cpus(); 770 if (!cpus) { 771 pr_debug("perf_cpu_map__new failed\n"); 772 goto out_put; 773 } 774 775 while (events[evidx]) { 776 const char *str; 777 778 evlist = evlist__new(); 779 if (!evlist) { 780 pr_debug("evlist__new failed\n"); 781 goto out_put; 782 } 783 784 perf_evlist__set_maps(&evlist->core, cpus, threads); 785 786 str = events[evidx]; 787 pr_debug("Parsing event '%s'\n", str); 788 ret = parse_event(evlist, str); 789 if (ret < 0) { 790 pr_debug("parse_events failed\n"); 791 goto out_put; 792 } 793 794 evlist__config(evlist, &opts, NULL); 795 796 evlist__for_each_entry(evlist, evsel) { 797 evsel->core.attr.comm = 1; 798 evsel->core.attr.disabled = 1; 799 evsel->core.attr.enable_on_exec = 0; 800 } 801 802 ret = evlist__open(evlist); 803 if (ret < 0) { 804 evidx++; 805 806 if (events[evidx] == NULL && verbose > 0) { 807 char errbuf[512]; 808 evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf)); 809 pr_debug("perf_evlist__open() failed!\n%s\n", errbuf); 810 } 811 812 perf_evlist__set_maps(&evlist->core, NULL, NULL); 813 evlist__delete(evlist); 814 evlist = NULL; 815 continue; 816 } 817 break; 818 } 819 820 if (events[evidx] == NULL) 821 goto out_put; 822 823 ret = evlist__mmap(evlist, UINT_MAX); 824 if (ret < 0) { 825 pr_debug("evlist__mmap failed\n"); 826 goto out_put; 827 } 828 829 evlist__enable(evlist); 830 831 do_something(); 832 833 evlist__disable(evlist); 834 835 ret = process_events(machine, evlist, &tested_sections); 836 if (ret < 0) 837 goto out_put; 838 839 if (!have_vmlinux && !have_kcore && !try_kcore) 840 err = TEST_CODE_READING_NO_KERNEL_OBJ; 841 else if (!have_vmlinux && !try_kcore) 842 err = TEST_CODE_READING_NO_VMLINUX; 843 else if (strstr(events[evidx], ":u")) 844 err = TEST_CODE_READING_NO_ACCESS; 845 else 846 err = TEST_CODE_READING_OK; 847 out_put: 848 thread__put(thread); 849 out_err: 850 evlist__delete(evlist); 851 perf_cpu_map__put(cpus); 852 perf_thread_map__put(threads); 853 machine__delete(machine); 854 perf_env__exit(&host_env); 855 tested_sections__free(&tested_sections); 856 857 return err; 858 } 859 860 static int test__code_reading(struct test_suite *test __maybe_unused, int subtest __maybe_unused) 861 { 862 int ret; 863 864 ret = do_test_code_reading(false); 865 if (!ret) 866 ret = do_test_code_reading(true); 867 868 switch (ret) { 869 case TEST_CODE_READING_OK: 870 return 0; 871 case TEST_CODE_READING_NO_VMLINUX: 872 pr_debug("no vmlinux\n"); 873 return 0; 874 case TEST_CODE_READING_NO_KCORE: 875 pr_debug("no kcore\n"); 876 return 0; 877 case TEST_CODE_READING_NO_ACCESS: 878 pr_debug("no access\n"); 879 return 0; 880 case TEST_CODE_READING_NO_KERNEL_OBJ: 881 pr_debug("no kernel obj\n"); 882 return 0; 883 default: 884 return -1; 885 }; 886 } 887 888 DEFINE_SUITE("Object code reading", code_reading); 889