Denys Vlasenko a écrit :
On Monday 28 December 2009 18:37, matthieu castet wrote:
Hi,

gcc with the -fpic option optimize code like :
__attribute__ ((visibility ("hidden")))
# define weak_function __attribute__ ((weak))

extern void weak_function _stdio_init(void) attribute_hidden;


int main()
{
       if (_stdio_init)
               _stdio_init();

       return 0;
}

to

__attribute__ ((visibility ("hidden")))
# define weak_function __attribute__ ((weak))

extern void weak_function _stdio_init(void) attribute_hidden;


int main()
{
               _stdio_init();

       return 0;
}
This crash if _stdio_init is null (because the linker didn't put it)
Without this patch, it is impossible to static link default config uClibc on 
x86.

The problem is, C/C++ says that function's address is never NULL,
and gcc uses this.
No weak function are special. The problem seems to be a gcc bug 
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=32219 .
But I wonder if it will be corrected one day.



How about using asm() to prevent gcc from understanding that the pointer
is a function pointer?


$cat p.c
#define attribute_hidden __attribute__ ((visibility ("hidden")))
# define weak_function __attribute__ ((weak))

extern void weak_function _stdio_init(void) attribute_hidden;

static inline __attribute__ ((__always_inline__)) int not_null(const void *p)
{
       const void *q;
       asm (""
       : "=r" (q) /* output */
       : "0" (p) /* input */
       );
       return q != 0;
}


int main()
{
     if (not_null(_stdio_init))
             _stdio_init();

     return 0;
} $gcc -fpic -O3 p.c -S $cat p.s .file "p.c"
       .text
       .p2align 4,,15
.globl main
       .type   main, @function
main:
       leal    4(%esp), %ecx
       andl    $-16, %esp
       pushl   -4(%ecx)
       pushl   %ebp
       movl    %esp, %ebp
       subl    $8, %esp
       movl    %ebx, 4(%esp)
       call    __i686.get_pc_thunk.bx
       addl    $_GLOBAL_OFFSET_TABLE_, %ebx
       movl    %ecx, (%esp)
       leal    _stdio_i...@gotoff(%ebx), %eax
       testl   %eax, %eax
       je      .L2
       call    _stdio_init
.L2:
       movl    (%esp), %ecx
       xorl    %eax, %eax
       movl    4(%esp), %ebx
       movl    %ebp, %esp
       popl    %ebp
       leal    -4(%ecx), %esp
       ret
       .size   main, .-main
       .weak   _stdio_init
       .hidden _stdio_init
       .ident  "GCC: (Debian 4.3.4-6) 4.3.4"
       .section        
.text.__i686.get_pc_thunk.bx,"axG",@progbits,__i686.get_pc_thunk.bx,comdat
.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
       .section        .note.GNU-stack,"",@progbits


Notice the usage of a GOT even if the symbol is hidden...


Care to remake the patch to use such not_null() wrapper?
Please also add a comment above it with explanation
why it is needed.
Ok

Matthieu
_______________________________________________
uClibc mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/uclibc

Reply via email to