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