[PATCH] Static linking binaries with uClibc

Denys Vlasenko vda.linux at googlemail.com
Sun May 16 04:59:12 UTC 2010


On Wednesday 03 February 2010 17:21, Will Newton wrote:
> Hello,
> 
> I have a problem with linking applications statically with uClibc but
> without including the stdio functions. This issue has been brought up
> before, but it still does not seem to be solved.
> 
> The issue would appear to be this:
> 
> _stdio_init is declared as weak and hidden in
> libc/misc/internals__uClibc_main.c:
> 
> extern void weak_function _stdio_init(void) attribute_hidden;
> 
> The reason it is defined hidden is to reduce the size of the external
> symbol set of uClibc and to bypass the PLT when calling it, which is
> really only of benefit in the shared library case. The reason it is
> declared weak is so that when uClibc is linked statically, _stdio_init
> is not called unless it has already pulled in by some other symbol.
> 
> However, static linking does not work in the no-stdio case at present.
> Looking at the code and disassembly we see why - the compiler omits
> the test for the null value of _stdio_init, e.g.:
> 
>     /*
>      * Initialize stdio here.  In the static library case, this will
>      * be bypassed if not needed because of the weak alias above.
>      * Thus we get a nice size savings because the stdio functions
>      * won't be pulled into the final static binary unless used.
>      */
>     if (likely(_stdio_init != NULL))
>         _stdio_init();
> 
> }
> 
>   34:   e8 fc ff ff ff          call   35 <__GI___uClibc_init+0x35>
>   39:   58                      pop    %eax
>   3a:   5a                      pop    %edx
>   3b:   5b                      pop    %ebx
>   3c:   e9 fc ff ff ff          jmp    3d <__GI___uClibc_init+0x3d>
>   41:   59                      pop    %ecx
>   42:   58                      pop    %eax
>   43:   5b                      pop    %ebx
>   44:   c3                      ret

Ew can use asm() to prevent gcc from understanding that the pointer
is a function pointer.

Test program:

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

Resulting code with gcc -Os -fomit-frame-pointer -S t.c:

f2:
       movl    $g2, %eax
       testl   %eax, %eax
       je      .L4
       jmp     g2
.L4:
       ret

f1:
       jmp     g1

-- 
vda


More information about the uClibc mailing list