如何确定使用哪个 C 或 C++ 编译器来构建特定的 Windows 可执行文件或 DLL?有些编译器会在最终的可执行文件中留下版本字符串,但这在 Windows 上似乎比在 Linux 上更罕见。
具体来说,我感兴趣的是区分 Visual C++ 和各种 MinGW 编译器(通常从函数签名来看相当容易),然后区分 Visual C++ 版本(6、2002/2003、2005、2008;更难做到)。有没有一种工具可以以半可靠的方式进行区分?
区分 VC 版本的提示来源之一是链接的特定 C 运行时库。由于默认情况是(至少在现代版本中)链接到 DLL,因此这相当容易做到。实用程序 Dependency Walker 对于验证您是否知道真正加载了哪些 DLL 来说几乎是必不可少的,它会告诉您正在使用哪个 C 运行时 DLL。尽管 Dependency Walker 包含在 Microsoft Platform SDK 中,但它已独立扩展,我链接的站点是其当前开发的主页。
VC6和MinGW默认都链接到MSVCRT.DLL,所以这不会区分它们。经过一些努力,MinGW 也可以链接到更高的 C 运行时版本,因此您需要独立排除 MinGW。
Runtime VC Version
---------- -------------
MSVCRT.DLL VC6
MSCVR80.DLL VC8 (VS 2005)
MSCVR90.DLL VC9 (VS 2008)
其他运行时 DLL 也是很好的线索,例如对 Delphi 运行时的引用可能表明 EXE 实际上是从 Delphi 构建的,而不是 C 工具链。
如果符号尚未从 .EXE 文件中删除,那么您可能会发现一些存在内部符号的线索。例如,对类似
_sjlj_init
之类内容的引用可能表明在某个时刻涉及为 setjmp/longjmp 异常处理配置的 MinGW GCC 3.x。
另一个选项是使用 depends.exe
检查 dll 链接到的 CRT 库
MinGW 和 Cygwin 有自己的 dll,很容易识别。
VC6通常使用MSVCRT.dll
任何较新版本的 VS 在 dll 文件名旁边都有其版本:
MSVCR90.dll - VS2008
MSVCR80.dll - VS2005
MSVCR71.dll - VS2003
MSVCR70.dll - VS2002
不要将此列表作为权威指南,因为这些名称往往有奇怪的变化,特别是在 VS2002-2003 领域。还有其他 dll,例如 MFC 和 ATL dll,也具有类似的版本控制方案。
只要 PE 实际上依赖于 CRT 并且没有静态链接到它,这就会起作用。
我认为 Delphi 也有一些链接到的 DLL,但我不太确定它是什么。