aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2010-03-23 09:49:40 -0400
committerSteven Rostedt <rostedt@goodmis.org>2010-03-23 09:49:40 -0400
commit7734efa436eb2a5fa86f079b9d8fa973b977e0dc (patch)
treebbe1ba87ffdb355536d204d3edc25641846921df
parentd632824b6d9993a862a8c7b6b71745ea8ed24bee (diff)
parse-events: Add hook for plugins to register function handling
Sometimes an event may use a helper function inside the print format. Unfortunately, parse-events does not know how to handle these. This patch adds a registration function pevent_register_print_function() That a plugin can use to register how to handle helper functions in the event's print format. Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r--parse-events.c265
-rw-r--r--parse-events.h26
2 files changed, 285 insertions, 6 deletions
diff --git a/parse-events.c b/parse-events.c
index aa4ea94..e942916 100644
--- a/parse-events.c
+++ b/parse-events.c
@@ -28,6 +28,7 @@
28#include <stdio.h> 28#include <stdio.h>
29#include <stdlib.h> 29#include <stdlib.h>
30#include <string.h> 30#include <string.h>
31#include <stdarg.h>
31#include <ctype.h> 32#include <ctype.h>
32#include <errno.h> 33#include <errno.h>
33 34
@@ -60,6 +61,24 @@ struct event_handler {
60 pevent_event_handler_func func; 61 pevent_event_handler_func func;
61}; 62};
62 63
64struct pevent_func_params {
65 struct pevent_func_params *next;
66 enum pevent_func_arg_type type;
67};
68
69struct pevent_function_handler {
70 struct pevent_function_handler *next;
71 enum pevent_func_arg_type ret_type;
72 char *name;
73 pevent_func_handler func;
74 struct pevent_func_params *params;
75 int nr_args;
76};
77
78static unsigned long long
79process_defined_func(struct trace_seq *s, void *data, int size,
80 struct event_format *event, struct print_arg *arg);
81
63/** 82/**
64 * pevent_buffer_init - init buffer for parsing 83 * pevent_buffer_init - init buffer for parsing
65 * @buf: buffer to parse 84 * @buf: buffer to parse
@@ -634,6 +653,8 @@ static void free_flag_sym(struct print_flag_sym *fsym)
634 653
635static void free_arg(struct print_arg *arg) 654static void free_arg(struct print_arg *arg)
636{ 655{
656 struct print_arg *farg;
657
637 if (!arg) 658 if (!arg)
638 return; 659 return;
639 660
@@ -667,6 +688,14 @@ static void free_arg(struct print_arg *arg)
667 free(arg->op.op); 688 free(arg->op.op);
668 free_arg(arg->op.left); 689 free_arg(arg->op.left);
669 free_arg(arg->op.right); 690 free_arg(arg->op.right);
691 break;
692 case PRINT_FUNC:
693 while (arg->func.args) {
694 farg = arg->func.args;
695 arg->func.args = farg->next;
696 free_arg(farg);
697 }
698 break;
670 699
671 case PRINT_NULL: 700 case PRINT_NULL:
672 default: 701 default:
@@ -2201,10 +2230,66 @@ process_str(struct event_format *event __unused, struct print_arg *arg, char **t
2201 return EVENT_ERROR; 2230 return EVENT_ERROR;
2202} 2231}
2203 2232
2233static struct pevent_function_handler *
2234find_func_handler(struct pevent *pevent, char *func_name)
2235{
2236 struct pevent_function_handler *func;
2237
2238 for (func = pevent->func_handlers; func; func = func->next) {
2239 if (strcmp(func->name, func_name) == 0)
2240 break;
2241 }
2242
2243 return func;
2244}
2245
2246static enum event_type
2247process_func_handler(struct event_format *event, struct pevent_function_handler *func,
2248 struct print_arg *arg, char **tok)
2249{
2250 struct print_arg **next_arg;
2251 struct print_arg *farg;
2252 enum event_type type;
2253 char *token;
2254 char *test;
2255 int i;
2256
2257 arg->type = PRINT_FUNC;
2258 arg->func.func = func;
2259
2260 *tok = NULL;
2261
2262 next_arg = &(arg->func.args);
2263 for (i = 0; i < func->nr_args; i++) {
2264 farg = alloc_arg();
2265 type = process_arg(event, farg, &token);
2266 if (i < (func->nr_args - 1))
2267 test = ",";
2268 else
2269 test = ")";
2270
2271 if (test_type_token(type, token, EVENT_DELIM, test)) {
2272 free_arg(farg);
2273 free_token(token);
2274 return EVENT_ERROR;
2275 }
2276
2277 *next_arg = farg;
2278 next_arg = &(farg->next);
2279 }
2280
2281 type = read_token(&token);
2282 *tok = token;
2283
2284 return type;
2285}
2286
2204static enum event_type 2287static enum event_type
2205process_function(struct event_format *event, struct print_arg *arg, 2288process_function(struct event_format *event, struct print_arg *arg,
2206 char *token, char **tok) 2289 char *token, char **tok)
2207{ 2290{
2291 struct pevent_function_handler *func;
2292
2208 if (strcmp(token, "__print_flags") == 0) { 2293 if (strcmp(token, "__print_flags") == 0) {
2209 free_token(token); 2294 free_token(token);
2210 return process_flags(event, arg, tok); 2295 return process_flags(event, arg, tok);
@@ -2222,6 +2307,12 @@ process_function(struct event_format *event, struct print_arg *arg,
2222 return process_dynamic_array(event, arg, tok); 2307 return process_dynamic_array(event, arg, tok);
2223 } 2308 }
2224 2309
2310 func = find_func_handler(event->pevent, token);
2311 if (func) {
2312 free_token(token);
2313 return process_func_handler(event, func, arg, tok);
2314 }
2315
2225 do_warning("function %s not defined", token); 2316 do_warning("function %s not defined", token);
2226 free_token(token); 2317 free_token(token);
2227 return EVENT_ERROR; 2318 return EVENT_ERROR;
@@ -2717,7 +2808,11 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg
2717 return eval_type(val, arg, 0); 2808 return eval_type(val, arg, 0);
2718 case PRINT_STRING: 2809 case PRINT_STRING:
2719 return 0; 2810 return 0;
2720 break; 2811 case PRINT_FUNC: {
2812 struct trace_seq s;
2813 trace_seq_init(&s);
2814 return process_defined_func(&s, data, size, event, arg);
2815 }
2721 case PRINT_OP: 2816 case PRINT_OP:
2722 if (strcmp(arg->op.op, "[") == 0) { 2817 if (strcmp(arg->op.op, "[") == 0) {
2723 /* 2818 /*
@@ -2974,12 +3069,81 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
2974 else 3069 else
2975 print_str_arg(s, data, size, event, arg->op.right->op.right); 3070 print_str_arg(s, data, size, event, arg->op.right->op.right);
2976 break; 3071 break;
3072 case PRINT_FUNC:
3073 process_defined_func(s, data, size, event, arg);
3074 break;
2977 default: 3075 default:
2978 /* well... */ 3076 /* well... */
2979 break; 3077 break;
2980 } 3078 }
2981} 3079}
2982 3080
3081static unsigned long long
3082process_defined_func(struct trace_seq *s, void *data, int size,
3083 struct event_format *event, struct print_arg *arg)
3084{
3085 struct pevent_function_handler *func_handle = arg->func.func;
3086 struct pevent_func_params *param;
3087 unsigned long long *args;
3088 unsigned long long ret;
3089 struct print_arg *farg;
3090 struct trace_seq str;
3091 struct save_str {
3092 struct save_str *next;
3093 char *str;
3094 } *strings = NULL, *string;
3095 int i;
3096
3097 if (!func_handle->nr_args) {
3098 ret = (*func_handle->func)(s, NULL);
3099 goto out;
3100 }
3101
3102 farg = arg->func.args;
3103 param = func_handle->params;
3104
3105 args = malloc_or_die(sizeof(*args) * func_handle->nr_args);
3106 for (i = 0; i < func_handle->nr_args; i++) {
3107 switch (param->type) {
3108 case PEVENT_FUNC_ARG_INT:
3109 case PEVENT_FUNC_ARG_LONG:
3110 case PEVENT_FUNC_ARG_PTR:
3111 args[i] = eval_num_arg(data, size, event, farg);
3112 break;
3113 case PEVENT_FUNC_ARG_STRING:
3114 trace_seq_init(&str);
3115 print_str_arg(&str, data, size, event, farg);
3116 trace_seq_terminate(&str);
3117 string = malloc_or_die(sizeof(*string));
3118 string->next = strings;
3119 string->str = strdup(str.buffer);
3120 strings = string;
3121 break;
3122 default:
3123 /*
3124 * Something went totally wrong, this is not
3125 * an input error, something in this code broke.
3126 */
3127 die("Unexpected end of arguments\n");
3128 break;
3129 }
3130 farg = farg->next;
3131 }
3132
3133 ret = (*func_handle->func)(s, args);
3134 free(args);
3135 while (strings) {
3136 string = strings;
3137 strings = string->next;
3138 free(string->str);
3139 free(string);
3140 }
3141
3142 out:
3143 /* TBD : handle return type here */
3144 return ret;
3145}
3146
2983static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struct event_format *event) 3147static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struct event_format *event)
2984{ 3148{
2985 struct pevent *pevent = event->pevent; 3149 struct pevent *pevent = event->pevent;
@@ -3143,12 +3307,17 @@ get_bprint_format(void *data, int size __unused, struct event_format *event)
3143 return format; 3307 return format;
3144} 3308}
3145 3309
3146static void print_mac_arg(struct trace_seq *s, int mac, void *data, 3310static void print_mac_arg(struct trace_seq *s, int mac, void *data, int size,
3147 struct event_format *event, struct print_arg *arg) 3311 struct event_format *event, struct print_arg *arg)
3148{ 3312{
3149 unsigned char *buf; 3313 unsigned char *buf;
3150 char *fmt = "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x"; 3314 char *fmt = "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x";
3151 3315
3316 if (arg->type == PRINT_FUNC) {
3317 process_defined_func(s, data, size, event, arg);
3318 return;
3319 }
3320
3152 if (arg->type != PRINT_FIELD) { 3321 if (arg->type != PRINT_FIELD) {
3153 trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d", 3322 trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d",
3154 arg->type); 3323 arg->type);
@@ -3256,7 +3425,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
3256 ptr++; 3425 ptr++;
3257 show_func = *ptr; 3426 show_func = *ptr;
3258 } else if (*(ptr+1) == 'M' || *(ptr+1) == 'm') { 3427 } else if (*(ptr+1) == 'M' || *(ptr+1) == 'm') {
3259 print_mac_arg(s, *(ptr+1), data, event, arg); 3428 print_mac_arg(s, *(ptr+1), data, size, event, arg);
3260 ptr++; 3429 ptr++;
3261 break; 3430 break;
3262 } 3431 }
@@ -3972,6 +4141,8 @@ int pevent_parse_event(struct pevent *pevent,
3972 if (find_event_handle(pevent, event)) 4141 if (find_event_handle(pevent, event))
3973 show_warning = 0; 4142 show_warning = 0;
3974 4143
4144 /* Add pevent to event so that function list can be referenced */
4145 event->pevent = pevent;
3975 ret = event_read_print(event); 4146 ret = event_read_print(event);
3976 if (ret < 0) { 4147 if (ret < 0) {
3977 do_warning("failed to read event print fmt for %s", 4148 do_warning("failed to read event print fmt for %s",
@@ -4014,6 +4185,94 @@ int pevent_parse_event(struct pevent *pevent,
4014 return -1; 4185 return -1;
4015} 4186}
4016 4187
4188static void free_func_handle(struct pevent_function_handler *func)
4189{
4190 struct pevent_func_params *params;
4191
4192 free(func->name);
4193
4194 while (func->params) {
4195 params = func->params;
4196 func->params = params->next;
4197 free(params);
4198 }
4199
4200 free(func);
4201}
4202
4203/**
4204 * pevent_register_print_function - register a helper function
4205 * @pevent: the handle to the pevent
4206 * @func: the function to process the helper function
4207 * @name: the name of the helper function
4208 * @parameters: A list of enum pevent_func_arg_type
4209 *
4210 * Some events may have helper functions in the print format arguments.
4211 * This allows a plugin to dynmically create a way to process one
4212 * of these functions.
4213 *
4214 * The @parameters is a variable list of pevent_func_arg_type enums that
4215 * must end with PEVENT_FUNC_ARG_VOID.
4216 */
4217int pevent_register_print_function(struct pevent *pevent,
4218 pevent_func_handler func,
4219 enum pevent_func_arg_type ret_type,
4220 char *name, ...)
4221{
4222 struct pevent_function_handler *func_handle;
4223 struct pevent_func_params **next_param;
4224 struct pevent_func_params *param;
4225 enum pevent_func_arg_type type;
4226 va_list ap;
4227
4228 func_handle = find_func_handler(pevent, name);
4229 if (func_handle) {
4230 warning("function helper '%s' already defined", name);
4231 return -1;
4232 }
4233
4234 func_handle = malloc_or_die(sizeof(*func_handle));
4235 memset(func_handle, 0, sizeof(*func_handle));
4236
4237 func_handle->ret_type = ret_type;
4238 func_handle->name = strdup(name);
4239 func_handle->func = func;
4240 if (!func_handle->name)
4241 die("Failed to allocate function name");
4242
4243 next_param = &(func_handle->params);
4244 va_start(ap, name);
4245 for (;;) {
4246 type = va_arg(ap, enum pevent_func_arg_type);
4247 if (type == PEVENT_FUNC_ARG_VOID)
4248 break;
4249
4250 if (type < 0 || type >= PEVENT_FUNC_ARG_MAX_TYPES) {
4251 warning("Invalid argument type %d", type);
4252 goto out_free;
4253 }
4254
4255 param = malloc_or_die(sizeof(*param));
4256 param->type = type;
4257 param->next = NULL;
4258
4259 *next_param = param;
4260 next_param = &(param->next);
4261
4262 func_handle->nr_args++;
4263 }
4264 va_end(ap);
4265
4266 func_handle->next = pevent->func_handlers;
4267 pevent->func_handlers = func_handle;
4268
4269 return 0;
4270 out_free:
4271 va_end(ap);
4272 free_func_handle(func_handle);
4273 return -1;
4274}
4275
4017/** 4276/**
4018 * pevent_register_event_handle - register a way to parse an event 4277 * pevent_register_event_handle - register a way to parse an event
4019 * @pevent: the handle to the pevent 4278 * @pevent: the handle to the pevent
diff --git a/parse-events.h b/parse-events.h
index d85aefd..33a5b70 100644
--- a/parse-events.h
+++ b/parse-events.h
@@ -176,9 +176,11 @@ struct print_arg_op {
176 struct print_arg *right; 176 struct print_arg *right;
177}; 177};
178 178
179struct pevent_function_handler;
180
179struct print_arg_func { 181struct print_arg_func {
180 char *name; 182 struct pevent_function_handler *func;
181 struct print_arg *args; 183 struct print_arg *args;
182}; 184};
183 185
184enum print_arg_type { 186enum print_arg_type {
@@ -191,6 +193,7 @@ enum print_arg_type {
191 PRINT_STRING, 193 PRINT_STRING,
192 PRINT_DYNAMIC_ARRAY, 194 PRINT_DYNAMIC_ARRAY,
193 PRINT_OP, 195 PRINT_OP,
196 PRINT_FUNC,
194}; 197};
195 198
196struct print_arg { 199struct print_arg {
@@ -253,6 +256,18 @@ enum event_type {
253 EVENT_SQUOTE, 256 EVENT_SQUOTE,
254}; 257};
255 258
259typedef unsigned long long (*pevent_func_handler)(struct trace_seq *s,
260 unsigned long long *args);
261
262enum pevent_func_arg_type {
263 PEVENT_FUNC_ARG_VOID,
264 PEVENT_FUNC_ARG_INT,
265 PEVENT_FUNC_ARG_LONG,
266 PEVENT_FUNC_ARG_STRING,
267 PEVENT_FUNC_ARG_PTR,
268 PEVENT_FUNC_ARG_MAX_TYPES
269};
270
256struct cmdline; 271struct cmdline;
257struct cmdline_list; 272struct cmdline_list;
258struct func_map; 273struct func_map;
@@ -316,6 +331,7 @@ struct pevent {
316 struct format_field *bprint_buf_field; 331 struct format_field *bprint_buf_field;
317 332
318 struct event_handler *handlers; 333 struct event_handler *handlers;
334 struct pevent_function_handler *func_handlers;
319 335
320 /* cache */ 336 /* cache */
321 struct event_format *last_event; 337 struct event_format *last_event;
@@ -390,7 +406,7 @@ enum trace_flag_type {
390}; 406};
391 407
392int pevent_register_comm(struct pevent *pevent, char *comm, int pid); 408int pevent_register_comm(struct pevent *pevent, char *comm, int pid);
393int pevent_register_function(struct pevent *pevetn, char *name, 409int pevent_register_function(struct pevent *pevent, char *name,
394 unsigned long long addr, char *mod); 410 unsigned long long addr, char *mod);
395int pevent_register_print_string(struct pevent *pevent, char *fmt, 411int pevent_register_print_string(struct pevent *pevent, char *fmt,
396 unsigned long long addr); 412 unsigned long long addr);
@@ -406,6 +422,10 @@ int pevent_parse_event(struct pevent *pevent, char *buf, unsigned long size, cha
406 422
407int pevent_register_event_handler(struct pevent *pevent, int id, char *sys_name, char *event_name, 423int pevent_register_event_handler(struct pevent *pevent, int id, char *sys_name, char *event_name,
408 pevent_event_handler_func func); 424 pevent_event_handler_func func);
425int pevent_register_print_function(struct pevent *pevent,
426 pevent_func_handler func,
427 enum pevent_func_arg_type ret_type,
428 char *name, ...);
409 429
410struct format_field *pevent_find_common_field(struct event_format *event, const char *name); 430struct format_field *pevent_find_common_field(struct event_format *event, const char *name);
411struct format_field *pevent_find_field(struct event_format *event, const char *name); 431struct format_field *pevent_find_field(struct event_format *event, const char *name);