public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* Re: GNU-ld behaviour does not match native linker behaviour
@ 1999-12-08 12:41 Nick Clifton
  1999-12-08 18:46 ` Ian Lance Taylor
  0 siblings, 1 reply; 16+ messages in thread
From: Nick Clifton @ 1999-12-08 12:41 UTC (permalink / raw)
  To: ian; +Cc: binutils

Hi Ian

  (Sorry about the delay in reply - I have just moved back to the
States and it has taken me a few days to settle in).


: It seems as though to make your test case work we would have to make
: two changes: 1) if a common symbol matches a symbol in the archive
: symbol map, include the element in the link; 2) do not put common
: symbols in the archive symbol map (see compute_and_write_armap in
: archive.c).
: 
: Change 2 seems correct at first glance.  If a library includes
: multiple objects which include a common symbol, we should not put that
: common symbol into the archive symbol map multiple times.  That
: doesn't make sense.
: 
: Given change 2, then change 1 makes some sense.  We will only see a
: symbol in the archive map if it is a definition.  If we have a common
: symbol, we want to bring in a definition.
: 
: I don't have the ELF spec handy.  I don't suppose it says anything
: about this issue?  I also think we must test other ELF systems before
: we should make either change.
: 
: Note that change 2 must not be made for the a.out object file format.
: a.out defines a different, and rather odd, procedure for linking
: against common symbols in archives.  See aout_link_check_ar_symbols in
: aoutx.h.

I think that this is the real problem.  There is no way that we can
know what the target file format is when we are creating the archive,
so we cannot decide whether we should include commons in the symbol
map or not.  (As an aside is there any reason why an archive cannot
contain object file sof multiple file formats ?)

It may be that my original (horrible) patch to the ELF linker is the
only way to solve this one....

Cheers
	Nick

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

* Re: GNU-ld behaviour does not match native linker behaviour
  1999-12-08 12:41 GNU-ld behaviour does not match native linker behaviour Nick Clifton
@ 1999-12-08 18:46 ` Ian Lance Taylor
  0 siblings, 0 replies; 16+ messages in thread
From: Ian Lance Taylor @ 1999-12-08 18:46 UTC (permalink / raw)
  To: nickc; +Cc: binutils

   Date: Wed, 8 Dec 1999 12:41:26 -0800
   From: Nick Clifton <nickc@cygnus.com>

   : Note that change 2 must not be made for the a.out object file format.
   : a.out defines a different, and rather odd, procedure for linking
   : against common symbols in archives.  See aout_link_check_ar_symbols in
   : aoutx.h.

   I think that this is the real problem.  There is no way that we can
   know what the target file format is when we are creating the archive,
   so we cannot decide whether we should include commons in the symbol
   map or not.

Sure, we can.  Archives have a format just like object files do.  Look
at coff-rs6000.c support to see how BFD can support a completely
different archive format.

   (As an aside is there any reason why an archive cannot
   contain object file sof multiple file formats ?)

No, there isn't.  But it's reasonable to not provide a symbol map for
such an archive.

Actually, that suggests a different approach.  Instead of replacing
compute_and_write_armap, just have that function call a new BFD target
function to decide whether to include a symbol in the archive map.  In
that case we would make the decision based on the archive member.

Ian

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

* Re: GNU-ld behaviour does not match native linker behaviour
  1999-12-10 11:55 Nick Clifton
@ 1999-12-10 12:05 ` Ian Lance Taylor
  0 siblings, 0 replies; 16+ messages in thread
From: Ian Lance Taylor @ 1999-12-10 12:05 UTC (permalink / raw)
  To: nickc; +Cc: binutils

   Date: Fri, 10 Dec 1999 11:55:34 -0800
   From: Nick Clifton <nickc@cygnus.com>

     OK here is a revised version of my original patch to fix this
     problem.  This patch is much more conservative.  It just fixes the
     ELF linker so that if it encounters a symbol in an archive map which
     matches a symbol which is currently known to be common, the linker
     will then examine the archive element's symbol table in order to
     determine oif the element contains an actual definition of the
     symbol or just another common declaration of it.

     OK to apply ?

   Cheers
	   Nick

   1999-12-10  Nick Clifton  <nickc@cygnus.com>

	   * elflink.h (elf_link_is_defined_archive_symbol): New
	   function: Decide if a symbol, in an archive map is there
	   because it is defined in the archive element, or because it is
	   just another common declaration of it.
	   (elf_link_add_archive_symbols): Use
	   elf_link_is_defined_archive_symbol to decide if an archive
	   element contain a reference to a common symbol should be
	   linked in or not.

The approach seems reasonably safe, after all of our discussion.

Ian

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

* Re: GNU-ld behaviour does not match native linker behaviour
@ 1999-12-10 11:55 Nick Clifton
  1999-12-10 12:05 ` Ian Lance Taylor
  0 siblings, 1 reply; 16+ messages in thread
From: Nick Clifton @ 1999-12-10 11:55 UTC (permalink / raw)
  To: ian; +Cc: schwab, binutils, evelyn_mast

Hi Guys,

  OK here is a revised version of my original patch to fix this
  problem.  This patch is much more conservative.  It just fixes the
  ELF linker so that if it encounters a symbol in an archive map which
  matches a symbol which is currently known to be common, the linker
  will then examine the archive element's symbol table in order to
  determine oif the element contains an actual definition of the
  symbol or just another common declaration of it.

  OK to apply ?

Cheers
	Nick

1999-12-10  Nick Clifton  <nickc@cygnus.com>

	* elflink.h (elf_link_is_defined_archive_symbol): New
	function: Decide if a symbol, in an archive map is there
	because it is defined in the archive element, or because it is
	just another common declaration of it.
	(elf_link_add_archive_symbols): Use
	elf_link_is_defined_archive_symbol to decide if an archive
	element contain a reference to a common symbol should be
	linked in or not.

Index: elflink.h
===================================================================
RCS file: /cvs/binutils/binutils/bfd/elflink.h,v
retrieving revision 1.38
diff -p -r1.38 elflink.h
*** elflink.h	1999/12/10 18:51:34	1.38
--- elflink.h	1999/12/10 19:47:57
*************** elf_bfd_link_add_symbols (abfd, info)
*** 80,86 ****
--- 80,177 ----
      }
  }
  \f
+ /* Search the symbol table of the archive element of the archive ABFD
+    whoes archove map contains a mention of SYMDEF, and determine if
+    the symbol is defined in this element.  */
+ static boolean
+ elf_link_is_defined_archive_symbol (abfd, symdef)
+      bfd * abfd;
+      carsym * symdef;
+ {
+   Elf_Internal_Shdr * hdr;
+   Elf_External_Sym *  esym;
+   Elf_External_Sym *  esymend;
+   Elf_External_Sym *  buf = NULL;
+   size_t symcount;
+   size_t extsymcount;
+   size_t extsymoff;
+   boolean result = false;
+   
+   abfd = _bfd_get_elt_at_filepos (abfd, symdef->file_offset);
+   if (abfd == (bfd *) NULL)
+     return false;
+ 
+   if (! bfd_check_format (abfd, bfd_object))
+     return false;
+ 
+   /* Select the appropriate symbol table.  */
+   if ((abfd->flags & DYNAMIC) == 0 || elf_dynsymtab (abfd) == 0)
+     hdr = &elf_tdata (abfd)->symtab_hdr;
+   else
+     hdr = &elf_tdata (abfd)->dynsymtab_hdr;
+ 
+   symcount = hdr->sh_size / sizeof (Elf_External_Sym);
+ 
+   /* The sh_info field of the symtab header tells us where the
+      external symbols start.  We don't care about the local symbols.  */
+   if (elf_bad_symtab (abfd))
+     {
+       extsymcount = symcount;
+       extsymoff = 0;
+     }
+   else
+     {
+       extsymcount = symcount - hdr->sh_info;
+       extsymoff = hdr->sh_info;
+     }
  
+   buf = ((Elf_External_Sym *)
+ 	 bfd_malloc (extsymcount * sizeof (Elf_External_Sym)));
+   if (buf == NULL && extsymcount != 0)
+     return false;
+ 
+   /* Read in the symbol table.
+      FIXME:  This ought to be cached somewhere.  */
+   if (bfd_seek (abfd,
+ 		hdr->sh_offset + extsymoff * sizeof (Elf_External_Sym),
+ 		SEEK_SET) != 0
+       || (bfd_read ((PTR) buf, sizeof (Elf_External_Sym), extsymcount, abfd)
+ 	  != extsymcount * sizeof (Elf_External_Sym)))
+     {
+       free (buf);
+       return false;
+     }
+ 
+   /* Scan the symbol table looking for SYMDEF.  */
+   esymend = buf + extsymcount;
+   for (esym = buf;
+        esym < esymend;
+        esym++)
+     {
+       Elf_Internal_Sym sym;
+       const char * name;
+ 
+       elf_swap_symbol_in (abfd, esym, & sym);
+ 
+       name = bfd_elf_string_from_elf_section (abfd, hdr->sh_link, sym.st_name);
+       if (name == (const char *) NULL)
+ 	break;
+ 
+       if (strcmp (name, symdef->name) == 0)
+ 	{
+ 	  result =
+ 	    (ELF_ST_BIND (sym.st_info) == STB_GLOBAL)
+ 	    && (sym.st_shndx != SHN_UNDEF);
+ 	  break;
+ 	}
+     }
+ 
+   free (buf);
+   
+   return result;
+ }
+ \f
+ 
  /* Add symbols from an ELF archive file to the linker hash table.  We
     don't use _bfd_generic_link_add_archive_symbols because of a
     problem which arises on UnixWare.  The UnixWare libc.so is an
*************** elf_link_add_archive_symbols (abfd, info
*** 200,206 ****
  	  if (h == NULL)
  	    continue;
  
! 	  if (h->root.type != bfd_link_hash_undefined)
  	    {
  	      if (h->root.type != bfd_link_hash_undefweak)
  		defined[i] = true;
--- 291,314 ----
  	  if (h == NULL)
  	    continue;
  
! 	  if (h->root.type == bfd_link_hash_common)
! 	    {
! 	      /* We currently have a common symbol.  The archive map contains
! 		 a reference to this symbol, so we may want to include it.  We
! 		 only want to include it however, if this archive element
! 		 contains a definition of the symbol, not just another common
! 		 declaration of it.
! 
! 		 Unfortunately some archivers (including GNU ar) will put
! 		 declarations of common symbols into their archive maps, as
! 		 well as real definitions, so we cannot just go by the archive
! 		 map alone.  Instead we must read in the element's symbol
! 		 table and check that to see what kind of symbol definition
! 		 this is.  */
! 	      if (! elf_link_is_defined_archive_symbol (abfd, symdef))
! 		continue;
! 	    }
! 	  else if (h->root.type != bfd_link_hash_undefined)
  	    {
  	      if (h->root.type != bfd_link_hash_undefweak)
  		defined[i] = true;

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

* Re: GNU-ld behaviour does not match native linker behaviour
@ 1999-12-10 10:53 Nick Clifton
  0 siblings, 0 replies; 16+ messages in thread
From: Nick Clifton @ 1999-12-10 10:53 UTC (permalink / raw)
  To: ian; +Cc: schwab, binutils, evelyn_mast

Hi Ian,

: So, Nick, it now looks to me like your original patch is the right way
: to go.
: 
: The old patch is not very efficient, but I suppose the inefficiency
: only arises when you use a common symbol in a main program and that
: symbol name appears in an archive map.  We must check whether the
: symbol in the archive element is common or defined, and that is what
: your patch did.

Ho Hum!  One of those days.  OK I have now reverted the patch that I
applied last night, and I am going to find, apply and test my old
patch before I resubmit it to this list.

Cheers
	Nick

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

* Re: GNU-ld behaviour does not match native linker behaviour
  1999-12-10  4:14 ` Andreas Schwab
@ 1999-12-10  8:13   ` Ian Lance Taylor
  0 siblings, 0 replies; 16+ messages in thread
From: Ian Lance Taylor @ 1999-12-10  8:13 UTC (permalink / raw)
  To: schwab, nickc; +Cc: binutils, evelyn_mast

   From: Andreas Schwab <schwab@suse.de>
   Date: 10 Dec 1999 13:14:14 +0100

   |> : Note that we may have some confusion with existing ELF archives in
   |> : some scenarios.  Existing ELF archives will have common symbols in the
   |> : armap.  We will now wind up pulling those in to satisfy common symbols
   |> : in the executable.  I'm not sure what to do about that.  I don't know
   |> : how often it will be a real problem.
   |> 
   |> I think we should be OK.  In the case where old archives are linked
   |> with the new linker, we may end up getting bigger than expected
   |> executables, but on the other hand we should also end up getting
   |> executables that work (becuase they have included the definition of
   |> the common as well), instead of ones that are broken.

   Unfortunately this will not always work.  Suppose you have a libarary
   (call it libgcc.a) that is created with the old ar program (and thus its
   armap contains the common symbols).  Suppose further that this library
   appears twice on the linker command line (which is always true for
   libgcc.a).  The linker will now try to link the object file that contains
   the common symbol twice whenever any symbol is referenced from it, which
   will fail due to multiple definitions of the other symbols.

Good point.

I'm also now concerned about the case in which there an undefined
symbol in an object, and a common symbol in an archive.  In the old
scenario, the archive element would satisfy the undefined reference.
In the new scenario, it would not.

I just checked /usr/ccs/bin/ar on Solaris 2.6, and it *does* put
common symbols in the armap.  Also, the ELF spec in its description of
archive symbol tables refers only to the distinction between global
and local symbols, and makes no reference to common symbols (which are
a form of global symbol in ELF).  This makes me doubt very much
whether the patch you have checked in is correct.  Sorry about that,
Nick.

When I try your original test case, with a common symbol in the main
program and a defined symbol in the archive, the Solaris 2.6 linker
does pull in the element from the archive.

When I try a test case in which an element in the archive provides a
common symbol which is also a common symbol in the main program, the
Solaris 2.6 linker does not pull in the element from the archive.

When I try a test case in which an element in the archive provides a
common symbol which is an undefined symbol in the main program, the
Solaris 2.6 linker does pull in the element from the archive.

Here is a table showing when an element is pulled in from an archive
with the Solaris 2.6 linker and ar program:

main program\archive   undefined    common    defined

undefined                no          yes       yes
common                   no          no        yes
defined                  no          no        no

In the original binutils code, the common\defined line was no.  In the
newly patched binutils code, the undefined\common line is no.

So, Nick, it now looks to me like your original patch is the right way
to go.

The old patch is not very efficient, but I suppose the inefficiency
only arises when you use a common symbol in a main program and that
symbol name appears in an archive map.  We must check whether the
symbol in the archive element is common or defined, and that is what
your patch did.

Sorry to put you through all this.  Previously I was replying without
testing other systems, because at the time I could not.

Ian

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

* Re: GNU-ld behaviour does not match native linker behaviour
  1999-12-09 16:14 Nick Clifton
@ 1999-12-10  4:14 ` Andreas Schwab
  1999-12-10  8:13   ` Ian Lance Taylor
  0 siblings, 1 reply; 16+ messages in thread
From: Andreas Schwab @ 1999-12-10  4:14 UTC (permalink / raw)
  To: Nick Clifton; +Cc: ian, binutils, evelyn_mast

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 1451 bytes --]

Nick Clifton <nickc@cygnus.com> writes:

|> Hi Ian,
|> 
|> : Note that we may have some confusion with existing ELF archives in
|> : some scenarios.  Existing ELF archives will have common symbols in the
|> : armap.  We will now wind up pulling those in to satisfy common symbols
|> : in the executable.  I'm not sure what to do about that.  I don't know
|> : how often it will be a real problem.
|> 
|> I think we should be OK.  In the case where old archives are linked
|> with the new linker, we may end up getting bigger than expected
|> executables, but on the other hand we should also end up getting
|> executables that work (becuase they have included the definition of
|> the common as well), instead of ones that are broken.

Unfortunately this will not always work.  Suppose you have a libarary
(call it libgcc.a) that is created with the old ar program (and thus its
armap contains the common symbols).  Suppose further that this library
appears twice on the linker command line (which is always true for
libgcc.a).  The linker will now try to link the object file that contains
the common symbol twice whenever any symbol is referenced from it, which
will fail due to multiple definitions of the other symbols.

Andreas.

-- 
Andreas Schwab                                  "And now for something
SuSE Labs                                        completely different."
schwab@suse.de
SuSE GmbH, Schanzäckerstr. 10, D-90443 Nürnberg

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

* Re: GNU-ld behaviour does not match native linker behaviour
@ 1999-12-09 16:14 Nick Clifton
  1999-12-10  4:14 ` Andreas Schwab
  0 siblings, 1 reply; 16+ messages in thread
From: Nick Clifton @ 1999-12-09 16:14 UTC (permalink / raw)
  To: ian; +Cc: binutils, evelyn_mast

Hi Ian,

: Note that we may have some confusion with existing ELF archives in
: some scenarios.  Existing ELF archives will have common symbols in the
: armap.  We will now wind up pulling those in to satisfy common symbols
: in the executable.  I'm not sure what to do about that.  I don't know
: how often it will be a real problem.

I think we should be OK.  In the case where old archives are linked
with the new linker, we may end up getting bigger than expected
executables, but on the other hand we should also end up getting
executables that work (becuase they have included the definition of
the common as well), instead of ones that are broken.

:    + #define _bfd_achive_bsd_allow_commons_in_armap bfd_true
: 
: Typo.

Oops - thanks for the catch.

I will check the patch in.

Cheers
	Nick

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

* Re: GNU-ld behaviour does not match native linker behaviour
  1999-12-09 12:49 Nick Clifton
@ 1999-12-09 15:20 ` Ian Lance Taylor
  0 siblings, 0 replies; 16+ messages in thread
From: Ian Lance Taylor @ 1999-12-09 15:20 UTC (permalink / raw)
  To: nickc; +Cc: binutils, evelyn_mast

   Date: Thu, 9 Dec 1999 12:49:23 -0800
   From: Nick Clifton <nickc@cygnus.com>

   : Actually, that suggests a different approach.  Instead of replacing
   : compute_and_write_armap, just have that function call a new BFD target
   : function to decide whether to include a symbol in the archive map.  In
   : that case we would make the decision based on the archive member.

   Yes - I like this idea.  Ok - so what do you think of this patch ?

   This patch:

     * Changes the default ELF linker so that an archive element will be
       linked in if it has a symbol in the archive map which is currently
       considered to be a common symbol.

     * Adds a new field to the bfd_target structure called
       _bfd_allow_commons_in_armap.

     * Fixes all of the current BFD targets to initialise this new field
       to false, except the default ELF target which initialises it to
       true.

Looks basically good to me.

Note that we may have some confusion with existing ELF archives in
some scenarios.  Existing ELF archives will have common symbols in the
armap.  We will now wind up pulling those in to satisfy common symbols
in the executable.  I'm not sure what to do about that.  I don't know
how often it will be a real problem.

   + #define _bfd_achive_bsd_allow_commons_in_armap bfd_true

Typo.

Ian

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

* Re: GNU-ld behaviour does not match native linker behaviour
@ 1999-12-09 12:49 Nick Clifton
  1999-12-09 15:20 ` Ian Lance Taylor
  0 siblings, 1 reply; 16+ messages in thread
From: Nick Clifton @ 1999-12-09 12:49 UTC (permalink / raw)
  To: ian; +Cc: binutils, evelyn_mast

Hi Ian,

: Actually, that suggests a different approach.  Instead of replacing
: compute_and_write_armap, just have that function call a new BFD target
: function to decide whether to include a symbol in the archive map.  In
: that case we would make the decision based on the archive member.

Yes - I like this idea.  Ok - so what do you think of this patch ?

This patch:

  * Changes the default ELF linker so that an archive element will be
    linked in if it has a symbol in the archive map which is currently
    considered to be a common symbol.

  * Adds a new field to the bfd_target structure called
    _bfd_allow_commons_in_armap.

  * Fixes all of the current BFD targets to initialise this new field
    to false, except the default ELF target which initialises it to
    true.

Cheers
	Nick

1999-12-09  Nick Clifton  <nickc@cygnus.com>

	* elflink.h (elf_link_add_archive_symbols): Add an archive
        element even if contains a symbol which is currently only
        considered to be a common.

	* targets.c (struct bfd_target): Add new field
	_bfd_allow_commons_in_armap.
	* bfd-in2.h:Regenerate.

	* libbfd-in2.h (_bfd_noarchive_allow_commons_in_armap):
	Define.
	 (_bfd_archive_bsd_allow_commons_in_armap): Define.
	* libbfd.h: Regenerate.

	* elfxx-target.h: If using COFF archive map, override
	definition of allow_commons_in_armap and replace with
	bfd_false.

	* archive.c (bfd_compute_and_write_armap): Do not place common
	symbols into the archive map unless _bfd_allow_commons_in_armap
	returns true.

	* aout-target.h (MY_allow_commons_in_armap): Define.
	* aout-tic30.h (MY_allow_commons_in_armap): Define.
	* bfd.c (bfd_allow_commons_in_armap): Define.
	* coff-alpha.h (alpha_ecoff_allow_commons_in_armap): Define.
	* coff-rs6000.h (xcoff_allow_commons_in_armap): Define.
	* elf64-mips.c (bfd_elf64_allow_commons_in_armap): Define.
	* ieee.c (ieee_ecoff_allow_commons_in_armap): Define.
	* libecoff.h (_bfd_ecoff_allow_commons_in_armap): Define.
	* oasys.c (oasys_allow_commons_in_armap): Define.
	* som.c (som_allow_commons_in_armap): Define.
	* vms.c (vms_allow_commons_in_armap): Define.


Index: elflink.h
===================================================================
RCS file: /cvs/cvsfiles/devo/bfd/elflink.h,v
retrieving revision 1.137
diff -p -r1.137 elflink.h
*** elflink.h	1999/09/06 01:58:44	1.137
--- elflink.h	1999/12/09 20:30:35
*************** elf_link_add_archive_symbols (abfd, info
*** 200,206 ****
  	  if (h == NULL)
  	    continue;
  
! 	  if (h->root.type != bfd_link_hash_undefined)
  	    {
  	      if (h->root.type != bfd_link_hash_undefweak)
  		defined[i] = true;
--- 200,225 ----
  	  if (h == NULL)
  	    continue;
  
! 	  /* We have changed the GNU archiver so that it will only place
! 	     non-common symbols into its archive map.  Thus if we come across
! 	     a symbol in the archive map, which is currently considered to be
! 	     a common symbol, we can safely assume that we should link the
! 	     element in, in order to get in the definition of the symbol.
! 	     
! 	     Previous versions of the archiver would place common symbols into
! 	     the archive map.  This meant that in order to only link in an
! 	     element if it contained a *definition* of a common symbol, it
! 	     would be necessary to read in the element and scan its symbol
! 	     table - a slow and wasteful process.
! 
! 	     In fact previous versions of this code did not even do that,
! 	     instead it just unilaterally ignored any symbols in the archive
! 	     map which were currently marked as common.  So in order to link
! 	     in an archive element containing the definition of a common
! 	     symbol it was necessary to have that element also contain the
! 	     defintion of a currently undefined symbol.  */
! 	  if (h->root.type != bfd_link_hash_undefined
! 	      && h->root.type != bfd_link_hash_common)
  	    {
  	      if (h->root.type != bfd_link_hash_undefweak)
  		defined[i] = true;

Index: bfd-in2.h
===================================================================
RCS file: /cvs/cvsfiles/devo/bfd/bfd-in2.h,v
retrieving revision 1.354
diff -p -r1.354 bfd-in2.h
*** bfd-in2.h	1999/12/01 10:28:34	1.354
--- bfd-in2.h	1999/12/09 20:30:36
*************** bfd_set_private_flags PARAMS ((bfd *abfd
*** 2884,2889 ****
--- 2884,2892 ----
  #define bfd_update_armap_timestamp(abfd) \
          BFD_SEND (abfd, _bfd_update_armap_timestamp, (abfd))
  
+ #define bfd_allow_commons_in_armap(abfd) \
+         BFD_SEND (abfd, _bfd_allow_commons_in_armap, (abfd))
+ 
  #define bfd_set_arch_mach(abfd, arch, mach)\
          BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach))
  
*************** CAT(NAME,_read_ar_hdr),\
*** 3091,3097 ****
  CAT(NAME,_openr_next_archived_file),\
  CAT(NAME,_get_elt_at_index),\
  CAT(NAME,_generic_stat_arch_elt),\
! CAT(NAME,_update_armap_timestamp)
    boolean  (*_bfd_slurp_armap) PARAMS ((bfd *));
    boolean  (*_bfd_slurp_extended_name_table) PARAMS ((bfd *));
    boolean  (*_bfd_construct_extended_name_table)
--- 3094,3101 ----
  CAT(NAME,_openr_next_archived_file),\
  CAT(NAME,_get_elt_at_index),\
  CAT(NAME,_generic_stat_arch_elt),\
! CAT(NAME,_update_armap_timestamp), \
! CAT(NAME,_allow_commons_in_armap)
    boolean  (*_bfd_slurp_armap) PARAMS ((bfd *));
    boolean  (*_bfd_slurp_extended_name_table) PARAMS ((bfd *));
    boolean  (*_bfd_construct_extended_name_table)
*************** CAT(NAME,_update_armap_timestamp)
*** 3102,3114 ****
                                struct orl *map,
                                unsigned int orl_count, 
                                int stridx));
!   PTR (*_bfd_read_ar_hdr_fn) PARAMS ((bfd *));
    bfd *    (*openr_next_archived_file) PARAMS ((bfd *arch, bfd *prev));
  #define bfd_get_elt_at_index(b,i) BFD_SEND(b, _bfd_get_elt_at_index, (b,i))
    bfd *    (*_bfd_get_elt_at_index) PARAMS ((bfd *, symindex));
    int      (*_bfd_stat_arch_elt) PARAMS ((bfd *, struct stat *));
    boolean  (*_bfd_update_armap_timestamp) PARAMS ((bfd *));
! 
     /* Entry points used for symbols.  */
  #define BFD_JUMP_TABLE_SYMBOLS(NAME)\
  CAT(NAME,_get_symtab_upper_bound),\
--- 3106,3119 ----
                                struct orl *map,
                                unsigned int orl_count, 
                                int stridx));
!   PTR      (*_bfd_read_ar_hdr_fn) PARAMS ((bfd *));
    bfd *    (*openr_next_archived_file) PARAMS ((bfd *arch, bfd *prev));
  #define bfd_get_elt_at_index(b,i) BFD_SEND(b, _bfd_get_elt_at_index, (b,i))
    bfd *    (*_bfd_get_elt_at_index) PARAMS ((bfd *, symindex));
    int      (*_bfd_stat_arch_elt) PARAMS ((bfd *, struct stat *));
    boolean  (*_bfd_update_armap_timestamp) PARAMS ((bfd *));
!   boolean  (*_bfd_allow_commons_in_armap) PARAMS ((bfd *));
! 	     
     /* Entry points used for symbols.  */
  #define BFD_JUMP_TABLE_SYMBOLS(NAME)\
  CAT(NAME,_get_symtab_upper_bound),\

Index: libbfd-in.h
===================================================================
RCS file: /cvs/cvsfiles/devo/bfd/libbfd-in.h,v
retrieving revision 1.99
diff -p -r1.99 libbfd-in.h
*** libbfd-in.h	1999/07/23 22:12:05	1.99
--- libbfd-in.h	1999/12/09 20:30:36
*************** extern boolean _bfd_nocore_core_file_mat
*** 211,216 ****
--- 211,217 ----
    ((bfd *(*) PARAMS ((bfd *, symindex))) bfd_nullvoidptr)
  #define _bfd_noarchive_generic_stat_arch_elt bfd_generic_stat_arch_elt
  #define _bfd_noarchive_update_armap_timestamp bfd_false
+ #define _bfd_noarchive_allow_commons_in_armap bfd_true
  
  /* Routines to use for BFD_JUMP_TABLE_ARCHIVE to get BSD style
     archives.  Use BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_bsd).  */
*************** extern boolean _bfd_archive_bsd_construc
*** 229,234 ****
--- 230,236 ----
  #define _bfd_archive_bsd_generic_stat_arch_elt \
    bfd_generic_stat_arch_elt
  extern boolean _bfd_archive_bsd_update_armap_timestamp PARAMS ((bfd *));
+ #define _bfd_achive_bsd_allow_commons_in_armap bfd_true
  
  /* Routines to use for BFD_JUMP_TABLE_ARCHIVE to get COFF style
     archives.  Use BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff).  */
*************** extern boolean _bfd_archive_coff_constru
*** 247,252 ****
--- 249,255 ----
  #define _bfd_archive_coff_generic_stat_arch_elt \
    bfd_generic_stat_arch_elt
  #define _bfd_archive_coff_update_armap_timestamp bfd_true
+ #define _bfd_archive_coff_allow_commons_in_armap bfd_true
  
  /* Routines to use for BFD_JUMP_TABLE_SYMBOLS where there is no symbol
     support.  Use BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols).  */

Index: libbfd.h
===================================================================
RCS file: /cvs/cvsfiles/devo/bfd/libbfd.h,v
retrieving revision 1.232
diff -p -r1.232 libbfd.h
*** libbfd.h	1999/11/28 03:41:05	1.232
--- libbfd.h	1999/12/09 20:30:36
*************** extern boolean _bfd_nocore_core_file_mat
*** 211,216 ****
--- 211,217 ----
    ((bfd *(*) PARAMS ((bfd *, symindex))) bfd_nullvoidptr)
  #define _bfd_noarchive_generic_stat_arch_elt bfd_generic_stat_arch_elt
  #define _bfd_noarchive_update_armap_timestamp bfd_false
+ #define _bfd_noarchive_allow_commons_in_armap bfd_true
  
  /* Routines to use for BFD_JUMP_TABLE_ARCHIVE to get BSD style
     archives.  Use BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_bsd).  */
*************** extern boolean _bfd_archive_bsd_construc
*** 229,234 ****
--- 230,236 ----
  #define _bfd_archive_bsd_generic_stat_arch_elt \
    bfd_generic_stat_arch_elt
  extern boolean _bfd_archive_bsd_update_armap_timestamp PARAMS ((bfd *));
+ #define _bfd_archive_bsd_allow_commons_in_armap bfd_true
  
  /* Routines to use for BFD_JUMP_TABLE_ARCHIVE to get COFF style
     archives.  Use BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff).  */
*************** extern boolean _bfd_archive_coff_constru
*** 247,252 ****
--- 249,255 ----
  #define _bfd_archive_coff_generic_stat_arch_elt \
    bfd_generic_stat_arch_elt
  #define _bfd_archive_coff_update_armap_timestamp bfd_true
+ #define _bfd_archive_coff_allow_commons_in_armap bfd_true
  
  /* Routines to use for BFD_JUMP_TABLE_SYMBOLS where there is no symbol
     support.  Use BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols).  */

Index: elfxx-target.h
===================================================================
RCS file: /cvs/cvsfiles/devo/bfd/elfxx-target.h,v
retrieving revision 1.44
diff -p -r1.44 elfxx-target.h
*** elfxx-target.h	1999/11/26 01:57:46	1.44
--- elfxx-target.h	1999/12/09 20:30:37
*************** const bfd_target TARGET_BIG_SYM =
*** 477,482 ****
--- 477,489 ----
  #ifdef bfd_elfNN_archive_functions
        BFD_JUMP_TABLE_ARCHIVE (bfd_elfNN_archive),
  #else
+   /* For ELF based targets we do not want to put common symbols into the
+      archive map.  This is a change from the old behaviour, and it is
+      being done because of a corresponding change in the linker, whereby
+      it will link in any archive element that contains a symbol which is
+      currently common.  (See elflink.h:elf_link_add_archive_symbol).  */
+ #undef  _bfd_archive_coff_allow_commons_in_armap
+ #define _bfd_archive_coff_allow_commons_in_armap bfd_false
        BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
  #endif
        BFD_JUMP_TABLE_SYMBOLS (bfd_elfNN),
*************** const bfd_target TARGET_LITTLE_SYM =
*** 572,577 ****
--- 579,586 ----
  #ifdef bfd_elfNN_archive_functions
        BFD_JUMP_TABLE_ARCHIVE (bfd_elfNN_archive),
  #else
+ #undef  _bfd_archive_coff_allow_commons_in_armap
+ #define _bfd_archive_coff_allow_commons_in_armap bfd_false
        BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
  #endif
        BFD_JUMP_TABLE_SYMBOLS (bfd_elfNN),

Index: archive.c
===================================================================
RCS file: /cvs/cvsfiles/devo/bfd/archive.c,v
retrieving revision 1.145
diff -p -r1.145 archive.c
*** archive.c	1999/09/16 20:26:44	1.145
--- archive.c	1999/12/09 20:30:37
*************** _bfd_compute_and_write_armap (arch, elen
*** 1855,1870 ****
  		{
  		  flagword flags = (syms[src_count])->flags;
  		  asection *sec = syms[src_count]->section;
  
! 		  if ((flags & BSF_GLOBAL ||
! 		       flags & BSF_WEAK ||
! 		       flags & BSF_INDIRECT ||
! 		       bfd_is_com_section (sec))
! 		      && ! bfd_is_und_section (sec))
  		    {
! 		      size_t namelen;
! 		      struct orl *new_map;
! 
  		      /* This symbol will go into the archive header */
  		      if (orl_count == orl_max)
  			{
--- 1855,1873 ----
  		{
  		  flagword flags = (syms[src_count])->flags;
  		  asection *sec = syms[src_count]->section;
+ 		  size_t namelen;
+ 		  struct orl *new_map;
  
! 		  if (bfd_is_und_section (sec))
! 		    continue;
! 		  else if (bfd_is_com_section (sec))
  		    {
! 		      if (! bfd_allow_commons_in_armap (arch))
! 			continue;
! 		    }
! 		  else if ((flags & (BSF_GLOBAL | BSF_WEAK | BSF_INDIRECT)) == 0)
! 		    continue;
! 		  
  		      /* This symbol will go into the archive header */
  		      if (orl_count == orl_max)
  			{
*************** _bfd_compute_and_write_armap (arch, elen
*** 1893,1899 ****
  
  		      stridx += namelen + 1;
  		      ++orl_count;
- 		    }
  		}
  	    }
  
--- 1896,1901 ----

Index: aout-target.h
===================================================================
RCS file: /cvs/cvsfiles/devo/bfd/aout-target.h,v
retrieving revision 1.78
diff -p -r1.78 aout-target.h
*** aout-target.h	1999/07/23 22:11:28	1.78
--- aout-target.h	1999/12/09 20:30:37
*************** MY_bfd_final_link (abfd, info)
*** 421,426 ****
--- 421,429 ----
  #ifndef MY_update_armap_timestamp
  #define MY_update_armap_timestamp _bfd_archive_bsd_update_armap_timestamp
  #endif
+ #ifndef MY_allow_commons_in_armap
+ #define MY_allow_commons_in_armap _bfd_archive_bsd_allow_commons_in_armap
+ #endif
  
  /* No core file defined here -- configure in trad-core.c separately.  */
  #ifndef	MY_core_file_failing_command

Index: aout-tic30.c
===================================================================
RCS file: /cvs/cvsfiles/devo/bfd/aout-tic30.c,v
retrieving revision 1.5
diff -p -r1.5 aout-tic30.c
*** aout-tic30.c	1999/07/23 22:11:28	1.5
--- aout-tic30.c	1999/12/09 20:30:37
*************** tic30_aout_set_arch_mach (abfd, arch, ma
*** 851,856 ****
--- 851,859 ----
  #ifndef MY_update_armap_timestamp
  #define MY_update_armap_timestamp _bfd_archive_bsd_update_armap_timestamp
  #endif
+ #ifndef MY_allow_commons_in_armap
+ #define MY_allow_commons_in_armap _bfd_archive_bsd_allow_commons_in_armap
+ #endif
  
  /* No core file defined here -- configure in trad-core.c separately.  */
  #ifndef	MY_core_file_failing_command

Index: bfd.c
===================================================================
RCS file: /cvs/cvsfiles/devo/bfd/bfd.c,v
retrieving revision 1.129
diff -p -r1.129 bfd.c
*** bfd.c	1999/07/23 22:11:33	1.129
--- bfd.c	1999/12/09 20:30:37
*************** DESCRIPTION
*** 1039,1044 ****
--- 1039,1047 ----
  .#define bfd_update_armap_timestamp(abfd) \
  .        BFD_SEND (abfd, _bfd_update_armap_timestamp, (abfd))
  .
+ .#define bfd_allow_commons_in_armap(abfd) \
+ .        BFD_SEND (abfd, _bfd_allow_commons_in_armap, (abfd))
+ .
  .#define bfd_set_arch_mach(abfd, arch, mach)\
  .        BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach))
  .

Index: coff-alpha.c
===================================================================
RCS file: /cvs/cvsfiles/devo/bfd/coff-alpha.c,v
retrieving revision 1.72
diff -p -r1.72 coff-alpha.c
*** coff-alpha.c	1999/07/19 07:53:38	1.72
--- coff-alpha.c	1999/12/09 20:30:38
*************** alpha_adjust_headers (abfd, fhdr, ahdr)
*** 2036,2041 ****
--- 2036,2043 ----
  #define alpha_ecoff_write_armap _bfd_ecoff_write_armap
  #define alpha_ecoff_generic_stat_arch_elt _bfd_ecoff_generic_stat_arch_elt
  #define alpha_ecoff_update_armap_timestamp _bfd_ecoff_update_armap_timestamp
+ #define alpha_ecoff_allow_commons_in_armap _bfd_true
+ 
  
  /* A compressed file uses this instead of ARFMAG.  */
  
Index: coff-rs6000.c
===================================================================
RCS file: /cvs/cvsfiles/devo/bfd/coff-rs6000.c,v
retrieving revision 1.63
diff -p -r1.63 coff-rs6000.c
*** coff-rs6000.c	1999/07/23 22:11:34	1.63
--- coff-rs6000.c	1999/12/09 20:30:38
*************** struct xcoff_ar_hdr
*** 694,699 ****
--- 694,700 ----
  /* XCOFF archives do not have a timestamp.  */
  
  #define xcoff_update_armap_timestamp bfd_true
+ #define xcoff_allow_commons_in_armap bfd_true
  
  /* Read in the armap of an XCOFF archive.  */
  
Index: elf64-mips.c
===================================================================
RCS file: /cvs/cvsfiles/devo/bfd/elf64-mips.c,v
retrieving revision 1.16
diff -p -r1.16 elf64-mips.c
*** elf64-mips.c	1999/07/23 22:12:03	1.16
--- elf64-mips.c	1999/12/09 20:30:39
*************** const struct elf_size_info mips_elf64_si
*** 2186,2190 ****
--- 2186,2191 ----
  					_bfd_archive_coff_generic_stat_arch_elt
  #define bfd_elf64_archive_update_armap_timestamp \
  				_bfd_archive_coff_update_armap_timestamp
+ #define _bfd_elf64_allow_commons_in_armap bfd_false
  
  #include "elf64-target.h"

Index: ieee.c
===================================================================
RCS file: /cvs/cvsfiles/devo/bfd/ieee.c,v
retrieving revision 1.129
diff -p -r1.129 ieee.c
*** ieee.c	1999/07/23 22:12:05	1.129
--- ieee.c	1999/12/09 20:30:39
*************** ieee_bfd_debug_info_accumulate (abfd, se
*** 3893,3898 ****
--- 3893,3899 ----
     bfd_true)
  #define ieee_read_ar_hdr bfd_nullvoidptr
  #define ieee_update_armap_timestamp bfd_true
+ #define ieee_allow_commons_in_armap bfd_true
  #define ieee_get_elt_at_index _bfd_generic_get_elt_at_index
  
  #define ieee_bfd_is_local_label_name bfd_generic_is_local_label_name

Index: libecoff.h
===================================================================
RCS file: /cvs/cvsfiles/devo/bfd/libecoff.h,v
retrieving revision 1.51
diff -p -r1.51 libecoff.h
*** libecoff.h	1997/04/30 16:12:22	1.51
--- libecoff.h	1999/12/09 20:30:39
*************** extern boolean _bfd_ecoff_write_armap
*** 295,300 ****
--- 295,301 ----
  #define _bfd_ecoff_get_elt_at_index _bfd_generic_get_elt_at_index
  #define _bfd_ecoff_generic_stat_arch_elt bfd_generic_stat_arch_elt
  #define _bfd_ecoff_update_armap_timestamp bfd_true
+ #define _bfd_ecoff_allow_commons_in_armap bfd_true
  
  extern long _bfd_ecoff_get_symtab_upper_bound PARAMS ((bfd *abfd));
  extern long _bfd_ecoff_get_symtab PARAMS ((bfd *abfd, asymbol **alocation));

Index: oasys.c
===================================================================
RCS file: /cvs/cvsfiles/devo/bfd/oasys.c,v
retrieving revision 1.99
diff -p -r1.99 oasys.c
*** oasys.c	1999/07/23 22:12:12	1.99
--- oasys.c	1999/12/09 20:30:39
*************** oasys_sizeof_headers (abfd, exec)
*** 1458,1463 ****
--- 1458,1464 ----
  #define oasys_read_ar_hdr bfd_nullvoidptr
  #define oasys_get_elt_at_index _bfd_generic_get_elt_at_index
  #define oasys_update_armap_timestamp bfd_true
+ #define oasys_allow_commons_in_armap bfd_true
  
  #define oasys_bfd_is_local_label_name bfd_generic_is_local_label_name
  #define oasys_get_lineno _bfd_nosymbols_get_lineno

Index: som.c
===================================================================
RCS file: /cvs/cvsfiles/devo/bfd/som.c,v
retrieving revision 1.180
diff -p -r1.180 som.c
*** som.c	1999/09/19 18:22:58	1.180
--- som.c	1999/12/09 20:30:41
*************** som_bfd_link_split_section (abfd, sec)
*** 6229,6234 ****
--- 6229,6235 ----
  #define som_construct_extended_name_table \
    _bfd_archive_coff_construct_extended_name_table
  #define som_update_armap_timestamp	bfd_true
+ #define som_allow_commons_in_armap	bfd_true
  #define som_bfd_print_private_bfd_data  _bfd_generic_bfd_print_private_bfd_data
  
  #define som_get_lineno                  _bfd_nosymbols_get_lineno

Index: targets.c
===================================================================
RCS file: /cvs/cvsfiles/devo/bfd/targets.c,v
retrieving revision 1.275
diff -p -r1.275 targets.c
*** targets.c	1999/09/28 22:33:52	1.275
--- targets.c	1999/12/09 20:30:41
*************** The general target vector.
*** 317,323 ****
  .CAT(NAME,_openr_next_archived_file),\
  .CAT(NAME,_get_elt_at_index),\
  .CAT(NAME,_generic_stat_arch_elt),\
! .CAT(NAME,_update_armap_timestamp)
  .  boolean  (*_bfd_slurp_armap) PARAMS ((bfd *));
  .  boolean  (*_bfd_slurp_extended_name_table) PARAMS ((bfd *));
  .  boolean  (*_bfd_construct_extended_name_table)
--- 317,324 ----
  .CAT(NAME,_openr_next_archived_file),\
  .CAT(NAME,_get_elt_at_index),\
  .CAT(NAME,_generic_stat_arch_elt),\
! .CAT(NAME,_update_armap_timestamp), \
! .CAT(NAME,_allow_commons_in_armap)
  .  boolean  (*_bfd_slurp_armap) PARAMS ((bfd *));
  .  boolean  (*_bfd_slurp_extended_name_table) PARAMS ((bfd *));
  .  boolean  (*_bfd_construct_extended_name_table)
*************** The general target vector.
*** 328,339 ****
  .                              struct orl *map,
  .                              unsigned int orl_count, 
  .                              int stridx));
! .  PTR (*_bfd_read_ar_hdr_fn) PARAMS ((bfd *));
  .  bfd *    (*openr_next_archived_file) PARAMS ((bfd *arch, bfd *prev));
  .#define bfd_get_elt_at_index(b,i) BFD_SEND(b, _bfd_get_elt_at_index, (b,i))
  .  bfd *    (*_bfd_get_elt_at_index) PARAMS ((bfd *, symindex));
  .  int      (*_bfd_stat_arch_elt) PARAMS ((bfd *, struct stat *));
  .  boolean  (*_bfd_update_armap_timestamp) PARAMS ((bfd *));
  .
  .  {* Entry points used for symbols.  *}
  .#define BFD_JUMP_TABLE_SYMBOLS(NAME)\
--- 329,341 ----
  .                              struct orl *map,
  .                              unsigned int orl_count, 
  .                              int stridx));
! .  PTR      (*_bfd_read_ar_hdr_fn) PARAMS ((bfd *));
  .  bfd *    (*openr_next_archived_file) PARAMS ((bfd *arch, bfd *prev));
  .#define bfd_get_elt_at_index(b,i) BFD_SEND(b, _bfd_get_elt_at_index, (b,i))
  .  bfd *    (*_bfd_get_elt_at_index) PARAMS ((bfd *, symindex));
  .  int      (*_bfd_stat_arch_elt) PARAMS ((bfd *, struct stat *));
  .  boolean  (*_bfd_update_armap_timestamp) PARAMS ((bfd *));
+ .  boolean  (*_bfd_allow_commons_in_armap) PARAMS ((bfd *));
  .
  .  {* Entry points used for symbols.  *}
  .#define BFD_JUMP_TABLE_SYMBOLS(NAME)\

Index: vms.c
===================================================================
RCS file: /cvs/cvsfiles/devo/bfd/vms.c,v
retrieving revision 1.3
diff -p -r1.3 vms.c
*** vms.c	1999/07/23 22:12:16	1.3
--- vms.c	1999/12/09 20:30:41
*************** static boolean vms_bfd_merge_private_bfd
*** 127,132 ****
--- 127,133 ----
  static boolean vms_bfd_set_private_flags PARAMS ((bfd *abfd, flagword flags));
  
  #define vms_make_empty_symbol _bfd_vms_make_empty_symbol
+ #define vms_allow_commons_in_armap bfd_true
  \f
  /*===========================================================================*/
  

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

* Re: GNU-ld behaviour does not match native linker behaviour
  1999-12-03  3:25 Nick Clifton
@ 1999-12-03 11:24 ` Ian Lance Taylor
  0 siblings, 0 replies; 16+ messages in thread
From: Ian Lance Taylor @ 1999-12-03 11:24 UTC (permalink / raw)
  To: nickc; +Cc: binutils

   Date: Fri, 3 Dec 1999 11:25:06 GMT
   From: Nick Clifton <nickc@cygnus.com>

   Presumably what should happen is that AR should only put a common
   symbol into its archive symbol table if the symbol is the definition
   of a common and not just another reference to it.  The the linker
   would know to link in that element.

That doesn't really make sense.  Common symbols are neither
definitions nor references.  They are a form of quasi definition which
becomes a reference if a real definition is seen, but get merged into
a real definition otherwise.

It seems as though to make your test case work we would have to make
two changes: 1) if a common symbol matches a symbol in the archive
symbol map, include the element in the link; 2) do not put common
symbols in the archive symbol map (see compute_and_write_armap in
archive.c).

Change 2 seems correct at first glance.  If a library includes
multiple objects which include a common symbol, we should not put that
common symbol into the archive symbol map multiple times.  That
doesn't make sense.

Given change 2, then change 1 makes some sense.  We will only see a
symbol in the archive map if it is a definition.  If we have a common
symbol, we want to bring in a definition.

I don't have the ELF spec handy.  I don't suppose it says anything
about this issue?  I also think we must test other ELF systems before
we should make either change.

Note that change 2 must not be made for the a.out object file format.
a.out defines a different, and rather odd, procedure for linking
against common symbols in archives.  See aout_link_check_ar_symbols in
aoutx.h.

Ian

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

* Re: GNU-ld behaviour does not match native linker behaviour
@ 1999-12-03  3:25 Nick Clifton
  1999-12-03 11:24 ` Ian Lance Taylor
  0 siblings, 1 reply; 16+ messages in thread
From: Nick Clifton @ 1999-12-03  3:25 UTC (permalink / raw)
  To: ian; +Cc: binutils

Hi Ian,

: That is too horrible.  The bug is that ar puts common symbols in the
: archive symbol table.  Check the behaviour of the Solaris ar program,
: and see whether the binutils version acts the same way.
: 
: I find it hard to believe that the Solaris linker goes through these
: gyrations.

Hmm, this may well be the case.  The customer who originally reported
this problem also had this to say:

: You should note something I find REALLY curious.  On HP,
: I get the correct, expected, behaviour if I use /bin/ar
: to create the fortran-code archive library.  However, if
: I use the gnu ar to create the archive - I then get the
: same incorrect behaviour I am seeing on Solaris and Linux.
: So could the gnu ar be somehow incorrectly marking something
: having to do with bkldta in the archive index?  Remember that
: we use the native ld on HP.
: 
: On Solaris I tried the same test, /usr/ccs/bin/ar vs. gnu ar.
: Didn't change anything, even if I used the native compiler
: to link.

Presumably what should happen is that AR should only put a common
symbol into its archive symbol table if the symbol is the definition
of a common and not just another reference to it.  The the linker
would know to link in that element.

I will have a look at fixing AR shortly.

Cheers
	Nick

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

* Re: GNU-ld behaviour does not match native linker behaviour
  1999-12-02 10:25 Nick Clifton
@ 1999-12-02 10:30 ` Ian Lance Taylor
  0 siblings, 0 replies; 16+ messages in thread
From: Ian Lance Taylor @ 1999-12-02 10:30 UTC (permalink / raw)
  To: nickc; +Cc: binutils

   Date: Thu, 2 Dec 1999 18:25:39 GMT
   From: Nick Clifton <nickc@cygnus.com>

   : You should be able to change the behaviour very easily.  In
   : elf_link_add_archive_symbols, just before the comment
   :     /* We need to include this archive member.  */
   : it checks the symbol in the archive map.  Right now it only includes
   : the archive member if the symbol is undefined.  You should be able to
   : change it to include the archive member if the symbol is common.

   Well that is what my patch does.  But the problem is that we still
   only want to include the archive element if it contains the
   *definition* of (the contents of) a common symbol, and not just
   another (common) declaration of it.  Thus the code has to open up the
   element, scan its symbol table, determine what kind of declaration of
   the symbol this is, and only then can the decision be made as to
   whether the element should be included in the link...

That is too horrible.  The bug is that ar puts common symbols in the
archive symbol table.  Check the behaviour of the Solaris ar program,
and see whether the binutils version acts the same way.

I find it hard to believe that the Solaris linker goes through these
gyrations.

Ian

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

* Re: GNU-ld behaviour does not match native linker behaviour
@ 1999-12-02 10:25 Nick Clifton
  1999-12-02 10:30 ` Ian Lance Taylor
  0 siblings, 1 reply; 16+ messages in thread
From: Nick Clifton @ 1999-12-02 10:25 UTC (permalink / raw)
  To: ian; +Cc: binutils

Hi Ian,

: You should be able to change the behaviour very easily.  In
: elf_link_add_archive_symbols, just before the comment
:     /* We need to include this archive member.  */
: it checks the symbol in the archive map.  Right now it only includes
: the archive member if the symbol is undefined.  You should be able to
: change it to include the archive member if the symbol is common.

Well that is what my patch does.  But the problem is that we still
only want to include the archive element if it contains the
*definition* of (the contents of) a common symbol, and not just
another (common) declaration of it.  Thus the code has to open up the
element, scan its symbol table, determine what kind of declaration of
the symbol this is, and only then can the decision be made as to
whether the element should be included in the link...

For reference purposes here is my current version of the patch.

Cheers
	Nick

Index: bfd/elflink.h
===================================================================
RCS file: /cvs/cvsfiles/devo/bfd/elflink.h,v
retrieving revision 1.107.4.1
diff -p -r1.107.4.1 elflink.h
*** elflink.h	1998/09/26 19:44:37	1.107.4.1
--- elflink.h	1999/12/01 16:11:55
*************** elf_bfd_link_add_symbols (abfd, info)
*** 72,77 ****
--- 72,164 ----
  }
  \f
  
+ /* Search the symbol table of the archive element of the archive ABFD
+    which contains the symbol SYMDEF and determine if it is defined there.  */
+ static boolean
+ elf_link_is_defined_archive_symbol (abfd, symdef)
+      bfd * abfd;
+      carsym * symdef;
+ {
+   Elf_Internal_Shdr * hdr;
+   Elf_External_Sym *  esym;
+   Elf_External_Sym *  esymend;
+   Elf_External_Sym *  buf = NULL;
+   size_t symcount;
+   size_t extsymcount;
+   size_t extsymoff;
+   boolean result = false;
+   
+   abfd = _bfd_get_elt_at_filepos (abfd, symdef->file_offset);
+   if (abfd == (bfd *) NULL)
+     return false;
+ 
+   if (! bfd_check_format (abfd, bfd_object))
+     return false;
+ 
+   if ((abfd->flags & DYNAMIC) == 0 || elf_dynsymtab (abfd) == 0)
+     hdr = &elf_tdata (abfd)->symtab_hdr;
+   else
+     hdr = &elf_tdata (abfd)->dynsymtab_hdr;
+ 
+   symcount = hdr->sh_size / sizeof (Elf_External_Sym);
+ 
+   /* The sh_info field of the symtab header tells us where the
+      external symbols start.  We don't care about the local
+      symbols at this point.  */
+   if (elf_bad_symtab (abfd))
+     {
+       extsymcount = symcount;
+       extsymoff = 0;
+     }
+   else
+     {
+       extsymcount = symcount - hdr->sh_info;
+       extsymoff = hdr->sh_info;
+     }
+ 
+   buf = ((Elf_External_Sym *)
+ 	 bfd_malloc (extsymcount * sizeof (Elf_External_Sym)));
+   if (buf == NULL && extsymcount != 0)
+     return false;
+ 
+   if (bfd_seek (abfd,
+ 		hdr->sh_offset + extsymoff * sizeof (Elf_External_Sym),
+ 		SEEK_SET) != 0
+       || (bfd_read ((PTR) buf, sizeof (Elf_External_Sym), extsymcount, abfd)
+ 	  != extsymcount * sizeof (Elf_External_Sym)))
+     {
+       free (buf);
+       return false;
+     }
+ 
+   esymend = buf + extsymcount;
+   for (esym = buf;
+        esym < esymend;
+        esym++)
+     {
+       Elf_Internal_Sym sym;
+       const char * name;
+ 
+       elf_swap_symbol_in (abfd, esym, & sym);
+ 
+       name = bfd_elf_string_from_elf_section (abfd, hdr->sh_link, sym.st_name);
+       if (name == (const char *) NULL)
+ 	break;
+ 
+       if (strcmp (name, symdef->name) == 0)
+ 	{
+ 	  result =
+ 	    (ELF_ST_BIND (sym.st_info) == STB_GLOBAL)
+ 	    && (sym.st_shndx != SHN_UNDEF);
+ 	  break;
+ 	}
+     }
+ 
+   free (buf);
+   
+   return result;
+ }
+ 
  /* Add symbols from an ELF archive file to the linker hash table.  We
     don't use _bfd_generic_link_add_archive_symbols because of a
     problem which arises on UnixWare.  The UnixWare libc.so is an
*************** elf_link_add_archive_symbols (abfd, info
*** 191,205 ****
  	  if (h == NULL)
  	    continue;
  
! 	  if (h->root.type != bfd_link_hash_undefined)
  	    {
  	      if (h->root.type != bfd_link_hash_undefweak)
  		defined[i] = true;
  	      continue;
  	    }
  
  	  /* We need to include this archive member.  */
- 
  	  element = _bfd_get_elt_at_filepos (abfd, symdef->file_offset);
  	  if (element == (bfd *) NULL)
  	    goto error_return;
--- 278,300 ----
  	  if (h == NULL)
  	    continue;
  
! 	  if (info->link_in_archive_definitions_of_commons
! 	      && h->root.type == bfd_link_hash_common)
  	    {
+ 	      /* If this archive element contains a definition of a common symbol
+ 		 then we need to include it.  If it just contains another common
+ 		 definition of the symbol, then we do not.  */
+ 	      if (! elf_link_is_defined_archive_symbol (abfd, symdef))
+ 		continue;
+ 	    }
+ 	  else if (h->root.type != bfd_link_hash_undefined)
+ 	    {
  	      if (h->root.type != bfd_link_hash_undefweak)
  		defined[i] = true;
  	      continue;
  	    }
  
  	  /* We need to include this archive member.  */
  	  element = _bfd_get_elt_at_filepos (abfd, symdef->file_offset);
  	  if (element == (bfd *) NULL)
  	    goto error_return;

Index: include/bfdlink.h
===================================================================
RCS file: /cvs/cvsfiles/devo/include/bfdlink.h,v
retrieving revision 1.32
diff -p -r1.32 bfdlink.h
*** bfdlink.h	1997/05/24 15:29:33	1.32
--- bfdlink.h	1999/12/01 16:11:57
*************** struct bfd_link_info
*** 193,198 ****
--- 193,203 ----
       on the output file, but may be checked when reading the input
       files.  */
    boolean traditional_format;
+   /* true if an archive element should be included in a link if it
+      defines a symbol which up until that point had only been defined
+      as a common symbol.  This is necessary when linking together
+      archives made up of FORTRAN generated objects.  */
+   boolean link_in_archive_definitions_of_commons;
    /* Which symbols to strip.  */
    enum bfd_link_strip strip;
    /* Which local symbols to discard.  */

Index: ld/ldmain.c
===================================================================
RCS file: /cvs/cvsfiles/devo/ld/ldmain.c,v
retrieving revision 1.157
diff -p -r1.157 ldmain.c
*** ldmain.c	1998/07/02 02:52:31	1.157
--- ldmain.c	1999/12/01 16:11:55
*************** main (argc, argv)
*** 206,211 ****
--- 206,212 ----
    link_info.symbolic = false;
    link_info.static_link = false;
    link_info.traditional_format = false;
+   link_info.link_in_archive_definitions_of_commons = false;
    link_info.strip = strip_none;
    link_info.discard = discard_none;
    link_info.keep_memory = true;

Index: ld/lexsup.c
===================================================================
RCS file: /cvs/cvsfiles/devo/ld/lexsup.c,v
retrieving revision 1.97
diff -p -r1.97 lexsup.c
*** lexsup.c	1998/07/23 16:24:43	1.97
--- lexsup.c	1999/12/01 16:11:56
*************** int parsing_defsym = 0;
*** 114,119 ****
--- 114,121 ----
  #define OPTION_FORCE_EXE_SUFFIX		(OPTION_WRAP + 1)
  #define OPTION_GC_SECTIONS		(OPTION_FORCE_EXE_SUFFIX + 1)
  #define OPTION_NO_GC_SECTIONS		(OPTION_GC_SECTIONS + 1)
+ #define OPTION_FORTRAN_LINKING		(OPTION_NO_GC_SECTIONS + 1)
+ #define OPTION_NO_FORTRAN_LINKING	(OPTION_FORTRAN_LINKING + 1)
  
  /* The long options.  This structure is used for both the option
     parsing and the help text.  */
*************** static const struct ld_option ld_options
*** 261,266 ****
--- 263,272 ----
        '\0', NULL, N_("Generate embedded relocs"), TWO_DASHES},
    { {"force-exe-suffix", no_argument, NULL, OPTION_FORCE_EXE_SUFFIX},
        '\0', NULL, N_("Force generation of file with .exe suffix"), TWO_DASHES},
+   { {"fortran-linking", no_argument, NULL, OPTION_FORTRAN_LINKING},
+       '\0', NULL, N_("link library objects which define common symbols"), TWO_DASHES},
+   { {"no-fortran-linking", no_argument, NULL, OPTION_NO_FORTRAN_LINKING},
+       '\0', NULL, "Turn off --fortran-linking", TWO_DASHES},
    { {"help", no_argument, NULL, OPTION_HELP},
        '\0', NULL, N_("Print option help"), TWO_DASHES },
    { {"Map", required_argument, NULL, OPTION_MAP},
*************** the GNU General Public License.  This pr
*** 891,897 ****
  	  lang_leave_group ();
  	  ingroup = 0;
  	  break;
! 
  	}
      }
  
--- 897,908 ----
  	  lang_leave_group ();
  	  ingroup = 0;
  	  break;
! 	case OPTION_FORTRAN_LINKING:
! 	  link_info.link_in_archive_definitions_of_commons = true;
! 	  break;
! 	case OPTION_NO_FORTRAN_LINKING:
! 	  link_info.link_in_archive_definitions_of_commons = false;
! 	  break;
  	}
      }
  
Index: ld/ld.texinfo
===================================================================
RCS file: /cvs/cvsfiles/devo/ld/ld.texinfo,v
retrieving revision 1.154
diff -p -r1.154 ld.texinfo
*** ld.texinfo	1998/07/13 17:23:54	1.154
--- ld.texinfo	1999/12/01 16:11:57
*************** option is useful when using unmodified U
*** 401,406 ****
--- 401,427 ----
  Windows host, since some versions of Windows won't run an image unless
  it ends in a @code{.exe} suffix.
  
+ @kindex --fortran-linking
+ @cindex linking FORTRAN libraries
+ @item --fortran-linking
+ Forces the linker to include object files in libraries that contain
+ defintions of symbols which up until that point in the link has only be
+ seen as common symbols.  This is not the standard beahviour of a linker,
+ which would normally only include a library object file if it contained
+ a defintion of a symbol which up until that point had been undefined.
+ 
+ This option is necessary in order to correctly link libraries which
+ contain FORTRAN generated object files.  In FORTRAN the definition of
+ the contents of a global common object are seperate from the declaration
+ of the object itself, and if these happen in different object files,
+ then without this option it is possible to link in the declaration of
+ the common object without linking in the definition of its contents.
+ 
+ @kindex --no-fortran-linking
+ @item --no-fortran-linking
+ Turns off the behaviour enabled by a previous @samp{--fortran-linking}
+ command line switch.
+ 
  @kindex -g
  @item -g
  Ignored.  Provided for compatibility with other tools.

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

* Re: GNU-ld behaviour does not match native linker behaviour
  1999-12-02  4:08 Nick Clifton
@ 1999-12-02 10:18 ` Ian Lance Taylor
  0 siblings, 0 replies; 16+ messages in thread
From: Ian Lance Taylor @ 1999-12-02 10:18 UTC (permalink / raw)
  To: nickc; +Cc: binutils

   Date: Thu, 2 Dec 1999 12:08:50 GMT
   From: Nick Clifton <nickc@cygnus.com>

     It has been brought to my attention that GNU-ld does not handle
     commons in libraries in the same way as SUN's or HP's linkers handle
     them.

   So - which linker is doing the right thing ?

I don't know.  I thought the GNU linker behaved the same as the
Solaris linker.  I remember testing it.  But perhaps I screwed up, or
perhaps the Solaris linker changed its behaviour.

It's hard to know what to do with common symbols, because they do not
have clearly defined semantics.  Different people have different
expectations of them.

Is it possible for you check an SVR4 or Unixware system?

   I have a patch to change the behaviour of GNU-ld, although it is
   rather cumbersome, but I do not know if I should even submit it, since
   I am not at all sure that GNU-ld is doing the wrong thing.

You should be able to change the behaviour very easily.  In
elf_link_add_archive_symbols, just before the comment
    /* We need to include this archive member.  */
it checks the symbol in the archive map.  Right now it only includes
the archive member if the symbol is undefined.  You should be able to
change it to include the archive member if the symbol is common.

Ian

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

* GNU-ld behaviour does not match native linker behaviour
@ 1999-12-02  4:08 Nick Clifton
  1999-12-02 10:18 ` Ian Lance Taylor
  0 siblings, 1 reply; 16+ messages in thread
From: Nick Clifton @ 1999-12-02  4:08 UTC (permalink / raw)
  To: binutils

Hi Guys,

  It has been brought to my attention that GNU-ld does not handle
  commons in libraries in the same way as SUN's or HP's linkers handle
  them.   Here is an example:

GNU-ld  (eg Linux)

   % cat main.c
   int common_sym;
   int main (void) { return printf ("%d\n\n", common_sym); }
 
   % gcc main.c
   % a.out
   0
 
   % cat define.c
   int common_sym = 3;
   int foo (void) { return 0; }
 
   % gcc -c define.c
   % ar r libtest.a define.o

   % gcc main.c define.o
   % a.out
   3
 
   % gcc main.c libtest.a
   % a.out
   0
 
   % gcc -Wl,-ufoo main.c libtest.a
   % a.out
   3

Note how linking with a library which contains a defintion of the
contents of a common symbol has no effect unless there is some other
reason to link in the archive element which contains the common
defintion.

However on Solaris 7 things are slightly different:

  % /opt/SUNWspro/bin/cc main.c
  % a.out
  0

  % /opt/SUNWspro/bin/cc -c define.c 
  % /usr/ccs/bin/ar r libtest.a define.o

  % /opt/SUNWspro/bin/cc main.c define.o
  % a.out
  3

  % /opt/SUNWspro/bin/cc main.c libtest.a
  % a.out
  3

  % /opt/SUNWspro/bin/cc -Wl,-ufoo main.c libtest.a
  % a.out
  3

So now the common symbol gets defined from the library even if there
is no other reason to link in that particular library element.  The
same thing happens using HP-UX 11.0's native linker.

So - which linker is doing the right thing ?

I have a patch to change the behaviour of GNU-ld, although it is
rather cumbersome, but I do not know if I should even submit it, since
I am not at all sure that GNU-ld is doing the wrong thing.

Note - this handling of commons is particularly important when linking
together FORTRAN libraries, since the definition of the contents of a
common symbol can often be found in a seperate object file to the
defintion of the use of the common symbol.

Cheers
	Nick

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

end of thread, other threads:[~1999-12-10 12:05 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1999-12-08 12:41 GNU-ld behaviour does not match native linker behaviour Nick Clifton
1999-12-08 18:46 ` Ian Lance Taylor
  -- strict thread matches above, loose matches on Subject: below --
1999-12-10 11:55 Nick Clifton
1999-12-10 12:05 ` Ian Lance Taylor
1999-12-10 10:53 Nick Clifton
1999-12-09 16:14 Nick Clifton
1999-12-10  4:14 ` Andreas Schwab
1999-12-10  8:13   ` Ian Lance Taylor
1999-12-09 12:49 Nick Clifton
1999-12-09 15:20 ` Ian Lance Taylor
1999-12-03  3:25 Nick Clifton
1999-12-03 11:24 ` Ian Lance Taylor
1999-12-02 10:25 Nick Clifton
1999-12-02 10:30 ` Ian Lance Taylor
1999-12-02  4:08 Nick Clifton
1999-12-02 10:18 ` 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).