From patchwork Wed Nov 23 08:01:48 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Song Chen X-Patchwork-Id: 24779 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp2653174wrr; Wed, 23 Nov 2022 00:04:44 -0800 (PST) X-Google-Smtp-Source: AA0mqf5SjOeh+Y+/iUjXKw+E5oU2/72jBNSQWXEKK1duIDUHOb8Q2vpwUt81WcGTse4xs9L2b0lz X-Received: by 2002:a17:90a:dc10:b0:20d:69a3:1fd9 with SMTP id i16-20020a17090adc1000b0020d69a31fd9mr36006872pjv.167.1669190683964; Wed, 23 Nov 2022 00:04:43 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1669190683; cv=none; d=google.com; s=arc-20160816; b=le54Q3bcKRnO8mZI28l0XdbSn8ghum1cbWpHJOgsZ4Jpw7puTm6GiO5Usl9nd9eTd/ Y5609zkGwURGYP9lgrjN+niiiJU5j1Zgwq/pST6C/qNfCwImIOCymIZ9QQG/Ne6aihhl wWzprIizhIxN+nYn8Lv9DjtRzmbu7RnHMjGY9CG5vFo2JgWODqPs0EuN072DOx9Eb1wV ZJ3nD8Ei8Yp0/TTZcrOWraEHMN+ny0CZSa/SoQlyXHFxpCyb5NJj3OeNau1uKoEqpykv kUTpvYVJMm7X3fDe0sa8r3vZLpU9UjuDOQJHfEMiDhnXPRrYSn0bm887nb5nYdrAmTQl 4g+Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:message-id:date:subject:cc:to:from:sender :hmm_source_type:hmm_attache_num:hmm_source_ip; bh=T0iubkX/aGcE5J0sCAGGmZH3x+m4tjyk3l6b6YP0zOQ=; b=npzGwx7Tcff/6rlUR6iK5nuPDvBajDXjXoyU8Bc7GaL0U2wJ+v0ae5YZ92KxnDVYex nnaxoLDtgqV0q5Kw+8iMhfz+4rdnq0+ksNkkUIfKmS0Kk5lfQ1WmYtOLqNqFATZDOWeP LB2Ik3Qrv3eqWjt82m3VLeakbrhz+T6Ck2a3mJM8wjXUNPcobQq1S4fHMs3nwhKBwMjy B6nrksYJdv6qm+qUncezMqFU5GT2uWQ78//9W5V2AXjug45gfSg680WIh37qhbAVYSdf 28Z1ws8PeUydCuJiSUdkmqB52t0I7hQP6elYvYbPdlZDd6+G6ThFkn2ip0PYLYVwb4l4 Zlpw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id g192-20020a636bc9000000b0047744510d34si11882680pgc.851.2022.11.23.00.04.30; Wed, 23 Nov 2022 00:04:43 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236428AbiKWH4k (ORCPT + 99 others); Wed, 23 Nov 2022 02:56:40 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33762 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236297AbiKWH4Q (ORCPT ); Wed, 23 Nov 2022 02:56:16 -0500 Received: from 189.cn (ptr.189.cn [183.61.185.103]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 7D7A6266; Tue, 22 Nov 2022 23:55:22 -0800 (PST) HMM_SOURCE_IP: 10.64.8.31:34174.1988677754 HMM_ATTACHE_NUM: 0000 HMM_SOURCE_TYPE: SMTP Received: from clientip-123.150.8.42 (unknown [10.64.8.31]) by 189.cn (HERMES) with SMTP id 24FC51001DD; Wed, 23 Nov 2022 15:55:20 +0800 (CST) Received: from ([123.150.8.42]) by gateway-153622-dep-6cffbd87dd-pzsb9 with ESMTP id 5bc6e5573a7f40ad9545e5cd099c39d9 for rostedt@goodmis.org; Wed, 23 Nov 2022 15:55:21 CST X-Transaction-ID: 5bc6e5573a7f40ad9545e5cd099c39d9 X-Real-From: chensong_2000@189.cn X-Receive-IP: 123.150.8.42 X-MEDUSA-Status: 0 Sender: chensong_2000@189.cn From: Song Chen To: rostedt@goodmis.org, mhiramat@kernel.org Cc: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, Song Chen Subject: [PATCH v2 1/2] kernel/trace: Introduce trace_probe_print_args and use it in *probes Date: Wed, 23 Nov 2022 16:01:48 +0800 Message-Id: <1669190508-2850-1-git-send-email-chensong_2000@189.cn> X-Mailer: git-send-email 2.7.4 X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00, FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM,SPF_HELO_PASS,SPF_PASS autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1750273290774013684?= X-GMAIL-MSGID: =?utf-8?q?1750273290774013684?= print_probe_args is currently inplemented in trace_probe_tmpl.h and included by *probes, as a result, each probe has an identical copy. This patch will move it to trace_probe.c as an new API, each probe calls it to print their args in trace file. Signed-off-by: Song Chen Acked-by: Masami Hiramatsu (Google) --- kernel/trace/trace_eprobe.c | 2 +- kernel/trace/trace_kprobe.c | 4 ++-- kernel/trace/trace_probe.c | 27 +++++++++++++++++++++++++++ kernel/trace/trace_probe.h | 2 ++ kernel/trace/trace_probe_tmpl.h | 28 ---------------------------- kernel/trace/trace_uprobe.c | 2 +- 6 files changed, 33 insertions(+), 32 deletions(-) diff --git a/kernel/trace/trace_eprobe.c b/kernel/trace/trace_eprobe.c index 5dd0617e5df6..bdb26eee7a0c 100644 --- a/kernel/trace/trace_eprobe.c +++ b/kernel/trace/trace_eprobe.c @@ -310,7 +310,7 @@ print_eprobe_event(struct trace_iterator *iter, int flags, trace_seq_putc(s, ')'); - if (print_probe_args(s, tp->args, tp->nr_args, + if (trace_probe_print_args(s, tp->args, tp->nr_args, (u8 *)&field[1], field) < 0) goto out; diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 5a75b039e586..a4ffa864dbb7 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c @@ -1426,7 +1426,7 @@ print_kprobe_event(struct trace_iterator *iter, int flags, trace_seq_putc(s, ')'); - if (print_probe_args(s, tp->args, tp->nr_args, + if (trace_probe_print_args(s, tp->args, tp->nr_args, (u8 *)&field[1], field) < 0) goto out; @@ -1461,7 +1461,7 @@ print_kretprobe_event(struct trace_iterator *iter, int flags, trace_seq_putc(s, ')'); - if (print_probe_args(s, tp->args, tp->nr_args, + if (trace_probe_print_args(s, tp->args, tp->nr_args, (u8 *)&field[1], field) < 0) goto out; diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c index 36dff277de46..ae13b6b2d5da 100644 --- a/kernel/trace/trace_probe.c +++ b/kernel/trace/trace_probe.c @@ -1218,3 +1218,30 @@ int trace_probe_create(const char *raw_command, int (*createfn)(int, const char return ret; } + +int trace_probe_print_args(struct trace_seq *s, struct probe_arg *args, int nr_args, + u8 *data, void *field) +{ + void *p; + int i, j; + + for (i = 0; i < nr_args; i++) { + struct probe_arg *a = args + i; + + trace_seq_printf(s, " %s=", a->name); + if (likely(!a->count)) { + if (!a->type->print(s, data + a->offset, field)) + return -ENOMEM; + continue; + } + trace_seq_putc(s, '{'); + p = data + a->offset; + for (j = 0; j < a->count; j++) { + if (!a->type->print(s, p, field)) + return -ENOMEM; + trace_seq_putc(s, j == a->count - 1 ? '}' : ','); + p += a->type->size; + } + } + return 0; +} diff --git a/kernel/trace/trace_probe.h b/kernel/trace/trace_probe.h index de38f1c03776..cfef198013af 100644 --- a/kernel/trace/trace_probe.h +++ b/kernel/trace/trace_probe.h @@ -343,6 +343,8 @@ int trace_probe_compare_arg_type(struct trace_probe *a, struct trace_probe *b); bool trace_probe_match_command_args(struct trace_probe *tp, int argc, const char **argv); int trace_probe_create(const char *raw_command, int (*createfn)(int, const char **)); +int trace_probe_print_args(struct trace_seq *s, struct probe_arg *args, int nr_args, + u8 *data, void *field); #define trace_probe_for_each_link(pos, tp) \ list_for_each_entry(pos, &(tp)->event->files, list) diff --git a/kernel/trace/trace_probe_tmpl.h b/kernel/trace/trace_probe_tmpl.h index b3bdb8ddb862..1b57420857e1 100644 --- a/kernel/trace/trace_probe_tmpl.h +++ b/kernel/trace/trace_probe_tmpl.h @@ -212,31 +212,3 @@ store_trace_args(void *data, struct trace_probe *tp, void *rec, } } } - -static inline int -print_probe_args(struct trace_seq *s, struct probe_arg *args, int nr_args, - u8 *data, void *field) -{ - void *p; - int i, j; - - for (i = 0; i < nr_args; i++) { - struct probe_arg *a = args + i; - - trace_seq_printf(s, " %s=", a->name); - if (likely(!a->count)) { - if (!a->type->print(s, data + a->offset, field)) - return -ENOMEM; - continue; - } - trace_seq_putc(s, '{'); - p = data + a->offset; - for (j = 0; j < a->count; j++) { - if (!a->type->print(s, p, field)) - return -ENOMEM; - trace_seq_putc(s, j == a->count - 1 ? '}' : ','); - p += a->type->size; - } - } - return 0; -} diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c index fb58e86dd117..1ff8f87211a6 100644 --- a/kernel/trace/trace_uprobe.c +++ b/kernel/trace/trace_uprobe.c @@ -1041,7 +1041,7 @@ print_uprobe_event(struct trace_iterator *iter, int flags, struct trace_event *e data = DATAOF_TRACE_ENTRY(entry, false); } - if (print_probe_args(s, tu->tp.args, tu->tp.nr_args, data, entry) < 0) + if (trace_probe_print_args(s, tu->tp.args, tu->tp.nr_args, data, entry) < 0) goto out; trace_seq_putc(s, '\n'); From patchwork Wed Nov 23 08:02:04 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Song Chen X-Patchwork-Id: 24780 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp2653277wrr; Wed, 23 Nov 2022 00:04:58 -0800 (PST) X-Google-Smtp-Source: AA0mqf47A50peUo+MYX9DibdqhhSgz03xw1SfV+PK2ITfPeLBD5VjhcdbwXO6xJzgm0963dTZtLH X-Received: by 2002:a63:cf41:0:b0:476:c65c:3761 with SMTP id b1-20020a63cf41000000b00476c65c3761mr8914775pgj.57.1669190698290; Wed, 23 Nov 2022 00:04:58 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1669190698; cv=none; d=google.com; s=arc-20160816; b=ERUMFH82h7PkZ/efSiOZW+grD6mb8jmyMn6bX6s1OBHuzmbz1M9uHbLrmP9L0/EkL1 ADWXy2ROv/FQmbSoYHaNf67fx93FrueFO0MUCDcAu+IVhRrEzD7AUXuMm6qf99CuXUhr /l8qaExKyzjNvaaVCZtoB5cCpiPGzt697aD2GE/rL5KxLDyO86dxXc/KLa8KbixD2ux4 AqnuO2mYM+kRl66hBoJTfJ4BpVyndOBDZ0AxIzmE+AdM5DNOiMdjxGUcEiEWNV2TDTmC b8HkT8l5TnuvbSnYNAdHsQ5e10qnaFzEPNgBJHiW7hgH4GwMbsU1bQ4shYSijOURDfWM pdyA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:message-id:date:subject:cc:to:from:sender :hmm_source_type:hmm_attache_num:hmm_source_ip; bh=K4dag1iNSR23loG6/mOC7cFwq8m2bmX4dlSmUPMn+1A=; b=OkmdTS0a8lx2yEevpOMAm1XS+lZmBVcOSBIBYyUIcUdbtltpLoz9vapbUCXjAljLBl FEGMsybcNXaKwgrnK7dRjwVKrflTnqkTAjlbAL2Otfuatf51ja+B66Y99qLULf3o9eBO mxIQLGJn6xqYZSTfqaPdqLb65wyLms0rVM0I/FMqEE2SeeklP3Z7ZZ2ESP7Ii161q53H vDwNzjf4wqPjGUksnxvHi/JeiUHmMlpbTrb3pipQTVFvBDS/StTq8tBYNNM4Dp8O3/6S U3xhKvx5Udc8gRUVSUCNg5JBRpseSf8Gg7W1U7hRAI77dlGOqxLv33Ttw21ExEyGjQ+G L9ig== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id f13-20020a170902ce8d00b0018862b71d11si17946904plg.381.2022.11.23.00.04.45; Wed, 23 Nov 2022 00:04:58 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236380AbiKWH4m (ORCPT + 99 others); Wed, 23 Nov 2022 02:56:42 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33778 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229563AbiKWH4Q (ORCPT ); Wed, 23 Nov 2022 02:56:16 -0500 Received: from 189.cn (ptr.189.cn [183.61.185.102]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 46BC5B12; Tue, 22 Nov 2022 23:55:37 -0800 (PST) HMM_SOURCE_IP: 10.64.8.41:60424.395643342 HMM_ATTACHE_NUM: 0000 HMM_SOURCE_TYPE: SMTP Received: from clientip-123.150.8.42 (unknown [10.64.8.41]) by 189.cn (HERMES) with SMTP id 7162E1002F8; Wed, 23 Nov 2022 15:55:35 +0800 (CST) Received: from ([123.150.8.42]) by gateway-153622-dep-6cffbd87dd-5n69v with ESMTP id 5ffab1451469406dac7f2bfd4a4a65a3 for rostedt@goodmis.org; Wed, 23 Nov 2022 15:55:36 CST X-Transaction-ID: 5ffab1451469406dac7f2bfd4a4a65a3 X-Real-From: chensong_2000@189.cn X-Receive-IP: 123.150.8.42 X-MEDUSA-Status: 0 Sender: chensong_2000@189.cn From: Song Chen To: rostedt@goodmis.org, mhiramat@kernel.org Cc: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, Song Chen Subject: [PATCH v2 2/2] kernel/trace: Provide default impelentations defined in trace_probe_tmpl.h Date: Wed, 23 Nov 2022 16:02:04 +0800 Message-Id: <1669190524-2894-1-git-send-email-chensong_2000@189.cn> X-Mailer: git-send-email 2.7.4 X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00, FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM,RCVD_IN_MSPIKE_H2, SPF_HELO_PASS,SPF_PASS autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1750273305620030381?= X-GMAIL-MSGID: =?utf-8?q?1750273305620030381?= There are 7 function definitions in trace_probe_tmpl.h, they are: 1, process_fetch_insn 2, fetch_store_strlen 3, fetch_store_string 4, fetch_store_strlen_user 5, fetch_store_string_user 6, probe_mem_read 7, probe_mem_read_user Every C file which includes trace_probe_tmpl.h has to implement them, otherwise it gets warnings and errors. However, some of them are identical, like kprobe and eprobe, as a result, there is a lot redundant code in those 2 files. This patch would like to provide default behaviors for those functions which kprobe and eprobe can share by just including trace_probe_kernel.h with trace_probe_tmpl.h together. It removes redundant code, increases readability, and more importantly, makes it easier to introduce a new feature based on trace probe (it's possible). Signed-off-by: Song Chen --- kernel/trace/trace_eprobe.c | 144 ------------------------------ kernel/trace/trace_events_synth.c | 7 +- kernel/trace/trace_kprobe.c | 102 --------------------- kernel/trace/trace_probe_kernel.h | 140 +++++++++++++++++++++++++++-- 4 files changed, 138 insertions(+), 255 deletions(-) diff --git a/kernel/trace/trace_eprobe.c b/kernel/trace/trace_eprobe.c index bdb26eee7a0c..60ced4a7a25d 100644 --- a/kernel/trace/trace_eprobe.c +++ b/kernel/trace/trace_eprobe.c @@ -319,64 +319,6 @@ print_eprobe_event(struct trace_iterator *iter, int flags, return trace_handle_return(s); } -static unsigned long get_event_field(struct fetch_insn *code, void *rec) -{ - struct ftrace_event_field *field = code->data; - unsigned long val; - void *addr; - - addr = rec + field->offset; - - if (is_string_field(field)) { - switch (field->filter_type) { - case FILTER_DYN_STRING: - val = (unsigned long)(rec + (*(unsigned int *)addr & 0xffff)); - break; - case FILTER_RDYN_STRING: - val = (unsigned long)(addr + (*(unsigned int *)addr & 0xffff)); - break; - case FILTER_STATIC_STRING: - val = (unsigned long)addr; - break; - case FILTER_PTR_STRING: - val = (unsigned long)(*(char *)addr); - break; - default: - WARN_ON_ONCE(1); - return 0; - } - return val; - } - - switch (field->size) { - case 1: - if (field->is_signed) - val = *(char *)addr; - else - val = *(unsigned char *)addr; - break; - case 2: - if (field->is_signed) - val = *(short *)addr; - else - val = *(unsigned short *)addr; - break; - case 4: - if (field->is_signed) - val = *(int *)addr; - else - val = *(unsigned int *)addr; - break; - default: - if (field->is_signed) - val = *(long *)addr; - else - val = *(unsigned long *)addr; - break; - } - return val; -} - static int get_eprobe_size(struct trace_probe *tp, void *rec) { struct fetch_insn *code; @@ -419,92 +361,6 @@ static int get_eprobe_size(struct trace_probe *tp, void *rec) return ret; } -/* Kprobe specific fetch functions */ - -/* Note that we don't verify it, since the code does not come from user space */ -static int -process_fetch_insn(struct fetch_insn *code, void *rec, void *dest, - void *base) -{ - unsigned long val; - - retry: - switch (code->op) { - case FETCH_OP_TP_ARG: - val = get_event_field(code, rec); - break; - case FETCH_OP_IMM: - val = code->immediate; - break; - case FETCH_OP_COMM: - val = (unsigned long)current->comm; - break; - case FETCH_OP_DATA: - val = (unsigned long)code->data; - break; - case FETCH_NOP_SYMBOL: /* Ignore a place holder */ - code++; - goto retry; - default: - return -EILSEQ; - } - code++; - return process_fetch_insn_bottom(code, val, dest, base); -} -NOKPROBE_SYMBOL(process_fetch_insn) - -/* Return the length of string -- including null terminal byte */ -static nokprobe_inline int -fetch_store_strlen_user(unsigned long addr) -{ - return kern_fetch_store_strlen_user(addr); -} - -/* Return the length of string -- including null terminal byte */ -static nokprobe_inline int -fetch_store_strlen(unsigned long addr) -{ - return kern_fetch_store_strlen(addr); -} - -/* - * Fetch a null-terminated string from user. Caller MUST set *(u32 *)buf - * with max length and relative data location. - */ -static nokprobe_inline int -fetch_store_string_user(unsigned long addr, void *dest, void *base) -{ - return kern_fetch_store_string_user(addr, dest, base); -} - -/* - * Fetch a null-terminated string. Caller MUST set *(u32 *)buf with max - * length and relative data location. - */ -static nokprobe_inline int -fetch_store_string(unsigned long addr, void *dest, void *base) -{ - return kern_fetch_store_string(addr, dest, base); -} - -static nokprobe_inline int -probe_mem_read_user(void *dest, void *src, size_t size) -{ - const void __user *uaddr = (__force const void __user *)src; - - return copy_from_user_nofault(dest, uaddr, size); -} - -static nokprobe_inline int -probe_mem_read(void *dest, void *src, size_t size) -{ -#ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE - if ((unsigned long)src < TASK_SIZE) - return probe_mem_read_user(dest, src, size); -#endif - return copy_from_kernel_nofault(dest, src, size); -} - /* eprobe handler */ static inline void __eprobe_trace_func(struct eprobe_data *edata, void *rec) diff --git a/kernel/trace/trace_events_synth.c b/kernel/trace/trace_events_synth.c index e310052dc83c..7460f18ba973 100644 --- a/kernel/trace/trace_events_synth.c +++ b/kernel/trace/trace_events_synth.c @@ -18,6 +18,7 @@ #include #include #include "trace_probe.h" +#include "trace_probe_tmpl.h" #include "trace_probe_kernel.h" #include "trace_synth.h" @@ -420,12 +421,12 @@ static unsigned int trace_string(struct synth_trace_event *entry, data_offset += event->n_u64 * sizeof(u64); data_offset += data_size; - len = kern_fetch_store_strlen((unsigned long)str_val); + len = fetch_store_strlen((unsigned long)str_val); data_offset |= len << 16; *(u32 *)&entry->fields[*n_u64] = data_offset; - ret = kern_fetch_store_string((unsigned long)str_val, &entry->fields[*n_u64], entry); + ret = fetch_store_string((unsigned long)str_val, &entry->fields[*n_u64], entry); (*n_u64)++; } else { @@ -473,7 +474,7 @@ static notrace void trace_event_raw_event_synth(void *__data, val_idx = var_ref_idx[field_pos]; str_val = (char *)(long)var_ref_vals[val_idx]; - len = kern_fetch_store_strlen((unsigned long)str_val); + len = fetch_store_strlen((unsigned long)str_val); fields_size += len; } diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index a4ffa864dbb7..c2e0b741ae82 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c @@ -1218,108 +1218,6 @@ static const struct file_operations kprobe_profile_ops = { .release = seq_release, }; -/* Kprobe specific fetch functions */ - -/* Return the length of string -- including null terminal byte */ -static nokprobe_inline int -fetch_store_strlen_user(unsigned long addr) -{ - return kern_fetch_store_strlen_user(addr); -} - -/* Return the length of string -- including null terminal byte */ -static nokprobe_inline int -fetch_store_strlen(unsigned long addr) -{ - return kern_fetch_store_strlen(addr); -} - -/* - * Fetch a null-terminated string from user. Caller MUST set *(u32 *)buf - * with max length and relative data location. - */ -static nokprobe_inline int -fetch_store_string_user(unsigned long addr, void *dest, void *base) -{ - return kern_fetch_store_string_user(addr, dest, base); -} - -/* - * Fetch a null-terminated string. Caller MUST set *(u32 *)buf with max - * length and relative data location. - */ -static nokprobe_inline int -fetch_store_string(unsigned long addr, void *dest, void *base) -{ - return kern_fetch_store_string(addr, dest, base); -} - -static nokprobe_inline int -probe_mem_read_user(void *dest, void *src, size_t size) -{ - const void __user *uaddr = (__force const void __user *)src; - - return copy_from_user_nofault(dest, uaddr, size); -} - -static nokprobe_inline int -probe_mem_read(void *dest, void *src, size_t size) -{ -#ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE - if ((unsigned long)src < TASK_SIZE) - return probe_mem_read_user(dest, src, size); -#endif - return copy_from_kernel_nofault(dest, src, size); -} - -/* Note that we don't verify it, since the code does not come from user space */ -static int -process_fetch_insn(struct fetch_insn *code, void *rec, void *dest, - void *base) -{ - struct pt_regs *regs = rec; - unsigned long val; - -retry: - /* 1st stage: get value from context */ - switch (code->op) { - case FETCH_OP_REG: - val = regs_get_register(regs, code->param); - break; - case FETCH_OP_STACK: - val = regs_get_kernel_stack_nth(regs, code->param); - break; - case FETCH_OP_STACKP: - val = kernel_stack_pointer(regs); - break; - case FETCH_OP_RETVAL: - val = regs_return_value(regs); - break; - case FETCH_OP_IMM: - val = code->immediate; - break; - case FETCH_OP_COMM: - val = (unsigned long)current->comm; - break; - case FETCH_OP_DATA: - val = (unsigned long)code->data; - break; -#ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API - case FETCH_OP_ARG: - val = regs_get_kernel_argument(regs, code->param); - break; -#endif - case FETCH_NOP_SYMBOL: /* Ignore a place holder */ - code++; - goto retry; - default: - return -EILSEQ; - } - code++; - - return process_fetch_insn_bottom(code, val, dest, base); -} -NOKPROBE_SYMBOL(process_fetch_insn) /* Kprobe handler */ static nokprobe_inline void diff --git a/kernel/trace/trace_probe_kernel.h b/kernel/trace/trace_probe_kernel.h index 77dbd9ff9782..cee6078b1043 100644 --- a/kernel/trace/trace_probe_kernel.h +++ b/kernel/trace/trace_probe_kernel.h @@ -12,7 +12,7 @@ */ /* Return the length of string -- including null terminal byte */ static nokprobe_inline int -kern_fetch_store_strlen_user(unsigned long addr) +fetch_store_strlen_user(unsigned long addr) { const void __user *uaddr = (__force const void __user *)addr; int ret; @@ -29,14 +29,14 @@ kern_fetch_store_strlen_user(unsigned long addr) /* Return the length of string -- including null terminal byte */ static nokprobe_inline int -kern_fetch_store_strlen(unsigned long addr) +fetch_store_strlen(unsigned long addr) { int ret, len = 0; u8 c; #ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE if (addr < TASK_SIZE) - return kern_fetch_store_strlen_user(addr); + return fetch_store_strlen_user(addr); #endif do { @@ -63,7 +63,7 @@ static nokprobe_inline void set_data_loc(int ret, void *dest, void *__dest, void * with max length and relative data location. */ static nokprobe_inline int -kern_fetch_store_string_user(unsigned long addr, void *dest, void *base) +fetch_store_string_user(unsigned long addr, void *dest, void *base) { const void __user *uaddr = (__force const void __user *)addr; int maxlen = get_loc_len(*(u32 *)dest); @@ -86,7 +86,7 @@ kern_fetch_store_string_user(unsigned long addr, void *dest, void *base) * length and relative data location. */ static nokprobe_inline int -kern_fetch_store_string(unsigned long addr, void *dest, void *base) +fetch_store_string(unsigned long addr, void *dest, void *base) { int maxlen = get_loc_len(*(u32 *)dest); void *__dest; @@ -94,7 +94,7 @@ kern_fetch_store_string(unsigned long addr, void *dest, void *base) #ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE if ((unsigned long)addr < TASK_SIZE) - return kern_fetch_store_string_user(addr, dest, base); + return fetch_store_string_user(addr, dest, base); #endif if (unlikely(!maxlen)) @@ -112,4 +112,132 @@ kern_fetch_store_string(unsigned long addr, void *dest, void *base) return ret; } +static nokprobe_inline int +probe_mem_read_user(void *dest, void *src, size_t size) +{ + const void __user *uaddr = (__force const void __user *)src; + + return copy_from_user_nofault(dest, uaddr, size); +} + +static nokprobe_inline int +probe_mem_read(void *dest, void *src, size_t size) +{ +#ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE + if ((unsigned long)src < TASK_SIZE) + return probe_mem_read_user(dest, src, size); +#endif + return copy_from_kernel_nofault(dest, src, size); +} + +static unsigned long get_event_field(struct fetch_insn *code, void *rec) +{ + struct ftrace_event_field *field = code->data; + unsigned long val; + void *addr; + + addr = rec + field->offset; + + if (is_string_field(field)) { + switch (field->filter_type) { + case FILTER_DYN_STRING: + val = (unsigned long)(rec + (*(unsigned int *)addr & 0xffff)); + break; + case FILTER_RDYN_STRING: + val = (unsigned long)(addr + (*(unsigned int *)addr & 0xffff)); + break; + case FILTER_STATIC_STRING: + val = (unsigned long)addr; + break; + case FILTER_PTR_STRING: + val = (unsigned long)(*(char *)addr); + break; + default: + WARN_ON_ONCE(1); + return 0; + } + return val; + } + + switch (field->size) { + case 1: + if (field->is_signed) + val = *(char *)addr; + else + val = *(unsigned char *)addr; + break; + case 2: + if (field->is_signed) + val = *(short *)addr; + else + val = *(unsigned short *)addr; + break; + case 4: + if (field->is_signed) + val = *(int *)addr; + else + val = *(unsigned int *)addr; + break; + default: + if (field->is_signed) + val = *(long *)addr; + else + val = *(unsigned long *)addr; + break; + } + return val; +} + +/* Note that we don't verify it, since the code does not come from user space */ +static int +process_fetch_insn(struct fetch_insn *code, void *rec, void *dest, + void *base) +{ + struct pt_regs *regs = rec; + unsigned long val; + +retry: + /* 1st stage: get value from context */ + switch (code->op) { + case FETCH_OP_REG: + val = regs_get_register(regs, code->param); + break; + case FETCH_OP_STACK: + val = regs_get_kernel_stack_nth(regs, code->param); + break; + case FETCH_OP_STACKP: + val = kernel_stack_pointer(regs); + break; + case FETCH_OP_RETVAL: + val = regs_return_value(regs); + break; + case FETCH_OP_IMM: + val = code->immediate; + break; + case FETCH_OP_COMM: + val = (unsigned long)current->comm; + break; + case FETCH_OP_DATA: + val = (unsigned long)code->data; + break; +#ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API + case FETCH_OP_ARG: + val = regs_get_kernel_argument(regs, code->param); + break; +#endif + case FETCH_NOP_SYMBOL: /* Ignore a place holder */ + code++; + goto retry; + case FETCH_OP_TP_ARG: + val = get_event_field(code, rec); + break; + default: + return -EILSEQ; + } + code++; + + return process_fetch_insn_bottom(code, val, dest, base); +} +NOKPROBE_SYMBOL(process_fetch_insn) + #endif /* __TRACE_PROBE_KERNEL_H_ */