首页 > 其他分享 >tracer ftrace笔记(11)—— DECLARE_HOOK 宏展开

tracer ftrace笔记(11)—— DECLARE_HOOK 宏展开

时间:2022-10-29 12:45:09浏览次数:50  
标签:11 ftrace struct trace int void event tracepoint DECLARE

一、说明

1. include/trace/hooks/vendor_hooks.h 中定义 #define DECLARE_HOOK DECLARE_TRACE。

2. hook模块的实现端(比如binder.c)和vendor使用端(比如要hook binder.c的ko驱动)都是使用端,drivers/android/vendor_hooks.c 才是实现端。


二、使用端展开

1. tmp.c模拟binder.c和使用binder.c导出的hook。

/* 拷贝内核中的配置事先定义好 */
#define CONFIG_MODULES 1
#define CONFIG_TRACEPOINTS 1
#define CONFIG_HAVE_SYSCALL_TRACEPOINTS 1
#define CONFIG_HAVE_ARCH_PREL32_RELOCATIONS 1
#define CONFIG_TRACING 1
#define MODULE 1 //编译成ko才定义
#define CONFIG_ANDROID_VENDOR_HOOKS 1 //vnedor hook特有,必须有,否则解析出来是错的
/*
 * 在没有define CREATE_TRACE_POINTS 的情况下,
 * 这三个无论是否define了解析出来是完全一样的。
 */
#define CONFIG_PERF_EVENTS 1
#define CONFIG_KPROBE_EVENTS 1
#define CONFIG_UPROBE_EVENTS 1
#define CONFIG_BPF_EVENTS 1

//--------------------------------------------

#include <trace/hooks/binder.h>

/* 模拟binder.c */
int main()
{
    trace_android_vh_binder_set_priority(transaction, task);

    return 0;
}

//--------------------------------------------

/* 模拟 vendor ko 模块注册hook handler函数 */
void register_binder_hooks(void)
    register_trace_android_vh_binder_set_priority(android_vh_binder_set_priority_handler, NULL);
}

//--------------------------------------------

 

2. 只保留一个hook声明的trace/hooks/binder.h

#undef TRACE_SYSTEM
#define TRACE_SYSTEM binder
#undef TRACE_INCLUDE_PATH
#define TRACE_INCLUDE_PATH trace/hooks
#if !defined(_TRACE_HOOK_BINDER_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_HOOK_BINDER_H
#include <linux/tracepoint.h>
#include <trace/hooks/vendor_hooks.h>


DECLARE_HOOK(android_vh_binder_set_priority,
    TP_PROTO(struct binder_transaction *t, struct task_struct *task),
    TP_ARGS(t, task));

#endif /* _TRACE_HOOK_BINDER_H */
/* This part must be outside protection */
#include <trace/define_trace.h>

 

3. export C_INCLUDE_PATH=. 然后 gcc -E tmp.c 展开

struct static_call_key;

struct trace_print_flags {
    unsigned long mask;
    const char *name;
};

struct trace_print_flags_u64 {
    unsigned long long mask;
    const char *name;
};

struct tracepoint_func {
    void *func;
    void *data;
    int prio;
};

struct tracepoint {
    const char *name;
    struct static_key key;
    struct static_call_key *static_call_key;
    void *static_call_tramp;
    void *iterator;
    int (*regfunc)(void);
    void (*unregfunc)(void);
    struct tracepoint_func __rcu *funcs;
};


typedef const int tracepoint_ptr_t;




struct bpf_raw_event_map {
    struct tracepoint *tp;
    void *bpf_func;
    u32 num_args;
    u32 writable_size;
} __aligned(32);

static inline int static_call_init(void) { return 0; }

struct static_call_key {
 void *func;
};
static inline void __static_call_nop(void) { }
static inline void __static_call_update(struct static_call_key *key, void *tramp, void *func)
{
    WRITE_ONCE(key->func, func);
}

static inline int static_call_text_reserved(void *start, void *end)
{
    return 0;
}

struct module;
struct tracepoint;
struct notifier_block;

struct trace_eval_map {
    const char *system;
    const char *eval_string;
    unsigned long eval_value;
};



extern struct srcu_struct tracepoint_srcu;

extern int tracepoint_probe_register(struct tracepoint *tp, void *probe, void *data);
extern int tracepoint_probe_register_prio(struct tracepoint *tp, void *probe, void *data, int prio);
extern int tracepoint_probe_register_prio_may_exist(struct tracepoint *tp, void *probe, void *data, int prio);
extern int tracepoint_probe_unregister(struct tracepoint *tp, void *probe, void *data);
static inline int tracepoint_probe_register_may_exist(struct tracepoint *tp, void *probe, void *data)
{
    return tracepoint_probe_register_prio_may_exist(tp, probe, data, 10);
}
extern void for_each_kernel_tracepoint(void (*fct)(struct tracepoint *tp, void *priv), void *priv);


struct tp_module {
    struct list_head list;
    struct module *mod;
};

bool trace_module_has_bad_taint(struct module *mod);
extern int register_tracepoint_module_notifier(struct notifier_block *nb);
extern int unregister_tracepoint_module_notifier(struct notifier_block *nb);

static inline void tracepoint_synchronize_unregister(void)
{
 synchronize_srcu(&tracepoint_srcu);
 synchronize_rcu();
}



extern int syscall_regfunc(void);
extern void syscall_unregfunc(void);

static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
{
 return offset_to_ptr(p);
}



int android_rvh_probe_register(struct tracepoint *tp, void *probe, void *data);


extern int __traceiter_android_vh_binder_set_priority(void *__data, struct binder_transaction *t, struct task_struct *task);
DECLARE_STATIC_CALL(tp_func_android_vh_binder_set_priority, __traceiter_android_vh_binder_set_priority);
extern struct tracepoint __tracepoint_android_vh_binder_set_priority;
static inline void __nocfi trace_android_vh_binder_set_priority(struct binder_transaction *t, struct task_struct *task)
{
    if (static_key_false(&__tracepoint_android_vh_binder_set_priority.key))
        do {
            struct tracepoint_func *it_func_ptr;
            int __maybe_unused __idx = 0;
            void *__data;
            if (!(cpu_online(raw_smp_processor_id())))
                return;
            WARN_ON_ONCE(0 && in_nmi());
            preempt_disable_notrace();
            if (0) {
                __idx = srcu_read_lock_notrace(&tracepoint_srcu);
                rcu_irq_enter_irqson();
            }

            it_func_ptr = rcu_dereference_raw((&__tracepoint_android_vh_binder_set_priority)->funcs);
            if (it_func_ptr) {
                __data = (it_func_ptr)->data;
                __traceiter_android_vh_binder_set_priority(__data, t, task);
            }
            
            if (0) {
                rcu_irq_exit_irqson();
                srcu_read_unlock_notrace(&tracepoint_srcu, __idx);
            }
            preempt_enable_notrace();
        } while (0);
        
    if (IS_ENABLED(CONFIG_LOCKDEP) && (cpu_online(raw_smp_processor_id()))) {
        rcu_read_lock_sched_notrace();
        rcu_dereference_sched(__tracepoint_android_vh_binder_set_priority.funcs);
        rcu_read_unlock_sched_notrace();
    }
}
    
static inline int register_trace_android_vh_binder_set_priority(void (*probe)(void *__data, struct binder_transaction *t, struct task_struct *task), void *data)
{
    return tracepoint_probe_register(&__tracepoint_android_vh_binder_set_priority, (void *)probe, data);
}

static inline int register_trace_prio_android_vh_binder_set_priority(void (*probe)(void *__data, struct binder_transaction *t, struct task_struct *task), void *data, int prio)
{
    return tracepoint_probe_register_prio(&__tracepoint_android_vh_binder_set_priority, (void *)probe, data, prio);
}

static inline int unregister_trace_android_vh_binder_set_priority(void (*probe)(void *__data, struct binder_transaction *t, struct task_struct *task), void *data)
{
    return tracepoint_probe_unregister(&__tracepoint_android_vh_binder_set_priority, (void *)probe, data);
}

static inline void check_trace_callback_type_android_vh_binder_set_priority(void (*cb)(void *__data, struct binder_transaction *t, struct task_struct *task)) { }

static inline bool trace_android_vh_binder_set_priority_enabled(void) {
    return static_key_false(&__tracepoint_android_vh_binder_set_priority.key);
}


int main()
{
    trace_android_vh_binder_set_priority(transaction, task);

    return 0;
}

void register_binder_hooks(void)
    register_trace_android_vh_binder_set_priority(android_vh_binder_set_priority_handler, NULL);
}

 

三、实现端展开

1. 只保留一个并可直接解析的 vendor_hooks.c

/* ------------ system config ------------- */
#define CONFIG_MODULES 1
#define CONFIG_TRACEPOINTS 1
#define CONFIG_HAVE_SYSCALL_TRACEPOINTS 1
#define CONFIG_HAVE_ARCH_PREL32_RELOCATIONS 1
#define CONFIG_TRACING 1
#define MODULE 1 //编译成ko才定义
#define CONFIG_ANDROID_VENDOR_HOOKS 1 //vnedor hook特有,必须有,否则解析出来是错的
/*
 * 在没有define CREATE_TRACE_POINTS 的情况下,
 * 这三个无论是否define了解析出来是完全一样的。
 */
#define CONFIG_PERF_EVENTS 1
#define CONFIG_KPROBE_EVENTS 1
#define CONFIG_UPROBE_EVENTS 1
#define CONFIG_BPF_EVENTS 1


/* ---------------------------------------- */

#define CREATE_TRACE_POINTS //实现端
#include <trace/hooks/vendor_hooks.h>
#include <linux/tracepoint.h>

#include <trace/hooks/binder.h>

EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_set_priority);

 

2.gcc -E vendor_hooks.c 展开

struct static_call_key;

struct trace_print_flags {
    unsigned long mask;
    const char *name;
};

struct trace_print_flags_u64 {
    unsigned long long mask;
    const char *name;
};

struct tracepoint_func {
    void *func;
    void *data;
    int prio;
};

struct tracepoint {
    const char *name;
    struct static_key key;
    struct static_call_key *static_call_key;
    void *static_call_tramp;
    void *iterator;
    int (*regfunc)(void);
    void (*unregfunc)(void);
    struct tracepoint_func __rcu *funcs;
};


typedef const int tracepoint_ptr_t;




struct bpf_raw_event_map {
    struct tracepoint *tp;
    void *bpf_func;
    u32 num_args;
    u32 writable_size;
} __aligned(32);

static inline int static_call_init(void) { return 0; }

struct static_call_key {
    void *func;
};

static inline void __static_call_nop(void) { }

static inline void __static_call_update(struct static_call_key *key, void *tramp, void *func)
{
    WRITE_ONCE(key->func, func);
}

static inline int static_call_text_reserved(void *start, void *end)
{
    return 0;
}


struct module;
struct tracepoint;
struct notifier_block;

struct trace_eval_map {
    const char *system;
    const char *eval_string;
    unsigned long eval_value;
};



extern struct srcu_struct tracepoint_srcu;

extern int tracepoint_probe_register(struct tracepoint *tp, void *probe, void *data);
extern int tracepoint_probe_register_prio(struct tracepoint *tp, void *probe, void *data, int prio);
extern int tracepoint_probe_register_prio_may_exist(struct tracepoint *tp, void *probe, void *data, int prio);
extern int tracepoint_probe_unregister(struct tracepoint *tp, void *probe, void *data);
static inline int tracepoint_probe_register_may_exist(struct tracepoint *tp, void *probe, void *data)
{
    return tracepoint_probe_register_prio_may_exist(tp, probe, data, 10);
}
extern void for_each_kernel_tracepoint(void (*fct)(struct tracepoint *tp, void *priv), void *priv);


struct tp_module {
    struct list_head list;
    struct module *mod;
};

bool trace_module_has_bad_taint(struct module *mod);
extern int register_tracepoint_module_notifier(struct notifier_block *nb);
extern int unregister_tracepoint_module_notifier(struct notifier_block *nb);

static inline void tracepoint_synchronize_unregister(void)
{
    synchronize_srcu(&tracepoint_srcu);
    synchronize_rcu();
}






extern int syscall_regfunc(void);
extern void syscall_unregfunc(void);

static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
{
 return offset_to_ptr(p);
}

int android_rvh_probe_register(struct tracepoint *tp, void *probe, void *data);

int android_rvh_probe_register(struct tracepoint *tp, void *probe, void *data);

extern int __traceiter_android_vh_binder_set_priority(void *__data, struct binder_transaction *t, struct task_struct *task);
DECLARE_STATIC_CALL(tp_func_android_vh_binder_set_priority, __traceiter_android_vh_binder_set_priority);
extern struct tracepoint __tracepoint_android_vh_binder_set_priority;

static inline void __nocfi trace_android_vh_binder_set_priority(struct binder_transaction *t, struct task_struct *task)
{
    if (static_key_false(&__tracepoint_android_vh_binder_set_priority.key))
        do {
            struct tracepoint_func *it_func_ptr;
            int __maybe_unused __idx = 0;
            void *__data;
            if (!(cpu_online(raw_smp_processor_id())))
                return;
            WARN_ON_ONCE(0 && in_nmi());
            preempt_disable_notrace();
            
            if (0) {
                __idx = srcu_read_lock_notrace(&tracepoint_srcu);
                rcu_irq_enter_irqson();
            }
            
            it_func_ptr = rcu_dereference_raw((&__tracepoint_android_vh_binder_set_priority)->funcs);
            if (it_func_ptr) {
                __data = (it_func_ptr)->data;
                __traceiter_android_vh_binder_set_priority(__data, t, task);
            }
            
            if (0) {
                rcu_irq_exit_irqson();
                srcu_read_unlock_notrace(&tracepoint_srcu, __idx);
            }
            
            preempt_enable_notrace();
        } while (0);
    
    if (IS_ENABLED(CONFIG_LOCKDEP) && (cpu_online(raw_smp_processor_id()))) {
        rcu_read_lock_sched_notrace();
        rcu_dereference_sched(__tracepoint_android_vh_binder_set_priority.funcs);
        rcu_read_unlock_sched_notrace();
    }
}

static inline int register_trace_android_vh_binder_set_priority(void (*probe)(void *__data, struct binder_transaction *t, struct task_struct *task), void *data)
{
    return tracepoint_probe_register(&__tracepoint_android_vh_binder_set_priority, (void *)probe, data);
}

static inline int register_trace_prio_android_vh_binder_set_priority(void (*probe)(void *__data, struct binder_transaction *t, struct task_struct *task), void *data, int prio)
{
    return tracepoint_probe_register_prio(&__tracepoint_android_vh_binder_set_priority, (void *)probe, data, prio);
}

static inline int unregister_trace_android_vh_binder_set_priority(void (*probe)(void *__data, struct binder_transaction *t, struct task_struct *task), void *data)
{
    return tracepoint_probe_unregister(&__tracepoint_android_vh_binder_set_priority, (void *)probe, data);
}

static inline void check_trace_callback_type_android_vh_binder_set_priority(void (*cb)(void *__data, struct binder_transaction *t, struct task_struct *task)) { }

static inline bool trace_android_vh_binder_set_priority_enabled(void) {
    return static_key_false(&__tracepoint_android_vh_binder_set_priority.key);
}

int android_rvh_probe_register(struct tracepoint *tp, void *probe, void *data);


static const char __tpstrtab_android_vh_binder_set_priority[] __section("__tracepoints_strings") = "android_vh_binder_set_priority";

extern struct static_call_key STATIC_CALL_KEY(tp_func_android_vh_binder_set_priority);

int __traceiter_android_vh_binder_set_priority(void *__data, struct binder_transaction *t, struct task_struct *task);

struct tracepoint __tracepoint_android_vh_binder_set_priority __used __section("__tracepoints") = {
    .name = __tpstrtab_android_vh_binder_set_priority, 
    .key = STATIC_KEY_INIT_FALSE,
    .static_call_key = &STATIC_CALL_KEY(tp_func_android_vh_binder_set_priority),
    .static_call_tramp = NULL,
    .iterator = &__traceiter_android_vh_binder_set_priority,
    .regfunc = NULL,
    .unregfunc = NULL,
    .funcs = NULL
};

asm(".section \"__tracepoints_ptrs\", \"a\"    \n" ".balign 4 \n" " .long     __tracepoint_" "android_vh_binder_set_priority" " - . \n" "    .previous \n");

int __nocfi __traceiter_android_vh_binder_set_priority(void *__data, struct binder_transaction *t, struct task_struct *task)
{
    struct tracepoint_func *it_func_ptr; void *it_func;
    it_func_ptr = rcu_dereference_raw((&__tracepoint_android_vh_binder_set_priority)->funcs);

    if (it_func_ptr) {
        do {
            it_func = (it_func_ptr)->func;
            __data = (it_func_ptr)->data;
            ((void(*)(void *, struct binder_transaction *t, struct task_struct *task))(it_func))(__data, t, task);
        } while ((++it_func_ptr)->func);
    } return 0;
}

DECLARE_STATIC_CALL(tp_func_android_vh_binder_set_priority, __traceiter_android_vh_binder_set_priority);

struct static_call_key STATIC_CALL_KEY(tp_func_android_vh_binder_set_priority) = {
    .func = __traceiter_android_vh_binder_set_priority,
};



struct trace_array;
struct array_buffer;
struct tracer;
struct dentry;
struct bpf_prog;

const char *trace_print_flags_seq(struct trace_seq *p, const char *delim, unsigned long flags, const struct trace_print_flags *flag_array);
const char *trace_print_symbols_seq(struct trace_seq *p, unsigned long val, const struct trace_print_flags *symbol_array);
const char *trace_print_bitmask_seq(struct trace_seq *p, void *bitmask_ptr, unsigned int bitmask_size);
const char *trace_print_hex_seq(struct trace_seq *p, const unsigned char *buf, int len, bool concatenate);
const char *trace_print_array_seq(struct trace_seq *p, const void *buf, int count, size_t el_size);

const char * trace_print_hex_dump_seq(struct trace_seq *p, const char *prefix_str,
    int prefix_type, int rowsize, int groupsize, const void *buf, size_t len, bool ascii);

struct trace_iterator;
struct trace_event;

int trace_raw_output_prep(struct trace_iterator *iter,struct trace_event *event);







struct trace_entry {
    unsigned short type;
    unsigned char flags;
    unsigned char preempt_count;
    int pid;
};

struct trace_iterator {
    struct trace_array *tr;
    struct tracer *trace;
    struct array_buffer *array_buffer;
    void *private;
    int cpu_file;
    struct mutex mutex;
    struct ring_buffer_iter **buffer_iter;
    unsigned long iter_flags;
    void *temp;
    unsigned int temp_size;

    struct trace_seq tmp_seq;

    cpumask_var_t started;

    bool snapshot;

    struct trace_seq seq;
    struct trace_entry *ent;
    unsigned long lost_events;
    int leftover;
    int ent_size;
    int cpu;
    u64 ts;

    loff_t pos;
    long idx;
};

enum trace_iter_flags {
    TRACE_FILE_LAT_FMT = 1,
    TRACE_FILE_ANNOTATE = 2,
    TRACE_FILE_TIME_IN_NS = 4,
};


typedef enum print_line_t (*trace_print_func)(struct trace_iterator *iter, int flags, struct trace_event *event);

struct trace_event_functions {
    trace_print_func trace;
    trace_print_func raw;
    trace_print_func hex;
    trace_print_func binary;
};

struct trace_event {
    struct hlist_node node;
    struct list_head list;
    int type;
    struct trace_event_functions *funcs;
};

extern int register_trace_event(struct trace_event *event);
extern int unregister_trace_event(struct trace_event *event);


enum print_line_t {
    TRACE_TYPE_PARTIAL_LINE = 0,
    TRACE_TYPE_HANDLED = 1,
    TRACE_TYPE_UNHANDLED = 2,
    TRACE_TYPE_NO_CONSUME = 3
};

enum print_line_t trace_handle_return(struct trace_seq *s);

void tracing_generic_entry_update(struct trace_entry *entry, unsigned short type, unsigned long flags, int pc);
struct trace_event_file;

struct ring_buffer_event * trace_event_buffer_lock_reserve(struct trace_buffer **current_buffer,
    struct trace_event_file *trace_file, int type, unsigned long len, unsigned long flags, int pc);




void tracing_record_taskinfo(struct task_struct *task, int flags);
void tracing_record_taskinfo_sched_switch(struct task_struct *prev, struct task_struct *next, int flags);

void tracing_record_cmdline(struct task_struct *task);
void tracing_record_tgid(struct task_struct *task);

int trace_output_call(struct trace_iterator *iter, char *name, char *fmt, ...);

struct event_filter;

enum trace_reg {
    TRACE_REG_REGISTER,
    TRACE_REG_UNREGISTER,

    TRACE_REG_PERF_REGISTER,
    TRACE_REG_PERF_UNREGISTER,
    TRACE_REG_PERF_OPEN,
    TRACE_REG_PERF_CLOSE,

    TRACE_REG_PERF_ADD,
    TRACE_REG_PERF_DEL,
};

struct trace_event_call;



struct trace_event_fields {
    const char *type;
    union {
        struct {
            const char *name;
            const int size;
            const int align;
            const int is_signed;
            const int filter_type;
        };
        int (*define_fields)(struct trace_event_call *);
    };
};

struct trace_event_class {
    const char *system;
    void *probe;

    void *perf_probe;

    int (*reg)(struct trace_event_call *event, enum trace_reg type, void *data);
    struct trace_event_fields *fields_array;
    struct list_head *(*get_fields)(struct trace_event_call *);
    struct list_head fields;
    int (*raw_init)(struct trace_event_call *);
};

extern int trace_event_reg(struct trace_event_call *event, enum trace_reg type, void *data);

struct trace_event_buffer {
    struct trace_buffer *buffer;
    struct ring_buffer_event *event;
    struct trace_event_file *trace_file;
    void *entry;
    unsigned long flags;
    int pc;
    struct pt_regs *regs;
};

void *trace_event_buffer_reserve(struct trace_event_buffer *fbuffer, struct trace_event_file *trace_file, unsigned long len);

void trace_event_buffer_commit(struct trace_event_buffer *fbuffer);

enum {
    TRACE_EVENT_FL_FILTERED_BIT,
    TRACE_EVENT_FL_CAP_ANY_BIT,
    TRACE_EVENT_FL_NO_SET_FILTER_BIT,
    TRACE_EVENT_FL_IGNORE_ENABLE_BIT,
    TRACE_EVENT_FL_TRACEPOINT_BIT,
    TRACE_EVENT_FL_KPROBE_BIT,
    TRACE_EVENT_FL_UPROBE_BIT,
};

enum {
    TRACE_EVENT_FL_FILTERED = (1 << TRACE_EVENT_FL_FILTERED_BIT),
    TRACE_EVENT_FL_CAP_ANY = (1 << TRACE_EVENT_FL_CAP_ANY_BIT),
    TRACE_EVENT_FL_NO_SET_FILTER = (1 << TRACE_EVENT_FL_NO_SET_FILTER_BIT),
    TRACE_EVENT_FL_IGNORE_ENABLE = (1 << TRACE_EVENT_FL_IGNORE_ENABLE_BIT),
    TRACE_EVENT_FL_TRACEPOINT = (1 << TRACE_EVENT_FL_TRACEPOINT_BIT),
    TRACE_EVENT_FL_KPROBE = (1 << TRACE_EVENT_FL_KPROBE_BIT),
    TRACE_EVENT_FL_UPROBE = (1 << TRACE_EVENT_FL_UPROBE_BIT),
};



struct trace_event_call {
    struct list_head list;
    struct trace_event_class *class;
    union {
    char *name;
        struct tracepoint *tp;
    };
    struct trace_event event;
    char *print_fmt;
    struct event_filter *filter;
    void *mod;
    void *data;
    int flags;

    int perf_refcount;
    struct hlist_head __percpu *perf_events;
    struct bpf_prog_array __rcu *prog_array;

    int (*perf_perm)(struct trace_event_call *, struct perf_event *);
};


static inline bool bpf_prog_array_valid(struct trace_event_call *call)
{
    return !!READ_ONCE(call->prog_array);
}


static inline const char *trace_event_name(struct trace_event_call *call)
{
    if (call->flags & TRACE_EVENT_FL_TRACEPOINT)
        return call->tp ? call->tp->name : NULL;
    else
        return call->name;
}

static inline struct list_head *trace_get_fields(struct trace_event_call *event_call)
{
    if (!event_call->class->get_fields)
        return &event_call->class->fields;
    return event_call->class->get_fields(event_call);
}

struct trace_array;
struct trace_subsystem_dir;

enum {
    EVENT_FILE_FL_ENABLED_BIT,
    EVENT_FILE_FL_RECORDED_CMD_BIT,
    EVENT_FILE_FL_RECORDED_TGID_BIT,
    EVENT_FILE_FL_FILTERED_BIT,
    EVENT_FILE_FL_NO_SET_FILTER_BIT,
    EVENT_FILE_FL_SOFT_MODE_BIT,
    EVENT_FILE_FL_SOFT_DISABLED_BIT,
    EVENT_FILE_FL_TRIGGER_MODE_BIT,
    EVENT_FILE_FL_TRIGGER_COND_BIT,
    EVENT_FILE_FL_PID_FILTER_BIT,
    EVENT_FILE_FL_WAS_ENABLED_BIT,
};

extern struct trace_event_file *trace_get_event_file(const char *instance, const char *system, const char *event);
extern void trace_put_event_file(struct trace_event_file *file);



enum dynevent_type {
    DYNEVENT_TYPE_SYNTH = 1,
    DYNEVENT_TYPE_KPROBE,
    DYNEVENT_TYPE_NONE,
};

struct dynevent_cmd;

typedef int (*dynevent_create_fn_t)(struct dynevent_cmd *cmd);

struct dynevent_cmd {
    struct seq_buf seq;
    const char *event_name;
    unsigned int n_fields;
    enum dynevent_type type;
    dynevent_create_fn_t run_command;
    void *private_data;
};

extern int dynevent_create(struct dynevent_cmd *cmd);
extern int synth_event_delete(const char *name);
extern void synth_event_cmd_init(struct dynevent_cmd *cmd, char *buf, int maxlen);

extern int __synth_event_gen_cmd_start(struct dynevent_cmd *cmd, const char *name, struct module *mod, ...);


struct synth_field_desc {
    const char *type;
    const char *name;
};

extern int synth_event_gen_cmd_array_start(struct dynevent_cmd *cmd,
    const char *name, struct module *mod, struct synth_field_desc *fields, unsigned int n_fields);
extern int synth_event_create(const char *name, struct synth_field_desc *fields,
    unsigned int n_fields, struct module *mod);

extern int synth_event_add_field(struct dynevent_cmd *cmd, const char *type, const char *name);
extern int synth_event_add_field_str(struct dynevent_cmd *cmd, const char *type_name);
extern int synth_event_add_fields(struct dynevent_cmd *cmd, struct synth_field_desc *fields, unsigned int n_fields);


struct synth_event;

struct synth_event_trace_state {
    struct trace_event_buffer fbuffer;
    struct synth_trace_event *entry;
    struct trace_buffer *buffer;
    struct synth_event *event;
    unsigned int cur_field;
    unsigned int n_u64;
    bool disabled;
    bool add_next;
    bool add_name;
};

extern int synth_event_trace(struct trace_event_file *file, unsigned int n_vals, ...);
extern int synth_event_trace_array(struct trace_event_file *file, u64 *vals, unsigned int n_vals);
extern int synth_event_trace_start(struct trace_event_file *file, struct synth_event_trace_state *trace_state);
extern int synth_event_add_next_val(u64 val, struct synth_event_trace_state *trace_state);
extern int synth_event_add_val(const char *field_name, u64 val, struct synth_event_trace_state *trace_state);
extern int synth_event_trace_end(struct synth_event_trace_state *trace_state);

extern int kprobe_event_delete(const char *name);
extern void kprobe_event_cmd_init(struct dynevent_cmd *cmd, char *buf, int maxlen);


extern int __kprobe_event_gen_cmd_start(struct dynevent_cmd *cmd,
    bool kretprobe, const char *name, const char *loc, ...);


extern int __kprobe_event_add_fields(struct dynevent_cmd *cmd, ...);

enum {
    EVENT_FILE_FL_ENABLED = (1 << EVENT_FILE_FL_ENABLED_BIT),
    EVENT_FILE_FL_RECORDED_CMD = (1 << EVENT_FILE_FL_RECORDED_CMD_BIT),
    EVENT_FILE_FL_RECORDED_TGID = (1 << EVENT_FILE_FL_RECORDED_TGID_BIT),
    EVENT_FILE_FL_FILTERED = (1 << EVENT_FILE_FL_FILTERED_BIT),
    EVENT_FILE_FL_NO_SET_FILTER = (1 << EVENT_FILE_FL_NO_SET_FILTER_BIT),
    EVENT_FILE_FL_SOFT_MODE = (1 << EVENT_FILE_FL_SOFT_MODE_BIT),
    EVENT_FILE_FL_SOFT_DISABLED = (1 << EVENT_FILE_FL_SOFT_DISABLED_BIT),
    EVENT_FILE_FL_TRIGGER_MODE = (1 << EVENT_FILE_FL_TRIGGER_MODE_BIT),
    EVENT_FILE_FL_TRIGGER_COND = (1 << EVENT_FILE_FL_TRIGGER_COND_BIT),
    EVENT_FILE_FL_PID_FILTER = (1 << EVENT_FILE_FL_PID_FILTER_BIT),
    EVENT_FILE_FL_WAS_ENABLED = (1 << EVENT_FILE_FL_WAS_ENABLED_BIT),
};

struct trace_event_file {
    struct list_head list;
    struct trace_event_call *event_call;
    struct event_filter __rcu *filter;
    struct dentry *dir;
    struct trace_array *tr;
    struct trace_subsystem_dir *system;
    struct list_head triggers;
    unsigned long flags;
    atomic_t sm_ref;
    atomic_t tm_ref;
};

enum event_trigger_type {
    ETT_NONE = (0),
    ETT_TRACE_ONOFF = (1 << 0),
    ETT_SNAPSHOT = (1 << 1),
    ETT_STACKTRACE = (1 << 2),
    ETT_EVENT_ENABLE = (1 << 3),
    ETT_EVENT_HIST = (1 << 4),
    ETT_HIST_ENABLE = (1 << 5),
};

extern int filter_match_preds(struct event_filter *filter, void *rec);

extern enum event_trigger_type event_triggers_call(struct trace_event_file *file, void *rec, struct ring_buffer_event *event);
extern void event_triggers_post_call(struct trace_event_file *file, enum event_trigger_type tt);

bool trace_event_ignore_this_pid(struct trace_event_file *trace_file);

static inline bool trace_trigger_soft_disabled(struct trace_event_file *file)
{
    unsigned long eflags = file->flags;

    if (!(eflags & EVENT_FILE_FL_TRIGGER_COND)) {
        if (eflags & EVENT_FILE_FL_TRIGGER_MODE)
            event_triggers_call(file, NULL, NULL);
        if (eflags & EVENT_FILE_FL_SOFT_DISABLED)
            return true;
        if (eflags & EVENT_FILE_FL_PID_FILTER)
            return trace_event_ignore_this_pid(file);
    }
    return false;
}


unsigned int trace_call_bpf(struct trace_event_call *call, void *ctx);
int perf_event_attach_bpf_prog(struct perf_event *event, struct bpf_prog *prog);
void perf_event_detach_bpf_prog(struct perf_event *event);
int perf_event_query_prog_array(struct perf_event *event, void __user *info);
int bpf_probe_register(struct bpf_raw_event_map *btp, struct bpf_prog *prog);
int bpf_probe_unregister(struct bpf_raw_event_map *btp, struct bpf_prog *prog);
struct bpf_raw_event_map *bpf_get_raw_tracepoint(const char *name);
void bpf_put_raw_tracepoint(struct bpf_raw_event_map *btp);
int bpf_get_perf_event_info(const struct perf_event *event, u32 *prog_id, u32 *fd_type, const char **buf, u64 *probe_offset, u64 *probe_addr);

enum {
    FILTER_OTHER = 0,
    FILTER_STATIC_STRING,
    FILTER_DYN_STRING,
    FILTER_PTR_STRING,
    FILTER_TRACE_FN,
    FILTER_COMM,
    FILTER_CPU,
};

extern int trace_event_raw_init(struct trace_event_call *call);
extern int trace_define_field(struct trace_event_call *call, const char *type, const char *name, int offset, int size, int is_signed, int filter_type);
extern int trace_add_event_call(struct trace_event_call *call);
extern int trace_remove_event_call(struct trace_event_call *call);
extern int trace_event_get_offsets(struct trace_event_call *call);


int ftrace_set_clr_event(struct trace_array *tr, char *buf, int set);
int trace_set_clr_event(const char *system, const char *event, int set);
int trace_array_set_clr_event(struct trace_array *tr, const char *system, const char *event, bool enable);

struct perf_event;

DECLARE_PER_CPU(struct pt_regs, perf_trace_regs);
DECLARE_PER_CPU(int, bpf_kprobe_override);

extern int perf_trace_init(struct perf_event *event);
extern void perf_trace_destroy(struct perf_event *event);
extern int perf_trace_add(struct perf_event *event, int flags);
extern void perf_trace_del(struct perf_event *event, int flags);

extern int perf_kprobe_init(struct perf_event *event, bool is_retprobe);
extern void perf_kprobe_destroy(struct perf_event *event);
extern int bpf_get_kprobe_info(const struct perf_event *event, u32 *fd_type, const char **symbol,
    u64 *probe_offset, u64 *probe_addr, bool perf_type_tracepoint);


extern int perf_uprobe_init(struct perf_event *event, unsigned long ref_ctr_offset, bool is_retprobe);
extern void perf_uprobe_destroy(struct perf_event *event);
extern int bpf_get_uprobe_info(const struct perf_event *event, u32 *fd_type, const char **filename,
    u64 *probe_offset, bool perf_type_tracepoint);

extern int ftrace_profile_set_filter(struct perf_event *event, int event_id, char *filter_str);
extern void ftrace_profile_free_filter(struct perf_event *event);
void perf_trace_buf_update(void *record, u16 type);
void *perf_trace_buf_alloc(int size, struct pt_regs **regs, int *rctxp);

void bpf_trace_run1(struct bpf_prog *prog, u64 arg1);
void bpf_trace_run2(struct bpf_prog *prog, u64 arg1, u64 arg2);
void bpf_trace_run3(struct bpf_prog *prog, u64 arg1, u64 arg2, u64 arg3);
void bpf_trace_run4(struct bpf_prog *prog, u64 arg1, u64 arg2, u64 arg3, u64 arg4);
void bpf_trace_run5(struct bpf_prog *prog, u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5);
void bpf_trace_run6(struct bpf_prog *prog, u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6);
void bpf_trace_run7(struct bpf_prog *prog, u64 arg1, u64 arg2,
    u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7);
void bpf_trace_run8(struct bpf_prog *prog, u64 arg1, u64 arg2,
    u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7, u64 arg8);
void bpf_trace_run9(struct bpf_prog *prog, u64 arg1, u64 arg2,
    u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7, u64 arg8, u64 arg9);
void bpf_trace_run10(struct bpf_prog *prog, u64 arg1, u64 arg2,
    u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7, u64 arg8, u64 arg9, u64 arg10);
void bpf_trace_run11(struct bpf_prog *prog, u64 arg1, u64 arg2,
    u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7, u64 arg8, u64 arg9, u64 arg10, u64 arg11);
void bpf_trace_run12(struct bpf_prog *prog, u64 arg1, u64 arg2,
    u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7, u64 arg8, u64 arg9, u64 arg10, u64 arg11, u64 arg12);
void perf_trace_run_bpf_submit(void *raw_data, int size, int rctx, struct trace_event_call *call, u64 count,
    struct pt_regs *regs, struct hlist_head *head, struct task_struct *task);

static inline void perf_trace_buf_submit(void *raw_data, int size, int rctx, u16 type,
    u64 count, struct pt_regs *regs, void *head, struct task_struct *task)
{
    perf_tp_event(type, count, raw_data, size, regs, head, rctx, task);
}

static const char str__binder__trace_system_name[] = "binder";

/* EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_set_priority); 宏展开: */
EXPORT_SYMBOL_GPL(__tracepoint_android_vh_binder_set_priority);
EXPORT_SYMBOL_GPL(__traceiter_android_vh_binder_set_priority);
EXPORT_SYMBOL_GPL(STATIC_CALL_KEY(tp_func_android_vh_binder_set_priority));

 

四、补充

1. EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_set_priority) 导出了可以给ko使用三个符号。

2. 若想新增导出一个hook给ko驱动使用,除了上面 binder.c、vendor_hooks.c 和 trace/hooks/binder.h 中的改动外,还需要改动 abi_gki_aarch64_<vendor>_whitelist 这个白名单,加上 __tracepoint_android_vh_binder_set_priority。

 

标签:11,ftrace,struct,trace,int,void,event,tracepoint,DECLARE
From: https://www.cnblogs.com/hellokitty2/p/16838490.html

相关文章