Pull kprobes updates from Masami Hiramatsu: - Skip negative return code check for snprintf in eprobe - Add recursive call test cases for kprobe unit test - Add 'char' type to probe events to show it as the character instead of value - Update kselftest kprobe-event testcase to ignore '__pfx_' symbols - Fix kselftest to check filter on eprobe event correctly - Add filter on eprobe to the README file in tracefs - Fix optprobes to check whether there is 'under unoptimizing' optprobe when optimizing another kprobe correctly - Fix optprobe to check whether there is 'under unoptimizing' optprobe when fetching the original instruction correctly - Fix optprobe to free 'forcibly unoptimized' optprobe correctly * tag 'probes-v6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace: tracing/eprobe: no need to check for negative ret value for snprintf test_kprobes: Add recursed kprobe test case tracing/probe: add a char type to show the character value of traced arguments selftests/ftrace: Fix probepoint testcase to ignore __pfx_* symbols selftests/ftrace: Fix eprobe syntax test case to check filter support tracing/eprobe: Fix to add filter on eprobe description in README file x86/kprobes: Fix arch_check_optimized_kprobe check within optimized_kprobe range x86/kprobes: Fix __recover_optprobed_insn check optimizing logic kprobes: Fix to handle forcibly unoptimized kprobes on freeing_list
Unified · Split
| @@ -58,7 +58,7 @@ Synopsis of kprobe_events · 57 unmodified lines | |||
| 58 | NAME=FETCHARG : Set NAME as the argument name of FETCHARG. | 58 | NAME=FETCHARG : Set NAME as the argument name of FETCHARG. |
| 59 | FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types | 59 | FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types |
| 60 | (u8/u16/u32/u64/s8/s16/s32/s64), hexadecimal types | 60 | (u8/u16/u32/u64/s8/s16/s32/s64), hexadecimal types |
| 61 | (x8/x16/x32/x64), "string", "ustring", "symbol", "symstr" | 61 | (x8/x16/x32/x64), "char", "string", "ustring", "symbol", "symstr" |
| 62 | and bitfield are supported. | 62 | and bitfield are supported. |
| 63 | 63 | ||
| 64 | (\*1) only for the probe on function entry (offs == 0). | 64 | (\*1) only for the probe on function entry (offs == 0). |
| @@ -82,6 +82,8 @@ Note that the array can be applied to memory type fetchargs, you can not · 17 unmodified lines | |||
| 82 | apply it to registers/stack-entries etc. (for example, '$stack1:x8[8]' is | 82 | apply it to registers/stack-entries etc. (for example, '$stack1:x8[8]' is |
| 83 | wrong, but '+8($stack):x8[8]' is OK.) | 83 | wrong, but '+8($stack):x8[8]' is OK.) |
| 84 | 84 | ||
| 85 | Char type can be used to show the character value of traced arguments. | ||
| 86 | |||
| 85 | String type is a special type, which fetches a "null-terminated" string from | 87 | String type is a special type, which fetches a "null-terminated" string from |
| 86 | kernel space. This means it will fail and store NULL if the string container | 88 | kernel space. This means it will fail and store NULL if the string container |
| 87 | has been paged out. "ustring" type is an alternative of string for user-space. | 89 | has been paged out. "ustring" type is an alternative of string for user-space. |
| @@ -46,8 +46,8 @@ unsigned long __recover_optprobed_insn(kprobe_opcode_t *buf, unsigned long addr) · 45 unmodified lines | |||
| 46 | /* This function only handles jump-optimized kprobe */ | 46 | /* This function only handles jump-optimized kprobe */ |
| 47 | if (kp && kprobe_optimized(kp)) { | 47 | if (kp && kprobe_optimized(kp)) { |
| 48 | op = container_of(kp, struct optimized_kprobe, kp); | 48 | op = container_of(kp, struct optimized_kprobe, kp); |
| 49 | /* If op->list is not empty, op is under optimizing */ | 49 | /* If op is optimized or under unoptimizing */ |
| 50 | if (list_empty(&op->list)) | 50 | if (list_empty(&op->list) || optprobe_queued_unopt(op)) |
| 51 | goto found; | 51 | goto found; |
| 52 | } | 52 | } |
| 53 | } | 53 | } |
| @@ -353,7 +353,7 @@ int arch_check_optimized_kprobe(struct optimized_kprobe *op) · 299 unmodified lines | |||
| 353 | 353 | ||
| 354 | for (i = 1; i < op->optinsn.size; i++) { | 354 | for (i = 1; i < op->optinsn.size; i++) { |
| 355 | p = get_kprobe(op->kp.addr + i); | 355 | p = get_kprobe(op->kp.addr + i); |
| 356 | if (p && !kprobe_disabled(p)) | 356 | if (p && !kprobe_disarmed(p)) |
| 357 | return -EEXIST; | 357 | return -EEXIST; |
| 358 | } | 358 | } |
| 359 | 359 | ||
| @@ -378,6 +378,8 @@ extern void opt_pre_handler(struct kprobe *p, struct pt_regs *regs); · 377 unmodified lines | |||
| 378 | DEFINE_INSN_CACHE_OPS(optinsn); | 378 | DEFINE_INSN_CACHE_OPS(optinsn); |
| 379 | 379 | ||
| 380 | extern void wait_for_kprobe_optimizer(void); | 380 | extern void wait_for_kprobe_optimizer(void); |
| 381 | bool optprobe_queued_unopt(struct optimized_kprobe *op); | ||
| 382 | bool kprobe_disarmed(struct kprobe *p); | ||
| 381 | #else /* !CONFIG_OPTPROBES */ | 383 | #else /* !CONFIG_OPTPROBES */ |
| 382 | static inline void wait_for_kprobe_optimizer(void) { } | 384 | static inline void wait_for_kprobe_optimizer(void) { } |
| 383 | #endif /* CONFIG_OPTPROBES */ | 385 | #endif /* CONFIG_OPTPROBES */ |
| @@ -458,7 +458,7 @@ static inline int kprobe_optready(struct kprobe *p) · 457 unmodified lines | |||
| 458 | } | 458 | } |
| 459 | 459 | ||
| 460 | /* Return true if the kprobe is disarmed. Note: p must be on hash list */ | 460 | /* Return true if the kprobe is disarmed. Note: p must be on hash list */ |
| 461 | static inline bool kprobe_disarmed(struct kprobe *p) | 461 | bool kprobe_disarmed(struct kprobe *p) |
| 462 | { | 462 | { |
| 463 | struct optimized_kprobe *op; | 463 | struct optimized_kprobe *op; |
| 464 | 464 | ||
| @@ -555,17 +555,15 @@ static void do_unoptimize_kprobes(void) · 90 unmodified lines | |||
| 555 | /* See comment in do_optimize_kprobes() */ | 555 | /* See comment in do_optimize_kprobes() */ |
| 556 | lockdep_assert_cpus_held(); | 556 | lockdep_assert_cpus_held(); |
| 557 | 557 | ||
| 558 | /* Unoptimization must be done anytime */ | 558 | if (!list_empty(&unoptimizing_list)) |
| 559 | if (list_empty(&unoptimizing_list)) | 559 | arch_unoptimize_kprobes(&unoptimizing_list, &freeing_list); |
| 560 | return; | ||
| 561 | 560 | ||
| 562 | arch_unoptimize_kprobes(&unoptimizing_list, &freeing_list); | 561 | /* Loop on 'freeing_list' for disarming and removing from kprobe hash list */ |
| 563 | /* Loop on 'freeing_list' for disarming */ | ||
| 564 | list_for_each_entry_safe(op, tmp, &freeing_list, list) { | 562 | list_for_each_entry_safe(op, tmp, &freeing_list, list) { |
| 565 | /* Switching from detour code to origin */ | 563 | /* Switching from detour code to origin */ |
| 566 | op->kp.flags &= ~KPROBE_FLAG_OPTIMIZED; | 564 | op->kp.flags &= ~KPROBE_FLAG_OPTIMIZED; |
| 567 | /* Disarm probes if marked disabled */ | 565 | /* Disarm probes if marked disabled and not gone */ |
| 568 | if (kprobe_disabled(&op->kp)) | 566 | if (kprobe_disabled(&op->kp) && !kprobe_gone(&op->kp)) |
| 569 | arch_disarm_kprobe(&op->kp); | 567 | arch_disarm_kprobe(&op->kp); |
| 570 | if (kprobe_unused(&op->kp)) { | 568 | if (kprobe_unused(&op->kp)) { |
| 571 | /* | 569 | /* |
| @@ -662,7 +660,7 @@ void wait_for_kprobe_optimizer(void) · 90 unmodified lines | |||
| 662 | mutex_unlock(&kprobe_mutex); | 660 | mutex_unlock(&kprobe_mutex); |
| 663 | } | 661 | } |
| 664 | 662 | ||
| 665 | static bool optprobe_queued_unopt(struct optimized_kprobe *op) | 663 | bool optprobe_queued_unopt(struct optimized_kprobe *op) |
| 666 | { | 664 | { |
| 667 | struct optimized_kprobe *_op; | 665 | struct optimized_kprobe *_op; |
| 668 | 666 | ||
| @@ -797,14 +795,13 @@ static void kill_optimized_kprobe(struct kprobe *p) · 128 unmodified lines | |||
| 797 | op->kp.flags &= ~KPROBE_FLAG_OPTIMIZED; | 795 | op->kp.flags &= ~KPROBE_FLAG_OPTIMIZED; |
| 798 | 796 | ||
| 799 | if (kprobe_unused(p)) { | 797 | if (kprobe_unused(p)) { |
| 800 | /* Enqueue if it is unused */ | ||
| 801 | list_add(&op->list, &freeing_list); | ||
| 802 | /* | 798 | /* |
| 803 | * Remove unused probes from the hash list. After waiting | 799 | * Unused kprobe is on unoptimizing or freeing list. We move it |
| 804 | * for synchronization, this probe is reclaimed. | 800 | * to freeing_list and let the kprobe_optimizer() remove it from |
| 805 | * (reclaiming is done by do_free_cleaned_kprobes().) | 801 | * the kprobe hash list and free it. |
| 806 | */ | 802 | */ |
| 807 | hlist_del_rcu(&op->kp.hlist); | 803 | if (optprobe_queued_unopt(op)) |
| 804 | list_move(&op->list, &freeing_list); | ||
| 808 | } | 805 | } |
| 809 | 806 | ||
| 810 | /* Don't touch the code, because it is already freed. */ | 807 | /* Don't touch the code, because it is already freed. */ |
| @@ -5646,7 +5646,7 @@ static const char readme_msg[] = · 5645 unmodified lines | |||
| 5646 | #ifdef CONFIG_HIST_TRIGGERS | 5646 | #ifdef CONFIG_HIST_TRIGGERS |
| 5647 | "\t s:[synthetic/]<event> <field> [<field>]\n" | 5647 | "\t s:[synthetic/]<event> <field> [<field>]\n" |
| 5648 | #endif | 5648 | #endif |
| 5649 | "\t e[:[<group>/][<event>]] <attached-group>.<attached-event> [<args>]\n" | 5649 | "\t e[:[<group>/][<event>]] <attached-group>.<attached-event> [<args>] [if <filter>]\n" |
| 5650 | "\t -:[<group>/][<event>]\n" | 5650 | "\t -:[<group>/][<event>]\n" |
| 5651 | #ifdef CONFIG_KPROBE_EVENTS | 5651 | #ifdef CONFIG_KPROBE_EVENTS |
| 5652 | "\t place: [<module>:]<symbol>[+<offset>]|<memaddr>\n" | 5652 | "\t place: [<module>:]<symbol>[+<offset>]|<memaddr>\n" |
| @@ -5663,7 +5663,7 @@ static const char readme_msg[] = · 10 unmodified lines | |||
| 5663 | "\t $stack<index>, $stack, $retval, $comm,\n" | 5663 | "\t $stack<index>, $stack, $retval, $comm,\n" |
| 5664 | #endif | 5664 | #endif |
| 5665 | "\t +|-[u]<offset>(<fetcharg>), \\imm-value, \\\"imm-string\"\n" | 5665 | "\t +|-[u]<offset>(<fetcharg>), \\imm-value, \\\"imm-string\"\n" |
| 5666 | "\t type: s8/16/32/64, u8/16/32/64, x8/16/32/64, string, symbol,\n" | 5666 | "\t type: s8/16/32/64, u8/16/32/64, x8/16/32/64, char, string, symbol,\n" |
| 5667 | "\t b<bit-width>@<bit-offset>/<container-size>, ustring,\n" | 5667 | "\t b<bit-width>@<bit-offset>/<container-size>, ustring,\n" |
| 5668 | "\t symstr, <type>\\[<array-size>\\]\n" | 5668 | "\t symstr, <type>\\[<array-size>\\]\n" |
| 5669 | #ifdef CONFIG_HIST_TRIGGERS | 5669 | #ifdef CONFIG_HIST_TRIGGERS |
| @@ -923,17 +923,13 @@ static int trace_eprobe_parse_filter(struct trace_eprobe *ep, int argc, const ch · 922 unmodified lines | |||
| 923 | 923 | ||
| 924 | p = ep->filter_str; | 924 | p = ep->filter_str; |
| 925 | for (i = 0; i < argc; i++) { | 925 | for (i = 0; i < argc; i++) { |
| 926 | ret = snprintf(p, len, "%s ", argv[i]); | 926 | if (i) |
| 927 | if (ret < 0) | 927 | ret = snprintf(p, len, " %s", argv[i]); |
| 928 | goto error; | 928 | else |
| 929 | if (ret > len) { | 929 | ret = snprintf(p, len, "%s", argv[i]); |
| 930 | ret = -E2BIG; | ||
| 931 | goto error; | ||
| 932 | } | ||
| 933 | p += ret; | 930 | p += ret; |
| 934 | len -= ret; | 931 | len -= ret; |
| 935 | } | 932 | } |
| 936 | p[-1] = '\0'; | ||
| 937 | 933 | ||
| 938 | /* | 934 | /* |
| 939 | * Ensure the filter string can be parsed correctly. Note, this | 935 | * Ensure the filter string can be parsed correctly. Note, this |
| @@ -50,6 +50,7 @@ DEFINE_BASIC_PRINT_TYPE_FUNC(x8, u8, "0x%x") · 49 unmodified lines | |||
| 50 | DEFINE_BASIC_PRINT_TYPE_FUNC(x16, u16, "0x%x") | 50 | DEFINE_BASIC_PRINT_TYPE_FUNC(x16, u16, "0x%x") |
| 51 | DEFINE_BASIC_PRINT_TYPE_FUNC(x32, u32, "0x%x") | 51 | DEFINE_BASIC_PRINT_TYPE_FUNC(x32, u32, "0x%x") |
| 52 | DEFINE_BASIC_PRINT_TYPE_FUNC(x64, u64, "0x%Lx") | 52 | DEFINE_BASIC_PRINT_TYPE_FUNC(x64, u64, "0x%Lx") |
| 53 | DEFINE_BASIC_PRINT_TYPE_FUNC(char, u8, "'%c'") | ||
| 53 | 54 | ||
| 54 | int PRINT_TYPE_FUNC_NAME(symbol)(struct trace_seq *s, void *data, void *ent) | 55 | int PRINT_TYPE_FUNC_NAME(symbol)(struct trace_seq *s, void *data, void *ent) |
| 55 | { | 56 | { |
| @@ -95,6 +96,7 @@ static const struct fetch_type probe_fetch_types[] = { · 39 unmodified lines | |||
| 95 | ASSIGN_FETCH_TYPE_ALIAS(x16, u16, u16, 0), | 96 | ASSIGN_FETCH_TYPE_ALIAS(x16, u16, u16, 0), |
| 96 | ASSIGN_FETCH_TYPE_ALIAS(x32, u32, u32, 0), | 97 | ASSIGN_FETCH_TYPE_ALIAS(x32, u32, u32, 0), |
| 97 | ASSIGN_FETCH_TYPE_ALIAS(x64, u64, u64, 0), | 98 | ASSIGN_FETCH_TYPE_ALIAS(x64, u64, u64, 0), |
| 99 | ASSIGN_FETCH_TYPE_ALIAS(char, u8, u8, 0), | ||
| 98 | ASSIGN_FETCH_TYPE_ALIAS(symbol, ADDR_FETCH_TYPE, ADDR_FETCH_TYPE, 0), | 100 | ASSIGN_FETCH_TYPE_ALIAS(symbol, ADDR_FETCH_TYPE, ADDR_FETCH_TYPE, 0), |
| 99 | 101 | ||
| 100 | ASSIGN_FETCH_TYPE_END | 102 | ASSIGN_FETCH_TYPE_END |
| @@ -166,6 +166,7 @@ DECLARE_BASIC_PRINT_TYPE_FUNC(x16); · 165 unmodified lines | |||
| 166 | DECLARE_BASIC_PRINT_TYPE_FUNC(x32); | 166 | DECLARE_BASIC_PRINT_TYPE_FUNC(x32); |
| 167 | DECLARE_BASIC_PRINT_TYPE_FUNC(x64); | 167 | DECLARE_BASIC_PRINT_TYPE_FUNC(x64); |
| 168 | 168 | ||
| 169 | DECLARE_BASIC_PRINT_TYPE_FUNC(char); | ||
| 169 | DECLARE_BASIC_PRINT_TYPE_FUNC(string); | 170 | DECLARE_BASIC_PRINT_TYPE_FUNC(string); |
| 170 | DECLARE_BASIC_PRINT_TYPE_FUNC(symbol); | 171 | DECLARE_BASIC_PRINT_TYPE_FUNC(symbol); |
| 171 | 172 | ||
| @@ -14,6 +14,7 @@ · 13 unmodified lines | |||
| 14 | 14 | ||
| 15 | static u32 rand1, preh_val, posth_val; | 15 | static u32 rand1, preh_val, posth_val; |
| 16 | static u32 (*target)(u32 value); | 16 | static u32 (*target)(u32 value); |
| 17 | static u32 (*recursed_target)(u32 value); | ||
| 17 | static u32 (*target2)(u32 value); | 18 | static u32 (*target2)(u32 value); |
| 18 | static struct kunit *current_test; | 19 | static struct kunit *current_test; |
| 19 | 20 | ||
| @@ -27,18 +28,27 @@ static noinline u32 kprobe_target(u32 value) · 7 unmodified lines | |||
| 27 | return (value / div_factor); | 28 | return (value / div_factor); |
| 28 | } | 29 | } |
| 29 | 30 | ||
| 31 | static noinline u32 kprobe_recursed_target(u32 value) | ||
| 32 | { | ||
| 33 | return (value / div_factor); | ||
| 34 | } | ||
| 35 | |||
| 30 | static int kp_pre_handler(struct kprobe *p, struct pt_regs *regs) | 36 | static int kp_pre_handler(struct kprobe *p, struct pt_regs *regs) |
| 31 | { | 37 | { |
| 32 | KUNIT_EXPECT_FALSE(current_test, preemptible()); | 38 | KUNIT_EXPECT_FALSE(current_test, preemptible()); |
| 33 | preh_val = (rand1 / div_factor); | 39 | |
| 40 | preh_val = recursed_target(rand1); | ||
| 34 | return 0; | 41 | return 0; |
| 35 | } | 42 | } |
| 36 | 43 | ||
| 37 | static void kp_post_handler(struct kprobe *p, struct pt_regs *regs, | 44 | static void kp_post_handler(struct kprobe *p, struct pt_regs *regs, |
| 38 | unsigned long flags) | 45 | unsigned long flags) |
| 39 | { | 46 | { |
| 47 | u32 expval = recursed_target(rand1); | ||
| 48 | |||
| 40 | KUNIT_EXPECT_FALSE(current_test, preemptible()); | 49 | KUNIT_EXPECT_FALSE(current_test, preemptible()); |
| 41 | KUNIT_EXPECT_EQ(current_test, preh_val, (rand1 / div_factor)); | 50 | KUNIT_EXPECT_EQ(current_test, preh_val, expval); |
| 51 | |||
| 42 | posth_val = preh_val + div_factor; | 52 | posth_val = preh_val + div_factor; |
| 43 | } | 53 | } |
| 44 | 54 | ||
| @@ -136,6 +146,29 @@ static void test_kprobes(struct kunit *test) · 91 unmodified lines | |||
| 136 | unregister_kprobes(kps, 2); | 146 | unregister_kprobes(kps, 2); |
| 137 | } | 147 | } |
| 138 | 148 | ||
| 149 | static struct kprobe kp_missed = { | ||
| 150 | .symbol_name = "kprobe_recursed_target", | ||
| 151 | .pre_handler = kp_pre_handler, | ||
| 152 | .post_handler = kp_post_handler, | ||
| 153 | }; | ||
| 154 | |||
| 155 | static void test_kprobe_missed(struct kunit *test) | ||
| 156 | { | ||
| 157 | current_test = test; | ||
| 158 | preh_val = 0; | ||
| 159 | posth_val = 0; | ||
| 160 | |||
| 161 | KUNIT_EXPECT_EQ(test, 0, register_kprobe(&kp_missed)); | ||
| 162 | |||
| 163 | recursed_target(rand1); | ||
| 164 | |||
| 165 | KUNIT_EXPECT_EQ(test, 2, kp_missed.nmissed); | ||
| 166 | KUNIT_EXPECT_NE(test, 0, preh_val); | ||
| 167 | KUNIT_EXPECT_NE(test, 0, posth_val); | ||
| 168 | |||
| 169 | unregister_kprobe(&kp_missed); | ||
| 170 | } | ||
| 171 | |||
| 139 | #ifdef CONFIG_KRETPROBES | 172 | #ifdef CONFIG_KRETPROBES |
| 140 | static u32 krph_val; | 173 | static u32 krph_val; |
| 141 | 174 | ||
| @@ -336,6 +369,7 @@ static int kprobes_test_init(struct kunit *test) · 194 unmodified lines | |||
| 336 | { | 369 | { |
| 337 | target = kprobe_target; | 370 | target = kprobe_target; |
| 338 | target2 = kprobe_target2; | 371 | target2 = kprobe_target2; |
| 372 | recursed_target = kprobe_recursed_target; | ||
| 339 | stacktrace_target = kprobe_stacktrace_target; | 373 | stacktrace_target = kprobe_stacktrace_target; |
| 340 | internal_target = kprobe_stacktrace_internal_target; | 374 | internal_target = kprobe_stacktrace_internal_target; |
| 341 | stacktrace_driver = kprobe_stacktrace_driver; | 375 | stacktrace_driver = kprobe_stacktrace_driver; |
| @@ -346,6 +380,7 @@ static int kprobes_test_init(struct kunit *test) · 4 unmodified lines | |||
| 346 | static struct kunit_case kprobes_testcases[] = { | 380 | static struct kunit_case kprobes_testcases[] = { |
| 347 | KUNIT_CASE(test_kprobe), | 381 | KUNIT_CASE(test_kprobe), |
| 348 | KUNIT_CASE(test_kprobes), | 382 | KUNIT_CASE(test_kprobes), |
| 383 | KUNIT_CASE(test_kprobe_missed), | ||
| 349 | #ifdef CONFIG_KRETPROBES | 384 | #ifdef CONFIG_KRETPROBES |
| 350 | KUNIT_CASE(test_kretprobe), | 385 | KUNIT_CASE(test_kretprobe), |
| 351 | KUNIT_CASE(test_kretprobes), | 386 | KUNIT_CASE(test_kretprobes), |
| @@ -22,6 +22,8 @@ check_error 'e:foo/^bar.1 syscalls/sys_enter_openat' # BAD_EVENT_NAME · 21 unmodified lines | |||
| 22 | check_error 'e:foo/bar syscalls/sys_enter_openat arg=^dfd' # BAD_FETCH_ARG | 22 | check_error 'e:foo/bar syscalls/sys_enter_openat arg=^dfd' # BAD_FETCH_ARG |
| 23 | check_error 'e:foo/bar syscalls/sys_enter_openat ^arg=$foo' # BAD_ATTACH_ARG | 23 | check_error 'e:foo/bar syscalls/sys_enter_openat ^arg=$foo' # BAD_ATTACH_ARG |
| 24 | 24 | ||
| 25 | check_error 'e:foo/bar syscalls/sys_enter_openat if ^' # NO_EP_FILTER | 25 | if grep -q '<attached-group>\.<attached-event>.*\[if <filter>\]' README; then |
| 26 | check_error 'e:foo/bar syscalls/sys_enter_openat if ^' # NO_EP_FILTER | ||
| 27 | fi | ||
| 26 | 28 | ||
| 27 | exit 0 | 29 | exit 0 |
| @@ -0,0 +1,47 @@ | |||
| 1 | #!/bin/sh | ||
| 2 | # SPDX-License-Identifier: GPL-2.0 | ||
| 3 | # description: Kprobe event char type argument | ||
| 4 | # requires: kprobe_events | ||
| 5 | |||
| 6 | case `uname -m` in | ||
| 7 | x86_64) | ||
| 8 | ARG1=%di | ||
| 9 | ;; | ||
| 10 | i[3456]86) | ||
| 11 | ARG1=%ax | ||
| 12 | ;; | ||
| 13 | aarch64) | ||
| 14 | ARG1=%x0 | ||
| 15 | ;; | ||
| 16 | arm*) | ||
| 17 | ARG1=%r0 | ||
| 18 | ;; | ||
| 19 | ppc64*) | ||
| 20 | ARG1=%r3 | ||
| 21 | ;; | ||
| 22 | ppc*) | ||
| 23 | ARG1=%r3 | ||
| 24 | ;; | ||
| 25 | s390*) | ||
| 26 | ARG1=%r2 | ||
| 27 | ;; | ||
| 28 | mips*) | ||
| 29 | ARG1=%r4 | ||
| 30 | ;; | ||
| 31 | *) | ||
| 32 | echo "Please implement other architecture here" | ||
| 33 | exit_untested | ||
| 34 | esac | ||
| 35 | |||
| 36 | : "Test get argument (1)" | ||
| 37 | echo "p:testprobe tracefs_create_dir arg1=+0(${ARG1}):char" > kprobe_events | ||
| 38 | echo 1 > events/kprobes/testprobe/enable | ||
| 39 | echo "p:test $FUNCTION_FORK" >> kprobe_events | ||
| 40 | grep -qe "testprobe.* arg1='t'" trace | ||
| 41 | |||
| 42 | echo 0 > events/kprobes/testprobe/enable | ||
| 43 | : "Test get argument (2)" | ||
| 44 | echo "p:testprobe tracefs_create_dir arg1=+0(${ARG1}):char arg2=+0(${ARG1}):char[4]" > kprobe_events | ||
| 45 | echo 1 > events/kprobes/testprobe/enable | ||
| 46 | echo "p:test $FUNCTION_FORK" >> kprobe_events | ||
| 47 | grep -qe "testprobe.* arg1='t' arg2={'t','e','s','t'}" trace | ||
| @@ -21,7 +21,7 @@ set_offs() { # prev target next · 20 unmodified lines | |||
| 21 | 21 | ||
| 22 | # We have to decode symbol addresses to get correct offsets. | 22 | # We have to decode symbol addresses to get correct offsets. |
| 23 | # If the offset is not an instruction boundary, it cause -EILSEQ. | 23 | # If the offset is not an instruction boundary, it cause -EILSEQ. |
| 24 | set_offs `grep -A1 -B1 ${TARGET_FUNC} /proc/kallsyms | cut -f 1 -d " " | xargs` | 24 | set_offs `grep -v __pfx_ /proc/kallsyms | grep -A1 -B1 ${TARGET_FUNC} | cut -f 1 -d " " | xargs` |
| 25 | 25 | ||
| 26 | UINT_TEST=no | 26 | UINT_TEST=no |
| 27 | # printf "%x" -1 returns (unsigned long)-1. | 27 | # printf "%x" -1 returns (unsigned long)-1. |