Commit | Line | Data |
---|---|---|
8ab83f56 SD |
1 | /* |
2 | * Common code 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.c 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 "trace_probe.h" | |
26 | ||
27 | const char *reserved_field_names[] = { | |
28 | "common_type", | |
29 | "common_flags", | |
30 | "common_preempt_count", | |
31 | "common_pid", | |
32 | "common_tgid", | |
33 | FIELD_STRING_IP, | |
34 | FIELD_STRING_RETIP, | |
35 | FIELD_STRING_FUNC, | |
36 | }; | |
37 | ||
38 | /* Printing function type */ | |
39 | #define PRINT_TYPE_FUNC_NAME(type) print_type_##type | |
40 | #define PRINT_TYPE_FMT_NAME(type) print_type_format_##type | |
41 | ||
42 | /* Printing in basic type function template */ | |
43 | #define DEFINE_BASIC_PRINT_TYPE_FUNC(type, fmt, cast) \ | |
44 | static __kprobes int PRINT_TYPE_FUNC_NAME(type)(struct trace_seq *s, \ | |
45 | const char *name, \ | |
46 | void *data, void *ent)\ | |
47 | { \ | |
48 | return trace_seq_printf(s, " %s=" fmt, name, (cast)*(type *)data);\ | |
49 | } \ | |
50 | static const char PRINT_TYPE_FMT_NAME(type)[] = fmt; | |
51 | ||
52 | DEFINE_BASIC_PRINT_TYPE_FUNC(u8, "%x", unsigned int) | |
53 | DEFINE_BASIC_PRINT_TYPE_FUNC(u16, "%x", unsigned int) | |
54 | DEFINE_BASIC_PRINT_TYPE_FUNC(u32, "%lx", unsigned long) | |
55 | DEFINE_BASIC_PRINT_TYPE_FUNC(u64, "%llx", unsigned long long) | |
56 | DEFINE_BASIC_PRINT_TYPE_FUNC(s8, "%d", int) | |
57 | DEFINE_BASIC_PRINT_TYPE_FUNC(s16, "%d", int) | |
58 | DEFINE_BASIC_PRINT_TYPE_FUNC(s32, "%ld", long) | |
59 | DEFINE_BASIC_PRINT_TYPE_FUNC(s64, "%lld", long long) | |
60 | ||
61 | static inline void *get_rloc_data(u32 *dl) | |
62 | { | |
63 | return (u8 *)dl + get_rloc_offs(*dl); | |
64 | } | |
65 | ||
66 | /* For data_loc conversion */ | |
67 | static inline void *get_loc_data(u32 *dl, void *ent) | |
68 | { | |
69 | return (u8 *)ent + get_rloc_offs(*dl); | |
70 | } | |
71 | ||
72 | /* For defining macros, define string/string_size types */ | |
73 | typedef u32 string; | |
74 | typedef u32 string_size; | |
75 | ||
76 | /* Print type function for string type */ | |
77 | static __kprobes int PRINT_TYPE_FUNC_NAME(string)(struct trace_seq *s, | |
78 | const char *name, | |
79 | void *data, void *ent) | |
80 | { | |
81 | int len = *(u32 *)data >> 16; | |
82 | ||
83 | if (!len) | |
84 | return trace_seq_printf(s, " %s=(fault)", name); | |
85 | else | |
86 | return trace_seq_printf(s, " %s=\"%s\"", name, | |
87 | (const char *)get_loc_data(data, ent)); | |
88 | } | |
89 | ||
90 | static const char PRINT_TYPE_FMT_NAME(string)[] = "\\\"%s\\\""; | |
91 | ||
92 | #define FETCH_FUNC_NAME(method, type) fetch_##method##_##type | |
93 | /* | |
94 | * Define macro for basic types - we don't need to define s* types, because | |
95 | * we have to care only about bitwidth at recording time. | |
96 | */ | |
97 | #define DEFINE_BASIC_FETCH_FUNCS(method) \ | |
98 | DEFINE_FETCH_##method(u8) \ | |
99 | DEFINE_FETCH_##method(u16) \ | |
100 | DEFINE_FETCH_##method(u32) \ | |
101 | DEFINE_FETCH_##method(u64) | |
102 | ||
103 | #define CHECK_FETCH_FUNCS(method, fn) \ | |
104 | (((FETCH_FUNC_NAME(method, u8) == fn) || \ | |
105 | (FETCH_FUNC_NAME(method, u16) == fn) || \ | |
106 | (FETCH_FUNC_NAME(method, u32) == fn) || \ | |
107 | (FETCH_FUNC_NAME(method, u64) == fn) || \ | |
108 | (FETCH_FUNC_NAME(method, string) == fn) || \ | |
109 | (FETCH_FUNC_NAME(method, string_size) == fn)) \ | |
110 | && (fn != NULL)) | |
111 | ||
112 | /* Data fetch function templates */ | |
113 | #define DEFINE_FETCH_reg(type) \ | |
114 | static __kprobes void FETCH_FUNC_NAME(reg, type)(struct pt_regs *regs, \ | |
115 | void *offset, void *dest) \ | |
116 | { \ | |
117 | *(type *)dest = (type)regs_get_register(regs, \ | |
118 | (unsigned int)((unsigned long)offset)); \ | |
119 | } | |
120 | DEFINE_BASIC_FETCH_FUNCS(reg) | |
121 | /* No string on the register */ | |
122 | #define fetch_reg_string NULL | |
123 | #define fetch_reg_string_size NULL | |
124 | ||
125 | #define DEFINE_FETCH_stack(type) \ | |
126 | static __kprobes void FETCH_FUNC_NAME(stack, type)(struct pt_regs *regs,\ | |
127 | void *offset, void *dest) \ | |
128 | { \ | |
129 | *(type *)dest = (type)regs_get_kernel_stack_nth(regs, \ | |
130 | (unsigned int)((unsigned long)offset)); \ | |
131 | } | |
132 | DEFINE_BASIC_FETCH_FUNCS(stack) | |
133 | /* No string on the stack entry */ | |
134 | #define fetch_stack_string NULL | |
135 | #define fetch_stack_string_size NULL | |
136 | ||
137 | #define DEFINE_FETCH_retval(type) \ | |
138 | static __kprobes void FETCH_FUNC_NAME(retval, type)(struct pt_regs *regs,\ | |
139 | void *dummy, void *dest) \ | |
140 | { \ | |
141 | *(type *)dest = (type)regs_return_value(regs); \ | |
142 | } | |
143 | DEFINE_BASIC_FETCH_FUNCS(retval) | |
144 | /* No string on the retval */ | |
145 | #define fetch_retval_string NULL | |
146 | #define fetch_retval_string_size NULL | |
147 | ||
148 | #define DEFINE_FETCH_memory(type) \ | |
149 | static __kprobes void FETCH_FUNC_NAME(memory, type)(struct pt_regs *regs,\ | |
150 | void *addr, void *dest) \ | |
151 | { \ | |
152 | type retval; \ | |
153 | if (probe_kernel_address(addr, retval)) \ | |
154 | *(type *)dest = 0; \ | |
155 | else \ | |
156 | *(type *)dest = retval; \ | |
157 | } | |
158 | DEFINE_BASIC_FETCH_FUNCS(memory) | |
159 | /* | |
160 | * Fetch a null-terminated string. Caller MUST set *(u32 *)dest with max | |
161 | * length and relative data location. | |
162 | */ | |
163 | static __kprobes void FETCH_FUNC_NAME(memory, string)(struct pt_regs *regs, | |
164 | void *addr, void *dest) | |
165 | { | |
166 | long ret; | |
167 | int maxlen = get_rloc_len(*(u32 *)dest); | |
168 | u8 *dst = get_rloc_data(dest); | |
169 | u8 *src = addr; | |
170 | mm_segment_t old_fs = get_fs(); | |
171 | ||
172 | if (!maxlen) | |
173 | return; | |
174 | ||
175 | /* | |
176 | * Try to get string again, since the string can be changed while | |
177 | * probing. | |
178 | */ | |
179 | set_fs(KERNEL_DS); | |
180 | pagefault_disable(); | |
181 | ||
182 | do | |
183 | ret = __copy_from_user_inatomic(dst++, src++, 1); | |
184 | while (dst[-1] && ret == 0 && src - (u8 *)addr < maxlen); | |
185 | ||
186 | dst[-1] = '\0'; | |
187 | pagefault_enable(); | |
188 | set_fs(old_fs); | |
189 | ||
190 | if (ret < 0) { /* Failed to fetch string */ | |
191 | ((u8 *)get_rloc_data(dest))[0] = '\0'; | |
192 | *(u32 *)dest = make_data_rloc(0, get_rloc_offs(*(u32 *)dest)); | |
193 | } else { | |
194 | *(u32 *)dest = make_data_rloc(src - (u8 *)addr, | |
195 | get_rloc_offs(*(u32 *)dest)); | |
196 | } | |
197 | } | |
198 | ||
199 | /* Return the length of string -- including null terminal byte */ | |
200 | static __kprobes void FETCH_FUNC_NAME(memory, string_size)(struct pt_regs *regs, | |
201 | void *addr, void *dest) | |
202 | { | |
203 | mm_segment_t old_fs; | |
204 | int ret, len = 0; | |
205 | u8 c; | |
206 | ||
207 | old_fs = get_fs(); | |
208 | set_fs(KERNEL_DS); | |
209 | pagefault_disable(); | |
210 | ||
211 | do { | |
212 | ret = __copy_from_user_inatomic(&c, (u8 *)addr + len, 1); | |
213 | len++; | |
214 | } while (c && ret == 0 && len < MAX_STRING_SIZE); | |
215 | ||
216 | pagefault_enable(); | |
217 | set_fs(old_fs); | |
218 | ||
219 | if (ret < 0) /* Failed to check the length */ | |
220 | *(u32 *)dest = 0; | |
221 | else | |
222 | *(u32 *)dest = len; | |
223 | } | |
224 | ||
225 | /* Memory fetching by symbol */ | |
226 | struct symbol_cache { | |
227 | char *symbol; | |
228 | long offset; | |
229 | unsigned long addr; | |
230 | }; | |
231 | ||
232 | static unsigned long update_symbol_cache(struct symbol_cache *sc) | |
233 | { | |
234 | sc->addr = (unsigned long)kallsyms_lookup_name(sc->symbol); | |
235 | ||
236 | if (sc->addr) | |
237 | sc->addr += sc->offset; | |
238 | ||
239 | return sc->addr; | |
240 | } | |
241 | ||
242 | static void free_symbol_cache(struct symbol_cache *sc) | |
243 | { | |
244 | kfree(sc->symbol); | |
245 | kfree(sc); | |
246 | } | |
247 | ||
248 | static struct symbol_cache *alloc_symbol_cache(const char *sym, long offset) | |
249 | { | |
250 | struct symbol_cache *sc; | |
251 | ||
252 | if (!sym || strlen(sym) == 0) | |
253 | return NULL; | |
254 | ||
255 | sc = kzalloc(sizeof(struct symbol_cache), GFP_KERNEL); | |
256 | if (!sc) | |
257 | return NULL; | |
258 | ||
259 | sc->symbol = kstrdup(sym, GFP_KERNEL); | |
260 | if (!sc->symbol) { | |
261 | kfree(sc); | |
262 | return NULL; | |
263 | } | |
264 | sc->offset = offset; | |
265 | update_symbol_cache(sc); | |
266 | ||
267 | return sc; | |
268 | } | |
269 | ||
270 | #define DEFINE_FETCH_symbol(type) \ | |
271 | static __kprobes void FETCH_FUNC_NAME(symbol, type)(struct pt_regs *regs,\ | |
272 | void *data, void *dest) \ | |
273 | { \ | |
274 | struct symbol_cache *sc = data; \ | |
275 | if (sc->addr) \ | |
276 | fetch_memory_##type(regs, (void *)sc->addr, dest); \ | |
277 | else \ | |
278 | *(type *)dest = 0; \ | |
279 | } | |
280 | DEFINE_BASIC_FETCH_FUNCS(symbol) | |
281 | DEFINE_FETCH_symbol(string) | |
282 | DEFINE_FETCH_symbol(string_size) | |
283 | ||
284 | /* Dereference memory access function */ | |
285 | struct deref_fetch_param { | |
286 | struct fetch_param orig; | |
287 | long offset; | |
288 | }; | |
289 | ||
290 | #define DEFINE_FETCH_deref(type) \ | |
291 | static __kprobes void FETCH_FUNC_NAME(deref, type)(struct pt_regs *regs,\ | |
292 | void *data, void *dest) \ | |
293 | { \ | |
294 | struct deref_fetch_param *dprm = data; \ | |
295 | unsigned long addr; \ | |
296 | call_fetch(&dprm->orig, regs, &addr); \ | |
297 | if (addr) { \ | |
298 | addr += dprm->offset; \ | |
299 | fetch_memory_##type(regs, (void *)addr, dest); \ | |
300 | } else \ | |
301 | *(type *)dest = 0; \ | |
302 | } | |
303 | DEFINE_BASIC_FETCH_FUNCS(deref) | |
304 | DEFINE_FETCH_deref(string) | |
305 | DEFINE_FETCH_deref(string_size) | |
306 | ||
307 | static __kprobes void update_deref_fetch_param(struct deref_fetch_param *data) | |
308 | { | |
309 | if (CHECK_FETCH_FUNCS(deref, data->orig.fn)) | |
310 | update_deref_fetch_param(data->orig.data); | |
311 | else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn)) | |
312 | update_symbol_cache(data->orig.data); | |
313 | } | |
314 | ||
315 | static __kprobes void free_deref_fetch_param(struct deref_fetch_param *data) | |
316 | { | |
317 | if (CHECK_FETCH_FUNCS(deref, data->orig.fn)) | |
318 | free_deref_fetch_param(data->orig.data); | |
319 | else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn)) | |
320 | free_symbol_cache(data->orig.data); | |
321 | kfree(data); | |
322 | } | |
323 | ||
324 | /* Bitfield fetch function */ | |
325 | struct bitfield_fetch_param { | |
326 | struct fetch_param orig; | |
327 | unsigned char hi_shift; | |
328 | unsigned char low_shift; | |
329 | }; | |
330 | ||
331 | #define DEFINE_FETCH_bitfield(type) \ | |
332 | static __kprobes void FETCH_FUNC_NAME(bitfield, type)(struct pt_regs *regs,\ | |
333 | void *data, void *dest) \ | |
334 | { \ | |
335 | struct bitfield_fetch_param *bprm = data; \ | |
336 | type buf = 0; \ | |
337 | call_fetch(&bprm->orig, regs, &buf); \ | |
338 | if (buf) { \ | |
339 | buf <<= bprm->hi_shift; \ | |
340 | buf >>= bprm->low_shift; \ | |
341 | } \ | |
342 | *(type *)dest = buf; \ | |
343 | } | |
344 | ||
345 | DEFINE_BASIC_FETCH_FUNCS(bitfield) | |
346 | #define fetch_bitfield_string NULL | |
347 | #define fetch_bitfield_string_size NULL | |
348 | ||
349 | static __kprobes void | |
350 | update_bitfield_fetch_param(struct bitfield_fetch_param *data) | |
351 | { | |
352 | /* | |
353 | * Don't check the bitfield itself, because this must be the | |
354 | * last fetch function. | |
355 | */ | |
356 | if (CHECK_FETCH_FUNCS(deref, data->orig.fn)) | |
357 | update_deref_fetch_param(data->orig.data); | |
358 | else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn)) | |
359 | update_symbol_cache(data->orig.data); | |
360 | } | |
361 | ||
362 | static __kprobes void | |
363 | free_bitfield_fetch_param(struct bitfield_fetch_param *data) | |
364 | { | |
365 | /* | |
366 | * Don't check the bitfield itself, because this must be the | |
367 | * last fetch function. | |
368 | */ | |
369 | if (CHECK_FETCH_FUNCS(deref, data->orig.fn)) | |
370 | free_deref_fetch_param(data->orig.data); | |
371 | else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn)) | |
372 | free_symbol_cache(data->orig.data); | |
373 | ||
374 | kfree(data); | |
375 | } | |
376 | ||
377 | /* Default (unsigned long) fetch type */ | |
378 | #define __DEFAULT_FETCH_TYPE(t) u##t | |
379 | #define _DEFAULT_FETCH_TYPE(t) __DEFAULT_FETCH_TYPE(t) | |
380 | #define DEFAULT_FETCH_TYPE _DEFAULT_FETCH_TYPE(BITS_PER_LONG) | |
381 | #define DEFAULT_FETCH_TYPE_STR __stringify(DEFAULT_FETCH_TYPE) | |
382 | ||
383 | #define ASSIGN_FETCH_FUNC(method, type) \ | |
384 | [FETCH_MTD_##method] = FETCH_FUNC_NAME(method, type) | |
385 | ||
386 | #define __ASSIGN_FETCH_TYPE(_name, ptype, ftype, _size, sign, _fmttype) \ | |
387 | {.name = _name, \ | |
388 | .size = _size, \ | |
389 | .is_signed = sign, \ | |
390 | .print = PRINT_TYPE_FUNC_NAME(ptype), \ | |
391 | .fmt = PRINT_TYPE_FMT_NAME(ptype), \ | |
392 | .fmttype = _fmttype, \ | |
393 | .fetch = { \ | |
394 | ASSIGN_FETCH_FUNC(reg, ftype), \ | |
395 | ASSIGN_FETCH_FUNC(stack, ftype), \ | |
396 | ASSIGN_FETCH_FUNC(retval, ftype), \ | |
397 | ASSIGN_FETCH_FUNC(memory, ftype), \ | |
398 | ASSIGN_FETCH_FUNC(symbol, ftype), \ | |
399 | ASSIGN_FETCH_FUNC(deref, ftype), \ | |
400 | ASSIGN_FETCH_FUNC(bitfield, ftype), \ | |
401 | } \ | |
402 | } | |
403 | ||
404 | #define ASSIGN_FETCH_TYPE(ptype, ftype, sign) \ | |
405 | __ASSIGN_FETCH_TYPE(#ptype, ptype, ftype, sizeof(ftype), sign, #ptype) | |
406 | ||
407 | #define FETCH_TYPE_STRING 0 | |
408 | #define FETCH_TYPE_STRSIZE 1 | |
409 | ||
410 | /* Fetch type information table */ | |
411 | static const struct fetch_type fetch_type_table[] = { | |
412 | /* Special types */ | |
413 | [FETCH_TYPE_STRING] = __ASSIGN_FETCH_TYPE("string", string, string, | |
414 | sizeof(u32), 1, "__data_loc char[]"), | |
415 | [FETCH_TYPE_STRSIZE] = __ASSIGN_FETCH_TYPE("string_size", u32, | |
416 | string_size, sizeof(u32), 0, "u32"), | |
417 | /* Basic types */ | |
418 | ASSIGN_FETCH_TYPE(u8, u8, 0), | |
419 | ASSIGN_FETCH_TYPE(u16, u16, 0), | |
420 | ASSIGN_FETCH_TYPE(u32, u32, 0), | |
421 | ASSIGN_FETCH_TYPE(u64, u64, 0), | |
422 | ASSIGN_FETCH_TYPE(s8, u8, 1), | |
423 | ASSIGN_FETCH_TYPE(s16, u16, 1), | |
424 | ASSIGN_FETCH_TYPE(s32, u32, 1), | |
425 | ASSIGN_FETCH_TYPE(s64, u64, 1), | |
426 | }; | |
427 | ||
428 | static const struct fetch_type *find_fetch_type(const char *type) | |
429 | { | |
430 | int i; | |
431 | ||
432 | if (!type) | |
433 | type = DEFAULT_FETCH_TYPE_STR; | |
434 | ||
435 | /* Special case: bitfield */ | |
436 | if (*type == 'b') { | |
437 | unsigned long bs; | |
438 | ||
439 | type = strchr(type, '/'); | |
440 | if (!type) | |
441 | goto fail; | |
442 | ||
443 | type++; | |
bcd83ea6 | 444 | if (kstrtoul(type, 0, &bs)) |
8ab83f56 SD |
445 | goto fail; |
446 | ||
447 | switch (bs) { | |
448 | case 8: | |
449 | return find_fetch_type("u8"); | |
450 | case 16: | |
451 | return find_fetch_type("u16"); | |
452 | case 32: | |
453 | return find_fetch_type("u32"); | |
454 | case 64: | |
455 | return find_fetch_type("u64"); | |
456 | default: | |
457 | goto fail; | |
458 | } | |
459 | } | |
460 | ||
461 | for (i = 0; i < ARRAY_SIZE(fetch_type_table); i++) | |
462 | if (strcmp(type, fetch_type_table[i].name) == 0) | |
463 | return &fetch_type_table[i]; | |
464 | ||
465 | fail: | |
466 | return NULL; | |
467 | } | |
468 | ||
469 | /* Special function : only accept unsigned long */ | |
470 | static __kprobes void fetch_stack_address(struct pt_regs *regs, | |
471 | void *dummy, void *dest) | |
472 | { | |
473 | *(unsigned long *)dest = kernel_stack_pointer(regs); | |
474 | } | |
475 | ||
476 | static fetch_func_t get_fetch_size_function(const struct fetch_type *type, | |
477 | fetch_func_t orig_fn) | |
478 | { | |
479 | int i; | |
480 | ||
481 | if (type != &fetch_type_table[FETCH_TYPE_STRING]) | |
482 | return NULL; /* Only string type needs size function */ | |
483 | ||
484 | for (i = 0; i < FETCH_MTD_END; i++) | |
485 | if (type->fetch[i] == orig_fn) | |
486 | return fetch_type_table[FETCH_TYPE_STRSIZE].fetch[i]; | |
487 | ||
488 | WARN_ON(1); /* This should not happen */ | |
489 | ||
490 | return NULL; | |
491 | } | |
492 | ||
493 | /* Split symbol and offset. */ | |
494 | int traceprobe_split_symbol_offset(char *symbol, unsigned long *offset) | |
495 | { | |
496 | char *tmp; | |
497 | int ret; | |
498 | ||
499 | if (!offset) | |
500 | return -EINVAL; | |
501 | ||
502 | tmp = strchr(symbol, '+'); | |
503 | if (tmp) { | |
bcd83ea6 DW |
504 | /* skip sign because kstrtoul doesn't accept '+' */ |
505 | ret = kstrtoul(tmp + 1, 0, offset); | |
8ab83f56 SD |
506 | if (ret) |
507 | return ret; | |
508 | ||
509 | *tmp = '\0'; | |
510 | } else | |
511 | *offset = 0; | |
512 | ||
513 | return 0; | |
514 | } | |
515 | ||
516 | #define PARAM_MAX_STACK (THREAD_SIZE / sizeof(unsigned long)) | |
517 | ||
518 | static int parse_probe_vars(char *arg, const struct fetch_type *t, | |
519 | struct fetch_param *f, bool is_return) | |
520 | { | |
521 | int ret = 0; | |
522 | unsigned long param; | |
523 | ||
524 | if (strcmp(arg, "retval") == 0) { | |
525 | if (is_return) | |
526 | f->fn = t->fetch[FETCH_MTD_retval]; | |
527 | else | |
528 | ret = -EINVAL; | |
529 | } else if (strncmp(arg, "stack", 5) == 0) { | |
530 | if (arg[5] == '\0') { | |
531 | if (strcmp(t->name, DEFAULT_FETCH_TYPE_STR) == 0) | |
532 | f->fn = fetch_stack_address; | |
533 | else | |
534 | ret = -EINVAL; | |
535 | } else if (isdigit(arg[5])) { | |
bcd83ea6 | 536 | ret = kstrtoul(arg + 5, 10, ¶m); |
8ab83f56 SD |
537 | if (ret || param > PARAM_MAX_STACK) |
538 | ret = -EINVAL; | |
539 | else { | |
540 | f->fn = t->fetch[FETCH_MTD_stack]; | |
541 | f->data = (void *)param; | |
542 | } | |
543 | } else | |
544 | ret = -EINVAL; | |
545 | } else | |
546 | ret = -EINVAL; | |
547 | ||
548 | return ret; | |
549 | } | |
550 | ||
551 | /* Recursive argument parser */ | |
552 | static int parse_probe_arg(char *arg, const struct fetch_type *t, | |
f3f096cf | 553 | struct fetch_param *f, bool is_return, bool is_kprobe) |
8ab83f56 SD |
554 | { |
555 | unsigned long param; | |
556 | long offset; | |
557 | char *tmp; | |
558 | int ret; | |
559 | ||
560 | ret = 0; | |
f3f096cf SD |
561 | |
562 | /* Until uprobe_events supports only reg arguments */ | |
563 | if (!is_kprobe && arg[0] != '%') | |
564 | return -EINVAL; | |
565 | ||
8ab83f56 SD |
566 | switch (arg[0]) { |
567 | case '$': | |
568 | ret = parse_probe_vars(arg + 1, t, f, is_return); | |
569 | break; | |
570 | ||
571 | case '%': /* named register */ | |
572 | ret = regs_query_register_offset(arg + 1); | |
573 | if (ret >= 0) { | |
574 | f->fn = t->fetch[FETCH_MTD_reg]; | |
575 | f->data = (void *)(unsigned long)ret; | |
576 | ret = 0; | |
577 | } | |
578 | break; | |
579 | ||
580 | case '@': /* memory or symbol */ | |
581 | if (isdigit(arg[1])) { | |
bcd83ea6 | 582 | ret = kstrtoul(arg + 1, 0, ¶m); |
8ab83f56 SD |
583 | if (ret) |
584 | break; | |
585 | ||
586 | f->fn = t->fetch[FETCH_MTD_memory]; | |
587 | f->data = (void *)param; | |
588 | } else { | |
589 | ret = traceprobe_split_symbol_offset(arg + 1, &offset); | |
590 | if (ret) | |
591 | break; | |
592 | ||
593 | f->data = alloc_symbol_cache(arg + 1, offset); | |
594 | if (f->data) | |
595 | f->fn = t->fetch[FETCH_MTD_symbol]; | |
596 | } | |
597 | break; | |
598 | ||
599 | case '+': /* deref memory */ | |
bcd83ea6 | 600 | arg++; /* Skip '+', because kstrtol() rejects it. */ |
8ab83f56 SD |
601 | case '-': |
602 | tmp = strchr(arg, '('); | |
603 | if (!tmp) | |
604 | break; | |
605 | ||
606 | *tmp = '\0'; | |
bcd83ea6 | 607 | ret = kstrtol(arg, 0, &offset); |
8ab83f56 SD |
608 | |
609 | if (ret) | |
610 | break; | |
611 | ||
612 | arg = tmp + 1; | |
613 | tmp = strrchr(arg, ')'); | |
614 | ||
615 | if (tmp) { | |
616 | struct deref_fetch_param *dprm; | |
617 | const struct fetch_type *t2; | |
618 | ||
619 | t2 = find_fetch_type(NULL); | |
620 | *tmp = '\0'; | |
621 | dprm = kzalloc(sizeof(struct deref_fetch_param), GFP_KERNEL); | |
622 | ||
623 | if (!dprm) | |
624 | return -ENOMEM; | |
625 | ||
626 | dprm->offset = offset; | |
f3f096cf SD |
627 | ret = parse_probe_arg(arg, t2, &dprm->orig, is_return, |
628 | is_kprobe); | |
8ab83f56 SD |
629 | if (ret) |
630 | kfree(dprm); | |
631 | else { | |
632 | f->fn = t->fetch[FETCH_MTD_deref]; | |
633 | f->data = (void *)dprm; | |
634 | } | |
635 | } | |
636 | break; | |
637 | } | |
638 | if (!ret && !f->fn) { /* Parsed, but do not find fetch method */ | |
639 | pr_info("%s type has no corresponding fetch method.\n", t->name); | |
640 | ret = -EINVAL; | |
641 | } | |
642 | ||
643 | return ret; | |
644 | } | |
645 | ||
646 | #define BYTES_TO_BITS(nb) ((BITS_PER_LONG * (nb)) / sizeof(long)) | |
647 | ||
648 | /* Bitfield type needs to be parsed into a fetch function */ | |
649 | static int __parse_bitfield_probe_arg(const char *bf, | |
650 | const struct fetch_type *t, | |
651 | struct fetch_param *f) | |
652 | { | |
653 | struct bitfield_fetch_param *bprm; | |
654 | unsigned long bw, bo; | |
655 | char *tail; | |
656 | ||
657 | if (*bf != 'b') | |
658 | return 0; | |
659 | ||
660 | bprm = kzalloc(sizeof(*bprm), GFP_KERNEL); | |
661 | if (!bprm) | |
662 | return -ENOMEM; | |
663 | ||
664 | bprm->orig = *f; | |
665 | f->fn = t->fetch[FETCH_MTD_bitfield]; | |
666 | f->data = (void *)bprm; | |
667 | bw = simple_strtoul(bf + 1, &tail, 0); /* Use simple one */ | |
668 | ||
669 | if (bw == 0 || *tail != '@') | |
670 | return -EINVAL; | |
671 | ||
672 | bf = tail + 1; | |
673 | bo = simple_strtoul(bf, &tail, 0); | |
674 | ||
675 | if (tail == bf || *tail != '/') | |
676 | return -EINVAL; | |
677 | ||
678 | bprm->hi_shift = BYTES_TO_BITS(t->size) - (bw + bo); | |
679 | bprm->low_shift = bprm->hi_shift + bo; | |
680 | ||
681 | return (BYTES_TO_BITS(t->size) < (bw + bo)) ? -EINVAL : 0; | |
682 | } | |
683 | ||
684 | /* String length checking wrapper */ | |
685 | int traceprobe_parse_probe_arg(char *arg, ssize_t *size, | |
f3f096cf | 686 | struct probe_arg *parg, bool is_return, bool is_kprobe) |
8ab83f56 SD |
687 | { |
688 | const char *t; | |
689 | int ret; | |
690 | ||
691 | if (strlen(arg) > MAX_ARGSTR_LEN) { | |
692 | pr_info("Argument is too long.: %s\n", arg); | |
693 | return -ENOSPC; | |
694 | } | |
695 | parg->comm = kstrdup(arg, GFP_KERNEL); | |
696 | if (!parg->comm) { | |
697 | pr_info("Failed to allocate memory for command '%s'.\n", arg); | |
698 | return -ENOMEM; | |
699 | } | |
700 | t = strchr(parg->comm, ':'); | |
701 | if (t) { | |
702 | arg[t - parg->comm] = '\0'; | |
703 | t++; | |
704 | } | |
705 | parg->type = find_fetch_type(t); | |
706 | if (!parg->type) { | |
707 | pr_info("Unsupported type: %s\n", t); | |
708 | return -EINVAL; | |
709 | } | |
710 | parg->offset = *size; | |
711 | *size += parg->type->size; | |
f3f096cf | 712 | ret = parse_probe_arg(arg, parg->type, &parg->fetch, is_return, is_kprobe); |
8ab83f56 SD |
713 | |
714 | if (ret >= 0 && t != NULL) | |
715 | ret = __parse_bitfield_probe_arg(t, parg->type, &parg->fetch); | |
716 | ||
717 | if (ret >= 0) { | |
718 | parg->fetch_size.fn = get_fetch_size_function(parg->type, | |
719 | parg->fetch.fn); | |
720 | parg->fetch_size.data = parg->fetch.data; | |
721 | } | |
722 | ||
723 | return ret; | |
724 | } | |
725 | ||
726 | /* Return 1 if name is reserved or already used by another argument */ | |
727 | int traceprobe_conflict_field_name(const char *name, | |
728 | struct probe_arg *args, int narg) | |
729 | { | |
730 | int i; | |
731 | ||
732 | for (i = 0; i < ARRAY_SIZE(reserved_field_names); i++) | |
733 | if (strcmp(reserved_field_names[i], name) == 0) | |
734 | return 1; | |
735 | ||
736 | for (i = 0; i < narg; i++) | |
737 | if (strcmp(args[i].name, name) == 0) | |
738 | return 1; | |
739 | ||
740 | return 0; | |
741 | } | |
742 | ||
743 | void traceprobe_update_arg(struct probe_arg *arg) | |
744 | { | |
745 | if (CHECK_FETCH_FUNCS(bitfield, arg->fetch.fn)) | |
746 | update_bitfield_fetch_param(arg->fetch.data); | |
747 | else if (CHECK_FETCH_FUNCS(deref, arg->fetch.fn)) | |
748 | update_deref_fetch_param(arg->fetch.data); | |
749 | else if (CHECK_FETCH_FUNCS(symbol, arg->fetch.fn)) | |
750 | update_symbol_cache(arg->fetch.data); | |
751 | } | |
752 | ||
753 | void traceprobe_free_probe_arg(struct probe_arg *arg) | |
754 | { | |
755 | if (CHECK_FETCH_FUNCS(bitfield, arg->fetch.fn)) | |
756 | free_bitfield_fetch_param(arg->fetch.data); | |
757 | else if (CHECK_FETCH_FUNCS(deref, arg->fetch.fn)) | |
758 | free_deref_fetch_param(arg->fetch.data); | |
759 | else if (CHECK_FETCH_FUNCS(symbol, arg->fetch.fn)) | |
760 | free_symbol_cache(arg->fetch.data); | |
761 | ||
762 | kfree(arg->name); | |
763 | kfree(arg->comm); | |
764 | } | |
765 | ||
766 | int traceprobe_command(const char *buf, int (*createfn)(int, char **)) | |
767 | { | |
768 | char **argv; | |
769 | int argc, ret; | |
770 | ||
771 | argc = 0; | |
772 | ret = 0; | |
773 | argv = argv_split(GFP_KERNEL, buf, &argc); | |
774 | if (!argv) | |
775 | return -ENOMEM; | |
776 | ||
777 | if (argc) | |
778 | ret = createfn(argc, argv); | |
779 | ||
780 | argv_free(argv); | |
781 | ||
782 | return ret; | |
783 | } | |
784 | ||
785 | #define WRITE_BUFSIZE 4096 | |
786 | ||
787 | ssize_t traceprobe_probes_write(struct file *file, const char __user *buffer, | |
788 | size_t count, loff_t *ppos, | |
789 | int (*createfn)(int, char **)) | |
790 | { | |
791 | char *kbuf, *tmp; | |
792 | int ret = 0; | |
793 | size_t done = 0; | |
794 | size_t size; | |
795 | ||
796 | kbuf = kmalloc(WRITE_BUFSIZE, GFP_KERNEL); | |
797 | if (!kbuf) | |
798 | return -ENOMEM; | |
799 | ||
800 | while (done < count) { | |
801 | size = count - done; | |
802 | ||
803 | if (size >= WRITE_BUFSIZE) | |
804 | size = WRITE_BUFSIZE - 1; | |
805 | ||
806 | if (copy_from_user(kbuf, buffer + done, size)) { | |
807 | ret = -EFAULT; | |
808 | goto out; | |
809 | } | |
810 | kbuf[size] = '\0'; | |
811 | tmp = strchr(kbuf, '\n'); | |
812 | ||
813 | if (tmp) { | |
814 | *tmp = '\0'; | |
815 | size = tmp - kbuf + 1; | |
816 | } else if (done + size < count) { | |
817 | pr_warning("Line length is too long: " | |
818 | "Should be less than %d.", WRITE_BUFSIZE); | |
819 | ret = -EINVAL; | |
820 | goto out; | |
821 | } | |
822 | done += size; | |
823 | /* Remove comments */ | |
824 | tmp = strchr(kbuf, '#'); | |
825 | ||
826 | if (tmp) | |
827 | *tmp = '\0'; | |
828 | ||
829 | ret = traceprobe_command(kbuf, createfn); | |
830 | if (ret) | |
831 | goto out; | |
832 | } | |
833 | ret = done; | |
834 | ||
835 | out: | |
836 | kfree(kbuf); | |
837 | ||
838 | return ret; | |
839 | } |