From patchwork Tue Jun 21 19:48:37 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thiago Jung Bauermann X-Patchwork-Id: 638863 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3rYz5L2Jd8z9sBf for ; Wed, 22 Jun 2016 05:56:54 +1000 (AEST) Received: from ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3rYz5L1MvvzDr1f for ; Wed, 22 Jun 2016 05:56:54 +1000 (AEST) X-Original-To: linuxppc-dev@lists.ozlabs.org Delivered-To: linuxppc-dev@lists.ozlabs.org Received: from mx0a-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 3rYywV1KCBzDqlT for ; Wed, 22 Jun 2016 05:49:13 +1000 (AEST) Received: from pps.filterd (m0098414.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.11/8.16.0.11) with SMTP id u5LJmhYY068828 for ; Tue, 21 Jun 2016 15:49:11 -0400 Received: from e24smtp03.br.ibm.com (e24smtp03.br.ibm.com [32.104.18.24]) by mx0b-001b2d01.pphosted.com with ESMTP id 23n2em8m0q-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Tue, 21 Jun 2016 15:49:11 -0400 Received: from localhost by e24smtp03.br.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 21 Jun 2016 16:49:09 -0300 Received: from d24dlp02.br.ibm.com (9.18.248.206) by e24smtp03.br.ibm.com (10.172.0.139) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Tue, 21 Jun 2016 16:49:08 -0300 X-IBM-Helo: d24dlp02.br.ibm.com X-IBM-MailFrom: bauerman@linux.vnet.ibm.com X-IBM-RcptTo: linuxppc-dev@lists.ozlabs.org Received: from d24relay02.br.ibm.com (d24relay02.br.ibm.com [9.13.184.26]) by d24dlp02.br.ibm.com (Postfix) with ESMTP id 572491DC006F for ; Tue, 21 Jun 2016 15:49:00 -0400 (EDT) Received: from d24av05.br.ibm.com (d24av05.br.ibm.com [9.18.232.44]) by d24relay02.br.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id u5LJn7U026935802 for ; Tue, 21 Jun 2016 16:49:07 -0300 Received: from d24av05.br.ibm.com (localhost [127.0.0.1]) by d24av05.br.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id u5LJn6UC019898 for ; Tue, 21 Jun 2016 16:49:07 -0300 Received: from hactar.ibm.com ([9.78.146.1]) by d24av05.br.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id u5LJmoFm019392; Tue, 21 Jun 2016 16:49:04 -0300 From: Thiago Jung Bauermann To: linuxppc-dev@lists.ozlabs.org Subject: [PATCH v3 5/9] powerpc: Generalize elf64_apply_relocate_add. Date: Tue, 21 Jun 2016 16:48:37 -0300 X-Mailer: git-send-email 1.9.1 In-Reply-To: <1466538521-31216-1-git-send-email-bauerman@linux.vnet.ibm.com> References: <1466538521-31216-1-git-send-email-bauerman@linux.vnet.ibm.com> X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 16062119-0024-0000-0000-000000D87A37 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 16062119-0025-0000-0000-0000154F61D2 Message-Id: <1466538521-31216-6-git-send-email-bauerman@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2016-06-21_10:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=1 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1604210000 definitions=main-1606210220 X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Torsten Duwe , kexec@lists.infradead.org, linux-kernel@vger.kernel.org, Paul Mackerras , Thiago Jung Bauermann MIME-Version: 1.0 Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" When apply_relocate_add is called, modules are already loaded at their final location in memory so Elf64_Shdr.sh_addr can be used for accessing the section contents as well as the base address for relocations. This is not the case for kexec's purgatory, because it will only be copied to its final location right before being executed. Therefore, it needs to be relocated while it is still in a temporary buffer. In this case, Elf64_Shdr.sh_addr can't be used to access the sections' contents. This patch allows elf64_apply_relocate_add to be used when the ELF binary is not yet at its final location by adding an addr_base argument to specify the address at which the section will be loaded, and rela, loc_base and syms_base to point to the sections' contents. Signed-off-by: Thiago Jung Bauermann Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Cc: Torsten Duwe Cc: kexec@lists.infradead.org Cc: linux-kernel@vger.kernel.org --- arch/powerpc/include/asm/elf_util.h | 6 ++-- arch/powerpc/kernel/elf_util_64.c | 63 +++++++++++++++++++++++++------------ arch/powerpc/kernel/module_64.c | 17 ++++++++-- 3 files changed, 61 insertions(+), 25 deletions(-) diff --git a/arch/powerpc/include/asm/elf_util.h b/arch/powerpc/include/asm/elf_util.h index 37372559fe62..a012ba03282d 100644 --- a/arch/powerpc/include/asm/elf_util.h +++ b/arch/powerpc/include/asm/elf_util.h @@ -64,7 +64,9 @@ static inline unsigned long my_r2(const struct elf_info *elf_info) } int elf64_apply_relocate_add(const struct elf_info *elf_info, - const char *strtab, unsigned int symindex, - unsigned int relsec, const char *obj_name); + const char *strtab, const Elf64_Rela *rela, + unsigned int num_rela, void *syms_base, + void *loc_base, Elf64_Addr addr_base, + const char *obj_name); #endif /* _ASM_POWERPC_ELF_UTIL_H */ diff --git a/arch/powerpc/kernel/elf_util_64.c b/arch/powerpc/kernel/elf_util_64.c index decad2c34f38..8e5d400ac9f2 100644 --- a/arch/powerpc/kernel/elf_util_64.c +++ b/arch/powerpc/kernel/elf_util_64.c @@ -69,33 +69,56 @@ static void squash_toc_save_inst(const char *name, unsigned long addr) { } * elf64_apply_relocate_add - apply 64 bit RELA relocations * @elf_info: Support information for the ELF binary being relocated. * @strtab: String table for the associated symbol table. - * @symindex: Section header index for the associated symbol table. - * @relsec: Section header index for the relocations to apply. + * @rela: Contents of the section with the relocations to apply. + * @num_rela: Number of relocation entries in the section. + * @syms_base: Contents of the associated symbol table. + * @loc_base: Contents of the section to which relocations apply. + * @addr_base: The address where the section will be loaded in memory. * @obj_name: The name of the ELF binary, for information messages. + * + * Applies RELA relocations to an ELF file already at its final location + * in memory (in which case loc_base == addr_base), or still in a temporary + * buffer. */ int elf64_apply_relocate_add(const struct elf_info *elf_info, - const char *strtab, unsigned int symindex, - unsigned int relsec, const char *obj_name) + const char *strtab, const Elf64_Rela *rela, + unsigned int num_rela, void *syms_base, + void *loc_base, Elf64_Addr addr_base, + const char *obj_name) { unsigned int i; - Elf64_Shdr *sechdrs = elf_info->sechdrs; - Elf64_Rela *rela = (void *)sechdrs[relsec].sh_addr; - Elf64_Sym *sym; unsigned long *location; + unsigned long address; unsigned long value; + const char *name; + Elf64_Sym *sym; + + for (i = 0; i < num_rela; i++) { + /* + * rels[i].r_offset contains the byte offset from the beginning + * of section to the storage unit affected. + * + * This is the location to update in the temporary buffer where + * the section is currently loaded. The section will finally + * be loaded to a different address later, pointed to by + * addr_base. + */ + location = loc_base + rela[i].r_offset; + + /* Final address of the location. */ + address = addr_base + rela[i].r_offset; + /* This is the symbol the relocation is referring to. */ + sym = (Elf64_Sym *) syms_base + ELF64_R_SYM(rela[i].r_info); - for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) { - /* This is where to make the change */ - location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr - + rela[i].r_offset; - /* This is the symbol it is referring to */ - sym = (Elf64_Sym *)sechdrs[symindex].sh_addr - + ELF64_R_SYM(rela[i].r_info); + if (sym->st_name) + name = strtab + sym->st_name; + else + name = ""; pr_debug("RELOC at %p: %li-type as %s (0x%lx) + %li\n", location, (long)ELF64_R_TYPE(rela[i].r_info), - strtab + sym->st_name, (unsigned long)sym->st_value, + name, (unsigned long)sym->st_value, (long)rela[i].r_addend); /* `Everything is relative'. */ @@ -187,7 +210,7 @@ int elf64_apply_relocate_add(const struct elf_info *elf_info, value += local_entry_offset(sym); /* Convert value to relative */ - value -= (unsigned long)location; + value -= address; if (value + 0x2000000 > 0x3ffffff || (value & 3) != 0){ pr_err("%s: REL24 %li out of range!\n", obj_name, (long int)value); @@ -202,7 +225,7 @@ int elf64_apply_relocate_add(const struct elf_info *elf_info, case R_PPC64_REL64: /* 64 bits relative (used by features fixups) */ - *location = value - (unsigned long)location; + *location = value - address; break; case R_PPC64_TOCSAVE: @@ -218,7 +241,7 @@ int elf64_apply_relocate_add(const struct elf_info *elf_info, * Optimize ELFv2 large code model entry point if * the TOC is within 2GB range of current location. */ - value = my_r2(elf_info) - (unsigned long)location; + value = my_r2(elf_info) - address; if (value + 0x80008000 > 0xffffffff) break; /* @@ -242,7 +265,7 @@ int elf64_apply_relocate_add(const struct elf_info *elf_info, case R_PPC64_REL16_HA: /* Subtract location pointer */ - value -= (unsigned long)location; + value -= address; value = ((value + 0x8000) >> 16); *((uint16_t *) location) = (*((uint16_t *) location) & ~0xffff) @@ -251,7 +274,7 @@ int elf64_apply_relocate_add(const struct elf_info *elf_info, case R_PPC64_REL16_LO: /* Subtract location pointer */ - value -= (unsigned long)location; + value -= address; *((uint16_t *) location) = (*((uint16_t *) location) & ~0xffff) | (value & 0xffff); diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c index f2b25b4f9066..7f3b17bcac05 100644 --- a/arch/powerpc/kernel/module_64.c +++ b/arch/powerpc/kernel/module_64.c @@ -438,16 +438,26 @@ int restore_r2(u32 *instruction, const char *obj_name) return 1; } +/* + * When this function is called, the module is already at its final location in + * memory, so Elf64_Shdr.sh_addr can be used for accessing the section + * contents as well as the base address for relocations. + */ int apply_relocate_add(Elf64_Shdr *sechdrs, const char *strtab, unsigned int symindex, unsigned int relsec, struct module *me) { + Elf64_Shdr *rel_section = &sechdrs[relsec]; + void *syms_base = (void *) sechdrs[symindex].sh_addr; + Elf64_Addr addr_base = sechdrs[rel_section->sh_info].sh_addr; + const Elf64_Rela *rela = (const Elf64_Rela *) rel_section->sh_addr; + unsigned int num_rela = rel_section->sh_size / sizeof(Elf64_Rela); Elf64_Sym *sym; pr_debug("Applying ADD relocate section %u to %u\n", relsec, - sechdrs[relsec].sh_info); + rel_section->sh_info); /* First time we're called, we can fix up .TOC. */ if (!me->arch.toc_fixed) { @@ -459,8 +469,9 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, me->arch.toc_fixed = true; } - return elf64_apply_relocate_add(&me->arch.elf_info, strtab, symindex, - relsec, me->name); + return elf64_apply_relocate_add(&me->arch.elf_info, strtab, rela, + num_rela, syms_base, (void *) addr_base, + addr_base, me->name); } #ifdef CONFIG_DYNAMIC_FTRACE