I am using MinGW-Builds to compile a 32-bit DLL and exe on a 64-bit system. I am using the m32
bit flag. The compilation and linkage stage produces no errors. When I try to run the program, I get:
The application was unable to start correctly (0xc000007b). Click OK to close the application.
I loaded up Dependency Walker and I got the following error message:
Error: Modules with different CPU types were found.
Indeed, Dependency walker shows that my DLL and executable are 32-bit. However, everything else it links against is 64-bit. For example, NTDLL.DLL, MSVCRT.DLL, LIBWINPTHREAD-1.DLL are all marked 64-bit. So, I believe I am not linking against the 32-bit DLLs correctly.
What is the command to get the linker to link against the 32-bit DLLs instead of the 64-bit DLLs?
What exactly am I looking for when I run the 32-bit Dependency Walker profile mode? I get this output in the log window:
--------------------------------------------------------------------------------
Starting profile on 3/31/2014 at 10:14:41 PM
Operating System: Microsoft Windows NT/2000/XP/2003/Vista based Media Center (64-bit), version 6.01.7601 Service Pack 1
Program Executable: c:\mingw\msys\1.0\home\samuel\projects\bmd2\build\debug\32\testcore\BMD2TESTCORE.EXE
Program Arguments:
Starting Directory: C:\MinGW\msys\1.0\home\samuel\projects\bmd2\build\debug\32\testcore\
Search Path: C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\MinGW\bin;C:\MinGW\libexec\gcc\x86_64-pc-mingw32\4.7.0;C:\Users\samuel\gcc\bin;C:\Users\samuel\gcc\libexec\gcc\x86_64-pc-mingw32\4.7.0;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files\Eclipse\adt-bundle\sdk\platform-tools;C:\Program Files\Eclipse\adt-bundle\sdk\tools;C:\Program Files (x86)\QuickTime\QTSystem\;C:\ant\bin;C:\Java\bin;C:\Program Files\TortoiseSVN\bin;C:\Users\samuel\Desktop\work\bmd2\build\debug\lib
Options Selected:
Simulate ShellExecute by inserting any App Paths directories into the PATH environment variable.
Log DllMain calls for process attach and process detach messages.
Log DllMain calls for all other messages, including thread attach and thread detach.
Hook the process to gather more detailed dependency information.
Log LoadLibrary function calls.
Log GetProcAddress function calls.
Log thread information.
Use simple thread numbers instead of actual thread IDs.
Log first chance exceptions.
Log debug output messages.
Log a time stamp with each line of log.
Automatically open and profile child processes.
--------------------------------------------------------------------------------
00:00:00.000: Started "BMD2TESTCORE.EXE" (process 0x1DC) at address 0x00400000 by thread 1. Successfully hooked module.
00:00:00.000: Loaded "NTDLL.DLL" at address 0x778C0000 by thread 1. Successfully hooked module.
00:00:00.031: Loaded "KERNEL32.DLL" at address 0x75510000 by thread 1. Successfully hooked module.
00:00:00.031: Loaded "KERNELBASE.DLL" at address 0x77340000 by thread 1. Successfully hooked module.
00:00:00.031: DllMain(0x77340000, DLL_PROCESS_ATTACH, 0x00000000) in "KERNELBASE.DLL" called by thread 1.
00:00:00.031: DllMain(0x77340000, DLL_PROCESS_ATTACH, 0x00000000) in "KERNELBASE.DLL" returned 1 (0x1) by thread 1.
00:00:00.031: DllMain(0x75510000, DLL_PROCESS_ATTACH, 0x00000000) in "KERNEL32.DLL" called by thread 1.
00:00:00.046: DllMain(0x75510000, DLL_PROCESS_ATTACH, 0x00000000) in "KERNEL32.DLL" returned 1 (0x1) by thread 1.
00:00:00.046: Injected "DEPENDS.DLL" at address 0x08370000 by thread 1.
00:00:00.078: DllMain(0x08370000, DLL_PROCESS_ATTACH, 0x00000000) in "DEPENDS.DLL" called by thread 1.
00:00:00.093: DllMain(0x08370000, DLL_PROCESS_ATTACH, 0x00000000) in "DEPENDS.DLL" returned 1 (0x1) by thread 1.
00:00:00.093: Loaded "MSVCRT.DLL" at address 0x75C90000 by thread 1. Successfully hooked module.
You don't specify the bitness of a DLL when you link against it. You merely specify the name of the DLL. It's up to the loader to find the DLLs with the names that you have specified.
Two of the DLLs that you name, ntdll and msvcrt, are system components. They reside in the system32 directory. Your 32 bit process is subject to the file system redirector. That means that when the loader looks in system32, the redirector silently maps that to syswow64, the 32 bit system directory. That happens transparently so the loader will find 32 bit versions of ntdll and msvcrt.
The error code that you report is 0xC000007B
. That is an NTSTATUS
error code. Specifically STATUS_INVALID_IMAGE_FORMAT
. Which is indeed the error reported when you attempt to load a 64 bit DLL in a 32 bit process. So it seems likely that this is what is happening.
You've done some debugging with Dependency Walker. This is an excellent tool for the job, but in the mode you have used it in (static mode) it does sometimes report false positives. It sounds like you are using the 64 bit version of Dependency Walker. You might get better diagnostics with the 32 bit version.
All that said, what you really need to do is to run your program under the Profile mode of Dependency Walker. That can be found under the Profile menu. When you do this you'll get a stream of diagnostics from the loader, including the name of the DLL that failed to load with error STATUS_INVALID_IMAGE_FORMAT
. At that point it should become clear what has gone wrong.