diff options
-rw-r--r-- | arch/sh/reloc.h | 2 | ||||
-rw-r--r-- | src/internal/dynlink.h | 4 | ||||
-rw-r--r-- | src/ldso/dynlink.c | 19 |
3 files changed, 21 insertions, 4 deletions
diff --git a/arch/sh/reloc.h b/arch/sh/reloc.h index d4fe348c..0238ce07 100644 --- a/arch/sh/reloc.h +++ b/arch/sh/reloc.h @@ -32,6 +32,8 @@ #define REL_DTPOFF R_SH_TLS_DTPOFF32 #define REL_TPOFF R_SH_TLS_TPOFF32 +#define DL_NOMMU_SUPPORT 1 + #if __SH_FDPIC__ #define REL_FUNCDESC R_SH_FUNCDESC #define REL_FUNCDESC_VAL R_SH_FUNCDESC_VALUE diff --git a/src/internal/dynlink.h b/src/internal/dynlink.h index 86f379e6..9c494e43 100644 --- a/src/internal/dynlink.h +++ b/src/internal/dynlink.h @@ -64,6 +64,10 @@ struct fdpic_dummy_loadmap { #define DL_FDPIC 0 #endif +#ifndef DL_NOMMU_SUPPORT +#define DL_NOMMU_SUPPORT 0 +#endif + #if !DL_FDPIC #define IS_RELATIVE(x,s) ( \ (R_TYPE(x) == REL_RELATIVE) || \ diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c index a6484dd5..5fbe2bb5 100644 --- a/src/ldso/dynlink.c +++ b/src/ldso/dynlink.c @@ -482,8 +482,14 @@ static void reclaim_gaps(struct dso *dso) static void *mmap_fixed(void *p, size_t n, int prot, int flags, int fd, off_t off) { - char *q = mmap(p, n, prot, flags, fd, off); - if (q != MAP_FAILED || errno != EINVAL) return q; + static int no_map_fixed; + char *q; + if (!no_map_fixed) { + q = mmap(p, n, prot, flags|MAP_FIXED, fd, off); + if (!DL_NOMMU_SUPPORT || q != MAP_FAILED || errno != EINVAL) + return q; + no_map_fixed = 1; + } /* Fallbacks for MAP_FIXED failure on NOMMU kernels. */ if (flags & MAP_ANONYMOUS) { memset(p, 0, n); @@ -631,7 +637,11 @@ static void *map_library(int fd, struct dso *dso) * the length of the file. This is okay because we will not * use the invalid part; we just need to reserve the right * amount of virtual address space to map over later. */ - map = mmap((void *)addr_min, map_len, prot, MAP_PRIVATE, fd, off_start); + map = DL_NOMMU_SUPPORT + ? mmap((void *)addr_min, map_len, PROT_READ|PROT_WRITE|PROT_EXEC, + MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) + : mmap((void *)addr_min, map_len, prot, + MAP_PRIVATE, fd, off_start); if (map==MAP_FAILED) goto error; dso->map = map; dso->map_len = map_len; @@ -656,7 +666,8 @@ static void *map_library(int fd, struct dso *dso) dso->phentsize = eh->e_phentsize; } /* Reuse the existing mapping for the lowest-address LOAD */ - if ((ph->p_vaddr & -PAGE_SIZE) == addr_min) continue; + if ((ph->p_vaddr & -PAGE_SIZE) == addr_min && !DL_NOMMU_SUPPORT) + continue; this_min = ph->p_vaddr & -PAGE_SIZE; this_max = ph->p_vaddr+ph->p_memsz+PAGE_SIZE-1 & -PAGE_SIZE; off_start = ph->p_offset & -PAGE_SIZE; |