bug-binutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Bug ld/17205] New: alpha procedure call invalid relaxation


From: martin at NetBSD dot org
Subject: [Bug ld/17205] New: alpha procedure call invalid relaxation
Date: Sun, 27 Jul 2014 15:21:38 +0000

https://sourceware.org/bugzilla/show_bug.cgi?id=17205

            Bug ID: 17205
           Summary: alpha procedure call invalid relaxation
           Product: binutils
           Version: 2.23
            Status: NEW
          Severity: normal
          Priority: P2
         Component: ld
          Assignee: unassigned at sourceware dot org
          Reporter: martin at NetBSD dot org

On the alpha elf target there are basically two types of functions, they are
marked with .prologue 0 or .prologue 1 by the compiler. The difference is setup
of the gp register for access to variables via GOT. The caller restores this
register after the call, but in some cases setup can be skipped and restoration
NOP'd.

I think we are hitting a case where such an optimization is erroneously applied
in NetBSD when linking threaded programs statically. The original bug report is
here: http://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=48709

The problem happens with a weak symbol function of type ".prologue 0" being
overwritten by another implementation of type ".prologue 1". In the NetBSD case
the issue is obscured a bit more by symbol renaming, but I think the below code
demonstrates the mis-relaxation already (unless I misunderstand something).

With this code in "main.c":
--8<--
#include <stdio.h>

int external_init_used = 0;

__attribute__((weak))
void
subsys_init(void)
{
        /* do nothing */
}

int
main(int argc, char **argv)
{
        subsys_init();
        if (external_init_used)
                printf("something overwrote subsys_init\n");
        else
                printf("our own subsys_init stub has been used\n");
        return 0;
}
-->8--

and this in "extern.c":

--8<--
#include <stdio.h>

extern int external_init_used;

void
subsys_init(void)
{
        external_init_used = 1;
        printf("initializing...\n");
}
-->8--

use this command line:
cc -static -Wall -O2 main.c extern.c

For details, check with -S and see that .prologue values differ between the
stub in main.c and the overwrite in extern.c. Also note that gcc did generate
correct code (including restoring gp after the call to subsys_init).

Now invoke gdb on the resulting binary and look at the call to subsys_init:

(gdb) x/16i main
   0x120026d40 <main>:  ldah    gp,2(t12)
   0x120026d44 <main+4>:        lda     gp,11112(gp)
   0x120026d48 <main+8>:        lda     sp,-16(sp)
   0x120026d4c <main+12>:       stq     ra,0(sp)
   0x120026d50 <main+16>:       unop    
   0x120026d54 <main+20>:       bsr     ra,0x1200003d8 <subsys_init+8>
   0x120026d58 <main+24>:       unop    
   0x120026d5c <main+28>:       unop    

Note the +8 offset for the subsys_init call, which means gp setup will be
skipped.
The last two lines are stubbed out reload instructions for the gp register
        ldah $29,0($26)         !gpdisp!7
        lda $29,0($29)          !gpdisp!7

This relaxation would be valid if the final call target would be the stub in
main.c, but as the weak symbol is overwritten they are invalid.

-- 
You are receiving this mail because:
You are on the CC list for the bug.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]