OSDN Git Service

Fix libdl bug reported by Cedric Hombourger in
authorJoakim Tjernlund <joakim.tjernlund@transmode.se>
Fri, 26 Jan 2007 00:25:10 +0000 (00:25 -0000)
committerJoakim Tjernlund <joakim.tjernlund@transmode.se>
Fri, 26 Jan 2007 00:25:10 +0000 (00:25 -0000)
http://uclibc.org/lists/uclibc/2007-January/017165.html

ldso/ldso/ldso.c
ldso/libdl/libdl.c

index f8f3dc6..d31ae1d 100644 (file)
@@ -192,6 +192,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
        unsigned long *_dl_envp;                /* The environment address */
        ElfW(Addr) relro_addr = 0;
        size_t relro_size = 0;
+       struct stat st;
 
        /* Wahoo!!! We managed to make a function call!  Get malloc
         * setup so we can use _dl_dprintf() to print debug noise
@@ -725,6 +726,10 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
                                              (unsigned long)tpnt->dynamic_addr,
                                              0);
 
+               if (_dl_stat(tpnt->libname, &st) >= 0) {
+                       tpnt->st_dev = st.st_dev;
+                       tpnt->st_ino = st.st_ino;
+               } 
                tpnt->n_phent = epnt->e_phnum;
                tpnt->ppnt = myppnt;
                for (j = 0; j < epnt->e_phnum; j++, myppnt++) {
index e7e33c4..505f095 100644 (file)
@@ -246,36 +246,31 @@ void *dlopen(const char *libname, int flag)
 
                                tpnt1->rtld_flags |= (flag & RTLD_GLOBAL);
 
-                               if (tpnt1->usage_count == 1) {
-                                       tpnt1->init_flag |= DL_OPENED;
-                                       /* This list is for dlsym() and relocation */
-                                       dyn_ptr->next = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));
-                                       _dl_memset (dyn_ptr->next, 0, sizeof (struct dyn_elf));
-                                       dyn_ptr = dyn_ptr->next;
-                                       dyn_ptr->dyn = tpnt1;
-                               }
-                               if (tpnt1->init_flag & DL_OPENED) {
-                                       /* Used to record RTLD_LOCAL scope */
-                                       tmp = alloca(sizeof(struct init_fini_list));
-                                       tmp->tpnt = tpnt1;
-                                       tmp->next = runp->tpnt->init_fini;
-                                       runp->tpnt->init_fini = tmp;
-
-                                       for (tmp=dep_list; tmp; tmp = tmp->next) {
-                                               if (tpnt1 == tmp->tpnt) { /* if match => cirular dependency, drop it */
-                                                       _dl_if_debug_print("Circular dependency, skipping '%s',\n",
-                                                                       tmp->tpnt->libname);
-                                                       tpnt1->usage_count--;
-                                                       break;
-                                               }
-                                       }
-                                       if (!tmp) { /* Don't add if circular dependency detected */
-                                               runp2->next = alloca(sizeof(*runp));
-                                               runp2 = runp2->next;
-                                               runp2->tpnt = tpnt1;
-                                               runp2->next = NULL;
+                               /* This list is for dlsym() and relocation */
+                               dyn_ptr->next = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));
+                               _dl_memset (dyn_ptr->next, 0, sizeof (struct dyn_elf));
+                               dyn_ptr = dyn_ptr->next;
+                               dyn_ptr->dyn = tpnt1;
+                               /* Used to record RTLD_LOCAL scope */
+                               tmp = alloca(sizeof(struct init_fini_list));
+                               tmp->tpnt = tpnt1;
+                               tmp->next = runp->tpnt->init_fini;
+                               runp->tpnt->init_fini = tmp;
+
+                               for (tmp=dep_list; tmp; tmp = tmp->next) {
+                                       if (tpnt1 == tmp->tpnt) { /* if match => cirular dependency, drop it */
+                                               _dl_if_debug_print("Circular dependency, skipping '%s',\n",
+                                                                  tmp->tpnt->libname);
+                                               tpnt1->usage_count--;
+                                               break;
                                        }
                                }
+                               if (!tmp) { /* Don't add if circular dependency detected */
+                                       runp2->next = alloca(sizeof(*runp));
+                                       runp2 = runp2->next;
+                                       runp2->tpnt = tpnt1;
+                                       runp2->next = NULL;
+                               }
                        }
                }
        }
@@ -441,8 +436,10 @@ void *dlsym(void *vhandle, const char *name)
                        }
                }
        }
-
-       ret = _dl_find_hash((char*)name, handle, NULL, 0);
+       tpnt = NULL;
+       if (handle == _dl_symbol_tables)
+          tpnt = handle->dyn; /* Only search RTLD_GLOBAL objs if global object */
+       ret = _dl_find_hash((char*)name, handle, tpnt, 0);
 
        /*
         * Nothing found.