1 /** @file
2 
3 Copyright (c) 2007 - 2016, Intel Corporation. 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
EdbLoadSymbolSingleEntry(IN EFI_DEBUGGER_SYMBOL_OBJECT * Object,IN CHAR8 * Name,IN CHAR8 * ObjName,IN UINTN Address,IN EFI_DEBUGGER_SYMBOL_TYPE Type)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
EdbLoadSymbolEntryByIec(IN EFI_DEBUGGER_SYMBOL_OBJECT * Object,IN UINTN BufferSize,IN VOID * Buffer)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
EdbLoadSymbolEntry(IN EFI_DEBUGGER_SYMBOL_OBJECT * Object,IN UINTN BufferSize,IN VOID * Buffer)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 *
EdbFindSymbolFile(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN CHAR16 * FileName,IN OUT UINTN * Index OPTIONAL)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
EbdFindSymbolAddress(IN UINTN Address,IN EDB_MATCH_SYMBOL_TYPE Type,OUT EFI_DEBUGGER_SYMBOL_OBJECT ** RetObject,OUT EFI_DEBUGGER_SYMBOL_ENTRY ** RetEntry)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
EdbUnloadSymbol(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN CHAR16 * FileName)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
EdbLoadSymbol(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN CHAR16 * FileName,IN UINTN BufferSize,IN VOID * Buffer)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 *
GetPdbPath(VOID * ImageBase)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
MatchPdbAndMap(IN CHAR8 * PdbFileName,IN CHAR16 * MapFileName)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
EdbFixDebugImageInfoTable(IN OUT EFI_DEBUG_IMAGE_INFO_TABLE_HEADER ** DebugImageInfoTableHeader)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
EdbPatchSymbolRVA(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN CHAR16 * FileName,IN EDB_EBC_IMAGE_RVA_SEARCH_TYPE SearchType)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
MatchObjAndCod(IN CHAR8 * ObjFileName,IN CHAR16 * CodFileName)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 *
EdbLoadCodBySymbolByIec(IN CHAR8 * Name,IN VOID * Buffer,IN UINTN BufferSize,OUT UINTN * CodeBufferSize,OUT UINTN * FuncOffset)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];
1187 
1188   //
1189   // Init
1190   //
1191   Char[0] = 9;
1192   Char[1] = 0;
1193   LineBuffer = AsciiStrGetNewTokenLine (Buffer, "\n\r");
1194   Offset = (UINTN)-1;
1195   BufferStart = NULL;
1196   BufferEnd = NULL;
1197   CodParseState = EdbEbcCodParseStateUninitialized;
1198 
1199   //
1200   // Check each line
1201   //
1202   while (LineBuffer != NULL) {
1203     switch (CodParseState) {
1204     case EdbEbcCodParseStateUninitialized:
1205       //
1206       // check mark_begin, begin to check line after this match
1207       //
1208       if (AsciiStrCmp (LineBuffer, "; mark_begin;") == 0) {
1209         CodParseState = EdbEbcCodParseStateSymbolInitialized;
1210       }
1211       LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
1212       PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1213       break;
1214 
1215     case EdbEbcCodParseStateSymbolInitialized:
1216       //
1217       // check mark_end, not check line after this match
1218       //
1219       if (AsciiStrCmp (LineBuffer, "; mark_end;") == 0) {
1220         CodParseState = EdbEbcCodParseStateUninitialized;
1221         LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
1222         PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1223         break;
1224       }
1225 
1226       //
1227       // not check this line if the first char is as follows
1228       //
1229       if ((*LineBuffer == 0)   ||
1230           (*LineBuffer == '$') ||
1231           (*LineBuffer == ';') ||
1232           (*LineBuffer == '_') ||
1233           (*LineBuffer == ' ')) {
1234         LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
1235         PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1236         break;
1237       }
1238 
1239       //
1240       // get function name, function name is followed by char 0x09.
1241       //
1242       FieldBuffer = AsciiStrGetNewTokenField (LineBuffer, Char);
1243       ASSERT (FieldBuffer != NULL);
1244       if (AsciiStriCmp (FieldBuffer, Name) == 0) {
1245         BufferStart = FieldBuffer;
1246         CodParseState = EdbEbcCodParseStateSymbolStart;
1247       }
1248       PatchForAsciiStrTokenAfter (FieldBuffer, 0x9);
1249 
1250       //
1251       // Get next line
1252       //
1253       LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
1254       PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1255       break;
1256 
1257     case EdbEbcCodParseStateSymbolStart:
1258       //
1259       // check mark_end, if this match, means the function is found successfully.
1260       //
1261       if (AsciiStrCmp (LineBuffer, "; mark_end;") == 0) {
1262         CodParseState = EdbEbcCodParseStateSymbolEnd;
1263         //
1264         // prepare CodeBufferSize, FuncOffset, and FuncStart to return
1265         //
1266         BufferEnd = LineBuffer + sizeof("; mark_end;") - 1;
1267         *CodeBufferSize = (UINTN)BufferEnd - (UINTN)BufferStart;
1268         *FuncOffset = Offset;
1269         PatchForAsciiStrTokenAfter (LineBuffer, '\n');
1270         return BufferStart;
1271       }
1272 
1273       //
1274       // Get function offset
1275       //
1276       if ((Offset == (UINTN)-1) &&
1277           (*LineBuffer == ' ')) {
1278         FieldBuffer = AsciiStrGetNewTokenField (LineBuffer + 2, " ");
1279         Offset = AsciiXtoi (FieldBuffer);
1280         PatchForAsciiStrTokenAfter (FieldBuffer, ' ');
1281       }
1282 
1283       //
1284       // Get next line
1285       //
1286       LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
1287       PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1288       break;
1289 
1290     case EdbEbcCodParseStateSymbolEnd:
1291       break;
1292 
1293     default:
1294       break;
1295     }
1296   }
1297 
1298   //
1299   // no function found
1300   //
1301   return NULL;
1302 }
1303 
1304 /**
1305 
1306   Load code by symbol.
1307 
1308   @param  Name            - Symbol file name
1309   @param  Buffer          - Symbol file buffer
1310   @param  BufferSize      - Symbol file buffer size
1311   @param  CodeBufferSize  - Code buffer size
1312   @param  FuncOffset      - Code funcion offset
1313 
1314   @return CodeBuffer
1315 
1316 **/
1317 CHAR8 *
EdbLoadCodBySymbol(IN CHAR8 * Name,IN VOID * Buffer,IN UINTN BufferSize,OUT UINTN * CodeBufferSize,OUT UINTN * FuncOffset)1318 EdbLoadCodBySymbol (
1319   IN CHAR8                       *Name,
1320   IN VOID                        *Buffer,
1321   IN UINTN                       BufferSize,
1322   OUT UINTN                      *CodeBufferSize,
1323   OUT UINTN                      *FuncOffset
1324   )
1325 {
1326   //
1327   // COD file format depends on the compiler.
1328   //
1329   // It is possible to check the different COD file format in this routine.
1330   // Now only IEC is supported.
1331   //
1332   return EdbLoadCodBySymbolByIec (Name, Buffer, BufferSize, CodeBufferSize, FuncOffset);
1333 }
1334 
1335 /**
1336 
1337   Find code from object.
1338 
1339   @param  DebuggerPrivate    EBC Debugger private data structure
1340   @param  Object          - Symbol object
1341   @param  FileName        - File name
1342 
1343 **/
1344 VOID *
EdbFindCodeFromObject(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN EFI_DEBUGGER_SYMBOL_OBJECT * Object,IN CHAR16 * FileName)1345 EdbFindCodeFromObject (
1346   IN EFI_DEBUGGER_PRIVATE_DATA   *DebuggerPrivate,
1347   IN EFI_DEBUGGER_SYMBOL_OBJECT  *Object,
1348   IN CHAR16                      *FileName
1349   )
1350 {
1351   UINTN                      EntryIndex;
1352 
1353   //
1354   // Go througn each Entry in this Object
1355   //
1356   for (EntryIndex = 0; EntryIndex < Object->EntryCount; EntryIndex++) {
1357     //
1358     // This check is for Function only
1359     //
1360     if ((Object->Entry[EntryIndex].Type != EfiDebuggerSymbolFunction) &&
1361         (Object->Entry[EntryIndex].Type != EfiDebuggerSymbolStaticFunction)) {
1362       continue;
1363     }
1364     //
1365     // Skip match varbss_init function, because they has no source code
1366     //
1367     if (AsciiStrnCmp (Object->Entry[EntryIndex].Name, "varbss_init", sizeof("varbss_init") - 1) == 0) {
1368       continue;
1369     }
1370     //
1371     // check the name
1372     //
1373     if (!MatchObjAndCod (Object->Entry[EntryIndex].ObjName, FileName)) {
1374       continue;
1375     }
1376     //
1377     // found it, return source buffer
1378     //
1379     if (Object->Entry[EntryIndex].CodBuffer != NULL) {
1380       return Object->Entry[EntryIndex].SourceBuffer;
1381     }
1382   }
1383 
1384   //
1385   // not found
1386   //
1387   return NULL;
1388 }
1389 
1390 /**
1391 
1392   Load code.
1393 
1394   @param  DebuggerPrivate - EBC Debugger private data structure
1395   @param  MapFileName     - Symbol file name
1396   @param  FileName        - Code file name
1397   @param  BufferSize      - Code file buffer size
1398   @param  Buffer          - Code file buffer
1399 
1400   @retval EFI_SUCCESS - Code loaded successfully
1401 
1402 **/
1403 EFI_STATUS
EdbLoadCode(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN CHAR16 * MapFileName,IN CHAR16 * FileName,IN UINTN BufferSize,IN VOID * Buffer)1404 EdbLoadCode (
1405   IN EFI_DEBUGGER_PRIVATE_DATA   *DebuggerPrivate,
1406   IN CHAR16                      *MapFileName,
1407   IN CHAR16                      *FileName,
1408   IN UINTN                       BufferSize,
1409   IN VOID                        *Buffer
1410   )
1411 {
1412   EFI_DEBUGGER_SYMBOL_OBJECT *Object;
1413   UINTN                      ObjectIndex;
1414   UINTN                      EntryIndex;
1415   VOID                       *SourceBuffer;
1416   EFI_STATUS                 Status;
1417 
1418   //
1419   // Find Symbol
1420   //
1421   Object = EdbFindSymbolFile (DebuggerPrivate, MapFileName, &ObjectIndex);
1422   if (Object == NULL) {
1423     EDBPrint (L"SymbolFile is not loaded!\n");
1424     return EFI_NOT_FOUND;
1425   } else {
1426     //
1427     // Check duplicated File
1428     //
1429     SourceBuffer = EdbFindCodeFromObject (DebuggerPrivate, Object, FileName);
1430     if (SourceBuffer != NULL) {
1431       //
1432       // unnload duplicated code
1433       //
1434       Status = EdbUnloadCode (DebuggerPrivate, MapFileName, FileName, &SourceBuffer);
1435       if (EFI_ERROR(Status)) {
1436         DEBUG ((DEBUG_ERROR, "Unload Duplicated Code File Error!\n"));
1437         return Status;
1438       }
1439       Status = EdbDeleteCodeBuffer (DebuggerPrivate, MapFileName, FileName, SourceBuffer);
1440       if (EFI_ERROR(Status)) {
1441         DEBUG ((DEBUG_ERROR, "Delete Duplicated Code File Error!\n"));
1442         return Status;
1443       }
1444     }
1445   }
1446 
1447   //
1448   // Go through each SymbolEntry
1449   //
1450   for (EntryIndex = 0; EntryIndex < Object->EntryCount; EntryIndex++) {
1451     //
1452     // load symbol for function only
1453     //
1454     if ((Object->Entry[EntryIndex].Type != EfiDebuggerSymbolFunction) &&
1455         (Object->Entry[EntryIndex].Type != EfiDebuggerSymbolStaticFunction)) {
1456       continue;
1457     }
1458     //
1459     // skip varbss_init
1460     //
1461     if (AsciiStrnCmp (Object->Entry[EntryIndex].Name, "varbss_init", sizeof("varbss_init") - 1) == 0) {
1462       continue;
1463     }
1464     //
1465     // Check the name
1466     //
1467     if (!MatchObjAndCod (Object->Entry[EntryIndex].ObjName, FileName)) {
1468       continue;
1469     }
1470     //
1471     // load code for this symbol
1472     //
1473     Object->Entry[EntryIndex].CodBuffer = EdbLoadCodBySymbol (
1474                                             Object->Entry[EntryIndex].Name,
1475                                             Buffer,
1476                                             BufferSize,
1477                                             &Object->Entry[EntryIndex].CodBufferSize,
1478                                             &Object->Entry[EntryIndex].FuncOffsetBase
1479                                             );
1480     if (Object->Entry[EntryIndex].CodBuffer != NULL) {
1481       Object->Entry[EntryIndex].SourceBuffer = Buffer;
1482     }
1483   }
1484 
1485   //
1486   // patch end '\0' for each code buffer
1487   //
1488   for (EntryIndex = 0; EntryIndex < Object->EntryCount; EntryIndex++) {
1489     if (Object->Entry[EntryIndex].CodBuffer != NULL) {
1490       *((UINT8 *)Object->Entry[EntryIndex].CodBuffer + Object->Entry[EntryIndex].CodBufferSize) = 0;
1491       DEBUG ((DEBUG_ERROR, "  CodeSymbol: %a, FuncOffset: 0x05%x\n", Object->Entry[EntryIndex].Name, Object->Entry[EntryIndex].FuncOffsetBase));
1492 //      DEBUG ((DEBUG_ERROR, "  [CODE]:\n%a\n", Object->Entry[EntryIndex].CodBuffer));
1493     }
1494   }
1495 
1496   //
1497   // Done
1498   //
1499   return EFI_SUCCESS;
1500 }
1501 
1502 /**
1503 
1504   Unload code.
1505 
1506   @param  DebuggerPrivate - EBC Debugger private data structure
1507   @param  MapFileName     - Symbol file name
1508   @param  FileName        - Code file name
1509   @param  Buffer          - Code file buffer
1510 
1511   @retval EFI_SUCCESS - Code unloaded successfully
1512 
1513 **/
1514 EFI_STATUS
EdbUnloadCode(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN CHAR16 * MapFileName,IN CHAR16 * FileName,OUT VOID ** Buffer)1515 EdbUnloadCode (
1516   IN EFI_DEBUGGER_PRIVATE_DATA   *DebuggerPrivate,
1517   IN CHAR16                      *MapFileName,
1518   IN CHAR16                      *FileName,
1519   OUT VOID                       **Buffer
1520   )
1521 {
1522   EFI_DEBUGGER_SYMBOL_OBJECT *Object;
1523   UINTN                      ObjectIndex;
1524   UINTN                      EntryIndex;
1525 
1526   //
1527   // Find Symbol
1528   //
1529   Object = EdbFindSymbolFile (DebuggerPrivate, MapFileName, &ObjectIndex);
1530   if (Object == NULL) {
1531     EDBPrint (L"SymbolFile is not loaded!\n");
1532     return EFI_NOT_FOUND;
1533   }
1534 
1535   //
1536   // Find code
1537   //
1538   *Buffer = EdbFindCodeFromObject (DebuggerPrivate, Object, FileName);
1539   if (*Buffer == NULL) {
1540     EDBPrint (L"CodeFile is not loaded!\n");
1541     return EFI_NOT_FOUND;
1542   }
1543 
1544   //
1545   // go through each entry
1546   //
1547   for (EntryIndex = 0; EntryIndex < Object->EntryCount; EntryIndex++) {
1548     if ((Object->Entry[EntryIndex].Type != EfiDebuggerSymbolFunction) &&
1549         (Object->Entry[EntryIndex].Type != EfiDebuggerSymbolStaticFunction)) {
1550       continue;
1551     }
1552     if (AsciiStrnCmp (Object->Entry[EntryIndex].Name, "varbss_init", sizeof("varbss_init") - 1) == 0) {
1553       continue;
1554     }
1555     if (!MatchObjAndCod (Object->Entry[EntryIndex].ObjName, FileName)) {
1556       continue;
1557     }
1558     //
1559     // clean up the buffer
1560     //
1561     Object->Entry[EntryIndex].CodBuffer = NULL;
1562     Object->Entry[EntryIndex].CodBufferSize = 0;
1563     Object->Entry[EntryIndex].FuncOffsetBase = 0;
1564     Object->Entry[EntryIndex].SourceBuffer = NULL;
1565   }
1566 
1567   //
1568   // Done
1569   //
1570   return EFI_SUCCESS;
1571 }
1572 
1573 /**
1574 
1575   Add code buffer.
1576 
1577   @param  DebuggerPrivate - EBC Debugger private data structure
1578   @param  MapFileName     - Symbol file name
1579   @param  CodeFileName    - Code file name
1580   @param  SourceBufferSize- Code buffer size
1581   @param  SourceBuffer    - Code buffer
1582 
1583   @retval EFI_SUCCESS - CodeBuffer added successfully
1584 
1585 **/
1586 EFI_STATUS
EdbAddCodeBuffer(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN CHAR16 * MapFileName,IN CHAR16 * CodeFileName,IN UINTN SourceBufferSize,IN VOID * SourceBuffer)1587 EdbAddCodeBuffer (
1588   IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
1589   IN     CHAR16                    *MapFileName,
1590   IN     CHAR16                    *CodeFileName,
1591   IN     UINTN                     SourceBufferSize,
1592   IN     VOID                      *SourceBuffer
1593   )
1594 {
1595   UINTN                      Index;
1596   EFI_DEBUGGER_SYMBOL_OBJECT *Object;
1597 
1598   //
1599   // Find Symbol
1600   //
1601   Object = EdbFindSymbolFile (DebuggerPrivate, MapFileName, NULL);
1602   if (Object == NULL) {
1603     EDBPrint (L"SymbolFile is not loaded!\n");
1604     return EFI_NOT_FOUND;
1605   }
1606 
1607   //
1608   // Add it to last entry
1609   //
1610   for (Index = 0; Object->SourceBuffer[Index] != NULL; Index++) {
1611     ;
1612   }
1613   Object->SourceBuffer[Index] = SourceBuffer;
1614 
1615   return EFI_SUCCESS;
1616 }
1617 
1618 /**
1619 
1620   Delete code buffer.
1621 
1622   @param  DebuggerPrivate - EBC Debugger private data structure
1623   @param  MapFileName     - Symbol file name
1624   @param  CodeFileName    - Code file name
1625   @param  SourceBuffer    - Code buffer
1626 
1627   @retval EFI_SUCCESS - CodeBuffer deleted successfully
1628 
1629 **/
1630 EFI_STATUS
EdbDeleteCodeBuffer(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN CHAR16 * MapFileName,IN CHAR16 * CodeFileName,IN VOID * SourceBuffer)1631 EdbDeleteCodeBuffer (
1632   IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
1633   IN     CHAR16                    *MapFileName,
1634   IN     CHAR16                    *CodeFileName,
1635   IN     VOID                      *SourceBuffer
1636   )
1637 {
1638   UINTN                      Index;
1639   EFI_DEBUGGER_SYMBOL_OBJECT *Object;
1640 
1641   //
1642   // Find Symbol
1643   //
1644   Object = EdbFindSymbolFile (DebuggerPrivate, MapFileName, NULL);
1645   if (Object == NULL) {
1646     EDBPrint (L"SymbolFile is not loaded!\n");
1647     return EFI_NOT_FOUND;
1648   }
1649 
1650   for (Index = 0; Object->SourceBuffer[Index] != NULL; Index++) {
1651     //
1652     // free the buffer if match
1653     //
1654     if (Object->SourceBuffer[Index] == SourceBuffer) {
1655       gBS->FreePool (SourceBuffer);
1656       break;
1657     }
1658   }
1659 
1660   if (Object->SourceBuffer[Index] == NULL) {
1661     //
1662     // not return NOT_FOUND
1663     //
1664     return EFI_SUCCESS;
1665   }
1666 
1667   //
1668   // remove the entry
1669   //
1670   Object->SourceBuffer[Index] = NULL;
1671   for (Index = Index + 1; Object->SourceBuffer[Index] != NULL; Index++) {
1672     Object->SourceBuffer[Index - 1] = Object->SourceBuffer[Index];
1673   }
1674   Object->SourceBuffer[Index - 1] = NULL;
1675 
1676   return EFI_SUCCESS;
1677 }
1678 
1679 /**
1680 
1681   Find the symbol string according to address.
1682 
1683   @param  Address         - Symbol address
1684 
1685   @return Symbol string
1686 
1687 **/
1688 CHAR8 *
FindSymbolStr(IN UINTN Address)1689 FindSymbolStr (
1690   IN UINTN Address
1691   )
1692 {
1693   UINTN                       ObjectIndex;
1694   EFI_DEBUGGER_SYMBOL_OBJECT  *Object;
1695   UINTN                       EntryIndex;
1696   EFI_DEBUGGER_SYMBOL_ENTRY   *Entry;
1697 
1698   //
1699   // need we display symbol
1700   //
1701   if (!mDebuggerPrivate.DebuggerSymbolContext.DisplaySymbol) {
1702     return NULL;
1703   }
1704 
1705   //
1706   // Go through each object and entry
1707   //
1708   Object = mDebuggerPrivate.DebuggerSymbolContext.Object;
1709   for (ObjectIndex = 0; ObjectIndex < mDebuggerPrivate.DebuggerSymbolContext.ObjectCount; ObjectIndex++) {
1710     Entry = Object[ObjectIndex].Entry;
1711     for (EntryIndex = 0; EntryIndex < Object[ObjectIndex].EntryCount; EntryIndex++) {
1712       //
1713       // if Address match, return Name
1714       //
1715       if (Address == (Entry[EntryIndex].Rva + Object[ObjectIndex].BaseAddress)) {
1716         return Entry[EntryIndex].Name;
1717       }
1718     }
1719   }
1720 
1721   //
1722   // not found
1723   //
1724   return NULL;
1725 }
1726 
1727 /**
1728 
1729   Get line number and offset from this line in code file.
1730 
1731   @param  Line            - Line buffer in code file
1732   @param  Offset          - Offset to functin entry
1733 
1734   @return Line number
1735 
1736 **/
1737 UINTN
EdbGetLineNumberAndOffsetFromThisLine(IN VOID * Line,OUT UINTN * Offset)1738 EdbGetLineNumberAndOffsetFromThisLine (
1739   IN VOID     *Line,
1740   OUT UINTN   *Offset
1741   )
1742 {
1743   UINTN  LineNumber;
1744   CHAR8  *LineBuffer;
1745   CHAR8  *FieldBuffer;
1746 
1747   LineNumber = (UINTN)-1;
1748   LineBuffer = Line;
1749   *Offset = (UINTN)-1;
1750 
1751   while (LineBuffer != NULL) {
1752     //
1753     // Check candidate
1754     //
1755     if (*LineBuffer != ' ') {
1756       return (UINTN)-1;
1757     }
1758 
1759     //
1760     // Get Offset
1761     //
1762     if (*(LineBuffer + 2) != ' ') {
1763       if (*Offset == (UINTN)-1) {
1764         FieldBuffer = AsciiStrGetNewTokenField (LineBuffer + 2, " ");
1765         *Offset = AsciiXtoi (FieldBuffer);
1766         PatchForAsciiStrTokenAfter (FieldBuffer, ' ');
1767       }
1768     }
1769 
1770     //
1771     // 1. assembly instruction
1772     //
1773     FieldBuffer = AsciiStrGetNewTokenField (LineBuffer, ":");
1774     //
1775     // 2. file path
1776     //
1777     FieldBuffer = AsciiStrGetNextTokenField (":");
1778     PatchForAsciiStrTokenBefore (FieldBuffer, ':');
1779     if (FieldBuffer == NULL) {
1780       //
1781       // candidate found
1782       //
1783       LineNumber = 0;
1784       LineBuffer = AsciiStrGetNextTokenLine ("\n");
1785       PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1786       continue;
1787     }
1788     //
1789     // 3. line number
1790     //
1791     FieldBuffer = AsciiStrGetNextTokenField (":");
1792     PatchForAsciiStrTokenBefore (FieldBuffer, ':');
1793     if (FieldBuffer == NULL) {
1794       //
1795       // impossible, TBD?
1796       //
1797       LineBuffer = AsciiStrGetNextTokenLine ("\n");
1798       PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1799       continue;
1800     }
1801 
1802     LineNumber = AsciiAtoi (FieldBuffer);
1803     //
1804     // Not patch after
1805     //
1806 
1807     return LineNumber;
1808   }
1809 
1810   return (UINTN)-1;
1811 }
1812 
1813 typedef enum {
1814   EdbEbcLineSearchTypeAny,
1815   EdbEbcLineSearchTypeFirst,
1816   EdbEbcLineSearchTypeLast,
1817   EdbEbcLineSearchTypeMax,
1818 } EDB_EBC_LINE_SEARCH_TYPE;
1819 
1820 /**
1821 
1822   Get line number from this code file.
1823 
1824   @param  Entry           - Symbol entry
1825   @param  FuncOffset      - Offset to functin entry
1826   @param  SearchType      - Search type for the code
1827 
1828   @return Line number
1829 
1830 **/
1831 UINTN
EdbGetLineNumberFromCode(IN EFI_DEBUGGER_SYMBOL_ENTRY * Entry,IN UINTN FuncOffset,IN EDB_EBC_LINE_SEARCH_TYPE SearchType)1832 EdbGetLineNumberFromCode (
1833   IN EFI_DEBUGGER_SYMBOL_ENTRY  *Entry,
1834   IN UINTN                      FuncOffset,
1835   IN EDB_EBC_LINE_SEARCH_TYPE   SearchType
1836   )
1837 {
1838   CHAR8  *LineBuffer;
1839   UINTN  LineNumber;
1840   UINTN  Offset;
1841   UINTN  CandidateLineNumber;
1842   UINTN  CandidateOffset;
1843 
1844   if (SearchType < 0 || SearchType >= EdbEbcLineSearchTypeMax) {
1845     return (UINTN)-1;
1846   }
1847 
1848   LineNumber = (UINTN)-1;
1849   CandidateLineNumber = (UINTN)-1;
1850   CandidateOffset = (UINTN)-1;
1851   LineBuffer = AsciiStrGetNewTokenLine (Entry->CodBuffer, "\n");
1852   while (LineBuffer != NULL) {
1853     if (*LineBuffer != ' ') {
1854       LineBuffer = AsciiStrGetNextTokenLine ("\n");
1855       PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1856       continue;
1857     }
1858 
1859     //
1860     // Get Info
1861     //
1862     LineNumber = EdbGetLineNumberAndOffsetFromThisLine (LineBuffer, &Offset);
1863 
1864     //
1865     // Check offset
1866     //
1867     if (Offset != FuncOffset) {
1868       //
1869       // Check last offset match
1870       //
1871       if (CandidateOffset == FuncOffset) {
1872         if (SearchType == EdbEbcLineSearchTypeLast) {
1873           PatchForAsciiStrTokenAfter (LineBuffer, '\n');
1874           if (CandidateLineNumber != LineNumber) {
1875             return CandidateLineNumber;
1876           } else {
1877             return (UINTN)-1;
1878           }
1879         } else {
1880           //
1881           // impossible, TBD?
1882           //
1883         }
1884       }
1885 
1886       LineBuffer = AsciiStrGetNextTokenLine ("\n");
1887       PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1888       CandidateLineNumber = LineNumber;
1889       continue;
1890     }
1891 
1892     //
1893     // Offset match, more check
1894     //
1895     if (SearchType == EdbEbcLineSearchTypeAny) {
1896       PatchForAsciiStrTokenAfter (LineBuffer, '\n');
1897       return LineNumber;
1898     }
1899 
1900     if (SearchType == EdbEbcLineSearchTypeFirst) {
1901       //
1902       // Check last line
1903       //
1904       PatchForAsciiStrTokenAfter (LineBuffer, '\n');
1905       if (CandidateLineNumber != LineNumber) {
1906         return LineNumber;
1907       } else {
1908         return (UINTN)-1;
1909       }
1910     }
1911 
1912     CandidateLineNumber = LineNumber;
1913     CandidateOffset = Offset;
1914 
1915     LineBuffer = AsciiStrGetNextTokenLine ("\n");
1916     PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1917   }
1918 
1919   //
1920   // Check last offset match
1921   //
1922   if (CandidateOffset == FuncOffset) {
1923     if (SearchType == EdbEbcLineSearchTypeLast) {
1924       return CandidateLineNumber;
1925     }
1926   }
1927 
1928   return (UINTN)-1;
1929 }
1930 
1931 /**
1932 
1933   Get the source string from this code file by line.
1934 
1935   @param  Entry           - Symbol entry
1936   @param  LineNumber      - line number
1937   @param  FuncEnd         - Function end
1938 
1939   @return Funtion start
1940 
1941 **/
1942 VOID *
EdbGetSourceStrFromCodeByLine(IN EFI_DEBUGGER_SYMBOL_ENTRY * Entry,IN UINTN LineNumber,IN VOID ** FuncEnd)1943 EdbGetSourceStrFromCodeByLine (
1944   IN EFI_DEBUGGER_SYMBOL_ENTRY  *Entry,
1945   IN UINTN                      LineNumber,
1946   IN VOID                       **FuncEnd
1947   )
1948 {
1949   CHAR8  *LineBuffer;
1950   CHAR8  *FieldBuffer;
1951   VOID   *FuncStart;
1952   UINTN  Number;
1953 
1954   FuncStart = NULL;
1955   LineBuffer = AsciiStrGetNewTokenLine (Entry->CodBuffer, "\n");
1956   while (LineBuffer != NULL) {
1957     if (*LineBuffer != ';') {
1958       if (FuncStart != NULL) {
1959         //
1960         // Over
1961         //
1962         *FuncEnd = LineBuffer - 1;
1963         PatchForAsciiStrTokenAfter (LineBuffer, '\n');
1964         return FuncStart;
1965       }
1966       LineBuffer = AsciiStrGetNextTokenLine ("\n");
1967       PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1968       continue;
1969     }
1970 
1971     //
1972     // Check LineNumber
1973     //
1974     FieldBuffer = AsciiStrGetNewTokenField (LineBuffer + 1, " ");
1975     Number = AsciiAtoi (FieldBuffer);
1976     PatchForAsciiStrTokenAfter (FieldBuffer, ' ');
1977     if (Number != LineNumber) {
1978       LineBuffer = AsciiStrGetNextTokenLine ("\n");
1979       PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1980       continue;
1981     }
1982 
1983     //
1984     // Line match, get line number
1985     //
1986     if (FuncStart == NULL) {
1987       FuncStart = LineBuffer;
1988     }
1989 
1990     LineBuffer = AsciiStrGetNextTokenLine ("\n");
1991     PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1992   }
1993 
1994   return NULL;
1995 }
1996 
1997 /**
1998 
1999   Get source string from this code file.
2000 
2001   @param  Entry           - Symbol entry
2002   @param  FuncOffset      - Offset to functin entry
2003   @param  FuncEnd         - Function end
2004 
2005   @retval Funtion start
2006 
2007 **/
2008 VOID *
EdbGetSourceStrFromCode(IN EFI_DEBUGGER_SYMBOL_ENTRY * Entry,IN UINTN FuncOffset,IN VOID ** FuncEnd)2009 EdbGetSourceStrFromCode (
2010   IN EFI_DEBUGGER_SYMBOL_ENTRY  *Entry,
2011   IN UINTN                      FuncOffset,
2012   IN VOID                       **FuncEnd
2013   )
2014 {
2015   UINTN  LineNumber;
2016 
2017   //
2018   // Only search the last line, then display
2019   //
2020   LineNumber = EdbGetLineNumberFromCode (Entry, FuncOffset, EdbEbcLineSearchTypeLast);
2021   if (LineNumber == (UINTN)-1) {
2022     return NULL;
2023   }
2024 
2025   return EdbGetSourceStrFromCodeByLine (Entry, LineNumber, FuncEnd);
2026 }
2027 
2028 /**
2029 
2030   Print source.
2031 
2032   @param  Address         - Instruction address
2033   @param  IsPrint         - Whether need to print
2034 
2035   @retval 1 - find the source
2036   @retval 0 - not find the source
2037 
2038 **/
2039 UINTN
EdbPrintSource(IN UINTN Address,IN BOOLEAN IsPrint)2040 EdbPrintSource (
2041   IN UINTN     Address,
2042   IN BOOLEAN   IsPrint
2043   )
2044 {
2045   UINTN                      SymbolAddress;
2046   EFI_DEBUGGER_SYMBOL_OBJECT *RetObject;
2047   EFI_DEBUGGER_SYMBOL_ENTRY  *RetEntry;
2048   UINTN                      FuncOffset;
2049   UINT8                      *FuncStart;
2050   UINT8                      *FuncEnd;
2051   UINT8                      *FuncIndex;
2052   CHAR8                      Buffer[EFI_DEBUG_MAX_PRINT_BUFFER];
2053   UINTN                      BufferSize;
2054 
2055   //
2056   // need we display symbol
2057   //
2058   if (!mDebuggerPrivate.DebuggerSymbolContext.DisplaySymbol) {
2059     return 0 ;
2060   }
2061 
2062   //
2063   // find the symbol address
2064   //
2065   SymbolAddress = EbdFindSymbolAddress (
2066                     Address,
2067                     EdbMatchSymbolTypeLowerAddress,
2068                     &RetObject,
2069                     &RetEntry
2070                     );
2071   if (SymbolAddress == 0) {
2072     return 0 ;
2073   }
2074 
2075   FuncOffset = Address - SymbolAddress + RetEntry->FuncOffsetBase;
2076 
2077   //
2078   // Get Func String
2079   //
2080   FuncStart = EdbGetSourceStrFromCode (RetEntry, FuncOffset, (VOID**) &FuncEnd);
2081   if (FuncStart == NULL) {
2082     return 0 ;
2083   }
2084 
2085   //
2086   // check whether need to real print
2087   //
2088   if (!IsPrint) {
2089     return 1;
2090   }
2091 
2092   *(UINT8 *)FuncEnd = 0;
2093 
2094   //
2095   // seperate buffer by \n, so that \r can be added.
2096   //
2097   FuncIndex = FuncStart;
2098   while (*FuncIndex != 0) {
2099     if (*FuncIndex == '\n') {
2100       if ((FuncIndex - FuncStart) < (EFI_DEBUG_MAX_PRINT_BUFFER - 3)) {
2101         BufferSize = FuncIndex - FuncStart;
2102       } else {
2103         BufferSize = EFI_DEBUG_MAX_PRINT_BUFFER - 3;
2104       }
2105       if (BufferSize != 0) {
2106         CopyMem (Buffer, FuncStart, BufferSize);
2107       }
2108       Buffer[BufferSize] = 0;
2109       EDBPrint (L"%a\n", Buffer);
2110       FuncStart = FuncIndex + 1;
2111       FuncIndex = FuncStart;
2112     } else {
2113       FuncIndex ++;
2114     }
2115   }
2116 
2117   //
2118   // Patch the end
2119   //
2120   *(UINT8 *)FuncEnd = '\n';
2121 
2122   return 1 ;
2123 }
2124 
2125 /**
2126 
2127   Get Mapfile and SymbolName from one symbol format: [MapFileName:]SymbolName.
2128 
2129   @param  Symbol          - whole Symbol name
2130   @param  MapfileName     - the mapfile name in the symbol
2131   @param  SymbolName      - the symbol name in the symbol
2132 
2133 **/
2134 VOID
GetMapfileAndSymbol(IN CHAR16 * Symbol,OUT CHAR16 ** MapfileName,OUT CHAR16 ** SymbolName)2135 GetMapfileAndSymbol (
2136   IN CHAR16   *Symbol,
2137   OUT CHAR16  **MapfileName,
2138   OUT CHAR16  **SymbolName
2139   )
2140 {
2141   CHAR16  *Ch;
2142 
2143   *MapfileName = NULL;
2144   *SymbolName = Symbol;
2145 
2146   for (Ch = Symbol; *Ch != 0; Ch++) {
2147     //
2148     // Find split char
2149     //
2150     if (*Ch == L':') {
2151       *MapfileName = Symbol;
2152       *Ch = 0;
2153       *SymbolName = Ch + 1;
2154       break;
2155     }
2156   }
2157 
2158   return ;
2159 }
2160 
2161 /**
2162 
2163   Convert a symbol to an address.
2164 
2165   @param  Symbol          - Symbol name
2166   @param  Address         - Symbol address
2167 
2168   @retval EFI_SUCCESS    - symbol found and address returned.
2169   @retval EFI_NOT_FOUND  - symbol not found
2170   @retval EFI_NO_MAPPING - duplicated symbol not found
2171 
2172 **/
2173 EFI_STATUS
Symboltoi(IN CHAR16 * Symbol,OUT UINTN * Address)2174 Symboltoi (
2175   IN CHAR16   *Symbol,
2176   OUT UINTN   *Address
2177   )
2178 {
2179   UINTN                       ObjectIndex;
2180   EFI_DEBUGGER_SYMBOL_OBJECT  *Object;
2181   UINTN                       EntryIndex;
2182   EFI_DEBUGGER_SYMBOL_ENTRY   *Entry;
2183   CHAR16                      *SymbolName;
2184   CHAR16                      *MapfileName;
2185 
2186   //
2187   // Split one symbol to mapfile name and symbol name
2188   //
2189   GetMapfileAndSymbol (Symbol, &MapfileName, &SymbolName);
2190 
2191   *Address = 0;
2192   //
2193   // Go through each object
2194   //
2195   Object = mDebuggerPrivate.DebuggerSymbolContext.Object;
2196   for (ObjectIndex = 0; ObjectIndex < mDebuggerPrivate.DebuggerSymbolContext.ObjectCount; ObjectIndex++) {
2197     //
2198     // Check MapfileName
2199     //
2200     if ((MapfileName != NULL) && (StriCmp (Object[ObjectIndex].Name, MapfileName) != 0)) {
2201       continue;
2202     }
2203     //
2204     // Go through each entry
2205     //
2206     Entry = Object[ObjectIndex].Entry;
2207     for (EntryIndex = 0; EntryIndex < Object[ObjectIndex].EntryCount; EntryIndex++) {
2208       //
2209       // Check SymbolName (case sensitive)
2210       //
2211       if (StrCmpUnicodeAndAscii (SymbolName, Entry[EntryIndex].Name) == 0) {
2212         if ((*Address != 0) && (MapfileName == NULL)) {
2213           //
2214           // Find the duplicated symbol
2215           //
2216           EDBPrint (L"Duplicated Symbol found!\n");
2217           return EFI_NO_MAPPING;
2218         } else {
2219           //
2220           // record Address
2221           //
2222           *Address = (Entry[EntryIndex].Rva + Object[ObjectIndex].BaseAddress);
2223         }
2224       }
2225     }
2226   }
2227 
2228   if (*Address == 0) {
2229     //
2230     // Not found
2231     //
2232     return EFI_NOT_FOUND;
2233   }
2234 
2235   return EFI_SUCCESS;
2236 }
2237