NetBSD/lib/libc/README

238 lines
7.3 KiB
Plaintext

$NetBSD: README,v 1.7 2017/02/08 13:31:36 riastradh Exp $
libc: The C library.
* ELF symbols and source names
libc contains symbols for:
(a) standard library routines in C and POSIX,
(b) published NetBSD-specific nonstandard extensions,
(c) internal symbols, and
(d) old versions of any published library routines.
** Standard library routines
If a library routine is standard and its signature has never changed,
it is provided as an ELF global symbol. Its name is declared normally
in the appropriate header file.
=> Example: The names `malloc' and `free' are declared normally in
<stdlib.h> (src/include/stdlib.h):
void *malloc(size_t);
void free(void *);
libc provides the following ELF symbols:
malloc global
free global
In the implementation of libc, malloc and free are defined normally
in src/lib/libc/stdlib/jemalloc.c:
void *
malloc(size_t size)
{
...
void
free(void *ptr)
{
...
** NetBSD-specific nonstandard extensions
If a library routine is nonstandard but published and its signature has
never changed, it is provided as an ELF weak symbol aliasing an ELF
global symbol of the same name with an underscore prefix.
The name is declared normally in the appropriate header file, provided
that the relevant feature macro, such as _NETBSD_SOURCE, is defined.
Within libc, the name is defined in "namespace.h"
(src/lib/libc/include/namespace.h) as a macro expanding to the
underscored name, which is included before the relevant header file, so
that
(a) the definition in a .c file will define the underscored ELF global
symbol, and
(b) the declaration in the standard header file will match the
definition in the .c file.
Alongside the definition in the .c file is a __weak_alias directive to
create the ELF weak symbol alias.
=> Example: For the nonstandard extension consttime_memequal, the
header file <string.h> (src/include/string.h) declares
`consttime_memequal' normally, if the caller defines _NETBSD_SOURCE:
#if defined(_NETBSD_SOURCE)
...
int consttime_memequal(const void *, const void *, size_t);
...
#endif /* _NETBSD_SOURCE */
libc provides the following ELF symbols:
_consttime_memequal global
consttime_memequal weak alias for _consttime_memequal
In the implementation of libc, the header file "namespace.h"
(src/lib/libc/include/namespace.h) defines `consttime_memequal' as a
macro expanding to `_consttime_memequal':
#define consttime_memequal _consttime_memequal
The source file src/common/lib/libc/string/consttime_memequal.c
includes "namespace.h" and <string.h>, and defines
`consttime_memequal' normally:
int
consttime_memequal(const void *b1, const void *b2, size_t len)
{
...
Macro expansion replaces `consttime_memequal' by
`_consttime_memequal', which is the ELF global symbol this defines.
Alongside the definition is
__weak_alias(consttime_memequal,_consttime_memequal)
to provide `consttime_memequal' as an ELF weak symbol aliasing
`_consttime_memequal'.
** Internal symbols
If a library routine is internal to libc, it is defined as an ELF
global symbol with an underscore prefix. Its name is declared in the
appropriate internal header file.
=> Example: The implementations of opendir and rewinddir use a common
subroutine _initdir, which is not part of the libc API or ABI -- it
is just an internal subroutine.
libc provides the following ELF symbols:
_initdir global
The name `_initdir' is declared normally in
src/lib/libc/gen/dirent_private.h:
int _initdir(DIR *, int, const char *);
The name `_initdir' is defined normally in
src/lib/libc/gen/initdir.c:
int
_initdir(DIR *dirp, int fd, const char *name)
{
...
** Old versions of library routines
If the signature or semantics of a library routine foo changed in (for
example) NetBSD 6.0, then libc provides
(1) an ELF global symbol `_foo' implementing its old signature,
(2) an ELF weak symbol `foo' aliasing `_foo', and
(3) an ELF global symbol `__foo50' implementing its new signature (yes,
`__foo50', not `__foo60').
The name foo is declared in the appropriate header file, under any
relevant feature macros, with a __RENAME directive so that for calls to
foo, the compiler will generate relocations for __foo50. Old programs,
compiled with the old signature, will continue to use the old symbol.
=> Example: In NetBSD 5.0, time_t was int32_t on every machine. In
NetBSD 6.0 and onward, time_t is int64_t on every machine.
Consequently, the signature of time(3), written as
time_t time(time_t *);
was effectively
int32_t time(int32_t *);
before NetBSD 6.0. In NetBSD 6.0, it changed to be effectively
int64_t time(int64_t *);
Before NetBSD 6.0, libc provided the following libc symbols:
_time global (implementing the old signature)
time weak alias for _time
In NetBSD 6.0 and later, libc provides the following ELF symbols:
_time global (implementing the old signature)
time weak alias for _time
__time50 global (implementing the new signature)
(Note that the only change is to add __time50, so that existing
programs linked against old versions of libc will see the same
semantics for the symbols that were already there.)
The header file <time.h> (src/include/time.h) declares
time_t time(time_t *) __RENAME(__time50);
so that compiling C programs that call time will yield objects that
use the __time50 symbol from libc. However, old programs that were
compiled against the 32-bit declaration will continue to use the
32-bit symbol from libc.
The header file "namespace.h" (src/lib/libc/include/namespace.h)
defines `time' as a macro expanding to `_time':
#define time _time
The source file src/lib/libc/gen/time.c includes "namespace.h" and
<time.h> and defines `time' normally:
time_t
time(time_t *t)
{
...
Macro expansion replaces `time' by `_time', but the
`__RENAME(__time50)' directive on the declaration <time.h> (to which
the "namespace.h" macro expansion also applies) means the ELF global
symbol defined here is actually `__time50'.
The header file <compat/include/time.h>
(src/lib/libc/compat/include/time.h) declares
int32_t time(int32_t *);
The source file src/lib/libc/compat/gen/compat_time.c includes
"namespace.h", <compat/include/time.h>, and <time.h>, but suppresses
the normal declaration of `time' in <time.h> by defining
__LIBC12_SOURCE__ and thus gets it from <compat/include/time.h>
instead. Then compat_time.c defines `time' normally:
int32_t
time(int32_t *t)
{
...
Again, macro expansion replaces `time' by `_time', but since there
is no __RENAME directive in <compat/include/time.h>, the resulting
ELF global symbol is `_time'. (Actually, compat_time.c just has
`#define time_t int32_t' and `#include "gen/time.c"' to get the same
text of the definition of time. The above definition is what we get
effectively by substituting int32_t for the type time_t.)
Finally, alongside the definition in compat_time.c is
__weak_alias(time,_time)
to define `time' as an ELF weak symbol aliasing `_time'.
The net effect is that NetBSD 6's libc provides the same definitions
as NetBSD 5's libc for the symbols `time' and `_time', so that old
programs that were compiled in NetBSD 5 will continue to work with
NetBSD 6's libc. But programs compiled in NetBSD 6 will have 64-bit
time_t.