将/ 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改变,最终不能在某些系统上工作?
只有一个猜测:在终端服务器系统上,您希望图像尽可能写入几页。 如果与该图像相对应的内存页面未被修改,则可以将单页物理RAM映射到正在使用该图像的eash会话中。 如果修改了映像中的页面,则系统必须对所有会话中的每个页面实例执行写入时复制操作,并使用不同的物理内存块来表示每个会话中的页面。
由于导入的DLL必须重新定位,因此经常需要修复映像的导入,导入的页面经常会被修改,因此无法参与会话之间的共享。 如果链接器将导入与通常未修改的其他数据合并,则可能会不必要地增加写入时复制页面的数量。
这可能是一种优化,有助于减少跨会话复制的页面数量。
就像我说的那样 – 这纯粹是一种猜测。
@WarrenP的评论是正确的。 根据MSDN文档 :
/ TSAWARE选项在程序图像的可选标题的IMAGE_OPTIONAL_HEADER DllCharacteristics字段中设置标志。 设置此标志时,终端服务器不会对应用程序进行某些更改。
当应用程序不能识别终端服务器(也称为遗留应用程序)时,终端服务器会对遗留应用程序进行某些修改,以使其在多用户环境中正常工作。 例如,终端服务器将创建一个虚拟的Windows文件夹,这样每个用户都可以得到一个Windows文件夹,而不是获取系统的Windows目录。 这使用户可以访问他们自己的INI文件。 另外,终端服务器对遗留应用程序的注册表进行一些调整。 这些修改会减慢终端服务器上传统应用程序的加载速度。
如果应用程序是终端服务器感知的,它不能依赖于INI文件,也不能在安装过程中写入HKEY_CURRENT_USER注册表。
如果您使用/ TSAWARE,并且您的应用程序仍使用INI文件,则文件将由系统的所有用户共享。 如果这是可以接受的,您仍然可以将您的应用程序与/ TSAWARE链接; 否则你需要使用/ TSAWARE:NO。
有一件事只暗示在这里,影子键只对不知道TS的进程启用。