[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.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Bug ld/17205] New: alpha procedure call invalid relaxation,
martin at NetBSD dot org <=