ia64/xen-unstable

view tools/xentrace/xenctx.c @ 8740:3d7ea7972b39

Update patches for linux 2.6.15.

Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Thu Feb 02 17:16:00 2006 +0000 (2006-02-02)
parents 635678c0fccc
children b16063ae0703
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, kernel_hypercallpage;
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_hypercallpage &&
72 addr <= kernel_hypercallpage + 4096)
73 return 1;
74 if (addr >= kernel_sinittext &&
75 addr <= kernel_einittext)
76 return 1;
77 return 0;
78 }
80 void free_symbol(struct symbol *symbol)
81 {
82 if (symbol == NULL)
83 return;
84 if (symbol->name)
85 free(symbol->name);
86 free(symbol);
87 }
89 void insert_symbol(struct symbol *symbol)
90 {
91 static struct symbol *prev = NULL;
92 struct symbol *s = symbol_table;
94 if (s == NULL) {
95 symbol_table = symbol;
96 symbol->next = NULL;
97 return;
98 }
100 /* The System.map is usually already sorted... */
101 if (prev
102 && prev->address < symbol->address
103 && (!prev->next || prev->next->address > symbol->address)) {
104 s = prev;
105 } else {
106 /* ... otherwise do crappy/slow search for the correct place */
107 while(s && s->next && s->next->address < symbol->address)
108 s = s->next;
109 }
111 symbol->next = s->next;
112 s->next = symbol;
113 prev = symbol;
114 }
116 struct symbol *lookup_symbol(size_t address)
117 {
118 struct symbol *s = symbol_table;
120 while(s && s->next && s->next->address < address)
121 s = s->next;
123 if (s && s->address < address)
124 return s;
126 return NULL;
127 }
129 void print_symbol(size_t addr)
130 {
131 struct symbol *s;
133 if (!is_kernel_text(addr))
134 return;
136 s = lookup_symbol(addr);
138 if (s==NULL)
139 return;
141 if (addr==s->address)
142 printf("%s", s->name);
143 else
144 printf("%s+%#x", s->name, (unsigned int)(addr - s->address));
145 }
147 void read_symbol_table(const char *symtab)
148 {
149 char line[256];
150 char *p;
151 struct symbol *symbol;
152 FILE *f;
154 f = fopen(symtab, "r");
155 if(f == NULL) {
156 fprintf(stderr, "failed to open symbol table %s\n", symtab);
157 exit(-1);
158 }
160 while(!feof(f)) {
161 if(fgets(line,256,f)==NULL)
162 break;
164 symbol = malloc(sizeof(*symbol));
166 /* need more checks for syntax here... */
167 symbol->address = strtoull(line, &p, 16);
168 p++;
169 symbol->type = *p++;
170 p++;
172 /* in the future we should handle the module name
173 * being appended here, this would allow us to use
174 * /proc/kallsyms as our symbol table
175 */
176 if (p[strlen(p)-1] == '\n')
177 p[strlen(p)-1] = '\0';
178 symbol->name = strdup(p);
180 insert_symbol(symbol);
182 if (strcmp(symbol->name, "_stext") == 0)
183 kernel_stext = symbol->address;
184 else if (strcmp(symbol->name, "_etext") == 0)
185 kernel_etext = symbol->address;
186 else if (strcmp(symbol->name, "_sinittext") == 0)
187 kernel_sinittext = symbol->address;
188 else if (strcmp(symbol->name, "_einittext") == 0)
189 kernel_einittext = symbol->address;
190 else if (strcmp(symbol->name, "hypercall_page") == 0)
191 kernel_hypercallpage = symbol->address;
192 }
194 fclose(f);
195 }
197 #ifdef __i386__
198 void print_ctx(vcpu_guest_context_t *ctx1)
199 {
200 struct cpu_user_regs *regs = &ctx1->user_regs;
202 printf("eip: %08x ", regs->eip);
203 print_symbol(regs->eip);
204 printf("\n");
206 printf("esp: %08x\n", regs->esp);
208 printf("eax: %08x\t", regs->eax);
209 printf("ebx: %08x\t", regs->ebx);
210 printf("ecx: %08x\t", regs->ecx);
211 printf("edx: %08x\n", regs->edx);
213 printf("esi: %08x\t", regs->esi);
214 printf("edi: %08x\t", regs->edi);
215 printf("ebp: %08x\n", regs->ebp);
217 printf(" cs: %08x\t", regs->cs);
218 printf(" ds: %08x\t", regs->ds);
219 printf(" fs: %08x\t", regs->fs);
220 printf(" gs: %08x\n", regs->gs);
222 }
223 #elif defined(__x86_64__)
224 void print_ctx(vcpu_guest_context_t *ctx1)
225 {
226 struct cpu_user_regs *regs = &ctx1->user_regs;
228 printf("rip: %08lx ", regs->rip);
229 print_symbol(regs->rip);
230 printf("\n");
231 printf("rsp: %08lx\n", regs->rsp);
233 printf("rax: %08lx\t", regs->rax);
234 printf("rbx: %08lx\t", regs->rbx);
235 printf("rcx: %08lx\t", regs->rcx);
236 printf("rdx: %08lx\n", regs->rdx);
238 printf("rsi: %08lx\t", regs->rsi);
239 printf("rdi: %08lx\t", regs->rdi);
240 printf("rbp: %08lx\n", regs->rbp);
242 printf(" r8: %08lx\t", regs->r8);
243 printf(" r9: %08lx\t", regs->r9);
244 printf("r10: %08lx\t", regs->r10);
245 printf("r11: %08lx\n", regs->r11);
247 printf("r12: %08lx\t", regs->r12);
248 printf("r13: %08lx\t", regs->r13);
249 printf("r14: %08lx\t", regs->r14);
250 printf("r15: %08lx\n", regs->r15);
252 printf(" cs: %08x\t", regs->cs);
253 printf(" ds: %08x\t", regs->ds);
254 printf(" fs: %08x\t", regs->fs);
255 printf(" gs: %08x\n", regs->gs);
257 }
258 #endif
260 void *map_page(vcpu_guest_context_t *ctx, int vcpu, size_t virt)
261 {
262 static unsigned long previous_mfn = 0;
263 static void *mapped = NULL;
265 unsigned long mfn = xc_translate_foreign_address(xc_handle, domid, vcpu, virt);
266 unsigned long offset = virt & ~XC_PAGE_MASK;
268 if (mapped && mfn == previous_mfn)
269 goto out;
271 if (mapped)
272 munmap(mapped, XC_PAGE_SIZE);
274 previous_mfn = mfn;
276 mapped = xc_map_foreign_range(xc_handle, domid, XC_PAGE_SIZE, PROT_READ, mfn);
278 if (mapped == NULL) {
279 fprintf(stderr, "failed to map page.\n");
280 exit(-1);
281 }
283 out:
284 return (void *)(mapped + offset);
285 }
287 void print_stack(vcpu_guest_context_t *ctx, int vcpu)
288 {
289 struct cpu_user_regs *regs = &ctx->user_regs;
290 size_t stack = STACK_POINTER(regs);
291 size_t stack_limit = (STACK_POINTER(regs) & XC_PAGE_MASK) + XC_PAGE_SIZE;
292 size_t frame;
293 size_t instr;
294 size_t *p;
295 int i;
297 printf("\n");
298 printf("Stack:\n");
299 for (i=1; i<STACK_ROWS+1 && stack < stack_limit; i++) {
300 while(stack < stack_limit && stack < STACK_POINTER(regs) + i*STACK_COLS*sizeof(stack)) {
301 p = map_page(ctx, vcpu, stack);
302 printf(" " FMT_SIZE_T, *p);
303 stack += sizeof(stack);
304 }
305 printf("\n");
306 }
307 printf("\n");
309 printf("Code:\n");
310 instr = INSTR_POINTER(regs) - 21;
311 for(i=0; i<32; i++) {
312 unsigned char *c = map_page(ctx, vcpu, instr+i);
313 if (instr+i == INSTR_POINTER(regs))
314 printf("<%02x> ", *c);
315 else
316 printf("%02x ", *c);
317 }
318 printf("\n");
320 printf("\n");
322 if(stack_trace)
323 printf("Stack Trace:\n");
324 else
325 printf("Call Trace:\n");
326 printf("%c [<" FMT_SIZE_T ">] ", stack_trace ? '*' : ' ', INSTR_POINTER(regs));
328 print_symbol(INSTR_POINTER(regs));
329 printf(" <--\n");
330 if (frame_ptrs) {
331 stack = STACK_POINTER(regs);
332 frame = FRAME_POINTER(regs);
333 while(frame && stack < stack_limit) {
334 if (stack_trace) {
335 while (stack < frame) {
336 p = map_page(ctx, vcpu, stack);
337 printf("| " FMT_SIZE_T " ", *p);
338 printf("\n");
339 stack += sizeof(*p);
340 }
341 } else {
342 stack = frame;
343 }
345 p = map_page(ctx, vcpu, stack);
346 frame = *p;
347 if (stack_trace)
348 printf("|-- " FMT_SIZE_T "\n", *p);
349 stack += sizeof(*p);
351 if (frame) {
352 p = map_page(ctx, vcpu, stack);
353 printf("%c [<" FMT_SIZE_T ">] ", stack_trace ? '|' : ' ', *p);
354 print_symbol(*p);
355 printf("\n");
356 stack += sizeof(*p);
357 }
358 }
359 } else {
360 stack = STACK_POINTER(regs);
361 while(stack < stack_limit) {
362 p = map_page(ctx, vcpu, stack);
363 if (is_kernel_text(*p)) {
364 printf(" [<" FMT_SIZE_T ">] ", *p);
365 print_symbol(*p);
366 printf("\n");
367 } else if (stack_trace) {
368 printf(" " FMT_SIZE_T "\n", *p);
369 }
370 stack += sizeof(*p);
371 }
372 }
373 }
375 void dump_ctx(int vcpu)
376 {
377 int ret;
378 vcpu_guest_context_t ctx;
380 xc_handle = xc_interface_open(); /* for accessing control interface */
382 ret = xc_domain_pause(xc_handle, domid);
383 if (ret < 0) {
384 perror("xc_domain_pause");
385 exit(-1);
386 }
388 ret = xc_vcpu_getcontext(xc_handle, domid, vcpu, &ctx);
389 if (ret < 0) {
390 xc_domain_unpause(xc_handle, domid);
391 perror("xc_vcpu_getcontext");
392 exit(-1);
393 }
395 print_ctx(&ctx);
396 if (is_kernel_text(ctx.user_regs.eip))
397 print_stack(&ctx, vcpu);
399 ret = xc_domain_unpause(xc_handle, domid);
400 if (ret < 0) {
401 perror("xc_domain_unpause");
402 exit(-1);
403 }
405 xc_interface_close(xc_handle);
406 if (ret < 0) {
407 perror("xc_interface_close");
408 exit(-1);
409 }
410 }
412 void usage(void)
413 {
414 printf("usage:\n\n");
416 printf(" xenctx [options] <DOMAIN> [VCPU]\n\n");
418 printf("options:\n");
419 printf(" -f, --frame-pointers\n");
420 printf(" assume the kernel was compiled with\n");
421 printf(" frame pointers.\n");
422 printf(" -s SYMTAB, --symbol-table=SYMTAB\n");
423 printf(" read symbol table from SYMTAB.\n");
424 printf(" --stack-trace print a complete stack trace.\n");
425 }
427 int main(int argc, char **argv)
428 {
429 int ch;
430 const char *sopts = "fs:h";
431 const struct option lopts[] = {
432 {"stack-trace", 0, NULL, 'S'},
433 {"symbol-table", 1, NULL, 's'},
434 {"frame-pointers", 0, NULL, 'f'},
435 {"help", 0, NULL, 'h'},
436 {0, 0, 0, 0}
437 };
438 const char *symbol_table = NULL;
440 int vcpu = 0;
442 while ((ch = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) {
443 switch(ch) {
444 case 'f':
445 frame_ptrs = 1;
446 break;
447 case 's':
448 symbol_table = optarg;
449 break;
450 case 'S':
451 stack_trace = 1;
452 break;
453 case 'h':
454 usage();
455 exit(-1);
456 case '?':
457 fprintf(stderr, "%s --help for more options\n", argv[0]);
458 exit(-1);
459 }
460 }
462 argv += optind; argc -= optind;
464 if (argc < 1 || argc > 2) {
465 printf("usage: xenctx [options] <domid> <optional vcpu>\n");
466 exit(-1);
467 }
469 domid = atoi(argv[0]);
470 if (domid==0) {
471 fprintf(stderr, "cannot trace dom0\n");
472 exit(-1);
473 }
475 if (argc == 2)
476 vcpu = atoi(argv[1]);
478 if (symbol_table)
479 read_symbol_table(symbol_table);
481 dump_ctx(vcpu);
483 return 0;
484 }
486 /*
487 * Local variables:
488 * mode: C
489 * c-set-style: "BSD"
490 * c-basic-offset: 4
491 * tab-width: 4
492 * indent-tabs-mode: nil
493 * End:
494 */