Blob Blame History Raw
From 2ed07609b2a8ed19ce3dda7a50b18373a6a8bd5c Mon Sep 17 00:00:00 2001
From: Dave Anderson <anderson@redhat.com>
Date: Mon, 25 Mar 2019 11:48:39 -0400
Subject: [PATCH 1/3] Fixes for the "trace.so" extension module: (1) The
 reader_page can be empty if it was never read, do not record     it if it is
 empty. Better yet, do not record any page that is     empty.  The struct
 buffer_page "real_end" is not available in     older kernels, so it needs to
 be tested if it exists before we     can use it. (2) In newer kernels, the
 sp->type of kernel module symbols does not     contain the symbol type
 character unless the module's debuginfo     data has been loaded into the
 crash session.  Writing a garbage     type to the kallsyms file for trace-cmd
 to read causes it to     crash, so just always write an 'm'. (3) Add the
 "trace dump -t <trace.dat>" option to the SYNOPSIS line     of the help page.
 (rostedt@goodmis.org)

---
 trace.c | 32 +++++++++++++++++++++++++++++---
 1 file changed, 29 insertions(+), 3 deletions(-)

diff --git a/trace.c b/trace.c
index ad71951e8740..c26b6c7ec475 100644
--- a/trace.c
+++ b/trace.c
@@ -43,6 +43,11 @@ static int max_buffer_available;
  */
 static int multiple_instances_available;
 
+/*
+ * buffer_page has "real_end"
+ */
+static int buffer_page_real_end_available;
+
 #define koffset(struct, member) struct##_##member##_offset
 
 static int koffset(trace_array, current_trace);
@@ -70,6 +75,7 @@ static int koffset(ring_buffer_per_cpu, entries);
 static int koffset(buffer_page, read);
 static int koffset(buffer_page, list);
 static int koffset(buffer_page, page);
+static int koffset(buffer_page, real_end);
 
 static int koffset(list_head, next);
 
@@ -229,6 +235,7 @@ static int init_offsets(void)
 	init_offset(buffer_page, read);
 	init_offset(buffer_page, list);
 	init_offset(buffer_page, page);
+	init_offset(buffer_page, real_end);
 
 	init_offset(list_head, next);
 
@@ -281,6 +288,7 @@ static void print_offsets(void)
 	print_offset(buffer_page, read);
 	print_offset(buffer_page, list);
 	print_offset(buffer_page, page);
+	print_offset(buffer_page, real_end);
 
 	print_offset(list_head, next);
 
@@ -295,6 +303,20 @@ static void print_offsets(void)
 #undef print_offset
 }
 
+static int buffer_page_has_data(ulong page)
+{
+	uint end;
+
+	if (!buffer_page_real_end_available)
+		return 1;
+
+	/* Only write pages with data in it */
+	read_value(end, page, buffer_page, real_end);
+	return end;
+out_fail:
+	return 0;
+}
+
 static int ftrace_init_pages(struct ring_buffer_per_cpu *cpu_buffer,
 		unsigned nr_pages)
 {
@@ -361,7 +383,8 @@ static int ftrace_init_pages(struct ring_buffer_per_cpu *cpu_buffer,
 
 	/* Setup linear pages */
 
-	cpu_buffer->linear_pages[count++] = cpu_buffer->reader_page;
+	if (buffer_page_has_data(cpu_buffer->reader_page))
+		cpu_buffer->linear_pages[count++] = cpu_buffer->reader_page;
 
 	if (cpu_buffer->reader_page == cpu_buffer->commit_page)
 		goto done;
@@ -647,6 +670,8 @@ static int ftrace_init(void)
 		ftrace_trace_arrays = sym_ftrace_trace_arrays->value;
 	}
 
+	if (MEMBER_EXISTS("buffer_page", "real_end"))
+		buffer_page_real_end_available = 1;
 
 	if (MEMBER_EXISTS("trace_array", "current_trace")) {
 		encapsulated_current_trace = 1;
@@ -1809,7 +1834,7 @@ static void cmd_ftrace(void)
 static char *help_ftrace[] = {
 "trace",
 "show or dump the tracing info",
-"[ <show [-c <cpulist>] [-f [no]<flagname>]> | <dump [-sm] <dest-dir>> ]",
+"[ <show [-c <cpulist>] [-f [no]<flagname>]> | <dump [-sm] <dest-dir>> ] | <dump -t <trace.dat> ]",
 "trace",
 "    shows the current tracer and other informations.",
 "",
@@ -2184,7 +2209,8 @@ static int save_proc_kallsyms(int fd)
 			if (!strncmp(sp->name, "_MODULE_", strlen("_MODULE_")))
 				continue;
 
-			tmp_fprintf("%lx %c %s\t[%s]\n", sp->value, sp->type,
+			/* Currently sp->type for modules is not trusted */
+			tmp_fprintf("%lx %c %s\t[%s]\n", sp->value, 'm',
 					sp->name, lm->mod_name);
 		}
 	}
-- 
2.17.1