From 1047405bf7ec74170bed2a0da1002bc529b7e194 Mon Sep 17 00:00:00 2001 From: Tim Abbott Date: Tue, 7 Oct 2008 21:04:31 -0400 Subject: [PATCH] Add support for run-pre matching CONFIG_DYNAMIC_FTRACE kernels. Current gcc does not support compiling with both -ffunction-sections and -pg. Thus, this patch is only useful when using a compiler that has been patched to allow compiling with both -ffunction-sections and -pg enabled. Signed-off-by: Tim Abbott --- kmodsrc/Makefile.in | 3 ++- kmodsrc/x86/ksplice-arch.c | 31 +++++++++++++++++++++++++++++-- objmanip.c | 4 ++++ 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/kmodsrc/Makefile.in b/kmodsrc/Makefile.in index 9d26f31..46bb5e7 100644 --- a/kmodsrc/Makefile.in +++ b/kmodsrc/Makefile.in @@ -110,7 +110,8 @@ RMSYMS = \ __start___kcrctab_gpl \ __start___kcrctab_gpl_future \ __start___kcrctab_unused \ - __start___kcrctab_unused_gpl + __start___kcrctab_unused_gpl \ + ftrace_trace_function quiet_cmd_ksplice-rmsyms = RMSYMS $@ cmd_ksplice-rmsyms = \ diff --git a/kmodsrc/x86/ksplice-arch.c b/kmodsrc/x86/ksplice-arch.c index cd77d86..33c6a74 100644 --- a/kmodsrc/x86/ksplice-arch.c +++ b/kmodsrc/x86/ksplice-arch.c @@ -33,6 +33,12 @@ extern const char thread_return[]; #ifndef CONFIG_FUNCTION_DATA_SECTIONS #include "udis86.h" +#ifdef CONFIG_FTRACE +#include +#include + +extern ftrace_func_t ftrace_trace_function; +#endif /* CONFIG_FTRACE */ static abort_t compare_operands(struct ksplice_pack *pack, const struct ksplice_section *sect, @@ -49,6 +55,7 @@ static long ud_operand_lval(struct ud_operand *operand); static int next_run_byte(struct ud *ud); static bool is_nop(struct ud *ud); static bool is_unconditional_jump(struct ud *ud); +static bool is_mcount_call(struct ud *ud, unsigned long addr); void initialize_ksplice_ud(struct ud *ud) { @@ -108,7 +115,8 @@ static abort_t arch_run_pre_cmp(struct ksplice_pack *pack, safety_offset); goto out; } - if (is_nop(&pre_ud)) { + if (is_nop(&pre_ud) || + is_mcount_call(&pre_ud, (unsigned long)pre)) { if (mode == RUN_PRE_DEBUG) { ksdebug(pack, "| nop: "); print_bytes(pack, run, 0, pre, @@ -124,7 +132,8 @@ static abort_t arch_run_pre_cmp(struct ksplice_pack *pack, ret = NO_MATCH; goto out; } - if (!is_nop(&run_ud)) + if (!is_nop(&run_ud) && + !is_mcount_call(&run_ud, (unsigned long)run)) break; if (mode == RUN_PRE_DEBUG) { ksdebug(pack, "| nop: "); @@ -386,6 +395,24 @@ static abort_t compare_operands(struct ksplice_pack *pack, } } +#ifdef CONFIG_FTRACE +static bool is_mcount_call(struct ud *ud, unsigned long addr) +{ + unsigned long target = addr + ud_insn_len(ud) + + ud_operand_lval(&ud->operand[0]); + if (ud->mnemonic == UD_Icall && + (target == (unsigned long)mcount || + target == (unsigned long)ftrace_trace_function)) + return true; + return false; +} +#else /* !CONFIG_FTRACE */ +static bool is_mcount_call(struct ud *ud, unsigned long addr) +{ + return false; +} +#endif /* CONFIG_FTRACE */ + static bool is_nop(struct ud *ud) { switch (ud->mnemonic) { diff --git a/objmanip.c b/objmanip.c index 28985d5..829c65c 100644 --- a/objmanip.c +++ b/objmanip.c @@ -1067,6 +1067,10 @@ void rm_some_relocs(struct supersect *ss) if (mode("finalize") && bfd_is_und_section(sym_ptr->section)) rm_reloc = true; + if (strcmp(sym_ptr->name, "mcount") == 0 && + bfd_is_und_section(sym_ptr->section)) + rm_reloc = false; + if (rm_reloc) write_ksplice_reloc(ss, *relocp); else -- 2.11.4.GIT