mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-29 18:11:20 +00:00
tracing: Add function probe to trigger a ftrace dump to console
Add the "dump" command to have the ftrace buffer dumped to console if a function is hit. This is useful when debugging a tripple fault, where you have an idea of a function that is called just before the tripple fault occurs, and can tell ftrace to dump its content out to the console before it continues. Format is: <function>:dump echo 'bad_address:dump' > /debug/tracing/set_ftrace_filter To remove this: echo '!bad_address:dump' > /debug/tracing/set_ftrace_filter Requested-by: Luis Claudio R. Goncalves <lclaudio@uudg.org> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
This commit is contained in:
parent
317ddd256b
commit
ad71d889b8
2 changed files with 61 additions and 5 deletions
|
@ -2430,6 +2430,13 @@ The following commands are supported:
|
||||||
echo '!schedule:disable_event:sched:sched_switch' > \
|
echo '!schedule:disable_event:sched:sched_switch' > \
|
||||||
set_ftrace_filter
|
set_ftrace_filter
|
||||||
|
|
||||||
|
- dump
|
||||||
|
When the function is hit, it will dump the contents of the ftrace
|
||||||
|
ring buffer to the console. This is useful if you need to debug
|
||||||
|
something, and want to dump the trace when a certain function
|
||||||
|
is hit. Perhaps its a function that is called before a tripple
|
||||||
|
fault happens and does not allow you to get a regular dump.
|
||||||
|
|
||||||
trace_pipe
|
trace_pipe
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
|
|
@ -290,6 +290,13 @@ ftrace_stacktrace_count(unsigned long ip, unsigned long parent_ip, void **data)
|
||||||
trace_dump_stack(STACK_SKIP);
|
trace_dump_stack(STACK_SKIP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ftrace_dump_probe(unsigned long ip, unsigned long parent_ip, void **data)
|
||||||
|
{
|
||||||
|
if (update_count(data))
|
||||||
|
ftrace_dump(DUMP_ALL);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ftrace_probe_print(const char *name, struct seq_file *m,
|
ftrace_probe_print(const char *name, struct seq_file *m,
|
||||||
unsigned long ip, void *data)
|
unsigned long ip, void *data)
|
||||||
|
@ -327,6 +334,13 @@ ftrace_stacktrace_print(struct seq_file *m, unsigned long ip,
|
||||||
return ftrace_probe_print("stacktrace", m, ip, data);
|
return ftrace_probe_print("stacktrace", m, ip, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ftrace_dump_print(struct seq_file *m, unsigned long ip,
|
||||||
|
struct ftrace_probe_ops *ops, void *data)
|
||||||
|
{
|
||||||
|
return ftrace_probe_print("dump", m, ip, data);
|
||||||
|
}
|
||||||
|
|
||||||
static struct ftrace_probe_ops traceon_count_probe_ops = {
|
static struct ftrace_probe_ops traceon_count_probe_ops = {
|
||||||
.func = ftrace_traceon_count,
|
.func = ftrace_traceon_count,
|
||||||
.print = ftrace_traceon_print,
|
.print = ftrace_traceon_print,
|
||||||
|
@ -342,6 +356,11 @@ static struct ftrace_probe_ops stacktrace_count_probe_ops = {
|
||||||
.print = ftrace_stacktrace_print,
|
.print = ftrace_stacktrace_print,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct ftrace_probe_ops dump_probe_ops = {
|
||||||
|
.func = ftrace_dump_probe,
|
||||||
|
.print = ftrace_dump_print,
|
||||||
|
};
|
||||||
|
|
||||||
static struct ftrace_probe_ops traceon_probe_ops = {
|
static struct ftrace_probe_ops traceon_probe_ops = {
|
||||||
.func = ftrace_traceon,
|
.func = ftrace_traceon,
|
||||||
.print = ftrace_traceon_print,
|
.print = ftrace_traceon_print,
|
||||||
|
@ -425,6 +444,19 @@ ftrace_stacktrace_callback(struct ftrace_hash *hash,
|
||||||
param, enable);
|
param, enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ftrace_dump_callback(struct ftrace_hash *hash,
|
||||||
|
char *glob, char *cmd, char *param, int enable)
|
||||||
|
{
|
||||||
|
struct ftrace_probe_ops *ops;
|
||||||
|
|
||||||
|
ops = &dump_probe_ops;
|
||||||
|
|
||||||
|
/* Only dump once. */
|
||||||
|
return ftrace_trace_probe_callback(ops, hash, glob, cmd,
|
||||||
|
"1", enable);
|
||||||
|
}
|
||||||
|
|
||||||
static struct ftrace_func_command ftrace_traceon_cmd = {
|
static struct ftrace_func_command ftrace_traceon_cmd = {
|
||||||
.name = "traceon",
|
.name = "traceon",
|
||||||
.func = ftrace_trace_onoff_callback,
|
.func = ftrace_trace_onoff_callback,
|
||||||
|
@ -440,6 +472,11 @@ static struct ftrace_func_command ftrace_stacktrace_cmd = {
|
||||||
.func = ftrace_stacktrace_callback,
|
.func = ftrace_stacktrace_callback,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct ftrace_func_command ftrace_dump_cmd = {
|
||||||
|
.name = "dump",
|
||||||
|
.func = ftrace_dump_callback,
|
||||||
|
};
|
||||||
|
|
||||||
static int __init init_func_cmd_traceon(void)
|
static int __init init_func_cmd_traceon(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -450,13 +487,25 @@ static int __init init_func_cmd_traceon(void)
|
||||||
|
|
||||||
ret = register_ftrace_command(&ftrace_traceon_cmd);
|
ret = register_ftrace_command(&ftrace_traceon_cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
unregister_ftrace_command(&ftrace_traceoff_cmd);
|
goto out_free_traceoff;
|
||||||
|
|
||||||
ret = register_ftrace_command(&ftrace_stacktrace_cmd);
|
ret = register_ftrace_command(&ftrace_stacktrace_cmd);
|
||||||
if (ret) {
|
if (ret)
|
||||||
unregister_ftrace_command(&ftrace_traceoff_cmd);
|
goto out_free_traceon;
|
||||||
unregister_ftrace_command(&ftrace_traceon_cmd);
|
|
||||||
}
|
ret = register_ftrace_command(&ftrace_dump_cmd);
|
||||||
|
if (ret)
|
||||||
|
goto out_free_stacktrace;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
out_free_stacktrace:
|
||||||
|
unregister_ftrace_command(&ftrace_stacktrace_cmd);
|
||||||
|
out_free_traceon:
|
||||||
|
unregister_ftrace_command(&ftrace_traceon_cmd);
|
||||||
|
out_free_traceoff:
|
||||||
|
unregister_ftrace_command(&ftrace_traceoff_cmd);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue