static link problems with alias

Nick Clifton nickc@redhat.com
Tue Jan 9 17:25:00 GMT 2007


Hi Carmelo,

> I switched the link order of the archives
> gcc -static -L. main.c -lfoo -lfoo_alias
> and this works fine.
> 
> so does the link take the foo symbol from libfoo:foo.o without further
> searching?

Yes.

When the linker scans libfoo_alias.a it only looks for symbols which it 
currently has marked as "unresolved".  So it finds the "bar" symbol in 
libfoo_alias:bar.o, and links in that entire object file.  This brings 
in an unresolved symbol "foo", but it now has a definition of that 
symbol in libfoo:foo.o (which it has already linked in because it 
contains a definition of "other" which is needed by "main").  So the 
linker resolves the reference to "foo" by using the definition in 
libfoo:foo.o.

Here is an interesting test.

   1.  Rerun your test but add "-Wl,-Map,main-calls-other" to the final
       gcc command line.
   2.  Edit main.c, comment out the call to "other", recompile main.c.
   3.  Rerun the final gcc command line again, but this time use
       "-Wl,-Map,main-only-calls-bar".

You should now have two linker map files called "main-calls-other" and 
"main-only-calls-bar".  Have a look through the files.  They are fairly 
self-documenting.  In particular you should see something like this in 
main-calls-other:

  .text          0x0000000000400264       0x16 ./libfoo.a(foo.o)
                 0x000000000040026f                other
                 0x0000000000400264                foo

Showing that the "foo" symbol has been resolved from the definition in 
foo.o, whereas in main-only-calls-bar you should see:

  .text          0x000000000040026c        0xb ./libfoo_alias.a(foo_alias.o)
                 0x000000000040026c                foo_alias
                 0x000000000040026c                foo

Showing that this time the "foo" symbol has been resolved to come from 
the definition in the foo_alias.o.

It is all about what symbols are undefined at the time that the linker 
encounters a library on the command line.  So when main calls "other" we 
have this:

   1. Linker see main.o on the command line and adds it to its output
      list.  The linker sees that it needs definitions of "bar" and
      "other"

   2. Linker encounters libfoo.a on the command line.
      This contains libfoo.a:foo.o which provides a definition of
      "other".  So this object file is linked in, and as a consequence a
      definition of the symbol "foo" is also brought in.

   3. The linker then *forgets* about any other object files contained in
      libfoo.a which it has decided not to link in.  (There are none in
      this particular case, but it becomes important in a moment).

   4. The linker encounters libfoo_alias.a on the command line.  This
      contains libfoo.a:bar.o which defines "bar", so this object file is
      linked in.  bar.o also refers to the "foo" symbol, but the linker
      already has a definition of this symbol from its inclusion of
      libfoo:foo.o.

OK ?  So now when we look at the second case, where main does not call 
"other":

   1. Linker see main.o on the command line and adds it to its output
      list.  The linker sees that it needs definitions of "bar" (but not
      a definition of "other").

   2. Linker encounters libfoo.a on the command line.
      This does not contain a definition of "bar".  So *none* of the
      object files in libfoo.a are included in the link.  In particular
      libfoo.a:foo.o is not included, so the linker does not gain a
      definition of the symbol "foo".

   3. The linker encounters libfoo_alias.a on the command line.  This
      contains libfoo.a:bar.o which defines "bar", so this object file is
      linked in.  bar.o also refers to the "foo" symbol, but since the
      linker has now forgotten all about the contents of libfoo.a it
      keeps on searching and finds a definition in
      libfoo_alias:foo_alias.o.  So this object file is included in the
      link.

Does this make things clear ?



> I know the order is important, so I'd like to understand if the
> following statements are correct:
> 1) when using alias (strong or weak) the symbol's searching is
> perfomed through all the
> libraries (failing if multiple definition will be found)

no.

> 2) while referring to a 'real' symbol the linker will stop at the
> first occurrence

no.

:-)


The linker uses the same algorithm for resolving undefined weak symbols 
as for resolving undefined undefined strong symbols.  Have a read of the 
linker manual.  (In particular have a look at the actions of the 
--startgroup and --endgroup switches which relate to whether the linker 
will repeatedly scan a group of libraries).

Cheers
   Nick



More information about the Binutils mailing list