1 /** @file
2 
3 Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
4 SPDX-License-Identifier: BSD-2-Clause-Patent
5 
6 **/
7 
8 #include <Uefi.h>
9 #include "Edb.h"
10 
11 EFI_DEBUGGER_PRIVATE_DATA mDebuggerPrivate = {
12   EFI_DEBUGGER_SIGNATURE,                    // Signature
13   IsaEbc,                                    // Isa
14   (EBC_DEBUGGER_MAJOR_VERSION << 16) |
15     EBC_DEBUGGER_MINOR_VERSION,              // EfiDebuggerRevision
16   (VM_MAJOR_VERSION << 16) |
17     VM_MINOR_VERSION,                        // EbcVmRevision
18   {
19     EFI_DEBUGGER_CONFIGURATION_VERSION,
20     &mDebuggerPrivate,
21   },                                         // DebuggerConfiguration
22   NULL,                                      // DebugImageInfoTableHeader
23   NULL,                                      // Vol
24   NULL,                                      // PciRootBridgeIo
25   mDebuggerCommandSet,                       // DebuggerCommandSet
26   {0},                                       // DebuggerSymbolContext
27   0,                                         // DebuggerBreakpointCount
28   {{0}},                                     // DebuggerBreakpointContext
29   0,                                         // CallStackEntryCount
30   {{0}},                                     // CallStackEntry
31   0,                                         // TraceEntryCount
32   {{0}},                                     // TraceEntry
33   {0},                                       // StepContext
34   {0},                                       // GoTilContext
35   0,                                         // InstructionScope
36   EFI_DEBUG_DEFAULT_INSTRUCTION_NUMBER,      // InstructionNumber
37   EFI_DEBUG_FLAG_EBC_BOE | EFI_DEBUG_FLAG_EBC_BOT, // FeatureFlags
38   0,                                               // StatusFlags
39   FALSE,                                           // EnablePageBreak
40   NULL                                             // BreakEvent
41 };
42 
43 CHAR16 *mExceptionStr[] = {
44   L"EXCEPT_EBC_UNDEFINED",
45   L"EXCEPT_EBC_DIVIDE_ERROR",
46   L"EXCEPT_EBC_DEBUG",
47   L"EXCEPT_EBC_BREAKPOINT",
48   L"EXCEPT_EBC_OVERFLOW",
49   L"EXCEPT_EBC_INVALID_OPCODE",
50   L"EXCEPT_EBC_STACK_FAULT",
51   L"EXCEPT_EBC_ALIGNMENT_CHECK",
52   L"EXCEPT_EBC_INSTRUCTION_ENCODING",
53   L"EXCEPT_EBC_BAD_BREAK",
54   L"EXCEPT_EBC_SINGLE_STEP",
55 };
56 
57 /**
58 
59   Clear all the breakpoint.
60 
61   @param DebuggerPrivate    EBC Debugger private data structure
62   @param NeedRemove         Whether need to remove all the breakpoint
63 
64 **/
65 VOID
EdbClearAllBreakpoint(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN BOOLEAN NeedRemove)66 EdbClearAllBreakpoint (
67   IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
68   IN     BOOLEAN                   NeedRemove
69   )
70 {
71   UINTN    Index;
72 
73   //
74   // Patch all the breakpoint
75   //
76   for (Index = 0; (Index < DebuggerPrivate->DebuggerBreakpointCount) && (Index < EFI_DEBUGGER_BREAKPOINT_MAX); Index++) {
77     if (DebuggerPrivate->DebuggerBreakpointContext[Index].State) {
78       CopyMem (
79         (VOID *)(UINTN)DebuggerPrivate->DebuggerBreakpointContext[Index].BreakpointAddress,
80         &DebuggerPrivate->DebuggerBreakpointContext[Index].OldInstruction,
81         sizeof(UINT16)
82         );
83     }
84   }
85 
86   //
87   // Zero Breakpoint context, if need to remove all breakpoint
88   //
89   if (NeedRemove) {
90     DebuggerPrivate->DebuggerBreakpointCount = 0;
91     ZeroMem (DebuggerPrivate->DebuggerBreakpointContext, sizeof(DebuggerPrivate->DebuggerBreakpointContext));
92   }
93 
94   //
95   // Done
96   //
97   return ;
98 }
99 
100 /**
101 
102   Set all the breakpoint.
103 
104   @param DebuggerPrivate    EBC Debugger private data structure
105 
106 **/
107 VOID
EdbSetAllBreakpoint(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate)108 EdbSetAllBreakpoint (
109   IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate
110   )
111 {
112   UINTN    Index;
113   UINT16   Data16;
114 
115   //
116   // Set all the breakpoint (BREAK(3) : 0x0300)
117   //
118   Data16 = 0x0300;
119   for (Index = 0; (Index < DebuggerPrivate->DebuggerBreakpointCount) && (Index < EFI_DEBUGGER_BREAKPOINT_MAX); Index++) {
120     if (DebuggerPrivate->DebuggerBreakpointContext[Index].State) {
121       CopyMem (
122         (VOID *)(UINTN)DebuggerPrivate->DebuggerBreakpointContext[Index].BreakpointAddress,
123         &Data16,
124         sizeof(UINT16)
125         );
126     }
127   }
128 
129   //
130   // Check if current break is caused by breakpoint set.
131   // If so, we need to patch memory back to let user see the real memory.
132   //
133   if (DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX].BreakpointAddress != 0) {
134     CopyMem (
135       (VOID *)(UINTN)DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX].BreakpointAddress,
136       &DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX].OldInstruction,
137       sizeof(UINT16)
138       );
139     DebuggerPrivate->StatusFlags &= ~EFI_DEBUG_FLAG_EBC_B_BP;
140   }
141 
142   //
143   // Done
144   //
145   return ;
146 }
147 
148 /**
149 
150   Check all the breakpoint, if match, then set status flag, and record current breakpoint.
151   Then clear all breakpoint to let user see a clean memory
152 
153   @param   DebuggerPrivate    EBC Debugger private data structure
154   @param   SystemContext      EBC system context.
155 
156 **/
157 VOID
EdbCheckBreakpoint(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN EFI_SYSTEM_CONTEXT SystemContext)158 EdbCheckBreakpoint (
159   IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
160   IN     EFI_SYSTEM_CONTEXT        SystemContext
161   )
162 {
163   UINT64   Address;
164   UINTN    Index;
165   BOOLEAN  IsHitBreakpoint;
166 
167   //
168   // Roll back IP for breakpoint instruction (BREAK(3) : 0x0300)
169   //
170   Address = SystemContext.SystemContextEbc->Ip - sizeof(UINT16);
171 
172   //
173   // Check if the breakpoint is hit
174   //
175   IsHitBreakpoint = FALSE;
176   for (Index = 0; (Index < DebuggerPrivate->DebuggerBreakpointCount) && (Index < EFI_DEBUGGER_BREAKPOINT_MAX); Index++) {
177     if ((DebuggerPrivate->DebuggerBreakpointContext[Index].BreakpointAddress == Address) &&
178         (DebuggerPrivate->DebuggerBreakpointContext[Index].State)) {
179       IsHitBreakpoint = TRUE;
180       break;
181     }
182   }
183 
184   if (IsHitBreakpoint) {
185     //
186     // If hit, record current breakpoint
187     //
188     DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX] = DebuggerPrivate->DebuggerBreakpointContext[Index];
189     DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX].State = TRUE;
190     //
191     // Update: IP and Instruction (NOTE: Since we not allow set breakpoint to BREAK 3, this update is safe)
192     //
193     SystemContext.SystemContextEbc->Ip = Address;
194     //
195     // Set Flags
196     //
197     DebuggerPrivate->StatusFlags |= EFI_DEBUG_FLAG_EBC_BP;
198   } else {
199     //
200     // If not hit, check whether current IP is in breakpoint list,
201     // because STEP will be triggered before execute the instruction.
202     // We should not patch it in de-init.
203     //
204     Address = SystemContext.SystemContextEbc->Ip;
205 
206     //
207     // Check if the breakpoint is hit
208     //
209     IsHitBreakpoint = FALSE;
210     for (Index = 0; (Index < DebuggerPrivate->DebuggerBreakpointCount) && (Index < EFI_DEBUGGER_BREAKPOINT_MAX); Index++) {
211       if ((DebuggerPrivate->DebuggerBreakpointContext[Index].BreakpointAddress == Address) &&
212           (DebuggerPrivate->DebuggerBreakpointContext[Index].State)) {
213         IsHitBreakpoint = TRUE;
214         break;
215       }
216     }
217 
218     if (IsHitBreakpoint) {
219       //
220       // If hit, record current breakpoint
221       //
222       DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX] = DebuggerPrivate->DebuggerBreakpointContext[Index];
223       DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX].State = TRUE;
224       //
225       // Do not set Breakpoint flag. We record the address here just let it not patch breakpoint address when de-init.
226       //
227     } else {
228       //
229       // Zero current breakpoint
230       //
231       ZeroMem (
232         &DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX],
233         sizeof(DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX])
234         );
235     }
236   }
237 
238   //
239   // Done
240   //
241   return ;
242 }
243 
244 /**
245   clear all the symbol.
246 
247   @param DebuggerPrivate    EBC Debugger private data structure
248 
249 **/
250 VOID
EdbClearSymbol(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate)251 EdbClearSymbol (
252   IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate
253   )
254 {
255   EFI_DEBUGGER_SYMBOL_CONTEXT *DebuggerSymbolContext;
256   EFI_DEBUGGER_SYMBOL_OBJECT  *Object;
257   UINTN                       ObjectIndex;
258   UINTN                       Index;
259 
260   //
261   // Go throuth each object
262   //
263   DebuggerSymbolContext = &DebuggerPrivate->DebuggerSymbolContext;
264   for (ObjectIndex = 0; ObjectIndex < DebuggerSymbolContext->ObjectCount; ObjectIndex++) {
265     Object = &DebuggerSymbolContext->Object[ObjectIndex];
266     //
267     // Go throuth each entry
268     //
269     for (Index = 0; Index < Object->EntryCount; Index++) {
270       ZeroMem (&Object->Entry[Index], sizeof(Object->Entry[Index]));
271     }
272     ZeroMem (Object->Name, sizeof(Object->Name));
273     Object->EntryCount = 0;
274     Object->BaseAddress = 0;
275     Object->StartEntrypointRVA = 0;
276     Object->MainEntrypointRVA = 0;
277     //
278     // Free source buffer
279     //
280     for (Index = 0; Object->SourceBuffer[Index] != NULL; Index++) {
281       gBS->FreePool (Object->SourceBuffer[Index]);
282       Object->SourceBuffer[Index] = NULL;
283     }
284   }
285   DebuggerSymbolContext->ObjectCount = 0;
286 
287   return ;
288 }
289 
290 /**
291 
292   Initialize Debugger private data structure
293 
294   @param DebuggerPrivate   EBC Debugger private data structure
295   @param ExceptionType     Exception type.
296   @param SystemContext     EBC system context.
297   @param Initialized       Whether the DebuggerPrivate data is initialized.
298 
299 **/
300 EFI_STATUS
InitDebuggerPrivateData(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN EFI_EXCEPTION_TYPE ExceptionType,IN EFI_SYSTEM_CONTEXT SystemContext,IN BOOLEAN Initialized)301 InitDebuggerPrivateData (
302   IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
303   IN     EFI_EXCEPTION_TYPE        ExceptionType,
304   IN     EFI_SYSTEM_CONTEXT        SystemContext,
305   IN     BOOLEAN                   Initialized
306   )
307 {
308   //
309   // clear STEP flag in any condition.
310   //
311   if (SystemContext.SystemContextEbc->Flags & ((UINT64) VMFLAGS_STEP)) {
312     SystemContext.SystemContextEbc->Flags &= ~((UINT64) VMFLAGS_STEP);
313   }
314 
315   if (!Initialized) {
316     //
317     // Initialize everything
318     //
319     DebuggerPrivate->InstructionNumber = EFI_DEBUG_DEFAULT_INSTRUCTION_NUMBER;
320 
321     DebuggerPrivate->DebuggerBreakpointCount = 0;
322     ZeroMem (DebuggerPrivate->DebuggerBreakpointContext, sizeof(DebuggerPrivate->DebuggerBreakpointContext));
323 
324 //    DebuggerPrivate->StatusFlags = 0;
325 
326     DebuggerPrivate->DebuggerSymbolContext.DisplaySymbol = TRUE;
327     DebuggerPrivate->DebuggerSymbolContext.DisplayCodeOnly = FALSE;
328     DebuggerPrivate->DebuggerSymbolContext.ObjectCount = 0;
329   } else {
330     //
331     // Already initialized, just check Breakpoint here.
332     //
333     if (ExceptionType == EXCEPT_EBC_BREAKPOINT) {
334       EdbCheckBreakpoint (DebuggerPrivate, SystemContext);
335     }
336 
337     //
338     // Clear all breakpoint
339     //
340     EdbClearAllBreakpoint (DebuggerPrivate, FALSE);
341   }
342 
343   //
344   // Set Scope to currentl IP. (Note: Check Breakpoint may change Ip)
345   //
346   DebuggerPrivate->InstructionScope = SystemContext.SystemContextEbc->Ip;
347 
348   //
349   // Done
350   //
351   return EFI_SUCCESS;
352 }
353 
354 /**
355 
356   De-initialize Debugger private data structure.
357 
358   @param DebuggerPrivate   EBC Debugger private data structure
359   @param ExceptionType     Exception type.
360   @param SystemContext     EBC system context.
361   @param Initialized       Whether the DebuggerPrivate data is initialized.
362 
363 **/
364 EFI_STATUS
DeinitDebuggerPrivateData(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN EFI_EXCEPTION_TYPE ExceptionType,IN EFI_SYSTEM_CONTEXT SystemContext,IN BOOLEAN Initialized)365 DeinitDebuggerPrivateData (
366   IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
367   IN     EFI_EXCEPTION_TYPE        ExceptionType,
368   IN     EFI_SYSTEM_CONTEXT        SystemContext,
369   IN     BOOLEAN                   Initialized
370   )
371 {
372   if (!Initialized) {
373     //
374     // If it does not want initialized state, de-init everything
375     //
376     DebuggerPrivate->FeatureFlags = EFI_DEBUG_FLAG_EBC_BOE | EFI_DEBUG_FLAG_EBC_BOT;
377     DebuggerPrivate->CallStackEntryCount = 0;
378     DebuggerPrivate->TraceEntryCount = 0;
379     ZeroMem (DebuggerPrivate->CallStackEntry, sizeof(DebuggerPrivate->CallStackEntry));
380     ZeroMem (DebuggerPrivate->TraceEntry, sizeof(DebuggerPrivate->TraceEntry));
381 
382     //
383     // Clear all breakpoint
384     //
385     EdbClearAllBreakpoint (DebuggerPrivate, TRUE);
386 
387     //
388     // Clear symbol
389     //
390     EdbClearSymbol (DebuggerPrivate);
391   } else {
392     //
393     // If it wants to keep initialized state, just set breakpoint.
394     //
395     EdbSetAllBreakpoint (DebuggerPrivate);
396   }
397 
398   //
399   // Clear Step context
400   //
401   ZeroMem (&mDebuggerPrivate.StepContext, sizeof(mDebuggerPrivate.StepContext));
402   DebuggerPrivate->StatusFlags = 0;
403 
404   //
405   // Done
406   //
407   return EFI_SUCCESS;
408 }
409 
410 /**
411 
412   Print the reason of current break to EbcDebugger.
413 
414   @param DebuggerPrivate   EBC Debugger private data structure
415   @param ExceptionType     Exception type.
416   @param SystemContext     EBC system context.
417   @param Initialized       Whether the DebuggerPrivate data is initialized.
418 
419 **/
420 VOID
PrintExceptionReason(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN EFI_EXCEPTION_TYPE ExceptionType,IN EFI_SYSTEM_CONTEXT SystemContext,IN BOOLEAN Initialized)421 PrintExceptionReason (
422   IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
423   IN     EFI_EXCEPTION_TYPE        ExceptionType,
424   IN     EFI_SYSTEM_CONTEXT        SystemContext,
425   IN     BOOLEAN                   Initialized
426   )
427 {
428   //
429   // Print break status
430   //
431   if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_GT) == EFI_DEBUG_FLAG_EBC_GT) {
432     EDBPrint (L"Break on GoTil\n");
433   } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_BOC) == EFI_DEBUG_FLAG_EBC_BOC) {
434     EDBPrint (L"Break on CALL\n");
435   } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_BOCX) == EFI_DEBUG_FLAG_EBC_BOCX) {
436     EDBPrint (L"Break on CALLEX\n");
437   } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_BOR) == EFI_DEBUG_FLAG_EBC_BOR) {
438     EDBPrint (L"Break on RET\n");
439   } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_BOE) == EFI_DEBUG_FLAG_EBC_BOE) {
440     EDBPrint (L"Break on Entrypoint\n");
441   } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_BOT) == EFI_DEBUG_FLAG_EBC_BOT) {
442     EDBPrint (L"Break on Thunk\n");
443   } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_STEPOVER) == EFI_DEBUG_FLAG_EBC_STEPOVER) {
444     EDBPrint (L"Break on StepOver\n");
445   } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_STEPOUT) == EFI_DEBUG_FLAG_EBC_STEPOUT) {
446     EDBPrint (L"Break on StepOut\n");
447   } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_BP) == EFI_DEBUG_FLAG_EBC_BP) {
448     EDBPrint (L"Break on Breakpoint\n");
449   } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_BOK) == EFI_DEBUG_FLAG_EBC_BOK) {
450     EDBPrint (L"Break on Key\n");
451   } else {
452     EDBPrint (L"Exception Type - %x", (UINTN)ExceptionType);
453     if ((ExceptionType >= EXCEPT_EBC_UNDEFINED) && (ExceptionType <= EXCEPT_EBC_STEP)) {
454       EDBPrint (L" (%s)\n", mExceptionStr[ExceptionType]);
455     } else {
456       EDBPrint (L"\n");
457     }
458   }
459 
460   return ;
461 }
462 
463 /**
464 
465   The default Exception Callback for the VM interpreter.
466   In this function, we report status code, and print debug information
467   about EBC_CONTEXT, then dead loop.
468 
469   @param ExceptionType    Exception type.
470   @param SystemContext    EBC system context.
471 
472 **/
473 VOID
474 EFIAPI
EdbExceptionHandler(IN EFI_EXCEPTION_TYPE ExceptionType,IN OUT EFI_SYSTEM_CONTEXT SystemContext)475 EdbExceptionHandler (
476   IN     EFI_EXCEPTION_TYPE   ExceptionType,
477   IN OUT EFI_SYSTEM_CONTEXT   SystemContext
478   )
479 {
480   CHAR16                  InputBuffer[EFI_DEBUG_INPUS_BUFFER_SIZE];
481   CHAR16                  *CommandArg;
482   EFI_DEBUGGER_COMMAND    DebuggerCommand;
483   EFI_DEBUG_STATUS        DebugStatus;
484   STATIC BOOLEAN          mInitialized;
485 
486   mInitialized = FALSE;
487 
488   DEBUG ((DEBUG_ERROR, "Hello EBC Debugger!\n"));
489 
490   if (!mInitialized) {
491     //
492     // Print version
493     //
494     EDBPrint (
495       L"EBC Interpreter Version - %d.%d\n",
496       (UINTN)VM_MAJOR_VERSION,
497       (UINTN)VM_MINOR_VERSION
498       );
499     EDBPrint (
500       L"EBC Debugger Version - %d.%d\n",
501       (UINTN)EBC_DEBUGGER_MAJOR_VERSION,
502       (UINTN)EBC_DEBUGGER_MINOR_VERSION
503       );
504   }
505   //
506   // Init Private Data
507   //
508   InitDebuggerPrivateData (&mDebuggerPrivate, ExceptionType, SystemContext, mInitialized);
509 
510   //
511   // EDBPrint basic info
512   //
513   PrintExceptionReason (&mDebuggerPrivate, ExceptionType, SystemContext, mInitialized);
514 
515   EdbShowDisasm (&mDebuggerPrivate, SystemContext);
516   // EFI_BREAKPOINT ();
517 
518   if (!mInitialized) {
519     //
520     // Interactive with user
521     //
522     EDBPrint (L"\nPlease enter command now, \'h\' for help.\n");
523     EDBPrint (L"(Using <Command> -b <...> to enable page break.)\n");
524   }
525   mInitialized = TRUE;
526 
527   //
528   // Dispatch each command
529   //
530   while (TRUE) {
531     //
532     // Get user input
533     //
534     Input (L"\n\r" EFI_DEBUG_PROMPT_STRING, InputBuffer, EFI_DEBUG_INPUS_BUFFER_SIZE);
535     EDBPrint (L"\n");
536 
537     //
538     // Get command
539     //
540     DebuggerCommand = MatchDebuggerCommand (InputBuffer, &CommandArg);
541     if (DebuggerCommand == NULL) {
542       EDBPrint (L"ERROR: Command not found!\n");
543       continue;
544     }
545 
546     //
547     // Check PageBreak;
548     //
549     if (CommandArg != NULL) {
550       if (StriCmp (CommandArg, L"-b") == 0) {
551         CommandArg = StrGetNextTokenLine (L" ");
552         mDebuggerPrivate.EnablePageBreak = TRUE;
553       }
554     }
555 
556     //
557     // Dispatch command
558     //
559     DebugStatus = DebuggerCommand (CommandArg, &mDebuggerPrivate, ExceptionType, SystemContext);
560     mDebuggerPrivate.EnablePageBreak = FALSE;
561 
562     //
563     // Check command return status
564     //
565     if (DebugStatus == EFI_DEBUG_RETURN) {
566       mInitialized = FALSE;
567       break;
568     } else if (DebugStatus == EFI_DEBUG_BREAK) {
569       break;
570     } else if (DebugStatus == EFI_DEBUG_CONTINUE) {
571       continue;
572     } else {
573       ASSERT (FALSE);
574     }
575   }
576 
577   //
578   // Deinit Private Data
579   //
580   DeinitDebuggerPrivateData (&mDebuggerPrivate, ExceptionType, SystemContext, mInitialized);
581 
582   DEBUG ((DEBUG_ERROR, "Goodbye EBC Debugger!\n"));
583 
584   return;
585 }
586