3 Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
4 SPDX-License-Identifier: BSD-2-Clause-Patent
11 EFI_DEBUGGER_PRIVATE_DATA mDebuggerPrivate
= {
12 EFI_DEBUGGER_SIGNATURE
, // Signature
14 (EBC_DEBUGGER_MAJOR_VERSION
<< 16) |
15 EBC_DEBUGGER_MINOR_VERSION
, // EfiDebuggerRevision
16 (VM_MAJOR_VERSION
<< 16) |
17 VM_MINOR_VERSION
, // EbcVmRevision
19 EFI_DEBUGGER_CONFIGURATION_VERSION
,
21 }, // DebuggerConfiguration
22 NULL
, // DebugImageInfoTableHeader
24 NULL
, // PciRootBridgeIo
25 mDebuggerCommandSet
, // DebuggerCommandSet
26 {0}, // DebuggerSymbolContext
27 0, // DebuggerBreakpointCount
28 {{0}}, // DebuggerBreakpointContext
29 0, // CallStackEntryCount
30 {{0}}, // CallStackEntry
35 0, // InstructionScope
36 EFI_DEBUG_DEFAULT_INSTRUCTION_NUMBER
, // InstructionNumber
37 EFI_DEBUG_FLAG_EBC_BOE
| EFI_DEBUG_FLAG_EBC_BOT
, // FeatureFlags
39 FALSE
, // EnablePageBreak
43 CHAR16
*mExceptionStr
[] = {
44 L
"EXCEPT_EBC_UNDEFINED",
45 L
"EXCEPT_EBC_DIVIDE_ERROR",
47 L
"EXCEPT_EBC_BREAKPOINT",
48 L
"EXCEPT_EBC_OVERFLOW",
49 L
"EXCEPT_EBC_INVALID_OPCODE",
50 L
"EXCEPT_EBC_STACK_FAULT",
51 L
"EXCEPT_EBC_ALIGNMENT_CHECK",
52 L
"EXCEPT_EBC_INSTRUCTION_ENCODING",
53 L
"EXCEPT_EBC_BAD_BREAK",
54 L
"EXCEPT_EBC_SINGLE_STEP",
59 Clear all the breakpoint.
61 @param DebuggerPrivate EBC Debugger private data structure
62 @param NeedRemove Whether need to remove all the breakpoint
66 EdbClearAllBreakpoint (
67 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
74 // Patch all the breakpoint
76 for (Index
= 0; (Index
< DebuggerPrivate
->DebuggerBreakpointCount
) && (Index
< EFI_DEBUGGER_BREAKPOINT_MAX
); Index
++) {
77 if (DebuggerPrivate
->DebuggerBreakpointContext
[Index
].State
) {
79 (VOID
*)(UINTN
)DebuggerPrivate
->DebuggerBreakpointContext
[Index
].BreakpointAddress
,
80 &DebuggerPrivate
->DebuggerBreakpointContext
[Index
].OldInstruction
,
87 // Zero Breakpoint context, if need to remove all breakpoint
90 DebuggerPrivate
->DebuggerBreakpointCount
= 0;
91 ZeroMem (DebuggerPrivate
->DebuggerBreakpointContext
, sizeof(DebuggerPrivate
->DebuggerBreakpointContext
));
102 Set all the breakpoint.
104 @param DebuggerPrivate EBC Debugger private data structure
108 EdbSetAllBreakpoint (
109 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
116 // Set all the breakpoint (BREAK(3) : 0x0300)
119 for (Index
= 0; (Index
< DebuggerPrivate
->DebuggerBreakpointCount
) && (Index
< EFI_DEBUGGER_BREAKPOINT_MAX
); Index
++) {
120 if (DebuggerPrivate
->DebuggerBreakpointContext
[Index
].State
) {
122 (VOID
*)(UINTN
)DebuggerPrivate
->DebuggerBreakpointContext
[Index
].BreakpointAddress
,
130 // Check if current break is caused by breakpoint set.
131 // If so, we need to patch memory back to let user see the real memory.
133 if (DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
].BreakpointAddress
!= 0) {
135 (VOID
*)(UINTN
)DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
].BreakpointAddress
,
136 &DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
].OldInstruction
,
139 DebuggerPrivate
->StatusFlags
&= ~EFI_DEBUG_FLAG_EBC_B_BP
;
150 Check all the breakpoint, if match, then set status flag, and record current breakpoint.
151 Then clear all breakpoint to let user see a clean memory
153 @param DebuggerPrivate EBC Debugger private data structure
154 @param SystemContext EBC system context.
159 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
160 IN EFI_SYSTEM_CONTEXT SystemContext
165 BOOLEAN IsHitBreakpoint
;
168 // Roll back IP for breakpoint instruction (BREAK(3) : 0x0300)
170 Address
= SystemContext
.SystemContextEbc
->Ip
- sizeof(UINT16
);
173 // Check if the breakpoint is hit
175 IsHitBreakpoint
= FALSE
;
176 for (Index
= 0; (Index
< DebuggerPrivate
->DebuggerBreakpointCount
) && (Index
< EFI_DEBUGGER_BREAKPOINT_MAX
); Index
++) {
177 if ((DebuggerPrivate
->DebuggerBreakpointContext
[Index
].BreakpointAddress
== Address
) &&
178 (DebuggerPrivate
->DebuggerBreakpointContext
[Index
].State
)) {
179 IsHitBreakpoint
= TRUE
;
184 if (IsHitBreakpoint
) {
186 // If hit, record current breakpoint
188 DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
] = DebuggerPrivate
->DebuggerBreakpointContext
[Index
];
189 DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
].State
= TRUE
;
191 // Update: IP and Instruction (NOTE: Since we not allow set breakpoint to BREAK 3, this update is safe)
193 SystemContext
.SystemContextEbc
->Ip
= Address
;
197 DebuggerPrivate
->StatusFlags
|= EFI_DEBUG_FLAG_EBC_BP
;
200 // If not hit, check whether current IP is in breakpoint list,
201 // because STEP will be triggered before execute the instruction.
202 // We should not patch it in de-init.
204 Address
= SystemContext
.SystemContextEbc
->Ip
;
207 // Check if the breakpoint is hit
209 IsHitBreakpoint
= FALSE
;
210 for (Index
= 0; (Index
< DebuggerPrivate
->DebuggerBreakpointCount
) && (Index
< EFI_DEBUGGER_BREAKPOINT_MAX
); Index
++) {
211 if ((DebuggerPrivate
->DebuggerBreakpointContext
[Index
].BreakpointAddress
== Address
) &&
212 (DebuggerPrivate
->DebuggerBreakpointContext
[Index
].State
)) {
213 IsHitBreakpoint
= TRUE
;
218 if (IsHitBreakpoint
) {
220 // If hit, record current breakpoint
222 DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
] = DebuggerPrivate
->DebuggerBreakpointContext
[Index
];
223 DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
].State
= TRUE
;
225 // Do not set Breakpoint flag. We record the address here just let it not patch breakpoint address when de-init.
229 // Zero current breakpoint
232 &DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
],
233 sizeof(DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
])
245 clear all the symbol.
247 @param DebuggerPrivate EBC Debugger private data structure
252 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
255 EFI_DEBUGGER_SYMBOL_CONTEXT
*DebuggerSymbolContext
;
256 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
261 // Go throuth each object
263 DebuggerSymbolContext
= &DebuggerPrivate
->DebuggerSymbolContext
;
264 for (ObjectIndex
= 0; ObjectIndex
< DebuggerSymbolContext
->ObjectCount
; ObjectIndex
++) {
265 Object
= &DebuggerSymbolContext
->Object
[ObjectIndex
];
267 // Go throuth each entry
269 for (Index
= 0; Index
< Object
->EntryCount
; Index
++) {
270 ZeroMem (&Object
->Entry
[Index
], sizeof(Object
->Entry
[Index
]));
272 ZeroMem (Object
->Name
, sizeof(Object
->Name
));
273 Object
->EntryCount
= 0;
274 Object
->BaseAddress
= 0;
275 Object
->StartEntrypointRVA
= 0;
276 Object
->MainEntrypointRVA
= 0;
278 // Free source buffer
280 for (Index
= 0; Object
->SourceBuffer
[Index
] != NULL
; Index
++) {
281 gBS
->FreePool (Object
->SourceBuffer
[Index
]);
282 Object
->SourceBuffer
[Index
] = NULL
;
285 DebuggerSymbolContext
->ObjectCount
= 0;
292 Initialize Debugger private data structure
294 @param DebuggerPrivate EBC Debugger private data structure
295 @param ExceptionType Exception type.
296 @param SystemContext EBC system context.
297 @param Initialized Whether the DebuggerPrivate data is initialized.
301 InitDebuggerPrivateData (
302 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
303 IN EFI_EXCEPTION_TYPE ExceptionType
,
304 IN EFI_SYSTEM_CONTEXT SystemContext
,
305 IN BOOLEAN Initialized
309 // clear STEP flag in any condition.
311 if (SystemContext
.SystemContextEbc
->Flags
& ((UINT64
) VMFLAGS_STEP
)) {
312 SystemContext
.SystemContextEbc
->Flags
&= ~((UINT64
) VMFLAGS_STEP
);
317 // Initialize everything
319 DebuggerPrivate
->InstructionNumber
= EFI_DEBUG_DEFAULT_INSTRUCTION_NUMBER
;
321 DebuggerPrivate
->DebuggerBreakpointCount
= 0;
322 ZeroMem (DebuggerPrivate
->DebuggerBreakpointContext
, sizeof(DebuggerPrivate
->DebuggerBreakpointContext
));
324 // DebuggerPrivate->StatusFlags = 0;
326 DebuggerPrivate
->DebuggerSymbolContext
.DisplaySymbol
= TRUE
;
327 DebuggerPrivate
->DebuggerSymbolContext
.DisplayCodeOnly
= FALSE
;
328 DebuggerPrivate
->DebuggerSymbolContext
.ObjectCount
= 0;
331 // Already initialized, just check Breakpoint here.
333 if (ExceptionType
== EXCEPT_EBC_BREAKPOINT
) {
334 EdbCheckBreakpoint (DebuggerPrivate
, SystemContext
);
338 // Clear all breakpoint
340 EdbClearAllBreakpoint (DebuggerPrivate
, FALSE
);
344 // Set Scope to currentl IP. (Note: Check Breakpoint may change Ip)
346 DebuggerPrivate
->InstructionScope
= SystemContext
.SystemContextEbc
->Ip
;
356 De-initialize Debugger private data structure.
358 @param DebuggerPrivate EBC Debugger private data structure
359 @param ExceptionType Exception type.
360 @param SystemContext EBC system context.
361 @param Initialized Whether the DebuggerPrivate data is initialized.
365 DeinitDebuggerPrivateData (
366 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
367 IN EFI_EXCEPTION_TYPE ExceptionType
,
368 IN EFI_SYSTEM_CONTEXT SystemContext
,
369 IN BOOLEAN Initialized
374 // If it does not want initialized state, de-init everything
376 DebuggerPrivate
->FeatureFlags
= EFI_DEBUG_FLAG_EBC_BOE
| EFI_DEBUG_FLAG_EBC_BOT
;
377 DebuggerPrivate
->CallStackEntryCount
= 0;
378 DebuggerPrivate
->TraceEntryCount
= 0;
379 ZeroMem (DebuggerPrivate
->CallStackEntry
, sizeof(DebuggerPrivate
->CallStackEntry
));
380 ZeroMem (DebuggerPrivate
->TraceEntry
, sizeof(DebuggerPrivate
->TraceEntry
));
383 // Clear all breakpoint
385 EdbClearAllBreakpoint (DebuggerPrivate
, TRUE
);
390 EdbClearSymbol (DebuggerPrivate
);
393 // If it wants to keep initialized state, just set breakpoint.
395 EdbSetAllBreakpoint (DebuggerPrivate
);
399 // Clear Step context
401 ZeroMem (&mDebuggerPrivate
.StepContext
, sizeof(mDebuggerPrivate
.StepContext
));
402 DebuggerPrivate
->StatusFlags
= 0;
412 Print the reason of current break to EbcDebugger.
414 @param DebuggerPrivate EBC Debugger private data structure
415 @param ExceptionType Exception type.
416 @param SystemContext EBC system context.
417 @param Initialized Whether the DebuggerPrivate data is initialized.
421 PrintExceptionReason (
422 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
423 IN EFI_EXCEPTION_TYPE ExceptionType
,
424 IN EFI_SYSTEM_CONTEXT SystemContext
,
425 IN BOOLEAN Initialized
429 // Print break status
431 if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_GT
) == EFI_DEBUG_FLAG_EBC_GT
) {
432 EDBPrint (L
"Break on GoTil\n");
433 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_BOC
) == EFI_DEBUG_FLAG_EBC_BOC
) {
434 EDBPrint (L
"Break on CALL\n");
435 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_BOCX
) == EFI_DEBUG_FLAG_EBC_BOCX
) {
436 EDBPrint (L
"Break on CALLEX\n");
437 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_BOR
) == EFI_DEBUG_FLAG_EBC_BOR
) {
438 EDBPrint (L
"Break on RET\n");
439 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_BOE
) == EFI_DEBUG_FLAG_EBC_BOE
) {
440 EDBPrint (L
"Break on Entrypoint\n");
441 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_BOT
) == EFI_DEBUG_FLAG_EBC_BOT
) {
442 EDBPrint (L
"Break on Thunk\n");
443 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_STEPOVER
) == EFI_DEBUG_FLAG_EBC_STEPOVER
) {
444 EDBPrint (L
"Break on StepOver\n");
445 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_STEPOUT
) == EFI_DEBUG_FLAG_EBC_STEPOUT
) {
446 EDBPrint (L
"Break on StepOut\n");
447 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_BP
) == EFI_DEBUG_FLAG_EBC_BP
) {
448 EDBPrint (L
"Break on Breakpoint\n");
449 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_BOK
) == EFI_DEBUG_FLAG_EBC_BOK
) {
450 EDBPrint (L
"Break on Key\n");
452 EDBPrint (L
"Exception Type - %x", (UINTN
)ExceptionType
);
453 if ((ExceptionType
>= EXCEPT_EBC_UNDEFINED
) && (ExceptionType
<= EXCEPT_EBC_STEP
)) {
454 EDBPrint (L
" (%s)\n", mExceptionStr
[ExceptionType
]);
465 The default Exception Callback for the VM interpreter.
466 In this function, we report status code, and print debug information
467 about EBC_CONTEXT, then dead loop.
469 @param ExceptionType Exception type.
470 @param SystemContext EBC system context.
475 EdbExceptionHandler (
476 IN EFI_EXCEPTION_TYPE ExceptionType
,
477 IN OUT EFI_SYSTEM_CONTEXT SystemContext
480 CHAR16 InputBuffer
[EFI_DEBUG_INPUS_BUFFER_SIZE
];
482 EFI_DEBUGGER_COMMAND DebuggerCommand
;
483 EFI_DEBUG_STATUS DebugStatus
;
484 STATIC BOOLEAN mInitialized
;
486 mInitialized
= FALSE
;
488 DEBUG ((DEBUG_ERROR
, "Hello EBC Debugger!\n"));
495 L
"EBC Interpreter Version - %d.%d\n",
496 (UINTN
)VM_MAJOR_VERSION
,
497 (UINTN
)VM_MINOR_VERSION
500 L
"EBC Debugger Version - %d.%d\n",
501 (UINTN
)EBC_DEBUGGER_MAJOR_VERSION
,
502 (UINTN
)EBC_DEBUGGER_MINOR_VERSION
508 InitDebuggerPrivateData (&mDebuggerPrivate
, ExceptionType
, SystemContext
, mInitialized
);
511 // EDBPrint basic info
513 PrintExceptionReason (&mDebuggerPrivate
, ExceptionType
, SystemContext
, mInitialized
);
515 EdbShowDisasm (&mDebuggerPrivate
, SystemContext
);
516 // EFI_BREAKPOINT ();
520 // Interactive with user
522 EDBPrint (L
"\nPlease enter command now, \'h\' for help.\n");
523 EDBPrint (L
"(Using <Command> -b <...> to enable page break.)\n");
528 // Dispatch each command
534 Input (L
"\n\r" EFI_DEBUG_PROMPT_STRING
, InputBuffer
, EFI_DEBUG_INPUS_BUFFER_SIZE
);
540 DebuggerCommand
= MatchDebuggerCommand (InputBuffer
, &CommandArg
);
541 if (DebuggerCommand
== NULL
) {
542 EDBPrint (L
"ERROR: Command not found!\n");
549 if (CommandArg
!= NULL
) {
550 if (StriCmp (CommandArg
, L
"-b") == 0) {
551 CommandArg
= StrGetNextTokenLine (L
" ");
552 mDebuggerPrivate
.EnablePageBreak
= TRUE
;
559 DebugStatus
= DebuggerCommand (CommandArg
, &mDebuggerPrivate
, ExceptionType
, SystemContext
);
560 mDebuggerPrivate
.EnablePageBreak
= FALSE
;
563 // Check command return status
565 if (DebugStatus
== EFI_DEBUG_RETURN
) {
566 mInitialized
= FALSE
;
568 } else if (DebugStatus
== EFI_DEBUG_BREAK
) {
570 } else if (DebugStatus
== EFI_DEBUG_CONTINUE
) {
578 // Deinit Private Data
580 DeinitDebuggerPrivateData (&mDebuggerPrivate
, ExceptionType
, SystemContext
, mInitialized
);
582 DEBUG ((DEBUG_ERROR
, "Goodbye EBC Debugger!\n"));