adding support for segment registers for vmware vmss dumps.
Signed-off-by: Ajay Kaher <ajay.kaher(a)broadcom.com>
---
vmware_guestdump.c | 2 +-
vmware_vmss.c | 114 +++++++++++++++++++++++++++++++++++----------
vmware_vmss.h | 92 +++++++++++++++++++++++++-----------
3 files changed, 154 insertions(+), 54 deletions(-)
diff --git a/vmware_guestdump.c b/vmware_guestdump.c
index 78f37fb..d515df5 100644
--- a/vmware_guestdump.c
+++ b/vmware_guestdump.c
@@ -320,7 +320,7 @@ vmware_guestdump_init(char *filename, FILE *ofp)
goto exit;
}
- vmss.vcpu_regs = malloc(vmss.num_vcpus * sizeof(uint32_t));
+ vmss.vcpu_regs = malloc(vmss.num_vcpus * sizeof(uint64_t));
vmss.regs64 = calloc(vmss.num_vcpus, sizeof(void *));
if (!vmss.vcpu_regs || !vmss.regs64) {
error(INFO, LOGPRX"Failed to allocate memory\n");
diff --git a/vmware_vmss.c b/vmware_vmss.c
index 8121ab6..1a71d02 100644
--- a/vmware_vmss.c
+++ b/vmware_vmss.c
@@ -317,7 +317,7 @@ vmware_vmss_init(char *filename, FILE *ofp)
vmss.num_vcpus = u.val32;
vmss.regs64 = malloc(vmss.num_vcpus * sizeof(void *));
- vmss.vcpu_regs = malloc(vmss.num_vcpus * sizeof(uint32_t));
+ vmss.vcpu_regs = malloc(vmss.num_vcpus * sizeof(uint64_t));
for (k = 0; k < vmss.num_vcpus; k++) {
vmss.regs64[k] = malloc(sizeof(vmssregs64));
@@ -432,15 +432,65 @@ vmware_vmss_init(char *filename, FILE *ofp)
int cpu = idx[0];
vmss.regs64[cpu]->rflags |= u.val32;
vmss.vcpu_regs[cpu] |= REGS_PRESENT_RFLAGS;
+ } else if (strcmp(name, "S.base64") == 0) {
+ int cpu = idx[0];
+ int seg_index = idx[1];
+ switch (seg_index) {
+ case SEG_FS:
+ vmss.regs64[cpu]->fs_base = u.val64;
+ vmss.vcpu_regs[cpu] |= REGS_PRESENT_FS_BASE;
+ break;
+ case SEG_GS:
+ vmss.regs64[cpu]->gs_base = u.val64;
+ vmss.vcpu_regs[cpu] |= REGS_PRESENT_GS_BASE;
+ break;
+ }
+ } else if (strcmp(name, "S") == 0) {
+ int cpu = idx[0];
+ int seg_index = idx[1];
+ switch (seg_index) {
+ case SEG_ES:
+ vmss.regs64[cpu]->es = u.val32;
+ vmss.vcpu_regs[cpu] |= REGS_PRESENT_ES;
+ break;
+ case SEG_CS:
+ vmss.regs64[cpu]->cs = u.val32;
+ vmss.vcpu_regs[cpu] |= REGS_PRESENT_CS;
+ break;
+ case SEG_SS:
+ vmss.regs64[cpu]->ss = u.val32;
+ vmss.vcpu_regs[cpu] |= REGS_PRESENT_SS;
+ break;
+ case SEG_DS:
+ vmss.regs64[cpu]->ds = u.val32;
+ vmss.vcpu_regs[cpu] |= REGS_PRESENT_DS;
+ break;
+ case SEG_FS:
+ vmss.regs64[cpu]->fs = u.val32;
+ vmss.vcpu_regs[cpu] |= REGS_PRESENT_FS;
+ break;
+ case SEG_GS:
+ vmss.regs64[cpu]->gs = u.val32;
+ vmss.vcpu_regs[cpu] |= REGS_PRESENT_GS;
+ break;
+ case SEG_LDTR:
+ vmss.regs64[cpu]->ldtr = u.val32;
+ vmss.vcpu_regs[cpu] |= REGS_PRESENT_LDTR;
+ break;
+ case SEG_TR:
+ vmss.regs64[cpu]->tr = u.val32;
+ vmss.vcpu_regs[cpu] |= REGS_PRESENT_TR;
+ break;
+ default:
+ error(INFO, "Unknown VMSS Segment [%d][%d]\n", cpu, seg_index);
+ }
}
}
-
DEBUG_PARSE_PRINT((ofp, "\n"));
}
}
}
-
if (vmss.memsize == 0) {
char *vmem_filename, *p;
@@ -902,36 +952,50 @@ vmware_vmss_get_cpu_reg(int cpu, int regno, const char *name, int
size,
if (cpu >= vmss.num_vcpus)
return FALSE;
- /* All supported registers are 8 bytes long. */
- if (size != 8)
- return FALSE;
-
-#define CASE(R,r) \
+#define CASE_32(R,r) \
case R##_REGNUM: \
+ if (size != 4) \
+ return FALSE; \
if (!(vmss.vcpu_regs[cpu] & REGS_PRESENT_##R)) \
return FALSE; \
memcpy(value, &vmss.regs64[cpu]->r, size); \
break
+#define CASE_64(R,r) \
+ case R##_REGNUM: \
+ if (size != 8) \
+ return FALSE; \
+ if (!(vmss.vcpu_regs[cpu] & REGS_PRESENT_##R)) \
+ return FALSE; \
+ memcpy(value, &vmss.regs64[cpu]->r, size); \
+ break
switch (regno) {
- CASE (RAX, rax);
- CASE (RBX, rbx);
- CASE (RCX, rcx);
- CASE (RDX, rdx);
- CASE (RSI, rsi);
- CASE (RDI, rdi);
- CASE (RBP, rbp);
- CASE (RSP, rsp);
- CASE (R8, r8);
- CASE (R9, r9);
- CASE (R10, r10);
- CASE (R11, r11);
- CASE (R12, r12);
- CASE (R13, r13);
- CASE (R14, r14);
- CASE (R15, r15);
- CASE (RIP, rip);
+ CASE_64 (RAX, rax);
+ CASE_64 (RBX, rbx);
+ CASE_64 (RCX, rcx);
+ CASE_64 (RDX, rdx);
+ CASE_64 (RSI, rsi);
+ CASE_64 (RDI, rdi);
+ CASE_64 (RBP, rbp);
+ CASE_64 (RSP, rsp);
+ CASE_64 (R8, r8);
+ CASE_64 (R9, r9);
+ CASE_64 (R10, r10);
+ CASE_64 (R11, r11);
+ CASE_64 (R12, r12);
+ CASE_64 (R13, r13);
+ CASE_64 (R14, r14);
+ CASE_64 (R15, r15);
+ CASE_64 (RIP, rip);
+ CASE_32 (ES, es);
+ CASE_32 (CS, cs);
+ CASE_32 (SS, ss);
+ CASE_32 (DS, ds);
+ CASE_32 (FS, fs);
+ CASE_32 (GS, gs);
+ CASE_64 (FS_BASE, fs_base);
+ CASE_64 (GS_BASE, gs_base);
case EFLAGS_REGNUM:
if (!(vmss.vcpu_regs[cpu] & REGS_PRESENT_RFLAGS))
return FALSE;
diff --git a/vmware_vmss.h b/vmware_vmss.h
index 01d9446..5bc0370 100644
--- a/vmware_vmss.h
+++ b/vmware_vmss.h
@@ -110,41 +110,77 @@ struct vmssregs64 {
uint64_t r13;
uint64_t r14;
uint64_t r15;
+ uint64_t es;
+ uint64_t cs;
+ uint64_t ss;
+ uint64_t ds;
+ uint64_t fs;
+ uint64_t gs;
+ uint64_t ldtr;
+ uint64_t tr;
+
/* manually managed */
uint64_t idtr;
uint64_t cr[VMW_CR64_SIZE / 8];
uint64_t rip;
uint64_t rflags;
+ uint64_t fs_base;
+ uint64_t gs_base;
};
typedef struct vmssregs64 vmssregs64;
-#define REGS_PRESENT_RAX 1<<0
-#define REGS_PRESENT_RCX 1<<1
-#define REGS_PRESENT_RDX 1<<2
-#define REGS_PRESENT_RBX 1<<3
-#define REGS_PRESENT_RBP 1<<4
-#define REGS_PRESENT_RSP 1<<5
-#define REGS_PRESENT_RSI 1<<6
-#define REGS_PRESENT_RDI 1<<7
-#define REGS_PRESENT_R8 1<<8
-#define REGS_PRESENT_R9 1<<9
-#define REGS_PRESENT_R10 1<<10
-#define REGS_PRESENT_R11 1<<11
-#define REGS_PRESENT_R12 1<<12
-#define REGS_PRESENT_R13 1<<13
-#define REGS_PRESENT_R14 1<<14
-#define REGS_PRESENT_R15 1<<15
-#define REGS_PRESENT_IDTR 1<<16
-#define REGS_PRESENT_CR0 1<<17
-#define REGS_PRESENT_CR1 1<<18
-#define REGS_PRESENT_CR2 1<<19
-#define REGS_PRESENT_CR3 1<<20
-#define REGS_PRESENT_CR4 1<<21
-#define REGS_PRESENT_RIP 1<<22
-#define REGS_PRESENT_RFLAGS 1<<23
-#define REGS_PRESENT_GPREGS 65535
-#define REGS_PRESENT_CRS 4063232
-#define REGS_PRESENT_ALL 16777215
+typedef enum SegmentName {
+ SEG_ES,
+ SEG_CS,
+ SEG_SS,
+ SEG_DS,
+ SEG_FS,
+ SEG_GS,
+ SEG_LDTR,
+ SEG_TR,
+ NUM_SEGS
+} SegmentName;
+
+#define REGS_PRESENT_RAX 1L<<0
+#define REGS_PRESENT_RCX 1L<<1
+#define REGS_PRESENT_RDX 1L<<2
+#define REGS_PRESENT_RBX 1L<<3
+#define REGS_PRESENT_RBP 1L<<4
+#define REGS_PRESENT_RSP 1L<<5
+#define REGS_PRESENT_RSI 1L<<6
+#define REGS_PRESENT_RDI 1L<<7
+#define REGS_PRESENT_R8 1L<<8
+#define REGS_PRESENT_R9 1L<<9
+#define REGS_PRESENT_R10 1L<<10
+#define REGS_PRESENT_R11 1L<<11
+#define REGS_PRESENT_R12 1L<<12
+#define REGS_PRESENT_R13 1L<<13
+#define REGS_PRESENT_R14 1L<<14
+#define REGS_PRESENT_R15 1L<<15
+#define REGS_PRESENT_IDTR 1L<<16
+#define REGS_PRESENT_CR0 1L<<17
+#define REGS_PRESENT_CR1 1L<<18
+#define REGS_PRESENT_CR2 1L<<19
+#define REGS_PRESENT_CR3 1L<<20
+#define REGS_PRESENT_CR4 1L<<21
+#define REGS_PRESENT_RIP 1L<<22
+#define REGS_PRESENT_RFLAGS 1L<<23
+
+#define REGS_PRESENT_ES 1L<<24
+#define REGS_PRESENT_CS 1L<<25
+#define REGS_PRESENT_SS 1L<<26
+#define REGS_PRESENT_DS 1L<<27
+#define REGS_PRESENT_FS 1L<<28
+#define REGS_PRESENT_GS 1L<<29
+#define REGS_PRESENT_LDTR 1L<<30
+#define REGS_PRESENT_TR 1L<<31
+#define REGS_PRESENT_FS_BASE 1L<<32
+#define REGS_PRESENT_GS_BASE 1L<<33
+
+#define REGS_PRESENT_GPREGS 0x000000000000FFFF
+#define REGS_PRESENT_CRS 0x00000000003E0000
+#define REGS_PRESENT_SEG 0x00000003FF000000
+#define REGS_PRESENT_ALL 0x00000003FFFFFFFF
#define MAX_REGIONS 3
struct vmssdata {
@@ -159,7 +195,7 @@ struct vmssdata {
uint64_t memsize;
ulong phys_base;
int separate_vmem;
- uint32_t *vcpu_regs;
+ uint64_t *vcpu_regs;
uint64_t num_vcpus;
vmssregs64 **regs64;
};
--
2.40.4