From 250122baed29d90c643be8809d75274336b98fb0 Mon Sep 17 00:00:00 2001 From: "Naveen N. Rao" Date: Thu, 19 Apr 2018 12:34:07 +0530 Subject: powerpc64/module: Tighten detection of mcount call sites with -mprofile-kernel For R_PPC64_REL24 relocations, we suppress emitting instructions for TOC load/restore in the relocation stub if the relocation is for _mcount() call when using -mprofile-kernel ABI. To detect this, we check if the preceding instructions are per the standard set of instructions emitted by gcc: either the two instruction sequence of 'mflr r0; std r0,16(r1)', or the more optimized variant of a single 'mflr r0'. This is not sufficient since nothing prevents users from hand coding sequences involving a 'mflr r0' followed by a 'bl'. For removing the toc save instruction from the stub, we additionally check if the symbol is "_mcount". Add the same check here as well. Also rename is_early_mcount_callsite() to is_mprofile_mcount_callsite() since that is what is being checked. The use of "early" is misleading since there is nothing involving this function that qualifies as early. Fixes: 153086644fd1f ("powerpc/ftrace: Add support for -mprofile-kernel ftrace ABI") Signed-off-by: Naveen N. Rao Signed-off-by: Michael Ellerman --- arch/powerpc/kernel/module_64.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c index a2636c2..8413be3 100644 --- a/arch/powerpc/kernel/module_64.c +++ b/arch/powerpc/kernel/module_64.c @@ -463,8 +463,11 @@ static unsigned long stub_for_addr(const Elf64_Shdr *sechdrs, } #ifdef CC_USING_MPROFILE_KERNEL -static bool is_early_mcount_callsite(u32 *instruction) +static bool is_mprofile_mcount_callsite(const char *name, u32 *instruction) { + if (strcmp("_mcount", name)) + return false; + /* * Check if this is one of the -mprofile-kernel sequences. */ @@ -496,8 +499,7 @@ static void squash_toc_save_inst(const char *name, unsigned long addr) #else static void squash_toc_save_inst(const char *name, unsigned long addr) { } -/* without -mprofile-kernel, mcount calls are never early */ -static bool is_early_mcount_callsite(u32 *instruction) +static bool is_mprofile_mcount_callsite(const char *name, u32 *instruction) { return false; } @@ -505,11 +507,11 @@ static bool is_early_mcount_callsite(u32 *instruction) /* We expect a noop next: if it is, replace it with instruction to restore r2. */ -static int restore_r2(u32 *instruction, struct module *me) +static int restore_r2(const char *name, u32 *instruction, struct module *me) { u32 *prev_insn = instruction - 1; - if (is_early_mcount_callsite(prev_insn)) + if (is_mprofile_mcount_callsite(name, prev_insn)) return 1; /* @@ -650,7 +652,8 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, value = stub_for_addr(sechdrs, value, me); if (!value) return -ENOENT; - if (!restore_r2((u32 *)location + 1, me)) + if (!restore_r2(strtab + sym->st_name, + (u32 *)location + 1, me)) return -ENOEXEC; squash_toc_save_inst(strtab + sym->st_name, value); -- cgit v1.1