diff options
Diffstat (limited to 'kernel/trace/trace_kprobe.c')
-rw-r--r-- | kernel/trace/trace_kprobe.c | 320 |
1 files changed, 266 insertions, 54 deletions
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 1865d5f76538..9f46e98ba8f2 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
@@ -27,7 +27,6 @@ | |||
27 | /** | 27 | /** |
28 | * Kprobe event core functions | 28 | * Kprobe event core functions |
29 | */ | 29 | */ |
30 | |||
31 | struct trace_probe { | 30 | struct trace_probe { |
32 | struct list_head list; | 31 | struct list_head list; |
33 | struct kretprobe rp; /* Use rp.kp for kprobe use */ | 32 | struct kretprobe rp; /* Use rp.kp for kprobe use */ |
@@ -36,6 +35,7 @@ struct trace_probe { | |||
36 | const char *symbol; /* symbol name */ | 35 | const char *symbol; /* symbol name */ |
37 | struct ftrace_event_class class; | 36 | struct ftrace_event_class class; |
38 | struct ftrace_event_call call; | 37 | struct ftrace_event_call call; |
38 | struct ftrace_event_file * __rcu *files; | ||
39 | ssize_t size; /* trace entry size */ | 39 | ssize_t size; /* trace entry size */ |
40 | unsigned int nr_args; | 40 | unsigned int nr_args; |
41 | struct probe_arg args[]; | 41 | struct probe_arg args[]; |
@@ -46,7 +46,7 @@ struct trace_probe { | |||
46 | (sizeof(struct probe_arg) * (n))) | 46 | (sizeof(struct probe_arg) * (n))) |
47 | 47 | ||
48 | 48 | ||
49 | static __kprobes int trace_probe_is_return(struct trace_probe *tp) | 49 | static __kprobes bool trace_probe_is_return(struct trace_probe *tp) |
50 | { | 50 | { |
51 | return tp->rp.handler != NULL; | 51 | return tp->rp.handler != NULL; |
52 | } | 52 | } |
@@ -183,12 +183,63 @@ static struct trace_probe *find_trace_probe(const char *event, | |||
183 | return NULL; | 183 | return NULL; |
184 | } | 184 | } |
185 | 185 | ||
186 | /* Enable trace_probe - @flag must be TP_FLAG_TRACE or TP_FLAG_PROFILE */ | 186 | static int trace_probe_nr_files(struct trace_probe *tp) |
187 | static int enable_trace_probe(struct trace_probe *tp, int flag) | 187 | { |
188 | struct ftrace_event_file **file; | ||
189 | int ret = 0; | ||
190 | |||
191 | /* | ||
192 | * Since all tp->files updater is protected by probe_enable_lock, | ||
193 | * we don't need to lock an rcu_read_lock. | ||
194 | */ | ||
195 | file = rcu_dereference_raw(tp->files); | ||
196 | if (file) | ||
197 | while (*(file++)) | ||
198 | ret++; | ||
199 | |||
200 | return ret; | ||
201 | } | ||
202 | |||
203 | static DEFINE_MUTEX(probe_enable_lock); | ||
204 | |||
205 | /* | ||
206 | * Enable trace_probe | ||
207 | * if the file is NULL, enable "perf" handler, or enable "trace" handler. | ||
208 | */ | ||
209 | static int | ||
210 | enable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file) | ||
188 | { | 211 | { |
189 | int ret = 0; | 212 | int ret = 0; |
190 | 213 | ||
191 | tp->flags |= flag; | 214 | mutex_lock(&probe_enable_lock); |
215 | |||
216 | if (file) { | ||
217 | struct ftrace_event_file **new, **old; | ||
218 | int n = trace_probe_nr_files(tp); | ||
219 | |||
220 | old = rcu_dereference_raw(tp->files); | ||
221 | /* 1 is for new one and 1 is for stopper */ | ||
222 | new = kzalloc((n + 2) * sizeof(struct ftrace_event_file *), | ||
223 | GFP_KERNEL); | ||
224 | if (!new) { | ||
225 | ret = -ENOMEM; | ||
226 | goto out_unlock; | ||
227 | } | ||
228 | memcpy(new, old, n * sizeof(struct ftrace_event_file *)); | ||
229 | new[n] = file; | ||
230 | /* The last one keeps a NULL */ | ||
231 | |||
232 | rcu_assign_pointer(tp->files, new); | ||
233 | tp->flags |= TP_FLAG_TRACE; | ||
234 | |||
235 | if (old) { | ||
236 | /* Make sure the probe is done with old files */ | ||
237 | synchronize_sched(); | ||
238 | kfree(old); | ||
239 | } | ||
240 | } else | ||
241 | tp->flags |= TP_FLAG_PROFILE; | ||
242 | |||
192 | if (trace_probe_is_enabled(tp) && trace_probe_is_registered(tp) && | 243 | if (trace_probe_is_enabled(tp) && trace_probe_is_registered(tp) && |
193 | !trace_probe_has_gone(tp)) { | 244 | !trace_probe_has_gone(tp)) { |
194 | if (trace_probe_is_return(tp)) | 245 | if (trace_probe_is_return(tp)) |
@@ -197,19 +248,90 @@ static int enable_trace_probe(struct trace_probe *tp, int flag) | |||
197 | ret = enable_kprobe(&tp->rp.kp); | 248 | ret = enable_kprobe(&tp->rp.kp); |
198 | } | 249 | } |
199 | 250 | ||
251 | out_unlock: | ||
252 | mutex_unlock(&probe_enable_lock); | ||
253 | |||
200 | return ret; | 254 | return ret; |
201 | } | 255 | } |
202 | 256 | ||
203 | /* Disable trace_probe - @flag must be TP_FLAG_TRACE or TP_FLAG_PROFILE */ | 257 | static int |
204 | static void disable_trace_probe(struct trace_probe *tp, int flag) | 258 | trace_probe_file_index(struct trace_probe *tp, struct ftrace_event_file *file) |
259 | { | ||
260 | struct ftrace_event_file **files; | ||
261 | int i; | ||
262 | |||
263 | /* | ||
264 | * Since all tp->files updater is protected by probe_enable_lock, | ||
265 | * we don't need to lock an rcu_read_lock. | ||
266 | */ | ||
267 | files = rcu_dereference_raw(tp->files); | ||
268 | if (files) { | ||
269 | for (i = 0; files[i]; i++) | ||
270 | if (files[i] == file) | ||
271 | return i; | ||
272 | } | ||
273 | |||
274 | return -1; | ||
275 | } | ||
276 | |||
277 | /* | ||
278 | * Disable trace_probe | ||
279 | * if the file is NULL, disable "perf" handler, or disable "trace" handler. | ||
280 | */ | ||
281 | static int | ||
282 | disable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file) | ||
205 | { | 283 | { |
206 | tp->flags &= ~flag; | 284 | int ret = 0; |
285 | |||
286 | mutex_lock(&probe_enable_lock); | ||
287 | |||
288 | if (file) { | ||
289 | struct ftrace_event_file **new, **old; | ||
290 | int n = trace_probe_nr_files(tp); | ||
291 | int i, j; | ||
292 | |||
293 | old = rcu_dereference_raw(tp->files); | ||
294 | if (n == 0 || trace_probe_file_index(tp, file) < 0) { | ||
295 | ret = -EINVAL; | ||
296 | goto out_unlock; | ||
297 | } | ||
298 | |||
299 | if (n == 1) { /* Remove the last file */ | ||
300 | tp->flags &= ~TP_FLAG_TRACE; | ||
301 | new = NULL; | ||
302 | } else { | ||
303 | new = kzalloc(n * sizeof(struct ftrace_event_file *), | ||
304 | GFP_KERNEL); | ||
305 | if (!new) { | ||
306 | ret = -ENOMEM; | ||
307 | goto out_unlock; | ||
308 | } | ||
309 | |||
310 | /* This copy & check loop copies the NULL stopper too */ | ||
311 | for (i = 0, j = 0; j < n && i < n + 1; i++) | ||
312 | if (old[i] != file) | ||
313 | new[j++] = old[i]; | ||
314 | } | ||
315 | |||
316 | rcu_assign_pointer(tp->files, new); | ||
317 | |||
318 | /* Make sure the probe is done with old files */ | ||
319 | synchronize_sched(); | ||
320 | kfree(old); | ||
321 | } else | ||
322 | tp->flags &= ~TP_FLAG_PROFILE; | ||
323 | |||
207 | if (!trace_probe_is_enabled(tp) && trace_probe_is_registered(tp)) { | 324 | if (!trace_probe_is_enabled(tp) && trace_probe_is_registered(tp)) { |
208 | if (trace_probe_is_return(tp)) | 325 | if (trace_probe_is_return(tp)) |
209 | disable_kretprobe(&tp->rp); | 326 | disable_kretprobe(&tp->rp); |
210 | else | 327 | else |
211 | disable_kprobe(&tp->rp.kp); | 328 | disable_kprobe(&tp->rp.kp); |
212 | } | 329 | } |
330 | |||
331 | out_unlock: | ||
332 | mutex_unlock(&probe_enable_lock); | ||
333 | |||
334 | return ret; | ||
213 | } | 335 | } |
214 | 336 | ||
215 | /* Internal register function - just handle k*probes and flags */ | 337 | /* Internal register function - just handle k*probes and flags */ |
@@ -723,9 +845,10 @@ static __kprobes void store_trace_args(int ent_size, struct trace_probe *tp, | |||
723 | } | 845 | } |
724 | 846 | ||
725 | /* Kprobe handler */ | 847 | /* Kprobe handler */ |
726 | static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) | 848 | static __kprobes void |
849 | __kprobe_trace_func(struct trace_probe *tp, struct pt_regs *regs, | ||
850 | struct ftrace_event_file *ftrace_file) | ||
727 | { | 851 | { |
728 | struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp); | ||
729 | struct kprobe_trace_entry_head *entry; | 852 | struct kprobe_trace_entry_head *entry; |
730 | struct ring_buffer_event *event; | 853 | struct ring_buffer_event *event; |
731 | struct ring_buffer *buffer; | 854 | struct ring_buffer *buffer; |
@@ -733,7 +856,10 @@ static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) | |||
733 | unsigned long irq_flags; | 856 | unsigned long irq_flags; |
734 | struct ftrace_event_call *call = &tp->call; | 857 | struct ftrace_event_call *call = &tp->call; |
735 | 858 | ||
736 | tp->nhit++; | 859 | WARN_ON(call != ftrace_file->event_call); |
860 | |||
861 | if (test_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &ftrace_file->flags)) | ||
862 | return; | ||
737 | 863 | ||
738 | local_save_flags(irq_flags); | 864 | local_save_flags(irq_flags); |
739 | pc = preempt_count(); | 865 | pc = preempt_count(); |
@@ -741,13 +867,14 @@ static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) | |||
741 | dsize = __get_data_size(tp, regs); | 867 | dsize = __get_data_size(tp, regs); |
742 | size = sizeof(*entry) + tp->size + dsize; | 868 | size = sizeof(*entry) + tp->size + dsize; |
743 | 869 | ||
744 | event = trace_current_buffer_lock_reserve(&buffer, call->event.type, | 870 | event = trace_event_buffer_lock_reserve(&buffer, ftrace_file, |
745 | size, irq_flags, pc); | 871 | call->event.type, |
872 | size, irq_flags, pc); | ||
746 | if (!event) | 873 | if (!event) |
747 | return; | 874 | return; |
748 | 875 | ||
749 | entry = ring_buffer_event_data(event); | 876 | entry = ring_buffer_event_data(event); |
750 | entry->ip = (unsigned long)kp->addr; | 877 | entry->ip = (unsigned long)tp->rp.kp.addr; |
751 | store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize); | 878 | store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize); |
752 | 879 | ||
753 | if (!filter_current_check_discard(buffer, call, entry, event)) | 880 | if (!filter_current_check_discard(buffer, call, entry, event)) |
@@ -755,11 +882,31 @@ static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) | |||
755 | irq_flags, pc, regs); | 882 | irq_flags, pc, regs); |
756 | } | 883 | } |
757 | 884 | ||
885 | static __kprobes void | ||
886 | kprobe_trace_func(struct trace_probe *tp, struct pt_regs *regs) | ||
887 | { | ||
888 | /* | ||
889 | * Note: preempt is already disabled around the kprobe handler. | ||
890 | * However, we still need an smp_read_barrier_depends() corresponding | ||
891 | * to smp_wmb() in rcu_assign_pointer() to access the pointer. | ||
892 | */ | ||
893 | struct ftrace_event_file **file = rcu_dereference_raw(tp->files); | ||
894 | |||
895 | if (unlikely(!file)) | ||
896 | return; | ||
897 | |||
898 | while (*file) { | ||
899 | __kprobe_trace_func(tp, regs, *file); | ||
900 | file++; | ||
901 | } | ||
902 | } | ||
903 | |||
758 | /* Kretprobe handler */ | 904 | /* Kretprobe handler */ |
759 | static __kprobes void kretprobe_trace_func(struct kretprobe_instance *ri, | 905 | static __kprobes void |
760 | struct pt_regs *regs) | 906 | __kretprobe_trace_func(struct trace_probe *tp, struct kretprobe_instance *ri, |
907 | struct pt_regs *regs, | ||
908 | struct ftrace_event_file *ftrace_file) | ||
761 | { | 909 | { |
762 | struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp); | ||
763 | struct kretprobe_trace_entry_head *entry; | 910 | struct kretprobe_trace_entry_head *entry; |
764 | struct ring_buffer_event *event; | 911 | struct ring_buffer_event *event; |
765 | struct ring_buffer *buffer; | 912 | struct ring_buffer *buffer; |
@@ -767,14 +914,20 @@ static __kprobes void kretprobe_trace_func(struct kretprobe_instance *ri, | |||
767 | unsigned long irq_flags; | 914 | unsigned long irq_flags; |
768 | struct ftrace_event_call *call = &tp->call; | 915 | struct ftrace_event_call *call = &tp->call; |
769 | 916 | ||
917 | WARN_ON(call != ftrace_file->event_call); | ||
918 | |||
919 | if (test_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &ftrace_file->flags)) | ||
920 | return; | ||
921 | |||
770 | local_save_flags(irq_flags); | 922 | local_save_flags(irq_flags); |
771 | pc = preempt_count(); | 923 | pc = preempt_count(); |
772 | 924 | ||
773 | dsize = __get_data_size(tp, regs); | 925 | dsize = __get_data_size(tp, regs); |
774 | size = sizeof(*entry) + tp->size + dsize; | 926 | size = sizeof(*entry) + tp->size + dsize; |
775 | 927 | ||
776 | event = trace_current_buffer_lock_reserve(&buffer, call->event.type, | 928 | event = trace_event_buffer_lock_reserve(&buffer, ftrace_file, |
777 | size, irq_flags, pc); | 929 | call->event.type, |
930 | size, irq_flags, pc); | ||
778 | if (!event) | 931 | if (!event) |
779 | return; | 932 | return; |
780 | 933 | ||
@@ -788,8 +941,28 @@ static __kprobes void kretprobe_trace_func(struct kretprobe_instance *ri, | |||
788 | irq_flags, pc, regs); | 941 | irq_flags, pc, regs); |
789 | } | 942 | } |
790 | 943 | ||
944 | static __kprobes void | ||
945 | kretprobe_trace_func(struct trace_probe *tp, struct kretprobe_instance *ri, | ||
946 | struct pt_regs *regs) | ||
947 | { | ||
948 | /* | ||
949 | * Note: preempt is already disabled around the kprobe handler. | ||
950 | * However, we still need an smp_read_barrier_depends() corresponding | ||
951 | * to smp_wmb() in rcu_assign_pointer() to access the pointer. | ||
952 | */ | ||
953 | struct ftrace_event_file **file = rcu_dereference_raw(tp->files); | ||
954 | |||
955 | if (unlikely(!file)) | ||
956 | return; | ||
957 | |||
958 | while (*file) { | ||
959 | __kretprobe_trace_func(tp, ri, regs, *file); | ||
960 | file++; | ||
961 | } | ||
962 | } | ||
963 | |||
791 | /* Event entry printers */ | 964 | /* Event entry printers */ |
792 | enum print_line_t | 965 | static enum print_line_t |
793 | print_kprobe_event(struct trace_iterator *iter, int flags, | 966 | print_kprobe_event(struct trace_iterator *iter, int flags, |
794 | struct trace_event *event) | 967 | struct trace_event *event) |
795 | { | 968 | { |
@@ -825,7 +998,7 @@ partial: | |||
825 | return TRACE_TYPE_PARTIAL_LINE; | 998 | return TRACE_TYPE_PARTIAL_LINE; |
826 | } | 999 | } |
827 | 1000 | ||
828 | enum print_line_t | 1001 | static enum print_line_t |
829 | print_kretprobe_event(struct trace_iterator *iter, int flags, | 1002 | print_kretprobe_event(struct trace_iterator *iter, int flags, |
830 | struct trace_event *event) | 1003 | struct trace_event *event) |
831 | { | 1004 | { |
@@ -975,10 +1148,9 @@ static int set_print_fmt(struct trace_probe *tp) | |||
975 | #ifdef CONFIG_PERF_EVENTS | 1148 | #ifdef CONFIG_PERF_EVENTS |
976 | 1149 | ||
977 | /* Kprobe profile handler */ | 1150 | /* Kprobe profile handler */ |
978 | static __kprobes void kprobe_perf_func(struct kprobe *kp, | 1151 | static __kprobes void |
979 | struct pt_regs *regs) | 1152 | kprobe_perf_func(struct trace_probe *tp, struct pt_regs *regs) |
980 | { | 1153 | { |
981 | struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp); | ||
982 | struct ftrace_event_call *call = &tp->call; | 1154 | struct ftrace_event_call *call = &tp->call; |
983 | struct kprobe_trace_entry_head *entry; | 1155 | struct kprobe_trace_entry_head *entry; |
984 | struct hlist_head *head; | 1156 | struct hlist_head *head; |
@@ -997,7 +1169,7 @@ static __kprobes void kprobe_perf_func(struct kprobe *kp, | |||
997 | if (!entry) | 1169 | if (!entry) |
998 | return; | 1170 | return; |
999 | 1171 | ||
1000 | entry->ip = (unsigned long)kp->addr; | 1172 | entry->ip = (unsigned long)tp->rp.kp.addr; |
1001 | memset(&entry[1], 0, dsize); | 1173 | memset(&entry[1], 0, dsize); |
1002 | store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize); | 1174 | store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize); |
1003 | 1175 | ||
@@ -1007,10 +1179,10 @@ static __kprobes void kprobe_perf_func(struct kprobe *kp, | |||
1007 | } | 1179 | } |
1008 | 1180 | ||
1009 | /* Kretprobe profile handler */ | 1181 | /* Kretprobe profile handler */ |
1010 | static __kprobes void kretprobe_perf_func(struct kretprobe_instance *ri, | 1182 | static __kprobes void |
1011 | struct pt_regs *regs) | 1183 | kretprobe_perf_func(struct trace_probe *tp, struct kretprobe_instance *ri, |
1184 | struct pt_regs *regs) | ||
1012 | { | 1185 | { |
1013 | struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp); | ||
1014 | struct ftrace_event_call *call = &tp->call; | 1186 | struct ftrace_event_call *call = &tp->call; |
1015 | struct kretprobe_trace_entry_head *entry; | 1187 | struct kretprobe_trace_entry_head *entry; |
1016 | struct hlist_head *head; | 1188 | struct hlist_head *head; |
@@ -1044,20 +1216,19 @@ int kprobe_register(struct ftrace_event_call *event, | |||
1044 | enum trace_reg type, void *data) | 1216 | enum trace_reg type, void *data) |
1045 | { | 1217 | { |
1046 | struct trace_probe *tp = (struct trace_probe *)event->data; | 1218 | struct trace_probe *tp = (struct trace_probe *)event->data; |
1219 | struct ftrace_event_file *file = data; | ||
1047 | 1220 | ||
1048 | switch (type) { | 1221 | switch (type) { |
1049 | case TRACE_REG_REGISTER: | 1222 | case TRACE_REG_REGISTER: |
1050 | return enable_trace_probe(tp, TP_FLAG_TRACE); | 1223 | return enable_trace_probe(tp, file); |
1051 | case TRACE_REG_UNREGISTER: | 1224 | case TRACE_REG_UNREGISTER: |
1052 | disable_trace_probe(tp, TP_FLAG_TRACE); | 1225 | return disable_trace_probe(tp, file); |
1053 | return 0; | ||
1054 | 1226 | ||
1055 | #ifdef CONFIG_PERF_EVENTS | 1227 | #ifdef CONFIG_PERF_EVENTS |
1056 | case TRACE_REG_PERF_REGISTER: | 1228 | case TRACE_REG_PERF_REGISTER: |
1057 | return enable_trace_probe(tp, TP_FLAG_PROFILE); | 1229 | return enable_trace_probe(tp, NULL); |
1058 | case TRACE_REG_PERF_UNREGISTER: | 1230 | case TRACE_REG_PERF_UNREGISTER: |
1059 | disable_trace_probe(tp, TP_FLAG_PROFILE); | 1231 | return disable_trace_probe(tp, NULL); |
1060 | return 0; | ||
1061 | case TRACE_REG_PERF_OPEN: | 1232 | case TRACE_REG_PERF_OPEN: |
1062 | case TRACE_REG_PERF_CLOSE: | 1233 | case TRACE_REG_PERF_CLOSE: |
1063 | case TRACE_REG_PERF_ADD: | 1234 | case TRACE_REG_PERF_ADD: |
@@ -1073,11 +1244,13 @@ int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs) | |||
1073 | { | 1244 | { |
1074 | struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp); | 1245 | struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp); |
1075 | 1246 | ||
1247 | tp->nhit++; | ||
1248 | |||
1076 | if (tp->flags & TP_FLAG_TRACE) | 1249 | if (tp->flags & TP_FLAG_TRACE) |
1077 | kprobe_trace_func(kp, regs); | 1250 | kprobe_trace_func(tp, regs); |
1078 | #ifdef CONFIG_PERF_EVENTS | 1251 | #ifdef CONFIG_PERF_EVENTS |
1079 | if (tp->flags & TP_FLAG_PROFILE) | 1252 | if (tp->flags & TP_FLAG_PROFILE) |
1080 | kprobe_perf_func(kp, regs); | 1253 | kprobe_perf_func(tp, regs); |
1081 | #endif | 1254 | #endif |
1082 | return 0; /* We don't tweek kernel, so just return 0 */ | 1255 | return 0; /* We don't tweek kernel, so just return 0 */ |
1083 | } | 1256 | } |
@@ -1087,11 +1260,13 @@ int kretprobe_dispatcher(struct kretprobe_instance *ri, struct pt_regs *regs) | |||
1087 | { | 1260 | { |
1088 | struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp); | 1261 | struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp); |
1089 | 1262 | ||
1263 | tp->nhit++; | ||
1264 | |||
1090 | if (tp->flags & TP_FLAG_TRACE) | 1265 | if (tp->flags & TP_FLAG_TRACE) |
1091 | kretprobe_trace_func(ri, regs); | 1266 | kretprobe_trace_func(tp, ri, regs); |
1092 | #ifdef CONFIG_PERF_EVENTS | 1267 | #ifdef CONFIG_PERF_EVENTS |
1093 | if (tp->flags & TP_FLAG_PROFILE) | 1268 | if (tp->flags & TP_FLAG_PROFILE) |
1094 | kretprobe_perf_func(ri, regs); | 1269 | kretprobe_perf_func(tp, ri, regs); |
1095 | #endif | 1270 | #endif |
1096 | return 0; /* We don't tweek kernel, so just return 0 */ | 1271 | return 0; /* We don't tweek kernel, so just return 0 */ |
1097 | } | 1272 | } |
@@ -1189,11 +1364,24 @@ static __used int kprobe_trace_selftest_target(int a1, int a2, int a3, | |||
1189 | return a1 + a2 + a3 + a4 + a5 + a6; | 1364 | return a1 + a2 + a3 + a4 + a5 + a6; |
1190 | } | 1365 | } |
1191 | 1366 | ||
1367 | static struct ftrace_event_file * | ||
1368 | find_trace_probe_file(struct trace_probe *tp, struct trace_array *tr) | ||
1369 | { | ||
1370 | struct ftrace_event_file *file; | ||
1371 | |||
1372 | list_for_each_entry(file, &tr->events, list) | ||
1373 | if (file->event_call == &tp->call) | ||
1374 | return file; | ||
1375 | |||
1376 | return NULL; | ||
1377 | } | ||
1378 | |||
1192 | static __init int kprobe_trace_self_tests_init(void) | 1379 | static __init int kprobe_trace_self_tests_init(void) |
1193 | { | 1380 | { |
1194 | int ret, warn = 0; | 1381 | int ret, warn = 0; |
1195 | int (*target)(int, int, int, int, int, int); | 1382 | int (*target)(int, int, int, int, int, int); |
1196 | struct trace_probe *tp; | 1383 | struct trace_probe *tp; |
1384 | struct ftrace_event_file *file; | ||
1197 | 1385 | ||
1198 | target = kprobe_trace_selftest_target; | 1386 | target = kprobe_trace_selftest_target; |
1199 | 1387 | ||
@@ -1203,31 +1391,43 @@ static __init int kprobe_trace_self_tests_init(void) | |||
1203 | "$stack $stack0 +0($stack)", | 1391 | "$stack $stack0 +0($stack)", |
1204 | create_trace_probe); | 1392 | create_trace_probe); |
1205 | if (WARN_ON_ONCE(ret)) { | 1393 | if (WARN_ON_ONCE(ret)) { |
1206 | pr_warning("error on probing function entry.\n"); | 1394 | pr_warn("error on probing function entry.\n"); |
1207 | warn++; | 1395 | warn++; |
1208 | } else { | 1396 | } else { |
1209 | /* Enable trace point */ | 1397 | /* Enable trace point */ |
1210 | tp = find_trace_probe("testprobe", KPROBE_EVENT_SYSTEM); | 1398 | tp = find_trace_probe("testprobe", KPROBE_EVENT_SYSTEM); |
1211 | if (WARN_ON_ONCE(tp == NULL)) { | 1399 | if (WARN_ON_ONCE(tp == NULL)) { |
1212 | pr_warning("error on getting new probe.\n"); | 1400 | pr_warn("error on getting new probe.\n"); |
1213 | warn++; | 1401 | warn++; |
1214 | } else | 1402 | } else { |
1215 | enable_trace_probe(tp, TP_FLAG_TRACE); | 1403 | file = find_trace_probe_file(tp, top_trace_array()); |
1404 | if (WARN_ON_ONCE(file == NULL)) { | ||
1405 | pr_warn("error on getting probe file.\n"); | ||
1406 | warn++; | ||
1407 | } else | ||
1408 | enable_trace_probe(tp, file); | ||
1409 | } | ||
1216 | } | 1410 | } |
1217 | 1411 | ||
1218 | ret = traceprobe_command("r:testprobe2 kprobe_trace_selftest_target " | 1412 | ret = traceprobe_command("r:testprobe2 kprobe_trace_selftest_target " |
1219 | "$retval", create_trace_probe); | 1413 | "$retval", create_trace_probe); |
1220 | if (WARN_ON_ONCE(ret)) { | 1414 | if (WARN_ON_ONCE(ret)) { |
1221 | pr_warning("error on probing function return.\n"); | 1415 | pr_warn("error on probing function return.\n"); |
1222 | warn++; | 1416 | warn++; |
1223 | } else { | 1417 | } else { |
1224 | /* Enable trace point */ | 1418 | /* Enable trace point */ |
1225 | tp = find_trace_probe("testprobe2", KPROBE_EVENT_SYSTEM); | 1419 | tp = find_trace_probe("testprobe2", KPROBE_EVENT_SYSTEM); |
1226 | if (WARN_ON_ONCE(tp == NULL)) { | 1420 | if (WARN_ON_ONCE(tp == NULL)) { |
1227 | pr_warning("error on getting new probe.\n"); | 1421 | pr_warn("error on getting 2nd new probe.\n"); |
1228 | warn++; | 1422 | warn++; |
1229 | } else | 1423 | } else { |
1230 | enable_trace_probe(tp, TP_FLAG_TRACE); | 1424 | file = find_trace_probe_file(tp, top_trace_array()); |
1425 | if (WARN_ON_ONCE(file == NULL)) { | ||
1426 | pr_warn("error on getting probe file.\n"); | ||
1427 | warn++; | ||
1428 | } else | ||
1429 | enable_trace_probe(tp, file); | ||
1430 | } | ||
1231 | } | 1431 | } |
1232 | 1432 | ||
1233 | if (warn) | 1433 | if (warn) |
@@ -1238,27 +1438,39 @@ static __init int kprobe_trace_self_tests_init(void) | |||
1238 | /* Disable trace points before removing it */ | 1438 | /* Disable trace points before removing it */ |
1239 | tp = find_trace_probe("testprobe", KPROBE_EVENT_SYSTEM); | 1439 | tp = find_trace_probe("testprobe", KPROBE_EVENT_SYSTEM); |
1240 | if (WARN_ON_ONCE(tp == NULL)) { | 1440 | if (WARN_ON_ONCE(tp == NULL)) { |
1241 | pr_warning("error on getting test probe.\n"); | 1441 | pr_warn("error on getting test probe.\n"); |
1242 | warn++; | 1442 | warn++; |
1243 | } else | 1443 | } else { |
1244 | disable_trace_probe(tp, TP_FLAG_TRACE); | 1444 | file = find_trace_probe_file(tp, top_trace_array()); |
1445 | if (WARN_ON_ONCE(file == NULL)) { | ||
1446 | pr_warn("error on getting probe file.\n"); | ||
1447 | warn++; | ||
1448 | } else | ||
1449 | disable_trace_probe(tp, file); | ||
1450 | } | ||
1245 | 1451 | ||
1246 | tp = find_trace_probe("testprobe2", KPROBE_EVENT_SYSTEM); | 1452 | tp = find_trace_probe("testprobe2", KPROBE_EVENT_SYSTEM); |
1247 | if (WARN_ON_ONCE(tp == NULL)) { | 1453 | if (WARN_ON_ONCE(tp == NULL)) { |
1248 | pr_warning("error on getting 2nd test probe.\n"); | 1454 | pr_warn("error on getting 2nd test probe.\n"); |
1249 | warn++; | 1455 | warn++; |
1250 | } else | 1456 | } else { |
1251 | disable_trace_probe(tp, TP_FLAG_TRACE); | 1457 | file = find_trace_probe_file(tp, top_trace_array()); |
1458 | if (WARN_ON_ONCE(file == NULL)) { | ||
1459 | pr_warn("error on getting probe file.\n"); | ||
1460 | warn++; | ||
1461 | } else | ||
1462 | disable_trace_probe(tp, file); | ||
1463 | } | ||
1252 | 1464 | ||
1253 | ret = traceprobe_command("-:testprobe", create_trace_probe); | 1465 | ret = traceprobe_command("-:testprobe", create_trace_probe); |
1254 | if (WARN_ON_ONCE(ret)) { | 1466 | if (WARN_ON_ONCE(ret)) { |
1255 | pr_warning("error on deleting a probe.\n"); | 1467 | pr_warn("error on deleting a probe.\n"); |
1256 | warn++; | 1468 | warn++; |
1257 | } | 1469 | } |
1258 | 1470 | ||
1259 | ret = traceprobe_command("-:testprobe2", create_trace_probe); | 1471 | ret = traceprobe_command("-:testprobe2", create_trace_probe); |
1260 | if (WARN_ON_ONCE(ret)) { | 1472 | if (WARN_ON_ONCE(ret)) { |
1261 | pr_warning("error on deleting a probe.\n"); | 1473 | pr_warn("error on deleting a probe.\n"); |
1262 | warn++; | 1474 | warn++; |
1263 | } | 1475 | } |
1264 | 1476 | ||