3 Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
4 SPDX-License-Identifier: BSD-2-Clause-Patent
13 Load single symbol entry.
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
21 @retval EFI_SUCCESS - add single symbol entry successfully
25 EdbLoadSymbolSingleEntry (
26 IN EFI_DEBUGGER_SYMBOL_OBJECT
*Object
,
30 IN EFI_DEBUGGER_SYMBOL_TYPE Type
33 EFI_DEBUGGER_SYMBOL_ENTRY
*Entry
;
36 // Check Count VS MaxCount
38 if (Object
->EntryCount
>= Object
->MaxEntryCount
) {
40 // reallocate (for codebuffer too)
43 return EFI_OUT_OF_RESOURCES
;
46 Entry
= &Object
->Entry
[Object
->EntryCount
];
51 if (sizeof (UINTN
) == sizeof(UINT64
)) {
52 DEBUG ((DEBUG_ERROR
, " Symbol: %a, Address: 0x%016lx (%d)\n", Name
, (UINT64
)Address
, (UINTN
)Type
));
54 DEBUG ((DEBUG_ERROR
, " Symbol: %a, Address: 0x%08x (%d)\n", Name
, Address
, (UINTN
)Type
));
58 // Fill the entry - name, RVA, type
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);
64 Entry
->Rva
= Address
% EFI_DEBUGGER_DEFAULT_LINK_IMAGEBASE
;
79 EdbEbcMapParseStateUninitialized
,
80 EdbEbcMapParseStateSymbolStart
,
81 EdbEbcMapParseStateSeHandlerSymbol
,
82 EdbEbcMapParseStateFunctionSymbol
,
83 EdbEbcMapParseStateVarbssInitSymbol
,
84 EdbEbcMapParseStateCrtSymbol
,
85 EdbEbcMapParseStateVariableSymbol
,
86 EdbEbcMapParseStateStaticFunctionSymbol
,
87 EdbEbcMapParseStateMax
,
88 } EDB_EBC_MAP_PARSE_STATE
;
91 EdbEbcSymbolParseStateUninitialized
,
92 EdbEbcSymbolParseStateReadyForName
,
93 EdbEbcSymbolParseStateReadyForRVA
,
94 EdbEbcSymbolParseStateReadyForType
,
95 EdbEbcSymbolParseStateReadyForObject
,
96 EdbEbcSymbolParseStateMax
,
97 } EDB_EBC_SYMBOL_PARSE_STATE
;
101 The following code depends on the MAP file generated by IEC compiler (actually Microsoft linker).
103 Sample as follows: EbcTest.map
104 ===============================================================================
107 Timestamp is 45b02718 (Fri Jan 19 10:04:08 2007)
109 Preferred load address is 10000000
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
125 Address Publics by Value Rva+Base Lib:Object
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
143 entry point at 0001:00000220
147 0001:00000000 TestSubRoutine2 10000400 f EbcTest.obj
148 ===============================================================================
154 Load symbol entry by Iec.
156 @param Object - Symbol file object
157 @param BufferSize - Symbol file buffer size
158 @param Buffer - Symbol file buffer
160 @retval EFI_SUCCESS - add symbol entry successfully
164 EdbLoadSymbolEntryByIec (
165 IN EFI_DEBUGGER_SYMBOL_OBJECT
*Object
,
172 EDB_EBC_MAP_PARSE_STATE MapParseState
;
173 EDB_EBC_SYMBOL_PARSE_STATE SymbolParseState
;
177 EFI_DEBUGGER_SYMBOL_TYPE Type
;
181 // Begin to parse the Buffer
183 LineBuffer
= AsciiStrGetNewTokenLine (Buffer
, "\n\r");
184 MapParseState
= EdbEbcMapParseStateUninitialized
;
188 while (LineBuffer
!= NULL
) {
189 FieldBuffer
= AsciiStrGetNewTokenField (LineBuffer
, " ");
190 SymbolParseState
= EdbEbcSymbolParseStateUninitialized
;
197 Type
= EfiDebuggerSymbolTypeMax
;
201 while (FieldBuffer
!= NULL
) {
202 if (AsciiStrCmp (FieldBuffer
, "") == 0) {
203 FieldBuffer
= AsciiStrGetNextTokenField (" ");
209 if (AsciiStrCmp (FieldBuffer
, "Address") == 0) {
210 MapParseState
= EdbEbcMapParseStateSymbolStart
;
216 if (AsciiStrCmp (FieldBuffer
, "Static") == 0) {
217 MapParseState
= EdbEbcMapParseStateStaticFunctionSymbol
;
221 if (MapParseState
== EdbEbcMapParseStateUninitialized
) {
223 // Do not parse anything until get "Address" or "Static"
227 if (AsciiStrCmp (FieldBuffer
, "entry") == 0) {
235 // Now we start to parse this line for Name, Address, and Object
237 switch (SymbolParseState
) {
238 case EdbEbcSymbolParseStateUninitialized
:
242 SymbolParseState
= EdbEbcSymbolParseStateReadyForName
;
244 case EdbEbcSymbolParseStateReadyForName
:
248 if (AsciiStrnCmp (FieldBuffer
, "___safe_se_handler", AsciiStrLen ("___safe_se_handler")) == 0) {
252 MapParseState
= EdbEbcMapParseStateSeHandlerSymbol
;
254 } else if (AsciiStrnCmp (FieldBuffer
, "varbss_init", AsciiStrLen ("varbss_init")) == 0) {
258 MapParseState
= EdbEbcMapParseStateVarbssInitSymbol
;
259 // goto ExitFieldParse;
261 SymbolParseState
= EdbEbcSymbolParseStateReadyForRVA
;
262 } else if (AsciiStrnCmp (FieldBuffer
, "Crt", AsciiStrLen ("Crt")) == 0) {
266 MapParseState
= EdbEbcMapParseStateCrtSymbol
;
267 // goto ExitFieldParse;
269 SymbolParseState
= EdbEbcSymbolParseStateReadyForRVA
;
272 // Now, it is normal function
274 switch (MapParseState
) {
275 case EdbEbcMapParseStateSeHandlerSymbol
:
276 MapParseState
= EdbEbcMapParseStateFunctionSymbol
;
278 case EdbEbcMapParseStateCrtSymbol
:
279 MapParseState
= EdbEbcMapParseStateVariableSymbol
;
281 case EdbEbcMapParseStateFunctionSymbol
:
282 case EdbEbcMapParseStateVariableSymbol
:
283 case EdbEbcMapParseStateStaticFunctionSymbol
:
290 SymbolParseState
= EdbEbcSymbolParseStateReadyForRVA
;
293 case EdbEbcSymbolParseStateReadyForRVA
:
297 Address
= AsciiXtoi (FieldBuffer
);
298 SymbolParseState
= EdbEbcSymbolParseStateReadyForType
;
300 case EdbEbcSymbolParseStateReadyForType
:
302 // Get the Type. This is optional, only for "f".
304 if (AsciiStrCmp (FieldBuffer
, "f") == 0) {
305 SymbolParseState
= EdbEbcSymbolParseStateReadyForObject
;
306 switch (MapParseState
) {
307 case EdbEbcMapParseStateFunctionSymbol
:
308 case EdbEbcMapParseStateVarbssInitSymbol
:
309 Type
= EfiDebuggerSymbolFunction
;
311 case EdbEbcMapParseStateStaticFunctionSymbol
:
312 Type
= EfiDebuggerSymbolStaticFunction
;
321 // Else it should be Object.
322 // let it bypass here
324 case EdbEbcSymbolParseStateReadyForObject
:
326 case EfiDebuggerSymbolTypeMax
:
327 switch (MapParseState
) {
328 case EdbEbcMapParseStateVariableSymbol
:
329 case EdbEbcMapParseStateCrtSymbol
:
330 Type
= EfiDebuggerSymbolGlobalVariable
;
332 case EdbEbcMapParseStateSeHandlerSymbol
:
342 case EfiDebuggerSymbolFunction
:
343 case EfiDebuggerSymbolStaticFunction
:
352 ObjName
= FieldBuffer
;
353 SymbolParseState
= EdbEbcSymbolParseStateUninitialized
;
361 // Get the next field
363 FieldBuffer
= AsciiStrGetNextTokenField (" ");
367 // Add the entry if we get everything.
369 if ((Name
!= NULL
) && (Type
!= EfiDebuggerSymbolTypeMax
)) {
370 EdbLoadSymbolSingleEntry (Object
, Name
, ObjName
, Address
, Type
);
377 LineBuffer
= AsciiStrGetNextTokenLine ("\n\r");
390 @param Object - Symbol file object
391 @param BufferSize - Symbol file buffer size
392 @param Buffer - Symbol file buffer
394 @retval EFI_SUCCESS - add symbol entry successfully
399 IN EFI_DEBUGGER_SYMBOL_OBJECT
*Object
,
405 // MAP file format depends on the compiler (actually linker).
407 // It is possible to check the different MAP file format in this routine.
408 // Now only IEC is supported.
410 return EdbLoadSymbolEntryByIec (Object
, BufferSize
, Buffer
);
415 Find symbol file by name.
417 @param DebuggerPrivate - EBC Debugger private data structure
418 @param FileName - Symbol file name
419 @param Index - Symbol file index
424 EFI_DEBUGGER_SYMBOL_OBJECT
*
426 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
428 IN OUT UINTN
*Index OPTIONAL
436 for (ObjectIndex
= 0; ObjectIndex
< DebuggerPrivate
->DebuggerSymbolContext
.ObjectCount
; ObjectIndex
++) {
437 if (StrCmp (FileName
, DebuggerPrivate
->DebuggerSymbolContext
.Object
[ObjectIndex
].Name
) == 0) {
439 // Name match, found it
442 *Index
= ObjectIndex
;
444 return &DebuggerPrivate
->DebuggerSymbolContext
.Object
[ObjectIndex
];
456 Find symbol by address.
458 @param Address - Symbol address
459 @param Type - Search type
460 @param RetObject - Symbol object
461 @param RetEntry - Symbol entry
463 @return Nearest symbol address
467 EbdFindSymbolAddress (
469 IN EDB_MATCH_SYMBOL_TYPE Type
,
470 OUT EFI_DEBUGGER_SYMBOL_OBJECT
**RetObject
,
471 OUT EFI_DEBUGGER_SYMBOL_ENTRY
**RetEntry
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
;
485 if ((Type
< 0) || (Type
>= EdbMatchSymbolTypeMax
)) {
492 CandidateLowerAddress
= 0;
493 CandidateUpperAddress
= (UINTN
)-1;
500 // Go through each object
502 Object
= mDebuggerPrivate
.DebuggerSymbolContext
.Object
;
503 for (Index
= 0; Index
< mDebuggerPrivate
.DebuggerSymbolContext
.ObjectCount
; Index
++, Object
++) {
504 if (Object
->EntryCount
== 0) {
508 // Go through each entry
510 Entry
= Object
->Entry
;
511 for (SubIndex
= 0; SubIndex
< Object
->EntryCount
; SubIndex
++, Entry
++) {
512 if (Address
!= Entry
->Rva
+ Object
->BaseAddress
) {
514 // Check for nearest address
516 if (Address
> Entry
->Rva
+ Object
->BaseAddress
) {
518 // Record it if Current RVA < Address
520 if (CandidateLowerAddress
< Entry
->Rva
+ Object
->BaseAddress
) {
521 CandidateLowerAddress
= Entry
->Rva
+ Object
->BaseAddress
;
527 // Record it if Current RVA > Address
529 if (CandidateUpperAddress
> Entry
->Rva
+ Object
->BaseAddress
) {
530 CandidateUpperAddress
= Entry
->Rva
+ Object
->BaseAddress
;
532 UpperObject
= Object
;
538 // address match, return directly
547 // No Match, provide latest symbol
550 if ((Address
- CandidateLowerAddress
) < EFI_DEBUGGER_MAX_SYMBOL_ADDRESS_DELTA_VALUE
) {
552 // Check for lower address
554 if (((Type
== EdbMatchSymbolTypeNearestAddress
) &&
555 ((CandidateUpperAddress
- Address
) > (Address
- CandidateLowerAddress
))) ||
556 (Type
== EdbMatchSymbolTypeLowerAddress
)) {
558 // return nearest lower address
560 *RetEntry
= LowEntry
;
561 *RetObject
= LowObject
;
562 return CandidateLowerAddress
;
566 if ((CandidateUpperAddress
- Address
) < EFI_DEBUGGER_MAX_SYMBOL_ADDRESS_DELTA_VALUE
) {
568 // Check for upper address
570 if (((Type
== EdbMatchSymbolTypeNearestAddress
) &&
571 ((CandidateUpperAddress
- Address
) < (Address
- CandidateLowerAddress
))) ||
572 (Type
== EdbMatchSymbolTypeUpperAddress
)) {
574 // return nearest upper address
576 *RetEntry
= UpperEntry
;
577 *RetObject
= UpperObject
;
578 return CandidateUpperAddress
;
583 // No match and nearest one, return NULL
590 Unload symbol file by name.
592 @param DebuggerPrivate - EBC Debugger private data structure
593 @param FileName - Symbol file name
595 @retval EFI_SUCCESS - unload symbol successfully
600 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
604 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
607 EFI_DEBUGGER_SYMBOL_ENTRY
*OldEntry
;
610 VOID
**OldSourceBuffer
;
615 Object
= EdbFindSymbolFile (DebuggerPrivate
, FileName
, &ObjectIndex
);
616 if (Object
== NULL
) {
617 EDBPrint (L
"SymbolFile is not loaded!\n");
618 return EFI_DEBUG_CONTINUE
;
624 Object
= DebuggerPrivate
->DebuggerSymbolContext
.Object
;
625 OldEntry
= Object
->Entry
;
626 OldSourceBuffer
= Object
->SourceBuffer
;
627 MaxEntryCount
= Object
->MaxEntryCount
;
628 OldEntryCount
= Object
->EntryCount
;
631 // Remove the matched Object
633 for (Index
= ObjectIndex
; Index
< DebuggerPrivate
->DebuggerSymbolContext
.ObjectCount
- 1; Index
++) {
634 CopyMem (&Object
[Index
], &Object
[Index
+ 1], sizeof(EFI_DEBUGGER_SYMBOL_OBJECT
));
636 ZeroMem (&Object
[Index
], sizeof(Object
[Index
]));
639 // Move old data to new place
641 Object
[Index
].Entry
= OldEntry
;
642 Object
[Index
].SourceBuffer
= OldSourceBuffer
;
643 Object
[Index
].MaxEntryCount
= MaxEntryCount
;
644 DebuggerPrivate
->DebuggerSymbolContext
.ObjectCount
--;
647 // Clean old entry data
649 for (Index
= 0; Index
< OldEntryCount
; Index
++) {
650 ZeroMem (&OldEntry
[Index
], sizeof(OldEntry
[Index
]));
654 // Free OldSourceBuffer
656 for (Index
= 0; OldSourceBuffer
[Index
] != NULL
; Index
++) {
657 gBS
->FreePool (OldSourceBuffer
[Index
]);
658 OldSourceBuffer
[Index
] = NULL
;
666 Load symbol file by name.
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
673 @retval EFI_SUCCESS - load symbol successfully
678 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
684 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
688 // Check duplicated File
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"));
700 // Check Count VS MaxCount
702 if (DebuggerPrivate
->DebuggerSymbolContext
.ObjectCount
>= DebuggerPrivate
->DebuggerSymbolContext
.MaxObjectCount
) {
707 return EFI_OUT_OF_RESOURCES
;
710 Object
= &DebuggerPrivate
->DebuggerSymbolContext
.Object
[DebuggerPrivate
->DebuggerSymbolContext
.ObjectCount
];
715 Object
->EntryCount
= 0;
716 Object
->MaxEntryCount
= EFI_DEBUGGER_SYMBOL_ENTRY_MAX
;
721 DEBUG ((DEBUG_ERROR
, "Symbol File: %s\n", FileName
));
722 Status
= EdbLoadSymbolEntry (Object
, BufferSize
, Buffer
);
723 if (EFI_ERROR (Status
)) {
730 StrnCpyS (Object
->Name
, sizeof(Object
->Name
) / sizeof(CHAR16
),
731 FileName
, (sizeof(Object
->Name
) / sizeof(CHAR16
)) - 1);
732 Object
->BaseAddress
= 0;
735 // Increase the object count
737 DebuggerPrivate
->DebuggerSymbolContext
.ObjectCount
++;
744 Located PDB path name in PE image.
746 @param ImageBase - base of PE to search
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.
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
;
770 CodeViewEntryPointer
= NULL
;
777 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
780 NtHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*) ((UINT8
*) DosHdr
+ DosHdr
->e_lfanew
);
782 // Check Machine, filter for EBC
784 if (NtHdr
->Pe32
.FileHeader
.Machine
!= EFI_IMAGE_MACHINE_EBC
) {
786 // If not EBC, return NULL
792 // Get DirectoryEntry
793 // EBC spec says PE32+, but implementation uses PE32. So check dynamically here.
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
]);
804 if (DirectoryEntry
->VirtualAddress
== 0) {
808 // Go through DirectoryEntry
811 (DirCount
< DirectoryEntry
->Size
/ sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
)) && CodeViewEntryPointer
== NULL
;
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
) {
817 // Match DebugEntry, only CODEVIEW_SIGNATURE_NB10 and CODEVIEW_SIGNATURE_RSDS are supported.
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
);
824 case CODEVIEW_SIGNATURE_RSDS
:
825 PdbPath
= (CHAR8
*) CodeViewEntryPointer
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY
);
841 Check whether PDB file and MAP file have same name.
843 @param PdbFileName - PDB file name
844 @param MapFileName - MAP file name
846 @retval TRUE - PDB and MAP file name match
847 @retval FALSE - PDB and MAP file name not match
852 IN CHAR8
*PdbFileName
,
853 IN CHAR16
*MapFileName
858 CHAR8
*PurePdbFileName
;
864 PurePdbFileName
= PdbFileName
;
865 for (Index
= 0; PdbFileName
[Index
] != 0; Index
++) {
866 if (PdbFileName
[Index
] == '\\') {
867 PurePdbFileName
= &PdbFileName
[Index
+ 1];
870 PdbFileName
= PurePdbFileName
;
875 PdbNameSize
= AsciiStrLen (PdbFileName
);
876 MapNameSize
= StrLen (MapFileName
);
878 if (PdbNameSize
!= MapNameSize
) {
885 for (Index
= 0; Index
< MapNameSize
- 4; Index
++) {
886 if ((PdbFileName
[Index
] | 0x20) != (MapFileName
[Index
] | 0x20)) {
895 // BUGBUG: work-around start
898 EFI_DEBUG_IMAGE_INFO
*EfiDebugImageInfoTable
;
899 volatile UINT32 UpdateStatus
;
901 } EFI_DEBUG_IMAGE_INFO_TABLE_HEADER_OLD
;
903 EFI_DEBUG_IMAGE_INFO_TABLE_HEADER mDebugImageInfoTableHeader
;
906 For compatibility consideration, we handle 2 cases:
910 +------------------------+ +------------------------+
911 | EfiDebugImageInfoTable | | UpdateStatus |
912 +------------------------+ +------------------------+
913 | UpdateStatus | | TableSize |
914 +------------------------+ +------------------------+
915 | TableSize | | EfiDebugImageInfoTable |
916 +------------------------+ +------------------------+
920 +------------------------+ +------------------------+
921 | EfiDebugImageInfoTable | | UpdateStatus |
922 | | +------------------------+
924 +------------------------+ +------------------------+
925 | UpdateStatus | | EfiDebugImageInfoTable |
926 +------------------------+ | |
928 +------------------------+ +------------------------+
930 @param DebugImageInfoTableHeader Point to the EFI_DEBUG_IMAGE_INFO_TABLE_HEADER structure.
934 EdbFixDebugImageInfoTable (
935 IN OUT EFI_DEBUG_IMAGE_INFO_TABLE_HEADER
**DebugImageInfoTableHeader
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
;
942 if ((*DebugImageInfoTableHeader
)->UpdateStatus
> 3) {
943 *DebugImageInfoTableHeader
= &mDebugImageInfoTableHeader
;
947 if ((*DebugImageInfoTableHeader
)->TableSize
% (EFI_PAGE_SIZE
/ (sizeof (VOID
*))) != 0) {
948 *DebugImageInfoTableHeader
= &mDebugImageInfoTableHeader
;
955 // BUGBUG: work-around end
962 @param DebuggerPrivate - EBC Debugger private data structure
963 @param FileName - Symbol file name
964 @param SearchType - Search type for Object
966 @retval EFI_SUCCESS - Patch symbol RVA successfully
967 @retval EFI_NOT_FOUND - Symbol RVA base not found
972 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
974 IN EDB_EBC_IMAGE_RVA_SEARCH_TYPE SearchType
979 EFI_DEBUG_IMAGE_INFO
*ImageTable
;
982 VOID
*CandidateImageBase
;
983 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
985 if (SearchType
< 0 || SearchType
>= EdbEbcImageRvaSearchTypeMax
) {
986 return EFI_INVALID_PARAMETER
;
990 // Get the related object
992 Object
= EdbFindSymbolFile (DebuggerPrivate
, FileName
, NULL
);
993 if (Object
== NULL
) {
994 return EFI_NOT_FOUND
;
998 // Try again to get DebugImageInfoTable
1000 if (mDebuggerPrivate
.DebugImageInfoTableHeader
== NULL
) {
1001 Status
= EfiGetSystemConfigurationTable (
1002 &gEfiDebugImageInfoTableGuid
,
1003 (VOID
**) &mDebuggerPrivate
.DebugImageInfoTableHeader
1005 if (EFI_ERROR (Status
)) {
1006 EDBPrint (L
"DebugImageInfoTable not found!\n");
1010 DEBUG ((DEBUG_ERROR
, "DebugImageInfoTableHeader: %x\n", mDebuggerPrivate
.DebugImageInfoTableHeader
));
1013 // BUGBUG: work-around start
1015 EdbFixDebugImageInfoTable (&mDebuggerPrivate
.DebugImageInfoTableHeader
);
1017 // BUGBUG: work-around end
1021 // Go through DebugImageInfoTable for each Image
1023 CandidateImageBase
= NULL
;
1024 ImageTable
= mDebuggerPrivate
.DebugImageInfoTableHeader
->EfiDebugImageInfoTable
;
1025 for (ImageNumber
= 0; ImageNumber
< mDebuggerPrivate
.DebugImageInfoTableHeader
->TableSize
; ImageNumber
++) {
1026 if (ImageTable
[ImageNumber
].NormalImage
== NULL
) {
1029 ImageBase
= ImageTable
[ImageNumber
].NormalImage
->LoadedImageProtocolInstance
->ImageBase
;
1033 PdbPath
= GetPdbPath (ImageBase
);
1034 if (PdbPath
== NULL
) {
1040 if (!MatchPdbAndMap (PdbPath
, FileName
)) {
1043 DEBUG ((DEBUG_ERROR
, "ImageBase: %x\n", ImageBase
));
1048 if (SearchType
== EdbEbcImageRvaSearchTypeAny
|| SearchType
== EdbEbcImageRvaSearchTypeFirst
) {
1050 // Assign base address and return
1052 Object
->BaseAddress
= (UINTN
)ImageBase
;
1057 // Get CandidateImageBase for EdbEbcImageRvaSearchTypeLast
1059 CandidateImageBase
= ImageBase
;
1063 // Check EdbEbcImageRvaSearchTypeLast
1065 if (SearchType
== EdbEbcImageRvaSearchTypeLast
) {
1066 if (CandidateImageBase
== NULL
) {
1067 return EFI_NOT_FOUND
;
1070 // Assign base address and return
1072 Object
->BaseAddress
= (UINTN
)CandidateImageBase
;
1079 return EFI_NOT_FOUND
;
1084 Check whether OBJ file and COD file have same name.
1086 @param ObjFileName - OBJ file name
1087 @param CodFileName - COD file name
1089 @retval TRUE - OBJ and COD file name match
1090 @retval FALSE - OBJ and COD file name not match
1095 IN CHAR8
*ObjFileName
,
1096 IN CHAR16
*CodFileName
1101 CHAR8
*PureObjFileName
;
1105 // remove library name
1107 PureObjFileName
= ObjFileName
;
1108 for (Index
= 0; ObjFileName
[Index
] != 0; Index
++) {
1109 if (ObjFileName
[Index
] == ':') {
1110 PureObjFileName
= &ObjFileName
[Index
+ 1];
1114 ObjFileName
= PureObjFileName
;
1119 ObjNameSize
= AsciiStrLen (ObjFileName
);
1120 CodNameSize
= StrLen (CodFileName
);
1122 if (ObjNameSize
!= CodNameSize
) {
1129 for (Index
= 0; Index
< CodNameSize
- 4; Index
++) {
1130 if ((ObjFileName
[Index
] | 0x20) != (CodFileName
[Index
] | 0x20)) {
1139 EdbEbcCodParseStateUninitialized
,
1140 EdbEbcCodParseStateSymbolInitialized
,
1141 EdbEbcCodParseStateSymbolStart
,
1142 EdbEbcCodParseStateSymbolEnd
,
1143 EdbEbcCodParseStateMax
,
1144 } EDB_EBC_COD_PARSE_STATE
;
1148 The following code depends on the COD file generated by IEC compiler.
1154 Load code by symbol by Iec.
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
1166 EdbLoadCodBySymbolByIec (
1169 IN UINTN BufferSize
,
1170 OUT UINTN
*CodeBufferSize
,
1171 OUT UINTN
*FuncOffset
1179 EDB_EBC_COD_PARSE_STATE CodParseState
;
1187 LineBuffer
= AsciiStrGetNewTokenLine (Buffer
, "\n\r");
1191 CodParseState
= EdbEbcCodParseStateUninitialized
;
1196 while (LineBuffer
!= NULL
) {
1197 switch (CodParseState
) {
1198 case EdbEbcCodParseStateUninitialized
:
1200 // check mark_begin, begin to check line after this match
1202 if (AsciiStrCmp (LineBuffer
, "; mark_begin;") == 0) {
1203 CodParseState
= EdbEbcCodParseStateSymbolInitialized
;
1205 LineBuffer
= AsciiStrGetNextTokenLine ("\n\r");
1206 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1209 case EdbEbcCodParseStateSymbolInitialized
:
1211 // check mark_end, not check line after this match
1213 if (AsciiStrCmp (LineBuffer
, "; mark_end;") == 0) {
1214 CodParseState
= EdbEbcCodParseStateUninitialized
;
1215 LineBuffer
= AsciiStrGetNextTokenLine ("\n\r");
1216 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1221 // not check this line if the first char is as follows
1223 if ((*LineBuffer
== 0) ||
1224 (*LineBuffer
== '$') ||
1225 (*LineBuffer
== ';') ||
1226 (*LineBuffer
== '_') ||
1227 (*LineBuffer
== ' ')) {
1228 LineBuffer
= AsciiStrGetNextTokenLine ("\n\r");
1229 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1234 // get function name, function name is followed by char 0x09.
1236 FieldBuffer
= AsciiStrGetNewTokenField (LineBuffer
, Char
);
1237 ASSERT (FieldBuffer
!= NULL
);
1238 if (AsciiStriCmp (FieldBuffer
, Name
) == 0) {
1239 BufferStart
= FieldBuffer
;
1240 CodParseState
= EdbEbcCodParseStateSymbolStart
;
1242 PatchForAsciiStrTokenAfter (FieldBuffer
, 0x9);
1247 LineBuffer
= AsciiStrGetNextTokenLine ("\n\r");
1248 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1251 case EdbEbcCodParseStateSymbolStart
:
1253 // check mark_end, if this match, means the function is found successfully.
1255 if (AsciiStrCmp (LineBuffer
, "; mark_end;") == 0) {
1256 CodParseState
= EdbEbcCodParseStateSymbolEnd
;
1258 // prepare CodeBufferSize, FuncOffset, and FuncStart to return
1260 BufferEnd
= LineBuffer
+ sizeof("; mark_end;") - 1;
1261 *CodeBufferSize
= (UINTN
)BufferEnd
- (UINTN
)BufferStart
;
1262 *FuncOffset
= Offset
;
1263 PatchForAsciiStrTokenAfter (LineBuffer
, '\n');
1268 // Get function offset
1270 if ((Offset
== (UINTN
)-1) &&
1271 (*LineBuffer
== ' ')) {
1272 FieldBuffer
= AsciiStrGetNewTokenField (LineBuffer
+ 2, " ");
1273 Offset
= AsciiXtoi (FieldBuffer
);
1274 PatchForAsciiStrTokenAfter (FieldBuffer
, ' ');
1280 LineBuffer
= AsciiStrGetNextTokenLine ("\n\r");
1281 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1284 case EdbEbcCodParseStateSymbolEnd
:
1293 // no function found
1300 Load code by symbol.
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
1312 EdbLoadCodBySymbol (
1315 IN UINTN BufferSize
,
1316 OUT UINTN
*CodeBufferSize
,
1317 OUT UINTN
*FuncOffset
1321 // COD file format depends on the compiler.
1323 // It is possible to check the different COD file format in this routine.
1324 // Now only IEC is supported.
1326 return EdbLoadCodBySymbolByIec (Name
, Buffer
, BufferSize
, CodeBufferSize
, FuncOffset
);
1331 Find code from object.
1333 @param DebuggerPrivate EBC Debugger private data structure
1334 @param Object - Symbol object
1335 @param FileName - File name
1339 EdbFindCodeFromObject (
1340 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
1341 IN EFI_DEBUGGER_SYMBOL_OBJECT
*Object
,
1348 // Go througn each Entry in this Object
1350 for (EntryIndex
= 0; EntryIndex
< Object
->EntryCount
; EntryIndex
++) {
1352 // This check is for Function only
1354 if ((Object
->Entry
[EntryIndex
].Type
!= EfiDebuggerSymbolFunction
) &&
1355 (Object
->Entry
[EntryIndex
].Type
!= EfiDebuggerSymbolStaticFunction
)) {
1359 // Skip match varbss_init function, because they has no source code
1361 if (AsciiStrnCmp (Object
->Entry
[EntryIndex
].Name
, "varbss_init", sizeof("varbss_init") - 1) == 0) {
1367 if (!MatchObjAndCod (Object
->Entry
[EntryIndex
].ObjName
, FileName
)) {
1371 // found it, return source buffer
1373 if (Object
->Entry
[EntryIndex
].CodBuffer
!= NULL
) {
1374 return Object
->Entry
[EntryIndex
].SourceBuffer
;
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
1394 @retval EFI_SUCCESS - Code loaded successfully
1399 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
1400 IN CHAR16
*MapFileName
,
1401 IN CHAR16
*FileName
,
1402 IN UINTN BufferSize
,
1406 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
1415 Object
= EdbFindSymbolFile (DebuggerPrivate
, MapFileName
, &ObjectIndex
);
1416 if (Object
== NULL
) {
1417 EDBPrint (L
"SymbolFile is not loaded!\n");
1418 return EFI_NOT_FOUND
;
1421 // Check duplicated File
1423 SourceBuffer
= EdbFindCodeFromObject (DebuggerPrivate
, Object
, FileName
);
1424 if (SourceBuffer
!= NULL
) {
1426 // unnload duplicated code
1428 Status
= EdbUnloadCode (DebuggerPrivate
, MapFileName
, FileName
, &SourceBuffer
);
1429 if (EFI_ERROR(Status
)) {
1430 DEBUG ((DEBUG_ERROR
, "Unload Duplicated Code File Error!\n"));
1433 Status
= EdbDeleteCodeBuffer (DebuggerPrivate
, MapFileName
, FileName
, SourceBuffer
);
1434 if (EFI_ERROR(Status
)) {
1435 DEBUG ((DEBUG_ERROR
, "Delete Duplicated Code File Error!\n"));
1442 // Go through each SymbolEntry
1444 for (EntryIndex
= 0; EntryIndex
< Object
->EntryCount
; EntryIndex
++) {
1446 // load symbol for function only
1448 if ((Object
->Entry
[EntryIndex
].Type
!= EfiDebuggerSymbolFunction
) &&
1449 (Object
->Entry
[EntryIndex
].Type
!= EfiDebuggerSymbolStaticFunction
)) {
1455 if (AsciiStrnCmp (Object
->Entry
[EntryIndex
].Name
, "varbss_init", sizeof("varbss_init") - 1) == 0) {
1461 if (!MatchObjAndCod (Object
->Entry
[EntryIndex
].ObjName
, FileName
)) {
1465 // load code for this symbol
1467 Object
->Entry
[EntryIndex
].CodBuffer
= EdbLoadCodBySymbol (
1468 Object
->Entry
[EntryIndex
].Name
,
1471 &Object
->Entry
[EntryIndex
].CodBufferSize
,
1472 &Object
->Entry
[EntryIndex
].FuncOffsetBase
1474 if (Object
->Entry
[EntryIndex
].CodBuffer
!= NULL
) {
1475 Object
->Entry
[EntryIndex
].SourceBuffer
= Buffer
;
1480 // patch end '\0' for each code buffer
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));
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
1505 @retval EFI_SUCCESS - Code unloaded successfully
1510 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
1511 IN CHAR16
*MapFileName
,
1512 IN CHAR16
*FileName
,
1516 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
1523 Object
= EdbFindSymbolFile (DebuggerPrivate
, MapFileName
, &ObjectIndex
);
1524 if (Object
== NULL
) {
1525 EDBPrint (L
"SymbolFile is not loaded!\n");
1526 return EFI_NOT_FOUND
;
1532 *Buffer
= EdbFindCodeFromObject (DebuggerPrivate
, Object
, FileName
);
1533 if (*Buffer
== NULL
) {
1534 EDBPrint (L
"CodeFile is not loaded!\n");
1535 return EFI_NOT_FOUND
;
1539 // go through each entry
1541 for (EntryIndex
= 0; EntryIndex
< Object
->EntryCount
; EntryIndex
++) {
1542 if ((Object
->Entry
[EntryIndex
].Type
!= EfiDebuggerSymbolFunction
) &&
1543 (Object
->Entry
[EntryIndex
].Type
!= EfiDebuggerSymbolStaticFunction
)) {
1546 if (AsciiStrnCmp (Object
->Entry
[EntryIndex
].Name
, "varbss_init", sizeof("varbss_init") - 1) == 0) {
1549 if (!MatchObjAndCod (Object
->Entry
[EntryIndex
].ObjName
, FileName
)) {
1553 // clean up the buffer
1555 Object
->Entry
[EntryIndex
].CodBuffer
= NULL
;
1556 Object
->Entry
[EntryIndex
].CodBufferSize
= 0;
1557 Object
->Entry
[EntryIndex
].FuncOffsetBase
= 0;
1558 Object
->Entry
[EntryIndex
].SourceBuffer
= NULL
;
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
1577 @retval EFI_SUCCESS - CodeBuffer added successfully
1582 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
1583 IN CHAR16
*MapFileName
,
1584 IN CHAR16
*CodeFileName
,
1585 IN UINTN SourceBufferSize
,
1586 IN VOID
*SourceBuffer
1590 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
1595 Object
= EdbFindSymbolFile (DebuggerPrivate
, MapFileName
, NULL
);
1596 if (Object
== NULL
) {
1597 EDBPrint (L
"SymbolFile is not loaded!\n");
1598 return EFI_NOT_FOUND
;
1602 // Add it to last entry
1604 for (Index
= 0; Object
->SourceBuffer
[Index
] != NULL
; Index
++) {
1607 Object
->SourceBuffer
[Index
] = SourceBuffer
;
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
1621 @retval EFI_SUCCESS - CodeBuffer deleted successfully
1625 EdbDeleteCodeBuffer (
1626 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
1627 IN CHAR16
*MapFileName
,
1628 IN CHAR16
*CodeFileName
,
1629 IN VOID
*SourceBuffer
1633 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
1638 Object
= EdbFindSymbolFile (DebuggerPrivate
, MapFileName
, NULL
);
1639 if (Object
== NULL
) {
1640 EDBPrint (L
"SymbolFile is not loaded!\n");
1641 return EFI_NOT_FOUND
;
1644 for (Index
= 0; Object
->SourceBuffer
[Index
] != NULL
; Index
++) {
1646 // free the buffer if match
1648 if (Object
->SourceBuffer
[Index
] == SourceBuffer
) {
1649 gBS
->FreePool (SourceBuffer
);
1654 if (Object
->SourceBuffer
[Index
] == NULL
) {
1656 // not return NOT_FOUND
1664 Object
->SourceBuffer
[Index
] = NULL
;
1665 for (Index
= Index
+ 1; Object
->SourceBuffer
[Index
] != NULL
; Index
++) {
1666 Object
->SourceBuffer
[Index
- 1] = Object
->SourceBuffer
[Index
];
1668 Object
->SourceBuffer
[Index
- 1] = NULL
;
1675 Find the symbol string according to address.
1677 @param Address - Symbol address
1679 @return Symbol string
1688 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
1690 EFI_DEBUGGER_SYMBOL_ENTRY
*Entry
;
1693 // need we display symbol
1695 if (!mDebuggerPrivate
.DebuggerSymbolContext
.DisplaySymbol
) {
1700 // Go through each object and entry
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
++) {
1707 // if Address match, return Name
1709 if (Address
== (Entry
[EntryIndex
].Rva
+ Object
[ObjectIndex
].BaseAddress
)) {
1710 return Entry
[EntryIndex
].Name
;
1723 Get line number and offset from this line in code file.
1725 @param Line - Line buffer in code file
1726 @param Offset - Offset to functin entry
1732 EdbGetLineNumberAndOffsetFromThisLine (
1741 LineNumber
= (UINTN
)-1;
1743 *Offset
= (UINTN
)-1;
1745 while (LineBuffer
!= NULL
) {
1749 if (*LineBuffer
!= ' ') {
1756 if (*(LineBuffer
+ 2) != ' ') {
1757 if (*Offset
== (UINTN
)-1) {
1758 FieldBuffer
= AsciiStrGetNewTokenField (LineBuffer
+ 2, " ");
1759 *Offset
= AsciiXtoi (FieldBuffer
);
1760 PatchForAsciiStrTokenAfter (FieldBuffer
, ' ');
1765 // 1. assembly instruction
1767 FieldBuffer
= AsciiStrGetNewTokenField (LineBuffer
, ":");
1771 FieldBuffer
= AsciiStrGetNextTokenField (":");
1772 PatchForAsciiStrTokenBefore (FieldBuffer
, ':');
1773 if (FieldBuffer
== NULL
) {
1778 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
1779 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1785 FieldBuffer
= AsciiStrGetNextTokenField (":");
1786 PatchForAsciiStrTokenBefore (FieldBuffer
, ':');
1787 if (FieldBuffer
== NULL
) {
1791 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
1792 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1796 LineNumber
= AsciiAtoi (FieldBuffer
);
1808 EdbEbcLineSearchTypeAny
,
1809 EdbEbcLineSearchTypeFirst
,
1810 EdbEbcLineSearchTypeLast
,
1811 EdbEbcLineSearchTypeMax
,
1812 } EDB_EBC_LINE_SEARCH_TYPE
;
1816 Get line number from this code file.
1818 @param Entry - Symbol entry
1819 @param FuncOffset - Offset to functin entry
1820 @param SearchType - Search type for the code
1826 EdbGetLineNumberFromCode (
1827 IN EFI_DEBUGGER_SYMBOL_ENTRY
*Entry
,
1828 IN UINTN FuncOffset
,
1829 IN EDB_EBC_LINE_SEARCH_TYPE SearchType
1835 UINTN CandidateLineNumber
;
1836 UINTN CandidateOffset
;
1838 if (SearchType
< 0 || SearchType
>= EdbEbcLineSearchTypeMax
) {
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');
1856 LineNumber
= EdbGetLineNumberAndOffsetFromThisLine (LineBuffer
, &Offset
);
1861 if (Offset
!= FuncOffset
) {
1863 // Check last offset match
1865 if (CandidateOffset
== FuncOffset
) {
1866 if (SearchType
== EdbEbcLineSearchTypeLast
) {
1867 PatchForAsciiStrTokenAfter (LineBuffer
, '\n');
1868 if (CandidateLineNumber
!= LineNumber
) {
1869 return CandidateLineNumber
;
1880 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
1881 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1882 CandidateLineNumber
= LineNumber
;
1887 // Offset match, more check
1889 if (SearchType
== EdbEbcLineSearchTypeAny
) {
1890 PatchForAsciiStrTokenAfter (LineBuffer
, '\n');
1894 if (SearchType
== EdbEbcLineSearchTypeFirst
) {
1898 PatchForAsciiStrTokenAfter (LineBuffer
, '\n');
1899 if (CandidateLineNumber
!= LineNumber
) {
1906 CandidateLineNumber
= LineNumber
;
1907 CandidateOffset
= Offset
;
1909 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
1910 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1914 // Check last offset match
1916 if (CandidateOffset
== FuncOffset
) {
1917 if (SearchType
== EdbEbcLineSearchTypeLast
) {
1918 return CandidateLineNumber
;
1927 Get the source string from this code file by line.
1929 @param Entry - Symbol entry
1930 @param LineNumber - line number
1931 @param FuncEnd - Function end
1933 @return Funtion start
1937 EdbGetSourceStrFromCodeByLine (
1938 IN EFI_DEBUGGER_SYMBOL_ENTRY
*Entry
,
1939 IN UINTN LineNumber
,
1949 LineBuffer
= AsciiStrGetNewTokenLine (Entry
->CodBuffer
, "\n");
1950 while (LineBuffer
!= NULL
) {
1951 if (*LineBuffer
!= ';') {
1952 if (FuncStart
!= NULL
) {
1956 *FuncEnd
= LineBuffer
- 1;
1957 PatchForAsciiStrTokenAfter (LineBuffer
, '\n');
1960 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
1961 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1968 FieldBuffer
= AsciiStrGetNewTokenField (LineBuffer
+ 1, " ");
1969 Number
= AsciiAtoi (FieldBuffer
);
1970 PatchForAsciiStrTokenAfter (FieldBuffer
, ' ');
1971 if (Number
!= LineNumber
) {
1972 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
1973 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1978 // Line match, get line number
1980 if (FuncStart
== NULL
) {
1981 FuncStart
= LineBuffer
;
1984 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
1985 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1993 Get source string from this code file.
1995 @param Entry - Symbol entry
1996 @param FuncOffset - Offset to functin entry
1997 @param FuncEnd - Function end
1999 @retval Funtion start
2003 EdbGetSourceStrFromCode (
2004 IN EFI_DEBUGGER_SYMBOL_ENTRY
*Entry
,
2005 IN UINTN FuncOffset
,
2012 // Only search the last line, then display
2014 LineNumber
= EdbGetLineNumberFromCode (Entry
, FuncOffset
, EdbEbcLineSearchTypeLast
);
2015 if (LineNumber
== (UINTN
)-1) {
2019 return EdbGetSourceStrFromCodeByLine (Entry
, LineNumber
, FuncEnd
);
2026 @param Address - Instruction address
2027 @param IsPrint - Whether need to print
2029 @retval 1 - find the source
2030 @retval 0 - not find the source
2039 UINTN SymbolAddress
;
2040 EFI_DEBUGGER_SYMBOL_OBJECT
*RetObject
;
2041 EFI_DEBUGGER_SYMBOL_ENTRY
*RetEntry
;
2046 CHAR8 Buffer
[EFI_DEBUG_MAX_PRINT_BUFFER
];
2050 // need we display symbol
2052 if (!mDebuggerPrivate
.DebuggerSymbolContext
.DisplaySymbol
) {
2057 // find the symbol address
2059 SymbolAddress
= EbdFindSymbolAddress (
2061 EdbMatchSymbolTypeLowerAddress
,
2065 if (SymbolAddress
== 0) {
2069 FuncOffset
= Address
- SymbolAddress
+ RetEntry
->FuncOffsetBase
;
2074 FuncStart
= EdbGetSourceStrFromCode (RetEntry
, FuncOffset
, (VOID
**) &FuncEnd
);
2075 if (FuncStart
== NULL
) {
2080 // check whether need to real print
2086 *(UINT8
*)FuncEnd
= 0;
2089 // seperate buffer by \n, so that \r can be added.
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
;
2097 BufferSize
= EFI_DEBUG_MAX_PRINT_BUFFER
- 3;
2099 if (BufferSize
!= 0) {
2100 CopyMem (Buffer
, FuncStart
, BufferSize
);
2102 Buffer
[BufferSize
] = 0;
2103 EDBPrint (L
"%a\n", Buffer
);
2104 FuncStart
= FuncIndex
+ 1;
2105 FuncIndex
= FuncStart
;
2114 *(UINT8
*)FuncEnd
= '\n';
2121 Get Mapfile and SymbolName from one symbol format: [MapFileName:]SymbolName.
2123 @param Symbol - whole Symbol name
2124 @param MapfileName - the mapfile name in the symbol
2125 @param SymbolName - the symbol name in the symbol
2129 GetMapfileAndSymbol (
2131 OUT CHAR16
**MapfileName
,
2132 OUT CHAR16
**SymbolName
2137 *MapfileName
= NULL
;
2138 *SymbolName
= Symbol
;
2140 for (Ch
= Symbol
; *Ch
!= 0; Ch
++) {
2145 *MapfileName
= Symbol
;
2147 *SymbolName
= Ch
+ 1;
2157 Convert a symbol to an address.
2159 @param Symbol - Symbol name
2160 @param Address - Symbol address
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
2174 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
2176 EFI_DEBUGGER_SYMBOL_ENTRY
*Entry
;
2178 CHAR16
*MapfileName
;
2181 // Split one symbol to mapfile name and symbol name
2183 GetMapfileAndSymbol (Symbol
, &MapfileName
, &SymbolName
);
2187 // Go through each object
2189 Object
= mDebuggerPrivate
.DebuggerSymbolContext
.Object
;
2190 for (ObjectIndex
= 0; ObjectIndex
< mDebuggerPrivate
.DebuggerSymbolContext
.ObjectCount
; ObjectIndex
++) {
2192 // Check MapfileName
2194 if ((MapfileName
!= NULL
) && (StriCmp (Object
[ObjectIndex
].Name
, MapfileName
) != 0)) {
2198 // Go through each entry
2200 Entry
= Object
[ObjectIndex
].Entry
;
2201 for (EntryIndex
= 0; EntryIndex
< Object
[ObjectIndex
].EntryCount
; EntryIndex
++) {
2203 // Check SymbolName (case sensitive)
2205 if (StrCmpUnicodeAndAscii (SymbolName
, Entry
[EntryIndex
].Name
) == 0) {
2206 if ((*Address
!= 0) && (MapfileName
== NULL
)) {
2208 // Find the duplicated symbol
2210 EDBPrint (L
"Duplicated Symbol found!\n");
2211 return EFI_NO_MAPPING
;
2216 *Address
= (Entry
[EntryIndex
].Rva
+ Object
[ObjectIndex
].BaseAddress
);
2222 if (*Address
== 0) {
2226 return EFI_NOT_FOUND
;