Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


added symbolic backtrace functionality
[palacios.git] / palacios / src / palacios / vmm_debug.c
1 /* 
2  * This file is part of the Palacios Virtual Machine Monitor developed
3  * by the V3VEE Project with funding from the United States National 
4  * Science Foundation and the Department of Energy.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
11  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20
21 #include <palacios/vmm_debug.h>
22 #include <palacios/vmm.h>
23 #include <palacios/vmm_host_events.h>
24 #include <palacios/vm_guest.h>
25 #include <palacios/vmm_decoder.h>
26 #include <palacios/vm_guest_mem.h>
27 #include <palacios/vmm_config.h>
28
29 #define PRINT_TELEMETRY  1
30 #define PRINT_CORE_STATE 2
31 #define PRINT_ARCH_STATE 3
32 #define PRINT_STACK      4
33 #define PRINT_BACKTRACE  5
34
35
36 #define PRINT_ALL        100 // Absolutely everything
37 #define PRINT_STATE      101 // telemetry, core state, arch state
38
39
40
41
42 static int core_handler(struct guest_info * core, uint32_t cmd) {
43
44
45     switch (cmd) {
46         case PRINT_TELEMETRY: 
47             v3_print_core_telemetry(core);
48             break;
49         
50         case PRINT_CORE_STATE:
51             v3_raise_barrier(core->vm_info, NULL);
52
53             v3_print_guest_state(core);
54
55             v3_lower_barrier(core->vm_info);
56             break;
57         case PRINT_ARCH_STATE:
58             v3_raise_barrier(core->vm_info, NULL);
59
60             v3_print_arch_state(core);
61
62             v3_lower_barrier(core->vm_info);
63             break;
64         case PRINT_STACK:
65             v3_raise_barrier(core->vm_info, NULL);
66
67             v3_print_stack(core);
68
69             v3_lower_barrier(core->vm_info);
70             break;
71         case PRINT_BACKTRACE:
72             v3_raise_barrier(core->vm_info, NULL);
73
74             v3_print_backtrace(core);
75             
76             v3_lower_barrier(core->vm_info);
77             break;
78
79         case PRINT_STATE:
80             v3_raise_barrier(core->vm_info, NULL);
81
82             v3_print_core_telemetry(core);
83             v3_print_guest_state(core);
84             v3_print_arch_state(core);
85
86             v3_lower_barrier(core->vm_info);
87             break;
88
89     }
90
91     return 0;
92 }
93
94
95 static int evt_handler(struct v3_vm_info * vm, struct v3_debug_event * evt, void * priv_data) {
96
97     V3_Print("Debug Event Handler for core %d\n", evt->core_id);
98
99     if (evt->core_id == -1) {
100         int i = 0;
101         for (i = 0; i < vm->num_cores; i++) {
102             core_handler(&(vm->cores[i]), evt->cmd);
103         }
104     } else {
105         return core_handler(&vm->cores[evt->core_id], evt->cmd);
106     }
107
108     
109     return 0;
110 }
111
112
113 int v3_init_vm_debugging(struct v3_vm_info * vm) {
114     v3_hook_host_event(vm, HOST_DEBUG_EVT, 
115                        V3_HOST_EVENT_HANDLER(evt_handler), 
116                        NULL);
117
118
119     return 0;
120 }
121
122
123
124
125
126 void v3_print_segments(struct v3_segments * segs) {
127     int i = 0;
128     struct v3_segment * seg_ptr;
129
130     seg_ptr=(struct v3_segment *)segs;
131   
132     char *seg_names[] = {"CS", "DS" , "ES", "FS", "GS", "SS" , "LDTR", "GDTR", "IDTR", "TR", NULL};
133     V3_Print("Segments\n");
134
135     for (i = 0; seg_names[i] != NULL; i++) {
136
137         V3_Print("\t%s: Sel=%x, base=%p, limit=%x (long_mode=%d, db=%d)\n", seg_names[i], seg_ptr[i].selector, 
138                    (void *)(addr_t)seg_ptr[i].base, seg_ptr[i].limit,
139                    seg_ptr[i].long_mode, seg_ptr[i].db);
140
141     }
142 }
143
144
145
146 void v3_print_ctrl_regs(struct guest_info * core) {
147     struct v3_ctrl_regs * regs = &(core->ctrl_regs);
148     int i = 0;
149     v3_reg_t * reg_ptr;
150     char * reg_names[] = {"CR0", "CR2", "CR3", "CR4", "CR8", "FLAGS", "EFER", NULL};
151    
152
153     reg_ptr = (v3_reg_t *)regs;
154
155     V3_Print("Ctrl Regs:\n");
156
157     for (i = 0; reg_names[i] != NULL; i++) {
158         V3_Print("\t%s=0x%p (at %p)\n", reg_names[i], (void *)(addr_t)reg_ptr[i], &(reg_ptr[i]));  
159     }
160
161
162 }
163
164 #if 0
165 static int safe_gva_to_hva(struct guest_info * core, addr_t linear_addr, addr_t * host_addr) {
166     /* select the proper translation based on guest mode */
167     if (core->mem_mode == PHYSICAL_MEM) {
168         if (v3_gpa_to_hva(core, linear_addr, host_addr) == -1) return -1;
169     } else if (core->mem_mode == VIRTUAL_MEM) {
170         if (v3_gva_to_hva(core, linear_addr, host_addr) == -1) return -1;
171     }
172     return 0;
173 }
174
175 static int v3_print_disassembly(struct guest_info * core) {
176     int passed_rip = 0;
177     addr_t rip, rip_linear, rip_host;
178
179     /* we don't know where the instructions preceding RIP start, so we just take
180      * a guess and hope the instruction stream synced up with our disassembly
181      * some time before RIP; if it has not we correct RIP at that point
182      */
183
184     /* start disassembly 64 bytes before current RIP, continue 32 bytes after */
185     rip = (addr_t) core->rip - 64;
186     while ((int) (rip - core->rip) < 32) {
187         V3_Print("disassembly step\n");
188
189         /* always print RIP, even if the instructions before were bad */
190         if (!passed_rip && rip >= core->rip) {
191             if (rip != core->rip) {
192                 V3_Print("***** bad disassembly up to this point *****\n");
193                 rip = core->rip;
194             }
195             passed_rip = 1;
196         }
197
198         /* look up host virtual address for this instruction */
199         rip_linear = get_addr_linear(core, rip, &(core->segments.cs));
200         if (safe_gva_to_hva(core, rip_linear, &rip_host) < 0) {
201             rip++;
202             continue;
203         }
204
205         /* print disassembled instrcution (updates rip) */
206         if (v3_disasm(core, (void *) rip_host, &rip, rip == core->rip) < 0) {
207             rip++;
208             continue;
209         }
210
211     }
212
213     return 0;
214 }
215
216 #endif
217
218 void v3_print_guest_state(struct guest_info * core) {
219     addr_t linear_addr = 0; 
220
221     V3_Print("RIP: %p\n", (void *)(addr_t)(core->rip));
222     linear_addr = get_addr_linear(core, core->rip, &(core->segments.cs));
223     V3_Print("RIP Linear: %p\n", (void *)linear_addr);
224
225     V3_Print("NumExits: %u\n", (uint32_t)core->num_exits);
226
227     V3_Print("IRQ STATE: started=%d, pending=%d\n", 
228              core->intr_core_state.irq_started, 
229              core->intr_core_state.irq_pending);
230     V3_Print("EXCP STATE: err_code_valid=%d, err_code=%x\n", 
231              core->excp_state.excp_error_code_valid, 
232              core->excp_state.excp_error_code);
233
234
235     v3_print_segments(&(core->segments));
236     v3_print_ctrl_regs(core);
237
238     if (core->shdw_pg_mode == SHADOW_PAGING) {
239         V3_Print("Shadow Paging Guest Registers:\n");
240         V3_Print("\tGuest CR0=%p\n", (void *)(addr_t)(core->shdw_pg_state.guest_cr0));
241         V3_Print("\tGuest CR3=%p\n", (void *)(addr_t)(core->shdw_pg_state.guest_cr3));
242         V3_Print("\tGuest EFER=%p\n", (void *)(addr_t)(core->shdw_pg_state.guest_efer.value));
243         // CR4
244     }
245     v3_print_GPRs(core);
246
247     v3_print_mem_map(core->vm_info);
248
249     v3_print_stack(core);
250
251     //  v3_print_disassembly(core);
252 }
253
254
255 void v3_print_arch_state(struct guest_info * core) {
256
257
258 }
259
260
261 void v3_print_guest_state_all(struct v3_vm_info * vm) {
262     int i = 0;
263
264     V3_Print("VM Core states for %s\n", vm->name);
265
266     for (i = 0; i < 80; i++) {
267         V3_Print("-");
268     }
269
270     for (i = 0; i < vm->num_cores; i++) {
271         v3_print_guest_state(&vm->cores[i]);  
272     }
273     
274     for (i = 0; i < 80; i++) {
275         V3_Print("-");
276     }
277
278     V3_Print("\n");    
279 }
280
281
282
283 void v3_print_stack(struct guest_info * core) {
284     addr_t linear_addr = 0;
285     addr_t host_addr = 0;
286     int i = 0;
287     v3_cpu_mode_t cpu_mode = v3_get_vm_cpu_mode(core);
288
289     linear_addr = get_addr_linear(core, core->vm_regs.rsp, &(core->segments.ss));
290  
291     V3_Print("Stack at %p:\n", (void *)linear_addr);
292    
293     if (core->mem_mode == PHYSICAL_MEM) {
294         if (v3_gpa_to_hva(core, linear_addr, &host_addr) == -1) {
295             PrintError("Could not translate Stack address\n");
296             return;
297         }
298     } else if (core->mem_mode == VIRTUAL_MEM) {
299         if (v3_gva_to_hva(core, linear_addr, &host_addr) == -1) {
300             PrintError("Could not translate Virtual Stack address\n");
301             return;
302         }
303     }
304     
305     V3_Print("Host Address of rsp = 0x%p\n", (void *)host_addr);
306  
307     // We start i at one because the current stack pointer points to an unused stack element
308     for (i = 0; i <= 24; i++) {
309
310         if (cpu_mode == REAL) {
311             V3_Print("\t0x%.4x\n", *((uint16_t *)host_addr + (i * 2)));
312         } else if (cpu_mode == LONG) {
313             V3_Print("\t%p\n", (void *)*(addr_t *)(host_addr + (i * 8)));
314         } else {
315             // 32 bit stacks...
316             V3_Print("\t0x%.8x\n", *(uint32_t *)(host_addr + (i * 4)));
317         }
318     }
319
320 }    
321
322
323 void v3_print_backtrace(struct guest_info * core) {
324     addr_t gla_rbp = 0;
325     int i = 0;
326     v3_cpu_mode_t cpu_mode = v3_get_vm_cpu_mode(core);
327     struct v3_cfg_file * system_map = v3_cfg_get_file(core->vm_info, "System.map");
328
329     V3_Print("Performing Backtrace for Core %d\n", core->vcpu_id);
330     V3_Print("\tRSP=%p, RBP=%p\n", (void *)core->vm_regs.rsp, (void *)core->vm_regs.rbp);
331
332     gla_rbp = get_addr_linear(core, core->vm_regs.rbp, &(core->segments.ss));
333
334
335     for (i = 0; i < 30; i++) {
336         addr_t hva_rbp = 0; 
337         addr_t hva_rip = 0; 
338         char * sym_name = NULL;
339         addr_t rip_val = 0;
340
341         if (core->mem_mode == PHYSICAL_MEM) {
342             if (v3_gpa_to_hva(core, gla_rbp, &hva_rbp) == -1) {
343                 PrintError("Could not translate Stack address\n");
344                 return;
345             }
346         } else if (core->mem_mode == VIRTUAL_MEM) {
347             if (v3_gva_to_hva(core, gla_rbp, &hva_rbp) == -1) {
348                 PrintError("Could not translate Virtual Stack address\n");
349                 return;
350             }
351         }
352
353
354         hva_rip = hva_rbp + v3_get_addr_width(core);
355         
356         if (cpu_mode == REAL) {
357             rip_val = (addr_t)*(uint16_t *)hva_rip;
358         } else if (cpu_mode == LONG) {
359             rip_val = (addr_t)*(uint64_t *)hva_rip;
360         } else {
361             rip_val = (addr_t)*(uint32_t *)hva_rip;
362         }
363
364         if (system_map) {
365             char * tmp_ptr = system_map->data;
366             char * sym_ptr = NULL;
367             uint64_t file_offset = 0; 
368             uint64_t sym_offset = 0;
369
370             while (file_offset < system_map->size) {
371                 sym_offset = strtox(tmp_ptr, &tmp_ptr);
372
373                 tmp_ptr += 3; // pass over symbol type
374
375                 if (sym_offset > rip_val) {
376                     char * end_ptr = strchr(sym_ptr, '\n');
377
378                     if (end_ptr) {
379                         *end_ptr = 0; // null terminate symbol...
380                     }
381
382                     sym_name = sym_ptr;
383                     break;
384                 }
385
386                 sym_ptr = tmp_ptr;
387                 { 
388                     char * end_ptr2 = strchr(tmp_ptr, '\n');
389
390                     if (!end_ptr2) {
391                         tmp_ptr += strlen(tmp_ptr) + 1;
392                     } else {
393                         tmp_ptr = end_ptr2 + 1;
394                     }
395                 }
396             }
397         }
398
399         if (!sym_name) {
400             sym_name = "?";
401         }
402
403         if (cpu_mode == REAL) {
404             V3_Print("Next RBP=0x%.4x, RIP=0x%.4x (%s)\n", 
405                      *(uint16_t *)hva_rbp,*(uint16_t *)hva_rip, 
406                      sym_name);
407             
408             gla_rbp = *(uint16_t *)hva_rbp;
409         } else if (cpu_mode == LONG) {
410             V3_Print("Next RBP=%p, RIP=%p (%s)\n", 
411                      (void *)*(uint64_t *)hva_rbp, (void *)*(uint64_t *)hva_rip,
412                      sym_name);
413             gla_rbp = *(uint64_t *)hva_rbp;
414         } else {
415             V3_Print("Next RBP=0x%.8x, RIP=0x%.8x (%s)\n", 
416                      *(uint32_t *)hva_rbp, *(uint32_t *)hva_rip,
417                      sym_name);
418             gla_rbp = *(uint32_t *)hva_rbp;
419         }
420
421     }
422 }
423
424
425 #ifdef __V3_32BIT__
426
427 void v3_print_GPRs(struct guest_info * core) {
428     struct v3_gprs * regs = &(core->vm_regs);
429     int i = 0;
430     v3_reg_t * reg_ptr;
431     char * reg_names[] = { "RDI", "RSI", "RBP", "RSP", "RBX", "RDX", "RCX", "RAX", NULL};
432
433     reg_ptr = (v3_reg_t *)regs;
434
435     V3_Print("32 bit GPRs:\n");
436
437     for (i = 0; reg_names[i] != NULL; i++) {
438         V3_Print("\t%s=0x%p (at %p)\n", reg_names[i], (void *)(addr_t)reg_ptr[i], &(reg_ptr[i]));  
439     }
440 }
441
442 #elif __V3_64BIT__
443
444 void v3_print_GPRs(struct guest_info * core) {
445     struct v3_gprs * regs = &(core->vm_regs);
446     int i = 0;
447     v3_reg_t * reg_ptr;
448     char * reg_names[] = { "RDI", "RSI", "RBP", "RSP", "RBX", "RDX", "RCX", "RAX", \
449                            "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", NULL};
450
451     reg_ptr = (v3_reg_t *)regs;
452
453     V3_Print("64 bit GPRs:\n");
454
455     for (i = 0; reg_names[i] != NULL; i++) {
456         V3_Print("\t%s=0x%p (at %p)\n", reg_names[i], (void *)(addr_t)reg_ptr[i], &(reg_ptr[i]));  
457     }
458 }
459
460 #endif