aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dlfcn.c100
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 */
516static const char *get_symbol_name( HMODULE module, IMAGE_IMPORT_DESCRIPTOR *iid, void *addr, void **func_address ) 516static 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
548static BOOL is_valid_address( void *addr ) 549static 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 */
609static char module_filename[2*MAX_PATH]; 610static char module_filename[2*MAX_PATH];
610 611
611static BOOL fill_module_info( void *addr, Dl_info *info ) 612static 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 )
630DLFCN_EXPORT 642DLFCN_EXPORT
631int dladdr( void *addr, Dl_info *info ) 643int 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