/ TSAWARE链接器标志对PE可执行文件做了什么?

时间:2009-08-11 15:54:30

标签: windows visual-c++ linker vc6 portable-executable

将/ 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 个答案:

答案 0 :(得分:4)

只有猜测:在终端服务器系统上,您希望图像尽可能写入几页。如果未修改与图像对应的内存页面,则可以将单页物理RAM映射到使用该图像的eash会话。如果修改了图像中的页面,则系统必须对所有会话中的每个页面实例执行写时复制操作,并使用不同的物理内存块来表示每个会话中的页面。

由于如果必须重新定位导入的DLL,则通常需要修复映像的导入,因此保存导入的页面通常会被修改,因此无法参与会话之间的共享。如果链接器将导入与通常未修改的其他数据合并,则可能会不必要地增加写入时复制页面的数量。

这可能是一种优化,有助于减少跨会话复制页面的数量。

就像我说的那样 - 这纯粹是猜测。

答案 1 :(得分:1)

@WarrenP的评论是正确的。根据{{​​3}}:

  

/ TSAWARE选项在IMAGE_OPTIONAL_HEADER中设置一个标志   程序图像的可选标题中的DllCharacteristics字段。什么时候   设置此标志后,终端服务器不会对其进行某些更改   应用

     

当应用程序不能识别终端服务器时(也称为   遗留应用程序),终端服务器进行了一些修改   遗留应用程序,使其在多用户中正常工作   环境。例如,终端服务器将创建一个虚拟   Windows文件夹,这样每个用户都可以获得Windows文件夹而不是   获取系统的Windows目录。这使用户可以访问   他们自己的INI文件。另外,终端服务器做了一些   调整遗留应用程序的注册表。这些   修改减慢了终端上遗留应用程序的加载速度   服务器

     

如果应用程序可识别终端服务器,则它必须既不依赖   INI文件也不会在安装过程中写入HKEY_CURRENT_USER注册表。

     

如果你使用/ TSAWARE并且你的应用程序仍然使用INI文件,那么   文件将由系统的所有用户共享。如果那样的话   可以接受,您仍然可以将您的应用程序与/ TSAWARE链接;   否则你需要使用/ TSAWARE:NO。

此处仅暗示的一点是,仅对不支持TS的进程启用了影子密钥。