VMware does not provide support for saving and including the vmcoreinfo
data into a VM dump. This patch adds support for calculating phys_base
and kaslr_offset for KASLR-enabled kernels, using the technique
developed by Takao Indoh.
---
defs.h | 3 +++
kaslr_helper.c | 3 +++
symbols.c | 10 ++++++----
vmware_vmss.c | 28 ++++++++++++++++++++++++++++
vmware_vmss.h | 1 +
x86_64.c | 20 ++++++++++++++++++--
6 files changed, 59 insertions(+), 6 deletions(-)
diff --git a/defs.h b/defs.h
index ba2e5e1..3a3b6f6 100644
--- a/defs.h
+++ b/defs.h
@@ -6429,6 +6429,9 @@ void get_vmware_vmss_regs(struct bt_info *, ulong *, ulong *);
int vmware_vmss_memory_dump(FILE *);
void dump_registers_for_vmss_dump(void);
int vmware_vmss_valid_regs(struct bt_info *);
+int vmware_vmss_get_cr3_idtr(ulong *, ulong *);
+int vmware_vmss_phys_base(ulong *phys_base);
+int vmware_vmss_set_phys_base(ulong);
/*
* kaslr_helper.c
diff --git a/kaslr_helper.c b/kaslr_helper.c
index 168cfb9..8a1fede 100644
--- a/kaslr_helper.c
+++ b/kaslr_helper.c
@@ -409,6 +409,9 @@ calc_kaslr_offset(ulong *kaslr_offset, ulong *phys_base)
} else if (QEMU_MEM_DUMP_NO_VMCOREINFO()) {
if (!qemu_get_cr3_idtr(&cr3, &idtr))
return FALSE;
+ } else if (VMSS_DUMPFILE()) {
+ if (!vmware_vmss_get_cr3_idtr(&cr3, &idtr))
+ return FALSE;
} else
return FALSE;
diff --git a/symbols.c b/symbols.c
index ddbce7d..638800a 100644
--- a/symbols.c
+++ b/symbols.c
@@ -631,7 +631,7 @@ kaslr_init(void)
}
}
- if (SADUMP_DUMPFILE())
+ if (SADUMP_DUMPFILE() || VMSS_DUMPFILE())
kt->flags2 |= KASLR_CHECK;
}
@@ -646,7 +646,7 @@ derive_kaslr_offset(bfd *abfd, int dynamic, bfd_byte *start, bfd_byte
*end,
unsigned long relocate;
ulong _stext_relocated;
- if (SADUMP_DUMPFILE() || QEMU_MEM_DUMP_NO_VMCOREINFO()) {
+ if (SADUMP_DUMPFILE() || QEMU_MEM_DUMP_NO_VMCOREINFO() || VMSS_DUMPFILE()) {
ulong kaslr_offset = 0;
ulong phys_base = 0;
@@ -664,6 +664,8 @@ derive_kaslr_offset(bfd *abfd, int dynamic, bfd_byte *start, bfd_byte
*end,
kdump_set_phys_base(phys_base);
else if (DISKDUMP_DUMPFILE())
diskdump_set_phys_base(phys_base);
+ else if (VMSS_DUMPFILE())
+ vmware_vmss_set_phys_base(phys_base);
}
return;
@@ -3083,7 +3085,7 @@ dump_symbol_table(void)
else
fprintf(fp, "\n");
- if (SADUMP_DUMPFILE() || QEMU_MEM_DUMP_NO_VMCOREINFO()) {
+ if (SADUMP_DUMPFILE() || QEMU_MEM_DUMP_NO_VMCOREINFO() || VMSS_DUMPFILE()) {
fprintf(fp, "divide_error_vmlinux: %lx\n", st->divide_error_vmlinux);
fprintf(fp, " idt_table_vmlinux: %lx\n", st->idt_table_vmlinux);
fprintf(fp, "saved_command_line_vmlinux: %lx\n",
st->saved_command_line_vmlinux);
@@ -12310,7 +12312,7 @@ numeric_forward(const void *P_x, const void *P_y)
}
}
- if (SADUMP_DUMPFILE() || QEMU_MEM_DUMP_NO_VMCOREINFO()) {
+ if (SADUMP_DUMPFILE() || QEMU_MEM_DUMP_NO_VMCOREINFO() || VMSS_DUMPFILE()) {
/* Need for kaslr_offset and phys_base */
if (STREQ(x->name, "divide_error"))
st->divide_error_vmlinux = valueof(x);
diff --git a/vmware_vmss.c b/vmware_vmss.c
index ad577b2..74c7483 100644
--- a/vmware_vmss.c
+++ b/vmware_vmss.c
@@ -863,3 +863,31 @@ vmware_vmss_valid_regs(struct bt_info *bt)
return FALSE;
}
+
+int
+vmware_vmss_get_cr3_idtr(ulong *cr3, ulong *idtr)
+{
+ if (vmss.num_vcpus == 0 || vmss.vcpu_regs[0] != REGS_PRESENT_ALL)
+ return FALSE;
+
+ *cr3 = vmss.regs64[0]->cr[3];
+ *idtr = vmss.regs64[0]->idtr;
+
+ return TRUE;
+}
+
+int
+vmware_vmss_phys_base(ulong *phys_base)
+{
+ *phys_base = vmss.phys_base;
+
+ return TRUE;
+}
+
+int
+vmware_vmss_set_phys_base(ulong phys_base)
+{
+ vmss.phys_base = phys_base;
+
+ return TRUE;
+}
diff --git a/vmware_vmss.h b/vmware_vmss.h
index f6966a5..a5828a0 100644
--- a/vmware_vmss.h
+++ b/vmware_vmss.h
@@ -157,6 +157,7 @@ struct vmssdata {
memregion regions[MAX_REGIONS];
uint64_t memoffset;
uint64_t memsize;
+ ulong phys_base;
int separate_vmem;
uint32_t *vcpu_regs;
uint64_t num_vcpus;
diff --git a/x86_64.c b/x86_64.c
index e46e70f..2934f80 100644
--- a/x86_64.c
+++ b/x86_64.c
@@ -202,7 +202,8 @@ x86_64_init(int when)
machdep->machspec->kernel_image_size = dtol(string, QUIET, NULL);
free(string);
}
- if (SADUMP_DUMPFILE() || QEMU_MEM_DUMP_NO_VMCOREINFO())
+ if (SADUMP_DUMPFILE() || QEMU_MEM_DUMP_NO_VMCOREINFO() ||
+ VMSS_DUMPFILE())
/* Need for calculation of kaslr_offset and phys_base */
machdep->kvtop = x86_64_kvtop;
break;
@@ -2220,7 +2221,7 @@ x86_64_kvtop(struct task_context *tc, ulong kvaddr, physaddr_t
*paddr, int verbo
ulong pte;
physaddr_t physpage;
- if ((SADUMP_DUMPFILE() || QEMU_MEM_DUMP_NO_VMCOREINFO())
+ if ((SADUMP_DUMPFILE() || QEMU_MEM_DUMP_NO_VMCOREINFO() || VMSS_DUMPFILE())
&& !(machdep->flags & KSYMS_START)) {
/*
* In the case of sadump, to calculate kaslr_offset and
@@ -6654,6 +6655,21 @@ x86_64_calc_phys_base(void)
return;
}
+ if (VMSS_DUMPFILE()) {
+ if (vmware_vmss_phys_base(&phys_base)) {
+ machdep->machspec->phys_base = phys_base;
+ if (!x86_64_virt_phys_base())
+ error(WARNING,
+ "cannot determine physical base address:"
+ " defaulting to %lx\n\n",
+ machdep->machspec->phys_base);
+ if (CRASHDEBUG(1))
+ fprintf(fp, "compressed kdump: phys_base: %lx\n",
+ phys_base);
+ }
+ return;
+ }
+
if (DISKDUMP_DUMPFILE()) {
if (diskdump_phys_base(&phys_base)) {
machdep->machspec->phys_base = phys_base;
--
2.14.3