~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/perf/tests/code-reading.c

Version: ~ [ linux-6.2-rc3 ] ~ [ linux-6.1.5 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.87 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.162 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.228 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.269 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.302 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.302 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp