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