[patch] init_array/fini_array support

John Bowler jbowler at acm.org
Thu Feb 2 18:45:01 UTC 2006


From: Joakim Tjernlund [mailto:joakim.tjernlund at transmode.se]
>For dynamic bulids the code is in rtld.c:
>if (!INTUSE(__libc_enable_secure)
>              && memcmp (envline, "DYNAMIC_WEAK", 12) == 0)
>            GLRO(dl_dynamic_weak) = 1;
>
>This will set dl_dynamic_weak to 1 if LD_DYNAMIC_WEAK is defined.

Ok, I tested it this time...  The program is appended to the email.

Given a program and three objects or shared libraries:

weak1 function foo is weak returns the string "weak1"
weak2 function foo is weak and returns the string "weak2"
strong function foo is weak and returns the string "strong"
function "bar" (-DSHARED) is strong in all three units

The main program just declares foo (const char *foo()), calls
it and printfs the result.

1) static: symbols are resolved by the static linker and the strong
   symbol always takes precedence.
2) DLL with LD_DYNAMIC_WEAK=<anything> (including ""), the strong
   symbol takes precedence.
3) DLL with no LD_DYNAMIC_WEAK in the environment, the result is
   the first implementation of foo on the link command line.
   E.g.:

     gcc -o t test-weak.o weak1.so weak2.so strong.so  --> weak1
     gcc -o t test-weak.o weak2.so weak1.so strong.so  --> weak2

This is i386 gentoo running glibc 2.3.5.  The function "bar" (which
is strong throughout) always behaves as (3) - the first definition
found in the objects on the original link command line is taken.

Typically the program objects are first and -lc is last, therefore
the appearance of strong program definitons overriding weak ones
in -lc is maintained.

Notice that there is absolutely no point defining a symbol 'weak'
in a DLL with this implementation - it behaves exactly as a strong
symbol.  The attached code demonstrates this with respect to 'bar'.
'weak' is only useful in the *declaration* of an undefined symbol to
ensure that the linker (ld or ld.so) will not fault the lack of
a definition!

I suspect this may be a bug fix work round in ld.so for a compiler
issue - there is no way I can see to make the symbol definition
strong in the presence of a weak symbol declaration.  With this
behaviour in ld.so, however, the code path for STB_WEAK matches
that for STB_GLOBAL (when looking for the definition of a symbol)
and therefore the weak attribute is effectively ignored.

I guess it doesn't matter because, since weak definition doesn't
work in  glibc (i.e. it doesn't do anything useful) program writers
outside libc/uclibc aren't going to be able to use it and program
build scripts will have to get the link library order correct (to
ensure that the required definition is retrieved).

Worse, since the presence or absence of a weak *declaration*
affects a definition within its scope, programmers will 
inevitably produce code which contains weak *definitions* which
should be strong.  So this means that it is probably no longer
possible to actually support such a feature ("my code can't
possibly be wrong because it works with glibc/gcc"...)

John Bowler <jbowler at acm.org>

diff -rupN n/strong.c t/strong.c
--- n/strong.c	1969-12-31 16:00:00.000000000 -0800
+++ t/strong.c	2006-02-02 10:06:49.634869781 -0800
@@ -0,0 +1,8 @@
+const char *foo(void) {
+	return "strong";
+}
+#if SHARED
+const char *bar(void) {
+	return "strong";
+}
+#endif
diff -rupN n/test-weak.c t/test-weak.c
--- n/test-weak.c	1969-12-31 16:00:00.000000000 -0800
+++ t/test-weak.c	2006-02-02 10:10:39.297869457 -0800
@@ -0,0 +1,10 @@
+extern char *foo(void);
+extern char *bar(void);
+
+int main(void) {
+	printf("foo is %s\n", foo());
+#	if SHARED
+		printf("bar is %s\n", bar());
+#	endif
+	return 0;
+}
diff -rupN n/weak1.c t/weak1.c
--- n/weak1.c	1969-12-31 16:00:00.000000000 -0800
+++ t/weak1.c	2006-02-02 10:06:30.524869808 -0800
@@ -0,0 +1,9 @@
+const char *foo(void) __attribute__((weak));
+const char *foo(void) {
+	return "weak1";
+}
+#if SHARED
+const char *bar(void) {
+	return "weak1";
+}
+#endif
diff -rupN n/weak2.c t/weak2.c
--- n/weak2.c	1969-12-31 16:00:00.000000000 -0800
+++ t/weak2.c	2006-02-02 10:06:44.097869789 -0800
@@ -0,0 +1,9 @@
+const char *foo(void) __attribute__((weak));
+const char *foo(void) {
+	return "weak2";
+}
+#if SHARED
+const char *bar(void) {
+	return "weak2";
+}
+#endif
-------------- next part --------------
A non-text attachment was scrubbed...
Name: winmail.dat
Type: application/ms-tnef
Size: 3720 bytes
Desc: not available
Url : http://lists.busybox.net/pipermail/uclibc/attachments/20060202/c337bb29/attachment.bin 


More information about the uClibc mailing list