3 Copyright (c) 2007 - 2016, Intel Corporation
4 All rights reserved. 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.
24 EdbLoadSymbolSingleEntry (
25 IN EFI_DEBUGGER_SYMBOL_OBJECT
*Object
,
29 IN EFI_DEBUGGER_SYMBOL_TYPE Type
35 Load single symbol entry
39 Object - Symbol file object
42 Address - Symbol address
47 EFI_SUCCESS - add single symbol entry successfully
51 EFI_DEBUGGER_SYMBOL_ENTRY
*Entry
;
54 // Check Count VS MaxCount
56 if (Object
->EntryCount
>= Object
->MaxEntryCount
) {
58 // reallocate (for codebuffer too)
61 return EFI_OUT_OF_RESOURCES
;
64 Entry
= &Object
->Entry
[Object
->EntryCount
];
69 if (sizeof (UINTN
) == sizeof(UINT64
)) {
70 DEBUG ((DEBUG_ERROR
, " Symbol: %a, Address: 0x%016lx (%d)\n", Name
, (UINT64
)Address
, (UINTN
)Type
));
72 DEBUG ((DEBUG_ERROR
, " Symbol: %a, Address: 0x%08x (%d)\n", Name
, Address
, (UINTN
)Type
));
76 // Fill the entry - name, RVA, type
78 AsciiStrnCpyS (Entry
->Name
, sizeof(Entry
->Name
), Name
, sizeof(Entry
->Name
) - 1);
79 if (ObjName
!= NULL
) {
80 AsciiStrnCpyS (Entry
->ObjName
, sizeof(Entry
->ObjName
), ObjName
, sizeof(Entry
->ObjName
) - 1);
82 Entry
->RVA
= Address
% EFI_DEBUGGER_DEFAULT_LINK_IMAGEBASE
;
97 EdbEbcMapParseStateUninitialized
,
98 EdbEbcMapParseStateSymbolStart
,
99 EdbEbcMapParseStateSeHandlerSymbol
,
100 EdbEbcMapParseStateFunctionSymbol
,
101 EdbEbcMapParseStateVarbssInitSymbol
,
102 EdbEbcMapParseStateCrtSymbol
,
103 EdbEbcMapParseStateVariableSymbol
,
104 EdbEbcMapParseStateStaticFunctionSymbol
,
105 EdbEbcMapParseStateMax
,
106 } EDB_EBC_MAP_PARSE_STATE
;
109 EdbEbcSymbolParseStateUninitialized
,
110 EdbEbcSymbolParseStateReadyForName
,
111 EdbEbcSymbolParseStateReadyForRVA
,
112 EdbEbcSymbolParseStateReadyForType
,
113 EdbEbcSymbolParseStateReadyForObject
,
114 EdbEbcSymbolParseStateMax
,
115 } EDB_EBC_SYMBOL_PARSE_STATE
;
119 The following code depends on the MAP file generated by IEC compiler (actually Microsoft linker).
121 Sample as follows: EbcTest.map
122 ===============================================================================
125 Timestamp is 45b02718 (Fri Jan 19 10:04:08 2007)
127 Preferred load address is 10000000
129 Start Length Name Class
130 0001:00000000 00000370H .text CODE
131 0002:00000000 00000030H _VARBSS_INIT CODE
132 0003:00000000 00000004H .CRT$TSA DATA
133 0003:00000004 00000004H .CRT$TSC DATA
134 0003:00000008 00000004H .CRT$X DATA
135 0003:0000000c 00000008H .CRT$XCU DATA
136 0003:00000014 00000004H .CRT$Z DATA
137 0003:00000020 0000001cH .rdata DATA
138 0003:0000003c 00000000H .edata DATA
139 0003:0000003c 00000056H .rdata$debug DATA
140 0004:00000000 00000070H .data DATA
141 0004:00000070 00000020H .bss DATA
143 Address Publics by Value Rva+Base Lib:Object
145 0000:00000000 ___safe_se_handler_table 00000000 <absolute>
146 0000:00000000 ___safe_se_handler_count 00000000 <absolute>
147 0001:00000042 TestSubRoutine 10000442 f EbcTest.obj
148 0001:0000011a EfiMain 1000051a f EbcTest.obj
149 0001:00000200 TestSubRoutineSub 10000600 f EbcTestSub.obj
150 0001:00000220 EfiStart 10000620 f EbcLib:EbcLib.obj
151 0002:00000000 varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest$c45b02717 10000800 f EbcTest.obj
152 0002:00000020 varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTestSub$c45af77f3 10000820 f EbcTestSub.obj
153 0003:00000000 CrtThunkBegin 10000a00 EbcLib:EbcLib.obj
154 0003:00000004 CrtThunkEnd 10000a04 EbcLib:EbcLib.obj
155 0003:00000008 CrtBegin 10000a08 EbcLib:EbcLib.obj
156 0003:00000014 CrtEnd 10000a14 EbcLib:EbcLib.obj
157 0004:00000070 TestStr 10000c70 EbcTest.obj
158 0004:00000078 TestVariable1 10000c78 EbcTest.obj
159 0004:00000080 TestSubVariableSub 10000c80 EbcTestSub.obj
161 entry point at 0001:00000220
165 0001:00000000 TestSubRoutine2 10000400 f EbcTest.obj
166 ===============================================================================
170 EdbLoadSymbolEntryByIec (
171 IN EFI_DEBUGGER_SYMBOL_OBJECT
*Object
,
179 Load symbol entry by Iec
183 DebuggerPrivate - EBC Debugger private data structure
184 Object - Symbol file object
185 BufferSize - Symbol file buffer size
186 Buffer - Symbol file buffer
190 EFI_SUCCESS - add symbol entry successfully
196 EDB_EBC_MAP_PARSE_STATE MapParseState
;
197 EDB_EBC_SYMBOL_PARSE_STATE SymbolParseState
;
201 EFI_DEBUGGER_SYMBOL_TYPE Type
;
205 // Begin to parse the Buffer
207 LineBuffer
= AsciiStrGetNewTokenLine (Buffer
, "\n\r");
208 MapParseState
= EdbEbcMapParseStateUninitialized
;
212 while (LineBuffer
!= NULL
) {
213 FieldBuffer
= AsciiStrGetNewTokenField (LineBuffer
, " ");
214 SymbolParseState
= EdbEbcSymbolParseStateUninitialized
;
221 Type
= EfiDebuggerSymbolTypeMax
;
225 while (FieldBuffer
!= NULL
) {
226 if (AsciiStrCmp (FieldBuffer
, "") == 0) {
227 FieldBuffer
= AsciiStrGetNextTokenField (" ");
233 if (AsciiStrCmp (FieldBuffer
, "Address") == 0) {
234 MapParseState
= EdbEbcMapParseStateSymbolStart
;
240 if (AsciiStrCmp (FieldBuffer
, "Static") == 0) {
241 MapParseState
= EdbEbcMapParseStateStaticFunctionSymbol
;
245 if (MapParseState
== EdbEbcMapParseStateUninitialized
) {
247 // Do not parse anything until get "Address" or "Static"
251 if (AsciiStrCmp (FieldBuffer
, "entry") == 0) {
259 // Now we start to parse this line for Name, Address, and Object
261 switch (SymbolParseState
) {
262 case EdbEbcSymbolParseStateUninitialized
:
266 SymbolParseState
= EdbEbcSymbolParseStateReadyForName
;
268 case EdbEbcSymbolParseStateReadyForName
:
272 if (AsciiStrnCmp (FieldBuffer
, "___safe_se_handler", AsciiStrLen ("___safe_se_handler")) == 0) {
276 MapParseState
= EdbEbcMapParseStateSeHandlerSymbol
;
278 } else if (AsciiStrnCmp (FieldBuffer
, "varbss_init", AsciiStrLen ("varbss_init")) == 0) {
282 MapParseState
= EdbEbcMapParseStateVarbssInitSymbol
;
283 // goto ExitFieldParse;
285 SymbolParseState
= EdbEbcSymbolParseStateReadyForRVA
;
286 } else if (AsciiStrnCmp (FieldBuffer
, "Crt", AsciiStrLen ("Crt")) == 0) {
290 MapParseState
= EdbEbcMapParseStateCrtSymbol
;
291 // goto ExitFieldParse;
293 SymbolParseState
= EdbEbcSymbolParseStateReadyForRVA
;
296 // Now, it is normal function
298 switch (MapParseState
) {
299 case EdbEbcMapParseStateSeHandlerSymbol
:
300 MapParseState
= EdbEbcMapParseStateFunctionSymbol
;
302 case EdbEbcMapParseStateCrtSymbol
:
303 MapParseState
= EdbEbcMapParseStateVariableSymbol
;
305 case EdbEbcMapParseStateFunctionSymbol
:
306 case EdbEbcMapParseStateVariableSymbol
:
307 case EdbEbcMapParseStateStaticFunctionSymbol
:
314 SymbolParseState
= EdbEbcSymbolParseStateReadyForRVA
;
317 case EdbEbcSymbolParseStateReadyForRVA
:
321 Address
= AsciiXtoi (FieldBuffer
);
322 SymbolParseState
= EdbEbcSymbolParseStateReadyForType
;
324 case EdbEbcSymbolParseStateReadyForType
:
326 // Get the Type. This is optional, only for "f".
328 if (AsciiStrCmp (FieldBuffer
, "f") == 0) {
329 SymbolParseState
= EdbEbcSymbolParseStateReadyForObject
;
330 switch (MapParseState
) {
331 case EdbEbcMapParseStateFunctionSymbol
:
332 case EdbEbcMapParseStateVarbssInitSymbol
:
333 Type
= EfiDebuggerSymbolFunction
;
335 case EdbEbcMapParseStateStaticFunctionSymbol
:
336 Type
= EfiDebuggerSymbolStaticFunction
;
345 // Else it should be Object.
346 // let it bypass here
348 case EdbEbcSymbolParseStateReadyForObject
:
350 case EfiDebuggerSymbolTypeMax
:
351 switch (MapParseState
) {
352 case EdbEbcMapParseStateVariableSymbol
:
353 case EdbEbcMapParseStateCrtSymbol
:
354 Type
= EfiDebuggerSymbolGlobalVariable
;
356 case EdbEbcMapParseStateSeHandlerSymbol
:
366 case EfiDebuggerSymbolFunction
:
367 case EfiDebuggerSymbolStaticFunction
:
376 ObjName
= FieldBuffer
;
377 SymbolParseState
= EdbEbcSymbolParseStateUninitialized
;
385 // Get the next field
387 FieldBuffer
= AsciiStrGetNextTokenField (" ");
391 // Add the entry if we get everything.
393 if ((Name
!= NULL
) && (Type
!= EfiDebuggerSymbolTypeMax
)) {
394 EdbLoadSymbolSingleEntry (Object
, Name
, ObjName
, Address
, Type
);
401 LineBuffer
= AsciiStrGetNextTokenLine ("\n\r");
412 IN EFI_DEBUGGER_SYMBOL_OBJECT
*Object
,
424 Object - Symbol file object
425 BufferSize - Symbol file buffer size
426 Buffer - Symbol file buffer
430 EFI_SUCCESS - add symbol entry successfully
435 // MAP file format depends on the compiler (actually linker).
437 // It is possible to check the different MAP file format in this routine.
438 // Now only IEC is supported.
440 return EdbLoadSymbolEntryByIec (Object
, BufferSize
, Buffer
);
443 EFI_DEBUGGER_SYMBOL_OBJECT
*
445 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
447 IN OUT UINTN
*Index OPTIONAL
453 Find symbol file by name
457 DebuggerPrivate - EBC Debugger private data structure
458 FileName - Symbol file name
459 Index - Symbol file index
472 for (ObjectIndex
= 0; ObjectIndex
< DebuggerPrivate
->DebuggerSymbolContext
.ObjectCount
; ObjectIndex
++) {
473 if (StrCmp (FileName
, DebuggerPrivate
->DebuggerSymbolContext
.Object
[ObjectIndex
].Name
) == 0) {
475 // Name match, found it
478 *Index
= ObjectIndex
;
480 return &DebuggerPrivate
->DebuggerSymbolContext
.Object
[ObjectIndex
];
491 EbdFindSymbolAddress (
493 IN EDB_MATCH_SYMBOL_TYPE Type
,
494 OUT EFI_DEBUGGER_SYMBOL_OBJECT
**RetObject
,
495 OUT EFI_DEBUGGER_SYMBOL_ENTRY
**RetEntry
501 Find symbol by address
505 Address - Symbol address
507 RetObject - Symbol object
508 RetEntry - Symbol entry
512 Nearest symbol address
518 UINTN CandidateLowerAddress
;
519 UINTN CandidateUpperAddress
;
520 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
521 EFI_DEBUGGER_SYMBOL_ENTRY
*Entry
;
522 EFI_DEBUGGER_SYMBOL_ENTRY
*LowEntry
;
523 EFI_DEBUGGER_SYMBOL_ENTRY
*UpperEntry
;
524 EFI_DEBUGGER_SYMBOL_OBJECT
*LowObject
;
525 EFI_DEBUGGER_SYMBOL_OBJECT
*UpperObject
;
527 if ((Type
< 0) || (Type
>= EdbMatchSymbolTypeMax
)) {
534 CandidateLowerAddress
= 0;
535 CandidateUpperAddress
= (UINTN
)-1;
542 // Go through each object
544 Object
= mDebuggerPrivate
.DebuggerSymbolContext
.Object
;
545 for (Index
= 0; Index
< mDebuggerPrivate
.DebuggerSymbolContext
.ObjectCount
; Index
++, Object
++) {
546 if (Object
->EntryCount
== 0) {
550 // Go through each entry
552 Entry
= Object
->Entry
;
553 for (SubIndex
= 0; SubIndex
< Object
->EntryCount
; SubIndex
++, Entry
++) {
554 if (Address
!= Entry
->RVA
+ Object
->BaseAddress
) {
556 // Check for nearest address
558 if (Address
> Entry
->RVA
+ Object
->BaseAddress
) {
560 // Record it if Current RVA < Address
562 if (CandidateLowerAddress
< Entry
->RVA
+ Object
->BaseAddress
) {
563 CandidateLowerAddress
= Entry
->RVA
+ Object
->BaseAddress
;
569 // Record it if Current RVA > Address
571 if (CandidateUpperAddress
> Entry
->RVA
+ Object
->BaseAddress
) {
572 CandidateUpperAddress
= Entry
->RVA
+ Object
->BaseAddress
;
574 UpperObject
= Object
;
580 // address match, return directly
589 // No Match, provide latest symbol
592 if ((Address
- CandidateLowerAddress
) < EFI_DEBUGGER_MAX_SYMBOL_ADDRESS_DELTA_VALUE
) {
594 // Check for lower address
596 if (((Type
== EdbMatchSymbolTypeNearestAddress
) &&
597 ((CandidateUpperAddress
- Address
) > (Address
- CandidateLowerAddress
))) ||
598 (Type
== EdbMatchSymbolTypeLowerAddress
)) {
600 // return nearest lower address
602 *RetEntry
= LowEntry
;
603 *RetObject
= LowObject
;
604 return CandidateLowerAddress
;
608 if ((CandidateUpperAddress
- Address
) < EFI_DEBUGGER_MAX_SYMBOL_ADDRESS_DELTA_VALUE
) {
610 // Check for upper address
612 if (((Type
== EdbMatchSymbolTypeNearestAddress
) &&
613 ((CandidateUpperAddress
- Address
) < (Address
- CandidateLowerAddress
))) ||
614 (Type
== EdbMatchSymbolTypeUpperAddress
)) {
616 // return nearest upper address
618 *RetEntry
= UpperEntry
;
619 *RetObject
= UpperObject
;
620 return CandidateUpperAddress
;
625 // No match and nearest one, return NULL
632 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
639 Unload symbol file by name
643 DebuggerPrivate - EBC Debugger private data structure
644 FileName - Symbol file name
648 EFI_SUCCESS - unload symbol successfully
652 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
655 EFI_DEBUGGER_SYMBOL_ENTRY
*OldEntry
;
658 VOID
**OldSourceBuffer
;
663 Object
= EdbFindSymbolFile (DebuggerPrivate
, FileName
, &ObjectIndex
);
664 if (Object
== NULL
) {
665 EDBPrint (L
"SymbolFile is not loaded!\n");
666 return EFI_DEBUG_CONTINUE
;
672 Object
= DebuggerPrivate
->DebuggerSymbolContext
.Object
;
673 OldEntry
= Object
->Entry
;
674 OldSourceBuffer
= Object
->SourceBuffer
;
675 MaxEntryCount
= Object
->MaxEntryCount
;
676 OldEntryCount
= Object
->EntryCount
;
679 // Remove the matched Object
681 for (Index
= ObjectIndex
; Index
< DebuggerPrivate
->DebuggerSymbolContext
.ObjectCount
- 1; Index
++) {
682 CopyMem (&Object
[Index
], &Object
[Index
+ 1], sizeof(EFI_DEBUGGER_SYMBOL_OBJECT
));
684 ZeroMem (&Object
[Index
], sizeof(Object
[Index
]));
687 // Move old data to new place
689 Object
[Index
].Entry
= OldEntry
;
690 Object
[Index
].SourceBuffer
= OldSourceBuffer
;
691 Object
[Index
].MaxEntryCount
= MaxEntryCount
;
692 DebuggerPrivate
->DebuggerSymbolContext
.ObjectCount
--;
695 // Clean old entry data
697 for (Index
= 0; Index
< OldEntryCount
; Index
++) {
698 ZeroMem (&OldEntry
[Index
], sizeof(OldEntry
[Index
]));
702 // Free OldSourceBuffer
704 for (Index
= 0; OldSourceBuffer
[Index
] != NULL
; Index
++) {
705 gBS
->FreePool (OldSourceBuffer
[Index
]);
706 OldSourceBuffer
[Index
] = NULL
;
714 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
723 Load symbol file by name
727 DebuggerPrivate - EBC Debugger private data structure
728 FileName - Symbol file name
729 BufferSize - Symbol file buffer size
730 Buffer - Symbol file buffer
734 EFI_SUCCESS - load symbol successfully
738 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
742 // Check duplicated File
744 Object
= EdbFindSymbolFile (DebuggerPrivate
, FileName
, NULL
);
745 if (Object
!= NULL
) {
746 Status
= EdbUnloadSymbol (DebuggerPrivate
, FileName
);
747 if (EFI_ERROR(Status
)) {
748 DEBUG ((DEBUG_ERROR
, "Unload Duplicated Symbol File Error!\n"));
754 // Check Count VS MaxCount
756 if (DebuggerPrivate
->DebuggerSymbolContext
.ObjectCount
>= DebuggerPrivate
->DebuggerSymbolContext
.MaxObjectCount
) {
761 return EFI_OUT_OF_RESOURCES
;
764 Object
= &DebuggerPrivate
->DebuggerSymbolContext
.Object
[DebuggerPrivate
->DebuggerSymbolContext
.ObjectCount
];
769 Object
->EntryCount
= 0;
770 Object
->MaxEntryCount
= EFI_DEBUGGER_SYMBOL_ENTRY_MAX
;
775 DEBUG ((DEBUG_ERROR
, "Symbol File: %s\n", FileName
));
776 Status
= EdbLoadSymbolEntry (Object
, BufferSize
, Buffer
);
777 if (EFI_ERROR (Status
)) {
784 StrnCpyS (Object
->Name
, sizeof(Object
->Name
) / sizeof(CHAR16
),
785 FileName
, (sizeof(Object
->Name
) / sizeof(CHAR16
)) - 1);
786 Object
->BaseAddress
= 0;
789 // Increase the object count
791 DebuggerPrivate
->DebuggerSymbolContext
.ObjectCount
++;
804 Located PDB path name in PE image
808 ImageBase - base of PE to search
812 Pointer into image at offset of PDB file name if PDB file name is found,
813 Otherwise a pointer to an empty string.
819 EFI_IMAGE_DOS_HEADER
*DosHdr
;
820 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NtHdr
;
821 EFI_IMAGE_OPTIONAL_HEADER32
*OptionalHdr32
;
822 EFI_IMAGE_OPTIONAL_HEADER64
*OptionalHdr64
;
823 EFI_IMAGE_DATA_DIRECTORY
*DirectoryEntry
;
824 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*DebugEntry
;
825 VOID
*CodeViewEntryPointer
;
830 CodeViewEntryPointer
= NULL
;
837 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
840 NtHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*) ((UINT8
*) DosHdr
+ DosHdr
->e_lfanew
);
842 // Check Machine, filter for EBC
844 if (NtHdr
->Pe32
.FileHeader
.Machine
!= EFI_IMAGE_MACHINE_EBC
) {
846 // If not EBC, return NULL
852 // Get DirectoryEntry
853 // EBC spec says PE32+, but implementation uses PE32. So check dynamically here.
855 if (NtHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
856 OptionalHdr32
= (VOID
*) &NtHdr
->Pe32
.OptionalHeader
;
857 DirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*) &(OptionalHdr32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
]);
858 } else if (NtHdr
->Pe32Plus
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
859 OptionalHdr64
= (VOID
*) &NtHdr
->Pe32Plus
.OptionalHeader
;
860 DirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*) &(OptionalHdr64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
]);
864 if (DirectoryEntry
->VirtualAddress
== 0) {
868 // Go through DirectoryEntry
871 (DirCount
< DirectoryEntry
->Size
/ sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
)) && CodeViewEntryPointer
== NULL
;
874 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*) (DirectoryEntry
->VirtualAddress
+ (UINTN
) ImageBase
+ DirCount
* sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
));
875 if (DebugEntry
->Type
== EFI_IMAGE_DEBUG_TYPE_CODEVIEW
) {
877 // Match DebugEntry, only CODEVIEW_SIGNATURE_NB10 and CODEVIEW_SIGNATURE_RSDS are supported.
879 CodeViewEntryPointer
= (VOID
*) ((UINTN
) DebugEntry
->RVA
+ (UINTN
) ImageBase
);
880 switch (*(UINT32
*) CodeViewEntryPointer
) {
881 case CODEVIEW_SIGNATURE_NB10
:
882 PdbPath
= (CHAR8
*) CodeViewEntryPointer
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
);
884 case CODEVIEW_SIGNATURE_RSDS
:
885 PdbPath
= (CHAR8
*) CodeViewEntryPointer
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY
);
901 IN CHAR8
*PdbFileName
,
902 IN CHAR16
*MapFileName
908 Check whether PDB file and MAP file have same name
912 PdbFileName - PDB file name
913 MapFileName - MAP file name
917 TRUE - PDB and MAP file name match
918 FALSE - PDB and MAP file name not match
924 CHAR8
*PurePdbFileName
;
930 PurePdbFileName
= PdbFileName
;
931 for (Index
= 0; PdbFileName
[Index
] != 0; Index
++) {
932 if (PdbFileName
[Index
] == '\\') {
933 PurePdbFileName
= &PdbFileName
[Index
+ 1];
936 PdbFileName
= PurePdbFileName
;
941 PdbNameSize
= AsciiStrLen (PdbFileName
);
942 MapNameSize
= StrLen (MapFileName
);
944 if (PdbNameSize
!= MapNameSize
) {
951 for (Index
= 0; Index
< MapNameSize
- 4; Index
++) {
952 if ((PdbFileName
[Index
] | 0x20) != (MapFileName
[Index
] | 0x20)) {
961 // BUGBUG: work-around start
964 EFI_DEBUG_IMAGE_INFO
*EfiDebugImageInfoTable
;
965 volatile UINT32 UpdateStatus
;
967 } EFI_DEBUG_IMAGE_INFO_TABLE_HEADER_OLD
;
969 EFI_DEBUG_IMAGE_INFO_TABLE_HEADER mDebugImageInfoTableHeader
;
972 EdbFixDebugImageInfoTable (
973 IN OUT EFI_DEBUG_IMAGE_INFO_TABLE_HEADER
**DebugImageInfoTableHeader
976 For compatibility consideration, we handle 2 cases:
980 +------------------------+ +------------------------+
981 | EfiDebugImageInfoTable | | UpdateStatus |
982 +------------------------+ +------------------------+
983 | UpdateStatus | | TableSize |
984 +------------------------+ +------------------------+
985 | TableSize | | EfiDebugImageInfoTable |
986 +------------------------+ +------------------------+
990 +------------------------+ +------------------------+
991 | EfiDebugImageInfoTable | | UpdateStatus |
992 | | +------------------------+
994 +------------------------+ +------------------------+
995 | UpdateStatus | | EfiDebugImageInfoTable |
996 +------------------------+ | |
998 +------------------------+ +------------------------+
1002 mDebugImageInfoTableHeader
.EfiDebugImageInfoTable
= ((EFI_DEBUG_IMAGE_INFO_TABLE_HEADER_OLD
*)(*DebugImageInfoTableHeader
))->EfiDebugImageInfoTable
;
1003 mDebugImageInfoTableHeader
.UpdateStatus
= ((EFI_DEBUG_IMAGE_INFO_TABLE_HEADER_OLD
*)(*DebugImageInfoTableHeader
))->UpdateStatus
;
1004 mDebugImageInfoTableHeader
.TableSize
= ((EFI_DEBUG_IMAGE_INFO_TABLE_HEADER_OLD
*)(*DebugImageInfoTableHeader
))->TableSize
;
1006 if ((*DebugImageInfoTableHeader
)->UpdateStatus
> 3) {
1007 *DebugImageInfoTableHeader
= &mDebugImageInfoTableHeader
;
1011 if ((*DebugImageInfoTableHeader
)->TableSize
% (EFI_PAGE_SIZE
/ (sizeof (VOID
*))) != 0) {
1012 *DebugImageInfoTableHeader
= &mDebugImageInfoTableHeader
;
1019 // BUGBUG: work-around end
1024 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
1025 IN CHAR16
*FileName
,
1026 IN EDB_EBC_IMAGE_RVA_SEARCH_TYPE SearchType
1030 Routine Description:
1036 DebuggerPrivate - EBC Debugger private data structure
1037 FileName - Symbol file name
1038 SearchType - Search type for Object
1042 EFI_SUCCESS - Patch symbol RVA successfully
1043 EFI_NOT_FOUND - Symbol RVA base not found
1049 EFI_DEBUG_IMAGE_INFO
*ImageTable
;
1052 VOID
*CandidateImageBase
;
1053 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
1055 if (SearchType
< 0 || SearchType
>= EdbEbcImageRvaSearchTypeMax
) {
1056 return EFI_INVALID_PARAMETER
;
1060 // Get the related object
1062 Object
= EdbFindSymbolFile (DebuggerPrivate
, FileName
, NULL
);
1063 if (Object
== NULL
) {
1064 return EFI_NOT_FOUND
;
1068 // Try again to get DebugImageInfoTable
1070 if (mDebuggerPrivate
.DebugImageInfoTableHeader
== NULL
) {
1071 Status
= EfiGetSystemConfigurationTable (
1072 &gEfiDebugImageInfoTableGuid
,
1073 (VOID
**) &mDebuggerPrivate
.DebugImageInfoTableHeader
1075 if (EFI_ERROR (Status
)) {
1076 EDBPrint (L
"DebugImageInfoTable not found!\n");
1080 DEBUG ((DEBUG_ERROR
, "DebugImageInfoTableHeader: %x\n", mDebuggerPrivate
.DebugImageInfoTableHeader
));
1083 // BUGBUG: work-around start
1085 EdbFixDebugImageInfoTable (&mDebuggerPrivate
.DebugImageInfoTableHeader
);
1087 // BUGBUG: work-around end
1091 // Go through DebugImageInfoTable for each Image
1093 CandidateImageBase
= NULL
;
1094 ImageTable
= mDebuggerPrivate
.DebugImageInfoTableHeader
->EfiDebugImageInfoTable
;
1095 for (ImageNumber
= 0; ImageNumber
< mDebuggerPrivate
.DebugImageInfoTableHeader
->TableSize
; ImageNumber
++) {
1096 if (ImageTable
[ImageNumber
].NormalImage
== NULL
) {
1099 ImageBase
= ImageTable
[ImageNumber
].NormalImage
->LoadedImageProtocolInstance
->ImageBase
;
1103 PdbPath
= GetPdbPath (ImageBase
);
1104 if (PdbPath
== NULL
) {
1110 if (!MatchPdbAndMap (PdbPath
, FileName
)) {
1113 DEBUG ((DEBUG_ERROR
, "ImageBase: %x\n", ImageBase
));
1118 if (SearchType
== EdbEbcImageRvaSearchTypeAny
|| SearchType
== EdbEbcImageRvaSearchTypeFirst
) {
1120 // Assign base address and return
1122 Object
->BaseAddress
= (UINTN
)ImageBase
;
1127 // Get CandidateImageBase for EdbEbcImageRvaSearchTypeLast
1129 CandidateImageBase
= ImageBase
;
1133 // Check EdbEbcImageRvaSearchTypeLast
1135 if (SearchType
== EdbEbcImageRvaSearchTypeLast
) {
1136 if (CandidateImageBase
== NULL
) {
1137 return EFI_NOT_FOUND
;
1140 // Assign base address and return
1142 Object
->BaseAddress
= (UINTN
)CandidateImageBase
;
1149 return EFI_NOT_FOUND
;
1154 IN CHAR8
*ObjFileName
,
1155 IN CHAR16
*CodFileName
1159 Routine Description:
1161 Check whether OBJ file and COD file have same name
1165 ObjFileName - OBJ file name
1166 CodFileName - COD file name
1170 TRUE - OBJ and COD file name match
1171 FALSE - OBJ and COD file name not match
1177 CHAR8
*PureObjFileName
;
1181 // remove library name
1183 PureObjFileName
= ObjFileName
;
1184 for (Index
= 0; ObjFileName
[Index
] != 0; Index
++) {
1185 if (ObjFileName
[Index
] == ':') {
1186 PureObjFileName
= &ObjFileName
[Index
+ 1];
1190 ObjFileName
= PureObjFileName
;
1195 ObjNameSize
= AsciiStrLen (ObjFileName
);
1196 CodNameSize
= StrLen (CodFileName
);
1198 if (ObjNameSize
!= CodNameSize
) {
1205 for (Index
= 0; Index
< CodNameSize
- 4; Index
++) {
1206 if ((ObjFileName
[Index
] | 0x20) != (CodFileName
[Index
] | 0x20)) {
1215 EdbEbcCodParseStateUninitialized
,
1216 EdbEbcCodParseStateSymbolInitialized
,
1217 EdbEbcCodParseStateSymbolStart
,
1218 EdbEbcCodParseStateSymbolEnd
,
1219 EdbEbcCodParseStateMax
,
1220 } EDB_EBC_COD_PARSE_STATE
;
1224 The following code depends on the COD file generated by IEC compiler.
1226 Sample as follows: EbcTest.cod
1227 ===============================================================================
1228 ; -- Machine type EFI
1229 ; mark_description "Intel(R) C Compiler for EFI Byte Code, Version 1.2 Build 20040123";
1230 ; mark_description "XXX";
1231 ;ident "Intel(R) C Compiler for EFI Byte Code, Version 1.2 Build 20040123"
1235 _TEXT SEGMENT PARA PUBLIC USE32 'CODE'
1237 _DATA SEGMENT PARA PUBLIC USE32 'DATA'
1240 _BSS SEGMENT PARA PUBLIC USE32 'BSS'
1243 _VARBSS SEGMENT PARA PUBLIC USE32 'BSS'
1246 ASSUME CS:FLAT,DS:FLAT,SS:FLAT
1247 _DATA SEGMENT PARA PUBLIC USE32 'DATA'
1248 TestVariable2 DD 000000003H,000000000H ; u64
1250 _DATA SEGMENT PARA PUBLIC USE32 'DATA'
1252 _TEXT SEGMENT PARA PUBLIC USE32 'CODE'
1262 0011a 60 00 70 80 MOVqw R0, R0(+0,-112) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:117
1265 ;118 ; UINT16 test = 0x1234;
1267 0011e 77 58 58 00 34
1268 12 MOVIww @R0(+0,+88), +4660 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:118
1271 ;121 ; EFI_STATUS Status;
1273 ;121 ; SystemTable->ConOut->OutputString (
1275 00124 72 87 01 12 MOVnw R7, @R0(+1,+128) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:121
1276 00128 72 f7 85 21 MOVnw R7, @R7(+5,+24) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:121
1279 ;122 ; SystemTable->ConOut,
1281 0012c 72 84 01 12 MOVnw R4, @R0(+1,+128) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:122
1282 00130 72 c8 85 21 MOVnw @R0, @R4(+5,+24) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:122
1283 00134 b9 34 00 00 00
1284 00 MOVreld R4, __STRING$1 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:122
1285 0013a b2 48 01 10 MOVnw @R0(+1,+0), R4 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:122
1286 0013e 83 2f 01 00 00
1287 10 CALLEX @R7(+1,+0) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:122
1291 ;125 ; L"Hello EBC Test!\n\r"
1293 ;125 ; EFI_BREAKPOINT ();
1295 00144 00 03 BREAK 3 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:125
1299 ;126 ; TestVariable1 = 6;
1301 00146 b9 37 00 00 00
1302 00 MOVreld R7, TestVariable1 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:126
1303 0014c 78 0f 06 00 MOVInw @R7, (0,6) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:126
1306 ;127 ; TestSubRoutineSub (1, 5);
1308 00150 78 08 01 00 MOVInw @R0, (0,1) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:127
1309 00154 78 48 01 10 05
1310 00 MOVInw @R0(1,0), (0,5) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:127
1311 0015a 83 10 00 00 00
1312 00 CALL TestSubRoutineSub ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:127
1317 ;129 ; SystemTable->ConOut->OutputString (
1319 00160 72 87 01 12 MOVnw R7, @R0(+1,+128) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:129
1320 00164 72 f7 85 21 MOVnw R7, @R7(+5,+24) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:129
1323 ;130 ; SystemTable->ConOut,
1325 00168 72 84 01 12 MOVnw R4, @R0(+1,+128) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:130
1326 0016c 72 c8 85 21 MOVnw @R0, @R4(+5,+24) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:130
1331 00170 b9 34 00 00 00
1332 00 MOVreld R4, TestStr ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:131
1333 00176 b2 c8 01 10 MOVnw @R0(+1, +0), @R4 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:131
1334 0017a 83 2f 01 00 00
1335 10 CALLEX @R7(+1,+0) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:131
1341 ;134 ; test = test & 0xFF;
1343 00180 de 88 58 00 58
1344 00 MOVww @R0(+0,+88), @R0(+0,+88) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:134
1347 ;139 ; if (test != 0x34) {
1348 ;139 ; // EFI_BREAKPOINT ();
1351 ;139 ; Status = TestSubRoutine (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
1353 00186 78 08 01 00 MOVInw @R0, (0,1) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1354 0018a 78 48 01 10 02
1355 00 MOVInw @R0(1,0), (0,2) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1356 00190 78 48 02 10 03
1357 00 MOVInw @R0(2,0), (0,3) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1358 00196 78 48 03 10 04
1359 00 MOVInw @R0(3,0), (0,4) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1360 0019c 78 48 04 20 05
1361 00 MOVInw @R0(4,0), (0,5) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1362 001a2 78 48 05 20 06
1363 00 MOVInw @R0(5,0), (0,6) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1364 001a8 78 48 06 20 07
1365 00 MOVInw @R0(6,0), (0,7) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1366 001ae 78 48 07 20 08
1367 00 MOVInw @R0(7,0), (0,8) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1368 001b4 78 48 08 20 09
1369 00 MOVInw @R0(8,0), (0,9) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1370 001ba 78 48 09 20 0a
1371 00 MOVInw @R0(9,0), (0,10) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1372 001c0 83 10 00 00 00
1373 00 CALL TestSubRoutine ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1375 001c6 b2 78 60 00 MOVnw @R0(+0,+96), R7 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1378 001ca f2 88 50 00 60
1379 00 MOVnw @R0(+0,+80), @R0(+0,+96) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1383 ;141 ; SystemTable->ConOut->OutputString (
1385 001d0 72 87 01 12 MOVnw R7, @R0(+1,+128) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:141
1386 001d4 72 f7 85 21 MOVnw R7, @R7(+5,+24) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:141
1389 ;142 ; SystemTable->ConOut,
1391 001d8 72 84 01 12 MOVnw R4, @R0(+1,+128) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:142
1392 001dc 72 c8 85 21 MOVnw @R0, @R4(+5,+24) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:142
1393 001e0 b9 34 00 00 00
1394 00 MOVreld R4, __STRING$2 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:142
1395 001e6 b2 48 01 10 MOVnw @R0(+1,+0), R4 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:142
1396 001ea 83 2f 01 00 00
1397 10 CALLEX @R7(+1,+0) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:142
1401 ;146 ; L"Goodbye EBC Test!\n\r"
1404 ;146 ; return Status;
1406 001f0 72 87 50 00 MOVnw R7, @R0(+0,+80) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:146
1407 001f4 60 00 70 00 MOVqw R0, R0(+0,+112) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:146
1408 001f8 04 00 RET ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:146
1412 _DATA SEGMENT PARA PUBLIC USE32 'DATA'
1414 __STRING$2 DW 71 ; u16
1434 __STRING$1 DW 72 ; u16
1453 _DATA SEGMENT PARA PUBLIC USE32 'DATA'
1456 _DATA SEGMENT PARA PUBLIC USE32 'DATA'
1457 __STRING$0 DW 55 ; u16
1470 _VARBSS SEGMENT PARA PUBLIC USE32 'BSS'
1472 TestStr DD 2 DUP (?) ; pad
1473 PUBLIC TestVariable1
1474 TestVariable1 DD 2 DUP (?) ; pad
1476 _VARBSS_INIT SEGMENT DWORD PUBLIC USE32 'CODE'
1477 ; -- Begin varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest$c45b815d2
1478 PUBLIC varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest$c45b815d2
1479 varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest$c45b815d2 PROC NEAR
1480 00000 b9 34 00 00 00
1481 00 MOVreld R4, TestStr
1482 00006 b9 35 00 00 00
1483 00 MOVreld R5, __STRING$0
1484 0000c 33 5c MOVnd @R4, R5
1485 0000e b9 34 00 00 00
1486 00 MOVreld R4, TestVariable1
1487 00014 78 0c 04 00 MOVInw @R4, (0,4)
1489 ; -- End varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest$c45b815d2
1491 _DATA SEGMENT PARA PUBLIC USE32 'DATA'
1493 EXTRN TestSubRoutineSub:PROC
1496 ===============================================================================
1500 EdbLoadCodBySymbolByIec (
1503 IN UINTN BufferSize
,
1504 OUT UINTN
*CodeBufferSize
,
1505 OUT UINTN
*FuncOffset
1509 Routine Description:
1511 Load code by symbol by Iec
1515 Name - Symbol file name
1516 BufferSize - Symbol file buffer size
1517 Buffer - Symbol file buffer
1518 CodeBufferSize - Code buffer size
1519 FuncOffset - Code funcion offset
1532 EDB_EBC_COD_PARSE_STATE CodParseState
;
1533 CHAR8 Char
[2] = {9, 0};
1538 LineBuffer
= AsciiStrGetNewTokenLine (Buffer
, "\n\r");
1542 CodParseState
= EdbEbcCodParseStateUninitialized
;
1547 while (LineBuffer
!= NULL
) {
1548 switch (CodParseState
) {
1549 case EdbEbcCodParseStateUninitialized
:
1551 // check mark_begin, begin to check line after this match
1553 if (AsciiStrCmp (LineBuffer
, "; mark_begin;") == 0) {
1554 CodParseState
= EdbEbcCodParseStateSymbolInitialized
;
1556 LineBuffer
= AsciiStrGetNextTokenLine ("\n\r");
1557 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1560 case EdbEbcCodParseStateSymbolInitialized
:
1562 // check mark_end, not check line after this match
1564 if (AsciiStrCmp (LineBuffer
, "; mark_end;") == 0) {
1565 CodParseState
= EdbEbcCodParseStateUninitialized
;
1566 LineBuffer
= AsciiStrGetNextTokenLine ("\n\r");
1567 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1572 // not check this line if the first char is as follows
1574 if ((*LineBuffer
== 0) ||
1575 (*LineBuffer
== '$') ||
1576 (*LineBuffer
== ';') ||
1577 (*LineBuffer
== '_') ||
1578 (*LineBuffer
== ' ')) {
1579 LineBuffer
= AsciiStrGetNextTokenLine ("\n\r");
1580 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1585 // get function name, function name is followed by char 0x09.
1587 FieldBuffer
= AsciiStrGetNewTokenField (LineBuffer
, Char
);
1588 ASSERT (FieldBuffer
!= NULL
);
1589 if (AsciiStriCmp (FieldBuffer
, Name
) == 0) {
1590 BufferStart
= FieldBuffer
;
1591 CodParseState
= EdbEbcCodParseStateSymbolStart
;
1593 PatchForAsciiStrTokenAfter (FieldBuffer
, 0x9);
1598 LineBuffer
= AsciiStrGetNextTokenLine ("\n\r");
1599 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1602 case EdbEbcCodParseStateSymbolStart
:
1604 // check mark_end, if this match, means the function is found successfully.
1606 if (AsciiStrCmp (LineBuffer
, "; mark_end;") == 0) {
1607 CodParseState
= EdbEbcCodParseStateSymbolEnd
;
1609 // prepare CodeBufferSize, FuncOffset, and FuncStart to return
1611 BufferEnd
= LineBuffer
+ sizeof("; mark_end;") - 1;
1612 *CodeBufferSize
= (UINTN
)BufferEnd
- (UINTN
)BufferStart
;
1613 *FuncOffset
= Offset
;
1614 PatchForAsciiStrTokenAfter (LineBuffer
, '\n');
1619 // Get function offset
1621 if ((Offset
== (UINTN
)-1) &&
1622 (*LineBuffer
== ' ')) {
1623 FieldBuffer
= AsciiStrGetNewTokenField (LineBuffer
+ 2, " ");
1624 Offset
= AsciiXtoi (FieldBuffer
);
1625 PatchForAsciiStrTokenAfter (FieldBuffer
, ' ');
1631 LineBuffer
= AsciiStrGetNextTokenLine ("\n\r");
1632 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
1635 case EdbEbcCodParseStateSymbolEnd
:
1644 // no function found
1650 EdbLoadCodBySymbol (
1653 IN UINTN BufferSize
,
1654 OUT UINTN
*CodeBufferSize
,
1655 OUT UINTN
*FuncOffset
1659 Routine Description:
1665 Name - Symbol file name
1666 BufferSize - Symbol file buffer size
1667 Buffer - Symbol file buffer
1668 CodeBufferSize - Code buffer size
1669 FuncOffset - Code funcion offset
1678 // COD file format depends on the compiler.
1680 // It is possible to check the different COD file format in this routine.
1681 // Now only IEC is supported.
1683 return EdbLoadCodBySymbolByIec (Name
, Buffer
, BufferSize
, CodeBufferSize
, FuncOffset
);
1687 EdbFindCodeFromObject (
1688 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
1689 IN EFI_DEBUGGER_SYMBOL_OBJECT
*Object
,
1694 Routine Description:
1696 Find code from object
1700 Object - Symbol object
1701 FileName - File name
1712 // Go througn each Entry in this Object
1714 for (EntryIndex
= 0; EntryIndex
< Object
->EntryCount
; EntryIndex
++) {
1716 // This check is for Function only
1718 if ((Object
->Entry
[EntryIndex
].Type
!= EfiDebuggerSymbolFunction
) &&
1719 (Object
->Entry
[EntryIndex
].Type
!= EfiDebuggerSymbolStaticFunction
)) {
1723 // Skip match varbss_init function, because they has no source code
1725 if (AsciiStrnCmp (Object
->Entry
[EntryIndex
].Name
, "varbss_init", sizeof("varbss_init") - 1) == 0) {
1731 if (!MatchObjAndCod (Object
->Entry
[EntryIndex
].ObjName
, FileName
)) {
1735 // found it, return source buffer
1737 if (Object
->Entry
[EntryIndex
].CodBuffer
!= NULL
) {
1738 return Object
->Entry
[EntryIndex
].SourceBuffer
;
1750 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
1751 IN CHAR16
*MapFileName
,
1752 IN CHAR16
*FileName
,
1753 IN UINTN BufferSize
,
1758 Routine Description:
1764 DebuggerPrivate - EBC Debugger private data structure
1765 MapFileName - Symbol file name
1766 FileName - Code file name
1767 BufferSize - Code file buffer size
1768 Buffer - Code file buffer
1772 EFI_SUCCESS - Code loaded successfully
1776 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
1785 Object
= EdbFindSymbolFile (DebuggerPrivate
, MapFileName
, &ObjectIndex
);
1786 if (Object
== NULL
) {
1787 EDBPrint (L
"SymbolFile is not loaded!\n");
1788 return EFI_NOT_FOUND
;
1791 // Check duplicated File
1793 SourceBuffer
= EdbFindCodeFromObject (DebuggerPrivate
, Object
, FileName
);
1794 if (SourceBuffer
!= NULL
) {
1796 // unnload duplicated code
1798 Status
= EdbUnloadCode (DebuggerPrivate
, MapFileName
, FileName
, &SourceBuffer
);
1799 if (EFI_ERROR(Status
)) {
1800 DEBUG ((DEBUG_ERROR
, "Unload Duplicated Code File Error!\n"));
1803 Status
= EdbDeleteCodeBuffer (DebuggerPrivate
, MapFileName
, FileName
, SourceBuffer
);
1804 if (EFI_ERROR(Status
)) {
1805 DEBUG ((DEBUG_ERROR
, "Delete Duplicated Code File Error!\n"));
1812 // Go through each SymbolEntry
1814 for (EntryIndex
= 0; EntryIndex
< Object
->EntryCount
; EntryIndex
++) {
1816 // load symbol for function only
1818 if ((Object
->Entry
[EntryIndex
].Type
!= EfiDebuggerSymbolFunction
) &&
1819 (Object
->Entry
[EntryIndex
].Type
!= EfiDebuggerSymbolStaticFunction
)) {
1825 if (AsciiStrnCmp (Object
->Entry
[EntryIndex
].Name
, "varbss_init", sizeof("varbss_init") - 1) == 0) {
1831 if (!MatchObjAndCod (Object
->Entry
[EntryIndex
].ObjName
, FileName
)) {
1835 // load code for this symbol
1837 Object
->Entry
[EntryIndex
].CodBuffer
= EdbLoadCodBySymbol (
1838 Object
->Entry
[EntryIndex
].Name
,
1841 &Object
->Entry
[EntryIndex
].CodBufferSize
,
1842 &Object
->Entry
[EntryIndex
].FuncOffsetBase
1844 if (Object
->Entry
[EntryIndex
].CodBuffer
!= NULL
) {
1845 Object
->Entry
[EntryIndex
].SourceBuffer
= Buffer
;
1850 // patch end '\0' for each code buffer
1852 for (EntryIndex
= 0; EntryIndex
< Object
->EntryCount
; EntryIndex
++) {
1853 if (Object
->Entry
[EntryIndex
].CodBuffer
!= NULL
) {
1854 *((UINT8
*)Object
->Entry
[EntryIndex
].CodBuffer
+ Object
->Entry
[EntryIndex
].CodBufferSize
) = 0;
1855 DEBUG ((DEBUG_ERROR
, " CodeSymbol: %a, FuncOffset: 0x05%x\n", Object
->Entry
[EntryIndex
].Name
, Object
->Entry
[EntryIndex
].FuncOffsetBase
));
1856 // DEBUG ((DEBUG_ERROR, " [CODE]:\n%a\n", Object->Entry[EntryIndex].CodBuffer));
1868 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
1869 IN CHAR16
*MapFileName
,
1870 IN CHAR16
*FileName
,
1875 Routine Description:
1881 DebuggerPrivate - EBC Debugger private data structure
1882 MapFileName - Symbol file name
1883 FileName - Code file name
1884 Buffer - Code file buffer
1888 EFI_SUCCESS - Code unloaded successfully
1892 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
1899 Object
= EdbFindSymbolFile (DebuggerPrivate
, MapFileName
, &ObjectIndex
);
1900 if (Object
== NULL
) {
1901 EDBPrint (L
"SymbolFile is not loaded!\n");
1902 return EFI_NOT_FOUND
;
1908 *Buffer
= EdbFindCodeFromObject (DebuggerPrivate
, Object
, FileName
);
1909 if (*Buffer
== NULL
) {
1910 EDBPrint (L
"CodeFile is not loaded!\n");
1911 return EFI_NOT_FOUND
;
1915 // go through each entry
1917 for (EntryIndex
= 0; EntryIndex
< Object
->EntryCount
; EntryIndex
++) {
1918 if ((Object
->Entry
[EntryIndex
].Type
!= EfiDebuggerSymbolFunction
) &&
1919 (Object
->Entry
[EntryIndex
].Type
!= EfiDebuggerSymbolStaticFunction
)) {
1922 if (AsciiStrnCmp (Object
->Entry
[EntryIndex
].Name
, "varbss_init", sizeof("varbss_init") - 1) == 0) {
1925 if (!MatchObjAndCod (Object
->Entry
[EntryIndex
].ObjName
, FileName
)) {
1929 // clean up the buffer
1931 Object
->Entry
[EntryIndex
].CodBuffer
= NULL
;
1932 Object
->Entry
[EntryIndex
].CodBufferSize
= 0;
1933 Object
->Entry
[EntryIndex
].FuncOffsetBase
= 0;
1934 Object
->Entry
[EntryIndex
].SourceBuffer
= NULL
;
1945 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
1946 IN CHAR16
*MapFileName
,
1947 IN CHAR16
*CodeFileName
,
1948 IN UINTN SourceBufferSize
,
1949 IN VOID
*SourceBuffer
1953 Routine Description:
1959 DebuggerPrivate - EBC Debugger private data structure
1960 MapFileName - Symbol file name
1961 CodeFileName - Code file name
1962 SourceBufferSize- Code buffer size
1963 SourceBuffer - Code buffer
1967 EFI_SUCCESS - CodeBuffer added successfully
1972 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
1977 Object
= EdbFindSymbolFile (DebuggerPrivate
, MapFileName
, NULL
);
1978 if (Object
== NULL
) {
1979 EDBPrint (L
"SymbolFile is not loaded!\n");
1980 return EFI_NOT_FOUND
;
1984 // Add it to last entry
1986 for (Index
= 0; Object
->SourceBuffer
[Index
] != NULL
; Index
++) {
1989 Object
->SourceBuffer
[Index
] = SourceBuffer
;
1995 EdbDeleteCodeBuffer (
1996 IN EFI_DEBUGGER_PRIVATE_DATA
*DebuggerPrivate
,
1997 IN CHAR16
*MapFileName
,
1998 IN CHAR16
*CodeFileName
,
1999 IN VOID
*SourceBuffer
2003 Routine Description:
2009 DebuggerPrivate - EBC Debugger private data structure
2010 MapFileName - Symbol file name
2011 CodeFileName - Code file name
2012 SourceBuffer - Code buffer
2016 EFI_SUCCESS - CodeBuffer deleted successfully
2021 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
2026 Object
= EdbFindSymbolFile (DebuggerPrivate
, MapFileName
, NULL
);
2027 if (Object
== NULL
) {
2028 EDBPrint (L
"SymbolFile is not loaded!\n");
2029 return EFI_NOT_FOUND
;
2032 for (Index
= 0; Object
->SourceBuffer
[Index
] != NULL
; Index
++) {
2034 // free the buffer if match
2036 if (Object
->SourceBuffer
[Index
] == SourceBuffer
) {
2037 gBS
->FreePool (SourceBuffer
);
2042 if (Object
->SourceBuffer
[Index
] == NULL
) {
2044 // not return NOT_FOUND
2052 Object
->SourceBuffer
[Index
] = NULL
;
2053 for (Index
= Index
+ 1; Object
->SourceBuffer
[Index
] != NULL
; Index
++) {
2054 Object
->SourceBuffer
[Index
- 1] = Object
->SourceBuffer
[Index
];
2056 Object
->SourceBuffer
[Index
- 1] = NULL
;
2067 Routine Description:
2069 Find the symbol string according to address
2073 Address - Symbol address
2082 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
2084 EFI_DEBUGGER_SYMBOL_ENTRY
*Entry
;
2087 // need we display symbol
2089 if (!mDebuggerPrivate
.DebuggerSymbolContext
.DisplaySymbol
) {
2094 // Go through each object and entry
2096 Object
= mDebuggerPrivate
.DebuggerSymbolContext
.Object
;
2097 for (ObjectIndex
= 0; ObjectIndex
< mDebuggerPrivate
.DebuggerSymbolContext
.ObjectCount
; ObjectIndex
++) {
2098 Entry
= Object
[ObjectIndex
].Entry
;
2099 for (EntryIndex
= 0; EntryIndex
< Object
[ObjectIndex
].EntryCount
; EntryIndex
++) {
2101 // if Address match, return Name
2103 if (Address
== (Entry
[EntryIndex
].RVA
+ Object
[ObjectIndex
].BaseAddress
)) {
2104 return Entry
[EntryIndex
].Name
;
2116 EdbGetLineNumberAndOffsetFromThisLine (
2122 Routine Description:
2124 Get line number and offset from this line in code file
2128 Line - Line buffer in code file
2129 Offset - Offset to functin entry
2141 LineNumber
= (UINTN
)-1;
2143 *Offset
= (UINTN
)-1;
2145 while (LineBuffer
!= NULL
) {
2149 if (*LineBuffer
!= ' ') {
2156 if (*(LineBuffer
+ 2) != ' ') {
2157 if (*Offset
== (UINTN
)-1) {
2158 FieldBuffer
= AsciiStrGetNewTokenField (LineBuffer
+ 2, " ");
2159 *Offset
= AsciiXtoi (FieldBuffer
);
2160 PatchForAsciiStrTokenAfter (FieldBuffer
, ' ');
2165 // 1. assembly instruction
2167 FieldBuffer
= AsciiStrGetNewTokenField (LineBuffer
, ":");
2171 FieldBuffer
= AsciiStrGetNextTokenField (":");
2172 PatchForAsciiStrTokenBefore (FieldBuffer
, ':');
2173 if (FieldBuffer
== NULL
) {
2178 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
2179 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
2185 FieldBuffer
= AsciiStrGetNextTokenField (":");
2186 PatchForAsciiStrTokenBefore (FieldBuffer
, ':');
2187 if (FieldBuffer
== NULL
) {
2191 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
2192 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
2196 LineNumber
= AsciiAtoi (FieldBuffer
);
2208 EdbEbcLineSearchTypeAny
,
2209 EdbEbcLineSearchTypeFirst
,
2210 EdbEbcLineSearchTypeLast
,
2211 EdbEbcLineSearchTypeMax
,
2212 } EDB_EBC_LINE_SEARCH_TYPE
;
2215 EdbGetLineNumberFromCode (
2216 IN EFI_DEBUGGER_SYMBOL_ENTRY
*Entry
,
2217 IN UINTN FuncOffset
,
2218 IN EDB_EBC_LINE_SEARCH_TYPE SearchType
2222 Routine Description:
2224 Get line number from this code file
2228 Entry - Symbol entry
2229 FuncOffset - Offset to functin entry
2230 SearchType - Search type for the code
2241 UINTN CandidateLineNumber
;
2242 UINTN CandidateOffset
;
2244 if (SearchType
< 0 || SearchType
>= EdbEbcLineSearchTypeMax
) {
2248 LineNumber
= (UINTN
)-1;
2249 CandidateLineNumber
= (UINTN
)-1;
2250 CandidateOffset
= (UINTN
)-1;
2251 LineBuffer
= AsciiStrGetNewTokenLine (Entry
->CodBuffer
, "\n");
2252 while (LineBuffer
!= NULL
) {
2253 if (*LineBuffer
!= ' ') {
2254 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
2255 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
2262 LineNumber
= EdbGetLineNumberAndOffsetFromThisLine (LineBuffer
, &Offset
);
2267 if (Offset
!= FuncOffset
) {
2269 // Check last offset match
2271 if (CandidateOffset
== FuncOffset
) {
2272 if (SearchType
== EdbEbcLineSearchTypeLast
) {
2273 PatchForAsciiStrTokenAfter (LineBuffer
, '\n');
2274 if (CandidateLineNumber
!= LineNumber
) {
2275 return CandidateLineNumber
;
2286 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
2287 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
2288 CandidateLineNumber
= LineNumber
;
2293 // Offset match, more check
2295 if (SearchType
== EdbEbcLineSearchTypeAny
) {
2296 PatchForAsciiStrTokenAfter (LineBuffer
, '\n');
2300 if (SearchType
== EdbEbcLineSearchTypeFirst
) {
2304 PatchForAsciiStrTokenAfter (LineBuffer
, '\n');
2305 if (CandidateLineNumber
!= LineNumber
) {
2312 CandidateLineNumber
= LineNumber
;
2313 CandidateOffset
= Offset
;
2315 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
2316 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
2320 // Check last offset match
2322 if (CandidateOffset
== FuncOffset
) {
2323 if (SearchType
== EdbEbcLineSearchTypeLast
) {
2324 return CandidateLineNumber
;
2332 EdbGetSourceStrFromCodeByLine (
2333 IN EFI_DEBUGGER_SYMBOL_ENTRY
*Entry
,
2334 IN UINTN LineNumber
,
2339 Routine Description:
2341 Get the source string from this code file by line
2345 Entry - Symbol entry
2346 LineNumber - line number
2347 FuncEnd - Function end
2361 LineBuffer
= AsciiStrGetNewTokenLine (Entry
->CodBuffer
, "\n");
2362 while (LineBuffer
!= NULL
) {
2363 if (*LineBuffer
!= ';') {
2364 if (FuncStart
!= NULL
) {
2368 *FuncEnd
= LineBuffer
- 1;
2369 PatchForAsciiStrTokenAfter (LineBuffer
, '\n');
2372 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
2373 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
2380 FieldBuffer
= AsciiStrGetNewTokenField (LineBuffer
+ 1, " ");
2381 Number
= AsciiAtoi (FieldBuffer
);
2382 PatchForAsciiStrTokenAfter (FieldBuffer
, ' ');
2383 if (Number
!= LineNumber
) {
2384 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
2385 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
2390 // Line match, get line number
2392 if (FuncStart
== NULL
) {
2393 FuncStart
= LineBuffer
;
2396 LineBuffer
= AsciiStrGetNextTokenLine ("\n");
2397 PatchForAsciiStrTokenBefore (LineBuffer
, '\n');
2404 EdbGetSourceStrFromCode (
2405 IN EFI_DEBUGGER_SYMBOL_ENTRY
*Entry
,
2406 IN UINTN FuncOffset
,
2411 Routine Description:
2413 Get source string from this code file
2417 Entry - Symbol entry
2418 FuncOffset - Offset to functin entry
2419 FuncEnd - Function end
2430 // Only search the last line, then display
2432 LineNumber
= EdbGetLineNumberFromCode (Entry
, FuncOffset
, EdbEbcLineSearchTypeLast
);
2433 if (LineNumber
== (UINTN
)-1) {
2437 return EdbGetSourceStrFromCodeByLine (Entry
, LineNumber
, FuncEnd
);
2447 Routine Description:
2453 Address - Instruction address
2454 IsPrint - Whether need to print
2459 0 - not find the source
2463 UINTN SymbolAddress
;
2464 EFI_DEBUGGER_SYMBOL_OBJECT
*RetObject
;
2465 EFI_DEBUGGER_SYMBOL_ENTRY
*RetEntry
;
2470 CHAR8 Buffer
[EFI_DEBUG_MAX_PRINT_BUFFER
];
2474 // need we display symbol
2476 if (!mDebuggerPrivate
.DebuggerSymbolContext
.DisplaySymbol
) {
2481 // find the symbol address
2483 SymbolAddress
= EbdFindSymbolAddress (
2485 EdbMatchSymbolTypeLowerAddress
,
2489 if (SymbolAddress
== 0) {
2493 FuncOffset
= Address
- SymbolAddress
+ RetEntry
->FuncOffsetBase
;
2498 FuncStart
= EdbGetSourceStrFromCode (RetEntry
, FuncOffset
, (VOID
**) &FuncEnd
);
2499 if (FuncStart
== NULL
) {
2504 // check whether need to real print
2510 *(UINT8
*)FuncEnd
= 0;
2513 // seperate buffer by \n, so that \r can be added.
2515 FuncIndex
= FuncStart
;
2516 while (*FuncIndex
!= 0) {
2517 if (*FuncIndex
== '\n') {
2518 if ((FuncIndex
- FuncStart
) < (EFI_DEBUG_MAX_PRINT_BUFFER
- 3)) {
2519 BufferSize
= FuncIndex
- FuncStart
;
2521 BufferSize
= EFI_DEBUG_MAX_PRINT_BUFFER
- 3;
2523 if (BufferSize
!= 0) {
2524 CopyMem (Buffer
, FuncStart
, BufferSize
);
2526 Buffer
[BufferSize
] = 0;
2527 EDBPrint (L
"%a\n", Buffer
);
2528 FuncStart
= FuncIndex
+ 1;
2529 FuncIndex
= FuncStart
;
2538 *(UINT8
*)FuncEnd
= '\n';
2544 GetMapfileAndSymbol (
2546 OUT CHAR16
**MapfileName
,
2547 OUT CHAR16
**SymbolName
2551 Routine Description:
2553 Get Mapfile and SymbolName from one symbol format: [MapFileName:]SymbolName
2557 Symbol - whole Symbol name
2558 MapfileName - the mapfile name in the symbol
2559 SymbolName - the symbol name in the symbol
2569 *MapfileName
= NULL
;
2570 *SymbolName
= Symbol
;
2572 for (Ch
= Symbol
; *Ch
!= 0; Ch
++) {
2577 *MapfileName
= Symbol
;
2579 *SymbolName
= Ch
+ 1;
2594 Routine Description:
2596 Convert a symbol to an address
2600 Symbol - Symbol name
2601 Address - Symbol address
2605 EFI_SUCCESS - symbol found and address returned.
2606 EFI_NOT_FOUND - symbol not found
2607 EFI_NO_MAPPING - duplicated symbol not found
2612 EFI_DEBUGGER_SYMBOL_OBJECT
*Object
;
2614 EFI_DEBUGGER_SYMBOL_ENTRY
*Entry
;
2616 CHAR16
*MapfileName
;
2619 // Split one symbol to mapfile name and symbol name
2621 GetMapfileAndSymbol (Symbol
, &MapfileName
, &SymbolName
);
2625 // Go through each object
2627 Object
= mDebuggerPrivate
.DebuggerSymbolContext
.Object
;
2628 for (ObjectIndex
= 0; ObjectIndex
< mDebuggerPrivate
.DebuggerSymbolContext
.ObjectCount
; ObjectIndex
++) {
2630 // Check MapfileName
2632 if ((MapfileName
!= NULL
) && (StriCmp (Object
[ObjectIndex
].Name
, MapfileName
) != 0)) {
2636 // Go through each entry
2638 Entry
= Object
[ObjectIndex
].Entry
;
2639 for (EntryIndex
= 0; EntryIndex
< Object
[ObjectIndex
].EntryCount
; EntryIndex
++) {
2641 // Check SymbolName (case sensitive)
2643 if (StrCmpUnicodeAndAscii (SymbolName
, Entry
[EntryIndex
].Name
) == 0) {
2644 if ((*Address
!= 0) && (MapfileName
== NULL
)) {
2646 // Find the duplicated symbol
2648 EDBPrint (L
"Duplicated Symbol found!\n");
2649 return EFI_NO_MAPPING
;
2654 *Address
= (Entry
[EntryIndex
].RVA
+ Object
[ObjectIndex
].BaseAddress
);
2660 if (*Address
== 0) {
2664 return EFI_NOT_FOUND
;