Always pass lower-case filenames to wine_dll_load().
Clear dlerror() before and after calls to dlopen/dlsym to work around a glibc bug (thanks to James Abbatiello for tracking the bug).
This commit is contained in:
parent
01eeb01f0b
commit
886604c715
|
@ -196,11 +196,13 @@ BOOL ODBC_LoadDriverManager()
|
||||||
else
|
else
|
||||||
strcpy(gProxyHandle.dmLibName, "libodbc.so");
|
strcpy(gProxyHandle.dmLibName, "libodbc.so");
|
||||||
|
|
||||||
|
dlerror(); /* clear dlerror first */
|
||||||
gProxyHandle.dmHandle = dlopen(gProxyHandle.dmLibName, RTLD_LAZY);
|
gProxyHandle.dmHandle = dlopen(gProxyHandle.dmLibName, RTLD_LAZY);
|
||||||
|
|
||||||
if (gProxyHandle.dmHandle == NULL) /* fail to load unixODBC driver manager */
|
if (gProxyHandle.dmHandle == NULL) /* fail to load unixODBC driver manager */
|
||||||
{
|
{
|
||||||
WARN("failed to open library %s\n", gProxyHandle.dmLibName);
|
const char *err = dlerror();
|
||||||
|
WARN("failed to open library %s: %s\n", gProxyHandle.dmLibName, err);
|
||||||
gProxyHandle.dmLibName[0] = '\0';
|
gProxyHandle.dmLibName[0] = '\0';
|
||||||
gProxyHandle.nErrorType = ERROR_LIBRARY_NOT_FOUND;
|
gProxyHandle.nErrorType = ERROR_LIBRARY_NOT_FOUND;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -230,6 +232,7 @@ BOOL ODBC_LoadDMFunctions()
|
||||||
if (gProxyHandle.dmHandle == NULL)
|
if (gProxyHandle.dmHandle == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
dlerror(); /* clear dlerror first */
|
||||||
for ( i = 0; i < NUM_SQLFUNC; i ++ )
|
for ( i = 0; i < NUM_SQLFUNC; i ++ )
|
||||||
{
|
{
|
||||||
gProxyHandle.functions[i] = template_func[i];
|
gProxyHandle.functions[i] = template_func[i];
|
||||||
|
|
|
@ -122,6 +122,7 @@ HMODULE16 BUILTIN_LoadModule( LPCSTR name )
|
||||||
strcpy( dllname, name );
|
strcpy( dllname, name );
|
||||||
p = strrchr( dllname, '.' );
|
p = strrchr( dllname, '.' );
|
||||||
if (!p) strcat( dllname, ".dll" );
|
if (!p) strcat( dllname, ".dll" );
|
||||||
|
for (p = dllname; *p; p++) *p = FILE_tolower(*p);
|
||||||
|
|
||||||
for (i = 0; i < nb_dlls; i++)
|
for (i = 0; i < nb_dlls; i++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -83,23 +83,25 @@ static void *dlopen_dll( const char *name )
|
||||||
{
|
{
|
||||||
#ifdef HAVE_DL_API
|
#ifdef HAVE_DL_API
|
||||||
int i, namelen = strlen(name);
|
int i, namelen = strlen(name);
|
||||||
char *buffer, *p;
|
char *buffer, *p, *ext;
|
||||||
void *ret = NULL;
|
void *ret = NULL;
|
||||||
|
|
||||||
if (!init_done) build_dll_path();
|
if (!init_done) build_dll_path();
|
||||||
|
|
||||||
/* check for .dll or .exe extension to remove */
|
/* clear dlerror to avoid glibc bug */
|
||||||
if ((p = strrchr( name, '.' )))
|
dlerror();
|
||||||
{
|
|
||||||
if (!strcasecmp( p, ".dll" ) || !strcasecmp( p, ".exe" )) namelen -= 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer = malloc( dll_path_maxlen + namelen + 8 );
|
buffer = malloc( dll_path_maxlen + namelen + 8 );
|
||||||
|
|
||||||
/* store the name at the end of the buffer, prefixed by /lib and followed by .so */
|
/* store the name at the end of the buffer, prefixed by /lib and followed by .so */
|
||||||
p = buffer + dll_path_maxlen;
|
p = buffer + dll_path_maxlen;
|
||||||
memcpy( p, "/lib", 4 );
|
memcpy( p, "/lib", 4 );
|
||||||
for (i = 0, p += 4; i < namelen; i++, p++) *p = tolower(name[i]);
|
p += 4;
|
||||||
|
memcpy( p, name, namelen+1 );
|
||||||
|
ext = strrchr( p, '.' );
|
||||||
|
p += namelen;
|
||||||
|
/* check for .dll or .exe extension to remove */
|
||||||
|
if (ext && (!strcmp( ext, ".dll" ) || !strcmp( ext, ".exe" ))) p = ext;
|
||||||
memcpy( p, ".so", 4 );
|
memcpy( p, ".so", 4 );
|
||||||
|
|
||||||
for (i = 0; i < nb_dll_paths; i++)
|
for (i = 0; i < nb_dll_paths; i++)
|
||||||
|
@ -108,6 +110,7 @@ static void *dlopen_dll( const char *name )
|
||||||
char *p = buffer + dll_path_maxlen - len;
|
char *p = buffer + dll_path_maxlen - len;
|
||||||
memcpy( p, dll_paths[i], len );
|
memcpy( p, dll_paths[i], len );
|
||||||
if ((ret = dlopen( p, RTLD_NOW ))) break;
|
if ((ret = dlopen( p, RTLD_NOW ))) break;
|
||||||
|
dlerror(); /* clear dlerror to avoid glibc bug */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* now try the default dlopen search path */
|
/* now try the default dlopen search path */
|
||||||
|
@ -327,7 +330,7 @@ void *wine_dll_load( const char *filename )
|
||||||
for (i = 0; i < nb_dlls; i++)
|
for (i = 0; i < nb_dlls; i++)
|
||||||
{
|
{
|
||||||
if (!builtin_dlls[i].nt) continue;
|
if (!builtin_dlls[i].nt) continue;
|
||||||
if (!strcasecmp( builtin_dlls[i].filename, filename ))
|
if (!strcmp( builtin_dlls[i].filename, filename ))
|
||||||
{
|
{
|
||||||
const IMAGE_NT_HEADERS *nt = builtin_dlls[i].nt;
|
const IMAGE_NT_HEADERS *nt = builtin_dlls[i].nt;
|
||||||
builtin_dlls[i].nt = NULL;
|
builtin_dlls[i].nt = NULL;
|
||||||
|
@ -356,6 +359,7 @@ void wine_dll_unload( void *handle )
|
||||||
* wine_dll_load_main_exe
|
* wine_dll_load_main_exe
|
||||||
*
|
*
|
||||||
* Try to load the .so for the main exe, optionally searching for it in PATH.
|
* Try to load the .so for the main exe, optionally searching for it in PATH.
|
||||||
|
* Note: dlerror() is cleared before returning because of a glibc bug.
|
||||||
*/
|
*/
|
||||||
void *wine_dll_load_main_exe( const char *name, int search_path )
|
void *wine_dll_load_main_exe( const char *name, int search_path )
|
||||||
{
|
{
|
||||||
|
@ -367,6 +371,7 @@ void *wine_dll_load_main_exe( const char *name, int search_path )
|
||||||
if (!path)
|
if (!path)
|
||||||
{
|
{
|
||||||
/* no path, try only the specified name */
|
/* no path, try only the specified name */
|
||||||
|
dlerror(); /* clear dlerror to avoid glibc bug */
|
||||||
ret = dlopen( name, RTLD_NOW );
|
ret = dlopen( name, RTLD_NOW );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -389,6 +394,7 @@ void *wine_dll_load_main_exe( const char *name, int search_path )
|
||||||
if ((len = p - path) > 0)
|
if ((len = p - path) > 0)
|
||||||
{
|
{
|
||||||
memcpy( basename - len, path, len );
|
memcpy( basename - len, path, len );
|
||||||
|
dlerror(); /* clear dlerror to avoid glibc bug */
|
||||||
if ((ret = dlopen( basename - len, RTLD_NOW ))) break;
|
if ((ret = dlopen( basename - len, RTLD_NOW ))) break;
|
||||||
}
|
}
|
||||||
if (!*p) break;
|
if (!*p) break;
|
||||||
|
@ -397,6 +403,7 @@ void *wine_dll_load_main_exe( const char *name, int search_path )
|
||||||
if (tmp != buffer) free( tmp );
|
if (tmp != buffer) free( tmp );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!ret) dlerror(); /* clear dlerror to avoid glibc bug */
|
||||||
#endif /* HAVE_DL_API */
|
#endif /* HAVE_DL_API */
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
18
loader/elf.c
18
loader/elf.c
|
@ -154,8 +154,10 @@ WINE_MODREF *ELF_LoadLibraryExA( LPCSTR libname, DWORD flags)
|
||||||
points to the ENTIRE DOS filename of the library
|
points to the ENTIRE DOS filename of the library
|
||||||
t is returned by HeapAlloc() above and so is also used
|
t is returned by HeapAlloc() above and so is also used
|
||||||
with HeapFree() below */
|
with HeapFree() below */
|
||||||
dlhandle = ELFDLL_dlopen(s,RTLD_NOW);
|
dlerror(); /* clear dlerror because of glibc bug */
|
||||||
|
dlhandle = dlopen(s,RTLD_NOW);
|
||||||
if (!dlhandle) {
|
if (!dlhandle) {
|
||||||
|
dlerror(); /* clear dlerror because of glibc bug */
|
||||||
HeapFree( GetProcessHeap(), 0, t );
|
HeapFree( GetProcessHeap(), 0, t );
|
||||||
SetLastError( ERROR_FILE_NOT_FOUND );
|
SetLastError( ERROR_FILE_NOT_FOUND );
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -181,12 +183,19 @@ static FARPROC ELF_FindExportedFunction( WINE_MODREF *wm, LPCSTR funcName, BOOL
|
||||||
ERR("Can't import from UNIX dynamic libs by ordinal, sorry.\n");
|
ERR("Can't import from UNIX dynamic libs by ordinal, sorry.\n");
|
||||||
return (FARPROC)0;
|
return (FARPROC)0;
|
||||||
}
|
}
|
||||||
|
dlerror(); /* clear dlerror() first */
|
||||||
fun = dlsym(wm->dlhandle,funcName);
|
fun = dlsym(wm->dlhandle,funcName);
|
||||||
/* we sometimes have an excess '_' at the beginning of the name */
|
if (!fun)
|
||||||
if (!fun && (funcName[0]=='_')) {
|
{
|
||||||
|
dlerror(); /* clear dlerror() to avoid glibc bug */
|
||||||
|
/* we sometimes have an excess '_' at the beginning of the name */
|
||||||
|
if (funcName[0]=='_')
|
||||||
|
{
|
||||||
funcName++ ;
|
funcName++ ;
|
||||||
fun = dlsym(wm->dlhandle,funcName);
|
fun = dlsym(wm->dlhandle,funcName);
|
||||||
}
|
if (!fun) dlerror(); /* clear dlerror() to avoid glibc bug */
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!fun) {
|
if (!fun) {
|
||||||
/* Function@nrofargs usually marks a stdcall function
|
/* Function@nrofargs usually marks a stdcall function
|
||||||
* with nrofargs bytes that are popped at the end
|
* with nrofargs bytes that are popped at the end
|
||||||
|
@ -199,6 +208,7 @@ static FARPROC ELF_FindExportedFunction( WINE_MODREF *wm, LPCSTR funcName, BOOL
|
||||||
nrofargs = 0;
|
nrofargs = 0;
|
||||||
sscanf(t+1,"%d",&nrofargs);
|
sscanf(t+1,"%d",&nrofargs);
|
||||||
fun = dlsym(wm->dlhandle,fn);
|
fun = dlsym(wm->dlhandle,fn);
|
||||||
|
if (!fun) dlerror(); /* clear dlerror() to avoid glibc bug */
|
||||||
HeapFree( GetProcessHeap(), 0, fn );
|
HeapFree( GetProcessHeap(), 0, fn );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "wine/library.h"
|
#include "wine/library.h"
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "module.h"
|
#include "module.h"
|
||||||
|
#include "file.h"
|
||||||
#include "heap.h"
|
#include "heap.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "winerror.h"
|
#include "winerror.h"
|
||||||
|
@ -46,12 +47,14 @@ void *BUILTIN32_dlopen( const char *name )
|
||||||
|
|
||||||
if (!(handle = wine_dll_load( name )))
|
if (!(handle = wine_dll_load( name )))
|
||||||
{
|
{
|
||||||
LPSTR pErr;
|
LPSTR pErr;
|
||||||
pErr = dlerror();
|
if ((pErr = dlerror()))
|
||||||
if (strstr(pErr, "undefined symbol")) /* undef symbol -> ERR() */
|
{
|
||||||
ERR("failed to load %s: %s\n", name, pErr);
|
if (strstr(pErr, "undefined symbol")) /* undef symbol -> ERR() */
|
||||||
else /* WARN() for libraries that are supposed to be native */
|
ERR("failed to load %s: %s\n", name, pErr);
|
||||||
WARN("failed to load %s: %s\n", name, pErr );
|
else /* WARN() for libraries that are supposed to be native */
|
||||||
|
WARN("failed to load %s: %s\n", name, pErr );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return handle;
|
return handle;
|
||||||
#else
|
#else
|
||||||
|
@ -136,6 +139,7 @@ WINE_MODREF *BUILTIN32_LoadLibraryExA(LPCSTR path, DWORD flags)
|
||||||
strcpy( dllname, name );
|
strcpy( dllname, name );
|
||||||
p = strrchr( dllname, '.' );
|
p = strrchr( dllname, '.' );
|
||||||
if (!p) strcat( dllname, ".dll" );
|
if (!p) strcat( dllname, ".dll" );
|
||||||
|
for (p = dllname; *p; p++) *p = FILE_tolower(*p);
|
||||||
|
|
||||||
if (!(handle = BUILTIN32_dlopen( dllname ))) goto error;
|
if (!(handle = BUILTIN32_dlopen( dllname ))) goto error;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue