summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilippo Arcidiacono <filippo.arcidiacono@st.com>2012-04-06 11:18:35 +0200
committerMike Frysinger <vapier@gentoo.org>2012-04-08 00:49:16 -0400
commit2e9c1dc78eedd055b5db779aadf0d09cf70c6710 (patch)
tree00e4c18b83175da48847eb47820ac20b202ab3c5
parentdd109669be4b2f5ac69cf38ee1b67d6be74b620d (diff)
ldso: fix fdpic support broken from prelink patch
The fdpic support has been broken since the prelink support was added, because it didn't take into account DL_LOADADDR_TYPE could be a different type of ElfW(Addr). Signed-off-by: Filippo Arcidiacono <filippo.arcidiacono@st.com> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
-rw-r--r--ldso/include/dl-defs.h22
-rw-r--r--ldso/ldso/c6x/dl-sysdep.h11
-rw-r--r--ldso/ldso/dl-elf.c27
-rw-r--r--ldso/ldso/dl-startup.c9
-rw-r--r--ldso/ldso/fdpic/dl-sysdep.h12
-rw-r--r--ldso/ldso/ldso.c17
6 files changed, 78 insertions, 20 deletions
diff --git a/ldso/include/dl-defs.h b/ldso/include/dl-defs.h
index 11edc4dfc..f71ba9b48 100644
--- a/ldso/include/dl-defs.h
+++ b/ldso/include/dl-defs.h
@@ -259,4 +259,26 @@ typedef struct {
# define DL_MAP_SEGMENT(EPNT, PPNT, INFILE, FLAGS) 0
#endif
+/* Define this to declare the library offset. */
+#ifndef DL_DEF_LIB_OFFSET
+# define DL_DEF_LIB_OFFSET static unsigned long _dl_library_offset
+#endif
+
+/* Define this to get the library offset. */
+#ifndef DL_GET_LIB_OFFSET
+# define DL_GET_LIB_OFFSET() _dl_library_offset
+#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 object's runtime address. */
+#ifndef DL_GET_RUN_ADDR
+# define DL_GET_RUN_ADDR(loadaddr, mapaddr) (mapaddr)
+#endif
+
#endif /* _LD_DEFS_H */
diff --git a/ldso/ldso/c6x/dl-sysdep.h b/ldso/ldso/c6x/dl-sysdep.h
index ff7accdf1..0dbe8bf90 100644
--- a/ldso/ldso/c6x/dl-sysdep.h
+++ b/ldso/ldso/c6x/dl-sysdep.h
@@ -166,6 +166,17 @@ while (0)
#define DL_BOOT_COMPUTE_DYN(dpnt, got, load_addr) \
((dpnt) = dl_boot_ldso_dyn_pointer)
+/* Define this to declare the library offset. */
+#define DL_DEF_LIB_OFFSET
+
+/* Define this to get the library offset. */
+#define DL_GET_LIB_OFFSET() 0
+
+/* Define this to set the library offset. */
+#define DL_SET_LIB_OFFSET(offset)
+
+/* Define this to get the real object's runtime address. */
+#define DL_GET_RUN_ADDR(loadaddr, mapaddr) (loadaddr)
#ifdef __USE_GNU
# include <link.h>
diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c
index b9de19910..9e2a12ce7 100644
--- a/ldso/ldso/dl-elf.c
+++ b/ldso/ldso/dl-elf.c
@@ -315,6 +315,9 @@ goof:
return NULL;
}
+/* Define the _dl_library_offset for the architectures that need it */
+DL_DEF_LIB_OFFSET;
+
/*
* Make a writeable mapping of a segment, regardless of whether PF_W is
* set or not.
@@ -357,7 +360,7 @@ map_writeable (int infile, ElfW(Phdr) *ppnt, int piclib, int flags,
}
tryaddr = piclib == 2 ? piclib2map
- : ((char*) (piclib ? libaddr : 0) +
+ : ((char *) (piclib ? libaddr : DL_GET_LIB_OFFSET()) +
(ppnt->p_vaddr & PAGE_ALIGN));
size = (ppnt->p_vaddr & ADDR_ALIGN) + ppnt->p_filesz;
@@ -459,7 +462,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 +620,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 +653,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_GET_LIB_OFFSET()));
size = (ppnt->p_vaddr & ADDR_ALIGN) + ppnt->p_filesz;
status = (char *) _dl_mmap
(tryaddr, size, LXFLAGS(ppnt->p_flags),
@@ -675,7 +680,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_GET_LIB_OFFSET()) {
+#else
+ if (piclib) {
+#endif
dynamic_addr = (unsigned long) DL_RELOC_ADDR(lib_loadaddr, dynamic_addr);
}
@@ -708,7 +717,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_GET_LIB_OFFSET()) +
(ppnt->p_vaddr & PAGE_ALIGN)),
(ppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) ppnt->p_filesz,
PROT_READ | PROT_WRITE | PROT_EXEC);
@@ -746,7 +755,9 @@ struct elf_resolve *_dl_load_elf_shared_library(unsigned rflags,
tpnt->relro_size = relro_size;
tpnt->st_dev = st.st_dev;
tpnt->st_ino = st.st_ino;
- tpnt->ppnt = (ElfW(Phdr) *) DL_RELOC_ADDR(tpnt->mapaddr, epnt->e_phoff);
+ tpnt->ppnt = (ElfW(Phdr) *)
+ DL_RELOC_ADDR(DL_GET_RUN_ADDR(tpnt->loadaddr, tpnt->mapaddr),
+ epnt->e_phoff);
tpnt->n_phent = epnt->e_phnum;
tpnt->rtld_flags |= rtld_flags;
#ifdef __LDSO_STANDALONE_SUPPORT__
@@ -954,11 +965,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 75ea564c2..4893409e9 100644
--- a/ldso/ldso/dl-startup.c
+++ b/ldso/ldso/dl-startup.c
@@ -203,7 +203,8 @@ 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(
+ DL_LOADADDR_BASE(DL_GET_RUN_ADDR(load_addr, 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 +279,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 +346,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 75d7951ac..546811ad0 100644
--- a/ldso/ldso/fdpic/dl-sysdep.h
+++ b/ldso/ldso/fdpic/dl-sysdep.h
@@ -115,6 +115,18 @@ struct funcdesc_ht;
#define DL_GET_READY_TO_RUN_EXTRA_ARGS \
, dl_boot_progmap, dl_boot_got_pointer
+/* Define this to declare the library offset. */
+#define DL_DEF_LIB_OFFSET
+
+/* Define this to get the library offset. */
+#define DL_GET_LIB_OFFSET() 0
+
+/* Define this to set the library offset. */
+#define DL_SET_LIB_OFFSET(offset)
+
+/* Define this to get the real object's runtime address. */
+#define DL_GET_RUN_ADDR(loadaddr, mapaddr) (loadaddr)
+
#ifdef __USE_GNU
# include <link.h>
#else
diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c
index 014bbf5a9..85d27a3d1 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_RUN_ADDR(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_RUN_ADDR(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