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