Lines Matching +full:tp +full:- +full:link
1 // SPDX-License-Identifier: GPL-2.0
3 * Common code for probe-based Dynamic events.
9 * Copyright (C) IBM Corporation, 2010-2011
211 *(p - 1) = '\0'; in __trace_probe_log_err()
226 return -EINVAL; in traceprobe_split_symbol_offset()
228 tmp = strpbrk(symbol, "+-"); in traceprobe_split_symbol_offset()
254 return -EINVAL; in traceprobe_parse_event_name()
256 if (slash - event + 1 > MAX_EVENT_NAME_LEN) { in traceprobe_parse_event_name()
258 return -EINVAL; in traceprobe_parse_event_name()
260 strscpy(buf, event, slash - event + 1); in traceprobe_parse_event_name()
263 return -EINVAL; in traceprobe_parse_event_name()
267 offset += slash - event + 1; in traceprobe_parse_event_name()
277 return -EINVAL; in traceprobe_parse_event_name()
280 return -EINVAL; in traceprobe_parse_event_name()
284 return -EINVAL; in traceprobe_parse_event_name()
295 head = trace_get_fields(ctx->event); in parse_trace_event_arg()
296 list_for_each_entry(field, head, link) { in parse_trace_event_arg()
297 if (!strcmp(arg, field->name)) { in parse_trace_event_arg()
298 code->op = FETCH_OP_TP_ARG; in parse_trace_event_arg()
299 code->data = field; in parse_trace_event_arg()
303 return -ENOENT; in parse_trace_event_arg()
319 real_type = btf_type_skip_modifiers(btf, type->type, &tid); in btf_type_is_char_ptr()
323 if (BTF_INFO_KIND(real_type->info) != BTF_KIND_INT) in btf_type_is_char_ptr()
338 if (BTF_INFO_KIND(type->info) != BTF_KIND_ARRAY) in btf_type_is_char_array()
343 real_type = btf_type_skip_modifiers(btf, array->type, &tid); in btf_type_is_char_array()
354 struct btf *btf = ctx->btf; in check_prepare_btf_string_fetch()
356 if (!btf || !ctx->last_type) in check_prepare_btf_string_fetch()
360 if (btf_type_is_char_array(btf, ctx->last_type)) in check_prepare_btf_string_fetch()
364 if (btf_type_is_char_ptr(btf, ctx->last_type)) { in check_prepare_btf_string_fetch()
367 if (code->op == FETCH_OP_END) { in check_prepare_btf_string_fetch()
368 trace_probe_log_err(ctx->offset, TOO_MANY_OPS); in check_prepare_btf_string_fetch()
369 return -E2BIG; in check_prepare_btf_string_fetch()
372 code->op = FETCH_OP_UDEREF; in check_prepare_btf_string_fetch()
374 code->op = FETCH_OP_DEREF; in check_prepare_btf_string_fetch()
375 code->offset = 0; in check_prepare_btf_string_fetch()
380 trace_probe_log_err(ctx->offset, BAD_TYPE4STR); in check_prepare_btf_string_fetch()
381 return -EINVAL; in check_prepare_btf_string_fetch()
391 switch (BTF_INFO_KIND(type->info)) { in fetch_type_from_btf_type()
428 ctx->last_bitsize = BTF_INT_BITS(intdata); in fetch_type_from_btf_type()
429 ctx->last_bitoffs += BTF_INT_OFFSET(intdata); in fetch_type_from_btf_type()
445 if (ctx->btf) in query_btf_context()
448 if (!ctx->funcname) in query_btf_context()
449 return -EINVAL; in query_btf_context()
451 type = btf_find_func_proto(ctx->funcname, &btf); in query_btf_context()
453 return -ENOENT; in query_btf_context()
455 ctx->btf = btf; in query_btf_context()
456 ctx->proto = type; in query_btf_context()
458 /* ctx->params is optional, since func(void) will not have params. */ in query_btf_context()
463 if (ctx->flags & TPARG_FL_TPOINT) { in query_btf_context()
464 nr--; in query_btf_context()
470 ctx->nr_params = nr; in query_btf_context()
471 ctx->params = param; in query_btf_context()
473 ctx->nr_params = 0; in query_btf_context()
474 ctx->params = NULL; in query_btf_context()
482 if (ctx->btf) { in clear_btf_context()
483 btf_put(ctx->btf); in clear_btf_context()
484 ctx->btf = NULL; in clear_btf_context()
485 ctx->proto = NULL; in clear_btf_context()
486 ctx->params = NULL; in clear_btf_context()
487 ctx->nr_params = 0; in clear_btf_context()
491 /* Return 1 if the field separater is arrow operator ('->') */
498 field = strpbrk(varname, ".-"); in split_next_field()
500 if (field[0] == '-' && field[1] == '>') { in split_next_field()
508 trace_probe_log_err(ctx->offset + field - varname, BAD_HYPHEN); in split_next_field()
509 return -EINVAL; in split_next_field()
533 /* Outer loop for solving arrow operator ('->') */ in parse_btf_field()
534 if (BTF_INFO_KIND(type->info) != BTF_KIND_PTR) { in parse_btf_field()
535 trace_probe_log_err(ctx->offset, NO_PTR_STRCT); in parse_btf_field()
536 return -EINVAL; in parse_btf_field()
539 type = btf_type_skip_modifiers(ctx->btf, type->type, &tid); in parse_btf_field()
541 trace_probe_log_err(ctx->offset, BAD_BTF_TID); in parse_btf_field()
542 return -EINVAL; in parse_btf_field()
554 field = btf_find_struct_member(ctx->btf, type, fieldname, in parse_btf_field()
557 trace_probe_log_err(ctx->offset, BAD_BTF_TID); in parse_btf_field()
561 trace_probe_log_err(ctx->offset, NO_BTF_FIELD); in parse_btf_field()
562 return -ENOENT; in parse_btf_field()
567 /* Accumulate the bit-offsets of the dot-connected fields */ in parse_btf_field()
569 bitoffs += BTF_MEMBER_BIT_OFFSET(field->offset); in parse_btf_field()
570 ctx->last_bitsize = BTF_MEMBER_BITFIELD_SIZE(field->offset); in parse_btf_field()
572 bitoffs += field->offset; in parse_btf_field()
573 ctx->last_bitsize = 0; in parse_btf_field()
576 type = btf_type_skip_modifiers(ctx->btf, field->type, &tid); in parse_btf_field()
578 trace_probe_log_err(ctx->offset, BAD_BTF_TID); in parse_btf_field()
579 return -EINVAL; in parse_btf_field()
582 ctx->offset += next - fieldname; in parse_btf_field()
587 trace_probe_log_err(ctx->offset, TOO_MANY_OPS); in parse_btf_field()
588 return -EINVAL; in parse_btf_field()
590 code->op = FETCH_OP_DEREF; /* TODO: user deref support */ in parse_btf_field()
591 code->offset = bitoffs / 8; in parse_btf_field()
594 ctx->last_bitoffs = bitoffs % 8; in parse_btf_field()
595 ctx->last_type = type; in parse_btf_field()
601 static int __store_entry_arg(struct trace_probe *tp, int argnum);
614 if (WARN_ON_ONCE(!ctx->funcname)) in parse_btf_arg()
615 return -EINVAL; in parse_btf_arg()
621 /* dot-connected field on an argument is not supported. */ in parse_btf_arg()
622 trace_probe_log_err(ctx->offset + field - varname, in parse_btf_arg()
624 return -EOPNOTSUPP; in parse_btf_arg()
627 if (ctx->flags & TPARG_FL_RETURN && !strcmp(varname, "$retval")) { in parse_btf_arg()
628 code->op = FETCH_OP_RETVAL; in parse_btf_arg()
631 if (ctx->proto->type == 0) { in parse_btf_arg()
632 trace_probe_log_err(ctx->offset, NO_RETVAL); in parse_btf_arg()
633 return -ENOENT; in parse_btf_arg()
635 tid = ctx->proto->type; in parse_btf_arg()
639 trace_probe_log_err(ctx->offset + field - varname, in parse_btf_arg()
641 return -ENOENT; in parse_btf_arg()
646 if (!ctx->btf) { in parse_btf_arg()
648 if (ret < 0 || ctx->nr_params == 0) { in parse_btf_arg()
649 trace_probe_log_err(ctx->offset, NO_BTF_ENTRY); in parse_btf_arg()
653 params = ctx->params; in parse_btf_arg()
655 for (i = 0; i < ctx->nr_params; i++) { in parse_btf_arg()
656 const char *name = btf_name_by_offset(ctx->btf, params[i].name_off); in parse_btf_arg()
659 if (tparg_is_function_entry(ctx->flags)) { in parse_btf_arg()
660 code->op = FETCH_OP_ARG; in parse_btf_arg()
661 if (ctx->flags & TPARG_FL_TPOINT) in parse_btf_arg()
662 code->param = i + 1; in parse_btf_arg()
664 code->param = i; in parse_btf_arg()
665 } else if (tparg_is_function_return(ctx->flags)) { in parse_btf_arg()
666 code->op = FETCH_OP_EDATA; in parse_btf_arg()
667 ret = __store_entry_arg(ctx->tp, i); in parse_btf_arg()
672 code->offset = ret; in parse_btf_arg()
678 trace_probe_log_err(ctx->offset, NO_BTFARG); in parse_btf_arg()
679 return -ENOENT; in parse_btf_arg()
682 type = btf_type_skip_modifiers(ctx->btf, tid, &tid); in parse_btf_arg()
684 trace_probe_log_err(ctx->offset, BAD_BTF_TID); in parse_btf_arg()
685 return -EINVAL; in parse_btf_arg()
688 ctx->last_type = type; in parse_btf_arg()
689 ctx->last_bitoffs = 0; in parse_btf_arg()
690 ctx->last_bitsize = 0; in parse_btf_arg()
692 ctx->offset += field - varname; in parse_btf_arg()
701 struct btf *btf = ctx->btf; in find_fetch_type_from_btf_type()
704 if (btf && ctx->last_type) in find_fetch_type_from_btf_type()
705 typestr = fetch_type_from_btf_type(btf, ctx->last_type, ctx); in find_fetch_type_from_btf_type()
707 return find_fetch_type(typestr, ctx->flags); in find_fetch_type_from_btf_type()
715 if ((ctx->last_bitsize % 8 == 0) && ctx->last_bitoffs == 0) in parse_btf_bitfield()
719 if (code->op != FETCH_OP_NOP) { in parse_btf_bitfield()
720 trace_probe_log_err(ctx->offset, TOO_MANY_OPS); in parse_btf_bitfield()
721 return -EINVAL; in parse_btf_bitfield()
725 code->op = FETCH_OP_MOD_BF; in parse_btf_bitfield()
726 code->lshift = 64 - (ctx->last_bitsize + ctx->last_bitoffs); in parse_btf_bitfield()
727 code->rshift = 64 - ctx->last_bitsize; in parse_btf_bitfield()
728 code->basesize = 64 / 8; in parse_btf_bitfield()
735 ctx->btf = NULL; in clear_btf_context()
740 return -EOPNOTSUPP; in query_btf_context()
747 trace_probe_log_err(ctx->offset, NOSUP_BTFARG); in parse_btf_arg()
748 return -EOPNOTSUPP; in parse_btf_arg()
754 trace_probe_log_err(ctx->offset, NOSUP_BTFARG); in parse_btf_bitfield()
755 return -EOPNOTSUPP; in parse_btf_bitfield()
759 find_fetch_type(NULL, ctx->flags)
772 static int __store_entry_arg(struct trace_probe *tp, int argnum) in __store_entry_arg() argument
774 struct probe_entry_arg *earg = tp->entry_arg; in __store_entry_arg()
779 earg = kzalloc(sizeof(*tp->entry_arg), GFP_KERNEL); in __store_entry_arg()
781 return -ENOMEM; in __store_entry_arg()
782 earg->size = 2 * tp->nr_args + 1; in __store_entry_arg()
783 earg->code = kcalloc(earg->size, sizeof(struct fetch_insn), in __store_entry_arg()
785 if (!earg->code) { in __store_entry_arg()
787 return -ENOMEM; in __store_entry_arg()
790 for (i = 0; i < earg->size; i++) in __store_entry_arg()
791 earg->code[i].op = FETCH_OP_END; in __store_entry_arg()
792 tp->entry_arg = earg; in __store_entry_arg()
796 for (i = 0; i < earg->size - 1; i++) { in __store_entry_arg()
797 switch (earg->code[i].op) { in __store_entry_arg()
799 earg->code[i].op = FETCH_OP_ARG; in __store_entry_arg()
800 earg->code[i].param = argnum; in __store_entry_arg()
801 earg->code[i + 1].op = FETCH_OP_ST_EDATA; in __store_entry_arg()
802 earg->code[i + 1].offset = offset; in __store_entry_arg()
805 match = (earg->code[i].param == argnum); in __store_entry_arg()
808 offset = earg->code[i].offset; in __store_entry_arg()
817 return -ENOSPC; in __store_entry_arg()
820 int traceprobe_get_entry_data_size(struct trace_probe *tp) in traceprobe_get_entry_data_size() argument
822 struct probe_entry_arg *earg = tp->entry_arg; in traceprobe_get_entry_data_size()
828 for (i = 0; i < earg->size; i++) { in traceprobe_get_entry_data_size()
829 switch (earg->code[i].op) { in traceprobe_get_entry_data_size()
833 size = earg->code[i].offset + sizeof(unsigned long); in traceprobe_get_entry_data_size()
843 void store_trace_entry_data(void *edata, struct trace_probe *tp, struct pt_regs *regs) in store_trace_entry_data() argument
845 struct probe_entry_arg *earg = tp->entry_arg; in store_trace_entry_data()
852 for (i = 0; i < earg->size; i++) { in store_trace_entry_data()
853 struct fetch_insn *code = &earg->code[i]; in store_trace_entry_data()
855 switch (code->op) { in store_trace_entry_data()
857 val = regs_get_kernel_argument(regs, code->param); in store_trace_entry_data()
860 *(unsigned long *)((unsigned long)edata + code->offset) = val; in store_trace_entry_data()
876 /* Parse $vars. @orig_arg points '$', which syncs to @ctx->offset */ in NOKPROBE_SYMBOL()
889 if (ctx->flags & TPARG_FL_TEVENT) { in NOKPROBE_SYMBOL()
890 if (code->data) in NOKPROBE_SYMBOL()
891 return -EFAULT; in NOKPROBE_SYMBOL()
896 code->op = FETCH_OP_COMM; in NOKPROBE_SYMBOL()
900 ctx->offset = 0; in NOKPROBE_SYMBOL()
905 if (!(ctx->flags & TPARG_FL_RETURN)) { in NOKPROBE_SYMBOL()
909 if (!(ctx->flags & TPARG_FL_KERNEL) || in NOKPROBE_SYMBOL()
911 code->op = FETCH_OP_RETVAL; in NOKPROBE_SYMBOL()
921 code->op = FETCH_OP_STACKP; in NOKPROBE_SYMBOL()
930 if ((ctx->flags & TPARG_FL_KERNEL) && in NOKPROBE_SYMBOL()
935 code->op = FETCH_OP_STACK; in NOKPROBE_SYMBOL()
936 code->param = (unsigned int)param; in NOKPROBE_SYMBOL()
943 code->op = FETCH_OP_COMM; in NOKPROBE_SYMBOL()
958 param--; /* argN starts from 1, but internal arg[N] starts from 0 */ in NOKPROBE_SYMBOL()
960 if (tparg_is_function_entry(ctx->flags)) { in NOKPROBE_SYMBOL()
961 code->op = FETCH_OP_ARG; in NOKPROBE_SYMBOL()
962 code->param = (unsigned int)param; in NOKPROBE_SYMBOL()
967 if (ctx->flags & TPARG_FL_TPOINT) in NOKPROBE_SYMBOL()
968 code->param++; in NOKPROBE_SYMBOL()
969 } else if (tparg_is_function_return(ctx->flags)) { in NOKPROBE_SYMBOL()
971 ret = __store_entry_arg(ctx->tp, param); in NOKPROBE_SYMBOL()
975 code->op = FETCH_OP_EDATA; in NOKPROBE_SYMBOL()
976 code->offset = ret; in NOKPROBE_SYMBOL()
986 __trace_probe_log_err(ctx->offset, err); in NOKPROBE_SYMBOL()
987 return -EINVAL; in NOKPROBE_SYMBOL()
994 else if (str[0] == '-') in str_to_immediate()
998 return -EINVAL; in str_to_immediate()
1005 if (str[len - 1] != '"') { in __parse_imm_string()
1007 return -EINVAL; in __parse_imm_string()
1009 *pbuf = kstrndup(str, len - 1, GFP_KERNEL); in __parse_imm_string()
1011 return -ENOMEM; in __parse_imm_string()
1034 if (ctx->flags & (TPARG_FL_TEVENT | TPARG_FL_FPROBE)) { in parse_probe_arg()
1036 trace_probe_log_err(ctx->offset, BAD_VAR); in parse_probe_arg()
1041 code->op = FETCH_OP_REG; in parse_probe_arg()
1042 code->param = (unsigned int)ret; in parse_probe_arg()
1045 trace_probe_log_err(ctx->offset, BAD_REG_NAME); in parse_probe_arg()
1048 case '@': /* memory, file-offset or symbol */ in parse_probe_arg()
1052 trace_probe_log_err(ctx->offset, BAD_MEM_ADDR); in parse_probe_arg()
1056 code->op = FETCH_OP_IMM; in parse_probe_arg()
1057 code->immediate = param; in parse_probe_arg()
1060 if (ctx->flags & TPARG_FL_KERNEL) { in parse_probe_arg()
1061 trace_probe_log_err(ctx->offset, FILE_ON_KPROBE); in parse_probe_arg()
1062 return -EINVAL; in parse_probe_arg()
1066 trace_probe_log_err(ctx->offset, BAD_FILE_OFFS); in parse_probe_arg()
1070 code->op = FETCH_OP_FOFFS; in parse_probe_arg()
1071 code->immediate = (unsigned long)offset; // imm64? in parse_probe_arg()
1074 if (!(ctx->flags & TPARG_FL_KERNEL)) { in parse_probe_arg()
1075 trace_probe_log_err(ctx->offset, SYM_ON_UPROBE); in parse_probe_arg()
1076 return -EINVAL; in parse_probe_arg()
1079 code->op = FETCH_NOP_SYMBOL; in parse_probe_arg()
1080 code->data = kstrdup(arg + 1, GFP_KERNEL); in parse_probe_arg()
1081 if (!code->data) in parse_probe_arg()
1082 return -ENOMEM; in parse_probe_arg()
1084 trace_probe_log_err(ctx->offset, TOO_MANY_OPS); in parse_probe_arg()
1085 return -EINVAL; in parse_probe_arg()
1087 code->op = FETCH_OP_IMM; in parse_probe_arg()
1088 code->immediate = 0; in parse_probe_arg()
1092 trace_probe_log_err(ctx->offset, TOO_MANY_OPS); in parse_probe_arg()
1093 return -EINVAL; in parse_probe_arg()
1096 code->op = FETCH_OP_DEREF; in parse_probe_arg()
1097 code->offset = offset; in parse_probe_arg()
1101 case '-': in parse_probe_arg()
1111 trace_probe_log_err(ctx->offset, DEREF_NEED_BRACE); in parse_probe_arg()
1112 return -EINVAL; in parse_probe_arg()
1117 trace_probe_log_err(ctx->offset, BAD_DEREF_OFFS); in parse_probe_arg()
1120 ctx->offset += (tmp + 1 - arg) + (arg[0] != '-' ? 1 : 0); in parse_probe_arg()
1124 trace_probe_log_err(ctx->offset + strlen(arg), in parse_probe_arg()
1126 return -EINVAL; in parse_probe_arg()
1128 const struct fetch_type *t2 = find_fetch_type(NULL, ctx->flags); in parse_probe_arg()
1129 int cur_offs = ctx->offset; in parse_probe_arg()
1135 ctx->offset = cur_offs; in parse_probe_arg()
1136 if (code->op == FETCH_OP_COMM || in parse_probe_arg()
1137 code->op == FETCH_OP_DATA) { in parse_probe_arg()
1138 trace_probe_log_err(ctx->offset, COMM_CANT_DEREF); in parse_probe_arg()
1139 return -EINVAL; in parse_probe_arg()
1142 trace_probe_log_err(ctx->offset, TOO_MANY_OPS); in parse_probe_arg()
1143 return -EINVAL; in parse_probe_arg()
1147 code->op = deref; in parse_probe_arg()
1148 code->offset = offset; in parse_probe_arg()
1150 ctx->last_type = NULL; in parse_probe_arg()
1155 ret = __parse_imm_string(arg + 2, &tmp, ctx->offset + 2); in parse_probe_arg()
1158 code->op = FETCH_OP_DATA; in parse_probe_arg()
1159 code->data = tmp; in parse_probe_arg()
1161 ret = str_to_immediate(arg + 1, &code->immediate); in parse_probe_arg()
1163 trace_probe_log_err(ctx->offset + 1, BAD_IMM); in parse_probe_arg()
1165 code->op = FETCH_OP_IMM; in parse_probe_arg()
1170 if (!tparg_is_function_entry(ctx->flags) && in parse_probe_arg()
1171 !tparg_is_function_return(ctx->flags)) { in parse_probe_arg()
1172 trace_probe_log_err(ctx->offset, NOSUP_BTFARG); in parse_probe_arg()
1173 return -EINVAL; in parse_probe_arg()
1179 if (!ret && code->op == FETCH_OP_NOP) { in parse_probe_arg()
1181 trace_probe_log_err(ctx->offset, BAD_FETCH_ARG); in parse_probe_arg()
1182 ret = -EINVAL; in parse_probe_arg()
1204 return -EINVAL; in __parse_bitfield_probe_arg()
1210 return -EINVAL; in __parse_bitfield_probe_arg()
1212 if (code->op != FETCH_OP_NOP) in __parse_bitfield_probe_arg()
1213 return -EINVAL; in __parse_bitfield_probe_arg()
1216 code->op = FETCH_OP_MOD_BF; in __parse_bitfield_probe_arg()
1217 code->lshift = BYTES_TO_BITS(t->size) - (bw + bo); in __parse_bitfield_probe_arg()
1218 code->rshift = BYTES_TO_BITS(t->size) - bw; in __parse_bitfield_probe_arg()
1219 code->basesize = t->size; in __parse_bitfield_probe_arg()
1221 return (BYTES_TO_BITS(t->size) < (bw + bo)) ? -EINVAL : 0; in __parse_bitfield_probe_arg()
1236 return -ENOMEM; in traceprobe_parse_probe_arg_body()
1238 ret = -EINVAL; in traceprobe_parse_probe_arg_body()
1241 trace_probe_log_err(ctx->offset, ARG_TOO_LONG); in traceprobe_parse_probe_arg_body()
1244 trace_probe_log_err(ctx->offset, NO_ARG_BODY); in traceprobe_parse_probe_arg_body()
1248 ret = -ENOMEM; in traceprobe_parse_probe_arg_body()
1249 parg->comm = kstrdup(arg, GFP_KERNEL); in traceprobe_parse_probe_arg_body()
1250 if (!parg->comm) in traceprobe_parse_probe_arg_body()
1253 ret = -EINVAL; in traceprobe_parse_probe_arg_body()
1262 int offs = t2 + strlen(t2) - arg; in traceprobe_parse_probe_arg_body()
1264 trace_probe_log_err(ctx->offset + offs, in traceprobe_parse_probe_arg_body()
1268 trace_probe_log_err(ctx->offset + t3 + 1 - arg, in traceprobe_parse_probe_arg_body()
1273 if (kstrtouint(t2, 0, &parg->count) || !parg->count) { in traceprobe_parse_probe_arg_body()
1274 trace_probe_log_err(ctx->offset + t2 - arg, in traceprobe_parse_probe_arg_body()
1278 if (parg->count > MAX_ARRAY_LEN) { in traceprobe_parse_probe_arg_body()
1279 trace_probe_log_err(ctx->offset + t2 - arg, in traceprobe_parse_probe_arg_body()
1290 if (!(ctx->flags & TPARG_FL_TEVENT) && in traceprobe_parse_probe_arg_body()
1294 if (parg->count || (t && strcmp(t, "string"))) { in traceprobe_parse_probe_arg_body()
1295 trace_probe_log_err(ctx->offset + (t ? (t - arg) : 0), in traceprobe_parse_probe_arg_body()
1299 parg->type = find_fetch_type("string", ctx->flags); in traceprobe_parse_probe_arg_body()
1301 parg->type = find_fetch_type(t, ctx->flags); in traceprobe_parse_probe_arg_body()
1302 if (!parg->type) { in traceprobe_parse_probe_arg_body()
1303 trace_probe_log_err(ctx->offset + (t ? (t - arg) : 0), BAD_TYPE); in traceprobe_parse_probe_arg_body()
1310 code[FETCH_INSN_MAX - 1].op = FETCH_OP_END; in traceprobe_parse_probe_arg_body()
1312 ctx->last_type = NULL; in traceprobe_parse_probe_arg_body()
1313 ret = parse_probe_arg(arg, parg->type, &code, &code[FETCH_INSN_MAX - 1], in traceprobe_parse_probe_arg_body()
1320 ctx->last_type) { in traceprobe_parse_probe_arg_body()
1322 parg->type = find_fetch_type_from_btf_type(ctx); in traceprobe_parse_probe_arg_body()
1329 parg->offset = *size; in traceprobe_parse_probe_arg_body()
1330 *size += parg->type->size * (parg->count ?: 1); in traceprobe_parse_probe_arg_body()
1332 if (parg->count) { in traceprobe_parse_probe_arg_body()
1333 len = strlen(parg->type->fmttype) + 6; in traceprobe_parse_probe_arg_body()
1334 parg->fmt = kmalloc(len, GFP_KERNEL); in traceprobe_parse_probe_arg_body()
1335 if (!parg->fmt) { in traceprobe_parse_probe_arg_body()
1336 ret = -ENOMEM; in traceprobe_parse_probe_arg_body()
1339 snprintf(parg->fmt, len, "%s[%d]", parg->type->fmttype, in traceprobe_parse_probe_arg_body()
1340 parg->count); in traceprobe_parse_probe_arg_body()
1343 ret = -EINVAL; in traceprobe_parse_probe_arg_body()
1345 if (parg->type->is_string) { in traceprobe_parse_probe_arg_body()
1346 if (!strcmp(parg->type->name, "symstr")) { in traceprobe_parse_probe_arg_body()
1347 if (code->op != FETCH_OP_REG && code->op != FETCH_OP_STACK && in traceprobe_parse_probe_arg_body()
1348 code->op != FETCH_OP_RETVAL && code->op != FETCH_OP_ARG && in traceprobe_parse_probe_arg_body()
1349 code->op != FETCH_OP_DEREF && code->op != FETCH_OP_TP_ARG) { in traceprobe_parse_probe_arg_body()
1350 trace_probe_log_err(ctx->offset + (t ? (t - arg) : 0), in traceprobe_parse_probe_arg_body()
1355 if (code->op != FETCH_OP_DEREF && code->op != FETCH_OP_UDEREF && in traceprobe_parse_probe_arg_body()
1356 code->op != FETCH_OP_IMM && code->op != FETCH_OP_COMM && in traceprobe_parse_probe_arg_body()
1357 code->op != FETCH_OP_DATA && code->op != FETCH_OP_TP_ARG) { in traceprobe_parse_probe_arg_body()
1358 trace_probe_log_err(ctx->offset + (t ? (t - arg) : 0), in traceprobe_parse_probe_arg_body()
1363 if (!strcmp(parg->type->name, "symstr") || in traceprobe_parse_probe_arg_body()
1364 (code->op == FETCH_OP_IMM || code->op == FETCH_OP_COMM || in traceprobe_parse_probe_arg_body()
1365 code->op == FETCH_OP_DATA) || code->op == FETCH_OP_TP_ARG || in traceprobe_parse_probe_arg_body()
1366 parg->count) { in traceprobe_parse_probe_arg_body()
1369 * must be kept, and if parg->count != 0, this is an in traceprobe_parse_probe_arg_body()
1376 if (code->op != FETCH_OP_NOP) { in traceprobe_parse_probe_arg_body()
1377 trace_probe_log_err(ctx->offset, TOO_MANY_OPS); in traceprobe_parse_probe_arg_body()
1382 if (!strcmp(parg->type->name, "ustring") || in traceprobe_parse_probe_arg_body()
1383 code->op == FETCH_OP_UDEREF) in traceprobe_parse_probe_arg_body()
1384 code->op = FETCH_OP_ST_USTRING; in traceprobe_parse_probe_arg_body()
1385 else if (!strcmp(parg->type->name, "symstr")) in traceprobe_parse_probe_arg_body()
1386 code->op = FETCH_OP_ST_SYMSTR; in traceprobe_parse_probe_arg_body()
1388 code->op = FETCH_OP_ST_STRING; in traceprobe_parse_probe_arg_body()
1389 code->size = parg->type->size; in traceprobe_parse_probe_arg_body()
1390 parg->dynamic = true; in traceprobe_parse_probe_arg_body()
1391 } else if (code->op == FETCH_OP_DEREF) { in traceprobe_parse_probe_arg_body()
1392 code->op = FETCH_OP_ST_MEM; in traceprobe_parse_probe_arg_body()
1393 code->size = parg->type->size; in traceprobe_parse_probe_arg_body()
1394 } else if (code->op == FETCH_OP_UDEREF) { in traceprobe_parse_probe_arg_body()
1395 code->op = FETCH_OP_ST_UMEM; in traceprobe_parse_probe_arg_body()
1396 code->size = parg->type->size; in traceprobe_parse_probe_arg_body()
1399 if (code->op != FETCH_OP_NOP) { in traceprobe_parse_probe_arg_body()
1400 trace_probe_log_err(ctx->offset, TOO_MANY_OPS); in traceprobe_parse_probe_arg_body()
1403 code->op = FETCH_OP_ST_RAW; in traceprobe_parse_probe_arg_body()
1404 code->size = parg->type->size; in traceprobe_parse_probe_arg_body()
1409 ret = __parse_bitfield_probe_arg(t, parg->type, &code); in traceprobe_parse_probe_arg_body()
1411 trace_probe_log_err(ctx->offset + t - arg, BAD_BITFIELD); in traceprobe_parse_probe_arg_body()
1415 ctx->last_type) { in traceprobe_parse_probe_arg_body()
1420 ret = -EINVAL; in traceprobe_parse_probe_arg_body()
1422 if (parg->count) { in traceprobe_parse_probe_arg_body()
1423 if (scode->op != FETCH_OP_ST_MEM && in traceprobe_parse_probe_arg_body()
1424 scode->op != FETCH_OP_ST_STRING && in traceprobe_parse_probe_arg_body()
1425 scode->op != FETCH_OP_ST_USTRING) { in traceprobe_parse_probe_arg_body()
1426 trace_probe_log_err(ctx->offset + (t ? (t - arg) : 0), in traceprobe_parse_probe_arg_body()
1431 if (code->op != FETCH_OP_NOP) { in traceprobe_parse_probe_arg_body()
1432 trace_probe_log_err(ctx->offset, TOO_MANY_OPS); in traceprobe_parse_probe_arg_body()
1435 code->op = FETCH_OP_LP_ARRAY; in traceprobe_parse_probe_arg_body()
1436 code->param = parg->count; in traceprobe_parse_probe_arg_body()
1439 code->op = FETCH_OP_END; in traceprobe_parse_probe_arg_body()
1443 parg->code = kcalloc(code - tmp + 1, sizeof(*code), GFP_KERNEL); in traceprobe_parse_probe_arg_body()
1444 if (!parg->code) in traceprobe_parse_probe_arg_body()
1445 ret = -ENOMEM; in traceprobe_parse_probe_arg_body()
1447 memcpy(parg->code, tmp, sizeof(*code) * (code - tmp + 1)); in traceprobe_parse_probe_arg_body()
1452 if (code->op == FETCH_NOP_SYMBOL || in traceprobe_parse_probe_arg_body()
1453 code->op == FETCH_OP_DATA) in traceprobe_parse_probe_arg_body()
1454 kfree(code->data); in traceprobe_parse_probe_arg_body()
1494 name = kmemdup_nul(arg, end - arg, GFP_KERNEL); in generate_probe_arg_name()
1507 int traceprobe_parse_probe_arg(struct trace_probe *tp, int i, const char *arg, in traceprobe_parse_probe_arg() argument
1510 struct probe_arg *parg = &tp->args[i]; in traceprobe_parse_probe_arg()
1513 ctx->tp = tp; in traceprobe_parse_probe_arg()
1516 if (body - arg > MAX_ARG_NAME_LEN) { in traceprobe_parse_probe_arg()
1518 return -EINVAL; in traceprobe_parse_probe_arg()
1521 return -EINVAL; in traceprobe_parse_probe_arg()
1523 parg->name = kmemdup_nul(arg, body - arg, GFP_KERNEL); in traceprobe_parse_probe_arg()
1526 parg->name = generate_probe_arg_name(arg, i); in traceprobe_parse_probe_arg()
1529 if (!parg->name) in traceprobe_parse_probe_arg()
1530 return -ENOMEM; in traceprobe_parse_probe_arg()
1532 if (!is_good_name(parg->name)) { in traceprobe_parse_probe_arg()
1534 return -EINVAL; in traceprobe_parse_probe_arg()
1536 if (traceprobe_conflict_field_name(parg->name, tp->args, i)) { in traceprobe_parse_probe_arg()
1538 return -EINVAL; in traceprobe_parse_probe_arg()
1540 ctx->offset = body - arg; in traceprobe_parse_probe_arg()
1542 return traceprobe_parse_probe_arg_body(body, &tp->size, parg, ctx); in traceprobe_parse_probe_arg()
1547 struct fetch_insn *code = arg->code; in traceprobe_free_probe_arg()
1549 while (code && code->op != FETCH_OP_END) { in traceprobe_free_probe_arg()
1550 if (code->op == FETCH_NOP_SYMBOL || in traceprobe_free_probe_arg()
1551 code->op == FETCH_OP_DATA) in traceprobe_free_probe_arg()
1552 kfree(code->data); in traceprobe_free_probe_arg()
1555 kfree(arg->code); in traceprobe_free_probe_arg()
1556 kfree(arg->name); in traceprobe_free_probe_arg()
1557 kfree(arg->comm); in traceprobe_free_probe_arg()
1558 kfree(arg->fmt); in traceprobe_free_probe_arg()
1570 if (!tparg_is_function_entry(ctx->flags) && in argv_has_var_arg()
1571 !tparg_is_function_return(ctx->flags)) { in argv_has_var_arg()
1573 return -EINVAL; in argv_has_var_arg()
1583 return -EINVAL; in argv_has_var_arg()
1588 return -EINVAL; in argv_has_var_arg()
1604 if (idx >= ctx->nr_params) { in sprint_nth_btf_arg()
1606 return -ENOENT; in sprint_nth_btf_arg()
1608 name = btf_name_by_offset(ctx->btf, ctx->params[idx].name_off); in sprint_nth_btf_arg()
1611 return -ENOENT; in sprint_nth_btf_arg()
1616 return -E2BIG; in sprint_nth_btf_arg()
1627 int i, j, n, used, ret, args_idx = -1; in traceprobe_expand_meta_args()
1640 if (ret < 0 || ctx->nr_params == 0) { in traceprobe_expand_meta_args()
1641 if (args_idx != -1) { in traceprobe_expand_meta_args()
1651 *new_argc = argc + ctx->nr_params - 1; in traceprobe_expand_meta_args()
1657 return ERR_PTR(-ENOMEM); in traceprobe_expand_meta_args()
1663 for (n = 0; n < ctx->nr_params; n++) { in traceprobe_expand_meta_args()
1665 bufsize - used, ctx); in traceprobe_expand_meta_args()
1681 ret = -ENOENT; in traceprobe_expand_meta_args()
1685 ret = sprint_nth_btf_arg(n - 1, type, buf + used, in traceprobe_expand_meta_args()
1686 bufsize - used, ctx); in traceprobe_expand_meta_args()
1709 struct fetch_insn *code = arg->code; in traceprobe_update_arg()
1715 while (code && code->op != FETCH_OP_END) { in traceprobe_update_arg()
1716 if (code->op == FETCH_NOP_SYMBOL) { in traceprobe_update_arg()
1718 return -EINVAL; in traceprobe_update_arg()
1720 tmp = strpbrk(code->data, "+-"); in traceprobe_update_arg()
1723 ret = traceprobe_split_symbol_offset(code->data, in traceprobe_update_arg()
1729 (unsigned long)kallsyms_lookup_name(code->data); in traceprobe_update_arg()
1733 return -ENOENT; in traceprobe_update_arg()
1742 #define LEN_OR_ZERO (len ? len - pos : 0)
1743 static int __set_print_fmt(struct trace_probe *tp, char *buf, int len, in __set_print_fmt() argument
1754 arg = ", REC->" FIELD_STRING_IP; in __set_print_fmt()
1757 fmt = "(%lx <- %lx)"; in __set_print_fmt()
1758 arg = ", REC->" FIELD_STRING_FUNC ", REC->" FIELD_STRING_RETIP; in __set_print_fmt()
1771 for (i = 0; i < tp->nr_args; i++) { in __set_print_fmt()
1772 parg = tp->args + i; in __set_print_fmt()
1773 pos += snprintf(buf + pos, LEN_OR_ZERO, " %s=", parg->name); in __set_print_fmt()
1774 if (parg->count) { in __set_print_fmt()
1776 parg->type->fmt); in __set_print_fmt()
1777 for (j = 1; j < parg->count; j++) in __set_print_fmt()
1779 parg->type->fmt); in __set_print_fmt()
1783 parg->type->fmt); in __set_print_fmt()
1788 for (i = 0; i < tp->nr_args; i++) { in __set_print_fmt()
1789 parg = tp->args + i; in __set_print_fmt()
1790 if (parg->count) { in __set_print_fmt()
1791 if (parg->type->is_string) in __set_print_fmt()
1794 fmt = ", REC->%s[%d]"; in __set_print_fmt()
1795 for (j = 0; j < parg->count; j++) in __set_print_fmt()
1797 fmt, parg->name, j); in __set_print_fmt()
1799 if (parg->type->is_string) in __set_print_fmt()
1802 fmt = ", REC->%s"; in __set_print_fmt()
1804 fmt, parg->name); in __set_print_fmt()
1813 int traceprobe_set_print_fmt(struct trace_probe *tp, enum probe_print_type ptype) in traceprobe_set_print_fmt() argument
1815 struct trace_event_call *call = trace_probe_event_call(tp); in traceprobe_set_print_fmt()
1820 len = __set_print_fmt(tp, NULL, 0, ptype); in traceprobe_set_print_fmt()
1823 return -ENOMEM; in traceprobe_set_print_fmt()
1826 __set_print_fmt(tp, print_fmt, len + 1, ptype); in traceprobe_set_print_fmt()
1827 call->print_fmt = print_fmt; in traceprobe_set_print_fmt()
1833 size_t offset, struct trace_probe *tp) in traceprobe_define_arg_fields() argument
1838 for (i = 0; i < tp->nr_args; i++) { in traceprobe_define_arg_fields()
1839 struct probe_arg *parg = &tp->args[i]; in traceprobe_define_arg_fields()
1840 const char *fmt = parg->type->fmttype; in traceprobe_define_arg_fields()
1841 int size = parg->type->size; in traceprobe_define_arg_fields()
1843 if (parg->fmt) in traceprobe_define_arg_fields()
1844 fmt = parg->fmt; in traceprobe_define_arg_fields()
1845 if (parg->count) in traceprobe_define_arg_fields()
1846 size *= parg->count; in traceprobe_define_arg_fields()
1847 ret = trace_define_field(event_call, fmt, parg->name, in traceprobe_define_arg_fields()
1848 offset + parg->offset, size, in traceprobe_define_arg_fields()
1849 parg->type->is_signed, in traceprobe_define_arg_fields()
1859 kfree(tpe->class.system); in trace_probe_event_free()
1860 kfree(tpe->call.name); in trace_probe_event_free()
1861 kfree(tpe->call.print_fmt); in trace_probe_event_free()
1865 int trace_probe_append(struct trace_probe *tp, struct trace_probe *to) in trace_probe_append() argument
1867 if (trace_probe_has_sibling(tp)) in trace_probe_append()
1868 return -EBUSY; in trace_probe_append()
1870 list_del_init(&tp->list); in trace_probe_append()
1871 trace_probe_event_free(tp->event); in trace_probe_append()
1873 tp->event = to->event; in trace_probe_append()
1874 list_add_tail(&tp->list, trace_probe_probe_list(to)); in trace_probe_append()
1879 void trace_probe_unlink(struct trace_probe *tp) in trace_probe_unlink() argument
1881 list_del_init(&tp->list); in trace_probe_unlink()
1882 if (list_empty(trace_probe_probe_list(tp))) in trace_probe_unlink()
1883 trace_probe_event_free(tp->event); in trace_probe_unlink()
1884 tp->event = NULL; in trace_probe_unlink()
1887 void trace_probe_cleanup(struct trace_probe *tp) in trace_probe_cleanup() argument
1891 for (i = 0; i < tp->nr_args; i++) in trace_probe_cleanup()
1892 traceprobe_free_probe_arg(&tp->args[i]); in trace_probe_cleanup()
1894 if (tp->entry_arg) { in trace_probe_cleanup()
1895 kfree(tp->entry_arg->code); in trace_probe_cleanup()
1896 kfree(tp->entry_arg); in trace_probe_cleanup()
1897 tp->entry_arg = NULL; in trace_probe_cleanup()
1900 if (tp->event) in trace_probe_cleanup()
1901 trace_probe_unlink(tp); in trace_probe_cleanup()
1904 int trace_probe_init(struct trace_probe *tp, const char *event, in trace_probe_init() argument
1912 return -EINVAL; in trace_probe_init()
1917 tp->event = kzalloc(size, GFP_KERNEL); in trace_probe_init()
1918 if (!tp->event) in trace_probe_init()
1919 return -ENOMEM; in trace_probe_init()
1921 INIT_LIST_HEAD(&tp->event->files); in trace_probe_init()
1922 INIT_LIST_HEAD(&tp->event->class.fields); in trace_probe_init()
1923 INIT_LIST_HEAD(&tp->event->probes); in trace_probe_init()
1924 INIT_LIST_HEAD(&tp->list); in trace_probe_init()
1925 list_add(&tp->list, &tp->event->probes); in trace_probe_init()
1927 call = trace_probe_event_call(tp); in trace_probe_init()
1928 call->class = &tp->event->class; in trace_probe_init()
1929 call->name = kstrdup(event, GFP_KERNEL); in trace_probe_init()
1930 if (!call->name) { in trace_probe_init()
1931 ret = -ENOMEM; in trace_probe_init()
1935 tp->event->class.system = kstrdup(group, GFP_KERNEL); in trace_probe_init()
1936 if (!tp->event->class.system) { in trace_probe_init()
1937 ret = -ENOMEM; in trace_probe_init()
1941 tp->nr_args = nargs; in trace_probe_init()
1944 memset(tp->args, 0, sizeof(tp->args[0]) * nargs); in trace_probe_init()
1949 trace_probe_cleanup(tp); in trace_probe_init()
1960 if (!tp_event->class->system || in find_trace_event_call()
1961 strcmp(system, tp_event->class->system)) in find_trace_event_call()
1972 int trace_probe_register_event_call(struct trace_probe *tp) in trace_probe_register_event_call() argument
1974 struct trace_event_call *call = trace_probe_event_call(tp); in trace_probe_register_event_call()
1979 if (find_trace_event_call(trace_probe_group_name(tp), in trace_probe_register_event_call()
1980 trace_probe_name(tp))) in trace_probe_register_event_call()
1981 return -EEXIST; in trace_probe_register_event_call()
1983 ret = register_trace_event(&call->event); in trace_probe_register_event_call()
1985 return -ENODEV; in trace_probe_register_event_call()
1989 unregister_trace_event(&call->event); in trace_probe_register_event_call()
1994 int trace_probe_add_file(struct trace_probe *tp, struct trace_event_file *file) in trace_probe_add_file() argument
1996 struct event_file_link *link; in trace_probe_add_file() local
1998 link = kmalloc(sizeof(*link), GFP_KERNEL); in trace_probe_add_file()
1999 if (!link) in trace_probe_add_file()
2000 return -ENOMEM; in trace_probe_add_file()
2002 link->file = file; in trace_probe_add_file()
2003 INIT_LIST_HEAD(&link->list); in trace_probe_add_file()
2004 list_add_tail_rcu(&link->list, &tp->event->files); in trace_probe_add_file()
2005 trace_probe_set_flag(tp, TP_FLAG_TRACE); in trace_probe_add_file()
2009 struct event_file_link *trace_probe_get_file_link(struct trace_probe *tp, in trace_probe_get_file_link() argument
2012 struct event_file_link *link; in trace_probe_get_file_link() local
2014 trace_probe_for_each_link(link, tp) { in trace_probe_get_file_link()
2015 if (link->file == file) in trace_probe_get_file_link()
2016 return link; in trace_probe_get_file_link()
2022 int trace_probe_remove_file(struct trace_probe *tp, in trace_probe_remove_file() argument
2025 struct event_file_link *link; in trace_probe_remove_file() local
2027 link = trace_probe_get_file_link(tp, file); in trace_probe_remove_file()
2028 if (!link) in trace_probe_remove_file()
2029 return -ENOENT; in trace_probe_remove_file()
2031 list_del_rcu(&link->list); in trace_probe_remove_file()
2032 kvfree_rcu_mightsleep(link); in trace_probe_remove_file()
2034 if (list_empty(&tp->event->files)) in trace_probe_remove_file()
2035 trace_probe_clear_flag(tp, TP_FLAG_TRACE); in trace_probe_remove_file()
2049 if (a->nr_args < b->nr_args) in trace_probe_compare_arg_type()
2050 return a->nr_args + 1; in trace_probe_compare_arg_type()
2051 if (a->nr_args > b->nr_args) in trace_probe_compare_arg_type()
2052 return b->nr_args + 1; in trace_probe_compare_arg_type()
2054 for (i = 0; i < a->nr_args; i++) { in trace_probe_compare_arg_type()
2055 if ((b->nr_args <= i) || in trace_probe_compare_arg_type()
2056 ((a->args[i].type != b->args[i].type) || in trace_probe_compare_arg_type()
2057 (a->args[i].count != b->args[i].count) || in trace_probe_compare_arg_type()
2058 strcmp(a->args[i].name, b->args[i].name))) in trace_probe_compare_arg_type()
2065 bool trace_probe_match_command_args(struct trace_probe *tp, in trace_probe_match_command_args() argument
2071 if (tp->nr_args < argc) in trace_probe_match_command_args()
2076 tp->args[i].name, tp->args[i].comm); in trace_probe_match_command_args()
2090 return -ENOMEM; in trace_probe_create()
2109 trace_seq_printf(s, " %s=", a->name); in trace_probe_print_args()
2110 if (likely(!a->count)) { in trace_probe_print_args()
2111 if (!a->type->print(s, data + a->offset, field)) in trace_probe_print_args()
2112 return -ENOMEM; in trace_probe_print_args()
2116 p = data + a->offset; in trace_probe_print_args()
2117 for (j = 0; j < a->count; j++) { in trace_probe_print_args()
2118 if (!a->type->print(s, p, field)) in trace_probe_print_args()
2119 return -ENOMEM; in trace_probe_print_args()
2120 trace_seq_putc(s, j == a->count - 1 ? '}' : ','); in trace_probe_print_args()
2121 p += a->type->size; in trace_probe_print_args()