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
[email protected]
https://www.redhat.com/mailman/listinfo/crash-utility

Reply via email to