errno/h_errno
H. Peter Anvin
hpa@zytor.com
Tue Jun 10 08:58:09 GMT 2025
On June 10, 2025 1:14:02 AM PDT, Florian Weimer <fweimer@redhat.com> wrote:
>* H. Peter Anvin:
>
>> On 2025-06-09 20:51, H. Peter Anvin wrote:
>>> Ok, I grok that back in 2016 the tools might not have been ready
>>> yet, but in 2025?
>>>
>>
>> It is also perhaps worth noting that the errno TLS symbol is already
>> globally exported and visible. This code works exactly as expected
>> when linked against current glibc, either statically or dynamically:
>>
>> #define _GNU_SOURCE
>> #include <stdio.h>
>> #include <errno.h>
>> #include <unistd.h>
>> #include <string.h>
>>
>> #undef errno
>> extern __thread int errno __attribute__((tls_model("initial-exec")));
>>
>> int main(void)
>> {
>> errno = 0;
>> close(999);
>> /* errno should be EBADF now */
>> printf("errno = %d (%s), &errno = %p, __errno_location = %p\n",
>> errno, strerrorname_np(errno), &errno, __errno_location());
>> return 0;
>> }
>
>This puts a GLIBC_PRIVATE reference into applications, which interferes
>with distribution dependency management. This could be fixed by
>exporting it as errno@@GLIBC_2.42.
>
>However, I'm not sure if we want to promote an initial-exec TLS
>reference, it makes it more difficult to move libc.so.6 off initial-exec
>TLS as a whole, to allow more dlmopen namespaces. Code overhead with
>GNU2 TLS descriptors is rather low, only with the __tls_get_addr calls,
>the function call approach is a clear win in terms of code size. (I was
>concerned about code size during the last discussion.)
>
>Thanks,
>Florian
>
It seems more than a little odd to want errno specifically on a different model. The initial-exec model works for errno, and since nearly every system call needs errno it is nearly impossible to have any cause at all without it, and certainly not to dynamically link it.
To put it differently, errno is special, very special; it is in fact so special that it could easily justify special handling in the ABI (by moving out into the TCB) like the stack canary at least used to have; this would further reduce the access cost down to a single instruction on most architectures.
Similarly, it isn't like the type or meaning of errno can realistically ever change.
The code size difference is generally negative due to omitting the function call and the associated bloat due to register usage (the original reason I was looking into this.)
The descriptor ABI for TLS is much nicer, to be sure, but it still involves a function call which, in the case of errno, will inherently be a noop.
errno@GLIBC_PRIVATE is certainly ugly. I have to admit to finding that notation a bit problematic in general as it prevents something that ends up getting "unauthorized" usage – intentionally or not – to become retroactively made ABI. It is a statement of intended policy, not of technical compatibility, and being by and large invisible to users, doesn't really serve much of that purpose.
More information about the Libc-alpha
mailing list