]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSymbol.c
9573c43a9d5d4c890279351f54424915158b11c0
[mirror_edk2.git] / MdeModulePkg / Universal / EbcDxe / EbcDebugger / EdbSymbol.c
1 /*++
2
3 Copyright (c) 2007, 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
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 Module Name:
13
14 EdbSymbol.c
15
16 Abstract:
17
18
19 --*/
20
21 #include "Edb.h"
22
23 EFI_STATUS
24 EdbLoadSymbolSingleEntry (
25 IN EFI_DEBUGGER_SYMBOL_OBJECT *Object,
26 IN CHAR8 *Name,
27 IN CHAR8 *ObjName,
28 IN UINTN Address,
29 IN EFI_DEBUGGER_SYMBOL_TYPE Type
30 )
31 /*++
32
33 Routine Description:
34
35 Load single symbol entry
36
37 Arguments:
38
39 Object - Symbol file object
40 Name - Symbol name
41 ObjName - Object name
42 Address - Symbol address
43 Type - Symbol type
44
45 Returns:
46
47 EFI_SUCCESS - add single symbol entry successfully
48
49 --*/
50 {
51 EFI_DEBUGGER_SYMBOL_ENTRY *Entry;
52
53 //
54 // Check Count VS MaxCount
55 //
56 if (Object->EntryCount >= Object->MaxEntryCount) {
57 //
58 // reallocate (for codebuffer too)
59 // TBD
60 //
61 return EFI_OUT_OF_RESOURCES;
62 }
63
64 Entry = &Object->Entry[Object->EntryCount];
65
66 //
67 // Print Debug info
68 //
69 if (sizeof (UINTN) == sizeof(UINT64)) {
70 DEBUG ((DEBUG_ERROR, " Symbol: %a, Address: 0x%016lx (%d)\n", Name, (UINT64)Address, (UINTN)Type));
71 } else {
72 DEBUG ((DEBUG_ERROR, " Symbol: %a, Address: 0x%08x (%d)\n", Name, Address, (UINTN)Type));
73 }
74
75 //
76 // Fill the entry - name, RVA, type
77 //
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);
81 }
82 Entry->RVA = Address % EFI_DEBUGGER_DEFAULT_LINK_IMAGEBASE;
83 Entry->Type = Type;
84
85 //
86 // Increase Count
87 //
88 Object->EntryCount++;
89
90 //
91 // Done
92 //
93 return EFI_SUCCESS;
94 }
95
96 typedef enum {
97 EdbEbcMapParseStateUninitialized,
98 EdbEbcMapParseStateSymbolStart,
99 EdbEbcMapParseStateSeHandlerSymbol,
100 EdbEbcMapParseStateFunctionSymbol,
101 EdbEbcMapParseStateVarbssInitSymbol,
102 EdbEbcMapParseStateCrtSymbol,
103 EdbEbcMapParseStateVariableSymbol,
104 EdbEbcMapParseStateStaticFunctionSymbol,
105 EdbEbcMapParseStateMax,
106 } EDB_EBC_MAP_PARSE_STATE;
107
108 typedef enum {
109 EdbEbcSymbolParseStateUninitialized,
110 EdbEbcSymbolParseStateReadyForName,
111 EdbEbcSymbolParseStateReadyForRVA,
112 EdbEbcSymbolParseStateReadyForType,
113 EdbEbcSymbolParseStateReadyForObject,
114 EdbEbcSymbolParseStateMax,
115 } EDB_EBC_SYMBOL_PARSE_STATE;
116
117 /*++
118
119 The following code depends on the MAP file generated by IEC compiler (actually Microsoft linker).
120
121 Sample as follows: EbcTest.map
122 ===============================================================================
123 EbcTest
124
125 Timestamp is 45b02718 (Fri Jan 19 10:04:08 2007)
126
127 Preferred load address is 10000000
128
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
142
143 Address Publics by Value Rva+Base Lib:Object
144
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
160
161 entry point at 0001:00000220
162
163 Static symbols
164
165 0001:00000000 TestSubRoutine2 10000400 f EbcTest.obj
166 ===============================================================================
167
168 --*/
169 EFI_STATUS
170 EdbLoadSymbolEntryByIec (
171 IN EFI_DEBUGGER_SYMBOL_OBJECT *Object,
172 IN UINTN BufferSize,
173 IN VOID *Buffer
174 )
175 /*++
176
177 Routine Description:
178
179 Load symbol entry by Iec
180
181 Arguments:
182
183 DebuggerPrivate - EBC Debugger private data structure
184 Object - Symbol file object
185 BufferSize - Symbol file buffer size
186 Buffer - Symbol file buffer
187
188 Returns:
189
190 EFI_SUCCESS - add symbol entry successfully
191
192 --*/
193 {
194 CHAR8 *LineBuffer;
195 CHAR8 *FieldBuffer;
196 EFI_DEBUGGER_SYMBOL_ENTRY *Entry;
197 EDB_EBC_MAP_PARSE_STATE MapParseState;
198 EDB_EBC_SYMBOL_PARSE_STATE SymbolParseState;
199 CHAR8 *Name;
200 CHAR8 *ObjName;
201 UINTN Address;
202 EFI_DEBUGGER_SYMBOL_TYPE Type;
203
204 Entry = Object->Entry;
205
206 //
207 // Begin to parse the Buffer
208 //
209 LineBuffer = AsciiStrGetNewTokenLine (Buffer, "\n\r");
210 MapParseState = EdbEbcMapParseStateUninitialized;
211 //
212 // Check each line
213 //
214 while (LineBuffer != NULL) {
215 FieldBuffer = AsciiStrGetNewTokenField (LineBuffer, " ");
216 SymbolParseState = EdbEbcSymbolParseStateUninitialized;
217 //
218 // Init entry value
219 //
220 Name = NULL;
221 ObjName = NULL;
222 Address = 0;
223 Type = EfiDebuggerSymbolTypeMax;
224 //
225 // Check each field
226 //
227 while (FieldBuffer != NULL) {
228 if (AsciiStrCmp (FieldBuffer, "") == 0) {
229 FieldBuffer = AsciiStrGetNextTokenField (" ");
230 continue;
231 }
232 //
233 // check "Address"
234 //
235 if (AsciiStrCmp (FieldBuffer, "Address") == 0) {
236 MapParseState = EdbEbcMapParseStateSymbolStart;
237 break;
238 }
239 //
240 // check "Static"
241 //
242 if (AsciiStrCmp (FieldBuffer, "Static") == 0) {
243 MapParseState = EdbEbcMapParseStateStaticFunctionSymbol;
244 break;
245 }
246
247 if (MapParseState == EdbEbcMapParseStateUninitialized) {
248 //
249 // Do not parse anything until get "Address" or "Static"
250 //
251 break;
252 }
253 if (AsciiStrCmp (FieldBuffer, "entry") == 0) {
254 //
255 // Skip entry point
256 //
257 break;
258 }
259
260 //
261 // Now we start to parse this line for Name, Address, and Object
262 //
263 switch (SymbolParseState) {
264 case EdbEbcSymbolParseStateUninitialized:
265 //
266 // Get the Address
267 //
268 SymbolParseState = EdbEbcSymbolParseStateReadyForName;
269 break;
270 case EdbEbcSymbolParseStateReadyForName:
271 //
272 // Get the Name
273 //
274 if (AsciiStrnCmp (FieldBuffer, "___safe_se_handler", AsciiStrLen ("___safe_se_handler")) == 0) {
275 //
276 // skip SeHandler
277 //
278 MapParseState = EdbEbcMapParseStateSeHandlerSymbol;
279 goto ExitFieldParse;
280 } else if (AsciiStrnCmp (FieldBuffer, "varbss_init", AsciiStrLen ("varbss_init")) == 0) {
281 //
282 // check VarbssInit
283 //
284 MapParseState = EdbEbcMapParseStateVarbssInitSymbol;
285 // goto ExitFieldParse;
286 Name = FieldBuffer;
287 SymbolParseState = EdbEbcSymbolParseStateReadyForRVA;
288 } else if (AsciiStrnCmp (FieldBuffer, "Crt", AsciiStrLen ("Crt")) == 0) {
289 //
290 // check Crt
291 //
292 MapParseState = EdbEbcMapParseStateCrtSymbol;
293 // goto ExitFieldParse;
294 Name = FieldBuffer;
295 SymbolParseState = EdbEbcSymbolParseStateReadyForRVA;
296 } else {
297 //
298 // Now, it is normal function
299 //
300 switch (MapParseState) {
301 case EdbEbcMapParseStateSeHandlerSymbol:
302 MapParseState = EdbEbcMapParseStateFunctionSymbol;
303 break;
304 case EdbEbcMapParseStateCrtSymbol:
305 MapParseState = EdbEbcMapParseStateVariableSymbol;
306 break;
307 case EdbEbcMapParseStateFunctionSymbol:
308 case EdbEbcMapParseStateVariableSymbol:
309 case EdbEbcMapParseStateStaticFunctionSymbol:
310 break;
311 default:
312 ASSERT (FALSE);
313 break;
314 }
315 Name = FieldBuffer;
316 SymbolParseState = EdbEbcSymbolParseStateReadyForRVA;
317 }
318 break;
319 case EdbEbcSymbolParseStateReadyForRVA:
320 //
321 // Get the RVA
322 //
323 Address = AsciiXtoi (FieldBuffer);
324 SymbolParseState = EdbEbcSymbolParseStateReadyForType;
325 break;
326 case EdbEbcSymbolParseStateReadyForType:
327 //
328 // Get the Type. This is optional, only for "f".
329 //
330 if (AsciiStrCmp (FieldBuffer, "f") == 0) {
331 SymbolParseState = EdbEbcSymbolParseStateReadyForObject;
332 switch (MapParseState) {
333 case EdbEbcMapParseStateFunctionSymbol:
334 case EdbEbcMapParseStateVarbssInitSymbol:
335 Type = EfiDebuggerSymbolFunction;
336 break;
337 case EdbEbcMapParseStateStaticFunctionSymbol:
338 Type = EfiDebuggerSymbolStaticFunction;
339 break;
340 default:
341 ASSERT (FALSE);
342 break;
343 }
344 break;
345 }
346 //
347 // Else it should be Object.
348 // let it bypass here
349 //
350 case EdbEbcSymbolParseStateReadyForObject:
351 switch (Type) {
352 case EfiDebuggerSymbolTypeMax:
353 switch (MapParseState) {
354 case EdbEbcMapParseStateVariableSymbol:
355 case EdbEbcMapParseStateCrtSymbol:
356 Type = EfiDebuggerSymbolGlobalVariable;
357 break;
358 case EdbEbcMapParseStateSeHandlerSymbol:
359 //
360 // do nothing here
361 //
362 break;
363 default:
364 ASSERT (FALSE);
365 break;
366 }
367 break;
368 case EfiDebuggerSymbolFunction:
369 case EfiDebuggerSymbolStaticFunction:
370 break;
371 default:
372 ASSERT (FALSE);
373 break;
374 }
375 //
376 // Get the Object
377 //
378 ObjName = FieldBuffer;
379 SymbolParseState = EdbEbcSymbolParseStateUninitialized;
380 break;
381 default:
382 ASSERT (FALSE);
383 break;
384 }
385
386 //
387 // Get the next field
388 //
389 FieldBuffer = AsciiStrGetNextTokenField (" ");
390 }
391
392 //
393 // Add the entry if we get everything.
394 //
395 if ((Name != NULL) && (Type != EfiDebuggerSymbolTypeMax)) {
396 EdbLoadSymbolSingleEntry (Object, Name, ObjName, Address, Type);
397 }
398
399 ExitFieldParse:
400 //
401 // Get the next line
402 //
403 LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
404 }
405
406 //
407 // Done
408 //
409 return EFI_SUCCESS;
410 }
411
412 EFI_STATUS
413 EdbLoadSymbolEntry (
414 IN EFI_DEBUGGER_SYMBOL_OBJECT *Object,
415 IN UINTN BufferSize,
416 IN VOID *Buffer
417 )
418 /*++
419
420 Routine Description:
421
422 Load symbol entry
423
424 Arguments:
425
426 Object - Symbol file object
427 BufferSize - Symbol file buffer size
428 Buffer - Symbol file buffer
429
430 Returns:
431
432 EFI_SUCCESS - add symbol entry successfully
433
434 --*/
435 {
436 //
437 // MAP file format depends on the compiler (actually linker).
438 //
439 // It is possible to check the different MAP file format in this routine.
440 // Now only IEC is supported.
441 //
442 return EdbLoadSymbolEntryByIec (Object, BufferSize, Buffer);
443 }
444
445 EFI_DEBUGGER_SYMBOL_OBJECT *
446 EdbFindSymbolFile (
447 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
448 IN CHAR16 *FileName,
449 IN OUT UINTN *Index OPTIONAL
450 )
451 /*++
452
453 Routine Description:
454
455 Find symbol file by name
456
457 Arguments:
458
459 DebuggerPrivate - EBC Debugger private data structure
460 FileName - Symbol file name
461 Index - Symbol file index
462
463 Returns:
464
465 Object
466
467 --*/
468 {
469 UINTN ObjectIndex;
470
471 //
472 // Check each Object
473 //
474 for (ObjectIndex = 0; ObjectIndex < DebuggerPrivate->DebuggerSymbolContext.ObjectCount; ObjectIndex++) {
475 if (StrCmp (FileName, DebuggerPrivate->DebuggerSymbolContext.Object[ObjectIndex].Name) == 0) {
476 //
477 // Name match, found it
478 //
479 if (Index != NULL) {
480 *Index = ObjectIndex;
481 }
482 return &DebuggerPrivate->DebuggerSymbolContext.Object[ObjectIndex];
483 }
484 }
485
486 //
487 // Not found
488 //
489 return NULL;
490 }
491
492 UINTN
493 EbdFindSymbolAddress (
494 IN UINTN Address,
495 IN EDB_MATCH_SYMBOL_TYPE Type,
496 OUT EFI_DEBUGGER_SYMBOL_OBJECT **RetObject,
497 OUT EFI_DEBUGGER_SYMBOL_ENTRY **RetEntry
498 )
499 /*++
500
501 Routine Description:
502
503 Find symbol by address
504
505 Arguments:
506
507 Address - Symbol address
508 Type - Search type
509 RetObject - Symbol object
510 RetEntry - Symbol entry
511
512 Returns:
513
514 Nearest symbol address
515
516 --*/
517 {
518 UINTN Index;
519 UINTN SubIndex;
520 UINTN CandidateLowerAddress;
521 UINTN CandidateUpperAddress;
522 EFI_DEBUGGER_SYMBOL_OBJECT *Object;
523 EFI_DEBUGGER_SYMBOL_ENTRY *Entry;
524 EFI_DEBUGGER_SYMBOL_ENTRY *LowEntry;
525 EFI_DEBUGGER_SYMBOL_ENTRY *UpperEntry;
526 EFI_DEBUGGER_SYMBOL_OBJECT *LowObject;
527 EFI_DEBUGGER_SYMBOL_OBJECT *UpperObject;
528
529 if ((Type < 0) || (Type >= EdbMatchSymbolTypeMax)) {
530 return 0;
531 }
532
533 //
534 // Init
535 //
536 CandidateLowerAddress = 0;
537 CandidateUpperAddress = (UINTN)-1;
538 LowEntry = NULL;
539 UpperEntry = NULL;
540 LowObject = NULL;
541 UpperObject = NULL;
542
543 //
544 // Go through each object
545 //
546 Object = mDebuggerPrivate.DebuggerSymbolContext.Object;
547 for (Index = 0; Index < mDebuggerPrivate.DebuggerSymbolContext.ObjectCount; Index++, Object++) {
548 if (Object->EntryCount == 0) {
549 continue;
550 }
551 //
552 // Go through each entry
553 //
554 Entry = Object->Entry;
555 for (SubIndex = 0; SubIndex < Object->EntryCount; SubIndex++, Entry++) {
556 if (Address != Entry->RVA + Object->BaseAddress) {
557 //
558 // Check for nearest address
559 //
560 if (Address > Entry->RVA + Object->BaseAddress) {
561 //
562 // Record it if Current RVA < Address
563 //
564 if (CandidateLowerAddress < Entry->RVA + Object->BaseAddress) {
565 CandidateLowerAddress = Entry->RVA + Object->BaseAddress;
566 LowEntry = Entry;
567 LowObject = Object;
568 }
569 } else {
570 //
571 // Record it if Current RVA > Address
572 //
573 if (CandidateUpperAddress > Entry->RVA + Object->BaseAddress) {
574 CandidateUpperAddress = Entry->RVA + Object->BaseAddress;
575 UpperEntry = Entry;
576 UpperObject = Object;
577 }
578 }
579 continue;
580 }
581 //
582 // address match, return directly
583 //
584 *RetEntry = Entry;
585 *RetObject = Object;
586 return Address;
587 }
588 }
589
590 //
591 // No Match, provide latest symbol
592 //
593
594 if ((Address - CandidateLowerAddress) < EFI_DEBUGGER_MAX_SYMBOL_ADDRESS_DELTA_VALUE) {
595 //
596 // Check for lower address
597 //
598 if (((Type == EdbMatchSymbolTypeNearestAddress) &&
599 ((CandidateUpperAddress - Address) > (Address - CandidateLowerAddress))) ||
600 (Type == EdbMatchSymbolTypeLowerAddress)) {
601 //
602 // return nearest lower address
603 //
604 *RetEntry = LowEntry;
605 *RetObject = LowObject;
606 return CandidateLowerAddress;
607 }
608 }
609
610 if ((CandidateUpperAddress - Address) < EFI_DEBUGGER_MAX_SYMBOL_ADDRESS_DELTA_VALUE) {
611 //
612 // Check for upper address
613 //
614 if (((Type == EdbMatchSymbolTypeNearestAddress) &&
615 ((CandidateUpperAddress - Address) < (Address - CandidateLowerAddress))) ||
616 (Type == EdbMatchSymbolTypeUpperAddress)) {
617 //
618 // return nearest upper address
619 //
620 *RetEntry = UpperEntry;
621 *RetObject = UpperObject;
622 return CandidateUpperAddress;
623 }
624 }
625
626 //
627 // No match and nearest one, return NULL
628 //
629 return 0;
630 }
631
632 EFI_STATUS
633 EdbUnloadSymbol (
634 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
635 IN CHAR16 *FileName
636 )
637 /*++
638
639 Routine Description:
640
641 Unload symbol file by name
642
643 Arguments:
644
645 DebuggerPrivate - EBC Debugger private data structure
646 FileName - Symbol file name
647
648 Returns:
649
650 EFI_SUCCESS - unload symbol successfully
651
652 --*/
653 {
654 EFI_DEBUGGER_SYMBOL_OBJECT *Object;
655 UINTN ObjectIndex;
656 UINTN Index;
657 EFI_DEBUGGER_SYMBOL_ENTRY *OldEntry;
658 UINTN OldEntryCount;
659 UINTN MaxEntryCount;
660 VOID **OldSourceBuffer;
661
662 //
663 // Find Symbol
664 //
665 Object = EdbFindSymbolFile (DebuggerPrivate, FileName, &ObjectIndex);
666 if (Object == NULL) {
667 EDBPrint (L"SymbolFile is not loaded!\n");
668 return EFI_DEBUG_CONTINUE;
669 }
670
671 //
672 // Record old data
673 //
674 Object = DebuggerPrivate->DebuggerSymbolContext.Object;
675 OldEntry = Object->Entry;
676 OldSourceBuffer = Object->SourceBuffer;
677 MaxEntryCount = Object->MaxEntryCount;
678 OldEntryCount = Object->EntryCount;
679
680 //
681 // Remove the matched Object
682 //
683 for (Index = ObjectIndex; Index < DebuggerPrivate->DebuggerSymbolContext.ObjectCount - 1; Index++) {
684 CopyMem (&Object[Index], &Object[Index + 1], sizeof(EFI_DEBUGGER_SYMBOL_OBJECT));
685 }
686 ZeroMem (&Object[Index], sizeof(Object[Index]));
687
688 //
689 // Move old data to new place
690 //
691 Object[Index].Entry = OldEntry;
692 Object[Index].SourceBuffer = OldSourceBuffer;
693 Object[Index].MaxEntryCount = MaxEntryCount;
694 DebuggerPrivate->DebuggerSymbolContext.ObjectCount --;
695
696 //
697 // Clean old entry data
698 //
699 for (Index = 0; Index < OldEntryCount; Index++) {
700 ZeroMem (&OldEntry[Index], sizeof(OldEntry[Index]));
701 }
702
703 //
704 // Free OldSourceBuffer
705 //
706 for (Index = 0; OldSourceBuffer[Index] != NULL; Index++) {
707 gBS->FreePool (OldSourceBuffer[Index]);
708 OldSourceBuffer[Index] = NULL;
709 }
710
711 return EFI_SUCCESS;
712 }
713
714 EFI_STATUS
715 EdbLoadSymbol (
716 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
717 IN CHAR16 *FileName,
718 IN UINTN BufferSize,
719 IN VOID *Buffer
720 )
721 /*++
722
723 Routine Description:
724
725 Load symbol file by name
726
727 Arguments:
728
729 DebuggerPrivate - EBC Debugger private data structure
730 FileName - Symbol file name
731 BufferSize - Symbol file buffer size
732 Buffer - Symbol file buffer
733
734 Returns:
735
736 EFI_SUCCESS - load symbol successfully
737
738 --*/
739 {
740 EFI_DEBUGGER_SYMBOL_OBJECT *Object;
741 EFI_STATUS Status;
742
743 //
744 // Check duplicated File
745 //
746 Object = EdbFindSymbolFile (DebuggerPrivate, FileName, NULL);
747 if (Object != NULL) {
748 Status = EdbUnloadSymbol (DebuggerPrivate, FileName);
749 if (EFI_ERROR(Status)) {
750 DEBUG ((DEBUG_ERROR, "Unload Duplicated Symbol File Error!\n"));
751 return Status;
752 }
753 }
754
755 //
756 // Check Count VS MaxCount
757 //
758 if (DebuggerPrivate->DebuggerSymbolContext.ObjectCount >= DebuggerPrivate->DebuggerSymbolContext.MaxObjectCount) {
759 //
760 // reallocate
761 // TBD
762 //
763 return EFI_OUT_OF_RESOURCES;
764 }
765
766 Object = &DebuggerPrivate->DebuggerSymbolContext.Object[DebuggerPrivate->DebuggerSymbolContext.ObjectCount];
767
768 //
769 // Init Object
770 //
771 Object->EntryCount = 0;
772 Object->MaxEntryCount = EFI_DEBUGGER_SYMBOL_ENTRY_MAX;
773
774 //
775 // Load SymbolEntry
776 //
777 DEBUG ((DEBUG_ERROR, "Symbol File: %s\n", FileName));
778 Status = EdbLoadSymbolEntry (Object, BufferSize, Buffer);
779 if (EFI_ERROR (Status)) {
780 return Status;
781 }
782
783 //
784 // Fill Object value
785 //
786 StrnCpyS (Object->Name, sizeof(Object->Name) / sizeof(CHAR16),
787 FileName, (sizeof(Object->Name) / sizeof(CHAR16)) - 1);
788 Object->BaseAddress = 0;
789
790 //
791 // Increase the object count
792 //
793 DebuggerPrivate->DebuggerSymbolContext.ObjectCount ++;
794
795 return EFI_SUCCESS;
796 }
797
798 CHAR8 *
799 GetPdbPath (
800 VOID *ImageBase
801 )
802 /*++
803
804 Routine Description:
805
806 Located PDB path name in PE image
807
808 Arguments:
809
810 ImageBase - base of PE to search
811
812 Returns:
813
814 Pointer into image at offset of PDB file name if PDB file name is found,
815 Otherwise a pointer to an empty string.
816
817 --*/
818 {
819 CHAR8 *PdbPath;
820 UINT32 DirCount;
821 EFI_IMAGE_DOS_HEADER *DosHdr;
822 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;
823 EFI_IMAGE_OPTIONAL_HEADER32 *OptionalHdr32;
824 EFI_IMAGE_OPTIONAL_HEADER64 *OptionalHdr64;
825 EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry;
826 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;
827 VOID *CodeViewEntryPointer;
828
829 //
830 // Init value
831 //
832 CodeViewEntryPointer = NULL;
833 PdbPath = NULL;
834 DosHdr = ImageBase;
835
836 //
837 // Check magic
838 //
839 if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
840 return NULL;
841 }
842 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *) ((UINT8 *) DosHdr + DosHdr->e_lfanew);
843 //
844 // Check Machine, filter for EBC
845 //
846 if (NtHdr->Pe32.FileHeader.Machine != EFI_IMAGE_MACHINE_EBC) {
847 //
848 // If not EBC, return NULL
849 //
850 return NULL;
851 }
852
853 //
854 // Get DirectoryEntry
855 // EBC spec says PE32+, but implementation uses PE32. So check dynamically here.
856 //
857 if (NtHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
858 OptionalHdr32 = (VOID *) &NtHdr->Pe32.OptionalHeader;
859 DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(OptionalHdr32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
860 } else if (NtHdr->Pe32Plus.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
861 OptionalHdr64 = (VOID *) &NtHdr->Pe32Plus.OptionalHeader;
862 DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(OptionalHdr64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
863 } else {
864 return NULL;
865 }
866 if (DirectoryEntry->VirtualAddress == 0) {
867 return NULL;
868 }
869 //
870 // Go through DirectoryEntry
871 //
872 for (DirCount = 0;
873 (DirCount < DirectoryEntry->Size / sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)) && CodeViewEntryPointer == NULL;
874 DirCount++
875 ) {
876 DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (DirectoryEntry->VirtualAddress + (UINTN) ImageBase + DirCount * sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY));
877 if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
878 //
879 // Match DebugEntry, only CODEVIEW_SIGNATURE_NB10 and CODEVIEW_SIGNATURE_RSDS are supported.
880 //
881 CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + (UINTN) ImageBase);
882 switch (*(UINT32 *) CodeViewEntryPointer) {
883 case CODEVIEW_SIGNATURE_NB10:
884 PdbPath = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);
885 break;
886 case CODEVIEW_SIGNATURE_RSDS:
887 PdbPath = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);
888 break;
889 default:
890 break;
891 }
892 }
893 }
894
895 //
896 // Done successfully
897 //
898 return PdbPath;
899 }
900
901 BOOLEAN
902 MatchPdbAndMap (
903 IN CHAR8 *PdbFileName,
904 IN CHAR16 *MapFileName
905 )
906 /*++
907
908 Routine Description:
909
910 Check whether PDB file and MAP file have same name
911
912 Arguments:
913
914 PdbFileName - PDB file name
915 MapFileName - MAP file name
916
917 Returns:
918
919 TRUE - PDB and MAP file name match
920 FALSE - PDB and MAP file name not match
921
922 --*/
923 {
924 UINTN PdbNameSize;
925 UINTN MapNameSize;
926 CHAR8 *PurePdbFileName;
927 UINTN Index;
928
929 //
930 // remove dir name
931 //
932 PurePdbFileName = PdbFileName;
933 for (Index = 0; PdbFileName[Index] != 0; Index++) {
934 if (PdbFileName[Index] == '\\') {
935 PurePdbFileName = &PdbFileName[Index + 1];
936 }
937 }
938 PdbFileName = PurePdbFileName;
939
940 //
941 // get size
942 //
943 PdbNameSize = AsciiStrLen (PdbFileName);
944 MapNameSize = StrLen (MapFileName);
945
946 if (PdbNameSize != MapNameSize) {
947 return FALSE;
948 }
949
950 //
951 // check the name
952 //
953 for (Index = 0; Index < MapNameSize - 4; Index++) {
954 if ((PdbFileName[Index] | 0x20) != (MapFileName[Index] | 0x20)) {
955 return FALSE;
956 }
957 }
958
959 return TRUE;
960 }
961
962 //
963 // BUGBUG: work-around start
964 //
965 typedef struct {
966 EFI_DEBUG_IMAGE_INFO *EfiDebugImageInfoTable;
967 volatile UINT32 UpdateStatus;
968 UINT32 TableSize;
969 } EFI_DEBUG_IMAGE_INFO_TABLE_HEADER_OLD;
970
971 EFI_DEBUG_IMAGE_INFO_TABLE_HEADER mDebugImageInfoTableHeader;
972
973 VOID
974 EdbFixDebugImageInfoTable (
975 IN OUT EFI_DEBUG_IMAGE_INFO_TABLE_HEADER **DebugImageInfoTableHeader
976 )
977 /*
978 For compatibility consideration, we handle 2 cases:
979
980 1) IA32:
981 Old: New:
982 +------------------------+ +------------------------+
983 | EfiDebugImageInfoTable | | UpdateStatus |
984 +------------------------+ +------------------------+
985 | UpdateStatus | | TableSize |
986 +------------------------+ +------------------------+
987 | TableSize | | EfiDebugImageInfoTable |
988 +------------------------+ +------------------------+
989
990 2) X64 and IPF:
991 Old: New:
992 +------------------------+ +------------------------+
993 | EfiDebugImageInfoTable | | UpdateStatus |
994 | | +------------------------+
995 | | | TableSize |
996 +------------------------+ +------------------------+
997 | UpdateStatus | | EfiDebugImageInfoTable |
998 +------------------------+ | |
999 | TableSize | | |
1000 +------------------------+ +------------------------+
1001
1002 */
1003 {
1004 mDebugImageInfoTableHeader.EfiDebugImageInfoTable = ((EFI_DEBUG_IMAGE_INFO_TABLE_HEADER_OLD *)(*DebugImageInfoTableHeader))->EfiDebugImageInfoTable;
1005 mDebugImageInfoTableHeader.UpdateStatus = ((EFI_DEBUG_IMAGE_INFO_TABLE_HEADER_OLD *)(*DebugImageInfoTableHeader))->UpdateStatus;
1006 mDebugImageInfoTableHeader.TableSize = ((EFI_DEBUG_IMAGE_INFO_TABLE_HEADER_OLD *)(*DebugImageInfoTableHeader))->TableSize;
1007
1008 if ((*DebugImageInfoTableHeader)->UpdateStatus > 3) {
1009 *DebugImageInfoTableHeader = &mDebugImageInfoTableHeader;
1010 return ;
1011 }
1012
1013 if ((*DebugImageInfoTableHeader)->TableSize % (EFI_PAGE_SIZE / (sizeof (VOID *))) != 0) {
1014 *DebugImageInfoTableHeader = &mDebugImageInfoTableHeader;
1015 return ;
1016 }
1017
1018 return ;
1019 }
1020 //
1021 // BUGBUG: work-around end
1022 //
1023
1024 EFI_STATUS
1025 EdbPatchSymbolRVA (
1026 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
1027 IN CHAR16 *FileName,
1028 IN EDB_EBC_IMAGE_RVA_SEARCH_TYPE SearchType
1029 )
1030 /*++
1031
1032 Routine Description:
1033
1034 Patch symbol RVA
1035
1036 Arguments:
1037
1038 DebuggerPrivate - EBC Debugger private data structure
1039 FileName - Symbol file name
1040 SearchType - Search type for Object
1041
1042 Returns:
1043
1044 EFI_SUCCESS - Patch symbol RVA successfully
1045 EFI_NOT_FOUND - Symbol RVA base not found
1046
1047 --*/
1048 {
1049 EFI_STATUS Status;
1050 UINTN ImageNumber;
1051 EFI_DEBUG_IMAGE_INFO *ImageTable;
1052 CHAR8 *PdbPath;
1053 VOID *ImageBase;
1054 VOID *CandidateImageBase;
1055 EFI_DEBUGGER_SYMBOL_OBJECT *Object;
1056
1057 if (SearchType < 0 || SearchType >= EdbEbcImageRvaSearchTypeMax) {
1058 return EFI_INVALID_PARAMETER;
1059 }
1060
1061 //
1062 // Get the related object
1063 //
1064 Object = EdbFindSymbolFile (DebuggerPrivate, FileName, NULL);
1065 if (Object == NULL) {
1066 return EFI_NOT_FOUND;
1067 }
1068
1069 //
1070 // Try again to get DebugImageInfoTable
1071 //
1072 if (mDebuggerPrivate.DebugImageInfoTableHeader == NULL) {
1073 Status = EfiGetSystemConfigurationTable (
1074 &gEfiDebugImageInfoTableGuid,
1075 (VOID **) &mDebuggerPrivate.DebugImageInfoTableHeader
1076 );
1077 if (EFI_ERROR (Status)) {
1078 EDBPrint (L"DebugImageInfoTable not found!\n");
1079 return Status;
1080 }
1081 }
1082 DEBUG ((DEBUG_ERROR, "DebugImageInfoTableHeader: %x\n", mDebuggerPrivate.DebugImageInfoTableHeader));
1083
1084 //
1085 // BUGBUG: work-around start
1086 //
1087 EdbFixDebugImageInfoTable (&mDebuggerPrivate.DebugImageInfoTableHeader);
1088 //
1089 // BUGBUG: work-around end
1090 //
1091
1092 //
1093 // Go through DebugImageInfoTable for each Image
1094 //
1095 CandidateImageBase = NULL;
1096 ImageTable = mDebuggerPrivate.DebugImageInfoTableHeader->EfiDebugImageInfoTable;
1097 for (ImageNumber = 0; ImageNumber < mDebuggerPrivate.DebugImageInfoTableHeader->TableSize; ImageNumber++) {
1098 if (ImageTable[ImageNumber].NormalImage == NULL) {
1099 continue;
1100 }
1101 ImageBase = ImageTable[ImageNumber].NormalImage->LoadedImageProtocolInstance->ImageBase;
1102 //
1103 // Get PDB path
1104 //
1105 PdbPath = GetPdbPath (ImageBase);
1106 if (PdbPath == NULL) {
1107 continue;
1108 }
1109 //
1110 // Check PDB name
1111 //
1112 if (!MatchPdbAndMap (PdbPath, FileName)) {
1113 continue;
1114 }
1115 DEBUG ((DEBUG_ERROR, "ImageBase: %x\n", ImageBase));
1116
1117 //
1118 // Check SearchType
1119 //
1120 if (SearchType == EdbEbcImageRvaSearchTypeAny || SearchType == EdbEbcImageRvaSearchTypeFirst) {
1121 //
1122 // Assign base address and return
1123 //
1124 Object->BaseAddress = (UINTN)ImageBase;
1125 return EFI_SUCCESS;
1126 }
1127
1128 //
1129 // Get CandidateImageBase for EdbEbcImageRvaSearchTypeLast
1130 //
1131 CandidateImageBase = ImageBase;
1132 }
1133
1134 //
1135 // Check EdbEbcImageRvaSearchTypeLast
1136 //
1137 if (SearchType == EdbEbcImageRvaSearchTypeLast) {
1138 if (CandidateImageBase == NULL) {
1139 return EFI_NOT_FOUND;
1140 }
1141 //
1142 // Assign base address and return
1143 //
1144 Object->BaseAddress = (UINTN)CandidateImageBase;
1145 return EFI_SUCCESS;
1146 }
1147
1148 //
1149 // No match
1150 //
1151 return EFI_NOT_FOUND;
1152 }
1153
1154 BOOLEAN
1155 MatchObjAndCod (
1156 IN CHAR8 *ObjFileName,
1157 IN CHAR16 *CodFileName
1158 )
1159 /*++
1160
1161 Routine Description:
1162
1163 Check whether OBJ file and COD file have same name
1164
1165 Arguments:
1166
1167 ObjFileName - OBJ file name
1168 CodFileName - COD file name
1169
1170 Returns:
1171
1172 TRUE - OBJ and COD file name match
1173 FALSE - OBJ and COD file name not match
1174
1175 --*/
1176 {
1177 UINTN ObjNameSize;
1178 UINTN CodNameSize;
1179 CHAR8 *PureObjFileName;
1180 UINTN Index;
1181
1182 //
1183 // remove library name
1184 //
1185 PureObjFileName = ObjFileName;
1186 for (Index = 0; ObjFileName[Index] != 0; Index++) {
1187 if (ObjFileName[Index] == ':') {
1188 PureObjFileName = &ObjFileName[Index + 1];
1189 break;
1190 }
1191 }
1192 ObjFileName = PureObjFileName;
1193
1194 //
1195 // get size
1196 //
1197 ObjNameSize = AsciiStrLen (ObjFileName);
1198 CodNameSize = StrLen (CodFileName);
1199
1200 if (ObjNameSize != CodNameSize) {
1201 return FALSE;
1202 }
1203
1204 //
1205 // check the name
1206 //
1207 for (Index = 0; Index < CodNameSize - 4; Index++) {
1208 if ((ObjFileName[Index] | 0x20) != (CodFileName[Index] | 0x20)) {
1209 return FALSE;
1210 }
1211 }
1212
1213 return TRUE;
1214 }
1215
1216 typedef enum {
1217 EdbEbcCodParseStateUninitialized,
1218 EdbEbcCodParseStateSymbolInitialized,
1219 EdbEbcCodParseStateSymbolStart,
1220 EdbEbcCodParseStateSymbolEnd,
1221 EdbEbcCodParseStateMax,
1222 } EDB_EBC_COD_PARSE_STATE;
1223
1224 /*++
1225
1226 The following code depends on the COD file generated by IEC compiler.
1227
1228 Sample as follows: EbcTest.cod
1229 ===============================================================================
1230 ; -- Machine type EFI
1231 ; mark_description "Intel(R) C Compiler for EFI Byte Code, Version 1.2 Build 20040123";
1232 ; mark_description "XXX";
1233 ;ident "Intel(R) C Compiler for EFI Byte Code, Version 1.2 Build 20040123"
1234 ;ident "XXX"
1235 .686P
1236 .387
1237 _TEXT SEGMENT PARA PUBLIC USE32 'CODE'
1238 _TEXT ENDS
1239 _DATA SEGMENT PARA PUBLIC USE32 'DATA'
1240 ALIGN 010H
1241 _DATA ENDS
1242 _BSS SEGMENT PARA PUBLIC USE32 'BSS'
1243 ALIGN 010H
1244 _BSS ENDS
1245 _VARBSS SEGMENT PARA PUBLIC USE32 'BSS'
1246 ALIGN 010H
1247 _VARBSS ENDS
1248 ASSUME CS:FLAT,DS:FLAT,SS:FLAT
1249 _DATA SEGMENT PARA PUBLIC USE32 'DATA'
1250 TestVariable2 DD 000000003H,000000000H ; u64
1251 _DATA ENDS
1252 _DATA SEGMENT PARA PUBLIC USE32 'DATA'
1253 _DATA ENDS
1254 _TEXT SEGMENT PARA PUBLIC USE32 'CODE'
1255 ; -- Begin EfiMain
1256 ; mark_begin;
1257 PUBLIC EfiMain
1258 EfiMain PROC NEAR
1259 $B3$1:; 11a
1260 $LN45:
1261
1262 ;117 ; {
1263
1264 0011a 60 00 70 80 MOVqw R0, R0(+0,-112) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:117
1265 $LN46:
1266
1267 ;118 ; UINT16 test = 0x1234;
1268
1269 0011e 77 58 58 00 34
1270 12 MOVIww @R0(+0,+88), +4660 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:118
1271 $LN47:
1272
1273 ;121 ; EFI_STATUS Status;
1274 ;121 ;
1275 ;121 ; SystemTable->ConOut->OutputString (
1276
1277 00124 72 87 01 12 MOVnw R7, @R0(+1,+128) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:121
1278 00128 72 f7 85 21 MOVnw R7, @R7(+5,+24) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:121
1279 $LN48:
1280
1281 ;122 ; SystemTable->ConOut,
1282
1283 0012c 72 84 01 12 MOVnw R4, @R0(+1,+128) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:122
1284 00130 72 c8 85 21 MOVnw @R0, @R4(+5,+24) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:122
1285 00134 b9 34 00 00 00
1286 00 MOVreld R4, __STRING$1 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:122
1287 0013a b2 48 01 10 MOVnw @R0(+1,+0), R4 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:122
1288 0013e 83 2f 01 00 00
1289 10 CALLEX @R7(+1,+0) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:122
1290 $B3$2:; 144
1291 $LN49:
1292
1293 ;125 ; L"Hello EBC Test!\n\r"
1294 ;125 ; );
1295 ;125 ; EFI_BREAKPOINT ();
1296
1297 00144 00 03 BREAK 3 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:125
1298 $B3$3:; 146
1299 $LN50:
1300
1301 ;126 ; TestVariable1 = 6;
1302
1303 00146 b9 37 00 00 00
1304 00 MOVreld R7, TestVariable1 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:126
1305 0014c 78 0f 06 00 MOVInw @R7, (0,6) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:126
1306 $LN51:
1307
1308 ;127 ; TestSubRoutineSub (1, 5);
1309
1310 00150 78 08 01 00 MOVInw @R0, (0,1) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:127
1311 00154 78 48 01 10 05
1312 00 MOVInw @R0(1,0), (0,5) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:127
1313 0015a 83 10 00 00 00
1314 00 CALL TestSubRoutineSub ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:127
1315 $B3$4:; 160
1316 $LN52:
1317
1318 ;129 ;
1319 ;129 ; SystemTable->ConOut->OutputString (
1320
1321 00160 72 87 01 12 MOVnw R7, @R0(+1,+128) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:129
1322 00164 72 f7 85 21 MOVnw R7, @R7(+5,+24) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:129
1323 $LN53:
1324
1325 ;130 ; SystemTable->ConOut,
1326
1327 00168 72 84 01 12 MOVnw R4, @R0(+1,+128) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:130
1328 0016c 72 c8 85 21 MOVnw @R0, @R4(+5,+24) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:130
1329 $LN54:
1330
1331 ;131 ; TestStr
1332
1333 00170 b9 34 00 00 00
1334 00 MOVreld R4, TestStr ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:131
1335 00176 b2 c8 01 10 MOVnw @R0(+1, +0), @R4 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:131
1336 0017a 83 2f 01 00 00
1337 10 CALLEX @R7(+1,+0) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:131
1338 $B3$5:; 180
1339 $LN55:
1340
1341 ;134 ; );
1342 ;134 ;
1343 ;134 ; test = test & 0xFF;
1344
1345 00180 de 88 58 00 58
1346 00 MOVww @R0(+0,+88), @R0(+0,+88) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:134
1347 $LN56:
1348
1349 ;139 ; if (test != 0x34) {
1350 ;139 ; // EFI_BREAKPOINT ();
1351 ;139 ; }
1352 ;139 ;
1353 ;139 ; Status = TestSubRoutine (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
1354
1355 00186 78 08 01 00 MOVInw @R0, (0,1) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1356 0018a 78 48 01 10 02
1357 00 MOVInw @R0(1,0), (0,2) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1358 00190 78 48 02 10 03
1359 00 MOVInw @R0(2,0), (0,3) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1360 00196 78 48 03 10 04
1361 00 MOVInw @R0(3,0), (0,4) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1362 0019c 78 48 04 20 05
1363 00 MOVInw @R0(4,0), (0,5) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1364 001a2 78 48 05 20 06
1365 00 MOVInw @R0(5,0), (0,6) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1366 001a8 78 48 06 20 07
1367 00 MOVInw @R0(6,0), (0,7) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1368 001ae 78 48 07 20 08
1369 00 MOVInw @R0(7,0), (0,8) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1370 001b4 78 48 08 20 09
1371 00 MOVInw @R0(8,0), (0,9) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1372 001ba 78 48 09 20 0a
1373 00 MOVInw @R0(9,0), (0,10) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1374 001c0 83 10 00 00 00
1375 00 CALL TestSubRoutine ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1376 $B3$10:; 1c6
1377 001c6 b2 78 60 00 MOVnw @R0(+0,+96), R7 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1378 $B3$6:; 1ca
1379 $LN57:
1380 001ca f2 88 50 00 60
1381 00 MOVnw @R0(+0,+80), @R0(+0,+96) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
1382 $LN58:
1383
1384 ;141 ;
1385 ;141 ; SystemTable->ConOut->OutputString (
1386
1387 001d0 72 87 01 12 MOVnw R7, @R0(+1,+128) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:141
1388 001d4 72 f7 85 21 MOVnw R7, @R7(+5,+24) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:141
1389 $LN59:
1390
1391 ;142 ; SystemTable->ConOut,
1392
1393 001d8 72 84 01 12 MOVnw R4, @R0(+1,+128) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:142
1394 001dc 72 c8 85 21 MOVnw @R0, @R4(+5,+24) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:142
1395 001e0 b9 34 00 00 00
1396 00 MOVreld R4, __STRING$2 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:142
1397 001e6 b2 48 01 10 MOVnw @R0(+1,+0), R4 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:142
1398 001ea 83 2f 01 00 00
1399 10 CALLEX @R7(+1,+0) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:142
1400 $B3$7:; 1f0
1401 $LN60:
1402
1403 ;146 ; L"Goodbye EBC Test!\n\r"
1404 ;146 ; );
1405 ;146 ;
1406 ;146 ; return Status;
1407
1408 001f0 72 87 50 00 MOVnw R7, @R0(+0,+80) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:146
1409 001f4 60 00 70 00 MOVqw R0, R0(+0,+112) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:146
1410 001f8 04 00 RET ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:146
1411 ; mark_end;
1412 EfiMain ENDP
1413 _TEXT ENDS
1414 _DATA SEGMENT PARA PUBLIC USE32 'DATA'
1415 DB 3 DUP (0) ; pad
1416 __STRING$2 DW 71 ; u16
1417 DW 111 ; u16
1418 DW 111 ; u16
1419 DW 100 ; u16
1420 DW 98 ; u16
1421 DW 121 ; u16
1422 DW 101 ; u16
1423 DW 32 ; u16
1424 DW 69 ; u16
1425 DW 66 ; u16
1426 DW 67 ; u16
1427 DW 32 ; u16
1428 DW 84 ; u16
1429 DW 101 ; u16
1430 DW 115 ; u16
1431 DW 116 ; u16
1432 DW 33 ; u16
1433 DW 10 ; u16
1434 DW 13 ; u16
1435 DW 0 ; u16
1436 __STRING$1 DW 72 ; u16
1437 DW 101 ; u16
1438 DW 108 ; u16
1439 DW 108 ; u16
1440 DW 111 ; u16
1441 DW 32 ; u16
1442 DW 69 ; u16
1443 DW 66 ; u16
1444 DW 67 ; u16
1445 DW 32 ; u16
1446 DW 84 ; u16
1447 DW 101 ; u16
1448 DW 115 ; u16
1449 DW 116 ; u16
1450 DW 33 ; u16
1451 DW 10 ; u16
1452 DW 13 ; u16
1453 DW 0 ; u16
1454 _DATA ENDS
1455 _DATA SEGMENT PARA PUBLIC USE32 'DATA'
1456 _DATA ENDS
1457 ; -- End EfiMain
1458 _DATA SEGMENT PARA PUBLIC USE32 'DATA'
1459 __STRING$0 DW 55 ; u16
1460 DW 56 ; u16
1461 DW 57 ; u16
1462 DW 52 ; u16
1463 DW 53 ; u16
1464 DW 54 ; u16
1465 DW 49 ; u16
1466 DW 50 ; u16
1467 DW 51 ; u16
1468 DW 13 ; u16
1469 DW 10 ; u16
1470 DW 0 ; u16
1471 _DATA ENDS
1472 _VARBSS SEGMENT PARA PUBLIC USE32 'BSS'
1473 PUBLIC TestStr
1474 TestStr DD 2 DUP (?) ; pad
1475 PUBLIC TestVariable1
1476 TestVariable1 DD 2 DUP (?) ; pad
1477 _VARBSS ENDS
1478 _VARBSS_INIT SEGMENT DWORD PUBLIC USE32 'CODE'
1479 ; -- Begin varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest$c45b815d2
1480 PUBLIC varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest$c45b815d2
1481 varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest$c45b815d2 PROC NEAR
1482 00000 b9 34 00 00 00
1483 00 MOVreld R4, TestStr
1484 00006 b9 35 00 00 00
1485 00 MOVreld R5, __STRING$0
1486 0000c 33 5c MOVnd @R4, R5
1487 0000e b9 34 00 00 00
1488 00 MOVreld R4, TestVariable1
1489 00014 78 0c 04 00 MOVInw @R4, (0,4)
1490 00018 04 00 RET
1491 ; -- End varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest$c45b815d2
1492 _VARBSS_INIT ENDS
1493 _DATA SEGMENT PARA PUBLIC USE32 'DATA'
1494 _DATA ENDS
1495 EXTRN TestSubRoutineSub:PROC
1496 END
1497
1498 ===============================================================================
1499
1500 --*/
1501 CHAR8 *
1502 EdbLoadCodBySymbolByIec (
1503 IN CHAR8 *Name,
1504 IN VOID *Buffer,
1505 IN UINTN BufferSize,
1506 OUT UINTN *CodeBufferSize,
1507 OUT UINTN *FuncOffset
1508 )
1509 /*++
1510
1511 Routine Description:
1512
1513 Load code by symbol by Iec
1514
1515 Arguments:
1516
1517 Name - Symbol file name
1518 BufferSize - Symbol file buffer size
1519 Buffer - Symbol file buffer
1520 CodeBufferSize - Code buffer size
1521 FuncOffset - Code funcion offset
1522
1523 Returns:
1524
1525 CodeBuffer
1526
1527 --*/
1528 {
1529 CHAR8 *LineBuffer;
1530 CHAR8 *FieldBuffer;
1531 VOID *BufferStart;
1532 VOID *BufferEnd;
1533 UINTN Offset;
1534 EDB_EBC_COD_PARSE_STATE CodParseState;
1535 CHAR8 Char[2] = {9, 0};
1536
1537 //
1538 // Init
1539 //
1540 LineBuffer = AsciiStrGetNewTokenLine (Buffer, "\n\r");
1541 Offset = (UINTN)-1;
1542 BufferStart = NULL;
1543 BufferEnd = NULL;
1544 CodParseState = EdbEbcCodParseStateUninitialized;
1545
1546 //
1547 // Check each line
1548 //
1549 while (LineBuffer != NULL) {
1550 switch (CodParseState) {
1551 case EdbEbcCodParseStateUninitialized:
1552 //
1553 // check mark_begin, begin to check line after this match
1554 //
1555 if (AsciiStrCmp (LineBuffer, "; mark_begin;") == 0) {
1556 CodParseState = EdbEbcCodParseStateSymbolInitialized;
1557 }
1558 LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
1559 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1560 break;
1561
1562 case EdbEbcCodParseStateSymbolInitialized:
1563 //
1564 // check mark_end, not check line after this match
1565 //
1566 if (AsciiStrCmp (LineBuffer, "; mark_end;") == 0) {
1567 CodParseState = EdbEbcCodParseStateUninitialized;
1568 LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
1569 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1570 break;
1571 }
1572
1573 //
1574 // not check this line if the first char is as follows
1575 //
1576 if ((*LineBuffer == 0) ||
1577 (*LineBuffer == '$') ||
1578 (*LineBuffer == ';') ||
1579 (*LineBuffer == '_') ||
1580 (*LineBuffer == ' ')) {
1581 LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
1582 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1583 break;
1584 }
1585
1586 //
1587 // get function name, function name is followed by char 0x09.
1588 //
1589 FieldBuffer = AsciiStrGetNewTokenField (LineBuffer, Char);
1590 if (AsciiStriCmp (FieldBuffer, Name) == 0) {
1591 BufferStart = FieldBuffer;
1592 CodParseState = EdbEbcCodParseStateSymbolStart;
1593 }
1594 PatchForAsciiStrTokenAfter (FieldBuffer, 0x9);
1595
1596 //
1597 // Get next line
1598 //
1599 LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
1600 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1601 break;
1602
1603 case EdbEbcCodParseStateSymbolStart:
1604 //
1605 // check mark_end, if this match, means the function is found successfully.
1606 //
1607 if (AsciiStrCmp (LineBuffer, "; mark_end;") == 0) {
1608 CodParseState = EdbEbcCodParseStateSymbolEnd;
1609 //
1610 // prepare CodeBufferSize, FuncOffset, and FuncStart to return
1611 //
1612 BufferEnd = LineBuffer + sizeof("; mark_end;") - 1;
1613 *CodeBufferSize = (UINTN)BufferEnd - (UINTN)BufferStart;
1614 *FuncOffset = Offset;
1615 PatchForAsciiStrTokenAfter (LineBuffer, '\n');
1616 return BufferStart;
1617 }
1618
1619 //
1620 // Get function offset
1621 //
1622 if ((Offset == (UINTN)-1) &&
1623 (*LineBuffer == ' ')) {
1624 FieldBuffer = AsciiStrGetNewTokenField (LineBuffer + 2, " ");
1625 Offset = AsciiXtoi (FieldBuffer);
1626 PatchForAsciiStrTokenAfter (FieldBuffer, ' ');
1627 }
1628
1629 //
1630 // Get next line
1631 //
1632 LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
1633 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
1634 break;
1635
1636 case EdbEbcCodParseStateSymbolEnd:
1637 break;
1638
1639 default:
1640 break;
1641 }
1642 }
1643
1644 //
1645 // no function found
1646 //
1647 return NULL;
1648 }
1649
1650 CHAR8 *
1651 EdbLoadCodBySymbol (
1652 IN CHAR8 *Name,
1653 IN VOID *Buffer,
1654 IN UINTN BufferSize,
1655 OUT UINTN *CodeBufferSize,
1656 OUT UINTN *FuncOffset
1657 )
1658 /*++
1659
1660 Routine Description:
1661
1662 Load code by symbol
1663
1664 Arguments:
1665
1666 Name - Symbol file name
1667 BufferSize - Symbol file buffer size
1668 Buffer - Symbol file buffer
1669 CodeBufferSize - Code buffer size
1670 FuncOffset - Code funcion offset
1671
1672 Returns:
1673
1674 CodeBuffer
1675
1676 --*/
1677 {
1678 //
1679 // COD file format depends on the compiler.
1680 //
1681 // It is possible to check the different COD file format in this routine.
1682 // Now only IEC is supported.
1683 //
1684 return EdbLoadCodBySymbolByIec (Name, Buffer, BufferSize, CodeBufferSize, FuncOffset);
1685 }
1686
1687 VOID *
1688 EdbFindCodeFromObject (
1689 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
1690 IN EFI_DEBUGGER_SYMBOL_OBJECT *Object,
1691 IN CHAR16 *FileName
1692 )
1693 /*++
1694
1695 Routine Description:
1696
1697 Find code from object
1698
1699 Arguments:
1700
1701 Object - Symbol object
1702 FileName - File name
1703
1704 Returns:
1705
1706 CodeBuffer
1707
1708 --*/
1709 {
1710 UINTN EntryIndex;
1711
1712 //
1713 // Go througn each Entry in this Object
1714 //
1715 for (EntryIndex = 0; EntryIndex < Object->EntryCount; EntryIndex++) {
1716 //
1717 // This check is for Function only
1718 //
1719 if ((Object->Entry[EntryIndex].Type != EfiDebuggerSymbolFunction) &&
1720 (Object->Entry[EntryIndex].Type != EfiDebuggerSymbolStaticFunction)) {
1721 continue;
1722 }
1723 //
1724 // Skip match varbss_init function, because they has no source code
1725 //
1726 if (AsciiStrnCmp (Object->Entry[EntryIndex].Name, "varbss_init", sizeof("varbss_init") - 1) == 0) {
1727 continue;
1728 }
1729 //
1730 // check the name
1731 //
1732 if (!MatchObjAndCod (Object->Entry[EntryIndex].ObjName, FileName)) {
1733 continue;
1734 }
1735 //
1736 // found it, return source buffer
1737 //
1738 if (Object->Entry[EntryIndex].CodBuffer != NULL) {
1739 return Object->Entry[EntryIndex].SourceBuffer;
1740 }
1741 }
1742
1743 //
1744 // not found
1745 //
1746 return NULL;
1747 }
1748
1749 EFI_STATUS
1750 EdbLoadCode (
1751 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
1752 IN CHAR16 *MapFileName,
1753 IN CHAR16 *FileName,
1754 IN UINTN BufferSize,
1755 IN VOID *Buffer
1756 )
1757 /*++
1758
1759 Routine Description:
1760
1761 Load code
1762
1763 Arguments:
1764
1765 DebuggerPrivate - EBC Debugger private data structure
1766 MapFileName - Symbol file name
1767 FileName - Code file name
1768 BufferSize - Code file buffer size
1769 Buffer - Code file buffer
1770
1771 Returns:
1772
1773 EFI_SUCCESS - Code loaded successfully
1774
1775 --*/
1776 {
1777 EFI_DEBUGGER_SYMBOL_OBJECT *Object;
1778 UINTN ObjectIndex;
1779 UINTN EntryIndex;
1780 VOID *SourceBuffer;
1781 EFI_STATUS Status;
1782
1783 //
1784 // Find Symbol
1785 //
1786 Object = EdbFindSymbolFile (DebuggerPrivate, MapFileName, &ObjectIndex);
1787 if (Object == NULL) {
1788 EDBPrint (L"SymbolFile is not loaded!\n");
1789 return EFI_NOT_FOUND;
1790 } else {
1791 //
1792 // Check duplicated File
1793 //
1794 SourceBuffer = EdbFindCodeFromObject (DebuggerPrivate, Object, FileName);
1795 if (SourceBuffer != NULL) {
1796 //
1797 // unnload duplicated code
1798 //
1799 Status = EdbUnloadCode (DebuggerPrivate, MapFileName, FileName, &SourceBuffer);
1800 if (EFI_ERROR(Status)) {
1801 DEBUG ((DEBUG_ERROR, "Unload Duplicated Code File Error!\n"));
1802 return Status;
1803 }
1804 Status = EdbDeleteCodeBuffer (DebuggerPrivate, MapFileName, FileName, SourceBuffer);
1805 if (EFI_ERROR(Status)) {
1806 DEBUG ((DEBUG_ERROR, "Delete Duplicated Code File Error!\n"));
1807 return Status;
1808 }
1809 }
1810 }
1811
1812 //
1813 // Go through each SymbolEntry
1814 //
1815 for (EntryIndex = 0; EntryIndex < Object->EntryCount; EntryIndex++) {
1816 //
1817 // load symbol for function only
1818 //
1819 if ((Object->Entry[EntryIndex].Type != EfiDebuggerSymbolFunction) &&
1820 (Object->Entry[EntryIndex].Type != EfiDebuggerSymbolStaticFunction)) {
1821 continue;
1822 }
1823 //
1824 // skip varbss_init
1825 //
1826 if (AsciiStrnCmp (Object->Entry[EntryIndex].Name, "varbss_init", sizeof("varbss_init") - 1) == 0) {
1827 continue;
1828 }
1829 //
1830 // Check the name
1831 //
1832 if (!MatchObjAndCod (Object->Entry[EntryIndex].ObjName, FileName)) {
1833 continue;
1834 }
1835 //
1836 // load code for this symbol
1837 //
1838 Object->Entry[EntryIndex].CodBuffer = EdbLoadCodBySymbol (
1839 Object->Entry[EntryIndex].Name,
1840 Buffer,
1841 BufferSize,
1842 &Object->Entry[EntryIndex].CodBufferSize,
1843 &Object->Entry[EntryIndex].FuncOffsetBase
1844 );
1845 if (Object->Entry[EntryIndex].CodBuffer != NULL) {
1846 Object->Entry[EntryIndex].SourceBuffer = Buffer;
1847 }
1848 }
1849
1850 //
1851 // patch end '\0' for each code buffer
1852 //
1853 for (EntryIndex = 0; EntryIndex < Object->EntryCount; EntryIndex++) {
1854 if (Object->Entry[EntryIndex].CodBuffer != NULL) {
1855 *((UINT8 *)Object->Entry[EntryIndex].CodBuffer + Object->Entry[EntryIndex].CodBufferSize) = 0;
1856 DEBUG ((DEBUG_ERROR, " CodeSymbol: %a, FuncOffset: 0x05%x\n", Object->Entry[EntryIndex].Name, Object->Entry[EntryIndex].FuncOffsetBase));
1857 // DEBUG ((DEBUG_ERROR, " [CODE]:\n%a\n", Object->Entry[EntryIndex].CodBuffer));
1858 }
1859 }
1860
1861 //
1862 // Done
1863 //
1864 return EFI_SUCCESS;
1865 }
1866
1867 EFI_STATUS
1868 EdbUnloadCode (
1869 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
1870 IN CHAR16 *MapFileName,
1871 IN CHAR16 *FileName,
1872 OUT VOID **Buffer
1873 )
1874 /*++
1875
1876 Routine Description:
1877
1878 Unload code
1879
1880 Arguments:
1881
1882 DebuggerPrivate - EBC Debugger private data structure
1883 MapFileName - Symbol file name
1884 FileName - Code file name
1885 Buffer - Code file buffer
1886
1887 Returns:
1888
1889 EFI_SUCCESS - Code unloaded successfully
1890
1891 --*/
1892 {
1893 EFI_DEBUGGER_SYMBOL_OBJECT *Object;
1894 UINTN ObjectIndex;
1895 UINTN EntryIndex;
1896
1897 //
1898 // Find Symbol
1899 //
1900 Object = EdbFindSymbolFile (DebuggerPrivate, MapFileName, &ObjectIndex);
1901 if (Object == NULL) {
1902 EDBPrint (L"SymbolFile is not loaded!\n");
1903 return EFI_NOT_FOUND;
1904 }
1905
1906 //
1907 // Find code
1908 //
1909 *Buffer = EdbFindCodeFromObject (DebuggerPrivate, Object, FileName);
1910 if (*Buffer == NULL) {
1911 EDBPrint (L"CodeFile is not loaded!\n");
1912 return EFI_NOT_FOUND;
1913 }
1914
1915 //
1916 // go through each entry
1917 //
1918 for (EntryIndex = 0; EntryIndex < Object->EntryCount; EntryIndex++) {
1919 if ((Object->Entry[EntryIndex].Type != EfiDebuggerSymbolFunction) &&
1920 (Object->Entry[EntryIndex].Type != EfiDebuggerSymbolStaticFunction)) {
1921 continue;
1922 }
1923 if (AsciiStrnCmp (Object->Entry[EntryIndex].Name, "varbss_init", sizeof("varbss_init") - 1) == 0) {
1924 continue;
1925 }
1926 if (!MatchObjAndCod (Object->Entry[EntryIndex].ObjName, FileName)) {
1927 continue;
1928 }
1929 //
1930 // clean up the buffer
1931 //
1932 Object->Entry[EntryIndex].CodBuffer = NULL;
1933 Object->Entry[EntryIndex].CodBufferSize = 0;
1934 Object->Entry[EntryIndex].FuncOffsetBase = 0;
1935 Object->Entry[EntryIndex].SourceBuffer = NULL;
1936 }
1937
1938 //
1939 // Done
1940 //
1941 return EFI_SUCCESS;
1942 }
1943
1944 EFI_STATUS
1945 EdbAddCodeBuffer (
1946 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
1947 IN CHAR16 *MapFileName,
1948 IN CHAR16 *CodeFileName,
1949 IN UINTN SourceBufferSize,
1950 IN VOID *SourceBuffer
1951 )
1952 /*++
1953
1954 Routine Description:
1955
1956 Add code buffer
1957
1958 Arguments:
1959
1960 DebuggerPrivate - EBC Debugger private data structure
1961 MapFileName - Symbol file name
1962 CodeFileName - Code file name
1963 SourceBufferSize- Code buffer size
1964 SourceBuffer - Code buffer
1965
1966 Returns:
1967
1968 EFI_SUCCESS - CodeBuffer added successfully
1969
1970 --*/
1971 {
1972 UINTN Index;
1973 EFI_DEBUGGER_SYMBOL_OBJECT *Object;
1974
1975 //
1976 // Find Symbol
1977 //
1978 Object = EdbFindSymbolFile (DebuggerPrivate, MapFileName, NULL);
1979 if (Object == NULL) {
1980 EDBPrint (L"SymbolFile is not loaded!\n");
1981 return EFI_NOT_FOUND;
1982 }
1983
1984 //
1985 // Add it to last entry
1986 //
1987 for (Index = 0; Object->SourceBuffer[Index] != NULL; Index++) {
1988 ;
1989 }
1990 Object->SourceBuffer[Index] = SourceBuffer;
1991
1992 return EFI_SUCCESS;
1993 }
1994
1995 EFI_STATUS
1996 EdbDeleteCodeBuffer (
1997 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
1998 IN CHAR16 *MapFileName,
1999 IN CHAR16 *CodeFileName,
2000 IN VOID *SourceBuffer
2001 )
2002 /*++
2003
2004 Routine Description:
2005
2006 Delete code buffer
2007
2008 Arguments:
2009
2010 DebuggerPrivate - EBC Debugger private data structure
2011 MapFileName - Symbol file name
2012 CodeFileName - Code file name
2013 SourceBuffer - Code buffer
2014
2015 Returns:
2016
2017 EFI_SUCCESS - CodeBuffer deleted successfully
2018
2019 --*/
2020 {
2021 UINTN Index;
2022 EFI_DEBUGGER_SYMBOL_OBJECT *Object;
2023
2024 //
2025 // Find Symbol
2026 //
2027 Object = EdbFindSymbolFile (DebuggerPrivate, MapFileName, NULL);
2028 if (Object == NULL) {
2029 EDBPrint (L"SymbolFile is not loaded!\n");
2030 return EFI_NOT_FOUND;
2031 }
2032
2033 for (Index = 0; Object->SourceBuffer[Index] != NULL; Index++) {
2034 //
2035 // free the buffer if match
2036 //
2037 if (Object->SourceBuffer[Index] == SourceBuffer) {
2038 gBS->FreePool (SourceBuffer);
2039 break;
2040 }
2041 }
2042
2043 if (Object->SourceBuffer[Index] == NULL) {
2044 //
2045 // not return NOT_FOUND
2046 //
2047 return EFI_SUCCESS;
2048 }
2049
2050 //
2051 // remove the entry
2052 //
2053 Object->SourceBuffer[Index] = NULL;
2054 for (Index = Index + 1; Object->SourceBuffer[Index] != NULL; Index++) {
2055 Object->SourceBuffer[Index - 1] = Object->SourceBuffer[Index];
2056 }
2057 Object->SourceBuffer[Index - 1] = NULL;
2058
2059 return EFI_SUCCESS;
2060 }
2061
2062 CHAR8 *
2063 FindSymbolStr (
2064 IN UINTN Address
2065 )
2066 /*++
2067
2068 Routine Description:
2069
2070 Find the symbol string according to address
2071
2072 Arguments:
2073
2074 Address - Symbol address
2075
2076 Returns:
2077
2078 Symbol string
2079
2080 --*/
2081 {
2082 UINTN ObjectIndex;
2083 EFI_DEBUGGER_SYMBOL_OBJECT *Object;
2084 UINTN EntryIndex;
2085 EFI_DEBUGGER_SYMBOL_ENTRY *Entry;
2086
2087 //
2088 // need we display symbol
2089 //
2090 if (!mDebuggerPrivate.DebuggerSymbolContext.DisplaySymbol) {
2091 return NULL;
2092 }
2093
2094 //
2095 // Go through each object and entry
2096 //
2097 Object = mDebuggerPrivate.DebuggerSymbolContext.Object;
2098 for (ObjectIndex = 0; ObjectIndex < mDebuggerPrivate.DebuggerSymbolContext.ObjectCount; ObjectIndex++) {
2099 Entry = Object[ObjectIndex].Entry;
2100 for (EntryIndex = 0; EntryIndex < Object[ObjectIndex].EntryCount; EntryIndex++) {
2101 //
2102 // if Address match, return Name
2103 //
2104 if (Address == (Entry[EntryIndex].RVA + Object[ObjectIndex].BaseAddress)) {
2105 return Entry[EntryIndex].Name;
2106 }
2107 }
2108 }
2109
2110 //
2111 // not found
2112 //
2113 return NULL;
2114 }
2115
2116 UINTN
2117 EdbGetLineNumberAndOffsetFromThisLine (
2118 IN VOID *Line,
2119 OUT UINTN *Offset
2120 )
2121 /*++
2122
2123 Routine Description:
2124
2125 Get line number and offset from this line in code file
2126
2127 Arguments:
2128
2129 Line - Line buffer in code file
2130 Offset - Offset to functin entry
2131
2132 Returns:
2133
2134 Line number
2135
2136 --*/
2137 {
2138 UINTN LineNumber;
2139 CHAR8 *LineBuffer;
2140 CHAR8 *FieldBuffer;
2141
2142 LineNumber = (UINTN)-1;
2143 LineBuffer = Line;
2144 *Offset = (UINTN)-1;
2145
2146 while (LineBuffer != NULL) {
2147 //
2148 // Check candidate
2149 //
2150 if (*LineBuffer != ' ') {
2151 return (UINTN)-1;
2152 }
2153
2154 //
2155 // Get Offset
2156 //
2157 if (*(LineBuffer + 2) != ' ') {
2158 if (*Offset == (UINTN)-1) {
2159 FieldBuffer = AsciiStrGetNewTokenField (LineBuffer + 2, " ");
2160 *Offset = AsciiXtoi (FieldBuffer);
2161 PatchForAsciiStrTokenAfter (FieldBuffer, ' ');
2162 }
2163 }
2164
2165 //
2166 // 1. assembly instruction
2167 //
2168 FieldBuffer = AsciiStrGetNewTokenField (LineBuffer, ":");
2169 //
2170 // 2. file path
2171 //
2172 FieldBuffer = AsciiStrGetNextTokenField (":");
2173 PatchForAsciiStrTokenBefore (FieldBuffer, ':');
2174 if (FieldBuffer == NULL) {
2175 //
2176 // candidate found
2177 //
2178 LineNumber = 0;
2179 LineBuffer = AsciiStrGetNextTokenLine ("\n");
2180 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
2181 continue;
2182 }
2183 //
2184 // 3. line number
2185 //
2186 FieldBuffer = AsciiStrGetNextTokenField (":");
2187 PatchForAsciiStrTokenBefore (FieldBuffer, ':');
2188 if (FieldBuffer == NULL) {
2189 //
2190 // impossible, TBD?
2191 //
2192 LineBuffer = AsciiStrGetNextTokenLine ("\n");
2193 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
2194 continue;
2195 }
2196
2197 LineNumber = AsciiAtoi (FieldBuffer);
2198 //
2199 // Not patch after
2200 //
2201
2202 return LineNumber;
2203 }
2204
2205 return (UINTN)-1;
2206 }
2207
2208 typedef enum {
2209 EdbEbcLineSearchTypeAny,
2210 EdbEbcLineSearchTypeFirst,
2211 EdbEbcLineSearchTypeLast,
2212 EdbEbcLineSearchTypeMax,
2213 } EDB_EBC_LINE_SEARCH_TYPE;
2214
2215 UINTN
2216 EdbGetLineNumberFromCode (
2217 IN EFI_DEBUGGER_SYMBOL_ENTRY *Entry,
2218 IN UINTN FuncOffset,
2219 IN EDB_EBC_LINE_SEARCH_TYPE SearchType
2220 )
2221 /*++
2222
2223 Routine Description:
2224
2225 Get line number from this code file
2226
2227 Arguments:
2228
2229 Entry - Symbol entry
2230 FuncOffset - Offset to functin entry
2231 SearchType - Search type for the code
2232
2233 Returns:
2234
2235 Line number
2236
2237 --*/
2238 {
2239 CHAR8 *LineBuffer;
2240 UINTN LineNumber;
2241 UINTN Offset;
2242 UINTN CandidateLineNumber;
2243 UINTN CandidateOffset;
2244
2245 if (SearchType < 0 || SearchType >= EdbEbcLineSearchTypeMax) {
2246 return (UINTN)-1;
2247 }
2248
2249 LineNumber = (UINTN)-1;
2250 CandidateLineNumber = (UINTN)-1;
2251 CandidateOffset = (UINTN)-1;
2252 LineBuffer = AsciiStrGetNewTokenLine (Entry->CodBuffer, "\n");
2253 while (LineBuffer != NULL) {
2254 if (*LineBuffer != ' ') {
2255 LineBuffer = AsciiStrGetNextTokenLine ("\n");
2256 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
2257 continue;
2258 }
2259
2260 //
2261 // Get Info
2262 //
2263 LineNumber = EdbGetLineNumberAndOffsetFromThisLine (LineBuffer, &Offset);
2264
2265 //
2266 // Check offset
2267 //
2268 if (Offset != FuncOffset) {
2269 //
2270 // Check last offset match
2271 //
2272 if (CandidateOffset == FuncOffset) {
2273 if (SearchType == EdbEbcLineSearchTypeLast) {
2274 PatchForAsciiStrTokenAfter (LineBuffer, '\n');
2275 if (CandidateLineNumber != LineNumber) {
2276 return CandidateLineNumber;
2277 } else {
2278 return (UINTN)-1;
2279 }
2280 } else {
2281 //
2282 // impossible, TBD?
2283 //
2284 }
2285 }
2286
2287 LineBuffer = AsciiStrGetNextTokenLine ("\n");
2288 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
2289 CandidateLineNumber = LineNumber;
2290 continue;
2291 }
2292
2293 //
2294 // Offset match, more check
2295 //
2296 if (SearchType == EdbEbcLineSearchTypeAny) {
2297 PatchForAsciiStrTokenAfter (LineBuffer, '\n');
2298 return LineNumber;
2299 }
2300
2301 if (SearchType == EdbEbcLineSearchTypeFirst) {
2302 //
2303 // Check last line
2304 //
2305 PatchForAsciiStrTokenAfter (LineBuffer, '\n');
2306 if (CandidateLineNumber != LineNumber) {
2307 return LineNumber;
2308 } else {
2309 return (UINTN)-1;
2310 }
2311 }
2312
2313 CandidateLineNumber = LineNumber;
2314 CandidateOffset = Offset;
2315
2316 LineBuffer = AsciiStrGetNextTokenLine ("\n");
2317 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
2318 }
2319
2320 //
2321 // Check last offset match
2322 //
2323 if (CandidateOffset == FuncOffset) {
2324 if (SearchType == EdbEbcLineSearchTypeLast) {
2325 return CandidateLineNumber;
2326 }
2327 }
2328
2329 return (UINTN)-1;
2330 }
2331
2332 VOID *
2333 EdbGetSourceStrFromCodeByLine (
2334 IN EFI_DEBUGGER_SYMBOL_ENTRY *Entry,
2335 IN UINTN LineNumber,
2336 IN VOID **FuncEnd
2337 )
2338 /*++
2339
2340 Routine Description:
2341
2342 Get the source string from this code file by line
2343
2344 Arguments:
2345
2346 Entry - Symbol entry
2347 LineNumber - line number
2348 FuncEnd - Function end
2349
2350 Returns:
2351
2352 Funtion start
2353
2354 --*/
2355 {
2356 CHAR8 *LineBuffer;
2357 CHAR8 *FieldBuffer;
2358 VOID *FuncStart;
2359 UINTN Number;
2360
2361 FuncStart = NULL;
2362 LineBuffer = AsciiStrGetNewTokenLine (Entry->CodBuffer, "\n");
2363 while (LineBuffer != NULL) {
2364 if (*LineBuffer != ';') {
2365 if (FuncStart != NULL) {
2366 //
2367 // Over
2368 //
2369 *FuncEnd = LineBuffer - 1;
2370 PatchForAsciiStrTokenAfter (LineBuffer, '\n');
2371 return FuncStart;
2372 }
2373 LineBuffer = AsciiStrGetNextTokenLine ("\n");
2374 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
2375 continue;
2376 }
2377
2378 //
2379 // Check LineNumber
2380 //
2381 FieldBuffer = AsciiStrGetNewTokenField (LineBuffer + 1, " ");
2382 Number = AsciiAtoi (FieldBuffer);
2383 PatchForAsciiStrTokenAfter (FieldBuffer, ' ');
2384 if (Number != LineNumber) {
2385 LineBuffer = AsciiStrGetNextTokenLine ("\n");
2386 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
2387 continue;
2388 }
2389
2390 //
2391 // Line match, get line number
2392 //
2393 if (FuncStart == NULL) {
2394 FuncStart = LineBuffer;
2395 }
2396
2397 LineBuffer = AsciiStrGetNextTokenLine ("\n");
2398 PatchForAsciiStrTokenBefore (LineBuffer, '\n');
2399 }
2400
2401 return NULL;
2402 }
2403
2404 VOID *
2405 EdbGetSourceStrFromCode (
2406 IN EFI_DEBUGGER_SYMBOL_ENTRY *Entry,
2407 IN UINTN FuncOffset,
2408 IN VOID **FuncEnd
2409 )
2410 /*++
2411
2412 Routine Description:
2413
2414 Get source string from this code file
2415
2416 Arguments:
2417
2418 Entry - Symbol entry
2419 FuncOffset - Offset to functin entry
2420 FuncEnd - Function end
2421
2422 Returns:
2423
2424 Funtion start
2425
2426 --*/
2427 {
2428 UINTN LineNumber;
2429
2430 //
2431 // Only search the last line, then display
2432 //
2433 LineNumber = EdbGetLineNumberFromCode (Entry, FuncOffset, EdbEbcLineSearchTypeLast);
2434 if (LineNumber == (UINTN)-1) {
2435 return NULL;
2436 }
2437
2438 return EdbGetSourceStrFromCodeByLine (Entry, LineNumber, FuncEnd);
2439 }
2440
2441 UINTN
2442 EdbPrintSource (
2443 IN UINTN Address,
2444 IN BOOLEAN IsPrint
2445 )
2446 /*++
2447
2448 Routine Description:
2449
2450 Print source
2451
2452 Arguments:
2453
2454 Address - Instruction address
2455 IsPrint - Whether need to print
2456
2457 Returns:
2458
2459 1 - find the source
2460 0 - not find the source
2461
2462 --*/
2463 {
2464 UINTN SymbolAddress;
2465 EFI_DEBUGGER_SYMBOL_OBJECT *RetObject;
2466 EFI_DEBUGGER_SYMBOL_ENTRY *RetEntry;
2467 UINTN FuncOffset;
2468 UINT8 *FuncStart;
2469 UINT8 *FuncEnd;
2470 UINT8 *FuncIndex;
2471 CHAR8 Buffer[EFI_DEBUG_MAX_PRINT_BUFFER];
2472 UINTN BufferSize;
2473
2474 //
2475 // need we display symbol
2476 //
2477 if (!mDebuggerPrivate.DebuggerSymbolContext.DisplaySymbol) {
2478 return 0 ;
2479 }
2480
2481 //
2482 // find the symbol address
2483 //
2484 SymbolAddress = EbdFindSymbolAddress (
2485 Address,
2486 EdbMatchSymbolTypeLowerAddress,
2487 &RetObject,
2488 &RetEntry
2489 );
2490 if (SymbolAddress == 0) {
2491 return 0 ;
2492 }
2493
2494 FuncOffset = Address - SymbolAddress + RetEntry->FuncOffsetBase;
2495
2496 //
2497 // Get Func String
2498 //
2499 FuncStart = EdbGetSourceStrFromCode (RetEntry, FuncOffset, (VOID**) &FuncEnd);
2500 if (FuncStart == NULL) {
2501 return 0 ;
2502 }
2503
2504 //
2505 // check whether need to real print
2506 //
2507 if (!IsPrint) {
2508 return 1;
2509 }
2510
2511 *(UINT8 *)FuncEnd = 0;
2512
2513 //
2514 // seperate buffer by \n, so that \r can be added.
2515 //
2516 FuncIndex = FuncStart;
2517 while (*FuncIndex != 0) {
2518 if (*FuncIndex == '\n') {
2519 if ((FuncIndex - FuncStart) < (EFI_DEBUG_MAX_PRINT_BUFFER - 3)) {
2520 BufferSize = FuncIndex - FuncStart;
2521 } else {
2522 BufferSize = EFI_DEBUG_MAX_PRINT_BUFFER - 3;
2523 }
2524 if (BufferSize != 0) {
2525 CopyMem (Buffer, FuncStart, BufferSize);
2526 }
2527 Buffer[BufferSize] = 0;
2528 EDBPrint (L"%a\n", Buffer);
2529 FuncStart = FuncIndex + 1;
2530 FuncIndex = FuncStart;
2531 } else {
2532 FuncIndex ++;
2533 }
2534 }
2535
2536 //
2537 // Patch the end
2538 //
2539 *(UINT8 *)FuncEnd = '\n';
2540
2541 return 1 ;
2542 }
2543
2544 VOID
2545 GetMapfileAndSymbol (
2546 IN CHAR16 *Symbol,
2547 OUT CHAR16 **MapfileName,
2548 OUT CHAR16 **SymbolName
2549 )
2550 /*++
2551
2552 Routine Description:
2553
2554 Get Mapfile and SymbolName from one symbol format: [MapFileName:]SymbolName
2555
2556 Arguments:
2557
2558 Symbol - whole Symbol name
2559 MapfileName - the mapfile name in the symbol
2560 SymbolName - the symbol name in the symbol
2561
2562 Returns:
2563
2564 None
2565
2566 --*/
2567 {
2568 CHAR16 *Ch;
2569
2570 *MapfileName = NULL;
2571 *SymbolName = Symbol;
2572
2573 for (Ch = Symbol; *Ch != 0; Ch++) {
2574 //
2575 // Find split char
2576 //
2577 if (*Ch == L':') {
2578 *MapfileName = Symbol;
2579 *Ch = 0;
2580 *SymbolName = Ch + 1;
2581 break;
2582 }
2583 }
2584
2585 return ;
2586 }
2587
2588 EFI_STATUS
2589 Symboltoi (
2590 IN CHAR16 *Symbol,
2591 OUT UINTN *Address
2592 )
2593 /*++
2594
2595 Routine Description:
2596
2597 Convert a symbol to an address
2598
2599 Arguments:
2600
2601 Symbol - Symbol name
2602 Address - Symbol address
2603
2604 Returns:
2605
2606 EFI_SUCCESS - symbol found and address returned.
2607 EFI_NOT_FOUND - symbol not found
2608 EFI_NO_MAPPING - duplicated symbol not found
2609
2610 --*/
2611 {
2612 UINTN ObjectIndex;
2613 EFI_DEBUGGER_SYMBOL_OBJECT *Object;
2614 UINTN EntryIndex;
2615 EFI_DEBUGGER_SYMBOL_ENTRY *Entry;
2616 CHAR16 *SymbolName;
2617 CHAR16 *MapfileName;
2618
2619 //
2620 // Split one symbol to mapfile name and symbol name
2621 //
2622 GetMapfileAndSymbol (Symbol, &MapfileName, &SymbolName);
2623
2624 *Address = 0;
2625 //
2626 // Go through each object
2627 //
2628 Object = mDebuggerPrivate.DebuggerSymbolContext.Object;
2629 for (ObjectIndex = 0; ObjectIndex < mDebuggerPrivate.DebuggerSymbolContext.ObjectCount; ObjectIndex++) {
2630 //
2631 // Check MapfileName
2632 //
2633 if ((MapfileName != NULL) && (StriCmp (Object[ObjectIndex].Name, MapfileName) != 0)) {
2634 continue;
2635 }
2636 //
2637 // Go through each entry
2638 //
2639 Entry = Object[ObjectIndex].Entry;
2640 for (EntryIndex = 0; EntryIndex < Object[ObjectIndex].EntryCount; EntryIndex++) {
2641 //
2642 // Check SymbolName (case sensitive)
2643 //
2644 if (StrCmpUnicodeAndAscii (SymbolName, Entry[EntryIndex].Name) == 0) {
2645 if ((*Address != 0) && (MapfileName == NULL)) {
2646 //
2647 // Find the duplicated symbol
2648 //
2649 EDBPrint (L"Duplicated Symbol found!\n");
2650 return EFI_NO_MAPPING;
2651 } else {
2652 //
2653 // record Address
2654 //
2655 *Address = (Entry[EntryIndex].RVA + Object[ObjectIndex].BaseAddress);
2656 }
2657 }
2658 }
2659 }
2660
2661 if (*Address == 0) {
2662 //
2663 // Not found
2664 //
2665 return EFI_NOT_FOUND;
2666 }
2667
2668 return EFI_SUCCESS;
2669 }