]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSymbol.c
57945023588d1b33940ca1238bd99dae79c1405e
[mirror_edk2.git] / MdeModulePkg / Universal / EbcDxe / EbcDebugger / EdbSymbol.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 EdbSymbol.c
15
16 Abstract:
17
18
19 --*/
20
21 #include "Edb.h"
22
23 EFI_STATUS
24 EdbLoadSymbolSingleEntry (
25 IN EFI_DEBUGGER_SYMBOL_OBJECT *Object,
26 IN CHAR8 *Name,
27 IN CHAR8 *ObjName,
28 IN UINTN Address,
29 IN EFI_DEBUGGER_SYMBOL_TYPE Type
30 )
31 /*++
32
33 Routine Description:
34
35 Load single symbol entry
36
37 Arguments:
38
39 Object - Symbol file object
40 Name - Symbol name
41 ObjName - Object name
42 Address - Symbol address
43 Type - Symbol type
44
45 Returns:
46
47 EFI_SUCCESS - add single symbol entry successfully
48
49 --*/
50 {
51 EFI_DEBUGGER_SYMBOL_ENTRY *Entry;
52
53 //
54 // Check Count VS MaxCount
55 //
56 if (Object->EntryCount >= Object->MaxEntryCount) {
57 //
58 // reallocate (for codebuffer too)
59 // TBD
60 //
61 return EFI_OUT_OF_RESOURCES;
62 }
63
64 Entry = &Object->Entry[Object->EntryCount];
65
66 //
67 // Print Debug info
68 //
69 if (sizeof (UINTN) == sizeof(UINT64)) {
70 DEBUG ((DEBUG_ERROR, " Symbol: %a, Address: 0x%016lx (%d)\n", Name, (UINT64)Address, (UINTN)Type));
71 } else {
72 DEBUG ((DEBUG_ERROR, " Symbol: %a, Address: 0x%08x (%d)\n", Name, Address, (UINTN)Type));
73 }
74
75 //
76 // Fill the entry - name, RVA, type
77 //
78 AsciiStrnCpyS (Entry->Name, sizeof(Entry->Name), Name, sizeof(Entry->Name) - 1);
79 if (ObjName != NULL) {
80 AsciiStrnCpyS (Entry->ObjName, sizeof(Entry->ObjName), ObjName, sizeof(Entry->ObjName) - 1);
81 }
82 Entry->RVA = Address % EFI_DEBUGGER_DEFAULT_LINK_IMAGEBASE;
83 Entry->Type = Type;
84
85 //
86 // Increase Count
87 //
88 Object->EntryCount++;
89
90 //
91 // Done
92 //
93 return EFI_SUCCESS;
94 }
95
96 typedef enum {
97 EdbEbcMapParseStateUninitialized,
98 EdbEbcMapParseStateSymbolStart,
99 EdbEbcMapParseStateSeHandlerSymbol,
100 EdbEbcMapParseStateFunctionSymbol,
101 EdbEbcMapParseStateVarbssInitSymbol,
102 EdbEbcMapParseStateCrtSymbol,
103 EdbEbcMapParseStateVariableSymbol,
104 EdbEbcMapParseStateStaticFunctionSymbol,
105 EdbEbcMapParseStateMax,
106 } EDB_EBC_MAP_PARSE_STATE;
107
108 typedef enum {
109 EdbEbcSymbolParseStateUninitialized,
110 EdbEbcSymbolParseStateReadyForName,
111 EdbEbcSymbolParseStateReadyForRVA,
112 EdbEbcSymbolParseStateReadyForType,
113 EdbEbcSymbolParseStateReadyForObject,
114 EdbEbcSymbolParseStateMax,
115 } EDB_EBC_SYMBOL_PARSE_STATE;
116
117 /*++
118
119 The following code depends on the MAP file generated by IEC compiler (actually Microsoft linker).
120
121 Sample as follows: EbcTest.map
122 ===============================================================================
123 EbcTest
124
125 Timestamp is 45b02718 (Fri Jan 19 10:04:08 2007)
126
127 Preferred load address is 10000000
128
129 Start Length Name Class
130 0001:00000000 00000370H .text CODE
131 0002:00000000 00000030H _VARBSS_INIT CODE
132 0003:00000000 00000004H .CRT$TSA DATA
133 0003:00000004 00000004H .CRT$TSC DATA
134 0003:00000008 00000004H .CRT$X DATA
135 0003:0000000c 00000008H .CRT$XCU DATA
136 0003:00000014 00000004H .CRT$Z DATA
137 0003:00000020 0000001cH .rdata DATA
138 0003:0000003c 00000000H .edata DATA
139 0003:0000003c 00000056H .rdata$debug DATA
140 0004:00000000 00000070H .data DATA
141 0004:00000070 00000020H .bss DATA
142
143 Address Publics by Value Rva+Base Lib:Object
144
145 0000:00000000 ___safe_se_handler_table 00000000 <absolute>
146 0000:00000000 ___safe_se_handler_count 00000000 <absolute>
147 0001:00000042 TestSubRoutine 10000442 f EbcTest.obj
148 0001:0000011a EfiMain 1000051a f EbcTest.obj
149 0001:00000200 TestSubRoutineSub 10000600 f EbcTestSub.obj
150 0001:00000220 EfiStart 10000620 f EbcLib:EbcLib.obj
151 0002:00000000 varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest$c45b02717 10000800 f EbcTest.obj
152 0002:00000020 varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTestSub$c45af77f3 10000820 f EbcTestSub.obj
153 0003:00000000 CrtThunkBegin 10000a00 EbcLib:EbcLib.obj
154 0003:00000004 CrtThunkEnd 10000a04 EbcLib:EbcLib.obj
155 0003:00000008 CrtBegin 10000a08 EbcLib:EbcLib.obj
156 0003:00000014 CrtEnd 10000a14 EbcLib:EbcLib.obj
157 0004:00000070 TestStr 10000c70 EbcTest.obj
158 0004:00000078 TestVariable1 10000c78 EbcTest.obj
159 0004:00000080 TestSubVariableSub 10000c80 EbcTestSub.obj
160
161 entry point at 0001:00000220
162
163 Static symbols
164
165 0001:00000000 TestSubRoutine2 10000400 f EbcTest.obj
166 ===============================================================================
167
168 --*/
169 EFI_STATUS
170 EdbLoadSymbolEntryByIec (
171 IN EFI_DEBUGGER_SYMBOL_OBJECT *Object,
172 IN UINTN BufferSize,
173 IN VOID *Buffer
174 )
175 /*++
176
177 Routine Description:
178
179 Load symbol entry by Iec
180
181 Arguments:
182
183 DebuggerPrivate - EBC Debugger private data structure
184 Object - Symbol file object
185 BufferSize - Symbol file buffer size
186 Buffer - Symbol file buffer
187
188 Returns:
189
190 EFI_SUCCESS - add symbol entry successfully
191
192 --*/
193 {
194 CHAR8 *LineBuffer;
195 CHAR8 *FieldBuffer;
196 EDB_EBC_MAP_PARSE_STATE MapParseState;
197 EDB_EBC_SYMBOL_PARSE_STATE SymbolParseState;
198 CHAR8 *Name;
199 CHAR8 *ObjName;
200 UINTN Address;
201 EFI_DEBUGGER_SYMBOL_TYPE Type;
202
203
204 //
205 // Begin to parse the Buffer
206 //
207 LineBuffer = AsciiStrGetNewTokenLine (Buffer, "\n\r");
208 MapParseState = EdbEbcMapParseStateUninitialized;
209 //
210 // Check each line
211 //
212 while (LineBuffer != NULL) {
213 FieldBuffer = AsciiStrGetNewTokenField (LineBuffer, " ");
214 SymbolParseState = EdbEbcSymbolParseStateUninitialized;
215 //
216 // Init entry value
217 //
218 Name = NULL;
219 ObjName = NULL;
220 Address = 0;
221 Type = EfiDebuggerSymbolTypeMax;
222 //
223 // Check each field
224 //
225 while (FieldBuffer != NULL) {
226 if (AsciiStrCmp (FieldBuffer, "") == 0) {
227 FieldBuffer = AsciiStrGetNextTokenField (" ");
228 continue;
229 }
230 //
231 // check "Address"
232 //
233 if (AsciiStrCmp (FieldBuffer, "Address") == 0) {
234 MapParseState = EdbEbcMapParseStateSymbolStart;
235 break;
236 }
237 //
238 // check "Static"
239 //
240 if (AsciiStrCmp (FieldBuffer, "Static") == 0) {
241 MapParseState = EdbEbcMapParseStateStaticFunctionSymbol;
242 break;
243 }
244
245 if (MapParseState == EdbEbcMapParseStateUninitialized) {
246 //
247 // Do not parse anything until get "Address" or "Static"
248 //
249 break;
250 }
251 if (AsciiStrCmp (FieldBuffer, "entry") == 0) {
252 //
253 // Skip entry point
254 //
255 break;
256 }
257
258 //
259 // Now we start to parse this line for Name, Address, and Object
260 //
261 switch (SymbolParseState) {
262 case EdbEbcSymbolParseStateUninitialized:
263 //
264 // Get the Address
265 //
266 SymbolParseState = EdbEbcSymbolParseStateReadyForName;
267 break;
268 case EdbEbcSymbolParseStateReadyForName:
269 //
270 // Get the Name
271 //
272 if (AsciiStrnCmp (FieldBuffer, "___safe_se_handler", AsciiStrLen ("___safe_se_handler")) == 0) {
273 //
274 // skip SeHandler
275 //
276 MapParseState = EdbEbcMapParseStateSeHandlerSymbol;
277 goto ExitFieldParse;
278 } else if (AsciiStrnCmp (FieldBuffer, "varbss_init", AsciiStrLen ("varbss_init")) == 0) {
279 //
280 // check VarbssInit
281 //
282 MapParseState = EdbEbcMapParseStateVarbssInitSymbol;
283 // goto ExitFieldParse;
284 Name = FieldBuffer;
285 SymbolParseState = EdbEbcSymbolParseStateReadyForRVA;
286 } else if (AsciiStrnCmp (FieldBuffer, "Crt", AsciiStrLen ("Crt")) == 0) {
287 //
288 // check Crt
289 //
290 MapParseState = EdbEbcMapParseStateCrtSymbol;
291 // goto ExitFieldParse;
292 Name = FieldBuffer;
293 SymbolParseState = EdbEbcSymbolParseStateReadyForRVA;
294 } else {
295 //
296 // Now, it is normal function
297 //
298 switch (MapParseState) {
299 case EdbEbcMapParseStateSeHandlerSymbol:
300 MapParseState = EdbEbcMapParseStateFunctionSymbol;
301 break;
302 case EdbEbcMapParseStateCrtSymbol:
303 MapParseState = EdbEbcMapParseStateVariableSymbol;
304 break;
305 case EdbEbcMapParseStateFunctionSymbol:
306 case EdbEbcMapParseStateVariableSymbol:
307 case EdbEbcMapParseStateStaticFunctionSymbol:
308 break;
309 default:
310 ASSERT (FALSE);
311 break;
312 }
313 Name = FieldBuffer;
314 SymbolParseState = EdbEbcSymbolParseStateReadyForRVA;
315 }
316 break;
317 case EdbEbcSymbolParseStateReadyForRVA:
318 //
319 // Get the RVA
320 //
321 Address = AsciiXtoi (FieldBuffer);
322 SymbolParseState = EdbEbcSymbolParseStateReadyForType;
323 break;
324 case EdbEbcSymbolParseStateReadyForType:
325 //
326 // Get the Type. This is optional, only for "f".
327 //
328 if (AsciiStrCmp (FieldBuffer, "f") == 0) {
329 SymbolParseState = EdbEbcSymbolParseStateReadyForObject;
330 switch (MapParseState) {
331 case EdbEbcMapParseStateFunctionSymbol:
332 case EdbEbcMapParseStateVarbssInitSymbol:
333 Type = EfiDebuggerSymbolFunction;
334 break;
335 case EdbEbcMapParseStateStaticFunctionSymbol:
336 Type = EfiDebuggerSymbolStaticFunction;
337 break;
338 default:
339 ASSERT (FALSE);
340 break;
341 }
342 break;
343 }
344 //
345 // Else it should be Object.
346 // let it bypass here
347 //
348 case EdbEbcSymbolParseStateReadyForObject:
349 switch (Type) {
350 case EfiDebuggerSymbolTypeMax:
351 switch (MapParseState) {
352 case EdbEbcMapParseStateVariableSymbol:
353 case EdbEbcMapParseStateCrtSymbol:
354 Type = EfiDebuggerSymbolGlobalVariable;
355 break;
356 case EdbEbcMapParseStateSeHandlerSymbol:
357 //
358 // do nothing here
359 //
360 break;
361 default:
362 ASSERT (FALSE);
363 break;
364 }
365 break;
366 case EfiDebuggerSymbolFunction:
367 case EfiDebuggerSymbolStaticFunction:
368 break;
369 default:
370 ASSERT (FALSE);
371 break;
372 }
373 //
374 // Get the Object
375 //
376 ObjName = FieldBuffer;
377 SymbolParseState = EdbEbcSymbolParseStateUninitialized;
378 break;
379 default:
380 ASSERT (FALSE);
381 break;
382 }
383
384 //
385 // Get the next field
386 //
387 FieldBuffer = AsciiStrGetNextTokenField (" ");
388 }
389
390 //
391 // Add the entry if we get everything.
392 //
393 if ((Name != NULL) && (Type != EfiDebuggerSymbolTypeMax)) {
394 EdbLoadSymbolSingleEntry (Object, Name, ObjName, Address, Type);
395 }
396
397 ExitFieldParse:
398 //
399 // Get the next line
400 //
401 LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
402 }
403
404 //
405 // Done
406 //
407 return EFI_SUCCESS;
408 }
409
410 EFI_STATUS
411 EdbLoadSymbolEntry (
412 IN EFI_DEBUGGER_SYMBOL_OBJECT *Object,
413 IN UINTN BufferSize,
414 IN VOID *Buffer
415 )
416 /*++
417
418 Routine Description:
419
420 Load symbol entry
421
422 Arguments:
423
424 Object - Symbol file object
425 BufferSize - Symbol file buffer size
426 Buffer - Symbol file buffer
427
428 Returns:
429
430 EFI_SUCCESS - add symbol entry successfully
431
432 --*/
433 {
434 //
435 // MAP file format depends on the compiler (actually linker).
436 //
437 // It is possible to check the different MAP file format in this routine.
438 // Now only IEC is supported.
439 //
440 return EdbLoadSymbolEntryByIec (Object, BufferSize, Buffer);
441 }
442
443 EFI_DEBUGGER_SYMBOL_OBJECT *
444 EdbFindSymbolFile (
445 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
446 IN CHAR16 *FileName,
447 IN OUT UINTN *Index OPTIONAL
448 )
449 /*++
450
451 Routine Description:
452
453 Find symbol file by name
454
455 Arguments:
456
457 DebuggerPrivate - EBC Debugger private data structure
458 FileName - Symbol file name
459 Index - Symbol file index
460
461 Returns:
462
463 Object
464
465 --*/
466 {
467 UINTN ObjectIndex;
468
469 //
470 // Check each Object
471 //
472 for (ObjectIndex = 0; ObjectIndex < DebuggerPrivate->DebuggerSymbolContext.ObjectCount; ObjectIndex++) {
473 if (StrCmp (FileName, DebuggerPrivate->DebuggerSymbolContext.Object[ObjectIndex].Name) == 0) {
474 //
475 // Name match, found it
476 //
477 if (Index != NULL) {
478 *Index = ObjectIndex;
479 }
480 return &DebuggerPrivate->DebuggerSymbolContext.Object[ObjectIndex];
481 }
482 }
483
484 //
485 // Not found
486 //
487 return NULL;
488 }
489
490 UINTN
491 EbdFindSymbolAddress (
492 IN UINTN Address,
493 IN EDB_MATCH_SYMBOL_TYPE Type,
494 OUT EFI_DEBUGGER_SYMBOL_OBJECT **RetObject,
495 OUT EFI_DEBUGGER_SYMBOL_ENTRY **RetEntry
496 )
497 /*++
498
499 Routine Description:
500
501 Find symbol by address
502
503 Arguments:
504
505 Address - Symbol address
506 Type - Search type
507 RetObject - Symbol object
508 RetEntry - Symbol entry
509
510 Returns:
511
512 Nearest symbol address
513
514 --*/
515 {
516 UINTN Index;
517 UINTN SubIndex;
518 UINTN CandidateLowerAddress;
519 UINTN CandidateUpperAddress;
520 EFI_DEBUGGER_SYMBOL_OBJECT *Object;
521 EFI_DEBUGGER_SYMBOL_ENTRY *Entry;
522 EFI_DEBUGGER_SYMBOL_ENTRY *LowEntry;
523 EFI_DEBUGGER_SYMBOL_ENTRY *UpperEntry;
524 EFI_DEBUGGER_SYMBOL_OBJECT *LowObject;
525 EFI_DEBUGGER_SYMBOL_OBJECT *UpperObject;
526
527 if ((Type < 0) || (Type >= EdbMatchSymbolTypeMax)) {
528 return 0;
529 }
530
531 //
532 // Init
533 //
534 CandidateLowerAddress = 0;
535 CandidateUpperAddress = (UINTN)-1;
536 LowEntry = NULL;
537 UpperEntry = NULL;
538 LowObject = NULL;
539 UpperObject = NULL;
540
541 //
542 // Go through each object
543 //
544 Object = mDebuggerPrivate.DebuggerSymbolContext.Object;
545 for (Index = 0; Index < mDebuggerPrivate.DebuggerSymbolContext.ObjectCount; Index++, Object++) {
546 if (Object->EntryCount == 0) {
547 continue;
548 }
549 //
550 // Go through each entry
551 //
552 Entry = Object->Entry;
553 for (SubIndex = 0; SubIndex < Object->EntryCount; SubIndex++, Entry++) {
554 if (Address != Entry->RVA + Object->BaseAddress) {
555 //
556 // Check for nearest address
557 //
558 if (Address > Entry->RVA + Object->BaseAddress) {
559 //
560 // Record it if Current RVA < Address
561 //
562 if (CandidateLowerAddress < Entry->RVA + Object->BaseAddress) {
563 CandidateLowerAddress = Entry->RVA + Object->BaseAddress;
564 LowEntry = Entry;
565 LowObject = Object;
566 }
567 } else {
568 //
569 // Record it if Current RVA > Address
570 //
571 if (CandidateUpperAddress > Entry->RVA + Object->BaseAddress) {
572 CandidateUpperAddress = Entry->RVA + Object->BaseAddress;
573 UpperEntry = Entry;
574 UpperObject = Object;
575 }
576 }
577 continue;
578 }
579 //
580 // address match, return directly
581 //
582 *RetEntry = Entry;
583 *RetObject = Object;
584 return Address;
585 }
586 }
587
588 //
589 // No Match, provide latest symbol
590 //
591
592 if ((Address - CandidateLowerAddress) < EFI_DEBUGGER_MAX_SYMBOL_ADDRESS_DELTA_VALUE) {
593 //
594 // Check for lower address
595 //
596 if (((Type == EdbMatchSymbolTypeNearestAddress) &&
597 ((CandidateUpperAddress - Address) > (Address - CandidateLowerAddress))) ||
598 (Type == EdbMatchSymbolTypeLowerAddress)) {
599 //
600 // return nearest lower address
601 //
602 *RetEntry = LowEntry;
603 *RetObject = LowObject;
604 return CandidateLowerAddress;
605 }
606 }
607
608 if ((CandidateUpperAddress - Address) < EFI_DEBUGGER_MAX_SYMBOL_ADDRESS_DELTA_VALUE) {
609 //
610 // Check for upper address
611 //
612 if (((Type == EdbMatchSymbolTypeNearestAddress) &&
613 ((CandidateUpperAddress - Address) < (Address - CandidateLowerAddress))) ||
614 (Type == EdbMatchSymbolTypeUpperAddress)) {
615 //
616 // return nearest upper address
617 //
618 *RetEntry = UpperEntry;
619 *RetObject = UpperObject;
620 return CandidateUpperAddress;
621 }
622 }
623
624 //
625 // No match and nearest one, return NULL
626 //
627 return 0;
628 }
629
630 EFI_STATUS
631 EdbUnloadSymbol (
632 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
633 IN CHAR16 *FileName
634 )
635 /*++
636
637 Routine Description:
638
639 Unload symbol file by name
640
641 Arguments:
642
643 DebuggerPrivate - EBC Debugger private data structure
644 FileName - Symbol file name
645
646 Returns:
647
648 EFI_SUCCESS - unload symbol successfully
649
650 --*/
651 {
652 EFI_DEBUGGER_SYMBOL_OBJECT *Object;
653 UINTN ObjectIndex;
654 UINTN Index;
655 EFI_DEBUGGER_SYMBOL_ENTRY *OldEntry;
656 UINTN OldEntryCount;
657 UINTN MaxEntryCount;
658 VOID **OldSourceBuffer;
659
660 //
661 // Find Symbol
662 //
663 Object = EdbFindSymbolFile (DebuggerPrivate, FileName, &ObjectIndex);
664 if (Object == NULL) {
665 EDBPrint (L"SymbolFile is not loaded!\n");
666 return EFI_DEBUG_CONTINUE;
667 }
668
669 //
670 // Record old data
671 //
672 Object = DebuggerPrivate->DebuggerSymbolContext.Object;
673 OldEntry = Object->Entry;
674 OldSourceBuffer = Object->SourceBuffer;
675 MaxEntryCount = Object->MaxEntryCount;
676 OldEntryCount = Object->EntryCount;
677
678 //
679 // Remove the matched Object
680 //
681 for (Index = ObjectIndex; Index < DebuggerPrivate->DebuggerSymbolContext.ObjectCount - 1; Index++) {
682 CopyMem (&Object[Index], &Object[Index + 1], sizeof(EFI_DEBUGGER_SYMBOL_OBJECT));
683 }
684 ZeroMem (&Object[Index], sizeof(Object[Index]));
685
686 //
687 // Move old data to new place
688 //
689 Object[Index].Entry = OldEntry;
690 Object[Index].SourceBuffer = OldSourceBuffer;
691 Object[Index].MaxEntryCount = MaxEntryCount;
692 DebuggerPrivate->DebuggerSymbolContext.ObjectCount --;
693
694 //
695 // Clean old entry data
696 //
697 for (Index = 0; Index < OldEntryCount; Index++) {
698 ZeroMem (&OldEntry[Index], sizeof(OldEntry[Index]));
699 }
700
701 //
702 // Free OldSourceBuffer
703 //
704 for (Index = 0; OldSourceBuffer[Index] != NULL; Index++) {
705 gBS->FreePool (OldSourceBuffer[Index]);
706 OldSourceBuffer[Index] = NULL;
707 }
708
709 return EFI_SUCCESS;
710 }
711
712 EFI_STATUS
713 EdbLoadSymbol (
714 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
715 IN CHAR16 *FileName,
716 IN UINTN BufferSize,
717 IN VOID *Buffer
718 )
719 /*++
720
721 Routine Description:
722
723 Load symbol file by name
724
725 Arguments:
726
727 DebuggerPrivate - EBC Debugger private data structure
728 FileName - Symbol file name
729 BufferSize - Symbol file buffer size
730 Buffer - Symbol file buffer
731
732 Returns:
733
734 EFI_SUCCESS - load symbol successfully
735
736 --*/
737 {
738 EFI_DEBUGGER_SYMBOL_OBJECT *Object;
739 EFI_STATUS Status;
740
741 //
742 // Check duplicated File
743 //
744 Object = EdbFindSymbolFile (DebuggerPrivate, FileName, NULL);
745 if (Object != NULL) {
746 Status = EdbUnloadSymbol (DebuggerPrivate, FileName);
747 if (EFI_ERROR(Status)) {
748 DEBUG ((DEBUG_ERROR, "Unload Duplicated Symbol File Error!\n"));
749 return Status;
750 }
751 }
752
753 //
754 // Check Count VS MaxCount
755 //
756 if (DebuggerPrivate->DebuggerSymbolContext.ObjectCount >= DebuggerPrivate->DebuggerSymbolContext.MaxObjectCount) {
757 //
758 // reallocate
759 // TBD
760 //
761 return EFI_OUT_OF_RESOURCES;
762 }
763
764 Object = &DebuggerPrivate->DebuggerSymbolContext.Object[DebuggerPrivate->DebuggerSymbolContext.ObjectCount];
765
766 //
767 // Init Object
768 //
769 Object->EntryCount = 0;
770 Object->MaxEntryCount = EFI_DEBUGGER_SYMBOL_ENTRY_MAX;
771
772 //
773 // Load SymbolEntry
774 //
775 DEBUG ((DEBUG_ERROR, "Symbol File: %s\n", FileName));
776 Status = EdbLoadSymbolEntry (Object, BufferSize, Buffer);
777 if (EFI_ERROR (Status)) {
778 return Status;
779 }
780
781 //
782 // Fill Object value
783 //
784 StrnCpyS (Object->Name, sizeof(Object->Name) / sizeof(CHAR16),
785 FileName, (sizeof(Object->Name) / sizeof(CHAR16)) - 1);
786 Object->BaseAddress = 0;
787
788 //
789 // Increase the object count
790 //
791 DebuggerPrivate->DebuggerSymbolContext.ObjectCount ++;
792
793 return EFI_SUCCESS;
794 }
795
796 CHAR8 *
797 GetPdbPath (
798 VOID *ImageBase
799 )
800 /*++
801
802 Routine Description:
803
804 Located PDB path name in PE image
805
806 Arguments:
807
808 ImageBase - base of PE to search
809
810 Returns:
811
812 Pointer into image at offset of PDB file name if PDB file name is found,
813 Otherwise a pointer to an empty string.
814
815 --*/
816 {
817 CHAR8 *PdbPath;
818 UINT32 DirCount;
819 EFI_IMAGE_DOS_HEADER *DosHdr;
820 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;
821 EFI_IMAGE_OPTIONAL_HEADER32 *OptionalHdr32;
822 EFI_IMAGE_OPTIONAL_HEADER64 *OptionalHdr64;
823 EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry;
824 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;
825 VOID *CodeViewEntryPointer;
826
827 //
828 // Init value
829 //
830 CodeViewEntryPointer = NULL;
831 PdbPath = NULL;
832 DosHdr = ImageBase;
833
834 //
835 // Check magic
836 //
837 if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
838 return NULL;
839 }
840 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *) ((UINT8 *) DosHdr + DosHdr->e_lfanew);
841 //
842 // Check Machine, filter for EBC
843 //
844 if (NtHdr->Pe32.FileHeader.Machine != EFI_IMAGE_MACHINE_EBC) {
845 //
846 // If not EBC, return NULL
847 //
848 return NULL;
849 }
850
851 //
852 // Get DirectoryEntry
853 // EBC spec says PE32+, but implementation uses PE32. So check dynamically here.
854 //
855 if (NtHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
856 OptionalHdr32 = (VOID *) &NtHdr->Pe32.OptionalHeader;
857 DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(OptionalHdr32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
858 } else if (NtHdr->Pe32Plus.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
859 OptionalHdr64 = (VOID *) &NtHdr->Pe32Plus.OptionalHeader;
860 DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(OptionalHdr64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
861 } else {
862 return NULL;
863 }
864 if (DirectoryEntry->VirtualAddress == 0) {
865 return NULL;
866 }
867 //
868 // Go through DirectoryEntry
869 //
870 for (DirCount = 0;
871 (DirCount < DirectoryEntry->Size / sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)) && CodeViewEntryPointer == NULL;
872 DirCount++
873 ) {
874 DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (DirectoryEntry->VirtualAddress + (UINTN) ImageBase + DirCount * sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY));
875 if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
876 //
877 // Match DebugEntry, only CODEVIEW_SIGNATURE_NB10 and CODEVIEW_SIGNATURE_RSDS are supported.
878 //
879 CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + (UINTN) ImageBase);
880 switch (*(UINT32 *) CodeViewEntryPointer) {
881 case CODEVIEW_SIGNATURE_NB10:
882 PdbPath = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);
883 break;
884 case CODEVIEW_SIGNATURE_RSDS:
885 PdbPath = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);
886 break;
887 default:
888 break;
889 }
890 }
891 }
892
893 //
894 // Done successfully
895 //
896 return PdbPath;
897 }
898
899 BOOLEAN
900 MatchPdbAndMap (
901 IN CHAR8 *PdbFileName,
902 IN CHAR16 *MapFileName
903 )
904 /*++
905
906 Routine Description:
907
908 Check whether PDB file and MAP file have same name
909
910 Arguments:
911
912 PdbFileName - PDB file name
913 MapFileName - MAP file name
914
915 Returns:
916
917 TRUE - PDB and MAP file name match
918 FALSE - PDB and MAP file name not match
919
920 --*/
921 {
922 UINTN PdbNameSize;
923 UINTN MapNameSize;
924 CHAR8 *PurePdbFileName;
925 UINTN Index;
926
927 //
928 // remove dir name
929 //
930 PurePdbFileName = PdbFileName;
931 for (Index = 0; PdbFileName[Index] != 0; Index++) {
932 if (PdbFileName[Index] == '\\') {
933 PurePdbFileName = &PdbFileName[Index + 1];
934 }
935 }
936 PdbFileName = PurePdbFileName;
937
938 //
939 // get size
940 //
941 PdbNameSize = AsciiStrLen (PdbFileName);
942 MapNameSize = StrLen (MapFileName);
943
944 if (PdbNameSize != MapNameSize) {
945 return FALSE;
946 }
947
948 //
949 // check the name
950 //
951 for (Index = 0; Index < MapNameSize - 4; Index++) {
952 if ((PdbFileName[Index] | 0x20) != (MapFileName[Index] | 0x20)) {
953 return FALSE;
954 }
955 }
956
957 return TRUE;
958 }
959
960 //
961 // BUGBUG: work-around start
962 //
963 typedef struct {
964 EFI_DEBUG_IMAGE_INFO *EfiDebugImageInfoTable;
965 volatile UINT32 UpdateStatus;
966 UINT32 TableSize;
967 } EFI_DEBUG_IMAGE_INFO_TABLE_HEADER_OLD;
968
969 EFI_DEBUG_IMAGE_INFO_TABLE_HEADER mDebugImageInfoTableHeader;
970
971 VOID
972 EdbFixDebugImageInfoTable (
973 IN OUT EFI_DEBUG_IMAGE_INFO_TABLE_HEADER **DebugImageInfoTableHeader
974 )
975 /*
976 For compatibility consideration, we handle 2 cases:
977
978 1) IA32:
979 Old: New:
980 +------------------------+ +------------------------+
981 | EfiDebugImageInfoTable | | UpdateStatus |
982 +------------------------+ +------------------------+
983 | UpdateStatus | | TableSize |
984 +------------------------+ +------------------------+
985 | TableSize | | EfiDebugImageInfoTable |
986 +------------------------+ +------------------------+
987
988 2) X64 and IPF:
989 Old: New:
990 +------------------------+ +------------------------+
991 | EfiDebugImageInfoTable | | UpdateStatus |
992 | | +------------------------+
993 | | | TableSize |
994 +------------------------+ +------------------------+
995 | UpdateStatus | | EfiDebugImageInfoTable |
996 +------------------------+ | |
997 | TableSize | | |
998 +------------------------+ +------------------------+
999
1000 */
1001 {
1002 mDebugImageInfoTableHeader.EfiDebugImageInfoTable = ((EFI_DEBUG_IMAGE_INFO_TABLE_HEADER_OLD *)(*DebugImageInfoTableHeader))->EfiDebugImageInfoTable;
1003 mDebugImageInfoTableHeader.UpdateStatus = ((EFI_DEBUG_IMAGE_INFO_TABLE_HEADER_OLD *)(*DebugImageInfoTableHeader))->UpdateStatus;
1004 mDebugImageInfoTableHeader.TableSize = ((EFI_DEBUG_IMAGE_INFO_TABLE_HEADER_OLD *)(*DebugImageInfoTableHeader))->TableSize;
1005
1006 if ((*DebugImageInfoTableHeader)->UpdateStatus > 3) {
1007 *DebugImageInfoTableHeader = &mDebugImageInfoTableHeader;
1008 return ;
1009 }
1010
1011 if ((*DebugImageInfoTableHeader)->TableSize % (EFI_PAGE_SIZE / (sizeof (VOID *))) != 0) {
1012 *DebugImageInfoTableHeader = &mDebugImageInfoTableHeader;
1013 return ;
1014 }
1015
1016 return ;
1017 }
1018 //
1019 // BUGBUG: work-around end
1020 //
1021
1022 EFI_STATUS
1023 EdbPatchSymbolRVA (
1024 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
1025 IN CHAR16 *FileName,
1026 IN EDB_EBC_IMAGE_RVA_SEARCH_TYPE SearchType
1027 )
1028 /*++
1029
1030 Routine Description:
1031
1032 Patch symbol RVA
1033
1034 Arguments:
1035
1036 DebuggerPrivate - EBC Debugger private data structure
1037 FileName - Symbol file name
1038 SearchType - Search type for Object
1039
1040 Returns:
1041
1042 EFI_SUCCESS - Patch symbol RVA successfully
1043 EFI_NOT_FOUND - Symbol RVA base not found
1044
1045 --*/
1046 {
1047 EFI_STATUS Status;
1048 UINTN ImageNumber;
1049 EFI_DEBUG_IMAGE_INFO *ImageTable;
1050 CHAR8 *PdbPath;
1051 VOID *ImageBase;
1052 VOID *CandidateImageBase;
1053 EFI_DEBUGGER_SYMBOL_OBJECT *Object;
1054
1055 if (SearchType < 0 || SearchType >= EdbEbcImageRvaSearchTypeMax) {
1056 return EFI_INVALID_PARAMETER;
1057 }
1058
1059 //
1060 // Get the related object
1061 //
1062 Object = EdbFindSymbolFile (DebuggerPrivate, FileName, NULL);
1063 if (Object == NULL) {
1064 return EFI_NOT_FOUND;
1065 }
1066
1067 //
1068 // Try again to get DebugImageInfoTable
1069 //
1070 if (mDebuggerPrivate.DebugImageInfoTableHeader == NULL) {
1071 Status = EfiGetSystemConfigurationTable (
1072 &gEfiDebugImageInfoTableGuid,
1073 (VOID **) &mDebuggerPrivate.DebugImageInfoTableHeader
1074 );
1075 if (EFI_ERROR (Status)) {
1076 EDBPrint (L"DebugImageInfoTable not found!\n");
1077 return Status;
1078 }
1079 }
1080 DEBUG ((DEBUG_ERROR, "DebugImageInfoTableHeader: %x\n", mDebuggerPrivate.DebugImageInfoTableHeader));
1081
1082 //
1083 // BUGBUG: work-around start
1084 //
1085 EdbFixDebugImageInfoTable (&mDebuggerPrivate.DebugImageInfoTableHeader);
1086 //
1087 // BUGBUG: work-around end
1088 //
1089
1090 //
1091 // Go through DebugImageInfoTable for each Image
1092 //
1093 CandidateImageBase = NULL;
1094 ImageTable = mDebuggerPrivate.DebugImageInfoTableHeader->EfiDebugImageInfoTable;
1095 for (ImageNumber = 0; ImageNumber < mDebuggerPrivate.DebugImageInfoTableHeader->TableSize; ImageNumber++) {
1096 if (ImageTable[ImageNumber].NormalImage == NULL) {
1097 continue;
1098 }
1099 ImageBase = ImageTable[ImageNumber].NormalImage->LoadedImageProtocolInstance->ImageBase;
1100 //
1101 // Get PDB path
1102 //
1103 PdbPath = GetPdbPath (ImageBase);
1104 if (PdbPath == NULL) {
1105 continue;
1106 }
1107 //
1108 // Check PDB name
1109 //
1110 if (!MatchPdbAndMap (PdbPath, FileName)) {
1111 continue;
1112 }
1113 DEBUG ((DEBUG_ERROR, "ImageBase: %x\n", ImageBase));
1114
1115 //
1116 // Check SearchType
1117 //
1118 if (SearchType == EdbEbcImageRvaSearchTypeAny || SearchType == EdbEbcImageRvaSearchTypeFirst) {
1119 //
1120 // Assign base address and return
1121 //
1122 Object->BaseAddress = (UINTN)ImageBase;
1123 return EFI_SUCCESS;
1124 }
1125
1126 //
1127 // Get CandidateImageBase for EdbEbcImageRvaSearchTypeLast
1128 //
1129 CandidateImageBase = ImageBase;
1130 }
1131
1132 //
1133 // Check EdbEbcImageRvaSearchTypeLast
1134 //
1135 if (SearchType == EdbEbcImageRvaSearchTypeLast) {
1136 if (CandidateImageBase == NULL) {
1137 return EFI_NOT_FOUND;
1138 }
1139 //
1140 // Assign base address and return
1141 //
1142 Object->BaseAddress = (UINTN)CandidateImageBase;
1143 return EFI_SUCCESS;
1144 }
1145
1146 //
1147 // No match
1148 //
1149 return EFI_NOT_FOUND;
1150 }
1151
1152 BOOLEAN
1153 MatchObjAndCod (
1154 IN CHAR8 *ObjFileName,
1155 IN CHAR16 *CodFileName
1156 )
1157 /*++
1158
1159 Routine Description:
1160
1161 Check whether OBJ file and COD file have same name
1162
1163 Arguments:
1164
1165 ObjFileName - OBJ file name
1166 CodFileName - COD file name
1167
1168 Returns:
1169
1170 TRUE - OBJ and COD file name match
1171 FALSE - OBJ and COD file name not match
1172
1173 --*/
1174 {
1175 UINTN ObjNameSize;
1176 UINTN CodNameSize;
1177 CHAR8 *PureObjFileName;
1178 UINTN Index;
1179
1180 //
1181 // remove library name
1182 //
1183 PureObjFileName = ObjFileName;
1184 for (Index = 0; ObjFileName[Index] != 0; Index++) {
1185 if (ObjFileName[Index] == ':') {
1186 PureObjFileName = &ObjFileName[Index + 1];
1187 break;
1188 }
1189 }
1190 ObjFileName = PureObjFileName;
1191
1192 //
1193 // get size
1194 //
1195 ObjNameSize = AsciiStrLen (ObjFileName);
1196 CodNameSize = StrLen (CodFileName);
1197
1198 if (ObjNameSize != CodNameSize) {
1199 return FALSE;
1200 }
1201
1202 //
1203 // check the name
1204 //
1205 for (Index = 0; Index < CodNameSize - 4; Index++) {
1206 if ((ObjFileName[Index] | 0x20) != (CodFileName[Index] | 0x20)) {
1207 return FALSE;
1208 }
1209 }
1210
1211 return TRUE;
1212 }
1213
1214 typedef enum {
1215 EdbEbcCodParseStateUninitialized,
1216 EdbEbcCodParseStateSymbolInitialized,
1217 EdbEbcCodParseStateSymbolStart,
1218 EdbEbcCodParseStateSymbolEnd,
1219 EdbEbcCodParseStateMax,
1220 } EDB_EBC_COD_PARSE_STATE;
1221
1222 /*++
1223
1224 The following code depends on the COD file generated by IEC compiler.
1225
1226 Sample as follows: EbcTest.cod
1227 ===============================================================================
1228 ; -- Machine type EFI
1229 ; mark_description "Intel(R) C Compiler for EFI Byte Code, Version 1.2 Build 20040123";
1230 ; mark_description "XXX";
1231 ;ident "Intel(R) C Compiler for EFI Byte Code, Version 1.2 Build 20040123"
1232 ;ident "XXX"
1233 .686P
1234 .387
1235 _TEXT SEGMENT PARA PUBLIC USE32 'CODE'
1236 _TEXT ENDS
1237 _DATA SEGMENT PARA PUBLIC USE32 'DATA'
1238 ALIGN 010H
1239 _DATA ENDS
1240 _BSS SEGMENT PARA PUBLIC USE32 'BSS'
1241 ALIGN 010H
1242 _BSS ENDS
1243 _VARBSS SEGMENT PARA PUBLIC USE32 'BSS'
1244 ALIGN 010H
1245 _VARBSS ENDS
1246 ASSUME CS:FLAT,DS:FLAT,SS:FLAT
1247 _DATA SEGMENT PARA PUBLIC USE32 'DATA'
1248 TestVariable2 DD 000000003H,000000000H ; u64
1249 _DATA ENDS
1250 _DATA SEGMENT PARA PUBLIC USE32 'DATA'
1251 _DATA ENDS
1252 _TEXT SEGMENT PARA PUBLIC USE32 'CODE'
1253 ; -- Begin EfiMain
1254 ; mark_begin;
1255 PUBLIC EfiMain
1256 EfiMain PROC NEAR
1257 $B3$1:; 11a
1258 $LN45:
1259
1260 ;117 ; {
1261
1262 0011a 60 00 70 80 MOVqw R0, R0(+0,-112) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:117
1263 $LN46:
1264
1265 ;118 ; UINT16 test = 0x1234;
1266
1267 0011e 77 58 58 00 34
1268 12 MOVIww @R0(+0,+88), +4660 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:118
1269 $LN47:
1270
1271 ;121 ; EFI_STATUS Status;
1272 ;121 ;
1273 ;121 ; SystemTable->ConOut->OutputString (
1274
1275 00124 72 87 01 12 MOVnw R7, @R0(+1,+128) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:121
1276 00128 72 f7 85 21 MOVnw R7, @R7(+5,+24) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:121
1277 $LN48:
1278
1279 ;122 ; SystemTable->ConOut,
1280
1281 0012c 72 84 01 12 MOVnw R4, @R0(+1,+128) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:122
1282 00130 72 c8 85 21 MOVnw @R0, @R4(+5,+24) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:122
1283 00134 b9 34 00 00 00
1284 00 MOVreld R4, __STRING$1 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:122
1285 0013a b2 48 01 10 MOVnw @R0(+1,+0), R4 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:122
1286 0013e 83 2f 01 00 00
1287 10 CALLEX @R7(+1,+0) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:122
1288 $B3$2:; 144
1289 $LN49:
1290
1291 ;125 ; L"Hello EBC Test!\n\r"
1292 ;125 ; );
1293 ;125 ; EFI_BREAKPOINT ();
1294
1295 00144 00 03 BREAK 3 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:125
1296 $B3$3:; 146
1297 $LN50:
1298
1299 ;126 ; TestVariable1 = 6;
1300
1301 00146 b9 37 00 00 00
1302 00 MOVreld R7, TestVariable1 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:126
1303 0014c 78 0f 06 00 MOVInw @R7, (0,6) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:126
1304 $LN51:
1305
1306 ;127 ; TestSubRoutineSub (1, 5);
1307
1308 00150 78 08 01 00 MOVInw @R0, (0,1) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:127
1309 00154 78 48 01 10 05
1310 00 MOVInw @R0(1,0), (0,5) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:127
1311 0015a 83 10 00 00 00
1312 00 CALL TestSubRoutineSub ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:127
1313 $B3$4:; 160
1314 $LN52:
1315
1316 ;129 ;
1317 ;129 ; SystemTable->ConOut->OutputString (
1318
1319 00160 72 87 01 12 MOVnw R7, @R0(+1,+128) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:129
1320 00164 72 f7 85 21 MOVnw R7, @R7(+5,+24) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:129
1321 $LN53:
1322
1323 ;130 ; SystemTable->ConOut,
1324
1325 00168 72 84 01 12 MOVnw R4, @R0(+1,+128) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:130
1326 0016c 72 c8 85 21 MOVnw @R0, @R4(+5,+24) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:130
1327 $LN54:
1328
1329 ;131 ; TestStr
1330
1331 00170 b9 34 00 00 00
1332 00 MOVreld R4, TestStr ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:131
1333 00176 b2 c8 01 10 MOVnw @R0(+1, +0), @R4 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:131
1334 0017a 83 2f 01 00 00
1335 10 CALLEX @R7(+1,+0) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:131
1336 $B3$5:; 180
1337 $LN55:
1338
1339 ;134 ; );
1340 ;134 ;
1341 ;134 ; test = test & 0xFF;
1342
1343 00180 de 88 58 00 58
1344 00 MOVww @R0(+0,+88), @R0(+0,+88) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:134
1345 $LN56:
1346
1347 ;139 ; if (test != 0x34) {
1348 ;139 ; // EFI_BREAKPOINT ();
1349 ;139 ; }
1350 ;139 ;
1351 ;139 ; Status = TestSubRoutine (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
1352
1353 00186 78 08 01 00 MOVInw @R0, (0,1) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1354 0018a 78 48 01 10 02
1355 00 MOVInw @R0(1,0), (0,2) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1356 00190 78 48 02 10 03
1357 00 MOVInw @R0(2,0), (0,3) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1358 00196 78 48 03 10 04
1359 00 MOVInw @R0(3,0), (0,4) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1360 0019c 78 48 04 20 05
1361 00 MOVInw @R0(4,0), (0,5) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1362 001a2 78 48 05 20 06
1363 00 MOVInw @R0(5,0), (0,6) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1364 001a8 78 48 06 20 07
1365 00 MOVInw @R0(6,0), (0,7) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1366 001ae 78 48 07 20 08
1367 00 MOVInw @R0(7,0), (0,8) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1368 001b4 78 48 08 20 09
1369 00 MOVInw @R0(8,0), (0,9) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1370 001ba 78 48 09 20 0a
1371 00 MOVInw @R0(9,0), (0,10) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1372 001c0 83 10 00 00 00
1373 00 CALL TestSubRoutine ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1374 $B3$10:; 1c6
1375 001c6 b2 78 60 00 MOVnw @R0(+0,+96), R7 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1376 $B3$6:; 1ca
1377 $LN57:
1378 001ca f2 88 50 00 60
1379 00 MOVnw @R0(+0,+80), @R0(+0,+96) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1380 $LN58:
1381
1382 ;141 ;
1383 ;141 ; SystemTable->ConOut->OutputString (
1384
1385 001d0 72 87 01 12 MOVnw R7, @R0(+1,+128) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:141
1386 001d4 72 f7 85 21 MOVnw R7, @R7(+5,+24) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:141
1387 $LN59:
1388
1389 ;142 ; SystemTable->ConOut,
1390
1391 001d8 72 84 01 12 MOVnw R4, @R0(+1,+128) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:142
1392 001dc 72 c8 85 21 MOVnw @R0, @R4(+5,+24) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:142
1393 001e0 b9 34 00 00 00
1394 00 MOVreld R4, __STRING$2 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:142
1395 001e6 b2 48 01 10 MOVnw @R0(+1,+0), R4 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:142
1396 001ea 83 2f 01 00 00
1397 10 CALLEX @R7(+1,+0) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:142
1398 $B3$7:; 1f0
1399 $LN60:
1400
1401 ;146 ; L"Goodbye EBC Test!\n\r"
1402 ;146 ; );
1403 ;146 ;
1404 ;146 ; return Status;
1405
1406 001f0 72 87 50 00 MOVnw R7, @R0(+0,+80) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:146
1407 001f4 60 00 70 00 MOVqw R0, R0(+0,+112) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:146
1408 001f8 04 00 RET ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:146
1409 ; mark_end;
1410 EfiMain ENDP
1411 _TEXT ENDS
1412 _DATA SEGMENT PARA PUBLIC USE32 'DATA'
1413 DB 3 DUP (0) ; pad
1414 __STRING$2 DW 71 ; u16
1415 DW 111 ; u16
1416 DW 111 ; u16
1417 DW 100 ; u16
1418 DW 98 ; u16
1419 DW 121 ; u16
1420 DW 101 ; u16
1421 DW 32 ; u16
1422 DW 69 ; u16
1423 DW 66 ; u16
1424 DW 67 ; u16
1425 DW 32 ; u16
1426 DW 84 ; u16
1427 DW 101 ; u16
1428 DW 115 ; u16
1429 DW 116 ; u16
1430 DW 33 ; u16
1431 DW 10 ; u16
1432 DW 13 ; u16
1433 DW 0 ; u16
1434 __STRING$1 DW 72 ; u16
1435 DW 101 ; u16
1436 DW 108 ; u16
1437 DW 108 ; u16
1438 DW 111 ; u16
1439 DW 32 ; u16
1440 DW 69 ; u16
1441 DW 66 ; u16
1442 DW 67 ; u16
1443 DW 32 ; u16
1444 DW 84 ; u16
1445 DW 101 ; u16
1446 DW 115 ; u16
1447 DW 116 ; u16
1448 DW 33 ; u16
1449 DW 10 ; u16
1450 DW 13 ; u16
1451 DW 0 ; u16
1452 _DATA ENDS
1453 _DATA SEGMENT PARA PUBLIC USE32 'DATA'
1454 _DATA ENDS
1455 ; -- End EfiMain
1456 _DATA SEGMENT PARA PUBLIC USE32 'DATA'
1457 __STRING$0 DW 55 ; u16
1458 DW 56 ; u16
1459 DW 57 ; u16
1460 DW 52 ; u16
1461 DW 53 ; u16
1462 DW 54 ; u16
1463 DW 49 ; u16
1464 DW 50 ; u16
1465 DW 51 ; u16
1466 DW 13 ; u16
1467 DW 10 ; u16
1468 DW 0 ; u16
1469 _DATA ENDS
1470 _VARBSS SEGMENT PARA PUBLIC USE32 'BSS'
1471 PUBLIC TestStr
1472 TestStr DD 2 DUP (?) ; pad
1473 PUBLIC TestVariable1
1474 TestVariable1 DD 2 DUP (?) ; pad
1475 _VARBSS ENDS
1476 _VARBSS_INIT SEGMENT DWORD PUBLIC USE32 'CODE'
1477 ; -- Begin varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest$c45b815d2
1478 PUBLIC varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest$c45b815d2
1479 varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest$c45b815d2 PROC NEAR
1480 00000 b9 34 00 00 00
1481 00 MOVreld R4, TestStr
1482 00006 b9 35 00 00 00
1483 00 MOVreld R5, __STRING$0
1484 0000c 33 5c MOVnd @R4, R5
1485 0000e b9 34 00 00 00
1486 00 MOVreld R4, TestVariable1
1487 00014 78 0c 04 00 MOVInw @R4, (0,4)
1488 00018 04 00 RET
1489 ; -- End varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest$c45b815d2
1490 _VARBSS_INIT ENDS
1491 _DATA SEGMENT PARA PUBLIC USE32 'DATA'
1492 _DATA ENDS
1493 EXTRN TestSubRoutineSub:PROC
1494 END
1495
1496 ===============================================================================
1497
1498 --*/
1499 CHAR8 *
1500 EdbLoadCodBySymbolByIec (
1501 IN CHAR8 *Name,
1502 IN VOID *Buffer,
1503 IN UINTN BufferSize,
1504 OUT UINTN *CodeBufferSize,
1505 OUT UINTN *FuncOffset
1506 )
1507 /*++
1508
1509 Routine Description:
1510
1511 Load code by symbol by Iec
1512
1513 Arguments:
1514
1515 Name - Symbol file name
1516 BufferSize - Symbol file buffer size
1517 Buffer - Symbol file buffer
1518 CodeBufferSize - Code buffer size
1519 FuncOffset - Code funcion offset
1520
1521 Returns:
1522
1523 CodeBuffer
1524
1525 --*/
1526 {
1527 CHAR8 *LineBuffer;
1528 CHAR8 *FieldBuffer;
1529 VOID *BufferStart;
1530 VOID *BufferEnd;
1531 UINTN Offset;
1532 EDB_EBC_COD_PARSE_STATE CodParseState;
1533 CHAR8 Char[2] = {9, 0};
1534
1535 //
1536 // Init
1537 //
1538 LineBuffer = AsciiStrGetNewTokenLine (Buffer, "\n\r");
1539 Offset = (UINTN)-1;
1540 BufferStart = NULL;
1541 BufferEnd = NULL;
1542 CodParseState = EdbEbcCodParseStateUninitialized;
1543
1544 //
1545 // Check each line
1546 //
1547 while (LineBuffer != NULL) {
1548 switch (CodParseState) {
1549 case EdbEbcCodParseStateUninitialized:
1550 //
1551 // check mark_begin, begin to check line after this match
1552 //
1553 if (AsciiStrCmp (LineBuffer, "; mark_begin;") == 0) {
1554 CodParseState = EdbEbcCodParseStateSymbolInitialized;
1555 }
1556 LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
1557 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1558 break;
1559
1560 case EdbEbcCodParseStateSymbolInitialized:
1561 //
1562 // check mark_end, not check line after this match
1563 //
1564 if (AsciiStrCmp (LineBuffer, "; mark_end;") == 0) {
1565 CodParseState = EdbEbcCodParseStateUninitialized;
1566 LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
1567 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1568 break;
1569 }
1570
1571 //
1572 // not check this line if the first char is as follows
1573 //
1574 if ((*LineBuffer == 0) ||
1575 (*LineBuffer == '$') ||
1576 (*LineBuffer == ';') ||
1577 (*LineBuffer == '_') ||
1578 (*LineBuffer == ' ')) {
1579 LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
1580 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1581 break;
1582 }
1583
1584 //
1585 // get function name, function name is followed by char 0x09.
1586 //
1587 FieldBuffer = AsciiStrGetNewTokenField (LineBuffer, Char);
1588 ASSERT (FieldBuffer != NULL);
1589 if (AsciiStriCmp (FieldBuffer, Name) == 0) {
1590 BufferStart = FieldBuffer;
1591 CodParseState = EdbEbcCodParseStateSymbolStart;
1592 }
1593 PatchForAsciiStrTokenAfter (FieldBuffer, 0x9);
1594
1595 //
1596 // Get next line
1597 //
1598 LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
1599 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1600 break;
1601
1602 case EdbEbcCodParseStateSymbolStart:
1603 //
1604 // check mark_end, if this match, means the function is found successfully.
1605 //
1606 if (AsciiStrCmp (LineBuffer, "; mark_end;") == 0) {
1607 CodParseState = EdbEbcCodParseStateSymbolEnd;
1608 //
1609 // prepare CodeBufferSize, FuncOffset, and FuncStart to return
1610 //
1611 BufferEnd = LineBuffer + sizeof("; mark_end;") - 1;
1612 *CodeBufferSize = (UINTN)BufferEnd - (UINTN)BufferStart;
1613 *FuncOffset = Offset;
1614 PatchForAsciiStrTokenAfter (LineBuffer, '\n');
1615 return BufferStart;
1616 }
1617
1618 //
1619 // Get function offset
1620 //
1621 if ((Offset == (UINTN)-1) &&
1622 (*LineBuffer == ' ')) {
1623 FieldBuffer = AsciiStrGetNewTokenField (LineBuffer + 2, " ");
1624 Offset = AsciiXtoi (FieldBuffer);
1625 PatchForAsciiStrTokenAfter (FieldBuffer, ' ');
1626 }
1627
1628 //
1629 // Get next line
1630 //
1631 LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
1632 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1633 break;
1634
1635 case EdbEbcCodParseStateSymbolEnd:
1636 break;
1637
1638 default:
1639 break;
1640 }
1641 }
1642
1643 //
1644 // no function found
1645 //
1646 return NULL;
1647 }
1648
1649 CHAR8 *
1650 EdbLoadCodBySymbol (
1651 IN CHAR8 *Name,
1652 IN VOID *Buffer,
1653 IN UINTN BufferSize,
1654 OUT UINTN *CodeBufferSize,
1655 OUT UINTN *FuncOffset
1656 )
1657 /*++
1658
1659 Routine Description:
1660
1661 Load code by symbol
1662
1663 Arguments:
1664
1665 Name - Symbol file name
1666 BufferSize - Symbol file buffer size
1667 Buffer - Symbol file buffer
1668 CodeBufferSize - Code buffer size
1669 FuncOffset - Code funcion offset
1670
1671 Returns:
1672
1673 CodeBuffer
1674
1675 --*/
1676 {
1677 //
1678 // COD file format depends on the compiler.
1679 //
1680 // It is possible to check the different COD file format in this routine.
1681 // Now only IEC is supported.
1682 //
1683 return EdbLoadCodBySymbolByIec (Name, Buffer, BufferSize, CodeBufferSize, FuncOffset);
1684 }
1685
1686 VOID *
1687 EdbFindCodeFromObject (
1688 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
1689 IN EFI_DEBUGGER_SYMBOL_OBJECT *Object,
1690 IN CHAR16 *FileName
1691 )
1692 /*++
1693
1694 Routine Description:
1695
1696 Find code from object
1697
1698 Arguments:
1699
1700 Object - Symbol object
1701 FileName - File name
1702
1703 Returns:
1704
1705 CodeBuffer
1706
1707 --*/
1708 {
1709 UINTN EntryIndex;
1710
1711 //
1712 // Go througn each Entry in this Object
1713 //
1714 for (EntryIndex = 0; EntryIndex < Object->EntryCount; EntryIndex++) {
1715 //
1716 // This check is for Function only
1717 //
1718 if ((Object->Entry[EntryIndex].Type != EfiDebuggerSymbolFunction) &&
1719 (Object->Entry[EntryIndex].Type != EfiDebuggerSymbolStaticFunction)) {
1720 continue;
1721 }
1722 //
1723 // Skip match varbss_init function, because they has no source code
1724 //
1725 if (AsciiStrnCmp (Object->Entry[EntryIndex].Name, "varbss_init", sizeof("varbss_init") - 1) == 0) {
1726 continue;
1727 }
1728 //
1729 // check the name
1730 //
1731 if (!MatchObjAndCod (Object->Entry[EntryIndex].ObjName, FileName)) {
1732 continue;
1733 }
1734 //
1735 // found it, return source buffer
1736 //
1737 if (Object->Entry[EntryIndex].CodBuffer != NULL) {
1738 return Object->Entry[EntryIndex].SourceBuffer;
1739 }
1740 }
1741
1742 //
1743 // not found
1744 //
1745 return NULL;
1746 }
1747
1748 EFI_STATUS
1749 EdbLoadCode (
1750 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
1751 IN CHAR16 *MapFileName,
1752 IN CHAR16 *FileName,
1753 IN UINTN BufferSize,
1754 IN VOID *Buffer
1755 )
1756 /*++
1757
1758 Routine Description:
1759
1760 Load code
1761
1762 Arguments:
1763
1764 DebuggerPrivate - EBC Debugger private data structure
1765 MapFileName - Symbol file name
1766 FileName - Code file name
1767 BufferSize - Code file buffer size
1768 Buffer - Code file buffer
1769
1770 Returns:
1771
1772 EFI_SUCCESS - Code loaded successfully
1773
1774 --*/
1775 {
1776 EFI_DEBUGGER_SYMBOL_OBJECT *Object;
1777 UINTN ObjectIndex;
1778 UINTN EntryIndex;
1779 VOID *SourceBuffer;
1780 EFI_STATUS Status;
1781
1782 //
1783 // Find Symbol
1784 //
1785 Object = EdbFindSymbolFile (DebuggerPrivate, MapFileName, &ObjectIndex);
1786 if (Object == NULL) {
1787 EDBPrint (L"SymbolFile is not loaded!\n");
1788 return EFI_NOT_FOUND;
1789 } else {
1790 //
1791 // Check duplicated File
1792 //
1793 SourceBuffer = EdbFindCodeFromObject (DebuggerPrivate, Object, FileName);
1794 if (SourceBuffer != NULL) {
1795 //
1796 // unnload duplicated code
1797 //
1798 Status = EdbUnloadCode (DebuggerPrivate, MapFileName, FileName, &SourceBuffer);
1799 if (EFI_ERROR(Status)) {
1800 DEBUG ((DEBUG_ERROR, "Unload Duplicated Code File Error!\n"));
1801 return Status;
1802 }
1803 Status = EdbDeleteCodeBuffer (DebuggerPrivate, MapFileName, FileName, SourceBuffer);
1804 if (EFI_ERROR(Status)) {
1805 DEBUG ((DEBUG_ERROR, "Delete Duplicated Code File Error!\n"));
1806 return Status;
1807 }
1808 }
1809 }
1810
1811 //
1812 // Go through each SymbolEntry
1813 //
1814 for (EntryIndex = 0; EntryIndex < Object->EntryCount; EntryIndex++) {
1815 //
1816 // load symbol for function only
1817 //
1818 if ((Object->Entry[EntryIndex].Type != EfiDebuggerSymbolFunction) &&
1819 (Object->Entry[EntryIndex].Type != EfiDebuggerSymbolStaticFunction)) {
1820 continue;
1821 }
1822 //
1823 // skip varbss_init
1824 //
1825 if (AsciiStrnCmp (Object->Entry[EntryIndex].Name, "varbss_init", sizeof("varbss_init") - 1) == 0) {
1826 continue;
1827 }
1828 //
1829 // Check the name
1830 //
1831 if (!MatchObjAndCod (Object->Entry[EntryIndex].ObjName, FileName)) {
1832 continue;
1833 }
1834 //
1835 // load code for this symbol
1836 //
1837 Object->Entry[EntryIndex].CodBuffer = EdbLoadCodBySymbol (
1838 Object->Entry[EntryIndex].Name,
1839 Buffer,
1840 BufferSize,
1841 &Object->Entry[EntryIndex].CodBufferSize,
1842 &Object->Entry[EntryIndex].FuncOffsetBase
1843 );
1844 if (Object->Entry[EntryIndex].CodBuffer != NULL) {
1845 Object->Entry[EntryIndex].SourceBuffer = Buffer;
1846 }
1847 }
1848
1849 //
1850 // patch end '\0' for each code buffer
1851 //
1852 for (EntryIndex = 0; EntryIndex < Object->EntryCount; EntryIndex++) {
1853 if (Object->Entry[EntryIndex].CodBuffer != NULL) {
1854 *((UINT8 *)Object->Entry[EntryIndex].CodBuffer + Object->Entry[EntryIndex].CodBufferSize) = 0;
1855 DEBUG ((DEBUG_ERROR, " CodeSymbol: %a, FuncOffset: 0x05%x\n", Object->Entry[EntryIndex].Name, Object->Entry[EntryIndex].FuncOffsetBase));
1856 // DEBUG ((DEBUG_ERROR, " [CODE]:\n%a\n", Object->Entry[EntryIndex].CodBuffer));
1857 }
1858 }
1859
1860 //
1861 // Done
1862 //
1863 return EFI_SUCCESS;
1864 }
1865
1866 EFI_STATUS
1867 EdbUnloadCode (
1868 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
1869 IN CHAR16 *MapFileName,
1870 IN CHAR16 *FileName,
1871 OUT VOID **Buffer
1872 )
1873 /*++
1874
1875 Routine Description:
1876
1877 Unload code
1878
1879 Arguments:
1880
1881 DebuggerPrivate - EBC Debugger private data structure
1882 MapFileName - Symbol file name
1883 FileName - Code file name
1884 Buffer - Code file buffer
1885
1886 Returns:
1887
1888 EFI_SUCCESS - Code unloaded successfully
1889
1890 --*/
1891 {
1892 EFI_DEBUGGER_SYMBOL_OBJECT *Object;
1893 UINTN ObjectIndex;
1894 UINTN EntryIndex;
1895
1896 //
1897 // Find Symbol
1898 //
1899 Object = EdbFindSymbolFile (DebuggerPrivate, MapFileName, &ObjectIndex);
1900 if (Object == NULL) {
1901 EDBPrint (L"SymbolFile is not loaded!\n");
1902 return EFI_NOT_FOUND;
1903 }
1904
1905 //
1906 // Find code
1907 //
1908 *Buffer = EdbFindCodeFromObject (DebuggerPrivate, Object, FileName);
1909 if (*Buffer == NULL) {
1910 EDBPrint (L"CodeFile is not loaded!\n");
1911 return EFI_NOT_FOUND;
1912 }
1913
1914 //
1915 // go through each entry
1916 //
1917 for (EntryIndex = 0; EntryIndex < Object->EntryCount; EntryIndex++) {
1918 if ((Object->Entry[EntryIndex].Type != EfiDebuggerSymbolFunction) &&
1919 (Object->Entry[EntryIndex].Type != EfiDebuggerSymbolStaticFunction)) {
1920 continue;
1921 }
1922 if (AsciiStrnCmp (Object->Entry[EntryIndex].Name, "varbss_init", sizeof("varbss_init") - 1) == 0) {
1923 continue;
1924 }
1925 if (!MatchObjAndCod (Object->Entry[EntryIndex].ObjName, FileName)) {
1926 continue;
1927 }
1928 //
1929 // clean up the buffer
1930 //
1931 Object->Entry[EntryIndex].CodBuffer = NULL;
1932 Object->Entry[EntryIndex].CodBufferSize = 0;
1933 Object->Entry[EntryIndex].FuncOffsetBase = 0;
1934 Object->Entry[EntryIndex].SourceBuffer = NULL;
1935 }
1936
1937 //
1938 // Done
1939 //
1940 return EFI_SUCCESS;
1941 }
1942
1943 EFI_STATUS
1944 EdbAddCodeBuffer (
1945 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
1946 IN CHAR16 *MapFileName,
1947 IN CHAR16 *CodeFileName,
1948 IN UINTN SourceBufferSize,
1949 IN VOID *SourceBuffer
1950 )
1951 /*++
1952
1953 Routine Description:
1954
1955 Add code buffer
1956
1957 Arguments:
1958
1959 DebuggerPrivate - EBC Debugger private data structure
1960 MapFileName - Symbol file name
1961 CodeFileName - Code file name
1962 SourceBufferSize- Code buffer size
1963 SourceBuffer - Code buffer
1964
1965 Returns:
1966
1967 EFI_SUCCESS - CodeBuffer added successfully
1968
1969 --*/
1970 {
1971 UINTN Index;
1972 EFI_DEBUGGER_SYMBOL_OBJECT *Object;
1973
1974 //
1975 // Find Symbol
1976 //
1977 Object = EdbFindSymbolFile (DebuggerPrivate, MapFileName, NULL);
1978 if (Object == NULL) {
1979 EDBPrint (L"SymbolFile is not loaded!\n");
1980 return EFI_NOT_FOUND;
1981 }
1982
1983 //
1984 // Add it to last entry
1985 //
1986 for (Index = 0; Object->SourceBuffer[Index] != NULL; Index++) {
1987 ;
1988 }
1989 Object->SourceBuffer[Index] = SourceBuffer;
1990
1991 return EFI_SUCCESS;
1992 }
1993
1994 EFI_STATUS
1995 EdbDeleteCodeBuffer (
1996 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
1997 IN CHAR16 *MapFileName,
1998 IN CHAR16 *CodeFileName,
1999 IN VOID *SourceBuffer
2000 )
2001 /*++
2002
2003 Routine Description:
2004
2005 Delete code buffer
2006
2007 Arguments:
2008
2009 DebuggerPrivate - EBC Debugger private data structure
2010 MapFileName - Symbol file name
2011 CodeFileName - Code file name
2012 SourceBuffer - Code buffer
2013
2014 Returns:
2015
2016 EFI_SUCCESS - CodeBuffer deleted successfully
2017
2018 --*/
2019 {
2020 UINTN Index;
2021 EFI_DEBUGGER_SYMBOL_OBJECT *Object;
2022
2023 //
2024 // Find Symbol
2025 //
2026 Object = EdbFindSymbolFile (DebuggerPrivate, MapFileName, NULL);
2027 if (Object == NULL) {
2028 EDBPrint (L"SymbolFile is not loaded!\n");
2029 return EFI_NOT_FOUND;
2030 }
2031
2032 for (Index = 0; Object->SourceBuffer[Index] != NULL; Index++) {
2033 //
2034 // free the buffer if match
2035 //
2036 if (Object->SourceBuffer[Index] == SourceBuffer) {
2037 gBS->FreePool (SourceBuffer);
2038 break;
2039 }
2040 }
2041
2042 if (Object->SourceBuffer[Index] == NULL) {
2043 //
2044 // not return NOT_FOUND
2045 //
2046 return EFI_SUCCESS;
2047 }
2048
2049 //
2050 // remove the entry
2051 //
2052 Object->SourceBuffer[Index] = NULL;
2053 for (Index = Index + 1; Object->SourceBuffer[Index] != NULL; Index++) {
2054 Object->SourceBuffer[Index - 1] = Object->SourceBuffer[Index];
2055 }
2056 Object->SourceBuffer[Index - 1] = NULL;
2057
2058 return EFI_SUCCESS;
2059 }
2060
2061 CHAR8 *
2062 FindSymbolStr (
2063 IN UINTN Address
2064 )
2065 /*++
2066
2067 Routine Description:
2068
2069 Find the symbol string according to address
2070
2071 Arguments:
2072
2073 Address - Symbol address
2074
2075 Returns:
2076
2077 Symbol string
2078
2079 --*/
2080 {
2081 UINTN ObjectIndex;
2082 EFI_DEBUGGER_SYMBOL_OBJECT *Object;
2083 UINTN EntryIndex;
2084 EFI_DEBUGGER_SYMBOL_ENTRY *Entry;
2085
2086 //
2087 // need we display symbol
2088 //
2089 if (!mDebuggerPrivate.DebuggerSymbolContext.DisplaySymbol) {
2090 return NULL;
2091 }
2092
2093 //
2094 // Go through each object and entry
2095 //
2096 Object = mDebuggerPrivate.DebuggerSymbolContext.Object;
2097 for (ObjectIndex = 0; ObjectIndex < mDebuggerPrivate.DebuggerSymbolContext.ObjectCount; ObjectIndex++) {
2098 Entry = Object[ObjectIndex].Entry;
2099 for (EntryIndex = 0; EntryIndex < Object[ObjectIndex].EntryCount; EntryIndex++) {
2100 //
2101 // if Address match, return Name
2102 //
2103 if (Address == (Entry[EntryIndex].RVA + Object[ObjectIndex].BaseAddress)) {
2104 return Entry[EntryIndex].Name;
2105 }
2106 }
2107 }
2108
2109 //
2110 // not found
2111 //
2112 return NULL;
2113 }
2114
2115 UINTN
2116 EdbGetLineNumberAndOffsetFromThisLine (
2117 IN VOID *Line,
2118 OUT UINTN *Offset
2119 )
2120 /*++
2121
2122 Routine Description:
2123
2124 Get line number and offset from this line in code file
2125
2126 Arguments:
2127
2128 Line - Line buffer in code file
2129 Offset - Offset to functin entry
2130
2131 Returns:
2132
2133 Line number
2134
2135 --*/
2136 {
2137 UINTN LineNumber;
2138 CHAR8 *LineBuffer;
2139 CHAR8 *FieldBuffer;
2140
2141 LineNumber = (UINTN)-1;
2142 LineBuffer = Line;
2143 *Offset = (UINTN)-1;
2144
2145 while (LineBuffer != NULL) {
2146 //
2147 // Check candidate
2148 //
2149 if (*LineBuffer != ' ') {
2150 return (UINTN)-1;
2151 }
2152
2153 //
2154 // Get Offset
2155 //
2156 if (*(LineBuffer + 2) != ' ') {
2157 if (*Offset == (UINTN)-1) {
2158 FieldBuffer = AsciiStrGetNewTokenField (LineBuffer + 2, " ");
2159 *Offset = AsciiXtoi (FieldBuffer);
2160 PatchForAsciiStrTokenAfter (FieldBuffer, ' ');
2161 }
2162 }
2163
2164 //
2165 // 1. assembly instruction
2166 //
2167 FieldBuffer = AsciiStrGetNewTokenField (LineBuffer, ":");
2168 //
2169 // 2. file path
2170 //
2171 FieldBuffer = AsciiStrGetNextTokenField (":");
2172 PatchForAsciiStrTokenBefore (FieldBuffer, ':');
2173 if (FieldBuffer == NULL) {
2174 //
2175 // candidate found
2176 //
2177 LineNumber = 0;
2178 LineBuffer = AsciiStrGetNextTokenLine ("\n");
2179 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
2180 continue;
2181 }
2182 //
2183 // 3. line number
2184 //
2185 FieldBuffer = AsciiStrGetNextTokenField (":");
2186 PatchForAsciiStrTokenBefore (FieldBuffer, ':');
2187 if (FieldBuffer == NULL) {
2188 //
2189 // impossible, TBD?
2190 //
2191 LineBuffer = AsciiStrGetNextTokenLine ("\n");
2192 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
2193 continue;
2194 }
2195
2196 LineNumber = AsciiAtoi (FieldBuffer);
2197 //
2198 // Not patch after
2199 //
2200
2201 return LineNumber;
2202 }
2203
2204 return (UINTN)-1;
2205 }
2206
2207 typedef enum {
2208 EdbEbcLineSearchTypeAny,
2209 EdbEbcLineSearchTypeFirst,
2210 EdbEbcLineSearchTypeLast,
2211 EdbEbcLineSearchTypeMax,
2212 } EDB_EBC_LINE_SEARCH_TYPE;
2213
2214 UINTN
2215 EdbGetLineNumberFromCode (
2216 IN EFI_DEBUGGER_SYMBOL_ENTRY *Entry,
2217 IN UINTN FuncOffset,
2218 IN EDB_EBC_LINE_SEARCH_TYPE SearchType
2219 )
2220 /*++
2221
2222 Routine Description:
2223
2224 Get line number from this code file
2225
2226 Arguments:
2227
2228 Entry - Symbol entry
2229 FuncOffset - Offset to functin entry
2230 SearchType - Search type for the code
2231
2232 Returns:
2233
2234 Line number
2235
2236 --*/
2237 {
2238 CHAR8 *LineBuffer;
2239 UINTN LineNumber;
2240 UINTN Offset;
2241 UINTN CandidateLineNumber;
2242 UINTN CandidateOffset;
2243
2244 if (SearchType < 0 || SearchType >= EdbEbcLineSearchTypeMax) {
2245 return (UINTN)-1;
2246 }
2247
2248 LineNumber = (UINTN)-1;
2249 CandidateLineNumber = (UINTN)-1;
2250 CandidateOffset = (UINTN)-1;
2251 LineBuffer = AsciiStrGetNewTokenLine (Entry->CodBuffer, "\n");
2252 while (LineBuffer != NULL) {
2253 if (*LineBuffer != ' ') {
2254 LineBuffer = AsciiStrGetNextTokenLine ("\n");
2255 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
2256 continue;
2257 }
2258
2259 //
2260 // Get Info
2261 //
2262 LineNumber = EdbGetLineNumberAndOffsetFromThisLine (LineBuffer, &Offset);
2263
2264 //
2265 // Check offset
2266 //
2267 if (Offset != FuncOffset) {
2268 //
2269 // Check last offset match
2270 //
2271 if (CandidateOffset == FuncOffset) {
2272 if (SearchType == EdbEbcLineSearchTypeLast) {
2273 PatchForAsciiStrTokenAfter (LineBuffer, '\n');
2274 if (CandidateLineNumber != LineNumber) {
2275 return CandidateLineNumber;
2276 } else {
2277 return (UINTN)-1;
2278 }
2279 } else {
2280 //
2281 // impossible, TBD?
2282 //
2283 }
2284 }
2285
2286 LineBuffer = AsciiStrGetNextTokenLine ("\n");
2287 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
2288 CandidateLineNumber = LineNumber;
2289 continue;
2290 }
2291
2292 //
2293 // Offset match, more check
2294 //
2295 if (SearchType == EdbEbcLineSearchTypeAny) {
2296 PatchForAsciiStrTokenAfter (LineBuffer, '\n');
2297 return LineNumber;
2298 }
2299
2300 if (SearchType == EdbEbcLineSearchTypeFirst) {
2301 //
2302 // Check last line
2303 //
2304 PatchForAsciiStrTokenAfter (LineBuffer, '\n');
2305 if (CandidateLineNumber != LineNumber) {
2306 return LineNumber;
2307 } else {
2308 return (UINTN)-1;
2309 }
2310 }
2311
2312 CandidateLineNumber = LineNumber;
2313 CandidateOffset = Offset;
2314
2315 LineBuffer = AsciiStrGetNextTokenLine ("\n");
2316 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
2317 }
2318
2319 //
2320 // Check last offset match
2321 //
2322 if (CandidateOffset == FuncOffset) {
2323 if (SearchType == EdbEbcLineSearchTypeLast) {
2324 return CandidateLineNumber;
2325 }
2326 }
2327
2328 return (UINTN)-1;
2329 }
2330
2331 VOID *
2332 EdbGetSourceStrFromCodeByLine (
2333 IN EFI_DEBUGGER_SYMBOL_ENTRY *Entry,
2334 IN UINTN LineNumber,
2335 IN VOID **FuncEnd
2336 )
2337 /*++
2338
2339 Routine Description:
2340
2341 Get the source string from this code file by line
2342
2343 Arguments:
2344
2345 Entry - Symbol entry
2346 LineNumber - line number
2347 FuncEnd - Function end
2348
2349 Returns:
2350
2351 Funtion start
2352
2353 --*/
2354 {
2355 CHAR8 *LineBuffer;
2356 CHAR8 *FieldBuffer;
2357 VOID *FuncStart;
2358 UINTN Number;
2359
2360 FuncStart = NULL;
2361 LineBuffer = AsciiStrGetNewTokenLine (Entry->CodBuffer, "\n");
2362 while (LineBuffer != NULL) {
2363 if (*LineBuffer != ';') {
2364 if (FuncStart != NULL) {
2365 //
2366 // Over
2367 //
2368 *FuncEnd = LineBuffer - 1;
2369 PatchForAsciiStrTokenAfter (LineBuffer, '\n');
2370 return FuncStart;
2371 }
2372 LineBuffer = AsciiStrGetNextTokenLine ("\n");
2373 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
2374 continue;
2375 }
2376
2377 //
2378 // Check LineNumber
2379 //
2380 FieldBuffer = AsciiStrGetNewTokenField (LineBuffer + 1, " ");
2381 Number = AsciiAtoi (FieldBuffer);
2382 PatchForAsciiStrTokenAfter (FieldBuffer, ' ');
2383 if (Number != LineNumber) {
2384 LineBuffer = AsciiStrGetNextTokenLine ("\n");
2385 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
2386 continue;
2387 }
2388
2389 //
2390 // Line match, get line number
2391 //
2392 if (FuncStart == NULL) {
2393 FuncStart = LineBuffer;
2394 }
2395
2396 LineBuffer = AsciiStrGetNextTokenLine ("\n");
2397 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
2398 }
2399
2400 return NULL;
2401 }
2402
2403 VOID *
2404 EdbGetSourceStrFromCode (
2405 IN EFI_DEBUGGER_SYMBOL_ENTRY *Entry,
2406 IN UINTN FuncOffset,
2407 IN VOID **FuncEnd
2408 )
2409 /*++
2410
2411 Routine Description:
2412
2413 Get source string from this code file
2414
2415 Arguments:
2416
2417 Entry - Symbol entry
2418 FuncOffset - Offset to functin entry
2419 FuncEnd - Function end
2420
2421 Returns:
2422
2423 Funtion start
2424
2425 --*/
2426 {
2427 UINTN LineNumber;
2428
2429 //
2430 // Only search the last line, then display
2431 //
2432 LineNumber = EdbGetLineNumberFromCode (Entry, FuncOffset, EdbEbcLineSearchTypeLast);
2433 if (LineNumber == (UINTN)-1) {
2434 return NULL;
2435 }
2436
2437 return EdbGetSourceStrFromCodeByLine (Entry, LineNumber, FuncEnd);
2438 }
2439
2440 UINTN
2441 EdbPrintSource (
2442 IN UINTN Address,
2443 IN BOOLEAN IsPrint
2444 )
2445 /*++
2446
2447 Routine Description:
2448
2449 Print source
2450
2451 Arguments:
2452
2453 Address - Instruction address
2454 IsPrint - Whether need to print
2455
2456 Returns:
2457
2458 1 - find the source
2459 0 - not find the source
2460
2461 --*/
2462 {
2463 UINTN SymbolAddress;
2464 EFI_DEBUGGER_SYMBOL_OBJECT *RetObject;
2465 EFI_DEBUGGER_SYMBOL_ENTRY *RetEntry;
2466 UINTN FuncOffset;
2467 UINT8 *FuncStart;
2468 UINT8 *FuncEnd;
2469 UINT8 *FuncIndex;
2470 CHAR8 Buffer[EFI_DEBUG_MAX_PRINT_BUFFER];
2471 UINTN BufferSize;
2472
2473 //
2474 // need we display symbol
2475 //
2476 if (!mDebuggerPrivate.DebuggerSymbolContext.DisplaySymbol) {
2477 return 0 ;
2478 }
2479
2480 //
2481 // find the symbol address
2482 //
2483 SymbolAddress = EbdFindSymbolAddress (
2484 Address,
2485 EdbMatchSymbolTypeLowerAddress,
2486 &RetObject,
2487 &RetEntry
2488 );
2489 if (SymbolAddress == 0) {
2490 return 0 ;
2491 }
2492
2493 FuncOffset = Address - SymbolAddress + RetEntry->FuncOffsetBase;
2494
2495 //
2496 // Get Func String
2497 //
2498 FuncStart = EdbGetSourceStrFromCode (RetEntry, FuncOffset, (VOID**) &FuncEnd);
2499 if (FuncStart == NULL) {
2500 return 0 ;
2501 }
2502
2503 //
2504 // check whether need to real print
2505 //
2506 if (!IsPrint) {
2507 return 1;
2508 }
2509
2510 *(UINT8 *)FuncEnd = 0;
2511
2512 //
2513 // seperate buffer by \n, so that \r can be added.
2514 //
2515 FuncIndex = FuncStart;
2516 while (*FuncIndex != 0) {
2517 if (*FuncIndex == '\n') {
2518 if ((FuncIndex - FuncStart) < (EFI_DEBUG_MAX_PRINT_BUFFER - 3)) {
2519 BufferSize = FuncIndex - FuncStart;
2520 } else {
2521 BufferSize = EFI_DEBUG_MAX_PRINT_BUFFER - 3;
2522 }
2523 if (BufferSize != 0) {
2524 CopyMem (Buffer, FuncStart, BufferSize);
2525 }
2526 Buffer[BufferSize] = 0;
2527 EDBPrint (L"%a\n", Buffer);
2528 FuncStart = FuncIndex + 1;
2529 FuncIndex = FuncStart;
2530 } else {
2531 FuncIndex ++;
2532 }
2533 }
2534
2535 //
2536 // Patch the end
2537 //
2538 *(UINT8 *)FuncEnd = '\n';
2539
2540 return 1 ;
2541 }
2542
2543 VOID
2544 GetMapfileAndSymbol (
2545 IN CHAR16 *Symbol,
2546 OUT CHAR16 **MapfileName,
2547 OUT CHAR16 **SymbolName
2548 )
2549 /*++
2550
2551 Routine Description:
2552
2553 Get Mapfile and SymbolName from one symbol format: [MapFileName:]SymbolName
2554
2555 Arguments:
2556
2557 Symbol - whole Symbol name
2558 MapfileName - the mapfile name in the symbol
2559 SymbolName - the symbol name in the symbol
2560
2561 Returns:
2562
2563 None
2564
2565 --*/
2566 {
2567 CHAR16 *Ch;
2568
2569 *MapfileName = NULL;
2570 *SymbolName = Symbol;
2571
2572 for (Ch = Symbol; *Ch != 0; Ch++) {
2573 //
2574 // Find split char
2575 //
2576 if (*Ch == L':') {
2577 *MapfileName = Symbol;
2578 *Ch = 0;
2579 *SymbolName = Ch + 1;
2580 break;
2581 }
2582 }
2583
2584 return ;
2585 }
2586
2587 EFI_STATUS
2588 Symboltoi (
2589 IN CHAR16 *Symbol,
2590 OUT UINTN *Address
2591 )
2592 /*++
2593
2594 Routine Description:
2595
2596 Convert a symbol to an address
2597
2598 Arguments:
2599
2600 Symbol - Symbol name
2601 Address - Symbol address
2602
2603 Returns:
2604
2605 EFI_SUCCESS - symbol found and address returned.
2606 EFI_NOT_FOUND - symbol not found
2607 EFI_NO_MAPPING - duplicated symbol not found
2608
2609 --*/
2610 {
2611 UINTN ObjectIndex;
2612 EFI_DEBUGGER_SYMBOL_OBJECT *Object;
2613 UINTN EntryIndex;
2614 EFI_DEBUGGER_SYMBOL_ENTRY *Entry;
2615 CHAR16 *SymbolName;
2616 CHAR16 *MapfileName;
2617
2618 //
2619 // Split one symbol to mapfile name and symbol name
2620 //
2621 GetMapfileAndSymbol (Symbol, &MapfileName, &SymbolName);
2622
2623 *Address = 0;
2624 //
2625 // Go through each object
2626 //
2627 Object = mDebuggerPrivate.DebuggerSymbolContext.Object;
2628 for (ObjectIndex = 0; ObjectIndex < mDebuggerPrivate.DebuggerSymbolContext.ObjectCount; ObjectIndex++) {
2629 //
2630 // Check MapfileName
2631 //
2632 if ((MapfileName != NULL) && (StriCmp (Object[ObjectIndex].Name, MapfileName) != 0)) {
2633 continue;
2634 }
2635 //
2636 // Go through each entry
2637 //
2638 Entry = Object[ObjectIndex].Entry;
2639 for (EntryIndex = 0; EntryIndex < Object[ObjectIndex].EntryCount; EntryIndex++) {
2640 //
2641 // Check SymbolName (case sensitive)
2642 //
2643 if (StrCmpUnicodeAndAscii (SymbolName, Entry[EntryIndex].Name) == 0) {
2644 if ((*Address != 0) && (MapfileName == NULL)) {
2645 //
2646 // Find the duplicated symbol
2647 //
2648 EDBPrint (L"Duplicated Symbol found!\n");
2649 return EFI_NO_MAPPING;
2650 } else {
2651 //
2652 // record Address
2653 //
2654 *Address = (Entry[EntryIndex].RVA + Object[ObjectIndex].BaseAddress);
2655 }
2656 }
2657 }
2658 }
2659
2660 if (*Address == 0) {
2661 //
2662 // Not found
2663 //
2664 return EFI_NOT_FOUND;
2665 }
2666
2667 return EFI_SUCCESS;
2668 }