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