linux-trace-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Beau Belgrave <beaub@linux.microsoft.com>
To: rostedt@goodmis.org, mhiramat@kernel.org
Cc: linux-trace-devel@vger.kernel.org, linux-kernel@vger.kernel.org,
	beaub@linux.microsoft.com
Subject: [PATCH v7 13/13] user_events: Use __get_rel_str for relative string fields
Date: Thu,  9 Dec 2021 14:32:10 -0800	[thread overview]
Message-ID: <20211209223210.1818-14-beaub@linux.microsoft.com> (raw)
In-Reply-To: <20211209223210.1818-1-beaub@linux.microsoft.com>

Switch between __get_str and __get_rel_str within the print_fmt of
user_events. Add unit test to ensure print_fmt is correct on known
types.

Signed-off-by: Beau Belgrave <beaub@linux.microsoft.com>
---
 kernel/trace/trace_events_user.c              |  24 ++-
 .../selftests/user_events/ftrace_test.c       | 166 ++++++++++++++++++
 2 files changed, 182 insertions(+), 8 deletions(-)

diff --git a/kernel/trace/trace_events_user.c b/kernel/trace/trace_events_user.c
index 56eb58ddb4cf..3779fa2ca14a 100644
--- a/kernel/trace/trace_events_user.c
+++ b/kernel/trace/trace_events_user.c
@@ -257,7 +257,7 @@ static int user_event_add_field(struct user_event *user, const char *type,
 	goto add_field;
 
 add_validator:
-	if (strstr(type, "char[") != 0)
+	if (strstr(type, "char") != 0)
 		validator_flags |= VALIDATOR_ENSURE_NULL;
 
 	validator = kmalloc(sizeof(*validator), GFP_KERNEL);
@@ -456,14 +456,21 @@ static const char *user_field_format(const char *type)
 	return "%llu";
 }
 
-static bool user_field_is_dyn_string(const char *type)
+static bool user_field_is_dyn_string(const char *type, const char **str_func)
 {
-	if (str_has_prefix(type, "__data_loc ") ||
-	    str_has_prefix(type, "__rel_loc "))
-		if (strstr(type, "char[") != 0)
-			return true;
+	if (str_has_prefix(type, "__data_loc ")) {
+		*str_func = "__get_str";
+		goto check;
+	}
+
+	if (str_has_prefix(type, "__rel_loc ")) {
+		*str_func = "__get_rel_str";
+		goto check;
+	}
 
 	return false;
+check:
+	return strstr(type, "char") != 0;
 }
 
 #define LEN_OR_ZERO (len ? len - pos : 0)
@@ -472,6 +479,7 @@ static int user_event_set_print_fmt(struct user_event *user, char *buf, int len)
 	struct ftrace_event_field *field, *next;
 	struct list_head *head = &user->fields;
 	int pos = 0, depth = 0;
+	const char *str_func;
 
 	pos += snprintf(buf + pos, LEN_OR_ZERO, "\"");
 
@@ -488,9 +496,9 @@ static int user_event_set_print_fmt(struct user_event *user, char *buf, int len)
 	pos += snprintf(buf + pos, LEN_OR_ZERO, "\"");
 
 	list_for_each_entry_safe_reverse(field, next, head, link) {
-		if (user_field_is_dyn_string(field->type))
+		if (user_field_is_dyn_string(field->type, &str_func))
 			pos += snprintf(buf + pos, LEN_OR_ZERO,
-					", __get_str(%s)", field->name);
+					", %s(%s)", str_func, field->name);
 		else
 			pos += snprintf(buf + pos, LEN_OR_ZERO,
 					", REC->%s", field->name);
diff --git a/tools/testing/selftests/user_events/ftrace_test.c b/tools/testing/selftests/user_events/ftrace_test.c
index 16aff1fb295a..b2e5c0765a68 100644
--- a/tools/testing/selftests/user_events/ftrace_test.c
+++ b/tools/testing/selftests/user_events/ftrace_test.c
@@ -20,6 +20,7 @@ const char *data_file = "/sys/kernel/debug/tracing/user_events_data";
 const char *status_file = "/sys/kernel/debug/tracing/user_events_status";
 const char *enable_file = "/sys/kernel/debug/tracing/events/user_events/__test_event/enable";
 const char *trace_file = "/sys/kernel/debug/tracing/trace";
+const char *fmt_file = "/sys/kernel/debug/tracing/events/user_events/__test_event/format";
 
 static int trace_bytes(void)
 {
@@ -47,6 +48,61 @@ static int trace_bytes(void)
 	return bytes;
 }
 
+static int get_print_fmt(char *buffer, int len)
+{
+	FILE *fp = fopen(fmt_file, "r");
+	int c, index = 0, last = 0;
+
+	if (!fp)
+		return -1;
+
+	/* Read until empty line (Skip Common) */
+	while (true) {
+		c = getc(fp);
+
+		if (c == EOF)
+			break;
+
+		if (last == '\n' && c == '\n')
+			break;
+
+		last = c;
+	}
+
+	last = 0;
+
+	/* Read until empty line (Skip Properties) */
+	while (true) {
+		c = getc(fp);
+
+		if (c == EOF)
+			break;
+
+		if (last == '\n' && c == '\n')
+			break;
+
+		last = c;
+	}
+
+	/* Read in print_fmt: */
+	while (len > 1) {
+		c = getc(fp);
+
+		if (c == EOF || c == '\n')
+			break;
+
+		buffer[index++] = c;
+
+		len--;
+	}
+
+	buffer[index] = 0;
+
+	fclose(fp);
+
+	return 0;
+}
+
 static int clear(void)
 {
 	int fd = open(data_file, O_RDWR);
@@ -63,6 +119,44 @@ static int clear(void)
 	return 0;
 }
 
+static int check_print_fmt(const char *event, const char *expected)
+{
+	struct user_reg reg = {0};
+	char print_fmt[256];
+	int ret;
+	int fd;
+
+	/* Ensure cleared */
+	ret = clear();
+
+	if (ret != 0)
+		return ret;
+
+	fd = open(data_file, O_RDWR);
+
+	if (fd == -1)
+		return fd;
+
+	reg.size = sizeof(reg);
+	reg.name_args = (__u64)event;
+
+	/* Register should work */
+	ret = ioctl(fd, DIAG_IOCSREG, &reg);
+
+	close(fd);
+
+	if (ret != 0)
+		return ret;
+
+	/* Ensure correct print_fmt */
+	ret = get_print_fmt(print_fmt, sizeof(print_fmt));
+
+	if (ret != 0)
+		return ret;
+
+	return strcmp(print_fmt, expected);
+}
+
 FIXTURE(user) {
 	int status_fd;
 	int data_fd;
@@ -282,6 +376,78 @@ TEST_F(user, write_validator) {
 	ASSERT_EQ(EFAULT, errno);
 }
 
+TEST_F(user, print_fmt) {
+	int ret;
+
+	ret = check_print_fmt("__test_event __rel_loc char[] data",
+			      "print fmt: \"data=%s\", __get_rel_str(data)");
+	ASSERT_EQ(0, ret);
+
+	ret = check_print_fmt("__test_event __data_loc char[] data",
+			      "print fmt: \"data=%s\", __get_str(data)");
+	ASSERT_EQ(0, ret);
+
+	ret = check_print_fmt("__test_event s64 data",
+			      "print fmt: \"data=%lld\", REC->data");
+	ASSERT_EQ(0, ret);
+
+	ret = check_print_fmt("__test_event u64 data",
+			      "print fmt: \"data=%llu\", REC->data");
+	ASSERT_EQ(0, ret);
+
+	ret = check_print_fmt("__test_event s32 data",
+			      "print fmt: \"data=%d\", REC->data");
+	ASSERT_EQ(0, ret);
+
+	ret = check_print_fmt("__test_event u32 data",
+			      "print fmt: \"data=%u\", REC->data");
+	ASSERT_EQ(0, ret);
+
+	ret = check_print_fmt("__test_event int data",
+			      "print fmt: \"data=%d\", REC->data");
+	ASSERT_EQ(0, ret);
+
+	ret = check_print_fmt("__test_event unsigned int data",
+			      "print fmt: \"data=%u\", REC->data");
+	ASSERT_EQ(0, ret);
+
+	ret = check_print_fmt("__test_event s16 data",
+			      "print fmt: \"data=%d\", REC->data");
+	ASSERT_EQ(0, ret);
+
+	ret = check_print_fmt("__test_event u16 data",
+			      "print fmt: \"data=%u\", REC->data");
+	ASSERT_EQ(0, ret);
+
+	ret = check_print_fmt("__test_event short data",
+			      "print fmt: \"data=%d\", REC->data");
+	ASSERT_EQ(0, ret);
+
+	ret = check_print_fmt("__test_event unsigned short data",
+			      "print fmt: \"data=%u\", REC->data");
+	ASSERT_EQ(0, ret);
+
+	ret = check_print_fmt("__test_event s8 data",
+			      "print fmt: \"data=%d\", REC->data");
+	ASSERT_EQ(0, ret);
+
+	ret = check_print_fmt("__test_event u8 data",
+			      "print fmt: \"data=%u\", REC->data");
+	ASSERT_EQ(0, ret);
+
+	ret = check_print_fmt("__test_event char data",
+			      "print fmt: \"data=%d\", REC->data");
+	ASSERT_EQ(0, ret);
+
+	ret = check_print_fmt("__test_event unsigned char data",
+			      "print fmt: \"data=%u\", REC->data");
+	ASSERT_EQ(0, ret);
+
+	ret = check_print_fmt("__test_event char[4] data",
+			      "print fmt: \"data=%s\", REC->data");
+	ASSERT_EQ(0, ret);
+}
+
 int main(int argc, char **argv)
 {
 	return test_harness_run(argc, argv);
-- 
2.17.1


  parent reply	other threads:[~2021-12-09 22:32 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-12-09 22:31 [PATCH v7 00/13] user_events: Enable user processes to create and write to trace events Beau Belgrave
2021-12-09 22:31 ` [PATCH v7 01/13] user_events: Add UABI header for user access to user_events Beau Belgrave
2021-12-10 13:30   ` Masami Hiramatsu
2021-12-10 17:29     ` Beau Belgrave
2021-12-09 22:31 ` [PATCH v7 02/13] user_events: Add minimal support for trace_event into ftrace Beau Belgrave
2021-12-10 10:43   ` Masami Hiramatsu
2021-12-10 17:43     ` Steven Rostedt
2021-12-13  0:09       ` Masami Hiramatsu
2021-12-13 16:48         ` Steven Rostedt
2021-12-10 18:03     ` Beau Belgrave
2021-12-13  4:24       ` Masami Hiramatsu
2021-12-13 17:58         ` Beau Belgrave
2021-12-09 22:32 ` [PATCH v7 03/13] user_events: Add print_fmt generation support for basic types Beau Belgrave
2021-12-10  2:50   ` Masami Hiramatsu
2021-12-09 22:32 ` [PATCH v7 04/13] user_events: Handle matching arguments from dyn_events Beau Belgrave
2021-12-09 22:32 ` [PATCH v7 05/13] user_events: Add basic perf and eBPF support Beau Belgrave
2021-12-09 22:32 ` [PATCH v7 06/13] user_events: Add self-test for ftrace integration Beau Belgrave
2021-12-09 22:32 ` [PATCH v7 07/13] user_events: Add self-test for dynamic_events integration Beau Belgrave
2021-12-09 22:32 ` [PATCH v7 08/13] user_events: Add self-test for perf_event integration Beau Belgrave
2021-12-09 22:32 ` [PATCH v7 09/13] user_events: Optimize writing events by only copying data once Beau Belgrave
2021-12-10 14:51   ` Masami Hiramatsu
2021-12-10 18:36     ` Beau Belgrave
2021-12-09 22:32 ` [PATCH v7 10/13] user_events: Add documentation file Beau Belgrave
2021-12-09 22:32 ` [PATCH v7 11/13] user_events: Add sample code for typical usage Beau Belgrave
2021-12-09 22:32 ` [PATCH v7 12/13] user_events: Validate user payloads for size and null termination Beau Belgrave
2021-12-10 14:46   ` Masami Hiramatsu
2021-12-09 22:32 ` Beau Belgrave [this message]
2021-12-10  1:23   ` [PATCH v7 13/13] user_events: Use __get_rel_str for relative string fields Masami Hiramatsu
2021-12-10 18:45     ` Beau Belgrave
2021-12-12 15:12       ` Masami Hiramatsu
2021-12-13 18:47         ` Beau Belgrave
2021-12-14  6:30           ` Masami Hiramatsu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20211209223210.1818-14-beaub@linux.microsoft.com \
    --to=beaub@linux.microsoft.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-trace-devel@vger.kernel.org \
    --cc=mhiramat@kernel.org \
    --cc=rostedt@goodmis.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).