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 
9 #include "Edb.h"
10 
11 /**
12 
13   Check the Hook flag, and trigger exception if match.
14 
15   @param  VmPtr        - EbcDebuggerCheckHookFlag
16   @param  Flag         - Feature flag
17 
18 **/
19 VOID
EbcDebuggerCheckHookFlag(IN VM_CONTEXT * VmPtr,IN UINT32 Flag)20 EbcDebuggerCheckHookFlag (
21   IN VM_CONTEXT *VmPtr,
22   IN UINT32     Flag
23   )
24 {
25   if ((mDebuggerPrivate.FeatureFlags & Flag) == Flag) {
26     mDebuggerPrivate.StatusFlags = Flag;
27     EbcDebugSignalException (
28       EXCEPT_EBC_BREAKPOINT,
29       EXCEPTION_FLAG_NONE,
30       VmPtr
31       );
32   }
33   return ;
34 }
35 
36 /**
37 
38   It will record soruce address for Callstack entry.
39 
40   @param  SourceEntry  - Source address
41   @param  Type         - Branch type
42 
43 **/
44 VOID
EbcDebuggerPushCallstackSource(IN UINT64 SourceEntry,IN EFI_DEBUGGER_BRANCH_TYPE Type)45 EbcDebuggerPushCallstackSource (
46   IN UINT64                   SourceEntry,
47   IN EFI_DEBUGGER_BRANCH_TYPE Type
48   )
49 {
50   if (mDebuggerPrivate.CallStackEntryCount > EFI_DEBUGGER_CALLSTACK_MAX) {
51     ASSERT (FALSE);
52     mDebuggerPrivate.CallStackEntryCount = EFI_DEBUGGER_CALLSTACK_MAX;
53   }
54   //
55   // Record the new callstack entry
56   //
57   mDebuggerPrivate.CallStackEntry[mDebuggerPrivate.CallStackEntryCount].SourceAddress = SourceEntry;
58   mDebuggerPrivate.CallStackEntry[mDebuggerPrivate.CallStackEntryCount].Type = Type;
59 
60   //
61   // Do not change CallStackEntryCount
62   //
63 
64   return ;
65 }
66 
67 /**
68 
69   It will record parameter for Callstack entry.
70 
71   @param  ParameterAddress - The address for the parameter
72   @param  Type             - Branch type
73 
74 **/
75 VOID
EbcDebuggerPushCallstackParameter(IN UINT64 ParameterAddress,IN EFI_DEBUGGER_BRANCH_TYPE Type)76 EbcDebuggerPushCallstackParameter (
77   IN UINT64                   ParameterAddress,
78   IN EFI_DEBUGGER_BRANCH_TYPE Type
79   )
80 {
81   if (mDebuggerPrivate.CallStackEntryCount > EFI_DEBUGGER_CALLSTACK_MAX) {
82     ASSERT (FALSE);
83     mDebuggerPrivate.CallStackEntryCount = EFI_DEBUGGER_CALLSTACK_MAX;
84   }
85   //
86   // Record the new callstack parameter
87   //
88   mDebuggerPrivate.CallStackEntry[mDebuggerPrivate.CallStackEntryCount].ParameterAddr = (UINTN)ParameterAddress;
89   CopyMem (
90     mDebuggerPrivate.CallStackEntry[mDebuggerPrivate.CallStackEntryCount].Parameter,
91     (VOID *)(UINTN)ParameterAddress,
92     sizeof(mDebuggerPrivate.CallStackEntry[mDebuggerPrivate.CallStackEntryCount].Parameter)
93     );
94 
95   //
96   // Do not change CallStackEntryCount
97   //
98 
99   return ;
100 }
101 
102 /**
103 
104   It will record source address for callstack entry.
105 
106   @param  DestEntry    - Source address
107   @param  Type         - Branch type
108 
109 **/
110 VOID
EbcDebuggerPushCallstackDest(IN UINT64 DestEntry,IN EFI_DEBUGGER_BRANCH_TYPE Type)111 EbcDebuggerPushCallstackDest (
112   IN UINT64                   DestEntry,
113   IN EFI_DEBUGGER_BRANCH_TYPE Type
114   )
115 {
116   UINTN Index;
117 
118   if (mDebuggerPrivate.CallStackEntryCount < EFI_DEBUGGER_CALLSTACK_MAX) {
119     //
120     // If there is empty entry for callstack, add it
121     //
122     ASSERT (mDebuggerPrivate.CallStackEntry[mDebuggerPrivate.CallStackEntryCount].Type == Type);
123     mDebuggerPrivate.CallStackEntry[mDebuggerPrivate.CallStackEntryCount].DestAddress = DestEntry;
124     mDebuggerPrivate.CallStackEntryCount ++;
125   } else {
126     //
127     // If there is no empty entry for callstack, throw the oldest one
128     //
129     ASSERT (mDebuggerPrivate.CallStackEntry[EFI_DEBUGGER_TRACE_MAX].Type == Type);
130     for (Index = 0; Index < EFI_DEBUGGER_CALLSTACK_MAX; Index++) {
131       CopyMem (&mDebuggerPrivate.CallStackEntry[Index],
132                &mDebuggerPrivate.CallStackEntry[Index + 1],
133                sizeof (mDebuggerPrivate.CallStackEntry[Index])
134                );
135     }
136     mDebuggerPrivate.CallStackEntry[EFI_DEBUGGER_CALLSTACK_MAX - 1].DestAddress = DestEntry;
137     mDebuggerPrivate.CallStackEntryCount = EFI_DEBUGGER_CALLSTACK_MAX;
138   }
139 
140   return ;
141 }
142 
143 /**
144 
145   It will throw the newest Callstack entry.
146 
147 **/
148 VOID
EbcDebuggerPopCallstack(VOID)149 EbcDebuggerPopCallstack (
150   VOID
151   )
152 {
153   if ((mDebuggerPrivate.CallStackEntryCount > 0) &&
154       (mDebuggerPrivate.CallStackEntryCount <= EFI_DEBUGGER_CALLSTACK_MAX)) {
155     //
156     // Throw the newest one
157     //
158     mDebuggerPrivate.CallStackEntryCount --;
159     mDebuggerPrivate.CallStackEntry[mDebuggerPrivate.CallStackEntryCount].SourceAddress = 0;
160     mDebuggerPrivate.CallStackEntry[mDebuggerPrivate.CallStackEntryCount].DestAddress = 0;
161   } else if (mDebuggerPrivate.CallStackEntryCount == 0) {
162     //
163     // NOT assert here because it is reasonable, because when we start to build
164     // callstack, we do not know how many function already called.
165     //
166   } else {
167     ASSERT (FALSE);
168   }
169 
170   return ;
171 }
172 
173 /**
174 
175   It will record source address for trace entry.
176 
177   @param  SourceEntry  - Source address
178   @param  Type         - Branch type
179 
180 **/
181 VOID
EbcDebuggerPushTraceSourceEntry(IN UINT64 SourceEntry,IN EFI_DEBUGGER_BRANCH_TYPE Type)182 EbcDebuggerPushTraceSourceEntry (
183   IN UINT64                   SourceEntry,
184   IN EFI_DEBUGGER_BRANCH_TYPE Type
185   )
186 {
187   if (mDebuggerPrivate.TraceEntryCount > EFI_DEBUGGER_TRACE_MAX) {
188     ASSERT (FALSE);
189     mDebuggerPrivate.TraceEntryCount = EFI_DEBUGGER_TRACE_MAX;
190   }
191   //
192   // Record the new trace entry
193   //
194   mDebuggerPrivate.TraceEntry[mDebuggerPrivate.TraceEntryCount].SourceAddress = SourceEntry;
195   mDebuggerPrivate.TraceEntry[mDebuggerPrivate.TraceEntryCount].Type = Type;
196 
197   //
198   // Do not change TraceEntryCount
199   //
200 
201   return ;
202 }
203 
204 /**
205 
206   It will record destination address for trace entry.
207 
208   @param  DestEntry    - Destination address
209   @param  Type         - Branch type
210 
211 **/
212 VOID
EbcDebuggerPushTraceDestEntry(IN UINT64 DestEntry,IN EFI_DEBUGGER_BRANCH_TYPE Type)213 EbcDebuggerPushTraceDestEntry (
214   IN UINT64                   DestEntry,
215   IN EFI_DEBUGGER_BRANCH_TYPE Type
216   )
217 {
218   UINTN Index;
219 
220   if (mDebuggerPrivate.TraceEntryCount < EFI_DEBUGGER_TRACE_MAX) {
221     //
222     // If there is empty entry for trace, add it
223     //
224     ASSERT (mDebuggerPrivate.TraceEntry[mDebuggerPrivate.TraceEntryCount].Type == Type);
225     mDebuggerPrivate.TraceEntry[mDebuggerPrivate.TraceEntryCount].DestAddress = DestEntry;
226     mDebuggerPrivate.TraceEntryCount ++;
227   } else {
228     //
229     // If there is no empty entry for trace, throw the oldest one
230     //
231     ASSERT (mDebuggerPrivate.TraceEntry[EFI_DEBUGGER_TRACE_MAX].Type == Type);
232     for (Index = 0; Index < EFI_DEBUGGER_TRACE_MAX; Index++) {
233       mDebuggerPrivate.TraceEntry[Index] = mDebuggerPrivate.TraceEntry[Index + 1];
234     }
235     mDebuggerPrivate.TraceEntry[EFI_DEBUGGER_CALLSTACK_MAX - 1].DestAddress = DestEntry;
236     mDebuggerPrivate.TraceEntryCount = EFI_DEBUGGER_TRACE_MAX;
237   }
238 
239   return ;
240 }
241 
242 /**
243 
244   It will record address for StepEntry, if STEPOVER or STEPOUT is enabled.
245 
246   @param  Entry    - Break Address
247   @param  FramePtr - Break Frame pointer
248   @param  Flag     - for STEPOVER or STEPOUT
249 
250 **/
251 VOID
EbcDebuggerPushStepEntry(IN UINT64 Entry,IN UINT64 FramePtr,IN UINT32 Flag)252 EbcDebuggerPushStepEntry (
253   IN UINT64                   Entry,
254   IN UINT64                   FramePtr,
255   IN UINT32                   Flag
256   )
257 {
258   //
259   // Check StepOver
260   //
261   if ((Flag == EFI_DEBUG_FLAG_EBC_STEPOVER) &&
262       ((mDebuggerPrivate.FeatureFlags & EFI_DEBUG_FLAG_EBC_STEPOVER) == EFI_DEBUG_FLAG_EBC_STEPOVER)) {
263     mDebuggerPrivate.StepContext.BreakAddress = Entry;
264     mDebuggerPrivate.StepContext.FramePointer = FramePtr;
265     mDebuggerPrivate.FeatureFlags &= ~EFI_DEBUG_FLAG_EBC_B_STEPOVER;
266   }
267   //
268   // Check StepOut
269   //
270   if ((Flag == EFI_DEBUG_FLAG_EBC_STEPOUT) &&
271       ((mDebuggerPrivate.FeatureFlags & EFI_DEBUG_FLAG_EBC_STEPOUT) == EFI_DEBUG_FLAG_EBC_STEPOUT)) {
272     mDebuggerPrivate.StepContext.BreakAddress = Entry;
273     mDebuggerPrivate.StepContext.FramePointer = FramePtr;
274     mDebuggerPrivate.FeatureFlags &= ~EFI_DEBUG_FLAG_EBC_B_STEPOUT;
275   }
276 }
277 
278 
279 /**
280   Notify the callback function when an event is triggered.
281 
282   @param  Event                    Indicates the event that invoke this function.
283   @param  Context                  Indicates the calling context.
284 
285 **/
286 VOID
287 EFIAPI
EbcDebuggerBreakEventFunc(IN EFI_EVENT Event,IN VOID * Context)288 EbcDebuggerBreakEventFunc (
289   IN EFI_EVENT                Event,
290   IN VOID                     *Context
291   )
292 {
293   EFI_STATUS  Status;
294 
295   if ((mDebuggerPrivate.FeatureFlags & EFI_DEBUG_FLAG_EBC_BOK) != EFI_DEBUG_FLAG_EBC_BOK) {
296     return ;
297   }
298 
299   Status = gBS->CheckEvent (gST->ConIn->WaitForKey);
300   if (Status == EFI_SUCCESS) {
301     mDebuggerPrivate.StatusFlags = EFI_DEBUG_FLAG_EBC_BOK;
302   }
303 }
304 
305 /**
306 
307   The hook in InitializeEbcDriver.
308   It will init the EbcDebuggerPrivate data structure.
309 
310   @param Handle           - The EbcDebugProtocol handle.
311   @param EbcDebugProtocol - The EbcDebugProtocol interface.
312 
313 **/
314 VOID
EbcDebuggerHookInit(IN EFI_HANDLE Handle,IN EFI_DEBUG_SUPPORT_PROTOCOL * EbcDebugProtocol)315 EbcDebuggerHookInit (
316   IN EFI_HANDLE                  Handle,
317   IN EFI_DEBUG_SUPPORT_PROTOCOL  *EbcDebugProtocol
318   )
319 {
320   EFI_STATUS                 Status;
321   UINTN                      Index;
322   EFI_DEBUGGER_SYMBOL_OBJECT *Object;
323   EFI_DEBUGGER_SYMBOL_ENTRY  *Entry;
324 
325 
326   //
327   // Register all exception handler
328   //
329   for (Index = EXCEPT_EBC_UNDEFINED; Index <= EXCEPT_EBC_STEP; Index++) {
330     EbcDebugProtocol->RegisterExceptionCallback (
331       EbcDebugProtocol,
332       0,
333       NULL,
334       Index
335       );
336     EbcDebugProtocol->RegisterExceptionCallback (
337       EbcDebugProtocol,
338       0,
339       EdbExceptionHandler,
340       Index
341       );
342   }
343 
344   //
345   // Init Symbol
346   //
347   Object = AllocateZeroPool (sizeof(EFI_DEBUGGER_SYMBOL_OBJECT) * EFI_DEBUGGER_SYMBOL_OBJECT_MAX);
348   ASSERT (Object != NULL);
349   mDebuggerPrivate.DebuggerSymbolContext.Object = Object;
350   mDebuggerPrivate.DebuggerSymbolContext.ObjectCount = 0;
351   mDebuggerPrivate.DebuggerSymbolContext.MaxObjectCount = EFI_DEBUGGER_SYMBOL_OBJECT_MAX;
352   for (Index = 0; Index < EFI_DEBUGGER_SYMBOL_OBJECT_MAX; Index++) {
353     Entry = AllocateZeroPool (sizeof(EFI_DEBUGGER_SYMBOL_ENTRY) * EFI_DEBUGGER_SYMBOL_ENTRY_MAX);
354     ASSERT (Entry != NULL);
355     Object[Index].Entry = Entry;
356     Object[Index].MaxEntryCount = EFI_DEBUGGER_SYMBOL_ENTRY_MAX;
357     Object[Index].SourceBuffer = AllocateZeroPool (sizeof(VOID *) * (EFI_DEBUGGER_SYMBOL_ENTRY_MAX + 1));
358     ASSERT (Object[Index].SourceBuffer != NULL);
359   }
360 
361   //
362   // locate PciRootBridgeIo
363   //
364   Status = gBS->LocateProtocol (
365                   &gEfiPciRootBridgeIoProtocolGuid,
366                   NULL,
367                   (VOID**) &mDebuggerPrivate.PciRootBridgeIo
368                   );
369 
370   //
371   // locate DebugImageInfoTable
372   //
373   Status = EfiGetSystemConfigurationTable (
374              &gEfiDebugImageInfoTableGuid,
375              (VOID**) &mDebuggerPrivate.DebugImageInfoTableHeader
376              );
377 
378   //
379   // Register Debugger Configuration Protocol, for config in shell
380   //
381   Status = gBS->InstallProtocolInterface (
382                   &Handle,
383                   &gEfiDebuggerConfigurationProtocolGuid,
384                   EFI_NATIVE_INTERFACE,
385                   &mDebuggerPrivate.DebuggerConfiguration
386                   );
387 
388   //
389   //
390   // Create break event
391   //
392   Status = gBS->CreateEvent (
393                   EVT_TIMER | EVT_NOTIFY_SIGNAL,
394                   TPL_CALLBACK,
395                   EbcDebuggerBreakEventFunc,
396                   NULL,
397                   &mDebuggerPrivate.BreakEvent
398                   );
399   if (!EFI_ERROR (Status)) {
400     Status = gBS->SetTimer (
401                     mDebuggerPrivate.BreakEvent,
402                     TimerPeriodic,
403                     EFI_DEBUG_BREAK_TIMER_INTERVAL
404                     );
405   }
406 
407   return ;
408 }
409 
410 /**
411 
412   The hook in UnloadImage for EBC Interpreter.
413   It clean up the environment.
414 
415 **/
416 VOID
EbcDebuggerHookUnload(VOID)417 EbcDebuggerHookUnload (
418   VOID
419   )
420 {
421   UINTN                      Index;
422   UINTN                      SubIndex;
423   EFI_DEBUGGER_SYMBOL_OBJECT *Object;
424 
425   //
426   // Close the break event
427   //
428   if (mDebuggerPrivate.BreakEvent != NULL) {
429     gBS->CloseEvent (mDebuggerPrivate.BreakEvent);
430   }
431 
432   //
433   // Clean up the symbol
434   //
435   Object = mDebuggerPrivate.DebuggerSymbolContext.Object;
436   for (Index = 0; Index < EFI_DEBUGGER_SYMBOL_OBJECT_MAX; Index++) {
437     //
438     // Clean up Entry
439     //
440     gBS->FreePool (Object[Index].Entry);
441     Object[Index].Entry = NULL;
442     Object[Index].EntryCount = 0;
443     //
444     // Clean up source buffer
445     //
446     for (SubIndex = 0; Object[Index].SourceBuffer[SubIndex] != NULL; SubIndex++) {
447       gBS->FreePool (Object[Index].SourceBuffer[SubIndex]);
448       Object[Index].SourceBuffer[SubIndex] = NULL;
449     }
450     gBS->FreePool (Object[Index].SourceBuffer);
451     Object[Index].SourceBuffer = NULL;
452   }
453 
454   //
455   // Clean up Object
456   //
457   gBS->FreePool (Object);
458   mDebuggerPrivate.DebuggerSymbolContext.Object = NULL;
459   mDebuggerPrivate.DebuggerSymbolContext.ObjectCount = 0;
460 
461   //
462   // Done
463   //
464   return ;
465 }
466 
467 /**
468 
469   The hook in EbcUnloadImage.
470   Currently do nothing here.
471 
472   @param  Handle           - The EbcImage handle.
473 
474 **/
475 VOID
EbcDebuggerHookEbcUnloadImage(IN EFI_HANDLE Handle)476 EbcDebuggerHookEbcUnloadImage (
477   IN EFI_HANDLE                  Handle
478   )
479 {
480   return ;
481 }
482 
483 /**
484 
485   The hook in ExecuteEbcImageEntryPoint.
486   It will record the call-stack entry. (-1 means EbcImageEntryPoint call)
487   and trigger Exception if BOE enabled.
488 
489 
490   @param  VmPtr - pointer to VM context.
491 
492 **/
493 VOID
EbcDebuggerHookExecuteEbcImageEntryPoint(IN VM_CONTEXT * VmPtr)494 EbcDebuggerHookExecuteEbcImageEntryPoint (
495   IN VM_CONTEXT *VmPtr
496   )
497 {
498   EbcDebuggerPushCallstackSource ((UINT64)(UINTN)-1, EfiDebuggerBranchTypeEbcCall);
499   EbcDebuggerPushCallstackParameter ((UINT64)(UINTN)VmPtr->Gpr[0], EfiDebuggerBranchTypeEbcCall);
500   EbcDebuggerPushCallstackDest ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCall);
501   EbcDebuggerCheckHookFlag (VmPtr, EFI_DEBUG_FLAG_EBC_BOE);
502   return ;
503 }
504 
505 /**
506 
507   The hook in ExecuteEbcImageEntryPoint.
508   It will record the call-stack entry. (-2 means EbcInterpret call)
509   and trigger Exception if BOT enabled.
510 
511   @param  VmPtr - pointer to VM context.
512 
513 **/
514 VOID
EbcDebuggerHookEbcInterpret(IN VM_CONTEXT * VmPtr)515 EbcDebuggerHookEbcInterpret (
516   IN VM_CONTEXT *VmPtr
517   )
518 {
519   EbcDebuggerPushCallstackSource ((UINT64)(UINTN)-2, EfiDebuggerBranchTypeEbcCall);
520   EbcDebuggerPushCallstackParameter ((UINT64)(UINTN)VmPtr->Gpr[0], EfiDebuggerBranchTypeEbcCall);
521   EbcDebuggerPushCallstackDest ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCall);
522   EbcDebuggerCheckHookFlag (VmPtr, EFI_DEBUG_FLAG_EBC_BOT);
523   return ;
524 }
525 
526 /**
527 
528   The hook in EbcExecute, before ExecuteFunction.
529   It will trigger Exception if GoTil, StepOver, or StepOut hit.
530 
531   @param  VmPtr - pointer to VM context.
532 
533 **/
534 VOID
EbcDebuggerHookExecuteStart(IN VM_CONTEXT * VmPtr)535 EbcDebuggerHookExecuteStart (
536   IN VM_CONTEXT *VmPtr
537   )
538 {
539   EFI_TPL   CurrentTpl;
540 
541   //
542   // Check Ip for GoTil
543   //
544   if (mDebuggerPrivate.GoTilContext.BreakAddress == (UINT64)(UINTN)VmPtr->Ip) {
545     mDebuggerPrivate.StatusFlags = EFI_DEBUG_FLAG_EBC_GT;
546     mDebuggerPrivate.GoTilContext.BreakAddress = 0;
547     EbcDebugSignalException (
548       EXCEPT_EBC_BREAKPOINT,
549       EXCEPTION_FLAG_NONE,
550       VmPtr
551       );
552     mDebuggerPrivate.StatusFlags &= ~EFI_DEBUG_FLAG_EBC_B_GT;
553     return ;
554   }
555   //
556   // Check ReturnAddress for StepOver
557   //
558   if ((mDebuggerPrivate.StepContext.BreakAddress == (UINT64)(UINTN)VmPtr->Ip) &&
559       (mDebuggerPrivate.StepContext.FramePointer == (UINT64)(UINTN)VmPtr->FramePtr)) {
560     mDebuggerPrivate.StatusFlags = EFI_DEBUG_FLAG_EBC_STEPOVER;
561     mDebuggerPrivate.StepContext.BreakAddress = 0;
562     mDebuggerPrivate.StepContext.FramePointer = 0;
563     EbcDebugSignalException (
564       EXCEPT_EBC_BREAKPOINT,
565       EXCEPTION_FLAG_NONE,
566       VmPtr
567       );
568     mDebuggerPrivate.StatusFlags &= ~EFI_DEBUG_FLAG_EBC_B_STEPOVER;
569   }
570   //
571   // Check FramePtr for StepOut
572   //
573   if (mDebuggerPrivate.StepContext.BreakAddress == (UINT64)(UINTN)VmPtr->FramePtr) {
574     mDebuggerPrivate.StatusFlags = EFI_DEBUG_FLAG_EBC_STEPOUT;
575     mDebuggerPrivate.StepContext.BreakAddress = 0;
576     mDebuggerPrivate.StepContext.FramePointer = 0;
577     EbcDebugSignalException (
578       EXCEPT_EBC_BREAKPOINT,
579       EXCEPTION_FLAG_NONE,
580       VmPtr
581       );
582     mDebuggerPrivate.StatusFlags &= ~EFI_DEBUG_FLAG_EBC_B_STEPOUT;
583   }
584   //
585   // Check Flags for BreakOnKey
586   //
587   if (mDebuggerPrivate.StatusFlags == EFI_DEBUG_FLAG_EBC_BOK) {
588     //
589     // Only break when the current TPL <= TPL_APPLICATION
590     //
591     CurrentTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
592     gBS->RestoreTPL (CurrentTpl);
593     if (CurrentTpl <= TPL_APPLICATION) {
594       EbcDebugSignalException (
595         EXCEPT_EBC_BREAKPOINT,
596         EXCEPTION_FLAG_NONE,
597         VmPtr
598         );
599       mDebuggerPrivate.StatusFlags &= ~EFI_DEBUG_FLAG_EBC_B_BOK;
600     }
601   }
602   return ;
603 }
604 
605 /**
606 
607   The hook in EbcExecute, after ExecuteFunction.
608   It will record StepOut Entry if need.
609 
610   @param  VmPtr - pointer to VM context.
611 
612 **/
613 VOID
EbcDebuggerHookExecuteEnd(IN VM_CONTEXT * VmPtr)614 EbcDebuggerHookExecuteEnd (
615   IN VM_CONTEXT *VmPtr
616   )
617 {
618   UINTN  Address;
619 
620   //
621   // Use FramePtr as checkpoint for StepOut
622   //
623   CopyMem (&Address, (VOID *)((UINTN)VmPtr->FramePtr), sizeof(Address));
624   EbcDebuggerPushStepEntry (Address, (UINT64)(UINTN)VmPtr->FramePtr, EFI_DEBUG_FLAG_EBC_STEPOUT);
625 
626   return ;
627 }
628 
629 /**
630 
631   The hook in ExecuteCALL, before move IP.
632   It will trigger Exception if BOC enabled,
633   and record Callstack, and trace information.
634 
635   @param  VmPtr - pointer to VM context.
636 
637 **/
638 VOID
EbcDebuggerHookCALLStart(IN VM_CONTEXT * VmPtr)639 EbcDebuggerHookCALLStart (
640   IN VM_CONTEXT *VmPtr
641   )
642 {
643   EbcDebuggerCheckHookFlag (VmPtr, EFI_DEBUG_FLAG_EBC_BOC);
644   EbcDebuggerPushCallstackSource ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCall);
645   EbcDebuggerPushCallstackParameter ((UINT64)(UINTN)VmPtr->Gpr[0], EfiDebuggerBranchTypeEbcCall);
646   EbcDebuggerPushTraceSourceEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCall);
647   return ;
648 }
649 
650 /**
651 
652   The hook in ExecuteCALL, after move IP.
653   It will record Callstack, trace information
654   and record StepOver/StepOut Entry if need.
655 
656   @param  VmPtr - pointer to VM context.
657 
658 **/
659 VOID
EbcDebuggerHookCALLEnd(IN VM_CONTEXT * VmPtr)660 EbcDebuggerHookCALLEnd (
661   IN VM_CONTEXT *VmPtr
662   )
663 {
664   UINT64  Address;
665   UINTN   FramePtr;
666 
667   EbcDebuggerPushCallstackDest ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCall);
668   EbcDebuggerPushTraceDestEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCall);
669 
670   //
671   // Get Old FramePtr
672   //
673   CopyMem (&FramePtr, (VOID *)((UINTN)VmPtr->FramePtr), sizeof(FramePtr));
674 
675   //
676   // Use ReturnAddress as checkpoint for StepOver
677   //
678   CopyMem (&Address, (VOID *)(UINTN)VmPtr->Gpr[0], sizeof(Address));
679   EbcDebuggerPushStepEntry (Address, FramePtr, EFI_DEBUG_FLAG_EBC_STEPOVER);
680 
681   //
682   // Use FramePtr as checkpoint for StepOut
683   //
684   Address = 0;
685   CopyMem (&Address, (VOID *)(FramePtr), sizeof(UINTN));
686   EbcDebuggerPushStepEntry (Address, FramePtr, EFI_DEBUG_FLAG_EBC_STEPOUT);
687 
688   return ;
689 }
690 
691 /**
692 
693   The hook in ExecuteCALL, before call EbcLLCALLEX.
694   It will trigger Exception if BOCX enabled,
695   and record Callstack information.
696 
697   @param  VmPtr - pointer to VM context.
698 
699 **/
700 VOID
EbcDebuggerHookCALLEXStart(IN VM_CONTEXT * VmPtr)701 EbcDebuggerHookCALLEXStart (
702   IN VM_CONTEXT *VmPtr
703   )
704 {
705   EbcDebuggerCheckHookFlag (VmPtr, EFI_DEBUG_FLAG_EBC_BOCX);
706 //  EbcDebuggerPushCallstackSource ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCallEx);
707 //  EbcDebuggerPushCallstackParameter ((UINT64)(UINTN)VmPtr->R[0], EfiDebuggerBranchTypeEbcCallEx);
708   EbcDebuggerPushTraceSourceEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCallEx);
709   return ;
710 }
711 
712 /**
713 
714   The hook in ExecuteCALL, after call EbcLLCALLEX.
715   It will record trace information.
716 
717   @param  VmPtr - pointer to VM context.
718 
719 **/
720 VOID
EbcDebuggerHookCALLEXEnd(IN VM_CONTEXT * VmPtr)721 EbcDebuggerHookCALLEXEnd (
722   IN VM_CONTEXT *VmPtr
723   )
724 {
725 //  EbcDebuggerPushCallstackDest ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCallEx);
726   EbcDebuggerPushTraceDestEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCallEx);
727   return ;
728 }
729 
730 /**
731 
732   The hook in ExecuteRET, before move IP.
733   It will trigger Exception if BOR enabled,
734   and record Callstack, and trace information.
735 
736   @param  VmPtr - pointer to VM context.
737 
738 **/
739 VOID
EbcDebuggerHookRETStart(IN VM_CONTEXT * VmPtr)740 EbcDebuggerHookRETStart (
741   IN VM_CONTEXT *VmPtr
742   )
743 {
744   EbcDebuggerCheckHookFlag (VmPtr, EFI_DEBUG_FLAG_EBC_BOR);
745   EbcDebuggerPopCallstack ();
746   EbcDebuggerPushTraceSourceEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcRet);
747   return ;
748 }
749 
750 /**
751 
752   The hook in ExecuteRET, after move IP.
753   It will record trace information.
754 
755   @param  VmPtr - pointer to VM context.
756 
757 **/
758 VOID
EbcDebuggerHookRETEnd(IN VM_CONTEXT * VmPtr)759 EbcDebuggerHookRETEnd (
760   IN VM_CONTEXT *VmPtr
761   )
762 {
763   EbcDebuggerPushTraceDestEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcRet);
764   return ;
765 }
766 
767 /**
768 
769   The hook in ExecuteJMP, before move IP.
770   It will record trace information.
771 
772   @param  VmPtr - pointer to VM context.
773 
774 **/
775 VOID
EbcDebuggerHookJMPStart(IN VM_CONTEXT * VmPtr)776 EbcDebuggerHookJMPStart (
777   IN VM_CONTEXT *VmPtr
778   )
779 {
780   EbcDebuggerPushTraceSourceEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcJmp);
781   return ;
782 }
783 
784 /**
785 
786   The hook in ExecuteJMP, after move IP.
787   It will record trace information.
788 
789   @param  VmPtr - pointer to VM context.
790 
791 **/
792 VOID
EbcDebuggerHookJMPEnd(IN VM_CONTEXT * VmPtr)793 EbcDebuggerHookJMPEnd (
794   IN VM_CONTEXT *VmPtr
795   )
796 {
797   EbcDebuggerPushTraceDestEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcJmp);
798   return ;
799 }
800 
801 /**
802 
803   The hook in ExecuteJMP8, before move IP.
804   It will record trace information.
805 
806   @param  VmPtr - pointer to VM context.
807 
808 **/
809 VOID
EbcDebuggerHookJMP8Start(IN VM_CONTEXT * VmPtr)810 EbcDebuggerHookJMP8Start (
811   IN VM_CONTEXT *VmPtr
812   )
813 {
814   EbcDebuggerPushTraceSourceEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcJmp8);
815   return ;
816 }
817 
818 /**
819 
820   The hook in ExecuteJMP8, after move IP.
821   It will record trace information.
822 
823   @param  VmPtr - pointer to VM context.
824 
825 **/
826 VOID
EbcDebuggerHookJMP8End(IN VM_CONTEXT * VmPtr)827 EbcDebuggerHookJMP8End (
828   IN VM_CONTEXT *VmPtr
829   )
830 {
831   EbcDebuggerPushTraceDestEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcJmp8);
832   return ;
833 }
834