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