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