[Bug 9056] Mono 1.2.4 fails to find mscorlib.dll on startup

wine-bugs at winehq.org wine-bugs at winehq.org
Sat Sep 15 15:53:39 CDT 2007


--- Comment #14 from Anastasius Focht <focht at gmx.net>  2007-09-15 15:53:38 ---
Hello again,

well actually there are more bugs in mono and wine regarding the assembly
loading mechanism. Start your engines ...

used: mono 1.2.5 win32

After using the AOT cache and msvcrt._wspawnvp() workaround i stumbled over
.NET gui app (windows forms) which uses pinvoke() calls to user32.dll.
The loader tries to locate the user32.dll and crashes.

--- snip ---
fixme:msvcrt:_wspawnvp stub
Mono-INFO: Assembly Loader loaded assembly from location: 'C:\Program
Mono-INFO: Config attempting to parse: 'C:\Program
Mono-INFO: Config attempting to parse: 'C:\Program
Mono-INFO: Assembly Ref addref System.Windows.Forms 00196660 -> Mono.Posix
001922E8: 2
Mono-INFO: DllImport attempting to load: 'user32.dll'.
Mono-INFO: DllImport loading location: 'user32.dll.dll'.

  at System.Windows.Forms.XplatUIWin32.GetInstance () <0xffffffff>
  at System.Windows.Forms.XplatUIWin32.GetInstance () <0x00020>
  at System.Windows.Forms.XplatUI..cctor () <0x000b8>
  at (wrapper runtime-invoke)
(object,intptr,intptr,intptr) <0xffffffff>
  at System.Windows.Forms.Application.EnableVisualStyles () <0xffffffff>
  at System.Windows.Forms.Application.EnableVisualStyles () <0x00008>
  at crc32_gui.Program.Main () <0x00008>
  at (wrapper runtime-invoke) crc32_gui.Program.runtime_invoke_void
(object,intptr,intptr,intptr) <0xffffffff>
--- snip ---

Notice the message "DllImport loading location: 'user32.dll.dll'."
Further search in mono source reveals this comes from
mono/mono/metadata/loader.c:mono_lookup_pinvoke_call() which tries to load the
module using a variety of names.
This function calls mono/mono/utils/mono-dl.c:mono_dl_build_path() to return
possible file names of the library.
Well mono_dl_build_path() assumes the library parameter is the "base name of a
library". Which is of course not the case: full name supplied instead. ".dll"
is mistakenly appended for all assemblies.

Next the module should be loaded: 

mono_lookup_pinvoke_call() -> cached_module_load() -> mono_dl_open()

It fails loading dll (LL_SO_OPEN -> w32_load_module -> LoadLibrary()).
Of course: user32.dll.dll wont work.
It tries then again with ".la" suffix appended and fails again.

Now the interesting part, the error handling.
When an error is encountered, LL_SO_ERROR() is called which should return a
formatted (system) error message (pointer to buffer).
LL_SO_ERROR maps to "w32_dlerror" which is this code:

--- snip mono-1-2-5/mono/mono/utils/mono-dl.c ---
static char* w32_dlerror (void)
        char* ret = NULL;
        wchar_t* buf = NULL;
        DWORD code = GetLastError ();

        if (FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
                code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, 0, NULL))
                ret = g_utf16_to_utf8 (buf, wcslen(buf), NULL, NULL, NULL);
                LocalFree (buf);
        return ret;
--- snip mono-1-2-5/mono/mono/utils/mono-dl.c ---

Can you spot the bug?
Hint: FORMAT_MESSAGE_ALLOCATE_BUFFER tells the callee to allocate memory.
Well, try to store the returned buffer pointer in nirvana and fail miserably

So actually it's both: a mono and a wine bug.
Mono should actually do FormatMessage( ...., &buf, ...) and Wine should
actually watch for supplied NULL ptrs in FormatMessageA/W() before trying to
access them (copy).

Now you might think "ok, that's it". No it isnt over yet ;-)
After i quick-fixed wine's FormatMessageA/W to handle buf == NULL case
(returning 0 length) mono crashed again.
Well mono assumes if any error occurs a system generated error message must be
The logging mechanism depends on that. If it fails somehow, like the bug in
mono code itself, which prevents FormatMessageA/W() from returning valid error
msg buffer it crashes by deref null pointer.

--- snip pseudo code ---
ret = call_some_native_func( ... &error_msg)
if( !ret)
  mono_trace( "... %s", error_msg);
  g_free (error_msg);
--- snip pseudo code ---

So there is currently no way to get around these issues without fixing mono
source itself.
Wine should fix the FormatMessageA/W() and msvcrt._wspawnvp() issues.

FOR THE RECORD: the code flow and issues are essentially the same on native
windows platform (except for the FormatMessage bug).
Start console (cmd.exe) there. Enable logging (set MONO_LOG_MASK=debug). Start
mono.exe with some .net app (i used simple 2.0 .net app generated by VC2005/C#)
and see it die.
For more fun, enable AOT cache (set MONO_AOT_CACHE=1). Die.


Configure bugmail: http://bugs.winehq.org/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are watching all bug changes.

More information about the wine-bugs mailing list