This test was changed from using fork to vfork by:
https://cgit.uclibc-ng.org/cgi/cgit/uclibc-ng.git/commit/?id=822e4896c1072b…
This change was wrong because man page says the child of vfork() must ONLY do either:
- a call to one of exec(2)
- a call to _exit(2)
- get killed by a signal
BUT the test case does:
- a call to kill
- and also a call to exit(3) and not _exit(2)
This test produces a double free() causing assert in free because this is called several times:
https://elixir.bootlin.com/uclibc-ng/latest/source/libc/stdlib/_atexit.c#L2…
So, it seems wrong both in theory (according to man page) and in fact in practice (assert in free).
Here I propose to get back to testing fork(), which is the original test case from:
https://sourceware.org/bugzilla/show_bug.cgi?id=838
And to just "PASS" on no-mmu systems.
For the record, here is the assert call stack:
FAIL tst-mallocfork got 1 expected 0
./tst-mallocfork: libc/stdlib/malloc-standard/malloc.c: 149: __do_check_inuse_chunk: Assertion `((((mchunkptr)(((char*)(p))+((p)->size & ~0x1)))->size) & 0x1)' failed.
Didn't expect signal from child: got `Aborted'
0 free (mem=0x3a010) at libc/stdlib/malloc-standard/free.c:285
1 0x00000000000220c4 in __exit_handler (status=1) at libc/stdlib/_atexit.c:270
2 0x000000000001afa0 in __GI_exit (rv=1) at libc/stdlib/_atexit.c:301
3 0x0000000000010dcc in main (argc=1, argv=0x7ffffffd98) at ../test-skeleton.c:405
4 0x000000000001cba8 in __uClibc_main (main=0x10988 <main>, argc=1, argv=0x7ffffffd98, app_init=0x100e8, app_fini=0x23918 <_fini>, rtld_fini=0x0 <k1c_start>, stack_end=0x7ffffffd90) at libc/misc/internals/__uClibc_main.c:512
5 0x00000000000eb8b8 in ?? ()
Signed-off-by: Yann Sionneau <ysionneau(a)kalray.eu>
---
test/malloc/tst-mallocfork.c | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/test/malloc/tst-mallocfork.c b/test/malloc/tst-mallocfork.c
index edd9c39..e9e5133 100644
--- a/test/malloc/tst-mallocfork.c
+++ b/test/malloc/tst-mallocfork.c
@@ -9,10 +9,12 @@
#include <sys/wait.h>
#include "../test-skeleton.h"
+#ifdef __ARCH_USE_MMU__
+
static void
sig_handler (int signum)
{
- pid_t child = vfork ();
+ pid_t child = fork ();
if (child == 0)
exit (0);
TEMP_FAILURE_RETRY (waitpid (child, NULL, 0));
@@ -35,7 +37,7 @@ do_test (void)
}
/* Create a child that sends the signal to be caught. */
- pid_t child = vfork ();
+ pid_t child = fork ();
if (child == 0)
{
if (kill (parent, SIGALRM) == -1)
@@ -48,5 +50,16 @@ do_test (void)
return 0;
}
+#else
+
+static int
+do_test (void)
+{
+ printf("Skipping test on non-mmu host!\n");
+ return EXIT_SUCCESS;
+}
+
+#endif
+
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
--
1.8.3.1
For ARCH where shared lib are not supported:
- SHARED is not set (!SHARED is true)
- __ARCH_HAS_NO_LDSO__ is set
so code inside #if !defined __ARCH_HAS_NO_LDSO__ && !defined SHARED
is compiled-out.
But without a call do _dl_aux_init(), _dl_phdr stays NULL and
__libc_setup_tls won't be able to allocate memory for the in-executable TLS
and also won't be able to load the initimage from ELF TLS segment.
This results in segfault when doing things like "errno = 0" like
in tst-cancel15.c for instance in uClibc-ng testsuite.
Signed-off-by: Yann Sionneau <ysionneau(a)kalray.eu>
---
libc/misc/internals/__uClibc_main.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libc/misc/internals/__uClibc_main.c b/libc/misc/internals/__uClibc_main.c
index 849bca8..affa0ce 100644
--- a/libc/misc/internals/__uClibc_main.c
+++ b/libc/misc/internals/__uClibc_main.c
@@ -370,7 +370,7 @@ void __uClibc_main(int (*main)(int, char **, char **), int argc,
char **argv, void (*app_init)(void), void (*app_fini)(void),
void (*rtld_fini)(void), void *stack_end attribute_unused)
{
-#if !defined __ARCH_HAS_NO_LDSO__ && !defined SHARED
+#ifndef SHARED
unsigned long *aux_dat;
ElfW(auxv_t) auxvt[AT_EGID + 1];
#endif
@@ -396,7 +396,7 @@ void __uClibc_main(int (*main)(int, char **, char **), int argc,
__environ = &argv[argc];
}
-#if !defined __ARCH_HAS_NO_LDSO__ && !defined SHARED
+#ifndef SHARED
/* Pull stuff from the ELF header when possible */
memset(auxvt, 0x00, sizeof(auxvt));
aux_dat = (unsigned long*)__environ;
--
1.8.3.1
This patch seems needed in builds where
- SHARED is not defined (no shared lib support)
- and USE_TLS is set
Without this patch, static_dtv is free'ed.
See the following backtrace:
0 __do_check_chunk (p=0x52638 <fork_handler_pool+2296>) at libc/stdlib/malloc-standard/malloc.c:80
1 0x0000000000017fa0 in __do_check_inuse_chunk (p=0x52638 <fork_handler_pool+2296>) at libc/stdlib/malloc-standard/malloc.c:143
2 0x0000000000017354 in free (mem=0x52648 <static_dtv>) at libc/stdlib/malloc-standard/free.c:293
3 0x000000000002d5b0 in _dl_deallocate_tls (tcb=0x58690, dealloc_tcb=false) at libpthread/nptl/sysdeps/generic/dl-tls.c:588
4 0x0000000000021c0c in __deallocate_stack (pd=0x58000) at libpthread/nptl/allocatestack.c:717
5 0x0000000000024408 in __free_tcb (pd=0x58000) at libpthread/nptl/pthread_create.c:217
6 0x00000000000200ac in pthread_join (threadid=360448, thread_return=0x0 <k1c_start>) at libpthread/nptl/pthread_join.c:109
7 0x0000000000010354 in tf (a=0x58000) at tst-basic3.c:42
8 0x00000000000247c8 in start_thread (arg=0x4000200960) at libpthread/nptl/pthread_create.c:285
9 0x0000000000026560 in ?? ()
This backtrace is obtained while debugging tst-basic3 from the uclibc-ng nptl testsuite.
It aborts because of the assert in malloc:
https://elixir.bootlin.com/uclibc-ng/v1.0.31/source/libc/stdlib/malloc-stan…
Signed-off-by: Yann Sionneau <ysionneau(a)kalray.eu>
---
libpthread/nptl/sysdeps/generic/dl-tls.c | 5 +++++
libpthread/nptl/sysdeps/generic/libc-tls.c | 5 ++++-
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/libpthread/nptl/sysdeps/generic/dl-tls.c b/libpthread/nptl/sysdeps/generic/dl-tls.c
index 989e587a2..7d25e4706 100644
--- a/libpthread/nptl/sysdeps/generic/dl-tls.c
+++ b/libpthread/nptl/sysdeps/generic/dl-tls.c
@@ -48,6 +48,9 @@
/* Value used for dtv entries for which the allocation is delayed. */
# define TLS_DTV_UNALLOCATED ((void *) -1l)
+#ifndef SHARED
+extern dtv_t static_dtv;
+#endif
/* Out-of-memory handler. */
# ifdef SHARED
@@ -584,6 +587,8 @@ _dl_deallocate_tls (void *tcb, bool dealloc_tcb)
/* The array starts with dtv[-1]. */
#ifdef SHARED
if (dtv != GL(dl_initial_dtv))
+#else
+ if ((dtv - 1) != &static_dtv)
#endif
free (dtv - 1);
diff --git a/libpthread/nptl/sysdeps/generic/libc-tls.c b/libpthread/nptl/sysdeps/generic/libc-tls.c
index a6df4cdc4..d746c9a38 100644
--- a/libpthread/nptl/sysdeps/generic/libc-tls.c
+++ b/libpthread/nptl/sysdeps/generic/libc-tls.c
@@ -42,7 +42,10 @@ extern size_t _dl_phnum;
extern int __tdata_start;
#endif
-static dtv_t static_dtv[2 + TLS_SLOTINFO_SURPLUS];
+#ifdef SHARED
+static
+#endif
+dtv_t static_dtv[2 + TLS_SLOTINFO_SURPLUS];
static struct
--
2.21.0
This patch seems needed in builds where
- SHARED is not defined (no shared lib support)
- and USE_TLS is set
Without this patch, static_dtv is free'ed.
See the following backtrace:
This backtrace is obtained while debugging tst-basic3 from the uclibc-ng nptl testsuite.
It aborts because of the assert in malloc:
https://elixir.bootlin.com/uclibc-ng/v1.0.31/source/libc/stdlib/malloc-stan…
Signed-off-by: Yann Sionneau <ysionneau(a)kalray.eu>
---
libpthread/nptl/sysdeps/generic/dl-tls.c | 5 +++++
libpthread/nptl/sysdeps/generic/libc-tls.c | 5 ++++-
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/libpthread/nptl/sysdeps/generic/dl-tls.c b/libpthread/nptl/sysdeps/generic/dl-tls.c
index 989e587a2..7d25e4706 100644
--- a/libpthread/nptl/sysdeps/generic/dl-tls.c
+++ b/libpthread/nptl/sysdeps/generic/dl-tls.c
@@ -48,6 +48,9 @@
/* Value used for dtv entries for which the allocation is delayed. */
# define TLS_DTV_UNALLOCATED ((void *) -1l)
+#ifndef SHARED
+extern dtv_t static_dtv;
+#endif
/* Out-of-memory handler. */
# ifdef SHARED
@@ -584,6 +587,8 @@ _dl_deallocate_tls (void *tcb, bool dealloc_tcb)
/* The array starts with dtv[-1]. */
#ifdef SHARED
if (dtv != GL(dl_initial_dtv))
+#else
+ if ((dtv - 1) != &static_dtv)
#endif
free (dtv - 1);
diff --git a/libpthread/nptl/sysdeps/generic/libc-tls.c b/libpthread/nptl/sysdeps/generic/libc-tls.c
index a6df4cdc4..d746c9a38 100644
--- a/libpthread/nptl/sysdeps/generic/libc-tls.c
+++ b/libpthread/nptl/sysdeps/generic/libc-tls.c
@@ -42,7 +42,10 @@ extern size_t _dl_phnum;
extern int __tdata_start;
#endif
-static dtv_t static_dtv[2 + TLS_SLOTINFO_SURPLUS];
+#ifdef SHARED
+static
+#endif
+dtv_t static_dtv[2 + TLS_SLOTINFO_SURPLUS];
static struct
--
2.21.0
After building uclibc-1.0.31 with AddressSanitizer enabled (gcc7.3 and
8.2), asan complains at runtime that it's not the first library in the
so-list.
With a breakpoint on AsanCheckDynamicRTPrereqs which calls
__dl_iterate_phdr, I see the first module that uClibc returns has
info->libname = "/home/user/myapp", while on glibc-2.27, libname is an
empty string. ASAN depends on seeing this empty string.
Should __dl_iterate_phdr return an empty string here, or is there an
alternative to get asan-enabled uClibc toolchains ?
Thanks.
On 3/14/19 3:01 AM, Petr Vorel wrote:
> Hi Vineet,
>
>> libcpuset.c relies on FTS which is not enabled by default on uClibc.
>> Instead of needing to reconfigure, rebuild uClibc lets disable this test
>> for uClibc
> Which uClibc version are you using?
> Both uClibc and uclibc-ng has it [1] since 2011, version v0.9.32, in commit
> a4aa01c12 ("Added fts support for traversing UNIX file hierarchies.")
Right I'm using bleeding edge as well, and do have the header in sources, its just
not configured/enabled by default hence not available in installation.
> It's actually MUSL, what is missing it [2]. Although there is some
> implementation [3], we should skip it for musl. But the clearest way is really
> to check presence of <fts.h>, that's fix it for all libc.
Spot on, that is indeed the best/ideal way of doing it. Do you know if such a
mechanism already exists in LTP. If you point me to an example I can respin the
patch accordingly.
Thx,
-Vineet
Hi!
I've been having troubles loading a gstreamer plugin for Raspberry Pi
(libgstrpicamsrc.so) on Buildroot with Uclibc-ng 1.0.30.
It seems that some circualr dependencies are preventing the plugin from
loading (specifically libmmal_core.so and libmmal_util.so).
I noticed that GStreamer loads its plugins using RTLD_NOW, but
shouldn't it still be able to handle circular dependencies? The plugin
does load correctly on glibc.
I'm attaching the output of the load using LD_DEBUG. There seem to be a
lot of messages regarding circular dependencies.
There is also a deeper analysis of the issue and how I eventually
worked around it in here:
https://wiki.avner.us/doku.php?id=embedded-web-interaction:uclibc-ng-proble…
Would appreciate any insights,
Thank you!
/Avner
Hi,
Current version of uClibc-ng has issue in open_memstream() function.
If the cookie variable is NULL (due malloc() fail) then null pointer is
dereferenced after if block.
The attached patch fixes this issue.
--
Best regards,
Eugene
Hi,
I've noticed that uClibc-ng now allows the FDPIC ELF for ARM: one of the
crosstool-NG samples that configures a toolchain for ARM with no MMU now
defaults to FDPIC rather than flat format. The problem is, though, it
then fails - because GCC complains that:
armv6-nommu-linux-uclibcgnueabi-gcc: error: unrecognized command line
option '-mfdpic'; did you mean '-fpic'?
I'll fix the default in crosstool-NG, but what intrigues me is that the
-mfdpic option isn't listed in GCC manual as one of the supported
options for ARM (it is only listed in FRV's options). How is this
configuration built?
Regards,
Alexey.