Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
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     /* Read bytes */
0052     while (*buf_len > 0) {
0053         char c1, c2;
0054 
0055         /* Get 2 hex digits */
0056         c1 = *(*line)++;
0057         if (!isxdigit(c1))
0058             break;
0059         c2 = *(*line)++;
0060         if (!isxdigit(c2))
0061             break;
0062 
0063         /* Store byte and advance buf */
0064         **buf = (hex(c1) << 4) | hex(c2);
0065         (*buf)++;
0066         (*buf_len)--;
0067         bytes_read++;
0068 
0069         /* End of chunk? */
0070         if (isspace(**line))
0071             break;
0072     }
0073 
0074     /*
0075      * objdump will display raw insn as LE if code endian
0076      * is LE and bytes_per_chunk > 1. In that case reverse
0077      * the chunk we just read.
0078      *
0079      * see disassemble_bytes() at binutils/objdump.c for details
0080      * how objdump chooses display endian)
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     /* Skip to a colon */
0105     p = strchr(line, ':');
0106     if (!p)
0107         return 0;
0108     p++;
0109 
0110     /* Skip initial spaces */
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     /* return number of successfully read bytes */
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         /* read objdump data into temporary buffer */
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         /* copy it from temporary buffer to 'buf' according
0162          * to address on current objdump line */
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     /* len returns number of bytes that could not be read */
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     /* Ignore objdump errors */
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     /* Do not go off the map */
0267     if (addr + len > al.map->end)
0268         len = al.map->end - addr;
0269 
0270     /* Read the object code using perf */
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      * Converting addresses for use by objdump requires more information.
0280      * map__load() does that.  See map__rip_2objdump() for details.
0281      */
0282     if (map__load(al.map))
0283         return -1;
0284 
0285     /* objdump struggles with kcore - try each map only once */
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     /* Read the object code using objdump */
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          * The kernel maps are inaccurate - assume objdump is right in
0326          * that case.
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                  * objdump cannot handle very large segments
0336                  * that may be found in kcore.
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     /* The results should be identical */
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)        /* Not available */
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     /* Fall through: missing authorization */
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     /* Force the use of kallsyms instead of vmlinux to try kcore */
0581     if (try_kcore)
0582         symbol_conf.kallsyms_name = "/proc/kallsyms";
0583 
0584     /* Load kernel map */
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     /* 2nd time through we just try kcore */
0595     if (try_kcore && !have_kcore)
0596         return TEST_CODE_READING_NO_KCORE;
0597 
0598     /* No point getting kernel events if there is no kernel object */
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                  * Both cpus and threads are now owned by evlist
0661                  * and will be freed by following perf_evlist__set_maps
0662                  * call. Getting reference to keep them alive.
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);