aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPali Rohár <pali.rohar@gmail.com>2021-01-25 23:27:22 +0100
committerPali Rohár <pali.rohar@gmail.com>2021-01-27 18:58:21 +0100
commit86a41b921ca5c4bad1d0d7e54f9276046a25e319 (patch)
treea8b64ba1d9a4cf2432d1f65333a1de1dd6a9299e /src
parenta5af061ce1d1bb3f58e74c48c0698dad59d79937 (diff)
downloaddlfcn-win32-86a41b921ca5c4bad1d0d7e54f9276046a25e319.tar.gz
dlfcn-win32-86a41b921ca5c4bad1d0d7e54f9276046a25e319.tar.bz2
dlfcn-win32-86a41b921ca5c4bad1d0d7e54f9276046a25e319.zip
Function dladdr() now retrieve symbol name and symbol address from both export and import tables
dladdr tests for Windows now should always pass like on other systems.
Diffstat (limited to 'src')
-rw-r--r--src/dlfcn.c106
1 files changed, 80 insertions, 26 deletions
diff --git a/src/dlfcn.c b/src/dlfcn.c
index 5dd1ccf..b52b307 100644
--- a/src/dlfcn.c
+++ b/src/dlfcn.c
@@ -512,8 +512,8 @@ 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 import table */
516static const char *get_symbol_name( HMODULE module, IMAGE_IMPORT_DESCRIPTOR *iid, void *addr, void **func_address ) 516static const char *get_import_symbol_name( HMODULE module, IMAGE_IMPORT_DESCRIPTOR *iid, void *addr, void **func_address )
517{ 517{
518 int i; 518 int i;
519 void *candidateAddr = NULL; 519 void *candidateAddr = NULL;
@@ -545,6 +545,40 @@ static const char *get_symbol_name( HMODULE module, IMAGE_IMPORT_DESCRIPTOR *iid
545 return candidateName; 545 return candidateName;
546} 546}
547 547
548/* Return symbol name for a given address from export table */
549static const char *get_export_symbol_name( HMODULE module, IMAGE_EXPORT_DIRECTORY *ied, void *addr, void **func_address )
550{
551 DWORD i;
552 void *candidateAddr = NULL;
553 int candidateIndex = -1;
554 BYTE *base = (BYTE *) module;
555 DWORD *functionAddressesOffsets = (DWORD *) (base + ied->AddressOfFunctions);
556 DWORD *functionNamesOffsets = (DWORD *) (base + ied->AddressOfNames);
557 USHORT *functionNameOrdinalsIndexes = (USHORT *) (base + ied->AddressOfNameOrdinals);
558
559 for( i = 0; i < ied->NumberOfFunctions; i++ )
560 {
561 if( (void *) ( base + functionAddressesOffsets[i] ) > addr || candidateAddr >= (void *) ( base + functionAddressesOffsets[i] ) )
562 continue;
563
564 candidateAddr = (void *) ( base + functionAddressesOffsets[i] );
565 candidateIndex = i;
566 }
567
568 if( candidateIndex == -1 )
569 return NULL;
570
571 *func_address = candidateAddr;
572
573 for( i = 0; i < ied->NumberOfNames; i++ )
574 {
575 if( functionNameOrdinalsIndexes[i] == candidateIndex )
576 return (const char *) ( base + functionNamesOffsets[i] );
577 }
578
579 return NULL;
580}
581
548static BOOL is_valid_address( void *addr ) 582static BOOL is_valid_address( void *addr )
549{ 583{
550 MEMORY_BASIC_INFORMATION info; 584 MEMORY_BASIC_INFORMATION info;
@@ -608,11 +642,16 @@ static void *get_address_from_import_address_table( void *iat, DWORD iat_size, v
608/* Holds module filename */ 642/* Holds module filename */
609static char module_filename[2*MAX_PATH]; 643static char module_filename[2*MAX_PATH];
610 644
611static BOOL fill_module_info( void *addr, Dl_info *info ) 645static BOOL fill_info( HMODULE hModuleImport, void *addr, Dl_info *info )
612{ 646{
613 HMODULE hModule; 647 HMODULE hModule;
614 DWORD dwSize; 648 DWORD dwSize;
649 IMAGE_EXPORT_DIRECTORY *ied;
650 IMAGE_IMPORT_DESCRIPTOR *iid;
651 const char *name;
652 void *funcAddress = NULL;
615 653
654 /* 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 ) 655 if( !GetModuleHandleExA( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, addr, &hModule ) || hModule == NULL )
617 return FALSE; 656 return FALSE;
618 657
@@ -621,8 +660,27 @@ static BOOL fill_module_info( void *addr, Dl_info *info )
621 if( dwSize == 0 || dwSize == sizeof( module_filename ) ) 660 if( dwSize == 0 || dwSize == sizeof( module_filename ) )
622 return FALSE; 661 return FALSE;
623 662
624 info->dli_fbase = (void *) hModule;
625 info->dli_fname = module_filename; 663 info->dli_fname = module_filename;
664 info->dli_fbase = (void *) hModule;
665 info->dli_sname = NULL;
666
667 /* First try to find function name and function address in module's export table */
668 if( get_image_section( hModule, IMAGE_DIRECTORY_ENTRY_EXPORT, (void **) &ied, NULL ) )
669 info->dli_sname = get_export_symbol_name( hModule, ied, addr, &funcAddress );
670
671 /* If symbol name is not known and we know which module is importing this address
672 * then try to find symbol name in this module's import table as the last resort. */
673 if( info->dli_sname == NULL && hModuleImport != NULL )
674 {
675 if( get_image_section( hModuleImport, IMAGE_DIRECTORY_ENTRY_IMPORT, (void **) &iid, NULL ) )
676 {
677 name = get_import_symbol_name( hModuleImport, iid, addr, &funcAddress );
678 if( name != NULL )
679 info->dli_sname = name;
680 }
681 }
682
683 info->dli_saddr = info->dli_sname == NULL ? NULL : funcAddress != NULL ? funcAddress : addr;
626 684
627 return TRUE; 685 return TRUE;
628} 686}
@@ -630,36 +688,33 @@ static BOOL fill_module_info( void *addr, Dl_info *info )
630DLFCN_EXPORT 688DLFCN_EXPORT
631int dladdr( void *addr, Dl_info *info ) 689int dladdr( void *addr, Dl_info *info )
632{ 690{
633 void *realAddr, *funcAddress = NULL; 691 HMODULE hModule = NULL;
634 HMODULE hModule;
635 IMAGE_IMPORT_DESCRIPTOR *iid;
636 DWORD iidSize = 0;
637 692
638 if( addr == NULL || info == NULL ) 693 if( addr == NULL || info == NULL )
639 return 0; 694 return 0;
640 695
641 hModule = GetModuleHandleA( NULL );
642 if( hModule == NULL )
643 return 0;
644
645 if( !is_valid_address( addr ) ) 696 if( !is_valid_address( addr ) )
646 return 0; 697 return 0;
647 698
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 ) ) 699 if( is_import_thunk( addr ) )
654 { 700 {
655 void *iat; 701 void *iat;
656 void *iatAddr = NULL; 702 DWORD iatSize;
657 DWORD iatSize = 0; 703
704 /* Get module of the import thunk address */
705 if( !GetModuleHandleExA( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, addr, &hModule ) || hModule == NULL )
706 return 0;
658 707
659 if( !get_image_section( hModule, IMAGE_DIRECTORY_ENTRY_IAT, &iat, &iatSize ) ) 708 if( !get_image_section( hModule, IMAGE_DIRECTORY_ENTRY_IAT, &iat, &iatSize ) )
660 { 709 {
661 /* Fallback for cases where the iat is not defined, 710 /* Fallback for cases where the iat is not defined,
662 * for example i586-mingw32msvc-gcc */ 711 * for example i586-mingw32msvc-gcc */
712 IMAGE_IMPORT_DESCRIPTOR *iid;
713 DWORD iidSize;
714
715 if( !get_image_section( hModule, IMAGE_DIRECTORY_ENTRY_IMPORT, (void **) &iid, &iidSize ) )
716 return 0;
717
663 if( iid == NULL || iid->Characteristics == 0 || iid->FirstThunk == 0 ) 718 if( iid == NULL || iid->Characteristics == 0 || iid->FirstThunk == 0 )
664 return 0; 719 return 0;
665 720
@@ -668,19 +723,18 @@ int dladdr( void *addr, Dl_info *info )
668 iatSize = iidSize - (DWORD) ( (BYTE *) iat - (BYTE *) iid ); 723 iatSize = iidSize - (DWORD) ( (BYTE *) iat - (BYTE *) iid );
669 } 724 }
670 725
671 iatAddr = get_address_from_import_address_table( iat, iatSize, addr ); 726 addr = get_address_from_import_address_table( iat, iatSize, addr );
672 if( iatAddr == NULL ) 727
728 if( addr == NULL )
673 return 0; 729 return 0;
674 730
675 realAddr = iatAddr; 731 if( !is_valid_address( addr ) )
732 return 0;
676 } 733 }
677 734
678 if( !fill_module_info( realAddr, info ) ) 735 if( !fill_info( hModule, addr, info ) )
679 return 0; 736 return 0;
680 737
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; 738 return 1;
685} 739}
686 740