Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
2/*
3 * stdlib function definitions for NOLIBC
4 * Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
5 */
6
7#ifndef _NOLIBC_STDLIB_H
8#define _NOLIBC_STDLIB_H
9
10#include "std.h"
11#include "arch.h"
12#include "types.h"
13#include "sys.h"
14#include "string.h"
15
16struct nolibc_heap {
17 size_t len;
18 char user_p[] __attribute__((__aligned__));
19};
20
21/* Buffer used to store int-to-ASCII conversions. Will only be implemented if
22 * any of the related functions is implemented. The area is large enough to
23 * store "18446744073709551615" or "-9223372036854775808" and the final zero.
24 */
25static __attribute__((unused)) char itoa_buffer[21];
26
27/*
28 * As much as possible, please keep functions alphabetically sorted.
29 */
30
31/* must be exported, as it's used by libgcc for various divide functions */
32__attribute__((weak,unused,noreturn,section(".text.nolibc_abort")))
33void abort(void)
34{
35 sys_kill(sys_getpid(), SIGABRT);
36 for (;;);
37}
38
39static __attribute__((unused))
40long atol(const char *s)
41{
42 unsigned long ret = 0;
43 unsigned long d;
44 int neg = 0;
45
46 if (*s == '-') {
47 neg = 1;
48 s++;
49 }
50
51 while (1) {
52 d = (*s++) - '0';
53 if (d > 9)
54 break;
55 ret *= 10;
56 ret += d;
57 }
58
59 return neg ? -ret : ret;
60}
61
62static __attribute__((unused))
63int atoi(const char *s)
64{
65 return atol(s);
66}
67
68static __attribute__((unused))
69void free(void *ptr)
70{
71 struct nolibc_heap *heap;
72
73 if (!ptr)
74 return;
75
76 heap = container_of(ptr, struct nolibc_heap, user_p);
77 munmap(heap, heap->len);
78}
79
80/* getenv() tries to find the environment variable named <name> in the
81 * environment array pointed to by global variable "environ" which must be
82 * declared as a char **, and must be terminated by a NULL (it is recommended
83 * to set this variable to the "envp" argument of main()). If the requested
84 * environment variable exists its value is returned otherwise NULL is
85 * returned. getenv() is forcefully inlined so that the reference to "environ"
86 * will be dropped if unused, even at -O0.
87 */
88static __attribute__((unused))
89char *_getenv(const char *name, char **environ)
90{
91 int idx, i;
92
93 if (environ) {
94 for (idx = 0; environ[idx]; idx++) {
95 for (i = 0; name[i] && name[i] == environ[idx][i];)
96 i++;
97 if (!name[i] && environ[idx][i] == '=')
98 return &environ[idx][i+1];
99 }
100 }
101 return NULL;
102}
103
104static inline __attribute__((unused,always_inline))
105char *getenv(const char *name)
106{
107 extern char **environ;
108 return _getenv(name, environ);
109}
110
111static __attribute__((unused))
112void *malloc(size_t len)
113{
114 struct nolibc_heap *heap;
115
116 /* Always allocate memory with size multiple of 4096. */
117 len = sizeof(*heap) + len;
118 len = (len + 4095UL) & -4096UL;
119 heap = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE,
120 -1, 0);
121 if (__builtin_expect(heap == MAP_FAILED, 0))
122 return NULL;
123
124 heap->len = len;
125 return heap->user_p;
126}
127
128static __attribute__((unused))
129void *calloc(size_t size, size_t nmemb)
130{
131 void *orig;
132 size_t res = 0;
133
134 if (__builtin_expect(__builtin_mul_overflow(nmemb, size, &res), 0)) {
135 SET_ERRNO(ENOMEM);
136 return NULL;
137 }
138
139 /*
140 * No need to zero the heap, the MAP_ANONYMOUS in malloc()
141 * already does it.
142 */
143 return malloc(res);
144}
145
146static __attribute__((unused))
147void *realloc(void *old_ptr, size_t new_size)
148{
149 struct nolibc_heap *heap;
150 size_t user_p_len;
151 void *ret;
152
153 if (!old_ptr)
154 return malloc(new_size);
155
156 heap = container_of(old_ptr, struct nolibc_heap, user_p);
157 user_p_len = heap->len - sizeof(*heap);
158 /*
159 * Don't realloc() if @user_p_len >= @new_size, this block of
160 * memory is still enough to handle the @new_size. Just return
161 * the same pointer.
162 */
163 if (user_p_len >= new_size)
164 return old_ptr;
165
166 ret = malloc(new_size);
167 if (__builtin_expect(!ret, 0))
168 return NULL;
169
170 memcpy(ret, heap->user_p, heap->len);
171 munmap(heap, heap->len);
172 return ret;
173}
174
175/* Converts the unsigned long integer <in> to its hex representation into
176 * buffer <buffer>, which must be long enough to store the number and the
177 * trailing zero (17 bytes for "ffffffffffffffff" or 9 for "ffffffff"). The
178 * buffer is filled from the first byte, and the number of characters emitted
179 * (not counting the trailing zero) is returned. The function is constructed
180 * in a way to optimize the code size and avoid any divide that could add a
181 * dependency on large external functions.
182 */
183static __attribute__((unused))
184int utoh_r(unsigned long in, char *buffer)
185{
186 signed char pos = (~0UL > 0xfffffffful) ? 60 : 28;
187 int digits = 0;
188 int dig;
189
190 do {
191 dig = in >> pos;
192 in -= (uint64_t)dig << pos;
193 pos -= 4;
194 if (dig || digits || pos < 0) {
195 if (dig > 9)
196 dig += 'a' - '0' - 10;
197 buffer[digits++] = '0' + dig;
198 }
199 } while (pos >= 0);
200
201 buffer[digits] = 0;
202 return digits;
203}
204
205/* converts unsigned long <in> to an hex string using the static itoa_buffer
206 * and returns the pointer to that string.
207 */
208static inline __attribute__((unused))
209char *utoh(unsigned long in)
210{
211 utoh_r(in, itoa_buffer);
212 return itoa_buffer;
213}
214
215/* Converts the unsigned long integer <in> to its string representation into
216 * buffer <buffer>, which must be long enough to store the number and the
217 * trailing zero (21 bytes for 18446744073709551615 in 64-bit, 11 for
218 * 4294967295 in 32-bit). The buffer is filled from the first byte, and the
219 * number of characters emitted (not counting the trailing zero) is returned.
220 * The function is constructed in a way to optimize the code size and avoid
221 * any divide that could add a dependency on large external functions.
222 */
223static __attribute__((unused))
224int utoa_r(unsigned long in, char *buffer)
225{
226 unsigned long lim;
227 int digits = 0;
228 int pos = (~0UL > 0xfffffffful) ? 19 : 9;
229 int dig;
230
231 do {
232 for (dig = 0, lim = 1; dig < pos; dig++)
233 lim *= 10;
234
235 if (digits || in >= lim || !pos) {
236 for (dig = 0; in >= lim; dig++)
237 in -= lim;
238 buffer[digits++] = '0' + dig;
239 }
240 } while (pos--);
241
242 buffer[digits] = 0;
243 return digits;
244}
245
246/* Converts the signed long integer <in> to its string representation into
247 * buffer <buffer>, which must be long enough to store the number and the
248 * trailing zero (21 bytes for -9223372036854775808 in 64-bit, 12 for
249 * -2147483648 in 32-bit). The buffer is filled from the first byte, and the
250 * number of characters emitted (not counting the trailing zero) is returned.
251 */
252static __attribute__((unused))
253int itoa_r(long in, char *buffer)
254{
255 char *ptr = buffer;
256 int len = 0;
257
258 if (in < 0) {
259 in = -in;
260 *(ptr++) = '-';
261 len++;
262 }
263 len += utoa_r(in, ptr);
264 return len;
265}
266
267/* for historical compatibility, same as above but returns the pointer to the
268 * buffer.
269 */
270static inline __attribute__((unused))
271char *ltoa_r(long in, char *buffer)
272{
273 itoa_r(in, buffer);
274 return buffer;
275}
276
277/* converts long integer <in> to a string using the static itoa_buffer and
278 * returns the pointer to that string.
279 */
280static inline __attribute__((unused))
281char *itoa(long in)
282{
283 itoa_r(in, itoa_buffer);
284 return itoa_buffer;
285}
286
287/* converts long integer <in> to a string using the static itoa_buffer and
288 * returns the pointer to that string. Same as above, for compatibility.
289 */
290static inline __attribute__((unused))
291char *ltoa(long in)
292{
293 itoa_r(in, itoa_buffer);
294 return itoa_buffer;
295}
296
297/* converts unsigned long integer <in> to a string using the static itoa_buffer
298 * and returns the pointer to that string.
299 */
300static inline __attribute__((unused))
301char *utoa(unsigned long in)
302{
303 utoa_r(in, itoa_buffer);
304 return itoa_buffer;
305}
306
307/* Converts the unsigned 64-bit integer <in> to its hex representation into
308 * buffer <buffer>, which must be long enough to store the number and the
309 * trailing zero (17 bytes for "ffffffffffffffff"). The buffer is filled from
310 * the first byte, and the number of characters emitted (not counting the
311 * trailing zero) is returned. The function is constructed in a way to optimize
312 * the code size and avoid any divide that could add a dependency on large
313 * external functions.
314 */
315static __attribute__((unused))
316int u64toh_r(uint64_t in, char *buffer)
317{
318 signed char pos = 60;
319 int digits = 0;
320 int dig;
321
322 do {
323 if (sizeof(long) >= 8) {
324 dig = (in >> pos) & 0xF;
325 } else {
326 /* 32-bit platforms: avoid a 64-bit shift */
327 uint32_t d = (pos >= 32) ? (in >> 32) : in;
328 dig = (d >> (pos & 31)) & 0xF;
329 }
330 if (dig > 9)
331 dig += 'a' - '0' - 10;
332 pos -= 4;
333 if (dig || digits || pos < 0)
334 buffer[digits++] = '0' + dig;
335 } while (pos >= 0);
336
337 buffer[digits] = 0;
338 return digits;
339}
340
341/* converts uint64_t <in> to an hex string using the static itoa_buffer and
342 * returns the pointer to that string.
343 */
344static inline __attribute__((unused))
345char *u64toh(uint64_t in)
346{
347 u64toh_r(in, itoa_buffer);
348 return itoa_buffer;
349}
350
351/* Converts the unsigned 64-bit integer <in> to its string representation into
352 * buffer <buffer>, which must be long enough to store the number and the
353 * trailing zero (21 bytes for 18446744073709551615). The buffer is filled from
354 * the first byte, and the number of characters emitted (not counting the
355 * trailing zero) is returned. The function is constructed in a way to optimize
356 * the code size and avoid any divide that could add a dependency on large
357 * external functions.
358 */
359static __attribute__((unused))
360int u64toa_r(uint64_t in, char *buffer)
361{
362 unsigned long long lim;
363 int digits = 0;
364 int pos = 19; /* start with the highest possible digit */
365 int dig;
366
367 do {
368 for (dig = 0, lim = 1; dig < pos; dig++)
369 lim *= 10;
370
371 if (digits || in >= lim || !pos) {
372 for (dig = 0; in >= lim; dig++)
373 in -= lim;
374 buffer[digits++] = '0' + dig;
375 }
376 } while (pos--);
377
378 buffer[digits] = 0;
379 return digits;
380}
381
382/* Converts the signed 64-bit integer <in> to its string representation into
383 * buffer <buffer>, which must be long enough to store the number and the
384 * trailing zero (21 bytes for -9223372036854775808). The buffer is filled from
385 * the first byte, and the number of characters emitted (not counting the
386 * trailing zero) is returned.
387 */
388static __attribute__((unused))
389int i64toa_r(int64_t in, char *buffer)
390{
391 char *ptr = buffer;
392 int len = 0;
393
394 if (in < 0) {
395 in = -in;
396 *(ptr++) = '-';
397 len++;
398 }
399 len += u64toa_r(in, ptr);
400 return len;
401}
402
403/* converts int64_t <in> to a string using the static itoa_buffer and returns
404 * the pointer to that string.
405 */
406static inline __attribute__((unused))
407char *i64toa(int64_t in)
408{
409 i64toa_r(in, itoa_buffer);
410 return itoa_buffer;
411}
412
413/* converts uint64_t <in> to a string using the static itoa_buffer and returns
414 * the pointer to that string.
415 */
416static inline __attribute__((unused))
417char *u64toa(uint64_t in)
418{
419 u64toa_r(in, itoa_buffer);
420 return itoa_buffer;
421}
422
423#endif /* _NOLIBC_STDLIB_H */