From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from [140.186.70.92] (port=53806 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PhMYn-0007A8-E5 for qemu-devel@nongnu.org; Mon, 24 Jan 2011 08:34:22 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PhMYl-000432-HJ for qemu-devel@nongnu.org; Mon, 24 Jan 2011 08:34:21 -0500 Received: from mail-wy0-f173.google.com ([74.125.82.173]:51840) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PhMYk-00042j-Up for qemu-devel@nongnu.org; Mon, 24 Jan 2011 08:34:19 -0500 Received: by wyg36 with SMTP id 36so4275986wyg.4 for ; Mon, 24 Jan 2011 05:34:18 -0800 (PST) Message-ID: <4D3D7FD4.3090008@gmail.com> Date: Mon, 24 Jan 2011 14:34:12 +0100 From: Stefano Bonifazi MIME-Version: 1.0 References: <1294562938-20097-1-git-send-email-vapier@gentoo.org> In-Reply-To: <1294562938-20097-1-git-send-email-vapier@gentoo.org> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Subject: [Qemu-devel] Re: [RFC/PATCH] elfload: add FDPIC support List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Mike Frysinger Cc: qemu-devel@nongnu.org On 01/09/2011 09:48 AM, Mike Frysinger wrote: > This is a PoC at this point, but it seems to be working for me. At > least, all the current crashes I'm seeing are due to my Blackfin port > being incomplete. All of the FDPIC table parsing seems to be OK ... > > If someone with a more functional target would like to try this, that'd > be cool. Or if people want to give feedback on how to approach this > problem so I can adjust the details now. > > Signed-off-by: Mike Frysinger > --- > elf.h | 19 ++++++++++++++ > linux-user/elfload.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++ > linux-user/qemu.h | 8 ++++++ > 3 files changed, 94 insertions(+), 0 deletions(-) > > diff --git a/elf.h b/elf.h > index 7067c90..d2f24f4 100644 > --- a/elf.h > +++ b/elf.h > @@ -1191,6 +1191,25 @@ typedef struct elf64_note { > Elf64_Word n_type; /* Content type */ > } 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 > #if ELF_CLASS == ELFCLASS32 > > diff --git a/linux-user/elfload.c b/linux-user/elfload.c > index 33d776d..8100ffd 100644 > --- a/linux-user/elfload.c > +++ b/linux-user/elfload.c > @@ -1075,6 +1075,32 @@ 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 */ > + for (n = 0; n< info->nsegs; ++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, > struct elfhdr *exec, > struct image_info *info, > @@ -1087,6 +1113,21 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc, > const int n = sizeof(elf_addr_t); > > 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; > k_platform = ELF_PLATFORM; > if (k_platform) { > @@ -1197,6 +1238,11 @@ static void load_elf_image(const char *image_name, int image_fd, > } > 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 > amount of memory to handle that. */ > loaddr = -1, hiaddr = 0; > @@ -1210,6 +1256,11 @@ static void load_elf_image(const char *image_name, int image_fd, > if (a> hiaddr) { > hiaddr = a; > } > +#ifdef CONFIG_USE_FDPIC > + ++info->nsegs; > + } else if (phdr[i].p_type == PT_DYNAMIC) { > + info->pt_dynamic_addr = phdr[i].p_vaddr; > +#endif > } > } > > @@ -1290,6 +1341,22 @@ static void load_elf_image(const char *image_name, int image_fd, > } > 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) { > + if (phdr[i].p_type != PT_LOAD) > + continue; > + loadsegs->addr = phdr[i].p_vaddr + load_bias; > + loadsegs->p_vaddr = phdr[i].p_vaddr; > + loadsegs->p_memsz = phdr[i].p_memsz; > + ++loadsegs; > + } > + } > +#endif > + > info->load_bias = load_bias; > info->load_addr = load_addr; > info->entry = ehdr->e_entry + load_bias; > diff --git a/linux-user/qemu.h b/linux-user/qemu.h > index 32de241..0924a1a 100644 > --- a/linux-user/qemu.h > +++ b/linux-user/qemu.h > @@ -51,6 +51,14 @@ struct image_info { > abi_ulong arg_start; > abi_ulong arg_end; > int personality; > +#ifdef CONFIG_USE_FDPIC > +#define FDPIC_MAX_LOAD_SEGS 4 > + abi_ulong loadmap_addr; > + uint16_t nsegs; > + void *loadsegs; > + abi_ulong pt_dynamic_addr; > + struct image_info *other_info; > +#endif > }; > > #ifdef TARGET_I386 Hi! Could you be so kind of explaining me, or addressing me to what this patch would do? Is FDPIC something different than simply PIC code (position independent code)? I am also trying to fight with the problem of changing the starting address of target code for qemu-user, and I was just moving into the option of using PIC target code .. but the original qemu-user load_elf_binary does not work on them.. and I was just about to try to edit it.. You would be more than a bless for me if you managed to do it! :) You may want to have a look at my post: http://lists.nongnu.org/archive/html/qemu-devel/2011-01/msg02361.html Thank you very much in advance! Stefano B