]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbHook.c
MdeModulePkg: Fix GCC build failure
[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 if (!EFI_ERROR (Status)) {
461 Status = gBS->SetTimer (
462 mDebuggerPrivate.BreakEvent,
463 TimerPeriodic,
464 EFI_DEBUG_BREAK_TIMER_INTERVAL
465 );
466 }
467
468 return ;
469 }
470
471 VOID
472 EbcDebuggerHookUnload (
473 VOID
474 )
475 /*++
476
477 Routine Description:
478
479 The hook in UnloadImage for EBC Interpreter.
480 It clean up the environment.
481
482 Arguments:
483
484 None
485
486 Returns:
487 None
488
489 --*/
490 {
491 UINTN Index;
492 UINTN SubIndex;
493 EFI_DEBUGGER_SYMBOL_OBJECT *Object;
494
495 //
496 // Close the break event
497 //
498 if (mDebuggerPrivate.BreakEvent != NULL) {
499 gBS->CloseEvent (mDebuggerPrivate.BreakEvent);
500 }
501
502 //
503 // Clean up the symbol
504 //
505 Object = mDebuggerPrivate.DebuggerSymbolContext.Object;
506 for (Index = 0; Index < EFI_DEBUGGER_SYMBOL_OBJECT_MAX; Index++) {
507 //
508 // Clean up Entry
509 //
510 gBS->FreePool (Object[Index].Entry);
511 Object[Index].Entry = NULL;
512 Object[Index].EntryCount = 0;
513 //
514 // Clean up source buffer
515 //
516 for (SubIndex = 0; Object[Index].SourceBuffer[SubIndex] != NULL; SubIndex++) {
517 gBS->FreePool (Object[Index].SourceBuffer[SubIndex]);
518 Object[Index].SourceBuffer[SubIndex] = NULL;
519 }
520 gBS->FreePool (Object[Index].SourceBuffer);
521 Object[Index].SourceBuffer = NULL;
522 }
523
524 //
525 // Clean up Object
526 //
527 gBS->FreePool (Object);
528 mDebuggerPrivate.DebuggerSymbolContext.Object = NULL;
529 mDebuggerPrivate.DebuggerSymbolContext.ObjectCount = 0;
530
531 //
532 // Done
533 //
534 return ;
535 }
536
537 VOID
538 EbcDebuggerHookEbcUnloadImage (
539 IN EFI_HANDLE Handle
540 )
541 /*++
542
543 Routine Description:
544
545 The hook in EbcUnloadImage.
546 Currently do nothing here.
547
548 Arguments:
549
550 Handle - The EbcImage handle.
551
552 Returns:
553 None
554
555 --*/
556 {
557 return ;
558 }
559
560 VOID
561 EbcDebuggerHookExecuteEbcImageEntryPoint (
562 IN VM_CONTEXT *VmPtr
563 )
564 /*++
565
566 Routine Description:
567
568 The hook in ExecuteEbcImageEntryPoint.
569 It will record the call-stack entry. (-1 means EbcImageEntryPoint call)
570 and trigger Exception if BOE enabled.
571
572 Arguments:
573
574 VmPtr - pointer to VM context.
575
576 Returns:
577 None
578
579 --*/
580 {
581 EbcDebuggerPushCallstackSource ((UINT64)(UINTN)-1, EfiDebuggerBranchTypeEbcCall);
582 EbcDebuggerPushCallstackParameter ((UINT64)(UINTN)VmPtr->Gpr[0], EfiDebuggerBranchTypeEbcCall);
583 EbcDebuggerPushCallstackDest ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCall);
584 EbcDebuggerCheckHookFlag (VmPtr, EFI_DEBUG_FLAG_EBC_BOE);
585 return ;
586 }
587
588 VOID
589 EbcDebuggerHookEbcInterpret (
590 IN VM_CONTEXT *VmPtr
591 )
592 /*++
593
594 Routine Description:
595
596 The hook in ExecuteEbcImageEntryPoint.
597 It will record the call-stack entry. (-2 means EbcInterpret call)
598 and trigger Exception if BOT enabled.
599
600 Arguments:
601
602 VmPtr - pointer to VM context.
603
604 Returns:
605 None
606
607 --*/
608 {
609 EbcDebuggerPushCallstackSource ((UINT64)(UINTN)-2, EfiDebuggerBranchTypeEbcCall);
610 EbcDebuggerPushCallstackParameter ((UINT64)(UINTN)VmPtr->Gpr[0], EfiDebuggerBranchTypeEbcCall);
611 EbcDebuggerPushCallstackDest ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCall);
612 EbcDebuggerCheckHookFlag (VmPtr, EFI_DEBUG_FLAG_EBC_BOT);
613 return ;
614 }
615
616 VOID
617 EbcDebuggerHookExecuteStart (
618 IN VM_CONTEXT *VmPtr
619 )
620 /*++
621
622 Routine Description:
623
624 The hook in EbcExecute, before ExecuteFunction.
625 It will trigger Exception if GoTil, StepOver, or StepOut hit.
626
627 Arguments:
628
629 VmPtr - pointer to VM context.
630
631 Returns:
632 None
633
634 --*/
635 {
636 EFI_TPL CurrentTpl;
637
638 //
639 // Check Ip for GoTil
640 //
641 if (mDebuggerPrivate.GoTilContext.BreakAddress == (UINT64)(UINTN)VmPtr->Ip) {
642 mDebuggerPrivate.StatusFlags = EFI_DEBUG_FLAG_EBC_GT;
643 mDebuggerPrivate.GoTilContext.BreakAddress = 0;
644 EbcDebugSignalException (
645 EXCEPT_EBC_BREAKPOINT,
646 EXCEPTION_FLAG_NONE,
647 VmPtr
648 );
649 mDebuggerPrivate.StatusFlags &= ~EFI_DEBUG_FLAG_EBC_B_GT;
650 return ;
651 }
652 //
653 // Check ReturnAddress for StepOver
654 //
655 if ((mDebuggerPrivate.StepContext.BreakAddress == (UINT64)(UINTN)VmPtr->Ip) &&
656 (mDebuggerPrivate.StepContext.FramePointer == (UINT64)(UINTN)VmPtr->FramePtr)) {
657 mDebuggerPrivate.StatusFlags = EFI_DEBUG_FLAG_EBC_STEPOVER;
658 mDebuggerPrivate.StepContext.BreakAddress = 0;
659 mDebuggerPrivate.StepContext.FramePointer = 0;
660 EbcDebugSignalException (
661 EXCEPT_EBC_BREAKPOINT,
662 EXCEPTION_FLAG_NONE,
663 VmPtr
664 );
665 mDebuggerPrivate.StatusFlags &= ~EFI_DEBUG_FLAG_EBC_B_STEPOVER;
666 }
667 //
668 // Check FramePtr for StepOut
669 //
670 if (mDebuggerPrivate.StepContext.BreakAddress == (UINT64)(UINTN)VmPtr->FramePtr) {
671 mDebuggerPrivate.StatusFlags = EFI_DEBUG_FLAG_EBC_STEPOUT;
672 mDebuggerPrivate.StepContext.BreakAddress = 0;
673 mDebuggerPrivate.StepContext.FramePointer = 0;
674 EbcDebugSignalException (
675 EXCEPT_EBC_BREAKPOINT,
676 EXCEPTION_FLAG_NONE,
677 VmPtr
678 );
679 mDebuggerPrivate.StatusFlags &= ~EFI_DEBUG_FLAG_EBC_B_STEPOUT;
680 }
681 //
682 // Check Flags for BreakOnKey
683 //
684 if (mDebuggerPrivate.StatusFlags == EFI_DEBUG_FLAG_EBC_BOK) {
685 //
686 // Only break when the current TPL <= TPL_APPLICATION
687 //
688 CurrentTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
689 gBS->RestoreTPL (CurrentTpl);
690 if (CurrentTpl <= TPL_APPLICATION) {
691 EbcDebugSignalException (
692 EXCEPT_EBC_BREAKPOINT,
693 EXCEPTION_FLAG_NONE,
694 VmPtr
695 );
696 mDebuggerPrivate.StatusFlags &= ~EFI_DEBUG_FLAG_EBC_B_BOK;
697 }
698 }
699 return ;
700 }
701
702 VOID
703 EbcDebuggerHookExecuteEnd (
704 IN VM_CONTEXT *VmPtr
705 )
706 /*++
707
708 Routine Description:
709
710 The hook in EbcExecute, after ExecuteFunction.
711 It will record StepOut Entry if need.
712
713 Arguments:
714
715 VmPtr - pointer to VM context.
716
717 Returns:
718 None
719
720 --*/
721 {
722 UINTN Address;
723
724 //
725 // Use FramePtr as checkpoint for StepOut
726 //
727 CopyMem (&Address, (VOID *)((UINTN)VmPtr->FramePtr), sizeof(Address));
728 EbcDebuggerPushStepEntry (Address, (UINT64)(UINTN)VmPtr->FramePtr, EFI_DEBUG_FLAG_EBC_STEPOUT);
729
730 return ;
731 }
732
733 VOID
734 EbcDebuggerHookCALLStart (
735 IN VM_CONTEXT *VmPtr
736 )
737 /*++
738
739 Routine Description:
740
741 The hook in ExecuteCALL, before move IP.
742 It will trigger Exception if BOC enabled,
743 and record Callstack, and trace information.
744
745 Arguments:
746
747 VmPtr - pointer to VM context.
748
749 Returns:
750 None
751
752 --*/
753 {
754 EbcDebuggerCheckHookFlag (VmPtr, EFI_DEBUG_FLAG_EBC_BOC);
755 EbcDebuggerPushCallstackSource ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCall);
756 EbcDebuggerPushCallstackParameter ((UINT64)(UINTN)VmPtr->Gpr[0], EfiDebuggerBranchTypeEbcCall);
757 EbcDebuggerPushTraceSourceEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCall);
758 return ;
759 }
760
761 VOID
762 EbcDebuggerHookCALLEnd (
763 IN VM_CONTEXT *VmPtr
764 )
765 /*++
766
767 Routine Description:
768
769 The hook in ExecuteCALL, after move IP.
770 It will record Callstack, trace information
771 and record StepOver/StepOut Entry if need.
772
773 Arguments:
774
775 VmPtr - pointer to VM context.
776
777 Returns:
778 None
779
780 --*/
781 {
782 UINT64 Address;
783 UINTN FramePtr;
784
785 EbcDebuggerPushCallstackDest ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCall);
786 EbcDebuggerPushTraceDestEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCall);
787
788 //
789 // Get Old FramePtr
790 //
791 CopyMem (&FramePtr, (VOID *)((UINTN)VmPtr->FramePtr), sizeof(FramePtr));
792
793 //
794 // Use ReturnAddress as checkpoint for StepOver
795 //
796 CopyMem (&Address, (VOID *)(UINTN)VmPtr->Gpr[0], sizeof(Address));
797 EbcDebuggerPushStepEntry (Address, FramePtr, EFI_DEBUG_FLAG_EBC_STEPOVER);
798
799 //
800 // Use FramePtr as checkpoint for StepOut
801 //
802 Address = 0;
803 CopyMem (&Address, (VOID *)(FramePtr), sizeof(UINTN));
804 EbcDebuggerPushStepEntry (Address, FramePtr, EFI_DEBUG_FLAG_EBC_STEPOUT);
805
806 return ;
807 }
808
809 VOID
810 EbcDebuggerHookCALLEXStart (
811 IN VM_CONTEXT *VmPtr
812 )
813 /*++
814
815 Routine Description:
816
817 The hook in ExecuteCALL, before call EbcLLCALLEX.
818 It will trigger Exception if BOCX enabled,
819 and record Callstack information.
820
821 Arguments:
822
823 VmPtr - pointer to VM context.
824
825 Returns:
826 None
827
828 --*/
829 {
830 EbcDebuggerCheckHookFlag (VmPtr, EFI_DEBUG_FLAG_EBC_BOCX);
831 // EbcDebuggerPushCallstackSource ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCallEx);
832 // EbcDebuggerPushCallstackParameter ((UINT64)(UINTN)VmPtr->R[0], EfiDebuggerBranchTypeEbcCallEx);
833 EbcDebuggerPushTraceSourceEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCallEx);
834 return ;
835 }
836
837 VOID
838 EbcDebuggerHookCALLEXEnd (
839 IN VM_CONTEXT *VmPtr
840 )
841 /*++
842
843 Routine Description:
844
845 The hook in ExecuteCALL, after call EbcLLCALLEX.
846 It will record trace information.
847
848 Arguments:
849
850 VmPtr - pointer to VM context.
851
852 Returns:
853 None
854
855 --*/
856 {
857 // EbcDebuggerPushCallstackDest ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCallEx);
858 EbcDebuggerPushTraceDestEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCallEx);
859 return ;
860 }
861
862 VOID
863 EbcDebuggerHookRETStart (
864 IN VM_CONTEXT *VmPtr
865 )
866 /*++
867
868 Routine Description:
869
870 The hook in ExecuteRET, before move IP.
871 It will trigger Exception if BOR enabled,
872 and record Callstack, and trace information.
873
874 Arguments:
875
876 VmPtr - pointer to VM context.
877
878 Returns:
879 None
880
881 --*/
882 {
883 EbcDebuggerCheckHookFlag (VmPtr, EFI_DEBUG_FLAG_EBC_BOR);
884 EbcDebuggerPopCallstack ();
885 EbcDebuggerPushTraceSourceEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcRet);
886 return ;
887 }
888
889 VOID
890 EbcDebuggerHookRETEnd (
891 IN VM_CONTEXT *VmPtr
892 )
893 /*++
894
895 Routine Description:
896
897 The hook in ExecuteRET, after move IP.
898 It will record trace information.
899
900 Arguments:
901
902 VmPtr - pointer to VM context.
903
904 Returns:
905 None
906
907 --*/
908 {
909 EbcDebuggerPushTraceDestEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcRet);
910 return ;
911 }
912
913 VOID
914 EbcDebuggerHookJMPStart (
915 IN VM_CONTEXT *VmPtr
916 )
917 /*++
918
919 Routine Description:
920
921 The hook in ExecuteJMP, before move IP.
922 It will record trace information.
923
924 Arguments:
925
926 VmPtr - pointer to VM context.
927
928 Returns:
929 None
930
931 --*/
932 {
933 EbcDebuggerPushTraceSourceEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcJmp);
934 return ;
935 }
936
937 VOID
938 EbcDebuggerHookJMPEnd (
939 IN VM_CONTEXT *VmPtr
940 )
941 /*++
942
943 Routine Description:
944
945 The hook in ExecuteJMP, after move IP.
946 It will record trace information.
947
948 Arguments:
949
950 VmPtr - pointer to VM context.
951
952 Returns:
953 None
954
955 --*/
956 {
957 EbcDebuggerPushTraceDestEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcJmp);
958 return ;
959 }
960
961 VOID
962 EbcDebuggerHookJMP8Start (
963 IN VM_CONTEXT *VmPtr
964 )
965 /*++
966
967 Routine Description:
968
969 The hook in ExecuteJMP8, before move IP.
970 It will record trace information.
971
972 Arguments:
973
974 VmPtr - pointer to VM context.
975
976 Returns:
977 None
978
979 --*/
980 {
981 EbcDebuggerPushTraceSourceEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcJmp8);
982 return ;
983 }
984
985 VOID
986 EbcDebuggerHookJMP8End (
987 IN VM_CONTEXT *VmPtr
988 )
989 /*++
990
991 Routine Description:
992
993 The hook in ExecuteJMP8, after move IP.
994 It will record trace information.
995
996 Arguments:
997
998 VmPtr - pointer to VM context.
999
1000 Returns:
1001 None
1002
1003 --*/
1004 {
1005 EbcDebuggerPushTraceDestEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcJmp8);
1006 return ;
1007 }