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
|
||||
strcpy(gProxyHandle.dmLibName, "libodbc.so");
|
||||
|
||||
dlerror(); /* clear dlerror first */
|
||||
gProxyHandle.dmHandle = dlopen(gProxyHandle.dmLibName, RTLD_LAZY);
|
||||
|
||||
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.nErrorType = ERROR_LIBRARY_NOT_FOUND;
|
||||
return FALSE;
|
||||
|
@ -230,6 +232,7 @@ BOOL ODBC_LoadDMFunctions()
|
|||
if (gProxyHandle.dmHandle == NULL)
|
||||
return FALSE;
|
||||
|
||||
dlerror(); /* clear dlerror first */
|
||||
for ( i = 0; i < NUM_SQLFUNC; i ++ )
|
||||
{
|
||||
gProxyHandle.functions[i] = template_func[i];
|
||||
|
|
|
@ -122,6 +122,7 @@ HMODULE16 BUILTIN_LoadModule( LPCSTR name )
|
|||
strcpy( dllname, name );
|
||||
p = strrchr( dllname, '.' );
|
||||
if (!p) strcat( dllname, ".dll" );
|
||||
for (p = dllname; *p; p++) *p = FILE_tolower(*p);
|
||||
|
||||
for (i = 0; i < nb_dlls; i++)
|
||||
{
|
||||
|
|
|
@ -83,23 +83,25 @@ static void *dlopen_dll( const char *name )
|
|||
{
|
||||
#ifdef HAVE_DL_API
|
||||
int i, namelen = strlen(name);
|
||||
char *buffer, *p;
|
||||
char *buffer, *p, *ext;
|
||||
void *ret = NULL;
|
||||
|
||||
if (!init_done) build_dll_path();
|
||||
|
||||
/* check for .dll or .exe extension to remove */
|
||||
if ((p = strrchr( name, '.' )))
|
||||
{
|
||||
if (!strcasecmp( p, ".dll" ) || !strcasecmp( p, ".exe" )) namelen -= 4;
|
||||
}
|
||||
/* clear dlerror to avoid glibc bug */
|
||||
dlerror();
|
||||
|
||||
buffer = malloc( dll_path_maxlen + namelen + 8 );
|
||||
|
||||
/* store the name at the end of the buffer, prefixed by /lib and followed by .so */
|
||||
p = buffer + dll_path_maxlen;
|
||||
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 );
|
||||
|
||||
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;
|
||||
memcpy( p, dll_paths[i], len );
|
||||
if ((ret = dlopen( p, RTLD_NOW ))) break;
|
||||
dlerror(); /* clear dlerror to avoid glibc bug */
|
||||
}
|
||||
|
||||
/* 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++)
|
||||
{
|
||||
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;
|
||||
builtin_dlls[i].nt = NULL;
|
||||
|
@ -356,6 +359,7 @@ void wine_dll_unload( void *handle )
|
|||
* wine_dll_load_main_exe
|
||||
*
|
||||
* 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 )
|
||||
{
|
||||
|
@ -367,6 +371,7 @@ void *wine_dll_load_main_exe( const char *name, int search_path )
|
|||
if (!path)
|
||||
{
|
||||
/* no path, try only the specified name */
|
||||
dlerror(); /* clear dlerror to avoid glibc bug */
|
||||
ret = dlopen( name, RTLD_NOW );
|
||||
}
|
||||
else
|
||||
|
@ -389,6 +394,7 @@ void *wine_dll_load_main_exe( const char *name, int search_path )
|
|||
if ((len = p - path) > 0)
|
||||
{
|
||||
memcpy( basename - len, path, len );
|
||||
dlerror(); /* clear dlerror to avoid glibc bug */
|
||||
if ((ret = dlopen( basename - len, RTLD_NOW ))) 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 (!ret) dlerror(); /* clear dlerror to avoid glibc bug */
|
||||
#endif /* HAVE_DL_API */
|
||||
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
|
||||
t is returned by HeapAlloc() above and so is also used
|
||||
with HeapFree() below */
|
||||
dlhandle = ELFDLL_dlopen(s,RTLD_NOW);
|
||||
dlerror(); /* clear dlerror because of glibc bug */
|
||||
dlhandle = dlopen(s,RTLD_NOW);
|
||||
if (!dlhandle) {
|
||||
dlerror(); /* clear dlerror because of glibc bug */
|
||||
HeapFree( GetProcessHeap(), 0, t );
|
||||
SetLastError( ERROR_FILE_NOT_FOUND );
|
||||
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");
|
||||
return (FARPROC)0;
|
||||
}
|
||||
dlerror(); /* clear dlerror() first */
|
||||
fun = dlsym(wm->dlhandle,funcName);
|
||||
/* we sometimes have an excess '_' at the beginning of the name */
|
||||
if (!fun && (funcName[0]=='_')) {
|
||||
if (!fun)
|
||||
{
|
||||
dlerror(); /* clear dlerror() to avoid glibc bug */
|
||||
/* we sometimes have an excess '_' at the beginning of the name */
|
||||
if (funcName[0]=='_')
|
||||
{
|
||||
funcName++ ;
|
||||
fun = dlsym(wm->dlhandle,funcName);
|
||||
}
|
||||
if (!fun) dlerror(); /* clear dlerror() to avoid glibc bug */
|
||||
}
|
||||
}
|
||||
if (!fun) {
|
||||
/* Function@nrofargs usually marks a stdcall function
|
||||
* 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;
|
||||
sscanf(t+1,"%d",&nrofargs);
|
||||
fun = dlsym(wm->dlhandle,fn);
|
||||
if (!fun) dlerror(); /* clear dlerror() to avoid glibc bug */
|
||||
HeapFree( GetProcessHeap(), 0, fn );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "wine/library.h"
|
||||
#include "global.h"
|
||||
#include "module.h"
|
||||
#include "file.h"
|
||||
#include "heap.h"
|
||||
#include "main.h"
|
||||
#include "winerror.h"
|
||||
|
@ -46,12 +47,14 @@ void *BUILTIN32_dlopen( const char *name )
|
|||
|
||||
if (!(handle = wine_dll_load( name )))
|
||||
{
|
||||
LPSTR pErr;
|
||||
pErr = dlerror();
|
||||
if (strstr(pErr, "undefined symbol")) /* undef symbol -> ERR() */
|
||||
ERR("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 );
|
||||
LPSTR pErr;
|
||||
if ((pErr = dlerror()))
|
||||
{
|
||||
if (strstr(pErr, "undefined symbol")) /* undef symbol -> ERR() */
|
||||
ERR("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;
|
||||
#else
|
||||
|
@ -136,6 +139,7 @@ WINE_MODREF *BUILTIN32_LoadLibraryExA(LPCSTR path, DWORD flags)
|
|||
strcpy( dllname, name );
|
||||
p = strrchr( dllname, '.' );
|
||||
if (!p) strcat( dllname, ".dll" );
|
||||
for (p = dllname; *p; p++) *p = FILE_tolower(*p);
|
||||
|
||||
if (!(handle = BUILTIN32_dlopen( dllname ))) goto error;
|
||||
|
||||
|
|
Loading…
Reference in New Issue