3 Copyright (c) 2007 - 2016, Intel Corporatio. 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
;
1186 CHAR8 Char
[2] = {9, 0};
1191 LineBuffer
= AsciiStrGetNewTokenLine (Buffer
, "\n\r");
1195 CodParseState
= EdbEbcCodParseStateUninitialized
;
1200 while (LineBuffer
!= NULL
) {
1201 switch (CodParseState
) {
1202 case EdbEbcCodParseStateUninitialized
:
1204 // check mark_begin, begin to check line after this match
1206 if (AsciiStrCmp (LineBuffer
, "; mark_begin;") == 0) {
1207 CodParseState
= EdbEbcCodParseStateSymbolInitialized
;
1209 LineBuffer
= AsciiStrGetNextTokenLine ("\n\r");
1210 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1213 case EdbEbcCodParseStateSymbolInitialized
:
1215 // check mark_end, not check line after this match
1217 if (AsciiStrCmp (LineBuffer
, "; mark_end;") == 0) {
1218 CodParseState
= EdbEbcCodParseStateUninitialized
;
1219 LineBuffer
= AsciiStrGetNextTokenLine ("\n\r");
1220 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1225 // not check this line if the first char is as follows
1227 if ((*LineBuffer
== 0) ||
1228 (*LineBuffer
== '$') ||
1229 (*LineBuffer
== ';') ||
1230 (*LineBuffer
== '_') ||
1231 (*LineBuffer
== ' ')) {
1232 LineBuffer
= AsciiStrGetNextTokenLine ("\n\r");
1233 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1238 // get function name, function name is followed by char 0x09.
1240 FieldBuffer
= AsciiStrGetNewTokenField (LineBuffer
, Char
);
1241 ASSERT (FieldBuffer
!= NULL
);
1242 if (AsciiStriCmp (FieldBuffer
, Name
) == 0) {
1243 BufferStart
= FieldBuffer
;
1244 CodParseState
= EdbEbcCodParseStateSymbolStart
;
1246 PatchForAsciiStrTokenAfter (FieldBuffer
, 0x9);
1251 LineBuffer
= AsciiStrGetNextTokenLine ("\n\r");
1252 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1255 case EdbEbcCodParseStateSymbolStart
:
1257 // check mark_end, if this match, means the function is found successfully.
1259 if (AsciiStrCmp (LineBuffer
, "; mark_end;") == 0) {
1260 CodParseState
= EdbEbcCodParseStateSymbolEnd
;
1262 // prepare CodeBufferSize, FuncOffset, and FuncStart to return
1264 BufferEnd
= LineBuffer
+ sizeof("; mark_end;") - 1;
1265 *CodeBufferSize
= (UINTN
)BufferEnd
- (UINTN
)BufferStart
;
1266 *FuncOffset
= Offset
;
1267 PatchForAsciiStrTokenAfter (LineBuffer
, '\n');
1272 // Get function offset
1274 if ((Offset
== (UINTN
)-1) &&
1275 (*LineBuffer
== ' ')) {
1276 FieldBuffer
= AsciiStrGetNewTokenField (LineBuffer
+ 2, " ");
1277 Offset
= AsciiXtoi (FieldBuffer
);
1278 PatchForAsciiStrTokenAfter (FieldBuffer
, ' ');
1284 LineBuffer
= AsciiStrGetNextTokenLine ("\n\r");
1285 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1288 case EdbEbcCodParseStateSymbolEnd
:
1297 // no function found
1304 Load code by symbol.
1306 @param Name - Symbol file name
1307 @param Buffer - Symbol file buffer
1308 @param BufferSize - Symbol file buffer size
1309 @param CodeBufferSize - Code buffer size
1310 @param FuncOffset - Code funcion offset
1316 EdbLoadCodBySymbol (
1319 IN UINTN BufferSize
,
1320 OUT UINTN
*CodeBufferSize
,
1321 OUT UINTN
*FuncOffset
1325 // COD file format depends on the compiler.
1327 // It is possible to check the different COD file format in this routine.
1328 // Now only IEC is supported.
1330 return EdbLoadCodBySymbolByIec (Name
, Buffer
, BufferSize
, CodeBufferSize
, FuncOffset
);
1335 Find code from object.
1337 @param DebuggerPrivate EBC Debugger private data structure
1338 @param Object - Symbol object
1339 @param FileName - File name
1343 EdbFindCodeFromObject (
1344 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
1345 IN EFI_DEBUGGER_SYMBOL_OBJECT
*Object
,
1352 // Go througn each Entry in this Object
1354 for (EntryIndex
= 0; EntryIndex
< Object
->EntryCount
; EntryIndex
++) {
1356 // This check is for Function only
1358 if ((Object
->Entry
[EntryIndex
].Type
!= EfiDebuggerSymbolFunction
) &&
1359 (Object
->Entry
[EntryIndex
].Type
!= EfiDebuggerSymbolStaticFunction
)) {
1363 // Skip match varbss_init function, because they has no source code
1365 if (AsciiStrnCmp (Object
->Entry
[EntryIndex
].Name
, "varbss_init", sizeof("varbss_init") - 1) == 0) {
1371 if (!MatchObjAndCod (Object
->Entry
[EntryIndex
].ObjName
, FileName
)) {
1375 // found it, return source buffer
1377 if (Object
->Entry
[EntryIndex
].CodBuffer
!= NULL
) {
1378 return Object
->Entry
[EntryIndex
].SourceBuffer
;
1392 @param DebuggerPrivate - EBC Debugger private data structure
1393 @param MapFileName - Symbol file name
1394 @param FileName - Code file name
1395 @param BufferSize - Code file buffer size
1396 @param Buffer - Code file buffer
1398 @retval EFI_SUCCESS - Code loaded successfully
1403 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
1404 IN CHAR16
*MapFileName
,
1405 IN CHAR16
*FileName
,
1406 IN UINTN BufferSize
,
1410 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
1419 Object
= EdbFindSymbolFile (DebuggerPrivate
, MapFileName
, &ObjectIndex
);
1420 if (Object
== NULL
) {
1421 EDBPrint (L
"SymbolFile is not loaded!\n");
1422 return EFI_NOT_FOUND
;
1425 // Check duplicated File
1427 SourceBuffer
= EdbFindCodeFromObject (DebuggerPrivate
, Object
, FileName
);
1428 if (SourceBuffer
!= NULL
) {
1430 // unnload duplicated code
1432 Status
= EdbUnloadCode (DebuggerPrivate
, MapFileName
, FileName
, &SourceBuffer
);
1433 if (EFI_ERROR(Status
)) {
1434 DEBUG ((DEBUG_ERROR
, "Unload Duplicated Code File Error!\n"));
1437 Status
= EdbDeleteCodeBuffer (DebuggerPrivate
, MapFileName
, FileName
, SourceBuffer
);
1438 if (EFI_ERROR(Status
)) {
1439 DEBUG ((DEBUG_ERROR
, "Delete Duplicated Code File Error!\n"));
1446 // Go through each SymbolEntry
1448 for (EntryIndex
= 0; EntryIndex
< Object
->EntryCount
; EntryIndex
++) {
1450 // load symbol for function only
1452 if ((Object
->Entry
[EntryIndex
].Type
!= EfiDebuggerSymbolFunction
) &&
1453 (Object
->Entry
[EntryIndex
].Type
!= EfiDebuggerSymbolStaticFunction
)) {
1459 if (AsciiStrnCmp (Object
->Entry
[EntryIndex
].Name
, "varbss_init", sizeof("varbss_init") - 1) == 0) {
1465 if (!MatchObjAndCod (Object
->Entry
[EntryIndex
].ObjName
, FileName
)) {
1469 // load code for this symbol
1471 Object
->Entry
[EntryIndex
].CodBuffer
= EdbLoadCodBySymbol (
1472 Object
->Entry
[EntryIndex
].Name
,
1475 &Object
->Entry
[EntryIndex
].CodBufferSize
,
1476 &Object
->Entry
[EntryIndex
].FuncOffsetBase
1478 if (Object
->Entry
[EntryIndex
].CodBuffer
!= NULL
) {
1479 Object
->Entry
[EntryIndex
].SourceBuffer
= Buffer
;
1484 // patch end '\0' for each code buffer
1486 for (EntryIndex
= 0; EntryIndex
< Object
->EntryCount
; EntryIndex
++) {
1487 if (Object
->Entry
[EntryIndex
].CodBuffer
!= NULL
) {
1488 *((UINT8
*)Object
->Entry
[EntryIndex
].CodBuffer
+ Object
->Entry
[EntryIndex
].CodBufferSize
) = 0;
1489 DEBUG ((DEBUG_ERROR
, " CodeSymbol: %a, FuncOffset: 0x05%x\n", Object
->Entry
[EntryIndex
].Name
, Object
->Entry
[EntryIndex
].FuncOffsetBase
));
1490 // DEBUG ((DEBUG_ERROR, " [CODE]:\n%a\n", Object->Entry[EntryIndex].CodBuffer));
1504 @param DebuggerPrivate - EBC Debugger private data structure
1505 @param MapFileName - Symbol file name
1506 @param FileName - Code file name
1507 @param Buffer - Code file buffer
1509 @retval EFI_SUCCESS - Code unloaded successfully
1514 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
1515 IN CHAR16
*MapFileName
,
1516 IN CHAR16
*FileName
,
1520 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
1527 Object
= EdbFindSymbolFile (DebuggerPrivate
, MapFileName
, &ObjectIndex
);
1528 if (Object
== NULL
) {
1529 EDBPrint (L
"SymbolFile is not loaded!\n");
1530 return EFI_NOT_FOUND
;
1536 *Buffer
= EdbFindCodeFromObject (DebuggerPrivate
, Object
, FileName
);
1537 if (*Buffer
== NULL
) {
1538 EDBPrint (L
"CodeFile is not loaded!\n");
1539 return EFI_NOT_FOUND
;
1543 // go through each entry
1545 for (EntryIndex
= 0; EntryIndex
< Object
->EntryCount
; EntryIndex
++) {
1546 if ((Object
->Entry
[EntryIndex
].Type
!= EfiDebuggerSymbolFunction
) &&
1547 (Object
->Entry
[EntryIndex
].Type
!= EfiDebuggerSymbolStaticFunction
)) {
1550 if (AsciiStrnCmp (Object
->Entry
[EntryIndex
].Name
, "varbss_init", sizeof("varbss_init") - 1) == 0) {
1553 if (!MatchObjAndCod (Object
->Entry
[EntryIndex
].ObjName
, FileName
)) {
1557 // clean up the buffer
1559 Object
->Entry
[EntryIndex
].CodBuffer
= NULL
;
1560 Object
->Entry
[EntryIndex
].CodBufferSize
= 0;
1561 Object
->Entry
[EntryIndex
].FuncOffsetBase
= 0;
1562 Object
->Entry
[EntryIndex
].SourceBuffer
= NULL
;
1575 @param DebuggerPrivate - EBC Debugger private data structure
1576 @param MapFileName - Symbol file name
1577 @param CodeFileName - Code file name
1578 @param SourceBufferSize- Code buffer size
1579 @param SourceBuffer - Code buffer
1581 @retval EFI_SUCCESS - CodeBuffer added successfully
1586 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
1587 IN CHAR16
*MapFileName
,
1588 IN CHAR16
*CodeFileName
,
1589 IN UINTN SourceBufferSize
,
1590 IN VOID
*SourceBuffer
1594 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
1599 Object
= EdbFindSymbolFile (DebuggerPrivate
, MapFileName
, NULL
);
1600 if (Object
== NULL
) {
1601 EDBPrint (L
"SymbolFile is not loaded!\n");
1602 return EFI_NOT_FOUND
;
1606 // Add it to last entry
1608 for (Index
= 0; Object
->SourceBuffer
[Index
] != NULL
; Index
++) {
1611 Object
->SourceBuffer
[Index
] = SourceBuffer
;
1620 @param DebuggerPrivate - EBC Debugger private data structure
1621 @param MapFileName - Symbol file name
1622 @param CodeFileName - Code file name
1623 @param SourceBuffer - Code buffer
1625 @retval EFI_SUCCESS - CodeBuffer deleted successfully
1629 EdbDeleteCodeBuffer (
1630 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
1631 IN CHAR16
*MapFileName
,
1632 IN CHAR16
*CodeFileName
,
1633 IN VOID
*SourceBuffer
1637 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
1642 Object
= EdbFindSymbolFile (DebuggerPrivate
, MapFileName
, NULL
);
1643 if (Object
== NULL
) {
1644 EDBPrint (L
"SymbolFile is not loaded!\n");
1645 return EFI_NOT_FOUND
;
1648 for (Index
= 0; Object
->SourceBuffer
[Index
] != NULL
; Index
++) {
1650 // free the buffer if match
1652 if (Object
->SourceBuffer
[Index
] == SourceBuffer
) {
1653 gBS
->FreePool (SourceBuffer
);
1658 if (Object
->SourceBuffer
[Index
] == NULL
) {
1660 // not return NOT_FOUND
1668 Object
->SourceBuffer
[Index
] = NULL
;
1669 for (Index
= Index
+ 1; Object
->SourceBuffer
[Index
] != NULL
; Index
++) {
1670 Object
->SourceBuffer
[Index
- 1] = Object
->SourceBuffer
[Index
];
1672 Object
->SourceBuffer
[Index
- 1] = NULL
;
1679 Find the symbol string according to address.
1681 @param Address - Symbol address
1683 @return Symbol string
1692 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
1694 EFI_DEBUGGER_SYMBOL_ENTRY
*Entry
;
1697 // need we display symbol
1699 if (!mDebuggerPrivate
.DebuggerSymbolContext
.DisplaySymbol
) {
1704 // Go through each object and entry
1706 Object
= mDebuggerPrivate
.DebuggerSymbolContext
.Object
;
1707 for (ObjectIndex
= 0; ObjectIndex
< mDebuggerPrivate
.DebuggerSymbolContext
.ObjectCount
; ObjectIndex
++) {
1708 Entry
= Object
[ObjectIndex
].Entry
;
1709 for (EntryIndex
= 0; EntryIndex
< Object
[ObjectIndex
].EntryCount
; EntryIndex
++) {
1711 // if Address match, return Name
1713 if (Address
== (Entry
[EntryIndex
].RVA
+ Object
[ObjectIndex
].BaseAddress
)) {
1714 return Entry
[EntryIndex
].Name
;
1727 Get line number and offset from this line in code file.
1729 @param Line - Line buffer in code file
1730 @param Offset - Offset to functin entry
1736 EdbGetLineNumberAndOffsetFromThisLine (
1745 LineNumber
= (UINTN
)-1;
1747 *Offset
= (UINTN
)-1;
1749 while (LineBuffer
!= NULL
) {
1753 if (*LineBuffer
!= ' ') {
1760 if (*(LineBuffer
+ 2) != ' ') {
1761 if (*Offset
== (UINTN
)-1) {
1762 FieldBuffer
= AsciiStrGetNewTokenField (LineBuffer
+ 2, " ");
1763 *Offset
= AsciiXtoi (FieldBuffer
);
1764 PatchForAsciiStrTokenAfter (FieldBuffer
, ' ');
1769 // 1. assembly instruction
1771 FieldBuffer
= AsciiStrGetNewTokenField (LineBuffer
, ":");
1775 FieldBuffer
= AsciiStrGetNextTokenField (":");
1776 PatchForAsciiStrTokenBefore (FieldBuffer
, ':');
1777 if (FieldBuffer
== NULL
) {
1782 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
1783 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1789 FieldBuffer
= AsciiStrGetNextTokenField (":");
1790 PatchForAsciiStrTokenBefore (FieldBuffer
, ':');
1791 if (FieldBuffer
== NULL
) {
1795 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
1796 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1800 LineNumber
= AsciiAtoi (FieldBuffer
);
1812 EdbEbcLineSearchTypeAny
,
1813 EdbEbcLineSearchTypeFirst
,
1814 EdbEbcLineSearchTypeLast
,
1815 EdbEbcLineSearchTypeMax
,
1816 } EDB_EBC_LINE_SEARCH_TYPE
;
1820 Get line number from this code file.
1822 @param Entry - Symbol entry
1823 @param FuncOffset - Offset to functin entry
1824 @param SearchType - Search type for the code
1830 EdbGetLineNumberFromCode (
1831 IN EFI_DEBUGGER_SYMBOL_ENTRY
*Entry
,
1832 IN UINTN FuncOffset
,
1833 IN EDB_EBC_LINE_SEARCH_TYPE SearchType
1839 UINTN CandidateLineNumber
;
1840 UINTN CandidateOffset
;
1842 if (SearchType
< 0 || SearchType
>= EdbEbcLineSearchTypeMax
) {
1846 LineNumber
= (UINTN
)-1;
1847 CandidateLineNumber
= (UINTN
)-1;
1848 CandidateOffset
= (UINTN
)-1;
1849 LineBuffer
= AsciiStrGetNewTokenLine (Entry
->CodBuffer
, "\n");
1850 while (LineBuffer
!= NULL
) {
1851 if (*LineBuffer
!= ' ') {
1852 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
1853 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1860 LineNumber
= EdbGetLineNumberAndOffsetFromThisLine (LineBuffer
, &Offset
);
1865 if (Offset
!= FuncOffset
) {
1867 // Check last offset match
1869 if (CandidateOffset
== FuncOffset
) {
1870 if (SearchType
== EdbEbcLineSearchTypeLast
) {
1871 PatchForAsciiStrTokenAfter (LineBuffer
, '\n');
1872 if (CandidateLineNumber
!= LineNumber
) {
1873 return CandidateLineNumber
;
1884 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
1885 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1886 CandidateLineNumber
= LineNumber
;
1891 // Offset match, more check
1893 if (SearchType
== EdbEbcLineSearchTypeAny
) {
1894 PatchForAsciiStrTokenAfter (LineBuffer
, '\n');
1898 if (SearchType
== EdbEbcLineSearchTypeFirst
) {
1902 PatchForAsciiStrTokenAfter (LineBuffer
, '\n');
1903 if (CandidateLineNumber
!= LineNumber
) {
1910 CandidateLineNumber
= LineNumber
;
1911 CandidateOffset
= Offset
;
1913 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
1914 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1918 // Check last offset match
1920 if (CandidateOffset
== FuncOffset
) {
1921 if (SearchType
== EdbEbcLineSearchTypeLast
) {
1922 return CandidateLineNumber
;
1931 Get the source string from this code file by line.
1933 @param Entry - Symbol entry
1934 @param LineNumber - line number
1935 @param FuncEnd - Function end
1937 @return Funtion start
1941 EdbGetSourceStrFromCodeByLine (
1942 IN EFI_DEBUGGER_SYMBOL_ENTRY
*Entry
,
1943 IN UINTN LineNumber
,
1953 LineBuffer
= AsciiStrGetNewTokenLine (Entry
->CodBuffer
, "\n");
1954 while (LineBuffer
!= NULL
) {
1955 if (*LineBuffer
!= ';') {
1956 if (FuncStart
!= NULL
) {
1960 *FuncEnd
= LineBuffer
- 1;
1961 PatchForAsciiStrTokenAfter (LineBuffer
, '\n');
1964 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
1965 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1972 FieldBuffer
= AsciiStrGetNewTokenField (LineBuffer
+ 1, " ");
1973 Number
= AsciiAtoi (FieldBuffer
);
1974 PatchForAsciiStrTokenAfter (FieldBuffer
, ' ');
1975 if (Number
!= LineNumber
) {
1976 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
1977 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1982 // Line match, get line number
1984 if (FuncStart
== NULL
) {
1985 FuncStart
= LineBuffer
;
1988 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
1989 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1997 Get source string from this code file.
1999 @param Entry - Symbol entry
2000 @param FuncOffset - Offset to functin entry
2001 @param FuncEnd - Function end
2003 @retval Funtion start
2007 EdbGetSourceStrFromCode (
2008 IN EFI_DEBUGGER_SYMBOL_ENTRY
*Entry
,
2009 IN UINTN FuncOffset
,
2016 // Only search the last line, then display
2018 LineNumber
= EdbGetLineNumberFromCode (Entry
, FuncOffset
, EdbEbcLineSearchTypeLast
);
2019 if (LineNumber
== (UINTN
)-1) {
2023 return EdbGetSourceStrFromCodeByLine (Entry
, LineNumber
, FuncEnd
);
2030 @param Address - Instruction address
2031 @param IsPrint - Whether need to print
2033 @retval 1 - find the source
2034 @retval 0 - not find the source
2043 UINTN SymbolAddress
;
2044 EFI_DEBUGGER_SYMBOL_OBJECT
*RetObject
;
2045 EFI_DEBUGGER_SYMBOL_ENTRY
*RetEntry
;
2050 CHAR8 Buffer
[EFI_DEBUG_MAX_PRINT_BUFFER
];
2054 // need we display symbol
2056 if (!mDebuggerPrivate
.DebuggerSymbolContext
.DisplaySymbol
) {
2061 // find the symbol address
2063 SymbolAddress
= EbdFindSymbolAddress (
2065 EdbMatchSymbolTypeLowerAddress
,
2069 if (SymbolAddress
== 0) {
2073 FuncOffset
= Address
- SymbolAddress
+ RetEntry
->FuncOffsetBase
;
2078 FuncStart
= EdbGetSourceStrFromCode (RetEntry
, FuncOffset
, (VOID
**) &FuncEnd
);
2079 if (FuncStart
== NULL
) {
2084 // check whether need to real print
2090 *(UINT8
*)FuncEnd
= 0;
2093 // seperate buffer by \n, so that \r can be added.
2095 FuncIndex
= FuncStart
;
2096 while (*FuncIndex
!= 0) {
2097 if (*FuncIndex
== '\n') {
2098 if ((FuncIndex
- FuncStart
) < (EFI_DEBUG_MAX_PRINT_BUFFER
- 3)) {
2099 BufferSize
= FuncIndex
- FuncStart
;
2101 BufferSize
= EFI_DEBUG_MAX_PRINT_BUFFER
- 3;
2103 if (BufferSize
!= 0) {
2104 CopyMem (Buffer
, FuncStart
, BufferSize
);
2106 Buffer
[BufferSize
] = 0;
2107 EDBPrint (L
"%a\n", Buffer
);
2108 FuncStart
= FuncIndex
+ 1;
2109 FuncIndex
= FuncStart
;
2118 *(UINT8
*)FuncEnd
= '\n';
2125 Get Mapfile and SymbolName from one symbol format: [MapFileName:]SymbolName.
2127 @param Symbol - whole Symbol name
2128 @param MapfileName - the mapfile name in the symbol
2129 @param SymbolName - the symbol name in the symbol
2133 GetMapfileAndSymbol (
2135 OUT CHAR16
**MapfileName
,
2136 OUT CHAR16
**SymbolName
2141 *MapfileName
= NULL
;
2142 *SymbolName
= Symbol
;
2144 for (Ch
= Symbol
; *Ch
!= 0; Ch
++) {
2149 *MapfileName
= Symbol
;
2151 *SymbolName
= Ch
+ 1;
2161 Convert a symbol to an address.
2163 @param Symbol - Symbol name
2164 @param Address - Symbol address
2166 @retval EFI_SUCCESS - symbol found and address returned.
2167 @retval EFI_NOT_FOUND - symbol not found
2168 @retval EFI_NO_MAPPING - duplicated symbol not found
2178 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
2180 EFI_DEBUGGER_SYMBOL_ENTRY
*Entry
;
2182 CHAR16
*MapfileName
;
2185 // Split one symbol to mapfile name and symbol name
2187 GetMapfileAndSymbol (Symbol
, &MapfileName
, &SymbolName
);
2191 // Go through each object
2193 Object
= mDebuggerPrivate
.DebuggerSymbolContext
.Object
;
2194 for (ObjectIndex
= 0; ObjectIndex
< mDebuggerPrivate
.DebuggerSymbolContext
.ObjectCount
; ObjectIndex
++) {
2196 // Check MapfileName
2198 if ((MapfileName
!= NULL
) && (StriCmp (Object
[ObjectIndex
].Name
, MapfileName
) != 0)) {
2202 // Go through each entry
2204 Entry
= Object
[ObjectIndex
].Entry
;
2205 for (EntryIndex
= 0; EntryIndex
< Object
[ObjectIndex
].EntryCount
; EntryIndex
++) {
2207 // Check SymbolName (case sensitive)
2209 if (StrCmpUnicodeAndAscii (SymbolName
, Entry
[EntryIndex
].Name
) == 0) {
2210 if ((*Address
!= 0) && (MapfileName
== NULL
)) {
2212 // Find the duplicated symbol
2214 EDBPrint (L
"Duplicated Symbol found!\n");
2215 return EFI_NO_MAPPING
;
2220 *Address
= (Entry
[EntryIndex
].RVA
+ Object
[ObjectIndex
].BaseAddress
);
2226 if (*Address
== 0) {
2230 return EFI_NOT_FOUND
;