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