Pantek Library
Hosting Provided By
CybrHost
High Speed Hosting

a.out ld.so fix for constructor order

From: Marc Espie <espie(at)nerim.net>
Date: Wed Jan 15 2003 - 13:40:36 EST


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;

 };  
Do you need help?X

 #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);
Do you need more help?X

+ }
+
+ 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

This archive was generated by hypermail 2.1.8 : Wed Aug 23 2006 - 13:48:28 EDT


Contact Us  Legal Notices  Order Services Online 
Pantek Home  Privacy Policy  IT news  Site Map  Pantek Library