]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/EbcDxe/EbcDebugger/Edb.c
MdeModulePkg/EbcDxe: add EBC Debugger configuration application
[mirror_edk2.git] / MdeModulePkg / Universal / EbcDxe / EbcDebugger / Edb.c
1 /*++
2
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
8
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.
11
12 Module Name:
13
14 Ebc.c
15
16 Abstract:
17
18 --*/
19
20 #include <Uefi.h>
21 #include "Edb.h"
22
23 EFI_DEBUGGER_PRIVATE_DATA mDebuggerPrivate = {
24 EFI_DEBUGGER_SIGNATURE, // Signature
25 IsaEbc, // Isa
26 (EBC_DEBUGGER_MAJOR_VERSION << 16) |
27 EBC_DEBUGGER_MINOR_VERSION, // EfiDebuggerRevision
28 (VM_MAJOR_VERSION << 16) |
29 VM_MINOR_VERSION, // EbcVmRevision
30 {
31 EFI_DEBUGGER_CONFIGURATION_VERSION,
32 &mDebuggerPrivate,
33 }, // DebuggerConfiguration
34 NULL, // DebugImageInfoTableHeader
35 NULL, // Vol
36 NULL, // PciRootBridgeIo
37 mDebuggerCommandSet, // DebuggerCommandSet
38 {0}, // DebuggerSymbolContext
39 0, // DebuggerBreakpointCount
40 {{0}}, // DebuggerBreakpointContext
41 0, // CallStackEntryCount
42 {{0}}, // CallStackEntry
43 0, // TraceEntryCount
44 {{0}}, // TraceEntry
45 {0}, // StepContext
46 {0}, // GoTilContext
47 0, // InstructionScope
48 EFI_DEBUG_DEFAULT_INSTRUCTION_NUMBER, // InstructionNumber
49 EFI_DEBUG_FLAG_EBC_BOE | EFI_DEBUG_FLAG_EBC_BOT, // FeatureFlags
50 0, // StatusFlags
51 FALSE, // EnablePageBreak
52 NULL // BreakEvent
53 };
54
55 CHAR16 *mExceptionStr[] = {
56 L"EXCEPT_EBC_UNDEFINED",
57 L"EXCEPT_EBC_DIVIDE_ERROR",
58 L"EXCEPT_EBC_DEBUG",
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",
67 };
68
69 VOID
70 EdbClearAllBreakpoint (
71 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
72 IN BOOLEAN NeedRemove
73 )
74 /*++
75
76 Routine Description:
77
78 Clear all the breakpoint
79
80 Arguments:
81
82 DebuggerPrivate - EBC Debugger private data structure
83 NeedRemove - Whether need to remove all the breakpoint
84
85 Returns:
86
87 None
88
89 --*/
90 {
91 UINTN Index;
92
93 //
94 // Patch all the breakpoint
95 //
96 for (Index = 0; (Index < DebuggerPrivate->DebuggerBreakpointCount) && (Index < EFI_DEBUGGER_BREAKPOINT_MAX); Index++) {
97 if (DebuggerPrivate->DebuggerBreakpointContext[Index].State) {
98 CopyMem (
99 (VOID *)(UINTN)DebuggerPrivate->DebuggerBreakpointContext[Index].BreakpointAddress,
100 &DebuggerPrivate->DebuggerBreakpointContext[Index].OldInstruction,
101 sizeof(UINT16)
102 );
103 }
104 }
105
106 //
107 // Zero Breakpoint context, if need to remove all breakpoint
108 //
109 if (NeedRemove) {
110 DebuggerPrivate->DebuggerBreakpointCount = 0;
111 ZeroMem (DebuggerPrivate->DebuggerBreakpointContext, sizeof(DebuggerPrivate->DebuggerBreakpointContext));
112 }
113
114 //
115 // Done
116 //
117 return ;
118 }
119
120 VOID
121 EdbSetAllBreakpoint (
122 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate
123 )
124 /*++
125
126 Routine Description:
127
128 Set all the breakpoint
129
130 Arguments:
131
132 DebuggerPrivate - EBC Debugger private data structure
133
134 Returns:
135
136 None
137
138 --*/
139 {
140 UINTN Index;
141 UINT16 Data16;
142
143 //
144 // Set all the breakpoint (BREAK(3) : 0x0300)
145 //
146 Data16 = 0x0300;
147 for (Index = 0; (Index < DebuggerPrivate->DebuggerBreakpointCount) && (Index < EFI_DEBUGGER_BREAKPOINT_MAX); Index++) {
148 if (DebuggerPrivate->DebuggerBreakpointContext[Index].State) {
149 CopyMem (
150 (VOID *)(UINTN)DebuggerPrivate->DebuggerBreakpointContext[Index].BreakpointAddress,
151 &Data16,
152 sizeof(UINT16)
153 );
154 }
155 }
156
157 //
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.
160 //
161 if (DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX].BreakpointAddress != 0) {
162 CopyMem (
163 (VOID *)(UINTN)DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX].BreakpointAddress,
164 &DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX].OldInstruction,
165 sizeof(UINT16)
166 );
167 DebuggerPrivate->StatusFlags &= ~EFI_DEBUG_FLAG_EBC_B_BP;
168 }
169
170 //
171 // Done
172 //
173 return ;
174 }
175
176 VOID
177 EdbCheckBreakpoint (
178 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
179 IN EFI_SYSTEM_CONTEXT SystemContext
180 )
181 /*++
182
183 Routine Description:
184
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
187
188 Arguments:
189
190 DebuggerPrivate - EBC Debugger private data structure
191 SystemContext - EBC system context.
192
193 Returns:
194
195 None
196
197 --*/
198 {
199 UINT64 Address;
200 UINTN Index;
201 BOOLEAN IsHitBreakpoint;
202
203 //
204 // Roll back IP for breakpoint instruction (BREAK(3) : 0x0300)
205 //
206 Address = SystemContext.SystemContextEbc->Ip - sizeof(UINT16);
207
208 //
209 // Check if the breakpoint is hit
210 //
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;
216 break;
217 }
218 }
219
220 if (IsHitBreakpoint) {
221 //
222 // If hit, record current breakpoint
223 //
224 DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX] = DebuggerPrivate->DebuggerBreakpointContext[Index];
225 DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX].State = TRUE;
226 //
227 // Update: IP and Instruction (NOTE: Since we not allow set breakpoint to BREAK 3, this update is safe)
228 //
229 SystemContext.SystemContextEbc->Ip = Address;
230 //
231 // Set Flags
232 //
233 DebuggerPrivate->StatusFlags |= EFI_DEBUG_FLAG_EBC_BP;
234 } else {
235 //
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.
239 //
240 Address = SystemContext.SystemContextEbc->Ip;
241
242 //
243 // Check if the breakpoint is hit
244 //
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;
250 break;
251 }
252 }
253
254 if (IsHitBreakpoint) {
255 //
256 // If hit, record current breakpoint
257 //
258 DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX] = DebuggerPrivate->DebuggerBreakpointContext[Index];
259 DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX].State = TRUE;
260 //
261 // Do not set Breakpoint flag. We record the address here just let it not patch breakpoint address when de-init.
262 //
263 } else {
264 //
265 // Zero current breakpoint
266 //
267 ZeroMem (
268 &DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX],
269 sizeof(DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX])
270 );
271 }
272 }
273
274 //
275 // Done
276 //
277 return ;
278 }
279
280 VOID
281 EdbClearSymbol (
282 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate
283 )
284 /*++
285
286 Routine Description:
287
288 clear all the symbol
289
290 Arguments:
291
292 DebuggerPrivate - EBC Debugger private data structure
293
294 Returns:
295
296 None
297
298 --*/
299 {
300 EFI_DEBUGGER_SYMBOL_CONTEXT *DebuggerSymbolContext;
301 EFI_DEBUGGER_SYMBOL_OBJECT *Object;
302 UINTN ObjectIndex;
303 UINTN Index;
304
305 //
306 // Go throuth each object
307 //
308 DebuggerSymbolContext = &DebuggerPrivate->DebuggerSymbolContext;
309 for (ObjectIndex = 0; ObjectIndex < DebuggerSymbolContext->ObjectCount; ObjectIndex++) {
310 Object = &DebuggerSymbolContext->Object[ObjectIndex];
311 //
312 // Go throuth each entry
313 //
314 for (Index = 0; Index < Object->EntryCount; Index++) {
315 ZeroMem (&Object->Entry[Index], sizeof(Object->Entry[Index]));
316 }
317 ZeroMem (Object->Name, sizeof(Object->Name));
318 Object->EntryCount = 0;
319 Object->BaseAddress = 0;
320 Object->StartEntrypointRVA = 0;
321 Object->MainEntrypointRVA = 0;
322 //
323 // Free source buffer
324 //
325 for (Index = 0; Object->SourceBuffer[Index] != NULL; Index++) {
326 gBS->FreePool (Object->SourceBuffer[Index]);
327 Object->SourceBuffer[Index] = NULL;
328 }
329 }
330 DebuggerSymbolContext->ObjectCount = 0;
331
332 return ;
333 }
334
335 EFI_STATUS
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
341 )
342 /*++
343
344 Routine Description:
345
346 Initialize Debugger private data structure
347
348 Arguments:
349
350 DebuggerPrivate - EBC Debugger private data structure
351 InterruptType - Interrupt type.
352 SystemContext - EBC system context.
353 Initialized - Whether the DebuggerPrivate data is initialized.
354
355 Returns:
356
357 None
358
359 --*/
360 {
361 //
362 // clear STEP flag in any condition.
363 //
364 if (SystemContext.SystemContextEbc->Flags & ((UINT64) VMFLAGS_STEP)) {
365 SystemContext.SystemContextEbc->Flags &= ~((UINT64) VMFLAGS_STEP);
366 }
367
368 if (!Initialized) {
369 //
370 // Initialize everything
371 //
372 DebuggerPrivate->InstructionNumber = EFI_DEBUG_DEFAULT_INSTRUCTION_NUMBER;
373
374 DebuggerPrivate->DebuggerBreakpointCount = 0;
375 ZeroMem (DebuggerPrivate->DebuggerBreakpointContext, sizeof(DebuggerPrivate->DebuggerBreakpointContext));
376
377 // DebuggerPrivate->StatusFlags = 0;
378
379 DebuggerPrivate->DebuggerSymbolContext.DisplaySymbol = TRUE;
380 DebuggerPrivate->DebuggerSymbolContext.DisplayCodeOnly = FALSE;
381 DebuggerPrivate->DebuggerSymbolContext.ObjectCount = 0;
382 } else {
383 //
384 // Already initialized, just check Breakpoint here.
385 //
386 if (ExceptionType == EXCEPT_EBC_BREAKPOINT) {
387 EdbCheckBreakpoint (DebuggerPrivate, SystemContext);
388 }
389
390 //
391 // Clear all breakpoint
392 //
393 EdbClearAllBreakpoint (DebuggerPrivate, FALSE);
394 }
395
396 //
397 // Set Scope to currentl IP. (Note: Check Breakpoint may change Ip)
398 //
399 DebuggerPrivate->InstructionScope = SystemContext.SystemContextEbc->Ip;
400
401 //
402 // Done
403 //
404 return EFI_SUCCESS;
405 }
406
407 EFI_STATUS
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
413 )
414 /*++
415
416 Routine Description:
417
418 De-initialize Debugger private data structure
419
420 Arguments:
421
422 DebuggerPrivate - EBC Debugger private data structure
423 InterruptType - Interrupt type.
424 SystemContext - EBC system context.
425 Initialized - Whether the DebuggerPrivate data is initialized.
426
427 Returns:
428
429 None
430
431 --*/
432 {
433 if (!Initialized) {
434 //
435 // If it does not want initialized state, de-init everything
436 //
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));
442
443 //
444 // Clear all breakpoint
445 //
446 EdbClearAllBreakpoint (DebuggerPrivate, TRUE);
447
448 //
449 // Clear symbol
450 //
451 EdbClearSymbol (DebuggerPrivate);
452 } else {
453 //
454 // If it wants to keep initialized state, just set breakpoint.
455 //
456 EdbSetAllBreakpoint (DebuggerPrivate);
457 }
458
459 //
460 // Clear Step context
461 //
462 ZeroMem (&mDebuggerPrivate.StepContext, sizeof(mDebuggerPrivate.StepContext));
463 DebuggerPrivate->StatusFlags = 0;
464
465 //
466 // Done
467 //
468 return EFI_SUCCESS;
469 }
470
471 VOID
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
477 )
478 /*++
479
480 Routine Description:
481
482 Print the reason of current break to EbcDebugger.
483
484 Arguments:
485
486 DebuggerPrivate - EBC Debugger private data structure
487 InterruptType - Interrupt type.
488 SystemContext - EBC system context.
489 Initialized - Whether the DebuggerPrivate data is initialized.
490
491 Returns:
492
493 None
494
495 --*/
496 {
497 //
498 // Print break status
499 //
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");
520 } else {
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]);
524 } else {
525 EDBPrint (L"\n");
526 }
527 }
528
529 return ;
530 }
531
532 VOID
533 EFIAPI
534 EdbExceptionHandler (
535 IN EFI_EXCEPTION_TYPE ExceptionType,
536 IN OUT EFI_SYSTEM_CONTEXT SystemContext
537 )
538 /*++
539
540 Routine Description:
541
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.
545
546 Arguments:
547
548 InterruptType - Interrupt type.
549 SystemContext - EBC system context.
550
551 Returns:
552
553 None
554
555 --*/
556 {
557 CHAR16 InputBuffer[EFI_DEBUG_INPUS_BUFFER_SIZE];
558 CHAR16 *CommandArg;
559 EFI_DEBUGGER_COMMAND DebuggerCommand;
560 EFI_DEBUG_STATUS DebugStatus;
561 STATIC BOOLEAN mInitialized = FALSE;
562
563 DEBUG ((DEBUG_ERROR, "Hello EBC Debugger!\n"));
564
565 if (!mInitialized) {
566 //
567 // Print version
568 //
569 EDBPrint (
570 L"EBC Interpreter Version - %d.%d\n",
571 (UINTN)VM_MAJOR_VERSION,
572 (UINTN)VM_MINOR_VERSION
573 );
574 EDBPrint (
575 L"EBC Debugger Version - %d.%d\n",
576 (UINTN)EBC_DEBUGGER_MAJOR_VERSION,
577 (UINTN)EBC_DEBUGGER_MINOR_VERSION
578 );
579 }
580 //
581 // Init Private Data
582 //
583 InitDebuggerPrivateData (&mDebuggerPrivate, ExceptionType, SystemContext, mInitialized);
584
585 //
586 // EDBPrint basic info
587 //
588 PrintExceptionReason (&mDebuggerPrivate, ExceptionType, SystemContext, mInitialized);
589
590 EdbShowDisasm (&mDebuggerPrivate, SystemContext);
591 // EFI_BREAKPOINT ();
592
593 if (!mInitialized) {
594 //
595 // Interactive with user
596 //
597 EDBPrint (L"\nPlease enter command now, \'h\' for help.\n");
598 EDBPrint (L"(Using <Command> -b <...> to enable page break.)\n");
599 }
600 mInitialized = TRUE;
601
602 //
603 // Dispatch each command
604 //
605 while (TRUE) {
606 //
607 // Get user input
608 //
609 Input (L"\n\r" EFI_DEBUG_PROMPT_STRING, InputBuffer, EFI_DEBUG_INPUS_BUFFER_SIZE);
610 EDBPrint (L"\n");
611
612 //
613 // Get command
614 //
615 DebuggerCommand = MatchDebuggerCommand (InputBuffer, &CommandArg);
616 if (DebuggerCommand == NULL) {
617 EDBPrint (L"ERROR: Command not found!\n");
618 continue;
619 }
620
621 //
622 // Check PageBreak;
623 //
624 if (CommandArg != NULL) {
625 if (StriCmp (CommandArg, L"-b") == 0) {
626 CommandArg = StrGetNextTokenLine (L" ");
627 mDebuggerPrivate.EnablePageBreak = TRUE;
628 }
629 }
630
631 //
632 // Dispatch command
633 //
634 DebugStatus = DebuggerCommand (CommandArg, &mDebuggerPrivate, ExceptionType, SystemContext);
635 mDebuggerPrivate.EnablePageBreak = FALSE;
636
637 //
638 // Check command return status
639 //
640 if (DebugStatus == EFI_DEBUG_RETURN) {
641 mInitialized = FALSE;
642 break;
643 } else if (DebugStatus == EFI_DEBUG_BREAK) {
644 break;
645 } else if (DebugStatus == EFI_DEBUG_CONTINUE) {
646 continue;
647 } else {
648 ASSERT (FALSE);
649 }
650 }
651
652 //
653 // Deinit Private Data
654 //
655 DeinitDebuggerPrivateData (&mDebuggerPrivate, ExceptionType, SystemContext, mInitialized);
656
657 DEBUG ((DEBUG_ERROR, "Goodbye EBC Debugger!\n"));
658
659 return;
660 }