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