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