From: Arnaldo Carvalho de Melo <acme@kernel.org>
To: Yonghong Song <yhs@fb.com>
Cc: Arnaldo Carvalho de Melo <arnaldo.melo@gmail.com>,
dwarves@vger.kernel.org, Alexei Starovoitov <ast@kernel.org>,
Andrii Nakryiko <andrii@kernel.org>,
bpf@vger.kernel.org, Daniel Borkmann <daniel@iogearbox.net>,
kernel-team@fb.com
Subject: Re: [PATCH dwarves v3 2/2] btf: Support BTF_KIND_ENUM64
Date: Wed, 29 Jun 2022 16:12:19 -0300 [thread overview]
Message-ID: <YrykE1zgKXvKaAgx@kernel.org> (raw)
In-Reply-To: <20220629071224.3180594-1-yhs@fb.com>
Em Wed, Jun 29, 2022 at 12:12:24AM -0700, Yonghong Song escreveu:
> BTF_KIND_ENUM64 is supported with latest libbpf, which
> supports 64-bit enum values. Latest libbpf also supports
> signedness for enum values. Add enum64 support in
> dwarf-to-btf conversion.
>
> The following is an example of new encoding which covers
> signed/unsigned enum64/enum variations.
So, testing this with torvalds/master I'm getting:
FAILED: load BTF from vmlinux: Invalid argument
make[1]: *** [/var/home/acme/git/linux/Makefile:1164: vmlinux] Error 255
make[1]: *** Deleting file 'vmlinux'
make[1]: Leaving directory '/var/home/acme/git/build/v5.19-rc4+'
make: *** [Makefile:219: __sub-make] Error 2
real 8m12.396s
user 183m18.009s
sys 44m27.085s
⬢[acme@toolbox linux]$ find . -name "*.c" | xargs grep "load BTF from vmlinux"
⬢[acme@toolbox linux]$ find . -name "*.c" | xargs grep "load BTF from"
./tools/bpf/bpftool/btf.c: p_err("failed to load BTF from %s: %s",
./tools/bpf/resolve_btfids/main.c: pr_err("FAILED: load BTF from %s: %s\n",
./tools/testing/selftests/bpf/prog_tests/resolve_btfids.c: "Failed to load BTF from btf_data.o\n"))
⬢[acme@toolbox linux]$ vim ./tools/bpf/resolve_btfids/main.c
Which is:
btf = btf__parse_split(obj->btf ?: obj->path, base_btf);
err = libbpf_get_error(btf);
if (err) {
pr_err("FAILED: load BTF from %s: %s\n",
obj->btf ?: obj->path, strerror(-err));
goto out;
}
I.e. tools/lib/bpf in torvalds/master doesn´t support BTF_KIND_ENUM64,
right? So to build it with a new pahole one needs to ask for
--skip_encoding_btf_enum64? How to do this automagically? I.e. its a
matter of checking if the in-kernel libbpf has support for it and if not
use --skip_encoding_btf_enum64?
I'm now going to try with bpf-next/master
- Arnaldo
> $cat t.c
> enum { /* signed, enum64 */
> A = -1,
> B = 0xffffffff,
> } g1;
> enum { /* unsigned, enum64 */
> C = 1,
> D = 0xfffffffff,
> } g2;
> enum { /* signed, enum */
> E = -1,
> F = 0xfffffff,
> } g3;
> enum { /* unsigned, enum */
> G = 1,
> H = 0xfffffff,
> } g4;
> $ clang -g -c t.c
> $ pahole -JV t.o
> btf_encoder__new: 't.o' doesn't have '.data..percpu' section
> Found 0 per-CPU variables!
> File t.o:
> [1] ENUM64 (anon) size=8
> A val=-1
> B val=4294967295
> [2] INT long size=8 nr_bits=64 encoding=SIGNED
> [3] ENUM64 (anon) size=8
> C val=1
> D val=68719476735
> [4] INT unsigned long size=8 nr_bits=64 encoding=(none)
> [5] ENUM (anon) size=4
> E val=-1
> F val=268435455
> [6] INT int size=4 nr_bits=32 encoding=SIGNED
> [7] ENUM (anon) size=4
> G val=1
> H val=268435455
> [8] INT unsigned int size=4 nr_bits=32 encoding=(none)
>
> With the flag to skip enum64 encoding,
>
> $ pahole -JV t.o --skip_encoding_btf_enum64
> btf_encoder__new: 't.o' doesn't have '.data..percpu' section
> Found 0 per-CPU variables!
> File t.o:
> [1] ENUM (anon) size=8
> A val=4294967295
> B val=4294967295
> [2] INT long size=8 nr_bits=64 encoding=SIGNED
> [3] ENUM (anon) size=8
> C val=1
> D val=4294967295
> [4] INT unsigned long size=8 nr_bits=64 encoding=(none)
> [5] ENUM (anon) size=4
> E val=4294967295
> F val=268435455
> [6] INT int size=4 nr_bits=32 encoding=SIGNED
> [7] ENUM (anon) size=4
> G val=1
> H val=268435455
> [8] INT unsigned int size=4 nr_bits=32 encoding=(none)
>
> In the above btf encoding without enum64, all enum types
> with the same type size as the corresponding enum64. All these
> enum types have unsigned type (kflag = 0) which is required
> before kernel enum64 support.
>
> Acked-by: Andrii Nakryiko <andrii@kernel.org>
> Signed-off-by: Yonghong Song <yhs@fb.com>
> ---
> btf_encoder.c | 67 +++++++++++++++++++++++++++++++++++------------
> btf_encoder.h | 2 +-
> dwarf_loader.c | 12 +++++++++
> dwarves.h | 4 ++-
> dwarves_fprintf.c | 6 ++++-
> pahole.c | 10 ++++++-
> 6 files changed, 80 insertions(+), 21 deletions(-)
>
> diff --git a/btf_encoder.c b/btf_encoder.c
> index 9e708e4..daa8e3b 100644
> --- a/btf_encoder.c
> +++ b/btf_encoder.c
> @@ -144,6 +144,7 @@ static const char * const btf_kind_str[NR_BTF_KINDS] = {
> [BTF_KIND_FLOAT] = "FLOAT",
> [BTF_KIND_DECL_TAG] = "DECL_TAG",
> [BTF_KIND_TYPE_TAG] = "TYPE_TAG",
> + [BTF_KIND_ENUM64] = "ENUM64",
> };
>
> static const char *btf__printable_name(const struct btf *btf, uint32_t offset)
> @@ -490,34 +491,64 @@ static int32_t btf_encoder__add_struct(struct btf_encoder *encoder, uint8_t kind
> return id;
> }
>
> -static int32_t btf_encoder__add_enum(struct btf_encoder *encoder, const char *name, uint32_t bit_size)
> +static int32_t btf_encoder__add_enum(struct btf_encoder *encoder, const char *name, struct type *etype,
> + struct conf_load *conf_load)
> {
> struct btf *btf = encoder->btf;
> const struct btf_type *t;
> int32_t id, size;
> + bool is_enum32;
>
> - size = BITS_ROUNDUP_BYTES(bit_size);
> - id = btf__add_enum(btf, name, size);
> + size = BITS_ROUNDUP_BYTES(etype->size);
> + is_enum32 = size <= 4 || conf_load->skip_encoding_btf_enum64;
> + if (is_enum32)
> + id = btf__add_enum(btf, name, size);
> + else
> + id = btf__add_enum64(btf, name, size, etype->is_signed_enum);
> if (id > 0) {
> t = btf__type_by_id(btf, id);
> btf_encoder__log_type(encoder, t, false, true, "size=%u", t->size);
> } else {
> - btf__log_err(btf, BTF_KIND_ENUM, name, true,
> + btf__log_err(btf, is_enum32 ? BTF_KIND_ENUM : BTF_KIND_ENUM64, name, true,
> "size=%u Error emitting BTF type", size);
> }
> return id;
> }
>
> -static int btf_encoder__add_enum_val(struct btf_encoder *encoder, const char *name, int32_t value)
> +static int btf_encoder__add_enum_val(struct btf_encoder *encoder, const char *name, int64_t value,
> + struct type *etype, struct conf_load *conf_load)
> {
> - int err = btf__add_enum_value(encoder->btf, name, value);
> + const char *fmt_str;
> + int err;
> +
> + /* If enum64 is not allowed, generate enum32 with unsigned int value. In enum64-supported
> + * libbpf library, btf__add_enum_value() will set the kflag (sign bit) in common_type
> + * if the value is negative.
> + */
> + if (conf_load->skip_encoding_btf_enum64)
> + err = btf__add_enum_value(encoder->btf, name, (uint32_t)value);
> + else if (etype->size > 32)
> + err = btf__add_enum64_value(encoder->btf, name, value);
> + else
> + err = btf__add_enum_value(encoder->btf, name, value);
>
> if (!err) {
> - if (encoder->verbose)
> - printf("\t%s val=%d\n", name, value);
> + if (encoder->verbose) {
> + if (conf_load->skip_encoding_btf_enum64) {
> + printf("\t%s val=%u\n", name, (uint32_t)value);
> + } else {
> + fmt_str = etype->is_signed_enum ? "\t%s val=%lld\n" : "\t%s val=%llu\n";
> + printf(fmt_str, name, (unsigned long long)value);
> + }
> + }
> } else {
> - fprintf(stderr, "\t%s val=%d Error emitting BTF enum value\n",
> - name, value);
> + if (conf_load->skip_encoding_btf_enum64) {
> + fprintf(stderr, "\t%s val=%u Error emitting BTF enum value\n", name, (uint32_t)value);
> + } else {
> + fmt_str = etype->is_signed_enum ? "\t%s val=%lld Error emitting BTF enum value\n"
> + : "\t%s val=%llu Error emitting BTF enum value\n";
> + fprintf(stderr, fmt_str, name, (unsigned long long)value);
> + }
> }
> return err;
> }
> @@ -844,27 +875,29 @@ static uint32_t array_type__nelems(struct tag *tag)
> return nelem;
> }
>
> -static int32_t btf_encoder__add_enum_type(struct btf_encoder *encoder, struct tag *tag)
> +static int32_t btf_encoder__add_enum_type(struct btf_encoder *encoder, struct tag *tag,
> + struct conf_load *conf_load)
> {
> struct type *etype = tag__type(tag);
> struct enumerator *pos;
> const char *name = type__name(etype);
> int32_t type_id;
>
> - type_id = btf_encoder__add_enum(encoder, name, etype->size);
> + type_id = btf_encoder__add_enum(encoder, name, etype, conf_load);
> if (type_id < 0)
> return type_id;
>
> type__for_each_enumerator(etype, pos) {
> name = enumerator__name(pos);
> - if (btf_encoder__add_enum_val(encoder, name, pos->value))
> + if (btf_encoder__add_enum_val(encoder, name, pos->value, etype, conf_load))
> return -1;
> }
>
> return type_id;
> }
>
> -static int btf_encoder__encode_tag(struct btf_encoder *encoder, struct tag *tag, uint32_t type_id_off)
> +static int btf_encoder__encode_tag(struct btf_encoder *encoder, struct tag *tag, uint32_t type_id_off,
> + struct conf_load *conf_load)
> {
> /* single out type 0 as it represents special type "void" */
> uint32_t ref_type_id = tag->type == 0 ? 0 : type_id_off + tag->type;
> @@ -903,7 +936,7 @@ static int btf_encoder__encode_tag(struct btf_encoder *encoder, struct tag *tag,
> encoder->need_index_type = true;
> return btf_encoder__add_array(encoder, ref_type_id, encoder->array_index_id, array_type__nelems(tag));
> case DW_TAG_enumeration_type:
> - return btf_encoder__add_enum_type(encoder, tag);
> + return btf_encoder__add_enum_type(encoder, tag, conf_load);
> case DW_TAG_subroutine_type:
> return btf_encoder__add_func_proto(encoder, tag__ftype(tag), type_id_off);
> default:
> @@ -1422,7 +1455,7 @@ void btf_encoder__delete(struct btf_encoder *encoder)
> free(encoder);
> }
>
> -int btf_encoder__encode_cu(struct btf_encoder *encoder, struct cu *cu)
> +int btf_encoder__encode_cu(struct btf_encoder *encoder, struct cu *cu, struct conf_load *conf_load)
> {
> uint32_t type_id_off = btf__type_cnt(encoder->btf) - 1;
> struct llvm_annotation *annot;
> @@ -1446,7 +1479,7 @@ int btf_encoder__encode_cu(struct btf_encoder *encoder, struct cu *cu)
> }
>
> cu__for_each_type(cu, core_id, pos) {
> - btf_type_id = btf_encoder__encode_tag(encoder, pos, type_id_off);
> + btf_type_id = btf_encoder__encode_tag(encoder, pos, type_id_off, conf_load);
>
> if (btf_type_id < 0 ||
> tag__check_id_drift(pos, core_id, btf_type_id, type_id_off)) {
> diff --git a/btf_encoder.h b/btf_encoder.h
> index 339fae2..a65120c 100644
> --- a/btf_encoder.h
> +++ b/btf_encoder.h
> @@ -21,7 +21,7 @@ void btf_encoder__delete(struct btf_encoder *encoder);
>
> int btf_encoder__encode(struct btf_encoder *encoder);
>
> -int btf_encoder__encode_cu(struct btf_encoder *encoder, struct cu *cu);
> +int btf_encoder__encode_cu(struct btf_encoder *encoder, struct cu *cu, struct conf_load *conf_load);
>
> void btf_encoders__add(struct list_head *encoders, struct btf_encoder *encoder);
>
> diff --git a/dwarf_loader.c b/dwarf_loader.c
> index a0d964b..4767602 100644
> --- a/dwarf_loader.c
> +++ b/dwarf_loader.c
> @@ -632,6 +632,18 @@ static void type__init(struct type *type, Dwarf_Die *die, struct cu *cu, struct
> type->resized = 0;
> type->nr_members = 0;
> type->nr_static_members = 0;
> + type->is_signed_enum = 0;
> +
> + Dwarf_Attribute attr;
> + if (dwarf_attr(die, DW_AT_type, &attr) != NULL) {
> + Dwarf_Die type_die;
> + if (dwarf_formref_die(&attr, &type_die) != NULL) {
> + uint64_t encoding = attr_numeric(&type_die, DW_AT_encoding);
> +
> + if (encoding == DW_ATE_signed || encoding == DW_ATE_signed_char)
> + type->is_signed_enum = 1;
> + }
> + }
> }
>
> static struct type *type__new(Dwarf_Die *die, struct cu *cu, struct conf_load *conf)
> diff --git a/dwarves.h b/dwarves.h
> index 4d0e4b6..bec9f08 100644
> --- a/dwarves.h
> +++ b/dwarves.h
> @@ -65,6 +65,7 @@ struct conf_load {
> bool skip_encoding_btf_decl_tag;
> bool skip_missing;
> bool skip_encoding_btf_type_tag;
> + bool skip_encoding_btf_enum64;
> uint8_t hashtable_bits;
> uint8_t max_hashtable_bits;
> uint16_t kabi_prefix_len;
> @@ -1046,6 +1047,7 @@ struct type {
> uint8_t definition_emitted:1;
> uint8_t fwd_decl_emitted:1;
> uint8_t resized:1;
> + uint8_t is_signed_enum:1;
> };
>
> void __type__init(struct type *type);
> @@ -1365,7 +1367,7 @@ static inline struct string_type *tag__string_type(const struct tag *tag)
> struct enumerator {
> struct tag tag;
> const char *name;
> - uint32_t value;
> + uint64_t value;
> struct tag_cu type_enum; // To cache the type_enum searches
> };
>
> diff --git a/dwarves_fprintf.c b/dwarves_fprintf.c
> index 2cec584..ce64c79 100644
> --- a/dwarves_fprintf.c
> +++ b/dwarves_fprintf.c
> @@ -437,7 +437,11 @@ size_t enumeration__fprintf(const struct tag *tag, const struct conf_fprintf *co
> type__for_each_enumerator(type, pos) {
> printed += fprintf(fp, "%.*s\t%-*s = ", indent, tabs,
> max_entry_name_len, enumerator__name(pos));
> - printed += fprintf(fp, conf->hex_fmt ? "%#x" : "%u", pos->value);
> + if (conf->hex_fmt)
> + printed += fprintf(fp, "%#llx", (unsigned long long)pos->value);
> + else
> + printed += fprintf(fp, type->is_signed_enum ? "%lld" : "%llu",
> + (unsigned long long)pos->value);
> printed += fprintf(fp, ",\n");
> }
>
> diff --git a/pahole.c b/pahole.c
> index 78caa08..e87d9a4 100644
> --- a/pahole.c
> +++ b/pahole.c
> @@ -1220,6 +1220,7 @@ ARGP_PROGRAM_VERSION_HOOK_DEF = dwarves_print_version;
> #define ARGP_compile 334
> #define ARGP_languages 335
> #define ARGP_languages_exclude 336
> +#define ARGP_skip_encoding_btf_enum64 337
>
> static const struct argp_option pahole__options[] = {
> {
> @@ -1622,6 +1623,11 @@ static const struct argp_option pahole__options[] = {
> .arg = "LANGUAGES",
> .doc = "Don't consider compilation units written in these languages"
> },
> + {
> + .name = "skip_encoding_btf_enum64",
> + .key = ARGP_skip_encoding_btf_enum64,
> + .doc = "Do not encode ENUM64sin BTF."
> + },
> {
> .name = NULL,
> }
> @@ -1787,6 +1793,8 @@ static error_t pahole__options_parser(int key, char *arg,
> /* fallthru */
> case ARGP_languages:
> languages.str = arg; break;
> + case ARGP_skip_encoding_btf_enum64:
> + conf_load.skip_encoding_btf_enum64 = true; break;
> default:
> return ARGP_ERR_UNKNOWN;
> }
> @@ -3067,7 +3075,7 @@ static enum load_steal_kind pahole_stealer(struct cu *cu,
> encoder = btf_encoder;
> }
>
> - if (btf_encoder__encode_cu(encoder, cu)) {
> + if (btf_encoder__encode_cu(encoder, cu, conf_load)) {
> fprintf(stderr, "Encountered error while encoding BTF.\n");
> exit(1);
> }
> --
> 2.30.2
--
- Arnaldo
next prev parent reply other threads:[~2022-06-29 19:12 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-06-29 7:12 [PATCH dwarves v3 0/2] btf: support BTF_KIND_ENUM64 Yonghong Song
2022-06-29 7:12 ` [PATCH dwarves v3 1/2] libbpf: Sync with latest libbpf repo Yonghong Song
2022-06-29 7:12 ` [PATCH dwarves v3 2/2] btf: Support BTF_KIND_ENUM64 Yonghong Song
2022-06-29 19:12 ` Arnaldo Carvalho de Melo [this message]
2022-06-29 20:00 ` Arnaldo Carvalho de Melo
2022-06-29 13:16 ` [PATCH dwarves v3 0/2] btf: support BTF_KIND_ENUM64 Arnaldo Carvalho de Melo
2022-06-29 21:44 ` Arnaldo Carvalho de Melo
2022-06-30 2:33 ` Yonghong Song
2022-07-11 9:16 ` Jiri Olsa
2022-07-11 9:37 ` Jiri Olsa
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=YrykE1zgKXvKaAgx@kernel.org \
--to=acme@kernel.org \
--cc=andrii@kernel.org \
--cc=arnaldo.melo@gmail.com \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=dwarves@vger.kernel.org \
--cc=kernel-team@fb.com \
--cc=yhs@fb.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.