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