/****************************************************************************** * tools/xentrace/xenctx.c * * Tool for dumping the cpu context * * Copyright (C) 2005 by Intel Corp * * Author: Arun Sharma * Date: February 2005 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "xenctrl.h" int xc_handle = 0; int domid = 0; int frame_ptrs = 0; int stack_trace = 0; int disp_all = 0; #if defined (__i386__) #if defined (__OpenBSD__) #define FMT_SIZE_T "%08lx" #define INSTR_POINTER(regs) (unsigned long)(regs->eip) #else #define FMT_SIZE_T "%08x" #define INSTR_POINTER(regs) (regs->eip) #endif #define STACK_POINTER(regs) (regs->esp) #define FRAME_POINTER(regs) (regs->ebp) #define STACK_ROWS 4 #define STACK_COLS 8 #elif defined (__x86_64__) #define FMT_SIZE_T "%016lx" #define STACK_POINTER(regs) (regs->rsp) #define FRAME_POINTER(regs) (regs->rbp) #define INSTR_POINTER(regs) (regs->rip) #define STACK_ROWS 4 #define STACK_COLS 4 #elif defined (__ia64__) /* On ia64, we can't translate virtual address to physical address. */ #define NO_TRANSLATION /* Which registers should be displayed. */ int disp_cr_regs; int disp_ar_regs; int disp_br_regs; int disp_bank_regs; int disp_tlb; #endif struct symbol { size_t address; char type; char *name; struct symbol *next; } *symbol_table = NULL; size_t kernel_stext, kernel_etext, kernel_sinittext, kernel_einittext, kernel_hypercallpage; int is_kernel_text(size_t addr) { #if defined (__i386__) if (symbol_table == NULL) return (addr > 0xc000000); #elif defined (__x86_64__) if (symbol_table == NULL) return (addr > 0xffffffff80000000UL); #elif defined (__ia64__) if (symbol_table == NULL) return (addr > 0xa000000000000000UL); #endif if (addr >= kernel_stext && addr <= kernel_etext) return 1; if (addr >= kernel_hypercallpage && addr <= kernel_hypercallpage + 4096) return 1; if (addr >= kernel_sinittext && addr <= kernel_einittext) return 1; return 0; } void free_symbol(struct symbol *symbol) { if (symbol == NULL) return; if (symbol->name) free(symbol->name); free(symbol); } void insert_symbol(struct symbol *symbol) { static struct symbol *prev = NULL; struct symbol *s = symbol_table; if (s == NULL) { symbol_table = symbol; symbol->next = NULL; return; } /* The System.map is usually already sorted... */ if (prev && prev->address < symbol->address && (!prev->next || prev->next->address > symbol->address)) { s = prev; } else { /* ... otherwise do crappy/slow search for the correct place */ while(s && s->next && s->next->address < symbol->address) s = s->next; } symbol->next = s->next; s->next = symbol; prev = symbol; } struct symbol *lookup_symbol(size_t address) { struct symbol *s = symbol_table; while(s && s->next && s->next->address < address) s = s->next; if (s && s->address < address) return s; return NULL; } void print_symbol(size_t addr) { struct symbol *s; if (!is_kernel_text(addr)) return; s = lookup_symbol(addr); if (s==NULL) return; if (addr==s->address) printf("%s ", s->name); else printf("%s+%#x ", s->name, (unsigned int)(addr - s->address)); } void read_symbol_table(const char *symtab) { char line[256]; char *p; struct symbol *symbol; FILE *f; f = fopen(symtab, "r"); if(f == NULL) { fprintf(stderr, "failed to open symbol table %s\n", symtab); exit(-1); } while(!feof(f)) { if(fgets(line,256,f)==NULL) break; symbol = malloc(sizeof(*symbol)); /* need more checks for syntax here... */ symbol->address = strtoull(line, &p, 16); p++; symbol->type = *p++; p++; /* in the future we should handle the module name * being appended here, this would allow us to use * /proc/kallsyms as our symbol table */ if (p[strlen(p)-1] == '\n') p[strlen(p)-1] = '\0'; symbol->name = strdup(p); insert_symbol(symbol); if (strcmp(symbol->name, "_stext") == 0) kernel_stext = symbol->address; else if (strcmp(symbol->name, "_etext") == 0) kernel_etext = symbol->address; else if (strcmp(symbol->name, "_sinittext") == 0) kernel_sinittext = symbol->address; else if (strcmp(symbol->name, "_einittext") == 0) kernel_einittext = symbol->address; else if (strcmp(symbol->name, "hypercall_page") == 0) kernel_hypercallpage = symbol->address; } fclose(f); } #if defined(__i386__) || defined(__x86_64__) char *flag_values[22][2] = {/* clear, set, bit# */ { NULL, "c" }, // 0 Carry { NULL, NULL }, // 1 { NULL, "p" }, // 2 Parity { NULL, NULL }, // 3 { NULL, "a" }, // 4 Adjust { NULL, NULL }, // 5 { "nz", "z" }, // 6 Zero { NULL, "s" }, // 7 Sign { NULL, "tf" }, // 8 Trap { NULL, "i" }, // 9 Interrupt (enabled) { NULL, "d=b" }, // 10 Direction { NULL, "o" }, // 11 Overflow { NULL, NULL }, // 12 12+13 == IOPL { NULL, NULL }, // 13 { NULL, "nt" }, // 14 Nested Task { NULL, NULL }, // 15 { NULL, "rf" }, // 16 Resume Flag { NULL, "v86" }, // 17 Virtual 8086 mode { NULL, "ac" }, // 18 Alignment Check (enabled) { NULL, "vif" }, // 19 Virtual Interrupt (enabled) { NULL, "vip" }, // 20 Virtual
/*
             LUFA Library
     Copyright (C) Dean Camera, 2017.

  dean [at] fourwalledcubicle [dot] com
           www.lufa-lib.org
*/

/*
  Copyright 2017  Dean Camera (dean [at] fourwalledcubicle [dot] com)

  Permission to use, copy, modify, distribute, and sell this
  software and its documentation for any purpose is hereby granted
  without fee, provided that the above copyright notice appear in
  all copies and that both that the copyright notice and this
  permission notice and warranty disclaimer appear in supporting
  documentation, and that the name of the author not be used in
  advertising or publicity pertaining to distribution of the
  software without specific, written prior permission.

  The author disclaims all warranties with regard to this
  software, including all implied warranties of merchantability
  and fitness.  In no event shall the author be liable for any
  special, indirect or consequential damages or any damages
  whatsoever resulting from loss of use, data or profits, whether
  in an action of contract, negligence or other tortious action,
  arising out of or in connection with the use or performance of
  this software.
*/

/** \file
 *
 *  Header file for DeviceFunctions.c.
 */

#ifndef _MOUSE_DEVICE_FUNCTIONS_H_
#define _MOUSE_DEVICE_FUNCTIONS_H_

	/* Includes: */
		#include "MouseHostDevice.h"

	/* External Variables: */
		extern USB_ClassInfo_HID_Device_t Mouse_HID_Device_Interface;

	/* Function Prototypes: */
		bool CALLBACK_HID_Device_CreateHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo,
		                                         uint8_t* const ReportID,
		                                         const uint8_t ReportType,
		                                         void* ReportData,
		                                         uint16_t* const ReportSize);
		void CALLBACK_HID_Device_ProcessHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo,
		                                          const uint8_t ReportID,
		                                          const uint8_t ReportType,
		                                          const void* ReportData,
		                                          const uint16_t ReportSize);

		void EVENT_USB_Device_Connect(void);
		void EVENT_USB_Device_Disconnect(void);
		void EVENT_USB_Device_ConfigurationChanged(void);
		void EVENT_USB_Device_ControlRequest(void);
		void EVENT_USB_Device_StartOfFrame(void);

#endif
30:%016lx ", regs->r[30]); printf ("31:%016lx ", regs->r[31]); printf ("30:%016lx ", regs->bank[14]); printf ("31:%016lx\n", regs->bank[15]); } else { printf(" r16: %016lx ", regs->r[16]); printf(" r17: %016lx ", regs->r[17]); printf(" r18: %016lx\n", regs->r[18]); printf(" r19: %016lx ", regs->r[19]); printf(" r20: %016lx ", regs->r[20]); printf(" r21: %016lx\n", regs->r[21]); printf(" r22: %016lx ", regs->r[22]); printf(" r23: %016lx ", regs->r[23]); printf(" r24: %016lx\n", regs->r[24]); printf(" r25: %016lx ", regs->r[25]); printf(" r26: %016lx ", regs->r[26]); printf(" r27: %016lx\n", regs->r[27]); printf(" r28: %016lx ", regs->r[28]); printf(" r29: %016lx ", regs->r[29]); printf(" r30: %016lx\n", regs->r[30]); printf(" r31: %016lx\n", regs->r[31]); } printf("\n"); rbs_size = (regs->ar.bsp - regs->ar.bspstore) / 8; cfm_sof = (regs->cfm & CFM_SOF_MASK); for (i = 0; i < cfm_sof; i++) { int off = cfm_sof - i; unsigned int rbs_off = (((62 - ((rbs_size + regs->rbs_voff) % 63) + off)) / 63) + off; if (rbs_off > rbs_size) break; printf(" r%02d: %016lx%s", 32 + i, regs->rbs[rbs_size - rbs_off], (i % 3) != 2 ? " " : "\n"); } if ((i % 3) != 0) printf ("\n"); if (disp_tlb) { printf("\n itr: P rid va pa ps ed pl " "ar a d ma key\n"); for (i = 0; i < 8; i++) print_tr(i, &tr->itrs[i]); printf("\n dtr: P rid va pa ps ed pl " "ar a d ma key\n"); for (i = 0; i < 8; i++) print_tr(i, &tr->dtrs[i]); } } #endif #ifndef NO_TRANSLATION void *map_page(vcpu_guest_context_t *ctx, int vcpu, size_t virt) { static unsigned long previous_mfn = 0; static void *mapped = NULL; unsigned long mfn = xc_translate_foreign_address(xc_handle, domid, vcpu, virt); unsigned long offset = virt & ~XC_PAGE_MASK; if (mapped && mfn == previous_mfn) goto out; if (mapped) munmap(mapped, XC_PAGE_SIZE); previous_mfn = mfn; mapped = xc_map_foreign_range(xc_handle, domid, XC_PAGE_SIZE, PROT_READ, mfn); if (mapped == NULL) { fprintf(stderr, "failed to map page.\n"); exit(-1); } out: return (void *)(mapped + offset); } void print_stack(vcpu_guest_context_t *ctx, int vcpu) { struct cpu_user_regs *regs = &ctx->user_regs; size_t stack = STACK_POINTER(regs); size_t stack_limit = (STACK_POINTER(regs) & XC_PAGE_MASK) + XC_PAGE_SIZE; size_t frame; size_t instr; size_t *p; int i; printf("\n"); printf("Stack:\n"); for (i=1; i ", *c); else printf("%02x ", *c); } printf("\n"); printf("\n"); if(stack_trace) printf("Stack Trace:\n"); else printf("Call Trace:\n"); printf("%c [<" FMT_SIZE_T ">] ", stack_trace ? '*' : ' ', INSTR_POINTER(regs)); print_symbol(INSTR_POINTER(regs)); printf(" <--\n"); if (frame_ptrs) { stack = STACK_POINTER(regs); frame = FRAME_POINTER(regs); while(frame && stack < stack_limit) { if (stack_trace) { while (stack < frame) { p = map_page(ctx, vcpu, stack); printf("| " FMT_SIZE_T " ", *p); printf("\n"); stack += sizeof(*p); } } else { stack = frame; } p = map_page(ctx, vcpu, stack); frame = *p; if (stack_trace) printf("|-- " FMT_SIZE_T "\n", *p); stack += sizeof(*p); if (frame) { p = map_page(ctx, vcpu, stack); printf("%c [<" FMT_SIZE_T ">] ", stack_trace ? '|' : ' ', *p); print_symbol(*p); printf("\n"); stack += sizeof(*p); } } } else { stack = STACK_POINTER(regs); while(stack < stack_limit) { p = map_page(ctx, vcpu, stack); if (is_kernel_text(*p)) { printf(" [<" FMT_SIZE_T ">] ", *p); print_symbol(*p); printf("\n"); } else if (stack_trace) { printf(" " FMT_SIZE_T "\n", *p); } stack += sizeof(*p); } } } #endif void dump_ctx(int vcpu) { int ret; vcpu_guest_context_t ctx; xc_dominfo_t dominfo; xc_handle = xc_interface_open(); /* for accessing control interface */ ret = xc_domain_getinfo(xc_handle, domid, 1, &dominfo); if (ret < 0) { perror("xc_domain_getinfo"); exit(-1); } ret = xc_domain_pause(xc_handle, domid); if (ret < 0) { perror("xc_domain_pause"); exit(-1); } ret = xc_vcpu_getcontext(xc_handle, domid, vcpu, &ctx); if (ret < 0) { if (!dominfo.paused) xc_domain_unpause(xc_handle, domid); perror("xc_vcpu_getcontext"); exit(-1); } print_ctx(&ctx); #ifndef NO_TRANSLATION if (is_kernel_text(INSTR_POINTER((&ctx.user_regs)))) print_stack(&ctx, vcpu); #endif if (!dominfo.paused) { ret = xc_domain_unpause(xc_handle, domid); if (ret < 0) { perror("xc_domain_unpause"); exit(-1); } } xc_interface_close(xc_handle); if (ret < 0) { perror("xc_interface_close"); exit(-1); } } void usage(void) { printf("usage:\n\n"); printf(" xenctx [options] [VCPU]\n\n"); printf("options:\n"); printf(" -f, --frame-pointers\n"); printf(" assume the kernel was compiled with\n"); printf(" frame pointers.\n"); printf(" -s SYMTAB, --symbol-table=SYMTAB\n"); printf(" read symbol table from SYMTAB.\n"); printf(" --stack-trace print a complete stack trace.\n"); #ifdef __ia64__ printf(" -r LIST, --regs=LIST display more registers.\n"); printf(" -a --all same as --regs=tlb,cr,ar,br,bk\n"); #else printf(" -a --all display more registers\n"); #endif } int main(int argc, char **argv) { int ch; static const char *sopts = "fs:h" #ifdef __ia64__ "ar:" #endif ; static const struct option lopts[] = { {"stack-trace", 0, NULL, 'S'}, {"symbol-table", 1, NULL, 's'}, {"frame-pointers", 0, NULL, 'f'}, #ifdef __ia64__ {"regs", 1, NULL, 'r'}, {"all", 0, NULL, 'a'}, #endif {"help", 0, NULL, 'h'}, {0, 0, 0, 0} }; const char *symbol_table = NULL; int vcpu = 0; while ((ch = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) { switch(ch) { case 'f': frame_ptrs = 1; break; case 's': symbol_table = optarg; break; case 'S': stack_trace = 1; break; #ifdef __ia64__ case 'r': { char *r; r = strtok(optarg, ","); while (r) { if (strcmp (r, "cr") == 0) disp_cr_regs = 1; else if (strcmp (r, "ar") == 0) disp_ar_regs = 1; else if (strcmp (r, "br") == 0) disp_br_regs = 1; else if (strcmp (r, "bk") == 0) disp_bank_regs = 1; else if (strcmp (r, "tlb") == 0) disp_tlb = 1; else { fprintf(stderr,"unknown register set %s\n", r); exit(-1); } r = strtok(NULL, "'"); } } break; case 'a': disp_cr_regs = 1; disp_ar_regs = 1; disp_br_regs = 1; disp_bank_regs = 1; disp_tlb = 1; break; #else case 'a': disp_all = 1; break; #endif case 'h': usage(); exit(-1); case '?': fprintf(stderr, "%s --help for more options\n", argv[0]); exit(-1); } } argv += optind; argc -= optind; if (argc < 1 || argc > 2) { printf("usage: xenctx [options] \n"); exit(-1); } domid = atoi(argv[0]); if (domid==0) { fprintf(stderr, "cannot trace dom0\n"); exit(-1); } if (argc == 2) vcpu = atoi(argv[1]); if (symbol_table) read_symbol_table(symbol_table); dump_ctx(vcpu); return 0; } /* * Local variables: * mode: C * c-set-style: "BSD" * c-basic-offset: 4 * tab-width: 4 * indent-tabs-mode: nil * End: */