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
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.
19 Load single symbol entry.
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
27 @retval EFI_SUCCESS - add single symbol entry successfully
31 EdbLoadSymbolSingleEntry (
32 IN EFI_DEBUGGER_SYMBOL_OBJECT
*Object
,
36 IN EFI_DEBUGGER_SYMBOL_TYPE Type
39 EFI_DEBUGGER_SYMBOL_ENTRY
*Entry
;
42 // Check Count VS MaxCount
44 if (Object
->EntryCount
>= Object
->MaxEntryCount
) {
46 // reallocate (for codebuffer too)
49 return EFI_OUT_OF_RESOURCES
;
52 Entry
= &Object
->Entry
[Object
->EntryCount
];
57 if (sizeof (UINTN
) == sizeof(UINT64
)) {
58 DEBUG ((DEBUG_ERROR
, " Symbol: %a, Address: 0x%016lx (%d)\n", Name
, (UINT64
)Address
, (UINTN
)Type
));
60 DEBUG ((DEBUG_ERROR
, " Symbol: %a, Address: 0x%08x (%d)\n", Name
, Address
, (UINTN
)Type
));
64 // Fill the entry - name, RVA, type
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);
70 Entry
->Rva
= Address
% EFI_DEBUGGER_DEFAULT_LINK_IMAGEBASE
;
85 EdbEbcMapParseStateUninitialized
,
86 EdbEbcMapParseStateSymbolStart
,
87 EdbEbcMapParseStateSeHandlerSymbol
,
88 EdbEbcMapParseStateFunctionSymbol
,
89 EdbEbcMapParseStateVarbssInitSymbol
,
90 EdbEbcMapParseStateCrtSymbol
,
91 EdbEbcMapParseStateVariableSymbol
,
92 EdbEbcMapParseStateStaticFunctionSymbol
,
93 EdbEbcMapParseStateMax
,
94 } EDB_EBC_MAP_PARSE_STATE
;
97 EdbEbcSymbolParseStateUninitialized
,
98 EdbEbcSymbolParseStateReadyForName
,
99 EdbEbcSymbolParseStateReadyForRVA
,
100 EdbEbcSymbolParseStateReadyForType
,
101 EdbEbcSymbolParseStateReadyForObject
,
102 EdbEbcSymbolParseStateMax
,
103 } EDB_EBC_SYMBOL_PARSE_STATE
;
107 The following code depends on the MAP file generated by IEC compiler (actually Microsoft linker).
109 Sample as follows: EbcTest.map
110 ===============================================================================
113 Timestamp is 45b02718 (Fri Jan 19 10:04:08 2007)
115 Preferred load address is 10000000
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
131 Address Publics by Value Rva+Base Lib:Object
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
149 entry point at 0001:00000220
153 0001:00000000 TestSubRoutine2 10000400 f EbcTest.obj
154 ===============================================================================
160 Load symbol entry by Iec.
162 @param Object - Symbol file object
163 @param BufferSize - Symbol file buffer size
164 @param Buffer - Symbol file buffer
166 @retval EFI_SUCCESS - add symbol entry successfully
170 EdbLoadSymbolEntryByIec (
171 IN EFI_DEBUGGER_SYMBOL_OBJECT
*Object
,
178 EDB_EBC_MAP_PARSE_STATE MapParseState
;
179 EDB_EBC_SYMBOL_PARSE_STATE SymbolParseState
;
183 EFI_DEBUGGER_SYMBOL_TYPE Type
;
187 // Begin to parse the Buffer
189 LineBuffer
= AsciiStrGetNewTokenLine (Buffer
, "\n\r");
190 MapParseState
= EdbEbcMapParseStateUninitialized
;
194 while (LineBuffer
!= NULL
) {
195 FieldBuffer
= AsciiStrGetNewTokenField (LineBuffer
, " ");
196 SymbolParseState
= EdbEbcSymbolParseStateUninitialized
;
203 Type
= EfiDebuggerSymbolTypeMax
;
207 while (FieldBuffer
!= NULL
) {
208 if (AsciiStrCmp (FieldBuffer
, "") == 0) {
209 FieldBuffer
= AsciiStrGetNextTokenField (" ");
215 if (AsciiStrCmp (FieldBuffer
, "Address") == 0) {
216 MapParseState
= EdbEbcMapParseStateSymbolStart
;
222 if (AsciiStrCmp (FieldBuffer
, "Static") == 0) {
223 MapParseState
= EdbEbcMapParseStateStaticFunctionSymbol
;
227 if (MapParseState
== EdbEbcMapParseStateUninitialized
) {
229 // Do not parse anything until get "Address" or "Static"
233 if (AsciiStrCmp (FieldBuffer
, "entry") == 0) {
241 // Now we start to parse this line for Name, Address, and Object
243 switch (SymbolParseState
) {
244 case EdbEbcSymbolParseStateUninitialized
:
248 SymbolParseState
= EdbEbcSymbolParseStateReadyForName
;
250 case EdbEbcSymbolParseStateReadyForName
:
254 if (AsciiStrnCmp (FieldBuffer
, "___safe_se_handler", AsciiStrLen ("___safe_se_handler")) == 0) {
258 MapParseState
= EdbEbcMapParseStateSeHandlerSymbol
;
260 } else if (AsciiStrnCmp (FieldBuffer
, "varbss_init", AsciiStrLen ("varbss_init")) == 0) {
264 MapParseState
= EdbEbcMapParseStateVarbssInitSymbol
;
265 // goto ExitFieldParse;
267 SymbolParseState
= EdbEbcSymbolParseStateReadyForRVA
;
268 } else if (AsciiStrnCmp (FieldBuffer
, "Crt", AsciiStrLen ("Crt")) == 0) {
272 MapParseState
= EdbEbcMapParseStateCrtSymbol
;
273 // goto ExitFieldParse;
275 SymbolParseState
= EdbEbcSymbolParseStateReadyForRVA
;
278 // Now, it is normal function
280 switch (MapParseState
) {
281 case EdbEbcMapParseStateSeHandlerSymbol
:
282 MapParseState
= EdbEbcMapParseStateFunctionSymbol
;
284 case EdbEbcMapParseStateCrtSymbol
:
285 MapParseState
= EdbEbcMapParseStateVariableSymbol
;
287 case EdbEbcMapParseStateFunctionSymbol
:
288 case EdbEbcMapParseStateVariableSymbol
:
289 case EdbEbcMapParseStateStaticFunctionSymbol
:
296 SymbolParseState
= EdbEbcSymbolParseStateReadyForRVA
;
299 case EdbEbcSymbolParseStateReadyForRVA
:
303 Address
= AsciiXtoi (FieldBuffer
);
304 SymbolParseState
= EdbEbcSymbolParseStateReadyForType
;
306 case EdbEbcSymbolParseStateReadyForType
:
308 // Get the Type. This is optional, only for "f".
310 if (AsciiStrCmp (FieldBuffer
, "f") == 0) {
311 SymbolParseState
= EdbEbcSymbolParseStateReadyForObject
;
312 switch (MapParseState
) {
313 case EdbEbcMapParseStateFunctionSymbol
:
314 case EdbEbcMapParseStateVarbssInitSymbol
:
315 Type
= EfiDebuggerSymbolFunction
;
317 case EdbEbcMapParseStateStaticFunctionSymbol
:
318 Type
= EfiDebuggerSymbolStaticFunction
;
327 // Else it should be Object.
328 // let it bypass here
330 case EdbEbcSymbolParseStateReadyForObject
:
332 case EfiDebuggerSymbolTypeMax
:
333 switch (MapParseState
) {
334 case EdbEbcMapParseStateVariableSymbol
:
335 case EdbEbcMapParseStateCrtSymbol
:
336 Type
= EfiDebuggerSymbolGlobalVariable
;
338 case EdbEbcMapParseStateSeHandlerSymbol
:
348 case EfiDebuggerSymbolFunction
:
349 case EfiDebuggerSymbolStaticFunction
:
358 ObjName
= FieldBuffer
;
359 SymbolParseState
= EdbEbcSymbolParseStateUninitialized
;
367 // Get the next field
369 FieldBuffer
= AsciiStrGetNextTokenField (" ");
373 // Add the entry if we get everything.
375 if ((Name
!= NULL
) && (Type
!= EfiDebuggerSymbolTypeMax
)) {
376 EdbLoadSymbolSingleEntry (Object
, Name
, ObjName
, Address
, Type
);
383 LineBuffer
= AsciiStrGetNextTokenLine ("\n\r");
396 @param Object - Symbol file object
397 @param BufferSize - Symbol file buffer size
398 @param Buffer - Symbol file buffer
400 @retval EFI_SUCCESS - add symbol entry successfully
405 IN EFI_DEBUGGER_SYMBOL_OBJECT
*Object
,
411 // MAP file format depends on the compiler (actually linker).
413 // It is possible to check the different MAP file format in this routine.
414 // Now only IEC is supported.
416 return EdbLoadSymbolEntryByIec (Object
, BufferSize
, Buffer
);
421 Find symbol file by name.
423 @param DebuggerPrivate - EBC Debugger private data structure
424 @param FileName - Symbol file name
425 @param Index - Symbol file index
430 EFI_DEBUGGER_SYMBOL_OBJECT
*
432 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
434 IN OUT UINTN
*Index OPTIONAL
442 for (ObjectIndex
= 0; ObjectIndex
< DebuggerPrivate
->DebuggerSymbolContext
.ObjectCount
; ObjectIndex
++) {
443 if (StrCmp (FileName
, DebuggerPrivate
->DebuggerSymbolContext
.Object
[ObjectIndex
].Name
) == 0) {
445 // Name match, found it
448 *Index
= ObjectIndex
;
450 return &DebuggerPrivate
->DebuggerSymbolContext
.Object
[ObjectIndex
];
462 Find symbol by address.
464 @param Address - Symbol address
465 @param Type - Search type
466 @param RetObject - Symbol object
467 @param RetEntry - Symbol entry
469 @return Nearest symbol address
473 EbdFindSymbolAddress (
475 IN EDB_MATCH_SYMBOL_TYPE Type
,
476 OUT EFI_DEBUGGER_SYMBOL_OBJECT
**RetObject
,
477 OUT EFI_DEBUGGER_SYMBOL_ENTRY
**RetEntry
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
;
491 if ((Type
< 0) || (Type
>= EdbMatchSymbolTypeMax
)) {
498 CandidateLowerAddress
= 0;
499 CandidateUpperAddress
= (UINTN
)-1;
506 // Go through each object
508 Object
= mDebuggerPrivate
.DebuggerSymbolContext
.Object
;
509 for (Index
= 0; Index
< mDebuggerPrivate
.DebuggerSymbolContext
.ObjectCount
; Index
++, Object
++) {
510 if (Object
->EntryCount
== 0) {
514 // Go through each entry
516 Entry
= Object
->Entry
;
517 for (SubIndex
= 0; SubIndex
< Object
->EntryCount
; SubIndex
++, Entry
++) {
518 if (Address
!= Entry
->Rva
+ Object
->BaseAddress
) {
520 // Check for nearest address
522 if (Address
> Entry
->Rva
+ Object
->BaseAddress
) {
524 // Record it if Current RVA < Address
526 if (CandidateLowerAddress
< Entry
->Rva
+ Object
->BaseAddress
) {
527 CandidateLowerAddress
= Entry
->Rva
+ Object
->BaseAddress
;
533 // Record it if Current RVA > Address
535 if (CandidateUpperAddress
> Entry
->Rva
+ Object
->BaseAddress
) {
536 CandidateUpperAddress
= Entry
->Rva
+ Object
->BaseAddress
;
538 UpperObject
= Object
;
544 // address match, return directly
553 // No Match, provide latest symbol
556 if ((Address
- CandidateLowerAddress
) < EFI_DEBUGGER_MAX_SYMBOL_ADDRESS_DELTA_VALUE
) {
558 // Check for lower address
560 if (((Type
== EdbMatchSymbolTypeNearestAddress
) &&
561 ((CandidateUpperAddress
- Address
) > (Address
- CandidateLowerAddress
))) ||
562 (Type
== EdbMatchSymbolTypeLowerAddress
)) {
564 // return nearest lower address
566 *RetEntry
= LowEntry
;
567 *RetObject
= LowObject
;
568 return CandidateLowerAddress
;
572 if ((CandidateUpperAddress
- Address
) < EFI_DEBUGGER_MAX_SYMBOL_ADDRESS_DELTA_VALUE
) {
574 // Check for upper address
576 if (((Type
== EdbMatchSymbolTypeNearestAddress
) &&
577 ((CandidateUpperAddress
- Address
) < (Address
- CandidateLowerAddress
))) ||
578 (Type
== EdbMatchSymbolTypeUpperAddress
)) {
580 // return nearest upper address
582 *RetEntry
= UpperEntry
;
583 *RetObject
= UpperObject
;
584 return CandidateUpperAddress
;
589 // No match and nearest one, return NULL
596 Unload symbol file by name.
598 @param DebuggerPrivate - EBC Debugger private data structure
599 @param FileName - Symbol file name
601 @retval EFI_SUCCESS - unload symbol successfully
606 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
610 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
613 EFI_DEBUGGER_SYMBOL_ENTRY
*OldEntry
;
616 VOID
**OldSourceBuffer
;
621 Object
= EdbFindSymbolFile (DebuggerPrivate
, FileName
, &ObjectIndex
);
622 if (Object
== NULL
) {
623 EDBPrint (L
"SymbolFile is not loaded!\n");
624 return EFI_DEBUG_CONTINUE
;
630 Object
= DebuggerPrivate
->DebuggerSymbolContext
.Object
;
631 OldEntry
= Object
->Entry
;
632 OldSourceBuffer
= Object
->SourceBuffer
;
633 MaxEntryCount
= Object
->MaxEntryCount
;
634 OldEntryCount
= Object
->EntryCount
;
637 // Remove the matched Object
639 for (Index
= ObjectIndex
; Index
< DebuggerPrivate
->DebuggerSymbolContext
.ObjectCount
- 1; Index
++) {
640 CopyMem (&Object
[Index
], &Object
[Index
+ 1], sizeof(EFI_DEBUGGER_SYMBOL_OBJECT
));
642 ZeroMem (&Object
[Index
], sizeof(Object
[Index
]));
645 // Move old data to new place
647 Object
[Index
].Entry
= OldEntry
;
648 Object
[Index
].SourceBuffer
= OldSourceBuffer
;
649 Object
[Index
].MaxEntryCount
= MaxEntryCount
;
650 DebuggerPrivate
->DebuggerSymbolContext
.ObjectCount
--;
653 // Clean old entry data
655 for (Index
= 0; Index
< OldEntryCount
; Index
++) {
656 ZeroMem (&OldEntry
[Index
], sizeof(OldEntry
[Index
]));
660 // Free OldSourceBuffer
662 for (Index
= 0; OldSourceBuffer
[Index
] != NULL
; Index
++) {
663 gBS
->FreePool (OldSourceBuffer
[Index
]);
664 OldSourceBuffer
[Index
] = NULL
;
672 Load symbol file by name.
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
679 @retval EFI_SUCCESS - load symbol successfully
684 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
690 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
694 // Check duplicated File
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"));
706 // Check Count VS MaxCount
708 if (DebuggerPrivate
->DebuggerSymbolContext
.ObjectCount
>= DebuggerPrivate
->DebuggerSymbolContext
.MaxObjectCount
) {
713 return EFI_OUT_OF_RESOURCES
;
716 Object
= &DebuggerPrivate
->DebuggerSymbolContext
.Object
[DebuggerPrivate
->DebuggerSymbolContext
.ObjectCount
];
721 Object
->EntryCount
= 0;
722 Object
->MaxEntryCount
= EFI_DEBUGGER_SYMBOL_ENTRY_MAX
;
727 DEBUG ((DEBUG_ERROR
, "Symbol File: %s\n", FileName
));
728 Status
= EdbLoadSymbolEntry (Object
, BufferSize
, Buffer
);
729 if (EFI_ERROR (Status
)) {
736 StrnCpyS (Object
->Name
, sizeof(Object
->Name
) / sizeof(CHAR16
),
737 FileName
, (sizeof(Object
->Name
) / sizeof(CHAR16
)) - 1);
738 Object
->BaseAddress
= 0;
741 // Increase the object count
743 DebuggerPrivate
->DebuggerSymbolContext
.ObjectCount
++;
750 Located PDB path name in PE image.
752 @param ImageBase - base of PE to search
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.
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
;
776 CodeViewEntryPointer
= NULL
;
783 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
786 NtHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*) ((UINT8
*) DosHdr
+ DosHdr
->e_lfanew
);
788 // Check Machine, filter for EBC
790 if (NtHdr
->Pe32
.FileHeader
.Machine
!= EFI_IMAGE_MACHINE_EBC
) {
792 // If not EBC, return NULL
798 // Get DirectoryEntry
799 // EBC spec says PE32+, but implementation uses PE32. So check dynamically here.
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
]);
810 if (DirectoryEntry
->VirtualAddress
== 0) {
814 // Go through DirectoryEntry
817 (DirCount
< DirectoryEntry
->Size
/ sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
)) && CodeViewEntryPointer
== NULL
;
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
) {
823 // Match DebugEntry, only CODEVIEW_SIGNATURE_NB10 and CODEVIEW_SIGNATURE_RSDS are supported.
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
);
830 case CODEVIEW_SIGNATURE_RSDS
:
831 PdbPath
= (CHAR8
*) CodeViewEntryPointer
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY
);
847 Check whether PDB file and MAP file have same name.
849 @param PdbFileName - PDB file name
850 @param MapFileName - MAP file name
852 @retval TRUE - PDB and MAP file name match
853 @retval FALSE - PDB and MAP file name not match
858 IN CHAR8
*PdbFileName
,
859 IN CHAR16
*MapFileName
864 CHAR8
*PurePdbFileName
;
870 PurePdbFileName
= PdbFileName
;
871 for (Index
= 0; PdbFileName
[Index
] != 0; Index
++) {
872 if (PdbFileName
[Index
] == '\\') {
873 PurePdbFileName
= &PdbFileName
[Index
+ 1];
876 PdbFileName
= PurePdbFileName
;
881 PdbNameSize
= AsciiStrLen (PdbFileName
);
882 MapNameSize
= StrLen (MapFileName
);
884 if (PdbNameSize
!= MapNameSize
) {
891 for (Index
= 0; Index
< MapNameSize
- 4; Index
++) {
892 if ((PdbFileName
[Index
] | 0x20) != (MapFileName
[Index
] | 0x20)) {
901 // BUGBUG: work-around start
904 EFI_DEBUG_IMAGE_INFO
*EfiDebugImageInfoTable
;
905 volatile UINT32 UpdateStatus
;
907 } EFI_DEBUG_IMAGE_INFO_TABLE_HEADER_OLD
;
909 EFI_DEBUG_IMAGE_INFO_TABLE_HEADER mDebugImageInfoTableHeader
;
912 For compatibility consideration, we handle 2 cases:
916 +------------------------+ +------------------------+
917 | EfiDebugImageInfoTable | | UpdateStatus |
918 +------------------------+ +------------------------+
919 | UpdateStatus | | TableSize |
920 +------------------------+ +------------------------+
921 | TableSize | | EfiDebugImageInfoTable |
922 +------------------------+ +------------------------+
926 +------------------------+ +------------------------+
927 | EfiDebugImageInfoTable | | UpdateStatus |
928 | | +------------------------+
930 +------------------------+ +------------------------+
931 | UpdateStatus | | EfiDebugImageInfoTable |
932 +------------------------+ | |
934 +------------------------+ +------------------------+
936 @param DebugImageInfoTableHeader Point to the EFI_DEBUG_IMAGE_INFO_TABLE_HEADER structure.
940 EdbFixDebugImageInfoTable (
941 IN OUT EFI_DEBUG_IMAGE_INFO_TABLE_HEADER
**DebugImageInfoTableHeader
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
;
948 if ((*DebugImageInfoTableHeader
)->UpdateStatus
> 3) {
949 *DebugImageInfoTableHeader
= &mDebugImageInfoTableHeader
;
953 if ((*DebugImageInfoTableHeader
)->TableSize
% (EFI_PAGE_SIZE
/ (sizeof (VOID
*))) != 0) {
954 *DebugImageInfoTableHeader
= &mDebugImageInfoTableHeader
;
961 // BUGBUG: work-around end
968 @param DebuggerPrivate - EBC Debugger private data structure
969 @param FileName - Symbol file name
970 @param SearchType - Search type for Object
972 @retval EFI_SUCCESS - Patch symbol RVA successfully
973 @retval EFI_NOT_FOUND - Symbol RVA base not found
978 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
980 IN EDB_EBC_IMAGE_RVA_SEARCH_TYPE SearchType
985 EFI_DEBUG_IMAGE_INFO
*ImageTable
;
988 VOID
*CandidateImageBase
;
989 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
991 if (SearchType
< 0 || SearchType
>= EdbEbcImageRvaSearchTypeMax
) {
992 return EFI_INVALID_PARAMETER
;
996 // Get the related object
998 Object
= EdbFindSymbolFile (DebuggerPrivate
, FileName
, NULL
);
999 if (Object
== NULL
) {
1000 return EFI_NOT_FOUND
;
1004 // Try again to get DebugImageInfoTable
1006 if (mDebuggerPrivate
.DebugImageInfoTableHeader
== NULL
) {
1007 Status
= EfiGetSystemConfigurationTable (
1008 &gEfiDebugImageInfoTableGuid
,
1009 (VOID
**) &mDebuggerPrivate
.DebugImageInfoTableHeader
1011 if (EFI_ERROR (Status
)) {
1012 EDBPrint (L
"DebugImageInfoTable not found!\n");
1016 DEBUG ((DEBUG_ERROR
, "DebugImageInfoTableHeader: %x\n", mDebuggerPrivate
.DebugImageInfoTableHeader
));
1019 // BUGBUG: work-around start
1021 EdbFixDebugImageInfoTable (&mDebuggerPrivate
.DebugImageInfoTableHeader
);
1023 // BUGBUG: work-around end
1027 // Go through DebugImageInfoTable for each Image
1029 CandidateImageBase
= NULL
;
1030 ImageTable
= mDebuggerPrivate
.DebugImageInfoTableHeader
->EfiDebugImageInfoTable
;
1031 for (ImageNumber
= 0; ImageNumber
< mDebuggerPrivate
.DebugImageInfoTableHeader
->TableSize
; ImageNumber
++) {
1032 if (ImageTable
[ImageNumber
].NormalImage
== NULL
) {
1035 ImageBase
= ImageTable
[ImageNumber
].NormalImage
->LoadedImageProtocolInstance
->ImageBase
;
1039 PdbPath
= GetPdbPath (ImageBase
);
1040 if (PdbPath
== NULL
) {
1046 if (!MatchPdbAndMap (PdbPath
, FileName
)) {
1049 DEBUG ((DEBUG_ERROR
, "ImageBase: %x\n", ImageBase
));
1054 if (SearchType
== EdbEbcImageRvaSearchTypeAny
|| SearchType
== EdbEbcImageRvaSearchTypeFirst
) {
1056 // Assign base address and return
1058 Object
->BaseAddress
= (UINTN
)ImageBase
;
1063 // Get CandidateImageBase for EdbEbcImageRvaSearchTypeLast
1065 CandidateImageBase
= ImageBase
;
1069 // Check EdbEbcImageRvaSearchTypeLast
1071 if (SearchType
== EdbEbcImageRvaSearchTypeLast
) {
1072 if (CandidateImageBase
== NULL
) {
1073 return EFI_NOT_FOUND
;
1076 // Assign base address and return
1078 Object
->BaseAddress
= (UINTN
)CandidateImageBase
;
1085 return EFI_NOT_FOUND
;
1090 Check whether OBJ file and COD file have same name.
1092 @param ObjFileName - OBJ file name
1093 @param CodFileName - COD file name
1095 @retval TRUE - OBJ and COD file name match
1096 @retval FALSE - OBJ and COD file name not match
1101 IN CHAR8
*ObjFileName
,
1102 IN CHAR16
*CodFileName
1107 CHAR8
*PureObjFileName
;
1111 // remove library name
1113 PureObjFileName
= ObjFileName
;
1114 for (Index
= 0; ObjFileName
[Index
] != 0; Index
++) {
1115 if (ObjFileName
[Index
] == ':') {
1116 PureObjFileName
= &ObjFileName
[Index
+ 1];
1120 ObjFileName
= PureObjFileName
;
1125 ObjNameSize
= AsciiStrLen (ObjFileName
);
1126 CodNameSize
= StrLen (CodFileName
);
1128 if (ObjNameSize
!= CodNameSize
) {
1135 for (Index
= 0; Index
< CodNameSize
- 4; Index
++) {
1136 if ((ObjFileName
[Index
] | 0x20) != (CodFileName
[Index
] | 0x20)) {
1145 EdbEbcCodParseStateUninitialized
,
1146 EdbEbcCodParseStateSymbolInitialized
,
1147 EdbEbcCodParseStateSymbolStart
,
1148 EdbEbcCodParseStateSymbolEnd
,
1149 EdbEbcCodParseStateMax
,
1150 } EDB_EBC_COD_PARSE_STATE
;
1154 The following code depends on the COD file generated by IEC compiler.
1160 Load code by symbol by Iec.
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
1172 EdbLoadCodBySymbolByIec (
1175 IN UINTN BufferSize
,
1176 OUT UINTN
*CodeBufferSize
,
1177 OUT UINTN
*FuncOffset
1185 EDB_EBC_COD_PARSE_STATE CodParseState
;
1193 LineBuffer
= AsciiStrGetNewTokenLine (Buffer
, "\n\r");
1197 CodParseState
= EdbEbcCodParseStateUninitialized
;
1202 while (LineBuffer
!= NULL
) {
1203 switch (CodParseState
) {
1204 case EdbEbcCodParseStateUninitialized
:
1206 // check mark_begin, begin to check line after this match
1208 if (AsciiStrCmp (LineBuffer
, "; mark_begin;") == 0) {
1209 CodParseState
= EdbEbcCodParseStateSymbolInitialized
;
1211 LineBuffer
= AsciiStrGetNextTokenLine ("\n\r");
1212 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1215 case EdbEbcCodParseStateSymbolInitialized
:
1217 // check mark_end, not check line after this match
1219 if (AsciiStrCmp (LineBuffer
, "; mark_end;") == 0) {
1220 CodParseState
= EdbEbcCodParseStateUninitialized
;
1221 LineBuffer
= AsciiStrGetNextTokenLine ("\n\r");
1222 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1227 // not check this line if the first char is as follows
1229 if ((*LineBuffer
== 0) ||
1230 (*LineBuffer
== '$') ||
1231 (*LineBuffer
== ';') ||
1232 (*LineBuffer
== '_') ||
1233 (*LineBuffer
== ' ')) {
1234 LineBuffer
= AsciiStrGetNextTokenLine ("\n\r");
1235 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1240 // get function name, function name is followed by char 0x09.
1242 FieldBuffer
= AsciiStrGetNewTokenField (LineBuffer
, Char
);
1243 ASSERT (FieldBuffer
!= NULL
);
1244 if (AsciiStriCmp (FieldBuffer
, Name
) == 0) {
1245 BufferStart
= FieldBuffer
;
1246 CodParseState
= EdbEbcCodParseStateSymbolStart
;
1248 PatchForAsciiStrTokenAfter (FieldBuffer
, 0x9);
1253 LineBuffer
= AsciiStrGetNextTokenLine ("\n\r");
1254 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1257 case EdbEbcCodParseStateSymbolStart
:
1259 // check mark_end, if this match, means the function is found successfully.
1261 if (AsciiStrCmp (LineBuffer
, "; mark_end;") == 0) {
1262 CodParseState
= EdbEbcCodParseStateSymbolEnd
;
1264 // prepare CodeBufferSize, FuncOffset, and FuncStart to return
1266 BufferEnd
= LineBuffer
+ sizeof("; mark_end;") - 1;
1267 *CodeBufferSize
= (UINTN
)BufferEnd
- (UINTN
)BufferStart
;
1268 *FuncOffset
= Offset
;
1269 PatchForAsciiStrTokenAfter (LineBuffer
, '\n');
1274 // Get function offset
1276 if ((Offset
== (UINTN
)-1) &&
1277 (*LineBuffer
== ' ')) {
1278 FieldBuffer
= AsciiStrGetNewTokenField (LineBuffer
+ 2, " ");
1279 Offset
= AsciiXtoi (FieldBuffer
);
1280 PatchForAsciiStrTokenAfter (FieldBuffer
, ' ');
1286 LineBuffer
= AsciiStrGetNextTokenLine ("\n\r");
1287 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1290 case EdbEbcCodParseStateSymbolEnd
:
1299 // no function found
1306 Load code by symbol.
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
1318 EdbLoadCodBySymbol (
1321 IN UINTN BufferSize
,
1322 OUT UINTN
*CodeBufferSize
,
1323 OUT UINTN
*FuncOffset
1327 // COD file format depends on the compiler.
1329 // It is possible to check the different COD file format in this routine.
1330 // Now only IEC is supported.
1332 return EdbLoadCodBySymbolByIec (Name
, Buffer
, BufferSize
, CodeBufferSize
, FuncOffset
);
1337 Find code from object.
1339 @param DebuggerPrivate EBC Debugger private data structure
1340 @param Object - Symbol object
1341 @param FileName - File name
1345 EdbFindCodeFromObject (
1346 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
1347 IN EFI_DEBUGGER_SYMBOL_OBJECT
*Object
,
1354 // Go througn each Entry in this Object
1356 for (EntryIndex
= 0; EntryIndex
< Object
->EntryCount
; EntryIndex
++) {
1358 // This check is for Function only
1360 if ((Object
->Entry
[EntryIndex
].Type
!= EfiDebuggerSymbolFunction
) &&
1361 (Object
->Entry
[EntryIndex
].Type
!= EfiDebuggerSymbolStaticFunction
)) {
1365 // Skip match varbss_init function, because they has no source code
1367 if (AsciiStrnCmp (Object
->Entry
[EntryIndex
].Name
, "varbss_init", sizeof("varbss_init") - 1) == 0) {
1373 if (!MatchObjAndCod (Object
->Entry
[EntryIndex
].ObjName
, FileName
)) {
1377 // found it, return source buffer
1379 if (Object
->Entry
[EntryIndex
].CodBuffer
!= NULL
) {
1380 return Object
->Entry
[EntryIndex
].SourceBuffer
;
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
1400 @retval EFI_SUCCESS - Code loaded successfully
1405 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
1406 IN CHAR16
*MapFileName
,
1407 IN CHAR16
*FileName
,
1408 IN UINTN BufferSize
,
1412 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
1421 Object
= EdbFindSymbolFile (DebuggerPrivate
, MapFileName
, &ObjectIndex
);
1422 if (Object
== NULL
) {
1423 EDBPrint (L
"SymbolFile is not loaded!\n");
1424 return EFI_NOT_FOUND
;
1427 // Check duplicated File
1429 SourceBuffer
= EdbFindCodeFromObject (DebuggerPrivate
, Object
, FileName
);
1430 if (SourceBuffer
!= NULL
) {
1432 // unnload duplicated code
1434 Status
= EdbUnloadCode (DebuggerPrivate
, MapFileName
, FileName
, &SourceBuffer
);
1435 if (EFI_ERROR(Status
)) {
1436 DEBUG ((DEBUG_ERROR
, "Unload Duplicated Code File Error!\n"));
1439 Status
= EdbDeleteCodeBuffer (DebuggerPrivate
, MapFileName
, FileName
, SourceBuffer
);
1440 if (EFI_ERROR(Status
)) {
1441 DEBUG ((DEBUG_ERROR
, "Delete Duplicated Code File Error!\n"));
1448 // Go through each SymbolEntry
1450 for (EntryIndex
= 0; EntryIndex
< Object
->EntryCount
; EntryIndex
++) {
1452 // load symbol for function only
1454 if ((Object
->Entry
[EntryIndex
].Type
!= EfiDebuggerSymbolFunction
) &&
1455 (Object
->Entry
[EntryIndex
].Type
!= EfiDebuggerSymbolStaticFunction
)) {
1461 if (AsciiStrnCmp (Object
->Entry
[EntryIndex
].Name
, "varbss_init", sizeof("varbss_init") - 1) == 0) {
1467 if (!MatchObjAndCod (Object
->Entry
[EntryIndex
].ObjName
, FileName
)) {
1471 // load code for this symbol
1473 Object
->Entry
[EntryIndex
].CodBuffer
= EdbLoadCodBySymbol (
1474 Object
->Entry
[EntryIndex
].Name
,
1477 &Object
->Entry
[EntryIndex
].CodBufferSize
,
1478 &Object
->Entry
[EntryIndex
].FuncOffsetBase
1480 if (Object
->Entry
[EntryIndex
].CodBuffer
!= NULL
) {
1481 Object
->Entry
[EntryIndex
].SourceBuffer
= Buffer
;
1486 // patch end '\0' for each code buffer
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));
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
1511 @retval EFI_SUCCESS - Code unloaded successfully
1516 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
1517 IN CHAR16
*MapFileName
,
1518 IN CHAR16
*FileName
,
1522 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
1529 Object
= EdbFindSymbolFile (DebuggerPrivate
, MapFileName
, &ObjectIndex
);
1530 if (Object
== NULL
) {
1531 EDBPrint (L
"SymbolFile is not loaded!\n");
1532 return EFI_NOT_FOUND
;
1538 *Buffer
= EdbFindCodeFromObject (DebuggerPrivate
, Object
, FileName
);
1539 if (*Buffer
== NULL
) {
1540 EDBPrint (L
"CodeFile is not loaded!\n");
1541 return EFI_NOT_FOUND
;
1545 // go through each entry
1547 for (EntryIndex
= 0; EntryIndex
< Object
->EntryCount
; EntryIndex
++) {
1548 if ((Object
->Entry
[EntryIndex
].Type
!= EfiDebuggerSymbolFunction
) &&
1549 (Object
->Entry
[EntryIndex
].Type
!= EfiDebuggerSymbolStaticFunction
)) {
1552 if (AsciiStrnCmp (Object
->Entry
[EntryIndex
].Name
, "varbss_init", sizeof("varbss_init") - 1) == 0) {
1555 if (!MatchObjAndCod (Object
->Entry
[EntryIndex
].ObjName
, FileName
)) {
1559 // clean up the buffer
1561 Object
->Entry
[EntryIndex
].CodBuffer
= NULL
;
1562 Object
->Entry
[EntryIndex
].CodBufferSize
= 0;
1563 Object
->Entry
[EntryIndex
].FuncOffsetBase
= 0;
1564 Object
->Entry
[EntryIndex
].SourceBuffer
= NULL
;
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
1583 @retval EFI_SUCCESS - CodeBuffer added successfully
1588 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
1589 IN CHAR16
*MapFileName
,
1590 IN CHAR16
*CodeFileName
,
1591 IN UINTN SourceBufferSize
,
1592 IN VOID
*SourceBuffer
1596 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
1601 Object
= EdbFindSymbolFile (DebuggerPrivate
, MapFileName
, NULL
);
1602 if (Object
== NULL
) {
1603 EDBPrint (L
"SymbolFile is not loaded!\n");
1604 return EFI_NOT_FOUND
;
1608 // Add it to last entry
1610 for (Index
= 0; Object
->SourceBuffer
[Index
] != NULL
; Index
++) {
1613 Object
->SourceBuffer
[Index
] = SourceBuffer
;
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
1627 @retval EFI_SUCCESS - CodeBuffer deleted successfully
1631 EdbDeleteCodeBuffer (
1632 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
1633 IN CHAR16
*MapFileName
,
1634 IN CHAR16
*CodeFileName
,
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
;
1650 for (Index
= 0; Object
->SourceBuffer
[Index
] != NULL
; Index
++) {
1652 // free the buffer if match
1654 if (Object
->SourceBuffer
[Index
] == SourceBuffer
) {
1655 gBS
->FreePool (SourceBuffer
);
1660 if (Object
->SourceBuffer
[Index
] == NULL
) {
1662 // not return NOT_FOUND
1670 Object
->SourceBuffer
[Index
] = NULL
;
1671 for (Index
= Index
+ 1; Object
->SourceBuffer
[Index
] != NULL
; Index
++) {
1672 Object
->SourceBuffer
[Index
- 1] = Object
->SourceBuffer
[Index
];
1674 Object
->SourceBuffer
[Index
- 1] = NULL
;
1681 Find the symbol string according to address.
1683 @param Address - Symbol address
1685 @return Symbol string
1694 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
1696 EFI_DEBUGGER_SYMBOL_ENTRY
*Entry
;
1699 // need we display symbol
1701 if (!mDebuggerPrivate
.DebuggerSymbolContext
.DisplaySymbol
) {
1706 // Go through each object and entry
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
++) {
1713 // if Address match, return Name
1715 if (Address
== (Entry
[EntryIndex
].Rva
+ Object
[ObjectIndex
].BaseAddress
)) {
1716 return Entry
[EntryIndex
].Name
;
1729 Get line number and offset from this line in code file.
1731 @param Line - Line buffer in code file
1732 @param Offset - Offset to functin entry
1738 EdbGetLineNumberAndOffsetFromThisLine (
1747 LineNumber
= (UINTN
)-1;
1749 *Offset
= (UINTN
)-1;
1751 while (LineBuffer
!= NULL
) {
1755 if (*LineBuffer
!= ' ') {
1762 if (*(LineBuffer
+ 2) != ' ') {
1763 if (*Offset
== (UINTN
)-1) {
1764 FieldBuffer
= AsciiStrGetNewTokenField (LineBuffer
+ 2, " ");
1765 *Offset
= AsciiXtoi (FieldBuffer
);
1766 PatchForAsciiStrTokenAfter (FieldBuffer
, ' ');
1771 // 1. assembly instruction
1773 FieldBuffer
= AsciiStrGetNewTokenField (LineBuffer
, ":");
1777 FieldBuffer
= AsciiStrGetNextTokenField (":");
1778 PatchForAsciiStrTokenBefore (FieldBuffer
, ':');
1779 if (FieldBuffer
== NULL
) {
1784 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
1785 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1791 FieldBuffer
= AsciiStrGetNextTokenField (":");
1792 PatchForAsciiStrTokenBefore (FieldBuffer
, ':');
1793 if (FieldBuffer
== NULL
) {
1797 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
1798 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1802 LineNumber
= AsciiAtoi (FieldBuffer
);
1814 EdbEbcLineSearchTypeAny
,
1815 EdbEbcLineSearchTypeFirst
,
1816 EdbEbcLineSearchTypeLast
,
1817 EdbEbcLineSearchTypeMax
,
1818 } EDB_EBC_LINE_SEARCH_TYPE
;
1822 Get line number from this code file.
1824 @param Entry - Symbol entry
1825 @param FuncOffset - Offset to functin entry
1826 @param SearchType - Search type for the code
1832 EdbGetLineNumberFromCode (
1833 IN EFI_DEBUGGER_SYMBOL_ENTRY
*Entry
,
1834 IN UINTN FuncOffset
,
1835 IN EDB_EBC_LINE_SEARCH_TYPE SearchType
1841 UINTN CandidateLineNumber
;
1842 UINTN CandidateOffset
;
1844 if (SearchType
< 0 || SearchType
>= EdbEbcLineSearchTypeMax
) {
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');
1862 LineNumber
= EdbGetLineNumberAndOffsetFromThisLine (LineBuffer
, &Offset
);
1867 if (Offset
!= FuncOffset
) {
1869 // Check last offset match
1871 if (CandidateOffset
== FuncOffset
) {
1872 if (SearchType
== EdbEbcLineSearchTypeLast
) {
1873 PatchForAsciiStrTokenAfter (LineBuffer
, '\n');
1874 if (CandidateLineNumber
!= LineNumber
) {
1875 return CandidateLineNumber
;
1886 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
1887 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1888 CandidateLineNumber
= LineNumber
;
1893 // Offset match, more check
1895 if (SearchType
== EdbEbcLineSearchTypeAny
) {
1896 PatchForAsciiStrTokenAfter (LineBuffer
, '\n');
1900 if (SearchType
== EdbEbcLineSearchTypeFirst
) {
1904 PatchForAsciiStrTokenAfter (LineBuffer
, '\n');
1905 if (CandidateLineNumber
!= LineNumber
) {
1912 CandidateLineNumber
= LineNumber
;
1913 CandidateOffset
= Offset
;
1915 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
1916 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1920 // Check last offset match
1922 if (CandidateOffset
== FuncOffset
) {
1923 if (SearchType
== EdbEbcLineSearchTypeLast
) {
1924 return CandidateLineNumber
;
1933 Get the source string from this code file by line.
1935 @param Entry - Symbol entry
1936 @param LineNumber - line number
1937 @param FuncEnd - Function end
1939 @return Funtion start
1943 EdbGetSourceStrFromCodeByLine (
1944 IN EFI_DEBUGGER_SYMBOL_ENTRY
*Entry
,
1945 IN UINTN LineNumber
,
1955 LineBuffer
= AsciiStrGetNewTokenLine (Entry
->CodBuffer
, "\n");
1956 while (LineBuffer
!= NULL
) {
1957 if (*LineBuffer
!= ';') {
1958 if (FuncStart
!= NULL
) {
1962 *FuncEnd
= LineBuffer
- 1;
1963 PatchForAsciiStrTokenAfter (LineBuffer
, '\n');
1966 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
1967 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1974 FieldBuffer
= AsciiStrGetNewTokenField (LineBuffer
+ 1, " ");
1975 Number
= AsciiAtoi (FieldBuffer
);
1976 PatchForAsciiStrTokenAfter (FieldBuffer
, ' ');
1977 if (Number
!= LineNumber
) {
1978 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
1979 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1984 // Line match, get line number
1986 if (FuncStart
== NULL
) {
1987 FuncStart
= LineBuffer
;
1990 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
1991 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1999 Get source string from this code file.
2001 @param Entry - Symbol entry
2002 @param FuncOffset - Offset to functin entry
2003 @param FuncEnd - Function end
2005 @retval Funtion start
2009 EdbGetSourceStrFromCode (
2010 IN EFI_DEBUGGER_SYMBOL_ENTRY
*Entry
,
2011 IN UINTN FuncOffset
,
2018 // Only search the last line, then display
2020 LineNumber
= EdbGetLineNumberFromCode (Entry
, FuncOffset
, EdbEbcLineSearchTypeLast
);
2021 if (LineNumber
== (UINTN
)-1) {
2025 return EdbGetSourceStrFromCodeByLine (Entry
, LineNumber
, FuncEnd
);
2032 @param Address - Instruction address
2033 @param IsPrint - Whether need to print
2035 @retval 1 - find the source
2036 @retval 0 - not find the source
2045 UINTN SymbolAddress
;
2046 EFI_DEBUGGER_SYMBOL_OBJECT
*RetObject
;
2047 EFI_DEBUGGER_SYMBOL_ENTRY
*RetEntry
;
2052 CHAR8 Buffer
[EFI_DEBUG_MAX_PRINT_BUFFER
];
2056 // need we display symbol
2058 if (!mDebuggerPrivate
.DebuggerSymbolContext
.DisplaySymbol
) {
2063 // find the symbol address
2065 SymbolAddress
= EbdFindSymbolAddress (
2067 EdbMatchSymbolTypeLowerAddress
,
2071 if (SymbolAddress
== 0) {
2075 FuncOffset
= Address
- SymbolAddress
+ RetEntry
->FuncOffsetBase
;
2080 FuncStart
= EdbGetSourceStrFromCode (RetEntry
, FuncOffset
, (VOID
**) &FuncEnd
);
2081 if (FuncStart
== NULL
) {
2086 // check whether need to real print
2092 *(UINT8
*)FuncEnd
= 0;
2095 // seperate buffer by \n, so that \r can be added.
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
;
2103 BufferSize
= EFI_DEBUG_MAX_PRINT_BUFFER
- 3;
2105 if (BufferSize
!= 0) {
2106 CopyMem (Buffer
, FuncStart
, BufferSize
);
2108 Buffer
[BufferSize
] = 0;
2109 EDBPrint (L
"%a\n", Buffer
);
2110 FuncStart
= FuncIndex
+ 1;
2111 FuncIndex
= FuncStart
;
2120 *(UINT8
*)FuncEnd
= '\n';
2127 Get Mapfile and SymbolName from one symbol format: [MapFileName:]SymbolName.
2129 @param Symbol - whole Symbol name
2130 @param MapfileName - the mapfile name in the symbol
2131 @param SymbolName - the symbol name in the symbol
2135 GetMapfileAndSymbol (
2137 OUT CHAR16
**MapfileName
,
2138 OUT CHAR16
**SymbolName
2143 *MapfileName
= NULL
;
2144 *SymbolName
= Symbol
;
2146 for (Ch
= Symbol
; *Ch
!= 0; Ch
++) {
2151 *MapfileName
= Symbol
;
2153 *SymbolName
= Ch
+ 1;
2163 Convert a symbol to an address.
2165 @param Symbol - Symbol name
2166 @param Address - Symbol address
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
2180 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
2182 EFI_DEBUGGER_SYMBOL_ENTRY
*Entry
;
2184 CHAR16
*MapfileName
;
2187 // Split one symbol to mapfile name and symbol name
2189 GetMapfileAndSymbol (Symbol
, &MapfileName
, &SymbolName
);
2193 // Go through each object
2195 Object
= mDebuggerPrivate
.DebuggerSymbolContext
.Object
;
2196 for (ObjectIndex
= 0; ObjectIndex
< mDebuggerPrivate
.DebuggerSymbolContext
.ObjectCount
; ObjectIndex
++) {
2198 // Check MapfileName
2200 if ((MapfileName
!= NULL
) && (StriCmp (Object
[ObjectIndex
].Name
, MapfileName
) != 0)) {
2204 // Go through each entry
2206 Entry
= Object
[ObjectIndex
].Entry
;
2207 for (EntryIndex
= 0; EntryIndex
< Object
[ObjectIndex
].EntryCount
; EntryIndex
++) {
2209 // Check SymbolName (case sensitive)
2211 if (StrCmpUnicodeAndAscii (SymbolName
, Entry
[EntryIndex
].Name
) == 0) {
2212 if ((*Address
!= 0) && (MapfileName
== NULL
)) {
2214 // Find the duplicated symbol
2216 EDBPrint (L
"Duplicated Symbol found!\n");
2217 return EFI_NO_MAPPING
;
2222 *Address
= (Entry
[EntryIndex
].Rva
+ Object
[ObjectIndex
].BaseAddress
);
2228 if (*Address
== 0) {
2232 return EFI_NOT_FOUND
;