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