OSDN Git Service

libdl: fix size parameter when unmap library in dlclose
authorFilippo Arcidiacono <filippo.arcidiacono@st.com>
Wed, 23 Nov 2011 10:50:55 +0000 (11:50 +0100)
committerCarmelo Amoroso <carmelo.amoroso@st.com>
Wed, 23 Nov 2011 15:12:09 +0000 (16:12 +0100)
Fix size parameter when unmap a library by means of dlclose, by
taking into account the p_vaddr of first PT_LOAD segment, so it works
also for prelinked shared objects.
Unmapping of dlopen shared libraries is broken since
94cc6edb78a12655c0602a246fa1cbdc8c6d0ad9

Signed-off-by: Filippo Arcidiacono <filippo.arcidiacono@st.com>
Signed-off-by: Carmelo Amoroso <carmelo.amoroso@st.com>
ldso/libdl/libdl.c

index cbbbcd4..324b76a 100644 (file)
@@ -751,7 +751,7 @@ static int do_dlclose(void *vhandle, int need_fini)
        int (*dl_elf_fini) (void);
        void (*dl_brk) (void);
        struct dyn_elf *handle;
-       unsigned int end;
+       unsigned int end = 0, start = 0xffffffff;
        unsigned int i, j;
        struct r_scope_elem *ls;
 #if defined(USE_TLS) && USE_TLS
@@ -813,6 +813,8 @@ static int do_dlclose(void *vhandle, int need_fini)
                                        i < tpnt->n_phent; ppnt++, i++) {
                                if (ppnt->p_type != PT_LOAD)
                                        continue;
+                               if (ppnt->p_vaddr < start)
+                                       start = ppnt->p_vaddr;
                                if (end < ppnt->p_vaddr + ppnt->p_memsz)
                                        end = ppnt->p_vaddr + ppnt->p_memsz;
                        }
@@ -919,7 +921,9 @@ static int do_dlclose(void *vhandle, int need_fini)
                        }
 #endif
 
-                       DL_LIB_UNMAP (tpnt, end - tpnt->mapaddr);
+                       end = (end + ADDR_ALIGN) & PAGE_ALIGN;
+                       start = start & ~ADDR_ALIGN;
+                       DL_LIB_UNMAP (tpnt, end - start);
                        /* Free elements in RTLD_LOCAL scope list */
                        for (runp = tpnt->rtld_local; runp; runp = tmp) {
                                tmp = runp->next;