diff --git a/lib/compiler_rt/elf/tls.zig b/lib/compiler_rt/elf/tls.zig index dccd2018ce02a2b32050b239a30f9d30dc9d06bd..1d53b6de023feb126a9a459a642ed7798ff414c8 100644 --- a/lib/compiler_rt/elf/tls.zig +++ b/lib/compiler_rt/elf/tls.zig @@ -29,10 +29,14 @@ comptime { // function for the GD and LD models. This function is unlikely to actually be used, since the // linker should be able to relax every TLS access to the LE model and therefore eliminate all // calls to this function, but that isn't guaranteed. - if (native_arch == .s390x) - symbol(&__tls_get_offset, "__tls_get_offset") - else + if (native_arch == .s390x) { + symbol(&__tls_get_offset, "__tls_get_offset"); + } else { symbol(&__tls_get_addr, "__tls_get_addr"); + if (native_arch == .x86) { + symbol(&___tls_get_addr, "___tls_get_addr"); + } + } } /// Represents an ELF TLS variant. @@ -740,6 +744,18 @@ fn __tls_get_addr(ti: *const TlsIndex) callconv(.c) *anyopaque { return block[@intCast(ti.offset)..]; } +fn ___tls_get_addr() callconv(.naked) *anyopaque { + comptime assert(native_arch == .x86); + + // We receive the `TlsIndex` pointer in eax. + comptime assert(@sizeOf(AbiTcb) + @sizeOf(ZigTcb) + @offsetOf(Dtv, "tls_block") == 12); + asm volatile ( + \\ mov 4(%%eax), %%eax + \\ add %%gs:12, %%eax + \\ ret + ); +} + fn __tls_get_offset() callconv(.naked) noreturn { comptime assert(native_arch == .s390x);