public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* A glibc dynamic linker or gld bug?
@ 1999-07-04 13:52 H.J. Lu
  1999-07-05  2:38 ` Geoff Keating
  0 siblings, 1 reply; 26+ messages in thread
From: H.J. Lu @ 1999-07-04 13:52 UTC (permalink / raw)
  To: Ulrich Drepper; +Cc: Ian Lance Taylor, binutils, GNU C Library, jgg

Hi,

Here is a testcase for a glibc dynamic linker or gld bug:

# make
cc -shared -o libfoo.so -fPIC -O -g foo.c
cc -o bar1.o -c -fPIC -O -g bar.c
cc -o foo1 -O -g libfoo.so main.c bar1.o -Wl,-rpath,.
cc -o bar2.o -c -O -g bar.c
cc -o foo2 -O -g libfoo.so main.c bar2.o -Wl,-rpath,.
for f in foo1 foo2; do echo "Running: $f"; ./$f; \
  if [ $? != 0 ]; then echo Failed; fi; done
Running: foo1
Failed
Running: foo2

The same testcase ran fine under Solaris/x86 and Solaris/Sparc even
with the GNU ld. I suspect the bug is in the weak symbol handling 
in the glibc dynamic linker. Since the Solaris dynamic linker treats
weak as strong, the bug may also be in gld.

-- 
H.J. Lu (hjl@gnu.org)
--
begin 644 shared.tar.gz
M'XL(`,S'?S<``^V7WVO;,!#'\QK]%;<NC"34KJ38%L24;00Z!ALMW<,>]@,4
MQTZ\.G)1'/HP]K]/LA,O@2;9'NP.>I^'&%FZTSFGK^^\6D@=S_A%IT'`H\+W
MH0/`A$_M%=B(E]<-%"`0(R&\D:#<S%(O\#K@-QG4EO6JD!J@L_B1'5UGEB5)
M&P&URVJ3_R3/W:BA/1BE@><=R3_WZOS3P#>SS/."#M"&XMGCF><_507,8IEE
M>22+&"Z!AN2I8T+:8ZO_C_(N3M(L;F*/4_H77-3Z#T1@9CGG#/7?!I.K#V_?
M?;ITKL&9$W)S>VT&8(H!LS^<$/-F&$.O7TX,2#?)-220JOI6"+,<XFB1P]GM
M6JE4S<WR7G(6@GMAKB%\)5V`-($OYO9K>&%>,/`MA&(1J\KL2II3-PLA2:TK
M%1-B=Q]#EDYM35KEL)2I<B.82LW<G'1[_<ED`$X.O3<FBBK^`?2^@_,Y.W?T
MO2P6YV[IA3_NA?^#E]I^#&6%K`TKW6P<.,G-^\F>&T*J<,=VPQVS:GETR((?
MMMA?&V6Q5&/2U4OCJDX&#.V3#LWS_77^M_JO_IYFSM@I_7/ZI_YSP6S]#SC6
M_U9X>:_E?"GA(99W.XT`>:PO*&\.[?F$_J`:$GMNS(C\)*7*^Z]VC(S8J[4#
M8M,LI[DN*DL`'1=KK:S77]AO/"%;_;OSV315:='$'B?[?V9J?C#R&?>-_*W^
MN>D`4/]M,-56^*:V$;U6J,1GQU;_9=/1T!ZG],]VOO\Y$]7WOT#]M\&A^G^D
G`;"-ZJ;B;ZKX3M''>HX@"((@"((@"((@"((@_P^_`1H*[V<`*```
`
end

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: A glibc dynamic linker or gld bug?
  1999-07-04 13:52 A glibc dynamic linker or gld bug? H.J. Lu
@ 1999-07-05  2:38 ` Geoff Keating
  1999-07-05  7:41   ` Jason Gunthorpe
  1999-07-05 20:48   ` Richard Henderson
  0 siblings, 2 replies; 26+ messages in thread
From: Geoff Keating @ 1999-07-05  2:38 UTC (permalink / raw)
  To: hjl; +Cc: drepper, ian, binutils, libc-hacker, jgg

> Mailing-List: contact libc-hacker-help@sourceware.cygnus.com; run by ezmlm
> Date: Sun, 4 Jul 1999 13:52:06 -0700 (PDT)
> Cc: ian@cygnus.com (Ian Lance Taylor), binutils@sourceware.cygnus.com,
>         libc-hacker@sourceware.cygnus.com (GNU C Library), jgg@ualberta.ca
> From: hjl@lucon.org (H.J. Lu)
> 
> Hi,
> 
> Here is a testcase for a glibc dynamic linker or gld bug:
> 
> # make
> cc -shared -o libfoo.so -fPIC -O -g foo.c
> cc -o bar1.o -c -fPIC -O -g bar.c
> cc -o foo1 -O -g libfoo.so main.c bar1.o -Wl,-rpath,.
> cc -o bar2.o -c -O -g bar.c
> cc -o foo2 -O -g libfoo.so main.c bar2.o -Wl,-rpath,.
> for f in foo1 foo2; do echo "Running: $f"; ./$f; \
>   if [ $? != 0 ]; then echo Failed; fi; done
> Running: foo1
> Failed
> Running: foo2
> 
> The same testcase ran fine under Solaris/x86 and Solaris/Sparc even
> with the GNU ld. I suspect the bug is in the weak symbol handling 
> in the glibc dynamic linker. Since the Solaris dynamic linker treats
> weak as strong, the bug may also be in gld.

I can't reproduce this on ppc with binutils snapshot from 981225, and
the released 2.1.1 ld.so.

I suspect there is a (possibly machine-specific) bug in your ld; in
fact, I would suspect the problem is in linking PIC code into
executables.

On my machine, the dynamic linker has no influence whatsoever on
whether 'abort' is called in foo1 or foo2.  The complete list of
relocations generated is:

[geoffk@geoffk shared2]$ objdump -R foo1

foo1:     file format elf32-powerpc

DYNAMIC RELOCATION RECORDS
OFFSET   TYPE              VALUE 
018406d4 R_PPC_JMP_SLOT    abort
018406dc R_PPC_JMP_SLOT    __libc_start_main

and it's the same for foo2.

This is correct.  There is no way that a weak symbol defined in an
executable can be overriden by anything else, so there should be no
relocations referring to it.

-- 
Geoffrey Keating <geoffk@ozemail.com.au>

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: A glibc dynamic linker or gld bug?
  1999-07-05  2:38 ` Geoff Keating
@ 1999-07-05  7:41   ` Jason Gunthorpe
  1999-07-05 20:48   ` Richard Henderson
  1 sibling, 0 replies; 26+ messages in thread
From: Jason Gunthorpe @ 1999-07-05  7:41 UTC (permalink / raw)
  To: Geoff Keating; +Cc: hjl, drepper, ian, binutils, libc-hacker

On Mon, 5 Jul 1999, Geoff Keating wrote:

> I suspect there is a (possibly machine-specific) bug in your ld; in
> fact, I would suspect the problem is in linking PIC code into
> executables.

When I originally looked at this using a different test case (G++ and some
templates) I found that you could only get it to happen reliably on intel,
sparc showed something similar and alpha appeared to work correctly. 

The binutils version was

GNU ld version 2.9.1 (with BFD 2.9.1.0.24)

Jason


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: A glibc dynamic linker or gld bug?
  1999-07-05  2:38 ` Geoff Keating
  1999-07-05  7:41   ` Jason Gunthorpe
@ 1999-07-05 20:48   ` Richard Henderson
  1999-07-06  1:01     ` Geoff Keating
  1999-07-06 19:11     ` Ian Lance Taylor
  1 sibling, 2 replies; 26+ messages in thread
From: Richard Henderson @ 1999-07-05 20:48 UTC (permalink / raw)
  To: Geoff Keating; +Cc: hjl, drepper, ian, binutils, libc-hacker, jgg

On Mon, Jul 05, 1999 at 02:55:51PM +1000, Geoff Keating wrote:
> There is no way that a weak symbol defined in an
> executable can be overriden by anything else, so there should be no
> relocations referring to it.

In the weak model prefered by glibc and SGI, sure there is.
A strong symbol defined in a shared library will override 
the weak symbol in the main executable.

But this is not the model Sun prefers, since it kills their
cute lazy loading scheme.


r~

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: A glibc dynamic linker or gld bug?
  1999-07-05 20:48   ` Richard Henderson
@ 1999-07-06  1:01     ` Geoff Keating
  1999-07-06 12:16       ` Geoff Keating
  1999-07-06 19:11     ` Ian Lance Taylor
  1 sibling, 1 reply; 26+ messages in thread
From: Geoff Keating @ 1999-07-06  1:01 UTC (permalink / raw)
  To: rth; +Cc: hjl, drepper, ian, binutils, libc-hacker, jgg

> Mailing-List: contact libc-hacker-help@sourceware.cygnus.com; run by ezmlm
> Date: Mon, 5 Jul 1999 20:48:14 -0700
> From: Richard Henderson <rth@twiddle.net>
> Cc: hjl@lucon.org, drepper@cygnus.com, ian@cygnus.com,
>         binutils@sourceware.cygnus.com, libc-hacker@sourceware.cygnus.com,
>         jgg@ualberta.ca
> 
> On Mon, Jul 05, 1999 at 02:55:51PM +1000, Geoff Keating wrote:
> > There is no way that a weak symbol defined in an
> > executable can be overriden by anything else, so there should be no
> > relocations referring to it.
> 
> In the weak model prefered by glibc and SGI, sure there is.
> A strong symbol defined in a shared library will override 
> the weak symbol in the main executable.
> 
> But this is not the model Sun prefers, since it kills their
> cute lazy loading scheme.

I now understand the bug report.  The problem on powerpc would look
similar if ld was trying to implement that weak symbol model.

However, clearly it is not, at least not for data objects.  The
problem is that, for instance in the executable given, it is necessary
to emit a R_*_COPY reloc for any data objects which are defined weak.

The current linker (well, the 981225 snapshot), however, only does
this for data objects that go in the .dyn.bss pseudo-section, at least on
i386, sparc, and ppc; that is, data objects that are not defined in
the application.

Note that in this case, ld.so is responsible for determining where the
'true' data for the data object is, and using it for the R_*_COPY
reloc.  It is also responsible for not doing the copy if it turned out
that there is never a strong definition of the symbol.

It must also ensure that any relocs to the weak symbol (from shared
libraries) end up pointed to the copy in the application, in the same
way that relocs to functions in shared libraries end up pointed to a
PLT entry in the application instead of the real function.

To make all this clear, I attach a shell script.  On ppc, it prints
the following at the end:

+ ./weak-w-wp-wm
1 1 1 
+ ./weak-w-sp-wm
1 2 1 
+ ./weak-wp-wm-s
1 1 1 
+ ./weak-sp-wm-s
1 1 1 

On sparc-solaris it prints:

+ ./weak-w-wp-wm 
1 1 1 
+ ./weak-w-sp-wm 
1 1 1 
+ ./weak-wp-wm-s 
1 1 1 
+ ./weak-sp-wm-s 
1 1 1 

which is what I expected.

You're saying that it should print, on glibc

+ ./weak-w-wp-wm
1 1 1 
+ ./weak-w-sp-wm
2 2 2
+ ./weak-wp-wm-s
1 1 1 
+ ./weak-sp-wm-s
1 1 1 

-- 
Geoffrey Keating <geoffk@ozemail.com.au>

===File ~/glibc-tests/weaktest.c============================
#define CONCAT(x,y) x ## y
#define CONCAT2(x,y) CONCAT(x,y)
#define STRING(x) #x
#define STRING2(x) STRING(x)

#ifdef WEAKDATA
#pragma weak dataitem
#endif

const char *dataitem = "weaktest-" STRING2(NUM) ".c";

const char *CONCAT2(getdataitem_,NUM)(void) 
{
  return dataitem;
}

extern const char *getdataitem_1(void);
extern const char *getdataitem_2(void);
extern const char *getdataitem_3(void);
extern const char *getdataitem_4(void);

#ifdef MAIN
#include <stdio.h>
int main(void)
{
  static const char *(*const (funcs[MAIN]))(void) = {
    getdataitem_1,
#if MAIN >= 2
    getdataitem_2,
#endif
#if MAIN >= 3
    getdataitem_3,
#endif
#if MAIN >= 4
    getdataitem_4
#endif
  };
  int i;

  for (i = 0; i < MAIN; i++)
    if (funcs[i])
      printf("getdataitem_%d has getdataitem defined in %s\n", i+1,
	     funcs[i]());
    else
      printf("getdataitem_%d is NULL\n", i+1);
}
#endif
============================================================

===File ~/glibc-tests/weaktest.sh===========================
#!/bin/sh
set -x
set -e
gcc -c -DNUM=1 weaktest.c -O -o weak1-strong.o
gcc -c -DNUM=1 -DWEAKDATA weaktest.c -O -o weak1-weak.o
gcc -c -DNUM=1 -fpic -DWEAKDATA weaktest.c -O -o weak1-weak-pic.o
gcc -shared -DNUM=2 -DWEAKDATA -fpic weaktest.c -O -o weak2-weak-pic.so
gcc -shared -DNUM=2 -DWEAKDATA -fpic weaktest.c -O -o weak2-strong-pic.so
gcc -c -DNUM=3 -DWEAKDATA -DMAIN=3 weaktest.c -O -o weak3-weak-main.o

gcc weak1-weak.o ./weak2-weak-pic.so weak3-weak-main.o -o weak-w-wp-wm
gcc weak1-weak.o ./weak2-strong-pic.so weak3-weak-main.o -o weak-w-sp-wm
gcc weak1-strong.o ./weak2-strong-pic.so weak3-weak-main.o -o weak-s-sp-wm
gcc ./weak2-strong-pic.so weak3-weak-main.o weak1-strong.o -o weak-sp-wm-s

============================================================

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: A glibc dynamic linker or gld bug?
  1999-07-06  1:01     ` Geoff Keating
@ 1999-07-06 12:16       ` Geoff Keating
  0 siblings, 0 replies; 26+ messages in thread
From: Geoff Keating @ 1999-07-06 12:16 UTC (permalink / raw)
  To: geoffk; +Cc: rth, hjl, drepper, ian, binutils, libc-hacker, jgg

Um.  The test case wouldn't have made things much clearer because I
sent the wrong version.  Try this.

-- 
Geoffrey Keating <geoffk@ozemail.com.au>

===File ~/glibc-tests/weaktest.c============================
#define CONCAT(x,y) x ## y
#define CONCAT2(x,y) CONCAT(x,y)
#define STRING(x) #x
#define STRING2(x) STRING(x)

#ifdef WEAKDATA
#pragma weak dataitem
#endif

int dataitem = NUM;

int CONCAT2(getdataitem_,NUM)(void) 
{
  return dataitem;
}

extern int getdataitem_1(void);
extern int getdataitem_2(void);
extern int getdataitem_3(void);
extern int getdataitem_4(void);

#ifdef MAIN
#include <stdio.h>
int main(void)
{
  static int (*const (funcs[MAIN]))(void) = {
    getdataitem_1,
#if MAIN >= 2
    getdataitem_2,
#endif
#if MAIN >= 3
    getdataitem_3,
#endif
#if MAIN >= 4
    getdataitem_4
#endif
  };
  int i;

  for (i = 0; i < MAIN; i++)
    if (funcs[i])
      printf("%d ", funcs[i]());
    else
      printf("NULL ", i+1);
  printf("\n");
}
#endif
============================================================

===File ~/glibc-tests/weaktest.sh===========================
#!/bin/sh
set -x
set -e
gcc -c -DNUM=1 weaktest.c -O -o weak1-strong.o
gcc -c -DNUM=1 -DWEAKDATA weaktest.c -O -o weak1-weak.o
gcc -c -DNUM=1 -fpic -DWEAKDATA weaktest.c -O -o weak1-weak-pic.o
gcc -shared -DNUM=2 -DWEAKDATA -fpic weaktest.c -O -o weak2-weak-pic.so
gcc -shared -DNUM=2 -fpic weaktest.c -O -o weak2-strong-pic.so
gcc -c -DNUM=3 -DWEAKDATA -DMAIN=3 weaktest.c -O -o weak3-weak-main.o

gcc weak1-weak.o ./weak2-weak-pic.so weak3-weak-main.o -o weak-w-wp-wm
gcc weak1-weak.o ./weak2-strong-pic.so weak3-weak-main.o -o weak-w-sp-wm
gcc ./weak2-weak-pic.so weak3-weak-main.o weak1-strong.o -o weak-wp-wm-s
gcc ./weak2-strong-pic.so weak3-weak-main.o weak1-strong.o -o weak-sp-wm-s

set +e
./weak-w-wp-wm
./weak-w-sp-wm
./weak-wp-wm-s
./weak-sp-wm-s
============================================================

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: A glibc dynamic linker or gld bug?
  1999-07-05 20:48   ` Richard Henderson
  1999-07-06  1:01     ` Geoff Keating
@ 1999-07-06 19:11     ` Ian Lance Taylor
  1999-07-06 19:28       ` Richard Henderson
                         ` (2 more replies)
  1 sibling, 3 replies; 26+ messages in thread
From: Ian Lance Taylor @ 1999-07-06 19:11 UTC (permalink / raw)
  To: rth; +Cc: geoffk, hjl, drepper, binutils, libc-hacker, jgg

   Date: Mon, 5 Jul 1999 20:48:14 -0700
   From: Richard Henderson <rth@twiddle.net>

   On Mon, Jul 05, 1999 at 02:55:51PM +1000, Geoff Keating wrote:
   > There is no way that a weak symbol defined in an
   > executable can be overriden by anything else, so there should be no
   > relocations referring to it.

   In the weak model prefered by glibc and SGI, sure there is.
   A strong symbol defined in a shared library will override 
   the weak symbol in the main executable.

   But this is not the model Sun prefers, since it kills their
   cute lazy loading scheme.

In order to implement ``strong defined symbol in shared library
overrides weak defined symbol in main executable'' correctly, we must
ensure that all relocations involving weak defined symbols in the
executable become dynamic relocations resolved at run time.

If we do not, then we will fail to implement the model correctly.
Consider the case in which a main executable defines a symbol weakly,
and a shared library does not define it at all.  At present we will
not generate any dynamic relocations for the weak defined symbol.

However, if we later replace the shared library with one which does
have a strong definition for the symbol, then correct operation would
appear to require that that strong symbol override the weak symbol in
the main executable.

As far as I can see, this can only happen if all relocations involving
the weak defined symbol are copied into the executable as dynamic
relocations.

Are we willing to pay that price for all weak defined symbols in all
dynamically linked executables?

Should we instead go for the half-measure of only copying relocations
for weak defined symbols in the case where we link against a shared
library which has a strong definition for the symbol?  It's easy to
predict that we will get bug reports on this in the future.

None of these choices seem clearly correct to me.

It is perhaps worth noting that the System V linker and the SGI
linker, unlike the GNU linker and the Solaris linker, considers a weak
definition followed by a strong definition to be a multiple definition
error.  (I am therefore a bit surprised to hear that the SGI dynamic
linker permits a strong definition in a shared library to override a
weak definition in an executable, since that appears to contradict the
program linker's behaviour.)

Ian

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: A glibc dynamic linker or gld bug?
  1999-07-06 19:11     ` Ian Lance Taylor
@ 1999-07-06 19:28       ` Richard Henderson
  1999-07-06 19:31         ` Ian Lance Taylor
  1999-07-06 21:45       ` H.J. Lu
  1999-07-07  1:33       ` Geoff Keating
  2 siblings, 1 reply; 26+ messages in thread
From: Richard Henderson @ 1999-07-06 19:28 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: geoffk, hjl, drepper, binutils, libc-hacker, jgg

On Tue, Jul 06, 1999 at 10:10:30PM -0400, Ian Lance Taylor wrote:
> In order to implement ``strong defined symbol in shared library
> overrides weak defined symbol in main executable'' correctly, we must
> ensure that all relocations involving weak defined symbols in the
> executable become dynamic relocations resolved at run time.

/* Should we do dynamic things to this symbol?  */

#define alpha_elf_dynamic_symbol_p(h, info)                             \
  ((((info)->shared && !(info)->symbolic)                               \
    || (((h)->elf_link_hash_flags                                       \
         & (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR))     \
        == (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR))     \
    || (h)->root.type == bfd_link_hash_undefweak                        \
    || (h)->root.type == bfd_link_hash_defweak)                         \
   && (h)->dynindx != -1)

This should probably just be generic.

> Are we willing to pay that price for all weak defined symbols in all
> dynamically linked executables?

I think so.  There are really very few of them in practice.
And failing to override weak symbols is surprising behaviour
from my point of view.

> It is perhaps worth noting that the System V linker and the SGI
> linker, unlike the GNU linker and the Solaris linker, considers a weak
> definition followed by a strong definition to be a multiple definition
> error.

Really?  SGI does this?  I'm a bit surprised.

> (I am therefore a bit surprised to hear that the SGI dynamic
> linker permits a strong definition in a shared library to override a
> weak definition in an executable, since that appears to contradict the
> program linker's behaviour.)

This based on how Uli reported that SGI was arguing the weak symbol
behaviour at load time topic at the IA64 ELF ABI meetings.  (Which,
btw, has reportedly degenerated into a generic ELF ABI meeting.)


r~

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: A glibc dynamic linker or gld bug?
  1999-07-06 19:28       ` Richard Henderson
@ 1999-07-06 19:31         ` Ian Lance Taylor
  0 siblings, 0 replies; 26+ messages in thread
From: Ian Lance Taylor @ 1999-07-06 19:31 UTC (permalink / raw)
  To: rth; +Cc: geoffk, hjl, drepper, binutils, libc-hacker, jgg

   Date: Tue, 6 Jul 1999 19:28:11 -0700
   From: Richard Henderson <rth@twiddle.net>

   > It is perhaps worth noting that the System V linker and the SGI
   > linker, unlike the GNU linker and the Solaris linker, considers a weak
   > definition followed by a strong definition to be a multiple definition
   > error.

   Really?  SGI does this?  I'm a bit surprised.

It actually follows from a careful reading of the SVR4 generic ELF
ABI.  The GNU linker originally behaved this way as well.  However,
somebody complained, and I checked Solaris.  Since Solaris acts
differently, I changed the GNU linker, thus unfortunately perpetuating
a split.

Ian

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: A glibc dynamic linker or gld bug?
  1999-07-06 19:11     ` Ian Lance Taylor
  1999-07-06 19:28       ` Richard Henderson
@ 1999-07-06 21:45       ` H.J. Lu
  1999-07-07  7:36         ` Ian Lance Taylor
  1999-07-07  1:33       ` Geoff Keating
  2 siblings, 1 reply; 26+ messages in thread
From: H.J. Lu @ 1999-07-06 21:45 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: rth, geoffk, hjl, drepper, binutils, libc-hacker, jgg

> If we do not, then we will fail to implement the model correctly.
> Consider the case in which a main executable defines a symbol weakly,
> and a shared library does not define it at all.  At present we will
> not generate any dynamic relocations for the weak defined symbol.
> 
> However, if we later replace the shared library with one which does
> have a strong definition for the symbol, then correct operation would
> appear to require that that strong symbol override the weak symbol in
> the main executable.
> 
> As far as I can see, this can only happen if all relocations involving
> the weak defined symbol are copied into the executable as dynamic
> relocations.

What if the definition in executable is strong? Do you have the same
problem? I don't think we should worry about this.

> 
> Are we willing to pay that price for all weak defined symbols in all
> dynamically linked executables?
> 
> Should we instead go for the half-measure of only copying relocations
> for weak defined symbols in the case where we link against a shared
> library which has a strong definition for the symbol?  It's easy to
> predict that we will get bug reports on this in the future.
> 

I have sent a patch to implement this.


H.J.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: A glibc dynamic linker or gld bug?
  1999-07-06 19:11     ` Ian Lance Taylor
  1999-07-06 19:28       ` Richard Henderson
  1999-07-06 21:45       ` H.J. Lu
@ 1999-07-07  1:33       ` Geoff Keating
  1999-07-07  7:35         ` Ian Lance Taylor
  1999-07-07 11:22         ` Ian Lance Taylor
  2 siblings, 2 replies; 26+ messages in thread
From: Geoff Keating @ 1999-07-07  1:33 UTC (permalink / raw)
  To: ian; +Cc: rth, hjl, drepper, binutils, libc-hacker, jgg

> Date: 6 Jul 1999 22:10:30 -0400
> From: Ian Lance Taylor <ian@zembu.com>

> In order to implement ``strong defined symbol in shared library
> overrides weak defined symbol in main executable'' correctly, we must
> ensure that all relocations involving weak defined symbols in the
> executable become dynamic relocations resolved at run time.
> 
> If we do not, then we will fail to implement the model correctly.
> Consider the case in which a main executable defines a symbol weakly,
> and a shared library does not define it at all.  At present we will
> not generate any dynamic relocations for the weak defined symbol.

There are also other cases that seem to go wrong at present.  For
instance, consider the case where an executable references a weak
symbol, but it is not defined anywhere.  Then, later, some shared
object defines it.  Usually, the address of the symbol (that is,
NULL), has been compiled into the executable in many places and no
relocs are/can be generated.

Or the converse; if the weak symbol is initially defined in a shared
object, referenced by the executable, but later becomes undefined.  I
think that if such a thing happens, it should be an error in ld.so
(only for symbols referenced by the executable, of course).  It would
be nice to make the first case a visible error too.

These cases are not fixable under the usual non-pic-executable model, in
which all addresses referenced by the executable are fixed at link
time.

-- 
Geoffrey Keating <geoffk@ozemail.com.au>

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: A glibc dynamic linker or gld bug?
  1999-07-07  1:33       ` Geoff Keating
@ 1999-07-07  7:35         ` Ian Lance Taylor
  1999-07-07 11:22         ` Ian Lance Taylor
  1 sibling, 0 replies; 26+ messages in thread
From: Ian Lance Taylor @ 1999-07-07  7:35 UTC (permalink / raw)
  To: geoffk; +Cc: rth, hjl, drepper, binutils, jgg

   Date: Wed, 7 Jul 1999 18:23:19 +1000
   From: Geoff Keating <geoffk@ozemail.com.au>

   Or the converse; if the weak symbol is initially defined in a shared
   object, referenced by the executable, but later becomes undefined.  I
   think that if such a thing happens, it should be an error in ld.so
   (only for symbols referenced by the executable, of course).  It would
   be nice to make the first case a visible error too.

I think that this particular case does work correctly now.  Assuming
we are talking about a weak undefined symbol, the program linker will
generate the appropriate relocations, and the dynamic linker will
handle them correctly if the weak symbol disappears from the shared
library.  This was sorted out in February 1999.

Ian

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: A glibc dynamic linker or gld bug?
  1999-07-06 21:45       ` H.J. Lu
@ 1999-07-07  7:36         ` Ian Lance Taylor
  1999-07-07  7:39           ` H.J. Lu
  0 siblings, 1 reply; 26+ messages in thread
From: Ian Lance Taylor @ 1999-07-07  7:36 UTC (permalink / raw)
  To: hjl; +Cc: rth, geoffk, hjl, drepper, binutils, jgg

   Date: Tue, 6 Jul 1999 21:45:02 -0700 (PDT)
   From: hjl@lucon.org (H.J. Lu)

   > If we do not, then we will fail to implement the model correctly.
   > Consider the case in which a main executable defines a symbol weakly,
   > and a shared library does not define it at all.  At present we will
   > not generate any dynamic relocations for the weak defined symbol.
   > 
   > However, if we later replace the shared library with one which does
   > have a strong definition for the symbol, then correct operation would
   > appear to require that that strong symbol override the weak symbol in
   > the main executable.
   > 
   > As far as I can see, this can only happen if all relocations involving
   > the weak defined symbol are copied into the executable as dynamic
   > relocations.

   What if the definition in executable is strong? Do you have the same
   problem? I don't think we should worry about this.

No, we don't have the same problem if the definition in the executable
is strong, because in that case the shared library will never override
the definition.  The only time a shared library can override a
definition is if it is weak in the executable.

Ian

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: A glibc dynamic linker or gld bug?
  1999-07-07  7:36         ` Ian Lance Taylor
@ 1999-07-07  7:39           ` H.J. Lu
  1999-07-07  7:44             ` Ian Lance Taylor
  0 siblings, 1 reply; 26+ messages in thread
From: H.J. Lu @ 1999-07-07  7:39 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: hjl, rth, geoffk, drepper, binutils, jgg

>    > As far as I can see, this can only happen if all relocations involving
>    > the weak defined symbol are copied into the executable as dynamic
>    > relocations.
> 
>    What if the definition in executable is strong? Do you have the same
>    problem? I don't think we should worry about this.
> 
> No, we don't have the same problem if the definition in the executable
> is strong, because in that case the shared library will never override
> the definition.  The only time a shared library can override a
> definition is if it is weak in the executable.
> 

By "problem", I mean the same symbol will have different values in
executable and DSO. When you update one of them, you won't see the
change in the other. If you relink executable against the new DSO,
the symbol in executable will override the one in DSO.

-- 
H.J. Lu (hjl@gnu.org)

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: A glibc dynamic linker or gld bug?
  1999-07-07  7:39           ` H.J. Lu
@ 1999-07-07  7:44             ` Ian Lance Taylor
  1999-07-07  7:57               ` H.J. Lu
  1999-07-07 20:12               ` Geoff Keating
  0 siblings, 2 replies; 26+ messages in thread
From: Ian Lance Taylor @ 1999-07-07  7:44 UTC (permalink / raw)
  To: hjl; +Cc: hjl, rth, geoffk, drepper, binutils, jgg

   Date: Wed, 7 Jul 1999 07:39:01 -0700 (PDT)
   From: hjl@lucon.org (H.J. Lu)

   >    > As far as I can see, this can only happen if all relocations involving
   >    > the weak defined symbol are copied into the executable as dynamic
   >    > relocations.
   > 
   >    What if the definition in executable is strong? Do you have the same
   >    problem? I don't think we should worry about this.
   > 
   > No, we don't have the same problem if the definition in the executable
   > is strong, because in that case the shared library will never override
   > the definition.  The only time a shared library can override a
   > definition is if it is weak in the executable.

   By "problem", I mean the same symbol will have different values in
   executable and DSO. When you update one of them, you won't see the
   change in the other. If you relink executable against the new DSO,
   the symbol in executable will override the one in DSO.

I guess I don't understand.  The DSO should have relocations for all
uses of the symbol, so it will wind up seeing the definition in the
executable.  At runtime the symbol will not have different values.
This is an ordinary case in which the executable overrides the DSO.

As far as I know, the only way you can get a DSO to see a different
value from the main executable is to use -Bsymbolic or version
scripts.  Also, you have just reported a case in which it happens due
to the use of weak defined symbols in the executable.  But there
definitely should not be any way to make the DSO and the executable
see a different value for a strong defined symbol.

Ian

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: A glibc dynamic linker or gld bug?
  1999-07-07  7:44             ` Ian Lance Taylor
@ 1999-07-07  7:57               ` H.J. Lu
  1999-07-07  8:03                 ` Ian Lance Taylor
  1999-07-07 20:12               ` Geoff Keating
  1 sibling, 1 reply; 26+ messages in thread
From: H.J. Lu @ 1999-07-07  7:57 UTC (permalink / raw)
  To: ian; +Cc: drepper, binutils

>    By "problem", I mean the same symbol will have different values in
>    executable and DSO. When you update one of them, you won't see the
>    change in the other. If you relink executable against the new DSO,
>    the symbol in executable will override the one in DSO.
> 
> I guess I don't understand.  The DSO should have relocations for all
> uses of the symbol, so it will wind up seeing the definition in the
> executable.  At runtime the symbol will not have different values.
> This is an ordinary case in which the executable overrides the DSO.

Here is the testcase.

> 
> As far as I know, the only way you can get a DSO to see a different
> value from the main executable is to use -Bsymbolic or version
> scripts.  Also, you have just reported a case in which it happens due
> to the use of weak defined symbols in the executable.  But there
> definitely should not be any way to make the DSO and the executable
> see a different value for a strong defined symbol.
> 

# make
cc -shared -o libfoo.so -fPIC -O -g foo.c
cc -o foo -O -g libfoo.so main.c -Wl,-rpath,.
for f in foo; do echo "Running: $f"; ./$f; \
  if [ $? != 0 ]; then echo Failed; fi; done
Running: foo
main: 0x8049670
DSO: (nil)
cc -shared -o libfoo.so -fPIC -O -g foo.c -DDEF
for f in foo; do echo "Running: $f"; ./$f; \
  if [ $? != 0 ]; then echo Failed; fi; done
Running: foo
main: 0x8049670
DSO: 0x2aac0634
Failed


-- 
H.J. Lu (hjl@gnu.org)
---
#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.2).
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
# Made on 1999-07-07 07:52 PDT by <hjl@osmium.su.varesearch.com>.
# Source directory was `/home/hjl/bugs/gas/shared4'.
#
# Existing files will *not* be overwritten unless `-c' is specified.
#
# This shar contains:
# length mode       name
# ------ ---------- ------------------------------------------
#    442 -rw-r--r-- Makefile
#    113 -rw-r--r-- foo.c
#    188 -rw-r--r-- main.c
#
save_IFS="${IFS}"
IFS="${IFS}:"
gettext_dir=FAILED
locale_dir=FAILED
first_param="$1"
for dir in $PATH
do
  if test "$gettext_dir" = FAILED && test -f $dir/gettext \
     && ($dir/gettext --version >/dev/null 2>&1)
  then
    set `$dir/gettext --version 2>&1`
    if test "$3" = GNU
    then
      gettext_dir=$dir
    fi
  fi
  if test "$locale_dir" = FAILED && test -f $dir/shar \
     && ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
  then
    locale_dir=`$dir/shar --print-text-domain-dir`
  fi
done
IFS="$save_IFS"
if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
then
  echo=echo
else
  TEXTDOMAINDIR=$locale_dir
  export TEXTDOMAINDIR
  TEXTDOMAIN=sharutils
  export TEXTDOMAIN
  echo="$gettext_dir/gettext -s"
fi
touch -am 1231235999 $$.touch >/dev/null 2>&1
if test ! -f 1231235999 && test -f $$.touch; then
  shar_touch=touch
else
  shar_touch=:
  echo
  $echo 'WARNING: not restoring timestamps.  Consider getting and'
  $echo "installing GNU \`touch', distributed in GNU File Utilities..."
  echo
fi
rm -f 1231235999 $$.touch
#
if mkdir _sh00601; then
  $echo 'x -' 'creating lock directory'
else
  $echo 'failed to create lock directory'
  exit 1
fi
# ============= Makefile ==============
if test -f 'Makefile' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'Makefile' '(file already exists)'
else
  $echo 'x -' extracting 'Makefile' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'Makefile' &&
CFLAGS=-O -g
X
PROGS= foo
X
all: $(PROGS)
X	for f in $(PROGS); do echo "Running: $$f"; ./$$f; \
X	  if [ $$? != 0 ]; then echo Failed; fi; done
X	cc -shared -o libfoo.so -fPIC -O -g foo.c -DDEF
X	for f in $(PROGS); do echo "Running: $$f"; ./$$f; \
X	  if [ $$? != 0 ]; then echo Failed; fi; done
X
foo: libfoo.so main.c
X	$(CC) -o $@ $(CFLAGS) $^ -Wl,-rpath,.
X
libfoo.so: foo.c
X	$(CC) -shared -o $@ -fPIC $(CFLAGS) $^
X
clean:
X	rm -f $(PROGS) *.so *.o
SHAR_EOF
  $shar_touch -am 0707075199 'Makefile' &&
  chmod 0644 'Makefile' ||
  $echo 'restore of' 'Makefile' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'Makefile:' 'MD5 check failed'
f0c616a6b715ce3606b9d73421d5d107  Makefile
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'Makefile'`"
    test 442 -eq "$shar_count" ||
    $echo 'Makefile:' 'original size' '442,' 'current size' "$shar_count!"
  fi
fi
# ============= foo.c ==============
if test -f 'foo.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'foo.c' '(file already exists)'
else
  $echo 'x -' extracting 'foo.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'foo.c' &&
#ifdef DEF
int deallocate = 0;
X
int *
foo ()
{
X  return &deallocate;
}
#else
int *
foo ()
{
X  return 0;
}
#endif
SHAR_EOF
  $shar_touch -am 0707075199 'foo.c' &&
  chmod 0644 'foo.c' ||
  $echo 'restore of' 'foo.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'foo.c:' 'MD5 check failed'
a31cb6bbe33929046ce845bca37bf145  foo.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'foo.c'`"
    test 113 -eq "$shar_count" ||
    $echo 'foo.c:' 'original size' '113,' 'current size' "$shar_count!"
  fi
fi
# ============= main.c ==============
if test -f 'main.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'main.c' '(file already exists)'
else
  $echo 'x -' extracting 'main.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'main.c' &&
int deallocate = 0;
X
int * foo ();
X
int
main ()
{
X  printf ("main: %p\n", &deallocate);
X  printf ("DSO: %p\n", foo ());
X  if (foo () && foo () != &deallocate)
X    abort ();
X
X  return 0;
}
SHAR_EOF
  $shar_touch -am 0707074999 'main.c' &&
  chmod 0644 'main.c' ||
  $echo 'restore of' 'main.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'main.c:' 'MD5 check failed'
88c903c7c636b45c40506df740f4de01  main.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'main.c'`"
    test 188 -eq "$shar_count" ||
    $echo 'main.c:' 'original size' '188,' 'current size' "$shar_count!"
  fi
fi
rm -fr _sh00601
exit 0

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: A glibc dynamic linker or gld bug?
  1999-07-07  7:57               ` H.J. Lu
@ 1999-07-07  8:03                 ` Ian Lance Taylor
  0 siblings, 0 replies; 26+ messages in thread
From: Ian Lance Taylor @ 1999-07-07  8:03 UTC (permalink / raw)
  To: hjl; +Cc: drepper, binutils

   Date: Wed, 7 Jul 1999 07:57:50 -0700 (PDT)
   From: hjl@lucon.org (H.J. Lu)

   >    By "problem", I mean the same symbol will have different values in
   >    executable and DSO. When you update one of them, you won't see the
   >    change in the other. If you relink executable against the new DSO,
   >    the symbol in executable will override the one in DSO.
   > 
   > I guess I don't understand.  The DSO should have relocations for all
   > uses of the symbol, so it will wind up seeing the definition in the
   > executable.  At runtime the symbol will not have different values.
   > This is an ordinary case in which the executable overrides the DSO.

   Here is the testcase.

I see what you mean.  You're right, to make this work you need to use
the --export-dynamic option when you link the executable.  That is the
default on Solaris, perhaps for this very reason.  What a pain.

Ian

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: A glibc dynamic linker or gld bug?
  1999-07-07  1:33       ` Geoff Keating
  1999-07-07  7:35         ` Ian Lance Taylor
@ 1999-07-07 11:22         ` Ian Lance Taylor
  1999-07-07 20:13           ` Geoff Keating
  1 sibling, 1 reply; 26+ messages in thread
From: Ian Lance Taylor @ 1999-07-07 11:22 UTC (permalink / raw)
  To: geoffk; +Cc: rth, hjl, drepper, binutils, jgg

   Date: Wed, 7 Jul 1999 18:23:19 +1000
   From: Geoff Keating <geoffk@ozemail.com.au>

   These cases are not fixable under the usual non-pic-executable model, in
   which all addresses referenced by the executable are fixed at link
   time.

No, they are fixable.  We just need to generate the appropriate
dynamic relocations.  At present we do not do that, but there is
nothing preventing us from doing it.

Ian

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: A glibc dynamic linker or gld bug?
  1999-07-07  7:44             ` Ian Lance Taylor
  1999-07-07  7:57               ` H.J. Lu
@ 1999-07-07 20:12               ` Geoff Keating
  1999-07-07 20:16                 ` Ian Lance Taylor
  1 sibling, 1 reply; 26+ messages in thread
From: Geoff Keating @ 1999-07-07 20:12 UTC (permalink / raw)
  To: ian; +Cc: hjl, hjl, rth, drepper, binutils, jgg

> Date: 7 Jul 1999 10:43:18 -0400
> From: Ian Lance Taylor <ian@zembu.com>

> As far as I know, the only way you can get a DSO to see a different
> value from the main executable is to use -Bsymbolic or version
> scripts.  Also, you have just reported a case in which it happens due
> to the use of weak defined symbols in the executable.  But there
> definitely should not be any way to make the DSO and the executable
> see a different value for a strong defined symbol.

If the DSO that is linked with does not reference the symbol, but the
actual DSO used at runtime does, then the executable will not export
the symbol value.

I don't think you would want to 'fix' that, it would mean exporting
every global symbol the executable defines.

-- 
Geoffrey Keating <geoffk@ozemail.com.au>

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: A glibc dynamic linker or gld bug?
  1999-07-07 11:22         ` Ian Lance Taylor
@ 1999-07-07 20:13           ` Geoff Keating
  1999-07-07 20:28             ` Ian Lance Taylor
  0 siblings, 1 reply; 26+ messages in thread
From: Geoff Keating @ 1999-07-07 20:13 UTC (permalink / raw)
  To: ian; +Cc: rth, hjl, drepper, binutils, jgg

> Date: 7 Jul 1999 14:21:41 -0400
> From: Ian Lance Taylor <ian@zembu.com>
> CC: rth@twiddle.net, hjl@lucon.org, drepper@cygnus.com,
>         binutils@sourceware.cygnus.com, jgg@ualberta.ca
> 
>    Date: Wed, 7 Jul 1999 18:23:19 +1000
>    From: Geoff Keating <geoffk@ozemail.com.au>
> 
>    These cases are not fixable under the usual non-pic-executable model, in
>    which all addresses referenced by the executable are fixed at link
>    time.
> 
> No, they are fixable.  We just need to generate the appropriate
> dynamic relocations.  At present we do not do that, but there is
> nothing preventing us from doing it.

To be precise:

These cases, if fixed by outputting all relevant relocations, would
lead to incredibly inefficient program loading because it would be
necessary to have run-time relocs for any weak symbol referenced by the
executable.  It would also cost large amounts of memory because the
text segment of executables would no longer be sharable between
invocations.


For instance, consider the following tiny bit of code, which we assume
goes in an executable:

extern int foo(void);
int main(void) { if (foo) return foo(); else return 42; }


This compiles to an object file with the following relocs: 

RELOCATION RECORDS FOR [.text]:
OFFSET   TYPE              VALUE 
0000000e R_PPC_ADDR16_HA   foo
00000012 R_PPC_ADDR16_LO   foo
00000024 R_PPC_REL24       foo

The first two are from the 'if (foo)', the third is the call in
'return foo()'.

Suppose we have a DSO like this:

#pragma weak foo
int foo(void) { return 2; }

Now, at present, a PLT entry is generated for foo() in the executable,
and all the relocs in the object file are pointed at it.  The relocs
generated are in the executable are:

DYNAMIC RELOCATION RECORDS
OFFSET   TYPE              VALUE 
01840650 R_PPC_JMP_SLOT    __libc_start_main
01840658 R_PPC_JMP_SLOT    foo

I think these are correct, and haven't changed recently.

Now, suppose foo() goes away in a future version of the DSO.  Now we
have a weak symbol which isn't defined anywhere, so it has address 0.

In that case, the test `if (foo)' will still pass, because it was
decided at link time where the ADDR16 relocs were bound (they get
bound to address 01840658, to the PLT entry).  The PLT entry will
branch to location 0, so the program will crash.  The only way to fix
this would be export the ADDR16 (and, to be completely correct, the
REL24) relocs; it would be like a DSO which had been compiled without
-fpic.

This will happen a lot.  For instance, in current glibc 'open()' is
weak.  open() is not likely to go away, but the linker doesn't know
that.


On some old systems, this implies that the .text section in the
executable must be put in a read-write segment, because you can't
change memory permissions on executable segments.

-- 
Geoffrey Keating <geoffk@ozemail.com.au>

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: A glibc dynamic linker or gld bug?
  1999-07-07 20:12               ` Geoff Keating
@ 1999-07-07 20:16                 ` Ian Lance Taylor
  0 siblings, 0 replies; 26+ messages in thread
From: Ian Lance Taylor @ 1999-07-07 20:16 UTC (permalink / raw)
  To: geoffk; +Cc: hjl, hjl, rth, drepper, binutils, jgg

   Date: Thu, 8 Jul 1999 12:27:36 +1000
   From: Geoff Keating <geoffk@ozemail.com.au>

   > As far as I know, the only way you can get a DSO to see a different
   > value from the main executable is to use -Bsymbolic or version
   > scripts.  Also, you have just reported a case in which it happens due
   > to the use of weak defined symbols in the executable.  But there
   > definitely should not be any way to make the DSO and the executable
   > see a different value for a strong defined symbol.

   If the DSO that is linked with does not reference the symbol, but the
   actual DSO used at runtime does, then the executable will not export
   the symbol value.

Yes, I did forget that case.

   I don't think you would want to 'fix' that, it would mean exporting
   every global symbol the executable defines.

That is exactly what the Solaris linker does, as it happens.  The
Solaris linker defaults to the behaviour which in the GNU linker can
be invoked with the --export-dynamic option.

Ian

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: A glibc dynamic linker or gld bug?
  1999-07-07 20:13           ` Geoff Keating
@ 1999-07-07 20:28             ` Ian Lance Taylor
  1999-07-08 17:29               ` Geoff Keating
  0 siblings, 1 reply; 26+ messages in thread
From: Ian Lance Taylor @ 1999-07-07 20:28 UTC (permalink / raw)
  To: geoffk; +Cc: rth, hjl, drepper, binutils, jgg

   Date: Thu, 8 Jul 1999 13:12:03 +1000
   From: Geoff Keating <geoffk@ozemail.com.au>

   >    These cases are not fixable under the usual non-pic-executable model, in
   >    which all addresses referenced by the executable are fixed at link
   >    time.
   > 
   > No, they are fixable.  We just need to generate the appropriate
   > dynamic relocations.  At present we do not do that, but there is
   > nothing preventing us from doing it.

   To be precise:

   These cases, if fixed by outputting all relevant relocations, would
   lead to incredibly inefficient program loading because it would be
   necessary to have run-time relocs for any weak symbol referenced by the
   executable.  It would also cost large amounts of memory because the
   text segment of executables would no longer be sharable between
   invocations.

Does the average executable really reference that many weak symbols?

   For instance, consider the following tiny bit of code, which we assume
   goes in an executable:

   extern int foo(void);
   int main(void) { if (foo) return foo(); else return 42; }

I can only follow your example if I assume that foo is weak undefined
in the executable, although that does not appear above.

   Now, suppose foo() goes away in a future version of the DSO.  Now we
   have a weak symbol which isn't defined anywhere, so it has address 0.

If foo is not weak undefined in the executable, then if it goes away
in the DSO, the dynamic linker will signal an error at run time.  It
doesn't matter that the foo is weak defined in the DSO.  If the
executable has a non-weak reference which can not be satisfied, the
program can not be run.

   This will happen a lot.  For instance, in current glibc 'open()' is
   weak.  open() is not likely to go away, but the linker doesn't know
   that.

The fact that open is weak defined in libc.so does not imply that it
is weak undefined in the executable.

I completely agree that to fix the various cases in your original note
we must issue dynamic relocations for all weak symbols, both defined
and undefined, in the executable.  However, we do not have to issue
relocations for symbols merely because they happen to be weak in a
shared object.

The average executable probably doesn't refer to any weak symbols in
user written code.  On the crt*.o files on my RedHat 5.2 system, the
weak symbol data_start is defined and the weak symbol __gmon_start__
is referenced.  The relocations for __gmon_start__ are GOT and PLT
relocs, and as such should not require any modification to the text
section at run time.

I do agree that making this work reliably would have a cost.  But I'm
not sure the cost would be as high as you suggest it would be.

Ian

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: A glibc dynamic linker or gld bug?
  1999-07-07 20:28             ` Ian Lance Taylor
@ 1999-07-08 17:29               ` Geoff Keating
  1999-07-09  6:11                 ` Franz Sirl
  0 siblings, 1 reply; 26+ messages in thread
From: Geoff Keating @ 1999-07-08 17:29 UTC (permalink / raw)
  To: ian; +Cc: rth, hjl, drepper, binutils, jgg

> Date: 7 Jul 1999 23:27:28 -0400
> From: Ian Lance Taylor <ian@zembu.com>

>    Date: Thu, 8 Jul 1999 13:12:03 +1000
>    From: Geoff Keating <geoffk@ozemail.com.au>

>    These cases, if fixed by outputting all relevant relocations, would
>    lead to incredibly inefficient program loading because it would be
>    necessary to have run-time relocs for any weak symbol referenced by the
>    executable.  It would also cost large amounts of memory because the
>    text segment of executables would no longer be sharable between
>    invocations.
> 
> Does the average executable really reference that many weak symbols?

It does both reference many weak symbols, and make many weak
references, but the last turns out to be a linker bug.

I attach a patch to fix the bug.  I'd like to attach a test case too,
but I think it will be better to wait until we've decided how all the
weak symbol stuff should work.

I predict that with this patch, the typical executable will make no
external weak references at all.  [I can only 'predict' at present
because the 990706 snapshot is failing too many tests to install.]

The typical executable will still make a few weak definitions,
typically to __gmon_start__, stat, mknod, and related functions
(perhaps more in C++ depending on what wacky things are going on
there).  This doesn't attract as great a performance penalty, because
it can only become defined to something else, not NULL.

-- 
Geoffrey Keating <geoffk@ozemail.com.au>

===File ~/patches/binutils-19.diff==========================
1999-07-08  Geoff Keating  <geoffk@cygnus.com>

	* elflink.h (elf_link_output_extsym): Don't output a weak
	reference to an undefined symbol just because it was
	defined weak in a shared object.

--- binutils-990629/bfd/elflink.h~	Thu Jul  8 23:24:49 1999
+++ binutils-990629/bfd/elflink.h	Thu Jul  8 23:36:16 1999
@@ -4668,14 +4668,22 @@ elf_link_output_extsym (h, data)
 
   /* If we are marking the symbol as undefined, and there are no
      non-weak references to this symbol from a regular object, then
-     mark the symbol as weak undefined.  We can't do this earlier,
+     mark the symbol as weak undefined; if there are non-weak
+     references, mark the symbol as strong.  We can't do this earlier,
      because it might not be marked as undefined until the
      finish_dynamic_symbol routine gets through with it.  */
   if (sym.st_shndx == SHN_UNDEF
-      && sym.st_info == ELF_ST_INFO (STB_GLOBAL, h->type)
       && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) != 0
-      && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR_NONWEAK) == 0)
-    sym.st_info = ELF_ST_INFO (STB_WEAK, h->type);
+      && (ELF_ST_BIND(sym.st_info) == STB_GLOBAL
+	  || ELF_ST_BIND(sym.st_info) == STB_WEAK))
+    {
+      int bindtype;
+      if ((h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR_NONWEAK) != 0)
+	bindtype = STB_GLOBAL;
+      else
+	bindtype = STB_WEAK;
+      sym.st_info = ELF_ST_INFO (bindtype, ELF_ST_TYPE (sym.st_info));
+    }
 
   /* If this symbol should be put in the .dynsym section, then put it
      there now.  We have already know the symbol index.  We also fill
============================================================

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: A glibc dynamic linker or gld bug?
  1999-07-08 17:29               ` Geoff Keating
@ 1999-07-09  6:11                 ` Franz Sirl
  1999-07-10  3:14                   ` Geoff Keating
  0 siblings, 1 reply; 26+ messages in thread
From: Franz Sirl @ 1999-07-09  6:11 UTC (permalink / raw)
  To: Geoff Keating; +Cc: binutils

At 16:18 08.07.99 , Geoff Keating wrote:


>I predict that with this patch, the typical executable will make no
>external weak references at all.  [I can only 'predict' at present
>because the 990706 snapshot is failing too many tests to install.]

Testsuite tests or your personal tests? 990626 checked fine for me on PPC, 
except one test of ld-shared, but this seems to be a bug in the dynamic linker.

In any case I'll try current cvs now again.

Franz.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: A glibc dynamic linker or gld bug?
  1999-07-09  6:11                 ` Franz Sirl
@ 1999-07-10  3:14                   ` Geoff Keating
  1999-07-10  5:40                     ` Ian Lance Taylor
  0 siblings, 1 reply; 26+ messages in thread
From: Geoff Keating @ 1999-07-10  3:14 UTC (permalink / raw)
  To: Franz.Sirl-kernel; +Cc: binutils

> Date: Fri, 09 Jul 1999 15:10:43 +0200
> From: Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
> Cc: binutils@sourceware.cygnus.com
> 
> At 16:18 08.07.99 , Geoff Keating wrote:
> 
> 
> >I predict that with this patch, the typical executable will make no
> >external weak references at all.  [I can only 'predict' at present
> >because the 990706 snapshot is failing too many tests to install.]
> 
> Testsuite tests or your personal tests? 990626 checked fine for me on PPC, 
> except one test of ld-shared, but this seems to be a bug in the dynamic linker.
> 
> In any case I'll try current cvs now again.

For me, it segfaults in the bootstrap test when it tries to run `ld
-r' (in all four bootstrap tests).  I haven't tried the previous
week's snapshot, it may a recent change.

I had to hack the .exp file to make the bootstrap test run.  The test
case skips this test if the path to the directory in which you are
building ld contains a symbolic link.

-- 
Geoffrey Keating <geoffk@ozemail.com.au>

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: A glibc dynamic linker or gld bug?
  1999-07-10  3:14                   ` Geoff Keating
@ 1999-07-10  5:40                     ` Ian Lance Taylor
  0 siblings, 0 replies; 26+ messages in thread
From: Ian Lance Taylor @ 1999-07-10  5:40 UTC (permalink / raw)
  To: geoffk; +Cc: Franz.Sirl-kernel, binutils

   Date: Sat, 10 Jul 1999 18:18:23 +1000
   From: Geoff Keating <geoffk@ozemail.com.au>

   For me, it segfaults in the bootstrap test when it tries to run `ld
   -r' (in all four bootstrap tests).  I haven't tried the previous
   week's snapshot, it may a recent change.

ld -r was temporarily broken on some platforms from 1999-07-01 to
1999-07-07.  It should work now.

Ian

^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~1999-07-10  5:40 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1999-07-04 13:52 A glibc dynamic linker or gld bug? H.J. Lu
1999-07-05  2:38 ` Geoff Keating
1999-07-05  7:41   ` Jason Gunthorpe
1999-07-05 20:48   ` Richard Henderson
1999-07-06  1:01     ` Geoff Keating
1999-07-06 12:16       ` Geoff Keating
1999-07-06 19:11     ` Ian Lance Taylor
1999-07-06 19:28       ` Richard Henderson
1999-07-06 19:31         ` Ian Lance Taylor
1999-07-06 21:45       ` H.J. Lu
1999-07-07  7:36         ` Ian Lance Taylor
1999-07-07  7:39           ` H.J. Lu
1999-07-07  7:44             ` Ian Lance Taylor
1999-07-07  7:57               ` H.J. Lu
1999-07-07  8:03                 ` Ian Lance Taylor
1999-07-07 20:12               ` Geoff Keating
1999-07-07 20:16                 ` Ian Lance Taylor
1999-07-07  1:33       ` Geoff Keating
1999-07-07  7:35         ` Ian Lance Taylor
1999-07-07 11:22         ` Ian Lance Taylor
1999-07-07 20:13           ` Geoff Keating
1999-07-07 20:28             ` Ian Lance Taylor
1999-07-08 17:29               ` Geoff Keating
1999-07-09  6:11                 ` Franz Sirl
1999-07-10  3:14                   ` Geoff Keating
1999-07-10  5:40                     ` Ian Lance Taylor

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).