[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