1 /** @file
2
3 Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
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.
11
12
13 **/
14
15 #include "Edb.h"
16
17 /**
18
19 Load single symbol entry.
20
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
26
27 @retval EFI_SUCCESS - add single symbol entry successfully
28
29 **/
30 EFI_STATUS
EdbLoadSymbolSingleEntry(IN EFI_DEBUGGER_SYMBOL_OBJECT * Object,IN CHAR8 * Name,IN CHAR8 * ObjName,IN UINTN Address,IN EFI_DEBUGGER_SYMBOL_TYPE Type)31 EdbLoadSymbolSingleEntry (
32 IN EFI_DEBUGGER_SYMBOL_OBJECT *Object,
33 IN CHAR8 *Name,
34 IN CHAR8 *ObjName,
35 IN UINTN Address,
36 IN EFI_DEBUGGER_SYMBOL_TYPE Type
37 )
38 {
39 EFI_DEBUGGER_SYMBOL_ENTRY *Entry;
40
41 //
42 // Check Count VS MaxCount
43 //
44 if (Object->EntryCount >= Object->MaxEntryCount) {
45 //
46 // reallocate (for codebuffer too)
47 // TBD
48 //
49 return EFI_OUT_OF_RESOURCES;
50 }
51
52 Entry = &Object->Entry[Object->EntryCount];
53
54 //
55 // Print Debug info
56 //
57 if (sizeof (UINTN) == sizeof(UINT64)) {
58 DEBUG ((DEBUG_ERROR, " Symbol: %a, Address: 0x%016lx (%d)\n", Name, (UINT64)Address, (UINTN)Type));
59 } else {
60 DEBUG ((DEBUG_ERROR, " Symbol: %a, Address: 0x%08x (%d)\n", Name, Address, (UINTN)Type));
61 }
62
63 //
64 // Fill the entry - name, RVA, type
65 //
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);
69 }
70 Entry->Rva = Address % EFI_DEBUGGER_DEFAULT_LINK_IMAGEBASE;
71 Entry->Type = Type;
72
73 //
74 // Increase Count
75 //
76 Object->EntryCount++;
77
78 //
79 // Done
80 //
81 return EFI_SUCCESS;
82 }
83
84 typedef enum {
85 EdbEbcMapParseStateUninitialized,
86 EdbEbcMapParseStateSymbolStart,
87 EdbEbcMapParseStateSeHandlerSymbol,
88 EdbEbcMapParseStateFunctionSymbol,
89 EdbEbcMapParseStateVarbssInitSymbol,
90 EdbEbcMapParseStateCrtSymbol,
91 EdbEbcMapParseStateVariableSymbol,
92 EdbEbcMapParseStateStaticFunctionSymbol,
93 EdbEbcMapParseStateMax,
94 } EDB_EBC_MAP_PARSE_STATE;
95
96 typedef enum {
97 EdbEbcSymbolParseStateUninitialized,
98 EdbEbcSymbolParseStateReadyForName,
99 EdbEbcSymbolParseStateReadyForRVA,
100 EdbEbcSymbolParseStateReadyForType,
101 EdbEbcSymbolParseStateReadyForObject,
102 EdbEbcSymbolParseStateMax,
103 } EDB_EBC_SYMBOL_PARSE_STATE;
104
105 /**
106
107 The following code depends on the MAP file generated by IEC compiler (actually Microsoft linker).
108
109 Sample as follows: EbcTest.map
110 ===============================================================================
111 EbcTest
112
113 Timestamp is 45b02718 (Fri Jan 19 10:04:08 2007)
114
115 Preferred load address is 10000000
116
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
130
131 Address Publics by Value Rva+Base Lib:Object
132
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
148
149 entry point at 0001:00000220
150
151 Static symbols
152
153 0001:00000000 TestSubRoutine2 10000400 f EbcTest.obj
154 ===============================================================================
155
156 **/
157
158 /**
159
160 Load symbol entry by Iec.
161
162 @param Object - Symbol file object
163 @param BufferSize - Symbol file buffer size
164 @param Buffer - Symbol file buffer
165
166 @retval EFI_SUCCESS - add symbol entry successfully
167
168 **/
169 EFI_STATUS
EdbLoadSymbolEntryByIec(IN EFI_DEBUGGER_SYMBOL_OBJECT * Object,IN UINTN BufferSize,IN VOID * Buffer)170 EdbLoadSymbolEntryByIec (
171 IN EFI_DEBUGGER_SYMBOL_OBJECT *Object,
172 IN UINTN BufferSize,
173 IN VOID *Buffer
174 )
175 {
176 CHAR8 *LineBuffer;
177 CHAR8 *FieldBuffer;
178 EDB_EBC_MAP_PARSE_STATE MapParseState;
179 EDB_EBC_SYMBOL_PARSE_STATE SymbolParseState;
180 CHAR8 *Name;
181 CHAR8 *ObjName;
182 UINTN Address;
183 EFI_DEBUGGER_SYMBOL_TYPE Type;
184
185
186 //
187 // Begin to parse the Buffer
188 //
189 LineBuffer = AsciiStrGetNewTokenLine (Buffer, "\n\r");
190 MapParseState = EdbEbcMapParseStateUninitialized;
191 //
192 // Check each line
193 //
194 while (LineBuffer != NULL) {
195 FieldBuffer = AsciiStrGetNewTokenField (LineBuffer, " ");
196 SymbolParseState = EdbEbcSymbolParseStateUninitialized;
197 //
198 // Init entry value
199 //
200 Name = NULL;
201 ObjName = NULL;
202 Address = 0;
203 Type = EfiDebuggerSymbolTypeMax;
204 //
205 // Check each field
206 //
207 while (FieldBuffer != NULL) {
208 if (AsciiStrCmp (FieldBuffer, "") == 0) {
209 FieldBuffer = AsciiStrGetNextTokenField (" ");
210 continue;
211 }
212 //
213 // check "Address"
214 //
215 if (AsciiStrCmp (FieldBuffer, "Address") == 0) {
216 MapParseState = EdbEbcMapParseStateSymbolStart;
217 break;
218 }
219 //
220 // check "Static"
221 //
222 if (AsciiStrCmp (FieldBuffer, "Static") == 0) {
223 MapParseState = EdbEbcMapParseStateStaticFunctionSymbol;
224 break;
225 }
226
227 if (MapParseState == EdbEbcMapParseStateUninitialized) {
228 //
229 // Do not parse anything until get "Address" or "Static"
230 //
231 break;
232 }
233 if (AsciiStrCmp (FieldBuffer, "entry") == 0) {
234 //
235 // Skip entry point
236 //
237 break;
238 }
239
240 //
241 // Now we start to parse this line for Name, Address, and Object
242 //
243 switch (SymbolParseState) {
244 case EdbEbcSymbolParseStateUninitialized:
245 //
246 // Get the Address
247 //
248 SymbolParseState = EdbEbcSymbolParseStateReadyForName;
249 break;
250 case EdbEbcSymbolParseStateReadyForName:
251 //
252 // Get the Name
253 //
254 if (AsciiStrnCmp (FieldBuffer, "___safe_se_handler", AsciiStrLen ("___safe_se_handler")) == 0) {
255 //
256 // skip SeHandler
257 //
258 MapParseState = EdbEbcMapParseStateSeHandlerSymbol;
259 goto ExitFieldParse;
260 } else if (AsciiStrnCmp (FieldBuffer, "varbss_init", AsciiStrLen ("varbss_init")) == 0) {
261 //
262 // check VarbssInit
263 //
264 MapParseState = EdbEbcMapParseStateVarbssInitSymbol;
265 // goto ExitFieldParse;
266 Name = FieldBuffer;
267 SymbolParseState = EdbEbcSymbolParseStateReadyForRVA;
268 } else if (AsciiStrnCmp (FieldBuffer, "Crt", AsciiStrLen ("Crt")) == 0) {
269 //
270 // check Crt
271 //
272 MapParseState = EdbEbcMapParseStateCrtSymbol;
273 // goto ExitFieldParse;
274 Name = FieldBuffer;
275 SymbolParseState = EdbEbcSymbolParseStateReadyForRVA;
276 } else {
277 //
278 // Now, it is normal function
279 //
280 switch (MapParseState) {
281 case EdbEbcMapParseStateSeHandlerSymbol:
282 MapParseState = EdbEbcMapParseStateFunctionSymbol;
283 break;
284 case EdbEbcMapParseStateCrtSymbol:
285 MapParseState = EdbEbcMapParseStateVariableSymbol;
286 break;
287 case EdbEbcMapParseStateFunctionSymbol:
288 case EdbEbcMapParseStateVariableSymbol:
289 case EdbEbcMapParseStateStaticFunctionSymbol:
290 break;
291 default:
292 ASSERT (FALSE);
293 break;
294 }
295 Name = FieldBuffer;
296 SymbolParseState = EdbEbcSymbolParseStateReadyForRVA;
297 }
298 break;
299 case EdbEbcSymbolParseStateReadyForRVA:
300 //
301 // Get the RVA
302 //
303 Address = AsciiXtoi (FieldBuffer);
304 SymbolParseState = EdbEbcSymbolParseStateReadyForType;
305 break;
306 case EdbEbcSymbolParseStateReadyForType:
307 //
308 // Get the Type. This is optional, only for "f".
309 //
310 if (AsciiStrCmp (FieldBuffer, "f") == 0) {
311 SymbolParseState = EdbEbcSymbolParseStateReadyForObject;
312 switch (MapParseState) {
313 case EdbEbcMapParseStateFunctionSymbol:
314 case EdbEbcMapParseStateVarbssInitSymbol:
315 Type = EfiDebuggerSymbolFunction;
316 break;
317 case EdbEbcMapParseStateStaticFunctionSymbol:
318 Type = EfiDebuggerSymbolStaticFunction;
319 break;
320 default:
321 ASSERT (FALSE);
322 break;
323 }
324 break;
325 }
326 //
327 // Else it should be Object.
328 // let it bypass here
329 //
330 case EdbEbcSymbolParseStateReadyForObject:
331 switch (Type) {
332 case EfiDebuggerSymbolTypeMax:
333 switch (MapParseState) {
334 case EdbEbcMapParseStateVariableSymbol:
335 case EdbEbcMapParseStateCrtSymbol:
336 Type = EfiDebuggerSymbolGlobalVariable;
337 break;
338 case EdbEbcMapParseStateSeHandlerSymbol:
339 //
340 // do nothing here
341 //
342 break;
343 default:
344 ASSERT (FALSE);
345 break;
346 }
347 break;
348 case EfiDebuggerSymbolFunction:
349 case EfiDebuggerSymbolStaticFunction:
350 break;
351 default:
352 ASSERT (FALSE);
353 break;
354 }
355 //
356 // Get the Object
357 //
358 ObjName = FieldBuffer;
359 SymbolParseState = EdbEbcSymbolParseStateUninitialized;
360 break;
361 default:
362 ASSERT (FALSE);
363 break;
364 }
365
366 //
367 // Get the next field
368 //
369 FieldBuffer = AsciiStrGetNextTokenField (" ");
370 }
371
372 //
373 // Add the entry if we get everything.
374 //
375 if ((Name != NULL) && (Type != EfiDebuggerSymbolTypeMax)) {
376 EdbLoadSymbolSingleEntry (Object, Name, ObjName, Address, Type);
377 }
378
379 ExitFieldParse:
380 //
381 // Get the next line
382 //
383 LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
384 }
385
386 //
387 // Done
388 //
389 return EFI_SUCCESS;
390 }
391
392 /**
393
394 Load symbol entry.
395
396 @param Object - Symbol file object
397 @param BufferSize - Symbol file buffer size
398 @param Buffer - Symbol file buffer
399
400 @retval EFI_SUCCESS - add symbol entry successfully
401
402 **/
403 EFI_STATUS
EdbLoadSymbolEntry(IN EFI_DEBUGGER_SYMBOL_OBJECT * Object,IN UINTN BufferSize,IN VOID * Buffer)404 EdbLoadSymbolEntry (
405 IN EFI_DEBUGGER_SYMBOL_OBJECT *Object,
406 IN UINTN BufferSize,
407 IN VOID *Buffer
408 )
409 {
410 //
411 // MAP file format depends on the compiler (actually linker).
412 //
413 // It is possible to check the different MAP file format in this routine.
414 // Now only IEC is supported.
415 //
416 return EdbLoadSymbolEntryByIec (Object, BufferSize, Buffer);
417 }
418
419 /**
420
421 Find symbol file by name.
422
423 @param DebuggerPrivate - EBC Debugger private data structure
424 @param FileName - Symbol file name
425 @param Index - Symbol file index
426
427 @return Object
428
429 **/
430 EFI_DEBUGGER_SYMBOL_OBJECT *
EdbFindSymbolFile(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN CHAR16 * FileName,IN OUT UINTN * Index OPTIONAL)431 EdbFindSymbolFile (
432 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
433 IN CHAR16 *FileName,
434 IN OUT UINTN *Index OPTIONAL
435 )
436 {
437 UINTN ObjectIndex;
438
439 //
440 // Check each Object
441 //
442 for (ObjectIndex = 0; ObjectIndex < DebuggerPrivate->DebuggerSymbolContext.ObjectCount; ObjectIndex++) {
443 if (StrCmp (FileName, DebuggerPrivate->DebuggerSymbolContext.Object[ObjectIndex].Name) == 0) {
444 //
445 // Name match, found it
446 //
447 if (Index != NULL) {
448 *Index = ObjectIndex;
449 }
450 return &DebuggerPrivate->DebuggerSymbolContext.Object[ObjectIndex];
451 }
452 }
453
454 //
455 // Not found
456 //
457 return NULL;
458 }
459
460 /**
461
462 Find symbol by address.
463
464 @param Address - Symbol address
465 @param Type - Search type
466 @param RetObject - Symbol object
467 @param RetEntry - Symbol entry
468
469 @return Nearest symbol address
470
471 **/
472 UINTN
EbdFindSymbolAddress(IN UINTN Address,IN EDB_MATCH_SYMBOL_TYPE Type,OUT EFI_DEBUGGER_SYMBOL_OBJECT ** RetObject,OUT EFI_DEBUGGER_SYMBOL_ENTRY ** RetEntry)473 EbdFindSymbolAddress (
474 IN UINTN Address,
475 IN EDB_MATCH_SYMBOL_TYPE Type,
476 OUT EFI_DEBUGGER_SYMBOL_OBJECT **RetObject,
477 OUT EFI_DEBUGGER_SYMBOL_ENTRY **RetEntry
478 )
479 {
480 UINTN Index;
481 UINTN SubIndex;
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;
490
491 if ((Type < 0) || (Type >= EdbMatchSymbolTypeMax)) {
492 return 0;
493 }
494
495 //
496 // Init
497 //
498 CandidateLowerAddress = 0;
499 CandidateUpperAddress = (UINTN)-1;
500 LowEntry = NULL;
501 UpperEntry = NULL;
502 LowObject = NULL;
503 UpperObject = NULL;
504
505 //
506 // Go through each object
507 //
508 Object = mDebuggerPrivate.DebuggerSymbolContext.Object;
509 for (Index = 0; Index < mDebuggerPrivate.DebuggerSymbolContext.ObjectCount; Index++, Object++) {
510 if (Object->EntryCount == 0) {
511 continue;
512 }
513 //
514 // Go through each entry
515 //
516 Entry = Object->Entry;
517 for (SubIndex = 0; SubIndex < Object->EntryCount; SubIndex++, Entry++) {
518 if (Address != Entry->Rva + Object->BaseAddress) {
519 //
520 // Check for nearest address
521 //
522 if (Address > Entry->Rva + Object->BaseAddress) {
523 //
524 // Record it if Current RVA < Address
525 //
526 if (CandidateLowerAddress < Entry->Rva + Object->BaseAddress) {
527 CandidateLowerAddress = Entry->Rva + Object->BaseAddress;
528 LowEntry = Entry;
529 LowObject = Object;
530 }
531 } else {
532 //
533 // Record it if Current RVA > Address
534 //
535 if (CandidateUpperAddress > Entry->Rva + Object->BaseAddress) {
536 CandidateUpperAddress = Entry->Rva + Object->BaseAddress;
537 UpperEntry = Entry;
538 UpperObject = Object;
539 }
540 }
541 continue;
542 }
543 //
544 // address match, return directly
545 //
546 *RetEntry = Entry;
547 *RetObject = Object;
548 return Address;
549 }
550 }
551
552 //
553 // No Match, provide latest symbol
554 //
555
556 if ((Address - CandidateLowerAddress) < EFI_DEBUGGER_MAX_SYMBOL_ADDRESS_DELTA_VALUE) {
557 //
558 // Check for lower address
559 //
560 if (((Type == EdbMatchSymbolTypeNearestAddress) &&
561 ((CandidateUpperAddress - Address) > (Address - CandidateLowerAddress))) ||
562 (Type == EdbMatchSymbolTypeLowerAddress)) {
563 //
564 // return nearest lower address
565 //
566 *RetEntry = LowEntry;
567 *RetObject = LowObject;
568 return CandidateLowerAddress;
569 }
570 }
571
572 if ((CandidateUpperAddress - Address) < EFI_DEBUGGER_MAX_SYMBOL_ADDRESS_DELTA_VALUE) {
573 //
574 // Check for upper address
575 //
576 if (((Type == EdbMatchSymbolTypeNearestAddress) &&
577 ((CandidateUpperAddress - Address) < (Address - CandidateLowerAddress))) ||
578 (Type == EdbMatchSymbolTypeUpperAddress)) {
579 //
580 // return nearest upper address
581 //
582 *RetEntry = UpperEntry;
583 *RetObject = UpperObject;
584 return CandidateUpperAddress;
585 }
586 }
587
588 //
589 // No match and nearest one, return NULL
590 //
591 return 0;
592 }
593
594 /**
595
596 Unload symbol file by name.
597
598 @param DebuggerPrivate - EBC Debugger private data structure
599 @param FileName - Symbol file name
600
601 @retval EFI_SUCCESS - unload symbol successfully
602
603 **/
604 EFI_STATUS
EdbUnloadSymbol(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN CHAR16 * FileName)605 EdbUnloadSymbol (
606 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
607 IN CHAR16 *FileName
608 )
609 {
610 EFI_DEBUGGER_SYMBOL_OBJECT *Object;
611 UINTN ObjectIndex;
612 UINTN Index;
613 EFI_DEBUGGER_SYMBOL_ENTRY *OldEntry;
614 UINTN OldEntryCount;
615 UINTN MaxEntryCount;
616 VOID **OldSourceBuffer;
617
618 //
619 // Find Symbol
620 //
621 Object = EdbFindSymbolFile (DebuggerPrivate, FileName, &ObjectIndex);
622 if (Object == NULL) {
623 EDBPrint (L"SymbolFile is not loaded!\n");
624 return EFI_DEBUG_CONTINUE;
625 }
626
627 //
628 // Record old data
629 //
630 Object = DebuggerPrivate->DebuggerSymbolContext.Object;
631 OldEntry = Object->Entry;
632 OldSourceBuffer = Object->SourceBuffer;
633 MaxEntryCount = Object->MaxEntryCount;
634 OldEntryCount = Object->EntryCount;
635
636 //
637 // Remove the matched Object
638 //
639 for (Index = ObjectIndex; Index < DebuggerPrivate->DebuggerSymbolContext.ObjectCount - 1; Index++) {
640 CopyMem (&Object[Index], &Object[Index + 1], sizeof(EFI_DEBUGGER_SYMBOL_OBJECT));
641 }
642 ZeroMem (&Object[Index], sizeof(Object[Index]));
643
644 //
645 // Move old data to new place
646 //
647 Object[Index].Entry = OldEntry;
648 Object[Index].SourceBuffer = OldSourceBuffer;
649 Object[Index].MaxEntryCount = MaxEntryCount;
650 DebuggerPrivate->DebuggerSymbolContext.ObjectCount --;
651
652 //
653 // Clean old entry data
654 //
655 for (Index = 0; Index < OldEntryCount; Index++) {
656 ZeroMem (&OldEntry[Index], sizeof(OldEntry[Index]));
657 }
658
659 //
660 // Free OldSourceBuffer
661 //
662 for (Index = 0; OldSourceBuffer[Index] != NULL; Index++) {
663 gBS->FreePool (OldSourceBuffer[Index]);
664 OldSourceBuffer[Index] = NULL;
665 }
666
667 return EFI_SUCCESS;
668 }
669
670 /**
671
672 Load symbol file by name.
673
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
678
679 @retval EFI_SUCCESS - load symbol successfully
680
681 **/
682 EFI_STATUS
EdbLoadSymbol(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN CHAR16 * FileName,IN UINTN BufferSize,IN VOID * Buffer)683 EdbLoadSymbol (
684 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
685 IN CHAR16 *FileName,
686 IN UINTN BufferSize,
687 IN VOID *Buffer
688 )
689 {
690 EFI_DEBUGGER_SYMBOL_OBJECT *Object;
691 EFI_STATUS Status;
692
693 //
694 // Check duplicated File
695 //
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"));
701 return Status;
702 }
703 }
704
705 //
706 // Check Count VS MaxCount
707 //
708 if (DebuggerPrivate->DebuggerSymbolContext.ObjectCount >= DebuggerPrivate->DebuggerSymbolContext.MaxObjectCount) {
709 //
710 // reallocate
711 // TBD
712 //
713 return EFI_OUT_OF_RESOURCES;
714 }
715
716 Object = &DebuggerPrivate->DebuggerSymbolContext.Object[DebuggerPrivate->DebuggerSymbolContext.ObjectCount];
717
718 //
719 // Init Object
720 //
721 Object->EntryCount = 0;
722 Object->MaxEntryCount = EFI_DEBUGGER_SYMBOL_ENTRY_MAX;
723
724 //
725 // Load SymbolEntry
726 //
727 DEBUG ((DEBUG_ERROR, "Symbol File: %s\n", FileName));
728 Status = EdbLoadSymbolEntry (Object, BufferSize, Buffer);
729 if (EFI_ERROR (Status)) {
730 return Status;
731 }
732
733 //
734 // Fill Object value
735 //
736 StrnCpyS (Object->Name, sizeof(Object->Name) / sizeof(CHAR16),
737 FileName, (sizeof(Object->Name) / sizeof(CHAR16)) - 1);
738 Object->BaseAddress = 0;
739
740 //
741 // Increase the object count
742 //
743 DebuggerPrivate->DebuggerSymbolContext.ObjectCount ++;
744
745 return EFI_SUCCESS;
746 }
747
748 /**
749
750 Located PDB path name in PE image.
751
752 @param ImageBase - base of PE to search
753
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.
756
757 **/
758 CHAR8 *
GetPdbPath(VOID * ImageBase)759 GetPdbPath (
760 VOID *ImageBase
761 )
762 {
763 CHAR8 *PdbPath;
764 UINT32 DirCount;
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;
772
773 //
774 // Init value
775 //
776 CodeViewEntryPointer = NULL;
777 PdbPath = NULL;
778 DosHdr = ImageBase;
779
780 //
781 // Check magic
782 //
783 if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
784 return NULL;
785 }
786 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *) ((UINT8 *) DosHdr + DosHdr->e_lfanew);
787 //
788 // Check Machine, filter for EBC
789 //
790 if (NtHdr->Pe32.FileHeader.Machine != EFI_IMAGE_MACHINE_EBC) {
791 //
792 // If not EBC, return NULL
793 //
794 return NULL;
795 }
796
797 //
798 // Get DirectoryEntry
799 // EBC spec says PE32+, but implementation uses PE32. So check dynamically here.
800 //
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]);
807 } else {
808 return NULL;
809 }
810 if (DirectoryEntry->VirtualAddress == 0) {
811 return NULL;
812 }
813 //
814 // Go through DirectoryEntry
815 //
816 for (DirCount = 0;
817 (DirCount < DirectoryEntry->Size / sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)) && CodeViewEntryPointer == NULL;
818 DirCount++
819 ) {
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) {
822 //
823 // Match DebugEntry, only CODEVIEW_SIGNATURE_NB10 and CODEVIEW_SIGNATURE_RSDS are supported.
824 //
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);
829 break;
830 case CODEVIEW_SIGNATURE_RSDS:
831 PdbPath = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);
832 break;
833 default:
834 break;
835 }
836 }
837 }
838
839 //
840 // Done successfully
841 //
842 return PdbPath;
843 }
844
845 /**
846
847 Check whether PDB file and MAP file have same name.
848
849 @param PdbFileName - PDB file name
850 @param MapFileName - MAP file name
851
852 @retval TRUE - PDB and MAP file name match
853 @retval FALSE - PDB and MAP file name not match
854
855 **/
856 BOOLEAN
MatchPdbAndMap(IN CHAR8 * PdbFileName,IN CHAR16 * MapFileName)857 MatchPdbAndMap (
858 IN CHAR8 *PdbFileName,
859 IN CHAR16 *MapFileName
860 )
861 {
862 UINTN PdbNameSize;
863 UINTN MapNameSize;
864 CHAR8 *PurePdbFileName;
865 UINTN Index;
866
867 //
868 // remove dir name
869 //
870 PurePdbFileName = PdbFileName;
871 for (Index = 0; PdbFileName[Index] != 0; Index++) {
872 if (PdbFileName[Index] == '\\') {
873 PurePdbFileName = &PdbFileName[Index + 1];
874 }
875 }
876 PdbFileName = PurePdbFileName;
877
878 //
879 // get size
880 //
881 PdbNameSize = AsciiStrLen (PdbFileName);
882 MapNameSize = StrLen (MapFileName);
883
884 if (PdbNameSize != MapNameSize) {
885 return FALSE;
886 }
887
888 //
889 // check the name
890 //
891 for (Index = 0; Index < MapNameSize - 4; Index++) {
892 if ((PdbFileName[Index] | 0x20) != (MapFileName[Index] | 0x20)) {
893 return FALSE;
894 }
895 }
896
897 return TRUE;
898 }
899
900 //
901 // BUGBUG: work-around start
902 //
903 typedef struct {
904 EFI_DEBUG_IMAGE_INFO *EfiDebugImageInfoTable;
905 volatile UINT32 UpdateStatus;
906 UINT32 TableSize;
907 } EFI_DEBUG_IMAGE_INFO_TABLE_HEADER_OLD;
908
909 EFI_DEBUG_IMAGE_INFO_TABLE_HEADER mDebugImageInfoTableHeader;
910
911 /**
912 For compatibility consideration, we handle 2 cases:
913
914 1) IA32:
915 Old: New:
916 +------------------------+ +------------------------+
917 | EfiDebugImageInfoTable | | UpdateStatus |
918 +------------------------+ +------------------------+
919 | UpdateStatus | | TableSize |
920 +------------------------+ +------------------------+
921 | TableSize | | EfiDebugImageInfoTable |
922 +------------------------+ +------------------------+
923
924 2) X64 and IPF:
925 Old: New:
926 +------------------------+ +------------------------+
927 | EfiDebugImageInfoTable | | UpdateStatus |
928 | | +------------------------+
929 | | | TableSize |
930 +------------------------+ +------------------------+
931 | UpdateStatus | | EfiDebugImageInfoTable |
932 +------------------------+ | |
933 | TableSize | | |
934 +------------------------+ +------------------------+
935
936 @param DebugImageInfoTableHeader Point to the EFI_DEBUG_IMAGE_INFO_TABLE_HEADER structure.
937
938 **/
939 VOID
EdbFixDebugImageInfoTable(IN OUT EFI_DEBUG_IMAGE_INFO_TABLE_HEADER ** DebugImageInfoTableHeader)940 EdbFixDebugImageInfoTable (
941 IN OUT EFI_DEBUG_IMAGE_INFO_TABLE_HEADER **DebugImageInfoTableHeader
942 )
943 {
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;
947
948 if ((*DebugImageInfoTableHeader)->UpdateStatus > 3) {
949 *DebugImageInfoTableHeader = &mDebugImageInfoTableHeader;
950 return ;
951 }
952
953 if ((*DebugImageInfoTableHeader)->TableSize % (EFI_PAGE_SIZE / (sizeof (VOID *))) != 0) {
954 *DebugImageInfoTableHeader = &mDebugImageInfoTableHeader;
955 return ;
956 }
957
958 return ;
959 }
960 //
961 // BUGBUG: work-around end
962 //
963
964 /**
965
966 Patch symbol RVA.
967
968 @param DebuggerPrivate - EBC Debugger private data structure
969 @param FileName - Symbol file name
970 @param SearchType - Search type for Object
971
972 @retval EFI_SUCCESS - Patch symbol RVA successfully
973 @retval EFI_NOT_FOUND - Symbol RVA base not found
974
975 **/
976 EFI_STATUS
EdbPatchSymbolRVA(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN CHAR16 * FileName,IN EDB_EBC_IMAGE_RVA_SEARCH_TYPE SearchType)977 EdbPatchSymbolRVA (
978 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
979 IN CHAR16 *FileName,
980 IN EDB_EBC_IMAGE_RVA_SEARCH_TYPE SearchType
981 )
982 {
983 EFI_STATUS Status;
984 UINTN ImageNumber;
985 EFI_DEBUG_IMAGE_INFO *ImageTable;
986 CHAR8 *PdbPath;
987 VOID *ImageBase;
988 VOID *CandidateImageBase;
989 EFI_DEBUGGER_SYMBOL_OBJECT *Object;
990
991 if (SearchType < 0 || SearchType >= EdbEbcImageRvaSearchTypeMax) {
992 return EFI_INVALID_PARAMETER;
993 }
994
995 //
996 // Get the related object
997 //
998 Object = EdbFindSymbolFile (DebuggerPrivate, FileName, NULL);
999 if (Object == NULL) {
1000 return EFI_NOT_FOUND;
1001 }
1002
1003 //
1004 // Try again to get DebugImageInfoTable
1005 //
1006 if (mDebuggerPrivate.DebugImageInfoTableHeader == NULL) {
1007 Status = EfiGetSystemConfigurationTable (
1008 &gEfiDebugImageInfoTableGuid,
1009 (VOID **) &mDebuggerPrivate.DebugImageInfoTableHeader
1010 );
1011 if (EFI_ERROR (Status)) {
1012 EDBPrint (L"DebugImageInfoTable not found!\n");
1013 return Status;
1014 }
1015 }
1016 DEBUG ((DEBUG_ERROR, "DebugImageInfoTableHeader: %x\n", mDebuggerPrivate.DebugImageInfoTableHeader));
1017
1018 //
1019 // BUGBUG: work-around start
1020 //
1021 EdbFixDebugImageInfoTable (&mDebuggerPrivate.DebugImageInfoTableHeader);
1022 //
1023 // BUGBUG: work-around end
1024 //
1025
1026 //
1027 // Go through DebugImageInfoTable for each Image
1028 //
1029 CandidateImageBase = NULL;
1030 ImageTable = mDebuggerPrivate.DebugImageInfoTableHeader->EfiDebugImageInfoTable;
1031 for (ImageNumber = 0; ImageNumber < mDebuggerPrivate.DebugImageInfoTableHeader->TableSize; ImageNumber++) {
1032 if (ImageTable[ImageNumber].NormalImage == NULL) {
1033 continue;
1034 }
1035 ImageBase = ImageTable[ImageNumber].NormalImage->LoadedImageProtocolInstance->ImageBase;
1036 //
1037 // Get PDB path
1038 //
1039 PdbPath = GetPdbPath (ImageBase);
1040 if (PdbPath == NULL) {
1041 continue;
1042 }
1043 //
1044 // Check PDB name
1045 //
1046 if (!MatchPdbAndMap (PdbPath, FileName)) {
1047 continue;
1048 }
1049 DEBUG ((DEBUG_ERROR, "ImageBase: %x\n", ImageBase));
1050
1051 //
1052 // Check SearchType
1053 //
1054 if (SearchType == EdbEbcImageRvaSearchTypeAny || SearchType == EdbEbcImageRvaSearchTypeFirst) {
1055 //
1056 // Assign base address and return
1057 //
1058 Object->BaseAddress = (UINTN)ImageBase;
1059 return EFI_SUCCESS;
1060 }
1061
1062 //
1063 // Get CandidateImageBase for EdbEbcImageRvaSearchTypeLast
1064 //
1065 CandidateImageBase = ImageBase;
1066 }
1067
1068 //
1069 // Check EdbEbcImageRvaSearchTypeLast
1070 //
1071 if (SearchType == EdbEbcImageRvaSearchTypeLast) {
1072 if (CandidateImageBase == NULL) {
1073 return EFI_NOT_FOUND;
1074 }
1075 //
1076 // Assign base address and return
1077 //
1078 Object->BaseAddress = (UINTN)CandidateImageBase;
1079 return EFI_SUCCESS;
1080 }
1081
1082 //
1083 // No match
1084 //
1085 return EFI_NOT_FOUND;
1086 }
1087
1088 /**
1089
1090 Check whether OBJ file and COD file have same name.
1091
1092 @param ObjFileName - OBJ file name
1093 @param CodFileName - COD file name
1094
1095 @retval TRUE - OBJ and COD file name match
1096 @retval FALSE - OBJ and COD file name not match
1097
1098 **/
1099 BOOLEAN
MatchObjAndCod(IN CHAR8 * ObjFileName,IN CHAR16 * CodFileName)1100 MatchObjAndCod (
1101 IN CHAR8 *ObjFileName,
1102 IN CHAR16 *CodFileName
1103 )
1104 {
1105 UINTN ObjNameSize;
1106 UINTN CodNameSize;
1107 CHAR8 *PureObjFileName;
1108 UINTN Index;
1109
1110 //
1111 // remove library name
1112 //
1113 PureObjFileName = ObjFileName;
1114 for (Index = 0; ObjFileName[Index] != 0; Index++) {
1115 if (ObjFileName[Index] == ':') {
1116 PureObjFileName = &ObjFileName[Index + 1];
1117 break;
1118 }
1119 }
1120 ObjFileName = PureObjFileName;
1121
1122 //
1123 // get size
1124 //
1125 ObjNameSize = AsciiStrLen (ObjFileName);
1126 CodNameSize = StrLen (CodFileName);
1127
1128 if (ObjNameSize != CodNameSize) {
1129 return FALSE;
1130 }
1131
1132 //
1133 // check the name
1134 //
1135 for (Index = 0; Index < CodNameSize - 4; Index++) {
1136 if ((ObjFileName[Index] | 0x20) != (CodFileName[Index] | 0x20)) {
1137 return FALSE;
1138 }
1139 }
1140
1141 return TRUE;
1142 }
1143
1144 typedef enum {
1145 EdbEbcCodParseStateUninitialized,
1146 EdbEbcCodParseStateSymbolInitialized,
1147 EdbEbcCodParseStateSymbolStart,
1148 EdbEbcCodParseStateSymbolEnd,
1149 EdbEbcCodParseStateMax,
1150 } EDB_EBC_COD_PARSE_STATE;
1151
1152 /**
1153
1154 The following code depends on the COD file generated by IEC compiler.
1155
1156 **/
1157
1158 /**
1159
1160 Load code by symbol by Iec.
1161
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
1167
1168 @return CodeBuffer
1169
1170 **/
1171 CHAR8 *
EdbLoadCodBySymbolByIec(IN CHAR8 * Name,IN VOID * Buffer,IN UINTN BufferSize,OUT UINTN * CodeBufferSize,OUT UINTN * FuncOffset)1172 EdbLoadCodBySymbolByIec (
1173 IN CHAR8 *Name,
1174 IN VOID *Buffer,
1175 IN UINTN BufferSize,
1176 OUT UINTN *CodeBufferSize,
1177 OUT UINTN *FuncOffset
1178 )
1179 {
1180 CHAR8 *LineBuffer;
1181 CHAR8 *FieldBuffer;
1182 VOID *BufferStart;
1183 VOID *BufferEnd;
1184 UINTN Offset;
1185 EDB_EBC_COD_PARSE_STATE CodParseState;
1186 CHAR8 Char[2];
1187
1188 //
1189 // Init
1190 //
1191 Char[0] = 9;
1192 Char[1] = 0;
1193 LineBuffer = AsciiStrGetNewTokenLine (Buffer, "\n\r");
1194 Offset = (UINTN)-1;
1195 BufferStart = NULL;
1196 BufferEnd = NULL;
1197 CodParseState = EdbEbcCodParseStateUninitialized;
1198
1199 //
1200 // Check each line
1201 //
1202 while (LineBuffer != NULL) {
1203 switch (CodParseState) {
1204 case EdbEbcCodParseStateUninitialized:
1205 //
1206 // check mark_begin, begin to check line after this match
1207 //
1208 if (AsciiStrCmp (LineBuffer, "; mark_begin;") == 0) {
1209 CodParseState = EdbEbcCodParseStateSymbolInitialized;
1210 }
1211 LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
1212 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1213 break;
1214
1215 case EdbEbcCodParseStateSymbolInitialized:
1216 //
1217 // check mark_end, not check line after this match
1218 //
1219 if (AsciiStrCmp (LineBuffer, "; mark_end;") == 0) {
1220 CodParseState = EdbEbcCodParseStateUninitialized;
1221 LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
1222 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1223 break;
1224 }
1225
1226 //
1227 // not check this line if the first char is as follows
1228 //
1229 if ((*LineBuffer == 0) ||
1230 (*LineBuffer == '$') ||
1231 (*LineBuffer == ';') ||
1232 (*LineBuffer == '_') ||
1233 (*LineBuffer == ' ')) {
1234 LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
1235 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1236 break;
1237 }
1238
1239 //
1240 // get function name, function name is followed by char 0x09.
1241 //
1242 FieldBuffer = AsciiStrGetNewTokenField (LineBuffer, Char);
1243 ASSERT (FieldBuffer != NULL);
1244 if (AsciiStriCmp (FieldBuffer, Name) == 0) {
1245 BufferStart = FieldBuffer;
1246 CodParseState = EdbEbcCodParseStateSymbolStart;
1247 }
1248 PatchForAsciiStrTokenAfter (FieldBuffer, 0x9);
1249
1250 //
1251 // Get next line
1252 //
1253 LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
1254 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1255 break;
1256
1257 case EdbEbcCodParseStateSymbolStart:
1258 //
1259 // check mark_end, if this match, means the function is found successfully.
1260 //
1261 if (AsciiStrCmp (LineBuffer, "; mark_end;") == 0) {
1262 CodParseState = EdbEbcCodParseStateSymbolEnd;
1263 //
1264 // prepare CodeBufferSize, FuncOffset, and FuncStart to return
1265 //
1266 BufferEnd = LineBuffer + sizeof("; mark_end;") - 1;
1267 *CodeBufferSize = (UINTN)BufferEnd - (UINTN)BufferStart;
1268 *FuncOffset = Offset;
1269 PatchForAsciiStrTokenAfter (LineBuffer, '\n');
1270 return BufferStart;
1271 }
1272
1273 //
1274 // Get function offset
1275 //
1276 if ((Offset == (UINTN)-1) &&
1277 (*LineBuffer == ' ')) {
1278 FieldBuffer = AsciiStrGetNewTokenField (LineBuffer + 2, " ");
1279 Offset = AsciiXtoi (FieldBuffer);
1280 PatchForAsciiStrTokenAfter (FieldBuffer, ' ');
1281 }
1282
1283 //
1284 // Get next line
1285 //
1286 LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
1287 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1288 break;
1289
1290 case EdbEbcCodParseStateSymbolEnd:
1291 break;
1292
1293 default:
1294 break;
1295 }
1296 }
1297
1298 //
1299 // no function found
1300 //
1301 return NULL;
1302 }
1303
1304 /**
1305
1306 Load code by symbol.
1307
1308 @param Name - Symbol file name
1309 @param Buffer - Symbol file buffer
1310 @param BufferSize - Symbol file buffer size
1311 @param CodeBufferSize - Code buffer size
1312 @param FuncOffset - Code funcion offset
1313
1314 @return CodeBuffer
1315
1316 **/
1317 CHAR8 *
EdbLoadCodBySymbol(IN CHAR8 * Name,IN VOID * Buffer,IN UINTN BufferSize,OUT UINTN * CodeBufferSize,OUT UINTN * FuncOffset)1318 EdbLoadCodBySymbol (
1319 IN CHAR8 *Name,
1320 IN VOID *Buffer,
1321 IN UINTN BufferSize,
1322 OUT UINTN *CodeBufferSize,
1323 OUT UINTN *FuncOffset
1324 )
1325 {
1326 //
1327 // COD file format depends on the compiler.
1328 //
1329 // It is possible to check the different COD file format in this routine.
1330 // Now only IEC is supported.
1331 //
1332 return EdbLoadCodBySymbolByIec (Name, Buffer, BufferSize, CodeBufferSize, FuncOffset);
1333 }
1334
1335 /**
1336
1337 Find code from object.
1338
1339 @param DebuggerPrivate EBC Debugger private data structure
1340 @param Object - Symbol object
1341 @param FileName - File name
1342
1343 **/
1344 VOID *
EdbFindCodeFromObject(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN EFI_DEBUGGER_SYMBOL_OBJECT * Object,IN CHAR16 * FileName)1345 EdbFindCodeFromObject (
1346 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
1347 IN EFI_DEBUGGER_SYMBOL_OBJECT *Object,
1348 IN CHAR16 *FileName
1349 )
1350 {
1351 UINTN EntryIndex;
1352
1353 //
1354 // Go througn each Entry in this Object
1355 //
1356 for (EntryIndex = 0; EntryIndex < Object->EntryCount; EntryIndex++) {
1357 //
1358 // This check is for Function only
1359 //
1360 if ((Object->Entry[EntryIndex].Type != EfiDebuggerSymbolFunction) &&
1361 (Object->Entry[EntryIndex].Type != EfiDebuggerSymbolStaticFunction)) {
1362 continue;
1363 }
1364 //
1365 // Skip match varbss_init function, because they has no source code
1366 //
1367 if (AsciiStrnCmp (Object->Entry[EntryIndex].Name, "varbss_init", sizeof("varbss_init") - 1) == 0) {
1368 continue;
1369 }
1370 //
1371 // check the name
1372 //
1373 if (!MatchObjAndCod (Object->Entry[EntryIndex].ObjName, FileName)) {
1374 continue;
1375 }
1376 //
1377 // found it, return source buffer
1378 //
1379 if (Object->Entry[EntryIndex].CodBuffer != NULL) {
1380 return Object->Entry[EntryIndex].SourceBuffer;
1381 }
1382 }
1383
1384 //
1385 // not found
1386 //
1387 return NULL;
1388 }
1389
1390 /**
1391
1392 Load code.
1393
1394 @param DebuggerPrivate - EBC Debugger private data structure
1395 @param MapFileName - Symbol file name
1396 @param FileName - Code file name
1397 @param BufferSize - Code file buffer size
1398 @param Buffer - Code file buffer
1399
1400 @retval EFI_SUCCESS - Code loaded successfully
1401
1402 **/
1403 EFI_STATUS
EdbLoadCode(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN CHAR16 * MapFileName,IN CHAR16 * FileName,IN UINTN BufferSize,IN VOID * Buffer)1404 EdbLoadCode (
1405 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
1406 IN CHAR16 *MapFileName,
1407 IN CHAR16 *FileName,
1408 IN UINTN BufferSize,
1409 IN VOID *Buffer
1410 )
1411 {
1412 EFI_DEBUGGER_SYMBOL_OBJECT *Object;
1413 UINTN ObjectIndex;
1414 UINTN EntryIndex;
1415 VOID *SourceBuffer;
1416 EFI_STATUS Status;
1417
1418 //
1419 // Find Symbol
1420 //
1421 Object = EdbFindSymbolFile (DebuggerPrivate, MapFileName, &ObjectIndex);
1422 if (Object == NULL) {
1423 EDBPrint (L"SymbolFile is not loaded!\n");
1424 return EFI_NOT_FOUND;
1425 } else {
1426 //
1427 // Check duplicated File
1428 //
1429 SourceBuffer = EdbFindCodeFromObject (DebuggerPrivate, Object, FileName);
1430 if (SourceBuffer != NULL) {
1431 //
1432 // unnload duplicated code
1433 //
1434 Status = EdbUnloadCode (DebuggerPrivate, MapFileName, FileName, &SourceBuffer);
1435 if (EFI_ERROR(Status)) {
1436 DEBUG ((DEBUG_ERROR, "Unload Duplicated Code File Error!\n"));
1437 return Status;
1438 }
1439 Status = EdbDeleteCodeBuffer (DebuggerPrivate, MapFileName, FileName, SourceBuffer);
1440 if (EFI_ERROR(Status)) {
1441 DEBUG ((DEBUG_ERROR, "Delete Duplicated Code File Error!\n"));
1442 return Status;
1443 }
1444 }
1445 }
1446
1447 //
1448 // Go through each SymbolEntry
1449 //
1450 for (EntryIndex = 0; EntryIndex < Object->EntryCount; EntryIndex++) {
1451 //
1452 // load symbol for function only
1453 //
1454 if ((Object->Entry[EntryIndex].Type != EfiDebuggerSymbolFunction) &&
1455 (Object->Entry[EntryIndex].Type != EfiDebuggerSymbolStaticFunction)) {
1456 continue;
1457 }
1458 //
1459 // skip varbss_init
1460 //
1461 if (AsciiStrnCmp (Object->Entry[EntryIndex].Name, "varbss_init", sizeof("varbss_init") - 1) == 0) {
1462 continue;
1463 }
1464 //
1465 // Check the name
1466 //
1467 if (!MatchObjAndCod (Object->Entry[EntryIndex].ObjName, FileName)) {
1468 continue;
1469 }
1470 //
1471 // load code for this symbol
1472 //
1473 Object->Entry[EntryIndex].CodBuffer = EdbLoadCodBySymbol (
1474 Object->Entry[EntryIndex].Name,
1475 Buffer,
1476 BufferSize,
1477 &Object->Entry[EntryIndex].CodBufferSize,
1478 &Object->Entry[EntryIndex].FuncOffsetBase
1479 );
1480 if (Object->Entry[EntryIndex].CodBuffer != NULL) {
1481 Object->Entry[EntryIndex].SourceBuffer = Buffer;
1482 }
1483 }
1484
1485 //
1486 // patch end '\0' for each code buffer
1487 //
1488 for (EntryIndex = 0; EntryIndex < Object->EntryCount; EntryIndex++) {
1489 if (Object->Entry[EntryIndex].CodBuffer != NULL) {
1490 *((UINT8 *)Object->Entry[EntryIndex].CodBuffer + Object->Entry[EntryIndex].CodBufferSize) = 0;
1491 DEBUG ((DEBUG_ERROR, " CodeSymbol: %a, FuncOffset: 0x05%x\n", Object->Entry[EntryIndex].Name, Object->Entry[EntryIndex].FuncOffsetBase));
1492 // DEBUG ((DEBUG_ERROR, " [CODE]:\n%a\n", Object->Entry[EntryIndex].CodBuffer));
1493 }
1494 }
1495
1496 //
1497 // Done
1498 //
1499 return EFI_SUCCESS;
1500 }
1501
1502 /**
1503
1504 Unload code.
1505
1506 @param DebuggerPrivate - EBC Debugger private data structure
1507 @param MapFileName - Symbol file name
1508 @param FileName - Code file name
1509 @param Buffer - Code file buffer
1510
1511 @retval EFI_SUCCESS - Code unloaded successfully
1512
1513 **/
1514 EFI_STATUS
EdbUnloadCode(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN CHAR16 * MapFileName,IN CHAR16 * FileName,OUT VOID ** Buffer)1515 EdbUnloadCode (
1516 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
1517 IN CHAR16 *MapFileName,
1518 IN CHAR16 *FileName,
1519 OUT VOID **Buffer
1520 )
1521 {
1522 EFI_DEBUGGER_SYMBOL_OBJECT *Object;
1523 UINTN ObjectIndex;
1524 UINTN EntryIndex;
1525
1526 //
1527 // Find Symbol
1528 //
1529 Object = EdbFindSymbolFile (DebuggerPrivate, MapFileName, &ObjectIndex);
1530 if (Object == NULL) {
1531 EDBPrint (L"SymbolFile is not loaded!\n");
1532 return EFI_NOT_FOUND;
1533 }
1534
1535 //
1536 // Find code
1537 //
1538 *Buffer = EdbFindCodeFromObject (DebuggerPrivate, Object, FileName);
1539 if (*Buffer == NULL) {
1540 EDBPrint (L"CodeFile is not loaded!\n");
1541 return EFI_NOT_FOUND;
1542 }
1543
1544 //
1545 // go through each entry
1546 //
1547 for (EntryIndex = 0; EntryIndex < Object->EntryCount; EntryIndex++) {
1548 if ((Object->Entry[EntryIndex].Type != EfiDebuggerSymbolFunction) &&
1549 (Object->Entry[EntryIndex].Type != EfiDebuggerSymbolStaticFunction)) {
1550 continue;
1551 }
1552 if (AsciiStrnCmp (Object->Entry[EntryIndex].Name, "varbss_init", sizeof("varbss_init") - 1) == 0) {
1553 continue;
1554 }
1555 if (!MatchObjAndCod (Object->Entry[EntryIndex].ObjName, FileName)) {
1556 continue;
1557 }
1558 //
1559 // clean up the buffer
1560 //
1561 Object->Entry[EntryIndex].CodBuffer = NULL;
1562 Object->Entry[EntryIndex].CodBufferSize = 0;
1563 Object->Entry[EntryIndex].FuncOffsetBase = 0;
1564 Object->Entry[EntryIndex].SourceBuffer = NULL;
1565 }
1566
1567 //
1568 // Done
1569 //
1570 return EFI_SUCCESS;
1571 }
1572
1573 /**
1574
1575 Add code buffer.
1576
1577 @param DebuggerPrivate - EBC Debugger private data structure
1578 @param MapFileName - Symbol file name
1579 @param CodeFileName - Code file name
1580 @param SourceBufferSize- Code buffer size
1581 @param SourceBuffer - Code buffer
1582
1583 @retval EFI_SUCCESS - CodeBuffer added successfully
1584
1585 **/
1586 EFI_STATUS
EdbAddCodeBuffer(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN CHAR16 * MapFileName,IN CHAR16 * CodeFileName,IN UINTN SourceBufferSize,IN VOID * SourceBuffer)1587 EdbAddCodeBuffer (
1588 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
1589 IN CHAR16 *MapFileName,
1590 IN CHAR16 *CodeFileName,
1591 IN UINTN SourceBufferSize,
1592 IN VOID *SourceBuffer
1593 )
1594 {
1595 UINTN Index;
1596 EFI_DEBUGGER_SYMBOL_OBJECT *Object;
1597
1598 //
1599 // Find Symbol
1600 //
1601 Object = EdbFindSymbolFile (DebuggerPrivate, MapFileName, NULL);
1602 if (Object == NULL) {
1603 EDBPrint (L"SymbolFile is not loaded!\n");
1604 return EFI_NOT_FOUND;
1605 }
1606
1607 //
1608 // Add it to last entry
1609 //
1610 for (Index = 0; Object->SourceBuffer[Index] != NULL; Index++) {
1611 ;
1612 }
1613 Object->SourceBuffer[Index] = SourceBuffer;
1614
1615 return EFI_SUCCESS;
1616 }
1617
1618 /**
1619
1620 Delete code buffer.
1621
1622 @param DebuggerPrivate - EBC Debugger private data structure
1623 @param MapFileName - Symbol file name
1624 @param CodeFileName - Code file name
1625 @param SourceBuffer - Code buffer
1626
1627 @retval EFI_SUCCESS - CodeBuffer deleted successfully
1628
1629 **/
1630 EFI_STATUS
EdbDeleteCodeBuffer(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN CHAR16 * MapFileName,IN CHAR16 * CodeFileName,IN VOID * SourceBuffer)1631 EdbDeleteCodeBuffer (
1632 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
1633 IN CHAR16 *MapFileName,
1634 IN CHAR16 *CodeFileName,
1635 IN VOID *SourceBuffer
1636 )
1637 {
1638 UINTN Index;
1639 EFI_DEBUGGER_SYMBOL_OBJECT *Object;
1640
1641 //
1642 // Find Symbol
1643 //
1644 Object = EdbFindSymbolFile (DebuggerPrivate, MapFileName, NULL);
1645 if (Object == NULL) {
1646 EDBPrint (L"SymbolFile is not loaded!\n");
1647 return EFI_NOT_FOUND;
1648 }
1649
1650 for (Index = 0; Object->SourceBuffer[Index] != NULL; Index++) {
1651 //
1652 // free the buffer if match
1653 //
1654 if (Object->SourceBuffer[Index] == SourceBuffer) {
1655 gBS->FreePool (SourceBuffer);
1656 break;
1657 }
1658 }
1659
1660 if (Object->SourceBuffer[Index] == NULL) {
1661 //
1662 // not return NOT_FOUND
1663 //
1664 return EFI_SUCCESS;
1665 }
1666
1667 //
1668 // remove the entry
1669 //
1670 Object->SourceBuffer[Index] = NULL;
1671 for (Index = Index + 1; Object->SourceBuffer[Index] != NULL; Index++) {
1672 Object->SourceBuffer[Index - 1] = Object->SourceBuffer[Index];
1673 }
1674 Object->SourceBuffer[Index - 1] = NULL;
1675
1676 return EFI_SUCCESS;
1677 }
1678
1679 /**
1680
1681 Find the symbol string according to address.
1682
1683 @param Address - Symbol address
1684
1685 @return Symbol string
1686
1687 **/
1688 CHAR8 *
FindSymbolStr(IN UINTN Address)1689 FindSymbolStr (
1690 IN UINTN Address
1691 )
1692 {
1693 UINTN ObjectIndex;
1694 EFI_DEBUGGER_SYMBOL_OBJECT *Object;
1695 UINTN EntryIndex;
1696 EFI_DEBUGGER_SYMBOL_ENTRY *Entry;
1697
1698 //
1699 // need we display symbol
1700 //
1701 if (!mDebuggerPrivate.DebuggerSymbolContext.DisplaySymbol) {
1702 return NULL;
1703 }
1704
1705 //
1706 // Go through each object and entry
1707 //
1708 Object = mDebuggerPrivate.DebuggerSymbolContext.Object;
1709 for (ObjectIndex = 0; ObjectIndex < mDebuggerPrivate.DebuggerSymbolContext.ObjectCount; ObjectIndex++) {
1710 Entry = Object[ObjectIndex].Entry;
1711 for (EntryIndex = 0; EntryIndex < Object[ObjectIndex].EntryCount; EntryIndex++) {
1712 //
1713 // if Address match, return Name
1714 //
1715 if (Address == (Entry[EntryIndex].Rva + Object[ObjectIndex].BaseAddress)) {
1716 return Entry[EntryIndex].Name;
1717 }
1718 }
1719 }
1720
1721 //
1722 // not found
1723 //
1724 return NULL;
1725 }
1726
1727 /**
1728
1729 Get line number and offset from this line in code file.
1730
1731 @param Line - Line buffer in code file
1732 @param Offset - Offset to functin entry
1733
1734 @return Line number
1735
1736 **/
1737 UINTN
EdbGetLineNumberAndOffsetFromThisLine(IN VOID * Line,OUT UINTN * Offset)1738 EdbGetLineNumberAndOffsetFromThisLine (
1739 IN VOID *Line,
1740 OUT UINTN *Offset
1741 )
1742 {
1743 UINTN LineNumber;
1744 CHAR8 *LineBuffer;
1745 CHAR8 *FieldBuffer;
1746
1747 LineNumber = (UINTN)-1;
1748 LineBuffer = Line;
1749 *Offset = (UINTN)-1;
1750
1751 while (LineBuffer != NULL) {
1752 //
1753 // Check candidate
1754 //
1755 if (*LineBuffer != ' ') {
1756 return (UINTN)-1;
1757 }
1758
1759 //
1760 // Get Offset
1761 //
1762 if (*(LineBuffer + 2) != ' ') {
1763 if (*Offset == (UINTN)-1) {
1764 FieldBuffer = AsciiStrGetNewTokenField (LineBuffer + 2, " ");
1765 *Offset = AsciiXtoi (FieldBuffer);
1766 PatchForAsciiStrTokenAfter (FieldBuffer, ' ');
1767 }
1768 }
1769
1770 //
1771 // 1. assembly instruction
1772 //
1773 FieldBuffer = AsciiStrGetNewTokenField (LineBuffer, ":");
1774 //
1775 // 2. file path
1776 //
1777 FieldBuffer = AsciiStrGetNextTokenField (":");
1778 PatchForAsciiStrTokenBefore (FieldBuffer, ':');
1779 if (FieldBuffer == NULL) {
1780 //
1781 // candidate found
1782 //
1783 LineNumber = 0;
1784 LineBuffer = AsciiStrGetNextTokenLine ("\n");
1785 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1786 continue;
1787 }
1788 //
1789 // 3. line number
1790 //
1791 FieldBuffer = AsciiStrGetNextTokenField (":");
1792 PatchForAsciiStrTokenBefore (FieldBuffer, ':');
1793 if (FieldBuffer == NULL) {
1794 //
1795 // impossible, TBD?
1796 //
1797 LineBuffer = AsciiStrGetNextTokenLine ("\n");
1798 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1799 continue;
1800 }
1801
1802 LineNumber = AsciiAtoi (FieldBuffer);
1803 //
1804 // Not patch after
1805 //
1806
1807 return LineNumber;
1808 }
1809
1810 return (UINTN)-1;
1811 }
1812
1813 typedef enum {
1814 EdbEbcLineSearchTypeAny,
1815 EdbEbcLineSearchTypeFirst,
1816 EdbEbcLineSearchTypeLast,
1817 EdbEbcLineSearchTypeMax,
1818 } EDB_EBC_LINE_SEARCH_TYPE;
1819
1820 /**
1821
1822 Get line number from this code file.
1823
1824 @param Entry - Symbol entry
1825 @param FuncOffset - Offset to functin entry
1826 @param SearchType - Search type for the code
1827
1828 @return Line number
1829
1830 **/
1831 UINTN
EdbGetLineNumberFromCode(IN EFI_DEBUGGER_SYMBOL_ENTRY * Entry,IN UINTN FuncOffset,IN EDB_EBC_LINE_SEARCH_TYPE SearchType)1832 EdbGetLineNumberFromCode (
1833 IN EFI_DEBUGGER_SYMBOL_ENTRY *Entry,
1834 IN UINTN FuncOffset,
1835 IN EDB_EBC_LINE_SEARCH_TYPE SearchType
1836 )
1837 {
1838 CHAR8 *LineBuffer;
1839 UINTN LineNumber;
1840 UINTN Offset;
1841 UINTN CandidateLineNumber;
1842 UINTN CandidateOffset;
1843
1844 if (SearchType < 0 || SearchType >= EdbEbcLineSearchTypeMax) {
1845 return (UINTN)-1;
1846 }
1847
1848 LineNumber = (UINTN)-1;
1849 CandidateLineNumber = (UINTN)-1;
1850 CandidateOffset = (UINTN)-1;
1851 LineBuffer = AsciiStrGetNewTokenLine (Entry->CodBuffer, "\n");
1852 while (LineBuffer != NULL) {
1853 if (*LineBuffer != ' ') {
1854 LineBuffer = AsciiStrGetNextTokenLine ("\n");
1855 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1856 continue;
1857 }
1858
1859 //
1860 // Get Info
1861 //
1862 LineNumber = EdbGetLineNumberAndOffsetFromThisLine (LineBuffer, &Offset);
1863
1864 //
1865 // Check offset
1866 //
1867 if (Offset != FuncOffset) {
1868 //
1869 // Check last offset match
1870 //
1871 if (CandidateOffset == FuncOffset) {
1872 if (SearchType == EdbEbcLineSearchTypeLast) {
1873 PatchForAsciiStrTokenAfter (LineBuffer, '\n');
1874 if (CandidateLineNumber != LineNumber) {
1875 return CandidateLineNumber;
1876 } else {
1877 return (UINTN)-1;
1878 }
1879 } else {
1880 //
1881 // impossible, TBD?
1882 //
1883 }
1884 }
1885
1886 LineBuffer = AsciiStrGetNextTokenLine ("\n");
1887 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1888 CandidateLineNumber = LineNumber;
1889 continue;
1890 }
1891
1892 //
1893 // Offset match, more check
1894 //
1895 if (SearchType == EdbEbcLineSearchTypeAny) {
1896 PatchForAsciiStrTokenAfter (LineBuffer, '\n');
1897 return LineNumber;
1898 }
1899
1900 if (SearchType == EdbEbcLineSearchTypeFirst) {
1901 //
1902 // Check last line
1903 //
1904 PatchForAsciiStrTokenAfter (LineBuffer, '\n');
1905 if (CandidateLineNumber != LineNumber) {
1906 return LineNumber;
1907 } else {
1908 return (UINTN)-1;
1909 }
1910 }
1911
1912 CandidateLineNumber = LineNumber;
1913 CandidateOffset = Offset;
1914
1915 LineBuffer = AsciiStrGetNextTokenLine ("\n");
1916 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1917 }
1918
1919 //
1920 // Check last offset match
1921 //
1922 if (CandidateOffset == FuncOffset) {
1923 if (SearchType == EdbEbcLineSearchTypeLast) {
1924 return CandidateLineNumber;
1925 }
1926 }
1927
1928 return (UINTN)-1;
1929 }
1930
1931 /**
1932
1933 Get the source string from this code file by line.
1934
1935 @param Entry - Symbol entry
1936 @param LineNumber - line number
1937 @param FuncEnd - Function end
1938
1939 @return Funtion start
1940
1941 **/
1942 VOID *
EdbGetSourceStrFromCodeByLine(IN EFI_DEBUGGER_SYMBOL_ENTRY * Entry,IN UINTN LineNumber,IN VOID ** FuncEnd)1943 EdbGetSourceStrFromCodeByLine (
1944 IN EFI_DEBUGGER_SYMBOL_ENTRY *Entry,
1945 IN UINTN LineNumber,
1946 IN VOID **FuncEnd
1947 )
1948 {
1949 CHAR8 *LineBuffer;
1950 CHAR8 *FieldBuffer;
1951 VOID *FuncStart;
1952 UINTN Number;
1953
1954 FuncStart = NULL;
1955 LineBuffer = AsciiStrGetNewTokenLine (Entry->CodBuffer, "\n");
1956 while (LineBuffer != NULL) {
1957 if (*LineBuffer != ';') {
1958 if (FuncStart != NULL) {
1959 //
1960 // Over
1961 //
1962 *FuncEnd = LineBuffer - 1;
1963 PatchForAsciiStrTokenAfter (LineBuffer, '\n');
1964 return FuncStart;
1965 }
1966 LineBuffer = AsciiStrGetNextTokenLine ("\n");
1967 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1968 continue;
1969 }
1970
1971 //
1972 // Check LineNumber
1973 //
1974 FieldBuffer = AsciiStrGetNewTokenField (LineBuffer + 1, " ");
1975 Number = AsciiAtoi (FieldBuffer);
1976 PatchForAsciiStrTokenAfter (FieldBuffer, ' ');
1977 if (Number != LineNumber) {
1978 LineBuffer = AsciiStrGetNextTokenLine ("\n");
1979 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1980 continue;
1981 }
1982
1983 //
1984 // Line match, get line number
1985 //
1986 if (FuncStart == NULL) {
1987 FuncStart = LineBuffer;
1988 }
1989
1990 LineBuffer = AsciiStrGetNextTokenLine ("\n");
1991 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1992 }
1993
1994 return NULL;
1995 }
1996
1997 /**
1998
1999 Get source string from this code file.
2000
2001 @param Entry - Symbol entry
2002 @param FuncOffset - Offset to functin entry
2003 @param FuncEnd - Function end
2004
2005 @retval Funtion start
2006
2007 **/
2008 VOID *
EdbGetSourceStrFromCode(IN EFI_DEBUGGER_SYMBOL_ENTRY * Entry,IN UINTN FuncOffset,IN VOID ** FuncEnd)2009 EdbGetSourceStrFromCode (
2010 IN EFI_DEBUGGER_SYMBOL_ENTRY *Entry,
2011 IN UINTN FuncOffset,
2012 IN VOID **FuncEnd
2013 )
2014 {
2015 UINTN LineNumber;
2016
2017 //
2018 // Only search the last line, then display
2019 //
2020 LineNumber = EdbGetLineNumberFromCode (Entry, FuncOffset, EdbEbcLineSearchTypeLast);
2021 if (LineNumber == (UINTN)-1) {
2022 return NULL;
2023 }
2024
2025 return EdbGetSourceStrFromCodeByLine (Entry, LineNumber, FuncEnd);
2026 }
2027
2028 /**
2029
2030 Print source.
2031
2032 @param Address - Instruction address
2033 @param IsPrint - Whether need to print
2034
2035 @retval 1 - find the source
2036 @retval 0 - not find the source
2037
2038 **/
2039 UINTN
EdbPrintSource(IN UINTN Address,IN BOOLEAN IsPrint)2040 EdbPrintSource (
2041 IN UINTN Address,
2042 IN BOOLEAN IsPrint
2043 )
2044 {
2045 UINTN SymbolAddress;
2046 EFI_DEBUGGER_SYMBOL_OBJECT *RetObject;
2047 EFI_DEBUGGER_SYMBOL_ENTRY *RetEntry;
2048 UINTN FuncOffset;
2049 UINT8 *FuncStart;
2050 UINT8 *FuncEnd;
2051 UINT8 *FuncIndex;
2052 CHAR8 Buffer[EFI_DEBUG_MAX_PRINT_BUFFER];
2053 UINTN BufferSize;
2054
2055 //
2056 // need we display symbol
2057 //
2058 if (!mDebuggerPrivate.DebuggerSymbolContext.DisplaySymbol) {
2059 return 0 ;
2060 }
2061
2062 //
2063 // find the symbol address
2064 //
2065 SymbolAddress = EbdFindSymbolAddress (
2066 Address,
2067 EdbMatchSymbolTypeLowerAddress,
2068 &RetObject,
2069 &RetEntry
2070 );
2071 if (SymbolAddress == 0) {
2072 return 0 ;
2073 }
2074
2075 FuncOffset = Address - SymbolAddress + RetEntry->FuncOffsetBase;
2076
2077 //
2078 // Get Func String
2079 //
2080 FuncStart = EdbGetSourceStrFromCode (RetEntry, FuncOffset, (VOID**) &FuncEnd);
2081 if (FuncStart == NULL) {
2082 return 0 ;
2083 }
2084
2085 //
2086 // check whether need to real print
2087 //
2088 if (!IsPrint) {
2089 return 1;
2090 }
2091
2092 *(UINT8 *)FuncEnd = 0;
2093
2094 //
2095 // seperate buffer by \n, so that \r can be added.
2096 //
2097 FuncIndex = FuncStart;
2098 while (*FuncIndex != 0) {
2099 if (*FuncIndex == '\n') {
2100 if ((FuncIndex - FuncStart) < (EFI_DEBUG_MAX_PRINT_BUFFER - 3)) {
2101 BufferSize = FuncIndex - FuncStart;
2102 } else {
2103 BufferSize = EFI_DEBUG_MAX_PRINT_BUFFER - 3;
2104 }
2105 if (BufferSize != 0) {
2106 CopyMem (Buffer, FuncStart, BufferSize);
2107 }
2108 Buffer[BufferSize] = 0;
2109 EDBPrint (L"%a\n", Buffer);
2110 FuncStart = FuncIndex + 1;
2111 FuncIndex = FuncStart;
2112 } else {
2113 FuncIndex ++;
2114 }
2115 }
2116
2117 //
2118 // Patch the end
2119 //
2120 *(UINT8 *)FuncEnd = '\n';
2121
2122 return 1 ;
2123 }
2124
2125 /**
2126
2127 Get Mapfile and SymbolName from one symbol format: [MapFileName:]SymbolName.
2128
2129 @param Symbol - whole Symbol name
2130 @param MapfileName - the mapfile name in the symbol
2131 @param SymbolName - the symbol name in the symbol
2132
2133 **/
2134 VOID
GetMapfileAndSymbol(IN CHAR16 * Symbol,OUT CHAR16 ** MapfileName,OUT CHAR16 ** SymbolName)2135 GetMapfileAndSymbol (
2136 IN CHAR16 *Symbol,
2137 OUT CHAR16 **MapfileName,
2138 OUT CHAR16 **SymbolName
2139 )
2140 {
2141 CHAR16 *Ch;
2142
2143 *MapfileName = NULL;
2144 *SymbolName = Symbol;
2145
2146 for (Ch = Symbol; *Ch != 0; Ch++) {
2147 //
2148 // Find split char
2149 //
2150 if (*Ch == L':') {
2151 *MapfileName = Symbol;
2152 *Ch = 0;
2153 *SymbolName = Ch + 1;
2154 break;
2155 }
2156 }
2157
2158 return ;
2159 }
2160
2161 /**
2162
2163 Convert a symbol to an address.
2164
2165 @param Symbol - Symbol name
2166 @param Address - Symbol address
2167
2168 @retval EFI_SUCCESS - symbol found and address returned.
2169 @retval EFI_NOT_FOUND - symbol not found
2170 @retval EFI_NO_MAPPING - duplicated symbol not found
2171
2172 **/
2173 EFI_STATUS
Symboltoi(IN CHAR16 * Symbol,OUT UINTN * Address)2174 Symboltoi (
2175 IN CHAR16 *Symbol,
2176 OUT UINTN *Address
2177 )
2178 {
2179 UINTN ObjectIndex;
2180 EFI_DEBUGGER_SYMBOL_OBJECT *Object;
2181 UINTN EntryIndex;
2182 EFI_DEBUGGER_SYMBOL_ENTRY *Entry;
2183 CHAR16 *SymbolName;
2184 CHAR16 *MapfileName;
2185
2186 //
2187 // Split one symbol to mapfile name and symbol name
2188 //
2189 GetMapfileAndSymbol (Symbol, &MapfileName, &SymbolName);
2190
2191 *Address = 0;
2192 //
2193 // Go through each object
2194 //
2195 Object = mDebuggerPrivate.DebuggerSymbolContext.Object;
2196 for (ObjectIndex = 0; ObjectIndex < mDebuggerPrivate.DebuggerSymbolContext.ObjectCount; ObjectIndex++) {
2197 //
2198 // Check MapfileName
2199 //
2200 if ((MapfileName != NULL) && (StriCmp (Object[ObjectIndex].Name, MapfileName) != 0)) {
2201 continue;
2202 }
2203 //
2204 // Go through each entry
2205 //
2206 Entry = Object[ObjectIndex].Entry;
2207 for (EntryIndex = 0; EntryIndex < Object[ObjectIndex].EntryCount; EntryIndex++) {
2208 //
2209 // Check SymbolName (case sensitive)
2210 //
2211 if (StrCmpUnicodeAndAscii (SymbolName, Entry[EntryIndex].Name) == 0) {
2212 if ((*Address != 0) && (MapfileName == NULL)) {
2213 //
2214 // Find the duplicated symbol
2215 //
2216 EDBPrint (L"Duplicated Symbol found!\n");
2217 return EFI_NO_MAPPING;
2218 } else {
2219 //
2220 // record Address
2221 //
2222 *Address = (Entry[EntryIndex].Rva + Object[ObjectIndex].BaseAddress);
2223 }
2224 }
2225 }
2226 }
2227
2228 if (*Address == 0) {
2229 //
2230 // Not found
2231 //
2232 return EFI_NOT_FOUND;
2233 }
2234
2235 return EFI_SUCCESS;
2236 }
2237