2 * Written in the D programming language.
3 * This module provides Win32-specific support for sections.
5 * Copyright: Copyright Digital Mars 2008 - 2012.
6 * License: Distributed under the
7 * $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
8 * (See accompanying file LICENSE)
9 * Authors: Walter Bright, Sean Kelly, Martin Nowak
10 * Source: $(DRUNTIMESRC src/rt/_sections_win64.d)
13 module rt
.sections_win64
;
15 version (CRuntime_Microsoft
):
18 debug(PRINTF
) import core
.stdc
.stdio
;
19 import core
.stdc
.stdlib
: malloc
, free
;
20 import rt
.deh
, rt
.minfo
;
24 static int opApply(scope int delegate(ref SectionGroup
) dg
)
29 static int opApplyReverse(scope int delegate(ref SectionGroup
) dg
)
34 @property immutable(ModuleInfo
*)[] modules() const nothrow @nogc
36 return _moduleGroup
.modules
;
39 @property ref inout(ModuleGroup
) moduleGroup() inout nothrow @nogc
45 @property immutable(FuncTable
)[] ehTables() const
47 auto pbeg
= cast(immutable(FuncTable
)*)&_deh_beg
;
48 auto pend
= cast(immutable(FuncTable
)*)&_deh_end
;
49 return pbeg
[0 .. pend
- pbeg
];
52 @property inout(void[])[] gcRanges() inout nothrow @nogc
58 ModuleGroup _moduleGroup
;
62 shared(bool) conservative
;
64 void initSections() nothrow @nogc
66 _sections
._moduleGroup
= ModuleGroup(getModuleInfos());
68 // the ".data" image section includes both object file sections ".data" and ".bss"
69 void[] dataSection
= findImageSection(".data");
70 debug(PRINTF
) printf("found .data section: [%p,+%llx]\n", dataSection
.ptr
,
71 cast(ulong)dataSection
.length
);
74 conservative
= !scanDataSegPrecisely();
78 _sections
._gcRanges
= (cast(void[]*) malloc((void[]).sizeof
))[0..1];
79 _sections
._gcRanges
[0] = dataSection
;
83 size_t count
= &_DP_end
- &_DP_beg
;
84 auto ranges
= cast(void[]*) malloc(count
* (void[]).sizeof
);
87 for (size_t i
= 0; i
< count
; i
++)
89 auto off
= (&_DP_beg
)[i
];
90 if (off
== 0) // skip zero entries added by incremental linking
91 continue; // assumes there is no D-pointer at the very beginning of .data
92 void* addr
= dataSection
.ptr
+ off
;
93 debug(PRINTF
) printf(" scan %p\n", addr
);
94 // combine consecutive pointers into single range
95 if (prev
+ (void*).sizeof
== addr
)
96 ranges
[r
-1] = ranges
[r
-1].ptr
[0 .. ranges
[r
-1].length
+ (void*).sizeof
];
98 ranges
[r
++] = (cast(void**)addr
)[0..1];
101 _sections
._gcRanges
= ranges
[0..r
];
105 void finiSections() nothrow @nogc
107 .free(cast(void*)_sections
.modules
.ptr
);
108 .free(_sections
._gcRanges
.ptr
);
111 void[] initTLSRanges() nothrow @nogc
115 // with VS2017 15.3.1, the linker no longer puts TLS segments into a
116 // separate image section. That way _tls_start and _tls_end no
117 // longer generate offsets into .tls, but DATA.
118 // Use the TEB entry to find the start of TLS instead and read the
119 // length from the TLS directory
120 version (D_InlineAsm_X86
)
125 mov ECX
, FS
:[0x2C]; // _tls_array
126 mov EAX
, [ECX
+4*EAX
];
128 add EAX
, [_tls_used
+4]; // end
129 sub EAX
, [_tls_used
+0]; // start
133 else version (D_InlineAsm_X86_64
)
140 mov RCX
, GS
:[RCX
]; // _tls_array (immediate value causes fixup)
141 mov RAX
, [RCX
+8*RAX
];
143 add RAX
, [_tls_used
+8]; // end
144 sub RAX
, [_tls_used
+0]; // start
149 static assert(false, "Architecture not supported.");
151 return pbeg
[0 .. pend
- pbeg
];
154 void finiTLSRanges(void[] rng
) nothrow @nogc
158 void scanTLSRanges(void[] rng
, scope void delegate(void* pbeg
, void* pend
) nothrow dg
) nothrow
162 dg(rng
.ptr
, rng
.ptr
+ rng
.length
);
166 for (auto p
= &_TP_beg
; p
< &_TP_end
; )
169 uint end
= beg
+ cast(uint)((void*).sizeof
);
170 while (p
< &_TP_end
&& *p
== end
)
172 end
+= (void*).sizeof
;
175 dg(rng
.ptr
+ beg
, rng
.ptr
+ end
);
181 __gshared SectionGroup _sections
;
185 extern __gshared
void* _minfo_beg
;
186 extern __gshared
void* _minfo_end
;
189 immutable(ModuleInfo
*)[] getModuleInfos() nothrow @nogc
197 auto m
= (cast(immutable(ModuleInfo
*)*)&_minfo_beg
)[1 .. &_minfo_end
- &_minfo_beg
];
198 /* Because of alignment inserted by the linker, various null pointers
199 * are there. We need to filter them out.
202 auto pend
= m
.ptr
+ m
.length
;
204 // count non-null pointers
206 for (; p
< pend
; ++p
)
208 if (*p
!is null) ++cnt
;
211 auto result
= (cast(immutable(ModuleInfo
)**).malloc(cnt
* size_t
.sizeof
))[0 .. cnt
];
215 for (; p
< pend
; ++p
)
216 if (*p
!is null) result
[cnt
++] = *p
;
218 return cast(immutable)result
;
223 /* Symbols created by the compiler/linker and inserted into the
224 * object file that 'bracket' sections.
238 void*[2] _tls_used
; // start, end
243 /////////////////////////////////////////////////////////////////////
245 enum IMAGE_DOS_SIGNATURE
= 0x5A4D; // MZ
247 struct IMAGE_DOS_HEADER
// DOS .EXE header
249 ushort e_magic
; // Magic number
250 ushort[29] e_res2
; // Reserved ushorts
251 int e_lfanew
; // File address of new exe header
254 struct IMAGE_FILE_HEADER
257 ushort NumberOfSections
;
259 uint PointerToSymbolTable
;
260 uint NumberOfSymbols
;
261 ushort SizeOfOptionalHeader
;
262 ushort Characteristics
;
265 struct IMAGE_NT_HEADERS
268 IMAGE_FILE_HEADER FileHeader
;
269 // optional header follows
272 struct IMAGE_SECTION_HEADER
276 uint PhysicalAddress
;
281 uint PointerToRawData
;
282 uint PointerToRelocations
;
283 uint PointerToLinenumbers
;
284 ushort NumberOfRelocations
;
285 ushort NumberOfLinenumbers
;
286 uint Characteristics
;
289 bool compareSectionName(ref IMAGE_SECTION_HEADER section
, string name
) nothrow @nogc
291 if (name
[] != section
.Name
[0 .. name
.length
])
293 return name
.length
== 8 || section
.Name
[name
.length
] == 0;
296 void[] findImageSection(string name
) nothrow @nogc
298 if (name
.length
> 8) // section name from string table not supported
300 IMAGE_DOS_HEADER
* doshdr
= cast(IMAGE_DOS_HEADER
*) &__ImageBase
;
301 if (doshdr
.e_magic
!= IMAGE_DOS_SIGNATURE
)
304 auto nthdr
= cast(IMAGE_NT_HEADERS
*)(cast(void*)doshdr
+ doshdr
.e_lfanew
);
305 auto sections
= cast(IMAGE_SECTION_HEADER
*)(cast(void*)nthdr
+ IMAGE_NT_HEADERS
.sizeof
+ nthdr
.FileHeader
.SizeOfOptionalHeader
);
306 for (ushort i
= 0; i
< nthdr
.FileHeader
.NumberOfSections
; i
++)
307 if (compareSectionName (sections
[i
], name
))
308 return (cast(void*)&__ImageBase
+ sections
[i
].VirtualAddress
)[0 .. sections
[i
].VirtualSize
];