1. 18 Dec, 2018 9 commits
    • Daniel Borkmann's avatar
      Merge branch 'bpf-btf-type-fixes' · 37c7b1ca
      Daniel Borkmann authored
      Yonghong Song says:
      
      ====================
      Commit 69b693f0 ("bpf: btf: Introduce BPF Type Format (BTF)")
      introduced BTF, a debug info format for BTF.
      
      The original design has a couple of issues though.
      First, the bitfield size is only encoded in int type.
      If the struct member bitfield type is enum, pahole ([1])
      or llvm is forced to replace enum with int type. As a result, the original
      type information gets lost.
      
      Second, the original BTF design does not envision the possibility of
      BTF=>header_file conversion ([2]), hence does not encode "struct" or
      "union" info for a forward type. Such information is necessary to
      convert BTF to a header file.
      
      This patch set fixed the issue by introducing kind_flag, using one bit
      in type->info. When kind_flag, the struct/union btf_member->offset
      will encode both bitfield_size and bit_offset, covering both
      int and enum base types. The kind_flag is also used to indicate whether
      the forward type is a union (when set) or a struct.
      
      Patch #1 refactors function btf_int_bits_seq_show() so Patch #2
      can reuse part of the function.
      Patch #2 implemented kind_flag support for struct/union/fwd types.
      Patch #3 added kind_flag support for cgroup local storage map pretty print.
      Patch #4 syncs kernel uapi btf.h to tools directory.
      Patch #5 added unit tests for kind_flag.
      Patch #6 added tests for kernel bpffs based pretty print with kind_flag.
      Patch #7 refactors function btf_dumper_int_bits() so Patch #8
      can reuse part of the function.
      Patch #8 added bpftool support of pretty print with kind_flag set.
      
        [1] https://git.kernel.org/pub/scm/devel/pahole/pahole.git/commit/?id=b18354f64cc215368c3bc0df4a7e5341c55c378c
        [2] https://lwn.net/SubscriberLink/773198/fe3074838f5c3f26/
      
      Change logs:
        v2 -> v3:
          . Relocated comments about bitfield_size/bit_offset interpretation
            of the "offset" field right before the "offset" struct member.
          . Added missing byte alignment checking for non-bitfield enum
            member of a struct with kind_flag set.
          . Added two test cases in unit tests for struct type, kind_flag set,
            non-bitfield int/enum member, not-byte aligned bit offsets.
          . Added comments to help understand there is no overflow for
            total_bits_offset in bpftool function btf_dumper_int_bits().
          . Added explanation of typedef type dumping fix in Patch #8 commit
            message.
      
        v1 -> v2:
          . If kind_flag is set for a structure, ensure an int member,
            whether it is a bitfield or not, is a regular int type.
          . Added support so cgroup local storage map pretty print
            works with kind_flag.
      ====================
      Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
      37c7b1ca
    • Yonghong Song's avatar
      tools: bpftool: support pretty print with kind_flag set · 8772c8bc
      Yonghong Song authored
      The following example shows map pretty print with structures
      which include bitfield members.
      
        enum A { A1, A2, A3, A4, A5 };
        typedef enum A ___A;
        struct tmp_t {
             char a1:4;
             int  a2:4;
             int  :4;
             __u32 a3:4;
             int b;
             ___A b1:4;
             enum A b2:4;
        };
        struct bpf_map_def SEC("maps") tmpmap = {
             .type = BPF_MAP_TYPE_ARRAY,
             .key_size = sizeof(__u32),
             .value_size = sizeof(struct tmp_t),
             .max_entries = 1,
        };
        BPF_ANNOTATE_KV_PAIR(tmpmap, int, struct tmp_t);
      
      and the following map update in the bpf program:
      
        key = 0;
        struct tmp_t t = {};
        t.a1 = 2;
        t.a2 = 4;
        t.a3 = 6;
        t.b = 7;
        t.b1 = 8;
        t.b2 = 10;
        bpf_map_update_elem(&tmpmap, &key, &t, 0);
      
      With this patch, I am able to print out the map values
      correctly with this patch:
      bpftool map dump id 187
        [{
              "key": 0,
              "value": {
                  "a1": 0x2,
                  "a2": 0x4,
                  "a3": 0x6,
                  "b": 7,
                  "b1": 0x8,
                  "b2": 0xa
              }
          }
        ]
      
      Previously, if a function prototype argument has a typedef
      type, the prototype is not printed since
      function __btf_dumper_type_only() bailed out with error
      if the type is a typedef. This commit corrected this
      behavior by printing out typedef properly.
      
      The following example shows forward type and
      typedef type can be properly printed in function prototype
      with modified test_btf_haskv.c.
      
        struct t;
        union  u;
      
        __attribute__((noinline))
        static int test_long_fname_1(struct dummy_tracepoint_args *arg,
                                     struct t *p1, union u *p2,
                                     __u32 unused)
        ...
        int _dummy_tracepoint(struct dummy_tracepoint_args *arg) {
          return test_long_fname_1(arg, 0, 0, 0);
        }
      
        $ bpftool p d xlated id 24
        ...
        int test_long_fname_1(struct dummy_tracepoint_args * arg,
                              struct t * p1, union u * p2,
                              __u32 unused)
        ...
      Acked-by: default avatarMartin KaFai Lau <kafai@fb.com>
      Signed-off-by: default avatarYonghong Song <yhs@fb.com>
      Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
      8772c8bc
    • Yonghong Song's avatar
      tools: bpftool: refactor btf_dumper_int_bits() · 9f95e37e
      Yonghong Song authored
      The core dump funcitonality in btf_dumper_int_bits() is
      refactored into a separate function btf_dumper_bitfield()
      which will be used by the next patch.
      Acked-by: default avatarMartin KaFai Lau <kafai@fb.com>
      Signed-off-by: default avatarYonghong Song <yhs@fb.com>
      Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
      9f95e37e
    • Yonghong Song's avatar
      tools/bpf: test kernel bpffs map pretty print with struct kind_flag · d0ebce68
      Yonghong Song authored
      The new tests are added to test bpffs map pretty print in kernel with kind_flag
      for structure type.
      
        $ test_btf -p
        ......
        BTF pretty print array(#1)......OK
        BTF pretty print array(#2)......OK
        PASS:8 SKIP:0 FAIL:0
      Acked-by: default avatarMartin KaFai Lau <kafai@fb.com>
      Signed-off-by: default avatarYonghong Song <yhs@fb.com>
      Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
      d0ebce68
    • Yonghong Song's avatar
      tools/bpf: add test_btf unit tests for kind_flag · cd9de5d3
      Yonghong Song authored
      This patch added unit tests for different types handling
      type->info.kind_flag. The following new tests are added:
        $ test_btf
        ...
        BTF raw test[82] (invalid int kind_flag): OK
        BTF raw test[83] (invalid ptr kind_flag): OK
        BTF raw test[84] (invalid array kind_flag): OK
        BTF raw test[85] (invalid enum kind_flag): OK
        BTF raw test[86] (valid fwd kind_flag): OK
        BTF raw test[87] (invalid typedef kind_flag): OK
        BTF raw test[88] (invalid volatile kind_flag): OK
        BTF raw test[89] (invalid const kind_flag): OK
        BTF raw test[90] (invalid restrict kind_flag): OK
        BTF raw test[91] (invalid func kind_flag): OK
        BTF raw test[92] (invalid func_proto kind_flag): OK
        BTF raw test[93] (valid struct kind_flag, bitfield_size = 0): OK
        BTF raw test[94] (valid struct kind_flag, int member, bitfield_size != 0): OK
        BTF raw test[95] (valid union kind_flag, int member, bitfield_size != 0): OK
        BTF raw test[96] (valid struct kind_flag, enum member, bitfield_size != 0): OK
        BTF raw test[97] (valid union kind_flag, enum member, bitfield_size != 0): OK
        BTF raw test[98] (valid struct kind_flag, typedef member, bitfield_size != 0): OK
        BTF raw test[99] (valid union kind_flag, typedef member, bitfield_size != 0): OK
        BTF raw test[100] (invalid struct type, bitfield_size greater than struct size): OK
        BTF raw test[101] (invalid struct type, kind_flag bitfield base_type int not regular): OK
        BTF raw test[102] (invalid struct type, kind_flag base_type int not regular): OK
        BTF raw test[103] (invalid union type, bitfield_size greater than struct size): OK
        ...
        PASS:122 SKIP:0 FAIL:0
      
      The second parameter name of macro
        BTF_INFO_ENC(kind, root, vlen)
      in selftests test_btf.c is also renamed from "root" to "kind_flag".
      Note that before this patch "root" is not used and always 0.
      Acked-by: default avatarMartin KaFai Lau <kafai@fb.com>
      Signed-off-by: default avatarYonghong Song <yhs@fb.com>
      Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
      cd9de5d3
    • Yonghong Song's avatar
      tools/bpf: sync btf.h header from kernel to tools · 128b343d
      Yonghong Song authored
      Sync include/uapi/linux/btf.h to tools/include/uapi/linux/btf.h.
      Acked-by: default avatarMartin KaFai Lau <kafai@fb.com>
      Signed-off-by: default avatarYonghong Song <yhs@fb.com>
      Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
      128b343d
    • Yonghong Song's avatar
      bpf: enable cgroup local storage map pretty print with kind_flag · ffa0c1cf
      Yonghong Song authored
      Commit 970289fc0a83 ("bpf: add bpffs pretty print for cgroup
      local storage maps") added bpffs pretty print for cgroup
      local storage maps. The commit worked for struct without kind_flag
      set.
      
      This patch refactored and made pretty print also work
      with kind_flag set for the struct.
      Acked-by: default avatarMartin KaFai Lau <kafai@fb.com>
      Signed-off-by: default avatarYonghong Song <yhs@fb.com>
      Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
      ffa0c1cf
    • Yonghong Song's avatar
      bpf: btf: fix struct/union/fwd types with kind_flag · 9d5f9f70
      Yonghong Song authored
      This patch fixed two issues with BTF. One is related to
      struct/union bitfield encoding and the other is related to
      forward type.
      
      Issue #1 and solution:
      
      ======================
      
      Current btf encoding of bitfield follows what pahole generates.
      For each bitfield, pahole will duplicate the type chain and
      put the bitfield size at the final int or enum type.
      Since the BTF enum type cannot encode bit size,
      pahole workarounds the issue by generating
      an int type whenever the enum bit size is not 32.
      
      For example,
        -bash-4.4$ cat t.c
        typedef int ___int;
        enum A { A1, A2, A3 };
        struct t {
          int a[5];
          ___int b:4;
          volatile enum A c:4;
        } g;
        -bash-4.4$ gcc -c -O2 -g t.c
      The current kernel supports the following BTF encoding:
        $ pahole -JV t.o
        [1] TYPEDEF ___int type_id=2
        [2] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED
        [3] ENUM A size=4 vlen=3
              A1 val=0
              A2 val=1
              A3 val=2
        [4] STRUCT t size=24 vlen=3
              a type_id=5 bits_offset=0
              b type_id=9 bits_offset=160
              c type_id=11 bits_offset=164
        [5] ARRAY (anon) type_id=2 index_type_id=2 nr_elems=5
        [6] INT sizetype size=8 bit_offset=0 nr_bits=64 encoding=(none)
        [7] VOLATILE (anon) type_id=3
        [8] INT int size=1 bit_offset=0 nr_bits=4 encoding=(none)
        [9] TYPEDEF ___int type_id=8
        [10] INT (anon) size=1 bit_offset=0 nr_bits=4 encoding=SIGNED
        [11] VOLATILE (anon) type_id=10
      
      Two issues are in the above:
        . by changing enum type to int, we lost the original
          type information and this will not be ideal later
          when we try to convert BTF to a header file.
        . the type duplication for bitfields will cause
          BTF bloat. Duplicated types cannot be deduplicated
          later if the bitfield size is different.
      
      To fix this issue, this patch implemented a compatible
      change for BTF struct type encoding:
        . the bit 31 of struct_type->info, previously reserved,
          now is used to indicate whether bitfield_size is
          encoded in btf_member or not.
        . if bit 31 of struct_type->info is set,
          btf_member->offset will encode like:
            bit 0 - 23: bit offset
            bit 24 - 31: bitfield size
          if bit 31 is not set, the old behavior is preserved:
            bit 0 - 31: bit offset
      
      So if the struct contains a bit field, the maximum bit offset
      will be reduced to (2^24 - 1) instead of MAX_UINT. The maximum
      bitfield size will be 256 which is enough for today as maximum
      bitfield in compiler can be 128 where int128 type is supported.
      
      This kernel patch intends to support the new BTF encoding:
        $ pahole -JV t.o
        [1] TYPEDEF ___int type_id=2
        [2] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED
        [3] ENUM A size=4 vlen=3
              A1 val=0
              A2 val=1
              A3 val=2
        [4] STRUCT t kind_flag=1 size=24 vlen=3
              a type_id=5 bitfield_size=0 bits_offset=0
              b type_id=1 bitfield_size=4 bits_offset=160
              c type_id=7 bitfield_size=4 bits_offset=164
        [5] ARRAY (anon) type_id=2 index_type_id=2 nr_elems=5
        [6] INT sizetype size=8 bit_offset=0 nr_bits=64 encoding=(none)
        [7] VOLATILE (anon) type_id=3
      
      Issue #2 and solution:
      ======================
      
      Current forward type in BTF does not specify whether the original
      type is struct or union. This will not work for type pretty print
      and BTF-to-header-file conversion as struct/union must be specified.
        $ cat tt.c
        struct t;
        union u;
        int foo(struct t *t, union u *u) { return 0; }
        $ gcc -c -g -O2 tt.c
        $ pahole -JV tt.o
        [1] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED
        [2] FWD t type_id=0
        [3] PTR (anon) type_id=2
        [4] FWD u type_id=0
        [5] PTR (anon) type_id=4
      
      To fix this issue, similar to issue #1, type->info bit 31
      is used. If the bit is set, it is union type. Otherwise, it is
      a struct type.
      
        $ pahole -JV tt.o
        [1] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED
        [2] FWD t kind_flag=0 type_id=0
        [3] PTR (anon) kind_flag=0 type_id=2
        [4] FWD u kind_flag=1 type_id=0
        [5] PTR (anon) kind_flag=0 type_id=4
      
      Pahole/LLVM change:
      ===================
      
      The new kind_flag functionality has been implemented in pahole
      and llvm:
        https://github.com/yonghong-song/pahole/tree/bitfield
        https://github.com/yonghong-song/llvm/tree/bitfield
      
      Note that pahole hasn't implemented func/func_proto kind
      and .BTF.ext. So to print function signature with bpftool,
      the llvm compiler should be used.
      
      Fixes: 69b693f0 ("bpf: btf: Introduce BPF Type Format (BTF)")
      Acked-by: default avatarMartin KaFai Lau <kafai@fb.com>
      Signed-off-by: default avatarMartin KaFai Lau <kafai@fb.com>
      Signed-off-by: default avatarYonghong Song <yhs@fb.com>
      Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
      9d5f9f70
    • Yonghong Song's avatar
      bpf: btf: refactor btf_int_bits_seq_show() · f97be3ab
      Yonghong Song authored
      Refactor function btf_int_bits_seq_show() by creating
      function btf_bitfield_seq_show() which has no dependence
      on btf and btf_type. The function btf_bitfield_seq_show()
      will be in later patch to directly dump bitfield member values.
      Acked-by: default avatarMartin KaFai Lau <kafai@fb.com>
      Signed-off-by: default avatarYonghong Song <yhs@fb.com>
      Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
      f97be3ab
  2. 17 Dec, 2018 1 commit
  3. 15 Dec, 2018 11 commits
  4. 14 Dec, 2018 3 commits
    • Alexei Starovoitov's avatar
      Merge branch 'bpf_line_info-in-verifier' · eb415c98
      Alexei Starovoitov authored
      Martin Lau says:
      
      ====================
      This patch set provides bpf_line_info during the verifier's verbose
      log.  Please see individual patch for details.
      ====================
      Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
      eb415c98
    • Martin KaFai Lau's avatar
      bpf: verbose log bpf_line_info in verifier · d9762e84
      Martin KaFai Lau authored
      This patch adds bpf_line_info during the verifier's verbose.
      It can give error context for debug purpose.
      
      ~~~~~~~~~~
      Here is the verbose log for backedge:
      	while (a) {
      		a += bpf_get_smp_processor_id();
      		bpf_trace_printk(fmt, sizeof(fmt), a);
      	}
      
      ~> bpftool prog load ./test_loop.o /sys/fs/bpf/test_loop type tracepoint
      13: while (a) {
      3: a += bpf_get_smp_processor_id();
      back-edge from insn 13 to 3
      
      ~~~~~~~~~~
      Here is the verbose log for invalid pkt access:
      Modification to test_xdp_noinline.c:
      
      	data = (void *)(long)xdp->data;
      	data_end = (void *)(long)xdp->data_end;
      /*
      	if (data + 4 > data_end)
      		return XDP_DROP;
      */
      	*(u32 *)data = dst->dst;
      
      ~> bpftool prog load ./test_xdp_noinline.o /sys/fs/bpf/test_xdp_noinline type xdp
      ; data = (void *)(long)xdp->data;
      224: (79) r2 = *(u64 *)(r10 -112)
      225: (61) r2 = *(u32 *)(r2 +0)
      ; *(u32 *)data = dst->dst;
      226: (63) *(u32 *)(r2 +0) = r1
      invalid access to packet, off=0 size=4, R2(id=0,off=0,r=0)
      R2 offset is outside of the packet
      Signed-off-by: default avatarMartin KaFai Lau <kafai@fb.com>
      Acked-by: default avatarYonghong Song <yhs@fb.com>
      Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
      d9762e84
    • Martin KaFai Lau's avatar
      bpf: Create a new btf_name_by_offset() for non type name use case · 23127b33
      Martin KaFai Lau authored
      The current btf_name_by_offset() is returning "(anon)" type name for
      the offset == 0 case and "(invalid-name-offset)" for the out-of-bound
      offset case.
      
      It fits well for the internal BTF verbose log purpose which
      is focusing on type.  For example,
      offset == 0 => "(anon)" => anonymous type/name.
      Returning non-NULL for the bad offset case is needed
      during the BTF verification process because the BTF verifier may
      complain about another field first before discovering the name_off
      is invalid.
      
      However, it may not be ideal for the newer use case which does not
      necessary mean type name.  For example, when logging line_info
      in the BPF verifier in the next patch, it is better to log an
      empty src line instead of logging "(anon)".
      
      The existing bpf_name_by_offset() is renamed to __bpf_name_by_offset()
      and static to btf.c.
      
      A new bpf_name_by_offset() is added for generic context usage.  It
      returns "\0" for name_off == 0 (note that btf->strings[0] is "\0")
      and NULL for invalid offset.  It allows the caller to decide
      what is the best output in its context.
      
      The new btf_name_by_offset() is overlapped with btf_name_offset_valid().
      Hence, btf_name_offset_valid() is removed from btf.h to keep the btf.h API
      minimal.  The existing btf_name_offset_valid() usage in btf.c could also be
      replaced later.
      Signed-off-by: default avatarMartin KaFai Lau <kafai@fb.com>
      Acked-by: default avatarYonghong Song <yhs@fb.com>
      Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
      23127b33
  5. 13 Dec, 2018 11 commits
  6. 12 Dec, 2018 5 commits