Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

The comment from @WarrenP is correct. According to the MSDN documentation:

The /TSAWARE option sets a flag in the IMAGE_OPTIONAL_HEADER DllCharacteristics field in the program image's optional header. When this flag is set, Terminal Server will not make certain changes to the application.

When an application is not Terminal Server aware (also known as a legacy application), Terminal Server makes certain modifications to the legacy application to make it work properly in a multiuser environment. For example, Terminal Server will create a virtual Windows folder, such that each user gets a Windows folder instead of getting the system's Windows directory. This gives users access to their own INI files. In addition, Terminal Server makes some adjustments to the registry for a legacy application. These modifications slow the loading of the legacy application on Terminal Server.

If an application is Terminal Server aware, it must neither rely on INI files nor write to the HKEY_CURRENT_USER registry during setup.

If you use /TSAWARE and your application still uses INI files, the files will be shared by all users of the system. If that is acceptable, you can still link your application with /TSAWARE; otherwise you need to use /TSAWARE:NO.

One thing only hinted at here is that shadow keys are enabled only for processes that are not TS aware.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top