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 }
602 
603 #ifdef __aarch64__
print_ctx_64(vcpu_guest_context_t * ctx)604 static void print_ctx_64(vcpu_guest_context_t *ctx)
605 {
606     vcpu_guest_core_regs_t *regs = &ctx->user_regs;
607 
608     printf("PC:       %016"PRIx64, regs->pc64);
609     print_symbol(regs->pc64, KERNEL_TEXT_ADDR);
610     printf("\n");
611 
612     printf("LR:       %016"PRIx64"\n", regs->x30);
613     printf("ELR_EL1:  %016"PRIx64"\n", regs->elr_el1);
614 
615     printf("CPSR:     %08"PRIx32"\n", regs->cpsr);
616     printf("SPSR_EL1: %08"PRIx32"\n", regs->spsr_el1);
617 
618     printf("SP_EL0:   %016"PRIx64"\n", regs->sp_el0);
619     printf("SP_EL1:   %016"PRIx64"\n", regs->sp_el1);
620 
621     printf("\n");
622     printf(" x0: %016"PRIx64"\t", regs->x0);
623     printf(" x1: %016"PRIx64"\t", regs->x1);
624     printf(" x2: %016"PRIx64"\n", regs->x2);
625 
626     printf(" x3: %016"PRIx64"\t", regs->x3);
627     printf(" x4: %016"PRIx64"\t", regs->x4);
628     printf(" x5: %016"PRIx64"\n", regs->x5);
629 
630     printf(" x6: %016"PRIx64"\t", regs->x6);
631     printf(" x7: %016"PRIx64"\t", regs->x7);
632     printf(" x8: %016"PRIx64"\n", regs->x8);
633 
634     printf(" x9: %016"PRIx64"\t", regs->x9);
635     printf("x10: %016"PRIx64"\t", regs->x10);
636     printf("x11: %016"PRIx64"\n", regs->x11);
637 
638     printf("x12: %016"PRIx64"\t", regs->x12);
639     printf("x13: %016"PRIx64"\t", regs->x13);
640     printf("x14: %016"PRIx64"\n", regs->x14);
641 
642     printf("x15: %016"PRIx64"\t", regs->x15);
643     printf("x16: %016"PRIx64"\t", regs->x16);
644     printf("x17: %016"PRIx64"\n", regs->x17);
645 
646     printf("x18: %016"PRIx64"\t", regs->x18);
647     printf("x19: %016"PRIx64"\t", regs->x19);
648     printf("x20: %016"PRIx64"\n", regs->x20);
649 
650     printf("x21: %016"PRIx64"\t", regs->x21);
651     printf("x22: %016"PRIx64"\t", regs->x22);
652     printf("x23: %016"PRIx64"\n", regs->x23);
653 
654     printf("x24: %016"PRIx64"\t", regs->x24);
655     printf("x25: %016"PRIx64"\t", regs->x25);
656     printf("x26: %016"PRIx64"\n", regs->x26);
657 
658     printf("x27: %016"PRIx64"\t", regs->x27);
659     printf("x28: %016"PRIx64"\t", regs->x28);
660     printf("x29: %016"PRIx64"\n", regs->x29);
661     printf("\n");
662 }
663 #endif /* __aarch64__ */
664 
print_ctx(vcpu_guest_context_any_t * ctx_any)665 static void print_ctx(vcpu_guest_context_any_t *ctx_any)
666 {
667     vcpu_guest_context_t *ctx = &ctx_any->c;
668 
669 #ifdef __aarch64__
670     if (ctx->user_regs.cpsr & PSR_MODE_BIT)
671         print_ctx_32(ctx);
672     else
673         print_ctx_64(ctx);
674 #else
675     print_ctx_32(ctx);
676 #endif
677 
678     printf("SCTLR: %08"PRIx32"\n", ctx->sctlr);
679     printf("TTBCR: %016"PRIx64"\n", ctx->ttbcr);
680     printf("TTBR0: %016"PRIx64"\n", ctx->ttbr0);
681     printf("TTBR1: %016"PRIx64"\n", ctx->ttbr1);
682 }
683 
684 #endif
685 
686 #ifndef NO_TRANSLATION
map_page(vcpu_guest_context_any_t * ctx,int vcpu,guest_word_t virt)687 static void *map_page(vcpu_guest_context_any_t *ctx, int vcpu, guest_word_t virt)
688 {
689     static unsigned long previous_mfn = 0;
690     static void *mapped = NULL;
691 
692     unsigned long mfn = xc_translate_foreign_address(xenctx.xc_handle, xenctx.domid, vcpu, virt);
693     unsigned long offset = virt & ~XC_PAGE_MASK;
694 
695     if (mapped && mfn == previous_mfn)
696         goto out;
697 
698     if (mapped)
699         munmap(mapped, XC_PAGE_SIZE);
700 
701     previous_mfn = mfn;
702 
703     mapped = xc_map_foreign_range(xenctx.xc_handle, xenctx.domid, XC_PAGE_SIZE, PROT_READ, mfn);
704 
705     if (mapped == NULL) {
706         fprintf(stderr, "\nfailed to map page for "FMT_32B_WORD".\n", virt);
707         return NULL;
708     }
709 
710  out:
711     return (void *)(mapped + offset);
712 }
713 
read_stack_word(guest_word_t * src,int width)714 static guest_word_t read_stack_word(guest_word_t *src, int width)
715 {
716     guest_word_t word = 0;
717     /* Little-endian only */
718     memcpy(&word, src, width);
719     return word;
720 }
721 
read_mem_word(vcpu_guest_context_any_t * ctx,int vcpu,guest_word_t virt,int width)722 static guest_word_t read_mem_word(vcpu_guest_context_any_t *ctx, int vcpu,
723                                   guest_word_t virt, int width)
724 {
725     if ( (virt & 7) == 0 )
726     {
727         guest_word_t *p = map_page(ctx, vcpu, virt);
728 
729         if ( p )
730             return read_stack_word(p, width);
731         else
732             return -1;
733     }
734     else
735     {
736         guest_word_t word = 0;
737         char *src, *dst;
738         int i;
739 
740         /* Little-endian only */
741         dst = (char *)&word;
742         for (i = 0; i < width; i++)
743         {
744             src = map_page(ctx, vcpu, virt + i);
745             if ( src )
746                 *dst++ = *src;
747             else
748             {
749                 guest_word_t missing = -1LL;
750 
751                 /* Return all ones for missing memory */
752                 memcpy(dst, &missing, width - i);
753                 return word;
754             }
755         }
756         return word;
757     }
758 }
759 
print_stack_word(guest_word_t word,int width)760 static void print_stack_word(guest_word_t word, int width)
761 {
762     if (width == 2)
763         printf(FMT_16B_WORD, word);
764     else if (width == 4)
765         printf(FMT_32B_WORD, word);
766     else
767         printf(FMT_64B_WORD, word);
768 }
769 
print_lines(vcpu_guest_context_any_t * ctx,int vcpu,int width,guest_word_t mem_addr,guest_word_t mem_limit)770 static int print_lines(vcpu_guest_context_any_t *ctx, int vcpu, int width,
771                        guest_word_t mem_addr, guest_word_t mem_limit)
772 {
773     guest_word_t mem_start = mem_addr;
774     guest_word_t word;
775     guest_word_t ascii[MAX_BYTES_PER_LINE/4];
776     int i;
777 
778     for (i = 1; i < xenctx.lines + 1 && mem_addr < mem_limit; i++)
779     {
780         int j = 0;
781         int k;
782 
783         if ( xenctx.tag_stack_dump )
784         {
785             print_stack_word(mem_addr, width);
786             printf(":");
787         }
788         while ( mem_addr < mem_limit &&
789                 mem_addr < mem_start + i * xenctx.bytes_per_line )
790         {
791             void *p = map_page(ctx, vcpu, mem_addr);
792             if ( !p )
793                 return -1;
794             word = read_mem_word(ctx, vcpu, mem_addr, width);
795             if ( xenctx.decode_as_ascii )
796                 ascii[j++] = word;
797             printf(" ");
798             print_stack_word(word, width);
799             mem_addr += width;
800         }
801         if ( xenctx.decode_as_ascii )
802         {
803             /*
804              * Line up ascii output if less than bytes_per_line
805              * were printed.
806              */
807             for (k = j; k < xenctx.bytes_per_line / width; k++)
808                 printf(" %*s", width * 2, "");
809             printf("  ");
810             for (k = 0; k < j; k++)
811             {
812                 int l;
813                 unsigned char *bytep = (unsigned char *)&ascii[k];
814 
815                 for (l = 0; l < width; l++)
816                 {
817                     if (isprint(*bytep))
818                         printf("%c", *bytep);
819                     else
820                         printf(".");
821                     bytep++;
822                 }
823             }
824         }
825         printf("\n");
826     }
827     printf("\n");
828     return 0;
829 }
830 
print_mem(vcpu_guest_context_any_t * ctx,int vcpu,int width,guest_word_t mem_addr)831 static void print_mem(vcpu_guest_context_any_t *ctx, int vcpu, int width,
832                           guest_word_t mem_addr)
833 {
834     printf("Memory (address ");
835     print_stack_word(mem_addr, width);
836     printf("):\n");
837     print_lines(ctx, vcpu, width, mem_addr,
838                 mem_addr + xenctx.lines * xenctx.bytes_per_line);
839 }
840 
print_code(vcpu_guest_context_any_t * ctx,int vcpu)841 static int print_code(vcpu_guest_context_any_t *ctx, int vcpu)
842 {
843     guest_word_t instr;
844     int i;
845 
846     instr = instr_pointer(ctx);
847     printf("Code (instr addr %08llx)\n", instr);
848     instr -= 21;
849     for(i=0; i<32; i++) {
850         unsigned char *c = map_page(ctx, vcpu, instr+i);
851         if (!c)
852             return -1;
853         if (instr+i == instr_pointer(ctx))
854             printf("<%02x> ", *c);
855         else
856             printf("%02x ", *c);
857     }
858     printf("\n\n\n");
859     return 0;
860 }
861 
print_stack_addr(guest_word_t addr,int width)862 static void print_stack_addr(guest_word_t addr, int width)
863 {
864     print_stack_word(addr, width);
865     printf(": ");
866 }
867 
print_stack(vcpu_guest_context_any_t * ctx,int vcpu,int width,guest_word_t stk_addr_start)868 static int print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width,
869                        guest_word_t stk_addr_start)
870 {
871     guest_word_t stack = stk_addr_start;
872     guest_word_t stack_limit;
873     guest_word_t frame;
874     guest_word_t word;
875     guest_word_t *p;
876 
877     if ( width )
878         xenctx.bytes_per_line =
879             ((xenctx.bytes_per_line + width - 1) / width) * width;
880     stack_limit = ((stack_pointer(ctx) + XC_PAGE_SIZE)
881                    & ~((guest_word_t) XC_PAGE_SIZE - 1))
882                    + (xenctx.nr_stack_pages - 1) * XC_PAGE_SIZE;
883     if ( xenctx.lines )
884     {
885         printf("Stack:\n");
886         if ( print_lines(ctx, vcpu, width, stack, stack_limit) )
887             return -1;
888     }
889 
890     if ( !guest_protected_mode )
891         return 0;
892 
893     if(xenctx.stack_trace)
894         printf("Stack Trace:\n");
895     else
896         printf("Call Trace:\n");
897     if ( !xenctx.do_stack )
898     {
899         printf("%*s  %c [<", width*2, "", xenctx.stack_trace ? '*' : ' ');
900         print_stack_word(instr_pointer(ctx), width);
901         printf(">]");
902 
903         print_symbol(instr_pointer(ctx), KERNEL_TEXT_ADDR);
904         printf(" <--\n");
905     }
906     if (xenctx.frame_ptrs) {
907         stack = stack_pointer(ctx);
908         frame = frame_pointer(ctx);
909         while(frame && stack < stack_limit) {
910             if (xenctx.stack_trace) {
911                 while (stack < frame) {
912                     p = map_page(ctx, vcpu, stack);
913                     if (!p)
914                         return -1;
915                     print_stack_addr(stack, width);
916                     printf("|   ");
917                     print_stack_word(read_stack_word(p, width), width);
918                     printf("\n");
919                     stack += width;
920                 }
921             } else {
922                 stack = frame;
923             }
924 
925             p = map_page(ctx, vcpu, stack);
926             if (!p)
927                 return -1;
928             frame = read_stack_word(p, width);
929             if (xenctx.stack_trace) {
930                 print_stack_addr(stack, width);
931                 printf("|-- ");
932                 print_stack_word(read_stack_word(p, width), width);
933                 printf("\n");
934             }
935             stack += width;
936 
937             if (frame) {
938                 p = map_page(ctx, vcpu, stack);
939                 if (!p)
940                     return -1;
941                 word = read_stack_word(p, width);
942                 print_stack_addr(stack, width);
943                 printf("%c [<", xenctx.stack_trace ? '|' : ' ');
944                 print_stack_word(word, width);
945                 printf(">]");
946                 print_symbol(word, KERNEL_TEXT_ADDR);
947                 printf("\n");
948                 stack += width;
949             }
950         }
951     } else {
952         stack = stk_addr_start;
953         while(stack < stack_limit) {
954             p = map_page(ctx, vcpu, stack);
955             if (!p)
956                 return -1;
957             word = read_mem_word(ctx, vcpu, stack, width);
958             if ( kernel_addr(word) >= KERNEL_TEXT_ADDR )
959             {
960                 print_stack_addr(stack, width);
961                 printf("  [<");
962                 print_stack_word(word, width);
963                 printf(">]");
964                 print_symbol(word, KERNEL_TEXT_ADDR);
965                 printf("\n");
966             } else if (xenctx.stack_trace) {
967                 print_stack_addr(stack, width);
968                 printf("    ");
969                 print_stack_word(word, width);
970                 printf("\n");
971             }
972             stack += width;
973         }
974     }
975     return 0;
976 }
977 #endif
978 
dump_ctx(int vcpu)979 static void dump_ctx(int vcpu)
980 {
981     vcpu_guest_context_any_t ctx;
982 
983     if (xc_vcpu_getcontext(xenctx.xc_handle, xenctx.domid, vcpu, &ctx) < 0) {
984         perror("xc_vcpu_getcontext");
985         return;
986     }
987 
988 #if defined(__i386__) || defined(__x86_64__)
989     {
990         if (xenctx.dominfo.hvm) {
991             struct hvm_hw_cpu cpuctx;
992             xen_capabilities_info_t xen_caps = "";
993             if (xc_domain_hvm_getcontext_partial(
994                     xenctx.xc_handle, xenctx.domid, HVM_SAVE_CODE(CPU),
995                     vcpu, &cpuctx, sizeof cpuctx) != 0) {
996                 perror("xc_domain_hvm_getcontext_partial");
997                 return;
998             }
999             guest_protected_mode = (cpuctx.cr0 & CR0_PE);
1000             guest_word_size = (cpuctx.msr_efer & 0x400) ? 8 :
1001                 guest_protected_mode ? 4 : 2;
1002             /* HVM guest context records are always host-sized */
1003             if (xc_version(xenctx.xc_handle, XENVER_capabilities, &xen_caps) != 0) {
1004                 perror("xc_version");
1005                 return;
1006             }
1007             ctxt_word_size = (strstr(xen_caps, "xen-3.0-x86_64")) ? 8 : 4;
1008         } else {
1009             unsigned int gw;
1010             if ( !xc_domain_get_guest_width(xenctx.xc_handle, xenctx.domid, &gw) )
1011                 ctxt_word_size = guest_word_size = gw;
1012         }
1013     }
1014 #endif
1015 
1016 #ifndef NO_TRANSLATION
1017     if ( xenctx.do_memory )
1018     {
1019         print_mem(&ctx, vcpu, guest_word_size, xenctx.mem_addr);
1020         return;
1021     }
1022     if ( xenctx.do_stack )
1023     {
1024         print_stack(&ctx, vcpu, guest_word_size, xenctx.stk_addr);
1025         return;
1026     }
1027 #endif
1028     print_ctx(&ctx);
1029 #ifndef NO_TRANSLATION
1030     if (print_code(&ctx, vcpu))
1031         return;
1032     if ( !guest_protected_mode ||
1033          kernel_addr(instr_pointer(&ctx)) >= KERNEL_TEXT_ADDR )
1034         if ( print_stack(&ctx, vcpu, guest_word_size,
1035                          stack_pointer(&ctx)) )
1036             return;
1037 #endif
1038 }
1039 
dump_all_vcpus(void)1040 static void dump_all_vcpus(void)
1041 {
1042     xc_vcpuinfo_t vinfo;
1043     int vcpu;
1044     for (vcpu = 0; vcpu <= xenctx.dominfo.max_vcpu_id; vcpu++)
1045     {
1046         if ( xc_vcpu_getinfo(xenctx.xc_handle, xenctx.domid, vcpu, &vinfo) )
1047             continue;
1048         if ( vinfo.online )
1049         {
1050             printf("vcpu%d:\n", vcpu);
1051             dump_ctx(vcpu);
1052             printf("\n");
1053         }
1054         else
1055             printf("vcpu%d offline\n\n", vcpu);
1056     }
1057 }
1058 
usage(void)1059 static void usage(void)
1060 {
1061     printf("usage:\n\n");
1062 
1063     printf("  xenctx [options] <DOMAIN> [VCPU]\n\n");
1064 
1065     printf("options:\n");
1066     printf("  -f, --frame-pointers\n");
1067     printf("                     assume the kernel was compiled with\n");
1068     printf("                     frame pointers.\n");
1069     printf("  -s SYMTAB, --symbol-table=SYMTAB\n");
1070     printf("                     read symbol table from SYMTAB.\n");
1071     printf("  -S, --stack-trace  print a complete stack trace.\n");
1072     printf("  -k KADDR, --kernel-start=KADDR\n");
1073     printf("                     set user/kernel split. (default 0x"FMT_32B_WORD")\n",
1074         kernel_start);
1075     printf("  -a, --all          display more registers\n");
1076     printf("  -C, --all-vcpus    print info for all vcpus\n");
1077     printf("  -n PAGES, --display-stack-pages=PAGES\n");
1078     printf("                     Display N pages from the stack pointer. (default %d)\n",
1079            DEFAULT_NR_STACK_PAGES);
1080     printf("                     Changes stack limit.  Note: use with caution (easy\n");
1081     printf("                     to get garbage).\n");
1082     printf("  -b <bytes>, --bytes-per-line <bytes>\n");
1083     printf("                     change the number of bytes per line output for Stack.\n");
1084     printf("                     (default %d) Note: rounded to native size (4 or 8 bytes).\n",
1085            DEFAULT_BYTES_PER_LINE);
1086     printf("  -l <lines>, --lines <lines>\n");
1087     printf("                     change the number of lines output for Stack. (default %d)\n",
1088            DEFAULT_LINES);
1089     printf("                     Can be specified as MAX.  Note: Fewer lines will be output\n");
1090     printf("                     if stack limit reached.\n");
1091     printf("  -D, --decode-as-ascii\n");
1092     printf("                     add a decode of Stack dump as ascii.\n");
1093     printf("  -t, --tag-stack-dump\n");
1094     printf("                     add address on each line of Stack dump.\n");
1095 #ifndef NO_TRANSLATION
1096     printf("  -m maddr, --memory=maddr\n");
1097     printf("                     dump memory at maddr.\n");
1098     printf("  -d daddr, --dump-as-stack=daddr\n");
1099     printf("                     dump memory as a stack at daddr.\n");
1100 #endif
1101 }
1102 
main(int argc,char ** argv)1103 int main(int argc, char **argv)
1104 {
1105     int ch;
1106     int ret;
1107     const char *prog = argv[0];
1108     static const char *sopts = "fs:hak:SCn:b:l:Dt"
1109 #ifndef NO_TRANSLATION
1110         "m:d:"
1111 #endif
1112         ;
1113     static const struct option lopts[] = {
1114         {"stack-trace", 0, NULL, 'S'},
1115         {"symbol-table", 1, NULL, 's'},
1116         {"frame-pointers", 0, NULL, 'f'},
1117         {"kernel-start", 1, NULL, 'k'},
1118         {"display-stack-pages", 0, NULL, 'n'},
1119         {"decode-as-ascii", 0, NULL, 'D'},
1120         {"tag-stack-dump", 0, NULL, 't'},
1121 #ifndef NO_TRANSLATION
1122         {"memory", 1, NULL, 'm'},
1123         {"dump-as-stack", 1, NULL, 'd'},
1124 #endif
1125         {"bytes-per-line", 1, NULL, 'b'},
1126         {"lines", 1, NULL, 'l'},
1127         {"all", 0, NULL, 'a'},
1128         {"all-vcpus", 0, NULL, 'C'},
1129         {"help", 0, NULL, 'h'},
1130         {0, 0, 0, 0}
1131     };
1132     const char *symbol_table = NULL;
1133 
1134     int vcpu = 0;
1135     int do_default = 1;
1136 
1137     xenctx.bytes_per_line = DEFAULT_BYTES_PER_LINE;
1138     xenctx.lines = DEFAULT_LINES;
1139     xenctx.nr_stack_pages = DEFAULT_NR_STACK_PAGES;
1140 
1141     while ((ch = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) {
1142         switch(ch) {
1143         case 'f':
1144             xenctx.frame_ptrs = 1;
1145             break;
1146         case 's':
1147             symbol_table = optarg;
1148             break;
1149         case 'S':
1150             xenctx.stack_trace = 1;
1151             break;
1152         case 'a':
1153             xenctx.disp_all = 1;
1154             break;
1155         case 'n':
1156             xenctx.nr_stack_pages = strtol(optarg, NULL, 0);
1157             if ( xenctx.nr_stack_pages < 1)
1158             {
1159                 fprintf(stderr,
1160                         "%s: Unsupported value(%d) for --display-stack-pages '%s'. Needs to be >= 1\n",
1161                         prog, xenctx.nr_stack_pages, optarg);
1162                 exit(-1);
1163             }
1164             break;
1165         case 'D':
1166             xenctx.decode_as_ascii = 1;
1167             break;
1168         case 't':
1169             xenctx.tag_stack_dump = 1;
1170             break;
1171         case 'b':
1172             xenctx.bytes_per_line = strtol(optarg, NULL, 0);
1173             if ( xenctx.bytes_per_line < 4 ||
1174                  xenctx.bytes_per_line > MAX_BYTES_PER_LINE )
1175             {
1176                 fprintf(stderr,
1177                         "%s: Unsupported value for --bytes-per-line '%s'. Needs to be 4 <= %d <= %d\n",
1178                         prog, optarg, xenctx.bytes_per_line,
1179                         MAX_BYTES_PER_LINE);
1180                 exit(-1);
1181             }
1182             break;
1183         case 'l':
1184             if ( !strcmp(optarg, "all") || !strcmp(optarg, "ALL") ||
1185                  !strcmp(optarg, "max") || !strcmp(optarg, "MAX") )
1186                 xenctx.lines = INT_MAX - 1;
1187             else
1188                 xenctx.lines = strtol(optarg, NULL, 0);
1189             if ( xenctx.lines < 0 || xenctx.lines == INT_MAX)
1190             {
1191                 fprintf(stderr,
1192                         "%s: Unsupported value(%d) for --lines '%s'. Needs to be >= 0, < %d\n",
1193                         prog, xenctx.lines, optarg, INT_MAX);
1194                 exit(-1);
1195             }
1196             break;
1197         case 'C':
1198             xenctx.all_vcpus = 1;
1199             do_default = 0;
1200             break;
1201         case 'k':
1202             kernel_start = strtoull(optarg, NULL, 0);
1203             xenctx.kernel_start_set = 1;
1204             break;
1205 #ifndef NO_TRANSLATION
1206         case 'm':
1207             xenctx.mem_addr = strtoull(optarg, NULL, 0);
1208             xenctx.do_memory = 1;
1209             do_default = 0;
1210             break;
1211         case 'd':
1212             xenctx.stk_addr = strtoull(optarg, NULL, 0);
1213             xenctx.do_stack = 1;
1214             do_default = 0;
1215             break;
1216 #endif
1217         case 'h':
1218             usage();
1219             exit(-1);
1220         case '?':
1221             fprintf(stderr, "%s --help for more options\n", prog);
1222             exit(-1);
1223         }
1224     }
1225 
1226     argv += optind; argc -= optind;
1227 
1228     if (argc < 1 || argc > 2) {
1229         printf("usage: xenctx [options] <domid> <optional vcpu>\n");
1230         exit(-1);
1231     }
1232 
1233 #ifndef NO_TRANSLATION
1234     if ( xenctx.frame_ptrs && xenctx.do_stack )
1235     {
1236         fprintf(stderr,
1237                 "%s: both --frame-pointers and --dump-as-stack is not supported\n",
1238                 prog);
1239         exit(-1);
1240     }
1241 #endif
1242 
1243     xenctx.domid = atoi(argv[0]);
1244     if (xenctx.domid==0) {
1245             fprintf(stderr, "cannot trace dom0\n");
1246             exit(-1);
1247     }
1248 
1249     if ( argc == 2 )
1250     {
1251         if ( xenctx.all_vcpus )
1252         {
1253             fprintf(stderr,
1254                     "%s: both --all-vcpus and [VCPU] is not supported\n",
1255                     prog);
1256             exit(-1);
1257         }
1258         vcpu = atoi(argv[1]);
1259     }
1260 
1261     if (symbol_table)
1262         read_symbol_table(symbol_table);
1263 
1264     xenctx.xc_handle = xc_interface_open(0,0,0); /* for accessing control interface */
1265     if (xenctx.xc_handle == NULL) {
1266         perror("xc_interface_open");
1267         exit(-1);
1268     }
1269 
1270     ret = xc_domain_getinfo(xenctx.xc_handle, xenctx.domid, 1, &xenctx.dominfo);
1271     if (ret < 0) {
1272         perror("xc_domain_getinfo");
1273         exit(-1);
1274     }
1275 
1276     ret = xc_domain_pause(xenctx.xc_handle, xenctx.domid);
1277     if (ret < 0) {
1278         perror("xc_domain_pause");
1279         exit(-1);
1280     }
1281 
1282 #ifndef NO_TRANSLATION
1283     if ( xenctx.do_memory )
1284     {
1285         dump_ctx(vcpu);
1286         if ( xenctx.do_stack || xenctx.all_vcpus )
1287             printf("\n");
1288     }
1289     xenctx.do_memory = 0;
1290     if ( xenctx.do_stack )
1291     {
1292         dump_ctx(vcpu);
1293         if ( xenctx.all_vcpus )
1294             printf("\n");
1295     }
1296     xenctx.do_stack = 0;
1297 #endif
1298     if (xenctx.all_vcpus)
1299         dump_all_vcpus();
1300     if ( do_default )
1301         dump_ctx(vcpu);
1302 
1303     ret = xc_domain_unpause(xenctx.xc_handle, xenctx.domid);
1304     if (ret < 0) {
1305         perror("xc_domain_unpause");
1306         exit(-1);
1307     }
1308 
1309     ret = xc_interface_close(xenctx.xc_handle);
1310     if (ret < 0) {
1311         perror("xc_interface_close");
1312         exit(-1);
1313     }
1314 
1315     return 0;
1316 }
1317 
1318 /*
1319  * Local variables:
1320  * mode: C
1321  * c-file-style: "BSD"
1322  * c-basic-offset: 4
1323  * tab-width: 4
1324  * indent-tabs-mode: nil
1325  * End:
1326  */
1327