Message ID | 20210324022211.1718762-5-revest@chromium.org (mailing list archive) |
---|---|
State | Changes Requested |
Delegated to: | BPF |
Headers | show |
Series | Add a snprintf eBPF helper | expand |
On Tue, Mar 23, 2021 at 7:23 PM Florent Revest <revest@chromium.org> wrote: > > When initializing the __param array with a one liner, if all args are > const, the initial array value will be placed in the rodata section but > because libbpf does not support relocation in the rodata section, any > pointer in this array will stay NULL. > > Fixes: c09add2fbc5a ("tools/libbpf: Add bpf_iter support") > Signed-off-by: Florent Revest <revest@chromium.org> > --- > tools/lib/bpf/bpf_tracing.h | 26 ++++++++++++++++++++++---- > 1 file changed, 22 insertions(+), 4 deletions(-) > > diff --git a/tools/lib/bpf/bpf_tracing.h b/tools/lib/bpf/bpf_tracing.h > index f9ef37707888..d9a4c3f77ff4 100644 > --- a/tools/lib/bpf/bpf_tracing.h > +++ b/tools/lib/bpf/bpf_tracing.h > @@ -413,6 +413,22 @@ typeof(name(0)) name(struct pt_regs *ctx) \ > } \ > static __always_inline typeof(name(0)) ____##name(struct pt_regs *ctx, ##args) > > +#define ___bpf_fill0(arr, p, x) can you please double-check that no-argument BPF_SEQ_PRINTF won't generate a warning about spurious ';'? Maybe it's better to have zero case as `do {} while(0);` ? > +#define ___bpf_fill1(arr, p, x) arr[p] = x > +#define ___bpf_fill2(arr, p, x, args...) arr[p] = x; ___bpf_fill1(arr, p + 1, args) > +#define ___bpf_fill3(arr, p, x, args...) arr[p] = x; ___bpf_fill2(arr, p + 1, args) > +#define ___bpf_fill4(arr, p, x, args...) arr[p] = x; ___bpf_fill3(arr, p + 1, args) > +#define ___bpf_fill5(arr, p, x, args...) arr[p] = x; ___bpf_fill4(arr, p + 1, args) > +#define ___bpf_fill6(arr, p, x, args...) arr[p] = x; ___bpf_fill5(arr, p + 1, args) > +#define ___bpf_fill7(arr, p, x, args...) arr[p] = x; ___bpf_fill6(arr, p + 1, args) > +#define ___bpf_fill8(arr, p, x, args...) arr[p] = x; ___bpf_fill7(arr, p + 1, args) > +#define ___bpf_fill9(arr, p, x, args...) arr[p] = x; ___bpf_fill8(arr, p + 1, args) > +#define ___bpf_fill10(arr, p, x, args...) arr[p] = x; ___bpf_fill9(arr, p + 1, args) > +#define ___bpf_fill11(arr, p, x, args...) arr[p] = x; ___bpf_fill10(arr, p + 1, args) > +#define ___bpf_fill12(arr, p, x, args...) arr[p] = x; ___bpf_fill11(arr, p + 1, args) > +#define ___bpf_fill(arr, args...) \ > + ___bpf_apply(___bpf_fill, ___bpf_narg(args))(arr, 0, args) cool. this is regular enough to easily comprehend :) > + > /* > * BPF_SEQ_PRINTF to wrap bpf_seq_printf to-be-printed values > * in a structure. > @@ -421,12 +437,14 @@ static __always_inline typeof(name(0)) ____##name(struct pt_regs *ctx, ##args) > ({ \ > _Pragma("GCC diagnostic push") \ > _Pragma("GCC diagnostic ignored \"-Wint-conversion\"") \ > + unsigned long long ___param[___bpf_narg(args)]; \ > static const char ___fmt[] = fmt; \ > - unsigned long long ___param[] = { args }; \ > + int __ret; \ > + ___bpf_fill(___param, args); \ > _Pragma("GCC diagnostic pop") \ Let's clean this up a little bit; 1. static const char ___fmt should be the very first 2. _Pragma scope should be minimal necessary, which includes only ___bpf_fill, right? 3. Empty line after int __ret; and let's keep three underscores for consistency. > - int ___ret = bpf_seq_printf(seq, ___fmt, sizeof(___fmt), \ > - ___param, sizeof(___param)); \ > - ___ret; \ > + __ret = bpf_seq_printf(seq, ___fmt, sizeof(___fmt), \ > + ___param, sizeof(___param)); \ > + __ret; \ but actually you don't need __ret at all, just bpf_seq_printf() here, right? > }) > > #endif > -- > 2.31.0.291.g576ba9dcdaf-goog >
On Sat, Mar 27, 2021 at 12:01 AM Andrii Nakryiko <andrii.nakryiko@gmail.com> wrote: > > On Tue, Mar 23, 2021 at 7:23 PM Florent Revest <revest@chromium.org> wrote: > > > > When initializing the __param array with a one liner, if all args are > > const, the initial array value will be placed in the rodata section but > > because libbpf does not support relocation in the rodata section, any > > pointer in this array will stay NULL. > > > > Fixes: c09add2fbc5a ("tools/libbpf: Add bpf_iter support") > > Signed-off-by: Florent Revest <revest@chromium.org> > > --- > > tools/lib/bpf/bpf_tracing.h | 26 ++++++++++++++++++++++---- > > 1 file changed, 22 insertions(+), 4 deletions(-) > > > > diff --git a/tools/lib/bpf/bpf_tracing.h b/tools/lib/bpf/bpf_tracing.h > > index f9ef37707888..d9a4c3f77ff4 100644 > > --- a/tools/lib/bpf/bpf_tracing.h > > +++ b/tools/lib/bpf/bpf_tracing.h > > @@ -413,6 +413,22 @@ typeof(name(0)) name(struct pt_regs *ctx) \ > > } \ > > static __always_inline typeof(name(0)) ____##name(struct pt_regs *ctx, ##args) > > > > +#define ___bpf_fill0(arr, p, x) > > can you please double-check that no-argument BPF_SEQ_PRINTF won't > generate a warning about spurious ';'? Maybe it's better to have zero > case as `do {} while(0);` ? > > > +#define ___bpf_fill1(arr, p, x) arr[p] = x > > +#define ___bpf_fill2(arr, p, x, args...) arr[p] = x; ___bpf_fill1(arr, p + 1, args) > > +#define ___bpf_fill3(arr, p, x, args...) arr[p] = x; ___bpf_fill2(arr, p + 1, args) > > +#define ___bpf_fill4(arr, p, x, args...) arr[p] = x; ___bpf_fill3(arr, p + 1, args) > > +#define ___bpf_fill5(arr, p, x, args...) arr[p] = x; ___bpf_fill4(arr, p + 1, args) > > +#define ___bpf_fill6(arr, p, x, args...) arr[p] = x; ___bpf_fill5(arr, p + 1, args) > > +#define ___bpf_fill7(arr, p, x, args...) arr[p] = x; ___bpf_fill6(arr, p + 1, args) > > +#define ___bpf_fill8(arr, p, x, args...) arr[p] = x; ___bpf_fill7(arr, p + 1, args) > > +#define ___bpf_fill9(arr, p, x, args...) arr[p] = x; ___bpf_fill8(arr, p + 1, args) > > +#define ___bpf_fill10(arr, p, x, args...) arr[p] = x; ___bpf_fill9(arr, p + 1, args) > > +#define ___bpf_fill11(arr, p, x, args...) arr[p] = x; ___bpf_fill10(arr, p + 1, args) > > +#define ___bpf_fill12(arr, p, x, args...) arr[p] = x; ___bpf_fill11(arr, p + 1, args) > > +#define ___bpf_fill(arr, args...) \ > > + ___bpf_apply(___bpf_fill, ___bpf_narg(args))(arr, 0, args) > > cool. this is regular enough to easily comprehend :) > > > + > > /* > > * BPF_SEQ_PRINTF to wrap bpf_seq_printf to-be-printed values > > * in a structure. > > @@ -421,12 +437,14 @@ static __always_inline typeof(name(0)) ____##name(struct pt_regs *ctx, ##args) > > ({ \ > > _Pragma("GCC diagnostic push") \ > > _Pragma("GCC diagnostic ignored \"-Wint-conversion\"") \ > > + unsigned long long ___param[___bpf_narg(args)]; \ > > static const char ___fmt[] = fmt; \ > > - unsigned long long ___param[] = { args }; \ > > + int __ret; \ > > + ___bpf_fill(___param, args); \ > > _Pragma("GCC diagnostic pop") \ > > Let's clean this up a little bit; > 1. static const char ___fmt should be the very first > 2. _Pragma scope should be minimal necessary, which includes only > ___bpf_fill, right? > 3. Empty line after int __ret; and let's keep three underscores for consistency. > > > > - int ___ret = bpf_seq_printf(seq, ___fmt, sizeof(___fmt), \ > > - ___param, sizeof(___param)); \ > > - ___ret; \ > > + __ret = bpf_seq_printf(seq, ___fmt, sizeof(___fmt), \ > > + ___param, sizeof(___param)); \ > > + __ret; \ > > but actually you don't need __ret at all, just bpf_seq_printf() here, right? Agreed with everything and also the indentation comment in 5/6, thanks.
diff --git a/tools/lib/bpf/bpf_tracing.h b/tools/lib/bpf/bpf_tracing.h index f9ef37707888..d9a4c3f77ff4 100644 --- a/tools/lib/bpf/bpf_tracing.h +++ b/tools/lib/bpf/bpf_tracing.h @@ -413,6 +413,22 @@ typeof(name(0)) name(struct pt_regs *ctx) \ } \ static __always_inline typeof(name(0)) ____##name(struct pt_regs *ctx, ##args) +#define ___bpf_fill0(arr, p, x) +#define ___bpf_fill1(arr, p, x) arr[p] = x +#define ___bpf_fill2(arr, p, x, args...) arr[p] = x; ___bpf_fill1(arr, p + 1, args) +#define ___bpf_fill3(arr, p, x, args...) arr[p] = x; ___bpf_fill2(arr, p + 1, args) +#define ___bpf_fill4(arr, p, x, args...) arr[p] = x; ___bpf_fill3(arr, p + 1, args) +#define ___bpf_fill5(arr, p, x, args...) arr[p] = x; ___bpf_fill4(arr, p + 1, args) +#define ___bpf_fill6(arr, p, x, args...) arr[p] = x; ___bpf_fill5(arr, p + 1, args) +#define ___bpf_fill7(arr, p, x, args...) arr[p] = x; ___bpf_fill6(arr, p + 1, args) +#define ___bpf_fill8(arr, p, x, args...) arr[p] = x; ___bpf_fill7(arr, p + 1, args) +#define ___bpf_fill9(arr, p, x, args...) arr[p] = x; ___bpf_fill8(arr, p + 1, args) +#define ___bpf_fill10(arr, p, x, args...) arr[p] = x; ___bpf_fill9(arr, p + 1, args) +#define ___bpf_fill11(arr, p, x, args...) arr[p] = x; ___bpf_fill10(arr, p + 1, args) +#define ___bpf_fill12(arr, p, x, args...) arr[p] = x; ___bpf_fill11(arr, p + 1, args) +#define ___bpf_fill(arr, args...) \ + ___bpf_apply(___bpf_fill, ___bpf_narg(args))(arr, 0, args) + /* * BPF_SEQ_PRINTF to wrap bpf_seq_printf to-be-printed values * in a structure. @@ -421,12 +437,14 @@ static __always_inline typeof(name(0)) ____##name(struct pt_regs *ctx, ##args) ({ \ _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wint-conversion\"") \ + unsigned long long ___param[___bpf_narg(args)]; \ static const char ___fmt[] = fmt; \ - unsigned long long ___param[] = { args }; \ + int __ret; \ + ___bpf_fill(___param, args); \ _Pragma("GCC diagnostic pop") \ - int ___ret = bpf_seq_printf(seq, ___fmt, sizeof(___fmt), \ - ___param, sizeof(___param)); \ - ___ret; \ + __ret = bpf_seq_printf(seq, ___fmt, sizeof(___fmt), \ + ___param, sizeof(___param)); \ + __ret; \ }) #endif
When initializing the __param array with a one liner, if all args are const, the initial array value will be placed in the rodata section but because libbpf does not support relocation in the rodata section, any pointer in this array will stay NULL. Fixes: c09add2fbc5a ("tools/libbpf: Add bpf_iter support") Signed-off-by: Florent Revest <revest@chromium.org> --- tools/lib/bpf/bpf_tracing.h | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-)