From patchwork Thu Mar 5 11:02:20 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Huth X-Patchwork-Id: 446677 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 15F441400EA for ; Thu, 5 Mar 2015 22:03:15 +1100 (AEDT) Received: from localhost ([::1]:50998 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YTTYf-0002QQ-2X for incoming@patchwork.ozlabs.org; Thu, 05 Mar 2015 06:03:13 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50701) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YTTY1-0001Dd-5t for qemu-devel@nongnu.org; Thu, 05 Mar 2015 06:02:39 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YTTXw-0005dD-3S for qemu-devel@nongnu.org; Thu, 05 Mar 2015 06:02:33 -0500 Received: from e06smtp12.uk.ibm.com ([195.75.94.108]:47385) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YTTXv-0005cZ-RM for qemu-devel@nongnu.org; Thu, 05 Mar 2015 06:02:28 -0500 Received: from /spool/local by e06smtp12.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Thu, 5 Mar 2015 11:02:26 -0000 Received: from d06dlp03.portsmouth.uk.ibm.com (9.149.20.15) by e06smtp12.uk.ibm.com (192.168.101.142) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Thu, 5 Mar 2015 11:02:25 -0000 Received: from b06cxnps3074.portsmouth.uk.ibm.com (d06relay09.portsmouth.uk.ibm.com [9.149.109.194]) by d06dlp03.portsmouth.uk.ibm.com (Postfix) with ESMTP id 058911B08067 for ; Thu, 5 Mar 2015 11:02:43 +0000 (GMT) Received: from d06av06.portsmouth.uk.ibm.com (d06av06.portsmouth.uk.ibm.com [9.149.37.217]) by b06cxnps3074.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id t25B2O9l11731258 for ; Thu, 5 Mar 2015 11:02:24 GMT Received: from d06av06.portsmouth.uk.ibm.com (localhost [127.0.0.1]) by d06av06.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id t255vbGi029884 for ; Thu, 5 Mar 2015 00:57:37 -0500 Received: from oc7435384737.ibm.com (sig-9-83-164-249.evts.uk.ibm.com [9.83.164.249]) by d06av06.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id t255vZQt029719; Thu, 5 Mar 2015 00:57:36 -0500 From: Thomas Huth To: qemu-devel@nongnu.org Date: Thu, 5 Mar 2015 12:02:20 +0100 Message-Id: <1425553341-566-2-git-send-email-thuth@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1425553341-566-1-git-send-email-thuth@linux.vnet.ibm.com> References: <1425553341-566-1-git-send-email-thuth@linux.vnet.ibm.com> X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 15030511-0009-0000-0000-000003591C82 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 195.75.94.108 Cc: agraf@suse.de, Thomas Huth Subject: [Qemu-devel] [PATCH RFC 1/2] elf-loader: Provide the possibility to relocate s390 ELF files X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org On s390, we would like to load our "BIOS" s390-ccw.img to the end of the RAM. Therefor we need the possibility to relocate the ELF file so that it can also run from different addresses. This patch adds the necessary code to the QEMU ELF loader function. Signed-off-by: Thomas Huth --- hw/core/loader.c | 2 + include/elf.h | 2 + include/hw/elf_ops.h | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 0 deletions(-) diff --git a/hw/core/loader.c b/hw/core/loader.c index e45dc0b..76d8aca 100644 --- a/hw/core/loader.c +++ b/hw/core/loader.c @@ -297,6 +297,7 @@ static void *load_at(int fd, int offset, int size) #undef elf_phdr #undef elf_shdr #undef elf_sym +#undef elf_rela #undef elf_note #undef elf_word #undef elf_sword @@ -307,6 +308,7 @@ static void *load_at(int fd, int offset, int size) #define elf_note elf64_note #define elf_shdr elf64_shdr #define elf_sym elf64_sym +#define elf_rela elf64_rela #define elf_word uint64_t #define elf_sword int64_t #define bswapSZs bswap64s diff --git a/include/elf.h b/include/elf.h index a516584..3e75f05 100644 --- a/include/elf.h +++ b/include/elf.h @@ -1508,6 +1508,7 @@ struct elf32_fdpic_loadmap { #define elf_shdr elf32_shdr #define elf_sym elf32_sym #define elf_addr_t Elf32_Off +#define elf_rela elf32_rela #ifdef ELF_USES_RELOCA # define ELF_RELOC Elf32_Rela @@ -1523,6 +1524,7 @@ struct elf32_fdpic_loadmap { #define elf_shdr elf64_shdr #define elf_sym elf64_sym #define elf_addr_t Elf64_Off +#define elf_rela elf64_rela #ifdef ELF_USES_RELOCA # define ELF_RELOC Elf64_Rela diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h index a517753..8bff1f7 100644 --- a/include/hw/elf_ops.h +++ b/include/hw/elf_ops.h @@ -182,6 +182,64 @@ static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab, return -1; } +static int glue(elf_reloc, SZ)(struct elfhdr *ehdr, int fd, int must_swab, + uint64_t (*translate_fn)(void *, uint64_t), + void *translate_opaque, uint8_t *data, + struct elf_phdr *ph, int elf_machine) +{ + struct elf_shdr *reltab, *shdr_table = NULL; + struct elf_rela *rels = NULL; + int nrels, i, ret = -1; + void *addr; + + shdr_table = load_at(fd, ehdr->e_shoff, + sizeof(struct elf_shdr) * ehdr->e_shnum); + if (!shdr_table) { + return -1; + } + if (must_swab) { + for (i = 0; i < ehdr->e_shnum; i++) { + glue(bswap_shdr, SZ)(shdr_table + i); + } + } + + reltab = glue(find_section, SZ)(shdr_table, ehdr->e_shnum, SHT_RELA); + if (!reltab) { + goto fail; + } + rels = load_at(fd, reltab->sh_offset, reltab->sh_size); + if (!rels) { + goto fail; + } + nrels = reltab->sh_size / sizeof(struct elf_rela); + + for (i = 0; i < nrels; i++) { + if (rels[i].r_offset < ph->p_vaddr || + rels[i].r_offset >= ph->p_vaddr + ph->p_filesz) { + continue; + } + addr = &data[rels[i].r_offset - ph->p_vaddr]; + switch (elf_machine) { + case EM_S390: + switch (rels[i].r_info) { + case R_390_RELATIVE: + *(elf_word *)addr = translate_fn(translate_opaque, + *(elf_word *)addr); + break; + default: + fprintf(stderr, "Unsupported relocation type %i!\n", + (int)rels[i].r_info); + } + } + } + + ret = 0; +fail: + g_free(rels); + g_free(shdr_table); + return ret; +} + static int glue(load_elf, SZ)(const char *name, int fd, uint64_t (*translate_fn)(void *, uint64_t), void *translate_opaque, @@ -271,6 +329,8 @@ static int glue(load_elf, SZ)(const char *name, int fd, linked at the wrong physical address. */ if (translate_fn) { addr = translate_fn(translate_opaque, ph->p_paddr); + glue(elf_reloc, SZ)(&ehdr, fd, must_swab, translate_fn, + translate_opaque, data, ph, elf_machine); } else { addr = ph->p_paddr; }