Received: by 10.213.65.68 with SMTP id h4csp219073imn; Tue, 13 Mar 2018 01:53:06 -0700 (PDT) X-Google-Smtp-Source: AG47ELu3JV1G6c7H9jd0NiqfKel16Trv+UpiTjg4H8JR3yC8aDRImWmNkH3A8bIEXXUwsqBDLZY7 X-Received: by 10.99.64.66 with SMTP id n63mr9185764pga.204.1520931186677; Tue, 13 Mar 2018 01:53:06 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1520931186; cv=none; d=google.com; s=arc-20160816; b=QqGH3KBjhVVGAhUF4owkBiPMcwLJ0Aq9jqVRzbL6kpQFtLcuu+F3fkk86aCEyGEOlI UGjYG9ezje1HyIVJvhXWRPqJgIvQSGEemHomOd/xbb9+JLXq7d7QxxrQLaIdHYh14W1e WXWlBVQEANq13JsCXzP3qZ+0Dwnru1++jhewjmVGtny1V2O0MCIsL0GDVvhgT27V06Xt oEtEIEMsj8PUnWxzx17lETIdMotKYSUtdChdfR24OTbPBEGdYiidwgY7QnD/L6yFZylW 3vj+SQZ0dS8zECQleoSNFSH7yjGlSDU7+UsZXhg5Ic1Ld+P1JgMAFuWFqxBGDqhkEQyh urJA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:arc-authentication-results; bh=EwD6bYN4BQmwYdRApO7AYwQ3hNIbTymmKPysSkldhOg=; b=R5mMKpmH7fVpXuudy3FOXc2U6dY1MXWJW8QUt7tao9/aiI8mZs7qH08Sc1f2+92Z/d fYioMKFAxXtCbwpjQI/NNgg1TG/qeKuIxIFNmOfq4ERFHtLTRKSAwydicuYwKZ57Ho92 4DY6BJEcaPf7PxM92aG9ETVX8Gk85ZFPpqWe6cGtFusIV4OWAWFPONZFYhj5NZqcKkAM QB74+n7UpxaMkajcNXJl8uq2fo1H1P82lg8ULCDvFe+gwCE+9R5TtzAeHdRy03cRjCl5 eKCihe8WOpYOELH4gnexY1u3OdvGhUhaN62k6f8iuSTQDrFfop22a/JnU91Yjlrzbhqm EBBQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id p11si6289318pgd.392.2018.03.13.01.52.52; Tue, 13 Mar 2018 01:53:06 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932471AbeCMIs1 (ORCPT + 99 others); Tue, 13 Mar 2018 04:48:27 -0400 Received: from exmail.andestech.com ([59.124.169.137]:51850 "EHLO ATCSQR.andestech.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752022AbeCMIsY (ORCPT ); Tue, 13 Mar 2018 04:48:24 -0400 Received: from ATCSQR.andestech.com (localhost [127.0.0.2] (may be forged)) by ATCSQR.andestech.com with ESMTP id w2D8XTFa025115 for ; Tue, 13 Mar 2018 16:33:29 +0800 (GMT-8) (envelope-from zong@andestech.com) Received: from mail.andestech.com (atcpcs16.andestech.com [10.0.1.222]) by ATCSQR.andestech.com with ESMTP id w2D8XAxE025032; Tue, 13 Mar 2018 16:33:10 +0800 (GMT-8) (envelope-from zong@andestech.com) Received: from atcsqa06.andestech.com (10.0.1.85) by ATCPCS16.andestech.com (10.0.1.222) with Microsoft SMTP Server id 14.3.123.3; Tue, 13 Mar 2018 16:36:36 +0800 From: Zong Li To: , , , , , CC: Subject: [PATCH 03/11] RISC-V: Support GOT_HI20/CALL_PLT relocation type in kernel module Date: Tue, 13 Mar 2018 16:35:08 +0800 Message-ID: <51685b481586d18182aaa8753f56d524d8ad3ca9.1520928420.git.zong@andestech.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.0.1.85] X-DNSRBL: X-MAIL: ATCSQR.andestech.com w2D8XAxE025032 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org For CALL_PLT, emit the plt entry only when offset is more than 32-bit. For PCREL_LO12, it uses the location of corresponding HI20 to get the address of external symbol. It should check the HI20 type is the PCREL_HI20 or GOT_HI20, because sometime the location will have two or more relocation types. For example: 0: 00000797 auipc a5,0x0 0: R_RISCV_ALIGN *ABS* 0: R_RISCV_GOT_HI20 SYMBOL 4: 0007b783 ld a5,0(a5) # 0 4: R_RISCV_PCREL_LO12_I .L0 4: R_RISCV_RELAX *ABS* Signed-off-by: Zong Li --- arch/riscv/kernel/module.c | 61 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 10 deletions(-) diff --git a/arch/riscv/kernel/module.c b/arch/riscv/kernel/module.c index e0f05034fc21..242d3a14c210 100644 --- a/arch/riscv/kernel/module.c +++ b/arch/riscv/kernel/module.c @@ -92,6 +92,28 @@ static int apply_r_riscv_pcrel_lo12_s_rela(struct module *me, u32 *location, return 0; } +static int apply_r_riscv_got_hi20_rela(struct module *me, u32 *location, + Elf_Addr v) +{ + s64 offset = (void *)v - (void *)location; + s32 hi20; + + /* Always emit the got entry */ + if (IS_ENABLED(CONFIG_MODULE_SECTIONS)) { + offset = module_emit_got_entry(me, v); + offset = (void *)offset - (void *)location; + } else { + pr_err( + "%s: can not generate the GOT entry for symbol = %016llx from PC = %p\n", + me->name, v, location); + return -EINVAL; + } + + hi20 = (offset + 0x800) & 0xfffff000; + *location = (*location & 0xfff) | hi20; + return 0; +} + static int apply_r_riscv_call_plt_rela(struct module *me, u32 *location, Elf_Addr v) { @@ -100,10 +122,16 @@ static int apply_r_riscv_call_plt_rela(struct module *me, u32 *location, u32 hi20, lo12; if (offset != fill_v) { - pr_err( - "%s: target %016llx can not be addressed by the 32-bit offset from PC = %p\n", - me->name, v, location); - return -EINVAL; + /* Only emit the plt entry if offset over 32-bit range */ + if (IS_ENABLED(CONFIG_MODULE_SECTIONS)) { + offset = module_emit_plt_entry(me, v); + offset = (void *)offset - (void *)location; + } else { + pr_err( + "%s: target %016llx can not be addressed by the 32-bit offset from PC = %p\n", + me->name, v, location); + return -EINVAL; + } } hi20 = (offset + 0x800) & 0xfffff000; @@ -127,6 +155,7 @@ static int (*reloc_handlers_rela[]) (struct module *me, u32 *location, [R_RISCV_PCREL_HI20] = apply_r_riscv_pcrel_hi20_rela, [R_RISCV_PCREL_LO12_I] = apply_r_riscv_pcrel_lo12_i_rela, [R_RISCV_PCREL_LO12_S] = apply_r_riscv_pcrel_lo12_s_rela, + [R_RISCV_GOT_HI20] = apply_r_riscv_got_hi20_rela, [R_RISCV_CALL_PLT] = apply_r_riscv_call_plt_rela, [R_RISCV_RELAX] = apply_r_riscv_relax_rela, }; @@ -184,25 +213,37 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, u64 hi20_loc = sechdrs[sechdrs[relsec].sh_info].sh_addr + rel[j].r_offset; - /* Find the corresponding HI20 PC-relative relocation entry */ - if (hi20_loc == sym->st_value) { + u32 hi20_type = ELF_RISCV_R_TYPE(rel[j].r_info); + + /* Find the corresponding HI20 relocation entry */ + if (hi20_loc == sym->st_value + && (hi20_type == R_RISCV_PCREL_HI20 + || hi20_type == R_RISCV_GOT_HI20)) { + s32 hi20, lo12; Elf_Sym *hi20_sym = (Elf_Sym *)sechdrs[symindex].sh_addr + ELF_RISCV_R_SYM(rel[j].r_info); u64 hi20_sym_val = hi20_sym->st_value + rel[j].r_addend; + /* Calculate lo12 */ - s64 offset = hi20_sym_val - hi20_loc; - s32 hi20 = (offset + 0x800) & 0xfffff000; - s32 lo12 = offset - hi20; + u64 offset = hi20_sym_val - hi20_loc; + if (hi20_type == R_RISCV_GOT_HI20) { + offset = module_emit_got_entry( + me, hi20_sym_val); + offset = offset - hi20_loc; + } + hi20 = (offset + 0x800) & 0xfffff000; + lo12 = offset - hi20; v = lo12; + break; } } if (j == sechdrs[relsec].sh_size / sizeof(*rel)) { pr_err( - "%s: Can not find HI20 PC-relative relocation information\n", + "%s: Can not find HI20 relocation information\n", me->name); return -EINVAL; } -- 2.16.1