The fdpic support has been broken since the prelink support was added,
because it doesn't take into account DL_LOADADDR_TYPE could be a
type different of ElfW(Addr).

Signed-off-by: Filippo Arcidiacono <filippo.arcidiac...@st.com>
---
 ldso/include/dl-defs.h      |   11 +++++++++++
 ldso/ldso/c6x/dl-sysdep.h   |    9 +++++++++
 ldso/ldso/dl-elf.c          |   22 ++++++++++++++--------
 ldso/ldso/dl-startup.c      |    8 +++-----
 ldso/ldso/fdpic/dl-sysdep.h |   10 ++++++++++
 ldso/ldso/ldso.c            |   17 +++++++++++------
 6 files changed, 58 insertions(+), 19 deletions(-)

diff --git a/ldso/include/dl-defs.h b/ldso/include/dl-defs.h
index 11edc4d..a95fe01 100644
--- a/ldso/include/dl-defs.h
+++ b/ldso/include/dl-defs.h
@@ -259,4 +259,15 @@ typedef struct {
 # define DL_MAP_SEGMENT(EPNT, PPNT, INFILE, FLAGS) 0
 #endif
 
+/* Define this to set the library offset  as difference beetwen the mapped
+   library address and the smallest virtual address of the first PT_LOAD
+   segment. */
+#ifndef DL_SET_LIB_OFFSET
+# define DL_SET_LIB_OFFSET(offset) (_dl_library_offset = (offset))
+#endif
+
+/* Define this to get the real map address of the dynamic linker. */
+#ifndef DL_GET_LDSO_MAPADDR
+# define DL_GET_LDSO_MAPADDR(load_addr, ldso_mapaddr) (ldso_mapaddr)
+#endif
 #endif /* _LD_DEFS_H */
diff --git a/ldso/ldso/c6x/dl-sysdep.h b/ldso/ldso/c6x/dl-sysdep.h
index ff7accd..95efabc 100644
--- a/ldso/ldso/c6x/dl-sysdep.h
+++ b/ldso/ldso/c6x/dl-sysdep.h
@@ -166,6 +166,15 @@ while (0)
 #define DL_BOOT_COMPUTE_DYN(dpnt, got, load_addr) \
   ((dpnt) = dl_boot_ldso_dyn_pointer)
 
+/* Define this to set the library offset. */
+#ifndef DL_SET_LIB_OFFSET
+# define DL_SET_LIB_OFFSET(offset) (_dl_library_offset = 0)
+#endif
+
+/* Define this to get the real map address of the dynamic linker. */
+#ifndef DL_GET_LDSO_MAPADDR
+# define DL_GET_LDSO_MAPADDR(load_addr, ldso_mapaddr) (load_addr)
+#endif
 
 #ifdef __USE_GNU
 # include <link.h>
diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c
index b9de199..6d7b7f8 100644
--- a/ldso/ldso/dl-elf.c
+++ b/ldso/ldso/dl-elf.c
@@ -315,6 +315,8 @@ goof:
        return NULL;
 }
 
+static unsigned long _dl_library_offset;
+
 /*
  * Make a writeable mapping of a segment, regardless of whether PF_W is
  * set or not.
@@ -357,7 +359,7 @@ map_writeable (int infile, ElfW(Phdr) *ppnt, int piclib, 
int flags,
        }
 
        tryaddr = piclib == 2 ? piclib2map
-               : ((char*) (piclib ? libaddr : 0) +
+               : ((char *) (piclib ? libaddr : _dl_library_offset) +
                   (ppnt->p_vaddr & PAGE_ALIGN));
 
        size = (ppnt->p_vaddr & ADDR_ALIGN) + ppnt->p_filesz;
@@ -459,7 +461,7 @@ struct elf_resolve *_dl_load_elf_shared_library(unsigned 
rflags,
        size_t relro_size = 0;
        struct stat st;
        uint32_t *p32;
-       DL_LOADADDR_TYPE lib_loadaddr = 0;
+       DL_LOADADDR_TYPE lib_loadaddr;
        DL_INIT_LOADADDR_EXTRA_DECLS
 
        libaddr = 0;
@@ -617,6 +619,8 @@ struct elf_resolve *_dl_load_elf_shared_library(unsigned 
rflags,
        ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff];
 
        DL_INIT_LOADADDR(lib_loadaddr, libaddr - minvma, ppnt, epnt->e_phnum);
+       /* Set _dl_library_offset to lib_loadaddr or 0. */
+       DL_SET_LIB_OFFSET(lib_loadaddr);
 
        for (i = 0; i < epnt->e_phnum; i++) {
                if (DL_IS_SPECIAL_SEGMENT (epnt, ppnt)) {
@@ -648,7 +652,7 @@ struct elf_resolve *_dl_load_elf_shared_library(unsigned 
rflags,
                        } else {
                                tryaddr = (piclib == 2 ? 0
                                           : (char *) (ppnt->p_vaddr & 
PAGE_ALIGN)
-                                          + (piclib ? libaddr : lib_loadaddr));
+                                          + (piclib ? libaddr : 
_dl_library_offset));
                                size = (ppnt->p_vaddr & ADDR_ALIGN) + 
ppnt->p_filesz;
                                status = (char *) _dl_mmap
                                           (tryaddr, size, 
LXFLAGS(ppnt->p_flags),
@@ -675,7 +679,11 @@ struct elf_resolve *_dl_load_elf_shared_library(unsigned 
rflags,
         * The dynamic_addr must be take into acount lib_loadaddr value, to note
         * it is zero when the SO has been mapped to the elf's physical addr
         */
-       if (lib_loadaddr) {
+#ifdef __LDSO_PRELINK_SUPPORT__
+       if (_dl_library_offset) {
+#else
+       if (piclib) {
+#endif
                dynamic_addr = (unsigned long) DL_RELOC_ADDR(lib_loadaddr, 
dynamic_addr);
        }
 
@@ -708,7 +716,7 @@ struct elf_resolve *_dl_load_elf_shared_library(unsigned 
rflags,
                for (i = 0; i < epnt->e_phnum; i++, ppnt++) {
                        if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W)) 
{
 #ifdef __ARCH_USE_MMU__
-                               _dl_mprotect((void *) ((piclib ? libaddr : 
lib_loadaddr) +
+                               _dl_mprotect((void *) ((piclib ? libaddr : 
_dl_library_offset) +
                                                        (ppnt->p_vaddr & 
PAGE_ALIGN)),
                                                (ppnt->p_vaddr & ADDR_ALIGN) + 
(unsigned long) ppnt->p_filesz,
                                                PROT_READ | PROT_WRITE | 
PROT_EXEC);
@@ -954,11 +962,9 @@ int _dl_fixup(struct dyn_elf *rpnt, struct r_scope_elem 
*scope, int now_flag)
                relative_count = tpnt->dynamic_info[DT_RELCONT_IDX];
                if (relative_count) { /* Optimize the XX_RELATIVE relocations 
if possible */
                        reloc_size -= relative_count * sizeof(ELF_RELOC);
-                       if (tpnt->loadaddr
 #ifdef __LDSO_PRELINK_SUPPORT__
-                               || (!tpnt->dynamic_info[DT_GNU_PRELINKED_IDX])
+                       if (tpnt->loadaddr || 
(!tpnt->dynamic_info[DT_GNU_PRELINKED_IDX]))
 #endif
-                               )
                                elf_machine_relative(tpnt->loadaddr, 
reloc_addr, relative_count);
                        reloc_addr += relative_count * sizeof(ELF_RELOC);
                }
diff --git a/ldso/ldso/dl-startup.c b/ldso/ldso/dl-startup.c
index 75ea564..d7b114c 100644
--- a/ldso/ldso/dl-startup.c
+++ b/ldso/ldso/dl-startup.c
@@ -203,7 +203,7 @@ DL_START(unsigned long args)
                _dl_exit(0);
        }
        SEND_EARLY_STDERR_DEBUG("ELF header=");
-       SEND_ADDRESS_STDERR_DEBUG(DL_LOADADDR_BASE(header), 1);
+       SEND_ADDRESS_STDERR_DEBUG(header, 1);
 
        /* Locate the global offset table.  Since this code must be PIC
         * we can take advantage of the magic offset register, if we
@@ -278,11 +278,9 @@ DL_START(unsigned long args)
 
                        if (!indx && relative_count) {
                                rel_size -= relative_count * sizeof(ELF_RELOC);
-                               if (load_addr
 #ifdef __LDSO_PRELINK_SUPPORT__
-                                       || 
!tpnt->dynamic_info[DT_GNU_PRELINKED_IDX]
+                               if (load_addr || 
!tpnt->dynamic_info[DT_GNU_PRELINKED_IDX])
 #endif
-                                       )
                                        elf_machine_relative(load_addr, 
rel_addr, relative_count);
                                rel_addr += relative_count * sizeof(ELF_RELOC);
                        }
@@ -347,7 +345,7 @@ DL_START(unsigned long args)
        __rtld_stack_end = (void *)(argv - 1);
 
        _dl_elf_main = (int (*)(int, char **, char **))
-                       _dl_get_ready_to_run(tpnt, (DL_LOADADDR_TYPE) header, 
auxvt, envp, argv
+                       _dl_get_ready_to_run(tpnt, load_addr, auxvt, envp, argv
                                             DL_GET_READY_TO_RUN_EXTRA_ARGS);
 
        /* Transfer control to the application.  */
diff --git a/ldso/ldso/fdpic/dl-sysdep.h b/ldso/ldso/fdpic/dl-sysdep.h
index 75d7951..f874722 100644
--- a/ldso/ldso/fdpic/dl-sysdep.h
+++ b/ldso/ldso/fdpic/dl-sysdep.h
@@ -115,6 +115,16 @@ struct funcdesc_ht;
 #define DL_GET_READY_TO_RUN_EXTRA_ARGS \
     , dl_boot_progmap, dl_boot_got_pointer
 
+/* Define this to set the library offset. */
+#ifndef DL_SET_LIB_OFFSET
+# define DL_SET_LIB_OFFSET(offset) (_dl_library_offset = 0)
+#endif
+
+/* Define this to get the real map address of the dynamic linker. */
+#ifndef DL_GET_LDSO_MAPADDR
+# define DL_GET_LDSO_MAPADDR(load_addr, ldso_mapaddr) (load_addr)
+#endif
+
 #ifdef __USE_GNU
 # include <link.h>
 #else
diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c
index 014bbf5..6e1bfc5 100644
--- a/ldso/ldso/ldso.c
+++ b/ldso/ldso/ldso.c
@@ -351,12 +351,14 @@ static void trace_objects(struct elf_resolve *tpnt, char 
*str_name)
 
 static struct elf_resolve * add_ldso(struct elf_resolve *tpnt,
                                                                         
DL_LOADADDR_TYPE load_addr,
+                                                                        
ElfW(Addr) ldso_mapaddr,
                                                                         
ElfW(auxv_t) auxvt[AT_EGID + 1],
                                                                         struct 
dyn_elf *rpnt)
 {
                ElfW(Ehdr) *epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val;
                ElfW(Phdr) *myppnt = (ElfW(Phdr) *)
-                                                               
DL_RELOC_ADDR(load_addr, epnt->e_phoff);
+                               DL_RELOC_ADDR(DL_GET_LDSO_MAPADDR(load_addr, 
ldso_mapaddr),
+                                                         epnt->e_phoff);
                int j;
                struct stat st;
 
@@ -364,7 +366,7 @@ static struct elf_resolve * add_ldso(struct elf_resolve 
*tpnt,
                                              tpnt->dynamic_info, (unsigned 
long)tpnt->dynamic_addr,
                                              0);
 
-               tpnt->mapaddr = load_addr;
+               tpnt->mapaddr = ldso_mapaddr;
                if (_dl_stat(tpnt->libname, &st) >= 0) {
                        tpnt->st_dev = st.st_dev;
                        tpnt->st_ino = st.st_ino;
@@ -411,7 +413,7 @@ void *_dl_get_ready_to_run(struct elf_resolve *tpnt, 
DL_LOADADDR_TYPE load_addr,
                          ElfW(auxv_t) auxvt[AT_EGID + 1], char **envp, char 
**argv
                          DL_GET_READY_TO_RUN_EXTRA_PARMS)
 {
-       ElfW(Addr) app_mapaddr = 0;
+       ElfW(Addr) app_mapaddr = 0, ldso_mapaddr = 0;
        ElfW(Phdr) *ppnt;
        ElfW(Dyn) *dpnt;
        char *lpntstr;
@@ -826,6 +828,7 @@ of this helper program; chances are you did not intend to 
run this program.\n\
        }
 #endif
 
+       ldso_mapaddr = (ElfW(Addr)) auxvt[AT_BASE].a_un.a_val;
        /*
         * OK, fix one more thing - set up debug_addr so it will point
         * to our chain.  Later we may need to fill in more fields, but this
@@ -833,7 +836,8 @@ of this helper program; chances are you did not intend to 
run this program.\n\
         */
        debug_addr->r_map = (struct link_map *) _dl_loaded_modules;
        debug_addr->r_version = 1;
-       debug_addr->r_ldbase = (ElfW(Addr)) DL_LOADADDR_BASE(load_addr);
+       debug_addr->r_ldbase = (ElfW(Addr))
+               DL_LOADADDR_BASE(DL_GET_LDSO_MAPADDR(load_addr, ldso_mapaddr));
        debug_addr->r_brk = (unsigned long) &_dl_debug_state;
        _dl_debug_addr = debug_addr;
 
@@ -1012,7 +1016,8 @@ of this helper program; chances are you did not intend to 
run this program.\n\
                                if (_dl_strcmp(name, UCLIBC_LDSO) == 0) {
                                                if (!ldso_tpnt) {
                                                        /* Insert the ld.so 
only once */
-                                                       ldso_tpnt = 
add_ldso(tpnt, load_addr, auxvt, rpnt);
+                                                       ldso_tpnt = 
add_ldso(tpnt, load_addr,
+                                                                               
                 ldso_mapaddr, auxvt, rpnt);
                                                }
                                                ldso_tpnt->usage_count++;
                                                tpnt1 = ldso_tpnt;
@@ -1112,7 +1117,7 @@ of this helper program; chances are you did not intend to 
run this program.\n\
         * again once all libs are loaded.
         */
        if (!ldso_tpnt) {
-               tpnt = add_ldso(tpnt, load_addr, auxvt, rpnt);
+               tpnt = add_ldso(tpnt, load_addr, ldso_mapaddr, auxvt, rpnt);
                tpnt->usage_count++;
                nscope_elem++;
        } else
-- 
1.5.5.6

_______________________________________________
uClibc mailing list
uClibc@uclibc.org
http://lists.busybox.net/mailman/listinfo/uclibc

Reply via email to