From: Don Slutz <Don@CloudSwitch.com> Also fixup handling of symbol files, and output of 2 page stacks, and output of non stack memory. Signed-off-by: Don Slutz <Don@CloudSwitch.com> --- tools/xentrace/xenctx.c | 562 +++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 496 insertions(+), 66 deletions(-) diff --git a/tools/xentrace/xenctx.c b/tools/xentrace/xenctx.c index 1214185..83aaece 100644 --- a/tools/xentrace/xenctx.c +++ b/tools/xentrace/xenctx.c @@ -35,6 +35,7 @@ static struct xenctx { int frame_ptrs; int stack_trace; int disp_all; + int two_pages; int all_vcpus; int self_paused; xc_dominfo_t dominfo; @@ -68,6 +69,7 @@ struct symbol { } *symbol_table = NULL; guest_word_t kernel_stext, kernel_etext, kernel_sinittext, kernel_einittext, kernel_hypercallpage; +guest_word_t kernel_text, kernel_end; #if defined (__i386__) unsigned long long kernel_start = 0xc0000000; @@ -77,17 +79,24 @@ unsigned long long kernel_start = 0xffffffff80000000UL; static int is_kernel_text(guest_word_t addr) { - if (symbol_table == NULL) - return (addr > kernel_start); + if (symbol_table == NULL) { + if (addr > kernel_start) + return 2; + else + return 0; + } if (addr >= kernel_stext && addr <= kernel_etext) - return 1; - if (addr >= kernel_hypercallpage && - addr <= kernel_hypercallpage + 4096) - return 1; + return 2; + if (kernel_hypercallpage && (addr >= kernel_hypercallpage && + addr <= kernel_hypercallpage + 4096)) + return 2; if (addr >= kernel_sinittext && addr <= kernel_einittext) + return 2; + if (addr >= kernel_text && + addr <= kernel_end) return 1; return 0; } @@ -143,11 +152,11 @@ static struct symbol *lookup_symbol(guest_word_t address) return s->next && s->next->address <= address ? s->next : s; } -static void print_symbol(guest_word_t addr) +static void print_symbol(guest_word_t addr, int type) { struct symbol *s; - if (!is_kernel_text(addr)) + if (is_kernel_text(addr) < type) return; s = lookup_symbol(addr); @@ -156,9 +165,9 @@ static void print_symbol(guest_word_t addr) return; if (addr==s->address) - printf("%s ", s->name); + printf(" %s", s->name); else - printf("%s+%#x ", s->name, (unsigned int)(addr - s->address)); + printf(" %s+%#x", s->name, (unsigned int)(addr - s->address)); } static void read_symbol_table(const char *symtab) @@ -215,6 +224,10 @@ static void read_symbol_table(const char *symtab) kernel_stext = symbol->address; else if (strcmp(symbol->name, "_etext") == 0) kernel_etext = symbol->address; + else if (strcmp(symbol->name, "_text") == 0) + kernel_text = symbol->address; + else if (strcmp(symbol->name, "_end") == 0) + kernel_end = symbol->address; else if (strcmp(symbol->name, "_sinittext") == 0) kernel_sinittext = symbol->address; else if (strcmp(symbol->name, "_einittext") == 0) @@ -285,8 +298,8 @@ static void print_ctx_32(vcpu_guest_context_x86_32_t *ctx) { struct cpu_user_regs_x86_32 *regs = &ctx->user_regs; - printf("cs:eip: %04x:%08x ", regs->cs, regs->eip); - print_symbol(regs->eip); + printf("cs:eip: %04x:%08x", regs->cs, regs->eip); + print_symbol(regs->eip, 2); print_flags(regs->eflags); printf("ss:esp: %04x:%08x\n", regs->ss, regs->esp); @@ -314,8 +327,8 @@ static void print_ctx_32on64(vcpu_guest_context_x86_64_t *ctx) { struct cpu_user_regs_x86_64 *regs = &ctx->user_regs; - printf("cs:eip: %04x:%08x ", regs->cs, (uint32_t)regs->eip); - print_symbol((uint32_t)regs->eip); + printf("cs:eip: %04x:%08x", regs->cs, (uint32_t)regs->eip); + print_symbol((uint32_t)regs->eip, 2); print_flags((uint32_t)regs->eflags); printf("ss:esp: %04x:%08x\n", regs->ss, (uint32_t)regs->esp); @@ -343,8 +356,8 @@ static void print_ctx_64(vcpu_guest_context_x86_64_t *ctx) { struct cpu_user_regs_x86_64 *regs = &ctx->user_regs; - printf("rip: %016"PRIx64" ", regs->rip); - print_symbol(regs->rip); + printf("rip: %016"PRIx64, regs->rip); + print_symbol(regs->rip, 2); print_flags(regs->rflags); printf("rsp: %016"PRIx64"\n", regs->rsp); @@ -393,6 +406,247 @@ static void print_ctx(vcpu_guest_context_any_t *ctx) print_ctx_64(&ctx->x64); } +#if defined(__i386__) || defined(__x86_64__) +static void print_cpuctx_regs64(struct hvm_hw_cpu *ctx) +{ + printf("rip: %016"PRIx64, ctx->rip); + print_symbol(ctx->rip, 2); + print_flags(ctx->rflags); + printf("rsp: %016"PRIx64"\n", ctx->rsp); + + printf("rax: %016"PRIx64"\t", ctx->rax); + printf("rcx: %016"PRIx64"\t", ctx->rcx); + printf("rdx: %016"PRIx64"\n", ctx->rdx); + + printf("rbx: %016"PRIx64"\t", ctx->rbx); + printf("rsi: %016"PRIx64"\t", ctx->rsi); + printf("rdi: %016"PRIx64"\n", ctx->rdi); + + printf("rbp: %016"PRIx64"\t", ctx->rbp); + printf(" r8: %016"PRIx64"\t", ctx->r8); + printf(" r9: %016"PRIx64"\n", ctx->r9); + + printf("r10: %016"PRIx64"\t", ctx->r10); + printf("r11: %016"PRIx64"\t", ctx->r11); + printf("r12: %016"PRIx64"\n", ctx->r12); + + printf("r13: %016"PRIx64"\t", ctx->r13); + printf("r14: %016"PRIx64"\t", ctx->r14); + printf("r15: %016"PRIx64"\n", ctx->r15); + + printf(" cs: %04x @ %016"PRIx64, ctx->cs_sel, ctx->cs_base); + if (ctx->cs_base) + print_symbol(ctx->cs_base, 1); + printf("\n /%08x(%x)\n", ctx->cs_limit, ctx->cs_arbytes); + printf(" ss: %04x @ %016"PRIx64, ctx->ss_sel, ctx->ss_base); + if (ctx->ss_base) + print_symbol(ctx->ss_base, 1); + printf("\n /%08x(%x)\n", ctx->ss_limit, ctx->ss_arbytes); + printf(" ds: %04x @ %016"PRIx64, ctx->ds_sel, ctx->ds_base); + if (ctx->ds_base) + print_symbol(ctx->ds_base, 1); + printf("\n /%08x(%x)\n", ctx->ds_limit, ctx->ds_arbytes); + printf(" es: %04x @ %016"PRIx64, ctx->es_sel, ctx->es_base); + if (ctx->es_base) + print_symbol(ctx->es_base, 1); + printf("\n /%08x(%x)\n", ctx->es_limit, ctx->es_arbytes); + printf(" fs: %04x @ %016"PRIx64, ctx->fs_sel, ctx->fs_base); + if (ctx->fs_base) + print_symbol(ctx->fs_base, 1); + printf("\n /%08x(%x)\n", ctx->fs_limit, ctx->fs_arbytes); + printf(" gs: %04x @ %016"PRIx64"\\%016"PRIx64, ctx->gs_sel, + ctx->gs_base, ctx->shadow_gs); + if (ctx->gs_base) + print_symbol(ctx->gs_base, 1); + printf("\\"); + if (ctx->shadow_gs) + print_symbol(ctx->shadow_gs, 1); + printf("\n /%08x(%x)\n", ctx->gs_limit, ctx->gs_arbytes); + + if (xenctx.disp_all) { + printf(" tr: %04x @ %016"PRIx64, ctx->tr_sel, ctx->tr_base); + if (ctx->tr_base) + print_symbol(ctx->tr_base, 1); + printf("\n /%08x(%x)\n", ctx->tr_limit, ctx->tr_arbytes); + printf(" ldt: %04x @ %016"PRIx64, ctx->ldtr_sel, ctx->ldtr_base); + if (ctx->ldtr_base) + print_symbol(ctx->ldtr_base, 1); + printf("\n /%08x(%x)\n", ctx->ldtr_limit, ctx->ldtr_arbytes); + printf("\n"); + printf("cr0: %08"PRIx64"\n", ctx->cr0); + printf("cr2: %08"PRIx64, ctx->cr2); + print_symbol(ctx->cr2, 1); + printf("\n"); + printf("cr3: %08"PRIx64"\n", ctx->cr3); + printf("cr4: %08"PRIx64"\n", ctx->cr4); + printf("\n"); + printf("dr0: %08"PRIx64, ctx->dr0); + print_symbol(ctx->dr0, 1); + printf("\n"); + printf("dr1: %08"PRIx64, ctx->dr1); + print_symbol(ctx->dr1, 1); + printf("\n"); + printf("dr2: %08"PRIx64, ctx->dr2); + print_symbol(ctx->dr2, 1); + printf("\n"); + printf("dr3: %08"PRIx64, ctx->dr3); + print_symbol(ctx->dr3, 1); + printf("\n"); + printf("dr6: %08"PRIx64"\n", ctx->dr6); + printf("dr7: %08"PRIx64"\n", ctx->dr7); + printf("\n"); + printf("gdt: %016"PRIx64"/%lx", ctx->gdtr_base, (long)(ctx->gdtr_limit)); + print_symbol(ctx->gdtr_base, 1); + printf("\n"); + printf("idt: %016"PRIx64"/%lx", ctx->idtr_base, (long)(ctx->idtr_limit)); + print_symbol(ctx->idtr_base, 1); + printf("\n"); + printf("\n"); + printf(" EFER: %08"PRIx64" flags: %08"PRIx64"\n", + ctx->msr_efer, ctx->msr_flags); + printf("SYSENTER cs: %08"PRIx64" esp: %08"PRIx64" eip: %08"PRIx64, + ctx->sysenter_cs, ctx->sysenter_esp, ctx->sysenter_eip); + print_symbol(ctx->sysenter_eip, 1); + printf("\n"); + printf(" STAR: %08"PRIx64" SFMASK: %08"PRIx64"\n", + ctx->msr_star, ctx->msr_syscall_mask); + printf("LSTAR: %08"PRIx64, ctx->msr_lstar); + print_symbol(ctx->msr_lstar, 1); + printf("\n"); + printf("CSTAR: %08"PRIx64, ctx->msr_cstar); + print_symbol(ctx->msr_cstar, 1); + printf("\n"); + printf("\n"); + printf("\n"); + printf(" tsc: %016"PRIx64"\n", ctx->tsc); + printf("\n"); + printf("\n"); + printf("pending_event: %lx pending_vector: %lx\n", + (long)(ctx->pending_event), (long)(ctx->pending_vector)); + printf("pending error_code: %lx\n\n", (long)(ctx->error_code)); + } +} + +static void print_cpuctx_regs32(struct hvm_hw_cpu *ctx) +{ + printf("cs:eip: %04x:%08x", ctx->cs_sel, (uint32_t)ctx->rip); + print_symbol((uint32_t)ctx->rip, 2); + print_flags((uint32_t)ctx->rflags); + printf("ss:esp: %04x:%08x\n", ctx->ss_sel, (uint32_t)ctx->rsp); + printf("\n"); + + printf("eax: %08x\t", (uint32_t)ctx->rax); + printf("ebx: %08x\t", (uint32_t)ctx->rbx); + printf("ecx: %08x\t", (uint32_t)ctx->rcx); + printf("edx: %08x\n", (uint32_t)ctx->rdx); + + printf("esi: %08x\t", (uint32_t)ctx->rsi); + printf("edi: %08x\t", (uint32_t)ctx->rdi); + printf("ebp: %08x\n", (uint32_t)ctx->rbp); + printf("\n"); + + printf(" cs: %04x @ %08"PRIx64, ctx->cs_sel, ctx->cs_base); + if (ctx->cs_base) + print_symbol(ctx->cs_base, 1); + printf("\n /%08x(%x)\n", ctx->cs_limit, ctx->cs_arbytes); + printf(" ss: %04x @ %08"PRIx64, ctx->ss_sel, ctx->ss_base); + if (ctx->ss_base) + print_symbol(ctx->ss_base, 1); + printf("\n /%08x(%x)\n", ctx->ss_limit, ctx->ss_arbytes); + printf(" ds: %04x @ %08"PRIx64, ctx->ds_sel, ctx->ds_base); + if (ctx->ds_base) + print_symbol(ctx->ds_base, 1); + printf("\n /%08x(%x)\n", ctx->ds_limit, ctx->ds_arbytes); + printf(" es: %04x @ %08"PRIx64, ctx->es_sel, ctx->es_base); + if (ctx->es_base) + print_symbol(ctx->es_base, 1); + printf("\n /%08x(%x)\n", ctx->es_limit, ctx->es_arbytes); + printf(" fs: %04x @ %08"PRIx64, ctx->fs_sel, ctx->fs_base); + if (ctx->fs_base) + print_symbol(ctx->fs_base, 1); + printf("\n /%08x(%x)\n", ctx->fs_limit, ctx->fs_arbytes); + printf(" gs: %04x @ %08"PRIx64"\\%08"PRIx64, ctx->gs_sel, + ctx->gs_base, ctx->shadow_gs); + if (ctx->gs_base) + print_symbol(ctx->gs_base, 1); + printf("\\"); + if (ctx->shadow_gs) + print_symbol(ctx->shadow_gs, 1); + printf("\n /%08x(%x)\n", ctx->gs_limit, ctx->gs_arbytes); + + if (xenctx.disp_all) { + printf(" tr: %04x @ %08"PRIx64, ctx->tr_sel, ctx->tr_base); + if (ctx->tr_base) + print_symbol(ctx->tr_base, 1); + printf("\n /%08x(%x)\n", ctx->tr_limit, ctx->tr_arbytes); + printf(" ldt: %04x @ %08"PRIx64, ctx->ldtr_sel, ctx->ldtr_base); + if (ctx->ldtr_base) + print_symbol(ctx->ldtr_base, 1); + printf("\n /%08x(%x)\n", ctx->ldtr_limit, ctx->ldtr_arbytes); + printf("\n"); + printf("cr0: %08"PRIx64"\n", ctx->cr0); + printf("cr2: %08"PRIx64, ctx->cr2); + print_symbol(ctx->cr2, 1); + printf("\n"); + printf("cr3: %08"PRIx64"\n", ctx->cr3); + printf("cr4: %08"PRIx64"\n", ctx->cr4); + printf("\n"); + printf("dr0: %08"PRIx64, ctx->dr0); + print_symbol(ctx->dr0, 1); + printf("\n"); + printf("dr1: %08"PRIx64, ctx->dr1); + print_symbol(ctx->dr1, 1); + printf("\n"); + printf("dr2: %08"PRIx64, ctx->dr2); + print_symbol(ctx->dr2, 1); + printf("\n"); + printf("dr3: %08"PRIx64, ctx->dr3); + print_symbol(ctx->dr3, 1); + printf("\n"); + printf("dr6: %08"PRIx64"\n", ctx->dr6); + printf("dr7: %08"PRIx64"\n", ctx->dr7); + printf("\n"); + printf("gdt: %08"PRIx64"/%lx", ctx->gdtr_base, (long)(ctx->gdtr_limit)); + print_symbol(ctx->gdtr_base, 1); + printf("\n"); + printf("idt: %08"PRIx64"/%lx", ctx->idtr_base, (long)(ctx->idtr_limit)); + print_symbol(ctx->idtr_base, 1); + printf("\n"); + printf("\n"); + printf(" EFER: %08"PRIx64" flags: %08"PRIx64"\n", + ctx->msr_efer, ctx->msr_flags); + printf("SYSENTER cs: %08"PRIx64" esp: %08"PRIx64" eip: %08"PRIx64, + ctx->sysenter_cs, ctx->sysenter_esp, ctx->sysenter_eip); + print_symbol(ctx->sysenter_eip, 1); + printf("\n"); + printf(" STAR: %08"PRIx64" SFMASK: %08"PRIx64"\n", + ctx->msr_star, ctx->msr_syscall_mask); + printf("LSTAR: %08"PRIx64, ctx->msr_lstar); + print_symbol(ctx->msr_lstar, 1); + printf("\n"); + printf("CSTAR: %08"PRIx64, ctx->msr_cstar); + print_symbol(ctx->msr_cstar, 1); + printf("\n"); + printf("\n"); + printf(" tsc: %016"PRIx64"\n", ctx->tsc); + printf("\n"); + printf("\n"); + printf("pending_event: %lx pending_vector: %lx\n", + (long)(ctx->pending_event), (long)(ctx->pending_vector)); + printf("pending error_code: %lx\n\n", (long)(ctx->error_code)); + } +} + +static void print_cpuctx(struct hvm_hw_cpu *ctx) +{ + if (guest_word_size == 8) + print_cpuctx_regs64(ctx); + else + print_cpuctx_regs32(ctx); + +} +#endif + #define NONPROT_MODE_SEGMENT_SHIFT 4 static guest_word_t instr_pointer(vcpu_guest_context_any_t *ctx) @@ -591,7 +845,7 @@ static void *map_page(vcpu_guest_context_any_t *ctx, int vcpu, guest_word_t virt mapped = xc_map_foreign_range(xenctx.xc_handle, xenctx.domid, XC_PAGE_SIZE, PROT_READ, mfn); if (mapped == NULL) { - fprintf(stderr, "failed to map page.\n"); + fprintf(stdout, "\nfailed to map page for %08llx.\n", virt); return NULL; } @@ -607,6 +861,28 @@ static guest_word_t read_stack_word(guest_word_t *src, int width) return word; } +static guest_word_t read_mem_word(vcpu_guest_context_any_t *ctx, int vcpu, guest_word_t virt, int width) +{ + + if ((virt & 7) == 0) { + guest_word_t *p = map_page(ctx, vcpu, virt); + + return read_stack_word(p, width); + } else { + guest_word_t word = 0; + char *src, *dst; + int i; + + dst = (char*)&word; + for(i=0; i<width; i++) { + src = map_page(ctx, vcpu, virt+i); + *dst++ = *src; + } + return word; + } +} + + static void print_stack_word(guest_word_t word, int width) { if (width == 4) @@ -615,6 +891,45 @@ static void print_stack_word(guest_word_t word, int width) printf(FMT_64B_WORD, word); } +static void print_mem(vcpu_guest_context_any_t *ctx, int vcpu, int width, long memAddr) +{ + guest_word_t instr; + guest_word_t instr_start; + guest_word_t word; + guest_word_t ascii[4]; + unsigned char *bytep; + int i, j, k, l; + + instr_start = memAddr; + instr = memAddr; + printf("Memory (addr %08llx)\n", instr); + for (i=1; i<10; i++) { + print_stack_word(instr, width); + printf(":"); + j = 0; + while(instr < instr_start + i*16) { + word = read_mem_word(ctx, vcpu, instr, width); + ascii[j++] = word; + printf(" "); + print_stack_word(word, width); + instr += width; + } + printf(" "); + for (k=0; k < j; k++) { + bytep = (unsigned char*)&ascii[k]; + for (l=0; l < width; l++) { + if ((*bytep < 127) && (*bytep >= 32)) + printf("%c", *bytep); + else + printf("."); + bytep++; + } + } + printf("\n"); + } + printf("\n"); +} + static int print_code(vcpu_guest_context_any_t *ctx, int vcpu) { guest_word_t instr; @@ -638,29 +953,52 @@ static int print_code(vcpu_guest_context_any_t *ctx, int vcpu) return 0; } -static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width) +static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width, long stkAddr) { - guest_word_t stack = stack_pointer(ctx); + long stkAddrStart = stack_pointer(ctx); + guest_word_t stack; guest_word_t stack_limit; guest_word_t frame; guest_word_t word; - guest_word_t *p; - int i; - stack_limit = ((stack_pointer(ctx) + XC_PAGE_SIZE) - & ~((guest_word_t) XC_PAGE_SIZE - 1)); + guest_word_t ascii[4]; + unsigned char *bytep; + int i, j, k, l; + + if (stkAddr && !xenctx.frame_ptrs) + stkAddrStart = stkAddr; + stack = stkAddrStart; + stack_limit = ((stkAddrStart + XC_PAGE_SIZE) + & ~((guest_word_t) XC_PAGE_SIZE - 1)); + if (xenctx.two_pages) + stack_limit += XC_PAGE_SIZE; printf("\n"); printf("Stack:\n"); - for (i=1; i<5 && stack < stack_limit; i++) { - while(stack < stack_limit && stack < stack_pointer(ctx) + i*32) { - p = map_page(ctx, vcpu, stack); + for (i=1; i<10 && stack < stack_limit; i++) { + print_stack_word(stack, width); + printf(":"); + j = 0; + while(stack < stack_limit && stack < stkAddrStart + i*16) { + void *p = map_page(ctx, vcpu, stack); if (!p) return -1; word = read_stack_word(p, width); + ascii[j++] = word; printf(" "); print_stack_word(word, width); stack += width; } + printf(" "); + for (k=0; k < j; k++) { + bytep = (unsigned char*)&ascii[k]; + for (l=0; l < width; l++) { + if ((*bytep < 127) && (*bytep >= 32)) + printf("%c", *bytep); + else + printf("."); + bytep++; + } + } printf("\n"); } printf("\n"); @@ -669,13 +1007,17 @@ static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width) printf("Stack Trace:\n"); else printf("Call Trace:\n"); - printf("%c [<", xenctx.stack_trace ? ''*'' : '' ''); - print_stack_word(instr_pointer(ctx), width); - printf(">] "); + if (!stkAddr || xenctx.frame_ptrs) { + printf("%c [<", xenctx.stack_trace ? ''*'' : '' ''); + print_stack_word(instr_pointer(ctx), width); + printf(">]"); + print_symbol(instr_pointer(ctx), 1); + printf(" <--\n"); + } - print_symbol(instr_pointer(ctx)); - printf(" <--\n"); if (xenctx.frame_ptrs) { + void *p; + stack = stack_pointer(ctx); frame = frame_pointer(ctx); while(frame && stack < stack_limit) { @@ -709,26 +1051,27 @@ static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width) if (!p) return -1; word = read_stack_word(p, width); - printf("%c [<", xenctx.stack_trace ? ''|'' : '' ''); + print_stack_word(stack, width); + printf(": %c [<", xenctx.stack_trace ? ''|'' : '' ''); print_stack_word(word, width); - printf(">] "); - print_symbol(word); + printf(">]"); + print_symbol(word, 1); printf("\n"); stack += width; } } } else { - stack = stack_pointer(ctx); + stack = stkAddrStart; while(stack < stack_limit) { - p = map_page(ctx, vcpu, stack); + void *p = map_page(ctx, vcpu, stack); if (!p) return -1; word = read_stack_word(p, width); - if (is_kernel_text(word)) { + if (is_kernel_text(word) >= 2) { printf(" [<"); print_stack_word(word, width); - printf(">] "); - print_symbol(word); + printf(">]"); + print_symbol(word, 2); printf("\n"); } else if (xenctx.stack_trace) { printf(" "); @@ -742,9 +1085,12 @@ static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width) } #endif -static void dump_ctx(int vcpu) +static void dump_ctx(int vcpu, int fcpu, long memAddr, long stkAddr) { vcpu_guest_context_any_t ctx; +#if defined(__i386__) || defined(__x86_64__) + struct hvm_hw_cpu cpuctx; +#endif if (xc_vcpu_getcontext(xenctx.xc_handle, xenctx.domid, vcpu, &ctx) < 0) { perror("xc_vcpu_getcontext"); @@ -753,12 +1099,11 @@ static void dump_ctx(int vcpu) #if defined(__i386__) || defined(__x86_64__) { - if (xenctx.dominfo.hvm) { - struct hvm_hw_cpu cpuctx; + if ((fcpu >= 0) && xenctx.dominfo.hvm) { xen_capabilities_info_t xen_caps = ""; if (xc_domain_hvm_getcontext_partial( xenctx.xc_handle, xenctx.domid, HVM_SAVE_CODE(CPU), - vcpu, &cpuctx, sizeof cpuctx) != 0) { + fcpu, &cpuctx, sizeof cpuctx) != 0) { perror("xc_domain_hvm_getcontext_partial"); return; } @@ -771,33 +1116,93 @@ static void dump_ctx(int vcpu) } ctxt_word_size = (strstr(xen_caps, "xen-3.0-x86_64")) ? 8 : 4; } else { - unsigned int gw; - if ( !xc_domain_get_guest_width(xenctx.xc_handle, xenctx.domid, &gw) ) - ctxt_word_size = guest_word_size = gw; + struct xen_domctl domctl; + memset(&domctl, 0, sizeof domctl); + domctl.domain = xenctx.domid; + domctl.cmd = XEN_DOMCTL_get_address_size; + if (xc_domctl(xenctx.xc_handle, &domctl) == 0) + ctxt_word_size = guest_word_size = domctl.u.address_size.size / 8; } } #endif - print_ctx(&ctx); + if (memAddr) + print_mem(&ctx, vcpu, guest_word_size, memAddr); + else { + if (!stkAddr) { +#if defined(__i386__) || defined(__x86_64__) + if ((fcpu >= 0) && xenctx.dominfo.hvm && (ctxt_word_size == 8)) { + if (guest_word_size == 4) { + if ((((uint32_t)ctx.x64.user_regs.eip) != cpuctx.rip) || + (((uint32_t)ctx.x64.user_regs.esp) != cpuctx.rsp) || + (((uint32_t)ctx.x64.ctrlreg[3]) != cpuctx.cr3)) { + fprintf(stderr, "Regs mismatch ip=%llx vs %llx sp=%llx vs %llx cr3=%llx vs %llx\n", + (long long)((uint32_t)ctx.x64.user_regs.eip), + (long long)cpuctx.rip, + (long long)((uint32_t)ctx.x64.user_regs.esp), + (long long)cpuctx.rsp, + (long long)((uint32_t)ctx.x64.ctrlreg[3]), + (long long)cpuctx.cr3); + fprintf(stdout, "=============Regs mismatch start=============\n"); + print_ctx(&ctx); + fprintf(stdout, "=============Regs mismatch end=============\n"); + } + } else { + if ((ctx.x64.user_regs.eip != cpuctx.rip) || + (ctx.x64.user_regs.esp != cpuctx.rsp) || + (ctx.x64.ctrlreg[3] != cpuctx.cr3)) { + fprintf(stderr, "Regs mismatch ip=%llx vs %llx sp=%llx vs %llx cr3=%llx vs %llx\n", + (long long)ctx.x64.user_regs.eip, + (long long)cpuctx.rip, + (long long)ctx.x64.user_regs.esp, + (long long)cpuctx.rsp, + (long long)ctx.x64.ctrlreg[3], + (long long)cpuctx.cr3); + fprintf(stdout, "=============Regs mismatch start=============\n"); + print_ctx(&ctx); + fprintf(stdout, "=============Regs mismatch end=============\n"); + } + } + print_cpuctx(&cpuctx); + } + else +#endif + print_ctx(&ctx); + } #ifndef NO_TRANSLATION - if (print_code(&ctx, vcpu)) - return; - if (is_kernel_text(instr_pointer(&ctx))) - if (print_stack(&ctx, vcpu, guest_word_size)) - return; + if (!stkAddr) { + print_code(&ctx, vcpu); + if (is_kernel_text(instr_pointer(&ctx))) + if (print_stack(&ctx, vcpu, guest_word_size, stkAddr)) + return; + } else { + if (print_stack(&ctx, vcpu, guest_word_size, stkAddr)) + return; + } #endif + } } -static void dump_all_vcpus(void) +static void dump_all_vcpus(long memAddr, long stkAddr) { xc_vcpuinfo_t vinfo; int vcpu; + int fcpu = 0; + for (vcpu = 0; vcpu <= xenctx.dominfo.max_vcpu_id; vcpu++) { if ( xc_vcpu_getinfo(xenctx.xc_handle, xenctx.domid, vcpu, &vinfo) ) continue; - if ( vinfo.online ) - dump_ctx(vcpu); + if ( vinfo.online ) { + printf("vcpu=%d(%d)\n", vcpu, fcpu); + dump_ctx(vcpu, fcpu, memAddr, stkAddr); + fcpu++; + printf("\n"); + } else { + printf("vcpu=%d offline\n", vcpu); + dump_ctx(vcpu, -1, memAddr, stkAddr); + printf("\n"); + } } } @@ -805,7 +1210,7 @@ static void usage(void) { printf("usage:\n\n"); - printf(" xenctx [options] <DOMAIN> [VCPU]\n\n"); + printf(" xenctx [options] <DOMAIN> [VCPU] [fCPU]\n\n"); printf("options:\n"); printf(" -f, --frame-pointers\n"); @@ -813,31 +1218,41 @@ static void usage(void) printf(" frame pointers.\n"); printf(" -s SYMTAB, --symbol-table=SYMTAB\n"); printf(" read symbol table from SYMTAB.\n"); - printf(" -S --stack-trace print a complete stack trace.\n"); + printf(" -S, --stack-trace print a complete stack trace.\n"); printf(" -k, --kernel-start\n"); printf(" set user/kernel split. (default 0xc0000000)\n"); - printf(" -a --all display more registers\n"); - printf(" -C --all-vcpus print info for all vcpus\n"); + printf(" -a, --all display more registers\n"); + printf(" -2, --two-pages assume the kernel was compiled with 8k stacks.\n"); + printf(" -C, --all-vcpus print info for all vcpus\n"); + printf(" -m, --memory dump memory at.\n"); + printf(" -d, --dump-as-stack\n"); + printf(" dump memory as a stack at.\n"); } int main(int argc, char **argv) { int ch; int ret; - static const char *sopts = "fs:hak:SC"; + static const char *sopts = "fs:hak:SCm:d:2"; static const struct option lopts[] = { {"stack-trace", 0, NULL, ''S''}, {"symbol-table", 1, NULL, ''s''}, {"frame-pointers", 0, NULL, ''f''}, {"kernel-start", 1, NULL, ''k''}, + {"two-pages", 0, NULL, ''2''}, + {"memory", 1, NULL, ''m''}, + {"dump-as-stack", 1, NULL, ''d''}, {"all", 0, NULL, ''a''}, {"all-vcpus", 0, NULL, ''C''}, {"help", 0, NULL, ''h''}, {0, 0, 0, 0} }; const char *symbol_table = NULL; + long memAddr = 0; + long stkAddr = 0; int vcpu = 0; + int fcpu = 0; while ((ch = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) { switch(ch) { @@ -853,12 +1268,21 @@ int main(int argc, char **argv) case ''a'': xenctx.disp_all = 1; break; + case ''2'': + xenctx.two_pages = 1; + break; case ''C'': xenctx.all_vcpus = 1; break; case ''k'': kernel_start = strtoull(optarg, NULL, 0); break; + case ''m'': + memAddr = strtoul(optarg, NULL, 0); + break; + case ''d'': + stkAddr = strtoul(optarg, NULL, 0); + break; case ''h'': usage(); exit(-1); @@ -870,8 +1294,8 @@ int main(int argc, char **argv) argv += optind; argc -= optind; - if (argc < 1 || argc > 2) { - printf("usage: xenctx [options] <domid> <optional vcpu>\n"); + if (argc < 1 || argc > 3) { + printf("usage: xenctx [options] <domid> <optional vcpu> <optional fcpu>\n"); exit(-1); } @@ -881,14 +1305,20 @@ int main(int argc, char **argv) exit(-1); } - if (argc == 2) + if (argc == 2) { vcpu = atoi(argv[1]); + fcpu = vcpu; + } + + if (argc == 3) { + fcpu = atoi(argv[2]); + } if (symbol_table) read_symbol_table(symbol_table); xenctx.xc_handle = xc_interface_open(0,0,0); /* for accessing control interface */ - if (xenctx.xc_handle < 0) { + if (!xenctx.xc_handle) { perror("xc_interface_open"); exit(-1); } @@ -909,9 +1339,9 @@ int main(int argc, char **argv) } if (xenctx.all_vcpus) - dump_all_vcpus(); + dump_all_vcpus(memAddr, stkAddr); else - dump_ctx(vcpu); + dump_ctx(vcpu, fcpu, memAddr, stkAddr); if (xenctx.self_paused) { ret = xc_domain_unpause(xenctx.xc_handle, xenctx.domid); -- 1.7.1
Jan Beulich
2013-Oct-18 08:00 UTC
Re: [PATCH] xenctx: Add an option to output more registers.
>>> On 17.10.13 at 20:41, Don Slutz <dslutz@verizon.com> wrote: > From: Don Slutz <Don@CloudSwitch.com> > > Also fixup handling of symbol files, and output of 2 page stacks, and output > of non stack memory.Considering the size of the change this should be broken up, and the individual changes need to be described better in the commit message. Without having done a thorough review, two things stand out immediately:> @@ -77,17 +79,24 @@ unsigned long long kernel_start = 0xffffffff80000000UL; > > static int is_kernel_text(guest_word_t addr) > { > - if (symbol_table == NULL) > - return (addr > kernel_start); > + if (symbol_table == NULL) { > + if (addr > kernel_start) > + return 2; > + else > + return 0; > + } > > if (addr >= kernel_stext && > addr <= kernel_etext) > - return 1; > - if (addr >= kernel_hypercallpage && > - addr <= kernel_hypercallpage + 4096) > - return 1; > + return 2; > + if (kernel_hypercallpage && (addr >= kernel_hypercallpage && > + addr <= kernel_hypercallpage + 4096)) > + return 2; > if (addr >= kernel_sinittext && > addr <= kernel_einittext) > + return 2; > + if (addr >= kernel_text && > + addr <= kernel_end) > return 1; > return 0; > }It remains entirely unclear what distinguishes the return values 1 and 2. This needs not just an explanation in the commit message, but rather a code comment...> @@ -143,11 +152,11 @@ static struct symbol *lookup_symbol(guest_word_t address) > return s->next && s->next->address <= address ? s->next : s; > } > > -static void print_symbol(guest_word_t addr) > +static void print_symbol(guest_word_t addr, int type) > { > struct symbol *s; > > - if (!is_kernel_text(addr)) > + if (is_kernel_text(addr) < type)... or, with this usage model, perhaps the return value should rather be a self describing enum.> @@ -615,6 +891,45 @@ static void print_stack_word(guest_word_t word, int width) > printf(FMT_64B_WORD, word); > } > > +static void print_mem(vcpu_guest_context_any_t *ctx, int vcpu, int width, long memAddr)"memAddr" and alike are not valid identifiers in Linux and Xen coding style, and you make things even worse by mixing this foreign style with our usual one inside this new function. Jan
Ian Campbell
2013-Oct-18 09:23 UTC
Re: [PATCH] xenctx: Add an option to output more registers.
On Fri, 2013-10-18 at 09:00 +0100, Jan Beulich wrote:> It remains entirely unclear what distinguishes the return values > 1 and 2. This needs not just an explanation in the commit message, > but rather a code comment... > > > @@ -143,11 +152,11 @@ static struct symbol *lookup_symbol(guest_word_t address) > > return s->next && s->next->address <= address ? s->next : s; > > } > > > > -static void print_symbol(guest_word_t addr) > > +static void print_symbol(guest_word_t addr, int type) > > { > > struct symbol *s; > > > > - if (!is_kernel_text(addr)) > > + if (is_kernel_text(addr) < type) > > ... or, with this usage model, perhaps the return value should > rather be a self describing enum.I think this would be preferable to a comment. Also is_kernel_addr likely needs to become type_of_addr or something of that nature since it is no longer returning a true/false result. Ian.