#include <linux/stop_machine.h>
#include <linux/clocksource.h>
#include <linux/sched/task.h>
#include <linux/kallsyms.h>
#include <linux/security.h>
#include <linux/seq_file.h>
#include <linux/tracefs.h>
#include <linux/hardirq.h>
#include <linux/kthread.h>
#include <linux/uaccess.h>
#include <linux/bsearch.h>
#include <linux/module.h>
#include <linux/ftrace.h>
#include <linux/sysctl.h>
#include <linux/slab.h>
#include <linux/ctype.h>
#include <linux/sort.h>
#include <linux/list.h>
#include <linux/hash.h>
#include <linux/rcupdate.h>
#include <linux/kprobes.h>
#include <trace/events/sched.h>
#include <asm/sections.h>
#include <asm/setup.h>
#include "ftrace_internal.h"
#include "trace_output.h"
#include "trace_stat.h"
#define FTRACE_NOCLEAR_FLAGS …
#define FTRACE_INVALID_FUNCTION …
#define FTRACE_WARN_ON(cond) …
#define FTRACE_WARN_ON_ONCE(cond) …
#define FTRACE_HASH_DEFAULT_BITS …
#define FTRACE_HASH_MAX_BITS …
#ifdef CONFIG_DYNAMIC_FTRACE
#define INIT_OPS_HASH(opsname) …
#else
#define INIT_OPS_HASH …
#endif
enum { … };
struct ftrace_ops ftrace_list_end __read_mostly = …;
int ftrace_enabled __read_mostly;
static int __maybe_unused last_ftrace_enabled;
struct ftrace_ops *function_trace_op __read_mostly = …;
static struct ftrace_ops *set_function_trace_op;
bool ftrace_pids_enabled(struct ftrace_ops *ops)
{ … }
static void ftrace_update_trampoline(struct ftrace_ops *ops);
static int ftrace_disabled __read_mostly;
DEFINE_MUTEX(…) …;
struct ftrace_ops __rcu *ftrace_ops_list __read_mostly = …;
ftrace_func_t ftrace_trace_function __read_mostly = …;
struct ftrace_ops global_ops;
void ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,
struct ftrace_ops *op, struct ftrace_regs *fregs);
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS
const struct ftrace_ops ftrace_list_ops = {
.func = ftrace_ops_list_func,
.flags = FTRACE_OPS_FL_STUB,
};
static void ftrace_ops_nop_func(unsigned long ip, unsigned long parent_ip,
struct ftrace_ops *op,
struct ftrace_regs *fregs)
{
}
const struct ftrace_ops ftrace_nop_ops = {
.func = ftrace_ops_nop_func,
.flags = FTRACE_OPS_FL_STUB,
};
#endif
static inline void ftrace_ops_init(struct ftrace_ops *ops)
{ … }
static void ftrace_pid_func(unsigned long ip, unsigned long parent_ip,
struct ftrace_ops *op, struct ftrace_regs *fregs)
{ … }
static void ftrace_sync_ipi(void *data)
{ … }
static ftrace_func_t ftrace_ops_get_list_func(struct ftrace_ops *ops)
{ … }
static void update_ftrace_function(void)
{ … }
static void add_ftrace_ops(struct ftrace_ops __rcu **list,
struct ftrace_ops *ops)
{ … }
static int remove_ftrace_ops(struct ftrace_ops __rcu **list,
struct ftrace_ops *ops)
{ … }
static void ftrace_update_trampoline(struct ftrace_ops *ops);
int __register_ftrace_function(struct ftrace_ops *ops)
{ … }
int __unregister_ftrace_function(struct ftrace_ops *ops)
{ … }
static void ftrace_update_pid_func(void)
{ … }
#ifdef CONFIG_FUNCTION_PROFILER
struct ftrace_profile { … };
struct ftrace_profile_page { … };
struct ftrace_profile_stat { … };
#define PROFILE_RECORDS_SIZE …
#define PROFILES_PER_PAGE …
static int ftrace_profile_enabled __read_mostly;
static DEFINE_MUTEX(ftrace_profile_lock);
static DEFINE_PER_CPU(struct ftrace_profile_stat, ftrace_profile_stats);
#define FTRACE_PROFILE_HASH_BITS …
#define FTRACE_PROFILE_HASH_SIZE …
static void *
function_stat_next(void *v, int idx)
{ … }
static void *function_stat_start(struct tracer_stat *trace)
{ … }
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
static int function_stat_cmp(const void *p1, const void *p2)
{ … }
#else
static int function_stat_cmp(const void *p1, const void *p2)
{
const struct ftrace_profile *a = p1;
const struct ftrace_profile *b = p2;
if (a->counter < b->counter)
return -1;
if (a->counter > b->counter)
return 1;
else
return 0;
}
#endif
static int function_stat_headers(struct seq_file *m)
{ … }
static int function_stat_show(struct seq_file *m, void *v)
{ … }
static void ftrace_profile_reset(struct ftrace_profile_stat *stat)
{ … }
static int ftrace_profile_pages_init(struct ftrace_profile_stat *stat)
{ … }
static int ftrace_profile_init_cpu(int cpu)
{ … }
static int ftrace_profile_init(void)
{ … }
static struct ftrace_profile *
ftrace_find_profiled_func(struct ftrace_profile_stat *stat, unsigned long ip)
{ … }
static void ftrace_add_profile(struct ftrace_profile_stat *stat,
struct ftrace_profile *rec)
{ … }
static struct ftrace_profile *
ftrace_profile_alloc(struct ftrace_profile_stat *stat, unsigned long ip)
{ … }
static void
function_profile_call(unsigned long ip, unsigned long parent_ip,
struct ftrace_ops *ops, struct ftrace_regs *fregs)
{ … }
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
static bool fgraph_graph_time = …;
void ftrace_graph_graph_time_control(bool enable)
{ … }
static int profile_graph_entry(struct ftrace_graph_ent *trace,
struct fgraph_ops *gops)
{ … }
static void profile_graph_return(struct ftrace_graph_ret *trace,
struct fgraph_ops *gops)
{ … }
static struct fgraph_ops fprofiler_ops = …;
static int register_ftrace_profiler(void)
{ … }
static void unregister_ftrace_profiler(void)
{ … }
#else
static struct ftrace_ops ftrace_profile_ops __read_mostly = {
.func = function_profile_call,
.flags = FTRACE_OPS_FL_INITIALIZED,
INIT_OPS_HASH(ftrace_profile_ops)
};
static int register_ftrace_profiler(void)
{
return register_ftrace_function(&ftrace_profile_ops);
}
static void unregister_ftrace_profiler(void)
{
unregister_ftrace_function(&ftrace_profile_ops);
}
#endif
static ssize_t
ftrace_profile_write(struct file *filp, const char __user *ubuf,
size_t cnt, loff_t *ppos)
{ … }
static ssize_t
ftrace_profile_read(struct file *filp, char __user *ubuf,
size_t cnt, loff_t *ppos)
{ … }
static const struct file_operations ftrace_profile_fops = …;
static struct tracer_stat function_stats __initdata = …;
static __init void ftrace_profile_tracefs(struct dentry *d_tracer)
{ … }
#else
static __init void ftrace_profile_tracefs(struct dentry *d_tracer)
{
}
#endif
#ifdef CONFIG_DYNAMIC_FTRACE
static struct ftrace_ops *removed_ops;
static bool update_all_ops;
#ifndef CONFIG_FTRACE_MCOUNT_RECORD
# error Dynamic ftrace depends on MCOUNT_RECORD
#endif
struct ftrace_func_probe { … };
static const struct hlist_head empty_buckets[1];
static const struct ftrace_hash empty_hash = …;
#define EMPTY_HASH …
struct ftrace_ops global_ops = …;
struct ftrace_ops *ftrace_ops_trampoline(unsigned long addr)
{ … }
bool is_ftrace_trampoline(unsigned long addr)
{ … }
struct ftrace_page { … };
#define ENTRY_SIZE …
#define ENTRIES_PER_PAGE …
static struct ftrace_page *ftrace_pages_start;
static struct ftrace_page *ftrace_pages;
static __always_inline unsigned long
ftrace_hash_key(struct ftrace_hash *hash, unsigned long ip)
{ … }
static __always_inline struct ftrace_func_entry *
__ftrace_lookup_ip(struct ftrace_hash *hash, unsigned long ip)
{ … }
struct ftrace_func_entry *
ftrace_lookup_ip(struct ftrace_hash *hash, unsigned long ip)
{ … }
static void __add_hash_entry(struct ftrace_hash *hash,
struct ftrace_func_entry *entry)
{ … }
static struct ftrace_func_entry *
add_hash_entry(struct ftrace_hash *hash, unsigned long ip)
{ … }
static void
free_hash_entry(struct ftrace_hash *hash,
struct ftrace_func_entry *entry)
{ … }
static void
remove_hash_entry(struct ftrace_hash *hash,
struct ftrace_func_entry *entry)
{ … }
static void ftrace_hash_clear(struct ftrace_hash *hash)
{ … }
static void free_ftrace_mod(struct ftrace_mod_load *ftrace_mod)
{ … }
static void clear_ftrace_mod_list(struct list_head *head)
{ … }
static void free_ftrace_hash(struct ftrace_hash *hash)
{ … }
static void __free_ftrace_hash_rcu(struct rcu_head *rcu)
{ … }
static void free_ftrace_hash_rcu(struct ftrace_hash *hash)
{ … }
void ftrace_free_filter(struct ftrace_ops *ops)
{ … }
EXPORT_SYMBOL_GPL(…);
static struct ftrace_hash *alloc_ftrace_hash(int size_bits)
{ … }
static int ftrace_add_mod(struct trace_array *tr,
const char *func, const char *module,
int enable)
{ … }
static struct ftrace_hash *
alloc_and_copy_ftrace_hash(int size_bits, struct ftrace_hash *hash)
{ … }
static void ftrace_hash_rec_disable_modify(struct ftrace_ops *ops);
static void ftrace_hash_rec_enable_modify(struct ftrace_ops *ops);
static int ftrace_hash_ipmodify_update(struct ftrace_ops *ops,
struct ftrace_hash *new_hash);
static struct ftrace_hash *__move_hash(struct ftrace_hash *src, int size)
{ … }
static struct ftrace_hash *
__ftrace_hash_move(struct ftrace_hash *src)
{ … }
static int
ftrace_hash_move(struct ftrace_ops *ops, int enable,
struct ftrace_hash **dst, struct ftrace_hash *src)
{ … }
static bool hash_contains_ip(unsigned long ip,
struct ftrace_ops_hash *hash)
{ … }
int
ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip, void *regs)
{ … }
#define do_for_each_ftrace_rec(pg, rec) …
#define while_for_each_ftrace_rec() …
static int ftrace_cmp_recs(const void *a, const void *b)
{ … }
static struct dyn_ftrace *lookup_rec(unsigned long start, unsigned long end)
{ … }
unsigned long ftrace_location_range(unsigned long start, unsigned long end)
{ … }
unsigned long ftrace_location(unsigned long ip)
{ … }
int ftrace_text_reserved(const void *start, const void *end)
{ … }
static bool test_rec_ops_needs_regs(struct dyn_ftrace *rec)
{ … }
static struct ftrace_ops *
ftrace_find_tramp_ops_any(struct dyn_ftrace *rec);
static struct ftrace_ops *
ftrace_find_tramp_ops_any_other(struct dyn_ftrace *rec, struct ftrace_ops *op_exclude);
static struct ftrace_ops *
ftrace_find_tramp_ops_next(struct dyn_ftrace *rec, struct ftrace_ops *ops);
static bool skip_record(struct dyn_ftrace *rec)
{ … }
static bool __ftrace_hash_rec_update(struct ftrace_ops *ops,
bool inc)
{ … }
static bool ftrace_hash_rec_disable(struct ftrace_ops *ops)
{ … }
static bool ftrace_hash_rec_enable(struct ftrace_ops *ops)
{ … }
static void ftrace_hash_rec_update_modify(struct ftrace_ops *ops, bool inc)
{ … }
static void ftrace_hash_rec_disable_modify(struct ftrace_ops *ops)
{ … }
static void ftrace_hash_rec_enable_modify(struct ftrace_ops *ops)
{ … }
static int __ftrace_hash_update_ipmodify(struct ftrace_ops *ops,
struct ftrace_hash *old_hash,
struct ftrace_hash *new_hash)
{ … }
static int ftrace_hash_ipmodify_enable(struct ftrace_ops *ops)
{ … }
static void ftrace_hash_ipmodify_disable(struct ftrace_ops *ops)
{ … }
static int ftrace_hash_ipmodify_update(struct ftrace_ops *ops,
struct ftrace_hash *new_hash)
{ … }
static void print_ip_ins(const char *fmt, const unsigned char *p)
{ … }
enum ftrace_bug_type ftrace_bug_type;
const void *ftrace_expected;
static void print_bug_type(void)
{ … }
void ftrace_bug(int failed, struct dyn_ftrace *rec)
{ … }
static int ftrace_check_record(struct dyn_ftrace *rec, bool enable, bool update)
{ … }
int ftrace_update_record(struct dyn_ftrace *rec, bool enable)
{ … }
int ftrace_test_record(struct dyn_ftrace *rec, bool enable)
{ … }
static struct ftrace_ops *
ftrace_find_tramp_ops_any(struct dyn_ftrace *rec)
{ … }
static struct ftrace_ops *
ftrace_find_tramp_ops_any_other(struct dyn_ftrace *rec, struct ftrace_ops *op_exclude)
{ … }
static struct ftrace_ops *
ftrace_find_tramp_ops_next(struct dyn_ftrace *rec,
struct ftrace_ops *op)
{ … }
static struct ftrace_ops *
ftrace_find_tramp_ops_curr(struct dyn_ftrace *rec)
{ … }
static struct ftrace_ops *
ftrace_find_tramp_ops_new(struct dyn_ftrace *rec)
{ … }
struct ftrace_ops *
ftrace_find_unique_ops(struct dyn_ftrace *rec)
{ … }
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
static struct ftrace_hash __rcu *direct_functions = …;
static DEFINE_MUTEX(direct_mutex);
unsigned long ftrace_find_rec_direct(unsigned long ip)
{ … }
static void call_direct_funcs(unsigned long ip, unsigned long pip,
struct ftrace_ops *ops, struct ftrace_regs *fregs)
{ … }
#endif
unsigned long ftrace_get_addr_new(struct dyn_ftrace *rec)
{ … }
unsigned long ftrace_get_addr_curr(struct dyn_ftrace *rec)
{ … }
static int
__ftrace_replace_code(struct dyn_ftrace *rec, bool enable)
{ … }
void __weak ftrace_replace_code(int mod_flags)
{ … }
struct ftrace_rec_iter { … };
struct ftrace_rec_iter *ftrace_rec_iter_start(void)
{ … }
struct ftrace_rec_iter *ftrace_rec_iter_next(struct ftrace_rec_iter *iter)
{ … }
struct dyn_ftrace *ftrace_rec_iter_record(struct ftrace_rec_iter *iter)
{ … }
static int
ftrace_nop_initialize(struct module *mod, struct dyn_ftrace *rec)
{ … }
void __weak ftrace_arch_code_modify_prepare(void)
{ … }
void __weak ftrace_arch_code_modify_post_process(void)
{ … }
static int update_ftrace_func(ftrace_func_t func)
{ … }
void ftrace_modify_all_code(int command)
{ … }
static int __ftrace_modify_code(void *data)
{ … }
void ftrace_run_stop_machine(int command)
{ … }
void __weak arch_ftrace_update_code(int command)
{ … }
static void ftrace_run_update_code(int command)
{ … }
static void ftrace_run_modify_code(struct ftrace_ops *ops, int command,
struct ftrace_ops_hash *old_hash)
{ … }
static ftrace_func_t saved_ftrace_func;
static int ftrace_start_up;
void __weak arch_ftrace_trampoline_free(struct ftrace_ops *ops)
{ … }
static LIST_HEAD(ftrace_ops_trampoline_list);
static void ftrace_add_trampoline_to_kallsyms(struct ftrace_ops *ops)
{ … }
static void ftrace_remove_trampoline_from_kallsyms(struct ftrace_ops *ops)
{ … }
#define FTRACE_TRAMPOLINE_MOD …
#define FTRACE_TRAMPOLINE_SYM …
static void ftrace_trampoline_free(struct ftrace_ops *ops)
{ … }
static void ftrace_startup_enable(int command)
{ … }
static void ftrace_startup_all(int command)
{ … }
int ftrace_startup(struct ftrace_ops *ops, int command)
{ … }
int ftrace_shutdown(struct ftrace_ops *ops, int command)
{ … }
static struct ftrace_hash *copy_hash(struct ftrace_hash *src)
{ … }
static int append_hash(struct ftrace_hash **hash, struct ftrace_hash *new_hash)
{ … }
static int intersect_hash(struct ftrace_hash **hash, struct ftrace_hash *new_hash1,
struct ftrace_hash *new_hash2)
{ … }
static struct ftrace_hash *append_hashes(struct ftrace_ops *ops)
{ … }
static struct ftrace_hash *intersect_hashes(struct ftrace_ops *ops)
{ … }
static bool ops_equal(struct ftrace_hash *A, struct ftrace_hash *B)
{ … }
static void ftrace_ops_update_code(struct ftrace_ops *ops,
struct ftrace_ops_hash *old_hash);
static int __ftrace_hash_move_and_update_ops(struct ftrace_ops *ops,
struct ftrace_hash **orig_hash,
struct ftrace_hash *hash,
int enable)
{ … }
static int ftrace_update_ops(struct ftrace_ops *ops, struct ftrace_hash *filter_hash,
struct ftrace_hash *notrace_hash)
{ … }
int ftrace_startup_subops(struct ftrace_ops *ops, struct ftrace_ops *subops, int command)
{ … }
int ftrace_shutdown_subops(struct ftrace_ops *ops, struct ftrace_ops *subops, int command)
{ … }
static int ftrace_hash_move_and_update_subops(struct ftrace_ops *subops,
struct ftrace_hash **orig_subhash,
struct ftrace_hash *hash,
int enable)
{ … }
static u64 ftrace_update_time;
unsigned long ftrace_update_tot_cnt;
unsigned long ftrace_number_of_pages;
unsigned long ftrace_number_of_groups;
static inline int ops_traces_mod(struct ftrace_ops *ops)
{ … }
static int ftrace_update_code(struct module *mod, struct ftrace_page *new_pgs)
{ … }
static int ftrace_allocate_records(struct ftrace_page *pg, int count)
{ … }
static void ftrace_free_pages(struct ftrace_page *pages)
{ … }
static struct ftrace_page *
ftrace_allocate_pages(unsigned long num_to_init)
{ … }
#define FTRACE_BUFF_MAX …
struct ftrace_iterator { … };
static void *
t_probe_next(struct seq_file *m, loff_t *pos)
{ … }
static void *t_probe_start(struct seq_file *m, loff_t *pos)
{ … }
static int
t_probe_show(struct seq_file *m, struct ftrace_iterator *iter)
{ … }
static void *
t_mod_next(struct seq_file *m, loff_t *pos)
{ … }
static void *t_mod_start(struct seq_file *m, loff_t *pos)
{ … }
static int
t_mod_show(struct seq_file *m, struct ftrace_iterator *iter)
{ … }
static void *
t_func_next(struct seq_file *m, loff_t *pos)
{ … }
static void *
t_next(struct seq_file *m, void *v, loff_t *pos)
{ … }
static void reset_iter_read(struct ftrace_iterator *iter)
{ … }
static void *t_start(struct seq_file *m, loff_t *pos)
{ … }
static void t_stop(struct seq_file *m, void *p)
{ … }
void * __weak
arch_ftrace_trampoline_func(struct ftrace_ops *ops, struct dyn_ftrace *rec)
{ … }
static void add_trampoline_func(struct seq_file *m, struct ftrace_ops *ops,
struct dyn_ftrace *rec)
{ … }
#ifdef FTRACE_MCOUNT_MAX_OFFSET
static int test_for_valid_rec(struct dyn_ftrace *rec)
{ … }
static struct workqueue_struct *ftrace_check_wq __initdata;
static struct work_struct ftrace_check_work __initdata;
static __init void ftrace_check_work_func(struct work_struct *work)
{ … }
static int __init ftrace_check_for_weak_functions(void)
{ … }
static int __init ftrace_check_sync(void)
{ … }
late_initcall_sync(ftrace_check_sync);
subsys_initcall(ftrace_check_for_weak_functions);
static int print_rec(struct seq_file *m, unsigned long ip)
{ … }
#else
static inline int test_for_valid_rec(struct dyn_ftrace *rec)
{
return 1;
}
static inline int print_rec(struct seq_file *m, unsigned long ip)
{
seq_printf(m, "%ps", (void *)ip);
return 0;
}
#endif
static int t_show(struct seq_file *m, void *v)
{ … }
static const struct seq_operations show_ftrace_seq_ops = …;
static int
ftrace_avail_open(struct inode *inode, struct file *file)
{ … }
static int
ftrace_enabled_open(struct inode *inode, struct file *file)
{ … }
static int
ftrace_touched_open(struct inode *inode, struct file *file)
{ … }
static int
ftrace_avail_addrs_open(struct inode *inode, struct file *file)
{ … }
int
ftrace_regex_open(struct ftrace_ops *ops, int flag,
struct inode *inode, struct file *file)
{ … }
static int
ftrace_filter_open(struct inode *inode, struct file *file)
{ … }
static int
ftrace_notrace_open(struct inode *inode, struct file *file)
{ … }
struct ftrace_glob { … };
char * __weak arch_ftrace_match_adjust(char *str, const char *search)
{ … }
static int ftrace_match(char *str, struct ftrace_glob *g)
{ … }
static int
enter_record(struct ftrace_hash *hash, struct dyn_ftrace *rec, int clear_filter)
{ … }
static int
add_rec_by_index(struct ftrace_hash *hash, struct ftrace_glob *func_g,
int clear_filter)
{ … }
#ifdef FTRACE_MCOUNT_MAX_OFFSET
static int lookup_ip(unsigned long ip, char **modname, char *str)
{ … }
#else
static int lookup_ip(unsigned long ip, char **modname, char *str)
{
kallsyms_lookup(ip, NULL, NULL, modname, str);
return 0;
}
#endif
static int
ftrace_match_record(struct dyn_ftrace *rec, struct ftrace_glob *func_g,
struct ftrace_glob *mod_g, int exclude_mod)
{ … }
static int
match_records(struct ftrace_hash *hash, char *func, int len, char *mod)
{ … }
static int
ftrace_match_records(struct ftrace_hash *hash, char *buff, int len)
{ … }
static void ftrace_ops_update_code(struct ftrace_ops *ops,
struct ftrace_ops_hash *old_hash)
{ … }
static int ftrace_hash_move_and_update_ops(struct ftrace_ops *ops,
struct ftrace_hash **orig_hash,
struct ftrace_hash *hash,
int enable)
{ … }
static bool module_exists(const char *module)
{ … }
static int cache_mod(struct trace_array *tr,
const char *func, char *module, int enable)
{ … }
static int
ftrace_set_regex(struct ftrace_ops *ops, unsigned char *buf, int len,
int reset, int enable);
#ifdef CONFIG_MODULES
static void process_mod_list(struct list_head *head, struct ftrace_ops *ops,
char *mod, bool enable)
{ … }
static void process_cached_mods(const char *mod_name)
{ … }
#endif
static int
ftrace_mod_callback(struct trace_array *tr, struct ftrace_hash *hash,
char *func_orig, char *cmd, char *module, int enable)
{ … }
static struct ftrace_func_command ftrace_mod_cmd = …;
static int __init ftrace_mod_cmd_init(void)
{ … }
core_initcall(ftrace_mod_cmd_init);
static void function_trace_probe_call(unsigned long ip, unsigned long parent_ip,
struct ftrace_ops *op, struct ftrace_regs *fregs)
{ … }
struct ftrace_func_map { … };
struct ftrace_func_mapper { … };
struct ftrace_func_mapper *allocate_ftrace_func_mapper(void)
{ … }
void **ftrace_func_mapper_find_ip(struct ftrace_func_mapper *mapper,
unsigned long ip)
{ … }
int ftrace_func_mapper_add_ip(struct ftrace_func_mapper *mapper,
unsigned long ip, void *data)
{ … }
void *ftrace_func_mapper_remove_ip(struct ftrace_func_mapper *mapper,
unsigned long ip)
{ … }
void free_ftrace_func_mapper(struct ftrace_func_mapper *mapper,
ftrace_mapper_func free_func)
{ … }
static void release_probe(struct ftrace_func_probe *probe)
{ … }
static void acquire_probe_locked(struct ftrace_func_probe *probe)
{ … }
int
register_ftrace_function_probe(char *glob, struct trace_array *tr,
struct ftrace_probe_ops *probe_ops,
void *data)
{ … }
int
unregister_ftrace_function_probe_func(char *glob, struct trace_array *tr,
struct ftrace_probe_ops *probe_ops)
{ … }
void clear_ftrace_function_probes(struct trace_array *tr)
{ … }
static LIST_HEAD(ftrace_commands);
static DEFINE_MUTEX(ftrace_cmd_mutex);
__init int register_ftrace_command(struct ftrace_func_command *cmd)
{ … }
__init int unregister_ftrace_command(struct ftrace_func_command *cmd)
{ … }
static int ftrace_process_regex(struct ftrace_iterator *iter,
char *buff, int len, int enable)
{ … }
static ssize_t
ftrace_regex_write(struct file *file, const char __user *ubuf,
size_t cnt, loff_t *ppos, int enable)
{ … }
ssize_t
ftrace_filter_write(struct file *file, const char __user *ubuf,
size_t cnt, loff_t *ppos)
{ … }
ssize_t
ftrace_notrace_write(struct file *file, const char __user *ubuf,
size_t cnt, loff_t *ppos)
{ … }
static int
__ftrace_match_addr(struct ftrace_hash *hash, unsigned long ip, int remove)
{ … }
static int
ftrace_match_addr(struct ftrace_hash *hash, unsigned long *ips,
unsigned int cnt, int remove)
{ … }
static int
ftrace_set_hash(struct ftrace_ops *ops, unsigned char *buf, int len,
unsigned long *ips, unsigned int cnt,
int remove, int reset, int enable)
{ … }
static int
ftrace_set_addr(struct ftrace_ops *ops, unsigned long *ips, unsigned int cnt,
int remove, int reset, int enable)
{ … }
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
static int register_ftrace_function_nolock(struct ftrace_ops *ops);
#ifndef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS
#define MULTI_FLAGS …
#else
#define MULTI_FLAGS …
#endif
static int check_direct_multi(struct ftrace_ops *ops)
{ … }
static void remove_direct_functions_hash(struct ftrace_hash *hash, unsigned long addr)
{ … }
static void register_ftrace_direct_cb(struct rcu_head *rhp)
{ … }
int register_ftrace_direct(struct ftrace_ops *ops, unsigned long addr)
{ … }
EXPORT_SYMBOL_GPL(…);
int unregister_ftrace_direct(struct ftrace_ops *ops, unsigned long addr,
bool free_filters)
{ … }
EXPORT_SYMBOL_GPL(…);
static int
__modify_ftrace_direct(struct ftrace_ops *ops, unsigned long addr)
{ … }
int modify_ftrace_direct_nolock(struct ftrace_ops *ops, unsigned long addr)
{ … }
EXPORT_SYMBOL_GPL(…);
int modify_ftrace_direct(struct ftrace_ops *ops, unsigned long addr)
{ … }
EXPORT_SYMBOL_GPL(…);
#endif
int ftrace_set_filter_ip(struct ftrace_ops *ops, unsigned long ip,
int remove, int reset)
{ … }
EXPORT_SYMBOL_GPL(…);
int ftrace_set_filter_ips(struct ftrace_ops *ops, unsigned long *ips,
unsigned int cnt, int remove, int reset)
{ … }
EXPORT_SYMBOL_GPL(…);
void ftrace_ops_set_global_filter(struct ftrace_ops *ops)
{ … }
EXPORT_SYMBOL_GPL(…);
static int
ftrace_set_regex(struct ftrace_ops *ops, unsigned char *buf, int len,
int reset, int enable)
{ … }
int ftrace_set_filter(struct ftrace_ops *ops, unsigned char *buf,
int len, int reset)
{ … }
EXPORT_SYMBOL_GPL(…);
int ftrace_set_notrace(struct ftrace_ops *ops, unsigned char *buf,
int len, int reset)
{ … }
EXPORT_SYMBOL_GPL(…);
void ftrace_set_global_filter(unsigned char *buf, int len, int reset)
{ … }
EXPORT_SYMBOL_GPL(…);
void ftrace_set_global_notrace(unsigned char *buf, int len, int reset)
{ … }
EXPORT_SYMBOL_GPL(…);
#define FTRACE_FILTER_SIZE …
static char ftrace_notrace_buf[FTRACE_FILTER_SIZE] __initdata;
static char ftrace_filter_buf[FTRACE_FILTER_SIZE] __initdata;
bool ftrace_filter_param __initdata;
static int __init set_ftrace_notrace(char *str)
{ … }
__setup(…);
static int __init set_ftrace_filter(char *str)
{ … }
__setup(…);
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
static char ftrace_graph_buf[FTRACE_FILTER_SIZE] __initdata;
static char ftrace_graph_notrace_buf[FTRACE_FILTER_SIZE] __initdata;
static int ftrace_graph_set_hash(struct ftrace_hash *hash, char *buffer);
static int __init set_graph_function(char *str)
{ … }
__setup(…);
static int __init set_graph_notrace_function(char *str)
{ … }
__setup(…);
static int __init set_graph_max_depth_function(char *str)
{ … }
__setup(…);
static void __init set_ftrace_early_graph(char *buf, int enable)
{ … }
#endif
void __init
ftrace_set_early_filter(struct ftrace_ops *ops, char *buf, int enable)
{ … }
static void __init set_ftrace_early_filters(void)
{ … }
int ftrace_regex_release(struct inode *inode, struct file *file)
{ … }
static const struct file_operations ftrace_avail_fops = …;
static const struct file_operations ftrace_enabled_fops = …;
static const struct file_operations ftrace_touched_fops = …;
static const struct file_operations ftrace_avail_addrs_fops = …;
static const struct file_operations ftrace_filter_fops = …;
static const struct file_operations ftrace_notrace_fops = …;
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
static DEFINE_MUTEX(graph_lock);
struct ftrace_hash __rcu *ftrace_graph_hash = …;
struct ftrace_hash __rcu *ftrace_graph_notrace_hash = …;
enum graph_filter_type { … };
#define FTRACE_GRAPH_EMPTY …
struct ftrace_graph_data { … };
static void *
__g_next(struct seq_file *m, loff_t *pos)
{ … }
static void *
g_next(struct seq_file *m, void *v, loff_t *pos)
{ … }
static void *g_start(struct seq_file *m, loff_t *pos)
{ … }
static void g_stop(struct seq_file *m, void *p)
{ … }
static int g_show(struct seq_file *m, void *v)
{ … }
static const struct seq_operations ftrace_graph_seq_ops = …;
static int
__ftrace_graph_open(struct inode *inode, struct file *file,
struct ftrace_graph_data *fgd)
{ … }
static int
ftrace_graph_open(struct inode *inode, struct file *file)
{ … }
static int
ftrace_graph_notrace_open(struct inode *inode, struct file *file)
{ … }
static int
ftrace_graph_release(struct inode *inode, struct file *file)
{ … }
static int
ftrace_graph_set_hash(struct ftrace_hash *hash, char *buffer)
{ … }
static ssize_t
ftrace_graph_write(struct file *file, const char __user *ubuf,
size_t cnt, loff_t *ppos)
{ … }
static const struct file_operations ftrace_graph_fops = …;
static const struct file_operations ftrace_graph_notrace_fops = …;
#endif
void ftrace_create_filter_files(struct ftrace_ops *ops,
struct dentry *parent)
{ … }
void ftrace_destroy_filter_files(struct ftrace_ops *ops)
{ … }
static __init int ftrace_init_dyn_tracefs(struct dentry *d_tracer)
{ … }
static int ftrace_cmp_ips(const void *a, const void *b)
{ … }
#ifdef CONFIG_FTRACE_SORT_STARTUP_TEST
static void test_is_sorted(unsigned long *start, unsigned long count)
{ … }
#else
static void test_is_sorted(unsigned long *start, unsigned long count)
{
}
#endif
static int ftrace_process_locs(struct module *mod,
unsigned long *start,
unsigned long *end)
{ … }
struct ftrace_mod_func { … };
struct ftrace_mod_map { … };
static int ftrace_get_trampoline_kallsym(unsigned int symnum,
unsigned long *value, char *type,
char *name, char *module_name,
int *exported)
{ … }
#if defined(CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS) || defined(CONFIG_MODULES)
static bool
ops_references_ip(struct ftrace_ops *ops, unsigned long ip)
{ … }
#endif
#ifdef CONFIG_MODULES
#define next_to_ftrace_page(p) …
static LIST_HEAD(ftrace_mod_maps);
static int referenced_filters(struct dyn_ftrace *rec)
{ … }
static void
clear_mod_from_hash(struct ftrace_page *pg, struct ftrace_hash *hash)
{ … }
static void clear_mod_from_hashes(struct ftrace_page *pg)
{ … }
static void ftrace_free_mod_map(struct rcu_head *rcu)
{ … }
void ftrace_release_mod(struct module *mod)
{ … }
void ftrace_module_enable(struct module *mod)
{ … }
void ftrace_module_init(struct module *mod)
{ … }
static void save_ftrace_mod_rec(struct ftrace_mod_map *mod_map,
struct dyn_ftrace *rec)
{ … }
static struct ftrace_mod_map *
allocate_ftrace_mod_map(struct module *mod,
unsigned long start, unsigned long end)
{ … }
static int
ftrace_func_address_lookup(struct ftrace_mod_map *mod_map,
unsigned long addr, unsigned long *size,
unsigned long *off, char *sym)
{ … }
int
ftrace_mod_address_lookup(unsigned long addr, unsigned long *size,
unsigned long *off, char **modname, char *sym)
{ … }
int ftrace_mod_get_kallsym(unsigned int symnum, unsigned long *value,
char *type, char *name,
char *module_name, int *exported)
{ … }
#else
static void save_ftrace_mod_rec(struct ftrace_mod_map *mod_map,
struct dyn_ftrace *rec) { }
static inline struct ftrace_mod_map *
allocate_ftrace_mod_map(struct module *mod,
unsigned long start, unsigned long end)
{
return NULL;
}
int ftrace_mod_get_kallsym(unsigned int symnum, unsigned long *value,
char *type, char *name, char *module_name,
int *exported)
{
int ret;
preempt_disable();
ret = ftrace_get_trampoline_kallsym(symnum, value, type, name,
module_name, exported);
preempt_enable();
return ret;
}
#endif
struct ftrace_init_func { … };
static void
clear_func_from_hash(struct ftrace_init_func *func, struct ftrace_hash *hash)
{ … }
static void
clear_func_from_hashes(struct ftrace_init_func *func)
{ … }
static void add_to_clear_hash_list(struct list_head *clear_list,
struct dyn_ftrace *rec)
{ … }
void ftrace_free_mem(struct module *mod, void *start_ptr, void *end_ptr)
{ … }
void __init ftrace_free_init_mem(void)
{ … }
int __init __weak ftrace_dyn_arch_init(void)
{ … }
void __init ftrace_init(void)
{ … }
void __weak arch_ftrace_update_trampoline(struct ftrace_ops *ops)
{ … }
static void ftrace_update_trampoline(struct ftrace_ops *ops)
{ … }
void ftrace_init_trace_array(struct trace_array *tr)
{ … }
#else
struct ftrace_ops global_ops = {
.func = ftrace_stub,
.flags = FTRACE_OPS_FL_INITIALIZED |
FTRACE_OPS_FL_PID,
};
static int __init ftrace_nodyn_init(void)
{
ftrace_enabled = 1;
return 0;
}
core_initcall(ftrace_nodyn_init);
static inline int ftrace_init_dyn_tracefs(struct dentry *d_tracer) { return 0; }
static inline void ftrace_startup_all(int command) { }
static void ftrace_update_trampoline(struct ftrace_ops *ops)
{
}
#endif
__init void ftrace_init_global_array_ops(struct trace_array *tr)
{ … }
void ftrace_init_array_ops(struct trace_array *tr, ftrace_func_t func)
{ … }
void ftrace_reset_array_ops(struct trace_array *tr)
{ … }
static nokprobe_inline void
__ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,
struct ftrace_ops *ignored, struct ftrace_regs *fregs)
{ … }
#if ARCH_SUPPORTS_FTRACE_OPS
void arch_ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,
struct ftrace_ops *op, struct ftrace_regs *fregs)
{ … }
#else
void arch_ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip)
{
__ftrace_ops_list_func(ip, parent_ip, NULL, NULL);
}
#endif
NOKPROBE_SYMBOL(arch_ftrace_ops_list_func);
static void ftrace_ops_assist_func(unsigned long ip, unsigned long parent_ip,
struct ftrace_ops *op, struct ftrace_regs *fregs)
{ … }
NOKPROBE_SYMBOL(ftrace_ops_assist_func);
ftrace_func_t ftrace_ops_get_func(struct ftrace_ops *ops)
{ … }
static void
ftrace_filter_pid_sched_switch_probe(void *data, bool preempt,
struct task_struct *prev,
struct task_struct *next,
unsigned int prev_state)
{ … }
static void
ftrace_pid_follow_sched_process_fork(void *data,
struct task_struct *self,
struct task_struct *task)
{ … }
static void
ftrace_pid_follow_sched_process_exit(void *data, struct task_struct *task)
{ … }
void ftrace_pid_follow_fork(struct trace_array *tr, bool enable)
{ … }
static void clear_ftrace_pids(struct trace_array *tr, int type)
{ … }
void ftrace_clear_pids(struct trace_array *tr)
{ … }
static void ftrace_pid_reset(struct trace_array *tr, int type)
{ … }
#define FTRACE_NO_PIDS …
static void *fpid_start(struct seq_file *m, loff_t *pos)
__acquires(RCU)
{ … }
static void *fpid_next(struct seq_file *m, void *v, loff_t *pos)
{ … }
static void fpid_stop(struct seq_file *m, void *p)
__releases(RCU)
{ … }
static int fpid_show(struct seq_file *m, void *v)
{ … }
static const struct seq_operations ftrace_pid_sops = …;
static void *fnpid_start(struct seq_file *m, loff_t *pos)
__acquires(RCU)
{ … }
static void *fnpid_next(struct seq_file *m, void *v, loff_t *pos)
{ … }
static const struct seq_operations ftrace_no_pid_sops = …;
static int pid_open(struct inode *inode, struct file *file, int type)
{ … }
static int
ftrace_pid_open(struct inode *inode, struct file *file)
{ … }
static int
ftrace_no_pid_open(struct inode *inode, struct file *file)
{ … }
static void ignore_task_cpu(void *data)
{ … }
static ssize_t
pid_write(struct file *filp, const char __user *ubuf,
size_t cnt, loff_t *ppos, int type)
{ … }
static ssize_t
ftrace_pid_write(struct file *filp, const char __user *ubuf,
size_t cnt, loff_t *ppos)
{ … }
static ssize_t
ftrace_no_pid_write(struct file *filp, const char __user *ubuf,
size_t cnt, loff_t *ppos)
{ … }
static int
ftrace_pid_release(struct inode *inode, struct file *file)
{ … }
static const struct file_operations ftrace_pid_fops = …;
static const struct file_operations ftrace_no_pid_fops = …;
void ftrace_init_tracefs(struct trace_array *tr, struct dentry *d_tracer)
{ … }
void __init ftrace_init_tracefs_toplevel(struct trace_array *tr,
struct dentry *d_tracer)
{ … }
void ftrace_kill(void)
{ … }
int ftrace_is_dead(void)
{ … }
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
static int prepare_direct_functions_for_ipmodify(struct ftrace_ops *ops)
{ … }
static void cleanup_direct_functions_after_ipmodify(struct ftrace_ops *ops)
{ … }
#define lock_direct_mutex() …
#define unlock_direct_mutex() …
#else
static int prepare_direct_functions_for_ipmodify(struct ftrace_ops *ops)
{
return 0;
}
static void cleanup_direct_functions_after_ipmodify(struct ftrace_ops *ops)
{
}
#define lock_direct_mutex …
#define unlock_direct_mutex …
#endif
static int register_ftrace_function_nolock(struct ftrace_ops *ops)
{ … }
int register_ftrace_function(struct ftrace_ops *ops)
{ … }
EXPORT_SYMBOL_GPL(…);
int unregister_ftrace_function(struct ftrace_ops *ops)
{ … }
EXPORT_SYMBOL_GPL(…);
static int symbols_cmp(const void *a, const void *b)
{ … }
struct kallsyms_data { … };
static int kallsyms_callback(void *data, const char *name, unsigned long addr)
{ … }
int ftrace_lookup_symbols(const char **sorted_syms, size_t cnt, unsigned long *addrs)
{ … }
#ifdef CONFIG_SYSCTL
#ifdef CONFIG_DYNAMIC_FTRACE
static void ftrace_startup_sysctl(void)
{ … }
static void ftrace_shutdown_sysctl(void)
{ … }
#else
#define ftrace_startup_sysctl …
#define ftrace_shutdown_sysctl …
#endif
static bool is_permanent_ops_registered(void)
{ … }
static int
ftrace_enable_sysctl(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{ … }
static struct ctl_table ftrace_sysctls[] = …;
static int __init ftrace_sysctl_init(void)
{ … }
late_initcall(ftrace_sysctl_init);
#endif