If a module has a trace_printk() and it is optimized to be a
trace_bprintk() then we want to save the format for that as well.
The trace_bprintk() just saves the pointer of the format in the
ftrace ring buffer, thus trace-cmd requires the mapping of that
address to the format.

Signed-off-by: Steven Rostedt <[email protected]>

Index: crash-5.1.3/extensions/trace.c
===================================================================
--- crash-5.1.3.orig/extensions/trace.c
+++ crash-5.1.3/extensions/trace.c
@@ -3341,11 +3341,46 @@ static int save_proc_kallsyms(int fd)
        return tmp_file_flush(fd);
 }
 
+static int add_print_address(long address)
+{
+       char string[4096];
+       size_t len;
+       int i;
+
+       len = read_string(address, string, sizeof(string));
+       if (!len)
+               return -1;
+
+       tmp_fprintf("0x%lx : \"", address);
+
+       for (i = 0; string[i]; i++) {
+               switch (string[i]) {
+               case '\n':
+                       tmp_fprintf("\\n");
+                       break;
+               case '\t':
+                       tmp_fprintf("\\t");
+                       break;
+               case '\\':
+                       tmp_fprintf("\\\\");
+                       break;
+               case '"':
+                       tmp_fprintf("\\\"");
+                       break;
+               default:
+                       tmp_fprintf("%c", string[i]);
+               }
+       }
+       tmp_fprintf("\"\n");
+
+       return 0;
+}
+
 static int save_ftrace_printk(int fd)
 {
-       struct syment *s, *e;
+       struct kernel_list_head *mod_fmt;
+       struct syment *s, *e, *b;
        long bprintk_fmt_s, bprintk_fmt_e;
-       char string[4096];
        long *address;
        size_t i, count;
 
@@ -3358,10 +3393,8 @@ static int save_ftrace_printk(int fd)
        bprintk_fmt_e = e->value;
        count = (bprintk_fmt_e - bprintk_fmt_s) / sizeof(long);
 
-       if (count == 0) {
-               unsigned int size = 0;
-               return write_and_check(fd, &size, 4);
-       }
+       if (count == 0)
+               goto do_mods;
 
        address = malloc(count * sizeof(long));
        if (address == NULL)
@@ -3374,37 +3407,49 @@ static int save_ftrace_printk(int fd)
        }
 
        for (i = 0; i < count; i++) {
-               size_t len = read_string(address[i], string, sizeof(string));
-               if (!len) {
+               if (add_print_address(address[i]) < 0) {
                        free(address);
                        return -1;
                }
-
-               tmp_fprintf("0x%lx : \"", address[i]);
-
-               for (i = 0; string[i]; i++) {
-                       switch (string[i]) {
-                       case '\n':
-                               tmp_fprintf("\\n");
-                               break;
-                       case '\t':
-                               tmp_fprintf("\\t");
-                               break;
-                       case '\\':
-                               tmp_fprintf("\\\\");
-                               break;
-                       case '"':
-                               tmp_fprintf("\\\"");
-                               break;
-                       default:
-                               tmp_fprintf("%c", string[i]);
-                       }
-               }
-               tmp_fprintf("\"\n");
        }
 
        free(address);
 
+ do_mods:
+
+       /* Add modules */
+       b = symbol_search("trace_bprintk_fmt_list");
+       if (!b)
+               goto out;
+
+       mod_fmt = (struct kernel_list_head *)GETBUF(SIZE(list_head));
+       if (!readmem(b->value, KVADDR, mod_fmt,
+                    SIZE(list_head), "trace_bprintk_fmt_list contents",
+                    RETURN_ON_ERROR))
+               goto out_free;
+
+       while ((unsigned long)mod_fmt->next != b->value) {
+               unsigned long addr;
+
+               addr = (unsigned long)mod_fmt->next + SIZE(list_head);
+
+               if (!readmem((unsigned long)mod_fmt->next, KVADDR, mod_fmt,
+                            SIZE(list_head), "trace_bprintk_fmt_list contents",
+                            RETURN_ON_ERROR))
+                       goto out_free;
+
+               if (add_print_address(addr) < 0)
+                       goto out_free;
+               count++;
+       }
+
+ out_free:
+       FREEBUF(mod_fmt);
+ out:
+       if (count == 0) {
+               unsigned int size = 0;
+               return write_and_check(fd, &size, 4);
+       }
        if (tmp_file_record_size4(fd))
                return -1;
        return tmp_file_flush(fd);

--
Crash-utility mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/crash-utility

Reply via email to