|
12 | 12 | #include <linux/sched/clock.h> |
13 | 13 | #include <linux/sched/mm.h> |
14 | 14 | #include <linux/idr.h> |
| 15 | +#include <linux/btf.h> |
| 16 | +#include <linux/bpf.h> |
15 | 17 |
|
16 | 18 | #include "trace_output.h" |
| 19 | +#include "trace_btf.h" |
17 | 20 |
|
18 | 21 | /* must be a power of 2 */ |
19 | 22 | #define EVENT_HASHSIZE 128 |
@@ -684,6 +687,88 @@ int trace_print_lat_context(struct trace_iterator *iter) |
684 | 687 | return !trace_seq_has_overflowed(s); |
685 | 688 | } |
686 | 689 |
|
| 690 | +#ifdef CONFIG_FUNCTION_TRACE_ARGS |
| 691 | +void print_function_args(struct trace_seq *s, unsigned long *args, |
| 692 | + unsigned long func) |
| 693 | +{ |
| 694 | + const struct btf_param *param; |
| 695 | + const struct btf_type *t; |
| 696 | + const char *param_name; |
| 697 | + char name[KSYM_NAME_LEN]; |
| 698 | + unsigned long arg; |
| 699 | + struct btf *btf; |
| 700 | + s32 tid, nr = 0; |
| 701 | + int a, p, x; |
| 702 | + |
| 703 | + trace_seq_printf(s, "("); |
| 704 | + |
| 705 | + if (!args) |
| 706 | + goto out; |
| 707 | + if (lookup_symbol_name(func, name)) |
| 708 | + goto out; |
| 709 | + |
| 710 | + /* TODO: Pass module name here too */ |
| 711 | + t = btf_find_func_proto(name, &btf); |
| 712 | + if (IS_ERR_OR_NULL(t)) |
| 713 | + goto out; |
| 714 | + |
| 715 | + param = btf_get_func_param(t, &nr); |
| 716 | + if (!param) |
| 717 | + goto out_put; |
| 718 | + |
| 719 | + for (a = 0, p = 0; p < nr; a++, p++) { |
| 720 | + if (p) |
| 721 | + trace_seq_puts(s, ", "); |
| 722 | + |
| 723 | + /* This only prints what the arch allows (6 args by default) */ |
| 724 | + if (a == FTRACE_REGS_MAX_ARGS) { |
| 725 | + trace_seq_puts(s, "..."); |
| 726 | + break; |
| 727 | + } |
| 728 | + |
| 729 | + arg = args[a]; |
| 730 | + |
| 731 | + param_name = btf_name_by_offset(btf, param[p].name_off); |
| 732 | + if (param_name) |
| 733 | + trace_seq_printf(s, "%s=", param_name); |
| 734 | + t = btf_type_skip_modifiers(btf, param[p].type, &tid); |
| 735 | + |
| 736 | + switch (t ? BTF_INFO_KIND(t->info) : BTF_KIND_UNKN) { |
| 737 | + case BTF_KIND_UNKN: |
| 738 | + trace_seq_putc(s, '?'); |
| 739 | + /* Still print unknown type values */ |
| 740 | + fallthrough; |
| 741 | + case BTF_KIND_PTR: |
| 742 | + trace_seq_printf(s, "0x%lx", arg); |
| 743 | + break; |
| 744 | + case BTF_KIND_INT: |
| 745 | + trace_seq_printf(s, "%ld", arg); |
| 746 | + break; |
| 747 | + case BTF_KIND_ENUM: |
| 748 | + trace_seq_printf(s, "%ld", arg); |
| 749 | + break; |
| 750 | + default: |
| 751 | + /* This does not handle complex arguments */ |
| 752 | + trace_seq_printf(s, "(%s)[0x%lx", btf_type_str(t), arg); |
| 753 | + for (x = sizeof(long); x < t->size; x += sizeof(long)) { |
| 754 | + trace_seq_putc(s, ':'); |
| 755 | + if (++a == FTRACE_REGS_MAX_ARGS) { |
| 756 | + trace_seq_puts(s, "...]"); |
| 757 | + goto out_put; |
| 758 | + } |
| 759 | + trace_seq_printf(s, "0x%lx", args[a]); |
| 760 | + } |
| 761 | + trace_seq_putc(s, ']'); |
| 762 | + break; |
| 763 | + } |
| 764 | + } |
| 765 | +out_put: |
| 766 | + btf_put(btf); |
| 767 | +out: |
| 768 | + trace_seq_printf(s, ")"); |
| 769 | +} |
| 770 | +#endif |
| 771 | + |
687 | 772 | /** |
688 | 773 | * ftrace_find_event - find a registered event |
689 | 774 | * @type: the type of event to look for |
|
0 commit comments