[PATCH] ldso: fix dlsym hang when reloading DSOs
It can happen under certain cases that the DSO had refcount 0, but was already loaded. (NODELETE flag is set, or it is pulled in via both NEEDED dependency and explicit dlopen()). In these cases we must not re-add the DSO to the global symbol scope as it is already there. Or we end up corrupting the linked list and further dlsym lookups will hang. Signed-off-by: Timo Teräs timo.te...@iki.fi --- ldso/libdl/libdl.c | 18 +- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c index c451b63..c901512 100644 --- a/ldso/libdl/libdl.c +++ b/ldso/libdl/libdl.c @@ -543,15 +543,23 @@ static void *do_dlopen(const char *libname, int flag, ElfW(Addr) from) #ifdef SHARED /* -* Get the tail of the list. * In the static case doesn't need to extend the global scope, it is * ready to be used as it is, because _dl_loaded_modules already points * to the dlopened library. +* +* Extend the global scope by adding the local scope of the dlopened DSO. +* But only if it's not there. It can happen under certain cases that the +* DSO had refcount = 0, but was already loaded. (NODELETE flag is set, or +* it is pulled in via both NEEDED dependency and explicit dlopen()). */ - for (ls = _dl_loaded_modules-symbol_scope; ls ls-next; ls = ls-next); - - /* Extend the global scope by adding the local scope of the dlopened DSO. */ - ls-next = dyn_chain-dyn-symbol_scope; + for (ls = _dl_loaded_modules-symbol_scope; ; ls = ls-next) { + if (ls == dyn_chain-dyn-symbol_scope) + break; + if (ls-next == NULL) { + ls-next = dyn_chain-dyn-symbol_scope; + break; + } + } #endif #ifdef __mips__ /* -- 1.8.3.1 ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
[PATCH] dl: fix dlsym lookups with RTLD_NEXT
The current code for dlsym() when invoked with RTLD_NEXT lookup searches for the module where it's being called from, and executes the _dl_find_hash only for the next module in the chain. However, if the looked symbol is not there, the rest of the modules are not checked. Generally this is not a problem as symbols are merged for the parent modules; so this affects only RTLD_NEXT. This patch adds a loop iterating through all the following modules. Signed-off-by: Timo Teräs timo.te...@iki.fi Reviewed-by: Filippo ARCIDIACONO filippo.arcidiac...@st.com Tested-by: Florian Fainelli flor...@openwrt.org --- ldso/libdl/libdl.c | 10 -- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c index af632dd..95a0650 100644 --- a/ldso/libdl/libdl.c +++ b/ldso/libdl/libdl.c @@ -671,7 +671,7 @@ static void *do_dlsym(void *vhandle, const char *name, void *caller_address) { struct elf_resolve *tpnt, *tfrom; struct dyn_elf *handle; - ElfW(Addr) from; + ElfW(Addr) from = 0; struct dyn_elf *rpnt; void *ret; struct symbol_ref sym_ref = { NULL, NULL }; @@ -729,7 +729,13 @@ static void *do_dlsym(void *vhandle, const char *name, void *caller_address) tpnt = NULL; if (handle == _dl_symbol_tables) tpnt = handle-dyn; /* Only search RTLD_GLOBAL objs if global object */ - ret = _dl_find_hash(name2, handle-dyn-symbol_scope, tpnt, ELF_RTYPE_CLASS_DLSYM, sym_ref); + + do { + ret = _dl_find_hash(name2, handle-dyn-symbol_scope, tpnt, ELF_RTYPE_CLASS_DLSYM, sym_ref); + if (ret != NULL) + break; + handle = handle-next; + } while (from handle); #if defined(USE_TLS) USE_TLS defined SHARED if (sym_ref.sym (ELF_ST_TYPE(sym_ref.sym-st_info) == STT_TLS) (sym_ref.tpnt)) { -- 1.8.1 ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
[PATCH 2/3] libc/x86: add dwarf-2 cfi unwinding information to clone()
Copied mostly from glibc. Adds proper information for unwinding application created threads. Without the proper unwind information the stack trace is considered as incomplete or corrupted after clone(). This adds the proper end-of-stack markers and thus removes gdb errors. Signed-off-by: Timo Teräs timo.te...@iki.fi --- libc/sysdeps/linux/i386/clone.S | 17 + 1 files changed, 17 insertions(+), 0 deletions(-) diff --git a/libc/sysdeps/linux/i386/clone.S b/libc/sysdeps/linux/i386/clone.S index a7de3fe..cf6cd35 100644 --- a/libc/sysdeps/linux/i386/clone.S +++ b/libc/sysdeps/linux/i386/clone.S @@ -25,6 +25,7 @@ #define _ERRNO_H 1 #include bits/errno.h +#include sysdep.h #include sys/syscall.h /* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg, @@ -45,6 +46,7 @@ .global clone .type clone,%function clone: + cfi_startproc; /* Sanity check arguments. */ movl$-EINVAL,%eax @@ -86,17 +88,28 @@ clone: /* Do the system call */ pushl %ebx + cfi_adjust_cfa_offset (4) pushl %esi + cfi_adjust_cfa_offset (4) pushl %edi + cfi_adjust_cfa_offset (4) + movlTLS+12(%esp),%esi + cfi_rel_offset (esi, 4) movlPTID+12(%esp),%edx movlFLAGS+12(%esp),%ebx + cfi_rel_offset (ebx, 8) movlCTID+12(%esp),%edi + cfi_rel_offset (edi, 0) movl$__NR_clone,%eax #ifdef RESET_PID /* Remember the flag value. */ movl%ebx, (%ecx) #endif + /* End FDE now, because in the child the unwind info will be + wrong. */ + cfi_endproc + int $0x80 popl%edi popl%esi @@ -108,6 +121,9 @@ clone: ret .Lthread_start: + cfi_startproc; + /* Clearing frame pointer is insufficient, use CFI. */ + cfi_undefined (eip); /* Note: %esi is zero. */ movl%esi,%ebp /* terminate the stack frame */ call*%ebx @@ -120,6 +136,7 @@ clone: movl%eax, %ebx movl$__NR_exit, %eax int $0x80 + cfi_endproc; /* Need to indirect jump to syscall error * or we end up with TEXTREL's -- 1.7.7.1 ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
[PATCH 1/3] libc/x86: add dwarf-2 cfi unwinding information to syscalls
Fixes unwinding of stack traces across system calls. Thus debuggers can show proper backtrace when inside a syscall. Additionally, this fixes a race condition: if a signal happens while inside syscall, and the signal handler aborts the thread, we would have been unable to unwind the stack and run the proper error handler. This patch also removes the xchg ebx, register trickery - it's very hard to add proper CFI info within macroes. It apparently never worked 100% reliably, and the speed gain is probably insignificant on modern processors. Signed-off-by: Timo Teräs timo.te...@iki.fi --- libc/sysdeps/linux/i386/bits/syscalls.h | 82 +++ 1 files changed, 7 insertions(+), 75 deletions(-) diff --git a/libc/sysdeps/linux/i386/bits/syscalls.h b/libc/sysdeps/linux/i386/bits/syscalls.h index eeafb3a..1f60a44 100644 --- a/libc/sysdeps/linux/i386/bits/syscalls.h +++ b/libc/sysdeps/linux/i386/bits/syscalls.h @@ -13,6 +13,7 @@ #ifndef __ASSEMBLER__ #include errno.h +#include common/sysdep.h #define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ ({ \ @@ -31,90 +32,21 @@ #if 1 /* defined __PIC__ || defined __pic__ */ -/* This code avoids pushing/popping ebx as much as possible. - * I think the main reason was that older GCCs had problems - * with proper saving/restoring of ebx if b constraint was used, - * which was breaking -fPIC code really badly. - * At least gcc 4.2.x seems to not need these tricks anymore, - * but this code is still useful because it often avoids - * using stack for saving ebx. - * Keeping it unconditionally enabled for now. - */ - -/* We need some help from the assembler to generate optimal code. - * We define some macros here which later will be used. */ -/* gcc=4.6 with LTO need the same guards as IMA (a.k.a --combine) did. - * See gcc.gnu.org/PR47577 */ -/* FIXME: drop these b* macros! */ - -__asm__ ( -#if defined __DOMULTI__ || __GNUC_PREREQ (4, 6) - /* Protect against asm macro redefinition (happens in __DOMULTI__ mode). -* Unfortunately, it ends up visible in .o files. */ - .ifndef _BITS_SYSCALLS_ASM\n\t - .set _BITS_SYSCALLS_ASM,1\n\t -#endif - .L__X'%ebx = 1\n\t - .L__X'%ecx = 2\n\t - .L__X'%edx = 2\n\t - .L__X'%eax = 3\n\t - .L__X'%esi = 3\n\t - .L__X'%edi = 3\n\t - .L__X'%ebp = 3\n\t - .L__X'%esp = 3\n\t - - /* Loading param #1 (ebx) is done by loading it into -* another register, and then performing bpushl+bmovl, -* since we must preserve ebx */ - - .macro bpushl name reg\n\t - .if 1 - \\name\n\t/* if reg!=ebx... */ - .if 2 - \\name\n\t/* if reg can't be clobbered... */ - pushl %ebx\n\t/* save ebx on stack */ - .else\n\t - xchgl \\reg, %ebx\n\t /* else save ebx in reg, and load reg to ebx */ - .endif\n\t - .endif\n\t - .endm\n\t - - .macro bmovl name reg\n\t - .if 1 - \\name\n\t - .if 2 - \\name\n\t/* if reg can't be clobbered... */ - movl \\reg, %ebx\n\t /* load reg to ebx */ - .endif\n\t - .endif\n\t - .endm\n\t - - .macro bpopl name reg\n\t - .if 1 - \\name\n\t - .if 2 - \\name\n\t/* if reg can't be clobbered... */ - popl %ebx\n\t /* restore ebx from stack */ - .else\n\t - xchgl \\reg, %ebx\n\t /* else restore ebx from reg */ - .endif\n\t - .endif\n\t - .endm\n\t - -#if defined __DOMULTI__ || __GNUC_PREREQ (4, 6) - .endif\n\t /* _BITS_SYSCALLS_ASM */ -#endif -); - #define LOADARGS_0 -#define LOADARGS_1 bpushl .L__X'%k2, %k2\n\t bmovl .L__X'%k2, %k2\n\t +#define LOADARGS_1 push %%ebx\n\t CFI_ADJUST_CFA_OFFSET(4) \n\t CFI_REL_OFFSET(ebx, 0) \n\t movl %k2, %%ebx\n\t #define LOADARGS_2 LOADARGS_1 #define LOADARGS_3 LOADARGS_1 #define LOADARGS_4 LOADARGS_1 #define LOADARGS_5 LOADARGS_1 -#define LOADARGS_6 LOADARGS_1 push %%ebp\n\t movl %7, %%ebp\n\t +#define LOADARGS_6 LOADARGS_1 push %%ebp\n\t CFI_ADJUST_CFA_OFFSET(4) \n\t CFI_REL_OFFSET(ebp, 0) \n\t movl %7, %%ebp\n\t #define RESTOREARGS_0 -#define RESTOREARGS_1 bpopl .L__X'%k2, %k2\n\t +#define RESTOREARGS_1 pop %%ebx\n\t CFI_ADJUST_CFA_OFFSET(-4) \n\t CFI_RESTORE(ebx) \n\t RESTOREARGS_0 #define RESTOREARGS_2 RESTOREARGS_1 #define RESTOREARGS_3 RESTOREARGS_1 #define RESTOREARGS_4 RESTOREARGS_1 #define RESTOREARGS_5 RESTOREARGS_1 -#define RESTOREARGS_6 pop %%ebp\n\t RESTOREARGS_1 +#define RESTOREARGS_6 pop %%ebp\n\t CFI_ADJUST_CFA_OFFSET(-4) \n\t CFI_RESTORE(ebp) \n\t RESTOREARGS_1 #define ASMFMT_0() /* acdSD constraint would work too, but SD would use esi/edi and cause @@ -162,7 +94,7 @@ __asm__ ( #define LOADARGS_3 #define LOADARGS_4 #define LOADARGS_5 -#define LOADARGS_6 push %%ebp\n\t movl %7, %%ebp\n\t +#define LOADARGS_6 push %%ebp\n\t CFI_ADJUST_CFA_OFFSET(4) \n\t CFI_REL_OFFSET(ebp, 0) \n\t movl %7, %%ebp\n\t #define RESTOREARGS_0 #define RESTOREARGS_1
[PATCH 3/3] libc/x86: pad signal return code on isolated area
If dwarf-2 cfi info was found for signal return code (which seems to happen if it's located right after a valid function), it will not be recognized as signal trampoline (gcc unwinder and gdb check first cfi info, and only if it does not exists it compares the exact opcode sequence to see if we are at signal return code block). This fixes a real crash if thread is cancelled and the cancellation handler fails to detect the signal return frame (common case if pthread_cancel is used as threads are often cancelled by sending a signal to them). Signed-off-by: Timo Teräs timo.te...@iki.fi --- libc/sysdeps/linux/i386/sigaction.c |4 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/libc/sysdeps/linux/i386/sigaction.c b/libc/sysdeps/linux/i386/sigaction.c index de0c75d..f9af3f7 100644 --- a/libc/sysdeps/linux/i386/sigaction.c +++ b/libc/sysdeps/linux/i386/sigaction.c @@ -112,6 +112,9 @@ libc_hidden_weak(sigaction) #define RESTORE2(name, syscall) \ __asm__( \ .text\n \ + .align 8\n\ + nop\n \ + .align 16\n \ __ #name :\n\ movl$ #syscall , %eax\n \ int $0x80\n\ @@ -128,6 +131,7 @@ RESTORE(restore_rt, __NR_rt_sigreturn) # define RESTORE2(name, syscall) \ __asm__ ( \ .text\n \ + .align 8\n\ __ #name :\n\ popl%eax\n \ movl$ #syscall , %eax\n \ -- 1.7.7.1 ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: [PATCH] libc/x86: fix stack unwinding and backtrace information
On 11/10/2011 10:21 AM, Timo Teräs wrote: When compiled without framepointer, the DWARF-2 CFI data is required for proper stack unwinding. This patch adds the CFI information to: * syscalls (so we get proper backtrace even for release builds) * new thread stub function (so the backtrace is clean for user created threads) Also pads the signal return trampolines separate from other functions. If CFI info was found for signal return code (which seems to happen if it's located right next a valid function), it will not be recognized as signal trampoline (gcc unwinder and gdb check first CFI info, and only if it does not exists it compares the exact opcode sequence to see if we are at signal return code block). This fixes a real crash if thread is cancelled and the cancellation handler fails to detect the signal return frame. Signed-off-by: Timo Teräs timo.te...@iki.fi @@ -71,6 +72,8 @@ __asm__ ( .if 1 - \\name\n\t/* if reg!=ebx... */ .if 2 - \\name\n\t/* if reg can't be clobbered... */ pushl %ebx\n\t/* save ebx on stack */ + CFI_ADJUST_CFA_OFFSET(4) \n\t + CFI_REL_OFFSET(ebx, 0) \n\t .else\n\t xchgl \\reg, %ebx\n\t /* else save ebx in reg, and load reg to ebx */ .endif\n\t @@ -89,6 +92,8 @@ __asm__ ( .if 1 - \\name\n\t .if 2 - \\name\n\t/* if reg can't be clobbered... */ popl %ebx\n\t /* restore ebx from stack */ + CFI_ADJUST_CFA_OFFSET(-4) \n\t + CFI_RESTORE(ebx) \n\t .else\n\t xchgl \\reg, %ebx\n\t /* else restore ebx from reg */ .endif\n\t Actually, this bit does not work. The problems to be that the CFI_ADJUST_CFA_OFFSET() stuff emits assembler directives, which get interpreted regardless of the .if block we are at. Or something like that. In any case, some syscalls would not get the info right. I'm now wondering if actually need the whole bpush/bpop/bmov hackery (even the comment suggests to remove it). For CFI generation, it'd be a lot better if we could just do push/pop of ebx always (for PIC builds) and leave it as-is for non-PIC builds. I'll send a corrected patch doing that soon. ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: [PATCH] libc/x86: fix stack unwinding and backtrace information
On 11/11/2011 03:31 PM, Peter Mazinger wrote: Original-Nachricht Datum: Fri, 11 Nov 2011 13:30:27 +0200 Von: Timo Teräs timo.te...@iki.fi An: CC: uclibc@uclibc.org Betreff: Re: [PATCH] libc/x86: fix stack unwinding and backtrace information On 11/10/2011 10:21 AM, Timo Teräs wrote: When compiled without framepointer, the DWARF-2 CFI data is required for proper stack unwinding. This patch adds the CFI information to: * syscalls (so we get proper backtrace even for release builds) * new thread stub function (so the backtrace is clean for user created threads) Also pads the signal return trampolines separate from other functions. If CFI info was found for signal return code (which seems to happen if it's located right next a valid function), it will not be recognized as signal trampoline (gcc unwinder and gdb check first CFI info, and only if it does not exists it compares the exact opcode sequence to see if we are at signal return code block). This fixes a real crash if thread is cancelled and the cancellation handler fails to detect the signal return frame. Signed-off-by: Timo Teräs timo.te...@iki.fi @@ -71,6 +72,8 @@ __asm__ ( .if 1 - \\name\n\t/* if reg!=ebx... */ .if 2 - \\name\n\t/* if reg can't be clobbered... */ pushl %ebx\n\t/* save ebx on stack */ + CFI_ADJUST_CFA_OFFSET(4) \n\t + CFI_REL_OFFSET(ebx, 0) \n\t .else\n\t xchgl \\reg, %ebx\n\t /* else save ebx in reg, and load reg to ebx */ .endif\n\t @@ -89,6 +92,8 @@ __asm__ ( .if 1 - \\name\n\t .if 2 - \\name\n\t/* if reg can't be clobbered... */ popl %ebx\n\t /* restore ebx from stack */ + CFI_ADJUST_CFA_OFFSET(-4) \n\t + CFI_RESTORE(ebx) \n\t .else\n\t xchgl \\reg, %ebx\n\t /* else restore ebx from reg */ .endif\n\t IIRC the two if's are anyway a bit wrong (looked into it when I added DOMULTI config option), I wanted some time ago to convert these to the current usage in glibc (where for less arguments the content is only exchanged), the only stopper was how to implement _syscall6 for PIC code I do not know how much the way of this implementation will influence the speed of execution, I can remember someone saying, that it is negligible. If so, the way the _syscall5 is done in glibc would be a way to implement _syscall6 as well. Syscalls are *slow*. Whether we do push/pop or 2*xchg sounds very insignificant to me. My feeling is that on modern CPUs the speed impact goes exactly the opposite way. I think *much* greater performance improvement can be achieved if we implement SYSENTER support instead of the currently hardcoded int 0x80. I haven't done any benchmarks about these though... - Timo ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
[PATCHv2] libc/x86: fix stack unwinding and backtrace information
When compiled without framepointer, the DWARF-2 CFI data is required for proper stack unwinding. This patch adds the CFI information to: * syscalls (so we get proper backtrace even for release builds) the ebx hack was removed as it would complicate the CFI generation * new thread stub function (so the backtrace is clean for user created threads) Also pads the signal return trampolines separate from other functions. If CFI info was found for signal return code (which seems to happen if it's located right next a valid function), it will not be recognized as signal trampoline (gcc unwinder and gdb check first CFI info, and only if it does not exists it compares the exact opcode sequence to see if we are at signal return code block). This fixes a real crash if thread is cancelled and the cancellation handler fails to detect the signal return frame. Signed-off-by: Timo Teräs timo.te...@iki.fi --- libc/sysdeps/linux/i386/bits/syscalls.h | 82 +++ libc/sysdeps/linux/i386/clone.S | 17 ++ libc/sysdeps/linux/i386/sigaction.c |4 ++ 3 files changed, 28 insertions(+), 75 deletions(-) diff --git a/libc/sysdeps/linux/i386/bits/syscalls.h b/libc/sysdeps/linux/i386/bits/syscalls.h index eeafb3a..1f60a44 100644 --- a/libc/sysdeps/linux/i386/bits/syscalls.h +++ b/libc/sysdeps/linux/i386/bits/syscalls.h @@ -13,6 +13,7 @@ #ifndef __ASSEMBLER__ #include errno.h +#include common/sysdep.h #define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ ({ \ @@ -31,90 +32,21 @@ #if 1 /* defined __PIC__ || defined __pic__ */ -/* This code avoids pushing/popping ebx as much as possible. - * I think the main reason was that older GCCs had problems - * with proper saving/restoring of ebx if b constraint was used, - * which was breaking -fPIC code really badly. - * At least gcc 4.2.x seems to not need these tricks anymore, - * but this code is still useful because it often avoids - * using stack for saving ebx. - * Keeping it unconditionally enabled for now. - */ - -/* We need some help from the assembler to generate optimal code. - * We define some macros here which later will be used. */ -/* gcc=4.6 with LTO need the same guards as IMA (a.k.a --combine) did. - * See gcc.gnu.org/PR47577 */ -/* FIXME: drop these b* macros! */ - -__asm__ ( -#if defined __DOMULTI__ || __GNUC_PREREQ (4, 6) - /* Protect against asm macro redefinition (happens in __DOMULTI__ mode). -* Unfortunately, it ends up visible in .o files. */ - .ifndef _BITS_SYSCALLS_ASM\n\t - .set _BITS_SYSCALLS_ASM,1\n\t -#endif - .L__X'%ebx = 1\n\t - .L__X'%ecx = 2\n\t - .L__X'%edx = 2\n\t - .L__X'%eax = 3\n\t - .L__X'%esi = 3\n\t - .L__X'%edi = 3\n\t - .L__X'%ebp = 3\n\t - .L__X'%esp = 3\n\t - - /* Loading param #1 (ebx) is done by loading it into -* another register, and then performing bpushl+bmovl, -* since we must preserve ebx */ - - .macro bpushl name reg\n\t - .if 1 - \\name\n\t/* if reg!=ebx... */ - .if 2 - \\name\n\t/* if reg can't be clobbered... */ - pushl %ebx\n\t/* save ebx on stack */ - .else\n\t - xchgl \\reg, %ebx\n\t /* else save ebx in reg, and load reg to ebx */ - .endif\n\t - .endif\n\t - .endm\n\t - - .macro bmovl name reg\n\t - .if 1 - \\name\n\t - .if 2 - \\name\n\t/* if reg can't be clobbered... */ - movl \\reg, %ebx\n\t /* load reg to ebx */ - .endif\n\t - .endif\n\t - .endm\n\t - - .macro bpopl name reg\n\t - .if 1 - \\name\n\t - .if 2 - \\name\n\t/* if reg can't be clobbered... */ - popl %ebx\n\t /* restore ebx from stack */ - .else\n\t - xchgl \\reg, %ebx\n\t /* else restore ebx from reg */ - .endif\n\t - .endif\n\t - .endm\n\t - -#if defined __DOMULTI__ || __GNUC_PREREQ (4, 6) - .endif\n\t /* _BITS_SYSCALLS_ASM */ -#endif -); - #define LOADARGS_0 -#define LOADARGS_1 bpushl .L__X'%k2, %k2\n\t bmovl .L__X'%k2, %k2\n\t +#define LOADARGS_1 push %%ebx\n\t CFI_ADJUST_CFA_OFFSET(4) \n\t CFI_REL_OFFSET(ebx, 0) \n\t movl %k2, %%ebx\n\t #define LOADARGS_2 LOADARGS_1 #define LOADARGS_3 LOADARGS_1 #define LOADARGS_4 LOADARGS_1 #define LOADARGS_5 LOADARGS_1 -#define LOADARGS_6 LOADARGS_1 push %%ebp\n\t movl %7, %%ebp\n\t +#define LOADARGS_6 LOADARGS_1 push %%ebp\n\t CFI_ADJUST_CFA_OFFSET(4) \n\t CFI_REL_OFFSET(ebp, 0) \n\t movl %7, %%ebp\n\t #define RESTOREARGS_0 -#define RESTOREARGS_1 bpopl .L__X'%k2, %k2\n\t +#define RESTOREARGS_1 pop %%ebx\n\t CFI_ADJUST_CFA_OFFSET(-4) \n\t CFI_RESTORE(ebx) \n\t RESTOREARGS_0 #define RESTOREARGS_2 RESTOREARGS_1 #define RESTOREARGS_3 RESTOREARGS_1 #define RESTOREARGS_4 RESTOREARGS_1 #define RESTOREARGS_5 RESTOREARGS_1 -#define RESTOREARGS_6 pop %%ebp\n\t RESTOREARGS_1 +#define RESTOREARGS_6 pop %%ebp\n\t CFI_ADJUST_CFA_OFFSET(-4) \n\t
[PATCH] libc/x86: fix stack unwinding and backtrace information
When compiled without framepointer, the DWARF-2 CFI data is required for proper stack unwinding. This patch adds the CFI information to: * syscalls (so we get proper backtrace even for release builds) * new thread stub function (so the backtrace is clean for user created threads) Also pads the signal return trampolines separate from other functions. If CFI info was found for signal return code (which seems to happen if it's located right next a valid function), it will not be recognized as signal trampoline (gcc unwinder and gdb check first CFI info, and only if it does not exists it compares the exact opcode sequence to see if we are at signal return code block). This fixes a real crash if thread is cancelled and the cancellation handler fails to detect the signal return frame. Signed-off-by: Timo Teräs timo.te...@iki.fi --- libc/sysdeps/linux/i386/bits/syscalls.h | 13 + libc/sysdeps/linux/i386/clone.S | 17 + libc/sysdeps/linux/i386/sigaction.c |4 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/libc/sysdeps/linux/i386/bits/syscalls.h b/libc/sysdeps/linux/i386/bits/syscalls.h index eeafb3a..47d0b4c 100644 --- a/libc/sysdeps/linux/i386/bits/syscalls.h +++ b/libc/sysdeps/linux/i386/bits/syscalls.h @@ -13,6 +13,7 @@ #ifndef __ASSEMBLER__ #include errno.h +#include common/sysdep.h #define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ ({ \ @@ -71,6 +72,8 @@ __asm__ ( .if 1 - \\name\n\t/* if reg!=ebx... */ .if 2 - \\name\n\t/* if reg can't be clobbered... */ pushl %ebx\n\t/* save ebx on stack */ + CFI_ADJUST_CFA_OFFSET(4) \n\t + CFI_REL_OFFSET(ebx, 0) \n\t .else\n\t xchgl \\reg, %ebx\n\t /* else save ebx in reg, and load reg to ebx */ .endif\n\t @@ -89,6 +92,8 @@ __asm__ ( .if 1 - \\name\n\t .if 2 - \\name\n\t/* if reg can't be clobbered... */ popl %ebx\n\t /* restore ebx from stack */ + CFI_ADJUST_CFA_OFFSET(-4) \n\t + CFI_RESTORE(ebx) \n\t .else\n\t xchgl \\reg, %ebx\n\t /* else restore ebx from reg */ .endif\n\t @@ -106,7 +111,7 @@ __asm__ ( #define LOADARGS_3 LOADARGS_1 #define LOADARGS_4 LOADARGS_1 #define LOADARGS_5 LOADARGS_1 -#define LOADARGS_6 LOADARGS_1 push %%ebp\n\t movl %7, %%ebp\n\t +#define LOADARGS_6 LOADARGS_1 push %%ebp\n\t CFI_ADJUST_CFA_OFFSET(4) \n\t CFI_REL_OFFSET(ebp, 0) \n\t movl %7, %%ebp\n\t #define RESTOREARGS_0 #define RESTOREARGS_1 bpopl .L__X'%k2, %k2\n\t @@ -114,7 +119,7 @@ __asm__ ( #define RESTOREARGS_3 RESTOREARGS_1 #define RESTOREARGS_4 RESTOREARGS_1 #define RESTOREARGS_5 RESTOREARGS_1 -#define RESTOREARGS_6 pop %%ebp\n\t RESTOREARGS_1 +#define RESTOREARGS_6 pop %%ebp\n\t CFI_ADJUST_CFA_OFFSET(-4) \n\t CFI_RESTORE(ebp) \n\t RESTOREARGS_1 #define ASMFMT_0() /* acdSD constraint would work too, but SD would use esi/edi and cause @@ -162,7 +167,7 @@ __asm__ ( #define LOADARGS_3 #define LOADARGS_4 #define LOADARGS_5 -#define LOADARGS_6 push %%ebp\n\t movl %7, %%ebp\n\t +#define LOADARGS_6 push %%ebp\n\t CFI_ADJUST_CFA_OFFSET(4) \n\t CFI_REL_OFFSET(ebp, 0) \n\t movl %7, %%ebp\n\t #define RESTOREARGS_0 #define RESTOREARGS_1 @@ -170,7 +175,7 @@ __asm__ ( #define RESTOREARGS_3 #define RESTOREARGS_4 #define RESTOREARGS_5 -#define RESTOREARGS_6 pop %%ebp\n\t +#define RESTOREARGS_6 pop %%ebp\n\t CFI_ADJUST_CFA_OFFSET(-4) \n\t CFI_RESTORE(ebp) \n\t #define ASMFMT_0() #define ASMFMT_1(arg1) \ diff --git a/libc/sysdeps/linux/i386/clone.S b/libc/sysdeps/linux/i386/clone.S index a7de3fe..cf6cd35 100644 --- a/libc/sysdeps/linux/i386/clone.S +++ b/libc/sysdeps/linux/i386/clone.S @@ -25,6 +25,7 @@ #define _ERRNO_H 1 #include bits/errno.h +#include sysdep.h #include sys/syscall.h /* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg, @@ -45,6 +46,7 @@ .global clone .type clone,%function clone: + cfi_startproc; /* Sanity check arguments. */ movl$-EINVAL,%eax @@ -86,17 +88,28 @@ clone: /* Do the system call */ pushl %ebx + cfi_adjust_cfa_offset (4) pushl %esi + cfi_adjust_cfa_offset (4) pushl %edi + cfi_adjust_cfa_offset (4) + movlTLS+12(%esp),%esi + cfi_rel_offset (esi, 4) movlPTID+12(%esp),%edx movlFLAGS+12(%esp),%ebx + cfi_rel_offset (ebx, 8) movlCTID+12(%esp),%edi + cfi_rel_offset (edi, 0) movl$__NR_clone,%eax #ifdef RESET_PID /* Remember the flag value. */ movl%ebx, (%ecx) #endif + /* End FDE now, because in the child the unwind info will be + wrong. */ + cfi_endproc + int $0x80 popl%edi popl%esi @@ -108,6 +121,9 @@ clone: ret .Lthread_start: + cfi_startproc; + /* Clearing frame pointer is insufficient, use CFI
[PATCH] resolv: fix resolver to return TRY_AGAIN on timeout
This fixes the internal __dns_lookup to get a h_errno pointer so it works nicely with the _r variants. Additionally the function is modified to permanent error if the static buffer lengths are not enough. And finally it fixed to return TRY_AGAIN if the nameservers timeout. res_search is fixed to continue searching if we receive TRY_AGAIN. It could be a problem with the specific search domain's server and not necessarily a problem in the recursive resolver we are querying. For same reason, it does not make sense to differentiate timeout or SERVFAIL error reply. The biggest issue this fixes is that we now properly set h_errno to TRY_AGAIN if upstream nameserver(s) timed out. Previously we would have returned NETDB_INTERNAL. Signed-off-by: Timo Teräs timo.te...@iki.fi --- libc/inet/resolv.c | 95 +++- 1 files changed, 49 insertions(+), 46 deletions(-) diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c index dc8a752..90ba31c 100644 --- a/libc/inet/resolv.c +++ b/libc/inet/resolv.c @@ -456,7 +456,8 @@ extern int __read_etc_hosts_r(parser_t *parser, extern int __dns_lookup(const char *name, int type, unsigned char **outpacket, - struct resolv_answer *a) attribute_hidden; + struct resolv_answer *a, + int *h_errnop) attribute_hidden; extern int __encode_dotted(const char *dotted, unsigned char *dest, int maxlen) attribute_hidden; @@ -1233,7 +1234,8 @@ static int __decode_answer(const unsigned char *message, /* packet */ int attribute_hidden __dns_lookup(const char *name, int type, unsigned char **outpacket, - struct resolv_answer *a) + struct resolv_answer *a, + int *h_errnop) { /* Protected by __resolv_lock: */ static int last_ns_num = 0; @@ -1265,11 +1267,15 @@ int attribute_hidden __dns_lookup(const char *name, fd = -1; lookup = NULL; name_len = strlen(name); - if ((unsigned)name_len = MAXDNAME - MAXLEN_searchdomain - 2) - goto fail; /* paranoia */ + if ((unsigned)name_len = MAXDNAME - MAXLEN_searchdomain - 2) { + *h_errnop = NO_RECOVERY; + goto fail1; /* paranoia */ + } lookup = malloc(name_len + 1/*for '.'*/ + MAXLEN_searchdomain + 1); - if (!packet || !lookup || !name[0]) - goto fail; + if (!packet || !lookup || !name[0]) { + *h_errnop = NO_RECOVERY; + goto fail1; + } ends_with_dot = (name[name_len - 1] == '.'); /* no strcpy! paranoia, user might change name[] under us */ memcpy(lookup, name, name_len); @@ -1337,8 +1343,10 @@ int attribute_hidden __dns_lookup(const char *name, h.rd = 1; DPRINTF(encoding header\n, h.rd); i = __encode_header(h, packet, PACKETSZ); - if (i 0) - goto fail; + if (i 0) { + *h_errnop = NO_RECOVERY; + goto fail1; + } /* encode question */ DPRINTF(lookup name: %s\n, lookup); @@ -1346,8 +1354,10 @@ int attribute_hidden __dns_lookup(const char *name, q.qtype = type; q.qclass = C_IN; /* CLASS_IN */ j = __encode_question(q, packet+i, PACKETSZ-i); - if (j 0) - goto fail; + if (j 0) { + *h_errnop = NO_RECOVERY; + goto fail1; + } packet_len = i + j; /* send packet */ @@ -1473,7 +1483,7 @@ int attribute_hidden __dns_lookup(const char *name, /* no more search domains to try */ } /* dont loop, this is no such host situation */ - h_errno = HOST_NOT_FOUND; + *h_errnop = HOST_NOT_FOUND; goto fail1; } /* Insert other non-fatal errors here, which do not warrant @@ -1485,7 +1495,7 @@ int attribute_hidden __dns_lookup(const char *name, /* Code below won't work correctly with h.ancount == 0, so... */ if (h.ancount = 0) { - h_errno = NO_DATA; /* [is this correct code to check for?] */ + *h_errnop = NO_DATA; /* [is this correct code to check for?] */ goto fail1; } pos = HFIXEDSZ; @@ -1562,8 +1572,7 @@ int attribute_hidden __dns_lookup(const char *name, variant = -1; } while (retries_left 0); - fail: - h_errno = NETDB_INTERNAL; + *h_errnop = TRY_AGAIN; fail1: if (fd != -1) close(fd); @@ -2104,9 +2113,8 @@ int gethostbyname_r
[PATCH] posix_fadvise64: fix x86 implementation
Commit 73d59554144f429b1cf0d4d7fa7de42bdf59ad92 completely broke the x86 implementation of posix_fadvise64. It moved the first the assembly code retn instruction gets missing depending on the Technically the file has two implementaions for posix_fadvise64, one when __NR_fadvise64_64 is available, and second one if only __NR_fadvise64 is there. Fix the #ifdef's to be proper for that. Signed-off-by: Timo Teräs timo.te...@iki.fi --- libc/sysdeps/linux/i386/posix_fadvise64.S |4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/libc/sysdeps/linux/i386/posix_fadvise64.S b/libc/sysdeps/linux/i386/posix_fadvise64.S index b4aeff1..8a8947d 100644 --- a/libc/sysdeps/linux/i386/posix_fadvise64.S +++ b/libc/sysdeps/linux/i386/posix_fadvise64.S @@ -22,7 +22,7 @@ #include bits/errno.h #include sys/syscall.h -#if defined __NR_fadvise64_64 +#if defined __NR_fadvise64_64 || defined __NR_fadvise64 /* Was named __libc_posix_fadvise64 for some inexplicable reason. ** google says only uclibc has *__libc*_posix_fadviseXXX, @@ -35,6 +35,7 @@ .global posix_fadvise64 .type posix_fadvise64,%function posix_fadvise64: +#if defined __NR_fadvise64_64 /* Save regs */ pushl %ebp pushl %ebx @@ -91,6 +92,7 @@ overflow: /* Returns 0 on success, else an error code. */ negl%eax +#endif /* Successful; return the syscall's value. */ ret -- 1.7.1 ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
[PATCH] resolv: fix res_close not to hang with ipv6
The memory release loop is missing an obvious counter increment. Signed-off-by: Timo Teräs timo.te...@iki.fi --- libc/inet/resolv.c |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c index 47bab75..1e394d4 100644 --- a/libc/inet/resolv.c +++ b/libc/inet/resolv.c @@ -3006,9 +3006,9 @@ void res_close(void) #ifdef __UCLIBC_HAS_IPV6__ { char *p1 = (char*) (_res.nsaddr_list[0]); - int m = 0; + int m; /* free nsaddrs[m] if they do not point to nsaddr_list[x] */ - while (m ARRAY_SIZE(_res._u._ext.nsaddrs)) { + for (m = 0; m ARRAY_SIZE(_res._u._ext.nsaddrs); m++) { char *p2 = (char*)(_res._u._ext.nsaddrs[m]); if (p2 p1 || (p2 - p1) sizeof(_res.nsaddr_list)) free(p2); -- 1.7.1 ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: ldd segfaults on libdl.so for 0.9.32-rc3 because of if (*tmp)
On 03/30/2011 01:24 PM, Peter Mazinger wrote: how is HARDWIRED_ABSPATH config option set? I'd say that most likely yes. :) But the fix below is still valid and should be applied, IMHO. Thanks, Peter Original-Nachricht Datum: Tue, 29 Mar 2011 23:15:18 -0500 Von: Kevin Day thekevin...@gmail.com An: uClibc uClibc@uclibc.org Betreff: ldd segfaults on libdl.so for 0.9.32-rc3 because of if (*tmp) The problem happens around utils/ldd.c:555: tmp = strrchr(interp_dir, '/'); if (*tmp) *tmp = '\0'; else { free(interp_dir); interp_dir = interp_name; } The *tmp is the culprit. If NULL is returned by strrchr(), then a segfault happens. Perhaps the following is what is intended? tmp = strrchr(interp_dir, '/'); if (tmp) *tmp = '\0'; else { free(interp_dir); interp_dir = interp_name; } ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: [PATCH] malloc-standard: synchronize on fork
On 03/28/2011 06:15 PM, Rich Felker wrote: On Sun, Mar 27, 2011 at 10:47:10PM +0300, Timo Teräs wrote: On 03/27/2011 10:21 PM, Rich Felker wrote: On Sat, Mar 26, 2011 at 08:28:04PM +0200, Timo Teräs wrote: Otherwise other threads can leave malloc state locked, and the child will hang indefinitely if it tries to malloc something. This change by itself breaks as much as it fixes, unless the mutex implementation is reentrant and recursive. fork() is specified to be async-signal-safe, which means it's legal for a signal handler to call fork() while malloc() is being executed. With your patch, this will hang the program. It is recursive mutex. It's works perfectly fine if same thread locks that mutex multiple times. But not from a signal handler. There's almost surely a race between locking the mutex and having it in the right state so that the signal handler sees it's the owner. Oh. That's right. There's a race for that. I've been trying to figure how glibc handles that, but it'd seem that it does not. Hmmh. Not sure what to do here. Need to think about it. Any great ideas? -Timo ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: [PATCH] malloc-standard: synchronize on fork
On 03/29/2011 01:06 AM, Rich Felker wrote: On Mon, Mar 28, 2011 at 11:43:00PM +0300, Timo Teräs wrote: It is recursive mutex. It's works perfectly fine if same thread locks that mutex multiple times. But not from a signal handler. There's almost surely a race between locking the mutex and having it in the right state so that the signal handler sees it's the owner. Oh. That's right. There's a race for that. I've been trying to figure how glibc handles that, but it'd seem that it does not. Hmmh. Not sure what to do here. Need to think about it. Any great ideas? You could enhance the recursive mutex implementation to be reentrant - having a single atomic int that serves as both the lock status and the owner and updating it with an atomic compare-and-swap should be one way to do this. Yes, I got the same idea too. Looking at the code, it might be easier to do a specific lock implementation for this. It'd be nice, if we had a general purpose re-entrant mutex implementation, though. - Timo ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: [PATCH] malloc-standard: synchronize on fork
On 03/27/2011 10:21 PM, Rich Felker wrote: On Sat, Mar 26, 2011 at 08:28:04PM +0200, Timo Teräs wrote: Otherwise other threads can leave malloc state locked, and the child will hang indefinitely if it tries to malloc something. This change by itself breaks as much as it fixes, unless the mutex implementation is reentrant and recursive. fork() is specified to be async-signal-safe, which means it's legal for a signal handler to call fork() while malloc() is being executed. With your patch, this will hang the program. It is recursive mutex. It's works perfectly fine if same thread locks that mutex multiple times. Doing fork from signal handler seems utterly stupid. That would need extra precautions to work properly, because the malloc code is not re-entrant. But this is not the case I'm fixing. It's thread A doing malloc while thread B is forking. As such, this does not break anything. Or could you provide example code on scenario that this breaks (and which was not broken before this)? I ran into the same issue developing musl's implementation of malloc, and for now I have left it alone. POSIX 2008 (SUSv4) went back on some of the promises of previous versions, and has now declared that it's UB to call any async-signal-unsafe functions (such as malloc()) after fork() in a multi-threaded program, so your patch is not needed to conform to the current standard, only to previous versions (and even then it's not clear that the older standard required malloc() after fork() to work in a threaded program). Yes. I agree, it's bad practice do things like that. But it just so happens, that there are programs doing this. This can also happen indirectly in certain scenarios: e.g. using opendir/readdir of /proc/self/fd to close open fd's. (opendir in uclibc seems ot use malloc). This patch is intended to provide glibc compatibility with the more or less broken programs. I may later revisit this issue and fix it, but the fix is not simply using locks. I would either need to ignore locking and actively repair all the potentially-corrupted malloc structures in the child process, or selectively determine which locks are held by the current thread (due to having interrupted malloc() with a signal handler) and only attempt to lock the other locks before forking. For uClibc which only has one big malloc() lock, it may be easier, but I think you'll at least need to fix the lock to be reentrant and either recursive or error-checking. And that of course has a cost... This prevents other threads not to execute malloc while we are forking. Thus assuring that we have consistent malloc-state for the child process. Since the thread doing fork has malloc-lock, it will own the lock, thus the lock can be safely reinitialized in the child (we need to reinitilize it since TID change on fork). When the parent continues, the lock is unlocked regularly and memory allocation can continue as normal. This exactly what glibc does and it works. This does not address the case that the thread forking is doing malloc and forks from signal handler. That case is just utterly broken and not worth fixing IMHO. - Timo ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
[PATCH] malloc-standard: synchronize on fork
Otherwise other threads can leave malloc state locked, and the child will hang indefinitely if it tries to malloc something. Signed-off-by: Timo Teräs timo.te...@iki.fi --- libc/stdlib/malloc-standard/free.c | 17 + 1 files changed, 17 insertions(+), 0 deletions(-) diff --git a/libc/stdlib/malloc-standard/free.c b/libc/stdlib/malloc-standard/free.c index 39e54d6..df512cc 100644 --- a/libc/stdlib/malloc-standard/free.c +++ b/libc/stdlib/malloc-standard/free.c @@ -118,6 +118,21 @@ int malloc_trim(size_t pad) to inline it at all call points, which turns out not to be an optimization at all. (Inlining it in __malloc_consolidate is fine though.) */ +static void _malloc_lock(void) +{ +__UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE(__malloc_lock); +} + +static void _malloc_unlock(void) +{ +__UCLIBC_MUTEX_UNLOCK_CANCEL_UNSAFE(__malloc_lock); +} + +static void _malloc_reset(void) +{ +__UCLIBC_MUTEX_INIT_VAR(__malloc_lock); +} + static void malloc_init_state(mstate av) { int i; @@ -145,6 +160,8 @@ static void malloc_init_state(mstate av) av-top= initial_top(av); av-pagesize = malloc_getpagesize; + +__libc_atfork(_malloc_lock, _malloc_unlock, _malloc_reset); } -- 1.7.1 ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: [PATCH] malloc-standard: synchronize on fork
On 03/26/2011 08:38 PM, Roman I Khimov wrote: В сообщении от 26 марта 2011 21:28:04 автор Timo Teräs написал: Otherwise other threads can leave malloc state locked, and the child will hang indefinitely if it tries to malloc something. Signed-off-by: Timo Teräs timo.te...@iki.fi FYI: https://bugs.busybox.net/show_bug.cgi?id=2341 Ah, didn't know there was a bug for this. But yes, the same bug happens with NPTL too. And this patch fixes it. Tested it locally here. I have a test program too if needed. - Timo ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: dlopen/dlclose thread safety
On 03/24/2011 12:27 AM, Mike Frysinger wrote: 2011/3/23 Timo Teräs: On 03/23/2011 06:33 PM, Mike Frysinger wrote: On Wed, Mar 23, 2011 at 12:29 PM, Carmelo AMOROSO wrote: indeed we have seen also some issue with dlopen, when TLS variables were involved. One suspect we have is actually thread-safety. glibc use some locking primitives to access TLS block, while we don't. Not yet had a free time slot to look at this deeply. i'm not sure how thread safety would play a role with TLS variables. TLS, by definition, is per-thread and that is guaranteed by the ABI/compiler/C lib/kernel down to the variable level, and that whole stack shouldnt be poking into any shared state (beyond shared .text). ldso needs to allocate each global TLS variable from globally single place. That's how it organises the per-thread data area. So yes, when dl allocates the TLS variables it needs to go fiddle global variables. mmm my understanding was that each thread got its own chunk of TLS area at thread creation time, and after that the ldso only existed when the thread needed to know the address of its TLS. what port are you talking about exactly ? Using TLS variables is safe obviously. But if after startup, someone does dlopen(libfoo.so) and libfoo defines global TLS variables, those variables need to be allocated from the global TLS tables. I believe that's mostly done in _dl_add_to_slotinfo. However, I think this is not my problem. I think the problem is _dl_loaded_modules as suspected first. What happens likely is (foo.so and bar.so both depend on same module): Thread A Thread B dlopen(foo.so) loads zap.so dlclose(foo.so) start unloading zap.so (finds it refcount=0) dlopen(bar.so) finds zap.so from _dl_loaded_modules refcount not checked, it's just referenced unconditionally unmaps zap.so goes along with reference to module being unloaded - BOOM So yes, we seem to have bunch of globals unprotected. _dl_loaded_modules and _dl_symbol_tables amongst others. (BTW. Singly linked list for loaded_modules is really inefficient, we should probably make it a hash table (indexed with st_dev and st_ino) so we can search it fast in _dl_load_elf_shared_library(). So. As immediate bandage aid, we probably need to add rwlock (or just regular mutex) to dlopen (rw)/dlsym (ro)/dlclose (rw). That should at least prevent crashes. But yes, more fine grained locking (or even RCU) would be preferable. - Timo ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
[PATCH] libdl: rudimentary locking for dlopen/dlsym/dlclose
This implements big-dlfcn lock to allow multithreaded usage of dlopen/dlsym/dlclose. We should really clean up the dl code so we can use more fine grained locking or even RCU where appropriate. But at least we won't crash now. Signed-off-by: Timo Teräs timo.te...@iki.fi --- TODO |1 + ldso/libdl/libdl.c | 54 +++ 2 files changed, 50 insertions(+), 5 deletions(-) diff --git a/TODO b/TODO index ae305a5..95cabd5 100644 --- a/TODO +++ b/TODO @@ -101,6 +101,7 @@ TODO list for AFTER the uClibc 1.0.0 release: *) run 'nm -D --size-sort -t d libuClibc-0.9.26.so' and work on the biggest things (i.e. stuff at the end of the list) to make them smaller. +*) Fix dlopen/dlsym/dlclose locking to more fine grained or use RCU more wishlist items here diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c index 68cd579..e007f54 100644 --- a/ldso/libdl/libdl.c +++ b/ldso/libdl/libdl.c @@ -34,6 +34,7 @@ #include stdio.h #include string.h /* Needed for 'strstr' prototype' */ #include stdbool.h +#include bits/uClibc_mutex.h #ifdef __UCLIBC_HAS_TLS__ #include tls.h @@ -44,6 +45,10 @@ extern void _dl_add_to_slotinfo(struct link_map *l); #endif +/* TODO: get rid of global lock and use more finegrained locking, or + * perhaps RCU for the global structures */ +__UCLIBC_MUTEX_STATIC(_dl_mutex, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + #ifdef SHARED # if defined(USE_TLS) USE_TLS # include dl-tls.h @@ -271,7 +276,7 @@ void dl_cleanup(void) } } -void *dlopen(const char *libname, int flag) +static void *do_dlopen(const char *libname, int flag) { struct elf_resolve *tpnt, *tfrom; struct dyn_elf *dyn_chain, *rpnt = NULL, *dyn_ptr, *relro_ptr, *handle; @@ -605,7 +610,18 @@ oops: return NULL; } -void *dlsym(void *vhandle, const char *name) +void *dlopen(const char *libname, int flag) +{ + void *ret; + + __UCLIBC_MUTEX_CONDITIONAL_LOCK(_dl_mutex, 1); + ret = do_dlopen(libname, flag); + __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(_dl_mutex, 1); + + return ret; +} + +static void *do_dlsym(void *vhandle, const char *name, void *caller_address) { struct elf_resolve *tpnt, *tfrom; struct dyn_elf *handle; @@ -653,7 +669,7 @@ void *dlsym(void *vhandle, const char *name) * dynamic loader itself, as it doesn't know * how to properly treat it. */ - from = (ElfW(Addr)) __builtin_return_address(0); + from = (ElfW(Addr)) caller_address; tfrom = NULL; for (rpnt = _dl_symbol_tables; rpnt; rpnt = rpnt-next) { @@ -690,6 +706,17 @@ out: return ret; } +void *dlsym(void *vhandle, const char *name) +{ + void *ret; + + __UCLIBC_MUTEX_CONDITIONAL_LOCK(_dl_mutex, 1); + ret = do_dlsym(vhandle, name, __builtin_return_address(0)); + __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(_dl_mutex, 1); + + return ret; +} + #if 0 void *dlvsym(void *vhandle, const char *name, const char *version) { @@ -957,7 +984,13 @@ static int do_dlclose(void *vhandle, int need_fini) int dlclose(void *vhandle) { - return do_dlclose(vhandle, 1); + int ret; + + __UCLIBC_MUTEX_CONDITIONAL_LOCK(_dl_mutex, 1); + ret = do_dlclose(vhandle, 1); + __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(_dl_mutex, 1); + + return ret; } char *dlerror(void) @@ -1004,7 +1037,7 @@ int dlinfo(void) return 0; } -int dladdr(const void *__address, Dl_info * __info) +static int do_dladdr(const void *__address, Dl_info * __info) { struct elf_resolve *pelf; struct elf_resolve *rpnt; @@ -1108,3 +1141,14 @@ int dladdr(const void *__address, Dl_info * __info) } } #endif + +int dladdr(const void *__address, Dl_info * __info) +{ + int ret; + + __UCLIBC_MUTEX_CONDITIONAL_LOCK(_dl_mutex, 1); + ret = do_dladdr(__address, __info); + __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(_dl_mutex, 1); + + return ret; +} -- 1.7.1 ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: [PATCH] libdl: rudimentary locking for dlopen/dlsym/dlclose
On 03/24/2011 04:58 PM, Mike Frysinger wrote: 2011/3/24 Timo Teräs: This implements big-dlfcn lock to allow multithreaded usage of dlopen/dlsym/dlclose. We should really clean up the dl code so we can use more fine grained locking or even RCU where appropriate. But at least we won't crash now. looks straight forward enough ... i'm assuming it actually fixes the crashes you were seeing ? Yes. No crashes on my box anymore. Valgrind is happy too. ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
dlopen/dlclose thread safety
Hi all, Is uclibc dlopen/dlclose thread safe? It looks like not. I'm currently trouble shooting issue where I needed to make debug build of uclibc+vlc and figure the issue out. Turned out that debug build of these very randomly crashes in dlopen(). gdb says that this happens when two threads are doing dlopen() and/or dlclose() simultaneously. So I have a feeling that our implementation is not thread safe. Valgrind says that we always do bad things at: ldso/libdl/libdl.c:453: if (!(runp-tpnt-rtld_flags RTLD_GLOBAL)) { accessing uninitialized (or unmapped) memory. VLC does lot of loads/unloads to figure out which .so's it wants to use. So I'd assume this is crashing when one thread is dlopening. SUPPORT_LD_DEBUG is also garbled because it's printing stuff from two dlopen() calls from two different threads. What I make of it, we are completely borked if we try to use dl* multithreadedly. Could someone with some ld knowledge at least add very basic mutexes to essential parts so that we do not crash? And yes, in libdl.so we should be able to use mutexes at least in NPTL as the main libc.so provides pthread_mutex_* symbols, and forwards them to libpthread if it's loaded. Though depending on how the code is shared, we might need extra care to make sure that the loader .so does not use those (as it can't depend on anything). Cheers, Timo ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
ldd broken with HARDWIRED_ABSPATH=n
Hi Peter, Your commit 5dffed7dd1a413f3965af702fa7ecd79809d1988 removed absolute path from the interpreter binary name embedded in ELF files. This makes ldd seg.fault as it seems to assume absolute paths. gdb sayeth: (gdb) where #0 0x00111ae3 in find_elf_interpreter (ehdr=0xb7a74000) at ../utils/ldd.c:556 #1 0x00111f2a in find_dependencies (filename=0x114910 /home/fabled/aports/main/libc0.9.32/src/uClibc-0.9.32-rc3/lib/librt.so.0.9.32) at ../utils/ldd.c:676 #2 0x0011228e in main (argc=1, argv=0xb6e8) at ../utils/ldd.c:777 (gdb) p tmp tmp = NULL (gdb) p interp_dir $1 = 0x116660 ld-uClibc.so.0.9.32 Care to fix? Thanks, Timo ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: dlopen/dlclose thread safety
On 03/23/2011 06:33 PM, Mike Frysinger wrote: On Wed, Mar 23, 2011 at 12:29 PM, Carmelo AMOROSO wrote: indeed we have seen also some issue with dlopen, when TLS variables were involved. One suspect we have is actually thread-safety. glibc use some locking primitives to access TLS block, while we don't. Not yet had a free time slot to look at this deeply. i'm not sure how thread safety would play a role with TLS variables. TLS, by definition, is per-thread and that is guaranteed by the ABI/compiler/C lib/kernel down to the variable level, and that whole stack shouldnt be poking into any shared state (beyond shared .text). ldso needs to allocate each global TLS variable from globally single place. That's how it organises the per-thread data area. So yes, when dl allocates the TLS variables it needs to go fiddle global variables. I was worried if the dlopen searching of already loaded modules is safe. Since dlopen first checks if the module has been already loaded or not, which also touches global variables. So there's multiple places where dlopen/dlclose need to touch global data and requires mutexes. - Timo ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
[PATCH 2/3] stdlib: fix arc4random return type to u_int32_t
It's documented to be u_int32_t and not uint32_t: http://www.manpagez.com/man/3/arc4random/ This also fixes a major bug that stdlib.h includes stdint.h. Things might go very wrong because stdint.h has conditional defines and if stdlib.h is included before #define's for stdint.h we end up missing things and breaking builds (e.g. openjdk). Signed-off-by: Timo Teräs timo.te...@iki.fi --- include/stdlib.h |4 ++-- libc/stdlib/arc4random.c |3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/stdlib.h b/include/stdlib.h index e9a8b84..7b35840 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -902,8 +902,8 @@ extern int getloadavg (double __loadavg[], int __nelem) #endif #ifdef __UCLIBC_HAS_ARC4RANDOM__ -#include stdint.h -extern uint32_t arc4random(void); +# include sys/types.h +extern u_int32_t arc4random(void); extern void arc4random_stir(void); extern void arc4random_addrandom(unsigned char *, int); #endif diff --git a/libc/stdlib/arc4random.c b/libc/stdlib/arc4random.c index c7aed66..7b9b12d 100644 --- a/libc/stdlib/arc4random.c +++ b/libc/stdlib/arc4random.c @@ -30,6 +30,7 @@ #include fcntl.h #include stdlib.h #include unistd.h +#include stdint.h #include sys/types.h #include sys/param.h #include sys/time.h @@ -175,7 +176,7 @@ arc4random_addrandom(u_char *dat, int datlen) arc4_addrandom(rs, dat, datlen); } -uint32_t +u_int32_t arc4random(void) { if (!rs_initialized) -- 1.7.1 ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
[PATCH 1/3] ldso: limited support for $ORIGIN in rpath
Handle it if it's in the beginning of the rpath entry as it should be. Signed-off-by: Timo Teräs timo.te...@iki.fi --- ldso/ldso/dl-elf.c | 80 --- ldso/ldso/ldso.c | 18 ++-- 2 files changed, 59 insertions(+), 39 deletions(-) diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c index 505247e..2b2d429 100644 --- a/ldso/ldso/dl-elf.c +++ b/ldso/ldso/dl-elf.c @@ -133,53 +133,60 @@ _dl_protect_relro (struct elf_resolve *l) * in uClibc/ldso/util/ldd.c */ static struct elf_resolve * search_for_named_library(const char *name, int secure, const char *path_list, - struct dyn_elf **rpnt) + struct dyn_elf **rpnt, const char *origin) { - char *path, *path_n, *mylibname; + char *mylibname; + const char *p, *pn; struct elf_resolve *tpnt; - int done; + int plen; if (path_list==NULL) return NULL; - /* We need a writable copy of this string, but we don't -* need this allocated permanently since we don't want -* to leak memory, so use alloca to put path on the stack */ - done = _dl_strlen(path_list); - path = alloca(done + 1); - /* another bit of local storage */ mylibname = alloca(2050); - _dl_memcpy(path, path_list, done+1); - /* Unlike ldd.c, don't bother to eliminate double //s */ /* Replace colons with zeros in path_list */ /* : at the beginning or end of path maps to CWD */ /* :: anywhere maps CWD */ /* maps to CWD */ - done = 0; - path_n = path; - do { - if (*path == 0) { - *path = ':'; - done = 1; - } - if (*path == ':') { - *path = 0; - if (*path_n) - _dl_strcpy(mylibname, path_n); - else - _dl_strcpy(mylibname, .); /* Assume current dir if empty path */ - _dl_strcat(mylibname, /); - _dl_strcat(mylibname, name); - if ((tpnt = _dl_load_elf_shared_library(secure, rpnt, mylibname)) != NULL) - return tpnt; - path_n = path+1; + for (p = path_list; p != NULL; p = pn) { + pn = _dl_strchr(p + 1, ':'); + if (pn != NULL) { + plen = pn - p; + pn++; + } else + plen = _dl_strlen(p); + + if (plen = 7 _dl_memcmp(p, $ORIGIN, 7) == 0) { + int olen; + if (secure plen != 7) + continue; + if (origin == NULL) + continue; + for (olen = _dl_strlen(origin) - 1; olen = 0 origin[olen] != '/'; olen--) + ; + if (olen = 0) + continue; + _dl_memcpy(mylibname[0], origin, olen); + _dl_memcpy(mylibname[olen], p + 7, plen - 7); + mylibname[olen + plen - 7] = 0; + } else if (plen != 0) { + _dl_memcpy(mylibname, p, plen); + mylibname[plen] = 0; + } else { + _dl_strcpy(mylibname, .); } - path++; - } while (!done); + _dl_strcat(mylibname, /); + _dl_strcat(mylibname, name); + + tpnt = _dl_load_elf_shared_library(secure, rpnt, mylibname); + if (tpnt != NULL) + return tpnt; + } + return NULL; } @@ -231,7 +238,8 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt, if (pnt) { pnt += (unsigned long) tpnt-dynamic_info[DT_STRTAB]; _dl_if_debug_dprint(\tsearching RPATH='%s'\n, pnt); - if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt)) != NULL) + if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt, + tpnt-libname)) != NULL) return tpnt1; } #endif @@ -239,7 +247,7 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt, /* Check in LD_{ELF_}LIBRARY_PATH, if specified and allowed */ if (_dl_library_path) { _dl_if_debug_dprint(\tsearching LD_LIBRARY_PATH='%s'\n, _dl_library_path); - if ((tpnt1 = search_for_named_library(libname, secure, _dl_library_path, rpnt)) != NULL) + if ((tpnt1 = search_for_named_library(libname, secure, _dl_library_path, rpnt, NULL)) != NULL) { return tpnt1
[PATCH 3/3] ldso: support RTLD_NOLOAD
So application query if specified modile is loaded or not with dlopen. Signed-off-by: Timo Teräs timo.te...@iki.fi --- ldso/include/dl-elf.h |6 -- ldso/ldso/dl-elf.c | 30 +- ldso/ldso/ldso.c |4 +++- ldso/libdl/libdl.c |5 +++-- libc/sysdeps/linux/common/bits/dlfcn.h |4 ++-- 5 files changed, 29 insertions(+), 20 deletions(-) diff --git a/ldso/include/dl-elf.h b/ldso/include/dl-elf.h index 7fbb373..7102351 100644 --- a/ldso/include/dl-elf.h +++ b/ldso/include/dl-elf.h @@ -25,16 +25,18 @@ static __inline__ void _dl_map_cache(void) { } static __inline__ void _dl_unmap_cache(void) { } #endif +#define DL_RESOLVE_SECURE 0x0001 +#define DL_RESOLVE_NOLOAD 0x0002 /* Function prototypes for non-static stuff in readelflib1.c */ extern void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, unsigned long rel_addr, unsigned long rel_size); extern int _dl_parse_relocation_information(struct dyn_elf *rpnt, unsigned long rel_addr, unsigned long rel_size); -extern struct elf_resolve * _dl_load_shared_library(int secure, +extern struct elf_resolve * _dl_load_shared_library(int resolve_flags, struct dyn_elf **rpnt, struct elf_resolve *tpnt, char *full_libname, int trace_loaded_objects); -extern struct elf_resolve * _dl_load_elf_shared_library(int secure, +extern struct elf_resolve * _dl_load_elf_shared_library(int resolve_flags, struct dyn_elf **rpnt, char *libname); extern struct elf_resolve *_dl_check_if_named_library_is_loaded(const char *full_libname, int trace_loaded_objects); diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c index 2b2d429..6d35bf2 100644 --- a/ldso/ldso/dl-elf.c +++ b/ldso/ldso/dl-elf.c @@ -132,7 +132,7 @@ _dl_protect_relro (struct elf_resolve *l) /* This function's behavior must exactly match that * in uClibc/ldso/util/ldd.c */ static struct elf_resolve * -search_for_named_library(const char *name, int secure, const char *path_list, +search_for_named_library(const char *name, int resolve_flags, const char *path_list, struct dyn_elf **rpnt, const char *origin) { char *mylibname; @@ -162,7 +162,7 @@ search_for_named_library(const char *name, int secure, const char *path_list, if (plen = 7 _dl_memcmp(p, $ORIGIN, 7) == 0) { int olen; - if (secure plen != 7) + if ((resolve_flags DL_RESOLVE_SECURE) plen != 7) continue; if (origin == NULL) continue; @@ -182,7 +182,7 @@ search_for_named_library(const char *name, int secure, const char *path_list, _dl_strcat(mylibname, /); _dl_strcat(mylibname, name); - tpnt = _dl_load_elf_shared_library(secure, rpnt, mylibname); + tpnt = _dl_load_elf_shared_library(resolve_flags, rpnt, mylibname); if (tpnt != NULL) return tpnt; } @@ -194,7 +194,7 @@ search_for_named_library(const char *name, int secure, const char *path_list, unsigned long _dl_error_number; unsigned long _dl_internal_error_number; -struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt, +struct elf_resolve *_dl_load_shared_library(int resolve_flags, struct dyn_elf **rpnt, struct elf_resolve *tpnt, char *full_libname, int attribute_unused trace_loaded_objects) { char *pnt; @@ -223,7 +223,7 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt, if (libname != full_libname) { _dl_if_debug_dprint(\ttrying file='%s'\n, full_libname); - tpnt1 = _dl_load_elf_shared_library(secure, rpnt, full_libname); + tpnt1 = _dl_load_elf_shared_library(resolve_flags, rpnt, full_libname); if (tpnt1) { return tpnt1; } @@ -238,7 +238,7 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt, if (pnt) { pnt += (unsigned long) tpnt-dynamic_info[DT_STRTAB]; _dl_if_debug_dprint(\tsearching RPATH='%s'\n, pnt); - if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt, + if ((tpnt1 = search_for_named_library(libname, resolve_flags, pnt, rpnt, tpnt-libname)) != NULL) return tpnt1; } @@ -247,7 +247,7 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt, /* Check in LD_{ELF_}LIBRARY_PATH, if specified and allowed */ if (_dl_library_path) { _dl_if_debug_dprint(\tsearching LD_LIBRARY_PATH='%s'\n, _dl_library_path); - if ((tpnt1 = search_for_named_library(libname
Re: getcontext
On 03/17/2011 01:06 AM, Rich Felker wrote: On Wed, Mar 16, 2011 at 09:16:48PM +0100, Joakim Tjernlund wrote: Impl. of portable CoRoutines, http://en.wikipedia.org/wiki/Coroutine , likes to use get/setcontext. Don't think there is anything else these can use. Coroutines can be implemented portably on top of pthreads and condition variables, barriers, or semaphores. But that's making the coroutines pointless. Their idea is to be light weight. And you can achieve that only with get/setcontext. We'll one could do setjmp hacks too. Or write one's own context changing things in assembler. But those are useful still today. E.g. the new Google Go language has coroutines built-in into it. The language runtime implements them with native assembler. ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: -lc -lpthread link order works on x86_64 glibc-2.9, but cause hang on uClibc-0.9.32-rc1 on mipsel with NPTL
On 01/11/2011 10:03 AM, Jian Peng wrote: -lc -lpthread link order works on Linux with glibc-2.9 on x86_64, but cause hang on uClibc-0.9.32-rc1 on mipsel with NPTL Would be because uclibc on mipsel does not support protected symbols. uclibc on x86 and some other platforms works too. I believe someone should be working on making the protected symbol support generic. - Timo ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
nptl_db not working
Hi all, I was trying to debug a multithreaded program in uclibc, but ntpl_db was not working at all. I hunted down the problem the fact that we are doing strip -x to the libpthread: it removes all non-global symbols. However, nptl_db inspects the local system, and uses them to verify libpthread (looks for static/local nptl_version symbol) and also to hook into libpthread (it uses certain local symbols to find libpthread event structures and modifies them). Thus gdb + uclibc nptl is broke. I'm not sure how to modify makefiles so that we do *not* do strip -x on libpthread, but this should be fixed. I removed the -x on global STRIP_FLAGS from Rules.mak, recompiled and then gdb was much more happier with ntpl_db. Cheers, Timo ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
[PATCH] nptl: fix Unwind_Resume PLT calls
My change a49b3a18e463cbe8c94c41501e386e7f4c61609e fixed two Unwind_Resume calls to go via PLT to avoid text relocations for PIC builds. However, it looks the reason for upstream not using PLT calls is that ebx gets clobbered. So we need to reload it. Signed-off-by: Timo Teräs timo.te...@iki.fi --- .../sysv/linux/i386/i486/pthread_cond_timedwait.S |4 .../unix/sysv/linux/i386/i486/pthread_cond_wait.S | 18 +++--- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S index ac7983c..3b61367 100644 --- a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S @@ -648,6 +648,10 @@ __condvar_tw_cleanup: movl%esi, (%esp) .LcallUR: +#ifdef __PIC__ + call__i686.get_pc_thunk.bx + addl$_GLOBAL_OFFSET_TABLE_, %ebx +#endif call_unwind_res...@plt hlt .LENDCODE: diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S index abc963f..a1294c5 100644 --- a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S @@ -535,6 +535,10 @@ __condvar_w_cleanup: movl%esi, (%esp) .LcallUR: +#ifdef __PIC__ + call__i686.get_pc_thunk.bx + addl$_GLOBAL_OFFSET_TABLE_, %ebx +#endif call_unwind_res...@plt hlt .LENDCODE: @@ -569,14 +573,14 @@ __condvar_w_cleanup: .Lcstend: #ifdef __PIC__ - .section .gnu.linkonce.t.__i686.get_pc_thunk.cx,ax,@progbits - .globl __i686.get_pc_thunk.cx - .hidden __i686.get_pc_thunk.cx - .type __i686.get_pc_thunk.cx,@function -__i686.get_pc_thunk.cx: - movl (%esp), %ecx; + .section .gnu.linkonce.t.__i686.get_pc_thunk.bx,ax,@progbits + .globl __i686.get_pc_thunk.bx + .hidden __i686.get_pc_thunk.bx + .type __i686.get_pc_thunk.bx,@function +__i686.get_pc_thunk.bx: + movl (%esp), %ebx; ret - .size __i686.get_pc_thunk.cx,.-__i686.get_pc_thunk.cx + .size __i686.get_pc_thunk.bx,.-__i686.get_pc_thunk.bx #endif #ifdef SHARED -- 1.7.1 ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: [PATCH] libm/x86: use call instead of jump for wrappers
On 11/01/2010 03:16 AM, Denys Vlasenko wrote: On Sunday 31 October 2010 23:07, Timo Teräs wrote: On 10/31/2010 05:10 PM, Denys Vlasenko wrote: Since by breaking long double wrappers I proved that no one actually runs math testsuite (does anyone runs ANY part of testsuite?), I decided that now it is my obligation to fix math testsuite first, so that in the future it will be easier to catch breakatge. I fixed it to a certain degree already. Then I reverted your fix, and _verified_ that it works with both static and shared build. Your code crashed. Mine version did not. I did not run the test suite I think we all neglected testsuite for too long. It has bit rotted. Needs work to restore to runnable state... nor test the call thingy. Sorry about that. Just build failed by segfault vs. succeed was enough for me. Yes, I know how the failure must have looked on your side. What is unclear is what caused gcc to emit a prologue with some stack pushes... It needs to be saved/restored *if ebx is used*. In these stubs it is not used, thus it is not saved by gcc, and therefore tail jump is ok even with __PIC__. I do not merely think so. I tested it. Try in the directory where you successfully built shared uclibc using PIC: I remember that the original crash I fixed was caused by PIC and not SSP. The issue is that the jmp target name is outside __asm__ and translated by gcc to ebx+xxx. So you use implicitly ebx in your __asm__ block. And thus gcc will save/restore and calculate the local ebx for you automatically. Uhhuh... so it will happen only if function gets called through inter-library stub. This should not happen with __GI_foo symbols, though - those are hidden and should be linked directly intra-library. BTW, there were no __GI_foo calls originally, I just called foo directly at first. Then affed __GI_ prefix. Maybe *that* fixed the problem. I think you had __GI_ prefix all the time. I rebuilt again with the original buggy config. It had both PIC and SSP enabled. The SSP abort __stack_chk_fail is called via plt and causes the ebx load. So using __SSP_ALL__ fixed this specific build. Thanks, replaced: -#if defined __i386__ defined __OPTIMIZE__ !defined __UCLIBC_HAS_SSP__ +#if defined __i386__ defined __OPTIMIZE__ !defined __SSP_ALL__ and pushed to git. Please add __PIC__ test. Do you see the failure with current git? I did __PIC__ test, it wroks for me... Yes, regular PIC and PIC+SSP now works. BUT, several other features do not. If I'm building with -fPIC -pg it instruments all C functions with profiler stuff which is called via PLT and causes EBX reloads -- crash -fno-omit-frame-pointer is sometimes useful for profiling too -- crash Also the upcoming -fsplit-stack will be broken by this too (that might need additional uclibc support though). And I'm pretty sure there's also other similar compiler features. There's no predefined #defines in gcc for any of these. What I'm trying to say that there are *numerous* situations when the compiler can create stack frame for you without you ever knowing it. And if you want to do a tail jump, you really should be doing it from .S file where you control fully the prologue/epilogue code. (GCC naked attribute does not seem to work on x86.) ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: [PATCH] libm/x86: use call instead of jump for wrappers
On 10/31/2010 08:57 AM, Timo Teräs wrote: Alternatively we could write the wrappers to cope with PIC properly and use the GCC attribute naked. Or write the wrappers as .S file. Or write the current assembly part correctly to use call: @@ -69,7 +71,7 @@ long double func##l(long double x) \ __asm ( \ fldt%1\n \ fstpl %1\n \ (Duh. Should have read this part to see that the floating point stuff is written back to stack and not just modified in ST(0)). So fix fstpl to push it proper position in stack. - jmp __stringify(__GI_##func) \n \ + call __stringify(__GI_##func) \n \ And add the stack pop here. : =t (st_top) \ : m (x) \ ); \ Assembly tail jump in middle of the code simply makes too many assumptions on how gcc works IMHO. The assembly block can make gcc generate all kind of interesting things depending on what the modifiers it has and what else the function is doing. My suggestion is: never do that. If you want to do it, use pure assembler function (in .S) then you control the full function. Otherwise it's bound to break someone's build because GCC assumes that execution returns to function after the assembly block. ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: Troubles with nptl on Geode
On 08/16/2010 04:00 PM, Pirmin Walthert wrote: I'll send more information as soon as I've collected them, what may take a few days as I'm quite busy this week. I've cross-compiled gdb now (and what I get is: #0 0xb7607343 in __pthread_mutex_cond_lock () from /lib/libpthread.so.0 #1 0x in ?? () Try the patch I sent earlier: http://lists.uclibc.org/pipermail/uclibc/2010-August/044250.html Someone should apply it. - Timo ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
[PATCH] nptl: fix calling convention for __pthread_mutex_cond_lock
The assembly versions of pthread_cond_wait calls __pthread_mutex_cond_lock and __pthread_mutex_cond_lock_adjust using internal calling convention (which differs from default calling convention at least on x86). Thus these two functions must be defined with internal_function or the call sequence goes wrong. __pthread_mutex_cond_lock resides in sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c, but it does evil macro definitions and includes pthread_mutex_lock.c, so we need to add some extra kludge to pthread_mutex_lock.c to get the prototypes correctly. Signed-off-by: Timo Teräs timo.te...@iki.fi --- libpthread/nptl/pthreadP.h |6 -- libpthread/nptl/pthread_mutex_lock.c |7 ++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/libpthread/nptl/pthreadP.h b/libpthread/nptl/pthreadP.h index 85601d4..c45bd11 100644 --- a/libpthread/nptl/pthreadP.h +++ b/libpthread/nptl/pthreadP.h @@ -414,8 +414,10 @@ extern int __pthread_mutex_trylock (pthread_mutex_t *_mutex); extern int __pthread_mutex_lock (pthread_mutex_t *__mutex); extern int __pthread_mutex_lock_internal (pthread_mutex_t *__mutex) attribute_hidden; -extern int __pthread_mutex_cond_lock (pthread_mutex_t *__mutex); -extern void __pthread_mutex_cond_lock_adjust (pthread_mutex_t *__mutex); +extern int __pthread_mutex_cond_lock (pthread_mutex_t *__mutex) + attribute_hidden internal_function; +extern void __pthread_mutex_cond_lock_adjust (pthread_mutex_t *__mutex) + attribute_hidden internal_function; extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex); extern int __pthread_mutex_unlock_internal (pthread_mutex_t *__mutex) attribute_hidden; diff --git a/libpthread/nptl/pthread_mutex_lock.c b/libpthread/nptl/pthread_mutex_lock.c index 78b6671..77147db 100644 --- a/libpthread/nptl/pthread_mutex_lock.c +++ b/libpthread/nptl/pthread_mutex_lock.c @@ -42,7 +42,11 @@ static int __pthread_mutex_lock_full (pthread_mutex_t *mutex) int +#ifdef NO_INCR +attribute_hidden internal_function +#else attribute_protected +#endif __pthread_mutex_lock ( pthread_mutex_t *mutex) { @@ -477,7 +481,8 @@ strong_alias (__pthread_mutex_lock, __pthread_mutex_lock_internal) #ifdef NO_INCR -void attribute_protected +void +attribute_hidden internal_function __pthread_mutex_cond_lock_adjust ( pthread_mutex_t *mutex) { -- 1.7.0.4 ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
[PATCH] nptl: fix x86 assembly PIC relocations
Unwind_Resume needs to be called via PLT. Most calls are already proper, this fix the remaining two problems. Signed-off-by: Timo Teräs timo.te...@iki.fi --- .../sysv/linux/i386/i486/pthread_cond_timedwait.S |2 +- .../unix/sysv/linux/i386/i486/pthread_cond_wait.S |2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S index 8a0c3fb..ac7983c 100644 --- a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S @@ -648,7 +648,7 @@ __condvar_tw_cleanup: movl%esi, (%esp) .LcallUR: - call_Unwind_Resume + call_unwind_res...@plt hlt .LENDCODE: cfi_endproc diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S index 006fc51..abc963f 100644 --- a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S @@ -535,7 +535,7 @@ __condvar_w_cleanup: movl%esi, (%esp) .LcallUR: - call_Unwind_Resume + call_unwind_res...@plt hlt .LENDCODE: cfi_endproc -- 1.7.0.4 ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
[PATCH] more workarounds for GCC PR32219
Commit 2e53dd645d5348f207cec7f8595969dc566c5a55 workarounds GCC bug when accessing _locale_init and _stdio_init. We need the same fix for __errno_location and __h_errno_location otherwise we crash calling null with static and non-threaded builds. Signed-off-by: Timo Teräs timo.te...@iki.fi --- libc/misc/internals/__uClibc_main.c |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libc/misc/internals/__uClibc_main.c b/libc/misc/internals/__uClibc_main.c index 44d1620..e8c470b 100644 --- a/libc/misc/internals/__uClibc_main.c +++ b/libc/misc/internals/__uClibc_main.c @@ -447,11 +447,11 @@ void __uClibc_main(int (*main)(int, char **, char **), int argc, * have resulted in errno being set nonzero, so set it to 0 before * we call main. */ -if (likely(__errno_location!=NULL)) +if (likely(not_null_ptr(__errno_location))) *(__errno_location()) = 0; /* Set h_errno to 0 as well */ -if (likely(__h_errno_location!=NULL)) +if (likely(not_null_ptr(__h_errno_location))) *(__h_errno_location()) = 0; #if defined HAVE_CLEANUP_JMP_BUF defined __UCLIBC_HAS_THREADS_NATIVE__ -- 1.7.0.4 ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: resolver broken in NPTL build
On 05/16/2010 07:00 AM, Denys Vlasenko wrote: On Wednesday 12 May 2010 09:32, Timo Teräs wrote: The combination of commit aab4df0fb51660300559f5f29290709db2f7bfee resolv.c: add support for per thread res_state commit cca45baf8353d1e338d232f5bdb2d1d6b357f1da /etc/resolv.conf: support timeout:n and attempts:n options .. and NPTL results in broken resolver in very annoying ways. Now, it seems that most of the uclibc code does not work well if res_state is TLS variable. Technically, this is the correct thing to do since this gives proper per-thread resolving behavior, and it also makes the config options overridable per thread. This probably what apps expect as glibc does it too. Do you have an example where per-threadness is used? I cannot really give any example immediately. But I still think we should stick to the per-threaded behavior. That is what the specifications say, and if we want to be specs compliant, _res needs to be in TLS. But alas, most places use _res to sync up static global variables which results in breakage. It gets more or less randomly selected which threads options get applied. Also in case of multiple servers it looks like the retry logic is shared between all threads, e.g. two concurrent resolutions can make other resolvers skip nameservers due to shared last_ns_num. I see. But still having the last_ns_num et al. as global, shared vars would probably be okay. And finally the timeout/attempts commit breaks the accumulated stuff horribly. What happens is: 1. multithreaded application startups, initializes resolver, resolves things just fine 2. resolv.conf gets changed, application calls res_init after res_init uclibc will call res_sync on all resolver functions to refresh globals from the TLS variable _res 3. res_init was called only in one thread, so other thread's _res contains all zeroes (yes, this is correct app usage: res_init should be called only from one thread) 4. threads not calling res_init get broken resolver due to timeout being set to zero Now, one proper solution would be to: 1. make __open_nameservers return the configuration options 2. pass the config options struct to res_sync_func so it can do the proper overrides from per-thread _res 3. remove the related globals and use locally config options from __open_nameservers But technically, the correct thing (as in glibc does this) is: - res_init increases global res_init timestamp - use _res (or pointer within there) for resolver retries etc. get proper per-thread behavior - resolvers functions call maybe_init which reinitialize the TLS'ed resolver state (e.g. reload resolv.conf) if their res_init timestamp is out dated It looks very complex. Can we just use a shared structure? That will be simple and small. Anyone objects to this? See above. I object having _res a global. Having the other stuff shared is ok. As an immediate emergency kludge fix, the following might do: resolv: fix options handling for TLS _res If _res is in TLS (NPTL), it might not get initialized. Assume zeroes mean default values. Signed-off-by: Timo Teräs timo.te...@iki.fi diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c index 320aec4..f8066d2 100644 --- a/libc/inet/resolv.c +++ b/libc/inet/resolv.c @@ -2916,8 +2916,8 @@ static void res_sync_func(void) __nameserver[n].sa4 = rp-nsaddr_list[n]; /* struct copy #endif } - __resolv_timeout = rp-retrans; - __resolv_attempts = rp-retry; + __resolv_timeout = rp-retrans ?: RES_TIMEOUT; + __resolv_attempts = rp-retry ?: RES_DFLRETRY; /* Extend and comment what program is known * to use which _res.XXX member(s). Comment why this is needed might be good. Isn't the commit log description enough? - Timo ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: [PATCH 1/2] static build: fix internal locking weaks to get pulled in always
On 05/16/2010 07:46 AM, Denys Vlasenko wrote: On Fri, May 7, 2010 at 4:19 PM, Timo Teras timo.te...@iki.fi wrote: Linker is smart and does not pull in weaks.os, ever. This happens because that compilation unit does not get strong references and ld eliminates dead code. We really need the weaks for static build in a compilation unit that is always there, otherwise it won't work. Signed-off-by: Timo Teras timo.te...@iki.fi Broke the build with attached .config: Bummer, I'll take a look at this first thing tomorrow. - Timo ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
resolver broken in NPTL build
The combination of commit aab4df0fb51660300559f5f29290709db2f7bfee resolv.c: add support for per thread res_state commit cca45baf8353d1e338d232f5bdb2d1d6b357f1da /etc/resolv.conf: support timeout:n and attempts:n options .. and NPTL results in broken resolver in very annoying ways. Now, it seems that most of the uclibc code does not work well if res_state is TLS variable. Technically, this is the correct thing to do since this gives proper per-thread resolving behavior, and it also makes the config options overridable per thread. This probably what apps expect as glibc does it too. But alas, most places use _res to sync up static global variables which results in breakage. It gets more or less randomly selected which threads options get applied. Also in case of multiple servers it looks like the retry logic is shared between all threads, e.g. two concurrent resolutions can make other resolvers skip nameservers due to shared last_ns_num. And finally the timeout/attempts commit breaks the accumulated stuff horribly. What happens is: 1. multithreaded application startups, initializes resolver, resolves things just fine 2. resolv.conf gets changed, application calls res_init after res_init uclibc will call res_sync on all resolver functions to refresh globals from the TLS variable _res 3. res_init was called only in one thread, so other thread's _res contains all zeroes (yes, this is correct app usage: res_init should be called only from one thread) 4. threads not calling res_init get broken resolver due to timeout being set to zero Now, one proper solution would be to: 1. make __open_nameservers return the configuration options 2. pass the config options struct to res_sync_func so it can do the proper overrides from per-thread _res 3. remove the related globals and use locally config options from __open_nameservers But technically, the correct thing (as in glibc does this) is: - res_init increases global res_init timestamp - use _res (or pointer within there) for resolver retries etc. get proper per-thread behavior - resolvers functions call maybe_init which reinitialize the TLS'ed resolver state (e.g. reload resolv.conf) if their res_init timestamp is out dated As an immediate emergency kludge fix, the following might do: resolv: fix options handling for TLS _res If _res is in TLS (NPTL), it might not get initialized. Assume zeroes mean default values. Signed-off-by: Timo Teräs timo.te...@iki.fi diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c index 320aec4..f8066d2 100644 --- a/libc/inet/resolv.c +++ b/libc/inet/resolv.c @@ -2916,8 +2916,8 @@ static void res_sync_func(void) __nameserver[n].sa4 = rp-nsaddr_list[n]; /* struct copy #endif } - __resolv_timeout = rp-retrans; - __resolv_attempts = rp-retry; + __resolv_timeout = rp-retrans ?: RES_TIMEOUT; + __resolv_attempts = rp-retry ?: RES_DFLRETRY; /* Extend and comment what program is known * to use which _res.XXX member(s). ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
[PATCH] libm/x86: use call instead of jump for wrappers
GCC can emit prologue/epilogue code for the functions in various different cases: - frame pointers - PIC build (to load ebx for indirect calls/jumps) - forced stack smashing protection If we used jump in such cases, we'd corrupt the call stack and crash. Signed-off-by: Timo Teräs timo.te...@iki.fi --- libm/ldouble_wrappers.c | 12 +++- 1 files changed, 7 insertions(+), 5 deletions(-) diff --git a/libm/ldouble_wrappers.c b/libm/ldouble_wrappers.c index 7d5af90..5b424dc 100644 --- a/libm/ldouble_wrappers.c +++ b/libm/ldouble_wrappers.c @@ -60,7 +60,9 @@ long long func##l(long double x) \ * The return value is returned in st(0) per ABI in both cases (returning * a long double or returning a double). So we can simply jump to func. * Using __GI_func in jump to make optimized intra-library jump. - * gcc will still generate a useless ret after asm. Oh well... + * + * We do need to use call (instead of tail jump) as gcc can create + * stack frame, and push/modify/pop ebx during PIC build. */ # define WRAPPER1(func) \ long double func##l(long double x) \ @@ -69,7 +71,7 @@ long double func##l(long double x) \ __asm ( \ fldt%1\n \ fstpl %1\n \ - jmp __stringify(__GI_##func) \n \ + call __stringify(__GI_##func) \n \ : =t (st_top) \ : m (x) \ ); \ @@ -82,7 +84,7 @@ int func##l(long double x) \ __asm ( \ fldt%1\n \ fstpl %1\n \ - jmp __stringify(__GI_##func) \n \ + call __stringify(__GI_##func) \n \ : =a (ret) \ : m (x) \ ); \ @@ -95,7 +97,7 @@ long func##l(long double x) \ __asm ( \ fldt%1\n \ fstpl %1\n \ - jmp __stringify(__GI_##func) \n \ + call __stringify(__GI_##func) \n \ : =a (ret) \ : m (x) \ ); \ @@ -108,7 +110,7 @@ long long func##l(long double x) \ __asm ( \ fldt%1\n \ fstpl %1\n \ - jmp __stringify(__GI_##func) \n \ + call __stringify(__GI_##func) \n \ : =A (ret) \ : m (x) \ ); \ -- 1.7.0.4 ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: alpine linux now officially uses uclibc with nptl
Carmelo AMOROSO wrote: On 5/5/2010 3:48 PM, Natanael Copa wrote: Last night we rebuild basicly all packages against uclibc with nptl which means that alpine linux (x86) now officially run uclibc with nptl. (first distro that does?) STLinux distro (www.stlinux.com) for SH4 from STMicroelectronics is running with uclibc-nptl since more than 2 years ;-) Emphasis was on *x86*. - Timo ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: [PATCH] nptl: proper soname handling
Rob Landley wrote: You're saying you want to support having two installations of uClibc the same system. Starting from separate dynamic linkers, and going through segregated library search paths. Because nothing says lightweight and embedded like installing two or three complete copies of your entire library search path side by side. What are you going to do about things like X11's libraries? Build that twice too? Along with zlib and openssl and whatever else the system needs? (Because it seems like you'd have to; how is shared library code calling into libc any different than an executable calling into libc? Either you have a stable ABI with glue code and a collection of version-annotated obsolete symbols to bind against, or you don't. When sizeof(sigset_t) changes, or you flip a config switch like UCLIBC_HAS_COMPAT_RES_STATE or UCLIBC_HAS_TM_EXTENSIONS or ipv6 or internationalization support... Well libSDL.so depends on libc (and librt, libpthread, libm...) just as much as /bin/ls does. It sonds like you're inviting users to experience the joy of _subtle_ bugs caused by library version skew. (And, of course, to post them to this mailing list...) Why are we opening this can of worms again? I missed a curve... No, the idea is not to have two versions installed all the time. The idea is to allow the coexistance temporarily while package manager is upgrading system. If we targeted flashable upgrade, then this would not be needed as everything would be updated in one go. If stuff is upgraded package at time, where libc is in one packages, and e.g. busybox in separate package, we do need temporarily to have two libc's if the ABI is incompatible. Otherwise the package manager would have to have lots of extra kludge for libc upgrade. After full dist upgrade the old libc should be gone, and new in place. But temporarily it needs to work so e.g. perl/bb/shells/whatever works while their libc is mismatching. And yes, it's not full solution. Deep library wise dependencies can be temporarily broken. And yes, we do need stable API for uclibc at some point. But since we don't have that yet, the temporary install of two libraries during upgrade is the best option. As conclusion was previously, it does not make sense to set ABI_VERSION due to gcc dynamic-linker issues. But it'll help distro which tries to keep compatibility on packages level (sets the dependencies right and wants to perform clean upgrades). ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: [PATCH] nptl: proper soname handling
Rob Landley wrote: No, the idea is not to have two versions installed all the time. The idea is to allow the coexistance temporarily while package manager is upgrading system. Isn't this what static linking is for? If we targeted flashable upgrade, then this would not be needed as everything would be updated in one go. Or the package manager would have to be statically linked? (Yeah there's some implementation details making sure the stuff it calls during its operation still works, too, changing the $PATH to point to a static busybox covers a multitude of sins...) And yes, it's not full solution. Deep library wise dependencies can be temporarily broken. And yes, we do need stable API for uclibc at some point. But since we don't have that yet, the temporary install of two libraries during upgrade is the best option. Or you could just statically link the package manager? Yes, static linking would be more bullet proof. But either the user, or the package manager needs jump through hoops in this case. There needs to be the static versions compiled, they need to get installed, then finally replaced with dynamic versions, etc. As conclusion was previously, it does not make sense to set ABI_VERSION due to gcc dynamic-linker issues. But it'll help distro which tries to keep compatibility on packages level (sets the dependencies right and wants to perform clean upgrades). *shrug* I'm not saying everyone needs to use this. I'm not asking support for this. I'm not even recommending this for anyone. I only want to do it myself, because it solves my immediate problems with less work and more user friendly way than static linking. The package manager is there to handle the other issues. ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: NPTL MIPS, current git head, programs block on startup
Andreas Schultz wrote: With the current git head (00891d9cf07efd992023f255164bba93d657ece4) NPTL no longer works on MIPS. It did work with a501a33e9761f32b3d38ab9f113892abe7cef3f1. The problem is somewhere in the _pthread_cleanup_push_defer: Program terminated with signal 5, Trace/breakpoint trap. #0 _pthread_cleanup_push_defer (buffer=value optimized out, routine=value optimized out, arg=value optimized out) at libpthread/nptl/forward.c:148 148 FORWARD2(_pthread_cleanup_push_defer, (gdb) bt #0 _pthread_cleanup_push_defer (buffer=value optimized out, routine=value optimized out, arg=value optimized out) at libpthread/nptl/forward.c:148 #1 0x2ac90ef0 in *__GI_openlog (ident=0x7fc74f48 hotplug, logstat=3, logfac=24) at libc/misc/syslog/syslog.c:176 #2 0x004027cc in main (argc=2, argv=0x7fc74454) at ctrl.c:932 It seems that it is stuck in a endless loop, where the FORWARD2 wrapper calls itself instead of the real implementation. Uh. Is the application linked against libc before libpthread? Check with ldd the order of how libraries are pulled in. Looking at init.c my best guess would be that .ptr__pthread_cleanup_push_defer should be initialized with __pthread_cleanup_push_defer and not with _pthread_cleanup_push_defer (two undelines instead of one). It's because MIPS ld.so is not supporting protected symbols yet. Mmm... Using the two underscore variant might help for immediate problems, but other things will broken unless protected symbols are implemented. Changing linking order of application to pull in libpthread first should fix it too. ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: NPTL MIPS, current git head, programs block on startup
Andreas Schultz wrote: 2010/4/27 Timo Teräs timo.te...@iki.fi: Andreas Schultz wrote: [...] Uh. Is the application linked against libc before libpthread? The application is not directly linked against libpthread, but one of the other libraries pulls it in. This has never worked on MIPS. Someone needs to implement the protected symbol support for mips ld.so. Check with ldd the order of how libraries are pulled in. Looking at init.c my best guess would be that .ptr__pthread_cleanup_push_defer should be initialized with __pthread_cleanup_push_defer and not with _pthread_cleanup_push_defer (two undelines instead of one). It's because MIPS ld.so is not supporting protected symbols yet. Mmm... Using the two underscore variant might help for immediate problems, but other things will broken unless protected symbols are implemented. The two underscore change alone is not sufficient, i have now managed to get it working with the attached patch. Everything seems to fine so far. Forgot to attach the patch? I learned the hard way that it's not easily doable without the protected symbols. Otherwise you easily mess up one of the weird linking scenarios or how libc-libpthread interacts. Changing linking order of application to pull in libpthread first should fix it too. I'll try that... Hacky solution for you is to add -lpthread for your main application. Proper solution is protected symbol support in ld.so. ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: NPTL MIPS, current git head, programs block on startup
Andreas Schultz wrote: 2010/4/27 Timo Teräs timo.te...@iki.fi: Andreas Schultz wrote: 2010/4/27 Timo Teräs timo.te...@iki.fi: Andreas Schultz wrote: [...] Uh. Is the application linked against libc before libpthread? The application is not directly linked against libpthread, but one of the other libraries pulls it in. This has never worked on MIPS. Someone needs to implement the protected symbol support for mips ld.so. Check with ldd the order of how libraries are pulled in. Looking at init.c my best guess would be that .ptr__pthread_cleanup_push_defer should be initialized with __pthread_cleanup_push_defer and not with _pthread_cleanup_push_defer (two undelines instead of one). It's because MIPS ld.so is not supporting protected symbols yet. Mmm... Using the two underscore variant might help for immediate problems, but other things will broken unless protected symbols are implemented. The two underscore change alone is not sufficient, i have now managed to get it working with the attached patch. Everything seems to fine so far. Forgot to attach the patch? ups, yes... This as such, will not fix all problems. All the symbols in the forwarding table need special attention. Currently all those symbols are marked with attribute_protected and it's expected that ld.so makes sure the libc counter parts do not override the libpthread internals. This currently works only on x86. I learned the hard way that it's not easily doable without the protected symbols. Otherwise you easily mess up one of the weird linking scenarios or how libc-libpthread interacts. mhh, there seem to be lots of protected symbols :-( Yes. I recently added those. Each function in the struct you are modifying is attribute_protected to make sure libpthread and libc interact properly under various circumstances. We could get away from using protected symbols if we renamed all those symbols to follow some rules. But attribute_hidden for easier at the time for me. Basically, all libpthread exported function would need to have internal libpthread used in the struct there, and then aliased to the exported name. Looking at the code, some of the symbols are done like that: - many pthread_* functions are referring to __pthread_* - many __pthread_* functions are referring to __pthread_*_internal BUT, some are just referring to the symbol with same name. This will break things without attribute_protected and ld.so support for it. Sadly, this has never worked properly. I may have renamed the two symbols involved for symmetry before fully understanding how the beast worked. But now it gives a good indication that there's a problem instead of breaking in subtle ways later. Also, using protected symbols is slightly better since it produces smaller libraries. It generates less symbols. Changing linking order of application to pull in libpthread first should fix it too. I'll try that... Hacky solution for you is to add -lpthread for your main application. Proper solution is protected symbol support in ld.so. Does linking the main binary to -lpthread fix the problem? ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: [PATCH] ldso/x86_64: support protected symbols
Roman I Khimov wrote: Fixes dltest with NPTL. Signed-off-by: Roman I Khimov khi...@altell.ru --- ldso/ldso/x86_64/elfinterp.c | 10 -- 1 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ldso/ldso/x86_64/elfinterp.c b/ldso/ldso/x86_64/elfinterp.c index 54528d3..ec53c48 100644 --- a/ldso/ldso/x86_64/elfinterp.c +++ b/ldso/ldso/x86_64/elfinterp.c @@ -172,7 +172,9 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, symbol_addr = 0; symname = strtab + sym-st_name; - if (symtab_index) { + if (symtab_index + (ELF64_ST_VISIBILITY(symtab[symtab_index].st_other) +!= STV_PROTECTED)) { symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt, elf_machine_type_class(reloc_type), tls_tpnt); /* @@ -189,7 +191,11 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, /* Relocs against STN_UNDEF are usually treated as using a * symbol value of zero, and using the module containing the * reloc itself. */ - symbol_addr = sym-st_value; + if (symtab_index) + symbol_addr = DL_FIND_HASH_VALUE(tpnt, elf_machine_type_class(reloc_type), +sym); + else + symbol_addr = sym-st_value; tls_tpnt = tpnt; } Joakim had a clean up patch for the above construct. See patch 1/2 of: http://lists.uclibc.org/pipermail/uclibc/2010-April/043840.html (patch 2/2 there is wrong). See also rest of the thread. For some reason that did not got merged yet. Austin, care to merge that? But otherwise looks good. - Timo ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: various nptl patches
Joakim Tjernlund wrote: Timo Teräs timo.te...@gmail.com wrote on 2010/04/17 12:09:22: Joakim Tjernlund wrote: Finally looked at the ldso patch and I am not entirely happy with it. I think the general structure should be different to make it easier to follow the code and port it to other archs. I can probably take a stab at it during the weekend but I have no env. to test in so I will have to do it blindly. So this is what I came up with. I do wonder if not linux_resolver need PROTECTED support too? Have you tested with LAZY relocation too? Have not tested lazy yet. The LAZY relocs is a bigger problem though. That has to work so it would be great if you could test that too. Hi Timo, did you get a chance to test LAZY relocs too? Now that NPTL is in main line it would be good to know if PROTECTED works as is or if more work is needed. Tested them now. LAZY works as expected too. - Timo ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: [PATCH] nptl: proper soname handling
Austin Foxley wrote: On 04/20/2010 07:49 AM, Natanael Copa wrote: Since sublevel releases are not ABI compatible we need to adjust the soname to include the sublevel version. This makes it possible to install ABI incompatible versions of the library side by side so clean upgrades are possible. Applied, minus the mistaken LDFLAGS hunk It might be useful to do: -ABI_VERSION := $(VERSION) +ABI_VERSION := $(MAJOR_VERSION) Since it seems that ld.so soname is hardcoded in GCC. If you want to use something else than /lib/ld-uClibc.so.0 as dynamic linker, you also need to update GCC default configration, create alternate specfile overriding the hardcoded -dynamic-linker, or pass-in -Wl,-dynamic-linker,... when compiling. Otherwise you end up with broken stuff. I'm thinking it might be better if the distro maintainer overrides ABI_VERSION and gcc together so gcc with default options will produce working binaries. - Timo ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: [PATCH] nptl: proper soname handling
Austin Foxley wrote: On 04/23/2010 07:18 AM, Timo Teräs wrote: Austin Foxley wrote: On 04/20/2010 07:49 AM, Natanael Copa wrote: Since sublevel releases are not ABI compatible we need to adjust the soname to include the sublevel version. This makes it possible to install ABI incompatible versions of the library side by side so clean upgrades are possible. Applied, minus the mistaken LDFLAGS hunk It might be useful to do: -ABI_VERSION := $(VERSION) +ABI_VERSION := $(MAJOR_VERSION) Since it seems that ld.so soname is hardcoded in GCC. If you want to use something else than /lib/ld-uClibc.so.0 as dynamic linker, you also need to update GCC default configration, create alternate specfile overriding the hardcoded -dynamic-linker, or pass-in -Wl,-dynamic-linker,... when compiling. Hmm, I didn't realize GCC hardcoded that. I'll push a fix. Me neither. Actually the dynamic section is generated properly. It's the .interp section that goes wrong. And I didn't notice that until trying to run things side-by-side where ld-uClibc.so.0 and ld-uClibc.so.0.9.32 did not refer to same file. ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: [PATCH] nptl: proper soname handling
Michael Deutschmann wrote: On Tue, 20 Apr 2010, Natanael Copa wrote: Since sublevel releases are not ABI compatible we need to adjust the soname to include the sublevel version. I see two reasons that this would be pointless. First, you'd need more than a more precise statement of the uClibc source version, because with uClibc, a single version of the source can produce many different ABI-incompatible libc.so.0 files. Yes, this does not help on building universal side-by-side thing. But within one distribution you generally want to keep the ABI compatible. This really is configuration management issue, and doable inside a single distribution. Second, sonames don't really help with the C library, because every other shared library on a system is linked to the C library. The differences in the C library often distort the ABI of these other libraries. It's very complicated to keep appropriate versions side-by-side because the soname of the other shared libraries does not change. In the case where the C library change doesn't outright break the other shared libraries, changing the soname makes it worse because an application can end up loading two different C libraries at once -- one through it's own DT_NEEDED, and one through the DT_NEEDED on another shared library. Again. This is configuration management issue. The distribution build system and package manager need to take special precaution here to not create binary packages ultimately depending on two different ABI versions of same package. The patch is still useful, as it makes ABI_VERSION configurable so each builder can define their ABI_VERSION something that makes sense to them. This is not a universal solution for all, but a step to right direction and helps a lot of distribution maintainer who would like to have a clean upgrade path. So IMHO the soname makes sense. ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: [PATCH] nptl: proper soname handling
Michael Deutschmann wrote: On Thu, 22 Apr 2010, Natanael Copa wrote: Do you have any better suggestions how to upgrade a running system? First, build the new uClibc, but don't install it yet. Build a customized ld-uclibc.so.0, from the previous uClibc source, that looks in a different place for shared libraries and ignores the /etc/ld.so.* files. Install it under a different filename. So for each transition X - Y you need both X and Y versions recompiled. If you want upgrade from n+1 different versions, you need to do work n times. Write a utility to modify the INTERP filename specified in an executable from /lib/ld-uclibc.so.0 to the filename of the special ld.so. (This is much simpler if the temporary ld.so filename is the same length as the original.) Hardlink the existing shared libraries into the alternate position, then hack every existing installed executable in this way. This means you need to mangle existing binaries?! This invalidates lot of package manager features. It also means that the running system cannot be reproduced from packages. Then, delete all the old libraries in /usr/lib and the include files. The shared libraries will be preserved by the hardlink, while everything else is dispensible. The system should still work for everything except compilation. Now, install the new uClibc. Unless the ABI is so thoroughly broken as to invalidate the old specs or libgcc.a, you should now be able to compile new binaries. I intend to do something like this for my 0.9.30.3 to 0.9.31 rollover, but I haven't finished writing the necessary utilities yet. Honestly. I still think it's less work to track the config, change ABI_VERSION when the ABI breaks, and make binary packages in a way that it depends only on packages using same libc ABI. This is fairly easily scriptable on any sane build system. You also get more or less free the fact that you can upgrade from any previous version. But as mentioned, it works only when making sure that the ABI_VERSION is maintained properly. Since uclibc provides currently no ABI stability the distribution maintainers can ensure that this holds true. - Timo ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
another set of nptl patches
This should make things work even if application not using libpthread dlopen():s a library pulling in libpthread. Also some minor other fixes. From 73e70c465830884b98d5036cee0f47b8c77ba07e Mon Sep 17 00:00:00 2001 From: =?utf-8?q?Timo=20Ter=C3=A4s?= timo.te...@iki.fi Date: Thu, 22 Apr 2010 05:41:17 + Subject: [PATCH 1/5] nptl: fix malloc library locking MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Update malloc library to use internal uclibc locking primitives to get the libpthread calls correct. Signed-off-by: Timo Teräs timo.te...@iki.fi --- libc/stdlib/malloc/heap.h |7 +++ libc/stdlib/malloc/malloc.h | 11 +-- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/libc/stdlib/malloc/heap.h b/libc/stdlib/malloc/heap.h index c0c5df8..3038079 100644 --- a/libc/stdlib/malloc/heap.h +++ b/libc/stdlib/malloc/heap.h @@ -16,11 +16,10 @@ /* On multi-threaded systems, the heap includes a lock. */ #ifdef __UCLIBC_HAS_THREADS__ -# include pthread.h -# include bits/uClibc_pthread.h +# include bits/uClibc_mutex.h # define HEAP_USE_LOCKING -# define __heap_lock(heap_lock) __pthread_mutex_lock (heap_lock) -# define __heap_unlock(heap_lock) __pthread_mutex_unlock (heap_lock) +# define __heap_lock(heap_lock) __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE(*(heap_lock)) +# define __heap_unlock(heap_lock) __UCLIBC_MUTEX_UNLOCK_CANCEL_UNSAFE(*(heap_lock)) #else # define __heap_lock(heap_lock) # define __heap_unlock(heap_lock) diff --git a/libc/stdlib/malloc/malloc.h b/libc/stdlib/malloc/malloc.h index 2afc3a8..0a4b43b 100644 --- a/libc/stdlib/malloc/malloc.h +++ b/libc/stdlib/malloc/malloc.h @@ -132,13 +132,12 @@ extern int __malloc_mmb_debug; /* Locking for multithreaded apps. */ #ifdef __UCLIBC_HAS_THREADS__ -# include pthread.h -# include bits/uClibc_pthread.h +# include bits/uClibc_mutex.h # define MALLOC_USE_LOCKING -typedef pthread_mutex_t malloc_mutex_t; -# define MALLOC_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER +typedef __UCLIBC_MUTEX_TYPE malloc_mutex_t; +# define MALLOC_MUTEX_INIT __UCLIBC_MUTEX_INITIALIZER # ifdef MALLOC_USE_SBRK /* This lock is used to serialize uses of the `sbrk' function (in both @@ -146,8 +145,8 @@ typedef pthread_mutex_t malloc_mutex_t; things will break if these multiple calls are interleaved with another thread's use of sbrk!). */ extern malloc_mutex_t __malloc_sbrk_lock; -# define __malloc_lock_sbrk() __pthread_mutex_lock (__malloc_sbrk_lock) -# define __malloc_unlock_sbrk() __pthread_mutex_unlock (__malloc_sbrk_lock) +# define __malloc_lock_sbrk() __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE (__malloc_sbrk_lock) +# define __malloc_unlock_sbrk() __UCLIBC_MUTEX_UNLOCK_CANCEL_UNSAFE (__malloc_sbrk_lock) # endif /* MALLOC_USE_SBRK */ #else /* !__UCLIBC_HAS_THREADS__ */ -- 1.6.3.3 From 0c701f4fcdda60b7abd5e02c74d35dd7127ff773 Mon Sep 17 00:00:00 2001 From: =?utf-8?q?Timo=20Ter=C3=A4s?= timo.te...@iki.fi Date: Thu, 22 Apr 2010 05:43:00 + Subject: [PATCH 2/5] nptl: fix warnings of shadowing __self MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Stdio locking macroes do: void *__self = THREAD_SELF; But THREAD_SELF uses __self also internally which causes shadowing warnings. Just rename the outer variable for now. Might be an idea to convert the macroes to static inline functions. Signed-off-by: Timo Teräs timo.te...@iki.fi --- libpthread/nptl/sysdeps/pthread/bits/stdio-lock.h | 12 ++-- 1 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libpthread/nptl/sysdeps/pthread/bits/stdio-lock.h b/libpthread/nptl/sysdeps/pthread/bits/stdio-lock.h index b8efdd8..3437e61 100644 --- a/libpthread/nptl/sysdeps/pthread/bits/stdio-lock.h +++ b/libpthread/nptl/sysdeps/pthread/bits/stdio-lock.h @@ -39,11 +39,11 @@ typedef struct { int lock; int cnt; void *owner; } _IO_lock_t; #define _IO_lock_lock(_name) \ do { \ -void *__self = THREAD_SELF; \ -if ((_name).owner != __self) \ +void *__meself = THREAD_SELF; \ +if ((_name).owner != __meself) \ { \ lll_lock ((_name).lock, LLL_PRIVATE); \ -(_name).owner = __self; \ +(_name).owner = __meself; \ } \ ++(_name).cnt; \ } while (0) @@ -51,12 +51,12 @@ typedef struct { int lock; int cnt; void *owner; } _IO_lock_t; #define _IO_lock_trylock(_name) \ ({ \ int __result = 0; \ -void *__self = THREAD_SELF; \ -if ((_name).owner != __self) \ +void *__meself = THREAD_SELF; \ +if ((_name).owner != __meself) \ { \ if (lll_trylock ((_name).lock) == 0) \ { \ -(_name).owner = __self; \ +(_name).owner = __meself; \
Re: [PATCH] nptl: proper soname handling
Michael Deutschmann wrote: On Thu, 22 Apr 2010, Timo wrote: This really is configuration management issue, and doable inside a single distribution. I don't understand what configuration management means. Perhaps this is why I don't quite get you and Natanael... It means the system used to build all packages, is aware of the multiple versions of libc it has had. It means it also makes sure the produced binaries are only linked against one version of libc, and marks the binary package dependencies so that the package manager can ensure that all dependency libraries depend on same version of libc. Thus producing a runnable application. Basically, my point is that in general, changing the soname is only of value to enable side-by-side. But in the case of the C library itself, changing the soname is far from sufficent, because there is no easy way to modify the sonames of every dependent shared library (ncurses, readline, bfd) so as to avoid collision. You are right. It is the package managers responsibility to make sure that there is no such conflicts. The distinction between libc.so.6 (Glibc) and libc.so.0 just barely works, and only because of special magic in ldconfig. If you want to support a libc.so.0 to libc.so.0.1 rollover in the same way, you'll need to also add LIB_ELF_LIBC0_1 to ldso/include/dl-defs.h, and then ring the changes through ld.so and ldconfig. Why? This only needed for ldso cache. It would seem that these magics are only used to see if the application is incorrectly linked against different libc versions. It is probably mostly needed for the multilib stuff where you have 32- and 64-bit libraries installed on same system. I don't see any immediate problem with mapping libc.so.0* to LIB_ELF_LIBC0 because in addition to the flag field also the soname is compared. If the package manager / build system ensures proper dependencies, the soname is sufficient. If ldso cache is turned off, this stuff is not even used at all. But yes, the ld cache is not working exactly right now. It maps the libc with long soname now to LIB_ELF. Everything will work, it just will not emit the warning if linked against e.g. libc0 and libc6. (Seeing as uClibc fans usually compile everything locally, and only need side-by-side at the moment of rollover, I'd add a single LIB_ELF_OLD_UC flags, and provide a utility to mark every binary on a system as OLD to ld.so and ldconfig. Rather than an endless LIB_ELF_LIBC0_1, LIB_ELF_LIBC0_2, ... until the type field overflows This would suffice so long as every old-ABI program gets recompiled before the next ABI break) It occurs to me that what you might want is not side-by-side, but self-identification of executables. So that if you run into some old forgotten binaries, you can guess what version of uClibc they were meant for. But that can be dealt with in other ways, such as the ABI tag note that glibc uses. Well, ABI tag would be useful to double check that the build system produced valid dependencies. But changing soname in controlled manner should suffice. ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
[patch] nptl: remove unneeded libc-lock.h include
I semi-accidentally added include for libc-lock.h because the intention was to use locking macroes from there. However, we ended up using using the weak alias stuff. This is additionally good since now this can result in compile errors like: In file included from /toolchain/include/bits/uClibc_mutex.h:16, from /toolchain/include/bits/uClibc_stdio.h:107, from /toolchain/include/stdio.h:72, from /work/freetype-2.3.11/include/freetype/config/ftstdlib.h:100, from ./builds/unix/ftconfig.h:43, from builds/unix/ftsystem.c:21: /toolchain/include/bits/libc-lock.h:309: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'void' Remove the unneeded include causing breakage. Reported-by: Kevin Day thekevin...@gmail.com Signed-off-by: Timo Teräs timo.te...@iki.fi diff --git a/libc/sysdeps/linux/common/bits/uClibc_mutex.h b/libc/sysdeps/linux /common/bits/uClibc_mutex.h index 02bcc72..6d004bb 100644 --- a/libc/sysdeps/linux/common/bits/uClibc_mutex.h +++ b/libc/sysdeps/linux/common/bits/uClibc_mutex.h @@ -13,7 +13,6 @@ #ifdef __UCLIBC_HAS_THREADS__ #include pthread.h -#include bits/libc-lock.h #include bits/uClibc_pthread.h #define __uclibc_maybe_call(FUNC, ARGS) \ ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: [patch] nptl: remove unneeded libc-lock.h include
Carmelo AMOROSO wrote: On 4/20/2010 10:59 AM, Timo Teräs wrote: Remove the unneeded include causing breakage. -#include bits/libc-lock.h I guess this is required for STDIO_FUTEXES, or am I wrong ? Not needed. If STDIO_FUTEXES is defined, the file includes later on bits/stdio-lock.h which ends up including the libc-lock.h. ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: [patch] nptl: remove unneeded libc-lock.h include
Laurent Bercot wrote: -#include bits/libc-lock.h I guess this is required for STDIO_FUTEXES, or am I wrong ? Not needed. If STDIO_FUTEXES is defined, the file includes later on bits/stdio-lock.h which ends up including the libc-lock.h. ok, that's fine. Not wanting to interfere, but shouldn't including an unneeded .h file be totally harmless? Shouldn't .h files be independent, self-contained entities that declare certain symbol and macros and don't break, just declare too much, if you include more than is necessary? Or should this only be guaranteed only for public .h files designed to be used by applications, while internal libc headers can do some black voodoo? Sounds kinda brittle and hard to maintain if it's the case. Yes, that's what I was assuming too. But it looks like libc-lock.h is taken from glibc, and never really ported to uclibc properly. In matter of fact, many sysdeps headers are like that. Some are even in uclibc, but never used. Some should clean up the headers. But it's slightly complicated. Especially if you want some easy way to sync with glibc. This patch just reverts the immediate damage I introduced. But yes, someone should fix up the headers properly. - Timo ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: uClibc_mutex.h and libc-lock.h
Kevin Day wrote: Apparently with freetype, including #include bits/libc-lock.h causes compile time errors. The error has something to do with line 309 of bits/libc-lock.h where the function __libc_cleanup_routine gets defined. I simply commented out #include bits/libc-lock.h from uClibc_mutex.h and freetype compiled properly. I had related problems with compiling gettext as well but was able to work around that. The commit is: http://git.uclibc.org/uClibc/commit/?h=nptlid=0eadd98d30c51d26fde4062e6b8c48f3c9b5148d The error was: In file included from /toolchain/include/bits/uClibc_mutex.h:16, from /toolchain/include/bits/uClibc_stdio.h:107, from /toolchain/include/stdio.h:72, from /work/freetype-2.3.11/include/freetype/config/ftstdlib.h:100, from ./builds/unix/ftconfig.h:43, from builds/unix/ftsystem.c:21: /toolchain/include/bits/libc-lock.h:309: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'void' Hmmh. Seems like I added that semi-incidentally. I was thinking of using the glibc used libc locking macroes from libc-lock.h, but ended up using the weak definitions. I think the whole uClibc_mutex.h should not be included (or ifdeffed out) if we are not building libc. I guess the lock definition defines are needed in public, headers; but at least the function macroes should not be visible to applications. Just removing the include should be ok though. But I suspect you might get similar errors if you have the __USE_STDIO_FUTEXES__ defined, which you probably should have enabled if you are using nptl. Seems like we need to sprinkle some #ifdef _LIBC's. - Timo ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: various nptl patches
Joakim Tjernlund wrote: Austin Foxley wrote: On 04/16/2010 07:37 AM, Timo Teräs wrote: We'll need to patch all the other arch's ldso as well to handle protected symbols, but I'll apply this for now. If I'm not mistaken, other archs will be no worse off than they are now in this situation. Right? Right. It makes things slightly better for other archs too, but in practice it won't work until they support protected symbols too. Finally looked at the ldso patch and I am not entirely happy with it. I think the general structure should be different to make it easier to follow the code and port it to other archs. I can probably take a stab at it during the weekend but I have no env. to test in so I will have to do it blindly. Ok. I'm not too familiar with the ldso internals and structure, so that was just the immediate fix I came up with. I can test whatever you come up with on x86. Thanks! ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: various nptl patches
Joakim Tjernlund wrote: Finally looked at the ldso patch and I am not entirely happy with it. I think the general structure should be different to make it easier to follow the code and port it to other archs. I can probably take a stab at it during the weekend but I have no env. to test in so I will have to do it blindly. So this is what I came up with. I do wonder if not linux_resolver need PROTECTED support too? Have you tested with LAZY relocation too? Have not tested lazy yet. --- a/ldso/ldso/i386/elfinterp.c +++ b/ldso/ldso/i386/elfinterp.c @@ -175,11 +175,16 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, symbol_addr = 0; symname = strtab + symtab[symtab_index].st_name; - if (symtab_index - (ELF32_ST_VISIBILITY(symtab[symtab_index].st_other) -!= STV_PROTECTED)) { - symbol_addr = (unsigned long)_dl_find_hash(symname, scope, tpnt, - elf_machine_type_class(reloc_type), tls_tpnt); + if (symtab_index) { + if (ELF32_ST_VISIBILITY(symtab[symtab_index].st_other) + != STV_PROTECTED) + symbol_addr = (unsigned long)_dl_find_hash(symname, scope, + tpnt, + elf_machine_type_class(reloc_type), + tls_tpnt); + else + symbol_addr = DL_FIND_HASH_VALUE(tpnt, elf_machine_type_class(reloc_type), +symtab[symtab_index]); /* * We want to allow undefined references to weak symbols - this @@ -190,11 +195,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) return 1; } else { - if (symtab_index) - symbol_addr = DL_FIND_HASH_VALUE(tpnt, elf_machine_type_class(reloc_type), -symtab[symtab_index]); - else - symbol_addr = symtab[symtab_index].st_value; + symbol_addr = symtab[symtab_index].st_value; tls_tpnt = tpnt; } This looks functionally equivalent. And yes, looks like this is more consistent approach. Related, I noticed that _dl_lookup_hash that uses DL_FIND_HASH_VALUE does actually first a check for TLS symbols: if ELF_ST_TYPE(sym-st_info) == STT_TLS the DL_FIND_HASH_VALUE is never called. I would suspect that protected TLS symbols are broken currently. Maybe all this should be split into some new function? diff --git a/ldso/ldso/i386/elfinterp.c b/ldso/ldso/i386/elfinterp.c index 7e05c14..b04febc 100644 --- a/ldso/ldso/i386/elfinterp.c +++ b/ldso/ldso/i386/elfinterp.c @@ -194,11 +194,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, if (unlikely(!symbol_addr (ELF_ST_TYPE(symtab[symtab_index].st_info) != STT_TLS) ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) return 1; - } else { - symbol_addr = symtab[symtab_index].st_value; - tls_tpnt = tpnt; } - This part was added as part of support for TLS symbols. Other parts of dlso doing the same thing have comment such as: /* Relocs against STN_UNDEF are usually treated as using a symbol value of zero, and using the module containing the reloc itself. */ Austin, since you did 534661b9 adding this, could you explain why this is needed? Looking also */elfinterp.c, there seems to be a lot of common code. I wonder if these could be merged somehow. ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: various nptl patches
Timo Teräs wrote: The whole __GI_ aliasing thingy on libc side is a bit weird still. I wonder if we could remove all that and just use the proper visibility attributes. But I guess that's another story. Oh well. At least nptl on x86 is starting to get to usable state now. There will be still problems application without libpthread goes and dlopen()'s a library loading libpthread. But that's easily fixable by just linking the main app to libpthread. I was thinking about how glibc gets away with this. Apparently libc-lock.h does some deep voodoo on what kind of locking primitives it chooses for each library. It looks like libc and libpthread end up always using the low level lock stuff directly lll_*. And for the remaining libpthread entries the libc ends up calling libpthread always via the ptf (the pthread function pointers struct). Thus libc should not be using the weak symbol magic at all. This seems to be the only way to make libc call the actual libpthread functions if it's dlopen()'ed later. Also, it would appear that libpthread needs additional fixing to initialize itself in case it's dlopen loaded. I also remember there's some ldso flags that make libpthread permanent so it won't get unloaded when the last library requiring it gets dlclosed. So I guess we need another stab on fixing libc-lock for uclibc. I might take a look at this next week if there's nothing else strange in the current tree. The previous patches are still needed though. Otherwise the main application can get wrong symbols depending on various things. The protected patches especially are important as some of the forwarding stubs have same name as the pthread implementation it forwards to (the actual name used in ptf struct initialization). This whole libc-libpthread interdependency and making libc run without libpthread seems pretty complicated, and misunderstood previously. Especially since the normal symbol vs. weak symbol semantics have changed (do note: it seems that strong symbol as concept seems to have been deprecated; apparently the consensus is that even if it sounds good idea, it's bound to cause more confusion and mistakes and non-consistent behaviour than solving problems). I guess we need a document, or at least some comments on how all this is supposed to be working. ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: nptl: mark symbols with libc forwarder hidden
Austin Foxley wrote: On 04/14/2010 10:01 AM, Timo Teräs wrote: Add attribute_hidden to all symbols having libc forwarder. This prevents recursive self calls which would happen if libc is before libpthread in linking order: the forwarder functions would call itself via the function table, since the libpthread symbols would get overwritten with libc ones. This has not been a problem in glibc since there these symbols are marked hidden with linker version-script. Since we don't use one, we need to mark these explicitly. Signed-off-by: Timo Teräs timo.te...@iki.fi This looks like what we want. I'll apply this. Hum. Actually looks like this is not right either. It appears that there's several different ways how the pthreads mutexes are called from libc. Previously uclibc had these: 1. internal libc locking: seems to resolve to use the internal __pthread_mutex_* weaks defined for__pthread_* in libc/misc/pthread/weaks.c to give dummy functions if linked statically or without libpthread 2. pthread_* forwarding for applications so single/multithread libs can link to basic pthreads stuff without libpthread; it uses the pthread_functions forwarding stubs in thread implementation specific forwarders.c 3. stdio locking that uses futexes (from nptl headers), or revers to #1 style locking However, (1) will never work properly. The reason is that weak vs. strong aliases are not resolved dynamically. If ld.so picks the weak definition from libc first (e.g. -lc before -lpthread), you end up using the libc version. (Only glibc ever had dynamic weak resolution, meaning strong alias from later library would override weak alias; but this behaviour was reverted as it was considered bad. It's still doable by setting LD_DYNAMIC_WEAK=1). Now, glibc seems to do (1) as follows: 1. define *protected* versions of __pthread_* from libpthread, so libpthread will use them always, but also exports (at least subset of them) 2. libc has *weak definition in headers* of __pthread_* causing the references to be weak, and linking succeed even if __pthread_* symbols are not present 3. it uses __libc_maybe_call to first check if the function symbol is null, and if not then calls it I think we should the same as glibc, by converting uClibc_mutex.h to use libc-lock.h from threading implementation. Sounds reasonable? ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: nptl: mark symbols with libc forwarder hidden
Joakim Tjernlund wrote: Austin Foxley wrote: On 04/14/2010 10:01 AM, Timo Teräs wrote: Hum. Actually looks like this is not right either. It appears that there's several different ways how the pthreads mutexes are called from libc. Previously uclibc had these: 1. internal libc locking: seems to resolve to use the internal __pthread_mutex_* weaks defined for__pthread_* in libc/misc/pthread/weaks.c to give dummy functions if linked statically or without libpthread 2. pthread_* forwarding for applications so single/multithread libs can link to basic pthreads stuff without libpthread; it uses the pthread_functions forwarding stubs in thread implementation specific forwarders.c 3. stdio locking that uses futexes (from nptl headers), or revers to #1 style locking However, (1) will never work properly. The reason is that weak vs. strong aliases are not resolved dynamically. If ld.so picks the weak definition from libc first (e.g. -lc before -lpthread), you end up using the libc version. Is this a big problem? To me this looks like an error in the app and the link order should be fixed there. It just isn't possible always easily. This also hits the case if libpthread gets pulled in by dependency library and not by the main app. (Only glibc ever had dynamic weak resolution, meaning strong alias from later library would override weak alias; but this behaviour was reverted as it was considered bad. It's still doable by setting LD_DYNAMIC_WEAK=1). Now, glibc seems to do (1) as follows: 1. define *protected* versions of __pthread_* from libpthread, so libpthread will use them always, but also exports (at least subset of them) 2. libc has *weak definition in headers* of __pthread_* causing the references to be weak, and linking succeed even if __pthread_* symbols are not present 3. it uses __libc_maybe_call to first check if the function symbol is null, and if not then calls it I think we should the same as glibc, by converting uClibc_mutex.h to use libc-lock.h from threading implementation. I don't think ld.so supports PROTECTED syms yet(unless someone added these lately) Shouldn't be too hard to add I guess. Isn't protected: define symbol as global, but generate local non-overridable relocations. Thus it's just code generation change compared to hidden visibility. Not entirely sure about this, though. But I think it should just work. ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: nptl: mark symbols with libc forwarder hidden
Joakim Tjernlund wrote: Timo Teräs timo.te...@gmail.com wrote on 2010/04/16 10:00:59: Joakim Tjernlund wrote: Austin Foxley wrote: On 04/14/2010 10:01 AM, Timo Teräs wrote: Hum. Actually looks like this is not right either. It appears that there's several different ways how the pthreads mutexes are called from libc. Previously uclibc had these: 1. internal libc locking: seems to resolve to use the internal __pthread_mutex_* weaks defined for__pthread_* in libc/misc/pthread/weaks.c to give dummy functions if linked statically or without libpthread 2. pthread_* forwarding for applications so single/multithread libs can link to basic pthreads stuff without libpthread; it uses the pthread_functions forwarding stubs in thread implementation specific forwarders.c 3. stdio locking that uses futexes (from nptl headers), or revers to #1 style locking However, (1) will never work properly. The reason is that weak vs. strong aliases are not resolved dynamically. If ld.so picks the weak definition from libc first (e.g. -lc before -lpthread), you end up using the libc version. Is this a big problem? To me this looks like an error in the app and the link order should be fixed there. It just isn't possible always easily. That can't be a big deal, feels like a bug in the app that should/could be fixed. This also hits the case if libpthread gets pulled in by dependency library and not by the main app. But this is a bigger concern. Is this supposed to work or is it an glibc extension? Both of the cases work on glibc, because it sets the symbol visibility correctly, and also uses the weak symbols in correct way. We would not even need to whole 'forwarding' stuff at all if could trust that libpthread was always linked before libc. The sole purpose of forwarders is to have strongs versions of these symbols in libpthread, and weak ones in libc. It may have been doable before via strongs/weak alias thingy. But it's not doable anymore since LD_DYNAMIC_WEAK is off by default. The other part is how the internatl __pthread_* is handled. And glibc does this right by using weak references from libc, and defining them only in libpthread. This way libc gets null pointers if libpthread is not pulled in. And this is what we should do too. (Only glibc ever had dynamic weak resolution, meaning strong alias from later library would override weak alias; but this behaviour was reverted as it was considered bad. It's still doable by setting LD_DYNAMIC_WEAK=1). Now, glibc seems to do (1) as follows: 1. define *protected* versions of __pthread_* from libpthread, so libpthread will use them always, but also exports (at least subset of them) 2. libc has *weak definition in headers* of __pthread_* causing the references to be weak, and linking succeed even if __pthread_* symbols are not present 3. it uses __libc_maybe_call to first check if the function symbol is null, and if not then calls it I think we should the same as glibc, by converting uClibc_mutex.h to use libc-lock.h from threading implementation. I don't think ld.so supports PROTECTED syms yet(unless someone added these lately) Shouldn't be too hard to add I guess. Isn't protected: define symbol as global, but generate local non-overridable relocations. Thus it's just code generation change compared to hidden visibility. Not entirely sure about this, though. But I think it should just work. Ah, like LD option -Bsymbolic does? That is library wide so one has to find some __attribute__ that operates on a single symbol. Yes. Exactly that. It's __attribute__(( visibility(protected) )). Or .protected for asm. I'm doing a patch on this right now. http://www.ohse.de/uwe/articles/gcc-attributes.html#func-visibility ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: nptl: mark symbols with libc forwarder hidden
Joakim Tjernlund wrote: Yes. Exactly that. It's __attribute__(( visibility(protected) )). Or .protected for asm. I'm doing a patch on this right now. http://www.ohse.de/uwe/articles/gcc-attributes.html#func-visibility But this is PROTECTED and you might need to impl. STB_PROTECTED in ldso That should be STV_PROTECTED to support it. I once looked at that when I was hacking ldso in uClibc some years ago but I don't remember the details any more. Ah, you're right. It does need ld.so support. I'll try to figure out if it's easy to implement, or if we get away with some linker flags. ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: nptl: mark symbols with libc forwarder hidden
Timo Teräs wrote: Joakim Tjernlund wrote: Yes. Exactly that. It's __attribute__(( visibility(protected) )). Or .protected for asm. I'm doing a patch on this right now. http://www.ohse.de/uwe/articles/gcc-attributes.html#func-visibility But this is PROTECTED and you might need to impl. STB_PROTECTED in ldso That should be STV_PROTECTED to support it. I once looked at that when I was hacking ldso in uClibc some years ago but I don't remember the details any more. Ah, you're right. It does need ld.so support. I'll try to figure out if it's easy to implement, or if we get away with some linker flags. Huh. Actually, I think we can keep attribute hidden, and just make the uclibc use internally the public pthread_* function that are being forwarded anyway. Duh. I'll try this. ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: nptl: mark symbols with libc forwarder hidden
Joakim Tjernlund wrote: Timo Teräs timo.te...@gmail.com wrote on 2010/04/16 11:39:00: Joakim Tjernlund wrote: Yes. Exactly that. It's __attribute__(( visibility(protected) )). Or .protected for asm. I'm doing a patch on this right now. http://www.ohse.de/uwe/articles/gcc-attributes.html#func-visibility But this is PROTECTED and you might need to impl. STB_PROTECTED in ldso That should be STV_PROTECTED to support it. I once looked at that when I was hacking ldso in uClibc some years ago but I don't remember the details any more. Ah, you're right. It does need ld.so support. I'll try to figure out if it's easy to implement, or if we get away with some linker flags. This MIGHT do it(completely untested): diff --git a/ldso/ldso/i386/elfinterp.c b/ldso/ldso/i386/elfinterp.c index a01c1d0..7f1b408 100644 --- a/ldso/ldso/i386/elfinterp.c +++ b/ldso/ldso/i386/elfinterp.c @@ -175,7 +175,9 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, symbol_addr = 0; symname = strtab + symtab[symtab_index].st_name; - if (symtab_index) { + if (symtab_index + (ELF32_ST_VISIBILITY(symtab[symtab_index].st_other) +!= STV_PROTECTED)) { symbol_addr = (unsigned long)_dl_find_hash(symname, scope, tpnt, elf_machine_type_class(reloc_type), tls_tpnt); Does not seem to work as expected. When using this, and getting the case when pthread_self is being forwarded via libc (so we end up using relocation of protected __pthread_self in nptl). where #0 0x964d in ?? () #1 0xb785302f in pthread_self () at libpthread/nptl/forward.c:137 #2 0xb77b66be in plugin_main () from ./plugin.so #3 0xb7876672 in main () from /home/ncopa/pthread/test But the symbol should is actually located at: (gdb) p __pthread_self $3 = {pthread_t (void)} 0xb77c264d __pthread_self Smells like we did not add the base address. - Timo ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: nptl: mark symbols with libc forwarder hidden
Timo Teräs wrote: Joakim Tjernlund wrote: Timo Teräs timo.te...@gmail.com wrote on 2010/04/16 11:39:00: Joakim Tjernlund wrote: Yes. Exactly that. It's __attribute__(( visibility(protected) )). Or .protected for asm. I'm doing a patch on this right now. http://www.ohse.de/uwe/articles/gcc-attributes.html#func-visibility But this is PROTECTED and you might need to impl. STB_PROTECTED in ldso That should be STV_PROTECTED to support it. I once looked at that when I was hacking ldso in uClibc some years ago but I don't remember the details any more. Ah, you're right. It does need ld.so support. I'll try to figure out if it's easy to implement, or if we get away with some linker flags. This MIGHT do it(completely untested): diff --git a/ldso/ldso/i386/elfinterp.c b/ldso/ldso/i386/elfinterp.c index a01c1d0..7f1b408 100644 --- a/ldso/ldso/i386/elfinterp.c +++ b/ldso/ldso/i386/elfinterp.c @@ -175,7 +175,9 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, symbol_addr = 0; symname = strtab + symtab[symtab_index].st_name; -if (symtab_index) { +if (symtab_index +(ELF32_ST_VISIBILITY(symtab[symtab_index].st_other) + != STV_PROTECTED)) { symbol_addr = (unsigned long)_dl_find_hash(symname, scope, tpnt, elf_machine_type_class(reloc_type), tls_tpnt); Does not seem to work as expected. When using this, and getting the case when pthread_self is being forwarded via libc (so we end up using relocation of protected __pthread_self in nptl). where #0 0x964d in ?? () #1 0xb785302f in pthread_self () at libpthread/nptl/forward.c:137 #2 0xb77b66be in plugin_main () from ./plugin.so #3 0xb7876672 in main () from /home/ncopa/pthread/test But the symbol should is actually located at: (gdb) p __pthread_self $3 = {pthread_t (void)} 0xb77c264d __pthread_self Smells like we did not add the base address. We are missing a: DL_FIND_HASH_VALUE(tpnt, type_class, sym); that turns into: DL_RELOC_ADDR ((SYM)-st_value, (TPNT)-loadaddr) # define DL_RELOC_ADDR(LOADADDR, ADDR) \ ((LOADADDR) + (ADDR)) That is done implicitly by the _dl_find_hash. I wonder if we can just simply add this to the else block, or if need to make the protected symbol case separate. ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: various nptl patches
Austin Foxley wrote: On 04/16/2010 07:37 AM, Timo Teräs wrote: Ok, second try on getting the libc - libpthread interactions right. This includes the Joakim's patch for protected symbols, with a little fix from me. I thought the hidden symbol thing would work, because I thought when you turned on stdio-futexes, everywhere used futexes. I didn't realize other places were using __pthread* symbols directly... Yeah, that was my impression too. But it turns out to work differently :/ We'll need to patch all the other arch's ldso as well to handle protected symbols, but I'll apply this for now. If I'm not mistaken, other archs will be no worse off than they are now in this situation. Right? Right. It makes things slightly better for other archs too, but in practice it won't work until they support protected symbols too. These patches finally cleaned up the _pthread_cleanup* mess for me though. Thanks! Yes, it's a bit better now. The whole __GI_ aliasing thingy on libc side is a bit weird still. I wonder if we could remove all that and just use the proper visibility attributes. But I guess that's another story. Oh well. At least nptl on x86 is starting to get to usable state now. There will be still problems application without libpthread goes and dlopen()'s a library loading libpthread. But that's easily fixable by just linking the main app to libpthread. Will continue testing next week. ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
nptl: fix libc sigtimedwait
It seems that 57e8823548ad6e65d33b2153edeb18fb0edc20e6 removed completely sigtimedwait symbol from libc which is wrong. I hope there is not too many other things like this. Apparently the libc_hidden_* macros actually make previously hidden symbols visible globally (creates alias from __GI_* to *). This is probably ancient confusion from times when gcc did not support visibility attribute and hiding symbols was done using hacks like this. This also adds attribute_hidden to the internal __sigtimedwait for nptl case. Signed-off-by: Timo Teräs timo.te...@iki.fi diff --git a/libc/sysdeps/linux/common/__rt_sigtimedwait.c b/libc/sysdeps/linux/common/__rt_sigtimedwait.c index 554c6b9..79b94ad 100644 --- a/libc/sysdeps/linux/common/__rt_sigtimedwait.c +++ b/libc/sysdeps/linux/common/__rt_sigtimedwait.c @@ -60,8 +60,8 @@ static int do_sigtimedwait(const sigset_t *set, siginfo_t *info, } /* Return any pending signal or wait for one for the given time. */ -int __sigtimedwait(const sigset_t *set, siginfo_t *info, - const struct timespec *timeout) +int attribute_hidden __sigtimedwait(const sigset_t *set, siginfo_t *info, + const struct timespec *timeout) { if(SINGLE_THREAD_P) return do_sigtimedwait(set, info, timeout); @@ -102,3 +102,4 @@ int attribute_hidden __sigtimedwait(const sigset_t * set, siginfo_t * info, } #endif weak_alias(__sigtimedwait,sigtimedwait) +libc_hidden_weak(sigtimedwait) ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: nptl: fix libc nptl forwarding stubs
Timo Teräs wrote: The attribute_hidden is added to all forward stubs, to avoid self recursion. If libc and libpthread linking order is reversed, the libc stub would end up being used in the libpthread side struct pthread_functions. Apparently glibc side is doing linker magic to avoid this. I don't think it really makes sense for libc to export pthreads symbols, so I'm using attribute_hidden there. Alternatively we could use protected visibility on libpthread side to make sure it's using it's own symbols. diff --git a/libpthread/nptl/forward.c b/libpthread/nptl/forward.c index 8f528d0..e9a2a0b 100644 --- a/libpthread/nptl/forward.c +++ b/libpthread/nptl/forward.c @@ -32,6 +32,7 @@ int __libc_pthread_functions_init attribute_hidden; #define FORWARD2(name, rettype, decl, params, defaction) \ +rettype name decl attribute_hidden; \ rettype \ name decl \ { \ We can't really do this part. Turns out that some wacko libraries such as libX11 test if libc has pthread_self and do funny stuff it it doesn't. The really proper thing is to go libpthread symbol by symbol and hide the non-exported ones. Glibc does this with linker version-script. Not sure if we want to do the same, or sprinkle hidden/protected definitions around the place. - Timo ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
nptl: mark symbols with libc forwarder hidden
Add attribute_hidden to all symbols having libc forwarder. This prevents recursive self calls which would happen if libc is before libpthread in linking order: the forwarder functions would call itself via the function table, since the libpthread symbols would get overwritten with libc ones. This has not been a problem in glibc since there these symbols are marked hidden with linker version-script. Since we don't use one, we need to mark these explicitly. Signed-off-by: Timo Teräs timo.te...@iki.fi diff --git a/libpthread/nptl/cleanup_defer_compat.c b/libpthread/nptl/cleanup_defer_compat.c index 8fd9b54..cc68893 100644 --- a/libpthread/nptl/cleanup_defer_compat.c +++ b/libpthread/nptl/cleanup_defer_compat.c @@ -21,6 +21,7 @@ void +attribute_hidden _pthread_cleanup_push_defer ( struct _pthread_cleanup_buffer *buffer, void (*routine) (void *), @@ -60,6 +61,7 @@ strong_alias (_pthread_cleanup_push_defer, __pthread_cleanup_push_defer) void +attribute_hidden _pthread_cleanup_pop_restore ( struct _pthread_cleanup_buffer *buffer, int execute) diff --git a/libpthread/nptl/init.c b/libpthread/nptl/init.c index b651a3e..87c08fa 100644 --- a/libpthread/nptl/init.c +++ b/libpthread/nptl/init.c @@ -111,8 +111,8 @@ static const struct pthread_functions pthread_functions = .ptr___pthread_key_create = __pthread_key_create_internal, .ptr___pthread_getspecific = __pthread_getspecific_internal, .ptr___pthread_setspecific = __pthread_setspecific_internal, -.ptr__pthread_cleanup_push_defer = __pthread_cleanup_push_defer, -.ptr__pthread_cleanup_pop_restore = __pthread_cleanup_pop_restore, +.ptr__pthread_cleanup_push_defer = _pthread_cleanup_push_defer, +.ptr__pthread_cleanup_pop_restore = _pthread_cleanup_pop_restore, .ptr_nthreads = __nptl_nthreads, .ptr___pthread_unwind = __pthread_unwind, .ptr__nptl_deallocate_tsd = __nptl_deallocate_tsd, diff --git a/libpthread/nptl/pt-cleanup.c b/libpthread/nptl/pt-cleanup.c index f72ea26..619eb8b 100644 --- a/libpthread/nptl/pt-cleanup.c +++ b/libpthread/nptl/pt-cleanup.c @@ -23,6 +23,7 @@ #include jmpbuf-unwind.h void +attribute_hidden __pthread_cleanup_upto (__jmp_buf target, char *targetframe) { struct pthread *self = THREAD_SELF; diff --git a/libpthread/nptl/pthread_attr_destroy.c b/libpthread/nptl/pthread_attr_destroy.c index b8e6a37..16b7164 100644 --- a/libpthread/nptl/pthread_attr_destroy.c +++ b/libpthread/nptl/pthread_attr_destroy.c @@ -24,6 +24,7 @@ #include pthreadP.h int +attribute_hidden __pthread_attr_destroy ( pthread_attr_t *attr) { diff --git a/libpthread/nptl/pthread_attr_getdetachstate.c b/libpthread/nptl/pthread_attr_getdetachstate.c index 5f549ba..14b91df 100644 --- a/libpthread/nptl/pthread_attr_getdetachstate.c +++ b/libpthread/nptl/pthread_attr_getdetachstate.c @@ -22,6 +22,7 @@ int +attribute_hidden __pthread_attr_getdetachstate ( const pthread_attr_t *attr, int *detachstate) diff --git a/libpthread/nptl/pthread_attr_getinheritsched.c b/libpthread/nptl/pthread_attr_getinheritsched.c index 3ff3040..8ab8657 100644 --- a/libpthread/nptl/pthread_attr_getinheritsched.c +++ b/libpthread/nptl/pthread_attr_getinheritsched.c @@ -22,6 +22,7 @@ int +attribute_hidden __pthread_attr_getinheritsched ( const pthread_attr_t *attr, int *inherit) diff --git a/libpthread/nptl/pthread_attr_getschedparam.c b/libpthread/nptl/pthread_attr_getschedparam.c index 82b2371..ee1d513 100644 --- a/libpthread/nptl/pthread_attr_getschedparam.c +++ b/libpthread/nptl/pthread_attr_getschedparam.c @@ -23,6 +23,7 @@ int +attribute_hidden __pthread_attr_getschedparam ( const pthread_attr_t *attr, struct sched_param *param) diff --git a/libpthread/nptl/pthread_attr_getschedpolicy.c b/libpthread/nptl/pthread_attr_getschedpolicy.c index 7b8f1de..54666da 100644 --- a/libpthread/nptl/pthread_attr_getschedpolicy.c +++ b/libpthread/nptl/pthread_attr_getschedpolicy.c @@ -22,6 +22,7 @@ int +attribute_hidden __pthread_attr_getschedpolicy ( const pthread_attr_t *attr, int *policy) diff --git a/libpthread/nptl/pthread_attr_getscope.c b/libpthread/nptl/pthread_attr_getscope.c index 9b05ffa..ccbebfa 100644 --- a/libpthread/nptl/pthread_attr_getscope.c +++ b/libpthread/nptl/pthread_attr_getscope.c @@ -22,6 +22,7 @@ int +attribute_hidden __pthread_attr_getscope ( const pthread_attr_t *attr, int *scope) diff --git a/libpthread/nptl/pthread_attr_init.c b/libpthread/nptl/pthread_attr_init.c index 65ce4e5..d019514 100644 --- a/libpthread/nptl/pthread_attr_init.c +++ b/libpthread/nptl/pthread_attr_init.c @@ -29,6 +29,7 @@ int __attr_list_lock = LLL_LOCK_INITIALIZER; int +attribute_hidden __pthread_attr_init_2_1 ( pthread_attr_t *attr) { diff --git a/libpthread/nptl/pthread_attr_setdetachstate.c b/libpthread/nptl/pthread_attr_setdetachstate.c index b6d9bb5..d72fd83 100644 --- a/libpthread/nptl/pthread_attr_setdetachstate.c +++ b/libpthread/nptl
linuxthreads.new: initialize stdio locking
uClibc requires the threading library to enable locking for stdio, or the locking is not done at all. Signed-off-by: Timo Teräs timo.te...@iki.fi -- Not compile tested either. Natanael, maybe you could test this too since you are using linuxthreads.new too. diff --git a/libpthread/linuxthreads/pthread.c b/libpthread/linuxthreads/pthread.c index 6ae9a10..614cad1 100644 --- a/libpthread/linuxthreads/pthread.c +++ b/libpthread/linuxthreads/pthread.c @@ -613,6 +613,17 @@ static void pthread_initialize(void) #ifdef USE_TLS GL(dl_init_static_tls) = __pthread_init_static_tls; #endif + + /* uClibc-specific stdio initialization for threads. */ + { +FILE *fp; +_stdio_user_locking = 0; /* 2 if threading not initialized */ +for (fp = _stdio_openlist; fp != NULL; fp = fp-__nextopen) { + if (fp-__user_locking != 1) { +fp-__user_locking = 0; + } +} + } } void __pthread_initialize(void) ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: problems with gnu make and stdout with uclibc nptl
Peter Kjellerstedt wrote: Unless it has changed in the last years, there are no expressed guarantees regarding API and ABI stability for the 0.x.y releases of uClibc. AFAIK the stable API/ABI is intended for the 1.0.0 release. And with the upcoming integration of the NPTL support, I do not see this as the right time to go to 1.0.0 and lock down the API/ABI... Could the uclibc project then start using appropriate soname, so we can install multiple versions of the library if needed (e.g. when doing package based upgrade). # objdump -p /lib/libuClibc-0.9.30.1.so |grep SONAME SONAME libc.so.0 Would indicate that all 0.x are compatible. Basically, soname should be 0.x.y if all 0.x.y.z are supposed to be ABI compatible. Currently it seems that link.so and linkm.so macros explicitly set soname according to $(2). define link.so $(Q)$(INSTALL) -d $(dir $@) $(Q)$(RM) $@ $...@.$(2) $(dir $@)$(1) @$(disp_ld) $(Q)$(CC) $(LDFLAGS-$(notdir $@)) -Wl,-soname=$(notdir $@).$(2) \ $(NOSTDLIB_CFLAGS) -o $(dir $@)$(1) $(START_FILE-$(notdir $@)) \ -Wl,--whole-archive $(firstword $^) -Wl,--no-whole-archive \ $(LIBS-$(notdir $@)) $(LIBGCC) $(END_FILE-$(notdir $@)) $(Q)$(LN) -sf $(1) $...@.$(2) $(Q)$(LN) -sf $(1) $@ endef Those get called like: ./libc/Makefile.in: $(call linkm.so,$(libc_FULL_NAME),$(MAJOR_VERSION)) And that's defined like: Rules.mak:MAJOR_VERSION := 0 Resulting in above mentioned soname, which is completely broken regarding to how shared object ABI compatibility should be handled. Please fix soname. Thanks, Timo ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: [nptl] more stdout issues
Austin Foxley wrote: On 04/12/2010 12:21 PM, Natanael Copa wrote: Smells like stdio is not threads safe? Interesting. I supposed there could be an issue with the libc internal futex code that replaces the old use of pthread mutexes directly. We could verify this with a bit of work by getting the old style mutexes to compile correctly with nptl enabled. If that fixes it, then it narrows down somewhat... The other thing is that this might just be x86, as there haven't been reports on other archs of these problems. Although maybe nobody else has tried it on multi-core? It looks like no one bothered to implement the uClibc needed stdio locking initialization. It seems that only linuxthreads.old does this. So both linuxthreads.new and nptl seem to be broken wrt. stdio locking. I did not even try compile testing the below, but something like this should help. Could you test this? nptl: initialize stdio locking uClibc requires the threading library to enable locking for stdio, or the locking is not done at all. Signed-off-by: Timo Teräs timo.te...@iki.fi diff --git a/libpthread/nptl/init.c b/libpthread/nptl/init.c index b651a3e..16f62f6 100644 --- a/libpthread/nptl/init.c +++ b/libpthread/nptl/init.c @@ -35,6 +35,7 @@ #include lowlevellock.h #include bits/kernel-features.h +#include uClibc_stdio.h /* Size and alignment of static TLS block. */ size_t __static_tls_size; @@ -423,6 +424,17 @@ __pthread_initialize_minimal_internal (void) /* Determine whether the machine is SMP or not. */ __is_smp = is_smp_system (); + + /* uClibc-specific stdio initialization for threads. */ + { +FILE *fp; +_stdio_user_locking = 0; /* 2 if threading not initialized */ +for (fp = _stdio_openlist; fp != NULL; fp = fp-__nextopen) { + if (fp-__user_locking != 1) { +fp-__user_locking = 0; + } +} + } } strong_alias (__pthread_initialize_minimal_internal, __pthread_initialize_minimal) ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: uClibc-0.9.31 symbol table oddities
Michael Deutschmann wrote: On a related note, is there ABI breakage in 0.9.31 aside from dropped symbols? Yes, ABI is broken regarding to signal handling. struct sigaction fields were reordered at 885f507317b6c8576ba2e298c2249d27ea6f8404. sigset_t size was also changed in 35ae1599438a15568818bf09b493d7b49039d452. - Timo ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: [branch] nptl_merge
Hi, Austin Foxley wrote: I've created a branch based on current master that has the entirety of the work done so far on nptl integrated. I attempted to break up into separate commits, related kinds of changes. Hopefully this well help in reviewing... My thought was that people could review each commit and either reply to this email for discussion, or simply commit fixes for any issues directly to the nptl_merge branch. I'm going to start fixing up obvious style issues now to preempt some comments :) I've tried hard to avoid reverting anybody's work, please let me know where I missed anything. Remember...I obviously didn't write most of this code... Let's get this beast merged already! This is something I've been waiting for a long time! Thanks! I will definitely try to get the i386 side up and running. uClibc NPTL is one of the things we listed for Alpine Linux (www.alpinelinux.org) to be in it's next major release. I already earlier did some work earlier to see how far away it is and got it working to some degree. I did very quick test just now, but it did not compile; there was some issues with stack protector support. But I'm sure I'll work on this with Natanael Copa in the upcoming weeks. Are there any known issues or things that still needs implementing? Though, I guess we'll just go along and see what needs to be done to get the usual stuff working we run on our boxes. Thanks, Timo ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
fstatat is broke
Hi all, I'm using the *at stuff and noticed that fstatat is broke. fstatat is a bit different since that syscall is not really available. Glibc makes fstatat do fstatat64 syscall and converts the struct kernel_stat64 to struct stat. I think that is what was also intended in uclibc case, but someone left the work halfway. Now it badly uses struct kernel_stat with fstatat64 syscall. We need to use the struct kernel_stat64 and implement the new conversion case. - Timo ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: linuxthreads/signals question
GoatZilla wrote: I'm using the linuxthreads.old version of the threading code in uClibc, and I seem to be getting a hang when using semaphores. What appears to be happening is one thread is reaching __new_sem_wait, but gets preempted between line 86 and when the actual system call to suspend actually occurs (line 97). By that point, it has checked the semaphore and found that it's not available, and added itself as waiting for the semaphore. http://git.uclibc.org/uClibc/tree/libpthread/linuxthreads.old/semaphore.c#n59 The other thread then hits __new_sem_post, discovers another thread is waiting for the semaphore and sends the signal to it. The 'wait' thread then wakes up, but hasn't hit the suspend call yet. It eventually gets there, but then sleeps indefinitely because I guess the previous signal, which was apparently an RT signal, was eaten or something. Is this what's supposed to happen in this circumstance? What should to happen to the RT signal that goes to a thread before it's actually reached its suspend call? Or is this a bug with uClibc? The signal is masked out by linuxthreads. It is kept pending until the suspend() call and the signal is delivered at that time. Is perhaps your program using the same signals that the linuxthreads uses to synchronize? - Timo ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: nptl branch with i386
Matteo Petracca wrote: Hello, I am trying to use the nptl branch with i386 support added by Timo through the patch: http://solidboot.com/~fabled/uclibc-nptl-i386.diff It works and the system compiles, but I am having some issues in using the lrintf function which gives segmentation fault. Thank you very much for any possible help. Could you provide a simple test program that crashes? Or a gdb backtrace of your program while it crashes? Looks like lrintf is just a simple inline function that executes a specific fpu instructions. The only way it can be nptl/i386 specific is that the fpu instruction is mangling some TLS specific variable. Do you know if it works with nptl branch on some other architecture? - Timo ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: NPTL on x86, anyone?
Cristi Magherusan wrote: Sorry for reviving this forgotten thread, but I'm really interested about this topic. I have set up a uClibc git branch that aims for proper x86 NPTL support, that I need for my GSoC project. Currently it only contains Timo's patches, applied on top of the current nptl branch, but I'm willing to shape it and make it properly work so that it finally can be merged back in the main uClibc repo. Feel free to test it, any contributions/feedback/hints are welcome. The code is stored at http://cristi.indefero.net/p/uClibc-cristi/source/changes/nptl/ While fixing the bugs (I sent earlier patches) in linuxthreads.new I got a better understanding how the libc and libpthreads integration works. When I get some extra jiffies I could revisit this patch and fix the blockers that prevent it from inclusion upstream (mainly the modifications to non-nptl parts). - Timo ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
res_query for CNAMEs
Hi, I had postfix failing for domains with MX-CNAME-A chain. In glibc it works. I tracked it to be a problem in uclibc res_query. It returns bogus data for CNAME entries, apparently intentionally, which is wrong. glibc return CNAME entries even for CNAME queries and most applications rely on this. So we should do the same in uclibc. Please apply. - Timo --- libc/inet/resolv.c.orig 2009-06-18 09:38:26.0 +0300 +++ libc/inet/resolv.c 2009-06-18 09:38:32.0 +0300 @@ -1337,10 +1337,9 @@ int res_query(const char *dname, int cla free(a.dotted); - if (a.atype == type) { /* CNAME */ - i = MIN(anslen, i); - memcpy(answer, packet, i); - } + i = MIN(anslen, i); + memcpy(answer, packet, i); + free(packet); return i; } diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c index 109ae02..3e9f9f4 100644 --- a/libc/inet/resolv.c +++ b/libc/inet/resolv.c @@ -3016,11 +3016,10 @@ int res_query(const char *dname, int class, int type, free(a.dotted); - if (a.atype == type) { /* CNAME */ - if (i anslen) - i = anslen; - memcpy(answer, packet, i); - } + if (i anslen) + i = anslen; + memcpy(answer, packet, i); + free(packet); return i; } ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
linuxthreads.new aliases
Hi, It looks like the aliases in linuxthreads.new are a bit off. If the main binary pulls in libc before libpthread, because of some other dependent .so, you end up using the aliases from libc and not libpthread. This causes forward.c definitions to call themselves recursively for the pthread_mutex_* where forward.c has strong_alias for the internal variants. Similar loop would occur for _pthread_cleanup_* since the libc implementation would take preference from the libpthread one. I fixed this for me by: 1. renaming the internal _pthread_cleanup_* to __pthread_cleanup_* and alias them properly 2. making the pthread_mutex_* aliases hidden. you should really have the hidden_strong_alias in some global header and do the compiler checking properly. As a side note, I tried making the forward.c aliases weak, but that did not fix the problem. Either there is a bug in the linker. Or when the first dependent .so is linked in and it pulls in the libc, the symbols that are resolved there are not looked up from libpthread.so. Might need a bit of further investigation if it's actually ld.so problem. But having the strong_aliases in forward.c is definitely wrong. - Timo diff --git a/libpthread/linuxthreads/cancel.c b/libpthread/linuxthreads/cancel.c index 3435680..1412b57 100644 --- a/libpthread/linuxthreads/cancel.c +++ b/libpthread/linuxthreads/cancel.c @@ -152,8 +152,8 @@ void pthread_testcancel(void) __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); } -void _pthread_cleanup_push(struct _pthread_cleanup_buffer * buffer, - void (*routine)(void *), void * arg) +void __pthread_cleanup_push(struct _pthread_cleanup_buffer * buffer, + void (*routine)(void *), void * arg) { pthread_descr self = thread_self(); buffer-__routine = routine; @@ -163,17 +163,19 @@ void _pthread_cleanup_push(struct _pthread_cleanup_buffer * buffer, buffer-__prev = NULL; THREAD_SETMEM(self, p_cleanup, buffer); } +strong_alias(__pthread_cleanup_push, _pthread_cleanup_push); -void _pthread_cleanup_pop(struct _pthread_cleanup_buffer * buffer, - int execute) +void __pthread_cleanup_pop(struct _pthread_cleanup_buffer * buffer, + int execute) { pthread_descr self = thread_self(); if (execute) buffer-__routine(buffer-__arg); THREAD_SETMEM(self, p_cleanup, buffer-__prev); } +strong_alias(__pthread_cleanup_pop, _pthread_cleanup_pop); -void _pthread_cleanup_push_defer(struct _pthread_cleanup_buffer * buffer, -void (*routine)(void *), void * arg) +void __pthread_cleanup_push_defer(struct _pthread_cleanup_buffer * buffer, + void (*routine)(void *), void * arg) { pthread_descr self = thread_self(); buffer-__routine = routine; @@ -185,9 +187,10 @@ void _pthread_cleanup_push_defer(struct _pthread_cleanup_buffer * buffer, THREAD_SETMEM(self, p_canceltype, PTHREAD_CANCEL_DEFERRED); THREAD_SETMEM(self, p_cleanup, buffer); } +strong_alias(__pthread_cleanup_push_defer, _pthread_cleanup_push_defer); -void _pthread_cleanup_pop_restore(struct _pthread_cleanup_buffer * buffer, - int execute) +void __pthread_cleanup_pop_restore(struct _pthread_cleanup_buffer * buffer, + int execute) { pthread_descr self = thread_self(); if (execute) buffer-__routine(buffer-__arg); @@ -198,6 +201,7 @@ void _pthread_cleanup_pop_restore(struct _pthread_cleanup_buffer * buffer, THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS) __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); } +strong_alias(__pthread_cleanup_pop_restore, _pthread_cleanup_pop_restore); extern void __rpc_thread_destroy(void); void __pthread_perform_cleanup(char *currentframe) diff --git a/libpthread/linuxthreads/forward.c b/libpthread/linuxthreads/forward.c index f9f8ea1..385e79f 100644 --- a/libpthread/linuxthreads/forward.c +++ b/libpthread/linuxthreads/forward.c @@ -24,6 +24,10 @@ /* psm: keep this before internals.h */ /* libc_hidden_proto(exit) */ +#define hidden_strong_alias(name, aliasname) \ + extern __typeof (name) aliasname __attribute__ ((alias (#name), \ + visibility (hidden))); + #include internals.h /* Pointers to the libc functions. */ @@ -104,8 +108,7 @@ FORWARD (pthread_equal, (pthread_t thread1, pthread_t thread2), /* Use an alias to avoid warning, as pthread_exit is declared noreturn. */ FORWARD2 (__pthread_exit, void, (void *retval), (retval), exit (EXIT_SUCCESS)) -strong_alias (__pthread_exit, pthread_exit) - +hidden_strong_alias (__pthread_exit, pthread_exit) FORWARD (pthread_getschedparam, (pthread_t target_thread, int *policy, struct sched_param *param), @@ -120,16 +123,16 @@ FORWARD (pthread_mutex_destroy, (pthread_mutex_t *mutex), (mutex), 0) FORWARD (pthread_mutex_init, (pthread_mutex_t *mutex, const
[patch nptl] i386 support somewhat usable
Hi, I took a quick stab at making i386 work on the nptl branch. What is done: 1. i386 specific makefiles 2. uclibc headers providing the syscall wrappers were updated 3. updated some files from newer nptl snapshot 4. added ld.so support for tls relocations 5. tried to clean up some files for not defining duplicate symbols What I'm not all sure about: 1. if e.g. clone.S update is correct; didn't see what where the original modifications for uclibc, just overwrote it with a new version 2. if libc is built properly with all the right objects from nptl Basic stuff seems to work for me. A large portion of the nptl test cases also run. But e.g. cancellations do not work. Patch is at: http://solidboot.com/~fabled/uclibc-nptl-i386.diff And updates to test cases at: http://solidboot.com/~fabled/uclibc-nptl-test.diff Cheers, Timo ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: NPTL on x86, anyone?
Mike Frysinger wrote: On Friday 10 April 2009 01:07:52 Timo Teräs wrote: Mike Frysinger wrote: On Thursday 09 April 2009 10:24:53 Cristi Magherusan wrote: Is there anyone interested in porting the NPTL branch to x86/x86-64? always interested in accepting patches, but no one appears to be interested in doing the porting work atm Did you all miss the mail I sent yesterday? http://lists.uclibc.org/pipermail/uclibc/2009-April/042289.html i saw it, but i generally skim over things that make me go to an external location The patch is about 70 kB. I find it good practice to send large (as in over 40-50kB) patches as URLs instead of as attachment/inline. But I can send it as attachment too if wanted. I just noticed that some changes there are probably not right based on the recent MIPS patch discussion. E.g. pthread_cleanup_push_defer related things. Also wondering if the NPTL version is planned for update? The nptl branch is based on pretty old snapshot. - Timo ___ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc
Re: [PATCH] splice, vmsplice and tee for i386
Peter Kjellerstedt wrote: I'll apply this patch in a few days unless i hear something controversial. Any particular reason to uncomment sync_file_range() in fcntl.h? It does not seem to be part of the patch. Also, you might as well take the latest fcntl.h from glibc while at it to get a couple of missing defines (unrelated to splice). Updated to latest fcntl.h with sync_file_range in #if 0. Also updated to have errno = ENOSYS, return -1 wrappers if the syscall numbers are not defined. Cheers, Timo Index: libc/sysdeps/linux/common/vmsplice.c === --- libc/sysdeps/linux/common/vmsplice.c (revision 0) +++ libc/sysdeps/linux/common/vmsplice.c (revision 0) @@ -0,0 +1,28 @@ +/* vi: set sw=4 ts=4: */ +/* + * vmsplice() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen [EMAIL PROTECTED] + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include sys/syscall.h +#include fcntl.h + +libc_hidden_proto(vmsplice) + +#ifdef __NR_vmsplice +_syscall4(ssize_t, vmsplice, int, __fdout, const struct iovec *, __iov, + size_t, __count, unsigned int, __flags); +#else +ssize_t vmsplice(int __fdout, const struct iovec *__iov, size_t __count, + unsigned int __flags) +{ + __set_errno(ENOSYS); + return -1; +} +#endif + +libc_hidden_def(vmsplice) + Index: libc/sysdeps/linux/common/tee.c === --- libc/sysdeps/linux/common/tee.c (revision 0) +++ libc/sysdeps/linux/common/tee.c (revision 0) @@ -0,0 +1,28 @@ +/* vi: set sw=4 ts=4: */ +/* + * tee() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen [EMAIL PROTECTED] + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include sys/syscall.h +#include fcntl.h + +libc_hidden_proto(tee) + +#ifdef __NR_tee +_syscall4(ssize_t, tee, int, __fdin, int, __fdout, size_t, __len, + unsigned int, __flags); +#else +ssize_t tee(int __fdin, int __fdout, size_t __len, unsigned int __flags) +{ + __set_errno(ENOSYS); + return -1; +} +#endif + +libc_hidden_def(tee) + + Index: libc/sysdeps/linux/common/splice.c === --- libc/sysdeps/linux/common/splice.c (revision 0) +++ libc/sysdeps/linux/common/splice.c (revision 0) @@ -0,0 +1,28 @@ +/* vi: set sw=4 ts=4: */ +/* + * splice() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen [EMAIL PROTECTED] + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include sys/syscall.h +#include fcntl.h + +libc_hidden_proto(splice) + +#ifdef __NR_splice +_syscall6(ssize_t, splice, int, __fdin, __off64_t *, __offin, int, __fdout, + __off64_t *, __offout, size_t, __len, unsigned int, __flags); +#else +ssize_t splice(int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, unsigned int __flags) +{ + __set_errno(ENOSYS); + return -1; +} +#endif + +libc_hidden_def(splice) + Index: libc/sysdeps/linux/i386/bits/fcntl.h === --- libc/sysdeps/linux/i386/bits/fcntl.h (revision 21789) +++ libc/sysdeps/linux/i386/bits/fcntl.h (working copy) @@ -1,5 +1,5 @@ /* O_*, F_*, FD_* bit values for Linux. - Copyright (C) 1995, 1996, 1997, 1998, 2000, 2004, 2006 + Copyright (C) 1995, 1996, 1997, 1998, 2000, 2004, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -50,6 +50,7 @@ # define O_DIRECTORY 020 /* Must be a directory. */ # define O_NOFOLLOW 040 /* Do not follow links. */ # define O_NOATIME 0100 /* Do not set atime. */ +# define O_CLOEXEC 0200 /* Set close_on_exec. */ #endif /* For now Linux has synchronisity options for data and read operations. @@ -97,9 +98,11 @@ # define F_SETLEASE 1024 /* Set a lease. */ # define F_GETLEASE 1025 /* Enquire what lease is active. */ # define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set. */ #endif -/* For F_[GET|SET]FL. */ +/* For F_[GET|SET]FD. */ #define FD_CLOEXEC 1 /* actually anything with low bit set goes */ /* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ @@ -185,6 +188,7 @@ #ifdef __USE_GNU +/* Flags for SYNC_FILE_RANGE. */ # define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages in the range before performing the write. */ @@ -194,6 +198,14 @@ # define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in the range after performing the write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more
[PATCH] splice, vmsplice and tee for i386
Hi, splice et al for i386. Against svn trunk. Cheers, Timo Index: libc/sysdeps/linux/common/vmsplice.c === --- libc/sysdeps/linux/common/vmsplice.c (revision 0) +++ libc/sysdeps/linux/common/vmsplice.c (revision 0) @@ -0,0 +1,21 @@ +/* vi: set sw=4 ts=4: */ +/* + * vmsplice() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen [EMAIL PROTECTED] + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include sys/syscall.h +#include fcntl.h + +#ifdef __NR_vmsplice + +libc_hidden_proto(vmsplice) + +_syscall4(ssize_t, vmsplice, int, __fdout, const struct iovec *, __iov, + size_t, __count, unsigned int, __flags); +libc_hidden_def(vmsplice) + +#endif Index: libc/sysdeps/linux/common/tee.c === --- libc/sysdeps/linux/common/tee.c (revision 0) +++ libc/sysdeps/linux/common/tee.c (revision 0) @@ -0,0 +1,21 @@ +/* vi: set sw=4 ts=4: */ +/* + * tee() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen [EMAIL PROTECTED] + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include sys/syscall.h +#include fcntl.h + +#ifdef __NR_tee + +libc_hidden_proto(tee) + +_syscall4(ssize_t, tee, int, __fdin, int, __fdout, size_t, __len, + unsigned int, __flags); +libc_hidden_def(tee) + +#endif Index: libc/sysdeps/linux/common/splice.c === --- libc/sysdeps/linux/common/splice.c (revision 0) +++ libc/sysdeps/linux/common/splice.c (revision 0) @@ -0,0 +1,22 @@ +/* vi: set sw=4 ts=4: */ +/* + * splice() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen [EMAIL PROTECTED] + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include sys/syscall.h +#include fcntl.h + +#ifdef __NR_splice + +libc_hidden_proto(splice) + +_syscall6(ssize_t, splice, int, __fdin, __off64_t *, __offin, int, __fdout, + __off64_t *, __offout, size_t, __len, unsigned int, __flags); + +libc_hidden_def(splice) + +#endif Index: libc/sysdeps/linux/i386/bits/fcntl.h === --- libc/sysdeps/linux/i386/bits/fcntl.h (revision 21789) +++ libc/sysdeps/linux/i386/bits/fcntl.h (working copy) @@ -194,6 +194,14 @@ # define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in the range after performing the write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ #endif __BEGIN_DECLS @@ -205,24 +213,25 @@ __THROW; -#if 0 /* Selective file content synch'ing. */ extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, unsigned int __flags); /* Splice address range into a pipe. */ -extern int vmsplice (int __fdout, const struct iovec *__iov, size_t __count, - unsigned int __flags); +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); /* Splice two files together. */ -extern int splice (int __fdin, int __fdout, size_t __len, unsigned int __flags) +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags) __THROW; /* In-kernel implementation of tee for pipe buffers. */ -extern int tee (int __fdin, int __fdout, size_t __len, unsigned int __flags) +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags) __THROW; -#endif #endif ___ uClibc mailing list uClibc@uclibc.org http://busybox.net/cgi-bin/mailman/listinfo/uclibc