This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "uClibc-ng - small C library for embedded systems".
The branch, upstream has been updated
via 92de8a5f6ffb1ff9f7183fd08d872aa098b75ae2 (commit)
via d88e1855ff2828fbad0335fc8e06dd295e1c1130 (commit)
via 4449e47c2bf51beebaa0b163f4445057b221ad4e (commit)
via 59f06d06f05abf20092617fcfa34438c77d92bdd (commit)
via e55f589191162eb40f44696c77e569049313d381 (commit)
via 217f0a86c07beae6a27d422b5f46ee853f3a447a (commit)
via a952a1dd2bba69da4c52a111600f4279aadc3602 (commit)
via 920db6d3935c86aff1b4fd0096ce6b5e3605d20d (commit)
via 78b154a95b507c205241dd883396952e0dfbede7 (commit)
via 516c45013d9fa31905f172e6fc7ca9072b5148cf (commit)
from 638a23483b40c5b606ee323e6612e7e454e5154b (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 92de8a5f6ffb1ff9f7183fd08d872aa098b75ae2
Author: Bernhard Reutner-Fischer <rep.dot.nop(a)gmail.com>
Date: Mon Jan 26 16:50:29 2015 +0100
libc: sync_file_range missing comma
Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop(a)gmail.com>
commit d88e1855ff2828fbad0335fc8e06dd295e1c1130
Author: Bernhard Reutner-Fischer <rep.dot.nop(a)gmail.com>
Date: Sat Jan 24 20:50:02 2015 +0100
libc: ppc64 etc: Fix sync_file_range
Fix copy'n paste error for ppc64 and other sync_file_range2 arches
Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop(a)gmail.com>
commit 4449e47c2bf51beebaa0b163f4445057b221ad4e
Author: Max Filippov <jcmvbkbc(a)gmail.com>
Date: Sat Jan 10 06:48:37 2015 +0300
xtensa: ldso: drop unused address calculation from _dl_linux_resolve
The result of the calculation in register a12 is never used as the
function _dl_linux_resolver only accepts 2 arguments. Drop it.
Signed-off-by: Max Filippov <jcmvbkbc(a)gmail.com>
Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop(a)gmail.com>
commit 59f06d06f05abf20092617fcfa34438c77d92bdd
Author: Max Filippov <jcmvbkbc(a)gmail.com>
Date: Sat Jan 10 04:42:42 2015 +0300
xtensa: ldso: coalesce dl_mprotect address ranges
This noticeably lowers the number of mprotect calls at program startup,
e.g. for busybox: 7 calls vs 1835 calls.
Signed-off-by: Max Filippov <jcmvbkbc(a)gmail.com>
Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop(a)gmail.com>
commit e55f589191162eb40f44696c77e569049313d381
Author: Wang Yufen <wangyufen(a)huawei.com>
Date: Tue Nov 11 15:59:11 2014 +0800
add argument check in mknod
mknod() in glibc/eglibc will check the argument, like this,
...
if (k_dev != dev) {
__set_errno (EINVAL);
return -1;
}
...
So add argument check in uclibc's mknod() too.
Signed-off-by: Wang Yufen <wangyufen(a)huawei.com>
Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop(a)gmail.com>
commit 217f0a86c07beae6a27d422b5f46ee853f3a447a
Author: Xishi Qiu <qiuxishi(a)huawei.com>
Date: Tue Nov 4 19:26:28 2014 +0800
add argument check in setenv()
setenv() in glibc/eglibc will check the argument, like this,
...
if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
{
__set_errno (EINVAL);
return -1;
}
...
So add argument check in uclibc's setenv() too.
Signed-off-by: Xishi Qiu <qiuxishi(a)huawei.com>
Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop(a)gmail.com>
commit a952a1dd2bba69da4c52a111600f4279aadc3602
Author: Bernhard Reutner-Fischer <rep.dot.nop(a)gmail.com>
Date: Fri Jan 23 15:47:02 2015 +0100
nptl: compile pt-vfork in ARM-mode
amending commit 49a67cf67d5a7194214566bc730ee7e28d55bbe1
could need a thumb implementation..
Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop(a)gmail.com>
commit 920db6d3935c86aff1b4fd0096ce6b5e3605d20d
Author: Bernhard Reutner-Fischer <rep.dot.nop(a)gmail.com>
Date: Mon Jan 19 22:49:10 2015 +0100
libc: Avoid redundant setting of ENOMEM
Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop(a)gmail.com>
commit 78b154a95b507c205241dd883396952e0dfbede7
Author: Bernhard Reutner-Fischer <rep.dot.nop(a)gmail.com>
Date: Mon Jan 19 17:24:19 2015 +0100
libcrypt: return NULL on unsupported salt
BZ #7808 asks us not to fallback to DES if the optional SHA are disabled
but requested by the user.
Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop(a)gmail.com>
commit 516c45013d9fa31905f172e6fc7ca9072b5148cf
Author: Bernhard Reutner-Fischer <rep.dot.nop(a)gmail.com>
Date: Wed Jan 7 13:26:42 2015 +0100
test: Adjust passed options
to follow suit 067637375658047d70c296606ae17ef0bc86499d
Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop(a)gmail.com>
-----------------------------------------------------------------------
Summary of changes:
ldso/ldso/xtensa/dl-startup.h | 20 +++++++++++++++-
ldso/ldso/xtensa/dl-sysdep.h | 24 +++++++++++++++++++-
ldso/ldso/xtensa/resolve.S | 7 ------
libc/misc/dirent/opendir.c | 2 +-
libc/stdlib/_atexit.c | 2 +-
libc/stdlib/malloc-simple/alloc.c | 4 +++-
libc/stdlib/malloc-standard/malloc.c | 2 +-
libc/stdlib/malloc-standard/malloc.h | 2 +-
libc/stdlib/setenv.c | 11 ++++++---
libc/stdlib/unix_grantpt.c | 2 +-
libc/string/_collate.c | 4 ++--
libc/sysdeps/linux/common/mknod.c | 4 ++++
libc/sysdeps/linux/common/sync_file_range.c | 5 +++-
libcrypt/crypt.c | 18 +++++++++------
.../nptl/sysdeps/unix/sysv/linux/arm/Makefile.arch | 3 +++
test/nptl/Makefile.in | 2 +-
test/nptl/tst-cancel7.c | 2 +-
test/nptl/tst-exec4.c | 2 +-
test/nptl/tst-mqueue7.c | 6 ++---
19 files changed, 88 insertions(+), 34 deletions(-)
diff --git a/ldso/ldso/xtensa/dl-startup.h b/ldso/ldso/xtensa/dl-startup.h
index b135a4c..0c28d5e 100644
--- a/ldso/ldso/xtensa/dl-startup.h
+++ b/ldso/ldso/xtensa/dl-startup.h
@@ -83,6 +83,7 @@ do { \
unsigned long l_addr = tpnt->loadaddr; \
Elf32_Word relative_count; \
unsigned long rel_addr; \
+ Elf32_Addr prev_got_start = 0, prev_got_end = 0; \
int x; \
\
got_loc = (xtensa_got_location *) \
@@ -93,7 +94,24 @@ do { \
got_start = got_loc[x].offset & ~(PAGE_SIZE - 1); \
got_end = ((got_loc[x].offset + got_loc[x].length + PAGE_SIZE - 1) \
& ~(PAGE_SIZE - 1)); \
- _dl_mprotect ((void *)(got_start + l_addr), got_end - got_start, \
+ if (got_end >= prev_got_start && got_start <= prev_got_end) { \
+ if (got_end > prev_got_end) \
+ prev_got_end = got_end; \
+ if (got_start < prev_got_start) \
+ prev_got_start = got_start; \
+ continue; \
+ } else if (prev_got_start != prev_got_end) { \
+ _dl_mprotect ((void *)(prev_got_start + l_addr), \
+ prev_got_end - prev_got_start, \
+ PROT_READ | PROT_WRITE | PROT_EXEC); \
+ } \
+ prev_got_start = got_start; \
+ prev_got_end = got_end; \
+ } \
+\
+ if (prev_got_start != prev_got_end) { \
+ _dl_mprotect ((void *)(prev_got_start + l_addr), \
+ prev_got_end - prev_got_start, \
PROT_READ | PROT_WRITE | PROT_EXEC); \
} \
\
diff --git a/ldso/ldso/xtensa/dl-sysdep.h b/ldso/ldso/xtensa/dl-sysdep.h
index a0ed4e5..5f8bcb0 100644
--- a/ldso/ldso/xtensa/dl-sysdep.h
+++ b/ldso/ldso/xtensa/dl-sysdep.h
@@ -36,6 +36,7 @@ typedef struct xtensa_got_location_struct {
do { \
xtensa_got_location *got_loc; \
Elf32_Addr l_addr = MODULE->loadaddr; \
+ Elf32_Addr prev_got_start = 0, prev_got_end = 0; \
int x; \
\
got_loc = (xtensa_got_location *) \
@@ -47,7 +48,28 @@ typedef struct xtensa_got_location_struct {
got_start = got_loc[x].offset & ~(PAGE_SIZE - 1); \
got_end = ((got_loc[x].offset + got_loc[x].length + PAGE_SIZE - 1) \
& ~(PAGE_SIZE - 1)); \
- _dl_mprotect ((void *)(got_start + l_addr) , got_end - got_start, \
+ if (got_end >= prev_got_start && got_start <= prev_got_end) \
+ { \
+ if (got_end > prev_got_end) \
+ prev_got_end = got_end; \
+ if (got_start < prev_got_start) \
+ prev_got_start = got_start; \
+ continue; \
+ } \
+ else if (prev_got_start != prev_got_end) \
+ { \
+ _dl_mprotect ((void *)(prev_got_start + l_addr), \
+ prev_got_end - prev_got_start, \
+ PROT_READ | PROT_WRITE | PROT_EXEC); \
+ } \
+ prev_got_start = got_start; \
+ prev_got_end = got_end; \
+ } \
+ \
+ if (prev_got_start != prev_got_end) \
+ { \
+ _dl_mprotect ((void *)(prev_got_start + l_addr), \
+ prev_got_end - prev_got_start, \
PROT_READ | PROT_WRITE | PROT_EXEC); \
} \
\
diff --git a/ldso/ldso/xtensa/resolve.S b/ldso/ldso/xtensa/resolve.S
index d1ae8aa..8061af2 100644
--- a/ldso/ldso/xtensa/resolve.S
+++ b/ldso/ldso/xtensa/resolve.S
@@ -31,13 +31,6 @@
.global _dl_linux_resolve
.type _dl_linux_resolve, @function
_dl_linux_resolve:
- /* Fix up the high 2 bits of the return address. */
- movi a13, 0f
- slli a12, a0, 2
-0: extui a13, a13, 30, 2
- ssai 2
- src a12, a13, a12
-
/* Call the fixup function. */
movi a8, _dl_linux_resolver
callx8 a8
diff --git a/libc/misc/dirent/opendir.c b/libc/misc/dirent/opendir.c
index 66a5cc9..8af00f8 100644
--- a/libc/misc/dirent/opendir.c
+++ b/libc/misc/dirent/opendir.c
@@ -110,7 +110,7 @@ DIR *opendir(const char *name)
if (!ptr) {
close_not_cancel_no_status(fd);
- __set_errno(ENOMEM);
+ /* __set_errno(ENOMEM); */
}
return ptr;
}
diff --git a/libc/stdlib/_atexit.c b/libc/stdlib/_atexit.c
index ef6772f..3faa9f0 100644
--- a/libc/stdlib/_atexit.c
+++ b/libc/stdlib/_atexit.c
@@ -257,7 +257,7 @@ struct exit_function attribute_hidden *__new_exitfn(void)
efp = realloc(__exit_function_table,
(__exit_slots+20)*sizeof(struct exit_function));
if (efp == NULL) {
- __set_errno(ENOMEM);
+ /* __set_errno(ENOMEM); */
goto DONE;
}
__exit_function_table = efp;
diff --git a/libc/stdlib/malloc-simple/alloc.c b/libc/stdlib/malloc-simple/alloc.c
index 14f3846..a3c068a 100644
--- a/libc/stdlib/malloc-simple/alloc.c
+++ b/libc/stdlib/malloc-simple/alloc.c
@@ -42,8 +42,10 @@ void *malloc(size_t size)
result = mmap((void *) 0, size + sizeof(size_t), PROT_READ | PROT_WRITE,
MMAP_FLAGS, 0, 0);
- if (result == MAP_FAILED)
+ if (result == MAP_FAILED) {
+ __set_errno(ENOMEM);
return 0;
+ }
* (size_t *) result = size;
return(result + sizeof(size_t));
}
diff --git a/libc/stdlib/malloc-standard/malloc.c b/libc/stdlib/malloc-standard/malloc.c
index 3253ebd..2abb5bb 100644
--- a/libc/stdlib/malloc-standard/malloc.c
+++ b/libc/stdlib/malloc-standard/malloc.c
@@ -744,7 +744,7 @@ static void* __malloc_alloc(size_t nb, mstate av)
}
/* catch all failure paths */
- errno = ENOMEM;
+ __set_errno(ENOMEM);
return 0;
}
diff --git a/libc/stdlib/malloc-standard/malloc.h b/libc/stdlib/malloc-standard/malloc.h
index d945627..1a4cc5a 100644
--- a/libc/stdlib/malloc-standard/malloc.h
+++ b/libc/stdlib/malloc-standard/malloc.h
@@ -512,7 +512,7 @@ nextchunk->
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
#define checked_request2size(req, sz) \
if (REQUEST_OUT_OF_RANGE(req)) { \
- errno = ENOMEM; \
+ __set_errno(ENOMEM); \
return 0; \
} \
(sz) = request2size(req);
diff --git a/libc/stdlib/setenv.c b/libc/stdlib/setenv.c
index 00e3f3d..ecc3025 100644
--- a/libc/stdlib/setenv.c
+++ b/libc/stdlib/setenv.c
@@ -41,7 +41,7 @@ static char **last_environ;
to reuse values once generated for a `setenv' call since we can never
free the strings. [in uclibc, we do not] */
static int __add_to_environ(const char *name, const char *value,
- int replace)
+ int replace)
{
register char **ep;
register size_t size;
@@ -76,7 +76,7 @@ static int __add_to_environ(const char *name, const char *value,
/* We allocated this space; we can extend it. */
new_environ = realloc(last_environ, (size + 2) * sizeof(char *));
if (new_environ == NULL) {
- __set_errno(ENOMEM);
+ /* __set_errno(ENOMEM); */
goto DONE;
}
if (__environ != last_environ) {
@@ -97,7 +97,7 @@ static int __add_to_environ(const char *name, const char *value,
var_val = malloc(namelen + 1 + vallen);
if (var_val == NULL) {
- __set_errno(ENOMEM);
+ /* __set_errno(ENOMEM); */
goto DONE;
}
memcpy(var_val, name, namelen);
@@ -116,6 +116,11 @@ static int __add_to_environ(const char *name, const char *value,
int setenv(const char *name, const char *value, int replace)
{
+ if (name == NULL || *name == '\0' || strchr (name, '=') != NULL) {
+ __set_errno(EINVAL);
+ return -1;
+ }
+
/* NB: setenv("VAR", NULL, 1) inserts "VAR=" string */
return __add_to_environ(name, value ? value : "", replace);
}
diff --git a/libc/stdlib/unix_grantpt.c b/libc/stdlib/unix_grantpt.c
index 5dbb7f5..66c18c0 100644
--- a/libc/stdlib/unix_grantpt.c
+++ b/libc/stdlib/unix_grantpt.c
@@ -68,7 +68,7 @@ pts_name (int fd, char **pts, size_t buf_len)
if (! new_buf)
{
rv = -1;
- errno = ENOMEM;
+ /* __set_errno(ENOMEM); */
break;
}
buf = new_buf;
diff --git a/libc/string/_collate.c b/libc/string/_collate.c
index 2ebfb93..93501b8 100644
--- a/libc/string/_collate.c
+++ b/libc/string/_collate.c
@@ -367,7 +367,7 @@ static void next_weight(col_state_t *cs, int pass __LOCALE_PARAM )
if (cs->back_buf == cs->ibb) { /* was using internal buffer */
cs->bp = malloc(cs->bb_size + 128);
if (!cs->bp) {
- __set_errno(ENOMEM);
+ /* __set_errno(ENOMEM); */
#ifdef __UCLIBC_MJN3_ONLY__
#warning what to do here?
#endif
@@ -379,7 +379,7 @@ static void next_weight(col_state_t *cs, int pass __LOCALE_PARAM )
} else {
cs->bp = realloc(cs->back_buf, cs->bb_size + 128);
if (!cs->bp) {
- __set_errno(ENOMEM);
+ /* __set_errno(ENOMEM); */
#ifdef __UCLIBC_MJN3_ONLY__
#warning what to do here?
#endif
diff --git a/libc/sysdeps/linux/common/mknod.c b/libc/sysdeps/linux/common/mknod.c
index 416cab6..e0c54e6 100644
--- a/libc/sysdeps/linux/common/mknod.c
+++ b/libc/sysdeps/linux/common/mknod.c
@@ -24,6 +24,10 @@ int mknod(const char *path, mode_t mode, dev_t dev)
/* We must convert the value to dev_t type used by the kernel. */
k_dev = (dev) & ((1ULL << 32) - 1);
+ if (k_dev != dev) {
+ __set_errno(EINVAL);
+ return -1;
+ }
return INLINE_SYSCALL(mknod, 3, path, mode, (unsigned int)k_dev);
}
#endif
diff --git a/libc/sysdeps/linux/common/sync_file_range.c
b/libc/sysdeps/linux/common/sync_file_range.c
index 8d4ed92..6cd7e94 100644
--- a/libc/sysdeps/linux/common/sync_file_range.c
+++ b/libc/sysdeps/linux/common/sync_file_range.c
@@ -23,10 +23,13 @@
static int __NC(sync_file_range)(int fd, off64_t offset, off64_t nbytes, unsigned int
flags)
{
# if defined __powerpc__ && __WORDSIZE == 64
- return INLINE_SYSCALL(sync_file_range, 4, fd, offset, nbytes, flags);
+ return INLINE_SYSCALL(sync_file_range, 4, fd, flags, offset, nbytes);
# elif defined __mips__ && _MIPS_SIM == _ABIO32
return INLINE_SYSCALL(sync_file_range, 7, fd, 0,
OFF64_HI_LO(offset), OFF64_HI_LO(nbytes), flags);
+# elif defined __NR_sync_file_range2
+ return INLINE_SYSCALL(sync_file_range, 6, fd, flags,
+ OFF64_HI_LO(offset), OFF64_HI_LO(nbytes));
# else
return INLINE_SYSCALL(sync_file_range, 6, fd,
OFF64_HI_LO(offset), OFF64_HI_LO(nbytes), flags);
diff --git a/libcrypt/crypt.c b/libcrypt/crypt.c
index f79c9fe..10061a0 100644
--- a/libcrypt/crypt.c
+++ b/libcrypt/crypt.c
@@ -14,17 +14,21 @@ char *crypt(const char *key, const char *salt)
const unsigned char *ukey = (const unsigned char *)key;
const unsigned char *usalt = (const unsigned char *)salt;
- if (salt[0] == '$' && salt[2] == '$') {
- if (*++salt == '1')
- return __md5_crypt(ukey, usalt);
+ if (salt[0] == '$') {
+ if (salt[1] && salt[2] == '$') { /* no blowfish '2X' here ATM
*/
+ if (*++salt == '1')
+ return __md5_crypt(ukey, usalt);
#ifdef __UCLIBC_HAS_SHA256_CRYPT_IMPL__
- else if (*salt == '5')
- return __sha256_crypt(ukey, usalt);
+ else if (*salt == '5')
+ return __sha256_crypt(ukey, usalt);
#endif
#ifdef __UCLIBC_HAS_SHA512_CRYPT_IMPL__
- else if (*salt == '6')
- return __sha512_crypt(ukey, usalt);
+ else if (*salt == '6')
+ return __sha512_crypt(ukey, usalt);
#endif
+ }
+ /* __set_errno(EINVAL);*/ /* ENOSYS might be misleading */
+ return NULL;
}
return __des_crypt(ukey, usalt);
}
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/Makefile.arch
b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/Makefile.arch
index 3a32598..0ea0b29 100644
--- a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/Makefile.arch
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/Makefile.arch
@@ -18,3 +18,6 @@ libc_linux_arch_SSRC-OMIT = waitpid.S
# This macro should be alternatively implemented in THUMB
# assembly.
ASFLAGS-pt-vfork.S = -marm
+CFLAGS-OMIT-pt-vfork.S = -mthumb
+ASFLAGS-vfork.S = -marm
+CFLAGS-OMIT-vfork.S = -mthumb
diff --git a/test/nptl/Makefile.in b/test/nptl/Makefile.in
index dd53f91..42a4654 100644
--- a/test/nptl/Makefile.in
+++ b/test/nptl/Makefile.in
@@ -207,7 +207,7 @@ tst-tls5: tst-tls5mod.so
tst-cleanupx4 : tst-cleanup4aux.o
tst-fini1: tst-fini1mod.so
-OPTS_tst-cancel7 = --command ./tst-cancel7
+OPTS_tst-cancel7 = -c ./tst-cancel7
OPTS_tst-mqueue7 = -- ./tst-mqueue7
OPTS_tst-exec4 = ./tst-exec4
diff --git a/test/nptl/tst-cancel7.c b/test/nptl/tst-cancel7.c
index fe543f7..bb9f739 100644
--- a/test/nptl/tst-cancel7.c
+++ b/test/nptl/tst-cancel7.c
@@ -32,7 +32,7 @@ char pidfilename[] = "/tmp/tst-cancel7-XXXXXX";
static void *
tf (void *arg)
{
- const char *args = " --direct --pidfile ";
+ const char *args = " -d -p ";
char *cmd = alloca (strlen (command) + strlen (args)
+ strlen (pidfilename) + 1);
diff --git a/test/nptl/tst-exec4.c b/test/nptl/tst-exec4.c
index b5d290f..1a4b88c 100644
--- a/test/nptl/tst-exec4.c
+++ b/test/nptl/tst-exec4.c
@@ -51,7 +51,7 @@ tf (void *arg)
char **argv = (char **) alloca ((n + 1) * sizeof (char *));
for (n = 0; oldargv[n + 1] != NULL; ++n)
argv[n] = oldargv[n + 1];
- argv[n++] = (char *) "--direct";
+ argv[n++] = (char *) "-d";
argv[n] = NULL;
execv (argv[0], argv);
diff --git a/test/nptl/tst-mqueue7.c b/test/nptl/tst-mqueue7.c
index 01d7cd7..12c6d9a 100644
--- a/test/nptl/tst-mqueue7.c
+++ b/test/nptl/tst-mqueue7.c
@@ -90,14 +90,14 @@ do_test (int argc, char **argv)
return 1;
}
- char after_exec_arg[sizeof "--after-exec=0x" + sizeof (long) * 3];
+ char after_exec_arg[sizeof "-a=0x" + sizeof (long) * 3];
snprintf (after_exec_arg, sizeof (after_exec_arg),
- "--after-exec=0x%lx", (long) q);
+ "-a=0x%lx", (long) q);
const char *newargv[argc + 2];
for (int i = 1; i < argc; ++i)
newargv[i - 1] = argv[i];
- newargv[argc - 1] = "--direct";
+ newargv[argc - 1] = "-d";
newargv[argc] = after_exec_arg;
newargv[argc + 1] = NULL;
hooks/post-receive
--
uClibc-ng - small C library for embedded systems