libbpf: Keep format strings of bpf_printk() in .rodata.str

bpf_printk(), BPF_SNPRINTF(), BPF_SEQ_PRINTF() and bpf_stream_printk()
copy the format into a static const array, which the compiler puts into
.rodata. When global data of the object is in arena .rodata is there
too and the helper doesn't take the format:

  R1 type=scalar expected=fp, pkt, pkt_meta, map_key, map_value, mem,
  ringbuf_mem, buf, trusted_ptr_, ctx

String literals are in .rodata.str1.1, which libbpf keeps in a read-only
map. No compiler flag moves a named array there. Put the arrays into
.rodata.str with a section attribute.

An object that uses the macros gets one more map, .rodata.str.

Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20261002124714.180012-14-alexei.starovoitov@gmail.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
This commit is contained in:
Alexei Starovoitov 2026-10-02 12:47:12 +00:00 committed by Kumar Kartikeya Dwivedi
parent 8ab58ed42b
commit 373e1223ff
No known key found for this signature in database
GPG Key ID: 472D377B63542F83

View File

@ -248,13 +248,21 @@ enum libbpf_tristate {
#define ___bpf_fill(arr, args...) \
___bpf_apply(___bpf_fill, ___bpf_narg(args))(arr, 0, args)
/*
* Format strings are in a section of their own. When global data of the object
* is in arena (the object has .arena.data section) libbpf keeps .rodata.str*
* sections in read-only maps, which is where helpers and kfuncs take strings
* from.
*/
#define ___bpf_fmt_sec __attribute__((section(".rodata.str")))
/*
* BPF_SEQ_PRINTF to wrap bpf_seq_printf to-be-printed values
* in a structure.
*/
#define BPF_SEQ_PRINTF(seq, fmt, args...) \
({ \
static const char ___fmt[] = fmt; \
static const char ___fmt[] ___bpf_fmt_sec = fmt; \
unsigned long long ___param[___bpf_narg(args)]; \
\
_Pragma("GCC diagnostic push") \
@ -272,7 +280,7 @@ enum libbpf_tristate {
*/
#define BPF_SNPRINTF(out, out_size, fmt, args...) \
({ \
static const char ___fmt[] = fmt; \
static const char ___fmt[] ___bpf_fmt_sec = fmt; \
unsigned long long ___param[___bpf_narg(args)]; \
\
_Pragma("GCC diagnostic push") \
@ -287,7 +295,7 @@ enum libbpf_tristate {
#ifdef BPF_NO_GLOBAL_DATA
#define BPF_PRINTK_FMT_MOD
#else
#define BPF_PRINTK_FMT_MOD static const
#define BPF_PRINTK_FMT_MOD static const ___bpf_fmt_sec
#endif
#define __bpf_printk(fmt, ...) \
@ -303,7 +311,7 @@ enum libbpf_tristate {
*/
#define __bpf_vprintk(fmt, args...) \
({ \
static const char ___fmt[] = fmt; \
static const char ___fmt[] ___bpf_fmt_sec = fmt; \
unsigned long long ___param[___bpf_narg(args)]; \
\
_Pragma("GCC diagnostic push") \
@ -317,7 +325,7 @@ enum libbpf_tristate {
#define bpf_stream_printk(stream_id, fmt, args...) \
({ \
static const char ___fmt[] = fmt; \
static const char ___fmt[] ___bpf_fmt_sec = fmt; \
unsigned long long ___param[___bpf_narg(args)]; \
\
_Pragma("GCC diagnostic push") \