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