3 Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
4 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.
17 EFI_DEBUGGER_PRIVATE_DATA mDebuggerPrivate
= {
18 EFI_DEBUGGER_SIGNATURE
, // Signature
20 (EBC_DEBUGGER_MAJOR_VERSION
<< 16) |
21 EBC_DEBUGGER_MINOR_VERSION
, // EfiDebuggerRevision
22 (VM_MAJOR_VERSION
<< 16) |
23 VM_MINOR_VERSION
, // EbcVmRevision
25 EFI_DEBUGGER_CONFIGURATION_VERSION
,
27 }, // DebuggerConfiguration
28 NULL
, // DebugImageInfoTableHeader
30 NULL
, // PciRootBridgeIo
31 mDebuggerCommandSet
, // DebuggerCommandSet
32 {0}, // DebuggerSymbolContext
33 0, // DebuggerBreakpointCount
34 {{0}}, // DebuggerBreakpointContext
35 0, // CallStackEntryCount
36 {{0}}, // CallStackEntry
41 0, // InstructionScope
42 EFI_DEBUG_DEFAULT_INSTRUCTION_NUMBER
, // InstructionNumber
43 EFI_DEBUG_FLAG_EBC_BOE
| EFI_DEBUG_FLAG_EBC_BOT
, // FeatureFlags
45 FALSE
, // EnablePageBreak
49 CHAR16
*mExceptionStr
[] = {
50 L
"EXCEPT_EBC_UNDEFINED",
51 L
"EXCEPT_EBC_DIVIDE_ERROR",
53 L
"EXCEPT_EBC_BREAKPOINT",
54 L
"EXCEPT_EBC_OVERFLOW",
55 L
"EXCEPT_EBC_INVALID_OPCODE",
56 L
"EXCEPT_EBC_STACK_FAULT",
57 L
"EXCEPT_EBC_ALIGNMENT_CHECK",
58 L
"EXCEPT_EBC_INSTRUCTION_ENCODING",
59 L
"EXCEPT_EBC_BAD_BREAK",
60 L
"EXCEPT_EBC_SINGLE_STEP",
65 Clear all the breakpoint.
67 @param DebuggerPrivate EBC Debugger private data structure
68 @param NeedRemove Whether need to remove all the breakpoint
72 EdbClearAllBreakpoint (
73 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
80 // Patch all the breakpoint
82 for (Index
= 0; (Index
< DebuggerPrivate
->DebuggerBreakpointCount
) && (Index
< EFI_DEBUGGER_BREAKPOINT_MAX
); Index
++) {
83 if (DebuggerPrivate
->DebuggerBreakpointContext
[Index
].State
) {
85 (VOID
*)(UINTN
)DebuggerPrivate
->DebuggerBreakpointContext
[Index
].BreakpointAddress
,
86 &DebuggerPrivate
->DebuggerBreakpointContext
[Index
].OldInstruction
,
93 // Zero Breakpoint context, if need to remove all breakpoint
96 DebuggerPrivate
->DebuggerBreakpointCount
= 0;
97 ZeroMem (DebuggerPrivate
->DebuggerBreakpointContext
, sizeof(DebuggerPrivate
->DebuggerBreakpointContext
));
108 Set all the breakpoint.
110 @param DebuggerPrivate EBC Debugger private data structure
114 EdbSetAllBreakpoint (
115 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
122 // Set all the breakpoint (BREAK(3) : 0x0300)
125 for (Index
= 0; (Index
< DebuggerPrivate
->DebuggerBreakpointCount
) && (Index
< EFI_DEBUGGER_BREAKPOINT_MAX
); Index
++) {
126 if (DebuggerPrivate
->DebuggerBreakpointContext
[Index
].State
) {
128 (VOID
*)(UINTN
)DebuggerPrivate
->DebuggerBreakpointContext
[Index
].BreakpointAddress
,
136 // Check if current break is caused by breakpoint set.
137 // If so, we need to patch memory back to let user see the real memory.
139 if (DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
].BreakpointAddress
!= 0) {
141 (VOID
*)(UINTN
)DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
].BreakpointAddress
,
142 &DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
].OldInstruction
,
145 DebuggerPrivate
->StatusFlags
&= ~EFI_DEBUG_FLAG_EBC_B_BP
;
156 Check all the breakpoint, if match, then set status flag, and record current breakpoint.
157 Then clear all breakpoint to let user see a clean memory
159 @param DebuggerPrivate EBC Debugger private data structure
160 @param SystemContext EBC system context.
165 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
166 IN EFI_SYSTEM_CONTEXT SystemContext
171 BOOLEAN IsHitBreakpoint
;
174 // Roll back IP for breakpoint instruction (BREAK(3) : 0x0300)
176 Address
= SystemContext
.SystemContextEbc
->Ip
- sizeof(UINT16
);
179 // Check if the breakpoint is hit
181 IsHitBreakpoint
= FALSE
;
182 for (Index
= 0; (Index
< DebuggerPrivate
->DebuggerBreakpointCount
) && (Index
< EFI_DEBUGGER_BREAKPOINT_MAX
); Index
++) {
183 if ((DebuggerPrivate
->DebuggerBreakpointContext
[Index
].BreakpointAddress
== Address
) &&
184 (DebuggerPrivate
->DebuggerBreakpointContext
[Index
].State
)) {
185 IsHitBreakpoint
= TRUE
;
190 if (IsHitBreakpoint
) {
192 // If hit, record current breakpoint
194 DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
] = DebuggerPrivate
->DebuggerBreakpointContext
[Index
];
195 DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
].State
= TRUE
;
197 // Update: IP and Instruction (NOTE: Since we not allow set breakpoint to BREAK 3, this update is safe)
199 SystemContext
.SystemContextEbc
->Ip
= Address
;
203 DebuggerPrivate
->StatusFlags
|= EFI_DEBUG_FLAG_EBC_BP
;
206 // If not hit, check whether current IP is in breakpoint list,
207 // because STEP will be triggered before execute the instruction.
208 // We should not patch it in de-init.
210 Address
= SystemContext
.SystemContextEbc
->Ip
;
213 // Check if the breakpoint is hit
215 IsHitBreakpoint
= FALSE
;
216 for (Index
= 0; (Index
< DebuggerPrivate
->DebuggerBreakpointCount
) && (Index
< EFI_DEBUGGER_BREAKPOINT_MAX
); Index
++) {
217 if ((DebuggerPrivate
->DebuggerBreakpointContext
[Index
].BreakpointAddress
== Address
) &&
218 (DebuggerPrivate
->DebuggerBreakpointContext
[Index
].State
)) {
219 IsHitBreakpoint
= TRUE
;
224 if (IsHitBreakpoint
) {
226 // If hit, record current breakpoint
228 DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
] = DebuggerPrivate
->DebuggerBreakpointContext
[Index
];
229 DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
].State
= TRUE
;
231 // Do not set Breakpoint flag. We record the address here just let it not patch breakpoint address when de-init.
235 // Zero current breakpoint
238 &DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
],
239 sizeof(DebuggerPrivate
->DebuggerBreakpointContext
[EFI_DEBUGGER_BREAKPOINT_MAX
])
251 clear all the symbol.
253 @param DebuggerPrivate EBC Debugger private data structure
258 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
261 EFI_DEBUGGER_SYMBOL_CONTEXT
*DebuggerSymbolContext
;
262 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
267 // Go throuth each object
269 DebuggerSymbolContext
= &DebuggerPrivate
->DebuggerSymbolContext
;
270 for (ObjectIndex
= 0; ObjectIndex
< DebuggerSymbolContext
->ObjectCount
; ObjectIndex
++) {
271 Object
= &DebuggerSymbolContext
->Object
[ObjectIndex
];
273 // Go throuth each entry
275 for (Index
= 0; Index
< Object
->EntryCount
; Index
++) {
276 ZeroMem (&Object
->Entry
[Index
], sizeof(Object
->Entry
[Index
]));
278 ZeroMem (Object
->Name
, sizeof(Object
->Name
));
279 Object
->EntryCount
= 0;
280 Object
->BaseAddress
= 0;
281 Object
->StartEntrypointRVA
= 0;
282 Object
->MainEntrypointRVA
= 0;
284 // Free source buffer
286 for (Index
= 0; Object
->SourceBuffer
[Index
] != NULL
; Index
++) {
287 gBS
->FreePool (Object
->SourceBuffer
[Index
]);
288 Object
->SourceBuffer
[Index
] = NULL
;
291 DebuggerSymbolContext
->ObjectCount
= 0;
298 Initialize Debugger private data structure
300 @param DebuggerPrivate EBC Debugger private data structure
301 @param ExceptionType Exception type.
302 @param SystemContext EBC system context.
303 @param Initialized Whether the DebuggerPrivate data is initialized.
307 InitDebuggerPrivateData (
308 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
309 IN EFI_EXCEPTION_TYPE ExceptionType
,
310 IN EFI_SYSTEM_CONTEXT SystemContext
,
311 IN BOOLEAN Initialized
315 // clear STEP flag in any condition.
317 if (SystemContext
.SystemContextEbc
->Flags
& ((UINT64
) VMFLAGS_STEP
)) {
318 SystemContext
.SystemContextEbc
->Flags
&= ~((UINT64
) VMFLAGS_STEP
);
323 // Initialize everything
325 DebuggerPrivate
->InstructionNumber
= EFI_DEBUG_DEFAULT_INSTRUCTION_NUMBER
;
327 DebuggerPrivate
->DebuggerBreakpointCount
= 0;
328 ZeroMem (DebuggerPrivate
->DebuggerBreakpointContext
, sizeof(DebuggerPrivate
->DebuggerBreakpointContext
));
330 // DebuggerPrivate->StatusFlags = 0;
332 DebuggerPrivate
->DebuggerSymbolContext
.DisplaySymbol
= TRUE
;
333 DebuggerPrivate
->DebuggerSymbolContext
.DisplayCodeOnly
= FALSE
;
334 DebuggerPrivate
->DebuggerSymbolContext
.ObjectCount
= 0;
337 // Already initialized, just check Breakpoint here.
339 if (ExceptionType
== EXCEPT_EBC_BREAKPOINT
) {
340 EdbCheckBreakpoint (DebuggerPrivate
, SystemContext
);
344 // Clear all breakpoint
346 EdbClearAllBreakpoint (DebuggerPrivate
, FALSE
);
350 // Set Scope to currentl IP. (Note: Check Breakpoint may change Ip)
352 DebuggerPrivate
->InstructionScope
= SystemContext
.SystemContextEbc
->Ip
;
362 De-initialize Debugger private data structure.
364 @param DebuggerPrivate EBC Debugger private data structure
365 @param ExceptionType Exception type.
366 @param SystemContext EBC system context.
367 @param Initialized Whether the DebuggerPrivate data is initialized.
371 DeinitDebuggerPrivateData (
372 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
373 IN EFI_EXCEPTION_TYPE ExceptionType
,
374 IN EFI_SYSTEM_CONTEXT SystemContext
,
375 IN BOOLEAN Initialized
380 // If it does not want initialized state, de-init everything
382 DebuggerPrivate
->FeatureFlags
= EFI_DEBUG_FLAG_EBC_BOE
| EFI_DEBUG_FLAG_EBC_BOT
;
383 DebuggerPrivate
->CallStackEntryCount
= 0;
384 DebuggerPrivate
->TraceEntryCount
= 0;
385 ZeroMem (DebuggerPrivate
->CallStackEntry
, sizeof(DebuggerPrivate
->CallStackEntry
));
386 ZeroMem (DebuggerPrivate
->TraceEntry
, sizeof(DebuggerPrivate
->TraceEntry
));
389 // Clear all breakpoint
391 EdbClearAllBreakpoint (DebuggerPrivate
, TRUE
);
396 EdbClearSymbol (DebuggerPrivate
);
399 // If it wants to keep initialized state, just set breakpoint.
401 EdbSetAllBreakpoint (DebuggerPrivate
);
405 // Clear Step context
407 ZeroMem (&mDebuggerPrivate
.StepContext
, sizeof(mDebuggerPrivate
.StepContext
));
408 DebuggerPrivate
->StatusFlags
= 0;
418 Print the reason of current break to EbcDebugger.
420 @param DebuggerPrivate EBC Debugger private data structure
421 @param ExceptionType Exception type.
422 @param SystemContext EBC system context.
423 @param Initialized Whether the DebuggerPrivate data is initialized.
427 PrintExceptionReason (
428 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
429 IN EFI_EXCEPTION_TYPE ExceptionType
,
430 IN EFI_SYSTEM_CONTEXT SystemContext
,
431 IN BOOLEAN Initialized
435 // Print break status
437 if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_GT
) == EFI_DEBUG_FLAG_EBC_GT
) {
438 EDBPrint (L
"Break on GoTil\n");
439 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_BOC
) == EFI_DEBUG_FLAG_EBC_BOC
) {
440 EDBPrint (L
"Break on CALL\n");
441 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_BOCX
) == EFI_DEBUG_FLAG_EBC_BOCX
) {
442 EDBPrint (L
"Break on CALLEX\n");
443 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_BOR
) == EFI_DEBUG_FLAG_EBC_BOR
) {
444 EDBPrint (L
"Break on RET\n");
445 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_BOE
) == EFI_DEBUG_FLAG_EBC_BOE
) {
446 EDBPrint (L
"Break on Entrypoint\n");
447 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_BOT
) == EFI_DEBUG_FLAG_EBC_BOT
) {
448 EDBPrint (L
"Break on Thunk\n");
449 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_STEPOVER
) == EFI_DEBUG_FLAG_EBC_STEPOVER
) {
450 EDBPrint (L
"Break on StepOver\n");
451 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_STEPOUT
) == EFI_DEBUG_FLAG_EBC_STEPOUT
) {
452 EDBPrint (L
"Break on StepOut\n");
453 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_BP
) == EFI_DEBUG_FLAG_EBC_BP
) {
454 EDBPrint (L
"Break on Breakpoint\n");
455 } else if ((DebuggerPrivate
->StatusFlags
& EFI_DEBUG_FLAG_EBC_BOK
) == EFI_DEBUG_FLAG_EBC_BOK
) {
456 EDBPrint (L
"Break on Key\n");
458 EDBPrint (L
"Exception Type - %x", (UINTN
)ExceptionType
);
459 if ((ExceptionType
>= EXCEPT_EBC_UNDEFINED
) && (ExceptionType
<= EXCEPT_EBC_STEP
)) {
460 EDBPrint (L
" (%s)\n", mExceptionStr
[ExceptionType
]);
471 The default Exception Callback for the VM interpreter.
472 In this function, we report status code, and print debug information
473 about EBC_CONTEXT, then dead loop.
475 @param ExceptionType Exception type.
476 @param SystemContext EBC system context.
481 EdbExceptionHandler (
482 IN EFI_EXCEPTION_TYPE ExceptionType
,
483 IN OUT EFI_SYSTEM_CONTEXT SystemContext
486 CHAR16 InputBuffer
[EFI_DEBUG_INPUS_BUFFER_SIZE
];
488 EFI_DEBUGGER_COMMAND DebuggerCommand
;
489 EFI_DEBUG_STATUS DebugStatus
;
490 STATIC BOOLEAN mInitialized
;
492 mInitialized
= FALSE
;
494 DEBUG ((DEBUG_ERROR
, "Hello EBC Debugger!\n"));
501 L
"EBC Interpreter Version - %d.%d\n",
502 (UINTN
)VM_MAJOR_VERSION
,
503 (UINTN
)VM_MINOR_VERSION
506 L
"EBC Debugger Version - %d.%d\n",
507 (UINTN
)EBC_DEBUGGER_MAJOR_VERSION
,
508 (UINTN
)EBC_DEBUGGER_MINOR_VERSION
514 InitDebuggerPrivateData (&mDebuggerPrivate
, ExceptionType
, SystemContext
, mInitialized
);
517 // EDBPrint basic info
519 PrintExceptionReason (&mDebuggerPrivate
, ExceptionType
, SystemContext
, mInitialized
);
521 EdbShowDisasm (&mDebuggerPrivate
, SystemContext
);
522 // EFI_BREAKPOINT ();
526 // Interactive with user
528 EDBPrint (L
"\nPlease enter command now, \'h\' for help.\n");
529 EDBPrint (L
"(Using <Command> -b <...> to enable page break.)\n");
534 // Dispatch each command
540 Input (L
"\n\r" EFI_DEBUG_PROMPT_STRING
, InputBuffer
, EFI_DEBUG_INPUS_BUFFER_SIZE
);
546 DebuggerCommand
= MatchDebuggerCommand (InputBuffer
, &CommandArg
);
547 if (DebuggerCommand
== NULL
) {
548 EDBPrint (L
"ERROR: Command not found!\n");
555 if (CommandArg
!= NULL
) {
556 if (StriCmp (CommandArg
, L
"-b") == 0) {
557 CommandArg
= StrGetNextTokenLine (L
" ");
558 mDebuggerPrivate
.EnablePageBreak
= TRUE
;
565 DebugStatus
= DebuggerCommand (CommandArg
, &mDebuggerPrivate
, ExceptionType
, SystemContext
);
566 mDebuggerPrivate
.EnablePageBreak
= FALSE
;
569 // Check command return status
571 if (DebugStatus
== EFI_DEBUG_RETURN
) {
572 mInitialized
= FALSE
;
574 } else if (DebugStatus
== EFI_DEBUG_BREAK
) {
576 } else if (DebugStatus
== EFI_DEBUG_CONTINUE
) {
584 // Deinit Private Data
586 DeinitDebuggerPrivateData (&mDebuggerPrivate
, ExceptionType
, SystemContext
, mInitialized
);
588 DEBUG ((DEBUG_ERROR
, "Goodbye EBC Debugger!\n"));