]> rtime.felk.cvut.cz Git - l4.git/blobdiff - l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/dl-elf.c
update
[l4.git] / l4 / pkg / uclibc / lib / contrib / uclibc / ldso / ldso / dl-elf.c
index dfd009d7b2b1db4eb35f68ce34835e96f3972d33..a63b997c31b32c623f8b5709d9eb8adfc2f18130 100644 (file)
@@ -337,6 +337,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
        unsigned long *lpnt;
        unsigned long libaddr;
        unsigned long minvma = 0xffffffff, maxvma = 0;
+       unsigned int rtld_flags;
        int i, flags, piclib, infile;
        ElfW(Addr) relro_addr = 0;
        size_t relro_size = 0;
@@ -468,7 +469,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
        DL_CHECK_LIB_TYPE (epnt, piclib, _dl_progname, libname);
 
        maxvma = (maxvma + ADDR_ALIGN) & PAGE_ALIGN;
-       minvma = minvma & ~0xffffU;
+       minvma = minvma & ~ADDR_ALIGN;
 
        flags = MAP_PRIVATE /*| MAP_DENYWRITE */ ;
        if (!piclib)
@@ -709,7 +710,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 
        dpnt = (ElfW(Dyn) *) dynamic_addr;
        _dl_memset(dynamic_info, 0, sizeof(dynamic_info));
-       _dl_parse_dynamic_info(dpnt, dynamic_info, NULL, lib_loadaddr);
+       rtld_flags = _dl_parse_dynamic_info(dpnt, dynamic_info, NULL, lib_loadaddr);
        /* If the TEXTREL is set, this means that we need to make the pages
           writable before we perform relocations.  Do this now. They get set
           back again later. */
@@ -741,13 +742,14 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
        tpnt->st_ino = st.st_ino;
        tpnt->ppnt = (ElfW(Phdr) *) DL_RELOC_ADDR(tpnt->loadaddr, epnt->e_phoff);
        tpnt->n_phent = epnt->e_phnum;
+       tpnt->rtld_flags |= rtld_flags;
 
 #if defined(USE_TLS) && USE_TLS
        if (tlsppnt) {
                _dl_debug_early("Found TLS header for %s\n", libname);
-#if NO_TLS_OFFSET != 0
+# if NO_TLS_OFFSET != 0
                tpnt->l_tls_offset = NO_TLS_OFFSET;
-#endif
+# endif
                tpnt->l_tls_blocksize = tlsppnt->p_memsz;
                tpnt->l_tls_align = tlsppnt->p_align;
                if (tlsppnt->p_align == 0)
@@ -764,10 +766,14 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
                /* We know the load address, so add it to the offset. */
                if (tpnt->l_tls_initimage != NULL)
                {
+# ifdef __SUPPORT_LD_DEBUG_EARLY__
                        unsigned int tmp = (unsigned int) tpnt->l_tls_initimage;
                        tpnt->l_tls_initimage = (char *) tlsppnt->p_vaddr + tpnt->loadaddr;
                        _dl_debug_early("Relocated TLS initial image from %x to %x (size = %x)\n", tmp, tpnt->l_tls_initimage, tpnt->l_tls_initimage_size);
                        tmp = 0;
+# else
+                       tpnt->l_tls_initimage = (char *) tlsppnt->p_vaddr + tpnt->loadaddr;
+# endif
                }
        }
 #endif
@@ -809,6 +815,54 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
                INIT_GOT(lpnt, tpnt);
        }
 
+#ifdef __DSBT__
+       /* Handle DSBT initialization */
+       {
+               struct elf_resolve *t, *ref = NULL;
+               int idx = tpnt->loadaddr.map->dsbt_index;
+               unsigned *dsbt = tpnt->loadaddr.map->dsbt_table;
+
+               if (idx == 0) {
+                       /* This DSO has not been assigned an index */
+                       _dl_dprintf(2, "%s: '%s' is missing a dsbt index assignment!\n",
+                                   _dl_progname, libname);
+                       _dl_exit(1);
+               }
+
+               /*
+                * Setup dsbt slot for this module in dsbt of all modules.
+                */
+               for (t = _dl_loaded_modules; t; t = t->next) {
+                       /* find a dsbt table from another module */
+                       if (ref == NULL && t != tpnt) {
+                               ref = t;
+
+                               /* make sure index is not already used */
+                               if (t->loadaddr.map->dsbt_table[idx]) {
+                                       struct elf_resolve *dup;
+                                       char *dup_name;
+
+                                       for (dup = _dl_loaded_modules; dup; dup = dup->next)
+                                               if (dup != tpnt && dup->loadaddr.map->dsbt_index == idx)
+                                                       break;
+                                       if (dup)
+                                               dup_name = dup->libname;
+                                       else if (idx == 1)
+                                               dup_name = "runtime linker";
+                                       else
+                                               dup_name = "unknown library";
+                                       _dl_dprintf(2, "%s: '%s' dsbt index %d already used by %s!\n",
+                                                   _dl_progname, libname, idx, dup_name);
+                                       _dl_exit(1);
+                               }
+                       }
+                       t->loadaddr.map->dsbt_table[idx] = (unsigned)dsbt;
+               }
+               if (ref)
+                       _dl_memcpy(dsbt, ref->loadaddr.map->dsbt_table,
+                                  tpnt->loadaddr.map->dsbt_size * sizeof(unsigned *));
+       }
+#endif
        _dl_if_debug_dprint("\n\tfile='%s';  generating link map\n", libname);
        _dl_if_debug_dprint("\t\tdynamic: %x  base: %x\n", dynamic_addr, DL_LOADADDR_BASE(lib_loadaddr));
        _dl_if_debug_dprint("\t\t  entry: %x  phdr: %x  phnum: %x\n\n",
@@ -1013,8 +1067,8 @@ char *_dl_strdup(const char *string)
        return retval;
 }
 
-void _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[],
-                            void *debug_addr, DL_LOADADDR_TYPE load_off)
+unsigned int _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[],
+                                    void *debug_addr, DL_LOADADDR_TYPE load_off)
 {
-       __dl_parse_dynamic_info(dpnt, dynamic_info, debug_addr, load_off);
+       return __dl_parse_dynamic_info(dpnt, dynamic_info, debug_addr, load_off);
 }