| author | |
| committer | |
| log | 8184912a9895523d23d03aa9bdcf607a56122a20 |
| tree | f6f1d8382aa05ccb48826a30ba5ed518b7d8b16d |
| parent | c0681d6b6e74bd70228bb79c6bf719da5a5fe444 |
| parent | cb1fffb29eae6eafd46c87d3950911f496288ab2 |
| signature |
`std`: Some Windows TLS cleanup and fixes3 files changed, 53 insertions(+), 51 deletions(-)
lib/std/os/windows/tls.zig created+50| ... | @@ -0,0 +1,50 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | const windows = std.os.windows; | ||
| 4 | |||
| 5 | export var _tls_index: u32 = std.os.windows.TLS_OUT_OF_INDEXES; | ||
| 6 | export var _tls_start: ?*anyopaque linksection(".tls") = null; | ||
| 7 | export var _tls_end: ?*anyopaque linksection(".tls$ZZZ") = null; | ||
| 8 | export var __xl_a: windows.PIMAGE_TLS_CALLBACK linksection(".CRT$XLA") = null; | ||
| 9 | export var __xl_z: windows.PIMAGE_TLS_CALLBACK linksection(".CRT$XLZ") = null; | ||
| 10 | |||
| 11 | comptime { | ||
| 12 | if (builtin.cpu.arch == .x86 and builtin.abi == .msvc and builtin.zig_backend != .stage2_c) { | ||
| 13 | // The __tls_array is the offset of the ThreadLocalStoragePointer field | ||
| 14 | // in the TEB block whose base address held in the %fs segment. | ||
| 15 | asm ( | ||
| 16 | \\ .global __tls_array | ||
| 17 | \\ __tls_array = 0x2C | ||
| 18 | ); | ||
| 19 | } | ||
| 20 | } | ||
| 21 | |||
| 22 | // TODO this is how I would like it to be expressed | ||
| 23 | //export const _tls_used linksection(".rdata$T") = std.os.windows.IMAGE_TLS_DIRECTORY { | ||
| 24 | // .StartAddressOfRawData = @intFromPtr(&_tls_start), | ||
| 25 | // .EndAddressOfRawData = @intFromPtr(&_tls_end), | ||
| 26 | // .AddressOfIndex = @intFromPtr(&_tls_index), | ||
| 27 | // .AddressOfCallBacks = @intFromPtr(__xl_a), | ||
| 28 | // .SizeOfZeroFill = 0, | ||
| 29 | // .Characteristics = 0, | ||
| 30 | //}; | ||
| 31 | // This is the workaround because we can't do @intFromPtr at comptime like that. | ||
| 32 | pub const IMAGE_TLS_DIRECTORY = extern struct { | ||
| 33 | StartAddressOfRawData: *?*anyopaque, | ||
| 34 | EndAddressOfRawData: *?*anyopaque, | ||
| 35 | AddressOfIndex: *u32, | ||
| 36 | AddressOfCallBacks: [*:null]windows.PIMAGE_TLS_CALLBACK, | ||
| 37 | SizeOfZeroFill: u32, | ||
| 38 | Characteristics: u32, | ||
| 39 | }; | ||
| 40 | export const _tls_used linksection(".rdata$T") = IMAGE_TLS_DIRECTORY{ | ||
| 41 | .StartAddressOfRawData = &_tls_start, | ||
| 42 | .EndAddressOfRawData = &_tls_end, | ||
| 43 | .AddressOfIndex = &_tls_index, | ||
| 44 | // __xl_a is just a global variable containing a null pointer; the actual callbacks sit in | ||
| 45 | // between __xl_a and __xl_z. So we need to skip over __xl_a here. If there are no callbacks, | ||
| 46 | // this just means we point to __xl_z (the null terminator). | ||
| 47 | .AddressOfCallBacks = @as([*:null]windows.PIMAGE_TLS_CALLBACK, @ptrCast(&__xl_a)) + 1, | ||
| 48 | .SizeOfZeroFill = 0, | ||
| 49 | .Characteristics = 0, | ||
| 50 | }; | ||
lib/std/start.zig+3-3| ... | @@ -176,7 +176,7 @@ fn _DllMainCRTStartup( | ... | @@ -176,7 +176,7 @@ fn _DllMainCRTStartup( |
| 176 | lpReserved: std.os.windows.LPVOID, | 176 | lpReserved: std.os.windows.LPVOID, |
| 177 | ) callconv(std.os.windows.WINAPI) std.os.windows.BOOL { | 177 | ) callconv(std.os.windows.WINAPI) std.os.windows.BOOL { |
| 178 | if (!builtin.single_threaded and !builtin.link_libc) { | 178 | if (!builtin.single_threaded and !builtin.link_libc) { |
| 179 | _ = @import("start_windows_tls.zig"); | 179 | _ = @import("os/windows/tls.zig"); |
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | if (@hasDecl(root, "DllMain")) { | 182 | if (@hasDecl(root, "DllMain")) { |
| ... | @@ -434,7 +434,7 @@ fn _start() callconv(.Naked) noreturn { | ... | @@ -434,7 +434,7 @@ fn _start() callconv(.Naked) noreturn { |
| 434 | fn WinStartup() callconv(std.os.windows.WINAPI) noreturn { | 434 | fn WinStartup() callconv(std.os.windows.WINAPI) noreturn { |
| 435 | @setAlignStack(16); | 435 | @setAlignStack(16); |
| 436 | if (!builtin.single_threaded and !builtin.link_libc) { | 436 | if (!builtin.single_threaded and !builtin.link_libc) { |
| 437 | _ = @import("start_windows_tls.zig"); | 437 | _ = @import("os/windows/tls.zig"); |
| 438 | } | 438 | } |
| 439 | 439 | ||
| 440 | std.debug.maybeEnableSegfaultHandler(); | 440 | std.debug.maybeEnableSegfaultHandler(); |
| ... | @@ -445,7 +445,7 @@ fn WinStartup() callconv(std.os.windows.WINAPI) noreturn { | ... | @@ -445,7 +445,7 @@ fn WinStartup() callconv(std.os.windows.WINAPI) noreturn { |
| 445 | fn wWinMainCRTStartup() callconv(std.os.windows.WINAPI) noreturn { | 445 | fn wWinMainCRTStartup() callconv(std.os.windows.WINAPI) noreturn { |
| 446 | @setAlignStack(16); | 446 | @setAlignStack(16); |
| 447 | if (!builtin.single_threaded and !builtin.link_libc) { | 447 | if (!builtin.single_threaded and !builtin.link_libc) { |
| 448 | _ = @import("start_windows_tls.zig"); | 448 | _ = @import("os/windows/tls.zig"); |
| 449 | } | 449 | } |
| 450 | 450 | ||
| 451 | std.debug.maybeEnableSegfaultHandler(); | 451 | std.debug.maybeEnableSegfaultHandler(); |
lib/std/start_windows_tls.zig deleted-48| ... | @@ -1,48 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | |||
| 4 | export var _tls_index: u32 = std.os.windows.TLS_OUT_OF_INDEXES; | ||
| 5 | export var _tls_start: u8 linksection(".tls") = 0; | ||
| 6 | export var _tls_end: u8 linksection(".tls$ZZZ") = 0; | ||
| 7 | export var __xl_a: std.os.windows.PIMAGE_TLS_CALLBACK linksection(".CRT$XLA") = null; | ||
| 8 | export var __xl_z: std.os.windows.PIMAGE_TLS_CALLBACK linksection(".CRT$XLZ") = null; | ||
| 9 | |||
| 10 | comptime { | ||
| 11 | if (builtin.target.cpu.arch == .x86 and builtin.zig_backend != .stage2_c) { | ||
| 12 | // The __tls_array is the offset of the ThreadLocalStoragePointer field | ||
| 13 | // in the TEB block whose base address held in the %fs segment. | ||
| 14 | asm ( | ||
| 15 | \\ .global __tls_array | ||
| 16 | \\ __tls_array = 0x2C | ||
| 17 | ); | ||
| 18 | } | ||
| 19 | } | ||
| 20 | |||
| 21 | // TODO this is how I would like it to be expressed | ||
| 22 | // TODO also note, ReactOS has a +1 on StartAddressOfRawData and AddressOfCallBacks. Investigate | ||
| 23 | // why they do that. | ||
| 24 | //export const _tls_used linksection(".rdata$T") = std.os.windows.IMAGE_TLS_DIRECTORY { | ||
| 25 | // .StartAddressOfRawData = @intFromPtr(&_tls_start), | ||
| 26 | // .EndAddressOfRawData = @intFromPtr(&_tls_end), | ||
| 27 | // .AddressOfIndex = @intFromPtr(&_tls_index), | ||
| 28 | // .AddressOfCallBacks = @intFromPtr(__xl_a), | ||
| 29 | // .SizeOfZeroFill = 0, | ||
| 30 | // .Characteristics = 0, | ||
| 31 | //}; | ||
| 32 | // This is the workaround because we can't do @intFromPtr at comptime like that. | ||
| 33 | pub const IMAGE_TLS_DIRECTORY = extern struct { | ||
| 34 | StartAddressOfRawData: *anyopaque, | ||
| 35 | EndAddressOfRawData: *anyopaque, | ||
| 36 | AddressOfIndex: *anyopaque, | ||
| 37 | AddressOfCallBacks: *anyopaque, | ||
| 38 | SizeOfZeroFill: u32, | ||
| 39 | Characteristics: u32, | ||
| 40 | }; | ||
| 41 | export const _tls_used linksection(".rdata$T") = IMAGE_TLS_DIRECTORY{ | ||
| 42 | .StartAddressOfRawData = &_tls_start, | ||
| 43 | .EndAddressOfRawData = &_tls_end, | ||
| 44 | .AddressOfIndex = &_tls_index, | ||
| 45 | .AddressOfCallBacks = @as(*anyopaque, @ptrCast(&__xl_a)), | ||
| 46 | .SizeOfZeroFill = 0, | ||
| 47 | .Characteristics = 0, | ||
| 48 | }; | ||