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