Linker bug? data_seg(".CRT$XIU") not merged into other .CRT segments

Using the x64 cross-compiler running on x86, linker and cl.exe file version "8.00.50727.42 (RTM.050727-4200)", the following code that works in x86 with the x86 cl.exe and link fails:

#pragma data_seg(".CRT$XIU")

static int (*initptr)() = APreCppInitFunction;

#pragma data_seg()

The problem occurs because cl.exe seems to create the data_seg as a DATA segment type (in x86 it gets generated as CODE), and link.exe does not merge the .CRT$XIU segment into the correct alphabetized sequence among the other CRT code segments (.CRT$XIA, etc.). Here is a sample from the x64 mapping file that results:

0001:00000b28 00000008H .CRT$XIA CODE

0001:00000b28 00000008H .CRT$XIAA CODE

0001:00000b28 00000008H .CRT$XIZ CODE

...

0004:00000000 00000008H .CRT$(XIU) DATA

In x86 the map is as expected:

0001:000005a0 00000004H .CRT$XIA CODE

0001:000005a4 00000004H .CRT$XIAA CODE

0001:000005ac 00000004H .CRT$XIC CODE

0001:000005a8 00000004H .CRT$XIU CODE

0001:0000059c 00000004H .CRT$XIZ CODE

Questions:

- Is this a known issue?

- Is there some cl.exe setting or #pragma setting that would let me ensure the data_seg gets compiled as a CODE segment? I tried changing this to a code_seg but the segment then does not appear in the map because it's really a read-only data segment. data_seg() has an optional third param that is ignored (according ot the docs), so that does not seem like a possibility.

- Is this fixed in VS2005 SP1? I cannot find a similar issue listed in the hotfixes for that release.

[1631 byte] By [erikmav] at [2007-12-29]
# 1
One clarification: The result of this problem is that initializers that are intended to run after C runtime init but before C++ init will not run at all - the CRT in crt0dat.c enumerates each .CRT$Xxx data segment situated between .CRT$XIA and .CRT$XIZ and executes the table of function pointers contained in the data segment, but since our .CRT$(XIU) does not get placed in the correct ordering in the map, it cannot be enumerated and executed.
erikmav at 2007-9-5 > top of Msdn Tech,Visual C++,Visual C++ General...
# 2

Resolved: It turns out that on x64 the .CRT$XIU segment was being allocated as a short segment by default, which did not match the long segment settings of the CRT-defined .CRT$XIA and other segments. This prevented the linker from merging my new segment into the existing ones. The solution then is to use a #pragma section directive to set the properties of the segment:

#pragma section(".CRT$XIU", long, read)

#pragma data_seg("$.CRT$XIU")

...

erikmav at 2007-9-5 > top of Msdn Tech,Visual C++,Visual C++ General...