|
@@ -807,8 +807,8 @@ struct process_args {
|
|
|
u64 start;
|
|
|
};
|
|
|
|
|
|
-static void machine__get_kallsyms_filename(struct machine *machine, char *buf,
|
|
|
- size_t bufsz)
|
|
|
+void machine__get_kallsyms_filename(struct machine *machine, char *buf,
|
|
|
+ size_t bufsz)
|
|
|
{
|
|
|
if (machine__is_default_guest(machine))
|
|
|
scnprintf(buf, bufsz, "%s", symbol_conf.default_guest_kallsyms);
|
|
@@ -851,17 +851,9 @@ static int machine__get_running_kernel_start(struct machine *machine,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-/* Kernel-space maps for symbols that are outside the main kernel map and module maps */
|
|
|
-struct extra_kernel_map {
|
|
|
- u64 start;
|
|
|
- u64 end;
|
|
|
- u64 pgoff;
|
|
|
- char name[KMAP_NAME_LEN];
|
|
|
-};
|
|
|
-
|
|
|
-static int machine__create_extra_kernel_map(struct machine *machine,
|
|
|
- struct dso *kernel,
|
|
|
- struct extra_kernel_map *xm)
|
|
|
+int machine__create_extra_kernel_map(struct machine *machine,
|
|
|
+ struct dso *kernel,
|
|
|
+ struct extra_kernel_map *xm)
|
|
|
{
|
|
|
struct kmap *kmap;
|
|
|
struct map *map;
|
|
@@ -923,9 +915,33 @@ static u64 find_entry_trampoline(struct dso *dso)
|
|
|
int machine__map_x86_64_entry_trampolines(struct machine *machine,
|
|
|
struct dso *kernel)
|
|
|
{
|
|
|
- u64 pgoff = find_entry_trampoline(kernel);
|
|
|
+ struct map_groups *kmaps = &machine->kmaps;
|
|
|
+ struct maps *maps = &kmaps->maps;
|
|
|
int nr_cpus_avail, cpu;
|
|
|
+ bool found = false;
|
|
|
+ struct map *map;
|
|
|
+ u64 pgoff;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * In the vmlinux case, pgoff is a virtual address which must now be
|
|
|
+ * mapped to a vmlinux offset.
|
|
|
+ */
|
|
|
+ for (map = maps__first(maps); map; map = map__next(map)) {
|
|
|
+ struct kmap *kmap = __map__kmap(map);
|
|
|
+ struct map *dest_map;
|
|
|
+
|
|
|
+ if (!kmap || !is_entry_trampoline(kmap->name))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ dest_map = map_groups__find(kmaps, map->pgoff);
|
|
|
+ if (dest_map != map)
|
|
|
+ map->pgoff = dest_map->map_ip(dest_map, map->pgoff);
|
|
|
+ found = true;
|
|
|
+ }
|
|
|
+ if (found || machine->trampolines_mapped)
|
|
|
+ return 0;
|
|
|
|
|
|
+ pgoff = find_entry_trampoline(kernel);
|
|
|
if (!pgoff)
|
|
|
return 0;
|
|
|
|
|
@@ -948,6 +964,14 @@ int machine__map_x86_64_entry_trampolines(struct machine *machine,
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
+ machine->trampolines_mapped = nr_cpus_avail;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+int __weak machine__create_extra_kernel_maps(struct machine *machine __maybe_unused,
|
|
|
+ struct dso *kernel __maybe_unused)
|
|
|
+{
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -1306,9 +1330,8 @@ int machine__create_kernel_maps(struct machine *machine)
|
|
|
return -1;
|
|
|
|
|
|
ret = __machine__create_kernel_maps(machine, kernel);
|
|
|
- dso__put(kernel);
|
|
|
if (ret < 0)
|
|
|
- return -1;
|
|
|
+ goto out_put;
|
|
|
|
|
|
if (symbol_conf.use_modules && machine__create_modules(machine) < 0) {
|
|
|
if (machine__is_host(machine))
|
|
@@ -1323,7 +1346,8 @@ int machine__create_kernel_maps(struct machine *machine)
|
|
|
if (name &&
|
|
|
map__set_kallsyms_ref_reloc_sym(machine->vmlinux_map, name, addr)) {
|
|
|
machine__destroy_kernel_maps(machine);
|
|
|
- return -1;
|
|
|
+ ret = -1;
|
|
|
+ goto out_put;
|
|
|
}
|
|
|
|
|
|
/* we have a real start address now, so re-order the kmaps */
|
|
@@ -1339,12 +1363,16 @@ int machine__create_kernel_maps(struct machine *machine)
|
|
|
map__put(map);
|
|
|
}
|
|
|
|
|
|
+ if (machine__create_extra_kernel_maps(machine, kernel))
|
|
|
+ pr_debug("Problems creating extra kernel maps, continuing anyway...\n");
|
|
|
+
|
|
|
/* update end address of the kernel map using adjacent module address */
|
|
|
map = map__next(machine__kernel_map(machine));
|
|
|
if (map)
|
|
|
machine__set_kernel_mmap(machine, addr, map->start);
|
|
|
-
|
|
|
- return 0;
|
|
|
+out_put:
|
|
|
+ dso__put(kernel);
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
static bool machine__uses_kcore(struct machine *machine)
|