From: Steven Rostedt <rostedt@goodmis.org>
To: linux-kernel@vger.kernel.org
Cc: Ingo Molnar <mingo@kernel.org>,
Andrew Morton <akpm@linux-foundation.org>
Subject: [for-next][PATCH 07/33] ftrace: Add ftrace_find_direct_func()
Date: Thu, 14 Nov 2019 13:17:41 -0500 [thread overview]
Message-ID: <20191114181824.438767916@goodmis.org> (raw)
In-Reply-To: 20191114181734.067922168@goodmis.org
From: "Steven Rostedt (VMware)" <rostedt@goodmis.org>
As function_graph tracer modifies the return address to insert a trampoline
to trace the return of a function, it must be aware of a direct caller, as
when it gets called, the function's return address may not be at on the
stack where it expects. It may have to see if that return address points to
the a direct caller and adjust if it is.
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
---
include/linux/ftrace.h | 6 ++++
kernel/trace/ftrace.c | 79 +++++++++++++++++++++++++++++++++++++++++-
2 files changed, 84 insertions(+), 1 deletion(-)
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index efe3e521aff4..8b37b8105398 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -51,6 +51,7 @@ static inline void early_trace_init(void) { }
struct module;
struct ftrace_hash;
+struct ftrace_direct_func;
#if defined(CONFIG_FUNCTION_TRACER) && defined(CONFIG_MODULES) && \
defined(CONFIG_DYNAMIC_FTRACE)
@@ -248,6 +249,7 @@ static inline void ftrace_free_mem(struct module *mod, void *start, void *end) {
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
int register_ftrace_direct(unsigned long ip, unsigned long addr);
int unregister_ftrace_direct(unsigned long ip, unsigned long addr);
+struct ftrace_direct_func *ftrace_find_direct_func(unsigned long addr);
#else
static inline int register_ftrace_direct(unsigned long ip, unsigned long addr)
{
@@ -257,6 +259,10 @@ static inline int unregister_ftrace_direct(unsigned long ip, unsigned long addr)
{
return -ENODEV;
}
+static inline struct ftrace_direct_func *ftrace_find_direct_func(unsigned long addr)
+{
+ return NULL;
+}
#endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */
#ifndef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 329a3f3789a1..c4446eabacbe 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -4938,6 +4938,46 @@ ftrace_set_addr(struct ftrace_ops *ops, unsigned long ip, int remove,
}
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
+
+struct ftrace_direct_func {
+ struct list_head next;
+ unsigned long addr;
+ int count;
+};
+
+static LIST_HEAD(ftrace_direct_funcs);
+
+/**
+ * ftrace_find_direct_func - test an address if it is a registered direct caller
+ * @addr: The address of a registered direct caller
+ *
+ * This searches to see if a ftrace direct caller has been registered
+ * at a specific address, and if so, it returns a descriptor for it.
+ *
+ * This can be used by architecture code to see if an address is
+ * a direct caller (trampoline) attached to a fentry/mcount location.
+ * This is useful for the function_graph tracer, as it may need to
+ * do adjustments if it traced a location that also has a direct
+ * trampoline attached to it.
+ */
+struct ftrace_direct_func *ftrace_find_direct_func(unsigned long addr)
+{
+ struct ftrace_direct_func *entry;
+ bool found = false;
+
+ /* May be called by fgraph trampoline (protected by rcu tasks) */
+ list_for_each_entry_rcu(entry, &ftrace_direct_funcs, next) {
+ if (entry->addr == addr) {
+ found = true;
+ break;
+ }
+ }
+ if (found)
+ return entry;
+
+ return NULL;
+}
+
/**
* register_ftrace_direct - Call a custom trampoline directly
* @ip: The address of the nop at the beginning of a function
@@ -4957,6 +4997,7 @@ ftrace_set_addr(struct ftrace_ops *ops, unsigned long ip, int remove,
*/
int register_ftrace_direct(unsigned long ip, unsigned long addr)
{
+ struct ftrace_direct_func *direct;
struct ftrace_func_entry *entry;
struct ftrace_hash *free_hash = NULL;
struct dyn_ftrace *rec;
@@ -5005,6 +5046,18 @@ int register_ftrace_direct(unsigned long ip, unsigned long addr)
if (!entry)
goto out_unlock;
+ direct = ftrace_find_direct_func(addr);
+ if (!direct) {
+ direct = kmalloc(sizeof(*direct), GFP_KERNEL);
+ if (!direct) {
+ kfree(entry);
+ goto out_unlock;
+ }
+ direct->addr = addr;
+ direct->count = 0;
+ list_add_rcu(&direct->next, &ftrace_direct_funcs);
+ }
+
entry->ip = ip;
entry->direct = addr;
__add_hash_entry(direct_functions, entry);
@@ -5019,8 +5072,20 @@ int register_ftrace_direct(unsigned long ip, unsigned long addr)
ftrace_set_filter_ip(&direct_ops, ip, 1, 0);
}
- if (ret)
+ if (ret) {
kfree(entry);
+ if (!direct->count) {
+ list_del_rcu(&direct->next);
+ synchronize_rcu_tasks();
+ kfree(direct);
+ if (free_hash)
+ free_ftrace_hash(free_hash);
+ free_hash = NULL;
+ }
+ } else {
+ if (!direct->count)
+ direct->count++;
+ }
out_unlock:
mutex_unlock(&direct_mutex);
@@ -5036,6 +5101,7 @@ EXPORT_SYMBOL_GPL(register_ftrace_direct);
int unregister_ftrace_direct(unsigned long ip, unsigned long addr)
{
struct ftrace_func_entry *entry;
+ struct ftrace_direct_func *direct;
struct dyn_ftrace *rec;
int ret = -ENODEV;
@@ -5066,6 +5132,17 @@ int unregister_ftrace_direct(unsigned long ip, unsigned long addr)
remove_hash_entry(direct_functions, entry);
+ direct = ftrace_find_direct_func(addr);
+ if (!WARN_ON(!direct)) {
+ /* This is the good path (see the ! before WARN) */
+ direct->count--;
+ WARN_ON(direct->count < 0);
+ if (!direct->count) {
+ list_del_rcu(&direct->next);
+ synchronize_rcu_tasks();
+ kfree(direct);
+ }
+ }
out_unlock:
mutex_unlock(&direct_mutex);
--
2.23.0
next prev parent reply other threads:[~2019-11-14 18:20 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-11-14 18:17 [for-next][PATCH 00/33] tracing: Updates for 5.5 Steven Rostedt
2019-11-14 18:17 ` [for-next][PATCH 01/33] ftrace: Introduce PERMANENT ftrace_ops flag Steven Rostedt
2019-11-14 18:17 ` [for-next][PATCH 02/33] selftests/livepatch: Make dynamic debug setup and restore generic Steven Rostedt
2019-11-14 18:17 ` [for-next][PATCH 03/33] selftests/livepatch: Test interaction with ftrace_enabled Steven Rostedt
2019-11-14 18:17 ` [for-next][PATCH 04/33] ftrace: Separate out the copying of a ftrace_hash from __ftrace_hash_move() Steven Rostedt
2019-11-14 18:17 ` [for-next][PATCH 05/33] ftrace: Separate out functionality from ftrace_location_range() Steven Rostedt
2019-11-14 18:17 ` [for-next][PATCH 06/33] ftrace: Add register_ftrace_direct() Steven Rostedt
2019-11-14 18:17 ` Steven Rostedt [this message]
2019-11-14 18:17 ` [for-next][PATCH 08/33] ftrace: Add sample module that uses register_ftrace_direct() Steven Rostedt
2019-11-14 18:17 ` [for-next][PATCH 09/33] ftrace/selftest: Add tests to test register_ftrace_direct() Steven Rostedt
2019-11-14 18:17 ` [for-next][PATCH 10/33] ftrace: Add another example of register_ftrace_direct() use case Steven Rostedt
2019-11-14 18:17 ` [for-next][PATCH 11/33] ftrace/selftests: Update the direct call selftests to test two direct calls Steven Rostedt
2019-11-14 18:17 ` [for-next][PATCH 12/33] ftrace/x86: Add register_ftrace_direct() for custom trampolines Steven Rostedt
2019-11-14 18:17 ` [for-next][PATCH 13/33] ftrace/x86: Add a counter to test function_graph with direct Steven Rostedt
2019-11-14 18:17 ` [for-next][PATCH 14/33] ftrace/x86: Tell objtool to ignore nondeterministic ftrace stack layout Steven Rostedt
2019-11-14 18:17 ` [for-next][PATCH 15/33] ftrace: Add information on number of page groups allocated Steven Rostedt
2019-11-14 18:17 ` [for-next][PATCH 16/33] ftrace: Implement fs notification for tracing_max_latency Steven Rostedt
2019-11-14 18:17 ` [for-next][PATCH 17/33] preemptirq_delay_test: Add the burst feature and a sysfs trigger Steven Rostedt
2019-11-14 18:17 ` [for-next][PATCH 18/33] tracing: Use CONFIG_PREEMPTION Steven Rostedt
2019-11-14 18:17 ` [for-next][PATCH 19/33] tracing: Make internal ftrace events static Steven Rostedt
2019-11-14 18:17 ` [for-next][PATCH 20/33] tracing: Declare newly exported APIs in include/linux/trace.h Steven Rostedt
2019-11-14 18:17 ` [for-next][PATCH 21/33] tracing: Verify if trace array exists before destroying it Steven Rostedt
2019-11-14 18:17 ` [for-next][PATCH 22/33] tracing: Adding NULL checks for trace_array descriptor pointer Steven Rostedt
2019-11-14 18:17 ` [for-next][PATCH 23/33] fgraph: Fix function type mismatches of ftrace_graph_return using ftrace_stub Steven Rostedt
2019-11-14 18:17 ` [for-next][PATCH 24/33] tracing/selftests: Turn off timeout setting Steven Rostedt
2019-11-14 18:17 ` [for-next][PATCH 25/33] lib/sort: Move swap, cmp and cmp_r function types for wider use Steven Rostedt
2019-11-14 18:18 ` [for-next][PATCH 26/33] lib/bsearch: Use generic type for comparator function Steven Rostedt
2019-11-14 18:18 ` [for-next][PATCH 27/33] tracing: " Steven Rostedt
2019-11-14 18:18 ` [for-next][PATCH 28/33] tracing/hwlat: Fix a few trivial nits Steven Rostedt
2019-11-14 18:18 ` [for-next][PATCH 29/33] tracing: use kvcalloc for tgid_map array allocation Steven Rostedt
2019-11-14 18:18 ` [for-next][PATCH 30/33] tracing/kprobe: Check whether the non-suffixed symbol is notrace Steven Rostedt
2019-11-14 18:18 ` [for-next][PATCH 31/33] seq_buf: Add printing formatted hex dumps Steven Rostedt
2019-11-14 18:18 ` [for-next][PATCH 32/33] tracing: Use seq_buf_hex_dump() to dump buffers Steven Rostedt
2019-11-14 18:18 ` [for-next][PATCH 33/33] tracing: Remove stray tab in TRACE_EVAL_MAP_FILEs help text Steven Rostedt
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=20191114181824.438767916@goodmis.org \
--to=rostedt@goodmis.org \
--cc=akpm@linux-foundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@kernel.org \
/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: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox