bpf: Add bpf_seq_printf_btf helper
authorAlan Maguire <alan.maguire@oracle.com>
Mon, 28 Sep 2020 11:31:09 +0000 (12:31 +0100)
committerAlexei Starovoitov <ast@kernel.org>
Tue, 29 Sep 2020 01:26:58 +0000 (18:26 -0700)
A helper is added to allow seq file writing of kernel data
structures using vmlinux BTF.  Its signature is

long bpf_seq_printf_btf(struct seq_file *m, struct btf_ptr *ptr,
                        u32 btf_ptr_size, u64 flags);

Flags and struct btf_ptr definitions/use are identical to the
bpf_snprintf_btf helper, and the helper returns 0 on success
or a negative error value.

Suggested-by: Alexei Starovoitov <alexei.starovoitov@gmail.com>
Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/1601292670-1616-8-git-send-email-alan.maguire@oracle.com
include/linux/btf.h
include/uapi/linux/bpf.h
kernel/bpf/btf.c
kernel/bpf/core.c
kernel/trace/bpf_trace.c
tools/include/uapi/linux/bpf.h

index 3e5cdc2..024e16f 100644 (file)
@@ -68,6 +68,8 @@ const struct btf_type *btf_type_id_size(const struct btf *btf,
 
 void btf_type_seq_show(const struct btf *btf, u32 type_id, void *obj,
                       struct seq_file *m);
+int btf_type_seq_show_flags(const struct btf *btf, u32 type_id, void *obj,
+                           struct seq_file *m, u64 flags);
 
 /*
  * Copy len bytes of string representation of obj of BTF type_id into buf.
index cca9eb1..96ddb00 100644 (file)
@@ -3630,6 +3630,14 @@ union bpf_attr {
  *             The number of bytes that were written (or would have been
  *             written if output had to be truncated due to string size),
  *             or a negative error in cases of failure.
+ *
+ * long bpf_seq_printf_btf(struct seq_file *m, struct btf_ptr *ptr, u32 ptr_size, u64 flags)
+ *     Description
+ *             Use BTF to write to seq_write a string representation of
+ *             *ptr*->ptr, using *ptr*->type_id as per bpf_snprintf_btf().
+ *             *flags* are identical to those used for bpf_snprintf_btf.
+ *     Return
+ *             0 on success or a negative error in case of failure.
  */
 #define __BPF_FUNC_MAPPER(FN)          \
        FN(unspec),                     \
@@ -3782,6 +3790,7 @@ union bpf_attr {
        FN(d_path),                     \
        FN(copy_from_user),             \
        FN(snprintf_btf),               \
+       FN(seq_printf_btf),             \
        /* */
 
 /* integer value in 'imm' field of BPF_CALL instruction selects which helper
index dcdd710..498e5e5 100644 (file)
@@ -5346,8 +5346,8 @@ static void btf_seq_show(struct btf_show *show, const char *fmt,
        seq_vprintf((struct seq_file *)show->target, fmt, args);
 }
 
-static int btf_type_seq_show_flags(const struct btf *btf, u32 type_id,
-                                  void *obj, struct seq_file *m, u64 flags)
+int btf_type_seq_show_flags(const struct btf *btf, u32 type_id,
+                           void *obj, struct seq_file *m, u64 flags)
 {
        struct btf_show sseq;
 
index 403fb23..c4ba45f 100644 (file)
@@ -2217,6 +2217,7 @@ const struct bpf_func_proto bpf_get_current_ancestor_cgroup_id_proto __weak;
 const struct bpf_func_proto bpf_get_local_storage_proto __weak;
 const struct bpf_func_proto bpf_get_ns_current_pid_tgid_proto __weak;
 const struct bpf_func_proto bpf_snprintf_btf_proto __weak;
+const struct bpf_func_proto bpf_seq_printf_btf_proto __weak;
 
 const struct bpf_func_proto * __weak bpf_get_trace_printk_proto(void)
 {
index 140e1be..e118a83 100644 (file)
@@ -71,6 +71,10 @@ static struct bpf_raw_event_map *bpf_get_raw_tracepoint_module(const char *name)
 u64 bpf_get_stackid(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5);
 u64 bpf_get_stack(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5);
 
+static int bpf_btf_printf_prepare(struct btf_ptr *ptr, u32 btf_ptr_size,
+                                 u64 flags, const struct btf **btf,
+                                 s32 *btf_id);
+
 /**
  * trace_call_bpf - invoke BPF program
  * @call: tracepoint event
@@ -776,6 +780,31 @@ static const struct bpf_func_proto bpf_seq_write_proto = {
        .arg3_type      = ARG_CONST_SIZE_OR_ZERO,
 };
 
+BPF_CALL_4(bpf_seq_printf_btf, struct seq_file *, m, struct btf_ptr *, ptr,
+          u32, btf_ptr_size, u64, flags)
+{
+       const struct btf *btf;
+       s32 btf_id;
+       int ret;
+
+       ret = bpf_btf_printf_prepare(ptr, btf_ptr_size, flags, &btf, &btf_id);
+       if (ret)
+               return ret;
+
+       return btf_type_seq_show_flags(btf, btf_id, ptr->ptr, m, flags);
+}
+
+static const struct bpf_func_proto bpf_seq_printf_btf_proto = {
+       .func           = bpf_seq_printf_btf,
+       .gpl_only       = true,
+       .ret_type       = RET_INTEGER,
+       .arg1_type      = ARG_PTR_TO_BTF_ID,
+       .arg1_btf_id    = &btf_seq_file_ids[0],
+       .arg2_type      = ARG_PTR_TO_MEM,
+       .arg3_type      = ARG_CONST_SIZE_OR_ZERO,
+       .arg4_type      = ARG_ANYTHING,
+};
+
 static __always_inline int
 get_map_perf_counter(struct bpf_map *map, u64 flags,
                     u64 *value, u64 *enabled, u64 *running)
@@ -1695,6 +1724,10 @@ tracing_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
                return prog->expected_attach_type == BPF_TRACE_ITER ?
                       &bpf_seq_write_proto :
                       NULL;
+       case BPF_FUNC_seq_printf_btf:
+               return prog->expected_attach_type == BPF_TRACE_ITER ?
+                      &bpf_seq_printf_btf_proto :
+                      NULL;
        case BPF_FUNC_d_path:
                return &bpf_d_path_proto;
        default:
index cca9eb1..96ddb00 100644 (file)
@@ -3630,6 +3630,14 @@ union bpf_attr {
  *             The number of bytes that were written (or would have been
  *             written if output had to be truncated due to string size),
  *             or a negative error in cases of failure.
+ *
+ * long bpf_seq_printf_btf(struct seq_file *m, struct btf_ptr *ptr, u32 ptr_size, u64 flags)
+ *     Description
+ *             Use BTF to write to seq_write a string representation of
+ *             *ptr*->ptr, using *ptr*->type_id as per bpf_snprintf_btf().
+ *             *flags* are identical to those used for bpf_snprintf_btf.
+ *     Return
+ *             0 on success or a negative error in case of failure.
  */
 #define __BPF_FUNC_MAPPER(FN)          \
        FN(unspec),                     \
@@ -3782,6 +3790,7 @@ union bpf_attr {
        FN(d_path),                     \
        FN(copy_from_user),             \
        FN(snprintf_btf),               \
+       FN(seq_printf_btf),             \
        /* */
 
 /* integer value in 'imm' field of BPF_CALL instruction selects which helper