[PATCH] fix static link

matthieu castet castet.matthieu at free.fr
Tue Dec 29 23:44:14 UTC 2009


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_init at 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", at 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,"", at 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


More information about the uClibc mailing list