]> Pileus Git - ~andy/linux/blobdiff - tools/perf/util/event.c
perf record: Get ref_reloc_sym from kernel map
[~andy/linux] / tools / perf / util / event.c
index bb788c109fe6efa4ecb2ae5784efa49cf33bca73..b0f3ca850e9e8ffbf5c1e70b9f04215e545a71ae 100644 (file)
@@ -7,6 +7,7 @@
 #include "strlist.h"
 #include "thread.h"
 #include "thread_map.h"
+#include "symbol/kallsyms.h"
 
 static const char *perf_event__names[] = {
        [0]                                     = "TOTAL",
@@ -105,8 +106,12 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
 
        memset(&event->comm, 0, sizeof(event->comm));
 
-       tgid = perf_event__get_comm_tgid(pid, event->comm.comm,
-                                        sizeof(event->comm.comm));
+       if (machine__is_host(machine))
+               tgid = perf_event__get_comm_tgid(pid, event->comm.comm,
+                                                sizeof(event->comm.comm));
+       else
+               tgid = machine->pid;
+
        if (tgid < 0)
                goto out;
 
@@ -128,7 +133,11 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
                goto out;
        }
 
-       snprintf(filename, sizeof(filename), "/proc/%d/task", pid);
+       if (machine__is_default_guest(machine))
+               return 0;
+
+       snprintf(filename, sizeof(filename), "%s/proc/%d/task",
+                machine->root_dir, pid);
 
        tasks = opendir(filename);
        if (tasks == NULL) {
@@ -166,18 +175,22 @@ out:
        return tgid;
 }
 
-static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
-                                             union perf_event *event,
-                                             pid_t pid, pid_t tgid,
-                                             perf_event__handler_t process,
-                                             struct machine *machine,
-                                             bool mmap_data)
+int perf_event__synthesize_mmap_events(struct perf_tool *tool,
+                                      union perf_event *event,
+                                      pid_t pid, pid_t tgid,
+                                      perf_event__handler_t process,
+                                      struct machine *machine,
+                                      bool mmap_data)
 {
        char filename[PATH_MAX];
        FILE *fp;
        int rc = 0;
 
-       snprintf(filename, sizeof(filename), "/proc/%d/maps", pid);
+       if (machine__is_default_guest(machine))
+               return 0;
+
+       snprintf(filename, sizeof(filename), "%s/proc/%d/maps",
+                machine->root_dir, pid);
 
        fp = fopen(filename, "r");
        if (fp == NULL) {
@@ -217,7 +230,10 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
                /*
                 * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
                 */
-               event->header.misc = PERF_RECORD_MISC_USER;
+               if (machine__is_host(machine))
+                       event->header.misc = PERF_RECORD_MISC_USER;
+               else
+                       event->header.misc = PERF_RECORD_MISC_GUEST_USER;
 
                if (prot[2] != 'x') {
                        if (!mmap_data || prot[0] != 'r')
@@ -386,6 +402,7 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
                                   struct machine *machine, bool mmap_data)
 {
        DIR *proc;
+       char proc_path[PATH_MAX];
        struct dirent dirent, *next;
        union perf_event *comm_event, *mmap_event;
        int err = -1;
@@ -398,7 +415,12 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
        if (mmap_event == NULL)
                goto out_free_comm;
 
-       proc = opendir("/proc");
+       if (machine__is_default_guest(machine))
+               return 0;
+
+       snprintf(proc_path, sizeof(proc_path), "%s/proc", machine->root_dir);
+       proc = opendir(proc_path);
+
        if (proc == NULL)
                goto out_free_mmap;
 
@@ -448,23 +470,32 @@ static int find_symbol_cb(void *arg, const char *name, char type,
        return 1;
 }
 
+u64 kallsyms__get_function_start(const char *kallsyms_filename,
+                                const char *symbol_name)
+{
+       struct process_symbol_args args = { .name = symbol_name, };
+
+       if (kallsyms__parse(kallsyms_filename, &args, find_symbol_cb) <= 0)
+               return 0;
+
+       return args.start;
+}
+
 int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
                                       perf_event__handler_t process,
-                                      struct machine *machine,
-                                      const char *symbol_name)
+                                      struct machine *machine)
 {
        size_t size;
-       const char *filename, *mmap_name;
-       char path[PATH_MAX];
+       const char *mmap_name;
        char name_buff[PATH_MAX];
        struct map *map;
+       struct kmap *kmap;
        int err;
        /*
         * We should get this from /sys/kernel/sections/.text, but till that is
         * available use this, and after it is use this as a fallback for older
         * kernels.
         */
-       struct process_symbol_args args = { .name = symbol_name, };
        union perf_event *event = zalloc((sizeof(event->mmap) +
                                          machine->id_hdr_size));
        if (event == NULL) {
@@ -480,30 +511,19 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
                 * see kernel/perf_event.c __perf_event_mmap
                 */
                event->header.misc = PERF_RECORD_MISC_KERNEL;
-               filename = "/proc/kallsyms";
        } else {
                event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
-               if (machine__is_default_guest(machine))
-                       filename = (char *) symbol_conf.default_guest_kallsyms;
-               else {
-                       sprintf(path, "%s/proc/kallsyms", machine->root_dir);
-                       filename = path;
-               }
-       }
-
-       if (kallsyms__parse(filename, &args, find_symbol_cb) <= 0) {
-               free(event);
-               return -ENOENT;
        }
 
        map = machine->vmlinux_maps[MAP__FUNCTION];
+       kmap = map__kmap(map);
        size = snprintf(event->mmap.filename, sizeof(event->mmap.filename),
-                       "%s%s", mmap_name, symbol_name) + 1;
+                       "%s%s", mmap_name, kmap->ref_reloc_sym->name) + 1;
        size = PERF_ALIGN(size, sizeof(u64));
        event->mmap.header.type = PERF_RECORD_MMAP;
        event->mmap.header.size = (sizeof(event->mmap) -
                        (sizeof(event->mmap.filename) - size) + machine->id_hdr_size);
-       event->mmap.pgoff = args.start;
+       event->mmap.pgoff = kmap->ref_reloc_sym->addr;
        event->mmap.start = map->start;
        event->mmap.len   = map->end - event->mmap.start;
        event->mmap.pid   = machine->pid;
@@ -637,6 +657,7 @@ void thread__find_addr_map(struct thread *thread,
        struct map_groups *mg = &thread->mg;
        bool load_map = false;
 
+       al->machine = machine;
        al->thread = thread;
        al->addr = addr;
        al->cpumode = cpumode;
@@ -657,15 +678,10 @@ void thread__find_addr_map(struct thread *thread,
                al->level = 'g';
                mg = &machine->kmaps;
                load_map = true;
+       } else if (cpumode == PERF_RECORD_MISC_GUEST_USER && perf_guest) {
+               al->level = 'u';
        } else {
-               /*
-                * 'u' means guest os user space.
-                * TODO: We don't support guest user space. Might support late.
-                */
-               if (cpumode == PERF_RECORD_MISC_GUEST_USER && perf_guest)
-                       al->level = 'u';
-               else
-                       al->level = 'H';
+               al->level = 'H';
                al->map = NULL;
 
                if ((cpumode == PERF_RECORD_MISC_GUEST_USER ||
@@ -732,8 +748,7 @@ int perf_event__preprocess_sample(const union perf_event *event,
        if (thread == NULL)
                return -1;
 
-       if (symbol_conf.comm_list &&
-           !strlist__has_entry(symbol_conf.comm_list, thread__comm_str(thread)))
+       if (thread__is_filtered(thread))
                goto out_filtered;
 
        dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid);