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