VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR3/DBGF.cpp@ 38908

Last change on this file since 38908 was 38838, checked in by vboxsync, 13 years ago

VMM,++: Try fix the async reset, suspend and power-off problems in PDM wrt conflicting VMM requests. Split them into priority requests and normal requests. The priority requests can safely be processed when PDM is doing async state change waits, the normal ones cannot. (The problem I bumped into was a unmap-chunk request from PGM being processed during PDMR3Reset, causing a recursive VMMR3EmtRendezvous deadlock.)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 31.5 KB
Line 
1/* $Id: DBGF.cpp 38838 2011-09-23 11:21:55Z vboxsync $ */
2/** @file
3 * DBGF - Debugger Facility.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/** @page pg_dbgf DBGF - The Debugger Facility
20 *
21 * The purpose of the DBGF is to provide an interface for debuggers to
22 * manipulate the VMM without having to mess up the source code for each of
23 * them. The DBGF is always built in and will always work when a debugger
24 * attaches to the VM. The DBGF provides the basic debugger features, such as
25 * halting execution, handling breakpoints, single step execution, instruction
26 * disassembly, info querying, OS specific diggers, symbol and module
27 * management.
28 *
29 * The interface is working in a manner similar to the win32, linux and os2
30 * debugger interfaces. The interface has an asynchronous nature. This comes
31 * from the fact that the VMM and the Debugger are running in different threads.
32 * They are referred to as the "emulation thread" and the "debugger thread", or
33 * as the "ping thread" and the "pong thread, respectivly. (The last set of
34 * names comes from the use of the Ping-Pong synchronization construct from the
35 * RTSem API.)
36 *
37 * @see grp_dbgf
38 *
39 *
40 * @section sec_dbgf_scenario Usage Scenario
41 *
42 * The debugger starts by attaching to the VM. For practical reasons we limit the
43 * number of concurrently attached debuggers to 1 per VM. The action of
44 * attaching to the VM causes the VM to check and generate debug events.
45 *
46 * The debugger then will wait/poll for debug events and issue commands.
47 *
48 * The waiting and polling is done by the DBGFEventWait() function. It will wait
49 * for the emulation thread to send a ping, thus indicating that there is an
50 * event waiting to be processed.
51 *
52 * An event can be a response to a command issued previously, the hitting of a
53 * breakpoint, or running into a bad/fatal VMM condition. The debugger now has
54 * the ping and must respond to the event at hand - the VMM is waiting. This
55 * usually means that the user of the debugger must do something, but it doesn't
56 * have to. The debugger is free to call any DBGF function (nearly at least)
57 * while processing the event.
58 *
59 * Typically the user will issue a request for the execution to be resumed, so
60 * the debugger calls DBGFResume() and goes back to waiting/polling for events.
61 *
62 * When the user eventually terminates the debugging session or selects another
63 * VM, the debugger detaches from the VM. This means that breakpoints are
64 * disabled and that the emulation thread no longer polls for debugger commands.
65 *
66 */
67
68
69/*******************************************************************************
70* Header Files *
71*******************************************************************************/
72#define LOG_GROUP LOG_GROUP_DBGF
73#include <VBox/vmm/dbgf.h>
74#include <VBox/vmm/selm.h>
75#include <VBox/vmm/rem.h>
76#include <VBox/vmm/em.h>
77#include <VBox/vmm/hwaccm.h>
78#include "DBGFInternal.h"
79#include <VBox/vmm/vm.h>
80#include <VBox/err.h>
81
82#include <VBox/log.h>
83#include <iprt/semaphore.h>
84#include <iprt/thread.h>
85#include <iprt/asm.h>
86#include <iprt/time.h>
87#include <iprt/assert.h>
88#include <iprt/stream.h>
89#include <iprt/env.h>
90
91
92/*******************************************************************************
93* Internal Functions *
94*******************************************************************************/
95static int dbgfR3VMMWait(PVM pVM);
96static int dbgfR3VMMCmd(PVM pVM, DBGFCMD enmCmd, PDBGFCMDDATA pCmdData, bool *pfResumeExecution);
97static DECLCALLBACK(int) dbgfR3Attach(PVM pVM);
98
99
100/**
101 * Sets the VMM Debug Command variable.
102 *
103 * @returns Previous command.
104 * @param pVM VM Handle.
105 * @param enmCmd The command.
106 */
107DECLINLINE(DBGFCMD) dbgfR3SetCmd(PVM pVM, DBGFCMD enmCmd)
108{
109 DBGFCMD rc;
110 if (enmCmd == DBGFCMD_NO_COMMAND)
111 {
112 Log2(("DBGF: Setting command to %d (DBGFCMD_NO_COMMAND)\n", enmCmd));
113 rc = (DBGFCMD)ASMAtomicXchgU32((uint32_t volatile *)(void *)&pVM->dbgf.s.enmVMMCmd, enmCmd);
114 VM_FF_CLEAR(pVM, VM_FF_DBGF);
115 }
116 else
117 {
118 Log2(("DBGF: Setting command to %d\n", enmCmd));
119 AssertMsg(pVM->dbgf.s.enmVMMCmd == DBGFCMD_NO_COMMAND, ("enmCmd=%d enmVMMCmd=%d\n", enmCmd, pVM->dbgf.s.enmVMMCmd));
120 rc = (DBGFCMD)ASMAtomicXchgU32((uint32_t volatile *)(void *)&pVM->dbgf.s.enmVMMCmd, enmCmd);
121 VM_FF_SET(pVM, VM_FF_DBGF);
122 VMR3NotifyGlobalFFU(pVM->pUVM, 0 /* didn't notify REM */);
123 }
124 return rc;
125}
126
127
128/**
129 * Initializes the DBGF.
130 *
131 * @returns VBox status code.
132 * @param pVM VM handle.
133 */
134VMMR3DECL(int) DBGFR3Init(PVM pVM)
135{
136 int rc = dbgfR3InfoInit(pVM);
137 if (RT_SUCCESS(rc))
138 rc = dbgfR3TraceInit(pVM);
139 if (RT_SUCCESS(rc))
140 rc = dbgfR3RegInit(pVM);
141 if (RT_SUCCESS(rc))
142 rc = dbgfR3AsInit(pVM);
143 if (RT_SUCCESS(rc))
144 rc = dbgfR3SymInit(pVM);
145 if (RT_SUCCESS(rc))
146 rc = dbgfR3BpInit(pVM);
147 return rc;
148}
149
150
151/**
152 * Terminates and cleans up resources allocated by the DBGF.
153 *
154 * @returns VBox status code.
155 * @param pVM VM Handle.
156 */
157VMMR3DECL(int) DBGFR3Term(PVM pVM)
158{
159 int rc;
160
161 /*
162 * Send a termination event to any attached debugger.
163 */
164 /* wait to become the speaker (we should already be that). */
165 if ( pVM->dbgf.s.fAttached
166 && RTSemPingShouldWait(&pVM->dbgf.s.PingPong))
167 RTSemPingWait(&pVM->dbgf.s.PingPong, 5000);
168
169 /* now, send the event if we're the speaker. */
170 if ( pVM->dbgf.s.fAttached
171 && RTSemPingIsSpeaker(&pVM->dbgf.s.PingPong))
172 {
173 DBGFCMD enmCmd = dbgfR3SetCmd(pVM, DBGFCMD_NO_COMMAND);
174 if (enmCmd == DBGFCMD_DETACH_DEBUGGER)
175 /* the debugger beat us to initiating the detaching. */
176 rc = VINF_SUCCESS;
177 else
178 {
179 /* ignore the command (if any). */
180 enmCmd = DBGFCMD_NO_COMMAND;
181 pVM->dbgf.s.DbgEvent.enmType = DBGFEVENT_TERMINATING;
182 pVM->dbgf.s.DbgEvent.enmCtx = DBGFEVENTCTX_OTHER;
183 rc = RTSemPing(&pVM->dbgf.s.PingPong);
184 }
185
186 /*
187 * Process commands until we get a detached command.
188 */
189 while (RT_SUCCESS(rc) && enmCmd != DBGFCMD_DETACHED_DEBUGGER)
190 {
191 if (enmCmd != DBGFCMD_NO_COMMAND)
192 {
193 /* process command */
194 bool fResumeExecution;
195 DBGFCMDDATA CmdData = pVM->dbgf.s.VMMCmdData;
196 rc = dbgfR3VMMCmd(pVM, enmCmd, &CmdData, &fResumeExecution);
197 enmCmd = DBGFCMD_NO_COMMAND;
198 }
199 else
200 {
201 /* wait for new command. */
202 rc = RTSemPingWait(&pVM->dbgf.s.PingPong, RT_INDEFINITE_WAIT);
203 if (RT_SUCCESS(rc))
204 enmCmd = dbgfR3SetCmd(pVM, DBGFCMD_NO_COMMAND);
205 }
206 }
207 }
208
209 /*
210 * Terminate the other bits.
211 */
212 dbgfR3OSTerm(pVM);
213 dbgfR3AsTerm(pVM);
214 dbgfR3RegTerm(pVM);
215 dbgfR3TraceTerm(pVM);
216 dbgfR3InfoTerm(pVM);
217 return VINF_SUCCESS;
218}
219
220
221/**
222 * Applies relocations to data and code managed by this
223 * component. This function will be called at init and
224 * whenever the VMM need to relocate it self inside the GC.
225 *
226 * @param pVM VM handle.
227 * @param offDelta Relocation delta relative to old location.
228 */
229VMMR3DECL(void) DBGFR3Relocate(PVM pVM, RTGCINTPTR offDelta)
230{
231 dbgfR3TraceRelocate(pVM);
232 dbgfR3AsRelocate(pVM, offDelta);
233}
234
235
236/**
237 * Waits a little while for a debuggger to attach.
238 *
239 * @returns True is a debugger have attached.
240 * @param pVM VM handle.
241 * @param enmEvent Event.
242 */
243bool dbgfR3WaitForAttach(PVM pVM, DBGFEVENTTYPE enmEvent)
244{
245 /*
246 * First a message.
247 */
248#ifndef RT_OS_L4
249
250# if !defined(DEBUG) || defined(DEBUG_sandervl) || defined(DEBUG_frank) || defined(IEM_VERIFICATION_MODE)
251 int cWait = 10;
252# else
253 int cWait = HWACCMIsEnabled(pVM)
254 && ( enmEvent == DBGFEVENT_ASSERTION_HYPER
255 || enmEvent == DBGFEVENT_FATAL_ERROR)
256 && !RTEnvExist("VBOX_DBGF_WAIT_FOR_ATTACH")
257 ? 10
258 : 150;
259# endif
260 RTStrmPrintf(g_pStdErr, "DBGF: No debugger attached, waiting %d second%s for one to attach (event=%d)\n",
261 cWait / 10, cWait != 10 ? "s" : "", enmEvent);
262 RTStrmFlush(g_pStdErr);
263 while (cWait > 0)
264 {
265 RTThreadSleep(100);
266 if (pVM->dbgf.s.fAttached)
267 {
268 RTStrmPrintf(g_pStdErr, "Attached!\n");
269 RTStrmFlush(g_pStdErr);
270 return true;
271 }
272
273 /* next */
274 if (!(cWait % 10))
275 {
276 RTStrmPrintf(g_pStdErr, "%d.", cWait / 10);
277 RTStrmFlush(g_pStdErr);
278 }
279 cWait--;
280 }
281#endif
282
283 RTStrmPrintf(g_pStdErr, "Stopping the VM!\n");
284 RTStrmFlush(g_pStdErr);
285 return false;
286}
287
288
289/**
290 * Forced action callback.
291 * The VMM will call this from it's main loop when VM_FF_DBGF is set.
292 *
293 * The function checks and executes pending commands from the debugger.
294 *
295 * @returns VINF_SUCCESS normally.
296 * @returns VERR_DBGF_RAISE_FATAL_ERROR to pretend a fatal error happened.
297 * @param pVM VM Handle.
298 */
299VMMR3DECL(int) DBGFR3VMMForcedAction(PVM pVM)
300{
301 int rc = VINF_SUCCESS;
302
303 if (VM_FF_TESTANDCLEAR(pVM, VM_FF_DBGF))
304 {
305 PVMCPU pVCpu = VMMGetCpu(pVM);
306
307 /*
308 * Commands?
309 */
310 if (pVM->dbgf.s.enmVMMCmd != DBGFCMD_NO_COMMAND)
311 {
312 /** @todo stupid GDT/LDT sync hack. go away! */
313 SELMR3UpdateFromCPUM(pVM, pVCpu);
314
315 /*
316 * Process the command.
317 */
318 bool fResumeExecution;
319 DBGFCMDDATA CmdData = pVM->dbgf.s.VMMCmdData;
320 DBGFCMD enmCmd = dbgfR3SetCmd(pVM, DBGFCMD_NO_COMMAND);
321 rc = dbgfR3VMMCmd(pVM, enmCmd, &CmdData, &fResumeExecution);
322 if (!fResumeExecution)
323 rc = dbgfR3VMMWait(pVM);
324 }
325 }
326 return rc;
327}
328
329
330/**
331 * Flag whether the event implies that we're stopped in the hypervisor code
332 * and have to block certain operations.
333 *
334 * @param pVM The VM handle.
335 * @param enmEvent The event.
336 */
337static void dbgfR3EventSetStoppedInHyperFlag(PVM pVM, DBGFEVENTTYPE enmEvent)
338{
339 switch (enmEvent)
340 {
341 case DBGFEVENT_STEPPED_HYPER:
342 case DBGFEVENT_ASSERTION_HYPER:
343 case DBGFEVENT_BREAKPOINT_HYPER:
344 pVM->dbgf.s.fStoppedInHyper = true;
345 break;
346 default:
347 pVM->dbgf.s.fStoppedInHyper = false;
348 break;
349 }
350}
351
352
353/**
354 * Try to determine the event context.
355 *
356 * @returns debug event context.
357 * @param pVM The VM handle.
358 */
359static DBGFEVENTCTX dbgfR3FigureEventCtx(PVM pVM)
360{
361 /** @todo SMP support! */
362 PVMCPU pVCpu = &pVM->aCpus[0];
363
364 switch (EMGetState(pVCpu))
365 {
366 case EMSTATE_RAW:
367 case EMSTATE_DEBUG_GUEST_RAW:
368 return DBGFEVENTCTX_RAW;
369
370 case EMSTATE_REM:
371 case EMSTATE_DEBUG_GUEST_REM:
372 return DBGFEVENTCTX_REM;
373
374 case EMSTATE_DEBUG_HYPER:
375 case EMSTATE_GURU_MEDITATION:
376 return DBGFEVENTCTX_HYPER;
377
378 default:
379 return DBGFEVENTCTX_OTHER;
380 }
381}
382
383/**
384 * The common event prologue code.
385 * It will set the 'stopped-in-hyper' flag, make sure someone is attached,
386 * and perhaps process any high priority pending actions (none yet).
387 *
388 * @returns VBox status.
389 * @param pVM The VM handle.
390 * @param enmEvent The event to be sent.
391 */
392static int dbgfR3EventPrologue(PVM pVM, DBGFEVENTTYPE enmEvent)
393{
394 /** @todo SMP */
395 PVMCPU pVCpu = VMMGetCpu(pVM);
396
397 /*
398 * Check if a debugger is attached.
399 */
400 if ( !pVM->dbgf.s.fAttached
401 && !dbgfR3WaitForAttach(pVM, enmEvent))
402 {
403 Log(("DBGFR3VMMEventSrc: enmEvent=%d - debugger not attached\n", enmEvent));
404 return VERR_DBGF_NOT_ATTACHED;
405 }
406
407 /*
408 * Sync back the state from the REM.
409 */
410 dbgfR3EventSetStoppedInHyperFlag(pVM, enmEvent);
411 if (!pVM->dbgf.s.fStoppedInHyper)
412 REMR3StateUpdate(pVM, pVCpu);
413
414 /*
415 * Look thru pending commands and finish those which make sense now.
416 */
417 /** @todo Process/purge pending commands. */
418 //int rc = DBGFR3VMMForcedAction(pVM);
419 return VINF_SUCCESS;
420}
421
422
423/**
424 * Sends the event in the event buffer.
425 *
426 * @returns VBox status code.
427 * @param pVM The VM handle.
428 */
429static int dbgfR3SendEvent(PVM pVM)
430{
431 int rc = RTSemPing(&pVM->dbgf.s.PingPong);
432 if (RT_SUCCESS(rc))
433 rc = dbgfR3VMMWait(pVM);
434
435 pVM->dbgf.s.fStoppedInHyper = false;
436 /** @todo sync VMM -> REM after exitting the debugger. everything may change while in the debugger! */
437 return rc;
438}
439
440
441/**
442 * Send a generic debugger event which takes no data.
443 *
444 * @returns VBox status.
445 * @param pVM The VM handle.
446 * @param enmEvent The event to send.
447 */
448VMMR3DECL(int) DBGFR3Event(PVM pVM, DBGFEVENTTYPE enmEvent)
449{
450 int rc = dbgfR3EventPrologue(pVM, enmEvent);
451 if (RT_FAILURE(rc))
452 return rc;
453
454 /*
455 * Send the event and process the reply communication.
456 */
457 pVM->dbgf.s.DbgEvent.enmType = enmEvent;
458 pVM->dbgf.s.DbgEvent.enmCtx = dbgfR3FigureEventCtx(pVM);
459 return dbgfR3SendEvent(pVM);
460}
461
462
463/**
464 * Send a debugger event which takes the full source file location.
465 *
466 * @returns VBox status.
467 * @param pVM The VM handle.
468 * @param enmEvent The event to send.
469 * @param pszFile Source file.
470 * @param uLine Line number in source file.
471 * @param pszFunction Function name.
472 * @param pszFormat Message which accompanies the event.
473 * @param ... Message arguments.
474 */
475VMMR3DECL(int) DBGFR3EventSrc(PVM pVM, DBGFEVENTTYPE enmEvent, const char *pszFile, unsigned uLine, const char *pszFunction, const char *pszFormat, ...)
476{
477 va_list args;
478 va_start(args, pszFormat);
479 int rc = DBGFR3EventSrcV(pVM, enmEvent, pszFile, uLine, pszFunction, pszFormat, args);
480 va_end(args);
481 return rc;
482}
483
484
485/**
486 * Send a debugger event which takes the full source file location.
487 *
488 * @returns VBox status.
489 * @param pVM The VM handle.
490 * @param enmEvent The event to send.
491 * @param pszFile Source file.
492 * @param uLine Line number in source file.
493 * @param pszFunction Function name.
494 * @param pszFormat Message which accompanies the event.
495 * @param args Message arguments.
496 */
497VMMR3DECL(int) DBGFR3EventSrcV(PVM pVM, DBGFEVENTTYPE enmEvent, const char *pszFile, unsigned uLine, const char *pszFunction, const char *pszFormat, va_list args)
498{
499 int rc = dbgfR3EventPrologue(pVM, enmEvent);
500 if (RT_FAILURE(rc))
501 return rc;
502
503 /*
504 * Format the message.
505 */
506 char *pszMessage = NULL;
507 char szMessage[8192];
508 if (pszFormat && *pszFormat)
509 {
510 pszMessage = &szMessage[0];
511 RTStrPrintfV(szMessage, sizeof(szMessage), pszFormat, args);
512 }
513
514 /*
515 * Send the event and process the reply communication.
516 */
517 pVM->dbgf.s.DbgEvent.enmType = enmEvent;
518 pVM->dbgf.s.DbgEvent.enmCtx = dbgfR3FigureEventCtx(pVM);
519 pVM->dbgf.s.DbgEvent.u.Src.pszFile = pszFile;
520 pVM->dbgf.s.DbgEvent.u.Src.uLine = uLine;
521 pVM->dbgf.s.DbgEvent.u.Src.pszFunction = pszFunction;
522 pVM->dbgf.s.DbgEvent.u.Src.pszMessage = pszMessage;
523 return dbgfR3SendEvent(pVM);
524}
525
526
527/**
528 * Send a debugger event which takes the two assertion messages.
529 *
530 * @returns VBox status.
531 * @param pVM The VM handle.
532 * @param enmEvent The event to send.
533 * @param pszMsg1 First assertion message.
534 * @param pszMsg2 Second assertion message.
535 */
536VMMR3DECL(int) DBGFR3EventAssertion(PVM pVM, DBGFEVENTTYPE enmEvent, const char *pszMsg1, const char *pszMsg2)
537{
538 int rc = dbgfR3EventPrologue(pVM, enmEvent);
539 if (RT_FAILURE(rc))
540 return rc;
541
542 /*
543 * Send the event and process the reply communication.
544 */
545 pVM->dbgf.s.DbgEvent.enmType = enmEvent;
546 pVM->dbgf.s.DbgEvent.enmCtx = dbgfR3FigureEventCtx(pVM);
547 pVM->dbgf.s.DbgEvent.u.Assert.pszMsg1 = pszMsg1;
548 pVM->dbgf.s.DbgEvent.u.Assert.pszMsg2 = pszMsg2;
549 return dbgfR3SendEvent(pVM);
550}
551
552
553/**
554 * Breakpoint was hit somewhere.
555 * Figure out which breakpoint it is and notify the debugger.
556 *
557 * @returns VBox status.
558 * @param pVM The VM handle.
559 * @param enmEvent DBGFEVENT_BREAKPOINT_HYPER or DBGFEVENT_BREAKPOINT.
560 */
561VMMR3DECL(int) DBGFR3EventBreakpoint(PVM pVM, DBGFEVENTTYPE enmEvent)
562{
563 int rc = dbgfR3EventPrologue(pVM, enmEvent);
564 if (RT_FAILURE(rc))
565 return rc;
566
567 /*
568 * Send the event and process the reply communication.
569 */
570 /** @todo SMP */
571 PVMCPU pVCpu = VMMGetCpu0(pVM);
572
573 pVM->dbgf.s.DbgEvent.enmType = enmEvent;
574 RTUINT iBp = pVM->dbgf.s.DbgEvent.u.Bp.iBp = pVCpu->dbgf.s.iActiveBp;
575 pVCpu->dbgf.s.iActiveBp = ~0U;
576 if (iBp != ~0U)
577 pVM->dbgf.s.DbgEvent.enmCtx = DBGFEVENTCTX_RAW;
578 else
579 {
580 /* REM breakpoints has be been searched for. */
581#if 0 /** @todo get flat PC api! */
582 uint32_t eip = CPUMGetGuestEIP(pVM);
583#else
584 /* @todo SMP support!! */
585 PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(VMMGetCpu(pVM));
586 RTGCPTR eip = pCtx->rip + pCtx->csHid.u64Base;
587#endif
588 for (iBp = 0; iBp < RT_ELEMENTS(pVM->dbgf.s.aBreakpoints); iBp++)
589 if ( pVM->dbgf.s.aBreakpoints[iBp].enmType == DBGFBPTYPE_REM
590 && pVM->dbgf.s.aBreakpoints[iBp].GCPtr == eip)
591 {
592 pVM->dbgf.s.DbgEvent.u.Bp.iBp = iBp;
593 break;
594 }
595 AssertMsg(pVM->dbgf.s.DbgEvent.u.Bp.iBp != ~0U, ("eip=%08x\n", eip));
596 pVM->dbgf.s.DbgEvent.enmCtx = DBGFEVENTCTX_REM;
597 }
598 return dbgfR3SendEvent(pVM);
599}
600
601
602/**
603 * Waits for the debugger to respond.
604 *
605 * @returns VBox status. (clearify)
606 * @param pVM VM handle.
607 */
608static int dbgfR3VMMWait(PVM pVM)
609{
610 PVMCPU pVCpu = VMMGetCpu(pVM);
611
612 LogFlow(("dbgfR3VMMWait:\n"));
613
614 /** @todo stupid GDT/LDT sync hack. go away! */
615 SELMR3UpdateFromCPUM(pVM, pVCpu);
616 int rcRet = VINF_SUCCESS;
617
618 /*
619 * Waits for the debugger to reply (i.e. issue an command).
620 */
621 for (;;)
622 {
623 /*
624 * Wait.
625 */
626 uint32_t cPollHack = 1; /** @todo this interface is horrible now that we're using lots of VMR3ReqCall stuff all over DBGF. */
627 for (;;)
628 {
629 int rc;
630 if ( !VM_FF_ISPENDING(pVM, VM_FF_EMT_RENDEZVOUS | VM_FF_REQUEST)
631 && !VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_REQUEST))
632 {
633 rc = RTSemPingWait(&pVM->dbgf.s.PingPong, cPollHack);
634 if (RT_SUCCESS(rc))
635 break;
636 if (rc != VERR_TIMEOUT)
637 {
638 LogFlow(("dbgfR3VMMWait: returns %Rrc\n", rc));
639 return rc;
640 }
641 }
642
643 if (VM_FF_ISPENDING(pVM, VM_FF_EMT_RENDEZVOUS))
644 {
645 rc = VMMR3EmtRendezvousFF(pVM, pVCpu);
646 cPollHack = 1;
647 }
648 else if ( VM_FF_ISPENDING(pVM, VM_FF_REQUEST)
649 || VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_REQUEST))
650 {
651 LogFlow(("dbgfR3VMMWait: Processes requests...\n"));
652 rc = VMR3ReqProcessU(pVM->pUVM, VMCPUID_ANY, false /*fPriorityOnly*/);
653 if (rc == VINF_SUCCESS)
654 rc = VMR3ReqProcessU(pVM->pUVM, pVCpu->idCpu, false /*fPriorityOnly*/);
655 LogFlow(("dbgfR3VMMWait: VMR3ReqProcess -> %Rrc rcRet=%Rrc\n", rc, rcRet));
656 cPollHack = 1;
657 }
658 else
659 {
660 rc = VINF_SUCCESS;
661 if (cPollHack < 120)
662 cPollHack++;
663 }
664
665 if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)
666 {
667 switch (rc)
668 {
669 case VINF_EM_DBG_BREAKPOINT:
670 case VINF_EM_DBG_STEPPED:
671 case VINF_EM_DBG_STEP:
672 case VINF_EM_DBG_STOP:
673 AssertMsgFailed(("rc=%Rrc\n", rc));
674 break;
675
676 /* return straight away */
677 case VINF_EM_TERMINATE:
678 case VINF_EM_OFF:
679 LogFlow(("dbgfR3VMMWait: returns %Rrc\n", rc));
680 return rc;
681
682 /* remember return code. */
683 default:
684 AssertReleaseMsgFailed(("rc=%Rrc is not in the switch!\n", rc));
685 case VINF_EM_RESET:
686 case VINF_EM_SUSPEND:
687 case VINF_EM_HALT:
688 case VINF_EM_RESUME:
689 case VINF_EM_RESCHEDULE:
690 case VINF_EM_RESCHEDULE_REM:
691 case VINF_EM_RESCHEDULE_RAW:
692 if (rc < rcRet || rcRet == VINF_SUCCESS)
693 rcRet = rc;
694 break;
695 }
696 }
697 else if (RT_FAILURE(rc))
698 {
699 LogFlow(("dbgfR3VMMWait: returns %Rrc\n", rc));
700 return rc;
701 }
702 }
703
704 /*
705 * Process the command.
706 */
707 bool fResumeExecution;
708 DBGFCMDDATA CmdData = pVM->dbgf.s.VMMCmdData;
709 DBGFCMD enmCmd = dbgfR3SetCmd(pVM, DBGFCMD_NO_COMMAND);
710 int rc = dbgfR3VMMCmd(pVM, enmCmd, &CmdData, &fResumeExecution);
711 if (fResumeExecution)
712 {
713 if (RT_FAILURE(rc))
714 rcRet = rc;
715 else if ( rc >= VINF_EM_FIRST
716 && rc <= VINF_EM_LAST
717 && (rc < rcRet || rcRet == VINF_SUCCESS))
718 rcRet = rc;
719 LogFlow(("dbgfR3VMMWait: returns %Rrc\n", rcRet));
720 return rcRet;
721 }
722 }
723}
724
725
726/**
727 * Executes command from debugger.
728 * The caller is responsible for waiting or resuming execution based on the
729 * value returned in the *pfResumeExecution indicator.
730 *
731 * @returns VBox status. (clearify!)
732 * @param pVM VM Handle.
733 * @param enmCmd The command in question.
734 * @param pCmdData Pointer to the command data.
735 * @param pfResumeExecution Where to store the resume execution / continue waiting indicator.
736 */
737static int dbgfR3VMMCmd(PVM pVM, DBGFCMD enmCmd, PDBGFCMDDATA pCmdData, bool *pfResumeExecution)
738{
739 bool fSendEvent;
740 bool fResume;
741 int rc = VINF_SUCCESS;
742
743 switch (enmCmd)
744 {
745 /*
746 * Halt is answered by an event say that we've halted.
747 */
748 case DBGFCMD_HALT:
749 {
750 pVM->dbgf.s.DbgEvent.enmType = DBGFEVENT_HALT_DONE;
751 pVM->dbgf.s.DbgEvent.enmCtx = dbgfR3FigureEventCtx(pVM);
752 fSendEvent = true;
753 fResume = false;
754 break;
755 }
756
757
758 /*
759 * Resume is not answered we'll just resume execution.
760 */
761 case DBGFCMD_GO:
762 {
763 fSendEvent = false;
764 fResume = true;
765 break;
766 }
767
768 /** @todo implement (and define) the rest of the commands. */
769
770 /*
771 * Disable breakpoints and stuff.
772 * Send an everythings cool event to the debugger thread and resume execution.
773 */
774 case DBGFCMD_DETACH_DEBUGGER:
775 {
776 ASMAtomicWriteBool(&pVM->dbgf.s.fAttached, false);
777 pVM->dbgf.s.DbgEvent.enmType = DBGFEVENT_DETACH_DONE;
778 pVM->dbgf.s.DbgEvent.enmCtx = DBGFEVENTCTX_OTHER;
779 fSendEvent = true;
780 fResume = true;
781 break;
782 }
783
784 /*
785 * The debugger has detached successfully.
786 * There is no reply to this event.
787 */
788 case DBGFCMD_DETACHED_DEBUGGER:
789 {
790 fSendEvent = false;
791 fResume = true;
792 break;
793 }
794
795 /*
796 * Single step, with trace into.
797 */
798 case DBGFCMD_SINGLE_STEP:
799 {
800 Log2(("Single step\n"));
801 rc = VINF_EM_DBG_STEP;
802 /** @todo SMP */
803 PVMCPU pVCpu = VMMGetCpu0(pVM);
804 pVCpu->dbgf.s.fSingleSteppingRaw = true;
805 fSendEvent = false;
806 fResume = true;
807 break;
808 }
809
810 /*
811 * Default is to send an invalid command event.
812 */
813 default:
814 {
815 pVM->dbgf.s.DbgEvent.enmType = DBGFEVENT_INVALID_COMMAND;
816 pVM->dbgf.s.DbgEvent.enmCtx = dbgfR3FigureEventCtx(pVM);
817 fSendEvent = true;
818 fResume = false;
819 break;
820 }
821 }
822
823 /*
824 * Send pending event.
825 */
826 if (fSendEvent)
827 {
828 Log2(("DBGF: Emulation thread: sending event %d\n", pVM->dbgf.s.DbgEvent.enmType));
829 int rc2 = RTSemPing(&pVM->dbgf.s.PingPong);
830 if (RT_FAILURE(rc2))
831 {
832 AssertRC(rc2);
833 *pfResumeExecution = true;
834 return rc2;
835 }
836 }
837
838 /*
839 * Return.
840 */
841 *pfResumeExecution = fResume;
842 return rc;
843}
844
845
846/**
847 * Attaches a debugger to the specified VM.
848 *
849 * Only one debugger at a time.
850 *
851 * @returns VBox status code.
852 * @param pVM VM Handle.
853 */
854VMMR3DECL(int) DBGFR3Attach(PVM pVM)
855{
856 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
857
858 /*
859 * Call the VM, use EMT for serialization.
860 */
861 /** @todo SMP */
862 return VMR3ReqCallWait(pVM, VMCPUID_ANY, (PFNRT)dbgfR3Attach, 1, pVM);
863}
864
865
866/**
867 * EMT worker for DBGFR3Attach.
868 *
869 * @returns VBox status code.
870 * @param pVM Pointer to the shared VM structure.
871 */
872static DECLCALLBACK(int) dbgfR3Attach(PVM pVM)
873{
874 if (pVM->dbgf.s.fAttached)
875 {
876 Log(("dbgR3Attach: Debugger already attached\n"));
877 return VERR_DBGF_ALREADY_ATTACHED;
878 }
879
880 /*
881 * Create the Ping-Pong structure.
882 */
883 int rc = RTSemPingPongInit(&pVM->dbgf.s.PingPong);
884 AssertRCReturn(rc, rc);
885
886 /*
887 * Set the attached flag.
888 */
889 ASMAtomicWriteBool(&pVM->dbgf.s.fAttached, true);
890 return VINF_SUCCESS;
891}
892
893
894/**
895 * Detaches a debugger from the specified VM.
896 *
897 * Caller must be attached to the VM.
898 *
899 * @returns VBox status code.
900 * @param pVM VM Handle.
901 */
902VMMR3DECL(int) DBGFR3Detach(PVM pVM)
903{
904 LogFlow(("DBGFR3Detach:\n"));
905 int rc;
906
907 /*
908 * Check if attached.
909 */
910 AssertReturn(pVM->dbgf.s.fAttached, VERR_DBGF_NOT_ATTACHED);
911
912 /*
913 * Try send the detach command.
914 * Keep in mind that we might be racing EMT, so, be extra careful.
915 */
916 DBGFCMD enmCmd = dbgfR3SetCmd(pVM, DBGFCMD_DETACH_DEBUGGER);
917 if (RTSemPongIsSpeaker(&pVM->dbgf.s.PingPong))
918 {
919 rc = RTSemPong(&pVM->dbgf.s.PingPong);
920 AssertMsgRCReturn(rc, ("Failed to signal emulation thread. rc=%Rrc\n", rc), rc);
921 LogRel(("DBGFR3Detach: enmCmd=%d (pong -> ping)\n", enmCmd));
922 }
923
924 /*
925 * Wait for the OK event.
926 */
927 rc = RTSemPongWait(&pVM->dbgf.s.PingPong, RT_INDEFINITE_WAIT);
928 AssertLogRelMsgRCReturn(rc, ("Wait on detach command failed, rc=%Rrc\n", rc), rc);
929
930 /*
931 * Send the notification command indicating that we're really done.
932 */
933 enmCmd = dbgfR3SetCmd(pVM, DBGFCMD_DETACHED_DEBUGGER);
934 rc = RTSemPong(&pVM->dbgf.s.PingPong);
935 AssertMsgRCReturn(rc, ("Failed to signal emulation thread. rc=%Rrc\n", rc), rc);
936
937 LogFlowFunc(("returns VINF_SUCCESS\n"));
938 return VINF_SUCCESS;
939}
940
941
942/**
943 * Wait for a debug event.
944 *
945 * @returns VBox status. Will not return VBOX_INTERRUPTED.
946 * @param pVM VM handle.
947 * @param cMillies Number of millis to wait.
948 * @param ppEvent Where to store the event pointer.
949 */
950VMMR3DECL(int) DBGFR3EventWait(PVM pVM, RTMSINTERVAL cMillies, PCDBGFEVENT *ppEvent)
951{
952 /*
953 * Check state.
954 */
955 AssertReturn(pVM->dbgf.s.fAttached, VERR_DBGF_NOT_ATTACHED);
956 *ppEvent = NULL;
957
958 /*
959 * Wait.
960 */
961 int rc = RTSemPongWait(&pVM->dbgf.s.PingPong, cMillies);
962 if (RT_SUCCESS(rc))
963 {
964 *ppEvent = &pVM->dbgf.s.DbgEvent;
965 Log2(("DBGF: Debugger thread: receiving event %d\n", (*ppEvent)->enmType));
966 return VINF_SUCCESS;
967 }
968
969 return rc;
970}
971
972
973/**
974 * Halts VM execution.
975 *
976 * After calling this the VM isn't actually halted till an DBGFEVENT_HALT_DONE
977 * arrives. Until that time it's not possible to issue any new commands.
978 *
979 * @returns VBox status.
980 * @param pVM VM handle.
981 */
982VMMR3DECL(int) DBGFR3Halt(PVM pVM)
983{
984 /*
985 * Check state.
986 */
987 AssertReturn(pVM->dbgf.s.fAttached, VERR_DBGF_NOT_ATTACHED);
988 RTPINGPONGSPEAKER enmSpeaker = pVM->dbgf.s.PingPong.enmSpeaker;
989 if ( enmSpeaker == RTPINGPONGSPEAKER_PONG
990 || enmSpeaker == RTPINGPONGSPEAKER_PONG_SIGNALED)
991 return VWRN_DBGF_ALREADY_HALTED;
992
993 /*
994 * Send command.
995 */
996 dbgfR3SetCmd(pVM, DBGFCMD_HALT);
997
998 return VINF_SUCCESS;
999}
1000
1001
1002/**
1003 * Checks if the VM is halted by the debugger.
1004 *
1005 * @returns True if halted.
1006 * @returns False if not halted.
1007 * @param pVM VM handle.
1008 */
1009VMMR3DECL(bool) DBGFR3IsHalted(PVM pVM)
1010{
1011 AssertReturn(pVM->dbgf.s.fAttached, false);
1012 RTPINGPONGSPEAKER enmSpeaker = pVM->dbgf.s.PingPong.enmSpeaker;
1013 return enmSpeaker == RTPINGPONGSPEAKER_PONG_SIGNALED
1014 || enmSpeaker == RTPINGPONGSPEAKER_PONG;
1015}
1016
1017
1018/**
1019 * Checks if the debugger can wait for events or not.
1020 *
1021 * This function is only used by lazy, multiplexing debuggers. :-)
1022 *
1023 * @returns True if waitable.
1024 * @returns False if not waitable.
1025 * @param pVM VM handle.
1026 */
1027VMMR3DECL(bool) DBGFR3CanWait(PVM pVM)
1028{
1029 AssertReturn(pVM->dbgf.s.fAttached, false);
1030 return RTSemPongShouldWait(&pVM->dbgf.s.PingPong);
1031}
1032
1033
1034/**
1035 * Resumes VM execution.
1036 *
1037 * There is no receipt event on this command.
1038 *
1039 * @returns VBox status.
1040 * @param pVM VM handle.
1041 */
1042VMMR3DECL(int) DBGFR3Resume(PVM pVM)
1043{
1044 /*
1045 * Check state.
1046 */
1047 AssertReturn(pVM->dbgf.s.fAttached, VERR_DBGF_NOT_ATTACHED);
1048 AssertReturn(RTSemPongIsSpeaker(&pVM->dbgf.s.PingPong), VERR_SEM_OUT_OF_TURN);
1049
1050 /*
1051 * Send the ping back to the emulation thread telling it to run.
1052 */
1053 dbgfR3SetCmd(pVM, DBGFCMD_GO);
1054 int rc = RTSemPong(&pVM->dbgf.s.PingPong);
1055 AssertRC(rc);
1056
1057 return rc;
1058}
1059
1060
1061/**
1062 * Step Into.
1063 *
1064 * A single step event is generated from this command.
1065 * The current implementation is not reliable, so don't rely on the event coming.
1066 *
1067 * @returns VBox status.
1068 * @param pVM VM handle.
1069 * @param idCpu The ID of the CPU to single step on.
1070 */
1071VMMR3DECL(int) DBGFR3Step(PVM pVM, VMCPUID idCpu)
1072{
1073 /*
1074 * Check state.
1075 */
1076 AssertReturn(pVM->dbgf.s.fAttached, VERR_DBGF_NOT_ATTACHED);
1077 AssertReturn(RTSemPongIsSpeaker(&pVM->dbgf.s.PingPong), VERR_SEM_OUT_OF_TURN);
1078 AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_PARAMETER);
1079
1080 /*
1081 * Send the ping back to the emulation thread telling it to run.
1082 */
1083/** @todo SMP (idCpu) */
1084 dbgfR3SetCmd(pVM, DBGFCMD_SINGLE_STEP);
1085 int rc = RTSemPong(&pVM->dbgf.s.PingPong);
1086 AssertRC(rc);
1087 return rc;
1088}
1089
1090
1091/**
1092 * Call this to single step programmatically.
1093 *
1094 * You must pass down the return code to the EM loop! That's
1095 * where the actual single stepping take place (at least in the
1096 * current implementation).
1097 *
1098 * @returns VINF_EM_DBG_STEP
1099 *
1100 * @param pVCpu The virtual CPU handle.
1101 *
1102 * @thread VCpu EMT
1103 */
1104VMMR3DECL(int) DBGFR3PrgStep(PVMCPU pVCpu)
1105{
1106 VMCPU_ASSERT_EMT(pVCpu);
1107
1108 pVCpu->dbgf.s.fSingleSteppingRaw = true;
1109 return VINF_EM_DBG_STEP;
1110}
1111
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette