aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
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