使用 MinGW-Build 在 64 位系统上编译 32 位 exe -- 编译 32 位 exe,但链接到 64 位

Using MinGW-Builds to compile a 32-bit exe on a 64-bit system -- compiles a 32-bit exe but links against 64-bit DLLs

本文关键字:exe 编译 链接 MinGW-Build 系统 使用      更新时间:2023-10-16

我正在使用MinGW-Builds在64位系统上编译32位DLL和exe。 我正在使用 m32 位标志。 编译和链接阶段不会产生任何错误。 当我尝试运行该程序时,我得到:

应用程序无法正确启动 (0xc000007b)。单击"确定"关闭应用程序。

我加载了依赖沃克,并收到以下错误消息:

错误:找到具有不同 CPU 类型的模块。

事实上,依赖沃克显示我的DLL和可执行文件是32位的。 但是,它链接的其他所有内容都是 64 位的。 例如,NTDLL.DLL、MSVCRT.DLL、LIBWINPTHREAD-1.DLL都标记为64位。 所以,我相信我没有正确链接到 32 位 DLL。

让链接器链接到 32 位 DLL 而不是 64 位 DLL 的命令是什么?

更新

当我运行 32 位依赖关系 Walker 配置文件模式时,我到底在寻找什么? 我在日志窗口中得到这个输出:

--------------------------------------------------------------------------------
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:mingwmsys1.0homesamuelprojectsbmd2builddebug32testcoreBMD2TESTCORE.EXE
Program Arguments: 
Starting Directory: C:MinGWmsys1.0homesamuelprojectsbmd2builddebug32testcore
Search Path: C:Program Files (x86)NVIDIA CorporationPhysXCommon;C:MinGWbin;C:MinGWlibexecgccx86_64-pc-mingw324.7.0;C:Userssamuelgccbin;C:Userssamuelgcclibexecgccx86_64-pc-mingw324.7.0;C:Windowssystem32;C:Windows;C:WindowsSystem32Wbem;C:WindowsSystem32WindowsPowerShellv1.0;C:Program FilesEclipseadt-bundlesdkplatform-tools;C:Program FilesEclipseadt-bundlesdktools;C:Program Files (x86)QuickTimeQTSystem;C:antbin;C:Javabin;C:Program FilesTortoiseSVNbin;C:UserssamuelDesktopworkbmd2builddebuglib
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.

链接 DLL 时,不要指定它的位数。您只需指定 DLL 的名称。由加载程序查找具有指定名称的 DLL。

您命名的两个 DLL(ntdll 和 msvcrt)是系统组件。它们驻留在 system32 目录中。您的 32 位进程受文件系统重定向程序的约束。这意味着当加载程序在 system32 中查找时,重定向器会静默地将其映射到 syswow64,即 32 位系统目录。这是透明发生的,因此加载程序将找到 32 位版本的 ntdll 和 msvcrt。

您报告的错误代码是 0xC000007B 。这是一个NTSTATUS错误代码。具体来说STATUS_INVALID_IMAGE_FORMAT.这确实是尝试在 64 位进程中加载 32 位 DLL 时报告的错误。因此,这似乎很可能就是正在发生的事情。

你已经使用依赖项查看器进行了一些调试。这是一个很好的工具,但在您使用它的模式下(静态模式),它有时会报告误报。听起来您使用的是 64 位版本的 Dependency Walker。使用 32 位版本,您可能会获得更好的诊断。

综上所述,您真正需要做的是在依赖步行者的配置文件模式下运行程序。可以在"配置文件"菜单下找到。执行此操作时,将从加载程序获取诊断流,包括加载失败并显示错误STATUS_INVALID_IMAGE_FORMAT的 DLL 的名称。在这一点上,应该清楚出了什么问题。

你用错了依赖沃克。

64 位版本的 Dependency Walker 不够智能,无法搜索 32 位 DLL 路径(David 的回答解释了在程序运行时如何通过重定向实际使用这些路径)。

您需要使用 32 位

依赖项查看器来分析 32 位代码。