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
31 EFI_DEBUGGER_CONFIGURATION_VERSION
,
33 }, // DebuggerConfiguration
34 NULL
, // DebugImageInfoTableHeader
36 NULL
, // PciRootBridgeIo
37 mDebuggerCommandSet
, // DebuggerCommandSet
38 {0}, // DebuggerSymbolContext
39 0, // DebuggerBreakpointCount
40 {{0}}, // DebuggerBreakpointContext
41 0, // CallStackEntryCount
42 {{0}}, // CallStackEntry
47 0, // InstructionScope
48 EFI_DEBUG_DEFAULT_INSTRUCTION_NUMBER
, // InstructionNumber
49 EFI_DEBUG_FLAG_EBC_BOE
| EFI_DEBUG_FLAG_EBC_BOT
, // FeatureFlags
51 FALSE
, // EnablePageBreak
55 CHAR16
*mExceptionStr
[] = {
56 L
"EXCEPT_EBC_UNDEFINED",
57 L
"EXCEPT_EBC_DIVIDE_ERROR",
59 L
"EXCEPT_EBC_BREAKPOINT",
60 L
"EXCEPT_EBC_OVERFLOW",
61 L
"EXCEPT_EBC_INVALID_OPCODE",
62 L
"EXCEPT_EBC_STACK_FAULT",
63 L
"EXCEPT_EBC_ALIGNMENT_CHECK",
64 L
"EXCEPT_EBC_INSTRUCTION_ENCODING",
65 L
"EXCEPT_EBC_BAD_BREAK",
66 L
"EXCEPT_EBC_SINGLE_STEP",
70 EdbClearAllBreakpoint (
71 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
78 Clear all the breakpoint
82 DebuggerPrivate - EBC Debugger private data structure
83 NeedRemove - Whether need to remove all the breakpoint
94 // Patch all the breakpoint
96 for (Index
= 0; (Index
< DebuggerPrivate
->DebuggerBreakpointCount
) && (Index
< EFI_DEBUGGER_BREAKPOINT_MAX
); Index
++) {
97 if (DebuggerPrivate
->DebuggerBreakpointContext
[Index
].State
) {
99 (VOID
*)(UINTN
)DebuggerPrivate
->DebuggerBreakpointContext
[Index
].BreakpointAddress
,
100 &DebuggerPrivate
->DebuggerBreakpointContext
[Index
].OldInstruction
,
107 // Zero Breakpoint context, if need to remove all breakpoint
110 DebuggerPrivate
->DebuggerBreakpointCount
= 0;
111 ZeroMem (DebuggerPrivate
->DebuggerBreakpointContext
, sizeof(DebuggerPrivate
->DebuggerBreakpointContext
));
121 EdbSetAllBreakpoint (
122 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
128 Set all the breakpoint
132 DebuggerPrivate - EBC Debugger private data structure
144 // Set all the breakpoint (BREAK(3) : 0x0300)
147 for (Index
= 0; (Index
< DebuggerPrivate
->DebuggerBreakpointCount
) && (Index
< EFI_DEBUGGER_BREAKPOINT_MAX
); Index
++) {
148 if (DebuggerPrivate
->DebuggerBreakpointContext
[Index
].State
) {
150 (VOID
*)(UINTN
)DebuggerPrivate
->DebuggerBreakpointContext
[Index
].BreakpointAddress
,
158 // Check if current break is caused by breakpoint set.
159 // If so, we need to patch memory back to let user see the real memory.
161 if (DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
].BreakpointAddress
!= 0) {
163 (VOID
*)(UINTN
)DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
].BreakpointAddress
,
164 &DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
].OldInstruction
,
167 DebuggerPrivate
->StatusFlags
&= ~EFI_DEBUG_FLAG_EBC_B_BP
;
178 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
179 IN EFI_SYSTEM_CONTEXT SystemContext
185 Check all the breakpoint, if match, then set status flag, and record current breakpoint.
186 Then clear all breakpoint to let user see a clean memory
190 DebuggerPrivate - EBC Debugger private data structure
191 SystemContext - EBC system context.
201 BOOLEAN IsHitBreakpoint
;
204 // Roll back IP for breakpoint instruction (BREAK(3) : 0x0300)
206 Address
= SystemContext
.SystemContextEbc
->Ip
- sizeof(UINT16
);
209 // Check if the breakpoint is hit
211 IsHitBreakpoint
= FALSE
;
212 for (Index
= 0; (Index
< DebuggerPrivate
->DebuggerBreakpointCount
) && (Index
< EFI_DEBUGGER_BREAKPOINT_MAX
); Index
++) {
213 if ((DebuggerPrivate
->DebuggerBreakpointContext
[Index
].BreakpointAddress
== Address
) &&
214 (DebuggerPrivate
->DebuggerBreakpointContext
[Index
].State
)) {
215 IsHitBreakpoint
= TRUE
;
220 if (IsHitBreakpoint
) {
222 // If hit, record current breakpoint
224 DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
] = DebuggerPrivate
->DebuggerBreakpointContext
[Index
];
225 DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
].State
= TRUE
;
227 // Update: IP and Instruction (NOTE: Since we not allow set breakpoint to BREAK 3, this update is safe)
229 SystemContext
.SystemContextEbc
->Ip
= Address
;
233 DebuggerPrivate
->StatusFlags
|= EFI_DEBUG_FLAG_EBC_BP
;
236 // If not hit, check whether current IP is in breakpoint list,
237 // because STEP will be triggered before execute the instruction.
238 // We should not patch it in de-init.
240 Address
= SystemContext
.SystemContextEbc
->Ip
;
243 // Check if the breakpoint is hit
245 IsHitBreakpoint
= FALSE
;
246 for (Index
= 0; (Index
< DebuggerPrivate
->DebuggerBreakpointCount
) && (Index
< EFI_DEBUGGER_BREAKPOINT_MAX
); Index
++) {
247 if ((DebuggerPrivate
->DebuggerBreakpointContext
[Index
].BreakpointAddress
== Address
) &&
248 (DebuggerPrivate
->DebuggerBreakpointContext
[Index
].State
)) {
249 IsHitBreakpoint
= TRUE
;
254 if (IsHitBreakpoint
) {
256 // If hit, record current breakpoint
258 DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
] = DebuggerPrivate
->DebuggerBreakpointContext
[Index
];
259 DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
].State
= TRUE
;
261 // Do not set Breakpoint flag. We record the address here just let it not patch breakpoint address when de-init.
265 // Zero current breakpoint
268 &DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
],
269 sizeof(DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
])
282 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
292 DebuggerPrivate - EBC Debugger private data structure
300 EFI_DEBUGGER_SYMBOL_CONTEXT
*DebuggerSymbolContext
;
301 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
306 // Go throuth each object
308 DebuggerSymbolContext
= &DebuggerPrivate
->DebuggerSymbolContext
;
309 for (ObjectIndex
= 0; ObjectIndex
< DebuggerSymbolContext
->ObjectCount
; ObjectIndex
++) {
310 Object
= &DebuggerSymbolContext
->Object
[ObjectIndex
];
312 // Go throuth each entry
314 for (Index
= 0; Index
< Object
->EntryCount
; Index
++) {
315 ZeroMem (&Object
->Entry
[Index
], sizeof(Object
->Entry
[Index
]));
317 ZeroMem (Object
->Name
, sizeof(Object
->Name
));
318 Object
->EntryCount
= 0;
319 Object
->BaseAddress
= 0;
320 Object
->StartEntrypointRVA
= 0;
321 Object
->MainEntrypointRVA
= 0;
323 // Free source buffer
325 for (Index
= 0; Object
->SourceBuffer
[Index
] != NULL
; Index
++) {
326 gBS
->FreePool (Object
->SourceBuffer
[Index
]);
327 Object
->SourceBuffer
[Index
] = NULL
;
330 DebuggerSymbolContext
->ObjectCount
= 0;
336 InitDebuggerPrivateData (
337 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
338 IN EFI_EXCEPTION_TYPE ExceptionType
,
339 IN EFI_SYSTEM_CONTEXT SystemContext
,
340 IN BOOLEAN Initialized
346 Initialize Debugger private data structure
350 DebuggerPrivate - EBC Debugger private data structure
351 InterruptType - Interrupt type.
352 SystemContext - EBC system context.
353 Initialized - Whether the DebuggerPrivate data is initialized.
362 // clear STEP flag in any condition.
364 if (SystemContext
.SystemContextEbc
->Flags
& ((UINT64
) VMFLAGS_STEP
)) {
365 SystemContext
.SystemContextEbc
->Flags
&= ~((UINT64
) VMFLAGS_STEP
);
370 // Initialize everything
372 DebuggerPrivate
->InstructionNumber
= EFI_DEBUG_DEFAULT_INSTRUCTION_NUMBER
;
374 DebuggerPrivate
->DebuggerBreakpointCount
= 0;
375 ZeroMem (DebuggerPrivate
->DebuggerBreakpointContext
, sizeof(DebuggerPrivate
->DebuggerBreakpointContext
));
377 // DebuggerPrivate->StatusFlags = 0;
379 DebuggerPrivate
->DebuggerSymbolContext
.DisplaySymbol
= TRUE
;
380 DebuggerPrivate
->DebuggerSymbolContext
.DisplayCodeOnly
= FALSE
;
381 DebuggerPrivate
->DebuggerSymbolContext
.ObjectCount
= 0;
384 // Already initialized, just check Breakpoint here.
386 if (ExceptionType
== EXCEPT_EBC_BREAKPOINT
) {
387 EdbCheckBreakpoint (DebuggerPrivate
, SystemContext
);
391 // Clear all breakpoint
393 EdbClearAllBreakpoint (DebuggerPrivate
, FALSE
);
397 // Set Scope to currentl IP. (Note: Check Breakpoint may change Ip)
399 DebuggerPrivate
->InstructionScope
= SystemContext
.SystemContextEbc
->Ip
;
408 DeinitDebuggerPrivateData (
409 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
410 IN EFI_EXCEPTION_TYPE ExceptionType
,
411 IN EFI_SYSTEM_CONTEXT SystemContext
,
412 IN BOOLEAN Initialized
418 De-initialize Debugger private data structure
422 DebuggerPrivate - EBC Debugger private data structure
423 InterruptType - Interrupt type.
424 SystemContext - EBC system context.
425 Initialized - Whether the DebuggerPrivate data is initialized.
435 // If it does not want initialized state, de-init everything
437 DebuggerPrivate
->FeatureFlags
= EFI_DEBUG_FLAG_EBC_BOE
| EFI_DEBUG_FLAG_EBC_BOT
;
438 DebuggerPrivate
->CallStackEntryCount
= 0;
439 DebuggerPrivate
->TraceEntryCount
= 0;
440 ZeroMem (DebuggerPrivate
->CallStackEntry
, sizeof(DebuggerPrivate
->CallStackEntry
));
441 ZeroMem (DebuggerPrivate
->TraceEntry
, sizeof(DebuggerPrivate
->TraceEntry
));
444 // Clear all breakpoint
446 EdbClearAllBreakpoint (DebuggerPrivate
, TRUE
);
451 EdbClearSymbol (DebuggerPrivate
);
454 // If it wants to keep initialized state, just set breakpoint.
456 EdbSetAllBreakpoint (DebuggerPrivate
);
460 // Clear Step context
462 ZeroMem (&mDebuggerPrivate
.StepContext
, sizeof(mDebuggerPrivate
.StepContext
));
463 DebuggerPrivate
->StatusFlags
= 0;
472 PrintExceptionReason (
473 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
474 IN EFI_EXCEPTION_TYPE ExceptionType
,
475 IN EFI_SYSTEM_CONTEXT SystemContext
,
476 IN BOOLEAN Initialized
482 Print the reason of current break to EbcDebugger.
486 DebuggerPrivate - EBC Debugger private data structure
487 InterruptType - Interrupt type.
488 SystemContext - EBC system context.
489 Initialized - Whether the DebuggerPrivate data is initialized.
498 // Print break status
500 if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_GT
) == EFI_DEBUG_FLAG_EBC_GT
) {
501 EDBPrint (L
"Break on GoTil\n");
502 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_BOC
) == EFI_DEBUG_FLAG_EBC_BOC
) {
503 EDBPrint (L
"Break on CALL\n");
504 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_BOCX
) == EFI_DEBUG_FLAG_EBC_BOCX
) {
505 EDBPrint (L
"Break on CALLEX\n");
506 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_BOR
) == EFI_DEBUG_FLAG_EBC_BOR
) {
507 EDBPrint (L
"Break on RET\n");
508 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_BOE
) == EFI_DEBUG_FLAG_EBC_BOE
) {
509 EDBPrint (L
"Break on Entrypoint\n");
510 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_BOT
) == EFI_DEBUG_FLAG_EBC_BOT
) {
511 EDBPrint (L
"Break on Thunk\n");
512 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_STEPOVER
) == EFI_DEBUG_FLAG_EBC_STEPOVER
) {
513 EDBPrint (L
"Break on StepOver\n");
514 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_STEPOUT
) == EFI_DEBUG_FLAG_EBC_STEPOUT
) {
515 EDBPrint (L
"Break on StepOut\n");
516 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_BP
) == EFI_DEBUG_FLAG_EBC_BP
) {
517 EDBPrint (L
"Break on Breakpoint\n");
518 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_BOK
) == EFI_DEBUG_FLAG_EBC_BOK
) {
519 EDBPrint (L
"Break on Key\n");
521 EDBPrint (L
"Exception Type - %x", (UINTN
)ExceptionType
);
522 if ((ExceptionType
>= EXCEPT_EBC_UNDEFINED
) && (ExceptionType
<= EXCEPT_EBC_STEP
)) {
523 EDBPrint (L
" (%s)\n", mExceptionStr
[ExceptionType
]);
534 EdbExceptionHandler (
535 IN EFI_EXCEPTION_TYPE ExceptionType
,
536 IN OUT EFI_SYSTEM_CONTEXT SystemContext
542 The default Exception Callback for the VM interpreter.
543 In this function, we report status code, and print debug information
544 about EBC_CONTEXT, then dead loop.
548 InterruptType - Interrupt type.
549 SystemContext - EBC system context.
557 CHAR16 InputBuffer
[EFI_DEBUG_INPUS_BUFFER_SIZE
];
559 EFI_DEBUGGER_COMMAND DebuggerCommand
;
560 EFI_DEBUG_STATUS DebugStatus
;
561 STATIC BOOLEAN mInitialized
= FALSE
;
563 DEBUG ((DEBUG_ERROR
, "Hello EBC Debugger!\n"));
570 L
"EBC Interpreter Version - %d.%d\n",
571 (UINTN
)VM_MAJOR_VERSION
,
572 (UINTN
)VM_MINOR_VERSION
575 L
"EBC Debugger Version - %d.%d\n",
576 (UINTN
)EBC_DEBUGGER_MAJOR_VERSION
,
577 (UINTN
)EBC_DEBUGGER_MINOR_VERSION
583 InitDebuggerPrivateData (&mDebuggerPrivate
, ExceptionType
, SystemContext
, mInitialized
);
586 // EDBPrint basic info
588 PrintExceptionReason (&mDebuggerPrivate
, ExceptionType
, SystemContext
, mInitialized
);
590 EdbShowDisasm (&mDebuggerPrivate
, SystemContext
);
591 // EFI_BREAKPOINT ();
595 // Interactive with user
597 EDBPrint (L
"\nPlease enter command now, \'h\' for help.\n");
598 EDBPrint (L
"(Using <Command> -b <...> to enable page break.)\n");
603 // Dispatch each command
609 Input (L
"\n\r" EFI_DEBUG_PROMPT_STRING
, InputBuffer
, EFI_DEBUG_INPUS_BUFFER_SIZE
);
615 DebuggerCommand
= MatchDebuggerCommand (InputBuffer
, &CommandArg
);
616 if (DebuggerCommand
== NULL
) {
617 EDBPrint (L
"ERROR: Command not found!\n");
624 if (CommandArg
!= NULL
) {
625 if (StriCmp (CommandArg
, L
"-b") == 0) {
626 CommandArg
= StrGetNextTokenLine (L
" ");
627 mDebuggerPrivate
.EnablePageBreak
= TRUE
;
634 DebugStatus
= DebuggerCommand (CommandArg
, &mDebuggerPrivate
, ExceptionType
, SystemContext
);
635 mDebuggerPrivate
.EnablePageBreak
= FALSE
;
638 // Check command return status
640 if (DebugStatus
== EFI_DEBUG_RETURN
) {
641 mInitialized
= FALSE
;
643 } else if (DebugStatus
== EFI_DEBUG_BREAK
) {
645 } else if (DebugStatus
== EFI_DEBUG_CONTINUE
) {
653 // Deinit Private Data
655 DeinitDebuggerPrivateData (&mDebuggerPrivate
, ExceptionType
, SystemContext
, mInitialized
);
657 DEBUG ((DEBUG_ERROR
, "Goodbye EBC Debugger!\n"));