没有 .RELOC 部分的可执行文件

Executable Without .RELOC Section

我正在使用 MSVC 2019。我已经编译了一个简单的 C++ 代码(Hello World...)。当我在x86架构下以release模式编译时,有一个.reloc段,但是当我在x64架构下编译它时,.reloc段不存在。

这是什么原因?我需要带有 .reloc 部分的可执行文件。

此致。

编辑 - 1:

C/C++ 设置:

/permissive- /GS- /GL /W3 /Gy /Zc:wchar_t /Zi /Gm- /O2 /sdl /Fd"x64\Release\vc142.pdb" /Zc:inline /fp:precise /D "NDEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /Gd /Oi /MT /FC /Fa"x64\Release\" /EHsc /nologo /Fo"x64\Release\" /Fp"x64\Release\test-reloc.pch" /diagnostics:column

链接器设置:

/OUT:"F:\Test\x64\Release\test-reloc.exe" /MANIFEST:NO /LTCG:incremental /NXCOMPAT /PDB:"F:\Test\x64\Release\test-reloc.pdb" /DYNAMICBASE "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /FIXED:NO /MACHINE:X64 /ENTRY:"relocMain" /OPT:REF /SAFESEH:NO /INCREMENTAL:NO /PGD:"F:\Test\x64\Release\test-reloc.pgd" /SUBSYSTEM:CONSOLE /MANIFESTUAC:NO /OPT:ICF /ERRORREPORT:PROMPT /NOLOGO /NODEFAULTLIB /TLBID:1

问题是关于 MSVC 在 x64 构建中生成的 PE 布局。省略不相关的细节,可以用普通 C 重述如下。

// main.c

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

int __stdcall rawMain()
{
    OutputDebugStringA("Hello World!\n");
    return 0;
}

上面的简约 C 程序没有使用或链接到 CRT,在 x64 编译中没有 .reloc 部分。

X:\etc>cl /nologo main.c /GS- /O2 /link /nodefaultlib kernel32.lib /manifest:no /subsystem:console /machine:x64 /entry:rawMain
main.c

X:\etc>dumpbin /nologo main.exe

Dump of file main.exe

File Type: EXECUTABLE IMAGE

  Summary

        1000 .pdata
        1000 .rdata
        1000 .text

X:\etc>

What is the reason of this?

原因是生成的代码没有重定位,因此没有创建 .reloc 部分,因为“Windows 将拒绝加载 DLL(或 EXE)如果有一个空的部分”——引自对 fasm 板上 on SO, with a reference to the dll in fasm (bug?!) 线程的回答。

如果绝对需要 .reloc 部分,最简单的方法是在代码中强制使用可重定位符号。例如,以下内容足以实现它。

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

static void (*foo)(LPCSTR) = OutputDebugStringA;

int __stdcall rawMain()
{
    foo("Hello World!\n");
    return 0;
}
X:\etc>cl /nologo main.c /GS- /O2 /link /nodefaultlib kernel32.lib /manifest:no /subsystem:console /machine:x64 /entry:rawMain
main.c

X:\etc>dumpbin /nologo /relocations main.exe

Dump of file main.exe

File Type: EXECUTABLE IMAGE

BASE RELOCATIONS #5
    3000 RVA,        C SizeOfBlock
       0  DIR64      0000000140001018
       0  ABS

  Summary

        1000 .data
        1000 .pdata
        1000 .rdata
        1000 .reloc
        1000 .text

X:\etc>