diff options
author | Steven Rostedt <srostedt@redhat.com> | 2010-05-17 22:26:53 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2010-05-18 00:35:23 -0400 |
commit | f0218b3e9974f06014b61be8987159f4a20e011e (patch) | |
tree | 29a593c4d71ab18cb0c450a34e79bf6bea66877e /kernel/trace/trace_kprobe.c | |
parent | 1eaa4787a774c4896518c81f24e8bccaa2244924 (diff) | |
parent | 9d192e118a094087494997ea1c8a2faf39af38c5 (diff) |
Merge branch 'perf/core' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip into trace/tip/tracing/core-6
Conflicts:
include/trace/ftrace.h
kernel/trace/trace_kprobe.c
Acked-by: Masami Hiramatsu <mhiramat@redhat.com>
Acked-by: Frederic Weisbecker <fweisbec@gmail.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/trace/trace_kprobe.c')
-rw-r--r-- | kernel/trace/trace_kprobe.c | 535 |
1 files changed, 329 insertions, 206 deletions
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 0e3ded64cdb7..9a082bba9537 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
@@ -29,6 +29,8 @@ | |||
29 | #include <linux/ctype.h> | 29 | #include <linux/ctype.h> |
30 | #include <linux/ptrace.h> | 30 | #include <linux/ptrace.h> |
31 | #include <linux/perf_event.h> | 31 | #include <linux/perf_event.h> |
32 | #include <linux/stringify.h> | ||
33 | #include <asm/bitsperlong.h> | ||
32 | 34 | ||
33 | #include "trace.h" | 35 | #include "trace.h" |
34 | #include "trace_output.h" | 36 | #include "trace_output.h" |
@@ -40,7 +42,6 @@ | |||
40 | 42 | ||
41 | /* Reserved field names */ | 43 | /* Reserved field names */ |
42 | #define FIELD_STRING_IP "__probe_ip" | 44 | #define FIELD_STRING_IP "__probe_ip" |
43 | #define FIELD_STRING_NARGS "__probe_nargs" | ||
44 | #define FIELD_STRING_RETIP "__probe_ret_ip" | 45 | #define FIELD_STRING_RETIP "__probe_ret_ip" |
45 | #define FIELD_STRING_FUNC "__probe_func" | 46 | #define FIELD_STRING_FUNC "__probe_func" |
46 | 47 | ||
@@ -52,56 +53,102 @@ const char *reserved_field_names[] = { | |||
52 | "common_tgid", | 53 | "common_tgid", |
53 | "common_lock_depth", | 54 | "common_lock_depth", |
54 | FIELD_STRING_IP, | 55 | FIELD_STRING_IP, |
55 | FIELD_STRING_NARGS, | ||
56 | FIELD_STRING_RETIP, | 56 | FIELD_STRING_RETIP, |
57 | FIELD_STRING_FUNC, | 57 | FIELD_STRING_FUNC, |
58 | }; | 58 | }; |
59 | 59 | ||
60 | struct fetch_func { | 60 | /* Printing function type */ |
61 | unsigned long (*func)(struct pt_regs *, void *); | 61 | typedef int (*print_type_func_t)(struct trace_seq *, const char *, void *); |
62 | #define PRINT_TYPE_FUNC_NAME(type) print_type_##type | ||
63 | #define PRINT_TYPE_FMT_NAME(type) print_type_format_##type | ||
64 | |||
65 | /* Printing in basic type function template */ | ||
66 | #define DEFINE_BASIC_PRINT_TYPE_FUNC(type, fmt, cast) \ | ||
67 | static __kprobes int PRINT_TYPE_FUNC_NAME(type)(struct trace_seq *s, \ | ||
68 | const char *name, void *data)\ | ||
69 | { \ | ||
70 | return trace_seq_printf(s, " %s=" fmt, name, (cast)*(type *)data);\ | ||
71 | } \ | ||
72 | static const char PRINT_TYPE_FMT_NAME(type)[] = fmt; | ||
73 | |||
74 | DEFINE_BASIC_PRINT_TYPE_FUNC(u8, "%x", unsigned int) | ||
75 | DEFINE_BASIC_PRINT_TYPE_FUNC(u16, "%x", unsigned int) | ||
76 | DEFINE_BASIC_PRINT_TYPE_FUNC(u32, "%lx", unsigned long) | ||
77 | DEFINE_BASIC_PRINT_TYPE_FUNC(u64, "%llx", unsigned long long) | ||
78 | DEFINE_BASIC_PRINT_TYPE_FUNC(s8, "%d", int) | ||
79 | DEFINE_BASIC_PRINT_TYPE_FUNC(s16, "%d", int) | ||
80 | DEFINE_BASIC_PRINT_TYPE_FUNC(s32, "%ld", long) | ||
81 | DEFINE_BASIC_PRINT_TYPE_FUNC(s64, "%lld", long long) | ||
82 | |||
83 | /* Data fetch function type */ | ||
84 | typedef void (*fetch_func_t)(struct pt_regs *, void *, void *); | ||
85 | |||
86 | struct fetch_param { | ||
87 | fetch_func_t fn; | ||
62 | void *data; | 88 | void *data; |
63 | }; | 89 | }; |
64 | 90 | ||
65 | static __kprobes unsigned long call_fetch(struct fetch_func *f, | 91 | static __kprobes void call_fetch(struct fetch_param *fprm, |
66 | struct pt_regs *regs) | 92 | struct pt_regs *regs, void *dest) |
67 | { | 93 | { |
68 | return f->func(regs, f->data); | 94 | return fprm->fn(regs, fprm->data, dest); |
69 | } | 95 | } |
70 | 96 | ||
71 | /* fetch handlers */ | 97 | #define FETCH_FUNC_NAME(kind, type) fetch_##kind##_##type |
72 | static __kprobes unsigned long fetch_register(struct pt_regs *regs, | 98 | /* |
73 | void *offset) | 99 | * Define macro for basic types - we don't need to define s* types, because |
74 | { | 100 | * we have to care only about bitwidth at recording time. |
75 | return regs_get_register(regs, (unsigned int)((unsigned long)offset)); | 101 | */ |
102 | #define DEFINE_BASIC_FETCH_FUNCS(kind) \ | ||
103 | DEFINE_FETCH_##kind(u8) \ | ||
104 | DEFINE_FETCH_##kind(u16) \ | ||
105 | DEFINE_FETCH_##kind(u32) \ | ||
106 | DEFINE_FETCH_##kind(u64) | ||
107 | |||
108 | #define CHECK_BASIC_FETCH_FUNCS(kind, fn) \ | ||
109 | ((FETCH_FUNC_NAME(kind, u8) == fn) || \ | ||
110 | (FETCH_FUNC_NAME(kind, u16) == fn) || \ | ||
111 | (FETCH_FUNC_NAME(kind, u32) == fn) || \ | ||
112 | (FETCH_FUNC_NAME(kind, u64) == fn)) | ||
113 | |||
114 | /* Data fetch function templates */ | ||
115 | #define DEFINE_FETCH_reg(type) \ | ||
116 | static __kprobes void FETCH_FUNC_NAME(reg, type)(struct pt_regs *regs, \ | ||
117 | void *offset, void *dest) \ | ||
118 | { \ | ||
119 | *(type *)dest = (type)regs_get_register(regs, \ | ||
120 | (unsigned int)((unsigned long)offset)); \ | ||
76 | } | 121 | } |
77 | 122 | DEFINE_BASIC_FETCH_FUNCS(reg) | |
78 | static __kprobes unsigned long fetch_stack(struct pt_regs *regs, | 123 | |
79 | void *num) | 124 | #define DEFINE_FETCH_stack(type) \ |
80 | { | 125 | static __kprobes void FETCH_FUNC_NAME(stack, type)(struct pt_regs *regs,\ |
81 | return regs_get_kernel_stack_nth(regs, | 126 | void *offset, void *dest) \ |
82 | (unsigned int)((unsigned long)num)); | 127 | { \ |
128 | *(type *)dest = (type)regs_get_kernel_stack_nth(regs, \ | ||
129 | (unsigned int)((unsigned long)offset)); \ | ||
83 | } | 130 | } |
131 | DEFINE_BASIC_FETCH_FUNCS(stack) | ||
84 | 132 | ||
85 | static __kprobes unsigned long fetch_memory(struct pt_regs *regs, void *addr) | 133 | #define DEFINE_FETCH_retval(type) \ |
86 | { | 134 | static __kprobes void FETCH_FUNC_NAME(retval, type)(struct pt_regs *regs,\ |
87 | unsigned long retval; | 135 | void *dummy, void *dest) \ |
88 | 136 | { \ | |
89 | if (probe_kernel_address(addr, retval)) | 137 | *(type *)dest = (type)regs_return_value(regs); \ |
90 | return 0; | ||
91 | return retval; | ||
92 | } | 138 | } |
93 | 139 | DEFINE_BASIC_FETCH_FUNCS(retval) | |
94 | static __kprobes unsigned long fetch_retvalue(struct pt_regs *regs, | 140 | |
95 | void *dummy) | 141 | #define DEFINE_FETCH_memory(type) \ |
96 | { | 142 | static __kprobes void FETCH_FUNC_NAME(memory, type)(struct pt_regs *regs,\ |
97 | return regs_return_value(regs); | 143 | void *addr, void *dest) \ |
98 | } | 144 | { \ |
99 | 145 | type retval; \ | |
100 | static __kprobes unsigned long fetch_stack_address(struct pt_regs *regs, | 146 | if (probe_kernel_address(addr, retval)) \ |
101 | void *dummy) | 147 | *(type *)dest = 0; \ |
102 | { | 148 | else \ |
103 | return kernel_stack_pointer(regs); | 149 | *(type *)dest = retval; \ |
104 | } | 150 | } |
151 | DEFINE_BASIC_FETCH_FUNCS(memory) | ||
105 | 152 | ||
106 | /* Memory fetching by symbol */ | 153 | /* Memory fetching by symbol */ |
107 | struct symbol_cache { | 154 | struct symbol_cache { |
@@ -145,51 +192,126 @@ static struct symbol_cache *alloc_symbol_cache(const char *sym, long offset) | |||
145 | return sc; | 192 | return sc; |
146 | } | 193 | } |
147 | 194 | ||
148 | static __kprobes unsigned long fetch_symbol(struct pt_regs *regs, void *data) | 195 | #define DEFINE_FETCH_symbol(type) \ |
149 | { | 196 | static __kprobes void FETCH_FUNC_NAME(symbol, type)(struct pt_regs *regs,\ |
150 | struct symbol_cache *sc = data; | 197 | void *data, void *dest) \ |
151 | 198 | { \ | |
152 | if (sc->addr) | 199 | struct symbol_cache *sc = data; \ |
153 | return fetch_memory(regs, (void *)sc->addr); | 200 | if (sc->addr) \ |
154 | else | 201 | fetch_memory_##type(regs, (void *)sc->addr, dest); \ |
155 | return 0; | 202 | else \ |
203 | *(type *)dest = 0; \ | ||
156 | } | 204 | } |
205 | DEFINE_BASIC_FETCH_FUNCS(symbol) | ||
157 | 206 | ||
158 | /* Special indirect memory access interface */ | 207 | /* Dereference memory access function */ |
159 | struct indirect_fetch_data { | 208 | struct deref_fetch_param { |
160 | struct fetch_func orig; | 209 | struct fetch_param orig; |
161 | long offset; | 210 | long offset; |
162 | }; | 211 | }; |
163 | 212 | ||
164 | static __kprobes unsigned long fetch_indirect(struct pt_regs *regs, void *data) | 213 | #define DEFINE_FETCH_deref(type) \ |
165 | { | 214 | static __kprobes void FETCH_FUNC_NAME(deref, type)(struct pt_regs *regs,\ |
166 | struct indirect_fetch_data *ind = data; | 215 | void *data, void *dest) \ |
167 | unsigned long addr; | 216 | { \ |
168 | 217 | struct deref_fetch_param *dprm = data; \ | |
169 | addr = call_fetch(&ind->orig, regs); | 218 | unsigned long addr; \ |
170 | if (addr) { | 219 | call_fetch(&dprm->orig, regs, &addr); \ |
171 | addr += ind->offset; | 220 | if (addr) { \ |
172 | return fetch_memory(regs, (void *)addr); | 221 | addr += dprm->offset; \ |
173 | } else | 222 | fetch_memory_##type(regs, (void *)addr, dest); \ |
174 | return 0; | 223 | } else \ |
224 | *(type *)dest = 0; \ | ||
175 | } | 225 | } |
226 | DEFINE_BASIC_FETCH_FUNCS(deref) | ||
176 | 227 | ||
177 | static __kprobes void free_indirect_fetch_data(struct indirect_fetch_data *data) | 228 | static __kprobes void free_deref_fetch_param(struct deref_fetch_param *data) |
178 | { | 229 | { |
179 | if (data->orig.func == fetch_indirect) | 230 | if (CHECK_BASIC_FETCH_FUNCS(deref, data->orig.fn)) |
180 | free_indirect_fetch_data(data->orig.data); | 231 | free_deref_fetch_param(data->orig.data); |
181 | else if (data->orig.func == fetch_symbol) | 232 | else if (CHECK_BASIC_FETCH_FUNCS(symbol, data->orig.fn)) |
182 | free_symbol_cache(data->orig.data); | 233 | free_symbol_cache(data->orig.data); |
183 | kfree(data); | 234 | kfree(data); |
184 | } | 235 | } |
185 | 236 | ||
237 | /* Default (unsigned long) fetch type */ | ||
238 | #define __DEFAULT_FETCH_TYPE(t) u##t | ||
239 | #define _DEFAULT_FETCH_TYPE(t) __DEFAULT_FETCH_TYPE(t) | ||
240 | #define DEFAULT_FETCH_TYPE _DEFAULT_FETCH_TYPE(BITS_PER_LONG) | ||
241 | #define DEFAULT_FETCH_TYPE_STR __stringify(DEFAULT_FETCH_TYPE) | ||
242 | |||
243 | #define ASSIGN_FETCH_FUNC(kind, type) \ | ||
244 | .kind = FETCH_FUNC_NAME(kind, type) | ||
245 | |||
246 | #define ASSIGN_FETCH_TYPE(ptype, ftype, sign) \ | ||
247 | {.name = #ptype, \ | ||
248 | .size = sizeof(ftype), \ | ||
249 | .is_signed = sign, \ | ||
250 | .print = PRINT_TYPE_FUNC_NAME(ptype), \ | ||
251 | .fmt = PRINT_TYPE_FMT_NAME(ptype), \ | ||
252 | ASSIGN_FETCH_FUNC(reg, ftype), \ | ||
253 | ASSIGN_FETCH_FUNC(stack, ftype), \ | ||
254 | ASSIGN_FETCH_FUNC(retval, ftype), \ | ||
255 | ASSIGN_FETCH_FUNC(memory, ftype), \ | ||
256 | ASSIGN_FETCH_FUNC(symbol, ftype), \ | ||
257 | ASSIGN_FETCH_FUNC(deref, ftype), \ | ||
258 | } | ||
259 | |||
260 | /* Fetch type information table */ | ||
261 | static const struct fetch_type { | ||
262 | const char *name; /* Name of type */ | ||
263 | size_t size; /* Byte size of type */ | ||
264 | int is_signed; /* Signed flag */ | ||
265 | print_type_func_t print; /* Print functions */ | ||
266 | const char *fmt; /* Fromat string */ | ||
267 | /* Fetch functions */ | ||
268 | fetch_func_t reg; | ||
269 | fetch_func_t stack; | ||
270 | fetch_func_t retval; | ||
271 | fetch_func_t memory; | ||
272 | fetch_func_t symbol; | ||
273 | fetch_func_t deref; | ||
274 | } fetch_type_table[] = { | ||
275 | ASSIGN_FETCH_TYPE(u8, u8, 0), | ||
276 | ASSIGN_FETCH_TYPE(u16, u16, 0), | ||
277 | ASSIGN_FETCH_TYPE(u32, u32, 0), | ||
278 | ASSIGN_FETCH_TYPE(u64, u64, 0), | ||
279 | ASSIGN_FETCH_TYPE(s8, u8, 1), | ||
280 | ASSIGN_FETCH_TYPE(s16, u16, 1), | ||
281 | ASSIGN_FETCH_TYPE(s32, u32, 1), | ||
282 | ASSIGN_FETCH_TYPE(s64, u64, 1), | ||
283 | }; | ||
284 | |||
285 | static const struct fetch_type *find_fetch_type(const char *type) | ||
286 | { | ||
287 | int i; | ||
288 | |||
289 | if (!type) | ||
290 | type = DEFAULT_FETCH_TYPE_STR; | ||
291 | |||
292 | for (i = 0; i < ARRAY_SIZE(fetch_type_table); i++) | ||
293 | if (strcmp(type, fetch_type_table[i].name) == 0) | ||
294 | return &fetch_type_table[i]; | ||
295 | return NULL; | ||
296 | } | ||
297 | |||
298 | /* Special function : only accept unsigned long */ | ||
299 | static __kprobes void fetch_stack_address(struct pt_regs *regs, | ||
300 | void *dummy, void *dest) | ||
301 | { | ||
302 | *(unsigned long *)dest = kernel_stack_pointer(regs); | ||
303 | } | ||
304 | |||
186 | /** | 305 | /** |
187 | * Kprobe event core functions | 306 | * Kprobe event core functions |
188 | */ | 307 | */ |
189 | 308 | ||
190 | struct probe_arg { | 309 | struct probe_arg { |
191 | struct fetch_func fetch; | 310 | struct fetch_param fetch; |
192 | const char *name; | 311 | unsigned int offset; /* Offset from argument entry */ |
312 | const char *name; /* Name of this argument */ | ||
313 | const char *comm; /* Command of this argument */ | ||
314 | const struct fetch_type *type; /* Type of this argument */ | ||
193 | }; | 315 | }; |
194 | 316 | ||
195 | /* Flags for trace_probe */ | 317 | /* Flags for trace_probe */ |
@@ -204,6 +326,7 @@ struct trace_probe { | |||
204 | const char *symbol; /* symbol name */ | 326 | const char *symbol; /* symbol name */ |
205 | struct ftrace_event_class class; | 327 | struct ftrace_event_class class; |
206 | struct ftrace_event_call call; | 328 | struct ftrace_event_call call; |
329 | ssize_t size; /* trace entry size */ | ||
207 | unsigned int nr_args; | 330 | unsigned int nr_args; |
208 | struct probe_arg args[]; | 331 | struct probe_arg args[]; |
209 | }; | 332 | }; |
@@ -212,6 +335,7 @@ struct trace_probe { | |||
212 | (offsetof(struct trace_probe, args) + \ | 335 | (offsetof(struct trace_probe, args) + \ |
213 | (sizeof(struct probe_arg) * (n))) | 336 | (sizeof(struct probe_arg) * (n))) |
214 | 337 | ||
338 | |||
215 | static __kprobes int probe_is_return(struct trace_probe *tp) | 339 | static __kprobes int probe_is_return(struct trace_probe *tp) |
216 | { | 340 | { |
217 | return tp->rp.handler != NULL; | 341 | return tp->rp.handler != NULL; |
@@ -222,49 +346,6 @@ static __kprobes const char *probe_symbol(struct trace_probe *tp) | |||
222 | return tp->symbol ? tp->symbol : "unknown"; | 346 | return tp->symbol ? tp->symbol : "unknown"; |
223 | } | 347 | } |
224 | 348 | ||
225 | static int probe_arg_string(char *buf, size_t n, struct fetch_func *ff) | ||
226 | { | ||
227 | int ret = -EINVAL; | ||
228 | |||
229 | if (ff->func == fetch_register) { | ||
230 | const char *name; | ||
231 | name = regs_query_register_name((unsigned int)((long)ff->data)); | ||
232 | ret = snprintf(buf, n, "%%%s", name); | ||
233 | } else if (ff->func == fetch_stack) | ||
234 | ret = snprintf(buf, n, "$stack%lu", (unsigned long)ff->data); | ||
235 | else if (ff->func == fetch_memory) | ||
236 | ret = snprintf(buf, n, "@0x%p", ff->data); | ||
237 | else if (ff->func == fetch_symbol) { | ||
238 | struct symbol_cache *sc = ff->data; | ||
239 | if (sc->offset) | ||
240 | ret = snprintf(buf, n, "@%s%+ld", sc->symbol, | ||
241 | sc->offset); | ||
242 | else | ||
243 | ret = snprintf(buf, n, "@%s", sc->symbol); | ||
244 | } else if (ff->func == fetch_retvalue) | ||
245 | ret = snprintf(buf, n, "$retval"); | ||
246 | else if (ff->func == fetch_stack_address) | ||
247 | ret = snprintf(buf, n, "$stack"); | ||
248 | else if (ff->func == fetch_indirect) { | ||
249 | struct indirect_fetch_data *id = ff->data; | ||
250 | size_t l = 0; | ||
251 | ret = snprintf(buf, n, "%+ld(", id->offset); | ||
252 | if (ret >= n) | ||
253 | goto end; | ||
254 | l += ret; | ||
255 | ret = probe_arg_string(buf + l, n - l, &id->orig); | ||
256 | if (ret < 0) | ||
257 | goto end; | ||
258 | l += ret; | ||
259 | ret = snprintf(buf + l, n - l, ")"); | ||
260 | ret += l; | ||
261 | } | ||
262 | end: | ||
263 | if (ret >= n) | ||
264 | return -ENOSPC; | ||
265 | return ret; | ||
266 | } | ||
267 | |||
268 | static int register_probe_event(struct trace_probe *tp); | 349 | static int register_probe_event(struct trace_probe *tp); |
269 | static void unregister_probe_event(struct trace_probe *tp); | 350 | static void unregister_probe_event(struct trace_probe *tp); |
270 | 351 | ||
@@ -348,11 +429,12 @@ error: | |||
348 | 429 | ||
349 | static void free_probe_arg(struct probe_arg *arg) | 430 | static void free_probe_arg(struct probe_arg *arg) |
350 | { | 431 | { |
351 | if (arg->fetch.func == fetch_symbol) | 432 | if (CHECK_BASIC_FETCH_FUNCS(deref, arg->fetch.fn)) |
433 | free_deref_fetch_param(arg->fetch.data); | ||
434 | else if (CHECK_BASIC_FETCH_FUNCS(symbol, arg->fetch.fn)) | ||
352 | free_symbol_cache(arg->fetch.data); | 435 | free_symbol_cache(arg->fetch.data); |
353 | else if (arg->fetch.func == fetch_indirect) | ||
354 | free_indirect_fetch_data(arg->fetch.data); | ||
355 | kfree(arg->name); | 436 | kfree(arg->name); |
437 | kfree(arg->comm); | ||
356 | } | 438 | } |
357 | 439 | ||
358 | static void free_trace_probe(struct trace_probe *tp) | 440 | static void free_trace_probe(struct trace_probe *tp) |
@@ -458,28 +540,30 @@ static int split_symbol_offset(char *symbol, unsigned long *offset) | |||
458 | #define PARAM_MAX_ARGS 16 | 540 | #define PARAM_MAX_ARGS 16 |
459 | #define PARAM_MAX_STACK (THREAD_SIZE / sizeof(unsigned long)) | 541 | #define PARAM_MAX_STACK (THREAD_SIZE / sizeof(unsigned long)) |
460 | 542 | ||
461 | static int parse_probe_vars(char *arg, struct fetch_func *ff, int is_return) | 543 | static int parse_probe_vars(char *arg, const struct fetch_type *t, |
544 | struct fetch_param *f, int is_return) | ||
462 | { | 545 | { |
463 | int ret = 0; | 546 | int ret = 0; |
464 | unsigned long param; | 547 | unsigned long param; |
465 | 548 | ||
466 | if (strcmp(arg, "retval") == 0) { | 549 | if (strcmp(arg, "retval") == 0) { |
467 | if (is_return) { | 550 | if (is_return) |
468 | ff->func = fetch_retvalue; | 551 | f->fn = t->retval; |
469 | ff->data = NULL; | 552 | else |
470 | } else | ||
471 | ret = -EINVAL; | 553 | ret = -EINVAL; |
472 | } else if (strncmp(arg, "stack", 5) == 0) { | 554 | } else if (strncmp(arg, "stack", 5) == 0) { |
473 | if (arg[5] == '\0') { | 555 | if (arg[5] == '\0') { |
474 | ff->func = fetch_stack_address; | 556 | if (strcmp(t->name, DEFAULT_FETCH_TYPE_STR) == 0) |
475 | ff->data = NULL; | 557 | f->fn = fetch_stack_address; |
558 | else | ||
559 | ret = -EINVAL; | ||
476 | } else if (isdigit(arg[5])) { | 560 | } else if (isdigit(arg[5])) { |
477 | ret = strict_strtoul(arg + 5, 10, ¶m); | 561 | ret = strict_strtoul(arg + 5, 10, ¶m); |
478 | if (ret || param > PARAM_MAX_STACK) | 562 | if (ret || param > PARAM_MAX_STACK) |
479 | ret = -EINVAL; | 563 | ret = -EINVAL; |
480 | else { | 564 | else { |
481 | ff->func = fetch_stack; | 565 | f->fn = t->stack; |
482 | ff->data = (void *)param; | 566 | f->data = (void *)param; |
483 | } | 567 | } |
484 | } else | 568 | } else |
485 | ret = -EINVAL; | 569 | ret = -EINVAL; |
@@ -489,7 +573,8 @@ static int parse_probe_vars(char *arg, struct fetch_func *ff, int is_return) | |||
489 | } | 573 | } |
490 | 574 | ||
491 | /* Recursive argument parser */ | 575 | /* Recursive argument parser */ |
492 | static int __parse_probe_arg(char *arg, struct fetch_func *ff, int is_return) | 576 | static int __parse_probe_arg(char *arg, const struct fetch_type *t, |
577 | struct fetch_param *f, int is_return) | ||
493 | { | 578 | { |
494 | int ret = 0; | 579 | int ret = 0; |
495 | unsigned long param; | 580 | unsigned long param; |
@@ -498,13 +583,13 @@ static int __parse_probe_arg(char *arg, struct fetch_func *ff, int is_return) | |||
498 | 583 | ||
499 | switch (arg[0]) { | 584 | switch (arg[0]) { |
500 | case '$': | 585 | case '$': |
501 | ret = parse_probe_vars(arg + 1, ff, is_return); | 586 | ret = parse_probe_vars(arg + 1, t, f, is_return); |
502 | break; | 587 | break; |
503 | case '%': /* named register */ | 588 | case '%': /* named register */ |
504 | ret = regs_query_register_offset(arg + 1); | 589 | ret = regs_query_register_offset(arg + 1); |
505 | if (ret >= 0) { | 590 | if (ret >= 0) { |
506 | ff->func = fetch_register; | 591 | f->fn = t->reg; |
507 | ff->data = (void *)(unsigned long)ret; | 592 | f->data = (void *)(unsigned long)ret; |
508 | ret = 0; | 593 | ret = 0; |
509 | } | 594 | } |
510 | break; | 595 | break; |
@@ -513,26 +598,22 @@ static int __parse_probe_arg(char *arg, struct fetch_func *ff, int is_return) | |||
513 | ret = strict_strtoul(arg + 1, 0, ¶m); | 598 | ret = strict_strtoul(arg + 1, 0, ¶m); |
514 | if (ret) | 599 | if (ret) |
515 | break; | 600 | break; |
516 | ff->func = fetch_memory; | 601 | f->fn = t->memory; |
517 | ff->data = (void *)param; | 602 | f->data = (void *)param; |
518 | } else { | 603 | } else { |
519 | ret = split_symbol_offset(arg + 1, &offset); | 604 | ret = split_symbol_offset(arg + 1, &offset); |
520 | if (ret) | 605 | if (ret) |
521 | break; | 606 | break; |
522 | ff->data = alloc_symbol_cache(arg + 1, offset); | 607 | f->data = alloc_symbol_cache(arg + 1, offset); |
523 | if (ff->data) | 608 | if (f->data) |
524 | ff->func = fetch_symbol; | 609 | f->fn = t->symbol; |
525 | else | ||
526 | ret = -EINVAL; | ||
527 | } | 610 | } |
528 | break; | 611 | break; |
529 | case '+': /* indirect memory */ | 612 | case '+': /* deref memory */ |
530 | case '-': | 613 | case '-': |
531 | tmp = strchr(arg, '('); | 614 | tmp = strchr(arg, '('); |
532 | if (!tmp) { | 615 | if (!tmp) |
533 | ret = -EINVAL; | ||
534 | break; | 616 | break; |
535 | } | ||
536 | *tmp = '\0'; | 617 | *tmp = '\0'; |
537 | ret = strict_strtol(arg + 1, 0, &offset); | 618 | ret = strict_strtol(arg + 1, 0, &offset); |
538 | if (ret) | 619 | if (ret) |
@@ -542,38 +623,58 @@ static int __parse_probe_arg(char *arg, struct fetch_func *ff, int is_return) | |||
542 | arg = tmp + 1; | 623 | arg = tmp + 1; |
543 | tmp = strrchr(arg, ')'); | 624 | tmp = strrchr(arg, ')'); |
544 | if (tmp) { | 625 | if (tmp) { |
545 | struct indirect_fetch_data *id; | 626 | struct deref_fetch_param *dprm; |
627 | const struct fetch_type *t2 = find_fetch_type(NULL); | ||
546 | *tmp = '\0'; | 628 | *tmp = '\0'; |
547 | id = kzalloc(sizeof(struct indirect_fetch_data), | 629 | dprm = kzalloc(sizeof(struct deref_fetch_param), |
548 | GFP_KERNEL); | 630 | GFP_KERNEL); |
549 | if (!id) | 631 | if (!dprm) |
550 | return -ENOMEM; | 632 | return -ENOMEM; |
551 | id->offset = offset; | 633 | dprm->offset = offset; |
552 | ret = __parse_probe_arg(arg, &id->orig, is_return); | 634 | ret = __parse_probe_arg(arg, t2, &dprm->orig, |
635 | is_return); | ||
553 | if (ret) | 636 | if (ret) |
554 | kfree(id); | 637 | kfree(dprm); |
555 | else { | 638 | else { |
556 | ff->func = fetch_indirect; | 639 | f->fn = t->deref; |
557 | ff->data = (void *)id; | 640 | f->data = (void *)dprm; |
558 | } | 641 | } |
559 | } else | 642 | } |
560 | ret = -EINVAL; | ||
561 | break; | 643 | break; |
562 | default: | ||
563 | /* TODO: support custom handler */ | ||
564 | ret = -EINVAL; | ||
565 | } | 644 | } |
645 | if (!ret && !f->fn) | ||
646 | ret = -EINVAL; | ||
566 | return ret; | 647 | return ret; |
567 | } | 648 | } |
568 | 649 | ||
569 | /* String length checking wrapper */ | 650 | /* String length checking wrapper */ |
570 | static int parse_probe_arg(char *arg, struct fetch_func *ff, int is_return) | 651 | static int parse_probe_arg(char *arg, struct trace_probe *tp, |
652 | struct probe_arg *parg, int is_return) | ||
571 | { | 653 | { |
654 | const char *t; | ||
655 | |||
572 | if (strlen(arg) > MAX_ARGSTR_LEN) { | 656 | if (strlen(arg) > MAX_ARGSTR_LEN) { |
573 | pr_info("Argument is too long.: %s\n", arg); | 657 | pr_info("Argument is too long.: %s\n", arg); |
574 | return -ENOSPC; | 658 | return -ENOSPC; |
575 | } | 659 | } |
576 | return __parse_probe_arg(arg, ff, is_return); | 660 | parg->comm = kstrdup(arg, GFP_KERNEL); |
661 | if (!parg->comm) { | ||
662 | pr_info("Failed to allocate memory for command '%s'.\n", arg); | ||
663 | return -ENOMEM; | ||
664 | } | ||
665 | t = strchr(parg->comm, ':'); | ||
666 | if (t) { | ||
667 | arg[t - parg->comm] = '\0'; | ||
668 | t++; | ||
669 | } | ||
670 | parg->type = find_fetch_type(t); | ||
671 | if (!parg->type) { | ||
672 | pr_info("Unsupported type: %s\n", t); | ||
673 | return -EINVAL; | ||
674 | } | ||
675 | parg->offset = tp->size; | ||
676 | tp->size += parg->type->size; | ||
677 | return __parse_probe_arg(arg, parg->type, &parg->fetch, is_return); | ||
577 | } | 678 | } |
578 | 679 | ||
579 | /* Return 1 if name is reserved or already used by another argument */ | 680 | /* Return 1 if name is reserved or already used by another argument */ |
@@ -603,15 +704,18 @@ static int create_trace_probe(int argc, char **argv) | |||
603 | * @ADDR : fetch memory at ADDR (ADDR should be in kernel) | 704 | * @ADDR : fetch memory at ADDR (ADDR should be in kernel) |
604 | * @SYM[+|-offs] : fetch memory at SYM +|- offs (SYM is a data symbol) | 705 | * @SYM[+|-offs] : fetch memory at SYM +|- offs (SYM is a data symbol) |
605 | * %REG : fetch register REG | 706 | * %REG : fetch register REG |
606 | * Indirect memory fetch: | 707 | * Dereferencing memory fetch: |
607 | * +|-offs(ARG) : fetch memory at ARG +|- offs address. | 708 | * +|-offs(ARG) : fetch memory at ARG +|- offs address. |
608 | * Alias name of args: | 709 | * Alias name of args: |
609 | * NAME=FETCHARG : set NAME as alias of FETCHARG. | 710 | * NAME=FETCHARG : set NAME as alias of FETCHARG. |
711 | * Type of args: | ||
712 | * FETCHARG:TYPE : use TYPE instead of unsigned long. | ||
610 | */ | 713 | */ |
611 | struct trace_probe *tp; | 714 | struct trace_probe *tp; |
612 | int i, ret = 0; | 715 | int i, ret = 0; |
613 | int is_return = 0, is_delete = 0; | 716 | int is_return = 0, is_delete = 0; |
614 | char *symbol = NULL, *event = NULL, *arg = NULL, *group = NULL; | 717 | char *symbol = NULL, *event = NULL, *group = NULL; |
718 | char *arg, *tmp; | ||
615 | unsigned long offset = 0; | 719 | unsigned long offset = 0; |
616 | void *addr = NULL; | 720 | void *addr = NULL; |
617 | char buf[MAX_EVENT_NAME_LEN]; | 721 | char buf[MAX_EVENT_NAME_LEN]; |
@@ -724,13 +828,6 @@ static int create_trace_probe(int argc, char **argv) | |||
724 | else | 828 | else |
725 | arg = argv[i]; | 829 | arg = argv[i]; |
726 | 830 | ||
727 | if (conflict_field_name(argv[i], tp->args, i)) { | ||
728 | pr_info("Argument%d name '%s' conflicts with " | ||
729 | "another field.\n", i, argv[i]); | ||
730 | ret = -EINVAL; | ||
731 | goto error; | ||
732 | } | ||
733 | |||
734 | tp->args[i].name = kstrdup(argv[i], GFP_KERNEL); | 831 | tp->args[i].name = kstrdup(argv[i], GFP_KERNEL); |
735 | if (!tp->args[i].name) { | 832 | if (!tp->args[i].name) { |
736 | pr_info("Failed to allocate argument%d name '%s'.\n", | 833 | pr_info("Failed to allocate argument%d name '%s'.\n", |
@@ -738,9 +835,19 @@ static int create_trace_probe(int argc, char **argv) | |||
738 | ret = -ENOMEM; | 835 | ret = -ENOMEM; |
739 | goto error; | 836 | goto error; |
740 | } | 837 | } |
838 | tmp = strchr(tp->args[i].name, ':'); | ||
839 | if (tmp) | ||
840 | *tmp = '_'; /* convert : to _ */ | ||
841 | |||
842 | if (conflict_field_name(tp->args[i].name, tp->args, i)) { | ||
843 | pr_info("Argument%d name '%s' conflicts with " | ||
844 | "another field.\n", i, argv[i]); | ||
845 | ret = -EINVAL; | ||
846 | goto error; | ||
847 | } | ||
741 | 848 | ||
742 | /* Parse fetch argument */ | 849 | /* Parse fetch argument */ |
743 | ret = parse_probe_arg(arg, &tp->args[i].fetch, is_return); | 850 | ret = parse_probe_arg(arg, tp, &tp->args[i], is_return); |
744 | if (ret) { | 851 | if (ret) { |
745 | pr_info("Parse error at argument%d. (%d)\n", i, ret); | 852 | pr_info("Parse error at argument%d. (%d)\n", i, ret); |
746 | kfree(tp->args[i].name); | 853 | kfree(tp->args[i].name); |
@@ -795,8 +902,7 @@ static void probes_seq_stop(struct seq_file *m, void *v) | |||
795 | static int probes_seq_show(struct seq_file *m, void *v) | 902 | static int probes_seq_show(struct seq_file *m, void *v) |
796 | { | 903 | { |
797 | struct trace_probe *tp = v; | 904 | struct trace_probe *tp = v; |
798 | int i, ret; | 905 | int i; |
799 | char buf[MAX_ARGSTR_LEN + 1]; | ||
800 | 906 | ||
801 | seq_printf(m, "%c", probe_is_return(tp) ? 'r' : 'p'); | 907 | seq_printf(m, "%c", probe_is_return(tp) ? 'r' : 'p'); |
802 | seq_printf(m, ":%s/%s", tp->call.class->system, tp->call.name); | 908 | seq_printf(m, ":%s/%s", tp->call.class->system, tp->call.name); |
@@ -808,15 +914,10 @@ static int probes_seq_show(struct seq_file *m, void *v) | |||
808 | else | 914 | else |
809 | seq_printf(m, " %s", probe_symbol(tp)); | 915 | seq_printf(m, " %s", probe_symbol(tp)); |
810 | 916 | ||
811 | for (i = 0; i < tp->nr_args; i++) { | 917 | for (i = 0; i < tp->nr_args; i++) |
812 | ret = probe_arg_string(buf, MAX_ARGSTR_LEN, &tp->args[i].fetch); | 918 | seq_printf(m, " %s=%s", tp->args[i].name, tp->args[i].comm); |
813 | if (ret < 0) { | ||
814 | pr_warning("Argument%d decoding error(%d).\n", i, ret); | ||
815 | return ret; | ||
816 | } | ||
817 | seq_printf(m, " %s=%s", tp->args[i].name, buf); | ||
818 | } | ||
819 | seq_printf(m, "\n"); | 919 | seq_printf(m, "\n"); |
920 | |||
820 | return 0; | 921 | return 0; |
821 | } | 922 | } |
822 | 923 | ||
@@ -946,9 +1047,10 @@ static const struct file_operations kprobe_profile_ops = { | |||
946 | static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) | 1047 | static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) |
947 | { | 1048 | { |
948 | struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp); | 1049 | struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp); |
949 | struct kprobe_trace_entry *entry; | 1050 | struct kprobe_trace_entry_head *entry; |
950 | struct ring_buffer_event *event; | 1051 | struct ring_buffer_event *event; |
951 | struct ring_buffer *buffer; | 1052 | struct ring_buffer *buffer; |
1053 | u8 *data; | ||
952 | int size, i, pc; | 1054 | int size, i, pc; |
953 | unsigned long irq_flags; | 1055 | unsigned long irq_flags; |
954 | struct ftrace_event_call *call = &tp->call; | 1056 | struct ftrace_event_call *call = &tp->call; |
@@ -958,7 +1060,7 @@ static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) | |||
958 | local_save_flags(irq_flags); | 1060 | local_save_flags(irq_flags); |
959 | pc = preempt_count(); | 1061 | pc = preempt_count(); |
960 | 1062 | ||
961 | size = SIZEOF_KPROBE_TRACE_ENTRY(tp->nr_args); | 1063 | size = sizeof(*entry) + tp->size; |
962 | 1064 | ||
963 | event = trace_current_buffer_lock_reserve(&buffer, call->event.type, | 1065 | event = trace_current_buffer_lock_reserve(&buffer, call->event.type, |
964 | size, irq_flags, pc); | 1066 | size, irq_flags, pc); |
@@ -966,10 +1068,10 @@ static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) | |||
966 | return; | 1068 | return; |
967 | 1069 | ||
968 | entry = ring_buffer_event_data(event); | 1070 | entry = ring_buffer_event_data(event); |
969 | entry->nargs = tp->nr_args; | ||
970 | entry->ip = (unsigned long)kp->addr; | 1071 | entry->ip = (unsigned long)kp->addr; |
1072 | data = (u8 *)&entry[1]; | ||
971 | for (i = 0; i < tp->nr_args; i++) | 1073 | for (i = 0; i < tp->nr_args; i++) |
972 | entry->args[i] = call_fetch(&tp->args[i].fetch, regs); | 1074 | call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset); |
973 | 1075 | ||
974 | if (!filter_current_check_discard(buffer, call, entry, event)) | 1076 | if (!filter_current_check_discard(buffer, call, entry, event)) |
975 | trace_nowake_buffer_unlock_commit(buffer, event, irq_flags, pc); | 1077 | trace_nowake_buffer_unlock_commit(buffer, event, irq_flags, pc); |
@@ -980,9 +1082,10 @@ static __kprobes void kretprobe_trace_func(struct kretprobe_instance *ri, | |||
980 | struct pt_regs *regs) | 1082 | struct pt_regs *regs) |
981 | { | 1083 | { |
982 | struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp); | 1084 | struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp); |
983 | struct kretprobe_trace_entry *entry; | 1085 | struct kretprobe_trace_entry_head *entry; |
984 | struct ring_buffer_event *event; | 1086 | struct ring_buffer_event *event; |
985 | struct ring_buffer *buffer; | 1087 | struct ring_buffer *buffer; |
1088 | u8 *data; | ||
986 | int size, i, pc; | 1089 | int size, i, pc; |
987 | unsigned long irq_flags; | 1090 | unsigned long irq_flags; |
988 | struct ftrace_event_call *call = &tp->call; | 1091 | struct ftrace_event_call *call = &tp->call; |
@@ -990,7 +1093,7 @@ static __kprobes void kretprobe_trace_func(struct kretprobe_instance *ri, | |||
990 | local_save_flags(irq_flags); | 1093 | local_save_flags(irq_flags); |
991 | pc = preempt_count(); | 1094 | pc = preempt_count(); |
992 | 1095 | ||
993 | size = SIZEOF_KRETPROBE_TRACE_ENTRY(tp->nr_args); | 1096 | size = sizeof(*entry) + tp->size; |
994 | 1097 | ||
995 | event = trace_current_buffer_lock_reserve(&buffer, call->event.type, | 1098 | event = trace_current_buffer_lock_reserve(&buffer, call->event.type, |
996 | size, irq_flags, pc); | 1099 | size, irq_flags, pc); |
@@ -998,11 +1101,11 @@ static __kprobes void kretprobe_trace_func(struct kretprobe_instance *ri, | |||
998 | return; | 1101 | return; |
999 | 1102 | ||
1000 | entry = ring_buffer_event_data(event); | 1103 | entry = ring_buffer_event_data(event); |
1001 | entry->nargs = tp->nr_args; | ||
1002 | entry->func = (unsigned long)tp->rp.kp.addr; | 1104 | entry->func = (unsigned long)tp->rp.kp.addr; |
1003 | entry->ret_ip = (unsigned long)ri->ret_addr; | 1105 | entry->ret_ip = (unsigned long)ri->ret_addr; |
1106 | data = (u8 *)&entry[1]; | ||
1004 | for (i = 0; i < tp->nr_args; i++) | 1107 | for (i = 0; i < tp->nr_args; i++) |
1005 | entry->args[i] = call_fetch(&tp->args[i].fetch, regs); | 1108 | call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset); |
1006 | 1109 | ||
1007 | if (!filter_current_check_discard(buffer, call, entry, event)) | 1110 | if (!filter_current_check_discard(buffer, call, entry, event)) |
1008 | trace_nowake_buffer_unlock_commit(buffer, event, irq_flags, pc); | 1111 | trace_nowake_buffer_unlock_commit(buffer, event, irq_flags, pc); |
@@ -1013,12 +1116,13 @@ enum print_line_t | |||
1013 | print_kprobe_event(struct trace_iterator *iter, int flags, | 1116 | print_kprobe_event(struct trace_iterator *iter, int flags, |
1014 | struct trace_event *event) | 1117 | struct trace_event *event) |
1015 | { | 1118 | { |
1016 | struct kprobe_trace_entry *field; | 1119 | struct kprobe_trace_entry_head *field; |
1017 | struct trace_seq *s = &iter->seq; | 1120 | struct trace_seq *s = &iter->seq; |
1018 | struct trace_probe *tp; | 1121 | struct trace_probe *tp; |
1122 | u8 *data; | ||
1019 | int i; | 1123 | int i; |
1020 | 1124 | ||
1021 | field = (struct kprobe_trace_entry *)iter->ent; | 1125 | field = (struct kprobe_trace_entry_head *)iter->ent; |
1022 | tp = container_of(event, struct trace_probe, call.event); | 1126 | tp = container_of(event, struct trace_probe, call.event); |
1023 | 1127 | ||
1024 | if (!trace_seq_printf(s, "%s: (", tp->call.name)) | 1128 | if (!trace_seq_printf(s, "%s: (", tp->call.name)) |
@@ -1030,9 +1134,10 @@ print_kprobe_event(struct trace_iterator *iter, int flags, | |||
1030 | if (!trace_seq_puts(s, ")")) | 1134 | if (!trace_seq_puts(s, ")")) |
1031 | goto partial; | 1135 | goto partial; |
1032 | 1136 | ||
1033 | for (i = 0; i < field->nargs; i++) | 1137 | data = (u8 *)&field[1]; |
1034 | if (!trace_seq_printf(s, " %s=%lx", | 1138 | for (i = 0; i < tp->nr_args; i++) |
1035 | tp->args[i].name, field->args[i])) | 1139 | if (!tp->args[i].type->print(s, tp->args[i].name, |
1140 | data + tp->args[i].offset)) | ||
1036 | goto partial; | 1141 | goto partial; |
1037 | 1142 | ||
1038 | if (!trace_seq_puts(s, "\n")) | 1143 | if (!trace_seq_puts(s, "\n")) |
@@ -1047,12 +1152,13 @@ enum print_line_t | |||
1047 | print_kretprobe_event(struct trace_iterator *iter, int flags, | 1152 | print_kretprobe_event(struct trace_iterator *iter, int flags, |
1048 | struct trace_event *event) | 1153 | struct trace_event *event) |
1049 | { | 1154 | { |
1050 | struct kretprobe_trace_entry *field; | 1155 | struct kretprobe_trace_entry_head *field; |
1051 | struct trace_seq *s = &iter->seq; | 1156 | struct trace_seq *s = &iter->seq; |
1052 | struct trace_probe *tp; | 1157 | struct trace_probe *tp; |
1158 | u8 *data; | ||
1053 | int i; | 1159 | int i; |
1054 | 1160 | ||
1055 | field = (struct kretprobe_trace_entry *)iter->ent; | 1161 | field = (struct kretprobe_trace_entry_head *)iter->ent; |
1056 | tp = container_of(event, struct trace_probe, call.event); | 1162 | tp = container_of(event, struct trace_probe, call.event); |
1057 | 1163 | ||
1058 | if (!trace_seq_printf(s, "%s: (", tp->call.name)) | 1164 | if (!trace_seq_printf(s, "%s: (", tp->call.name)) |
@@ -1070,9 +1176,10 @@ print_kretprobe_event(struct trace_iterator *iter, int flags, | |||
1070 | if (!trace_seq_puts(s, ")")) | 1176 | if (!trace_seq_puts(s, ")")) |
1071 | goto partial; | 1177 | goto partial; |
1072 | 1178 | ||
1073 | for (i = 0; i < field->nargs; i++) | 1179 | data = (u8 *)&field[1]; |
1074 | if (!trace_seq_printf(s, " %s=%lx", | 1180 | for (i = 0; i < tp->nr_args; i++) |
1075 | tp->args[i].name, field->args[i])) | 1181 | if (!tp->args[i].type->print(s, tp->args[i].name, |
1182 | data + tp->args[i].offset)) | ||
1076 | goto partial; | 1183 | goto partial; |
1077 | 1184 | ||
1078 | if (!trace_seq_puts(s, "\n")) | 1185 | if (!trace_seq_puts(s, "\n")) |
@@ -1126,29 +1233,43 @@ static int probe_event_raw_init(struct ftrace_event_call *event_call) | |||
1126 | static int kprobe_event_define_fields(struct ftrace_event_call *event_call) | 1233 | static int kprobe_event_define_fields(struct ftrace_event_call *event_call) |
1127 | { | 1234 | { |
1128 | int ret, i; | 1235 | int ret, i; |
1129 | struct kprobe_trace_entry field; | 1236 | struct kprobe_trace_entry_head field; |
1130 | struct trace_probe *tp = (struct trace_probe *)event_call->data; | 1237 | struct trace_probe *tp = (struct trace_probe *)event_call->data; |
1131 | 1238 | ||
1132 | DEFINE_FIELD(unsigned long, ip, FIELD_STRING_IP, 0); | 1239 | DEFINE_FIELD(unsigned long, ip, FIELD_STRING_IP, 0); |
1133 | DEFINE_FIELD(int, nargs, FIELD_STRING_NARGS, 1); | ||
1134 | /* Set argument names as fields */ | 1240 | /* Set argument names as fields */ |
1135 | for (i = 0; i < tp->nr_args; i++) | 1241 | for (i = 0; i < tp->nr_args; i++) { |
1136 | DEFINE_FIELD(unsigned long, args[i], tp->args[i].name, 0); | 1242 | ret = trace_define_field(event_call, tp->args[i].type->name, |
1243 | tp->args[i].name, | ||
1244 | sizeof(field) + tp->args[i].offset, | ||
1245 | tp->args[i].type->size, | ||
1246 | tp->args[i].type->is_signed, | ||
1247 | FILTER_OTHER); | ||
1248 | if (ret) | ||
1249 | return ret; | ||
1250 | } | ||
1137 | return 0; | 1251 | return 0; |
1138 | } | 1252 | } |
1139 | 1253 | ||
1140 | static int kretprobe_event_define_fields(struct ftrace_event_call *event_call) | 1254 | static int kretprobe_event_define_fields(struct ftrace_event_call *event_call) |
1141 | { | 1255 | { |
1142 | int ret, i; | 1256 | int ret, i; |
1143 | struct kretprobe_trace_entry field; | 1257 | struct kretprobe_trace_entry_head field; |
1144 | struct trace_probe *tp = (struct trace_probe *)event_call->data; | 1258 | struct trace_probe *tp = (struct trace_probe *)event_call->data; |
1145 | 1259 | ||
1146 | DEFINE_FIELD(unsigned long, func, FIELD_STRING_FUNC, 0); | 1260 | DEFINE_FIELD(unsigned long, func, FIELD_STRING_FUNC, 0); |
1147 | DEFINE_FIELD(unsigned long, ret_ip, FIELD_STRING_RETIP, 0); | 1261 | DEFINE_FIELD(unsigned long, ret_ip, FIELD_STRING_RETIP, 0); |
1148 | DEFINE_FIELD(int, nargs, FIELD_STRING_NARGS, 1); | ||
1149 | /* Set argument names as fields */ | 1262 | /* Set argument names as fields */ |
1150 | for (i = 0; i < tp->nr_args; i++) | 1263 | for (i = 0; i < tp->nr_args; i++) { |
1151 | DEFINE_FIELD(unsigned long, args[i], tp->args[i].name, 0); | 1264 | ret = trace_define_field(event_call, tp->args[i].type->name, |
1265 | tp->args[i].name, | ||
1266 | sizeof(field) + tp->args[i].offset, | ||
1267 | tp->args[i].type->size, | ||
1268 | tp->args[i].type->is_signed, | ||
1269 | FILTER_OTHER); | ||
1270 | if (ret) | ||
1271 | return ret; | ||
1272 | } | ||
1152 | return 0; | 1273 | return 0; |
1153 | } | 1274 | } |
1154 | 1275 | ||
@@ -1173,8 +1294,8 @@ static int __set_print_fmt(struct trace_probe *tp, char *buf, int len) | |||
1173 | pos += snprintf(buf + pos, LEN_OR_ZERO, "\"%s", fmt); | 1294 | pos += snprintf(buf + pos, LEN_OR_ZERO, "\"%s", fmt); |
1174 | 1295 | ||
1175 | for (i = 0; i < tp->nr_args; i++) { | 1296 | for (i = 0; i < tp->nr_args; i++) { |
1176 | pos += snprintf(buf + pos, LEN_OR_ZERO, " %s=%%lx", | 1297 | pos += snprintf(buf + pos, LEN_OR_ZERO, " %s=%s", |
1177 | tp->args[i].name); | 1298 | tp->args[i].name, tp->args[i].type->fmt); |
1178 | } | 1299 | } |
1179 | 1300 | ||
1180 | pos += snprintf(buf + pos, LEN_OR_ZERO, "\", %s", arg); | 1301 | pos += snprintf(buf + pos, LEN_OR_ZERO, "\", %s", arg); |
@@ -1216,12 +1337,13 @@ static __kprobes void kprobe_perf_func(struct kprobe *kp, | |||
1216 | { | 1337 | { |
1217 | struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp); | 1338 | struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp); |
1218 | struct ftrace_event_call *call = &tp->call; | 1339 | struct ftrace_event_call *call = &tp->call; |
1219 | struct kprobe_trace_entry *entry; | 1340 | struct kprobe_trace_entry_head *entry; |
1341 | u8 *data; | ||
1220 | int size, __size, i; | 1342 | int size, __size, i; |
1221 | unsigned long irq_flags; | 1343 | unsigned long irq_flags; |
1222 | int rctx; | 1344 | int rctx; |
1223 | 1345 | ||
1224 | __size = SIZEOF_KPROBE_TRACE_ENTRY(tp->nr_args); | 1346 | __size = sizeof(*entry) + tp->size; |
1225 | size = ALIGN(__size + sizeof(u32), sizeof(u64)); | 1347 | size = ALIGN(__size + sizeof(u32), sizeof(u64)); |
1226 | size -= sizeof(u32); | 1348 | size -= sizeof(u32); |
1227 | if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, | 1349 | if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, |
@@ -1233,10 +1355,10 @@ static __kprobes void kprobe_perf_func(struct kprobe *kp, | |||
1233 | if (!entry) | 1355 | if (!entry) |
1234 | return; | 1356 | return; |
1235 | 1357 | ||
1236 | entry->nargs = tp->nr_args; | ||
1237 | entry->ip = (unsigned long)kp->addr; | 1358 | entry->ip = (unsigned long)kp->addr; |
1359 | data = (u8 *)&entry[1]; | ||
1238 | for (i = 0; i < tp->nr_args; i++) | 1360 | for (i = 0; i < tp->nr_args; i++) |
1239 | entry->args[i] = call_fetch(&tp->args[i].fetch, regs); | 1361 | call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset); |
1240 | 1362 | ||
1241 | perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, irq_flags, regs); | 1363 | perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, irq_flags, regs); |
1242 | } | 1364 | } |
@@ -1247,12 +1369,13 @@ static __kprobes void kretprobe_perf_func(struct kretprobe_instance *ri, | |||
1247 | { | 1369 | { |
1248 | struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp); | 1370 | struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp); |
1249 | struct ftrace_event_call *call = &tp->call; | 1371 | struct ftrace_event_call *call = &tp->call; |
1250 | struct kretprobe_trace_entry *entry; | 1372 | struct kretprobe_trace_entry_head *entry; |
1373 | u8 *data; | ||
1251 | int size, __size, i; | 1374 | int size, __size, i; |
1252 | unsigned long irq_flags; | 1375 | unsigned long irq_flags; |
1253 | int rctx; | 1376 | int rctx; |
1254 | 1377 | ||
1255 | __size = SIZEOF_KRETPROBE_TRACE_ENTRY(tp->nr_args); | 1378 | __size = sizeof(*entry) + tp->size; |
1256 | size = ALIGN(__size + sizeof(u32), sizeof(u64)); | 1379 | size = ALIGN(__size + sizeof(u32), sizeof(u64)); |
1257 | size -= sizeof(u32); | 1380 | size -= sizeof(u32); |
1258 | if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, | 1381 | if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, |
@@ -1264,11 +1387,11 @@ static __kprobes void kretprobe_perf_func(struct kretprobe_instance *ri, | |||
1264 | if (!entry) | 1387 | if (!entry) |
1265 | return; | 1388 | return; |
1266 | 1389 | ||
1267 | entry->nargs = tp->nr_args; | ||
1268 | entry->func = (unsigned long)tp->rp.kp.addr; | 1390 | entry->func = (unsigned long)tp->rp.kp.addr; |
1269 | entry->ret_ip = (unsigned long)ri->ret_addr; | 1391 | entry->ret_ip = (unsigned long)ri->ret_addr; |
1392 | data = (u8 *)&entry[1]; | ||
1270 | for (i = 0; i < tp->nr_args; i++) | 1393 | for (i = 0; i < tp->nr_args; i++) |
1271 | entry->args[i] = call_fetch(&tp->args[i].fetch, regs); | 1394 | call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset); |
1272 | 1395 | ||
1273 | perf_trace_buf_submit(entry, size, rctx, entry->ret_ip, 1, | 1396 | perf_trace_buf_submit(entry, size, rctx, entry->ret_ip, 1, |
1274 | irq_flags, regs); | 1397 | irq_flags, regs); |