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
EdbLoadSymbolSingleEntry(IN EFI_DEBUGGER_SYMBOL_OBJECT * Object,IN CHAR8 * Name,IN CHAR8 * ObjName,IN UINTN Address,IN EFI_DEBUGGER_SYMBOL_TYPE Type)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
EdbLoadSymbolEntryByIec(IN EFI_DEBUGGER_SYMBOL_OBJECT * Object,IN UINTN BufferSize,IN VOID * Buffer)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
EdbLoadSymbolEntry(IN EFI_DEBUGGER_SYMBOL_OBJECT * Object,IN UINTN BufferSize,IN VOID * Buffer)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 *
EdbFindSymbolFile(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN CHAR16 * FileName,IN OUT UINTN * Index OPTIONAL)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
EbdFindSymbolAddress(IN UINTN Address,IN EDB_MATCH_SYMBOL_TYPE Type,OUT EFI_DEBUGGER_SYMBOL_OBJECT ** RetObject,OUT EFI_DEBUGGER_SYMBOL_ENTRY ** RetEntry)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
EdbUnloadSymbol(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN CHAR16 * FileName)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
EdbLoadSymbol(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN CHAR16 * FileName,IN UINTN BufferSize,IN VOID * Buffer)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 *
GetPdbPath(VOID * ImageBase)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
MatchPdbAndMap(IN CHAR8 * PdbFileName,IN CHAR16 * MapFileName)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
EdbFixDebugImageInfoTable(IN OUT EFI_DEBUG_IMAGE_INFO_TABLE_HEADER ** DebugImageInfoTableHeader)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
EdbPatchSymbolRVA(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN CHAR16 * FileName,IN EDB_EBC_IMAGE_RVA_SEARCH_TYPE SearchType)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
MatchObjAndCod(IN CHAR8 * ObjFileName,IN CHAR16 * CodFileName)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 *
EdbLoadCodBySymbolByIec(IN CHAR8 * Name,IN VOID * Buffer,IN UINTN BufferSize,OUT UINTN * CodeBufferSize,OUT UINTN * FuncOffset)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 *
EdbLoadCodBySymbol(IN CHAR8 * Name,IN VOID * Buffer,IN UINTN BufferSize,OUT UINTN * CodeBufferSize,OUT UINTN * FuncOffset)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 *
EdbFindCodeFromObject(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN EFI_DEBUGGER_SYMBOL_OBJECT * Object,IN CHAR16 * FileName)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
EdbLoadCode(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN CHAR16 * MapFileName,IN CHAR16 * FileName,IN UINTN BufferSize,IN VOID * Buffer)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
EdbUnloadCode(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN CHAR16 * MapFileName,IN CHAR16 * FileName,OUT VOID ** Buffer)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
EdbAddCodeBuffer(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN CHAR16 * MapFileName,IN CHAR16 * CodeFileName,IN UINTN SourceBufferSize,IN VOID * SourceBuffer)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
EdbDeleteCodeBuffer(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN CHAR16 * MapFileName,IN CHAR16 * CodeFileName,IN VOID * SourceBuffer)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 *
FindSymbolStr(IN UINTN Address)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
EdbGetLineNumberAndOffsetFromThisLine(IN VOID * Line,OUT UINTN * Offset)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
EdbGetLineNumberFromCode(IN EFI_DEBUGGER_SYMBOL_ENTRY * Entry,IN UINTN FuncOffset,IN EDB_EBC_LINE_SEARCH_TYPE SearchType)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 *
EdbGetSourceStrFromCodeByLine(IN EFI_DEBUGGER_SYMBOL_ENTRY * Entry,IN UINTN LineNumber,IN VOID ** FuncEnd)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 *
EdbGetSourceStrFromCode(IN EFI_DEBUGGER_SYMBOL_ENTRY * Entry,IN UINTN FuncOffset,IN VOID ** FuncEnd)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
EdbPrintSource(IN UINTN Address,IN BOOLEAN IsPrint)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
GetMapfileAndSymbol(IN CHAR16 * Symbol,OUT CHAR16 ** MapfileName,OUT CHAR16 ** SymbolName)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
Symboltoi(IN CHAR16 * Symbol,OUT UINTN * Address)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 }
2231