All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alan Maguire <alan.maguire@oracle.com>
To: Alexei Starovoitov <alexei.starovoitov@gmail.com>, bpf@vger.kernel.org
Cc: daniel@iogearbox.net, andrii@kernel.org, eddyz87@gmail.com,
	memxor@gmail.com
Subject: Re: [PATCH bpf-next 05/14] bpf: Allow names of Rust types and functions in BTF
Date: Thu, 1 Oct 2026 18:42:09 +0100	[thread overview]
Message-ID: <82f7ccc5-da2a-4b78-a10a-442acfac1855@oracle.com> (raw)
In-Reply-To: <20260930193127.2181684-6-alexei.starovoitov@gmail.com>

On 30/09/2026 20:31, Alexei Starovoitov wrote:
> From: Alexei Starovoitov <ast@kernel.org>
> 
> Names of types and functions in BTF that LLVM makes for a Rust program
> are not C identifiers:
> 
>   [69] STRUCT 'NonNull<str>' size=16 vlen=1
>   [147] FUNC 'write_fmt<scx_cosmos::BpfStream>' type_id=146
> 
> and the kernel rejects such BTF with "Invalid name". scx_simple and
> scx_cosmos schedulers written in Rust have them in STRUCT, FWD and FUNC,
> made of letters, digits and " #&()*,:;<>[]{}", 430 characters at most.
> 
> Allow any printable character in btf_name_valid_identifier(), like it's
> done for DATASEC. It checks names of types, functions, members,
> enumerators, variables and arguments, so all of them can have such
> characters now. The limit of KSYM_NAME_LEN stays.
> 
> The name of FUNC is a part of the name of the program in kallsyms, where
> a space would break the parsers. Replace what is not a character of
> an identifier with '_' there.

One idea I've been experimenting with for pahole-generated BTF is to
retain a more friendly rust-centric name, while keeping the kallsyms name
(which is name-mangled) in a structured BTF decl tag pointing at it [1]. 
The idea is that for tracing rust functions you could specify the rust name
(from DWARF DW_AT_name) in the SEC(), but to map to the actual symbol
address in kallsyms the decl tag that referenced that function could use 
the DW_AT_linkage name.

So the decl tag would have the form 

<lang>:linkage:<linkage-symbol>

and it would reference the FUNC type id.

Could we do similar here for the name -> symbol mapping?

[1] https://github.com/acmel/dwarves/commit/a14b368960635b30b188a899a1245143df53e70b



> 
> Tests in prog_tests/btf.c expect "Invalid name" for names with '!' and
> '*', which are valid now. Put a character that is not printable there.
> The type name '?foo' is expected to load.
> 
> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
> ---
>  kernel/bpf/btf.c                             | 15 ++----
>  kernel/bpf/core.c                            |  5 ++
>  tools/testing/selftests/bpf/prog_tests/btf.c | 52 ++++++++++----------
>  3 files changed, 33 insertions(+), 39 deletions(-)
> 
> diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
> index 8cc17a1cd25c..d27af5d8e495 100644
> --- a/kernel/bpf/btf.c
> +++ b/kernel/bpf/btf.c
> @@ -901,16 +901,6 @@ static bool btf_name_offset_valid(const struct btf *btf, u32 offset)
>  	return offset < btf->hdr.str_len;
>  }
>  
> -static bool __btf_name_char_ok(char c, bool first)
> -{
> -	if ((first ? !isalpha(c) :
> -		     !isalnum(c)) &&
> -	    c != '_' &&
> -	    c != '.')
> -		return false;
> -	return true;
> -}
> -
>  const char *btf_str_by_offset(const struct btf *btf, u32 offset)
>  {
>  	while (offset < btf->start_str_off)
> @@ -923,20 +913,21 @@ const char *btf_str_by_offset(const struct btf *btf, u32 offset)
>  	return NULL;
>  }
>  
> +/* Names in BTF of Rust are not C identifiers. Allow any printable character */
>  static bool btf_name_valid_identifier(const struct btf *btf, u32 offset)
>  {
>  	/* offset must be valid */
>  	const char *src = btf_str_by_offset(btf, offset);
>  	const char *src_limit;
>  
> -	if (!__btf_name_char_ok(*src, true))
> +	if (!isprint(*src))
>  		return false;
>  
>  	/* set a limit on identifier length */
>  	src_limit = src + KSYM_NAME_LEN;
>  	src++;
>  	while (*src && src < src_limit) {
> -		if (!__btf_name_char_ok(*src, false))
> +		if (!isprint(*src))
>  			return false;
>  		src++;
>  	}
> diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
> index a1721f9c0f52..36900b02d668 100644
> --- a/kernel/bpf/core.c
> +++ b/kernel/bpf/core.c
> @@ -18,6 +18,7 @@
>   */
>  
>  #include <uapi/linux/btf.h>
> +#include <linux/ctype.h>
>  #include <linux/filter.h>
>  #include <linux/sched/signal.h>
>  #include <linux/skbuff.h>
> @@ -589,6 +590,10 @@ bpf_prog_ksym_set_name(struct bpf_prog *prog)
>  				      prog->aux->func_info[prog->aux->func_idx].type_id);
>  		func_name = btf_name_by_offset(prog->aux->btf, type->name_off);
>  		snprintf(sym, (size_t)(end - sym), "_%s", func_name);
> +		/* the name of a function of Rust is not an identifier */
> +		for (; *sym; sym++)
> +			if (!isalnum(*sym) && *sym != '_' && *sym != '.')
> +				*sym = '_';
>  		return;
>  	}
>  
> diff --git a/tools/testing/selftests/bpf/prog_tests/btf.c b/tools/testing/selftests/bpf/prog_tests/btf.c
> index df6ad38d287d..87b554067071 100644
> --- a/tools/testing/selftests/bpf/prog_tests/btf.c
> +++ b/tools/testing/selftests/bpf/prog_tests/btf.c
> @@ -1987,14 +1987,14 @@ static struct btf_raw_test raw_tests[] = {
>  },
>  
>  {
> -	.descr = "typedef (invalid name, invalid identifier)",
> +	.descr = "typedef (invalid name, not printable)",
>  	.raw_types = {
>  		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
>  		BTF_TYPEDEF_ENC(NAME_TBD, 1),			/* [2] */
>  		BTF_END_RAW,
>  	},
> -	.str_sec = "\0__!int",
> -	.str_sec_size = sizeof("\0__!int"),
> +	.str_sec = "\0__\7int",
> +	.str_sec_size = sizeof("\0__\7int"),
>  	.map_type = BPF_MAP_TYPE_ARRAY,
>  	.map_name = "typedef_check_btf",
>  	.key_size = sizeof(int),
> @@ -2112,15 +2112,15 @@ static struct btf_raw_test raw_tests[] = {
>  },
>  
>  {
> -	.descr = "fwd type (invalid name, invalid identifier)",
> +	.descr = "fwd type (invalid name, not printable)",
>  	.raw_types = {
>  		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),		/* [1] */
>  		BTF_TYPE_ENC(NAME_TBD,
>  			     BTF_INFO_ENC(BTF_KIND_FWD, 0, 0), 0),	/* [2] */
>  		BTF_END_RAW,
>  	},
> -	.str_sec = "\0__!skb",
> -	.str_sec_size = sizeof("\0__!skb"),
> +	.str_sec = "\0__\7skb",
> +	.str_sec_size = sizeof("\0__\7skb"),
>  	.map_type = BPF_MAP_TYPE_ARRAY,
>  	.map_name = "fwd_type_check_btf",
>  	.key_size = sizeof(int),
> @@ -2175,7 +2175,7 @@ static struct btf_raw_test raw_tests[] = {
>  },
>  
>  {
> -	.descr = "struct type (invalid name, invalid identifier)",
> +	.descr = "struct type (invalid name, not printable)",
>  	.raw_types = {
>  		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),		/* [1] */
>  		BTF_TYPE_ENC(NAME_TBD,
> @@ -2183,8 +2183,8 @@ static struct btf_raw_test raw_tests[] = {
>  		BTF_MEMBER_ENC(NAME_TBD, 1, 0),
>  		BTF_END_RAW,
>  	},
> -	.str_sec = "\0A!\0B",
> -	.str_sec_size = sizeof("\0A!\0B"),
> +	.str_sec = "\0A\7\0B",
> +	.str_sec_size = sizeof("\0A\7\0B"),
>  	.map_type = BPF_MAP_TYPE_ARRAY,
>  	.map_name = "struct_type_check_btf",
>  	.key_size = sizeof(int),
> @@ -2217,7 +2217,7 @@ static struct btf_raw_test raw_tests[] = {
>  },
>  
>  {
> -	.descr = "struct member (invalid name, invalid identifier)",
> +	.descr = "struct member (invalid name, not printable)",
>  	.raw_types = {
>  		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),		/* [1] */
>  		BTF_TYPE_ENC(NAME_TBD,
> @@ -2225,8 +2225,8 @@ static struct btf_raw_test raw_tests[] = {
>  		BTF_MEMBER_ENC(NAME_TBD, 1, 0),
>  		BTF_END_RAW,
>  	},
> -	.str_sec = "\0A\0B*",
> -	.str_sec_size = sizeof("\0A\0B*"),
> +	.str_sec = "\0A\0B\7",
> +	.str_sec_size = sizeof("\0A\0B\7"),
>  	.map_type = BPF_MAP_TYPE_ARRAY,
>  	.map_name = "struct_type_check_btf",
>  	.key_size = sizeof(int),
> @@ -2260,7 +2260,7 @@ static struct btf_raw_test raw_tests[] = {
>  },
>  
>  {
> -	.descr = "enum type (invalid name, invalid identifier)",
> +	.descr = "enum type (invalid name, not printable)",
>  	.raw_types = {
>  		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),		/* [1] */
>  		BTF_TYPE_ENC(NAME_TBD,
> @@ -2269,8 +2269,8 @@ static struct btf_raw_test raw_tests[] = {
>  		BTF_ENUM_ENC(NAME_TBD, 0),
>  		BTF_END_RAW,
>  	},
> -	.str_sec = "\0A!\0B",
> -	.str_sec_size = sizeof("\0A!\0B"),
> +	.str_sec = "\0A\7\0B",
> +	.str_sec_size = sizeof("\0A\7\0B"),
>  	.map_type = BPF_MAP_TYPE_ARRAY,
>  	.map_name = "enum_type_check_btf",
>  	.key_size = sizeof(int),
> @@ -2306,7 +2306,7 @@ static struct btf_raw_test raw_tests[] = {
>  },
>  
>  {
> -	.descr = "enum member (invalid name, invalid identifier)",
> +	.descr = "enum member (invalid name, not printable)",
>  	.raw_types = {
>  		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),		/* [1] */
>  		BTF_TYPE_ENC(0,
> @@ -2315,8 +2315,8 @@ static struct btf_raw_test raw_tests[] = {
>  		BTF_ENUM_ENC(NAME_TBD, 0),
>  		BTF_END_RAW,
>  	},
> -	.str_sec = "\0A!",
> -	.str_sec_size = sizeof("\0A!"),
> +	.str_sec = "\0A\7",
> +	.str_sec_size = sizeof("\0A\7"),
>  	.map_type = BPF_MAP_TYPE_ARRAY,
>  	.map_name = "enum_type_check_btf",
>  	.key_size = sizeof(int),
> @@ -2625,14 +2625,14 @@ static struct btf_raw_test raw_tests[] = {
>  	.raw_types = {
>  		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
>  		BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),		/* [2] */
> -		/* void (*)(int a, unsigned int !!!) */
> +		/* void (*)(int a, unsigned int \7) */
>  		BTF_FUNC_PROTO_ENC(0, 2),			/* [3] */
>  			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
>  			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
>  		BTF_END_RAW,
>  	},
> -	.str_sec = "\0a\0!!!",
> -	.str_sec_size = sizeof("\0a\0!!!"),
> +	.str_sec = "\0a\0\7",
> +	.str_sec_size = sizeof("\0a\0\7"),
>  	.map_type = BPF_MAP_TYPE_ARRAY,
>  	.map_name = "func_proto_type_check_btf",
>  	.key_size = sizeof(int),
> @@ -2775,12 +2775,12 @@ static struct btf_raw_test raw_tests[] = {
>  		BTF_FUNC_PROTO_ENC(0, 2),			/* [3] */
>  			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
>  			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
> -		/* void !!!(int a, unsigned int b) */
> +		/* void \7(int a, unsigned int b) */
>  		BTF_FUNC_ENC(NAME_TBD, 3),			/* [4] */
>  		BTF_END_RAW,
>  	},
> -	.str_sec = "\0a\0b\0!!!",
> -	.str_sec_size = sizeof("\0a\0b\0!!!"),
> +	.str_sec = "\0a\0b\0\7",
> +	.str_sec_size = sizeof("\0a\0b\0\7"),
>  	.map_type = BPF_MAP_TYPE_ARRAY,
>  	.map_name = "func_type_check_btf",
>  	.key_size = sizeof(int),
> @@ -3585,15 +3585,13 @@ static struct btf_raw_test raw_tests[] = {
>  	.btf_load_err = true,
>  },
>  {
> -	.descr = "type name '?foo' is not ok",
> +	.descr = "type name '?foo' is ok",
>  	.raw_types = {
>  		/* union ?foo; */
>  		BTF_TYPE_ENC(1, BTF_INFO_ENC(BTF_KIND_FWD, 1, 0), 0), /* [1] */
>  		BTF_END_RAW,
>  	},
>  	BTF_STR_SEC("\0?foo"),
> -	.err_str = "Invalid name",
> -	.btf_load_err = true,
>  },
>  
>  {


  parent reply	other threads:[~2026-10-01 17:42 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-30 19:31 [PATCH bpf-next 00/14] bpf: Support programs compiled by rust-bpf Alexei Starovoitov
2026-09-30 19:31 ` [PATCH bpf-next 01/14] bpf: Allow bitwise ops, shifts and mul/div on pointers with CAP_PERFMON Alexei Starovoitov
2026-09-30 19:31 ` [PATCH bpf-next 02/14] selftests/bpf: Add tests for ALU " Alexei Starovoitov
2026-09-30 19:31 ` [PATCH bpf-next 03/14] bpf: Treat load and store through a number as arena access Alexei Starovoitov
2026-09-30 19:31 ` [PATCH bpf-next 04/14] selftests/bpf: Add tests for arena access through numbers Alexei Starovoitov
2026-09-30 19:48   ` sashiko-bot
2026-09-30 20:22   ` bot+bpf-ci
2026-09-30 19:31 ` [PATCH bpf-next 05/14] bpf: Allow names of Rust types and functions in BTF Alexei Starovoitov
2026-09-30 20:22   ` bot+bpf-ci
2026-10-01 17:42   ` Alan Maguire [this message]
2026-10-02 12:24     ` Alexei Starovoitov
2026-10-02 13:38       ` Alan Maguire
2026-09-30 19:31 ` [PATCH bpf-next 06/14] selftests/bpf: Add tests for " Alexei Starovoitov
2026-09-30 20:22   ` bot+bpf-ci
2026-09-30 19:31 ` [PATCH bpf-next 07/14] bpf: Allow arguments without names in static " Alexei Starovoitov
2026-10-01 21:14   ` Alan Maguire
2026-09-30 19:31 ` [PATCH bpf-next 08/14] selftests/bpf: Add test for arguments without names in static functions Alexei Starovoitov
2026-10-01 21:22   ` Alan Maguire
2026-09-30 19:31 ` [PATCH bpf-next 09/14] bpf: Allow a variable in DATASEC that is smaller than its type Alexei Starovoitov
2026-09-30 19:47   ` sashiko-bot
2026-09-30 19:31 ` [PATCH bpf-next 10/14] selftests/bpf: Add tests for a variable " Alexei Starovoitov
2026-09-30 19:31 ` [PATCH bpf-next 11/14] libbpf: Keep global data in arena when the object has .arena.data Alexei Starovoitov
2026-09-30 19:46   ` sashiko-bot
2026-09-30 20:22   ` bot+bpf-ci
2026-09-30 19:31 ` [PATCH bpf-next 12/14] libbpf: Keep format strings of bpf_printk() in .rodata.str Alexei Starovoitov
2026-09-30 20:22   ` bot+bpf-ci
2026-09-30 19:31 ` [PATCH bpf-next 13/14] selftests/bpf: Add test for global data in arena Alexei Starovoitov
2026-09-30 20:22   ` bot+bpf-ci
2026-09-30 19:31 ` [PATCH bpf-next 14/14] selftests/bpf: Add test for global data of a program in Rust Alexei Starovoitov
2026-09-30 19:53   ` sashiko-bot
2026-09-30 20:22   ` bot+bpf-ci

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=82f7ccc5-da2a-4b78-a10a-442acfac1855@oracle.com \
    --to=alan.maguire@oracle.com \
    --cc=alexei.starovoitov@gmail.com \
    --cc=andrii@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=eddyz87@gmail.com \
    --cc=memxor@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.