Found this while compiling kde 3.1.
kpovmodeler works statically, but not dynamically.
Looking at the link graph,
kpovmodeler is linked against libkpovmodelerpart and libqt-mt
and libkpovmodelerpart is linked against libqt-mt
The issue is that the linker resolves ctors sequentially, so libqt-mt
ctors are called after libkpovmodelerpart... and some libkpovmodelerpart
ctors are dependent on libqt-mt being initialized already.
Logically, ctors for a dependent library should be called *before* ctors
for the library itself.
The following patch allows ld.so to build a full dependency tree of
libraries it loads, and to resolve constructors in a better order:
dependent libraries first, in sequential order, and then main library
(there is a flag that forbids initializing a library twice).
I'm now running with this. Please test and comment.
Note: there is a possibility that this is the bug that cripples dynamic
builds of mozilla, though I haven't checked yet...
Index: rtld.c
RCS file: /cvs/src/gnu/usr.bin/ld/rtld/rtld.c,v
retrieving revision 1.33
diff -u -p -r1.33 rtld.c
--- rtld.c 5 Jan 2003 09:04:10 -0000 1.33
+++ rtld.c 15 Jan 2003 18:31:55 -0000
@@ -97,11 +97,19 @@ struct somap_private {
#define RTLD_MAIN 1
#define RTLD_RTLD 2
#define RTLD_DL 4
+#define RTLD_INITED 8
size_t spd_size;
#ifdef SUN_COMPAT
long spd_offset; /* Correction for Sun main programs */
#endif
+ struct dep_node *first_child;
+ struct dep_node *last_child;
+};
+
+struct dep_node {
+ struct dep_node *next_sibling;
+ struct so_map *data;
};
#define LM_PRIVATE(smp) ((struct somap_private *)(smp)->som_spd)
@@ -358,6 +366,23 @@ rtld(int version, struct crt_ldso *crtp,
return 0;
}
+static void
+link_sub(struct so_map *dep, struct so_map *p)
+{
+ struct dep_node *n;
+ struct somap_private *pp;
+
+ n = xmalloc(sizeof *n);
+ n->data = dep;
+ n->next_sibling = NULL;
+ pp = LM_PRIVATE(p);
+ if (pp->first_child) {
+ pp->last_child->next_sibling = n;
+ pp->last_child = n;
+ } else {
+ pp->first_child = pp->last_child = n;
+ }
+}
static int
load_subs(struct so_map *smp)
@@ -380,16 +405,35 @@ load_subs(struct so_map *smp)
if ((newmap = map_object(sodp, smp)) == NULL) {
if (!ld_tracing) {
- char *fmt = sodp->sod_library ?
- "%s: lib%s.so.%d.%d" :
- "%s: %s";
- err(1, fmt, main_progname,
+ if (smp != main_map)
+ if (sodp->sod_library)
+ err(1, "%s(%s): lib%s.so.%d.%d",
+ main_progname,
+ smp->som_path,
+ sodp->sod_name+LM_LDBASE(smp),
+ sodp->sod_major,
+ sodp->sod_minor);
+ else
+ err(1, "%s(%s): %s",
+ main_progname,
+ smp->som_path,
+ sodp->sod_name+LM_LDBASE(smp));
+ else
+ if (sodp->sod_library)
+ err(1, "%s: lib%s.so.%d.%d",
+ main_progname,
sodp->sod_name+LM_LDBASE(smp),
sodp->sod_major,
sodp->sod_minor);
+ else
+ err(1, "%s: %s",
+ main_progname,
+ sodp->sod_name+LM_LDBASE(smp));
}
newmap = alloc_link_map(NULL, sodp, smp,
0, 0, 0);
+ } else {
+ link_sub(newmap, smp);
}
LM_PRIVATE(newmap)->spd_refcount++;
next = sodp->sod_next;
@@ -511,6 +555,8 @@ alloc_link_map(char *path, struct sod *s
smpp->spd_flags = 0;
smpp->spd_parent = parent;
smpp->spd_size = size;
+ smpp->first_child = NULL;
+ smpp->last_child = NULL;
#ifdef SUN_COMPAT
smpp->spd_offset =
@@ -690,6 +736,23 @@ unmap_object(struct so_map *smp)
(void)munmap(smp->som_addr, LM_PRIVATE(smp)->spd_size);
}
+void init_dependent_before_main(struct so_map *smp)
+{
+ struct dep_node *n;
+
+ LM_PRIVATE(smp)->spd_flags |= RTLD_INITED;
+
+ for (n = LM_PRIVATE(smp)->first_child; n; n = n->next_sibling) {
+ if (LM_PRIVATE(n->data)->spd_flags & RTLD_INITED)
+ continue;
+ init_dependent_before_main(n->data);
+ }
+
+ call_map(smp, ".init");
+ call_map(smp, "__init");
+ call_map(smp, "__GLOBAL__DI");
+}
+
void
init_maps(struct so_map *head)
{
@@ -713,9 +776,9 @@ init_maps(struct so_map *head)
for (smp = head; smp; smp = smp->som_next) {
if (LM_PRIVATE(smp)->spd_flags & RTLD_RTLD)
continue;
- call_map(smp, ".init");
- call_map(smp, "__init");
- call_map(smp, "__GLOBAL__DI");
+ if (LM_PRIVATE(smp)->spd_flags & RTLD_INITED)
+ continue;
+ init_dependent_before_main(smp);
}
}
Received on Wed Jan 15 13:42:07 2003