direct-io.hg

view tools/xentrace/xenctx.c @ 8500:dd5649730b32

Fix a couple of bogus dom0_op names:
setdomaininfo -> setvcpucontext
pincpudomain -> setvcpuaffinity

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Fri Jan 06 12:53:19 2006 +0100 (2006-01-06)
parents 8d5d4d58407f
children 635678c0fccc
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 <argp.h>
22 #include <signal.h>
23 #include <string.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;
33 #if defined (__i386__)
34 #define FMT_SIZE_T "%08x"
35 #define STACK_POINTER(regs) (regs->esp)
36 #define FRAME_POINTER(regs) (regs->ebp)
37 #define INSTR_POINTER(regs) (regs->eip)
38 #define STACK_ROWS 4
39 #define STACK_COLS 8
40 #elif defined (__x86_64__)
41 #define FMT_SIZE_T "%016lx"
42 #define STACK_POINTER(regs) (regs->rsp)
43 #define FRAME_POINTER(regs) (regs->rbp)
44 #define INSTR_POINTER(regs) (regs->rip)
45 #define STACK_ROWS 4
46 #define STACK_COLS 4
47 #endif
49 struct symbol {
50 size_t address;
51 char type;
52 char *name;
53 struct symbol *next;
54 } *symbol_table = NULL;
56 size_t kernel_stext, kernel_etext, kernel_sinittext, kernel_einittext;
58 int is_kernel_text(size_t addr)
59 {
60 #if defined (__i386__)
61 if (symbol_table == NULL)
62 return (addr > 0xc000000);
63 #elif defined (__x86_64__)
64 if (symbol_table == NULL)
65 return (addr > 0xffffffff80000000UL);
66 #endif
68 if (addr >= kernel_stext &&
69 addr <= kernel_etext)
70 return 1;
71 if (addr >= kernel_sinittext &&
72 addr <= kernel_einittext)
73 return 1;
74 return 0;
75 }
77 void free_symbol(struct symbol *symbol)
78 {
79 if (symbol == NULL)
80 return;
81 if (symbol->name)
82 free(symbol->name);
83 free(symbol);
84 }
86 void insert_symbol(struct symbol *symbol)
87 {
88 static struct symbol *prev = NULL;
89 struct symbol *s = symbol_table;
91 if (s == NULL) {
92 symbol_table = symbol;
93 symbol->next = NULL;
94 return;
95 }
97 /* The System.map is usually already sorted... */
98 if (prev
99 && prev->address < symbol->address
100 && (!prev->next || prev->next->address > symbol->address)) {
101 s = prev;
102 } else {
103 /* ... otherwise do crappy/slow search for the correct place */
104 while(s && s->next && s->next->address < symbol->address)
105 s = s->next;
106 }
108 symbol->next = s->next;
109 s->next = symbol;
110 prev = symbol;
111 }
113 struct symbol *lookup_symbol(size_t address)
114 {
115 struct symbol *s = symbol_table;
117 while(s && s->next && s->next->address < address)
118 s = s->next;
120 if (s && s->address < address)
121 return s;
123 return NULL;
124 }
126 void print_symbol(size_t addr)
127 {
128 struct symbol *s;
130 if (!is_kernel_text(addr))
131 return;
133 s = lookup_symbol(addr);
135 if (s==NULL)
136 return;
138 if (addr==s->address)
139 printf("%s", s->name);
140 else
141 printf("%s+%#x", s->name, (unsigned int)(addr - s->address));
142 }
144 void read_symbol_table(const char *symtab)
145 {
146 char line[256];
147 char *p;
148 struct symbol *symbol;
149 FILE *f;
151 f = fopen(symtab, "r");
152 if(f == NULL) {
153 fprintf(stderr, "failed to open symbol table %s\n", symtab);
154 exit(-1);
155 }
157 while(!feof(f)) {
158 if(fgets(line,256,f)==NULL)
159 break;
161 symbol = malloc(sizeof(*symbol));
163 /* need more checks for syntax here... */
164 symbol->address = strtoull(line, &p, 16);
165 p++;
166 symbol->type = *p++;
167 p++;
169 /* in the future we should handle the module name
170 * being appended here, this would allow us to use
171 * /proc/kallsyms as our symbol table
172 */
173 if (p[strlen(p)-1] == '\n')
174 p[strlen(p)-1] = '\0';
175 symbol->name = strdup(p);
177 insert_symbol(symbol);
179 if (strcmp(symbol->name, "_stext") == 0)
180 kernel_stext = symbol->address;
181 else if (strcmp(symbol->name, "_etext") == 0)
182 kernel_etext = symbol->address;
183 else if (strcmp(symbol->name, "_sinittext") == 0)
184 kernel_sinittext = symbol->address;
185 else if (strcmp(symbol->name, "_einittext") == 0)
186 kernel_einittext = symbol->address;
187 }
189 fclose(f);
190 }
192 #ifdef __i386__
193 void print_ctx(vcpu_guest_context_t *ctx1)
194 {
195 struct cpu_user_regs *regs = &ctx1->user_regs;
197 printf("eip: %08x ", regs->eip);
198 print_symbol(regs->eip);
199 printf("\n");
201 printf("esp: %08x\n", regs->esp);
203 printf("eax: %08x\t", regs->eax);
204 printf("ebx: %08x\t", regs->ebx);
205 printf("ecx: %08x\t", regs->ecx);
206 printf("edx: %08x\n", regs->edx);
208 printf("esi: %08x\t", regs->esi);
209 printf("edi: %08x\t", regs->edi);
210 printf("ebp: %08x\n", regs->ebp);
212 printf(" cs: %08x\t", regs->cs);
213 printf(" ds: %08x\t", regs->ds);
214 printf(" fs: %08x\t", regs->fs);
215 printf(" gs: %08x\n", regs->gs);
217 }
218 #elif defined(__x86_64__)
219 void print_ctx(vcpu_guest_context_t *ctx1)
220 {
221 struct cpu_user_regs *regs = &ctx1->user_regs;
223 printf("rip: %08lx ", regs->rip);
224 print_symbol(regs->rip);
225 printf("\n");
226 printf("rsp: %08lx\n", regs->rsp);
228 printf("rax: %08lx\t", regs->rax);
229 printf("rbx: %08lx\t", regs->rbx);
230 printf("rcx: %08lx\t", regs->rcx);
231 printf("rdx: %08lx\n", regs->rdx);
233 printf("rsi: %08lx\t", regs->rsi);
234 printf("rdi: %08lx\t", regs->rdi);
235 printf("rbp: %08lx\n", regs->rbp);
237 printf(" r8: %08lx\t", regs->r8);
238 printf(" r9: %08lx\t", regs->r9);
239 printf("r10: %08lx\t", regs->r10);
240 printf("r11: %08lx\n", regs->r11);
242 printf("r12: %08lx\t", regs->r12);
243 printf("r13: %08lx\t", regs->r13);
244 printf("r14: %08lx\t", regs->r14);
245 printf("r15: %08lx\n", regs->r15);
247 printf(" cs: %08x\t", regs->cs);
248 printf(" ds: %08x\t", regs->ds);
249 printf(" fs: %08x\t", regs->fs);
250 printf(" gs: %08x\n", regs->gs);
252 }
253 #endif
255 void *map_page(vcpu_guest_context_t *ctx, int vcpu, size_t virt)
256 {
257 static unsigned long previous_mfn = 0;
258 static void *mapped = NULL;
260 unsigned long mfn = xc_translate_foreign_address(xc_handle, domid, vcpu, virt);
261 unsigned long offset = virt & ~XC_PAGE_MASK;
263 if (mapped && mfn == previous_mfn)
264 goto out;
266 if (mapped)
267 munmap(mapped, XC_PAGE_SIZE);
269 previous_mfn = mfn;
271 mapped = xc_map_foreign_range(xc_handle, domid, XC_PAGE_SIZE, PROT_READ, mfn);
273 if (mapped == NULL) {
274 fprintf(stderr, "failed to map page.\n");
275 exit(-1);
276 }
278 out:
279 return (void *)(mapped + offset);
280 }
282 void print_stack(vcpu_guest_context_t *ctx, int vcpu)
283 {
284 struct cpu_user_regs *regs = &ctx->user_regs;
285 size_t stack = STACK_POINTER(regs);
286 size_t stack_limit = (STACK_POINTER(regs) & XC_PAGE_MASK) + XC_PAGE_SIZE;
287 size_t frame;
288 size_t instr;
289 size_t *p;
290 int i;
292 printf("\n");
293 printf("Stack:\n");
294 for (i=1; i<STACK_ROWS+1 && stack < stack_limit; i++) {
295 while(stack < stack_limit && stack < STACK_POINTER(regs) + i*STACK_COLS*sizeof(stack)) {
296 p = map_page(ctx, vcpu, stack);
297 printf(" " FMT_SIZE_T, *p);
298 stack += sizeof(stack);
299 }
300 printf("\n");
301 }
302 printf("\n");
304 printf("Code:\n");
305 instr = INSTR_POINTER(regs) - 21;
306 for(i=0; i<32; i++) {
307 unsigned char *c = map_page(ctx, vcpu, instr+i);
308 if (instr+i == INSTR_POINTER(regs))
309 printf("<%02x> ", *c);
310 else
311 printf("%02x ", *c);
312 }
313 printf("\n");
315 printf("\n");
317 if(stack_trace)
318 printf("Stack Trace:\n");
319 else
320 printf("Call Trace:\n");
321 printf("%c [<" FMT_SIZE_T ">] ", stack_trace ? '*' : ' ', INSTR_POINTER(regs));
323 print_symbol(INSTR_POINTER(regs));
324 printf(" <--\n");
325 if (frame_ptrs) {
326 stack = STACK_POINTER(regs);
327 frame = FRAME_POINTER(regs);
328 while(frame && stack < stack_limit) {
329 if (stack_trace) {
330 while (stack < frame) {
331 p = map_page(ctx, vcpu, stack);
332 printf("| " FMT_SIZE_T " ", *p);
333 printf("\n");
334 stack += sizeof(*p);
335 }
336 } else {
337 stack = frame;
338 }
340 p = map_page(ctx, vcpu, stack);
341 frame = *p;
342 if (stack_trace)
343 printf("|-- " FMT_SIZE_T "\n", *p);
344 stack += sizeof(*p);
346 if (frame) {
347 p = map_page(ctx, vcpu, stack);
348 printf("%c [<" FMT_SIZE_T ">] ", stack_trace ? '|' : ' ', *p);
349 print_symbol(*p);
350 printf("\n");
351 stack += sizeof(*p);
352 }
353 }
354 } else {
355 stack = STACK_POINTER(regs);
356 while(stack < stack_limit) {
357 p = map_page(ctx, vcpu, stack);
358 if (is_kernel_text(*p)) {
359 printf(" [<" FMT_SIZE_T ">] ", *p);
360 print_symbol(*p);
361 printf("\n");
362 } else if (stack_trace) {
363 printf(" " FMT_SIZE_T "\n", *p);
364 }
365 stack += sizeof(*p);
366 }
367 }
368 }
370 void dump_ctx(int vcpu)
371 {
372 int ret;
373 vcpu_guest_context_t ctx;
375 xc_handle = xc_interface_open(); /* for accessing control interface */
377 ret = xc_domain_pause(xc_handle, domid);
378 if (ret < 0) {
379 perror("xc_domain_pause");
380 exit(-1);
381 }
383 ret = xc_vcpu_getcontext(xc_handle, domid, vcpu, &ctx);
384 if (ret < 0) {
385 xc_domain_unpause(xc_handle, domid);
386 perror("xc_vcpu_getcontext");
387 exit(-1);
388 }
390 print_ctx(&ctx);
391 if (is_kernel_text(ctx.user_regs.eip))
392 print_stack(&ctx, vcpu);
394 ret = xc_domain_unpause(xc_handle, domid);
395 if (ret < 0) {
396 perror("xc_domain_unpause");
397 exit(-1);
398 }
400 xc_interface_close(xc_handle);
401 if (ret < 0) {
402 perror("xc_interface_close");
403 exit(-1);
404 }
405 }
407 void usage(void)
408 {
409 printf("usage:\n\n");
411 printf(" xenctx [options] <DOMAIN> [VCPU]\n\n");
413 printf("options:\n");
414 printf(" -f, --frame-pointers\n");
415 printf(" assume the kernel was compiled with\n");
416 printf(" frame pointers.\n");
417 printf(" -s SYMTAB, --symbol-table=SYMTAB\n");
418 printf(" read symbol table from SYMTAB.\n");
419 printf(" --stack-trace print a complete stack trace.\n");
420 }
422 int main(int argc, char **argv)
423 {
424 int ch;
425 const char *sopts = "fs:h";
426 const struct option lopts[] = {
427 {"stack-trace", 0, NULL, 'S'},
428 {"symbol-table", 1, NULL, 's'},
429 {"frame-pointers", 0, NULL, 'f'},
430 {"help", 0, NULL, 'h'},
431 {0, 0, 0, 0}
432 };
433 const char *symbol_table = NULL;
435 int vcpu = 0;
437 while ((ch = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) {
438 switch(ch) {
439 case 'f':
440 frame_ptrs = 1;
441 break;
442 case 's':
443 symbol_table = optarg;
444 break;
445 case 'S':
446 stack_trace = 1;
447 break;
448 case 'h':
449 usage();
450 exit(-1);
451 case '?':
452 fprintf(stderr, "%s --help for more options\n", argv[0]);
453 exit(-1);
454 }
455 }
457 argv += optind; argc -= optind;
459 if (argc < 1 || argc > 2) {
460 printf("usage: xenctx [options] <domid> <optional vcpu>\n");
461 exit(-1);
462 }
464 domid = atoi(argv[0]);
465 if (domid==0) {
466 fprintf(stderr, "cannot trace dom0\n");
467 exit(-1);
468 }
470 if (argc == 2)
471 vcpu = atoi(argv[1]);
473 if (symbol_table)
474 read_symbol_table(symbol_table);
476 dump_ctx(vcpu);
478 return 0;
479 }
481 /*
482 * Local variables:
483 * mode: C
484 * c-set-style: "BSD"
485 * c-basic-offset: 4
486 * tab-width: 4
487 * indent-tabs-mode: nil
488 * End:
489 */