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