linux-user/elfload: add FDPIC support
Signed-off-by: Mike Frysinger <vapier@gentoo.org> Signed-off-by: Riku Voipio <riku.voipio@nokia.com>
This commit is contained in:
parent
73160d9529
commit
1af02e83c0
19
elf.h
19
elf.h
@ -1191,6 +1191,25 @@ typedef struct elf64_note {
|
|||||||
Elf64_Word n_type; /* Content type */
|
Elf64_Word n_type; /* Content type */
|
||||||
} Elf64_Nhdr;
|
} Elf64_Nhdr;
|
||||||
|
|
||||||
|
|
||||||
|
/* This data structure represents a PT_LOAD segment. */
|
||||||
|
struct elf32_fdpic_loadseg {
|
||||||
|
/* Core address to which the segment is mapped. */
|
||||||
|
Elf32_Addr addr;
|
||||||
|
/* VMA recorded in the program header. */
|
||||||
|
Elf32_Addr p_vaddr;
|
||||||
|
/* Size of this segment in memory. */
|
||||||
|
Elf32_Word p_memsz;
|
||||||
|
};
|
||||||
|
struct elf32_fdpic_loadmap {
|
||||||
|
/* Protocol version number, must be zero. */
|
||||||
|
Elf32_Half version;
|
||||||
|
/* Number of segments in this map. */
|
||||||
|
Elf32_Half nsegs;
|
||||||
|
/* The actual memory map. */
|
||||||
|
struct elf32_fdpic_loadseg segs[/*nsegs*/];
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef ELF_CLASS
|
#ifdef ELF_CLASS
|
||||||
#if ELF_CLASS == ELFCLASS32
|
#if ELF_CLASS == ELFCLASS32
|
||||||
|
|
||||||
|
@ -1075,6 +1075,33 @@ static void zero_bss(abi_ulong elf_bss, abi_ulong last_bss, int prot)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_USE_FDPIC
|
||||||
|
static abi_ulong loader_build_fdpic_loadmap(struct image_info *info, abi_ulong sp)
|
||||||
|
{
|
||||||
|
uint16_t n;
|
||||||
|
struct elf32_fdpic_loadseg *loadsegs = info->loadsegs;
|
||||||
|
|
||||||
|
/* elf32_fdpic_loadseg */
|
||||||
|
n = info->nsegs;
|
||||||
|
while (n--) {
|
||||||
|
sp -= 12;
|
||||||
|
put_user_u32(loadsegs[n].addr, sp+0);
|
||||||
|
put_user_u32(loadsegs[n].p_vaddr, sp+4);
|
||||||
|
put_user_u32(loadsegs[n].p_memsz, sp+8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* elf32_fdpic_loadmap */
|
||||||
|
sp -= 4;
|
||||||
|
put_user_u16(0, sp+0); /* version */
|
||||||
|
put_user_u16(info->nsegs, sp+2); /* nsegs */
|
||||||
|
|
||||||
|
info->personality = PER_LINUX_FDPIC;
|
||||||
|
info->loadmap_addr = sp;
|
||||||
|
|
||||||
|
return sp;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
|
static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
|
||||||
struct elfhdr *exec,
|
struct elfhdr *exec,
|
||||||
struct image_info *info,
|
struct image_info *info,
|
||||||
@ -1087,6 +1114,21 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
|
|||||||
const int n = sizeof(elf_addr_t);
|
const int n = sizeof(elf_addr_t);
|
||||||
|
|
||||||
sp = p;
|
sp = p;
|
||||||
|
|
||||||
|
#ifdef CONFIG_USE_FDPIC
|
||||||
|
/* Needs to be before we load the env/argc/... */
|
||||||
|
if (elf_is_fdpic(exec)) {
|
||||||
|
/* Need 4 byte alignment for these structs */
|
||||||
|
sp &= ~3;
|
||||||
|
sp = loader_build_fdpic_loadmap(info, sp);
|
||||||
|
info->other_info = interp_info;
|
||||||
|
if (interp_info) {
|
||||||
|
interp_info->other_info = info;
|
||||||
|
sp = loader_build_fdpic_loadmap(interp_info, sp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
u_platform = 0;
|
u_platform = 0;
|
||||||
k_platform = ELF_PLATFORM;
|
k_platform = ELF_PLATFORM;
|
||||||
if (k_platform) {
|
if (k_platform) {
|
||||||
@ -1197,6 +1239,11 @@ static void load_elf_image(const char *image_name, int image_fd,
|
|||||||
}
|
}
|
||||||
bswap_phdr(phdr, ehdr->e_phnum);
|
bswap_phdr(phdr, ehdr->e_phnum);
|
||||||
|
|
||||||
|
#ifdef CONFIG_USE_FDPIC
|
||||||
|
info->nsegs = 0;
|
||||||
|
info->pt_dynamic_addr = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Find the maximum size of the image and allocate an appropriate
|
/* Find the maximum size of the image and allocate an appropriate
|
||||||
amount of memory to handle that. */
|
amount of memory to handle that. */
|
||||||
loaddr = -1, hiaddr = 0;
|
loaddr = -1, hiaddr = 0;
|
||||||
@ -1210,6 +1257,9 @@ static void load_elf_image(const char *image_name, int image_fd,
|
|||||||
if (a > hiaddr) {
|
if (a > hiaddr) {
|
||||||
hiaddr = a;
|
hiaddr = a;
|
||||||
}
|
}
|
||||||
|
#ifdef CONFIG_USE_FDPIC
|
||||||
|
++info->nsegs;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1290,6 +1340,27 @@ static void load_elf_image(const char *image_name, int image_fd,
|
|||||||
}
|
}
|
||||||
load_bias = load_addr - loaddr;
|
load_bias = load_addr - loaddr;
|
||||||
|
|
||||||
|
#ifdef CONFIG_USE_FDPIC
|
||||||
|
{
|
||||||
|
struct elf32_fdpic_loadseg *loadsegs = info->loadsegs =
|
||||||
|
qemu_malloc(sizeof(*loadsegs) * info->nsegs);
|
||||||
|
|
||||||
|
for (i = 0; i < ehdr->e_phnum; ++i) {
|
||||||
|
switch (phdr[i].p_type) {
|
||||||
|
case PT_DYNAMIC:
|
||||||
|
info->pt_dynamic_addr = phdr[i].p_vaddr + load_bias;
|
||||||
|
break;
|
||||||
|
case PT_LOAD:
|
||||||
|
loadsegs->addr = phdr[i].p_vaddr + load_bias;
|
||||||
|
loadsegs->p_vaddr = phdr[i].p_vaddr;
|
||||||
|
loadsegs->p_memsz = phdr[i].p_memsz;
|
||||||
|
++loadsegs;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
info->load_bias = load_bias;
|
info->load_bias = load_bias;
|
||||||
info->load_addr = load_addr;
|
info->load_addr = load_addr;
|
||||||
info->entry = ehdr->e_entry + load_bias;
|
info->entry = ehdr->e_entry + load_bias;
|
||||||
|
@ -51,6 +51,13 @@ struct image_info {
|
|||||||
abi_ulong arg_start;
|
abi_ulong arg_start;
|
||||||
abi_ulong arg_end;
|
abi_ulong arg_end;
|
||||||
int personality;
|
int personality;
|
||||||
|
#ifdef CONFIG_USE_FDPIC
|
||||||
|
abi_ulong loadmap_addr;
|
||||||
|
uint16_t nsegs;
|
||||||
|
void *loadsegs;
|
||||||
|
abi_ulong pt_dynamic_addr;
|
||||||
|
struct image_info *other_info;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef TARGET_I386
|
#ifdef TARGET_I386
|
||||||
|
Loading…
Reference in New Issue
Block a user