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