btf: Generate correct struct bitfield member types

For int types, the correct type size will be generated.  For enum types,
if the bit size is not 32, current BTF enum cannot represent it so a
signed int type will be generated.

For the following example:

  $ cat test.c
  enum A { A1, A2, A3 };
  struct t {
    enum A a:3;
    volatile enum A b:4;
  } g;
  $ gcc -c -g -O2 test.c

Without this patch, we will have:

  $ pahole -JV test.o
  [1] ENUM A size=4 vlen=3
        A1 val=0
        A2 val=1
        A3 val=2
  [2] STRUCT t size=4 vlen=2
        a type_id=4 bits_offset=0
        b type_id=6 bits_offset=3
  [3] VOLATILE (anon) type_id=1
  [4] ENUM A size=1 vlen=3
        A1 val=0
        A2 val=1
        A3 val=2
  [5] ENUM A size=1 vlen=3
        A1 val=0
        A2 val=1
        A3 val=2
  [6] VOLATILE (anon) type_id=5
  [7] INT (anon) size=4 bit_offset=0 nr_bits=32 encoding=(none)

There are two issues in the above. The struct "t" member "a" points to
type [4]. But the nr_bits is lost in type [4].

The same for type [5] which is for struct "t" member "b".

Since BTF ENUM type cannot encode nr_bits, this patch fixed the issue by
generating a BTF INT type if the ENUM type number of bits in pahole is
not 32.

With this patch, the incorrect member nr_bits issue is fixed as below:

  $ pahole -JV test.o
  [1] ENUM A size=4 vlen=3
        A1 val=0
        A2 val=1
        A3 val=2
  [2] STRUCT t size=4 vlen=2
        a type_id=4 bits_offset=0
        b type_id=6 bits_offset=3
  [3] VOLATILE (anon) type_id=1
  [4] INT (anon) size=1 bit_offset=0 nr_bits=3 encoding=SIGNED
  [5] INT (anon) size=1 bit_offset=0 nr_bits=4 encoding=SIGNED
  [6] VOLATILE (anon) type_id=5
  [7] INT (anon) size=4 bit_offset=0 nr_bits=32 encoding=(none)

Signed-off-by: Yonghong Song <yhs@fb.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Acked-by: Martin KaFai Lau <kafai@fb.com>
Cc: Alexei Starovoitov <ast@fb.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Yonghong Song 2018-11-29 15:45:49 -08:00 committed by Arnaldo Carvalho de Melo
parent 70ef8c7f07
commit b18354f64c
2 changed files with 10 additions and 1 deletions

View File

@ -85,6 +85,15 @@ static int32_t enumeration_type__encode(struct btf *btf, struct tag *tag)
struct enumerator *pos; struct enumerator *pos;
int32_t type_id; int32_t type_id;
/* if enumerator bit_size is not 32, generate an int type instead. */
if (etype->size != 32) {
struct base_type bt = {};
bt.bit_size = etype->size;
bt.is_signed = true;
return btf__add_base_type(btf, &bt);
}
type_id = btf__add_enum(btf, etype->namespace.name, type_id = btf__add_enum(btf, etype->namespace.name,
etype->size, etype->nr_members); etype->size, etype->nr_members);
if (type_id < 0) if (type_id < 0)

View File

@ -228,7 +228,7 @@ int32_t btf__add_base_type(struct btf *btf, const struct base_type *bt)
{ {
struct btf_int_type int_type; struct btf_int_type int_type;
struct btf_type *t = &int_type.type; struct btf_type *t = &int_type.type;
uint8_t encoding; uint8_t encoding = 0;
t->name_off = bt->name; t->name_off = bt->name;
t->info = BTF_INFO_ENCODE(BTF_KIND_INT, 0, 0); t->info = BTF_INFO_ENCODE(BTF_KIND_INT, 0, 0);