// adapted from http://gcc.gnu.org/ml/java-patches/2006-q2/msg00511.html int dladdr(const void *addr, Dl_info *info) { MEMORY_BASIC_INFORMATION mbi; HMODULE hMod; printf("addr: %p\n", addr); if (!VirtualQuery (addr, &mbi, sizeof (mbi))) { save_err_str("VirtualQuery() failed!\n"); return 0; } hMod = (HMODULE) mbi.AllocationBase; char module_name[MAX_PATH]; // FIXME: We explicitly use the ANSI variant of the function here. if (!GetModuleFileNameA (hMod, module_name, sizeof (module_name))) { save_err_str("GetModuleFileNameA() failed!"); return 0; } strcpy (info->dli_fname, module_name); info->dli_fbase = mbi.BaseAddress; // this is *probably* right info->dli_saddr = (char*)addr; strcpy (info->dli_sname, module_name); return 1; }
static void save_err_ptr_str(const void *ptr) { char ptr_buf[19]; sprintf( ptr_buf, "0x%p", ptr); save_err_str( ptr_buf ); }
void *dlsym( void *handle, const char *name ) { FARPROC symbol; current_error = NULL; symbol = GetProcAddress( handle, name ); if( symbol == NULL ) { HMODULE hModule; /* If the handle for the original program file is passed, also search * in all globally loaded objects. */ hModule = GetModuleHandle( NULL ); if( hModule == handle ) { global_object *pobject; for( pobject = &first_object; pobject ; pobject = pobject->next ) { if( pobject->hModule ) { symbol = GetProcAddress( pobject->hModule, name ); if( symbol != NULL ) break; } } } } if( symbol == NULL ) save_err_str( name ); return (void*) symbol; }
void *dlopen( const char *file, int mode ) { HMODULE hModule; UINT uMode; current_error = NULL; /* Do not let Windows display the critical-error-handler message box */ uMode = SetErrorMode( SEM_FAILCRITICALERRORS ); if( file == 0 ) { /* POSIX says that if the value of file is 0, a handle on a global * symbol object must be provided. That object must be able to access * all symbols from the original program file, and any objects loaded * with the RTLD_GLOBAL flag. * The return value from GetModuleHandle( ) allows us to retrieve * symbols only from the original program file. For objects loaded with * the RTLD_GLOBAL flag, we create our own list later on. */ hModule = GetModuleHandle( NULL ); if( !hModule ) save_err_ptr_str( file ); } else { char lpFileName[MAX_PATH]; int i; /* MSDN says backslashes *must* be used instead of forward slashes. */ for( i = 0 ; i < sizeof(lpFileName)-1 ; i++ ) { if( !file[i] ) break; else if( file[i] == '/' ) lpFileName[i] = '\\'; else lpFileName[i] = file[i]; } lpFileName[i] = '\0'; /* POSIX says the search path is implementation-defined. * LOAD_WITH_ALTERED_SEARCH_PATH is used to make it behave more closely * to UNIX's search paths (start with system folders instead of current * folder). */ hModule = LoadLibraryEx( (LPSTR) lpFileName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH ); /* If the object was loaded with RTLD_GLOBAL, add it to list of global * objects, so that its symbols may be retrieved even if the handle for * the original program file is passed. POSIX says that if the same * file is specified in multiple invocations, and any of them are * RTLD_GLOBAL, even if any further invocations use RTLD_LOCAL, the * symbols will remain global. */ if( !hModule ) save_err_str( lpFileName ); else if( (mode & RTLD_GLOBAL) ) global_add( hModule ); } /* Return to previous state of the error-mode bit flags. */ SetErrorMode( uMode ); return (void *) hModule; }
static void save_err_ptr( const void *ptr ) { char ptr_buf[19]; /* 0x<pointer> up to 64 bits. */ sprintf( ptr_buf, "0x%p", ptr ); save_err_str( ptr_buf ); }
void *dlopen(const char *file, int mode) { HMODULE hModule; UINT uMode; current_error = NULL; /* Do not let Windows display the critical-error-handler message box */ uMode = SetErrorMode(SEM_FAILCRITICALERRORS); if( file == 0 ) { /* POSIX says that if the value of file is 0, a handle on a global * symbol object must be provided. That object must be able to access * all symbols from the original program file, and any objects loaded * with the RTLD_GLOBAL flag. * The return value from GetModuleHandle( ) allows us to retrieve * symbols only from the original program file. For objects loaded with * the RTLD_GLOBAL flag, we create our own list later on. */ hModule = GetModuleHandle( NULL ); if( !hModule ) save_err_ptr_str( file ); } else { char lpFileName[MAX_PATH]; int i; /* MSDN says backslashes *must* be used instead of forward slashes. */ for( i = 0 ; i < sizeof(lpFileName)-1 ; i++ ) { if( !file[i] ) break; else if( file[i] == '/' ) lpFileName[i] = '\\'; else lpFileName[i] = file[i]; } lpFileName[i] = '\0'; hModule = LoadLibraryEx( (LPSTR) lpFileName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH ); if( !hModule ) save_err_str( lpFileName ); else if( (mode & RTLD_GLOBAL) ) global_add(hModule); } /* Return to previous state of the error-mode bit flags. */ SetErrorMode( uMode ); return (void *) hModule; }
void *dlsym( void *handle, const char *name ) { FARPROC symbol; HMODULE hModule; current_error = NULL; symbol = GetProcAddress( handle, name ); if( symbol != NULL ) goto end; /* If the handle for the original program file is passed, also search * in all globally loaded objects. */ hModule = GetModuleHandle( NULL ); if( hModule == handle ) { global_object *pobject; for( pobject = &first_object; pobject; pobject = pobject->next ) { if( pobject->hModule ) { symbol = GetProcAddress( pobject->hModule, name ); if( symbol != NULL ) goto end; } } for( pobject = &first_automatic_object; pobject; pobject = pobject->next ) { if( pobject->hModule ) { symbol = GetProcAddress( pobject->hModule, name ); if( symbol != NULL ) goto end; } } } end: if( symbol == NULL ) save_err_str( name ); // warning C4054: 'type cast' : from function pointer 'FARPROC' to data pointer 'void *' #ifdef _MSC_VER #pragma warning( suppress: 4054 ) #endif return (void*) symbol; }
int dladdr(void *addr, Dl_info *info) { MEMORY_BASIC_INFORMATION mbi; if (!VirtualQuery(addr, &mbi, sizeof (mbi))) { save_err_str("VirtualQuery() failed!\n"); return 0; } HMODULE module = (HMODULE)mbi.AllocationBase; char name[MAX_PATH]; if (!GetModuleFileNameA(module, name, sizeof(name))) { save_err_str("GetModuleFileNameA() failed!"); return 0; } strcpy((char *)info->dli_fname, name); info->dli_fbase = mbi.BaseAddress; info->dli_saddr = addr; strcpy((char *)info->dli_sname, name); return 1; }
static void save_err_ptr_str( const void *ptr ) { CHAR ptr_buf[19]; /* 0x<pointer> up to 64 bits. */ #ifdef UNICODE # if ((defined(_WIN32) || defined(WIN32)) && (defined(_MSC_VER)) ) swprintf_s( ptr_buf, 19, UNICODE_L("0x%p"), ptr ); # else swprintf(ptr_buf, 19, UNICODE_L("0x%p"), ptr); # endif #else snprintf( ptr_buf, 19, "0x%p", ptr ); #endif save_err_str( ptr_buf ); }
void *dlopen( const char *file, int mode ) { HMODULE hModule; UINT uMode; current_error = NULL; /* Do not let Windows display the critical-error-handler message box */ uMode = SetErrorMode( SEM_FAILCRITICALERRORS ); if( file == 0 ) { HMODULE hAddtnlMods[1024]; // Already loaded modules HANDLE hCurrentProc = GetCurrentProcess( ); DWORD cbNeeded; /* POSIX says that if the value of file is 0, a handle on a global * symbol object must be provided. That object must be able to access * all symbols from the original program file, and any objects loaded * with the RTLD_GLOBAL flag. * The return value from GetModuleHandle( ) allows us to retrieve * symbols only from the original program file. For objects loaded with * the RTLD_GLOBAL flag, we create our own list later on. For objects * outside of the program file but already loaded (e.g. linked DLLs) * they are added below. */ hModule = GetModuleHandle( NULL ); if( !hModule ) save_err_ptr_str( file ); /* GetModuleHandle( NULL ) only returns the current program file. So * if we want to get ALL loaded module including those in linked DLLs, * we have to use EnumProcessModules( ). */ if( EnumProcessModules( hCurrentProc, hAddtnlMods, sizeof( hAddtnlMods ), &cbNeeded ) != 0 ) { DWORD i; for( i = 0; i < cbNeeded / sizeof( HMODULE ); i++ ) { global_add( &first_automatic_object, hAddtnlMods[i] ); } } auto_ref_count++; } else { char lpFileName[MAX_PATH]; int i; /* MSDN says backslashes *must* be used instead of forward slashes. */ for( i = 0 ; i < sizeof(lpFileName)-1 ; i++ ) { if( !file[i] ) break; else if( file[i] == '/' ) lpFileName[i] = '\\'; else lpFileName[i] = file[i]; } lpFileName[i] = '\0'; /* POSIX says the search path is implementation-defined. * LOAD_WITH_ALTERED_SEARCH_PATH is used to make it behave more closely * to UNIX's search paths (start with system folders instead of current * folder). */ hModule = LoadLibraryEx( (LPSTR) lpFileName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH ); /* If the object was loaded with RTLD_GLOBAL, add it to list of global * objects, so that its symbols may be retrieved even if the handle for * the original program file is passed. POSIX says that if the same * file is specified in multiple invocations, and any of them are * RTLD_GLOBAL, even if any further invocations use RTLD_LOCAL, the * symbols will remain global. */ if( !hModule ) save_err_str( lpFileName ); else if( (mode & RTLD_GLOBAL) ) global_add( &first_object, hModule ); } /* Return to previous state of the error-mode bit flags. */ SetErrorMode( uMode ); return (void *) hModule; }
void *dlsym( void *handle, const char *name ) { FARPROC symbol; HMODULE hModule; #ifdef UNICODE wchar_t namew[MAX_PATH]; wmemset(namew, 0, MAX_PATH); #endif current_error = NULL; symbol = GetProcAddress( (HMODULE) handle, name ); if( symbol != NULL ) goto end; /* If the handle for the original program file is passed, also search * in all globally loaded objects. */ hModule = GetModuleHandle( NULL ); if( hModule == handle ) { global_object *pobject; for( pobject = &first_object; pobject; pobject = pobject->next ) { if( pobject->hModule ) { symbol = GetProcAddress( pobject->hModule, name ); if( symbol != NULL ) goto end; } } for( pobject = &first_automatic_object; pobject; pobject = pobject->next ) { if( pobject->hModule ) { symbol = GetProcAddress( pobject->hModule, name ); if( symbol != NULL ) goto end; } } } end: if( symbol == NULL ) { #ifdef UNICODE size_t converted_chars; size_t str_len = strlen(name) + 1; #if ((defined(_WIN32) || defined(WIN32)) && (defined(_MSC_VER)) ) errno_t err = mbstowcs_s(&converted_chars, namew, str_len, name, str_len); if (err != 0) return NULL; #else mbstowcs(namew, name, str_len); #endif save_err_str( namew ); #else save_err_str( name ); #endif } // warning C4054: 'type cast' : from function pointer 'FARPROC' to data pointer 'void *' #ifdef _MSC_VER #pragma warning( suppress: 4054 ) #endif return (void*) symbol; }
void *dlvsym(void *handle, char *symbol, char *version) { // FIXME save_err_str("dlvsym() not implemented"); return NULL; }