bpf: Create a new btf_name_by_offset() for non type name use case
authorMartin KaFai Lau <kafai@fb.com>
Thu, 13 Dec 2018 18:41:46 +0000 (10:41 -0800)
committerAlexei Starovoitov <ast@kernel.org>
Fri, 14 Dec 2018 22:17:34 +0000 (14:17 -0800)
The current btf_name_by_offset() is returning "(anon)" type name for
the offset == 0 case and "(invalid-name-offset)" for the out-of-bound
offset case.

It fits well for the internal BTF verbose log purpose which
is focusing on type.  For example,
offset == 0 => "(anon)" => anonymous type/name.
Returning non-NULL for the bad offset case is needed
during the BTF verification process because the BTF verifier may
complain about another field first before discovering the name_off
is invalid.

However, it may not be ideal for the newer use case which does not
necessary mean type name.  For example, when logging line_info
in the BPF verifier in the next patch, it is better to log an
empty src line instead of logging "(anon)".

The existing bpf_name_by_offset() is renamed to __bpf_name_by_offset()
and static to btf.c.

A new bpf_name_by_offset() is added for generic context usage.  It
returns "\0" for name_off == 0 (note that btf->strings[0] is "\0")
and NULL for invalid offset.  It allows the caller to decide
what is the best output in its context.

The new btf_name_by_offset() is overlapped with btf_name_offset_valid().
Hence, btf_name_offset_valid() is removed from btf.h to keep the btf.h API
minimal.  The existing btf_name_offset_valid() usage in btf.c could also be
replaced later.

Signed-off-by: Martin KaFai Lau <kafai@fb.com>
Acked-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
include/linux/btf.h
kernel/bpf/btf.c
kernel/bpf/verifier.c

index a4cf075b89eb17bc1fdaa345123c13aaafead7a9..58000d7e06e36019c9f1b02011ba463163351b92 100644 (file)
@@ -46,7 +46,6 @@ void btf_type_seq_show(const struct btf *btf, u32 type_id, void *obj,
                       struct seq_file *m);
 int btf_get_fd_by_id(u32 id);
 u32 btf_id(const struct btf *btf);
-bool btf_name_offset_valid(const struct btf *btf, u32 offset);
 bool btf_type_is_reg_int(const struct btf_type *t, u32 expected_size);
 
 #ifdef CONFIG_BPF_SYSCALL
index 1545ddfb6fa57bef44510019467f10c84c41e723..8fa0bf1c33fdff712330d38f5d5a93a26354e59a 100644 (file)
@@ -474,7 +474,7 @@ static bool btf_name_valid_identifier(const struct btf *btf, u32 offset)
        return !*src;
 }
 
-const char *btf_name_by_offset(const struct btf *btf, u32 offset)
+static const char *__btf_name_by_offset(const struct btf *btf, u32 offset)
 {
        if (!offset)
                return "(anon)";
@@ -484,6 +484,14 @@ const char *btf_name_by_offset(const struct btf *btf, u32 offset)
                return "(invalid-name-offset)";
 }
 
+const char *btf_name_by_offset(const struct btf *btf, u32 offset)
+{
+       if (offset < btf->hdr.str_len)
+               return &btf->strings[offset];
+
+       return NULL;
+}
+
 const struct btf_type *btf_type_by_id(const struct btf *btf, u32 type_id)
 {
        if (type_id > btf->nr_types)
@@ -576,7 +584,7 @@ __printf(4, 5) static void __btf_verifier_log_type(struct btf_verifier_env *env,
        __btf_verifier_log(log, "[%u] %s %s%s",
                           env->log_type_id,
                           btf_kind_str[kind],
-                          btf_name_by_offset(btf, t->name_off),
+                          __btf_name_by_offset(btf, t->name_off),
                           log_details ? " " : "");
 
        if (log_details)
@@ -620,7 +628,7 @@ static void btf_verifier_log_member(struct btf_verifier_env *env,
                btf_verifier_log_type(env, struct_type, NULL);
 
        __btf_verifier_log(log, "\t%s type_id=%u bits_offset=%u",
-                          btf_name_by_offset(btf, member->name_off),
+                          __btf_name_by_offset(btf, member->name_off),
                           member->type, member->offset);
 
        if (fmt && *fmt) {
@@ -1872,7 +1880,7 @@ static s32 btf_enum_check_meta(struct btf_verifier_env *env,
 
 
                btf_verifier_log(env, "\t%s val=%d\n",
-                                btf_name_by_offset(btf, enums[i].name_off),
+                                __btf_name_by_offset(btf, enums[i].name_off),
                                 enums[i].val);
        }
 
@@ -1896,7 +1904,8 @@ static void btf_enum_seq_show(const struct btf *btf, const struct btf_type *t,
        for (i = 0; i < nr_enums; i++) {
                if (v == enums[i].val) {
                        seq_printf(m, "%s",
-                                  btf_name_by_offset(btf, enums[i].name_off));
+                                  __btf_name_by_offset(btf,
+                                                       enums[i].name_off));
                        return;
                }
        }
@@ -1954,20 +1963,20 @@ static void btf_func_proto_log(struct btf_verifier_env *env,
        }
 
        btf_verifier_log(env, "%u %s", args[0].type,
-                        btf_name_by_offset(env->btf,
-                                           args[0].name_off));
+                        __btf_name_by_offset(env->btf,
+                                             args[0].name_off));
        for (i = 1; i < nr_args - 1; i++)
                btf_verifier_log(env, ", %u %s", args[i].type,
-                                btf_name_by_offset(env->btf,
-                                                   args[i].name_off));
+                                __btf_name_by_offset(env->btf,
+                                                     args[i].name_off));
 
        if (nr_args > 1) {
                const struct btf_param *last_arg = &args[nr_args - 1];
 
                if (last_arg->type)
                        btf_verifier_log(env, ", %u %s", last_arg->type,
-                                        btf_name_by_offset(env->btf,
-                                                           last_arg->name_off));
+                                        __btf_name_by_offset(env->btf,
+                                                             last_arg->name_off));
                else
                        btf_verifier_log(env, ", vararg");
        }
index 8b511a4fe84ad932d4ce7a34b5b0b1651aa55b5e..89ce2613fdb0617d349d131557664939bf4cb0cb 100644 (file)
@@ -4910,8 +4910,8 @@ static int check_btf_line(struct bpf_verifier_env *env,
                        goto err_free;
                }
 
-               if (!btf_name_offset_valid(btf, linfo[i].line_off) ||
-                   !btf_name_offset_valid(btf, linfo[i].file_name_off)) {
+               if (!btf_name_by_offset(btf, linfo[i].line_off) ||
+                   !btf_name_by_offset(btf, linfo[i].file_name_off)) {
                        verbose(env, "Invalid line_info[%u].line_off or .file_name_off\n", i);
                        err = -EINVAL;
                        goto err_free;