提交 eaf7ab6e 编写于 作者: R Rich Felker

add real fdpic loading of shared libraries

previously, the normal ELF library loading code was used even for
fdpic, so only the kernel-loaded dynamic linker and main app could
benefit from separate placement of segments and shared text.
上级 2462370b
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#define REL_FUNCDESC_VAL R_SH_FUNCDESC_VALUE #define REL_FUNCDESC_VAL R_SH_FUNCDESC_VALUE
#undef REL_RELATIVE #undef REL_RELATIVE
#define DL_FDPIC 1 #define DL_FDPIC 1
#define FDPIC_CONSTDISP_FLAG 0x100
#define CRTJMP(pc,sp) do { \ #define CRTJMP(pc,sp) do { \
register size_t r8 __asm__("r8") = ((size_t *)(sp))[-2]; \ register size_t r8 __asm__("r8") = ((size_t *)(sp))[-2]; \
__asm__ __volatile__( "jmp @%0 ; mov %1,r15" \ __asm__ __volatile__( "jmp @%0 ; mov %1,r15" \
......
...@@ -56,6 +56,10 @@ struct fdpic_dummy_loadmap { ...@@ -56,6 +56,10 @@ struct fdpic_dummy_loadmap {
#include "reloc.h" #include "reloc.h"
#ifndef FDPIC_CONSTDISP_FLAG
#define FDPIC_CONSTDISP_FLAG 0
#endif
#ifndef DL_FDPIC #ifndef DL_FDPIC
#define DL_FDPIC 0 #define DL_FDPIC 0
#endif #endif
......
...@@ -502,6 +502,22 @@ static void *mmap_fixed(void *p, size_t n, int prot, int flags, int fd, off_t of ...@@ -502,6 +502,22 @@ static void *mmap_fixed(void *p, size_t n, int prot, int flags, int fd, off_t of
return p; return p;
} }
static void unmap_library(struct dso *dso)
{
if (dso->loadmap) {
size_t i;
for (i=0; i<dso->loadmap->nsegs; i++) {
if (!dso->loadmap->segs[i].p_memsz)
continue;
munmap((void *)dso->loadmap->segs[i].addr,
dso->loadmap->segs[i].p_memsz);
}
free(dso->loadmap);
} else if (dso->map && dso->map_len) {
munmap(dso->map, dso->map_len);
}
}
static void *map_library(int fd, struct dso *dso) static void *map_library(int fd, struct dso *dso)
{ {
Ehdr buf[(896+sizeof(Ehdr))/sizeof(Ehdr)]; Ehdr buf[(896+sizeof(Ehdr))/sizeof(Ehdr)];
...@@ -509,6 +525,7 @@ static void *map_library(int fd, struct dso *dso) ...@@ -509,6 +525,7 @@ static void *map_library(int fd, struct dso *dso)
size_t phsize; size_t phsize;
size_t addr_min=SIZE_MAX, addr_max=0, map_len; size_t addr_min=SIZE_MAX, addr_max=0, map_len;
size_t this_min, this_max; size_t this_min, this_max;
size_t nsegs = 0;
off_t off_start; off_t off_start;
Ehdr *eh; Ehdr *eh;
Phdr *ph, *ph0; Phdr *ph, *ph0;
...@@ -552,6 +569,7 @@ static void *map_library(int fd, struct dso *dso) ...@@ -552,6 +569,7 @@ static void *map_library(int fd, struct dso *dso)
dso->relro_end = (ph->p_vaddr + ph->p_memsz) & -PAGE_SIZE; dso->relro_end = (ph->p_vaddr + ph->p_memsz) & -PAGE_SIZE;
} }
if (ph->p_type != PT_LOAD) continue; if (ph->p_type != PT_LOAD) continue;
nsegs++;
if (ph->p_vaddr < addr_min) { if (ph->p_vaddr < addr_min) {
addr_min = ph->p_vaddr; addr_min = ph->p_vaddr;
off_start = ph->p_offset; off_start = ph->p_offset;
...@@ -564,6 +582,33 @@ static void *map_library(int fd, struct dso *dso) ...@@ -564,6 +582,33 @@ static void *map_library(int fd, struct dso *dso)
} }
} }
if (!dyn) goto noexec; if (!dyn) goto noexec;
if (DL_FDPIC && !(eh->e_flags & FDPIC_CONSTDISP_FLAG)) {
dso->loadmap = calloc(1, sizeof *dso->loadmap
+ nsegs * sizeof *dso->loadmap->segs);
if (!dso->loadmap) goto error;
dso->loadmap->nsegs = nsegs;
for (ph=ph0, i=0; i<nsegs; ph=(void *)((char *)ph+eh->e_phentsize)) {
if (ph->p_type != PT_LOAD) continue;
prot = (((ph->p_flags&PF_R) ? PROT_READ : 0) |
((ph->p_flags&PF_W) ? PROT_WRITE: 0) |
((ph->p_flags&PF_X) ? PROT_EXEC : 0));
map = mmap(0, ph->p_memsz + (ph->p_vaddr & PAGE_SIZE-1),
prot, (prot&PROT_WRITE) ? MAP_PRIVATE : MAP_SHARED,
fd, ph->p_offset & -PAGE_SIZE);
if (map == MAP_FAILED) {
unmap_library(dso);
goto error;
}
dso->loadmap->segs[i].addr = (size_t)map +
(ph->p_vaddr & PAGE_SIZE-1);
dso->loadmap->segs[i].p_vaddr = ph->p_vaddr;
dso->loadmap->segs[i].p_memsz = ph->p_memsz;
i++;
}
map = (void *)dso->loadmap->segs[0].addr;
map_len = 0;
goto done_mapping;
}
addr_max += PAGE_SIZE-1; addr_max += PAGE_SIZE-1;
addr_max &= -PAGE_SIZE; addr_max &= -PAGE_SIZE;
addr_min &= -PAGE_SIZE; addr_min &= -PAGE_SIZE;
...@@ -575,6 +620,8 @@ static void *map_library(int fd, struct dso *dso) ...@@ -575,6 +620,8 @@ static void *map_library(int fd, struct dso *dso)
* amount of virtual address space to map over later. */ * amount of virtual address space to map over later. */
map = mmap((void *)addr_min, map_len, prot, MAP_PRIVATE, fd, off_start); map = mmap((void *)addr_min, map_len, prot, MAP_PRIVATE, fd, off_start);
if (map==MAP_FAILED) goto error; if (map==MAP_FAILED) goto error;
dso->map = map;
dso->map_len = map_len;
/* If the loaded file is not relocatable and the requested address is /* If the loaded file is not relocatable and the requested address is
* not available, then the load operation must fail. */ * not available, then the load operation must fail. */
if (eh->e_type != ET_DYN && addr_min && map!=(void *)addr_min) { if (eh->e_type != ET_DYN && addr_min && map!=(void *)addr_min) {
...@@ -620,18 +667,17 @@ static void *map_library(int fd, struct dso *dso) ...@@ -620,18 +667,17 @@ static void *map_library(int fd, struct dso *dso)
goto error; goto error;
break; break;
} }
dso->map = map; done_mapping:
dso->map_len = map_len;
dso->base = base; dso->base = base;
dso->dynv = (void *)(base+dyn); dso->dynv = laddr(dso, dyn);
if (dso->tls_size) dso->tls_image = (void *)(base+tls_image); if (dso->tls_size) dso->tls_image = laddr(dso, tls_image);
if (!runtime) reclaim_gaps(dso); if (!runtime) reclaim_gaps(dso);
free(allocated_buf); free(allocated_buf);
return map; return map;
noexec: noexec:
errno = ENOEXEC; errno = ENOEXEC;
error: error:
if (map!=MAP_FAILED) munmap(map, map_len); if (map!=MAP_FAILED) unmap_library(dso);
free(allocated_buf); free(allocated_buf);
return 0; return 0;
} }
...@@ -950,7 +996,7 @@ static struct dso *load_library(const char *name, struct dso *needed_by) ...@@ -950,7 +996,7 @@ static struct dso *load_library(const char *name, struct dso *needed_by)
} }
p = calloc(1, alloc_size); p = calloc(1, alloc_size);
if (!p) { if (!p) {
munmap(map, temp_dso.map_len); unmap_library(&temp_dso);
return 0; return 0;
} }
memcpy(p, &temp_dso, sizeof temp_dso); memcpy(p, &temp_dso, sizeof temp_dso);
...@@ -1620,17 +1666,16 @@ void *dlopen(const char *file, int mode) ...@@ -1620,17 +1666,16 @@ void *dlopen(const char *file, int mode)
p->deps[i]->global = 0; p->deps[i]->global = 0;
for (p=orig_tail->next; p; p=next) { for (p=orig_tail->next; p; p=next) {
next = p->next; next = p->next;
munmap(p->map, p->map_len);
while (p->td_index) { while (p->td_index) {
void *tmp = p->td_index->next; void *tmp = p->td_index->next;
free(p->td_index); free(p->td_index);
p->td_index = tmp; p->td_index = tmp;
} }
if (p->funcdescs) free(p->funcdescs);
free(p->funcdescs);
if (p->rpath != p->rpath_orig) if (p->rpath != p->rpath_orig)
free(p->rpath); free(p->rpath);
free(p->deps); free(p->deps);
unmap_library(p);
free(p); free(p);
} }
tls_cnt = orig_tls_cnt; tls_cnt = orig_tls_cnt;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册