Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20220419162647.GA10881@brightrain.aerifal.cx>
Date: Tue, 19 Apr 2022 12:26:49 -0400
From: Rich Felker <dalias@...c.org>
To: libc-coord@...ts.openwall.com
Subject: Macro-based advertisement of libc extensions, cont'd

Context is picking back up the proposal from 2020:

https://www.openwall.com/lists/libc-coord/2020/04/22/1
Message-ID: <20200422173825.GA8375@...ghtrain.aerifal.cx>

On the basis of a user frustrated at not having a configure-probe-free
way to look for extensions (for header-only library use), I started
looking at this again, actually digging into the scope of what needs
to be covered. I have a partial list of the interfaces from musl I
would want to advertise the presence of (which I'll post in a
follow-up when I flesh it out a bit more), and some general thoughts
from sorting through them:

1. A number of the nonstandard interfaces we have are purely legacy
things that serve no purpose in new code -- for example, setbuffer and
setlinebuf in stdio.h, which have direct portable rephrasing in terms
of the standard C setvbuf. I'm of the opinion that these should be
omitted entirely, and that, in general, decisions to advertise the
presence of an extension via a macro should be motivated by that
extension having some utility in facilitating portability.

2. Extensions fall into at least 2 broad groups by how they're
exposed: many are additional declarations in standard headers, while
others have their own nonstandard headers. For the former, it's
plausible that existing implementations differ as to where they're
declared (and this may vary by FTMs). This probably helps decide
whether to expose the macros via the same header exposing the
interfaces, or via unistd.h.

3. I think the list I'm making from musl is actually a really good
cross-platform starting point for this, specifically because in musl
we've been careful about only including extensions that other existing
implementations are widely in agreement on. That's not to say there
aren't a fairly large number of other extensions that should be
exposable via this proposal that musl doesn't have, but that the ones
from my list should be pretty much entirely non-controversial and a
good starting point for populating the "spec".

4. None of my investigation yet includes advertising of behavioral
properties that can't be compile-tested. I'll look more into that as a
separate phase. A good first case to look at advertising would be
extension format specifiers accepted by printf and strftime.


So, some specifics for this proposal:

For individual interfaces, macro is exposed where the interface is
exposed, under the same conditions (FTMs) that expose it. For example:

string.h:

void *memmem(const void *, size_t, const void *, size_t);
#define _EXT_MEMMEM 202204L

The value of the macro works like POSIX ones, where the date-style
version should reflect when the macro was added to the official list,
and specifically, can be less than the earliest version in the
official list if it's being advertised tentatively before inclusion. I
would expect applications to just do

#if _EXT_MEMMEM > 0

or

#if defined(_EXT_MEMMEM) && _EXT_MEMMEM > 0

or whatever warning-avoiding tricks they like, but the version allows
handling of any mistakes (advertising something that turns out not to
actually have cross-platform commonality) if that's ever needed.

The special value of 0 also exists, as proposed before, for
functionality that's available for link but might not be available at
runtime.

For extension headers, unistd.h declares the availability of the
header. For example:

unistd.h:

#define _EXT_SYS_AUXV_H 202204L

sys/auxv.h:

unsigned long getauxval(unsigned long);
#define _EXT_GETAUXVAL 202204L

Strictly speaking, advertising individual baseline functions for the
extension header like this is not necessary; presence of the header
could be deemed to imply them. However it seems to be polite in case
there's any doubt about whether future implementations might have a
same-named extension header without the same idea of what constitutes
"baseline" functionality for it.

Not that advertising headers like this overlaps in functionality with
__has_include in recent compilers. I still think it's useful in that
it doesn't assume compiler features and relies on what the
implementation reports rather than on probing files -- the whole point
of this proposal is allowing the implementation to self-describe
extensions in ways that don't require probing.

In some cases, implementations might differ in where they expose an
interface. A program trying to use getentropy portably might do:

#define _BSD_SOURCE
#define _GNU_SOURCE
#include <unistd.h>
#if _EXT_SYS_RANDOM_H
#include <sys/random.h>
#endif
#if #_EXT_GETENTROPY > 0
// ...
#endif

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.