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