linux/kernel/trace/trace_fprobe.c

// SPDX-License-Identifier: GPL-2.0
/*
 * Fprobe-based tracing events
 * Copyright (C) 2022 Google LLC.
 */
#define pr_fmt(fmt)
#include <asm/ptrace.h>

#include <linux/fprobe.h>
#include <linux/module.h>
#include <linux/rculist.h>
#include <linux/security.h>
#include <linux/tracepoint.h>
#include <linux/uaccess.h>

#include "trace_dynevent.h"
#include "trace_probe.h"
#include "trace_probe_kernel.h"
#include "trace_probe_tmpl.h"

#define FPROBE_EVENT_SYSTEM
#define TRACEPOINT_EVENT_SYSTEM
#define RETHOOK_MAXACTIVE_MAX

static int trace_fprobe_create(const char *raw_command);
static int trace_fprobe_show(struct seq_file *m, struct dyn_event *ev);
static int trace_fprobe_release(struct dyn_event *ev);
static bool trace_fprobe_is_busy(struct dyn_event *ev);
static bool trace_fprobe_match(const char *system, const char *event,
			int argc, const char **argv, struct dyn_event *ev);

static struct dyn_event_operations trace_fprobe_ops =;

/*
 * Fprobe event core functions
 */
struct trace_fprobe {};

static bool is_trace_fprobe(struct dyn_event *ev)
{}

static struct trace_fprobe *to_trace_fprobe(struct dyn_event *ev)
{}

/**
 * for_each_trace_fprobe - iterate over the trace_fprobe list
 * @pos:	the struct trace_fprobe * for each entry
 * @dpos:	the struct dyn_event * to use as a loop cursor
 */
#define for_each_trace_fprobe(pos, dpos)

static bool trace_fprobe_is_return(struct trace_fprobe *tf)
{}

static bool trace_fprobe_is_tracepoint(struct trace_fprobe *tf)
{}

static const char *trace_fprobe_symbol(struct trace_fprobe *tf)
{}

static bool trace_fprobe_is_busy(struct dyn_event *ev)
{}

static bool trace_fprobe_match_command_head(struct trace_fprobe *tf,
					    int argc, const char **argv)
{}

static bool trace_fprobe_match(const char *system, const char *event,
			int argc, const char **argv, struct dyn_event *ev)
{}

static bool trace_fprobe_is_registered(struct trace_fprobe *tf)
{}

/*
 * Note that we don't verify the fetch_insn code, since it does not come
 * from user space.
 */
static int
process_fetch_insn(struct fetch_insn *code, void *rec, void *edata,
		   void *dest, void *base)
{}
NOKPROBE_SYMBOL()

/* function entry handler */
static nokprobe_inline void
__fentry_trace_func(struct trace_fprobe *tf, unsigned long entry_ip,
		    struct pt_regs *regs,
		    struct trace_event_file *trace_file)
{}

static void
fentry_trace_func(struct trace_fprobe *tf, unsigned long entry_ip,
		  struct pt_regs *regs)
{}
NOKPROBE_SYMBOL(fentry_trace_func);

/* function exit handler */
static int trace_fprobe_entry_handler(struct fprobe *fp, unsigned long entry_ip,
				unsigned long ret_ip, struct pt_regs *regs,
				void *entry_data)
{}
NOKPROBE_SYMBOL()

static nokprobe_inline void
__fexit_trace_func(struct trace_fprobe *tf, unsigned long entry_ip,
		   unsigned long ret_ip, struct pt_regs *regs,
		   void *entry_data, struct trace_event_file *trace_file)
{}

static void
fexit_trace_func(struct trace_fprobe *tf, unsigned long entry_ip,
		 unsigned long ret_ip, struct pt_regs *regs, void *entry_data)
{}
NOKPROBE_SYMBOL(fexit_trace_func);

#ifdef CONFIG_PERF_EVENTS

static int fentry_perf_func(struct trace_fprobe *tf, unsigned long entry_ip,
			    struct pt_regs *regs)
{}
NOKPROBE_SYMBOL(fentry_perf_func);

static void
fexit_perf_func(struct trace_fprobe *tf, unsigned long entry_ip,
		unsigned long ret_ip, struct pt_regs *regs,
		void *entry_data)
{}
NOKPROBE_SYMBOL(fexit_perf_func);
#endif	/* CONFIG_PERF_EVENTS */

static int fentry_dispatcher(struct fprobe *fp, unsigned long entry_ip,
			     unsigned long ret_ip, struct pt_regs *regs,
			     void *entry_data)
{}
NOKPROBE_SYMBOL(fentry_dispatcher);

static void fexit_dispatcher(struct fprobe *fp, unsigned long entry_ip,
			     unsigned long ret_ip, struct pt_regs *regs,
			     void *entry_data)
{}
NOKPROBE_SYMBOL(fexit_dispatcher);

static void free_trace_fprobe(struct trace_fprobe *tf)
{}

/*
 * Allocate new trace_probe and initialize it (including fprobe).
 */
static struct trace_fprobe *alloc_trace_fprobe(const char *group,
					       const char *event,
					       const char *symbol,
					       struct tracepoint *tpoint,
					       int maxactive,
					       int nargs, bool is_return)
{}

static struct trace_fprobe *find_trace_fprobe(const char *event,
					      const char *group)
{}

static inline int __enable_trace_fprobe(struct trace_fprobe *tf)
{}

static void __disable_trace_fprobe(struct trace_probe *tp)
{}

/*
 * Enable trace_probe
 * if the file is NULL, enable "perf" handler, or enable "trace" handler.
 */
static int enable_trace_fprobe(struct trace_event_call *call,
			       struct trace_event_file *file)
{}

/*
 * Disable trace_probe
 * if the file is NULL, disable "perf" handler, or disable "trace" handler.
 */
static int disable_trace_fprobe(struct trace_event_call *call,
				struct trace_event_file *file)
{}

/* Event entry printers */
static enum print_line_t
print_fentry_event(struct trace_iterator *iter, int flags,
		   struct trace_event *event)
{}

static enum print_line_t
print_fexit_event(struct trace_iterator *iter, int flags,
		  struct trace_event *event)
{}

static int fentry_event_define_fields(struct trace_event_call *event_call)
{}

static int fexit_event_define_fields(struct trace_event_call *event_call)
{}

static struct trace_event_functions fentry_funcs =;

static struct trace_event_functions fexit_funcs =;

static struct trace_event_fields fentry_fields_array[] =;

static struct trace_event_fields fexit_fields_array[] =;

static int fprobe_register(struct trace_event_call *event,
			   enum trace_reg type, void *data);

static inline void init_trace_event_call(struct trace_fprobe *tf)
{}

static int register_fprobe_event(struct trace_fprobe *tf)
{}

static int unregister_fprobe_event(struct trace_fprobe *tf)
{}

/* Internal register function - just handle fprobe and flags */
static int __register_trace_fprobe(struct trace_fprobe *tf)
{}

/* Internal unregister function - just handle fprobe and flags */
static void __unregister_trace_fprobe(struct trace_fprobe *tf)
{}

/* TODO: make this trace_*probe common function */
/* Unregister a trace_probe and probe_event */
static int unregister_trace_fprobe(struct trace_fprobe *tf)
{}

static bool trace_fprobe_has_same_fprobe(struct trace_fprobe *orig,
					 struct trace_fprobe *comp)
{}

static int append_trace_fprobe(struct trace_fprobe *tf, struct trace_fprobe *to)
{}

/* Register a trace_probe and probe_event */
static int register_trace_fprobe(struct trace_fprobe *tf)
{}

#ifdef CONFIG_MODULES
static int __tracepoint_probe_module_cb(struct notifier_block *self,
					unsigned long val, void *data)
{}

static struct notifier_block tracepoint_module_nb =;
#endif /* CONFIG_MODULES */

struct __find_tracepoint_cb_data {};

static void __find_tracepoint_cb(struct tracepoint *tp, void *priv)
{}

static struct tracepoint *find_tracepoint(const char *tp_name)
{}

static int parse_symbol_and_return(int argc, const char *argv[],
				   char **symbol, bool *is_return,
				   bool is_tracepoint)
{}

static int __trace_fprobe_create(int argc, const char *argv[])
{}

static int trace_fprobe_create(const char *raw_command)
{}

static int trace_fprobe_release(struct dyn_event *ev)
{}

static int trace_fprobe_show(struct seq_file *m, struct dyn_event *ev)
{}

/*
 * called by perf_trace_init() or __ftrace_set_clr_event() under event_mutex.
 */
static int fprobe_register(struct trace_event_call *event,
			   enum trace_reg type, void *data)
{}

/*
 * Register dynevent at core_initcall. This allows kernel to setup fprobe
 * events in postcore_initcall without tracefs.
 */
static __init int init_fprobe_trace_early(void)
{}
core_initcall(init_fprobe_trace_early);