没有 .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>
我正在使用 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 板上
如果绝对需要 .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>