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