OSDN Git Service

weak symbols need to be "defined" weak but "declared" strong
authorVineet Gupta <vgupta@synopsys.com>
Wed, 16 Apr 2014 10:36:01 +0000 (16:06 +0530)
committerBernhard Reutner-Fischer <rep.dot.nop@gmail.com>
Wed, 23 Apr 2014 11:21:23 +0000 (13:21 +0200)
commit00f425b39b9258a78df47cebdd0d2c779753392f
tree842646521e6d028f0d8d156372f3c4fb11be4e94
parent8f550715c2b211036fc273add3cb5219397ed312
weak symbols need to be "defined" weak but "declared" strong

Patch "LT.old: Make __errno_location/__h_errno_location thread safe"
uncovered yet another bug with static linking and errno (hopefully this
is last of them all).

Currently, __errno_location is declared weak but is defined strong.
While this provides with the desired weak semantics in dso, it
is subtly broken in static links.

Quoting Joern Rennecke (ARC gcc expert):

| I think the issue is that you declare the function as weak in the
| header file.  That is a rare instance where you want the reference
| use declaration that differs a bit from the definition.
| If the reference uses a weakly declared function, that creates a
| weakref, i.e. the linker won't bother to look for this symbol at
|  all - if it gets linked in for some other reason, fine,
| otherwise, it stays zero.

So the solution to declare strong, define weak.

Supporting data
-----------------
orig code: ARM mmap wrapper (LT.old build + my prev patch for errno)

_mmap:
    @ args = 8, pretend = 0, frame = 0
    @ frame_needed = 0, uses_anonymous_args = 0
    stmfd    sp!, {r4, r5, r7, lr}
    ldr    r5, [sp, #20]
    movs    ip, r5, asl #20
    beq    .L2
    bl    __errno_location(PLT)
    mov    r3, #22
    str    r3, [r0, #0]
    mvn    r0, #0
...
...
   .weak __errno_location

A statically linked hello world program which uses mmap too.
As we can see__errno_location is completely gone - which is
semantically wrong - we need functional errno.

00008274 <__GI_mmap>:
    8274:    e92d40b0     push    {r4, r5, r7, lr}
    8278:    e59d5014     ldr    r5, [sp, #20]
    827c:    e1b0ca05     lsls    ip, r5, #20
    8280:    0a000004     beq    8298
    8284:    e320f000     nop    {0}
          ^^^^^^^^^^
    8288:    e3a03016     mov    r3, #22
    828c:    e5803000     str    r3, [r0]
    8290:    e3e00000     mvn    r0, #0

This in turn is due to a fixup in ARM ld which transforms branch-to-null
into a nop. It is better than crashing but still wrong since errno
handling is removed.

With the patch, errno_location is restored back in test program.

00008274 <__GI_mmap>:
    8274: e92d40b0  push {r4, r5, r7, lr}
    8278: e59d5014  ldr r5, [sp, #20]
    827c: e1b0ca05  lsls ip, r5, #20
    8280: 0a000004  beq 8298 <__GI_mmap+0x24>
    8284: eb000010  bl 82cc <__errno_location>
    8288: e3a03016  mov r3, #22
    828c: e5803000  str r3, [r0]

Cc: Christian Ruppert <christian.ruppert@abilis.com>
CC: Francois Bedard <Francois.Bedard@synopsys.com>
Cc: Anton Kolesov <Anton.Kolesov@synopsys.com>
Cc: Joern Rennecke <joern.rennecke@embecosm.com>
Cc: Jeremy Bennett <jeremy.bennett@embecosm.com>
Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Peter Korsgaard <peter@korsgaard.com>
Cc: Khem Raj <raj.khem@gmail.com>
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com>
include/netdb.h
libc/misc/internals/__errno_location.c
libc/misc/internals/__h_errno_location.c
libc/sysdeps/linux/common/bits/errno.h