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