Lines Matching +full:traces +full:-

1 /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
72 " ARG := { arg | arg [PRED] | arg->member [PRED] }\n" in cmd_help()
74 " OPTIONS := { {-d|--debug} | {-v|--verbose} | {-V|--version} |\n" in cmd_help()
75 " {-p|--pid filter_pid}|\n" in cmd_help()
76 " {-P|--pages nr_pages} }\n" in cmd_help()
77 " {-s|--stack}\n", in cmd_help()
84 " %s trace \"ip_send_skb(skb->sk, return)\"\n" in cmd_help()
85 " %s trace \"ip_send_skb(skb->len > 128, skb)\"\n" in cmd_help()
86 " %s trace -s udp_sendmsg ip_send_skb\n", in cmd_help()
103 if (strlen(val->name) == 0) { in type_to_value()
105 strncpy(val->name, name, in type_to_value()
106 sizeof(val->name) - 1); in type_to_value()
108 val->name[0] = '\0'; in type_to_value()
113 switch (BTF_INFO_KIND(type->info)) { in type_to_value()
117 id = type->type; in type_to_value()
120 val->flags |= KSNOOP_F_PTR; in type_to_value()
121 id = type->type; in type_to_value()
124 val->type_id = id; in type_to_value()
129 val->type_id = KSNOOP_ID_UNKNOWN; in type_to_value()
132 val->size = btf__resolve_size(btf, val->type_id); in type_to_value()
152 pname = btf__str_by_offset(btf, type->name_off); in member_to_value()
156 kind = BTF_INFO_KIND(type->info); in member_to_value()
160 nmembers = BTF_INFO_VLEN(type->info); in member_to_value()
168 type = btf__type_by_id(btf, member->type); in member_to_value()
169 mname = btf__str_by_offset(btf, member->name_off); in member_to_value()
170 offset = member->offset / 8; in member_to_value()
173 mname, member->type, offset); in member_to_value()
176 kind = BTF_INFO_KIND(type->info); in member_to_value()
181 member->type); in member_to_value()
182 val->offset += offset; in member_to_value()
183 if (!member_to_value(btf, name, member->type, in member_to_value()
186 val->offset -= offset; in member_to_value()
191 val->offset += offset; in member_to_value()
192 val->flags |= KSNOOP_F_MEMBER; in member_to_value()
193 type_to_value(btf, NULL, member->type, val); in member_to_value()
195 mname, val->offset, val->flags, in member_to_value()
196 val->size); in member_to_value()
203 id, val->offset); in member_to_value()
209 return -ENOENT; in member_to_value()
218 func->id = btf__find_by_name_kind(btf, func->name, BTF_KIND_FUNC); in get_func_btf()
219 if (func->id <= 0) { in get_func_btf()
221 func->name, strerror(-func->id)); in get_func_btf()
222 return -ENOENT; in get_func_btf()
224 type = btf__type_by_id(btf, func->id); in get_func_btf()
225 if (!type || BTF_INFO_KIND(type->info) != BTF_KIND_FUNC) { in get_func_btf()
226 p_err("Error looking up function type via id '%d'", func->id); in get_func_btf()
227 return -EINVAL; in get_func_btf()
229 type = btf__type_by_id(btf, type->type); in get_func_btf()
230 if (!type || BTF_INFO_KIND(type->info) != BTF_KIND_FUNC_PROTO) { in get_func_btf()
232 func->id); in get_func_btf()
233 return -EINVAL; in get_func_btf()
236 i < BTF_INFO_VLEN(type->info) && i < MAX_ARGS; in get_func_btf()
239 (char *)btf__str_by_offset(btf, param->name_off), in get_func_btf()
240 param->type, &func->args[i]); in get_func_btf()
242 i + 1, func->args[i].name, func->args[i].type_id); in get_func_btf()
246 func->nr_args = BTF_INFO_VLEN(type->info); in get_func_btf()
248 type_to_value(btf, KSNOOP_RETURN_NAME, type->type, in get_func_btf()
249 &func->args[KSNOOP_RETURN]); in get_func_btf()
251 func->args[KSNOOP_RETURN].type_id); in get_func_btf()
263 p_debug("checking predicate '%s' for '%s'", predicate, val->name); in predicate_to_value()
268 return -EINVAL; in predicate_to_value()
270 if (!(val->flags & KSNOOP_F_PTR) && in predicate_to_value()
271 (val->size == 0 || val->size > sizeof(__u64))) { in predicate_to_value()
273 val->name, val->size); in predicate_to_value()
274 return -EINVAL; in predicate_to_value()
276 val->predicate_value = (__u64)v; in predicate_to_value()
279 val->flags |= KSNOOP_F_PREDICATE_EQ; in predicate_to_value()
282 val->flags |= KSNOOP_F_PREDICATE_NOTEQ; in predicate_to_value()
286 val->flags |= KSNOOP_F_PREDICATE_GT; in predicate_to_value()
288 val->flags |= KSNOOP_F_PREDICATE_LT; in predicate_to_value()
295 return -EINVAL; in predicate_to_value()
297 val->flags |= KSNOOP_F_PREDICATE_EQ; in predicate_to_value()
301 pred, val->flags, val->predicate_value); in predicate_to_value()
312 snprintf(val->name, sizeof(val->name), "%s->%s", in trace_to_value()
315 strncpy(val->name, argname, sizeof(val->name)); in trace_to_value()
318 if (strcmp(argname, func->args[i].name) != 0) in trace_to_value()
320 p_debug("setting base arg for val %s to %d", val->name, i); in trace_to_value()
321 val->base_arg = i; in trace_to_value()
325 func->args[i].type_id, val, 0)) in trace_to_value()
326 return -ENOENT; in trace_to_value()
328 val->type_id = func->args[i].type_id; in trace_to_value()
329 val->flags |= func->args[i].flags; in trace_to_value()
330 val->size = func->args[i].size; in trace_to_value()
335 argname, func->name); in trace_to_value()
336 return -ENOENT; in trace_to_value()
350 err = -errno; in get_btf()
351 p_err("No BTF, cannot determine type info: %s", strerror(-err)); in get_btf()
360 err = -errno; in get_btf()
361 p_err("No BTF for module '%s': %s", name, strerror(-err)); in get_btf()
400 switch (BTF_INFO_KIND(type->info)) { in type_id_to_str()
404 type_id = type->type; in type_id_to_str()
408 type_id = type->type; in type_id_to_str()
412 type_id = type->type; in type_id_to_str()
416 name = btf__str_by_offset(btf, type->name_off); in type_id_to_str()
420 name = btf__str_by_offset(btf, type->name_off); in type_id_to_str()
424 name = btf__str_by_offset(btf, type->name_off); in type_id_to_str()
427 name = btf__str_by_offset(btf, type->name_off); in type_id_to_str()
430 name = btf__str_by_offset(btf, type->name_off); in type_id_to_str()
444 str = type_id_to_str(btf, val->type_id, str); in value_to_str()
445 if (val->flags & KSNOOP_F_PTR) in value_to_str()
447 if (strlen(val->name) > 0 && in value_to_str()
448 strcmp(val->name, KSNOOP_RETURN_NAME) != 0) in value_to_str()
449 strncat(str, val->name, MAX_STR); in value_to_str()
476 err = -EINVAL; in get_func_ip_mod()
479 if (strcmp(func->name, sym_name) != 0) in get_func_ip_mod()
481 func->ip = sym_addr; in get_func_ip_mod()
482 func->mod[0] = '\0'; in get_func_ip_mod()
485 if (sscanf(mod_info, "%*[\t ][%[^]]", func->mod) < 1) { in get_func_ip_mod()
487 err = -EINVAL; in get_func_ip_mod()
491 p_debug("%s = <ip %llx, mod %s>", func->name, func->ip, in get_func_ip_mod()
492 strlen(func->mod) > 0 ? func->mod : "vmlinux"); in get_func_ip_mod()
505 #define VALID_NAME "%[A-Za-z0-9\\-_]"
513 struct func *func = &trace->func; in parse_trace()
521 trace->filter_pid = (__u32)filter_pid; in parse_trace()
523 p_debug("Using pid %lu as filter", trace->filter_pid); in parse_trace()
525 trace->btf = vmlinux_btf; in parse_trace()
527 ret = sscanf(tracestr, VALID_NAME "(" ARGDATA ")", func->name, argdata); in parse_trace()
531 if (strlen(tracestr) > strlen(func->name)) { in parse_trace()
536 p_debug("got func '%s'", func->name); in parse_trace()
539 strlen(func->name) + strlen(argdata) + 2) { in parse_trace()
543 p_debug("got func '%s', args '%s'", func->name, argdata); in parse_trace()
544 trace->flags |= KSNOOP_F_CUSTOM; in parse_trace()
549 p_err("could not get address of '%s'", func->name); in parse_trace()
552 trace->btf = get_btf(func->mod); in parse_trace()
553 if (!trace->btf) { in parse_trace()
554 ret = -errno; in parse_trace()
556 strlen(func->mod) ? func->mod : "vmlinux", in parse_trace()
557 strerror(-ret)); in parse_trace()
558 return -ENOENT; in parse_trace()
560 trace->dump = btf_dump__new(trace->btf, trace_printf, NULL, NULL); in parse_trace()
561 if (!trace->dump) { in parse_trace()
562 ret = -errno; in parse_trace()
563 p_err("could not create BTF dump : %s", strerror(-ret)); in parse_trace()
564 return -EINVAL; in parse_trace()
567 ret = get_func_btf(trace->btf, func); in parse_trace()
578 ret = sscanf(arg, VALID_NAME "->" VALID_NAME, in parse_trace()
598 return -EINVAL; in parse_trace()
600 if (trace_to_value(trace->btf, func, argname, membername, in parse_trace()
601 predicate, &trace->traces[i])) in parse_trace()
602 return -EINVAL; in parse_trace()
606 if (trace->traces[i].base_arg == KSNOOP_RETURN) in parse_trace()
610 trace->nr_traces++; in parse_trace()
613 if (trace->nr_traces > 0) { in parse_trace()
614 trace->flags |= KSNOOP_F_CUSTOM; in parse_trace()
615 p_debug("custom trace with %d args", trace->nr_traces); in parse_trace()
619 * mode where arg traces are stored on entry and not in parse_trace()
623 trace->flags |= KSNOOP_F_STASH; in parse_trace()
628 func->nr_args); in parse_trace()
630 memcpy(trace->traces, func->args, sizeof(trace->traces)); in parse_trace()
632 trace->traces[i].base_arg = i; in parse_trace()
633 trace->nr_traces = MAX_TRACES; in parse_trace()
639 static int parse_traces(int argc, char **argv, struct trace **traces) in parse_traces() argument
647 p_err("A maximum of %d traces are supported", MAX_FUNC_TRACES); in parse_traces()
648 return -EINVAL; in parse_traces()
650 *traces = calloc(argc, sizeof(struct trace)); in parse_traces()
651 if (!*traces) { in parse_traces()
652 p_err("Could not allocate %d traces", argc); in parse_traces()
653 return -ENOMEM; in parse_traces()
656 if (parse_trace(argv[i], &((*traces)[i]))) in parse_traces()
657 return -EINVAL; in parse_traces()
661 (*traces)[i].prev_ip = (*traces)[i-1].func.ip; in parse_traces()
662 (*traces)[i-1].next_ip = (*traces)[i].func.ip; in parse_traces()
669 struct trace *traces = NULL; in cmd_info() local
674 nr_traces = parse_traces(argc, argv, &traces); in cmd_info()
679 struct func *func = &traces[i].func; in cmd_info()
682 value_to_str(traces[i].btf, &func->args[KSNOOP_RETURN], in cmd_info()
684 func->name); in cmd_info()
685 for (j = 0; j < func->nr_args; j++) { in cmd_info()
688 printf("%s", value_to_str(traces[i].btf, &func->args[j], in cmd_info()
691 if (func->nr_args > MAX_ARGS) in cmd_info()
693 func->nr_args - MAX_ARGS); in cmd_info()
696 free(traces); in cmd_info()
706 if (size < (sizeof(*trace) - MAX_TRACE_BUF)) { in trace_handler()
708 size, sizeof(trace) - MAX_TRACE_BUF); in trace_handler()
711 printf("%16lld %4d %8u %s(\n", trace->time, trace->cpu, trace->pid, in trace_handler()
712 trace->func.name); in trace_handler()
714 for (i = 0, shown = 0; i < trace->nr_traces; i++) { in trace_handler()
716 bool entry = trace->data_flags & KSNOOP_F_ENTRY; in trace_handler()
717 struct value *val = &trace->traces[i]; in trace_handler()
718 struct trace_data *data = &trace->trace_data[i]; in trace_handler()
729 if ((entry && !base_arg_is_entry(val->base_arg)) || in trace_handler()
730 (!entry && base_arg_is_entry(val->base_arg) && in trace_handler()
731 !(trace->flags & KSNOOP_F_STASH))) in trace_handler()
734 if (val->type_id == 0) in trace_handler()
739 printf("%34s %s = ", "", val->name); in trace_handler()
740 if (val->flags & KSNOOP_F_PTR) in trace_handler()
741 printf("*(0x%llx)", data->raw_value); in trace_handler()
744 if (data->err_type_id != 0) { in trace_handler()
749 val->name, in trace_handler()
750 type_id_to_str(trace->btf, in trace_handler()
751 val->type_id, in trace_handler()
753 val->flags & KSNOOP_F_PTR ? in trace_handler()
757 (trace->dump, val->type_id, in trace_handler()
758 trace->buf + data->buf_offset, in trace_handler()
759 data->buf_len, &opts); in trace_handler()
761 if (ret == -E2BIG) in trace_handler()
763 data->buf_len, in trace_handler()
764 val->size); in trace_handler()
783 static int add_traces(struct bpf_map *func_map, struct trace *traces, in add_traces() argument
791 p_err("Could not allocate memory for %d traces", nr_traces); in add_traces()
792 return -ENOMEM; in add_traces()
796 memcpy(&map_traces[j], &traces[i], in add_traces()
800 &traces[i].func.ip, in add_traces()
805 traces[i].func.name, strerror(-ret)); in add_traces()
813 static int attach_traces(struct ksnoop_bpf *skel, struct trace *traces, in attach_traces() argument
819 traces[i].links[0] = in attach_traces()
820 bpf_program__attach_kprobe(skel->progs.kprobe_entry, in attach_traces()
822 traces[i].func.name); in attach_traces()
823 if (!traces[i].links[0]) { in attach_traces()
824 ret = -errno; in attach_traces()
826 traces[i].func.name, strerror(-ret)); in attach_traces()
829 p_debug("Attached kprobe for '%s'", traces[i].func.name); in attach_traces()
831 traces[i].links[1] = in attach_traces()
832 bpf_program__attach_kprobe(skel->progs.kprobe_return, in attach_traces()
834 traces[i].func.name); in attach_traces()
835 if (!traces[i].links[1]) { in attach_traces()
836 ret = -errno; in attach_traces()
838 traces[i].func.name, strerror(-ret)); in attach_traces()
841 p_debug("Attached kretprobe for '%s'", traces[i].func.name); in attach_traces()
851 int i, nr_traces, ret = -1; in cmd_trace()
852 struct trace *traces = NULL; in cmd_trace() local
854 nr_traces = parse_traces(argc, argv, &traces); in cmd_trace()
860 ret = -errno; in cmd_trace()
861 p_err("Could not load ksnoop BPF: %s", strerror(-ret)); in cmd_trace()
865 perf_map = skel->maps.ksnoop_perf_map; in cmd_trace()
870 func_map = bpf_object__find_map_by_name(skel->obj, "ksnoop_func_map"); in cmd_trace()
876 if (add_traces(func_map, traces, nr_traces)) { in cmd_trace()
877 p_err("Could not add traces to '%s'", "ksnoop_func_map"); in cmd_trace()
881 if (attach_traces(skel, traces, nr_traces)) { in cmd_trace()
882 p_err("Could not attach %d traces", nr_traces); in cmd_trace()
889 ret = -errno; in cmd_trace()
890 p_err("Could not create perf buffer: %s", strerror(-ret)); in cmd_trace()
904 if (ret < 0 && ret != -EINTR) { in cmd_trace()
905 fprintf(stderr, "error polling perf buffer: %s\n", strerror(-ret)); in cmd_trace()
914 bpf_link__destroy(traces[i].links[0]); in cmd_trace()
915 bpf_link__destroy(traces[i].links[1]); in cmd_trace()
917 free(traces); in cmd_trace()
942 return cmds[i].func(argc - 1, argv + 1); in cmd_select()
994 p_err("unrecognized option '%s'", argv[optind - 1]); in main()
1000 argc -= optind; in main()