Commit | Line | Data |
---|---|---|
8ab83f56 SD |
1 | /* |
2 | * Common header file for probe-based Dynamic events. | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License version 2 as | |
6 | * published by the Free Software Foundation. | |
7 | * | |
8 | * This program is distributed in the hope that it will be useful, | |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | * GNU General Public License for more details. | |
12 | * | |
13 | * You should have received a copy of the GNU General Public License | |
14 | * along with this program; if not, write to the Free Software | |
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
16 | * | |
17 | * This code was copied from kernel/trace/trace_kprobe.h written by | |
18 | * Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> | |
19 | * | |
20 | * Updates to make this generic: | |
21 | * Copyright (C) IBM Corporation, 2010-2011 | |
22 | * Author: Srikar Dronamraju | |
23 | */ | |
24 | ||
25 | #include <linux/seq_file.h> | |
26 | #include <linux/slab.h> | |
27 | #include <linux/smp.h> | |
28 | #include <linux/debugfs.h> | |
29 | #include <linux/types.h> | |
30 | #include <linux/string.h> | |
31 | #include <linux/ctype.h> | |
32 | #include <linux/ptrace.h> | |
33 | #include <linux/perf_event.h> | |
34 | #include <linux/kprobes.h> | |
35 | #include <linux/stringify.h> | |
36 | #include <linux/limits.h> | |
37 | #include <linux/uaccess.h> | |
38 | #include <asm/bitsperlong.h> | |
39 | ||
40 | #include "trace.h" | |
41 | #include "trace_output.h" | |
42 | ||
43 | #define MAX_TRACE_ARGS 128 | |
44 | #define MAX_ARGSTR_LEN 63 | |
45 | #define MAX_EVENT_NAME_LEN 64 | |
46 | #define MAX_STRING_SIZE PATH_MAX | |
47 | ||
48 | /* Reserved field names */ | |
49 | #define FIELD_STRING_IP "__probe_ip" | |
50 | #define FIELD_STRING_RETIP "__probe_ret_ip" | |
51 | #define FIELD_STRING_FUNC "__probe_func" | |
52 | ||
53 | #undef DEFINE_FIELD | |
54 | #define DEFINE_FIELD(type, item, name, is_signed) \ | |
55 | do { \ | |
56 | ret = trace_define_field(event_call, #type, name, \ | |
57 | offsetof(typeof(field), item), \ | |
58 | sizeof(field.item), is_signed, \ | |
59 | FILTER_OTHER); \ | |
60 | if (ret) \ | |
61 | return ret; \ | |
62 | } while (0) | |
63 | ||
64 | ||
65 | /* Flags for trace_probe */ | |
66 | #define TP_FLAG_TRACE 1 | |
67 | #define TP_FLAG_PROFILE 2 | |
68 | #define TP_FLAG_REGISTERED 4 | |
69 | ||
70 | ||
71 | /* data_rloc: data relative location, compatible with u32 */ | |
72 | #define make_data_rloc(len, roffs) \ | |
73 | (((u32)(len) << 16) | ((u32)(roffs) & 0xffff)) | |
74 | #define get_rloc_len(dl) ((u32)(dl) >> 16) | |
75 | #define get_rloc_offs(dl) ((u32)(dl) & 0xffff) | |
76 | ||
77 | /* | |
78 | * Convert data_rloc to data_loc: | |
79 | * data_rloc stores the offset from data_rloc itself, but data_loc | |
80 | * stores the offset from event entry. | |
81 | */ | |
82 | #define convert_rloc_to_loc(dl, offs) ((u32)(dl) + (offs)) | |
83 | ||
84 | /* Data fetch function type */ | |
85 | typedef void (*fetch_func_t)(struct pt_regs *, void *, void *); | |
86 | /* Printing function type */ | |
87 | typedef int (*print_type_func_t)(struct trace_seq *, const char *, void *, void *); | |
88 | ||
89 | /* Fetch types */ | |
90 | enum { | |
91 | FETCH_MTD_reg = 0, | |
92 | FETCH_MTD_stack, | |
93 | FETCH_MTD_retval, | |
94 | FETCH_MTD_memory, | |
95 | FETCH_MTD_symbol, | |
96 | FETCH_MTD_deref, | |
97 | FETCH_MTD_bitfield, | |
98 | FETCH_MTD_END, | |
99 | }; | |
100 | ||
101 | /* Fetch type information table */ | |
102 | struct fetch_type { | |
103 | const char *name; /* Name of type */ | |
104 | size_t size; /* Byte size of type */ | |
105 | int is_signed; /* Signed flag */ | |
106 | print_type_func_t print; /* Print functions */ | |
107 | const char *fmt; /* Fromat string */ | |
108 | const char *fmttype; /* Name in format file */ | |
109 | /* Fetch functions */ | |
110 | fetch_func_t fetch[FETCH_MTD_END]; | |
111 | }; | |
112 | ||
113 | struct fetch_param { | |
114 | fetch_func_t fn; | |
115 | void *data; | |
116 | }; | |
117 | ||
118 | struct probe_arg { | |
119 | struct fetch_param fetch; | |
120 | struct fetch_param fetch_size; | |
121 | unsigned int offset; /* Offset from argument entry */ | |
122 | const char *name; /* Name of this argument */ | |
123 | const char *comm; /* Command of this argument */ | |
124 | const struct fetch_type *type; /* Type of this argument */ | |
125 | }; | |
126 | ||
127 | static inline __kprobes void call_fetch(struct fetch_param *fprm, | |
128 | struct pt_regs *regs, void *dest) | |
129 | { | |
130 | return fprm->fn(regs, fprm->data, dest); | |
131 | } | |
132 | ||
133 | /* Check the name is good for event/group/fields */ | |
134 | static inline int is_good_name(const char *name) | |
135 | { | |
136 | if (!isalpha(*name) && *name != '_') | |
137 | return 0; | |
138 | while (*++name != '\0') { | |
139 | if (!isalpha(*name) && !isdigit(*name) && *name != '_') | |
140 | return 0; | |
141 | } | |
142 | return 1; | |
143 | } | |
144 | ||
145 | extern int traceprobe_parse_probe_arg(char *arg, ssize_t *size, | |
f3f096cf | 146 | struct probe_arg *parg, bool is_return, bool is_kprobe); |
8ab83f56 SD |
147 | |
148 | extern int traceprobe_conflict_field_name(const char *name, | |
149 | struct probe_arg *args, int narg); | |
150 | ||
151 | extern void traceprobe_update_arg(struct probe_arg *arg); | |
152 | extern void traceprobe_free_probe_arg(struct probe_arg *arg); | |
153 | ||
154 | extern int traceprobe_split_symbol_offset(char *symbol, unsigned long *offset); | |
155 | ||
156 | extern ssize_t traceprobe_probes_write(struct file *file, | |
157 | const char __user *buffer, size_t count, loff_t *ppos, | |
158 | int (*createfn)(int, char**)); | |
159 | ||
160 | extern int traceprobe_command(const char *buf, int (*createfn)(int, char**)); |