0001
0002 #include <errno.h>
0003 #include <linux/kernel.h>
0004 #include <linux/types.h>
0005 #include <inttypes.h>
0006 #include <stdlib.h>
0007 #include <unistd.h>
0008 #include <stdio.h>
0009 #include <string.h>
0010 #include <sys/param.h>
0011 #include <perf/cpumap.h>
0012 #include <perf/evlist.h>
0013 #include <perf/mmap.h>
0014
0015 #include "debug.h"
0016 #include "dso.h"
0017 #include "env.h"
0018 #include "parse-events.h"
0019 #include "trace-event.h"
0020 #include "evlist.h"
0021 #include "evsel.h"
0022 #include "thread_map.h"
0023 #include "machine.h"
0024 #include "map.h"
0025 #include "symbol.h"
0026 #include "event.h"
0027 #include "record.h"
0028 #include "util/mmap.h"
0029 #include "util/string2.h"
0030 #include "util/synthetic-events.h"
0031 #include "thread.h"
0032
0033 #include "tests.h"
0034
0035 #include <linux/ctype.h>
0036
0037 #define BUFSZ 1024
0038 #define READLEN 128
0039
0040 struct state {
0041 u64 done[1024];
0042 size_t done_cnt;
0043 };
0044
0045 static size_t read_objdump_chunk(const char **line, unsigned char **buf,
0046 size_t *buf_len)
0047 {
0048 size_t bytes_read = 0;
0049 unsigned char *chunk_start = *buf;
0050
0051
0052 while (*buf_len > 0) {
0053 char c1, c2;
0054
0055
0056 c1 = *(*line)++;
0057 if (!isxdigit(c1))
0058 break;
0059 c2 = *(*line)++;
0060 if (!isxdigit(c2))
0061 break;
0062
0063
0064 **buf = (hex(c1) << 4) | hex(c2);
0065 (*buf)++;
0066 (*buf_len)--;
0067 bytes_read++;
0068
0069
0070 if (isspace(**line))
0071 break;
0072 }
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082 if (bytes_read > 1 && !bigendian()) {
0083 unsigned char *chunk_end = chunk_start + bytes_read - 1;
0084 unsigned char tmp;
0085
0086 while (chunk_start < chunk_end) {
0087 tmp = *chunk_start;
0088 *chunk_start = *chunk_end;
0089 *chunk_end = tmp;
0090 chunk_start++;
0091 chunk_end--;
0092 }
0093 }
0094
0095 return bytes_read;
0096 }
0097
0098 static size_t read_objdump_line(const char *line, unsigned char *buf,
0099 size_t buf_len)
0100 {
0101 const char *p;
0102 size_t ret, bytes_read = 0;
0103
0104
0105 p = strchr(line, ':');
0106 if (!p)
0107 return 0;
0108 p++;
0109
0110
0111 while (*p) {
0112 if (!isspace(*p))
0113 break;
0114 p++;
0115 }
0116
0117 do {
0118 ret = read_objdump_chunk(&p, &buf, &buf_len);
0119 bytes_read += ret;
0120 p++;
0121 } while (ret > 0);
0122
0123
0124 return bytes_read;
0125 }
0126
0127 static int read_objdump_output(FILE *f, void *buf, size_t *len, u64 start_addr)
0128 {
0129 char *line = NULL;
0130 size_t line_len, off_last = 0;
0131 ssize_t ret;
0132 int err = 0;
0133 u64 addr, last_addr = start_addr;
0134
0135 while (off_last < *len) {
0136 size_t off, read_bytes, written_bytes;
0137 unsigned char tmp[BUFSZ];
0138
0139 ret = getline(&line, &line_len, f);
0140 if (feof(f))
0141 break;
0142 if (ret < 0) {
0143 pr_debug("getline failed\n");
0144 err = -1;
0145 break;
0146 }
0147
0148
0149 read_bytes = read_objdump_line(line, tmp, sizeof(tmp));
0150 if (!read_bytes)
0151 continue;
0152
0153 if (sscanf(line, "%"PRIx64, &addr) != 1)
0154 continue;
0155 if (addr < last_addr) {
0156 pr_debug("addr going backwards, read beyond section?\n");
0157 break;
0158 }
0159 last_addr = addr;
0160
0161
0162
0163 off = addr - start_addr;
0164 if (off >= *len)
0165 break;
0166 written_bytes = MIN(read_bytes, *len - off);
0167 memcpy(buf + off, tmp, written_bytes);
0168 off_last = off + written_bytes;
0169 }
0170
0171
0172 *len -= off_last;
0173
0174 free(line);
0175
0176 return err;
0177 }
0178
0179 static int read_via_objdump(const char *filename, u64 addr, void *buf,
0180 size_t len)
0181 {
0182 char cmd[PATH_MAX * 2];
0183 const char *fmt;
0184 FILE *f;
0185 int ret;
0186
0187 fmt = "%s -z -d --start-address=0x%"PRIx64" --stop-address=0x%"PRIx64" %s";
0188 ret = snprintf(cmd, sizeof(cmd), fmt, "objdump", addr, addr + len,
0189 filename);
0190 if (ret <= 0 || (size_t)ret >= sizeof(cmd))
0191 return -1;
0192
0193 pr_debug("Objdump command is: %s\n", cmd);
0194
0195
0196 strcat(cmd, " 2>/dev/null");
0197
0198 f = popen(cmd, "r");
0199 if (!f) {
0200 pr_debug("popen failed\n");
0201 return -1;
0202 }
0203
0204 ret = read_objdump_output(f, buf, &len, addr);
0205 if (len) {
0206 pr_debug("objdump read too few bytes: %zd\n", len);
0207 if (!ret)
0208 ret = len;
0209 }
0210
0211 pclose(f);
0212
0213 return ret;
0214 }
0215
0216 static void dump_buf(unsigned char *buf, size_t len)
0217 {
0218 size_t i;
0219
0220 for (i = 0; i < len; i++) {
0221 pr_debug("0x%02x ", buf[i]);
0222 if (i % 16 == 15)
0223 pr_debug("\n");
0224 }
0225 pr_debug("\n");
0226 }
0227
0228 static int read_object_code(u64 addr, size_t len, u8 cpumode,
0229 struct thread *thread, struct state *state)
0230 {
0231 struct addr_location al;
0232 unsigned char buf1[BUFSZ] = {0};
0233 unsigned char buf2[BUFSZ] = {0};
0234 size_t ret_len;
0235 u64 objdump_addr;
0236 const char *objdump_name;
0237 char decomp_name[KMOD_DECOMP_LEN];
0238 bool decomp = false;
0239 int ret;
0240
0241 pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr);
0242
0243 if (!thread__find_map(thread, cpumode, addr, &al) || !al.map->dso) {
0244 if (cpumode == PERF_RECORD_MISC_HYPERVISOR) {
0245 pr_debug("Hypervisor address can not be resolved - skipping\n");
0246 return 0;
0247 }
0248
0249 pr_debug("thread__find_map failed\n");
0250 return -1;
0251 }
0252
0253 pr_debug("File is: %s\n", al.map->dso->long_name);
0254
0255 if (al.map->dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
0256 !dso__is_kcore(al.map->dso)) {
0257 pr_debug("Unexpected kernel address - skipping\n");
0258 return 0;
0259 }
0260
0261 pr_debug("On file address is: %#"PRIx64"\n", al.addr);
0262
0263 if (len > BUFSZ)
0264 len = BUFSZ;
0265
0266
0267 if (addr + len > al.map->end)
0268 len = al.map->end - addr;
0269
0270
0271 ret_len = dso__data_read_offset(al.map->dso, thread->maps->machine,
0272 al.addr, buf1, len);
0273 if (ret_len != len) {
0274 pr_debug("dso__data_read_offset failed\n");
0275 return -1;
0276 }
0277
0278
0279
0280
0281
0282 if (map__load(al.map))
0283 return -1;
0284
0285
0286 if (dso__is_kcore(al.map->dso)) {
0287 size_t d;
0288
0289 for (d = 0; d < state->done_cnt; d++) {
0290 if (state->done[d] == al.map->start) {
0291 pr_debug("kcore map tested already");
0292 pr_debug(" - skipping\n");
0293 return 0;
0294 }
0295 }
0296 if (state->done_cnt >= ARRAY_SIZE(state->done)) {
0297 pr_debug("Too many kcore maps - skipping\n");
0298 return 0;
0299 }
0300 state->done[state->done_cnt++] = al.map->start;
0301 }
0302
0303 objdump_name = al.map->dso->long_name;
0304 if (dso__needs_decompress(al.map->dso)) {
0305 if (dso__decompress_kmodule_path(al.map->dso, objdump_name,
0306 decomp_name,
0307 sizeof(decomp_name)) < 0) {
0308 pr_debug("decompression failed\n");
0309 return -1;
0310 }
0311
0312 decomp = true;
0313 objdump_name = decomp_name;
0314 }
0315
0316
0317 objdump_addr = map__rip_2objdump(al.map, al.addr);
0318 ret = read_via_objdump(objdump_name, objdump_addr, buf2, len);
0319
0320 if (decomp)
0321 unlink(objdump_name);
0322
0323 if (ret > 0) {
0324
0325
0326
0327
0328 if (cpumode == PERF_RECORD_MISC_KERNEL ||
0329 cpumode == PERF_RECORD_MISC_GUEST_KERNEL) {
0330 len -= ret;
0331 if (len) {
0332 pr_debug("Reducing len to %zu\n", len);
0333 } else if (dso__is_kcore(al.map->dso)) {
0334
0335
0336
0337
0338 pr_debug("objdump failed for kcore");
0339 pr_debug(" - skipping\n");
0340 return 0;
0341 } else {
0342 return -1;
0343 }
0344 }
0345 }
0346 if (ret < 0) {
0347 pr_debug("read_via_objdump failed\n");
0348 return -1;
0349 }
0350
0351
0352 if (memcmp(buf1, buf2, len)) {
0353 pr_debug("Bytes read differ from those read by objdump\n");
0354 pr_debug("buf1 (dso):\n");
0355 dump_buf(buf1, len);
0356 pr_debug("buf2 (objdump):\n");
0357 dump_buf(buf2, len);
0358 return -1;
0359 }
0360 pr_debug("Bytes read match those read by objdump\n");
0361
0362 return 0;
0363 }
0364
0365 static int process_sample_event(struct machine *machine,
0366 struct evlist *evlist,
0367 union perf_event *event, struct state *state)
0368 {
0369 struct perf_sample sample;
0370 struct thread *thread;
0371 int ret;
0372
0373 if (evlist__parse_sample(evlist, event, &sample)) {
0374 pr_debug("evlist__parse_sample failed\n");
0375 return -1;
0376 }
0377
0378 thread = machine__findnew_thread(machine, sample.pid, sample.tid);
0379 if (!thread) {
0380 pr_debug("machine__findnew_thread failed\n");
0381 return -1;
0382 }
0383
0384 ret = read_object_code(sample.ip, READLEN, sample.cpumode, thread, state);
0385 thread__put(thread);
0386 return ret;
0387 }
0388
0389 static int process_event(struct machine *machine, struct evlist *evlist,
0390 union perf_event *event, struct state *state)
0391 {
0392 if (event->header.type == PERF_RECORD_SAMPLE)
0393 return process_sample_event(machine, evlist, event, state);
0394
0395 if (event->header.type == PERF_RECORD_THROTTLE ||
0396 event->header.type == PERF_RECORD_UNTHROTTLE)
0397 return 0;
0398
0399 if (event->header.type < PERF_RECORD_MAX) {
0400 int ret;
0401
0402 ret = machine__process_event(machine, event, NULL);
0403 if (ret < 0)
0404 pr_debug("machine__process_event failed, event type %u\n",
0405 event->header.type);
0406 return ret;
0407 }
0408
0409 return 0;
0410 }
0411
0412 static int process_events(struct machine *machine, struct evlist *evlist,
0413 struct state *state)
0414 {
0415 union perf_event *event;
0416 struct mmap *md;
0417 int i, ret;
0418
0419 for (i = 0; i < evlist->core.nr_mmaps; i++) {
0420 md = &evlist->mmap[i];
0421 if (perf_mmap__read_init(&md->core) < 0)
0422 continue;
0423
0424 while ((event = perf_mmap__read_event(&md->core)) != NULL) {
0425 ret = process_event(machine, evlist, event, state);
0426 perf_mmap__consume(&md->core);
0427 if (ret < 0)
0428 return ret;
0429 }
0430 perf_mmap__read_done(&md->core);
0431 }
0432 return 0;
0433 }
0434
0435 static int comp(const void *a, const void *b)
0436 {
0437 return *(int *)a - *(int *)b;
0438 }
0439
0440 static void do_sort_something(void)
0441 {
0442 int buf[40960], i;
0443
0444 for (i = 0; i < (int)ARRAY_SIZE(buf); i++)
0445 buf[i] = ARRAY_SIZE(buf) - i - 1;
0446
0447 qsort(buf, ARRAY_SIZE(buf), sizeof(int), comp);
0448
0449 for (i = 0; i < (int)ARRAY_SIZE(buf); i++) {
0450 if (buf[i] != i) {
0451 pr_debug("qsort failed\n");
0452 break;
0453 }
0454 }
0455 }
0456
0457 static void sort_something(void)
0458 {
0459 int i;
0460
0461 for (i = 0; i < 10; i++)
0462 do_sort_something();
0463 }
0464
0465 static void syscall_something(void)
0466 {
0467 int pipefd[2];
0468 int i;
0469
0470 for (i = 0; i < 1000; i++) {
0471 if (pipe(pipefd) < 0) {
0472 pr_debug("pipe failed\n");
0473 break;
0474 }
0475 close(pipefd[1]);
0476 close(pipefd[0]);
0477 }
0478 }
0479
0480 static void fs_something(void)
0481 {
0482 const char *test_file_name = "temp-perf-code-reading-test-file--";
0483 FILE *f;
0484 int i;
0485
0486 for (i = 0; i < 1000; i++) {
0487 f = fopen(test_file_name, "w+");
0488 if (f) {
0489 fclose(f);
0490 unlink(test_file_name);
0491 }
0492 }
0493 }
0494
0495 #ifdef __s390x__
0496 #include "header.h" // for get_cpuid()
0497 #endif
0498
0499 static const char *do_determine_event(bool excl_kernel)
0500 {
0501 const char *event = excl_kernel ? "cycles:u" : "cycles";
0502
0503 #ifdef __s390x__
0504 char cpuid[128], model[16], model_c[16], cpum_cf_v[16];
0505 unsigned int family;
0506 int ret, cpum_cf_a;
0507
0508 if (get_cpuid(cpuid, sizeof(cpuid)))
0509 goto out_clocks;
0510 ret = sscanf(cpuid, "%*[^,],%u,%[^,],%[^,],%[^,],%x", &family, model_c,
0511 model, cpum_cf_v, &cpum_cf_a);
0512 if (ret != 5)
0513 goto out_clocks;
0514 if (excl_kernel && (cpum_cf_a & 4))
0515 return event;
0516 if (!excl_kernel && (cpum_cf_a & 2))
0517 return event;
0518
0519
0520 out_clocks:
0521 event = excl_kernel ? "cpu-clock:u" : "cpu-clock";
0522
0523 #endif
0524 return event;
0525 }
0526
0527 static void do_something(void)
0528 {
0529 fs_something();
0530
0531 sort_something();
0532
0533 syscall_something();
0534 }
0535
0536 enum {
0537 TEST_CODE_READING_OK,
0538 TEST_CODE_READING_NO_VMLINUX,
0539 TEST_CODE_READING_NO_KCORE,
0540 TEST_CODE_READING_NO_ACCESS,
0541 TEST_CODE_READING_NO_KERNEL_OBJ,
0542 };
0543
0544 static int do_test_code_reading(bool try_kcore)
0545 {
0546 struct machine *machine;
0547 struct thread *thread;
0548 struct record_opts opts = {
0549 .mmap_pages = UINT_MAX,
0550 .user_freq = UINT_MAX,
0551 .user_interval = ULLONG_MAX,
0552 .freq = 500,
0553 .target = {
0554 .uses_mmap = true,
0555 },
0556 };
0557 struct state state = {
0558 .done_cnt = 0,
0559 };
0560 struct perf_thread_map *threads = NULL;
0561 struct perf_cpu_map *cpus = NULL;
0562 struct evlist *evlist = NULL;
0563 struct evsel *evsel = NULL;
0564 int err = -1, ret;
0565 pid_t pid;
0566 struct map *map;
0567 bool have_vmlinux, have_kcore, excl_kernel = false;
0568
0569 pid = getpid();
0570
0571 machine = machine__new_host();
0572 machine->env = &perf_env;
0573
0574 ret = machine__create_kernel_maps(machine);
0575 if (ret < 0) {
0576 pr_debug("machine__create_kernel_maps failed\n");
0577 goto out_err;
0578 }
0579
0580
0581 if (try_kcore)
0582 symbol_conf.kallsyms_name = "/proc/kallsyms";
0583
0584
0585 map = machine__kernel_map(machine);
0586 ret = map__load(map);
0587 if (ret < 0) {
0588 pr_debug("map__load failed\n");
0589 goto out_err;
0590 }
0591 have_vmlinux = dso__is_vmlinux(map->dso);
0592 have_kcore = dso__is_kcore(map->dso);
0593
0594
0595 if (try_kcore && !have_kcore)
0596 return TEST_CODE_READING_NO_KCORE;
0597
0598
0599 if (!have_vmlinux && !have_kcore)
0600 excl_kernel = true;
0601
0602 threads = thread_map__new_by_tid(pid);
0603 if (!threads) {
0604 pr_debug("thread_map__new_by_tid failed\n");
0605 goto out_err;
0606 }
0607
0608 ret = perf_event__synthesize_thread_map(NULL, threads,
0609 perf_event__process, machine,
0610 true, false);
0611 if (ret < 0) {
0612 pr_debug("perf_event__synthesize_thread_map failed\n");
0613 goto out_err;
0614 }
0615
0616 thread = machine__findnew_thread(machine, pid, pid);
0617 if (!thread) {
0618 pr_debug("machine__findnew_thread failed\n");
0619 goto out_put;
0620 }
0621
0622 cpus = perf_cpu_map__new(NULL);
0623 if (!cpus) {
0624 pr_debug("perf_cpu_map__new failed\n");
0625 goto out_put;
0626 }
0627
0628 while (1) {
0629 const char *str;
0630
0631 evlist = evlist__new();
0632 if (!evlist) {
0633 pr_debug("evlist__new failed\n");
0634 goto out_put;
0635 }
0636
0637 perf_evlist__set_maps(&evlist->core, cpus, threads);
0638
0639 str = do_determine_event(excl_kernel);
0640 pr_debug("Parsing event '%s'\n", str);
0641 ret = parse_event(evlist, str);
0642 if (ret < 0) {
0643 pr_debug("parse_events failed\n");
0644 goto out_put;
0645 }
0646
0647 evlist__config(evlist, &opts, NULL);
0648
0649 evsel = evlist__first(evlist);
0650
0651 evsel->core.attr.comm = 1;
0652 evsel->core.attr.disabled = 1;
0653 evsel->core.attr.enable_on_exec = 0;
0654
0655 ret = evlist__open(evlist);
0656 if (ret < 0) {
0657 if (!excl_kernel) {
0658 excl_kernel = true;
0659
0660
0661
0662
0663
0664 perf_cpu_map__get(cpus);
0665 perf_thread_map__get(threads);
0666 perf_evlist__set_maps(&evlist->core, NULL, NULL);
0667 evlist__delete(evlist);
0668 evlist = NULL;
0669 continue;
0670 }
0671
0672 if (verbose > 0) {
0673 char errbuf[512];
0674 evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf));
0675 pr_debug("perf_evlist__open() failed!\n%s\n", errbuf);
0676 }
0677
0678 goto out_put;
0679 }
0680 break;
0681 }
0682
0683 ret = evlist__mmap(evlist, UINT_MAX);
0684 if (ret < 0) {
0685 pr_debug("evlist__mmap failed\n");
0686 goto out_put;
0687 }
0688
0689 evlist__enable(evlist);
0690
0691 do_something();
0692
0693 evlist__disable(evlist);
0694
0695 ret = process_events(machine, evlist, &state);
0696 if (ret < 0)
0697 goto out_put;
0698
0699 if (!have_vmlinux && !have_kcore && !try_kcore)
0700 err = TEST_CODE_READING_NO_KERNEL_OBJ;
0701 else if (!have_vmlinux && !try_kcore)
0702 err = TEST_CODE_READING_NO_VMLINUX;
0703 else if (excl_kernel)
0704 err = TEST_CODE_READING_NO_ACCESS;
0705 else
0706 err = TEST_CODE_READING_OK;
0707 out_put:
0708 thread__put(thread);
0709 out_err:
0710 evlist__delete(evlist);
0711 perf_cpu_map__put(cpus);
0712 perf_thread_map__put(threads);
0713 machine__delete_threads(machine);
0714 machine__delete(machine);
0715
0716 return err;
0717 }
0718
0719 static int test__code_reading(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
0720 {
0721 int ret;
0722
0723 ret = do_test_code_reading(false);
0724 if (!ret)
0725 ret = do_test_code_reading(true);
0726
0727 switch (ret) {
0728 case TEST_CODE_READING_OK:
0729 return 0;
0730 case TEST_CODE_READING_NO_VMLINUX:
0731 pr_debug("no vmlinux\n");
0732 return 0;
0733 case TEST_CODE_READING_NO_KCORE:
0734 pr_debug("no kcore\n");
0735 return 0;
0736 case TEST_CODE_READING_NO_ACCESS:
0737 pr_debug("no access\n");
0738 return 0;
0739 case TEST_CODE_READING_NO_KERNEL_OBJ:
0740 pr_debug("no kernel obj\n");
0741 return 0;
0742 default:
0743 return -1;
0744 };
0745 }
0746
0747 DEFINE_SUITE("Object code reading", code_reading);