After adding the /TSAWARE linker flag to one of my projects (Visual Studio 6), I was surprised to find a new section in the PE file (.idata). If I don't set the flag, the imports are merged into .rdata.
To illustrate the "problem" we start out with a simple console program:
#include <stdio.h>
int main()
{
printf("hello world\n");
return 0;
}
and compile with: cl /Og /O1 /GF /WX /c main.c
Then link with
link /MACHINE:IX86 /SUBSYSTEM:CONSOLE /RELEASE /OUT:a.exe main.obj
link /MACHINE:IX86 /SUBSYSTEM:CONSOLE /RELEASE /OUT:b.exe /TSAWARE main.obj
Let's compare the dumpbin output:
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
So for some reason, the linker decides that the imports cannot be merged.
But if we run editbin /TSAWARE a.exe
only the DLL characteristics field in the PE optional header is changed.
Can anyone explain this to me? Is this a bug in the linker or can the executable changed by editbin end up not working on certain systems?
The comment from @WarrenP is correct. According to the MSDN documentation:
One thing only hinted at here is that shadow keys are enabled only for processes that are not TS aware.
Only a guess: on a terminal server system, you want an image to have a few pages written to as possible. If a memory page that corresponds to the image is not modified, a single page of physical RAM can be mapped into eash session that is using that image. If a page from an image is modified, the system has to perform a copy-on-write operation for each instance of the page among all the sessions and use a different block of physical memory to represent the page in each session.
Since the imports for an image often need to be fixed up if the DLL that is being imported had to be relocated, the pages that hold the imports often get modified and therefore can't participate in sharing between the sessions. If the linker merges the imports with other data that is usually not modified, it might increase the number of copy-on-write pages unnecessarily.
This may be a sort of optimization that helps reduce the number of copied pages across sessions.
Like I said though - this is purely a guess.