将/ TSAWARE链接器标志添加到我的一个项目(Visual Studio 6)后,我很惊讶在PE文件(.idata)中找到了一个新部分 . 如果我没有设置标志,则导入将合并到.rdata中 .
为了说明“问题”,我们从一个简单的控制台程序开始:
#include <stdio.h>
int main()
{
printf("hello world\n");
return 0;
}
并编译: cl /Og /O1 /GF /WX /c main.c
然后链接
-
link /MACHINE:IX86 /SUBSYSTEM:CONSOLE /RELEASE /OUT:a.exe main.obj
-
link /MACHINE:IX86 /SUBSYSTEM:CONSOLE /RELEASE /OUT:b.exe /TSAWARE main.obj
让我们比较dumpbin输出:
Dump of file a.exe
File Type: EXECUTABLE IMAGE
Summary
4000 .data
1000 .rdata
5000 .text
Dump of file b.exe
File Type: EXECUTABLE IMAGE
Summary
4000 .data
1000 .idata
1000 .rdata
5000 .text
因此,由于某种原因,链接器决定无法合并导入 .
但是如果我们运行 editbin /TSAWARE a.exe
,则只更改PE可选头中的DLL特征字段 .
任何人都可以向我解释这个吗?这是链接器中的错误还是由editbin更改的可执行文件最终无法在某些系统上运行?
2 回答
只是猜测:在终端服务器系统上,您希望图像尽可能地写入几页 . 如果未修改与图像对应的内存页面,则可以将单页物理RAM映射到使用该图像的eash会话 . 如果修改了图像中的页面,则系统必须对所有会话中的每个页面实例执行写时复制操作,并使用不同的物理内存块来表示每个会话中的页面 .
如果必须重新定位导入的DLL,则通常需要修复映像的导入,因此保存导入的页面通常会被修改,因此无法参与会话之间的共享 . 如果链接器将导入与通常未修改的其他数据合并,则可能会不必要地增加写入时复制页面的数量 .
这可能是一种优化,有助于减少跨会话复制页面的数量 .
就像我说的那样 - 这纯粹是猜测 .
来自@WarrenP的评论是正确的 . 根据MSDN documentation:
这里只暗示的一件事是,仅对不支持TS的进程启用了影子密钥 .