]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/EbcDxe/EbcDebugger/Edb.c
MdeModulePkg: Fix GCC build failure
[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 BOOLEAN IsHitBreakpoint;
198
199 //
200 // Roll back IP for breakpoint instruction (BREAK(3) : 0x0300)
201 //
202 Address = SystemContext.SystemContextEbc->Ip - sizeof(UINT16);
203
204 //
205 // Check if the breakpoint is hit
206 //
207 IsHitBreakpoint = FALSE;
208 for (Index = 0; (Index < DebuggerPrivate->DebuggerBreakpointCount) && (Index < EFI_DEBUGGER_BREAKPOINT_MAX); Index++) {
209 if ((DebuggerPrivate->DebuggerBreakpointContext[Index].BreakpointAddress == Address) &&
210 (DebuggerPrivate->DebuggerBreakpointContext[Index].State)) {
211 IsHitBreakpoint = TRUE;
212 break;
213 }
214 }
215
216 if (IsHitBreakpoint) {
217 //
218 // If hit, record current breakpoint
219 //
220 DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX] = DebuggerPrivate->DebuggerBreakpointContext[Index];
221 DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX].State = TRUE;
222 //
223 // Update: IP and Instruction (NOTE: Since we not allow set breakpoint to BREAK 3, this update is safe)
224 //
225 SystemContext.SystemContextEbc->Ip = Address;
226 //
227 // Set Flags
228 //
229 DebuggerPrivate->StatusFlags |= EFI_DEBUG_FLAG_EBC_BP;
230 } else {
231 //
232 // If not hit, check whether current IP is in breakpoint list,
233 // because STEP will be triggered before execute the instruction.
234 // We should not patch it in de-init.
235 //
236 Address = SystemContext.SystemContextEbc->Ip;
237
238 //
239 // Check if the breakpoint is hit
240 //
241 IsHitBreakpoint = FALSE;
242 for (Index = 0; (Index < DebuggerPrivate->DebuggerBreakpointCount) && (Index < EFI_DEBUGGER_BREAKPOINT_MAX); Index++) {
243 if ((DebuggerPrivate->DebuggerBreakpointContext[Index].BreakpointAddress == Address) &&
244 (DebuggerPrivate->DebuggerBreakpointContext[Index].State)) {
245 IsHitBreakpoint = TRUE;
246 break;
247 }
248 }
249
250 if (IsHitBreakpoint) {
251 //
252 // If hit, record current breakpoint
253 //
254 DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX] = DebuggerPrivate->DebuggerBreakpointContext[Index];
255 DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX].State = TRUE;
256 //
257 // Do not set Breakpoint flag. We record the address here just let it not patch breakpoint address when de-init.
258 //
259 } else {
260 //
261 // Zero current breakpoint
262 //
263 ZeroMem (
264 &DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX],
265 sizeof(DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX])
266 );
267 }
268 }
269
270 //
271 // Done
272 //
273 return ;
274 }
275
276 VOID
277 EdbClearSymbol (
278 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate
279 )
280 /*++
281
282 Routine Description:
283
284 clear all the symbol
285
286 Arguments:
287
288 DebuggerPrivate - EBC Debugger private data structure
289
290 Returns:
291
292 None
293
294 --*/
295 {
296 EFI_DEBUGGER_SYMBOL_CONTEXT *DebuggerSymbolContext;
297 EFI_DEBUGGER_SYMBOL_OBJECT *Object;
298 UINTN ObjectIndex;
299 UINTN Index;
300
301 //
302 // Go throuth each object
303 //
304 DebuggerSymbolContext = &DebuggerPrivate->DebuggerSymbolContext;
305 for (ObjectIndex = 0; ObjectIndex < DebuggerSymbolContext->ObjectCount; ObjectIndex++) {
306 Object = &DebuggerSymbolContext->Object[ObjectIndex];
307 //
308 // Go throuth each entry
309 //
310 for (Index = 0; Index < Object->EntryCount; Index++) {
311 ZeroMem (&Object->Entry[Index], sizeof(Object->Entry[Index]));
312 }
313 ZeroMem (Object->Name, sizeof(Object->Name));
314 Object->EntryCount = 0;
315 Object->BaseAddress = 0;
316 Object->StartEntrypointRVA = 0;
317 Object->MainEntrypointRVA = 0;
318 //
319 // Free source buffer
320 //
321 for (Index = 0; Object->SourceBuffer[Index] != NULL; Index++) {
322 gBS->FreePool (Object->SourceBuffer[Index]);
323 Object->SourceBuffer[Index] = NULL;
324 }
325 }
326 DebuggerSymbolContext->ObjectCount = 0;
327
328 return ;
329 }
330
331 EFI_STATUS
332 InitDebuggerPrivateData (
333 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
334 IN EFI_EXCEPTION_TYPE ExceptionType,
335 IN EFI_SYSTEM_CONTEXT SystemContext,
336 IN BOOLEAN Initialized
337 )
338 /*++
339
340 Routine Description:
341
342 Initialize Debugger private data structure
343
344 Arguments:
345
346 DebuggerPrivate - EBC Debugger private data structure
347 InterruptType - Interrupt type.
348 SystemContext - EBC system context.
349 Initialized - Whether the DebuggerPrivate data is initialized.
350
351 Returns:
352
353 None
354
355 --*/
356 {
357 //
358 // clear STEP flag in any condition.
359 //
360 if (SystemContext.SystemContextEbc->Flags & ((UINT64) VMFLAGS_STEP)) {
361 SystemContext.SystemContextEbc->Flags &= ~((UINT64) VMFLAGS_STEP);
362 }
363
364 if (!Initialized) {
365 //
366 // Initialize everything
367 //
368 DebuggerPrivate->InstructionNumber = EFI_DEBUG_DEFAULT_INSTRUCTION_NUMBER;
369
370 DebuggerPrivate->DebuggerBreakpointCount = 0;
371 ZeroMem (DebuggerPrivate->DebuggerBreakpointContext, sizeof(DebuggerPrivate->DebuggerBreakpointContext));
372
373 // DebuggerPrivate->StatusFlags = 0;
374
375 DebuggerPrivate->DebuggerSymbolContext.DisplaySymbol = TRUE;
376 DebuggerPrivate->DebuggerSymbolContext.DisplayCodeOnly = FALSE;
377 DebuggerPrivate->DebuggerSymbolContext.ObjectCount = 0;
378 } else {
379 //
380 // Already initialized, just check Breakpoint here.
381 //
382 if (ExceptionType == EXCEPT_EBC_BREAKPOINT) {
383 EdbCheckBreakpoint (DebuggerPrivate, SystemContext);
384 }
385
386 //
387 // Clear all breakpoint
388 //
389 EdbClearAllBreakpoint (DebuggerPrivate, FALSE);
390 }
391
392 //
393 // Set Scope to currentl IP. (Note: Check Breakpoint may change Ip)
394 //
395 DebuggerPrivate->InstructionScope = SystemContext.SystemContextEbc->Ip;
396
397 //
398 // Done
399 //
400 return EFI_SUCCESS;
401 }
402
403 EFI_STATUS
404 DeinitDebuggerPrivateData (
405 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
406 IN EFI_EXCEPTION_TYPE ExceptionType,
407 IN EFI_SYSTEM_CONTEXT SystemContext,
408 IN BOOLEAN Initialized
409 )
410 /*++
411
412 Routine Description:
413
414 De-initialize Debugger private data structure
415
416 Arguments:
417
418 DebuggerPrivate - EBC Debugger private data structure
419 InterruptType - Interrupt type.
420 SystemContext - EBC system context.
421 Initialized - Whether the DebuggerPrivate data is initialized.
422
423 Returns:
424
425 None
426
427 --*/
428 {
429 if (!Initialized) {
430 //
431 // If it does not want initialized state, de-init everything
432 //
433 DebuggerPrivate->FeatureFlags = EFI_DEBUG_FLAG_EBC_BOE | EFI_DEBUG_FLAG_EBC_BOT;
434 DebuggerPrivate->CallStackEntryCount = 0;
435 DebuggerPrivate->TraceEntryCount = 0;
436 ZeroMem (DebuggerPrivate->CallStackEntry, sizeof(DebuggerPrivate->CallStackEntry));
437 ZeroMem (DebuggerPrivate->TraceEntry, sizeof(DebuggerPrivate->TraceEntry));
438
439 //
440 // Clear all breakpoint
441 //
442 EdbClearAllBreakpoint (DebuggerPrivate, TRUE);
443
444 //
445 // Clear symbol
446 //
447 EdbClearSymbol (DebuggerPrivate);
448 } else {
449 //
450 // If it wants to keep initialized state, just set breakpoint.
451 //
452 EdbSetAllBreakpoint (DebuggerPrivate);
453 }
454
455 //
456 // Clear Step context
457 //
458 ZeroMem (&mDebuggerPrivate.StepContext, sizeof(mDebuggerPrivate.StepContext));
459 DebuggerPrivate->StatusFlags = 0;
460
461 //
462 // Done
463 //
464 return EFI_SUCCESS;
465 }
466
467 VOID
468 PrintExceptionReason (
469 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
470 IN EFI_EXCEPTION_TYPE ExceptionType,
471 IN EFI_SYSTEM_CONTEXT SystemContext,
472 IN BOOLEAN Initialized
473 )
474 /*++
475
476 Routine Description:
477
478 Print the reason of current break to EbcDebugger.
479
480 Arguments:
481
482 DebuggerPrivate - EBC Debugger private data structure
483 InterruptType - Interrupt type.
484 SystemContext - EBC system context.
485 Initialized - Whether the DebuggerPrivate data is initialized.
486
487 Returns:
488
489 None
490
491 --*/
492 {
493 //
494 // Print break status
495 //
496 if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_GT) == EFI_DEBUG_FLAG_EBC_GT) {
497 EDBPrint (L"Break on GoTil\n");
498 } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_BOC) == EFI_DEBUG_FLAG_EBC_BOC) {
499 EDBPrint (L"Break on CALL\n");
500 } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_BOCX) == EFI_DEBUG_FLAG_EBC_BOCX) {
501 EDBPrint (L"Break on CALLEX\n");
502 } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_BOR) == EFI_DEBUG_FLAG_EBC_BOR) {
503 EDBPrint (L"Break on RET\n");
504 } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_BOE) == EFI_DEBUG_FLAG_EBC_BOE) {
505 EDBPrint (L"Break on Entrypoint\n");
506 } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_BOT) == EFI_DEBUG_FLAG_EBC_BOT) {
507 EDBPrint (L"Break on Thunk\n");
508 } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_STEPOVER) == EFI_DEBUG_FLAG_EBC_STEPOVER) {
509 EDBPrint (L"Break on StepOver\n");
510 } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_STEPOUT) == EFI_DEBUG_FLAG_EBC_STEPOUT) {
511 EDBPrint (L"Break on StepOut\n");
512 } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_BP) == EFI_DEBUG_FLAG_EBC_BP) {
513 EDBPrint (L"Break on Breakpoint\n");
514 } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_BOK) == EFI_DEBUG_FLAG_EBC_BOK) {
515 EDBPrint (L"Break on Key\n");
516 } else {
517 EDBPrint (L"Exception Type - %x", (UINTN)ExceptionType);
518 if ((ExceptionType >= EXCEPT_EBC_UNDEFINED) && (ExceptionType <= EXCEPT_EBC_STEP)) {
519 EDBPrint (L" (%s)\n", mExceptionStr[ExceptionType]);
520 } else {
521 EDBPrint (L"\n");
522 }
523 }
524
525 return ;
526 }
527
528 VOID
529 EFIAPI
530 EdbExceptionHandler (
531 IN EFI_EXCEPTION_TYPE ExceptionType,
532 IN OUT EFI_SYSTEM_CONTEXT SystemContext
533 )
534 /*++
535
536 Routine Description:
537
538 The default Exception Callback for the VM interpreter.
539 In this function, we report status code, and print debug information
540 about EBC_CONTEXT, then dead loop.
541
542 Arguments:
543
544 InterruptType - Interrupt type.
545 SystemContext - EBC system context.
546
547 Returns:
548
549 None
550
551 --*/
552 {
553 CHAR16 InputBuffer[EFI_DEBUG_INPUS_BUFFER_SIZE];
554 CHAR16 *CommandArg;
555 EFI_DEBUGGER_COMMAND DebuggerCommand;
556 EFI_DEBUG_STATUS DebugStatus;
557 STATIC BOOLEAN mInitialized = FALSE;
558
559 DEBUG ((DEBUG_ERROR, "Hello EBC Debugger!\n"));
560
561 if (!mInitialized) {
562 //
563 // Print version
564 //
565 EDBPrint (
566 L"EBC Interpreter Version - %d.%d\n",
567 (UINTN)VM_MAJOR_VERSION,
568 (UINTN)VM_MINOR_VERSION
569 );
570 EDBPrint (
571 L"EBC Debugger Version - %d.%d\n",
572 (UINTN)EBC_DEBUGGER_MAJOR_VERSION,
573 (UINTN)EBC_DEBUGGER_MINOR_VERSION
574 );
575 }
576 //
577 // Init Private Data
578 //
579 InitDebuggerPrivateData (&mDebuggerPrivate, ExceptionType, SystemContext, mInitialized);
580
581 //
582 // EDBPrint basic info
583 //
584 PrintExceptionReason (&mDebuggerPrivate, ExceptionType, SystemContext, mInitialized);
585
586 EdbShowDisasm (&mDebuggerPrivate, SystemContext);
587 // EFI_BREAKPOINT ();
588
589 if (!mInitialized) {
590 //
591 // Interactive with user
592 //
593 EDBPrint (L"\nPlease enter command now, \'h\' for help.\n");
594 EDBPrint (L"(Using <Command> -b <...> to enable page break.)\n");
595 }
596 mInitialized = TRUE;
597
598 //
599 // Dispatch each command
600 //
601 while (TRUE) {
602 //
603 // Get user input
604 //
605 Input (L"\n\r" EFI_DEBUG_PROMPT_STRING, InputBuffer, EFI_DEBUG_INPUS_BUFFER_SIZE);
606 EDBPrint (L"\n");
607
608 //
609 // Get command
610 //
611 DebuggerCommand = MatchDebuggerCommand (InputBuffer, &CommandArg);
612 if (DebuggerCommand == NULL) {
613 EDBPrint (L"ERROR: Command not found!\n");
614 continue;
615 }
616
617 //
618 // Check PageBreak;
619 //
620 if (CommandArg != NULL) {
621 if (StriCmp (CommandArg, L"-b") == 0) {
622 CommandArg = StrGetNextTokenLine (L" ");
623 mDebuggerPrivate.EnablePageBreak = TRUE;
624 }
625 }
626
627 //
628 // Dispatch command
629 //
630 DebugStatus = DebuggerCommand (CommandArg, &mDebuggerPrivate, ExceptionType, SystemContext);
631 mDebuggerPrivate.EnablePageBreak = FALSE;
632
633 //
634 // Check command return status
635 //
636 if (DebugStatus == EFI_DEBUG_RETURN) {
637 mInitialized = FALSE;
638 break;
639 } else if (DebugStatus == EFI_DEBUG_BREAK) {
640 break;
641 } else if (DebugStatus == EFI_DEBUG_CONTINUE) {
642 continue;
643 } else {
644 ASSERT (FALSE);
645 }
646 }
647
648 //
649 // Deinit Private Data
650 //
651 DeinitDebuggerPrivateData (&mDebuggerPrivate, ExceptionType, SystemContext, mInitialized);
652
653 DEBUG ((DEBUG_ERROR, "Goodbye EBC Debugger!\n"));
654
655 return;
656 }