aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2009-07-21 18:18:18 -0400
committerSteven Rostedt <rostedt@goodmis.org>2009-07-21 18:18:18 -0400
commite3b16be293af31394b9d1257e08e94e55d48b3da (patch)
tree273fc5e328dab47705039f6d4e859f89ecc3c80c
parent5f2168be9994e284209cb3f02a30932e0a538f5e (diff)
handle bprint events
The ftrace bprint uses a special binary format to record trace_print events. This patch changes trace-cmd to handle the format. Part of that is to read (and record) the printk_formats file in the trace.dat. Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r--parse-events.c254
-rw-r--r--parse-events.h2
-rw-r--r--trace-cmd.c25
-rw-r--r--trace-read.c28
4 files changed, 308 insertions, 1 deletions
diff --git a/parse-events.c b/parse-events.c
index f1d8d74..288af2b 100644
--- a/parse-events.c
+++ b/parse-events.c
@@ -262,6 +262,92 @@ void print_funcs(void)
262 } 262 }
263} 263}
264 264
265static struct printk_map {
266 unsigned long long addr;
267 char *printk;
268} *printk_list;
269static unsigned int printk_count;
270
271static int printk_cmp(const void *a, const void *b)
272{
273 const struct func_map *fa = a;
274 const struct func_map *fb = b;
275
276 if (fa->addr < fb->addr)
277 return -1;
278 if (fa->addr > fb->addr)
279 return 1;
280
281 return 0;
282}
283
284static struct printk_map *find_printk(unsigned long long addr)
285{
286 struct printk_map *printk;
287 struct printk_map key;
288
289 key.addr = addr;
290
291 printk = bsearch(&key, printk_list, printk_count, sizeof(*printk_list),
292 printk_cmp);
293
294 return printk;
295}
296
297void parse_ftrace_printk(char *file, unsigned int size)
298{
299 struct printk_list {
300 struct printk_list *next;
301 unsigned long long addr;
302 char *printk;
303 } *list = NULL, *item;
304 char *line;
305 char *next;
306 char *addr_str;
307 int ret;
308 int i;
309
310 line = strtok_r(file, "\n", &next);
311 while (line) {
312 item = malloc_or_die(sizeof(*item));
313 ret = sscanf(line, "%as : %as",
314 &addr_str,
315 &item->printk);
316 item->addr = strtoull(addr_str, NULL, 16);
317 free(addr_str);
318
319 item->next = list;
320 list = item;
321 line = strtok_r(NULL, "\n", &next);
322 printk_count++;
323 }
324
325 printk_list = malloc_or_die(sizeof(*printk_list) * printk_count + 1);
326
327 i = 0;
328 while (list) {
329 printk_list[i].printk = list->printk;
330 printk_list[i].addr = list->addr;
331 i++;
332 item = list;
333 list = list->next;
334 free(item);
335 }
336
337 qsort(printk_list, printk_count, sizeof(*printk_list), printk_cmp);
338}
339
340void print_printk(void)
341{
342 int i;
343
344 for (i = 0; i < printk_count; i++) {
345 printf("%016llx %s\n",
346 printk_list[i].addr,
347 printk_list[i].printk);
348 }
349}
350
265struct event *alloc_event(void) 351struct event *alloc_event(void)
266{ 352{
267 struct event *event; 353 struct event *event;
@@ -1915,14 +2001,167 @@ static void print_str_arg(void *data, int size,
1915 } 2001 }
1916} 2002}
1917 2003
2004static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struct event *event)
2005{
2006 static struct format_field *field, *ip_field;
2007 struct print_arg *args, *arg, **next;
2008 unsigned long long ip, val;
2009 char *ptr;
2010 void *bptr;
2011
2012 if (!field) {
2013 field = find_field(event, "buf");
2014 if (!field)
2015 die("can't find buffer field for binary printk");
2016 ip_field = find_field(event, "ip");
2017 if (!ip_field)
2018 die("can't find ip field for binary printk");
2019 }
2020
2021 ip = read_size(data + ip_field->offset, ip_field->size);
2022
2023 /*
2024 * The first arg is the IP pointer.
2025 */
2026 args = malloc_or_die(sizeof(*args));
2027 arg = args;
2028 arg->next = NULL;
2029 next = &arg->next;
2030
2031 arg->type = PRINT_ATOM;
2032 arg->atom.atom = malloc_or_die(32);
2033 sprintf(arg->atom.atom, "%lld", ip);
2034
2035 /* skip the first "%pf : " */
2036 for (ptr = fmt + 6, bptr = data + field->offset;
2037 bptr < data + size && *ptr; ptr++) {
2038 int ls = 0;
2039
2040 if (*ptr == '%') {
2041 process_again:
2042 ptr++;
2043 switch (*ptr) {
2044 case '%':
2045 break;
2046 case 'l':
2047 ls++;
2048 goto process_again;
2049 case 'L':
2050 ls = 2;
2051 goto process_again;
2052 case '0' ... '9':
2053 goto process_again;
2054 case 'p':
2055 ls = 1;
2056 /* fall through */
2057 case 'd':
2058 case 'u':
2059 case 'x':
2060 case 'i':
2061 bptr = (void *)(((unsigned long)bptr + (long_size - 1)) &
2062 ~(long_size - 1));
2063 switch (ls) {
2064 case 0:
2065 case 1:
2066 ls = long_size;
2067 break;
2068 case 2:
2069 ls = 8;
2070 }
2071 val = read_size(bptr, ls);
2072 bptr += ls;
2073 arg = malloc_or_die(sizeof(*arg));
2074 arg->next = NULL;
2075 arg->type = PRINT_ATOM;
2076 arg->atom.atom = malloc_or_die(32);
2077 sprintf(arg->atom.atom, "%lld", val);
2078 *next = arg;
2079 next = &arg->next;
2080 break;
2081 case 's':
2082 arg = malloc_or_die(sizeof(*arg));
2083 arg->next = NULL;
2084 arg->type = PRINT_STRING;
2085 arg->string.string = strdup(bptr);
2086 bptr += strlen(bptr) + 1;
2087 *next = arg;
2088 next = &arg->next;
2089 }
2090 }
2091 }
2092
2093 return args;
2094}
2095
2096static void free_args(struct print_arg *args)
2097{
2098 struct print_arg *next;
2099
2100 while (args) {
2101 next = args->next;
2102
2103 if (args->type == PRINT_ATOM)
2104 free(args->atom.atom);
2105 else
2106 free(args->string.string);
2107 free(args);
2108 args = next;
2109 }
2110}
2111
2112static char *get_bprint_format(void *data, int size, struct event *event)
2113{
2114 unsigned long long addr;
2115 static struct format_field *field;
2116 struct printk_map *printk;
2117 char *format;
2118 char *p;
2119
2120 if (!field) {
2121 field = find_field(event, "fmt");
2122 if (!field)
2123 die("can't find format field for binary printk");
2124 printf("field->offset = %d size=%d\n", field->offset, field->size);
2125 }
2126
2127 addr = read_size(data + field->offset, field->size);
2128
2129 printk = find_printk(addr);
2130 if (!printk) {
2131 format = malloc_or_die(45);
2132 sprintf(format, "%%pf : (NO FORMAT FOUND at %llx)\n",
2133 addr);
2134 return format;
2135 }
2136
2137 p = printk->printk;
2138 /* Remove any quotes. */
2139 if (*p == '"')
2140 p++;
2141 format = malloc_or_die(strlen(p) + 10);
2142 sprintf(format, "%s : %s", "%pf", p);
2143 /* remove ending quotes and new line since we will add one too */
2144 p = format + strlen(format) - 1;
2145 if (*p == '"')
2146 *p = 0;
2147
2148 p -= 2;
2149 if (strcmp(p, "\\n") == 0)
2150 *p = 0;
2151
2152 return format;
2153}
2154
1918static void pretty_print(void *data, int size, struct event *event) 2155static void pretty_print(void *data, int size, struct event *event)
1919{ 2156{
1920 struct print_fmt *print_fmt = &event->print_fmt; 2157 struct print_fmt *print_fmt = &event->print_fmt;
1921 struct print_arg *arg = print_fmt->args; 2158 struct print_arg *arg = print_fmt->args;
2159 struct print_arg *args = NULL;
1922 const char *ptr = print_fmt->format; 2160 const char *ptr = print_fmt->format;
1923 unsigned long long val; 2161 unsigned long long val;
1924 struct func_map *func; 2162 struct func_map *func;
1925 const char *saveptr; 2163 const char *saveptr;
2164 char *bprint_fmt = NULL;
1926 char format[32]; 2165 char format[32];
1927 int show_func; 2166 int show_func;
1928 int len; 2167 int len;
@@ -1931,6 +2170,13 @@ static void pretty_print(void *data, int size, struct event *event)
1931 if (event->flags & EVENT_FL_ISFUNC) 2170 if (event->flags & EVENT_FL_ISFUNC)
1932 ptr = " %pF <-- %pF"; 2171 ptr = " %pF <-- %pF";
1933 2172
2173 if (event->flags & EVENT_FL_ISBPRINT) {
2174 bprint_fmt = get_bprint_format(data, size, event);
2175 args = make_bprint_args(bprint_fmt, data, size, event);
2176 arg = args;
2177 ptr = bprint_fmt;
2178 }
2179
1934 for (; *ptr; ptr++) { 2180 for (; *ptr; ptr++) {
1935 ls = 0; 2181 ls = 0;
1936 if (*ptr == '%') { 2182 if (*ptr == '%') {
@@ -2023,6 +2269,11 @@ static void pretty_print(void *data, int size, struct event *event)
2023 } else 2269 } else
2024 printf("%c", *ptr); 2270 printf("%c", *ptr);
2025 } 2271 }
2272
2273 if (args) {
2274 free_args(args);
2275 free(bprint_fmt);
2276 }
2026} 2277}
2027 2278
2028static inline int log10_cpu(int nb) 2279static inline int log10_cpu(int nb)
@@ -2546,6 +2797,9 @@ int parse_ftrace_file(char *buf, unsigned long size)
2546 else if (strcmp(event->name, "funcgraph_exit") == 0) 2797 else if (strcmp(event->name, "funcgraph_exit") == 0)
2547 event->flags |= EVENT_FL_ISFUNCRET; 2798 event->flags |= EVENT_FL_ISFUNCRET;
2548 2799
2800 else if (strcmp(event->name, "bprint") == 0)
2801 event->flags |= EVENT_FL_ISBPRINT;
2802
2549 event->id = event_read_id(); 2803 event->id = event_read_id();
2550 if (event->id < 0) 2804 if (event->id < 0)
2551 die("failed to read ftrace event id"); 2805 die("failed to read ftrace event id");
diff --git a/parse-events.h b/parse-events.h
index d41abd5..2401c8d 100644
--- a/parse-events.h
+++ b/parse-events.h
@@ -159,8 +159,10 @@ void *malloc_or_die(unsigned int size);
159 159
160void parse_cmdlines(char *file, int size); 160void parse_cmdlines(char *file, int size);
161void parse_proc_kallsyms(char *file, unsigned int size); 161void parse_proc_kallsyms(char *file, unsigned int size);
162void parse_ftrace_printk(char *file, unsigned int size);
162 163
163void print_funcs(void); 164void print_funcs(void);
165void print_printk(void);
164 166
165int parse_ftrace_file(char *buf, unsigned long size); 167int parse_ftrace_file(char *buf, unsigned long size);
166int parse_event_file(char *buf, unsigned long size, char *system); 168int parse_event_file(char *buf, unsigned long size, char *system);
diff --git a/trace-cmd.c b/trace-cmd.c
index 12581bc..6973bba 100644
--- a/trace-cmd.c
+++ b/trace-cmd.c
@@ -849,6 +849,29 @@ static void read_proc_kallsyms(void)
849 849
850} 850}
851 851
852static void read_ftrace_printk(void)
853{
854 unsigned int size, check_size;
855 const char *path;
856 struct stat st;
857 int ret;
858
859 path = get_tracing_file("printk_formats");
860 ret = stat(path, &st);
861 if (ret < 0) {
862 /* not found */
863 size = 0;
864 write_or_die(&size, 4);
865 return;
866 }
867 size = get_size(path);
868 write_or_die(&size, 4);
869 check_size = copy_file(path);
870 if (size != check_size)
871 die("error in size of file '%s'", path);
872
873}
874
852static void read_tracing_data(void) 875static void read_tracing_data(void)
853{ 876{
854 char buf[BUFSIZ]; 877 char buf[BUFSIZ];
@@ -886,6 +909,7 @@ static void read_tracing_data(void)
886 read_ftrace_files(); 909 read_ftrace_files();
887 read_event_files(); 910 read_event_files();
888 read_proc_kallsyms(); 911 read_proc_kallsyms();
912 read_ftrace_printk();
889} 913}
890 914
891static unsigned long long read_thread_file(int cpu) 915static unsigned long long read_thread_file(int cpu)
@@ -1006,6 +1030,7 @@ void usage(char **argv)
1006 " -i input file [default trace.dat]\n" 1030 " -i input file [default trace.dat]\n"
1007 " -e show file endianess\n" 1031 " -e show file endianess\n"
1008 " -f show function list\n" 1032 " -f show function list\n"
1033 " -P show printk list\n"
1009 "\n" 1034 "\n"
1010 " %s list [-e][-p]\n" 1035 " %s list [-e][-p]\n"
1011 " -e list available events\n" 1036 " -e list available events\n"
diff --git a/trace-read.c b/trace-read.c
index ed11a71..3be4fe2 100644
--- a/trace-read.c
+++ b/trace-read.c
@@ -148,6 +148,23 @@ static void read_proc_kallsyms(void)
148 free(buf); 148 free(buf);
149} 149}
150 150
151static void read_ftrace_printk(void)
152{
153 unsigned int size;
154 char *buf;
155
156 size = read4();
157 if (!size)
158 return;
159
160 buf = malloc_or_die(size);
161 read_or_die(buf, size);
162
163 parse_ftrace_printk(buf, size);
164
165 free(buf);
166}
167
151static void read_header_files(void) 168static void read_header_files(void)
152{ 169{
153 unsigned long long size; 170 unsigned long long size;
@@ -579,6 +596,7 @@ void trace_report (int argc, char **argv)
579 int show_funcs = 0; 596 int show_funcs = 0;
580 int show_endian = 0; 597 int show_endian = 0;
581 int show_page_size = 0; 598 int show_page_size = 0;
599 int show_printk = 0;
582 int c; 600 int c;
583 601
584 if (argc < 2) 602 if (argc < 2)
@@ -595,7 +613,7 @@ void trace_report (int argc, char **argv)
595 {NULL, 0, NULL, 0} 613 {NULL, 0, NULL, 0}
596 }; 614 };
597 615
598 c = getopt_long (argc-1, argv+1, "+hi:fep", 616 c = getopt_long (argc-1, argv+1, "+hi:fepP",
599 long_options, &option_index); 617 long_options, &option_index);
600 if (c == -1) 618 if (c == -1)
601 break; 619 break;
@@ -609,6 +627,9 @@ void trace_report (int argc, char **argv)
609 case 'f': 627 case 'f':
610 show_funcs = 1; 628 show_funcs = 1;
611 break; 629 break;
630 case 'P':
631 show_printk = 1;
632 break;
612 case 'e': 633 case 'e':
613 show_endian = 1; 634 show_endian = 1;
614 break; 635 break;
@@ -671,11 +692,16 @@ void trace_report (int argc, char **argv)
671 read_ftrace_files(); 692 read_ftrace_files();
672 read_event_files(); 693 read_event_files();
673 read_proc_kallsyms(); 694 read_proc_kallsyms();
695 read_ftrace_printk();
674 696
675 if (show_funcs) { 697 if (show_funcs) {
676 print_funcs(); 698 print_funcs();
677 return; 699 return;
678 } 700 }
701 if (show_printk) {
702 print_printk();
703 return;
704 }
679 read_data_info(); 705 read_data_info();
680 706
681 return; 707 return;