1 $NetBSD: README,v 1.8 2026/05/15 14:07:17 riastradh Exp $
2
3 libc: The C library.
4
5 * ELF symbols and source names
6
7 libc contains symbols for:
8
9 (a) standard library routines in C and POSIX,
10 (b) published NetBSD-specific nonstandard extensions,
11 (c) internal symbols, and
12 (d) old versions of any published library routines.
13
14 ** Standard library routines
15
16 If a library routine is standard and its signature has never changed,
17 it is provided as an ELF global symbol. Its name is declared normally
18 in the appropriate header file.
19
20 => Example: The names `malloc' and `free' are declared normally in
21 <stdlib.h> (src/include/stdlib.h):
22
23 void *malloc(size_t);
24 void free(void *);
25
26 libc provides the following ELF symbols:
27
28 malloc global
29 free global
30
31 In the implementation of libc, malloc and free are defined normally
32 in src/lib/libc/stdlib/jemalloc.c (on some ports, though it is
33 buried in the guts of src/external/bsd/jemalloc/dist/src/* on newer
34 ports):
35
36 void *
37 malloc(size_t size)
38 {
39 ...
40
41 void
42 free(void *ptr)
43 {
44 ...
45
46 ** NetBSD-specific nonstandard extensions
47
48 If a library routine is nonstandard but published and its signature has
49 never changed, it is provided as an ELF weak symbol aliasing an ELF
50 global symbol of the same name with an underscore prefix.
51
52 The name is declared normally in the appropriate header file, provided
53 that the relevant feature macro, such as _NETBSD_SOURCE, is defined.
54
55 Within libc, the name is defined in "namespace.h"
56 (src/lib/libc/include/namespace.h) as a macro expanding to the
57 underscored name, which is included before the relevant header file, so
58 that
59
60 (a) the definition in a .c file will define the underscored ELF global
61 symbol, and
62
63 (b) the declaration in the standard header file will match the
64 definition in the .c file.
65
66 Alongside the definition in the .c file is a __weak_alias directive to
67 create the ELF weak symbol alias.
68
69 => Example: For the nonstandard extension consttime_memequal, the
70 header file <string.h> (src/include/string.h) declares
71 `consttime_memequal' normally, if the caller defines _NETBSD_SOURCE:
72
73 #if defined(_NETBSD_SOURCE)
74 ...
75 int consttime_memequal(const void *, const void *, size_t);
76 ...
77 #endif /* _NETBSD_SOURCE */
78
79 libc provides the following ELF symbols:
80
81 _consttime_memequal global
82 consttime_memequal weak alias for _consttime_memequal
83
84 In the implementation of libc, the header file "namespace.h"
85 (src/lib/libc/include/namespace.h) defines `consttime_memequal' as a
86 macro expanding to `_consttime_memequal':
87
88 #define consttime_memequal _consttime_memequal
89
90 The source file src/common/lib/libc/string/consttime_memequal.c
91 includes "namespace.h" and <string.h>, and defines
92 `consttime_memequal' normally:
93
94 int
95 consttime_memequal(const void *b1, const void *b2, size_t len)
96 {
97 ...
98
99 Macro expansion replaces `consttime_memequal' by
100 `_consttime_memequal', which is the ELF global symbol this defines.
101 Alongside the definition is
102
103 __weak_alias(consttime_memequal,_consttime_memequal)
104
105 to provide `consttime_memequal' as an ELF weak symbol aliasing
106 `_consttime_memequal'.
107
108 ** Internal symbols
109
110 If a library routine is internal to libc, it is defined as an ELF
111 global symbol with an underscore prefix. Its name is declared in the
112 appropriate internal header file.
113
114 => Example: The implementations of opendir and rewinddir use a common
115 subroutine _initdir, which is not part of the libc API or ABI -- it
116 is just an internal subroutine.
117
118 libc provides the following ELF symbols:
119
120 _initdir global
121
122 The name `_initdir' is declared normally in
123 src/lib/libc/gen/dirent_private.h:
124
125 int _initdir(DIR *, int, const char *);
126
127 The name `_initdir' is defined normally in
128 src/lib/libc/gen/initdir.c:
129
130 int
131 _initdir(DIR *dirp, int fd, const char *name)
132 {
133 ...
134
135 ** Old versions of library routines
136
137 If the signature or semantics of a library routine foo changed in (for
138 example) NetBSD 6.0, then libc provides
139
140 (1) an ELF global symbol `_foo' implementing its old signature,
141 (2) an ELF weak symbol `foo' aliasing `_foo', and
142 (3) an ELF global symbol `__foo50' implementing its new signature (yes,
143 `__foo50', not `__foo60').
144
145 The name foo is declared in the appropriate header file, under any
146 relevant feature macros, with a __RENAME directive so that for calls to
147 foo, the compiler will generate relocations for __foo50. Old programs,
148 compiled with the old signature, will continue to use the old symbol.
149
150 => Example: In NetBSD 5.0, time_t was int32_t on every machine. In
151 NetBSD 6.0 and onward, time_t is int64_t on every machine.
152 Consequently, the signature of time(3), written as
153
154 time_t time(time_t *);
155
156 was effectively
157
158 int32_t time(int32_t *);
159
160 before NetBSD 6.0. In NetBSD 6.0, it changed to be effectively
161
162 int64_t time(int64_t *);
163
164 Before NetBSD 6.0, libc provided the following libc symbols:
165
166 _time global (implementing the old signature)
167 time weak alias for _time
168
169 In NetBSD 6.0 and later, libc provides the following ELF symbols:
170
171 _time global (implementing the old signature)
172 time weak alias for _time
173 __time50 global (implementing the new signature)
174
175 (Note that the only change is to add __time50, so that existing
176 programs linked against old versions of libc will see the same
177 semantics for the symbols that were already there.)
178
179 The header file <time.h> (src/include/time.h) declares
180
181 time_t time(time_t *) __RENAME(__time50);
182
183 so that compiling C programs that call time will yield objects that
184 use the __time50 symbol from libc. However, old programs that were
185 compiled against the 32-bit declaration will continue to use the
186 32-bit symbol from libc.
187
188 The header file "namespace.h" (src/lib/libc/include/namespace.h)
189 defines `time' as a macro expanding to `_time':
190
191 #define time _time
192
193 The source file src/lib/libc/gen/time.c includes "namespace.h" and
194 <time.h> and defines `time' normally:
195
196 time_t
197 time(time_t *t)
198 {
199 ...
200
201 Macro expansion replaces `time' by `_time', but the
202 `__RENAME(__time50)' directive on the declaration <time.h> (to which
203 the "namespace.h" macro expansion also applies) means the ELF global
204 symbol defined here is actually `__time50'.
205
206 The header file <compat/include/time.h>
207 (src/lib/libc/compat/include/time.h) declares
208
209 int32_t time(int32_t *);
210
211 The source file src/lib/libc/compat/gen/compat_time.c includes
212 "namespace.h", <compat/include/time.h>, and <time.h>, but suppresses
213 the normal declaration of `time' in <time.h> by defining
214 __LIBC12_SOURCE__ and thus gets it from <compat/include/time.h>
215 instead. Then compat_time.c defines `time' normally:
216
217 int32_t
218 time(int32_t *t)
219 {
220 ...
221
222 Again, macro expansion replaces `time' by `_time', but since there
223 is no __RENAME directive in <compat/include/time.h>, the resulting
224 ELF global symbol is `_time'. (Actually, compat_time.c just has
225 `#define time_t int32_t' and `#include "gen/time.c"' to get the same
226 text of the definition of time. The above definition is what we get
227 effectively by substituting int32_t for the type time_t.)
228
229 Finally, alongside the definition in compat_time.c is
230
231 __weak_alias(time,_time)
232
233 to define `time' as an ELF weak symbol aliasing `_time'.
234
235 The net effect is that NetBSD 6's libc provides the same definitions
236 as NetBSD 5's libc for the symbols `time' and `_time', so that old
237 programs that were compiled in NetBSD 5 will continue to work with
238 NetBSD 6's libc. But programs compiled in NetBSD 6 will have 64-bit
239 time_t.
240