diff options
Diffstat (limited to 'tools/lib/traceevent/event-parse.c')
| -rw-r--r-- | tools/lib/traceevent/event-parse.c | 399 |
1 files changed, 295 insertions, 104 deletions
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index 554828219c3..5f34aa371b5 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c | |||
| @@ -467,8 +467,10 @@ int pevent_register_function(struct pevent *pevent, char *func, | |||
| 467 | item->mod = NULL; | 467 | item->mod = NULL; |
| 468 | item->addr = addr; | 468 | item->addr = addr; |
| 469 | 469 | ||
| 470 | pevent->funclist = item; | 470 | if (!item->func || (mod && !item->mod)) |
| 471 | die("malloc func"); | ||
| 471 | 472 | ||
| 473 | pevent->funclist = item; | ||
| 472 | pevent->func_count++; | 474 | pevent->func_count++; |
| 473 | 475 | ||
| 474 | return 0; | 476 | return 0; |
| @@ -511,12 +513,12 @@ struct printk_list { | |||
| 511 | 513 | ||
| 512 | static int printk_cmp(const void *a, const void *b) | 514 | static int printk_cmp(const void *a, const void *b) |
| 513 | { | 515 | { |
| 514 | const struct func_map *fa = a; | 516 | const struct printk_map *pa = a; |
| 515 | const struct func_map *fb = b; | 517 | const struct printk_map *pb = b; |
| 516 | 518 | ||
| 517 | if (fa->addr < fb->addr) | 519 | if (pa->addr < pb->addr) |
| 518 | return -1; | 520 | return -1; |
| 519 | if (fa->addr > fb->addr) | 521 | if (pa->addr > pb->addr) |
| 520 | return 1; | 522 | return 1; |
| 521 | 523 | ||
| 522 | return 0; | 524 | return 0; |
| @@ -583,10 +585,13 @@ int pevent_register_print_string(struct pevent *pevent, char *fmt, | |||
| 583 | item = malloc_or_die(sizeof(*item)); | 585 | item = malloc_or_die(sizeof(*item)); |
| 584 | 586 | ||
| 585 | item->next = pevent->printklist; | 587 | item->next = pevent->printklist; |
| 586 | pevent->printklist = item; | ||
| 587 | item->printk = strdup(fmt); | 588 | item->printk = strdup(fmt); |
| 588 | item->addr = addr; | 589 | item->addr = addr; |
| 589 | 590 | ||
| 591 | if (!item->printk) | ||
| 592 | die("malloc fmt"); | ||
| 593 | |||
| 594 | pevent->printklist = item; | ||
| 590 | pevent->printk_count++; | 595 | pevent->printk_count++; |
| 591 | 596 | ||
| 592 | return 0; | 597 | return 0; |
| @@ -616,7 +621,9 @@ static struct event_format *alloc_event(void) | |||
| 616 | { | 621 | { |
| 617 | struct event_format *event; | 622 | struct event_format *event; |
| 618 | 623 | ||
| 619 | event = malloc_or_die(sizeof(*event)); | 624 | event = malloc(sizeof(*event)); |
| 625 | if (!event) | ||
| 626 | return NULL; | ||
| 620 | memset(event, 0, sizeof(*event)); | 627 | memset(event, 0, sizeof(*event)); |
| 621 | 628 | ||
| 622 | return event; | 629 | return event; |
| @@ -626,12 +633,8 @@ static void add_event(struct pevent *pevent, struct event_format *event) | |||
| 626 | { | 633 | { |
| 627 | int i; | 634 | int i; |
| 628 | 635 | ||
| 629 | if (!pevent->events) | 636 | pevent->events = realloc(pevent->events, sizeof(event) * |
| 630 | pevent->events = malloc_or_die(sizeof(event)); | 637 | (pevent->nr_events + 1)); |
| 631 | else | ||
| 632 | pevent->events = | ||
| 633 | realloc(pevent->events, sizeof(event) * | ||
| 634 | (pevent->nr_events + 1)); | ||
| 635 | if (!pevent->events) | 638 | if (!pevent->events) |
| 636 | die("Can not allocate events"); | 639 | die("Can not allocate events"); |
| 637 | 640 | ||
| @@ -697,6 +700,10 @@ static void free_arg(struct print_arg *arg) | |||
| 697 | free_arg(arg->symbol.field); | 700 | free_arg(arg->symbol.field); |
| 698 | free_flag_sym(arg->symbol.symbols); | 701 | free_flag_sym(arg->symbol.symbols); |
| 699 | break; | 702 | break; |
| 703 | case PRINT_HEX: | ||
| 704 | free_arg(arg->hex.field); | ||
| 705 | free_arg(arg->hex.size); | ||
| 706 | break; | ||
| 700 | case PRINT_TYPE: | 707 | case PRINT_TYPE: |
| 701 | free(arg->typecast.type); | 708 | free(arg->typecast.type); |
| 702 | free_arg(arg->typecast.item); | 709 | free_arg(arg->typecast.item); |
| @@ -775,6 +782,25 @@ int pevent_peek_char(void) | |||
| 775 | return __peek_char(); | 782 | return __peek_char(); |
| 776 | } | 783 | } |
| 777 | 784 | ||
| 785 | static int extend_token(char **tok, char *buf, int size) | ||
| 786 | { | ||
| 787 | char *newtok = realloc(*tok, size); | ||
| 788 | |||
| 789 | if (!newtok) { | ||
| 790 | free(*tok); | ||
| 791 | *tok = NULL; | ||
| 792 | return -1; | ||
| 793 | } | ||
| 794 | |||
| 795 | if (!*tok) | ||
| 796 | strcpy(newtok, buf); | ||
| 797 | else | ||
| 798 | strcat(newtok, buf); | ||
| 799 | *tok = newtok; | ||
| 800 | |||
| 801 | return 0; | ||
| 802 | } | ||
| 803 | |||
| 778 | static enum event_type force_token(const char *str, char **tok); | 804 | static enum event_type force_token(const char *str, char **tok); |
| 779 | 805 | ||
| 780 | static enum event_type __read_token(char **tok) | 806 | static enum event_type __read_token(char **tok) |
| @@ -859,17 +885,10 @@ static enum event_type __read_token(char **tok) | |||
| 859 | do { | 885 | do { |
| 860 | if (i == (BUFSIZ - 1)) { | 886 | if (i == (BUFSIZ - 1)) { |
| 861 | buf[i] = 0; | 887 | buf[i] = 0; |
| 862 | if (*tok) { | 888 | tok_size += BUFSIZ; |
| 863 | *tok = realloc(*tok, tok_size + BUFSIZ); | ||
| 864 | if (!*tok) | ||
| 865 | return EVENT_NONE; | ||
| 866 | strcat(*tok, buf); | ||
| 867 | } else | ||
| 868 | *tok = strdup(buf); | ||
| 869 | 889 | ||
| 870 | if (!*tok) | 890 | if (extend_token(tok, buf, tok_size) < 0) |
| 871 | return EVENT_NONE; | 891 | return EVENT_NONE; |
| 872 | tok_size += BUFSIZ; | ||
| 873 | i = 0; | 892 | i = 0; |
| 874 | } | 893 | } |
| 875 | last_ch = ch; | 894 | last_ch = ch; |
| @@ -908,17 +927,10 @@ static enum event_type __read_token(char **tok) | |||
| 908 | while (get_type(__peek_char()) == type) { | 927 | while (get_type(__peek_char()) == type) { |
| 909 | if (i == (BUFSIZ - 1)) { | 928 | if (i == (BUFSIZ - 1)) { |
| 910 | buf[i] = 0; | 929 | buf[i] = 0; |
| 911 | if (*tok) { | 930 | tok_size += BUFSIZ; |
| 912 | *tok = realloc(*tok, tok_size + BUFSIZ); | ||
| 913 | if (!*tok) | ||
| 914 | return EVENT_NONE; | ||
| 915 | strcat(*tok, buf); | ||
| 916 | } else | ||
| 917 | *tok = strdup(buf); | ||
| 918 | 931 | ||
| 919 | if (!*tok) | 932 | if (extend_token(tok, buf, tok_size) < 0) |
| 920 | return EVENT_NONE; | 933 | return EVENT_NONE; |
| 921 | tok_size += BUFSIZ; | ||
| 922 | i = 0; | 934 | i = 0; |
| 923 | } | 935 | } |
| 924 | ch = __read_char(); | 936 | ch = __read_char(); |
| @@ -927,14 +939,7 @@ static enum event_type __read_token(char **tok) | |||
| 927 | 939 | ||
| 928 | out: | 940 | out: |
| 929 | buf[i] = 0; | 941 | buf[i] = 0; |
| 930 | if (*tok) { | 942 | if (extend_token(tok, buf, tok_size + i + 1) < 0) |
| 931 | *tok = realloc(*tok, tok_size + i); | ||
| 932 | if (!*tok) | ||
| 933 | return EVENT_NONE; | ||
| 934 | strcat(*tok, buf); | ||
| 935 | } else | ||
| 936 | *tok = strdup(buf); | ||
| 937 | if (!*tok) | ||
| 938 | return EVENT_NONE; | 943 | return EVENT_NONE; |
| 939 | 944 | ||
| 940 | if (type == EVENT_ITEM) { | 945 | if (type == EVENT_ITEM) { |
| @@ -1255,9 +1260,15 @@ static int event_read_fields(struct event_format *event, struct format_field **f | |||
| 1255 | field->flags |= FIELD_IS_POINTER; | 1260 | field->flags |= FIELD_IS_POINTER; |
| 1256 | 1261 | ||
| 1257 | if (field->type) { | 1262 | if (field->type) { |
| 1258 | field->type = realloc(field->type, | 1263 | char *new_type; |
| 1259 | strlen(field->type) + | 1264 | new_type = realloc(field->type, |
| 1260 | strlen(last_token) + 2); | 1265 | strlen(field->type) + |
| 1266 | strlen(last_token) + 2); | ||
| 1267 | if (!new_type) { | ||
| 1268 | free(last_token); | ||
| 1269 | goto fail; | ||
| 1270 | } | ||
| 1271 | field->type = new_type; | ||
| 1261 | strcat(field->type, " "); | 1272 | strcat(field->type, " "); |
| 1262 | strcat(field->type, last_token); | 1273 | strcat(field->type, last_token); |
| 1263 | free(last_token); | 1274 | free(last_token); |
| @@ -1282,6 +1293,7 @@ static int event_read_fields(struct event_format *event, struct format_field **f | |||
| 1282 | if (strcmp(token, "[") == 0) { | 1293 | if (strcmp(token, "[") == 0) { |
| 1283 | enum event_type last_type = type; | 1294 | enum event_type last_type = type; |
| 1284 | char *brackets = token; | 1295 | char *brackets = token; |
| 1296 | char *new_brackets; | ||
| 1285 | int len; | 1297 | int len; |
| 1286 | 1298 | ||
| 1287 | field->flags |= FIELD_IS_ARRAY; | 1299 | field->flags |= FIELD_IS_ARRAY; |
| @@ -1301,9 +1313,14 @@ static int event_read_fields(struct event_format *event, struct format_field **f | |||
| 1301 | len = 1; | 1313 | len = 1; |
| 1302 | last_type = type; | 1314 | last_type = type; |
| 1303 | 1315 | ||
| 1304 | brackets = realloc(brackets, | 1316 | new_brackets = realloc(brackets, |
| 1305 | strlen(brackets) + | 1317 | strlen(brackets) + |
| 1306 | strlen(token) + len); | 1318 | strlen(token) + len); |
| 1319 | if (!new_brackets) { | ||
| 1320 | free(brackets); | ||
| 1321 | goto fail; | ||
| 1322 | } | ||
| 1323 | brackets = new_brackets; | ||
| 1307 | if (len == 2) | 1324 | if (len == 2) |
| 1308 | strcat(brackets, " "); | 1325 | strcat(brackets, " "); |
| 1309 | strcat(brackets, token); | 1326 | strcat(brackets, token); |
| @@ -1319,7 +1336,12 @@ static int event_read_fields(struct event_format *event, struct format_field **f | |||
| 1319 | 1336 | ||
| 1320 | free_token(token); | 1337 | free_token(token); |
| 1321 | 1338 | ||
| 1322 | brackets = realloc(brackets, strlen(brackets) + 2); | 1339 | new_brackets = realloc(brackets, strlen(brackets) + 2); |
| 1340 | if (!new_brackets) { | ||
| 1341 | free(brackets); | ||
| 1342 | goto fail; | ||
| 1343 | } | ||
| 1344 | brackets = new_brackets; | ||
| 1323 | strcat(brackets, "]"); | 1345 | strcat(brackets, "]"); |
| 1324 | 1346 | ||
| 1325 | /* add brackets to type */ | 1347 | /* add brackets to type */ |
| @@ -1330,10 +1352,16 @@ static int event_read_fields(struct event_format *event, struct format_field **f | |||
| 1330 | * the format: type [] item; | 1352 | * the format: type [] item; |
| 1331 | */ | 1353 | */ |
| 1332 | if (type == EVENT_ITEM) { | 1354 | if (type == EVENT_ITEM) { |
| 1333 | field->type = realloc(field->type, | 1355 | char *new_type; |
| 1334 | strlen(field->type) + | 1356 | new_type = realloc(field->type, |
| 1335 | strlen(field->name) + | 1357 | strlen(field->type) + |
| 1336 | strlen(brackets) + 2); | 1358 | strlen(field->name) + |
| 1359 | strlen(brackets) + 2); | ||
| 1360 | if (!new_type) { | ||
| 1361 | free(brackets); | ||
| 1362 | goto fail; | ||
| 1363 | } | ||
| 1364 | field->type = new_type; | ||
| 1337 | strcat(field->type, " "); | 1365 | strcat(field->type, " "); |
| 1338 | strcat(field->type, field->name); | 1366 | strcat(field->type, field->name); |
| 1339 | free_token(field->name); | 1367 | free_token(field->name); |
| @@ -1341,9 +1369,15 @@ static int event_read_fields(struct event_format *event, struct format_field **f | |||
| 1341 | field->name = token; | 1369 | field->name = token; |
| 1342 | type = read_token(&token); | 1370 | type = read_token(&token); |
| 1343 | } else { | 1371 | } else { |
| 1344 | field->type = realloc(field->type, | 1372 | char *new_type; |
| 1345 | strlen(field->type) + | 1373 | new_type = realloc(field->type, |
| 1346 | strlen(brackets) + 1); | 1374 | strlen(field->type) + |
| 1375 | strlen(brackets) + 1); | ||
| 1376 | if (!new_type) { | ||
| 1377 | free(brackets); | ||
| 1378 | goto fail; | ||
| 1379 | } | ||
| 1380 | field->type = new_type; | ||
| 1347 | strcat(field->type, brackets); | 1381 | strcat(field->type, brackets); |
| 1348 | } | 1382 | } |
| 1349 | free(brackets); | 1383 | free(brackets); |
| @@ -1726,10 +1760,16 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok) | |||
| 1726 | /* could just be a type pointer */ | 1760 | /* could just be a type pointer */ |
| 1727 | if ((strcmp(arg->op.op, "*") == 0) && | 1761 | if ((strcmp(arg->op.op, "*") == 0) && |
| 1728 | type == EVENT_DELIM && (strcmp(token, ")") == 0)) { | 1762 | type == EVENT_DELIM && (strcmp(token, ")") == 0)) { |
| 1763 | char *new_atom; | ||
| 1764 | |||
| 1729 | if (left->type != PRINT_ATOM) | 1765 | if (left->type != PRINT_ATOM) |
| 1730 | die("bad pointer type"); | 1766 | die("bad pointer type"); |
| 1731 | left->atom.atom = realloc(left->atom.atom, | 1767 | new_atom = realloc(left->atom.atom, |
| 1732 | strlen(left->atom.atom) + 3); | 1768 | strlen(left->atom.atom) + 3); |
| 1769 | if (!new_atom) | ||
| 1770 | goto out_free; | ||
| 1771 | |||
| 1772 | left->atom.atom = new_atom; | ||
| 1733 | strcat(left->atom.atom, " *"); | 1773 | strcat(left->atom.atom, " *"); |
| 1734 | free(arg->op.op); | 1774 | free(arg->op.op); |
| 1735 | *arg = *left; | 1775 | *arg = *left; |
| @@ -2146,6 +2186,8 @@ process_fields(struct event_format *event, struct print_flag_sym **list, char ** | |||
| 2146 | if (value == NULL) | 2186 | if (value == NULL) |
| 2147 | goto out_free; | 2187 | goto out_free; |
| 2148 | field->value = strdup(value); | 2188 | field->value = strdup(value); |
| 2189 | if (field->value == NULL) | ||
| 2190 | goto out_free; | ||
| 2149 | 2191 | ||
| 2150 | free_arg(arg); | 2192 | free_arg(arg); |
| 2151 | arg = alloc_arg(); | 2193 | arg = alloc_arg(); |
| @@ -2159,6 +2201,8 @@ process_fields(struct event_format *event, struct print_flag_sym **list, char ** | |||
| 2159 | if (value == NULL) | 2201 | if (value == NULL) |
| 2160 | goto out_free; | 2202 | goto out_free; |
| 2161 | field->str = strdup(value); | 2203 | field->str = strdup(value); |
| 2204 | if (field->str == NULL) | ||
| 2205 | goto out_free; | ||
| 2162 | free_arg(arg); | 2206 | free_arg(arg); |
| 2163 | arg = NULL; | 2207 | arg = NULL; |
| 2164 | 2208 | ||
| @@ -2260,6 +2304,45 @@ process_symbols(struct event_format *event, struct print_arg *arg, char **tok) | |||
| 2260 | } | 2304 | } |
| 2261 | 2305 | ||
| 2262 | static enum event_type | 2306 | static enum event_type |
| 2307 | process_hex(struct event_format *event, struct print_arg *arg, char **tok) | ||
| 2308 | { | ||
| 2309 | struct print_arg *field; | ||
| 2310 | enum event_type type; | ||
| 2311 | char *token; | ||
| 2312 | |||
| 2313 | memset(arg, 0, sizeof(*arg)); | ||
| 2314 | arg->type = PRINT_HEX; | ||
| 2315 | |||
| 2316 | field = alloc_arg(); | ||
| 2317 | type = process_arg(event, field, &token); | ||
| 2318 | |||
| 2319 | if (test_type_token(type, token, EVENT_DELIM, ",")) | ||
| 2320 | goto out_free; | ||
| 2321 | |||
| 2322 | arg->hex.field = field; | ||
| 2323 | |||
| 2324 | free_token(token); | ||
| 2325 | |||
| 2326 | field = alloc_arg(); | ||
| 2327 | type = process_arg(event, field, &token); | ||
| 2328 | |||
| 2329 | if (test_type_token(type, token, EVENT_DELIM, ")")) | ||
| 2330 | goto out_free; | ||
| 2331 | |||
| 2332 | arg->hex.size = field; | ||
| 2333 | |||
| 2334 | free_token(token); | ||
| 2335 | type = read_token_item(tok); | ||
| 2336 | return type; | ||
| 2337 | |||
| 2338 | out_free: | ||
| 2339 | free_arg(field); | ||
| 2340 | free_token(token); | ||
| 2341 | *tok = NULL; | ||
| 2342 | return EVENT_ERROR; | ||
| 2343 | } | ||
| 2344 | |||
| 2345 | static enum event_type | ||
| 2263 | process_dynamic_array(struct event_format *event, struct print_arg *arg, char **tok) | 2346 | process_dynamic_array(struct event_format *event, struct print_arg *arg, char **tok) |
| 2264 | { | 2347 | { |
| 2265 | struct format_field *field; | 2348 | struct format_field *field; |
| @@ -2488,6 +2571,10 @@ process_function(struct event_format *event, struct print_arg *arg, | |||
| 2488 | is_symbolic_field = 1; | 2571 | is_symbolic_field = 1; |
| 2489 | return process_symbols(event, arg, tok); | 2572 | return process_symbols(event, arg, tok); |
| 2490 | } | 2573 | } |
| 2574 | if (strcmp(token, "__print_hex") == 0) { | ||
| 2575 | free_token(token); | ||
| 2576 | return process_hex(event, arg, tok); | ||
| 2577 | } | ||
| 2491 | if (strcmp(token, "__get_str") == 0) { | 2578 | if (strcmp(token, "__get_str") == 0) { |
| 2492 | free_token(token); | 2579 | free_token(token); |
| 2493 | return process_str(event, arg, tok); | 2580 | return process_str(event, arg, tok); |
| @@ -2541,7 +2628,16 @@ process_arg_token(struct event_format *event, struct print_arg *arg, | |||
| 2541 | } | 2628 | } |
| 2542 | /* atoms can be more than one token long */ | 2629 | /* atoms can be more than one token long */ |
| 2543 | while (type == EVENT_ITEM) { | 2630 | while (type == EVENT_ITEM) { |
| 2544 | atom = realloc(atom, strlen(atom) + strlen(token) + 2); | 2631 | char *new_atom; |
| 2632 | new_atom = realloc(atom, | ||
| 2633 | strlen(atom) + strlen(token) + 2); | ||
| 2634 | if (!new_atom) { | ||
| 2635 | free(atom); | ||
| 2636 | *tok = NULL; | ||
| 2637 | free_token(token); | ||
| 2638 | return EVENT_ERROR; | ||
| 2639 | } | ||
| 2640 | atom = new_atom; | ||
| 2545 | strcat(atom, " "); | 2641 | strcat(atom, " "); |
| 2546 | strcat(atom, token); | 2642 | strcat(atom, token); |
| 2547 | free_token(token); | 2643 | free_token(token); |
| @@ -2835,7 +2931,7 @@ static int get_common_info(struct pevent *pevent, | |||
| 2835 | event = pevent->events[0]; | 2931 | event = pevent->events[0]; |
| 2836 | field = pevent_find_common_field(event, type); | 2932 | field = pevent_find_common_field(event, type); |
| 2837 | if (!field) | 2933 | if (!field) |
| 2838 | die("field '%s' not found", type); | 2934 | return -1; |
| 2839 | 2935 | ||
| 2840 | *offset = field->offset; | 2936 | *offset = field->offset; |
| 2841 | *size = field->size; | 2937 | *size = field->size; |
| @@ -2886,15 +2982,16 @@ static int parse_common_flags(struct pevent *pevent, void *data) | |||
| 2886 | 2982 | ||
| 2887 | static int parse_common_lock_depth(struct pevent *pevent, void *data) | 2983 | static int parse_common_lock_depth(struct pevent *pevent, void *data) |
| 2888 | { | 2984 | { |
| 2889 | int ret; | 2985 | return __parse_common(pevent, data, |
| 2890 | 2986 | &pevent->ld_size, &pevent->ld_offset, | |
| 2891 | ret = __parse_common(pevent, data, | 2987 | "common_lock_depth"); |
| 2892 | &pevent->ld_size, &pevent->ld_offset, | 2988 | } |
| 2893 | "common_lock_depth"); | ||
| 2894 | if (ret < 0) | ||
| 2895 | return -1; | ||
| 2896 | 2989 | ||
| 2897 | return ret; | 2990 | static int parse_common_migrate_disable(struct pevent *pevent, void *data) |
| 2991 | { | ||
| 2992 | return __parse_common(pevent, data, | ||
| 2993 | &pevent->ld_size, &pevent->ld_offset, | ||
| 2994 | "common_migrate_disable"); | ||
| 2898 | } | 2995 | } |
| 2899 | 2996 | ||
| 2900 | static int events_id_cmp(const void *a, const void *b); | 2997 | static int events_id_cmp(const void *a, const void *b); |
| @@ -2995,6 +3092,7 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg | |||
| 2995 | break; | 3092 | break; |
| 2996 | case PRINT_FLAGS: | 3093 | case PRINT_FLAGS: |
| 2997 | case PRINT_SYMBOL: | 3094 | case PRINT_SYMBOL: |
| 3095 | case PRINT_HEX: | ||
| 2998 | break; | 3096 | break; |
| 2999 | case PRINT_TYPE: | 3097 | case PRINT_TYPE: |
| 3000 | val = eval_num_arg(data, size, event, arg->typecast.item); | 3098 | val = eval_num_arg(data, size, event, arg->typecast.item); |
| @@ -3214,11 +3312,13 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, | |||
| 3214 | { | 3312 | { |
| 3215 | struct pevent *pevent = event->pevent; | 3313 | struct pevent *pevent = event->pevent; |
| 3216 | struct print_flag_sym *flag; | 3314 | struct print_flag_sym *flag; |
| 3315 | struct format_field *field; | ||
| 3217 | unsigned long long val, fval; | 3316 | unsigned long long val, fval; |
| 3218 | unsigned long addr; | 3317 | unsigned long addr; |
| 3219 | char *str; | 3318 | char *str; |
| 3319 | unsigned char *hex; | ||
| 3220 | int print; | 3320 | int print; |
| 3221 | int len; | 3321 | int i, len; |
| 3222 | 3322 | ||
| 3223 | switch (arg->type) { | 3323 | switch (arg->type) { |
| 3224 | case PRINT_NULL: | 3324 | case PRINT_NULL: |
| @@ -3228,27 +3328,29 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, | |||
| 3228 | print_str_to_seq(s, format, len_arg, arg->atom.atom); | 3328 | print_str_to_seq(s, format, len_arg, arg->atom.atom); |
| 3229 | return; | 3329 | return; |
| 3230 | case PRINT_FIELD: | 3330 | case PRINT_FIELD: |
| 3231 | if (!arg->field.field) { | 3331 | field = arg->field.field; |
| 3232 | arg->field.field = pevent_find_any_field(event, arg->field.name); | 3332 | if (!field) { |
| 3233 | if (!arg->field.field) | 3333 | field = pevent_find_any_field(event, arg->field.name); |
| 3334 | if (!field) | ||
| 3234 | die("field %s not found", arg->field.name); | 3335 | die("field %s not found", arg->field.name); |
| 3336 | arg->field.field = field; | ||
| 3235 | } | 3337 | } |
| 3236 | /* Zero sized fields, mean the rest of the data */ | 3338 | /* Zero sized fields, mean the rest of the data */ |
| 3237 | len = arg->field.field->size ? : size - arg->field.field->offset; | 3339 | len = field->size ? : size - field->offset; |
| 3238 | 3340 | ||
| 3239 | /* | 3341 | /* |
| 3240 | * Some events pass in pointers. If this is not an array | 3342 | * Some events pass in pointers. If this is not an array |
| 3241 | * and the size is the same as long_size, assume that it | 3343 | * and the size is the same as long_size, assume that it |
| 3242 | * is a pointer. | 3344 | * is a pointer. |
| 3243 | */ | 3345 | */ |
| 3244 | if (!(arg->field.field->flags & FIELD_IS_ARRAY) && | 3346 | if (!(field->flags & FIELD_IS_ARRAY) && |
| 3245 | arg->field.field->size == pevent->long_size) { | 3347 | field->size == pevent->long_size) { |
| 3246 | addr = *(unsigned long *)(data + arg->field.field->offset); | 3348 | addr = *(unsigned long *)(data + field->offset); |
| 3247 | trace_seq_printf(s, "%lx", addr); | 3349 | trace_seq_printf(s, "%lx", addr); |
| 3248 | break; | 3350 | break; |
| 3249 | } | 3351 | } |
| 3250 | str = malloc_or_die(len + 1); | 3352 | str = malloc_or_die(len + 1); |
| 3251 | memcpy(str, data + arg->field.field->offset, len); | 3353 | memcpy(str, data + field->offset, len); |
| 3252 | str[len] = 0; | 3354 | str[len] = 0; |
| 3253 | print_str_to_seq(s, format, len_arg, str); | 3355 | print_str_to_seq(s, format, len_arg, str); |
| 3254 | free(str); | 3356 | free(str); |
| @@ -3281,6 +3383,23 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, | |||
| 3281 | } | 3383 | } |
| 3282 | } | 3384 | } |
| 3283 | break; | 3385 | break; |
| 3386 | case PRINT_HEX: | ||
| 3387 | field = arg->hex.field->field.field; | ||
| 3388 | if (!field) { | ||
| 3389 | str = arg->hex.field->field.name; | ||
| 3390 | field = pevent_find_any_field(event, str); | ||
| 3391 | if (!field) | ||
| 3392 | die("field %s not found", str); | ||
| 3393 | arg->hex.field->field.field = field; | ||
| 3394 | } | ||
| 3395 | hex = data + field->offset; | ||
| 3396 | len = eval_num_arg(data, size, event, arg->hex.size); | ||
| 3397 | for (i = 0; i < len; i++) { | ||
| 3398 | if (i) | ||
| 3399 | trace_seq_putc(s, ' '); | ||
| 3400 | trace_seq_printf(s, "%02x", hex[i]); | ||
| 3401 | } | ||
| 3402 | break; | ||
| 3284 | 3403 | ||
| 3285 | case PRINT_TYPE: | 3404 | case PRINT_TYPE: |
| 3286 | break; | 3405 | break; |
| @@ -3299,7 +3418,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, | |||
| 3299 | break; | 3418 | break; |
| 3300 | } | 3419 | } |
| 3301 | case PRINT_BSTRING: | 3420 | case PRINT_BSTRING: |
| 3302 | trace_seq_printf(s, format, arg->string.string); | 3421 | print_str_to_seq(s, format, len_arg, arg->string.string); |
| 3303 | break; | 3422 | break; |
| 3304 | case PRINT_OP: | 3423 | case PRINT_OP: |
| 3305 | /* | 3424 | /* |
| @@ -3363,6 +3482,10 @@ process_defined_func(struct trace_seq *s, void *data, int size, | |||
| 3363 | string = malloc_or_die(sizeof(*string)); | 3482 | string = malloc_or_die(sizeof(*string)); |
| 3364 | string->next = strings; | 3483 | string->next = strings; |
| 3365 | string->str = strdup(str.buffer); | 3484 | string->str = strdup(str.buffer); |
| 3485 | if (!string->str) | ||
| 3486 | die("malloc str"); | ||
| 3487 | |||
| 3488 | args[i] = (unsigned long long)string->str; | ||
| 3366 | strings = string; | 3489 | strings = string; |
| 3367 | trace_seq_destroy(&str); | 3490 | trace_seq_destroy(&str); |
| 3368 | break; | 3491 | break; |
| @@ -3400,6 +3523,7 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc | |||
| 3400 | unsigned long long ip, val; | 3523 | unsigned long long ip, val; |
| 3401 | char *ptr; | 3524 | char *ptr; |
| 3402 | void *bptr; | 3525 | void *bptr; |
| 3526 | int vsize; | ||
| 3403 | 3527 | ||
| 3404 | field = pevent->bprint_buf_field; | 3528 | field = pevent->bprint_buf_field; |
| 3405 | ip_field = pevent->bprint_ip_field; | 3529 | ip_field = pevent->bprint_ip_field; |
| @@ -3448,6 +3572,8 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc | |||
| 3448 | goto process_again; | 3572 | goto process_again; |
| 3449 | case '0' ... '9': | 3573 | case '0' ... '9': |
| 3450 | goto process_again; | 3574 | goto process_again; |
| 3575 | case '.': | ||
| 3576 | goto process_again; | ||
| 3451 | case 'p': | 3577 | case 'p': |
| 3452 | ls = 1; | 3578 | ls = 1; |
| 3453 | /* fall through */ | 3579 | /* fall through */ |
| @@ -3455,23 +3581,30 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc | |||
| 3455 | case 'u': | 3581 | case 'u': |
| 3456 | case 'x': | 3582 | case 'x': |
| 3457 | case 'i': | 3583 | case 'i': |
| 3458 | /* the pointers are always 4 bytes aligned */ | ||
| 3459 | bptr = (void *)(((unsigned long)bptr + 3) & | ||
| 3460 | ~3); | ||
| 3461 | switch (ls) { | 3584 | switch (ls) { |
| 3462 | case 0: | 3585 | case 0: |
| 3463 | ls = 4; | 3586 | vsize = 4; |
| 3464 | break; | 3587 | break; |
| 3465 | case 1: | 3588 | case 1: |
| 3466 | ls = pevent->long_size; | 3589 | vsize = pevent->long_size; |
| 3467 | break; | 3590 | break; |
| 3468 | case 2: | 3591 | case 2: |
| 3469 | ls = 8; | 3592 | vsize = 8; |
| 3593 | break; | ||
| 3470 | default: | 3594 | default: |
| 3595 | vsize = ls; /* ? */ | ||
| 3471 | break; | 3596 | break; |
| 3472 | } | 3597 | } |
| 3473 | val = pevent_read_number(pevent, bptr, ls); | 3598 | /* fall through */ |
| 3474 | bptr += ls; | 3599 | case '*': |
| 3600 | if (*ptr == '*') | ||
| 3601 | vsize = 4; | ||
| 3602 | |||
| 3603 | /* the pointers are always 4 bytes aligned */ | ||
| 3604 | bptr = (void *)(((unsigned long)bptr + 3) & | ||
| 3605 | ~3); | ||
| 3606 | val = pevent_read_number(pevent, bptr, vsize); | ||
| 3607 | bptr += vsize; | ||
| 3475 | arg = alloc_arg(); | 3608 | arg = alloc_arg(); |
| 3476 | arg->next = NULL; | 3609 | arg->next = NULL; |
| 3477 | arg->type = PRINT_ATOM; | 3610 | arg->type = PRINT_ATOM; |
| @@ -3479,12 +3612,21 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc | |||
| 3479 | sprintf(arg->atom.atom, "%lld", val); | 3612 | sprintf(arg->atom.atom, "%lld", val); |
| 3480 | *next = arg; | 3613 | *next = arg; |
| 3481 | next = &arg->next; | 3614 | next = &arg->next; |
| 3615 | /* | ||
| 3616 | * The '*' case means that an arg is used as the length. | ||
| 3617 | * We need to continue to figure out for what. | ||
| 3618 | */ | ||
| 3619 | if (*ptr == '*') | ||
| 3620 | goto process_again; | ||
| 3621 | |||
| 3482 | break; | 3622 | break; |
| 3483 | case 's': | 3623 | case 's': |
| 3484 | arg = alloc_arg(); | 3624 | arg = alloc_arg(); |
| 3485 | arg->next = NULL; | 3625 | arg->next = NULL; |
| 3486 | arg->type = PRINT_BSTRING; | 3626 | arg->type = PRINT_BSTRING; |
| 3487 | arg->string.string = strdup(bptr); | 3627 | arg->string.string = strdup(bptr); |
| 3628 | if (!arg->string.string) | ||
| 3629 | break; | ||
| 3488 | bptr += strlen(bptr) + 1; | 3630 | bptr += strlen(bptr) + 1; |
| 3489 | *next = arg; | 3631 | *next = arg; |
| 3490 | next = &arg->next; | 3632 | next = &arg->next; |
| @@ -3589,6 +3731,16 @@ static void print_mac_arg(struct trace_seq *s, int mac, void *data, int size, | |||
| 3589 | trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); | 3731 | trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); |
| 3590 | } | 3732 | } |
| 3591 | 3733 | ||
| 3734 | static int is_printable_array(char *p, unsigned int len) | ||
| 3735 | { | ||
| 3736 | unsigned int i; | ||
| 3737 | |||
| 3738 | for (i = 0; i < len && p[i]; i++) | ||
| 3739 | if (!isprint(p[i])) | ||
| 3740 | return 0; | ||
| 3741 | return 1; | ||
| 3742 | } | ||
| 3743 | |||
| 3592 | static void print_event_fields(struct trace_seq *s, void *data, int size, | 3744 | static void print_event_fields(struct trace_seq *s, void *data, int size, |
| 3593 | struct event_format *event) | 3745 | struct event_format *event) |
| 3594 | { | 3746 | { |
| @@ -3608,7 +3760,8 @@ static void print_event_fields(struct trace_seq *s, void *data, int size, | |||
| 3608 | len = offset >> 16; | 3760 | len = offset >> 16; |
| 3609 | offset &= 0xffff; | 3761 | offset &= 0xffff; |
| 3610 | } | 3762 | } |
| 3611 | if (field->flags & FIELD_IS_STRING) { | 3763 | if (field->flags & FIELD_IS_STRING && |
| 3764 | is_printable_array(data + offset, len)) { | ||
| 3612 | trace_seq_printf(s, "%s", (char *)data + offset); | 3765 | trace_seq_printf(s, "%s", (char *)data + offset); |
| 3613 | } else { | 3766 | } else { |
| 3614 | trace_seq_puts(s, "ARRAY["); | 3767 | trace_seq_puts(s, "ARRAY["); |
| @@ -3619,6 +3772,7 @@ static void print_event_fields(struct trace_seq *s, void *data, int size, | |||
| 3619 | *((unsigned char *)data + offset + i)); | 3772 | *((unsigned char *)data + offset + i)); |
| 3620 | } | 3773 | } |
| 3621 | trace_seq_putc(s, ']'); | 3774 | trace_seq_putc(s, ']'); |
| 3775 | field->flags &= ~FIELD_IS_STRING; | ||
| 3622 | } | 3776 | } |
| 3623 | } else { | 3777 | } else { |
| 3624 | val = pevent_read_number(event->pevent, data + field->offset, | 3778 | val = pevent_read_number(event->pevent, data + field->offset, |
| @@ -3758,6 +3912,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event | |||
| 3758 | } else if (*(ptr+1) == 'M' || *(ptr+1) == 'm') { | 3912 | } else if (*(ptr+1) == 'M' || *(ptr+1) == 'm') { |
| 3759 | print_mac_arg(s, *(ptr+1), data, size, event, arg); | 3913 | print_mac_arg(s, *(ptr+1), data, size, event, arg); |
| 3760 | ptr++; | 3914 | ptr++; |
| 3915 | arg = arg->next; | ||
| 3761 | break; | 3916 | break; |
| 3762 | } | 3917 | } |
| 3763 | 3918 | ||
| @@ -3794,14 +3949,15 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event | |||
| 3794 | break; | 3949 | break; |
| 3795 | } | 3950 | } |
| 3796 | } | 3951 | } |
| 3797 | if (pevent->long_size == 8 && ls) { | 3952 | if (pevent->long_size == 8 && ls && |
| 3953 | sizeof(long) != 8) { | ||
| 3798 | char *p; | 3954 | char *p; |
| 3799 | 3955 | ||
| 3800 | ls = 2; | 3956 | ls = 2; |
| 3801 | /* make %l into %ll */ | 3957 | /* make %l into %ll */ |
| 3802 | p = strchr(format, 'l'); | 3958 | p = strchr(format, 'l'); |
| 3803 | if (p) | 3959 | if (p) |
| 3804 | memmove(p, p+1, strlen(p)+1); | 3960 | memmove(p+1, p, strlen(p)+1); |
| 3805 | else if (strcmp(format, "%p") == 0) | 3961 | else if (strcmp(format, "%p") == 0) |
| 3806 | strcpy(format, "0x%llx"); | 3962 | strcpy(format, "0x%llx"); |
| 3807 | } | 3963 | } |
| @@ -3878,8 +4034,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event | |||
| 3878 | * pevent_data_lat_fmt - parse the data for the latency format | 4034 | * pevent_data_lat_fmt - parse the data for the latency format |
| 3879 | * @pevent: a handle to the pevent | 4035 | * @pevent: a handle to the pevent |
| 3880 | * @s: the trace_seq to write to | 4036 | * @s: the trace_seq to write to |
| 3881 | * @data: the raw data to read from | 4037 | * @record: the record to read from |
| 3882 | * @size: currently unused. | ||
| 3883 | * | 4038 | * |
| 3884 | * This parses out the Latency format (interrupts disabled, | 4039 | * This parses out the Latency format (interrupts disabled, |
| 3885 | * need rescheduling, in hard/soft interrupt, preempt count | 4040 | * need rescheduling, in hard/soft interrupt, preempt count |
| @@ -3889,10 +4044,13 @@ void pevent_data_lat_fmt(struct pevent *pevent, | |||
| 3889 | struct trace_seq *s, struct pevent_record *record) | 4044 | struct trace_seq *s, struct pevent_record *record) |
| 3890 | { | 4045 | { |
| 3891 | static int check_lock_depth = 1; | 4046 | static int check_lock_depth = 1; |
| 4047 | static int check_migrate_disable = 1; | ||
| 3892 | static int lock_depth_exists; | 4048 | static int lock_depth_exists; |
| 4049 | static int migrate_disable_exists; | ||
| 3893 | unsigned int lat_flags; | 4050 | unsigned int lat_flags; |
| 3894 | unsigned int pc; | 4051 | unsigned int pc; |
| 3895 | int lock_depth; | 4052 | int lock_depth; |
| 4053 | int migrate_disable; | ||
| 3896 | int hardirq; | 4054 | int hardirq; |
| 3897 | int softirq; | 4055 | int softirq; |
| 3898 | void *data = record->data; | 4056 | void *data = record->data; |
| @@ -3900,18 +4058,26 @@ void pevent_data_lat_fmt(struct pevent *pevent, | |||
| 3900 | lat_flags = parse_common_flags(pevent, data); | 4058 | lat_flags = parse_common_flags(pevent, data); |
| 3901 | pc = parse_common_pc(pevent, data); | 4059 | pc = parse_common_pc(pevent, data); |
| 3902 | /* lock_depth may not always exist */ | 4060 | /* lock_depth may not always exist */ |
| 3903 | if (check_lock_depth) { | ||
| 3904 | struct format_field *field; | ||
| 3905 | struct event_format *event; | ||
| 3906 | |||
| 3907 | check_lock_depth = 0; | ||
| 3908 | event = pevent->events[0]; | ||
| 3909 | field = pevent_find_common_field(event, "common_lock_depth"); | ||
| 3910 | if (field) | ||
| 3911 | lock_depth_exists = 1; | ||
| 3912 | } | ||
| 3913 | if (lock_depth_exists) | 4061 | if (lock_depth_exists) |
| 3914 | lock_depth = parse_common_lock_depth(pevent, data); | 4062 | lock_depth = parse_common_lock_depth(pevent, data); |
| 4063 | else if (check_lock_depth) { | ||
| 4064 | lock_depth = parse_common_lock_depth(pevent, data); | ||
| 4065 | if (lock_depth < 0) | ||
| 4066 | check_lock_depth = 0; | ||
| 4067 | else | ||
| 4068 | lock_depth_exists = 1; | ||
| 4069 | } | ||
| 4070 | |||
| 4071 | /* migrate_disable may not always exist */ | ||
| 4072 | if (migrate_disable_exists) | ||
| 4073 | migrate_disable = parse_common_migrate_disable(pevent, data); | ||
| 4074 | else if (check_migrate_disable) { | ||
| 4075 | migrate_disable = parse_common_migrate_disable(pevent, data); | ||
| 4076 | if (migrate_disable < 0) | ||
| 4077 | check_migrate_disable = 0; | ||
| 4078 | else | ||
| 4079 | migrate_disable_exists = 1; | ||
| 4080 | } | ||
| 3915 | 4081 | ||
| 3916 | hardirq = lat_flags & TRACE_FLAG_HARDIRQ; | 4082 | hardirq = lat_flags & TRACE_FLAG_HARDIRQ; |
| 3917 | softirq = lat_flags & TRACE_FLAG_SOFTIRQ; | 4083 | softirq = lat_flags & TRACE_FLAG_SOFTIRQ; |
| @@ -3930,6 +4096,13 @@ void pevent_data_lat_fmt(struct pevent *pevent, | |||
| 3930 | else | 4096 | else |
| 3931 | trace_seq_putc(s, '.'); | 4097 | trace_seq_putc(s, '.'); |
| 3932 | 4098 | ||
| 4099 | if (migrate_disable_exists) { | ||
| 4100 | if (migrate_disable < 0) | ||
| 4101 | trace_seq_putc(s, '.'); | ||
| 4102 | else | ||
| 4103 | trace_seq_printf(s, "%d", migrate_disable); | ||
| 4104 | } | ||
| 4105 | |||
| 3933 | if (lock_depth_exists) { | 4106 | if (lock_depth_exists) { |
| 3934 | if (lock_depth < 0) | 4107 | if (lock_depth < 0) |
| 3935 | trace_seq_putc(s, '.'); | 4108 | trace_seq_putc(s, '.'); |
| @@ -3996,10 +4169,7 @@ const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid) | |||
| 3996 | * pevent_data_comm_from_pid - parse the data into the print format | 4169 | * pevent_data_comm_from_pid - parse the data into the print format |
| 3997 | * @s: the trace_seq to write to | 4170 | * @s: the trace_seq to write to |
| 3998 | * @event: the handle to the event | 4171 | * @event: the handle to the event |
| 3999 | * @cpu: the cpu the event was recorded on | 4172 | * @record: the record to read from |
| 4000 | * @data: the raw data | ||
| 4001 | * @size: the size of the raw data | ||
| 4002 | * @nsecs: the timestamp of the event | ||
| 4003 | * | 4173 | * |
| 4004 | * This parses the raw @data using the given @event information and | 4174 | * This parses the raw @data using the given @event information and |
| 4005 | * writes the print format into the trace_seq. | 4175 | * writes the print format into the trace_seq. |
| @@ -4279,6 +4449,13 @@ static void print_args(struct print_arg *args) | |||
| 4279 | trace_seq_destroy(&s); | 4449 | trace_seq_destroy(&s); |
| 4280 | printf(")"); | 4450 | printf(")"); |
| 4281 | break; | 4451 | break; |
| 4452 | case PRINT_HEX: | ||
| 4453 | printf("__print_hex("); | ||
| 4454 | print_args(args->hex.field); | ||
| 4455 | printf(", "); | ||
| 4456 | print_args(args->hex.size); | ||
| 4457 | printf(")"); | ||
| 4458 | break; | ||
| 4282 | case PRINT_STRING: | 4459 | case PRINT_STRING: |
| 4283 | case PRINT_BSTRING: | 4460 | case PRINT_BSTRING: |
| 4284 | printf("__get_str(%s)", args->string.string); | 4461 | printf("__get_str(%s)", args->string.string); |
| @@ -4541,6 +4718,8 @@ int pevent_parse_event(struct pevent *pevent, | |||
| 4541 | die("failed to read event id"); | 4718 | die("failed to read event id"); |
| 4542 | 4719 | ||
| 4543 | event->system = strdup(sys); | 4720 | event->system = strdup(sys); |
| 4721 | if (!event->system) | ||
| 4722 | die("failed to allocate system"); | ||
| 4544 | 4723 | ||
| 4545 | /* Add pevent to event so that it can be referenced */ | 4724 | /* Add pevent to event so that it can be referenced */ |
| 4546 | event->pevent = pevent; | 4725 | event->pevent = pevent; |
| @@ -4582,6 +4761,11 @@ int pevent_parse_event(struct pevent *pevent, | |||
| 4582 | list = &arg->next; | 4761 | list = &arg->next; |
| 4583 | arg->type = PRINT_FIELD; | 4762 | arg->type = PRINT_FIELD; |
| 4584 | arg->field.name = strdup(field->name); | 4763 | arg->field.name = strdup(field->name); |
| 4764 | if (!arg->field.name) { | ||
| 4765 | do_warning("failed to allocate field name"); | ||
| 4766 | event->flags |= EVENT_FL_FAILED; | ||
| 4767 | return -1; | ||
| 4768 | } | ||
| 4585 | arg->field.field = field; | 4769 | arg->field.field = field; |
| 4586 | } | 4770 | } |
| 4587 | return 0; | 4771 | return 0; |
| @@ -4753,7 +4937,7 @@ int pevent_get_any_field_val(struct trace_seq *s, struct event_format *event, | |||
| 4753 | * @record: The record with the field name. | 4937 | * @record: The record with the field name. |
| 4754 | * @err: print default error if failed. | 4938 | * @err: print default error if failed. |
| 4755 | * | 4939 | * |
| 4756 | * Returns: 0 on success, -1 field not fould, or 1 if buffer is full. | 4940 | * Returns: 0 on success, -1 field not found, or 1 if buffer is full. |
| 4757 | */ | 4941 | */ |
| 4758 | int pevent_print_num_field(struct trace_seq *s, const char *fmt, | 4942 | int pevent_print_num_field(struct trace_seq *s, const char *fmt, |
| 4759 | struct event_format *event, const char *name, | 4943 | struct event_format *event, const char *name, |
| @@ -4795,11 +4979,12 @@ static void free_func_handle(struct pevent_function_handler *func) | |||
| 4795 | * pevent_register_print_function - register a helper function | 4979 | * pevent_register_print_function - register a helper function |
| 4796 | * @pevent: the handle to the pevent | 4980 | * @pevent: the handle to the pevent |
| 4797 | * @func: the function to process the helper function | 4981 | * @func: the function to process the helper function |
| 4982 | * @ret_type: the return type of the helper function | ||
| 4798 | * @name: the name of the helper function | 4983 | * @name: the name of the helper function |
| 4799 | * @parameters: A list of enum pevent_func_arg_type | 4984 | * @parameters: A list of enum pevent_func_arg_type |
| 4800 | * | 4985 | * |
| 4801 | * Some events may have helper functions in the print format arguments. | 4986 | * Some events may have helper functions in the print format arguments. |
| 4802 | * This allows a plugin to dynmically create a way to process one | 4987 | * This allows a plugin to dynamically create a way to process one |
| 4803 | * of these functions. | 4988 | * of these functions. |
| 4804 | * | 4989 | * |
| 4805 | * The @parameters is a variable list of pevent_func_arg_type enums that | 4990 | * The @parameters is a variable list of pevent_func_arg_type enums that |
| @@ -4870,12 +5055,13 @@ int pevent_register_print_function(struct pevent *pevent, | |||
| 4870 | } | 5055 | } |
| 4871 | 5056 | ||
| 4872 | /** | 5057 | /** |
| 4873 | * pevent_register_event_handle - register a way to parse an event | 5058 | * pevent_register_event_handler - register a way to parse an event |
| 4874 | * @pevent: the handle to the pevent | 5059 | * @pevent: the handle to the pevent |
| 4875 | * @id: the id of the event to register | 5060 | * @id: the id of the event to register |
| 4876 | * @sys_name: the system name the event belongs to | 5061 | * @sys_name: the system name the event belongs to |
| 4877 | * @event_name: the name of the event | 5062 | * @event_name: the name of the event |
| 4878 | * @func: the function to call to parse the event information | 5063 | * @func: the function to call to parse the event information |
| 5064 | * @context: the data to be passed to @func | ||
| 4879 | * | 5065 | * |
| 4880 | * This function allows a developer to override the parsing of | 5066 | * This function allows a developer to override the parsing of |
| 4881 | * a given event. If for some reason the default print format | 5067 | * a given event. If for some reason the default print format |
| @@ -4925,6 +5111,11 @@ int pevent_register_event_handler(struct pevent *pevent, | |||
| 4925 | if (sys_name) | 5111 | if (sys_name) |
| 4926 | handle->sys_name = strdup(sys_name); | 5112 | handle->sys_name = strdup(sys_name); |
| 4927 | 5113 | ||
| 5114 | if ((event_name && !handle->event_name) || | ||
| 5115 | (sys_name && !handle->sys_name)) { | ||
| 5116 | die("Failed to allocate event/sys name"); | ||
| 5117 | } | ||
| 5118 | |||
| 4928 | handle->func = func; | 5119 | handle->func = func; |
| 4929 | handle->next = pevent->handlers; | 5120 | handle->next = pevent->handlers; |
| 4930 | pevent->handlers = handle; | 5121 | pevent->handlers = handle; |
