From: Zong Li <zong@andestech.com> To: <palmer@sifive.com>, <albert@sifive.com>, <linux-riscv@lists.infradead.org>, <linux-kernel@vger.kernel.org>, <zong@andestech.com>, <zongbox@gmail.com> Cc: <greentime@andestech.com> Subject: [PATCH 02/11] RISC-V: Add section of GOT.PLT for kernel module Date: Tue, 13 Mar 2018 16:35:07 +0800 [thread overview] Message-ID: <66eb534368782f411021e1a59f3292761d6576cd.1520928420.git.zong@andestech.com> (raw) In-Reply-To: <cover.1520928420.git.zong@andestech.com> Separate the function symbol address from .plt to .got.plt section. The original plt entry has trampoline code with symbol address, there is a 32-bit padding bwtween jar instruction and symbol address. Extract the symbol address to .got.plt to reduce the module size. Signed-off-by: Zong Li <zong@andestech.com> --- arch/riscv/include/asm/module.h | 40 +++++++++++++++++++++++-------------- arch/riscv/kernel/module-sections.c | 21 +++++++++++++++++-- arch/riscv/kernel/module.lds | 1 + 3 files changed, 45 insertions(+), 17 deletions(-) diff --git a/arch/riscv/include/asm/module.h b/arch/riscv/include/asm/module.h index bcc48d113deb..016e6a618e83 100644 --- a/arch/riscv/include/asm/module.h +++ b/arch/riscv/include/asm/module.h @@ -18,6 +18,7 @@ struct mod_section { struct mod_arch_specific { struct mod_section got; struct mod_section plt; + struct mod_section got_plt; }; #endif @@ -49,13 +50,10 @@ struct plt_entry { /* * Trampoline code to real target address. The return address * should be the original (pc+4) before entring plt entry. - * For 8 byte alignment of symbol_addr, - * don't pack structure to remove the padding. */ u32 insn_auipc; /* auipc t0, 0x0 */ u32 insn_ld; /* ld t1, 0x10(t0) */ u32 insn_jr; /* jr t1 */ - u64 symbol_addr; /* the real jump target address */ }; #define OPC_AUIPC 0x0017 @@ -63,9 +61,8 @@ struct plt_entry { #define OPC_JALR 0x0067 #define REG_T0 0x5 #define REG_T1 0x6 -#define IMM_OFFSET 0x10 -static inline struct plt_entry emit_plt_entry(u64 val) +static inline struct plt_entry emit_plt_entry(u64 val, u64 plt, u64 got_plt) { /* * U-Type encoding: @@ -79,24 +76,37 @@ static inline struct plt_entry emit_plt_entry(u64 val) * +------------+------------+--------+----------+----------+ * */ + u64 offset = got_plt - plt; + u32 hi20 = (offset + 0x800) & 0xfffff000; + u32 lo12 = (offset - hi20); return (struct plt_entry) { - OPC_AUIPC | (REG_T0 << 7), - OPC_LD | (IMM_OFFSET << 20) | (REG_T0 << 15) | (REG_T1 << 7), - OPC_JALR | (REG_T1 << 15), - val + OPC_AUIPC | (REG_T0 << 7) | hi20, + OPC_LD | (lo12 << 20) | (REG_T0 << 15) | (REG_T1 << 7), + OPC_JALR | (REG_T1 << 15) }; } -static inline struct plt_entry *get_plt_entry(u64 val, - const struct mod_section *sec) +static inline int get_got_plt_idx(u64 val, const struct mod_section *sec) { - struct plt_entry *plt = (struct plt_entry *)sec->shdr->sh_addr; + struct got_entry *got_plt = (struct got_entry *)sec->shdr->sh_addr; int i; for (i = 0; i < sec->num_entries; i++) { - if (plt[i].symbol_addr == val) - return &plt[i]; + if (got_plt[i].symbol_addr == val) + return i; } - return NULL; + return -1; +} + +static inline struct plt_entry *get_plt_entry(u64 val, + const struct mod_section *sec_plt, + const struct mod_section *sec_got_plt) +{ + struct plt_entry *plt = (struct plt_entry *)sec_plt->shdr->sh_addr; + int got_plt_idx = get_got_plt_idx(val, sec_got_plt); + if (got_plt_idx >= 0) + return plt + got_plt_idx; + else + return NULL; } #endif /* _ASM_RISCV_MODULE_H */ diff --git a/arch/riscv/kernel/module-sections.c b/arch/riscv/kernel/module-sections.c index 94ba1551eac3..bbbd26e19bfd 100644 --- a/arch/riscv/kernel/module-sections.c +++ b/arch/riscv/kernel/module-sections.c @@ -30,18 +30,23 @@ u64 module_emit_got_entry(struct module *mod, u64 val) u64 module_emit_plt_entry(struct module *mod, u64 val) { + struct mod_section *got_plt_sec = &mod->arch.got_plt; + struct got_entry *got_plt; struct mod_section *plt_sec = &mod->arch.plt; - struct plt_entry *plt = get_plt_entry(val, plt_sec); + struct plt_entry *plt = get_plt_entry(val, plt_sec, got_plt_sec); int i = plt_sec->num_entries; if (plt) return (u64)plt; /* There is no duplicate entry, create a new one */ + got_plt = (struct got_entry *)got_plt_sec->shdr->sh_addr; + got_plt[i] = emit_got_entry(val); plt = (struct plt_entry *)plt_sec->shdr->sh_addr; - plt[i] = emit_plt_entry(val); + plt[i] = emit_plt_entry(val, (u64)&plt[i], (u64)&got_plt[i]); plt_sec->num_entries++; + got_plt_sec->num_entries++; BUG_ON(plt_sec->num_entries > plt_sec->max_entries); return (u64)&plt[i]; @@ -94,6 +99,8 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, mod->arch.plt.shdr = sechdrs + i; else if (!strcmp(secstrings + sechdrs[i].sh_name, ".got")) mod->arch.got.shdr = sechdrs + i; + else if (!strcmp(secstrings + sechdrs[i].sh_name, ".got.plt")) + mod->arch.got_plt.shdr = sechdrs + i; } if (!mod->arch.plt.shdr) { @@ -104,6 +111,10 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, pr_err("%s: module GOT section(s) missing\n", mod->name); return -ENOEXEC; } + if (!mod->arch.got_plt.shdr) { + pr_err("%s: module GOT.PLT section(s) missing\n", mod->name); + return -ENOEXEC; + } /* Calculate the maxinum number of entries */ for (i = 0; i < ehdr->e_shnum; i++) { @@ -135,5 +146,11 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, mod->arch.got.num_entries = 0; mod->arch.got.max_entries = num_gots; + mod->arch.got_plt.shdr->sh_type = SHT_NOBITS; + mod->arch.got_plt.shdr->sh_flags = SHF_ALLOC; + mod->arch.got_plt.shdr->sh_addralign = L1_CACHE_BYTES; + mod->arch.got_plt.shdr->sh_size = (num_plts + 1) * sizeof(struct got_entry); + mod->arch.got_plt.num_entries = 0; + mod->arch.got_plt.max_entries = num_plts; return 0; } diff --git a/arch/riscv/kernel/module.lds b/arch/riscv/kernel/module.lds index 7ef580e62883..295ecfb341a2 100644 --- a/arch/riscv/kernel/module.lds +++ b/arch/riscv/kernel/module.lds @@ -4,4 +4,5 @@ SECTIONS { .plt (NOLOAD) : { BYTE(0) } .got (NOLOAD) : { BYTE(0) } + .got.plt (NOLOAD) : { BYTE(0) } } -- 2.16.1
WARNING: multiple messages have this Message-ID (diff)
From: zong@andestech.com (Zong Li) To: linux-riscv@lists.infradead.org Subject: [PATCH 02/11] RISC-V: Add section of GOT.PLT for kernel module Date: Tue, 13 Mar 2018 16:35:07 +0800 [thread overview] Message-ID: <66eb534368782f411021e1a59f3292761d6576cd.1520928420.git.zong@andestech.com> (raw) In-Reply-To: <cover.1520928420.git.zong@andestech.com> Separate the function symbol address from .plt to .got.plt section. The original plt entry has trampoline code with symbol address, there is a 32-bit padding bwtween jar instruction and symbol address. Extract the symbol address to .got.plt to reduce the module size. Signed-off-by: Zong Li <zong@andestech.com> --- arch/riscv/include/asm/module.h | 40 +++++++++++++++++++++++-------------- arch/riscv/kernel/module-sections.c | 21 +++++++++++++++++-- arch/riscv/kernel/module.lds | 1 + 3 files changed, 45 insertions(+), 17 deletions(-) diff --git a/arch/riscv/include/asm/module.h b/arch/riscv/include/asm/module.h index bcc48d113deb..016e6a618e83 100644 --- a/arch/riscv/include/asm/module.h +++ b/arch/riscv/include/asm/module.h @@ -18,6 +18,7 @@ struct mod_section { struct mod_arch_specific { struct mod_section got; struct mod_section plt; + struct mod_section got_plt; }; #endif @@ -49,13 +50,10 @@ struct plt_entry { /* * Trampoline code to real target address. The return address * should be the original (pc+4) before entring plt entry. - * For 8 byte alignment of symbol_addr, - * don't pack structure to remove the padding. */ u32 insn_auipc; /* auipc t0, 0x0 */ u32 insn_ld; /* ld t1, 0x10(t0) */ u32 insn_jr; /* jr t1 */ - u64 symbol_addr; /* the real jump target address */ }; #define OPC_AUIPC 0x0017 @@ -63,9 +61,8 @@ struct plt_entry { #define OPC_JALR 0x0067 #define REG_T0 0x5 #define REG_T1 0x6 -#define IMM_OFFSET 0x10 -static inline struct plt_entry emit_plt_entry(u64 val) +static inline struct plt_entry emit_plt_entry(u64 val, u64 plt, u64 got_plt) { /* * U-Type encoding: @@ -79,24 +76,37 @@ static inline struct plt_entry emit_plt_entry(u64 val) * +------------+------------+--------+----------+----------+ * */ + u64 offset = got_plt - plt; + u32 hi20 = (offset + 0x800) & 0xfffff000; + u32 lo12 = (offset - hi20); return (struct plt_entry) { - OPC_AUIPC | (REG_T0 << 7), - OPC_LD | (IMM_OFFSET << 20) | (REG_T0 << 15) | (REG_T1 << 7), - OPC_JALR | (REG_T1 << 15), - val + OPC_AUIPC | (REG_T0 << 7) | hi20, + OPC_LD | (lo12 << 20) | (REG_T0 << 15) | (REG_T1 << 7), + OPC_JALR | (REG_T1 << 15) }; } -static inline struct plt_entry *get_plt_entry(u64 val, - const struct mod_section *sec) +static inline int get_got_plt_idx(u64 val, const struct mod_section *sec) { - struct plt_entry *plt = (struct plt_entry *)sec->shdr->sh_addr; + struct got_entry *got_plt = (struct got_entry *)sec->shdr->sh_addr; int i; for (i = 0; i < sec->num_entries; i++) { - if (plt[i].symbol_addr == val) - return &plt[i]; + if (got_plt[i].symbol_addr == val) + return i; } - return NULL; + return -1; +} + +static inline struct plt_entry *get_plt_entry(u64 val, + const struct mod_section *sec_plt, + const struct mod_section *sec_got_plt) +{ + struct plt_entry *plt = (struct plt_entry *)sec_plt->shdr->sh_addr; + int got_plt_idx = get_got_plt_idx(val, sec_got_plt); + if (got_plt_idx >= 0) + return plt + got_plt_idx; + else + return NULL; } #endif /* _ASM_RISCV_MODULE_H */ diff --git a/arch/riscv/kernel/module-sections.c b/arch/riscv/kernel/module-sections.c index 94ba1551eac3..bbbd26e19bfd 100644 --- a/arch/riscv/kernel/module-sections.c +++ b/arch/riscv/kernel/module-sections.c @@ -30,18 +30,23 @@ u64 module_emit_got_entry(struct module *mod, u64 val) u64 module_emit_plt_entry(struct module *mod, u64 val) { + struct mod_section *got_plt_sec = &mod->arch.got_plt; + struct got_entry *got_plt; struct mod_section *plt_sec = &mod->arch.plt; - struct plt_entry *plt = get_plt_entry(val, plt_sec); + struct plt_entry *plt = get_plt_entry(val, plt_sec, got_plt_sec); int i = plt_sec->num_entries; if (plt) return (u64)plt; /* There is no duplicate entry, create a new one */ + got_plt = (struct got_entry *)got_plt_sec->shdr->sh_addr; + got_plt[i] = emit_got_entry(val); plt = (struct plt_entry *)plt_sec->shdr->sh_addr; - plt[i] = emit_plt_entry(val); + plt[i] = emit_plt_entry(val, (u64)&plt[i], (u64)&got_plt[i]); plt_sec->num_entries++; + got_plt_sec->num_entries++; BUG_ON(plt_sec->num_entries > plt_sec->max_entries); return (u64)&plt[i]; @@ -94,6 +99,8 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, mod->arch.plt.shdr = sechdrs + i; else if (!strcmp(secstrings + sechdrs[i].sh_name, ".got")) mod->arch.got.shdr = sechdrs + i; + else if (!strcmp(secstrings + sechdrs[i].sh_name, ".got.plt")) + mod->arch.got_plt.shdr = sechdrs + i; } if (!mod->arch.plt.shdr) { @@ -104,6 +111,10 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, pr_err("%s: module GOT section(s) missing\n", mod->name); return -ENOEXEC; } + if (!mod->arch.got_plt.shdr) { + pr_err("%s: module GOT.PLT section(s) missing\n", mod->name); + return -ENOEXEC; + } /* Calculate the maxinum number of entries */ for (i = 0; i < ehdr->e_shnum; i++) { @@ -135,5 +146,11 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, mod->arch.got.num_entries = 0; mod->arch.got.max_entries = num_gots; + mod->arch.got_plt.shdr->sh_type = SHT_NOBITS; + mod->arch.got_plt.shdr->sh_flags = SHF_ALLOC; + mod->arch.got_plt.shdr->sh_addralign = L1_CACHE_BYTES; + mod->arch.got_plt.shdr->sh_size = (num_plts + 1) * sizeof(struct got_entry); + mod->arch.got_plt.num_entries = 0; + mod->arch.got_plt.max_entries = num_plts; return 0; } diff --git a/arch/riscv/kernel/module.lds b/arch/riscv/kernel/module.lds index 7ef580e62883..295ecfb341a2 100644 --- a/arch/riscv/kernel/module.lds +++ b/arch/riscv/kernel/module.lds @@ -4,4 +4,5 @@ SECTIONS { .plt (NOLOAD) : { BYTE(0) } .got (NOLOAD) : { BYTE(0) } + .got.plt (NOLOAD) : { BYTE(0) } } -- 2.16.1
next prev parent reply other threads:[~2018-03-13 8:51 UTC|newest] Thread overview: 62+ messages / expand[flat|nested] mbox.gz Atom feed top 2018-03-13 8:35 [PATCH 00/11] RISC-V: Resolve the issue of loadable module on 64-bit Zong Li 2018-03-13 8:35 ` Zong Li 2018-03-13 8:35 ` [PATCH 01/11] RISC-V: Add sections of PLT and GOT for kernel module Zong Li 2018-03-13 8:35 ` Zong Li 2018-03-14 17:20 ` kbuild test robot 2018-03-14 17:20 ` kbuild test robot 2018-03-13 8:35 ` Zong Li [this message] 2018-03-13 8:35 ` [PATCH 02/11] RISC-V: Add section of GOT.PLT " Zong Li 2018-03-14 17:34 ` kbuild test robot 2018-03-14 17:34 ` kbuild test robot 2018-03-15 9:35 ` Zong Li 2018-03-15 9:35 ` Zong Li 2018-03-13 8:35 ` [PATCH 03/11] RISC-V: Support GOT_HI20/CALL_PLT relocation type in " Zong Li 2018-03-13 8:35 ` Zong Li 2018-03-13 8:35 ` [PATCH 04/11] RISC-V: Support CALL " Zong Li 2018-03-13 8:35 ` Zong Li 2018-03-13 8:35 ` [PATCH 05/11] RISC-V: Support HI20/LO12_I/LO12_S " Zong Li 2018-03-13 8:35 ` Zong Li 2018-03-13 8:35 ` [PATCH 06/11] RISC-V: Support RVC_BRANCH/JUMP relocation type in kernel modulewq Zong Li 2018-03-13 8:35 ` Zong Li 2018-03-13 8:35 ` [PATCH 07/11] RISC-V: Support ALIGN relocation type in kernel module Zong Li 2018-03-13 8:35 ` Zong Li 2018-03-13 8:35 ` [PATCH 08/11] RISC-V: Support ADD32 " Zong Li 2018-03-13 8:35 ` Zong Li 2018-03-13 8:35 ` [PATCH 09/11] RISC-V: Support SUB32 " Zong Li 2018-03-13 8:35 ` Zong Li 2018-03-13 8:35 ` [PATCH 10/11] RISC-V: Enable module support in defconfig Zong Li 2018-03-13 8:35 ` Zong Li 2018-03-13 8:35 ` [PATCH 11/11] RISC-V: Add definition of relocation types Zong Li 2018-03-13 8:35 ` Zong Li 2018-03-13 10:35 ` [PATCH 00/11] RISC-V: Resolve the issue of loadable module on 64-bit Zong Li 2018-03-13 10:35 ` Zong Li 2018-03-13 18:35 ` Palmer Dabbelt 2018-03-13 18:35 ` Palmer Dabbelt 2018-03-13 21:30 ` Shea Levy 2018-03-13 21:30 ` Shea Levy 2018-03-14 1:34 ` Zong Li 2018-03-14 1:34 ` Zong Li 2018-03-14 3:07 ` Palmer Dabbelt 2018-03-14 3:07 ` Palmer Dabbelt 2018-03-14 11:15 ` Zong Li 2018-03-14 11:15 ` Zong Li 2018-03-14 11:56 ` Shea Levy 2018-03-14 11:56 ` Shea Levy 2018-03-14 12:20 ` Zong Li 2018-03-14 12:20 ` Zong Li 2018-03-14 11:54 ` Shea Levy 2018-03-14 11:54 ` Shea Levy 2018-03-14 17:07 ` Palmer Dabbelt 2018-03-14 17:07 ` Palmer Dabbelt 2018-03-14 3:51 ` Palmer Dabbelt 2018-03-14 3:51 ` Palmer Dabbelt 2018-03-14 12:07 ` Shea Levy 2018-03-14 12:07 ` Shea Levy 2018-03-14 17:07 ` Palmer Dabbelt 2018-03-14 17:07 ` Palmer Dabbelt 2018-03-14 17:11 ` Shea Levy 2018-03-14 17:11 ` Shea Levy 2018-03-14 17:30 ` Palmer Dabbelt 2018-03-14 17:30 ` Palmer Dabbelt 2018-03-13 21:26 ` Shea Levy 2018-03-13 21:26 ` Shea Levy
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=66eb534368782f411021e1a59f3292761d6576cd.1520928420.git.zong@andestech.com \ --to=zong@andestech.com \ --cc=albert@sifive.com \ --cc=greentime@andestech.com \ --cc=linux-kernel@vger.kernel.org \ --cc=linux-riscv@lists.infradead.org \ --cc=palmer@sifive.com \ --cc=zongbox@gmail.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.