aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/trace/trace_uprobe.c93
1 files changed, 56 insertions, 37 deletions
</
diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c
index c5d2612bf233..d83155e0da78 100644
--- a/kernel/trace/trace_uprobe.c
+++ b/kernel/trace/trace_uprobe.c
@@ -759,30 +759,25 @@ static void uprobe_buffer_put(struct uprobe_cpu_buffer *ucb)
759} 759}
760 760
761static void __uprobe_trace_func(struct trace_uprobe *tu, 761static void __uprobe_trace_func(struct trace_uprobe *tu,
762 unsigned long func, struct pt_regs *regs) 762 unsigned long func, struct pt_regs *regs,
763 struct uprobe_cpu_buffer *ucb, int dsize)
763{ 764{
764 struct uprobe_trace_entry_head *entry; 765 struct uprobe_trace_entry_head *entry;
765 struct ring_buffer_event *event; 766 struct ring_buffer_event *event;
766 struct ring_buffer *buffer; 767 struct ring_buffer *buffer;
767 struct uprobe_cpu_buffer *ucb;
768 void *data; 768 void *data;
769 int size, dsize, esize; 769 int size, esize;
770 struct ftrace_event_call *call = &tu->tp.call; 770 struct ftrace_event_call *call = &tu->tp.call;
771 771
772 dsize = __get_data_size(&tu->tp, regs); 772 if (WARN_ON_ONCE(tu->tp.size + dsize > PAGE_SIZE))
773 esize = SIZEOF_TRACE_ENTRY(is_ret_probe(tu));
774
775 if (WARN_ON_ONCE(!uprobe_cpu_buffer || tu->tp.size + dsize > PAGE_SIZE))
776 return; 773 return;
777 774
778 ucb = uprobe_buffer_get(); 775 esize = SIZEOF_TRACE_ENTRY(is_ret_probe(tu));
779 store_trace_args(esize, &tu->tp, regs, ucb->buf, dsize);
780
781 size = esize + tu->tp.size + dsize; 776 size = esize + tu->tp.size + dsize;
782 event = trace_current_buffer_lock_reserve(&buffer, call->event.type, 777 event = trace_current_buffer_lock_reserve(&buffer, call->event.type,
783 size, 0, 0); 778 size, 0, 0);
784 if (!event) 779 if (!event)
785 goto out; 780 return;
786 781
787 entry = ring_buffer_event_data(event); 782 entry = ring_buffer_event_data(event);
788 if (is_ret_probe(tu)) { 783 if (is_ret_probe(tu)) {
@@ -798,23 +793,22 @@ static void __uprobe_trace_func(struct trace_uprobe *tu,
798 793
799 if (!call_filter_check_discard(call, entry, buffer, event)) 794 if (!call_filter_check_discard(call, entry, buffer, event))
800 trace_buffer_unlock_commit(buffer, event, 0, 0); 795 trace_buffer_unlock_commit(buffer, event, 0, 0);
801
802out:
803 uprobe_buffer_put(ucb);
804} 796}
805 797
806/* uprobe handler */ 798/* uprobe handler */
807static int uprobe_trace_func(struct trace_uprobe *tu, struct pt_regs *regs) 799static int uprobe_trace_func(struct trace_uprobe *tu, struct pt_regs *regs,
800 struct uprobe_cpu_buffer *ucb, int dsize)
808{ 801{
809 if (!is_ret_probe(tu)) 802 if (!is_ret_probe(tu))
810 __uprobe_trace_func(tu, 0, regs); 803 __uprobe_trace_func(tu, 0, regs, ucb, dsize);
811 return 0; 804 return 0;
812} 805}
813 806
814static void uretprobe_trace_func(struct trace_uprobe *tu, unsigned long func, 807static void uretprobe_trace_func(struct trace_uprobe *tu, unsigned long func,
815 struct pt_regs *regs) 808 struct pt_regs *regs,
809 struct uprobe_cpu_buffer *ucb, int dsize)
816{ 810{
817 __uprobe_trace_func(tu, func, regs); 811 __uprobe_trace_func(tu, func, regs, ucb, dsize);
818} 812}
819 813
820/* Event entry printers */ 814/* Event entry printers */
@@ -1015,30 +1009,23 @@ static bool uprobe_perf_filter(struct uprobe_consumer *uc,
1015} 1009}
1016 1010
1017static void __uprobe_perf_func(struct trace_uprobe *tu, 1011static void __uprobe_perf_func(struct trace_uprobe *tu,
1018 unsigned long func, struct pt_regs *regs) 1012 unsigned long func, struct pt_regs *regs,
1013 struct uprobe_cpu_buffer *ucb, int dsize)
1019{ 1014{
1020 struct ftrace_event_call *call = &tu->tp.call; 1015 struct ftrace_event_call *call = &tu->tp.call;
1021 struct uprobe_trace_entry_head *entry; 1016 struct uprobe_trace_entry_head *entry;
1022 struct hlist_head *head; 1017 struct hlist_head *head;
1023 struct uprobe_cpu_buffer *ucb;
1024 void *data; 1018 void *data;
1025 int size, dsize, esize; 1019 int size, esize;
1026 int rctx; 1020 int rctx;
1027 1021
1028 dsize = __get_data_size(&tu->tp, regs);
1029 esize = SIZEOF_TRACE_ENTRY(is_ret_probe(tu)); 1022 esize = SIZEOF_TRACE_ENTRY(is_ret_probe(tu));
1030 1023
1031 if (WARN_ON_ONCE(!uprobe_cpu_buffer))
1032 return;
1033
1034 size = esize + tu->tp.size + dsize; 1024 size = esize + tu->tp.size + dsize;
1035 size = ALIGN(size + sizeof(u32), sizeof(u64)) - sizeof(u32); 1025 size = ALIGN(size + sizeof(u32), sizeof(u64)) - sizeof(u32);
1036 if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, "profile buffer not large enough")) 1026 if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, "profile buffer not large enough"))
1037 return; 1027 return;
1038 1028
1039 ucb = uprobe_buffer_get();
1040 store_trace_args(esize, &tu->tp, regs, ucb->buf, dsize);
1041
1042 preempt_disable(); 1029 preempt_disable();
1043 head = this_cpu_ptr(call->perf_events); 1030 head = this_cpu_ptr(call->perf_events);
1044 if (hlist_empty(head)) 1031 if (hlist_empty(head))
@@ -1068,24 +1055,25 @@ static void __uprobe_perf_func(struct trace_uprobe *tu,
1068 perf_trace_buf_submit(entry, size, rctx, 0, 1, regs, head, NULL); 1055 perf_trace_buf_submit(entry, size, rctx, 0, 1, regs, head, NULL);
1069 out: 1056 out:
1070 preempt_enable(); 1057 preempt_enable();
1071 uprobe_buffer_put(ucb);
1072} 1058}
1073 1059
1074/* uprobe profile handler */ 1060/* uprobe profile handler */
1075static int uprobe_perf_func(struct trace_uprobe *tu, struct pt_regs *regs) 1061static int uprobe_perf_func(struct trace_uprobe *tu, struct pt_regs *regs,
1062 struct uprobe_cpu_buffer *ucb, int dsize)
1076{ 1063{
1077 if (!uprobe_perf_filter(&tu->consumer, 0, current->mm)) 1064 if (!uprobe_perf_filter(&tu->consumer, 0, current->mm))
1078 return UPROBE_HANDLER_REMOVE; 1065 return UPROBE_HANDLER_REMOVE;
1079 1066
1080 if (!is_ret_probe(tu)) 1067 if (!is_ret_probe(tu))
1081 __uprobe_perf_func(tu, 0, regs); 1068 __uprobe_perf_func(tu, 0, regs, ucb, dsize);
1082 return 0; 1069 return 0;
1083} 1070}
1084 1071
1085static void uretprobe_perf_func(struct trace_uprobe *tu, unsigned long func, 1072static void uretprobe_perf_func(struct trace_uprobe *tu, unsigned long func,
1086 struct pt_regs *regs) 1073 struct pt_regs *regs,
1074 struct uprobe_cpu_buffer *ucb, int dsize)
1087{ 1075{
1088 __uprobe_perf_func(tu, func, regs); 1076 __uprobe_perf_func(tu, func, regs, ucb, dsize);
1089} 1077}
1090#endif /* CONFIG_PERF_EVENTS */ 1078#endif /* CONFIG_PERF_EVENTS */
1091 1079
@@ -1127,8 +1115,11 @@ static int uprobe_dispatcher(struct uprobe_consumer *con, struct pt_regs *regs)
1127{ 1115{
1128 struct trace_uprobe *tu; 1116 struct trace_uprobe *tu;
1129 struct uprobe_dispatch_data udd; 1117 struct uprobe_dispatch_data udd;
1118 struct uprobe_cpu_buffer *ucb;
1119 int dsize, esize;
1130 int ret = 0; 1120 int ret = 0;
1131 1121
1122
1132 tu = container_of(con, struct trace_uprobe, consumer); 1123 tu = container_of(con, struct trace_uprobe, consumer);
1133 tu->nhit++; 1124 tu->nhit++;
1134 1125
@@ -1137,13 +1128,29 @@ static int uprobe_dispatcher(struct uprobe_consumer *con, struct pt_regs *regs)
1137 1128
1138 current->utask->vaddr = (unsigned long) &udd; 1129 current->utask->vaddr = (unsigned long) &udd;
1139 1130
1131#ifdef CONFIG_PERF_EVENTS
1132 if ((tu->tp.flags & TP_FLAG_TRACE) == 0 &&
1133 !uprobe_perf_filter(&tu->consumer, 0, current->mm))
1134 return UPROBE_HANDLER_REMOVE;
1135#endif
1136
1137 if (WARN_ON_ONCE(!uprobe_cpu_buffer))
1138 return 0;
1139
1140 dsize = __get_data_size(&tu->tp, regs);
1141 esize = SIZEOF_TRACE_ENTRY(is_ret_probe(tu));
1142