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