ia64/xen-unstable

view tools/xentrace/xenctx.c @ 16806:edc95d23493b

xenctx/x86: fix format for readability and add information
Signed-off-by: Jan Beulich <jbeulich@novell.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jan 18 15:27:02 2008 +0000 (2008-01-18)
parents e2f5b5b24e07
children d3a87899985d
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"
28 int xc_handle = 0;
29 int domid = 0;
30 int frame_ptrs = 0;
31 int stack_trace = 0;
32 int disp_all = 0;
34 #if defined (__i386__)
35 #if defined (__OpenBSD__)
36 #define FMT_SIZE_T "%08lx"
37 #define INSTR_POINTER(regs) (unsigned long)(regs->eip)
38 #else
39 #define FMT_SIZE_T "%08x"
40 #define INSTR_POINTER(regs) (regs->eip)
41 #endif
42 #define STACK_POINTER(regs) (regs->esp)
43 #define FRAME_POINTER(regs) (regs->ebp)
44 #define STACK_ROWS 4
45 #define STACK_COLS 8
46 #elif defined (__x86_64__)
47 #define FMT_SIZE_T "%016lx"
48 #define STACK_POINTER(regs) (regs->rsp)
49 #define FRAME_POINTER(regs) (regs->rbp)
50 #define INSTR_POINTER(regs) (regs->rip)
51 #define STACK_ROWS 4
52 #define STACK_COLS 4
53 #elif defined (__ia64__)
54 /* On ia64, we can't translate virtual address to physical address. */
55 #define NO_TRANSLATION
57 /* Which registers should be displayed. */
58 int disp_cr_regs;
59 int disp_ar_regs;
60 int disp_br_regs;
61 int disp_bank_regs;
62 int disp_tlb;
63 #endif
65 struct symbol {
66 size_t address;
67 char type;
68 char *name;
69 struct symbol *next;
70 } *symbol_table = NULL;
72 size_t kernel_stext, kernel_etext, kernel_sinittext, kernel_einittext, kernel_hypercallpage;
74 int is_kernel_text(size_t addr)
75 {
76 #if defined (__i386__)
77 if (symbol_table == NULL)
78 return (addr > 0xc000000);
79 #elif defined (__x86_64__)
80 if (symbol_table == NULL)
81 return (addr > 0xffffffff80000000UL);
82 #elif defined (__ia64__)
83 if (symbol_table == NULL)
84 return (addr > 0xa000000000000000UL);
85 #endif
87 if (addr >= kernel_stext &&
88 addr <= kernel_etext)
89 return 1;
90 if (addr >= kernel_hypercallpage &&
91 addr <= kernel_hypercallpage + 4096)
92 return 1;
93 if (addr >= kernel_sinittext &&
94 addr <= kernel_einittext)
95 return 1;
96 return 0;
97 }
99 void free_symbol(struct symbol *symbol)
100 {
101 if (symbol == NULL)
102 return;
103 if (symbol->name)
104 free(symbol->name);
105 free(symbol);
106 }
108 void insert_symbol(struct symbol *symbol)
109 {
110 static struct symbol *prev = NULL;
111 struct symbol *s = symbol_table;
113 if (s == NULL) {
114 symbol_table = symbol;
115 symbol->next = NULL;
116 return;
117 }
119 /* The System.map is usually already sorted... */
120 if (prev
121 && prev->address < symbol->address
122 && (!prev->next || prev->next->address > symbol->address)) {
123 s = prev;
124 } else {
125 /* ... otherwise do crappy/slow search for the correct place */
126 while(s && s->next && s->next->address < symbol->address)
127 s = s->next;
128 }
130 symbol->next = s->next;
131 s->next = symbol;
132 prev = symbol;
133 }
135 struct symbol *lookup_symbol(size_t address)
136 {
137 struct symbol *s = symbol_table;
139 while(s && s->next && s->next->address < address)
140 s = s->next;
142 if (s && s->address < address)
143 return s;
145 return NULL;
146 }
148 void print_symbol(size_t addr)
149 {
150 struct symbol *s;
152 if (!is_kernel_text(addr))
153 return;
155 s = lookup_symbol(addr);
157 if (s==NULL)
158 return;
160 if (addr==s->address)
161 printf("%s ", s->name);
162 else
163 printf("%s+%#x ", s->name, (unsigned int)(addr - s->address));
164 }
166 void read_symbol_table(const char *symtab)
167 {
168 char line[256];
169 char *p;
170 struct symbol *symbol;
171 FILE *f;
173 f = fopen(symtab, "r");
174 if(f == NULL) {
175 fprintf(stderr, "failed to open symbol table %s\n", symtab);
176 exit(-1);
177 }
179 while(!feof(f)) {
180 if(fgets(line,256,f)==NULL)
181 break;
183 symbol = malloc(sizeof(*symbol));
185 /* need more checks for syntax here... */
186 symbol->address = strtoull(line, &p, 16);
187 p++;
188 symbol->type = *p++;
189 p++;
191 /* in the future we should handle the module name
192 * being appended here, this would allow us to use
193 * /proc/kallsyms as our symbol table
194 */
195 if (p[strlen(p)-1] == '\n')
196 p[strlen(p)-1] = '\0';
197 symbol->name = strdup(p);
199 insert_symbol(symbol);
201 if (strcmp(symbol->name, "_stext") == 0)
202 kernel_stext = symbol->address;
203 else if (strcmp(symbol->name, "_etext") == 0)
204 kernel_etext = symbol->address;
205 else if (strcmp(symbol->name, "_sinittext") == 0)
206 kernel_sinittext = symbol->address;
207 else if (strcmp(symbol->name, "_einittext") == 0)
208 kernel_einittext = symbol->address;
209 else if (strcmp(symbol->name, "hypercall_page") == 0)
210 kernel_hypercallpage = symbol->address;
211 }
213 fclose(f);
214 }
216 #if defined(__i386__) || defined(__x86_64__)
217 char *flag_values[22][2] =
218 {/* clear, set, bit# */
219 { NULL, "c" }, // 0 Carry
220 { NULL, NULL }, // 1
221 { NULL, "p" }, // 2 Parity
222 { NULL, NULL }, // 3
223 { NULL, "a" }, // 4 Adjust
224 { NULL, NULL }, // 5
225 { "nz", "z" }, // 6 Zero
226 { NULL, "s" }, // 7 Sign
227 { NULL, "tf" }, // 8 Trap
228 { NULL, "i" }, // 9 Interrupt (enabled)
229 { NULL, "d=b" }, // 10 Direction
230 { NULL, "o" }, // 11 Overflow
231 { NULL, NULL }, // 12 12+13 == IOPL
232 { NULL, NULL }, // 13
233 { NULL, "nt" }, // 14 Nested Task
234 { NULL, NULL }, // 15
235 { NULL, "rf" }, // 16 Resume Flag
236 { NULL, "v86" }, // 17 Virtual 8086 mode
237 { NULL, "ac" }, // 18 Alignment Check (enabled)
238 { NULL, "vif" }, // 19 Virtual Interrupt (enabled)
239 { NULL, "vip" }, // 20 Virtual Interrupt Pending
240 { NULL, "cid" } // 21 Cpuid Identification Flag
241 };
243 void print_flags(uint64_t flags)
244 {
245 int i;
247 printf("\nflags: %08" PRIx64, flags);
248 for (i = 21; i >= 0; i--) {
249 char *s = flag_values[i][(flags >> i) & 1];
250 if (s != NULL)
251 printf(" %s", s);
252 }
253 printf("\n");
254 }
256 void print_special(unsigned long *regs, const char *name, unsigned int mask)
257 {
258 unsigned int i;
260 printf("\n");
261 for (i = 0; mask; mask >>= 1, ++i)
262 if (mask & 1)
263 printf("%s%u: " FMT_SIZE_T "\n", name, i, (size_t)regs[i]);
264 }
265 #endif
267 #ifdef __i386__
268 void print_ctx(vcpu_guest_context_t *ctx1)
269 {
270 struct cpu_user_regs *regs = &ctx1->user_regs;
272 printf("cs:eip: %04x:%08x ", regs->cs, regs->eip);
273 print_symbol(regs->eip);
274 print_flags(regs->eflags);
275 printf("ss:esp: %04x:%08x\n", regs->ss, regs->esp);
277 printf("eax: %08x\t", regs->eax);
278 printf("ebx: %08x\t", regs->ebx);
279 printf("ecx: %08x\t", regs->ecx);
280 printf("edx: %08x\n", regs->edx);
282 printf("esi: %08x\t", regs->esi);
283 printf("edi: %08x\t", regs->edi);
284 printf("ebp: %08x\n", regs->ebp);
286 printf(" ds: %04x\t", regs->ds);
287 printf(" es: %04x\t", regs->es);
288 printf(" fs: %04x\t", regs->fs);
289 printf(" gs: %04x\n", regs->gs);
291 if (disp_all) {
292 print_special(ctx1->ctrlreg, "cr", 0x1d);
293 print_special(ctx1->debugreg, "dr", 0xcf);
294 }
295 }
296 #elif defined(__x86_64__)
297 void print_ctx(vcpu_guest_context_t *ctx1)
298 {
299 struct cpu_user_regs *regs = &ctx1->user_regs;
301 printf("rip: %016lx ", regs->rip);
302 print_symbol(regs->rip);
303 print_flags(regs->rflags);
304 printf("rsp: %016lx\n", regs->rsp);
306 printf("rax: %016lx\t", regs->rax);
307 printf("rcx: %016lx\t", regs->rcx);
308 printf("rdx: %016lx\n", regs->rdx);
310 printf("rbx: %016lx\t", regs->rbx);
311 printf("rsi: %016lx\t", regs->rsi);
312 printf("rdi: %016lx\n", regs->rdi);
314 printf("rbp: %016lx\t", regs->rbp);
315 printf(" r8: %016lx\t", regs->r8);
316 printf(" r9: %016lx\n", regs->r9);
318 printf("r10: %016lx\t", regs->r10);
319 printf("r11: %016lx\t", regs->r11);
320 printf("r12: %016lx\n", regs->r12);
322 printf("r13: %016lx\t", regs->r13);
323 printf("r14: %016lx\t", regs->r14);
324 printf("r15: %016lx\n", regs->r15);
326 printf(" cs: %04x\t", regs->cs);
327 printf(" ss: %04x\t", regs->ss);
328 printf(" ds: %04x\t", regs->ds);
329 printf(" es: %04x\n", regs->es);
331 printf(" fs: %04x @ %016lx\n", regs->fs, ctx1->fs_base);
332 printf(" gs: %04x @ %016lx/%016lx\n", regs->gs,
333 ctx1->gs_base_kernel, ctx1->gs_base_user);
335 if (disp_all) {
336 print_special(ctx1->ctrlreg, "cr", 0x1d);
337 print_special(ctx1->debugreg, "dr", 0xcf);
338 }
339 }
340 #elif defined(__ia64__)
342 #define PTE_ED_SHIFT 52
343 #define PTE_ED_MASK 1
344 #define PTE_PPN_SHIFT 12
345 #define PTE_PPN_MASK 0x3fffffffff
346 #define PTE_AR_SHIFT 9
347 #define PTE_AR_MASK 7
348 #define PTE_PL_SHIFT 7
349 #define PTE_PL_MASK 3
350 #define PTE_D_SHIFT 6
351 #define PTE_D_MASK 1
352 #define PTE_A_SHIFT 5
353 #define PTE_A_MASK 1
354 #define PTE_MA_SHIFT 2
355 #define PTE_MA_MASK 7
356 #define PTE_P_SHIFT 0
357 #define PTE_P_MASK 1
358 #define ITIR_KEY_SHIFT 8
359 #define ITIR_KEY_MASK 0xffffff
360 #define ITIR_PS_SHIFT 2
361 #define ITIR_PS_MASK 0x3f
362 #define ITIR_PS_MIN 12
363 #define ITIR_PS_MAX 28
364 #define RR_RID_SHIFT 8
365 #define RR_RID_MASK 0xffffff
366 #define PSR_BN (1UL << 44)
367 #define CFM_SOF_MASK 0x3f
369 static void print_tr(int i, const struct ia64_tr_entry *tr)
370 {
371 int ps_val, ma_val;
372 unsigned long pa;
374 static const char ps[][5] = {" 4K", " 8K", " 16K", " ",
375 " 64K", " ", "256K", " ",
376 " 1M", " ", " 4M", " ",
377 " 16M", " ", " 64M", " ",
378 "256M"};
379 static const char ma[][4] = {"WB ", " ", " ", " ",
380 "UC ", "UCE", "WC ", "Nat"};
382 ps_val = tr->itir >> ITIR_PS_SHIFT & ITIR_PS_MASK;
383 ma_val = tr->pte >> PTE_MA_SHIFT & PTE_MA_MASK;
384 pa = (tr->pte >> PTE_PPN_SHIFT & PTE_PPN_MASK) << PTE_PPN_SHIFT;
385 pa = (pa >> ps_val) << ps_val;
386 printf(" [%d] %ld %06lx %016lx %013lx %02x %s %ld %ld %ld %ld "
387 "%ld %d %s %06lx\n", i,
388 tr->pte >> PTE_P_SHIFT & PTE_P_MASK,
389 tr->rid >> RR_RID_SHIFT & RR_RID_MASK,
390 tr->vadr, pa, ps_val,
391 ((ps_val >= ITIR_PS_MIN && ps_val <= ITIR_PS_MAX) ?
392 ps[ps_val - ITIR_PS_MIN] : " "),
393 tr->pte >> PTE_ED_SHIFT & PTE_ED_MASK,
394 tr->pte >> PTE_PL_SHIFT & PTE_PL_MASK,
395 tr->pte >> PTE_AR_SHIFT & PTE_AR_MASK,
396 tr->pte >> PTE_A_SHIFT & PTE_A_MASK,
397 tr->pte >> PTE_D_SHIFT & PTE_D_MASK,
398 ma_val, ma[ma_val],
399 tr->itir >> ITIR_KEY_SHIFT & ITIR_KEY_MASK);
400 }
402 void print_ctx(vcpu_guest_context_t *ctx)
403 {
404 struct vcpu_guest_context_regs *regs = &ctx->regs;
405 struct vcpu_tr_regs *tr = &ctx->regs.tr;
406 int i;
407 unsigned int rbs_size, cfm_sof;
409 printf(" ip: %016lx ", regs->ip);
410 print_symbol(regs->ip);
411 printf("\n");
412 printf(" psr: %016lx ", regs->psr);
413 printf(" cfm: %016lx ", regs->cfm);
414 printf(" pr: %016lx\n", regs->pr);
416 if (disp_br_regs) {
417 printf(" b0: %016lx ", regs->b[0]);
418 printf(" b1: %016lx ", regs->b[1]);
419 printf(" b2: %016lx\n", regs->b[2]);
420 printf(" b3: %016lx ", regs->b[3]);
421 printf(" b4: %016lx ", regs->b[4]);
422 printf(" b5: %016lx\n", regs->b[5]);
423 printf(" b6: %016lx ", regs->b[6]);
424 printf(" b7: %016lx\n", regs->b[7]);
425 } else {
426 printf(" b0: %016lx\n", regs->b[0]);
427 }
429 if (disp_cr_regs) {
430 printf ("\n"
431 " CR:\n");
432 printf(" dcr: %016lx ", regs->cr.dcr);
433 printf(" itm: %016lx ", regs->cr.itm);
434 printf(" iva: %016lx\n", regs->cr.iva);
435 printf(" pta: %016lx ", regs->cr.pta);
436 printf(" ipsr: %016lx ", regs->cr.ipsr);
437 printf(" isr: %016lx\n", regs->cr.isr);
438 printf(" iip: %016lx ", regs->cr.iip);
439 printf(" ifa: %016lx ", regs->cr.ifa);
440 printf(" itir: %016lx\n", regs->cr.itir);
441 printf(" iipa: %016lx ", regs->cr.iipa);
442 printf(" ifs: %016lx ", regs->cr.ifs);
443 printf(" iim: %016lx\n", regs->cr.iim);
444 printf(" iha: %016lx ", regs->cr.iha);
445 printf(" lid: %016lx ", regs->cr.lid);
446 printf(" ivr: %016lx\n", regs->cr.ivr);
447 printf(" tpr: %016lx ", regs->cr.tpr);
448 printf(" eoi: %016lx ", regs->cr.eoi);
449 printf(" irr0: %016lx\n", regs->cr.irr[0]);
450 printf(" irr1: %016lx ", regs->cr.irr[1]);
451 printf(" irr2: %016lx ", regs->cr.irr[2]);
452 printf(" irr3: %016lx\n", regs->cr.irr[3]);
453 printf(" itv: %016lx ", regs->cr.itv);
454 printf(" pmv: %016lx ", regs->cr.pmv);
455 printf(" cmcv: %016lx\n", regs->cr.cmcv);
456 printf(" lrr0: %016lx ", regs->cr.lrr0);
457 printf(" lrr1: %016lx ", regs->cr.lrr1);
458 printf(" ev_cb:%016lx\n", ctx->event_callback_ip);
460 }
461 if (disp_ar_regs) {
462 printf ("\n"
463 " AR:\n");
464 printf(" kr0: %016lx ", regs->ar.kr[0]);
465 printf(" kr1: %016lx ", regs->ar.kr[1]);
466 printf(" kr2: %016lx\n", regs->ar.kr[2]);
467 printf(" kr3: %016lx ", regs->ar.kr[3]);
468 printf(" kr4: %016lx ", regs->ar.kr[4]);
469 printf(" kr5: %016lx\n", regs->ar.kr[5]);
470 printf(" kr6: %016lx ", regs->ar.kr[6]);
471 printf(" kr7: %016lx ", regs->ar.kr[7]);
472 printf(" rsc: %016lx\n", regs->ar.rsc);
473 printf(" bsp: %016lx ", regs->ar.bsp);
474 printf(" bsps: %016lx ", regs->ar.bspstore);
475 printf(" rnat: %016lx\n", regs->ar.rnat);
476 printf(" csd: %016lx ", regs->ar.csd);
477 printf(" ccv: %016lx ", regs->ar.ccv);
478 printf(" unat: %016lx\n", regs->ar.unat);
479 printf(" fpsr: %016lx ", regs->ar.fpsr);
480 printf(" itc: %016lx\n", regs->ar.itc);
481 printf(" pfs: %016lx ", regs->ar.pfs);
482 printf(" lc: %016lx ", regs->ar.lc);
483 printf(" ec: %016lx\n", regs->ar.ec);
484 }
485 printf("\n");
486 printf(" r1: %016lx ", regs->r[1]);
487 printf(" r2: %016lx ", regs->r[2]);
488 printf(" r3: %016lx\n", regs->r[3]);
489 printf(" r4: %016lx ", regs->r[4]);
490 printf(" r5: %016lx ", regs->r[5]);
491 printf(" r6: %016lx\n", regs->r[6]);
492 printf(" r7: %016lx ", regs->r[7]);
493 printf(" r8: %016lx ", regs->r[8]);
494 printf(" r9: %016lx\n", regs->r[9]);
495 printf(" r10: %016lx ", regs->r[10]);
496 printf(" r11: %016lx ", regs->r[11]);
497 printf(" sp: %016lx\n", regs->r[12]);
498 printf(" tp: %016lx ", regs->r[13]);
499 printf(" r14: %016lx ", regs->r[14]);
500 printf(" r15: %016lx\n", regs->r[15]);
501 if (disp_bank_regs) {
502 printf(" Bank %d (current) Bank %d\n",
503 (regs->psr & PSR_BN) ? 1 : 0, (regs->psr & PSR_BN) ? 0 : 1);
504 printf ("16:%016lx ", regs->r[16]);
505 printf ("17:%016lx ", regs->r[17]);
506 printf ("16:%016lx ", regs->bank[0]);
507 printf ("17:%016lx\n", regs->bank[1]);
508 printf ("18:%016lx ", regs->r[18]);
509 printf ("19:%016lx ", regs->r[19]);
510 printf ("18:%016lx ", regs->bank[2]);
511 printf ("19:%016lx\n", regs->bank[3]);
512 printf ("20:%016lx ", regs->r[20]);
513 printf ("21:%016lx ", regs->r[21]);
514 printf ("20:%016lx ", regs->bank[4]);
515 printf ("21:%016lx\n", regs->bank[5]);
516 printf ("22:%016lx ", regs->r[22]);
517 printf ("23:%016lx ", regs->r[23]);
518 printf ("22:%016lx ", regs->bank[6]);
519 printf ("23:%016lx\n", regs->bank[7]);
520 printf ("24:%016lx ", regs->r[24]);
521 printf ("25:%016lx ", regs->r[25]);
522 printf ("24:%016lx ", regs->bank[8]);
523 printf ("25:%016lx\n", regs->bank[9]);
524 printf ("26:%016lx ", regs->r[26]);
525 printf ("27:%016lx ", regs->r[27]);
526 printf ("26:%016lx ", regs->bank[10]);
527 printf ("27:%016lx\n", regs->bank[11]);
528 printf ("28:%016lx ", regs->r[28]);
529 printf ("29:%016lx ", regs->r[29]);
530 printf ("28:%016lx ", regs->bank[12]);
531 printf ("29:%016lx\n", regs->bank[13]);
532 printf ("30:%016lx ", regs->r[30]);
533 printf ("31:%016lx ", regs->r[31]);
534 printf ("30:%016lx ", regs->bank[14]);
535 printf ("31:%016lx\n", regs->bank[15]);
536 } else {
537 printf(" r16: %016lx ", regs->r[16]);
538 printf(" r17: %016lx ", regs->r[17]);
539 printf(" r18: %016lx\n", regs->r[18]);
540 printf(" r19: %016lx ", regs->r[19]);
541 printf(" r20: %016lx ", regs->r[20]);
542 printf(" r21: %016lx\n", regs->r[21]);
543 printf(" r22: %016lx ", regs->r[22]);
544 printf(" r23: %016lx ", regs->r[23]);
545 printf(" r24: %016lx\n", regs->r[24]);
546 printf(" r25: %016lx ", regs->r[25]);
547 printf(" r26: %016lx ", regs->r[26]);
548 printf(" r27: %016lx\n", regs->r[27]);
549 printf(" r28: %016lx ", regs->r[28]);
550 printf(" r29: %016lx ", regs->r[29]);
551 printf(" r30: %016lx\n", regs->r[30]);
552 printf(" r31: %016lx\n", regs->r[31]);
553 }
555 printf("\n");
556 rbs_size = (regs->ar.bsp - regs->ar.bspstore) / 8;
557 cfm_sof = (regs->cfm & CFM_SOF_MASK);
558 for (i = 0; i < cfm_sof; i++) {
559 int off = cfm_sof - i;
560 unsigned int rbs_off =
561 (((62 - ((rbs_size + regs->rbs_voff) % 63) + off)) / 63) + off;
562 if (rbs_off > rbs_size)
563 break;
564 printf(" r%02d: %016lx%s", 32 + i,
565 regs->rbs[rbs_size - rbs_off],
566 (i % 3) != 2 ? " " : "\n");
567 }
568 if ((i % 3) != 0)
569 printf ("\n");
571 if (disp_tlb) {
572 printf("\n itr: P rid va pa ps ed pl "
573 "ar a d ma key\n");
574 for (i = 0; i < 8; i++)
575 print_tr(i, &tr->itrs[i]);
576 printf("\n dtr: P rid va pa ps ed pl "
577 "ar a d ma key\n");
578 for (i = 0; i < 8; i++)
579 print_tr(i, &tr->dtrs[i]);
580 }
581 }
582 #endif
584 #ifndef NO_TRANSLATION
585 void *map_page(vcpu_guest_context_t *ctx, int vcpu, size_t virt)
586 {
587 static unsigned long previous_mfn = 0;
588 static void *mapped = NULL;
590 unsigned long mfn = xc_translate_foreign_address(xc_handle, domid, vcpu, virt);
591 unsigned long offset = virt & ~XC_PAGE_MASK;
593 if (mapped && mfn == previous_mfn)
594 goto out;
596 if (mapped)
597 munmap(mapped, XC_PAGE_SIZE);
599 previous_mfn = mfn;
601 mapped = xc_map_foreign_range(xc_handle, domid, XC_PAGE_SIZE, PROT_READ, mfn);
603 if (mapped == NULL) {
604 fprintf(stderr, "failed to map page.\n");
605 exit(-1);
606 }
608 out:
609 return (void *)(mapped + offset);
610 }
612 void print_stack(vcpu_guest_context_t *ctx, int vcpu)
613 {
614 struct cpu_user_regs *regs = &ctx->user_regs;
615 size_t stack = STACK_POINTER(regs);
616 size_t stack_limit = (STACK_POINTER(regs) & XC_PAGE_MASK) + XC_PAGE_SIZE;
617 size_t frame;
618 size_t instr;
619 size_t *p;
620 int i;
622 printf("\n");
623 printf("Stack:\n");
624 for (i=1; i<STACK_ROWS+1 && stack < stack_limit; i++) {
625 while(stack < stack_limit && stack < STACK_POINTER(regs) + i*STACK_COLS*sizeof(stack)) {
626 p = map_page(ctx, vcpu, stack);
627 printf(" " FMT_SIZE_T, *p);
628 stack += sizeof(stack);
629 }
630 printf("\n");
631 }
632 printf("\n");
634 printf("Code:\n");
635 instr = INSTR_POINTER(regs) - 21;
636 for(i=0; i<32; i++) {
637 unsigned char *c = map_page(ctx, vcpu, instr+i);
638 if (instr+i == INSTR_POINTER(regs))
639 printf("<%02x> ", *c);
640 else
641 printf("%02x ", *c);
642 }
643 printf("\n");
645 printf("\n");
647 if(stack_trace)
648 printf("Stack Trace:\n");
649 else
650 printf("Call Trace:\n");
651 printf("%c [<" FMT_SIZE_T ">] ",
652 stack_trace ? '*' : ' ', INSTR_POINTER(regs));
654 print_symbol(INSTR_POINTER(regs));
655 printf(" <--\n");
656 if (frame_ptrs) {
657 stack = STACK_POINTER(regs);
658 frame = FRAME_POINTER(regs);
659 while(frame && stack < stack_limit) {
660 if (stack_trace) {
661 while (stack < frame) {
662 p = map_page(ctx, vcpu, stack);
663 printf("| " FMT_SIZE_T " ", *p);
664 printf("\n");
665 stack += sizeof(*p);
666 }
667 } else {
668 stack = frame;
669 }
671 p = map_page(ctx, vcpu, stack);
672 frame = *p;
673 if (stack_trace)
674 printf("|-- " FMT_SIZE_T "\n", *p);
675 stack += sizeof(*p);
677 if (frame) {
678 p = map_page(ctx, vcpu, stack);
679 printf("%c [<" FMT_SIZE_T ">] ", stack_trace ? '|' : ' ', *p);
680 print_symbol(*p);
681 printf("\n");
682 stack += sizeof(*p);
683 }
684 }
685 } else {
686 stack = STACK_POINTER(regs);
687 while(stack < stack_limit) {
688 p = map_page(ctx, vcpu, stack);
689 if (is_kernel_text(*p)) {
690 printf(" [<" FMT_SIZE_T ">] ", *p);
691 print_symbol(*p);
692 printf("\n");
693 } else if (stack_trace) {
694 printf(" " FMT_SIZE_T "\n", *p);
695 }
696 stack += sizeof(*p);
697 }
698 }
699 }
700 #endif
702 void dump_ctx(int vcpu)
703 {
704 int ret;
705 vcpu_guest_context_t ctx;
706 xc_dominfo_t dominfo;
708 xc_handle = xc_interface_open(); /* for accessing control interface */
710 ret = xc_domain_getinfo(xc_handle, domid, 1, &dominfo);
711 if (ret < 0) {
712 perror("xc_domain_getinfo");
713 exit(-1);
714 }
716 ret = xc_domain_pause(xc_handle, domid);
717 if (ret < 0) {
718 perror("xc_domain_pause");
719 exit(-1);
720 }
722 ret = xc_vcpu_getcontext(xc_handle, domid, vcpu, &ctx);
723 if (ret < 0) {
724 if (!dominfo.paused)
725 xc_domain_unpause(xc_handle, domid);
726 perror("xc_vcpu_getcontext");
727 exit(-1);
728 }
730 print_ctx(&ctx);
731 #ifndef NO_TRANSLATION
732 if (is_kernel_text(INSTR_POINTER((&ctx.user_regs))))
733 print_stack(&ctx, vcpu);
734 #endif
736 if (!dominfo.paused) {
737 ret = xc_domain_unpause(xc_handle, domid);
738 if (ret < 0) {
739 perror("xc_domain_unpause");
740 exit(-1);
741 }
742 }
744 xc_interface_close(xc_handle);
745 if (ret < 0) {
746 perror("xc_interface_close");
747 exit(-1);
748 }
749 }
751 void usage(void)
752 {
753 printf("usage:\n\n");
755 printf(" xenctx [options] <DOMAIN> [VCPU]\n\n");
757 printf("options:\n");
758 printf(" -f, --frame-pointers\n");
759 printf(" assume the kernel was compiled with\n");
760 printf(" frame pointers.\n");
761 printf(" -s SYMTAB, --symbol-table=SYMTAB\n");
762 printf(" read symbol table from SYMTAB.\n");
763 printf(" --stack-trace print a complete stack trace.\n");
764 #ifdef __ia64__
765 printf(" -r LIST, --regs=LIST display more registers.\n");
766 printf(" -a --all same as --regs=tlb,cr,ar,br,bk\n");
767 #else
768 printf(" -a --all display more registers\n");
769 #endif
770 }
772 int main(int argc, char **argv)
773 {
774 int ch;
775 static const char *sopts = "fs:h"
776 #ifdef __ia64__
777 "ar:"
778 #endif
779 ;
780 static const struct option lopts[] = {
781 {"stack-trace", 0, NULL, 'S'},
782 {"symbol-table", 1, NULL, 's'},
783 {"frame-pointers", 0, NULL, 'f'},
784 #ifdef __ia64__
785 {"regs", 1, NULL, 'r'},
786 {"all", 0, NULL, 'a'},
787 #endif
788 {"help", 0, NULL, 'h'},
789 {0, 0, 0, 0}
790 };
791 const char *symbol_table = NULL;
793 int vcpu = 0;
795 while ((ch = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) {
796 switch(ch) {
797 case 'f':
798 frame_ptrs = 1;
799 break;
800 case 's':
801 symbol_table = optarg;
802 break;
803 case 'S':
804 stack_trace = 1;
805 break;
806 #ifdef __ia64__
807 case 'r':
808 {
809 char *r;
811 r = strtok(optarg, ",");
812 while (r) {
813 if (strcmp (r, "cr") == 0)
814 disp_cr_regs = 1;
815 else if (strcmp (r, "ar") == 0)
816 disp_ar_regs = 1;
817 else if (strcmp (r, "br") == 0)
818 disp_br_regs = 1;
819 else if (strcmp (r, "bk") == 0)
820 disp_bank_regs = 1;
821 else if (strcmp (r, "tlb") == 0)
822 disp_tlb = 1;
823 else {
824 fprintf(stderr,"unknown register set %s\n", r);
825 exit(-1);
826 }
827 r = strtok(NULL, "'");
828 }
829 }
830 break;
831 case 'a':
832 disp_cr_regs = 1;
833 disp_ar_regs = 1;
834 disp_br_regs = 1;
835 disp_bank_regs = 1;
836 disp_tlb = 1;
837 break;
838 #else
839 case 'a':
840 disp_all = 1;
841 break;
842 #endif
843 case 'h':
844 usage();
845 exit(-1);
846 case '?':
847 fprintf(stderr, "%s --help for more options\n", argv[0]);
848 exit(-1);
849 }
850 }
852 argv += optind; argc -= optind;
854 if (argc < 1 || argc > 2) {
855 printf("usage: xenctx [options] <domid> <optional vcpu>\n");
856 exit(-1);
857 }
859 domid = atoi(argv[0]);
860 if (domid==0) {
861 fprintf(stderr, "cannot trace dom0\n");
862 exit(-1);
863 }
865 if (argc == 2)
866 vcpu = atoi(argv[1]);
868 if (symbol_table)
869 read_symbol_table(symbol_table);
871 dump_ctx(vcpu);
873 return 0;
874 }
876 /*
877 * Local variables:
878 * mode: C
879 * c-set-style: "BSD"
880 * c-basic-offset: 4
881 * tab-width: 4
882 * indent-tabs-mode: nil
883 * End:
884 */