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 <rostedt(a)goodmis.org>
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);