debuggers.hg

view tools/xentrace/xenctx.c @ 21067:b4a1832a916f

Update Xen version to 4.0.0-rc6
author Keir Fraser <keir.fraser@citrix.com>
date Tue Mar 09 18:18:05 2010 +0000 (2010-03-09)
parents cb5b609c4164
children 3ffdb094c2c0 22ecd7178608
line source
1 /******************************************************************************
2 * tools/xentrace/xenctx.c
3 *
4 * Tool for dumping the cpu context
5 *
6 * Copyright (C) 2005 by Intel Corp
7 *
8 * Author: Arun Sharma <arun.sharma@intel.com>
9 * Date: February 2005
10 */
12 #include <time.h>
13 #include <stdlib.h>
14 #include <sys/mman.h>
15 #include <stdio.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <fcntl.h>
19 #include <unistd.h>
20 #include <errno.h>
21 #include <signal.h>
22 #include <string.h>
23 #include <inttypes.h>
24 #include <getopt.h>
26 #include "xenctrl.h"
27 #include <xen/foreign/x86_32.h>
28 #include <xen/foreign/x86_64.h>
29 #include <xen/hvm/save.h>
31 int xc_handle = 0;
32 int domid = 0;
33 int frame_ptrs = 0;
34 int stack_trace = 0;
35 int disp_all = 0;
37 #if defined (__i386__) || defined (__x86_64__)
38 typedef unsigned long long guest_word_t;
39 #define FMT_32B_WORD "%08llx"
40 #define FMT_64B_WORD "%016llx"
41 /* Word-length of the guest's own data structures */
42 int guest_word_size = sizeof (unsigned long);
43 /* Word-length of the context record we get from xen */
44 int ctxt_word_size = sizeof (unsigned long);
45 int guest_protected_mode = 1;
46 #elif defined (__ia64__)
47 /* On ia64, we can't translate virtual address to physical address. */
48 #define NO_TRANSLATION
49 typedef size_t guest_word_t;
51 /* Which registers should be displayed. */
52 int disp_cr_regs;
53 int disp_ar_regs;
54 int disp_br_regs;
55 int disp_bank_regs;
56 int disp_tlb;
57 #endif
59 struct symbol {
60 guest_word_t address;
61 char type;
62 char *name;
63 struct symbol *next;
64 } *symbol_table = NULL;
66 guest_word_t kernel_stext, kernel_etext, kernel_sinittext, kernel_einittext, kernel_hypercallpage;
68 static int is_kernel_text(guest_word_t addr)
69 {
70 #if defined (__i386__) || defined (__x86_64__)
71 if (symbol_table == NULL)
72 return (addr > ((guest_word_size == 4) ? 0xc000000 : 0xffffffff80000000ULL));
73 #elif defined (__ia64__)
74 if (symbol_table == NULL)
75 return (addr > 0xa000000000000000UL);
76 #endif
78 if (addr >= kernel_stext &&
79 addr <= kernel_etext)
80 return 1;
81 if (addr >= kernel_hypercallpage &&
82 addr <= kernel_hypercallpage + 4096)
83 return 1;
84 if (addr >= kernel_sinittext &&
85 addr <= kernel_einittext)
86 return 1;
87 return 0;
88 }
90 #if 0
91 static void free_symbol(struct symbol *symbol)
92 {
93 if (symbol == NULL)
94 return;
95 if (symbol->name)
96 free(symbol->name);
97 free(symbol);
98 }
99 #endif
101 static void insert_symbol(struct symbol *symbol)
102 {
103 static struct symbol *prev = NULL;
104 struct symbol *s = symbol_table;
106 if (s == NULL) {
107 symbol_table = symbol;
108 symbol->next = NULL;
109 return;
110 }
112 /* The System.map is usually already sorted... */
113 if (prev
114 && prev->address < symbol->address
115 && (!prev->next || prev->next->address > symbol->address)) {
116 s = prev;
117 } else {
118 /* ... otherwise do crappy/slow search for the correct place */
119 while(s && s->next && s->next->address < symbol->address)
120 s = s->next;
121 }
123 symbol->next = s->next;
124 s->next = symbol;
125 prev = symbol;
126 }
128 static struct symbol *lookup_symbol(guest_word_t address)
129 {
130 struct symbol *s = symbol_table;
132 while(s && s->next && s->next->address < address)
133 s = s->next;
135 if (s && s->address < address)
136 return s;
138 return NULL;
139 }
141 static void print_symbol(guest_word_t addr)
142 {
143 struct symbol *s;
145 if (!is_kernel_text(addr))
146 return;
148 s = lookup_symbol(addr);
150 if (s==NULL)
151 return;
153 if (addr==s->address)
154 printf("%s ", s->name);
155 else
156 printf("%s+%#x ", s->name, (unsigned int)(addr - s->address));
157 }
159 static void read_symbol_table(const char *symtab)
160 {
161 char line[256];
162 char *p;
163 struct symbol *symbol;
164 FILE *f;
166 f = fopen(symtab, "r");
167 if(f == NULL) {
168 fprintf(stderr, "failed to open symbol table %s\n", symtab);
169 exit(-1);
170 }
172 while(!feof(f)) {
173 if(fgets(line,256,f)==NULL)
174 break;
176 symbol = malloc(sizeof(*symbol));
178 /* need more checks for syntax here... */
179 symbol->address = strtoull(line, &p, 16);
180 p++;
181 symbol->type = *p++;
182 p++;
184 /* in the future we should handle the module name
185 * being appended here, this would allow us to use
186 * /proc/kallsyms as our symbol table
187 */
188 if (p[strlen(p)-1] == '\n')
189 p[strlen(p)-1] = '\0';
190 symbol->name = strdup(p);
192 insert_symbol(symbol);
194 if (strcmp(symbol->name, "_stext") == 0)
195 kernel_stext = symbol->address;
196 else if (strcmp(symbol->name, "_etext") == 0)
197 kernel_etext = symbol->address;
198 else if (strcmp(symbol->name, "_sinittext") == 0)
199 kernel_sinittext = symbol->address;
200 else if (strcmp(symbol->name, "_einittext") == 0)
201 kernel_einittext = symbol->address;
202 else if (strcmp(symbol->name, "hypercall_page") == 0)
203 kernel_hypercallpage = symbol->address;
204 }
206 fclose(f);
207 }
209 #if defined(__i386__) || defined(__x86_64__)
210 #define CR0_PE 0x1
211 char *flag_values[22][2] =
212 {/* clear, set, bit# */
213 { NULL, "c" }, // 0 Carry
214 { NULL, NULL }, // 1
215 { NULL, "p" }, // 2 Parity
216 { NULL, NULL }, // 3
217 { NULL, "a" }, // 4 Adjust
218 { NULL, NULL }, // 5
219 { "nz", "z" }, // 6 Zero
220 { NULL, "s" }, // 7 Sign
221 { NULL, "tf" }, // 8 Trap
222 { NULL, "i" }, // 9 Interrupt (enabled)
223 { NULL, "d=b" }, // 10 Direction
224 { NULL, "o" }, // 11 Overflow
225 { NULL, NULL }, // 12 12+13 == IOPL
226 { NULL, NULL }, // 13
227 { NULL, "nt" }, // 14 Nested Task
228 { NULL, NULL }, // 15
229 { NULL, "rf" }, // 16 Resume Flag
230 { NULL, "v86" }, // 17 Virtual 8086 mode
231 { NULL, "ac" }, // 18 Alignment Check (enabled)
232 { NULL, "vif" }, // 19 Virtual Interrupt (enabled)
233 { NULL, "vip" }, // 20 Virtual Interrupt Pending
234 { NULL, "cid" } // 21 Cpuid Identification Flag
235 };
237 static void print_flags(uint64_t flags)
238 {
239 int i;
241 printf("\nflags: %08" PRIx64, flags);
242 for (i = 21; i >= 0; i--) {
243 char *s = flag_values[i][(flags >> i) & 1];
244 if (s != NULL)
245 printf(" %s", s);
246 }
247 printf("\n");
248 }
250 static void print_special(void *regs, const char *name, unsigned int mask, int width)
251 {
252 unsigned int i;
254 printf("\n");
255 for (i = 0; mask; mask >>= 1, ++i)
256 if (mask & 1) {
257 if (width == 4)
258 printf("%s%u: %08"PRIx32"\n", name, i, ((uint32_t *) regs)[i]);
259 else
260 printf("%s%u: %08"PRIx64"\n", name, i, ((uint64_t *) regs)[i]);
261 }
262 }
264 static void print_ctx_32(vcpu_guest_context_x86_32_t *ctx)
265 {
266 struct cpu_user_regs_x86_32 *regs = &ctx->user_regs;
268 printf("cs:eip: %04x:%08x ", regs->cs, regs->eip);
269 print_symbol(regs->eip);
270 print_flags(regs->eflags);
271 printf("ss:esp: %04x:%08x\n", regs->ss, regs->esp);
273 printf("eax: %08x\t", regs->eax);
274 printf("ebx: %08x\t", regs->ebx);
275 printf("ecx: %08x\t", regs->ecx);
276 printf("edx: %08x\n", regs->edx);
278 printf("esi: %08x\t", regs->esi);
279 printf("edi: %08x\t", regs->edi);
280 printf("ebp: %08x\n", regs->ebp);
282 printf(" ds: %04x\t", regs->ds);
283 printf(" es: %04x\t", regs->es);
284 printf(" fs: %04x\t", regs->fs);
285 printf(" gs: %04x\n", regs->gs);
287 if (disp_all) {
288 print_special(ctx->ctrlreg, "cr", 0x1d, 4);
289 print_special(ctx->debugreg, "dr", 0xcf, 4);
290 }
291 }
293 static void print_ctx_32on64(vcpu_guest_context_x86_64_t *ctx)
294 {
295 struct cpu_user_regs_x86_64 *regs = &ctx->user_regs;
297 printf("cs:eip: %04x:%08x ", regs->cs, (uint32_t)regs->eip);
298 print_symbol((uint32_t)regs->eip);
299 print_flags((uint32_t)regs->eflags);
300 printf("ss:esp: %04x:%08x\n", regs->ss, (uint32_t)regs->esp);
302 printf("eax: %08x\t", (uint32_t)regs->eax);
303 printf("ebx: %08x\t", (uint32_t)regs->ebx);
304 printf("ecx: %08x\t", (uint32_t)regs->ecx);
305 printf("edx: %08x\n", (uint32_t)regs->edx);
307 printf("esi: %08x\t", (uint32_t)regs->esi);
308 printf("edi: %08x\t", (uint32_t)regs->edi);
309 printf("ebp: %08x\n", (uint32_t)regs->ebp);
311 printf(" ds: %04x\t", regs->ds);
312 printf(" es: %04x\t", regs->es);
313 printf(" fs: %04x\t", regs->fs);
314 printf(" gs: %04x\n", regs->gs);
316 if (disp_all) {
317 print_special(ctx->ctrlreg, "cr", 0x1d, 4);
318 print_special(ctx->debugreg, "dr", 0xcf, 4);
319 }
320 }
322 static void print_ctx_64(vcpu_guest_context_x86_64_t *ctx)
323 {
324 struct cpu_user_regs_x86_64 *regs = &ctx->user_regs;
326 printf("rip: %016"PRIx64" ", regs->rip);
327 print_symbol(regs->rip);
328 print_flags(regs->rflags);
329 printf("rsp: %016"PRIx64"\n", regs->rsp);
331 printf("rax: %016"PRIx64"\t", regs->rax);
332 printf("rcx: %016"PRIx64"\t", regs->rcx);
333 printf("rdx: %016"PRIx64"\n", regs->rdx);
335 printf("rbx: %016"PRIx64"\t", regs->rbx);
336 printf("rsi: %016"PRIx64"\t", regs->rsi);
337 printf("rdi: %016"PRIx64"\n", regs->rdi);
339 printf("rbp: %016"PRIx64"\t", regs->rbp);
340 printf(" r8: %016"PRIx64"\t", regs->r8);
341 printf(" r9: %016"PRIx64"\n", regs->r9);
343 printf("r10: %016"PRIx64"\t", regs->r10);
344 printf("r11: %016"PRIx64"\t", regs->r11);
345 printf("r12: %016"PRIx64"\n", regs->r12);
347 printf("r13: %016"PRIx64"\t", regs->r13);
348 printf("r14: %016"PRIx64"\t", regs->r14);
349 printf("r15: %016"PRIx64"\n", regs->r15);
351 printf(" cs: %04x\t", regs->cs);
352 printf(" ss: %04x\t", regs->ss);
353 printf(" ds: %04x\t", regs->ds);
354 printf(" es: %04x\n", regs->es);
356 printf(" fs: %04x @ %016"PRIx64"\n", regs->fs, ctx->fs_base);
357 printf(" gs: %04x @ %016"PRIx64"/%016"PRIx64"\n", regs->gs,
358 ctx->gs_base_kernel, ctx->gs_base_user);
360 if (disp_all) {
361 print_special(ctx->ctrlreg, "cr", 0x1d, 8);
362 print_special(ctx->debugreg, "dr", 0xcf, 8);
363 }
364 }
366 static void print_ctx(vcpu_guest_context_any_t *ctx)
367 {
368 if (ctxt_word_size == 4)
369 print_ctx_32(&ctx->x32);
370 else if (guest_word_size == 4)
371 print_ctx_32on64(&ctx->x64);
372 else
373 print_ctx_64(&ctx->x64);
374 }
376 #define NONPROT_MODE_SEGMENT_SHIFT 4
378 static guest_word_t instr_pointer(vcpu_guest_context_any_t *ctx)
379 {
380 guest_word_t r;
381 if (ctxt_word_size == 4)
382 {
383 r = ctx->x32.user_regs.eip;
385 if ( !guest_protected_mode )
386 r += ctx->x32.user_regs.cs << NONPROT_MODE_SEGMENT_SHIFT;
387 }
388 else
389 r = ctx->x64.user_regs.rip;
391 return r;
392 }
394 static guest_word_t stack_pointer(vcpu_guest_context_any_t *ctx)
395 {
396 guest_word_t r;
397 if (ctxt_word_size == 4)
398 {
399 r = ctx->x32.user_regs.esp;
401 if ( !guest_protected_mode )
402 r += ctx->x32.user_regs.ss << NONPROT_MODE_SEGMENT_SHIFT;
403 }
404 else
405 r = ctx->x64.user_regs.rsp;
407 return r;
408 }
410 static guest_word_t frame_pointer(vcpu_guest_context_any_t *ctx)
411 {
412 if (ctxt_word_size == 4)
413 return ctx->x32.user_regs.ebp;
414 else
415 return ctx->x64.user_regs.rbp;
416 }
418 #elif defined(__ia64__)
420 #define PTE_ED_SHIFT 52
421 #define PTE_ED_MASK 1
422 #define PTE_PPN_SHIFT 12
423 #define PTE_PPN_MASK 0x3fffffffff
424 #define PTE_AR_SHIFT 9
425 #define PTE_AR_MASK 7
426 #define PTE_PL_SHIFT 7
427 #define PTE_PL_MASK 3
428 #define PTE_D_SHIFT 6
429 #define PTE_D_MASK 1
430 #define PTE_A_SHIFT 5
431 #define PTE_A_MASK 1
432 #define PTE_MA_SHIFT 2
433 #define PTE_MA_MASK 7
434 #define PTE_P_SHIFT 0
435 #define PTE_P_MASK 1
436 #define ITIR_KEY_SHIFT 8
437 #define ITIR_KEY_MASK 0xffffff
438 #define ITIR_PS_SHIFT 2
439 #define ITIR_PS_MASK 0x3f
440 #define ITIR_PS_MIN 12
441 #define ITIR_PS_MAX 28
442 #define RR_RID_SHIFT 8
443 #define RR_RID_MASK 0xffffff
444 #define PSR_BN (1UL << 44)
445 #define CFM_SOF_MASK 0x3f
447 static void print_tr(int i, const struct ia64_tr_entry *tr)
448 {
449 int ps_val, ma_val;
450 unsigned long pa;
452 static const char ps[][5] = {" 4K", " 8K", " 16K", " ",
453 " 64K", " ", "256K", " ",
454 " 1M", " ", " 4M", " ",
455 " 16M", " ", " 64M", " ",
456 "256M"};
457 static const char ma[][4] = {"WB ", " ", " ", " ",
458 "UC ", "UCE", "WC ", "Nat"};
460 ps_val = tr->itir >> ITIR_PS_SHIFT & ITIR_PS_MASK;
461 ma_val = tr->pte >> PTE_MA_SHIFT & PTE_MA_MASK;
462 pa = (tr->pte >> PTE_PPN_SHIFT & PTE_PPN_MASK) << PTE_PPN_SHIFT;
463 pa = (pa >> ps_val) << ps_val;
464 printf(" [%d] %ld %06lx %016lx %013lx %02x %s %ld %ld %ld %ld "
465 "%ld %d %s %06lx\n", i,
466 tr->pte >> PTE_P_SHIFT & PTE_P_MASK,
467 tr->rid >> RR_RID_SHIFT & RR_RID_MASK,
468 tr->vadr, pa, ps_val,
469 ((ps_val >= ITIR_PS_MIN && ps_val <= ITIR_PS_MAX) ?
470 ps[ps_val - ITIR_PS_MIN] : " "),
471 tr->pte >> PTE_ED_SHIFT & PTE_ED_MASK,
472 tr->pte >> PTE_PL_SHIFT & PTE_PL_MASK,
473 tr->pte >> PTE_AR_SHIFT & PTE_AR_MASK,
474 tr->pte >> PTE_A_SHIFT & PTE_A_MASK,
475 tr->pte >> PTE_D_SHIFT & PTE_D_MASK,
476 ma_val, ma[ma_val],
477 tr->itir >> ITIR_KEY_SHIFT & ITIR_KEY_MASK);
478 }
480 void print_ctx(vcpu_guest_context_any_t *ctx)
481 {
482 struct vcpu_guest_context_regs *regs = &ctx->c.regs;
483 struct vcpu_tr_regs *tr = &ctx->c.regs.tr;
484 int i;
485 unsigned int rbs_size, cfm_sof;
487 printf(" ip: %016lx ", regs->ip);
488 print_symbol(regs->ip);
489 printf("\n");
490 printf(" psr: %016lx ", regs->psr);
491 printf(" cfm: %016lx ", regs->cfm);
492 printf(" pr: %016lx\n", regs->pr);
494 if (disp_br_regs) {
495 printf(" b0: %016lx ", regs->b[0]);
496 printf(" b1: %016lx ", regs->b[1]);
497 printf(" b2: %016lx\n", regs->b[2]);
498 printf(" b3: %016lx ", regs->b[3]);
499 printf(" b4: %016lx ", regs->b[4]);
500 printf(" b5: %016lx\n", regs->b[5]);
501 printf(" b6: %016lx ", regs->b[6]);
502 printf(" b7: %016lx\n", regs->b[7]);
503 } else {
504 printf(" b0: %016lx\n", regs->b[0]);
505 }
507 if (disp_cr_regs) {
508 printf ("\n"
509 " CR:\n");
510 printf(" dcr: %016lx ", regs->cr.dcr);
511 printf(" itm: %016lx ", regs->cr.itm);
512 printf(" iva: %016lx\n", regs->cr.iva);
513 printf(" pta: %016lx ", regs->cr.pta);
514 printf(" ipsr: %016lx ", regs->cr.ipsr);
515 printf(" isr: %016lx\n", regs->cr.isr);
516 printf(" iip: %016lx ", regs->cr.iip);
517 printf(" ifa: %016lx ", regs->cr.ifa);
518 printf(" itir: %016lx\n", regs->cr.itir);
519 printf(" iipa: %016lx ", regs->cr.iipa);
520 printf(" ifs: %016lx ", regs->cr.ifs);
521 printf(" iim: %016lx\n", regs->cr.iim);
522 printf(" iha: %016lx ", regs->cr.iha);
523 printf(" lid: %016lx ", regs->cr.lid);
524 printf(" ivr: %016lx\n", regs->cr.ivr);
525 printf(" tpr: %016lx ", regs->cr.tpr);
526 printf(" eoi: %016lx ", regs->cr.eoi);
527 printf(" irr0: %016lx\n", regs->cr.irr[0]);
528 printf(" irr1: %016lx ", regs->cr.irr[1]);
529 printf(" irr2: %016lx ", regs->cr.irr[2]);
530 printf(" irr3: %016lx\n", regs->cr.irr[3]);
531 printf(" itv: %016lx ", regs->cr.itv);
532 printf(" pmv: %016lx ", regs->cr.pmv);
533 printf(" cmcv: %016lx\n", regs->cr.cmcv);
534 printf(" lrr0: %016lx ", regs->cr.lrr0);
535 printf(" lrr1: %016lx ", regs->cr.lrr1);
536 printf(" ev_cb:%016lx\n", ctx->c.event_callback_ip);
538 }
539 if (disp_ar_regs) {
540 printf ("\n"
541 " AR:\n");
542 printf(" kr0: %016lx ", regs->ar.kr[0]);
543 printf(" kr1: %016lx ", regs->ar.kr[1]);
544 printf(" kr2: %016lx\n", regs->ar.kr[2]);
545 printf(" kr3: %016lx ", regs->ar.kr[3]);
546 printf(" kr4: %016lx ", regs->ar.kr[4]);
547 printf(" kr5: %016lx\n", regs->ar.kr[5]);
548 printf(" kr6: %016lx ", regs->ar.kr[6]);
549 printf(" kr7: %016lx ", regs->ar.kr[7]);
550 printf(" rsc: %016lx\n", regs->ar.rsc);
551 printf(" bsp: %016lx ", regs->ar.bsp);
552 printf(" bsps: %016lx ", regs->ar.bspstore);
553 printf(" rnat: %016lx\n", regs->ar.rnat);
554 printf(" csd: %016lx ", regs->ar.csd);
555 printf(" ccv: %016lx ", regs->ar.ccv);
556 printf(" unat: %016lx\n", regs->ar.unat);
557 printf(" fpsr: %016lx ", regs->ar.fpsr);
558 printf(" itc: %016lx\n", regs->ar.itc);
559 printf(" pfs: %016lx ", regs->ar.pfs);
560 printf(" lc: %016lx ", regs->ar.lc);
561 printf(" ec: %016lx\n", regs->ar.ec);
562 }
563 printf("\n");
564 printf(" r1: %016lx ", regs->r[1]);
565 printf(" r2: %016lx ", regs->r[2]);
566 printf(" r3: %016lx\n", regs->r[3]);
567 printf(" r4: %016lx ", regs->r[4]);
568 printf(" r5: %016lx ", regs->r[5]);
569 printf(" r6: %016lx\n", regs->r[6]);
570 printf(" r7: %016lx ", regs->r[7]);
571 printf(" r8: %016lx ", regs->r[8]);
572 printf(" r9: %016lx\n", regs->r[9]);
573 printf(" r10: %016lx ", regs->r[10]);
574 printf(" r11: %016lx ", regs->r[11]);
575 printf(" sp: %016lx\n", regs->r[12]);
576 printf(" tp: %016lx ", regs->r[13]);
577 printf(" r14: %016lx ", regs->r[14]);
578 printf(" r15: %016lx\n", regs->r[15]);
579 if (disp_bank_regs) {
580 printf(" Bank %d (current) Bank %d\n",
581 (regs->psr & PSR_BN) ? 1 : 0, (regs->psr & PSR_BN) ? 0 : 1);
582 printf ("16:%016lx ", regs->r[16]);
583 printf ("17:%016lx ", regs->r[17]);
584 printf ("16:%016lx ", regs->bank[0]);
585 printf ("17:%016lx\n", regs->bank[1]);
586 printf ("18:%016lx ", regs->r[18]);
587 printf ("19:%016lx ", regs->r[19]);
588 printf ("18:%016lx ", regs->bank[2]);
589 printf ("19:%016lx\n", regs->bank[3]);
590 printf ("20:%016lx ", regs->r[20]);
591 printf ("21:%016lx ", regs->r[21]);
592 printf ("20:%016lx ", regs->bank[4]);
593 printf ("21:%016lx\n", regs->bank[5]);
594 printf ("22:%016lx ", regs->r[22]);
595 printf ("23:%016lx ", regs->r[23]);
596 printf ("22:%016lx ", regs->bank[6]);
597 printf ("23:%016lx\n", regs->bank[7]);
598 printf ("24:%016lx ", regs->r[24]);
599 printf ("25:%016lx ", regs->r[25]);
600 printf ("24:%016lx ", regs->bank[8]);
601 printf ("25:%016lx\n", regs->bank[9]);
602 printf ("26:%016lx ", regs->r[26]);
603 printf ("27:%016lx ", regs->r[27]);
604 printf ("26:%016lx ", regs->bank[10]);
605 printf ("27:%016lx\n", regs->bank[11]);
606 printf ("28:%016lx ", regs->r[28]);
607 printf ("29:%016lx ", regs->r[29]);
608 printf ("28:%016lx ", regs->bank[12]);
609 printf ("29:%016lx\n", regs->bank[13]);
610 printf ("30:%016lx ", regs->r[30]);
611 printf ("31:%016lx ", regs->r[31]);
612 printf ("30:%016lx ", regs->bank[14]);
613 printf ("31:%016lx\n", regs->bank[15]);
614 } else {
615 printf(" r16: %016lx ", regs->r[16]);
616 printf(" r17: %016lx ", regs->r[17]);
617 printf(" r18: %016lx\n", regs->r[18]);
618 printf(" r19: %016lx ", regs->r[19]);
619 printf(" r20: %016lx ", regs->r[20]);
620 printf(" r21: %016lx\n", regs->r[21]);
621 printf(" r22: %016lx ", regs->r[22]);
622 printf(" r23: %016lx ", regs->r[23]);
623 printf(" r24: %016lx\n", regs->r[24]);
624 printf(" r25: %016lx ", regs->r[25]);
625 printf(" r26: %016lx ", regs->r[26]);
626 printf(" r27: %016lx\n", regs->r[27]);
627 printf(" r28: %016lx ", regs->r[28]);
628 printf(" r29: %016lx ", regs->r[29]);
629 printf(" r30: %016lx\n", regs->r[30]);
630 printf(" r31: %016lx\n", regs->r[31]);
631 }
633 printf("\n");
634 rbs_size = (regs->ar.bsp - regs->ar.bspstore) / 8;
635 cfm_sof = (regs->cfm & CFM_SOF_MASK);
636 for (i = 0; i < cfm_sof; i++) {
637 int off = cfm_sof - i;
638 unsigned int rbs_off =
639 (((62 - ((rbs_size + regs->rbs_voff) % 63) + off)) / 63) + off;
640 if (rbs_off > rbs_size)
641 break;
642 printf(" r%02d: %016lx%s", 32 + i,
643 regs->rbs[rbs_size - rbs_off],
644 (i % 3) != 2 ? " " : "\n");
645 }
646 if ((i % 3) != 0)
647 printf ("\n");
649 if (disp_tlb) {
650 printf("\n itr: P rid va pa ps ed pl "
651 "ar a d ma key\n");
652 for (i = 0; i < 8; i++)
653 print_tr(i, &tr->itrs[i]);
654 printf("\n dtr: P rid va pa ps ed pl "
655 "ar a d ma key\n");
656 for (i = 0; i < 8; i++)
657 print_tr(i, &tr->dtrs[i]);
658 }
659 }
660 #endif
662 #ifndef NO_TRANSLATION
663 static void *map_page(vcpu_guest_context_any_t *ctx, int vcpu, guest_word_t virt)
664 {
665 static unsigned long previous_mfn = 0;
666 static void *mapped = NULL;
668 unsigned long mfn = xc_translate_foreign_address(xc_handle, domid, vcpu, virt);
669 unsigned long offset = virt & ~XC_PAGE_MASK;
671 if (mapped && mfn == previous_mfn)
672 goto out;
674 if (mapped)
675 munmap(mapped, XC_PAGE_SIZE);
677 previous_mfn = mfn;
679 mapped = xc_map_foreign_range(xc_handle, domid, XC_PAGE_SIZE, PROT_READ, mfn);
681 if (mapped == NULL) {
682 fprintf(stderr, "failed to map page.\n");
683 exit(-1);
684 }
686 out:
687 return (void *)(mapped + offset);
688 }
690 static guest_word_t read_stack_word(guest_word_t *src, int width)
691 {
692 guest_word_t word = 0;
693 /* Little-endian only */
694 memcpy(&word, src, width);
695 return word;
696 }
698 static void print_stack_word(guest_word_t word, int width)
699 {
700 if (width == 4)
701 printf(FMT_32B_WORD, word);
702 else
703 printf(FMT_64B_WORD, word);
704 }
706 static void print_code(vcpu_guest_context_any_t *ctx, int vcpu)
707 {
708 guest_word_t instr;
709 int i;
711 instr = instr_pointer(ctx);
712 printf("Code (instr addr %08llx)\n", instr);
713 instr -= 21;
714 for(i=0; i<32; i++) {
715 unsigned char *c = map_page(ctx, vcpu, instr+i);
716 if (instr+i == instr_pointer(ctx))
717 printf("<%02x> ", *c);
718 else
719 printf("%02x ", *c);
720 }
721 printf("\n");
723 printf("\n");
724 }
726 static void print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width)
727 {
728 guest_word_t stack = stack_pointer(ctx);
729 guest_word_t stack_limit;
730 guest_word_t frame;
731 guest_word_t word;
732 guest_word_t *p;
733 int i;
735 stack_limit = ((stack_pointer(ctx) + XC_PAGE_SIZE)
736 & ~((guest_word_t) XC_PAGE_SIZE - 1));
737 printf("\n");
738 printf("Stack:\n");
739 for (i=1; i<5 && stack < stack_limit; i++) {
740 while(stack < stack_limit && stack < stack_pointer(ctx) + i*32) {
741 p = map_page(ctx, vcpu, stack);
742 word = read_stack_word(p, width);
743 printf(" ");
744 print_stack_word(word, width);
745 stack += width;
746 }
747 printf("\n");
748 }
749 printf("\n");
751 if(stack_trace)
752 printf("Stack Trace:\n");
753 else
754 printf("Call Trace:\n");
755 printf("%c [<", stack_trace ? '*' : ' ');
756 print_stack_word(instr_pointer(ctx), width);
757 printf(">] ");
759 print_symbol(instr_pointer(ctx));
760 printf(" <--\n");
761 if (frame_ptrs) {
762 stack = stack_pointer(ctx);
763 frame = frame_pointer(ctx);
764 while(frame && stack < stack_limit) {
765 if (stack_trace) {
766 while (stack < frame) {
767 p = map_page(ctx, vcpu, stack);
768 printf("| ");
769 print_stack_word(read_stack_word(p, width), width);
770 printf(" \n");
771 stack += width;
772 }
773 } else {
774 stack = frame;
775 }
777 p = map_page(ctx, vcpu, stack);
778 frame = read_stack_word(p, width);
779 if (stack_trace) {
780 printf("|-- ");
781 print_stack_word(read_stack_word(p, width), width);
782 printf("\n");
783 }
784 stack += width;
786 if (frame) {
787 p = map_page(ctx, vcpu, stack);
788 word = read_stack_word(p, width);
789 printf("%c [<", stack_trace ? '|' : ' ');
790 print_stack_word(word, width);
791 printf(">] ");
792 print_symbol(word);
793 printf("\n");
794 stack += width;
795 }
796 }
797 } else {
798 stack = stack_pointer(ctx);
799 while(stack < stack_limit) {
800 p = map_page(ctx, vcpu, stack);
801 word = read_stack_word(p, width);
802 if (is_kernel_text(word)) {
803 printf(" [<");
804 print_stack_word(word, width);
805 printf(">] ");
806 print_symbol(word);
807 printf("\n");
808 } else if (stack_trace) {
809 printf(" ");
810 print_stack_word(word, width);
811 printf("\n");
812 }
813 stack += width;
814 }
815 }
816 }
817 #endif
819 static void dump_ctx(int vcpu)
820 {
821 int ret;
822 vcpu_guest_context_any_t ctx;
823 xc_dominfo_t dominfo;
825 xc_handle = xc_interface_open(); /* for accessing control interface */
827 ret = xc_domain_getinfo(xc_handle, domid, 1, &dominfo);
828 if (ret < 0) {
829 perror("xc_domain_getinfo");
830 exit(-1);
831 }
833 ret = xc_domain_pause(xc_handle, domid);
834 if (ret < 0) {
835 perror("xc_domain_pause");
836 exit(-1);
837 }
839 ret = xc_vcpu_getcontext(xc_handle, domid, vcpu, &ctx);
840 if (ret < 0) {
841 if (!dominfo.paused)
842 xc_domain_unpause(xc_handle, domid);
843 perror("xc_vcpu_getcontext");
844 exit(-1);
845 }
847 #if defined(__i386__) || defined(__x86_64__)
848 {
849 if (dominfo.hvm) {
850 struct hvm_hw_cpu cpuctx;
851 xen_capabilities_info_t xen_caps = "";
852 if (xc_domain_hvm_getcontext_partial(
853 xc_handle, domid, HVM_SAVE_CODE(CPU),
854 vcpu, &cpuctx, sizeof cpuctx) != 0) {
855 perror("xc_domain_hvm_getcontext_partial");
856 exit(-1);
857 }
858 guest_word_size = (cpuctx.msr_efer & 0x400) ? 8 : 4;
859 guest_protected_mode = (cpuctx.cr0 & CR0_PE);
860 /* HVM guest context records are always host-sized */
861 if (xc_version(xc_handle, XENVER_capabilities, &xen_caps) != 0) {
862 perror("xc_version");
863 exit(-1);
864 }
865 ctxt_word_size = (strstr(xen_caps, "xen-3.0-x86_64")) ? 8 : 4;
866 } else {
867 struct xen_domctl domctl;
868 memset(&domctl, 0, sizeof domctl);
869 domctl.domain = domid;
870 domctl.cmd = XEN_DOMCTL_get_address_size;
871 if (xc_domctl(xc_handle, &domctl) == 0)
872 ctxt_word_size = guest_word_size = domctl.u.address_size.size / 8;
873 }
874 }
875 #endif
877 print_ctx(&ctx);
878 #ifndef NO_TRANSLATION
879 print_code(&ctx, vcpu);
880 if (is_kernel_text(instr_pointer(&ctx)))
881 print_stack(&ctx, vcpu, guest_word_size);
882 #endif
884 if (!dominfo.paused) {
885 ret = xc_domain_unpause(xc_handle, domid);
886 if (ret < 0) {
887 perror("xc_domain_unpause");
888 exit(-1);
889 }
890 }
892 xc_interface_close(xc_handle);
893 if (ret < 0) {
894 perror("xc_interface_close");
895 exit(-1);
896 }
897 }
899 static void usage(void)
900 {
901 printf("usage:\n\n");
903 printf(" xenctx [options] <DOMAIN> [VCPU]\n\n");
905 printf("options:\n");
906 printf(" -f, --frame-pointers\n");
907 printf(" assume the kernel was compiled with\n");
908 printf(" frame pointers.\n");
909 printf(" -s SYMTAB, --symbol-table=SYMTAB\n");
910 printf(" read symbol table from SYMTAB.\n");
911 printf(" --stack-trace print a complete stack trace.\n");
912 #ifdef __ia64__
913 printf(" -r LIST, --regs=LIST display more registers.\n");
914 printf(" -a --all same as --regs=tlb,cr,ar,br,bk\n");
915 #else
916 printf(" -a --all display more registers\n");
917 #endif
918 }
920 int main(int argc, char **argv)
921 {
922 int ch;
923 static const char *sopts = "fs:ha"
924 #ifdef __ia64__
925 "r:"
926 #endif
927 ;
928 static const struct option lopts[] = {
929 {"stack-trace", 0, NULL, 'S'},
930 {"symbol-table", 1, NULL, 's'},
931 {"frame-pointers", 0, NULL, 'f'},
932 #ifdef __ia64__
933 {"regs", 1, NULL, 'r'},
934 #endif
935 {"all", 0, NULL, 'a'},
936 {"help", 0, NULL, 'h'},
937 {0, 0, 0, 0}
938 };
939 const char *symbol_table = NULL;
941 int vcpu = 0;
943 while ((ch = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) {
944 switch(ch) {
945 case 'f':
946 frame_ptrs = 1;
947 break;
948 case 's':
949 symbol_table = optarg;
950 break;
951 case 'S':
952 stack_trace = 1;
953 break;
954 #ifdef __ia64__
955 case 'r':
956 {
957 char *r;
959 r = strtok(optarg, ",");
960 while (r) {
961 if (strcmp (r, "cr") == 0)
962 disp_cr_regs = 1;
963 else if (strcmp (r, "ar") == 0)
964 disp_ar_regs = 1;
965 else if (strcmp (r, "br") == 0)
966 disp_br_regs = 1;
967 else if (strcmp (r, "bk") == 0)
968 disp_bank_regs = 1;
969 else if (strcmp (r, "tlb") == 0)
970 disp_tlb = 1;
971 else {
972 fprintf(stderr,"unknown register set %s\n", r);
973 exit(-1);
974 }
975 r = strtok(NULL, "'");
976 }
977 }
978 break;
979 case 'a':
980 disp_cr_regs = 1;
981 disp_ar_regs = 1;
982 disp_br_regs = 1;
983 disp_bank_regs = 1;
984 disp_tlb = 1;
985 break;
986 #else
987 case 'a':
988 disp_all = 1;
989 break;
990 #endif
991 case 'h':
992 usage();
993 exit(-1);
994 case '?':
995 fprintf(stderr, "%s --help for more options\n", argv[0]);
996 exit(-1);
997 }
998 }
1000 argv += optind; argc -= optind;
1002 if (argc < 1 || argc > 2) {
1003 printf("usage: xenctx [options] <domid> <optional vcpu>\n");
1004 exit(-1);
1007 domid = atoi(argv[0]);
1008 if (domid==0) {
1009 fprintf(stderr, "cannot trace dom0\n");
1010 exit(-1);
1013 if (argc == 2)
1014 vcpu = atoi(argv[1]);
1016 if (symbol_table)
1017 read_symbol_table(symbol_table);
1019 dump_ctx(vcpu);
1021 return 0;
1024 /*
1025 * Local variables:
1026 * mode: C
1027 * c-set-style: "BSD"
1028 * c-basic-offset: 4
1029 * tab-width: 4
1030 * indent-tabs-mode: nil
1031 * End:
1032 */