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);
65 Entry
->Rva
= Address
% EFI_DEBUGGER_DEFAULT_LINK_IMAGEBASE
;
80 EdbEbcMapParseStateUninitialized
,
81 EdbEbcMapParseStateSymbolStart
,
82 EdbEbcMapParseStateSeHandlerSymbol
,
83 EdbEbcMapParseStateFunctionSymbol
,
84 EdbEbcMapParseStateVarbssInitSymbol
,
85 EdbEbcMapParseStateCrtSymbol
,
86 EdbEbcMapParseStateVariableSymbol
,
87 EdbEbcMapParseStateStaticFunctionSymbol
,
88 EdbEbcMapParseStateMax
,
89 } EDB_EBC_MAP_PARSE_STATE
;
92 EdbEbcSymbolParseStateUninitialized
,
93 EdbEbcSymbolParseStateReadyForName
,
94 EdbEbcSymbolParseStateReadyForRVA
,
95 EdbEbcSymbolParseStateReadyForType
,
96 EdbEbcSymbolParseStateReadyForObject
,
97 EdbEbcSymbolParseStateMax
,
98 } EDB_EBC_SYMBOL_PARSE_STATE
;
102 The following code depends on the MAP file generated by IEC compiler (actually Microsoft linker).
104 Sample as follows: EbcTest.map
105 ===============================================================================
108 Timestamp is 45b02718 (Fri Jan 19 10:04:08 2007)
110 Preferred load address is 10000000
112 Start Length Name Class
113 0001:00000000 00000370H .text CODE
114 0002:00000000 00000030H _VARBSS_INIT CODE
115 0003:00000000 00000004H .CRT$TSA DATA
116 0003:00000004 00000004H .CRT$TSC DATA
117 0003:00000008 00000004H .CRT$X DATA
118 0003:0000000c 00000008H .CRT$XCU DATA
119 0003:00000014 00000004H .CRT$Z DATA
120 0003:00000020 0000001cH .rdata DATA
121 0003:0000003c 00000000H .edata DATA
122 0003:0000003c 00000056H .rdata$debug DATA
123 0004:00000000 00000070H .data DATA
124 0004:00000070 00000020H .bss DATA
126 Address Publics by Value Rva+Base Lib:Object
128 0000:00000000 ___safe_se_handler_table 00000000 <absolute>
129 0000:00000000 ___safe_se_handler_count 00000000 <absolute>
130 0001:00000042 TestSubRoutine 10000442 f EbcTest.obj
131 0001:0000011a EfiMain 1000051a f EbcTest.obj
132 0001:00000200 TestSubRoutineSub 10000600 f EbcTestSub.obj
133 0001:00000220 EfiStart 10000620 f EbcLib:EbcLib.obj
134 0002:00000000 varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest$c45b02717 10000800 f EbcTest.obj
135 0002:00000020 varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTestSub$c45af77f3 10000820 f EbcTestSub.obj
136 0003:00000000 CrtThunkBegin 10000a00 EbcLib:EbcLib.obj
137 0003:00000004 CrtThunkEnd 10000a04 EbcLib:EbcLib.obj
138 0003:00000008 CrtBegin 10000a08 EbcLib:EbcLib.obj
139 0003:00000014 CrtEnd 10000a14 EbcLib:EbcLib.obj
140 0004:00000070 TestStr 10000c70 EbcTest.obj
141 0004:00000078 TestVariable1 10000c78 EbcTest.obj
142 0004:00000080 TestSubVariableSub 10000c80 EbcTestSub.obj
144 entry point at 0001:00000220
148 0001:00000000 TestSubRoutine2 10000400 f EbcTest.obj
149 ===============================================================================
155 Load symbol entry by Iec.
157 @param Object - Symbol file object
158 @param BufferSize - Symbol file buffer size
159 @param Buffer - Symbol file buffer
161 @retval EFI_SUCCESS - add symbol entry successfully
165 EdbLoadSymbolEntryByIec (
166 IN EFI_DEBUGGER_SYMBOL_OBJECT
*Object
,
173 EDB_EBC_MAP_PARSE_STATE MapParseState
;
174 EDB_EBC_SYMBOL_PARSE_STATE SymbolParseState
;
178 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 (" ");
210 if (AsciiStrCmp (FieldBuffer
, "Address") == 0) {
211 MapParseState
= EdbEbcMapParseStateSymbolStart
;
218 if (AsciiStrCmp (FieldBuffer
, "Static") == 0) {
219 MapParseState
= EdbEbcMapParseStateStaticFunctionSymbol
;
223 if (MapParseState
== EdbEbcMapParseStateUninitialized
) {
225 // Do not parse anything until get "Address" or "Static"
230 if (AsciiStrCmp (FieldBuffer
, "entry") == 0) {
238 // Now we start to parse this line for Name, Address, and Object
240 switch (SymbolParseState
) {
241 case EdbEbcSymbolParseStateUninitialized
:
245 SymbolParseState
= EdbEbcSymbolParseStateReadyForName
;
247 case EdbEbcSymbolParseStateReadyForName
:
251 if (AsciiStrnCmp (FieldBuffer
, "___safe_se_handler", AsciiStrLen ("___safe_se_handler")) == 0) {
255 MapParseState
= EdbEbcMapParseStateSeHandlerSymbol
;
257 } else if (AsciiStrnCmp (FieldBuffer
, "varbss_init", AsciiStrLen ("varbss_init")) == 0) {
261 MapParseState
= EdbEbcMapParseStateVarbssInitSymbol
;
262 // goto ExitFieldParse;
264 SymbolParseState
= EdbEbcSymbolParseStateReadyForRVA
;
265 } else if (AsciiStrnCmp (FieldBuffer
, "Crt", AsciiStrLen ("Crt")) == 0) {
269 MapParseState
= EdbEbcMapParseStateCrtSymbol
;
270 // goto ExitFieldParse;
272 SymbolParseState
= EdbEbcSymbolParseStateReadyForRVA
;
275 // Now, it is normal function
277 switch (MapParseState
) {
278 case EdbEbcMapParseStateSeHandlerSymbol
:
279 MapParseState
= EdbEbcMapParseStateFunctionSymbol
;
281 case EdbEbcMapParseStateCrtSymbol
:
282 MapParseState
= EdbEbcMapParseStateVariableSymbol
;
284 case EdbEbcMapParseStateFunctionSymbol
:
285 case EdbEbcMapParseStateVariableSymbol
:
286 case EdbEbcMapParseStateStaticFunctionSymbol
:
294 SymbolParseState
= EdbEbcSymbolParseStateReadyForRVA
;
298 case EdbEbcSymbolParseStateReadyForRVA
:
302 Address
= AsciiXtoi (FieldBuffer
);
303 SymbolParseState
= EdbEbcSymbolParseStateReadyForType
;
305 case EdbEbcSymbolParseStateReadyForType
:
307 // Get the Type. This is optional, only for "f".
309 if (AsciiStrCmp (FieldBuffer
, "f") == 0) {
310 SymbolParseState
= EdbEbcSymbolParseStateReadyForObject
;
311 switch (MapParseState
) {
312 case EdbEbcMapParseStateFunctionSymbol
:
313 case EdbEbcMapParseStateVarbssInitSymbol
:
314 Type
= EfiDebuggerSymbolFunction
;
316 case EdbEbcMapParseStateStaticFunctionSymbol
:
317 Type
= EfiDebuggerSymbolStaticFunction
;
328 // Else it should be Object.
329 // let it bypass here
331 case EdbEbcSymbolParseStateReadyForObject
:
333 case EfiDebuggerSymbolTypeMax
:
334 switch (MapParseState
) {
335 case EdbEbcMapParseStateVariableSymbol
:
336 case EdbEbcMapParseStateCrtSymbol
:
337 Type
= EfiDebuggerSymbolGlobalVariable
;
339 case EdbEbcMapParseStateSeHandlerSymbol
:
350 case EfiDebuggerSymbolFunction
:
351 case EfiDebuggerSymbolStaticFunction
:
361 ObjName
= FieldBuffer
;
362 SymbolParseState
= EdbEbcSymbolParseStateUninitialized
;
370 // Get the next field
372 FieldBuffer
= AsciiStrGetNextTokenField (" ");
376 // Add the entry if we get everything.
378 if ((Name
!= NULL
) && (Type
!= EfiDebuggerSymbolTypeMax
)) {
379 EdbLoadSymbolSingleEntry (Object
, Name
, ObjName
, Address
, Type
);
386 LineBuffer
= AsciiStrGetNextTokenLine ("\n\r");
399 @param Object - Symbol file object
400 @param BufferSize - Symbol file buffer size
401 @param Buffer - Symbol file buffer
403 @retval EFI_SUCCESS - add symbol entry successfully
408 IN EFI_DEBUGGER_SYMBOL_OBJECT
*Object
,
414 // MAP file format depends on the compiler (actually linker).
416 // It is possible to check the different MAP file format in this routine.
417 // Now only IEC is supported.
419 return EdbLoadSymbolEntryByIec (Object
, BufferSize
, Buffer
);
424 Find symbol file by name.
426 @param DebuggerPrivate - EBC Debugger private data structure
427 @param FileName - Symbol file name
428 @param Index - Symbol file index
433 EFI_DEBUGGER_SYMBOL_OBJECT
*
435 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
437 IN OUT UINTN
*Index OPTIONAL
445 for (ObjectIndex
= 0; ObjectIndex
< DebuggerPrivate
->DebuggerSymbolContext
.ObjectCount
; ObjectIndex
++) {
446 if (StrCmp (FileName
, DebuggerPrivate
->DebuggerSymbolContext
.Object
[ObjectIndex
].Name
) == 0) {
448 // Name match, found it
451 *Index
= ObjectIndex
;
454 return &DebuggerPrivate
->DebuggerSymbolContext
.Object
[ObjectIndex
];
466 Find symbol by address.
468 @param Address - Symbol address
469 @param Type - Search type
470 @param RetObject - Symbol object
471 @param RetEntry - Symbol entry
473 @return Nearest symbol address
477 EbdFindSymbolAddress (
479 IN EDB_MATCH_SYMBOL_TYPE Type
,
480 OUT EFI_DEBUGGER_SYMBOL_OBJECT
**RetObject
,
481 OUT EFI_DEBUGGER_SYMBOL_ENTRY
**RetEntry
486 UINTN CandidateLowerAddress
;
487 UINTN CandidateUpperAddress
;
488 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
489 EFI_DEBUGGER_SYMBOL_ENTRY
*Entry
;
490 EFI_DEBUGGER_SYMBOL_ENTRY
*LowEntry
;
491 EFI_DEBUGGER_SYMBOL_ENTRY
*UpperEntry
;
492 EFI_DEBUGGER_SYMBOL_OBJECT
*LowObject
;
493 EFI_DEBUGGER_SYMBOL_OBJECT
*UpperObject
;
495 if ((Type
< 0) || (Type
>= EdbMatchSymbolTypeMax
)) {
502 CandidateLowerAddress
= 0;
503 CandidateUpperAddress
= (UINTN
)-1;
510 // Go through each object
512 Object
= mDebuggerPrivate
.DebuggerSymbolContext
.Object
;
513 for (Index
= 0; Index
< mDebuggerPrivate
.DebuggerSymbolContext
.ObjectCount
; Index
++, Object
++) {
514 if (Object
->EntryCount
== 0) {
519 // Go through each entry
521 Entry
= Object
->Entry
;
522 for (SubIndex
= 0; SubIndex
< Object
->EntryCount
; SubIndex
++, Entry
++) {
523 if (Address
!= Entry
->Rva
+ Object
->BaseAddress
) {
525 // Check for nearest address
527 if (Address
> Entry
->Rva
+ Object
->BaseAddress
) {
529 // Record it if Current RVA < Address
531 if (CandidateLowerAddress
< Entry
->Rva
+ Object
->BaseAddress
) {
532 CandidateLowerAddress
= Entry
->Rva
+ Object
->BaseAddress
;
538 // Record it if Current RVA > Address
540 if (CandidateUpperAddress
> Entry
->Rva
+ Object
->BaseAddress
) {
541 CandidateUpperAddress
= Entry
->Rva
+ Object
->BaseAddress
;
543 UpperObject
= Object
;
551 // address match, return directly
560 // No Match, provide latest symbol
563 if ((Address
- CandidateLowerAddress
) < EFI_DEBUGGER_MAX_SYMBOL_ADDRESS_DELTA_VALUE
) {
565 // Check for lower address
567 if (((Type
== EdbMatchSymbolTypeNearestAddress
) &&
568 ((CandidateUpperAddress
- Address
) > (Address
- CandidateLowerAddress
))) ||
569 (Type
== EdbMatchSymbolTypeLowerAddress
))
572 // return nearest lower address
574 *RetEntry
= LowEntry
;
575 *RetObject
= LowObject
;
576 return CandidateLowerAddress
;
580 if ((CandidateUpperAddress
- Address
) < EFI_DEBUGGER_MAX_SYMBOL_ADDRESS_DELTA_VALUE
) {
582 // Check for upper address
584 if (((Type
== EdbMatchSymbolTypeNearestAddress
) &&
585 ((CandidateUpperAddress
- Address
) < (Address
- CandidateLowerAddress
))) ||
586 (Type
== EdbMatchSymbolTypeUpperAddress
))
589 // return nearest upper address
591 *RetEntry
= UpperEntry
;
592 *RetObject
= UpperObject
;
593 return CandidateUpperAddress
;
598 // No match and nearest one, return NULL
605 Unload symbol file by name.
607 @param DebuggerPrivate - EBC Debugger private data structure
608 @param FileName - Symbol file name
610 @retval EFI_SUCCESS - unload symbol successfully
615 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
619 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
622 EFI_DEBUGGER_SYMBOL_ENTRY
*OldEntry
;
625 VOID
**OldSourceBuffer
;
630 Object
= EdbFindSymbolFile (DebuggerPrivate
, FileName
, &ObjectIndex
);
631 if (Object
== NULL
) {
632 EDBPrint (L
"SymbolFile is not loaded!\n");
633 return EFI_DEBUG_CONTINUE
;
639 Object
= DebuggerPrivate
->DebuggerSymbolContext
.Object
;
640 OldEntry
= Object
->Entry
;
641 OldSourceBuffer
= Object
->SourceBuffer
;
642 MaxEntryCount
= Object
->MaxEntryCount
;
643 OldEntryCount
= Object
->EntryCount
;
646 // Remove the matched Object
648 for (Index
= ObjectIndex
; Index
< DebuggerPrivate
->DebuggerSymbolContext
.ObjectCount
- 1; Index
++) {
649 CopyMem (&Object
[Index
], &Object
[Index
+ 1], sizeof (EFI_DEBUGGER_SYMBOL_OBJECT
));
652 ZeroMem (&Object
[Index
], sizeof (Object
[Index
]));
655 // Move old data to new place
657 Object
[Index
].Entry
= OldEntry
;
658 Object
[Index
].SourceBuffer
= OldSourceBuffer
;
659 Object
[Index
].MaxEntryCount
= MaxEntryCount
;
660 DebuggerPrivate
->DebuggerSymbolContext
.ObjectCount
--;
663 // Clean old entry data
665 for (Index
= 0; Index
< OldEntryCount
; Index
++) {
666 ZeroMem (&OldEntry
[Index
], sizeof (OldEntry
[Index
]));
670 // Free OldSourceBuffer
672 for (Index
= 0; OldSourceBuffer
[Index
] != NULL
; Index
++) {
673 gBS
->FreePool (OldSourceBuffer
[Index
]);
674 OldSourceBuffer
[Index
] = NULL
;
682 Load symbol file by name.
684 @param DebuggerPrivate - EBC Debugger private data structure
685 @param FileName - Symbol file name
686 @param BufferSize - Symbol file buffer size
687 @param Buffer - Symbol file buffer
689 @retval EFI_SUCCESS - load symbol successfully
694 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
700 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
704 // Check duplicated File
706 Object
= EdbFindSymbolFile (DebuggerPrivate
, FileName
, NULL
);
707 if (Object
!= NULL
) {
708 Status
= EdbUnloadSymbol (DebuggerPrivate
, FileName
);
709 if (EFI_ERROR (Status
)) {
710 DEBUG ((DEBUG_ERROR
, "Unload Duplicated Symbol File Error!\n"));
716 // Check Count VS MaxCount
718 if (DebuggerPrivate
->DebuggerSymbolContext
.ObjectCount
>= DebuggerPrivate
->DebuggerSymbolContext
.MaxObjectCount
) {
723 return EFI_OUT_OF_RESOURCES
;
726 Object
= &DebuggerPrivate
->DebuggerSymbolContext
.Object
[DebuggerPrivate
->DebuggerSymbolContext
.ObjectCount
];
731 Object
->EntryCount
= 0;
732 Object
->MaxEntryCount
= EFI_DEBUGGER_SYMBOL_ENTRY_MAX
;
737 DEBUG ((DEBUG_ERROR
, "Symbol File: %s\n", FileName
));
738 Status
= EdbLoadSymbolEntry (Object
, BufferSize
, Buffer
);
739 if (EFI_ERROR (Status
)) {
748 sizeof (Object
->Name
) / sizeof (CHAR16
),
750 (sizeof (Object
->Name
) / sizeof (CHAR16
)) - 1
752 Object
->BaseAddress
= 0;
755 // Increase the object count
757 DebuggerPrivate
->DebuggerSymbolContext
.ObjectCount
++;
764 Located PDB path name in PE image.
766 @param ImageBase - base of PE to search
768 @return Pointer into image at offset of PDB file name if PDB file name is found,
769 Otherwise a pointer to an empty string.
779 EFI_IMAGE_DOS_HEADER
*DosHdr
;
780 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NtHdr
;
781 EFI_IMAGE_OPTIONAL_HEADER32
*OptionalHdr32
;
782 EFI_IMAGE_OPTIONAL_HEADER64
*OptionalHdr64
;
783 EFI_IMAGE_DATA_DIRECTORY
*DirectoryEntry
;
784 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*DebugEntry
;
785 VOID
*CodeViewEntryPointer
;
790 CodeViewEntryPointer
= NULL
;
797 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
801 NtHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)((UINT8
*)DosHdr
+ DosHdr
->e_lfanew
);
803 // Check Machine, filter for EBC
805 if (NtHdr
->Pe32
.FileHeader
.Machine
!= EFI_IMAGE_MACHINE_EBC
) {
807 // If not EBC, return NULL
813 // Get DirectoryEntry
814 // EBC spec says PE32+, but implementation uses PE32. So check dynamically here.
816 if (NtHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
817 OptionalHdr32
= (VOID
*)&NtHdr
->Pe32
.OptionalHeader
;
818 DirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*)&(OptionalHdr32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
]);
819 } else if (NtHdr
->Pe32Plus
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
820 OptionalHdr64
= (VOID
*)&NtHdr
->Pe32Plus
.OptionalHeader
;
821 DirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*)&(OptionalHdr64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
]);
826 if (DirectoryEntry
->VirtualAddress
== 0) {
831 // Go through DirectoryEntry
834 (DirCount
< DirectoryEntry
->Size
/ sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
)) && CodeViewEntryPointer
== NULL
;
838 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*)(DirectoryEntry
->VirtualAddress
+ (UINTN
)ImageBase
+ DirCount
* sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
));
839 if (DebugEntry
->Type
== EFI_IMAGE_DEBUG_TYPE_CODEVIEW
) {
841 // Match DebugEntry, only CODEVIEW_SIGNATURE_NB10 and CODEVIEW_SIGNATURE_RSDS are supported.
843 CodeViewEntryPointer
= (VOID
*)((UINTN
)DebugEntry
->RVA
+ (UINTN
)ImageBase
);
844 switch (*(UINT32
*)CodeViewEntryPointer
) {
845 case CODEVIEW_SIGNATURE_NB10
:
846 PdbPath
= (CHAR8
*)CodeViewEntryPointer
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
);
848 case CODEVIEW_SIGNATURE_RSDS
:
849 PdbPath
= (CHAR8
*)CodeViewEntryPointer
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY
);
865 Check whether PDB file and MAP file have same name.
867 @param PdbFileName - PDB file name
868 @param MapFileName - MAP file name
870 @retval TRUE - PDB and MAP file name match
871 @retval FALSE - PDB and MAP file name not match
876 IN CHAR8
*PdbFileName
,
877 IN CHAR16
*MapFileName
882 CHAR8
*PurePdbFileName
;
888 PurePdbFileName
= PdbFileName
;
889 for (Index
= 0; PdbFileName
[Index
] != 0; Index
++) {
890 if (PdbFileName
[Index
] == '\\') {
891 PurePdbFileName
= &PdbFileName
[Index
+ 1];
895 PdbFileName
= PurePdbFileName
;
900 PdbNameSize
= AsciiStrLen (PdbFileName
);
901 MapNameSize
= StrLen (MapFileName
);
903 if (PdbNameSize
!= MapNameSize
) {
910 for (Index
= 0; Index
< MapNameSize
- 4; Index
++) {
911 if ((PdbFileName
[Index
] | 0x20) != (MapFileName
[Index
] | 0x20)) {
920 // BUGBUG: work-around start
923 EFI_DEBUG_IMAGE_INFO
*EfiDebugImageInfoTable
;
924 volatile UINT32 UpdateStatus
;
926 } EFI_DEBUG_IMAGE_INFO_TABLE_HEADER_OLD
;
928 EFI_DEBUG_IMAGE_INFO_TABLE_HEADER mDebugImageInfoTableHeader
;
931 For compatibility consideration, we handle 2 cases:
935 +------------------------+ +------------------------+
936 | EfiDebugImageInfoTable | | UpdateStatus |
937 +------------------------+ +------------------------+
938 | UpdateStatus | | TableSize |
939 +------------------------+ +------------------------+
940 | TableSize | | EfiDebugImageInfoTable |
941 +------------------------+ +------------------------+
945 +------------------------+ +------------------------+
946 | EfiDebugImageInfoTable | | UpdateStatus |
947 | | +------------------------+
949 +------------------------+ +------------------------+
950 | UpdateStatus | | EfiDebugImageInfoTable |
951 +------------------------+ | |
953 +------------------------+ +------------------------+
955 @param DebugImageInfoTableHeader Point to the EFI_DEBUG_IMAGE_INFO_TABLE_HEADER structure.
959 EdbFixDebugImageInfoTable (
960 IN OUT EFI_DEBUG_IMAGE_INFO_TABLE_HEADER
**DebugImageInfoTableHeader
963 mDebugImageInfoTableHeader
.EfiDebugImageInfoTable
= ((EFI_DEBUG_IMAGE_INFO_TABLE_HEADER_OLD
*)(*DebugImageInfoTableHeader
))->EfiDebugImageInfoTable
;
964 mDebugImageInfoTableHeader
.UpdateStatus
= ((EFI_DEBUG_IMAGE_INFO_TABLE_HEADER_OLD
*)(*DebugImageInfoTableHeader
))->UpdateStatus
;
965 mDebugImageInfoTableHeader
.TableSize
= ((EFI_DEBUG_IMAGE_INFO_TABLE_HEADER_OLD
*)(*DebugImageInfoTableHeader
))->TableSize
;
967 if ((*DebugImageInfoTableHeader
)->UpdateStatus
> 3) {
968 *DebugImageInfoTableHeader
= &mDebugImageInfoTableHeader
;
972 if ((*DebugImageInfoTableHeader
)->TableSize
% (EFI_PAGE_SIZE
/ (sizeof (VOID
*))) != 0) {
973 *DebugImageInfoTableHeader
= &mDebugImageInfoTableHeader
;
981 // BUGBUG: work-around end
988 @param DebuggerPrivate - EBC Debugger private data structure
989 @param FileName - Symbol file name
990 @param SearchType - Search type for Object
992 @retval EFI_SUCCESS - Patch symbol RVA successfully
993 @retval EFI_NOT_FOUND - Symbol RVA base not found
998 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
1000 IN EDB_EBC_IMAGE_RVA_SEARCH_TYPE SearchType
1005 EFI_DEBUG_IMAGE_INFO
*ImageTable
;
1008 VOID
*CandidateImageBase
;
1009 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
1011 if ((SearchType
< 0) || (SearchType
>= EdbEbcImageRvaSearchTypeMax
)) {
1012 return EFI_INVALID_PARAMETER
;
1016 // Get the related object
1018 Object
= EdbFindSymbolFile (DebuggerPrivate
, FileName
, NULL
);
1019 if (Object
== NULL
) {
1020 return EFI_NOT_FOUND
;
1024 // Try again to get DebugImageInfoTable
1026 if (mDebuggerPrivate
.DebugImageInfoTableHeader
== NULL
) {
1027 Status
= EfiGetSystemConfigurationTable (
1028 &gEfiDebugImageInfoTableGuid
,
1029 (VOID
**)&mDebuggerPrivate
.DebugImageInfoTableHeader
1031 if (EFI_ERROR (Status
)) {
1032 EDBPrint (L
"DebugImageInfoTable not found!\n");
1037 DEBUG ((DEBUG_ERROR
, "DebugImageInfoTableHeader: %x\n", mDebuggerPrivate
.DebugImageInfoTableHeader
));
1040 // BUGBUG: work-around start
1042 EdbFixDebugImageInfoTable (&mDebuggerPrivate
.DebugImageInfoTableHeader
);
1044 // BUGBUG: work-around end
1048 // Go through DebugImageInfoTable for each Image
1050 CandidateImageBase
= NULL
;
1051 ImageTable
= mDebuggerPrivate
.DebugImageInfoTableHeader
->EfiDebugImageInfoTable
;
1052 for (ImageNumber
= 0; ImageNumber
< mDebuggerPrivate
.DebugImageInfoTableHeader
->TableSize
; ImageNumber
++) {
1053 if (ImageTable
[ImageNumber
].NormalImage
== NULL
) {
1057 ImageBase
= ImageTable
[ImageNumber
].NormalImage
->LoadedImageProtocolInstance
->ImageBase
;
1061 PdbPath
= GetPdbPath (ImageBase
);
1062 if (PdbPath
== NULL
) {
1069 if (!MatchPdbAndMap (PdbPath
, FileName
)) {
1073 DEBUG ((DEBUG_ERROR
, "ImageBase: %x\n", ImageBase
));
1078 if ((SearchType
== EdbEbcImageRvaSearchTypeAny
) || (SearchType
== EdbEbcImageRvaSearchTypeFirst
)) {
1080 // Assign base address and return
1082 Object
->BaseAddress
= (UINTN
)ImageBase
;
1087 // Get CandidateImageBase for EdbEbcImageRvaSearchTypeLast
1089 CandidateImageBase
= ImageBase
;
1093 // Check EdbEbcImageRvaSearchTypeLast
1095 if (SearchType
== EdbEbcImageRvaSearchTypeLast
) {
1096 if (CandidateImageBase
== NULL
) {
1097 return EFI_NOT_FOUND
;
1101 // Assign base address and return
1103 Object
->BaseAddress
= (UINTN
)CandidateImageBase
;
1110 return EFI_NOT_FOUND
;
1115 Check whether OBJ file and COD file have same name.
1117 @param ObjFileName - OBJ file name
1118 @param CodFileName - COD file name
1120 @retval TRUE - OBJ and COD file name match
1121 @retval FALSE - OBJ and COD file name not match
1126 IN CHAR8
*ObjFileName
,
1127 IN CHAR16
*CodFileName
1132 CHAR8
*PureObjFileName
;
1136 // remove library name
1138 PureObjFileName
= ObjFileName
;
1139 for (Index
= 0; ObjFileName
[Index
] != 0; Index
++) {
1140 if (ObjFileName
[Index
] == ':') {
1141 PureObjFileName
= &ObjFileName
[Index
+ 1];
1146 ObjFileName
= PureObjFileName
;
1151 ObjNameSize
= AsciiStrLen (ObjFileName
);
1152 CodNameSize
= StrLen (CodFileName
);
1154 if (ObjNameSize
!= CodNameSize
) {
1161 for (Index
= 0; Index
< CodNameSize
- 4; Index
++) {
1162 if ((ObjFileName
[Index
] | 0x20) != (CodFileName
[Index
] | 0x20)) {
1171 EdbEbcCodParseStateUninitialized
,
1172 EdbEbcCodParseStateSymbolInitialized
,
1173 EdbEbcCodParseStateSymbolStart
,
1174 EdbEbcCodParseStateSymbolEnd
,
1175 EdbEbcCodParseStateMax
,
1176 } EDB_EBC_COD_PARSE_STATE
;
1180 The following code depends on the COD file generated by IEC compiler.
1186 Load code by symbol by Iec.
1188 @param Name - Symbol file name
1189 @param Buffer - Symbol file buffer
1190 @param BufferSize - Symbol file buffer size
1191 @param CodeBufferSize - Code buffer size
1192 @param FuncOffset - Code funcion offset
1198 EdbLoadCodBySymbolByIec (
1201 IN UINTN BufferSize
,
1202 OUT UINTN
*CodeBufferSize
,
1203 OUT UINTN
*FuncOffset
1211 EDB_EBC_COD_PARSE_STATE CodParseState
;
1219 LineBuffer
= AsciiStrGetNewTokenLine (Buffer
, "\n\r");
1223 CodParseState
= EdbEbcCodParseStateUninitialized
;
1228 while (LineBuffer
!= NULL
) {
1229 switch (CodParseState
) {
1230 case EdbEbcCodParseStateUninitialized
:
1232 // check mark_begin, begin to check line after this match
1234 if (AsciiStrCmp (LineBuffer
, "; mark_begin;") == 0) {
1235 CodParseState
= EdbEbcCodParseStateSymbolInitialized
;
1238 LineBuffer
= AsciiStrGetNextTokenLine ("\n\r");
1239 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1242 case EdbEbcCodParseStateSymbolInitialized
:
1244 // check mark_end, not check line after this match
1246 if (AsciiStrCmp (LineBuffer
, "; mark_end;") == 0) {
1247 CodParseState
= EdbEbcCodParseStateUninitialized
;
1248 LineBuffer
= AsciiStrGetNextTokenLine ("\n\r");
1249 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1254 // not check this line if the first char is as follows
1256 if ((*LineBuffer
== 0) ||
1257 (*LineBuffer
== '$') ||
1258 (*LineBuffer
== ';') ||
1259 (*LineBuffer
== '_') ||
1260 (*LineBuffer
== ' '))
1262 LineBuffer
= AsciiStrGetNextTokenLine ("\n\r");
1263 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1268 // get function name, function name is followed by char 0x09.
1270 FieldBuffer
= AsciiStrGetNewTokenField (LineBuffer
, Char
);
1271 ASSERT (FieldBuffer
!= NULL
);
1272 if (AsciiStriCmp (FieldBuffer
, Name
) == 0) {
1273 BufferStart
= FieldBuffer
;
1274 CodParseState
= EdbEbcCodParseStateSymbolStart
;
1277 PatchForAsciiStrTokenAfter (FieldBuffer
, 0x9);
1282 LineBuffer
= AsciiStrGetNextTokenLine ("\n\r");
1283 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1286 case EdbEbcCodParseStateSymbolStart
:
1288 // check mark_end, if this match, means the function is found successfully.
1290 if (AsciiStrCmp (LineBuffer
, "; mark_end;") == 0) {
1291 CodParseState
= EdbEbcCodParseStateSymbolEnd
;
1293 // prepare CodeBufferSize, FuncOffset, and FuncStart to return
1295 BufferEnd
= LineBuffer
+ sizeof ("; mark_end;") - 1;
1296 *CodeBufferSize
= (UINTN
)BufferEnd
- (UINTN
)BufferStart
;
1297 *FuncOffset
= Offset
;
1298 PatchForAsciiStrTokenAfter (LineBuffer
, '\n');
1303 // Get function offset
1305 if ((Offset
== (UINTN
)-1) &&
1306 (*LineBuffer
== ' '))
1308 FieldBuffer
= AsciiStrGetNewTokenField (LineBuffer
+ 2, " ");
1309 Offset
= AsciiXtoi (FieldBuffer
);
1310 PatchForAsciiStrTokenAfter (FieldBuffer
, ' ');
1316 LineBuffer
= AsciiStrGetNextTokenLine ("\n\r");
1317 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1320 case EdbEbcCodParseStateSymbolEnd
:
1329 // no function found
1336 Load code by symbol.
1338 @param Name - Symbol file name
1339 @param Buffer - Symbol file buffer
1340 @param BufferSize - Symbol file buffer size
1341 @param CodeBufferSize - Code buffer size
1342 @param FuncOffset - Code funcion offset
1348 EdbLoadCodBySymbol (
1351 IN UINTN BufferSize
,
1352 OUT UINTN
*CodeBufferSize
,
1353 OUT UINTN
*FuncOffset
1357 // COD file format depends on the compiler.
1359 // It is possible to check the different COD file format in this routine.
1360 // Now only IEC is supported.
1362 return EdbLoadCodBySymbolByIec (Name
, Buffer
, BufferSize
, CodeBufferSize
, FuncOffset
);
1367 Find code from object.
1369 @param DebuggerPrivate EBC Debugger private data structure
1370 @param Object - Symbol object
1371 @param FileName - File name
1375 EdbFindCodeFromObject (
1376 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
1377 IN EFI_DEBUGGER_SYMBOL_OBJECT
*Object
,
1384 // Go througn each Entry in this Object
1386 for (EntryIndex
= 0; EntryIndex
< Object
->EntryCount
; EntryIndex
++) {
1388 // This check is for Function only
1390 if ((Object
->Entry
[EntryIndex
].Type
!= EfiDebuggerSymbolFunction
) &&
1391 (Object
->Entry
[EntryIndex
].Type
!= EfiDebuggerSymbolStaticFunction
))
1397 // Skip match varbss_init function, because they has no source code
1399 if (AsciiStrnCmp (Object
->Entry
[EntryIndex
].Name
, "varbss_init", sizeof ("varbss_init") - 1) == 0) {
1406 if (!MatchObjAndCod (Object
->Entry
[EntryIndex
].ObjName
, FileName
)) {
1411 // found it, return source buffer
1413 if (Object
->Entry
[EntryIndex
].CodBuffer
!= NULL
) {
1414 return Object
->Entry
[EntryIndex
].SourceBuffer
;
1428 @param DebuggerPrivate - EBC Debugger private data structure
1429 @param MapFileName - Symbol file name
1430 @param FileName - Code file name
1431 @param BufferSize - Code file buffer size
1432 @param Buffer - Code file buffer
1434 @retval EFI_SUCCESS - Code loaded successfully
1439 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
1440 IN CHAR16
*MapFileName
,
1441 IN CHAR16
*FileName
,
1442 IN UINTN BufferSize
,
1446 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
1455 Object
= EdbFindSymbolFile (DebuggerPrivate
, MapFileName
, &ObjectIndex
);
1456 if (Object
== NULL
) {
1457 EDBPrint (L
"SymbolFile is not loaded!\n");
1458 return EFI_NOT_FOUND
;
1461 // Check duplicated File
1463 SourceBuffer
= EdbFindCodeFromObject (DebuggerPrivate
, Object
, FileName
);
1464 if (SourceBuffer
!= NULL
) {
1466 // unnload duplicated code
1468 Status
= EdbUnloadCode (DebuggerPrivate
, MapFileName
, FileName
, &SourceBuffer
);
1469 if (EFI_ERROR (Status
)) {
1470 DEBUG ((DEBUG_ERROR
, "Unload Duplicated Code File Error!\n"));
1474 Status
= EdbDeleteCodeBuffer (DebuggerPrivate
, MapFileName
, FileName
, SourceBuffer
);
1475 if (EFI_ERROR (Status
)) {
1476 DEBUG ((DEBUG_ERROR
, "Delete Duplicated Code File Error!\n"));
1483 // Go through each SymbolEntry
1485 for (EntryIndex
= 0; EntryIndex
< Object
->EntryCount
; EntryIndex
++) {
1487 // load symbol for function only
1489 if ((Object
->Entry
[EntryIndex
].Type
!= EfiDebuggerSymbolFunction
) &&
1490 (Object
->Entry
[EntryIndex
].Type
!= EfiDebuggerSymbolStaticFunction
))
1498 if (AsciiStrnCmp (Object
->Entry
[EntryIndex
].Name
, "varbss_init", sizeof ("varbss_init") - 1) == 0) {
1505 if (!MatchObjAndCod (Object
->Entry
[EntryIndex
].ObjName
, FileName
)) {
1510 // load code for this symbol
1512 Object
->Entry
[EntryIndex
].CodBuffer
= EdbLoadCodBySymbol (
1513 Object
->Entry
[EntryIndex
].Name
,
1516 &Object
->Entry
[EntryIndex
].CodBufferSize
,
1517 &Object
->Entry
[EntryIndex
].FuncOffsetBase
1519 if (Object
->Entry
[EntryIndex
].CodBuffer
!= NULL
) {
1520 Object
->Entry
[EntryIndex
].SourceBuffer
= Buffer
;
1525 // patch end '\0' for each code buffer
1527 for (EntryIndex
= 0; EntryIndex
< Object
->EntryCount
; EntryIndex
++) {
1528 if (Object
->Entry
[EntryIndex
].CodBuffer
!= NULL
) {
1529 *((UINT8
*)Object
->Entry
[EntryIndex
].CodBuffer
+ Object
->Entry
[EntryIndex
].CodBufferSize
) = 0;
1530 DEBUG ((DEBUG_ERROR
, " CodeSymbol: %a, FuncOffset: 0x05%x\n", Object
->Entry
[EntryIndex
].Name
, Object
->Entry
[EntryIndex
].FuncOffsetBase
));
1531 // DEBUG ((DEBUG_ERROR, " [CODE]:\n%a\n", Object->Entry[EntryIndex].CodBuffer));
1545 @param DebuggerPrivate - EBC Debugger private data structure
1546 @param MapFileName - Symbol file name
1547 @param FileName - Code file name
1548 @param Buffer - Code file buffer
1550 @retval EFI_SUCCESS - Code unloaded successfully
1555 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
1556 IN CHAR16
*MapFileName
,
1557 IN CHAR16
*FileName
,
1561 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
1568 Object
= EdbFindSymbolFile (DebuggerPrivate
, MapFileName
, &ObjectIndex
);
1569 if (Object
== NULL
) {
1570 EDBPrint (L
"SymbolFile is not loaded!\n");
1571 return EFI_NOT_FOUND
;
1577 *Buffer
= EdbFindCodeFromObject (DebuggerPrivate
, Object
, FileName
);
1578 if (*Buffer
== NULL
) {
1579 EDBPrint (L
"CodeFile is not loaded!\n");
1580 return EFI_NOT_FOUND
;
1584 // go through each entry
1586 for (EntryIndex
= 0; EntryIndex
< Object
->EntryCount
; EntryIndex
++) {
1587 if ((Object
->Entry
[EntryIndex
].Type
!= EfiDebuggerSymbolFunction
) &&
1588 (Object
->Entry
[EntryIndex
].Type
!= EfiDebuggerSymbolStaticFunction
))
1593 if (AsciiStrnCmp (Object
->Entry
[EntryIndex
].Name
, "varbss_init", sizeof ("varbss_init") - 1) == 0) {
1597 if (!MatchObjAndCod (Object
->Entry
[EntryIndex
].ObjName
, FileName
)) {
1602 // clean up the buffer
1604 Object
->Entry
[EntryIndex
].CodBuffer
= NULL
;
1605 Object
->Entry
[EntryIndex
].CodBufferSize
= 0;
1606 Object
->Entry
[EntryIndex
].FuncOffsetBase
= 0;
1607 Object
->Entry
[EntryIndex
].SourceBuffer
= NULL
;
1620 @param DebuggerPrivate - EBC Debugger private data structure
1621 @param MapFileName - Symbol file name
1622 @param CodeFileName - Code file name
1623 @param SourceBufferSize- Code buffer size
1624 @param SourceBuffer - Code buffer
1626 @retval EFI_SUCCESS - CodeBuffer added successfully
1631 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
1632 IN CHAR16
*MapFileName
,
1633 IN CHAR16
*CodeFileName
,
1634 IN UINTN SourceBufferSize
,
1635 IN VOID
*SourceBuffer
1639 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
1644 Object
= EdbFindSymbolFile (DebuggerPrivate
, MapFileName
, NULL
);
1645 if (Object
== NULL
) {
1646 EDBPrint (L
"SymbolFile is not loaded!\n");
1647 return EFI_NOT_FOUND
;
1651 // Add it to last entry
1653 for (Index
= 0; Object
->SourceBuffer
[Index
] != NULL
; Index
++) {
1656 Object
->SourceBuffer
[Index
] = SourceBuffer
;
1665 @param DebuggerPrivate - EBC Debugger private data structure
1666 @param MapFileName - Symbol file name
1667 @param CodeFileName - Code file name
1668 @param SourceBuffer - Code buffer
1670 @retval EFI_SUCCESS - CodeBuffer deleted successfully
1674 EdbDeleteCodeBuffer (
1675 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
1676 IN CHAR16
*MapFileName
,
1677 IN CHAR16
*CodeFileName
,
1678 IN VOID
*SourceBuffer
1682 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
1687 Object
= EdbFindSymbolFile (DebuggerPrivate
, MapFileName
, NULL
);
1688 if (Object
== NULL
) {
1689 EDBPrint (L
"SymbolFile is not loaded!\n");
1690 return EFI_NOT_FOUND
;
1693 for (Index
= 0; Object
->SourceBuffer
[Index
] != NULL
; Index
++) {
1695 // free the buffer if match
1697 if (Object
->SourceBuffer
[Index
] == SourceBuffer
) {
1698 gBS
->FreePool (SourceBuffer
);
1703 if (Object
->SourceBuffer
[Index
] == NULL
) {
1705 // not return NOT_FOUND
1713 Object
->SourceBuffer
[Index
] = NULL
;
1714 for (Index
= Index
+ 1; Object
->SourceBuffer
[Index
] != NULL
; Index
++) {
1715 Object
->SourceBuffer
[Index
- 1] = Object
->SourceBuffer
[Index
];
1718 Object
->SourceBuffer
[Index
- 1] = NULL
;
1725 Find the symbol string according to address.
1727 @param Address - Symbol address
1729 @return Symbol string
1738 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
1740 EFI_DEBUGGER_SYMBOL_ENTRY
*Entry
;
1743 // need we display symbol
1745 if (!mDebuggerPrivate
.DebuggerSymbolContext
.DisplaySymbol
) {
1750 // Go through each object and entry
1752 Object
= mDebuggerPrivate
.DebuggerSymbolContext
.Object
;
1753 for (ObjectIndex
= 0; ObjectIndex
< mDebuggerPrivate
.DebuggerSymbolContext
.ObjectCount
; ObjectIndex
++) {
1754 Entry
= Object
[ObjectIndex
].Entry
;
1755 for (EntryIndex
= 0; EntryIndex
< Object
[ObjectIndex
].EntryCount
; EntryIndex
++) {
1757 // if Address match, return Name
1759 if (Address
== (Entry
[EntryIndex
].Rva
+ Object
[ObjectIndex
].BaseAddress
)) {
1760 return Entry
[EntryIndex
].Name
;
1773 Get line number and offset from this line in code file.
1775 @param Line - Line buffer in code file
1776 @param Offset - Offset to functin entry
1782 EdbGetLineNumberAndOffsetFromThisLine (
1791 LineNumber
= (UINTN
)-1;
1793 *Offset
= (UINTN
)-1;
1795 while (LineBuffer
!= NULL
) {
1799 if (*LineBuffer
!= ' ') {
1806 if (*(LineBuffer
+ 2) != ' ') {
1807 if (*Offset
== (UINTN
)-1) {
1808 FieldBuffer
= AsciiStrGetNewTokenField (LineBuffer
+ 2, " ");
1809 *Offset
= AsciiXtoi (FieldBuffer
);
1810 PatchForAsciiStrTokenAfter (FieldBuffer
, ' ');
1815 // 1. assembly instruction
1817 FieldBuffer
= AsciiStrGetNewTokenField (LineBuffer
, ":");
1821 FieldBuffer
= AsciiStrGetNextTokenField (":");
1822 PatchForAsciiStrTokenBefore (FieldBuffer
, ':');
1823 if (FieldBuffer
== NULL
) {
1828 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
1829 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1836 FieldBuffer
= AsciiStrGetNextTokenField (":");
1837 PatchForAsciiStrTokenBefore (FieldBuffer
, ':');
1838 if (FieldBuffer
== NULL
) {
1842 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
1843 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1847 LineNumber
= AsciiAtoi (FieldBuffer
);
1859 EdbEbcLineSearchTypeAny
,
1860 EdbEbcLineSearchTypeFirst
,
1861 EdbEbcLineSearchTypeLast
,
1862 EdbEbcLineSearchTypeMax
,
1863 } EDB_EBC_LINE_SEARCH_TYPE
;
1867 Get line number from this code file.
1869 @param Entry - Symbol entry
1870 @param FuncOffset - Offset to functin entry
1871 @param SearchType - Search type for the code
1877 EdbGetLineNumberFromCode (
1878 IN EFI_DEBUGGER_SYMBOL_ENTRY
*Entry
,
1879 IN UINTN FuncOffset
,
1880 IN EDB_EBC_LINE_SEARCH_TYPE SearchType
1886 UINTN CandidateLineNumber
;
1887 UINTN CandidateOffset
;
1889 if ((SearchType
< 0) || (SearchType
>= EdbEbcLineSearchTypeMax
)) {
1893 LineNumber
= (UINTN
)-1;
1894 CandidateLineNumber
= (UINTN
)-1;
1895 CandidateOffset
= (UINTN
)-1;
1896 LineBuffer
= AsciiStrGetNewTokenLine (Entry
->CodBuffer
, "\n");
1897 while (LineBuffer
!= NULL
) {
1898 if (*LineBuffer
!= ' ') {
1899 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
1900 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1907 LineNumber
= EdbGetLineNumberAndOffsetFromThisLine (LineBuffer
, &Offset
);
1912 if (Offset
!= FuncOffset
) {
1914 // Check last offset match
1916 if (CandidateOffset
== FuncOffset
) {
1917 if (SearchType
== EdbEbcLineSearchTypeLast
) {
1918 PatchForAsciiStrTokenAfter (LineBuffer
, '\n');
1919 if (CandidateLineNumber
!= LineNumber
) {
1920 return CandidateLineNumber
;
1931 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
1932 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1933 CandidateLineNumber
= LineNumber
;
1938 // Offset match, more check
1940 if (SearchType
== EdbEbcLineSearchTypeAny
) {
1941 PatchForAsciiStrTokenAfter (LineBuffer
, '\n');
1945 if (SearchType
== EdbEbcLineSearchTypeFirst
) {
1949 PatchForAsciiStrTokenAfter (LineBuffer
, '\n');
1950 if (CandidateLineNumber
!= LineNumber
) {
1957 CandidateLineNumber
= LineNumber
;
1958 CandidateOffset
= Offset
;
1960 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
1961 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1965 // Check last offset match
1967 if (CandidateOffset
== FuncOffset
) {
1968 if (SearchType
== EdbEbcLineSearchTypeLast
) {
1969 return CandidateLineNumber
;
1978 Get the source string from this code file by line.
1980 @param Entry - Symbol entry
1981 @param LineNumber - line number
1982 @param FuncEnd - Function end
1984 @return Funtion start
1988 EdbGetSourceStrFromCodeByLine (
1989 IN EFI_DEBUGGER_SYMBOL_ENTRY
*Entry
,
1990 IN UINTN LineNumber
,
2000 LineBuffer
= AsciiStrGetNewTokenLine (Entry
->CodBuffer
, "\n");
2001 while (LineBuffer
!= NULL
) {
2002 if (*LineBuffer
!= ';') {
2003 if (FuncStart
!= NULL
) {
2007 *FuncEnd
= LineBuffer
- 1;
2008 PatchForAsciiStrTokenAfter (LineBuffer
, '\n');
2012 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
2013 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
2020 FieldBuffer
= AsciiStrGetNewTokenField (LineBuffer
+ 1, " ");
2021 Number
= AsciiAtoi (FieldBuffer
);
2022 PatchForAsciiStrTokenAfter (FieldBuffer
, ' ');
2023 if (Number
!= LineNumber
) {
2024 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
2025 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
2030 // Line match, get line number
2032 if (FuncStart
== NULL
) {
2033 FuncStart
= LineBuffer
;
2036 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
2037 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
2045 Get source string from this code file.
2047 @param Entry - Symbol entry
2048 @param FuncOffset - Offset to functin entry
2049 @param FuncEnd - Function end
2051 @retval Funtion start
2055 EdbGetSourceStrFromCode (
2056 IN EFI_DEBUGGER_SYMBOL_ENTRY
*Entry
,
2057 IN UINTN FuncOffset
,
2064 // Only search the last line, then display
2066 LineNumber
= EdbGetLineNumberFromCode (Entry
, FuncOffset
, EdbEbcLineSearchTypeLast
);
2067 if (LineNumber
== (UINTN
)-1) {
2071 return EdbGetSourceStrFromCodeByLine (Entry
, LineNumber
, FuncEnd
);
2078 @param Address - Instruction address
2079 @param IsPrint - Whether need to print
2081 @retval 1 - find the source
2082 @retval 0 - not find the source
2091 UINTN SymbolAddress
;
2092 EFI_DEBUGGER_SYMBOL_OBJECT
*RetObject
;
2093 EFI_DEBUGGER_SYMBOL_ENTRY
*RetEntry
;
2098 CHAR8 Buffer
[EFI_DEBUG_MAX_PRINT_BUFFER
];
2102 // need we display symbol
2104 if (!mDebuggerPrivate
.DebuggerSymbolContext
.DisplaySymbol
) {
2109 // find the symbol address
2111 SymbolAddress
= EbdFindSymbolAddress (
2113 EdbMatchSymbolTypeLowerAddress
,
2117 if ((SymbolAddress
== 0) || (RetEntry
== NULL
)) {
2121 FuncOffset
= Address
- SymbolAddress
+ RetEntry
->FuncOffsetBase
;
2126 FuncStart
= EdbGetSourceStrFromCode (RetEntry
, FuncOffset
, (VOID
**)&FuncEnd
);
2127 if (FuncStart
== NULL
) {
2132 // check whether need to real print
2138 *(UINT8
*)FuncEnd
= 0;
2141 // seperate buffer by \n, so that \r can be added.
2143 FuncIndex
= FuncStart
;
2144 while (*FuncIndex
!= 0) {
2145 if (*FuncIndex
== '\n') {
2146 if ((FuncIndex
- FuncStart
) < (EFI_DEBUG_MAX_PRINT_BUFFER
- 3)) {
2147 BufferSize
= FuncIndex
- FuncStart
;
2149 BufferSize
= EFI_DEBUG_MAX_PRINT_BUFFER
- 3;
2152 if (BufferSize
!= 0) {
2153 CopyMem (Buffer
, FuncStart
, BufferSize
);
2156 Buffer
[BufferSize
] = 0;
2157 EDBPrint (L
"%a\n", Buffer
);
2158 FuncStart
= FuncIndex
+ 1;
2159 FuncIndex
= FuncStart
;
2168 *(UINT8
*)FuncEnd
= '\n';
2175 Get Mapfile and SymbolName from one symbol format: [MapFileName:]SymbolName.
2177 @param Symbol - whole Symbol name
2178 @param MapfileName - the mapfile name in the symbol
2179 @param SymbolName - the symbol name in the symbol
2183 GetMapfileAndSymbol (
2185 OUT CHAR16
**MapfileName
,
2186 OUT CHAR16
**SymbolName
2191 *MapfileName
= NULL
;
2192 *SymbolName
= Symbol
;
2194 for (Ch
= Symbol
; *Ch
!= 0; Ch
++) {
2199 *MapfileName
= Symbol
;
2201 *SymbolName
= Ch
+ 1;
2211 Convert a symbol to an address.
2213 @param Symbol - Symbol name
2214 @param Address - Symbol address
2216 @retval EFI_SUCCESS - symbol found and address returned.
2217 @retval EFI_NOT_FOUND - symbol not found
2218 @retval EFI_NO_MAPPING - duplicated symbol not found
2228 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
2230 EFI_DEBUGGER_SYMBOL_ENTRY
*Entry
;
2232 CHAR16
*MapfileName
;
2235 // Split one symbol to mapfile name and symbol name
2237 GetMapfileAndSymbol (Symbol
, &MapfileName
, &SymbolName
);
2241 // Go through each object
2243 Object
= mDebuggerPrivate
.DebuggerSymbolContext
.Object
;
2244 for (ObjectIndex
= 0; ObjectIndex
< mDebuggerPrivate
.DebuggerSymbolContext
.ObjectCount
; ObjectIndex
++) {
2246 // Check MapfileName
2248 if ((MapfileName
!= NULL
) && (StriCmp (Object
[ObjectIndex
].Name
, MapfileName
) != 0)) {
2253 // Go through each entry
2255 Entry
= Object
[ObjectIndex
].Entry
;
2256 for (EntryIndex
= 0; EntryIndex
< Object
[ObjectIndex
].EntryCount
; EntryIndex
++) {
2258 // Check SymbolName (case sensitive)
2260 if (StrCmpUnicodeAndAscii (SymbolName
, Entry
[EntryIndex
].Name
) == 0) {
2261 if ((*Address
!= 0) && (MapfileName
== NULL
)) {
2263 // Find the duplicated symbol
2265 EDBPrint (L
"Duplicated Symbol found!\n");
2266 return EFI_NO_MAPPING
;
2271 *Address
= (Entry
[EntryIndex
].Rva
+ Object
[ObjectIndex
].BaseAddress
);
2277 if (*Address
== 0) {
2281 return EFI_NOT_FOUND
;