authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-04-04 01:08:26-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-04-04 01:08:26-04:00
loge4d595a8ba2e4466dc29bec7bc90a04420b34d4d
tree4d062b3b3a2cb026b9f12b49b618e9d3a68ffc2e
parent70ae3222b54c05fc88e9c94a1ae12ead07fa4341
signaturelock-open Commit is signed but in an unrecognized format.

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

6 files changed, 15 insertions(+), 31 deletions(-)

src/codegen.cpp+7-10
...@@ -7314,17 +7314,14 @@ static bool detect_dynamic_link(CodeGen *g) {...@@ -7314,17 +7314,14 @@ static bool detect_dynamic_link(CodeGen *g) {
7314 return false;7314 return false;
7315 if (target_requires_pic(g->zig_target, g->libc_link_lib != nullptr))7315 if (target_requires_pic(g->zig_target, g->libc_link_lib != nullptr))
7316 return true;7316 return true;
7317 if (g->out_type == OutTypeExe) {7317 // If there are no dynamic libraries then we can disable PIC
7318 // If there are no dynamic libraries then we can disable PIC7318 for (size_t i = 0; i < g->link_libs_list.length; i += 1) {
7319 for (size_t i = 0; i < g->link_libs_list.length; i += 1) {7319 LinkLib *link_lib = g->link_libs_list.at(i);
7320 LinkLib *link_lib = g->link_libs_list.at(i);7320 if (target_is_libc_lib_name(g->zig_target, buf_ptr(link_lib->name)))
7321 if (target_is_libc_lib_name(g->zig_target, buf_ptr(link_lib->name)))7321 continue;
7322 continue;7322 return true;
7323 return true;
7324 }
7325 return false;
7326 }7323 }
7327 return true;7324 return false;
7328}7325}
73297326
7330static bool detect_pic(CodeGen *g) {7327static bool detect_pic(CodeGen *g) {
src/main.cpp-5
...@@ -938,11 +938,6 @@ int main(int argc, char **argv) {...@@ -938,11 +938,6 @@ int main(int argc, char **argv) {
938 return print_error_usage(arg0);938 return print_error_usage(arg0);
939 }939 }
940940
941 if (out_type != OutTypeLib && is_dynamic) {
942 fprintf(stderr, "`-dynamic` may only be specified with `build-lib`.\n");
943 return print_error_usage(arg0);
944 }
945
946 if (llvm_argv.length > 1) {941 if (llvm_argv.length > 1) {
947 llvm_argv.append(nullptr);942 llvm_argv.append(nullptr);
948 ZigLLVMParseCommandLineOptions(llvm_argv.length - 1, llvm_argv.items);943 ZigLLVMParseCommandLineOptions(llvm_argv.length - 1, llvm_argv.items);
std/os.zig+2-3
...@@ -2934,7 +2934,6 @@ pub const Thread = struct {...@@ -2934,7 +2934,6 @@ pub const Thread = struct {
2934 handle: Thread.Handle,2934 handle: Thread.Handle,
2935 mmap_addr: usize,2935 mmap_addr: usize,
2936 mmap_len: usize,2936 mmap_len: usize,
2937 tls_end_addr: usize,
2938 },2937 },
2939 builtin.Os.windows => struct {2938 builtin.Os.windows => struct {
2940 handle: Thread.Handle,2939 handle: Thread.Handle,
...@@ -3185,8 +3184,8 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread...@@ -3185,8 +3184,8 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread
3185 var newtls: usize = undefined;3184 var newtls: usize = undefined;
3186 if (linux_tls_phdr) |tls_phdr| {3185 if (linux_tls_phdr) |tls_phdr| {
3187 @memcpy(@intToPtr([*]u8, mmap_addr + tls_start_offset), linux_tls_img_src, tls_phdr.p_filesz);3186 @memcpy(@intToPtr([*]u8, mmap_addr + tls_start_offset), linux_tls_img_src, tls_phdr.p_filesz);
3188 thread_ptr.data.tls_end_addr = mmap_addr + mmap_len;3187 newtls = mmap_addr + mmap_len;
3189 newtls = @ptrToInt(&thread_ptr.data.tls_end_addr);3188 @intToPtr(*usize, newtls).* = newtls;
3190 flags |= posix.CLONE_SETTLS;3189 flags |= posix.CLONE_SETTLS;
3191 }3190 }
3192 const rc = posix.clone(MainFuncs.linuxThreadMain, mmap_addr + stack_end_offset, flags, arg, &thread_ptr.data.handle, newtls, &thread_ptr.data.handle);3191 const rc = posix.clone(MainFuncs.linuxThreadMain, mmap_addr + stack_end_offset, flags, arg, &thread_ptr.data.handle, newtls, &thread_ptr.data.handle);
std/os/test.zig-4
...@@ -108,10 +108,6 @@ test "AtomicFile" {...@@ -108,10 +108,6 @@ test "AtomicFile" {
108108
109test "thread local storage" {109test "thread local storage" {
110 if (builtin.single_threaded) return error.SkipZigTest;110 if (builtin.single_threaded) return error.SkipZigTest;
111 if (!builtin.position_independent_code and !builtin.link_libc) {
112 // TODO https://github.com/ziglang/zig/issues/2063
113 return error.SkipZigTest;
114 }
115 const thread1 = try std.os.spawnThread({}, testTls);111 const thread1 = try std.os.spawnThread({}, testTls);
116 const thread2 = try std.os.spawnThread({}, testTls);112 const thread2 = try std.os.spawnThread({}, testTls);
117 testTls({});113 testTls({});
std/special/bootstrap.zig+6-4
...@@ -134,7 +134,6 @@ inline fn callMain() u8 {...@@ -134,7 +134,6 @@ inline fn callMain() u8 {
134 }134 }
135}135}
136136
137var tls_end_addr: usize = undefined;
138const main_thread_tls_align = 32;137const main_thread_tls_align = 32;
139var main_thread_tls_bytes: [64]u8 align(main_thread_tls_align) = [1]u8{0} ** 64;138var main_thread_tls_bytes: [64]u8 align(main_thread_tls_align) = [1]u8{0} ** 64;
140139
...@@ -156,11 +155,14 @@ fn linuxInitializeThreadLocalStorage(at_phdr: usize, at_phnum: usize, at_phent:...@@ -156,11 +155,14 @@ fn linuxInitializeThreadLocalStorage(at_phdr: usize, at_phnum: usize, at_phent:
156 }155 }
157 const tls_phdr = std.os.linux_tls_phdr orelse return;156 const tls_phdr = std.os.linux_tls_phdr orelse return;
158 std.os.linux_tls_img_src = @intToPtr([*]const u8, base + tls_phdr.p_vaddr);157 std.os.linux_tls_img_src = @intToPtr([*]const u8, base + tls_phdr.p_vaddr);
159 assert(main_thread_tls_bytes.len >= tls_phdr.p_memsz); // not enough preallocated Thread Local Storage158 const end_addr = @ptrToInt(&main_thread_tls_bytes) + tls_phdr.p_memsz;
159 const max_end_addr = @ptrToInt(&main_thread_tls_bytes) + main_thread_tls_bytes.len;
160 assert(max_end_addr >= end_addr + @sizeOf(usize)); // not enough preallocated Thread Local Storage
160 assert(main_thread_tls_align >= tls_phdr.p_align); // preallocated Thread Local Storage not aligned enough161 assert(main_thread_tls_align >= tls_phdr.p_align); // preallocated Thread Local Storage not aligned enough
161 @memcpy(&main_thread_tls_bytes, std.os.linux_tls_img_src, tls_phdr.p_filesz);162 @memcpy(&main_thread_tls_bytes, std.os.linux_tls_img_src, tls_phdr.p_filesz);
162 tls_end_addr = @ptrToInt(&main_thread_tls_bytes) + tls_phdr.p_memsz;163 const end_ptr = @intToPtr(*usize, end_addr);
163 linuxSetThreadArea(@ptrToInt(&tls_end_addr));164 end_ptr.* = end_addr;
165 linuxSetThreadArea(end_addr);
164}166}
165167
166fn linuxSetThreadArea(addr: usize) void {168fn linuxSetThreadArea(addr: usize) void {
test/stage1/behavior/misc.zig-5
...@@ -688,11 +688,6 @@ fn getNull() ?*i32 {...@@ -688,11 +688,6 @@ fn getNull() ?*i32 {
688}688}
689689
690test "thread local variable" {690test "thread local variable" {
691 if (!builtin.position_independent_code and !builtin.link_libc) {
692 // TODO https://github.com/ziglang/zig/issues/2063
693 return error.SkipZigTest;
694 }
695
696 const S = struct {691 const S = struct {
697 threadlocal var t: i32 = 1234;692 threadlocal var t: i32 = 1234;
698 };693 };