#define pr_fmt(fmt) …
#include <linux/bpf-cgroup.h>
#include <linux/security.h>
#include <linux/module.h>
#include <linux/uaccess.h>
#include <linux/rculist.h>
#include <linux/error-injection.h>
#include <asm/setup.h>
#include "trace_dynevent.h"
#include "trace_kprobe_selftest.h"
#include "trace_probe.h"
#include "trace_probe_tmpl.h"
#include "trace_probe_kernel.h"
#define KPROBE_EVENT_SYSTEM …
#define KRETPROBE_MAXACTIVE_MAX …
static char kprobe_boot_events_buf[COMMAND_LINE_SIZE] __initdata;
static int __init set_kprobe_boot_events(char *str)
{ … }
__setup(…);
static int trace_kprobe_create(const char *raw_command);
static int trace_kprobe_show(struct seq_file *m, struct dyn_event *ev);
static int trace_kprobe_release(struct dyn_event *ev);
static bool trace_kprobe_is_busy(struct dyn_event *ev);
static bool trace_kprobe_match(const char *system, const char *event,
int argc, const char **argv, struct dyn_event *ev);
static struct dyn_event_operations trace_kprobe_ops = …;
struct trace_kprobe { … };
static bool is_trace_kprobe(struct dyn_event *ev)
{ … }
static struct trace_kprobe *to_trace_kprobe(struct dyn_event *ev)
{ … }
#define for_each_trace_kprobe(pos, dpos) …
static nokprobe_inline bool trace_kprobe_is_return(struct trace_kprobe *tk)
{ … }
static nokprobe_inline const char *trace_kprobe_symbol(struct trace_kprobe *tk)
{ … }
static nokprobe_inline unsigned long trace_kprobe_offset(struct trace_kprobe *tk)
{ … }
static nokprobe_inline bool trace_kprobe_has_gone(struct trace_kprobe *tk)
{ … }
static nokprobe_inline bool trace_kprobe_within_module(struct trace_kprobe *tk,
struct module *mod)
{ … }
#ifdef CONFIG_MODULES
static nokprobe_inline bool trace_kprobe_module_exist(struct trace_kprobe *tk)
{ … }
#else
static inline bool trace_kprobe_module_exist(struct trace_kprobe *tk)
{
return false;
}
#endif
static bool trace_kprobe_is_busy(struct dyn_event *ev)
{ … }
static bool trace_kprobe_match_command_head(struct trace_kprobe *tk,
int argc, const char **argv)
{ … }
static bool trace_kprobe_match(const char *system, const char *event,
int argc, const char **argv, struct dyn_event *ev)
{ … }
static nokprobe_inline unsigned long trace_kprobe_nhit(struct trace_kprobe *tk)
{ … }
static nokprobe_inline bool trace_kprobe_is_registered(struct trace_kprobe *tk)
{ … }
static nokprobe_inline
unsigned long trace_kprobe_address(struct trace_kprobe *tk)
{ … }
static nokprobe_inline struct trace_kprobe *
trace_kprobe_primary_from_call(struct trace_event_call *call)
{ … }
bool trace_kprobe_on_func_entry(struct trace_event_call *call)
{ … }
bool trace_kprobe_error_injectable(struct trace_event_call *call)
{ … }
static int register_kprobe_event(struct trace_kprobe *tk);
static int unregister_kprobe_event(struct trace_kprobe *tk);
static int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs);
static int kretprobe_dispatcher(struct kretprobe_instance *ri,
struct pt_regs *regs);
static void free_trace_kprobe(struct trace_kprobe *tk)
{ … }
static struct trace_kprobe *alloc_trace_kprobe(const char *group,
const char *event,
void *addr,
const char *symbol,
unsigned long offs,
int maxactive,
int nargs, bool is_return)
{ … }
static struct trace_kprobe *find_trace_kprobe(const char *event,
const char *group)
{ … }
static inline int __enable_trace_kprobe(struct trace_kprobe *tk)
{ … }
static void __disable_trace_kprobe(struct trace_probe *tp)
{ … }
static int enable_trace_kprobe(struct trace_event_call *call,
struct trace_event_file *file)
{ … }
static int disable_trace_kprobe(struct trace_event_call *call,
struct trace_event_file *file)
{ … }
#if defined(CONFIG_DYNAMIC_FTRACE) && \
!defined(CONFIG_KPROBE_EVENTS_ON_NOTRACE)
static bool __within_notrace_func(unsigned long addr)
{
unsigned long offset, size;
if (!addr || !kallsyms_lookup_size_offset(addr, &size, &offset))
return false;
addr -= offset;
return !ftrace_location_range(addr, addr + size - 1);
}
static bool within_notrace_func(struct trace_kprobe *tk)
{
unsigned long addr = trace_kprobe_address(tk);
char symname[KSYM_NAME_LEN], *p;
if (!__within_notrace_func(addr))
return false;
if (!lookup_symbol_name(addr, symname)) {
p = strchr(symname, '.');
if (!p)
return true;
*p = '\0';
addr = (unsigned long)kprobe_lookup_name(symname, 0);
if (addr)
return __within_notrace_func(addr);
}
return true;
}
#else
#define within_notrace_func(tk) …
#endif
static int __register_trace_kprobe(struct trace_kprobe *tk)
{ … }
static void __unregister_trace_kprobe(struct trace_kprobe *tk)
{ … }
static int unregister_trace_kprobe(struct trace_kprobe *tk)
{ … }
static bool trace_kprobe_has_same_kprobe(struct trace_kprobe *orig,
struct trace_kprobe *comp)
{ … }
static int append_trace_kprobe(struct trace_kprobe *tk, struct trace_kprobe *to)
{ … }
static int register_trace_kprobe(struct trace_kprobe *tk)
{ … }
#ifdef CONFIG_MODULES
static int validate_module_probe_symbol(const char *modname, const char *symbol);
static int register_module_trace_kprobe(struct module *mod, struct trace_kprobe *tk)
{ … }
static int trace_kprobe_module_callback(struct notifier_block *nb,
unsigned long val, void *data)
{ … }
static struct notifier_block trace_kprobe_module_nb = …;
static int trace_kprobe_register_module_notifier(void)
{ … }
#else
static int trace_kprobe_register_module_notifier(void)
{
return 0;
}
#endif
static int count_symbols(void *data, unsigned long unused)
{ … }
struct sym_count_ctx { … };
static int count_mod_symbols(void *data, const char *name, unsigned long unused)
{ … }
static unsigned int number_of_same_symbols(const char *mod, const char *func_name)
{ … }
static int validate_module_probe_symbol(const char *modname, const char *symbol)
{ … }
#ifdef CONFIG_MODULES
static struct module *try_module_get_by_name(const char *name)
{ … }
#else
#define try_module_get_by_name …
#endif
static int validate_probe_symbol(char *symbol)
{ … }
static int trace_kprobe_entry_handler(struct kretprobe_instance *ri,
struct pt_regs *regs);
static int __trace_kprobe_create(int argc, const char *argv[])
{ … }
static int trace_kprobe_create(const char *raw_command)
{ … }
static int create_or_delete_trace_kprobe(const char *raw_command)
{ … }
static int trace_kprobe_run_command(struct dynevent_cmd *cmd)
{ … }
void kprobe_event_cmd_init(struct dynevent_cmd *cmd, char *buf, int maxlen)
{ … }
EXPORT_SYMBOL_GPL(…);
int __kprobe_event_gen_cmd_start(struct dynevent_cmd *cmd, bool kretprobe,
const char *name, const char *loc, ...)
{ … }
EXPORT_SYMBOL_GPL(…);
int __kprobe_event_add_fields(struct dynevent_cmd *cmd, ...)
{ … }
EXPORT_SYMBOL_GPL(…);
int kprobe_event_delete(const char *name)
{ … }
EXPORT_SYMBOL_GPL(…);
static int trace_kprobe_release(struct dyn_event *ev)
{ … }
static int trace_kprobe_show(struct seq_file *m, struct dyn_event *ev)
{ … }
static int probes_seq_show(struct seq_file *m, void *v)
{ … }
static const struct seq_operations probes_seq_op = …;
static int probes_open(struct inode *inode, struct file *file)
{ … }
static ssize_t probes_write(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos)
{ … }
static const struct file_operations kprobe_events_ops = …;
static unsigned long trace_kprobe_missed(struct trace_kprobe *tk)
{ … }
static int probes_profile_seq_show(struct seq_file *m, void *v)
{ … }
static const struct seq_operations profile_seq_op = …;
static int profile_open(struct inode *inode, struct file *file)
{ … }
static const struct file_operations kprobe_profile_ops = …;
static int
process_fetch_insn(struct fetch_insn *code, void *rec, void *edata,
void *dest, void *base)
{ … }
NOKPROBE_SYMBOL(…)
static nokprobe_inline void
__kprobe_trace_func(struct trace_kprobe *tk, struct pt_regs *regs,
struct trace_event_file *trace_file)
{ … }
static void
kprobe_trace_func(struct trace_kprobe *tk, struct pt_regs *regs)
{ … }
NOKPROBE_SYMBOL(kprobe_trace_func);
static int trace_kprobe_entry_handler(struct kretprobe_instance *ri,
struct pt_regs *regs)
{ … }
static nokprobe_inline void
__kretprobe_trace_func(struct trace_kprobe *tk, struct kretprobe_instance *ri,
struct pt_regs *regs,
struct trace_event_file *trace_file)
{ … }
static void
kretprobe_trace_func(struct trace_kprobe *tk, struct kretprobe_instance *ri,
struct pt_regs *regs)
{ … }
NOKPROBE_SYMBOL(kretprobe_trace_func);
static enum print_line_t
print_kprobe_event(struct trace_iterator *iter, int flags,
struct trace_event *event)
{ … }
static enum print_line_t
print_kretprobe_event(struct trace_iterator *iter, int flags,
struct trace_event *event)
{ … }
static int kprobe_event_define_fields(struct trace_event_call *event_call)
{ … }
static int kretprobe_event_define_fields(struct trace_event_call *event_call)
{ … }
#ifdef CONFIG_PERF_EVENTS
static int
kprobe_perf_func(struct trace_kprobe *tk, struct pt_regs *regs)
{ … }
NOKPROBE_SYMBOL(kprobe_perf_func);
static void
kretprobe_perf_func(struct trace_kprobe *tk, struct kretprobe_instance *ri,
struct pt_regs *regs)
{ … }
NOKPROBE_SYMBOL(kretprobe_perf_func);
int bpf_get_kprobe_info(const struct perf_event *event, u32 *fd_type,
const char **symbol, u64 *probe_offset,
u64 *probe_addr, unsigned long *missed,
bool perf_type_tracepoint)
{ … }
#endif
static int kprobe_register(struct trace_event_call *event,
enum trace_reg type, void *data)
{ … }
static int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs)
{ … }
NOKPROBE_SYMBOL(kprobe_dispatcher);
static int
kretprobe_dispatcher(struct kretprobe_instance *ri, struct pt_regs *regs)
{ … }
NOKPROBE_SYMBOL(kretprobe_dispatcher);
static struct trace_event_functions kretprobe_funcs = …;
static struct trace_event_functions kprobe_funcs = …;
static struct trace_event_fields kretprobe_fields_array[] = …;
static struct trace_event_fields kprobe_fields_array[] = …;
static inline void init_trace_event_call(struct trace_kprobe *tk)
{ … }
static int register_kprobe_event(struct trace_kprobe *tk)
{ … }
static int unregister_kprobe_event(struct trace_kprobe *tk)
{ … }
#ifdef CONFIG_PERF_EVENTS
struct trace_event_call *
create_local_trace_kprobe(char *func, void *addr, unsigned long offs,
bool is_return)
{ … }
void destroy_local_trace_kprobe(struct trace_event_call *event_call)
{ … }
#endif
static __init void enable_boot_kprobe_events(void)
{ … }
static __init void setup_boot_kprobe_events(void)
{ … }
static __init int init_kprobe_trace_early(void)
{ … }
core_initcall(init_kprobe_trace_early);
static __init int init_kprobe_trace(void)
{ … }
fs_initcall(init_kprobe_trace);
#ifdef CONFIG_FTRACE_STARTUP_TEST
static __init struct trace_event_file *
find_trace_probe_file(struct trace_kprobe *tk, struct trace_array *tr)
{ … }
static __init int kprobe_trace_self_tests_init(void)
{ … }
late_initcall(kprobe_trace_self_tests_init);
#endif