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