authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-07-22 13:24:03+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-08-08 14:38:56+02:00
log9daad52a12deaa0bc53f9a54cfad3e5c7ae907d7
treee8bf554ee894e81fccfca9f809826f5ffbd3ef44
parentc9c97ee845459f416f7132f4d381301072315baa

std.os.linux.tls: export __tls_get_offset instead of __tls_get_addr on s390x

This needs to return the offset from TP for the variable, which will be negative because this is TLS variant II. This ABI does not use __tls_get_addr at all, so it's best not to even export it, as that will help catch bad code.

1 files changed, 23 insertions(+), 2 deletions(-)

lib/std/os/linux/tls.zig+23-2
......@@ -726,12 +726,14 @@ comptime {
726726 // function for the GD and LD models. This function is unlikely to actually be used, since
727727 // the linker should be able to relax every TLS access to the LE model and therefore
728728 // eliminate all calls to this function, but that isn't guaranteed.
729 _ = struct {
729 const Fns = struct {
730730 const TlsIndex = switch (native_arch) {
731731 .x86_64 => extern struct { module: u64, offset: u64 }, // Even for x32...
732732 else => extern struct { module: usize, offset: usize }, // ...but not MIPS N32!
733733 };
734 export fn __tls_get_addr(ti: *const TlsIndex) *anyopaque {
734 fn __tls_get_addr(ti: *const TlsIndex) callconv(.c) *anyopaque {
735 comptime assert(native_arch != .s390x);
736
735737 assert(ti.module == 1); // The executable's module ID is always 1
736738 const tp = getThreadPointer();
737739 const block: [*]u8 = switch (current_variant) {
......@@ -743,6 +745,25 @@ comptime {
743745 };
744746 return block[@intCast(ti.offset)..];
745747 }
748 fn __tls_get_offset() callconv(.naked) noreturn {
749 comptime assert(native_arch == .s390x);
750
751 // We receive the module's GOT pointer in r12 and the GOT offset in r2.
752 asm volatile (
753 \\ la %%r1, 0(%%r12, %%r2)
754 \\ lg %%r2, 8(%%r1)
755 \\ lgrl %%r0, %[block_size]
756 \\ sgr %%r2, %%r0
757 \\ br %%r14
758 :
759 : [block_size] "s" (&area_desc.block.size),
760 );
761 }
746762 };
763
764 if (native_arch == .s390x)
765 @export(&Fns.__tls_get_offset, .{ .name = "__tls_get_offset" })
766 else
767 @export(&Fns.__tls_get_addr, .{ .name = "__tls_get_addr" });
747768 }
748769}