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
212 *(p - 1) = '\0'; in __trace_probe_log_err()
227 return -EINVAL; in traceprobe_split_symbol_offset()
229 tmp = strpbrk(symbol, "+-"); in traceprobe_split_symbol_offset()
255 return -EINVAL; in traceprobe_parse_event_name()
257 if (slash - event + 1 > MAX_EVENT_NAME_LEN) { in traceprobe_parse_event_name()
259 return -EINVAL; in traceprobe_parse_event_name()
261 strscpy(buf, event, slash - event + 1); in traceprobe_parse_event_name()
264 return -EINVAL; in traceprobe_parse_event_name()
268 offset += slash - event + 1; in traceprobe_parse_event_name()
278 return -EINVAL; in traceprobe_parse_event_name()
281 return -EINVAL; in traceprobe_parse_event_name()
285 return -EINVAL; in traceprobe_parse_event_name()
296 head = trace_get_fields(ctx->event); in parse_trace_event_arg()
297 list_for_each_entry(field, head, link) { in parse_trace_event_arg()
298 if (!strcmp(arg, field->name)) { in parse_trace_event_arg()
299 code->op = FETCH_OP_TP_ARG; in parse_trace_event_arg()
300 code->data = field; in parse_trace_event_arg()
304 return -ENOENT; in parse_trace_event_arg()
320 real_type = btf_type_skip_modifiers(btf, type->type, &tid); in btf_type_is_char_ptr()
324 if (BTF_INFO_KIND(real_type->info) != BTF_KIND_INT) in btf_type_is_char_ptr()
339 if (BTF_INFO_KIND(type->info) != BTF_KIND_ARRAY) in btf_type_is_char_array()
344 real_type = btf_type_skip_modifiers(btf, array->type, &tid); in btf_type_is_char_array()
355 struct btf *btf = ctx->btf; in check_prepare_btf_string_fetch()
357 if (!btf || !ctx->last_type) in check_prepare_btf_string_fetch()
361 if (btf_type_is_char_array(btf, ctx->last_type)) in check_prepare_btf_string_fetch()
365 if (btf_type_is_char_ptr(btf, ctx->last_type)) { in check_prepare_btf_string_fetch()
368 if (code->op == FETCH_OP_END) { in check_prepare_btf_string_fetch()
369 trace_probe_log_err(ctx->offset, TOO_MANY_OPS); in check_prepare_btf_string_fetch()
370 return -E2BIG; in check_prepare_btf_string_fetch()
373 code->op = FETCH_OP_UDEREF; in check_prepare_btf_string_fetch()
375 code->op = FETCH_OP_DEREF; in check_prepare_btf_string_fetch()
376 code->offset = 0; in check_prepare_btf_string_fetch()
381 trace_probe_log_err(ctx->offset, BAD_TYPE4STR); in check_prepare_btf_string_fetch()
382 return -EINVAL; in check_prepare_btf_string_fetch()
392 switch (BTF_INFO_KIND(type->info)) { in fetch_type_from_btf_type()
429 ctx->last_bitsize = BTF_INT_BITS(intdata); in fetch_type_from_btf_type()
430 ctx->last_bitoffs += BTF_INT_OFFSET(intdata); in fetch_type_from_btf_type()
446 if (ctx->btf) in query_btf_context()
449 if (!ctx->funcname) in query_btf_context()
450 return -EINVAL; in query_btf_context()
452 type = btf_find_func_proto(ctx->funcname, &btf); in query_btf_context()
454 return -ENOENT; in query_btf_context()
456 ctx->btf = btf; in query_btf_context()
457 ctx->proto = type; in query_btf_context()
459 /* ctx->params is optional, since func(void) will not have params. */ in query_btf_context()
464 if (ctx->flags & TPARG_FL_TPOINT) { in query_btf_context()
465 nr--; in query_btf_context()
471 ctx->nr_params = nr; in query_btf_context()
472 ctx->params = param; in query_btf_context()
474 ctx->nr_params = 0; in query_btf_context()
475 ctx->params = NULL; in query_btf_context()
483 if (ctx->btf) { in clear_btf_context()
484 btf_put(ctx->btf); in clear_btf_context()
485 ctx->btf = NULL; in clear_btf_context()
486 ctx->proto = NULL; in clear_btf_context()
487 ctx->params = NULL; in clear_btf_context()
488 ctx->nr_params = 0; in clear_btf_context()
492 /* Return 1 if the field separater is arrow operator ('->') */
499 field = strpbrk(varname, ".-"); in split_next_field()
501 if (field[0] == '-' && field[1] == '>') { in split_next_field()
509 trace_probe_log_err(ctx->offset + field - varname, BAD_HYPHEN); in split_next_field()
510 return -EINVAL; in split_next_field()
534 /* Outer loop for solving arrow operator ('->') */ in parse_btf_field()
535 if (BTF_INFO_KIND(type->info) != BTF_KIND_PTR) { in parse_btf_field()
536 trace_probe_log_err(ctx->offset, NO_PTR_STRCT); in parse_btf_field()
537 return -EINVAL; in parse_btf_field()
540 type = btf_type_skip_modifiers(ctx->btf, type->type, &tid); in parse_btf_field()
542 trace_probe_log_err(ctx->offset, BAD_BTF_TID); in parse_btf_field()
543 return -EINVAL; in parse_btf_field()
555 field = btf_find_struct_member(ctx->btf, type, fieldname, in parse_btf_field()
558 trace_probe_log_err(ctx->offset, BAD_BTF_TID); in parse_btf_field()
562 trace_probe_log_err(ctx->offset, NO_BTF_FIELD); in parse_btf_field()
563 return -ENOENT; in parse_btf_field()
568 /* Accumulate the bit-offsets of the dot-connected fields */ in parse_btf_field()
570 bitoffs += BTF_MEMBER_BIT_OFFSET(field->offset); in parse_btf_field()
571 ctx->last_bitsize = BTF_MEMBER_BITFIELD_SIZE(field->offset); in parse_btf_field()
573 bitoffs += field->offset; in parse_btf_field()
574 ctx->last_bitsize = 0; in parse_btf_field()
577 type = btf_type_skip_modifiers(ctx->btf, field->type, &tid); in parse_btf_field()
579 trace_probe_log_err(ctx->offset, BAD_BTF_TID); in parse_btf_field()
580 return -EINVAL; in parse_btf_field()
583 ctx->offset += next - fieldname; in parse_btf_field()
588 trace_probe_log_err(ctx->offset, TOO_MANY_OPS); in parse_btf_field()
589 return -EINVAL; in parse_btf_field()
591 code->op = FETCH_OP_DEREF; /* TODO: user deref support */ in parse_btf_field()
592 code->offset = bitoffs / 8; in parse_btf_field()
595 ctx->last_bitoffs = bitoffs % 8; in parse_btf_field()
596 ctx->last_type = type; in parse_btf_field()
602 static int __store_entry_arg(struct trace_probe *tp, int argnum);
615 if (WARN_ON_ONCE(!ctx->funcname)) in parse_btf_arg()
616 return -EINVAL; in parse_btf_arg()
622 /* dot-connected field on an argument is not supported. */ in parse_btf_arg()
623 trace_probe_log_err(ctx->offset + field - varname, in parse_btf_arg()
625 return -EOPNOTSUPP; in parse_btf_arg()
628 if (ctx->flags & TPARG_FL_RETURN && !strcmp(varname, "$retval")) { in parse_btf_arg()
629 code->op = FETCH_OP_RETVAL; in parse_btf_arg()
632 if (ctx->proto->type == 0) { in parse_btf_arg()
633 trace_probe_log_err(ctx->offset, NO_RETVAL); in parse_btf_arg()
634 return -ENOENT; in parse_btf_arg()
636 tid = ctx->proto->type; in parse_btf_arg()
640 trace_probe_log_err(ctx->offset + field - varname, in parse_btf_arg()
642 return -ENOENT; in parse_btf_arg()
647 if (!ctx->btf) { in parse_btf_arg()
649 if (ret < 0 || ctx->nr_params == 0) { in parse_btf_arg()
650 trace_probe_log_err(ctx->offset, NO_BTF_ENTRY); in parse_btf_arg()
654 params = ctx->params; in parse_btf_arg()
656 for (i = 0; i < ctx->nr_params; i++) { in parse_btf_arg()
657 const char *name = btf_name_by_offset(ctx->btf, params[i].name_off); in parse_btf_arg()
660 if (tparg_is_function_entry(ctx->flags)) { in parse_btf_arg()
661 code->op = FETCH_OP_ARG; in parse_btf_arg()
662 if (ctx->flags & TPARG_FL_TPOINT) in parse_btf_arg()
663 code->param = i + 1; in parse_btf_arg()
665 code->param = i; in parse_btf_arg()
666 } else if (tparg_is_function_return(ctx->flags)) { in parse_btf_arg()
667 code->op = FETCH_OP_EDATA; in parse_btf_arg()
668 ret = __store_entry_arg(ctx->tp, i); in parse_btf_arg()
673 code->offset = ret; in parse_btf_arg()
679 trace_probe_log_err(ctx->offset, NO_BTFARG); in parse_btf_arg()
680 return -ENOENT; in parse_btf_arg()
683 type = btf_type_skip_modifiers(ctx->btf, tid, &tid); in parse_btf_arg()
685 trace_probe_log_err(ctx->offset, BAD_BTF_TID); in parse_btf_arg()
686 return -EINVAL; in parse_btf_arg()
689 ctx->last_type = type; in parse_btf_arg()
690 ctx->last_bitoffs = 0; in parse_btf_arg()
691 ctx->last_bitsize = 0; in parse_btf_arg()
693 ctx->offset += field - varname; in parse_btf_arg()
702 struct btf *btf = ctx->btf; in find_fetch_type_from_btf_type()
705 if (btf && ctx->last_type) in find_fetch_type_from_btf_type()
706 typestr = fetch_type_from_btf_type(btf, ctx->last_type, ctx); in find_fetch_type_from_btf_type()
708 return find_fetch_type(typestr, ctx->flags); in find_fetch_type_from_btf_type()
716 if ((ctx->last_bitsize % 8 == 0) && ctx->last_bitoffs == 0) in parse_btf_bitfield()
720 if (code->op != FETCH_OP_NOP) { in parse_btf_bitfield()
721 trace_probe_log_err(ctx->offset, TOO_MANY_OPS); in parse_btf_bitfield()
722 return -EINVAL; in parse_btf_bitfield()
726 code->op = FETCH_OP_MOD_BF; in parse_btf_bitfield()
727 code->lshift = 64 - (ctx->last_bitsize + ctx->last_bitoffs); in parse_btf_bitfield()
728 code->rshift = 64 - ctx->last_bitsize; in parse_btf_bitfield()
729 code->basesize = 64 / 8; in parse_btf_bitfield()
736 ctx->btf = NULL; in clear_btf_context()
741 return -EOPNOTSUPP; in query_btf_context()
748 trace_probe_log_err(ctx->offset, NOSUP_BTFARG); in parse_btf_arg()
749 return -EOPNOTSUPP; in parse_btf_arg()
755 trace_probe_log_err(ctx->offset, NOSUP_BTFARG); in parse_btf_bitfield()
756 return -EOPNOTSUPP; in parse_btf_bitfield()
760 find_fetch_type(NULL, ctx->flags)
773 static int __store_entry_arg(struct trace_probe *tp, int argnum) in __store_entry_arg() argument
775 struct probe_entry_arg *earg = tp->entry_arg; in __store_entry_arg()
780 earg = kzalloc(sizeof(*tp->entry_arg), GFP_KERNEL); in __store_entry_arg()
782 return -ENOMEM; in __store_entry_arg()
783 earg->size = 2 * tp->nr_args + 1; in __store_entry_arg()
784 earg->code = kcalloc(earg->size, sizeof(struct fetch_insn), in __store_entry_arg()
786 if (!earg->code) { in __store_entry_arg()
788 return -ENOMEM; in __store_entry_arg()
791 for (i = 0; i < earg->size; i++) in __store_entry_arg()
792 earg->code[i].op = FETCH_OP_END; in __store_entry_arg()
793 tp->entry_arg = earg; in __store_entry_arg()
797 for (i = 0; i < earg->size - 1; i++) { in __store_entry_arg()
798 switch (earg->code[i].op) { in __store_entry_arg()
800 earg->code[i].op = FETCH_OP_ARG; in __store_entry_arg()
801 earg->code[i].param = argnum; in __store_entry_arg()
802 earg->code[i + 1].op = FETCH_OP_ST_EDATA; in __store_entry_arg()
803 earg->code[i + 1].offset = offset; in __store_entry_arg()
806 match = (earg->code[i].param == argnum); in __store_entry_arg()
809 offset = earg->code[i].offset; in __store_entry_arg()
818 return -ENOSPC; in __store_entry_arg()
821 int traceprobe_get_entry_data_size(struct trace_probe *tp) in traceprobe_get_entry_data_size() argument
823 struct probe_entry_arg *earg = tp->entry_arg; in traceprobe_get_entry_data_size()
829 for (i = 0; i < earg->size; i++) { in traceprobe_get_entry_data_size()
830 switch (earg->code[i].op) { in traceprobe_get_entry_data_size()
834 size = earg->code[i].offset + sizeof(unsigned long); in traceprobe_get_entry_data_size()
844 void store_trace_entry_data(void *edata, struct trace_probe *tp, struct pt_regs *regs) in store_trace_entry_data() argument
846 struct probe_entry_arg *earg = tp->entry_arg; in store_trace_entry_data()
853 for (i = 0; i < earg->size; i++) { in store_trace_entry_data()
854 struct fetch_insn *code = &earg->code[i]; in store_trace_entry_data()
856 switch (code->op) { in store_trace_entry_data()
858 val = regs_get_kernel_argument(regs, code->param); in store_trace_entry_data()
861 *(unsigned long *)((unsigned long)edata + code->offset) = val; in store_trace_entry_data()
877 /* Parse $vars. @orig_arg points '$', which syncs to @ctx->offset */ in NOKPROBE_SYMBOL()
890 if (ctx->flags & TPARG_FL_TEVENT) { in NOKPROBE_SYMBOL()
891 if (code->data) in NOKPROBE_SYMBOL()
892 return -EFAULT; in NOKPROBE_SYMBOL()
897 code->op = FETCH_OP_COMM; in NOKPROBE_SYMBOL()
901 ctx->offset = 0; in NOKPROBE_SYMBOL()
906 if (!(ctx->flags & TPARG_FL_RETURN)) { in NOKPROBE_SYMBOL()
910 if (!(ctx->flags & TPARG_FL_KERNEL) || in NOKPROBE_SYMBOL()
912 code->op = FETCH_OP_RETVAL; in NOKPROBE_SYMBOL()
922 code->op = FETCH_OP_STACKP; in NOKPROBE_SYMBOL()
931 if ((ctx->flags & TPARG_FL_KERNEL) && in NOKPROBE_SYMBOL()
936 code->op = FETCH_OP_STACK; in NOKPROBE_SYMBOL()
937 code->param = (unsigned int)param; in NOKPROBE_SYMBOL()
944 code->op = FETCH_OP_COMM; in NOKPROBE_SYMBOL()
959 param--; /* argN starts from 1, but internal arg[N] starts from 0 */ in NOKPROBE_SYMBOL()
961 if (tparg_is_function_entry(ctx->flags)) { in NOKPROBE_SYMBOL()
962 code->op = FETCH_OP_ARG; in NOKPROBE_SYMBOL()
963 code->param = (unsigned int)param; in NOKPROBE_SYMBOL()
968 if (ctx->flags & TPARG_FL_TPOINT) in NOKPROBE_SYMBOL()
969 code->param++; in NOKPROBE_SYMBOL()
970 } else if (tparg_is_function_return(ctx->flags)) { in NOKPROBE_SYMBOL()
972 ret = __store_entry_arg(ctx->tp, param); in NOKPROBE_SYMBOL()
976 code->op = FETCH_OP_EDATA; in NOKPROBE_SYMBOL()
977 code->offset = ret; in NOKPROBE_SYMBOL()
987 __trace_probe_log_err(ctx->offset, err); in NOKPROBE_SYMBOL()
988 return -EINVAL; in NOKPROBE_SYMBOL()
995 else if (str[0] == '-') in str_to_immediate()
999 return -EINVAL; in str_to_immediate()
1006 if (str[len - 1] != '"') { in __parse_imm_string()
1008 return -EINVAL; in __parse_imm_string()
1010 *pbuf = kstrndup(str, len - 1, GFP_KERNEL); in __parse_imm_string()
1012 return -ENOMEM; in __parse_imm_string()
1035 if (ctx->flags & (TPARG_FL_TEVENT | TPARG_FL_FPROBE)) { in parse_probe_arg()
1037 trace_probe_log_err(ctx->offset, BAD_VAR); in parse_probe_arg()
1042 code->op = FETCH_OP_REG; in parse_probe_arg()
1043 code->param = (unsigned int)ret; in parse_probe_arg()
1046 trace_probe_log_err(ctx->offset, BAD_REG_NAME); in parse_probe_arg()
1049 case '@': /* memory, file-offset or symbol */ in parse_probe_arg()
1053 trace_probe_log_err(ctx->offset, BAD_MEM_ADDR); in parse_probe_arg()
1057 code->op = FETCH_OP_IMM; in parse_probe_arg()
1058 code->immediate = param; in parse_probe_arg()
1061 if (ctx->flags & TPARG_FL_KERNEL) { in parse_probe_arg()
1062 trace_probe_log_err(ctx->offset, FILE_ON_KPROBE); in parse_probe_arg()
1063 return -EINVAL; in parse_probe_arg()
1067 trace_probe_log_err(ctx->offset, BAD_FILE_OFFS); in parse_probe_arg()
1071 code->op = FETCH_OP_FOFFS; in parse_probe_arg()
1072 code->immediate = (unsigned long)offset; // imm64? in parse_probe_arg()
1075 if (!(ctx->flags & TPARG_FL_KERNEL)) { in parse_probe_arg()
1076 trace_probe_log_err(ctx->offset, SYM_ON_UPROBE); in parse_probe_arg()
1077 return -EINVAL; in parse_probe_arg()
1080 code->op = FETCH_NOP_SYMBOL; in parse_probe_arg()
1081 code->data = kstrdup(arg + 1, GFP_KERNEL); in parse_probe_arg()
1082 if (!code->data) in parse_probe_arg()
1083 return -ENOMEM; in parse_probe_arg()
1085 trace_probe_log_err(ctx->offset, TOO_MANY_OPS); in parse_probe_arg()
1086 return -EINVAL; in parse_probe_arg()
1088 code->op = FETCH_OP_IMM; in parse_probe_arg()
1089 code->immediate = 0; in parse_probe_arg()
1093 trace_probe_log_err(ctx->offset, TOO_MANY_OPS); in parse_probe_arg()
1094 return -EINVAL; in parse_probe_arg()
1097 code->op = FETCH_OP_DEREF; in parse_probe_arg()
1098 code->offset = offset; in parse_probe_arg()
1102 case '-': in parse_probe_arg()
1112 trace_probe_log_err(ctx->offset, DEREF_NEED_BRACE); in parse_probe_arg()
1113 return -EINVAL; in parse_probe_arg()
1118 trace_probe_log_err(ctx->offset, BAD_DEREF_OFFS); in parse_probe_arg()
1121 ctx->offset += (tmp + 1 - arg) + (arg[0] != '-' ? 1 : 0); in parse_probe_arg()
1125 trace_probe_log_err(ctx->offset + strlen(arg), in parse_probe_arg()
1127 return -EINVAL; in parse_probe_arg()
1129 const struct fetch_type *t2 = find_fetch_type(NULL, ctx->flags); in parse_probe_arg()
1130 int cur_offs = ctx->offset; in parse_probe_arg()
1136 ctx->offset = cur_offs; in parse_probe_arg()
1137 if (code->op == FETCH_OP_COMM || in parse_probe_arg()
1138 code->op == FETCH_OP_DATA) { in parse_probe_arg()
1139 trace_probe_log_err(ctx->offset, COMM_CANT_DEREF); in parse_probe_arg()
1140 return -EINVAL; in parse_probe_arg()
1143 trace_probe_log_err(ctx->offset, TOO_MANY_OPS); in parse_probe_arg()
1144 return -EINVAL; in parse_probe_arg()
1148 code->op = deref; in parse_probe_arg()
1149 code->offset = offset; in parse_probe_arg()
1151 ctx->last_type = NULL; in parse_probe_arg()
1156 ret = __parse_imm_string(arg + 2, &tmp, ctx->offset + 2); in parse_probe_arg()
1159 code->op = FETCH_OP_DATA; in parse_probe_arg()
1160 code->data = tmp; in parse_probe_arg()
1162 ret = str_to_immediate(arg + 1, &code->immediate); in parse_probe_arg()
1164 trace_probe_log_err(ctx->offset + 1, BAD_IMM); in parse_probe_arg()
1166 code->op = FETCH_OP_IMM; in parse_probe_arg()
1171 if (!tparg_is_function_entry(ctx->flags) && in parse_probe_arg()
1172 !tparg_is_function_return(ctx->flags)) { in parse_probe_arg()
1173 trace_probe_log_err(ctx->offset, NOSUP_BTFARG); in parse_probe_arg()
1174 return -EINVAL; in parse_probe_arg()
1180 if (!ret && code->op == FETCH_OP_NOP) { in parse_probe_arg()
1182 trace_probe_log_err(ctx->offset, BAD_FETCH_ARG); in parse_probe_arg()
1183 ret = -EINVAL; in parse_probe_arg()
1203 return -EINVAL; in __parse_bitfield_probe_arg()
1209 return -EINVAL; in __parse_bitfield_probe_arg()
1211 if (code->op != FETCH_OP_NOP) in __parse_bitfield_probe_arg()
1212 return -EINVAL; in __parse_bitfield_probe_arg()
1215 code->op = FETCH_OP_MOD_BF; in __parse_bitfield_probe_arg()
1216 code->lshift = BYTES_TO_BITS(t->size) - (bw + bo); in __parse_bitfield_probe_arg()
1217 code->rshift = BYTES_TO_BITS(t->size) - bw; in __parse_bitfield_probe_arg()
1218 code->basesize = t->size; in __parse_bitfield_probe_arg()
1220 return (BYTES_TO_BITS(t->size) < (bw + bo)) ? -EINVAL : 0; in __parse_bitfield_probe_arg()
1238 offs = t2 + strlen(t2) - arg; in parse_probe_arg_type()
1240 trace_probe_log_err(ctx->offset + offs, in parse_probe_arg_type()
1242 return ERR_PTR(-EINVAL); in parse_probe_arg_type()
1244 trace_probe_log_err(ctx->offset + t3 + 1 - arg, in parse_probe_arg_type()
1246 return ERR_PTR(-EINVAL); in parse_probe_arg_type()
1249 if (kstrtouint(t2, 0, &parg->count) || !parg->count) { in parse_probe_arg_type()
1250 trace_probe_log_err(ctx->offset + t2 - arg, in parse_probe_arg_type()
1252 return ERR_PTR(-EINVAL); in parse_probe_arg_type()
1254 if (parg->count > MAX_ARRAY_LEN) { in parse_probe_arg_type()
1255 trace_probe_log_err(ctx->offset + t2 - arg, in parse_probe_arg_type()
1257 return ERR_PTR(-EINVAL); in parse_probe_arg_type()
1261 offs = t ? t - arg : 0; in parse_probe_arg_type()
1267 if (!(ctx->flags & TPARG_FL_TEVENT) && in parse_probe_arg_type()
1271 if (parg->count || (t && strcmp(t, "string"))) { in parse_probe_arg_type()
1272 trace_probe_log_err(ctx->offset + offs, NEED_STRING_TYPE); in parse_probe_arg_type()
1273 return ERR_PTR(-EINVAL); in parse_probe_arg_type()
1275 parg->type = find_fetch_type("string", ctx->flags); in parse_probe_arg_type()
1277 parg->type = find_fetch_type(t, ctx->flags); in parse_probe_arg_type()
1279 if (!parg->type) { in parse_probe_arg_type()
1280 trace_probe_log_err(ctx->offset + offs, BAD_TYPE); in parse_probe_arg_type()
1281 return ERR_PTR(-EINVAL); in parse_probe_arg_type()
1298 if (parg->type->is_string) { in finalize_fetch_insn()
1300 if (!strcmp(parg->type->name, "symstr")) { in finalize_fetch_insn()
1301 if (code->op != FETCH_OP_REG && code->op != FETCH_OP_STACK && in finalize_fetch_insn()
1302 code->op != FETCH_OP_RETVAL && code->op != FETCH_OP_ARG && in finalize_fetch_insn()
1303 code->op != FETCH_OP_DEREF && code->op != FETCH_OP_TP_ARG) { in finalize_fetch_insn()
1304 trace_probe_log_err(ctx->offset + type_offset, in finalize_fetch_insn()
1306 return -EINVAL; in finalize_fetch_insn()
1309 if (code->op != FETCH_OP_DEREF && code->op != FETCH_OP_UDEREF && in finalize_fetch_insn()
1310 code->op != FETCH_OP_IMM && code->op != FETCH_OP_COMM && in finalize_fetch_insn()
1311 code->op != FETCH_OP_DATA && code->op != FETCH_OP_TP_ARG) { in finalize_fetch_insn()
1312 trace_probe_log_err(ctx->offset + type_offset, in finalize_fetch_insn()
1314 return -EINVAL; in finalize_fetch_insn()
1318 if (!strcmp(parg->type->name, "symstr") || in finalize_fetch_insn()
1319 (code->op == FETCH_OP_IMM || code->op == FETCH_OP_COMM || in finalize_fetch_insn()
1320 code->op == FETCH_OP_DATA) || code->op == FETCH_OP_TP_ARG || in finalize_fetch_insn()
1321 parg->count) { in finalize_fetch_insn()
1324 * must be kept, and if parg->count != 0, this is an in finalize_fetch_insn()
1331 if (code->op != FETCH_OP_NOP) { in finalize_fetch_insn()
1332 trace_probe_log_err(ctx->offset, TOO_MANY_OPS); in finalize_fetch_insn()
1333 return -EINVAL; in finalize_fetch_insn()
1338 if (!strcmp(parg->type->name, "ustring") || in finalize_fetch_insn()
1339 code->op == FETCH_OP_UDEREF) in finalize_fetch_insn()
1340 code->op = FETCH_OP_ST_USTRING; in finalize_fetch_insn()
1341 else if (!strcmp(parg->type->name, "symstr")) in finalize_fetch_insn()
1342 code->op = FETCH_OP_ST_SYMSTR; in finalize_fetch_insn()
1344 code->op = FETCH_OP_ST_STRING; in finalize_fetch_insn()
1345 code->size = parg->type->size; in finalize_fetch_insn()
1346 parg->dynamic = true; in finalize_fetch_insn()
1347 } else if (code->op == FETCH_OP_DEREF) { in finalize_fetch_insn()
1348 code->op = FETCH_OP_ST_MEM; in finalize_fetch_insn()
1349 code->size = parg->type->size; in finalize_fetch_insn()
1350 } else if (code->op == FETCH_OP_UDEREF) { in finalize_fetch_insn()
1351 code->op = FETCH_OP_ST_UMEM; in finalize_fetch_insn()
1352 code->size = parg->type->size; in finalize_fetch_insn()
1355 if (code->op != FETCH_OP_NOP) { in finalize_fetch_insn()
1356 trace_probe_log_err(ctx->offset, TOO_MANY_OPS); in finalize_fetch_insn()
1357 return -E2BIG; in finalize_fetch_insn()
1359 code->op = FETCH_OP_ST_RAW; in finalize_fetch_insn()
1360 code->size = parg->type->size; in finalize_fetch_insn()
1369 ret = __parse_bitfield_probe_arg(type, parg->type, &code); in finalize_fetch_insn()
1371 trace_probe_log_err(ctx->offset + type_offset, BAD_BITFIELD); in finalize_fetch_insn()
1375 ctx->last_type) { in finalize_fetch_insn()
1383 if (parg->count) { in finalize_fetch_insn()
1384 if (scode->op != FETCH_OP_ST_MEM && in finalize_fetch_insn()
1385 scode->op != FETCH_OP_ST_STRING && in finalize_fetch_insn()
1386 scode->op != FETCH_OP_ST_USTRING) { in finalize_fetch_insn()
1387 trace_probe_log_err(ctx->offset + type_offset, BAD_STRING); in finalize_fetch_insn()
1388 return -EINVAL; in finalize_fetch_insn()
1391 if (code->op != FETCH_OP_NOP) { in finalize_fetch_insn()
1392 trace_probe_log_err(ctx->offset, TOO_MANY_OPS); in finalize_fetch_insn()
1393 return -E2BIG; in finalize_fetch_insn()
1395 code->op = FETCH_OP_LP_ARRAY; in finalize_fetch_insn()
1396 code->param = parg->count; in finalize_fetch_insn()
1401 code->op = FETCH_OP_END; in finalize_fetch_insn()
1417 trace_probe_log_err(ctx->offset, ARG_TOO_LONG); in traceprobe_parse_probe_arg_body()
1418 return -E2BIG; in traceprobe_parse_probe_arg_body()
1420 trace_probe_log_err(ctx->offset, NO_ARG_BODY); in traceprobe_parse_probe_arg_body()
1421 return -EINVAL; in traceprobe_parse_probe_arg_body()
1426 return -ENOMEM; in traceprobe_parse_probe_arg_body()
1428 parg->comm = kstrdup(arg, GFP_KERNEL); in traceprobe_parse_probe_arg_body()
1429 if (!parg->comm) { in traceprobe_parse_probe_arg_body()
1430 ret = -ENOMEM; in traceprobe_parse_probe_arg_body()
1442 ret = -ENOMEM; in traceprobe_parse_probe_arg_body()
1445 code[FETCH_INSN_MAX - 1].op = FETCH_OP_END; in traceprobe_parse_probe_arg_body()
1447 ctx->last_type = NULL; in traceprobe_parse_probe_arg_body()
1448 ret = parse_probe_arg(arg, parg->type, &code, &code[FETCH_INSN_MAX - 1], in traceprobe_parse_probe_arg_body()
1455 ctx->last_type) { in traceprobe_parse_probe_arg_body()
1457 parg->type = find_fetch_type_from_btf_type(ctx); in traceprobe_parse_probe_arg_body()
1464 parg->offset = *size; in traceprobe_parse_probe_arg_body()
1465 *size += parg->type->size * (parg->count ?: 1); in traceprobe_parse_probe_arg_body()
1467 if (parg->count) { in traceprobe_parse_probe_arg_body()
1468 len = strlen(parg->type->fmttype) + 6; in traceprobe_parse_probe_arg_body()
1469 parg->fmt = kmalloc(len, GFP_KERNEL); in traceprobe_parse_probe_arg_body()
1470 if (!parg->fmt) { in traceprobe_parse_probe_arg_body()
1471 ret = -ENOMEM; in traceprobe_parse_probe_arg_body()
1474 snprintf(parg->fmt, len, "%s[%d]", parg->type->fmttype, in traceprobe_parse_probe_arg_body()
1475 parg->count); in traceprobe_parse_probe_arg_body()
1478 ret = finalize_fetch_insn(code, parg, type, type ? type - arg : 0, ctx); in traceprobe_parse_probe_arg_body()
1483 if (code->op == FETCH_OP_END) in traceprobe_parse_probe_arg_body()
1486 parg->code = kcalloc(code - tmp + 1, sizeof(*code), GFP_KERNEL); in traceprobe_parse_probe_arg_body()
1487 if (!parg->code) in traceprobe_parse_probe_arg_body()
1488 ret = -ENOMEM; in traceprobe_parse_probe_arg_body()
1490 memcpy(parg->code, tmp, sizeof(*code) * (code - tmp + 1)); in traceprobe_parse_probe_arg_body()
1495 if (code->op == FETCH_NOP_SYMBOL || in traceprobe_parse_probe_arg_body()
1496 code->op == FETCH_OP_DATA) in traceprobe_parse_probe_arg_body()
1497 kfree(code->data); in traceprobe_parse_probe_arg_body()
1537 name = kmemdup_nul(arg, end - arg, GFP_KERNEL); in generate_probe_arg_name()
1550 int traceprobe_parse_probe_arg(struct trace_probe *tp, int i, const char *arg, in traceprobe_parse_probe_arg() argument
1553 struct probe_arg *parg = &tp->args[i]; in traceprobe_parse_probe_arg()
1556 ctx->tp = tp; in traceprobe_parse_probe_arg()
1559 if (body - arg > MAX_ARG_NAME_LEN) { in traceprobe_parse_probe_arg()
1561 return -EINVAL; in traceprobe_parse_probe_arg()
1564 return -EINVAL; in traceprobe_parse_probe_arg()
1566 parg->name = kmemdup_nul(arg, body - arg, GFP_KERNEL); in traceprobe_parse_probe_arg()
1569 parg->name = generate_probe_arg_name(arg, i); in traceprobe_parse_probe_arg()
1572 if (!parg->name) in traceprobe_parse_probe_arg()
1573 return -ENOMEM; in traceprobe_parse_probe_arg()
1575 if (!is_good_name(parg->name)) { in traceprobe_parse_probe_arg()
1577 return -EINVAL; in traceprobe_parse_probe_arg()
1579 if (traceprobe_conflict_field_name(parg->name, tp->args, i)) { in traceprobe_parse_probe_arg()
1581 return -EINVAL; in traceprobe_parse_probe_arg()
1583 ctx->offset = body - arg; in traceprobe_parse_probe_arg()
1585 return traceprobe_parse_probe_arg_body(body, &tp->size, parg, ctx); in traceprobe_parse_probe_arg()
1590 struct fetch_insn *code = arg->code; in traceprobe_free_probe_arg()
1592 while (code && code->op != FETCH_OP_END) { in traceprobe_free_probe_arg()
1593 if (code->op == FETCH_NOP_SYMBOL || in traceprobe_free_probe_arg()
1594 code->op == FETCH_OP_DATA) in traceprobe_free_probe_arg()
1595 kfree(code->data); in traceprobe_free_probe_arg()
1598 kfree(arg->code); in traceprobe_free_probe_arg()
1599 kfree(arg->name); in traceprobe_free_probe_arg()
1600 kfree(arg->comm); in traceprobe_free_probe_arg()
1601 kfree(arg->fmt); in traceprobe_free_probe_arg()
1613 if (!tparg_is_function_entry(ctx->flags) && in argv_has_var_arg()
1614 !tparg_is_function_return(ctx->flags)) { in argv_has_var_arg()
1616 return -EINVAL; in argv_has_var_arg()
1626 return -EINVAL; in argv_has_var_arg()
1631 return -EINVAL; in argv_has_var_arg()
1647 if (idx >= ctx->nr_params) { in sprint_nth_btf_arg()
1649 return -ENOENT; in sprint_nth_btf_arg()
1651 name = btf_name_by_offset(ctx->btf, ctx->params[idx].name_off); in sprint_nth_btf_arg()
1654 return -ENOENT; in sprint_nth_btf_arg()
1659 return -E2BIG; in sprint_nth_btf_arg()
1670 int i, j, n, used, ret, args_idx = -1; in traceprobe_expand_meta_args()
1683 if (ret < 0 || ctx->nr_params == 0) { in traceprobe_expand_meta_args()
1684 if (args_idx != -1) { in traceprobe_expand_meta_args()
1694 *new_argc = argc + ctx->nr_params - 1; in traceprobe_expand_meta_args()
1700 return ERR_PTR(-ENOMEM); in traceprobe_expand_meta_args()
1706 for (n = 0; n < ctx->nr_params; n++) { in traceprobe_expand_meta_args()
1708 bufsize - used, ctx); in traceprobe_expand_meta_args()
1724 ret = -ENOENT; in traceprobe_expand_meta_args()
1728 ret = sprint_nth_btf_arg(n - 1, type, buf + used, in traceprobe_expand_meta_args()
1729 bufsize - used, ctx); in traceprobe_expand_meta_args()
1753 return -EINVAL; in traceprobe_expand_dentry_args()
1767 return -ENOMEM; in traceprobe_expand_dentry_args()
1778 tmp[arg_len - 4] = '\0'; in traceprobe_expand_dentry_args()
1779 if (argv[i][arg_len - 1] == 'd') in traceprobe_expand_dentry_args()
1780 ret = snprintf(tmpbuf + used, bufsize - used, in traceprobe_expand_dentry_args()
1786 ret = snprintf(tmpbuf + used, bufsize - used, in traceprobe_expand_dentry_args()
1794 if (ret >= bufsize - used) in traceprobe_expand_dentry_args()
1804 return -ENOMEM; in traceprobe_expand_dentry_args()
1814 struct fetch_insn *code = arg->code; in traceprobe_update_arg()
1820 while (code && code->op != FETCH_OP_END) { in traceprobe_update_arg()
1821 if (code->op == FETCH_NOP_SYMBOL) { in traceprobe_update_arg()
1823 return -EINVAL; in traceprobe_update_arg()
1825 tmp = strpbrk(code->data, "+-"); in traceprobe_update_arg()
1828 ret = traceprobe_split_symbol_offset(code->data, in traceprobe_update_arg()
1834 (unsigned long)kallsyms_lookup_name(code->data); in traceprobe_update_arg()
1838 return -ENOENT; in traceprobe_update_arg()
1847 #define LEN_OR_ZERO (len ? len - pos : 0)
1848 static int __set_print_fmt(struct trace_probe *tp, char *buf, int len, in __set_print_fmt() argument
1859 arg = ", REC->" FIELD_STRING_IP; in __set_print_fmt()
1862 fmt = "(%lx <- %lx)"; in __set_print_fmt()
1863 arg = ", REC->" FIELD_STRING_FUNC ", REC->" FIELD_STRING_RETIP; in __set_print_fmt()
1876 for (i = 0; i < tp->nr_args; i++) { in __set_print_fmt()
1877 parg = tp->args + i; in __set_print_fmt()
1878 pos += snprintf(buf + pos, LEN_OR_ZERO, " %s=", parg->name); in __set_print_fmt()
1879 if (parg->count) { in __set_print_fmt()
1881 parg->type->fmt); in __set_print_fmt()
1882 for (j = 1; j < parg->count; j++) in __set_print_fmt()
1884 parg->type->fmt); in __set_print_fmt()
1888 parg->type->fmt); in __set_print_fmt()
1893 for (i = 0; i < tp->nr_args; i++) { in __set_print_fmt()
1894 parg = tp->args + i; in __set_print_fmt()
1895 if (parg->count) { in __set_print_fmt()
1896 if (parg->type->is_string) in __set_print_fmt()
1899 fmt = ", REC->%s[%d]"; in __set_print_fmt()
1900 for (j = 0; j < parg->count; j++) in __set_print_fmt()
1902 fmt, parg->name, j); in __set_print_fmt()
1904 if (parg->type->is_string) in __set_print_fmt()
1907 fmt = ", REC->%s"; in __set_print_fmt()
1909 fmt, parg->name); in __set_print_fmt()
1918 int traceprobe_set_print_fmt(struct trace_probe *tp, enum probe_print_type ptype) in traceprobe_set_print_fmt() argument
1920 struct trace_event_call *call = trace_probe_event_call(tp); in traceprobe_set_print_fmt()
1925 len = __set_print_fmt(tp, NULL, 0, ptype); in traceprobe_set_print_fmt()
1928 return -ENOMEM; in traceprobe_set_print_fmt()
1931 __set_print_fmt(tp, print_fmt, len + 1, ptype); in traceprobe_set_print_fmt()
1932 call->print_fmt = print_fmt; in traceprobe_set_print_fmt()
1938 size_t offset, struct trace_probe *tp) in traceprobe_define_arg_fields() argument
1943 for (i = 0; i < tp->nr_args; i++) { in traceprobe_define_arg_fields()
1944 struct probe_arg *parg = &tp->args[i]; in traceprobe_define_arg_fields()
1945 const char *fmt = parg->type->fmttype; in traceprobe_define_arg_fields()
1946 int size = parg->type->size; in traceprobe_define_arg_fields()
1948 if (parg->fmt) in traceprobe_define_arg_fields()
1949 fmt = parg->fmt; in traceprobe_define_arg_fields()
1950 if (parg->count) in traceprobe_define_arg_fields()
1951 size *= parg->count; in traceprobe_define_arg_fields()
1952 ret = trace_define_field(event_call, fmt, parg->name, in traceprobe_define_arg_fields()
1953 offset + parg->offset, size, in traceprobe_define_arg_fields()
1954 parg->type->is_signed, in traceprobe_define_arg_fields()
1964 kfree(tpe->class.system); in trace_probe_event_free()
1965 kfree(tpe->call.name); in trace_probe_event_free()
1966 kfree(tpe->call.print_fmt); in trace_probe_event_free()
1970 int trace_probe_append(struct trace_probe *tp, struct trace_probe *to) in trace_probe_append() argument
1972 if (trace_probe_has_sibling(tp)) in trace_probe_append()
1973 return -EBUSY; in trace_probe_append()
1975 list_del_init(&tp->list); in trace_probe_append()
1976 trace_probe_event_free(tp->event); in trace_probe_append()
1978 tp->event = to->event; in trace_probe_append()
1979 list_add_tail(&tp->list, trace_probe_probe_list(to)); in trace_probe_append()
1984 void trace_probe_unlink(struct trace_probe *tp) in trace_probe_unlink() argument
1986 list_del_init(&tp->list); in trace_probe_unlink()
1987 if (list_empty(trace_probe_probe_list(tp))) in trace_probe_unlink()
1988 trace_probe_event_free(tp->event); in trace_probe_unlink()
1989 tp->event = NULL; in trace_probe_unlink()
1992 void trace_probe_cleanup(struct trace_probe *tp) in trace_probe_cleanup() argument
1996 for (i = 0; i < tp->nr_args; i++) in trace_probe_cleanup()
1997 traceprobe_free_probe_arg(&tp->args[i]); in trace_probe_cleanup()
1999 if (tp->entry_arg) { in trace_probe_cleanup()
2000 kfree(tp->entry_arg->code); in trace_probe_cleanup()
2001 kfree(tp->entry_arg); in trace_probe_cleanup()
2002 tp->entry_arg = NULL; in trace_probe_cleanup()
2005 if (tp->event) in trace_probe_cleanup()
2006 trace_probe_unlink(tp); in trace_probe_cleanup()
2009 int trace_probe_init(struct trace_probe *tp, const char *event, in trace_probe_init() argument
2017 return -EINVAL; in trace_probe_init()
2022 tp->event = kzalloc(size, GFP_KERNEL); in trace_probe_init()
2023 if (!tp->event) in trace_probe_init()
2024 return -ENOMEM; in trace_probe_init()
2026 INIT_LIST_HEAD(&tp->event->files); in trace_probe_init()
2027 INIT_LIST_HEAD(&tp->event->class.fields); in trace_probe_init()
2028 INIT_LIST_HEAD(&tp->event->probes); in trace_probe_init()
2029 INIT_LIST_HEAD(&tp->list); in trace_probe_init()
2030 list_add(&tp->list, &tp->event->probes); in trace_probe_init()
2032 call = trace_probe_event_call(tp); in trace_probe_init()
2033 call->class = &tp->event->class; in trace_probe_init()
2034 call->name = kstrdup(event, GFP_KERNEL); in trace_probe_init()
2035 if (!call->name) { in trace_probe_init()
2036 ret = -ENOMEM; in trace_probe_init()
2040 tp->event->class.system = kstrdup(group, GFP_KERNEL); in trace_probe_init()
2041 if (!tp->event->class.system) { in trace_probe_init()
2042 ret = -ENOMEM; in trace_probe_init()
2046 tp->nr_args = nargs; in trace_probe_init()
2049 memset(tp->args, 0, sizeof(tp->args[0]) * nargs); in trace_probe_init()
2054 trace_probe_cleanup(tp); in trace_probe_init()
2065 if (!tp_event->class->system || in find_trace_event_call()
2066 strcmp(system, tp_event->class->system)) in find_trace_event_call()
2077 int trace_probe_register_event_call(struct trace_probe *tp) in trace_probe_register_event_call() argument
2079 struct trace_event_call *call = trace_probe_event_call(tp); in trace_probe_register_event_call()
2084 if (find_trace_event_call(trace_probe_group_name(tp), in trace_probe_register_event_call()
2085 trace_probe_name(tp))) in trace_probe_register_event_call()
2086 return -EEXIST; in trace_probe_register_event_call()
2088 ret = register_trace_event(&call->event); in trace_probe_register_event_call()
2090 return -ENODEV; in trace_probe_register_event_call()
2094 unregister_trace_event(&call->event); in trace_probe_register_event_call()
2099 int trace_probe_add_file(struct trace_probe *tp, struct trace_event_file *file) in trace_probe_add_file() argument
2101 struct event_file_link *link; in trace_probe_add_file() local
2103 link = kmalloc(sizeof(*link), GFP_KERNEL); in trace_probe_add_file()
2104 if (!link) in trace_probe_add_file()
2105 return -ENOMEM; in trace_probe_add_file()
2107 link->file = file; in trace_probe_add_file()
2108 INIT_LIST_HEAD(&link->list); in trace_probe_add_file()
2109 list_add_tail_rcu(&link->list, &tp->event->files); in trace_probe_add_file()
2110 trace_probe_set_flag(tp, TP_FLAG_TRACE); in trace_probe_add_file()
2114 struct event_file_link *trace_probe_get_file_link(struct trace_probe *tp, in trace_probe_get_file_link() argument
2117 struct event_file_link *link; in trace_probe_get_file_link() local
2119 trace_probe_for_each_link(link, tp) { in trace_probe_get_file_link()
2120 if (link->file == file) in trace_probe_get_file_link()
2121 return link; in trace_probe_get_file_link()
2127 int trace_probe_remove_file(struct trace_probe *tp, in trace_probe_remove_file() argument
2130 struct event_file_link *link; in trace_probe_remove_file() local
2132 link = trace_probe_get_file_link(tp, file); in trace_probe_remove_file()
2133 if (!link) in trace_probe_remove_file()
2134 return -ENOENT; in trace_probe_remove_file()
2136 list_del_rcu(&link->list); in trace_probe_remove_file()
2137 kvfree_rcu_mightsleep(link); in trace_probe_remove_file()
2139 if (list_empty(&tp->event->files)) in trace_probe_remove_file()
2140 trace_probe_clear_flag(tp, TP_FLAG_TRACE); in trace_probe_remove_file()
2154 if (a->nr_args < b->nr_args) in trace_probe_compare_arg_type()
2155 return a->nr_args + 1; in trace_probe_compare_arg_type()
2156 if (a->nr_args > b->nr_args) in trace_probe_compare_arg_type()
2157 return b->nr_args + 1; in trace_probe_compare_arg_type()
2159 for (i = 0; i < a->nr_args; i++) { in trace_probe_compare_arg_type()
2160 if ((b->nr_args <= i) || in trace_probe_compare_arg_type()
2161 ((a->args[i].type != b->args[i].type) || in trace_probe_compare_arg_type()
2162 (a->args[i].count != b->args[i].count) || in trace_probe_compare_arg_type()
2163 strcmp(a->args[i].name, b->args[i].name))) in trace_probe_compare_arg_type()
2170 bool trace_probe_match_command_args(struct trace_probe *tp, in trace_probe_match_command_args() argument
2176 if (tp->nr_args < argc) in trace_probe_match_command_args()
2181 tp->args[i].name, tp->args[i].comm); in trace_probe_match_command_args()
2195 return -ENOMEM; in trace_probe_create()
2214 trace_seq_printf(s, " %s=", a->name); in trace_probe_print_args()
2215 if (likely(!a->count)) { in trace_probe_print_args()
2216 if (!a->type->print(s, data + a->offset, field)) in trace_probe_print_args()
2217 return -ENOMEM; in trace_probe_print_args()
2221 p = data + a->offset; in trace_probe_print_args()
2222 for (j = 0; j < a->count; j++) { in trace_probe_print_args()
2223 if (!a->type->print(s, p, field)) in trace_probe_print_args()
2224 return -ENOMEM; in trace_probe_print_args()
2225 trace_seq_putc(s, j == a->count - 1 ? '}' : ','); in trace_probe_print_args()
2226 p += a->type->size; in trace_probe_print_args()