diff options
| author | Namhyung Kim <namhyung.kim@lge.com> | 2013-11-26 00:56:28 -0500 |
|---|---|---|
| committer | Steven Rostedt <rostedt@goodmis.org> | 2014-01-02 16:17:39 -0500 |
| commit | 34fee3a104cea1c4b658e51836e4bcd99bd76c70 (patch) | |
| tree | 4b73d864e468c395f6c9d484bef5a8f138a02b5e /kernel/trace | |
| parent | b26c74e116ad8433da22a72f03d148f88aab36e5 (diff) | |
tracing/probes: Split [ku]probes_fetch_type_table
Use separate fetch_type_table for kprobes and uprobes. It currently
shares all fetch methods but some of them will be implemented
differently later.
This is not to break build if [ku]probes is configured alone (like
!CONFIG_KPROBE_EVENT and CONFIG_UPROBE_EVENT). So I added '__weak'
to the table declaration so that it can be safely omitted when it
configured out.
Acked-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: zhangwei(Jovi) <jovi.zhangwei@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Diffstat (limited to 'kernel/trace')
| -rw-r--r-- | kernel/trace/trace_kprobe.c | 20 | ||||
| -rw-r--r-- | kernel/trace/trace_probe.c | 65 | ||||
| -rw-r--r-- | kernel/trace/trace_probe.h | 53 | ||||
| -rw-r--r-- | kernel/trace/trace_uprobe.c | 20 |
4 files changed, 119 insertions, 39 deletions
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index c9ffdafb9ada..fe3f00c381c0 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
| @@ -88,6 +88,26 @@ static int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs); | |||
| 88 | static int kretprobe_dispatcher(struct kretprobe_instance *ri, | 88 | static int kretprobe_dispatcher(struct kretprobe_instance *ri, |
| 89 | struct pt_regs *regs); | 89 | struct pt_regs *regs); |
| 90 | 90 | ||
| 91 | /* Fetch type information table */ | ||
| 92 | const struct fetch_type kprobes_fetch_type_table[] = { | ||
| 93 | /* Special types */ | ||
| 94 | [FETCH_TYPE_STRING] = __ASSIGN_FETCH_TYPE("string", string, string, | ||
| 95 | sizeof(u32), 1, "__data_loc char[]"), | ||
| 96 | [FETCH_TYPE_STRSIZE] = __ASSIGN_FETCH_TYPE("string_size", u32, | ||
| 97 | string_size, sizeof(u32), 0, "u32"), | ||
| 98 | /* Basic types */ | ||
| 99 | ASSIGN_FETCH_TYPE(u8, u8, 0), | ||
| 100 | ASSIGN_FETCH_TYPE(u16, u16, 0), | ||
| 101 | ASSIGN_FETCH_TYPE(u32, u32, 0), | ||
| 102 | ASSIGN_FETCH_TYPE(u64, u64, 0), | ||
| 103 | ASSIGN_FETCH_TYPE(s8, u8, 1), | ||
| 104 | ASSIGN_FETCH_TYPE(s16, u16, 1), | ||
| 105 | ASSIGN_FETCH_TYPE(s32, u32, 1), | ||
| 106 | ASSIGN_FETCH_TYPE(s64, u64, 1), | ||
| 107 | |||
| 108 | ASSIGN_FETCH_TYPE_END | ||
| 109 | }; | ||
| 110 | |||
| 91 | /* | 111 | /* |
| 92 | * Allocate new trace_probe and initialize it (including kprobes). | 112 | * Allocate new trace_probe and initialize it (including kprobes). |
| 93 | */ | 113 | */ |
diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c index c26bc9eaa2ac..541036ec7392 100644 --- a/kernel/trace/trace_probe.c +++ b/kernel/trace/trace_probe.c | |||
| @@ -54,10 +54,6 @@ DEFINE_BASIC_PRINT_TYPE_FUNC(s16, "%d") | |||
| 54 | DEFINE_BASIC_PRINT_TYPE_FUNC(s32, "%d") | 54 | DEFINE_BASIC_PRINT_TYPE_FUNC(s32, "%d") |
| 55 | DEFINE_BASIC_PRINT_TYPE_FUNC(s64, "%Ld") | 55 | DEFINE_BASIC_PRINT_TYPE_FUNC(s64, "%Ld") |
| 56 | 56 | ||
| 57 | /* For defining macros, define string/string_size types */ | ||
| 58 | typedef u32 string; | ||
| 59 | typedef u32 string_size; | ||
| 60 | |||
| 61 | /* Print type function for string type */ | 57 | /* Print type function for string type */ |
| 62 | __kprobes int PRINT_TYPE_FUNC_NAME(string)(struct trace_seq *s, | 58 | __kprobes int PRINT_TYPE_FUNC_NAME(string)(struct trace_seq *s, |
| 63 | const char *name, | 59 | const char *name, |
| @@ -74,7 +70,6 @@ __kprobes int PRINT_TYPE_FUNC_NAME(string)(struct trace_seq *s, | |||
| 74 | 70 | ||
| 75 | const char PRINT_TYPE_FMT_NAME(string)[] = "\\\"%s\\\""; | 71 | const char PRINT_TYPE_FMT_NAME(string)[] = "\\\"%s\\\""; |
| 76 | 72 | ||
| 77 | #define FETCH_FUNC_NAME(method, type) fetch_##method##_##type | ||
| 78 | /* | 73 | /* |
| 79 | * Define macro for basic types - we don't need to define s* types, because | 74 | * Define macro for basic types - we don't need to define s* types, because |
| 80 | * we have to care only about bitwidth at recording time. | 75 | * we have to care only about bitwidth at recording time. |
| @@ -359,25 +354,8 @@ free_bitfield_fetch_param(struct bitfield_fetch_param *data) | |||
| 359 | kfree(data); | 354 | kfree(data); |
| 360 | } | 355 | } |
| 361 | 356 | ||
| 362 | /* Fetch type information table */ | 357 | static const struct fetch_type *find_fetch_type(const char *type, |
| 363 | static const struct fetch_type fetch_type_table[] = { | 358 | const struct fetch_type *ftbl) |
| 364 | /* Special types */ | ||
| 365 | [FETCH_TYPE_STRING] = __ASSIGN_FETCH_TYPE("string", string, string, | ||
| 366 | sizeof(u32), 1, "__data_loc char[]"), | ||
| 367 | [FETCH_TYPE_STRSIZE] = __ASSIGN_FETCH_TYPE("string_size", u32, | ||
| 368 | string_size, sizeof(u32), 0, "u32"), | ||
| 369 | /* Basic types */ | ||
| 370 | ASSIGN_FETCH_TYPE(u8, u8, 0), | ||
| 371 | ASSIGN_FETCH_TYPE(u16, u16, 0), | ||
| 372 | ASSIGN_FETCH_TYPE(u32, u32, 0), | ||
| 373 | ASSIGN_FETCH_TYPE(u64, u64, 0), | ||
| 374 | ASSIGN_FETCH_TYPE(s8, u8, 1), | ||
| 375 | ASSIGN_FETCH_TYPE(s16, u16, 1), | ||
| 376 | ASSIGN_FETCH_TYPE(s32, u32, 1), | ||
| 377 | ASSIGN_FETCH_TYPE(s64, u64, 1), | ||
| 378 | }; | ||
| 379 | |||
| 380 | static const struct fetch_type *find_fetch_type(const char *type) | ||
| 381 | { | 359 | { |
| 382 | int i; | 360 | int i; |
| 383 | 361 | ||
| @@ -398,21 +376,22 @@ static const struct fetch_type *find_fetch_type(const char *type) | |||
| 398 | 376 | ||
| 399 | switch (bs) { | 377 | switch (bs) { |
| 400 | case 8: | 378 | case 8: |
| 401 | return find_fetch_type("u8"); | 379 | return find_fetch_type("u8", ftbl); |
| 402 | case 16: | 380 | case 16: |
| 403 | return find_fetch_type("u16"); | 381 | return find_fetch_type("u16", ftbl); |
| 404 | case 32: | 382 | case 32: |
| 405 | return find_fetch_type("u32"); | 383 | return find_fetch_type("u32", ftbl); |
| 406 | case 64: | 384 | case 64: |
| 407 | return find_fetch_type("u64"); | 385 | return find_fetch_type("u64", ftbl); |
| 408 | default: | 386 | default: |
| 409 | goto fail; | 387 | goto fail; |
| 410 | } | 388 | } |
| 411 | } | 389 | } |
| 412 | 390 | ||
| 413 | for (i = 0; i < ARRAY_SIZE(fetch_type_table); i++) | 391 | for (i = 0; ftbl[i].name; i++) { |
| 414 | if (strcmp(type, fetch_type_table[i].name) == 0) | 392 | if (strcmp(type, ftbl[i].name) == 0) |
| 415 | return &fetch_type_table[i]; | 393 | return &ftbl[i]; |
| 394 | } | ||
| 416 | 395 | ||
| 417 | fail: | 396 | fail: |
| 418 | return NULL; | 397 | return NULL; |
| @@ -426,16 +405,17 @@ static __kprobes void fetch_stack_address(struct pt_regs *regs, | |||
| 426 | } | 405 | } |
| 427 | 406 | ||
| 428 | static fetch_func_t get_fetch_size_function(const struct fetch_type *type, | 407 | static fetch_func_t get_fetch_size_function(const struct fetch_type *type, |
| 429 | fetch_func_t orig_fn) | 408 | fetch_func_t orig_fn, |
| 409 | const struct fetch_type *ftbl) | ||
| 430 | { | 410 | { |
| 431 | int i; | 411 | int i; |
| 432 | 412 | ||
| 433 | if (type != &fetch_type_table[FETCH_TYPE_STRING]) | 413 | if (type != &ftbl[FETCH_TYPE_STRING]) |
| 434 | return NULL; /* Only string type needs size function */ | 414 | return NULL; /* Only string type needs size function */ |
| 435 | 415 | ||
| 436 | for (i = 0; i < FETCH_MTD_END; i++) | 416 | for (i = 0; i < FETCH_MTD_END; i++) |
| 437 | if (type->fetch[i] == orig_fn) | 417 | if (type->fetch[i] == orig_fn) |
| 438 | return fetch_type_table[FETCH_TYPE_STRSIZE].fetch[i]; | 418 | return ftbl[FETCH_TYPE_STRSIZE].fetch[i]; |
| 439 | 419 | ||
| 440 | WARN_ON(1); /* This should not happen */ | 420 | WARN_ON(1); /* This should not happen */ |
| 441 | 421 | ||
| @@ -504,12 +484,14 @@ static int parse_probe_vars(char *arg, const struct fetch_type *t, | |||
| 504 | static int parse_probe_arg(char *arg, const struct fetch_type *t, | 484 | static int parse_probe_arg(char *arg, const struct fetch_type *t, |
| 505 | struct fetch_param *f, bool is_return, bool is_kprobe) | 485 | struct fetch_param *f, bool is_return, bool is_kprobe) |
| 506 | { | 486 | { |
| 487 | const struct fetch_type *ftbl; | ||
| 507 | unsigned long param; | 488 | unsigned long param; |
| 508 | long offset; | 489 | long offset; |
| 509 | char *tmp; | 490 | char *tmp; |
| 510 | int ret; | 491 | int ret = 0; |
| 511 | 492 | ||
| 512 | ret = 0; | 493 | ftbl = is_kprobe ? kprobes_fetch_type_table : uprobes_fetch_type_table; |
| 494 | BUG_ON(ftbl == NULL); | ||
| 513 | 495 | ||
| 514 | /* Until uprobe_events supports only reg arguments */ | 496 | /* Until uprobe_events supports only reg arguments */ |
| 515 | if (!is_kprobe && arg[0] != '%') | 497 | if (!is_kprobe && arg[0] != '%') |
| @@ -568,7 +550,7 @@ static int parse_probe_arg(char *arg, const struct fetch_type *t, | |||
| 568 | struct deref_fetch_param *dprm; | 550 | struct deref_fetch_param *dprm; |
| 569 | const struct fetch_type *t2; | 551 | const struct fetch_type *t2; |
| 570 | 552 | ||
| 571 | t2 = find_fetch_type(NULL); | 553 | t2 = find_fetch_type(NULL, ftbl); |
| 572 | *tmp = '\0'; | 554 | *tmp = '\0'; |
| 573 | dprm = kzalloc(sizeof(struct deref_fetch_param), GFP_KERNEL); | 555 | dprm = kzalloc(sizeof(struct deref_fetch_param), GFP_KERNEL); |
| 574 | 556 | ||
| @@ -637,9 +619,13 @@ static int __parse_bitfield_probe_arg(const char *bf, | |||
| 637 | int traceprobe_parse_probe_arg(char *arg, ssize_t *size, | 619 | int traceprobe_parse_probe_arg(char *arg, ssize_t *size, |
| 638 | struct probe_arg *parg, bool is_return, bool is_kprobe) | 620 | struct probe_arg *parg, bool is_return, bool is_kprobe) |
| 639 | { | 621 | { |
| 622 | const struct fetch_type *ftbl; | ||
| 640 | const char *t; | 623 | const char *t; |
| 641 | int ret; | 624 | int ret; |
| 642 | 625 | ||
| 626 | ftbl = is_kprobe ? kprobes_fetch_type_table : uprobes_fetch_type_table; | ||
| 627 | BUG_ON(ftbl == NULL); | ||
| 628 | |||
| 643 | if (strlen(arg) > MAX_ARGSTR_LEN) { | 629 | if (strlen(arg) > MAX_ARGSTR_LEN) { |
| 644 | pr_info("Argument is too long.: %s\n", arg); | 630 | pr_info("Argument is too long.: %s\n", arg); |
| 645 | return -ENOSPC; | 631 | return -ENOSPC; |
| @@ -654,7 +640,7 @@ int traceprobe_parse_probe_arg(char *arg, ssize_t *size, | |||
| 654 | arg[t - parg->comm] = '\0'; | 640 | arg[t - parg->comm] = '\0'; |
| 655 | t++; | 641 | t++; |
| 656 | } | 642 | } |
| 657 | parg->type = find_fetch_type(t); | 643 | parg->type = find_fetch_type(t, ftbl); |
| 658 | if (!parg->type) { | 644 | if (!parg->type) { |
| 659 | pr_info("Unsupported type: %s\n", t); | 645 | pr_info("Unsupported type: %s\n", t); |
| 660 | return -EINVAL; | 646 | return -EINVAL; |
| @@ -668,7 +654,8 @@ int traceprobe_parse_probe_arg(char *arg, ssize_t *size, | |||
| 668 | 654 | ||
| 669 | if (ret >= 0) { | 655 | if (ret >= 0) { |
| 670 | parg->fetch_size.fn = get_fetch_size_function(parg->type, | 656 | parg->fetch_size.fn = get_fetch_size_function(parg->type, |
| 671 | parg->fetch.fn); | 657 | parg->fetch.fn, |
| 658 | ftbl); | ||
| 672 | parg->fetch_size.data = parg->fetch.data; | 659 | parg->fetch_size.data = parg->fetch.data; |
| 673 | } | 660 | } |
| 674 | 661 | ||
diff --git a/kernel/trace/trace_probe.h b/kernel/trace/trace_probe.h index bd621c08b6c6..5b77798d1130 100644 --- a/kernel/trace/trace_probe.h +++ b/kernel/trace/trace_probe.h | |||
| @@ -126,6 +126,10 @@ struct fetch_param { | |||
| 126 | void *data; | 126 | void *data; |
| 127 | }; | 127 | }; |
| 128 | 128 | ||
| 129 | /* For defining macros, define string/string_size types */ | ||
| 130 | typedef u32 string; | ||
| 131 | typedef u32 string_size; | ||
| 132 | |||
| 129 | #define PRINT_TYPE_FUNC_NAME(type) print_type_##type | 133 | #define PRINT_TYPE_FUNC_NAME(type) print_type_##type |
| 130 | #define PRINT_TYPE_FMT_NAME(type) print_type_format_##type | 134 | #define PRINT_TYPE_FMT_NAME(type) print_type_format_##type |
| 131 | 135 | ||
| @@ -146,6 +150,47 @@ DECLARE_BASIC_PRINT_TYPE_FUNC(s32); | |||
| 146 | DECLARE_BASIC_PRINT_TYPE_FUNC(s64); | 150 | DECLARE_BASIC_PRINT_TYPE_FUNC(s64); |
| 147 | DECLARE_BASIC_PRINT_TYPE_FUNC(string); | 151 | DECLARE_BASIC_PRINT_TYPE_FUNC(string); |
| 148 | 152 | ||
| 153 | #define FETCH_FUNC_NAME(method, type) fetch_##method##_##type | ||
| 154 | |||
| 155 | /* Declare macro for basic types */ | ||
| 156 | #define DECLARE_FETCH_FUNC(method, type) \ | ||
| 157 | extern void FETCH_FUNC_NAME(method, type)(struct pt_regs *regs, \ | ||
| 158 | void *data, void *dest) | ||
| 159 | |||
| 160 | #define DECLARE_BASIC_FETCH_FUNCS(method) \ | ||
| 161 | DECLARE_FETCH_FUNC(method, u8); \ | ||
| 162 | DECLARE_FETCH_FUNC(method, u16); \ | ||
| 163 | DECLARE_FETCH_FUNC(method, u32); \ | ||
| 164 | DECLARE_FETCH_FUNC(method, u64) | ||
| 165 | |||
| 166 | DECLARE_BASIC_FETCH_FUNCS(reg); | ||
| 167 | #define fetch_reg_string NULL | ||
| 168 | #define fetch_reg_string_size NULL | ||
| 169 | |||
| 170 | DECLARE_BASIC_FETCH_FUNCS(stack); | ||
| 171 | #define fetch_stack_string NULL | ||
| 172 | #define fetch_stack_string_size NULL | ||
| 173 | |||
| 174 | DECLARE_BASIC_FETCH_FUNCS(retval); | ||
| 175 | #define fetch_retval_string NULL | ||
| 176 | #define fetch_retval_string_size NULL | ||
| 177 | |||
| 178 | DECLARE_BASIC_FETCH_FUNCS(memory); | ||
| 179 | DECLARE_FETCH_FUNC(memory, string); | ||
| 180 | DECLARE_FETCH_FUNC(memory, string_size); | ||
| 181 | |||
| 182 | DECLARE_BASIC_FETCH_FUNCS(symbol); | ||
| 183 | DECLARE_FETCH_FUNC(symbol, string); | ||
| 184 | DECLARE_FETCH_FUNC(symbol, string_size); | ||
| 185 | |||
| 186 | DECLARE_BASIC_FETCH_FUNCS(deref); | ||
| 187 | DECLARE_FETCH_FUNC(deref, string); | ||
| 188 | DECLARE_FETCH_FUNC(deref, string_size); | ||
| 189 | |||
| 190 | DECLARE_BASIC_FETCH_FUNCS(bitfield); | ||
| 191 | #define fetch_bitfield_string NULL | ||
| 192 | #define fetch_bitfield_string_size NULL | ||
| 193 | |||
| 149 | /* Default (unsigned long) fetch type */ | 194 | /* Default (unsigned long) fetch type */ |
| 150 | #define __DEFAULT_FETCH_TYPE(t) u##t | 195 | #define __DEFAULT_FETCH_TYPE(t) u##t |
| 151 | #define _DEFAULT_FETCH_TYPE(t) __DEFAULT_FETCH_TYPE(t) | 196 | #define _DEFAULT_FETCH_TYPE(t) __DEFAULT_FETCH_TYPE(t) |
| @@ -176,9 +221,17 @@ ASSIGN_FETCH_FUNC(bitfield, ftype), \ | |||
| 176 | #define ASSIGN_FETCH_TYPE(ptype, ftype, sign) \ | 221 | #define ASSIGN_FETCH_TYPE(ptype, ftype, sign) \ |
| 177 | __ASSIGN_FETCH_TYPE(#ptype, ptype, ftype, sizeof(ftype), sign, #ptype) | 222 | __ASSIGN_FETCH_TYPE(#ptype, ptype, ftype, sizeof(ftype), sign, #ptype) |
| 178 | 223 | ||
| 224 | #define ASSIGN_FETCH_TYPE_END {} | ||
| 225 | |||
| 179 | #define FETCH_TYPE_STRING 0 | 226 | #define FETCH_TYPE_STRING 0 |
| 180 | #define FETCH_TYPE_STRSIZE 1 | 227 | #define FETCH_TYPE_STRSIZE 1 |
| 181 | 228 | ||
| 229 | /* | ||
| 230 | * Fetch type information table. | ||
| 231 | * It's declared as a weak symbol due to conditional compilation. | ||
| 232 | */ | ||
| 233 | extern __weak const struct fetch_type kprobes_fetch_type_table[]; | ||
| 234 | extern __weak const struct fetch_type uprobes_fetch_type_table[]; | ||
| 182 | 235 | ||
| 183 | struct probe_arg { | 236 | struct probe_arg { |
| 184 | struct fetch_param fetch; | 237 | struct fetch_param fetch; |
diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c index b233d9cb1216..2c60925ea073 100644 --- a/kernel/trace/trace_uprobe.c +++ b/kernel/trace/trace_uprobe.c | |||
| @@ -74,6 +74,26 @@ static int uprobe_dispatcher(struct uprobe_consumer *con, struct pt_regs *regs); | |||
| 74 | static int uretprobe_dispatcher(struct uprobe_consumer *con, | 74 | static int uretprobe_dispatcher(struct uprobe_consumer *con, |
| 75 | unsigned long func, struct pt_regs *regs); | 75 | unsigned long func, struct pt_regs *regs); |
| 76 | 76 | ||
| 77 | /* Fetch type information table */ | ||
| 78 | const struct fetch_type uprobes_fetch_type_table[] = { | ||
| 79 | /* Special types */ | ||
| 80 | [FETCH_TYPE_STRING] = __ASSIGN_FETCH_TYPE("string", string, string, | ||
| 81 | sizeof(u32), 1, "__data_loc char[]"), | ||
| 82 | [FETCH_TYPE_STRSIZE] = __ASSIGN_FETCH_TYPE("string_size", u32, | ||
| 83 | string_size, sizeof(u32), 0, "u32"), | ||
| 84 | /* Basic types */ | ||
| 85 | ASSIGN_FETCH_TYPE(u8, u8, 0), | ||
| 86 | ASSIGN_FETCH_TYPE(u16, u16, 0), | ||
| 87 | ASSIGN_FETCH_TYPE(u32, u32, 0), | ||
| 88 | ASSIGN_FETCH_TYPE(u64, u64, 0), | ||
| 89 | ASSIGN_FETCH_TYPE(s8, u8, 1), | ||
| 90 | ASSIGN_FETCH_TYPE(s16, u16, 1), | ||
| 91 | ASSIGN_FETCH_TYPE(s32, u32, 1), | ||
| 92 | ASSIGN_FETCH_TYPE(s64, u64, 1), | ||
| 93 | |||
| 94 | ASSIGN_FETCH_TYPE_END | ||
| 95 | }; | ||
| 96 | |||
| 77 | static inline void init_trace_uprobe_filter(struct trace_uprobe_filter *filter) | 97 | static inline void init_trace_uprobe_filter(struct trace_uprobe_filter *filter) |
| 78 | { | 98 | { |
| 79 | rwlock_init(&filter->rwlock); | 99 | rwlock_init(&filter->rwlock); |
