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 -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility