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