Symbol Resolution Inconsistencies
Suprateeka R Hegde
hegdesmailbox@gmail.com
Fri Jan 1 00:00:00 GMT 2016
Hi
There are some inconsistencies in terms of symbol resolution and library
search mechanism.
Consider this: case:
---
$ cat main.c
extern void foo(void);
int main() { foo(); return 0;}
$ cat weakfoo.c
#include <stdio.h>
#pragma weak foo
void foo(void){ printf("WEAK foo\n"); }
$ cat defauktfoo.c
#include <stdio.h>
void foo(void){ printf("DEFAULT foo\n"); }
(creating archive libraries)
$ cc main.o -L. -ldefaultfoo -lweakfoo
$ ./a.out
DEFAULT foo
(Reversing the archive lib order)
$ cc main.o -L. -lweakfoo -ldefaultfoo
$ ./a.out
WEAK foo
---
The resolution for foo is based on the order in which it appears and not
based on the binding type.
However, adding a new dependency bar() in main.c and defining it in
defaultfoo.c to forceload defaultfoo.o from archive libdefaultfoo.a, as in:
---
$ cat main.c
extern void foo(void);
extern void bar(void);
int main() { foo(); bar(); return 0;}
$ cat defaultfoo.c
#include <stdio.h>
void foo(void){ printf("DEFAULT foo\n"); }
void bar(void){ printf("BAR from default foo\n"); }
$ ar r libdefaultfoo.a defaultfoo.o
$ ar r libweakfoo.a weakfoo.o
$ cc main.o -L. -lweakfoo -ldefaultfoo
$ ./a.out
DEFAULT foo
BAR from default foo
---
In the above case, though weakfoo appears first in the order, the WEAK
foo is discarded. It is clear that this is because defaultfoo.o is now
forceloaded (because of bar) into linker's symbol resolution phase.
However, even the above case (with bar) does not pick Default foo when
both are shared libraries. In case of shared libraries, it is always
based on the library order irrespective of binding type.
Technically, as linker engineers, we can explain whats happening. But
aren't all these inconsistent in the perspective of an application
developer? Like:
1. Adding a totally new reference changes resolution of existing symbols.
2. Changing archive to shared library type changes symbol resolution.
Now consider a case where we mark the reference to foo (in main) as WEAK
(IMHO I am against the philosophy of assigning a binding type to a
reference). In this case, the behavior is as per SYS-V gABI -- "The link
editor does not extract archive members to resolve undefined weak
symbols. Unresolved weak symbols have a zero value".
Either we need a rule that says once a symbol has been resolved to a
definition either weak or non-weak in an archive library, that symbol
should not participate further in the resolution phase.
Or a rule that says, if an undefined symbol is resolved to a weak
symbol, link editor continues searching all objects and archive
libraries for the availability of a non-weak symbol. In the absence of
such a non-weak symbol, final resolution shall be to the weak symbol.
However, this latter rule also means, some work for dynamic linker or
some sort of symbol_name@lib_name coupling.
This is not about right or wrong behavior. This is about making a
behavior consistent at least on the same platform -- GNU.
--
Supra
More information about the Gnu-gabi
mailing list