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) {
73147314 return false;
73157315 if (target_requires_pic(g->zig_target, g->libc_link_lib != nullptr))
73167316 return true;
7317 if (g->out_type == OutTypeExe) {
7318 // If there are no dynamic libraries then we can disable PIC
7319 for (size_t i = 0; i < g->link_libs_list.length; i += 1) {
7320 LinkLib *link_lib = g->link_libs_list.at(i);
7321 if (target_is_libc_lib_name(g->zig_target, buf_ptr(link_lib->name)))
7322 continue;
7323 return true;
7324 }
7325 return false;
7317 // If there are no dynamic libraries then we can disable PIC
7318 for (size_t i = 0; i < g->link_libs_list.length; i += 1) {
7319 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 continue;
7322 return true;
73267323 }
7327 return true;
7324 return false;
73287325}
73297326
73307327static bool detect_pic(CodeGen *g) {
src/main.cpp-5
......@@ -938,11 +938,6 @@ int main(int argc, char **argv) {
938938 return print_error_usage(arg0);
939939 }
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
946941 if (llvm_argv.length > 1) {
947942 llvm_argv.append(nullptr);
948943 ZigLLVMParseCommandLineOptions(llvm_argv.length - 1, llvm_argv.items);
std/os.zig+2-3
......@@ -2934,7 +2934,6 @@ pub const Thread = struct {
29342934 handle: Thread.Handle,
29352935 mmap_addr: usize,
29362936 mmap_len: usize,
2937 tls_end_addr: usize,
29382937 },
29392938 builtin.Os.windows => struct {
29402939 handle: Thread.Handle,
......@@ -3185,8 +3184,8 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread
31853184 var newtls: usize = undefined;
31863185 if (linux_tls_phdr) |tls_phdr| {
31873186 @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;
3189 newtls = @ptrToInt(&thread_ptr.data.tls_end_addr);
3187 newtls = mmap_addr + mmap_len;
3188 @intToPtr(*usize, newtls).* = newtls;
31903189 flags |= posix.CLONE_SETTLS;
31913190 }
31923191 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" {
108108
109109test "thread local storage" {
110110 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 }
115111 const thread1 = try std.os.spawnThread({}, testTls);
116112 const thread2 = try std.os.spawnThread({}, testTls);
117113 testTls({});
std/special/bootstrap.zig+6-4
......@@ -134,7 +134,6 @@ inline fn callMain() u8 {
134134 }
135135}
136136
137var tls_end_addr: usize = undefined;
138137const main_thread_tls_align = 32;
139138var 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:
156155 }
157156 const tls_phdr = std.os.linux_tls_phdr orelse return;
158157 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 Storage
158 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
160161 assert(main_thread_tls_align >= tls_phdr.p_align); // preallocated Thread Local Storage not aligned enough
161162 @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 linuxSetThreadArea(@ptrToInt(&tls_end_addr));
163 const end_ptr = @intToPtr(*usize, end_addr);
164 end_ptr.* = end_addr;
165 linuxSetThreadArea(end_addr);
164166}
165167
166168fn linuxSetThreadArea(addr: usize) void {
test/stage1/behavior/misc.zig-5
......@@ -688,11 +688,6 @@ fn getNull() ?*i32 {
688688}
689689
690690test "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
696691 const S = struct {
697692 threadlocal var t: i32 = 1234;
698693 };