public inbox for gas2@sourceware.org
 help / color / mirror / Atom feed
* properties of weak symbols
@ 1994-09-13 23:16 Rick Sladkey
  1994-09-14  5:27 ` Eric Youngdale
  1994-09-14  8:22 ` Ian Lance Taylor
  0 siblings, 2 replies; 5+ messages in thread
From: Rick Sladkey @ 1994-09-13 23:16 UTC (permalink / raw)
  To: gas2; +Cc: Eric Youngdale

I am not quite sure how elf weak symbols are supposed to work but the
following program doesn't work when linked dynamically using
gas-940906 configured for i486-linuxelf.

main()
{
	extern char **environ;
	extern char **__environ;

	printf("%s\n", environ[0]);
	printf("%s\n", __environ[0]);
}

Under Linux (whose libc is partically glibc derived) __environ
is supposed to be an alias for environ.  I don't know why.

Anyway, when compiled it resolves environ and __environ to two
different addresses and environ ends up NULL.  This is becuase the
"weakness" of environ is lost when linking --shared.  This only
happens when there is a reference to the weak symbol in another object
in the link.

Here is a precise example:

$ cat __environ.S
.globl __environ
.data
__environ:
	.long 0
.type __environ,@object
.size __environ,4
.weak environ
environ = __environ
$ cat environ-ref.c
environ_ref()
{
	extern char **environ;
	printf("%s\n", environ[0]);
}
$ gcc -b i486-linuxelf -fPIC -c __environ.S environ-ref.c
$ nm __environ.o | grep environ$
00000000 D __environ
00000000 ? environ
$ nm environ-ref.o | grep environ$
         U environ
$ ld -m elf_i386 --shared __environ.o environ-ref.o -o libenv.so
$ nm libenv.so | grep environ$
00001260 D __environ
00001260 D environ
$ gcc -b i486-linuxelf -nostdlib /usr/lib/elf/crt0.o data.c -L. -lenv /usr/lib/elf/libc.a
$ nm | grep environ$
08009480 B __environ
08009484 B environ
$ 

Notice how the last grep shows environ and __environ being allocated
at different addresses.  So you can see that it is impossible as it
currently stands to have a reference to an weak symbol in an library
linked as a shared object.  Linking relocatably has the same behavior.

My intuition is that linking --shared or -r should cause weak symbols
to be preserved and cause references to them to be resolved to the
symbol the weak symbol is equated with.  That is, weak symbols should
only disappear in a ordinary link.

How does the SVR4 linker handle this?

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

* properties of weak symbols
  1994-09-13 23:16 properties of weak symbols Rick Sladkey
@ 1994-09-14  5:27 ` Eric Youngdale
  1994-09-14  8:22 ` Ian Lance Taylor
  1 sibling, 0 replies; 5+ messages in thread
From: Eric Youngdale @ 1994-09-14  5:27 UTC (permalink / raw)
  To: jrs; +Cc: gas2

>My intuition is that linking --shared or -r should cause weak symbols
>to be preserved and cause references to them to be resolved to the
>symbol the weak symbol is equated with.  That is, weak symbols should
>only disappear in a ordinary link.
>
>How does the SVR4 linker handle this?

	Under SVr4, the weakness of a symbol is lost if you reference the
symbol within the shared object.  Thus you need to be diligent about not
using any weak symbols within the shared library.

	I believe that even if the symbol is referenced and the weakness lost,
the two symbols should be assigned the same address.  This is probably a bug
of some sort, I guess.

-Eric



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

* Re: properties of weak symbols
  1994-09-13 23:16 properties of weak symbols Rick Sladkey
  1994-09-14  5:27 ` Eric Youngdale
@ 1994-09-14  8:22 ` Ian Lance Taylor
  1994-09-14 11:23   ` Roland McGrath
  1994-09-14 12:03   ` Eric Youngdale
  1 sibling, 2 replies; 5+ messages in thread
From: Ian Lance Taylor @ 1994-09-14  8:22 UTC (permalink / raw)
  To: jrs; +Cc: gas2, ericy

   From: jrs@world.std.com (Rick Sladkey)
   Date: Wed, 14 Sep 1994 02:17:12 EDT

   I am not quite sure how elf weak symbols are supposed to work but the
   following program doesn't work when linked dynamically using
   gas-940906 configured for i486-linuxelf.

   main()
   {
	   extern char **environ;
	   extern char **__environ;

	   printf("%s\n", environ[0]);
	   printf("%s\n", __environ[0]);
   }

I don't think your test case showed why this program would fail,
unless your libc is incorrect in some respect.

   Under Linux (whose libc is partically glibc derived) __environ
   is supposed to be an alias for environ.  I don't know why.

It's because environ is in the ANSI C reserved name space.  Therefore,
a user program must be permitted to redefine environ.  However, some
library routines will need to get access to the environment.  The
library routines must always refer to __environ, not to environ.  If
they ever refer to environ, they could get confused by a user program
which redefined environ.  environ is made a weak alias for __environ
to provide the traditional UNIX behaviour for programs which do not
redefine environ.

   Anyway, when compiled it resolves environ and __environ to two
   different addresses and environ ends up NULL.  This is becuase the
   "weakness" of environ is lost when linking --shared.  This only
   happens when there is a reference to the weak symbol in another object
   in the link.

By the above argument, there should never be a reference to environ,
rather than __environ, in another object in the link --shared.  At
least, not for libc.  If there is such a reference, you are doing
something wrong.

However, I agree that the linker is doing something strange.  I
checked your test case on Solaris, and it does preserve the weakness.
Apparently Eric's i386 SVR4 system does not.  However, unless there is
some reason to preserve the i386 behaviour, I think the Solaris
behaviour makes more sense.

Eric, if you know of any reason to preserve the i386 behaviour, let me
know.

This patch to bfd/elfcode.h will change it to preserve weakness even
for symbols which are referenced by another object.

Ian

Index: elfcode.h
===================================================================
RCS file: /rel/cvsfiles/devo/bfd/elfcode.h,v
retrieving revision 1.126
diff -p -r1.126 elfcode.h
*** elfcode.h	1994/09/12 22:16:27	1.126
--- elfcode.h	1994/09/14 15:02:15
*************** elf_link_output_extsym (h, data)
*** 5855,5864 ****
    sym.st_size = h->size;
    sym.st_other = 0;
    if (h->root.type == bfd_link_hash_weak
!       || ((h->elf_link_hash_flags & ELF_LINK_HASH_DEFINED_WEAK) != 0
! 	  && ((h->elf_link_hash_flags & (ELF_LINK_HASH_REF_REGULAR
! 					 | ELF_LINK_HASH_REF_DYNAMIC))
! 	      == 0)))
      sym.st_info = ELF_ST_INFO (STB_WEAK, h->type);
    else
      sym.st_info = ELF_ST_INFO (STB_GLOBAL, h->type);
--- 5855,5861 ----
    sym.st_size = h->size;
    sym.st_other = 0;
    if (h->root.type == bfd_link_hash_weak
!       || (h->elf_link_hash_flags & ELF_LINK_HASH_DEFINED_WEAK) != 0)
      sym.st_info = ELF_ST_INFO (STB_WEAK, h->type);
    else
      sym.st_info = ELF_ST_INFO (STB_GLOBAL, h->type);


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

* Re: properties of weak symbols
  1994-09-14  8:22 ` Ian Lance Taylor
@ 1994-09-14 11:23   ` Roland McGrath
  1994-09-14 12:03   ` Eric Youngdale
  1 sibling, 0 replies; 5+ messages in thread
From: Roland McGrath @ 1994-09-14 11:23 UTC (permalink / raw)
  To: ian; +Cc: jrs, gas2, ericy

It is important for glibc that weakness be preserved.


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

* properties of weak symbols
  1994-09-14  8:22 ` Ian Lance Taylor
  1994-09-14 11:23   ` Roland McGrath
@ 1994-09-14 12:03   ` Eric Youngdale
  1 sibling, 0 replies; 5+ messages in thread
From: Eric Youngdale @ 1994-09-14 12:03 UTC (permalink / raw)
  To: ian; +Cc: jrs, gas2

>By the above argument, there should never be a reference to environ,
>rather than __environ, in another object in the link --shared.  At
>least, not for libc.  If there is such a reference, you are doing
>something wrong.

	No, the problem is different.  It is general problem with aliasing
which will come up with the following example:

.data
.globl foo
foo:
	.long 3
.type foo,@object
bar=foo

Here we have two different variables at the same address.  If this were in a
shared library and we link against it, and the application references both foo
and bar, then the linker will create space in .bss (actually .dynbss, which is
merged into .bss) for both foo and bar, and it will generate R_386_COPY
relocations to initialize these from the values in the shared library.
In effect, this is what Rick has reported, it is just that the previously .weak
variable was converted to .globl when the shared library was created.

	I have not decided what the correct behavior would be in the above case
- one could argue that the current behavior  is correct (except for the
symbol being changed from .globl to .weak).

>Eric, if you know of any reason to preserve the i386 behaviour, let me
>know.

	I cannot think of a good reason.  For all I know, it is a bug in the
SVr4 linker that we have.

>This patch to bfd/elfcode.h will change it to preserve weakness even
>for symbols which are referenced by another object.

	I was about to suggest the same thing.

-Eric


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

end of thread, other threads:[~1994-09-14 12:03 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1994-09-13 23:16 properties of weak symbols Rick Sladkey
1994-09-14  5:27 ` Eric Youngdale
1994-09-14  8:22 ` Ian Lance Taylor
1994-09-14 11:23   ` Roland McGrath
1994-09-14 12:03   ` Eric Youngdale

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).