#include "util.h"
 #include "../perf.h"
-#include "session.h"
 #include "sort.h"
 #include "string.h"
 #include "symbol.h"
 static void dsos__add(struct list_head *head, struct dso *dso);
 static struct map *map__new2(u64 start, struct dso *dso, enum map_type type);
 static int dso__load_kernel_sym(struct dso *self, struct map *map,
-                               struct perf_session *session, symbol_filter_t filter);
+                               symbol_filter_t filter);
 static int vmlinux_path__nr_entries;
 static char **vmlinux_path;
 
  * the original ELF section names vmlinux have.
  */
 static int dso__split_kallsyms(struct dso *self, struct map *map,
-                              struct perf_session *session, symbol_filter_t filter)
+                              symbol_filter_t filter)
 {
+       struct map_groups *kmaps = map__kmap(map)->kmaps;
        struct map *curr_map = map;
        struct symbol *pos;
        int count = 0;
                        *module++ = '\0';
 
                        if (strcmp(curr_map->dso->short_name, module)) {
-                               curr_map = map_groups__find_by_name(&session->kmaps, map->type, module);
+                               curr_map = map_groups__find_by_name(kmaps, map->type, module);
                                if (curr_map == NULL) {
                                        pr_debug("/proc/{kallsyms,modules} "
                                                 "inconsistency while looking "
                        }
 
                        curr_map->map_ip = curr_map->unmap_ip = identity__map_ip;
-                       map_groups__insert(&session->kmaps, curr_map);
+                       map_groups__insert(kmaps, curr_map);
                        ++kernel_range;
                }
 
        return count;
 }
 
-
-static int dso__load_kallsyms(struct dso *self, const char *filename, struct map *map,
-                             struct perf_session *session, symbol_filter_t filter)
+int dso__load_kallsyms(struct dso *self, const char *filename,
+                      struct map *map, symbol_filter_t filter)
 {
        if (dso__load_all_kallsyms(self, filename, map) < 0)
                return -1;
        symbols__fixup_end(&self->symbols[map->type]);
        self->origin = DSO__ORIG_KERNEL;
 
-       return dso__split_kallsyms(self, map, session, filter);
+       return dso__split_kallsyms(self, map, filter);
 }
 
 static int dso__load_perf_map(struct dso *self, struct map *map,
        }
 }
 
-static int dso__load_sym(struct dso *self, struct map *map,
-                        struct perf_session *session, const char *name, int fd,
-                        symbol_filter_t filter, int kernel, int kmodule)
+static int dso__load_sym(struct dso *self, struct map *map, const char *name,
+                        int fd, symbol_filter_t filter, int kmodule)
 {
+       struct kmap *kmap = self->kernel ? map__kmap(map) : NULL;
        struct map *curr_map = map;
        struct dso *curr_dso = self;
        size_t dso_name_len = strlen(self->short_name);
        nr_syms = shdr.sh_size / shdr.sh_entsize;
 
        memset(&sym, 0, sizeof(sym));
-       if (!kernel) {
+       if (!self->kernel) {
                self->adjust_symbols = (ehdr.e_type == ET_EXEC ||
                                elf_section_by_name(elf, &ehdr, &shdr,
                                                     ".gnu.prelink_undo",
                int is_label = elf_sym__is_label(&sym);
                const char *section_name;
 
-               if (kernel && session->ref_reloc_sym.name != NULL &&
-                   strcmp(elf_name, session->ref_reloc_sym.name) == 0)
-                       perf_session__reloc_vmlinux_maps(session, sym.st_value);
+               if (kmap && kmap->ref_reloc_sym && kmap->ref_reloc_sym->name &&
+                   strcmp(elf_name, kmap->ref_reloc_sym->name) == 0)
+                       kmap->ref_reloc_sym->unrelocated_addr = sym.st_value;
 
                if (!is_label && !elf_sym__is_a(&sym, map->type))
                        continue;
 
                section_name = elf_sec__name(&shdr, secstrs);
 
-               if (kernel || kmodule) {
+               if (self->kernel || kmodule) {
                        char dso_name[PATH_MAX];
 
                        if (strcmp(section_name,
                        snprintf(dso_name, sizeof(dso_name),
                                 "%s%s", self->short_name, section_name);
 
-                       curr_map = map_groups__find_by_name(&session->kmaps, map->type, dso_name);
+                       curr_map = map_groups__find_by_name(kmap->kmaps, map->type, dso_name);
                        if (curr_map == NULL) {
                                u64 start = sym.st_value;
 
                                curr_map->map_ip = identity__map_ip;
                                curr_map->unmap_ip = identity__map_ip;
                                curr_dso->origin = DSO__ORIG_KERNEL;
-                               map_groups__insert(&session->kmaps, curr_map);
+                               map_groups__insert(kmap->kmaps, curr_map);
                                dsos__add(&dsos__kernel, curr_dso);
                        } else
                                curr_dso = curr_map->dso;
        return origin[self->origin];
 }
 
-int dso__load(struct dso *self, struct map *map, struct perf_session *session,
-             symbol_filter_t filter)
+int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
 {
        int size = PATH_MAX;
        char *name;
        dso__set_loaded(self, map->type);
 
        if (self->kernel)
-               return dso__load_kernel_sym(self, map, session, filter);
+               return dso__load_kernel_sym(self, map, filter);
 
        name = malloc(size);
        if (!name)
                fd = open(name, O_RDONLY);
        } while (fd < 0);
 
-       ret = dso__load_sym(self, map, NULL, name, fd, filter, 0, 0);
+       ret = dso__load_sym(self, map, name, fd, filter, 0);
        close(fd);
 
        /*
        return 0;
 }
 
-static int perf_session__set_modules_path_dir(struct perf_session *self, char *dirname)
+static int map_groups__set_modules_path_dir(struct map_groups *self, char *dirname)
 {
        struct dirent *dent;
        DIR *dir = opendir(dirname);
 
                        snprintf(path, sizeof(path), "%s/%s",
                                 dirname, dent->d_name);
-                       if (perf_session__set_modules_path_dir(self, path) < 0)
+                       if (map_groups__set_modules_path_dir(self, path) < 0)
                                goto failure;
                } else {
                        char *dot = strrchr(dent->d_name, '.'),
                                 (int)(dot - dent->d_name), dent->d_name);
 
                        strxfrchar(dso_name, '-', '_');
-                       map = map_groups__find_by_name(&self->kmaps, MAP__FUNCTION, dso_name);
+                       map = map_groups__find_by_name(self, MAP__FUNCTION, dso_name);
                        if (map == NULL)
                                continue;
 
        return -1;
 }
 
-static int perf_session__set_modules_path(struct perf_session *self)
+static int map_groups__set_modules_path(struct map_groups *self)
 {
        struct utsname uts;
        char modules_path[PATH_MAX];
        snprintf(modules_path, sizeof(modules_path), "/lib/modules/%s/kernel",
                 uts.release);
 
-       return perf_session__set_modules_path_dir(self, modules_path);
+       return map_groups__set_modules_path_dir(self, modules_path);
 }
 
 /*
  */
 static struct map *map__new2(u64 start, struct dso *dso, enum map_type type)
 {
-       struct map *self = malloc(sizeof(*self));
-
+       struct map *self = zalloc(sizeof(*self) +
+                                 (dso->kernel ? sizeof(struct kmap) : 0));
        if (self != NULL) {
                /*
                 * ->end will be filled after we load all the symbols
        return self;
 }
 
-struct map *perf_session__new_module_map(struct perf_session *self, u64 start,
-                                        const char *filename)
+struct map *map_groups__new_module(struct map_groups *self, u64 start,
+                                  const char *filename)
 {
        struct map *map;
        struct dso *dso = __dsos__findnew(&dsos__kernel, filename);
                return NULL;
 
        dso->origin = DSO__ORIG_KMODULE;
-       map_groups__insert(&self->kmaps, map);
+       map_groups__insert(self, map);
        return map;
 }
 
-static int perf_session__create_module_maps(struct perf_session *self)
+static int map_groups__create_modules(struct map_groups *self)
 {
        char *line = NULL;
        size_t n;
                *sep = '\0';
 
                snprintf(name, sizeof(name), "[%s]", line);
-               map = perf_session__new_module_map(self, start, name);
+               map = map_groups__new_module(self, start, name);
                if (map == NULL)
                        goto out_delete_line;
                dso__kernel_module_get_build_id(map->dso);
        free(line);
        fclose(file);
 
-       return perf_session__set_modules_path(self);
+       return map_groups__set_modules_path(self);
 
 out_delete_line:
        free(line);
 }
 
 static int dso__load_vmlinux(struct dso *self, struct map *map,
-                            struct perf_session *session,
                             const char *vmlinux, symbol_filter_t filter)
 {
        int err = -1, fd;
                return -1;
 
        dso__set_loaded(self, map->type);
-       err = dso__load_sym(self, map, session, vmlinux, fd, filter, 1, 0);
+       err = dso__load_sym(self, map, vmlinux, fd, filter, 0);
        close(fd);
 
        return err;
 }
 
 int dso__load_vmlinux_path(struct dso *self, struct map *map,
-                          struct perf_session *session, symbol_filter_t filter)
+                          symbol_filter_t filter)
 {
        int i, err = 0;
 
                 vmlinux_path__nr_entries);
 
        for (i = 0; i < vmlinux_path__nr_entries; ++i) {
-               err = dso__load_vmlinux(self, map, session, vmlinux_path[i],
-                                       filter);
+               err = dso__load_vmlinux(self, map, vmlinux_path[i], filter);
                if (err > 0) {
                        pr_debug("Using %s for symbols\n", vmlinux_path[i]);
                        dso__set_long_name(self, strdup(vmlinux_path[i]));
 }
 
 static int dso__load_kernel_sym(struct dso *self, struct map *map,
-                               struct perf_session *session, symbol_filter_t filter)
+                               symbol_filter_t filter)
 {
        int err;
        const char *kallsyms_filename = NULL;
         * match.
         */
        if (symbol_conf.vmlinux_name != NULL) {
-               err = dso__load_vmlinux(self, map, session,
+               err = dso__load_vmlinux(self, map,
                                        symbol_conf.vmlinux_name, filter);
                goto out_try_fixup;
        }
 
        if (vmlinux_path != NULL) {
-               err = dso__load_vmlinux_path(self, map, session, filter);
+               err = dso__load_vmlinux_path(self, map, filter);
                if (err > 0)
                        goto out_fixup;
        }
        }
 
 do_kallsyms:
-       err = dso__load_kallsyms(self, kallsyms_filename, map, session, filter);
+       err = dso__load_kallsyms(self, kallsyms_filename, map, filter);
        free(kallsyms_allocated_filename);
 
 out_try_fixup:
        enum map_type type;
 
        for (type = 0; type < MAP__NR_TYPES; ++type) {
+               struct kmap *kmap;
+
                vmlinux_maps[type] = map__new2(0, kernel, type);
                if (vmlinux_maps[type] == NULL)
                        return -1;
 
                vmlinux_maps[type]->map_ip =
                        vmlinux_maps[type]->unmap_ip = identity__map_ip;
+
+               kmap = map__kmap(vmlinux_maps[type]);
+               kmap->kmaps = self;
                map_groups__insert(self, vmlinux_maps[type]);
        }
 
        return 0;
 }
 
-static int map_groups__create_kernel_maps(struct map_groups *self,
-                                         struct map *vmlinux_maps[MAP__NR_TYPES],
-                                         const char *vmlinux)
-{
-       struct dso *kernel = dsos__create_kernel(vmlinux);
-
-       if (kernel == NULL)
-               return -1;
-
-       return __map_groups__create_kernel_maps(self, vmlinux_maps, kernel);
-}
-
 static void vmlinux_path__exit(void)
 {
        while (--vmlinux_path__nr_entries >= 0) {
        return -1;
 }
 
-int perf_session__create_kernel_maps(struct perf_session *self)
+int map_groups__create_kernel_maps(struct map_groups *self,
+                                  struct map *vmlinux_maps[MAP__NR_TYPES])
 {
-       if (map_groups__create_kernel_maps(&self->kmaps, self->vmlinux_maps,
-                                          symbol_conf.vmlinux_name) < 0)
+       struct dso *kernel = dsos__create_kernel(symbol_conf.vmlinux_name);
+
+       if (kernel == NULL)
+               return -1;
+
+       if (__map_groups__create_kernel_maps(self, vmlinux_maps, kernel) < 0)
                return -1;
 
-       if (symbol_conf.use_modules &&
-           perf_session__create_module_maps(self) < 0)
-               pr_debug("Failed to load list of modules for session %s, "
-                        "continuing...\n", self->filename);
+       if (symbol_conf.use_modules && map_groups__create_modules(self) < 0)
+               return -1;
        /*
         * Now that we have all the maps created, just set the ->end of them:
         */
-       map_groups__fixup_end(&self->kmaps);
+       map_groups__fixup_end(self);
        return 0;
 }