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  */
11 
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 <ctype.h>
23 #include <string.h>
24 #include <inttypes.h>
25 #include <getopt.h>
26 #include <limits.h>
27 
28 #define XC_WANT_COMPAT_MAP_FOREIGN_API
29 #include <xenctrl.h>
30 #include <xen/foreign/x86_32.h>
31 #include <xen/foreign/x86_64.h>
32 #include <xen/hvm/save.h>
33 
34 #define DEFAULT_NR_STACK_PAGES 1
35 #define DEFAULT_BYTES_PER_LINE 32
36 #define DEFAULT_LINES 5
37 
38 /* Note: the order of these matter.
39  * NOT_KERNEL_ADDR must be < both KERNEL_DATA_ADDR and KERNEL_TEXT_ADDR.
40  * KERNEL_DATA_ADDR must be < KERNEL_TEXT_ADDR. */
41 typedef enum type_of_addr_ {
42     NOT_KERNEL_ADDR,
43     KERNEL_DATA_ADDR,
44     KERNEL_TEXT_ADDR,
45 } type_of_addr;
46 
47 #if defined (__i386__) || defined (__x86_64__)
48 static const uint64_t cr_reg_mask[5] = { [2] = ~UINT64_C(0) };
49 static const uint64_t dr_reg_mask[8] = { [0 ... 3] = ~UINT64_C(0) };
50 typedef unsigned long long guest_word_t;
51 #define FMT_16B_WORD "%04llx"
52 #define FMT_32B_WORD "%08llx"
53 #define FMT_64B_WORD "%016llx"
54 /* Word-length of the guest's own data structures */
55 int guest_word_size = sizeof (unsigned long);
56 /* Word-length of the context record we get from xen */
57 int ctxt_word_size = sizeof (unsigned long);
58 int guest_protected_mode = 1;
59 #elif defined(__arm__)
60 #define NO_TRANSLATION
61 typedef uint64_t guest_word_t;
62 #define FMT_16B_WORD "%04llx"
63 #define FMT_32B_WORD "%08llx"
64 #define FMT_64B_WORD "%016llx"
65 #elif defined(__aarch64__)
66 #define NO_TRANSLATION
67 typedef uint64_t guest_word_t;
68 #define FMT_16B_WORD "%04llx"
69 #define FMT_32B_WORD "%08llx"
70 #define FMT_64B_WORD "%016llx"
71 #endif
72 
73 #define MAX_BYTES_PER_LINE 128
74 
75 static struct xenctx {
76     xc_interface *xc_handle;
77     int domid;
78     int frame_ptrs;
79     int stack_trace;
80     int disp_all;
81     int nr_stack_pages;
82     int bytes_per_line;
83     int lines;
84     int decode_as_ascii;
85     int tag_stack_dump;
86     int tag_call_trace;
87     int all_vcpus;
88 #ifndef NO_TRANSLATION
89     guest_word_t mem_addr;
90     guest_word_t stk_addr;
91     int do_memory;
92     int do_stack;
93 #endif
94     int kernel_start_set;
95     xc_dominfo_t dominfo;
96 } xenctx;
97 
98 struct symbol {
99     guest_word_t address;
100     char *name;
101     struct symbol *next;
102 } *symbol_table = NULL;
103 
104 guest_word_t kernel_stext, kernel_etext, kernel_sinittext, kernel_einittext, kernel_hypercallpage;
105 guest_word_t kernel_text;
106 
107 #if defined (__i386__) || defined (__arm__)
108 unsigned long long kernel_start = 0xc0000000;
109 unsigned long long kernel_end = 0xffffffffULL;
110 #elif defined (__x86_64__)
111 unsigned long long kernel_start = 0xffffffff80000000UL;
112 unsigned long long kernel_end = 0xffffffffffffffffUL;
113 #elif defined (__aarch64__)
114 unsigned long long kernel_start = 0xffffff8000000000UL;
115 unsigned long long kernel_end = 0xffffffffffffffffULL;
116 #endif
117 
kernel_addr(guest_word_t addr)118 static type_of_addr kernel_addr(guest_word_t addr)
119 {
120     if ( symbol_table == NULL )
121     {
122         if ( addr > kernel_start )
123             return KERNEL_TEXT_ADDR;
124         else
125             return NOT_KERNEL_ADDR;
126     }
127 
128     if (addr >= kernel_stext &&
129         addr <= kernel_etext)
130         return KERNEL_TEXT_ADDR;
131     if ( kernel_hypercallpage &&
132          (addr >= kernel_hypercallpage &&
133           addr <= kernel_hypercallpage + 4096) )
134         return KERNEL_TEXT_ADDR;
135     if (addr >= kernel_sinittext &&
136         addr <= kernel_einittext)
137         return KERNEL_TEXT_ADDR;
138     if ( xenctx.kernel_start_set )
139     {
140         if ( addr > kernel_start )
141             return KERNEL_TEXT_ADDR;
142     } else {
143         if ( addr >= kernel_text &&
144              addr <= kernel_end )
145             return KERNEL_DATA_ADDR;
146         if ( addr >= kernel_start &&
147              addr <= kernel_end )
148             return KERNEL_TEXT_ADDR;
149     }
150     return NOT_KERNEL_ADDR;
151 }
152 
153 #if 0
154 static void free_symbol(struct symbol *symbol)
155 {
156     if (symbol == NULL)
157         return;
158     if (symbol->name)
159         free(symbol->name);
160     free(symbol);
161 }
162 #endif
163 
insert_symbol(struct symbol * symbol)164 static void insert_symbol(struct symbol *symbol)
165 {
166     static struct symbol *prev = NULL;
167     struct symbol *s = symbol_table;
168 
169     if (s == NULL) {
170         symbol_table = symbol;
171         symbol->next = NULL;
172         return;
173     }
174 
175     /* The System.map is usually already sorted... */
176     if (prev
177         && prev->address <= symbol->address
178         && (!prev->next || prev->next->address > symbol->address)) {
179         s = prev;
180     } else {
181         /* ... otherwise do crappy/slow search for the correct place */
182         while (s->next && s->next->address <= symbol->address)
183             s = s->next;
184     }
185 
186     symbol->next = s->next;
187     s->next = symbol;
188     prev = symbol;
189 }
190 
lookup_symbol(guest_word_t address)191 static struct symbol *lookup_symbol(guest_word_t address)
192 {
193     struct symbol *s = symbol_table;
194 
195     if (!s)
196         return NULL;
197 
198     while (s->next && s->next->address < address)
199         s = s->next;
200 
201     return s->next && s->next->address <= address ? s->next : s;
202 }
203 
print_symbol(guest_word_t addr,type_of_addr type)204 static void print_symbol(guest_word_t addr, type_of_addr type)
205 {
206     struct symbol *s;
207 
208     if ( kernel_addr(addr) < type )
209         return;
210 
211     s = lookup_symbol(addr);
212 
213     if (s==NULL)
214         return;
215 
216     if (addr==s->address)
217         printf(" %s", s->name);
218     else
219         printf(" %s+%#x", s->name, (unsigned int)(addr - s->address));
220 }
221 
read_symbol_table(const char * symtab)222 static void read_symbol_table(const char *symtab)
223 {
224     char type, line[256];
225     char *p;
226     struct symbol *symbol;
227     FILE *f;
228     guest_word_t address;
229 
230     f = fopen(symtab, "r");
231     if(f == NULL) {
232         fprintf(stderr, "failed to open symbol table %s\n", symtab);
233         exit(-1);
234     }
235 
236     while(!feof(f)) {
237         if(fgets(line,256,f)==NULL)
238             break;
239 
240         /* need more checks for syntax here... */
241         address = strtoull(line, &p, 16);
242         if (!isspace((uint8_t)*p++))
243             continue;
244         type = *p++;
245         if (!isalpha((uint8_t)type) && type != '?')
246             continue;
247         if (!isspace((uint8_t)*p++))
248             continue;
249 
250         /* in the future we should handle the module name
251          * being appended here, this would allow us to use
252          * /proc/kallsyms as our symbol table
253          */
254         if (p[strlen(p)-1] == '\n')
255             p[strlen(p)-1] = '\0';
256 
257         switch (type) {
258         case 'A': /* global absolute */
259         case 'a': /* local absolute */
260             break;
261         case 'U': /* undefined */
262         case 'v': /* undefined weak object */
263         case 'w': /* undefined weak function */
264             continue;
265         default:
266             symbol = malloc(sizeof(*symbol));
267             if (symbol == NULL) {
268                 fclose(f);
269                 return;
270             }
271 
272             symbol->address = address;
273             symbol->name = strdup(p);
274             if (symbol->name == NULL) {
275                 free(symbol);
276                 fclose(f);
277                 return;
278             }
279 
280             insert_symbol(symbol);
281             break;
282         }
283 
284         if (strcmp(p, "_stext") == 0)
285             kernel_stext = address;
286         else if (strcmp(p, "_etext") == 0)
287             kernel_etext = address;
288         else if ( strcmp(p, "_text") == 0 )
289             kernel_text = address;
290         else if ( strcmp(p, "_end") == 0 || strcmp(p, "__bss_stop") == 0 )
291             kernel_end = address;
292         else if (strcmp(p, "_sinittext") == 0)
293             kernel_sinittext = address;
294         else if (strcmp(p, "_einittext") == 0)
295             kernel_einittext = address;
296         else if (strcmp(p, "hypercall_page") == 0)
297             kernel_hypercallpage = address;
298     }
299 
300     fclose(f);
301 }
302 
303 #if defined(__i386__) || defined(__x86_64__)
304 #define CR0_PE  0x1
305 char *flag_values[22][2] =
306 {/*  clear,     set,       bit# */
307     { NULL,     "c"    }, // 0        Carry
308     { NULL,     NULL   }, // 1
309     { NULL,     "p"    }, // 2        Parity
310     { NULL,     NULL   }, // 3
311     { NULL,     "a"    }, // 4        Adjust
312     { NULL,     NULL   }, // 5
313     { "nz",     "z"    }, // 6        Zero
314     { NULL,     "s"    }, // 7        Sign
315     { NULL,     "tf"   }, // 8        Trap
316     { NULL,     "i"    }, // 9        Interrupt (enabled)
317     { NULL,     "d=b"  }, // 10       Direction
318     { NULL,     "o"    }, // 11       Overflow
319     { NULL,     NULL   }, // 12       12+13 == IOPL
320     { NULL,     NULL   }, // 13
321     { NULL,     "nt"   }, // 14       Nested Task
322     { NULL,     NULL   }, // 15
323     { NULL,     "rf"   }, // 16       Resume Flag
324     { NULL,     "v86"  }, // 17       Virtual 8086 mode
325     { NULL,     "ac"   }, // 18       Alignment Check (enabled)
326     { NULL,     "vif"  }, // 19       Virtual Interrupt (enabled)
327     { NULL,     "vip"  }, // 20       Virtual Interrupt Pending
328     { NULL,     "cid"  }  // 21       Cpuid Identification Flag
329 };
330 
print_flags(uint64_t flags)331 static void print_flags(uint64_t flags)
332 {
333     int i;
334 
335     printf("\nflags: %08" PRIx64, flags);
336     for (i = 21; i >= 0; i--) {
337         char *s = flag_values[i][(flags >> i) & 1];
338         if (s != NULL)
339             printf(" %s", s);
340     }
341     printf("\n");
342 }
343 
print_special(void * regs,const char * name,unsigned int mask,const uint64_t reg_is_addr_mask[],int width)344 static void print_special(void *regs, const char *name, unsigned int mask,
345                           const uint64_t reg_is_addr_mask[], int width)
346 {
347     unsigned int i;
348 
349     printf("\n");
350     for (i = 0; mask; mask >>= 1, ++i)
351         if (mask & 1) {
352             if ( width == 4 )
353             {
354                 printf("%s%u: %08"PRIx32, name, i, ((uint32_t *) regs)[i]);
355                 if ( reg_is_addr_mask[i] )
356                     print_symbol(reg_is_addr_mask[i] & ((uint32_t *) regs)[i],
357                                  KERNEL_DATA_ADDR);
358             }
359             else
360             {
361                 printf("%s%u: %016"PRIx64, name, i, ((uint64_t *) regs)[i]);
362                 if ( reg_is_addr_mask[i] )
363                     print_symbol(reg_is_addr_mask[i] & ((uint64_t *) regs)[i],
364                                  KERNEL_DATA_ADDR);
365             }
366             printf("\n");
367         }
368 }
369 
print_ctx_32(vcpu_guest_context_x86_32_t * ctx)370 static void print_ctx_32(vcpu_guest_context_x86_32_t *ctx)
371 {
372     struct cpu_user_regs_x86_32 *regs = &ctx->user_regs;
373 
374     printf("cs:eip: %04x:%08x", regs->cs, regs->eip);
375     print_symbol(regs->eip, KERNEL_TEXT_ADDR);
376     print_flags(regs->eflags);
377     printf("ss:esp: %04x:%08x\n", regs->ss, regs->esp);
378 
379     printf("eax: %08x\t", regs->eax);
380     printf("ebx: %08x\t", regs->ebx);
381     printf("ecx: %08x\t", regs->ecx);
382     printf("edx: %08x\n", regs->edx);
383 
384     printf("esi: %08x\t", regs->esi);
385     printf("edi: %08x\t", regs->edi);
386     printf("ebp: %08x\n", regs->ebp);
387 
388     printf(" ds:     %04x\t", regs->ds);
389     printf(" es:     %04x\t", regs->es);
390     printf(" fs:     %04x\t", regs->fs);
391     printf(" gs:     %04x\n", regs->gs);
392 
393     if (xenctx.disp_all) {
394         print_special(ctx->ctrlreg, "cr", 0x1d, cr_reg_mask, 4);
395         print_special(ctx->debugreg, "dr", 0xcf, dr_reg_mask, 4);
396     }
397 }
398 
print_ctx_32on64(vcpu_guest_context_x86_64_t * ctx)399 static void print_ctx_32on64(vcpu_guest_context_x86_64_t *ctx)
400 {
401     struct cpu_user_regs_x86_64 *regs = &ctx->user_regs;
402 
403     printf("cs:eip: %04x:%08x", regs->cs, (uint32_t)regs->eip);
404     print_symbol((uint32_t)regs->eip, KERNEL_TEXT_ADDR);
405     print_flags((uint32_t)regs->eflags);
406     printf("ss:esp: %04x:%08x\n", regs->ss, (uint32_t)regs->esp);
407 
408     printf("eax: %08x\t", (uint32_t)regs->eax);
409     printf("ebx: %08x\t", (uint32_t)regs->ebx);
410     printf("ecx: %08x\t", (uint32_t)regs->ecx);
411     printf("edx: %08x\n", (uint32_t)regs->edx);
412 
413     printf("esi: %08x\t", (uint32_t)regs->esi);
414     printf("edi: %08x\t", (uint32_t)regs->edi);
415     printf("ebp: %08x\n", (uint32_t)regs->ebp);
416 
417     printf(" ds:     %04x\t", regs->ds);
418     printf(" es:     %04x\t", regs->es);
419     printf(" fs:     %04x\t", regs->fs);
420     printf(" gs:     %04x\n", regs->gs);
421 
422     if (xenctx.disp_all) {
423         uint32_t tmp_regs[8];
424         int i;
425 
426         for (i = 0; i < 5; i++)
427             tmp_regs[i] = ctx->ctrlreg[i];
428         print_special(tmp_regs, "cr", 0x1d, cr_reg_mask, 4);
429         for (i = 0; i < 8; i++)
430             tmp_regs[i] = ctx->debugreg[i];
431         print_special(tmp_regs, "dr", 0xcf, dr_reg_mask, 4);
432     }
433 }
434 
print_ctx_64(vcpu_guest_context_x86_64_t * ctx)435 static void print_ctx_64(vcpu_guest_context_x86_64_t *ctx)
436 {
437     struct cpu_user_regs_x86_64 *regs = &ctx->user_regs;
438 
439     printf("rip: %016"PRIx64, regs->rip);
440     print_symbol(regs->rip, KERNEL_TEXT_ADDR);
441     print_flags(regs->rflags);
442     printf("rsp: %016"PRIx64"\n", regs->rsp);
443 
444     printf("rax: %016"PRIx64"\t", regs->rax);
445     printf("rcx: %016"PRIx64"\t", regs->rcx);
446     printf("rdx: %016"PRIx64"\n", regs->rdx);
447 
448     printf("rbx: %016"PRIx64"\t", regs->rbx);
449     printf("rsi: %016"PRIx64"\t", regs->rsi);
450     printf("rdi: %016"PRIx64"\n", regs->rdi);
451 
452     printf("rbp: %016"PRIx64"\t", regs->rbp);
453     printf(" r8: %016"PRIx64"\t", regs->r8);
454     printf(" r9: %016"PRIx64"\n", regs->r9);
455 
456     printf("r10: %016"PRIx64"\t", regs->r10);
457     printf("r11: %016"PRIx64"\t", regs->r11);
458     printf("r12: %016"PRIx64"\n", regs->r12);
459 
460     printf("r13: %016"PRIx64"\t", regs->r13);
461     printf("r14: %016"PRIx64"\t", regs->r14);
462     printf("r15: %016"PRIx64"\n", regs->r15);
463 
464     printf(" cs: %04x\t", regs->cs);
465     printf(" ss: %04x\t", regs->ss);
466     printf(" ds: %04x\t", regs->ds);
467     printf(" es: %04x\n", regs->es);
468 
469     printf(" fs: %04x @ %016"PRIx64, regs->fs, ctx->fs_base);
470     print_symbol(ctx->fs_base, KERNEL_DATA_ADDR);
471     printf("\n");
472     printf(" gs: %04x @ %016"PRIx64"/%016"PRIx64, regs->gs,
473            ctx->gs_base_kernel, ctx->gs_base_user);
474     if ( symbol_table )
475     {
476         print_symbol(ctx->gs_base_kernel, KERNEL_DATA_ADDR);
477         printf("/");
478         print_symbol(ctx->gs_base_user, KERNEL_DATA_ADDR);
479     }
480     printf("\n");
481 
482     if (xenctx.disp_all) {
483         print_special(ctx->ctrlreg, "cr", 0x1d, cr_reg_mask, 8);
484         print_special(ctx->debugreg, "dr", 0xcf, dr_reg_mask, 8);
485     }
486 }
487 
print_ctx(vcpu_guest_context_any_t * ctx)488 static void print_ctx(vcpu_guest_context_any_t *ctx)
489 {
490     if (ctxt_word_size == 4)
491         print_ctx_32(&ctx->x32);
492     else if (guest_word_size != 8)
493         print_ctx_32on64(&ctx->x64);
494     else
495         print_ctx_64(&ctx->x64);
496 }
497 
498 #define NONPROT_MODE_SEGMENT_SHIFT 4
499 
instr_pointer(vcpu_guest_context_any_t * ctx)500 static guest_word_t instr_pointer(vcpu_guest_context_any_t *ctx)
501 {
502     guest_word_t r;
503     if (ctxt_word_size == 4)
504     {
505         r = ctx->x32.user_regs.eip;
506 
507         if ( !guest_protected_mode )
508             r += ctx->x32.user_regs.cs << NONPROT_MODE_SEGMENT_SHIFT;
509     }
510     else
511     {
512         r = ctx->x64.user_regs.rip;
513 
514         if ( !guest_protected_mode )
515             r += ctx->x64.user_regs.cs << NONPROT_MODE_SEGMENT_SHIFT;
516     }
517 
518     return r;
519 }
520 
stack_pointer(vcpu_guest_context_any_t * ctx)521 static guest_word_t stack_pointer(vcpu_guest_context_any_t *ctx)
522 {
523     guest_word_t r;
524     if (ctxt_word_size == 4)
525     {
526         r = ctx->x32.user_regs.esp;
527 
528         if ( !guest_protected_mode )
529             r += ctx->x32.user_regs.ss << NONPROT_MODE_SEGMENT_SHIFT;
530     }
531     else
532     {
533         r = ctx->x64.user_regs.rsp;
534 
535         if ( !guest_protected_mode )
536             r += ctx->x64.user_regs.ss << NONPROT_MODE_SEGMENT_SHIFT;
537     }
538 
539     return r;
540 }
541 
frame_pointer(vcpu_guest_context_any_t * ctx)542 static guest_word_t frame_pointer(vcpu_guest_context_any_t *ctx)
543 {
544     if (ctxt_word_size == 4)
545         return ctx->x32.user_regs.ebp;
546     else
547         return ctx->x64.user_regs.rbp;
548 }
549 
550 #elif defined(__arm__) || defined(__aarch64__)
551 
print_ctx_32(vcpu_guest_context_t * ctx)552 static void print_ctx_32(vcpu_guest_context_t *ctx)
553 {
554     vcpu_guest_core_regs_t *regs = &ctx->user_regs;
555 
556     printf("PC:       %08"PRIx32, regs->pc32);
557     print_symbol(regs->pc32, KERNEL_TEXT_ADDR);
558     printf("\n");
559     printf("CPSR:     %08"PRIx32"\n", regs->cpsr);
560     printf("USR:               SP:%08"PRIx32" LR:%08"PRIx32"\n",
561            regs->sp_usr, regs->lr_usr);
562     printf("SVC: SPSR:%08"PRIx32" SP:%08"PRIx32" LR:%08"PRIx32"\n",
563            regs->spsr_svc, regs->sp_svc, regs->lr_svc);
564     printf("FIQ: SPSR:%08"PRIx32" SP:%08"PRIx32" LR:%08"PRIx32"\n",
565            regs->spsr_fiq, regs->sp_fiq, regs->lr_fiq);
566     printf("IRQ: SPSR:%08"PRIx32" SP:%08"PRIx32" LR:%08"PRIx32"\n",
567            regs->spsr_irq, regs->sp_irq, regs->lr_irq);
568     printf("ABT: SPSR:%08"PRIx32" SP:%08"PRIx32" LR:%08"PRIx32"\n",
569            regs->spsr_abt, regs->sp_abt, regs->lr_abt);
570     printf("UND: SPSR:%08"PRIx32" SP:%08"PRIx32" LR:%08"PRIx32"\n",
571            regs->spsr_und, regs->sp_und, regs->lr_und);
572 
573     printf("\n");
574     printf(" r0_usr: %08"PRIx32"\t", regs->r0_usr);
575     printf(" r1_usr: %08"PRIx32"\t", regs->r1_usr);
576     printf(" r2_usr: %08"PRIx32"\n", regs->r2_usr);
577 
578     printf(" r3_usr: %08"PRIx32"\t", regs->r3_usr);
579     printf(" r4_usr: %08"PRIx32"\t", regs->r4_usr);
580     printf(" r5_usr: %08"PRIx32"\n", regs->r5_usr);
581 
582     printf(" r6_usr: %08"PRIx32"\t", regs->r6_usr);
583     printf(" r7_usr: %08"PRIx32"\t", regs->r7_usr);
584     printf(" r8_usr: %08"PRIx32"\n", regs->r8_usr);
585 
586     printf(" r9_usr: %08"PRIx32"\t", regs->r9_usr);
587     printf("r10_usr: %08"PRIx32"\t", regs->r10_usr);
588     printf("r11_usr: %08"PRIx32"\n", regs->r11_usr);
589 
590     printf("r12_usr: %08"PRIx32"\n", regs->r12_usr);
591     printf("\n");
592 
593     printf(" r8_fiq: %08"PRIx32"\n", regs->r8_fiq);
594 
595     printf(" r9_fiq: %08"PRIx32"\t", regs->r9_fiq);
596     printf("r10_fiq: %08"PRIx32"\t", regs->r10_fiq);
597     printf("r11_fiq: %08"PRIx32"\n", regs->r11_fiq);
598 
599     printf("r12_fiq: %08"PRIx32"\n", regs->r12_fiq);
600     printf("\n");
601     /* SCTLR is always 32-bit */
602     printf("SCTLR: %08"PRIx32"\n", (uint32_t)ctx->sctlr);
603 }
604 
605 #ifdef __aarch64__
print_ctx_64(vcpu_guest_context_t * ctx)606 static void print_ctx_64(vcpu_guest_context_t *ctx)
607 {
608     vcpu_guest_core_regs_t *regs = &ctx->user_regs;
609 
610     printf("PC:       %016"PRIx64, regs->pc64);
611     print_symbol(regs->pc64, KERNEL_TEXT_ADDR);
612     printf("\n");
613 
614     printf("LR:       %016"PRIx64"\n", regs->x30);
615     printf("ELR_EL1:  %016"PRIx64"\n", regs->elr_el1);
616 
617     printf("CPSR:     %08"PRIx32"\n", regs->cpsr);
618     printf("SPSR_EL1: %08"PRIx32"\n", regs->spsr_el1);
619 
620     printf("SP_EL0:   %016"PRIx64"\n", regs->sp_el0);
621     printf("SP_EL1:   %016"PRIx64"\n", regs->sp_el1);
622 
623     printf("\n");
624     printf(" x0: %016"PRIx64"\t", regs->x0);
625     printf(" x1: %016"PRIx64"\t", regs->x1);
626     printf(" x2: %016"PRIx64"\n", regs->x2);
627 
628     printf(" x3: %016"PRIx64"\t", regs->x3);
629     printf(" x4: %016"PRIx64"\t", regs->x4);
630     printf(" x5: %016"PRIx64"\n", regs->x5);
631 
632     printf(" x6: %016"PRIx64"\t", regs->x6);
633     printf(" x7: %016"PRIx64"\t", regs->x7);
634     printf(" x8: %016"PRIx64"\n", regs->x8);
635 
636     printf(" x9: %016"PRIx64"\t", regs->x9);
637     printf("x10: %016"PRIx64"\t", regs->x10);
638     printf("x11: %016"PRIx64"\n", regs->x11);
639 
640     printf("x12: %016"PRIx64"\t", regs->x12);
641     printf("x13: %016"PRIx64"\t", regs->x13);
642     printf("x14: %016"PRIx64"\n", regs->x14);
643 
644     printf("x15: %016"PRIx64"\t", regs->x15);
645     printf("x16: %016"PRIx64"\t", regs->x16);
646     printf("x17: %016"PRIx64"\n", regs->x17);
647 
648     printf("x18: %016"PRIx64"\t", regs->x18);
649     printf("x19: %016"PRIx64"\t", regs->x19);
650     printf("x20: %016"PRIx64"\n", regs->x20);
651 
652     printf("x21: %016"PRIx64"\t", regs->x21);
653     printf("x22: %016"PRIx64"\t", regs->x22);
654     printf("x23: %016"PRIx64"\n", regs->x23);
655 
656     printf("x24: %016"PRIx64"\t", regs->x24);
657     printf("x25: %016"PRIx64"\t", regs->x25);
658     printf("x26: %016"PRIx64"\n", regs->x26);
659 
660     printf("x27: %016"PRIx64"\t", regs->x27);
661     printf("x28: %016"PRIx64"\t", regs->x28);
662     printf("x29: %016"PRIx64"\n", regs->x29);
663     printf("\n");
664     printf("SCTLR_EL1: %016"PRIx64"\n", ctx->sctlr);
665 }
666 #endif /* __aarch64__ */
667 
print_ctx(vcpu_guest_context_any_t * ctx_any)668 static void print_ctx(vcpu_guest_context_any_t *ctx_any)
669 {
670     vcpu_guest_context_t *ctx = &ctx_any->c;
671 
672 #ifdef __aarch64__
673     if (ctx->user_regs.cpsr & PSR_MODE_BIT)
674         print_ctx_32(ctx);
675     else
676         print_ctx_64(ctx);
677 #else
678     print_ctx_32(ctx);
679 #endif
680 
681     printf("TTBCR: %016"PRIx64"\n", ctx->ttbcr);
682     printf("TTBR0: %016"PRIx64"\n", ctx->ttbr0);
683     printf("TTBR1: %016"PRIx64"\n", ctx->ttbr1);
684 }
685 
686 #endif
687 
688 #ifndef NO_TRANSLATION
map_page(vcpu_guest_context_any_t * ctx,int vcpu,guest_word_t virt)689 static void *map_page(vcpu_guest_context_any_t *ctx, int vcpu, guest_word_t virt)
690 {
691     static unsigned long previous_mfn = 0;
692     static void *mapped = NULL;
693 
694     unsigned long mfn = xc_translate_foreign_address(xenctx.xc_handle, xenctx.domid, vcpu, virt);
695     unsigned long offset = virt & ~XC_PAGE_MASK;
696 
697     if (mapped && mfn == previous_mfn)
698         goto out;
699 
700     if (mapped)
701         munmap(mapped, XC_PAGE_SIZE);
702 
703     previous_mfn = mfn;
704 
705     mapped = xc_map_foreign_range(xenctx.xc_handle, xenctx.domid, XC_PAGE_SIZE, PROT_READ, mfn);
706 
707     if (mapped == NULL) {
708         fprintf(stderr, "\nfailed to map page for "FMT_32B_WORD".\n", virt);
709         return NULL;
710     }
711 
712  out:
713     return (void *)(mapped + offset);
714 }
715 
read_stack_word(guest_word_t * src,int width)716 static guest_word_t read_stack_word(guest_word_t *src, int width)
717 {
718     guest_word_t word = 0;
719     /* Little-endian only */
720     memcpy(&word, src, width);
721     return word;
722 }
723 
read_mem_word(vcpu_guest_context_any_t * ctx,int vcpu,guest_word_t virt,int width)724 static guest_word_t read_mem_word(vcpu_guest_context_any_t *ctx, int vcpu,
725                                   guest_word_t virt, int width)
726 {
727     if ( (virt & 7) == 0 )
728     {
729         guest_word_t *p = map_page(ctx, vcpu, virt);
730 
731         if ( p )
732             return read_stack_word(p, width);
733         else
734             return -1;
735     }
736     else
737     {
738         guest_word_t word = 0;
739         char *src, *dst;
740         int i;
741 
742         /* Little-endian only */
743         dst = (char *)&word;
744         for (i = 0; i < width; i++)
745         {
746             src = map_page(ctx, vcpu, virt + i);
747             if ( src )
748                 *dst++ = *src;
749             else
750             {
751                 guest_word_t missing = -1LL;
752 
753                 /* Return all ones for missing memory */
754                 memcpy(dst, &missing, width - i);
755                 return word;
756             }
757         }
758         return word;
759     }
760 }
761 
print_stack_word(guest_word_t word,int width)762 static void print_stack_word(guest_word_t word, int width)
763 {
764     if (width == 2)
765         printf(FMT_16B_WORD, word);
766     else if (width == 4)
767         printf(FMT_32B_WORD, word);
768     else
769         printf(FMT_64B_WORD, word);
770 }
771 
print_lines(vcpu_guest_context_any_t * ctx,int vcpu,int width,guest_word_t mem_addr,guest_word_t mem_limit)772 static int print_lines(vcpu_guest_context_any_t *ctx, int vcpu, int width,
773                        guest_word_t mem_addr, guest_word_t mem_limit)
774 {
775     guest_word_t mem_start = mem_addr;
776     guest_word_t word;
777     guest_word_t ascii[MAX_BYTES_PER_LINE/4];
778     int i;
779 
780     for (i = 1; i < xenctx.lines + 1 && mem_addr < mem_limit; i++)
781     {
782         int j = 0;
783         int k;
784 
785         if ( xenctx.tag_stack_dump )
786         {
787             print_stack_word(mem_addr, width);
788             printf(":");
789         }
790         while ( mem_addr < mem_limit &&
791                 mem_addr < mem_start + i * xenctx.bytes_per_line )
792         {
793             void *p = map_page(ctx, vcpu, mem_addr);
794             if ( !p )
795                 return -1;
796             word = read_mem_word(ctx, vcpu, mem_addr, width);
797             if ( xenctx.decode_as_ascii )
798                 ascii[j++] = word;
799             printf(" ");
800             print_stack_word(word, width);
801             mem_addr += width;
802         }
803         if ( xenctx.decode_as_ascii )
804         {
805             /*
806              * Line up ascii output if less than bytes_per_line
807              * were printed.
808              */
809             for (k = j; k < xenctx.bytes_per_line / width; k++)
810                 printf(" %*s", width * 2, "");
811             printf("  ");
812             for (k = 0; k < j; k++)
813             {
814                 int l;
815                 unsigned char *bytep = (unsigned char *)&ascii[k];
816 
817                 for (l = 0; l < width; l++)
818                 {
819                     if (isprint(*bytep))
820                         printf("%c", *bytep);
821                     else
822                         printf(".");
823                     bytep++;
824                 }
825             }
826         }
827         printf("\n");
828     }
829     printf("\n");
830     return 0;
831 }
832 
print_mem(vcpu_guest_context_any_t * ctx,int vcpu,int width,guest_word_t mem_addr)833 static void print_mem(vcpu_guest_context_any_t *ctx, int vcpu, int width,
834                           guest_word_t mem_addr)
835 {
836     printf("Memory (address ");
837     print_stack_word(mem_addr, width);
838     printf("):\n");
839     print_lines(ctx, vcpu, width, mem_addr,
840                 mem_addr + xenctx.lines * xenctx.bytes_per_line);
841 }
842 
print_code(vcpu_guest_context_any_t * ctx,int vcpu)843 static int print_code(vcpu_guest_context_any_t *ctx, int vcpu)
844 {
845     guest_word_t instr;
846     int i;
847 
848     instr = instr_pointer(ctx);
849     printf("Code (instr addr %08llx)\n", instr);
850     instr -= 21;
851     for(i=0; i<32; i++) {
852         unsigned char *c = map_page(ctx, vcpu, instr+i);
853         if (!c)
854             return -1;
855         if (instr+i == instr_pointer(ctx))
856             printf("<%02x> ", *c);
857         else
858             printf("%02x ", *c);
859     }
860     printf("\n\n\n");
861     return 0;
862 }
863 
print_stack_addr(guest_word_t addr,int width)864 static void print_stack_addr(guest_word_t addr, int width)
865 {
866     print_stack_word(addr, width);
867     printf(": ");
868 }
869 
print_stack(vcpu_guest_context_any_t * ctx,int vcpu,int width,guest_word_t stk_addr_start)870 static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width,
871                        guest_word_t stk_addr_start)
872 {
873     guest_word_t stack = stk_addr_start;
874     guest_word_t stack_limit;
875     guest_word_t frame;
876     guest_word_t word;
877     guest_word_t *p;
878 
879     if ( width )
880         xenctx.bytes_per_line =
881             ((xenctx.bytes_per_line + width - 1) / width) * width;
882     stack_limit = ((stack_pointer(ctx) + XC_PAGE_SIZE)
883                    & ~((guest_word_t) XC_PAGE_SIZE - 1))
884                    + (xenctx.nr_stack_pages - 1) * XC_PAGE_SIZE;
885     if ( xenctx.lines )
886     {
887         printf("Stack:\n");
888         if ( print_lines(ctx, vcpu, width, stack, stack_limit) )
889             return -1;
890     }
891 
892     if ( !guest_protected_mode )
893         return 0;
894 
895     if(xenctx.stack_trace)
896         printf("Stack Trace:\n");
897     else
898         printf("Call Trace:\n");
899     if ( !xenctx.do_stack )
900     {
901         printf("%*s  %c [<", width*2, "", xenctx.stack_trace ? '*' : ' ');
902         print_stack_word(instr_pointer(ctx), width);
903         printf(">]");
904 
905         print_symbol(instr_pointer(ctx), KERNEL_TEXT_ADDR);
906         printf(" <--\n");
907     }
908     if (xenctx.frame_ptrs) {
909         stack = stack_pointer(ctx);
910         frame = frame_pointer(ctx);
911         while(frame && stack < stack_limit) {
912             if (xenctx.stack_trace) {
913                 while (stack < frame) {
914                     p = map_page(ctx, vcpu, stack);
915                     if (!p)
916                         return -1;
917                     print_stack_addr(stack, width);
918                     printf("|   ");
919                     print_stack_word(read_stack_word(p, width), width);
920                     printf("\n");
921                     stack += width;
922                 }
923             } else {
924                 stack = frame;
925             }
926 
927             p = map_page(ctx, vcpu, stack);
928             if (!p)
929                 return -1;
930             frame = read_stack_word(p, width);
931             if (xenctx.stack_trace) {
932                 print_stack_addr(stack, width);
933                 printf("|-- ");
934                 print_stack_word(read_stack_word(p, width), width);
935                 printf("\n");
936             }
937             stack += width;
938 
939             if (frame) {
940                 p = map_page(ctx, vcpu, stack);
941                 if (!p)
942                     return -1;
943                 word = read_stack_word(p, width);
944                 print_stack_addr(stack, width);
945                 printf("%c [<", xenctx.stack_trace ? '|' : ' ');
946                 print_stack_word(word, width);
947                 printf(">]");
948                 print_symbol(word, KERNEL_TEXT_ADDR);
949                 printf("\n");
950                 stack += width;
951             }
952         }
953     } else {
954         stack = stk_addr_start;
955         while(stack < stack_limit) {
956             p = map_page(ctx, vcpu, stack);
957             if (!p)
958                 return -1;
959             word = read_mem_word(ctx, vcpu, stack, width);
960             if ( kernel_addr(word) >= KERNEL_TEXT_ADDR )
961             {
962                 print_stack_addr(stack, width);
963                 printf("  [<");
964                 print_stack_word(word, width);
965                 printf(">]");
966                 print_symbol(word, KERNEL_TEXT_ADDR);
967                 printf("\n");
968             } else if (xenctx.stack_trace) {
969                 print_stack_addr(stack, width);
970                 printf("    ");
971                 print_stack_word(word, width);
972                 printf("\n");
973             }
974             stack += width;
975         }
976     }
977     return 0;
978 }
979 #endif
980 
dump_ctx(int vcpu)981 static void dump_ctx(int vcpu)
982 {
983     vcpu_guest_context_any_t ctx;
984 
985     if (xc_vcpu_getcontext(xenctx.xc_handle, xenctx.domid, vcpu, &ctx) < 0) {
986         perror("xc_vcpu_getcontext");
987         return;
988     }
989 
990 #if defined(__i386__) || defined(__x86_64__)
991     {
992         if (xenctx.dominfo.hvm) {
993             struct hvm_hw_cpu cpuctx;
994             xen_capabilities_info_t xen_caps = "";
995             if (xc_domain_hvm_getcontext_partial(
996                     xenctx.xc_handle, xenctx.domid, HVM_SAVE_CODE(CPU),
997                     vcpu, &cpuctx, sizeof cpuctx) != 0) {
998                 perror("xc_domain_hvm_getcontext_partial");
999                 return;
1000             }
1001             guest_protected_mode = (cpuctx.cr0 & CR0_PE);
1002             guest_word_size = (cpuctx.msr_efer & 0x400) ? 8 :
1003                 guest_protected_mode ? 4 : 2;
1004             /* HVM guest context records are always host-sized */
1005             if (xc_version(xenctx.xc_handle, XENVER_capabilities, &xen_caps) != 0) {
1006                 perror("xc_version");
1007                 return;
1008             }
1009             ctxt_word_size = (strstr(xen_caps, "xen-3.0-x86_64")) ? 8 : 4;
1010         } else {
1011             unsigned int gw;
1012             if ( !xc_domain_get_guest_width(xenctx.xc_handle, xenctx.domid, &gw) )
1013                 ctxt_word_size = guest_word_size = gw;
1014         }
1015     }
1016 #endif
1017 
1018 #ifndef NO_TRANSLATION
1019     if ( xenctx.do_memory )
1020     {
1021         print_mem(&ctx, vcpu, guest_word_size, xenctx.mem_addr);
1022         return;
1023     }
1024     if ( xenctx.do_stack )
1025     {
1026         print_stack(&ctx, vcpu, guest_word_size, xenctx.stk_addr);
1027         return;
1028     }
1029 #endif
1030     print_ctx(&ctx);
1031 #ifndef NO_TRANSLATION
1032     if (print_code(&ctx, vcpu))
1033         return;
1034     if ( !guest_protected_mode ||
1035          kernel_addr(instr_pointer(&ctx)) >= KERNEL_TEXT_ADDR )
1036         if ( print_stack(&ctx, vcpu, guest_word_size,
1037                          stack_pointer(&ctx)) )
1038             return;
1039 #endif
1040 }
1041 
dump_all_vcpus(void)1042 static void dump_all_vcpus(void)
1043 {
1044     xc_vcpuinfo_t vinfo;
1045     int vcpu;
1046     for (vcpu = 0; vcpu <= xenctx.dominfo.max_vcpu_id; vcpu++)
1047     {
1048         if ( xc_vcpu_getinfo(xenctx.xc_handle, xenctx.domid, vcpu, &vinfo) )
1049             continue;
1050         if ( vinfo.online )
1051         {
1052             printf("vcpu%d:\n", vcpu);
1053             dump_ctx(vcpu);
1054             printf("\n");
1055         }
1056         else
1057             printf("vcpu%d offline\n\n", vcpu);
1058     }
1059 }
1060 
usage(void)1061 static void usage(void)
1062 {
1063     printf("usage:\n\n");
1064 
1065     printf("  xenctx [options] <DOMAIN> [VCPU]\n\n");
1066 
1067     printf("options:\n");
1068     printf("  -f, --frame-pointers\n");
1069     printf("                     assume the kernel was compiled with\n");
1070     printf("                     frame pointers.\n");
1071     printf("  -s SYMTAB, --symbol-table=SYMTAB\n");
1072     printf("                     read symbol table from SYMTAB.\n");
1073     printf("  -S, --stack-trace  print a complete stack trace.\n");
1074     printf("  -k KADDR, --kernel-start=KADDR\n");
1075     printf("                     set user/kernel split. (default 0x"FMT_32B_WORD")\n",
1076         kernel_start);
1077     printf("  -a, --all          display more registers\n");
1078     printf("  -C, --all-vcpus    print info for all vcpus\n");
1079     printf("  -n PAGES, --display-stack-pages=PAGES\n");
1080     printf("                     Display N pages from the stack pointer. (default %d)\n",
1081            DEFAULT_NR_STACK_PAGES);
1082     printf("                     Changes stack limit.  Note: use with caution (easy\n");
1083     printf("                     to get garbage).\n");
1084     printf("  -b <bytes>, --bytes-per-line <bytes>\n");
1085     printf("                     change the number of bytes per line output for Stack.\n");
1086     printf("                     (default %d) Note: rounded to native size (4 or 8 bytes).\n",
1087            DEFAULT_BYTES_PER_LINE);
1088     printf("  -l <lines>, --lines <lines>\n");
1089     printf("                     change the number of lines output for Stack. (default %d)\n",
1090            DEFAULT_LINES);
1091     printf("                     Can be specified as MAX.  Note: Fewer lines will be output\n");
1092     printf("                     if stack limit reached.\n");
1093     printf("  -D, --decode-as-ascii\n");
1094     printf("                     add a decode of Stack dump as ascii.\n");
1095     printf("  -t, --tag-stack-dump\n");
1096     printf("                     add address on each line of Stack dump.\n");
1097 #ifndef NO_TRANSLATION
1098     printf("  -m maddr, --memory=maddr\n");
1099     printf("                     dump memory at maddr.\n");
1100     printf("  -d daddr, --dump-as-stack=daddr\n");
1101     printf("                     dump memory as a stack at daddr.\n");
1102 #endif
1103 }
1104 
main(int argc,char ** argv)1105 int main(int argc, char **argv)
1106 {
1107     int ch;
1108     int ret;
1109     const char *prog = argv[0];
1110     static const char *sopts = "fs:hak:SCn:b:l:Dt"
1111 #ifndef NO_TRANSLATION
1112         "m:d:"
1113 #endif
1114         ;
1115     static const struct option lopts[] = {
1116         {"stack-trace", 0, NULL, 'S'},
1117         {"symbol-table", 1, NULL, 's'},
1118         {"frame-pointers", 0, NULL, 'f'},
1119         {"kernel-start", 1, NULL, 'k'},
1120         {"display-stack-pages", 0, NULL, 'n'},
1121         {"decode-as-ascii", 0, NULL, 'D'},
1122         {"tag-stack-dump", 0, NULL, 't'},
1123 #ifndef NO_TRANSLATION
1124         {"memory", 1, NULL, 'm'},
1125         {"dump-as-stack", 1, NULL, 'd'},
1126 #endif
1127         {"bytes-per-line", 1, NULL, 'b'},
1128         {"lines", 1, NULL, 'l'},
1129         {"all", 0, NULL, 'a'},
1130         {"all-vcpus", 0, NULL, 'C'},
1131         {"help", 0, NULL, 'h'},
1132         {0, 0, 0, 0}
1133     };
1134     const char *symbol_table = NULL;
1135 
1136     int vcpu = 0;
1137     int do_default = 1;
1138 
1139     xenctx.bytes_per_line = DEFAULT_BYTES_PER_LINE;
1140     xenctx.lines = DEFAULT_LINES;
1141     xenctx.nr_stack_pages = DEFAULT_NR_STACK_PAGES;
1142 
1143     while ((ch = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) {
1144         switch(ch) {
1145         case 'f':
1146             xenctx.frame_ptrs = 1;
1147             break;
1148         case 's':
1149             symbol_table = optarg;
1150             break;
1151         case 'S':
1152             xenctx.stack_trace = 1;
1153             break;
1154         case 'a':
1155             xenctx.disp_all = 1;
1156             break;
1157         case 'n':
1158             xenctx.nr_stack_pages = strtol(optarg, NULL, 0);
1159             if ( xenctx.nr_stack_pages < 1)
1160             {
1161                 fprintf(stderr,
1162                         "%s: Unsupported value(%d) for --display-stack-pages '%s'. Needs to be >= 1\n",
1163                         prog, xenctx.nr_stack_pages, optarg);
1164                 exit(-1);
1165             }
1166             break;
1167         case 'D':
1168             xenctx.decode_as_ascii = 1;
1169             break;
1170         case 't':
1171             xenctx.tag_stack_dump = 1;
1172             break;
1173         case 'b':
1174             xenctx.bytes_per_line = strtol(optarg, NULL, 0);
1175             if ( xenctx.bytes_per_line < 4 ||
1176                  xenctx.bytes_per_line > MAX_BYTES_PER_LINE )
1177             {
1178                 fprintf(stderr,
1179                         "%s: Unsupported value for --bytes-per-line '%s'. Needs to be 4 <= %d <= %d\n",
1180                         prog, optarg, xenctx.bytes_per_line,
1181                         MAX_BYTES_PER_LINE);
1182                 exit(-1);
1183             }
1184             break;
1185         case 'l':
1186             if ( !strcmp(optarg, "all") || !strcmp(optarg, "ALL") ||
1187                  !strcmp(optarg, "max") || !strcmp(optarg, "MAX") )
1188                 xenctx.lines = INT_MAX - 1;
1189             else
1190                 xenctx.lines = strtol(optarg, NULL, 0);
1191             if ( xenctx.lines < 0 || xenctx.lines == INT_MAX)
1192             {
1193                 fprintf(stderr,
1194                         "%s: Unsupported value(%d) for --lines '%s'. Needs to be >= 0, < %d\n",
1195                         prog, xenctx.lines, optarg, INT_MAX);
1196                 exit(-1);
1197             }
1198             break;
1199         case 'C':
1200             xenctx.all_vcpus = 1;
1201             do_default = 0;
1202             break;
1203         case 'k':
1204             kernel_start = strtoull(optarg, NULL, 0);
1205             xenctx.kernel_start_set = 1;
1206             break;
1207 #ifndef NO_TRANSLATION
1208         case 'm':
1209             xenctx.mem_addr = strtoull(optarg, NULL, 0);
1210             xenctx.do_memory = 1;
1211             do_default = 0;
1212             break;
1213         case 'd':
1214             xenctx.stk_addr = strtoull(optarg, NULL, 0);
1215             xenctx.do_stack = 1;
1216             do_default = 0;
1217             break;
1218 #endif
1219         case 'h':
1220             usage();
1221             exit(-1);
1222         case '?':
1223             fprintf(stderr, "%s --help for more options\n", prog);
1224             exit(-1);
1225         }
1226     }
1227 
1228     argv += optind; argc -= optind;
1229 
1230     if (argc < 1 || argc > 2) {
1231         printf("usage: xenctx [options] <domid> <optional vcpu>\n");
1232         exit(-1);
1233     }
1234 
1235 #ifndef NO_TRANSLATION
1236     if ( xenctx.frame_ptrs && xenctx.do_stack )
1237     {
1238         fprintf(stderr,
1239                 "%s: both --frame-pointers and --dump-as-stack is not supported\n",
1240                 prog);
1241         exit(-1);
1242     }
1243 #endif
1244 
1245     xenctx.domid = atoi(argv[0]);
1246     if (xenctx.domid==0) {
1247             fprintf(stderr, "cannot trace dom0\n");
1248             exit(-1);
1249     }
1250 
1251     if ( argc == 2 )
1252     {
1253         if ( xenctx.all_vcpus )
1254         {
1255             fprintf(stderr,
1256                     "%s: both --all-vcpus and [VCPU] is not supported\n",
1257                     prog);
1258             exit(-1);
1259         }
1260         vcpu = atoi(argv[1]);
1261     }
1262 
1263     if (symbol_table)
1264         read_symbol_table(symbol_table);
1265 
1266     xenctx.xc_handle = xc_interface_open(0,0,0); /* for accessing control interface */
1267     if (xenctx.xc_handle == NULL) {
1268         perror("xc_interface_open");
1269         exit(-1);
1270     }
1271 
1272     ret = xc_domain_getinfo(xenctx.xc_handle, xenctx.domid, 1, &xenctx.dominfo);
1273     if (ret < 0) {
1274         perror("xc_domain_getinfo");
1275         exit(-1);
1276     }
1277 
1278     ret = xc_domain_pause(xenctx.xc_handle, xenctx.domid);
1279     if (ret < 0) {
1280         perror("xc_domain_pause");
1281         exit(-1);
1282     }
1283 
1284 #ifndef NO_TRANSLATION
1285     if ( xenctx.do_memory )
1286     {
1287         dump_ctx(vcpu);
1288         if ( xenctx.do_stack || xenctx.all_vcpus )
1289             printf("\n");
1290     }
1291     xenctx.do_memory = 0;
1292     if ( xenctx.do_stack )
1293     {
1294         dump_ctx(vcpu);
1295         if ( xenctx.all_vcpus )
1296             printf("\n");
1297     }
1298     xenctx.do_stack = 0;
1299 #endif
1300     if (xenctx.all_vcpus)
1301         dump_all_vcpus();
1302     if ( do_default )
1303         dump_ctx(vcpu);
1304 
1305     ret = xc_domain_unpause(xenctx.xc_handle, xenctx.domid);
1306     if (ret < 0) {
1307         perror("xc_domain_unpause");
1308         exit(-1);
1309     }
1310 
1311     ret = xc_interface_close(xenctx.xc_handle);
1312     if (ret < 0) {
1313         perror("xc_interface_close");
1314         exit(-1);
1315     }
1316 
1317     return 0;
1318 }
1319 
1320 /*
1321  * Local variables:
1322  * mode: C
1323  * c-file-style: "BSD"
1324  * c-basic-offset: 4
1325  * tab-width: 4
1326  * indent-tabs-mode: nil
1327  * End:
1328  */
1329