Re: [PATCH bpf-next 07/10] libbpf: refactor CO-RE relo human description formatting routine

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Apr 25, 2022 at 05:45:08PM -0700, Andrii Nakryiko wrote:
> Refactor how CO-RE relocation is formatted. Now it dumps human-readable
> representation, currently used by libbpf in either debug or error
> message output during CO-RE relocation resolution process, into provided
> buffer. This approach allows for better reuse of this functionality
> outside of CO-RE relocation resolution, which we'll use in next patch
> for providing better error message for BPF verifier rejecting BPF
> program due to unguarded failed CO-RE relocation.
> 
> It also gets rid of annoying "stitching" of libbpf_print() calls, which
> was the only place where we did this.
> 
> Signed-off-by: Andrii Nakryiko <andrii@xxxxxxxxxx>
> ---
>  tools/lib/bpf/relo_core.c | 64 +++++++++++++++++++++++----------------
>  1 file changed, 38 insertions(+), 26 deletions(-)
> 
> diff --git a/tools/lib/bpf/relo_core.c b/tools/lib/bpf/relo_core.c
> index adaa22160692..13d36a705464 100644
> --- a/tools/lib/bpf/relo_core.c
> +++ b/tools/lib/bpf/relo_core.c
> @@ -1055,51 +1055,66 @@ int bpf_core_patch_insn(const char *prog_name, struct bpf_insn *insn,
>   * [<type-id>] (<type-name>) + <raw-spec> => <offset>@<spec>,
>   * where <spec> is a C-syntax view of recorded field access, e.g.: x.a[3].b
>   */
> -static void bpf_core_dump_spec(const char *prog_name, int level, const struct bpf_core_spec *spec)
> +static int bpf_core_format_spec(char *buf, size_t buf_sz, const struct bpf_core_spec *spec)
>  {
>  	const struct btf_type *t;
>  	const struct btf_enum *e;
>  	const char *s;
>  	__u32 type_id;
> -	int i;
> +	int i, len = 0;
> +
> +#define append_buf(fmt, args...)				\
> +	({							\
> +		int r;						\
> +		r = snprintf(buf, buf_sz, fmt, ##args);		\
> +		len += r;					\
> +		if (r >= buf_sz)				\

Do we need to check for r<0 here too or it's highly unlikely?

> +			r = buf_sz;				\
> +		buf += r;					\
> +		buf_sz -= r;					\
> +	})
>  
>  	type_id = spec->root_type_id;
>  	t = btf_type_by_id(spec->btf, type_id);
>  	s = btf__name_by_offset(spec->btf, t->name_off);
>  
> -	libbpf_print(level, "[%u] %s %s", type_id, btf_kind_str(t), str_is_empty(s) ? "<anon>" : s);
> +	append_buf("<%s> [%u] %s %s",
> +		   core_relo_kind_str(spec->relo_kind),
> +		   type_id, btf_kind_str(t), str_is_empty(s) ? "<anon>" : s);
>  
>  	if (core_relo_is_type_based(spec->relo_kind))
> -		return;
> +		return len;
>  
>  	if (core_relo_is_enumval_based(spec->relo_kind)) {
>  		t = skip_mods_and_typedefs(spec->btf, type_id, NULL);
>  		e = btf_enum(t) + spec->raw_spec[0];
>  		s = btf__name_by_offset(spec->btf, e->name_off);
>  
> -		libbpf_print(level, "::%s = %u", s, e->val);
> -		return;
> +		append_buf("::%s = %u", s, e->val);
> +		return len;
>  	}
>  
>  	if (core_relo_is_field_based(spec->relo_kind)) {
>  		for (i = 0; i < spec->len; i++) {
>  			if (spec->spec[i].name)
> -				libbpf_print(level, ".%s", spec->spec[i].name);
> +				append_buf(".%s", spec->spec[i].name);
>  			else if (i > 0 || spec->spec[i].idx > 0)
> -				libbpf_print(level, "[%u]", spec->spec[i].idx);
> +				append_buf("[%u]", spec->spec[i].idx);
>  		}
>  
> -		libbpf_print(level, " (");
> +		append_buf(" (");
>  		for (i = 0; i < spec->raw_len; i++)
> -			libbpf_print(level, "%s%d", i == 0 ? "" : ":", spec->raw_spec[i]);
> +			append_buf("%s%d", i == 0 ? "" : ":", spec->raw_spec[i]);
>  
>  		if (spec->bit_offset % 8)
> -			libbpf_print(level, " @ offset %u.%u)",
> -				     spec->bit_offset / 8, spec->bit_offset % 8);
> +			append_buf(" @ offset %u.%u)", spec->bit_offset / 8, spec->bit_offset % 8);
>  		else
> -			libbpf_print(level, " @ offset %u)", spec->bit_offset / 8);
> -		return;
> +			append_buf(" @ offset %u)", spec->bit_offset / 8);
> +		return len;
>  	}
> +
> +	return len;
> +#undef append_buf
>  }
>  
>  /*
> @@ -1168,6 +1183,7 @@ int bpf_core_calc_relo_insn(const char *prog_name,
>  	const char *local_name;
>  	__u32 local_id;
>  	const char *spec_str;
> +	char spec_buf[256];
>  	int i, j, err;
>  
>  	local_id = relo->type_id;
> @@ -1190,10 +1206,8 @@ int bpf_core_calc_relo_insn(const char *prog_name,
>  		return -EINVAL;
>  	}
>  
> -	pr_debug("prog '%s': relo #%d: kind <%s> (%d), spec is ", prog_name,
> -		 relo_idx, core_relo_kind_str(relo->kind), relo->kind);
> -	bpf_core_dump_spec(prog_name, LIBBPF_DEBUG, local_spec);
> -	libbpf_print(LIBBPF_DEBUG, "\n");
> +	bpf_core_format_spec(spec_buf, sizeof(spec_buf), local_spec);
> +	pr_debug("prog '%s': relo #%d: %s\n", prog_name, relo_idx, spec_buf);

Looks great, but return value 'len' doesn't seem to be used in this
patch or in the following patch.
What was the intent ?



[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux