Commit 479f259ea4

Andrew Kelley <andrew@ziglang.org>
2020-11-25 03:51:24
make start code more versatile
* always align the stack to 16. I saw an instance on x86_64 linux where it was needed. * detect at runtime if being interpreted by a dynamic loader and if so avoid clobbering the fs register.
1 parent a1fb10b
Changed files (2)
lib/std/dynamic_library.zig
@@ -59,8 +59,14 @@ const RDebug = extern struct {
     r_ldbase: usize,
 };
 
+/// TODO make it possible to reference this same external symbol 2x so we don't need this
+/// helper function.
+pub fn get_DYNAMIC() ?[*]elf.Dyn {
+    return @extern([*]elf.Dyn, .{ .name = "_DYNAMIC", .linkage = .Weak });
+}
+
 pub fn linkmap_iterator(phdrs: []elf.Phdr) !LinkMap.Iterator {
-    const _DYNAMIC = @extern([*]elf.Dyn, .{ .name = "_DYNAMIC", .linkage = .Weak }) orelse {
+    const _DYNAMIC = get_DYNAMIC() orelse {
         // No PT_DYNAMIC means this is either a statically-linked program or a
         // badly corrupted dynamically-linked one.
         return LinkMap.Iterator{ .current = null };
lib/std/start.zig
@@ -187,9 +187,8 @@ fn wWinMainCRTStartup() callconv(std.os.windows.WINAPI) noreturn {
 
 // TODO https://github.com/ziglang/zig/issues/265
 fn posixCallMainAndExit() noreturn {
-    if (builtin.os.tag == .freebsd) {
-        @setAlignStack(16);
-    }
+    @setAlignStack(16);
+
     const argc = argc_argv_ptr[0];
     const argv = @ptrCast([*][*:0]u8, argc_argv_ptr + 1);
 
@@ -208,8 +207,13 @@ fn posixCallMainAndExit() noreturn {
             @import("os/linux/start_pie.zig").apply_relocations();
         }
 
-        // Initialize the TLS area
-        std.os.linux.tls.initStaticTLS();
+        // Initialize the TLS area. We do a runtime check here to make sure
+        // this code is truly being statically executed and not inside a dynamic
+        // loader, otherwise this would clobber the thread ID register.
+        const is_dynamic = @import("dynamic_library.zig").get_DYNAMIC() != null;
+        if (!is_dynamic) {
+            std.os.linux.tls.initStaticTLS();
+        }
 
         // TODO This is disabled because what should we do when linking libc and this code
         // does not execute? And also it's causing a test failure in stack traces in release modes.