diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/dlfcn.c | 100 |
1 files changed, 52 insertions, 48 deletions
diff --git a/src/dlfcn.c b/src/dlfcn.c index 5dd1ccf..abbd58d 100644 --- a/src/dlfcn.c +++ b/src/dlfcn.c | |||
@@ -512,37 +512,38 @@ static BOOL get_image_section( HMODULE module, int index, void **ptr, DWORD *siz | |||
512 | return TRUE; | 512 | return TRUE; |
513 | } | 513 | } |
514 | 514 | ||
515 | /* Return symbol name for a given address */ | 515 | /* Return symbol name for a given address from export table */ |
516 | static const char *get_symbol_name( HMODULE module, IMAGE_IMPORT_DESCRIPTOR *iid, void *addr, void **func_address ) | 516 | static const char *get_export_symbol_name( HMODULE module, IMAGE_EXPORT_DIRECTORY *ied, void *addr, void **func_address ) |
517 | { | 517 | { |
518 | int i; | 518 | DWORD i; |
519 | void *candidateAddr = NULL; | 519 | void *candidateAddr = NULL; |
520 | const char *candidateName = NULL; | 520 | int candidateIndex = -1; |
521 | BYTE *base = (BYTE *) module; /* Required to have correct calculations */ | 521 | BYTE *base = (BYTE *) module; |
522 | DWORD *functionAddressesOffsets = (DWORD *) (base + ied->AddressOfFunctions); | ||
523 | DWORD *functionNamesOffsets = (DWORD *) (base + ied->AddressOfNames); | ||
524 | USHORT *functionNameOrdinalsIndexes = (USHORT *) (base + ied->AddressOfNameOrdinals); | ||
522 | 525 | ||
523 | for( i = 0; iid[i].Characteristics != 0 && iid[i].FirstThunk != 0; i++ ) | 526 | for( i = 0; i < ied->NumberOfFunctions; i++ ) |
524 | { | 527 | { |
525 | IMAGE_THUNK_DATA *thunkILT = (IMAGE_THUNK_DATA *)( base + iid[i].Characteristics ); | 528 | if( (void *) ( base + functionAddressesOffsets[i] ) > addr || candidateAddr >= (void *) ( base + functionAddressesOffsets[i] ) ) |
526 | IMAGE_THUNK_DATA *thunkIAT = (IMAGE_THUNK_DATA *)( base + iid[i].FirstThunk ); | 529 | continue; |
527 | 530 | ||
528 | for( ; thunkILT->u1.AddressOfData != 0; thunkILT++, thunkIAT++ ) | 531 | candidateAddr = (void *) ( base + functionAddressesOffsets[i] ); |
529 | { | 532 | candidateIndex = i; |
530 | IMAGE_IMPORT_BY_NAME *nameData; | 533 | } |
531 | 534 | ||
532 | if( IMAGE_SNAP_BY_ORDINAL( thunkILT->u1.Ordinal ) ) | 535 | if( candidateIndex == -1 ) |
533 | continue; | 536 | return NULL; |
534 | 537 | ||
535 | if( (void *) thunkIAT->u1.Function > addr || candidateAddr >= (void *) thunkIAT->u1.Function ) | 538 | *func_address = candidateAddr; |
536 | continue; | ||
537 | 539 | ||
538 | candidateAddr = (void *) thunkIAT->u1.Function; | 540 | for( i = 0; i < ied->NumberOfNames; i++ ) |
539 | nameData = (IMAGE_IMPORT_BY_NAME *)( base + (ULONG_PTR) thunkILT->u1.AddressOfData ); | 541 | { |
540 | candidateName = (const char *) nameData->Name; | 542 | if( functionNameOrdinalsIndexes[i] == candidateIndex ) |
541 | } | 543 | return (const char *) ( base + functionNamesOffsets[i] ); |
542 | } | 544 | } |
543 | 545 | ||
544 | *func_address = candidateAddr; | 546 | return NULL; |
545 | return candidateName; | ||
546 | } | 547 | } |
547 | 548 | ||
548 | static BOOL is_valid_address( void *addr ) | 549 | static BOOL is_valid_address( void *addr ) |
@@ -608,11 +609,14 @@ static void *get_address_from_import_address_table( void *iat, DWORD iat_size, v | |||
608 | /* Holds module filename */ | 609 | /* Holds module filename */ |
609 | static char module_filename[2*MAX_PATH]; | 610 | static char module_filename[2*MAX_PATH]; |
610 | 611 | ||
611 | static BOOL fill_module_info( void *addr, Dl_info *info ) | 612 | static BOOL fill_info( void *addr, Dl_info *info ) |
612 | { | 613 | { |
613 | HMODULE hModule; | 614 | HMODULE hModule; |
614 | DWORD dwSize; | 615 | DWORD dwSize; |
616 | IMAGE_EXPORT_DIRECTORY *ied; | ||
617 | void *funcAddress = NULL; | ||
615 | 618 | ||
619 | /* Get module of the specified address */ | ||
616 | if( !GetModuleHandleExA( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, addr, &hModule ) || hModule == NULL ) | 620 | if( !GetModuleHandleExA( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, addr, &hModule ) || hModule == NULL ) |
617 | return FALSE; | 621 | return FALSE; |
618 | 622 | ||
@@ -621,8 +625,16 @@ static BOOL fill_module_info( void *addr, Dl_info *info ) | |||
621 | if( dwSize == 0 || dwSize == sizeof( module_filename ) ) | 625 | if( dwSize == 0 || dwSize == sizeof( module_filename ) ) |
622 | return FALSE; | 626 | return FALSE; |
623 | 627 | ||
624 | info->dli_fbase = (void *) hModule; | ||
625 | info->dli_fname = module_filename; | 628 | info->dli_fname = module_filename; |
629 | info->dli_fbase = (void *) hModule; | ||
630 | |||
631 | /* Find function name and function address in module's export table */ | ||
632 | if( get_image_section( hModule, IMAGE_DIRECTORY_ENTRY_EXPORT, (void **) &ied, NULL ) ) | ||
633 | info->dli_sname = get_export_symbol_name( hModule, ied, addr, &funcAddress ); | ||
634 | else | ||
635 | info->dli_sname = NULL; | ||
636 | |||
637 | info->dli_saddr = info->dli_sname == NULL ? NULL : funcAddress != NULL ? funcAddress : addr; | ||
626 | 638 | ||
627 | return TRUE; | 639 | return TRUE; |
628 | } | 640 | } |
@@ -630,36 +642,32 @@ static BOOL fill_module_info( void *addr, Dl_info *info ) | |||
630 | DLFCN_EXPORT | 642 | DLFCN_EXPORT |
631 | int dladdr( void *addr, Dl_info *info ) | 643 | int dladdr( void *addr, Dl_info *info ) |
632 | { | 644 | { |
633 | void *realAddr, *funcAddress = NULL; | 645 | if( info == NULL ) |
634 | HMODULE hModule; | ||
635 | IMAGE_IMPORT_DESCRIPTOR *iid; | ||
636 | DWORD iidSize = 0; | ||
637 | |||
638 | if( addr == NULL || info == NULL ) | ||
639 | return 0; | ||
640 | |||
641 | hModule = GetModuleHandleA( NULL ); | ||
642 | if( hModule == NULL ) | ||
643 | return 0; | 646 | return 0; |
644 | 647 | ||
645 | if( !is_valid_address( addr ) ) | 648 | if( !is_valid_address( addr ) ) |
646 | return 0; | 649 | return 0; |
647 | 650 | ||
648 | realAddr = addr; | ||
649 | |||
650 | if( !get_image_section( hModule, IMAGE_DIRECTORY_ENTRY_IMPORT, (void **) &iid, &iidSize ) ) | ||
651 | return 0; | ||
652 | |||
653 | if( is_import_thunk( addr ) ) | 651 | if( is_import_thunk( addr ) ) |
654 | { | 652 | { |
655 | void *iat; | 653 | void *iat; |
656 | void *iatAddr = NULL; | 654 | DWORD iatSize; |
657 | DWORD iatSize = 0; | 655 | HMODULE hModule; |
656 | |||
657 | /* Get module of the import thunk address */ | ||
658 | if( !GetModuleHandleExA( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, addr, &hModule ) || hModule == NULL ) | ||
659 | return 0; | ||
658 | 660 | ||
659 | if( !get_image_section( hModule, IMAGE_DIRECTORY_ENTRY_IAT, &iat, &iatSize ) ) | 661 | if( !get_image_section( hModule, IMAGE_DIRECTORY_ENTRY_IAT, &iat, &iatSize ) ) |
660 | { | 662 | { |
661 | /* Fallback for cases where the iat is not defined, | 663 | /* Fallback for cases where the iat is not defined, |
662 | * for example i586-mingw32msvc-gcc */ | 664 | * for example i586-mingw32msvc-gcc */ |
665 | IMAGE_IMPORT_DESCRIPTOR *iid; | ||
666 | DWORD iidSize; | ||
667 | |||
668 | if( !get_image_section( hModule, IMAGE_DIRECTORY_ENTRY_IMPORT, (void **) &iid, &iidSize ) ) | ||
669 | return 0; | ||
670 | |||
663 | if( iid == NULL || iid->Characteristics == 0 || iid->FirstThunk == 0 ) | 671 | if( iid == NULL || iid->Characteristics == 0 || iid->FirstThunk == 0 ) |
664 | return 0; | 672 | return 0; |
665 | 673 | ||
@@ -668,19 +676,15 @@ int dladdr( void *addr, Dl_info *info ) | |||
668 | iatSize = iidSize - (DWORD) ( (BYTE *) iat - (BYTE *) iid ); | 676 | iatSize = iidSize - (DWORD) ( (BYTE *) iat - (BYTE *) iid ); |
669 | } | 677 | } |
670 | 678 | ||
671 | iatAddr = get_address_from_import_address_table( iat, iatSize, addr ); | 679 | addr = get_address_from_import_address_table( iat, iatSize, addr ); |
672 | if( iatAddr == NULL ) | ||
673 | return 0; | ||
674 | 680 | ||
675 | realAddr = iatAddr; | 681 | if( !is_valid_address( addr ) ) |
682 | return 0; | ||
676 | } | 683 | } |
677 | 684 | ||
678 | if( !fill_module_info( realAddr, info ) ) | 685 | if( !fill_info( addr, info ) ) |
679 | return 0; | 686 | return 0; |
680 | 687 | ||
681 | info->dli_sname = get_symbol_name( hModule, iid, realAddr, &funcAddress ); | ||
682 | |||
683 | info->dli_saddr = !info->dli_sname ? NULL : funcAddress ? funcAddress : realAddr; | ||
684 | return 1; | 688 | return 1; |
685 | } | 689 | } |
686 | 690 | ||