3 ms·
Perhaps your conflation was deliberate, but it actually feels like you may not be conflating exactly what you think you are. Let me try to be fairly precise abo
by lgg 4y ago
Perhaps your conflation was deliberate, but it actually feels like you may not be conflating exactly what you think you are. Let me try to be fairly precise about some things:
By standard UNIX function I take it that you mean a function defined via POSIX and part of one of the various specifications used for UNIX certification (for the moment lets ignore the fact there are multiple revisions and optional extensions). It is important to note that the specifications says essentially nothing about:
* Binary formats
* Libraries (static or dynamic)[1]
* What symbols are in what library
It is all written in terms of what source code should compile, and how that compiled code functions. Everything else such as calling conventions, syscall interfaces, what is library code vs a syscall, etc is an implementation detail.
So given the above, I am not entirely sure what you mean by a `"private" C ABI when this ABI actually implemented a standard UNIX function.` Do you mean has Apple ever changed an internal function called by a function specified in POSIX? IOW, if your question is does Apple reserve the right to implement `stat()` as a call to `stat_internal()` and then change the arguments to "stat_internal()" ? Absolutely.
If you mean has Apple ever changed a function that is part of POSIX but it considers private? Those don't really exist on macOS, if POSIX allows it and it is part of the standard that has passed conformance it is by definition public and the C ABI level interfaces for as exposed by libSystem are stable (which is not to say that all of those interfaces are great, but they are standard and supported). IOW, the standard specifies that `stat()` exists, and it is by definition public.
That is not to say incompatible changes have never had to happen (for example, when UNIX conformance was originally implemented a lot of existing functions required incompatible changes to pass the test suites). All of that is handled via symbol versioning and redirecting new binaries to different symbols than the older binaries used, which maintains both binary compatibility for old binaries and allows new source to compile in the correct (conformant) way. This is why if you inspect libsystem_kernel.dylib you see variants of symbols like:
* _recvmsg
* _recvmsg$NOCANCEL$UNIX2003
* _recvmsg$UNIX2003
The old ones keep working with the existing semantics for older binaries, the headers have magic in them redirect to the newer ones when targeting the appropriate minimum OS version, and the userspace libraries have multiple entry points that provide both sets of semantics (often implemented in the userspace shim, sometimes by dispatching to the kernel with different syscalls).
[1]: Despite that, at this point POSIX does specify some of the semantic of `dlopen()` and `dlsym()`, which is pretty insane when you think about.