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