This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Bug report: objc classes linked in wrong order
- To: hjl at lucon dot org
- Subject: Re: Bug report: objc classes linked in wrong order
- From: nicola at brainstorm dot co dot uk
- Date: Mon, 15 May 2000 13:05:12 +0100 (BST)
- cc: egcs at egcs dot cygnus dot com, ovidiu at cup dot hp dot com
> > It is a very interesting problem. I know very little about Objective-C.
> > From the asm output, I have an impression that the Objective-C class
> > implemenation is registered via the .ctors section. When you link with
> >
> > # cc -I./ -L/user/hjl/bugs/objc/shared/bug.report/install -o test-shared test.o -ltest1 -ltest2 -lobjc -lpthread
> >
> > "-ltest1 -ltest2 -lobjc -lpthread -lgcc -lc -lgcc" is passed to the
> > linker. The dynamic linker in glibc 2.1 will process the .ctors section
> > in the reverse order. That is
> >
> > 11951: calling init: /lib/libc.so.6
> > 11951: calling init: /lib/libpthread.so.0
> > 11951: calling init: ./install/libtest2.so.0
> > 11951: calling init: ./install/libtest1.so.0
> >
> > As the result, the implemenation in libtest2 gets register first. For
> > the static link, libtest2.a is not even used at all. I don't know for
> > sure what the right answer for it is.
> >
Thank you very much for the diagnosis. My conclusions were similar, but
having a word from someone experienced in the field helps a lot. :-)
> This patch seems to work for me. But I know nothing about Objective-C.
> It may be the wrong thing to do.
While I wouldn't use the patch, I am very impressed that you tried
to help that way. It was really great.
I have solved my problem in a different way.
The problem arises because I patched libobjc to be compiled as shared
library using libtool (patches submitted already but stuck because of the
copyright assignment taking long to be processed).
At this point, I of course want to use the new shared libobjc with
GNUstep. What happens is that libobjc is providing a minimal
implementation of the class NXConstantString, so that you can compile
trivial Objective-C stuff with libobjc only; but GNUstep is overriding
NXConstantString with a much more complete and powerful implementation,
fully integrated in the GNUstep framework. (NB: GNUstep's
NXConstantString has a different place in the classes' hierarchy than
libobjc's one).
During the link stage, we want GNUstep's implementation and not libobjc's
one to be used. This worked till libobjc was static. It doesn't plainly
work with a shared libobjc (as far as I know, this is the only problem we
have).
Actually in the end it probably looks like a very specific problem - I
know no other case in which an objective C library would need to
completely override the implementation of a class in another objective C
library, at the same time moving the class to a different position in the
class hierarchy (what we need to do with NXConstantString). This is
because usually Objective-C already provides so many ways to
implement/override other classes implementations, that it is rarely needed
to do something of this kind. I think it's not worth to try having the
runtime load an implementation over another one - causing problems.
So - an ad hoc solution is probably appropriate.
A good idea would simply be not to link in the NXConstantString
implementation in the shared libobjc. I know people who like this idea a
lot. My opinion is that this would not allow people to run objective-C
code without linking to GNUstep or another library providing an
implementation of NXConstantString - and we don't want to scare newcomers,
so my proposal is to use the following patch to libobjc/init.c:
--- /home/nicola/egcs-20000424/libobjc/init.c Mon Jun 21 05:41:41 1999
+++ ./init.c Wed May 10 13:15:18 2000
@@ -26,6 +26,14 @@
#include "runtime.h"
+/* This can be overriden with a function returning 1.
+ In that case, libobjc does not load its own version of NXConstantString */
+int
+_user_defined_NXConstantString (void)
+{
+ return 0;
+}
+
/* The version number of this runtime. This must match the number
defined in gcc (objc-act.c) */
#define OBJC_VERSION 8
@@ -469,7 +477,34 @@
/* dummy counter */
int i;
+ /* dummy pointer */
+ const char *p;
+
DEBUG_PRINTF ("received module: %s\n", module->name);
+
+ if (_user_defined_NXConstantString () == 1)
+ {
+ /* The user has overridden _user_defined_NXConstantString () to
+ tell us that he doesn't want us to load the library's
+ NXConstantString implementation */
+ DEBUG_PRINTF ("Filtering out libobjc's NXConstantString at programmer's request:\n");
+
+ /* Search last occurrence of letter 'N' in the module name */
+ p = (char *)strrchr (module->name, 'N');
+ if (p)
+ {
+ /* Found; compare string starting with this last 'N' to
+ "NXConstStr_libobjc.m" */
+ if (strcmp (p, "NXConstStr_libobjc.m") == 0)
+ {
+ /* it matches, so it is (should be) our NXConstantString
+ module - don't load it */
+ DEBUG_PRINTF ("Module not loaded\n");
+ return;
+ }
+ }
+ DEBUG_PRINTF ("Module loaded\n");
+ }
/* check gcc version */
init_check_module_version(module);
Then, by patching GNUstep's core/base/NSGCString.m adding the following
lines at the beginning:
/*
* Newer versions of libobjc require this not to include
* libobjc's implementation of NXConstantString
*/
int
_user_defined_NXConstantString (void)
{
return 1;
}
everything works fine: when linking with -lgnustep-base -lobjc, GNUstep's
NXConstantString gets used, while when linking only with -lobjc the
libobjc NXConstantString gets used.
Other libraries different from GNUstep needing to implement their own
NXConstantString instead of the minimal one provided by the Objective C
runtime can do the same using the same trick.