Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: LGPL-2.1
0002 /*
0003  * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
0004  */
0005 #include <stdio.h>
0006 #include <stdlib.h>
0007 #include <string.h>
0008 
0009 #include "event-parse.h"
0010 #include "event-utils.h"
0011 #include "trace-seq.h"
0012 
0013 static struct func_stack {
0014     int size;
0015     char **stack;
0016 } *fstack;
0017 
0018 static int cpus = -1;
0019 
0020 #define STK_BLK 10
0021 
0022 struct tep_plugin_option plugin_options[] =
0023 {
0024     {
0025         .name = "parent",
0026         .plugin_alias = "ftrace",
0027         .description =
0028         "Print parent of functions for function events",
0029     },
0030     {
0031         .name = "indent",
0032         .plugin_alias = "ftrace",
0033         .description =
0034         "Try to show function call indents, based on parents",
0035         .set = 1,
0036     },
0037     {
0038         .name = "offset",
0039         .plugin_alias = "ftrace",
0040         .description =
0041         "Show function names as well as their offsets",
0042         .set = 0,
0043     },
0044     {
0045         .name = NULL,
0046     }
0047 };
0048 
0049 static struct tep_plugin_option *ftrace_parent = &plugin_options[0];
0050 static struct tep_plugin_option *ftrace_indent = &plugin_options[1];
0051 static struct tep_plugin_option *ftrace_offset = &plugin_options[2];
0052 
0053 static void add_child(struct func_stack *stack, const char *child, int pos)
0054 {
0055     int i;
0056 
0057     if (!child)
0058         return;
0059 
0060     if (pos < stack->size)
0061         free(stack->stack[pos]);
0062     else {
0063         char **ptr;
0064 
0065         ptr = realloc(stack->stack, sizeof(char *) *
0066                   (stack->size + STK_BLK));
0067         if (!ptr) {
0068             warning("could not allocate plugin memory\n");
0069             return;
0070         }
0071 
0072         stack->stack = ptr;
0073 
0074         for (i = stack->size; i < stack->size + STK_BLK; i++)
0075             stack->stack[i] = NULL;
0076         stack->size += STK_BLK;
0077     }
0078 
0079     stack->stack[pos] = strdup(child);
0080 }
0081 
0082 static int add_and_get_index(const char *parent, const char *child, int cpu)
0083 {
0084     int i;
0085 
0086     if (cpu < 0)
0087         return 0;
0088 
0089     if (cpu > cpus) {
0090         struct func_stack *ptr;
0091 
0092         ptr = realloc(fstack, sizeof(*fstack) * (cpu + 1));
0093         if (!ptr) {
0094             warning("could not allocate plugin memory\n");
0095             return 0;
0096         }
0097 
0098         fstack = ptr;
0099 
0100         /* Account for holes in the cpu count */
0101         for (i = cpus + 1; i <= cpu; i++)
0102             memset(&fstack[i], 0, sizeof(fstack[i]));
0103         cpus = cpu;
0104     }
0105 
0106     for (i = 0; i < fstack[cpu].size && fstack[cpu].stack[i]; i++) {
0107         if (strcmp(parent, fstack[cpu].stack[i]) == 0) {
0108             add_child(&fstack[cpu], child, i+1);
0109             return i;
0110         }
0111     }
0112 
0113     /* Not found */
0114     add_child(&fstack[cpu], parent, 0);
0115     add_child(&fstack[cpu], child, 1);
0116     return 0;
0117 }
0118 
0119 static void show_function(struct trace_seq *s, struct tep_handle *tep,
0120               const char *func, unsigned long long function)
0121 {
0122     unsigned long long offset;
0123 
0124     trace_seq_printf(s, "%s", func);
0125     if (ftrace_offset->set) {
0126         offset = tep_find_function_address(tep, function);
0127         trace_seq_printf(s, "+0x%x ", (int)(function - offset));
0128     }
0129 }
0130 
0131 static int function_handler(struct trace_seq *s, struct tep_record *record,
0132                 struct tep_event *event, void *context)
0133 {
0134     struct tep_handle *tep = event->tep;
0135     unsigned long long function;
0136     unsigned long long pfunction;
0137     const char *func;
0138     const char *parent;
0139     int index = 0;
0140 
0141     if (tep_get_field_val(s, event, "ip", record, &function, 1))
0142         return trace_seq_putc(s, '!');
0143 
0144     func = tep_find_function(tep, function);
0145 
0146     if (tep_get_field_val(s, event, "parent_ip", record, &pfunction, 1))
0147         return trace_seq_putc(s, '!');
0148 
0149     parent = tep_find_function(tep, pfunction);
0150 
0151     if (parent && ftrace_indent->set)
0152         index = add_and_get_index(parent, func, record->cpu);
0153 
0154     trace_seq_printf(s, "%*s", index*3, "");
0155 
0156     if (func)
0157         show_function(s, tep, func, function);
0158     else
0159         trace_seq_printf(s, "0x%llx", function);
0160 
0161     if (ftrace_parent->set) {
0162         trace_seq_printf(s, " <-- ");
0163         if (parent)
0164             show_function(s, tep, parent, pfunction);
0165         else
0166             trace_seq_printf(s, "0x%llx", pfunction);
0167     }
0168 
0169     return 0;
0170 }
0171 
0172 static int
0173 trace_stack_handler(struct trace_seq *s, struct tep_record *record,
0174             struct tep_event *event, void *context)
0175 {
0176     struct tep_format_field *field;
0177     unsigned long long addr;
0178     const char *func;
0179     int long_size;
0180     void *data = record->data;
0181 
0182     field = tep_find_any_field(event, "caller");
0183     if (!field) {
0184         trace_seq_printf(s, "<CANT FIND FIELD %s>", "caller");
0185         return 0;
0186     }
0187 
0188     trace_seq_puts(s, "<stack trace >\n");
0189 
0190     long_size = tep_get_long_size(event->tep);
0191 
0192     for (data += field->offset; data < record->data + record->size;
0193          data += long_size) {
0194         addr = tep_read_number(event->tep, data, long_size);
0195 
0196         if ((long_size == 8 && addr == (unsigned long long)-1) ||
0197             ((int)addr == -1))
0198             break;
0199 
0200         func = tep_find_function(event->tep, addr);
0201         if (func)
0202             trace_seq_printf(s, "=> %s (%llx)\n", func, addr);
0203         else
0204             trace_seq_printf(s, "=> %llx\n", addr);
0205     }
0206 
0207     return 0;
0208 }
0209 
0210 static int
0211 trace_raw_data_handler(struct trace_seq *s, struct tep_record *record,
0212             struct tep_event *event, void *context)
0213 {
0214     struct tep_format_field *field;
0215     unsigned long long id;
0216     int long_size;
0217     void *data = record->data;
0218 
0219     if (tep_get_field_val(s, event, "id", record, &id, 1))
0220         return trace_seq_putc(s, '!');
0221 
0222     trace_seq_printf(s, "# %llx", id);
0223 
0224     field = tep_find_any_field(event, "buf");
0225     if (!field) {
0226         trace_seq_printf(s, "<CANT FIND FIELD %s>", "buf");
0227         return 0;
0228     }
0229 
0230     long_size = tep_get_long_size(event->tep);
0231 
0232     for (data += field->offset; data < record->data + record->size;
0233          data += long_size) {
0234         int size = sizeof(long);
0235         int left = (record->data + record->size) - data;
0236         int i;
0237 
0238         if (size > left)
0239             size = left;
0240 
0241         for (i = 0; i < size; i++)
0242             trace_seq_printf(s, " %02x", *(unsigned char *)(data + i));
0243     }
0244 
0245     return 0;
0246 }
0247 
0248 int TEP_PLUGIN_LOADER(struct tep_handle *tep)
0249 {
0250     tep_register_event_handler(tep, -1, "ftrace", "function",
0251                    function_handler, NULL);
0252 
0253     tep_register_event_handler(tep, -1, "ftrace", "kernel_stack",
0254                       trace_stack_handler, NULL);
0255 
0256     tep_register_event_handler(tep, -1, "ftrace", "raw_data",
0257                       trace_raw_data_handler, NULL);
0258 
0259     tep_plugin_add_options("ftrace", plugin_options);
0260 
0261     return 0;
0262 }
0263 
0264 void TEP_PLUGIN_UNLOADER(struct tep_handle *tep)
0265 {
0266     int i, x;
0267 
0268     tep_unregister_event_handler(tep, -1, "ftrace", "function",
0269                      function_handler, NULL);
0270 
0271     for (i = 0; i <= cpus; i++) {
0272         for (x = 0; x < fstack[i].size && fstack[i].stack[x]; x++)
0273             free(fstack[i].stack[x]);
0274         free(fstack[i].stack);
0275     }
0276 
0277     tep_plugin_remove_options(plugin_options);
0278 
0279     free(fstack);
0280     fstack = NULL;
0281     cpus = -1;
0282 }