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 UINT16 OldInstruction
;
198 BOOLEAN IsHitBreakpoint
;
201 // Roll back IP for breakpoint instruction (BREAK(3) : 0x0300)
203 Address
= SystemContext
.SystemContextEbc
->Ip
- sizeof(UINT16
);
206 // Check if the breakpoint is hit
208 IsHitBreakpoint
= FALSE
;
209 for (Index
= 0; (Index
< DebuggerPrivate
->DebuggerBreakpointCount
) && (Index
< EFI_DEBUGGER_BREAKPOINT_MAX
); Index
++) {
210 if ((DebuggerPrivate
->DebuggerBreakpointContext
[Index
].BreakpointAddress
== Address
) &&
211 (DebuggerPrivate
->DebuggerBreakpointContext
[Index
].State
)) {
212 OldInstruction
= (UINT16
)DebuggerPrivate
->DebuggerBreakpointContext
[Index
].OldInstruction
;
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 // Update: IP and Instruction (NOTE: Since we not allow set breakpoint to BREAK 3, this update is safe)
227 SystemContext
.SystemContextEbc
->Ip
= Address
;
231 DebuggerPrivate
->StatusFlags
|= EFI_DEBUG_FLAG_EBC_BP
;
234 // If not hit, check whether current IP is in breakpoint list,
235 // because STEP will be triggered before execute the instruction.
236 // We should not patch it in de-init.
238 Address
= SystemContext
.SystemContextEbc
->Ip
;
241 // Check if the breakpoint is hit
243 IsHitBreakpoint
= FALSE
;
244 for (Index
= 0; (Index
< DebuggerPrivate
->DebuggerBreakpointCount
) && (Index
< EFI_DEBUGGER_BREAKPOINT_MAX
); Index
++) {
245 if ((DebuggerPrivate
->DebuggerBreakpointContext
[Index
].BreakpointAddress
== Address
) &&
246 (DebuggerPrivate
->DebuggerBreakpointContext
[Index
].State
)) {
247 OldInstruction
= (UINT16
)DebuggerPrivate
->DebuggerBreakpointContext
[Index
].OldInstruction
;
248 IsHitBreakpoint
= TRUE
;
253 if (IsHitBreakpoint
) {
255 // If hit, record current breakpoint
257 DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
] = DebuggerPrivate
->DebuggerBreakpointContext
[Index
];
258 DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
].State
= TRUE
;
260 // Do not set Breakpoint flag. We record the address here just let it not patch breakpoint address when de-init.
264 // Zero current breakpoint
267 &DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
],
268 sizeof(DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
])
281 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
291 DebuggerPrivate - EBC Debugger private data structure
299 EFI_DEBUGGER_SYMBOL_CONTEXT
*DebuggerSymbolContext
;
300 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
305 // Go throuth each object
307 DebuggerSymbolContext
= &DebuggerPrivate
->DebuggerSymbolContext
;
308 for (ObjectIndex
= 0; ObjectIndex
< DebuggerSymbolContext
->ObjectCount
; ObjectIndex
++) {
309 Object
= &DebuggerSymbolContext
->Object
[ObjectIndex
];
311 // Go throuth each entry
313 for (Index
= 0; Index
< Object
->EntryCount
; Index
++) {
314 ZeroMem (&Object
->Entry
[Index
], sizeof(Object
->Entry
[Index
]));
316 ZeroMem (Object
->Name
, sizeof(Object
->Name
));
317 Object
->EntryCount
= 0;
318 Object
->BaseAddress
= 0;
319 Object
->StartEntrypointRVA
= 0;
320 Object
->MainEntrypointRVA
= 0;
322 // Free source buffer
324 for (Index
= 0; Object
->SourceBuffer
[Index
] != NULL
; Index
++) {
325 gBS
->FreePool (Object
->SourceBuffer
[Index
]);
326 Object
->SourceBuffer
[Index
] = NULL
;
329 DebuggerSymbolContext
->ObjectCount
= 0;
335 InitDebuggerPrivateData (
336 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
337 IN EFI_EXCEPTION_TYPE ExceptionType
,
338 IN EFI_SYSTEM_CONTEXT SystemContext
,
339 IN BOOLEAN Initialized
345 Initialize Debugger private data structure
349 DebuggerPrivate - EBC Debugger private data structure
350 InterruptType - Interrupt type.
351 SystemContext - EBC system context.
352 Initialized - Whether the DebuggerPrivate data is initialized.
361 // clear STEP flag in any condition.
363 if (SystemContext
.SystemContextEbc
->Flags
& ((UINT64
) VMFLAGS_STEP
)) {
364 SystemContext
.SystemContextEbc
->Flags
&= ~((UINT64
) VMFLAGS_STEP
);
369 // Initialize everything
371 DebuggerPrivate
->InstructionNumber
= EFI_DEBUG_DEFAULT_INSTRUCTION_NUMBER
;
373 DebuggerPrivate
->DebuggerBreakpointCount
= 0;
374 ZeroMem (DebuggerPrivate
->DebuggerBreakpointContext
, sizeof(DebuggerPrivate
->DebuggerBreakpointContext
));
376 // DebuggerPrivate->StatusFlags = 0;
378 DebuggerPrivate
->DebuggerSymbolContext
.DisplaySymbol
= TRUE
;
379 DebuggerPrivate
->DebuggerSymbolContext
.DisplayCodeOnly
= FALSE
;
380 DebuggerPrivate
->DebuggerSymbolContext
.ObjectCount
= 0;
383 // Already initialized, just check Breakpoint here.
385 if (ExceptionType
== EXCEPT_EBC_BREAKPOINT
) {
386 EdbCheckBreakpoint (DebuggerPrivate
, SystemContext
);
390 // Clear all breakpoint
392 EdbClearAllBreakpoint (DebuggerPrivate
, FALSE
);
396 // Set Scope to currentl IP. (Note: Check Breakpoint may change Ip)
398 DebuggerPrivate
->InstructionScope
= SystemContext
.SystemContextEbc
->Ip
;
407 DeinitDebuggerPrivateData (
408 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
409 IN EFI_EXCEPTION_TYPE ExceptionType
,
410 IN EFI_SYSTEM_CONTEXT SystemContext
,
411 IN BOOLEAN Initialized
417 De-initialize Debugger private data structure
421 DebuggerPrivate - EBC Debugger private data structure
422 InterruptType - Interrupt type.
423 SystemContext - EBC system context.
424 Initialized - Whether the DebuggerPrivate data is initialized.
434 // If it does not want initialized state, de-init everything
436 DebuggerPrivate
->FeatureFlags
= EFI_DEBUG_FLAG_EBC_BOE
| EFI_DEBUG_FLAG_EBC_BOT
;
437 DebuggerPrivate
->CallStackEntryCount
= 0;
438 DebuggerPrivate
->TraceEntryCount
= 0;
439 ZeroMem (DebuggerPrivate
->CallStackEntry
, sizeof(DebuggerPrivate
->CallStackEntry
));
440 ZeroMem (DebuggerPrivate
->TraceEntry
, sizeof(DebuggerPrivate
->TraceEntry
));
443 // Clear all breakpoint
445 EdbClearAllBreakpoint (DebuggerPrivate
, TRUE
);
450 EdbClearSymbol (DebuggerPrivate
);
453 // If it wants to keep initialized state, just set breakpoint.
455 EdbSetAllBreakpoint (DebuggerPrivate
);
459 // Clear Step context
461 ZeroMem (&mDebuggerPrivate
.StepContext
, sizeof(mDebuggerPrivate
.StepContext
));
462 DebuggerPrivate
->StatusFlags
= 0;
471 PrintExceptionReason (
472 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
473 IN EFI_EXCEPTION_TYPE ExceptionType
,
474 IN EFI_SYSTEM_CONTEXT SystemContext
,
475 IN BOOLEAN Initialized
481 Print the reason of current break to EbcDebugger.
485 DebuggerPrivate - EBC Debugger private data structure
486 InterruptType - Interrupt type.
487 SystemContext - EBC system context.
488 Initialized - Whether the DebuggerPrivate data is initialized.
497 // Print break status
499 if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_GT
) == EFI_DEBUG_FLAG_EBC_GT
) {
500 EDBPrint (L
"Break on GoTil\n");
501 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_BOC
) == EFI_DEBUG_FLAG_EBC_BOC
) {
502 EDBPrint (L
"Break on CALL\n");
503 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_BOCX
) == EFI_DEBUG_FLAG_EBC_BOCX
) {
504 EDBPrint (L
"Break on CALLEX\n");
505 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_BOR
) == EFI_DEBUG_FLAG_EBC_BOR
) {
506 EDBPrint (L
"Break on RET\n");
507 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_BOE
) == EFI_DEBUG_FLAG_EBC_BOE
) {
508 EDBPrint (L
"Break on Entrypoint\n");
509 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_BOT
) == EFI_DEBUG_FLAG_EBC_BOT
) {
510 EDBPrint (L
"Break on Thunk\n");
511 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_STEPOVER
) == EFI_DEBUG_FLAG_EBC_STEPOVER
) {
512 EDBPrint (L
"Break on StepOver\n");
513 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_STEPOUT
) == EFI_DEBUG_FLAG_EBC_STEPOUT
) {
514 EDBPrint (L
"Break on StepOut\n");
515 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_BP
) == EFI_DEBUG_FLAG_EBC_BP
) {
516 EDBPrint (L
"Break on Breakpoint\n");
517 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_BOK
) == EFI_DEBUG_FLAG_EBC_BOK
) {
518 EDBPrint (L
"Break on Key\n");
520 EDBPrint (L
"Exception Type - %x", (UINTN
)ExceptionType
);
521 if ((ExceptionType
>= EXCEPT_EBC_UNDEFINED
) && (ExceptionType
<= EXCEPT_EBC_STEP
)) {
522 EDBPrint (L
" (%s)\n", mExceptionStr
[ExceptionType
]);
533 EdbExceptionHandler (
534 IN EFI_EXCEPTION_TYPE ExceptionType
,
535 IN OUT EFI_SYSTEM_CONTEXT SystemContext
541 The default Exception Callback for the VM interpreter.
542 In this function, we report status code, and print debug information
543 about EBC_CONTEXT, then dead loop.
547 InterruptType - Interrupt type.
548 SystemContext - EBC system context.
556 CHAR16 InputBuffer
[EFI_DEBUG_INPUS_BUFFER_SIZE
];
558 EFI_DEBUGGER_COMMAND DebuggerCommand
;
559 EFI_DEBUG_STATUS DebugStatus
;
560 STATIC BOOLEAN mInitialized
= FALSE
;
562 DEBUG ((DEBUG_ERROR
, "Hello EBC Debugger!\n"));
569 L
"EBC Interpreter Version - %d.%d\n",
570 (UINTN
)VM_MAJOR_VERSION
,
571 (UINTN
)VM_MINOR_VERSION
574 L
"EBC Debugger Version - %d.%d\n",
575 (UINTN
)EBC_DEBUGGER_MAJOR_VERSION
,
576 (UINTN
)EBC_DEBUGGER_MINOR_VERSION
582 InitDebuggerPrivateData (&mDebuggerPrivate
, ExceptionType
, SystemContext
, mInitialized
);
585 // EDBPrint basic info
587 PrintExceptionReason (&mDebuggerPrivate
, ExceptionType
, SystemContext
, mInitialized
);
589 EdbShowDisasm (&mDebuggerPrivate
, SystemContext
);
590 // EFI_BREAKPOINT ();
594 // Interactive with user
596 EDBPrint (L
"\nPlease enter command now, \'h\' for help.\n");
597 EDBPrint (L
"(Using <Command> -b <...> to enable page break.)\n");
602 // Dispatch each command
608 Input (L
"\n\r" EFI_DEBUG_PROMPT_STRING
, InputBuffer
, EFI_DEBUG_INPUS_BUFFER_SIZE
);
614 DebuggerCommand
= MatchDebuggerCommand (InputBuffer
, &CommandArg
);
615 if (DebuggerCommand
== NULL
) {
616 EDBPrint (L
"ERROR: Command not found!\n");
623 if (CommandArg
!= NULL
) {
624 if (StriCmp (CommandArg
, L
"-b") == 0) {
625 CommandArg
= StrGetNextTokenLine (L
" ");
626 mDebuggerPrivate
.EnablePageBreak
= TRUE
;
633 DebugStatus
= DebuggerCommand (CommandArg
, &mDebuggerPrivate
, ExceptionType
, SystemContext
);
634 mDebuggerPrivate
.EnablePageBreak
= FALSE
;
637 // Check command return status
639 if (DebugStatus
== EFI_DEBUG_RETURN
) {
640 mInitialized
= FALSE
;
642 } else if (DebugStatus
== EFI_DEBUG_BREAK
) {
644 } else if (DebugStatus
== EFI_DEBUG_CONTINUE
) {
652 // Deinit Private Data
654 DeinitDebuggerPrivateData (&mDebuggerPrivate
, ExceptionType
, SystemContext
, mInitialized
);
656 DEBUG ((DEBUG_ERROR
, "Goodbye EBC Debugger!\n"));