3 Copyright (c) 2007 - 2016, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
23 EFI_DEBUGGER_PRIVATE_DATA mDebuggerPrivate
= {
24 EFI_DEBUGGER_SIGNATURE
, // Signature
26 (EBC_DEBUGGER_MAJOR_VERSION
<< 16) |
27 EBC_DEBUGGER_MINOR_VERSION
, // EfiDebuggerRevision
28 (VM_MAJOR_VERSION
<< 16) |
29 VM_MINOR_VERSION
, // EbcVmRevision
30 NULL
, // DebugImageInfoTableHeader
32 NULL
, // PciRootBridgeIo
33 mDebuggerCommandSet
, // DebuggerCommandSet
34 {0}, // DebuggerSymbolContext
35 0, // DebuggerBreakpointCount
36 {{0}}, // DebuggerBreakpointContext
37 0, // CallStackEntryCount
38 {{0}}, // CallStackEntry
43 0, // InstructionScope
44 EFI_DEBUG_DEFAULT_INSTRUCTION_NUMBER
, // InstructionNumber
45 EFI_DEBUG_FLAG_EBC_BOE
| EFI_DEBUG_FLAG_EBC_BOT
, // FeatureFlags
47 FALSE
, // EnablePageBreak
51 CHAR16
*mExceptionStr
[] = {
52 L
"EXCEPT_EBC_UNDEFINED",
53 L
"EXCEPT_EBC_DIVIDE_ERROR",
55 L
"EXCEPT_EBC_BREAKPOINT",
56 L
"EXCEPT_EBC_OVERFLOW",
57 L
"EXCEPT_EBC_INVALID_OPCODE",
58 L
"EXCEPT_EBC_STACK_FAULT",
59 L
"EXCEPT_EBC_ALIGNMENT_CHECK",
60 L
"EXCEPT_EBC_INSTRUCTION_ENCODING",
61 L
"EXCEPT_EBC_BAD_BREAK",
62 L
"EXCEPT_EBC_SINGLE_STEP",
66 EdbClearAllBreakpoint (
67 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
74 Clear all the breakpoint
78 DebuggerPrivate - EBC Debugger private data structure
79 NeedRemove - Whether need to remove all the breakpoint
90 // Patch all the breakpoint
92 for (Index
= 0; (Index
< DebuggerPrivate
->DebuggerBreakpointCount
) && (Index
< EFI_DEBUGGER_BREAKPOINT_MAX
); Index
++) {
93 if (DebuggerPrivate
->DebuggerBreakpointContext
[Index
].State
) {
95 (VOID
*)(UINTN
)DebuggerPrivate
->DebuggerBreakpointContext
[Index
].BreakpointAddress
,
96 &DebuggerPrivate
->DebuggerBreakpointContext
[Index
].OldInstruction
,
103 // Zero Breakpoint context, if need to remove all breakpoint
106 DebuggerPrivate
->DebuggerBreakpointCount
= 0;
107 ZeroMem (DebuggerPrivate
->DebuggerBreakpointContext
, sizeof(DebuggerPrivate
->DebuggerBreakpointContext
));
117 EdbSetAllBreakpoint (
118 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
124 Set all the breakpoint
128 DebuggerPrivate - EBC Debugger private data structure
140 // Set all the breakpoint (BREAK(3) : 0x0300)
143 for (Index
= 0; (Index
< DebuggerPrivate
->DebuggerBreakpointCount
) && (Index
< EFI_DEBUGGER_BREAKPOINT_MAX
); Index
++) {
144 if (DebuggerPrivate
->DebuggerBreakpointContext
[Index
].State
) {
146 (VOID
*)(UINTN
)DebuggerPrivate
->DebuggerBreakpointContext
[Index
].BreakpointAddress
,
154 // Check if current break is caused by breakpoint set.
155 // If so, we need to patch memory back to let user see the real memory.
157 if (DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
].BreakpointAddress
!= 0) {
159 (VOID
*)(UINTN
)DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
].BreakpointAddress
,
160 &DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
].OldInstruction
,
163 DebuggerPrivate
->StatusFlags
&= ~EFI_DEBUG_FLAG_EBC_B_BP
;
174 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
175 IN EFI_SYSTEM_CONTEXT SystemContext
181 Check all the breakpoint, if match, then set status flag, and record current breakpoint.
182 Then clear all breakpoint to let user see a clean memory
186 DebuggerPrivate - EBC Debugger private data structure
187 SystemContext - EBC system context.
197 BOOLEAN IsHitBreakpoint
;
200 // Roll back IP for breakpoint instruction (BREAK(3) : 0x0300)
202 Address
= SystemContext
.SystemContextEbc
->Ip
- sizeof(UINT16
);
205 // Check if the breakpoint is hit
207 IsHitBreakpoint
= FALSE
;
208 for (Index
= 0; (Index
< DebuggerPrivate
->DebuggerBreakpointCount
) && (Index
< EFI_DEBUGGER_BREAKPOINT_MAX
); Index
++) {
209 if ((DebuggerPrivate
->DebuggerBreakpointContext
[Index
].BreakpointAddress
== Address
) &&
210 (DebuggerPrivate
->DebuggerBreakpointContext
[Index
].State
)) {
211 IsHitBreakpoint
= TRUE
;
216 if (IsHitBreakpoint
) {
218 // If hit, record current breakpoint
220 DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
] = DebuggerPrivate
->DebuggerBreakpointContext
[Index
];
221 DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
].State
= TRUE
;
223 // Update: IP and Instruction (NOTE: Since we not allow set breakpoint to BREAK 3, this update is safe)
225 SystemContext
.SystemContextEbc
->Ip
= Address
;
229 DebuggerPrivate
->StatusFlags
|= EFI_DEBUG_FLAG_EBC_BP
;
232 // If not hit, check whether current IP is in breakpoint list,
233 // because STEP will be triggered before execute the instruction.
234 // We should not patch it in de-init.
236 Address
= SystemContext
.SystemContextEbc
->Ip
;
239 // Check if the breakpoint is hit
241 IsHitBreakpoint
= FALSE
;
242 for (Index
= 0; (Index
< DebuggerPrivate
->DebuggerBreakpointCount
) && (Index
< EFI_DEBUGGER_BREAKPOINT_MAX
); Index
++) {
243 if ((DebuggerPrivate
->DebuggerBreakpointContext
[Index
].BreakpointAddress
== Address
) &&
244 (DebuggerPrivate
->DebuggerBreakpointContext
[Index
].State
)) {
245 IsHitBreakpoint
= TRUE
;
250 if (IsHitBreakpoint
) {
252 // If hit, record current breakpoint
254 DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
] = DebuggerPrivate
->DebuggerBreakpointContext
[Index
];
255 DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
].State
= TRUE
;
257 // Do not set Breakpoint flag. We record the address here just let it not patch breakpoint address when de-init.
261 // Zero current breakpoint
264 &DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
],
265 sizeof(DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
])
278 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
288 DebuggerPrivate - EBC Debugger private data structure
296 EFI_DEBUGGER_SYMBOL_CONTEXT
*DebuggerSymbolContext
;
297 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
302 // Go throuth each object
304 DebuggerSymbolContext
= &DebuggerPrivate
->DebuggerSymbolContext
;
305 for (ObjectIndex
= 0; ObjectIndex
< DebuggerSymbolContext
->ObjectCount
; ObjectIndex
++) {
306 Object
= &DebuggerSymbolContext
->Object
[ObjectIndex
];
308 // Go throuth each entry
310 for (Index
= 0; Index
< Object
->EntryCount
; Index
++) {
311 ZeroMem (&Object
->Entry
[Index
], sizeof(Object
->Entry
[Index
]));
313 ZeroMem (Object
->Name
, sizeof(Object
->Name
));
314 Object
->EntryCount
= 0;
315 Object
->BaseAddress
= 0;
316 Object
->StartEntrypointRVA
= 0;
317 Object
->MainEntrypointRVA
= 0;
319 // Free source buffer
321 for (Index
= 0; Object
->SourceBuffer
[Index
] != NULL
; Index
++) {
322 gBS
->FreePool (Object
->SourceBuffer
[Index
]);
323 Object
->SourceBuffer
[Index
] = NULL
;
326 DebuggerSymbolContext
->ObjectCount
= 0;
332 InitDebuggerPrivateData (
333 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
334 IN EFI_EXCEPTION_TYPE ExceptionType
,
335 IN EFI_SYSTEM_CONTEXT SystemContext
,
336 IN BOOLEAN Initialized
342 Initialize Debugger private data structure
346 DebuggerPrivate - EBC Debugger private data structure
347 InterruptType - Interrupt type.
348 SystemContext - EBC system context.
349 Initialized - Whether the DebuggerPrivate data is initialized.
358 // clear STEP flag in any condition.
360 if (SystemContext
.SystemContextEbc
->Flags
& ((UINT64
) VMFLAGS_STEP
)) {
361 SystemContext
.SystemContextEbc
->Flags
&= ~((UINT64
) VMFLAGS_STEP
);
366 // Initialize everything
368 DebuggerPrivate
->InstructionNumber
= EFI_DEBUG_DEFAULT_INSTRUCTION_NUMBER
;
370 DebuggerPrivate
->DebuggerBreakpointCount
= 0;
371 ZeroMem (DebuggerPrivate
->DebuggerBreakpointContext
, sizeof(DebuggerPrivate
->DebuggerBreakpointContext
));
373 // DebuggerPrivate->StatusFlags = 0;
375 DebuggerPrivate
->DebuggerSymbolContext
.DisplaySymbol
= TRUE
;
376 DebuggerPrivate
->DebuggerSymbolContext
.DisplayCodeOnly
= FALSE
;
377 DebuggerPrivate
->DebuggerSymbolContext
.ObjectCount
= 0;
380 // Already initialized, just check Breakpoint here.
382 if (ExceptionType
== EXCEPT_EBC_BREAKPOINT
) {
383 EdbCheckBreakpoint (DebuggerPrivate
, SystemContext
);
387 // Clear all breakpoint
389 EdbClearAllBreakpoint (DebuggerPrivate
, FALSE
);
393 // Set Scope to currentl IP. (Note: Check Breakpoint may change Ip)
395 DebuggerPrivate
->InstructionScope
= SystemContext
.SystemContextEbc
->Ip
;
404 DeinitDebuggerPrivateData (
405 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
406 IN EFI_EXCEPTION_TYPE ExceptionType
,
407 IN EFI_SYSTEM_CONTEXT SystemContext
,
408 IN BOOLEAN Initialized
414 De-initialize Debugger private data structure
418 DebuggerPrivate - EBC Debugger private data structure
419 InterruptType - Interrupt type.
420 SystemContext - EBC system context.
421 Initialized - Whether the DebuggerPrivate data is initialized.
431 // If it does not want initialized state, de-init everything
433 DebuggerPrivate
->FeatureFlags
= EFI_DEBUG_FLAG_EBC_BOE
| EFI_DEBUG_FLAG_EBC_BOT
;
434 DebuggerPrivate
->CallStackEntryCount
= 0;
435 DebuggerPrivate
->TraceEntryCount
= 0;
436 ZeroMem (DebuggerPrivate
->CallStackEntry
, sizeof(DebuggerPrivate
->CallStackEntry
));
437 ZeroMem (DebuggerPrivate
->TraceEntry
, sizeof(DebuggerPrivate
->TraceEntry
));
440 // Clear all breakpoint
442 EdbClearAllBreakpoint (DebuggerPrivate
, TRUE
);
447 EdbClearSymbol (DebuggerPrivate
);
450 // If it wants to keep initialized state, just set breakpoint.
452 EdbSetAllBreakpoint (DebuggerPrivate
);
456 // Clear Step context
458 ZeroMem (&mDebuggerPrivate
.StepContext
, sizeof(mDebuggerPrivate
.StepContext
));
459 DebuggerPrivate
->StatusFlags
= 0;
468 PrintExceptionReason (
469 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
470 IN EFI_EXCEPTION_TYPE ExceptionType
,
471 IN EFI_SYSTEM_CONTEXT SystemContext
,
472 IN BOOLEAN Initialized
478 Print the reason of current break to EbcDebugger.
482 DebuggerPrivate - EBC Debugger private data structure
483 InterruptType - Interrupt type.
484 SystemContext - EBC system context.
485 Initialized - Whether the DebuggerPrivate data is initialized.
494 // Print break status
496 if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_GT
) == EFI_DEBUG_FLAG_EBC_GT
) {
497 EDBPrint (L
"Break on GoTil\n");
498 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_BOC
) == EFI_DEBUG_FLAG_EBC_BOC
) {
499 EDBPrint (L
"Break on CALL\n");
500 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_BOCX
) == EFI_DEBUG_FLAG_EBC_BOCX
) {
501 EDBPrint (L
"Break on CALLEX\n");
502 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_BOR
) == EFI_DEBUG_FLAG_EBC_BOR
) {
503 EDBPrint (L
"Break on RET\n");
504 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_BOE
) == EFI_DEBUG_FLAG_EBC_BOE
) {
505 EDBPrint (L
"Break on Entrypoint\n");
506 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_BOT
) == EFI_DEBUG_FLAG_EBC_BOT
) {
507 EDBPrint (L
"Break on Thunk\n");
508 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_STEPOVER
) == EFI_DEBUG_FLAG_EBC_STEPOVER
) {
509 EDBPrint (L
"Break on StepOver\n");
510 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_STEPOUT
) == EFI_DEBUG_FLAG_EBC_STEPOUT
) {
511 EDBPrint (L
"Break on StepOut\n");
512 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_BP
) == EFI_DEBUG_FLAG_EBC_BP
) {
513 EDBPrint (L
"Break on Breakpoint\n");
514 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_BOK
) == EFI_DEBUG_FLAG_EBC_BOK
) {
515 EDBPrint (L
"Break on Key\n");
517 EDBPrint (L
"Exception Type - %x", (UINTN
)ExceptionType
);
518 if ((ExceptionType
>= EXCEPT_EBC_UNDEFINED
) && (ExceptionType
<= EXCEPT_EBC_STEP
)) {
519 EDBPrint (L
" (%s)\n", mExceptionStr
[ExceptionType
]);
530 EdbExceptionHandler (
531 IN EFI_EXCEPTION_TYPE ExceptionType
,
532 IN OUT EFI_SYSTEM_CONTEXT SystemContext
538 The default Exception Callback for the VM interpreter.
539 In this function, we report status code, and print debug information
540 about EBC_CONTEXT, then dead loop.
544 InterruptType - Interrupt type.
545 SystemContext - EBC system context.
553 CHAR16 InputBuffer
[EFI_DEBUG_INPUS_BUFFER_SIZE
];
555 EFI_DEBUGGER_COMMAND DebuggerCommand
;
556 EFI_DEBUG_STATUS DebugStatus
;
557 STATIC BOOLEAN mInitialized
= FALSE
;
559 DEBUG ((DEBUG_ERROR
, "Hello EBC Debugger!\n"));
566 L
"EBC Interpreter Version - %d.%d\n",
567 (UINTN
)VM_MAJOR_VERSION
,
568 (UINTN
)VM_MINOR_VERSION
571 L
"EBC Debugger Version - %d.%d\n",
572 (UINTN
)EBC_DEBUGGER_MAJOR_VERSION
,
573 (UINTN
)EBC_DEBUGGER_MINOR_VERSION
579 InitDebuggerPrivateData (&mDebuggerPrivate
, ExceptionType
, SystemContext
, mInitialized
);
582 // EDBPrint basic info
584 PrintExceptionReason (&mDebuggerPrivate
, ExceptionType
, SystemContext
, mInitialized
);
586 EdbShowDisasm (&mDebuggerPrivate
, SystemContext
);
587 // EFI_BREAKPOINT ();
591 // Interactive with user
593 EDBPrint (L
"\nPlease enter command now, \'h\' for help.\n");
594 EDBPrint (L
"(Using <Command> -b <...> to enable page break.)\n");
599 // Dispatch each command
605 Input (L
"\n\r" EFI_DEBUG_PROMPT_STRING
, InputBuffer
, EFI_DEBUG_INPUS_BUFFER_SIZE
);
611 DebuggerCommand
= MatchDebuggerCommand (InputBuffer
, &CommandArg
);
612 if (DebuggerCommand
== NULL
) {
613 EDBPrint (L
"ERROR: Command not found!\n");
620 if (CommandArg
!= NULL
) {
621 if (StriCmp (CommandArg
, L
"-b") == 0) {
622 CommandArg
= StrGetNextTokenLine (L
" ");
623 mDebuggerPrivate
.EnablePageBreak
= TRUE
;
630 DebugStatus
= DebuggerCommand (CommandArg
, &mDebuggerPrivate
, ExceptionType
, SystemContext
);
631 mDebuggerPrivate
.EnablePageBreak
= FALSE
;
634 // Check command return status
636 if (DebugStatus
== EFI_DEBUG_RETURN
) {
637 mInitialized
= FALSE
;
639 } else if (DebugStatus
== EFI_DEBUG_BREAK
) {
641 } else if (DebugStatus
== EFI_DEBUG_CONTINUE
) {
649 // Deinit Private Data
651 DeinitDebuggerPrivateData (&mDebuggerPrivate
, ExceptionType
, SystemContext
, mInitialized
);
653 DEBUG ((DEBUG_ERROR
, "Goodbye EBC Debugger!\n"));