linux/tools/perf/arch/x86/util/machine.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2#include <linux/types.h>
   3#include <linux/string.h>
   4#include <limits.h>
   5#include <stdlib.h>
   6
   7#include <internal/lib.h> // page_size
   8#include "../../../util/machine.h"
   9#include "../../../util/map.h"
  10#include "../../../util/symbol.h"
  11#include <linux/ctype.h>
  12
  13#include <symbol/kallsyms.h>
  14
  15#if defined(__x86_64__)
  16
  17struct extra_kernel_map_info {
  18        int cnt;
  19        int max_cnt;
  20        struct extra_kernel_map *maps;
  21        bool get_entry_trampolines;
  22        u64 entry_trampoline;
  23};
  24
  25static int add_extra_kernel_map(struct extra_kernel_map_info *mi, u64 start,
  26                                u64 end, u64 pgoff, const char *name)
  27{
  28        if (mi->cnt >= mi->max_cnt) {
  29                void *buf;
  30                size_t sz;
  31
  32                mi->max_cnt = mi->max_cnt ? mi->max_cnt * 2 : 32;
  33                sz = sizeof(struct extra_kernel_map) * mi->max_cnt;
  34                buf = realloc(mi->maps, sz);
  35                if (!buf)
  36                        return -1;
  37                mi->maps = buf;
  38        }
  39
  40        mi->maps[mi->cnt].start = start;
  41        mi->maps[mi->cnt].end   = end;
  42        mi->maps[mi->cnt].pgoff = pgoff;
  43        strlcpy(mi->maps[mi->cnt].name, name, KMAP_NAME_LEN);
  44
  45        mi->cnt += 1;
  46
  47        return 0;
  48}
  49
  50static int find_extra_kernel_maps(void *arg, const char *name, char type,
  51                                  u64 start)
  52{
  53        struct extra_kernel_map_info *mi = arg;
  54
  55        if (!mi->entry_trampoline && kallsyms2elf_binding(type) == STB_GLOBAL &&
  56            !strcmp(name, "_entry_trampoline")) {
  57                mi->entry_trampoline = start;
  58                return 0;
  59        }
  60
  61        if (is_entry_trampoline(name)) {
  62                u64 end = start + page_size;
  63
  64                return add_extra_kernel_map(mi, start, end, 0, name);
  65        }
  66
  67        return 0;
  68}
  69
  70int machine__create_extra_kernel_maps(struct machine *machine,
  71                                      struct dso *kernel)
  72{
  73        struct extra_kernel_map_info mi = { .cnt = 0, };
  74        char filename[PATH_MAX];
  75        int ret;
  76        int i;
  77
  78        machine__get_kallsyms_filename(machine, filename, PATH_MAX);
  79
  80        if (symbol__restricted_filename(filename, "/proc/kallsyms"))
  81                return 0;
  82
  83        ret = kallsyms__parse(filename, &mi, find_extra_kernel_maps);
  84        if (ret)
  85                goto out_free;
  86
  87        if (!mi.entry_trampoline)
  88                goto out_free;
  89
  90        for (i = 0; i < mi.cnt; i++) {
  91                struct extra_kernel_map *xm = &mi.maps[i];
  92
  93                xm->pgoff = mi.entry_trampoline;
  94                ret = machine__create_extra_kernel_map(machine, kernel, xm);
  95                if (ret)
  96                        goto out_free;
  97        }
  98
  99        machine->trampolines_mapped = mi.cnt;
 100out_free:
 101        free(mi.maps);
 102        return ret;
 103}
 104
 105#endif
 106