| @@ -332,6 +332,23 @@ static int parse_trace_event_arg(char *arg, struct fetch_insn *code, · 331 unmodified lines |
| 332 | return -ENOENT; | 332 | return -ENOENT; |
| 333 | } | 333 | } |
| 334 | | 334 | |
| | 335 | static int parse_trace_event(char *arg, struct fetch_insn *code, |
| | 336 | struct traceprobe_parse_context *ctx) |
| | 337 | { |
| | 338 | int ret; |
| | 339 | |
| | 340 | if (code->data) |
| | 341 | return -EFAULT; |
| | 342 | ret = parse_trace_event_arg(arg, code, ctx); |
| | 343 | if (!ret) |
| | 344 | return 0; |
| | 345 | if (strcmp(arg, "comm") == 0 || strcmp(arg, "COMM") == 0) { |
| | 346 | code->op = FETCH_OP_COMM; |
| | 347 | return 0; |
| | 348 | } |
| | 349 | return -EINVAL; |
| | 350 | } |
| | 351 | |
| 335 | #ifdef CONFIG_PROBE_EVENTS_BTF_ARGS | 352 | #ifdef CONFIG_PROBE_EVENTS_BTF_ARGS |
| 336 | | 353 | |
| 337 | static u32 btf_type_int(const struct btf_type *t) | 354 | static u32 btf_type_int(const struct btf_type *t) |
| @@ -376,11 +393,16 @@ static bool btf_type_is_char_array(struct btf *btf, const struct btf_type *type) · 38 unmodified lines |
| 376 | && BTF_INT_BITS(intdata) == 8; | 393 | && BTF_INT_BITS(intdata) == 8; |
| 377 | } | 394 | } |
| 378 | | 395 | |
| | 396 | static struct btf *ctx_btf(struct traceprobe_parse_context *ctx) |
| | 397 | { |
| | 398 | return ctx->struct_btf ? : ctx->btf; |
| | 399 | } |
| | 400 | |
| 379 | static int check_prepare_btf_string_fetch(char *typename, | 401 | static int check_prepare_btf_string_fetch(char *typename, |
| 380 | struct fetch_insn **pcode, | 402 | struct fetch_insn **pcode, |
| 381 | struct traceprobe_parse_context *ctx) | 403 | struct traceprobe_parse_context *ctx) |
| 382 | { | 404 | { |
| 383 | struct btf *btf = ctx->btf; | 405 | struct btf *btf = ctx_btf(ctx); |
| 384 | | 406 | |
| 385 | if (!btf || !ctx->last_type) | 407 | if (!btf || !ctx->last_type) |
| 386 | return 0; | 408 | return 0; |
| @@ -506,6 +528,15 @@ static int query_btf_context(struct traceprobe_parse_context *ctx) · 119 unmodified lines |
| 506 | return 0; | 528 | return 0; |
| 507 | } | 529 | } |
| 508 | | 530 | |
| | 531 | static void clear_struct_btf(struct traceprobe_parse_context *ctx) |
| | 532 | { |
| | 533 | if (ctx->struct_btf) { |
| | 534 | btf_put(ctx->struct_btf); |
| | 535 | ctx->struct_btf = NULL; |
| | 536 | ctx->last_struct = NULL; |
| | 537 | } |
| | 538 | } |
| | 539 | |
| 509 | static void clear_btf_context(struct traceprobe_parse_context *ctx) | 540 | static void clear_btf_context(struct traceprobe_parse_context *ctx) |
| 510 | { | 541 | { |
| 511 | if (ctx->btf) { | 542 | if (ctx->btf) { |
| @@ -554,22 +585,29 @@ static int parse_btf_field(char *fieldname, const struct btf_type *type, · 42 unmodified lines |
| 554 | struct fetch_insn *code = *pcode; | 585 | struct fetch_insn *code = *pcode; |
| 555 | const struct btf_member *field; | 586 | const struct btf_member *field; |
| 556 | u32 bitoffs, anon_offs; | 587 | u32 bitoffs, anon_offs; |
| | 588 | bool is_struct = ctx->struct_btf != NULL; |
| | 589 | struct btf *btf = ctx_btf(ctx); |
| 557 | char *next; | 590 | char *next; |
| 558 | int is_ptr; | 591 | int is_ptr; |
| 559 | s32 tid; | 592 | s32 tid; |
| 560 | | 593 | |
| 561 | do { | 594 | do { |
| 562 | /* Outer loop for solving arrow operator ('->') */ | 595 | if (!is_struct) { |
| 563 | if (BTF_INFO_KIND(type->info) != BTF_KIND_PTR) { | 596 | /* Outer loop for solving arrow operator ('->') */ |
| 564 | trace_probe_log_err(ctx->offset, NO_PTR_STRCT); | 597 | if (BTF_INFO_KIND(type->info) != BTF_KIND_PTR) { |
| 565 | return -EINVAL; | 598 | trace_probe_log_err(ctx->offset, NO_PTR_STRCT); |
| 566 | } | 599 | return -EINVAL; |
| 567 | /* Convert a struct pointer type to a struct type */ | 600 | } |
| 568 | type = btf_type_skip_modifiers(ctx->btf, type->type, &tid); | 601 | |
| 569 | if (!type) { | 602 | /* Convert a struct pointer type to a struct type */ |
| 570 | trace_probe_log_err(ctx->offset, BAD_BTF_TID); | 603 | type = btf_type_skip_modifiers(btf, type->type, &tid); |
| 571 | return -EINVAL; | 604 | if (!type) { |
| | 605 | trace_probe_log_err(ctx->offset, BAD_BTF_TID); |
| | 606 | return -EINVAL; |
| | 607 | } |
| 572 | } | 608 | } |
| | 609 | /* Only the first type can skip being a pointer */ |
| | 610 | is_struct = false; |
| 573 | | 611 | |
| 574 | bitoffs = 0; | 612 | bitoffs = 0; |
| 575 | do { | 613 | do { |
| @@ -580,7 +618,7 @@ static int parse_btf_field(char *fieldname, const struct btf_type *type, · 4 unmodified lines |
| 580 | return is_ptr; | 618 | return is_ptr; |
| 581 | | 619 | |
| 582 | anon_offs = 0; | 620 | anon_offs = 0; |
| 583 | field = btf_find_struct_member(ctx->btf, type, fieldname, | 621 | field = btf_find_struct_member(btf, type, fieldname, |
| 584 | &anon_offs); | 622 | &anon_offs); |
| 585 | if (IS_ERR(field)) { | 623 | if (IS_ERR(field)) { |
| 586 | trace_probe_log_err(ctx->offset, BAD_BTF_TID); | 624 | trace_probe_log_err(ctx->offset, BAD_BTF_TID); |
| @@ -602,7 +640,7 @@ static int parse_btf_field(char *fieldname, const struct btf_type *type, · 15 unmodified lines |
| 602 | ctx->last_bitsize = 0; | 640 | ctx->last_bitsize = 0; |
| 603 | } | 641 | } |
| 604 | | 642 | |
| 605 | type = btf_type_skip_modifiers(ctx->btf, field->type, &tid); | 643 | type = btf_type_skip_modifiers(btf, field->type, &tid); |
| 606 | if (!type) { | 644 | if (!type) { |
| 607 | trace_probe_log_err(ctx->offset, BAD_BTF_TID); | 645 | trace_probe_log_err(ctx->offset, BAD_BTF_TID); |
| 608 | return -EINVAL; | 646 | return -EINVAL; |
| @@ -640,7 +678,7 @@ static int parse_btf_arg(char *varname, · 31 unmodified lines |
| 640 | int i, is_ptr, ret; | 678 | int i, is_ptr, ret; |
| 641 | u32 tid; | 679 | u32 tid; |
| 642 | | 680 | |
| 643 | if (WARN_ON_ONCE(!ctx->funcname)) | 681 | if (WARN_ON_ONCE(!ctx->funcname && !(ctx->flags & TPARG_FL_TEVENT))) |
| 644 | return -EINVAL; | 682 | return -EINVAL; |
| 645 | | 683 | |
| 646 | is_ptr = split_next_field(varname, &field, ctx); | 684 | is_ptr = split_next_field(varname, &field, ctx); |
| @@ -653,6 +691,19 @@ static int parse_btf_arg(char *varname, · 6 unmodified lines |
| 653 | return -EOPNOTSUPP; | 691 | return -EOPNOTSUPP; |
| 654 | } | 692 | } |
| 655 | | 693 | |
| | 694 | if (ctx->flags & TPARG_FL_TEVENT) { |
| | 695 | ret = parse_trace_event(varname, code, ctx); |
| | 696 | if (ret < 0) { |
| | 697 | trace_probe_log_err(ctx->offset, BAD_ATTACH_ARG); |
| | 698 | return ret; |
| | 699 | } |
| | 700 | /* TEVENT is only here via a typecast */ |
| | 701 | if (WARN_ON_ONCE(ctx->struct_btf == NULL)) |
| | 702 | return -EINVAL; |
| | 703 | type = ctx->last_struct; |
| | 704 | goto found_type; |
| | 705 | } |
| | 706 | |
| 656 | if (ctx->flags & TPARG_FL_RETURN && !strcmp(varname, "$retval")) { | 707 | if (ctx->flags & TPARG_FL_RETURN && !strcmp(varname, "$retval")) { |
| 657 | code->op = FETCH_OP_RETVAL; | 708 | code->op = FETCH_OP_RETVAL; |
| 658 | /* Check whether the function return type is not void */ | 709 | /* Check whether the function return type is not void */ |
| @@ -709,6 +760,7 @@ static int parse_btf_arg(char *varname, · 50 unmodified lines |
| 709 | | 760 | |
| 710 | found: | 761 | found: |
| 711 | type = btf_type_skip_modifiers(ctx->btf, tid, &tid); | 762 | type = btf_type_skip_modifiers(ctx->btf, tid, &tid); |
| | 763 | found_type: |
| 712 | if (!type) { | 764 | if (!type) { |
| 713 | trace_probe_log_err(ctx->offset, BAD_BTF_TID); | 765 | trace_probe_log_err(ctx->offset, BAD_BTF_TID); |
| 714 | return -EINVAL; | 766 | return -EINVAL; |
| @@ -727,7 +779,7 @@ found: · 12 unmodified lines |
| 727 | static const struct fetch_type *find_fetch_type_from_btf_type( | 779 | static const struct fetch_type *find_fetch_type_from_btf_type( |
| 728 | struct traceprobe_parse_context *ctx) | 780 | struct traceprobe_parse_context *ctx) |
| 729 | { | 781 | { |
| 730 | struct btf *btf = ctx->btf; | 782 | struct btf *btf = ctx_btf(ctx); |
| 731 | const char *typestr = NULL; | 783 | const char *typestr = NULL; |
| 732 | | 784 | |
| 733 | if (btf && ctx->last_type) | 785 | if (btf && ctx->last_type) |
| @@ -758,7 +810,67 @@ static int parse_btf_bitfield(struct fetch_insn **pcode, · 24 unmodified lines |
| 758 | return 0; | 810 | return 0; |
| 759 | } | 811 | } |
| 760 | | 812 | |
| 761 | #else | 813 | static int query_btf_struct(const char *sname, struct traceprobe_parse_context *ctx) |
| | 814 | { |
| | 815 | struct btf *btf = NULL; |
| | 816 | int id; |
| | 817 | |
| | 818 | /* A struct_btf should only be used by a single argument */ |
| | 819 | if (WARN_ON_ONCE(ctx->struct_btf)) { |
| | 820 | btf_put(ctx->struct_btf); |
| | 821 | ctx->struct_btf = NULL; |
| | 822 | } |
| | 823 | |
| | 824 | id = bpf_find_btf_id(sname, BTF_KIND_STRUCT, &btf); |
| | 825 | if (id < 0) |
| | 826 | return id; |
| | 827 | ctx->struct_btf = btf; |
| | 828 | ctx->last_struct = btf_type_by_id(ctx->struct_btf, id); |
| | 829 | return 0; |
| | 830 | } |
| | 831 | |
| | 832 | static int handle_typecast(char *arg, struct fetch_insn **pcode, |
| | 833 | struct fetch_insn *end, |
| | 834 | struct traceprobe_parse_context *ctx) |
| | 835 | { |
| | 836 | char *tmp; |
| | 837 | int ret; |
| | 838 | |
| | 839 | /* Currently this only works for eprobes */ |
| | 840 | if (!(ctx->flags & TPARG_FL_TEVENT)) { |
| | 841 | trace_probe_log_err(ctx->offset, TYPECAST_NOT_EVENT); |
| | 842 | return -EINVAL; |
| | 843 | } |
| | 844 | |
| | 845 | tmp = strchr(arg, ')'); |
| | 846 | if (!tmp) { |
| | 847 | trace_probe_log_err(ctx->offset + strlen(arg), |
| | 848 | DEREF_OPEN_BRACE); |
| | 849 | return -EINVAL; |
| | 850 | } |
| | 851 | *tmp = '\0'; |
| | 852 | ret = query_btf_struct(arg + 1, ctx); |
| | 853 | *tmp = ')'; |
| | 854 | |
| | 855 | if (ret < 0) { |
| | 856 | trace_probe_log_err(ctx->offset + 1, NO_PTR_STRCT); |
| | 857 | return -EINVAL; |
| | 858 | } |
| | 859 | |
| | 860 | tmp++; |
| | 861 | |
| | 862 | ctx->offset += tmp - arg; |
| | 863 | ret = parse_btf_arg(tmp, pcode, end, ctx); |
| | 864 | return ret; |
| | 865 | } |
| | 866 | |
| | 867 | #else /* !CONFIG_PROBE_EVENTS_BTF_ARGS */ |
| | 868 | |
| | 869 | static void clear_struct_btf(struct traceprobe_parse_context *ctx) |
| | 870 | { |
| | 871 | ctx->struct_btf = NULL; |
| | 872 | } |
| | 873 | |
| 762 | static void clear_btf_context(struct traceprobe_parse_context *ctx) | 874 | static void clear_btf_context(struct traceprobe_parse_context *ctx) |
| 763 | { | 875 | { |
| 764 | ctx->btf = NULL; | 876 | ctx->btf = NULL; |
| @@ -794,7 +906,15 @@ static int check_prepare_btf_string_fetch(char *typename, · 29 unmodified lines |
| 794 | return 0; | 906 | return 0; |
| 795 | } | 907 | } |
| 796 | | 908 | |
| 797 | #endif | 909 | static int handle_typecast(char *arg, struct fetch_insn **pcode, |
| | 910 | struct fetch_insn *end, |
| | 911 | struct traceprobe_parse_context *ctx) |
| | 912 | { |
| | 913 | trace_probe_log_err(ctx->offset, NOSUP_BTFARG); |
| | 914 | return -EOPNOTSUPP; |
| | 915 | } |
| | 916 | |
| | 917 | #endif /* CONFIG_PROBE_EVENTS_BTF_ARGS */ |
| 798 | | 918 | |
| 799 | #ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API | 919 | #ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API |
| 800 | | 920 | |
| @@ -838,15 +958,10 @@ static int __store_entry_arg(struct trace_probe *tp, int argnum) · 37 unmodified lines |
| 838 | int i, offset, last_offset = 0; | 958 | int i, offset, last_offset = 0; |
| 839 | | 959 | |
| 840 | if (!earg) { | 960 | if (!earg) { |
| 841 | earg = kzalloc_obj(*tp->entry_arg); | 961 | earg = kzalloc_flex(*earg, code, 2 * tp->nr_args + 1); |
| 842 | if (!earg) | 962 | if (!earg) |
| 843 | return -ENOMEM; | 963 | return -ENOMEM; |
| 844 | earg->size = 2 * tp->nr_args + 1; | 964 | earg->size = 2 * tp->nr_args + 1; |
| 845 | earg->code = kzalloc_objs(struct fetch_insn, earg->size); | | |
| 846 | if (!earg->code) { | | |
| 847 | kfree(earg); | | |
| 848 | return -ENOMEM; | | |
| 849 | } | | |
| 850 | /* Fill the code buffer with 'end' to simplify it */ | 965 | /* Fill the code buffer with 'end' to simplify it */ |
| 851 | for (i = 0; i < earg->size; i++) | 966 | for (i = 0; i < earg->size; i++) |
| 852 | earg->code[i].op = FETCH_OP_END; | 967 | earg->code[i].op = FETCH_OP_END; |
| @@ -953,16 +1068,9 @@ static int parse_probe_vars(char *orig_arg, const struct fetch_type *t, · 100 unmodified lines |
| 953 | int len; | 1068 | int len; |
| 954 | | 1069 | |
| 955 | if (ctx->flags & TPARG_FL_TEVENT) { | 1070 | if (ctx->flags & TPARG_FL_TEVENT) { |
| 956 | if (code->data) | 1071 | if (parse_trace_event(arg, code, ctx) < 0) |
| 957 | return -EFAULT; | 1072 | goto inval; |
| 958 | ret = parse_trace_event_arg(arg, code, ctx); | 1073 | return 0; |
| 959 | if (!ret) | | |
| 960 | return 0; | | |
| 961 | if (strcmp(arg, "comm") == 0 || strcmp(arg, "COMM") == 0) { | | |
| 962 | code->op = FETCH_OP_COMM; | | |
| 963 | return 0; | | |
| 964 | } | | |
| 965 | goto inval; | | |
| 966 | } | 1074 | } |
| 967 | | 1075 | |
| 968 | if (str_has_prefix(arg, "retval")) { | 1076 | if (str_has_prefix(arg, "retval")) { |
| @@ -1229,6 +1337,9 @@ parse_probe_arg(char *arg, const struct fetch_type *type, · 260 unmodified lines |
| 1229 | code->op = FETCH_OP_IMM; | 1337 | code->op = FETCH_OP_IMM; |
| 1230 | } | 1338 | } |
| 1231 | break; | 1339 | break; |
| | 1340 | case '(': |
| | 1341 | ret = handle_typecast(arg, pcode, end, ctx); |
| | 1342 | break; |
| 1232 | default: | 1343 | default: |
| 1233 | if (isalpha(arg[0]) || arg[0] == '_') { /* BTF variable */ | 1344 | if (isalpha(arg[0]) || arg[0] == '_') { /* BTF variable */ |
| 1234 | if (!tparg_is_function_entry(ctx->flags) && | 1345 | if (!tparg_is_function_entry(ctx->flags) && |
| @@ -1561,6 +1672,9 @@ fail: · 326 unmodified lines |
| 1561 | } | 1672 | } |
| 1562 | kfree(tmp); | 1673 | kfree(tmp); |
| 1563 | | 1674 | |
| | 1675 | /* struct_btf should not be passed to other arguments */ |
| | 1676 | clear_struct_btf(ctx); |
| | 1677 | |
| 1564 | return ret; | 1678 | return ret; |
| 1565 | } | 1679 | } |
| 1566 | | 1680 | |
| @@ -2049,7 +2163,6 @@ void trace_probe_cleanup(struct trace_probe *tp) · 482 unmodified lines |
| 2049 | traceprobe_free_probe_arg(&tp->args[i]); | 2163 | traceprobe_free_probe_arg(&tp->args[i]); |
| 2050 | | 2164 | |
| 2051 | if (tp->entry_arg) { | 2165 | if (tp->entry_arg) { |
| 2052 | kfree(tp->entry_arg->code); | | |
| 2053 | kfree(tp->entry_arg); | 2166 | kfree(tp->entry_arg); |
| 2054 | tp->entry_arg = NULL; | 2167 | tp->entry_arg = NULL; |
| 2055 | } | 2168 | } |