From e4d595a8ba2e4466dc29bec7bc90a04420b34d4d Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 4 Apr 2019 01:08:26 -0400 Subject: [PATCH] fix thread local variables for non- position independent code This fixes comes thanks to Rich Felker from the musl libc project, who gave me this crucial information: "to satisfy the abi, your init code has to write the same value to that memory location as the value passed to the [arch_prctl] syscall" This commit also changes the rules for when to build statically by default. When building objects and static libraries, position independent code is disabled if no libraries will be dynamically linked and the target does not require position independent code. closes #2063 --- src/codegen.cpp | 17 +++++++---------- src/main.cpp | 5 ----- std/os.zig | 5 ++--- std/os/test.zig | 4 ---- std/special/bootstrap.zig | 10 ++++++---- test/stage1/behavior/misc.zig | 5 ----- 6 files changed, 15 insertions(+), 31 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 55733464521d0c144b80708124d467591dab48e5..cf8af9664fd6860636af6e80775c5a491e8285f8 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -7314,17 +7314,14 @@ static bool detect_dynamic_link(CodeGen *g) { return false; if (target_requires_pic(g->zig_target, g->libc_link_lib != nullptr)) return true; - if (g->out_type == OutTypeExe) { - // If there are no dynamic libraries then we can disable PIC - for (size_t i = 0; i < g->link_libs_list.length; i += 1) { - LinkLib *link_lib = g->link_libs_list.at(i); - if (target_is_libc_lib_name(g->zig_target, buf_ptr(link_lib->name))) - continue; - return true; - } - return false; + // If there are no dynamic libraries then we can disable PIC + for (size_t i = 0; i < g->link_libs_list.length; i += 1) { + LinkLib *link_lib = g->link_libs_list.at(i); + if (target_is_libc_lib_name(g->zig_target, buf_ptr(link_lib->name))) + continue; + return true; } - return true; + return false; } static bool detect_pic(CodeGen *g) { diff --git a/src/main.cpp b/src/main.cpp index 76261d4d686ea1a5961e175101d4a341c9306732..bd3d5749560092a56351478f7870b7886a7d8689 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -938,11 +938,6 @@ int main(int argc, char **argv) { return print_error_usage(arg0); } - if (out_type != OutTypeLib && is_dynamic) { - fprintf(stderr, "`-dynamic` may only be specified with `build-lib`.\n"); - return print_error_usage(arg0); - } - if (llvm_argv.length > 1) { llvm_argv.append(nullptr); ZigLLVMParseCommandLineOptions(llvm_argv.length - 1, llvm_argv.items); diff --git a/std/os.zig b/std/os.zig index c5025bbeb4dcfa3061ef0a89815614dc297c7d28..1416f3d49e80b7474088d5f62840ff0d477cf259 100644 --- a/std/os.zig +++ b/std/os.zig @@ -2934,7 +2934,6 @@ pub const Thread = struct { handle: Thread.Handle, mmap_addr: usize, mmap_len: usize, - tls_end_addr: usize, }, builtin.Os.windows => struct { handle: Thread.Handle, @@ -3185,8 +3184,8 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread var newtls: usize = undefined; if (linux_tls_phdr) |tls_phdr| { @memcpy(@intToPtr([*]u8, mmap_addr + tls_start_offset), linux_tls_img_src, tls_phdr.p_filesz); - thread_ptr.data.tls_end_addr = mmap_addr + mmap_len; - newtls = @ptrToInt(&thread_ptr.data.tls_end_addr); + newtls = mmap_addr + mmap_len; + @intToPtr(*usize, newtls).* = newtls; flags |= posix.CLONE_SETTLS; } const rc = posix.clone(MainFuncs.linuxThreadMain, mmap_addr + stack_end_offset, flags, arg, &thread_ptr.data.handle, newtls, &thread_ptr.data.handle); diff --git a/std/os/test.zig b/std/os/test.zig index 943960a925d79bcf5974266fa160cd5f14a608c5..ab21ea1568b0f2d90f1d9e4a93d3eb7ce04876c7 100644 --- a/std/os/test.zig +++ b/std/os/test.zig @@ -108,10 +108,6 @@ test "AtomicFile" { test "thread local storage" { if (builtin.single_threaded) return error.SkipZigTest; - if (!builtin.position_independent_code and !builtin.link_libc) { - // TODO https://github.com/ziglang/zig/issues/2063 - return error.SkipZigTest; - } const thread1 = try std.os.spawnThread({}, testTls); const thread2 = try std.os.spawnThread({}, testTls); testTls({}); diff --git a/std/special/bootstrap.zig b/std/special/bootstrap.zig index 064d8bac689b883c98b57108310d9d92aa0ee92d..32f913a5b040c608a10352d830bc410c5b117e8b 100644 --- a/std/special/bootstrap.zig +++ b/std/special/bootstrap.zig @@ -134,7 +134,6 @@ inline fn callMain() u8 { } } -var tls_end_addr: usize = undefined; const main_thread_tls_align = 32; var main_thread_tls_bytes: [64]u8 align(main_thread_tls_align) = [1]u8{0} ** 64; @@ -156,11 +155,14 @@ fn linuxInitializeThreadLocalStorage(at_phdr: usize, at_phnum: usize, at_phent: } const tls_phdr = std.os.linux_tls_phdr orelse return; std.os.linux_tls_img_src = @intToPtr([*]const u8, base + tls_phdr.p_vaddr); - assert(main_thread_tls_bytes.len >= tls_phdr.p_memsz); // not enough preallocated Thread Local Storage + const end_addr = @ptrToInt(&main_thread_tls_bytes) + tls_phdr.p_memsz; + const max_end_addr = @ptrToInt(&main_thread_tls_bytes) + main_thread_tls_bytes.len; + assert(max_end_addr >= end_addr + @sizeOf(usize)); // not enough preallocated Thread Local Storage assert(main_thread_tls_align >= tls_phdr.p_align); // preallocated Thread Local Storage not aligned enough @memcpy(&main_thread_tls_bytes, std.os.linux_tls_img_src, tls_phdr.p_filesz); - tls_end_addr = @ptrToInt(&main_thread_tls_bytes) + tls_phdr.p_memsz; - linuxSetThreadArea(@ptrToInt(&tls_end_addr)); + const end_ptr = @intToPtr(*usize, end_addr); + end_ptr.* = end_addr; + linuxSetThreadArea(end_addr); } fn linuxSetThreadArea(addr: usize) void { diff --git a/test/stage1/behavior/misc.zig b/test/stage1/behavior/misc.zig index fd407821e678bd9f523a0daa8fc9b4347d23f8d8..4cc401a008e55c9b3505b170a4ade7354268d1ec 100644 --- a/test/stage1/behavior/misc.zig +++ b/test/stage1/behavior/misc.zig @@ -688,11 +688,6 @@ fn getNull() ?*i32 { } test "thread local variable" { - if (!builtin.position_independent_code and !builtin.link_libc) { - // TODO https://github.com/ziglang/zig/issues/2063 - return error.SkipZigTest; - } - const S = struct { threadlocal var t: i32 = 1234; }; -- 2.54.0