Commit Graph

152 Commits

Author SHA1 Message Date
Yonghong Song 0d2511fd1d btf: Fix bitfield encoding
The btf bitfield encoding is broken.

For the following example:

  -bash-4.2$ cat t.c
  struct t {
     int a:2;
     int b:1;
     int :3;
     int c:1;
     int d;
     char e:1;
     char f:1;
     int g;
  };
  void test(struct t *t) {
     return;
  }
  -bash-4.2$ clang -S -g -emit-llvm t.c

The output for bpf "little and big" endian results with pahole dwarf2btf
conversion:

  -bash-4.2$ llc -march=bpfel -mattr=dwarfris -filetype=obj t.ll
  -bash-4.2$ pahole -JV t.o
  [1] PTR (anon) type_id=2
  [2] STRUCT t size=16 vlen=7
        a type_id=5 bits_offset=30
        b type_id=6 bits_offset=29
        c type_id=6 bits_offset=25
        d type_id=3 bits_offset=32
        e type_id=7 bits_offset=71
        f type_id=7 bits_offset=70
        g type_id=3 bits_offset=96
  [3] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED
  [4] INT char size=1 bit_offset=0 nr_bits=8 encoding=(none)
  [5] INT int size=1 bit_offset=0 nr_bits=2 encoding=(none)
  [6] INT int size=1 bit_offset=0 nr_bits=1 encoding=(none)
  [7] INT char size=1 bit_offset=0 nr_bits=1 encoding=(none)
  -bash-4.2$ llc -march=bpfeb -mattr=dwarfris -filetype=obj t.ll
  -bash-4.2$ pahole -JV t.o
  [1] PTR (anon) type_id=2
  [2] STRUCT t size=16 vlen=7
        a type_id=5 bits_offset=0
        b type_id=6 bits_offset=2
        c type_id=6 bits_offset=6
        d type_id=3 bits_offset=32
        e type_id=7 bits_offset=64
        f type_id=7 bits_offset=65
        g type_id=3 bits_offset=96
  [3] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED
  [4] INT char size=1 bit_offset=0 nr_bits=8 encoding=(none)
  [5] INT int size=1 bit_offset=0 nr_bits=2 encoding=(none)
  [6] INT int size=1 bit_offset=0 nr_bits=1 encoding=(none)
  [7] INT char size=1 bit_offset=0 nr_bits=1 encoding=(none)

The BTF struct member bits_offset counts bits from the beginning of the
containing entity regardless of endianness, similar to what
DW_AT_bit_offset from DWARF4 does. Such counting is equivalent to the
big endian conversion in the above.

But the little endian conversion is not correct since dwarf generates
DW_AT_bit_offset based on actual bit position in the little endian
architecture.  For example, for the above struct member "a", the dwarf
would generate DW_AT_bit_offset=30 for little endian, and
DW_AT_bit_offset=0 for big endian.

This patch fixed the little endian structure member bits_offset problem
with proper calculation based on dwarf attributes.

With the fix, we get:

  -bash-4.2$ llc -march=bpfel -mattr=dwarfris -filetype=obj t.ll
  -bash-4.2$ pahole -JV t.o
    [1] STRUCT t size=16 vlen=7
        a type_id=5 bits_offset=0
        b type_id=6 bits_offset=2
        c type_id=6 bits_offset=6
        d type_id=2 bits_offset=32
        e type_id=7 bits_offset=64
        f type_id=7 bits_offset=65
        g type_id=2 bits_offset=96
    [2] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED
    [3] INT char size=1 bit_offset=0 nr_bits=8 encoding=(none)
    [4] PTR (anon) type_id=1
    [5] INT int size=1 bit_offset=0 nr_bits=2 encoding=(none)
    [6] INT int size=1 bit_offset=0 nr_bits=1 encoding=(none)
    [7] INT char size=1 bit_offset=0 nr_bits=1 encoding=(none)
  -bash-4.2$ llc -march=bpfeb -mattr=dwarfris -filetype=obj t.ll
  -bash-4.2$ pahole -JV t.o
  [1] PTR (anon) type_id=2
  [2] STRUCT t size=16 vlen=7
        a type_id=5 bits_offset=0
        b type_id=6 bits_offset=2
        c type_id=6 bits_offset=6
        d type_id=3 bits_offset=32
        e type_id=7 bits_offset=64
        f type_id=7 bits_offset=65
        g type_id=3 bits_offset=96
  [3] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED
  [4] INT char size=1 bit_offset=0 nr_bits=8 encoding=(none)
  [5] INT int size=1 bit_offset=0 nr_bits=2 encoding=(none)
  [6] INT int size=1 bit_offset=0 nr_bits=1 encoding=(none)
  [7] INT char size=1 bit_offset=0 nr_bits=1 encoding=(none)
  -bash-4.2$

For both little endian and big endian, we have correct and
same bits_offset for struct members.

We could fix pos->bit_offset, but pos->bit_offset will be inconsistent
to pos->bitfield_offset in the meaning and pos->bitfield_offset is used
to print out pahole data structure:

  -bash-4.2$ llc -march=bpfel -mattr=dwarfris -filetype=obj t.ll
  -bash-4.2$ /bin/pahole t.o
  struct t {
        int                        a:2;                  /*     0:30  4 */
        int                        b:1;                  /*     0:29  4 */
        int                        c:1;                  /*     0:25  4 */
  .....

So this patch just made the change in btf specific routines.

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>
2018-09-17 11:44:58 -03:00
Martin KaFai Lau 68645f7fac btf: Add BTF support
This patch introduces BPF Type Format (BTF).

BTF (BPF Type Format) is the meta data format which describes
the data types of BPF program/map.  Hence, it basically focus
on the C programming language which the modern BPF is primary
using.  The first use case is to provide a generic pretty print
capability for a BPF map.

Signed-off-by: Martin KaFai Lau <kafai@fb.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2018-07-25 14:42:06 -03:00