All of lore.kernel.org
 help / color / mirror / Atom feed
* bpftool gen object doesn't handle GCC built BPF ELF files
@ 2022-07-06 17:11 James Hilliard
  2022-07-06 17:20 ` Andrii Nakryiko
  0 siblings, 1 reply; 38+ messages in thread
From: James Hilliard @ 2022-07-06 17:11 UTC (permalink / raw)
  To: bpf

Note I'm testing with the following patches:
https://lore.kernel.org/bpf/20220706111839.1247911-1-james.hilliard1@gmail.com/
https://lore.kernel.org/bpf/20220706140623.2917858-1-james.hilliard1@gmail.com/

It would appear there's some compatibility issues with bpftool gen and
GCC, not sure what side though is wrong here:
/home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
gen object src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
libbpf: failed to find BTF info for global/extern symbol 'sd_restrictif_i'
Error: failed to link
'src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o':
Unknown error -2 (-2)

Relevant difference seems to be this:
GCC:
[55] FUNC 'sd_restrictif_i' type_id=47 linkage=static
Clang:
[27] FUNC 'sd_restrictif_i' type_id=26 linkage=global

GCC:

[1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
[2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
[3] TYPEDEF '__u8' type_id=2
[4] CONST '(anon)' type_id=3
[5] VOLATILE '(anon)' type_id=4
[6] INT 'short int' size=2 bits_offset=0 nr_bits=16 encoding=SIGNED
[7] INT 'short unsigned int' size=2 bits_offset=0 nr_bits=16 encoding=(none)
[8] TYPEDEF '__u16' type_id=7
[9] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
[10] TYPEDEF '__s32' type_id=9
[11] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
[12] TYPEDEF '__u32' type_id=11
[13] INT 'long long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
[14] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64
encoding=(none)
[15] TYPEDEF '__u64' type_id=14
[16] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
[17] INT 'long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
[18] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
[19] CONST '(anon)' type_id=18
[20] TYPEDEF '__be16' type_id=8
[21] TYPEDEF '__be32' type_id=12
[22] ENUM 'bpf_map_type' encoding=UNSIGNED size=4 vlen=31
    'BPF_MAP_TYPE_UNSPEC' val=0
    'BPF_MAP_TYPE_HASH' val=1
    'BPF_MAP_TYPE_ARRAY' val=2
    'BPF_MAP_TYPE_PROG_ARRAY' val=3
    'BPF_MAP_TYPE_PERF_EVENT_ARRAY' val=4
    'BPF_MAP_TYPE_PERCPU_HASH' val=5
    'BPF_MAP_TYPE_PERCPU_ARRAY' val=6
    'BPF_MAP_TYPE_STACK_TRACE' val=7
    'BPF_MAP_TYPE_CGROUP_ARRAY' val=8
    'BPF_MAP_TYPE_LRU_HASH' val=9
    'BPF_MAP_TYPE_LRU_PERCPU_HASH' val=10
    'BPF_MAP_TYPE_LPM_TRIE' val=11
    'BPF_MAP_TYPE_ARRAY_OF_MAPS' val=12
    'BPF_MAP_TYPE_HASH_OF_MAPS' val=13
    'BPF_MAP_TYPE_DEVMAP' val=14
    'BPF_MAP_TYPE_SOCKMAP' val=15
    'BPF_MAP_TYPE_CPUMAP' val=16
    'BPF_MAP_TYPE_XSKMAP' val=17
    'BPF_MAP_TYPE_SOCKHASH' val=18
    'BPF_MAP_TYPE_CGROUP_STORAGE' val=19
    'BPF_MAP_TYPE_REUSEPORT_SOCKARRAY' val=20
    'BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE' val=21
    'BPF_MAP_TYPE_QUEUE' val=22
    'BPF_MAP_TYPE_STACK' val=23
    'BPF_MAP_TYPE_SK_STORAGE' val=24
    'BPF_MAP_TYPE_DEVMAP_HASH' val=25
    'BPF_MAP_TYPE_STRUCT_OPS' val=26
    'BPF_MAP_TYPE_RINGBUF' val=27
    'BPF_MAP_TYPE_INODE_STORAGE' val=28
    'BPF_MAP_TYPE_TASK_STORAGE' val=29
    'BPF_MAP_TYPE_BLOOM_FILTER' val=30
[23] UNION '(anon)' size=8 vlen=1
    'flow_keys' type_id=29 bits_offset=0
[24] STRUCT 'bpf_flow_keys' size=56 vlen=13
    'nhoff' type_id=8 bits_offset=0
    'thoff' type_id=8 bits_offset=16
    'addr_proto' type_id=8 bits_offset=32
    'is_frag' type_id=3 bits_offset=48
    'is_first_frag' type_id=3 bits_offset=56
    'is_encap' type_id=3 bits_offset=64
    'ip_proto' type_id=3 bits_offset=72
    'n_proto' type_id=20 bits_offset=80
    'sport' type_id=20 bits_offset=96
    'dport' type_id=20 bits_offset=112
    '(anon)' type_id=25 bits_offset=128
    'flags' type_id=12 bits_offset=384
    'flow_label' type_id=21 bits_offset=416
[25] UNION '(anon)' size=32 vlen=2
    '(anon)' type_id=26 bits_offset=0
    '(anon)' type_id=27 bits_offset=0
[26] STRUCT '(anon)' size=8 vlen=2
    'ipv4_src' type_id=21 bits_offset=0
    'ipv4_dst' type_id=21 bits_offset=32
[27] STRUCT '(anon)' size=32 vlen=2
    'ipv6_src' type_id=28 bits_offset=0
    'ipv6_dst' type_id=28 bits_offset=128
[28] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=4
[29] PTR '(anon)' type_id=24
[30] UNION '(anon)' size=8 vlen=1
    'sk' type_id=32 bits_offset=0
[31] STRUCT 'bpf_sock' size=80 vlen=14
    'bound_dev_if' type_id=12 bits_offset=0
    'family' type_id=12 bits_offset=32
    'type' type_id=12 bits_offset=64
    'protocol' type_id=12 bits_offset=96
    'mark' type_id=12 bits_offset=128
    'priority' type_id=12 bits_offset=160
    'src_ip4' type_id=12 bits_offset=192
    'src_ip6' type_id=28 bits_offset=224
    'src_port' type_id=12 bits_offset=352
    'dst_port' type_id=20 bits_offset=384
    'dst_ip4' type_id=12 bits_offset=416
    'dst_ip6' type_id=28 bits_offset=448
    'state' type_id=12 bits_offset=576
    'rx_queue_mapping' type_id=10 bits_offset=608
[32] PTR '(anon)' type_id=31
[33] STRUCT '__sk_buff' size=192 vlen=33
    'len' type_id=12 bits_offset=0
    'pkt_type' type_id=12 bits_offset=32
    'mark' type_id=12 bits_offset=64
    'queue_mapping' type_id=12 bits_offset=96
    'protocol' type_id=12 bits_offset=128
    'vlan_present' type_id=12 bits_offset=160
    'vlan_tci' type_id=12 bits_offset=192
    'vlan_proto' type_id=12 bits_offset=224
    'priority' type_id=12 bits_offset=256
    'ingress_ifindex' type_id=12 bits_offset=288
    'ifindex' type_id=12 bits_offset=320
    'tc_index' type_id=12 bits_offset=352
    'cb' type_id=34 bits_offset=384
    'hash' type_id=12 bits_offset=544
    'tc_classid' type_id=12 bits_offset=576
    'data' type_id=12 bits_offset=608
    'data_end' type_id=12 bits_offset=640
    'napi_id' type_id=12 bits_offset=672
    'family' type_id=12 bits_offset=704
    'remote_ip4' type_id=12 bits_offset=736
    'local_ip4' type_id=12 bits_offset=768
    'remote_ip6' type_id=28 bits_offset=800
    'local_ip6' type_id=28 bits_offset=928
    'remote_port' type_id=12 bits_offset=1056
    'local_port' type_id=12 bits_offset=1088
    'data_meta' type_id=12 bits_offset=1120
    '(anon)' type_id=23 bits_offset=1152
    'tstamp' type_id=15 bits_offset=1216
    'wire_len' type_id=12 bits_offset=1280
    'gso_segs' type_id=12 bits_offset=1312
    '(anon)' type_id=30 bits_offset=1344
    'gso_size' type_id=12 bits_offset=1408
    'hwtstamp' type_id=15 bits_offset=1472
[34] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=5
[35] CONST '(anon)' type_id=33
[36] PTR '(anon)' type_id=0
[37] STRUCT '(anon)' size=24 vlen=3
    'type' type_id=39 bits_offset=0
    'key' type_id=40 bits_offset=64
    'value' type_id=41 bits_offset=128
[38] ARRAY '(anon)' type_id=9 index_type_id=16 nr_elems=1
[39] PTR '(anon)' type_id=38
[40] PTR '(anon)' type_id=12
[41] PTR '(anon)' type_id=3
[42] ARRAY '(anon)' type_id=19 index_type_id=16 nr_elems=18
[43] CONST '(anon)' type_id=42
[44] FUNC_PROTO '(anon)' ret_type_id=36 vlen=2
    '(anon)' type_id=36
    '(anon)' type_id=46
[45] CONST '(anon)' type_id=0
[46] PTR '(anon)' type_id=45
[47] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
    'sk' type_id=48
[48] PTR '(anon)' type_id=35
[49] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
    'sk' type_id=48
[50] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
    'sk' type_id=48
[51] VAR '_license' type_id=43, linkage=static
[52] VAR 'sd_restrictif' type_id=37, linkage=global
[53] VAR 'is_allow_list' type_id=5, linkage=global
[54] FUNC 'bpf_map_lookup_elem' type_id=44 linkage=static
[55] FUNC 'sd_restrictif_i' type_id=47 linkage=static
[56] FUNC 'sd_restrictif_e' type_id=49 linkage=static
[57] FUNC 'restrict_network_interfaces_impl' type_id=50 linkage=static
[58] DATASEC 'license' size=0 vlen=1
    type_id=51 offset=0 size=18 (VAR '_license')
[59] DATASEC '.maps' size=0 vlen=1
    type_id=52 offset=0 size=24 (VAR 'sd_restrictif')
[60] DATASEC '.data' size=0 vlen=1
    type_id=53 offset=0 size=1 (VAR 'is_allow_list')



Clang:

[1] PTR '(anon)' type_id=3
[2] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
[3] ARRAY '(anon)' type_id=2 index_type_id=4 nr_elems=1
[4] INT '__ARRAY_SIZE_TYPE__' size=4 bits_offset=0 nr_bits=32 encoding=(none)
[5] PTR '(anon)' type_id=6
[6] TYPEDEF '__u32' type_id=7
[7] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
[8] PTR '(anon)' type_id=9
[9] TYPEDEF '__u8' type_id=10
[10] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=(none)
[11] STRUCT '(anon)' size=24 vlen=3
    'type' type_id=1 bits_offset=0
    'key' type_id=5 bits_offset=64
    'value' type_id=8 bits_offset=128
[12] VAR 'sd_restrictif' type_id=11, linkage=global
[13] PTR '(anon)' type_id=14
[14] CONST '(anon)' type_id=15
[15] STRUCT '__sk_buff' size=192 vlen=33
    'len' type_id=6 bits_offset=0
    'pkt_type' type_id=6 bits_offset=32
    'mark' type_id=6 bits_offset=64
    'queue_mapping' type_id=6 bits_offset=96
    'protocol' type_id=6 bits_offset=128
    'vlan_present' type_id=6 bits_offset=160
    'vlan_tci' type_id=6 bits_offset=192
    'vlan_proto' type_id=6 bits_offset=224
    'priority' type_id=6 bits_offset=256
    'ingress_ifindex' type_id=6 bits_offset=288
    'ifindex' type_id=6 bits_offset=320
    'tc_index' type_id=6 bits_offset=352
    'cb' type_id=16 bits_offset=384
    'hash' type_id=6 bits_offset=544
    'tc_classid' type_id=6 bits_offset=576
    'data' type_id=6 bits_offset=608
    'data_end' type_id=6 bits_offset=640
    'napi_id' type_id=6 bits_offset=672
    'family' type_id=6 bits_offset=704
    'remote_ip4' type_id=6 bits_offset=736
    'local_ip4' type_id=6 bits_offset=768
    'remote_ip6' type_id=17 bits_offset=800
    'local_ip6' type_id=17 bits_offset=928
    'remote_port' type_id=6 bits_offset=1056
    'local_port' type_id=6 bits_offset=1088
    'data_meta' type_id=6 bits_offset=1120
    '(anon)' type_id=18 bits_offset=1152
    'tstamp' type_id=20 bits_offset=1216
    'wire_len' type_id=6 bits_offset=1280
    'gso_segs' type_id=6 bits_offset=1312
    '(anon)' type_id=22 bits_offset=1344
    'gso_size' type_id=6 bits_offset=1408
    'hwtstamp' type_id=20 bits_offset=1472
[16] ARRAY '(anon)' type_id=6 index_type_id=4 nr_elems=5
[17] ARRAY '(anon)' type_id=6 index_type_id=4 nr_elems=4
[18] UNION '(anon)' size=8 vlen=1
    'flow_keys' type_id=19 bits_offset=0
[19] PTR '(anon)' type_id=38
[20] TYPEDEF '__u64' type_id=21
[21] INT 'unsigned long long' size=8 bits_offset=0 nr_bits=64 encoding=(none)
[22] UNION '(anon)' size=8 vlen=1
    'sk' type_id=23 bits_offset=0
[23] PTR '(anon)' type_id=39
[24] FUNC_PROTO '(anon)' ret_type_id=2 vlen=1
    'sk' type_id=13
[25] FUNC 'sd_restrictif_e' type_id=24 linkage=global
[26] FUNC_PROTO '(anon)' ret_type_id=2 vlen=1
    'sk' type_id=13
[27] FUNC 'sd_restrictif_i' type_id=26 linkage=global
[28] CONST '(anon)' type_id=29
[29] VOLATILE '(anon)' type_id=9
[30] VAR 'is_allow_list' type_id=28, linkage=global
[31] CONST '(anon)' type_id=32
[32] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=SIGNED
[33] ARRAY '(anon)' type_id=31 index_type_id=4 nr_elems=18
[34] VAR '_license' type_id=33, linkage=static
[35] DATASEC '.maps' size=0 vlen=1
    type_id=12 offset=0 size=24 (VAR 'sd_restrictif')
[36] DATASEC '.rodata' size=0 vlen=1
    type_id=30 offset=0 size=1 (VAR 'is_allow_list')
[37] DATASEC 'license' size=0 vlen=1
    type_id=34 offset=0 size=18 (VAR '_license')
[38] FWD 'bpf_flow_keys' fwd_kind=struct
[39] FWD 'bpf_sock' fwd_kind=struct

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-07-06 17:11 bpftool gen object doesn't handle GCC built BPF ELF files James Hilliard
@ 2022-07-06 17:20 ` Andrii Nakryiko
  2022-07-06 17:49   ` James Hilliard
                     ` (2 more replies)
  0 siblings, 3 replies; 38+ messages in thread
From: Andrii Nakryiko @ 2022-07-06 17:20 UTC (permalink / raw)
  To: James Hilliard; +Cc: bpf

On Wed, Jul 6, 2022 at 10:13 AM James Hilliard
<james.hilliard1@gmail.com> wrote:
>
> Note I'm testing with the following patches:
> https://lore.kernel.org/bpf/20220706111839.1247911-1-james.hilliard1@gmail.com/
> https://lore.kernel.org/bpf/20220706140623.2917858-1-james.hilliard1@gmail.com/
>
> It would appear there's some compatibility issues with bpftool gen and
> GCC, not sure what side though is wrong here:
> /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> gen object src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
> libbpf: failed to find BTF info for global/extern symbol 'sd_restrictif_i'
> Error: failed to link
> 'src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o':
> Unknown error -2 (-2)
>
> Relevant difference seems to be this:
> GCC:
> [55] FUNC 'sd_restrictif_i' type_id=47 linkage=static
> Clang:
> [27] FUNC 'sd_restrictif_i' type_id=26 linkage=global
>

GCC is wrong, clearly. This function is global ([0]) and libbpf
expects it to be marked as such in BTF.

https://github.com/systemd/systemd/blob/main/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.c#L42-L50


> GCC:
>
> [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
> [3] TYPEDEF '__u8' type_id=2
> [4] CONST '(anon)' type_id=3

[...]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-07-06 17:20 ` Andrii Nakryiko
@ 2022-07-06 17:49   ` James Hilliard
  2022-07-08 11:55     ` Jose E. Marchesi
  2022-07-08 14:51   ` Jose E. Marchesi
  2022-07-12  0:34   ` Indu Bhagat
  2 siblings, 1 reply; 38+ messages in thread
From: James Hilliard @ 2022-07-06 17:49 UTC (permalink / raw)
  To: Andrii Nakryiko; +Cc: bpf

On Wed, Jul 6, 2022 at 11:20 AM Andrii Nakryiko
<andrii.nakryiko@gmail.com> wrote:
>
> On Wed, Jul 6, 2022 at 10:13 AM James Hilliard
> <james.hilliard1@gmail.com> wrote:
> >
> > Note I'm testing with the following patches:
> > https://lore.kernel.org/bpf/20220706111839.1247911-1-james.hilliard1@gmail.com/
> > https://lore.kernel.org/bpf/20220706140623.2917858-1-james.hilliard1@gmail.com/
> >
> > It would appear there's some compatibility issues with bpftool gen and
> > GCC, not sure what side though is wrong here:
> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> > gen object src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> > src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
> > libbpf: failed to find BTF info for global/extern symbol 'sd_restrictif_i'
> > Error: failed to link
> > 'src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o':
> > Unknown error -2 (-2)
> >
> > Relevant difference seems to be this:
> > GCC:
> > [55] FUNC 'sd_restrictif_i' type_id=47 linkage=static
> > Clang:
> > [27] FUNC 'sd_restrictif_i' type_id=26 linkage=global
> >
>
> GCC is wrong, clearly. This function is global ([0]) and libbpf
> expects it to be marked as such in BTF.

Does this invocation look correct?
/home/buildroot/buildroot/output/per-package/systemd/host/bin/bpf-gcc
-O2 -mkernel=5.2 -mcpu=v3 -mco-re -gbtf -r -std=gnu11 -D__x86_64__
-mlittle-endian -I. -idirafter
/home/buildroot/buildroot/output/per-package/systemd/host/x86_64-buildroot-linux-gnu/sysroot/usr/include
../src/core/bpf/restrict_fs/restrict-fs.bpf.c -o
src/core/bpf/restrict_fs/restrict-fs.bpf.unstripped.o

I've also tried without the -r(relocatable object) flag but that gives
a different error:
/home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
gen object src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
libbpf: unsupported kind of ELF file
src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o: no
error
Error: failed to link
'src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o':
Unknown error -95 (-95)

GCC without relocatable flag:
[1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
[2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
[3] TYPEDEF '__u8' type_id=2
[4] CONST '(anon)' type_id=3
[5] VOLATILE '(anon)' type_id=4
[6] INT 'short int' size=2 bits_offset=0 nr_bits=16 encoding=SIGNED
[7] INT 'short unsigned int' size=2 bits_offset=0 nr_bits=16 encoding=(none)
[8] TYPEDEF '__u16' type_id=7
[9] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
[10] TYPEDEF '__s32' type_id=9
[11] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
[12] TYPEDEF '__u32' type_id=11
[13] INT 'long long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
[14] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64
encoding=(none)
[15] TYPEDEF '__u64' type_id=14
[16] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
[17] INT 'long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
[18] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
[19] CONST '(anon)' type_id=18
[20] TYPEDEF '__be16' type_id=8
[21] TYPEDEF '__be32' type_id=12
[22] ENUM 'bpf_map_type' encoding=UNSIGNED size=4 vlen=31
    'BPF_MAP_TYPE_UNSPEC' val=0
    'BPF_MAP_TYPE_HASH' val=1
    'BPF_MAP_TYPE_ARRAY' val=2
    'BPF_MAP_TYPE_PROG_ARRAY' val=3
    'BPF_MAP_TYPE_PERF_EVENT_ARRAY' val=4
    'BPF_MAP_TYPE_PERCPU_HASH' val=5
    'BPF_MAP_TYPE_PERCPU_ARRAY' val=6
    'BPF_MAP_TYPE_STACK_TRACE' val=7
    'BPF_MAP_TYPE_CGROUP_ARRAY' val=8
    'BPF_MAP_TYPE_LRU_HASH' val=9
    'BPF_MAP_TYPE_LRU_PERCPU_HASH' val=10
    'BPF_MAP_TYPE_LPM_TRIE' val=11
    'BPF_MAP_TYPE_ARRAY_OF_MAPS' val=12
    'BPF_MAP_TYPE_HASH_OF_MAPS' val=13
    'BPF_MAP_TYPE_DEVMAP' val=14
    'BPF_MAP_TYPE_SOCKMAP' val=15
    'BPF_MAP_TYPE_CPUMAP' val=16
    'BPF_MAP_TYPE_XSKMAP' val=17
    'BPF_MAP_TYPE_SOCKHASH' val=18
    'BPF_MAP_TYPE_CGROUP_STORAGE' val=19
    'BPF_MAP_TYPE_REUSEPORT_SOCKARRAY' val=20
    'BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE' val=21
    'BPF_MAP_TYPE_QUEUE' val=22
    'BPF_MAP_TYPE_STACK' val=23
    'BPF_MAP_TYPE_SK_STORAGE' val=24
    'BPF_MAP_TYPE_DEVMAP_HASH' val=25
    'BPF_MAP_TYPE_STRUCT_OPS' val=26
    'BPF_MAP_TYPE_RINGBUF' val=27
    'BPF_MAP_TYPE_INODE_STORAGE' val=28
    'BPF_MAP_TYPE_TASK_STORAGE' val=29
    'BPF_MAP_TYPE_BLOOM_FILTER' val=30
[23] UNION '(anon)' size=8 vlen=1
    'flow_keys' type_id=29 bits_offset=0
[24] STRUCT 'bpf_flow_keys' size=56 vlen=13
    'nhoff' type_id=8 bits_offset=0
    'thoff' type_id=8 bits_offset=16
    'addr_proto' type_id=8 bits_offset=32
    'is_frag' type_id=3 bits_offset=48
    'is_first_frag' type_id=3 bits_offset=56
    'is_encap' type_id=3 bits_offset=64
    'ip_proto' type_id=3 bits_offset=72
    'n_proto' type_id=20 bits_offset=80
    'sport' type_id=20 bits_offset=96
    'dport' type_id=20 bits_offset=112
    '(anon)' type_id=25 bits_offset=128
    'flags' type_id=12 bits_offset=384
    'flow_label' type_id=21 bits_offset=416
[25] UNION '(anon)' size=32 vlen=2
    '(anon)' type_id=26 bits_offset=0
    '(anon)' type_id=27 bits_offset=0
[26] STRUCT '(anon)' size=8 vlen=2
    'ipv4_src' type_id=21 bits_offset=0
    'ipv4_dst' type_id=21 bits_offset=32
[27] STRUCT '(anon)' size=32 vlen=2
    'ipv6_src' type_id=28 bits_offset=0
    'ipv6_dst' type_id=28 bits_offset=128
[28] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=4
[29] PTR '(anon)' type_id=24
[30] UNION '(anon)' size=8 vlen=1
    'sk' type_id=32 bits_offset=0
[31] STRUCT 'bpf_sock' size=80 vlen=14
    'bound_dev_if' type_id=12 bits_offset=0
    'family' type_id=12 bits_offset=32
    'type' type_id=12 bits_offset=64
    'protocol' type_id=12 bits_offset=96
    'mark' type_id=12 bits_offset=128
    'priority' type_id=12 bits_offset=160
    'src_ip4' type_id=12 bits_offset=192
    'src_ip6' type_id=28 bits_offset=224
    'src_port' type_id=12 bits_offset=352
    'dst_port' type_id=20 bits_offset=384
    'dst_ip4' type_id=12 bits_offset=416
    'dst_ip6' type_id=28 bits_offset=448
    'state' type_id=12 bits_offset=576
    'rx_queue_mapping' type_id=10 bits_offset=608
[32] PTR '(anon)' type_id=31
[33] STRUCT '__sk_buff' size=192 vlen=33
    'len' type_id=12 bits_offset=0
    'pkt_type' type_id=12 bits_offset=32
    'mark' type_id=12 bits_offset=64
    'queue_mapping' type_id=12 bits_offset=96
    'protocol' type_id=12 bits_offset=128
    'vlan_present' type_id=12 bits_offset=160
    'vlan_tci' type_id=12 bits_offset=192
    'vlan_proto' type_id=12 bits_offset=224
    'priority' type_id=12 bits_offset=256
    'ingress_ifindex' type_id=12 bits_offset=288
    'ifindex' type_id=12 bits_offset=320
    'tc_index' type_id=12 bits_offset=352
    'cb' type_id=34 bits_offset=384
    'hash' type_id=12 bits_offset=544
    'tc_classid' type_id=12 bits_offset=576
    'data' type_id=12 bits_offset=608
    'data_end' type_id=12 bits_offset=640
    'napi_id' type_id=12 bits_offset=672
    'family' type_id=12 bits_offset=704
    'remote_ip4' type_id=12 bits_offset=736
    'local_ip4' type_id=12 bits_offset=768
    'remote_ip6' type_id=28 bits_offset=800
    'local_ip6' type_id=28 bits_offset=928
    'remote_port' type_id=12 bits_offset=1056
    'local_port' type_id=12 bits_offset=1088
    'data_meta' type_id=12 bits_offset=1120
    '(anon)' type_id=23 bits_offset=1152
    'tstamp' type_id=15 bits_offset=1216
    'wire_len' type_id=12 bits_offset=1280
    'gso_segs' type_id=12 bits_offset=1312
    '(anon)' type_id=30 bits_offset=1344
    'gso_size' type_id=12 bits_offset=1408
    'hwtstamp' type_id=15 bits_offset=1472
[34] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=5
[35] CONST '(anon)' type_id=33
[36] PTR '(anon)' type_id=0
[37] STRUCT '(anon)' size=24 vlen=3
    'type' type_id=39 bits_offset=0
    'key' type_id=40 bits_offset=64
    'value' type_id=41 bits_offset=128
[38] ARRAY '(anon)' type_id=9 index_type_id=16 nr_elems=1
[39] PTR '(anon)' type_id=38
[40] PTR '(anon)' type_id=12
[41] PTR '(anon)' type_id=3
[42] ARRAY '(anon)' type_id=19 index_type_id=16 nr_elems=18
[43] CONST '(anon)' type_id=42
[44] FUNC_PROTO '(anon)' ret_type_id=36 vlen=2
    '(anon)' type_id=36
    '(anon)' type_id=46
[45] CONST '(anon)' type_id=0
[46] PTR '(anon)' type_id=45
[47] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
    'sk' type_id=48
[48] PTR '(anon)' type_id=35
[49] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
    'sk' type_id=48
[50] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
    'sk' type_id=48
[51] VAR 'is_allow_list' type_id=5, linkage=global
[52] VAR '_license' type_id=43, linkage=static
[53] VAR 'sd_restrictif' type_id=37, linkage=global
[54] FUNC 'bpf_map_lookup_elem' type_id=44 linkage=static
[55] FUNC 'sd_restrictif_i' type_id=47 linkage=static
[56] FUNC 'sd_restrictif_e' type_id=49 linkage=static
[57] FUNC 'restrict_network_interfaces_impl' type_id=50 linkage=static
[58] DATASEC 'license' size=0 vlen=1
    type_id=52 offset=0 size=18 (VAR '_license')
[59] DATASEC '.maps' size=0 vlen=1
    type_id=53 offset=0 size=24 (VAR 'sd_restrictif')
[60] DATASEC '.data' size=0 vlen=1
    type_id=51 offset=0 size=1 (VAR 'is_allow_list')

>
> https://github.com/systemd/systemd/blob/main/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.c#L42-L50
>
>
> > GCC:
> >
> > [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> > [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
> > [3] TYPEDEF '__u8' type_id=2
> > [4] CONST '(anon)' type_id=3
>
> [...]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-07-06 17:49   ` James Hilliard
@ 2022-07-08 11:55     ` Jose E. Marchesi
  2022-07-08 12:23       ` James Hilliard
  0 siblings, 1 reply; 38+ messages in thread
From: Jose E. Marchesi @ 2022-07-08 11:55 UTC (permalink / raw)
  To: James Hilliard; +Cc: Andrii Nakryiko, bpf


> On Wed, Jul 6, 2022 at 11:20 AM Andrii Nakryiko
> <andrii.nakryiko@gmail.com> wrote:
>>
>> On Wed, Jul 6, 2022 at 10:13 AM James Hilliard
>> <james.hilliard1@gmail.com> wrote:
>> >
>> > Note I'm testing with the following patches:
>> > https://lore.kernel.org/bpf/20220706111839.1247911-1-james.hilliard1@gmail.com/
>> > https://lore.kernel.org/bpf/20220706140623.2917858-1-james.hilliard1@gmail.com/
>> >
>> > It would appear there's some compatibility issues with bpftool gen and
>> > GCC, not sure what side though is wrong here:
>> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>> > gen object src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>> > src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
>> > libbpf: failed to find BTF info for global/extern symbol 'sd_restrictif_i'
>> > Error: failed to link
>> > 'src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o':
>> > Unknown error -2 (-2)
>> >
>> > Relevant difference seems to be this:
>> > GCC:
>> > [55] FUNC 'sd_restrictif_i' type_id=47 linkage=static
>> > Clang:
>> > [27] FUNC 'sd_restrictif_i' type_id=26 linkage=global
>> >
>>
>> GCC is wrong, clearly. This function is global ([0]) and libbpf
>> expects it to be marked as such in BTF.
>
> Does this invocation look correct?
> /home/buildroot/buildroot/output/per-package/systemd/host/bin/bpf-gcc
> -O2 -mkernel=5.2 -mcpu=v3 -mco-re -gbtf -r -std=gnu11 -D__x86_64__
> -mlittle-endian -I. -idirafter
> /home/buildroot/buildroot/output/per-package/systemd/host/x86_64-buildroot-linux-gnu/sysroot/usr/include
> ../src/core/bpf/restrict_fs/restrict-fs.bpf.c -o
> src/core/bpf/restrict_fs/restrict-fs.bpf.unstripped.o

Hmm, why linking a relocatable ELF instead of just using a compiled
object (with -c)?

> I've also tried without the -r(relocatable object) flag but that gives
> a different error:
> /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> gen object src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
> libbpf: unsupported kind of ELF file
> src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o: no
> error
> Error: failed to link
> 'src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o':
> Unknown error -95 (-95)
>
> GCC without relocatable flag:
> [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
> [3] TYPEDEF '__u8' type_id=2
> [4] CONST '(anon)' type_id=3
> [5] VOLATILE '(anon)' type_id=4
> [6] INT 'short int' size=2 bits_offset=0 nr_bits=16 encoding=SIGNED
> [7] INT 'short unsigned int' size=2 bits_offset=0 nr_bits=16 encoding=(none)
> [8] TYPEDEF '__u16' type_id=7
> [9] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
> [10] TYPEDEF '__s32' type_id=9
> [11] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
> [12] TYPEDEF '__u32' type_id=11
> [13] INT 'long long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
> [14] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64
> encoding=(none)
> [15] TYPEDEF '__u64' type_id=14
> [16] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
> [17] INT 'long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
> [18] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> [19] CONST '(anon)' type_id=18
> [20] TYPEDEF '__be16' type_id=8
> [21] TYPEDEF '__be32' type_id=12
> [22] ENUM 'bpf_map_type' encoding=UNSIGNED size=4 vlen=31
>     'BPF_MAP_TYPE_UNSPEC' val=0
>     'BPF_MAP_TYPE_HASH' val=1
>     'BPF_MAP_TYPE_ARRAY' val=2
>     'BPF_MAP_TYPE_PROG_ARRAY' val=3
>     'BPF_MAP_TYPE_PERF_EVENT_ARRAY' val=4
>     'BPF_MAP_TYPE_PERCPU_HASH' val=5
>     'BPF_MAP_TYPE_PERCPU_ARRAY' val=6
>     'BPF_MAP_TYPE_STACK_TRACE' val=7
>     'BPF_MAP_TYPE_CGROUP_ARRAY' val=8
>     'BPF_MAP_TYPE_LRU_HASH' val=9
>     'BPF_MAP_TYPE_LRU_PERCPU_HASH' val=10
>     'BPF_MAP_TYPE_LPM_TRIE' val=11
>     'BPF_MAP_TYPE_ARRAY_OF_MAPS' val=12
>     'BPF_MAP_TYPE_HASH_OF_MAPS' val=13
>     'BPF_MAP_TYPE_DEVMAP' val=14
>     'BPF_MAP_TYPE_SOCKMAP' val=15
>     'BPF_MAP_TYPE_CPUMAP' val=16
>     'BPF_MAP_TYPE_XSKMAP' val=17
>     'BPF_MAP_TYPE_SOCKHASH' val=18
>     'BPF_MAP_TYPE_CGROUP_STORAGE' val=19
>     'BPF_MAP_TYPE_REUSEPORT_SOCKARRAY' val=20
>     'BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE' val=21
>     'BPF_MAP_TYPE_QUEUE' val=22
>     'BPF_MAP_TYPE_STACK' val=23
>     'BPF_MAP_TYPE_SK_STORAGE' val=24
>     'BPF_MAP_TYPE_DEVMAP_HASH' val=25
>     'BPF_MAP_TYPE_STRUCT_OPS' val=26
>     'BPF_MAP_TYPE_RINGBUF' val=27
>     'BPF_MAP_TYPE_INODE_STORAGE' val=28
>     'BPF_MAP_TYPE_TASK_STORAGE' val=29
>     'BPF_MAP_TYPE_BLOOM_FILTER' val=30
> [23] UNION '(anon)' size=8 vlen=1
>     'flow_keys' type_id=29 bits_offset=0
> [24] STRUCT 'bpf_flow_keys' size=56 vlen=13
>     'nhoff' type_id=8 bits_offset=0
>     'thoff' type_id=8 bits_offset=16
>     'addr_proto' type_id=8 bits_offset=32
>     'is_frag' type_id=3 bits_offset=48
>     'is_first_frag' type_id=3 bits_offset=56
>     'is_encap' type_id=3 bits_offset=64
>     'ip_proto' type_id=3 bits_offset=72
>     'n_proto' type_id=20 bits_offset=80
>     'sport' type_id=20 bits_offset=96
>     'dport' type_id=20 bits_offset=112
>     '(anon)' type_id=25 bits_offset=128
>     'flags' type_id=12 bits_offset=384
>     'flow_label' type_id=21 bits_offset=416
> [25] UNION '(anon)' size=32 vlen=2
>     '(anon)' type_id=26 bits_offset=0
>     '(anon)' type_id=27 bits_offset=0
> [26] STRUCT '(anon)' size=8 vlen=2
>     'ipv4_src' type_id=21 bits_offset=0
>     'ipv4_dst' type_id=21 bits_offset=32
> [27] STRUCT '(anon)' size=32 vlen=2
>     'ipv6_src' type_id=28 bits_offset=0
>     'ipv6_dst' type_id=28 bits_offset=128
> [28] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=4
> [29] PTR '(anon)' type_id=24
> [30] UNION '(anon)' size=8 vlen=1
>     'sk' type_id=32 bits_offset=0
> [31] STRUCT 'bpf_sock' size=80 vlen=14
>     'bound_dev_if' type_id=12 bits_offset=0
>     'family' type_id=12 bits_offset=32
>     'type' type_id=12 bits_offset=64
>     'protocol' type_id=12 bits_offset=96
>     'mark' type_id=12 bits_offset=128
>     'priority' type_id=12 bits_offset=160
>     'src_ip4' type_id=12 bits_offset=192
>     'src_ip6' type_id=28 bits_offset=224
>     'src_port' type_id=12 bits_offset=352
>     'dst_port' type_id=20 bits_offset=384
>     'dst_ip4' type_id=12 bits_offset=416
>     'dst_ip6' type_id=28 bits_offset=448
>     'state' type_id=12 bits_offset=576
>     'rx_queue_mapping' type_id=10 bits_offset=608
> [32] PTR '(anon)' type_id=31
> [33] STRUCT '__sk_buff' size=192 vlen=33
>     'len' type_id=12 bits_offset=0
>     'pkt_type' type_id=12 bits_offset=32
>     'mark' type_id=12 bits_offset=64
>     'queue_mapping' type_id=12 bits_offset=96
>     'protocol' type_id=12 bits_offset=128
>     'vlan_present' type_id=12 bits_offset=160
>     'vlan_tci' type_id=12 bits_offset=192
>     'vlan_proto' type_id=12 bits_offset=224
>     'priority' type_id=12 bits_offset=256
>     'ingress_ifindex' type_id=12 bits_offset=288
>     'ifindex' type_id=12 bits_offset=320
>     'tc_index' type_id=12 bits_offset=352
>     'cb' type_id=34 bits_offset=384
>     'hash' type_id=12 bits_offset=544
>     'tc_classid' type_id=12 bits_offset=576
>     'data' type_id=12 bits_offset=608
>     'data_end' type_id=12 bits_offset=640
>     'napi_id' type_id=12 bits_offset=672
>     'family' type_id=12 bits_offset=704
>     'remote_ip4' type_id=12 bits_offset=736
>     'local_ip4' type_id=12 bits_offset=768
>     'remote_ip6' type_id=28 bits_offset=800
>     'local_ip6' type_id=28 bits_offset=928
>     'remote_port' type_id=12 bits_offset=1056
>     'local_port' type_id=12 bits_offset=1088
>     'data_meta' type_id=12 bits_offset=1120
>     '(anon)' type_id=23 bits_offset=1152
>     'tstamp' type_id=15 bits_offset=1216
>     'wire_len' type_id=12 bits_offset=1280
>     'gso_segs' type_id=12 bits_offset=1312
>     '(anon)' type_id=30 bits_offset=1344
>     'gso_size' type_id=12 bits_offset=1408
>     'hwtstamp' type_id=15 bits_offset=1472
> [34] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=5
> [35] CONST '(anon)' type_id=33
> [36] PTR '(anon)' type_id=0
> [37] STRUCT '(anon)' size=24 vlen=3
>     'type' type_id=39 bits_offset=0
>     'key' type_id=40 bits_offset=64
>     'value' type_id=41 bits_offset=128
> [38] ARRAY '(anon)' type_id=9 index_type_id=16 nr_elems=1
> [39] PTR '(anon)' type_id=38
> [40] PTR '(anon)' type_id=12
> [41] PTR '(anon)' type_id=3
> [42] ARRAY '(anon)' type_id=19 index_type_id=16 nr_elems=18
> [43] CONST '(anon)' type_id=42
> [44] FUNC_PROTO '(anon)' ret_type_id=36 vlen=2
>     '(anon)' type_id=36
>     '(anon)' type_id=46
> [45] CONST '(anon)' type_id=0
> [46] PTR '(anon)' type_id=45
> [47] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>     'sk' type_id=48
> [48] PTR '(anon)' type_id=35
> [49] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>     'sk' type_id=48
> [50] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>     'sk' type_id=48
> [51] VAR 'is_allow_list' type_id=5, linkage=global
> [52] VAR '_license' type_id=43, linkage=static
> [53] VAR 'sd_restrictif' type_id=37, linkage=global
> [54] FUNC 'bpf_map_lookup_elem' type_id=44 linkage=static
> [55] FUNC 'sd_restrictif_i' type_id=47 linkage=static
> [56] FUNC 'sd_restrictif_e' type_id=49 linkage=static
> [57] FUNC 'restrict_network_interfaces_impl' type_id=50 linkage=static
> [58] DATASEC 'license' size=0 vlen=1
>     type_id=52 offset=0 size=18 (VAR '_license')
> [59] DATASEC '.maps' size=0 vlen=1
>     type_id=53 offset=0 size=24 (VAR 'sd_restrictif')
> [60] DATASEC '.data' size=0 vlen=1
>     type_id=51 offset=0 size=1 (VAR 'is_allow_list')
>
>>
>> https://github.com/systemd/systemd/blob/main/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.c#L42-L50
>>
>>
>> > GCC:
>> >
>> > [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>> > [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
>> > [3] TYPEDEF '__u8' type_id=2
>> > [4] CONST '(anon)' type_id=3
>>
>> [...]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-07-08 11:55     ` Jose E. Marchesi
@ 2022-07-08 12:23       ` James Hilliard
  2022-07-08 13:46         ` Jose E. Marchesi
  0 siblings, 1 reply; 38+ messages in thread
From: James Hilliard @ 2022-07-08 12:23 UTC (permalink / raw)
  To: Jose E. Marchesi; +Cc: Andrii Nakryiko, bpf

On Fri, Jul 8, 2022 at 5:56 AM Jose E. Marchesi
<jose.marchesi@oracle.com> wrote:
>
>
> > On Wed, Jul 6, 2022 at 11:20 AM Andrii Nakryiko
> > <andrii.nakryiko@gmail.com> wrote:
> >>
> >> On Wed, Jul 6, 2022 at 10:13 AM James Hilliard
> >> <james.hilliard1@gmail.com> wrote:
> >> >
> >> > Note I'm testing with the following patches:
> >> > https://lore.kernel.org/bpf/20220706111839.1247911-1-james.hilliard1@gmail.com/
> >> > https://lore.kernel.org/bpf/20220706140623.2917858-1-james.hilliard1@gmail.com/
> >> >
> >> > It would appear there's some compatibility issues with bpftool gen and
> >> > GCC, not sure what side though is wrong here:
> >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> >> > gen object src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> >> > src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
> >> > libbpf: failed to find BTF info for global/extern symbol 'sd_restrictif_i'
> >> > Error: failed to link
> >> > 'src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o':
> >> > Unknown error -2 (-2)
> >> >
> >> > Relevant difference seems to be this:
> >> > GCC:
> >> > [55] FUNC 'sd_restrictif_i' type_id=47 linkage=static
> >> > Clang:
> >> > [27] FUNC 'sd_restrictif_i' type_id=26 linkage=global
> >> >
> >>
> >> GCC is wrong, clearly. This function is global ([0]) and libbpf
> >> expects it to be marked as such in BTF.
> >
> > Does this invocation look correct?
> > /home/buildroot/buildroot/output/per-package/systemd/host/bin/bpf-gcc
> > -O2 -mkernel=5.2 -mcpu=v3 -mco-re -gbtf -r -std=gnu11 -D__x86_64__
> > -mlittle-endian -I. -idirafter
> > /home/buildroot/buildroot/output/per-package/systemd/host/x86_64-buildroot-linux-gnu/sysroot/usr/include
> > ../src/core/bpf/restrict_fs/restrict-fs.bpf.c -o
> > src/core/bpf/restrict_fs/restrict-fs.bpf.unstripped.o
>
> Hmm, why linking a relocatable ELF instead of just using a compiled
> object (with -c)?

This bpftool gen object build stage AFAIU is needed to strip the object before
using it for skeleton generation, does that sound right?

>
> > I've also tried without the -r(relocatable object) flag but that gives
> > a different error:
> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> > gen object src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> > src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
> > libbpf: unsupported kind of ELF file
> > src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o: no
> > error
> > Error: failed to link
> > 'src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o':
> > Unknown error -95 (-95)
> >
> > GCC without relocatable flag:
> > [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> > [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
> > [3] TYPEDEF '__u8' type_id=2
> > [4] CONST '(anon)' type_id=3
> > [5] VOLATILE '(anon)' type_id=4
> > [6] INT 'short int' size=2 bits_offset=0 nr_bits=16 encoding=SIGNED
> > [7] INT 'short unsigned int' size=2 bits_offset=0 nr_bits=16 encoding=(none)
> > [8] TYPEDEF '__u16' type_id=7
> > [9] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
> > [10] TYPEDEF '__s32' type_id=9
> > [11] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
> > [12] TYPEDEF '__u32' type_id=11
> > [13] INT 'long long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
> > [14] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64
> > encoding=(none)
> > [15] TYPEDEF '__u64' type_id=14
> > [16] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
> > [17] INT 'long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
> > [18] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> > [19] CONST '(anon)' type_id=18
> > [20] TYPEDEF '__be16' type_id=8
> > [21] TYPEDEF '__be32' type_id=12
> > [22] ENUM 'bpf_map_type' encoding=UNSIGNED size=4 vlen=31
> >     'BPF_MAP_TYPE_UNSPEC' val=0
> >     'BPF_MAP_TYPE_HASH' val=1
> >     'BPF_MAP_TYPE_ARRAY' val=2
> >     'BPF_MAP_TYPE_PROG_ARRAY' val=3
> >     'BPF_MAP_TYPE_PERF_EVENT_ARRAY' val=4
> >     'BPF_MAP_TYPE_PERCPU_HASH' val=5
> >     'BPF_MAP_TYPE_PERCPU_ARRAY' val=6
> >     'BPF_MAP_TYPE_STACK_TRACE' val=7
> >     'BPF_MAP_TYPE_CGROUP_ARRAY' val=8
> >     'BPF_MAP_TYPE_LRU_HASH' val=9
> >     'BPF_MAP_TYPE_LRU_PERCPU_HASH' val=10
> >     'BPF_MAP_TYPE_LPM_TRIE' val=11
> >     'BPF_MAP_TYPE_ARRAY_OF_MAPS' val=12
> >     'BPF_MAP_TYPE_HASH_OF_MAPS' val=13
> >     'BPF_MAP_TYPE_DEVMAP' val=14
> >     'BPF_MAP_TYPE_SOCKMAP' val=15
> >     'BPF_MAP_TYPE_CPUMAP' val=16
> >     'BPF_MAP_TYPE_XSKMAP' val=17
> >     'BPF_MAP_TYPE_SOCKHASH' val=18
> >     'BPF_MAP_TYPE_CGROUP_STORAGE' val=19
> >     'BPF_MAP_TYPE_REUSEPORT_SOCKARRAY' val=20
> >     'BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE' val=21
> >     'BPF_MAP_TYPE_QUEUE' val=22
> >     'BPF_MAP_TYPE_STACK' val=23
> >     'BPF_MAP_TYPE_SK_STORAGE' val=24
> >     'BPF_MAP_TYPE_DEVMAP_HASH' val=25
> >     'BPF_MAP_TYPE_STRUCT_OPS' val=26
> >     'BPF_MAP_TYPE_RINGBUF' val=27
> >     'BPF_MAP_TYPE_INODE_STORAGE' val=28
> >     'BPF_MAP_TYPE_TASK_STORAGE' val=29
> >     'BPF_MAP_TYPE_BLOOM_FILTER' val=30
> > [23] UNION '(anon)' size=8 vlen=1
> >     'flow_keys' type_id=29 bits_offset=0
> > [24] STRUCT 'bpf_flow_keys' size=56 vlen=13
> >     'nhoff' type_id=8 bits_offset=0
> >     'thoff' type_id=8 bits_offset=16
> >     'addr_proto' type_id=8 bits_offset=32
> >     'is_frag' type_id=3 bits_offset=48
> >     'is_first_frag' type_id=3 bits_offset=56
> >     'is_encap' type_id=3 bits_offset=64
> >     'ip_proto' type_id=3 bits_offset=72
> >     'n_proto' type_id=20 bits_offset=80
> >     'sport' type_id=20 bits_offset=96
> >     'dport' type_id=20 bits_offset=112
> >     '(anon)' type_id=25 bits_offset=128
> >     'flags' type_id=12 bits_offset=384
> >     'flow_label' type_id=21 bits_offset=416
> > [25] UNION '(anon)' size=32 vlen=2
> >     '(anon)' type_id=26 bits_offset=0
> >     '(anon)' type_id=27 bits_offset=0
> > [26] STRUCT '(anon)' size=8 vlen=2
> >     'ipv4_src' type_id=21 bits_offset=0
> >     'ipv4_dst' type_id=21 bits_offset=32
> > [27] STRUCT '(anon)' size=32 vlen=2
> >     'ipv6_src' type_id=28 bits_offset=0
> >     'ipv6_dst' type_id=28 bits_offset=128
> > [28] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=4
> > [29] PTR '(anon)' type_id=24
> > [30] UNION '(anon)' size=8 vlen=1
> >     'sk' type_id=32 bits_offset=0
> > [31] STRUCT 'bpf_sock' size=80 vlen=14
> >     'bound_dev_if' type_id=12 bits_offset=0
> >     'family' type_id=12 bits_offset=32
> >     'type' type_id=12 bits_offset=64
> >     'protocol' type_id=12 bits_offset=96
> >     'mark' type_id=12 bits_offset=128
> >     'priority' type_id=12 bits_offset=160
> >     'src_ip4' type_id=12 bits_offset=192
> >     'src_ip6' type_id=28 bits_offset=224
> >     'src_port' type_id=12 bits_offset=352
> >     'dst_port' type_id=20 bits_offset=384
> >     'dst_ip4' type_id=12 bits_offset=416
> >     'dst_ip6' type_id=28 bits_offset=448
> >     'state' type_id=12 bits_offset=576
> >     'rx_queue_mapping' type_id=10 bits_offset=608
> > [32] PTR '(anon)' type_id=31
> > [33] STRUCT '__sk_buff' size=192 vlen=33
> >     'len' type_id=12 bits_offset=0
> >     'pkt_type' type_id=12 bits_offset=32
> >     'mark' type_id=12 bits_offset=64
> >     'queue_mapping' type_id=12 bits_offset=96
> >     'protocol' type_id=12 bits_offset=128
> >     'vlan_present' type_id=12 bits_offset=160
> >     'vlan_tci' type_id=12 bits_offset=192
> >     'vlan_proto' type_id=12 bits_offset=224
> >     'priority' type_id=12 bits_offset=256
> >     'ingress_ifindex' type_id=12 bits_offset=288
> >     'ifindex' type_id=12 bits_offset=320
> >     'tc_index' type_id=12 bits_offset=352
> >     'cb' type_id=34 bits_offset=384
> >     'hash' type_id=12 bits_offset=544
> >     'tc_classid' type_id=12 bits_offset=576
> >     'data' type_id=12 bits_offset=608
> >     'data_end' type_id=12 bits_offset=640
> >     'napi_id' type_id=12 bits_offset=672
> >     'family' type_id=12 bits_offset=704
> >     'remote_ip4' type_id=12 bits_offset=736
> >     'local_ip4' type_id=12 bits_offset=768
> >     'remote_ip6' type_id=28 bits_offset=800
> >     'local_ip6' type_id=28 bits_offset=928
> >     'remote_port' type_id=12 bits_offset=1056
> >     'local_port' type_id=12 bits_offset=1088
> >     'data_meta' type_id=12 bits_offset=1120
> >     '(anon)' type_id=23 bits_offset=1152
> >     'tstamp' type_id=15 bits_offset=1216
> >     'wire_len' type_id=12 bits_offset=1280
> >     'gso_segs' type_id=12 bits_offset=1312
> >     '(anon)' type_id=30 bits_offset=1344
> >     'gso_size' type_id=12 bits_offset=1408
> >     'hwtstamp' type_id=15 bits_offset=1472
> > [34] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=5
> > [35] CONST '(anon)' type_id=33
> > [36] PTR '(anon)' type_id=0
> > [37] STRUCT '(anon)' size=24 vlen=3
> >     'type' type_id=39 bits_offset=0
> >     'key' type_id=40 bits_offset=64
> >     'value' type_id=41 bits_offset=128
> > [38] ARRAY '(anon)' type_id=9 index_type_id=16 nr_elems=1
> > [39] PTR '(anon)' type_id=38
> > [40] PTR '(anon)' type_id=12
> > [41] PTR '(anon)' type_id=3
> > [42] ARRAY '(anon)' type_id=19 index_type_id=16 nr_elems=18
> > [43] CONST '(anon)' type_id=42
> > [44] FUNC_PROTO '(anon)' ret_type_id=36 vlen=2
> >     '(anon)' type_id=36
> >     '(anon)' type_id=46
> > [45] CONST '(anon)' type_id=0
> > [46] PTR '(anon)' type_id=45
> > [47] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
> >     'sk' type_id=48
> > [48] PTR '(anon)' type_id=35
> > [49] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
> >     'sk' type_id=48
> > [50] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
> >     'sk' type_id=48
> > [51] VAR 'is_allow_list' type_id=5, linkage=global
> > [52] VAR '_license' type_id=43, linkage=static
> > [53] VAR 'sd_restrictif' type_id=37, linkage=global
> > [54] FUNC 'bpf_map_lookup_elem' type_id=44 linkage=static
> > [55] FUNC 'sd_restrictif_i' type_id=47 linkage=static
> > [56] FUNC 'sd_restrictif_e' type_id=49 linkage=static
> > [57] FUNC 'restrict_network_interfaces_impl' type_id=50 linkage=static
> > [58] DATASEC 'license' size=0 vlen=1
> >     type_id=52 offset=0 size=18 (VAR '_license')
> > [59] DATASEC '.maps' size=0 vlen=1
> >     type_id=53 offset=0 size=24 (VAR 'sd_restrictif')
> > [60] DATASEC '.data' size=0 vlen=1
> >     type_id=51 offset=0 size=1 (VAR 'is_allow_list')
> >
> >>
> >> https://github.com/systemd/systemd/blob/main/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.c#L42-L50
> >>
> >>
> >> > GCC:
> >> >
> >> > [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> >> > [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
> >> > [3] TYPEDEF '__u8' type_id=2
> >> > [4] CONST '(anon)' type_id=3
> >>
> >> [...]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-07-08 12:23       ` James Hilliard
@ 2022-07-08 13:46         ` Jose E. Marchesi
  2022-07-08 13:53           ` James Hilliard
  0 siblings, 1 reply; 38+ messages in thread
From: Jose E. Marchesi @ 2022-07-08 13:46 UTC (permalink / raw)
  To: James Hilliard; +Cc: Andrii Nakryiko, bpf


> On Fri, Jul 8, 2022 at 5:56 AM Jose E. Marchesi
> <jose.marchesi@oracle.com> wrote:
>>
>>
>> > On Wed, Jul 6, 2022 at 11:20 AM Andrii Nakryiko
>> > <andrii.nakryiko@gmail.com> wrote:
>> >>
>> >> On Wed, Jul 6, 2022 at 10:13 AM James Hilliard
>> >> <james.hilliard1@gmail.com> wrote:
>> >> >
>> >> > Note I'm testing with the following patches:
>> >> > https://lore.kernel.org/bpf/20220706111839.1247911-1-james.hilliard1@gmail.com/
>> >> > https://lore.kernel.org/bpf/20220706140623.2917858-1-james.hilliard1@gmail.com/
>> >> >
>> >> > It would appear there's some compatibility issues with bpftool gen and
>> >> > GCC, not sure what side though is wrong here:
>> >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>> >> > gen object src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>> >> > src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
>> >> > libbpf: failed to find BTF info for global/extern symbol 'sd_restrictif_i'
>> >> > Error: failed to link
>> >> > 'src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o':
>> >> > Unknown error -2 (-2)
>> >> >
>> >> > Relevant difference seems to be this:
>> >> > GCC:
>> >> > [55] FUNC 'sd_restrictif_i' type_id=47 linkage=static
>> >> > Clang:
>> >> > [27] FUNC 'sd_restrictif_i' type_id=26 linkage=global
>> >> >
>> >>
>> >> GCC is wrong, clearly. This function is global ([0]) and libbpf
>> >> expects it to be marked as such in BTF.
>> >
>> > Does this invocation look correct?
>> > /home/buildroot/buildroot/output/per-package/systemd/host/bin/bpf-gcc
>> > -O2 -mkernel=5.2 -mcpu=v3 -mco-re -gbtf -r -std=gnu11 -D__x86_64__
>> > -mlittle-endian -I. -idirafter
>> > /home/buildroot/buildroot/output/per-package/systemd/host/x86_64-buildroot-linux-gnu/sysroot/usr/include
>> > ../src/core/bpf/restrict_fs/restrict-fs.bpf.c -o
>> > src/core/bpf/restrict_fs/restrict-fs.bpf.unstripped.o
>>
>> Hmm, why linking a relocatable ELF instead of just using a compiled
>> object (with -c)?
>
> This bpftool gen object build stage AFAIU is needed to strip the object before
> using it for skeleton generation, does that sound right?

Thing is, `gcc -r' involves the linker.  The GNU linker (ld) supports
linking BPF objects, but AFAIK the kernel BPF objects are all supposed
to be compiled objects, not linked as relocatable objects.  (The LLVM
BPF toolchain doesn't support linking BPF objects as far as I know.)

That's my understanding, but note I'm not very familiar with bpftool
(I'm trying to find time now to fix that.)

>>
>> > I've also tried without the -r(relocatable object) flag but that gives
>> > a different error:
>> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>> > gen object src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>> > src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
>> > libbpf: unsupported kind of ELF file
>> > src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o: no
>> > error
>> > Error: failed to link
>> > 'src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o':
>> > Unknown error -95 (-95)
>> >
>> > GCC without relocatable flag:
>> > [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>> > [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
>> > [3] TYPEDEF '__u8' type_id=2
>> > [4] CONST '(anon)' type_id=3
>> > [5] VOLATILE '(anon)' type_id=4
>> > [6] INT 'short int' size=2 bits_offset=0 nr_bits=16 encoding=SIGNED
>> > [7] INT 'short unsigned int' size=2 bits_offset=0 nr_bits=16 encoding=(none)
>> > [8] TYPEDEF '__u16' type_id=7
>> > [9] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
>> > [10] TYPEDEF '__s32' type_id=9
>> > [11] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
>> > [12] TYPEDEF '__u32' type_id=11
>> > [13] INT 'long long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
>> > [14] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64
>> > encoding=(none)
>> > [15] TYPEDEF '__u64' type_id=14
>> > [16] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
>> > [17] INT 'long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
>> > [18] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>> > [19] CONST '(anon)' type_id=18
>> > [20] TYPEDEF '__be16' type_id=8
>> > [21] TYPEDEF '__be32' type_id=12
>> > [22] ENUM 'bpf_map_type' encoding=UNSIGNED size=4 vlen=31
>> >     'BPF_MAP_TYPE_UNSPEC' val=0
>> >     'BPF_MAP_TYPE_HASH' val=1
>> >     'BPF_MAP_TYPE_ARRAY' val=2
>> >     'BPF_MAP_TYPE_PROG_ARRAY' val=3
>> >     'BPF_MAP_TYPE_PERF_EVENT_ARRAY' val=4
>> >     'BPF_MAP_TYPE_PERCPU_HASH' val=5
>> >     'BPF_MAP_TYPE_PERCPU_ARRAY' val=6
>> >     'BPF_MAP_TYPE_STACK_TRACE' val=7
>> >     'BPF_MAP_TYPE_CGROUP_ARRAY' val=8
>> >     'BPF_MAP_TYPE_LRU_HASH' val=9
>> >     'BPF_MAP_TYPE_LRU_PERCPU_HASH' val=10
>> >     'BPF_MAP_TYPE_LPM_TRIE' val=11
>> >     'BPF_MAP_TYPE_ARRAY_OF_MAPS' val=12
>> >     'BPF_MAP_TYPE_HASH_OF_MAPS' val=13
>> >     'BPF_MAP_TYPE_DEVMAP' val=14
>> >     'BPF_MAP_TYPE_SOCKMAP' val=15
>> >     'BPF_MAP_TYPE_CPUMAP' val=16
>> >     'BPF_MAP_TYPE_XSKMAP' val=17
>> >     'BPF_MAP_TYPE_SOCKHASH' val=18
>> >     'BPF_MAP_TYPE_CGROUP_STORAGE' val=19
>> >     'BPF_MAP_TYPE_REUSEPORT_SOCKARRAY' val=20
>> >     'BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE' val=21
>> >     'BPF_MAP_TYPE_QUEUE' val=22
>> >     'BPF_MAP_TYPE_STACK' val=23
>> >     'BPF_MAP_TYPE_SK_STORAGE' val=24
>> >     'BPF_MAP_TYPE_DEVMAP_HASH' val=25
>> >     'BPF_MAP_TYPE_STRUCT_OPS' val=26
>> >     'BPF_MAP_TYPE_RINGBUF' val=27
>> >     'BPF_MAP_TYPE_INODE_STORAGE' val=28
>> >     'BPF_MAP_TYPE_TASK_STORAGE' val=29
>> >     'BPF_MAP_TYPE_BLOOM_FILTER' val=30
>> > [23] UNION '(anon)' size=8 vlen=1
>> >     'flow_keys' type_id=29 bits_offset=0
>> > [24] STRUCT 'bpf_flow_keys' size=56 vlen=13
>> >     'nhoff' type_id=8 bits_offset=0
>> >     'thoff' type_id=8 bits_offset=16
>> >     'addr_proto' type_id=8 bits_offset=32
>> >     'is_frag' type_id=3 bits_offset=48
>> >     'is_first_frag' type_id=3 bits_offset=56
>> >     'is_encap' type_id=3 bits_offset=64
>> >     'ip_proto' type_id=3 bits_offset=72
>> >     'n_proto' type_id=20 bits_offset=80
>> >     'sport' type_id=20 bits_offset=96
>> >     'dport' type_id=20 bits_offset=112
>> >     '(anon)' type_id=25 bits_offset=128
>> >     'flags' type_id=12 bits_offset=384
>> >     'flow_label' type_id=21 bits_offset=416
>> > [25] UNION '(anon)' size=32 vlen=2
>> >     '(anon)' type_id=26 bits_offset=0
>> >     '(anon)' type_id=27 bits_offset=0
>> > [26] STRUCT '(anon)' size=8 vlen=2
>> >     'ipv4_src' type_id=21 bits_offset=0
>> >     'ipv4_dst' type_id=21 bits_offset=32
>> > [27] STRUCT '(anon)' size=32 vlen=2
>> >     'ipv6_src' type_id=28 bits_offset=0
>> >     'ipv6_dst' type_id=28 bits_offset=128
>> > [28] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=4
>> > [29] PTR '(anon)' type_id=24
>> > [30] UNION '(anon)' size=8 vlen=1
>> >     'sk' type_id=32 bits_offset=0
>> > [31] STRUCT 'bpf_sock' size=80 vlen=14
>> >     'bound_dev_if' type_id=12 bits_offset=0
>> >     'family' type_id=12 bits_offset=32
>> >     'type' type_id=12 bits_offset=64
>> >     'protocol' type_id=12 bits_offset=96
>> >     'mark' type_id=12 bits_offset=128
>> >     'priority' type_id=12 bits_offset=160
>> >     'src_ip4' type_id=12 bits_offset=192
>> >     'src_ip6' type_id=28 bits_offset=224
>> >     'src_port' type_id=12 bits_offset=352
>> >     'dst_port' type_id=20 bits_offset=384
>> >     'dst_ip4' type_id=12 bits_offset=416
>> >     'dst_ip6' type_id=28 bits_offset=448
>> >     'state' type_id=12 bits_offset=576
>> >     'rx_queue_mapping' type_id=10 bits_offset=608
>> > [32] PTR '(anon)' type_id=31
>> > [33] STRUCT '__sk_buff' size=192 vlen=33
>> >     'len' type_id=12 bits_offset=0
>> >     'pkt_type' type_id=12 bits_offset=32
>> >     'mark' type_id=12 bits_offset=64
>> >     'queue_mapping' type_id=12 bits_offset=96
>> >     'protocol' type_id=12 bits_offset=128
>> >     'vlan_present' type_id=12 bits_offset=160
>> >     'vlan_tci' type_id=12 bits_offset=192
>> >     'vlan_proto' type_id=12 bits_offset=224
>> >     'priority' type_id=12 bits_offset=256
>> >     'ingress_ifindex' type_id=12 bits_offset=288
>> >     'ifindex' type_id=12 bits_offset=320
>> >     'tc_index' type_id=12 bits_offset=352
>> >     'cb' type_id=34 bits_offset=384
>> >     'hash' type_id=12 bits_offset=544
>> >     'tc_classid' type_id=12 bits_offset=576
>> >     'data' type_id=12 bits_offset=608
>> >     'data_end' type_id=12 bits_offset=640
>> >     'napi_id' type_id=12 bits_offset=672
>> >     'family' type_id=12 bits_offset=704
>> >     'remote_ip4' type_id=12 bits_offset=736
>> >     'local_ip4' type_id=12 bits_offset=768
>> >     'remote_ip6' type_id=28 bits_offset=800
>> >     'local_ip6' type_id=28 bits_offset=928
>> >     'remote_port' type_id=12 bits_offset=1056
>> >     'local_port' type_id=12 bits_offset=1088
>> >     'data_meta' type_id=12 bits_offset=1120
>> >     '(anon)' type_id=23 bits_offset=1152
>> >     'tstamp' type_id=15 bits_offset=1216
>> >     'wire_len' type_id=12 bits_offset=1280
>> >     'gso_segs' type_id=12 bits_offset=1312
>> >     '(anon)' type_id=30 bits_offset=1344
>> >     'gso_size' type_id=12 bits_offset=1408
>> >     'hwtstamp' type_id=15 bits_offset=1472
>> > [34] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=5
>> > [35] CONST '(anon)' type_id=33
>> > [36] PTR '(anon)' type_id=0
>> > [37] STRUCT '(anon)' size=24 vlen=3
>> >     'type' type_id=39 bits_offset=0
>> >     'key' type_id=40 bits_offset=64
>> >     'value' type_id=41 bits_offset=128
>> > [38] ARRAY '(anon)' type_id=9 index_type_id=16 nr_elems=1
>> > [39] PTR '(anon)' type_id=38
>> > [40] PTR '(anon)' type_id=12
>> > [41] PTR '(anon)' type_id=3
>> > [42] ARRAY '(anon)' type_id=19 index_type_id=16 nr_elems=18
>> > [43] CONST '(anon)' type_id=42
>> > [44] FUNC_PROTO '(anon)' ret_type_id=36 vlen=2
>> >     '(anon)' type_id=36
>> >     '(anon)' type_id=46
>> > [45] CONST '(anon)' type_id=0
>> > [46] PTR '(anon)' type_id=45
>> > [47] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>> >     'sk' type_id=48
>> > [48] PTR '(anon)' type_id=35
>> > [49] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>> >     'sk' type_id=48
>> > [50] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>> >     'sk' type_id=48
>> > [51] VAR 'is_allow_list' type_id=5, linkage=global
>> > [52] VAR '_license' type_id=43, linkage=static
>> > [53] VAR 'sd_restrictif' type_id=37, linkage=global
>> > [54] FUNC 'bpf_map_lookup_elem' type_id=44 linkage=static
>> > [55] FUNC 'sd_restrictif_i' type_id=47 linkage=static
>> > [56] FUNC 'sd_restrictif_e' type_id=49 linkage=static
>> > [57] FUNC 'restrict_network_interfaces_impl' type_id=50 linkage=static
>> > [58] DATASEC 'license' size=0 vlen=1
>> >     type_id=52 offset=0 size=18 (VAR '_license')
>> > [59] DATASEC '.maps' size=0 vlen=1
>> >     type_id=53 offset=0 size=24 (VAR 'sd_restrictif')
>> > [60] DATASEC '.data' size=0 vlen=1
>> >     type_id=51 offset=0 size=1 (VAR 'is_allow_list')
>> >
>> >>
>> >> https://github.com/systemd/systemd/blob/main/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.c#L42-L50
>> >>
>> >>
>> >> > GCC:
>> >> >
>> >> > [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>> >> > [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
>> >> > [3] TYPEDEF '__u8' type_id=2
>> >> > [4] CONST '(anon)' type_id=3
>> >>
>> >> [...]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-07-08 13:46         ` Jose E. Marchesi
@ 2022-07-08 13:53           ` James Hilliard
  2022-07-08 14:39             ` Jose E. Marchesi
  0 siblings, 1 reply; 38+ messages in thread
From: James Hilliard @ 2022-07-08 13:53 UTC (permalink / raw)
  To: Jose E. Marchesi; +Cc: Andrii Nakryiko, bpf

On Fri, Jul 8, 2022 at 7:46 AM Jose E. Marchesi
<jose.marchesi@oracle.com> wrote:
>
>
> > On Fri, Jul 8, 2022 at 5:56 AM Jose E. Marchesi
> > <jose.marchesi@oracle.com> wrote:
> >>
> >>
> >> > On Wed, Jul 6, 2022 at 11:20 AM Andrii Nakryiko
> >> > <andrii.nakryiko@gmail.com> wrote:
> >> >>
> >> >> On Wed, Jul 6, 2022 at 10:13 AM James Hilliard
> >> >> <james.hilliard1@gmail.com> wrote:
> >> >> >
> >> >> > Note I'm testing with the following patches:
> >> >> > https://lore.kernel.org/bpf/20220706111839.1247911-1-james.hilliard1@gmail.com/
> >> >> > https://lore.kernel.org/bpf/20220706140623.2917858-1-james.hilliard1@gmail.com/
> >> >> >
> >> >> > It would appear there's some compatibility issues with bpftool gen and
> >> >> > GCC, not sure what side though is wrong here:
> >> >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> >> >> > gen object src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> >> >> > src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
> >> >> > libbpf: failed to find BTF info for global/extern symbol 'sd_restrictif_i'
> >> >> > Error: failed to link
> >> >> > 'src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o':
> >> >> > Unknown error -2 (-2)
> >> >> >
> >> >> > Relevant difference seems to be this:
> >> >> > GCC:
> >> >> > [55] FUNC 'sd_restrictif_i' type_id=47 linkage=static
> >> >> > Clang:
> >> >> > [27] FUNC 'sd_restrictif_i' type_id=26 linkage=global
> >> >> >
> >> >>
> >> >> GCC is wrong, clearly. This function is global ([0]) and libbpf
> >> >> expects it to be marked as such in BTF.
> >> >
> >> > Does this invocation look correct?
> >> > /home/buildroot/buildroot/output/per-package/systemd/host/bin/bpf-gcc
> >> > -O2 -mkernel=5.2 -mcpu=v3 -mco-re -gbtf -r -std=gnu11 -D__x86_64__
> >> > -mlittle-endian -I. -idirafter
> >> > /home/buildroot/buildroot/output/per-package/systemd/host/x86_64-buildroot-linux-gnu/sysroot/usr/include
> >> > ../src/core/bpf/restrict_fs/restrict-fs.bpf.c -o
> >> > src/core/bpf/restrict_fs/restrict-fs.bpf.unstripped.o
> >>
> >> Hmm, why linking a relocatable ELF instead of just using a compiled
> >> object (with -c)?
> >
> > This bpftool gen object build stage AFAIU is needed to strip the object before
> > using it for skeleton generation, does that sound right?
>
> Thing is, `gcc -r' involves the linker.  The GNU linker (ld) supports
> linking BPF objects, but AFAIK the kernel BPF objects are all supposed
> to be compiled objects, not linked as relocatable objects.  (The LLVM
> BPF toolchain doesn't support linking BPF objects as far as I know.)

Maybe bpftool needs support for a different ELF file kind?

When I omit the '-r' flag I get this error from bpftool:
libbpf: unsupported kind of ELF file

>
> That's my understanding, but note I'm not very familiar with bpftool
> (I'm trying to find time now to fix that.)
>
> >>
> >> > I've also tried without the -r(relocatable object) flag but that gives
> >> > a different error:
> >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> >> > gen object src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> >> > src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
> >> > libbpf: unsupported kind of ELF file
> >> > src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o: no
> >> > error
> >> > Error: failed to link
> >> > 'src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o':
> >> > Unknown error -95 (-95)
> >> >
> >> > GCC without relocatable flag:
> >> > [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> >> > [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
> >> > [3] TYPEDEF '__u8' type_id=2
> >> > [4] CONST '(anon)' type_id=3
> >> > [5] VOLATILE '(anon)' type_id=4
> >> > [6] INT 'short int' size=2 bits_offset=0 nr_bits=16 encoding=SIGNED
> >> > [7] INT 'short unsigned int' size=2 bits_offset=0 nr_bits=16 encoding=(none)
> >> > [8] TYPEDEF '__u16' type_id=7
> >> > [9] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
> >> > [10] TYPEDEF '__s32' type_id=9
> >> > [11] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
> >> > [12] TYPEDEF '__u32' type_id=11
> >> > [13] INT 'long long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
> >> > [14] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64
> >> > encoding=(none)
> >> > [15] TYPEDEF '__u64' type_id=14
> >> > [16] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
> >> > [17] INT 'long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
> >> > [18] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> >> > [19] CONST '(anon)' type_id=18
> >> > [20] TYPEDEF '__be16' type_id=8
> >> > [21] TYPEDEF '__be32' type_id=12
> >> > [22] ENUM 'bpf_map_type' encoding=UNSIGNED size=4 vlen=31
> >> >     'BPF_MAP_TYPE_UNSPEC' val=0
> >> >     'BPF_MAP_TYPE_HASH' val=1
> >> >     'BPF_MAP_TYPE_ARRAY' val=2
> >> >     'BPF_MAP_TYPE_PROG_ARRAY' val=3
> >> >     'BPF_MAP_TYPE_PERF_EVENT_ARRAY' val=4
> >> >     'BPF_MAP_TYPE_PERCPU_HASH' val=5
> >> >     'BPF_MAP_TYPE_PERCPU_ARRAY' val=6
> >> >     'BPF_MAP_TYPE_STACK_TRACE' val=7
> >> >     'BPF_MAP_TYPE_CGROUP_ARRAY' val=8
> >> >     'BPF_MAP_TYPE_LRU_HASH' val=9
> >> >     'BPF_MAP_TYPE_LRU_PERCPU_HASH' val=10
> >> >     'BPF_MAP_TYPE_LPM_TRIE' val=11
> >> >     'BPF_MAP_TYPE_ARRAY_OF_MAPS' val=12
> >> >     'BPF_MAP_TYPE_HASH_OF_MAPS' val=13
> >> >     'BPF_MAP_TYPE_DEVMAP' val=14
> >> >     'BPF_MAP_TYPE_SOCKMAP' val=15
> >> >     'BPF_MAP_TYPE_CPUMAP' val=16
> >> >     'BPF_MAP_TYPE_XSKMAP' val=17
> >> >     'BPF_MAP_TYPE_SOCKHASH' val=18
> >> >     'BPF_MAP_TYPE_CGROUP_STORAGE' val=19
> >> >     'BPF_MAP_TYPE_REUSEPORT_SOCKARRAY' val=20
> >> >     'BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE' val=21
> >> >     'BPF_MAP_TYPE_QUEUE' val=22
> >> >     'BPF_MAP_TYPE_STACK' val=23
> >> >     'BPF_MAP_TYPE_SK_STORAGE' val=24
> >> >     'BPF_MAP_TYPE_DEVMAP_HASH' val=25
> >> >     'BPF_MAP_TYPE_STRUCT_OPS' val=26
> >> >     'BPF_MAP_TYPE_RINGBUF' val=27
> >> >     'BPF_MAP_TYPE_INODE_STORAGE' val=28
> >> >     'BPF_MAP_TYPE_TASK_STORAGE' val=29
> >> >     'BPF_MAP_TYPE_BLOOM_FILTER' val=30
> >> > [23] UNION '(anon)' size=8 vlen=1
> >> >     'flow_keys' type_id=29 bits_offset=0
> >> > [24] STRUCT 'bpf_flow_keys' size=56 vlen=13
> >> >     'nhoff' type_id=8 bits_offset=0
> >> >     'thoff' type_id=8 bits_offset=16
> >> >     'addr_proto' type_id=8 bits_offset=32
> >> >     'is_frag' type_id=3 bits_offset=48
> >> >     'is_first_frag' type_id=3 bits_offset=56
> >> >     'is_encap' type_id=3 bits_offset=64
> >> >     'ip_proto' type_id=3 bits_offset=72
> >> >     'n_proto' type_id=20 bits_offset=80
> >> >     'sport' type_id=20 bits_offset=96
> >> >     'dport' type_id=20 bits_offset=112
> >> >     '(anon)' type_id=25 bits_offset=128
> >> >     'flags' type_id=12 bits_offset=384
> >> >     'flow_label' type_id=21 bits_offset=416
> >> > [25] UNION '(anon)' size=32 vlen=2
> >> >     '(anon)' type_id=26 bits_offset=0
> >> >     '(anon)' type_id=27 bits_offset=0
> >> > [26] STRUCT '(anon)' size=8 vlen=2
> >> >     'ipv4_src' type_id=21 bits_offset=0
> >> >     'ipv4_dst' type_id=21 bits_offset=32
> >> > [27] STRUCT '(anon)' size=32 vlen=2
> >> >     'ipv6_src' type_id=28 bits_offset=0
> >> >     'ipv6_dst' type_id=28 bits_offset=128
> >> > [28] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=4
> >> > [29] PTR '(anon)' type_id=24
> >> > [30] UNION '(anon)' size=8 vlen=1
> >> >     'sk' type_id=32 bits_offset=0
> >> > [31] STRUCT 'bpf_sock' size=80 vlen=14
> >> >     'bound_dev_if' type_id=12 bits_offset=0
> >> >     'family' type_id=12 bits_offset=32
> >> >     'type' type_id=12 bits_offset=64
> >> >     'protocol' type_id=12 bits_offset=96
> >> >     'mark' type_id=12 bits_offset=128
> >> >     'priority' type_id=12 bits_offset=160
> >> >     'src_ip4' type_id=12 bits_offset=192
> >> >     'src_ip6' type_id=28 bits_offset=224
> >> >     'src_port' type_id=12 bits_offset=352
> >> >     'dst_port' type_id=20 bits_offset=384
> >> >     'dst_ip4' type_id=12 bits_offset=416
> >> >     'dst_ip6' type_id=28 bits_offset=448
> >> >     'state' type_id=12 bits_offset=576
> >> >     'rx_queue_mapping' type_id=10 bits_offset=608
> >> > [32] PTR '(anon)' type_id=31
> >> > [33] STRUCT '__sk_buff' size=192 vlen=33
> >> >     'len' type_id=12 bits_offset=0
> >> >     'pkt_type' type_id=12 bits_offset=32
> >> >     'mark' type_id=12 bits_offset=64
> >> >     'queue_mapping' type_id=12 bits_offset=96
> >> >     'protocol' type_id=12 bits_offset=128
> >> >     'vlan_present' type_id=12 bits_offset=160
> >> >     'vlan_tci' type_id=12 bits_offset=192
> >> >     'vlan_proto' type_id=12 bits_offset=224
> >> >     'priority' type_id=12 bits_offset=256
> >> >     'ingress_ifindex' type_id=12 bits_offset=288
> >> >     'ifindex' type_id=12 bits_offset=320
> >> >     'tc_index' type_id=12 bits_offset=352
> >> >     'cb' type_id=34 bits_offset=384
> >> >     'hash' type_id=12 bits_offset=544
> >> >     'tc_classid' type_id=12 bits_offset=576
> >> >     'data' type_id=12 bits_offset=608
> >> >     'data_end' type_id=12 bits_offset=640
> >> >     'napi_id' type_id=12 bits_offset=672
> >> >     'family' type_id=12 bits_offset=704
> >> >     'remote_ip4' type_id=12 bits_offset=736
> >> >     'local_ip4' type_id=12 bits_offset=768
> >> >     'remote_ip6' type_id=28 bits_offset=800
> >> >     'local_ip6' type_id=28 bits_offset=928
> >> >     'remote_port' type_id=12 bits_offset=1056
> >> >     'local_port' type_id=12 bits_offset=1088
> >> >     'data_meta' type_id=12 bits_offset=1120
> >> >     '(anon)' type_id=23 bits_offset=1152
> >> >     'tstamp' type_id=15 bits_offset=1216
> >> >     'wire_len' type_id=12 bits_offset=1280
> >> >     'gso_segs' type_id=12 bits_offset=1312
> >> >     '(anon)' type_id=30 bits_offset=1344
> >> >     'gso_size' type_id=12 bits_offset=1408
> >> >     'hwtstamp' type_id=15 bits_offset=1472
> >> > [34] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=5
> >> > [35] CONST '(anon)' type_id=33
> >> > [36] PTR '(anon)' type_id=0
> >> > [37] STRUCT '(anon)' size=24 vlen=3
> >> >     'type' type_id=39 bits_offset=0
> >> >     'key' type_id=40 bits_offset=64
> >> >     'value' type_id=41 bits_offset=128
> >> > [38] ARRAY '(anon)' type_id=9 index_type_id=16 nr_elems=1
> >> > [39] PTR '(anon)' type_id=38
> >> > [40] PTR '(anon)' type_id=12
> >> > [41] PTR '(anon)' type_id=3
> >> > [42] ARRAY '(anon)' type_id=19 index_type_id=16 nr_elems=18
> >> > [43] CONST '(anon)' type_id=42
> >> > [44] FUNC_PROTO '(anon)' ret_type_id=36 vlen=2
> >> >     '(anon)' type_id=36
> >> >     '(anon)' type_id=46
> >> > [45] CONST '(anon)' type_id=0
> >> > [46] PTR '(anon)' type_id=45
> >> > [47] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
> >> >     'sk' type_id=48
> >> > [48] PTR '(anon)' type_id=35
> >> > [49] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
> >> >     'sk' type_id=48
> >> > [50] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
> >> >     'sk' type_id=48
> >> > [51] VAR 'is_allow_list' type_id=5, linkage=global
> >> > [52] VAR '_license' type_id=43, linkage=static
> >> > [53] VAR 'sd_restrictif' type_id=37, linkage=global
> >> > [54] FUNC 'bpf_map_lookup_elem' type_id=44 linkage=static
> >> > [55] FUNC 'sd_restrictif_i' type_id=47 linkage=static
> >> > [56] FUNC 'sd_restrictif_e' type_id=49 linkage=static
> >> > [57] FUNC 'restrict_network_interfaces_impl' type_id=50 linkage=static
> >> > [58] DATASEC 'license' size=0 vlen=1
> >> >     type_id=52 offset=0 size=18 (VAR '_license')
> >> > [59] DATASEC '.maps' size=0 vlen=1
> >> >     type_id=53 offset=0 size=24 (VAR 'sd_restrictif')
> >> > [60] DATASEC '.data' size=0 vlen=1
> >> >     type_id=51 offset=0 size=1 (VAR 'is_allow_list')
> >> >
> >> >>
> >> >> https://github.com/systemd/systemd/blob/main/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.c#L42-L50
> >> >>
> >> >>
> >> >> > GCC:
> >> >> >
> >> >> > [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> >> >> > [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
> >> >> > [3] TYPEDEF '__u8' type_id=2
> >> >> > [4] CONST '(anon)' type_id=3
> >> >>
> >> >> [...]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-07-08 13:53           ` James Hilliard
@ 2022-07-08 14:39             ` Jose E. Marchesi
  0 siblings, 0 replies; 38+ messages in thread
From: Jose E. Marchesi @ 2022-07-08 14:39 UTC (permalink / raw)
  To: James Hilliard; +Cc: Andrii Nakryiko, bpf


> On Fri, Jul 8, 2022 at 7:46 AM Jose E. Marchesi
> <jose.marchesi@oracle.com> wrote:
>>
>>
>> > On Fri, Jul 8, 2022 at 5:56 AM Jose E. Marchesi
>> > <jose.marchesi@oracle.com> wrote:
>> >>
>> >>
>> >> > On Wed, Jul 6, 2022 at 11:20 AM Andrii Nakryiko
>> >> > <andrii.nakryiko@gmail.com> wrote:
>> >> >>
>> >> >> On Wed, Jul 6, 2022 at 10:13 AM James Hilliard
>> >> >> <james.hilliard1@gmail.com> wrote:
>> >> >> >
>> >> >> > Note I'm testing with the following patches:
>> >> >> > https://lore.kernel.org/bpf/20220706111839.1247911-1-james.hilliard1@gmail.com/
>> >> >> > https://lore.kernel.org/bpf/20220706140623.2917858-1-james.hilliard1@gmail.com/
>> >> >> >
>> >> >> > It would appear there's some compatibility issues with bpftool gen and
>> >> >> > GCC, not sure what side though is wrong here:
>> >> >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>> >> >> > gen object src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>> >> >> > src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
>> >> >> > libbpf: failed to find BTF info for global/extern symbol 'sd_restrictif_i'
>> >> >> > Error: failed to link
>> >> >> > 'src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o':
>> >> >> > Unknown error -2 (-2)
>> >> >> >
>> >> >> > Relevant difference seems to be this:
>> >> >> > GCC:
>> >> >> > [55] FUNC 'sd_restrictif_i' type_id=47 linkage=static
>> >> >> > Clang:
>> >> >> > [27] FUNC 'sd_restrictif_i' type_id=26 linkage=global
>> >> >> >
>> >> >>
>> >> >> GCC is wrong, clearly. This function is global ([0]) and libbpf
>> >> >> expects it to be marked as such in BTF.
>> >> >
>> >> > Does this invocation look correct?
>> >> > /home/buildroot/buildroot/output/per-package/systemd/host/bin/bpf-gcc
>> >> > -O2 -mkernel=5.2 -mcpu=v3 -mco-re -gbtf -r -std=gnu11 -D__x86_64__
>> >> > -mlittle-endian -I. -idirafter
>> >> > /home/buildroot/buildroot/output/per-package/systemd/host/x86_64-buildroot-linux-gnu/sysroot/usr/include
>> >> > ../src/core/bpf/restrict_fs/restrict-fs.bpf.c -o
>> >> > src/core/bpf/restrict_fs/restrict-fs.bpf.unstripped.o
>> >>
>> >> Hmm, why linking a relocatable ELF instead of just using a compiled
>> >> object (with -c)?
>> >
>> > This bpftool gen object build stage AFAIU is needed to strip the object before
>> > using it for skeleton generation, does that sound right?
>>
>> Thing is, `gcc -r' involves the linker.  The GNU linker (ld) supports
>> linking BPF objects, but AFAIK the kernel BPF objects are all supposed
>> to be compiled objects, not linked as relocatable objects.  (The LLVM
>> BPF toolchain doesn't support linking BPF objects as far as I know.)
>
> Maybe bpftool needs support for a different ELF file kind?
>
> When I omit the '-r' flag I get this error from bpftool:
> libbpf: unsupported kind of ELF file

Yes, because if you omit -r you are basically linking an ELF executable,
which libbpf doesn't support.

If you instead replace -r with -c, you will get a plain object file.

>>
>> That's my understanding, but note I'm not very familiar with bpftool
>> (I'm trying to find time now to fix that.)
>>
>> >>
>> >> > I've also tried without the -r(relocatable object) flag but that gives
>> >> > a different error:
>> >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>> >> > gen object src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>> >> > src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
>> >> > libbpf: unsupported kind of ELF file
>> >> > src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o: no
>> >> > error
>> >> > Error: failed to link
>> >> > 'src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o':
>> >> > Unknown error -95 (-95)
>> >> >
>> >> > GCC without relocatable flag:
>> >> > [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>> >> > [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
>> >> > [3] TYPEDEF '__u8' type_id=2
>> >> > [4] CONST '(anon)' type_id=3
>> >> > [5] VOLATILE '(anon)' type_id=4
>> >> > [6] INT 'short int' size=2 bits_offset=0 nr_bits=16 encoding=SIGNED
>> >> > [7] INT 'short unsigned int' size=2 bits_offset=0 nr_bits=16 encoding=(none)
>> >> > [8] TYPEDEF '__u16' type_id=7
>> >> > [9] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
>> >> > [10] TYPEDEF '__s32' type_id=9
>> >> > [11] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
>> >> > [12] TYPEDEF '__u32' type_id=11
>> >> > [13] INT 'long long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
>> >> > [14] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64
>> >> > encoding=(none)
>> >> > [15] TYPEDEF '__u64' type_id=14
>> >> > [16] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
>> >> > [17] INT 'long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
>> >> > [18] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>> >> > [19] CONST '(anon)' type_id=18
>> >> > [20] TYPEDEF '__be16' type_id=8
>> >> > [21] TYPEDEF '__be32' type_id=12
>> >> > [22] ENUM 'bpf_map_type' encoding=UNSIGNED size=4 vlen=31
>> >> >     'BPF_MAP_TYPE_UNSPEC' val=0
>> >> >     'BPF_MAP_TYPE_HASH' val=1
>> >> >     'BPF_MAP_TYPE_ARRAY' val=2
>> >> >     'BPF_MAP_TYPE_PROG_ARRAY' val=3
>> >> >     'BPF_MAP_TYPE_PERF_EVENT_ARRAY' val=4
>> >> >     'BPF_MAP_TYPE_PERCPU_HASH' val=5
>> >> >     'BPF_MAP_TYPE_PERCPU_ARRAY' val=6
>> >> >     'BPF_MAP_TYPE_STACK_TRACE' val=7
>> >> >     'BPF_MAP_TYPE_CGROUP_ARRAY' val=8
>> >> >     'BPF_MAP_TYPE_LRU_HASH' val=9
>> >> >     'BPF_MAP_TYPE_LRU_PERCPU_HASH' val=10
>> >> >     'BPF_MAP_TYPE_LPM_TRIE' val=11
>> >> >     'BPF_MAP_TYPE_ARRAY_OF_MAPS' val=12
>> >> >     'BPF_MAP_TYPE_HASH_OF_MAPS' val=13
>> >> >     'BPF_MAP_TYPE_DEVMAP' val=14
>> >> >     'BPF_MAP_TYPE_SOCKMAP' val=15
>> >> >     'BPF_MAP_TYPE_CPUMAP' val=16
>> >> >     'BPF_MAP_TYPE_XSKMAP' val=17
>> >> >     'BPF_MAP_TYPE_SOCKHASH' val=18
>> >> >     'BPF_MAP_TYPE_CGROUP_STORAGE' val=19
>> >> >     'BPF_MAP_TYPE_REUSEPORT_SOCKARRAY' val=20
>> >> >     'BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE' val=21
>> >> >     'BPF_MAP_TYPE_QUEUE' val=22
>> >> >     'BPF_MAP_TYPE_STACK' val=23
>> >> >     'BPF_MAP_TYPE_SK_STORAGE' val=24
>> >> >     'BPF_MAP_TYPE_DEVMAP_HASH' val=25
>> >> >     'BPF_MAP_TYPE_STRUCT_OPS' val=26
>> >> >     'BPF_MAP_TYPE_RINGBUF' val=27
>> >> >     'BPF_MAP_TYPE_INODE_STORAGE' val=28
>> >> >     'BPF_MAP_TYPE_TASK_STORAGE' val=29
>> >> >     'BPF_MAP_TYPE_BLOOM_FILTER' val=30
>> >> > [23] UNION '(anon)' size=8 vlen=1
>> >> >     'flow_keys' type_id=29 bits_offset=0
>> >> > [24] STRUCT 'bpf_flow_keys' size=56 vlen=13
>> >> >     'nhoff' type_id=8 bits_offset=0
>> >> >     'thoff' type_id=8 bits_offset=16
>> >> >     'addr_proto' type_id=8 bits_offset=32
>> >> >     'is_frag' type_id=3 bits_offset=48
>> >> >     'is_first_frag' type_id=3 bits_offset=56
>> >> >     'is_encap' type_id=3 bits_offset=64
>> >> >     'ip_proto' type_id=3 bits_offset=72
>> >> >     'n_proto' type_id=20 bits_offset=80
>> >> >     'sport' type_id=20 bits_offset=96
>> >> >     'dport' type_id=20 bits_offset=112
>> >> >     '(anon)' type_id=25 bits_offset=128
>> >> >     'flags' type_id=12 bits_offset=384
>> >> >     'flow_label' type_id=21 bits_offset=416
>> >> > [25] UNION '(anon)' size=32 vlen=2
>> >> >     '(anon)' type_id=26 bits_offset=0
>> >> >     '(anon)' type_id=27 bits_offset=0
>> >> > [26] STRUCT '(anon)' size=8 vlen=2
>> >> >     'ipv4_src' type_id=21 bits_offset=0
>> >> >     'ipv4_dst' type_id=21 bits_offset=32
>> >> > [27] STRUCT '(anon)' size=32 vlen=2
>> >> >     'ipv6_src' type_id=28 bits_offset=0
>> >> >     'ipv6_dst' type_id=28 bits_offset=128
>> >> > [28] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=4
>> >> > [29] PTR '(anon)' type_id=24
>> >> > [30] UNION '(anon)' size=8 vlen=1
>> >> >     'sk' type_id=32 bits_offset=0
>> >> > [31] STRUCT 'bpf_sock' size=80 vlen=14
>> >> >     'bound_dev_if' type_id=12 bits_offset=0
>> >> >     'family' type_id=12 bits_offset=32
>> >> >     'type' type_id=12 bits_offset=64
>> >> >     'protocol' type_id=12 bits_offset=96
>> >> >     'mark' type_id=12 bits_offset=128
>> >> >     'priority' type_id=12 bits_offset=160
>> >> >     'src_ip4' type_id=12 bits_offset=192
>> >> >     'src_ip6' type_id=28 bits_offset=224
>> >> >     'src_port' type_id=12 bits_offset=352
>> >> >     'dst_port' type_id=20 bits_offset=384
>> >> >     'dst_ip4' type_id=12 bits_offset=416
>> >> >     'dst_ip6' type_id=28 bits_offset=448
>> >> >     'state' type_id=12 bits_offset=576
>> >> >     'rx_queue_mapping' type_id=10 bits_offset=608
>> >> > [32] PTR '(anon)' type_id=31
>> >> > [33] STRUCT '__sk_buff' size=192 vlen=33
>> >> >     'len' type_id=12 bits_offset=0
>> >> >     'pkt_type' type_id=12 bits_offset=32
>> >> >     'mark' type_id=12 bits_offset=64
>> >> >     'queue_mapping' type_id=12 bits_offset=96
>> >> >     'protocol' type_id=12 bits_offset=128
>> >> >     'vlan_present' type_id=12 bits_offset=160
>> >> >     'vlan_tci' type_id=12 bits_offset=192
>> >> >     'vlan_proto' type_id=12 bits_offset=224
>> >> >     'priority' type_id=12 bits_offset=256
>> >> >     'ingress_ifindex' type_id=12 bits_offset=288
>> >> >     'ifindex' type_id=12 bits_offset=320
>> >> >     'tc_index' type_id=12 bits_offset=352
>> >> >     'cb' type_id=34 bits_offset=384
>> >> >     'hash' type_id=12 bits_offset=544
>> >> >     'tc_classid' type_id=12 bits_offset=576
>> >> >     'data' type_id=12 bits_offset=608
>> >> >     'data_end' type_id=12 bits_offset=640
>> >> >     'napi_id' type_id=12 bits_offset=672
>> >> >     'family' type_id=12 bits_offset=704
>> >> >     'remote_ip4' type_id=12 bits_offset=736
>> >> >     'local_ip4' type_id=12 bits_offset=768
>> >> >     'remote_ip6' type_id=28 bits_offset=800
>> >> >     'local_ip6' type_id=28 bits_offset=928
>> >> >     'remote_port' type_id=12 bits_offset=1056
>> >> >     'local_port' type_id=12 bits_offset=1088
>> >> >     'data_meta' type_id=12 bits_offset=1120
>> >> >     '(anon)' type_id=23 bits_offset=1152
>> >> >     'tstamp' type_id=15 bits_offset=1216
>> >> >     'wire_len' type_id=12 bits_offset=1280
>> >> >     'gso_segs' type_id=12 bits_offset=1312
>> >> >     '(anon)' type_id=30 bits_offset=1344
>> >> >     'gso_size' type_id=12 bits_offset=1408
>> >> >     'hwtstamp' type_id=15 bits_offset=1472
>> >> > [34] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=5
>> >> > [35] CONST '(anon)' type_id=33
>> >> > [36] PTR '(anon)' type_id=0
>> >> > [37] STRUCT '(anon)' size=24 vlen=3
>> >> >     'type' type_id=39 bits_offset=0
>> >> >     'key' type_id=40 bits_offset=64
>> >> >     'value' type_id=41 bits_offset=128
>> >> > [38] ARRAY '(anon)' type_id=9 index_type_id=16 nr_elems=1
>> >> > [39] PTR '(anon)' type_id=38
>> >> > [40] PTR '(anon)' type_id=12
>> >> > [41] PTR '(anon)' type_id=3
>> >> > [42] ARRAY '(anon)' type_id=19 index_type_id=16 nr_elems=18
>> >> > [43] CONST '(anon)' type_id=42
>> >> > [44] FUNC_PROTO '(anon)' ret_type_id=36 vlen=2
>> >> >     '(anon)' type_id=36
>> >> >     '(anon)' type_id=46
>> >> > [45] CONST '(anon)' type_id=0
>> >> > [46] PTR '(anon)' type_id=45
>> >> > [47] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>> >> >     'sk' type_id=48
>> >> > [48] PTR '(anon)' type_id=35
>> >> > [49] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>> >> >     'sk' type_id=48
>> >> > [50] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>> >> >     'sk' type_id=48
>> >> > [51] VAR 'is_allow_list' type_id=5, linkage=global
>> >> > [52] VAR '_license' type_id=43, linkage=static
>> >> > [53] VAR 'sd_restrictif' type_id=37, linkage=global
>> >> > [54] FUNC 'bpf_map_lookup_elem' type_id=44 linkage=static
>> >> > [55] FUNC 'sd_restrictif_i' type_id=47 linkage=static
>> >> > [56] FUNC 'sd_restrictif_e' type_id=49 linkage=static
>> >> > [57] FUNC 'restrict_network_interfaces_impl' type_id=50 linkage=static
>> >> > [58] DATASEC 'license' size=0 vlen=1
>> >> >     type_id=52 offset=0 size=18 (VAR '_license')
>> >> > [59] DATASEC '.maps' size=0 vlen=1
>> >> >     type_id=53 offset=0 size=24 (VAR 'sd_restrictif')
>> >> > [60] DATASEC '.data' size=0 vlen=1
>> >> >     type_id=51 offset=0 size=1 (VAR 'is_allow_list')
>> >> >
>> >> >>
>> >> >> https://github.com/systemd/systemd/blob/main/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.c#L42-L50
>> >> >>
>> >> >>
>> >> >> > GCC:
>> >> >> >
>> >> >> > [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>> >> >> > [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
>> >> >> > [3] TYPEDEF '__u8' type_id=2
>> >> >> > [4] CONST '(anon)' type_id=3
>> >> >>
>> >> >> [...]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-07-06 17:20 ` Andrii Nakryiko
  2022-07-06 17:49   ` James Hilliard
@ 2022-07-08 14:51   ` Jose E. Marchesi
  2022-07-08 18:33     ` Jose E. Marchesi
  2022-07-12  0:34   ` Indu Bhagat
  2 siblings, 1 reply; 38+ messages in thread
From: Jose E. Marchesi @ 2022-07-08 14:51 UTC (permalink / raw)
  To: Andrii Nakryiko; +Cc: James Hilliard, bpf, david.faust


> On Wed, Jul 6, 2022 at 10:13 AM James Hilliard
> <james.hilliard1@gmail.com> wrote:
>>
>> Note I'm testing with the following patches:
>> https://lore.kernel.org/bpf/20220706111839.1247911-1-james.hilliard1@gmail.com/
>> https://lore.kernel.org/bpf/20220706140623.2917858-1-james.hilliard1@gmail.com/
>>
>> It would appear there's some compatibility issues with bpftool gen and
>> GCC, not sure what side though is wrong here:
>> /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>> gen object src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>> src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
>> libbpf: failed to find BTF info for global/extern symbol 'sd_restrictif_i'
>> Error: failed to link
>> 'src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o':
>> Unknown error -2 (-2)
>>
>> Relevant difference seems to be this:
>> GCC:
>> [55] FUNC 'sd_restrictif_i' type_id=47 linkage=static
>> Clang:
>> [27] FUNC 'sd_restrictif_i' type_id=26 linkage=global

For functions GCC generates a BTF_KIND_FUNC entry, which has no linkage
information, or so we thought: I just looked at bpftool/btf.c and I
found the linkage info for function types is expected to be encoded in
the vlen field of BTF_KIND_FUNC entries (why not adding a btf_func
instead???) which is surprising to say the least.

We are changing GCC to encode the linkage info in vlen for these types.
Thanks for reporting this.

> GCC is wrong, clearly. This function is global ([0]) and libbpf
> expects it to be marked as such in BTF.
>
> https://github.com/systemd/systemd/blob/main/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.c#L42-L50
>
>
>> GCC:
>>
>> [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>> [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
>> [3] TYPEDEF '__u8' type_id=2
>> [4] CONST '(anon)' type_id=3
>
> [...]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-07-08 14:51   ` Jose E. Marchesi
@ 2022-07-08 18:33     ` Jose E. Marchesi
  2022-07-08 20:59       ` James Hilliard
  2022-08-02 15:57       ` Jose E. Marchesi
  0 siblings, 2 replies; 38+ messages in thread
From: Jose E. Marchesi @ 2022-07-08 18:33 UTC (permalink / raw)
  To: Andrii Nakryiko; +Cc: James Hilliard, bpf, david.faust


>> On Wed, Jul 6, 2022 at 10:13 AM James Hilliard
>> <james.hilliard1@gmail.com> wrote:
>>>
>>> Note I'm testing with the following patches:
>>> https://lore.kernel.org/bpf/20220706111839.1247911-1-james.hilliard1@gmail.com/
>>> https://lore.kernel.org/bpf/20220706140623.2917858-1-james.hilliard1@gmail.com/
>>>
>>> It would appear there's some compatibility issues with bpftool gen and
>>> GCC, not sure what side though is wrong here:
>>> /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>>> gen object src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>>> src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
>>> libbpf: failed to find BTF info for global/extern symbol 'sd_restrictif_i'
>>> Error: failed to link
>>> 'src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o':
>>> Unknown error -2 (-2)
>>>
>>> Relevant difference seems to be this:
>>> GCC:
>>> [55] FUNC 'sd_restrictif_i' type_id=47 linkage=static
>>> Clang:
>>> [27] FUNC 'sd_restrictif_i' type_id=26 linkage=global
>
> For functions GCC generates a BTF_KIND_FUNC entry, which has no linkage
> information, or so we thought: I just looked at bpftool/btf.c and I
> found the linkage info for function types is expected to be encoded in
> the vlen field of BTF_KIND_FUNC entries (why not adding a btf_func
> instead???) which is surprising to say the least.
>
> We are changing GCC to encode the linkage info in vlen for these types.
> Thanks for reporting this.

Patch sent to GCC upstream:
https://gcc.gnu.org/pipermail/gcc-patches/2022-July/598090.html

>> GCC is wrong, clearly. This function is global ([0]) and libbpf
>> expects it to be marked as such in BTF.
>>
>> https://github.com/systemd/systemd/blob/main/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.c#L42-L50
>>
>>
>>> GCC:
>>>
>>> [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>>> [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
>>> [3] TYPEDEF '__u8' type_id=2
>>> [4] CONST '(anon)' type_id=3
>>
>> [...]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-07-08 18:33     ` Jose E. Marchesi
@ 2022-07-08 20:59       ` James Hilliard
  2022-07-09 17:24         ` Jose E. Marchesi
  2022-08-02 15:57       ` Jose E. Marchesi
  1 sibling, 1 reply; 38+ messages in thread
From: James Hilliard @ 2022-07-08 20:59 UTC (permalink / raw)
  To: Jose E. Marchesi; +Cc: Andrii Nakryiko, bpf, david.faust

On Fri, Jul 8, 2022 at 12:33 PM Jose E. Marchesi
<jose.marchesi@oracle.com> wrote:
>
>
> >> On Wed, Jul 6, 2022 at 10:13 AM James Hilliard
> >> <james.hilliard1@gmail.com> wrote:
> >>>
> >>> Note I'm testing with the following patches:
> >>> https://lore.kernel.org/bpf/20220706111839.1247911-1-james.hilliard1@gmail.com/
> >>> https://lore.kernel.org/bpf/20220706140623.2917858-1-james.hilliard1@gmail.com/
> >>>
> >>> It would appear there's some compatibility issues with bpftool gen and
> >>> GCC, not sure what side though is wrong here:
> >>> /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> >>> gen object src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> >>> src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
> >>> libbpf: failed to find BTF info for global/extern symbol 'sd_restrictif_i'
> >>> Error: failed to link
> >>> 'src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o':
> >>> Unknown error -2 (-2)
> >>>
> >>> Relevant difference seems to be this:
> >>> GCC:
> >>> [55] FUNC 'sd_restrictif_i' type_id=47 linkage=static
> >>> Clang:
> >>> [27] FUNC 'sd_restrictif_i' type_id=26 linkage=global
> >
> > For functions GCC generates a BTF_KIND_FUNC entry, which has no linkage
> > information, or so we thought: I just looked at bpftool/btf.c and I
> > found the linkage info for function types is expected to be encoded in
> > the vlen field of BTF_KIND_FUNC entries (why not adding a btf_func
> > instead???) which is surprising to say the least.
> >
> > We are changing GCC to encode the linkage info in vlen for these types.
> > Thanks for reporting this.
>
> Patch sent to GCC upstream:
> https://gcc.gnu.org/pipermail/gcc-patches/2022-July/598090.html

I applied that patch on top of GCC 12.1.0 and it appears to fix the
bpftool gen object bug.

I am however now hitting a different error during skeleton generation:
/home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
gen skeleton src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
libbpf: elf: skipping unrecognized data section(9) .comment
libbpf: failed to alloc map 'restrict.bss' content buffer: -22
Error: failed to open BPF object file: Invalid argument

Stripped file passed to gen skeleton:
/home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
btf dump file output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
format raw
[1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
[2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
[3] TYPEDEF '__u8' type_id=2
[4] CONST '(anon)' type_id=3
[5] VOLATILE '(anon)' type_id=4
[6] INT 'short int' size=2 bits_offset=0 nr_bits=16 encoding=SIGNED
[7] INT 'short unsigned int' size=2 bits_offset=0 nr_bits=16 encoding=(none)
[8] TYPEDEF '__u16' type_id=7
[9] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
[10] TYPEDEF '__s32' type_id=9
[11] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
[12] TYPEDEF '__u32' type_id=11
[13] INT 'long long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
[14] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64
encoding=(none)
[15] TYPEDEF '__u64' type_id=14
[16] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
[17] INT 'long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
[18] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
[19] CONST '(anon)' type_id=18
[20] TYPEDEF '__be16' type_id=8
[21] TYPEDEF '__be32' type_id=12
[22] ENUM 'bpf_map_type' encoding=UNSIGNED size=4 vlen=31
    'BPF_MAP_TYPE_UNSPEC' val=0
    'BPF_MAP_TYPE_HASH' val=1
    'BPF_MAP_TYPE_ARRAY' val=2
    'BPF_MAP_TYPE_PROG_ARRAY' val=3
    'BPF_MAP_TYPE_PERF_EVENT_ARRAY' val=4
    'BPF_MAP_TYPE_PERCPU_HASH' val=5
    'BPF_MAP_TYPE_PERCPU_ARRAY' val=6
    'BPF_MAP_TYPE_STACK_TRACE' val=7
    'BPF_MAP_TYPE_CGROUP_ARRAY' val=8
    'BPF_MAP_TYPE_LRU_HASH' val=9
    'BPF_MAP_TYPE_LRU_PERCPU_HASH' val=10
    'BPF_MAP_TYPE_LPM_TRIE' val=11
    'BPF_MAP_TYPE_ARRAY_OF_MAPS' val=12
    'BPF_MAP_TYPE_HASH_OF_MAPS' val=13
    'BPF_MAP_TYPE_DEVMAP' val=14
    'BPF_MAP_TYPE_SOCKMAP' val=15
    'BPF_MAP_TYPE_CPUMAP' val=16
    'BPF_MAP_TYPE_XSKMAP' val=17
    'BPF_MAP_TYPE_SOCKHASH' val=18
    'BPF_MAP_TYPE_CGROUP_STORAGE' val=19
    'BPF_MAP_TYPE_REUSEPORT_SOCKARRAY' val=20
    'BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE' val=21
    'BPF_MAP_TYPE_QUEUE' val=22
    'BPF_MAP_TYPE_STACK' val=23
    'BPF_MAP_TYPE_SK_STORAGE' val=24
    'BPF_MAP_TYPE_DEVMAP_HASH' val=25
    'BPF_MAP_TYPE_STRUCT_OPS' val=26
    'BPF_MAP_TYPE_RINGBUF' val=27
    'BPF_MAP_TYPE_INODE_STORAGE' val=28
    'BPF_MAP_TYPE_TASK_STORAGE' val=29
    'BPF_MAP_TYPE_BLOOM_FILTER' val=30
[23] UNION '(anon)' size=8 vlen=1
    'flow_keys' type_id=29 bits_offset=0
[24] STRUCT 'bpf_flow_keys' size=56 vlen=13
    'nhoff' type_id=8 bits_offset=0
    'thoff' type_id=8 bits_offset=16
    'addr_proto' type_id=8 bits_offset=32
    'is_frag' type_id=3 bits_offset=48
    'is_first_frag' type_id=3 bits_offset=56
    'is_encap' type_id=3 bits_offset=64
    'ip_proto' type_id=3 bits_offset=72
    'n_proto' type_id=20 bits_offset=80
    'sport' type_id=20 bits_offset=96
    'dport' type_id=20 bits_offset=112
    '(anon)' type_id=25 bits_offset=128
    'flags' type_id=12 bits_offset=384
    'flow_label' type_id=21 bits_offset=416
[25] UNION '(anon)' size=32 vlen=2
    '(anon)' type_id=26 bits_offset=0
    '(anon)' type_id=27 bits_offset=0
[26] STRUCT '(anon)' size=8 vlen=2
    'ipv4_src' type_id=21 bits_offset=0
    'ipv4_dst' type_id=21 bits_offset=32
[27] STRUCT '(anon)' size=32 vlen=2
    'ipv6_src' type_id=28 bits_offset=0
    'ipv6_dst' type_id=28 bits_offset=128
[28] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=4
[29] PTR '(anon)' type_id=24
[30] UNION '(anon)' size=8 vlen=1
    'sk' type_id=32 bits_offset=0
[31] STRUCT 'bpf_sock' size=80 vlen=14
    'bound_dev_if' type_id=12 bits_offset=0
    'family' type_id=12 bits_offset=32
    'type' type_id=12 bits_offset=64
    'protocol' type_id=12 bits_offset=96
    'mark' type_id=12 bits_offset=128
    'priority' type_id=12 bits_offset=160
    'src_ip4' type_id=12 bits_offset=192
    'src_ip6' type_id=28 bits_offset=224
    'src_port' type_id=12 bits_offset=352
    'dst_port' type_id=20 bits_offset=384
    'dst_ip4' type_id=12 bits_offset=416
    'dst_ip6' type_id=28 bits_offset=448
    'state' type_id=12 bits_offset=576
    'rx_queue_mapping' type_id=10 bits_offset=608
[32] PTR '(anon)' type_id=31
[33] STRUCT '__sk_buff' size=192 vlen=33
    'len' type_id=12 bits_offset=0
    'pkt_type' type_id=12 bits_offset=32
    'mark' type_id=12 bits_offset=64
    'queue_mapping' type_id=12 bits_offset=96
    'protocol' type_id=12 bits_offset=128
    'vlan_present' type_id=12 bits_offset=160
    'vlan_tci' type_id=12 bits_offset=192
    'vlan_proto' type_id=12 bits_offset=224
    'priority' type_id=12 bits_offset=256
    'ingress_ifindex' type_id=12 bits_offset=288
    'ifindex' type_id=12 bits_offset=320
    'tc_index' type_id=12 bits_offset=352
    'cb' type_id=34 bits_offset=384
    'hash' type_id=12 bits_offset=544
    'tc_classid' type_id=12 bits_offset=576
    'data' type_id=12 bits_offset=608
    'data_end' type_id=12 bits_offset=640
    'napi_id' type_id=12 bits_offset=672
    'family' type_id=12 bits_offset=704
    'remote_ip4' type_id=12 bits_offset=736
    'local_ip4' type_id=12 bits_offset=768
    'remote_ip6' type_id=28 bits_offset=800
    'local_ip6' type_id=28 bits_offset=928
    'remote_port' type_id=12 bits_offset=1056
    'local_port' type_id=12 bits_offset=1088
    'data_meta' type_id=12 bits_offset=1120
    '(anon)' type_id=23 bits_offset=1152
    'tstamp' type_id=15 bits_offset=1216
    'wire_len' type_id=12 bits_offset=1280
    'gso_segs' type_id=12 bits_offset=1312
    '(anon)' type_id=30 bits_offset=1344
    'gso_size' type_id=12 bits_offset=1408
    'hwtstamp' type_id=15 bits_offset=1472
[34] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=5
[35] CONST '(anon)' type_id=33
[36] PTR '(anon)' type_id=0
[37] STRUCT '(anon)' size=24 vlen=3
    'type' type_id=39 bits_offset=0
    'key' type_id=40 bits_offset=64
    'value' type_id=41 bits_offset=128
[38] ARRAY '(anon)' type_id=9 index_type_id=16 nr_elems=1
[39] PTR '(anon)' type_id=38
[40] PTR '(anon)' type_id=12
[41] PTR '(anon)' type_id=3
[42] ARRAY '(anon)' type_id=19 index_type_id=16 nr_elems=18
[43] CONST '(anon)' type_id=42
[44] FUNC_PROTO '(anon)' ret_type_id=36 vlen=2
    '(anon)' type_id=36
    '(anon)' type_id=46
[45] CONST '(anon)' type_id=0
[46] PTR '(anon)' type_id=45
[47] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
    'sk' type_id=48
[48] PTR '(anon)' type_id=35
[49] VAR '_license' type_id=43, linkage=static
[50] VAR 'is_allow_list' type_id=5, linkage=global
[51] VAR 'sd_restrictif' type_id=37, linkage=global
[52] FUNC 'sd_restrictif_i' type_id=47 linkage=global
[53] FUNC 'sd_restrictif_e' type_id=47 linkage=global
[54] FUNC 'restrict_network_interfaces_impl' type_id=47 linkage=static
[55] DATASEC '.data' size=1 vlen=1
    type_id=50 offset=0 size=1 (VAR 'is_allow_list')
[56] DATASEC 'license' size=18 vlen=1
    type_id=49 offset=0 size=18 (VAR '_license')
[57] DATASEC '.maps' size=24 vlen=1
    type_id=51 offset=0 size=24 (VAR 'sd_restrictif')

File before being stripped using bpftool gen object:
/home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
btf dump file output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
format raw
[1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
[2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
[3] TYPEDEF '__u8' type_id=2
[4] CONST '(anon)' type_id=3
[5] VOLATILE '(anon)' type_id=4
[6] INT 'short int' size=2 bits_offset=0 nr_bits=16 encoding=SIGNED
[7] INT 'short unsigned int' size=2 bits_offset=0 nr_bits=16 encoding=(none)
[8] TYPEDEF '__u16' type_id=7
[9] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
[10] TYPEDEF '__s32' type_id=9
[11] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
[12] TYPEDEF '__u32' type_id=11
[13] INT 'long long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
[14] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64
encoding=(none)
[15] TYPEDEF '__u64' type_id=14
[16] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
[17] INT 'long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
[18] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
[19] CONST '(anon)' type_id=18
[20] TYPEDEF '__be16' type_id=8
[21] TYPEDEF '__be32' type_id=12
[22] ENUM 'bpf_map_type' encoding=UNSIGNED size=4 vlen=31
    'BPF_MAP_TYPE_UNSPEC' val=0
    'BPF_MAP_TYPE_HASH' val=1
    'BPF_MAP_TYPE_ARRAY' val=2
    'BPF_MAP_TYPE_PROG_ARRAY' val=3
    'BPF_MAP_TYPE_PERF_EVENT_ARRAY' val=4
    'BPF_MAP_TYPE_PERCPU_HASH' val=5
    'BPF_MAP_TYPE_PERCPU_ARRAY' val=6
    'BPF_MAP_TYPE_STACK_TRACE' val=7
    'BPF_MAP_TYPE_CGROUP_ARRAY' val=8
    'BPF_MAP_TYPE_LRU_HASH' val=9
    'BPF_MAP_TYPE_LRU_PERCPU_HASH' val=10
    'BPF_MAP_TYPE_LPM_TRIE' val=11
    'BPF_MAP_TYPE_ARRAY_OF_MAPS' val=12
    'BPF_MAP_TYPE_HASH_OF_MAPS' val=13
    'BPF_MAP_TYPE_DEVMAP' val=14
    'BPF_MAP_TYPE_SOCKMAP' val=15
    'BPF_MAP_TYPE_CPUMAP' val=16
    'BPF_MAP_TYPE_XSKMAP' val=17
    'BPF_MAP_TYPE_SOCKHASH' val=18
    'BPF_MAP_TYPE_CGROUP_STORAGE' val=19
    'BPF_MAP_TYPE_REUSEPORT_SOCKARRAY' val=20
    'BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE' val=21
    'BPF_MAP_TYPE_QUEUE' val=22
    'BPF_MAP_TYPE_STACK' val=23
    'BPF_MAP_TYPE_SK_STORAGE' val=24
    'BPF_MAP_TYPE_DEVMAP_HASH' val=25
    'BPF_MAP_TYPE_STRUCT_OPS' val=26
    'BPF_MAP_TYPE_RINGBUF' val=27
    'BPF_MAP_TYPE_INODE_STORAGE' val=28
    'BPF_MAP_TYPE_TASK_STORAGE' val=29
    'BPF_MAP_TYPE_BLOOM_FILTER' val=30
[23] UNION '(anon)' size=8 vlen=1
    'flow_keys' type_id=29 bits_offset=0
[24] STRUCT 'bpf_flow_keys' size=56 vlen=13
    'nhoff' type_id=8 bits_offset=0
    'thoff' type_id=8 bits_offset=16
    'addr_proto' type_id=8 bits_offset=32
    'is_frag' type_id=3 bits_offset=48
    'is_first_frag' type_id=3 bits_offset=56
    'is_encap' type_id=3 bits_offset=64
    'ip_proto' type_id=3 bits_offset=72
    'n_proto' type_id=20 bits_offset=80
    'sport' type_id=20 bits_offset=96
    'dport' type_id=20 bits_offset=112
    '(anon)' type_id=25 bits_offset=128
    'flags' type_id=12 bits_offset=384
    'flow_label' type_id=21 bits_offset=416
[25] UNION '(anon)' size=32 vlen=2
    '(anon)' type_id=26 bits_offset=0
    '(anon)' type_id=27 bits_offset=0
[26] STRUCT '(anon)' size=8 vlen=2
    'ipv4_src' type_id=21 bits_offset=0
    'ipv4_dst' type_id=21 bits_offset=32
[27] STRUCT '(anon)' size=32 vlen=2
    'ipv6_src' type_id=28 bits_offset=0
    'ipv6_dst' type_id=28 bits_offset=128
[28] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=4
[29] PTR '(anon)' type_id=24
[30] UNION '(anon)' size=8 vlen=1
    'sk' type_id=32 bits_offset=0
[31] STRUCT 'bpf_sock' size=80 vlen=14
    'bound_dev_if' type_id=12 bits_offset=0
    'family' type_id=12 bits_offset=32
    'type' type_id=12 bits_offset=64
    'protocol' type_id=12 bits_offset=96
    'mark' type_id=12 bits_offset=128
    'priority' type_id=12 bits_offset=160
    'src_ip4' type_id=12 bits_offset=192
    'src_ip6' type_id=28 bits_offset=224
    'src_port' type_id=12 bits_offset=352
    'dst_port' type_id=20 bits_offset=384
    'dst_ip4' type_id=12 bits_offset=416
    'dst_ip6' type_id=28 bits_offset=448
    'state' type_id=12 bits_offset=576
    'rx_queue_mapping' type_id=10 bits_offset=608
[32] PTR '(anon)' type_id=31
[33] STRUCT '__sk_buff' size=192 vlen=33
    'len' type_id=12 bits_offset=0
    'pkt_type' type_id=12 bits_offset=32
    'mark' type_id=12 bits_offset=64
    'queue_mapping' type_id=12 bits_offset=96
    'protocol' type_id=12 bits_offset=128
    'vlan_present' type_id=12 bits_offset=160
    'vlan_tci' type_id=12 bits_offset=192
    'vlan_proto' type_id=12 bits_offset=224
    'priority' type_id=12 bits_offset=256
    'ingress_ifindex' type_id=12 bits_offset=288
    'ifindex' type_id=12 bits_offset=320
    'tc_index' type_id=12 bits_offset=352
    'cb' type_id=34 bits_offset=384
    'hash' type_id=12 bits_offset=544
    'tc_classid' type_id=12 bits_offset=576
    'data' type_id=12 bits_offset=608
    'data_end' type_id=12 bits_offset=640
    'napi_id' type_id=12 bits_offset=672
    'family' type_id=12 bits_offset=704
    'remote_ip4' type_id=12 bits_offset=736
    'local_ip4' type_id=12 bits_offset=768
    'remote_ip6' type_id=28 bits_offset=800
    'local_ip6' type_id=28 bits_offset=928
    'remote_port' type_id=12 bits_offset=1056
    'local_port' type_id=12 bits_offset=1088
    'data_meta' type_id=12 bits_offset=1120
    '(anon)' type_id=23 bits_offset=1152
    'tstamp' type_id=15 bits_offset=1216
    'wire_len' type_id=12 bits_offset=1280
    'gso_segs' type_id=12 bits_offset=1312
    '(anon)' type_id=30 bits_offset=1344
    'gso_size' type_id=12 bits_offset=1408
    'hwtstamp' type_id=15 bits_offset=1472
[34] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=5
[35] CONST '(anon)' type_id=33
[36] PTR '(anon)' type_id=0
[37] STRUCT '(anon)' size=24 vlen=3
    'type' type_id=39 bits_offset=0
    'key' type_id=40 bits_offset=64
    'value' type_id=41 bits_offset=128
[38] ARRAY '(anon)' type_id=9 index_type_id=16 nr_elems=1
[39] PTR '(anon)' type_id=38
[40] PTR '(anon)' type_id=12
[41] PTR '(anon)' type_id=3
[42] ARRAY '(anon)' type_id=19 index_type_id=16 nr_elems=18
[43] CONST '(anon)' type_id=42
[44] FUNC_PROTO '(anon)' ret_type_id=36 vlen=2
    '(anon)' type_id=36
    '(anon)' type_id=46
[45] CONST '(anon)' type_id=0
[46] PTR '(anon)' type_id=45
[47] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
    'sk' type_id=48
[48] PTR '(anon)' type_id=35
[49] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
    'sk' type_id=48
[50] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
    'sk' type_id=48
[51] VAR '_license' type_id=43, linkage=static
[52] VAR 'is_allow_list' type_id=5, linkage=global
[53] VAR 'sd_restrictif' type_id=37, linkage=global
[54] FUNC 'bpf_map_lookup_elem' type_id=44 linkage=global
[55] FUNC 'sd_restrictif_i' type_id=47 linkage=global
[56] FUNC 'sd_restrictif_e' type_id=49 linkage=global
[57] FUNC 'restrict_network_interfaces_impl' type_id=50 linkage=static
[58] DATASEC 'license' size=0 vlen=1
    type_id=51 offset=0 size=18 (VAR '_license')
[59] DATASEC '.maps' size=0 vlen=1
    type_id=53 offset=0 size=24 (VAR 'sd_restrictif')
[60] DATASEC '.data' size=0 vlen=1
    type_id=52 offset=0 size=1 (VAR 'is_allow_list')

>
> >> GCC is wrong, clearly. This function is global ([0]) and libbpf
> >> expects it to be marked as such in BTF.
> >>
> >> https://github.com/systemd/systemd/blob/main/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.c#L42-L50
> >>
> >>
> >>> GCC:
> >>>
> >>> [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> >>> [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
> >>> [3] TYPEDEF '__u8' type_id=2
> >>> [4] CONST '(anon)' type_id=3
> >>
> >> [...]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-07-08 20:59       ` James Hilliard
@ 2022-07-09 17:24         ` Jose E. Marchesi
  2022-07-09 17:28           ` James Hilliard
  0 siblings, 1 reply; 38+ messages in thread
From: Jose E. Marchesi @ 2022-07-09 17:24 UTC (permalink / raw)
  To: James Hilliard; +Cc: Andrii Nakryiko, bpf, david.faust


> On Fri, Jul 8, 2022 at 12:33 PM Jose E. Marchesi
> <jose.marchesi@oracle.com> wrote:
>>
>>
>> >> On Wed, Jul 6, 2022 at 10:13 AM James Hilliard
>> >> <james.hilliard1@gmail.com> wrote:
>> >>>
>> >>> Note I'm testing with the following patches:
>> >>> https://lore.kernel.org/bpf/20220706111839.1247911-1-james.hilliard1@gmail.com/
>> >>> https://lore.kernel.org/bpf/20220706140623.2917858-1-james.hilliard1@gmail.com/
>> >>>
>> >>> It would appear there's some compatibility issues with bpftool gen and
>> >>> GCC, not sure what side though is wrong here:
>> >>> /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>> >>> gen object src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>> >>> src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
>> >>> libbpf: failed to find BTF info for global/extern symbol 'sd_restrictif_i'
>> >>> Error: failed to link
>> >>> 'src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o':
>> >>> Unknown error -2 (-2)
>> >>>
>> >>> Relevant difference seems to be this:
>> >>> GCC:
>> >>> [55] FUNC 'sd_restrictif_i' type_id=47 linkage=static
>> >>> Clang:
>> >>> [27] FUNC 'sd_restrictif_i' type_id=26 linkage=global
>> >
>> > For functions GCC generates a BTF_KIND_FUNC entry, which has no linkage
>> > information, or so we thought: I just looked at bpftool/btf.c and I
>> > found the linkage info for function types is expected to be encoded in
>> > the vlen field of BTF_KIND_FUNC entries (why not adding a btf_func
>> > instead???) which is surprising to say the least.
>> >
>> > We are changing GCC to encode the linkage info in vlen for these types.
>> > Thanks for reporting this.
>>
>> Patch sent to GCC upstream:
>> https://gcc.gnu.org/pipermail/gcc-patches/2022-July/598090.html
>
> I applied that patch on top of GCC 12.1.0 and it appears to fix the
> bpftool gen object bug.
>
> I am however now hitting a different error during skeleton generation:
> /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> gen skeleton src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> libbpf: elf: skipping unrecognized data section(9) .comment
> libbpf: failed to alloc map 'restrict.bss' content buffer: -22
> Error: failed to open BPF object file: Invalid argument

What is the size of the .bss section in the object file?  Try with:

$ size restrict-ifaces.bpf.o

Looking at libbpf.c, it seems to me that this may be due of trying to
mmap 0 bytes in `bpf_object__init_internal_map':

	map->mmaped = mmap(NULL, bpf_map_mmap_sz(map), PROT_READ | PROT_WRITE,
			   MAP_SHARED | MAP_ANONYMOUS, -1, 0);
	if (map->mmaped == MAP_FAILED) {
		err = -errno;
		map->mmaped = NULL;
		pr_warn("failed to alloc map '%s' content buffer: %d\n",
			map->name, err);
		zfree(&map->real_name);
		zfree(&map->name);
		return err;
	}

I see no check for zero sized sections in
bpf_object__init_global_data_maps.

Is maybe GCC failing to allocate stuff in BSS that is supposed to be
there?

> Stripped file passed to gen skeleton:
> /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> btf dump file
> output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> format raw
> [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
> [3] TYPEDEF '__u8' type_id=2
> [4] CONST '(anon)' type_id=3
> [5] VOLATILE '(anon)' type_id=4
> [6] INT 'short int' size=2 bits_offset=0 nr_bits=16 encoding=SIGNED
> [7] INT 'short unsigned int' size=2 bits_offset=0 nr_bits=16 encoding=(none)
> [8] TYPEDEF '__u16' type_id=7
> [9] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
> [10] TYPEDEF '__s32' type_id=9
> [11] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
> [12] TYPEDEF '__u32' type_id=11
> [13] INT 'long long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
> [14] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64
> encoding=(none)
> [15] TYPEDEF '__u64' type_id=14
> [16] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
> [17] INT 'long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
> [18] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> [19] CONST '(anon)' type_id=18
> [20] TYPEDEF '__be16' type_id=8
> [21] TYPEDEF '__be32' type_id=12
> [22] ENUM 'bpf_map_type' encoding=UNSIGNED size=4 vlen=31
>     'BPF_MAP_TYPE_UNSPEC' val=0
>     'BPF_MAP_TYPE_HASH' val=1
>     'BPF_MAP_TYPE_ARRAY' val=2
>     'BPF_MAP_TYPE_PROG_ARRAY' val=3
>     'BPF_MAP_TYPE_PERF_EVENT_ARRAY' val=4
>     'BPF_MAP_TYPE_PERCPU_HASH' val=5
>     'BPF_MAP_TYPE_PERCPU_ARRAY' val=6
>     'BPF_MAP_TYPE_STACK_TRACE' val=7
>     'BPF_MAP_TYPE_CGROUP_ARRAY' val=8
>     'BPF_MAP_TYPE_LRU_HASH' val=9
>     'BPF_MAP_TYPE_LRU_PERCPU_HASH' val=10
>     'BPF_MAP_TYPE_LPM_TRIE' val=11
>     'BPF_MAP_TYPE_ARRAY_OF_MAPS' val=12
>     'BPF_MAP_TYPE_HASH_OF_MAPS' val=13
>     'BPF_MAP_TYPE_DEVMAP' val=14
>     'BPF_MAP_TYPE_SOCKMAP' val=15
>     'BPF_MAP_TYPE_CPUMAP' val=16
>     'BPF_MAP_TYPE_XSKMAP' val=17
>     'BPF_MAP_TYPE_SOCKHASH' val=18
>     'BPF_MAP_TYPE_CGROUP_STORAGE' val=19
>     'BPF_MAP_TYPE_REUSEPORT_SOCKARRAY' val=20
>     'BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE' val=21
>     'BPF_MAP_TYPE_QUEUE' val=22
>     'BPF_MAP_TYPE_STACK' val=23
>     'BPF_MAP_TYPE_SK_STORAGE' val=24
>     'BPF_MAP_TYPE_DEVMAP_HASH' val=25
>     'BPF_MAP_TYPE_STRUCT_OPS' val=26
>     'BPF_MAP_TYPE_RINGBUF' val=27
>     'BPF_MAP_TYPE_INODE_STORAGE' val=28
>     'BPF_MAP_TYPE_TASK_STORAGE' val=29
>     'BPF_MAP_TYPE_BLOOM_FILTER' val=30
> [23] UNION '(anon)' size=8 vlen=1
>     'flow_keys' type_id=29 bits_offset=0
> [24] STRUCT 'bpf_flow_keys' size=56 vlen=13
>     'nhoff' type_id=8 bits_offset=0
>     'thoff' type_id=8 bits_offset=16
>     'addr_proto' type_id=8 bits_offset=32
>     'is_frag' type_id=3 bits_offset=48
>     'is_first_frag' type_id=3 bits_offset=56
>     'is_encap' type_id=3 bits_offset=64
>     'ip_proto' type_id=3 bits_offset=72
>     'n_proto' type_id=20 bits_offset=80
>     'sport' type_id=20 bits_offset=96
>     'dport' type_id=20 bits_offset=112
>     '(anon)' type_id=25 bits_offset=128
>     'flags' type_id=12 bits_offset=384
>     'flow_label' type_id=21 bits_offset=416
> [25] UNION '(anon)' size=32 vlen=2
>     '(anon)' type_id=26 bits_offset=0
>     '(anon)' type_id=27 bits_offset=0
> [26] STRUCT '(anon)' size=8 vlen=2
>     'ipv4_src' type_id=21 bits_offset=0
>     'ipv4_dst' type_id=21 bits_offset=32
> [27] STRUCT '(anon)' size=32 vlen=2
>     'ipv6_src' type_id=28 bits_offset=0
>     'ipv6_dst' type_id=28 bits_offset=128
> [28] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=4
> [29] PTR '(anon)' type_id=24
> [30] UNION '(anon)' size=8 vlen=1
>     'sk' type_id=32 bits_offset=0
> [31] STRUCT 'bpf_sock' size=80 vlen=14
>     'bound_dev_if' type_id=12 bits_offset=0
>     'family' type_id=12 bits_offset=32
>     'type' type_id=12 bits_offset=64
>     'protocol' type_id=12 bits_offset=96
>     'mark' type_id=12 bits_offset=128
>     'priority' type_id=12 bits_offset=160
>     'src_ip4' type_id=12 bits_offset=192
>     'src_ip6' type_id=28 bits_offset=224
>     'src_port' type_id=12 bits_offset=352
>     'dst_port' type_id=20 bits_offset=384
>     'dst_ip4' type_id=12 bits_offset=416
>     'dst_ip6' type_id=28 bits_offset=448
>     'state' type_id=12 bits_offset=576
>     'rx_queue_mapping' type_id=10 bits_offset=608
> [32] PTR '(anon)' type_id=31
> [33] STRUCT '__sk_buff' size=192 vlen=33
>     'len' type_id=12 bits_offset=0
>     'pkt_type' type_id=12 bits_offset=32
>     'mark' type_id=12 bits_offset=64
>     'queue_mapping' type_id=12 bits_offset=96
>     'protocol' type_id=12 bits_offset=128
>     'vlan_present' type_id=12 bits_offset=160
>     'vlan_tci' type_id=12 bits_offset=192
>     'vlan_proto' type_id=12 bits_offset=224
>     'priority' type_id=12 bits_offset=256
>     'ingress_ifindex' type_id=12 bits_offset=288
>     'ifindex' type_id=12 bits_offset=320
>     'tc_index' type_id=12 bits_offset=352
>     'cb' type_id=34 bits_offset=384
>     'hash' type_id=12 bits_offset=544
>     'tc_classid' type_id=12 bits_offset=576
>     'data' type_id=12 bits_offset=608
>     'data_end' type_id=12 bits_offset=640
>     'napi_id' type_id=12 bits_offset=672
>     'family' type_id=12 bits_offset=704
>     'remote_ip4' type_id=12 bits_offset=736
>     'local_ip4' type_id=12 bits_offset=768
>     'remote_ip6' type_id=28 bits_offset=800
>     'local_ip6' type_id=28 bits_offset=928
>     'remote_port' type_id=12 bits_offset=1056
>     'local_port' type_id=12 bits_offset=1088
>     'data_meta' type_id=12 bits_offset=1120
>     '(anon)' type_id=23 bits_offset=1152
>     'tstamp' type_id=15 bits_offset=1216
>     'wire_len' type_id=12 bits_offset=1280
>     'gso_segs' type_id=12 bits_offset=1312
>     '(anon)' type_id=30 bits_offset=1344
>     'gso_size' type_id=12 bits_offset=1408
>     'hwtstamp' type_id=15 bits_offset=1472
> [34] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=5
> [35] CONST '(anon)' type_id=33
> [36] PTR '(anon)' type_id=0
> [37] STRUCT '(anon)' size=24 vlen=3
>     'type' type_id=39 bits_offset=0
>     'key' type_id=40 bits_offset=64
>     'value' type_id=41 bits_offset=128
> [38] ARRAY '(anon)' type_id=9 index_type_id=16 nr_elems=1
> [39] PTR '(anon)' type_id=38
> [40] PTR '(anon)' type_id=12
> [41] PTR '(anon)' type_id=3
> [42] ARRAY '(anon)' type_id=19 index_type_id=16 nr_elems=18
> [43] CONST '(anon)' type_id=42
> [44] FUNC_PROTO '(anon)' ret_type_id=36 vlen=2
>     '(anon)' type_id=36
>     '(anon)' type_id=46
> [45] CONST '(anon)' type_id=0
> [46] PTR '(anon)' type_id=45
> [47] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>     'sk' type_id=48
> [48] PTR '(anon)' type_id=35
> [49] VAR '_license' type_id=43, linkage=static
> [50] VAR 'is_allow_list' type_id=5, linkage=global
> [51] VAR 'sd_restrictif' type_id=37, linkage=global
> [52] FUNC 'sd_restrictif_i' type_id=47 linkage=global
> [53] FUNC 'sd_restrictif_e' type_id=47 linkage=global
> [54] FUNC 'restrict_network_interfaces_impl' type_id=47 linkage=static
> [55] DATASEC '.data' size=1 vlen=1
>     type_id=50 offset=0 size=1 (VAR 'is_allow_list')
> [56] DATASEC 'license' size=18 vlen=1
>     type_id=49 offset=0 size=18 (VAR '_license')
> [57] DATASEC '.maps' size=24 vlen=1
>     type_id=51 offset=0 size=24 (VAR 'sd_restrictif')
>
> File before being stripped using bpftool gen object:
> /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> btf dump file
> output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
> format raw
> [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
> [3] TYPEDEF '__u8' type_id=2
> [4] CONST '(anon)' type_id=3
> [5] VOLATILE '(anon)' type_id=4
> [6] INT 'short int' size=2 bits_offset=0 nr_bits=16 encoding=SIGNED
> [7] INT 'short unsigned int' size=2 bits_offset=0 nr_bits=16 encoding=(none)
> [8] TYPEDEF '__u16' type_id=7
> [9] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
> [10] TYPEDEF '__s32' type_id=9
> [11] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
> [12] TYPEDEF '__u32' type_id=11
> [13] INT 'long long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
> [14] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64
> encoding=(none)
> [15] TYPEDEF '__u64' type_id=14
> [16] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
> [17] INT 'long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
> [18] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> [19] CONST '(anon)' type_id=18
> [20] TYPEDEF '__be16' type_id=8
> [21] TYPEDEF '__be32' type_id=12
> [22] ENUM 'bpf_map_type' encoding=UNSIGNED size=4 vlen=31
>     'BPF_MAP_TYPE_UNSPEC' val=0
>     'BPF_MAP_TYPE_HASH' val=1
>     'BPF_MAP_TYPE_ARRAY' val=2
>     'BPF_MAP_TYPE_PROG_ARRAY' val=3
>     'BPF_MAP_TYPE_PERF_EVENT_ARRAY' val=4
>     'BPF_MAP_TYPE_PERCPU_HASH' val=5
>     'BPF_MAP_TYPE_PERCPU_ARRAY' val=6
>     'BPF_MAP_TYPE_STACK_TRACE' val=7
>     'BPF_MAP_TYPE_CGROUP_ARRAY' val=8
>     'BPF_MAP_TYPE_LRU_HASH' val=9
>     'BPF_MAP_TYPE_LRU_PERCPU_HASH' val=10
>     'BPF_MAP_TYPE_LPM_TRIE' val=11
>     'BPF_MAP_TYPE_ARRAY_OF_MAPS' val=12
>     'BPF_MAP_TYPE_HASH_OF_MAPS' val=13
>     'BPF_MAP_TYPE_DEVMAP' val=14
>     'BPF_MAP_TYPE_SOCKMAP' val=15
>     'BPF_MAP_TYPE_CPUMAP' val=16
>     'BPF_MAP_TYPE_XSKMAP' val=17
>     'BPF_MAP_TYPE_SOCKHASH' val=18
>     'BPF_MAP_TYPE_CGROUP_STORAGE' val=19
>     'BPF_MAP_TYPE_REUSEPORT_SOCKARRAY' val=20
>     'BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE' val=21
>     'BPF_MAP_TYPE_QUEUE' val=22
>     'BPF_MAP_TYPE_STACK' val=23
>     'BPF_MAP_TYPE_SK_STORAGE' val=24
>     'BPF_MAP_TYPE_DEVMAP_HASH' val=25
>     'BPF_MAP_TYPE_STRUCT_OPS' val=26
>     'BPF_MAP_TYPE_RINGBUF' val=27
>     'BPF_MAP_TYPE_INODE_STORAGE' val=28
>     'BPF_MAP_TYPE_TASK_STORAGE' val=29
>     'BPF_MAP_TYPE_BLOOM_FILTER' val=30
> [23] UNION '(anon)' size=8 vlen=1
>     'flow_keys' type_id=29 bits_offset=0
> [24] STRUCT 'bpf_flow_keys' size=56 vlen=13
>     'nhoff' type_id=8 bits_offset=0
>     'thoff' type_id=8 bits_offset=16
>     'addr_proto' type_id=8 bits_offset=32
>     'is_frag' type_id=3 bits_offset=48
>     'is_first_frag' type_id=3 bits_offset=56
>     'is_encap' type_id=3 bits_offset=64
>     'ip_proto' type_id=3 bits_offset=72
>     'n_proto' type_id=20 bits_offset=80
>     'sport' type_id=20 bits_offset=96
>     'dport' type_id=20 bits_offset=112
>     '(anon)' type_id=25 bits_offset=128
>     'flags' type_id=12 bits_offset=384
>     'flow_label' type_id=21 bits_offset=416
> [25] UNION '(anon)' size=32 vlen=2
>     '(anon)' type_id=26 bits_offset=0
>     '(anon)' type_id=27 bits_offset=0
> [26] STRUCT '(anon)' size=8 vlen=2
>     'ipv4_src' type_id=21 bits_offset=0
>     'ipv4_dst' type_id=21 bits_offset=32
> [27] STRUCT '(anon)' size=32 vlen=2
>     'ipv6_src' type_id=28 bits_offset=0
>     'ipv6_dst' type_id=28 bits_offset=128
> [28] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=4
> [29] PTR '(anon)' type_id=24
> [30] UNION '(anon)' size=8 vlen=1
>     'sk' type_id=32 bits_offset=0
> [31] STRUCT 'bpf_sock' size=80 vlen=14
>     'bound_dev_if' type_id=12 bits_offset=0
>     'family' type_id=12 bits_offset=32
>     'type' type_id=12 bits_offset=64
>     'protocol' type_id=12 bits_offset=96
>     'mark' type_id=12 bits_offset=128
>     'priority' type_id=12 bits_offset=160
>     'src_ip4' type_id=12 bits_offset=192
>     'src_ip6' type_id=28 bits_offset=224
>     'src_port' type_id=12 bits_offset=352
>     'dst_port' type_id=20 bits_offset=384
>     'dst_ip4' type_id=12 bits_offset=416
>     'dst_ip6' type_id=28 bits_offset=448
>     'state' type_id=12 bits_offset=576
>     'rx_queue_mapping' type_id=10 bits_offset=608
> [32] PTR '(anon)' type_id=31
> [33] STRUCT '__sk_buff' size=192 vlen=33
>     'len' type_id=12 bits_offset=0
>     'pkt_type' type_id=12 bits_offset=32
>     'mark' type_id=12 bits_offset=64
>     'queue_mapping' type_id=12 bits_offset=96
>     'protocol' type_id=12 bits_offset=128
>     'vlan_present' type_id=12 bits_offset=160
>     'vlan_tci' type_id=12 bits_offset=192
>     'vlan_proto' type_id=12 bits_offset=224
>     'priority' type_id=12 bits_offset=256
>     'ingress_ifindex' type_id=12 bits_offset=288
>     'ifindex' type_id=12 bits_offset=320
>     'tc_index' type_id=12 bits_offset=352
>     'cb' type_id=34 bits_offset=384
>     'hash' type_id=12 bits_offset=544
>     'tc_classid' type_id=12 bits_offset=576
>     'data' type_id=12 bits_offset=608
>     'data_end' type_id=12 bits_offset=640
>     'napi_id' type_id=12 bits_offset=672
>     'family' type_id=12 bits_offset=704
>     'remote_ip4' type_id=12 bits_offset=736
>     'local_ip4' type_id=12 bits_offset=768
>     'remote_ip6' type_id=28 bits_offset=800
>     'local_ip6' type_id=28 bits_offset=928
>     'remote_port' type_id=12 bits_offset=1056
>     'local_port' type_id=12 bits_offset=1088
>     'data_meta' type_id=12 bits_offset=1120
>     '(anon)' type_id=23 bits_offset=1152
>     'tstamp' type_id=15 bits_offset=1216
>     'wire_len' type_id=12 bits_offset=1280
>     'gso_segs' type_id=12 bits_offset=1312
>     '(anon)' type_id=30 bits_offset=1344
>     'gso_size' type_id=12 bits_offset=1408
>     'hwtstamp' type_id=15 bits_offset=1472
> [34] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=5
> [35] CONST '(anon)' type_id=33
> [36] PTR '(anon)' type_id=0
> [37] STRUCT '(anon)' size=24 vlen=3
>     'type' type_id=39 bits_offset=0
>     'key' type_id=40 bits_offset=64
>     'value' type_id=41 bits_offset=128
> [38] ARRAY '(anon)' type_id=9 index_type_id=16 nr_elems=1
> [39] PTR '(anon)' type_id=38
> [40] PTR '(anon)' type_id=12
> [41] PTR '(anon)' type_id=3
> [42] ARRAY '(anon)' type_id=19 index_type_id=16 nr_elems=18
> [43] CONST '(anon)' type_id=42
> [44] FUNC_PROTO '(anon)' ret_type_id=36 vlen=2
>     '(anon)' type_id=36
>     '(anon)' type_id=46
> [45] CONST '(anon)' type_id=0
> [46] PTR '(anon)' type_id=45
> [47] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>     'sk' type_id=48
> [48] PTR '(anon)' type_id=35
> [49] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>     'sk' type_id=48
> [50] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>     'sk' type_id=48
> [51] VAR '_license' type_id=43, linkage=static
> [52] VAR 'is_allow_list' type_id=5, linkage=global
> [53] VAR 'sd_restrictif' type_id=37, linkage=global
> [54] FUNC 'bpf_map_lookup_elem' type_id=44 linkage=global
> [55] FUNC 'sd_restrictif_i' type_id=47 linkage=global
> [56] FUNC 'sd_restrictif_e' type_id=49 linkage=global
> [57] FUNC 'restrict_network_interfaces_impl' type_id=50 linkage=static
> [58] DATASEC 'license' size=0 vlen=1
>     type_id=51 offset=0 size=18 (VAR '_license')
> [59] DATASEC '.maps' size=0 vlen=1
>     type_id=53 offset=0 size=24 (VAR 'sd_restrictif')
> [60] DATASEC '.data' size=0 vlen=1
>     type_id=52 offset=0 size=1 (VAR 'is_allow_list')
>
>>
>> >> GCC is wrong, clearly. This function is global ([0]) and libbpf
>> >> expects it to be marked as such in BTF.
>> >>
>> >>
> https://github.com/systemd/systemd/blob/main/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.c#L42-L50
>> >>
>> >>
>> >>> GCC:
>> >>>
>> >>> [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>> >>> [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
>> >>> [3] TYPEDEF '__u8' type_id=2
>> >>> [4] CONST '(anon)' type_id=3
>> >>
>> >> [...]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-07-09 17:24         ` Jose E. Marchesi
@ 2022-07-09 17:28           ` James Hilliard
  2022-07-09 20:20             ` Jose E. Marchesi
  0 siblings, 1 reply; 38+ messages in thread
From: James Hilliard @ 2022-07-09 17:28 UTC (permalink / raw)
  To: Jose E. Marchesi; +Cc: Andrii Nakryiko, bpf, david.faust

On Sat, Jul 9, 2022 at 11:24 AM Jose E. Marchesi
<jose.marchesi@oracle.com> wrote:
>
>
> > On Fri, Jul 8, 2022 at 12:33 PM Jose E. Marchesi
> > <jose.marchesi@oracle.com> wrote:
> >>
> >>
> >> >> On Wed, Jul 6, 2022 at 10:13 AM James Hilliard
> >> >> <james.hilliard1@gmail.com> wrote:
> >> >>>
> >> >>> Note I'm testing with the following patches:
> >> >>> https://lore.kernel.org/bpf/20220706111839.1247911-1-james.hilliard1@gmail.com/
> >> >>> https://lore.kernel.org/bpf/20220706140623.2917858-1-james.hilliard1@gmail.com/
> >> >>>
> >> >>> It would appear there's some compatibility issues with bpftool gen and
> >> >>> GCC, not sure what side though is wrong here:
> >> >>> /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> >> >>> gen object src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> >> >>> src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
> >> >>> libbpf: failed to find BTF info for global/extern symbol 'sd_restrictif_i'
> >> >>> Error: failed to link
> >> >>> 'src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o':
> >> >>> Unknown error -2 (-2)
> >> >>>
> >> >>> Relevant difference seems to be this:
> >> >>> GCC:
> >> >>> [55] FUNC 'sd_restrictif_i' type_id=47 linkage=static
> >> >>> Clang:
> >> >>> [27] FUNC 'sd_restrictif_i' type_id=26 linkage=global
> >> >
> >> > For functions GCC generates a BTF_KIND_FUNC entry, which has no linkage
> >> > information, or so we thought: I just looked at bpftool/btf.c and I
> >> > found the linkage info for function types is expected to be encoded in
> >> > the vlen field of BTF_KIND_FUNC entries (why not adding a btf_func
> >> > instead???) which is surprising to say the least.
> >> >
> >> > We are changing GCC to encode the linkage info in vlen for these types.
> >> > Thanks for reporting this.
> >>
> >> Patch sent to GCC upstream:
> >> https://gcc.gnu.org/pipermail/gcc-patches/2022-July/598090.html
> >
> > I applied that patch on top of GCC 12.1.0 and it appears to fix the
> > bpftool gen object bug.
> >
> > I am however now hitting a different error during skeleton generation:
> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> > gen skeleton src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> > libbpf: elf: skipping unrecognized data section(9) .comment
> > libbpf: failed to alloc map 'restrict.bss' content buffer: -22
> > Error: failed to open BPF object file: Invalid argument
>
> What is the size of the .bss section in the object file?  Try with:
>
> $ size restrict-ifaces.bpf.o

$ size output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
   text       data        bss        dec        hex    filename
    386         25          0        411        19b
output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o

>
> Looking at libbpf.c, it seems to me that this may be due of trying to
> mmap 0 bytes in `bpf_object__init_internal_map':
>
>         map->mmaped = mmap(NULL, bpf_map_mmap_sz(map), PROT_READ | PROT_WRITE,
>                            MAP_SHARED | MAP_ANONYMOUS, -1, 0);
>         if (map->mmaped == MAP_FAILED) {
>                 err = -errno;
>                 map->mmaped = NULL;
>                 pr_warn("failed to alloc map '%s' content buffer: %d\n",
>                         map->name, err);
>                 zfree(&map->real_name);
>                 zfree(&map->name);
>                 return err;
>         }
>
> I see no check for zero sized sections in
> bpf_object__init_global_data_maps.
>
> Is maybe GCC failing to allocate stuff in BSS that is supposed to be
> there?
>
> > Stripped file passed to gen skeleton:
> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> > btf dump file
> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> > format raw
> > [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> > [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
> > [3] TYPEDEF '__u8' type_id=2
> > [4] CONST '(anon)' type_id=3
> > [5] VOLATILE '(anon)' type_id=4
> > [6] INT 'short int' size=2 bits_offset=0 nr_bits=16 encoding=SIGNED
> > [7] INT 'short unsigned int' size=2 bits_offset=0 nr_bits=16 encoding=(none)
> > [8] TYPEDEF '__u16' type_id=7
> > [9] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
> > [10] TYPEDEF '__s32' type_id=9
> > [11] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
> > [12] TYPEDEF '__u32' type_id=11
> > [13] INT 'long long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
> > [14] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64
> > encoding=(none)
> > [15] TYPEDEF '__u64' type_id=14
> > [16] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
> > [17] INT 'long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
> > [18] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> > [19] CONST '(anon)' type_id=18
> > [20] TYPEDEF '__be16' type_id=8
> > [21] TYPEDEF '__be32' type_id=12
> > [22] ENUM 'bpf_map_type' encoding=UNSIGNED size=4 vlen=31
> >     'BPF_MAP_TYPE_UNSPEC' val=0
> >     'BPF_MAP_TYPE_HASH' val=1
> >     'BPF_MAP_TYPE_ARRAY' val=2
> >     'BPF_MAP_TYPE_PROG_ARRAY' val=3
> >     'BPF_MAP_TYPE_PERF_EVENT_ARRAY' val=4
> >     'BPF_MAP_TYPE_PERCPU_HASH' val=5
> >     'BPF_MAP_TYPE_PERCPU_ARRAY' val=6
> >     'BPF_MAP_TYPE_STACK_TRACE' val=7
> >     'BPF_MAP_TYPE_CGROUP_ARRAY' val=8
> >     'BPF_MAP_TYPE_LRU_HASH' val=9
> >     'BPF_MAP_TYPE_LRU_PERCPU_HASH' val=10
> >     'BPF_MAP_TYPE_LPM_TRIE' val=11
> >     'BPF_MAP_TYPE_ARRAY_OF_MAPS' val=12
> >     'BPF_MAP_TYPE_HASH_OF_MAPS' val=13
> >     'BPF_MAP_TYPE_DEVMAP' val=14
> >     'BPF_MAP_TYPE_SOCKMAP' val=15
> >     'BPF_MAP_TYPE_CPUMAP' val=16
> >     'BPF_MAP_TYPE_XSKMAP' val=17
> >     'BPF_MAP_TYPE_SOCKHASH' val=18
> >     'BPF_MAP_TYPE_CGROUP_STORAGE' val=19
> >     'BPF_MAP_TYPE_REUSEPORT_SOCKARRAY' val=20
> >     'BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE' val=21
> >     'BPF_MAP_TYPE_QUEUE' val=22
> >     'BPF_MAP_TYPE_STACK' val=23
> >     'BPF_MAP_TYPE_SK_STORAGE' val=24
> >     'BPF_MAP_TYPE_DEVMAP_HASH' val=25
> >     'BPF_MAP_TYPE_STRUCT_OPS' val=26
> >     'BPF_MAP_TYPE_RINGBUF' val=27
> >     'BPF_MAP_TYPE_INODE_STORAGE' val=28
> >     'BPF_MAP_TYPE_TASK_STORAGE' val=29
> >     'BPF_MAP_TYPE_BLOOM_FILTER' val=30
> > [23] UNION '(anon)' size=8 vlen=1
> >     'flow_keys' type_id=29 bits_offset=0
> > [24] STRUCT 'bpf_flow_keys' size=56 vlen=13
> >     'nhoff' type_id=8 bits_offset=0
> >     'thoff' type_id=8 bits_offset=16
> >     'addr_proto' type_id=8 bits_offset=32
> >     'is_frag' type_id=3 bits_offset=48
> >     'is_first_frag' type_id=3 bits_offset=56
> >     'is_encap' type_id=3 bits_offset=64
> >     'ip_proto' type_id=3 bits_offset=72
> >     'n_proto' type_id=20 bits_offset=80
> >     'sport' type_id=20 bits_offset=96
> >     'dport' type_id=20 bits_offset=112
> >     '(anon)' type_id=25 bits_offset=128
> >     'flags' type_id=12 bits_offset=384
> >     'flow_label' type_id=21 bits_offset=416
> > [25] UNION '(anon)' size=32 vlen=2
> >     '(anon)' type_id=26 bits_offset=0
> >     '(anon)' type_id=27 bits_offset=0
> > [26] STRUCT '(anon)' size=8 vlen=2
> >     'ipv4_src' type_id=21 bits_offset=0
> >     'ipv4_dst' type_id=21 bits_offset=32
> > [27] STRUCT '(anon)' size=32 vlen=2
> >     'ipv6_src' type_id=28 bits_offset=0
> >     'ipv6_dst' type_id=28 bits_offset=128
> > [28] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=4
> > [29] PTR '(anon)' type_id=24
> > [30] UNION '(anon)' size=8 vlen=1
> >     'sk' type_id=32 bits_offset=0
> > [31] STRUCT 'bpf_sock' size=80 vlen=14
> >     'bound_dev_if' type_id=12 bits_offset=0
> >     'family' type_id=12 bits_offset=32
> >     'type' type_id=12 bits_offset=64
> >     'protocol' type_id=12 bits_offset=96
> >     'mark' type_id=12 bits_offset=128
> >     'priority' type_id=12 bits_offset=160
> >     'src_ip4' type_id=12 bits_offset=192
> >     'src_ip6' type_id=28 bits_offset=224
> >     'src_port' type_id=12 bits_offset=352
> >     'dst_port' type_id=20 bits_offset=384
> >     'dst_ip4' type_id=12 bits_offset=416
> >     'dst_ip6' type_id=28 bits_offset=448
> >     'state' type_id=12 bits_offset=576
> >     'rx_queue_mapping' type_id=10 bits_offset=608
> > [32] PTR '(anon)' type_id=31
> > [33] STRUCT '__sk_buff' size=192 vlen=33
> >     'len' type_id=12 bits_offset=0
> >     'pkt_type' type_id=12 bits_offset=32
> >     'mark' type_id=12 bits_offset=64
> >     'queue_mapping' type_id=12 bits_offset=96
> >     'protocol' type_id=12 bits_offset=128
> >     'vlan_present' type_id=12 bits_offset=160
> >     'vlan_tci' type_id=12 bits_offset=192
> >     'vlan_proto' type_id=12 bits_offset=224
> >     'priority' type_id=12 bits_offset=256
> >     'ingress_ifindex' type_id=12 bits_offset=288
> >     'ifindex' type_id=12 bits_offset=320
> >     'tc_index' type_id=12 bits_offset=352
> >     'cb' type_id=34 bits_offset=384
> >     'hash' type_id=12 bits_offset=544
> >     'tc_classid' type_id=12 bits_offset=576
> >     'data' type_id=12 bits_offset=608
> >     'data_end' type_id=12 bits_offset=640
> >     'napi_id' type_id=12 bits_offset=672
> >     'family' type_id=12 bits_offset=704
> >     'remote_ip4' type_id=12 bits_offset=736
> >     'local_ip4' type_id=12 bits_offset=768
> >     'remote_ip6' type_id=28 bits_offset=800
> >     'local_ip6' type_id=28 bits_offset=928
> >     'remote_port' type_id=12 bits_offset=1056
> >     'local_port' type_id=12 bits_offset=1088
> >     'data_meta' type_id=12 bits_offset=1120
> >     '(anon)' type_id=23 bits_offset=1152
> >     'tstamp' type_id=15 bits_offset=1216
> >     'wire_len' type_id=12 bits_offset=1280
> >     'gso_segs' type_id=12 bits_offset=1312
> >     '(anon)' type_id=30 bits_offset=1344
> >     'gso_size' type_id=12 bits_offset=1408
> >     'hwtstamp' type_id=15 bits_offset=1472
> > [34] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=5
> > [35] CONST '(anon)' type_id=33
> > [36] PTR '(anon)' type_id=0
> > [37] STRUCT '(anon)' size=24 vlen=3
> >     'type' type_id=39 bits_offset=0
> >     'key' type_id=40 bits_offset=64
> >     'value' type_id=41 bits_offset=128
> > [38] ARRAY '(anon)' type_id=9 index_type_id=16 nr_elems=1
> > [39] PTR '(anon)' type_id=38
> > [40] PTR '(anon)' type_id=12
> > [41] PTR '(anon)' type_id=3
> > [42] ARRAY '(anon)' type_id=19 index_type_id=16 nr_elems=18
> > [43] CONST '(anon)' type_id=42
> > [44] FUNC_PROTO '(anon)' ret_type_id=36 vlen=2
> >     '(anon)' type_id=36
> >     '(anon)' type_id=46
> > [45] CONST '(anon)' type_id=0
> > [46] PTR '(anon)' type_id=45
> > [47] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
> >     'sk' type_id=48
> > [48] PTR '(anon)' type_id=35
> > [49] VAR '_license' type_id=43, linkage=static
> > [50] VAR 'is_allow_list' type_id=5, linkage=global
> > [51] VAR 'sd_restrictif' type_id=37, linkage=global
> > [52] FUNC 'sd_restrictif_i' type_id=47 linkage=global
> > [53] FUNC 'sd_restrictif_e' type_id=47 linkage=global
> > [54] FUNC 'restrict_network_interfaces_impl' type_id=47 linkage=static
> > [55] DATASEC '.data' size=1 vlen=1
> >     type_id=50 offset=0 size=1 (VAR 'is_allow_list')
> > [56] DATASEC 'license' size=18 vlen=1
> >     type_id=49 offset=0 size=18 (VAR '_license')
> > [57] DATASEC '.maps' size=24 vlen=1
> >     type_id=51 offset=0 size=24 (VAR 'sd_restrictif')
> >
> > File before being stripped using bpftool gen object:
> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> > btf dump file
> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
> > format raw
> > [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> > [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
> > [3] TYPEDEF '__u8' type_id=2
> > [4] CONST '(anon)' type_id=3
> > [5] VOLATILE '(anon)' type_id=4
> > [6] INT 'short int' size=2 bits_offset=0 nr_bits=16 encoding=SIGNED
> > [7] INT 'short unsigned int' size=2 bits_offset=0 nr_bits=16 encoding=(none)
> > [8] TYPEDEF '__u16' type_id=7
> > [9] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
> > [10] TYPEDEF '__s32' type_id=9
> > [11] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
> > [12] TYPEDEF '__u32' type_id=11
> > [13] INT 'long long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
> > [14] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64
> > encoding=(none)
> > [15] TYPEDEF '__u64' type_id=14
> > [16] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
> > [17] INT 'long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
> > [18] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> > [19] CONST '(anon)' type_id=18
> > [20] TYPEDEF '__be16' type_id=8
> > [21] TYPEDEF '__be32' type_id=12
> > [22] ENUM 'bpf_map_type' encoding=UNSIGNED size=4 vlen=31
> >     'BPF_MAP_TYPE_UNSPEC' val=0
> >     'BPF_MAP_TYPE_HASH' val=1
> >     'BPF_MAP_TYPE_ARRAY' val=2
> >     'BPF_MAP_TYPE_PROG_ARRAY' val=3
> >     'BPF_MAP_TYPE_PERF_EVENT_ARRAY' val=4
> >     'BPF_MAP_TYPE_PERCPU_HASH' val=5
> >     'BPF_MAP_TYPE_PERCPU_ARRAY' val=6
> >     'BPF_MAP_TYPE_STACK_TRACE' val=7
> >     'BPF_MAP_TYPE_CGROUP_ARRAY' val=8
> >     'BPF_MAP_TYPE_LRU_HASH' val=9
> >     'BPF_MAP_TYPE_LRU_PERCPU_HASH' val=10
> >     'BPF_MAP_TYPE_LPM_TRIE' val=11
> >     'BPF_MAP_TYPE_ARRAY_OF_MAPS' val=12
> >     'BPF_MAP_TYPE_HASH_OF_MAPS' val=13
> >     'BPF_MAP_TYPE_DEVMAP' val=14
> >     'BPF_MAP_TYPE_SOCKMAP' val=15
> >     'BPF_MAP_TYPE_CPUMAP' val=16
> >     'BPF_MAP_TYPE_XSKMAP' val=17
> >     'BPF_MAP_TYPE_SOCKHASH' val=18
> >     'BPF_MAP_TYPE_CGROUP_STORAGE' val=19
> >     'BPF_MAP_TYPE_REUSEPORT_SOCKARRAY' val=20
> >     'BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE' val=21
> >     'BPF_MAP_TYPE_QUEUE' val=22
> >     'BPF_MAP_TYPE_STACK' val=23
> >     'BPF_MAP_TYPE_SK_STORAGE' val=24
> >     'BPF_MAP_TYPE_DEVMAP_HASH' val=25
> >     'BPF_MAP_TYPE_STRUCT_OPS' val=26
> >     'BPF_MAP_TYPE_RINGBUF' val=27
> >     'BPF_MAP_TYPE_INODE_STORAGE' val=28
> >     'BPF_MAP_TYPE_TASK_STORAGE' val=29
> >     'BPF_MAP_TYPE_BLOOM_FILTER' val=30
> > [23] UNION '(anon)' size=8 vlen=1
> >     'flow_keys' type_id=29 bits_offset=0
> > [24] STRUCT 'bpf_flow_keys' size=56 vlen=13
> >     'nhoff' type_id=8 bits_offset=0
> >     'thoff' type_id=8 bits_offset=16
> >     'addr_proto' type_id=8 bits_offset=32
> >     'is_frag' type_id=3 bits_offset=48
> >     'is_first_frag' type_id=3 bits_offset=56
> >     'is_encap' type_id=3 bits_offset=64
> >     'ip_proto' type_id=3 bits_offset=72
> >     'n_proto' type_id=20 bits_offset=80
> >     'sport' type_id=20 bits_offset=96
> >     'dport' type_id=20 bits_offset=112
> >     '(anon)' type_id=25 bits_offset=128
> >     'flags' type_id=12 bits_offset=384
> >     'flow_label' type_id=21 bits_offset=416
> > [25] UNION '(anon)' size=32 vlen=2
> >     '(anon)' type_id=26 bits_offset=0
> >     '(anon)' type_id=27 bits_offset=0
> > [26] STRUCT '(anon)' size=8 vlen=2
> >     'ipv4_src' type_id=21 bits_offset=0
> >     'ipv4_dst' type_id=21 bits_offset=32
> > [27] STRUCT '(anon)' size=32 vlen=2
> >     'ipv6_src' type_id=28 bits_offset=0
> >     'ipv6_dst' type_id=28 bits_offset=128
> > [28] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=4
> > [29] PTR '(anon)' type_id=24
> > [30] UNION '(anon)' size=8 vlen=1
> >     'sk' type_id=32 bits_offset=0
> > [31] STRUCT 'bpf_sock' size=80 vlen=14
> >     'bound_dev_if' type_id=12 bits_offset=0
> >     'family' type_id=12 bits_offset=32
> >     'type' type_id=12 bits_offset=64
> >     'protocol' type_id=12 bits_offset=96
> >     'mark' type_id=12 bits_offset=128
> >     'priority' type_id=12 bits_offset=160
> >     'src_ip4' type_id=12 bits_offset=192
> >     'src_ip6' type_id=28 bits_offset=224
> >     'src_port' type_id=12 bits_offset=352
> >     'dst_port' type_id=20 bits_offset=384
> >     'dst_ip4' type_id=12 bits_offset=416
> >     'dst_ip6' type_id=28 bits_offset=448
> >     'state' type_id=12 bits_offset=576
> >     'rx_queue_mapping' type_id=10 bits_offset=608
> > [32] PTR '(anon)' type_id=31
> > [33] STRUCT '__sk_buff' size=192 vlen=33
> >     'len' type_id=12 bits_offset=0
> >     'pkt_type' type_id=12 bits_offset=32
> >     'mark' type_id=12 bits_offset=64
> >     'queue_mapping' type_id=12 bits_offset=96
> >     'protocol' type_id=12 bits_offset=128
> >     'vlan_present' type_id=12 bits_offset=160
> >     'vlan_tci' type_id=12 bits_offset=192
> >     'vlan_proto' type_id=12 bits_offset=224
> >     'priority' type_id=12 bits_offset=256
> >     'ingress_ifindex' type_id=12 bits_offset=288
> >     'ifindex' type_id=12 bits_offset=320
> >     'tc_index' type_id=12 bits_offset=352
> >     'cb' type_id=34 bits_offset=384
> >     'hash' type_id=12 bits_offset=544
> >     'tc_classid' type_id=12 bits_offset=576
> >     'data' type_id=12 bits_offset=608
> >     'data_end' type_id=12 bits_offset=640
> >     'napi_id' type_id=12 bits_offset=672
> >     'family' type_id=12 bits_offset=704
> >     'remote_ip4' type_id=12 bits_offset=736
> >     'local_ip4' type_id=12 bits_offset=768
> >     'remote_ip6' type_id=28 bits_offset=800
> >     'local_ip6' type_id=28 bits_offset=928
> >     'remote_port' type_id=12 bits_offset=1056
> >     'local_port' type_id=12 bits_offset=1088
> >     'data_meta' type_id=12 bits_offset=1120
> >     '(anon)' type_id=23 bits_offset=1152
> >     'tstamp' type_id=15 bits_offset=1216
> >     'wire_len' type_id=12 bits_offset=1280
> >     'gso_segs' type_id=12 bits_offset=1312
> >     '(anon)' type_id=30 bits_offset=1344
> >     'gso_size' type_id=12 bits_offset=1408
> >     'hwtstamp' type_id=15 bits_offset=1472
> > [34] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=5
> > [35] CONST '(anon)' type_id=33
> > [36] PTR '(anon)' type_id=0
> > [37] STRUCT '(anon)' size=24 vlen=3
> >     'type' type_id=39 bits_offset=0
> >     'key' type_id=40 bits_offset=64
> >     'value' type_id=41 bits_offset=128
> > [38] ARRAY '(anon)' type_id=9 index_type_id=16 nr_elems=1
> > [39] PTR '(anon)' type_id=38
> > [40] PTR '(anon)' type_id=12
> > [41] PTR '(anon)' type_id=3
> > [42] ARRAY '(anon)' type_id=19 index_type_id=16 nr_elems=18
> > [43] CONST '(anon)' type_id=42
> > [44] FUNC_PROTO '(anon)' ret_type_id=36 vlen=2
> >     '(anon)' type_id=36
> >     '(anon)' type_id=46
> > [45] CONST '(anon)' type_id=0
> > [46] PTR '(anon)' type_id=45
> > [47] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
> >     'sk' type_id=48
> > [48] PTR '(anon)' type_id=35
> > [49] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
> >     'sk' type_id=48
> > [50] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
> >     'sk' type_id=48
> > [51] VAR '_license' type_id=43, linkage=static
> > [52] VAR 'is_allow_list' type_id=5, linkage=global
> > [53] VAR 'sd_restrictif' type_id=37, linkage=global
> > [54] FUNC 'bpf_map_lookup_elem' type_id=44 linkage=global
> > [55] FUNC 'sd_restrictif_i' type_id=47 linkage=global
> > [56] FUNC 'sd_restrictif_e' type_id=49 linkage=global
> > [57] FUNC 'restrict_network_interfaces_impl' type_id=50 linkage=static
> > [58] DATASEC 'license' size=0 vlen=1
> >     type_id=51 offset=0 size=18 (VAR '_license')
> > [59] DATASEC '.maps' size=0 vlen=1
> >     type_id=53 offset=0 size=24 (VAR 'sd_restrictif')
> > [60] DATASEC '.data' size=0 vlen=1
> >     type_id=52 offset=0 size=1 (VAR 'is_allow_list')
> >
> >>
> >> >> GCC is wrong, clearly. This function is global ([0]) and libbpf
> >> >> expects it to be marked as such in BTF.
> >> >>
> >> >>
> > https://github.com/systemd/systemd/blob/main/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.c#L42-L50
> >> >>
> >> >>
> >> >>> GCC:
> >> >>>
> >> >>> [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> >> >>> [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
> >> >>> [3] TYPEDEF '__u8' type_id=2
> >> >>> [4] CONST '(anon)' type_id=3
> >> >>
> >> >> [...]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-07-09 17:28           ` James Hilliard
@ 2022-07-09 20:20             ` Jose E. Marchesi
  2022-07-09 20:32               ` James Hilliard
  0 siblings, 1 reply; 38+ messages in thread
From: Jose E. Marchesi @ 2022-07-09 20:20 UTC (permalink / raw)
  To: James Hilliard; +Cc: Andrii Nakryiko, bpf, david.faust


> On Sat, Jul 9, 2022 at 11:24 AM Jose E. Marchesi
> <jose.marchesi@oracle.com> wrote:
>>
>>
>> > On Fri, Jul 8, 2022 at 12:33 PM Jose E. Marchesi
>> > <jose.marchesi@oracle.com> wrote:
>> >>
>> >>
>> >> >> On Wed, Jul 6, 2022 at 10:13 AM James Hilliard
>> >> >> <james.hilliard1@gmail.com> wrote:
>> >> >>>
>> >> >>> Note I'm testing with the following patches:
>> >> >>> https://lore.kernel.org/bpf/20220706111839.1247911-1-james.hilliard1@gmail.com/
>> >> >>> https://lore.kernel.org/bpf/20220706140623.2917858-1-james.hilliard1@gmail.com/
>> >> >>>
>> >> >>> It would appear there's some compatibility issues with bpftool gen and
>> >> >>> GCC, not sure what side though is wrong here:
>> >> >>> /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>> >> >>> gen object src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>> >> >>> src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
>> >> >>> libbpf: failed to find BTF info for global/extern symbol 'sd_restrictif_i'
>> >> >>> Error: failed to link
>> >> >>> 'src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o':
>> >> >>> Unknown error -2 (-2)
>> >> >>>
>> >> >>> Relevant difference seems to be this:
>> >> >>> GCC:
>> >> >>> [55] FUNC 'sd_restrictif_i' type_id=47 linkage=static
>> >> >>> Clang:
>> >> >>> [27] FUNC 'sd_restrictif_i' type_id=26 linkage=global
>> >> >
>> >> > For functions GCC generates a BTF_KIND_FUNC entry, which has no linkage
>> >> > information, or so we thought: I just looked at bpftool/btf.c and I
>> >> > found the linkage info for function types is expected to be encoded in
>> >> > the vlen field of BTF_KIND_FUNC entries (why not adding a btf_func
>> >> > instead???) which is surprising to say the least.
>> >> >
>> >> > We are changing GCC to encode the linkage info in vlen for these types.
>> >> > Thanks for reporting this.
>> >>
>> >> Patch sent to GCC upstream:
>> >> https://gcc.gnu.org/pipermail/gcc-patches/2022-July/598090.html
>> >
>> > I applied that patch on top of GCC 12.1.0 and it appears to fix the
>> > bpftool gen object bug.
>> >
>> > I am however now hitting a different error during skeleton generation:
>> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>> > gen skeleton src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>> > libbpf: elf: skipping unrecognized data section(9) .comment
>> > libbpf: failed to alloc map 'restrict.bss' content buffer: -22
>> > Error: failed to open BPF object file: Invalid argument
>>
>> What is the size of the .bss section in the object file?  Try with:
>>
>> $ size restrict-ifaces.bpf.o
>
> $ size output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>    text       data        bss        dec        hex    filename
>     386         25          0        411        19b
> output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o

Right, so the .bss section is empty.  I see a `const volatile unsigned
char is_allow_list = 0;' in restrict-ifaces.bpf.c, but that goes to
.data and not to .bss, as expected.

If you build restrict-ifaces.bpf.o with LLVM, is the bss still empty?  I
don't think the code in libbpf.c even checks for this eventuality...

>>
>> Looking at libbpf.c, it seems to me that this may be due of trying to
>> mmap 0 bytes in `bpf_object__init_internal_map':
>>
>>         map->mmaped = mmap(NULL, bpf_map_mmap_sz(map), PROT_READ | PROT_WRITE,
>>                            MAP_SHARED | MAP_ANONYMOUS, -1, 0);
>>         if (map->mmaped == MAP_FAILED) {
>>                 err = -errno;
>>                 map->mmaped = NULL;
>>                 pr_warn("failed to alloc map '%s' content buffer: %d\n",
>>                         map->name, err);
>>                 zfree(&map->real_name);
>>                 zfree(&map->name);
>>                 return err;
>>         }
>>
>> I see no check for zero sized sections in
>> bpf_object__init_global_data_maps.
>>
>> Is maybe GCC failing to allocate stuff in BSS that is supposed to be
>> there?
>>
>> > Stripped file passed to gen skeleton:
>> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>> > btf dump file
>> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>> > format raw
>> > [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>> > [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
>> > [3] TYPEDEF '__u8' type_id=2
>> > [4] CONST '(anon)' type_id=3
>> > [5] VOLATILE '(anon)' type_id=4
>> > [6] INT 'short int' size=2 bits_offset=0 nr_bits=16 encoding=SIGNED
>> > [7] INT 'short unsigned int' size=2 bits_offset=0 nr_bits=16 encoding=(none)
>> > [8] TYPEDEF '__u16' type_id=7
>> > [9] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
>> > [10] TYPEDEF '__s32' type_id=9
>> > [11] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
>> > [12] TYPEDEF '__u32' type_id=11
>> > [13] INT 'long long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
>> > [14] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64
>> > encoding=(none)
>> > [15] TYPEDEF '__u64' type_id=14
>> > [16] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
>> > [17] INT 'long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
>> > [18] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>> > [19] CONST '(anon)' type_id=18
>> > [20] TYPEDEF '__be16' type_id=8
>> > [21] TYPEDEF '__be32' type_id=12
>> > [22] ENUM 'bpf_map_type' encoding=UNSIGNED size=4 vlen=31
>> >     'BPF_MAP_TYPE_UNSPEC' val=0
>> >     'BPF_MAP_TYPE_HASH' val=1
>> >     'BPF_MAP_TYPE_ARRAY' val=2
>> >     'BPF_MAP_TYPE_PROG_ARRAY' val=3
>> >     'BPF_MAP_TYPE_PERF_EVENT_ARRAY' val=4
>> >     'BPF_MAP_TYPE_PERCPU_HASH' val=5
>> >     'BPF_MAP_TYPE_PERCPU_ARRAY' val=6
>> >     'BPF_MAP_TYPE_STACK_TRACE' val=7
>> >     'BPF_MAP_TYPE_CGROUP_ARRAY' val=8
>> >     'BPF_MAP_TYPE_LRU_HASH' val=9
>> >     'BPF_MAP_TYPE_LRU_PERCPU_HASH' val=10
>> >     'BPF_MAP_TYPE_LPM_TRIE' val=11
>> >     'BPF_MAP_TYPE_ARRAY_OF_MAPS' val=12
>> >     'BPF_MAP_TYPE_HASH_OF_MAPS' val=13
>> >     'BPF_MAP_TYPE_DEVMAP' val=14
>> >     'BPF_MAP_TYPE_SOCKMAP' val=15
>> >     'BPF_MAP_TYPE_CPUMAP' val=16
>> >     'BPF_MAP_TYPE_XSKMAP' val=17
>> >     'BPF_MAP_TYPE_SOCKHASH' val=18
>> >     'BPF_MAP_TYPE_CGROUP_STORAGE' val=19
>> >     'BPF_MAP_TYPE_REUSEPORT_SOCKARRAY' val=20
>> >     'BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE' val=21
>> >     'BPF_MAP_TYPE_QUEUE' val=22
>> >     'BPF_MAP_TYPE_STACK' val=23
>> >     'BPF_MAP_TYPE_SK_STORAGE' val=24
>> >     'BPF_MAP_TYPE_DEVMAP_HASH' val=25
>> >     'BPF_MAP_TYPE_STRUCT_OPS' val=26
>> >     'BPF_MAP_TYPE_RINGBUF' val=27
>> >     'BPF_MAP_TYPE_INODE_STORAGE' val=28
>> >     'BPF_MAP_TYPE_TASK_STORAGE' val=29
>> >     'BPF_MAP_TYPE_BLOOM_FILTER' val=30
>> > [23] UNION '(anon)' size=8 vlen=1
>> >     'flow_keys' type_id=29 bits_offset=0
>> > [24] STRUCT 'bpf_flow_keys' size=56 vlen=13
>> >     'nhoff' type_id=8 bits_offset=0
>> >     'thoff' type_id=8 bits_offset=16
>> >     'addr_proto' type_id=8 bits_offset=32
>> >     'is_frag' type_id=3 bits_offset=48
>> >     'is_first_frag' type_id=3 bits_offset=56
>> >     'is_encap' type_id=3 bits_offset=64
>> >     'ip_proto' type_id=3 bits_offset=72
>> >     'n_proto' type_id=20 bits_offset=80
>> >     'sport' type_id=20 bits_offset=96
>> >     'dport' type_id=20 bits_offset=112
>> >     '(anon)' type_id=25 bits_offset=128
>> >     'flags' type_id=12 bits_offset=384
>> >     'flow_label' type_id=21 bits_offset=416
>> > [25] UNION '(anon)' size=32 vlen=2
>> >     '(anon)' type_id=26 bits_offset=0
>> >     '(anon)' type_id=27 bits_offset=0
>> > [26] STRUCT '(anon)' size=8 vlen=2
>> >     'ipv4_src' type_id=21 bits_offset=0
>> >     'ipv4_dst' type_id=21 bits_offset=32
>> > [27] STRUCT '(anon)' size=32 vlen=2
>> >     'ipv6_src' type_id=28 bits_offset=0
>> >     'ipv6_dst' type_id=28 bits_offset=128
>> > [28] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=4
>> > [29] PTR '(anon)' type_id=24
>> > [30] UNION '(anon)' size=8 vlen=1
>> >     'sk' type_id=32 bits_offset=0
>> > [31] STRUCT 'bpf_sock' size=80 vlen=14
>> >     'bound_dev_if' type_id=12 bits_offset=0
>> >     'family' type_id=12 bits_offset=32
>> >     'type' type_id=12 bits_offset=64
>> >     'protocol' type_id=12 bits_offset=96
>> >     'mark' type_id=12 bits_offset=128
>> >     'priority' type_id=12 bits_offset=160
>> >     'src_ip4' type_id=12 bits_offset=192
>> >     'src_ip6' type_id=28 bits_offset=224
>> >     'src_port' type_id=12 bits_offset=352
>> >     'dst_port' type_id=20 bits_offset=384
>> >     'dst_ip4' type_id=12 bits_offset=416
>> >     'dst_ip6' type_id=28 bits_offset=448
>> >     'state' type_id=12 bits_offset=576
>> >     'rx_queue_mapping' type_id=10 bits_offset=608
>> > [32] PTR '(anon)' type_id=31
>> > [33] STRUCT '__sk_buff' size=192 vlen=33
>> >     'len' type_id=12 bits_offset=0
>> >     'pkt_type' type_id=12 bits_offset=32
>> >     'mark' type_id=12 bits_offset=64
>> >     'queue_mapping' type_id=12 bits_offset=96
>> >     'protocol' type_id=12 bits_offset=128
>> >     'vlan_present' type_id=12 bits_offset=160
>> >     'vlan_tci' type_id=12 bits_offset=192
>> >     'vlan_proto' type_id=12 bits_offset=224
>> >     'priority' type_id=12 bits_offset=256
>> >     'ingress_ifindex' type_id=12 bits_offset=288
>> >     'ifindex' type_id=12 bits_offset=320
>> >     'tc_index' type_id=12 bits_offset=352
>> >     'cb' type_id=34 bits_offset=384
>> >     'hash' type_id=12 bits_offset=544
>> >     'tc_classid' type_id=12 bits_offset=576
>> >     'data' type_id=12 bits_offset=608
>> >     'data_end' type_id=12 bits_offset=640
>> >     'napi_id' type_id=12 bits_offset=672
>> >     'family' type_id=12 bits_offset=704
>> >     'remote_ip4' type_id=12 bits_offset=736
>> >     'local_ip4' type_id=12 bits_offset=768
>> >     'remote_ip6' type_id=28 bits_offset=800
>> >     'local_ip6' type_id=28 bits_offset=928
>> >     'remote_port' type_id=12 bits_offset=1056
>> >     'local_port' type_id=12 bits_offset=1088
>> >     'data_meta' type_id=12 bits_offset=1120
>> >     '(anon)' type_id=23 bits_offset=1152
>> >     'tstamp' type_id=15 bits_offset=1216
>> >     'wire_len' type_id=12 bits_offset=1280
>> >     'gso_segs' type_id=12 bits_offset=1312
>> >     '(anon)' type_id=30 bits_offset=1344
>> >     'gso_size' type_id=12 bits_offset=1408
>> >     'hwtstamp' type_id=15 bits_offset=1472
>> > [34] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=5
>> > [35] CONST '(anon)' type_id=33
>> > [36] PTR '(anon)' type_id=0
>> > [37] STRUCT '(anon)' size=24 vlen=3
>> >     'type' type_id=39 bits_offset=0
>> >     'key' type_id=40 bits_offset=64
>> >     'value' type_id=41 bits_offset=128
>> > [38] ARRAY '(anon)' type_id=9 index_type_id=16 nr_elems=1
>> > [39] PTR '(anon)' type_id=38
>> > [40] PTR '(anon)' type_id=12
>> > [41] PTR '(anon)' type_id=3
>> > [42] ARRAY '(anon)' type_id=19 index_type_id=16 nr_elems=18
>> > [43] CONST '(anon)' type_id=42
>> > [44] FUNC_PROTO '(anon)' ret_type_id=36 vlen=2
>> >     '(anon)' type_id=36
>> >     '(anon)' type_id=46
>> > [45] CONST '(anon)' type_id=0
>> > [46] PTR '(anon)' type_id=45
>> > [47] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>> >     'sk' type_id=48
>> > [48] PTR '(anon)' type_id=35
>> > [49] VAR '_license' type_id=43, linkage=static
>> > [50] VAR 'is_allow_list' type_id=5, linkage=global
>> > [51] VAR 'sd_restrictif' type_id=37, linkage=global
>> > [52] FUNC 'sd_restrictif_i' type_id=47 linkage=global
>> > [53] FUNC 'sd_restrictif_e' type_id=47 linkage=global
>> > [54] FUNC 'restrict_network_interfaces_impl' type_id=47 linkage=static
>> > [55] DATASEC '.data' size=1 vlen=1
>> >     type_id=50 offset=0 size=1 (VAR 'is_allow_list')
>> > [56] DATASEC 'license' size=18 vlen=1
>> >     type_id=49 offset=0 size=18 (VAR '_license')
>> > [57] DATASEC '.maps' size=24 vlen=1
>> >     type_id=51 offset=0 size=24 (VAR 'sd_restrictif')
>> >
>> > File before being stripped using bpftool gen object:
>> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>> > btf dump file
>> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
>> > format raw
>> > [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>> > [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
>> > [3] TYPEDEF '__u8' type_id=2
>> > [4] CONST '(anon)' type_id=3
>> > [5] VOLATILE '(anon)' type_id=4
>> > [6] INT 'short int' size=2 bits_offset=0 nr_bits=16 encoding=SIGNED
>> > [7] INT 'short unsigned int' size=2 bits_offset=0 nr_bits=16 encoding=(none)
>> > [8] TYPEDEF '__u16' type_id=7
>> > [9] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
>> > [10] TYPEDEF '__s32' type_id=9
>> > [11] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
>> > [12] TYPEDEF '__u32' type_id=11
>> > [13] INT 'long long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
>> > [14] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64
>> > encoding=(none)
>> > [15] TYPEDEF '__u64' type_id=14
>> > [16] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
>> > [17] INT 'long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
>> > [18] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>> > [19] CONST '(anon)' type_id=18
>> > [20] TYPEDEF '__be16' type_id=8
>> > [21] TYPEDEF '__be32' type_id=12
>> > [22] ENUM 'bpf_map_type' encoding=UNSIGNED size=4 vlen=31
>> >     'BPF_MAP_TYPE_UNSPEC' val=0
>> >     'BPF_MAP_TYPE_HASH' val=1
>> >     'BPF_MAP_TYPE_ARRAY' val=2
>> >     'BPF_MAP_TYPE_PROG_ARRAY' val=3
>> >     'BPF_MAP_TYPE_PERF_EVENT_ARRAY' val=4
>> >     'BPF_MAP_TYPE_PERCPU_HASH' val=5
>> >     'BPF_MAP_TYPE_PERCPU_ARRAY' val=6
>> >     'BPF_MAP_TYPE_STACK_TRACE' val=7
>> >     'BPF_MAP_TYPE_CGROUP_ARRAY' val=8
>> >     'BPF_MAP_TYPE_LRU_HASH' val=9
>> >     'BPF_MAP_TYPE_LRU_PERCPU_HASH' val=10
>> >     'BPF_MAP_TYPE_LPM_TRIE' val=11
>> >     'BPF_MAP_TYPE_ARRAY_OF_MAPS' val=12
>> >     'BPF_MAP_TYPE_HASH_OF_MAPS' val=13
>> >     'BPF_MAP_TYPE_DEVMAP' val=14
>> >     'BPF_MAP_TYPE_SOCKMAP' val=15
>> >     'BPF_MAP_TYPE_CPUMAP' val=16
>> >     'BPF_MAP_TYPE_XSKMAP' val=17
>> >     'BPF_MAP_TYPE_SOCKHASH' val=18
>> >     'BPF_MAP_TYPE_CGROUP_STORAGE' val=19
>> >     'BPF_MAP_TYPE_REUSEPORT_SOCKARRAY' val=20
>> >     'BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE' val=21
>> >     'BPF_MAP_TYPE_QUEUE' val=22
>> >     'BPF_MAP_TYPE_STACK' val=23
>> >     'BPF_MAP_TYPE_SK_STORAGE' val=24
>> >     'BPF_MAP_TYPE_DEVMAP_HASH' val=25
>> >     'BPF_MAP_TYPE_STRUCT_OPS' val=26
>> >     'BPF_MAP_TYPE_RINGBUF' val=27
>> >     'BPF_MAP_TYPE_INODE_STORAGE' val=28
>> >     'BPF_MAP_TYPE_TASK_STORAGE' val=29
>> >     'BPF_MAP_TYPE_BLOOM_FILTER' val=30
>> > [23] UNION '(anon)' size=8 vlen=1
>> >     'flow_keys' type_id=29 bits_offset=0
>> > [24] STRUCT 'bpf_flow_keys' size=56 vlen=13
>> >     'nhoff' type_id=8 bits_offset=0
>> >     'thoff' type_id=8 bits_offset=16
>> >     'addr_proto' type_id=8 bits_offset=32
>> >     'is_frag' type_id=3 bits_offset=48
>> >     'is_first_frag' type_id=3 bits_offset=56
>> >     'is_encap' type_id=3 bits_offset=64
>> >     'ip_proto' type_id=3 bits_offset=72
>> >     'n_proto' type_id=20 bits_offset=80
>> >     'sport' type_id=20 bits_offset=96
>> >     'dport' type_id=20 bits_offset=112
>> >     '(anon)' type_id=25 bits_offset=128
>> >     'flags' type_id=12 bits_offset=384
>> >     'flow_label' type_id=21 bits_offset=416
>> > [25] UNION '(anon)' size=32 vlen=2
>> >     '(anon)' type_id=26 bits_offset=0
>> >     '(anon)' type_id=27 bits_offset=0
>> > [26] STRUCT '(anon)' size=8 vlen=2
>> >     'ipv4_src' type_id=21 bits_offset=0
>> >     'ipv4_dst' type_id=21 bits_offset=32
>> > [27] STRUCT '(anon)' size=32 vlen=2
>> >     'ipv6_src' type_id=28 bits_offset=0
>> >     'ipv6_dst' type_id=28 bits_offset=128
>> > [28] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=4
>> > [29] PTR '(anon)' type_id=24
>> > [30] UNION '(anon)' size=8 vlen=1
>> >     'sk' type_id=32 bits_offset=0
>> > [31] STRUCT 'bpf_sock' size=80 vlen=14
>> >     'bound_dev_if' type_id=12 bits_offset=0
>> >     'family' type_id=12 bits_offset=32
>> >     'type' type_id=12 bits_offset=64
>> >     'protocol' type_id=12 bits_offset=96
>> >     'mark' type_id=12 bits_offset=128
>> >     'priority' type_id=12 bits_offset=160
>> >     'src_ip4' type_id=12 bits_offset=192
>> >     'src_ip6' type_id=28 bits_offset=224
>> >     'src_port' type_id=12 bits_offset=352
>> >     'dst_port' type_id=20 bits_offset=384
>> >     'dst_ip4' type_id=12 bits_offset=416
>> >     'dst_ip6' type_id=28 bits_offset=448
>> >     'state' type_id=12 bits_offset=576
>> >     'rx_queue_mapping' type_id=10 bits_offset=608
>> > [32] PTR '(anon)' type_id=31
>> > [33] STRUCT '__sk_buff' size=192 vlen=33
>> >     'len' type_id=12 bits_offset=0
>> >     'pkt_type' type_id=12 bits_offset=32
>> >     'mark' type_id=12 bits_offset=64
>> >     'queue_mapping' type_id=12 bits_offset=96
>> >     'protocol' type_id=12 bits_offset=128
>> >     'vlan_present' type_id=12 bits_offset=160
>> >     'vlan_tci' type_id=12 bits_offset=192
>> >     'vlan_proto' type_id=12 bits_offset=224
>> >     'priority' type_id=12 bits_offset=256
>> >     'ingress_ifindex' type_id=12 bits_offset=288
>> >     'ifindex' type_id=12 bits_offset=320
>> >     'tc_index' type_id=12 bits_offset=352
>> >     'cb' type_id=34 bits_offset=384
>> >     'hash' type_id=12 bits_offset=544
>> >     'tc_classid' type_id=12 bits_offset=576
>> >     'data' type_id=12 bits_offset=608
>> >     'data_end' type_id=12 bits_offset=640
>> >     'napi_id' type_id=12 bits_offset=672
>> >     'family' type_id=12 bits_offset=704
>> >     'remote_ip4' type_id=12 bits_offset=736
>> >     'local_ip4' type_id=12 bits_offset=768
>> >     'remote_ip6' type_id=28 bits_offset=800
>> >     'local_ip6' type_id=28 bits_offset=928
>> >     'remote_port' type_id=12 bits_offset=1056
>> >     'local_port' type_id=12 bits_offset=1088
>> >     'data_meta' type_id=12 bits_offset=1120
>> >     '(anon)' type_id=23 bits_offset=1152
>> >     'tstamp' type_id=15 bits_offset=1216
>> >     'wire_len' type_id=12 bits_offset=1280
>> >     'gso_segs' type_id=12 bits_offset=1312
>> >     '(anon)' type_id=30 bits_offset=1344
>> >     'gso_size' type_id=12 bits_offset=1408
>> >     'hwtstamp' type_id=15 bits_offset=1472
>> > [34] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=5
>> > [35] CONST '(anon)' type_id=33
>> > [36] PTR '(anon)' type_id=0
>> > [37] STRUCT '(anon)' size=24 vlen=3
>> >     'type' type_id=39 bits_offset=0
>> >     'key' type_id=40 bits_offset=64
>> >     'value' type_id=41 bits_offset=128
>> > [38] ARRAY '(anon)' type_id=9 index_type_id=16 nr_elems=1
>> > [39] PTR '(anon)' type_id=38
>> > [40] PTR '(anon)' type_id=12
>> > [41] PTR '(anon)' type_id=3
>> > [42] ARRAY '(anon)' type_id=19 index_type_id=16 nr_elems=18
>> > [43] CONST '(anon)' type_id=42
>> > [44] FUNC_PROTO '(anon)' ret_type_id=36 vlen=2
>> >     '(anon)' type_id=36
>> >     '(anon)' type_id=46
>> > [45] CONST '(anon)' type_id=0
>> > [46] PTR '(anon)' type_id=45
>> > [47] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>> >     'sk' type_id=48
>> > [48] PTR '(anon)' type_id=35
>> > [49] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>> >     'sk' type_id=48
>> > [50] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>> >     'sk' type_id=48
>> > [51] VAR '_license' type_id=43, linkage=static
>> > [52] VAR 'is_allow_list' type_id=5, linkage=global
>> > [53] VAR 'sd_restrictif' type_id=37, linkage=global
>> > [54] FUNC 'bpf_map_lookup_elem' type_id=44 linkage=global
>> > [55] FUNC 'sd_restrictif_i' type_id=47 linkage=global
>> > [56] FUNC 'sd_restrictif_e' type_id=49 linkage=global
>> > [57] FUNC 'restrict_network_interfaces_impl' type_id=50 linkage=static
>> > [58] DATASEC 'license' size=0 vlen=1
>> >     type_id=51 offset=0 size=18 (VAR '_license')
>> > [59] DATASEC '.maps' size=0 vlen=1
>> >     type_id=53 offset=0 size=24 (VAR 'sd_restrictif')
>> > [60] DATASEC '.data' size=0 vlen=1
>> >     type_id=52 offset=0 size=1 (VAR 'is_allow_list')
>> >
>> >>
>> >> >> GCC is wrong, clearly. This function is global ([0]) and libbpf
>> >> >> expects it to be marked as such in BTF.
>> >> >>
>> >> >>
>> > https://github.com/systemd/systemd/blob/main/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.c#L42-L50
>> >> >>
>> >> >>
>> >> >>> GCC:
>> >> >>>
>> >> >>> [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>> >> >>> [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
>> >> >>> [3] TYPEDEF '__u8' type_id=2
>> >> >>> [4] CONST '(anon)' type_id=3
>> >> >>
>> >> >> [...]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-07-09 20:20             ` Jose E. Marchesi
@ 2022-07-09 20:32               ` James Hilliard
  2022-07-09 20:39                 ` James Hilliard
  0 siblings, 1 reply; 38+ messages in thread
From: James Hilliard @ 2022-07-09 20:32 UTC (permalink / raw)
  To: Jose E. Marchesi; +Cc: Andrii Nakryiko, bpf, david.faust

On Sat, Jul 9, 2022 at 2:21 PM Jose E. Marchesi
<jose.marchesi@oracle.com> wrote:
>
>
> > On Sat, Jul 9, 2022 at 11:24 AM Jose E. Marchesi
> > <jose.marchesi@oracle.com> wrote:
> >>
> >>
> >> > On Fri, Jul 8, 2022 at 12:33 PM Jose E. Marchesi
> >> > <jose.marchesi@oracle.com> wrote:
> >> >>
> >> >>
> >> >> >> On Wed, Jul 6, 2022 at 10:13 AM James Hilliard
> >> >> >> <james.hilliard1@gmail.com> wrote:
> >> >> >>>
> >> >> >>> Note I'm testing with the following patches:
> >> >> >>> https://lore.kernel.org/bpf/20220706111839.1247911-1-james.hilliard1@gmail.com/
> >> >> >>> https://lore.kernel.org/bpf/20220706140623.2917858-1-james.hilliard1@gmail.com/
> >> >> >>>
> >> >> >>> It would appear there's some compatibility issues with bpftool gen and
> >> >> >>> GCC, not sure what side though is wrong here:
> >> >> >>> /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> >> >> >>> gen object src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> >> >> >>> src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
> >> >> >>> libbpf: failed to find BTF info for global/extern symbol 'sd_restrictif_i'
> >> >> >>> Error: failed to link
> >> >> >>> 'src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o':
> >> >> >>> Unknown error -2 (-2)
> >> >> >>>
> >> >> >>> Relevant difference seems to be this:
> >> >> >>> GCC:
> >> >> >>> [55] FUNC 'sd_restrictif_i' type_id=47 linkage=static
> >> >> >>> Clang:
> >> >> >>> [27] FUNC 'sd_restrictif_i' type_id=26 linkage=global
> >> >> >
> >> >> > For functions GCC generates a BTF_KIND_FUNC entry, which has no linkage
> >> >> > information, or so we thought: I just looked at bpftool/btf.c and I
> >> >> > found the linkage info for function types is expected to be encoded in
> >> >> > the vlen field of BTF_KIND_FUNC entries (why not adding a btf_func
> >> >> > instead???) which is surprising to say the least.
> >> >> >
> >> >> > We are changing GCC to encode the linkage info in vlen for these types.
> >> >> > Thanks for reporting this.
> >> >>
> >> >> Patch sent to GCC upstream:
> >> >> https://gcc.gnu.org/pipermail/gcc-patches/2022-July/598090.html
> >> >
> >> > I applied that patch on top of GCC 12.1.0 and it appears to fix the
> >> > bpftool gen object bug.
> >> >
> >> > I am however now hitting a different error during skeleton generation:
> >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> >> > gen skeleton src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> >> > libbpf: elf: skipping unrecognized data section(9) .comment
> >> > libbpf: failed to alloc map 'restrict.bss' content buffer: -22
> >> > Error: failed to open BPF object file: Invalid argument
> >>
> >> What is the size of the .bss section in the object file?  Try with:
> >>
> >> $ size restrict-ifaces.bpf.o
> >
> > $ size output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> >    text       data        bss        dec        hex    filename
> >     386         25          0        411        19b
> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>
> Right, so the .bss section is empty.  I see a `const volatile unsigned
> char is_allow_list = 0;' in restrict-ifaces.bpf.c, but that goes to
> .data and not to .bss, as expected.
>
> If you build restrict-ifaces.bpf.o with LLVM, is the bss still empty?  I
> don't think the code in libbpf.c even checks for this eventuality...

LLVM version(which skeleton generation works with):
$ size restrict-ifaces.bpf.o
   text       data        bss        dec        hex    filename
    323         24          0        347        15b    restrict-ifaces.bpf.o

$ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
btf dump file restrict-ifaces.bpf.o format raw
[1] PTR '(anon)' type_id=3
[2] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
[3] ARRAY '(anon)' type_id=2 index_type_id=4 nr_elems=1
[4] INT '__ARRAY_SIZE_TYPE__' size=4 bits_offset=0 nr_bits=32 encoding=(none)
[5] PTR '(anon)' type_id=6
[6] TYPEDEF '__u32' type_id=7
[7] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
[8] PTR '(anon)' type_id=9
[9] TYPEDEF '__u8' type_id=10
[10] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=(none)
[11] STRUCT '(anon)' size=24 vlen=3
    'type' type_id=1 bits_offset=0
    'key' type_id=5 bits_offset=64
    'value' type_id=8 bits_offset=128
[12] VAR 'sd_restrictif' type_id=11, linkage=global
[13] PTR '(anon)' type_id=14
[14] CONST '(anon)' type_id=15
[15] STRUCT '__sk_buff' size=192 vlen=33
    'len' type_id=6 bits_offset=0
    'pkt_type' type_id=6 bits_offset=32
    'mark' type_id=6 bits_offset=64
    'queue_mapping' type_id=6 bits_offset=96
    'protocol' type_id=6 bits_offset=128
    'vlan_present' type_id=6 bits_offset=160
    'vlan_tci' type_id=6 bits_offset=192
    'vlan_proto' type_id=6 bits_offset=224
    'priority' type_id=6 bits_offset=256
    'ingress_ifindex' type_id=6 bits_offset=288
    'ifindex' type_id=6 bits_offset=320
    'tc_index' type_id=6 bits_offset=352
    'cb' type_id=16 bits_offset=384
    'hash' type_id=6 bits_offset=544
    'tc_classid' type_id=6 bits_offset=576
    'data' type_id=6 bits_offset=608
    'data_end' type_id=6 bits_offset=640
    'napi_id' type_id=6 bits_offset=672
    'family' type_id=6 bits_offset=704
    'remote_ip4' type_id=6 bits_offset=736
    'local_ip4' type_id=6 bits_offset=768
    'remote_ip6' type_id=17 bits_offset=800
    'local_ip6' type_id=17 bits_offset=928
    'remote_port' type_id=6 bits_offset=1056
    'local_port' type_id=6 bits_offset=1088
    'data_meta' type_id=6 bits_offset=1120
    '(anon)' type_id=18 bits_offset=1152
    'tstamp' type_id=20 bits_offset=1216
    'wire_len' type_id=6 bits_offset=1280
    'gso_segs' type_id=6 bits_offset=1312
    '(anon)' type_id=22 bits_offset=1344
    'gso_size' type_id=6 bits_offset=1408
    'hwtstamp' type_id=20 bits_offset=1472
[16] ARRAY '(anon)' type_id=6 index_type_id=4 nr_elems=5
[17] ARRAY '(anon)' type_id=6 index_type_id=4 nr_elems=4
[18] UNION '(anon)' size=8 vlen=1
    'flow_keys' type_id=19 bits_offset=0
[19] PTR '(anon)' type_id=34
[20] TYPEDEF '__u64' type_id=21
[21] INT 'unsigned long long' size=8 bits_offset=0 nr_bits=64 encoding=(none)
[22] UNION '(anon)' size=8 vlen=1
    'sk' type_id=23 bits_offset=0
[23] PTR '(anon)' type_id=35
[24] FUNC_PROTO '(anon)' ret_type_id=2 vlen=1
    'sk' type_id=13
[25] FUNC 'sd_restrictif_e' type_id=24 linkage=global
[26] FUNC 'sd_restrictif_i' type_id=24 linkage=global
[27] CONST '(anon)' type_id=28
[28] VOLATILE '(anon)' type_id=9
[29] VAR 'is_allow_list' type_id=27, linkage=global
[30] CONST '(anon)' type_id=31
[31] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=SIGNED
[32] ARRAY '(anon)' type_id=30 index_type_id=4 nr_elems=18
[33] VAR '_license' type_id=32, linkage=static
[34] FWD 'bpf_flow_keys' fwd_kind=struct
[35] FWD 'bpf_sock' fwd_kind=struct
[36] DATASEC '.rodata' size=1 vlen=1
    type_id=29 offset=0 size=1 (VAR 'is_allow_list')
[37] DATASEC 'license' size=18 vlen=1
    type_id=33 offset=0 size=18 (VAR '_license')
[38] DATASEC '.maps' size=24 vlen=1
    type_id=12 offset=0 size=24 (VAR 'sd_restrictif')

>
> >>
> >> Looking at libbpf.c, it seems to me that this may be due of trying to
> >> mmap 0 bytes in `bpf_object__init_internal_map':
> >>
> >>         map->mmaped = mmap(NULL, bpf_map_mmap_sz(map), PROT_READ | PROT_WRITE,
> >>                            MAP_SHARED | MAP_ANONYMOUS, -1, 0);
> >>         if (map->mmaped == MAP_FAILED) {
> >>                 err = -errno;
> >>                 map->mmaped = NULL;
> >>                 pr_warn("failed to alloc map '%s' content buffer: %d\n",
> >>                         map->name, err);
> >>                 zfree(&map->real_name);
> >>                 zfree(&map->name);
> >>                 return err;
> >>         }
> >>
> >> I see no check for zero sized sections in
> >> bpf_object__init_global_data_maps.
> >>
> >> Is maybe GCC failing to allocate stuff in BSS that is supposed to be
> >> there?
> >>
> >> > Stripped file passed to gen skeleton:
> >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> >> > btf dump file
> >> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> >> > format raw
> >> > [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> >> > [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
> >> > [3] TYPEDEF '__u8' type_id=2
> >> > [4] CONST '(anon)' type_id=3
> >> > [5] VOLATILE '(anon)' type_id=4
> >> > [6] INT 'short int' size=2 bits_offset=0 nr_bits=16 encoding=SIGNED
> >> > [7] INT 'short unsigned int' size=2 bits_offset=0 nr_bits=16 encoding=(none)
> >> > [8] TYPEDEF '__u16' type_id=7
> >> > [9] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
> >> > [10] TYPEDEF '__s32' type_id=9
> >> > [11] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
> >> > [12] TYPEDEF '__u32' type_id=11
> >> > [13] INT 'long long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
> >> > [14] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64
> >> > encoding=(none)
> >> > [15] TYPEDEF '__u64' type_id=14
> >> > [16] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
> >> > [17] INT 'long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
> >> > [18] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> >> > [19] CONST '(anon)' type_id=18
> >> > [20] TYPEDEF '__be16' type_id=8
> >> > [21] TYPEDEF '__be32' type_id=12
> >> > [22] ENUM 'bpf_map_type' encoding=UNSIGNED size=4 vlen=31
> >> >     'BPF_MAP_TYPE_UNSPEC' val=0
> >> >     'BPF_MAP_TYPE_HASH' val=1
> >> >     'BPF_MAP_TYPE_ARRAY' val=2
> >> >     'BPF_MAP_TYPE_PROG_ARRAY' val=3
> >> >     'BPF_MAP_TYPE_PERF_EVENT_ARRAY' val=4
> >> >     'BPF_MAP_TYPE_PERCPU_HASH' val=5
> >> >     'BPF_MAP_TYPE_PERCPU_ARRAY' val=6
> >> >     'BPF_MAP_TYPE_STACK_TRACE' val=7
> >> >     'BPF_MAP_TYPE_CGROUP_ARRAY' val=8
> >> >     'BPF_MAP_TYPE_LRU_HASH' val=9
> >> >     'BPF_MAP_TYPE_LRU_PERCPU_HASH' val=10
> >> >     'BPF_MAP_TYPE_LPM_TRIE' val=11
> >> >     'BPF_MAP_TYPE_ARRAY_OF_MAPS' val=12
> >> >     'BPF_MAP_TYPE_HASH_OF_MAPS' val=13
> >> >     'BPF_MAP_TYPE_DEVMAP' val=14
> >> >     'BPF_MAP_TYPE_SOCKMAP' val=15
> >> >     'BPF_MAP_TYPE_CPUMAP' val=16
> >> >     'BPF_MAP_TYPE_XSKMAP' val=17
> >> >     'BPF_MAP_TYPE_SOCKHASH' val=18
> >> >     'BPF_MAP_TYPE_CGROUP_STORAGE' val=19
> >> >     'BPF_MAP_TYPE_REUSEPORT_SOCKARRAY' val=20
> >> >     'BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE' val=21
> >> >     'BPF_MAP_TYPE_QUEUE' val=22
> >> >     'BPF_MAP_TYPE_STACK' val=23
> >> >     'BPF_MAP_TYPE_SK_STORAGE' val=24
> >> >     'BPF_MAP_TYPE_DEVMAP_HASH' val=25
> >> >     'BPF_MAP_TYPE_STRUCT_OPS' val=26
> >> >     'BPF_MAP_TYPE_RINGBUF' val=27
> >> >     'BPF_MAP_TYPE_INODE_STORAGE' val=28
> >> >     'BPF_MAP_TYPE_TASK_STORAGE' val=29
> >> >     'BPF_MAP_TYPE_BLOOM_FILTER' val=30
> >> > [23] UNION '(anon)' size=8 vlen=1
> >> >     'flow_keys' type_id=29 bits_offset=0
> >> > [24] STRUCT 'bpf_flow_keys' size=56 vlen=13
> >> >     'nhoff' type_id=8 bits_offset=0
> >> >     'thoff' type_id=8 bits_offset=16
> >> >     'addr_proto' type_id=8 bits_offset=32
> >> >     'is_frag' type_id=3 bits_offset=48
> >> >     'is_first_frag' type_id=3 bits_offset=56
> >> >     'is_encap' type_id=3 bits_offset=64
> >> >     'ip_proto' type_id=3 bits_offset=72
> >> >     'n_proto' type_id=20 bits_offset=80
> >> >     'sport' type_id=20 bits_offset=96
> >> >     'dport' type_id=20 bits_offset=112
> >> >     '(anon)' type_id=25 bits_offset=128
> >> >     'flags' type_id=12 bits_offset=384
> >> >     'flow_label' type_id=21 bits_offset=416
> >> > [25] UNION '(anon)' size=32 vlen=2
> >> >     '(anon)' type_id=26 bits_offset=0
> >> >     '(anon)' type_id=27 bits_offset=0
> >> > [26] STRUCT '(anon)' size=8 vlen=2
> >> >     'ipv4_src' type_id=21 bits_offset=0
> >> >     'ipv4_dst' type_id=21 bits_offset=32
> >> > [27] STRUCT '(anon)' size=32 vlen=2
> >> >     'ipv6_src' type_id=28 bits_offset=0
> >> >     'ipv6_dst' type_id=28 bits_offset=128
> >> > [28] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=4
> >> > [29] PTR '(anon)' type_id=24
> >> > [30] UNION '(anon)' size=8 vlen=1
> >> >     'sk' type_id=32 bits_offset=0
> >> > [31] STRUCT 'bpf_sock' size=80 vlen=14
> >> >     'bound_dev_if' type_id=12 bits_offset=0
> >> >     'family' type_id=12 bits_offset=32
> >> >     'type' type_id=12 bits_offset=64
> >> >     'protocol' type_id=12 bits_offset=96
> >> >     'mark' type_id=12 bits_offset=128
> >> >     'priority' type_id=12 bits_offset=160
> >> >     'src_ip4' type_id=12 bits_offset=192
> >> >     'src_ip6' type_id=28 bits_offset=224
> >> >     'src_port' type_id=12 bits_offset=352
> >> >     'dst_port' type_id=20 bits_offset=384
> >> >     'dst_ip4' type_id=12 bits_offset=416
> >> >     'dst_ip6' type_id=28 bits_offset=448
> >> >     'state' type_id=12 bits_offset=576
> >> >     'rx_queue_mapping' type_id=10 bits_offset=608
> >> > [32] PTR '(anon)' type_id=31
> >> > [33] STRUCT '__sk_buff' size=192 vlen=33
> >> >     'len' type_id=12 bits_offset=0
> >> >     'pkt_type' type_id=12 bits_offset=32
> >> >     'mark' type_id=12 bits_offset=64
> >> >     'queue_mapping' type_id=12 bits_offset=96
> >> >     'protocol' type_id=12 bits_offset=128
> >> >     'vlan_present' type_id=12 bits_offset=160
> >> >     'vlan_tci' type_id=12 bits_offset=192
> >> >     'vlan_proto' type_id=12 bits_offset=224
> >> >     'priority' type_id=12 bits_offset=256
> >> >     'ingress_ifindex' type_id=12 bits_offset=288
> >> >     'ifindex' type_id=12 bits_offset=320
> >> >     'tc_index' type_id=12 bits_offset=352
> >> >     'cb' type_id=34 bits_offset=384
> >> >     'hash' type_id=12 bits_offset=544
> >> >     'tc_classid' type_id=12 bits_offset=576
> >> >     'data' type_id=12 bits_offset=608
> >> >     'data_end' type_id=12 bits_offset=640
> >> >     'napi_id' type_id=12 bits_offset=672
> >> >     'family' type_id=12 bits_offset=704
> >> >     'remote_ip4' type_id=12 bits_offset=736
> >> >     'local_ip4' type_id=12 bits_offset=768
> >> >     'remote_ip6' type_id=28 bits_offset=800
> >> >     'local_ip6' type_id=28 bits_offset=928
> >> >     'remote_port' type_id=12 bits_offset=1056
> >> >     'local_port' type_id=12 bits_offset=1088
> >> >     'data_meta' type_id=12 bits_offset=1120
> >> >     '(anon)' type_id=23 bits_offset=1152
> >> >     'tstamp' type_id=15 bits_offset=1216
> >> >     'wire_len' type_id=12 bits_offset=1280
> >> >     'gso_segs' type_id=12 bits_offset=1312
> >> >     '(anon)' type_id=30 bits_offset=1344
> >> >     'gso_size' type_id=12 bits_offset=1408
> >> >     'hwtstamp' type_id=15 bits_offset=1472
> >> > [34] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=5
> >> > [35] CONST '(anon)' type_id=33
> >> > [36] PTR '(anon)' type_id=0
> >> > [37] STRUCT '(anon)' size=24 vlen=3
> >> >     'type' type_id=39 bits_offset=0
> >> >     'key' type_id=40 bits_offset=64
> >> >     'value' type_id=41 bits_offset=128
> >> > [38] ARRAY '(anon)' type_id=9 index_type_id=16 nr_elems=1
> >> > [39] PTR '(anon)' type_id=38
> >> > [40] PTR '(anon)' type_id=12
> >> > [41] PTR '(anon)' type_id=3
> >> > [42] ARRAY '(anon)' type_id=19 index_type_id=16 nr_elems=18
> >> > [43] CONST '(anon)' type_id=42
> >> > [44] FUNC_PROTO '(anon)' ret_type_id=36 vlen=2
> >> >     '(anon)' type_id=36
> >> >     '(anon)' type_id=46
> >> > [45] CONST '(anon)' type_id=0
> >> > [46] PTR '(anon)' type_id=45
> >> > [47] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
> >> >     'sk' type_id=48
> >> > [48] PTR '(anon)' type_id=35
> >> > [49] VAR '_license' type_id=43, linkage=static
> >> > [50] VAR 'is_allow_list' type_id=5, linkage=global
> >> > [51] VAR 'sd_restrictif' type_id=37, linkage=global
> >> > [52] FUNC 'sd_restrictif_i' type_id=47 linkage=global
> >> > [53] FUNC 'sd_restrictif_e' type_id=47 linkage=global
> >> > [54] FUNC 'restrict_network_interfaces_impl' type_id=47 linkage=static
> >> > [55] DATASEC '.data' size=1 vlen=1
> >> >     type_id=50 offset=0 size=1 (VAR 'is_allow_list')
> >> > [56] DATASEC 'license' size=18 vlen=1
> >> >     type_id=49 offset=0 size=18 (VAR '_license')
> >> > [57] DATASEC '.maps' size=24 vlen=1
> >> >     type_id=51 offset=0 size=24 (VAR 'sd_restrictif')
> >> >
> >> > File before being stripped using bpftool gen object:
> >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> >> > btf dump file
> >> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
> >> > format raw
> >> > [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> >> > [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
> >> > [3] TYPEDEF '__u8' type_id=2
> >> > [4] CONST '(anon)' type_id=3
> >> > [5] VOLATILE '(anon)' type_id=4
> >> > [6] INT 'short int' size=2 bits_offset=0 nr_bits=16 encoding=SIGNED
> >> > [7] INT 'short unsigned int' size=2 bits_offset=0 nr_bits=16 encoding=(none)
> >> > [8] TYPEDEF '__u16' type_id=7
> >> > [9] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
> >> > [10] TYPEDEF '__s32' type_id=9
> >> > [11] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
> >> > [12] TYPEDEF '__u32' type_id=11
> >> > [13] INT 'long long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
> >> > [14] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64
> >> > encoding=(none)
> >> > [15] TYPEDEF '__u64' type_id=14
> >> > [16] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
> >> > [17] INT 'long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
> >> > [18] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> >> > [19] CONST '(anon)' type_id=18
> >> > [20] TYPEDEF '__be16' type_id=8
> >> > [21] TYPEDEF '__be32' type_id=12
> >> > [22] ENUM 'bpf_map_type' encoding=UNSIGNED size=4 vlen=31
> >> >     'BPF_MAP_TYPE_UNSPEC' val=0
> >> >     'BPF_MAP_TYPE_HASH' val=1
> >> >     'BPF_MAP_TYPE_ARRAY' val=2
> >> >     'BPF_MAP_TYPE_PROG_ARRAY' val=3
> >> >     'BPF_MAP_TYPE_PERF_EVENT_ARRAY' val=4
> >> >     'BPF_MAP_TYPE_PERCPU_HASH' val=5
> >> >     'BPF_MAP_TYPE_PERCPU_ARRAY' val=6
> >> >     'BPF_MAP_TYPE_STACK_TRACE' val=7
> >> >     'BPF_MAP_TYPE_CGROUP_ARRAY' val=8
> >> >     'BPF_MAP_TYPE_LRU_HASH' val=9
> >> >     'BPF_MAP_TYPE_LRU_PERCPU_HASH' val=10
> >> >     'BPF_MAP_TYPE_LPM_TRIE' val=11
> >> >     'BPF_MAP_TYPE_ARRAY_OF_MAPS' val=12
> >> >     'BPF_MAP_TYPE_HASH_OF_MAPS' val=13
> >> >     'BPF_MAP_TYPE_DEVMAP' val=14
> >> >     'BPF_MAP_TYPE_SOCKMAP' val=15
> >> >     'BPF_MAP_TYPE_CPUMAP' val=16
> >> >     'BPF_MAP_TYPE_XSKMAP' val=17
> >> >     'BPF_MAP_TYPE_SOCKHASH' val=18
> >> >     'BPF_MAP_TYPE_CGROUP_STORAGE' val=19
> >> >     'BPF_MAP_TYPE_REUSEPORT_SOCKARRAY' val=20
> >> >     'BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE' val=21
> >> >     'BPF_MAP_TYPE_QUEUE' val=22
> >> >     'BPF_MAP_TYPE_STACK' val=23
> >> >     'BPF_MAP_TYPE_SK_STORAGE' val=24
> >> >     'BPF_MAP_TYPE_DEVMAP_HASH' val=25
> >> >     'BPF_MAP_TYPE_STRUCT_OPS' val=26
> >> >     'BPF_MAP_TYPE_RINGBUF' val=27
> >> >     'BPF_MAP_TYPE_INODE_STORAGE' val=28
> >> >     'BPF_MAP_TYPE_TASK_STORAGE' val=29
> >> >     'BPF_MAP_TYPE_BLOOM_FILTER' val=30
> >> > [23] UNION '(anon)' size=8 vlen=1
> >> >     'flow_keys' type_id=29 bits_offset=0
> >> > [24] STRUCT 'bpf_flow_keys' size=56 vlen=13
> >> >     'nhoff' type_id=8 bits_offset=0
> >> >     'thoff' type_id=8 bits_offset=16
> >> >     'addr_proto' type_id=8 bits_offset=32
> >> >     'is_frag' type_id=3 bits_offset=48
> >> >     'is_first_frag' type_id=3 bits_offset=56
> >> >     'is_encap' type_id=3 bits_offset=64
> >> >     'ip_proto' type_id=3 bits_offset=72
> >> >     'n_proto' type_id=20 bits_offset=80
> >> >     'sport' type_id=20 bits_offset=96
> >> >     'dport' type_id=20 bits_offset=112
> >> >     '(anon)' type_id=25 bits_offset=128
> >> >     'flags' type_id=12 bits_offset=384
> >> >     'flow_label' type_id=21 bits_offset=416
> >> > [25] UNION '(anon)' size=32 vlen=2
> >> >     '(anon)' type_id=26 bits_offset=0
> >> >     '(anon)' type_id=27 bits_offset=0
> >> > [26] STRUCT '(anon)' size=8 vlen=2
> >> >     'ipv4_src' type_id=21 bits_offset=0
> >> >     'ipv4_dst' type_id=21 bits_offset=32
> >> > [27] STRUCT '(anon)' size=32 vlen=2
> >> >     'ipv6_src' type_id=28 bits_offset=0
> >> >     'ipv6_dst' type_id=28 bits_offset=128
> >> > [28] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=4
> >> > [29] PTR '(anon)' type_id=24
> >> > [30] UNION '(anon)' size=8 vlen=1
> >> >     'sk' type_id=32 bits_offset=0
> >> > [31] STRUCT 'bpf_sock' size=80 vlen=14
> >> >     'bound_dev_if' type_id=12 bits_offset=0
> >> >     'family' type_id=12 bits_offset=32
> >> >     'type' type_id=12 bits_offset=64
> >> >     'protocol' type_id=12 bits_offset=96
> >> >     'mark' type_id=12 bits_offset=128
> >> >     'priority' type_id=12 bits_offset=160
> >> >     'src_ip4' type_id=12 bits_offset=192
> >> >     'src_ip6' type_id=28 bits_offset=224
> >> >     'src_port' type_id=12 bits_offset=352
> >> >     'dst_port' type_id=20 bits_offset=384
> >> >     'dst_ip4' type_id=12 bits_offset=416
> >> >     'dst_ip6' type_id=28 bits_offset=448
> >> >     'state' type_id=12 bits_offset=576
> >> >     'rx_queue_mapping' type_id=10 bits_offset=608
> >> > [32] PTR '(anon)' type_id=31
> >> > [33] STRUCT '__sk_buff' size=192 vlen=33
> >> >     'len' type_id=12 bits_offset=0
> >> >     'pkt_type' type_id=12 bits_offset=32
> >> >     'mark' type_id=12 bits_offset=64
> >> >     'queue_mapping' type_id=12 bits_offset=96
> >> >     'protocol' type_id=12 bits_offset=128
> >> >     'vlan_present' type_id=12 bits_offset=160
> >> >     'vlan_tci' type_id=12 bits_offset=192
> >> >     'vlan_proto' type_id=12 bits_offset=224
> >> >     'priority' type_id=12 bits_offset=256
> >> >     'ingress_ifindex' type_id=12 bits_offset=288
> >> >     'ifindex' type_id=12 bits_offset=320
> >> >     'tc_index' type_id=12 bits_offset=352
> >> >     'cb' type_id=34 bits_offset=384
> >> >     'hash' type_id=12 bits_offset=544
> >> >     'tc_classid' type_id=12 bits_offset=576
> >> >     'data' type_id=12 bits_offset=608
> >> >     'data_end' type_id=12 bits_offset=640
> >> >     'napi_id' type_id=12 bits_offset=672
> >> >     'family' type_id=12 bits_offset=704
> >> >     'remote_ip4' type_id=12 bits_offset=736
> >> >     'local_ip4' type_id=12 bits_offset=768
> >> >     'remote_ip6' type_id=28 bits_offset=800
> >> >     'local_ip6' type_id=28 bits_offset=928
> >> >     'remote_port' type_id=12 bits_offset=1056
> >> >     'local_port' type_id=12 bits_offset=1088
> >> >     'data_meta' type_id=12 bits_offset=1120
> >> >     '(anon)' type_id=23 bits_offset=1152
> >> >     'tstamp' type_id=15 bits_offset=1216
> >> >     'wire_len' type_id=12 bits_offset=1280
> >> >     'gso_segs' type_id=12 bits_offset=1312
> >> >     '(anon)' type_id=30 bits_offset=1344
> >> >     'gso_size' type_id=12 bits_offset=1408
> >> >     'hwtstamp' type_id=15 bits_offset=1472
> >> > [34] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=5
> >> > [35] CONST '(anon)' type_id=33
> >> > [36] PTR '(anon)' type_id=0
> >> > [37] STRUCT '(anon)' size=24 vlen=3
> >> >     'type' type_id=39 bits_offset=0
> >> >     'key' type_id=40 bits_offset=64
> >> >     'value' type_id=41 bits_offset=128
> >> > [38] ARRAY '(anon)' type_id=9 index_type_id=16 nr_elems=1
> >> > [39] PTR '(anon)' type_id=38
> >> > [40] PTR '(anon)' type_id=12
> >> > [41] PTR '(anon)' type_id=3
> >> > [42] ARRAY '(anon)' type_id=19 index_type_id=16 nr_elems=18
> >> > [43] CONST '(anon)' type_id=42
> >> > [44] FUNC_PROTO '(anon)' ret_type_id=36 vlen=2
> >> >     '(anon)' type_id=36
> >> >     '(anon)' type_id=46
> >> > [45] CONST '(anon)' type_id=0
> >> > [46] PTR '(anon)' type_id=45
> >> > [47] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
> >> >     'sk' type_id=48
> >> > [48] PTR '(anon)' type_id=35
> >> > [49] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
> >> >     'sk' type_id=48
> >> > [50] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
> >> >     'sk' type_id=48
> >> > [51] VAR '_license' type_id=43, linkage=static
> >> > [52] VAR 'is_allow_list' type_id=5, linkage=global
> >> > [53] VAR 'sd_restrictif' type_id=37, linkage=global
> >> > [54] FUNC 'bpf_map_lookup_elem' type_id=44 linkage=global
> >> > [55] FUNC 'sd_restrictif_i' type_id=47 linkage=global
> >> > [56] FUNC 'sd_restrictif_e' type_id=49 linkage=global
> >> > [57] FUNC 'restrict_network_interfaces_impl' type_id=50 linkage=static
> >> > [58] DATASEC 'license' size=0 vlen=1
> >> >     type_id=51 offset=0 size=18 (VAR '_license')
> >> > [59] DATASEC '.maps' size=0 vlen=1
> >> >     type_id=53 offset=0 size=24 (VAR 'sd_restrictif')
> >> > [60] DATASEC '.data' size=0 vlen=1
> >> >     type_id=52 offset=0 size=1 (VAR 'is_allow_list')
> >> >
> >> >>
> >> >> >> GCC is wrong, clearly. This function is global ([0]) and libbpf
> >> >> >> expects it to be marked as such in BTF.
> >> >> >>
> >> >> >>
> >> > https://github.com/systemd/systemd/blob/main/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.c#L42-L50
> >> >> >>
> >> >> >>
> >> >> >>> GCC:
> >> >> >>>
> >> >> >>> [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> >> >> >>> [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
> >> >> >>> [3] TYPEDEF '__u8' type_id=2
> >> >> >>> [4] CONST '(anon)' type_id=3
> >> >> >>
> >> >> >> [...]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-07-09 20:32               ` James Hilliard
@ 2022-07-09 20:39                 ` James Hilliard
  2022-07-09 22:41                   ` Jose E. Marchesi
  0 siblings, 1 reply; 38+ messages in thread
From: James Hilliard @ 2022-07-09 20:39 UTC (permalink / raw)
  To: Jose E. Marchesi; +Cc: Andrii Nakryiko, bpf, david.faust

On Sat, Jul 9, 2022 at 2:32 PM James Hilliard <james.hilliard1@gmail.com> wrote:
>
> On Sat, Jul 9, 2022 at 2:21 PM Jose E. Marchesi
> <jose.marchesi@oracle.com> wrote:
> >
> >
> > > On Sat, Jul 9, 2022 at 11:24 AM Jose E. Marchesi
> > > <jose.marchesi@oracle.com> wrote:
> > >>
> > >>
> > >> > On Fri, Jul 8, 2022 at 12:33 PM Jose E. Marchesi
> > >> > <jose.marchesi@oracle.com> wrote:
> > >> >>
> > >> >>
> > >> >> >> On Wed, Jul 6, 2022 at 10:13 AM James Hilliard
> > >> >> >> <james.hilliard1@gmail.com> wrote:
> > >> >> >>>
> > >> >> >>> Note I'm testing with the following patches:
> > >> >> >>> https://lore.kernel.org/bpf/20220706111839.1247911-1-james.hilliard1@gmail.com/
> > >> >> >>> https://lore.kernel.org/bpf/20220706140623.2917858-1-james.hilliard1@gmail.com/
> > >> >> >>>
> > >> >> >>> It would appear there's some compatibility issues with bpftool gen and
> > >> >> >>> GCC, not sure what side though is wrong here:
> > >> >> >>> /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> > >> >> >>> gen object src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> > >> >> >>> src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
> > >> >> >>> libbpf: failed to find BTF info for global/extern symbol 'sd_restrictif_i'
> > >> >> >>> Error: failed to link
> > >> >> >>> 'src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o':
> > >> >> >>> Unknown error -2 (-2)
> > >> >> >>>
> > >> >> >>> Relevant difference seems to be this:
> > >> >> >>> GCC:
> > >> >> >>> [55] FUNC 'sd_restrictif_i' type_id=47 linkage=static
> > >> >> >>> Clang:
> > >> >> >>> [27] FUNC 'sd_restrictif_i' type_id=26 linkage=global
> > >> >> >
> > >> >> > For functions GCC generates a BTF_KIND_FUNC entry, which has no linkage
> > >> >> > information, or so we thought: I just looked at bpftool/btf.c and I
> > >> >> > found the linkage info for function types is expected to be encoded in
> > >> >> > the vlen field of BTF_KIND_FUNC entries (why not adding a btf_func
> > >> >> > instead???) which is surprising to say the least.
> > >> >> >
> > >> >> > We are changing GCC to encode the linkage info in vlen for these types.
> > >> >> > Thanks for reporting this.
> > >> >>
> > >> >> Patch sent to GCC upstream:
> > >> >> https://gcc.gnu.org/pipermail/gcc-patches/2022-July/598090.html
> > >> >
> > >> > I applied that patch on top of GCC 12.1.0 and it appears to fix the
> > >> > bpftool gen object bug.
> > >> >
> > >> > I am however now hitting a different error during skeleton generation:
> > >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> > >> > gen skeleton src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> > >> > libbpf: elf: skipping unrecognized data section(9) .comment
> > >> > libbpf: failed to alloc map 'restrict.bss' content buffer: -22
> > >> > Error: failed to open BPF object file: Invalid argument
> > >>
> > >> What is the size of the .bss section in the object file?  Try with:
> > >>
> > >> $ size restrict-ifaces.bpf.o
> > >
> > > $ size output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> > >    text       data        bss        dec        hex    filename
> > >     386         25          0        411        19b
> > > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> >
> > Right, so the .bss section is empty.  I see a `const volatile unsigned
> > char is_allow_list = 0;' in restrict-ifaces.bpf.c, but that goes to
> > .data and not to .bss, as expected.
> >
> > If you build restrict-ifaces.bpf.o with LLVM, is the bss still empty?  I
> > don't think the code in libbpf.c even checks for this eventuality...
>
> LLVM version(which skeleton generation works with):
> $ size restrict-ifaces.bpf.o
>    text       data        bss        dec        hex    filename
>     323         24          0        347        15b    restrict-ifaces.bpf.o
>
> $ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> btf dump file restrict-ifaces.bpf.o format raw
> [1] PTR '(anon)' type_id=3
> [2] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
> [3] ARRAY '(anon)' type_id=2 index_type_id=4 nr_elems=1
> [4] INT '__ARRAY_SIZE_TYPE__' size=4 bits_offset=0 nr_bits=32 encoding=(none)
> [5] PTR '(anon)' type_id=6
> [6] TYPEDEF '__u32' type_id=7
> [7] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
> [8] PTR '(anon)' type_id=9
> [9] TYPEDEF '__u8' type_id=10
> [10] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=(none)
> [11] STRUCT '(anon)' size=24 vlen=3
>     'type' type_id=1 bits_offset=0
>     'key' type_id=5 bits_offset=64
>     'value' type_id=8 bits_offset=128
> [12] VAR 'sd_restrictif' type_id=11, linkage=global
> [13] PTR '(anon)' type_id=14
> [14] CONST '(anon)' type_id=15
> [15] STRUCT '__sk_buff' size=192 vlen=33
>     'len' type_id=6 bits_offset=0
>     'pkt_type' type_id=6 bits_offset=32
>     'mark' type_id=6 bits_offset=64
>     'queue_mapping' type_id=6 bits_offset=96
>     'protocol' type_id=6 bits_offset=128
>     'vlan_present' type_id=6 bits_offset=160
>     'vlan_tci' type_id=6 bits_offset=192
>     'vlan_proto' type_id=6 bits_offset=224
>     'priority' type_id=6 bits_offset=256
>     'ingress_ifindex' type_id=6 bits_offset=288
>     'ifindex' type_id=6 bits_offset=320
>     'tc_index' type_id=6 bits_offset=352
>     'cb' type_id=16 bits_offset=384
>     'hash' type_id=6 bits_offset=544
>     'tc_classid' type_id=6 bits_offset=576
>     'data' type_id=6 bits_offset=608
>     'data_end' type_id=6 bits_offset=640
>     'napi_id' type_id=6 bits_offset=672
>     'family' type_id=6 bits_offset=704
>     'remote_ip4' type_id=6 bits_offset=736
>     'local_ip4' type_id=6 bits_offset=768
>     'remote_ip6' type_id=17 bits_offset=800
>     'local_ip6' type_id=17 bits_offset=928
>     'remote_port' type_id=6 bits_offset=1056
>     'local_port' type_id=6 bits_offset=1088
>     'data_meta' type_id=6 bits_offset=1120
>     '(anon)' type_id=18 bits_offset=1152
>     'tstamp' type_id=20 bits_offset=1216
>     'wire_len' type_id=6 bits_offset=1280
>     'gso_segs' type_id=6 bits_offset=1312
>     '(anon)' type_id=22 bits_offset=1344
>     'gso_size' type_id=6 bits_offset=1408
>     'hwtstamp' type_id=20 bits_offset=1472
> [16] ARRAY '(anon)' type_id=6 index_type_id=4 nr_elems=5
> [17] ARRAY '(anon)' type_id=6 index_type_id=4 nr_elems=4
> [18] UNION '(anon)' size=8 vlen=1
>     'flow_keys' type_id=19 bits_offset=0
> [19] PTR '(anon)' type_id=34
> [20] TYPEDEF '__u64' type_id=21
> [21] INT 'unsigned long long' size=8 bits_offset=0 nr_bits=64 encoding=(none)
> [22] UNION '(anon)' size=8 vlen=1
>     'sk' type_id=23 bits_offset=0
> [23] PTR '(anon)' type_id=35
> [24] FUNC_PROTO '(anon)' ret_type_id=2 vlen=1
>     'sk' type_id=13
> [25] FUNC 'sd_restrictif_e' type_id=24 linkage=global
> [26] FUNC 'sd_restrictif_i' type_id=24 linkage=global
> [27] CONST '(anon)' type_id=28
> [28] VOLATILE '(anon)' type_id=9
> [29] VAR 'is_allow_list' type_id=27, linkage=global
> [30] CONST '(anon)' type_id=31
> [31] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=SIGNED
> [32] ARRAY '(anon)' type_id=30 index_type_id=4 nr_elems=18
> [33] VAR '_license' type_id=32, linkage=static
> [34] FWD 'bpf_flow_keys' fwd_kind=struct
> [35] FWD 'bpf_sock' fwd_kind=struct
> [36] DATASEC '.rodata' size=1 vlen=1
>     type_id=29 offset=0 size=1 (VAR 'is_allow_list')
> [37] DATASEC 'license' size=18 vlen=1
>     type_id=33 offset=0 size=18 (VAR '_license')
> [38] DATASEC '.maps' size=24 vlen=1
>     type_id=12 offset=0 size=24 (VAR 'sd_restrictif')
>

Skeleton generation debug output for GCC(failing) and LLVM(working)
which may be helpful:

GCC:
$ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
--debug gen skeleton
output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
libbpf: loading object 'restrict_ifaces_bpf' from buffer
libbpf: elf: section(2) .symtab, size 336, link 1, flags 0, type=2
libbpf: elf: section(3) .data, size 1, link 0, flags 3, type=1
libbpf: elf: section(4) .bss, size 0, link 0, flags 3, type=8
libbpf: elf: section(5) cgroup_skb/egress, size 184, link 0, flags 6, type=1
libbpf: sec 'cgroup_skb/egress': found program 'sd_restrictif_e' at
insn offset 0 (0 bytes), code size 23 insns (184 bytes)
libbpf: elf: section(6) cgroup_skb/ingress, size 184, link 0, flags 6, type=1
libbpf: sec 'cgroup_skb/ingress': found program 'sd_restrictif_i' at
insn offset 0 (0 bytes), code size 23 insns (184 bytes)
libbpf: elf: section(7) license, size 18, link 0, flags 2, type=1
libbpf: license of restrict_ifaces_bpf is LGPL-2.1-or-later
libbpf: elf: section(8) .maps, size 24, link 0, flags 3, type=1
libbpf: elf: section(9) .comment, size 49, link 0, flags 30, type=1
libbpf: elf: skipping unrecognized data section(9) .comment
libbpf: elf: section(10) .relcgroup_skb/egress, size 32, link 2, flags
40, type=9
libbpf: elf: section(11) .relcgroup_skb/ingress, size 32, link 2,
flags 40, type=9
libbpf: elf: section(12) .BTF, size 3606, link 0, flags 0, type=1
libbpf: looking for externs among 14 symbols...
libbpf: collected 0 externs total
libbpf: map 'sd_restrictif': at sec_idx 8, offset 0.
libbpf: map 'sd_restrictif': found type = 1.
libbpf: map 'sd_restrictif': found key [12], sz = 4.
libbpf: map 'sd_restrictif': found value [3], sz = 1.
libbpf: map 'restrict.data' (global data): at sec_idx 3, offset 0, flags 400.
libbpf: map 1 is "restrict.data"
libbpf: map 'restrict.bss' (global data): at sec_idx 4, offset 0, flags 400.
libbpf: failed to alloc map 'restrict.bss' content buffer: -22
Error: failed to open BPF object file: Invalid argument

LLVM:
$ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
--debug gen skeleton restrict-ifaces.bpf.o
libbpf: loading object 'restrict_ifaces_bpf' from buffer
libbpf: elf: section(2) .symtab, size 384, link 1, flags 0, type=2
libbpf: elf: section(3) cgroup_skb/egress, size 152, link 0, flags 6, type=1
libbpf: sec 'cgroup_skb/egress': found program 'sd_restrictif_e' at
insn offset 0 (0 bytes), code size 19 insns (152 bytes)
libbpf: elf: section(4) cgroup_skb/ingress, size 152, link 0, flags 6, type=1
libbpf: sec 'cgroup_skb/ingress': found program 'sd_restrictif_i' at
insn offset 0 (0 bytes), code size 19 insns (152 bytes)
libbpf: elf: section(5) .rodata, size 1, link 0, flags 2, type=1
libbpf: elf: section(6) license, size 18, link 0, flags 2, type=1
libbpf: license of restrict_ifaces_bpf is LGPL-2.1-or-later
libbpf: elf: section(7) .maps, size 24, link 0, flags 3, type=1
libbpf: elf: section(8) .relcgroup_skb/egress, size 32, link 2, flags 40, type=9
libbpf: elf: section(9) .relcgroup_skb/ingress, size 32, link 2, flags
40, type=9
libbpf: elf: section(10) .BTF, size 1988, link 0, flags 0, type=1
libbpf: elf: section(11) .BTF.ext, size 376, link 0, flags 0, type=1
libbpf: looking for externs among 16 symbols...
libbpf: collected 0 externs total
libbpf: map 'sd_restrictif': at sec_idx 7, offset 0.
libbpf: map 'sd_restrictif': found type = 1.
libbpf: map 'sd_restrictif': found key [6], sz = 4.
libbpf: map 'sd_restrictif': found value [9], sz = 1.
libbpf: map 'restrict.rodata' (global data): at sec_idx 5, offset 0, flags 480.
libbpf: map 1 is "restrict.rodata"
libbpf: sec '.relcgroup_skb/egress': collecting relocation for
section(3) 'cgroup_skb/egress'
libbpf: sec '.relcgroup_skb/egress': relo #0: insn #4 against 'sd_restrictif'
libbpf: prog 'sd_restrictif_e': found map 0 (sd_restrictif, sec 7, off
0) for insn #4
libbpf: sec '.relcgroup_skb/egress': relo #1: insn #7 against 'is_allow_list'
libbpf: prog 'sd_restrictif_e': found data map 1 (restrict.rodata, sec
5, off 0) for insn 7
libbpf: sec '.relcgroup_skb/ingress': collecting relocation for
section(4) 'cgroup_skb/ingress'
libbpf: sec '.relcgroup_skb/ingress': relo #0: insn #4 against 'sd_restrictif'
libbpf: prog 'sd_restrictif_i': found map 0 (sd_restrictif, sec 7, off
0) for insn #4
libbpf: sec '.relcgroup_skb/ingress': relo #1: insn #7 against 'is_allow_list'
libbpf: prog 'sd_restrictif_i': found data map 1 (restrict.rodata, sec
5, off 0) for insn 7

> >
> > >>
> > >> Looking at libbpf.c, it seems to me that this may be due of trying to
> > >> mmap 0 bytes in `bpf_object__init_internal_map':
> > >>
> > >>         map->mmaped = mmap(NULL, bpf_map_mmap_sz(map), PROT_READ | PROT_WRITE,
> > >>                            MAP_SHARED | MAP_ANONYMOUS, -1, 0);
> > >>         if (map->mmaped == MAP_FAILED) {
> > >>                 err = -errno;
> > >>                 map->mmaped = NULL;
> > >>                 pr_warn("failed to alloc map '%s' content buffer: %d\n",
> > >>                         map->name, err);
> > >>                 zfree(&map->real_name);
> > >>                 zfree(&map->name);
> > >>                 return err;
> > >>         }
> > >>
> > >> I see no check for zero sized sections in
> > >> bpf_object__init_global_data_maps.
> > >>
> > >> Is maybe GCC failing to allocate stuff in BSS that is supposed to be
> > >> there?
> > >>
> > >> > Stripped file passed to gen skeleton:
> > >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> > >> > btf dump file
> > >> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> > >> > format raw
> > >> > [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> > >> > [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
> > >> > [3] TYPEDEF '__u8' type_id=2
> > >> > [4] CONST '(anon)' type_id=3
> > >> > [5] VOLATILE '(anon)' type_id=4
> > >> > [6] INT 'short int' size=2 bits_offset=0 nr_bits=16 encoding=SIGNED
> > >> > [7] INT 'short unsigned int' size=2 bits_offset=0 nr_bits=16 encoding=(none)
> > >> > [8] TYPEDEF '__u16' type_id=7
> > >> > [9] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
> > >> > [10] TYPEDEF '__s32' type_id=9
> > >> > [11] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
> > >> > [12] TYPEDEF '__u32' type_id=11
> > >> > [13] INT 'long long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
> > >> > [14] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64
> > >> > encoding=(none)
> > >> > [15] TYPEDEF '__u64' type_id=14
> > >> > [16] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
> > >> > [17] INT 'long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
> > >> > [18] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> > >> > [19] CONST '(anon)' type_id=18
> > >> > [20] TYPEDEF '__be16' type_id=8
> > >> > [21] TYPEDEF '__be32' type_id=12
> > >> > [22] ENUM 'bpf_map_type' encoding=UNSIGNED size=4 vlen=31
> > >> >     'BPF_MAP_TYPE_UNSPEC' val=0
> > >> >     'BPF_MAP_TYPE_HASH' val=1
> > >> >     'BPF_MAP_TYPE_ARRAY' val=2
> > >> >     'BPF_MAP_TYPE_PROG_ARRAY' val=3
> > >> >     'BPF_MAP_TYPE_PERF_EVENT_ARRAY' val=4
> > >> >     'BPF_MAP_TYPE_PERCPU_HASH' val=5
> > >> >     'BPF_MAP_TYPE_PERCPU_ARRAY' val=6
> > >> >     'BPF_MAP_TYPE_STACK_TRACE' val=7
> > >> >     'BPF_MAP_TYPE_CGROUP_ARRAY' val=8
> > >> >     'BPF_MAP_TYPE_LRU_HASH' val=9
> > >> >     'BPF_MAP_TYPE_LRU_PERCPU_HASH' val=10
> > >> >     'BPF_MAP_TYPE_LPM_TRIE' val=11
> > >> >     'BPF_MAP_TYPE_ARRAY_OF_MAPS' val=12
> > >> >     'BPF_MAP_TYPE_HASH_OF_MAPS' val=13
> > >> >     'BPF_MAP_TYPE_DEVMAP' val=14
> > >> >     'BPF_MAP_TYPE_SOCKMAP' val=15
> > >> >     'BPF_MAP_TYPE_CPUMAP' val=16
> > >> >     'BPF_MAP_TYPE_XSKMAP' val=17
> > >> >     'BPF_MAP_TYPE_SOCKHASH' val=18
> > >> >     'BPF_MAP_TYPE_CGROUP_STORAGE' val=19
> > >> >     'BPF_MAP_TYPE_REUSEPORT_SOCKARRAY' val=20
> > >> >     'BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE' val=21
> > >> >     'BPF_MAP_TYPE_QUEUE' val=22
> > >> >     'BPF_MAP_TYPE_STACK' val=23
> > >> >     'BPF_MAP_TYPE_SK_STORAGE' val=24
> > >> >     'BPF_MAP_TYPE_DEVMAP_HASH' val=25
> > >> >     'BPF_MAP_TYPE_STRUCT_OPS' val=26
> > >> >     'BPF_MAP_TYPE_RINGBUF' val=27
> > >> >     'BPF_MAP_TYPE_INODE_STORAGE' val=28
> > >> >     'BPF_MAP_TYPE_TASK_STORAGE' val=29
> > >> >     'BPF_MAP_TYPE_BLOOM_FILTER' val=30
> > >> > [23] UNION '(anon)' size=8 vlen=1
> > >> >     'flow_keys' type_id=29 bits_offset=0
> > >> > [24] STRUCT 'bpf_flow_keys' size=56 vlen=13
> > >> >     'nhoff' type_id=8 bits_offset=0
> > >> >     'thoff' type_id=8 bits_offset=16
> > >> >     'addr_proto' type_id=8 bits_offset=32
> > >> >     'is_frag' type_id=3 bits_offset=48
> > >> >     'is_first_frag' type_id=3 bits_offset=56
> > >> >     'is_encap' type_id=3 bits_offset=64
> > >> >     'ip_proto' type_id=3 bits_offset=72
> > >> >     'n_proto' type_id=20 bits_offset=80
> > >> >     'sport' type_id=20 bits_offset=96
> > >> >     'dport' type_id=20 bits_offset=112
> > >> >     '(anon)' type_id=25 bits_offset=128
> > >> >     'flags' type_id=12 bits_offset=384
> > >> >     'flow_label' type_id=21 bits_offset=416
> > >> > [25] UNION '(anon)' size=32 vlen=2
> > >> >     '(anon)' type_id=26 bits_offset=0
> > >> >     '(anon)' type_id=27 bits_offset=0
> > >> > [26] STRUCT '(anon)' size=8 vlen=2
> > >> >     'ipv4_src' type_id=21 bits_offset=0
> > >> >     'ipv4_dst' type_id=21 bits_offset=32
> > >> > [27] STRUCT '(anon)' size=32 vlen=2
> > >> >     'ipv6_src' type_id=28 bits_offset=0
> > >> >     'ipv6_dst' type_id=28 bits_offset=128
> > >> > [28] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=4
> > >> > [29] PTR '(anon)' type_id=24
> > >> > [30] UNION '(anon)' size=8 vlen=1
> > >> >     'sk' type_id=32 bits_offset=0
> > >> > [31] STRUCT 'bpf_sock' size=80 vlen=14
> > >> >     'bound_dev_if' type_id=12 bits_offset=0
> > >> >     'family' type_id=12 bits_offset=32
> > >> >     'type' type_id=12 bits_offset=64
> > >> >     'protocol' type_id=12 bits_offset=96
> > >> >     'mark' type_id=12 bits_offset=128
> > >> >     'priority' type_id=12 bits_offset=160
> > >> >     'src_ip4' type_id=12 bits_offset=192
> > >> >     'src_ip6' type_id=28 bits_offset=224
> > >> >     'src_port' type_id=12 bits_offset=352
> > >> >     'dst_port' type_id=20 bits_offset=384
> > >> >     'dst_ip4' type_id=12 bits_offset=416
> > >> >     'dst_ip6' type_id=28 bits_offset=448
> > >> >     'state' type_id=12 bits_offset=576
> > >> >     'rx_queue_mapping' type_id=10 bits_offset=608
> > >> > [32] PTR '(anon)' type_id=31
> > >> > [33] STRUCT '__sk_buff' size=192 vlen=33
> > >> >     'len' type_id=12 bits_offset=0
> > >> >     'pkt_type' type_id=12 bits_offset=32
> > >> >     'mark' type_id=12 bits_offset=64
> > >> >     'queue_mapping' type_id=12 bits_offset=96
> > >> >     'protocol' type_id=12 bits_offset=128
> > >> >     'vlan_present' type_id=12 bits_offset=160
> > >> >     'vlan_tci' type_id=12 bits_offset=192
> > >> >     'vlan_proto' type_id=12 bits_offset=224
> > >> >     'priority' type_id=12 bits_offset=256
> > >> >     'ingress_ifindex' type_id=12 bits_offset=288
> > >> >     'ifindex' type_id=12 bits_offset=320
> > >> >     'tc_index' type_id=12 bits_offset=352
> > >> >     'cb' type_id=34 bits_offset=384
> > >> >     'hash' type_id=12 bits_offset=544
> > >> >     'tc_classid' type_id=12 bits_offset=576
> > >> >     'data' type_id=12 bits_offset=608
> > >> >     'data_end' type_id=12 bits_offset=640
> > >> >     'napi_id' type_id=12 bits_offset=672
> > >> >     'family' type_id=12 bits_offset=704
> > >> >     'remote_ip4' type_id=12 bits_offset=736
> > >> >     'local_ip4' type_id=12 bits_offset=768
> > >> >     'remote_ip6' type_id=28 bits_offset=800
> > >> >     'local_ip6' type_id=28 bits_offset=928
> > >> >     'remote_port' type_id=12 bits_offset=1056
> > >> >     'local_port' type_id=12 bits_offset=1088
> > >> >     'data_meta' type_id=12 bits_offset=1120
> > >> >     '(anon)' type_id=23 bits_offset=1152
> > >> >     'tstamp' type_id=15 bits_offset=1216
> > >> >     'wire_len' type_id=12 bits_offset=1280
> > >> >     'gso_segs' type_id=12 bits_offset=1312
> > >> >     '(anon)' type_id=30 bits_offset=1344
> > >> >     'gso_size' type_id=12 bits_offset=1408
> > >> >     'hwtstamp' type_id=15 bits_offset=1472
> > >> > [34] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=5
> > >> > [35] CONST '(anon)' type_id=33
> > >> > [36] PTR '(anon)' type_id=0
> > >> > [37] STRUCT '(anon)' size=24 vlen=3
> > >> >     'type' type_id=39 bits_offset=0
> > >> >     'key' type_id=40 bits_offset=64
> > >> >     'value' type_id=41 bits_offset=128
> > >> > [38] ARRAY '(anon)' type_id=9 index_type_id=16 nr_elems=1
> > >> > [39] PTR '(anon)' type_id=38
> > >> > [40] PTR '(anon)' type_id=12
> > >> > [41] PTR '(anon)' type_id=3
> > >> > [42] ARRAY '(anon)' type_id=19 index_type_id=16 nr_elems=18
> > >> > [43] CONST '(anon)' type_id=42
> > >> > [44] FUNC_PROTO '(anon)' ret_type_id=36 vlen=2
> > >> >     '(anon)' type_id=36
> > >> >     '(anon)' type_id=46
> > >> > [45] CONST '(anon)' type_id=0
> > >> > [46] PTR '(anon)' type_id=45
> > >> > [47] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
> > >> >     'sk' type_id=48
> > >> > [48] PTR '(anon)' type_id=35
> > >> > [49] VAR '_license' type_id=43, linkage=static
> > >> > [50] VAR 'is_allow_list' type_id=5, linkage=global
> > >> > [51] VAR 'sd_restrictif' type_id=37, linkage=global
> > >> > [52] FUNC 'sd_restrictif_i' type_id=47 linkage=global
> > >> > [53] FUNC 'sd_restrictif_e' type_id=47 linkage=global
> > >> > [54] FUNC 'restrict_network_interfaces_impl' type_id=47 linkage=static
> > >> > [55] DATASEC '.data' size=1 vlen=1
> > >> >     type_id=50 offset=0 size=1 (VAR 'is_allow_list')
> > >> > [56] DATASEC 'license' size=18 vlen=1
> > >> >     type_id=49 offset=0 size=18 (VAR '_license')
> > >> > [57] DATASEC '.maps' size=24 vlen=1
> > >> >     type_id=51 offset=0 size=24 (VAR 'sd_restrictif')
> > >> >
> > >> > File before being stripped using bpftool gen object:
> > >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> > >> > btf dump file
> > >> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
> > >> > format raw
> > >> > [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> > >> > [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
> > >> > [3] TYPEDEF '__u8' type_id=2
> > >> > [4] CONST '(anon)' type_id=3
> > >> > [5] VOLATILE '(anon)' type_id=4
> > >> > [6] INT 'short int' size=2 bits_offset=0 nr_bits=16 encoding=SIGNED
> > >> > [7] INT 'short unsigned int' size=2 bits_offset=0 nr_bits=16 encoding=(none)
> > >> > [8] TYPEDEF '__u16' type_id=7
> > >> > [9] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
> > >> > [10] TYPEDEF '__s32' type_id=9
> > >> > [11] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
> > >> > [12] TYPEDEF '__u32' type_id=11
> > >> > [13] INT 'long long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
> > >> > [14] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64
> > >> > encoding=(none)
> > >> > [15] TYPEDEF '__u64' type_id=14
> > >> > [16] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
> > >> > [17] INT 'long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
> > >> > [18] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> > >> > [19] CONST '(anon)' type_id=18
> > >> > [20] TYPEDEF '__be16' type_id=8
> > >> > [21] TYPEDEF '__be32' type_id=12
> > >> > [22] ENUM 'bpf_map_type' encoding=UNSIGNED size=4 vlen=31
> > >> >     'BPF_MAP_TYPE_UNSPEC' val=0
> > >> >     'BPF_MAP_TYPE_HASH' val=1
> > >> >     'BPF_MAP_TYPE_ARRAY' val=2
> > >> >     'BPF_MAP_TYPE_PROG_ARRAY' val=3
> > >> >     'BPF_MAP_TYPE_PERF_EVENT_ARRAY' val=4
> > >> >     'BPF_MAP_TYPE_PERCPU_HASH' val=5
> > >> >     'BPF_MAP_TYPE_PERCPU_ARRAY' val=6
> > >> >     'BPF_MAP_TYPE_STACK_TRACE' val=7
> > >> >     'BPF_MAP_TYPE_CGROUP_ARRAY' val=8
> > >> >     'BPF_MAP_TYPE_LRU_HASH' val=9
> > >> >     'BPF_MAP_TYPE_LRU_PERCPU_HASH' val=10
> > >> >     'BPF_MAP_TYPE_LPM_TRIE' val=11
> > >> >     'BPF_MAP_TYPE_ARRAY_OF_MAPS' val=12
> > >> >     'BPF_MAP_TYPE_HASH_OF_MAPS' val=13
> > >> >     'BPF_MAP_TYPE_DEVMAP' val=14
> > >> >     'BPF_MAP_TYPE_SOCKMAP' val=15
> > >> >     'BPF_MAP_TYPE_CPUMAP' val=16
> > >> >     'BPF_MAP_TYPE_XSKMAP' val=17
> > >> >     'BPF_MAP_TYPE_SOCKHASH' val=18
> > >> >     'BPF_MAP_TYPE_CGROUP_STORAGE' val=19
> > >> >     'BPF_MAP_TYPE_REUSEPORT_SOCKARRAY' val=20
> > >> >     'BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE' val=21
> > >> >     'BPF_MAP_TYPE_QUEUE' val=22
> > >> >     'BPF_MAP_TYPE_STACK' val=23
> > >> >     'BPF_MAP_TYPE_SK_STORAGE' val=24
> > >> >     'BPF_MAP_TYPE_DEVMAP_HASH' val=25
> > >> >     'BPF_MAP_TYPE_STRUCT_OPS' val=26
> > >> >     'BPF_MAP_TYPE_RINGBUF' val=27
> > >> >     'BPF_MAP_TYPE_INODE_STORAGE' val=28
> > >> >     'BPF_MAP_TYPE_TASK_STORAGE' val=29
> > >> >     'BPF_MAP_TYPE_BLOOM_FILTER' val=30
> > >> > [23] UNION '(anon)' size=8 vlen=1
> > >> >     'flow_keys' type_id=29 bits_offset=0
> > >> > [24] STRUCT 'bpf_flow_keys' size=56 vlen=13
> > >> >     'nhoff' type_id=8 bits_offset=0
> > >> >     'thoff' type_id=8 bits_offset=16
> > >> >     'addr_proto' type_id=8 bits_offset=32
> > >> >     'is_frag' type_id=3 bits_offset=48
> > >> >     'is_first_frag' type_id=3 bits_offset=56
> > >> >     'is_encap' type_id=3 bits_offset=64
> > >> >     'ip_proto' type_id=3 bits_offset=72
> > >> >     'n_proto' type_id=20 bits_offset=80
> > >> >     'sport' type_id=20 bits_offset=96
> > >> >     'dport' type_id=20 bits_offset=112
> > >> >     '(anon)' type_id=25 bits_offset=128
> > >> >     'flags' type_id=12 bits_offset=384
> > >> >     'flow_label' type_id=21 bits_offset=416
> > >> > [25] UNION '(anon)' size=32 vlen=2
> > >> >     '(anon)' type_id=26 bits_offset=0
> > >> >     '(anon)' type_id=27 bits_offset=0
> > >> > [26] STRUCT '(anon)' size=8 vlen=2
> > >> >     'ipv4_src' type_id=21 bits_offset=0
> > >> >     'ipv4_dst' type_id=21 bits_offset=32
> > >> > [27] STRUCT '(anon)' size=32 vlen=2
> > >> >     'ipv6_src' type_id=28 bits_offset=0
> > >> >     'ipv6_dst' type_id=28 bits_offset=128
> > >> > [28] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=4
> > >> > [29] PTR '(anon)' type_id=24
> > >> > [30] UNION '(anon)' size=8 vlen=1
> > >> >     'sk' type_id=32 bits_offset=0
> > >> > [31] STRUCT 'bpf_sock' size=80 vlen=14
> > >> >     'bound_dev_if' type_id=12 bits_offset=0
> > >> >     'family' type_id=12 bits_offset=32
> > >> >     'type' type_id=12 bits_offset=64
> > >> >     'protocol' type_id=12 bits_offset=96
> > >> >     'mark' type_id=12 bits_offset=128
> > >> >     'priority' type_id=12 bits_offset=160
> > >> >     'src_ip4' type_id=12 bits_offset=192
> > >> >     'src_ip6' type_id=28 bits_offset=224
> > >> >     'src_port' type_id=12 bits_offset=352
> > >> >     'dst_port' type_id=20 bits_offset=384
> > >> >     'dst_ip4' type_id=12 bits_offset=416
> > >> >     'dst_ip6' type_id=28 bits_offset=448
> > >> >     'state' type_id=12 bits_offset=576
> > >> >     'rx_queue_mapping' type_id=10 bits_offset=608
> > >> > [32] PTR '(anon)' type_id=31
> > >> > [33] STRUCT '__sk_buff' size=192 vlen=33
> > >> >     'len' type_id=12 bits_offset=0
> > >> >     'pkt_type' type_id=12 bits_offset=32
> > >> >     'mark' type_id=12 bits_offset=64
> > >> >     'queue_mapping' type_id=12 bits_offset=96
> > >> >     'protocol' type_id=12 bits_offset=128
> > >> >     'vlan_present' type_id=12 bits_offset=160
> > >> >     'vlan_tci' type_id=12 bits_offset=192
> > >> >     'vlan_proto' type_id=12 bits_offset=224
> > >> >     'priority' type_id=12 bits_offset=256
> > >> >     'ingress_ifindex' type_id=12 bits_offset=288
> > >> >     'ifindex' type_id=12 bits_offset=320
> > >> >     'tc_index' type_id=12 bits_offset=352
> > >> >     'cb' type_id=34 bits_offset=384
> > >> >     'hash' type_id=12 bits_offset=544
> > >> >     'tc_classid' type_id=12 bits_offset=576
> > >> >     'data' type_id=12 bits_offset=608
> > >> >     'data_end' type_id=12 bits_offset=640
> > >> >     'napi_id' type_id=12 bits_offset=672
> > >> >     'family' type_id=12 bits_offset=704
> > >> >     'remote_ip4' type_id=12 bits_offset=736
> > >> >     'local_ip4' type_id=12 bits_offset=768
> > >> >     'remote_ip6' type_id=28 bits_offset=800
> > >> >     'local_ip6' type_id=28 bits_offset=928
> > >> >     'remote_port' type_id=12 bits_offset=1056
> > >> >     'local_port' type_id=12 bits_offset=1088
> > >> >     'data_meta' type_id=12 bits_offset=1120
> > >> >     '(anon)' type_id=23 bits_offset=1152
> > >> >     'tstamp' type_id=15 bits_offset=1216
> > >> >     'wire_len' type_id=12 bits_offset=1280
> > >> >     'gso_segs' type_id=12 bits_offset=1312
> > >> >     '(anon)' type_id=30 bits_offset=1344
> > >> >     'gso_size' type_id=12 bits_offset=1408
> > >> >     'hwtstamp' type_id=15 bits_offset=1472
> > >> > [34] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=5
> > >> > [35] CONST '(anon)' type_id=33
> > >> > [36] PTR '(anon)' type_id=0
> > >> > [37] STRUCT '(anon)' size=24 vlen=3
> > >> >     'type' type_id=39 bits_offset=0
> > >> >     'key' type_id=40 bits_offset=64
> > >> >     'value' type_id=41 bits_offset=128
> > >> > [38] ARRAY '(anon)' type_id=9 index_type_id=16 nr_elems=1
> > >> > [39] PTR '(anon)' type_id=38
> > >> > [40] PTR '(anon)' type_id=12
> > >> > [41] PTR '(anon)' type_id=3
> > >> > [42] ARRAY '(anon)' type_id=19 index_type_id=16 nr_elems=18
> > >> > [43] CONST '(anon)' type_id=42
> > >> > [44] FUNC_PROTO '(anon)' ret_type_id=36 vlen=2
> > >> >     '(anon)' type_id=36
> > >> >     '(anon)' type_id=46
> > >> > [45] CONST '(anon)' type_id=0
> > >> > [46] PTR '(anon)' type_id=45
> > >> > [47] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
> > >> >     'sk' type_id=48
> > >> > [48] PTR '(anon)' type_id=35
> > >> > [49] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
> > >> >     'sk' type_id=48
> > >> > [50] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
> > >> >     'sk' type_id=48
> > >> > [51] VAR '_license' type_id=43, linkage=static
> > >> > [52] VAR 'is_allow_list' type_id=5, linkage=global
> > >> > [53] VAR 'sd_restrictif' type_id=37, linkage=global
> > >> > [54] FUNC 'bpf_map_lookup_elem' type_id=44 linkage=global
> > >> > [55] FUNC 'sd_restrictif_i' type_id=47 linkage=global
> > >> > [56] FUNC 'sd_restrictif_e' type_id=49 linkage=global
> > >> > [57] FUNC 'restrict_network_interfaces_impl' type_id=50 linkage=static
> > >> > [58] DATASEC 'license' size=0 vlen=1
> > >> >     type_id=51 offset=0 size=18 (VAR '_license')
> > >> > [59] DATASEC '.maps' size=0 vlen=1
> > >> >     type_id=53 offset=0 size=24 (VAR 'sd_restrictif')
> > >> > [60] DATASEC '.data' size=0 vlen=1
> > >> >     type_id=52 offset=0 size=1 (VAR 'is_allow_list')
> > >> >
> > >> >>
> > >> >> >> GCC is wrong, clearly. This function is global ([0]) and libbpf
> > >> >> >> expects it to be marked as such in BTF.
> > >> >> >>
> > >> >> >>
> > >> > https://github.com/systemd/systemd/blob/main/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.c#L42-L50
> > >> >> >>
> > >> >> >>
> > >> >> >>> GCC:
> > >> >> >>>
> > >> >> >>> [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> > >> >> >>> [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
> > >> >> >>> [3] TYPEDEF '__u8' type_id=2
> > >> >> >>> [4] CONST '(anon)' type_id=3
> > >> >> >>
> > >> >> >> [...]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-07-09 20:39                 ` James Hilliard
@ 2022-07-09 22:41                   ` Jose E. Marchesi
  2022-07-09 22:54                     ` James Hilliard
  0 siblings, 1 reply; 38+ messages in thread
From: Jose E. Marchesi @ 2022-07-09 22:41 UTC (permalink / raw)
  To: James Hilliard; +Cc: Andrii Nakryiko, bpf, david.faust


> On Sat, Jul 9, 2022 at 2:32 PM James Hilliard <james.hilliard1@gmail.com> wrote:
>>
>> On Sat, Jul 9, 2022 at 2:21 PM Jose E. Marchesi
>> <jose.marchesi@oracle.com> wrote:
>> >
>> >
>> > > On Sat, Jul 9, 2022 at 11:24 AM Jose E. Marchesi
>> > > <jose.marchesi@oracle.com> wrote:
>> > >>
>> > >>
>> > >> > On Fri, Jul 8, 2022 at 12:33 PM Jose E. Marchesi
>> > >> > <jose.marchesi@oracle.com> wrote:
>> > >> >>
>> > >> >>
>> > >> >> >> On Wed, Jul 6, 2022 at 10:13 AM James Hilliard
>> > >> >> >> <james.hilliard1@gmail.com> wrote:
>> > >> >> >>>
>> > >> >> >>> Note I'm testing with the following patches:
>> > >> >> >>> https://lore.kernel.org/bpf/20220706111839.1247911-1-james.hilliard1@gmail.com/
>> > >> >> >>> https://lore.kernel.org/bpf/20220706140623.2917858-1-james.hilliard1@gmail.com/
>> > >> >> >>>
>> > >> >> >>> It would appear there's some compatibility issues with bpftool gen and
>> > >> >> >>> GCC, not sure what side though is wrong here:
>> > >> >> >>> /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>> > >> >> >>> gen object src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>> > >> >> >>> src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
>> > >> >> >>> libbpf: failed to find BTF info for global/extern symbol 'sd_restrictif_i'
>> > >> >> >>> Error: failed to link
>> > >> >> >>> 'src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o':
>> > >> >> >>> Unknown error -2 (-2)
>> > >> >> >>>
>> > >> >> >>> Relevant difference seems to be this:
>> > >> >> >>> GCC:
>> > >> >> >>> [55] FUNC 'sd_restrictif_i' type_id=47 linkage=static
>> > >> >> >>> Clang:
>> > >> >> >>> [27] FUNC 'sd_restrictif_i' type_id=26 linkage=global
>> > >> >> >
>> > >> >> > For functions GCC generates a BTF_KIND_FUNC entry, which has no linkage
>> > >> >> > information, or so we thought: I just looked at bpftool/btf.c and I
>> > >> >> > found the linkage info for function types is expected to be encoded in
>> > >> >> > the vlen field of BTF_KIND_FUNC entries (why not adding a btf_func
>> > >> >> > instead???) which is surprising to say the least.
>> > >> >> >
>> > >> >> > We are changing GCC to encode the linkage info in vlen for these types.
>> > >> >> > Thanks for reporting this.
>> > >> >>
>> > >> >> Patch sent to GCC upstream:
>> > >> >> https://gcc.gnu.org/pipermail/gcc-patches/2022-July/598090.html
>> > >> >
>> > >> > I applied that patch on top of GCC 12.1.0 and it appears to fix the
>> > >> > bpftool gen object bug.
>> > >> >
>> > >> > I am however now hitting a different error during skeleton generation:
>> > >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>> > >> > gen skeleton src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>> > >> > libbpf: elf: skipping unrecognized data section(9) .comment
>> > >> > libbpf: failed to alloc map 'restrict.bss' content buffer: -22
>> > >> > Error: failed to open BPF object file: Invalid argument
>> > >>
>> > >> What is the size of the .bss section in the object file?  Try with:
>> > >>
>> > >> $ size restrict-ifaces.bpf.o
>> > >
>> > > $ size
> output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>> > >    text       data        bss        dec        hex    filename
>> > >     386         25          0        411        19b
>> > > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>> >
>> > Right, so the .bss section is empty.  I see a `const volatile unsigned
>> > char is_allow_list = 0;' in restrict-ifaces.bpf.c, but that goes to
>> > .data and not to .bss, as expected.
>> >
>> > If you build restrict-ifaces.bpf.o with LLVM, is the bss still empty?  I
>> > don't think the code in libbpf.c even checks for this eventuality...
>>
>> LLVM version(which skeleton generation works with):
>> $ size restrict-ifaces.bpf.o
>>    text       data        bss        dec        hex    filename
>>     323         24          0        347        15b    restrict-ifaces.bpf.o
>>
>> $ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>> btf dump file restrict-ifaces.bpf.o format raw
>> [1] PTR '(anon)' type_id=3
>> [2] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
>> [3] ARRAY '(anon)' type_id=2 index_type_id=4 nr_elems=1
>> [4] INT '__ARRAY_SIZE_TYPE__' size=4 bits_offset=0 nr_bits=32 encoding=(none)
>> [5] PTR '(anon)' type_id=6
>> [6] TYPEDEF '__u32' type_id=7
>> [7] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
>> [8] PTR '(anon)' type_id=9
>> [9] TYPEDEF '__u8' type_id=10
>> [10] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=(none)
>> [11] STRUCT '(anon)' size=24 vlen=3
>>     'type' type_id=1 bits_offset=0
>>     'key' type_id=5 bits_offset=64
>>     'value' type_id=8 bits_offset=128
>> [12] VAR 'sd_restrictif' type_id=11, linkage=global
>> [13] PTR '(anon)' type_id=14
>> [14] CONST '(anon)' type_id=15
>> [15] STRUCT '__sk_buff' size=192 vlen=33
>>     'len' type_id=6 bits_offset=0
>>     'pkt_type' type_id=6 bits_offset=32
>>     'mark' type_id=6 bits_offset=64
>>     'queue_mapping' type_id=6 bits_offset=96
>>     'protocol' type_id=6 bits_offset=128
>>     'vlan_present' type_id=6 bits_offset=160
>>     'vlan_tci' type_id=6 bits_offset=192
>>     'vlan_proto' type_id=6 bits_offset=224
>>     'priority' type_id=6 bits_offset=256
>>     'ingress_ifindex' type_id=6 bits_offset=288
>>     'ifindex' type_id=6 bits_offset=320
>>     'tc_index' type_id=6 bits_offset=352
>>     'cb' type_id=16 bits_offset=384
>>     'hash' type_id=6 bits_offset=544
>>     'tc_classid' type_id=6 bits_offset=576
>>     'data' type_id=6 bits_offset=608
>>     'data_end' type_id=6 bits_offset=640
>>     'napi_id' type_id=6 bits_offset=672
>>     'family' type_id=6 bits_offset=704
>>     'remote_ip4' type_id=6 bits_offset=736
>>     'local_ip4' type_id=6 bits_offset=768
>>     'remote_ip6' type_id=17 bits_offset=800
>>     'local_ip6' type_id=17 bits_offset=928
>>     'remote_port' type_id=6 bits_offset=1056
>>     'local_port' type_id=6 bits_offset=1088
>>     'data_meta' type_id=6 bits_offset=1120
>>     '(anon)' type_id=18 bits_offset=1152
>>     'tstamp' type_id=20 bits_offset=1216
>>     'wire_len' type_id=6 bits_offset=1280
>>     'gso_segs' type_id=6 bits_offset=1312
>>     '(anon)' type_id=22 bits_offset=1344
>>     'gso_size' type_id=6 bits_offset=1408
>>     'hwtstamp' type_id=20 bits_offset=1472
>> [16] ARRAY '(anon)' type_id=6 index_type_id=4 nr_elems=5
>> [17] ARRAY '(anon)' type_id=6 index_type_id=4 nr_elems=4
>> [18] UNION '(anon)' size=8 vlen=1
>>     'flow_keys' type_id=19 bits_offset=0
>> [19] PTR '(anon)' type_id=34
>> [20] TYPEDEF '__u64' type_id=21
>> [21] INT 'unsigned long long' size=8 bits_offset=0 nr_bits=64 encoding=(none)
>> [22] UNION '(anon)' size=8 vlen=1
>>     'sk' type_id=23 bits_offset=0
>> [23] PTR '(anon)' type_id=35
>> [24] FUNC_PROTO '(anon)' ret_type_id=2 vlen=1
>>     'sk' type_id=13
>> [25] FUNC 'sd_restrictif_e' type_id=24 linkage=global
>> [26] FUNC 'sd_restrictif_i' type_id=24 linkage=global
>> [27] CONST '(anon)' type_id=28
>> [28] VOLATILE '(anon)' type_id=9
>> [29] VAR 'is_allow_list' type_id=27, linkage=global
>> [30] CONST '(anon)' type_id=31
>> [31] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=SIGNED
>> [32] ARRAY '(anon)' type_id=30 index_type_id=4 nr_elems=18
>> [33] VAR '_license' type_id=32, linkage=static
>> [34] FWD 'bpf_flow_keys' fwd_kind=struct
>> [35] FWD 'bpf_sock' fwd_kind=struct
>> [36] DATASEC '.rodata' size=1 vlen=1
>>     type_id=29 offset=0 size=1 (VAR 'is_allow_list')
>> [37] DATASEC 'license' size=18 vlen=1
>>     type_id=33 offset=0 size=18 (VAR '_license')
>> [38] DATASEC '.maps' size=24 vlen=1
>>     type_id=12 offset=0 size=24 (VAR 'sd_restrictif')
>>
>
> Skeleton generation debug output for GCC(failing) and LLVM(working)
> which may be helpful:

Indeed it was helpful :)

The GNU assembler generates an empty .bss section.  This is a well
established behavior in GAS that happens in all supported targets.

The LLVM assembler doesn't generate an empty .bss section.

bpftool chokes on the empty .bss section.

In this case I would suggest to fix bpf_object__init_global_data_maps in
order to skip empty sections.

Something like this:

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index e89cc9c885b3..e3a6808f0bb6 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -1591,6 +1591,10 @@ static int bpf_object__init_global_data_maps(struct bpf_object *obj)
 	for (sec_idx = 1; sec_idx < obj->efile.sec_cnt; sec_idx++) {
 		sec_desc = &obj->efile.secs[sec_idx];
 
+                /* Skip empty sections.  */
+                if (sec_desc->data->d_size == 0)
+                  continue;
+
 		switch (sec_desc->sec_type) {
 		case SEC_DATA:
 			sec_name = elf_sec_name(obj, elf_sec_by_idx(obj, sec_idx));

> GCC:
> $ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> --debug gen skeleton
> output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> libbpf: loading object 'restrict_ifaces_bpf' from buffer
> libbpf: elf: section(2) .symtab, size 336, link 1, flags 0, type=2
> libbpf: elf: section(3) .data, size 1, link 0, flags 3, type=1
> libbpf: elf: section(4) .bss, size 0, link 0, flags 3, type=8
> libbpf: elf: section(5) cgroup_skb/egress, size 184, link 0, flags 6, type=1
> libbpf: sec 'cgroup_skb/egress': found program 'sd_restrictif_e' at
> insn offset 0 (0 bytes), code size 23 insns (184 bytes)
> libbpf: elf: section(6) cgroup_skb/ingress, size 184, link 0, flags 6, type=1
> libbpf: sec 'cgroup_skb/ingress': found program 'sd_restrictif_i' at
> insn offset 0 (0 bytes), code size 23 insns (184 bytes)
> libbpf: elf: section(7) license, size 18, link 0, flags 2, type=1
> libbpf: license of restrict_ifaces_bpf is LGPL-2.1-or-later
> libbpf: elf: section(8) .maps, size 24, link 0, flags 3, type=1
> libbpf: elf: section(9) .comment, size 49, link 0, flags 30, type=1
> libbpf: elf: skipping unrecognized data section(9) .comment
> libbpf: elf: section(10) .relcgroup_skb/egress, size 32, link 2, flags
> 40, type=9
> libbpf: elf: section(11) .relcgroup_skb/ingress, size 32, link 2,
> flags 40, type=9
> libbpf: elf: section(12) .BTF, size 3606, link 0, flags 0, type=1
> libbpf: looking for externs among 14 symbols...
> libbpf: collected 0 externs total
> libbpf: map 'sd_restrictif': at sec_idx 8, offset 0.
> libbpf: map 'sd_restrictif': found type = 1.
> libbpf: map 'sd_restrictif': found key [12], sz = 4.
> libbpf: map 'sd_restrictif': found value [3], sz = 1.
> libbpf: map 'restrict.data' (global data): at sec_idx 3, offset 0, flags 400.
> libbpf: map 1 is "restrict.data"
> libbpf: map 'restrict.bss' (global data): at sec_idx 4, offset 0, flags 400.
> libbpf: failed to alloc map 'restrict.bss' content buffer: -22
> Error: failed to open BPF object file: Invalid argument
>
> LLVM:
> $ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> --debug gen skeleton restrict-ifaces.bpf.o
> libbpf: loading object 'restrict_ifaces_bpf' from buffer
> libbpf: elf: section(2) .symtab, size 384, link 1, flags 0, type=2
> libbpf: elf: section(3) cgroup_skb/egress, size 152, link 0, flags 6, type=1
> libbpf: sec 'cgroup_skb/egress': found program 'sd_restrictif_e' at
> insn offset 0 (0 bytes), code size 19 insns (152 bytes)
> libbpf: elf: section(4) cgroup_skb/ingress, size 152, link 0, flags 6, type=1
> libbpf: sec 'cgroup_skb/ingress': found program 'sd_restrictif_i' at
> insn offset 0 (0 bytes), code size 19 insns (152 bytes)
> libbpf: elf: section(5) .rodata, size 1, link 0, flags 2, type=1
> libbpf: elf: section(6) license, size 18, link 0, flags 2, type=1
> libbpf: license of restrict_ifaces_bpf is LGPL-2.1-or-later
> libbpf: elf: section(7) .maps, size 24, link 0, flags 3, type=1
> libbpf: elf: section(8) .relcgroup_skb/egress, size 32, link 2, flags 40, type=9
> libbpf: elf: section(9) .relcgroup_skb/ingress, size 32, link 2, flags
> 40, type=9
> libbpf: elf: section(10) .BTF, size 1988, link 0, flags 0, type=1
> libbpf: elf: section(11) .BTF.ext, size 376, link 0, flags 0, type=1
> libbpf: looking for externs among 16 symbols...
> libbpf: collected 0 externs total
> libbpf: map 'sd_restrictif': at sec_idx 7, offset 0.
> libbpf: map 'sd_restrictif': found type = 1.
> libbpf: map 'sd_restrictif': found key [6], sz = 4.
> libbpf: map 'sd_restrictif': found value [9], sz = 1.
> libbpf: map 'restrict.rodata' (global data): at sec_idx 5, offset 0, flags 480.
> libbpf: map 1 is "restrict.rodata"
> libbpf: sec '.relcgroup_skb/egress': collecting relocation for
> section(3) 'cgroup_skb/egress'
> libbpf: sec '.relcgroup_skb/egress': relo #0: insn #4 against 'sd_restrictif'
> libbpf: prog 'sd_restrictif_e': found map 0 (sd_restrictif, sec 7, off
> 0) for insn #4
> libbpf: sec '.relcgroup_skb/egress': relo #1: insn #7 against 'is_allow_list'
> libbpf: prog 'sd_restrictif_e': found data map 1 (restrict.rodata, sec
> 5, off 0) for insn 7
> libbpf: sec '.relcgroup_skb/ingress': collecting relocation for
> section(4) 'cgroup_skb/ingress'
> libbpf: sec '.relcgroup_skb/ingress': relo #0: insn #4 against 'sd_restrictif'
> libbpf: prog 'sd_restrictif_i': found map 0 (sd_restrictif, sec 7, off
> 0) for insn #4
> libbpf: sec '.relcgroup_skb/ingress': relo #1: insn #7 against 'is_allow_list'
> libbpf: prog 'sd_restrictif_i': found data map 1 (restrict.rodata, sec
> 5, off 0) for insn 7
>
>> >
>> > >>
>> > >> Looking at libbpf.c, it seems to me that this may be due of trying to
>> > >> mmap 0 bytes in `bpf_object__init_internal_map':
>> > >>
>> > >>         map->mmaped = mmap(NULL, bpf_map_mmap_sz(map), PROT_READ | PROT_WRITE,
>> > >>                            MAP_SHARED | MAP_ANONYMOUS, -1, 0);
>> > >>         if (map->mmaped == MAP_FAILED) {
>> > >>                 err = -errno;
>> > >>                 map->mmaped = NULL;
>> > >>                 pr_warn("failed to alloc map '%s' content buffer: %d\n",
>> > >>                         map->name, err);
>> > >>                 zfree(&map->real_name);
>> > >>                 zfree(&map->name);
>> > >>                 return err;
>> > >>         }
>> > >>
>> > >> I see no check for zero sized sections in
>> > >> bpf_object__init_global_data_maps.
>> > >>
>> > >> Is maybe GCC failing to allocate stuff in BSS that is supposed to be
>> > >> there?
>> > >>
>> > >> > Stripped file passed to gen skeleton:
>> > >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>> > >> > btf dump file
>> > >> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>> > >> > format raw
>> > >> > [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>> > >> > [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
>> > >> > [3] TYPEDEF '__u8' type_id=2
>> > >> > [4] CONST '(anon)' type_id=3
>> > >> > [5] VOLATILE '(anon)' type_id=4
>> > >> > [6] INT 'short int' size=2 bits_offset=0 nr_bits=16 encoding=SIGNED
>> > >> > [7] INT 'short unsigned int' size=2 bits_offset=0 nr_bits=16 encoding=(none)
>> > >> > [8] TYPEDEF '__u16' type_id=7
>> > >> > [9] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
>> > >> > [10] TYPEDEF '__s32' type_id=9
>> > >> > [11] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
>> > >> > [12] TYPEDEF '__u32' type_id=11
>> > >> > [13] INT 'long long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
>> > >> > [14] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64
>> > >> > encoding=(none)
>> > >> > [15] TYPEDEF '__u64' type_id=14
>> > >> > [16] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
>> > >> > [17] INT 'long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
>> > >> > [18] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>> > >> > [19] CONST '(anon)' type_id=18
>> > >> > [20] TYPEDEF '__be16' type_id=8
>> > >> > [21] TYPEDEF '__be32' type_id=12
>> > >> > [22] ENUM 'bpf_map_type' encoding=UNSIGNED size=4 vlen=31
>> > >> >     'BPF_MAP_TYPE_UNSPEC' val=0
>> > >> >     'BPF_MAP_TYPE_HASH' val=1
>> > >> >     'BPF_MAP_TYPE_ARRAY' val=2
>> > >> >     'BPF_MAP_TYPE_PROG_ARRAY' val=3
>> > >> >     'BPF_MAP_TYPE_PERF_EVENT_ARRAY' val=4
>> > >> >     'BPF_MAP_TYPE_PERCPU_HASH' val=5
>> > >> >     'BPF_MAP_TYPE_PERCPU_ARRAY' val=6
>> > >> >     'BPF_MAP_TYPE_STACK_TRACE' val=7
>> > >> >     'BPF_MAP_TYPE_CGROUP_ARRAY' val=8
>> > >> >     'BPF_MAP_TYPE_LRU_HASH' val=9
>> > >> >     'BPF_MAP_TYPE_LRU_PERCPU_HASH' val=10
>> > >> >     'BPF_MAP_TYPE_LPM_TRIE' val=11
>> > >> >     'BPF_MAP_TYPE_ARRAY_OF_MAPS' val=12
>> > >> >     'BPF_MAP_TYPE_HASH_OF_MAPS' val=13
>> > >> >     'BPF_MAP_TYPE_DEVMAP' val=14
>> > >> >     'BPF_MAP_TYPE_SOCKMAP' val=15
>> > >> >     'BPF_MAP_TYPE_CPUMAP' val=16
>> > >> >     'BPF_MAP_TYPE_XSKMAP' val=17
>> > >> >     'BPF_MAP_TYPE_SOCKHASH' val=18
>> > >> >     'BPF_MAP_TYPE_CGROUP_STORAGE' val=19
>> > >> >     'BPF_MAP_TYPE_REUSEPORT_SOCKARRAY' val=20
>> > >> >     'BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE' val=21
>> > >> >     'BPF_MAP_TYPE_QUEUE' val=22
>> > >> >     'BPF_MAP_TYPE_STACK' val=23
>> > >> >     'BPF_MAP_TYPE_SK_STORAGE' val=24
>> > >> >     'BPF_MAP_TYPE_DEVMAP_HASH' val=25
>> > >> >     'BPF_MAP_TYPE_STRUCT_OPS' val=26
>> > >> >     'BPF_MAP_TYPE_RINGBUF' val=27
>> > >> >     'BPF_MAP_TYPE_INODE_STORAGE' val=28
>> > >> >     'BPF_MAP_TYPE_TASK_STORAGE' val=29
>> > >> >     'BPF_MAP_TYPE_BLOOM_FILTER' val=30
>> > >> > [23] UNION '(anon)' size=8 vlen=1
>> > >> >     'flow_keys' type_id=29 bits_offset=0
>> > >> > [24] STRUCT 'bpf_flow_keys' size=56 vlen=13
>> > >> >     'nhoff' type_id=8 bits_offset=0
>> > >> >     'thoff' type_id=8 bits_offset=16
>> > >> >     'addr_proto' type_id=8 bits_offset=32
>> > >> >     'is_frag' type_id=3 bits_offset=48
>> > >> >     'is_first_frag' type_id=3 bits_offset=56
>> > >> >     'is_encap' type_id=3 bits_offset=64
>> > >> >     'ip_proto' type_id=3 bits_offset=72
>> > >> >     'n_proto' type_id=20 bits_offset=80
>> > >> >     'sport' type_id=20 bits_offset=96
>> > >> >     'dport' type_id=20 bits_offset=112
>> > >> >     '(anon)' type_id=25 bits_offset=128
>> > >> >     'flags' type_id=12 bits_offset=384
>> > >> >     'flow_label' type_id=21 bits_offset=416
>> > >> > [25] UNION '(anon)' size=32 vlen=2
>> > >> >     '(anon)' type_id=26 bits_offset=0
>> > >> >     '(anon)' type_id=27 bits_offset=0
>> > >> > [26] STRUCT '(anon)' size=8 vlen=2
>> > >> >     'ipv4_src' type_id=21 bits_offset=0
>> > >> >     'ipv4_dst' type_id=21 bits_offset=32
>> > >> > [27] STRUCT '(anon)' size=32 vlen=2
>> > >> >     'ipv6_src' type_id=28 bits_offset=0
>> > >> >     'ipv6_dst' type_id=28 bits_offset=128
>> > >> > [28] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=4
>> > >> > [29] PTR '(anon)' type_id=24
>> > >> > [30] UNION '(anon)' size=8 vlen=1
>> > >> >     'sk' type_id=32 bits_offset=0
>> > >> > [31] STRUCT 'bpf_sock' size=80 vlen=14
>> > >> >     'bound_dev_if' type_id=12 bits_offset=0
>> > >> >     'family' type_id=12 bits_offset=32
>> > >> >     'type' type_id=12 bits_offset=64
>> > >> >     'protocol' type_id=12 bits_offset=96
>> > >> >     'mark' type_id=12 bits_offset=128
>> > >> >     'priority' type_id=12 bits_offset=160
>> > >> >     'src_ip4' type_id=12 bits_offset=192
>> > >> >     'src_ip6' type_id=28 bits_offset=224
>> > >> >     'src_port' type_id=12 bits_offset=352
>> > >> >     'dst_port' type_id=20 bits_offset=384
>> > >> >     'dst_ip4' type_id=12 bits_offset=416
>> > >> >     'dst_ip6' type_id=28 bits_offset=448
>> > >> >     'state' type_id=12 bits_offset=576
>> > >> >     'rx_queue_mapping' type_id=10 bits_offset=608
>> > >> > [32] PTR '(anon)' type_id=31
>> > >> > [33] STRUCT '__sk_buff' size=192 vlen=33
>> > >> >     'len' type_id=12 bits_offset=0
>> > >> >     'pkt_type' type_id=12 bits_offset=32
>> > >> >     'mark' type_id=12 bits_offset=64
>> > >> >     'queue_mapping' type_id=12 bits_offset=96
>> > >> >     'protocol' type_id=12 bits_offset=128
>> > >> >     'vlan_present' type_id=12 bits_offset=160
>> > >> >     'vlan_tci' type_id=12 bits_offset=192
>> > >> >     'vlan_proto' type_id=12 bits_offset=224
>> > >> >     'priority' type_id=12 bits_offset=256
>> > >> >     'ingress_ifindex' type_id=12 bits_offset=288
>> > >> >     'ifindex' type_id=12 bits_offset=320
>> > >> >     'tc_index' type_id=12 bits_offset=352
>> > >> >     'cb' type_id=34 bits_offset=384
>> > >> >     'hash' type_id=12 bits_offset=544
>> > >> >     'tc_classid' type_id=12 bits_offset=576
>> > >> >     'data' type_id=12 bits_offset=608
>> > >> >     'data_end' type_id=12 bits_offset=640
>> > >> >     'napi_id' type_id=12 bits_offset=672
>> > >> >     'family' type_id=12 bits_offset=704
>> > >> >     'remote_ip4' type_id=12 bits_offset=736
>> > >> >     'local_ip4' type_id=12 bits_offset=768
>> > >> >     'remote_ip6' type_id=28 bits_offset=800
>> > >> >     'local_ip6' type_id=28 bits_offset=928
>> > >> >     'remote_port' type_id=12 bits_offset=1056
>> > >> >     'local_port' type_id=12 bits_offset=1088
>> > >> >     'data_meta' type_id=12 bits_offset=1120
>> > >> >     '(anon)' type_id=23 bits_offset=1152
>> > >> >     'tstamp' type_id=15 bits_offset=1216
>> > >> >     'wire_len' type_id=12 bits_offset=1280
>> > >> >     'gso_segs' type_id=12 bits_offset=1312
>> > >> >     '(anon)' type_id=30 bits_offset=1344
>> > >> >     'gso_size' type_id=12 bits_offset=1408
>> > >> >     'hwtstamp' type_id=15 bits_offset=1472
>> > >> > [34] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=5
>> > >> > [35] CONST '(anon)' type_id=33
>> > >> > [36] PTR '(anon)' type_id=0
>> > >> > [37] STRUCT '(anon)' size=24 vlen=3
>> > >> >     'type' type_id=39 bits_offset=0
>> > >> >     'key' type_id=40 bits_offset=64
>> > >> >     'value' type_id=41 bits_offset=128
>> > >> > [38] ARRAY '(anon)' type_id=9 index_type_id=16 nr_elems=1
>> > >> > [39] PTR '(anon)' type_id=38
>> > >> > [40] PTR '(anon)' type_id=12
>> > >> > [41] PTR '(anon)' type_id=3
>> > >> > [42] ARRAY '(anon)' type_id=19 index_type_id=16 nr_elems=18
>> > >> > [43] CONST '(anon)' type_id=42
>> > >> > [44] FUNC_PROTO '(anon)' ret_type_id=36 vlen=2
>> > >> >     '(anon)' type_id=36
>> > >> >     '(anon)' type_id=46
>> > >> > [45] CONST '(anon)' type_id=0
>> > >> > [46] PTR '(anon)' type_id=45
>> > >> > [47] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>> > >> >     'sk' type_id=48
>> > >> > [48] PTR '(anon)' type_id=35
>> > >> > [49] VAR '_license' type_id=43, linkage=static
>> > >> > [50] VAR 'is_allow_list' type_id=5, linkage=global
>> > >> > [51] VAR 'sd_restrictif' type_id=37, linkage=global
>> > >> > [52] FUNC 'sd_restrictif_i' type_id=47 linkage=global
>> > >> > [53] FUNC 'sd_restrictif_e' type_id=47 linkage=global
>> > >> > [54] FUNC 'restrict_network_interfaces_impl' type_id=47 linkage=static
>> > >> > [55] DATASEC '.data' size=1 vlen=1
>> > >> >     type_id=50 offset=0 size=1 (VAR 'is_allow_list')
>> > >> > [56] DATASEC 'license' size=18 vlen=1
>> > >> >     type_id=49 offset=0 size=18 (VAR '_license')
>> > >> > [57] DATASEC '.maps' size=24 vlen=1
>> > >> >     type_id=51 offset=0 size=24 (VAR 'sd_restrictif')
>> > >> >
>> > >> > File before being stripped using bpftool gen object:
>> > >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>> > >> > btf dump file
>> > >> >
> output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
>> > >> > format raw
>> > >> > [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>> > >> > [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
>> > >> > [3] TYPEDEF '__u8' type_id=2
>> > >> > [4] CONST '(anon)' type_id=3
>> > >> > [5] VOLATILE '(anon)' type_id=4
>> > >> > [6] INT 'short int' size=2 bits_offset=0 nr_bits=16 encoding=SIGNED
>> > >> > [7] INT 'short unsigned int' size=2 bits_offset=0 nr_bits=16 encoding=(none)
>> > >> > [8] TYPEDEF '__u16' type_id=7
>> > >> > [9] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
>> > >> > [10] TYPEDEF '__s32' type_id=9
>> > >> > [11] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
>> > >> > [12] TYPEDEF '__u32' type_id=11
>> > >> > [13] INT 'long long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
>> > >> > [14] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64
>> > >> > encoding=(none)
>> > >> > [15] TYPEDEF '__u64' type_id=14
>> > >> > [16] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
>> > >> > [17] INT 'long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
>> > >> > [18] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>> > >> > [19] CONST '(anon)' type_id=18
>> > >> > [20] TYPEDEF '__be16' type_id=8
>> > >> > [21] TYPEDEF '__be32' type_id=12
>> > >> > [22] ENUM 'bpf_map_type' encoding=UNSIGNED size=4 vlen=31
>> > >> >     'BPF_MAP_TYPE_UNSPEC' val=0
>> > >> >     'BPF_MAP_TYPE_HASH' val=1
>> > >> >     'BPF_MAP_TYPE_ARRAY' val=2
>> > >> >     'BPF_MAP_TYPE_PROG_ARRAY' val=3
>> > >> >     'BPF_MAP_TYPE_PERF_EVENT_ARRAY' val=4
>> > >> >     'BPF_MAP_TYPE_PERCPU_HASH' val=5
>> > >> >     'BPF_MAP_TYPE_PERCPU_ARRAY' val=6
>> > >> >     'BPF_MAP_TYPE_STACK_TRACE' val=7
>> > >> >     'BPF_MAP_TYPE_CGROUP_ARRAY' val=8
>> > >> >     'BPF_MAP_TYPE_LRU_HASH' val=9
>> > >> >     'BPF_MAP_TYPE_LRU_PERCPU_HASH' val=10
>> > >> >     'BPF_MAP_TYPE_LPM_TRIE' val=11
>> > >> >     'BPF_MAP_TYPE_ARRAY_OF_MAPS' val=12
>> > >> >     'BPF_MAP_TYPE_HASH_OF_MAPS' val=13
>> > >> >     'BPF_MAP_TYPE_DEVMAP' val=14
>> > >> >     'BPF_MAP_TYPE_SOCKMAP' val=15
>> > >> >     'BPF_MAP_TYPE_CPUMAP' val=16
>> > >> >     'BPF_MAP_TYPE_XSKMAP' val=17
>> > >> >     'BPF_MAP_TYPE_SOCKHASH' val=18
>> > >> >     'BPF_MAP_TYPE_CGROUP_STORAGE' val=19
>> > >> >     'BPF_MAP_TYPE_REUSEPORT_SOCKARRAY' val=20
>> > >> >     'BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE' val=21
>> > >> >     'BPF_MAP_TYPE_QUEUE' val=22
>> > >> >     'BPF_MAP_TYPE_STACK' val=23
>> > >> >     'BPF_MAP_TYPE_SK_STORAGE' val=24
>> > >> >     'BPF_MAP_TYPE_DEVMAP_HASH' val=25
>> > >> >     'BPF_MAP_TYPE_STRUCT_OPS' val=26
>> > >> >     'BPF_MAP_TYPE_RINGBUF' val=27
>> > >> >     'BPF_MAP_TYPE_INODE_STORAGE' val=28
>> > >> >     'BPF_MAP_TYPE_TASK_STORAGE' val=29
>> > >> >     'BPF_MAP_TYPE_BLOOM_FILTER' val=30
>> > >> > [23] UNION '(anon)' size=8 vlen=1
>> > >> >     'flow_keys' type_id=29 bits_offset=0
>> > >> > [24] STRUCT 'bpf_flow_keys' size=56 vlen=13
>> > >> >     'nhoff' type_id=8 bits_offset=0
>> > >> >     'thoff' type_id=8 bits_offset=16
>> > >> >     'addr_proto' type_id=8 bits_offset=32
>> > >> >     'is_frag' type_id=3 bits_offset=48
>> > >> >     'is_first_frag' type_id=3 bits_offset=56
>> > >> >     'is_encap' type_id=3 bits_offset=64
>> > >> >     'ip_proto' type_id=3 bits_offset=72
>> > >> >     'n_proto' type_id=20 bits_offset=80
>> > >> >     'sport' type_id=20 bits_offset=96
>> > >> >     'dport' type_id=20 bits_offset=112
>> > >> >     '(anon)' type_id=25 bits_offset=128
>> > >> >     'flags' type_id=12 bits_offset=384
>> > >> >     'flow_label' type_id=21 bits_offset=416
>> > >> > [25] UNION '(anon)' size=32 vlen=2
>> > >> >     '(anon)' type_id=26 bits_offset=0
>> > >> >     '(anon)' type_id=27 bits_offset=0
>> > >> > [26] STRUCT '(anon)' size=8 vlen=2
>> > >> >     'ipv4_src' type_id=21 bits_offset=0
>> > >> >     'ipv4_dst' type_id=21 bits_offset=32
>> > >> > [27] STRUCT '(anon)' size=32 vlen=2
>> > >> >     'ipv6_src' type_id=28 bits_offset=0
>> > >> >     'ipv6_dst' type_id=28 bits_offset=128
>> > >> > [28] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=4
>> > >> > [29] PTR '(anon)' type_id=24
>> > >> > [30] UNION '(anon)' size=8 vlen=1
>> > >> >     'sk' type_id=32 bits_offset=0
>> > >> > [31] STRUCT 'bpf_sock' size=80 vlen=14
>> > >> >     'bound_dev_if' type_id=12 bits_offset=0
>> > >> >     'family' type_id=12 bits_offset=32
>> > >> >     'type' type_id=12 bits_offset=64
>> > >> >     'protocol' type_id=12 bits_offset=96
>> > >> >     'mark' type_id=12 bits_offset=128
>> > >> >     'priority' type_id=12 bits_offset=160
>> > >> >     'src_ip4' type_id=12 bits_offset=192
>> > >> >     'src_ip6' type_id=28 bits_offset=224
>> > >> >     'src_port' type_id=12 bits_offset=352
>> > >> >     'dst_port' type_id=20 bits_offset=384
>> > >> >     'dst_ip4' type_id=12 bits_offset=416
>> > >> >     'dst_ip6' type_id=28 bits_offset=448
>> > >> >     'state' type_id=12 bits_offset=576
>> > >> >     'rx_queue_mapping' type_id=10 bits_offset=608
>> > >> > [32] PTR '(anon)' type_id=31
>> > >> > [33] STRUCT '__sk_buff' size=192 vlen=33
>> > >> >     'len' type_id=12 bits_offset=0
>> > >> >     'pkt_type' type_id=12 bits_offset=32
>> > >> >     'mark' type_id=12 bits_offset=64
>> > >> >     'queue_mapping' type_id=12 bits_offset=96
>> > >> >     'protocol' type_id=12 bits_offset=128
>> > >> >     'vlan_present' type_id=12 bits_offset=160
>> > >> >     'vlan_tci' type_id=12 bits_offset=192
>> > >> >     'vlan_proto' type_id=12 bits_offset=224
>> > >> >     'priority' type_id=12 bits_offset=256
>> > >> >     'ingress_ifindex' type_id=12 bits_offset=288
>> > >> >     'ifindex' type_id=12 bits_offset=320
>> > >> >     'tc_index' type_id=12 bits_offset=352
>> > >> >     'cb' type_id=34 bits_offset=384
>> > >> >     'hash' type_id=12 bits_offset=544
>> > >> >     'tc_classid' type_id=12 bits_offset=576
>> > >> >     'data' type_id=12 bits_offset=608
>> > >> >     'data_end' type_id=12 bits_offset=640
>> > >> >     'napi_id' type_id=12 bits_offset=672
>> > >> >     'family' type_id=12 bits_offset=704
>> > >> >     'remote_ip4' type_id=12 bits_offset=736
>> > >> >     'local_ip4' type_id=12 bits_offset=768
>> > >> >     'remote_ip6' type_id=28 bits_offset=800
>> > >> >     'local_ip6' type_id=28 bits_offset=928
>> > >> >     'remote_port' type_id=12 bits_offset=1056
>> > >> >     'local_port' type_id=12 bits_offset=1088
>> > >> >     'data_meta' type_id=12 bits_offset=1120
>> > >> >     '(anon)' type_id=23 bits_offset=1152
>> > >> >     'tstamp' type_id=15 bits_offset=1216
>> > >> >     'wire_len' type_id=12 bits_offset=1280
>> > >> >     'gso_segs' type_id=12 bits_offset=1312
>> > >> >     '(anon)' type_id=30 bits_offset=1344
>> > >> >     'gso_size' type_id=12 bits_offset=1408
>> > >> >     'hwtstamp' type_id=15 bits_offset=1472
>> > >> > [34] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=5
>> > >> > [35] CONST '(anon)' type_id=33
>> > >> > [36] PTR '(anon)' type_id=0
>> > >> > [37] STRUCT '(anon)' size=24 vlen=3
>> > >> >     'type' type_id=39 bits_offset=0
>> > >> >     'key' type_id=40 bits_offset=64
>> > >> >     'value' type_id=41 bits_offset=128
>> > >> > [38] ARRAY '(anon)' type_id=9 index_type_id=16 nr_elems=1
>> > >> > [39] PTR '(anon)' type_id=38
>> > >> > [40] PTR '(anon)' type_id=12
>> > >> > [41] PTR '(anon)' type_id=3
>> > >> > [42] ARRAY '(anon)' type_id=19 index_type_id=16 nr_elems=18
>> > >> > [43] CONST '(anon)' type_id=42
>> > >> > [44] FUNC_PROTO '(anon)' ret_type_id=36 vlen=2
>> > >> >     '(anon)' type_id=36
>> > >> >     '(anon)' type_id=46
>> > >> > [45] CONST '(anon)' type_id=0
>> > >> > [46] PTR '(anon)' type_id=45
>> > >> > [47] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>> > >> >     'sk' type_id=48
>> > >> > [48] PTR '(anon)' type_id=35
>> > >> > [49] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>> > >> >     'sk' type_id=48
>> > >> > [50] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>> > >> >     'sk' type_id=48
>> > >> > [51] VAR '_license' type_id=43, linkage=static
>> > >> > [52] VAR 'is_allow_list' type_id=5, linkage=global
>> > >> > [53] VAR 'sd_restrictif' type_id=37, linkage=global
>> > >> > [54] FUNC 'bpf_map_lookup_elem' type_id=44 linkage=global
>> > >> > [55] FUNC 'sd_restrictif_i' type_id=47 linkage=global
>> > >> > [56] FUNC 'sd_restrictif_e' type_id=49 linkage=global
>> > >> > [57] FUNC 'restrict_network_interfaces_impl' type_id=50 linkage=static
>> > >> > [58] DATASEC 'license' size=0 vlen=1
>> > >> >     type_id=51 offset=0 size=18 (VAR '_license')
>> > >> > [59] DATASEC '.maps' size=0 vlen=1
>> > >> >     type_id=53 offset=0 size=24 (VAR 'sd_restrictif')
>> > >> > [60] DATASEC '.data' size=0 vlen=1
>> > >> >     type_id=52 offset=0 size=1 (VAR 'is_allow_list')
>> > >> >
>> > >> >>
>> > >> >> >> GCC is wrong, clearly. This function is global ([0]) and libbpf
>> > >> >> >> expects it to be marked as such in BTF.
>> > >> >> >>
>> > >> >> >>
>> > >> >
> https://github.com/systemd/systemd/blob/main/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.c#L42-L50
>> > >> >> >>
>> > >> >> >>
>> > >> >> >>> GCC:
>> > >> >> >>>
>> > >> >> >>> [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>> > >> >> >>> [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
>> > >> >> >>> [3] TYPEDEF '__u8' type_id=2
>> > >> >> >>> [4] CONST '(anon)' type_id=3
>> > >> >> >>
>> > >> >> >> [...]

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-07-09 22:41                   ` Jose E. Marchesi
@ 2022-07-09 22:54                     ` James Hilliard
  2022-07-10  9:38                       ` Jose E. Marchesi
  0 siblings, 1 reply; 38+ messages in thread
From: James Hilliard @ 2022-07-09 22:54 UTC (permalink / raw)
  To: Jose E. Marchesi; +Cc: Andrii Nakryiko, bpf, david.faust

On Sat, Jul 9, 2022 at 4:41 PM Jose E. Marchesi
<jose.marchesi@oracle.com> wrote:
>
>
> > On Sat, Jul 9, 2022 at 2:32 PM James Hilliard <james.hilliard1@gmail.com> wrote:
> >>
> >> On Sat, Jul 9, 2022 at 2:21 PM Jose E. Marchesi
> >> <jose.marchesi@oracle.com> wrote:
> >> >
> >> >
> >> > > On Sat, Jul 9, 2022 at 11:24 AM Jose E. Marchesi
> >> > > <jose.marchesi@oracle.com> wrote:
> >> > >>
> >> > >>
> >> > >> > On Fri, Jul 8, 2022 at 12:33 PM Jose E. Marchesi
> >> > >> > <jose.marchesi@oracle.com> wrote:
> >> > >> >>
> >> > >> >>
> >> > >> >> >> On Wed, Jul 6, 2022 at 10:13 AM James Hilliard
> >> > >> >> >> <james.hilliard1@gmail.com> wrote:
> >> > >> >> >>>
> >> > >> >> >>> Note I'm testing with the following patches:
> >> > >> >> >>> https://lore.kernel.org/bpf/20220706111839.1247911-1-james.hilliard1@gmail.com/
> >> > >> >> >>> https://lore.kernel.org/bpf/20220706140623.2917858-1-james.hilliard1@gmail.com/
> >> > >> >> >>>
> >> > >> >> >>> It would appear there's some compatibility issues with bpftool gen and
> >> > >> >> >>> GCC, not sure what side though is wrong here:
> >> > >> >> >>> /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> >> > >> >> >>> gen object src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> >> > >> >> >>> src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
> >> > >> >> >>> libbpf: failed to find BTF info for global/extern symbol 'sd_restrictif_i'
> >> > >> >> >>> Error: failed to link
> >> > >> >> >>> 'src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o':
> >> > >> >> >>> Unknown error -2 (-2)
> >> > >> >> >>>
> >> > >> >> >>> Relevant difference seems to be this:
> >> > >> >> >>> GCC:
> >> > >> >> >>> [55] FUNC 'sd_restrictif_i' type_id=47 linkage=static
> >> > >> >> >>> Clang:
> >> > >> >> >>> [27] FUNC 'sd_restrictif_i' type_id=26 linkage=global
> >> > >> >> >
> >> > >> >> > For functions GCC generates a BTF_KIND_FUNC entry, which has no linkage
> >> > >> >> > information, or so we thought: I just looked at bpftool/btf.c and I
> >> > >> >> > found the linkage info for function types is expected to be encoded in
> >> > >> >> > the vlen field of BTF_KIND_FUNC entries (why not adding a btf_func
> >> > >> >> > instead???) which is surprising to say the least.
> >> > >> >> >
> >> > >> >> > We are changing GCC to encode the linkage info in vlen for these types.
> >> > >> >> > Thanks for reporting this.
> >> > >> >>
> >> > >> >> Patch sent to GCC upstream:
> >> > >> >> https://gcc.gnu.org/pipermail/gcc-patches/2022-July/598090.html
> >> > >> >
> >> > >> > I applied that patch on top of GCC 12.1.0 and it appears to fix the
> >> > >> > bpftool gen object bug.
> >> > >> >
> >> > >> > I am however now hitting a different error during skeleton generation:
> >> > >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> >> > >> > gen skeleton src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> >> > >> > libbpf: elf: skipping unrecognized data section(9) .comment
> >> > >> > libbpf: failed to alloc map 'restrict.bss' content buffer: -22
> >> > >> > Error: failed to open BPF object file: Invalid argument
> >> > >>
> >> > >> What is the size of the .bss section in the object file?  Try with:
> >> > >>
> >> > >> $ size restrict-ifaces.bpf.o
> >> > >
> >> > > $ size
> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> >> > >    text       data        bss        dec        hex    filename
> >> > >     386         25          0        411        19b
> >> > > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> >> >
> >> > Right, so the .bss section is empty.  I see a `const volatile unsigned
> >> > char is_allow_list = 0;' in restrict-ifaces.bpf.c, but that goes to
> >> > .data and not to .bss, as expected.
> >> >
> >> > If you build restrict-ifaces.bpf.o with LLVM, is the bss still empty?  I
> >> > don't think the code in libbpf.c even checks for this eventuality...
> >>
> >> LLVM version(which skeleton generation works with):
> >> $ size restrict-ifaces.bpf.o
> >>    text       data        bss        dec        hex    filename
> >>     323         24          0        347        15b    restrict-ifaces.bpf.o
> >>
> >> $ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> >> btf dump file restrict-ifaces.bpf.o format raw
> >> [1] PTR '(anon)' type_id=3
> >> [2] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
> >> [3] ARRAY '(anon)' type_id=2 index_type_id=4 nr_elems=1
> >> [4] INT '__ARRAY_SIZE_TYPE__' size=4 bits_offset=0 nr_bits=32 encoding=(none)
> >> [5] PTR '(anon)' type_id=6
> >> [6] TYPEDEF '__u32' type_id=7
> >> [7] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
> >> [8] PTR '(anon)' type_id=9
> >> [9] TYPEDEF '__u8' type_id=10
> >> [10] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=(none)
> >> [11] STRUCT '(anon)' size=24 vlen=3
> >>     'type' type_id=1 bits_offset=0
> >>     'key' type_id=5 bits_offset=64
> >>     'value' type_id=8 bits_offset=128
> >> [12] VAR 'sd_restrictif' type_id=11, linkage=global
> >> [13] PTR '(anon)' type_id=14
> >> [14] CONST '(anon)' type_id=15
> >> [15] STRUCT '__sk_buff' size=192 vlen=33
> >>     'len' type_id=6 bits_offset=0
> >>     'pkt_type' type_id=6 bits_offset=32
> >>     'mark' type_id=6 bits_offset=64
> >>     'queue_mapping' type_id=6 bits_offset=96
> >>     'protocol' type_id=6 bits_offset=128
> >>     'vlan_present' type_id=6 bits_offset=160
> >>     'vlan_tci' type_id=6 bits_offset=192
> >>     'vlan_proto' type_id=6 bits_offset=224
> >>     'priority' type_id=6 bits_offset=256
> >>     'ingress_ifindex' type_id=6 bits_offset=288
> >>     'ifindex' type_id=6 bits_offset=320
> >>     'tc_index' type_id=6 bits_offset=352
> >>     'cb' type_id=16 bits_offset=384
> >>     'hash' type_id=6 bits_offset=544
> >>     'tc_classid' type_id=6 bits_offset=576
> >>     'data' type_id=6 bits_offset=608
> >>     'data_end' type_id=6 bits_offset=640
> >>     'napi_id' type_id=6 bits_offset=672
> >>     'family' type_id=6 bits_offset=704
> >>     'remote_ip4' type_id=6 bits_offset=736
> >>     'local_ip4' type_id=6 bits_offset=768
> >>     'remote_ip6' type_id=17 bits_offset=800
> >>     'local_ip6' type_id=17 bits_offset=928
> >>     'remote_port' type_id=6 bits_offset=1056
> >>     'local_port' type_id=6 bits_offset=1088
> >>     'data_meta' type_id=6 bits_offset=1120
> >>     '(anon)' type_id=18 bits_offset=1152
> >>     'tstamp' type_id=20 bits_offset=1216
> >>     'wire_len' type_id=6 bits_offset=1280
> >>     'gso_segs' type_id=6 bits_offset=1312
> >>     '(anon)' type_id=22 bits_offset=1344
> >>     'gso_size' type_id=6 bits_offset=1408
> >>     'hwtstamp' type_id=20 bits_offset=1472
> >> [16] ARRAY '(anon)' type_id=6 index_type_id=4 nr_elems=5
> >> [17] ARRAY '(anon)' type_id=6 index_type_id=4 nr_elems=4
> >> [18] UNION '(anon)' size=8 vlen=1
> >>     'flow_keys' type_id=19 bits_offset=0
> >> [19] PTR '(anon)' type_id=34
> >> [20] TYPEDEF '__u64' type_id=21
> >> [21] INT 'unsigned long long' size=8 bits_offset=0 nr_bits=64 encoding=(none)
> >> [22] UNION '(anon)' size=8 vlen=1
> >>     'sk' type_id=23 bits_offset=0
> >> [23] PTR '(anon)' type_id=35
> >> [24] FUNC_PROTO '(anon)' ret_type_id=2 vlen=1
> >>     'sk' type_id=13
> >> [25] FUNC 'sd_restrictif_e' type_id=24 linkage=global
> >> [26] FUNC 'sd_restrictif_i' type_id=24 linkage=global
> >> [27] CONST '(anon)' type_id=28
> >> [28] VOLATILE '(anon)' type_id=9
> >> [29] VAR 'is_allow_list' type_id=27, linkage=global
> >> [30] CONST '(anon)' type_id=31
> >> [31] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=SIGNED
> >> [32] ARRAY '(anon)' type_id=30 index_type_id=4 nr_elems=18
> >> [33] VAR '_license' type_id=32, linkage=static
> >> [34] FWD 'bpf_flow_keys' fwd_kind=struct
> >> [35] FWD 'bpf_sock' fwd_kind=struct
> >> [36] DATASEC '.rodata' size=1 vlen=1
> >>     type_id=29 offset=0 size=1 (VAR 'is_allow_list')
> >> [37] DATASEC 'license' size=18 vlen=1
> >>     type_id=33 offset=0 size=18 (VAR '_license')
> >> [38] DATASEC '.maps' size=24 vlen=1
> >>     type_id=12 offset=0 size=24 (VAR 'sd_restrictif')
> >>
> >
> > Skeleton generation debug output for GCC(failing) and LLVM(working)
> > which may be helpful:
>
> Indeed it was helpful :)
>
> The GNU assembler generates an empty .bss section.  This is a well
> established behavior in GAS that happens in all supported targets.
>
> The LLVM assembler doesn't generate an empty .bss section.
>
> bpftool chokes on the empty .bss section.
>
> In this case I would suggest to fix bpf_object__init_global_data_maps in
> order to skip empty sections.
>
> Something like this:

Hmm, that seems to segfault:
Starting program:
/home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
--debug gen skeleton
output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".
libbpf: loading object 'restrict_ifaces_bpf' from buffer
libbpf: elf: section(2) .symtab, size 336, link 1, flags 0, type=2
libbpf: elf: section(3) .data, size 1, link 0, flags 3, type=1
libbpf: elf: section(4) .bss, size 0, link 0, flags 3, type=8
libbpf: elf: section(5) cgroup_skb/egress, size 184, link 0, flags 6, type=1
libbpf: sec 'cgroup_skb/egress': found program 'sd_restrictif_e' at
insn offset 0 (0 bytes), code size 23 insns (184 bytes)
libbpf: elf: section(6) cgroup_skb/ingress, size 184, link 0, flags 6, type=1
libbpf: sec 'cgroup_skb/ingress': found program 'sd_restrictif_i' at
insn offset 0 (0 bytes), code size 23 insns (184 bytes)
libbpf: elf: section(7) license, size 18, link 0, flags 2, type=1
libbpf: license of restrict_ifaces_bpf is LGPL-2.1-or-later
libbpf: elf: section(8) .maps, size 24, link 0, flags 3, type=1
libbpf: elf: section(9) .comment, size 49, link 0, flags 30, type=1
libbpf: elf: skipping unrecognized data section(9) .comment
libbpf: elf: section(10) .relcgroup_skb/egress, size 32, link 2, flags
40, type=9
libbpf: elf: section(11) .relcgroup_skb/ingress, size 32, link 2,
flags 40, type=9
libbpf: elf: section(12) .BTF, size 3606, link 0, flags 0, type=1
libbpf: looking for externs among 14 symbols...
libbpf: collected 0 externs total
libbpf: map 'sd_restrictif': at sec_idx 8, offset 0.
libbpf: map 'sd_restrictif': found type = 1.
libbpf: map 'sd_restrictif': found key [12], sz = 4.
libbpf: map 'sd_restrictif': found value [3], sz = 1.

Program received signal SIGSEGV, Segmentation fault.
0x0000aaaaaab4fd2c in bpf_object.init_maps ()
(gdb) bt
#0  0x0000aaaaaab4fd2c in bpf_object.init_maps ()
#1  0x0000aaaaaab52178 in bpf_object_open.part ()
#2  0x0000aaaaaab544e8 in bpf_object.open_mem ()
#3  0x0000aaaaaab2a58c in do_skeleton ()
#4  0x0000aaaaaab1e204 in main ()

>
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index e89cc9c885b3..e3a6808f0bb6 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -1591,6 +1591,10 @@ static int bpf_object__init_global_data_maps(struct bpf_object *obj)
>         for (sec_idx = 1; sec_idx < obj->efile.sec_cnt; sec_idx++) {
>                 sec_desc = &obj->efile.secs[sec_idx];
>
> +                /* Skip empty sections.  */
> +                if (sec_desc->data->d_size == 0)
> +                  continue;
> +
>                 switch (sec_desc->sec_type) {
>                 case SEC_DATA:
>                         sec_name = elf_sec_name(obj, elf_sec_by_idx(obj, sec_idx));
>
> > GCC:
> > $ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> > --debug gen skeleton
> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> > libbpf: loading object 'restrict_ifaces_bpf' from buffer
> > libbpf: elf: section(2) .symtab, size 336, link 1, flags 0, type=2
> > libbpf: elf: section(3) .data, size 1, link 0, flags 3, type=1
> > libbpf: elf: section(4) .bss, size 0, link 0, flags 3, type=8
> > libbpf: elf: section(5) cgroup_skb/egress, size 184, link 0, flags 6, type=1
> > libbpf: sec 'cgroup_skb/egress': found program 'sd_restrictif_e' at
> > insn offset 0 (0 bytes), code size 23 insns (184 bytes)
> > libbpf: elf: section(6) cgroup_skb/ingress, size 184, link 0, flags 6, type=1
> > libbpf: sec 'cgroup_skb/ingress': found program 'sd_restrictif_i' at
> > insn offset 0 (0 bytes), code size 23 insns (184 bytes)
> > libbpf: elf: section(7) license, size 18, link 0, flags 2, type=1
> > libbpf: license of restrict_ifaces_bpf is LGPL-2.1-or-later
> > libbpf: elf: section(8) .maps, size 24, link 0, flags 3, type=1
> > libbpf: elf: section(9) .comment, size 49, link 0, flags 30, type=1
> > libbpf: elf: skipping unrecognized data section(9) .comment
> > libbpf: elf: section(10) .relcgroup_skb/egress, size 32, link 2, flags
> > 40, type=9
> > libbpf: elf: section(11) .relcgroup_skb/ingress, size 32, link 2,
> > flags 40, type=9
> > libbpf: elf: section(12) .BTF, size 3606, link 0, flags 0, type=1
> > libbpf: looking for externs among 14 symbols...
> > libbpf: collected 0 externs total
> > libbpf: map 'sd_restrictif': at sec_idx 8, offset 0.
> > libbpf: map 'sd_restrictif': found type = 1.
> > libbpf: map 'sd_restrictif': found key [12], sz = 4.
> > libbpf: map 'sd_restrictif': found value [3], sz = 1.
> > libbpf: map 'restrict.data' (global data): at sec_idx 3, offset 0, flags 400.
> > libbpf: map 1 is "restrict.data"
> > libbpf: map 'restrict.bss' (global data): at sec_idx 4, offset 0, flags 400.
> > libbpf: failed to alloc map 'restrict.bss' content buffer: -22
> > Error: failed to open BPF object file: Invalid argument
> >
> > LLVM:
> > $ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> > --debug gen skeleton restrict-ifaces.bpf.o
> > libbpf: loading object 'restrict_ifaces_bpf' from buffer
> > libbpf: elf: section(2) .symtab, size 384, link 1, flags 0, type=2
> > libbpf: elf: section(3) cgroup_skb/egress, size 152, link 0, flags 6, type=1
> > libbpf: sec 'cgroup_skb/egress': found program 'sd_restrictif_e' at
> > insn offset 0 (0 bytes), code size 19 insns (152 bytes)
> > libbpf: elf: section(4) cgroup_skb/ingress, size 152, link 0, flags 6, type=1
> > libbpf: sec 'cgroup_skb/ingress': found program 'sd_restrictif_i' at
> > insn offset 0 (0 bytes), code size 19 insns (152 bytes)
> > libbpf: elf: section(5) .rodata, size 1, link 0, flags 2, type=1
> > libbpf: elf: section(6) license, size 18, link 0, flags 2, type=1
> > libbpf: license of restrict_ifaces_bpf is LGPL-2.1-or-later
> > libbpf: elf: section(7) .maps, size 24, link 0, flags 3, type=1
> > libbpf: elf: section(8) .relcgroup_skb/egress, size 32, link 2, flags 40, type=9
> > libbpf: elf: section(9) .relcgroup_skb/ingress, size 32, link 2, flags
> > 40, type=9
> > libbpf: elf: section(10) .BTF, size 1988, link 0, flags 0, type=1
> > libbpf: elf: section(11) .BTF.ext, size 376, link 0, flags 0, type=1
> > libbpf: looking for externs among 16 symbols...
> > libbpf: collected 0 externs total
> > libbpf: map 'sd_restrictif': at sec_idx 7, offset 0.
> > libbpf: map 'sd_restrictif': found type = 1.
> > libbpf: map 'sd_restrictif': found key [6], sz = 4.
> > libbpf: map 'sd_restrictif': found value [9], sz = 1.
> > libbpf: map 'restrict.rodata' (global data): at sec_idx 5, offset 0, flags 480.
> > libbpf: map 1 is "restrict.rodata"
> > libbpf: sec '.relcgroup_skb/egress': collecting relocation for
> > section(3) 'cgroup_skb/egress'
> > libbpf: sec '.relcgroup_skb/egress': relo #0: insn #4 against 'sd_restrictif'
> > libbpf: prog 'sd_restrictif_e': found map 0 (sd_restrictif, sec 7, off
> > 0) for insn #4
> > libbpf: sec '.relcgroup_skb/egress': relo #1: insn #7 against 'is_allow_list'
> > libbpf: prog 'sd_restrictif_e': found data map 1 (restrict.rodata, sec
> > 5, off 0) for insn 7
> > libbpf: sec '.relcgroup_skb/ingress': collecting relocation for
> > section(4) 'cgroup_skb/ingress'
> > libbpf: sec '.relcgroup_skb/ingress': relo #0: insn #4 against 'sd_restrictif'
> > libbpf: prog 'sd_restrictif_i': found map 0 (sd_restrictif, sec 7, off
> > 0) for insn #4
> > libbpf: sec '.relcgroup_skb/ingress': relo #1: insn #7 against 'is_allow_list'
> > libbpf: prog 'sd_restrictif_i': found data map 1 (restrict.rodata, sec
> > 5, off 0) for insn 7
> >
> >> >
> >> > >>
> >> > >> Looking at libbpf.c, it seems to me that this may be due of trying to
> >> > >> mmap 0 bytes in `bpf_object__init_internal_map':
> >> > >>
> >> > >>         map->mmaped = mmap(NULL, bpf_map_mmap_sz(map), PROT_READ | PROT_WRITE,
> >> > >>                            MAP_SHARED | MAP_ANONYMOUS, -1, 0);
> >> > >>         if (map->mmaped == MAP_FAILED) {
> >> > >>                 err = -errno;
> >> > >>                 map->mmaped = NULL;
> >> > >>                 pr_warn("failed to alloc map '%s' content buffer: %d\n",
> >> > >>                         map->name, err);
> >> > >>                 zfree(&map->real_name);
> >> > >>                 zfree(&map->name);
> >> > >>                 return err;
> >> > >>         }
> >> > >>
> >> > >> I see no check for zero sized sections in
> >> > >> bpf_object__init_global_data_maps.
> >> > >>
> >> > >> Is maybe GCC failing to allocate stuff in BSS that is supposed to be
> >> > >> there?
> >> > >>
> >> > >> > Stripped file passed to gen skeleton:
> >> > >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> >> > >> > btf dump file
> >> > >> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> >> > >> > format raw
> >> > >> > [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> >> > >> > [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
> >> > >> > [3] TYPEDEF '__u8' type_id=2
> >> > >> > [4] CONST '(anon)' type_id=3
> >> > >> > [5] VOLATILE '(anon)' type_id=4
> >> > >> > [6] INT 'short int' size=2 bits_offset=0 nr_bits=16 encoding=SIGNED
> >> > >> > [7] INT 'short unsigned int' size=2 bits_offset=0 nr_bits=16 encoding=(none)
> >> > >> > [8] TYPEDEF '__u16' type_id=7
> >> > >> > [9] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
> >> > >> > [10] TYPEDEF '__s32' type_id=9
> >> > >> > [11] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
> >> > >> > [12] TYPEDEF '__u32' type_id=11
> >> > >> > [13] INT 'long long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
> >> > >> > [14] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64
> >> > >> > encoding=(none)
> >> > >> > [15] TYPEDEF '__u64' type_id=14
> >> > >> > [16] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
> >> > >> > [17] INT 'long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
> >> > >> > [18] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> >> > >> > [19] CONST '(anon)' type_id=18
> >> > >> > [20] TYPEDEF '__be16' type_id=8
> >> > >> > [21] TYPEDEF '__be32' type_id=12
> >> > >> > [22] ENUM 'bpf_map_type' encoding=UNSIGNED size=4 vlen=31
> >> > >> >     'BPF_MAP_TYPE_UNSPEC' val=0
> >> > >> >     'BPF_MAP_TYPE_HASH' val=1
> >> > >> >     'BPF_MAP_TYPE_ARRAY' val=2
> >> > >> >     'BPF_MAP_TYPE_PROG_ARRAY' val=3
> >> > >> >     'BPF_MAP_TYPE_PERF_EVENT_ARRAY' val=4
> >> > >> >     'BPF_MAP_TYPE_PERCPU_HASH' val=5
> >> > >> >     'BPF_MAP_TYPE_PERCPU_ARRAY' val=6
> >> > >> >     'BPF_MAP_TYPE_STACK_TRACE' val=7
> >> > >> >     'BPF_MAP_TYPE_CGROUP_ARRAY' val=8
> >> > >> >     'BPF_MAP_TYPE_LRU_HASH' val=9
> >> > >> >     'BPF_MAP_TYPE_LRU_PERCPU_HASH' val=10
> >> > >> >     'BPF_MAP_TYPE_LPM_TRIE' val=11
> >> > >> >     'BPF_MAP_TYPE_ARRAY_OF_MAPS' val=12
> >> > >> >     'BPF_MAP_TYPE_HASH_OF_MAPS' val=13
> >> > >> >     'BPF_MAP_TYPE_DEVMAP' val=14
> >> > >> >     'BPF_MAP_TYPE_SOCKMAP' val=15
> >> > >> >     'BPF_MAP_TYPE_CPUMAP' val=16
> >> > >> >     'BPF_MAP_TYPE_XSKMAP' val=17
> >> > >> >     'BPF_MAP_TYPE_SOCKHASH' val=18
> >> > >> >     'BPF_MAP_TYPE_CGROUP_STORAGE' val=19
> >> > >> >     'BPF_MAP_TYPE_REUSEPORT_SOCKARRAY' val=20
> >> > >> >     'BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE' val=21
> >> > >> >     'BPF_MAP_TYPE_QUEUE' val=22
> >> > >> >     'BPF_MAP_TYPE_STACK' val=23
> >> > >> >     'BPF_MAP_TYPE_SK_STORAGE' val=24
> >> > >> >     'BPF_MAP_TYPE_DEVMAP_HASH' val=25
> >> > >> >     'BPF_MAP_TYPE_STRUCT_OPS' val=26
> >> > >> >     'BPF_MAP_TYPE_RINGBUF' val=27
> >> > >> >     'BPF_MAP_TYPE_INODE_STORAGE' val=28
> >> > >> >     'BPF_MAP_TYPE_TASK_STORAGE' val=29
> >> > >> >     'BPF_MAP_TYPE_BLOOM_FILTER' val=30
> >> > >> > [23] UNION '(anon)' size=8 vlen=1
> >> > >> >     'flow_keys' type_id=29 bits_offset=0
> >> > >> > [24] STRUCT 'bpf_flow_keys' size=56 vlen=13
> >> > >> >     'nhoff' type_id=8 bits_offset=0
> >> > >> >     'thoff' type_id=8 bits_offset=16
> >> > >> >     'addr_proto' type_id=8 bits_offset=32
> >> > >> >     'is_frag' type_id=3 bits_offset=48
> >> > >> >     'is_first_frag' type_id=3 bits_offset=56
> >> > >> >     'is_encap' type_id=3 bits_offset=64
> >> > >> >     'ip_proto' type_id=3 bits_offset=72
> >> > >> >     'n_proto' type_id=20 bits_offset=80
> >> > >> >     'sport' type_id=20 bits_offset=96
> >> > >> >     'dport' type_id=20 bits_offset=112
> >> > >> >     '(anon)' type_id=25 bits_offset=128
> >> > >> >     'flags' type_id=12 bits_offset=384
> >> > >> >     'flow_label' type_id=21 bits_offset=416
> >> > >> > [25] UNION '(anon)' size=32 vlen=2
> >> > >> >     '(anon)' type_id=26 bits_offset=0
> >> > >> >     '(anon)' type_id=27 bits_offset=0
> >> > >> > [26] STRUCT '(anon)' size=8 vlen=2
> >> > >> >     'ipv4_src' type_id=21 bits_offset=0
> >> > >> >     'ipv4_dst' type_id=21 bits_offset=32
> >> > >> > [27] STRUCT '(anon)' size=32 vlen=2
> >> > >> >     'ipv6_src' type_id=28 bits_offset=0
> >> > >> >     'ipv6_dst' type_id=28 bits_offset=128
> >> > >> > [28] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=4
> >> > >> > [29] PTR '(anon)' type_id=24
> >> > >> > [30] UNION '(anon)' size=8 vlen=1
> >> > >> >     'sk' type_id=32 bits_offset=0
> >> > >> > [31] STRUCT 'bpf_sock' size=80 vlen=14
> >> > >> >     'bound_dev_if' type_id=12 bits_offset=0
> >> > >> >     'family' type_id=12 bits_offset=32
> >> > >> >     'type' type_id=12 bits_offset=64
> >> > >> >     'protocol' type_id=12 bits_offset=96
> >> > >> >     'mark' type_id=12 bits_offset=128
> >> > >> >     'priority' type_id=12 bits_offset=160
> >> > >> >     'src_ip4' type_id=12 bits_offset=192
> >> > >> >     'src_ip6' type_id=28 bits_offset=224
> >> > >> >     'src_port' type_id=12 bits_offset=352
> >> > >> >     'dst_port' type_id=20 bits_offset=384
> >> > >> >     'dst_ip4' type_id=12 bits_offset=416
> >> > >> >     'dst_ip6' type_id=28 bits_offset=448
> >> > >> >     'state' type_id=12 bits_offset=576
> >> > >> >     'rx_queue_mapping' type_id=10 bits_offset=608
> >> > >> > [32] PTR '(anon)' type_id=31
> >> > >> > [33] STRUCT '__sk_buff' size=192 vlen=33
> >> > >> >     'len' type_id=12 bits_offset=0
> >> > >> >     'pkt_type' type_id=12 bits_offset=32
> >> > >> >     'mark' type_id=12 bits_offset=64
> >> > >> >     'queue_mapping' type_id=12 bits_offset=96
> >> > >> >     'protocol' type_id=12 bits_offset=128
> >> > >> >     'vlan_present' type_id=12 bits_offset=160
> >> > >> >     'vlan_tci' type_id=12 bits_offset=192
> >> > >> >     'vlan_proto' type_id=12 bits_offset=224
> >> > >> >     'priority' type_id=12 bits_offset=256
> >> > >> >     'ingress_ifindex' type_id=12 bits_offset=288
> >> > >> >     'ifindex' type_id=12 bits_offset=320
> >> > >> >     'tc_index' type_id=12 bits_offset=352
> >> > >> >     'cb' type_id=34 bits_offset=384
> >> > >> >     'hash' type_id=12 bits_offset=544
> >> > >> >     'tc_classid' type_id=12 bits_offset=576
> >> > >> >     'data' type_id=12 bits_offset=608
> >> > >> >     'data_end' type_id=12 bits_offset=640
> >> > >> >     'napi_id' type_id=12 bits_offset=672
> >> > >> >     'family' type_id=12 bits_offset=704
> >> > >> >     'remote_ip4' type_id=12 bits_offset=736
> >> > >> >     'local_ip4' type_id=12 bits_offset=768
> >> > >> >     'remote_ip6' type_id=28 bits_offset=800
> >> > >> >     'local_ip6' type_id=28 bits_offset=928
> >> > >> >     'remote_port' type_id=12 bits_offset=1056
> >> > >> >     'local_port' type_id=12 bits_offset=1088
> >> > >> >     'data_meta' type_id=12 bits_offset=1120
> >> > >> >     '(anon)' type_id=23 bits_offset=1152
> >> > >> >     'tstamp' type_id=15 bits_offset=1216
> >> > >> >     'wire_len' type_id=12 bits_offset=1280
> >> > >> >     'gso_segs' type_id=12 bits_offset=1312
> >> > >> >     '(anon)' type_id=30 bits_offset=1344
> >> > >> >     'gso_size' type_id=12 bits_offset=1408
> >> > >> >     'hwtstamp' type_id=15 bits_offset=1472
> >> > >> > [34] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=5
> >> > >> > [35] CONST '(anon)' type_id=33
> >> > >> > [36] PTR '(anon)' type_id=0
> >> > >> > [37] STRUCT '(anon)' size=24 vlen=3
> >> > >> >     'type' type_id=39 bits_offset=0
> >> > >> >     'key' type_id=40 bits_offset=64
> >> > >> >     'value' type_id=41 bits_offset=128
> >> > >> > [38] ARRAY '(anon)' type_id=9 index_type_id=16 nr_elems=1
> >> > >> > [39] PTR '(anon)' type_id=38
> >> > >> > [40] PTR '(anon)' type_id=12
> >> > >> > [41] PTR '(anon)' type_id=3
> >> > >> > [42] ARRAY '(anon)' type_id=19 index_type_id=16 nr_elems=18
> >> > >> > [43] CONST '(anon)' type_id=42
> >> > >> > [44] FUNC_PROTO '(anon)' ret_type_id=36 vlen=2
> >> > >> >     '(anon)' type_id=36
> >> > >> >     '(anon)' type_id=46
> >> > >> > [45] CONST '(anon)' type_id=0
> >> > >> > [46] PTR '(anon)' type_id=45
> >> > >> > [47] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
> >> > >> >     'sk' type_id=48
> >> > >> > [48] PTR '(anon)' type_id=35
> >> > >> > [49] VAR '_license' type_id=43, linkage=static
> >> > >> > [50] VAR 'is_allow_list' type_id=5, linkage=global
> >> > >> > [51] VAR 'sd_restrictif' type_id=37, linkage=global
> >> > >> > [52] FUNC 'sd_restrictif_i' type_id=47 linkage=global
> >> > >> > [53] FUNC 'sd_restrictif_e' type_id=47 linkage=global
> >> > >> > [54] FUNC 'restrict_network_interfaces_impl' type_id=47 linkage=static
> >> > >> > [55] DATASEC '.data' size=1 vlen=1
> >> > >> >     type_id=50 offset=0 size=1 (VAR 'is_allow_list')
> >> > >> > [56] DATASEC 'license' size=18 vlen=1
> >> > >> >     type_id=49 offset=0 size=18 (VAR '_license')
> >> > >> > [57] DATASEC '.maps' size=24 vlen=1
> >> > >> >     type_id=51 offset=0 size=24 (VAR 'sd_restrictif')
> >> > >> >
> >> > >> > File before being stripped using bpftool gen object:
> >> > >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> >> > >> > btf dump file
> >> > >> >
> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
> >> > >> > format raw
> >> > >> > [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> >> > >> > [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
> >> > >> > [3] TYPEDEF '__u8' type_id=2
> >> > >> > [4] CONST '(anon)' type_id=3
> >> > >> > [5] VOLATILE '(anon)' type_id=4
> >> > >> > [6] INT 'short int' size=2 bits_offset=0 nr_bits=16 encoding=SIGNED
> >> > >> > [7] INT 'short unsigned int' size=2 bits_offset=0 nr_bits=16 encoding=(none)
> >> > >> > [8] TYPEDEF '__u16' type_id=7
> >> > >> > [9] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
> >> > >> > [10] TYPEDEF '__s32' type_id=9
> >> > >> > [11] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
> >> > >> > [12] TYPEDEF '__u32' type_id=11
> >> > >> > [13] INT 'long long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
> >> > >> > [14] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64
> >> > >> > encoding=(none)
> >> > >> > [15] TYPEDEF '__u64' type_id=14
> >> > >> > [16] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
> >> > >> > [17] INT 'long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
> >> > >> > [18] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> >> > >> > [19] CONST '(anon)' type_id=18
> >> > >> > [20] TYPEDEF '__be16' type_id=8
> >> > >> > [21] TYPEDEF '__be32' type_id=12
> >> > >> > [22] ENUM 'bpf_map_type' encoding=UNSIGNED size=4 vlen=31
> >> > >> >     'BPF_MAP_TYPE_UNSPEC' val=0
> >> > >> >     'BPF_MAP_TYPE_HASH' val=1
> >> > >> >     'BPF_MAP_TYPE_ARRAY' val=2
> >> > >> >     'BPF_MAP_TYPE_PROG_ARRAY' val=3
> >> > >> >     'BPF_MAP_TYPE_PERF_EVENT_ARRAY' val=4
> >> > >> >     'BPF_MAP_TYPE_PERCPU_HASH' val=5
> >> > >> >     'BPF_MAP_TYPE_PERCPU_ARRAY' val=6
> >> > >> >     'BPF_MAP_TYPE_STACK_TRACE' val=7
> >> > >> >     'BPF_MAP_TYPE_CGROUP_ARRAY' val=8
> >> > >> >     'BPF_MAP_TYPE_LRU_HASH' val=9
> >> > >> >     'BPF_MAP_TYPE_LRU_PERCPU_HASH' val=10
> >> > >> >     'BPF_MAP_TYPE_LPM_TRIE' val=11
> >> > >> >     'BPF_MAP_TYPE_ARRAY_OF_MAPS' val=12
> >> > >> >     'BPF_MAP_TYPE_HASH_OF_MAPS' val=13
> >> > >> >     'BPF_MAP_TYPE_DEVMAP' val=14
> >> > >> >     'BPF_MAP_TYPE_SOCKMAP' val=15
> >> > >> >     'BPF_MAP_TYPE_CPUMAP' val=16
> >> > >> >     'BPF_MAP_TYPE_XSKMAP' val=17
> >> > >> >     'BPF_MAP_TYPE_SOCKHASH' val=18
> >> > >> >     'BPF_MAP_TYPE_CGROUP_STORAGE' val=19
> >> > >> >     'BPF_MAP_TYPE_REUSEPORT_SOCKARRAY' val=20
> >> > >> >     'BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE' val=21
> >> > >> >     'BPF_MAP_TYPE_QUEUE' val=22
> >> > >> >     'BPF_MAP_TYPE_STACK' val=23
> >> > >> >     'BPF_MAP_TYPE_SK_STORAGE' val=24
> >> > >> >     'BPF_MAP_TYPE_DEVMAP_HASH' val=25
> >> > >> >     'BPF_MAP_TYPE_STRUCT_OPS' val=26
> >> > >> >     'BPF_MAP_TYPE_RINGBUF' val=27
> >> > >> >     'BPF_MAP_TYPE_INODE_STORAGE' val=28
> >> > >> >     'BPF_MAP_TYPE_TASK_STORAGE' val=29
> >> > >> >     'BPF_MAP_TYPE_BLOOM_FILTER' val=30
> >> > >> > [23] UNION '(anon)' size=8 vlen=1
> >> > >> >     'flow_keys' type_id=29 bits_offset=0
> >> > >> > [24] STRUCT 'bpf_flow_keys' size=56 vlen=13
> >> > >> >     'nhoff' type_id=8 bits_offset=0
> >> > >> >     'thoff' type_id=8 bits_offset=16
> >> > >> >     'addr_proto' type_id=8 bits_offset=32
> >> > >> >     'is_frag' type_id=3 bits_offset=48
> >> > >> >     'is_first_frag' type_id=3 bits_offset=56
> >> > >> >     'is_encap' type_id=3 bits_offset=64
> >> > >> >     'ip_proto' type_id=3 bits_offset=72
> >> > >> >     'n_proto' type_id=20 bits_offset=80
> >> > >> >     'sport' type_id=20 bits_offset=96
> >> > >> >     'dport' type_id=20 bits_offset=112
> >> > >> >     '(anon)' type_id=25 bits_offset=128
> >> > >> >     'flags' type_id=12 bits_offset=384
> >> > >> >     'flow_label' type_id=21 bits_offset=416
> >> > >> > [25] UNION '(anon)' size=32 vlen=2
> >> > >> >     '(anon)' type_id=26 bits_offset=0
> >> > >> >     '(anon)' type_id=27 bits_offset=0
> >> > >> > [26] STRUCT '(anon)' size=8 vlen=2
> >> > >> >     'ipv4_src' type_id=21 bits_offset=0
> >> > >> >     'ipv4_dst' type_id=21 bits_offset=32
> >> > >> > [27] STRUCT '(anon)' size=32 vlen=2
> >> > >> >     'ipv6_src' type_id=28 bits_offset=0
> >> > >> >     'ipv6_dst' type_id=28 bits_offset=128
> >> > >> > [28] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=4
> >> > >> > [29] PTR '(anon)' type_id=24
> >> > >> > [30] UNION '(anon)' size=8 vlen=1
> >> > >> >     'sk' type_id=32 bits_offset=0
> >> > >> > [31] STRUCT 'bpf_sock' size=80 vlen=14
> >> > >> >     'bound_dev_if' type_id=12 bits_offset=0
> >> > >> >     'family' type_id=12 bits_offset=32
> >> > >> >     'type' type_id=12 bits_offset=64
> >> > >> >     'protocol' type_id=12 bits_offset=96
> >> > >> >     'mark' type_id=12 bits_offset=128
> >> > >> >     'priority' type_id=12 bits_offset=160
> >> > >> >     'src_ip4' type_id=12 bits_offset=192
> >> > >> >     'src_ip6' type_id=28 bits_offset=224
> >> > >> >     'src_port' type_id=12 bits_offset=352
> >> > >> >     'dst_port' type_id=20 bits_offset=384
> >> > >> >     'dst_ip4' type_id=12 bits_offset=416
> >> > >> >     'dst_ip6' type_id=28 bits_offset=448
> >> > >> >     'state' type_id=12 bits_offset=576
> >> > >> >     'rx_queue_mapping' type_id=10 bits_offset=608
> >> > >> > [32] PTR '(anon)' type_id=31
> >> > >> > [33] STRUCT '__sk_buff' size=192 vlen=33
> >> > >> >     'len' type_id=12 bits_offset=0
> >> > >> >     'pkt_type' type_id=12 bits_offset=32
> >> > >> >     'mark' type_id=12 bits_offset=64
> >> > >> >     'queue_mapping' type_id=12 bits_offset=96
> >> > >> >     'protocol' type_id=12 bits_offset=128
> >> > >> >     'vlan_present' type_id=12 bits_offset=160
> >> > >> >     'vlan_tci' type_id=12 bits_offset=192
> >> > >> >     'vlan_proto' type_id=12 bits_offset=224
> >> > >> >     'priority' type_id=12 bits_offset=256
> >> > >> >     'ingress_ifindex' type_id=12 bits_offset=288
> >> > >> >     'ifindex' type_id=12 bits_offset=320
> >> > >> >     'tc_index' type_id=12 bits_offset=352
> >> > >> >     'cb' type_id=34 bits_offset=384
> >> > >> >     'hash' type_id=12 bits_offset=544
> >> > >> >     'tc_classid' type_id=12 bits_offset=576
> >> > >> >     'data' type_id=12 bits_offset=608
> >> > >> >     'data_end' type_id=12 bits_offset=640
> >> > >> >     'napi_id' type_id=12 bits_offset=672
> >> > >> >     'family' type_id=12 bits_offset=704
> >> > >> >     'remote_ip4' type_id=12 bits_offset=736
> >> > >> >     'local_ip4' type_id=12 bits_offset=768
> >> > >> >     'remote_ip6' type_id=28 bits_offset=800
> >> > >> >     'local_ip6' type_id=28 bits_offset=928
> >> > >> >     'remote_port' type_id=12 bits_offset=1056
> >> > >> >     'local_port' type_id=12 bits_offset=1088
> >> > >> >     'data_meta' type_id=12 bits_offset=1120
> >> > >> >     '(anon)' type_id=23 bits_offset=1152
> >> > >> >     'tstamp' type_id=15 bits_offset=1216
> >> > >> >     'wire_len' type_id=12 bits_offset=1280
> >> > >> >     'gso_segs' type_id=12 bits_offset=1312
> >> > >> >     '(anon)' type_id=30 bits_offset=1344
> >> > >> >     'gso_size' type_id=12 bits_offset=1408
> >> > >> >     'hwtstamp' type_id=15 bits_offset=1472
> >> > >> > [34] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=5
> >> > >> > [35] CONST '(anon)' type_id=33
> >> > >> > [36] PTR '(anon)' type_id=0
> >> > >> > [37] STRUCT '(anon)' size=24 vlen=3
> >> > >> >     'type' type_id=39 bits_offset=0
> >> > >> >     'key' type_id=40 bits_offset=64
> >> > >> >     'value' type_id=41 bits_offset=128
> >> > >> > [38] ARRAY '(anon)' type_id=9 index_type_id=16 nr_elems=1
> >> > >> > [39] PTR '(anon)' type_id=38
> >> > >> > [40] PTR '(anon)' type_id=12
> >> > >> > [41] PTR '(anon)' type_id=3
> >> > >> > [42] ARRAY '(anon)' type_id=19 index_type_id=16 nr_elems=18
> >> > >> > [43] CONST '(anon)' type_id=42
> >> > >> > [44] FUNC_PROTO '(anon)' ret_type_id=36 vlen=2
> >> > >> >     '(anon)' type_id=36
> >> > >> >     '(anon)' type_id=46
> >> > >> > [45] CONST '(anon)' type_id=0
> >> > >> > [46] PTR '(anon)' type_id=45
> >> > >> > [47] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
> >> > >> >     'sk' type_id=48
> >> > >> > [48] PTR '(anon)' type_id=35
> >> > >> > [49] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
> >> > >> >     'sk' type_id=48
> >> > >> > [50] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
> >> > >> >     'sk' type_id=48
> >> > >> > [51] VAR '_license' type_id=43, linkage=static
> >> > >> > [52] VAR 'is_allow_list' type_id=5, linkage=global
> >> > >> > [53] VAR 'sd_restrictif' type_id=37, linkage=global
> >> > >> > [54] FUNC 'bpf_map_lookup_elem' type_id=44 linkage=global
> >> > >> > [55] FUNC 'sd_restrictif_i' type_id=47 linkage=global
> >> > >> > [56] FUNC 'sd_restrictif_e' type_id=49 linkage=global
> >> > >> > [57] FUNC 'restrict_network_interfaces_impl' type_id=50 linkage=static
> >> > >> > [58] DATASEC 'license' size=0 vlen=1
> >> > >> >     type_id=51 offset=0 size=18 (VAR '_license')
> >> > >> > [59] DATASEC '.maps' size=0 vlen=1
> >> > >> >     type_id=53 offset=0 size=24 (VAR 'sd_restrictif')
> >> > >> > [60] DATASEC '.data' size=0 vlen=1
> >> > >> >     type_id=52 offset=0 size=1 (VAR 'is_allow_list')
> >> > >> >
> >> > >> >>
> >> > >> >> >> GCC is wrong, clearly. This function is global ([0]) and libbpf
> >> > >> >> >> expects it to be marked as such in BTF.
> >> > >> >> >>
> >> > >> >> >>
> >> > >> >
> > https://github.com/systemd/systemd/blob/main/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.c#L42-L50
> >> > >> >> >>
> >> > >> >> >>
> >> > >> >> >>> GCC:
> >> > >> >> >>>
> >> > >> >> >>> [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> >> > >> >> >>> [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
> >> > >> >> >>> [3] TYPEDEF '__u8' type_id=2
> >> > >> >> >>> [4] CONST '(anon)' type_id=3
> >> > >> >> >>
> >> > >> >> >> [...]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-07-09 22:54                     ` James Hilliard
@ 2022-07-10  9:38                       ` Jose E. Marchesi
  2022-07-10 12:16                         ` James Hilliard
  0 siblings, 1 reply; 38+ messages in thread
From: Jose E. Marchesi @ 2022-07-10  9:38 UTC (permalink / raw)
  To: James Hilliard; +Cc: Andrii Nakryiko, bpf, david.faust


> On Sat, Jul 9, 2022 at 4:41 PM Jose E. Marchesi
> <jose.marchesi@oracle.com> wrote:
>>
>>
>> > On Sat, Jul 9, 2022 at 2:32 PM James Hilliard <james.hilliard1@gmail.com> wrote:
>> >>
>> >> On Sat, Jul 9, 2022 at 2:21 PM Jose E. Marchesi
>> >> <jose.marchesi@oracle.com> wrote:
>> >> >
>> >> >
>> >> > > On Sat, Jul 9, 2022 at 11:24 AM Jose E. Marchesi
>> >> > > <jose.marchesi@oracle.com> wrote:
>> >> > >>
>> >> > >>
>> >> > >> > On Fri, Jul 8, 2022 at 12:33 PM Jose E. Marchesi
>> >> > >> > <jose.marchesi@oracle.com> wrote:
>> >> > >> >>
>> >> > >> >>
>> >> > >> >> >> On Wed, Jul 6, 2022 at 10:13 AM James Hilliard
>> >> > >> >> >> <james.hilliard1@gmail.com> wrote:
>> >> > >> >> >>>
>> >> > >> >> >>> Note I'm testing with the following patches:
>> >> > >> >> >>> https://lore.kernel.org/bpf/20220706111839.1247911-1-james.hilliard1@gmail.com/
>> >> > >> >> >>> https://lore.kernel.org/bpf/20220706140623.2917858-1-james.hilliard1@gmail.com/
>> >> > >> >> >>>
>> >> > >> >> >>> It would appear there's some compatibility issues with bpftool gen and
>> >> > >> >> >>> GCC, not sure what side though is wrong here:
>> >> > >> >> >>> /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>> >> > >> >> >>> gen object src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>> >> > >> >> >>> src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
>> >> > >> >> >>> libbpf: failed to find BTF info for global/extern symbol 'sd_restrictif_i'
>> >> > >> >> >>> Error: failed to link
>> >> > >> >> >>> 'src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o':
>> >> > >> >> >>> Unknown error -2 (-2)
>> >> > >> >> >>>
>> >> > >> >> >>> Relevant difference seems to be this:
>> >> > >> >> >>> GCC:
>> >> > >> >> >>> [55] FUNC 'sd_restrictif_i' type_id=47 linkage=static
>> >> > >> >> >>> Clang:
>> >> > >> >> >>> [27] FUNC 'sd_restrictif_i' type_id=26 linkage=global
>> >> > >> >> >
>> >> > >> >> > For functions GCC generates a BTF_KIND_FUNC entry, which has no linkage
>> >> > >> >> > information, or so we thought: I just looked at bpftool/btf.c and I
>> >> > >> >> > found the linkage info for function types is expected to be encoded in
>> >> > >> >> > the vlen field of BTF_KIND_FUNC entries (why not adding a btf_func
>> >> > >> >> > instead???) which is surprising to say the least.
>> >> > >> >> >
>> >> > >> >> > We are changing GCC to encode the linkage info in vlen for these types.
>> >> > >> >> > Thanks for reporting this.
>> >> > >> >>
>> >> > >> >> Patch sent to GCC upstream:
>> >> > >> >> https://gcc.gnu.org/pipermail/gcc-patches/2022-July/598090.html
>> >> > >> >
>> >> > >> > I applied that patch on top of GCC 12.1.0 and it appears to fix the
>> >> > >> > bpftool gen object bug.
>> >> > >> >
>> >> > >> > I am however now hitting a different error during skeleton generation:
>> >> > >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>> >> > >> > gen skeleton src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>> >> > >> > libbpf: elf: skipping unrecognized data section(9) .comment
>> >> > >> > libbpf: failed to alloc map 'restrict.bss' content buffer: -22
>> >> > >> > Error: failed to open BPF object file: Invalid argument
>> >> > >>
>> >> > >> What is the size of the .bss section in the object file?  Try with:
>> >> > >>
>> >> > >> $ size restrict-ifaces.bpf.o
>> >> > >
>> >> > > $ size
>> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>> >> > >    text       data        bss        dec        hex    filename
>> >> > >     386         25          0        411        19b
>> >> > > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>> >> >
>> >> > Right, so the .bss section is empty.  I see a `const volatile unsigned
>> >> > char is_allow_list = 0;' in restrict-ifaces.bpf.c, but that goes to
>> >> > .data and not to .bss, as expected.
>> >> >
>> >> > If you build restrict-ifaces.bpf.o with LLVM, is the bss still empty?  I
>> >> > don't think the code in libbpf.c even checks for this eventuality...
>> >>
>> >> LLVM version(which skeleton generation works with):
>> >> $ size restrict-ifaces.bpf.o
>> >>    text       data        bss        dec        hex    filename
>> >>     323         24          0        347        15b    restrict-ifaces.bpf.o
>> >>
>> >> $ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>> >> btf dump file restrict-ifaces.bpf.o format raw
>> >> [1] PTR '(anon)' type_id=3
>> >> [2] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
>> >> [3] ARRAY '(anon)' type_id=2 index_type_id=4 nr_elems=1
>> >> [4] INT '__ARRAY_SIZE_TYPE__' size=4 bits_offset=0 nr_bits=32 encoding=(none)
>> >> [5] PTR '(anon)' type_id=6
>> >> [6] TYPEDEF '__u32' type_id=7
>> >> [7] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
>> >> [8] PTR '(anon)' type_id=9
>> >> [9] TYPEDEF '__u8' type_id=10
>> >> [10] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=(none)
>> >> [11] STRUCT '(anon)' size=24 vlen=3
>> >>     'type' type_id=1 bits_offset=0
>> >>     'key' type_id=5 bits_offset=64
>> >>     'value' type_id=8 bits_offset=128
>> >> [12] VAR 'sd_restrictif' type_id=11, linkage=global
>> >> [13] PTR '(anon)' type_id=14
>> >> [14] CONST '(anon)' type_id=15
>> >> [15] STRUCT '__sk_buff' size=192 vlen=33
>> >>     'len' type_id=6 bits_offset=0
>> >>     'pkt_type' type_id=6 bits_offset=32
>> >>     'mark' type_id=6 bits_offset=64
>> >>     'queue_mapping' type_id=6 bits_offset=96
>> >>     'protocol' type_id=6 bits_offset=128
>> >>     'vlan_present' type_id=6 bits_offset=160
>> >>     'vlan_tci' type_id=6 bits_offset=192
>> >>     'vlan_proto' type_id=6 bits_offset=224
>> >>     'priority' type_id=6 bits_offset=256
>> >>     'ingress_ifindex' type_id=6 bits_offset=288
>> >>     'ifindex' type_id=6 bits_offset=320
>> >>     'tc_index' type_id=6 bits_offset=352
>> >>     'cb' type_id=16 bits_offset=384
>> >>     'hash' type_id=6 bits_offset=544
>> >>     'tc_classid' type_id=6 bits_offset=576
>> >>     'data' type_id=6 bits_offset=608
>> >>     'data_end' type_id=6 bits_offset=640
>> >>     'napi_id' type_id=6 bits_offset=672
>> >>     'family' type_id=6 bits_offset=704
>> >>     'remote_ip4' type_id=6 bits_offset=736
>> >>     'local_ip4' type_id=6 bits_offset=768
>> >>     'remote_ip6' type_id=17 bits_offset=800
>> >>     'local_ip6' type_id=17 bits_offset=928
>> >>     'remote_port' type_id=6 bits_offset=1056
>> >>     'local_port' type_id=6 bits_offset=1088
>> >>     'data_meta' type_id=6 bits_offset=1120
>> >>     '(anon)' type_id=18 bits_offset=1152
>> >>     'tstamp' type_id=20 bits_offset=1216
>> >>     'wire_len' type_id=6 bits_offset=1280
>> >>     'gso_segs' type_id=6 bits_offset=1312
>> >>     '(anon)' type_id=22 bits_offset=1344
>> >>     'gso_size' type_id=6 bits_offset=1408
>> >>     'hwtstamp' type_id=20 bits_offset=1472
>> >> [16] ARRAY '(anon)' type_id=6 index_type_id=4 nr_elems=5
>> >> [17] ARRAY '(anon)' type_id=6 index_type_id=4 nr_elems=4
>> >> [18] UNION '(anon)' size=8 vlen=1
>> >>     'flow_keys' type_id=19 bits_offset=0
>> >> [19] PTR '(anon)' type_id=34
>> >> [20] TYPEDEF '__u64' type_id=21
>> >> [21] INT 'unsigned long long' size=8 bits_offset=0 nr_bits=64 encoding=(none)
>> >> [22] UNION '(anon)' size=8 vlen=1
>> >>     'sk' type_id=23 bits_offset=0
>> >> [23] PTR '(anon)' type_id=35
>> >> [24] FUNC_PROTO '(anon)' ret_type_id=2 vlen=1
>> >>     'sk' type_id=13
>> >> [25] FUNC 'sd_restrictif_e' type_id=24 linkage=global
>> >> [26] FUNC 'sd_restrictif_i' type_id=24 linkage=global
>> >> [27] CONST '(anon)' type_id=28
>> >> [28] VOLATILE '(anon)' type_id=9
>> >> [29] VAR 'is_allow_list' type_id=27, linkage=global
>> >> [30] CONST '(anon)' type_id=31
>> >> [31] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=SIGNED
>> >> [32] ARRAY '(anon)' type_id=30 index_type_id=4 nr_elems=18
>> >> [33] VAR '_license' type_id=32, linkage=static
>> >> [34] FWD 'bpf_flow_keys' fwd_kind=struct
>> >> [35] FWD 'bpf_sock' fwd_kind=struct
>> >> [36] DATASEC '.rodata' size=1 vlen=1
>> >>     type_id=29 offset=0 size=1 (VAR 'is_allow_list')
>> >> [37] DATASEC 'license' size=18 vlen=1
>> >>     type_id=33 offset=0 size=18 (VAR '_license')
>> >> [38] DATASEC '.maps' size=24 vlen=1
>> >>     type_id=12 offset=0 size=24 (VAR 'sd_restrictif')
>> >>
>> >
>> > Skeleton generation debug output for GCC(failing) and LLVM(working)
>> > which may be helpful:
>>
>> Indeed it was helpful :)
>>
>> The GNU assembler generates an empty .bss section.  This is a well
>> established behavior in GAS that happens in all supported targets.
>>
>> The LLVM assembler doesn't generate an empty .bss section.
>>
>> bpftool chokes on the empty .bss section.
>>
>> In this case I would suggest to fix bpf_object__init_global_data_maps in
>> order to skip empty sections.
>>
>> Something like this:
>
> Hmm, that seems to segfault:

Yes, I see in bpf_object__elf_collect that sec_desc->data is not
initialized when a section is not recognized.  In this case, this
happens with .comment.

All right then:

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index e89cc9c885b3..887b78780099 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -1591,6 +1591,10 @@ static int bpf_object__init_global_data_maps(struct bpf_object *obj)
 	for (sec_idx = 1; sec_idx < obj->efile.sec_cnt; sec_idx++) {
 		sec_desc = &obj->efile.secs[sec_idx];
 
+                /* Skip recognized sections with size 0.  */
+                if (sec_desc->data && sec_desc->data->d_size == 0)
+                  continue;
+
 		switch (sec_desc->sec_type) {
 		case SEC_DATA:
 			sec_name = elf_sec_name(obj, elf_sec_by_idx(obj, sec_idx));


> Starting program:
> /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> --debug gen skeleton
> output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> [Thread debugging using libthread_db enabled]
> Using host libthread_db library "/usr/lib/libthread_db.so.1".
> libbpf: loading object 'restrict_ifaces_bpf' from buffer
> libbpf: elf: section(2) .symtab, size 336, link 1, flags 0, type=2
> libbpf: elf: section(3) .data, size 1, link 0, flags 3, type=1
> libbpf: elf: section(4) .bss, size 0, link 0, flags 3, type=8
> libbpf: elf: section(5) cgroup_skb/egress, size 184, link 0, flags 6, type=1
> libbpf: sec 'cgroup_skb/egress': found program 'sd_restrictif_e' at
> insn offset 0 (0 bytes), code size 23 insns (184 bytes)
> libbpf: elf: section(6) cgroup_skb/ingress, size 184, link 0, flags 6, type=1
> libbpf: sec 'cgroup_skb/ingress': found program 'sd_restrictif_i' at
> insn offset 0 (0 bytes), code size 23 insns (184 bytes)
> libbpf: elf: section(7) license, size 18, link 0, flags 2, type=1
> libbpf: license of restrict_ifaces_bpf is LGPL-2.1-or-later
> libbpf: elf: section(8) .maps, size 24, link 0, flags 3, type=1
> libbpf: elf: section(9) .comment, size 49, link 0, flags 30, type=1
> libbpf: elf: skipping unrecognized data section(9) .comment
> libbpf: elf: section(10) .relcgroup_skb/egress, size 32, link 2, flags
> 40, type=9
> libbpf: elf: section(11) .relcgroup_skb/ingress, size 32, link 2,
> flags 40, type=9
> libbpf: elf: section(12) .BTF, size 3606, link 0, flags 0, type=1
> libbpf: looking for externs among 14 symbols...
> libbpf: collected 0 externs total
> libbpf: map 'sd_restrictif': at sec_idx 8, offset 0.
> libbpf: map 'sd_restrictif': found type = 1.
> libbpf: map 'sd_restrictif': found key [12], sz = 4.
> libbpf: map 'sd_restrictif': found value [3], sz = 1.
>
> Program received signal SIGSEGV, Segmentation fault.
> 0x0000aaaaaab4fd2c in bpf_object.init_maps ()
> (gdb) bt
> #0  0x0000aaaaaab4fd2c in bpf_object.init_maps ()
> #1  0x0000aaaaaab52178 in bpf_object_open.part ()
> #2  0x0000aaaaaab544e8 in bpf_object.open_mem ()
> #3  0x0000aaaaaab2a58c in do_skeleton ()
> #4  0x0000aaaaaab1e204 in main ()
>
>>
>> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
>> index e89cc9c885b3..e3a6808f0bb6 100644
>> --- a/tools/lib/bpf/libbpf.c
>> +++ b/tools/lib/bpf/libbpf.c
>> @@ -1591,6 +1591,10 @@ static int bpf_object__init_global_data_maps(struct bpf_object *obj)
>>         for (sec_idx = 1; sec_idx < obj->efile.sec_cnt; sec_idx++) {
>>                 sec_desc = &obj->efile.secs[sec_idx];
>>
>> +                /* Skip empty sections.  */
>> +                if (sec_desc->data->d_size == 0)
>> +                  continue;
>> +
>>                 switch (sec_desc->sec_type) {
>>                 case SEC_DATA:
>>                         sec_name = elf_sec_name(obj, elf_sec_by_idx(obj, sec_idx));
>>
>> > GCC:
>> > $ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>> > --debug gen skeleton
>> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>> > libbpf: loading object 'restrict_ifaces_bpf' from buffer
>> > libbpf: elf: section(2) .symtab, size 336, link 1, flags 0, type=2
>> > libbpf: elf: section(3) .data, size 1, link 0, flags 3, type=1
>> > libbpf: elf: section(4) .bss, size 0, link 0, flags 3, type=8
>> > libbpf: elf: section(5) cgroup_skb/egress, size 184, link 0, flags 6, type=1
>> > libbpf: sec 'cgroup_skb/egress': found program 'sd_restrictif_e' at
>> > insn offset 0 (0 bytes), code size 23 insns (184 bytes)
>> > libbpf: elf: section(6) cgroup_skb/ingress, size 184, link 0, flags 6, type=1
>> > libbpf: sec 'cgroup_skb/ingress': found program 'sd_restrictif_i' at
>> > insn offset 0 (0 bytes), code size 23 insns (184 bytes)
>> > libbpf: elf: section(7) license, size 18, link 0, flags 2, type=1
>> > libbpf: license of restrict_ifaces_bpf is LGPL-2.1-or-later
>> > libbpf: elf: section(8) .maps, size 24, link 0, flags 3, type=1
>> > libbpf: elf: section(9) .comment, size 49, link 0, flags 30, type=1
>> > libbpf: elf: skipping unrecognized data section(9) .comment
>> > libbpf: elf: section(10) .relcgroup_skb/egress, size 32, link 2, flags
>> > 40, type=9
>> > libbpf: elf: section(11) .relcgroup_skb/ingress, size 32, link 2,
>> > flags 40, type=9
>> > libbpf: elf: section(12) .BTF, size 3606, link 0, flags 0, type=1
>> > libbpf: looking for externs among 14 symbols...
>> > libbpf: collected 0 externs total
>> > libbpf: map 'sd_restrictif': at sec_idx 8, offset 0.
>> > libbpf: map 'sd_restrictif': found type = 1.
>> > libbpf: map 'sd_restrictif': found key [12], sz = 4.
>> > libbpf: map 'sd_restrictif': found value [3], sz = 1.
>> > libbpf: map 'restrict.data' (global data): at sec_idx 3, offset 0, flags 400.
>> > libbpf: map 1 is "restrict.data"
>> > libbpf: map 'restrict.bss' (global data): at sec_idx 4, offset 0, flags 400.
>> > libbpf: failed to alloc map 'restrict.bss' content buffer: -22
>> > Error: failed to open BPF object file: Invalid argument
>> >
>> > LLVM:
>> > $ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>> > --debug gen skeleton restrict-ifaces.bpf.o
>> > libbpf: loading object 'restrict_ifaces_bpf' from buffer
>> > libbpf: elf: section(2) .symtab, size 384, link 1, flags 0, type=2
>> > libbpf: elf: section(3) cgroup_skb/egress, size 152, link 0, flags 6, type=1
>> > libbpf: sec 'cgroup_skb/egress': found program 'sd_restrictif_e' at
>> > insn offset 0 (0 bytes), code size 19 insns (152 bytes)
>> > libbpf: elf: section(4) cgroup_skb/ingress, size 152, link 0, flags 6, type=1
>> > libbpf: sec 'cgroup_skb/ingress': found program 'sd_restrictif_i' at
>> > insn offset 0 (0 bytes), code size 19 insns (152 bytes)
>> > libbpf: elf: section(5) .rodata, size 1, link 0, flags 2, type=1
>> > libbpf: elf: section(6) license, size 18, link 0, flags 2, type=1
>> > libbpf: license of restrict_ifaces_bpf is LGPL-2.1-or-later
>> > libbpf: elf: section(7) .maps, size 24, link 0, flags 3, type=1
>> > libbpf: elf: section(8) .relcgroup_skb/egress, size 32, link 2, flags 40, type=9
>> > libbpf: elf: section(9) .relcgroup_skb/ingress, size 32, link 2, flags
>> > 40, type=9
>> > libbpf: elf: section(10) .BTF, size 1988, link 0, flags 0, type=1
>> > libbpf: elf: section(11) .BTF.ext, size 376, link 0, flags 0, type=1
>> > libbpf: looking for externs among 16 symbols...
>> > libbpf: collected 0 externs total
>> > libbpf: map 'sd_restrictif': at sec_idx 7, offset 0.
>> > libbpf: map 'sd_restrictif': found type = 1.
>> > libbpf: map 'sd_restrictif': found key [6], sz = 4.
>> > libbpf: map 'sd_restrictif': found value [9], sz = 1.
>> > libbpf: map 'restrict.rodata' (global data): at sec_idx 5, offset 0, flags 480.
>> > libbpf: map 1 is "restrict.rodata"
>> > libbpf: sec '.relcgroup_skb/egress': collecting relocation for
>> > section(3) 'cgroup_skb/egress'
>> > libbpf: sec '.relcgroup_skb/egress': relo #0: insn #4 against 'sd_restrictif'
>> > libbpf: prog 'sd_restrictif_e': found map 0 (sd_restrictif, sec 7, off
>> > 0) for insn #4
>> > libbpf: sec '.relcgroup_skb/egress': relo #1: insn #7 against 'is_allow_list'
>> > libbpf: prog 'sd_restrictif_e': found data map 1 (restrict.rodata, sec
>> > 5, off 0) for insn 7
>> > libbpf: sec '.relcgroup_skb/ingress': collecting relocation for
>> > section(4) 'cgroup_skb/ingress'
>> > libbpf: sec '.relcgroup_skb/ingress': relo #0: insn #4 against 'sd_restrictif'
>> > libbpf: prog 'sd_restrictif_i': found map 0 (sd_restrictif, sec 7, off
>> > 0) for insn #4
>> > libbpf: sec '.relcgroup_skb/ingress': relo #1: insn #7 against 'is_allow_list'
>> > libbpf: prog 'sd_restrictif_i': found data map 1 (restrict.rodata, sec
>> > 5, off 0) for insn 7
>> >
>> >> >
>> >> > >>
>> >> > >> Looking at libbpf.c, it seems to me that this may be due of trying to
>> >> > >> mmap 0 bytes in `bpf_object__init_internal_map':
>> >> > >>
>> >> > >>         map->mmaped = mmap(NULL, bpf_map_mmap_sz(map), PROT_READ | PROT_WRITE,
>> >> > >>                            MAP_SHARED | MAP_ANONYMOUS, -1, 0);
>> >> > >>         if (map->mmaped == MAP_FAILED) {
>> >> > >>                 err = -errno;
>> >> > >>                 map->mmaped = NULL;
>> >> > >>                 pr_warn("failed to alloc map '%s' content buffer: %d\n",
>> >> > >>                         map->name, err);
>> >> > >>                 zfree(&map->real_name);
>> >> > >>                 zfree(&map->name);
>> >> > >>                 return err;
>> >> > >>         }
>> >> > >>
>> >> > >> I see no check for zero sized sections in
>> >> > >> bpf_object__init_global_data_maps.
>> >> > >>
>> >> > >> Is maybe GCC failing to allocate stuff in BSS that is supposed to be
>> >> > >> there?
>> >> > >>
>> >> > >> > Stripped file passed to gen skeleton:
>> >> > >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>> >> > >> > btf dump file
>> >> > >> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>> >> > >> > format raw
>> >> > >> > [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>> >> > >> > [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
>> >> > >> > [3] TYPEDEF '__u8' type_id=2
>> >> > >> > [4] CONST '(anon)' type_id=3
>> >> > >> > [5] VOLATILE '(anon)' type_id=4
>> >> > >> > [6] INT 'short int' size=2 bits_offset=0 nr_bits=16 encoding=SIGNED
>> >> > >> > [7] INT 'short unsigned int' size=2 bits_offset=0 nr_bits=16 encoding=(none)
>> >> > >> > [8] TYPEDEF '__u16' type_id=7
>> >> > >> > [9] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
>> >> > >> > [10] TYPEDEF '__s32' type_id=9
>> >> > >> > [11] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
>> >> > >> > [12] TYPEDEF '__u32' type_id=11
>> >> > >> > [13] INT 'long long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
>> >> > >> > [14] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64
>> >> > >> > encoding=(none)
>> >> > >> > [15] TYPEDEF '__u64' type_id=14
>> >> > >> > [16] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
>> >> > >> > [17] INT 'long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
>> >> > >> > [18] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>> >> > >> > [19] CONST '(anon)' type_id=18
>> >> > >> > [20] TYPEDEF '__be16' type_id=8
>> >> > >> > [21] TYPEDEF '__be32' type_id=12
>> >> > >> > [22] ENUM 'bpf_map_type' encoding=UNSIGNED size=4 vlen=31
>> >> > >> >     'BPF_MAP_TYPE_UNSPEC' val=0
>> >> > >> >     'BPF_MAP_TYPE_HASH' val=1
>> >> > >> >     'BPF_MAP_TYPE_ARRAY' val=2
>> >> > >> >     'BPF_MAP_TYPE_PROG_ARRAY' val=3
>> >> > >> >     'BPF_MAP_TYPE_PERF_EVENT_ARRAY' val=4
>> >> > >> >     'BPF_MAP_TYPE_PERCPU_HASH' val=5
>> >> > >> >     'BPF_MAP_TYPE_PERCPU_ARRAY' val=6
>> >> > >> >     'BPF_MAP_TYPE_STACK_TRACE' val=7
>> >> > >> >     'BPF_MAP_TYPE_CGROUP_ARRAY' val=8
>> >> > >> >     'BPF_MAP_TYPE_LRU_HASH' val=9
>> >> > >> >     'BPF_MAP_TYPE_LRU_PERCPU_HASH' val=10
>> >> > >> >     'BPF_MAP_TYPE_LPM_TRIE' val=11
>> >> > >> >     'BPF_MAP_TYPE_ARRAY_OF_MAPS' val=12
>> >> > >> >     'BPF_MAP_TYPE_HASH_OF_MAPS' val=13
>> >> > >> >     'BPF_MAP_TYPE_DEVMAP' val=14
>> >> > >> >     'BPF_MAP_TYPE_SOCKMAP' val=15
>> >> > >> >     'BPF_MAP_TYPE_CPUMAP' val=16
>> >> > >> >     'BPF_MAP_TYPE_XSKMAP' val=17
>> >> > >> >     'BPF_MAP_TYPE_SOCKHASH' val=18
>> >> > >> >     'BPF_MAP_TYPE_CGROUP_STORAGE' val=19
>> >> > >> >     'BPF_MAP_TYPE_REUSEPORT_SOCKARRAY' val=20
>> >> > >> >     'BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE' val=21
>> >> > >> >     'BPF_MAP_TYPE_QUEUE' val=22
>> >> > >> >     'BPF_MAP_TYPE_STACK' val=23
>> >> > >> >     'BPF_MAP_TYPE_SK_STORAGE' val=24
>> >> > >> >     'BPF_MAP_TYPE_DEVMAP_HASH' val=25
>> >> > >> >     'BPF_MAP_TYPE_STRUCT_OPS' val=26
>> >> > >> >     'BPF_MAP_TYPE_RINGBUF' val=27
>> >> > >> >     'BPF_MAP_TYPE_INODE_STORAGE' val=28
>> >> > >> >     'BPF_MAP_TYPE_TASK_STORAGE' val=29
>> >> > >> >     'BPF_MAP_TYPE_BLOOM_FILTER' val=30
>> >> > >> > [23] UNION '(anon)' size=8 vlen=1
>> >> > >> >     'flow_keys' type_id=29 bits_offset=0
>> >> > >> > [24] STRUCT 'bpf_flow_keys' size=56 vlen=13
>> >> > >> >     'nhoff' type_id=8 bits_offset=0
>> >> > >> >     'thoff' type_id=8 bits_offset=16
>> >> > >> >     'addr_proto' type_id=8 bits_offset=32
>> >> > >> >     'is_frag' type_id=3 bits_offset=48
>> >> > >> >     'is_first_frag' type_id=3 bits_offset=56
>> >> > >> >     'is_encap' type_id=3 bits_offset=64
>> >> > >> >     'ip_proto' type_id=3 bits_offset=72
>> >> > >> >     'n_proto' type_id=20 bits_offset=80
>> >> > >> >     'sport' type_id=20 bits_offset=96
>> >> > >> >     'dport' type_id=20 bits_offset=112
>> >> > >> >     '(anon)' type_id=25 bits_offset=128
>> >> > >> >     'flags' type_id=12 bits_offset=384
>> >> > >> >     'flow_label' type_id=21 bits_offset=416
>> >> > >> > [25] UNION '(anon)' size=32 vlen=2
>> >> > >> >     '(anon)' type_id=26 bits_offset=0
>> >> > >> >     '(anon)' type_id=27 bits_offset=0
>> >> > >> > [26] STRUCT '(anon)' size=8 vlen=2
>> >> > >> >     'ipv4_src' type_id=21 bits_offset=0
>> >> > >> >     'ipv4_dst' type_id=21 bits_offset=32
>> >> > >> > [27] STRUCT '(anon)' size=32 vlen=2
>> >> > >> >     'ipv6_src' type_id=28 bits_offset=0
>> >> > >> >     'ipv6_dst' type_id=28 bits_offset=128
>> >> > >> > [28] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=4
>> >> > >> > [29] PTR '(anon)' type_id=24
>> >> > >> > [30] UNION '(anon)' size=8 vlen=1
>> >> > >> >     'sk' type_id=32 bits_offset=0
>> >> > >> > [31] STRUCT 'bpf_sock' size=80 vlen=14
>> >> > >> >     'bound_dev_if' type_id=12 bits_offset=0
>> >> > >> >     'family' type_id=12 bits_offset=32
>> >> > >> >     'type' type_id=12 bits_offset=64
>> >> > >> >     'protocol' type_id=12 bits_offset=96
>> >> > >> >     'mark' type_id=12 bits_offset=128
>> >> > >> >     'priority' type_id=12 bits_offset=160
>> >> > >> >     'src_ip4' type_id=12 bits_offset=192
>> >> > >> >     'src_ip6' type_id=28 bits_offset=224
>> >> > >> >     'src_port' type_id=12 bits_offset=352
>> >> > >> >     'dst_port' type_id=20 bits_offset=384
>> >> > >> >     'dst_ip4' type_id=12 bits_offset=416
>> >> > >> >     'dst_ip6' type_id=28 bits_offset=448
>> >> > >> >     'state' type_id=12 bits_offset=576
>> >> > >> >     'rx_queue_mapping' type_id=10 bits_offset=608
>> >> > >> > [32] PTR '(anon)' type_id=31
>> >> > >> > [33] STRUCT '__sk_buff' size=192 vlen=33
>> >> > >> >     'len' type_id=12 bits_offset=0
>> >> > >> >     'pkt_type' type_id=12 bits_offset=32
>> >> > >> >     'mark' type_id=12 bits_offset=64
>> >> > >> >     'queue_mapping' type_id=12 bits_offset=96
>> >> > >> >     'protocol' type_id=12 bits_offset=128
>> >> > >> >     'vlan_present' type_id=12 bits_offset=160
>> >> > >> >     'vlan_tci' type_id=12 bits_offset=192
>> >> > >> >     'vlan_proto' type_id=12 bits_offset=224
>> >> > >> >     'priority' type_id=12 bits_offset=256
>> >> > >> >     'ingress_ifindex' type_id=12 bits_offset=288
>> >> > >> >     'ifindex' type_id=12 bits_offset=320
>> >> > >> >     'tc_index' type_id=12 bits_offset=352
>> >> > >> >     'cb' type_id=34 bits_offset=384
>> >> > >> >     'hash' type_id=12 bits_offset=544
>> >> > >> >     'tc_classid' type_id=12 bits_offset=576
>> >> > >> >     'data' type_id=12 bits_offset=608
>> >> > >> >     'data_end' type_id=12 bits_offset=640
>> >> > >> >     'napi_id' type_id=12 bits_offset=672
>> >> > >> >     'family' type_id=12 bits_offset=704
>> >> > >> >     'remote_ip4' type_id=12 bits_offset=736
>> >> > >> >     'local_ip4' type_id=12 bits_offset=768
>> >> > >> >     'remote_ip6' type_id=28 bits_offset=800
>> >> > >> >     'local_ip6' type_id=28 bits_offset=928
>> >> > >> >     'remote_port' type_id=12 bits_offset=1056
>> >> > >> >     'local_port' type_id=12 bits_offset=1088
>> >> > >> >     'data_meta' type_id=12 bits_offset=1120
>> >> > >> >     '(anon)' type_id=23 bits_offset=1152
>> >> > >> >     'tstamp' type_id=15 bits_offset=1216
>> >> > >> >     'wire_len' type_id=12 bits_offset=1280
>> >> > >> >     'gso_segs' type_id=12 bits_offset=1312
>> >> > >> >     '(anon)' type_id=30 bits_offset=1344
>> >> > >> >     'gso_size' type_id=12 bits_offset=1408
>> >> > >> >     'hwtstamp' type_id=15 bits_offset=1472
>> >> > >> > [34] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=5
>> >> > >> > [35] CONST '(anon)' type_id=33
>> >> > >> > [36] PTR '(anon)' type_id=0
>> >> > >> > [37] STRUCT '(anon)' size=24 vlen=3
>> >> > >> >     'type' type_id=39 bits_offset=0
>> >> > >> >     'key' type_id=40 bits_offset=64
>> >> > >> >     'value' type_id=41 bits_offset=128
>> >> > >> > [38] ARRAY '(anon)' type_id=9 index_type_id=16 nr_elems=1
>> >> > >> > [39] PTR '(anon)' type_id=38
>> >> > >> > [40] PTR '(anon)' type_id=12
>> >> > >> > [41] PTR '(anon)' type_id=3
>> >> > >> > [42] ARRAY '(anon)' type_id=19 index_type_id=16 nr_elems=18
>> >> > >> > [43] CONST '(anon)' type_id=42
>> >> > >> > [44] FUNC_PROTO '(anon)' ret_type_id=36 vlen=2
>> >> > >> >     '(anon)' type_id=36
>> >> > >> >     '(anon)' type_id=46
>> >> > >> > [45] CONST '(anon)' type_id=0
>> >> > >> > [46] PTR '(anon)' type_id=45
>> >> > >> > [47] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>> >> > >> >     'sk' type_id=48
>> >> > >> > [48] PTR '(anon)' type_id=35
>> >> > >> > [49] VAR '_license' type_id=43, linkage=static
>> >> > >> > [50] VAR 'is_allow_list' type_id=5, linkage=global
>> >> > >> > [51] VAR 'sd_restrictif' type_id=37, linkage=global
>> >> > >> > [52] FUNC 'sd_restrictif_i' type_id=47 linkage=global
>> >> > >> > [53] FUNC 'sd_restrictif_e' type_id=47 linkage=global
>> >> > >> > [54] FUNC 'restrict_network_interfaces_impl' type_id=47 linkage=static
>> >> > >> > [55] DATASEC '.data' size=1 vlen=1
>> >> > >> >     type_id=50 offset=0 size=1 (VAR 'is_allow_list')
>> >> > >> > [56] DATASEC 'license' size=18 vlen=1
>> >> > >> >     type_id=49 offset=0 size=18 (VAR '_license')
>> >> > >> > [57] DATASEC '.maps' size=24 vlen=1
>> >> > >> >     type_id=51 offset=0 size=24 (VAR 'sd_restrictif')
>> >> > >> >
>> >> > >> > File before being stripped using bpftool gen object:
>> >> > >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>> >> > >> > btf dump file
>> >> > >> >
>> >
> output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
>> >> > >> > format raw
>> >> > >> > [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>> >> > >> > [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
>> >> > >> > [3] TYPEDEF '__u8' type_id=2
>> >> > >> > [4] CONST '(anon)' type_id=3
>> >> > >> > [5] VOLATILE '(anon)' type_id=4
>> >> > >> > [6] INT 'short int' size=2 bits_offset=0 nr_bits=16 encoding=SIGNED
>> >> > >> > [7] INT 'short unsigned int' size=2 bits_offset=0 nr_bits=16 encoding=(none)
>> >> > >> > [8] TYPEDEF '__u16' type_id=7
>> >> > >> > [9] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
>> >> > >> > [10] TYPEDEF '__s32' type_id=9
>> >> > >> > [11] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
>> >> > >> > [12] TYPEDEF '__u32' type_id=11
>> >> > >> > [13] INT 'long long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
>> >> > >> > [14] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64
>> >> > >> > encoding=(none)
>> >> > >> > [15] TYPEDEF '__u64' type_id=14
>> >> > >> > [16] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
>> >> > >> > [17] INT 'long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
>> >> > >> > [18] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>> >> > >> > [19] CONST '(anon)' type_id=18
>> >> > >> > [20] TYPEDEF '__be16' type_id=8
>> >> > >> > [21] TYPEDEF '__be32' type_id=12
>> >> > >> > [22] ENUM 'bpf_map_type' encoding=UNSIGNED size=4 vlen=31
>> >> > >> >     'BPF_MAP_TYPE_UNSPEC' val=0
>> >> > >> >     'BPF_MAP_TYPE_HASH' val=1
>> >> > >> >     'BPF_MAP_TYPE_ARRAY' val=2
>> >> > >> >     'BPF_MAP_TYPE_PROG_ARRAY' val=3
>> >> > >> >     'BPF_MAP_TYPE_PERF_EVENT_ARRAY' val=4
>> >> > >> >     'BPF_MAP_TYPE_PERCPU_HASH' val=5
>> >> > >> >     'BPF_MAP_TYPE_PERCPU_ARRAY' val=6
>> >> > >> >     'BPF_MAP_TYPE_STACK_TRACE' val=7
>> >> > >> >     'BPF_MAP_TYPE_CGROUP_ARRAY' val=8
>> >> > >> >     'BPF_MAP_TYPE_LRU_HASH' val=9
>> >> > >> >     'BPF_MAP_TYPE_LRU_PERCPU_HASH' val=10
>> >> > >> >     'BPF_MAP_TYPE_LPM_TRIE' val=11
>> >> > >> >     'BPF_MAP_TYPE_ARRAY_OF_MAPS' val=12
>> >> > >> >     'BPF_MAP_TYPE_HASH_OF_MAPS' val=13
>> >> > >> >     'BPF_MAP_TYPE_DEVMAP' val=14
>> >> > >> >     'BPF_MAP_TYPE_SOCKMAP' val=15
>> >> > >> >     'BPF_MAP_TYPE_CPUMAP' val=16
>> >> > >> >     'BPF_MAP_TYPE_XSKMAP' val=17
>> >> > >> >     'BPF_MAP_TYPE_SOCKHASH' val=18
>> >> > >> >     'BPF_MAP_TYPE_CGROUP_STORAGE' val=19
>> >> > >> >     'BPF_MAP_TYPE_REUSEPORT_SOCKARRAY' val=20
>> >> > >> >     'BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE' val=21
>> >> > >> >     'BPF_MAP_TYPE_QUEUE' val=22
>> >> > >> >     'BPF_MAP_TYPE_STACK' val=23
>> >> > >> >     'BPF_MAP_TYPE_SK_STORAGE' val=24
>> >> > >> >     'BPF_MAP_TYPE_DEVMAP_HASH' val=25
>> >> > >> >     'BPF_MAP_TYPE_STRUCT_OPS' val=26
>> >> > >> >     'BPF_MAP_TYPE_RINGBUF' val=27
>> >> > >> >     'BPF_MAP_TYPE_INODE_STORAGE' val=28
>> >> > >> >     'BPF_MAP_TYPE_TASK_STORAGE' val=29
>> >> > >> >     'BPF_MAP_TYPE_BLOOM_FILTER' val=30
>> >> > >> > [23] UNION '(anon)' size=8 vlen=1
>> >> > >> >     'flow_keys' type_id=29 bits_offset=0
>> >> > >> > [24] STRUCT 'bpf_flow_keys' size=56 vlen=13
>> >> > >> >     'nhoff' type_id=8 bits_offset=0
>> >> > >> >     'thoff' type_id=8 bits_offset=16
>> >> > >> >     'addr_proto' type_id=8 bits_offset=32
>> >> > >> >     'is_frag' type_id=3 bits_offset=48
>> >> > >> >     'is_first_frag' type_id=3 bits_offset=56
>> >> > >> >     'is_encap' type_id=3 bits_offset=64
>> >> > >> >     'ip_proto' type_id=3 bits_offset=72
>> >> > >> >     'n_proto' type_id=20 bits_offset=80
>> >> > >> >     'sport' type_id=20 bits_offset=96
>> >> > >> >     'dport' type_id=20 bits_offset=112
>> >> > >> >     '(anon)' type_id=25 bits_offset=128
>> >> > >> >     'flags' type_id=12 bits_offset=384
>> >> > >> >     'flow_label' type_id=21 bits_offset=416
>> >> > >> > [25] UNION '(anon)' size=32 vlen=2
>> >> > >> >     '(anon)' type_id=26 bits_offset=0
>> >> > >> >     '(anon)' type_id=27 bits_offset=0
>> >> > >> > [26] STRUCT '(anon)' size=8 vlen=2
>> >> > >> >     'ipv4_src' type_id=21 bits_offset=0
>> >> > >> >     'ipv4_dst' type_id=21 bits_offset=32
>> >> > >> > [27] STRUCT '(anon)' size=32 vlen=2
>> >> > >> >     'ipv6_src' type_id=28 bits_offset=0
>> >> > >> >     'ipv6_dst' type_id=28 bits_offset=128
>> >> > >> > [28] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=4
>> >> > >> > [29] PTR '(anon)' type_id=24
>> >> > >> > [30] UNION '(anon)' size=8 vlen=1
>> >> > >> >     'sk' type_id=32 bits_offset=0
>> >> > >> > [31] STRUCT 'bpf_sock' size=80 vlen=14
>> >> > >> >     'bound_dev_if' type_id=12 bits_offset=0
>> >> > >> >     'family' type_id=12 bits_offset=32
>> >> > >> >     'type' type_id=12 bits_offset=64
>> >> > >> >     'protocol' type_id=12 bits_offset=96
>> >> > >> >     'mark' type_id=12 bits_offset=128
>> >> > >> >     'priority' type_id=12 bits_offset=160
>> >> > >> >     'src_ip4' type_id=12 bits_offset=192
>> >> > >> >     'src_ip6' type_id=28 bits_offset=224
>> >> > >> >     'src_port' type_id=12 bits_offset=352
>> >> > >> >     'dst_port' type_id=20 bits_offset=384
>> >> > >> >     'dst_ip4' type_id=12 bits_offset=416
>> >> > >> >     'dst_ip6' type_id=28 bits_offset=448
>> >> > >> >     'state' type_id=12 bits_offset=576
>> >> > >> >     'rx_queue_mapping' type_id=10 bits_offset=608
>> >> > >> > [32] PTR '(anon)' type_id=31
>> >> > >> > [33] STRUCT '__sk_buff' size=192 vlen=33
>> >> > >> >     'len' type_id=12 bits_offset=0
>> >> > >> >     'pkt_type' type_id=12 bits_offset=32
>> >> > >> >     'mark' type_id=12 bits_offset=64
>> >> > >> >     'queue_mapping' type_id=12 bits_offset=96
>> >> > >> >     'protocol' type_id=12 bits_offset=128
>> >> > >> >     'vlan_present' type_id=12 bits_offset=160
>> >> > >> >     'vlan_tci' type_id=12 bits_offset=192
>> >> > >> >     'vlan_proto' type_id=12 bits_offset=224
>> >> > >> >     'priority' type_id=12 bits_offset=256
>> >> > >> >     'ingress_ifindex' type_id=12 bits_offset=288
>> >> > >> >     'ifindex' type_id=12 bits_offset=320
>> >> > >> >     'tc_index' type_id=12 bits_offset=352
>> >> > >> >     'cb' type_id=34 bits_offset=384
>> >> > >> >     'hash' type_id=12 bits_offset=544
>> >> > >> >     'tc_classid' type_id=12 bits_offset=576
>> >> > >> >     'data' type_id=12 bits_offset=608
>> >> > >> >     'data_end' type_id=12 bits_offset=640
>> >> > >> >     'napi_id' type_id=12 bits_offset=672
>> >> > >> >     'family' type_id=12 bits_offset=704
>> >> > >> >     'remote_ip4' type_id=12 bits_offset=736
>> >> > >> >     'local_ip4' type_id=12 bits_offset=768
>> >> > >> >     'remote_ip6' type_id=28 bits_offset=800
>> >> > >> >     'local_ip6' type_id=28 bits_offset=928
>> >> > >> >     'remote_port' type_id=12 bits_offset=1056
>> >> > >> >     'local_port' type_id=12 bits_offset=1088
>> >> > >> >     'data_meta' type_id=12 bits_offset=1120
>> >> > >> >     '(anon)' type_id=23 bits_offset=1152
>> >> > >> >     'tstamp' type_id=15 bits_offset=1216
>> >> > >> >     'wire_len' type_id=12 bits_offset=1280
>> >> > >> >     'gso_segs' type_id=12 bits_offset=1312
>> >> > >> >     '(anon)' type_id=30 bits_offset=1344
>> >> > >> >     'gso_size' type_id=12 bits_offset=1408
>> >> > >> >     'hwtstamp' type_id=15 bits_offset=1472
>> >> > >> > [34] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=5
>> >> > >> > [35] CONST '(anon)' type_id=33
>> >> > >> > [36] PTR '(anon)' type_id=0
>> >> > >> > [37] STRUCT '(anon)' size=24 vlen=3
>> >> > >> >     'type' type_id=39 bits_offset=0
>> >> > >> >     'key' type_id=40 bits_offset=64
>> >> > >> >     'value' type_id=41 bits_offset=128
>> >> > >> > [38] ARRAY '(anon)' type_id=9 index_type_id=16 nr_elems=1
>> >> > >> > [39] PTR '(anon)' type_id=38
>> >> > >> > [40] PTR '(anon)' type_id=12
>> >> > >> > [41] PTR '(anon)' type_id=3
>> >> > >> > [42] ARRAY '(anon)' type_id=19 index_type_id=16 nr_elems=18
>> >> > >> > [43] CONST '(anon)' type_id=42
>> >> > >> > [44] FUNC_PROTO '(anon)' ret_type_id=36 vlen=2
>> >> > >> >     '(anon)' type_id=36
>> >> > >> >     '(anon)' type_id=46
>> >> > >> > [45] CONST '(anon)' type_id=0
>> >> > >> > [46] PTR '(anon)' type_id=45
>> >> > >> > [47] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>> >> > >> >     'sk' type_id=48
>> >> > >> > [48] PTR '(anon)' type_id=35
>> >> > >> > [49] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>> >> > >> >     'sk' type_id=48
>> >> > >> > [50] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>> >> > >> >     'sk' type_id=48
>> >> > >> > [51] VAR '_license' type_id=43, linkage=static
>> >> > >> > [52] VAR 'is_allow_list' type_id=5, linkage=global
>> >> > >> > [53] VAR 'sd_restrictif' type_id=37, linkage=global
>> >> > >> > [54] FUNC 'bpf_map_lookup_elem' type_id=44 linkage=global
>> >> > >> > [55] FUNC 'sd_restrictif_i' type_id=47 linkage=global
>> >> > >> > [56] FUNC 'sd_restrictif_e' type_id=49 linkage=global
>> >> > >> > [57] FUNC 'restrict_network_interfaces_impl' type_id=50 linkage=static
>> >> > >> > [58] DATASEC 'license' size=0 vlen=1
>> >> > >> >     type_id=51 offset=0 size=18 (VAR '_license')
>> >> > >> > [59] DATASEC '.maps' size=0 vlen=1
>> >> > >> >     type_id=53 offset=0 size=24 (VAR 'sd_restrictif')
>> >> > >> > [60] DATASEC '.data' size=0 vlen=1
>> >> > >> >     type_id=52 offset=0 size=1 (VAR 'is_allow_list')
>> >> > >> >
>> >> > >> >>
>> >> > >> >> >> GCC is wrong, clearly. This function is global ([0]) and libbpf
>> >> > >> >> >> expects it to be marked as such in BTF.
>> >> > >> >> >>
>> >> > >> >> >>
>> >> > >> >
>> >
> https://github.com/systemd/systemd/blob/main/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.c#L42-L50
>> >> > >> >> >>
>> >> > >> >> >>
>> >> > >> >> >>> GCC:
>> >> > >> >> >>>
>> >> > >> >> >>> [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>> >> > >> >> >>> [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
>> >> > >> >> >>> [3] TYPEDEF '__u8' type_id=2
>> >> > >> >> >>> [4] CONST '(anon)' type_id=3
>> >> > >> >> >>
>> >> > >> >> >> [...]

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-07-10  9:38                       ` Jose E. Marchesi
@ 2022-07-10 12:16                         ` James Hilliard
  2022-07-10 13:06                           ` Jose E. Marchesi
  0 siblings, 1 reply; 38+ messages in thread
From: James Hilliard @ 2022-07-10 12:16 UTC (permalink / raw)
  To: Jose E. Marchesi; +Cc: Andrii Nakryiko, bpf, david.faust

On Sun, Jul 10, 2022 at 3:38 AM Jose E. Marchesi
<jose.marchesi@oracle.com> wrote:
>
>
> > On Sat, Jul 9, 2022 at 4:41 PM Jose E. Marchesi
> > <jose.marchesi@oracle.com> wrote:
> >>
> >>
> >> > On Sat, Jul 9, 2022 at 2:32 PM James Hilliard <james.hilliard1@gmail.com> wrote:
> >> >>
> >> >> On Sat, Jul 9, 2022 at 2:21 PM Jose E. Marchesi
> >> >> <jose.marchesi@oracle.com> wrote:
> >> >> >
> >> >> >
> >> >> > > On Sat, Jul 9, 2022 at 11:24 AM Jose E. Marchesi
> >> >> > > <jose.marchesi@oracle.com> wrote:
> >> >> > >>
> >> >> > >>
> >> >> > >> > On Fri, Jul 8, 2022 at 12:33 PM Jose E. Marchesi
> >> >> > >> > <jose.marchesi@oracle.com> wrote:
> >> >> > >> >>
> >> >> > >> >>
> >> >> > >> >> >> On Wed, Jul 6, 2022 at 10:13 AM James Hilliard
> >> >> > >> >> >> <james.hilliard1@gmail.com> wrote:
> >> >> > >> >> >>>
> >> >> > >> >> >>> Note I'm testing with the following patches:
> >> >> > >> >> >>> https://lore.kernel.org/bpf/20220706111839.1247911-1-james.hilliard1@gmail.com/
> >> >> > >> >> >>> https://lore.kernel.org/bpf/20220706140623.2917858-1-james.hilliard1@gmail.com/
> >> >> > >> >> >>>
> >> >> > >> >> >>> It would appear there's some compatibility issues with bpftool gen and
> >> >> > >> >> >>> GCC, not sure what side though is wrong here:
> >> >> > >> >> >>> /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> >> >> > >> >> >>> gen object src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> >> >> > >> >> >>> src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
> >> >> > >> >> >>> libbpf: failed to find BTF info for global/extern symbol 'sd_restrictif_i'
> >> >> > >> >> >>> Error: failed to link
> >> >> > >> >> >>> 'src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o':
> >> >> > >> >> >>> Unknown error -2 (-2)
> >> >> > >> >> >>>
> >> >> > >> >> >>> Relevant difference seems to be this:
> >> >> > >> >> >>> GCC:
> >> >> > >> >> >>> [55] FUNC 'sd_restrictif_i' type_id=47 linkage=static
> >> >> > >> >> >>> Clang:
> >> >> > >> >> >>> [27] FUNC 'sd_restrictif_i' type_id=26 linkage=global
> >> >> > >> >> >
> >> >> > >> >> > For functions GCC generates a BTF_KIND_FUNC entry, which has no linkage
> >> >> > >> >> > information, or so we thought: I just looked at bpftool/btf.c and I
> >> >> > >> >> > found the linkage info for function types is expected to be encoded in
> >> >> > >> >> > the vlen field of BTF_KIND_FUNC entries (why not adding a btf_func
> >> >> > >> >> > instead???) which is surprising to say the least.
> >> >> > >> >> >
> >> >> > >> >> > We are changing GCC to encode the linkage info in vlen for these types.
> >> >> > >> >> > Thanks for reporting this.
> >> >> > >> >>
> >> >> > >> >> Patch sent to GCC upstream:
> >> >> > >> >> https://gcc.gnu.org/pipermail/gcc-patches/2022-July/598090.html
> >> >> > >> >
> >> >> > >> > I applied that patch on top of GCC 12.1.0 and it appears to fix the
> >> >> > >> > bpftool gen object bug.
> >> >> > >> >
> >> >> > >> > I am however now hitting a different error during skeleton generation:
> >> >> > >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> >> >> > >> > gen skeleton src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> >> >> > >> > libbpf: elf: skipping unrecognized data section(9) .comment
> >> >> > >> > libbpf: failed to alloc map 'restrict.bss' content buffer: -22
> >> >> > >> > Error: failed to open BPF object file: Invalid argument
> >> >> > >>
> >> >> > >> What is the size of the .bss section in the object file?  Try with:
> >> >> > >>
> >> >> > >> $ size restrict-ifaces.bpf.o
> >> >> > >
> >> >> > > $ size
> >> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> >> >> > >    text       data        bss        dec        hex    filename
> >> >> > >     386         25          0        411        19b
> >> >> > > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> >> >> >
> >> >> > Right, so the .bss section is empty.  I see a `const volatile unsigned
> >> >> > char is_allow_list = 0;' in restrict-ifaces.bpf.c, but that goes to
> >> >> > .data and not to .bss, as expected.
> >> >> >
> >> >> > If you build restrict-ifaces.bpf.o with LLVM, is the bss still empty?  I
> >> >> > don't think the code in libbpf.c even checks for this eventuality...
> >> >>
> >> >> LLVM version(which skeleton generation works with):
> >> >> $ size restrict-ifaces.bpf.o
> >> >>    text       data        bss        dec        hex    filename
> >> >>     323         24          0        347        15b    restrict-ifaces.bpf.o
> >> >>
> >> >> $ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> >> >> btf dump file restrict-ifaces.bpf.o format raw
> >> >> [1] PTR '(anon)' type_id=3
> >> >> [2] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
> >> >> [3] ARRAY '(anon)' type_id=2 index_type_id=4 nr_elems=1
> >> >> [4] INT '__ARRAY_SIZE_TYPE__' size=4 bits_offset=0 nr_bits=32 encoding=(none)
> >> >> [5] PTR '(anon)' type_id=6
> >> >> [6] TYPEDEF '__u32' type_id=7
> >> >> [7] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
> >> >> [8] PTR '(anon)' type_id=9
> >> >> [9] TYPEDEF '__u8' type_id=10
> >> >> [10] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=(none)
> >> >> [11] STRUCT '(anon)' size=24 vlen=3
> >> >>     'type' type_id=1 bits_offset=0
> >> >>     'key' type_id=5 bits_offset=64
> >> >>     'value' type_id=8 bits_offset=128
> >> >> [12] VAR 'sd_restrictif' type_id=11, linkage=global
> >> >> [13] PTR '(anon)' type_id=14
> >> >> [14] CONST '(anon)' type_id=15
> >> >> [15] STRUCT '__sk_buff' size=192 vlen=33
> >> >>     'len' type_id=6 bits_offset=0
> >> >>     'pkt_type' type_id=6 bits_offset=32
> >> >>     'mark' type_id=6 bits_offset=64
> >> >>     'queue_mapping' type_id=6 bits_offset=96
> >> >>     'protocol' type_id=6 bits_offset=128
> >> >>     'vlan_present' type_id=6 bits_offset=160
> >> >>     'vlan_tci' type_id=6 bits_offset=192
> >> >>     'vlan_proto' type_id=6 bits_offset=224
> >> >>     'priority' type_id=6 bits_offset=256
> >> >>     'ingress_ifindex' type_id=6 bits_offset=288
> >> >>     'ifindex' type_id=6 bits_offset=320
> >> >>     'tc_index' type_id=6 bits_offset=352
> >> >>     'cb' type_id=16 bits_offset=384
> >> >>     'hash' type_id=6 bits_offset=544
> >> >>     'tc_classid' type_id=6 bits_offset=576
> >> >>     'data' type_id=6 bits_offset=608
> >> >>     'data_end' type_id=6 bits_offset=640
> >> >>     'napi_id' type_id=6 bits_offset=672
> >> >>     'family' type_id=6 bits_offset=704
> >> >>     'remote_ip4' type_id=6 bits_offset=736
> >> >>     'local_ip4' type_id=6 bits_offset=768
> >> >>     'remote_ip6' type_id=17 bits_offset=800
> >> >>     'local_ip6' type_id=17 bits_offset=928
> >> >>     'remote_port' type_id=6 bits_offset=1056
> >> >>     'local_port' type_id=6 bits_offset=1088
> >> >>     'data_meta' type_id=6 bits_offset=1120
> >> >>     '(anon)' type_id=18 bits_offset=1152
> >> >>     'tstamp' type_id=20 bits_offset=1216
> >> >>     'wire_len' type_id=6 bits_offset=1280
> >> >>     'gso_segs' type_id=6 bits_offset=1312
> >> >>     '(anon)' type_id=22 bits_offset=1344
> >> >>     'gso_size' type_id=6 bits_offset=1408
> >> >>     'hwtstamp' type_id=20 bits_offset=1472
> >> >> [16] ARRAY '(anon)' type_id=6 index_type_id=4 nr_elems=5
> >> >> [17] ARRAY '(anon)' type_id=6 index_type_id=4 nr_elems=4
> >> >> [18] UNION '(anon)' size=8 vlen=1
> >> >>     'flow_keys' type_id=19 bits_offset=0
> >> >> [19] PTR '(anon)' type_id=34
> >> >> [20] TYPEDEF '__u64' type_id=21
> >> >> [21] INT 'unsigned long long' size=8 bits_offset=0 nr_bits=64 encoding=(none)
> >> >> [22] UNION '(anon)' size=8 vlen=1
> >> >>     'sk' type_id=23 bits_offset=0
> >> >> [23] PTR '(anon)' type_id=35
> >> >> [24] FUNC_PROTO '(anon)' ret_type_id=2 vlen=1
> >> >>     'sk' type_id=13
> >> >> [25] FUNC 'sd_restrictif_e' type_id=24 linkage=global
> >> >> [26] FUNC 'sd_restrictif_i' type_id=24 linkage=global
> >> >> [27] CONST '(anon)' type_id=28
> >> >> [28] VOLATILE '(anon)' type_id=9
> >> >> [29] VAR 'is_allow_list' type_id=27, linkage=global
> >> >> [30] CONST '(anon)' type_id=31
> >> >> [31] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=SIGNED
> >> >> [32] ARRAY '(anon)' type_id=30 index_type_id=4 nr_elems=18
> >> >> [33] VAR '_license' type_id=32, linkage=static
> >> >> [34] FWD 'bpf_flow_keys' fwd_kind=struct
> >> >> [35] FWD 'bpf_sock' fwd_kind=struct
> >> >> [36] DATASEC '.rodata' size=1 vlen=1
> >> >>     type_id=29 offset=0 size=1 (VAR 'is_allow_list')
> >> >> [37] DATASEC 'license' size=18 vlen=1
> >> >>     type_id=33 offset=0 size=18 (VAR '_license')
> >> >> [38] DATASEC '.maps' size=24 vlen=1
> >> >>     type_id=12 offset=0 size=24 (VAR 'sd_restrictif')
> >> >>
> >> >
> >> > Skeleton generation debug output for GCC(failing) and LLVM(working)
> >> > which may be helpful:
> >>
> >> Indeed it was helpful :)
> >>
> >> The GNU assembler generates an empty .bss section.  This is a well
> >> established behavior in GAS that happens in all supported targets.
> >>
> >> The LLVM assembler doesn't generate an empty .bss section.
> >>
> >> bpftool chokes on the empty .bss section.
> >>
> >> In this case I would suggest to fix bpf_object__init_global_data_maps in
> >> order to skip empty sections.
> >>
> >> Something like this:
> >
> > Hmm, that seems to segfault:
>
> Yes, I see in bpf_object__elf_collect that sec_desc->data is not
> initialized when a section is not recognized.  In this case, this
> happens with .comment.
>
> All right then:
>
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index e89cc9c885b3..887b78780099 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -1591,6 +1591,10 @@ static int bpf_object__init_global_data_maps(struct bpf_object *obj)
>         for (sec_idx = 1; sec_idx < obj->efile.sec_cnt; sec_idx++) {
>                 sec_desc = &obj->efile.secs[sec_idx];
>
> +                /* Skip recognized sections with size 0.  */
> +                if (sec_desc->data && sec_desc->data->d_size == 0)
> +                  continue;
> +
>                 switch (sec_desc->sec_type) {
>                 case SEC_DATA:
>                         sec_name = elf_sec_name(obj, elf_sec_by_idx(obj, sec_idx));

Ok, skeleton is now getting generated successfully, however it differs from the
clang version so there's a build error when we include/use the header:
../src/core/restrict-ifaces.c: In function ‘prepare_restrict_ifaces_bpf’:
../src/core/restrict-ifaces.c:45:14: error: ‘struct
restrict_ifaces_bpf’ has no member named ‘rodata’; did you mean
‘data’?
   45 |         obj->rodata->is_allow_list = is_allow_list;
      |              ^~~~~~
      |              data

The issue appears to be that clang generates "rodata" members in
restrict_ifaces_bpf while with gcc we get "data" members instead.

Differences below:

GCC:
$ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
--debug gen skeleton
output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
libbpf: loading object 'restrict_ifaces_bpf' from buffer
libbpf: elf: section(2) .symtab, size 336, link 1, flags 0, type=2
libbpf: elf: section(3) .data, size 1, link 0, flags 3, type=1
libbpf: elf: section(4) .bss, size 0, link 0, flags 3, type=8
libbpf: elf: section(5) cgroup_skb/egress, size 184, link 0, flags 6, type=1
libbpf: sec 'cgroup_skb/egress': found program 'sd_restrictif_e' at
insn offset 0 (0 bytes), code size 23 insns (184 bytes)
libbpf: elf: section(6) cgroup_skb/ingress, size 184, link 0, flags 6, type=1
libbpf: sec 'cgroup_skb/ingress': found program 'sd_restrictif_i' at
insn offset 0 (0 bytes), code size 23 insns (184 bytes)
libbpf: elf: section(7) license, size 18, link 0, flags 2, type=1
libbpf: license of restrict_ifaces_bpf is LGPL-2.1-or-later
libbpf: elf: section(8) .maps, size 24, link 0, flags 3, type=1
libbpf: elf: section(9) .comment, size 49, link 0, flags 30, type=1
libbpf: elf: skipping unrecognized data section(9) .comment
libbpf: elf: section(10) .relcgroup_skb/egress, size 32, link 2, flags
40, type=9
libbpf: elf: section(11) .relcgroup_skb/ingress, size 32, link 2,
flags 40, type=9
libbpf: elf: section(12) .BTF, size 3606, link 0, flags 0, type=1
libbpf: looking for externs among 14 symbols...
libbpf: collected 0 externs total
libbpf: map 'sd_restrictif': at sec_idx 8, offset 0.
libbpf: map 'sd_restrictif': found type = 1.
libbpf: map 'sd_restrictif': found key [12], sz = 4.
libbpf: map 'sd_restrictif': found value [3], sz = 1.
libbpf: map 'restrict.data' (global data): at sec_idx 3, offset 0, flags 400.
libbpf: map 1 is "restrict.data"
libbpf: sec '.relcgroup_skb/egress': collecting relocation for
section(5) 'cgroup_skb/egress'
libbpf: sec '.relcgroup_skb/egress': relo #0: insn #4 against 'sd_restrictif'
libbpf: prog 'sd_restrictif_e': found map 0 (sd_restrictif, sec 8, off
0) for insn #4
libbpf: sec '.relcgroup_skb/egress': relo #1: insn #7 against 'is_allow_list'
libbpf: prog 'sd_restrictif_e': found data map 1 (restrict.data, sec
3, off 0) for insn 7
libbpf: sec '.relcgroup_skb/ingress': collecting relocation for
section(6) 'cgroup_skb/ingress'
libbpf: sec '.relcgroup_skb/ingress': relo #0: insn #4 against 'sd_restrictif'
libbpf: prog 'sd_restrictif_i': found map 0 (sd_restrictif, sec 8, off
0) for insn #4
libbpf: sec '.relcgroup_skb/ingress': relo #1: insn #7 against 'is_allow_list'
libbpf: prog 'sd_restrictif_i': found data map 1 (restrict.data, sec
3, off 0) for insn 7
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */

/* THIS FILE IS AUTOGENERATED BY BPFTOOL! */
#ifndef __RESTRICT_IFACES_BPF_SKEL_H__
#define __RESTRICT_IFACES_BPF_SKEL_H__

#include <errno.h>
#include <stdlib.h>
#include <bpf/libbpf.h>

struct restrict_ifaces_bpf {
    struct bpf_object_skeleton *skeleton;
    struct bpf_object *obj;
    struct {
        struct bpf_map *sd_restrictif;
        struct bpf_map *data;
    } maps;
    struct {
        struct bpf_program *sd_restrictif_e;
        struct bpf_program *sd_restrictif_i;
    } progs;
    struct {
        struct bpf_link *sd_restrictif_e;
        struct bpf_link *sd_restrictif_i;
    } links;
    struct restrict_ifaces_bpf__data {
        __u8 is_allow_list;
    } *data;

#ifdef __cplusplus
    static inline struct restrict_ifaces_bpf *open(const struct
bpf_object_open_opts *opts = nullptr);
    static inline struct restrict_ifaces_bpf *open_and_load();
    static inline int load(struct restrict_ifaces_bpf *skel);
    static inline int attach(struct restrict_ifaces_bpf *skel);
    static inline void detach(struct restrict_ifaces_bpf *skel);
    static inline void destroy(struct restrict_ifaces_bpf *skel);
    static inline const void *elf_bytes(size_t *sz);
#endif /* __cplusplus */
};

static void
restrict_ifaces_bpf__destroy(struct restrict_ifaces_bpf *obj)
{
    if (!obj)
        return;
    if (obj->skeleton)
        bpf_object__destroy_skeleton(obj->skeleton);
    free(obj);
}

static inline int
restrict_ifaces_bpf__create_skeleton(struct restrict_ifaces_bpf *obj);

static inline struct restrict_ifaces_bpf *
restrict_ifaces_bpf__open_opts(const struct bpf_object_open_opts *opts)
{
    struct restrict_ifaces_bpf *obj;
    int err;

    obj = (struct restrict_ifaces_bpf *)calloc(1, sizeof(*obj));
    if (!obj) {
        errno = ENOMEM;
        return NULL;
    }

    err = restrict_ifaces_bpf__create_skeleton(obj);
    if (err)
        goto err_out;

    err = bpf_object__open_skeleton(obj->skeleton, opts);
    if (err)
        goto err_out;

    return obj;
err_out:
    restrict_ifaces_bpf__destroy(obj);
    errno = -err;
    return NULL;
}

static inline struct restrict_ifaces_bpf *
restrict_ifaces_bpf__open(void)
{
    return restrict_ifaces_bpf__open_opts(NULL);
}

static inline int
restrict_ifaces_bpf__load(struct restrict_ifaces_bpf *obj)
{
    return bpf_object__load_skeleton(obj->skeleton);
}

static inline struct restrict_ifaces_bpf *
restrict_ifaces_bpf__open_and_load(void)
{
    struct restrict_ifaces_bpf *obj;
    int err;

    obj = restrict_ifaces_bpf__open();
    if (!obj)
        return NULL;
    err = restrict_ifaces_bpf__load(obj);
    if (err) {
        restrict_ifaces_bpf__destroy(obj);
        errno = -err;
        return NULL;
    }
    return obj;
}

static inline int
restrict_ifaces_bpf__attach(struct restrict_ifaces_bpf *obj)
{
    return bpf_object__attach_skeleton(obj->skeleton);
}

static inline void
restrict_ifaces_bpf__detach(struct restrict_ifaces_bpf *obj)
{
    return bpf_object__detach_skeleton(obj->skeleton);
}

static inline const void *restrict_ifaces_bpf__elf_bytes(size_t *sz);

static inline int
restrict_ifaces_bpf__create_skeleton(struct restrict_ifaces_bpf *obj)
{
    struct bpf_object_skeleton *s;
    int err;

    s = (struct bpf_object_skeleton *)calloc(1, sizeof(*s));
    if (!s)    {
        err = -ENOMEM;
        goto err;
    }

    s->sz = sizeof(*s);
    s->name = "restrict_ifaces_bpf";
    s->obj = &obj->obj;

    /* maps */
    s->map_cnt = 2;
    s->map_skel_sz = sizeof(*s->maps);
    s->maps = (struct bpf_map_skeleton *)calloc(s->map_cnt, s->map_skel_sz);
    if (!s->maps) {
        err = -ENOMEM;
        goto err;
    }

    s->maps[0].name = "sd_restrictif";
    s->maps[0].map = &obj->maps.sd_restrictif;

    s->maps[1].name = "restrict.data";
    s->maps[1].map = &obj->maps.data;
    s->maps[1].mmaped = (void **)&obj->data;

    /* programs */
    s->prog_cnt = 2;
    s->prog_skel_sz = sizeof(*s->progs);
    s->progs = (struct bpf_prog_skeleton *)calloc(s->prog_cnt, s->prog_skel_sz);
    if (!s->progs) {
        err = -ENOMEM;
        goto err;
    }

    s->progs[0].name = "sd_restrictif_e";
    s->progs[0].prog = &obj->progs.sd_restrictif_e;
    s->progs[0].link = &obj->links.sd_restrictif_e;

    s->progs[1].name = "sd_restrictif_i";
    s->progs[1].prog = &obj->progs.sd_restrictif_i;
    s->progs[1].link = &obj->links.sd_restrictif_i;

    s->data = (void *)restrict_ifaces_bpf__elf_bytes(&s->data_sz);

    obj->skeleton = s;
    return 0;
err:
    bpf_object__destroy_skeleton(s);
    return err;
}

static inline const void *restrict_ifaces_bpf__elf_bytes(size_t *sz)
{
    *sz = 5616;
    return (const void *)"\
\x7f\x45\x4c\x46\x02\x01\x01\0\0\0\0\0\0\0\0\0\x01\0\xf7\0\x01\0\0\0\0\0\0\0\0\
\0\0\0\0\0\0\0\0\0\0\0\xb0\x12\0\0\0\0\0\0\0\0\0\0\x40\0\0\0\0\0\x40\0\x0d\0\
\x01\0\0\x2e\x73\x74\x72\x74\x61\x62\0\x2e\x73\x79\x6d\x74\x61\x62\0\x2e\x64\
\x61\x74\x61\0\x2e\x62\x73\x73\0\x63\x67\x72\x6f\x75\x70\x5f\x73\x6b\x62\x2f\
\x65\x67\x72\x65\x73\x73\0\x63\x67\x72\x6f\x75\x70\x5f\x73\x6b\x62\x2f\x69\x6e\
\x67\x72\x65\x73\x73\0\x6c\x69\x63\x65\x6e\x73\x65\0\x2e\x6d\x61\x70\x73\0\x2e\
\x63\x6f\x6d\x6d\x65\x6e\x74\0\x72\x65\x73\x74\x72\x69\x63\x74\x2d\x69\x66\x61\
\x63\x65\x73\x2e\x62\x70\x66\x2e\x63\0\x5f\x6c\x69\x63\x65\x6e\x73\x65\0\x73\
\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\x5f\x65\0\x73\x64\x5f\x72\x65\
\x73\x74\x72\x69\x63\x74\x69\x66\0\x69\x73\x5f\x61\x6c\x6c\x6f\x77\x5f\x6c\x69\
\x73\x74\0\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\x5f\x69\0\x2e\
\x72\x65\x6c\x63\x67\x72\x6f\x75\x70\x5f\x73\x6b\x62\x2f\x65\x67\x72\x65\x73\
\x73\0\x2e\x72\x65\x6c\x63\x67\x72\x6f\x75\x70\x5f\x73\x6b\x62\x2f\x69\x6e\x67\
\x72\x65\x73\x73\0\x2e\x42\x54\x46\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
\0\0\0\0\0\0\x58\0\0\0\x04\0\xf1\xff\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
\x03\0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x03\0\x04\0\0\0\0\0\0\0\0\
\0\0\0\0\0\0\0\0\0\0\0\0\0\x03\0\x05\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
\x03\0\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x03\0\x07\0\0\0\0\0\0\0\0\
\0\0\0\0\0\0\0\0\0\x6e\0\0\0\x01\0\x07\0\0\0\0\0\0\0\0\0\x12\0\0\0\0\0\0\0\0\0\
\0\0\x03\0\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x03\0\x09\0\0\0\0\0\0\
\0\0\0\0\0\0\0\0\0\0\0\x77\0\0\0\x12\0\x05\0\0\0\0\0\0\0\0\0\xb8\0\0\0\0\0\0\0\
\x87\0\0\0\x11\0\x08\0\0\0\0\0\0\0\0\0\x18\0\0\0\0\0\0\0\x95\0\0\0\x11\0\x03\0\
\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\xa3\0\0\0\x12\0\x06\0\0\0\0\0\0\0\0\0\xb8\0\
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x61\x10\x28\0\0\0\0\0\x63\x0a\xfc\xff\0\0\0\0\xbf\
\xa2\0\0\0\0\0\0\x07\x02\0\0\xfc\xff\xff\xff\x18\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\
\0\x85\0\0\0\x01\0\0\0\x18\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x71\x13\0\0\0\0\0\0\
\x57\x03\0\0\xff\0\0\0\x15\x03\x05\0\0\0\0\0\xbf\x02\0\0\0\0\0\0\x87\x02\0\0\0\
\0\0\0\x4f\x20\0\0\0\0\0\0\x77\0\0\0\x3f\0\0\0\x95\0\0\0\0\0\0\0\xb7\x01\0\0\
\x01\0\0\0\x15\0\x01\0\0\0\0\0\xbf\x31\0\0\0\0\0\0\xbf\x10\0\0\0\0\0\0\x57\0\0\
\0\x01\0\0\0\x95\0\0\0\0\0\0\0\x61\x10\x28\0\0\0\0\0\x63\x0a\xfc\xff\0\0\0\0\
\xbf\xa2\0\0\0\0\0\0\x07\x02\0\0\xfc\xff\xff\xff\x18\x01\0\0\0\0\0\0\0\0\0\0\0\
\0\0\0\x85\0\0\0\x01\0\0\0\x18\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x71\x13\0\0\0\0\
\0\0\x57\x03\0\0\xff\0\0\0\x15\x03\x05\0\0\0\0\0\xbf\x02\0\0\0\0\0\0\x87\x02\0\
\0\0\0\0\0\x4f\x20\0\0\0\0\0\0\x77\0\0\0\x3f\0\0\0\x95\0\0\0\0\0\0\0\xb7\x01\0\
\0\x01\0\0\0\x15\0\x01\0\0\0\0\0\xbf\x31\0\0\0\0\0\0\xbf\x10\0\0\0\0\0\0\x57\0\
\0\0\x01\0\0\0\x95\0\0\0\0\0\0\0\x4c\x47\x50\x4c\x2d\x32\x2e\x31\x2d\x6f\x72\
\x2d\x6c\x61\x74\x65\x72\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
\0\0\0\0\0\x47\x43\x43\x3a\x20\x28\x42\x75\x69\x6c\x64\x72\x6f\x6f\x74\x20\x32\
\x30\x32\x32\x2e\x30\x35\x2d\x31\x33\x32\x2d\x67\x35\x32\x38\x62\x35\x61\x36\
\x35\x66\x36\x29\x20\x31\x32\x2e\x31\x2e\x30\0\0\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\
\x01\0\0\0\x0b\0\0\0\x38\0\0\0\0\0\0\0\x01\0\0\0\x0c\0\0\0\x20\0\0\0\0\0\0\0\
\x01\0\0\0\x0b\0\0\0\x38\0\0\0\0\0\0\0\x01\0\0\0\x0c\0\0\0\x9f\xeb\x01\0\x18\0\
\0\0\0\0\0\0\x9c\x07\0\0\x9c\x07\0\0\x62\x06\0\0\x01\0\0\0\0\0\0\x01\x01\0\0\0\
\x08\0\0\x03\x0d\0\0\0\0\0\0\x01\x01\0\0\0\x08\0\0\x02\x1b\0\0\0\0\0\0\x08\x02\
\0\0\0\0\0\0\0\0\0\0\x0a\x03\0\0\0\0\0\0\0\0\0\0\x09\x04\0\0\0\x20\0\0\0\0\0\0\
\x01\x02\0\0\0\x10\0\0\x01\x2a\0\0\0\0\0\0\x01\x02\0\0\0\x10\0\0\0\x3d\0\0\0\0\
\0\0\x08\x07\0\0\0\x43\0\0\0\0\0\0\x01\x04\0\0\0\x20\0\0\x01\x47\0\0\0\0\0\0\
\x08\x09\0\0\0\x4d\0\0\0\0\0\0\x01\x04\0\0\0\x20\0\0\0\x5a\0\0\0\0\0\0\x08\x0b\
\0\0\0\x60\0\0\0\0\0\0\x01\x08\0\0\0\x40\0\0\x01\x6e\0\0\0\0\0\0\x01\x08\0\0\0\
\x40\0\0\0\x85\0\0\0\0\0\0\x08\x0e\0\0\0\x8b\0\0\0\0\0\0\x01\x08\0\0\0\x40\0\0\
\0\x9d\0\0\0\0\0\0\x01\x08\0\0\0\x40\0\0\x01\xa6\0\0\0\0\0\0\x01\x01\0\0\0\x08\
\0\0\x03\0\0\0\0\0\0\0\x0a\x12\0\0\0\xab\0\0\0\0\0\0\x08\x08\0\0\0\xb2\0\0\0\0\
\0\0\x08\x0c\0\0\0\xb9\0\0\0\x1f\0\0\x06\x04\0\0\0\xc6\0\0\0\0\0\0\0\xda\0\0\0\
\x01\0\0\0\xec\0\0\0\x02\0\0\0\xff\0\0\0\x03\0\0\0\x17\x01\0\0\x04\0\0\0\x35\
\x01\0\0\x05\0\0\0\x4e\x01\0\0\x06\0\0\0\x68\x01\0\0\x07\0\0\0\x81\x01\0\0\x08\
\0\0\0\x9b\x01\0\0\x09\0\0\0\xb1\x01\0\0\x0a\0\0\0\xce\x01\0\0\x0b\0\0\0\xe4\
\x01\0\0\x0c\0\0\0\xff\x01\0\0\x0d\0\0\0\x19\x02\0\0\x0e\0\0\0\x2d\x02\0\0\x0f\
\0\0\0\x42\x02\0\0\x10\0\0\0\x56\x02\0\0\x11\0\0\0\x6a\x02\0\0\x12\0\0\0\x80\
\x02\0\0\x13\0\0\0\x9c\x02\0\0\x14\0\0\0\xbd\x02\0\0\x15\0\0\0\xe0\x02\0\0\x16\
\0\0\0\xf3\x02\0\0\x17\0\0\0\x06\x03\0\0\x18\0\0\0\x1e\x03\0\0\x19\0\0\0\x37\
\x03\0\0\x1a\0\0\0\x4f\x03\0\0\x1b\0\0\0\x64\x03\0\0\x1c\0\0\0\x7f\x03\0\0\x1d\
\0\0\0\x99\x03\0\0\x1e\0\0\0\0\0\0\0\x01\0\0\x05\x08\0\0\0\xb3\x03\0\0\x1d\0\0\
\0\0\0\0\0\xbd\x03\0\0\x0d\0\0\x04\x38\0\0\0\xcb\x03\0\0\x08\0\0\0\0\0\0\0\xd1\
\x03\0\0\x08\0\0\0\x10\0\0\0\xd7\x03\0\0\x08\0\0\0\x20\0\0\0\xe2\x03\0\0\x03\0\
\0\0\x30\0\0\0\xea\x03\0\0\x03\0\0\0\x38\0\0\0\xf8\x03\0\0\x03\0\0\0\x40\0\0\0\
\x01\x04\0\0\x03\0\0\0\x48\0\0\0\x0a\x04\0\0\x14\0\0\0\x50\0\0\0\x12\x04\0\0\
\x14\0\0\0\x60\0\0\0\x18\x04\0\0\x14\0\0\0\x70\0\0\0\0\0\0\0\x19\0\0\0\x80\0\0\
\0\x1e\x04\0\0\x0c\0\0\0\x80\x01\0\0\x24\x04\0\0\x15\0\0\0\xa0\x01\0\0\0\0\0\0\
\x02\0\0\x05\x20\0\0\0\0\0\0\0\x1a\0\0\0\0\0\0\0\0\0\0\0\x1b\0\0\0\0\0\0\0\0\0\
\0\0\x02\0\0\x04\x08\0\0\0\x2f\x04\0\0\x15\0\0\0\0\0\0\0\x38\x04\0\0\x15\0\0\0\
\x20\0\0\0\0\0\0\0\x02\0\0\x04\x20\0\0\0\x41\x04\0\0\x1c\0\0\0\0\0\0\0\x4a\x04\
\0\0\x1c\0\0\0\x80\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x0c\0\0\0\x10\0\0\0\x04\0\0\
\0\0\0\0\0\0\0\0\x02\x18\0\0\0\0\0\0\0\x01\0\0\x05\x08\0\0\0\x53\x04\0\0\x20\0\
\0\0\0\0\0\0\x56\x04\0\0\x0e\0\0\x04\x50\0\0\0\x5f\x04\0\0\x0c\0\0\0\0\0\0\0\
\x6c\x04\0\0\x0c\0\0\0\x20\0\0\0\x73\x04\0\0\x0c\0\0\0\x40\0\0\0\x78\x04\0\0\
\x0c\0\0\0\x60\0\0\0\x81\x04\0\0\x0c\0\0\0\x80\0\0\0\x86\x04\0\0\x0c\0\0\0\xa0\
\0\0\0\x8f\x04\0\0\x0c\0\0\0\xc0\0\0\0\x97\x04\0\0\x1c\0\0\0\xe0\0\0\0\x9f\x04\
\0\0\x0c\0\0\0\x60\x01\0\0\xa8\x04\0\0\x14\0\0\0\x80\x01\0\0\xb1\x04\0\0\x0c\0\
\0\0\xa0\x01\0\0\xb9\x04\0\0\x1c\0\0\0\xc0\x01\0\0\xc1\x04\0\0\x0c\0\0\0\x40\
\x02\0\0\xc7\x04\0\0\x0a\0\0\0\x60\x02\0\0\0\0\0\0\0\0\0\x02\x1f\0\0\0\xd8\x04\
\0\0\x21\0\0\x04\xc0\0\0\0\xe2\x04\0\0\x0c\0\0\0\0\0\0\0\xe6\x04\0\0\x0c\0\0\0\
\x20\0\0\0\x81\x04\0\0\x0c\0\0\0\x40\0\0\0\xef\x04\0\0\x0c\0\0\0\x60\0\0\0\x78\
\x04\0\0\x0c\0\0\0\x80\0\0\0\xfd\x04\0\0\x0c\0\0\0\xa0\0\0\0\x0a\x05\0\0\x0c\0\
\0\0\xc0\0\0\0\x13\x05\0\0\x0c\0\0\0\xe0\0\0\0\x86\x04\0\0\x0c\0\0\0\0\x01\0\0\
\x1e\x05\0\0\x0c\0\0\0\x20\x01\0\0\x2e\x05\0\0\x0c\0\0\0\x40\x01\0\0\x36\x05\0\
\0\x0c\0\0\0\x60\x01\0\0\x3f\x05\0\0\x22\0\0\0\x80\x01\0\0\x42\x05\0\0\x0c\0\0\
\0\x20\x02\0\0\x47\x05\0\0\x0c\0\0\0\x40\x02\0\0\x52\x05\0\0\x0c\0\0\0\x60\x02\
\0\0\x57\x05\0\0\x0c\0\0\0\x80\x02\0\0\x60\x05\0\0\x0c\0\0\0\xa0\x02\0\0\x6c\
\x04\0\0\x0c\0\0\0\xc0\x02\0\0\x68\x05\0\0\x0c\0\0\0\xe0\x02\0\0\x73\x05\0\0\
\x0c\0\0\0\0\x03\0\0\x7d\x05\0\0\x1c\0\0\0\x20\x03\0\0\x88\x05\0\0\x1c\0\0\0\
\xa0\x03\0\0\x92\x05\0\0\x0c\0\0\0\x20\x04\0\0\x9e\x05\0\0\x0c\0\0\0\x40\x04\0\
\0\xa9\x05\0\0\x0c\0\0\0\x60\x04\0\0\0\0\0\0\x17\0\0\0\x80\x04\0\0\xb3\x05\0\0\
\x0f\0\0\0\xc0\x04\0\0\xba\x05\0\0\x0c\0\0\0\0\x05\0\0\xc3\x05\0\0\x0c\0\0\0\
\x20\x05\0\0\0\0\0\0\x1e\0\0\0\x40\x05\0\0\xcc\x05\0\0\x0c\0\0\0\x80\x05\0\0\
\xd5\x05\0\0\x0f\0\0\0\xc0\x05\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x0c\0\0\0\x10\0\0\
\0\x05\0\0\0\0\0\0\0\0\0\0\x0a\x21\0\0\0\0\0\0\0\0\0\0\x02\0\0\0\0\0\0\0\0\x03\
\0\0\x04\x18\0\0\0\x73\x04\0\0\x27\0\0\0\0\0\0\0\xde\x05\0\0\x28\0\0\0\x40\0\0\
\0\xe2\x05\0\0\x29\0\0\0\x80\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x09\0\0\0\x10\0\0\
\0\x01\0\0\0\0\0\0\0\0\0\0\x02\x26\0\0\0\0\0\0\0\0\0\0\x02\x0c\0\0\0\0\0\0\0\0\
\0\0\x02\x03\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x13\0\0\0\x10\0\0\0\x12\0\0\0\0\0\
\0\0\0\0\0\x0a\x2a\0\0\0\0\0\0\0\x02\0\0\x0d\x24\0\0\0\0\0\0\0\x24\0\0\0\0\0\0\
\0\x2e\0\0\0\0\0\0\0\0\0\0\x0a\0\0\0\0\0\0\0\0\0\0\0\x02\x2d\0\0\0\0\0\0\0\x01\
\0\0\x0d\x09\0\0\0\x53\x04\0\0\x30\0\0\0\0\0\0\0\0\0\0\x02\x23\0\0\0\xe8\x05\0\
\0\0\0\0\x0e\x2b\0\0\0\0\0\0\0\xf1\x05\0\0\0\0\0\x0e\x05\0\0\0\x01\0\0\0\xff\
\x05\0\0\0\0\0\x0e\x25\0\0\0\x01\0\0\0\x0d\x06\0\0\x01\0\0\x0c\x2f\0\0\0\x1d\
\x06\0\0\x01\0\0\x0c\x2f\0\0\0\x2d\x06\0\0\0\0\0\x0c\x2f\0\0\0\x4e\x06\0\0\x01\
\0\0\x0f\x01\0\0\0\x32\0\0\0\0\0\0\0\x01\0\0\0\x54\x06\0\0\x01\0\0\x0f\x12\0\0\
\0\x31\0\0\0\0\0\0\0\x12\0\0\0\x5c\x06\0\0\x01\0\0\x0f\x18\0\0\0\x33\0\0\0\0\0\
\0\0\x18\0\0\0\0\x73\x69\x67\x6e\x65\x64\x20\x63\x68\x61\x72\0\x75\x6e\x73\x69\
\x67\x6e\x65\x64\x20\x63\x68\x61\x72\0\x5f\x5f\x75\x38\0\x73\x68\x6f\x72\x74\
\x20\x69\x6e\x74\0\x73\x68\x6f\x72\x74\x20\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\
\x69\x6e\x74\0\x5f\x5f\x75\x31\x36\0\x69\x6e\x74\0\x5f\x5f\x73\x33\x32\0\x75\
\x6e\x73\x69\x67\x6e\x65\x64\x20\x69\x6e\x74\0\x5f\x5f\x75\x33\x32\0\x6c\x6f\
\x6e\x67\x20\x6c\x6f\x6e\x67\x20\x69\x6e\x74\0\x6c\x6f\x6e\x67\x20\x6c\x6f\x6e\
\x67\x20\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x69\x6e\x74\0\x5f\x5f\x75\x36\x34\
\0\x6c\x6f\x6e\x67\x20\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x69\x6e\x74\0\x6c\
\x6f\x6e\x67\x20\x69\x6e\x74\0\x63\x68\x61\x72\0\x5f\x5f\x62\x65\x31\x36\0\x5f\
\x5f\x62\x65\x33\x32\0\x62\x70\x66\x5f\x6d\x61\x70\x5f\x74\x79\x70\x65\0\x42\
\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x55\x4e\x53\x50\x45\x43\0\x42\
\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x48\x41\x53\x48\0\x42\x50\x46\
\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x41\x52\x52\x41\x59\0\x42\x50\x46\x5f\
\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x50\x52\x4f\x47\x5f\x41\x52\x52\x41\x59\0\
\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x50\x45\x52\x46\x5f\x45\
\x56\x45\x4e\x54\x5f\x41\x52\x52\x41\x59\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\
\x59\x50\x45\x5f\x50\x45\x52\x43\x50\x55\x5f\x48\x41\x53\x48\0\x42\x50\x46\x5f\
\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x50\x45\x52\x43\x50\x55\x5f\x41\x52\x52\
\x41\x59\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x53\x54\x41\x43\
\x4b\x5f\x54\x52\x41\x43\x45\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\
\x5f\x43\x47\x52\x4f\x55\x50\x5f\x41\x52\x52\x41\x59\0\x42\x50\x46\x5f\x4d\x41\
\x50\x5f\x54\x59\x50\x45\x5f\x4c\x52\x55\x5f\x48\x41\x53\x48\0\x42\x50\x46\x5f\
\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x4c\x52\x55\x5f\x50\x45\x52\x43\x50\x55\
\x5f\x48\x41\x53\x48\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x4c\
\x50\x4d\x5f\x54\x52\x49\x45\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\
\x5f\x41\x52\x52\x41\x59\x5f\x4f\x46\x5f\x4d\x41\x50\x53\0\x42\x50\x46\x5f\x4d\
\x41\x50\x5f\x54\x59\x50\x45\x5f\x48\x41\x53\x48\x5f\x4f\x46\x5f\x4d\x41\x50\
\x53\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x44\x45\x56\x4d\x41\
\x50\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x53\x4f\x43\x4b\x4d\
\x41\x50\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x43\x50\x55\x4d\
\x41\x50\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x58\x53\x4b\x4d\
\x41\x50\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x53\x4f\x43\x4b\
\x48\x41\x53\x48\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x43\x47\
\x52\x4f\x55\x50\x5f\x53\x54\x4f\x52\x41\x47\x45\0\x42\x50\x46\x5f\x4d\x41\x50\
\x5f\x54\x59\x50\x45\x5f\x52\x45\x55\x53\x45\x50\x4f\x52\x54\x5f\x53\x4f\x43\
\x4b\x41\x52\x52\x41\x59\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\
\x50\x45\x52\x43\x50\x55\x5f\x43\x47\x52\x4f\x55\x50\x5f\x53\x54\x4f\x52\x41\
\x47\x45\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x51\x55\x45\x55\
\x45\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x53\x54\x41\x43\x4b\
\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x53\x4b\x5f\x53\x54\x4f\
\x52\x41\x47\x45\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x44\x45\
\x56\x4d\x41\x50\x5f\x48\x41\x53\x48\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\
\x50\x45\x5f\x53\x54\x52\x55\x43\x54\x5f\x4f\x50\x53\0\x42\x50\x46\x5f\x4d\x41\
\x50\x5f\x54\x59\x50\x45\x5f\x52\x49\x4e\x47\x42\x55\x46\0\x42\x50\x46\x5f\x4d\
\x41\x50\x5f\x54\x59\x50\x45\x5f\x49\x4e\x4f\x44\x45\x5f\x53\x54\x4f\x52\x41\
\x47\x45\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x54\x41\x53\x4b\
\x5f\x53\x54\x4f\x52\x41\x47\x45\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\
\x45\x5f\x42\x4c\x4f\x4f\x4d\x5f\x46\x49\x4c\x54\x45\x52\0\x66\x6c\x6f\x77\x5f\
\x6b\x65\x79\x73\0\x62\x70\x66\x5f\x66\x6c\x6f\x77\x5f\x6b\x65\x79\x73\0\x6e\
\x68\x6f\x66\x66\0\x74\x68\x6f\x66\x66\0\x61\x64\x64\x72\x5f\x70\x72\x6f\x74\
\x6f\0\x69\x73\x5f\x66\x72\x61\x67\0\x69\x73\x5f\x66\x69\x72\x73\x74\x5f\x66\
\x72\x61\x67\0\x69\x73\x5f\x65\x6e\x63\x61\x70\0\x69\x70\x5f\x70\x72\x6f\x74\
\x6f\0\x6e\x5f\x70\x72\x6f\x74\x6f\0\x73\x70\x6f\x72\x74\0\x64\x70\x6f\x72\x74\
\0\x66\x6c\x61\x67\x73\0\x66\x6c\x6f\x77\x5f\x6c\x61\x62\x65\x6c\0\x69\x70\x76\
\x34\x5f\x73\x72\x63\0\x69\x70\x76\x34\x5f\x64\x73\x74\0\x69\x70\x76\x36\x5f\
\x73\x72\x63\0\x69\x70\x76\x36\x5f\x64\x73\x74\0\x73\x6b\0\x62\x70\x66\x5f\x73\
\x6f\x63\x6b\0\x62\x6f\x75\x6e\x64\x5f\x64\x65\x76\x5f\x69\x66\0\x66\x61\x6d\
\x69\x6c\x79\0\x74\x79\x70\x65\0\x70\x72\x6f\x74\x6f\x63\x6f\x6c\0\x6d\x61\x72\
\x6b\0\x70\x72\x69\x6f\x72\x69\x74\x79\0\x73\x72\x63\x5f\x69\x70\x34\0\x73\x72\
\x63\x5f\x69\x70\x36\0\x73\x72\x63\x5f\x70\x6f\x72\x74\0\x64\x73\x74\x5f\x70\
\x6f\x72\x74\0\x64\x73\x74\x5f\x69\x70\x34\0\x64\x73\x74\x5f\x69\x70\x36\0\x73\
\x74\x61\x74\x65\0\x72\x78\x5f\x71\x75\x65\x75\x65\x5f\x6d\x61\x70\x70\x69\x6e\
\x67\0\x5f\x5f\x73\x6b\x5f\x62\x75\x66\x66\0\x6c\x65\x6e\0\x70\x6b\x74\x5f\x74\
\x79\x70\x65\0\x71\x75\x65\x75\x65\x5f\x6d\x61\x70\x70\x69\x6e\x67\0\x76\x6c\
\x61\x6e\x5f\x70\x72\x65\x73\x65\x6e\x74\0\x76\x6c\x61\x6e\x5f\x74\x63\x69\0\
\x76\x6c\x61\x6e\x5f\x70\x72\x6f\x74\x6f\0\x69\x6e\x67\x72\x65\x73\x73\x5f\x69\
\x66\x69\x6e\x64\x65\x78\0\x69\x66\x69\x6e\x64\x65\x78\0\x74\x63\x5f\x69\x6e\
\x64\x65\x78\0\x63\x62\0\x68\x61\x73\x68\0\x74\x63\x5f\x63\x6c\x61\x73\x73\x69\
\x64\0\x64\x61\x74\x61\0\x64\x61\x74\x61\x5f\x65\x6e\x64\0\x6e\x61\x70\x69\x5f\
\x69\x64\0\x72\x65\x6d\x6f\x74\x65\x5f\x69\x70\x34\0\x6c\x6f\x63\x61\x6c\x5f\
\x69\x70\x34\0\x72\x65\x6d\x6f\x74\x65\x5f\x69\x70\x36\0\x6c\x6f\x63\x61\x6c\
\x5f\x69\x70\x36\0\x72\x65\x6d\x6f\x74\x65\x5f\x70\x6f\x72\x74\0\x6c\x6f\x63\
\x61\x6c\x5f\x70\x6f\x72\x74\0\x64\x61\x74\x61\x5f\x6d\x65\x74\x61\0\x74\x73\
\x74\x61\x6d\x70\0\x77\x69\x72\x65\x5f\x6c\x65\x6e\0\x67\x73\x6f\x5f\x73\x65\
\x67\x73\0\x67\x73\x6f\x5f\x73\x69\x7a\x65\0\x68\x77\x74\x73\x74\x61\x6d\x70\0\
\x6b\x65\x79\0\x76\x61\x6c\x75\x65\0\x5f\x6c\x69\x63\x65\x6e\x73\x65\0\x69\x73\
\x5f\x61\x6c\x6c\x6f\x77\x5f\x6c\x69\x73\x74\0\x73\x64\x5f\x72\x65\x73\x74\x72\
\x69\x63\x74\x69\x66\0\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\x5f\
\x69\0\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\x5f\x65\0\x72\x65\
\x73\x74\x72\x69\x63\x74\x5f\x6e\x65\x74\x77\x6f\x72\x6b\x5f\x69\x6e\x74\x65\
\x72\x66\x61\x63\x65\x73\x5f\x69\x6d\x70\x6c\0\x2e\x64\x61\x74\x61\0\x6c\x69\
\x63\x65\x6e\x73\x65\0\x2e\x6d\x61\x70\x73\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\x03\0\0\0\x20\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x40\
\0\0\0\0\0\0\0\xe5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\
\0\0\x09\0\0\0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x28\x01\0\0\0\0\0\0\
\x50\x01\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\x18\0\0\0\0\0\0\0\x11\
\0\0\0\x01\0\0\0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x78\x02\0\0\0\0\0\0\x01\0\0\
\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x17\0\0\0\x08\0\0\
\0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x79\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x1c\0\0\0\x01\0\0\0\x06\0\0\0\0\0\
\0\0\0\0\0\0\0\0\0\0\x80\x02\0\0\0\0\0\0\xb8\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x2e\0\0\0\x01\0\0\0\x06\0\0\0\0\0\0\0\0\0\0\0\0\
\0\0\0\x38\x03\0\0\0\0\0\0\xb8\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\
\0\0\0\0\0\0\0\0\x41\0\0\0\x01\0\0\0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xf0\x03\
\0\0\0\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
\0\x49\0\0\0\x01\0\0\0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\x04\0\0\0\0\0\0\
\x18\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x4f\0\0\0\
\x01\0\0\0\x30\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x20\x04\0\0\0\0\0\0\x31\0\0\0\0\0\
\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\xb3\0\0\0\x09\0\0\0\
\x40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x58\x04\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\x02\0\
\0\0\x05\0\0\0\x08\0\0\0\0\0\0\0\x10\0\0\0\0\0\0\0\xc9\0\0\0\x09\0\0\0\x40\0\0\
\0\0\0\0\0\0\0\0\0\0\0\0\0\x78\x04\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\x02\0\0\0\x06\
\0\0\0\x08\0\0\0\0\0\0\0\x10\0\0\0\0\0\0\0\xe0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\
\0\0\0\0\0\0\0\0\x98\x04\0\0\0\0\0\0\x16\x0e\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\
\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
}

#ifdef __cplusplus
struct restrict_ifaces_bpf *restrict_ifaces_bpf::open(const struct
bpf_object_open_opts *opts) { return
restrict_ifaces_bpf__open_opts(opts); }
struct restrict_ifaces_bpf *restrict_ifaces_bpf::open_and_load() {
return restrict_ifaces_bpf__open_and_load(); }
int restrict_ifaces_bpf::load(struct restrict_ifaces_bpf *skel) {
return restrict_ifaces_bpf__load(skel); }
int restrict_ifaces_bpf::attach(struct restrict_ifaces_bpf *skel) {
return restrict_ifaces_bpf__attach(skel); }
void restrict_ifaces_bpf::detach(struct restrict_ifaces_bpf *skel) {
restrict_ifaces_bpf__detach(skel); }
void restrict_ifaces_bpf::destroy(struct restrict_ifaces_bpf *skel) {
restrict_ifaces_bpf__destroy(skel); }
const void *restrict_ifaces_bpf::elf_bytes(size_t *sz) { return
restrict_ifaces_bpf__elf_bytes(sz); }
#endif /* __cplusplus */

__attribute__((unused)) static void
restrict_ifaces_bpf__assert(struct restrict_ifaces_bpf *s
__attribute__((unused)))
{
#ifdef __cplusplus
#define _Static_assert static_assert
#endif
    _Static_assert(sizeof(s->data->is_allow_list) == 1, "unexpected
size of 'is_allow_list'");
#ifdef __cplusplus
#undef _Static_assert
#endif
}

#endif /* __RESTRICT_IFACES_BPF_SKEL_H__ */

Clang:
$ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
--debug gen skeleton restrict-ifaces.bpf.o
libbpf: loading object 'restrict_ifaces_bpf' from buffer
libbpf: elf: section(2) .symtab, size 384, link 1, flags 0, type=2
libbpf: elf: section(3) cgroup_skb/egress, size 152, link 0, flags 6, type=1
libbpf: sec 'cgroup_skb/egress': found program 'sd_restrictif_e' at
insn offset 0 (0 bytes), code size 19 insns (152 bytes)
libbpf: elf: section(4) cgroup_skb/ingress, size 152, link 0, flags 6, type=1
libbpf: sec 'cgroup_skb/ingress': found program 'sd_restrictif_i' at
insn offset 0 (0 bytes), code size 19 insns (152 bytes)
libbpf: elf: section(5) .rodata, size 1, link 0, flags 2, type=1
libbpf: elf: section(6) license, size 18, link 0, flags 2, type=1
libbpf: license of restrict_ifaces_bpf is LGPL-2.1-or-later
libbpf: elf: section(7) .maps, size 24, link 0, flags 3, type=1
libbpf: elf: section(8) .relcgroup_skb/egress, size 32, link 2, flags 40, type=9
libbpf: elf: section(9) .relcgroup_skb/ingress, size 32, link 2, flags
40, type=9
libbpf: elf: section(10) .BTF, size 1988, link 0, flags 0, type=1
libbpf: elf: section(11) .BTF.ext, size 376, link 0, flags 0, type=1
libbpf: looking for externs among 16 symbols...
libbpf: collected 0 externs total
libbpf: map 'sd_restrictif': at sec_idx 7, offset 0.
libbpf: map 'sd_restrictif': found type = 1.
libbpf: map 'sd_restrictif': found key [6], sz = 4.
libbpf: map 'sd_restrictif': found value [9], sz = 1.
libbpf: map 'restrict.rodata' (global data): at sec_idx 5, offset 0, flags 480.
libbpf: map 1 is "restrict.rodata"
libbpf: sec '.relcgroup_skb/egress': collecting relocation for
section(3) 'cgroup_skb/egress'
libbpf: sec '.relcgroup_skb/egress': relo #0: insn #4 against 'sd_restrictif'
libbpf: prog 'sd_restrictif_e': found map 0 (sd_restrictif, sec 7, off
0) for insn #4
libbpf: sec '.relcgroup_skb/egress': relo #1: insn #7 against 'is_allow_list'
libbpf: prog 'sd_restrictif_e': found data map 1 (restrict.rodata, sec
5, off 0) for insn 7
libbpf: sec '.relcgroup_skb/ingress': collecting relocation for
section(4) 'cgroup_skb/ingress'
libbpf: sec '.relcgroup_skb/ingress': relo #0: insn #4 against 'sd_restrictif'
libbpf: prog 'sd_restrictif_i': found map 0 (sd_restrictif, sec 7, off
0) for insn #4
libbpf: sec '.relcgroup_skb/ingress': relo #1: insn #7 against 'is_allow_list'
libbpf: prog 'sd_restrictif_i': found data map 1 (restrict.rodata, sec
5, off 0) for insn 7
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */

/* THIS FILE IS AUTOGENERATED BY BPFTOOL! */
#ifndef __RESTRICT_IFACES_BPF_SKEL_H__
#define __RESTRICT_IFACES_BPF_SKEL_H__

#include <errno.h>
#include <stdlib.h>
#include <bpf/libbpf.h>

struct restrict_ifaces_bpf {
    struct bpf_object_skeleton *skeleton;
    struct bpf_object *obj;
    struct {
        struct bpf_map *sd_restrictif;
        struct bpf_map *rodata;
    } maps;
    struct {
        struct bpf_program *sd_restrictif_e;
        struct bpf_program *sd_restrictif_i;
    } progs;
    struct {
        struct bpf_link *sd_restrictif_e;
        struct bpf_link *sd_restrictif_i;
    } links;
    struct restrict_ifaces_bpf__rodata {
        __u8 is_allow_list;
    } *rodata;

#ifdef __cplusplus
    static inline struct restrict_ifaces_bpf *open(const struct
bpf_object_open_opts *opts = nullptr);
    static inline struct restrict_ifaces_bpf *open_and_load();
    static inline int load(struct restrict_ifaces_bpf *skel);
    static inline int attach(struct restrict_ifaces_bpf *skel);
    static inline void detach(struct restrict_ifaces_bpf *skel);
    static inline void destroy(struct restrict_ifaces_bpf *skel);
    static inline const void *elf_bytes(size_t *sz);
#endif /* __cplusplus */
};

static void
restrict_ifaces_bpf__destroy(struct restrict_ifaces_bpf *obj)
{
    if (!obj)
        return;
    if (obj->skeleton)
        bpf_object__destroy_skeleton(obj->skeleton);
    free(obj);
}

static inline int
restrict_ifaces_bpf__create_skeleton(struct restrict_ifaces_bpf *obj);

static inline struct restrict_ifaces_bpf *
restrict_ifaces_bpf__open_opts(const struct bpf_object_open_opts *opts)
{
    struct restrict_ifaces_bpf *obj;
    int err;

    obj = (struct restrict_ifaces_bpf *)calloc(1, sizeof(*obj));
    if (!obj) {
        errno = ENOMEM;
        return NULL;
    }

    err = restrict_ifaces_bpf__create_skeleton(obj);
    if (err)
        goto err_out;

    err = bpf_object__open_skeleton(obj->skeleton, opts);
    if (err)
        goto err_out;

    return obj;
err_out:
    restrict_ifaces_bpf__destroy(obj);
    errno = -err;
    return NULL;
}

static inline struct restrict_ifaces_bpf *
restrict_ifaces_bpf__open(void)
{
    return restrict_ifaces_bpf__open_opts(NULL);
}

static inline int
restrict_ifaces_bpf__load(struct restrict_ifaces_bpf *obj)
{
    return bpf_object__load_skeleton(obj->skeleton);
}

static inline struct restrict_ifaces_bpf *
restrict_ifaces_bpf__open_and_load(void)
{
    struct restrict_ifaces_bpf *obj;
    int err;

    obj = restrict_ifaces_bpf__open();
    if (!obj)
        return NULL;
    err = restrict_ifaces_bpf__load(obj);
    if (err) {
        restrict_ifaces_bpf__destroy(obj);
        errno = -err;
        return NULL;
    }
    return obj;
}

static inline int
restrict_ifaces_bpf__attach(struct restrict_ifaces_bpf *obj)
{
    return bpf_object__attach_skeleton(obj->skeleton);
}

static inline void
restrict_ifaces_bpf__detach(struct restrict_ifaces_bpf *obj)
{
    return bpf_object__detach_skeleton(obj->skeleton);
}

static inline const void *restrict_ifaces_bpf__elf_bytes(size_t *sz);

static inline int
restrict_ifaces_bpf__create_skeleton(struct restrict_ifaces_bpf *obj)
{
    struct bpf_object_skeleton *s;
    int err;

    s = (struct bpf_object_skeleton *)calloc(1, sizeof(*s));
    if (!s)    {
        err = -ENOMEM;
        goto err;
    }

    s->sz = sizeof(*s);
    s->name = "restrict_ifaces_bpf";
    s->obj = &obj->obj;

    /* maps */
    s->map_cnt = 2;
    s->map_skel_sz = sizeof(*s->maps);
    s->maps = (struct bpf_map_skeleton *)calloc(s->map_cnt, s->map_skel_sz);
    if (!s->maps) {
        err = -ENOMEM;
        goto err;
    }

    s->maps[0].name = "sd_restrictif";
    s->maps[0].map = &obj->maps.sd_restrictif;

    s->maps[1].name = "restrict.rodata";
    s->maps[1].map = &obj->maps.rodata;
    s->maps[1].mmaped = (void **)&obj->rodata;

    /* programs */
    s->prog_cnt = 2;
    s->prog_skel_sz = sizeof(*s->progs);
    s->progs = (struct bpf_prog_skeleton *)calloc(s->prog_cnt, s->prog_skel_sz);
    if (!s->progs) {
        err = -ENOMEM;
        goto err;
    }

    s->progs[0].name = "sd_restrictif_e";
    s->progs[0].prog = &obj->progs.sd_restrictif_e;
    s->progs[0].link = &obj->links.sd_restrictif_e;

    s->progs[1].name = "sd_restrictif_i";
    s->progs[1].prog = &obj->progs.sd_restrictif_i;
    s->progs[1].link = &obj->links.sd_restrictif_i;

    s->data = (void *)restrict_ifaces_bpf__elf_bytes(&s->data_sz);

    obj->skeleton = s;
    return 0;
err:
    bpf_object__destroy_skeleton(s);
    return err;
}

static inline const void *restrict_ifaces_bpf__elf_bytes(size_t *sz)
{
    *sz = 4272;
    return (const void *)"\
\x7f\x45\x4c\x46\x02\x01\x01\0\0\0\0\0\0\0\0\0\x01\0\xf7\0\x01\0\0\0\0\0\0\0\0\
\0\0\0\0\0\0\0\0\0\0\0\xb0\x0d\0\0\0\0\0\0\0\0\0\0\x40\0\0\0\0\0\x40\0\x0c\0\
\x01\0\0\x2e\x73\x74\x72\x74\x61\x62\0\x2e\x73\x79\x6d\x74\x61\x62\0\x63\x67\
\x72\x6f\x75\x70\x5f\x73\x6b\x62\x2f\x65\x67\x72\x65\x73\x73\0\x63\x67\x72\x6f\
\x75\x70\x5f\x73\x6b\x62\x2f\x69\x6e\x67\x72\x65\x73\x73\0\x2e\x72\x6f\x64\x61\
\x74\x61\0\x6c\x69\x63\x65\x6e\x73\x65\0\x2e\x6d\x61\x70\x73\0\x72\x65\x73\x74\
\x72\x69\x63\x74\x2d\x69\x66\x61\x63\x65\x73\x2e\x62\x70\x66\x2e\x63\0\x4c\x42\
\x42\x30\x5f\x32\0\x4c\x42\x42\x30\x5f\x33\0\x4c\x42\x42\x30\x5f\x34\0\x4c\x42\
\x42\x31\x5f\x32\0\x4c\x42\x42\x31\x5f\x33\0\x4c\x42\x42\x31\x5f\x34\0\x5f\x6c\
\x69\x63\x65\x6e\x73\x65\0\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\
\x5f\x65\0\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\0\x69\x73\x5f\
\x61\x6c\x6c\x6f\x77\x5f\x6c\x69\x73\x74\0\x73\x64\x5f\x72\x65\x73\x74\x72\x69\
\x63\x74\x69\x66\x5f\x69\0\x2e\x72\x65\x6c\x63\x67\x72\x6f\x75\x70\x5f\x73\x6b\
\x62\x2f\x65\x67\x72\x65\x73\x73\0\x2e\x72\x65\x6c\x63\x67\x72\x6f\x75\x70\x5f\
\x73\x6b\x62\x2f\x69\x6e\x67\x72\x65\x73\x73\0\x2e\x42\x54\x46\0\x2e\x42\x54\
\x46\x2e\x65\x78\x74\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
\x4c\0\0\0\x04\0\xf1\xff\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x03\0\x03\0\0\
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x62\0\0\0\0\0\x03\0\x70\0\0\0\0\0\0\0\0\0\0\0\0\
\0\0\0\x69\0\0\0\0\0\x03\0\x80\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x70\0\0\0\0\0\x03\
\0\x88\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x03\0\x04\0\0\0\0\0\0\0\0\0\0\0\0\
\0\0\0\0\0\x77\0\0\0\0\0\x04\0\x70\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x7e\0\0\0\0\0\
\x04\0\x80\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x85\0\0\0\0\0\x04\0\x88\0\0\0\0\0\0\0\
\0\0\0\0\0\0\0\0\x8c\0\0\0\x01\0\x06\0\0\0\0\0\0\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\
\0\x03\0\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x95\0\0\0\x12\0\x03\0\0\0\0\0\0\
\0\0\0\x98\0\0\0\0\0\0\0\xa5\0\0\0\x11\0\x07\0\0\0\0\0\0\0\0\0\x18\0\0\0\0\0\0\
\0\xb3\0\0\0\x11\0\x05\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\xc1\0\0\0\x12\0\x04\
\0\0\0\0\0\0\0\0\0\x98\0\0\0\0\0\0\0\x61\x11\x28\0\0\0\0\0\x63\x1a\xfc\xff\0\0\
\0\0\xbf\xa2\0\0\0\0\0\0\x07\x02\0\0\xfc\xff\xff\xff\x18\x01\0\0\0\0\0\0\0\0\0\
\0\0\0\0\0\x85\0\0\0\x01\0\0\0\x18\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x71\x11\0\0\
\0\0\0\0\x15\x01\x03\0\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x15\0\x03\0\0\0\0\0\x05\0\
\x03\0\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x15\0\x01\0\0\0\0\0\xb7\x01\0\0\0\0\0\0\
\xbf\x10\0\0\0\0\0\0\x95\0\0\0\0\0\0\0\x61\x11\x28\0\0\0\0\0\x63\x1a\xfc\xff\0\
\0\0\0\xbf\xa2\0\0\0\0\0\0\x07\x02\0\0\xfc\xff\xff\xff\x18\x01\0\0\0\0\0\0\0\0\
\0\0\0\0\0\0\x85\0\0\0\x01\0\0\0\x18\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x71\x11\0\
\0\0\0\0\0\x15\x01\x03\0\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x15\0\x03\0\0\0\0\0\x05\
\0\x03\0\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x15\0\x01\0\0\0\0\0\xb7\x01\0\0\0\0\0\0\
\xbf\x10\0\0\0\0\0\0\x95\0\0\0\0\0\0\0\0\x4c\x47\x50\x4c\x2d\x32\x2e\x31\x2d\
\x6f\x72\x2d\x6c\x61\x74\x65\x72\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
\0\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\x01\0\0\0\x0d\0\0\0\x38\0\0\0\0\0\0\0\x01\0\0\
\0\x0e\0\0\0\x20\0\0\0\0\0\0\0\x01\0\0\0\x0d\0\0\0\x38\0\0\0\0\0\0\0\x01\0\0\0\
\x0e\0\0\0\x9f\xeb\x01\0\x18\0\0\0\0\0\0\0\x10\x04\0\0\x10\x04\0\0\x9c\x03\0\0\
\0\0\0\0\0\0\0\x02\x03\0\0\0\x01\0\0\0\0\0\0\x01\x04\0\0\0\x20\0\0\x01\0\0\0\0\
\0\0\0\x03\0\0\0\0\x02\0\0\0\x04\0\0\0\x01\0\0\0\x05\0\0\0\0\0\0\x01\x04\0\0\0\
\x20\0\0\0\0\0\0\0\0\0\0\x02\x06\0\0\0\x19\0\0\0\0\0\0\x08\x07\0\0\0\x1f\0\0\0\
\0\0\0\x01\x04\0\0\0\x20\0\0\0\0\0\0\0\0\0\0\x02\x09\0\0\0\x2c\0\0\0\0\0\0\x08\
\x0a\0\0\0\x31\0\0\0\0\0\0\x01\x01\0\0\0\x08\0\0\0\0\0\0\0\x03\0\0\x04\x18\0\0\
\0\x3f\0\0\0\x01\0\0\0\0\0\0\0\x44\0\0\0\x05\0\0\0\x40\0\0\0\x48\0\0\0\x08\0\0\
\0\x80\0\0\0\x4e\0\0\0\0\0\0\x0e\x0b\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\x02\x0e\0\0\
\0\0\0\0\0\0\0\0\x0a\x0f\0\0\0\x5c\0\0\0\x21\0\0\x04\xc0\0\0\0\x66\0\0\0\x06\0\
\0\0\0\0\0\0\x6a\0\0\0\x06\0\0\0\x20\0\0\0\x73\0\0\0\x06\0\0\0\x40\0\0\0\x78\0\
\0\0\x06\0\0\0\x60\0\0\0\x86\0\0\0\x06\0\0\0\x80\0\0\0\x8f\0\0\0\x06\0\0\0\xa0\
\0\0\0\x9c\0\0\0\x06\0\0\0\xc0\0\0\0\xa5\0\0\0\x06\0\0\0\xe0\0\0\0\xb0\0\0\0\
\x06\0\0\0\0\x01\0\0\xb9\0\0\0\x06\0\0\0\x20\x01\0\0\xc9\0\0\0\x06\0\0\0\x40\
\x01\0\0\xd1\0\0\0\x06\0\0\0\x60\x01\0\0\xda\0\0\0\x10\0\0\0\x80\x01\0\0\xdd\0\
\0\0\x06\0\0\0\x20\x02\0\0\xe2\0\0\0\x06\0\0\0\x40\x02\0\0\xed\0\0\0\x06\0\0\0\
\x60\x02\0\0\xf2\0\0\0\x06\0\0\0\x80\x02\0\0\xfb\0\0\0\x06\0\0\0\xa0\x02\0\0\
\x03\x01\0\0\x06\0\0\0\xc0\x02\0\0\x0a\x01\0\0\x06\0\0\0\xe0\x02\0\0\x15\x01\0\
\0\x06\0\0\0\0\x03\0\0\x1f\x01\0\0\x11\0\0\0\x20\x03\0\0\x2a\x01\0\0\x11\0\0\0\
\xa0\x03\0\0\x34\x01\0\0\x06\0\0\0\x20\x04\0\0\x40\x01\0\0\x06\0\0\0\x40\x04\0\
\0\x4b\x01\0\0\x06\0\0\0\x60\x04\0\0\0\0\0\0\x12\0\0\0\x80\x04\0\0\x55\x01\0\0\
\x14\0\0\0\xc0\x04\0\0\x5c\x01\0\0\x06\0\0\0\0\x05\0\0\x65\x01\0\0\x06\0\0\0\
\x20\x05\0\0\0\0\0\0\x16\0\0\0\x40\x05\0\0\x6e\x01\0\0\x06\0\0\0\x80\x05\0\0\
\x77\x01\0\0\x14\0\0\0\xc0\x05\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x06\0\0\0\x04\0\0\
\0\x05\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x06\0\0\0\x04\0\0\0\x04\0\0\0\0\0\0\0\
\x01\0\0\x05\x08\0\0\0\x80\x01\0\0\x13\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x02\x22\0\0\
\0\x8a\x01\0\0\0\0\0\x08\x15\0\0\0\x90\x01\0\0\0\0\0\x01\x08\0\0\0\x40\0\0\0\0\
\0\0\0\x01\0\0\x05\x08\0\0\0\xa3\x01\0\0\x17\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x02\
\x23\0\0\0\0\0\0\0\x01\0\0\x0d\x02\0\0\0\xa3\x01\0\0\x0d\0\0\0\xa6\x01\0\0\x01\
\0\0\x0c\x18\0\0\0\xb6\x01\0\0\x01\0\0\x0c\x18\0\0\0\0\0\0\0\0\0\0\x0a\x1c\0\0\
\0\0\0\0\0\0\0\0\x09\x09\0\0\0\xc6\x01\0\0\0\0\0\x0e\x1b\0\0\0\x01\0\0\0\0\0\0\
\0\0\0\0\x0a\x1f\0\0\0\xd4\x01\0\0\0\0\0\x01\x01\0\0\0\x08\0\0\x01\0\0\0\0\0\0\
\0\x03\0\0\0\0\x1e\0\0\0\x04\0\0\0\x12\0\0\0\xd9\x01\0\0\0\0\0\x0e\x20\0\0\0\0\
\0\0\0\xe2\x01\0\0\0\0\0\x07\0\0\0\0\xf0\x01\0\0\0\0\0\x07\0\0\0\0\x61\x03\0\0\
\x01\0\0\x0f\x01\0\0\0\x1d\0\0\0\0\0\0\0\x01\0\0\0\x69\x03\0\0\x01\0\0\x0f\x12\
\0\0\0\x21\0\0\0\0\0\0\0\x12\0\0\0\x71\x03\0\0\x01\0\0\x0f\x18\0\0\0\x0c\0\0\0\
\0\0\0\0\x18\0\0\0\0\x69\x6e\x74\0\x5f\x5f\x41\x52\x52\x41\x59\x5f\x53\x49\x5a\
\x45\x5f\x54\x59\x50\x45\x5f\x5f\0\x5f\x5f\x75\x33\x32\0\x75\x6e\x73\x69\x67\
\x6e\x65\x64\x20\x69\x6e\x74\0\x5f\x5f\x75\x38\0\x75\x6e\x73\x69\x67\x6e\x65\
\x64\x20\x63\x68\x61\x72\0\x74\x79\x70\x65\0\x6b\x65\x79\0\x76\x61\x6c\x75\x65\
\0\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\0\x5f\x5f\x73\x6b\x5f\
\x62\x75\x66\x66\0\x6c\x65\x6e\0\x70\x6b\x74\x5f\x74\x79\x70\x65\0\x6d\x61\x72\
\x6b\0\x71\x75\x65\x75\x65\x5f\x6d\x61\x70\x70\x69\x6e\x67\0\x70\x72\x6f\x74\
\x6f\x63\x6f\x6c\0\x76\x6c\x61\x6e\x5f\x70\x72\x65\x73\x65\x6e\x74\0\x76\x6c\
\x61\x6e\x5f\x74\x63\x69\0\x76\x6c\x61\x6e\x5f\x70\x72\x6f\x74\x6f\0\x70\x72\
\x69\x6f\x72\x69\x74\x79\0\x69\x6e\x67\x72\x65\x73\x73\x5f\x69\x66\x69\x6e\x64\
\x65\x78\0\x69\x66\x69\x6e\x64\x65\x78\0\x74\x63\x5f\x69\x6e\x64\x65\x78\0\x63\
\x62\0\x68\x61\x73\x68\0\x74\x63\x5f\x63\x6c\x61\x73\x73\x69\x64\0\x64\x61\x74\
\x61\0\x64\x61\x74\x61\x5f\x65\x6e\x64\0\x6e\x61\x70\x69\x5f\x69\x64\0\x66\x61\
\x6d\x69\x6c\x79\0\x72\x65\x6d\x6f\x74\x65\x5f\x69\x70\x34\0\x6c\x6f\x63\x61\
\x6c\x5f\x69\x70\x34\0\x72\x65\x6d\x6f\x74\x65\x5f\x69\x70\x36\0\x6c\x6f\x63\
\x61\x6c\x5f\x69\x70\x36\0\x72\x65\x6d\x6f\x74\x65\x5f\x70\x6f\x72\x74\0\x6c\
\x6f\x63\x61\x6c\x5f\x70\x6f\x72\x74\0\x64\x61\x74\x61\x5f\x6d\x65\x74\x61\0\
\x74\x73\x74\x61\x6d\x70\0\x77\x69\x72\x65\x5f\x6c\x65\x6e\0\x67\x73\x6f\x5f\
\x73\x65\x67\x73\0\x67\x73\x6f\x5f\x73\x69\x7a\x65\0\x68\x77\x74\x73\x74\x61\
\x6d\x70\0\x66\x6c\x6f\x77\x5f\x6b\x65\x79\x73\0\x5f\x5f\x75\x36\x34\0\x75\x6e\
\x73\x69\x67\x6e\x65\x64\x20\x6c\x6f\x6e\x67\x20\x6c\x6f\x6e\x67\0\x73\x6b\0\
\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\x5f\x65\0\x73\x64\x5f\x72\
\x65\x73\x74\x72\x69\x63\x74\x69\x66\x5f\x69\0\x69\x73\x5f\x61\x6c\x6c\x6f\x77\
\x5f\x6c\x69\x73\x74\0\x63\x68\x61\x72\0\x5f\x6c\x69\x63\x65\x6e\x73\x65\0\x62\
\x70\x66\x5f\x66\x6c\x6f\x77\x5f\x6b\x65\x79\x73\0\x62\x70\x66\x5f\x73\x6f\x63\
\x6b\0\x2f\x68\x6f\x6d\x65\x2f\x62\x75\x69\x6c\x64\x72\x6f\x6f\x74\x2f\x62\x75\
\x69\x6c\x64\x72\x6f\x6f\x74\x2f\x6f\x75\x74\x70\x75\x74\x2f\x62\x75\x69\x6c\
\x64\x2f\x73\x79\x73\x74\x65\x6d\x64\x2d\x63\x75\x73\x74\x6f\x6d\x2f\x73\x72\
\x63\x2f\x63\x6f\x72\x65\x2f\x62\x70\x66\x2f\x72\x65\x73\x74\x72\x69\x63\x74\
\x5f\x69\x66\x61\x63\x65\x73\x2f\x72\x65\x73\x74\x72\x69\x63\x74\x2d\x69\x66\
\x61\x63\x65\x73\x2e\x62\x70\x66\x2e\x63\0\x20\x20\x20\x20\x20\x20\x20\x20\x69\
\x66\x69\x6e\x64\x65\x78\x20\x3d\x20\x73\x6b\x2d\x3e\x69\x66\x69\x6e\x64\x65\
\x78\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x6c\x6f\x6f\x6b\x75\x70\x5f\x72\x65\
\x73\x75\x6c\x74\x20\x3d\x20\x62\x70\x66\x5f\x6d\x61\x70\x5f\x6c\x6f\x6f\x6b\
\x75\x70\x5f\x65\x6c\x65\x6d\x28\x26\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\
\x74\x69\x66\x2c\x20\x26\x69\x66\x69\x6e\x64\x65\x78\x29\x3b\0\x20\x20\x20\x20\
\x20\x20\x20\x20\x69\x66\x20\x28\x69\x73\x5f\x61\x6c\x6c\x6f\x77\x5f\x6c\x69\
\x73\x74\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
\x20\x20\x69\x66\x20\x28\x6c\x6f\x6f\x6b\x75\x70\x5f\x72\x65\x73\x75\x6c\x74\
\x29\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\
\x20\x28\x21\x6c\x6f\x6f\x6b\x75\x70\x5f\x72\x65\x73\x75\x6c\x74\x29\0\x20\x20\
\x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x72\x65\x73\x74\x72\x69\
\x63\x74\x5f\x6e\x65\x74\x77\x6f\x72\x6b\x5f\x69\x6e\x74\x65\x72\x66\x61\x63\
\x65\x73\x5f\x69\x6d\x70\x6c\x28\x73\x6b\x29\x3b\0\x2e\x72\x6f\x64\x61\x74\x61\
\0\x6c\x69\x63\x65\x6e\x73\x65\0\x2e\x6d\x61\x70\x73\0\x63\x67\x72\x6f\x75\x70\
\x5f\x73\x6b\x62\x2f\x65\x67\x72\x65\x73\x73\0\x63\x67\x72\x6f\x75\x70\x5f\x73\
\x6b\x62\x2f\x69\x6e\x67\x72\x65\x73\x73\0\0\0\0\0\x9f\xeb\x01\0\x20\0\0\0\0\0\
\0\0\x24\0\0\0\x24\0\0\0\x34\x01\0\0\x58\x01\0\0\0\0\0\0\x08\0\0\0\x77\x03\0\0\
\x01\0\0\0\0\0\0\0\x19\0\0\0\x89\x03\0\0\x01\0\0\0\0\0\0\0\x1a\0\0\0\x10\0\0\0\
\x77\x03\0\0\x09\0\0\0\0\0\0\0\xf9\x01\0\0\x62\x02\0\0\x17\x6c\0\0\x08\0\0\0\
\xf9\x01\0\0\x62\x02\0\0\x11\x6c\0\0\x18\0\0\0\xf9\x01\0\0\0\0\0\0\0\0\0\0\x20\
\0\0\0\xf9\x01\0\0\x81\x02\0\0\x19\x70\0\0\x38\0\0\0\xf9\x01\0\0\xc8\x02\0\0\
\x0d\x74\0\0\x50\0\0\0\xf9\x01\0\0\xc8\x02\0\0\x0d\x74\0\0\x60\0\0\0\xf9\x01\0\
\0\xe5\x02\0\0\x15\x7c\0\0\x78\0\0\0\xf9\x01\0\0\x08\x03\0\0\x15\x8c\0\0\x88\0\
\0\0\xf9\x01\0\0\x2c\x03\0\0\x09\xb0\0\0\x89\x03\0\0\x09\0\0\0\0\0\0\0\xf9\x01\
\0\0\x62\x02\0\0\x17\x6c\0\0\x08\0\0\0\xf9\x01\0\0\x62\x02\0\0\x11\x6c\0\0\x18\
\0\0\0\xf9\x01\0\0\0\0\0\0\0\0\0\0\x20\0\0\0\xf9\x01\0\0\x81\x02\0\0\x19\x70\0\
\0\x38\0\0\0\xf9\x01\0\0\xc8\x02\0\0\x0d\x74\0\0\x50\0\0\0\xf9\x01\0\0\xc8\x02\
\0\0\x0d\x74\0\0\x60\0\0\0\xf9\x01\0\0\xe5\x02\0\0\x15\x7c\0\0\x78\0\0\0\xf9\
\x01\0\0\x08\x03\0\0\x15\x8c\0\0\x88\0\0\0\xf9\x01\0\0\x2c\x03\0\0\x09\xc4\0\0\
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\x03\0\0\0\x20\0\0\
\0\0\0\0\0\0\0\0\0\0\0\0\0\x40\0\0\0\0\0\0\0\x0c\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\
\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x09\0\0\0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
\0\0\0\0\0\x50\x01\0\0\0\0\0\0\x80\x01\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\x08\0\0\0\
\0\0\0\0\x18\0\0\0\0\0\0\0\x11\0\0\0\x01\0\0\0\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
\0\xd0\x02\0\0\0\0\0\0\x98\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0\0\
\0\0\0\0\0\0\x23\0\0\0\x01\0\0\0\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x68\x03\0\0\
\0\0\0\0\x98\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
\x36\0\0\0\x01\0\0\0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\x01\0\
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x3e\0\0\0\x01\0\
\0\0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x04\0\0\0\0\0\0\x12\0\0\0\0\0\0\0\0\
\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x46\0\0\0\x01\0\0\0\x03\0\0\0\
\0\0\0\0\0\0\0\0\0\0\0\0\x18\x04\0\0\0\0\0\0\x18\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xd1\0\0\0\x09\0\0\0\x40\0\0\0\0\0\0\0\0\0\0\
\0\0\0\0\0\x30\x04\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\x02\0\0\0\x03\0\0\0\x08\0\0\0\
\0\0\0\0\x10\0\0\0\0\0\0\0\xe7\0\0\0\x09\0\0\0\x40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
\0\x50\x04\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\x02\0\0\0\x04\0\0\0\x08\0\0\0\0\0\0\0\
\x10\0\0\0\0\0\0\0\xfe\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x70\x04\
\0\0\0\0\0\0\xc4\x07\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\
\0\0\x03\x01\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x38\x0c\0\0\0\0\0\0\
\x78\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
}

#ifdef __cplusplus
struct restrict_ifaces_bpf *restrict_ifaces_bpf::open(const struct
bpf_object_open_opts *opts) { return
restrict_ifaces_bpf__open_opts(opts); }
struct restrict_ifaces_bpf *restrict_ifaces_bpf::open_and_load() {
return restrict_ifaces_bpf__open_and_load(); }
int restrict_ifaces_bpf::load(struct restrict_ifaces_bpf *skel) {
return restrict_ifaces_bpf__load(skel); }
int restrict_ifaces_bpf::attach(struct restrict_ifaces_bpf *skel) {
return restrict_ifaces_bpf__attach(skel); }
void restrict_ifaces_bpf::detach(struct restrict_ifaces_bpf *skel) {
restrict_ifaces_bpf__detach(skel); }
void restrict_ifaces_bpf::destroy(struct restrict_ifaces_bpf *skel) {
restrict_ifaces_bpf__destroy(skel); }
const void *restrict_ifaces_bpf::elf_bytes(size_t *sz) { return
restrict_ifaces_bpf__elf_bytes(sz); }
#endif /* __cplusplus */

__attribute__((unused)) static void
restrict_ifaces_bpf__assert(struct restrict_ifaces_bpf *s
__attribute__((unused)))
{
#ifdef __cplusplus
#define _Static_assert static_assert
#endif
    _Static_assert(sizeof(s->rodata->is_allow_list) == 1, "unexpected
size of 'is_allow_list'");
#ifdef __cplusplus
#undef _Static_assert
#endif
}

#endif /* __RESTRICT_IFACES_BPF_SKEL_H__ */

>
>
> > Starting program:
> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> > --debug gen skeleton
> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> > [Thread debugging using libthread_db enabled]
> > Using host libthread_db library "/usr/lib/libthread_db.so.1".
> > libbpf: loading object 'restrict_ifaces_bpf' from buffer
> > libbpf: elf: section(2) .symtab, size 336, link 1, flags 0, type=2
> > libbpf: elf: section(3) .data, size 1, link 0, flags 3, type=1
> > libbpf: elf: section(4) .bss, size 0, link 0, flags 3, type=8
> > libbpf: elf: section(5) cgroup_skb/egress, size 184, link 0, flags 6, type=1
> > libbpf: sec 'cgroup_skb/egress': found program 'sd_restrictif_e' at
> > insn offset 0 (0 bytes), code size 23 insns (184 bytes)
> > libbpf: elf: section(6) cgroup_skb/ingress, size 184, link 0, flags 6, type=1
> > libbpf: sec 'cgroup_skb/ingress': found program 'sd_restrictif_i' at
> > insn offset 0 (0 bytes), code size 23 insns (184 bytes)
> > libbpf: elf: section(7) license, size 18, link 0, flags 2, type=1
> > libbpf: license of restrict_ifaces_bpf is LGPL-2.1-or-later
> > libbpf: elf: section(8) .maps, size 24, link 0, flags 3, type=1
> > libbpf: elf: section(9) .comment, size 49, link 0, flags 30, type=1
> > libbpf: elf: skipping unrecognized data section(9) .comment
> > libbpf: elf: section(10) .relcgroup_skb/egress, size 32, link 2, flags
> > 40, type=9
> > libbpf: elf: section(11) .relcgroup_skb/ingress, size 32, link 2,
> > flags 40, type=9
> > libbpf: elf: section(12) .BTF, size 3606, link 0, flags 0, type=1
> > libbpf: looking for externs among 14 symbols...
> > libbpf: collected 0 externs total
> > libbpf: map 'sd_restrictif': at sec_idx 8, offset 0.
> > libbpf: map 'sd_restrictif': found type = 1.
> > libbpf: map 'sd_restrictif': found key [12], sz = 4.
> > libbpf: map 'sd_restrictif': found value [3], sz = 1.
> >
> > Program received signal SIGSEGV, Segmentation fault.
> > 0x0000aaaaaab4fd2c in bpf_object.init_maps ()
> > (gdb) bt
> > #0  0x0000aaaaaab4fd2c in bpf_object.init_maps ()
> > #1  0x0000aaaaaab52178 in bpf_object_open.part ()
> > #2  0x0000aaaaaab544e8 in bpf_object.open_mem ()
> > #3  0x0000aaaaaab2a58c in do_skeleton ()
> > #4  0x0000aaaaaab1e204 in main ()
> >
> >>
> >> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> >> index e89cc9c885b3..e3a6808f0bb6 100644
> >> --- a/tools/lib/bpf/libbpf.c
> >> +++ b/tools/lib/bpf/libbpf.c
> >> @@ -1591,6 +1591,10 @@ static int bpf_object__init_global_data_maps(struct bpf_object *obj)
> >>         for (sec_idx = 1; sec_idx < obj->efile.sec_cnt; sec_idx++) {
> >>                 sec_desc = &obj->efile.secs[sec_idx];
> >>
> >> +                /* Skip empty sections.  */
> >> +                if (sec_desc->data->d_size == 0)
> >> +                  continue;
> >> +
> >>                 switch (sec_desc->sec_type) {
> >>                 case SEC_DATA:
> >>                         sec_name = elf_sec_name(obj, elf_sec_by_idx(obj, sec_idx));
> >>
> >> > GCC:
> >> > $ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> >> > --debug gen skeleton
> >> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> >> > libbpf: loading object 'restrict_ifaces_bpf' from buffer
> >> > libbpf: elf: section(2) .symtab, size 336, link 1, flags 0, type=2
> >> > libbpf: elf: section(3) .data, size 1, link 0, flags 3, type=1
> >> > libbpf: elf: section(4) .bss, size 0, link 0, flags 3, type=8
> >> > libbpf: elf: section(5) cgroup_skb/egress, size 184, link 0, flags 6, type=1
> >> > libbpf: sec 'cgroup_skb/egress': found program 'sd_restrictif_e' at
> >> > insn offset 0 (0 bytes), code size 23 insns (184 bytes)
> >> > libbpf: elf: section(6) cgroup_skb/ingress, size 184, link 0, flags 6, type=1
> >> > libbpf: sec 'cgroup_skb/ingress': found program 'sd_restrictif_i' at
> >> > insn offset 0 (0 bytes), code size 23 insns (184 bytes)
> >> > libbpf: elf: section(7) license, size 18, link 0, flags 2, type=1
> >> > libbpf: license of restrict_ifaces_bpf is LGPL-2.1-or-later
> >> > libbpf: elf: section(8) .maps, size 24, link 0, flags 3, type=1
> >> > libbpf: elf: section(9) .comment, size 49, link 0, flags 30, type=1
> >> > libbpf: elf: skipping unrecognized data section(9) .comment
> >> > libbpf: elf: section(10) .relcgroup_skb/egress, size 32, link 2, flags
> >> > 40, type=9
> >> > libbpf: elf: section(11) .relcgroup_skb/ingress, size 32, link 2,
> >> > flags 40, type=9
> >> > libbpf: elf: section(12) .BTF, size 3606, link 0, flags 0, type=1
> >> > libbpf: looking for externs among 14 symbols...
> >> > libbpf: collected 0 externs total
> >> > libbpf: map 'sd_restrictif': at sec_idx 8, offset 0.
> >> > libbpf: map 'sd_restrictif': found type = 1.
> >> > libbpf: map 'sd_restrictif': found key [12], sz = 4.
> >> > libbpf: map 'sd_restrictif': found value [3], sz = 1.
> >> > libbpf: map 'restrict.data' (global data): at sec_idx 3, offset 0, flags 400.
> >> > libbpf: map 1 is "restrict.data"
> >> > libbpf: map 'restrict.bss' (global data): at sec_idx 4, offset 0, flags 400.
> >> > libbpf: failed to alloc map 'restrict.bss' content buffer: -22
> >> > Error: failed to open BPF object file: Invalid argument
> >> >
> >> > LLVM:
> >> > $ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> >> > --debug gen skeleton restrict-ifaces.bpf.o
> >> > libbpf: loading object 'restrict_ifaces_bpf' from buffer
> >> > libbpf: elf: section(2) .symtab, size 384, link 1, flags 0, type=2
> >> > libbpf: elf: section(3) cgroup_skb/egress, size 152, link 0, flags 6, type=1
> >> > libbpf: sec 'cgroup_skb/egress': found program 'sd_restrictif_e' at
> >> > insn offset 0 (0 bytes), code size 19 insns (152 bytes)
> >> > libbpf: elf: section(4) cgroup_skb/ingress, size 152, link 0, flags 6, type=1
> >> > libbpf: sec 'cgroup_skb/ingress': found program 'sd_restrictif_i' at
> >> > insn offset 0 (0 bytes), code size 19 insns (152 bytes)
> >> > libbpf: elf: section(5) .rodata, size 1, link 0, flags 2, type=1
> >> > libbpf: elf: section(6) license, size 18, link 0, flags 2, type=1
> >> > libbpf: license of restrict_ifaces_bpf is LGPL-2.1-or-later
> >> > libbpf: elf: section(7) .maps, size 24, link 0, flags 3, type=1
> >> > libbpf: elf: section(8) .relcgroup_skb/egress, size 32, link 2, flags 40, type=9
> >> > libbpf: elf: section(9) .relcgroup_skb/ingress, size 32, link 2, flags
> >> > 40, type=9
> >> > libbpf: elf: section(10) .BTF, size 1988, link 0, flags 0, type=1
> >> > libbpf: elf: section(11) .BTF.ext, size 376, link 0, flags 0, type=1
> >> > libbpf: looking for externs among 16 symbols...
> >> > libbpf: collected 0 externs total
> >> > libbpf: map 'sd_restrictif': at sec_idx 7, offset 0.
> >> > libbpf: map 'sd_restrictif': found type = 1.
> >> > libbpf: map 'sd_restrictif': found key [6], sz = 4.
> >> > libbpf: map 'sd_restrictif': found value [9], sz = 1.
> >> > libbpf: map 'restrict.rodata' (global data): at sec_idx 5, offset 0, flags 480.
> >> > libbpf: map 1 is "restrict.rodata"
> >> > libbpf: sec '.relcgroup_skb/egress': collecting relocation for
> >> > section(3) 'cgroup_skb/egress'
> >> > libbpf: sec '.relcgroup_skb/egress': relo #0: insn #4 against 'sd_restrictif'
> >> > libbpf: prog 'sd_restrictif_e': found map 0 (sd_restrictif, sec 7, off
> >> > 0) for insn #4
> >> > libbpf: sec '.relcgroup_skb/egress': relo #1: insn #7 against 'is_allow_list'
> >> > libbpf: prog 'sd_restrictif_e': found data map 1 (restrict.rodata, sec
> >> > 5, off 0) for insn 7
> >> > libbpf: sec '.relcgroup_skb/ingress': collecting relocation for
> >> > section(4) 'cgroup_skb/ingress'
> >> > libbpf: sec '.relcgroup_skb/ingress': relo #0: insn #4 against 'sd_restrictif'
> >> > libbpf: prog 'sd_restrictif_i': found map 0 (sd_restrictif, sec 7, off
> >> > 0) for insn #4
> >> > libbpf: sec '.relcgroup_skb/ingress': relo #1: insn #7 against 'is_allow_list'
> >> > libbpf: prog 'sd_restrictif_i': found data map 1 (restrict.rodata, sec
> >> > 5, off 0) for insn 7
> >> >
> >> >> >
> >> >> > >>
> >> >> > >> Looking at libbpf.c, it seems to me that this may be due of trying to
> >> >> > >> mmap 0 bytes in `bpf_object__init_internal_map':
> >> >> > >>
> >> >> > >>         map->mmaped = mmap(NULL, bpf_map_mmap_sz(map), PROT_READ | PROT_WRITE,
> >> >> > >>                            MAP_SHARED | MAP_ANONYMOUS, -1, 0);
> >> >> > >>         if (map->mmaped == MAP_FAILED) {
> >> >> > >>                 err = -errno;
> >> >> > >>                 map->mmaped = NULL;
> >> >> > >>                 pr_warn("failed to alloc map '%s' content buffer: %d\n",
> >> >> > >>                         map->name, err);
> >> >> > >>                 zfree(&map->real_name);
> >> >> > >>                 zfree(&map->name);
> >> >> > >>                 return err;
> >> >> > >>         }
> >> >> > >>
> >> >> > >> I see no check for zero sized sections in
> >> >> > >> bpf_object__init_global_data_maps.
> >> >> > >>
> >> >> > >> Is maybe GCC failing to allocate stuff in BSS that is supposed to be
> >> >> > >> there?
> >> >> > >>
> >> >> > >> > Stripped file passed to gen skeleton:
> >> >> > >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> >> >> > >> > btf dump file
> >> >> > >> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> >> >> > >> > format raw
> >> >> > >> > [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> >> >> > >> > [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
> >> >> > >> > [3] TYPEDEF '__u8' type_id=2
> >> >> > >> > [4] CONST '(anon)' type_id=3
> >> >> > >> > [5] VOLATILE '(anon)' type_id=4
> >> >> > >> > [6] INT 'short int' size=2 bits_offset=0 nr_bits=16 encoding=SIGNED
> >> >> > >> > [7] INT 'short unsigned int' size=2 bits_offset=0 nr_bits=16 encoding=(none)
> >> >> > >> > [8] TYPEDEF '__u16' type_id=7
> >> >> > >> > [9] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
> >> >> > >> > [10] TYPEDEF '__s32' type_id=9
> >> >> > >> > [11] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
> >> >> > >> > [12] TYPEDEF '__u32' type_id=11
> >> >> > >> > [13] INT 'long long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
> >> >> > >> > [14] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64
> >> >> > >> > encoding=(none)
> >> >> > >> > [15] TYPEDEF '__u64' type_id=14
> >> >> > >> > [16] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
> >> >> > >> > [17] INT 'long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
> >> >> > >> > [18] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> >> >> > >> > [19] CONST '(anon)' type_id=18
> >> >> > >> > [20] TYPEDEF '__be16' type_id=8
> >> >> > >> > [21] TYPEDEF '__be32' type_id=12
> >> >> > >> > [22] ENUM 'bpf_map_type' encoding=UNSIGNED size=4 vlen=31
> >> >> > >> >     'BPF_MAP_TYPE_UNSPEC' val=0
> >> >> > >> >     'BPF_MAP_TYPE_HASH' val=1
> >> >> > >> >     'BPF_MAP_TYPE_ARRAY' val=2
> >> >> > >> >     'BPF_MAP_TYPE_PROG_ARRAY' val=3
> >> >> > >> >     'BPF_MAP_TYPE_PERF_EVENT_ARRAY' val=4
> >> >> > >> >     'BPF_MAP_TYPE_PERCPU_HASH' val=5
> >> >> > >> >     'BPF_MAP_TYPE_PERCPU_ARRAY' val=6
> >> >> > >> >     'BPF_MAP_TYPE_STACK_TRACE' val=7
> >> >> > >> >     'BPF_MAP_TYPE_CGROUP_ARRAY' val=8
> >> >> > >> >     'BPF_MAP_TYPE_LRU_HASH' val=9
> >> >> > >> >     'BPF_MAP_TYPE_LRU_PERCPU_HASH' val=10
> >> >> > >> >     'BPF_MAP_TYPE_LPM_TRIE' val=11
> >> >> > >> >     'BPF_MAP_TYPE_ARRAY_OF_MAPS' val=12
> >> >> > >> >     'BPF_MAP_TYPE_HASH_OF_MAPS' val=13
> >> >> > >> >     'BPF_MAP_TYPE_DEVMAP' val=14
> >> >> > >> >     'BPF_MAP_TYPE_SOCKMAP' val=15
> >> >> > >> >     'BPF_MAP_TYPE_CPUMAP' val=16
> >> >> > >> >     'BPF_MAP_TYPE_XSKMAP' val=17
> >> >> > >> >     'BPF_MAP_TYPE_SOCKHASH' val=18
> >> >> > >> >     'BPF_MAP_TYPE_CGROUP_STORAGE' val=19
> >> >> > >> >     'BPF_MAP_TYPE_REUSEPORT_SOCKARRAY' val=20
> >> >> > >> >     'BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE' val=21
> >> >> > >> >     'BPF_MAP_TYPE_QUEUE' val=22
> >> >> > >> >     'BPF_MAP_TYPE_STACK' val=23
> >> >> > >> >     'BPF_MAP_TYPE_SK_STORAGE' val=24
> >> >> > >> >     'BPF_MAP_TYPE_DEVMAP_HASH' val=25
> >> >> > >> >     'BPF_MAP_TYPE_STRUCT_OPS' val=26
> >> >> > >> >     'BPF_MAP_TYPE_RINGBUF' val=27
> >> >> > >> >     'BPF_MAP_TYPE_INODE_STORAGE' val=28
> >> >> > >> >     'BPF_MAP_TYPE_TASK_STORAGE' val=29
> >> >> > >> >     'BPF_MAP_TYPE_BLOOM_FILTER' val=30
> >> >> > >> > [23] UNION '(anon)' size=8 vlen=1
> >> >> > >> >     'flow_keys' type_id=29 bits_offset=0
> >> >> > >> > [24] STRUCT 'bpf_flow_keys' size=56 vlen=13
> >> >> > >> >     'nhoff' type_id=8 bits_offset=0
> >> >> > >> >     'thoff' type_id=8 bits_offset=16
> >> >> > >> >     'addr_proto' type_id=8 bits_offset=32
> >> >> > >> >     'is_frag' type_id=3 bits_offset=48
> >> >> > >> >     'is_first_frag' type_id=3 bits_offset=56
> >> >> > >> >     'is_encap' type_id=3 bits_offset=64
> >> >> > >> >     'ip_proto' type_id=3 bits_offset=72
> >> >> > >> >     'n_proto' type_id=20 bits_offset=80
> >> >> > >> >     'sport' type_id=20 bits_offset=96
> >> >> > >> >     'dport' type_id=20 bits_offset=112
> >> >> > >> >     '(anon)' type_id=25 bits_offset=128
> >> >> > >> >     'flags' type_id=12 bits_offset=384
> >> >> > >> >     'flow_label' type_id=21 bits_offset=416
> >> >> > >> > [25] UNION '(anon)' size=32 vlen=2
> >> >> > >> >     '(anon)' type_id=26 bits_offset=0
> >> >> > >> >     '(anon)' type_id=27 bits_offset=0
> >> >> > >> > [26] STRUCT '(anon)' size=8 vlen=2
> >> >> > >> >     'ipv4_src' type_id=21 bits_offset=0
> >> >> > >> >     'ipv4_dst' type_id=21 bits_offset=32
> >> >> > >> > [27] STRUCT '(anon)' size=32 vlen=2
> >> >> > >> >     'ipv6_src' type_id=28 bits_offset=0
> >> >> > >> >     'ipv6_dst' type_id=28 bits_offset=128
> >> >> > >> > [28] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=4
> >> >> > >> > [29] PTR '(anon)' type_id=24
> >> >> > >> > [30] UNION '(anon)' size=8 vlen=1
> >> >> > >> >     'sk' type_id=32 bits_offset=0
> >> >> > >> > [31] STRUCT 'bpf_sock' size=80 vlen=14
> >> >> > >> >     'bound_dev_if' type_id=12 bits_offset=0
> >> >> > >> >     'family' type_id=12 bits_offset=32
> >> >> > >> >     'type' type_id=12 bits_offset=64
> >> >> > >> >     'protocol' type_id=12 bits_offset=96
> >> >> > >> >     'mark' type_id=12 bits_offset=128
> >> >> > >> >     'priority' type_id=12 bits_offset=160
> >> >> > >> >     'src_ip4' type_id=12 bits_offset=192
> >> >> > >> >     'src_ip6' type_id=28 bits_offset=224
> >> >> > >> >     'src_port' type_id=12 bits_offset=352
> >> >> > >> >     'dst_port' type_id=20 bits_offset=384
> >> >> > >> >     'dst_ip4' type_id=12 bits_offset=416
> >> >> > >> >     'dst_ip6' type_id=28 bits_offset=448
> >> >> > >> >     'state' type_id=12 bits_offset=576
> >> >> > >> >     'rx_queue_mapping' type_id=10 bits_offset=608
> >> >> > >> > [32] PTR '(anon)' type_id=31
> >> >> > >> > [33] STRUCT '__sk_buff' size=192 vlen=33
> >> >> > >> >     'len' type_id=12 bits_offset=0
> >> >> > >> >     'pkt_type' type_id=12 bits_offset=32
> >> >> > >> >     'mark' type_id=12 bits_offset=64
> >> >> > >> >     'queue_mapping' type_id=12 bits_offset=96
> >> >> > >> >     'protocol' type_id=12 bits_offset=128
> >> >> > >> >     'vlan_present' type_id=12 bits_offset=160
> >> >> > >> >     'vlan_tci' type_id=12 bits_offset=192
> >> >> > >> >     'vlan_proto' type_id=12 bits_offset=224
> >> >> > >> >     'priority' type_id=12 bits_offset=256
> >> >> > >> >     'ingress_ifindex' type_id=12 bits_offset=288
> >> >> > >> >     'ifindex' type_id=12 bits_offset=320
> >> >> > >> >     'tc_index' type_id=12 bits_offset=352
> >> >> > >> >     'cb' type_id=34 bits_offset=384
> >> >> > >> >     'hash' type_id=12 bits_offset=544
> >> >> > >> >     'tc_classid' type_id=12 bits_offset=576
> >> >> > >> >     'data' type_id=12 bits_offset=608
> >> >> > >> >     'data_end' type_id=12 bits_offset=640
> >> >> > >> >     'napi_id' type_id=12 bits_offset=672
> >> >> > >> >     'family' type_id=12 bits_offset=704
> >> >> > >> >     'remote_ip4' type_id=12 bits_offset=736
> >> >> > >> >     'local_ip4' type_id=12 bits_offset=768
> >> >> > >> >     'remote_ip6' type_id=28 bits_offset=800
> >> >> > >> >     'local_ip6' type_id=28 bits_offset=928
> >> >> > >> >     'remote_port' type_id=12 bits_offset=1056
> >> >> > >> >     'local_port' type_id=12 bits_offset=1088
> >> >> > >> >     'data_meta' type_id=12 bits_offset=1120
> >> >> > >> >     '(anon)' type_id=23 bits_offset=1152
> >> >> > >> >     'tstamp' type_id=15 bits_offset=1216
> >> >> > >> >     'wire_len' type_id=12 bits_offset=1280
> >> >> > >> >     'gso_segs' type_id=12 bits_offset=1312
> >> >> > >> >     '(anon)' type_id=30 bits_offset=1344
> >> >> > >> >     'gso_size' type_id=12 bits_offset=1408
> >> >> > >> >     'hwtstamp' type_id=15 bits_offset=1472
> >> >> > >> > [34] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=5
> >> >> > >> > [35] CONST '(anon)' type_id=33
> >> >> > >> > [36] PTR '(anon)' type_id=0
> >> >> > >> > [37] STRUCT '(anon)' size=24 vlen=3
> >> >> > >> >     'type' type_id=39 bits_offset=0
> >> >> > >> >     'key' type_id=40 bits_offset=64
> >> >> > >> >     'value' type_id=41 bits_offset=128
> >> >> > >> > [38] ARRAY '(anon)' type_id=9 index_type_id=16 nr_elems=1
> >> >> > >> > [39] PTR '(anon)' type_id=38
> >> >> > >> > [40] PTR '(anon)' type_id=12
> >> >> > >> > [41] PTR '(anon)' type_id=3
> >> >> > >> > [42] ARRAY '(anon)' type_id=19 index_type_id=16 nr_elems=18
> >> >> > >> > [43] CONST '(anon)' type_id=42
> >> >> > >> > [44] FUNC_PROTO '(anon)' ret_type_id=36 vlen=2
> >> >> > >> >     '(anon)' type_id=36
> >> >> > >> >     '(anon)' type_id=46
> >> >> > >> > [45] CONST '(anon)' type_id=0
> >> >> > >> > [46] PTR '(anon)' type_id=45
> >> >> > >> > [47] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
> >> >> > >> >     'sk' type_id=48
> >> >> > >> > [48] PTR '(anon)' type_id=35
> >> >> > >> > [49] VAR '_license' type_id=43, linkage=static
> >> >> > >> > [50] VAR 'is_allow_list' type_id=5, linkage=global
> >> >> > >> > [51] VAR 'sd_restrictif' type_id=37, linkage=global
> >> >> > >> > [52] FUNC 'sd_restrictif_i' type_id=47 linkage=global
> >> >> > >> > [53] FUNC 'sd_restrictif_e' type_id=47 linkage=global
> >> >> > >> > [54] FUNC 'restrict_network_interfaces_impl' type_id=47 linkage=static
> >> >> > >> > [55] DATASEC '.data' size=1 vlen=1
> >> >> > >> >     type_id=50 offset=0 size=1 (VAR 'is_allow_list')
> >> >> > >> > [56] DATASEC 'license' size=18 vlen=1
> >> >> > >> >     type_id=49 offset=0 size=18 (VAR '_license')
> >> >> > >> > [57] DATASEC '.maps' size=24 vlen=1
> >> >> > >> >     type_id=51 offset=0 size=24 (VAR 'sd_restrictif')
> >> >> > >> >
> >> >> > >> > File before being stripped using bpftool gen object:
> >> >> > >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> >> >> > >> > btf dump file
> >> >> > >> >
> >> >
> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
> >> >> > >> > format raw
> >> >> > >> > [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> >> >> > >> > [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
> >> >> > >> > [3] TYPEDEF '__u8' type_id=2
> >> >> > >> > [4] CONST '(anon)' type_id=3
> >> >> > >> > [5] VOLATILE '(anon)' type_id=4
> >> >> > >> > [6] INT 'short int' size=2 bits_offset=0 nr_bits=16 encoding=SIGNED
> >> >> > >> > [7] INT 'short unsigned int' size=2 bits_offset=0 nr_bits=16 encoding=(none)
> >> >> > >> > [8] TYPEDEF '__u16' type_id=7
> >> >> > >> > [9] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
> >> >> > >> > [10] TYPEDEF '__s32' type_id=9
> >> >> > >> > [11] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
> >> >> > >> > [12] TYPEDEF '__u32' type_id=11
> >> >> > >> > [13] INT 'long long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
> >> >> > >> > [14] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64
> >> >> > >> > encoding=(none)
> >> >> > >> > [15] TYPEDEF '__u64' type_id=14
> >> >> > >> > [16] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
> >> >> > >> > [17] INT 'long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
> >> >> > >> > [18] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> >> >> > >> > [19] CONST '(anon)' type_id=18
> >> >> > >> > [20] TYPEDEF '__be16' type_id=8
> >> >> > >> > [21] TYPEDEF '__be32' type_id=12
> >> >> > >> > [22] ENUM 'bpf_map_type' encoding=UNSIGNED size=4 vlen=31
> >> >> > >> >     'BPF_MAP_TYPE_UNSPEC' val=0
> >> >> > >> >     'BPF_MAP_TYPE_HASH' val=1
> >> >> > >> >     'BPF_MAP_TYPE_ARRAY' val=2
> >> >> > >> >     'BPF_MAP_TYPE_PROG_ARRAY' val=3
> >> >> > >> >     'BPF_MAP_TYPE_PERF_EVENT_ARRAY' val=4
> >> >> > >> >     'BPF_MAP_TYPE_PERCPU_HASH' val=5
> >> >> > >> >     'BPF_MAP_TYPE_PERCPU_ARRAY' val=6
> >> >> > >> >     'BPF_MAP_TYPE_STACK_TRACE' val=7
> >> >> > >> >     'BPF_MAP_TYPE_CGROUP_ARRAY' val=8
> >> >> > >> >     'BPF_MAP_TYPE_LRU_HASH' val=9
> >> >> > >> >     'BPF_MAP_TYPE_LRU_PERCPU_HASH' val=10
> >> >> > >> >     'BPF_MAP_TYPE_LPM_TRIE' val=11
> >> >> > >> >     'BPF_MAP_TYPE_ARRAY_OF_MAPS' val=12
> >> >> > >> >     'BPF_MAP_TYPE_HASH_OF_MAPS' val=13
> >> >> > >> >     'BPF_MAP_TYPE_DEVMAP' val=14
> >> >> > >> >     'BPF_MAP_TYPE_SOCKMAP' val=15
> >> >> > >> >     'BPF_MAP_TYPE_CPUMAP' val=16
> >> >> > >> >     'BPF_MAP_TYPE_XSKMAP' val=17
> >> >> > >> >     'BPF_MAP_TYPE_SOCKHASH' val=18
> >> >> > >> >     'BPF_MAP_TYPE_CGROUP_STORAGE' val=19
> >> >> > >> >     'BPF_MAP_TYPE_REUSEPORT_SOCKARRAY' val=20
> >> >> > >> >     'BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE' val=21
> >> >> > >> >     'BPF_MAP_TYPE_QUEUE' val=22
> >> >> > >> >     'BPF_MAP_TYPE_STACK' val=23
> >> >> > >> >     'BPF_MAP_TYPE_SK_STORAGE' val=24
> >> >> > >> >     'BPF_MAP_TYPE_DEVMAP_HASH' val=25
> >> >> > >> >     'BPF_MAP_TYPE_STRUCT_OPS' val=26
> >> >> > >> >     'BPF_MAP_TYPE_RINGBUF' val=27
> >> >> > >> >     'BPF_MAP_TYPE_INODE_STORAGE' val=28
> >> >> > >> >     'BPF_MAP_TYPE_TASK_STORAGE' val=29
> >> >> > >> >     'BPF_MAP_TYPE_BLOOM_FILTER' val=30
> >> >> > >> > [23] UNION '(anon)' size=8 vlen=1
> >> >> > >> >     'flow_keys' type_id=29 bits_offset=0
> >> >> > >> > [24] STRUCT 'bpf_flow_keys' size=56 vlen=13
> >> >> > >> >     'nhoff' type_id=8 bits_offset=0
> >> >> > >> >     'thoff' type_id=8 bits_offset=16
> >> >> > >> >     'addr_proto' type_id=8 bits_offset=32
> >> >> > >> >     'is_frag' type_id=3 bits_offset=48
> >> >> > >> >     'is_first_frag' type_id=3 bits_offset=56
> >> >> > >> >     'is_encap' type_id=3 bits_offset=64
> >> >> > >> >     'ip_proto' type_id=3 bits_offset=72
> >> >> > >> >     'n_proto' type_id=20 bits_offset=80
> >> >> > >> >     'sport' type_id=20 bits_offset=96
> >> >> > >> >     'dport' type_id=20 bits_offset=112
> >> >> > >> >     '(anon)' type_id=25 bits_offset=128
> >> >> > >> >     'flags' type_id=12 bits_offset=384
> >> >> > >> >     'flow_label' type_id=21 bits_offset=416
> >> >> > >> > [25] UNION '(anon)' size=32 vlen=2
> >> >> > >> >     '(anon)' type_id=26 bits_offset=0
> >> >> > >> >     '(anon)' type_id=27 bits_offset=0
> >> >> > >> > [26] STRUCT '(anon)' size=8 vlen=2
> >> >> > >> >     'ipv4_src' type_id=21 bits_offset=0
> >> >> > >> >     'ipv4_dst' type_id=21 bits_offset=32
> >> >> > >> > [27] STRUCT '(anon)' size=32 vlen=2
> >> >> > >> >     'ipv6_src' type_id=28 bits_offset=0
> >> >> > >> >     'ipv6_dst' type_id=28 bits_offset=128
> >> >> > >> > [28] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=4
> >> >> > >> > [29] PTR '(anon)' type_id=24
> >> >> > >> > [30] UNION '(anon)' size=8 vlen=1
> >> >> > >> >     'sk' type_id=32 bits_offset=0
> >> >> > >> > [31] STRUCT 'bpf_sock' size=80 vlen=14
> >> >> > >> >     'bound_dev_if' type_id=12 bits_offset=0
> >> >> > >> >     'family' type_id=12 bits_offset=32
> >> >> > >> >     'type' type_id=12 bits_offset=64
> >> >> > >> >     'protocol' type_id=12 bits_offset=96
> >> >> > >> >     'mark' type_id=12 bits_offset=128
> >> >> > >> >     'priority' type_id=12 bits_offset=160
> >> >> > >> >     'src_ip4' type_id=12 bits_offset=192
> >> >> > >> >     'src_ip6' type_id=28 bits_offset=224
> >> >> > >> >     'src_port' type_id=12 bits_offset=352
> >> >> > >> >     'dst_port' type_id=20 bits_offset=384
> >> >> > >> >     'dst_ip4' type_id=12 bits_offset=416
> >> >> > >> >     'dst_ip6' type_id=28 bits_offset=448
> >> >> > >> >     'state' type_id=12 bits_offset=576
> >> >> > >> >     'rx_queue_mapping' type_id=10 bits_offset=608
> >> >> > >> > [32] PTR '(anon)' type_id=31
> >> >> > >> > [33] STRUCT '__sk_buff' size=192 vlen=33
> >> >> > >> >     'len' type_id=12 bits_offset=0
> >> >> > >> >     'pkt_type' type_id=12 bits_offset=32
> >> >> > >> >     'mark' type_id=12 bits_offset=64
> >> >> > >> >     'queue_mapping' type_id=12 bits_offset=96
> >> >> > >> >     'protocol' type_id=12 bits_offset=128
> >> >> > >> >     'vlan_present' type_id=12 bits_offset=160
> >> >> > >> >     'vlan_tci' type_id=12 bits_offset=192
> >> >> > >> >     'vlan_proto' type_id=12 bits_offset=224
> >> >> > >> >     'priority' type_id=12 bits_offset=256
> >> >> > >> >     'ingress_ifindex' type_id=12 bits_offset=288
> >> >> > >> >     'ifindex' type_id=12 bits_offset=320
> >> >> > >> >     'tc_index' type_id=12 bits_offset=352
> >> >> > >> >     'cb' type_id=34 bits_offset=384
> >> >> > >> >     'hash' type_id=12 bits_offset=544
> >> >> > >> >     'tc_classid' type_id=12 bits_offset=576
> >> >> > >> >     'data' type_id=12 bits_offset=608
> >> >> > >> >     'data_end' type_id=12 bits_offset=640
> >> >> > >> >     'napi_id' type_id=12 bits_offset=672
> >> >> > >> >     'family' type_id=12 bits_offset=704
> >> >> > >> >     'remote_ip4' type_id=12 bits_offset=736
> >> >> > >> >     'local_ip4' type_id=12 bits_offset=768
> >> >> > >> >     'remote_ip6' type_id=28 bits_offset=800
> >> >> > >> >     'local_ip6' type_id=28 bits_offset=928
> >> >> > >> >     'remote_port' type_id=12 bits_offset=1056
> >> >> > >> >     'local_port' type_id=12 bits_offset=1088
> >> >> > >> >     'data_meta' type_id=12 bits_offset=1120
> >> >> > >> >     '(anon)' type_id=23 bits_offset=1152
> >> >> > >> >     'tstamp' type_id=15 bits_offset=1216
> >> >> > >> >     'wire_len' type_id=12 bits_offset=1280
> >> >> > >> >     'gso_segs' type_id=12 bits_offset=1312
> >> >> > >> >     '(anon)' type_id=30 bits_offset=1344
> >> >> > >> >     'gso_size' type_id=12 bits_offset=1408
> >> >> > >> >     'hwtstamp' type_id=15 bits_offset=1472
> >> >> > >> > [34] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=5
> >> >> > >> > [35] CONST '(anon)' type_id=33
> >> >> > >> > [36] PTR '(anon)' type_id=0
> >> >> > >> > [37] STRUCT '(anon)' size=24 vlen=3
> >> >> > >> >     'type' type_id=39 bits_offset=0
> >> >> > >> >     'key' type_id=40 bits_offset=64
> >> >> > >> >     'value' type_id=41 bits_offset=128
> >> >> > >> > [38] ARRAY '(anon)' type_id=9 index_type_id=16 nr_elems=1
> >> >> > >> > [39] PTR '(anon)' type_id=38
> >> >> > >> > [40] PTR '(anon)' type_id=12
> >> >> > >> > [41] PTR '(anon)' type_id=3
> >> >> > >> > [42] ARRAY '(anon)' type_id=19 index_type_id=16 nr_elems=18
> >> >> > >> > [43] CONST '(anon)' type_id=42
> >> >> > >> > [44] FUNC_PROTO '(anon)' ret_type_id=36 vlen=2
> >> >> > >> >     '(anon)' type_id=36
> >> >> > >> >     '(anon)' type_id=46
> >> >> > >> > [45] CONST '(anon)' type_id=0
> >> >> > >> > [46] PTR '(anon)' type_id=45
> >> >> > >> > [47] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
> >> >> > >> >     'sk' type_id=48
> >> >> > >> > [48] PTR '(anon)' type_id=35
> >> >> > >> > [49] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
> >> >> > >> >     'sk' type_id=48
> >> >> > >> > [50] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
> >> >> > >> >     'sk' type_id=48
> >> >> > >> > [51] VAR '_license' type_id=43, linkage=static
> >> >> > >> > [52] VAR 'is_allow_list' type_id=5, linkage=global
> >> >> > >> > [53] VAR 'sd_restrictif' type_id=37, linkage=global
> >> >> > >> > [54] FUNC 'bpf_map_lookup_elem' type_id=44 linkage=global
> >> >> > >> > [55] FUNC 'sd_restrictif_i' type_id=47 linkage=global
> >> >> > >> > [56] FUNC 'sd_restrictif_e' type_id=49 linkage=global
> >> >> > >> > [57] FUNC 'restrict_network_interfaces_impl' type_id=50 linkage=static
> >> >> > >> > [58] DATASEC 'license' size=0 vlen=1
> >> >> > >> >     type_id=51 offset=0 size=18 (VAR '_license')
> >> >> > >> > [59] DATASEC '.maps' size=0 vlen=1
> >> >> > >> >     type_id=53 offset=0 size=24 (VAR 'sd_restrictif')
> >> >> > >> > [60] DATASEC '.data' size=0 vlen=1
> >> >> > >> >     type_id=52 offset=0 size=1 (VAR 'is_allow_list')
> >> >> > >> >
> >> >> > >> >>
> >> >> > >> >> >> GCC is wrong, clearly. This function is global ([0]) and libbpf
> >> >> > >> >> >> expects it to be marked as such in BTF.
> >> >> > >> >> >>
> >> >> > >> >> >>
> >> >> > >> >
> >> >
> > https://github.com/systemd/systemd/blob/main/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.c#L42-L50
> >> >> > >> >> >>
> >> >> > >> >> >>
> >> >> > >> >> >>> GCC:
> >> >> > >> >> >>>
> >> >> > >> >> >>> [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
> >> >> > >> >> >>> [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
> >> >> > >> >> >>> [3] TYPEDEF '__u8' type_id=2
> >> >> > >> >> >>> [4] CONST '(anon)' type_id=3
> >> >> > >> >> >>
> >> >> > >> >> >> [...]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-07-10 12:16                         ` James Hilliard
@ 2022-07-10 13:06                           ` Jose E. Marchesi
  2022-07-10 19:49                             ` Jose E. Marchesi
  0 siblings, 1 reply; 38+ messages in thread
From: Jose E. Marchesi @ 2022-07-10 13:06 UTC (permalink / raw)
  To: James Hilliard; +Cc: Andrii Nakryiko, bpf, david.faust


> On Sun, Jul 10, 2022 at 3:38 AM Jose E. Marchesi
> <jose.marchesi@oracle.com> wrote:
>>
>>
>> > On Sat, Jul 9, 2022 at 4:41 PM Jose E. Marchesi
>> > <jose.marchesi@oracle.com> wrote:
>> >>
>> >>
>> >> > On Sat, Jul 9, 2022 at 2:32 PM James Hilliard <james.hilliard1@gmail.com> wrote:
>> >> >>
>> >> >> On Sat, Jul 9, 2022 at 2:21 PM Jose E. Marchesi
>> >> >> <jose.marchesi@oracle.com> wrote:
>> >> >> >
>> >> >> >
>> >> >> > > On Sat, Jul 9, 2022 at 11:24 AM Jose E. Marchesi
>> >> >> > > <jose.marchesi@oracle.com> wrote:
>> >> >> > >>
>> >> >> > >>
>> >> >> > >> > On Fri, Jul 8, 2022 at 12:33 PM Jose E. Marchesi
>> >> >> > >> > <jose.marchesi@oracle.com> wrote:
>> >> >> > >> >>
>> >> >> > >> >>
>> >> >> > >> >> >> On Wed, Jul 6, 2022 at 10:13 AM James Hilliard
>> >> >> > >> >> >> <james.hilliard1@gmail.com> wrote:
>> >> >> > >> >> >>>
>> >> >> > >> >> >>> Note I'm testing with the following patches:
>> >> >> > >> >> >>> https://lore.kernel.org/bpf/20220706111839.1247911-1-james.hilliard1@gmail.com/
>> >> >> > >> >> >>> https://lore.kernel.org/bpf/20220706140623.2917858-1-james.hilliard1@gmail.com/
>> >> >> > >> >> >>>
>> >> >> > >> >> >>> It would appear there's some compatibility issues with bpftool gen and
>> >> >> > >> >> >>> GCC, not sure what side though is wrong here:
>> >> >> > >> >> >>> /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>> >> >> > >> >> >>> gen object src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>> >> >> > >> >> >>> src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
>> >> >> > >> >> >>> libbpf: failed to find BTF info for global/extern symbol 'sd_restrictif_i'
>> >> >> > >> >> >>> Error: failed to link
>> >> >> > >> >> >>> 'src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o':
>> >> >> > >> >> >>> Unknown error -2 (-2)
>> >> >> > >> >> >>>
>> >> >> > >> >> >>> Relevant difference seems to be this:
>> >> >> > >> >> >>> GCC:
>> >> >> > >> >> >>> [55] FUNC 'sd_restrictif_i' type_id=47 linkage=static
>> >> >> > >> >> >>> Clang:
>> >> >> > >> >> >>> [27] FUNC 'sd_restrictif_i' type_id=26 linkage=global
>> >> >> > >> >> >
>> >> >> > >> >> > For functions GCC generates a BTF_KIND_FUNC entry, which has no linkage
>> >> >> > >> >> > information, or so we thought: I just looked at bpftool/btf.c and I
>> >> >> > >> >> > found the linkage info for function types is expected to be encoded in
>> >> >> > >> >> > the vlen field of BTF_KIND_FUNC entries (why not adding a btf_func
>> >> >> > >> >> > instead???) which is surprising to say the least.
>> >> >> > >> >> >
>> >> >> > >> >> > We are changing GCC to encode the linkage info in vlen for these types.
>> >> >> > >> >> > Thanks for reporting this.
>> >> >> > >> >>
>> >> >> > >> >> Patch sent to GCC upstream:
>> >> >> > >> >> https://gcc.gnu.org/pipermail/gcc-patches/2022-July/598090.html
>> >> >> > >> >
>> >> >> > >> > I applied that patch on top of GCC 12.1.0 and it appears to fix the
>> >> >> > >> > bpftool gen object bug.
>> >> >> > >> >
>> >> >> > >> > I am however now hitting a different error during skeleton generation:
>> >> >> > >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>> >> >> > >> > gen skeleton src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>> >> >> > >> > libbpf: elf: skipping unrecognized data section(9) .comment
>> >> >> > >> > libbpf: failed to alloc map 'restrict.bss' content buffer: -22
>> >> >> > >> > Error: failed to open BPF object file: Invalid argument
>> >> >> > >>
>> >> >> > >> What is the size of the .bss section in the object file?  Try with:
>> >> >> > >>
>> >> >> > >> $ size restrict-ifaces.bpf.o
>> >> >> > >
>> >> >> > > $ size
>> >> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>> >> >> > >    text       data        bss        dec        hex    filename
>> >> >> > >     386         25          0        411        19b
>> >> >> > > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>> >> >> >
>> >> >> > Right, so the .bss section is empty.  I see a `const volatile unsigned
>> >> >> > char is_allow_list = 0;' in restrict-ifaces.bpf.c, but that goes to
>> >> >> > .data and not to .bss, as expected.
>> >> >> >
>> >> >> > If you build restrict-ifaces.bpf.o with LLVM, is the bss still empty?  I
>> >> >> > don't think the code in libbpf.c even checks for this eventuality...
>> >> >>
>> >> >> LLVM version(which skeleton generation works with):
>> >> >> $ size restrict-ifaces.bpf.o
>> >> >>    text       data        bss        dec        hex    filename
>> >> >>     323         24          0        347        15b    restrict-ifaces.bpf.o
>> >> >>
>> >> >> $ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>> >> >> btf dump file restrict-ifaces.bpf.o format raw
>> >> >> [1] PTR '(anon)' type_id=3
>> >> >> [2] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
>> >> >> [3] ARRAY '(anon)' type_id=2 index_type_id=4 nr_elems=1
>> >> >> [4] INT '__ARRAY_SIZE_TYPE__' size=4 bits_offset=0 nr_bits=32 encoding=(none)
>> >> >> [5] PTR '(anon)' type_id=6
>> >> >> [6] TYPEDEF '__u32' type_id=7
>> >> >> [7] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
>> >> >> [8] PTR '(anon)' type_id=9
>> >> >> [9] TYPEDEF '__u8' type_id=10
>> >> >> [10] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=(none)
>> >> >> [11] STRUCT '(anon)' size=24 vlen=3
>> >> >>     'type' type_id=1 bits_offset=0
>> >> >>     'key' type_id=5 bits_offset=64
>> >> >>     'value' type_id=8 bits_offset=128
>> >> >> [12] VAR 'sd_restrictif' type_id=11, linkage=global
>> >> >> [13] PTR '(anon)' type_id=14
>> >> >> [14] CONST '(anon)' type_id=15
>> >> >> [15] STRUCT '__sk_buff' size=192 vlen=33
>> >> >>     'len' type_id=6 bits_offset=0
>> >> >>     'pkt_type' type_id=6 bits_offset=32
>> >> >>     'mark' type_id=6 bits_offset=64
>> >> >>     'queue_mapping' type_id=6 bits_offset=96
>> >> >>     'protocol' type_id=6 bits_offset=128
>> >> >>     'vlan_present' type_id=6 bits_offset=160
>> >> >>     'vlan_tci' type_id=6 bits_offset=192
>> >> >>     'vlan_proto' type_id=6 bits_offset=224
>> >> >>     'priority' type_id=6 bits_offset=256
>> >> >>     'ingress_ifindex' type_id=6 bits_offset=288
>> >> >>     'ifindex' type_id=6 bits_offset=320
>> >> >>     'tc_index' type_id=6 bits_offset=352
>> >> >>     'cb' type_id=16 bits_offset=384
>> >> >>     'hash' type_id=6 bits_offset=544
>> >> >>     'tc_classid' type_id=6 bits_offset=576
>> >> >>     'data' type_id=6 bits_offset=608
>> >> >>     'data_end' type_id=6 bits_offset=640
>> >> >>     'napi_id' type_id=6 bits_offset=672
>> >> >>     'family' type_id=6 bits_offset=704
>> >> >>     'remote_ip4' type_id=6 bits_offset=736
>> >> >>     'local_ip4' type_id=6 bits_offset=768
>> >> >>     'remote_ip6' type_id=17 bits_offset=800
>> >> >>     'local_ip6' type_id=17 bits_offset=928
>> >> >>     'remote_port' type_id=6 bits_offset=1056
>> >> >>     'local_port' type_id=6 bits_offset=1088
>> >> >>     'data_meta' type_id=6 bits_offset=1120
>> >> >>     '(anon)' type_id=18 bits_offset=1152
>> >> >>     'tstamp' type_id=20 bits_offset=1216
>> >> >>     'wire_len' type_id=6 bits_offset=1280
>> >> >>     'gso_segs' type_id=6 bits_offset=1312
>> >> >>     '(anon)' type_id=22 bits_offset=1344
>> >> >>     'gso_size' type_id=6 bits_offset=1408
>> >> >>     'hwtstamp' type_id=20 bits_offset=1472
>> >> >> [16] ARRAY '(anon)' type_id=6 index_type_id=4 nr_elems=5
>> >> >> [17] ARRAY '(anon)' type_id=6 index_type_id=4 nr_elems=4
>> >> >> [18] UNION '(anon)' size=8 vlen=1
>> >> >>     'flow_keys' type_id=19 bits_offset=0
>> >> >> [19] PTR '(anon)' type_id=34
>> >> >> [20] TYPEDEF '__u64' type_id=21
>> >> >> [21] INT 'unsigned long long' size=8 bits_offset=0 nr_bits=64 encoding=(none)
>> >> >> [22] UNION '(anon)' size=8 vlen=1
>> >> >>     'sk' type_id=23 bits_offset=0
>> >> >> [23] PTR '(anon)' type_id=35
>> >> >> [24] FUNC_PROTO '(anon)' ret_type_id=2 vlen=1
>> >> >>     'sk' type_id=13
>> >> >> [25] FUNC 'sd_restrictif_e' type_id=24 linkage=global
>> >> >> [26] FUNC 'sd_restrictif_i' type_id=24 linkage=global
>> >> >> [27] CONST '(anon)' type_id=28
>> >> >> [28] VOLATILE '(anon)' type_id=9
>> >> >> [29] VAR 'is_allow_list' type_id=27, linkage=global
>> >> >> [30] CONST '(anon)' type_id=31
>> >> >> [31] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=SIGNED
>> >> >> [32] ARRAY '(anon)' type_id=30 index_type_id=4 nr_elems=18
>> >> >> [33] VAR '_license' type_id=32, linkage=static
>> >> >> [34] FWD 'bpf_flow_keys' fwd_kind=struct
>> >> >> [35] FWD 'bpf_sock' fwd_kind=struct
>> >> >> [36] DATASEC '.rodata' size=1 vlen=1
>> >> >>     type_id=29 offset=0 size=1 (VAR 'is_allow_list')
>> >> >> [37] DATASEC 'license' size=18 vlen=1
>> >> >>     type_id=33 offset=0 size=18 (VAR '_license')
>> >> >> [38] DATASEC '.maps' size=24 vlen=1
>> >> >>     type_id=12 offset=0 size=24 (VAR 'sd_restrictif')
>> >> >>
>> >> >
>> >> > Skeleton generation debug output for GCC(failing) and LLVM(working)
>> >> > which may be helpful:
>> >>
>> >> Indeed it was helpful :)
>> >>
>> >> The GNU assembler generates an empty .bss section.  This is a well
>> >> established behavior in GAS that happens in all supported targets.
>> >>
>> >> The LLVM assembler doesn't generate an empty .bss section.
>> >>
>> >> bpftool chokes on the empty .bss section.
>> >>
>> >> In this case I would suggest to fix bpf_object__init_global_data_maps in
>> >> order to skip empty sections.
>> >>
>> >> Something like this:
>> >
>> > Hmm, that seems to segfault:
>>
>> Yes, I see in bpf_object__elf_collect that sec_desc->data is not
>> initialized when a section is not recognized.  In this case, this
>> happens with .comment.
>>
>> All right then:
>>
>> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
>> index e89cc9c885b3..887b78780099 100644
>> --- a/tools/lib/bpf/libbpf.c
>> +++ b/tools/lib/bpf/libbpf.c
>> @@ -1591,6 +1591,10 @@ static int bpf_object__init_global_data_maps(struct bpf_object *obj)
>>         for (sec_idx = 1; sec_idx < obj->efile.sec_cnt; sec_idx++) {
>>                 sec_desc = &obj->efile.secs[sec_idx];
>>
>> +                /* Skip recognized sections with size 0.  */
>> +                if (sec_desc->data && sec_desc->data->d_size == 0)
>> +                  continue;
>> +
>>                 switch (sec_desc->sec_type) {
>>                 case SEC_DATA:
>>                         sec_name = elf_sec_name(obj, elf_sec_by_idx(obj, sec_idx));
>
> Ok, skeleton is now getting generated successfully, however it differs from the
> clang version so there's a build error when we include/use the header:
> ../src/core/restrict-ifaces.c: In function ‘prepare_restrict_ifaces_bpf’:
> ../src/core/restrict-ifaces.c:45:14: error: ‘struct
> restrict_ifaces_bpf’ has no member named ‘rodata’; did you mean
> ‘data’?
>    45 |         obj->rodata->is_allow_list = is_allow_list;
>       |              ^~~~~~
>       |              data
>
> The issue appears to be that clang generates "rodata" members in
> restrict_ifaces_bpf while with gcc we get "data" members instead.

This is because the BPF GCC port is putting the

  const volatile unsigned char is_allow_list = 0;

in a .data section instead of .rodata, due to the `volatile'.  The
x86_64 GCC seems to use .rodata.

Looking at why the PBF port does this...


> Differences below:
>
> GCC:
> $ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> --debug gen skeleton
> output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
> libbpf: loading object 'restrict_ifaces_bpf' from buffer
> libbpf: elf: section(2) .symtab, size 336, link 1, flags 0, type=2
> libbpf: elf: section(3) .data, size 1, link 0, flags 3, type=1
> libbpf: elf: section(4) .bss, size 0, link 0, flags 3, type=8
> libbpf: elf: section(5) cgroup_skb/egress, size 184, link 0, flags 6, type=1
> libbpf: sec 'cgroup_skb/egress': found program 'sd_restrictif_e' at
> insn offset 0 (0 bytes), code size 23 insns (184 bytes)
> libbpf: elf: section(6) cgroup_skb/ingress, size 184, link 0, flags 6, type=1
> libbpf: sec 'cgroup_skb/ingress': found program 'sd_restrictif_i' at
> insn offset 0 (0 bytes), code size 23 insns (184 bytes)
> libbpf: elf: section(7) license, size 18, link 0, flags 2, type=1
> libbpf: license of restrict_ifaces_bpf is LGPL-2.1-or-later
> libbpf: elf: section(8) .maps, size 24, link 0, flags 3, type=1
> libbpf: elf: section(9) .comment, size 49, link 0, flags 30, type=1
> libbpf: elf: skipping unrecognized data section(9) .comment
> libbpf: elf: section(10) .relcgroup_skb/egress, size 32, link 2, flags
> 40, type=9
> libbpf: elf: section(11) .relcgroup_skb/ingress, size 32, link 2,
> flags 40, type=9
> libbpf: elf: section(12) .BTF, size 3606, link 0, flags 0, type=1
> libbpf: looking for externs among 14 symbols...
> libbpf: collected 0 externs total
> libbpf: map 'sd_restrictif': at sec_idx 8, offset 0.
> libbpf: map 'sd_restrictif': found type = 1.
> libbpf: map 'sd_restrictif': found key [12], sz = 4.
> libbpf: map 'sd_restrictif': found value [3], sz = 1.
> libbpf: map 'restrict.data' (global data): at sec_idx 3, offset 0, flags 400.
> libbpf: map 1 is "restrict.data"
> libbpf: sec '.relcgroup_skb/egress': collecting relocation for
> section(5) 'cgroup_skb/egress'
> libbpf: sec '.relcgroup_skb/egress': relo #0: insn #4 against 'sd_restrictif'
> libbpf: prog 'sd_restrictif_e': found map 0 (sd_restrictif, sec 8, off
> 0) for insn #4
> libbpf: sec '.relcgroup_skb/egress': relo #1: insn #7 against 'is_allow_list'
> libbpf: prog 'sd_restrictif_e': found data map 1 (restrict.data, sec
> 3, off 0) for insn 7
> libbpf: sec '.relcgroup_skb/ingress': collecting relocation for
> section(6) 'cgroup_skb/ingress'
> libbpf: sec '.relcgroup_skb/ingress': relo #0: insn #4 against 'sd_restrictif'
> libbpf: prog 'sd_restrictif_i': found map 0 (sd_restrictif, sec 8, off
> 0) for insn #4
> libbpf: sec '.relcgroup_skb/ingress': relo #1: insn #7 against 'is_allow_list'
> libbpf: prog 'sd_restrictif_i': found data map 1 (restrict.data, sec
> 3, off 0) for insn 7
> /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
>
> /* THIS FILE IS AUTOGENERATED BY BPFTOOL! */
> #ifndef __RESTRICT_IFACES_BPF_SKEL_H__
> #define __RESTRICT_IFACES_BPF_SKEL_H__
>
> #include <errno.h>
> #include <stdlib.h>
> #include <bpf/libbpf.h>
>
> struct restrict_ifaces_bpf {
>     struct bpf_object_skeleton *skeleton;
>     struct bpf_object *obj;
>     struct {
>         struct bpf_map *sd_restrictif;
>         struct bpf_map *data;
>     } maps;
>     struct {
>         struct bpf_program *sd_restrictif_e;
>         struct bpf_program *sd_restrictif_i;
>     } progs;
>     struct {
>         struct bpf_link *sd_restrictif_e;
>         struct bpf_link *sd_restrictif_i;
>     } links;
>     struct restrict_ifaces_bpf__data {
>         __u8 is_allow_list;
>     } *data;
>
> #ifdef __cplusplus
>     static inline struct restrict_ifaces_bpf *open(const struct
> bpf_object_open_opts *opts = nullptr);
>     static inline struct restrict_ifaces_bpf *open_and_load();
>     static inline int load(struct restrict_ifaces_bpf *skel);
>     static inline int attach(struct restrict_ifaces_bpf *skel);
>     static inline void detach(struct restrict_ifaces_bpf *skel);
>     static inline void destroy(struct restrict_ifaces_bpf *skel);
>     static inline const void *elf_bytes(size_t *sz);
> #endif /* __cplusplus */
> };
>
> static void
> restrict_ifaces_bpf__destroy(struct restrict_ifaces_bpf *obj)
> {
>     if (!obj)
>         return;
>     if (obj->skeleton)
>         bpf_object__destroy_skeleton(obj->skeleton);
>     free(obj);
> }
>
> static inline int
> restrict_ifaces_bpf__create_skeleton(struct restrict_ifaces_bpf *obj);
>
> static inline struct restrict_ifaces_bpf *
> restrict_ifaces_bpf__open_opts(const struct bpf_object_open_opts *opts)
> {
>     struct restrict_ifaces_bpf *obj;
>     int err;
>
>     obj = (struct restrict_ifaces_bpf *)calloc(1, sizeof(*obj));
>     if (!obj) {
>         errno = ENOMEM;
>         return NULL;
>     }
>
>     err = restrict_ifaces_bpf__create_skeleton(obj);
>     if (err)
>         goto err_out;
>
>     err = bpf_object__open_skeleton(obj->skeleton, opts);
>     if (err)
>         goto err_out;
>
>     return obj;
> err_out:
>     restrict_ifaces_bpf__destroy(obj);
>     errno = -err;
>     return NULL;
> }
>
> static inline struct restrict_ifaces_bpf *
> restrict_ifaces_bpf__open(void)
> {
>     return restrict_ifaces_bpf__open_opts(NULL);
> }
>
> static inline int
> restrict_ifaces_bpf__load(struct restrict_ifaces_bpf *obj)
> {
>     return bpf_object__load_skeleton(obj->skeleton);
> }
>
> static inline struct restrict_ifaces_bpf *
> restrict_ifaces_bpf__open_and_load(void)
> {
>     struct restrict_ifaces_bpf *obj;
>     int err;
>
>     obj = restrict_ifaces_bpf__open();
>     if (!obj)
>         return NULL;
>     err = restrict_ifaces_bpf__load(obj);
>     if (err) {
>         restrict_ifaces_bpf__destroy(obj);
>         errno = -err;
>         return NULL;
>     }
>     return obj;
> }
>
> static inline int
> restrict_ifaces_bpf__attach(struct restrict_ifaces_bpf *obj)
> {
>     return bpf_object__attach_skeleton(obj->skeleton);
> }
>
> static inline void
> restrict_ifaces_bpf__detach(struct restrict_ifaces_bpf *obj)
> {
>     return bpf_object__detach_skeleton(obj->skeleton);
> }
>
> static inline const void *restrict_ifaces_bpf__elf_bytes(size_t *sz);
>
> static inline int
> restrict_ifaces_bpf__create_skeleton(struct restrict_ifaces_bpf *obj)
> {
>     struct bpf_object_skeleton *s;
>     int err;
>
>     s = (struct bpf_object_skeleton *)calloc(1, sizeof(*s));
>     if (!s)    {
>         err = -ENOMEM;
>         goto err;
>     }
>
>     s->sz = sizeof(*s);
>     s->name = "restrict_ifaces_bpf";
>     s->obj = &obj->obj;
>
>     /* maps */
>     s->map_cnt = 2;
>     s->map_skel_sz = sizeof(*s->maps);
>     s->maps = (struct bpf_map_skeleton *)calloc(s->map_cnt, s->map_skel_sz);
>     if (!s->maps) {
>         err = -ENOMEM;
>         goto err;
>     }
>
>     s->maps[0].name = "sd_restrictif";
>     s->maps[0].map = &obj->maps.sd_restrictif;
>
>     s->maps[1].name = "restrict.data";
>     s->maps[1].map = &obj->maps.data;
>     s->maps[1].mmaped = (void **)&obj->data;
>
>     /* programs */
>     s->prog_cnt = 2;
>     s->prog_skel_sz = sizeof(*s->progs);
>     s->progs = (struct bpf_prog_skeleton *)calloc(s->prog_cnt, s->prog_skel_sz);
>     if (!s->progs) {
>         err = -ENOMEM;
>         goto err;
>     }
>
>     s->progs[0].name = "sd_restrictif_e";
>     s->progs[0].prog = &obj->progs.sd_restrictif_e;
>     s->progs[0].link = &obj->links.sd_restrictif_e;
>
>     s->progs[1].name = "sd_restrictif_i";
>     s->progs[1].prog = &obj->progs.sd_restrictif_i;
>     s->progs[1].link = &obj->links.sd_restrictif_i;
>
>     s->data = (void *)restrict_ifaces_bpf__elf_bytes(&s->data_sz);
>
>     obj->skeleton = s;
>     return 0;
> err:
>     bpf_object__destroy_skeleton(s);
>     return err;
> }
>
> static inline const void *restrict_ifaces_bpf__elf_bytes(size_t *sz)
> {
>     *sz = 5616;
>     return (const void *)"\
> \x7f\x45\x4c\x46\x02\x01\x01\0\0\0\0\0\0\0\0\0\x01\0\xf7\0\x01\0\0\0\0\0\0\0\0\
> \0\0\0\0\0\0\0\0\0\0\0\xb0\x12\0\0\0\0\0\0\0\0\0\0\x40\0\0\0\0\0\x40\0\x0d\0\
> \x01\0\0\x2e\x73\x74\x72\x74\x61\x62\0\x2e\x73\x79\x6d\x74\x61\x62\0\x2e\x64\
> \x61\x74\x61\0\x2e\x62\x73\x73\0\x63\x67\x72\x6f\x75\x70\x5f\x73\x6b\x62\x2f\
> \x65\x67\x72\x65\x73\x73\0\x63\x67\x72\x6f\x75\x70\x5f\x73\x6b\x62\x2f\x69\x6e\
> \x67\x72\x65\x73\x73\0\x6c\x69\x63\x65\x6e\x73\x65\0\x2e\x6d\x61\x70\x73\0\x2e\
> \x63\x6f\x6d\x6d\x65\x6e\x74\0\x72\x65\x73\x74\x72\x69\x63\x74\x2d\x69\x66\x61\
> \x63\x65\x73\x2e\x62\x70\x66\x2e\x63\0\x5f\x6c\x69\x63\x65\x6e\x73\x65\0\x73\
> \x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\x5f\x65\0\x73\x64\x5f\x72\x65\
> \x73\x74\x72\x69\x63\x74\x69\x66\0\x69\x73\x5f\x61\x6c\x6c\x6f\x77\x5f\x6c\x69\
> \x73\x74\0\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\x5f\x69\0\x2e\
> \x72\x65\x6c\x63\x67\x72\x6f\x75\x70\x5f\x73\x6b\x62\x2f\x65\x67\x72\x65\x73\
> \x73\0\x2e\x72\x65\x6c\x63\x67\x72\x6f\x75\x70\x5f\x73\x6b\x62\x2f\x69\x6e\x67\
> \x72\x65\x73\x73\0\x2e\x42\x54\x46\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
> \0\0\0\0\0\0\x58\0\0\0\x04\0\xf1\xff\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
> \x03\0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x03\0\x04\0\0\0\0\0\0\0\0\
> \0\0\0\0\0\0\0\0\0\0\0\0\0\x03\0\x05\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
> \x03\0\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x03\0\x07\0\0\0\0\0\0\0\0\
> \0\0\0\0\0\0\0\0\0\x6e\0\0\0\x01\0\x07\0\0\0\0\0\0\0\0\0\x12\0\0\0\0\0\0\0\0\0\
> \0\0\x03\0\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x03\0\x09\0\0\0\0\0\0\
> \0\0\0\0\0\0\0\0\0\0\0\x77\0\0\0\x12\0\x05\0\0\0\0\0\0\0\0\0\xb8\0\0\0\0\0\0\0\
> \x87\0\0\0\x11\0\x08\0\0\0\0\0\0\0\0\0\x18\0\0\0\0\0\0\0\x95\0\0\0\x11\0\x03\0\
> \0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\xa3\0\0\0\x12\0\x06\0\0\0\0\0\0\0\0\0\xb8\0\
> \0\0\0\0\0\0\0\0\0\0\0\0\0\0\x61\x10\x28\0\0\0\0\0\x63\x0a\xfc\xff\0\0\0\0\xbf\
> \xa2\0\0\0\0\0\0\x07\x02\0\0\xfc\xff\xff\xff\x18\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\
> \0\x85\0\0\0\x01\0\0\0\x18\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x71\x13\0\0\0\0\0\0\
> \x57\x03\0\0\xff\0\0\0\x15\x03\x05\0\0\0\0\0\xbf\x02\0\0\0\0\0\0\x87\x02\0\0\0\
> \0\0\0\x4f\x20\0\0\0\0\0\0\x77\0\0\0\x3f\0\0\0\x95\0\0\0\0\0\0\0\xb7\x01\0\0\
> \x01\0\0\0\x15\0\x01\0\0\0\0\0\xbf\x31\0\0\0\0\0\0\xbf\x10\0\0\0\0\0\0\x57\0\0\
> \0\x01\0\0\0\x95\0\0\0\0\0\0\0\x61\x10\x28\0\0\0\0\0\x63\x0a\xfc\xff\0\0\0\0\
> \xbf\xa2\0\0\0\0\0\0\x07\x02\0\0\xfc\xff\xff\xff\x18\x01\0\0\0\0\0\0\0\0\0\0\0\
> \0\0\0\x85\0\0\0\x01\0\0\0\x18\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x71\x13\0\0\0\0\
> \0\0\x57\x03\0\0\xff\0\0\0\x15\x03\x05\0\0\0\0\0\xbf\x02\0\0\0\0\0\0\x87\x02\0\
> \0\0\0\0\0\x4f\x20\0\0\0\0\0\0\x77\0\0\0\x3f\0\0\0\x95\0\0\0\0\0\0\0\xb7\x01\0\
> \0\x01\0\0\0\x15\0\x01\0\0\0\0\0\xbf\x31\0\0\0\0\0\0\xbf\x10\0\0\0\0\0\0\x57\0\
> \0\0\x01\0\0\0\x95\0\0\0\0\0\0\0\x4c\x47\x50\x4c\x2d\x32\x2e\x31\x2d\x6f\x72\
> \x2d\x6c\x61\x74\x65\x72\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
> \0\0\0\0\0\x47\x43\x43\x3a\x20\x28\x42\x75\x69\x6c\x64\x72\x6f\x6f\x74\x20\x32\
> \x30\x32\x32\x2e\x30\x35\x2d\x31\x33\x32\x2d\x67\x35\x32\x38\x62\x35\x61\x36\
> \x35\x66\x36\x29\x20\x31\x32\x2e\x31\x2e\x30\0\0\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\
> \x01\0\0\0\x0b\0\0\0\x38\0\0\0\0\0\0\0\x01\0\0\0\x0c\0\0\0\x20\0\0\0\0\0\0\0\
> \x01\0\0\0\x0b\0\0\0\x38\0\0\0\0\0\0\0\x01\0\0\0\x0c\0\0\0\x9f\xeb\x01\0\x18\0\
> \0\0\0\0\0\0\x9c\x07\0\0\x9c\x07\0\0\x62\x06\0\0\x01\0\0\0\0\0\0\x01\x01\0\0\0\
> \x08\0\0\x03\x0d\0\0\0\0\0\0\x01\x01\0\0\0\x08\0\0\x02\x1b\0\0\0\0\0\0\x08\x02\
> \0\0\0\0\0\0\0\0\0\0\x0a\x03\0\0\0\0\0\0\0\0\0\0\x09\x04\0\0\0\x20\0\0\0\0\0\0\
> \x01\x02\0\0\0\x10\0\0\x01\x2a\0\0\0\0\0\0\x01\x02\0\0\0\x10\0\0\0\x3d\0\0\0\0\
> \0\0\x08\x07\0\0\0\x43\0\0\0\0\0\0\x01\x04\0\0\0\x20\0\0\x01\x47\0\0\0\0\0\0\
> \x08\x09\0\0\0\x4d\0\0\0\0\0\0\x01\x04\0\0\0\x20\0\0\0\x5a\0\0\0\0\0\0\x08\x0b\
> \0\0\0\x60\0\0\0\0\0\0\x01\x08\0\0\0\x40\0\0\x01\x6e\0\0\0\0\0\0\x01\x08\0\0\0\
> \x40\0\0\0\x85\0\0\0\0\0\0\x08\x0e\0\0\0\x8b\0\0\0\0\0\0\x01\x08\0\0\0\x40\0\0\
> \0\x9d\0\0\0\0\0\0\x01\x08\0\0\0\x40\0\0\x01\xa6\0\0\0\0\0\0\x01\x01\0\0\0\x08\
> \0\0\x03\0\0\0\0\0\0\0\x0a\x12\0\0\0\xab\0\0\0\0\0\0\x08\x08\0\0\0\xb2\0\0\0\0\
> \0\0\x08\x0c\0\0\0\xb9\0\0\0\x1f\0\0\x06\x04\0\0\0\xc6\0\0\0\0\0\0\0\xda\0\0\0\
> \x01\0\0\0\xec\0\0\0\x02\0\0\0\xff\0\0\0\x03\0\0\0\x17\x01\0\0\x04\0\0\0\x35\
> \x01\0\0\x05\0\0\0\x4e\x01\0\0\x06\0\0\0\x68\x01\0\0\x07\0\0\0\x81\x01\0\0\x08\
> \0\0\0\x9b\x01\0\0\x09\0\0\0\xb1\x01\0\0\x0a\0\0\0\xce\x01\0\0\x0b\0\0\0\xe4\
> \x01\0\0\x0c\0\0\0\xff\x01\0\0\x0d\0\0\0\x19\x02\0\0\x0e\0\0\0\x2d\x02\0\0\x0f\
> \0\0\0\x42\x02\0\0\x10\0\0\0\x56\x02\0\0\x11\0\0\0\x6a\x02\0\0\x12\0\0\0\x80\
> \x02\0\0\x13\0\0\0\x9c\x02\0\0\x14\0\0\0\xbd\x02\0\0\x15\0\0\0\xe0\x02\0\0\x16\
> \0\0\0\xf3\x02\0\0\x17\0\0\0\x06\x03\0\0\x18\0\0\0\x1e\x03\0\0\x19\0\0\0\x37\
> \x03\0\0\x1a\0\0\0\x4f\x03\0\0\x1b\0\0\0\x64\x03\0\0\x1c\0\0\0\x7f\x03\0\0\x1d\
> \0\0\0\x99\x03\0\0\x1e\0\0\0\0\0\0\0\x01\0\0\x05\x08\0\0\0\xb3\x03\0\0\x1d\0\0\
> \0\0\0\0\0\xbd\x03\0\0\x0d\0\0\x04\x38\0\0\0\xcb\x03\0\0\x08\0\0\0\0\0\0\0\xd1\
> \x03\0\0\x08\0\0\0\x10\0\0\0\xd7\x03\0\0\x08\0\0\0\x20\0\0\0\xe2\x03\0\0\x03\0\
> \0\0\x30\0\0\0\xea\x03\0\0\x03\0\0\0\x38\0\0\0\xf8\x03\0\0\x03\0\0\0\x40\0\0\0\
> \x01\x04\0\0\x03\0\0\0\x48\0\0\0\x0a\x04\0\0\x14\0\0\0\x50\0\0\0\x12\x04\0\0\
> \x14\0\0\0\x60\0\0\0\x18\x04\0\0\x14\0\0\0\x70\0\0\0\0\0\0\0\x19\0\0\0\x80\0\0\
> \0\x1e\x04\0\0\x0c\0\0\0\x80\x01\0\0\x24\x04\0\0\x15\0\0\0\xa0\x01\0\0\0\0\0\0\
> \x02\0\0\x05\x20\0\0\0\0\0\0\0\x1a\0\0\0\0\0\0\0\0\0\0\0\x1b\0\0\0\0\0\0\0\0\0\
> \0\0\x02\0\0\x04\x08\0\0\0\x2f\x04\0\0\x15\0\0\0\0\0\0\0\x38\x04\0\0\x15\0\0\0\
> \x20\0\0\0\0\0\0\0\x02\0\0\x04\x20\0\0\0\x41\x04\0\0\x1c\0\0\0\0\0\0\0\x4a\x04\
> \0\0\x1c\0\0\0\x80\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x0c\0\0\0\x10\0\0\0\x04\0\0\
> \0\0\0\0\0\0\0\0\x02\x18\0\0\0\0\0\0\0\x01\0\0\x05\x08\0\0\0\x53\x04\0\0\x20\0\
> \0\0\0\0\0\0\x56\x04\0\0\x0e\0\0\x04\x50\0\0\0\x5f\x04\0\0\x0c\0\0\0\0\0\0\0\
> \x6c\x04\0\0\x0c\0\0\0\x20\0\0\0\x73\x04\0\0\x0c\0\0\0\x40\0\0\0\x78\x04\0\0\
> \x0c\0\0\0\x60\0\0\0\x81\x04\0\0\x0c\0\0\0\x80\0\0\0\x86\x04\0\0\x0c\0\0\0\xa0\
> \0\0\0\x8f\x04\0\0\x0c\0\0\0\xc0\0\0\0\x97\x04\0\0\x1c\0\0\0\xe0\0\0\0\x9f\x04\
> \0\0\x0c\0\0\0\x60\x01\0\0\xa8\x04\0\0\x14\0\0\0\x80\x01\0\0\xb1\x04\0\0\x0c\0\
> \0\0\xa0\x01\0\0\xb9\x04\0\0\x1c\0\0\0\xc0\x01\0\0\xc1\x04\0\0\x0c\0\0\0\x40\
> \x02\0\0\xc7\x04\0\0\x0a\0\0\0\x60\x02\0\0\0\0\0\0\0\0\0\x02\x1f\0\0\0\xd8\x04\
> \0\0\x21\0\0\x04\xc0\0\0\0\xe2\x04\0\0\x0c\0\0\0\0\0\0\0\xe6\x04\0\0\x0c\0\0\0\
> \x20\0\0\0\x81\x04\0\0\x0c\0\0\0\x40\0\0\0\xef\x04\0\0\x0c\0\0\0\x60\0\0\0\x78\
> \x04\0\0\x0c\0\0\0\x80\0\0\0\xfd\x04\0\0\x0c\0\0\0\xa0\0\0\0\x0a\x05\0\0\x0c\0\
> \0\0\xc0\0\0\0\x13\x05\0\0\x0c\0\0\0\xe0\0\0\0\x86\x04\0\0\x0c\0\0\0\0\x01\0\0\
> \x1e\x05\0\0\x0c\0\0\0\x20\x01\0\0\x2e\x05\0\0\x0c\0\0\0\x40\x01\0\0\x36\x05\0\
> \0\x0c\0\0\0\x60\x01\0\0\x3f\x05\0\0\x22\0\0\0\x80\x01\0\0\x42\x05\0\0\x0c\0\0\
> \0\x20\x02\0\0\x47\x05\0\0\x0c\0\0\0\x40\x02\0\0\x52\x05\0\0\x0c\0\0\0\x60\x02\
> \0\0\x57\x05\0\0\x0c\0\0\0\x80\x02\0\0\x60\x05\0\0\x0c\0\0\0\xa0\x02\0\0\x6c\
> \x04\0\0\x0c\0\0\0\xc0\x02\0\0\x68\x05\0\0\x0c\0\0\0\xe0\x02\0\0\x73\x05\0\0\
> \x0c\0\0\0\0\x03\0\0\x7d\x05\0\0\x1c\0\0\0\x20\x03\0\0\x88\x05\0\0\x1c\0\0\0\
> \xa0\x03\0\0\x92\x05\0\0\x0c\0\0\0\x20\x04\0\0\x9e\x05\0\0\x0c\0\0\0\x40\x04\0\
> \0\xa9\x05\0\0\x0c\0\0\0\x60\x04\0\0\0\0\0\0\x17\0\0\0\x80\x04\0\0\xb3\x05\0\0\
> \x0f\0\0\0\xc0\x04\0\0\xba\x05\0\0\x0c\0\0\0\0\x05\0\0\xc3\x05\0\0\x0c\0\0\0\
> \x20\x05\0\0\0\0\0\0\x1e\0\0\0\x40\x05\0\0\xcc\x05\0\0\x0c\0\0\0\x80\x05\0\0\
> \xd5\x05\0\0\x0f\0\0\0\xc0\x05\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x0c\0\0\0\x10\0\0\
> \0\x05\0\0\0\0\0\0\0\0\0\0\x0a\x21\0\0\0\0\0\0\0\0\0\0\x02\0\0\0\0\0\0\0\0\x03\
> \0\0\x04\x18\0\0\0\x73\x04\0\0\x27\0\0\0\0\0\0\0\xde\x05\0\0\x28\0\0\0\x40\0\0\
> \0\xe2\x05\0\0\x29\0\0\0\x80\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x09\0\0\0\x10\0\0\
> \0\x01\0\0\0\0\0\0\0\0\0\0\x02\x26\0\0\0\0\0\0\0\0\0\0\x02\x0c\0\0\0\0\0\0\0\0\
> \0\0\x02\x03\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x13\0\0\0\x10\0\0\0\x12\0\0\0\0\0\
> \0\0\0\0\0\x0a\x2a\0\0\0\0\0\0\0\x02\0\0\x0d\x24\0\0\0\0\0\0\0\x24\0\0\0\0\0\0\
> \0\x2e\0\0\0\0\0\0\0\0\0\0\x0a\0\0\0\0\0\0\0\0\0\0\0\x02\x2d\0\0\0\0\0\0\0\x01\
> \0\0\x0d\x09\0\0\0\x53\x04\0\0\x30\0\0\0\0\0\0\0\0\0\0\x02\x23\0\0\0\xe8\x05\0\
> \0\0\0\0\x0e\x2b\0\0\0\0\0\0\0\xf1\x05\0\0\0\0\0\x0e\x05\0\0\0\x01\0\0\0\xff\
> \x05\0\0\0\0\0\x0e\x25\0\0\0\x01\0\0\0\x0d\x06\0\0\x01\0\0\x0c\x2f\0\0\0\x1d\
> \x06\0\0\x01\0\0\x0c\x2f\0\0\0\x2d\x06\0\0\0\0\0\x0c\x2f\0\0\0\x4e\x06\0\0\x01\
> \0\0\x0f\x01\0\0\0\x32\0\0\0\0\0\0\0\x01\0\0\0\x54\x06\0\0\x01\0\0\x0f\x12\0\0\
> \0\x31\0\0\0\0\0\0\0\x12\0\0\0\x5c\x06\0\0\x01\0\0\x0f\x18\0\0\0\x33\0\0\0\0\0\
> \0\0\x18\0\0\0\0\x73\x69\x67\x6e\x65\x64\x20\x63\x68\x61\x72\0\x75\x6e\x73\x69\
> \x67\x6e\x65\x64\x20\x63\x68\x61\x72\0\x5f\x5f\x75\x38\0\x73\x68\x6f\x72\x74\
> \x20\x69\x6e\x74\0\x73\x68\x6f\x72\x74\x20\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\
> \x69\x6e\x74\0\x5f\x5f\x75\x31\x36\0\x69\x6e\x74\0\x5f\x5f\x73\x33\x32\0\x75\
> \x6e\x73\x69\x67\x6e\x65\x64\x20\x69\x6e\x74\0\x5f\x5f\x75\x33\x32\0\x6c\x6f\
> \x6e\x67\x20\x6c\x6f\x6e\x67\x20\x69\x6e\x74\0\x6c\x6f\x6e\x67\x20\x6c\x6f\x6e\
> \x67\x20\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x69\x6e\x74\0\x5f\x5f\x75\x36\x34\
> \0\x6c\x6f\x6e\x67\x20\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x69\x6e\x74\0\x6c\
> \x6f\x6e\x67\x20\x69\x6e\x74\0\x63\x68\x61\x72\0\x5f\x5f\x62\x65\x31\x36\0\x5f\
> \x5f\x62\x65\x33\x32\0\x62\x70\x66\x5f\x6d\x61\x70\x5f\x74\x79\x70\x65\0\x42\
> \x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x55\x4e\x53\x50\x45\x43\0\x42\
> \x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x48\x41\x53\x48\0\x42\x50\x46\
> \x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x41\x52\x52\x41\x59\0\x42\x50\x46\x5f\
> \x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x50\x52\x4f\x47\x5f\x41\x52\x52\x41\x59\0\
> \x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x50\x45\x52\x46\x5f\x45\
> \x56\x45\x4e\x54\x5f\x41\x52\x52\x41\x59\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\
> \x59\x50\x45\x5f\x50\x45\x52\x43\x50\x55\x5f\x48\x41\x53\x48\0\x42\x50\x46\x5f\
> \x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x50\x45\x52\x43\x50\x55\x5f\x41\x52\x52\
> \x41\x59\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x53\x54\x41\x43\
> \x4b\x5f\x54\x52\x41\x43\x45\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\
> \x5f\x43\x47\x52\x4f\x55\x50\x5f\x41\x52\x52\x41\x59\0\x42\x50\x46\x5f\x4d\x41\
> \x50\x5f\x54\x59\x50\x45\x5f\x4c\x52\x55\x5f\x48\x41\x53\x48\0\x42\x50\x46\x5f\
> \x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x4c\x52\x55\x5f\x50\x45\x52\x43\x50\x55\
> \x5f\x48\x41\x53\x48\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x4c\
> \x50\x4d\x5f\x54\x52\x49\x45\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\
> \x5f\x41\x52\x52\x41\x59\x5f\x4f\x46\x5f\x4d\x41\x50\x53\0\x42\x50\x46\x5f\x4d\
> \x41\x50\x5f\x54\x59\x50\x45\x5f\x48\x41\x53\x48\x5f\x4f\x46\x5f\x4d\x41\x50\
> \x53\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x44\x45\x56\x4d\x41\
> \x50\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x53\x4f\x43\x4b\x4d\
> \x41\x50\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x43\x50\x55\x4d\
> \x41\x50\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x58\x53\x4b\x4d\
> \x41\x50\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x53\x4f\x43\x4b\
> \x48\x41\x53\x48\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x43\x47\
> \x52\x4f\x55\x50\x5f\x53\x54\x4f\x52\x41\x47\x45\0\x42\x50\x46\x5f\x4d\x41\x50\
> \x5f\x54\x59\x50\x45\x5f\x52\x45\x55\x53\x45\x50\x4f\x52\x54\x5f\x53\x4f\x43\
> \x4b\x41\x52\x52\x41\x59\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\
> \x50\x45\x52\x43\x50\x55\x5f\x43\x47\x52\x4f\x55\x50\x5f\x53\x54\x4f\x52\x41\
> \x47\x45\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x51\x55\x45\x55\
> \x45\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x53\x54\x41\x43\x4b\
> \0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x53\x4b\x5f\x53\x54\x4f\
> \x52\x41\x47\x45\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x44\x45\
> \x56\x4d\x41\x50\x5f\x48\x41\x53\x48\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\
> \x50\x45\x5f\x53\x54\x52\x55\x43\x54\x5f\x4f\x50\x53\0\x42\x50\x46\x5f\x4d\x41\
> \x50\x5f\x54\x59\x50\x45\x5f\x52\x49\x4e\x47\x42\x55\x46\0\x42\x50\x46\x5f\x4d\
> \x41\x50\x5f\x54\x59\x50\x45\x5f\x49\x4e\x4f\x44\x45\x5f\x53\x54\x4f\x52\x41\
> \x47\x45\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x54\x41\x53\x4b\
> \x5f\x53\x54\x4f\x52\x41\x47\x45\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\
> \x45\x5f\x42\x4c\x4f\x4f\x4d\x5f\x46\x49\x4c\x54\x45\x52\0\x66\x6c\x6f\x77\x5f\
> \x6b\x65\x79\x73\0\x62\x70\x66\x5f\x66\x6c\x6f\x77\x5f\x6b\x65\x79\x73\0\x6e\
> \x68\x6f\x66\x66\0\x74\x68\x6f\x66\x66\0\x61\x64\x64\x72\x5f\x70\x72\x6f\x74\
> \x6f\0\x69\x73\x5f\x66\x72\x61\x67\0\x69\x73\x5f\x66\x69\x72\x73\x74\x5f\x66\
> \x72\x61\x67\0\x69\x73\x5f\x65\x6e\x63\x61\x70\0\x69\x70\x5f\x70\x72\x6f\x74\
> \x6f\0\x6e\x5f\x70\x72\x6f\x74\x6f\0\x73\x70\x6f\x72\x74\0\x64\x70\x6f\x72\x74\
> \0\x66\x6c\x61\x67\x73\0\x66\x6c\x6f\x77\x5f\x6c\x61\x62\x65\x6c\0\x69\x70\x76\
> \x34\x5f\x73\x72\x63\0\x69\x70\x76\x34\x5f\x64\x73\x74\0\x69\x70\x76\x36\x5f\
> \x73\x72\x63\0\x69\x70\x76\x36\x5f\x64\x73\x74\0\x73\x6b\0\x62\x70\x66\x5f\x73\
> \x6f\x63\x6b\0\x62\x6f\x75\x6e\x64\x5f\x64\x65\x76\x5f\x69\x66\0\x66\x61\x6d\
> \x69\x6c\x79\0\x74\x79\x70\x65\0\x70\x72\x6f\x74\x6f\x63\x6f\x6c\0\x6d\x61\x72\
> \x6b\0\x70\x72\x69\x6f\x72\x69\x74\x79\0\x73\x72\x63\x5f\x69\x70\x34\0\x73\x72\
> \x63\x5f\x69\x70\x36\0\x73\x72\x63\x5f\x70\x6f\x72\x74\0\x64\x73\x74\x5f\x70\
> \x6f\x72\x74\0\x64\x73\x74\x5f\x69\x70\x34\0\x64\x73\x74\x5f\x69\x70\x36\0\x73\
> \x74\x61\x74\x65\0\x72\x78\x5f\x71\x75\x65\x75\x65\x5f\x6d\x61\x70\x70\x69\x6e\
> \x67\0\x5f\x5f\x73\x6b\x5f\x62\x75\x66\x66\0\x6c\x65\x6e\0\x70\x6b\x74\x5f\x74\
> \x79\x70\x65\0\x71\x75\x65\x75\x65\x5f\x6d\x61\x70\x70\x69\x6e\x67\0\x76\x6c\
> \x61\x6e\x5f\x70\x72\x65\x73\x65\x6e\x74\0\x76\x6c\x61\x6e\x5f\x74\x63\x69\0\
> \x76\x6c\x61\x6e\x5f\x70\x72\x6f\x74\x6f\0\x69\x6e\x67\x72\x65\x73\x73\x5f\x69\
> \x66\x69\x6e\x64\x65\x78\0\x69\x66\x69\x6e\x64\x65\x78\0\x74\x63\x5f\x69\x6e\
> \x64\x65\x78\0\x63\x62\0\x68\x61\x73\x68\0\x74\x63\x5f\x63\x6c\x61\x73\x73\x69\
> \x64\0\x64\x61\x74\x61\0\x64\x61\x74\x61\x5f\x65\x6e\x64\0\x6e\x61\x70\x69\x5f\
> \x69\x64\0\x72\x65\x6d\x6f\x74\x65\x5f\x69\x70\x34\0\x6c\x6f\x63\x61\x6c\x5f\
> \x69\x70\x34\0\x72\x65\x6d\x6f\x74\x65\x5f\x69\x70\x36\0\x6c\x6f\x63\x61\x6c\
> \x5f\x69\x70\x36\0\x72\x65\x6d\x6f\x74\x65\x5f\x70\x6f\x72\x74\0\x6c\x6f\x63\
> \x61\x6c\x5f\x70\x6f\x72\x74\0\x64\x61\x74\x61\x5f\x6d\x65\x74\x61\0\x74\x73\
> \x74\x61\x6d\x70\0\x77\x69\x72\x65\x5f\x6c\x65\x6e\0\x67\x73\x6f\x5f\x73\x65\
> \x67\x73\0\x67\x73\x6f\x5f\x73\x69\x7a\x65\0\x68\x77\x74\x73\x74\x61\x6d\x70\0\
> \x6b\x65\x79\0\x76\x61\x6c\x75\x65\0\x5f\x6c\x69\x63\x65\x6e\x73\x65\0\x69\x73\
> \x5f\x61\x6c\x6c\x6f\x77\x5f\x6c\x69\x73\x74\0\x73\x64\x5f\x72\x65\x73\x74\x72\
> \x69\x63\x74\x69\x66\0\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\x5f\
> \x69\0\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\x5f\x65\0\x72\x65\
> \x73\x74\x72\x69\x63\x74\x5f\x6e\x65\x74\x77\x6f\x72\x6b\x5f\x69\x6e\x74\x65\
> \x72\x66\x61\x63\x65\x73\x5f\x69\x6d\x70\x6c\0\x2e\x64\x61\x74\x61\0\x6c\x69\
> \x63\x65\x6e\x73\x65\0\x2e\x6d\x61\x70\x73\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
> \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
> \0\0\0\0\0\0\0\0\0\0\x01\0\0\0\x03\0\0\0\x20\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x40\
> \0\0\0\0\0\0\0\xe5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\
> \0\0\x09\0\0\0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x28\x01\0\0\0\0\0\0\
> \x50\x01\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\x18\0\0\0\0\0\0\0\x11\
> \0\0\0\x01\0\0\0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x78\x02\0\0\0\0\0\0\x01\0\0\
> \0\0\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x17\0\0\0\x08\0\0\
> \0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x79\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
> \0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x1c\0\0\0\x01\0\0\0\x06\0\0\0\0\0\
> \0\0\0\0\0\0\0\0\0\0\x80\x02\0\0\0\0\0\0\xb8\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\
> \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x2e\0\0\0\x01\0\0\0\x06\0\0\0\0\0\0\0\0\0\0\0\0\
> \0\0\0\x38\x03\0\0\0\0\0\0\xb8\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\
> \0\0\0\0\0\0\0\0\x41\0\0\0\x01\0\0\0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xf0\x03\
> \0\0\0\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
> \0\x49\0\0\0\x01\0\0\0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\x04\0\0\0\0\0\0\
> \x18\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x4f\0\0\0\
> \x01\0\0\0\x30\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x20\x04\0\0\0\0\0\0\x31\0\0\0\0\0\
> \0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\xb3\0\0\0\x09\0\0\0\
> \x40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x58\x04\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\x02\0\
> \0\0\x05\0\0\0\x08\0\0\0\0\0\0\0\x10\0\0\0\0\0\0\0\xc9\0\0\0\x09\0\0\0\x40\0\0\
> \0\0\0\0\0\0\0\0\0\0\0\0\0\x78\x04\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\x02\0\0\0\x06\
> \0\0\0\x08\0\0\0\0\0\0\0\x10\0\0\0\0\0\0\0\xe0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\
> \0\0\0\0\0\0\0\0\x98\x04\0\0\0\0\0\0\x16\x0e\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\
> \0\0\0\0\0\0\0\0\0\0\0\0\0\0";
> }
>
> #ifdef __cplusplus
> struct restrict_ifaces_bpf *restrict_ifaces_bpf::open(const struct
> bpf_object_open_opts *opts) { return
> restrict_ifaces_bpf__open_opts(opts); }
> struct restrict_ifaces_bpf *restrict_ifaces_bpf::open_and_load() {
> return restrict_ifaces_bpf__open_and_load(); }
> int restrict_ifaces_bpf::load(struct restrict_ifaces_bpf *skel) {
> return restrict_ifaces_bpf__load(skel); }
> int restrict_ifaces_bpf::attach(struct restrict_ifaces_bpf *skel) {
> return restrict_ifaces_bpf__attach(skel); }
> void restrict_ifaces_bpf::detach(struct restrict_ifaces_bpf *skel) {
> restrict_ifaces_bpf__detach(skel); }
> void restrict_ifaces_bpf::destroy(struct restrict_ifaces_bpf *skel) {
> restrict_ifaces_bpf__destroy(skel); }
> const void *restrict_ifaces_bpf::elf_bytes(size_t *sz) { return
> restrict_ifaces_bpf__elf_bytes(sz); }
> #endif /* __cplusplus */
>
> __attribute__((unused)) static void
> restrict_ifaces_bpf__assert(struct restrict_ifaces_bpf *s
> __attribute__((unused)))
> {
> #ifdef __cplusplus
> #define _Static_assert static_assert
> #endif
>     _Static_assert(sizeof(s->data->is_allow_list) == 1, "unexpected
> size of 'is_allow_list'");
> #ifdef __cplusplus
> #undef _Static_assert
> #endif
> }
>
> #endif /* __RESTRICT_IFACES_BPF_SKEL_H__ */
>
> Clang:
> $ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
> --debug gen skeleton restrict-ifaces.bpf.o
> libbpf: loading object 'restrict_ifaces_bpf' from buffer
> libbpf: elf: section(2) .symtab, size 384, link 1, flags 0, type=2
> libbpf: elf: section(3) cgroup_skb/egress, size 152, link 0, flags 6, type=1
> libbpf: sec 'cgroup_skb/egress': found program 'sd_restrictif_e' at
> insn offset 0 (0 bytes), code size 19 insns (152 bytes)
> libbpf: elf: section(4) cgroup_skb/ingress, size 152, link 0, flags 6, type=1
> libbpf: sec 'cgroup_skb/ingress': found program 'sd_restrictif_i' at
> insn offset 0 (0 bytes), code size 19 insns (152 bytes)
> libbpf: elf: section(5) .rodata, size 1, link 0, flags 2, type=1
> libbpf: elf: section(6) license, size 18, link 0, flags 2, type=1
> libbpf: license of restrict_ifaces_bpf is LGPL-2.1-or-later
> libbpf: elf: section(7) .maps, size 24, link 0, flags 3, type=1
> libbpf: elf: section(8) .relcgroup_skb/egress, size 32, link 2, flags 40, type=9
> libbpf: elf: section(9) .relcgroup_skb/ingress, size 32, link 2, flags
> 40, type=9
> libbpf: elf: section(10) .BTF, size 1988, link 0, flags 0, type=1
> libbpf: elf: section(11) .BTF.ext, size 376, link 0, flags 0, type=1
> libbpf: looking for externs among 16 symbols...
> libbpf: collected 0 externs total
> libbpf: map 'sd_restrictif': at sec_idx 7, offset 0.
> libbpf: map 'sd_restrictif': found type = 1.
> libbpf: map 'sd_restrictif': found key [6], sz = 4.
> libbpf: map 'sd_restrictif': found value [9], sz = 1.
> libbpf: map 'restrict.rodata' (global data): at sec_idx 5, offset 0, flags 480.
> libbpf: map 1 is "restrict.rodata"
> libbpf: sec '.relcgroup_skb/egress': collecting relocation for
> section(3) 'cgroup_skb/egress'
> libbpf: sec '.relcgroup_skb/egress': relo #0: insn #4 against 'sd_restrictif'
> libbpf: prog 'sd_restrictif_e': found map 0 (sd_restrictif, sec 7, off
> 0) for insn #4
> libbpf: sec '.relcgroup_skb/egress': relo #1: insn #7 against 'is_allow_list'
> libbpf: prog 'sd_restrictif_e': found data map 1 (restrict.rodata, sec
> 5, off 0) for insn 7
> libbpf: sec '.relcgroup_skb/ingress': collecting relocation for
> section(4) 'cgroup_skb/ingress'
> libbpf: sec '.relcgroup_skb/ingress': relo #0: insn #4 against 'sd_restrictif'
> libbpf: prog 'sd_restrictif_i': found map 0 (sd_restrictif, sec 7, off
> 0) for insn #4
> libbpf: sec '.relcgroup_skb/ingress': relo #1: insn #7 against 'is_allow_list'
> libbpf: prog 'sd_restrictif_i': found data map 1 (restrict.rodata, sec
> 5, off 0) for insn 7
> /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
>
> /* THIS FILE IS AUTOGENERATED BY BPFTOOL! */
> #ifndef __RESTRICT_IFACES_BPF_SKEL_H__
> #define __RESTRICT_IFACES_BPF_SKEL_H__
>
> #include <errno.h>
> #include <stdlib.h>
> #include <bpf/libbpf.h>
>
> struct restrict_ifaces_bpf {
>     struct bpf_object_skeleton *skeleton;
>     struct bpf_object *obj;
>     struct {
>         struct bpf_map *sd_restrictif;
>         struct bpf_map *rodata;
>     } maps;
>     struct {
>         struct bpf_program *sd_restrictif_e;
>         struct bpf_program *sd_restrictif_i;
>     } progs;
>     struct {
>         struct bpf_link *sd_restrictif_e;
>         struct bpf_link *sd_restrictif_i;
>     } links;
>     struct restrict_ifaces_bpf__rodata {
>         __u8 is_allow_list;
>     } *rodata;
>
> #ifdef __cplusplus
>     static inline struct restrict_ifaces_bpf *open(const struct
> bpf_object_open_opts *opts = nullptr);
>     static inline struct restrict_ifaces_bpf *open_and_load();
>     static inline int load(struct restrict_ifaces_bpf *skel);
>     static inline int attach(struct restrict_ifaces_bpf *skel);
>     static inline void detach(struct restrict_ifaces_bpf *skel);
>     static inline void destroy(struct restrict_ifaces_bpf *skel);
>     static inline const void *elf_bytes(size_t *sz);
> #endif /* __cplusplus */
> };
>
> static void
> restrict_ifaces_bpf__destroy(struct restrict_ifaces_bpf *obj)
> {
>     if (!obj)
>         return;
>     if (obj->skeleton)
>         bpf_object__destroy_skeleton(obj->skeleton);
>     free(obj);
> }
>
> static inline int
> restrict_ifaces_bpf__create_skeleton(struct restrict_ifaces_bpf *obj);
>
> static inline struct restrict_ifaces_bpf *
> restrict_ifaces_bpf__open_opts(const struct bpf_object_open_opts *opts)
> {
>     struct restrict_ifaces_bpf *obj;
>     int err;
>
>     obj = (struct restrict_ifaces_bpf *)calloc(1, sizeof(*obj));
>     if (!obj) {
>         errno = ENOMEM;
>         return NULL;
>     }
>
>     err = restrict_ifaces_bpf__create_skeleton(obj);
>     if (err)
>         goto err_out;
>
>     err = bpf_object__open_skeleton(obj->skeleton, opts);
>     if (err)
>         goto err_out;
>
>     return obj;
> err_out:
>     restrict_ifaces_bpf__destroy(obj);
>     errno = -err;
>     return NULL;
> }
>
> static inline struct restrict_ifaces_bpf *
> restrict_ifaces_bpf__open(void)
> {
>     return restrict_ifaces_bpf__open_opts(NULL);
> }
>
> static inline int
> restrict_ifaces_bpf__load(struct restrict_ifaces_bpf *obj)
> {
>     return bpf_object__load_skeleton(obj->skeleton);
> }
>
> static inline struct restrict_ifaces_bpf *
> restrict_ifaces_bpf__open_and_load(void)
> {
>     struct restrict_ifaces_bpf *obj;
>     int err;
>
>     obj = restrict_ifaces_bpf__open();
>     if (!obj)
>         return NULL;
>     err = restrict_ifaces_bpf__load(obj);
>     if (err) {
>         restrict_ifaces_bpf__destroy(obj);
>         errno = -err;
>         return NULL;
>     }
>     return obj;
> }
>
> static inline int
> restrict_ifaces_bpf__attach(struct restrict_ifaces_bpf *obj)
> {
>     return bpf_object__attach_skeleton(obj->skeleton);
> }
>
> static inline void
> restrict_ifaces_bpf__detach(struct restrict_ifaces_bpf *obj)
> {
>     return bpf_object__detach_skeleton(obj->skeleton);
> }
>
> static inline const void *restrict_ifaces_bpf__elf_bytes(size_t *sz);
>
> static inline int
> restrict_ifaces_bpf__create_skeleton(struct restrict_ifaces_bpf *obj)
> {
>     struct bpf_object_skeleton *s;
>     int err;
>
>     s = (struct bpf_object_skeleton *)calloc(1, sizeof(*s));
>     if (!s)    {
>         err = -ENOMEM;
>         goto err;
>     }
>
>     s->sz = sizeof(*s);
>     s->name = "restrict_ifaces_bpf";
>     s->obj = &obj->obj;
>
>     /* maps */
>     s->map_cnt = 2;
>     s->map_skel_sz = sizeof(*s->maps);
>     s->maps = (struct bpf_map_skeleton *)calloc(s->map_cnt, s->map_skel_sz);
>     if (!s->maps) {
>         err = -ENOMEM;
>         goto err;
>     }
>
>     s->maps[0].name = "sd_restrictif";
>     s->maps[0].map = &obj->maps.sd_restrictif;
>
>     s->maps[1].name = "restrict.rodata";
>     s->maps[1].map = &obj->maps.rodata;
>     s->maps[1].mmaped = (void **)&obj->rodata;
>
>     /* programs */
>     s->prog_cnt = 2;
>     s->prog_skel_sz = sizeof(*s->progs);
>     s->progs = (struct bpf_prog_skeleton *)calloc(s->prog_cnt, s->prog_skel_sz);
>     if (!s->progs) {
>         err = -ENOMEM;
>         goto err;
>     }
>
>     s->progs[0].name = "sd_restrictif_e";
>     s->progs[0].prog = &obj->progs.sd_restrictif_e;
>     s->progs[0].link = &obj->links.sd_restrictif_e;
>
>     s->progs[1].name = "sd_restrictif_i";
>     s->progs[1].prog = &obj->progs.sd_restrictif_i;
>     s->progs[1].link = &obj->links.sd_restrictif_i;
>
>     s->data = (void *)restrict_ifaces_bpf__elf_bytes(&s->data_sz);
>
>     obj->skeleton = s;
>     return 0;
> err:
>     bpf_object__destroy_skeleton(s);
>     return err;
> }
>
> static inline const void *restrict_ifaces_bpf__elf_bytes(size_t *sz)
> {
>     *sz = 4272;
>     return (const void *)"\
> \x7f\x45\x4c\x46\x02\x01\x01\0\0\0\0\0\0\0\0\0\x01\0\xf7\0\x01\0\0\0\0\0\0\0\0\
> \0\0\0\0\0\0\0\0\0\0\0\xb0\x0d\0\0\0\0\0\0\0\0\0\0\x40\0\0\0\0\0\x40\0\x0c\0\
> \x01\0\0\x2e\x73\x74\x72\x74\x61\x62\0\x2e\x73\x79\x6d\x74\x61\x62\0\x63\x67\
> \x72\x6f\x75\x70\x5f\x73\x6b\x62\x2f\x65\x67\x72\x65\x73\x73\0\x63\x67\x72\x6f\
> \x75\x70\x5f\x73\x6b\x62\x2f\x69\x6e\x67\x72\x65\x73\x73\0\x2e\x72\x6f\x64\x61\
> \x74\x61\0\x6c\x69\x63\x65\x6e\x73\x65\0\x2e\x6d\x61\x70\x73\0\x72\x65\x73\x74\
> \x72\x69\x63\x74\x2d\x69\x66\x61\x63\x65\x73\x2e\x62\x70\x66\x2e\x63\0\x4c\x42\
> \x42\x30\x5f\x32\0\x4c\x42\x42\x30\x5f\x33\0\x4c\x42\x42\x30\x5f\x34\0\x4c\x42\
> \x42\x31\x5f\x32\0\x4c\x42\x42\x31\x5f\x33\0\x4c\x42\x42\x31\x5f\x34\0\x5f\x6c\
> \x69\x63\x65\x6e\x73\x65\0\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\
> \x5f\x65\0\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\0\x69\x73\x5f\
> \x61\x6c\x6c\x6f\x77\x5f\x6c\x69\x73\x74\0\x73\x64\x5f\x72\x65\x73\x74\x72\x69\
> \x63\x74\x69\x66\x5f\x69\0\x2e\x72\x65\x6c\x63\x67\x72\x6f\x75\x70\x5f\x73\x6b\
> \x62\x2f\x65\x67\x72\x65\x73\x73\0\x2e\x72\x65\x6c\x63\x67\x72\x6f\x75\x70\x5f\
> \x73\x6b\x62\x2f\x69\x6e\x67\x72\x65\x73\x73\0\x2e\x42\x54\x46\0\x2e\x42\x54\
> \x46\x2e\x65\x78\x74\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
> \x4c\0\0\0\x04\0\xf1\xff\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x03\0\x03\0\0\
> \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x62\0\0\0\0\0\x03\0\x70\0\0\0\0\0\0\0\0\0\0\0\0\
> \0\0\0\x69\0\0\0\0\0\x03\0\x80\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x70\0\0\0\0\0\x03\
> \0\x88\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x03\0\x04\0\0\0\0\0\0\0\0\0\0\0\0\
> \0\0\0\0\0\x77\0\0\0\0\0\x04\0\x70\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x7e\0\0\0\0\0\
> \x04\0\x80\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x85\0\0\0\0\0\x04\0\x88\0\0\0\0\0\0\0\
> \0\0\0\0\0\0\0\0\x8c\0\0\0\x01\0\x06\0\0\0\0\0\0\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\
> \0\x03\0\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x95\0\0\0\x12\0\x03\0\0\0\0\0\0\
> \0\0\0\x98\0\0\0\0\0\0\0\xa5\0\0\0\x11\0\x07\0\0\0\0\0\0\0\0\0\x18\0\0\0\0\0\0\
> \0\xb3\0\0\0\x11\0\x05\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\xc1\0\0\0\x12\0\x04\
> \0\0\0\0\0\0\0\0\0\x98\0\0\0\0\0\0\0\x61\x11\x28\0\0\0\0\0\x63\x1a\xfc\xff\0\0\
> \0\0\xbf\xa2\0\0\0\0\0\0\x07\x02\0\0\xfc\xff\xff\xff\x18\x01\0\0\0\0\0\0\0\0\0\
> \0\0\0\0\0\x85\0\0\0\x01\0\0\0\x18\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x71\x11\0\0\
> \0\0\0\0\x15\x01\x03\0\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x15\0\x03\0\0\0\0\0\x05\0\
> \x03\0\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x15\0\x01\0\0\0\0\0\xb7\x01\0\0\0\0\0\0\
> \xbf\x10\0\0\0\0\0\0\x95\0\0\0\0\0\0\0\x61\x11\x28\0\0\0\0\0\x63\x1a\xfc\xff\0\
> \0\0\0\xbf\xa2\0\0\0\0\0\0\x07\x02\0\0\xfc\xff\xff\xff\x18\x01\0\0\0\0\0\0\0\0\
> \0\0\0\0\0\0\x85\0\0\0\x01\0\0\0\x18\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x71\x11\0\
> \0\0\0\0\0\x15\x01\x03\0\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x15\0\x03\0\0\0\0\0\x05\
> \0\x03\0\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x15\0\x01\0\0\0\0\0\xb7\x01\0\0\0\0\0\0\
> \xbf\x10\0\0\0\0\0\0\x95\0\0\0\0\0\0\0\0\x4c\x47\x50\x4c\x2d\x32\x2e\x31\x2d\
> \x6f\x72\x2d\x6c\x61\x74\x65\x72\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
> \0\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\x01\0\0\0\x0d\0\0\0\x38\0\0\0\0\0\0\0\x01\0\0\
> \0\x0e\0\0\0\x20\0\0\0\0\0\0\0\x01\0\0\0\x0d\0\0\0\x38\0\0\0\0\0\0\0\x01\0\0\0\
> \x0e\0\0\0\x9f\xeb\x01\0\x18\0\0\0\0\0\0\0\x10\x04\0\0\x10\x04\0\0\x9c\x03\0\0\
> \0\0\0\0\0\0\0\x02\x03\0\0\0\x01\0\0\0\0\0\0\x01\x04\0\0\0\x20\0\0\x01\0\0\0\0\
> \0\0\0\x03\0\0\0\0\x02\0\0\0\x04\0\0\0\x01\0\0\0\x05\0\0\0\0\0\0\x01\x04\0\0\0\
> \x20\0\0\0\0\0\0\0\0\0\0\x02\x06\0\0\0\x19\0\0\0\0\0\0\x08\x07\0\0\0\x1f\0\0\0\
> \0\0\0\x01\x04\0\0\0\x20\0\0\0\0\0\0\0\0\0\0\x02\x09\0\0\0\x2c\0\0\0\0\0\0\x08\
> \x0a\0\0\0\x31\0\0\0\0\0\0\x01\x01\0\0\0\x08\0\0\0\0\0\0\0\x03\0\0\x04\x18\0\0\
> \0\x3f\0\0\0\x01\0\0\0\0\0\0\0\x44\0\0\0\x05\0\0\0\x40\0\0\0\x48\0\0\0\x08\0\0\
> \0\x80\0\0\0\x4e\0\0\0\0\0\0\x0e\x0b\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\x02\x0e\0\0\
> \0\0\0\0\0\0\0\0\x0a\x0f\0\0\0\x5c\0\0\0\x21\0\0\x04\xc0\0\0\0\x66\0\0\0\x06\0\
> \0\0\0\0\0\0\x6a\0\0\0\x06\0\0\0\x20\0\0\0\x73\0\0\0\x06\0\0\0\x40\0\0\0\x78\0\
> \0\0\x06\0\0\0\x60\0\0\0\x86\0\0\0\x06\0\0\0\x80\0\0\0\x8f\0\0\0\x06\0\0\0\xa0\
> \0\0\0\x9c\0\0\0\x06\0\0\0\xc0\0\0\0\xa5\0\0\0\x06\0\0\0\xe0\0\0\0\xb0\0\0\0\
> \x06\0\0\0\0\x01\0\0\xb9\0\0\0\x06\0\0\0\x20\x01\0\0\xc9\0\0\0\x06\0\0\0\x40\
> \x01\0\0\xd1\0\0\0\x06\0\0\0\x60\x01\0\0\xda\0\0\0\x10\0\0\0\x80\x01\0\0\xdd\0\
> \0\0\x06\0\0\0\x20\x02\0\0\xe2\0\0\0\x06\0\0\0\x40\x02\0\0\xed\0\0\0\x06\0\0\0\
> \x60\x02\0\0\xf2\0\0\0\x06\0\0\0\x80\x02\0\0\xfb\0\0\0\x06\0\0\0\xa0\x02\0\0\
> \x03\x01\0\0\x06\0\0\0\xc0\x02\0\0\x0a\x01\0\0\x06\0\0\0\xe0\x02\0\0\x15\x01\0\
> \0\x06\0\0\0\0\x03\0\0\x1f\x01\0\0\x11\0\0\0\x20\x03\0\0\x2a\x01\0\0\x11\0\0\0\
> \xa0\x03\0\0\x34\x01\0\0\x06\0\0\0\x20\x04\0\0\x40\x01\0\0\x06\0\0\0\x40\x04\0\
> \0\x4b\x01\0\0\x06\0\0\0\x60\x04\0\0\0\0\0\0\x12\0\0\0\x80\x04\0\0\x55\x01\0\0\
> \x14\0\0\0\xc0\x04\0\0\x5c\x01\0\0\x06\0\0\0\0\x05\0\0\x65\x01\0\0\x06\0\0\0\
> \x20\x05\0\0\0\0\0\0\x16\0\0\0\x40\x05\0\0\x6e\x01\0\0\x06\0\0\0\x80\x05\0\0\
> \x77\x01\0\0\x14\0\0\0\xc0\x05\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x06\0\0\0\x04\0\0\
> \0\x05\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x06\0\0\0\x04\0\0\0\x04\0\0\0\0\0\0\0\
> \x01\0\0\x05\x08\0\0\0\x80\x01\0\0\x13\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x02\x22\0\0\
> \0\x8a\x01\0\0\0\0\0\x08\x15\0\0\0\x90\x01\0\0\0\0\0\x01\x08\0\0\0\x40\0\0\0\0\
> \0\0\0\x01\0\0\x05\x08\0\0\0\xa3\x01\0\0\x17\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x02\
> \x23\0\0\0\0\0\0\0\x01\0\0\x0d\x02\0\0\0\xa3\x01\0\0\x0d\0\0\0\xa6\x01\0\0\x01\
> \0\0\x0c\x18\0\0\0\xb6\x01\0\0\x01\0\0\x0c\x18\0\0\0\0\0\0\0\0\0\0\x0a\x1c\0\0\
> \0\0\0\0\0\0\0\0\x09\x09\0\0\0\xc6\x01\0\0\0\0\0\x0e\x1b\0\0\0\x01\0\0\0\0\0\0\
> \0\0\0\0\x0a\x1f\0\0\0\xd4\x01\0\0\0\0\0\x01\x01\0\0\0\x08\0\0\x01\0\0\0\0\0\0\
> \0\x03\0\0\0\0\x1e\0\0\0\x04\0\0\0\x12\0\0\0\xd9\x01\0\0\0\0\0\x0e\x20\0\0\0\0\
> \0\0\0\xe2\x01\0\0\0\0\0\x07\0\0\0\0\xf0\x01\0\0\0\0\0\x07\0\0\0\0\x61\x03\0\0\
> \x01\0\0\x0f\x01\0\0\0\x1d\0\0\0\0\0\0\0\x01\0\0\0\x69\x03\0\0\x01\0\0\x0f\x12\
> \0\0\0\x21\0\0\0\0\0\0\0\x12\0\0\0\x71\x03\0\0\x01\0\0\x0f\x18\0\0\0\x0c\0\0\0\
> \0\0\0\0\x18\0\0\0\0\x69\x6e\x74\0\x5f\x5f\x41\x52\x52\x41\x59\x5f\x53\x49\x5a\
> \x45\x5f\x54\x59\x50\x45\x5f\x5f\0\x5f\x5f\x75\x33\x32\0\x75\x6e\x73\x69\x67\
> \x6e\x65\x64\x20\x69\x6e\x74\0\x5f\x5f\x75\x38\0\x75\x6e\x73\x69\x67\x6e\x65\
> \x64\x20\x63\x68\x61\x72\0\x74\x79\x70\x65\0\x6b\x65\x79\0\x76\x61\x6c\x75\x65\
> \0\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\0\x5f\x5f\x73\x6b\x5f\
> \x62\x75\x66\x66\0\x6c\x65\x6e\0\x70\x6b\x74\x5f\x74\x79\x70\x65\0\x6d\x61\x72\
> \x6b\0\x71\x75\x65\x75\x65\x5f\x6d\x61\x70\x70\x69\x6e\x67\0\x70\x72\x6f\x74\
> \x6f\x63\x6f\x6c\0\x76\x6c\x61\x6e\x5f\x70\x72\x65\x73\x65\x6e\x74\0\x76\x6c\
> \x61\x6e\x5f\x74\x63\x69\0\x76\x6c\x61\x6e\x5f\x70\x72\x6f\x74\x6f\0\x70\x72\
> \x69\x6f\x72\x69\x74\x79\0\x69\x6e\x67\x72\x65\x73\x73\x5f\x69\x66\x69\x6e\x64\
> \x65\x78\0\x69\x66\x69\x6e\x64\x65\x78\0\x74\x63\x5f\x69\x6e\x64\x65\x78\0\x63\
> \x62\0\x68\x61\x73\x68\0\x74\x63\x5f\x63\x6c\x61\x73\x73\x69\x64\0\x64\x61\x74\
> \x61\0\x64\x61\x74\x61\x5f\x65\x6e\x64\0\x6e\x61\x70\x69\x5f\x69\x64\0\x66\x61\
> \x6d\x69\x6c\x79\0\x72\x65\x6d\x6f\x74\x65\x5f\x69\x70\x34\0\x6c\x6f\x63\x61\
> \x6c\x5f\x69\x70\x34\0\x72\x65\x6d\x6f\x74\x65\x5f\x69\x70\x36\0\x6c\x6f\x63\
> \x61\x6c\x5f\x69\x70\x36\0\x72\x65\x6d\x6f\x74\x65\x5f\x70\x6f\x72\x74\0\x6c\
> \x6f\x63\x61\x6c\x5f\x70\x6f\x72\x74\0\x64\x61\x74\x61\x5f\x6d\x65\x74\x61\0\
> \x74\x73\x74\x61\x6d\x70\0\x77\x69\x72\x65\x5f\x6c\x65\x6e\0\x67\x73\x6f\x5f\
> \x73\x65\x67\x73\0\x67\x73\x6f\x5f\x73\x69\x7a\x65\0\x68\x77\x74\x73\x74\x61\
> \x6d\x70\0\x66\x6c\x6f\x77\x5f\x6b\x65\x79\x73\0\x5f\x5f\x75\x36\x34\0\x75\x6e\
> \x73\x69\x67\x6e\x65\x64\x20\x6c\x6f\x6e\x67\x20\x6c\x6f\x6e\x67\0\x73\x6b\0\
> \x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\x5f\x65\0\x73\x64\x5f\x72\
> \x65\x73\x74\x72\x69\x63\x74\x69\x66\x5f\x69\0\x69\x73\x5f\x61\x6c\x6c\x6f\x77\
> \x5f\x6c\x69\x73\x74\0\x63\x68\x61\x72\0\x5f\x6c\x69\x63\x65\x6e\x73\x65\0\x62\
> \x70\x66\x5f\x66\x6c\x6f\x77\x5f\x6b\x65\x79\x73\0\x62\x70\x66\x5f\x73\x6f\x63\
> \x6b\0\x2f\x68\x6f\x6d\x65\x2f\x62\x75\x69\x6c\x64\x72\x6f\x6f\x74\x2f\x62\x75\
> \x69\x6c\x64\x72\x6f\x6f\x74\x2f\x6f\x75\x74\x70\x75\x74\x2f\x62\x75\x69\x6c\
> \x64\x2f\x73\x79\x73\x74\x65\x6d\x64\x2d\x63\x75\x73\x74\x6f\x6d\x2f\x73\x72\
> \x63\x2f\x63\x6f\x72\x65\x2f\x62\x70\x66\x2f\x72\x65\x73\x74\x72\x69\x63\x74\
> \x5f\x69\x66\x61\x63\x65\x73\x2f\x72\x65\x73\x74\x72\x69\x63\x74\x2d\x69\x66\
> \x61\x63\x65\x73\x2e\x62\x70\x66\x2e\x63\0\x20\x20\x20\x20\x20\x20\x20\x20\x69\
> \x66\x69\x6e\x64\x65\x78\x20\x3d\x20\x73\x6b\x2d\x3e\x69\x66\x69\x6e\x64\x65\
> \x78\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x6c\x6f\x6f\x6b\x75\x70\x5f\x72\x65\
> \x73\x75\x6c\x74\x20\x3d\x20\x62\x70\x66\x5f\x6d\x61\x70\x5f\x6c\x6f\x6f\x6b\
> \x75\x70\x5f\x65\x6c\x65\x6d\x28\x26\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\
> \x74\x69\x66\x2c\x20\x26\x69\x66\x69\x6e\x64\x65\x78\x29\x3b\0\x20\x20\x20\x20\
> \x20\x20\x20\x20\x69\x66\x20\x28\x69\x73\x5f\x61\x6c\x6c\x6f\x77\x5f\x6c\x69\
> \x73\x74\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
> \x20\x20\x69\x66\x20\x28\x6c\x6f\x6f\x6b\x75\x70\x5f\x72\x65\x73\x75\x6c\x74\
> \x29\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\
> \x20\x28\x21\x6c\x6f\x6f\x6b\x75\x70\x5f\x72\x65\x73\x75\x6c\x74\x29\0\x20\x20\
> \x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x72\x65\x73\x74\x72\x69\
> \x63\x74\x5f\x6e\x65\x74\x77\x6f\x72\x6b\x5f\x69\x6e\x74\x65\x72\x66\x61\x63\
> \x65\x73\x5f\x69\x6d\x70\x6c\x28\x73\x6b\x29\x3b\0\x2e\x72\x6f\x64\x61\x74\x61\
> \0\x6c\x69\x63\x65\x6e\x73\x65\0\x2e\x6d\x61\x70\x73\0\x63\x67\x72\x6f\x75\x70\
> \x5f\x73\x6b\x62\x2f\x65\x67\x72\x65\x73\x73\0\x63\x67\x72\x6f\x75\x70\x5f\x73\
> \x6b\x62\x2f\x69\x6e\x67\x72\x65\x73\x73\0\0\0\0\0\x9f\xeb\x01\0\x20\0\0\0\0\0\
> \0\0\x24\0\0\0\x24\0\0\0\x34\x01\0\0\x58\x01\0\0\0\0\0\0\x08\0\0\0\x77\x03\0\0\
> \x01\0\0\0\0\0\0\0\x19\0\0\0\x89\x03\0\0\x01\0\0\0\0\0\0\0\x1a\0\0\0\x10\0\0\0\
> \x77\x03\0\0\x09\0\0\0\0\0\0\0\xf9\x01\0\0\x62\x02\0\0\x17\x6c\0\0\x08\0\0\0\
> \xf9\x01\0\0\x62\x02\0\0\x11\x6c\0\0\x18\0\0\0\xf9\x01\0\0\0\0\0\0\0\0\0\0\x20\
> \0\0\0\xf9\x01\0\0\x81\x02\0\0\x19\x70\0\0\x38\0\0\0\xf9\x01\0\0\xc8\x02\0\0\
> \x0d\x74\0\0\x50\0\0\0\xf9\x01\0\0\xc8\x02\0\0\x0d\x74\0\0\x60\0\0\0\xf9\x01\0\
> \0\xe5\x02\0\0\x15\x7c\0\0\x78\0\0\0\xf9\x01\0\0\x08\x03\0\0\x15\x8c\0\0\x88\0\
> \0\0\xf9\x01\0\0\x2c\x03\0\0\x09\xb0\0\0\x89\x03\0\0\x09\0\0\0\0\0\0\0\xf9\x01\
> \0\0\x62\x02\0\0\x17\x6c\0\0\x08\0\0\0\xf9\x01\0\0\x62\x02\0\0\x11\x6c\0\0\x18\
> \0\0\0\xf9\x01\0\0\0\0\0\0\0\0\0\0\x20\0\0\0\xf9\x01\0\0\x81\x02\0\0\x19\x70\0\
> \0\x38\0\0\0\xf9\x01\0\0\xc8\x02\0\0\x0d\x74\0\0\x50\0\0\0\xf9\x01\0\0\xc8\x02\
> \0\0\x0d\x74\0\0\x60\0\0\0\xf9\x01\0\0\xe5\x02\0\0\x15\x7c\0\0\x78\0\0\0\xf9\
> \x01\0\0\x08\x03\0\0\x15\x8c\0\0\x88\0\0\0\xf9\x01\0\0\x2c\x03\0\0\x09\xc4\0\0\
> \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
> \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\x03\0\0\0\x20\0\0\
> \0\0\0\0\0\0\0\0\0\0\0\0\0\x40\0\0\0\0\0\0\0\x0c\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\
> \0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x09\0\0\0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
> \0\0\0\0\0\x50\x01\0\0\0\0\0\0\x80\x01\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\x08\0\0\0\
> \0\0\0\0\x18\0\0\0\0\0\0\0\x11\0\0\0\x01\0\0\0\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
> \0\xd0\x02\0\0\0\0\0\0\x98\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0\0\
> \0\0\0\0\0\0\x23\0\0\0\x01\0\0\0\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x68\x03\0\0\
> \0\0\0\0\x98\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
> \x36\0\0\0\x01\0\0\0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\x01\0\
> \0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x3e\0\0\0\x01\0\
> \0\0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x04\0\0\0\0\0\0\x12\0\0\0\0\0\0\0\0\
> \0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x46\0\0\0\x01\0\0\0\x03\0\0\0\
> \0\0\0\0\0\0\0\0\0\0\0\0\x18\x04\0\0\0\0\0\0\x18\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
> \x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xd1\0\0\0\x09\0\0\0\x40\0\0\0\0\0\0\0\0\0\0\
> \0\0\0\0\0\x30\x04\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\x02\0\0\0\x03\0\0\0\x08\0\0\0\
> \0\0\0\0\x10\0\0\0\0\0\0\0\xe7\0\0\0\x09\0\0\0\x40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
> \0\x50\x04\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\x02\0\0\0\x04\0\0\0\x08\0\0\0\0\0\0\0\
> \x10\0\0\0\0\0\0\0\xfe\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x70\x04\
> \0\0\0\0\0\0\xc4\x07\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\
> \0\0\x03\x01\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x38\x0c\0\0\0\0\0\0\
> \x78\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
> }
>
> #ifdef __cplusplus
> struct restrict_ifaces_bpf *restrict_ifaces_bpf::open(const struct
> bpf_object_open_opts *opts) { return
> restrict_ifaces_bpf__open_opts(opts); }
> struct restrict_ifaces_bpf *restrict_ifaces_bpf::open_and_load() {
> return restrict_ifaces_bpf__open_and_load(); }
> int restrict_ifaces_bpf::load(struct restrict_ifaces_bpf *skel) {
> return restrict_ifaces_bpf__load(skel); }
> int restrict_ifaces_bpf::attach(struct restrict_ifaces_bpf *skel) {
> return restrict_ifaces_bpf__attach(skel); }
> void restrict_ifaces_bpf::detach(struct restrict_ifaces_bpf *skel) {
> restrict_ifaces_bpf__detach(skel); }
> void restrict_ifaces_bpf::destroy(struct restrict_ifaces_bpf *skel) {
> restrict_ifaces_bpf__destroy(skel); }
> const void *restrict_ifaces_bpf::elf_bytes(size_t *sz) { return
> restrict_ifaces_bpf__elf_bytes(sz); }
> #endif /* __cplusplus */
>
> __attribute__((unused)) static void
> restrict_ifaces_bpf__assert(struct restrict_ifaces_bpf *s
> __attribute__((unused)))
> {
> #ifdef __cplusplus
> #define _Static_assert static_assert
> #endif
>     _Static_assert(sizeof(s->rodata->is_allow_list) == 1, "unexpected
> size of 'is_allow_list'");
> #ifdef __cplusplus
> #undef _Static_assert
> #endif
> }
>
> #endif /* __RESTRICT_IFACES_BPF_SKEL_H__ */
>
>>
>>
>> > Starting program:
>> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>> > --debug gen skeleton
>> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>> > [Thread debugging using libthread_db enabled]
>> > Using host libthread_db library "/usr/lib/libthread_db.so.1".
>> > libbpf: loading object 'restrict_ifaces_bpf' from buffer
>> > libbpf: elf: section(2) .symtab, size 336, link 1, flags 0, type=2
>> > libbpf: elf: section(3) .data, size 1, link 0, flags 3, type=1
>> > libbpf: elf: section(4) .bss, size 0, link 0, flags 3, type=8
>> > libbpf: elf: section(5) cgroup_skb/egress, size 184, link 0, flags 6, type=1
>> > libbpf: sec 'cgroup_skb/egress': found program 'sd_restrictif_e' at
>> > insn offset 0 (0 bytes), code size 23 insns (184 bytes)
>> > libbpf: elf: section(6) cgroup_skb/ingress, size 184, link 0, flags 6, type=1
>> > libbpf: sec 'cgroup_skb/ingress': found program 'sd_restrictif_i' at
>> > insn offset 0 (0 bytes), code size 23 insns (184 bytes)
>> > libbpf: elf: section(7) license, size 18, link 0, flags 2, type=1
>> > libbpf: license of restrict_ifaces_bpf is LGPL-2.1-or-later
>> > libbpf: elf: section(8) .maps, size 24, link 0, flags 3, type=1
>> > libbpf: elf: section(9) .comment, size 49, link 0, flags 30, type=1
>> > libbpf: elf: skipping unrecognized data section(9) .comment
>> > libbpf: elf: section(10) .relcgroup_skb/egress, size 32, link 2, flags
>> > 40, type=9
>> > libbpf: elf: section(11) .relcgroup_skb/ingress, size 32, link 2,
>> > flags 40, type=9
>> > libbpf: elf: section(12) .BTF, size 3606, link 0, flags 0, type=1
>> > libbpf: looking for externs among 14 symbols...
>> > libbpf: collected 0 externs total
>> > libbpf: map 'sd_restrictif': at sec_idx 8, offset 0.
>> > libbpf: map 'sd_restrictif': found type = 1.
>> > libbpf: map 'sd_restrictif': found key [12], sz = 4.
>> > libbpf: map 'sd_restrictif': found value [3], sz = 1.
>> >
>> > Program received signal SIGSEGV, Segmentation fault.
>> > 0x0000aaaaaab4fd2c in bpf_object.init_maps ()
>> > (gdb) bt
>> > #0  0x0000aaaaaab4fd2c in bpf_object.init_maps ()
>> > #1  0x0000aaaaaab52178 in bpf_object_open.part ()
>> > #2  0x0000aaaaaab544e8 in bpf_object.open_mem ()
>> > #3  0x0000aaaaaab2a58c in do_skeleton ()
>> > #4  0x0000aaaaaab1e204 in main ()
>> >
>> >>
>> >> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
>> >> index e89cc9c885b3..e3a6808f0bb6 100644
>> >> --- a/tools/lib/bpf/libbpf.c
>> >> +++ b/tools/lib/bpf/libbpf.c
>> >> @@ -1591,6 +1591,10 @@ static int bpf_object__init_global_data_maps(struct bpf_object *obj)
>> >>         for (sec_idx = 1; sec_idx < obj->efile.sec_cnt; sec_idx++) {
>> >>                 sec_desc = &obj->efile.secs[sec_idx];
>> >>
>> >> +                /* Skip empty sections.  */
>> >> +                if (sec_desc->data->d_size == 0)
>> >> +                  continue;
>> >> +
>> >>                 switch (sec_desc->sec_type) {
>> >>                 case SEC_DATA:
>> >>                         sec_name = elf_sec_name(obj, elf_sec_by_idx(obj, sec_idx));
>> >>
>> >> > GCC:
>> >> > $ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>> >> > --debug gen skeleton
>> >> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>> >> > libbpf: loading object 'restrict_ifaces_bpf' from buffer
>> >> > libbpf: elf: section(2) .symtab, size 336, link 1, flags 0, type=2
>> >> > libbpf: elf: section(3) .data, size 1, link 0, flags 3, type=1
>> >> > libbpf: elf: section(4) .bss, size 0, link 0, flags 3, type=8
>> >> > libbpf: elf: section(5) cgroup_skb/egress, size 184, link 0, flags 6, type=1
>> >> > libbpf: sec 'cgroup_skb/egress': found program 'sd_restrictif_e' at
>> >> > insn offset 0 (0 bytes), code size 23 insns (184 bytes)
>> >> > libbpf: elf: section(6) cgroup_skb/ingress, size 184, link 0, flags 6, type=1
>> >> > libbpf: sec 'cgroup_skb/ingress': found program 'sd_restrictif_i' at
>> >> > insn offset 0 (0 bytes), code size 23 insns (184 bytes)
>> >> > libbpf: elf: section(7) license, size 18, link 0, flags 2, type=1
>> >> > libbpf: license of restrict_ifaces_bpf is LGPL-2.1-or-later
>> >> > libbpf: elf: section(8) .maps, size 24, link 0, flags 3, type=1
>> >> > libbpf: elf: section(9) .comment, size 49, link 0, flags 30, type=1
>> >> > libbpf: elf: skipping unrecognized data section(9) .comment
>> >> > libbpf: elf: section(10) .relcgroup_skb/egress, size 32, link 2, flags
>> >> > 40, type=9
>> >> > libbpf: elf: section(11) .relcgroup_skb/ingress, size 32, link 2,
>> >> > flags 40, type=9
>> >> > libbpf: elf: section(12) .BTF, size 3606, link 0, flags 0, type=1
>> >> > libbpf: looking for externs among 14 symbols...
>> >> > libbpf: collected 0 externs total
>> >> > libbpf: map 'sd_restrictif': at sec_idx 8, offset 0.
>> >> > libbpf: map 'sd_restrictif': found type = 1.
>> >> > libbpf: map 'sd_restrictif': found key [12], sz = 4.
>> >> > libbpf: map 'sd_restrictif': found value [3], sz = 1.
>> >> > libbpf: map 'restrict.data' (global data): at sec_idx 3, offset 0, flags 400.
>> >> > libbpf: map 1 is "restrict.data"
>> >> > libbpf: map 'restrict.bss' (global data): at sec_idx 4, offset 0, flags 400.
>> >> > libbpf: failed to alloc map 'restrict.bss' content buffer: -22
>> >> > Error: failed to open BPF object file: Invalid argument
>> >> >
>> >> > LLVM:
>> >> > $ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>> >> > --debug gen skeleton restrict-ifaces.bpf.o
>> >> > libbpf: loading object 'restrict_ifaces_bpf' from buffer
>> >> > libbpf: elf: section(2) .symtab, size 384, link 1, flags 0, type=2
>> >> > libbpf: elf: section(3) cgroup_skb/egress, size 152, link 0, flags 6, type=1
>> >> > libbpf: sec 'cgroup_skb/egress': found program 'sd_restrictif_e' at
>> >> > insn offset 0 (0 bytes), code size 19 insns (152 bytes)
>> >> > libbpf: elf: section(4) cgroup_skb/ingress, size 152, link 0, flags 6, type=1
>> >> > libbpf: sec 'cgroup_skb/ingress': found program 'sd_restrictif_i' at
>> >> > insn offset 0 (0 bytes), code size 19 insns (152 bytes)
>> >> > libbpf: elf: section(5) .rodata, size 1, link 0, flags 2, type=1
>> >> > libbpf: elf: section(6) license, size 18, link 0, flags 2, type=1
>> >> > libbpf: license of restrict_ifaces_bpf is LGPL-2.1-or-later
>> >> > libbpf: elf: section(7) .maps, size 24, link 0, flags 3, type=1
>> >> > libbpf: elf: section(8) .relcgroup_skb/egress, size 32, link 2, flags 40, type=9
>> >> > libbpf: elf: section(9) .relcgroup_skb/ingress, size 32, link 2, flags
>> >> > 40, type=9
>> >> > libbpf: elf: section(10) .BTF, size 1988, link 0, flags 0, type=1
>> >> > libbpf: elf: section(11) .BTF.ext, size 376, link 0, flags 0, type=1
>> >> > libbpf: looking for externs among 16 symbols...
>> >> > libbpf: collected 0 externs total
>> >> > libbpf: map 'sd_restrictif': at sec_idx 7, offset 0.
>> >> > libbpf: map 'sd_restrictif': found type = 1.
>> >> > libbpf: map 'sd_restrictif': found key [6], sz = 4.
>> >> > libbpf: map 'sd_restrictif': found value [9], sz = 1.
>> >> > libbpf: map 'restrict.rodata' (global data): at sec_idx 5, offset 0, flags 480.
>> >> > libbpf: map 1 is "restrict.rodata"
>> >> > libbpf: sec '.relcgroup_skb/egress': collecting relocation for
>> >> > section(3) 'cgroup_skb/egress'
>> >> > libbpf: sec '.relcgroup_skb/egress': relo #0: insn #4 against 'sd_restrictif'
>> >> > libbpf: prog 'sd_restrictif_e': found map 0 (sd_restrictif, sec 7, off
>> >> > 0) for insn #4
>> >> > libbpf: sec '.relcgroup_skb/egress': relo #1: insn #7 against 'is_allow_list'
>> >> > libbpf: prog 'sd_restrictif_e': found data map 1 (restrict.rodata, sec
>> >> > 5, off 0) for insn 7
>> >> > libbpf: sec '.relcgroup_skb/ingress': collecting relocation for
>> >> > section(4) 'cgroup_skb/ingress'
>> >> > libbpf: sec '.relcgroup_skb/ingress': relo #0: insn #4 against 'sd_restrictif'
>> >> > libbpf: prog 'sd_restrictif_i': found map 0 (sd_restrictif, sec 7, off
>> >> > 0) for insn #4
>> >> > libbpf: sec '.relcgroup_skb/ingress': relo #1: insn #7 against 'is_allow_list'
>> >> > libbpf: prog 'sd_restrictif_i': found data map 1 (restrict.rodata, sec
>> >> > 5, off 0) for insn 7
>> >> >
>> >> >> >
>> >> >> > >>
>> >> >> > >> Looking at libbpf.c, it seems to me that this may be due of trying to
>> >> >> > >> mmap 0 bytes in `bpf_object__init_internal_map':
>> >> >> > >>
>> >> >> > >>         map->mmaped = mmap(NULL, bpf_map_mmap_sz(map), PROT_READ | PROT_WRITE,
>> >> >> > >>                            MAP_SHARED | MAP_ANONYMOUS, -1, 0);
>> >> >> > >>         if (map->mmaped == MAP_FAILED) {
>> >> >> > >>                 err = -errno;
>> >> >> > >>                 map->mmaped = NULL;
>> >> >> > >>                 pr_warn("failed to alloc map '%s' content buffer: %d\n",
>> >> >> > >>                         map->name, err);
>> >> >> > >>                 zfree(&map->real_name);
>> >> >> > >>                 zfree(&map->name);
>> >> >> > >>                 return err;
>> >> >> > >>         }
>> >> >> > >>
>> >> >> > >> I see no check for zero sized sections in
>> >> >> > >> bpf_object__init_global_data_maps.
>> >> >> > >>
>> >> >> > >> Is maybe GCC failing to allocate stuff in BSS that is supposed to be
>> >> >> > >> there?
>> >> >> > >>
>> >> >> > >> > Stripped file passed to gen skeleton:
>> >> >> > >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>> >> >> > >> > btf dump file
>> >> >> > >> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>> >> >> > >> > format raw
>> >> >> > >> > [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>> >> >> > >> > [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
>> >> >> > >> > [3] TYPEDEF '__u8' type_id=2
>> >> >> > >> > [4] CONST '(anon)' type_id=3
>> >> >> > >> > [5] VOLATILE '(anon)' type_id=4
>> >> >> > >> > [6] INT 'short int' size=2 bits_offset=0 nr_bits=16 encoding=SIGNED
>> >> >> > >> > [7] INT 'short unsigned int' size=2 bits_offset=0 nr_bits=16 encoding=(none)
>> >> >> > >> > [8] TYPEDEF '__u16' type_id=7
>> >> >> > >> > [9] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
>> >> >> > >> > [10] TYPEDEF '__s32' type_id=9
>> >> >> > >> > [11] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
>> >> >> > >> > [12] TYPEDEF '__u32' type_id=11
>> >> >> > >> > [13] INT 'long long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
>> >> >> > >> > [14] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64
>> >> >> > >> > encoding=(none)
>> >> >> > >> > [15] TYPEDEF '__u64' type_id=14
>> >> >> > >> > [16] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
>> >> >> > >> > [17] INT 'long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
>> >> >> > >> > [18] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>> >> >> > >> > [19] CONST '(anon)' type_id=18
>> >> >> > >> > [20] TYPEDEF '__be16' type_id=8
>> >> >> > >> > [21] TYPEDEF '__be32' type_id=12
>> >> >> > >> > [22] ENUM 'bpf_map_type' encoding=UNSIGNED size=4 vlen=31
>> >> >> > >> >     'BPF_MAP_TYPE_UNSPEC' val=0
>> >> >> > >> >     'BPF_MAP_TYPE_HASH' val=1
>> >> >> > >> >     'BPF_MAP_TYPE_ARRAY' val=2
>> >> >> > >> >     'BPF_MAP_TYPE_PROG_ARRAY' val=3
>> >> >> > >> >     'BPF_MAP_TYPE_PERF_EVENT_ARRAY' val=4
>> >> >> > >> >     'BPF_MAP_TYPE_PERCPU_HASH' val=5
>> >> >> > >> >     'BPF_MAP_TYPE_PERCPU_ARRAY' val=6
>> >> >> > >> >     'BPF_MAP_TYPE_STACK_TRACE' val=7
>> >> >> > >> >     'BPF_MAP_TYPE_CGROUP_ARRAY' val=8
>> >> >> > >> >     'BPF_MAP_TYPE_LRU_HASH' val=9
>> >> >> > >> >     'BPF_MAP_TYPE_LRU_PERCPU_HASH' val=10
>> >> >> > >> >     'BPF_MAP_TYPE_LPM_TRIE' val=11
>> >> >> > >> >     'BPF_MAP_TYPE_ARRAY_OF_MAPS' val=12
>> >> >> > >> >     'BPF_MAP_TYPE_HASH_OF_MAPS' val=13
>> >> >> > >> >     'BPF_MAP_TYPE_DEVMAP' val=14
>> >> >> > >> >     'BPF_MAP_TYPE_SOCKMAP' val=15
>> >> >> > >> >     'BPF_MAP_TYPE_CPUMAP' val=16
>> >> >> > >> >     'BPF_MAP_TYPE_XSKMAP' val=17
>> >> >> > >> >     'BPF_MAP_TYPE_SOCKHASH' val=18
>> >> >> > >> >     'BPF_MAP_TYPE_CGROUP_STORAGE' val=19
>> >> >> > >> >     'BPF_MAP_TYPE_REUSEPORT_SOCKARRAY' val=20
>> >> >> > >> >     'BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE' val=21
>> >> >> > >> >     'BPF_MAP_TYPE_QUEUE' val=22
>> >> >> > >> >     'BPF_MAP_TYPE_STACK' val=23
>> >> >> > >> >     'BPF_MAP_TYPE_SK_STORAGE' val=24
>> >> >> > >> >     'BPF_MAP_TYPE_DEVMAP_HASH' val=25
>> >> >> > >> >     'BPF_MAP_TYPE_STRUCT_OPS' val=26
>> >> >> > >> >     'BPF_MAP_TYPE_RINGBUF' val=27
>> >> >> > >> >     'BPF_MAP_TYPE_INODE_STORAGE' val=28
>> >> >> > >> >     'BPF_MAP_TYPE_TASK_STORAGE' val=29
>> >> >> > >> >     'BPF_MAP_TYPE_BLOOM_FILTER' val=30
>> >> >> > >> > [23] UNION '(anon)' size=8 vlen=1
>> >> >> > >> >     'flow_keys' type_id=29 bits_offset=0
>> >> >> > >> > [24] STRUCT 'bpf_flow_keys' size=56 vlen=13
>> >> >> > >> >     'nhoff' type_id=8 bits_offset=0
>> >> >> > >> >     'thoff' type_id=8 bits_offset=16
>> >> >> > >> >     'addr_proto' type_id=8 bits_offset=32
>> >> >> > >> >     'is_frag' type_id=3 bits_offset=48
>> >> >> > >> >     'is_first_frag' type_id=3 bits_offset=56
>> >> >> > >> >     'is_encap' type_id=3 bits_offset=64
>> >> >> > >> >     'ip_proto' type_id=3 bits_offset=72
>> >> >> > >> >     'n_proto' type_id=20 bits_offset=80
>> >> >> > >> >     'sport' type_id=20 bits_offset=96
>> >> >> > >> >     'dport' type_id=20 bits_offset=112
>> >> >> > >> >     '(anon)' type_id=25 bits_offset=128
>> >> >> > >> >     'flags' type_id=12 bits_offset=384
>> >> >> > >> >     'flow_label' type_id=21 bits_offset=416
>> >> >> > >> > [25] UNION '(anon)' size=32 vlen=2
>> >> >> > >> >     '(anon)' type_id=26 bits_offset=0
>> >> >> > >> >     '(anon)' type_id=27 bits_offset=0
>> >> >> > >> > [26] STRUCT '(anon)' size=8 vlen=2
>> >> >> > >> >     'ipv4_src' type_id=21 bits_offset=0
>> >> >> > >> >     'ipv4_dst' type_id=21 bits_offset=32
>> >> >> > >> > [27] STRUCT '(anon)' size=32 vlen=2
>> >> >> > >> >     'ipv6_src' type_id=28 bits_offset=0
>> >> >> > >> >     'ipv6_dst' type_id=28 bits_offset=128
>> >> >> > >> > [28] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=4
>> >> >> > >> > [29] PTR '(anon)' type_id=24
>> >> >> > >> > [30] UNION '(anon)' size=8 vlen=1
>> >> >> > >> >     'sk' type_id=32 bits_offset=0
>> >> >> > >> > [31] STRUCT 'bpf_sock' size=80 vlen=14
>> >> >> > >> >     'bound_dev_if' type_id=12 bits_offset=0
>> >> >> > >> >     'family' type_id=12 bits_offset=32
>> >> >> > >> >     'type' type_id=12 bits_offset=64
>> >> >> > >> >     'protocol' type_id=12 bits_offset=96
>> >> >> > >> >     'mark' type_id=12 bits_offset=128
>> >> >> > >> >     'priority' type_id=12 bits_offset=160
>> >> >> > >> >     'src_ip4' type_id=12 bits_offset=192
>> >> >> > >> >     'src_ip6' type_id=28 bits_offset=224
>> >> >> > >> >     'src_port' type_id=12 bits_offset=352
>> >> >> > >> >     'dst_port' type_id=20 bits_offset=384
>> >> >> > >> >     'dst_ip4' type_id=12 bits_offset=416
>> >> >> > >> >     'dst_ip6' type_id=28 bits_offset=448
>> >> >> > >> >     'state' type_id=12 bits_offset=576
>> >> >> > >> >     'rx_queue_mapping' type_id=10 bits_offset=608
>> >> >> > >> > [32] PTR '(anon)' type_id=31
>> >> >> > >> > [33] STRUCT '__sk_buff' size=192 vlen=33
>> >> >> > >> >     'len' type_id=12 bits_offset=0
>> >> >> > >> >     'pkt_type' type_id=12 bits_offset=32
>> >> >> > >> >     'mark' type_id=12 bits_offset=64
>> >> >> > >> >     'queue_mapping' type_id=12 bits_offset=96
>> >> >> > >> >     'protocol' type_id=12 bits_offset=128
>> >> >> > >> >     'vlan_present' type_id=12 bits_offset=160
>> >> >> > >> >     'vlan_tci' type_id=12 bits_offset=192
>> >> >> > >> >     'vlan_proto' type_id=12 bits_offset=224
>> >> >> > >> >     'priority' type_id=12 bits_offset=256
>> >> >> > >> >     'ingress_ifindex' type_id=12 bits_offset=288
>> >> >> > >> >     'ifindex' type_id=12 bits_offset=320
>> >> >> > >> >     'tc_index' type_id=12 bits_offset=352
>> >> >> > >> >     'cb' type_id=34 bits_offset=384
>> >> >> > >> >     'hash' type_id=12 bits_offset=544
>> >> >> > >> >     'tc_classid' type_id=12 bits_offset=576
>> >> >> > >> >     'data' type_id=12 bits_offset=608
>> >> >> > >> >     'data_end' type_id=12 bits_offset=640
>> >> >> > >> >     'napi_id' type_id=12 bits_offset=672
>> >> >> > >> >     'family' type_id=12 bits_offset=704
>> >> >> > >> >     'remote_ip4' type_id=12 bits_offset=736
>> >> >> > >> >     'local_ip4' type_id=12 bits_offset=768
>> >> >> > >> >     'remote_ip6' type_id=28 bits_offset=800
>> >> >> > >> >     'local_ip6' type_id=28 bits_offset=928
>> >> >> > >> >     'remote_port' type_id=12 bits_offset=1056
>> >> >> > >> >     'local_port' type_id=12 bits_offset=1088
>> >> >> > >> >     'data_meta' type_id=12 bits_offset=1120
>> >> >> > >> >     '(anon)' type_id=23 bits_offset=1152
>> >> >> > >> >     'tstamp' type_id=15 bits_offset=1216
>> >> >> > >> >     'wire_len' type_id=12 bits_offset=1280
>> >> >> > >> >     'gso_segs' type_id=12 bits_offset=1312
>> >> >> > >> >     '(anon)' type_id=30 bits_offset=1344
>> >> >> > >> >     'gso_size' type_id=12 bits_offset=1408
>> >> >> > >> >     'hwtstamp' type_id=15 bits_offset=1472
>> >> >> > >> > [34] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=5
>> >> >> > >> > [35] CONST '(anon)' type_id=33
>> >> >> > >> > [36] PTR '(anon)' type_id=0
>> >> >> > >> > [37] STRUCT '(anon)' size=24 vlen=3
>> >> >> > >> >     'type' type_id=39 bits_offset=0
>> >> >> > >> >     'key' type_id=40 bits_offset=64
>> >> >> > >> >     'value' type_id=41 bits_offset=128
>> >> >> > >> > [38] ARRAY '(anon)' type_id=9 index_type_id=16 nr_elems=1
>> >> >> > >> > [39] PTR '(anon)' type_id=38
>> >> >> > >> > [40] PTR '(anon)' type_id=12
>> >> >> > >> > [41] PTR '(anon)' type_id=3
>> >> >> > >> > [42] ARRAY '(anon)' type_id=19 index_type_id=16 nr_elems=18
>> >> >> > >> > [43] CONST '(anon)' type_id=42
>> >> >> > >> > [44] FUNC_PROTO '(anon)' ret_type_id=36 vlen=2
>> >> >> > >> >     '(anon)' type_id=36
>> >> >> > >> >     '(anon)' type_id=46
>> >> >> > >> > [45] CONST '(anon)' type_id=0
>> >> >> > >> > [46] PTR '(anon)' type_id=45
>> >> >> > >> > [47] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>> >> >> > >> >     'sk' type_id=48
>> >> >> > >> > [48] PTR '(anon)' type_id=35
>> >> >> > >> > [49] VAR '_license' type_id=43, linkage=static
>> >> >> > >> > [50] VAR 'is_allow_list' type_id=5, linkage=global
>> >> >> > >> > [51] VAR 'sd_restrictif' type_id=37, linkage=global
>> >> >> > >> > [52] FUNC 'sd_restrictif_i' type_id=47 linkage=global
>> >> >> > >> > [53] FUNC 'sd_restrictif_e' type_id=47 linkage=global
>> >> >> > >> > [54] FUNC 'restrict_network_interfaces_impl' type_id=47 linkage=static
>> >> >> > >> > [55] DATASEC '.data' size=1 vlen=1
>> >> >> > >> >     type_id=50 offset=0 size=1 (VAR 'is_allow_list')
>> >> >> > >> > [56] DATASEC 'license' size=18 vlen=1
>> >> >> > >> >     type_id=49 offset=0 size=18 (VAR '_license')
>> >> >> > >> > [57] DATASEC '.maps' size=24 vlen=1
>> >> >> > >> >     type_id=51 offset=0 size=24 (VAR 'sd_restrictif')
>> >> >> > >> >
>> >> >> > >> > File before being stripped using bpftool gen object:
>> >> >> > >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>> >> >> > >> > btf dump file
>> >> >> > >> >
>> >> >
>> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
>> >> >> > >> > format raw
>> >> >> > >> > [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>> >> >> > >> > [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
>> >> >> > >> > [3] TYPEDEF '__u8' type_id=2
>> >> >> > >> > [4] CONST '(anon)' type_id=3
>> >> >> > >> > [5] VOLATILE '(anon)' type_id=4
>> >> >> > >> > [6] INT 'short int' size=2 bits_offset=0 nr_bits=16 encoding=SIGNED
>> >> >> > >> > [7] INT 'short unsigned int' size=2 bits_offset=0 nr_bits=16 encoding=(none)
>> >> >> > >> > [8] TYPEDEF '__u16' type_id=7
>> >> >> > >> > [9] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
>> >> >> > >> > [10] TYPEDEF '__s32' type_id=9
>> >> >> > >> > [11] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
>> >> >> > >> > [12] TYPEDEF '__u32' type_id=11
>> >> >> > >> > [13] INT 'long long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
>> >> >> > >> > [14] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64
>> >> >> > >> > encoding=(none)
>> >> >> > >> > [15] TYPEDEF '__u64' type_id=14
>> >> >> > >> > [16] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
>> >> >> > >> > [17] INT 'long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
>> >> >> > >> > [18] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>> >> >> > >> > [19] CONST '(anon)' type_id=18
>> >> >> > >> > [20] TYPEDEF '__be16' type_id=8
>> >> >> > >> > [21] TYPEDEF '__be32' type_id=12
>> >> >> > >> > [22] ENUM 'bpf_map_type' encoding=UNSIGNED size=4 vlen=31
>> >> >> > >> >     'BPF_MAP_TYPE_UNSPEC' val=0
>> >> >> > >> >     'BPF_MAP_TYPE_HASH' val=1
>> >> >> > >> >     'BPF_MAP_TYPE_ARRAY' val=2
>> >> >> > >> >     'BPF_MAP_TYPE_PROG_ARRAY' val=3
>> >> >> > >> >     'BPF_MAP_TYPE_PERF_EVENT_ARRAY' val=4
>> >> >> > >> >     'BPF_MAP_TYPE_PERCPU_HASH' val=5
>> >> >> > >> >     'BPF_MAP_TYPE_PERCPU_ARRAY' val=6
>> >> >> > >> >     'BPF_MAP_TYPE_STACK_TRACE' val=7
>> >> >> > >> >     'BPF_MAP_TYPE_CGROUP_ARRAY' val=8
>> >> >> > >> >     'BPF_MAP_TYPE_LRU_HASH' val=9
>> >> >> > >> >     'BPF_MAP_TYPE_LRU_PERCPU_HASH' val=10
>> >> >> > >> >     'BPF_MAP_TYPE_LPM_TRIE' val=11
>> >> >> > >> >     'BPF_MAP_TYPE_ARRAY_OF_MAPS' val=12
>> >> >> > >> >     'BPF_MAP_TYPE_HASH_OF_MAPS' val=13
>> >> >> > >> >     'BPF_MAP_TYPE_DEVMAP' val=14
>> >> >> > >> >     'BPF_MAP_TYPE_SOCKMAP' val=15
>> >> >> > >> >     'BPF_MAP_TYPE_CPUMAP' val=16
>> >> >> > >> >     'BPF_MAP_TYPE_XSKMAP' val=17
>> >> >> > >> >     'BPF_MAP_TYPE_SOCKHASH' val=18
>> >> >> > >> >     'BPF_MAP_TYPE_CGROUP_STORAGE' val=19
>> >> >> > >> >     'BPF_MAP_TYPE_REUSEPORT_SOCKARRAY' val=20
>> >> >> > >> >     'BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE' val=21
>> >> >> > >> >     'BPF_MAP_TYPE_QUEUE' val=22
>> >> >> > >> >     'BPF_MAP_TYPE_STACK' val=23
>> >> >> > >> >     'BPF_MAP_TYPE_SK_STORAGE' val=24
>> >> >> > >> >     'BPF_MAP_TYPE_DEVMAP_HASH' val=25
>> >> >> > >> >     'BPF_MAP_TYPE_STRUCT_OPS' val=26
>> >> >> > >> >     'BPF_MAP_TYPE_RINGBUF' val=27
>> >> >> > >> >     'BPF_MAP_TYPE_INODE_STORAGE' val=28
>> >> >> > >> >     'BPF_MAP_TYPE_TASK_STORAGE' val=29
>> >> >> > >> >     'BPF_MAP_TYPE_BLOOM_FILTER' val=30
>> >> >> > >> > [23] UNION '(anon)' size=8 vlen=1
>> >> >> > >> >     'flow_keys' type_id=29 bits_offset=0
>> >> >> > >> > [24] STRUCT 'bpf_flow_keys' size=56 vlen=13
>> >> >> > >> >     'nhoff' type_id=8 bits_offset=0
>> >> >> > >> >     'thoff' type_id=8 bits_offset=16
>> >> >> > >> >     'addr_proto' type_id=8 bits_offset=32
>> >> >> > >> >     'is_frag' type_id=3 bits_offset=48
>> >> >> > >> >     'is_first_frag' type_id=3 bits_offset=56
>> >> >> > >> >     'is_encap' type_id=3 bits_offset=64
>> >> >> > >> >     'ip_proto' type_id=3 bits_offset=72
>> >> >> > >> >     'n_proto' type_id=20 bits_offset=80
>> >> >> > >> >     'sport' type_id=20 bits_offset=96
>> >> >> > >> >     'dport' type_id=20 bits_offset=112
>> >> >> > >> >     '(anon)' type_id=25 bits_offset=128
>> >> >> > >> >     'flags' type_id=12 bits_offset=384
>> >> >> > >> >     'flow_label' type_id=21 bits_offset=416
>> >> >> > >> > [25] UNION '(anon)' size=32 vlen=2
>> >> >> > >> >     '(anon)' type_id=26 bits_offset=0
>> >> >> > >> >     '(anon)' type_id=27 bits_offset=0
>> >> >> > >> > [26] STRUCT '(anon)' size=8 vlen=2
>> >> >> > >> >     'ipv4_src' type_id=21 bits_offset=0
>> >> >> > >> >     'ipv4_dst' type_id=21 bits_offset=32
>> >> >> > >> > [27] STRUCT '(anon)' size=32 vlen=2
>> >> >> > >> >     'ipv6_src' type_id=28 bits_offset=0
>> >> >> > >> >     'ipv6_dst' type_id=28 bits_offset=128
>> >> >> > >> > [28] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=4
>> >> >> > >> > [29] PTR '(anon)' type_id=24
>> >> >> > >> > [30] UNION '(anon)' size=8 vlen=1
>> >> >> > >> >     'sk' type_id=32 bits_offset=0
>> >> >> > >> > [31] STRUCT 'bpf_sock' size=80 vlen=14
>> >> >> > >> >     'bound_dev_if' type_id=12 bits_offset=0
>> >> >> > >> >     'family' type_id=12 bits_offset=32
>> >> >> > >> >     'type' type_id=12 bits_offset=64
>> >> >> > >> >     'protocol' type_id=12 bits_offset=96
>> >> >> > >> >     'mark' type_id=12 bits_offset=128
>> >> >> > >> >     'priority' type_id=12 bits_offset=160
>> >> >> > >> >     'src_ip4' type_id=12 bits_offset=192
>> >> >> > >> >     'src_ip6' type_id=28 bits_offset=224
>> >> >> > >> >     'src_port' type_id=12 bits_offset=352
>> >> >> > >> >     'dst_port' type_id=20 bits_offset=384
>> >> >> > >> >     'dst_ip4' type_id=12 bits_offset=416
>> >> >> > >> >     'dst_ip6' type_id=28 bits_offset=448
>> >> >> > >> >     'state' type_id=12 bits_offset=576
>> >> >> > >> >     'rx_queue_mapping' type_id=10 bits_offset=608
>> >> >> > >> > [32] PTR '(anon)' type_id=31
>> >> >> > >> > [33] STRUCT '__sk_buff' size=192 vlen=33
>> >> >> > >> >     'len' type_id=12 bits_offset=0
>> >> >> > >> >     'pkt_type' type_id=12 bits_offset=32
>> >> >> > >> >     'mark' type_id=12 bits_offset=64
>> >> >> > >> >     'queue_mapping' type_id=12 bits_offset=96
>> >> >> > >> >     'protocol' type_id=12 bits_offset=128
>> >> >> > >> >     'vlan_present' type_id=12 bits_offset=160
>> >> >> > >> >     'vlan_tci' type_id=12 bits_offset=192
>> >> >> > >> >     'vlan_proto' type_id=12 bits_offset=224
>> >> >> > >> >     'priority' type_id=12 bits_offset=256
>> >> >> > >> >     'ingress_ifindex' type_id=12 bits_offset=288
>> >> >> > >> >     'ifindex' type_id=12 bits_offset=320
>> >> >> > >> >     'tc_index' type_id=12 bits_offset=352
>> >> >> > >> >     'cb' type_id=34 bits_offset=384
>> >> >> > >> >     'hash' type_id=12 bits_offset=544
>> >> >> > >> >     'tc_classid' type_id=12 bits_offset=576
>> >> >> > >> >     'data' type_id=12 bits_offset=608
>> >> >> > >> >     'data_end' type_id=12 bits_offset=640
>> >> >> > >> >     'napi_id' type_id=12 bits_offset=672
>> >> >> > >> >     'family' type_id=12 bits_offset=704
>> >> >> > >> >     'remote_ip4' type_id=12 bits_offset=736
>> >> >> > >> >     'local_ip4' type_id=12 bits_offset=768
>> >> >> > >> >     'remote_ip6' type_id=28 bits_offset=800
>> >> >> > >> >     'local_ip6' type_id=28 bits_offset=928
>> >> >> > >> >     'remote_port' type_id=12 bits_offset=1056
>> >> >> > >> >     'local_port' type_id=12 bits_offset=1088
>> >> >> > >> >     'data_meta' type_id=12 bits_offset=1120
>> >> >> > >> >     '(anon)' type_id=23 bits_offset=1152
>> >> >> > >> >     'tstamp' type_id=15 bits_offset=1216
>> >> >> > >> >     'wire_len' type_id=12 bits_offset=1280
>> >> >> > >> >     'gso_segs' type_id=12 bits_offset=1312
>> >> >> > >> >     '(anon)' type_id=30 bits_offset=1344
>> >> >> > >> >     'gso_size' type_id=12 bits_offset=1408
>> >> >> > >> >     'hwtstamp' type_id=15 bits_offset=1472
>> >> >> > >> > [34] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=5
>> >> >> > >> > [35] CONST '(anon)' type_id=33
>> >> >> > >> > [36] PTR '(anon)' type_id=0
>> >> >> > >> > [37] STRUCT '(anon)' size=24 vlen=3
>> >> >> > >> >     'type' type_id=39 bits_offset=0
>> >> >> > >> >     'key' type_id=40 bits_offset=64
>> >> >> > >> >     'value' type_id=41 bits_offset=128
>> >> >> > >> > [38] ARRAY '(anon)' type_id=9 index_type_id=16 nr_elems=1
>> >> >> > >> > [39] PTR '(anon)' type_id=38
>> >> >> > >> > [40] PTR '(anon)' type_id=12
>> >> >> > >> > [41] PTR '(anon)' type_id=3
>> >> >> > >> > [42] ARRAY '(anon)' type_id=19 index_type_id=16 nr_elems=18
>> >> >> > >> > [43] CONST '(anon)' type_id=42
>> >> >> > >> > [44] FUNC_PROTO '(anon)' ret_type_id=36 vlen=2
>> >> >> > >> >     '(anon)' type_id=36
>> >> >> > >> >     '(anon)' type_id=46
>> >> >> > >> > [45] CONST '(anon)' type_id=0
>> >> >> > >> > [46] PTR '(anon)' type_id=45
>> >> >> > >> > [47] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>> >> >> > >> >     'sk' type_id=48
>> >> >> > >> > [48] PTR '(anon)' type_id=35
>> >> >> > >> > [49] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>> >> >> > >> >     'sk' type_id=48
>> >> >> > >> > [50] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>> >> >> > >> >     'sk' type_id=48
>> >> >> > >> > [51] VAR '_license' type_id=43, linkage=static
>> >> >> > >> > [52] VAR 'is_allow_list' type_id=5, linkage=global
>> >> >> > >> > [53] VAR 'sd_restrictif' type_id=37, linkage=global
>> >> >> > >> > [54] FUNC 'bpf_map_lookup_elem' type_id=44 linkage=global
>> >> >> > >> > [55] FUNC 'sd_restrictif_i' type_id=47 linkage=global
>> >> >> > >> > [56] FUNC 'sd_restrictif_e' type_id=49 linkage=global
>> >> >> > >> > [57] FUNC 'restrict_network_interfaces_impl' type_id=50 linkage=static
>> >> >> > >> > [58] DATASEC 'license' size=0 vlen=1
>> >> >> > >> >     type_id=51 offset=0 size=18 (VAR '_license')
>> >> >> > >> > [59] DATASEC '.maps' size=0 vlen=1
>> >> >> > >> >     type_id=53 offset=0 size=24 (VAR 'sd_restrictif')
>> >> >> > >> > [60] DATASEC '.data' size=0 vlen=1
>> >> >> > >> >     type_id=52 offset=0 size=1 (VAR 'is_allow_list')
>> >> >> > >> >
>> >> >> > >> >>
>> >> >> > >> >> >> GCC is wrong, clearly. This function is global ([0]) and libbpf
>> >> >> > >> >> >> expects it to be marked as such in BTF.
>> >> >> > >> >> >>
>> >> >> > >> >> >>
>> >> >> > >> >
>> >> >
>> > https://github.com/systemd/systemd/blob/main/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.c#L42-L50
>> >> >> > >> >> >>
>> >> >> > >> >> >>
>> >> >> > >> >> >>> GCC:
>> >> >> > >> >> >>>
>> >> >> > >> >> >>> [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>> >> >> > >> >> >>> [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
>> >> >> > >> >> >>> [3] TYPEDEF '__u8' type_id=2
>> >> >> > >> >> >>> [4] CONST '(anon)' type_id=3
>> >> >> > >> >> >>
>> >> >> > >> >> >> [...]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-07-10 13:06                           ` Jose E. Marchesi
@ 2022-07-10 19:49                             ` Jose E. Marchesi
  2022-07-10 20:22                               ` Jose E. Marchesi
  0 siblings, 1 reply; 38+ messages in thread
From: Jose E. Marchesi @ 2022-07-10 19:49 UTC (permalink / raw)
  To: James Hilliard; +Cc: Andrii Nakryiko, bpf, david.faust


>> On Sun, Jul 10, 2022 at 3:38 AM Jose E. Marchesi
>> <jose.marchesi@oracle.com> wrote:
>>>
>>>
>>> > On Sat, Jul 9, 2022 at 4:41 PM Jose E. Marchesi
>>> > <jose.marchesi@oracle.com> wrote:
>>> >>
>>> >>
>>> >> > On Sat, Jul 9, 2022 at 2:32 PM James Hilliard <james.hilliard1@gmail.com> wrote:
>>> >> >>
>>> >> >> On Sat, Jul 9, 2022 at 2:21 PM Jose E. Marchesi
>>> >> >> <jose.marchesi@oracle.com> wrote:
>>> >> >> >
>>> >> >> >
>>> >> >> > > On Sat, Jul 9, 2022 at 11:24 AM Jose E. Marchesi
>>> >> >> > > <jose.marchesi@oracle.com> wrote:
>>> >> >> > >>
>>> >> >> > >>
>>> >> >> > >> > On Fri, Jul 8, 2022 at 12:33 PM Jose E. Marchesi
>>> >> >> > >> > <jose.marchesi@oracle.com> wrote:
>>> >> >> > >> >>
>>> >> >> > >> >>
>>> >> >> > >> >> >> On Wed, Jul 6, 2022 at 10:13 AM James Hilliard
>>> >> >> > >> >> >> <james.hilliard1@gmail.com> wrote:
>>> >> >> > >> >> >>>
>>> >> >> > >> >> >>> Note I'm testing with the following patches:
>>> >> >> > >> >> >>>
> https://lore.kernel.org/bpf/20220706111839.1247911-1-james.hilliard1@gmail.com/
>>> >> >> > >> >> >>>
> https://lore.kernel.org/bpf/20220706140623.2917858-1-james.hilliard1@gmail.com/
>>> >> >> > >> >> >>>
>>> >> >> > >> >> >>> It would appear there's some compatibility issues with bpftool gen and
>>> >> >> > >> >> >>> GCC, not sure what side though is wrong here:
>>> >> >> > >> >> >>> /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>>> >> >> > >> >> >>> gen object src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>>> >> >> > >> >> >>> src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
>>> >> >> > >> >> >>> libbpf: failed to find BTF info for global/extern symbol 'sd_restrictif_i'
>>> >> >> > >> >> >>> Error: failed to link
>>> >> >> > >> >> >>> 'src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o':
>>> >> >> > >> >> >>> Unknown error -2 (-2)
>>> >> >> > >> >> >>>
>>> >> >> > >> >> >>> Relevant difference seems to be this:
>>> >> >> > >> >> >>> GCC:
>>> >> >> > >> >> >>> [55] FUNC 'sd_restrictif_i' type_id=47 linkage=static
>>> >> >> > >> >> >>> Clang:
>>> >> >> > >> >> >>> [27] FUNC 'sd_restrictif_i' type_id=26 linkage=global
>>> >> >> > >> >> >
>>> >> >> > >> >> > For functions GCC generates a BTF_KIND_FUNC entry, which has no linkage
>>> >> >> > >> >> > information, or so we thought: I just looked at bpftool/btf.c and I
>>> >> >> > >> >> > found the linkage info for function types is expected to be encoded in
>>> >> >> > >> >> > the vlen field of BTF_KIND_FUNC entries (why not adding a btf_func
>>> >> >> > >> >> > instead???) which is surprising to say the least.
>>> >> >> > >> >> >
>>> >> >> > >> >> > We are changing GCC to encode the linkage info in vlen for these types.
>>> >> >> > >> >> > Thanks for reporting this.
>>> >> >> > >> >>
>>> >> >> > >> >> Patch sent to GCC upstream:
>>> >> >> > >> >> https://gcc.gnu.org/pipermail/gcc-patches/2022-July/598090.html
>>> >> >> > >> >
>>> >> >> > >> > I applied that patch on top of GCC 12.1.0 and it appears to fix the
>>> >> >> > >> > bpftool gen object bug.
>>> >> >> > >> >
>>> >> >> > >> > I am however now hitting a different error during skeleton generation:
>>> >> >> > >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>>> >> >> > >> > gen skeleton src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>>> >> >> > >> > libbpf: elf: skipping unrecognized data section(9) .comment
>>> >> >> > >> > libbpf: failed to alloc map 'restrict.bss' content buffer: -22
>>> >> >> > >> > Error: failed to open BPF object file: Invalid argument
>>> >> >> > >>
>>> >> >> > >> What is the size of the .bss section in the object file?  Try with:
>>> >> >> > >>
>>> >> >> > >> $ size restrict-ifaces.bpf.o
>>> >> >> > >
>>> >> >> > > $ size
>>> >> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>>> >> >> > >    text       data        bss        dec        hex    filename
>>> >> >> > >     386         25          0        411        19b
>>> >> >> > >
> output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>>> >> >> >
>>> >> >> > Right, so the .bss section is empty.  I see a `const volatile unsigned
>>> >> >> > char is_allow_list = 0;' in restrict-ifaces.bpf.c, but that goes to
>>> >> >> > .data and not to .bss, as expected.
>>> >> >> >
>>> >> >> > If you build restrict-ifaces.bpf.o with LLVM, is the bss still empty?  I
>>> >> >> > don't think the code in libbpf.c even checks for this eventuality...
>>> >> >>
>>> >> >> LLVM version(which skeleton generation works with):
>>> >> >> $ size restrict-ifaces.bpf.o
>>> >> >>    text       data        bss        dec        hex    filename
>>> >> >>     323         24          0        347        15b    restrict-ifaces.bpf.o
>>> >> >>
>>> >> >> $ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>>> >> >> btf dump file restrict-ifaces.bpf.o format raw
>>> >> >> [1] PTR '(anon)' type_id=3
>>> >> >> [2] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
>>> >> >> [3] ARRAY '(anon)' type_id=2 index_type_id=4 nr_elems=1
>>> >> >> [4] INT '__ARRAY_SIZE_TYPE__' size=4 bits_offset=0 nr_bits=32 encoding=(none)
>>> >> >> [5] PTR '(anon)' type_id=6
>>> >> >> [6] TYPEDEF '__u32' type_id=7
>>> >> >> [7] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
>>> >> >> [8] PTR '(anon)' type_id=9
>>> >> >> [9] TYPEDEF '__u8' type_id=10
>>> >> >> [10] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=(none)
>>> >> >> [11] STRUCT '(anon)' size=24 vlen=3
>>> >> >>     'type' type_id=1 bits_offset=0
>>> >> >>     'key' type_id=5 bits_offset=64
>>> >> >>     'value' type_id=8 bits_offset=128
>>> >> >> [12] VAR 'sd_restrictif' type_id=11, linkage=global
>>> >> >> [13] PTR '(anon)' type_id=14
>>> >> >> [14] CONST '(anon)' type_id=15
>>> >> >> [15] STRUCT '__sk_buff' size=192 vlen=33
>>> >> >>     'len' type_id=6 bits_offset=0
>>> >> >>     'pkt_type' type_id=6 bits_offset=32
>>> >> >>     'mark' type_id=6 bits_offset=64
>>> >> >>     'queue_mapping' type_id=6 bits_offset=96
>>> >> >>     'protocol' type_id=6 bits_offset=128
>>> >> >>     'vlan_present' type_id=6 bits_offset=160
>>> >> >>     'vlan_tci' type_id=6 bits_offset=192
>>> >> >>     'vlan_proto' type_id=6 bits_offset=224
>>> >> >>     'priority' type_id=6 bits_offset=256
>>> >> >>     'ingress_ifindex' type_id=6 bits_offset=288
>>> >> >>     'ifindex' type_id=6 bits_offset=320
>>> >> >>     'tc_index' type_id=6 bits_offset=352
>>> >> >>     'cb' type_id=16 bits_offset=384
>>> >> >>     'hash' type_id=6 bits_offset=544
>>> >> >>     'tc_classid' type_id=6 bits_offset=576
>>> >> >>     'data' type_id=6 bits_offset=608
>>> >> >>     'data_end' type_id=6 bits_offset=640
>>> >> >>     'napi_id' type_id=6 bits_offset=672
>>> >> >>     'family' type_id=6 bits_offset=704
>>> >> >>     'remote_ip4' type_id=6 bits_offset=736
>>> >> >>     'local_ip4' type_id=6 bits_offset=768
>>> >> >>     'remote_ip6' type_id=17 bits_offset=800
>>> >> >>     'local_ip6' type_id=17 bits_offset=928
>>> >> >>     'remote_port' type_id=6 bits_offset=1056
>>> >> >>     'local_port' type_id=6 bits_offset=1088
>>> >> >>     'data_meta' type_id=6 bits_offset=1120
>>> >> >>     '(anon)' type_id=18 bits_offset=1152
>>> >> >>     'tstamp' type_id=20 bits_offset=1216
>>> >> >>     'wire_len' type_id=6 bits_offset=1280
>>> >> >>     'gso_segs' type_id=6 bits_offset=1312
>>> >> >>     '(anon)' type_id=22 bits_offset=1344
>>> >> >>     'gso_size' type_id=6 bits_offset=1408
>>> >> >>     'hwtstamp' type_id=20 bits_offset=1472
>>> >> >> [16] ARRAY '(anon)' type_id=6 index_type_id=4 nr_elems=5
>>> >> >> [17] ARRAY '(anon)' type_id=6 index_type_id=4 nr_elems=4
>>> >> >> [18] UNION '(anon)' size=8 vlen=1
>>> >> >>     'flow_keys' type_id=19 bits_offset=0
>>> >> >> [19] PTR '(anon)' type_id=34
>>> >> >> [20] TYPEDEF '__u64' type_id=21
>>> >> >> [21] INT 'unsigned long long' size=8 bits_offset=0 nr_bits=64 encoding=(none)
>>> >> >> [22] UNION '(anon)' size=8 vlen=1
>>> >> >>     'sk' type_id=23 bits_offset=0
>>> >> >> [23] PTR '(anon)' type_id=35
>>> >> >> [24] FUNC_PROTO '(anon)' ret_type_id=2 vlen=1
>>> >> >>     'sk' type_id=13
>>> >> >> [25] FUNC 'sd_restrictif_e' type_id=24 linkage=global
>>> >> >> [26] FUNC 'sd_restrictif_i' type_id=24 linkage=global
>>> >> >> [27] CONST '(anon)' type_id=28
>>> >> >> [28] VOLATILE '(anon)' type_id=9
>>> >> >> [29] VAR 'is_allow_list' type_id=27, linkage=global
>>> >> >> [30] CONST '(anon)' type_id=31
>>> >> >> [31] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=SIGNED
>>> >> >> [32] ARRAY '(anon)' type_id=30 index_type_id=4 nr_elems=18
>>> >> >> [33] VAR '_license' type_id=32, linkage=static
>>> >> >> [34] FWD 'bpf_flow_keys' fwd_kind=struct
>>> >> >> [35] FWD 'bpf_sock' fwd_kind=struct
>>> >> >> [36] DATASEC '.rodata' size=1 vlen=1
>>> >> >>     type_id=29 offset=0 size=1 (VAR 'is_allow_list')
>>> >> >> [37] DATASEC 'license' size=18 vlen=1
>>> >> >>     type_id=33 offset=0 size=18 (VAR '_license')
>>> >> >> [38] DATASEC '.maps' size=24 vlen=1
>>> >> >>     type_id=12 offset=0 size=24 (VAR 'sd_restrictif')
>>> >> >>
>>> >> >
>>> >> > Skeleton generation debug output for GCC(failing) and LLVM(working)
>>> >> > which may be helpful:
>>> >>
>>> >> Indeed it was helpful :)
>>> >>
>>> >> The GNU assembler generates an empty .bss section.  This is a well
>>> >> established behavior in GAS that happens in all supported targets.
>>> >>
>>> >> The LLVM assembler doesn't generate an empty .bss section.
>>> >>
>>> >> bpftool chokes on the empty .bss section.
>>> >>
>>> >> In this case I would suggest to fix bpf_object__init_global_data_maps in
>>> >> order to skip empty sections.
>>> >>
>>> >> Something like this:
>>> >
>>> > Hmm, that seems to segfault:
>>>
>>> Yes, I see in bpf_object__elf_collect that sec_desc->data is not
>>> initialized when a section is not recognized.  In this case, this
>>> happens with .comment.
>>>
>>> All right then:
>>>
>>> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
>>> index e89cc9c885b3..887b78780099 100644
>>> --- a/tools/lib/bpf/libbpf.c
>>> +++ b/tools/lib/bpf/libbpf.c
>>> @@ -1591,6 +1591,10 @@ static int bpf_object__init_global_data_maps(struct bpf_object *obj)
>>>         for (sec_idx = 1; sec_idx < obj->efile.sec_cnt; sec_idx++) {
>>>                 sec_desc = &obj->efile.secs[sec_idx];
>>>
>>> +                /* Skip recognized sections with size 0.  */
>>> +                if (sec_desc->data && sec_desc->data->d_size == 0)
>>> +                  continue;
>>> +
>>>                 switch (sec_desc->sec_type) {
>>>                 case SEC_DATA:
>>>                         sec_name = elf_sec_name(obj, elf_sec_by_idx(obj, sec_idx));
>>
>> Ok, skeleton is now getting generated successfully, however it differs from the
>> clang version so there's a build error when we include/use the header:
>> ../src/core/restrict-ifaces.c: In function ‘prepare_restrict_ifaces_bpf’:
>> ../src/core/restrict-ifaces.c:45:14: error: ‘struct
>> restrict_ifaces_bpf’ has no member named ‘rodata’; did you mean
>> ‘data’?
>>    45 |         obj->rodata->is_allow_list = is_allow_list;
>>       |              ^~~~~~
>>       |              data
>>
>> The issue appears to be that clang generates "rodata" members in
>> restrict_ifaces_bpf while with gcc we get "data" members instead.
>
> This is because the BPF GCC port is putting the
>
>   const volatile unsigned char is_allow_list = 0;
>
> in a .data section instead of .rodata, due to the `volatile'.  The
> x86_64 GCC seems to use .rodata.
>
> Looking at why the PBF port does this...

So, turns out GCC puts zero-initialized `const volatile' variables in
.data sections (and not .rodata) in all the targets I have tried, like
x86_64 and aarch64.

So this is a LLVM and GCC divergence :/

>> Differences below:
>>
>> GCC:
>> $ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>> --debug gen skeleton
>> output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>> libbpf: loading object 'restrict_ifaces_bpf' from buffer
>> libbpf: elf: section(2) .symtab, size 336, link 1, flags 0, type=2
>> libbpf: elf: section(3) .data, size 1, link 0, flags 3, type=1
>> libbpf: elf: section(4) .bss, size 0, link 0, flags 3, type=8
>> libbpf: elf: section(5) cgroup_skb/egress, size 184, link 0, flags 6, type=1
>> libbpf: sec 'cgroup_skb/egress': found program 'sd_restrictif_e' at
>> insn offset 0 (0 bytes), code size 23 insns (184 bytes)
>> libbpf: elf: section(6) cgroup_skb/ingress, size 184, link 0, flags 6, type=1
>> libbpf: sec 'cgroup_skb/ingress': found program 'sd_restrictif_i' at
>> insn offset 0 (0 bytes), code size 23 insns (184 bytes)
>> libbpf: elf: section(7) license, size 18, link 0, flags 2, type=1
>> libbpf: license of restrict_ifaces_bpf is LGPL-2.1-or-later
>> libbpf: elf: section(8) .maps, size 24, link 0, flags 3, type=1
>> libbpf: elf: section(9) .comment, size 49, link 0, flags 30, type=1
>> libbpf: elf: skipping unrecognized data section(9) .comment
>> libbpf: elf: section(10) .relcgroup_skb/egress, size 32, link 2, flags
>> 40, type=9
>> libbpf: elf: section(11) .relcgroup_skb/ingress, size 32, link 2,
>> flags 40, type=9
>> libbpf: elf: section(12) .BTF, size 3606, link 0, flags 0, type=1
>> libbpf: looking for externs among 14 symbols...
>> libbpf: collected 0 externs total
>> libbpf: map 'sd_restrictif': at sec_idx 8, offset 0.
>> libbpf: map 'sd_restrictif': found type = 1.
>> libbpf: map 'sd_restrictif': found key [12], sz = 4.
>> libbpf: map 'sd_restrictif': found value [3], sz = 1.
>> libbpf: map 'restrict.data' (global data): at sec_idx 3, offset 0, flags 400.
>> libbpf: map 1 is "restrict.data"
>> libbpf: sec '.relcgroup_skb/egress': collecting relocation for
>> section(5) 'cgroup_skb/egress'
>> libbpf: sec '.relcgroup_skb/egress': relo #0: insn #4 against 'sd_restrictif'
>> libbpf: prog 'sd_restrictif_e': found map 0 (sd_restrictif, sec 8, off
>> 0) for insn #4
>> libbpf: sec '.relcgroup_skb/egress': relo #1: insn #7 against 'is_allow_list'
>> libbpf: prog 'sd_restrictif_e': found data map 1 (restrict.data, sec
>> 3, off 0) for insn 7
>> libbpf: sec '.relcgroup_skb/ingress': collecting relocation for
>> section(6) 'cgroup_skb/ingress'
>> libbpf: sec '.relcgroup_skb/ingress': relo #0: insn #4 against 'sd_restrictif'
>> libbpf: prog 'sd_restrictif_i': found map 0 (sd_restrictif, sec 8, off
>> 0) for insn #4
>> libbpf: sec '.relcgroup_skb/ingress': relo #1: insn #7 against 'is_allow_list'
>> libbpf: prog 'sd_restrictif_i': found data map 1 (restrict.data, sec
>> 3, off 0) for insn 7
>> /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
>>
>> /* THIS FILE IS AUTOGENERATED BY BPFTOOL! */
>> #ifndef __RESTRICT_IFACES_BPF_SKEL_H__
>> #define __RESTRICT_IFACES_BPF_SKEL_H__
>>
>> #include <errno.h>
>> #include <stdlib.h>
>> #include <bpf/libbpf.h>
>>
>> struct restrict_ifaces_bpf {
>>     struct bpf_object_skeleton *skeleton;
>>     struct bpf_object *obj;
>>     struct {
>>         struct bpf_map *sd_restrictif;
>>         struct bpf_map *data;
>>     } maps;
>>     struct {
>>         struct bpf_program *sd_restrictif_e;
>>         struct bpf_program *sd_restrictif_i;
>>     } progs;
>>     struct {
>>         struct bpf_link *sd_restrictif_e;
>>         struct bpf_link *sd_restrictif_i;
>>     } links;
>>     struct restrict_ifaces_bpf__data {
>>         __u8 is_allow_list;
>>     } *data;
>>
>> #ifdef __cplusplus
>>     static inline struct restrict_ifaces_bpf *open(const struct
>> bpf_object_open_opts *opts = nullptr);
>>     static inline struct restrict_ifaces_bpf *open_and_load();
>>     static inline int load(struct restrict_ifaces_bpf *skel);
>>     static inline int attach(struct restrict_ifaces_bpf *skel);
>>     static inline void detach(struct restrict_ifaces_bpf *skel);
>>     static inline void destroy(struct restrict_ifaces_bpf *skel);
>>     static inline const void *elf_bytes(size_t *sz);
>> #endif /* __cplusplus */
>> };
>>
>> static void
>> restrict_ifaces_bpf__destroy(struct restrict_ifaces_bpf *obj)
>> {
>>     if (!obj)
>>         return;
>>     if (obj->skeleton)
>>         bpf_object__destroy_skeleton(obj->skeleton);
>>     free(obj);
>> }
>>
>> static inline int
>> restrict_ifaces_bpf__create_skeleton(struct restrict_ifaces_bpf *obj);
>>
>> static inline struct restrict_ifaces_bpf *
>> restrict_ifaces_bpf__open_opts(const struct bpf_object_open_opts *opts)
>> {
>>     struct restrict_ifaces_bpf *obj;
>>     int err;
>>
>>     obj = (struct restrict_ifaces_bpf *)calloc(1, sizeof(*obj));
>>     if (!obj) {
>>         errno = ENOMEM;
>>         return NULL;
>>     }
>>
>>     err = restrict_ifaces_bpf__create_skeleton(obj);
>>     if (err)
>>         goto err_out;
>>
>>     err = bpf_object__open_skeleton(obj->skeleton, opts);
>>     if (err)
>>         goto err_out;
>>
>>     return obj;
>> err_out:
>>     restrict_ifaces_bpf__destroy(obj);
>>     errno = -err;
>>     return NULL;
>> }
>>
>> static inline struct restrict_ifaces_bpf *
>> restrict_ifaces_bpf__open(void)
>> {
>>     return restrict_ifaces_bpf__open_opts(NULL);
>> }
>>
>> static inline int
>> restrict_ifaces_bpf__load(struct restrict_ifaces_bpf *obj)
>> {
>>     return bpf_object__load_skeleton(obj->skeleton);
>> }
>>
>> static inline struct restrict_ifaces_bpf *
>> restrict_ifaces_bpf__open_and_load(void)
>> {
>>     struct restrict_ifaces_bpf *obj;
>>     int err;
>>
>>     obj = restrict_ifaces_bpf__open();
>>     if (!obj)
>>         return NULL;
>>     err = restrict_ifaces_bpf__load(obj);
>>     if (err) {
>>         restrict_ifaces_bpf__destroy(obj);
>>         errno = -err;
>>         return NULL;
>>     }
>>     return obj;
>> }
>>
>> static inline int
>> restrict_ifaces_bpf__attach(struct restrict_ifaces_bpf *obj)
>> {
>>     return bpf_object__attach_skeleton(obj->skeleton);
>> }
>>
>> static inline void
>> restrict_ifaces_bpf__detach(struct restrict_ifaces_bpf *obj)
>> {
>>     return bpf_object__detach_skeleton(obj->skeleton);
>> }
>>
>> static inline const void *restrict_ifaces_bpf__elf_bytes(size_t *sz);
>>
>> static inline int
>> restrict_ifaces_bpf__create_skeleton(struct restrict_ifaces_bpf *obj)
>> {
>>     struct bpf_object_skeleton *s;
>>     int err;
>>
>>     s = (struct bpf_object_skeleton *)calloc(1, sizeof(*s));
>>     if (!s)    {
>>         err = -ENOMEM;
>>         goto err;
>>     }
>>
>>     s->sz = sizeof(*s);
>>     s->name = "restrict_ifaces_bpf";
>>     s->obj = &obj->obj;
>>
>>     /* maps */
>>     s->map_cnt = 2;
>>     s->map_skel_sz = sizeof(*s->maps);
>>     s->maps = (struct bpf_map_skeleton *)calloc(s->map_cnt, s->map_skel_sz);
>>     if (!s->maps) {
>>         err = -ENOMEM;
>>         goto err;
>>     }
>>
>>     s->maps[0].name = "sd_restrictif";
>>     s->maps[0].map = &obj->maps.sd_restrictif;
>>
>>     s->maps[1].name = "restrict.data";
>>     s->maps[1].map = &obj->maps.data;
>>     s->maps[1].mmaped = (void **)&obj->data;
>>
>>     /* programs */
>>     s->prog_cnt = 2;
>>     s->prog_skel_sz = sizeof(*s->progs);
>>     s->progs = (struct bpf_prog_skeleton *)calloc(s->prog_cnt, s->prog_skel_sz);
>>     if (!s->progs) {
>>         err = -ENOMEM;
>>         goto err;
>>     }
>>
>>     s->progs[0].name = "sd_restrictif_e";
>>     s->progs[0].prog = &obj->progs.sd_restrictif_e;
>>     s->progs[0].link = &obj->links.sd_restrictif_e;
>>
>>     s->progs[1].name = "sd_restrictif_i";
>>     s->progs[1].prog = &obj->progs.sd_restrictif_i;
>>     s->progs[1].link = &obj->links.sd_restrictif_i;
>>
>>     s->data = (void *)restrict_ifaces_bpf__elf_bytes(&s->data_sz);
>>
>>     obj->skeleton = s;
>>     return 0;
>> err:
>>     bpf_object__destroy_skeleton(s);
>>     return err;
>> }
>>
>> static inline const void *restrict_ifaces_bpf__elf_bytes(size_t *sz)
>> {
>>     *sz = 5616;
>>     return (const void *)"\
>> \x7f\x45\x4c\x46\x02\x01\x01\0\0\0\0\0\0\0\0\0\x01\0\xf7\0\x01\0\0\0\0\0\0\0\0\
>> \0\0\0\0\0\0\0\0\0\0\0\xb0\x12\0\0\0\0\0\0\0\0\0\0\x40\0\0\0\0\0\x40\0\x0d\0\
>> \x01\0\0\x2e\x73\x74\x72\x74\x61\x62\0\x2e\x73\x79\x6d\x74\x61\x62\0\x2e\x64\
>> \x61\x74\x61\0\x2e\x62\x73\x73\0\x63\x67\x72\x6f\x75\x70\x5f\x73\x6b\x62\x2f\
>> \x65\x67\x72\x65\x73\x73\0\x63\x67\x72\x6f\x75\x70\x5f\x73\x6b\x62\x2f\x69\x6e\
>> \x67\x72\x65\x73\x73\0\x6c\x69\x63\x65\x6e\x73\x65\0\x2e\x6d\x61\x70\x73\0\x2e\
>> \x63\x6f\x6d\x6d\x65\x6e\x74\0\x72\x65\x73\x74\x72\x69\x63\x74\x2d\x69\x66\x61\
>> \x63\x65\x73\x2e\x62\x70\x66\x2e\x63\0\x5f\x6c\x69\x63\x65\x6e\x73\x65\0\x73\
>> \x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\x5f\x65\0\x73\x64\x5f\x72\x65\
>> \x73\x74\x72\x69\x63\x74\x69\x66\0\x69\x73\x5f\x61\x6c\x6c\x6f\x77\x5f\x6c\x69\
>> \x73\x74\0\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\x5f\x69\0\x2e\
>> \x72\x65\x6c\x63\x67\x72\x6f\x75\x70\x5f\x73\x6b\x62\x2f\x65\x67\x72\x65\x73\
>> \x73\0\x2e\x72\x65\x6c\x63\x67\x72\x6f\x75\x70\x5f\x73\x6b\x62\x2f\x69\x6e\x67\
>> \x72\x65\x73\x73\0\x2e\x42\x54\x46\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>> \0\0\0\0\0\0\x58\0\0\0\x04\0\xf1\xff\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>> \x03\0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x03\0\x04\0\0\0\0\0\0\0\0\
>> \0\0\0\0\0\0\0\0\0\0\0\0\0\x03\0\x05\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>> \x03\0\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x03\0\x07\0\0\0\0\0\0\0\0\
>> \0\0\0\0\0\0\0\0\0\x6e\0\0\0\x01\0\x07\0\0\0\0\0\0\0\0\0\x12\0\0\0\0\0\0\0\0\0\
>> \0\0\x03\0\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x03\0\x09\0\0\0\0\0\0\
>> \0\0\0\0\0\0\0\0\0\0\0\x77\0\0\0\x12\0\x05\0\0\0\0\0\0\0\0\0\xb8\0\0\0\0\0\0\0\
>> \x87\0\0\0\x11\0\x08\0\0\0\0\0\0\0\0\0\x18\0\0\0\0\0\0\0\x95\0\0\0\x11\0\x03\0\
>> \0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\xa3\0\0\0\x12\0\x06\0\0\0\0\0\0\0\0\0\xb8\0\
>> \0\0\0\0\0\0\0\0\0\0\0\0\0\0\x61\x10\x28\0\0\0\0\0\x63\x0a\xfc\xff\0\0\0\0\xbf\
>> \xa2\0\0\0\0\0\0\x07\x02\0\0\xfc\xff\xff\xff\x18\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\
>> \0\x85\0\0\0\x01\0\0\0\x18\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x71\x13\0\0\0\0\0\0\
>> \x57\x03\0\0\xff\0\0\0\x15\x03\x05\0\0\0\0\0\xbf\x02\0\0\0\0\0\0\x87\x02\0\0\0\
>> \0\0\0\x4f\x20\0\0\0\0\0\0\x77\0\0\0\x3f\0\0\0\x95\0\0\0\0\0\0\0\xb7\x01\0\0\
>> \x01\0\0\0\x15\0\x01\0\0\0\0\0\xbf\x31\0\0\0\0\0\0\xbf\x10\0\0\0\0\0\0\x57\0\0\
>> \0\x01\0\0\0\x95\0\0\0\0\0\0\0\x61\x10\x28\0\0\0\0\0\x63\x0a\xfc\xff\0\0\0\0\
>> \xbf\xa2\0\0\0\0\0\0\x07\x02\0\0\xfc\xff\xff\xff\x18\x01\0\0\0\0\0\0\0\0\0\0\0\
>> \0\0\0\x85\0\0\0\x01\0\0\0\x18\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x71\x13\0\0\0\0\
>> \0\0\x57\x03\0\0\xff\0\0\0\x15\x03\x05\0\0\0\0\0\xbf\x02\0\0\0\0\0\0\x87\x02\0\
>> \0\0\0\0\0\x4f\x20\0\0\0\0\0\0\x77\0\0\0\x3f\0\0\0\x95\0\0\0\0\0\0\0\xb7\x01\0\
>> \0\x01\0\0\0\x15\0\x01\0\0\0\0\0\xbf\x31\0\0\0\0\0\0\xbf\x10\0\0\0\0\0\0\x57\0\
>> \0\0\x01\0\0\0\x95\0\0\0\0\0\0\0\x4c\x47\x50\x4c\x2d\x32\x2e\x31\x2d\x6f\x72\
>> \x2d\x6c\x61\x74\x65\x72\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>> \0\0\0\0\0\x47\x43\x43\x3a\x20\x28\x42\x75\x69\x6c\x64\x72\x6f\x6f\x74\x20\x32\
>> \x30\x32\x32\x2e\x30\x35\x2d\x31\x33\x32\x2d\x67\x35\x32\x38\x62\x35\x61\x36\
>> \x35\x66\x36\x29\x20\x31\x32\x2e\x31\x2e\x30\0\0\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\
>> \x01\0\0\0\x0b\0\0\0\x38\0\0\0\0\0\0\0\x01\0\0\0\x0c\0\0\0\x20\0\0\0\0\0\0\0\
>> \x01\0\0\0\x0b\0\0\0\x38\0\0\0\0\0\0\0\x01\0\0\0\x0c\0\0\0\x9f\xeb\x01\0\x18\0\
>> \0\0\0\0\0\0\x9c\x07\0\0\x9c\x07\0\0\x62\x06\0\0\x01\0\0\0\0\0\0\x01\x01\0\0\0\
>> \x08\0\0\x03\x0d\0\0\0\0\0\0\x01\x01\0\0\0\x08\0\0\x02\x1b\0\0\0\0\0\0\x08\x02\
>> \0\0\0\0\0\0\0\0\0\0\x0a\x03\0\0\0\0\0\0\0\0\0\0\x09\x04\0\0\0\x20\0\0\0\0\0\0\
>> \x01\x02\0\0\0\x10\0\0\x01\x2a\0\0\0\0\0\0\x01\x02\0\0\0\x10\0\0\0\x3d\0\0\0\0\
>> \0\0\x08\x07\0\0\0\x43\0\0\0\0\0\0\x01\x04\0\0\0\x20\0\0\x01\x47\0\0\0\0\0\0\
>> \x08\x09\0\0\0\x4d\0\0\0\0\0\0\x01\x04\0\0\0\x20\0\0\0\x5a\0\0\0\0\0\0\x08\x0b\
>> \0\0\0\x60\0\0\0\0\0\0\x01\x08\0\0\0\x40\0\0\x01\x6e\0\0\0\0\0\0\x01\x08\0\0\0\
>> \x40\0\0\0\x85\0\0\0\0\0\0\x08\x0e\0\0\0\x8b\0\0\0\0\0\0\x01\x08\0\0\0\x40\0\0\
>> \0\x9d\0\0\0\0\0\0\x01\x08\0\0\0\x40\0\0\x01\xa6\0\0\0\0\0\0\x01\x01\0\0\0\x08\
>> \0\0\x03\0\0\0\0\0\0\0\x0a\x12\0\0\0\xab\0\0\0\0\0\0\x08\x08\0\0\0\xb2\0\0\0\0\
>> \0\0\x08\x0c\0\0\0\xb9\0\0\0\x1f\0\0\x06\x04\0\0\0\xc6\0\0\0\0\0\0\0\xda\0\0\0\
>> \x01\0\0\0\xec\0\0\0\x02\0\0\0\xff\0\0\0\x03\0\0\0\x17\x01\0\0\x04\0\0\0\x35\
>> \x01\0\0\x05\0\0\0\x4e\x01\0\0\x06\0\0\0\x68\x01\0\0\x07\0\0\0\x81\x01\0\0\x08\
>> \0\0\0\x9b\x01\0\0\x09\0\0\0\xb1\x01\0\0\x0a\0\0\0\xce\x01\0\0\x0b\0\0\0\xe4\
>> \x01\0\0\x0c\0\0\0\xff\x01\0\0\x0d\0\0\0\x19\x02\0\0\x0e\0\0\0\x2d\x02\0\0\x0f\
>> \0\0\0\x42\x02\0\0\x10\0\0\0\x56\x02\0\0\x11\0\0\0\x6a\x02\0\0\x12\0\0\0\x80\
>> \x02\0\0\x13\0\0\0\x9c\x02\0\0\x14\0\0\0\xbd\x02\0\0\x15\0\0\0\xe0\x02\0\0\x16\
>> \0\0\0\xf3\x02\0\0\x17\0\0\0\x06\x03\0\0\x18\0\0\0\x1e\x03\0\0\x19\0\0\0\x37\
>> \x03\0\0\x1a\0\0\0\x4f\x03\0\0\x1b\0\0\0\x64\x03\0\0\x1c\0\0\0\x7f\x03\0\0\x1d\
>> \0\0\0\x99\x03\0\0\x1e\0\0\0\0\0\0\0\x01\0\0\x05\x08\0\0\0\xb3\x03\0\0\x1d\0\0\
>> \0\0\0\0\0\xbd\x03\0\0\x0d\0\0\x04\x38\0\0\0\xcb\x03\0\0\x08\0\0\0\0\0\0\0\xd1\
>> \x03\0\0\x08\0\0\0\x10\0\0\0\xd7\x03\0\0\x08\0\0\0\x20\0\0\0\xe2\x03\0\0\x03\0\
>> \0\0\x30\0\0\0\xea\x03\0\0\x03\0\0\0\x38\0\0\0\xf8\x03\0\0\x03\0\0\0\x40\0\0\0\
>> \x01\x04\0\0\x03\0\0\0\x48\0\0\0\x0a\x04\0\0\x14\0\0\0\x50\0\0\0\x12\x04\0\0\
>> \x14\0\0\0\x60\0\0\0\x18\x04\0\0\x14\0\0\0\x70\0\0\0\0\0\0\0\x19\0\0\0\x80\0\0\
>> \0\x1e\x04\0\0\x0c\0\0\0\x80\x01\0\0\x24\x04\0\0\x15\0\0\0\xa0\x01\0\0\0\0\0\0\
>> \x02\0\0\x05\x20\0\0\0\0\0\0\0\x1a\0\0\0\0\0\0\0\0\0\0\0\x1b\0\0\0\0\0\0\0\0\0\
>> \0\0\x02\0\0\x04\x08\0\0\0\x2f\x04\0\0\x15\0\0\0\0\0\0\0\x38\x04\0\0\x15\0\0\0\
>> \x20\0\0\0\0\0\0\0\x02\0\0\x04\x20\0\0\0\x41\x04\0\0\x1c\0\0\0\0\0\0\0\x4a\x04\
>> \0\0\x1c\0\0\0\x80\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x0c\0\0\0\x10\0\0\0\x04\0\0\
>> \0\0\0\0\0\0\0\0\x02\x18\0\0\0\0\0\0\0\x01\0\0\x05\x08\0\0\0\x53\x04\0\0\x20\0\
>> \0\0\0\0\0\0\x56\x04\0\0\x0e\0\0\x04\x50\0\0\0\x5f\x04\0\0\x0c\0\0\0\0\0\0\0\
>> \x6c\x04\0\0\x0c\0\0\0\x20\0\0\0\x73\x04\0\0\x0c\0\0\0\x40\0\0\0\x78\x04\0\0\
>> \x0c\0\0\0\x60\0\0\0\x81\x04\0\0\x0c\0\0\0\x80\0\0\0\x86\x04\0\0\x0c\0\0\0\xa0\
>> \0\0\0\x8f\x04\0\0\x0c\0\0\0\xc0\0\0\0\x97\x04\0\0\x1c\0\0\0\xe0\0\0\0\x9f\x04\
>> \0\0\x0c\0\0\0\x60\x01\0\0\xa8\x04\0\0\x14\0\0\0\x80\x01\0\0\xb1\x04\0\0\x0c\0\
>> \0\0\xa0\x01\0\0\xb9\x04\0\0\x1c\0\0\0\xc0\x01\0\0\xc1\x04\0\0\x0c\0\0\0\x40\
>> \x02\0\0\xc7\x04\0\0\x0a\0\0\0\x60\x02\0\0\0\0\0\0\0\0\0\x02\x1f\0\0\0\xd8\x04\
>> \0\0\x21\0\0\x04\xc0\0\0\0\xe2\x04\0\0\x0c\0\0\0\0\0\0\0\xe6\x04\0\0\x0c\0\0\0\
>> \x20\0\0\0\x81\x04\0\0\x0c\0\0\0\x40\0\0\0\xef\x04\0\0\x0c\0\0\0\x60\0\0\0\x78\
>> \x04\0\0\x0c\0\0\0\x80\0\0\0\xfd\x04\0\0\x0c\0\0\0\xa0\0\0\0\x0a\x05\0\0\x0c\0\
>> \0\0\xc0\0\0\0\x13\x05\0\0\x0c\0\0\0\xe0\0\0\0\x86\x04\0\0\x0c\0\0\0\0\x01\0\0\
>> \x1e\x05\0\0\x0c\0\0\0\x20\x01\0\0\x2e\x05\0\0\x0c\0\0\0\x40\x01\0\0\x36\x05\0\
>> \0\x0c\0\0\0\x60\x01\0\0\x3f\x05\0\0\x22\0\0\0\x80\x01\0\0\x42\x05\0\0\x0c\0\0\
>> \0\x20\x02\0\0\x47\x05\0\0\x0c\0\0\0\x40\x02\0\0\x52\x05\0\0\x0c\0\0\0\x60\x02\
>> \0\0\x57\x05\0\0\x0c\0\0\0\x80\x02\0\0\x60\x05\0\0\x0c\0\0\0\xa0\x02\0\0\x6c\
>> \x04\0\0\x0c\0\0\0\xc0\x02\0\0\x68\x05\0\0\x0c\0\0\0\xe0\x02\0\0\x73\x05\0\0\
>> \x0c\0\0\0\0\x03\0\0\x7d\x05\0\0\x1c\0\0\0\x20\x03\0\0\x88\x05\0\0\x1c\0\0\0\
>> \xa0\x03\0\0\x92\x05\0\0\x0c\0\0\0\x20\x04\0\0\x9e\x05\0\0\x0c\0\0\0\x40\x04\0\
>> \0\xa9\x05\0\0\x0c\0\0\0\x60\x04\0\0\0\0\0\0\x17\0\0\0\x80\x04\0\0\xb3\x05\0\0\
>> \x0f\0\0\0\xc0\x04\0\0\xba\x05\0\0\x0c\0\0\0\0\x05\0\0\xc3\x05\0\0\x0c\0\0\0\
>> \x20\x05\0\0\0\0\0\0\x1e\0\0\0\x40\x05\0\0\xcc\x05\0\0\x0c\0\0\0\x80\x05\0\0\
>> \xd5\x05\0\0\x0f\0\0\0\xc0\x05\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x0c\0\0\0\x10\0\0\
>> \0\x05\0\0\0\0\0\0\0\0\0\0\x0a\x21\0\0\0\0\0\0\0\0\0\0\x02\0\0\0\0\0\0\0\0\x03\
>> \0\0\x04\x18\0\0\0\x73\x04\0\0\x27\0\0\0\0\0\0\0\xde\x05\0\0\x28\0\0\0\x40\0\0\
>> \0\xe2\x05\0\0\x29\0\0\0\x80\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x09\0\0\0\x10\0\0\
>> \0\x01\0\0\0\0\0\0\0\0\0\0\x02\x26\0\0\0\0\0\0\0\0\0\0\x02\x0c\0\0\0\0\0\0\0\0\
>> \0\0\x02\x03\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x13\0\0\0\x10\0\0\0\x12\0\0\0\0\0\
>> \0\0\0\0\0\x0a\x2a\0\0\0\0\0\0\0\x02\0\0\x0d\x24\0\0\0\0\0\0\0\x24\0\0\0\0\0\0\
>> \0\x2e\0\0\0\0\0\0\0\0\0\0\x0a\0\0\0\0\0\0\0\0\0\0\0\x02\x2d\0\0\0\0\0\0\0\x01\
>> \0\0\x0d\x09\0\0\0\x53\x04\0\0\x30\0\0\0\0\0\0\0\0\0\0\x02\x23\0\0\0\xe8\x05\0\
>> \0\0\0\0\x0e\x2b\0\0\0\0\0\0\0\xf1\x05\0\0\0\0\0\x0e\x05\0\0\0\x01\0\0\0\xff\
>> \x05\0\0\0\0\0\x0e\x25\0\0\0\x01\0\0\0\x0d\x06\0\0\x01\0\0\x0c\x2f\0\0\0\x1d\
>> \x06\0\0\x01\0\0\x0c\x2f\0\0\0\x2d\x06\0\0\0\0\0\x0c\x2f\0\0\0\x4e\x06\0\0\x01\
>> \0\0\x0f\x01\0\0\0\x32\0\0\0\0\0\0\0\x01\0\0\0\x54\x06\0\0\x01\0\0\x0f\x12\0\0\
>> \0\x31\0\0\0\0\0\0\0\x12\0\0\0\x5c\x06\0\0\x01\0\0\x0f\x18\0\0\0\x33\0\0\0\0\0\
>> \0\0\x18\0\0\0\0\x73\x69\x67\x6e\x65\x64\x20\x63\x68\x61\x72\0\x75\x6e\x73\x69\
>> \x67\x6e\x65\x64\x20\x63\x68\x61\x72\0\x5f\x5f\x75\x38\0\x73\x68\x6f\x72\x74\
>> \x20\x69\x6e\x74\0\x73\x68\x6f\x72\x74\x20\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\
>> \x69\x6e\x74\0\x5f\x5f\x75\x31\x36\0\x69\x6e\x74\0\x5f\x5f\x73\x33\x32\0\x75\
>> \x6e\x73\x69\x67\x6e\x65\x64\x20\x69\x6e\x74\0\x5f\x5f\x75\x33\x32\0\x6c\x6f\
>> \x6e\x67\x20\x6c\x6f\x6e\x67\x20\x69\x6e\x74\0\x6c\x6f\x6e\x67\x20\x6c\x6f\x6e\
>> \x67\x20\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x69\x6e\x74\0\x5f\x5f\x75\x36\x34\
>> \0\x6c\x6f\x6e\x67\x20\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x69\x6e\x74\0\x6c\
>> \x6f\x6e\x67\x20\x69\x6e\x74\0\x63\x68\x61\x72\0\x5f\x5f\x62\x65\x31\x36\0\x5f\
>> \x5f\x62\x65\x33\x32\0\x62\x70\x66\x5f\x6d\x61\x70\x5f\x74\x79\x70\x65\0\x42\
>> \x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x55\x4e\x53\x50\x45\x43\0\x42\
>> \x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x48\x41\x53\x48\0\x42\x50\x46\
>> \x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x41\x52\x52\x41\x59\0\x42\x50\x46\x5f\
>> \x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x50\x52\x4f\x47\x5f\x41\x52\x52\x41\x59\0\
>> \x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x50\x45\x52\x46\x5f\x45\
>> \x56\x45\x4e\x54\x5f\x41\x52\x52\x41\x59\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\
>> \x59\x50\x45\x5f\x50\x45\x52\x43\x50\x55\x5f\x48\x41\x53\x48\0\x42\x50\x46\x5f\
>> \x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x50\x45\x52\x43\x50\x55\x5f\x41\x52\x52\
>> \x41\x59\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x53\x54\x41\x43\
>> \x4b\x5f\x54\x52\x41\x43\x45\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\
>> \x5f\x43\x47\x52\x4f\x55\x50\x5f\x41\x52\x52\x41\x59\0\x42\x50\x46\x5f\x4d\x41\
>> \x50\x5f\x54\x59\x50\x45\x5f\x4c\x52\x55\x5f\x48\x41\x53\x48\0\x42\x50\x46\x5f\
>> \x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x4c\x52\x55\x5f\x50\x45\x52\x43\x50\x55\
>> \x5f\x48\x41\x53\x48\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x4c\
>> \x50\x4d\x5f\x54\x52\x49\x45\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\
>> \x5f\x41\x52\x52\x41\x59\x5f\x4f\x46\x5f\x4d\x41\x50\x53\0\x42\x50\x46\x5f\x4d\
>> \x41\x50\x5f\x54\x59\x50\x45\x5f\x48\x41\x53\x48\x5f\x4f\x46\x5f\x4d\x41\x50\
>> \x53\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x44\x45\x56\x4d\x41\
>> \x50\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x53\x4f\x43\x4b\x4d\
>> \x41\x50\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x43\x50\x55\x4d\
>> \x41\x50\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x58\x53\x4b\x4d\
>> \x41\x50\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x53\x4f\x43\x4b\
>> \x48\x41\x53\x48\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x43\x47\
>> \x52\x4f\x55\x50\x5f\x53\x54\x4f\x52\x41\x47\x45\0\x42\x50\x46\x5f\x4d\x41\x50\
>> \x5f\x54\x59\x50\x45\x5f\x52\x45\x55\x53\x45\x50\x4f\x52\x54\x5f\x53\x4f\x43\
>> \x4b\x41\x52\x52\x41\x59\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\
>> \x50\x45\x52\x43\x50\x55\x5f\x43\x47\x52\x4f\x55\x50\x5f\x53\x54\x4f\x52\x41\
>> \x47\x45\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x51\x55\x45\x55\
>> \x45\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x53\x54\x41\x43\x4b\
>> \0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x53\x4b\x5f\x53\x54\x4f\
>> \x52\x41\x47\x45\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x44\x45\
>> \x56\x4d\x41\x50\x5f\x48\x41\x53\x48\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\
>> \x50\x45\x5f\x53\x54\x52\x55\x43\x54\x5f\x4f\x50\x53\0\x42\x50\x46\x5f\x4d\x41\
>> \x50\x5f\x54\x59\x50\x45\x5f\x52\x49\x4e\x47\x42\x55\x46\0\x42\x50\x46\x5f\x4d\
>> \x41\x50\x5f\x54\x59\x50\x45\x5f\x49\x4e\x4f\x44\x45\x5f\x53\x54\x4f\x52\x41\
>> \x47\x45\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x54\x41\x53\x4b\
>> \x5f\x53\x54\x4f\x52\x41\x47\x45\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\
>> \x45\x5f\x42\x4c\x4f\x4f\x4d\x5f\x46\x49\x4c\x54\x45\x52\0\x66\x6c\x6f\x77\x5f\
>> \x6b\x65\x79\x73\0\x62\x70\x66\x5f\x66\x6c\x6f\x77\x5f\x6b\x65\x79\x73\0\x6e\
>> \x68\x6f\x66\x66\0\x74\x68\x6f\x66\x66\0\x61\x64\x64\x72\x5f\x70\x72\x6f\x74\
>> \x6f\0\x69\x73\x5f\x66\x72\x61\x67\0\x69\x73\x5f\x66\x69\x72\x73\x74\x5f\x66\
>> \x72\x61\x67\0\x69\x73\x5f\x65\x6e\x63\x61\x70\0\x69\x70\x5f\x70\x72\x6f\x74\
>> \x6f\0\x6e\x5f\x70\x72\x6f\x74\x6f\0\x73\x70\x6f\x72\x74\0\x64\x70\x6f\x72\x74\
>> \0\x66\x6c\x61\x67\x73\0\x66\x6c\x6f\x77\x5f\x6c\x61\x62\x65\x6c\0\x69\x70\x76\
>> \x34\x5f\x73\x72\x63\0\x69\x70\x76\x34\x5f\x64\x73\x74\0\x69\x70\x76\x36\x5f\
>> \x73\x72\x63\0\x69\x70\x76\x36\x5f\x64\x73\x74\0\x73\x6b\0\x62\x70\x66\x5f\x73\
>> \x6f\x63\x6b\0\x62\x6f\x75\x6e\x64\x5f\x64\x65\x76\x5f\x69\x66\0\x66\x61\x6d\
>> \x69\x6c\x79\0\x74\x79\x70\x65\0\x70\x72\x6f\x74\x6f\x63\x6f\x6c\0\x6d\x61\x72\
>> \x6b\0\x70\x72\x69\x6f\x72\x69\x74\x79\0\x73\x72\x63\x5f\x69\x70\x34\0\x73\x72\
>> \x63\x5f\x69\x70\x36\0\x73\x72\x63\x5f\x70\x6f\x72\x74\0\x64\x73\x74\x5f\x70\
>> \x6f\x72\x74\0\x64\x73\x74\x5f\x69\x70\x34\0\x64\x73\x74\x5f\x69\x70\x36\0\x73\
>> \x74\x61\x74\x65\0\x72\x78\x5f\x71\x75\x65\x75\x65\x5f\x6d\x61\x70\x70\x69\x6e\
>> \x67\0\x5f\x5f\x73\x6b\x5f\x62\x75\x66\x66\0\x6c\x65\x6e\0\x70\x6b\x74\x5f\x74\
>> \x79\x70\x65\0\x71\x75\x65\x75\x65\x5f\x6d\x61\x70\x70\x69\x6e\x67\0\x76\x6c\
>> \x61\x6e\x5f\x70\x72\x65\x73\x65\x6e\x74\0\x76\x6c\x61\x6e\x5f\x74\x63\x69\0\
>> \x76\x6c\x61\x6e\x5f\x70\x72\x6f\x74\x6f\0\x69\x6e\x67\x72\x65\x73\x73\x5f\x69\
>> \x66\x69\x6e\x64\x65\x78\0\x69\x66\x69\x6e\x64\x65\x78\0\x74\x63\x5f\x69\x6e\
>> \x64\x65\x78\0\x63\x62\0\x68\x61\x73\x68\0\x74\x63\x5f\x63\x6c\x61\x73\x73\x69\
>> \x64\0\x64\x61\x74\x61\0\x64\x61\x74\x61\x5f\x65\x6e\x64\0\x6e\x61\x70\x69\x5f\
>> \x69\x64\0\x72\x65\x6d\x6f\x74\x65\x5f\x69\x70\x34\0\x6c\x6f\x63\x61\x6c\x5f\
>> \x69\x70\x34\0\x72\x65\x6d\x6f\x74\x65\x5f\x69\x70\x36\0\x6c\x6f\x63\x61\x6c\
>> \x5f\x69\x70\x36\0\x72\x65\x6d\x6f\x74\x65\x5f\x70\x6f\x72\x74\0\x6c\x6f\x63\
>> \x61\x6c\x5f\x70\x6f\x72\x74\0\x64\x61\x74\x61\x5f\x6d\x65\x74\x61\0\x74\x73\
>> \x74\x61\x6d\x70\0\x77\x69\x72\x65\x5f\x6c\x65\x6e\0\x67\x73\x6f\x5f\x73\x65\
>> \x67\x73\0\x67\x73\x6f\x5f\x73\x69\x7a\x65\0\x68\x77\x74\x73\x74\x61\x6d\x70\0\
>> \x6b\x65\x79\0\x76\x61\x6c\x75\x65\0\x5f\x6c\x69\x63\x65\x6e\x73\x65\0\x69\x73\
>> \x5f\x61\x6c\x6c\x6f\x77\x5f\x6c\x69\x73\x74\0\x73\x64\x5f\x72\x65\x73\x74\x72\
>> \x69\x63\x74\x69\x66\0\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\x5f\
>> \x69\0\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\x5f\x65\0\x72\x65\
>> \x73\x74\x72\x69\x63\x74\x5f\x6e\x65\x74\x77\x6f\x72\x6b\x5f\x69\x6e\x74\x65\
>> \x72\x66\x61\x63\x65\x73\x5f\x69\x6d\x70\x6c\0\x2e\x64\x61\x74\x61\0\x6c\x69\
>> \x63\x65\x6e\x73\x65\0\x2e\x6d\x61\x70\x73\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>> \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>> \0\0\0\0\0\0\0\0\0\0\x01\0\0\0\x03\0\0\0\x20\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x40\
>> \0\0\0\0\0\0\0\xe5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\
>> \0\0\x09\0\0\0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x28\x01\0\0\0\0\0\0\
>> \x50\x01\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\x18\0\0\0\0\0\0\0\x11\
>> \0\0\0\x01\0\0\0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x78\x02\0\0\0\0\0\0\x01\0\0\
>> \0\0\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x17\0\0\0\x08\0\0\
>> \0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x79\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>> \0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x1c\0\0\0\x01\0\0\0\x06\0\0\0\0\0\
>> \0\0\0\0\0\0\0\0\0\0\x80\x02\0\0\0\0\0\0\xb8\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\
>> \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x2e\0\0\0\x01\0\0\0\x06\0\0\0\0\0\0\0\0\0\0\0\0\
>> \0\0\0\x38\x03\0\0\0\0\0\0\xb8\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\
>> \0\0\0\0\0\0\0\0\x41\0\0\0\x01\0\0\0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xf0\x03\
>> \0\0\0\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>> \0\x49\0\0\0\x01\0\0\0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\x04\0\0\0\0\0\0\
>> \x18\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x4f\0\0\0\
>> \x01\0\0\0\x30\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x20\x04\0\0\0\0\0\0\x31\0\0\0\0\0\
>> \0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\xb3\0\0\0\x09\0\0\0\
>> \x40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x58\x04\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\x02\0\
>> \0\0\x05\0\0\0\x08\0\0\0\0\0\0\0\x10\0\0\0\0\0\0\0\xc9\0\0\0\x09\0\0\0\x40\0\0\
>> \0\0\0\0\0\0\0\0\0\0\0\0\0\x78\x04\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\x02\0\0\0\x06\
>> \0\0\0\x08\0\0\0\0\0\0\0\x10\0\0\0\0\0\0\0\xe0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\
>> \0\0\0\0\0\0\0\0\x98\x04\0\0\0\0\0\0\x16\x0e\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\
>> \0\0\0\0\0\0\0\0\0\0\0\0\0\0";
>> }
>>
>> #ifdef __cplusplus
>> struct restrict_ifaces_bpf *restrict_ifaces_bpf::open(const struct
>> bpf_object_open_opts *opts) { return
>> restrict_ifaces_bpf__open_opts(opts); }
>> struct restrict_ifaces_bpf *restrict_ifaces_bpf::open_and_load() {
>> return restrict_ifaces_bpf__open_and_load(); }
>> int restrict_ifaces_bpf::load(struct restrict_ifaces_bpf *skel) {
>> return restrict_ifaces_bpf__load(skel); }
>> int restrict_ifaces_bpf::attach(struct restrict_ifaces_bpf *skel) {
>> return restrict_ifaces_bpf__attach(skel); }
>> void restrict_ifaces_bpf::detach(struct restrict_ifaces_bpf *skel) {
>> restrict_ifaces_bpf__detach(skel); }
>> void restrict_ifaces_bpf::destroy(struct restrict_ifaces_bpf *skel) {
>> restrict_ifaces_bpf__destroy(skel); }
>> const void *restrict_ifaces_bpf::elf_bytes(size_t *sz) { return
>> restrict_ifaces_bpf__elf_bytes(sz); }
>> #endif /* __cplusplus */
>>
>> __attribute__((unused)) static void
>> restrict_ifaces_bpf__assert(struct restrict_ifaces_bpf *s
>> __attribute__((unused)))
>> {
>> #ifdef __cplusplus
>> #define _Static_assert static_assert
>> #endif
>>     _Static_assert(sizeof(s->data->is_allow_list) == 1, "unexpected
>> size of 'is_allow_list'");
>> #ifdef __cplusplus
>> #undef _Static_assert
>> #endif
>> }
>>
>> #endif /* __RESTRICT_IFACES_BPF_SKEL_H__ */
>>
>> Clang:
>> $ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>> --debug gen skeleton restrict-ifaces.bpf.o
>> libbpf: loading object 'restrict_ifaces_bpf' from buffer
>> libbpf: elf: section(2) .symtab, size 384, link 1, flags 0, type=2
>> libbpf: elf: section(3) cgroup_skb/egress, size 152, link 0, flags 6, type=1
>> libbpf: sec 'cgroup_skb/egress': found program 'sd_restrictif_e' at
>> insn offset 0 (0 bytes), code size 19 insns (152 bytes)
>> libbpf: elf: section(4) cgroup_skb/ingress, size 152, link 0, flags 6, type=1
>> libbpf: sec 'cgroup_skb/ingress': found program 'sd_restrictif_i' at
>> insn offset 0 (0 bytes), code size 19 insns (152 bytes)
>> libbpf: elf: section(5) .rodata, size 1, link 0, flags 2, type=1
>> libbpf: elf: section(6) license, size 18, link 0, flags 2, type=1
>> libbpf: license of restrict_ifaces_bpf is LGPL-2.1-or-later
>> libbpf: elf: section(7) .maps, size 24, link 0, flags 3, type=1
>> libbpf: elf: section(8) .relcgroup_skb/egress, size 32, link 2, flags 40, type=9
>> libbpf: elf: section(9) .relcgroup_skb/ingress, size 32, link 2, flags
>> 40, type=9
>> libbpf: elf: section(10) .BTF, size 1988, link 0, flags 0, type=1
>> libbpf: elf: section(11) .BTF.ext, size 376, link 0, flags 0, type=1
>> libbpf: looking for externs among 16 symbols...
>> libbpf: collected 0 externs total
>> libbpf: map 'sd_restrictif': at sec_idx 7, offset 0.
>> libbpf: map 'sd_restrictif': found type = 1.
>> libbpf: map 'sd_restrictif': found key [6], sz = 4.
>> libbpf: map 'sd_restrictif': found value [9], sz = 1.
>> libbpf: map 'restrict.rodata' (global data): at sec_idx 5, offset 0, flags 480.
>> libbpf: map 1 is "restrict.rodata"
>> libbpf: sec '.relcgroup_skb/egress': collecting relocation for
>> section(3) 'cgroup_skb/egress'
>> libbpf: sec '.relcgroup_skb/egress': relo #0: insn #4 against 'sd_restrictif'
>> libbpf: prog 'sd_restrictif_e': found map 0 (sd_restrictif, sec 7, off
>> 0) for insn #4
>> libbpf: sec '.relcgroup_skb/egress': relo #1: insn #7 against 'is_allow_list'
>> libbpf: prog 'sd_restrictif_e': found data map 1 (restrict.rodata, sec
>> 5, off 0) for insn 7
>> libbpf: sec '.relcgroup_skb/ingress': collecting relocation for
>> section(4) 'cgroup_skb/ingress'
>> libbpf: sec '.relcgroup_skb/ingress': relo #0: insn #4 against 'sd_restrictif'
>> libbpf: prog 'sd_restrictif_i': found map 0 (sd_restrictif, sec 7, off
>> 0) for insn #4
>> libbpf: sec '.relcgroup_skb/ingress': relo #1: insn #7 against 'is_allow_list'
>> libbpf: prog 'sd_restrictif_i': found data map 1 (restrict.rodata, sec
>> 5, off 0) for insn 7
>> /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
>>
>> /* THIS FILE IS AUTOGENERATED BY BPFTOOL! */
>> #ifndef __RESTRICT_IFACES_BPF_SKEL_H__
>> #define __RESTRICT_IFACES_BPF_SKEL_H__
>>
>> #include <errno.h>
>> #include <stdlib.h>
>> #include <bpf/libbpf.h>
>>
>> struct restrict_ifaces_bpf {
>>     struct bpf_object_skeleton *skeleton;
>>     struct bpf_object *obj;
>>     struct {
>>         struct bpf_map *sd_restrictif;
>>         struct bpf_map *rodata;
>>     } maps;
>>     struct {
>>         struct bpf_program *sd_restrictif_e;
>>         struct bpf_program *sd_restrictif_i;
>>     } progs;
>>     struct {
>>         struct bpf_link *sd_restrictif_e;
>>         struct bpf_link *sd_restrictif_i;
>>     } links;
>>     struct restrict_ifaces_bpf__rodata {
>>         __u8 is_allow_list;
>>     } *rodata;
>>
>> #ifdef __cplusplus
>>     static inline struct restrict_ifaces_bpf *open(const struct
>> bpf_object_open_opts *opts = nullptr);
>>     static inline struct restrict_ifaces_bpf *open_and_load();
>>     static inline int load(struct restrict_ifaces_bpf *skel);
>>     static inline int attach(struct restrict_ifaces_bpf *skel);
>>     static inline void detach(struct restrict_ifaces_bpf *skel);
>>     static inline void destroy(struct restrict_ifaces_bpf *skel);
>>     static inline const void *elf_bytes(size_t *sz);
>> #endif /* __cplusplus */
>> };
>>
>> static void
>> restrict_ifaces_bpf__destroy(struct restrict_ifaces_bpf *obj)
>> {
>>     if (!obj)
>>         return;
>>     if (obj->skeleton)
>>         bpf_object__destroy_skeleton(obj->skeleton);
>>     free(obj);
>> }
>>
>> static inline int
>> restrict_ifaces_bpf__create_skeleton(struct restrict_ifaces_bpf *obj);
>>
>> static inline struct restrict_ifaces_bpf *
>> restrict_ifaces_bpf__open_opts(const struct bpf_object_open_opts *opts)
>> {
>>     struct restrict_ifaces_bpf *obj;
>>     int err;
>>
>>     obj = (struct restrict_ifaces_bpf *)calloc(1, sizeof(*obj));
>>     if (!obj) {
>>         errno = ENOMEM;
>>         return NULL;
>>     }
>>
>>     err = restrict_ifaces_bpf__create_skeleton(obj);
>>     if (err)
>>         goto err_out;
>>
>>     err = bpf_object__open_skeleton(obj->skeleton, opts);
>>     if (err)
>>         goto err_out;
>>
>>     return obj;
>> err_out:
>>     restrict_ifaces_bpf__destroy(obj);
>>     errno = -err;
>>     return NULL;
>> }
>>
>> static inline struct restrict_ifaces_bpf *
>> restrict_ifaces_bpf__open(void)
>> {
>>     return restrict_ifaces_bpf__open_opts(NULL);
>> }
>>
>> static inline int
>> restrict_ifaces_bpf__load(struct restrict_ifaces_bpf *obj)
>> {
>>     return bpf_object__load_skeleton(obj->skeleton);
>> }
>>
>> static inline struct restrict_ifaces_bpf *
>> restrict_ifaces_bpf__open_and_load(void)
>> {
>>     struct restrict_ifaces_bpf *obj;
>>     int err;
>>
>>     obj = restrict_ifaces_bpf__open();
>>     if (!obj)
>>         return NULL;
>>     err = restrict_ifaces_bpf__load(obj);
>>     if (err) {
>>         restrict_ifaces_bpf__destroy(obj);
>>         errno = -err;
>>         return NULL;
>>     }
>>     return obj;
>> }
>>
>> static inline int
>> restrict_ifaces_bpf__attach(struct restrict_ifaces_bpf *obj)
>> {
>>     return bpf_object__attach_skeleton(obj->skeleton);
>> }
>>
>> static inline void
>> restrict_ifaces_bpf__detach(struct restrict_ifaces_bpf *obj)
>> {
>>     return bpf_object__detach_skeleton(obj->skeleton);
>> }
>>
>> static inline const void *restrict_ifaces_bpf__elf_bytes(size_t *sz);
>>
>> static inline int
>> restrict_ifaces_bpf__create_skeleton(struct restrict_ifaces_bpf *obj)
>> {
>>     struct bpf_object_skeleton *s;
>>     int err;
>>
>>     s = (struct bpf_object_skeleton *)calloc(1, sizeof(*s));
>>     if (!s)    {
>>         err = -ENOMEM;
>>         goto err;
>>     }
>>
>>     s->sz = sizeof(*s);
>>     s->name = "restrict_ifaces_bpf";
>>     s->obj = &obj->obj;
>>
>>     /* maps */
>>     s->map_cnt = 2;
>>     s->map_skel_sz = sizeof(*s->maps);
>>     s->maps = (struct bpf_map_skeleton *)calloc(s->map_cnt, s->map_skel_sz);
>>     if (!s->maps) {
>>         err = -ENOMEM;
>>         goto err;
>>     }
>>
>>     s->maps[0].name = "sd_restrictif";
>>     s->maps[0].map = &obj->maps.sd_restrictif;
>>
>>     s->maps[1].name = "restrict.rodata";
>>     s->maps[1].map = &obj->maps.rodata;
>>     s->maps[1].mmaped = (void **)&obj->rodata;
>>
>>     /* programs */
>>     s->prog_cnt = 2;
>>     s->prog_skel_sz = sizeof(*s->progs);
>>     s->progs = (struct bpf_prog_skeleton *)calloc(s->prog_cnt, s->prog_skel_sz);
>>     if (!s->progs) {
>>         err = -ENOMEM;
>>         goto err;
>>     }
>>
>>     s->progs[0].name = "sd_restrictif_e";
>>     s->progs[0].prog = &obj->progs.sd_restrictif_e;
>>     s->progs[0].link = &obj->links.sd_restrictif_e;
>>
>>     s->progs[1].name = "sd_restrictif_i";
>>     s->progs[1].prog = &obj->progs.sd_restrictif_i;
>>     s->progs[1].link = &obj->links.sd_restrictif_i;
>>
>>     s->data = (void *)restrict_ifaces_bpf__elf_bytes(&s->data_sz);
>>
>>     obj->skeleton = s;
>>     return 0;
>> err:
>>     bpf_object__destroy_skeleton(s);
>>     return err;
>> }
>>
>> static inline const void *restrict_ifaces_bpf__elf_bytes(size_t *sz)
>> {
>>     *sz = 4272;
>>     return (const void *)"\
>> \x7f\x45\x4c\x46\x02\x01\x01\0\0\0\0\0\0\0\0\0\x01\0\xf7\0\x01\0\0\0\0\0\0\0\0\
>> \0\0\0\0\0\0\0\0\0\0\0\xb0\x0d\0\0\0\0\0\0\0\0\0\0\x40\0\0\0\0\0\x40\0\x0c\0\
>> \x01\0\0\x2e\x73\x74\x72\x74\x61\x62\0\x2e\x73\x79\x6d\x74\x61\x62\0\x63\x67\
>> \x72\x6f\x75\x70\x5f\x73\x6b\x62\x2f\x65\x67\x72\x65\x73\x73\0\x63\x67\x72\x6f\
>> \x75\x70\x5f\x73\x6b\x62\x2f\x69\x6e\x67\x72\x65\x73\x73\0\x2e\x72\x6f\x64\x61\
>> \x74\x61\0\x6c\x69\x63\x65\x6e\x73\x65\0\x2e\x6d\x61\x70\x73\0\x72\x65\x73\x74\
>> \x72\x69\x63\x74\x2d\x69\x66\x61\x63\x65\x73\x2e\x62\x70\x66\x2e\x63\0\x4c\x42\
>> \x42\x30\x5f\x32\0\x4c\x42\x42\x30\x5f\x33\0\x4c\x42\x42\x30\x5f\x34\0\x4c\x42\
>> \x42\x31\x5f\x32\0\x4c\x42\x42\x31\x5f\x33\0\x4c\x42\x42\x31\x5f\x34\0\x5f\x6c\
>> \x69\x63\x65\x6e\x73\x65\0\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\
>> \x5f\x65\0\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\0\x69\x73\x5f\
>> \x61\x6c\x6c\x6f\x77\x5f\x6c\x69\x73\x74\0\x73\x64\x5f\x72\x65\x73\x74\x72\x69\
>> \x63\x74\x69\x66\x5f\x69\0\x2e\x72\x65\x6c\x63\x67\x72\x6f\x75\x70\x5f\x73\x6b\
>> \x62\x2f\x65\x67\x72\x65\x73\x73\0\x2e\x72\x65\x6c\x63\x67\x72\x6f\x75\x70\x5f\
>> \x73\x6b\x62\x2f\x69\x6e\x67\x72\x65\x73\x73\0\x2e\x42\x54\x46\0\x2e\x42\x54\
>> \x46\x2e\x65\x78\x74\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>> \x4c\0\0\0\x04\0\xf1\xff\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x03\0\x03\0\0\
>> \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x62\0\0\0\0\0\x03\0\x70\0\0\0\0\0\0\0\0\0\0\0\0\
>> \0\0\0\x69\0\0\0\0\0\x03\0\x80\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x70\0\0\0\0\0\x03\
>> \0\x88\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x03\0\x04\0\0\0\0\0\0\0\0\0\0\0\0\
>> \0\0\0\0\0\x77\0\0\0\0\0\x04\0\x70\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x7e\0\0\0\0\0\
>> \x04\0\x80\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x85\0\0\0\0\0\x04\0\x88\0\0\0\0\0\0\0\
>> \0\0\0\0\0\0\0\0\x8c\0\0\0\x01\0\x06\0\0\0\0\0\0\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\
>> \0\x03\0\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x95\0\0\0\x12\0\x03\0\0\0\0\0\0\
>> \0\0\0\x98\0\0\0\0\0\0\0\xa5\0\0\0\x11\0\x07\0\0\0\0\0\0\0\0\0\x18\0\0\0\0\0\0\
>> \0\xb3\0\0\0\x11\0\x05\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\xc1\0\0\0\x12\0\x04\
>> \0\0\0\0\0\0\0\0\0\x98\0\0\0\0\0\0\0\x61\x11\x28\0\0\0\0\0\x63\x1a\xfc\xff\0\0\
>> \0\0\xbf\xa2\0\0\0\0\0\0\x07\x02\0\0\xfc\xff\xff\xff\x18\x01\0\0\0\0\0\0\0\0\0\
>> \0\0\0\0\0\x85\0\0\0\x01\0\0\0\x18\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x71\x11\0\0\
>> \0\0\0\0\x15\x01\x03\0\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x15\0\x03\0\0\0\0\0\x05\0\
>> \x03\0\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x15\0\x01\0\0\0\0\0\xb7\x01\0\0\0\0\0\0\
>> \xbf\x10\0\0\0\0\0\0\x95\0\0\0\0\0\0\0\x61\x11\x28\0\0\0\0\0\x63\x1a\xfc\xff\0\
>> \0\0\0\xbf\xa2\0\0\0\0\0\0\x07\x02\0\0\xfc\xff\xff\xff\x18\x01\0\0\0\0\0\0\0\0\
>> \0\0\0\0\0\0\x85\0\0\0\x01\0\0\0\x18\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x71\x11\0\
>> \0\0\0\0\0\x15\x01\x03\0\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x15\0\x03\0\0\0\0\0\x05\
>> \0\x03\0\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x15\0\x01\0\0\0\0\0\xb7\x01\0\0\0\0\0\0\
>> \xbf\x10\0\0\0\0\0\0\x95\0\0\0\0\0\0\0\0\x4c\x47\x50\x4c\x2d\x32\x2e\x31\x2d\
>> \x6f\x72\x2d\x6c\x61\x74\x65\x72\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>> \0\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\x01\0\0\0\x0d\0\0\0\x38\0\0\0\0\0\0\0\x01\0\0\
>> \0\x0e\0\0\0\x20\0\0\0\0\0\0\0\x01\0\0\0\x0d\0\0\0\x38\0\0\0\0\0\0\0\x01\0\0\0\
>> \x0e\0\0\0\x9f\xeb\x01\0\x18\0\0\0\0\0\0\0\x10\x04\0\0\x10\x04\0\0\x9c\x03\0\0\
>> \0\0\0\0\0\0\0\x02\x03\0\0\0\x01\0\0\0\0\0\0\x01\x04\0\0\0\x20\0\0\x01\0\0\0\0\
>> \0\0\0\x03\0\0\0\0\x02\0\0\0\x04\0\0\0\x01\0\0\0\x05\0\0\0\0\0\0\x01\x04\0\0\0\
>> \x20\0\0\0\0\0\0\0\0\0\0\x02\x06\0\0\0\x19\0\0\0\0\0\0\x08\x07\0\0\0\x1f\0\0\0\
>> \0\0\0\x01\x04\0\0\0\x20\0\0\0\0\0\0\0\0\0\0\x02\x09\0\0\0\x2c\0\0\0\0\0\0\x08\
>> \x0a\0\0\0\x31\0\0\0\0\0\0\x01\x01\0\0\0\x08\0\0\0\0\0\0\0\x03\0\0\x04\x18\0\0\
>> \0\x3f\0\0\0\x01\0\0\0\0\0\0\0\x44\0\0\0\x05\0\0\0\x40\0\0\0\x48\0\0\0\x08\0\0\
>> \0\x80\0\0\0\x4e\0\0\0\0\0\0\x0e\x0b\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\x02\x0e\0\0\
>> \0\0\0\0\0\0\0\0\x0a\x0f\0\0\0\x5c\0\0\0\x21\0\0\x04\xc0\0\0\0\x66\0\0\0\x06\0\
>> \0\0\0\0\0\0\x6a\0\0\0\x06\0\0\0\x20\0\0\0\x73\0\0\0\x06\0\0\0\x40\0\0\0\x78\0\
>> \0\0\x06\0\0\0\x60\0\0\0\x86\0\0\0\x06\0\0\0\x80\0\0\0\x8f\0\0\0\x06\0\0\0\xa0\
>> \0\0\0\x9c\0\0\0\x06\0\0\0\xc0\0\0\0\xa5\0\0\0\x06\0\0\0\xe0\0\0\0\xb0\0\0\0\
>> \x06\0\0\0\0\x01\0\0\xb9\0\0\0\x06\0\0\0\x20\x01\0\0\xc9\0\0\0\x06\0\0\0\x40\
>> \x01\0\0\xd1\0\0\0\x06\0\0\0\x60\x01\0\0\xda\0\0\0\x10\0\0\0\x80\x01\0\0\xdd\0\
>> \0\0\x06\0\0\0\x20\x02\0\0\xe2\0\0\0\x06\0\0\0\x40\x02\0\0\xed\0\0\0\x06\0\0\0\
>> \x60\x02\0\0\xf2\0\0\0\x06\0\0\0\x80\x02\0\0\xfb\0\0\0\x06\0\0\0\xa0\x02\0\0\
>> \x03\x01\0\0\x06\0\0\0\xc0\x02\0\0\x0a\x01\0\0\x06\0\0\0\xe0\x02\0\0\x15\x01\0\
>> \0\x06\0\0\0\0\x03\0\0\x1f\x01\0\0\x11\0\0\0\x20\x03\0\0\x2a\x01\0\0\x11\0\0\0\
>> \xa0\x03\0\0\x34\x01\0\0\x06\0\0\0\x20\x04\0\0\x40\x01\0\0\x06\0\0\0\x40\x04\0\
>> \0\x4b\x01\0\0\x06\0\0\0\x60\x04\0\0\0\0\0\0\x12\0\0\0\x80\x04\0\0\x55\x01\0\0\
>> \x14\0\0\0\xc0\x04\0\0\x5c\x01\0\0\x06\0\0\0\0\x05\0\0\x65\x01\0\0\x06\0\0\0\
>> \x20\x05\0\0\0\0\0\0\x16\0\0\0\x40\x05\0\0\x6e\x01\0\0\x06\0\0\0\x80\x05\0\0\
>> \x77\x01\0\0\x14\0\0\0\xc0\x05\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x06\0\0\0\x04\0\0\
>> \0\x05\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x06\0\0\0\x04\0\0\0\x04\0\0\0\0\0\0\0\
>> \x01\0\0\x05\x08\0\0\0\x80\x01\0\0\x13\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x02\x22\0\0\
>> \0\x8a\x01\0\0\0\0\0\x08\x15\0\0\0\x90\x01\0\0\0\0\0\x01\x08\0\0\0\x40\0\0\0\0\
>> \0\0\0\x01\0\0\x05\x08\0\0\0\xa3\x01\0\0\x17\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x02\
>> \x23\0\0\0\0\0\0\0\x01\0\0\x0d\x02\0\0\0\xa3\x01\0\0\x0d\0\0\0\xa6\x01\0\0\x01\
>> \0\0\x0c\x18\0\0\0\xb6\x01\0\0\x01\0\0\x0c\x18\0\0\0\0\0\0\0\0\0\0\x0a\x1c\0\0\
>> \0\0\0\0\0\0\0\0\x09\x09\0\0\0\xc6\x01\0\0\0\0\0\x0e\x1b\0\0\0\x01\0\0\0\0\0\0\
>> \0\0\0\0\x0a\x1f\0\0\0\xd4\x01\0\0\0\0\0\x01\x01\0\0\0\x08\0\0\x01\0\0\0\0\0\0\
>> \0\x03\0\0\0\0\x1e\0\0\0\x04\0\0\0\x12\0\0\0\xd9\x01\0\0\0\0\0\x0e\x20\0\0\0\0\
>> \0\0\0\xe2\x01\0\0\0\0\0\x07\0\0\0\0\xf0\x01\0\0\0\0\0\x07\0\0\0\0\x61\x03\0\0\
>> \x01\0\0\x0f\x01\0\0\0\x1d\0\0\0\0\0\0\0\x01\0\0\0\x69\x03\0\0\x01\0\0\x0f\x12\
>> \0\0\0\x21\0\0\0\0\0\0\0\x12\0\0\0\x71\x03\0\0\x01\0\0\x0f\x18\0\0\0\x0c\0\0\0\
>> \0\0\0\0\x18\0\0\0\0\x69\x6e\x74\0\x5f\x5f\x41\x52\x52\x41\x59\x5f\x53\x49\x5a\
>> \x45\x5f\x54\x59\x50\x45\x5f\x5f\0\x5f\x5f\x75\x33\x32\0\x75\x6e\x73\x69\x67\
>> \x6e\x65\x64\x20\x69\x6e\x74\0\x5f\x5f\x75\x38\0\x75\x6e\x73\x69\x67\x6e\x65\
>> \x64\x20\x63\x68\x61\x72\0\x74\x79\x70\x65\0\x6b\x65\x79\0\x76\x61\x6c\x75\x65\
>> \0\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\0\x5f\x5f\x73\x6b\x5f\
>> \x62\x75\x66\x66\0\x6c\x65\x6e\0\x70\x6b\x74\x5f\x74\x79\x70\x65\0\x6d\x61\x72\
>> \x6b\0\x71\x75\x65\x75\x65\x5f\x6d\x61\x70\x70\x69\x6e\x67\0\x70\x72\x6f\x74\
>> \x6f\x63\x6f\x6c\0\x76\x6c\x61\x6e\x5f\x70\x72\x65\x73\x65\x6e\x74\0\x76\x6c\
>> \x61\x6e\x5f\x74\x63\x69\0\x76\x6c\x61\x6e\x5f\x70\x72\x6f\x74\x6f\0\x70\x72\
>> \x69\x6f\x72\x69\x74\x79\0\x69\x6e\x67\x72\x65\x73\x73\x5f\x69\x66\x69\x6e\x64\
>> \x65\x78\0\x69\x66\x69\x6e\x64\x65\x78\0\x74\x63\x5f\x69\x6e\x64\x65\x78\0\x63\
>> \x62\0\x68\x61\x73\x68\0\x74\x63\x5f\x63\x6c\x61\x73\x73\x69\x64\0\x64\x61\x74\
>> \x61\0\x64\x61\x74\x61\x5f\x65\x6e\x64\0\x6e\x61\x70\x69\x5f\x69\x64\0\x66\x61\
>> \x6d\x69\x6c\x79\0\x72\x65\x6d\x6f\x74\x65\x5f\x69\x70\x34\0\x6c\x6f\x63\x61\
>> \x6c\x5f\x69\x70\x34\0\x72\x65\x6d\x6f\x74\x65\x5f\x69\x70\x36\0\x6c\x6f\x63\
>> \x61\x6c\x5f\x69\x70\x36\0\x72\x65\x6d\x6f\x74\x65\x5f\x70\x6f\x72\x74\0\x6c\
>> \x6f\x63\x61\x6c\x5f\x70\x6f\x72\x74\0\x64\x61\x74\x61\x5f\x6d\x65\x74\x61\0\
>> \x74\x73\x74\x61\x6d\x70\0\x77\x69\x72\x65\x5f\x6c\x65\x6e\0\x67\x73\x6f\x5f\
>> \x73\x65\x67\x73\0\x67\x73\x6f\x5f\x73\x69\x7a\x65\0\x68\x77\x74\x73\x74\x61\
>> \x6d\x70\0\x66\x6c\x6f\x77\x5f\x6b\x65\x79\x73\0\x5f\x5f\x75\x36\x34\0\x75\x6e\
>> \x73\x69\x67\x6e\x65\x64\x20\x6c\x6f\x6e\x67\x20\x6c\x6f\x6e\x67\0\x73\x6b\0\
>> \x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\x5f\x65\0\x73\x64\x5f\x72\
>> \x65\x73\x74\x72\x69\x63\x74\x69\x66\x5f\x69\0\x69\x73\x5f\x61\x6c\x6c\x6f\x77\
>> \x5f\x6c\x69\x73\x74\0\x63\x68\x61\x72\0\x5f\x6c\x69\x63\x65\x6e\x73\x65\0\x62\
>> \x70\x66\x5f\x66\x6c\x6f\x77\x5f\x6b\x65\x79\x73\0\x62\x70\x66\x5f\x73\x6f\x63\
>> \x6b\0\x2f\x68\x6f\x6d\x65\x2f\x62\x75\x69\x6c\x64\x72\x6f\x6f\x74\x2f\x62\x75\
>> \x69\x6c\x64\x72\x6f\x6f\x74\x2f\x6f\x75\x74\x70\x75\x74\x2f\x62\x75\x69\x6c\
>> \x64\x2f\x73\x79\x73\x74\x65\x6d\x64\x2d\x63\x75\x73\x74\x6f\x6d\x2f\x73\x72\
>> \x63\x2f\x63\x6f\x72\x65\x2f\x62\x70\x66\x2f\x72\x65\x73\x74\x72\x69\x63\x74\
>> \x5f\x69\x66\x61\x63\x65\x73\x2f\x72\x65\x73\x74\x72\x69\x63\x74\x2d\x69\x66\
>> \x61\x63\x65\x73\x2e\x62\x70\x66\x2e\x63\0\x20\x20\x20\x20\x20\x20\x20\x20\x69\
>> \x66\x69\x6e\x64\x65\x78\x20\x3d\x20\x73\x6b\x2d\x3e\x69\x66\x69\x6e\x64\x65\
>> \x78\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x6c\x6f\x6f\x6b\x75\x70\x5f\x72\x65\
>> \x73\x75\x6c\x74\x20\x3d\x20\x62\x70\x66\x5f\x6d\x61\x70\x5f\x6c\x6f\x6f\x6b\
>> \x75\x70\x5f\x65\x6c\x65\x6d\x28\x26\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\
>> \x74\x69\x66\x2c\x20\x26\x69\x66\x69\x6e\x64\x65\x78\x29\x3b\0\x20\x20\x20\x20\
>> \x20\x20\x20\x20\x69\x66\x20\x28\x69\x73\x5f\x61\x6c\x6c\x6f\x77\x5f\x6c\x69\
>> \x73\x74\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
>> \x20\x20\x69\x66\x20\x28\x6c\x6f\x6f\x6b\x75\x70\x5f\x72\x65\x73\x75\x6c\x74\
>> \x29\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\
>> \x20\x28\x21\x6c\x6f\x6f\x6b\x75\x70\x5f\x72\x65\x73\x75\x6c\x74\x29\0\x20\x20\
>> \x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x72\x65\x73\x74\x72\x69\
>> \x63\x74\x5f\x6e\x65\x74\x77\x6f\x72\x6b\x5f\x69\x6e\x74\x65\x72\x66\x61\x63\
>> \x65\x73\x5f\x69\x6d\x70\x6c\x28\x73\x6b\x29\x3b\0\x2e\x72\x6f\x64\x61\x74\x61\
>> \0\x6c\x69\x63\x65\x6e\x73\x65\0\x2e\x6d\x61\x70\x73\0\x63\x67\x72\x6f\x75\x70\
>> \x5f\x73\x6b\x62\x2f\x65\x67\x72\x65\x73\x73\0\x63\x67\x72\x6f\x75\x70\x5f\x73\
>> \x6b\x62\x2f\x69\x6e\x67\x72\x65\x73\x73\0\0\0\0\0\x9f\xeb\x01\0\x20\0\0\0\0\0\
>> \0\0\x24\0\0\0\x24\0\0\0\x34\x01\0\0\x58\x01\0\0\0\0\0\0\x08\0\0\0\x77\x03\0\0\
>> \x01\0\0\0\0\0\0\0\x19\0\0\0\x89\x03\0\0\x01\0\0\0\0\0\0\0\x1a\0\0\0\x10\0\0\0\
>> \x77\x03\0\0\x09\0\0\0\0\0\0\0\xf9\x01\0\0\x62\x02\0\0\x17\x6c\0\0\x08\0\0\0\
>> \xf9\x01\0\0\x62\x02\0\0\x11\x6c\0\0\x18\0\0\0\xf9\x01\0\0\0\0\0\0\0\0\0\0\x20\
>> \0\0\0\xf9\x01\0\0\x81\x02\0\0\x19\x70\0\0\x38\0\0\0\xf9\x01\0\0\xc8\x02\0\0\
>> \x0d\x74\0\0\x50\0\0\0\xf9\x01\0\0\xc8\x02\0\0\x0d\x74\0\0\x60\0\0\0\xf9\x01\0\
>> \0\xe5\x02\0\0\x15\x7c\0\0\x78\0\0\0\xf9\x01\0\0\x08\x03\0\0\x15\x8c\0\0\x88\0\
>> \0\0\xf9\x01\0\0\x2c\x03\0\0\x09\xb0\0\0\x89\x03\0\0\x09\0\0\0\0\0\0\0\xf9\x01\
>> \0\0\x62\x02\0\0\x17\x6c\0\0\x08\0\0\0\xf9\x01\0\0\x62\x02\0\0\x11\x6c\0\0\x18\
>> \0\0\0\xf9\x01\0\0\0\0\0\0\0\0\0\0\x20\0\0\0\xf9\x01\0\0\x81\x02\0\0\x19\x70\0\
>> \0\x38\0\0\0\xf9\x01\0\0\xc8\x02\0\0\x0d\x74\0\0\x50\0\0\0\xf9\x01\0\0\xc8\x02\
>> \0\0\x0d\x74\0\0\x60\0\0\0\xf9\x01\0\0\xe5\x02\0\0\x15\x7c\0\0\x78\0\0\0\xf9\
>> \x01\0\0\x08\x03\0\0\x15\x8c\0\0\x88\0\0\0\xf9\x01\0\0\x2c\x03\0\0\x09\xc4\0\0\
>> \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>> \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\x03\0\0\0\x20\0\0\
>> \0\0\0\0\0\0\0\0\0\0\0\0\0\x40\0\0\0\0\0\0\0\x0c\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\
>> \0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x09\0\0\0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>> \0\0\0\0\0\x50\x01\0\0\0\0\0\0\x80\x01\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\x08\0\0\0\
>> \0\0\0\0\x18\0\0\0\0\0\0\0\x11\0\0\0\x01\0\0\0\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>> \0\xd0\x02\0\0\0\0\0\0\x98\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0\0\
>> \0\0\0\0\0\0\x23\0\0\0\x01\0\0\0\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x68\x03\0\0\
>> \0\0\0\0\x98\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>> \x36\0\0\0\x01\0\0\0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\x01\0\
>> \0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x3e\0\0\0\x01\0\
>> \0\0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x04\0\0\0\0\0\0\x12\0\0\0\0\0\0\0\0\
>> \0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x46\0\0\0\x01\0\0\0\x03\0\0\0\
>> \0\0\0\0\0\0\0\0\0\0\0\0\x18\x04\0\0\0\0\0\0\x18\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>> \x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xd1\0\0\0\x09\0\0\0\x40\0\0\0\0\0\0\0\0\0\0\
>> \0\0\0\0\0\x30\x04\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\x02\0\0\0\x03\0\0\0\x08\0\0\0\
>> \0\0\0\0\x10\0\0\0\0\0\0\0\xe7\0\0\0\x09\0\0\0\x40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>> \0\x50\x04\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\x02\0\0\0\x04\0\0\0\x08\0\0\0\0\0\0\0\
>> \x10\0\0\0\0\0\0\0\xfe\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x70\x04\
>> \0\0\0\0\0\0\xc4\x07\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\
>> \0\0\x03\x01\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x38\x0c\0\0\0\0\0\0\
>> \x78\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
>> }
>>
>> #ifdef __cplusplus
>> struct restrict_ifaces_bpf *restrict_ifaces_bpf::open(const struct
>> bpf_object_open_opts *opts) { return
>> restrict_ifaces_bpf__open_opts(opts); }
>> struct restrict_ifaces_bpf *restrict_ifaces_bpf::open_and_load() {
>> return restrict_ifaces_bpf__open_and_load(); }
>> int restrict_ifaces_bpf::load(struct restrict_ifaces_bpf *skel) {
>> return restrict_ifaces_bpf__load(skel); }
>> int restrict_ifaces_bpf::attach(struct restrict_ifaces_bpf *skel) {
>> return restrict_ifaces_bpf__attach(skel); }
>> void restrict_ifaces_bpf::detach(struct restrict_ifaces_bpf *skel) {
>> restrict_ifaces_bpf__detach(skel); }
>> void restrict_ifaces_bpf::destroy(struct restrict_ifaces_bpf *skel) {
>> restrict_ifaces_bpf__destroy(skel); }
>> const void *restrict_ifaces_bpf::elf_bytes(size_t *sz) { return
>> restrict_ifaces_bpf__elf_bytes(sz); }
>> #endif /* __cplusplus */
>>
>> __attribute__((unused)) static void
>> restrict_ifaces_bpf__assert(struct restrict_ifaces_bpf *s
>> __attribute__((unused)))
>> {
>> #ifdef __cplusplus
>> #define _Static_assert static_assert
>> #endif
>>     _Static_assert(sizeof(s->rodata->is_allow_list) == 1, "unexpected
>> size of 'is_allow_list'");
>> #ifdef __cplusplus
>> #undef _Static_assert
>> #endif
>> }
>>
>> #endif /* __RESTRICT_IFACES_BPF_SKEL_H__ */
>>
>>>
>>>
>>> > Starting program:
>>> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>>> > --debug gen skeleton
>>> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>>> > [Thread debugging using libthread_db enabled]
>>> > Using host libthread_db library "/usr/lib/libthread_db.so.1".
>>> > libbpf: loading object 'restrict_ifaces_bpf' from buffer
>>> > libbpf: elf: section(2) .symtab, size 336, link 1, flags 0, type=2
>>> > libbpf: elf: section(3) .data, size 1, link 0, flags 3, type=1
>>> > libbpf: elf: section(4) .bss, size 0, link 0, flags 3, type=8
>>> > libbpf: elf: section(5) cgroup_skb/egress, size 184, link 0, flags 6, type=1
>>> > libbpf: sec 'cgroup_skb/egress': found program 'sd_restrictif_e' at
>>> > insn offset 0 (0 bytes), code size 23 insns (184 bytes)
>>> > libbpf: elf: section(6) cgroup_skb/ingress, size 184, link 0, flags 6, type=1
>>> > libbpf: sec 'cgroup_skb/ingress': found program 'sd_restrictif_i' at
>>> > insn offset 0 (0 bytes), code size 23 insns (184 bytes)
>>> > libbpf: elf: section(7) license, size 18, link 0, flags 2, type=1
>>> > libbpf: license of restrict_ifaces_bpf is LGPL-2.1-or-later
>>> > libbpf: elf: section(8) .maps, size 24, link 0, flags 3, type=1
>>> > libbpf: elf: section(9) .comment, size 49, link 0, flags 30, type=1
>>> > libbpf: elf: skipping unrecognized data section(9) .comment
>>> > libbpf: elf: section(10) .relcgroup_skb/egress, size 32, link 2, flags
>>> > 40, type=9
>>> > libbpf: elf: section(11) .relcgroup_skb/ingress, size 32, link 2,
>>> > flags 40, type=9
>>> > libbpf: elf: section(12) .BTF, size 3606, link 0, flags 0, type=1
>>> > libbpf: looking for externs among 14 symbols...
>>> > libbpf: collected 0 externs total
>>> > libbpf: map 'sd_restrictif': at sec_idx 8, offset 0.
>>> > libbpf: map 'sd_restrictif': found type = 1.
>>> > libbpf: map 'sd_restrictif': found key [12], sz = 4.
>>> > libbpf: map 'sd_restrictif': found value [3], sz = 1.
>>> >
>>> > Program received signal SIGSEGV, Segmentation fault.
>>> > 0x0000aaaaaab4fd2c in bpf_object.init_maps ()
>>> > (gdb) bt
>>> > #0  0x0000aaaaaab4fd2c in bpf_object.init_maps ()
>>> > #1  0x0000aaaaaab52178 in bpf_object_open.part ()
>>> > #2  0x0000aaaaaab544e8 in bpf_object.open_mem ()
>>> > #3  0x0000aaaaaab2a58c in do_skeleton ()
>>> > #4  0x0000aaaaaab1e204 in main ()
>>> >
>>> >>
>>> >> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
>>> >> index e89cc9c885b3..e3a6808f0bb6 100644
>>> >> --- a/tools/lib/bpf/libbpf.c
>>> >> +++ b/tools/lib/bpf/libbpf.c
>>> >> @@ -1591,6 +1591,10 @@ static int
> bpf_object__init_global_data_maps(struct bpf_object *obj)
>>> >>         for (sec_idx = 1; sec_idx < obj->efile.sec_cnt; sec_idx++) {
>>> >>                 sec_desc = &obj->efile.secs[sec_idx];
>>> >>
>>> >> +                /* Skip empty sections.  */
>>> >> +                if (sec_desc->data->d_size == 0)
>>> >> +                  continue;
>>> >> +
>>> >>                 switch (sec_desc->sec_type) {
>>> >>                 case SEC_DATA:
>>> >>                         sec_name = elf_sec_name(obj, elf_sec_by_idx(obj, sec_idx));
>>> >>
>>> >> > GCC:
>>> >> > $ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>>> >> > --debug gen skeleton
>>> >> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>>> >> > libbpf: loading object 'restrict_ifaces_bpf' from buffer
>>> >> > libbpf: elf: section(2) .symtab, size 336, link 1, flags 0, type=2
>>> >> > libbpf: elf: section(3) .data, size 1, link 0, flags 3, type=1
>>> >> > libbpf: elf: section(4) .bss, size 0, link 0, flags 3, type=8
>>> >> > libbpf: elf: section(5) cgroup_skb/egress, size 184, link 0, flags 6, type=1
>>> >> > libbpf: sec 'cgroup_skb/egress': found program 'sd_restrictif_e' at
>>> >> > insn offset 0 (0 bytes), code size 23 insns (184 bytes)
>>> >> > libbpf: elf: section(6) cgroup_skb/ingress, size 184, link 0, flags 6, type=1
>>> >> > libbpf: sec 'cgroup_skb/ingress': found program 'sd_restrictif_i' at
>>> >> > insn offset 0 (0 bytes), code size 23 insns (184 bytes)
>>> >> > libbpf: elf: section(7) license, size 18, link 0, flags 2, type=1
>>> >> > libbpf: license of restrict_ifaces_bpf is LGPL-2.1-or-later
>>> >> > libbpf: elf: section(8) .maps, size 24, link 0, flags 3, type=1
>>> >> > libbpf: elf: section(9) .comment, size 49, link 0, flags 30, type=1
>>> >> > libbpf: elf: skipping unrecognized data section(9) .comment
>>> >> > libbpf: elf: section(10) .relcgroup_skb/egress, size 32, link 2, flags
>>> >> > 40, type=9
>>> >> > libbpf: elf: section(11) .relcgroup_skb/ingress, size 32, link 2,
>>> >> > flags 40, type=9
>>> >> > libbpf: elf: section(12) .BTF, size 3606, link 0, flags 0, type=1
>>> >> > libbpf: looking for externs among 14 symbols...
>>> >> > libbpf: collected 0 externs total
>>> >> > libbpf: map 'sd_restrictif': at sec_idx 8, offset 0.
>>> >> > libbpf: map 'sd_restrictif': found type = 1.
>>> >> > libbpf: map 'sd_restrictif': found key [12], sz = 4.
>>> >> > libbpf: map 'sd_restrictif': found value [3], sz = 1.
>>> >> > libbpf: map 'restrict.data' (global data): at sec_idx 3, offset 0, flags 400.
>>> >> > libbpf: map 1 is "restrict.data"
>>> >> > libbpf: map 'restrict.bss' (global data): at sec_idx 4, offset 0, flags 400.
>>> >> > libbpf: failed to alloc map 'restrict.bss' content buffer: -22
>>> >> > Error: failed to open BPF object file: Invalid argument
>>> >> >
>>> >> > LLVM:
>>> >> > $ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>>> >> > --debug gen skeleton restrict-ifaces.bpf.o
>>> >> > libbpf: loading object 'restrict_ifaces_bpf' from buffer
>>> >> > libbpf: elf: section(2) .symtab, size 384, link 1, flags 0, type=2
>>> >> > libbpf: elf: section(3) cgroup_skb/egress, size 152, link 0, flags 6, type=1
>>> >> > libbpf: sec 'cgroup_skb/egress': found program 'sd_restrictif_e' at
>>> >> > insn offset 0 (0 bytes), code size 19 insns (152 bytes)
>>> >> > libbpf: elf: section(4) cgroup_skb/ingress, size 152, link 0, flags 6, type=1
>>> >> > libbpf: sec 'cgroup_skb/ingress': found program 'sd_restrictif_i' at
>>> >> > insn offset 0 (0 bytes), code size 19 insns (152 bytes)
>>> >> > libbpf: elf: section(5) .rodata, size 1, link 0, flags 2, type=1
>>> >> > libbpf: elf: section(6) license, size 18, link 0, flags 2, type=1
>>> >> > libbpf: license of restrict_ifaces_bpf is LGPL-2.1-or-later
>>> >> > libbpf: elf: section(7) .maps, size 24, link 0, flags 3, type=1
>>> >> > libbpf: elf: section(8) .relcgroup_skb/egress, size 32, link 2, flags 40, type=9
>>> >> > libbpf: elf: section(9) .relcgroup_skb/ingress, size 32, link 2, flags
>>> >> > 40, type=9
>>> >> > libbpf: elf: section(10) .BTF, size 1988, link 0, flags 0, type=1
>>> >> > libbpf: elf: section(11) .BTF.ext, size 376, link 0, flags 0, type=1
>>> >> > libbpf: looking for externs among 16 symbols...
>>> >> > libbpf: collected 0 externs total
>>> >> > libbpf: map 'sd_restrictif': at sec_idx 7, offset 0.
>>> >> > libbpf: map 'sd_restrictif': found type = 1.
>>> >> > libbpf: map 'sd_restrictif': found key [6], sz = 4.
>>> >> > libbpf: map 'sd_restrictif': found value [9], sz = 1.
>>> >> > libbpf: map 'restrict.rodata' (global data): at sec_idx 5, offset 0, flags 480.
>>> >> > libbpf: map 1 is "restrict.rodata"
>>> >> > libbpf: sec '.relcgroup_skb/egress': collecting relocation for
>>> >> > section(3) 'cgroup_skb/egress'
>>> >> > libbpf: sec '.relcgroup_skb/egress': relo #0: insn #4 against 'sd_restrictif'
>>> >> > libbpf: prog 'sd_restrictif_e': found map 0 (sd_restrictif, sec 7, off
>>> >> > 0) for insn #4
>>> >> > libbpf: sec '.relcgroup_skb/egress': relo #1: insn #7 against 'is_allow_list'
>>> >> > libbpf: prog 'sd_restrictif_e': found data map 1 (restrict.rodata, sec
>>> >> > 5, off 0) for insn 7
>>> >> > libbpf: sec '.relcgroup_skb/ingress': collecting relocation for
>>> >> > section(4) 'cgroup_skb/ingress'
>>> >> > libbpf: sec '.relcgroup_skb/ingress': relo #0: insn #4 against 'sd_restrictif'
>>> >> > libbpf: prog 'sd_restrictif_i': found map 0 (sd_restrictif, sec 7, off
>>> >> > 0) for insn #4
>>> >> > libbpf: sec '.relcgroup_skb/ingress': relo #1: insn #7 against 'is_allow_list'
>>> >> > libbpf: prog 'sd_restrictif_i': found data map 1 (restrict.rodata, sec
>>> >> > 5, off 0) for insn 7
>>> >> >
>>> >> >> >
>>> >> >> > >>
>>> >> >> > >> Looking at libbpf.c, it seems to me that this may be due of trying to
>>> >> >> > >> mmap 0 bytes in `bpf_object__init_internal_map':
>>> >> >> > >>
>>> >> >> > >>         map->mmaped = mmap(NULL, bpf_map_mmap_sz(map), PROT_READ | PROT_WRITE,
>>> >> >> > >>                            MAP_SHARED | MAP_ANONYMOUS, -1, 0);
>>> >> >> > >>         if (map->mmaped == MAP_FAILED) {
>>> >> >> > >>                 err = -errno;
>>> >> >> > >>                 map->mmaped = NULL;
>>> >> >> > >>                 pr_warn("failed to alloc map '%s' content buffer: %d\n",
>>> >> >> > >>                         map->name, err);
>>> >> >> > >>                 zfree(&map->real_name);
>>> >> >> > >>                 zfree(&map->name);
>>> >> >> > >>                 return err;
>>> >> >> > >>         }
>>> >> >> > >>
>>> >> >> > >> I see no check for zero sized sections in
>>> >> >> > >> bpf_object__init_global_data_maps.
>>> >> >> > >>
>>> >> >> > >> Is maybe GCC failing to allocate stuff in BSS that is supposed to be
>>> >> >> > >> there?
>>> >> >> > >>
>>> >> >> > >> > Stripped file passed to gen skeleton:
>>> >> >> > >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>>> >> >> > >> > btf dump file
>>> >> >> > >> >
> output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>>> >> >> > >> > format raw
>>> >> >> > >> > [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>>> >> >> > >> > [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
>>> >> >> > >> > [3] TYPEDEF '__u8' type_id=2
>>> >> >> > >> > [4] CONST '(anon)' type_id=3
>>> >> >> > >> > [5] VOLATILE '(anon)' type_id=4
>>> >> >> > >> > [6] INT 'short int' size=2 bits_offset=0 nr_bits=16 encoding=SIGNED
>>> >> >> > >> > [7] INT 'short unsigned int' size=2 bits_offset=0 nr_bits=16 encoding=(none)
>>> >> >> > >> > [8] TYPEDEF '__u16' type_id=7
>>> >> >> > >> > [9] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
>>> >> >> > >> > [10] TYPEDEF '__s32' type_id=9
>>> >> >> > >> > [11] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
>>> >> >> > >> > [12] TYPEDEF '__u32' type_id=11
>>> >> >> > >> > [13] INT 'long long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
>>> >> >> > >> > [14] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64
>>> >> >> > >> > encoding=(none)
>>> >> >> > >> > [15] TYPEDEF '__u64' type_id=14
>>> >> >> > >> > [16] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
>>> >> >> > >> > [17] INT 'long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
>>> >> >> > >> > [18] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>>> >> >> > >> > [19] CONST '(anon)' type_id=18
>>> >> >> > >> > [20] TYPEDEF '__be16' type_id=8
>>> >> >> > >> > [21] TYPEDEF '__be32' type_id=12
>>> >> >> > >> > [22] ENUM 'bpf_map_type' encoding=UNSIGNED size=4 vlen=31
>>> >> >> > >> >     'BPF_MAP_TYPE_UNSPEC' val=0
>>> >> >> > >> >     'BPF_MAP_TYPE_HASH' val=1
>>> >> >> > >> >     'BPF_MAP_TYPE_ARRAY' val=2
>>> >> >> > >> >     'BPF_MAP_TYPE_PROG_ARRAY' val=3
>>> >> >> > >> >     'BPF_MAP_TYPE_PERF_EVENT_ARRAY' val=4
>>> >> >> > >> >     'BPF_MAP_TYPE_PERCPU_HASH' val=5
>>> >> >> > >> >     'BPF_MAP_TYPE_PERCPU_ARRAY' val=6
>>> >> >> > >> >     'BPF_MAP_TYPE_STACK_TRACE' val=7
>>> >> >> > >> >     'BPF_MAP_TYPE_CGROUP_ARRAY' val=8
>>> >> >> > >> >     'BPF_MAP_TYPE_LRU_HASH' val=9
>>> >> >> > >> >     'BPF_MAP_TYPE_LRU_PERCPU_HASH' val=10
>>> >> >> > >> >     'BPF_MAP_TYPE_LPM_TRIE' val=11
>>> >> >> > >> >     'BPF_MAP_TYPE_ARRAY_OF_MAPS' val=12
>>> >> >> > >> >     'BPF_MAP_TYPE_HASH_OF_MAPS' val=13
>>> >> >> > >> >     'BPF_MAP_TYPE_DEVMAP' val=14
>>> >> >> > >> >     'BPF_MAP_TYPE_SOCKMAP' val=15
>>> >> >> > >> >     'BPF_MAP_TYPE_CPUMAP' val=16
>>> >> >> > >> >     'BPF_MAP_TYPE_XSKMAP' val=17
>>> >> >> > >> >     'BPF_MAP_TYPE_SOCKHASH' val=18
>>> >> >> > >> >     'BPF_MAP_TYPE_CGROUP_STORAGE' val=19
>>> >> >> > >> >     'BPF_MAP_TYPE_REUSEPORT_SOCKARRAY' val=20
>>> >> >> > >> >     'BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE' val=21
>>> >> >> > >> >     'BPF_MAP_TYPE_QUEUE' val=22
>>> >> >> > >> >     'BPF_MAP_TYPE_STACK' val=23
>>> >> >> > >> >     'BPF_MAP_TYPE_SK_STORAGE' val=24
>>> >> >> > >> >     'BPF_MAP_TYPE_DEVMAP_HASH' val=25
>>> >> >> > >> >     'BPF_MAP_TYPE_STRUCT_OPS' val=26
>>> >> >> > >> >     'BPF_MAP_TYPE_RINGBUF' val=27
>>> >> >> > >> >     'BPF_MAP_TYPE_INODE_STORAGE' val=28
>>> >> >> > >> >     'BPF_MAP_TYPE_TASK_STORAGE' val=29
>>> >> >> > >> >     'BPF_MAP_TYPE_BLOOM_FILTER' val=30
>>> >> >> > >> > [23] UNION '(anon)' size=8 vlen=1
>>> >> >> > >> >     'flow_keys' type_id=29 bits_offset=0
>>> >> >> > >> > [24] STRUCT 'bpf_flow_keys' size=56 vlen=13
>>> >> >> > >> >     'nhoff' type_id=8 bits_offset=0
>>> >> >> > >> >     'thoff' type_id=8 bits_offset=16
>>> >> >> > >> >     'addr_proto' type_id=8 bits_offset=32
>>> >> >> > >> >     'is_frag' type_id=3 bits_offset=48
>>> >> >> > >> >     'is_first_frag' type_id=3 bits_offset=56
>>> >> >> > >> >     'is_encap' type_id=3 bits_offset=64
>>> >> >> > >> >     'ip_proto' type_id=3 bits_offset=72
>>> >> >> > >> >     'n_proto' type_id=20 bits_offset=80
>>> >> >> > >> >     'sport' type_id=20 bits_offset=96
>>> >> >> > >> >     'dport' type_id=20 bits_offset=112
>>> >> >> > >> >     '(anon)' type_id=25 bits_offset=128
>>> >> >> > >> >     'flags' type_id=12 bits_offset=384
>>> >> >> > >> >     'flow_label' type_id=21 bits_offset=416
>>> >> >> > >> > [25] UNION '(anon)' size=32 vlen=2
>>> >> >> > >> >     '(anon)' type_id=26 bits_offset=0
>>> >> >> > >> >     '(anon)' type_id=27 bits_offset=0
>>> >> >> > >> > [26] STRUCT '(anon)' size=8 vlen=2
>>> >> >> > >> >     'ipv4_src' type_id=21 bits_offset=0
>>> >> >> > >> >     'ipv4_dst' type_id=21 bits_offset=32
>>> >> >> > >> > [27] STRUCT '(anon)' size=32 vlen=2
>>> >> >> > >> >     'ipv6_src' type_id=28 bits_offset=0
>>> >> >> > >> >     'ipv6_dst' type_id=28 bits_offset=128
>>> >> >> > >> > [28] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=4
>>> >> >> > >> > [29] PTR '(anon)' type_id=24
>>> >> >> > >> > [30] UNION '(anon)' size=8 vlen=1
>>> >> >> > >> >     'sk' type_id=32 bits_offset=0
>>> >> >> > >> > [31] STRUCT 'bpf_sock' size=80 vlen=14
>>> >> >> > >> >     'bound_dev_if' type_id=12 bits_offset=0
>>> >> >> > >> >     'family' type_id=12 bits_offset=32
>>> >> >> > >> >     'type' type_id=12 bits_offset=64
>>> >> >> > >> >     'protocol' type_id=12 bits_offset=96
>>> >> >> > >> >     'mark' type_id=12 bits_offset=128
>>> >> >> > >> >     'priority' type_id=12 bits_offset=160
>>> >> >> > >> >     'src_ip4' type_id=12 bits_offset=192
>>> >> >> > >> >     'src_ip6' type_id=28 bits_offset=224
>>> >> >> > >> >     'src_port' type_id=12 bits_offset=352
>>> >> >> > >> >     'dst_port' type_id=20 bits_offset=384
>>> >> >> > >> >     'dst_ip4' type_id=12 bits_offset=416
>>> >> >> > >> >     'dst_ip6' type_id=28 bits_offset=448
>>> >> >> > >> >     'state' type_id=12 bits_offset=576
>>> >> >> > >> >     'rx_queue_mapping' type_id=10 bits_offset=608
>>> >> >> > >> > [32] PTR '(anon)' type_id=31
>>> >> >> > >> > [33] STRUCT '__sk_buff' size=192 vlen=33
>>> >> >> > >> >     'len' type_id=12 bits_offset=0
>>> >> >> > >> >     'pkt_type' type_id=12 bits_offset=32
>>> >> >> > >> >     'mark' type_id=12 bits_offset=64
>>> >> >> > >> >     'queue_mapping' type_id=12 bits_offset=96
>>> >> >> > >> >     'protocol' type_id=12 bits_offset=128
>>> >> >> > >> >     'vlan_present' type_id=12 bits_offset=160
>>> >> >> > >> >     'vlan_tci' type_id=12 bits_offset=192
>>> >> >> > >> >     'vlan_proto' type_id=12 bits_offset=224
>>> >> >> > >> >     'priority' type_id=12 bits_offset=256
>>> >> >> > >> >     'ingress_ifindex' type_id=12 bits_offset=288
>>> >> >> > >> >     'ifindex' type_id=12 bits_offset=320
>>> >> >> > >> >     'tc_index' type_id=12 bits_offset=352
>>> >> >> > >> >     'cb' type_id=34 bits_offset=384
>>> >> >> > >> >     'hash' type_id=12 bits_offset=544
>>> >> >> > >> >     'tc_classid' type_id=12 bits_offset=576
>>> >> >> > >> >     'data' type_id=12 bits_offset=608
>>> >> >> > >> >     'data_end' type_id=12 bits_offset=640
>>> >> >> > >> >     'napi_id' type_id=12 bits_offset=672
>>> >> >> > >> >     'family' type_id=12 bits_offset=704
>>> >> >> > >> >     'remote_ip4' type_id=12 bits_offset=736
>>> >> >> > >> >     'local_ip4' type_id=12 bits_offset=768
>>> >> >> > >> >     'remote_ip6' type_id=28 bits_offset=800
>>> >> >> > >> >     'local_ip6' type_id=28 bits_offset=928
>>> >> >> > >> >     'remote_port' type_id=12 bits_offset=1056
>>> >> >> > >> >     'local_port' type_id=12 bits_offset=1088
>>> >> >> > >> >     'data_meta' type_id=12 bits_offset=1120
>>> >> >> > >> >     '(anon)' type_id=23 bits_offset=1152
>>> >> >> > >> >     'tstamp' type_id=15 bits_offset=1216
>>> >> >> > >> >     'wire_len' type_id=12 bits_offset=1280
>>> >> >> > >> >     'gso_segs' type_id=12 bits_offset=1312
>>> >> >> > >> >     '(anon)' type_id=30 bits_offset=1344
>>> >> >> > >> >     'gso_size' type_id=12 bits_offset=1408
>>> >> >> > >> >     'hwtstamp' type_id=15 bits_offset=1472
>>> >> >> > >> > [34] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=5
>>> >> >> > >> > [35] CONST '(anon)' type_id=33
>>> >> >> > >> > [36] PTR '(anon)' type_id=0
>>> >> >> > >> > [37] STRUCT '(anon)' size=24 vlen=3
>>> >> >> > >> >     'type' type_id=39 bits_offset=0
>>> >> >> > >> >     'key' type_id=40 bits_offset=64
>>> >> >> > >> >     'value' type_id=41 bits_offset=128
>>> >> >> > >> > [38] ARRAY '(anon)' type_id=9 index_type_id=16 nr_elems=1
>>> >> >> > >> > [39] PTR '(anon)' type_id=38
>>> >> >> > >> > [40] PTR '(anon)' type_id=12
>>> >> >> > >> > [41] PTR '(anon)' type_id=3
>>> >> >> > >> > [42] ARRAY '(anon)' type_id=19 index_type_id=16 nr_elems=18
>>> >> >> > >> > [43] CONST '(anon)' type_id=42
>>> >> >> > >> > [44] FUNC_PROTO '(anon)' ret_type_id=36 vlen=2
>>> >> >> > >> >     '(anon)' type_id=36
>>> >> >> > >> >     '(anon)' type_id=46
>>> >> >> > >> > [45] CONST '(anon)' type_id=0
>>> >> >> > >> > [46] PTR '(anon)' type_id=45
>>> >> >> > >> > [47] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>>> >> >> > >> >     'sk' type_id=48
>>> >> >> > >> > [48] PTR '(anon)' type_id=35
>>> >> >> > >> > [49] VAR '_license' type_id=43, linkage=static
>>> >> >> > >> > [50] VAR 'is_allow_list' type_id=5, linkage=global
>>> >> >> > >> > [51] VAR 'sd_restrictif' type_id=37, linkage=global
>>> >> >> > >> > [52] FUNC 'sd_restrictif_i' type_id=47 linkage=global
>>> >> >> > >> > [53] FUNC 'sd_restrictif_e' type_id=47 linkage=global
>>> >> >> > >> > [54] FUNC 'restrict_network_interfaces_impl' type_id=47 linkage=static
>>> >> >> > >> > [55] DATASEC '.data' size=1 vlen=1
>>> >> >> > >> >     type_id=50 offset=0 size=1 (VAR 'is_allow_list')
>>> >> >> > >> > [56] DATASEC 'license' size=18 vlen=1
>>> >> >> > >> >     type_id=49 offset=0 size=18 (VAR '_license')
>>> >> >> > >> > [57] DATASEC '.maps' size=24 vlen=1
>>> >> >> > >> >     type_id=51 offset=0 size=24 (VAR 'sd_restrictif')
>>> >> >> > >> >
>>> >> >> > >> > File before being stripped using bpftool gen object:
>>> >> >> > >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>>> >> >> > >> > btf dump file
>>> >> >> > >> >
>>> >> >
>>> >
> output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
>>> >> >> > >> > format raw
>>> >> >> > >> > [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>>> >> >> > >> > [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
>>> >> >> > >> > [3] TYPEDEF '__u8' type_id=2
>>> >> >> > >> > [4] CONST '(anon)' type_id=3
>>> >> >> > >> > [5] VOLATILE '(anon)' type_id=4
>>> >> >> > >> > [6] INT 'short int' size=2 bits_offset=0 nr_bits=16 encoding=SIGNED
>>> >> >> > >> > [7] INT 'short unsigned int' size=2 bits_offset=0 nr_bits=16 encoding=(none)
>>> >> >> > >> > [8] TYPEDEF '__u16' type_id=7
>>> >> >> > >> > [9] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
>>> >> >> > >> > [10] TYPEDEF '__s32' type_id=9
>>> >> >> > >> > [11] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
>>> >> >> > >> > [12] TYPEDEF '__u32' type_id=11
>>> >> >> > >> > [13] INT 'long long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
>>> >> >> > >> > [14] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64
>>> >> >> > >> > encoding=(none)
>>> >> >> > >> > [15] TYPEDEF '__u64' type_id=14
>>> >> >> > >> > [16] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
>>> >> >> > >> > [17] INT 'long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
>>> >> >> > >> > [18] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>>> >> >> > >> > [19] CONST '(anon)' type_id=18
>>> >> >> > >> > [20] TYPEDEF '__be16' type_id=8
>>> >> >> > >> > [21] TYPEDEF '__be32' type_id=12
>>> >> >> > >> > [22] ENUM 'bpf_map_type' encoding=UNSIGNED size=4 vlen=31
>>> >> >> > >> >     'BPF_MAP_TYPE_UNSPEC' val=0
>>> >> >> > >> >     'BPF_MAP_TYPE_HASH' val=1
>>> >> >> > >> >     'BPF_MAP_TYPE_ARRAY' val=2
>>> >> >> > >> >     'BPF_MAP_TYPE_PROG_ARRAY' val=3
>>> >> >> > >> >     'BPF_MAP_TYPE_PERF_EVENT_ARRAY' val=4
>>> >> >> > >> >     'BPF_MAP_TYPE_PERCPU_HASH' val=5
>>> >> >> > >> >     'BPF_MAP_TYPE_PERCPU_ARRAY' val=6
>>> >> >> > >> >     'BPF_MAP_TYPE_STACK_TRACE' val=7
>>> >> >> > >> >     'BPF_MAP_TYPE_CGROUP_ARRAY' val=8
>>> >> >> > >> >     'BPF_MAP_TYPE_LRU_HASH' val=9
>>> >> >> > >> >     'BPF_MAP_TYPE_LRU_PERCPU_HASH' val=10
>>> >> >> > >> >     'BPF_MAP_TYPE_LPM_TRIE' val=11
>>> >> >> > >> >     'BPF_MAP_TYPE_ARRAY_OF_MAPS' val=12
>>> >> >> > >> >     'BPF_MAP_TYPE_HASH_OF_MAPS' val=13
>>> >> >> > >> >     'BPF_MAP_TYPE_DEVMAP' val=14
>>> >> >> > >> >     'BPF_MAP_TYPE_SOCKMAP' val=15
>>> >> >> > >> >     'BPF_MAP_TYPE_CPUMAP' val=16
>>> >> >> > >> >     'BPF_MAP_TYPE_XSKMAP' val=17
>>> >> >> > >> >     'BPF_MAP_TYPE_SOCKHASH' val=18
>>> >> >> > >> >     'BPF_MAP_TYPE_CGROUP_STORAGE' val=19
>>> >> >> > >> >     'BPF_MAP_TYPE_REUSEPORT_SOCKARRAY' val=20
>>> >> >> > >> >     'BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE' val=21
>>> >> >> > >> >     'BPF_MAP_TYPE_QUEUE' val=22
>>> >> >> > >> >     'BPF_MAP_TYPE_STACK' val=23
>>> >> >> > >> >     'BPF_MAP_TYPE_SK_STORAGE' val=24
>>> >> >> > >> >     'BPF_MAP_TYPE_DEVMAP_HASH' val=25
>>> >> >> > >> >     'BPF_MAP_TYPE_STRUCT_OPS' val=26
>>> >> >> > >> >     'BPF_MAP_TYPE_RINGBUF' val=27
>>> >> >> > >> >     'BPF_MAP_TYPE_INODE_STORAGE' val=28
>>> >> >> > >> >     'BPF_MAP_TYPE_TASK_STORAGE' val=29
>>> >> >> > >> >     'BPF_MAP_TYPE_BLOOM_FILTER' val=30
>>> >> >> > >> > [23] UNION '(anon)' size=8 vlen=1
>>> >> >> > >> >     'flow_keys' type_id=29 bits_offset=0
>>> >> >> > >> > [24] STRUCT 'bpf_flow_keys' size=56 vlen=13
>>> >> >> > >> >     'nhoff' type_id=8 bits_offset=0
>>> >> >> > >> >     'thoff' type_id=8 bits_offset=16
>>> >> >> > >> >     'addr_proto' type_id=8 bits_offset=32
>>> >> >> > >> >     'is_frag' type_id=3 bits_offset=48
>>> >> >> > >> >     'is_first_frag' type_id=3 bits_offset=56
>>> >> >> > >> >     'is_encap' type_id=3 bits_offset=64
>>> >> >> > >> >     'ip_proto' type_id=3 bits_offset=72
>>> >> >> > >> >     'n_proto' type_id=20 bits_offset=80
>>> >> >> > >> >     'sport' type_id=20 bits_offset=96
>>> >> >> > >> >     'dport' type_id=20 bits_offset=112
>>> >> >> > >> >     '(anon)' type_id=25 bits_offset=128
>>> >> >> > >> >     'flags' type_id=12 bits_offset=384
>>> >> >> > >> >     'flow_label' type_id=21 bits_offset=416
>>> >> >> > >> > [25] UNION '(anon)' size=32 vlen=2
>>> >> >> > >> >     '(anon)' type_id=26 bits_offset=0
>>> >> >> > >> >     '(anon)' type_id=27 bits_offset=0
>>> >> >> > >> > [26] STRUCT '(anon)' size=8 vlen=2
>>> >> >> > >> >     'ipv4_src' type_id=21 bits_offset=0
>>> >> >> > >> >     'ipv4_dst' type_id=21 bits_offset=32
>>> >> >> > >> > [27] STRUCT '(anon)' size=32 vlen=2
>>> >> >> > >> >     'ipv6_src' type_id=28 bits_offset=0
>>> >> >> > >> >     'ipv6_dst' type_id=28 bits_offset=128
>>> >> >> > >> > [28] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=4
>>> >> >> > >> > [29] PTR '(anon)' type_id=24
>>> >> >> > >> > [30] UNION '(anon)' size=8 vlen=1
>>> >> >> > >> >     'sk' type_id=32 bits_offset=0
>>> >> >> > >> > [31] STRUCT 'bpf_sock' size=80 vlen=14
>>> >> >> > >> >     'bound_dev_if' type_id=12 bits_offset=0
>>> >> >> > >> >     'family' type_id=12 bits_offset=32
>>> >> >> > >> >     'type' type_id=12 bits_offset=64
>>> >> >> > >> >     'protocol' type_id=12 bits_offset=96
>>> >> >> > >> >     'mark' type_id=12 bits_offset=128
>>> >> >> > >> >     'priority' type_id=12 bits_offset=160
>>> >> >> > >> >     'src_ip4' type_id=12 bits_offset=192
>>> >> >> > >> >     'src_ip6' type_id=28 bits_offset=224
>>> >> >> > >> >     'src_port' type_id=12 bits_offset=352
>>> >> >> > >> >     'dst_port' type_id=20 bits_offset=384
>>> >> >> > >> >     'dst_ip4' type_id=12 bits_offset=416
>>> >> >> > >> >     'dst_ip6' type_id=28 bits_offset=448
>>> >> >> > >> >     'state' type_id=12 bits_offset=576
>>> >> >> > >> >     'rx_queue_mapping' type_id=10 bits_offset=608
>>> >> >> > >> > [32] PTR '(anon)' type_id=31
>>> >> >> > >> > [33] STRUCT '__sk_buff' size=192 vlen=33
>>> >> >> > >> >     'len' type_id=12 bits_offset=0
>>> >> >> > >> >     'pkt_type' type_id=12 bits_offset=32
>>> >> >> > >> >     'mark' type_id=12 bits_offset=64
>>> >> >> > >> >     'queue_mapping' type_id=12 bits_offset=96
>>> >> >> > >> >     'protocol' type_id=12 bits_offset=128
>>> >> >> > >> >     'vlan_present' type_id=12 bits_offset=160
>>> >> >> > >> >     'vlan_tci' type_id=12 bits_offset=192
>>> >> >> > >> >     'vlan_proto' type_id=12 bits_offset=224
>>> >> >> > >> >     'priority' type_id=12 bits_offset=256
>>> >> >> > >> >     'ingress_ifindex' type_id=12 bits_offset=288
>>> >> >> > >> >     'ifindex' type_id=12 bits_offset=320
>>> >> >> > >> >     'tc_index' type_id=12 bits_offset=352
>>> >> >> > >> >     'cb' type_id=34 bits_offset=384
>>> >> >> > >> >     'hash' type_id=12 bits_offset=544
>>> >> >> > >> >     'tc_classid' type_id=12 bits_offset=576
>>> >> >> > >> >     'data' type_id=12 bits_offset=608
>>> >> >> > >> >     'data_end' type_id=12 bits_offset=640
>>> >> >> > >> >     'napi_id' type_id=12 bits_offset=672
>>> >> >> > >> >     'family' type_id=12 bits_offset=704
>>> >> >> > >> >     'remote_ip4' type_id=12 bits_offset=736
>>> >> >> > >> >     'local_ip4' type_id=12 bits_offset=768
>>> >> >> > >> >     'remote_ip6' type_id=28 bits_offset=800
>>> >> >> > >> >     'local_ip6' type_id=28 bits_offset=928
>>> >> >> > >> >     'remote_port' type_id=12 bits_offset=1056
>>> >> >> > >> >     'local_port' type_id=12 bits_offset=1088
>>> >> >> > >> >     'data_meta' type_id=12 bits_offset=1120
>>> >> >> > >> >     '(anon)' type_id=23 bits_offset=1152
>>> >> >> > >> >     'tstamp' type_id=15 bits_offset=1216
>>> >> >> > >> >     'wire_len' type_id=12 bits_offset=1280
>>> >> >> > >> >     'gso_segs' type_id=12 bits_offset=1312
>>> >> >> > >> >     '(anon)' type_id=30 bits_offset=1344
>>> >> >> > >> >     'gso_size' type_id=12 bits_offset=1408
>>> >> >> > >> >     'hwtstamp' type_id=15 bits_offset=1472
>>> >> >> > >> > [34] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=5
>>> >> >> > >> > [35] CONST '(anon)' type_id=33
>>> >> >> > >> > [36] PTR '(anon)' type_id=0
>>> >> >> > >> > [37] STRUCT '(anon)' size=24 vlen=3
>>> >> >> > >> >     'type' type_id=39 bits_offset=0
>>> >> >> > >> >     'key' type_id=40 bits_offset=64
>>> >> >> > >> >     'value' type_id=41 bits_offset=128
>>> >> >> > >> > [38] ARRAY '(anon)' type_id=9 index_type_id=16 nr_elems=1
>>> >> >> > >> > [39] PTR '(anon)' type_id=38
>>> >> >> > >> > [40] PTR '(anon)' type_id=12
>>> >> >> > >> > [41] PTR '(anon)' type_id=3
>>> >> >> > >> > [42] ARRAY '(anon)' type_id=19 index_type_id=16 nr_elems=18
>>> >> >> > >> > [43] CONST '(anon)' type_id=42
>>> >> >> > >> > [44] FUNC_PROTO '(anon)' ret_type_id=36 vlen=2
>>> >> >> > >> >     '(anon)' type_id=36
>>> >> >> > >> >     '(anon)' type_id=46
>>> >> >> > >> > [45] CONST '(anon)' type_id=0
>>> >> >> > >> > [46] PTR '(anon)' type_id=45
>>> >> >> > >> > [47] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>>> >> >> > >> >     'sk' type_id=48
>>> >> >> > >> > [48] PTR '(anon)' type_id=35
>>> >> >> > >> > [49] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>>> >> >> > >> >     'sk' type_id=48
>>> >> >> > >> > [50] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>>> >> >> > >> >     'sk' type_id=48
>>> >> >> > >> > [51] VAR '_license' type_id=43, linkage=static
>>> >> >> > >> > [52] VAR 'is_allow_list' type_id=5, linkage=global
>>> >> >> > >> > [53] VAR 'sd_restrictif' type_id=37, linkage=global
>>> >> >> > >> > [54] FUNC 'bpf_map_lookup_elem' type_id=44 linkage=global
>>> >> >> > >> > [55] FUNC 'sd_restrictif_i' type_id=47 linkage=global
>>> >> >> > >> > [56] FUNC 'sd_restrictif_e' type_id=49 linkage=global
>>> >> >> > >> > [57] FUNC 'restrict_network_interfaces_impl' type_id=50 linkage=static
>>> >> >> > >> > [58] DATASEC 'license' size=0 vlen=1
>>> >> >> > >> >     type_id=51 offset=0 size=18 (VAR '_license')
>>> >> >> > >> > [59] DATASEC '.maps' size=0 vlen=1
>>> >> >> > >> >     type_id=53 offset=0 size=24 (VAR 'sd_restrictif')
>>> >> >> > >> > [60] DATASEC '.data' size=0 vlen=1
>>> >> >> > >> >     type_id=52 offset=0 size=1 (VAR 'is_allow_list')
>>> >> >> > >> >
>>> >> >> > >> >>
>>> >> >> > >> >> >> GCC is wrong, clearly. This function is global ([0]) and libbpf
>>> >> >> > >> >> >> expects it to be marked as such in BTF.
>>> >> >> > >> >> >>
>>> >> >> > >> >> >>
>>> >> >> > >> >
>>> >> >
>>> >
> https://github.com/systemd/systemd/blob/main/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.c#L42-L50
>>> >> >> > >> >> >>
>>> >> >> > >> >> >>
>>> >> >> > >> >> >>> GCC:
>>> >> >> > >> >> >>>
>>> >> >> > >> >> >>> [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>>> >> >> > >> >> >>> [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
>>> >> >> > >> >> >>> [3] TYPEDEF '__u8' type_id=2
>>> >> >> > >> >> >>> [4] CONST '(anon)' type_id=3
>>> >> >> > >> >> >>
>>> >> >> > >> >> >> [...]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-07-10 19:49                             ` Jose E. Marchesi
@ 2022-07-10 20:22                               ` Jose E. Marchesi
  2022-07-11  1:55                                 ` Jose E. Marchesi
       [not found]                                 ` <CADvTj4o-36iuru665BW0XnEauXBeszW438QTtpt4_VUEjf5nXg@mail.gmail.com>
  0 siblings, 2 replies; 38+ messages in thread
From: Jose E. Marchesi @ 2022-07-10 20:22 UTC (permalink / raw)
  To: James Hilliard; +Cc: Andrii Nakryiko, bpf, david.faust


>>> On Sun, Jul 10, 2022 at 3:38 AM Jose E. Marchesi
>>> <jose.marchesi@oracle.com> wrote:
>>>>
>>>>
>>>> > On Sat, Jul 9, 2022 at 4:41 PM Jose E. Marchesi
>>>> > <jose.marchesi@oracle.com> wrote:
>>>> >>
>>>> >>
>>>> >> > On Sat, Jul 9, 2022 at 2:32 PM James Hilliard <james.hilliard1@gmail.com> wrote:
>>>> >> >>
>>>> >> >> On Sat, Jul 9, 2022 at 2:21 PM Jose E. Marchesi
>>>> >> >> <jose.marchesi@oracle.com> wrote:
>>>> >> >> >
>>>> >> >> >
>>>> >> >> > > On Sat, Jul 9, 2022 at 11:24 AM Jose E. Marchesi
>>>> >> >> > > <jose.marchesi@oracle.com> wrote:
>>>> >> >> > >>
>>>> >> >> > >>
>>>> >> >> > >> > On Fri, Jul 8, 2022 at 12:33 PM Jose E. Marchesi
>>>> >> >> > >> > <jose.marchesi@oracle.com> wrote:
>>>> >> >> > >> >>
>>>> >> >> > >> >>
>>>> >> >> > >> >> >> On Wed, Jul 6, 2022 at 10:13 AM James Hilliard
>>>> >> >> > >> >> >> <james.hilliard1@gmail.com> wrote:
>>>> >> >> > >> >> >>>
>>>> >> >> > >> >> >>> Note I'm testing with the following patches:
>>>> >> >> > >> >> >>>
>> https://lore.kernel.org/bpf/20220706111839.1247911-1-james.hilliard1@gmail.com/
>>>> >> >> > >> >> >>>
>> https://lore.kernel.org/bpf/20220706140623.2917858-1-james.hilliard1@gmail.com/
>>>> >> >> > >> >> >>>
>>>> >> >> > >> >> >>> It would appear there's some compatibility issues with bpftool gen and
>>>> >> >> > >> >> >>> GCC, not sure what side though is wrong here:
>>>> >> >> > >> >> >>> /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>>>> >> >> > >> >> >>> gen object src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>>>> >> >> > >> >> >>> src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
>>>> >> >> > >> >> >>> libbpf: failed to find BTF info for global/extern symbol 'sd_restrictif_i'
>>>> >> >> > >> >> >>> Error: failed to link
>>>> >> >> > >> >> >>> 'src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o':
>>>> >> >> > >> >> >>> Unknown error -2 (-2)
>>>> >> >> > >> >> >>>
>>>> >> >> > >> >> >>> Relevant difference seems to be this:
>>>> >> >> > >> >> >>> GCC:
>>>> >> >> > >> >> >>> [55] FUNC 'sd_restrictif_i' type_id=47 linkage=static
>>>> >> >> > >> >> >>> Clang:
>>>> >> >> > >> >> >>> [27] FUNC 'sd_restrictif_i' type_id=26 linkage=global
>>>> >> >> > >> >> >
>>>> >> >> > >> >> > For functions GCC generates a BTF_KIND_FUNC entry, which has no linkage
>>>> >> >> > >> >> > information, or so we thought: I just looked at bpftool/btf.c and I
>>>> >> >> > >> >> > found the linkage info for function types is expected to be encoded in
>>>> >> >> > >> >> > the vlen field of BTF_KIND_FUNC entries (why not adding a btf_func
>>>> >> >> > >> >> > instead???) which is surprising to say the least.
>>>> >> >> > >> >> >
>>>> >> >> > >> >> > We are changing GCC to encode the linkage info in vlen for these types.
>>>> >> >> > >> >> > Thanks for reporting this.
>>>> >> >> > >> >>
>>>> >> >> > >> >> Patch sent to GCC upstream:
>>>> >> >> > >> >> https://gcc.gnu.org/pipermail/gcc-patches/2022-July/598090.html
>>>> >> >> > >> >
>>>> >> >> > >> > I applied that patch on top of GCC 12.1.0 and it appears to fix the
>>>> >> >> > >> > bpftool gen object bug.
>>>> >> >> > >> >
>>>> >> >> > >> > I am however now hitting a different error during skeleton generation:
>>>> >> >> > >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>>>> >> >> > >> > gen skeleton src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>>>> >> >> > >> > libbpf: elf: skipping unrecognized data section(9) .comment
>>>> >> >> > >> > libbpf: failed to alloc map 'restrict.bss' content buffer: -22
>>>> >> >> > >> > Error: failed to open BPF object file: Invalid argument
>>>> >> >> > >>
>>>> >> >> > >> What is the size of the .bss section in the object file?  Try with:
>>>> >> >> > >>
>>>> >> >> > >> $ size restrict-ifaces.bpf.o
>>>> >> >> > >
>>>> >> >> > > $ size
>>>> >> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>>>> >> >> > >    text       data        bss        dec        hex    filename
>>>> >> >> > >     386         25          0        411        19b
>>>> >> >> > >
>> output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>>>> >> >> >
>>>> >> >> > Right, so the .bss section is empty.  I see a `const volatile unsigned
>>>> >> >> > char is_allow_list = 0;' in restrict-ifaces.bpf.c, but that goes to
>>>> >> >> > .data and not to .bss, as expected.
>>>> >> >> >
>>>> >> >> > If you build restrict-ifaces.bpf.o with LLVM, is the bss still empty?  I
>>>> >> >> > don't think the code in libbpf.c even checks for this eventuality...
>>>> >> >>
>>>> >> >> LLVM version(which skeleton generation works with):
>>>> >> >> $ size restrict-ifaces.bpf.o
>>>> >> >>    text       data        bss        dec        hex    filename
>>>> >> >>     323         24          0        347        15b    restrict-ifaces.bpf.o
>>>> >> >>
>>>> >> >> $ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>>>> >> >> btf dump file restrict-ifaces.bpf.o format raw
>>>> >> >> [1] PTR '(anon)' type_id=3
>>>> >> >> [2] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
>>>> >> >> [3] ARRAY '(anon)' type_id=2 index_type_id=4 nr_elems=1
>>>> >> >> [4] INT '__ARRAY_SIZE_TYPE__' size=4 bits_offset=0 nr_bits=32 encoding=(none)
>>>> >> >> [5] PTR '(anon)' type_id=6
>>>> >> >> [6] TYPEDEF '__u32' type_id=7
>>>> >> >> [7] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
>>>> >> >> [8] PTR '(anon)' type_id=9
>>>> >> >> [9] TYPEDEF '__u8' type_id=10
>>>> >> >> [10] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=(none)
>>>> >> >> [11] STRUCT '(anon)' size=24 vlen=3
>>>> >> >>     'type' type_id=1 bits_offset=0
>>>> >> >>     'key' type_id=5 bits_offset=64
>>>> >> >>     'value' type_id=8 bits_offset=128
>>>> >> >> [12] VAR 'sd_restrictif' type_id=11, linkage=global
>>>> >> >> [13] PTR '(anon)' type_id=14
>>>> >> >> [14] CONST '(anon)' type_id=15
>>>> >> >> [15] STRUCT '__sk_buff' size=192 vlen=33
>>>> >> >>     'len' type_id=6 bits_offset=0
>>>> >> >>     'pkt_type' type_id=6 bits_offset=32
>>>> >> >>     'mark' type_id=6 bits_offset=64
>>>> >> >>     'queue_mapping' type_id=6 bits_offset=96
>>>> >> >>     'protocol' type_id=6 bits_offset=128
>>>> >> >>     'vlan_present' type_id=6 bits_offset=160
>>>> >> >>     'vlan_tci' type_id=6 bits_offset=192
>>>> >> >>     'vlan_proto' type_id=6 bits_offset=224
>>>> >> >>     'priority' type_id=6 bits_offset=256
>>>> >> >>     'ingress_ifindex' type_id=6 bits_offset=288
>>>> >> >>     'ifindex' type_id=6 bits_offset=320
>>>> >> >>     'tc_index' type_id=6 bits_offset=352
>>>> >> >>     'cb' type_id=16 bits_offset=384
>>>> >> >>     'hash' type_id=6 bits_offset=544
>>>> >> >>     'tc_classid' type_id=6 bits_offset=576
>>>> >> >>     'data' type_id=6 bits_offset=608
>>>> >> >>     'data_end' type_id=6 bits_offset=640
>>>> >> >>     'napi_id' type_id=6 bits_offset=672
>>>> >> >>     'family' type_id=6 bits_offset=704
>>>> >> >>     'remote_ip4' type_id=6 bits_offset=736
>>>> >> >>     'local_ip4' type_id=6 bits_offset=768
>>>> >> >>     'remote_ip6' type_id=17 bits_offset=800
>>>> >> >>     'local_ip6' type_id=17 bits_offset=928
>>>> >> >>     'remote_port' type_id=6 bits_offset=1056
>>>> >> >>     'local_port' type_id=6 bits_offset=1088
>>>> >> >>     'data_meta' type_id=6 bits_offset=1120
>>>> >> >>     '(anon)' type_id=18 bits_offset=1152
>>>> >> >>     'tstamp' type_id=20 bits_offset=1216
>>>> >> >>     'wire_len' type_id=6 bits_offset=1280
>>>> >> >>     'gso_segs' type_id=6 bits_offset=1312
>>>> >> >>     '(anon)' type_id=22 bits_offset=1344
>>>> >> >>     'gso_size' type_id=6 bits_offset=1408
>>>> >> >>     'hwtstamp' type_id=20 bits_offset=1472
>>>> >> >> [16] ARRAY '(anon)' type_id=6 index_type_id=4 nr_elems=5
>>>> >> >> [17] ARRAY '(anon)' type_id=6 index_type_id=4 nr_elems=4
>>>> >> >> [18] UNION '(anon)' size=8 vlen=1
>>>> >> >>     'flow_keys' type_id=19 bits_offset=0
>>>> >> >> [19] PTR '(anon)' type_id=34
>>>> >> >> [20] TYPEDEF '__u64' type_id=21
>>>> >> >> [21] INT 'unsigned long long' size=8 bits_offset=0 nr_bits=64 encoding=(none)
>>>> >> >> [22] UNION '(anon)' size=8 vlen=1
>>>> >> >>     'sk' type_id=23 bits_offset=0
>>>> >> >> [23] PTR '(anon)' type_id=35
>>>> >> >> [24] FUNC_PROTO '(anon)' ret_type_id=2 vlen=1
>>>> >> >>     'sk' type_id=13
>>>> >> >> [25] FUNC 'sd_restrictif_e' type_id=24 linkage=global
>>>> >> >> [26] FUNC 'sd_restrictif_i' type_id=24 linkage=global
>>>> >> >> [27] CONST '(anon)' type_id=28
>>>> >> >> [28] VOLATILE '(anon)' type_id=9
>>>> >> >> [29] VAR 'is_allow_list' type_id=27, linkage=global
>>>> >> >> [30] CONST '(anon)' type_id=31
>>>> >> >> [31] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=SIGNED
>>>> >> >> [32] ARRAY '(anon)' type_id=30 index_type_id=4 nr_elems=18
>>>> >> >> [33] VAR '_license' type_id=32, linkage=static
>>>> >> >> [34] FWD 'bpf_flow_keys' fwd_kind=struct
>>>> >> >> [35] FWD 'bpf_sock' fwd_kind=struct
>>>> >> >> [36] DATASEC '.rodata' size=1 vlen=1
>>>> >> >>     type_id=29 offset=0 size=1 (VAR 'is_allow_list')
>>>> >> >> [37] DATASEC 'license' size=18 vlen=1
>>>> >> >>     type_id=33 offset=0 size=18 (VAR '_license')
>>>> >> >> [38] DATASEC '.maps' size=24 vlen=1
>>>> >> >>     type_id=12 offset=0 size=24 (VAR 'sd_restrictif')
>>>> >> >>
>>>> >> >
>>>> >> > Skeleton generation debug output for GCC(failing) and LLVM(working)
>>>> >> > which may be helpful:
>>>> >>
>>>> >> Indeed it was helpful :)
>>>> >>
>>>> >> The GNU assembler generates an empty .bss section.  This is a well
>>>> >> established behavior in GAS that happens in all supported targets.
>>>> >>
>>>> >> The LLVM assembler doesn't generate an empty .bss section.
>>>> >>
>>>> >> bpftool chokes on the empty .bss section.
>>>> >>
>>>> >> In this case I would suggest to fix bpf_object__init_global_data_maps in
>>>> >> order to skip empty sections.
>>>> >>
>>>> >> Something like this:
>>>> >
>>>> > Hmm, that seems to segfault:
>>>>
>>>> Yes, I see in bpf_object__elf_collect that sec_desc->data is not
>>>> initialized when a section is not recognized.  In this case, this
>>>> happens with .comment.
>>>>
>>>> All right then:
>>>>
>>>> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
>>>> index e89cc9c885b3..887b78780099 100644
>>>> --- a/tools/lib/bpf/libbpf.c
>>>> +++ b/tools/lib/bpf/libbpf.c
>>>> @@ -1591,6 +1591,10 @@ static int bpf_object__init_global_data_maps(struct bpf_object *obj)
>>>>         for (sec_idx = 1; sec_idx < obj->efile.sec_cnt; sec_idx++) {
>>>>                 sec_desc = &obj->efile.secs[sec_idx];
>>>>
>>>> +                /* Skip recognized sections with size 0.  */
>>>> +                if (sec_desc->data && sec_desc->data->d_size == 0)
>>>> +                  continue;
>>>> +
>>>>                 switch (sec_desc->sec_type) {
>>>>                 case SEC_DATA:
>>>>                         sec_name = elf_sec_name(obj, elf_sec_by_idx(obj, sec_idx));
>>>
>>> Ok, skeleton is now getting generated successfully, however it differs from the
>>> clang version so there's a build error when we include/use the header:
>>> ../src/core/restrict-ifaces.c: In function ‘prepare_restrict_ifaces_bpf’:
>>> ../src/core/restrict-ifaces.c:45:14: error: ‘struct
>>> restrict_ifaces_bpf’ has no member named ‘rodata’; did you mean
>>> ‘data’?
>>>    45 |         obj->rodata->is_allow_list = is_allow_list;
>>>       |              ^~~~~~
>>>       |              data
>>>
>>> The issue appears to be that clang generates "rodata" members in
>>> restrict_ifaces_bpf while with gcc we get "data" members instead.
>>
>> This is because the BPF GCC port is putting the
>>
>>   const volatile unsigned char is_allow_list = 0;
>>
>> in a .data section instead of .rodata, due to the `volatile'.  The
>> x86_64 GCC seems to use .rodata.
>>
>> Looking at why the PBF port does this...
>
> So, turns out GCC puts zero-initialized `const volatile' variables in
> .data sections (and not .rodata) in all the targets I have tried, like
> x86_64 and aarch64.
>
> So this is a LLVM and GCC divergence :/

See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25521.

You may try, as a workaround:

__attribute__((section(".rodata"))) const volatile unsigned char is_allow_list = 0;

But that will use permissions "aw" for the .rodata section (and you will
get a warning from the assembler.)  It may be problematic for libbpf.

>>> Differences below:
>>>
>>> GCC:
>>> $ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>>> --debug gen skeleton
>>> output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>>> libbpf: loading object 'restrict_ifaces_bpf' from buffer
>>> libbpf: elf: section(2) .symtab, size 336, link 1, flags 0, type=2
>>> libbpf: elf: section(3) .data, size 1, link 0, flags 3, type=1
>>> libbpf: elf: section(4) .bss, size 0, link 0, flags 3, type=8
>>> libbpf: elf: section(5) cgroup_skb/egress, size 184, link 0, flags 6, type=1
>>> libbpf: sec 'cgroup_skb/egress': found program 'sd_restrictif_e' at
>>> insn offset 0 (0 bytes), code size 23 insns (184 bytes)
>>> libbpf: elf: section(6) cgroup_skb/ingress, size 184, link 0, flags 6, type=1
>>> libbpf: sec 'cgroup_skb/ingress': found program 'sd_restrictif_i' at
>>> insn offset 0 (0 bytes), code size 23 insns (184 bytes)
>>> libbpf: elf: section(7) license, size 18, link 0, flags 2, type=1
>>> libbpf: license of restrict_ifaces_bpf is LGPL-2.1-or-later
>>> libbpf: elf: section(8) .maps, size 24, link 0, flags 3, type=1
>>> libbpf: elf: section(9) .comment, size 49, link 0, flags 30, type=1
>>> libbpf: elf: skipping unrecognized data section(9) .comment
>>> libbpf: elf: section(10) .relcgroup_skb/egress, size 32, link 2, flags
>>> 40, type=9
>>> libbpf: elf: section(11) .relcgroup_skb/ingress, size 32, link 2,
>>> flags 40, type=9
>>> libbpf: elf: section(12) .BTF, size 3606, link 0, flags 0, type=1
>>> libbpf: looking for externs among 14 symbols...
>>> libbpf: collected 0 externs total
>>> libbpf: map 'sd_restrictif': at sec_idx 8, offset 0.
>>> libbpf: map 'sd_restrictif': found type = 1.
>>> libbpf: map 'sd_restrictif': found key [12], sz = 4.
>>> libbpf: map 'sd_restrictif': found value [3], sz = 1.
>>> libbpf: map 'restrict.data' (global data): at sec_idx 3, offset 0, flags 400.
>>> libbpf: map 1 is "restrict.data"
>>> libbpf: sec '.relcgroup_skb/egress': collecting relocation for
>>> section(5) 'cgroup_skb/egress'
>>> libbpf: sec '.relcgroup_skb/egress': relo #0: insn #4 against 'sd_restrictif'
>>> libbpf: prog 'sd_restrictif_e': found map 0 (sd_restrictif, sec 8, off
>>> 0) for insn #4
>>> libbpf: sec '.relcgroup_skb/egress': relo #1: insn #7 against 'is_allow_list'
>>> libbpf: prog 'sd_restrictif_e': found data map 1 (restrict.data, sec
>>> 3, off 0) for insn 7
>>> libbpf: sec '.relcgroup_skb/ingress': collecting relocation for
>>> section(6) 'cgroup_skb/ingress'
>>> libbpf: sec '.relcgroup_skb/ingress': relo #0: insn #4 against 'sd_restrictif'
>>> libbpf: prog 'sd_restrictif_i': found map 0 (sd_restrictif, sec 8, off
>>> 0) for insn #4
>>> libbpf: sec '.relcgroup_skb/ingress': relo #1: insn #7 against 'is_allow_list'
>>> libbpf: prog 'sd_restrictif_i': found data map 1 (restrict.data, sec
>>> 3, off 0) for insn 7
>>> /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
>>>
>>> /* THIS FILE IS AUTOGENERATED BY BPFTOOL! */
>>> #ifndef __RESTRICT_IFACES_BPF_SKEL_H__
>>> #define __RESTRICT_IFACES_BPF_SKEL_H__
>>>
>>> #include <errno.h>
>>> #include <stdlib.h>
>>> #include <bpf/libbpf.h>
>>>
>>> struct restrict_ifaces_bpf {
>>>     struct bpf_object_skeleton *skeleton;
>>>     struct bpf_object *obj;
>>>     struct {
>>>         struct bpf_map *sd_restrictif;
>>>         struct bpf_map *data;
>>>     } maps;
>>>     struct {
>>>         struct bpf_program *sd_restrictif_e;
>>>         struct bpf_program *sd_restrictif_i;
>>>     } progs;
>>>     struct {
>>>         struct bpf_link *sd_restrictif_e;
>>>         struct bpf_link *sd_restrictif_i;
>>>     } links;
>>>     struct restrict_ifaces_bpf__data {
>>>         __u8 is_allow_list;
>>>     } *data;
>>>
>>> #ifdef __cplusplus
>>>     static inline struct restrict_ifaces_bpf *open(const struct
>>> bpf_object_open_opts *opts = nullptr);
>>>     static inline struct restrict_ifaces_bpf *open_and_load();
>>>     static inline int load(struct restrict_ifaces_bpf *skel);
>>>     static inline int attach(struct restrict_ifaces_bpf *skel);
>>>     static inline void detach(struct restrict_ifaces_bpf *skel);
>>>     static inline void destroy(struct restrict_ifaces_bpf *skel);
>>>     static inline const void *elf_bytes(size_t *sz);
>>> #endif /* __cplusplus */
>>> };
>>>
>>> static void
>>> restrict_ifaces_bpf__destroy(struct restrict_ifaces_bpf *obj)
>>> {
>>>     if (!obj)
>>>         return;
>>>     if (obj->skeleton)
>>>         bpf_object__destroy_skeleton(obj->skeleton);
>>>     free(obj);
>>> }
>>>
>>> static inline int
>>> restrict_ifaces_bpf__create_skeleton(struct restrict_ifaces_bpf *obj);
>>>
>>> static inline struct restrict_ifaces_bpf *
>>> restrict_ifaces_bpf__open_opts(const struct bpf_object_open_opts *opts)
>>> {
>>>     struct restrict_ifaces_bpf *obj;
>>>     int err;
>>>
>>>     obj = (struct restrict_ifaces_bpf *)calloc(1, sizeof(*obj));
>>>     if (!obj) {
>>>         errno = ENOMEM;
>>>         return NULL;
>>>     }
>>>
>>>     err = restrict_ifaces_bpf__create_skeleton(obj);
>>>     if (err)
>>>         goto err_out;
>>>
>>>     err = bpf_object__open_skeleton(obj->skeleton, opts);
>>>     if (err)
>>>         goto err_out;
>>>
>>>     return obj;
>>> err_out:
>>>     restrict_ifaces_bpf__destroy(obj);
>>>     errno = -err;
>>>     return NULL;
>>> }
>>>
>>> static inline struct restrict_ifaces_bpf *
>>> restrict_ifaces_bpf__open(void)
>>> {
>>>     return restrict_ifaces_bpf__open_opts(NULL);
>>> }
>>>
>>> static inline int
>>> restrict_ifaces_bpf__load(struct restrict_ifaces_bpf *obj)
>>> {
>>>     return bpf_object__load_skeleton(obj->skeleton);
>>> }
>>>
>>> static inline struct restrict_ifaces_bpf *
>>> restrict_ifaces_bpf__open_and_load(void)
>>> {
>>>     struct restrict_ifaces_bpf *obj;
>>>     int err;
>>>
>>>     obj = restrict_ifaces_bpf__open();
>>>     if (!obj)
>>>         return NULL;
>>>     err = restrict_ifaces_bpf__load(obj);
>>>     if (err) {
>>>         restrict_ifaces_bpf__destroy(obj);
>>>         errno = -err;
>>>         return NULL;
>>>     }
>>>     return obj;
>>> }
>>>
>>> static inline int
>>> restrict_ifaces_bpf__attach(struct restrict_ifaces_bpf *obj)
>>> {
>>>     return bpf_object__attach_skeleton(obj->skeleton);
>>> }
>>>
>>> static inline void
>>> restrict_ifaces_bpf__detach(struct restrict_ifaces_bpf *obj)
>>> {
>>>     return bpf_object__detach_skeleton(obj->skeleton);
>>> }
>>>
>>> static inline const void *restrict_ifaces_bpf__elf_bytes(size_t *sz);
>>>
>>> static inline int
>>> restrict_ifaces_bpf__create_skeleton(struct restrict_ifaces_bpf *obj)
>>> {
>>>     struct bpf_object_skeleton *s;
>>>     int err;
>>>
>>>     s = (struct bpf_object_skeleton *)calloc(1, sizeof(*s));
>>>     if (!s)    {
>>>         err = -ENOMEM;
>>>         goto err;
>>>     }
>>>
>>>     s->sz = sizeof(*s);
>>>     s->name = "restrict_ifaces_bpf";
>>>     s->obj = &obj->obj;
>>>
>>>     /* maps */
>>>     s->map_cnt = 2;
>>>     s->map_skel_sz = sizeof(*s->maps);
>>>     s->maps = (struct bpf_map_skeleton *)calloc(s->map_cnt, s->map_skel_sz);
>>>     if (!s->maps) {
>>>         err = -ENOMEM;
>>>         goto err;
>>>     }
>>>
>>>     s->maps[0].name = "sd_restrictif";
>>>     s->maps[0].map = &obj->maps.sd_restrictif;
>>>
>>>     s->maps[1].name = "restrict.data";
>>>     s->maps[1].map = &obj->maps.data;
>>>     s->maps[1].mmaped = (void **)&obj->data;
>>>
>>>     /* programs */
>>>     s->prog_cnt = 2;
>>>     s->prog_skel_sz = sizeof(*s->progs);
>>>     s->progs = (struct bpf_prog_skeleton *)calloc(s->prog_cnt, s->prog_skel_sz);
>>>     if (!s->progs) {
>>>         err = -ENOMEM;
>>>         goto err;
>>>     }
>>>
>>>     s->progs[0].name = "sd_restrictif_e";
>>>     s->progs[0].prog = &obj->progs.sd_restrictif_e;
>>>     s->progs[0].link = &obj->links.sd_restrictif_e;
>>>
>>>     s->progs[1].name = "sd_restrictif_i";
>>>     s->progs[1].prog = &obj->progs.sd_restrictif_i;
>>>     s->progs[1].link = &obj->links.sd_restrictif_i;
>>>
>>>     s->data = (void *)restrict_ifaces_bpf__elf_bytes(&s->data_sz);
>>>
>>>     obj->skeleton = s;
>>>     return 0;
>>> err:
>>>     bpf_object__destroy_skeleton(s);
>>>     return err;
>>> }
>>>
>>> static inline const void *restrict_ifaces_bpf__elf_bytes(size_t *sz)
>>> {
>>>     *sz = 5616;
>>>     return (const void *)"\
>>> \x7f\x45\x4c\x46\x02\x01\x01\0\0\0\0\0\0\0\0\0\x01\0\xf7\0\x01\0\0\0\0\0\0\0\0\
>>> \0\0\0\0\0\0\0\0\0\0\0\xb0\x12\0\0\0\0\0\0\0\0\0\0\x40\0\0\0\0\0\x40\0\x0d\0\
>>> \x01\0\0\x2e\x73\x74\x72\x74\x61\x62\0\x2e\x73\x79\x6d\x74\x61\x62\0\x2e\x64\
>>> \x61\x74\x61\0\x2e\x62\x73\x73\0\x63\x67\x72\x6f\x75\x70\x5f\x73\x6b\x62\x2f\
>>> \x65\x67\x72\x65\x73\x73\0\x63\x67\x72\x6f\x75\x70\x5f\x73\x6b\x62\x2f\x69\x6e\
>>> \x67\x72\x65\x73\x73\0\x6c\x69\x63\x65\x6e\x73\x65\0\x2e\x6d\x61\x70\x73\0\x2e\
>>> \x63\x6f\x6d\x6d\x65\x6e\x74\0\x72\x65\x73\x74\x72\x69\x63\x74\x2d\x69\x66\x61\
>>> \x63\x65\x73\x2e\x62\x70\x66\x2e\x63\0\x5f\x6c\x69\x63\x65\x6e\x73\x65\0\x73\
>>> \x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\x5f\x65\0\x73\x64\x5f\x72\x65\
>>> \x73\x74\x72\x69\x63\x74\x69\x66\0\x69\x73\x5f\x61\x6c\x6c\x6f\x77\x5f\x6c\x69\
>>> \x73\x74\0\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\x5f\x69\0\x2e\
>>> \x72\x65\x6c\x63\x67\x72\x6f\x75\x70\x5f\x73\x6b\x62\x2f\x65\x67\x72\x65\x73\
>>> \x73\0\x2e\x72\x65\x6c\x63\x67\x72\x6f\x75\x70\x5f\x73\x6b\x62\x2f\x69\x6e\x67\
>>> \x72\x65\x73\x73\0\x2e\x42\x54\x46\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>> \0\0\0\0\0\0\x58\0\0\0\x04\0\xf1\xff\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>> \x03\0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x03\0\x04\0\0\0\0\0\0\0\0\
>>> \0\0\0\0\0\0\0\0\0\0\0\0\0\x03\0\x05\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>> \x03\0\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x03\0\x07\0\0\0\0\0\0\0\0\
>>> \0\0\0\0\0\0\0\0\0\x6e\0\0\0\x01\0\x07\0\0\0\0\0\0\0\0\0\x12\0\0\0\0\0\0\0\0\0\
>>> \0\0\x03\0\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x03\0\x09\0\0\0\0\0\0\
>>> \0\0\0\0\0\0\0\0\0\0\0\x77\0\0\0\x12\0\x05\0\0\0\0\0\0\0\0\0\xb8\0\0\0\0\0\0\0\
>>> \x87\0\0\0\x11\0\x08\0\0\0\0\0\0\0\0\0\x18\0\0\0\0\0\0\0\x95\0\0\0\x11\0\x03\0\
>>> \0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\xa3\0\0\0\x12\0\x06\0\0\0\0\0\0\0\0\0\xb8\0\
>>> \0\0\0\0\0\0\0\0\0\0\0\0\0\0\x61\x10\x28\0\0\0\0\0\x63\x0a\xfc\xff\0\0\0\0\xbf\
>>> \xa2\0\0\0\0\0\0\x07\x02\0\0\xfc\xff\xff\xff\x18\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>> \0\x85\0\0\0\x01\0\0\0\x18\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x71\x13\0\0\0\0\0\0\
>>> \x57\x03\0\0\xff\0\0\0\x15\x03\x05\0\0\0\0\0\xbf\x02\0\0\0\0\0\0\x87\x02\0\0\0\
>>> \0\0\0\x4f\x20\0\0\0\0\0\0\x77\0\0\0\x3f\0\0\0\x95\0\0\0\0\0\0\0\xb7\x01\0\0\
>>> \x01\0\0\0\x15\0\x01\0\0\0\0\0\xbf\x31\0\0\0\0\0\0\xbf\x10\0\0\0\0\0\0\x57\0\0\
>>> \0\x01\0\0\0\x95\0\0\0\0\0\0\0\x61\x10\x28\0\0\0\0\0\x63\x0a\xfc\xff\0\0\0\0\
>>> \xbf\xa2\0\0\0\0\0\0\x07\x02\0\0\xfc\xff\xff\xff\x18\x01\0\0\0\0\0\0\0\0\0\0\0\
>>> \0\0\0\x85\0\0\0\x01\0\0\0\x18\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x71\x13\0\0\0\0\
>>> \0\0\x57\x03\0\0\xff\0\0\0\x15\x03\x05\0\0\0\0\0\xbf\x02\0\0\0\0\0\0\x87\x02\0\
>>> \0\0\0\0\0\x4f\x20\0\0\0\0\0\0\x77\0\0\0\x3f\0\0\0\x95\0\0\0\0\0\0\0\xb7\x01\0\
>>> \0\x01\0\0\0\x15\0\x01\0\0\0\0\0\xbf\x31\0\0\0\0\0\0\xbf\x10\0\0\0\0\0\0\x57\0\
>>> \0\0\x01\0\0\0\x95\0\0\0\0\0\0\0\x4c\x47\x50\x4c\x2d\x32\x2e\x31\x2d\x6f\x72\
>>> \x2d\x6c\x61\x74\x65\x72\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>> \0\0\0\0\0\x47\x43\x43\x3a\x20\x28\x42\x75\x69\x6c\x64\x72\x6f\x6f\x74\x20\x32\
>>> \x30\x32\x32\x2e\x30\x35\x2d\x31\x33\x32\x2d\x67\x35\x32\x38\x62\x35\x61\x36\
>>> \x35\x66\x36\x29\x20\x31\x32\x2e\x31\x2e\x30\0\0\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\
>>> \x01\0\0\0\x0b\0\0\0\x38\0\0\0\0\0\0\0\x01\0\0\0\x0c\0\0\0\x20\0\0\0\0\0\0\0\
>>> \x01\0\0\0\x0b\0\0\0\x38\0\0\0\0\0\0\0\x01\0\0\0\x0c\0\0\0\x9f\xeb\x01\0\x18\0\
>>> \0\0\0\0\0\0\x9c\x07\0\0\x9c\x07\0\0\x62\x06\0\0\x01\0\0\0\0\0\0\x01\x01\0\0\0\
>>> \x08\0\0\x03\x0d\0\0\0\0\0\0\x01\x01\0\0\0\x08\0\0\x02\x1b\0\0\0\0\0\0\x08\x02\
>>> \0\0\0\0\0\0\0\0\0\0\x0a\x03\0\0\0\0\0\0\0\0\0\0\x09\x04\0\0\0\x20\0\0\0\0\0\0\
>>> \x01\x02\0\0\0\x10\0\0\x01\x2a\0\0\0\0\0\0\x01\x02\0\0\0\x10\0\0\0\x3d\0\0\0\0\
>>> \0\0\x08\x07\0\0\0\x43\0\0\0\0\0\0\x01\x04\0\0\0\x20\0\0\x01\x47\0\0\0\0\0\0\
>>> \x08\x09\0\0\0\x4d\0\0\0\0\0\0\x01\x04\0\0\0\x20\0\0\0\x5a\0\0\0\0\0\0\x08\x0b\
>>> \0\0\0\x60\0\0\0\0\0\0\x01\x08\0\0\0\x40\0\0\x01\x6e\0\0\0\0\0\0\x01\x08\0\0\0\
>>> \x40\0\0\0\x85\0\0\0\0\0\0\x08\x0e\0\0\0\x8b\0\0\0\0\0\0\x01\x08\0\0\0\x40\0\0\
>>> \0\x9d\0\0\0\0\0\0\x01\x08\0\0\0\x40\0\0\x01\xa6\0\0\0\0\0\0\x01\x01\0\0\0\x08\
>>> \0\0\x03\0\0\0\0\0\0\0\x0a\x12\0\0\0\xab\0\0\0\0\0\0\x08\x08\0\0\0\xb2\0\0\0\0\
>>> \0\0\x08\x0c\0\0\0\xb9\0\0\0\x1f\0\0\x06\x04\0\0\0\xc6\0\0\0\0\0\0\0\xda\0\0\0\
>>> \x01\0\0\0\xec\0\0\0\x02\0\0\0\xff\0\0\0\x03\0\0\0\x17\x01\0\0\x04\0\0\0\x35\
>>> \x01\0\0\x05\0\0\0\x4e\x01\0\0\x06\0\0\0\x68\x01\0\0\x07\0\0\0\x81\x01\0\0\x08\
>>> \0\0\0\x9b\x01\0\0\x09\0\0\0\xb1\x01\0\0\x0a\0\0\0\xce\x01\0\0\x0b\0\0\0\xe4\
>>> \x01\0\0\x0c\0\0\0\xff\x01\0\0\x0d\0\0\0\x19\x02\0\0\x0e\0\0\0\x2d\x02\0\0\x0f\
>>> \0\0\0\x42\x02\0\0\x10\0\0\0\x56\x02\0\0\x11\0\0\0\x6a\x02\0\0\x12\0\0\0\x80\
>>> \x02\0\0\x13\0\0\0\x9c\x02\0\0\x14\0\0\0\xbd\x02\0\0\x15\0\0\0\xe0\x02\0\0\x16\
>>> \0\0\0\xf3\x02\0\0\x17\0\0\0\x06\x03\0\0\x18\0\0\0\x1e\x03\0\0\x19\0\0\0\x37\
>>> \x03\0\0\x1a\0\0\0\x4f\x03\0\0\x1b\0\0\0\x64\x03\0\0\x1c\0\0\0\x7f\x03\0\0\x1d\
>>> \0\0\0\x99\x03\0\0\x1e\0\0\0\0\0\0\0\x01\0\0\x05\x08\0\0\0\xb3\x03\0\0\x1d\0\0\
>>> \0\0\0\0\0\xbd\x03\0\0\x0d\0\0\x04\x38\0\0\0\xcb\x03\0\0\x08\0\0\0\0\0\0\0\xd1\
>>> \x03\0\0\x08\0\0\0\x10\0\0\0\xd7\x03\0\0\x08\0\0\0\x20\0\0\0\xe2\x03\0\0\x03\0\
>>> \0\0\x30\0\0\0\xea\x03\0\0\x03\0\0\0\x38\0\0\0\xf8\x03\0\0\x03\0\0\0\x40\0\0\0\
>>> \x01\x04\0\0\x03\0\0\0\x48\0\0\0\x0a\x04\0\0\x14\0\0\0\x50\0\0\0\x12\x04\0\0\
>>> \x14\0\0\0\x60\0\0\0\x18\x04\0\0\x14\0\0\0\x70\0\0\0\0\0\0\0\x19\0\0\0\x80\0\0\
>>> \0\x1e\x04\0\0\x0c\0\0\0\x80\x01\0\0\x24\x04\0\0\x15\0\0\0\xa0\x01\0\0\0\0\0\0\
>>> \x02\0\0\x05\x20\0\0\0\0\0\0\0\x1a\0\0\0\0\0\0\0\0\0\0\0\x1b\0\0\0\0\0\0\0\0\0\
>>> \0\0\x02\0\0\x04\x08\0\0\0\x2f\x04\0\0\x15\0\0\0\0\0\0\0\x38\x04\0\0\x15\0\0\0\
>>> \x20\0\0\0\0\0\0\0\x02\0\0\x04\x20\0\0\0\x41\x04\0\0\x1c\0\0\0\0\0\0\0\x4a\x04\
>>> \0\0\x1c\0\0\0\x80\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x0c\0\0\0\x10\0\0\0\x04\0\0\
>>> \0\0\0\0\0\0\0\0\x02\x18\0\0\0\0\0\0\0\x01\0\0\x05\x08\0\0\0\x53\x04\0\0\x20\0\
>>> \0\0\0\0\0\0\x56\x04\0\0\x0e\0\0\x04\x50\0\0\0\x5f\x04\0\0\x0c\0\0\0\0\0\0\0\
>>> \x6c\x04\0\0\x0c\0\0\0\x20\0\0\0\x73\x04\0\0\x0c\0\0\0\x40\0\0\0\x78\x04\0\0\
>>> \x0c\0\0\0\x60\0\0\0\x81\x04\0\0\x0c\0\0\0\x80\0\0\0\x86\x04\0\0\x0c\0\0\0\xa0\
>>> \0\0\0\x8f\x04\0\0\x0c\0\0\0\xc0\0\0\0\x97\x04\0\0\x1c\0\0\0\xe0\0\0\0\x9f\x04\
>>> \0\0\x0c\0\0\0\x60\x01\0\0\xa8\x04\0\0\x14\0\0\0\x80\x01\0\0\xb1\x04\0\0\x0c\0\
>>> \0\0\xa0\x01\0\0\xb9\x04\0\0\x1c\0\0\0\xc0\x01\0\0\xc1\x04\0\0\x0c\0\0\0\x40\
>>> \x02\0\0\xc7\x04\0\0\x0a\0\0\0\x60\x02\0\0\0\0\0\0\0\0\0\x02\x1f\0\0\0\xd8\x04\
>>> \0\0\x21\0\0\x04\xc0\0\0\0\xe2\x04\0\0\x0c\0\0\0\0\0\0\0\xe6\x04\0\0\x0c\0\0\0\
>>> \x20\0\0\0\x81\x04\0\0\x0c\0\0\0\x40\0\0\0\xef\x04\0\0\x0c\0\0\0\x60\0\0\0\x78\
>>> \x04\0\0\x0c\0\0\0\x80\0\0\0\xfd\x04\0\0\x0c\0\0\0\xa0\0\0\0\x0a\x05\0\0\x0c\0\
>>> \0\0\xc0\0\0\0\x13\x05\0\0\x0c\0\0\0\xe0\0\0\0\x86\x04\0\0\x0c\0\0\0\0\x01\0\0\
>>> \x1e\x05\0\0\x0c\0\0\0\x20\x01\0\0\x2e\x05\0\0\x0c\0\0\0\x40\x01\0\0\x36\x05\0\
>>> \0\x0c\0\0\0\x60\x01\0\0\x3f\x05\0\0\x22\0\0\0\x80\x01\0\0\x42\x05\0\0\x0c\0\0\
>>> \0\x20\x02\0\0\x47\x05\0\0\x0c\0\0\0\x40\x02\0\0\x52\x05\0\0\x0c\0\0\0\x60\x02\
>>> \0\0\x57\x05\0\0\x0c\0\0\0\x80\x02\0\0\x60\x05\0\0\x0c\0\0\0\xa0\x02\0\0\x6c\
>>> \x04\0\0\x0c\0\0\0\xc0\x02\0\0\x68\x05\0\0\x0c\0\0\0\xe0\x02\0\0\x73\x05\0\0\
>>> \x0c\0\0\0\0\x03\0\0\x7d\x05\0\0\x1c\0\0\0\x20\x03\0\0\x88\x05\0\0\x1c\0\0\0\
>>> \xa0\x03\0\0\x92\x05\0\0\x0c\0\0\0\x20\x04\0\0\x9e\x05\0\0\x0c\0\0\0\x40\x04\0\
>>> \0\xa9\x05\0\0\x0c\0\0\0\x60\x04\0\0\0\0\0\0\x17\0\0\0\x80\x04\0\0\xb3\x05\0\0\
>>> \x0f\0\0\0\xc0\x04\0\0\xba\x05\0\0\x0c\0\0\0\0\x05\0\0\xc3\x05\0\0\x0c\0\0\0\
>>> \x20\x05\0\0\0\0\0\0\x1e\0\0\0\x40\x05\0\0\xcc\x05\0\0\x0c\0\0\0\x80\x05\0\0\
>>> \xd5\x05\0\0\x0f\0\0\0\xc0\x05\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x0c\0\0\0\x10\0\0\
>>> \0\x05\0\0\0\0\0\0\0\0\0\0\x0a\x21\0\0\0\0\0\0\0\0\0\0\x02\0\0\0\0\0\0\0\0\x03\
>>> \0\0\x04\x18\0\0\0\x73\x04\0\0\x27\0\0\0\0\0\0\0\xde\x05\0\0\x28\0\0\0\x40\0\0\
>>> \0\xe2\x05\0\0\x29\0\0\0\x80\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x09\0\0\0\x10\0\0\
>>> \0\x01\0\0\0\0\0\0\0\0\0\0\x02\x26\0\0\0\0\0\0\0\0\0\0\x02\x0c\0\0\0\0\0\0\0\0\
>>> \0\0\x02\x03\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x13\0\0\0\x10\0\0\0\x12\0\0\0\0\0\
>>> \0\0\0\0\0\x0a\x2a\0\0\0\0\0\0\0\x02\0\0\x0d\x24\0\0\0\0\0\0\0\x24\0\0\0\0\0\0\
>>> \0\x2e\0\0\0\0\0\0\0\0\0\0\x0a\0\0\0\0\0\0\0\0\0\0\0\x02\x2d\0\0\0\0\0\0\0\x01\
>>> \0\0\x0d\x09\0\0\0\x53\x04\0\0\x30\0\0\0\0\0\0\0\0\0\0\x02\x23\0\0\0\xe8\x05\0\
>>> \0\0\0\0\x0e\x2b\0\0\0\0\0\0\0\xf1\x05\0\0\0\0\0\x0e\x05\0\0\0\x01\0\0\0\xff\
>>> \x05\0\0\0\0\0\x0e\x25\0\0\0\x01\0\0\0\x0d\x06\0\0\x01\0\0\x0c\x2f\0\0\0\x1d\
>>> \x06\0\0\x01\0\0\x0c\x2f\0\0\0\x2d\x06\0\0\0\0\0\x0c\x2f\0\0\0\x4e\x06\0\0\x01\
>>> \0\0\x0f\x01\0\0\0\x32\0\0\0\0\0\0\0\x01\0\0\0\x54\x06\0\0\x01\0\0\x0f\x12\0\0\
>>> \0\x31\0\0\0\0\0\0\0\x12\0\0\0\x5c\x06\0\0\x01\0\0\x0f\x18\0\0\0\x33\0\0\0\0\0\
>>> \0\0\x18\0\0\0\0\x73\x69\x67\x6e\x65\x64\x20\x63\x68\x61\x72\0\x75\x6e\x73\x69\
>>> \x67\x6e\x65\x64\x20\x63\x68\x61\x72\0\x5f\x5f\x75\x38\0\x73\x68\x6f\x72\x74\
>>> \x20\x69\x6e\x74\0\x73\x68\x6f\x72\x74\x20\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\
>>> \x69\x6e\x74\0\x5f\x5f\x75\x31\x36\0\x69\x6e\x74\0\x5f\x5f\x73\x33\x32\0\x75\
>>> \x6e\x73\x69\x67\x6e\x65\x64\x20\x69\x6e\x74\0\x5f\x5f\x75\x33\x32\0\x6c\x6f\
>>> \x6e\x67\x20\x6c\x6f\x6e\x67\x20\x69\x6e\x74\0\x6c\x6f\x6e\x67\x20\x6c\x6f\x6e\
>>> \x67\x20\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x69\x6e\x74\0\x5f\x5f\x75\x36\x34\
>>> \0\x6c\x6f\x6e\x67\x20\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x69\x6e\x74\0\x6c\
>>> \x6f\x6e\x67\x20\x69\x6e\x74\0\x63\x68\x61\x72\0\x5f\x5f\x62\x65\x31\x36\0\x5f\
>>> \x5f\x62\x65\x33\x32\0\x62\x70\x66\x5f\x6d\x61\x70\x5f\x74\x79\x70\x65\0\x42\
>>> \x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x55\x4e\x53\x50\x45\x43\0\x42\
>>> \x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x48\x41\x53\x48\0\x42\x50\x46\
>>> \x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x41\x52\x52\x41\x59\0\x42\x50\x46\x5f\
>>> \x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x50\x52\x4f\x47\x5f\x41\x52\x52\x41\x59\0\
>>> \x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x50\x45\x52\x46\x5f\x45\
>>> \x56\x45\x4e\x54\x5f\x41\x52\x52\x41\x59\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\
>>> \x59\x50\x45\x5f\x50\x45\x52\x43\x50\x55\x5f\x48\x41\x53\x48\0\x42\x50\x46\x5f\
>>> \x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x50\x45\x52\x43\x50\x55\x5f\x41\x52\x52\
>>> \x41\x59\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x53\x54\x41\x43\
>>> \x4b\x5f\x54\x52\x41\x43\x45\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\
>>> \x5f\x43\x47\x52\x4f\x55\x50\x5f\x41\x52\x52\x41\x59\0\x42\x50\x46\x5f\x4d\x41\
>>> \x50\x5f\x54\x59\x50\x45\x5f\x4c\x52\x55\x5f\x48\x41\x53\x48\0\x42\x50\x46\x5f\
>>> \x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x4c\x52\x55\x5f\x50\x45\x52\x43\x50\x55\
>>> \x5f\x48\x41\x53\x48\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x4c\
>>> \x50\x4d\x5f\x54\x52\x49\x45\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\
>>> \x5f\x41\x52\x52\x41\x59\x5f\x4f\x46\x5f\x4d\x41\x50\x53\0\x42\x50\x46\x5f\x4d\
>>> \x41\x50\x5f\x54\x59\x50\x45\x5f\x48\x41\x53\x48\x5f\x4f\x46\x5f\x4d\x41\x50\
>>> \x53\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x44\x45\x56\x4d\x41\
>>> \x50\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x53\x4f\x43\x4b\x4d\
>>> \x41\x50\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x43\x50\x55\x4d\
>>> \x41\x50\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x58\x53\x4b\x4d\
>>> \x41\x50\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x53\x4f\x43\x4b\
>>> \x48\x41\x53\x48\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x43\x47\
>>> \x52\x4f\x55\x50\x5f\x53\x54\x4f\x52\x41\x47\x45\0\x42\x50\x46\x5f\x4d\x41\x50\
>>> \x5f\x54\x59\x50\x45\x5f\x52\x45\x55\x53\x45\x50\x4f\x52\x54\x5f\x53\x4f\x43\
>>> \x4b\x41\x52\x52\x41\x59\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\
>>> \x50\x45\x52\x43\x50\x55\x5f\x43\x47\x52\x4f\x55\x50\x5f\x53\x54\x4f\x52\x41\
>>> \x47\x45\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x51\x55\x45\x55\
>>> \x45\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x53\x54\x41\x43\x4b\
>>> \0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x53\x4b\x5f\x53\x54\x4f\
>>> \x52\x41\x47\x45\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x44\x45\
>>> \x56\x4d\x41\x50\x5f\x48\x41\x53\x48\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\
>>> \x50\x45\x5f\x53\x54\x52\x55\x43\x54\x5f\x4f\x50\x53\0\x42\x50\x46\x5f\x4d\x41\
>>> \x50\x5f\x54\x59\x50\x45\x5f\x52\x49\x4e\x47\x42\x55\x46\0\x42\x50\x46\x5f\x4d\
>>> \x41\x50\x5f\x54\x59\x50\x45\x5f\x49\x4e\x4f\x44\x45\x5f\x53\x54\x4f\x52\x41\
>>> \x47\x45\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x54\x41\x53\x4b\
>>> \x5f\x53\x54\x4f\x52\x41\x47\x45\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\
>>> \x45\x5f\x42\x4c\x4f\x4f\x4d\x5f\x46\x49\x4c\x54\x45\x52\0\x66\x6c\x6f\x77\x5f\
>>> \x6b\x65\x79\x73\0\x62\x70\x66\x5f\x66\x6c\x6f\x77\x5f\x6b\x65\x79\x73\0\x6e\
>>> \x68\x6f\x66\x66\0\x74\x68\x6f\x66\x66\0\x61\x64\x64\x72\x5f\x70\x72\x6f\x74\
>>> \x6f\0\x69\x73\x5f\x66\x72\x61\x67\0\x69\x73\x5f\x66\x69\x72\x73\x74\x5f\x66\
>>> \x72\x61\x67\0\x69\x73\x5f\x65\x6e\x63\x61\x70\0\x69\x70\x5f\x70\x72\x6f\x74\
>>> \x6f\0\x6e\x5f\x70\x72\x6f\x74\x6f\0\x73\x70\x6f\x72\x74\0\x64\x70\x6f\x72\x74\
>>> \0\x66\x6c\x61\x67\x73\0\x66\x6c\x6f\x77\x5f\x6c\x61\x62\x65\x6c\0\x69\x70\x76\
>>> \x34\x5f\x73\x72\x63\0\x69\x70\x76\x34\x5f\x64\x73\x74\0\x69\x70\x76\x36\x5f\
>>> \x73\x72\x63\0\x69\x70\x76\x36\x5f\x64\x73\x74\0\x73\x6b\0\x62\x70\x66\x5f\x73\
>>> \x6f\x63\x6b\0\x62\x6f\x75\x6e\x64\x5f\x64\x65\x76\x5f\x69\x66\0\x66\x61\x6d\
>>> \x69\x6c\x79\0\x74\x79\x70\x65\0\x70\x72\x6f\x74\x6f\x63\x6f\x6c\0\x6d\x61\x72\
>>> \x6b\0\x70\x72\x69\x6f\x72\x69\x74\x79\0\x73\x72\x63\x5f\x69\x70\x34\0\x73\x72\
>>> \x63\x5f\x69\x70\x36\0\x73\x72\x63\x5f\x70\x6f\x72\x74\0\x64\x73\x74\x5f\x70\
>>> \x6f\x72\x74\0\x64\x73\x74\x5f\x69\x70\x34\0\x64\x73\x74\x5f\x69\x70\x36\0\x73\
>>> \x74\x61\x74\x65\0\x72\x78\x5f\x71\x75\x65\x75\x65\x5f\x6d\x61\x70\x70\x69\x6e\
>>> \x67\0\x5f\x5f\x73\x6b\x5f\x62\x75\x66\x66\0\x6c\x65\x6e\0\x70\x6b\x74\x5f\x74\
>>> \x79\x70\x65\0\x71\x75\x65\x75\x65\x5f\x6d\x61\x70\x70\x69\x6e\x67\0\x76\x6c\
>>> \x61\x6e\x5f\x70\x72\x65\x73\x65\x6e\x74\0\x76\x6c\x61\x6e\x5f\x74\x63\x69\0\
>>> \x76\x6c\x61\x6e\x5f\x70\x72\x6f\x74\x6f\0\x69\x6e\x67\x72\x65\x73\x73\x5f\x69\
>>> \x66\x69\x6e\x64\x65\x78\0\x69\x66\x69\x6e\x64\x65\x78\0\x74\x63\x5f\x69\x6e\
>>> \x64\x65\x78\0\x63\x62\0\x68\x61\x73\x68\0\x74\x63\x5f\x63\x6c\x61\x73\x73\x69\
>>> \x64\0\x64\x61\x74\x61\0\x64\x61\x74\x61\x5f\x65\x6e\x64\0\x6e\x61\x70\x69\x5f\
>>> \x69\x64\0\x72\x65\x6d\x6f\x74\x65\x5f\x69\x70\x34\0\x6c\x6f\x63\x61\x6c\x5f\
>>> \x69\x70\x34\0\x72\x65\x6d\x6f\x74\x65\x5f\x69\x70\x36\0\x6c\x6f\x63\x61\x6c\
>>> \x5f\x69\x70\x36\0\x72\x65\x6d\x6f\x74\x65\x5f\x70\x6f\x72\x74\0\x6c\x6f\x63\
>>> \x61\x6c\x5f\x70\x6f\x72\x74\0\x64\x61\x74\x61\x5f\x6d\x65\x74\x61\0\x74\x73\
>>> \x74\x61\x6d\x70\0\x77\x69\x72\x65\x5f\x6c\x65\x6e\0\x67\x73\x6f\x5f\x73\x65\
>>> \x67\x73\0\x67\x73\x6f\x5f\x73\x69\x7a\x65\0\x68\x77\x74\x73\x74\x61\x6d\x70\0\
>>> \x6b\x65\x79\0\x76\x61\x6c\x75\x65\0\x5f\x6c\x69\x63\x65\x6e\x73\x65\0\x69\x73\
>>> \x5f\x61\x6c\x6c\x6f\x77\x5f\x6c\x69\x73\x74\0\x73\x64\x5f\x72\x65\x73\x74\x72\
>>> \x69\x63\x74\x69\x66\0\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\x5f\
>>> \x69\0\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\x5f\x65\0\x72\x65\
>>> \x73\x74\x72\x69\x63\x74\x5f\x6e\x65\x74\x77\x6f\x72\x6b\x5f\x69\x6e\x74\x65\
>>> \x72\x66\x61\x63\x65\x73\x5f\x69\x6d\x70\x6c\0\x2e\x64\x61\x74\x61\0\x6c\x69\
>>> \x63\x65\x6e\x73\x65\0\x2e\x6d\x61\x70\x73\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>> \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>> \0\0\0\0\0\0\0\0\0\0\x01\0\0\0\x03\0\0\0\x20\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x40\
>>> \0\0\0\0\0\0\0\xe5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>> \0\0\x09\0\0\0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x28\x01\0\0\0\0\0\0\
>>> \x50\x01\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\x18\0\0\0\0\0\0\0\x11\
>>> \0\0\0\x01\0\0\0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x78\x02\0\0\0\0\0\0\x01\0\0\
>>> \0\0\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x17\0\0\0\x08\0\0\
>>> \0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x79\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>> \0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x1c\0\0\0\x01\0\0\0\x06\0\0\0\0\0\
>>> \0\0\0\0\0\0\0\0\0\0\x80\x02\0\0\0\0\0\0\xb8\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\
>>> \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x2e\0\0\0\x01\0\0\0\x06\0\0\0\0\0\0\0\0\0\0\0\0\
>>> \0\0\0\x38\x03\0\0\0\0\0\0\xb8\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\
>>> \0\0\0\0\0\0\0\0\x41\0\0\0\x01\0\0\0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xf0\x03\
>>> \0\0\0\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>> \0\x49\0\0\0\x01\0\0\0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\x04\0\0\0\0\0\0\
>>> \x18\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x4f\0\0\0\
>>> \x01\0\0\0\x30\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x20\x04\0\0\0\0\0\0\x31\0\0\0\0\0\
>>> \0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\xb3\0\0\0\x09\0\0\0\
>>> \x40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x58\x04\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\x02\0\
>>> \0\0\x05\0\0\0\x08\0\0\0\0\0\0\0\x10\0\0\0\0\0\0\0\xc9\0\0\0\x09\0\0\0\x40\0\0\
>>> \0\0\0\0\0\0\0\0\0\0\0\0\0\x78\x04\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\x02\0\0\0\x06\
>>> \0\0\0\x08\0\0\0\0\0\0\0\x10\0\0\0\0\0\0\0\xe0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\
>>> \0\0\0\0\0\0\0\0\x98\x04\0\0\0\0\0\0\x16\x0e\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\
>>> \0\0\0\0\0\0\0\0\0\0\0\0\0\0";
>>> }
>>>
>>> #ifdef __cplusplus
>>> struct restrict_ifaces_bpf *restrict_ifaces_bpf::open(const struct
>>> bpf_object_open_opts *opts) { return
>>> restrict_ifaces_bpf__open_opts(opts); }
>>> struct restrict_ifaces_bpf *restrict_ifaces_bpf::open_and_load() {
>>> return restrict_ifaces_bpf__open_and_load(); }
>>> int restrict_ifaces_bpf::load(struct restrict_ifaces_bpf *skel) {
>>> return restrict_ifaces_bpf__load(skel); }
>>> int restrict_ifaces_bpf::attach(struct restrict_ifaces_bpf *skel) {
>>> return restrict_ifaces_bpf__attach(skel); }
>>> void restrict_ifaces_bpf::detach(struct restrict_ifaces_bpf *skel) {
>>> restrict_ifaces_bpf__detach(skel); }
>>> void restrict_ifaces_bpf::destroy(struct restrict_ifaces_bpf *skel) {
>>> restrict_ifaces_bpf__destroy(skel); }
>>> const void *restrict_ifaces_bpf::elf_bytes(size_t *sz) { return
>>> restrict_ifaces_bpf__elf_bytes(sz); }
>>> #endif /* __cplusplus */
>>>
>>> __attribute__((unused)) static void
>>> restrict_ifaces_bpf__assert(struct restrict_ifaces_bpf *s
>>> __attribute__((unused)))
>>> {
>>> #ifdef __cplusplus
>>> #define _Static_assert static_assert
>>> #endif
>>>     _Static_assert(sizeof(s->data->is_allow_list) == 1, "unexpected
>>> size of 'is_allow_list'");
>>> #ifdef __cplusplus
>>> #undef _Static_assert
>>> #endif
>>> }
>>>
>>> #endif /* __RESTRICT_IFACES_BPF_SKEL_H__ */
>>>
>>> Clang:
>>> $ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>>> --debug gen skeleton restrict-ifaces.bpf.o
>>> libbpf: loading object 'restrict_ifaces_bpf' from buffer
>>> libbpf: elf: section(2) .symtab, size 384, link 1, flags 0, type=2
>>> libbpf: elf: section(3) cgroup_skb/egress, size 152, link 0, flags 6, type=1
>>> libbpf: sec 'cgroup_skb/egress': found program 'sd_restrictif_e' at
>>> insn offset 0 (0 bytes), code size 19 insns (152 bytes)
>>> libbpf: elf: section(4) cgroup_skb/ingress, size 152, link 0, flags 6, type=1
>>> libbpf: sec 'cgroup_skb/ingress': found program 'sd_restrictif_i' at
>>> insn offset 0 (0 bytes), code size 19 insns (152 bytes)
>>> libbpf: elf: section(5) .rodata, size 1, link 0, flags 2, type=1
>>> libbpf: elf: section(6) license, size 18, link 0, flags 2, type=1
>>> libbpf: license of restrict_ifaces_bpf is LGPL-2.1-or-later
>>> libbpf: elf: section(7) .maps, size 24, link 0, flags 3, type=1
>>> libbpf: elf: section(8) .relcgroup_skb/egress, size 32, link 2, flags 40, type=9
>>> libbpf: elf: section(9) .relcgroup_skb/ingress, size 32, link 2, flags
>>> 40, type=9
>>> libbpf: elf: section(10) .BTF, size 1988, link 0, flags 0, type=1
>>> libbpf: elf: section(11) .BTF.ext, size 376, link 0, flags 0, type=1
>>> libbpf: looking for externs among 16 symbols...
>>> libbpf: collected 0 externs total
>>> libbpf: map 'sd_restrictif': at sec_idx 7, offset 0.
>>> libbpf: map 'sd_restrictif': found type = 1.
>>> libbpf: map 'sd_restrictif': found key [6], sz = 4.
>>> libbpf: map 'sd_restrictif': found value [9], sz = 1.
>>> libbpf: map 'restrict.rodata' (global data): at sec_idx 5, offset 0, flags 480.
>>> libbpf: map 1 is "restrict.rodata"
>>> libbpf: sec '.relcgroup_skb/egress': collecting relocation for
>>> section(3) 'cgroup_skb/egress'
>>> libbpf: sec '.relcgroup_skb/egress': relo #0: insn #4 against 'sd_restrictif'
>>> libbpf: prog 'sd_restrictif_e': found map 0 (sd_restrictif, sec 7, off
>>> 0) for insn #4
>>> libbpf: sec '.relcgroup_skb/egress': relo #1: insn #7 against 'is_allow_list'
>>> libbpf: prog 'sd_restrictif_e': found data map 1 (restrict.rodata, sec
>>> 5, off 0) for insn 7
>>> libbpf: sec '.relcgroup_skb/ingress': collecting relocation for
>>> section(4) 'cgroup_skb/ingress'
>>> libbpf: sec '.relcgroup_skb/ingress': relo #0: insn #4 against 'sd_restrictif'
>>> libbpf: prog 'sd_restrictif_i': found map 0 (sd_restrictif, sec 7, off
>>> 0) for insn #4
>>> libbpf: sec '.relcgroup_skb/ingress': relo #1: insn #7 against 'is_allow_list'
>>> libbpf: prog 'sd_restrictif_i': found data map 1 (restrict.rodata, sec
>>> 5, off 0) for insn 7
>>> /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
>>>
>>> /* THIS FILE IS AUTOGENERATED BY BPFTOOL! */
>>> #ifndef __RESTRICT_IFACES_BPF_SKEL_H__
>>> #define __RESTRICT_IFACES_BPF_SKEL_H__
>>>
>>> #include <errno.h>
>>> #include <stdlib.h>
>>> #include <bpf/libbpf.h>
>>>
>>> struct restrict_ifaces_bpf {
>>>     struct bpf_object_skeleton *skeleton;
>>>     struct bpf_object *obj;
>>>     struct {
>>>         struct bpf_map *sd_restrictif;
>>>         struct bpf_map *rodata;
>>>     } maps;
>>>     struct {
>>>         struct bpf_program *sd_restrictif_e;
>>>         struct bpf_program *sd_restrictif_i;
>>>     } progs;
>>>     struct {
>>>         struct bpf_link *sd_restrictif_e;
>>>         struct bpf_link *sd_restrictif_i;
>>>     } links;
>>>     struct restrict_ifaces_bpf__rodata {
>>>         __u8 is_allow_list;
>>>     } *rodata;
>>>
>>> #ifdef __cplusplus
>>>     static inline struct restrict_ifaces_bpf *open(const struct
>>> bpf_object_open_opts *opts = nullptr);
>>>     static inline struct restrict_ifaces_bpf *open_and_load();
>>>     static inline int load(struct restrict_ifaces_bpf *skel);
>>>     static inline int attach(struct restrict_ifaces_bpf *skel);
>>>     static inline void detach(struct restrict_ifaces_bpf *skel);
>>>     static inline void destroy(struct restrict_ifaces_bpf *skel);
>>>     static inline const void *elf_bytes(size_t *sz);
>>> #endif /* __cplusplus */
>>> };
>>>
>>> static void
>>> restrict_ifaces_bpf__destroy(struct restrict_ifaces_bpf *obj)
>>> {
>>>     if (!obj)
>>>         return;
>>>     if (obj->skeleton)
>>>         bpf_object__destroy_skeleton(obj->skeleton);
>>>     free(obj);
>>> }
>>>
>>> static inline int
>>> restrict_ifaces_bpf__create_skeleton(struct restrict_ifaces_bpf *obj);
>>>
>>> static inline struct restrict_ifaces_bpf *
>>> restrict_ifaces_bpf__open_opts(const struct bpf_object_open_opts *opts)
>>> {
>>>     struct restrict_ifaces_bpf *obj;
>>>     int err;
>>>
>>>     obj = (struct restrict_ifaces_bpf *)calloc(1, sizeof(*obj));
>>>     if (!obj) {
>>>         errno = ENOMEM;
>>>         return NULL;
>>>     }
>>>
>>>     err = restrict_ifaces_bpf__create_skeleton(obj);
>>>     if (err)
>>>         goto err_out;
>>>
>>>     err = bpf_object__open_skeleton(obj->skeleton, opts);
>>>     if (err)
>>>         goto err_out;
>>>
>>>     return obj;
>>> err_out:
>>>     restrict_ifaces_bpf__destroy(obj);
>>>     errno = -err;
>>>     return NULL;
>>> }
>>>
>>> static inline struct restrict_ifaces_bpf *
>>> restrict_ifaces_bpf__open(void)
>>> {
>>>     return restrict_ifaces_bpf__open_opts(NULL);
>>> }
>>>
>>> static inline int
>>> restrict_ifaces_bpf__load(struct restrict_ifaces_bpf *obj)
>>> {
>>>     return bpf_object__load_skeleton(obj->skeleton);
>>> }
>>>
>>> static inline struct restrict_ifaces_bpf *
>>> restrict_ifaces_bpf__open_and_load(void)
>>> {
>>>     struct restrict_ifaces_bpf *obj;
>>>     int err;
>>>
>>>     obj = restrict_ifaces_bpf__open();
>>>     if (!obj)
>>>         return NULL;
>>>     err = restrict_ifaces_bpf__load(obj);
>>>     if (err) {
>>>         restrict_ifaces_bpf__destroy(obj);
>>>         errno = -err;
>>>         return NULL;
>>>     }
>>>     return obj;
>>> }
>>>
>>> static inline int
>>> restrict_ifaces_bpf__attach(struct restrict_ifaces_bpf *obj)
>>> {
>>>     return bpf_object__attach_skeleton(obj->skeleton);
>>> }
>>>
>>> static inline void
>>> restrict_ifaces_bpf__detach(struct restrict_ifaces_bpf *obj)
>>> {
>>>     return bpf_object__detach_skeleton(obj->skeleton);
>>> }
>>>
>>> static inline const void *restrict_ifaces_bpf__elf_bytes(size_t *sz);
>>>
>>> static inline int
>>> restrict_ifaces_bpf__create_skeleton(struct restrict_ifaces_bpf *obj)
>>> {
>>>     struct bpf_object_skeleton *s;
>>>     int err;
>>>
>>>     s = (struct bpf_object_skeleton *)calloc(1, sizeof(*s));
>>>     if (!s)    {
>>>         err = -ENOMEM;
>>>         goto err;
>>>     }
>>>
>>>     s->sz = sizeof(*s);
>>>     s->name = "restrict_ifaces_bpf";
>>>     s->obj = &obj->obj;
>>>
>>>     /* maps */
>>>     s->map_cnt = 2;
>>>     s->map_skel_sz = sizeof(*s->maps);
>>>     s->maps = (struct bpf_map_skeleton *)calloc(s->map_cnt, s->map_skel_sz);
>>>     if (!s->maps) {
>>>         err = -ENOMEM;
>>>         goto err;
>>>     }
>>>
>>>     s->maps[0].name = "sd_restrictif";
>>>     s->maps[0].map = &obj->maps.sd_restrictif;
>>>
>>>     s->maps[1].name = "restrict.rodata";
>>>     s->maps[1].map = &obj->maps.rodata;
>>>     s->maps[1].mmaped = (void **)&obj->rodata;
>>>
>>>     /* programs */
>>>     s->prog_cnt = 2;
>>>     s->prog_skel_sz = sizeof(*s->progs);
>>>     s->progs = (struct bpf_prog_skeleton *)calloc(s->prog_cnt, s->prog_skel_sz);
>>>     if (!s->progs) {
>>>         err = -ENOMEM;
>>>         goto err;
>>>     }
>>>
>>>     s->progs[0].name = "sd_restrictif_e";
>>>     s->progs[0].prog = &obj->progs.sd_restrictif_e;
>>>     s->progs[0].link = &obj->links.sd_restrictif_e;
>>>
>>>     s->progs[1].name = "sd_restrictif_i";
>>>     s->progs[1].prog = &obj->progs.sd_restrictif_i;
>>>     s->progs[1].link = &obj->links.sd_restrictif_i;
>>>
>>>     s->data = (void *)restrict_ifaces_bpf__elf_bytes(&s->data_sz);
>>>
>>>     obj->skeleton = s;
>>>     return 0;
>>> err:
>>>     bpf_object__destroy_skeleton(s);
>>>     return err;
>>> }
>>>
>>> static inline const void *restrict_ifaces_bpf__elf_bytes(size_t *sz)
>>> {
>>>     *sz = 4272;
>>>     return (const void *)"\
>>> \x7f\x45\x4c\x46\x02\x01\x01\0\0\0\0\0\0\0\0\0\x01\0\xf7\0\x01\0\0\0\0\0\0\0\0\
>>> \0\0\0\0\0\0\0\0\0\0\0\xb0\x0d\0\0\0\0\0\0\0\0\0\0\x40\0\0\0\0\0\x40\0\x0c\0\
>>> \x01\0\0\x2e\x73\x74\x72\x74\x61\x62\0\x2e\x73\x79\x6d\x74\x61\x62\0\x63\x67\
>>> \x72\x6f\x75\x70\x5f\x73\x6b\x62\x2f\x65\x67\x72\x65\x73\x73\0\x63\x67\x72\x6f\
>>> \x75\x70\x5f\x73\x6b\x62\x2f\x69\x6e\x67\x72\x65\x73\x73\0\x2e\x72\x6f\x64\x61\
>>> \x74\x61\0\x6c\x69\x63\x65\x6e\x73\x65\0\x2e\x6d\x61\x70\x73\0\x72\x65\x73\x74\
>>> \x72\x69\x63\x74\x2d\x69\x66\x61\x63\x65\x73\x2e\x62\x70\x66\x2e\x63\0\x4c\x42\
>>> \x42\x30\x5f\x32\0\x4c\x42\x42\x30\x5f\x33\0\x4c\x42\x42\x30\x5f\x34\0\x4c\x42\
>>> \x42\x31\x5f\x32\0\x4c\x42\x42\x31\x5f\x33\0\x4c\x42\x42\x31\x5f\x34\0\x5f\x6c\
>>> \x69\x63\x65\x6e\x73\x65\0\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\
>>> \x5f\x65\0\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\0\x69\x73\x5f\
>>> \x61\x6c\x6c\x6f\x77\x5f\x6c\x69\x73\x74\0\x73\x64\x5f\x72\x65\x73\x74\x72\x69\
>>> \x63\x74\x69\x66\x5f\x69\0\x2e\x72\x65\x6c\x63\x67\x72\x6f\x75\x70\x5f\x73\x6b\
>>> \x62\x2f\x65\x67\x72\x65\x73\x73\0\x2e\x72\x65\x6c\x63\x67\x72\x6f\x75\x70\x5f\
>>> \x73\x6b\x62\x2f\x69\x6e\x67\x72\x65\x73\x73\0\x2e\x42\x54\x46\0\x2e\x42\x54\
>>> \x46\x2e\x65\x78\x74\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>> \x4c\0\0\0\x04\0\xf1\xff\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x03\0\x03\0\0\
>>> \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x62\0\0\0\0\0\x03\0\x70\0\0\0\0\0\0\0\0\0\0\0\0\
>>> \0\0\0\x69\0\0\0\0\0\x03\0\x80\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x70\0\0\0\0\0\x03\
>>> \0\x88\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x03\0\x04\0\0\0\0\0\0\0\0\0\0\0\0\
>>> \0\0\0\0\0\x77\0\0\0\0\0\x04\0\x70\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x7e\0\0\0\0\0\
>>> \x04\0\x80\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x85\0\0\0\0\0\x04\0\x88\0\0\0\0\0\0\0\
>>> \0\0\0\0\0\0\0\0\x8c\0\0\0\x01\0\x06\0\0\0\0\0\0\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\
>>> \0\x03\0\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x95\0\0\0\x12\0\x03\0\0\0\0\0\0\
>>> \0\0\0\x98\0\0\0\0\0\0\0\xa5\0\0\0\x11\0\x07\0\0\0\0\0\0\0\0\0\x18\0\0\0\0\0\0\
>>> \0\xb3\0\0\0\x11\0\x05\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\xc1\0\0\0\x12\0\x04\
>>> \0\0\0\0\0\0\0\0\0\x98\0\0\0\0\0\0\0\x61\x11\x28\0\0\0\0\0\x63\x1a\xfc\xff\0\0\
>>> \0\0\xbf\xa2\0\0\0\0\0\0\x07\x02\0\0\xfc\xff\xff\xff\x18\x01\0\0\0\0\0\0\0\0\0\
>>> \0\0\0\0\0\x85\0\0\0\x01\0\0\0\x18\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x71\x11\0\0\
>>> \0\0\0\0\x15\x01\x03\0\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x15\0\x03\0\0\0\0\0\x05\0\
>>> \x03\0\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x15\0\x01\0\0\0\0\0\xb7\x01\0\0\0\0\0\0\
>>> \xbf\x10\0\0\0\0\0\0\x95\0\0\0\0\0\0\0\x61\x11\x28\0\0\0\0\0\x63\x1a\xfc\xff\0\
>>> \0\0\0\xbf\xa2\0\0\0\0\0\0\x07\x02\0\0\xfc\xff\xff\xff\x18\x01\0\0\0\0\0\0\0\0\
>>> \0\0\0\0\0\0\x85\0\0\0\x01\0\0\0\x18\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x71\x11\0\
>>> \0\0\0\0\0\x15\x01\x03\0\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x15\0\x03\0\0\0\0\0\x05\
>>> \0\x03\0\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x15\0\x01\0\0\0\0\0\xb7\x01\0\0\0\0\0\0\
>>> \xbf\x10\0\0\0\0\0\0\x95\0\0\0\0\0\0\0\0\x4c\x47\x50\x4c\x2d\x32\x2e\x31\x2d\
>>> \x6f\x72\x2d\x6c\x61\x74\x65\x72\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>> \0\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\x01\0\0\0\x0d\0\0\0\x38\0\0\0\0\0\0\0\x01\0\0\
>>> \0\x0e\0\0\0\x20\0\0\0\0\0\0\0\x01\0\0\0\x0d\0\0\0\x38\0\0\0\0\0\0\0\x01\0\0\0\
>>> \x0e\0\0\0\x9f\xeb\x01\0\x18\0\0\0\0\0\0\0\x10\x04\0\0\x10\x04\0\0\x9c\x03\0\0\
>>> \0\0\0\0\0\0\0\x02\x03\0\0\0\x01\0\0\0\0\0\0\x01\x04\0\0\0\x20\0\0\x01\0\0\0\0\
>>> \0\0\0\x03\0\0\0\0\x02\0\0\0\x04\0\0\0\x01\0\0\0\x05\0\0\0\0\0\0\x01\x04\0\0\0\
>>> \x20\0\0\0\0\0\0\0\0\0\0\x02\x06\0\0\0\x19\0\0\0\0\0\0\x08\x07\0\0\0\x1f\0\0\0\
>>> \0\0\0\x01\x04\0\0\0\x20\0\0\0\0\0\0\0\0\0\0\x02\x09\0\0\0\x2c\0\0\0\0\0\0\x08\
>>> \x0a\0\0\0\x31\0\0\0\0\0\0\x01\x01\0\0\0\x08\0\0\0\0\0\0\0\x03\0\0\x04\x18\0\0\
>>> \0\x3f\0\0\0\x01\0\0\0\0\0\0\0\x44\0\0\0\x05\0\0\0\x40\0\0\0\x48\0\0\0\x08\0\0\
>>> \0\x80\0\0\0\x4e\0\0\0\0\0\0\x0e\x0b\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\x02\x0e\0\0\
>>> \0\0\0\0\0\0\0\0\x0a\x0f\0\0\0\x5c\0\0\0\x21\0\0\x04\xc0\0\0\0\x66\0\0\0\x06\0\
>>> \0\0\0\0\0\0\x6a\0\0\0\x06\0\0\0\x20\0\0\0\x73\0\0\0\x06\0\0\0\x40\0\0\0\x78\0\
>>> \0\0\x06\0\0\0\x60\0\0\0\x86\0\0\0\x06\0\0\0\x80\0\0\0\x8f\0\0\0\x06\0\0\0\xa0\
>>> \0\0\0\x9c\0\0\0\x06\0\0\0\xc0\0\0\0\xa5\0\0\0\x06\0\0\0\xe0\0\0\0\xb0\0\0\0\
>>> \x06\0\0\0\0\x01\0\0\xb9\0\0\0\x06\0\0\0\x20\x01\0\0\xc9\0\0\0\x06\0\0\0\x40\
>>> \x01\0\0\xd1\0\0\0\x06\0\0\0\x60\x01\0\0\xda\0\0\0\x10\0\0\0\x80\x01\0\0\xdd\0\
>>> \0\0\x06\0\0\0\x20\x02\0\0\xe2\0\0\0\x06\0\0\0\x40\x02\0\0\xed\0\0\0\x06\0\0\0\
>>> \x60\x02\0\0\xf2\0\0\0\x06\0\0\0\x80\x02\0\0\xfb\0\0\0\x06\0\0\0\xa0\x02\0\0\
>>> \x03\x01\0\0\x06\0\0\0\xc0\x02\0\0\x0a\x01\0\0\x06\0\0\0\xe0\x02\0\0\x15\x01\0\
>>> \0\x06\0\0\0\0\x03\0\0\x1f\x01\0\0\x11\0\0\0\x20\x03\0\0\x2a\x01\0\0\x11\0\0\0\
>>> \xa0\x03\0\0\x34\x01\0\0\x06\0\0\0\x20\x04\0\0\x40\x01\0\0\x06\0\0\0\x40\x04\0\
>>> \0\x4b\x01\0\0\x06\0\0\0\x60\x04\0\0\0\0\0\0\x12\0\0\0\x80\x04\0\0\x55\x01\0\0\
>>> \x14\0\0\0\xc0\x04\0\0\x5c\x01\0\0\x06\0\0\0\0\x05\0\0\x65\x01\0\0\x06\0\0\0\
>>> \x20\x05\0\0\0\0\0\0\x16\0\0\0\x40\x05\0\0\x6e\x01\0\0\x06\0\0\0\x80\x05\0\0\
>>> \x77\x01\0\0\x14\0\0\0\xc0\x05\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x06\0\0\0\x04\0\0\
>>> \0\x05\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x06\0\0\0\x04\0\0\0\x04\0\0\0\0\0\0\0\
>>> \x01\0\0\x05\x08\0\0\0\x80\x01\0\0\x13\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x02\x22\0\0\
>>> \0\x8a\x01\0\0\0\0\0\x08\x15\0\0\0\x90\x01\0\0\0\0\0\x01\x08\0\0\0\x40\0\0\0\0\
>>> \0\0\0\x01\0\0\x05\x08\0\0\0\xa3\x01\0\0\x17\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x02\
>>> \x23\0\0\0\0\0\0\0\x01\0\0\x0d\x02\0\0\0\xa3\x01\0\0\x0d\0\0\0\xa6\x01\0\0\x01\
>>> \0\0\x0c\x18\0\0\0\xb6\x01\0\0\x01\0\0\x0c\x18\0\0\0\0\0\0\0\0\0\0\x0a\x1c\0\0\
>>> \0\0\0\0\0\0\0\0\x09\x09\0\0\0\xc6\x01\0\0\0\0\0\x0e\x1b\0\0\0\x01\0\0\0\0\0\0\
>>> \0\0\0\0\x0a\x1f\0\0\0\xd4\x01\0\0\0\0\0\x01\x01\0\0\0\x08\0\0\x01\0\0\0\0\0\0\
>>> \0\x03\0\0\0\0\x1e\0\0\0\x04\0\0\0\x12\0\0\0\xd9\x01\0\0\0\0\0\x0e\x20\0\0\0\0\
>>> \0\0\0\xe2\x01\0\0\0\0\0\x07\0\0\0\0\xf0\x01\0\0\0\0\0\x07\0\0\0\0\x61\x03\0\0\
>>> \x01\0\0\x0f\x01\0\0\0\x1d\0\0\0\0\0\0\0\x01\0\0\0\x69\x03\0\0\x01\0\0\x0f\x12\
>>> \0\0\0\x21\0\0\0\0\0\0\0\x12\0\0\0\x71\x03\0\0\x01\0\0\x0f\x18\0\0\0\x0c\0\0\0\
>>> \0\0\0\0\x18\0\0\0\0\x69\x6e\x74\0\x5f\x5f\x41\x52\x52\x41\x59\x5f\x53\x49\x5a\
>>> \x45\x5f\x54\x59\x50\x45\x5f\x5f\0\x5f\x5f\x75\x33\x32\0\x75\x6e\x73\x69\x67\
>>> \x6e\x65\x64\x20\x69\x6e\x74\0\x5f\x5f\x75\x38\0\x75\x6e\x73\x69\x67\x6e\x65\
>>> \x64\x20\x63\x68\x61\x72\0\x74\x79\x70\x65\0\x6b\x65\x79\0\x76\x61\x6c\x75\x65\
>>> \0\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\0\x5f\x5f\x73\x6b\x5f\
>>> \x62\x75\x66\x66\0\x6c\x65\x6e\0\x70\x6b\x74\x5f\x74\x79\x70\x65\0\x6d\x61\x72\
>>> \x6b\0\x71\x75\x65\x75\x65\x5f\x6d\x61\x70\x70\x69\x6e\x67\0\x70\x72\x6f\x74\
>>> \x6f\x63\x6f\x6c\0\x76\x6c\x61\x6e\x5f\x70\x72\x65\x73\x65\x6e\x74\0\x76\x6c\
>>> \x61\x6e\x5f\x74\x63\x69\0\x76\x6c\x61\x6e\x5f\x70\x72\x6f\x74\x6f\0\x70\x72\
>>> \x69\x6f\x72\x69\x74\x79\0\x69\x6e\x67\x72\x65\x73\x73\x5f\x69\x66\x69\x6e\x64\
>>> \x65\x78\0\x69\x66\x69\x6e\x64\x65\x78\0\x74\x63\x5f\x69\x6e\x64\x65\x78\0\x63\
>>> \x62\0\x68\x61\x73\x68\0\x74\x63\x5f\x63\x6c\x61\x73\x73\x69\x64\0\x64\x61\x74\
>>> \x61\0\x64\x61\x74\x61\x5f\x65\x6e\x64\0\x6e\x61\x70\x69\x5f\x69\x64\0\x66\x61\
>>> \x6d\x69\x6c\x79\0\x72\x65\x6d\x6f\x74\x65\x5f\x69\x70\x34\0\x6c\x6f\x63\x61\
>>> \x6c\x5f\x69\x70\x34\0\x72\x65\x6d\x6f\x74\x65\x5f\x69\x70\x36\0\x6c\x6f\x63\
>>> \x61\x6c\x5f\x69\x70\x36\0\x72\x65\x6d\x6f\x74\x65\x5f\x70\x6f\x72\x74\0\x6c\
>>> \x6f\x63\x61\x6c\x5f\x70\x6f\x72\x74\0\x64\x61\x74\x61\x5f\x6d\x65\x74\x61\0\
>>> \x74\x73\x74\x61\x6d\x70\0\x77\x69\x72\x65\x5f\x6c\x65\x6e\0\x67\x73\x6f\x5f\
>>> \x73\x65\x67\x73\0\x67\x73\x6f\x5f\x73\x69\x7a\x65\0\x68\x77\x74\x73\x74\x61\
>>> \x6d\x70\0\x66\x6c\x6f\x77\x5f\x6b\x65\x79\x73\0\x5f\x5f\x75\x36\x34\0\x75\x6e\
>>> \x73\x69\x67\x6e\x65\x64\x20\x6c\x6f\x6e\x67\x20\x6c\x6f\x6e\x67\0\x73\x6b\0\
>>> \x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\x5f\x65\0\x73\x64\x5f\x72\
>>> \x65\x73\x74\x72\x69\x63\x74\x69\x66\x5f\x69\0\x69\x73\x5f\x61\x6c\x6c\x6f\x77\
>>> \x5f\x6c\x69\x73\x74\0\x63\x68\x61\x72\0\x5f\x6c\x69\x63\x65\x6e\x73\x65\0\x62\
>>> \x70\x66\x5f\x66\x6c\x6f\x77\x5f\x6b\x65\x79\x73\0\x62\x70\x66\x5f\x73\x6f\x63\
>>> \x6b\0\x2f\x68\x6f\x6d\x65\x2f\x62\x75\x69\x6c\x64\x72\x6f\x6f\x74\x2f\x62\x75\
>>> \x69\x6c\x64\x72\x6f\x6f\x74\x2f\x6f\x75\x74\x70\x75\x74\x2f\x62\x75\x69\x6c\
>>> \x64\x2f\x73\x79\x73\x74\x65\x6d\x64\x2d\x63\x75\x73\x74\x6f\x6d\x2f\x73\x72\
>>> \x63\x2f\x63\x6f\x72\x65\x2f\x62\x70\x66\x2f\x72\x65\x73\x74\x72\x69\x63\x74\
>>> \x5f\x69\x66\x61\x63\x65\x73\x2f\x72\x65\x73\x74\x72\x69\x63\x74\x2d\x69\x66\
>>> \x61\x63\x65\x73\x2e\x62\x70\x66\x2e\x63\0\x20\x20\x20\x20\x20\x20\x20\x20\x69\
>>> \x66\x69\x6e\x64\x65\x78\x20\x3d\x20\x73\x6b\x2d\x3e\x69\x66\x69\x6e\x64\x65\
>>> \x78\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x6c\x6f\x6f\x6b\x75\x70\x5f\x72\x65\
>>> \x73\x75\x6c\x74\x20\x3d\x20\x62\x70\x66\x5f\x6d\x61\x70\x5f\x6c\x6f\x6f\x6b\
>>> \x75\x70\x5f\x65\x6c\x65\x6d\x28\x26\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\
>>> \x74\x69\x66\x2c\x20\x26\x69\x66\x69\x6e\x64\x65\x78\x29\x3b\0\x20\x20\x20\x20\
>>> \x20\x20\x20\x20\x69\x66\x20\x28\x69\x73\x5f\x61\x6c\x6c\x6f\x77\x5f\x6c\x69\
>>> \x73\x74\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
>>> \x20\x20\x69\x66\x20\x28\x6c\x6f\x6f\x6b\x75\x70\x5f\x72\x65\x73\x75\x6c\x74\
>>> \x29\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\
>>> \x20\x28\x21\x6c\x6f\x6f\x6b\x75\x70\x5f\x72\x65\x73\x75\x6c\x74\x29\0\x20\x20\
>>> \x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x72\x65\x73\x74\x72\x69\
>>> \x63\x74\x5f\x6e\x65\x74\x77\x6f\x72\x6b\x5f\x69\x6e\x74\x65\x72\x66\x61\x63\
>>> \x65\x73\x5f\x69\x6d\x70\x6c\x28\x73\x6b\x29\x3b\0\x2e\x72\x6f\x64\x61\x74\x61\
>>> \0\x6c\x69\x63\x65\x6e\x73\x65\0\x2e\x6d\x61\x70\x73\0\x63\x67\x72\x6f\x75\x70\
>>> \x5f\x73\x6b\x62\x2f\x65\x67\x72\x65\x73\x73\0\x63\x67\x72\x6f\x75\x70\x5f\x73\
>>> \x6b\x62\x2f\x69\x6e\x67\x72\x65\x73\x73\0\0\0\0\0\x9f\xeb\x01\0\x20\0\0\0\0\0\
>>> \0\0\x24\0\0\0\x24\0\0\0\x34\x01\0\0\x58\x01\0\0\0\0\0\0\x08\0\0\0\x77\x03\0\0\
>>> \x01\0\0\0\0\0\0\0\x19\0\0\0\x89\x03\0\0\x01\0\0\0\0\0\0\0\x1a\0\0\0\x10\0\0\0\
>>> \x77\x03\0\0\x09\0\0\0\0\0\0\0\xf9\x01\0\0\x62\x02\0\0\x17\x6c\0\0\x08\0\0\0\
>>> \xf9\x01\0\0\x62\x02\0\0\x11\x6c\0\0\x18\0\0\0\xf9\x01\0\0\0\0\0\0\0\0\0\0\x20\
>>> \0\0\0\xf9\x01\0\0\x81\x02\0\0\x19\x70\0\0\x38\0\0\0\xf9\x01\0\0\xc8\x02\0\0\
>>> \x0d\x74\0\0\x50\0\0\0\xf9\x01\0\0\xc8\x02\0\0\x0d\x74\0\0\x60\0\0\0\xf9\x01\0\
>>> \0\xe5\x02\0\0\x15\x7c\0\0\x78\0\0\0\xf9\x01\0\0\x08\x03\0\0\x15\x8c\0\0\x88\0\
>>> \0\0\xf9\x01\0\0\x2c\x03\0\0\x09\xb0\0\0\x89\x03\0\0\x09\0\0\0\0\0\0\0\xf9\x01\
>>> \0\0\x62\x02\0\0\x17\x6c\0\0\x08\0\0\0\xf9\x01\0\0\x62\x02\0\0\x11\x6c\0\0\x18\
>>> \0\0\0\xf9\x01\0\0\0\0\0\0\0\0\0\0\x20\0\0\0\xf9\x01\0\0\x81\x02\0\0\x19\x70\0\
>>> \0\x38\0\0\0\xf9\x01\0\0\xc8\x02\0\0\x0d\x74\0\0\x50\0\0\0\xf9\x01\0\0\xc8\x02\
>>> \0\0\x0d\x74\0\0\x60\0\0\0\xf9\x01\0\0\xe5\x02\0\0\x15\x7c\0\0\x78\0\0\0\xf9\
>>> \x01\0\0\x08\x03\0\0\x15\x8c\0\0\x88\0\0\0\xf9\x01\0\0\x2c\x03\0\0\x09\xc4\0\0\
>>> \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>> \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\x03\0\0\0\x20\0\0\
>>> \0\0\0\0\0\0\0\0\0\0\0\0\0\x40\0\0\0\0\0\0\0\x0c\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>> \0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x09\0\0\0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>> \0\0\0\0\0\x50\x01\0\0\0\0\0\0\x80\x01\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\x08\0\0\0\
>>> \0\0\0\0\x18\0\0\0\0\0\0\0\x11\0\0\0\x01\0\0\0\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>> \0\xd0\x02\0\0\0\0\0\0\x98\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0\0\
>>> \0\0\0\0\0\0\x23\0\0\0\x01\0\0\0\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x68\x03\0\0\
>>> \0\0\0\0\x98\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>> \x36\0\0\0\x01\0\0\0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\x01\0\
>>> \0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x3e\0\0\0\x01\0\
>>> \0\0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x04\0\0\0\0\0\0\x12\0\0\0\0\0\0\0\0\
>>> \0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x46\0\0\0\x01\0\0\0\x03\0\0\0\
>>> \0\0\0\0\0\0\0\0\0\0\0\0\x18\x04\0\0\0\0\0\0\x18\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>> \x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xd1\0\0\0\x09\0\0\0\x40\0\0\0\0\0\0\0\0\0\0\
>>> \0\0\0\0\0\x30\x04\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\x02\0\0\0\x03\0\0\0\x08\0\0\0\
>>> \0\0\0\0\x10\0\0\0\0\0\0\0\xe7\0\0\0\x09\0\0\0\x40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>> \0\x50\x04\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\x02\0\0\0\x04\0\0\0\x08\0\0\0\0\0\0\0\
>>> \x10\0\0\0\0\0\0\0\xfe\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x70\x04\
>>> \0\0\0\0\0\0\xc4\x07\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>> \0\0\x03\x01\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x38\x0c\0\0\0\0\0\0\
>>> \x78\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
>>> }
>>>
>>> #ifdef __cplusplus
>>> struct restrict_ifaces_bpf *restrict_ifaces_bpf::open(const struct
>>> bpf_object_open_opts *opts) { return
>>> restrict_ifaces_bpf__open_opts(opts); }
>>> struct restrict_ifaces_bpf *restrict_ifaces_bpf::open_and_load() {
>>> return restrict_ifaces_bpf__open_and_load(); }
>>> int restrict_ifaces_bpf::load(struct restrict_ifaces_bpf *skel) {
>>> return restrict_ifaces_bpf__load(skel); }
>>> int restrict_ifaces_bpf::attach(struct restrict_ifaces_bpf *skel) {
>>> return restrict_ifaces_bpf__attach(skel); }
>>> void restrict_ifaces_bpf::detach(struct restrict_ifaces_bpf *skel) {
>>> restrict_ifaces_bpf__detach(skel); }
>>> void restrict_ifaces_bpf::destroy(struct restrict_ifaces_bpf *skel) {
>>> restrict_ifaces_bpf__destroy(skel); }
>>> const void *restrict_ifaces_bpf::elf_bytes(size_t *sz) { return
>>> restrict_ifaces_bpf__elf_bytes(sz); }
>>> #endif /* __cplusplus */
>>>
>>> __attribute__((unused)) static void
>>> restrict_ifaces_bpf__assert(struct restrict_ifaces_bpf *s
>>> __attribute__((unused)))
>>> {
>>> #ifdef __cplusplus
>>> #define _Static_assert static_assert
>>> #endif
>>>     _Static_assert(sizeof(s->rodata->is_allow_list) == 1, "unexpected
>>> size of 'is_allow_list'");
>>> #ifdef __cplusplus
>>> #undef _Static_assert
>>> #endif
>>> }
>>>
>>> #endif /* __RESTRICT_IFACES_BPF_SKEL_H__ */
>>>
>>>>
>>>>
>>>> > Starting program:
>>>> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>>>> > --debug gen skeleton
>>>> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>>>> > [Thread debugging using libthread_db enabled]
>>>> > Using host libthread_db library "/usr/lib/libthread_db.so.1".
>>>> > libbpf: loading object 'restrict_ifaces_bpf' from buffer
>>>> > libbpf: elf: section(2) .symtab, size 336, link 1, flags 0, type=2
>>>> > libbpf: elf: section(3) .data, size 1, link 0, flags 3, type=1
>>>> > libbpf: elf: section(4) .bss, size 0, link 0, flags 3, type=8
>>>> > libbpf: elf: section(5) cgroup_skb/egress, size 184, link 0, flags 6, type=1
>>>> > libbpf: sec 'cgroup_skb/egress': found program 'sd_restrictif_e' at
>>>> > insn offset 0 (0 bytes), code size 23 insns (184 bytes)
>>>> > libbpf: elf: section(6) cgroup_skb/ingress, size 184, link 0, flags 6, type=1
>>>> > libbpf: sec 'cgroup_skb/ingress': found program 'sd_restrictif_i' at
>>>> > insn offset 0 (0 bytes), code size 23 insns (184 bytes)
>>>> > libbpf: elf: section(7) license, size 18, link 0, flags 2, type=1
>>>> > libbpf: license of restrict_ifaces_bpf is LGPL-2.1-or-later
>>>> > libbpf: elf: section(8) .maps, size 24, link 0, flags 3, type=1
>>>> > libbpf: elf: section(9) .comment, size 49, link 0, flags 30, type=1
>>>> > libbpf: elf: skipping unrecognized data section(9) .comment
>>>> > libbpf: elf: section(10) .relcgroup_skb/egress, size 32, link 2, flags
>>>> > 40, type=9
>>>> > libbpf: elf: section(11) .relcgroup_skb/ingress, size 32, link 2,
>>>> > flags 40, type=9
>>>> > libbpf: elf: section(12) .BTF, size 3606, link 0, flags 0, type=1
>>>> > libbpf: looking for externs among 14 symbols...
>>>> > libbpf: collected 0 externs total
>>>> > libbpf: map 'sd_restrictif': at sec_idx 8, offset 0.
>>>> > libbpf: map 'sd_restrictif': found type = 1.
>>>> > libbpf: map 'sd_restrictif': found key [12], sz = 4.
>>>> > libbpf: map 'sd_restrictif': found value [3], sz = 1.
>>>> >
>>>> > Program received signal SIGSEGV, Segmentation fault.
>>>> > 0x0000aaaaaab4fd2c in bpf_object.init_maps ()
>>>> > (gdb) bt
>>>> > #0  0x0000aaaaaab4fd2c in bpf_object.init_maps ()
>>>> > #1  0x0000aaaaaab52178 in bpf_object_open.part ()
>>>> > #2  0x0000aaaaaab544e8 in bpf_object.open_mem ()
>>>> > #3  0x0000aaaaaab2a58c in do_skeleton ()
>>>> > #4  0x0000aaaaaab1e204 in main ()
>>>> >
>>>> >>
>>>> >> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
>>>> >> index e89cc9c885b3..e3a6808f0bb6 100644
>>>> >> --- a/tools/lib/bpf/libbpf.c
>>>> >> +++ b/tools/lib/bpf/libbpf.c
>>>> >> @@ -1591,6 +1591,10 @@ static int
>> bpf_object__init_global_data_maps(struct bpf_object *obj)
>>>> >>         for (sec_idx = 1; sec_idx < obj->efile.sec_cnt; sec_idx++) {
>>>> >>                 sec_desc = &obj->efile.secs[sec_idx];
>>>> >>
>>>> >> +                /* Skip empty sections.  */
>>>> >> +                if (sec_desc->data->d_size == 0)
>>>> >> +                  continue;
>>>> >> +
>>>> >>                 switch (sec_desc->sec_type) {
>>>> >>                 case SEC_DATA:
>>>> >>                         sec_name = elf_sec_name(obj, elf_sec_by_idx(obj, sec_idx));
>>>> >>
>>>> >> > GCC:
>>>> >> > $ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>>>> >> > --debug gen skeleton
>>>> >> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>>>> >> > libbpf: loading object 'restrict_ifaces_bpf' from buffer
>>>> >> > libbpf: elf: section(2) .symtab, size 336, link 1, flags 0, type=2
>>>> >> > libbpf: elf: section(3) .data, size 1, link 0, flags 3, type=1
>>>> >> > libbpf: elf: section(4) .bss, size 0, link 0, flags 3, type=8
>>>> >> > libbpf: elf: section(5) cgroup_skb/egress, size 184, link 0, flags 6, type=1
>>>> >> > libbpf: sec 'cgroup_skb/egress': found program 'sd_restrictif_e' at
>>>> >> > insn offset 0 (0 bytes), code size 23 insns (184 bytes)
>>>> >> > libbpf: elf: section(6) cgroup_skb/ingress, size 184, link 0, flags 6, type=1
>>>> >> > libbpf: sec 'cgroup_skb/ingress': found program 'sd_restrictif_i' at
>>>> >> > insn offset 0 (0 bytes), code size 23 insns (184 bytes)
>>>> >> > libbpf: elf: section(7) license, size 18, link 0, flags 2, type=1
>>>> >> > libbpf: license of restrict_ifaces_bpf is LGPL-2.1-or-later
>>>> >> > libbpf: elf: section(8) .maps, size 24, link 0, flags 3, type=1
>>>> >> > libbpf: elf: section(9) .comment, size 49, link 0, flags 30, type=1
>>>> >> > libbpf: elf: skipping unrecognized data section(9) .comment
>>>> >> > libbpf: elf: section(10) .relcgroup_skb/egress, size 32, link 2, flags
>>>> >> > 40, type=9
>>>> >> > libbpf: elf: section(11) .relcgroup_skb/ingress, size 32, link 2,
>>>> >> > flags 40, type=9
>>>> >> > libbpf: elf: section(12) .BTF, size 3606, link 0, flags 0, type=1
>>>> >> > libbpf: looking for externs among 14 symbols...
>>>> >> > libbpf: collected 0 externs total
>>>> >> > libbpf: map 'sd_restrictif': at sec_idx 8, offset 0.
>>>> >> > libbpf: map 'sd_restrictif': found type = 1.
>>>> >> > libbpf: map 'sd_restrictif': found key [12], sz = 4.
>>>> >> > libbpf: map 'sd_restrictif': found value [3], sz = 1.
>>>> >> > libbpf: map 'restrict.data' (global data): at sec_idx 3, offset 0, flags 400.
>>>> >> > libbpf: map 1 is "restrict.data"
>>>> >> > libbpf: map 'restrict.bss' (global data): at sec_idx 4, offset 0, flags 400.
>>>> >> > libbpf: failed to alloc map 'restrict.bss' content buffer: -22
>>>> >> > Error: failed to open BPF object file: Invalid argument
>>>> >> >
>>>> >> > LLVM:
>>>> >> > $ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>>>> >> > --debug gen skeleton restrict-ifaces.bpf.o
>>>> >> > libbpf: loading object 'restrict_ifaces_bpf' from buffer
>>>> >> > libbpf: elf: section(2) .symtab, size 384, link 1, flags 0, type=2
>>>> >> > libbpf: elf: section(3) cgroup_skb/egress, size 152, link 0, flags 6, type=1
>>>> >> > libbpf: sec 'cgroup_skb/egress': found program 'sd_restrictif_e' at
>>>> >> > insn offset 0 (0 bytes), code size 19 insns (152 bytes)
>>>> >> > libbpf: elf: section(4) cgroup_skb/ingress, size 152, link 0, flags 6, type=1
>>>> >> > libbpf: sec 'cgroup_skb/ingress': found program 'sd_restrictif_i' at
>>>> >> > insn offset 0 (0 bytes), code size 19 insns (152 bytes)
>>>> >> > libbpf: elf: section(5) .rodata, size 1, link 0, flags 2, type=1
>>>> >> > libbpf: elf: section(6) license, size 18, link 0, flags 2, type=1
>>>> >> > libbpf: license of restrict_ifaces_bpf is LGPL-2.1-or-later
>>>> >> > libbpf: elf: section(7) .maps, size 24, link 0, flags 3, type=1
>>>> >> > libbpf: elf: section(8) .relcgroup_skb/egress, size 32, link 2, flags 40, type=9
>>>> >> > libbpf: elf: section(9) .relcgroup_skb/ingress, size 32, link 2, flags
>>>> >> > 40, type=9
>>>> >> > libbpf: elf: section(10) .BTF, size 1988, link 0, flags 0, type=1
>>>> >> > libbpf: elf: section(11) .BTF.ext, size 376, link 0, flags 0, type=1
>>>> >> > libbpf: looking for externs among 16 symbols...
>>>> >> > libbpf: collected 0 externs total
>>>> >> > libbpf: map 'sd_restrictif': at sec_idx 7, offset 0.
>>>> >> > libbpf: map 'sd_restrictif': found type = 1.
>>>> >> > libbpf: map 'sd_restrictif': found key [6], sz = 4.
>>>> >> > libbpf: map 'sd_restrictif': found value [9], sz = 1.
>>>> >> > libbpf: map 'restrict.rodata' (global data): at sec_idx 5, offset 0, flags 480.
>>>> >> > libbpf: map 1 is "restrict.rodata"
>>>> >> > libbpf: sec '.relcgroup_skb/egress': collecting relocation for
>>>> >> > section(3) 'cgroup_skb/egress'
>>>> >> > libbpf: sec '.relcgroup_skb/egress': relo #0: insn #4 against 'sd_restrictif'
>>>> >> > libbpf: prog 'sd_restrictif_e': found map 0 (sd_restrictif, sec 7, off
>>>> >> > 0) for insn #4
>>>> >> > libbpf: sec '.relcgroup_skb/egress': relo #1: insn #7 against 'is_allow_list'
>>>> >> > libbpf: prog 'sd_restrictif_e': found data map 1 (restrict.rodata, sec
>>>> >> > 5, off 0) for insn 7
>>>> >> > libbpf: sec '.relcgroup_skb/ingress': collecting relocation for
>>>> >> > section(4) 'cgroup_skb/ingress'
>>>> >> > libbpf: sec '.relcgroup_skb/ingress': relo #0: insn #4 against 'sd_restrictif'
>>>> >> > libbpf: prog 'sd_restrictif_i': found map 0 (sd_restrictif, sec 7, off
>>>> >> > 0) for insn #4
>>>> >> > libbpf: sec '.relcgroup_skb/ingress': relo #1: insn #7 against 'is_allow_list'
>>>> >> > libbpf: prog 'sd_restrictif_i': found data map 1 (restrict.rodata, sec
>>>> >> > 5, off 0) for insn 7
>>>> >> >
>>>> >> >> >
>>>> >> >> > >>
>>>> >> >> > >> Looking at libbpf.c, it seems to me that this may be due of trying to
>>>> >> >> > >> mmap 0 bytes in `bpf_object__init_internal_map':
>>>> >> >> > >>
>>>> >> >> > >>         map->mmaped = mmap(NULL, bpf_map_mmap_sz(map), PROT_READ | PROT_WRITE,
>>>> >> >> > >>                            MAP_SHARED | MAP_ANONYMOUS, -1, 0);
>>>> >> >> > >>         if (map->mmaped == MAP_FAILED) {
>>>> >> >> > >>                 err = -errno;
>>>> >> >> > >>                 map->mmaped = NULL;
>>>> >> >> > >>                 pr_warn("failed to alloc map '%s' content buffer: %d\n",
>>>> >> >> > >>                         map->name, err);
>>>> >> >> > >>                 zfree(&map->real_name);
>>>> >> >> > >>                 zfree(&map->name);
>>>> >> >> > >>                 return err;
>>>> >> >> > >>         }
>>>> >> >> > >>
>>>> >> >> > >> I see no check for zero sized sections in
>>>> >> >> > >> bpf_object__init_global_data_maps.
>>>> >> >> > >>
>>>> >> >> > >> Is maybe GCC failing to allocate stuff in BSS that is supposed to be
>>>> >> >> > >> there?
>>>> >> >> > >>
>>>> >> >> > >> > Stripped file passed to gen skeleton:
>>>> >> >> > >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>>>> >> >> > >> > btf dump file
>>>> >> >> > >> >
>> output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>>>> >> >> > >> > format raw
>>>> >> >> > >> > [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>>>> >> >> > >> > [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
>>>> >> >> > >> > [3] TYPEDEF '__u8' type_id=2
>>>> >> >> > >> > [4] CONST '(anon)' type_id=3
>>>> >> >> > >> > [5] VOLATILE '(anon)' type_id=4
>>>> >> >> > >> > [6] INT 'short int' size=2 bits_offset=0 nr_bits=16 encoding=SIGNED
>>>> >> >> > >> > [7] INT 'short unsigned int' size=2 bits_offset=0 nr_bits=16 encoding=(none)
>>>> >> >> > >> > [8] TYPEDEF '__u16' type_id=7
>>>> >> >> > >> > [9] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
>>>> >> >> > >> > [10] TYPEDEF '__s32' type_id=9
>>>> >> >> > >> > [11] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
>>>> >> >> > >> > [12] TYPEDEF '__u32' type_id=11
>>>> >> >> > >> > [13] INT 'long long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
>>>> >> >> > >> > [14] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64
>>>> >> >> > >> > encoding=(none)
>>>> >> >> > >> > [15] TYPEDEF '__u64' type_id=14
>>>> >> >> > >> > [16] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
>>>> >> >> > >> > [17] INT 'long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
>>>> >> >> > >> > [18] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>>>> >> >> > >> > [19] CONST '(anon)' type_id=18
>>>> >> >> > >> > [20] TYPEDEF '__be16' type_id=8
>>>> >> >> > >> > [21] TYPEDEF '__be32' type_id=12
>>>> >> >> > >> > [22] ENUM 'bpf_map_type' encoding=UNSIGNED size=4 vlen=31
>>>> >> >> > >> >     'BPF_MAP_TYPE_UNSPEC' val=0
>>>> >> >> > >> >     'BPF_MAP_TYPE_HASH' val=1
>>>> >> >> > >> >     'BPF_MAP_TYPE_ARRAY' val=2
>>>> >> >> > >> >     'BPF_MAP_TYPE_PROG_ARRAY' val=3
>>>> >> >> > >> >     'BPF_MAP_TYPE_PERF_EVENT_ARRAY' val=4
>>>> >> >> > >> >     'BPF_MAP_TYPE_PERCPU_HASH' val=5
>>>> >> >> > >> >     'BPF_MAP_TYPE_PERCPU_ARRAY' val=6
>>>> >> >> > >> >     'BPF_MAP_TYPE_STACK_TRACE' val=7
>>>> >> >> > >> >     'BPF_MAP_TYPE_CGROUP_ARRAY' val=8
>>>> >> >> > >> >     'BPF_MAP_TYPE_LRU_HASH' val=9
>>>> >> >> > >> >     'BPF_MAP_TYPE_LRU_PERCPU_HASH' val=10
>>>> >> >> > >> >     'BPF_MAP_TYPE_LPM_TRIE' val=11
>>>> >> >> > >> >     'BPF_MAP_TYPE_ARRAY_OF_MAPS' val=12
>>>> >> >> > >> >     'BPF_MAP_TYPE_HASH_OF_MAPS' val=13
>>>> >> >> > >> >     'BPF_MAP_TYPE_DEVMAP' val=14
>>>> >> >> > >> >     'BPF_MAP_TYPE_SOCKMAP' val=15
>>>> >> >> > >> >     'BPF_MAP_TYPE_CPUMAP' val=16
>>>> >> >> > >> >     'BPF_MAP_TYPE_XSKMAP' val=17
>>>> >> >> > >> >     'BPF_MAP_TYPE_SOCKHASH' val=18
>>>> >> >> > >> >     'BPF_MAP_TYPE_CGROUP_STORAGE' val=19
>>>> >> >> > >> >     'BPF_MAP_TYPE_REUSEPORT_SOCKARRAY' val=20
>>>> >> >> > >> >     'BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE' val=21
>>>> >> >> > >> >     'BPF_MAP_TYPE_QUEUE' val=22
>>>> >> >> > >> >     'BPF_MAP_TYPE_STACK' val=23
>>>> >> >> > >> >     'BPF_MAP_TYPE_SK_STORAGE' val=24
>>>> >> >> > >> >     'BPF_MAP_TYPE_DEVMAP_HASH' val=25
>>>> >> >> > >> >     'BPF_MAP_TYPE_STRUCT_OPS' val=26
>>>> >> >> > >> >     'BPF_MAP_TYPE_RINGBUF' val=27
>>>> >> >> > >> >     'BPF_MAP_TYPE_INODE_STORAGE' val=28
>>>> >> >> > >> >     'BPF_MAP_TYPE_TASK_STORAGE' val=29
>>>> >> >> > >> >     'BPF_MAP_TYPE_BLOOM_FILTER' val=30
>>>> >> >> > >> > [23] UNION '(anon)' size=8 vlen=1
>>>> >> >> > >> >     'flow_keys' type_id=29 bits_offset=0
>>>> >> >> > >> > [24] STRUCT 'bpf_flow_keys' size=56 vlen=13
>>>> >> >> > >> >     'nhoff' type_id=8 bits_offset=0
>>>> >> >> > >> >     'thoff' type_id=8 bits_offset=16
>>>> >> >> > >> >     'addr_proto' type_id=8 bits_offset=32
>>>> >> >> > >> >     'is_frag' type_id=3 bits_offset=48
>>>> >> >> > >> >     'is_first_frag' type_id=3 bits_offset=56
>>>> >> >> > >> >     'is_encap' type_id=3 bits_offset=64
>>>> >> >> > >> >     'ip_proto' type_id=3 bits_offset=72
>>>> >> >> > >> >     'n_proto' type_id=20 bits_offset=80
>>>> >> >> > >> >     'sport' type_id=20 bits_offset=96
>>>> >> >> > >> >     'dport' type_id=20 bits_offset=112
>>>> >> >> > >> >     '(anon)' type_id=25 bits_offset=128
>>>> >> >> > >> >     'flags' type_id=12 bits_offset=384
>>>> >> >> > >> >     'flow_label' type_id=21 bits_offset=416
>>>> >> >> > >> > [25] UNION '(anon)' size=32 vlen=2
>>>> >> >> > >> >     '(anon)' type_id=26 bits_offset=0
>>>> >> >> > >> >     '(anon)' type_id=27 bits_offset=0
>>>> >> >> > >> > [26] STRUCT '(anon)' size=8 vlen=2
>>>> >> >> > >> >     'ipv4_src' type_id=21 bits_offset=0
>>>> >> >> > >> >     'ipv4_dst' type_id=21 bits_offset=32
>>>> >> >> > >> > [27] STRUCT '(anon)' size=32 vlen=2
>>>> >> >> > >> >     'ipv6_src' type_id=28 bits_offset=0
>>>> >> >> > >> >     'ipv6_dst' type_id=28 bits_offset=128
>>>> >> >> > >> > [28] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=4
>>>> >> >> > >> > [29] PTR '(anon)' type_id=24
>>>> >> >> > >> > [30] UNION '(anon)' size=8 vlen=1
>>>> >> >> > >> >     'sk' type_id=32 bits_offset=0
>>>> >> >> > >> > [31] STRUCT 'bpf_sock' size=80 vlen=14
>>>> >> >> > >> >     'bound_dev_if' type_id=12 bits_offset=0
>>>> >> >> > >> >     'family' type_id=12 bits_offset=32
>>>> >> >> > >> >     'type' type_id=12 bits_offset=64
>>>> >> >> > >> >     'protocol' type_id=12 bits_offset=96
>>>> >> >> > >> >     'mark' type_id=12 bits_offset=128
>>>> >> >> > >> >     'priority' type_id=12 bits_offset=160
>>>> >> >> > >> >     'src_ip4' type_id=12 bits_offset=192
>>>> >> >> > >> >     'src_ip6' type_id=28 bits_offset=224
>>>> >> >> > >> >     'src_port' type_id=12 bits_offset=352
>>>> >> >> > >> >     'dst_port' type_id=20 bits_offset=384
>>>> >> >> > >> >     'dst_ip4' type_id=12 bits_offset=416
>>>> >> >> > >> >     'dst_ip6' type_id=28 bits_offset=448
>>>> >> >> > >> >     'state' type_id=12 bits_offset=576
>>>> >> >> > >> >     'rx_queue_mapping' type_id=10 bits_offset=608
>>>> >> >> > >> > [32] PTR '(anon)' type_id=31
>>>> >> >> > >> > [33] STRUCT '__sk_buff' size=192 vlen=33
>>>> >> >> > >> >     'len' type_id=12 bits_offset=0
>>>> >> >> > >> >     'pkt_type' type_id=12 bits_offset=32
>>>> >> >> > >> >     'mark' type_id=12 bits_offset=64
>>>> >> >> > >> >     'queue_mapping' type_id=12 bits_offset=96
>>>> >> >> > >> >     'protocol' type_id=12 bits_offset=128
>>>> >> >> > >> >     'vlan_present' type_id=12 bits_offset=160
>>>> >> >> > >> >     'vlan_tci' type_id=12 bits_offset=192
>>>> >> >> > >> >     'vlan_proto' type_id=12 bits_offset=224
>>>> >> >> > >> >     'priority' type_id=12 bits_offset=256
>>>> >> >> > >> >     'ingress_ifindex' type_id=12 bits_offset=288
>>>> >> >> > >> >     'ifindex' type_id=12 bits_offset=320
>>>> >> >> > >> >     'tc_index' type_id=12 bits_offset=352
>>>> >> >> > >> >     'cb' type_id=34 bits_offset=384
>>>> >> >> > >> >     'hash' type_id=12 bits_offset=544
>>>> >> >> > >> >     'tc_classid' type_id=12 bits_offset=576
>>>> >> >> > >> >     'data' type_id=12 bits_offset=608
>>>> >> >> > >> >     'data_end' type_id=12 bits_offset=640
>>>> >> >> > >> >     'napi_id' type_id=12 bits_offset=672
>>>> >> >> > >> >     'family' type_id=12 bits_offset=704
>>>> >> >> > >> >     'remote_ip4' type_id=12 bits_offset=736
>>>> >> >> > >> >     'local_ip4' type_id=12 bits_offset=768
>>>> >> >> > >> >     'remote_ip6' type_id=28 bits_offset=800
>>>> >> >> > >> >     'local_ip6' type_id=28 bits_offset=928
>>>> >> >> > >> >     'remote_port' type_id=12 bits_offset=1056
>>>> >> >> > >> >     'local_port' type_id=12 bits_offset=1088
>>>> >> >> > >> >     'data_meta' type_id=12 bits_offset=1120
>>>> >> >> > >> >     '(anon)' type_id=23 bits_offset=1152
>>>> >> >> > >> >     'tstamp' type_id=15 bits_offset=1216
>>>> >> >> > >> >     'wire_len' type_id=12 bits_offset=1280
>>>> >> >> > >> >     'gso_segs' type_id=12 bits_offset=1312
>>>> >> >> > >> >     '(anon)' type_id=30 bits_offset=1344
>>>> >> >> > >> >     'gso_size' type_id=12 bits_offset=1408
>>>> >> >> > >> >     'hwtstamp' type_id=15 bits_offset=1472
>>>> >> >> > >> > [34] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=5
>>>> >> >> > >> > [35] CONST '(anon)' type_id=33
>>>> >> >> > >> > [36] PTR '(anon)' type_id=0
>>>> >> >> > >> > [37] STRUCT '(anon)' size=24 vlen=3
>>>> >> >> > >> >     'type' type_id=39 bits_offset=0
>>>> >> >> > >> >     'key' type_id=40 bits_offset=64
>>>> >> >> > >> >     'value' type_id=41 bits_offset=128
>>>> >> >> > >> > [38] ARRAY '(anon)' type_id=9 index_type_id=16 nr_elems=1
>>>> >> >> > >> > [39] PTR '(anon)' type_id=38
>>>> >> >> > >> > [40] PTR '(anon)' type_id=12
>>>> >> >> > >> > [41] PTR '(anon)' type_id=3
>>>> >> >> > >> > [42] ARRAY '(anon)' type_id=19 index_type_id=16 nr_elems=18
>>>> >> >> > >> > [43] CONST '(anon)' type_id=42
>>>> >> >> > >> > [44] FUNC_PROTO '(anon)' ret_type_id=36 vlen=2
>>>> >> >> > >> >     '(anon)' type_id=36
>>>> >> >> > >> >     '(anon)' type_id=46
>>>> >> >> > >> > [45] CONST '(anon)' type_id=0
>>>> >> >> > >> > [46] PTR '(anon)' type_id=45
>>>> >> >> > >> > [47] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>>>> >> >> > >> >     'sk' type_id=48
>>>> >> >> > >> > [48] PTR '(anon)' type_id=35
>>>> >> >> > >> > [49] VAR '_license' type_id=43, linkage=static
>>>> >> >> > >> > [50] VAR 'is_allow_list' type_id=5, linkage=global
>>>> >> >> > >> > [51] VAR 'sd_restrictif' type_id=37, linkage=global
>>>> >> >> > >> > [52] FUNC 'sd_restrictif_i' type_id=47 linkage=global
>>>> >> >> > >> > [53] FUNC 'sd_restrictif_e' type_id=47 linkage=global
>>>> >> >> > >> > [54] FUNC 'restrict_network_interfaces_impl' type_id=47 linkage=static
>>>> >> >> > >> > [55] DATASEC '.data' size=1 vlen=1
>>>> >> >> > >> >     type_id=50 offset=0 size=1 (VAR 'is_allow_list')
>>>> >> >> > >> > [56] DATASEC 'license' size=18 vlen=1
>>>> >> >> > >> >     type_id=49 offset=0 size=18 (VAR '_license')
>>>> >> >> > >> > [57] DATASEC '.maps' size=24 vlen=1
>>>> >> >> > >> >     type_id=51 offset=0 size=24 (VAR 'sd_restrictif')
>>>> >> >> > >> >
>>>> >> >> > >> > File before being stripped using bpftool gen object:
>>>> >> >> > >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>>>> >> >> > >> > btf dump file
>>>> >> >> > >> >
>>>> >> >
>>>> >
>>
> output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
>>>> >> >> > >> > format raw
>>>> >> >> > >> > [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>>>> >> >> > >> > [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
>>>> >> >> > >> > [3] TYPEDEF '__u8' type_id=2
>>>> >> >> > >> > [4] CONST '(anon)' type_id=3
>>>> >> >> > >> > [5] VOLATILE '(anon)' type_id=4
>>>> >> >> > >> > [6] INT 'short int' size=2 bits_offset=0 nr_bits=16 encoding=SIGNED
>>>> >> >> > >> > [7] INT 'short unsigned int' size=2 bits_offset=0 nr_bits=16 encoding=(none)
>>>> >> >> > >> > [8] TYPEDEF '__u16' type_id=7
>>>> >> >> > >> > [9] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
>>>> >> >> > >> > [10] TYPEDEF '__s32' type_id=9
>>>> >> >> > >> > [11] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
>>>> >> >> > >> > [12] TYPEDEF '__u32' type_id=11
>>>> >> >> > >> > [13] INT 'long long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
>>>> >> >> > >> > [14] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64
>>>> >> >> > >> > encoding=(none)
>>>> >> >> > >> > [15] TYPEDEF '__u64' type_id=14
>>>> >> >> > >> > [16] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
>>>> >> >> > >> > [17] INT 'long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
>>>> >> >> > >> > [18] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>>>> >> >> > >> > [19] CONST '(anon)' type_id=18
>>>> >> >> > >> > [20] TYPEDEF '__be16' type_id=8
>>>> >> >> > >> > [21] TYPEDEF '__be32' type_id=12
>>>> >> >> > >> > [22] ENUM 'bpf_map_type' encoding=UNSIGNED size=4 vlen=31
>>>> >> >> > >> >     'BPF_MAP_TYPE_UNSPEC' val=0
>>>> >> >> > >> >     'BPF_MAP_TYPE_HASH' val=1
>>>> >> >> > >> >     'BPF_MAP_TYPE_ARRAY' val=2
>>>> >> >> > >> >     'BPF_MAP_TYPE_PROG_ARRAY' val=3
>>>> >> >> > >> >     'BPF_MAP_TYPE_PERF_EVENT_ARRAY' val=4
>>>> >> >> > >> >     'BPF_MAP_TYPE_PERCPU_HASH' val=5
>>>> >> >> > >> >     'BPF_MAP_TYPE_PERCPU_ARRAY' val=6
>>>> >> >> > >> >     'BPF_MAP_TYPE_STACK_TRACE' val=7
>>>> >> >> > >> >     'BPF_MAP_TYPE_CGROUP_ARRAY' val=8
>>>> >> >> > >> >     'BPF_MAP_TYPE_LRU_HASH' val=9
>>>> >> >> > >> >     'BPF_MAP_TYPE_LRU_PERCPU_HASH' val=10
>>>> >> >> > >> >     'BPF_MAP_TYPE_LPM_TRIE' val=11
>>>> >> >> > >> >     'BPF_MAP_TYPE_ARRAY_OF_MAPS' val=12
>>>> >> >> > >> >     'BPF_MAP_TYPE_HASH_OF_MAPS' val=13
>>>> >> >> > >> >     'BPF_MAP_TYPE_DEVMAP' val=14
>>>> >> >> > >> >     'BPF_MAP_TYPE_SOCKMAP' val=15
>>>> >> >> > >> >     'BPF_MAP_TYPE_CPUMAP' val=16
>>>> >> >> > >> >     'BPF_MAP_TYPE_XSKMAP' val=17
>>>> >> >> > >> >     'BPF_MAP_TYPE_SOCKHASH' val=18
>>>> >> >> > >> >     'BPF_MAP_TYPE_CGROUP_STORAGE' val=19
>>>> >> >> > >> >     'BPF_MAP_TYPE_REUSEPORT_SOCKARRAY' val=20
>>>> >> >> > >> >     'BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE' val=21
>>>> >> >> > >> >     'BPF_MAP_TYPE_QUEUE' val=22
>>>> >> >> > >> >     'BPF_MAP_TYPE_STACK' val=23
>>>> >> >> > >> >     'BPF_MAP_TYPE_SK_STORAGE' val=24
>>>> >> >> > >> >     'BPF_MAP_TYPE_DEVMAP_HASH' val=25
>>>> >> >> > >> >     'BPF_MAP_TYPE_STRUCT_OPS' val=26
>>>> >> >> > >> >     'BPF_MAP_TYPE_RINGBUF' val=27
>>>> >> >> > >> >     'BPF_MAP_TYPE_INODE_STORAGE' val=28
>>>> >> >> > >> >     'BPF_MAP_TYPE_TASK_STORAGE' val=29
>>>> >> >> > >> >     'BPF_MAP_TYPE_BLOOM_FILTER' val=30
>>>> >> >> > >> > [23] UNION '(anon)' size=8 vlen=1
>>>> >> >> > >> >     'flow_keys' type_id=29 bits_offset=0
>>>> >> >> > >> > [24] STRUCT 'bpf_flow_keys' size=56 vlen=13
>>>> >> >> > >> >     'nhoff' type_id=8 bits_offset=0
>>>> >> >> > >> >     'thoff' type_id=8 bits_offset=16
>>>> >> >> > >> >     'addr_proto' type_id=8 bits_offset=32
>>>> >> >> > >> >     'is_frag' type_id=3 bits_offset=48
>>>> >> >> > >> >     'is_first_frag' type_id=3 bits_offset=56
>>>> >> >> > >> >     'is_encap' type_id=3 bits_offset=64
>>>> >> >> > >> >     'ip_proto' type_id=3 bits_offset=72
>>>> >> >> > >> >     'n_proto' type_id=20 bits_offset=80
>>>> >> >> > >> >     'sport' type_id=20 bits_offset=96
>>>> >> >> > >> >     'dport' type_id=20 bits_offset=112
>>>> >> >> > >> >     '(anon)' type_id=25 bits_offset=128
>>>> >> >> > >> >     'flags' type_id=12 bits_offset=384
>>>> >> >> > >> >     'flow_label' type_id=21 bits_offset=416
>>>> >> >> > >> > [25] UNION '(anon)' size=32 vlen=2
>>>> >> >> > >> >     '(anon)' type_id=26 bits_offset=0
>>>> >> >> > >> >     '(anon)' type_id=27 bits_offset=0
>>>> >> >> > >> > [26] STRUCT '(anon)' size=8 vlen=2
>>>> >> >> > >> >     'ipv4_src' type_id=21 bits_offset=0
>>>> >> >> > >> >     'ipv4_dst' type_id=21 bits_offset=32
>>>> >> >> > >> > [27] STRUCT '(anon)' size=32 vlen=2
>>>> >> >> > >> >     'ipv6_src' type_id=28 bits_offset=0
>>>> >> >> > >> >     'ipv6_dst' type_id=28 bits_offset=128
>>>> >> >> > >> > [28] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=4
>>>> >> >> > >> > [29] PTR '(anon)' type_id=24
>>>> >> >> > >> > [30] UNION '(anon)' size=8 vlen=1
>>>> >> >> > >> >     'sk' type_id=32 bits_offset=0
>>>> >> >> > >> > [31] STRUCT 'bpf_sock' size=80 vlen=14
>>>> >> >> > >> >     'bound_dev_if' type_id=12 bits_offset=0
>>>> >> >> > >> >     'family' type_id=12 bits_offset=32
>>>> >> >> > >> >     'type' type_id=12 bits_offset=64
>>>> >> >> > >> >     'protocol' type_id=12 bits_offset=96
>>>> >> >> > >> >     'mark' type_id=12 bits_offset=128
>>>> >> >> > >> >     'priority' type_id=12 bits_offset=160
>>>> >> >> > >> >     'src_ip4' type_id=12 bits_offset=192
>>>> >> >> > >> >     'src_ip6' type_id=28 bits_offset=224
>>>> >> >> > >> >     'src_port' type_id=12 bits_offset=352
>>>> >> >> > >> >     'dst_port' type_id=20 bits_offset=384
>>>> >> >> > >> >     'dst_ip4' type_id=12 bits_offset=416
>>>> >> >> > >> >     'dst_ip6' type_id=28 bits_offset=448
>>>> >> >> > >> >     'state' type_id=12 bits_offset=576
>>>> >> >> > >> >     'rx_queue_mapping' type_id=10 bits_offset=608
>>>> >> >> > >> > [32] PTR '(anon)' type_id=31
>>>> >> >> > >> > [33] STRUCT '__sk_buff' size=192 vlen=33
>>>> >> >> > >> >     'len' type_id=12 bits_offset=0
>>>> >> >> > >> >     'pkt_type' type_id=12 bits_offset=32
>>>> >> >> > >> >     'mark' type_id=12 bits_offset=64
>>>> >> >> > >> >     'queue_mapping' type_id=12 bits_offset=96
>>>> >> >> > >> >     'protocol' type_id=12 bits_offset=128
>>>> >> >> > >> >     'vlan_present' type_id=12 bits_offset=160
>>>> >> >> > >> >     'vlan_tci' type_id=12 bits_offset=192
>>>> >> >> > >> >     'vlan_proto' type_id=12 bits_offset=224
>>>> >> >> > >> >     'priority' type_id=12 bits_offset=256
>>>> >> >> > >> >     'ingress_ifindex' type_id=12 bits_offset=288
>>>> >> >> > >> >     'ifindex' type_id=12 bits_offset=320
>>>> >> >> > >> >     'tc_index' type_id=12 bits_offset=352
>>>> >> >> > >> >     'cb' type_id=34 bits_offset=384
>>>> >> >> > >> >     'hash' type_id=12 bits_offset=544
>>>> >> >> > >> >     'tc_classid' type_id=12 bits_offset=576
>>>> >> >> > >> >     'data' type_id=12 bits_offset=608
>>>> >> >> > >> >     'data_end' type_id=12 bits_offset=640
>>>> >> >> > >> >     'napi_id' type_id=12 bits_offset=672
>>>> >> >> > >> >     'family' type_id=12 bits_offset=704
>>>> >> >> > >> >     'remote_ip4' type_id=12 bits_offset=736
>>>> >> >> > >> >     'local_ip4' type_id=12 bits_offset=768
>>>> >> >> > >> >     'remote_ip6' type_id=28 bits_offset=800
>>>> >> >> > >> >     'local_ip6' type_id=28 bits_offset=928
>>>> >> >> > >> >     'remote_port' type_id=12 bits_offset=1056
>>>> >> >> > >> >     'local_port' type_id=12 bits_offset=1088
>>>> >> >> > >> >     'data_meta' type_id=12 bits_offset=1120
>>>> >> >> > >> >     '(anon)' type_id=23 bits_offset=1152
>>>> >> >> > >> >     'tstamp' type_id=15 bits_offset=1216
>>>> >> >> > >> >     'wire_len' type_id=12 bits_offset=1280
>>>> >> >> > >> >     'gso_segs' type_id=12 bits_offset=1312
>>>> >> >> > >> >     '(anon)' type_id=30 bits_offset=1344
>>>> >> >> > >> >     'gso_size' type_id=12 bits_offset=1408
>>>> >> >> > >> >     'hwtstamp' type_id=15 bits_offset=1472
>>>> >> >> > >> > [34] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=5
>>>> >> >> > >> > [35] CONST '(anon)' type_id=33
>>>> >> >> > >> > [36] PTR '(anon)' type_id=0
>>>> >> >> > >> > [37] STRUCT '(anon)' size=24 vlen=3
>>>> >> >> > >> >     'type' type_id=39 bits_offset=0
>>>> >> >> > >> >     'key' type_id=40 bits_offset=64
>>>> >> >> > >> >     'value' type_id=41 bits_offset=128
>>>> >> >> > >> > [38] ARRAY '(anon)' type_id=9 index_type_id=16 nr_elems=1
>>>> >> >> > >> > [39] PTR '(anon)' type_id=38
>>>> >> >> > >> > [40] PTR '(anon)' type_id=12
>>>> >> >> > >> > [41] PTR '(anon)' type_id=3
>>>> >> >> > >> > [42] ARRAY '(anon)' type_id=19 index_type_id=16 nr_elems=18
>>>> >> >> > >> > [43] CONST '(anon)' type_id=42
>>>> >> >> > >> > [44] FUNC_PROTO '(anon)' ret_type_id=36 vlen=2
>>>> >> >> > >> >     '(anon)' type_id=36
>>>> >> >> > >> >     '(anon)' type_id=46
>>>> >> >> > >> > [45] CONST '(anon)' type_id=0
>>>> >> >> > >> > [46] PTR '(anon)' type_id=45
>>>> >> >> > >> > [47] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>>>> >> >> > >> >     'sk' type_id=48
>>>> >> >> > >> > [48] PTR '(anon)' type_id=35
>>>> >> >> > >> > [49] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>>>> >> >> > >> >     'sk' type_id=48
>>>> >> >> > >> > [50] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>>>> >> >> > >> >     'sk' type_id=48
>>>> >> >> > >> > [51] VAR '_license' type_id=43, linkage=static
>>>> >> >> > >> > [52] VAR 'is_allow_list' type_id=5, linkage=global
>>>> >> >> > >> > [53] VAR 'sd_restrictif' type_id=37, linkage=global
>>>> >> >> > >> > [54] FUNC 'bpf_map_lookup_elem' type_id=44 linkage=global
>>>> >> >> > >> > [55] FUNC 'sd_restrictif_i' type_id=47 linkage=global
>>>> >> >> > >> > [56] FUNC 'sd_restrictif_e' type_id=49 linkage=global
>>>> >> >> > >> > [57] FUNC 'restrict_network_interfaces_impl' type_id=50 linkage=static
>>>> >> >> > >> > [58] DATASEC 'license' size=0 vlen=1
>>>> >> >> > >> >     type_id=51 offset=0 size=18 (VAR '_license')
>>>> >> >> > >> > [59] DATASEC '.maps' size=0 vlen=1
>>>> >> >> > >> >     type_id=53 offset=0 size=24 (VAR 'sd_restrictif')
>>>> >> >> > >> > [60] DATASEC '.data' size=0 vlen=1
>>>> >> >> > >> >     type_id=52 offset=0 size=1 (VAR 'is_allow_list')
>>>> >> >> > >> >
>>>> >> >> > >> >>
>>>> >> >> > >> >> >> GCC is wrong, clearly. This function is global ([0]) and libbpf
>>>> >> >> > >> >> >> expects it to be marked as such in BTF.
>>>> >> >> > >> >> >>
>>>> >> >> > >> >> >>
>>>> >> >> > >> >
>>>> >> >
>>>> >
>>
> https://github.com/systemd/systemd/blob/main/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.c#L42-L50
>>>> >> >> > >> >> >>
>>>> >> >> > >> >> >>
>>>> >> >> > >> >> >>> GCC:
>>>> >> >> > >> >> >>>
>>>> >> >> > >> >> >>> [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>>>> >> >> > >> >> >>> [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
>>>> >> >> > >> >> >>> [3] TYPEDEF '__u8' type_id=2
>>>> >> >> > >> >> >>> [4] CONST '(anon)' type_id=3
>>>> >> >> > >> >> >>
>>>> >> >> > >> >> >> [...]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-07-10 20:22                               ` Jose E. Marchesi
@ 2022-07-11  1:55                                 ` Jose E. Marchesi
       [not found]                                 ` <CADvTj4o-36iuru665BW0XnEauXBeszW438QTtpt4_VUEjf5nXg@mail.gmail.com>
  1 sibling, 0 replies; 38+ messages in thread
From: Jose E. Marchesi @ 2022-07-11  1:55 UTC (permalink / raw)
  To: James Hilliard; +Cc: Andrii Nakryiko, bpf, david.faust


>>>> On Sun, Jul 10, 2022 at 3:38 AM Jose E. Marchesi
>>>> <jose.marchesi@oracle.com> wrote:
>>>>>
>>>>>
>>>>> > On Sat, Jul 9, 2022 at 4:41 PM Jose E. Marchesi
>>>>> > <jose.marchesi@oracle.com> wrote:
>>>>> >>
>>>>> >>
>>>>> >> > On Sat, Jul 9, 2022 at 2:32 PM James Hilliard <james.hilliard1@gmail.com> wrote:
>>>>> >> >>
>>>>> >> >> On Sat, Jul 9, 2022 at 2:21 PM Jose E. Marchesi
>>>>> >> >> <jose.marchesi@oracle.com> wrote:
>>>>> >> >> >
>>>>> >> >> >
>>>>> >> >> > > On Sat, Jul 9, 2022 at 11:24 AM Jose E. Marchesi
>>>>> >> >> > > <jose.marchesi@oracle.com> wrote:
>>>>> >> >> > >>
>>>>> >> >> > >>
>>>>> >> >> > >> > On Fri, Jul 8, 2022 at 12:33 PM Jose E. Marchesi
>>>>> >> >> > >> > <jose.marchesi@oracle.com> wrote:
>>>>> >> >> > >> >>
>>>>> >> >> > >> >>
>>>>> >> >> > >> >> >> On Wed, Jul 6, 2022 at 10:13 AM James Hilliard
>>>>> >> >> > >> >> >> <james.hilliard1@gmail.com> wrote:
>>>>> >> >> > >> >> >>>
>>>>> >> >> > >> >> >>> Note I'm testing with the following patches:
>>>>> >> >> > >> >> >>>
>>> https://lore.kernel.org/bpf/20220706111839.1247911-1-james.hilliard1@gmail.com/
>>>>> >> >> > >> >> >>>
>>> https://lore.kernel.org/bpf/20220706140623.2917858-1-james.hilliard1@gmail.com/
>>>>> >> >> > >> >> >>>
>>>>> >> >> > >> >> >>> It would appear there's some compatibility issues with bpftool gen and
>>>>> >> >> > >> >> >>> GCC, not sure what side though is wrong here:
>>>>> >> >> > >> >> >>> /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>>>>> >> >> > >> >> >>> gen object src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>>>>> >> >> > >> >> >>> src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
>>>>> >> >> > >> >> >>> libbpf: failed to find BTF info for
> global/extern symbol 'sd_restrictif_i'
>>>>> >> >> > >> >> >>> Error: failed to link
>>>>> >> >> > >> >> >>> 'src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o':
>>>>> >> >> > >> >> >>> Unknown error -2 (-2)
>>>>> >> >> > >> >> >>>
>>>>> >> >> > >> >> >>> Relevant difference seems to be this:
>>>>> >> >> > >> >> >>> GCC:
>>>>> >> >> > >> >> >>> [55] FUNC 'sd_restrictif_i' type_id=47 linkage=static
>>>>> >> >> > >> >> >>> Clang:
>>>>> >> >> > >> >> >>> [27] FUNC 'sd_restrictif_i' type_id=26 linkage=global
>>>>> >> >> > >> >> >
>>>>> >> >> > >> >> > For functions GCC generates a BTF_KIND_FUNC entry, which has no linkage
>>>>> >> >> > >> >> > information, or so we thought: I just looked at bpftool/btf.c and I
>>>>> >> >> > >> >> > found the linkage info for function types is expected to be encoded in
>>>>> >> >> > >> >> > the vlen field of BTF_KIND_FUNC entries (why not adding a btf_func
>>>>> >> >> > >> >> > instead???) which is surprising to say the least.
>>>>> >> >> > >> >> >
>>>>> >> >> > >> >> > We are changing GCC to encode the linkage info in vlen for these types.
>>>>> >> >> > >> >> > Thanks for reporting this.
>>>>> >> >> > >> >>
>>>>> >> >> > >> >> Patch sent to GCC upstream:
>>>>> >> >> > >> >> https://gcc.gnu.org/pipermail/gcc-patches/2022-July/598090.html
>>>>> >> >> > >> >
>>>>> >> >> > >> > I applied that patch on top of GCC 12.1.0 and it appears to fix the
>>>>> >> >> > >> > bpftool gen object bug.
>>>>> >> >> > >> >
>>>>> >> >> > >> > I am however now hitting a different error during skeleton generation:
>>>>> >> >> > >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>>>>> >> >> > >> > gen skeleton src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>>>>> >> >> > >> > libbpf: elf: skipping unrecognized data section(9) .comment
>>>>> >> >> > >> > libbpf: failed to alloc map 'restrict.bss' content buffer: -22
>>>>> >> >> > >> > Error: failed to open BPF object file: Invalid argument
>>>>> >> >> > >>
>>>>> >> >> > >> What is the size of the .bss section in the object file?  Try with:
>>>>> >> >> > >>
>>>>> >> >> > >> $ size restrict-ifaces.bpf.o
>>>>> >> >> > >
>>>>> >> >> > > $ size
>>>>> >> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>>>>> >> >> > >    text       data        bss        dec        hex    filename
>>>>> >> >> > >     386         25          0        411        19b
>>>>> >> >> > >
>>> output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>>>>> >> >> >
>>>>> >> >> > Right, so the .bss section is empty.  I see a `const volatile unsigned
>>>>> >> >> > char is_allow_list = 0;' in restrict-ifaces.bpf.c, but that goes to
>>>>> >> >> > .data and not to .bss, as expected.
>>>>> >> >> >
>>>>> >> >> > If you build restrict-ifaces.bpf.o with LLVM, is the bss still empty?  I
>>>>> >> >> > don't think the code in libbpf.c even checks for this eventuality...
>>>>> >> >>
>>>>> >> >> LLVM version(which skeleton generation works with):
>>>>> >> >> $ size restrict-ifaces.bpf.o
>>>>> >> >>    text       data        bss        dec        hex    filename
>>>>> >> >>     323         24          0        347        15b    restrict-ifaces.bpf.o
>>>>> >> >>
>>>>> >> >> $ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>>>>> >> >> btf dump file restrict-ifaces.bpf.o format raw
>>>>> >> >> [1] PTR '(anon)' type_id=3
>>>>> >> >> [2] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
>>>>> >> >> [3] ARRAY '(anon)' type_id=2 index_type_id=4 nr_elems=1
>>>>> >> >> [4] INT '__ARRAY_SIZE_TYPE__' size=4 bits_offset=0 nr_bits=32 encoding=(none)
>>>>> >> >> [5] PTR '(anon)' type_id=6
>>>>> >> >> [6] TYPEDEF '__u32' type_id=7
>>>>> >> >> [7] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
>>>>> >> >> [8] PTR '(anon)' type_id=9
>>>>> >> >> [9] TYPEDEF '__u8' type_id=10
>>>>> >> >> [10] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=(none)
>>>>> >> >> [11] STRUCT '(anon)' size=24 vlen=3
>>>>> >> >>     'type' type_id=1 bits_offset=0
>>>>> >> >>     'key' type_id=5 bits_offset=64
>>>>> >> >>     'value' type_id=8 bits_offset=128
>>>>> >> >> [12] VAR 'sd_restrictif' type_id=11, linkage=global
>>>>> >> >> [13] PTR '(anon)' type_id=14
>>>>> >> >> [14] CONST '(anon)' type_id=15
>>>>> >> >> [15] STRUCT '__sk_buff' size=192 vlen=33
>>>>> >> >>     'len' type_id=6 bits_offset=0
>>>>> >> >>     'pkt_type' type_id=6 bits_offset=32
>>>>> >> >>     'mark' type_id=6 bits_offset=64
>>>>> >> >>     'queue_mapping' type_id=6 bits_offset=96
>>>>> >> >>     'protocol' type_id=6 bits_offset=128
>>>>> >> >>     'vlan_present' type_id=6 bits_offset=160
>>>>> >> >>     'vlan_tci' type_id=6 bits_offset=192
>>>>> >> >>     'vlan_proto' type_id=6 bits_offset=224
>>>>> >> >>     'priority' type_id=6 bits_offset=256
>>>>> >> >>     'ingress_ifindex' type_id=6 bits_offset=288
>>>>> >> >>     'ifindex' type_id=6 bits_offset=320
>>>>> >> >>     'tc_index' type_id=6 bits_offset=352
>>>>> >> >>     'cb' type_id=16 bits_offset=384
>>>>> >> >>     'hash' type_id=6 bits_offset=544
>>>>> >> >>     'tc_classid' type_id=6 bits_offset=576
>>>>> >> >>     'data' type_id=6 bits_offset=608
>>>>> >> >>     'data_end' type_id=6 bits_offset=640
>>>>> >> >>     'napi_id' type_id=6 bits_offset=672
>>>>> >> >>     'family' type_id=6 bits_offset=704
>>>>> >> >>     'remote_ip4' type_id=6 bits_offset=736
>>>>> >> >>     'local_ip4' type_id=6 bits_offset=768
>>>>> >> >>     'remote_ip6' type_id=17 bits_offset=800
>>>>> >> >>     'local_ip6' type_id=17 bits_offset=928
>>>>> >> >>     'remote_port' type_id=6 bits_offset=1056
>>>>> >> >>     'local_port' type_id=6 bits_offset=1088
>>>>> >> >>     'data_meta' type_id=6 bits_offset=1120
>>>>> >> >>     '(anon)' type_id=18 bits_offset=1152
>>>>> >> >>     'tstamp' type_id=20 bits_offset=1216
>>>>> >> >>     'wire_len' type_id=6 bits_offset=1280
>>>>> >> >>     'gso_segs' type_id=6 bits_offset=1312
>>>>> >> >>     '(anon)' type_id=22 bits_offset=1344
>>>>> >> >>     'gso_size' type_id=6 bits_offset=1408
>>>>> >> >>     'hwtstamp' type_id=20 bits_offset=1472
>>>>> >> >> [16] ARRAY '(anon)' type_id=6 index_type_id=4 nr_elems=5
>>>>> >> >> [17] ARRAY '(anon)' type_id=6 index_type_id=4 nr_elems=4
>>>>> >> >> [18] UNION '(anon)' size=8 vlen=1
>>>>> >> >>     'flow_keys' type_id=19 bits_offset=0
>>>>> >> >> [19] PTR '(anon)' type_id=34
>>>>> >> >> [20] TYPEDEF '__u64' type_id=21
>>>>> >> >> [21] INT 'unsigned long long' size=8 bits_offset=0 nr_bits=64 encoding=(none)
>>>>> >> >> [22] UNION '(anon)' size=8 vlen=1
>>>>> >> >>     'sk' type_id=23 bits_offset=0
>>>>> >> >> [23] PTR '(anon)' type_id=35
>>>>> >> >> [24] FUNC_PROTO '(anon)' ret_type_id=2 vlen=1
>>>>> >> >>     'sk' type_id=13
>>>>> >> >> [25] FUNC 'sd_restrictif_e' type_id=24 linkage=global
>>>>> >> >> [26] FUNC 'sd_restrictif_i' type_id=24 linkage=global
>>>>> >> >> [27] CONST '(anon)' type_id=28
>>>>> >> >> [28] VOLATILE '(anon)' type_id=9
>>>>> >> >> [29] VAR 'is_allow_list' type_id=27, linkage=global
>>>>> >> >> [30] CONST '(anon)' type_id=31
>>>>> >> >> [31] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=SIGNED
>>>>> >> >> [32] ARRAY '(anon)' type_id=30 index_type_id=4 nr_elems=18
>>>>> >> >> [33] VAR '_license' type_id=32, linkage=static
>>>>> >> >> [34] FWD 'bpf_flow_keys' fwd_kind=struct
>>>>> >> >> [35] FWD 'bpf_sock' fwd_kind=struct
>>>>> >> >> [36] DATASEC '.rodata' size=1 vlen=1
>>>>> >> >>     type_id=29 offset=0 size=1 (VAR 'is_allow_list')
>>>>> >> >> [37] DATASEC 'license' size=18 vlen=1
>>>>> >> >>     type_id=33 offset=0 size=18 (VAR '_license')
>>>>> >> >> [38] DATASEC '.maps' size=24 vlen=1
>>>>> >> >>     type_id=12 offset=0 size=24 (VAR 'sd_restrictif')
>>>>> >> >>
>>>>> >> >
>>>>> >> > Skeleton generation debug output for GCC(failing) and LLVM(working)
>>>>> >> > which may be helpful:
>>>>> >>
>>>>> >> Indeed it was helpful :)
>>>>> >>
>>>>> >> The GNU assembler generates an empty .bss section.  This is a well
>>>>> >> established behavior in GAS that happens in all supported targets.
>>>>> >>
>>>>> >> The LLVM assembler doesn't generate an empty .bss section.
>>>>> >>
>>>>> >> bpftool chokes on the empty .bss section.
>>>>> >>
>>>>> >> In this case I would suggest to fix bpf_object__init_global_data_maps in
>>>>> >> order to skip empty sections.
>>>>> >>
>>>>> >> Something like this:
>>>>> >
>>>>> > Hmm, that seems to segfault:
>>>>>
>>>>> Yes, I see in bpf_object__elf_collect that sec_desc->data is not
>>>>> initialized when a section is not recognized.  In this case, this
>>>>> happens with .comment.
>>>>>
>>>>> All right then:
>>>>>
>>>>> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
>>>>> index e89cc9c885b3..887b78780099 100644
>>>>> --- a/tools/lib/bpf/libbpf.c
>>>>> +++ b/tools/lib/bpf/libbpf.c
>>>>> @@ -1591,6 +1591,10 @@ static int bpf_object__init_global_data_maps(struct bpf_object *obj)
>>>>>         for (sec_idx = 1; sec_idx < obj->efile.sec_cnt; sec_idx++) {
>>>>>                 sec_desc = &obj->efile.secs[sec_idx];
>>>>>
>>>>> +                /* Skip recognized sections with size 0.  */
>>>>> +                if (sec_desc->data && sec_desc->data->d_size == 0)
>>>>> +                  continue;
>>>>> +
>>>>>                 switch (sec_desc->sec_type) {
>>>>>                 case SEC_DATA:
>>>>>                         sec_name = elf_sec_name(obj, elf_sec_by_idx(obj, sec_idx));
>>>>
>>>> Ok, skeleton is now getting generated successfully, however it differs from the
>>>> clang version so there's a build error when we include/use the header:
>>>> ../src/core/restrict-ifaces.c: In function ‘prepare_restrict_ifaces_bpf’:
>>>> ../src/core/restrict-ifaces.c:45:14: error: ‘struct
>>>> restrict_ifaces_bpf’ has no member named ‘rodata’; did you mean
>>>> ‘data’?
>>>>    45 |         obj->rodata->is_allow_list = is_allow_list;
>>>>       |              ^~~~~~
>>>>       |              data
>>>>
>>>> The issue appears to be that clang generates "rodata" members in
>>>> restrict_ifaces_bpf while with gcc we get "data" members instead.
>>>
>>> This is because the BPF GCC port is putting the
>>>
>>>   const volatile unsigned char is_allow_list = 0;
>>>
>>> in a .data section instead of .rodata, due to the `volatile'.  The
>>> x86_64 GCC seems to use .rodata.
>>>
>>> Looking at why the PBF port does this...
>>
>> So, turns out GCC puts zero-initialized `const volatile' variables in
>> .data sections (and not .rodata) in all the targets I have tried, like
>> x86_64 and aarch64.
>>
>> So this is a LLVM and GCC divergence :/
>
> See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25521.
>
> You may try, as a workaround:
>
> __attribute__((section(".rodata"))) const volatile unsigned char is_allow_list = 0;
>
> But that will use permissions "aw" for the .rodata section (and you will
> get a warning from the assembler.)  It may be problematic for libbpf.

See also  https://github.com/llvm/llvm-project/issues/56468

>>>> Differences below:
>>>>
>>>> GCC:
>>>> $ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>>>> --debug gen skeleton
>>>> output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>>>> libbpf: loading object 'restrict_ifaces_bpf' from buffer
>>>> libbpf: elf: section(2) .symtab, size 336, link 1, flags 0, type=2
>>>> libbpf: elf: section(3) .data, size 1, link 0, flags 3, type=1
>>>> libbpf: elf: section(4) .bss, size 0, link 0, flags 3, type=8
>>>> libbpf: elf: section(5) cgroup_skb/egress, size 184, link 0, flags 6, type=1
>>>> libbpf: sec 'cgroup_skb/egress': found program 'sd_restrictif_e' at
>>>> insn offset 0 (0 bytes), code size 23 insns (184 bytes)
>>>> libbpf: elf: section(6) cgroup_skb/ingress, size 184, link 0, flags 6, type=1
>>>> libbpf: sec 'cgroup_skb/ingress': found program 'sd_restrictif_i' at
>>>> insn offset 0 (0 bytes), code size 23 insns (184 bytes)
>>>> libbpf: elf: section(7) license, size 18, link 0, flags 2, type=1
>>>> libbpf: license of restrict_ifaces_bpf is LGPL-2.1-or-later
>>>> libbpf: elf: section(8) .maps, size 24, link 0, flags 3, type=1
>>>> libbpf: elf: section(9) .comment, size 49, link 0, flags 30, type=1
>>>> libbpf: elf: skipping unrecognized data section(9) .comment
>>>> libbpf: elf: section(10) .relcgroup_skb/egress, size 32, link 2, flags
>>>> 40, type=9
>>>> libbpf: elf: section(11) .relcgroup_skb/ingress, size 32, link 2,
>>>> flags 40, type=9
>>>> libbpf: elf: section(12) .BTF, size 3606, link 0, flags 0, type=1
>>>> libbpf: looking for externs among 14 symbols...
>>>> libbpf: collected 0 externs total
>>>> libbpf: map 'sd_restrictif': at sec_idx 8, offset 0.
>>>> libbpf: map 'sd_restrictif': found type = 1.
>>>> libbpf: map 'sd_restrictif': found key [12], sz = 4.
>>>> libbpf: map 'sd_restrictif': found value [3], sz = 1.
>>>> libbpf: map 'restrict.data' (global data): at sec_idx 3, offset 0, flags 400.
>>>> libbpf: map 1 is "restrict.data"
>>>> libbpf: sec '.relcgroup_skb/egress': collecting relocation for
>>>> section(5) 'cgroup_skb/egress'
>>>> libbpf: sec '.relcgroup_skb/egress': relo #0: insn #4 against 'sd_restrictif'
>>>> libbpf: prog 'sd_restrictif_e': found map 0 (sd_restrictif, sec 8, off
>>>> 0) for insn #4
>>>> libbpf: sec '.relcgroup_skb/egress': relo #1: insn #7 against 'is_allow_list'
>>>> libbpf: prog 'sd_restrictif_e': found data map 1 (restrict.data, sec
>>>> 3, off 0) for insn 7
>>>> libbpf: sec '.relcgroup_skb/ingress': collecting relocation for
>>>> section(6) 'cgroup_skb/ingress'
>>>> libbpf: sec '.relcgroup_skb/ingress': relo #0: insn #4 against 'sd_restrictif'
>>>> libbpf: prog 'sd_restrictif_i': found map 0 (sd_restrictif, sec 8, off
>>>> 0) for insn #4
>>>> libbpf: sec '.relcgroup_skb/ingress': relo #1: insn #7 against 'is_allow_list'
>>>> libbpf: prog 'sd_restrictif_i': found data map 1 (restrict.data, sec
>>>> 3, off 0) for insn 7
>>>> /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
>>>>
>>>> /* THIS FILE IS AUTOGENERATED BY BPFTOOL! */
>>>> #ifndef __RESTRICT_IFACES_BPF_SKEL_H__
>>>> #define __RESTRICT_IFACES_BPF_SKEL_H__
>>>>
>>>> #include <errno.h>
>>>> #include <stdlib.h>
>>>> #include <bpf/libbpf.h>
>>>>
>>>> struct restrict_ifaces_bpf {
>>>>     struct bpf_object_skeleton *skeleton;
>>>>     struct bpf_object *obj;
>>>>     struct {
>>>>         struct bpf_map *sd_restrictif;
>>>>         struct bpf_map *data;
>>>>     } maps;
>>>>     struct {
>>>>         struct bpf_program *sd_restrictif_e;
>>>>         struct bpf_program *sd_restrictif_i;
>>>>     } progs;
>>>>     struct {
>>>>         struct bpf_link *sd_restrictif_e;
>>>>         struct bpf_link *sd_restrictif_i;
>>>>     } links;
>>>>     struct restrict_ifaces_bpf__data {
>>>>         __u8 is_allow_list;
>>>>     } *data;
>>>>
>>>> #ifdef __cplusplus
>>>>     static inline struct restrict_ifaces_bpf *open(const struct
>>>> bpf_object_open_opts *opts = nullptr);
>>>>     static inline struct restrict_ifaces_bpf *open_and_load();
>>>>     static inline int load(struct restrict_ifaces_bpf *skel);
>>>>     static inline int attach(struct restrict_ifaces_bpf *skel);
>>>>     static inline void detach(struct restrict_ifaces_bpf *skel);
>>>>     static inline void destroy(struct restrict_ifaces_bpf *skel);
>>>>     static inline const void *elf_bytes(size_t *sz);
>>>> #endif /* __cplusplus */
>>>> };
>>>>
>>>> static void
>>>> restrict_ifaces_bpf__destroy(struct restrict_ifaces_bpf *obj)
>>>> {
>>>>     if (!obj)
>>>>         return;
>>>>     if (obj->skeleton)
>>>>         bpf_object__destroy_skeleton(obj->skeleton);
>>>>     free(obj);
>>>> }
>>>>
>>>> static inline int
>>>> restrict_ifaces_bpf__create_skeleton(struct restrict_ifaces_bpf *obj);
>>>>
>>>> static inline struct restrict_ifaces_bpf *
>>>> restrict_ifaces_bpf__open_opts(const struct bpf_object_open_opts *opts)
>>>> {
>>>>     struct restrict_ifaces_bpf *obj;
>>>>     int err;
>>>>
>>>>     obj = (struct restrict_ifaces_bpf *)calloc(1, sizeof(*obj));
>>>>     if (!obj) {
>>>>         errno = ENOMEM;
>>>>         return NULL;
>>>>     }
>>>>
>>>>     err = restrict_ifaces_bpf__create_skeleton(obj);
>>>>     if (err)
>>>>         goto err_out;
>>>>
>>>>     err = bpf_object__open_skeleton(obj->skeleton, opts);
>>>>     if (err)
>>>>         goto err_out;
>>>>
>>>>     return obj;
>>>> err_out:
>>>>     restrict_ifaces_bpf__destroy(obj);
>>>>     errno = -err;
>>>>     return NULL;
>>>> }
>>>>
>>>> static inline struct restrict_ifaces_bpf *
>>>> restrict_ifaces_bpf__open(void)
>>>> {
>>>>     return restrict_ifaces_bpf__open_opts(NULL);
>>>> }
>>>>
>>>> static inline int
>>>> restrict_ifaces_bpf__load(struct restrict_ifaces_bpf *obj)
>>>> {
>>>>     return bpf_object__load_skeleton(obj->skeleton);
>>>> }
>>>>
>>>> static inline struct restrict_ifaces_bpf *
>>>> restrict_ifaces_bpf__open_and_load(void)
>>>> {
>>>>     struct restrict_ifaces_bpf *obj;
>>>>     int err;
>>>>
>>>>     obj = restrict_ifaces_bpf__open();
>>>>     if (!obj)
>>>>         return NULL;
>>>>     err = restrict_ifaces_bpf__load(obj);
>>>>     if (err) {
>>>>         restrict_ifaces_bpf__destroy(obj);
>>>>         errno = -err;
>>>>         return NULL;
>>>>     }
>>>>     return obj;
>>>> }
>>>>
>>>> static inline int
>>>> restrict_ifaces_bpf__attach(struct restrict_ifaces_bpf *obj)
>>>> {
>>>>     return bpf_object__attach_skeleton(obj->skeleton);
>>>> }
>>>>
>>>> static inline void
>>>> restrict_ifaces_bpf__detach(struct restrict_ifaces_bpf *obj)
>>>> {
>>>>     return bpf_object__detach_skeleton(obj->skeleton);
>>>> }
>>>>
>>>> static inline const void *restrict_ifaces_bpf__elf_bytes(size_t *sz);
>>>>
>>>> static inline int
>>>> restrict_ifaces_bpf__create_skeleton(struct restrict_ifaces_bpf *obj)
>>>> {
>>>>     struct bpf_object_skeleton *s;
>>>>     int err;
>>>>
>>>>     s = (struct bpf_object_skeleton *)calloc(1, sizeof(*s));
>>>>     if (!s)    {
>>>>         err = -ENOMEM;
>>>>         goto err;
>>>>     }
>>>>
>>>>     s->sz = sizeof(*s);
>>>>     s->name = "restrict_ifaces_bpf";
>>>>     s->obj = &obj->obj;
>>>>
>>>>     /* maps */
>>>>     s->map_cnt = 2;
>>>>     s->map_skel_sz = sizeof(*s->maps);
>>>>     s->maps = (struct bpf_map_skeleton *)calloc(s->map_cnt, s->map_skel_sz);
>>>>     if (!s->maps) {
>>>>         err = -ENOMEM;
>>>>         goto err;
>>>>     }
>>>>
>>>>     s->maps[0].name = "sd_restrictif";
>>>>     s->maps[0].map = &obj->maps.sd_restrictif;
>>>>
>>>>     s->maps[1].name = "restrict.data";
>>>>     s->maps[1].map = &obj->maps.data;
>>>>     s->maps[1].mmaped = (void **)&obj->data;
>>>>
>>>>     /* programs */
>>>>     s->prog_cnt = 2;
>>>>     s->prog_skel_sz = sizeof(*s->progs);
>>>>     s->progs = (struct bpf_prog_skeleton *)calloc(s->prog_cnt, s->prog_skel_sz);
>>>>     if (!s->progs) {
>>>>         err = -ENOMEM;
>>>>         goto err;
>>>>     }
>>>>
>>>>     s->progs[0].name = "sd_restrictif_e";
>>>>     s->progs[0].prog = &obj->progs.sd_restrictif_e;
>>>>     s->progs[0].link = &obj->links.sd_restrictif_e;
>>>>
>>>>     s->progs[1].name = "sd_restrictif_i";
>>>>     s->progs[1].prog = &obj->progs.sd_restrictif_i;
>>>>     s->progs[1].link = &obj->links.sd_restrictif_i;
>>>>
>>>>     s->data = (void *)restrict_ifaces_bpf__elf_bytes(&s->data_sz);
>>>>
>>>>     obj->skeleton = s;
>>>>     return 0;
>>>> err:
>>>>     bpf_object__destroy_skeleton(s);
>>>>     return err;
>>>> }
>>>>
>>>> static inline const void *restrict_ifaces_bpf__elf_bytes(size_t *sz)
>>>> {
>>>>     *sz = 5616;
>>>>     return (const void *)"\
>>>> \x7f\x45\x4c\x46\x02\x01\x01\0\0\0\0\0\0\0\0\0\x01\0\xf7\0\x01\0\0\0\0\0\0\0\0\
>>>> \0\0\0\0\0\0\0\0\0\0\0\xb0\x12\0\0\0\0\0\0\0\0\0\0\x40\0\0\0\0\0\x40\0\x0d\0\
>>>> \x01\0\0\x2e\x73\x74\x72\x74\x61\x62\0\x2e\x73\x79\x6d\x74\x61\x62\0\x2e\x64\
>>>> \x61\x74\x61\0\x2e\x62\x73\x73\0\x63\x67\x72\x6f\x75\x70\x5f\x73\x6b\x62\x2f\
>>>> \x65\x67\x72\x65\x73\x73\0\x63\x67\x72\x6f\x75\x70\x5f\x73\x6b\x62\x2f\x69\x6e\
>>>> \x67\x72\x65\x73\x73\0\x6c\x69\x63\x65\x6e\x73\x65\0\x2e\x6d\x61\x70\x73\0\x2e\
>>>> \x63\x6f\x6d\x6d\x65\x6e\x74\0\x72\x65\x73\x74\x72\x69\x63\x74\x2d\x69\x66\x61\
>>>> \x63\x65\x73\x2e\x62\x70\x66\x2e\x63\0\x5f\x6c\x69\x63\x65\x6e\x73\x65\0\x73\
>>>> \x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\x5f\x65\0\x73\x64\x5f\x72\x65\
>>>> \x73\x74\x72\x69\x63\x74\x69\x66\0\x69\x73\x5f\x61\x6c\x6c\x6f\x77\x5f\x6c\x69\
>>>> \x73\x74\0\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\x5f\x69\0\x2e\
>>>> \x72\x65\x6c\x63\x67\x72\x6f\x75\x70\x5f\x73\x6b\x62\x2f\x65\x67\x72\x65\x73\
>>>> \x73\0\x2e\x72\x65\x6c\x63\x67\x72\x6f\x75\x70\x5f\x73\x6b\x62\x2f\x69\x6e\x67\
>>>> \x72\x65\x73\x73\0\x2e\x42\x54\x46\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>>> \0\0\0\0\0\0\x58\0\0\0\x04\0\xf1\xff\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>>> \x03\0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x03\0\x04\0\0\0\0\0\0\0\0\
>>>> \0\0\0\0\0\0\0\0\0\0\0\0\0\x03\0\x05\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>>> \x03\0\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x03\0\x07\0\0\0\0\0\0\0\0\
>>>> \0\0\0\0\0\0\0\0\0\x6e\0\0\0\x01\0\x07\0\0\0\0\0\0\0\0\0\x12\0\0\0\0\0\0\0\0\0\
>>>> \0\0\x03\0\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x03\0\x09\0\0\0\0\0\0\
>>>> \0\0\0\0\0\0\0\0\0\0\0\x77\0\0\0\x12\0\x05\0\0\0\0\0\0\0\0\0\xb8\0\0\0\0\0\0\0\
>>>> \x87\0\0\0\x11\0\x08\0\0\0\0\0\0\0\0\0\x18\0\0\0\0\0\0\0\x95\0\0\0\x11\0\x03\0\
>>>> \0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\xa3\0\0\0\x12\0\x06\0\0\0\0\0\0\0\0\0\xb8\0\
>>>> \0\0\0\0\0\0\0\0\0\0\0\0\0\0\x61\x10\x28\0\0\0\0\0\x63\x0a\xfc\xff\0\0\0\0\xbf\
>>>> \xa2\0\0\0\0\0\0\x07\x02\0\0\xfc\xff\xff\xff\x18\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>>> \0\x85\0\0\0\x01\0\0\0\x18\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x71\x13\0\0\0\0\0\0\
>>>> \x57\x03\0\0\xff\0\0\0\x15\x03\x05\0\0\0\0\0\xbf\x02\0\0\0\0\0\0\x87\x02\0\0\0\
>>>> \0\0\0\x4f\x20\0\0\0\0\0\0\x77\0\0\0\x3f\0\0\0\x95\0\0\0\0\0\0\0\xb7\x01\0\0\
>>>> \x01\0\0\0\x15\0\x01\0\0\0\0\0\xbf\x31\0\0\0\0\0\0\xbf\x10\0\0\0\0\0\0\x57\0\0\
>>>> \0\x01\0\0\0\x95\0\0\0\0\0\0\0\x61\x10\x28\0\0\0\0\0\x63\x0a\xfc\xff\0\0\0\0\
>>>> \xbf\xa2\0\0\0\0\0\0\x07\x02\0\0\xfc\xff\xff\xff\x18\x01\0\0\0\0\0\0\0\0\0\0\0\
>>>> \0\0\0\x85\0\0\0\x01\0\0\0\x18\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x71\x13\0\0\0\0\
>>>> \0\0\x57\x03\0\0\xff\0\0\0\x15\x03\x05\0\0\0\0\0\xbf\x02\0\0\0\0\0\0\x87\x02\0\
>>>> \0\0\0\0\0\x4f\x20\0\0\0\0\0\0\x77\0\0\0\x3f\0\0\0\x95\0\0\0\0\0\0\0\xb7\x01\0\
>>>> \0\x01\0\0\0\x15\0\x01\0\0\0\0\0\xbf\x31\0\0\0\0\0\0\xbf\x10\0\0\0\0\0\0\x57\0\
>>>> \0\0\x01\0\0\0\x95\0\0\0\0\0\0\0\x4c\x47\x50\x4c\x2d\x32\x2e\x31\x2d\x6f\x72\
>>>> \x2d\x6c\x61\x74\x65\x72\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>>> \0\0\0\0\0\x47\x43\x43\x3a\x20\x28\x42\x75\x69\x6c\x64\x72\x6f\x6f\x74\x20\x32\
>>>> \x30\x32\x32\x2e\x30\x35\x2d\x31\x33\x32\x2d\x67\x35\x32\x38\x62\x35\x61\x36\
>>>> \x35\x66\x36\x29\x20\x31\x32\x2e\x31\x2e\x30\0\0\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\
>>>> \x01\0\0\0\x0b\0\0\0\x38\0\0\0\0\0\0\0\x01\0\0\0\x0c\0\0\0\x20\0\0\0\0\0\0\0\
>>>> \x01\0\0\0\x0b\0\0\0\x38\0\0\0\0\0\0\0\x01\0\0\0\x0c\0\0\0\x9f\xeb\x01\0\x18\0\
>>>> \0\0\0\0\0\0\x9c\x07\0\0\x9c\x07\0\0\x62\x06\0\0\x01\0\0\0\0\0\0\x01\x01\0\0\0\
>>>> \x08\0\0\x03\x0d\0\0\0\0\0\0\x01\x01\0\0\0\x08\0\0\x02\x1b\0\0\0\0\0\0\x08\x02\
>>>> \0\0\0\0\0\0\0\0\0\0\x0a\x03\0\0\0\0\0\0\0\0\0\0\x09\x04\0\0\0\x20\0\0\0\0\0\0\
>>>> \x01\x02\0\0\0\x10\0\0\x01\x2a\0\0\0\0\0\0\x01\x02\0\0\0\x10\0\0\0\x3d\0\0\0\0\
>>>> \0\0\x08\x07\0\0\0\x43\0\0\0\0\0\0\x01\x04\0\0\0\x20\0\0\x01\x47\0\0\0\0\0\0\
>>>> \x08\x09\0\0\0\x4d\0\0\0\0\0\0\x01\x04\0\0\0\x20\0\0\0\x5a\0\0\0\0\0\0\x08\x0b\
>>>> \0\0\0\x60\0\0\0\0\0\0\x01\x08\0\0\0\x40\0\0\x01\x6e\0\0\0\0\0\0\x01\x08\0\0\0\
>>>> \x40\0\0\0\x85\0\0\0\0\0\0\x08\x0e\0\0\0\x8b\0\0\0\0\0\0\x01\x08\0\0\0\x40\0\0\
>>>> \0\x9d\0\0\0\0\0\0\x01\x08\0\0\0\x40\0\0\x01\xa6\0\0\0\0\0\0\x01\x01\0\0\0\x08\
>>>> \0\0\x03\0\0\0\0\0\0\0\x0a\x12\0\0\0\xab\0\0\0\0\0\0\x08\x08\0\0\0\xb2\0\0\0\0\
>>>> \0\0\x08\x0c\0\0\0\xb9\0\0\0\x1f\0\0\x06\x04\0\0\0\xc6\0\0\0\0\0\0\0\xda\0\0\0\
>>>> \x01\0\0\0\xec\0\0\0\x02\0\0\0\xff\0\0\0\x03\0\0\0\x17\x01\0\0\x04\0\0\0\x35\
>>>> \x01\0\0\x05\0\0\0\x4e\x01\0\0\x06\0\0\0\x68\x01\0\0\x07\0\0\0\x81\x01\0\0\x08\
>>>> \0\0\0\x9b\x01\0\0\x09\0\0\0\xb1\x01\0\0\x0a\0\0\0\xce\x01\0\0\x0b\0\0\0\xe4\
>>>> \x01\0\0\x0c\0\0\0\xff\x01\0\0\x0d\0\0\0\x19\x02\0\0\x0e\0\0\0\x2d\x02\0\0\x0f\
>>>> \0\0\0\x42\x02\0\0\x10\0\0\0\x56\x02\0\0\x11\0\0\0\x6a\x02\0\0\x12\0\0\0\x80\
>>>> \x02\0\0\x13\0\0\0\x9c\x02\0\0\x14\0\0\0\xbd\x02\0\0\x15\0\0\0\xe0\x02\0\0\x16\
>>>> \0\0\0\xf3\x02\0\0\x17\0\0\0\x06\x03\0\0\x18\0\0\0\x1e\x03\0\0\x19\0\0\0\x37\
>>>> \x03\0\0\x1a\0\0\0\x4f\x03\0\0\x1b\0\0\0\x64\x03\0\0\x1c\0\0\0\x7f\x03\0\0\x1d\
>>>> \0\0\0\x99\x03\0\0\x1e\0\0\0\0\0\0\0\x01\0\0\x05\x08\0\0\0\xb3\x03\0\0\x1d\0\0\
>>>> \0\0\0\0\0\xbd\x03\0\0\x0d\0\0\x04\x38\0\0\0\xcb\x03\0\0\x08\0\0\0\0\0\0\0\xd1\
>>>> \x03\0\0\x08\0\0\0\x10\0\0\0\xd7\x03\0\0\x08\0\0\0\x20\0\0\0\xe2\x03\0\0\x03\0\
>>>> \0\0\x30\0\0\0\xea\x03\0\0\x03\0\0\0\x38\0\0\0\xf8\x03\0\0\x03\0\0\0\x40\0\0\0\
>>>> \x01\x04\0\0\x03\0\0\0\x48\0\0\0\x0a\x04\0\0\x14\0\0\0\x50\0\0\0\x12\x04\0\0\
>>>> \x14\0\0\0\x60\0\0\0\x18\x04\0\0\x14\0\0\0\x70\0\0\0\0\0\0\0\x19\0\0\0\x80\0\0\
>>>> \0\x1e\x04\0\0\x0c\0\0\0\x80\x01\0\0\x24\x04\0\0\x15\0\0\0\xa0\x01\0\0\0\0\0\0\
>>>> \x02\0\0\x05\x20\0\0\0\0\0\0\0\x1a\0\0\0\0\0\0\0\0\0\0\0\x1b\0\0\0\0\0\0\0\0\0\
>>>> \0\0\x02\0\0\x04\x08\0\0\0\x2f\x04\0\0\x15\0\0\0\0\0\0\0\x38\x04\0\0\x15\0\0\0\
>>>> \x20\0\0\0\0\0\0\0\x02\0\0\x04\x20\0\0\0\x41\x04\0\0\x1c\0\0\0\0\0\0\0\x4a\x04\
>>>> \0\0\x1c\0\0\0\x80\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x0c\0\0\0\x10\0\0\0\x04\0\0\
>>>> \0\0\0\0\0\0\0\0\x02\x18\0\0\0\0\0\0\0\x01\0\0\x05\x08\0\0\0\x53\x04\0\0\x20\0\
>>>> \0\0\0\0\0\0\x56\x04\0\0\x0e\0\0\x04\x50\0\0\0\x5f\x04\0\0\x0c\0\0\0\0\0\0\0\
>>>> \x6c\x04\0\0\x0c\0\0\0\x20\0\0\0\x73\x04\0\0\x0c\0\0\0\x40\0\0\0\x78\x04\0\0\
>>>> \x0c\0\0\0\x60\0\0\0\x81\x04\0\0\x0c\0\0\0\x80\0\0\0\x86\x04\0\0\x0c\0\0\0\xa0\
>>>> \0\0\0\x8f\x04\0\0\x0c\0\0\0\xc0\0\0\0\x97\x04\0\0\x1c\0\0\0\xe0\0\0\0\x9f\x04\
>>>> \0\0\x0c\0\0\0\x60\x01\0\0\xa8\x04\0\0\x14\0\0\0\x80\x01\0\0\xb1\x04\0\0\x0c\0\
>>>> \0\0\xa0\x01\0\0\xb9\x04\0\0\x1c\0\0\0\xc0\x01\0\0\xc1\x04\0\0\x0c\0\0\0\x40\
>>>> \x02\0\0\xc7\x04\0\0\x0a\0\0\0\x60\x02\0\0\0\0\0\0\0\0\0\x02\x1f\0\0\0\xd8\x04\
>>>> \0\0\x21\0\0\x04\xc0\0\0\0\xe2\x04\0\0\x0c\0\0\0\0\0\0\0\xe6\x04\0\0\x0c\0\0\0\
>>>> \x20\0\0\0\x81\x04\0\0\x0c\0\0\0\x40\0\0\0\xef\x04\0\0\x0c\0\0\0\x60\0\0\0\x78\
>>>> \x04\0\0\x0c\0\0\0\x80\0\0\0\xfd\x04\0\0\x0c\0\0\0\xa0\0\0\0\x0a\x05\0\0\x0c\0\
>>>> \0\0\xc0\0\0\0\x13\x05\0\0\x0c\0\0\0\xe0\0\0\0\x86\x04\0\0\x0c\0\0\0\0\x01\0\0\
>>>> \x1e\x05\0\0\x0c\0\0\0\x20\x01\0\0\x2e\x05\0\0\x0c\0\0\0\x40\x01\0\0\x36\x05\0\
>>>> \0\x0c\0\0\0\x60\x01\0\0\x3f\x05\0\0\x22\0\0\0\x80\x01\0\0\x42\x05\0\0\x0c\0\0\
>>>> \0\x20\x02\0\0\x47\x05\0\0\x0c\0\0\0\x40\x02\0\0\x52\x05\0\0\x0c\0\0\0\x60\x02\
>>>> \0\0\x57\x05\0\0\x0c\0\0\0\x80\x02\0\0\x60\x05\0\0\x0c\0\0\0\xa0\x02\0\0\x6c\
>>>> \x04\0\0\x0c\0\0\0\xc0\x02\0\0\x68\x05\0\0\x0c\0\0\0\xe0\x02\0\0\x73\x05\0\0\
>>>> \x0c\0\0\0\0\x03\0\0\x7d\x05\0\0\x1c\0\0\0\x20\x03\0\0\x88\x05\0\0\x1c\0\0\0\
>>>> \xa0\x03\0\0\x92\x05\0\0\x0c\0\0\0\x20\x04\0\0\x9e\x05\0\0\x0c\0\0\0\x40\x04\0\
>>>> \0\xa9\x05\0\0\x0c\0\0\0\x60\x04\0\0\0\0\0\0\x17\0\0\0\x80\x04\0\0\xb3\x05\0\0\
>>>> \x0f\0\0\0\xc0\x04\0\0\xba\x05\0\0\x0c\0\0\0\0\x05\0\0\xc3\x05\0\0\x0c\0\0\0\
>>>> \x20\x05\0\0\0\0\0\0\x1e\0\0\0\x40\x05\0\0\xcc\x05\0\0\x0c\0\0\0\x80\x05\0\0\
>>>> \xd5\x05\0\0\x0f\0\0\0\xc0\x05\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x0c\0\0\0\x10\0\0\
>>>> \0\x05\0\0\0\0\0\0\0\0\0\0\x0a\x21\0\0\0\0\0\0\0\0\0\0\x02\0\0\0\0\0\0\0\0\x03\
>>>> \0\0\x04\x18\0\0\0\x73\x04\0\0\x27\0\0\0\0\0\0\0\xde\x05\0\0\x28\0\0\0\x40\0\0\
>>>> \0\xe2\x05\0\0\x29\0\0\0\x80\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x09\0\0\0\x10\0\0\
>>>> \0\x01\0\0\0\0\0\0\0\0\0\0\x02\x26\0\0\0\0\0\0\0\0\0\0\x02\x0c\0\0\0\0\0\0\0\0\
>>>> \0\0\x02\x03\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x13\0\0\0\x10\0\0\0\x12\0\0\0\0\0\
>>>> \0\0\0\0\0\x0a\x2a\0\0\0\0\0\0\0\x02\0\0\x0d\x24\0\0\0\0\0\0\0\x24\0\0\0\0\0\0\
>>>> \0\x2e\0\0\0\0\0\0\0\0\0\0\x0a\0\0\0\0\0\0\0\0\0\0\0\x02\x2d\0\0\0\0\0\0\0\x01\
>>>> \0\0\x0d\x09\0\0\0\x53\x04\0\0\x30\0\0\0\0\0\0\0\0\0\0\x02\x23\0\0\0\xe8\x05\0\
>>>> \0\0\0\0\x0e\x2b\0\0\0\0\0\0\0\xf1\x05\0\0\0\0\0\x0e\x05\0\0\0\x01\0\0\0\xff\
>>>> \x05\0\0\0\0\0\x0e\x25\0\0\0\x01\0\0\0\x0d\x06\0\0\x01\0\0\x0c\x2f\0\0\0\x1d\
>>>> \x06\0\0\x01\0\0\x0c\x2f\0\0\0\x2d\x06\0\0\0\0\0\x0c\x2f\0\0\0\x4e\x06\0\0\x01\
>>>> \0\0\x0f\x01\0\0\0\x32\0\0\0\0\0\0\0\x01\0\0\0\x54\x06\0\0\x01\0\0\x0f\x12\0\0\
>>>> \0\x31\0\0\0\0\0\0\0\x12\0\0\0\x5c\x06\0\0\x01\0\0\x0f\x18\0\0\0\x33\0\0\0\0\0\
>>>> \0\0\x18\0\0\0\0\x73\x69\x67\x6e\x65\x64\x20\x63\x68\x61\x72\0\x75\x6e\x73\x69\
>>>> \x67\x6e\x65\x64\x20\x63\x68\x61\x72\0\x5f\x5f\x75\x38\0\x73\x68\x6f\x72\x74\
>>>> \x20\x69\x6e\x74\0\x73\x68\x6f\x72\x74\x20\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\
>>>> \x69\x6e\x74\0\x5f\x5f\x75\x31\x36\0\x69\x6e\x74\0\x5f\x5f\x73\x33\x32\0\x75\
>>>> \x6e\x73\x69\x67\x6e\x65\x64\x20\x69\x6e\x74\0\x5f\x5f\x75\x33\x32\0\x6c\x6f\
>>>> \x6e\x67\x20\x6c\x6f\x6e\x67\x20\x69\x6e\x74\0\x6c\x6f\x6e\x67\x20\x6c\x6f\x6e\
>>>> \x67\x20\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x69\x6e\x74\0\x5f\x5f\x75\x36\x34\
>>>> \0\x6c\x6f\x6e\x67\x20\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x69\x6e\x74\0\x6c\
>>>> \x6f\x6e\x67\x20\x69\x6e\x74\0\x63\x68\x61\x72\0\x5f\x5f\x62\x65\x31\x36\0\x5f\
>>>> \x5f\x62\x65\x33\x32\0\x62\x70\x66\x5f\x6d\x61\x70\x5f\x74\x79\x70\x65\0\x42\
>>>> \x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x55\x4e\x53\x50\x45\x43\0\x42\
>>>> \x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x48\x41\x53\x48\0\x42\x50\x46\
>>>> \x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x41\x52\x52\x41\x59\0\x42\x50\x46\x5f\
>>>> \x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x50\x52\x4f\x47\x5f\x41\x52\x52\x41\x59\0\
>>>> \x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x50\x45\x52\x46\x5f\x45\
>>>> \x56\x45\x4e\x54\x5f\x41\x52\x52\x41\x59\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\
>>>> \x59\x50\x45\x5f\x50\x45\x52\x43\x50\x55\x5f\x48\x41\x53\x48\0\x42\x50\x46\x5f\
>>>> \x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x50\x45\x52\x43\x50\x55\x5f\x41\x52\x52\
>>>> \x41\x59\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x53\x54\x41\x43\
>>>> \x4b\x5f\x54\x52\x41\x43\x45\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\
>>>> \x5f\x43\x47\x52\x4f\x55\x50\x5f\x41\x52\x52\x41\x59\0\x42\x50\x46\x5f\x4d\x41\
>>>> \x50\x5f\x54\x59\x50\x45\x5f\x4c\x52\x55\x5f\x48\x41\x53\x48\0\x42\x50\x46\x5f\
>>>> \x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x4c\x52\x55\x5f\x50\x45\x52\x43\x50\x55\
>>>> \x5f\x48\x41\x53\x48\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x4c\
>>>> \x50\x4d\x5f\x54\x52\x49\x45\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\
>>>> \x5f\x41\x52\x52\x41\x59\x5f\x4f\x46\x5f\x4d\x41\x50\x53\0\x42\x50\x46\x5f\x4d\
>>>> \x41\x50\x5f\x54\x59\x50\x45\x5f\x48\x41\x53\x48\x5f\x4f\x46\x5f\x4d\x41\x50\
>>>> \x53\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x44\x45\x56\x4d\x41\
>>>> \x50\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x53\x4f\x43\x4b\x4d\
>>>> \x41\x50\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x43\x50\x55\x4d\
>>>> \x41\x50\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x58\x53\x4b\x4d\
>>>> \x41\x50\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x53\x4f\x43\x4b\
>>>> \x48\x41\x53\x48\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x43\x47\
>>>> \x52\x4f\x55\x50\x5f\x53\x54\x4f\x52\x41\x47\x45\0\x42\x50\x46\x5f\x4d\x41\x50\
>>>> \x5f\x54\x59\x50\x45\x5f\x52\x45\x55\x53\x45\x50\x4f\x52\x54\x5f\x53\x4f\x43\
>>>> \x4b\x41\x52\x52\x41\x59\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\
>>>> \x50\x45\x52\x43\x50\x55\x5f\x43\x47\x52\x4f\x55\x50\x5f\x53\x54\x4f\x52\x41\
>>>> \x47\x45\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x51\x55\x45\x55\
>>>> \x45\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x53\x54\x41\x43\x4b\
>>>> \0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x53\x4b\x5f\x53\x54\x4f\
>>>> \x52\x41\x47\x45\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x44\x45\
>>>> \x56\x4d\x41\x50\x5f\x48\x41\x53\x48\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\
>>>> \x50\x45\x5f\x53\x54\x52\x55\x43\x54\x5f\x4f\x50\x53\0\x42\x50\x46\x5f\x4d\x41\
>>>> \x50\x5f\x54\x59\x50\x45\x5f\x52\x49\x4e\x47\x42\x55\x46\0\x42\x50\x46\x5f\x4d\
>>>> \x41\x50\x5f\x54\x59\x50\x45\x5f\x49\x4e\x4f\x44\x45\x5f\x53\x54\x4f\x52\x41\
>>>> \x47\x45\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\x45\x5f\x54\x41\x53\x4b\
>>>> \x5f\x53\x54\x4f\x52\x41\x47\x45\0\x42\x50\x46\x5f\x4d\x41\x50\x5f\x54\x59\x50\
>>>> \x45\x5f\x42\x4c\x4f\x4f\x4d\x5f\x46\x49\x4c\x54\x45\x52\0\x66\x6c\x6f\x77\x5f\
>>>> \x6b\x65\x79\x73\0\x62\x70\x66\x5f\x66\x6c\x6f\x77\x5f\x6b\x65\x79\x73\0\x6e\
>>>> \x68\x6f\x66\x66\0\x74\x68\x6f\x66\x66\0\x61\x64\x64\x72\x5f\x70\x72\x6f\x74\
>>>> \x6f\0\x69\x73\x5f\x66\x72\x61\x67\0\x69\x73\x5f\x66\x69\x72\x73\x74\x5f\x66\
>>>> \x72\x61\x67\0\x69\x73\x5f\x65\x6e\x63\x61\x70\0\x69\x70\x5f\x70\x72\x6f\x74\
>>>> \x6f\0\x6e\x5f\x70\x72\x6f\x74\x6f\0\x73\x70\x6f\x72\x74\0\x64\x70\x6f\x72\x74\
>>>> \0\x66\x6c\x61\x67\x73\0\x66\x6c\x6f\x77\x5f\x6c\x61\x62\x65\x6c\0\x69\x70\x76\
>>>> \x34\x5f\x73\x72\x63\0\x69\x70\x76\x34\x5f\x64\x73\x74\0\x69\x70\x76\x36\x5f\
>>>> \x73\x72\x63\0\x69\x70\x76\x36\x5f\x64\x73\x74\0\x73\x6b\0\x62\x70\x66\x5f\x73\
>>>> \x6f\x63\x6b\0\x62\x6f\x75\x6e\x64\x5f\x64\x65\x76\x5f\x69\x66\0\x66\x61\x6d\
>>>> \x69\x6c\x79\0\x74\x79\x70\x65\0\x70\x72\x6f\x74\x6f\x63\x6f\x6c\0\x6d\x61\x72\
>>>> \x6b\0\x70\x72\x69\x6f\x72\x69\x74\x79\0\x73\x72\x63\x5f\x69\x70\x34\0\x73\x72\
>>>> \x63\x5f\x69\x70\x36\0\x73\x72\x63\x5f\x70\x6f\x72\x74\0\x64\x73\x74\x5f\x70\
>>>> \x6f\x72\x74\0\x64\x73\x74\x5f\x69\x70\x34\0\x64\x73\x74\x5f\x69\x70\x36\0\x73\
>>>> \x74\x61\x74\x65\0\x72\x78\x5f\x71\x75\x65\x75\x65\x5f\x6d\x61\x70\x70\x69\x6e\
>>>> \x67\0\x5f\x5f\x73\x6b\x5f\x62\x75\x66\x66\0\x6c\x65\x6e\0\x70\x6b\x74\x5f\x74\
>>>> \x79\x70\x65\0\x71\x75\x65\x75\x65\x5f\x6d\x61\x70\x70\x69\x6e\x67\0\x76\x6c\
>>>> \x61\x6e\x5f\x70\x72\x65\x73\x65\x6e\x74\0\x76\x6c\x61\x6e\x5f\x74\x63\x69\0\
>>>> \x76\x6c\x61\x6e\x5f\x70\x72\x6f\x74\x6f\0\x69\x6e\x67\x72\x65\x73\x73\x5f\x69\
>>>> \x66\x69\x6e\x64\x65\x78\0\x69\x66\x69\x6e\x64\x65\x78\0\x74\x63\x5f\x69\x6e\
>>>> \x64\x65\x78\0\x63\x62\0\x68\x61\x73\x68\0\x74\x63\x5f\x63\x6c\x61\x73\x73\x69\
>>>> \x64\0\x64\x61\x74\x61\0\x64\x61\x74\x61\x5f\x65\x6e\x64\0\x6e\x61\x70\x69\x5f\
>>>> \x69\x64\0\x72\x65\x6d\x6f\x74\x65\x5f\x69\x70\x34\0\x6c\x6f\x63\x61\x6c\x5f\
>>>> \x69\x70\x34\0\x72\x65\x6d\x6f\x74\x65\x5f\x69\x70\x36\0\x6c\x6f\x63\x61\x6c\
>>>> \x5f\x69\x70\x36\0\x72\x65\x6d\x6f\x74\x65\x5f\x70\x6f\x72\x74\0\x6c\x6f\x63\
>>>> \x61\x6c\x5f\x70\x6f\x72\x74\0\x64\x61\x74\x61\x5f\x6d\x65\x74\x61\0\x74\x73\
>>>> \x74\x61\x6d\x70\0\x77\x69\x72\x65\x5f\x6c\x65\x6e\0\x67\x73\x6f\x5f\x73\x65\
>>>> \x67\x73\0\x67\x73\x6f\x5f\x73\x69\x7a\x65\0\x68\x77\x74\x73\x74\x61\x6d\x70\0\
>>>> \x6b\x65\x79\0\x76\x61\x6c\x75\x65\0\x5f\x6c\x69\x63\x65\x6e\x73\x65\0\x69\x73\
>>>> \x5f\x61\x6c\x6c\x6f\x77\x5f\x6c\x69\x73\x74\0\x73\x64\x5f\x72\x65\x73\x74\x72\
>>>> \x69\x63\x74\x69\x66\0\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\x5f\
>>>> \x69\0\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\x5f\x65\0\x72\x65\
>>>> \x73\x74\x72\x69\x63\x74\x5f\x6e\x65\x74\x77\x6f\x72\x6b\x5f\x69\x6e\x74\x65\
>>>> \x72\x66\x61\x63\x65\x73\x5f\x69\x6d\x70\x6c\0\x2e\x64\x61\x74\x61\0\x6c\x69\
>>>> \x63\x65\x6e\x73\x65\0\x2e\x6d\x61\x70\x73\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>>> \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>>> \0\0\0\0\0\0\0\0\0\0\x01\0\0\0\x03\0\0\0\x20\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x40\
>>>> \0\0\0\0\0\0\0\xe5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>>> \0\0\x09\0\0\0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x28\x01\0\0\0\0\0\0\
>>>> \x50\x01\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\x18\0\0\0\0\0\0\0\x11\
>>>> \0\0\0\x01\0\0\0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x78\x02\0\0\0\0\0\0\x01\0\0\
>>>> \0\0\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x17\0\0\0\x08\0\0\
>>>> \0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x79\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>>> \0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x1c\0\0\0\x01\0\0\0\x06\0\0\0\0\0\
>>>> \0\0\0\0\0\0\0\0\0\0\x80\x02\0\0\0\0\0\0\xb8\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\
>>>> \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x2e\0\0\0\x01\0\0\0\x06\0\0\0\0\0\0\0\0\0\0\0\0\
>>>> \0\0\0\x38\x03\0\0\0\0\0\0\xb8\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\
>>>> \0\0\0\0\0\0\0\0\x41\0\0\0\x01\0\0\0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xf0\x03\
>>>> \0\0\0\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>>> \0\x49\0\0\0\x01\0\0\0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\x04\0\0\0\0\0\0\
>>>> \x18\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x4f\0\0\0\
>>>> \x01\0\0\0\x30\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x20\x04\0\0\0\0\0\0\x31\0\0\0\0\0\
>>>> \0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\xb3\0\0\0\x09\0\0\0\
>>>> \x40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x58\x04\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\x02\0\
>>>> \0\0\x05\0\0\0\x08\0\0\0\0\0\0\0\x10\0\0\0\0\0\0\0\xc9\0\0\0\x09\0\0\0\x40\0\0\
>>>> \0\0\0\0\0\0\0\0\0\0\0\0\0\x78\x04\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\x02\0\0\0\x06\
>>>> \0\0\0\x08\0\0\0\0\0\0\0\x10\0\0\0\0\0\0\0\xe0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\
>>>> \0\0\0\0\0\0\0\0\x98\x04\0\0\0\0\0\0\x16\x0e\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\
>>>> \0\0\0\0\0\0\0\0\0\0\0\0\0\0";
>>>> }
>>>>
>>>> #ifdef __cplusplus
>>>> struct restrict_ifaces_bpf *restrict_ifaces_bpf::open(const struct
>>>> bpf_object_open_opts *opts) { return
>>>> restrict_ifaces_bpf__open_opts(opts); }
>>>> struct restrict_ifaces_bpf *restrict_ifaces_bpf::open_and_load() {
>>>> return restrict_ifaces_bpf__open_and_load(); }
>>>> int restrict_ifaces_bpf::load(struct restrict_ifaces_bpf *skel) {
>>>> return restrict_ifaces_bpf__load(skel); }
>>>> int restrict_ifaces_bpf::attach(struct restrict_ifaces_bpf *skel) {
>>>> return restrict_ifaces_bpf__attach(skel); }
>>>> void restrict_ifaces_bpf::detach(struct restrict_ifaces_bpf *skel) {
>>>> restrict_ifaces_bpf__detach(skel); }
>>>> void restrict_ifaces_bpf::destroy(struct restrict_ifaces_bpf *skel) {
>>>> restrict_ifaces_bpf__destroy(skel); }
>>>> const void *restrict_ifaces_bpf::elf_bytes(size_t *sz) { return
>>>> restrict_ifaces_bpf__elf_bytes(sz); }
>>>> #endif /* __cplusplus */
>>>>
>>>> __attribute__((unused)) static void
>>>> restrict_ifaces_bpf__assert(struct restrict_ifaces_bpf *s
>>>> __attribute__((unused)))
>>>> {
>>>> #ifdef __cplusplus
>>>> #define _Static_assert static_assert
>>>> #endif
>>>>     _Static_assert(sizeof(s->data->is_allow_list) == 1, "unexpected
>>>> size of 'is_allow_list'");
>>>> #ifdef __cplusplus
>>>> #undef _Static_assert
>>>> #endif
>>>> }
>>>>
>>>> #endif /* __RESTRICT_IFACES_BPF_SKEL_H__ */
>>>>
>>>> Clang:
>>>> $ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>>>> --debug gen skeleton restrict-ifaces.bpf.o
>>>> libbpf: loading object 'restrict_ifaces_bpf' from buffer
>>>> libbpf: elf: section(2) .symtab, size 384, link 1, flags 0, type=2
>>>> libbpf: elf: section(3) cgroup_skb/egress, size 152, link 0, flags 6, type=1
>>>> libbpf: sec 'cgroup_skb/egress': found program 'sd_restrictif_e' at
>>>> insn offset 0 (0 bytes), code size 19 insns (152 bytes)
>>>> libbpf: elf: section(4) cgroup_skb/ingress, size 152, link 0, flags 6, type=1
>>>> libbpf: sec 'cgroup_skb/ingress': found program 'sd_restrictif_i' at
>>>> insn offset 0 (0 bytes), code size 19 insns (152 bytes)
>>>> libbpf: elf: section(5) .rodata, size 1, link 0, flags 2, type=1
>>>> libbpf: elf: section(6) license, size 18, link 0, flags 2, type=1
>>>> libbpf: license of restrict_ifaces_bpf is LGPL-2.1-or-later
>>>> libbpf: elf: section(7) .maps, size 24, link 0, flags 3, type=1
>>>> libbpf: elf: section(8) .relcgroup_skb/egress, size 32, link 2, flags 40, type=9
>>>> libbpf: elf: section(9) .relcgroup_skb/ingress, size 32, link 2, flags
>>>> 40, type=9
>>>> libbpf: elf: section(10) .BTF, size 1988, link 0, flags 0, type=1
>>>> libbpf: elf: section(11) .BTF.ext, size 376, link 0, flags 0, type=1
>>>> libbpf: looking for externs among 16 symbols...
>>>> libbpf: collected 0 externs total
>>>> libbpf: map 'sd_restrictif': at sec_idx 7, offset 0.
>>>> libbpf: map 'sd_restrictif': found type = 1.
>>>> libbpf: map 'sd_restrictif': found key [6], sz = 4.
>>>> libbpf: map 'sd_restrictif': found value [9], sz = 1.
>>>> libbpf: map 'restrict.rodata' (global data): at sec_idx 5, offset 0, flags 480.
>>>> libbpf: map 1 is "restrict.rodata"
>>>> libbpf: sec '.relcgroup_skb/egress': collecting relocation for
>>>> section(3) 'cgroup_skb/egress'
>>>> libbpf: sec '.relcgroup_skb/egress': relo #0: insn #4 against 'sd_restrictif'
>>>> libbpf: prog 'sd_restrictif_e': found map 0 (sd_restrictif, sec 7, off
>>>> 0) for insn #4
>>>> libbpf: sec '.relcgroup_skb/egress': relo #1: insn #7 against 'is_allow_list'
>>>> libbpf: prog 'sd_restrictif_e': found data map 1 (restrict.rodata, sec
>>>> 5, off 0) for insn 7
>>>> libbpf: sec '.relcgroup_skb/ingress': collecting relocation for
>>>> section(4) 'cgroup_skb/ingress'
>>>> libbpf: sec '.relcgroup_skb/ingress': relo #0: insn #4 against 'sd_restrictif'
>>>> libbpf: prog 'sd_restrictif_i': found map 0 (sd_restrictif, sec 7, off
>>>> 0) for insn #4
>>>> libbpf: sec '.relcgroup_skb/ingress': relo #1: insn #7 against 'is_allow_list'
>>>> libbpf: prog 'sd_restrictif_i': found data map 1 (restrict.rodata, sec
>>>> 5, off 0) for insn 7
>>>> /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
>>>>
>>>> /* THIS FILE IS AUTOGENERATED BY BPFTOOL! */
>>>> #ifndef __RESTRICT_IFACES_BPF_SKEL_H__
>>>> #define __RESTRICT_IFACES_BPF_SKEL_H__
>>>>
>>>> #include <errno.h>
>>>> #include <stdlib.h>
>>>> #include <bpf/libbpf.h>
>>>>
>>>> struct restrict_ifaces_bpf {
>>>>     struct bpf_object_skeleton *skeleton;
>>>>     struct bpf_object *obj;
>>>>     struct {
>>>>         struct bpf_map *sd_restrictif;
>>>>         struct bpf_map *rodata;
>>>>     } maps;
>>>>     struct {
>>>>         struct bpf_program *sd_restrictif_e;
>>>>         struct bpf_program *sd_restrictif_i;
>>>>     } progs;
>>>>     struct {
>>>>         struct bpf_link *sd_restrictif_e;
>>>>         struct bpf_link *sd_restrictif_i;
>>>>     } links;
>>>>     struct restrict_ifaces_bpf__rodata {
>>>>         __u8 is_allow_list;
>>>>     } *rodata;
>>>>
>>>> #ifdef __cplusplus
>>>>     static inline struct restrict_ifaces_bpf *open(const struct
>>>> bpf_object_open_opts *opts = nullptr);
>>>>     static inline struct restrict_ifaces_bpf *open_and_load();
>>>>     static inline int load(struct restrict_ifaces_bpf *skel);
>>>>     static inline int attach(struct restrict_ifaces_bpf *skel);
>>>>     static inline void detach(struct restrict_ifaces_bpf *skel);
>>>>     static inline void destroy(struct restrict_ifaces_bpf *skel);
>>>>     static inline const void *elf_bytes(size_t *sz);
>>>> #endif /* __cplusplus */
>>>> };
>>>>
>>>> static void
>>>> restrict_ifaces_bpf__destroy(struct restrict_ifaces_bpf *obj)
>>>> {
>>>>     if (!obj)
>>>>         return;
>>>>     if (obj->skeleton)
>>>>         bpf_object__destroy_skeleton(obj->skeleton);
>>>>     free(obj);
>>>> }
>>>>
>>>> static inline int
>>>> restrict_ifaces_bpf__create_skeleton(struct restrict_ifaces_bpf *obj);
>>>>
>>>> static inline struct restrict_ifaces_bpf *
>>>> restrict_ifaces_bpf__open_opts(const struct bpf_object_open_opts *opts)
>>>> {
>>>>     struct restrict_ifaces_bpf *obj;
>>>>     int err;
>>>>
>>>>     obj = (struct restrict_ifaces_bpf *)calloc(1, sizeof(*obj));
>>>>     if (!obj) {
>>>>         errno = ENOMEM;
>>>>         return NULL;
>>>>     }
>>>>
>>>>     err = restrict_ifaces_bpf__create_skeleton(obj);
>>>>     if (err)
>>>>         goto err_out;
>>>>
>>>>     err = bpf_object__open_skeleton(obj->skeleton, opts);
>>>>     if (err)
>>>>         goto err_out;
>>>>
>>>>     return obj;
>>>> err_out:
>>>>     restrict_ifaces_bpf__destroy(obj);
>>>>     errno = -err;
>>>>     return NULL;
>>>> }
>>>>
>>>> static inline struct restrict_ifaces_bpf *
>>>> restrict_ifaces_bpf__open(void)
>>>> {
>>>>     return restrict_ifaces_bpf__open_opts(NULL);
>>>> }
>>>>
>>>> static inline int
>>>> restrict_ifaces_bpf__load(struct restrict_ifaces_bpf *obj)
>>>> {
>>>>     return bpf_object__load_skeleton(obj->skeleton);
>>>> }
>>>>
>>>> static inline struct restrict_ifaces_bpf *
>>>> restrict_ifaces_bpf__open_and_load(void)
>>>> {
>>>>     struct restrict_ifaces_bpf *obj;
>>>>     int err;
>>>>
>>>>     obj = restrict_ifaces_bpf__open();
>>>>     if (!obj)
>>>>         return NULL;
>>>>     err = restrict_ifaces_bpf__load(obj);
>>>>     if (err) {
>>>>         restrict_ifaces_bpf__destroy(obj);
>>>>         errno = -err;
>>>>         return NULL;
>>>>     }
>>>>     return obj;
>>>> }
>>>>
>>>> static inline int
>>>> restrict_ifaces_bpf__attach(struct restrict_ifaces_bpf *obj)
>>>> {
>>>>     return bpf_object__attach_skeleton(obj->skeleton);
>>>> }
>>>>
>>>> static inline void
>>>> restrict_ifaces_bpf__detach(struct restrict_ifaces_bpf *obj)
>>>> {
>>>>     return bpf_object__detach_skeleton(obj->skeleton);
>>>> }
>>>>
>>>> static inline const void *restrict_ifaces_bpf__elf_bytes(size_t *sz);
>>>>
>>>> static inline int
>>>> restrict_ifaces_bpf__create_skeleton(struct restrict_ifaces_bpf *obj)
>>>> {
>>>>     struct bpf_object_skeleton *s;
>>>>     int err;
>>>>
>>>>     s = (struct bpf_object_skeleton *)calloc(1, sizeof(*s));
>>>>     if (!s)    {
>>>>         err = -ENOMEM;
>>>>         goto err;
>>>>     }
>>>>
>>>>     s->sz = sizeof(*s);
>>>>     s->name = "restrict_ifaces_bpf";
>>>>     s->obj = &obj->obj;
>>>>
>>>>     /* maps */
>>>>     s->map_cnt = 2;
>>>>     s->map_skel_sz = sizeof(*s->maps);
>>>>     s->maps = (struct bpf_map_skeleton *)calloc(s->map_cnt, s->map_skel_sz);
>>>>     if (!s->maps) {
>>>>         err = -ENOMEM;
>>>>         goto err;
>>>>     }
>>>>
>>>>     s->maps[0].name = "sd_restrictif";
>>>>     s->maps[0].map = &obj->maps.sd_restrictif;
>>>>
>>>>     s->maps[1].name = "restrict.rodata";
>>>>     s->maps[1].map = &obj->maps.rodata;
>>>>     s->maps[1].mmaped = (void **)&obj->rodata;
>>>>
>>>>     /* programs */
>>>>     s->prog_cnt = 2;
>>>>     s->prog_skel_sz = sizeof(*s->progs);
>>>>     s->progs = (struct bpf_prog_skeleton *)calloc(s->prog_cnt, s->prog_skel_sz);
>>>>     if (!s->progs) {
>>>>         err = -ENOMEM;
>>>>         goto err;
>>>>     }
>>>>
>>>>     s->progs[0].name = "sd_restrictif_e";
>>>>     s->progs[0].prog = &obj->progs.sd_restrictif_e;
>>>>     s->progs[0].link = &obj->links.sd_restrictif_e;
>>>>
>>>>     s->progs[1].name = "sd_restrictif_i";
>>>>     s->progs[1].prog = &obj->progs.sd_restrictif_i;
>>>>     s->progs[1].link = &obj->links.sd_restrictif_i;
>>>>
>>>>     s->data = (void *)restrict_ifaces_bpf__elf_bytes(&s->data_sz);
>>>>
>>>>     obj->skeleton = s;
>>>>     return 0;
>>>> err:
>>>>     bpf_object__destroy_skeleton(s);
>>>>     return err;
>>>> }
>>>>
>>>> static inline const void *restrict_ifaces_bpf__elf_bytes(size_t *sz)
>>>> {
>>>>     *sz = 4272;
>>>>     return (const void *)"\
>>>> \x7f\x45\x4c\x46\x02\x01\x01\0\0\0\0\0\0\0\0\0\x01\0\xf7\0\x01\0\0\0\0\0\0\0\0\
>>>> \0\0\0\0\0\0\0\0\0\0\0\xb0\x0d\0\0\0\0\0\0\0\0\0\0\x40\0\0\0\0\0\x40\0\x0c\0\
>>>> \x01\0\0\x2e\x73\x74\x72\x74\x61\x62\0\x2e\x73\x79\x6d\x74\x61\x62\0\x63\x67\
>>>> \x72\x6f\x75\x70\x5f\x73\x6b\x62\x2f\x65\x67\x72\x65\x73\x73\0\x63\x67\x72\x6f\
>>>> \x75\x70\x5f\x73\x6b\x62\x2f\x69\x6e\x67\x72\x65\x73\x73\0\x2e\x72\x6f\x64\x61\
>>>> \x74\x61\0\x6c\x69\x63\x65\x6e\x73\x65\0\x2e\x6d\x61\x70\x73\0\x72\x65\x73\x74\
>>>> \x72\x69\x63\x74\x2d\x69\x66\x61\x63\x65\x73\x2e\x62\x70\x66\x2e\x63\0\x4c\x42\
>>>> \x42\x30\x5f\x32\0\x4c\x42\x42\x30\x5f\x33\0\x4c\x42\x42\x30\x5f\x34\0\x4c\x42\
>>>> \x42\x31\x5f\x32\0\x4c\x42\x42\x31\x5f\x33\0\x4c\x42\x42\x31\x5f\x34\0\x5f\x6c\
>>>> \x69\x63\x65\x6e\x73\x65\0\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\
>>>> \x5f\x65\0\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\0\x69\x73\x5f\
>>>> \x61\x6c\x6c\x6f\x77\x5f\x6c\x69\x73\x74\0\x73\x64\x5f\x72\x65\x73\x74\x72\x69\
>>>> \x63\x74\x69\x66\x5f\x69\0\x2e\x72\x65\x6c\x63\x67\x72\x6f\x75\x70\x5f\x73\x6b\
>>>> \x62\x2f\x65\x67\x72\x65\x73\x73\0\x2e\x72\x65\x6c\x63\x67\x72\x6f\x75\x70\x5f\
>>>> \x73\x6b\x62\x2f\x69\x6e\x67\x72\x65\x73\x73\0\x2e\x42\x54\x46\0\x2e\x42\x54\
>>>> \x46\x2e\x65\x78\x74\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>>> \x4c\0\0\0\x04\0\xf1\xff\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x03\0\x03\0\0\
>>>> \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x62\0\0\0\0\0\x03\0\x70\0\0\0\0\0\0\0\0\0\0\0\0\
>>>> \0\0\0\x69\0\0\0\0\0\x03\0\x80\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x70\0\0\0\0\0\x03\
>>>> \0\x88\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x03\0\x04\0\0\0\0\0\0\0\0\0\0\0\0\
>>>> \0\0\0\0\0\x77\0\0\0\0\0\x04\0\x70\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x7e\0\0\0\0\0\
>>>> \x04\0\x80\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x85\0\0\0\0\0\x04\0\x88\0\0\0\0\0\0\0\
>>>> \0\0\0\0\0\0\0\0\x8c\0\0\0\x01\0\x06\0\0\0\0\0\0\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\
>>>> \0\x03\0\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x95\0\0\0\x12\0\x03\0\0\0\0\0\0\
>>>> \0\0\0\x98\0\0\0\0\0\0\0\xa5\0\0\0\x11\0\x07\0\0\0\0\0\0\0\0\0\x18\0\0\0\0\0\0\
>>>> \0\xb3\0\0\0\x11\0\x05\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\xc1\0\0\0\x12\0\x04\
>>>> \0\0\0\0\0\0\0\0\0\x98\0\0\0\0\0\0\0\x61\x11\x28\0\0\0\0\0\x63\x1a\xfc\xff\0\0\
>>>> \0\0\xbf\xa2\0\0\0\0\0\0\x07\x02\0\0\xfc\xff\xff\xff\x18\x01\0\0\0\0\0\0\0\0\0\
>>>> \0\0\0\0\0\x85\0\0\0\x01\0\0\0\x18\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x71\x11\0\0\
>>>> \0\0\0\0\x15\x01\x03\0\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x15\0\x03\0\0\0\0\0\x05\0\
>>>> \x03\0\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x15\0\x01\0\0\0\0\0\xb7\x01\0\0\0\0\0\0\
>>>> \xbf\x10\0\0\0\0\0\0\x95\0\0\0\0\0\0\0\x61\x11\x28\0\0\0\0\0\x63\x1a\xfc\xff\0\
>>>> \0\0\0\xbf\xa2\0\0\0\0\0\0\x07\x02\0\0\xfc\xff\xff\xff\x18\x01\0\0\0\0\0\0\0\0\
>>>> \0\0\0\0\0\0\x85\0\0\0\x01\0\0\0\x18\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x71\x11\0\
>>>> \0\0\0\0\0\x15\x01\x03\0\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x15\0\x03\0\0\0\0\0\x05\
>>>> \0\x03\0\0\0\0\0\xb7\x01\0\0\x01\0\0\0\x15\0\x01\0\0\0\0\0\xb7\x01\0\0\0\0\0\0\
>>>> \xbf\x10\0\0\0\0\0\0\x95\0\0\0\0\0\0\0\0\x4c\x47\x50\x4c\x2d\x32\x2e\x31\x2d\
>>>> \x6f\x72\x2d\x6c\x61\x74\x65\x72\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>>> \0\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\x01\0\0\0\x0d\0\0\0\x38\0\0\0\0\0\0\0\x01\0\0\
>>>> \0\x0e\0\0\0\x20\0\0\0\0\0\0\0\x01\0\0\0\x0d\0\0\0\x38\0\0\0\0\0\0\0\x01\0\0\0\
>>>> \x0e\0\0\0\x9f\xeb\x01\0\x18\0\0\0\0\0\0\0\x10\x04\0\0\x10\x04\0\0\x9c\x03\0\0\
>>>> \0\0\0\0\0\0\0\x02\x03\0\0\0\x01\0\0\0\0\0\0\x01\x04\0\0\0\x20\0\0\x01\0\0\0\0\
>>>> \0\0\0\x03\0\0\0\0\x02\0\0\0\x04\0\0\0\x01\0\0\0\x05\0\0\0\0\0\0\x01\x04\0\0\0\
>>>> \x20\0\0\0\0\0\0\0\0\0\0\x02\x06\0\0\0\x19\0\0\0\0\0\0\x08\x07\0\0\0\x1f\0\0\0\
>>>> \0\0\0\x01\x04\0\0\0\x20\0\0\0\0\0\0\0\0\0\0\x02\x09\0\0\0\x2c\0\0\0\0\0\0\x08\
>>>> \x0a\0\0\0\x31\0\0\0\0\0\0\x01\x01\0\0\0\x08\0\0\0\0\0\0\0\x03\0\0\x04\x18\0\0\
>>>> \0\x3f\0\0\0\x01\0\0\0\0\0\0\0\x44\0\0\0\x05\0\0\0\x40\0\0\0\x48\0\0\0\x08\0\0\
>>>> \0\x80\0\0\0\x4e\0\0\0\0\0\0\x0e\x0b\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\x02\x0e\0\0\
>>>> \0\0\0\0\0\0\0\0\x0a\x0f\0\0\0\x5c\0\0\0\x21\0\0\x04\xc0\0\0\0\x66\0\0\0\x06\0\
>>>> \0\0\0\0\0\0\x6a\0\0\0\x06\0\0\0\x20\0\0\0\x73\0\0\0\x06\0\0\0\x40\0\0\0\x78\0\
>>>> \0\0\x06\0\0\0\x60\0\0\0\x86\0\0\0\x06\0\0\0\x80\0\0\0\x8f\0\0\0\x06\0\0\0\xa0\
>>>> \0\0\0\x9c\0\0\0\x06\0\0\0\xc0\0\0\0\xa5\0\0\0\x06\0\0\0\xe0\0\0\0\xb0\0\0\0\
>>>> \x06\0\0\0\0\x01\0\0\xb9\0\0\0\x06\0\0\0\x20\x01\0\0\xc9\0\0\0\x06\0\0\0\x40\
>>>> \x01\0\0\xd1\0\0\0\x06\0\0\0\x60\x01\0\0\xda\0\0\0\x10\0\0\0\x80\x01\0\0\xdd\0\
>>>> \0\0\x06\0\0\0\x20\x02\0\0\xe2\0\0\0\x06\0\0\0\x40\x02\0\0\xed\0\0\0\x06\0\0\0\
>>>> \x60\x02\0\0\xf2\0\0\0\x06\0\0\0\x80\x02\0\0\xfb\0\0\0\x06\0\0\0\xa0\x02\0\0\
>>>> \x03\x01\0\0\x06\0\0\0\xc0\x02\0\0\x0a\x01\0\0\x06\0\0\0\xe0\x02\0\0\x15\x01\0\
>>>> \0\x06\0\0\0\0\x03\0\0\x1f\x01\0\0\x11\0\0\0\x20\x03\0\0\x2a\x01\0\0\x11\0\0\0\
>>>> \xa0\x03\0\0\x34\x01\0\0\x06\0\0\0\x20\x04\0\0\x40\x01\0\0\x06\0\0\0\x40\x04\0\
>>>> \0\x4b\x01\0\0\x06\0\0\0\x60\x04\0\0\0\0\0\0\x12\0\0\0\x80\x04\0\0\x55\x01\0\0\
>>>> \x14\0\0\0\xc0\x04\0\0\x5c\x01\0\0\x06\0\0\0\0\x05\0\0\x65\x01\0\0\x06\0\0\0\
>>>> \x20\x05\0\0\0\0\0\0\x16\0\0\0\x40\x05\0\0\x6e\x01\0\0\x06\0\0\0\x80\x05\0\0\
>>>> \x77\x01\0\0\x14\0\0\0\xc0\x05\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x06\0\0\0\x04\0\0\
>>>> \0\x05\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x06\0\0\0\x04\0\0\0\x04\0\0\0\0\0\0\0\
>>>> \x01\0\0\x05\x08\0\0\0\x80\x01\0\0\x13\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x02\x22\0\0\
>>>> \0\x8a\x01\0\0\0\0\0\x08\x15\0\0\0\x90\x01\0\0\0\0\0\x01\x08\0\0\0\x40\0\0\0\0\
>>>> \0\0\0\x01\0\0\x05\x08\0\0\0\xa3\x01\0\0\x17\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x02\
>>>> \x23\0\0\0\0\0\0\0\x01\0\0\x0d\x02\0\0\0\xa3\x01\0\0\x0d\0\0\0\xa6\x01\0\0\x01\
>>>> \0\0\x0c\x18\0\0\0\xb6\x01\0\0\x01\0\0\x0c\x18\0\0\0\0\0\0\0\0\0\0\x0a\x1c\0\0\
>>>> \0\0\0\0\0\0\0\0\x09\x09\0\0\0\xc6\x01\0\0\0\0\0\x0e\x1b\0\0\0\x01\0\0\0\0\0\0\
>>>> \0\0\0\0\x0a\x1f\0\0\0\xd4\x01\0\0\0\0\0\x01\x01\0\0\0\x08\0\0\x01\0\0\0\0\0\0\
>>>> \0\x03\0\0\0\0\x1e\0\0\0\x04\0\0\0\x12\0\0\0\xd9\x01\0\0\0\0\0\x0e\x20\0\0\0\0\
>>>> \0\0\0\xe2\x01\0\0\0\0\0\x07\0\0\0\0\xf0\x01\0\0\0\0\0\x07\0\0\0\0\x61\x03\0\0\
>>>> \x01\0\0\x0f\x01\0\0\0\x1d\0\0\0\0\0\0\0\x01\0\0\0\x69\x03\0\0\x01\0\0\x0f\x12\
>>>> \0\0\0\x21\0\0\0\0\0\0\0\x12\0\0\0\x71\x03\0\0\x01\0\0\x0f\x18\0\0\0\x0c\0\0\0\
>>>> \0\0\0\0\x18\0\0\0\0\x69\x6e\x74\0\x5f\x5f\x41\x52\x52\x41\x59\x5f\x53\x49\x5a\
>>>> \x45\x5f\x54\x59\x50\x45\x5f\x5f\0\x5f\x5f\x75\x33\x32\0\x75\x6e\x73\x69\x67\
>>>> \x6e\x65\x64\x20\x69\x6e\x74\0\x5f\x5f\x75\x38\0\x75\x6e\x73\x69\x67\x6e\x65\
>>>> \x64\x20\x63\x68\x61\x72\0\x74\x79\x70\x65\0\x6b\x65\x79\0\x76\x61\x6c\x75\x65\
>>>> \0\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\0\x5f\x5f\x73\x6b\x5f\
>>>> \x62\x75\x66\x66\0\x6c\x65\x6e\0\x70\x6b\x74\x5f\x74\x79\x70\x65\0\x6d\x61\x72\
>>>> \x6b\0\x71\x75\x65\x75\x65\x5f\x6d\x61\x70\x70\x69\x6e\x67\0\x70\x72\x6f\x74\
>>>> \x6f\x63\x6f\x6c\0\x76\x6c\x61\x6e\x5f\x70\x72\x65\x73\x65\x6e\x74\0\x76\x6c\
>>>> \x61\x6e\x5f\x74\x63\x69\0\x76\x6c\x61\x6e\x5f\x70\x72\x6f\x74\x6f\0\x70\x72\
>>>> \x69\x6f\x72\x69\x74\x79\0\x69\x6e\x67\x72\x65\x73\x73\x5f\x69\x66\x69\x6e\x64\
>>>> \x65\x78\0\x69\x66\x69\x6e\x64\x65\x78\0\x74\x63\x5f\x69\x6e\x64\x65\x78\0\x63\
>>>> \x62\0\x68\x61\x73\x68\0\x74\x63\x5f\x63\x6c\x61\x73\x73\x69\x64\0\x64\x61\x74\
>>>> \x61\0\x64\x61\x74\x61\x5f\x65\x6e\x64\0\x6e\x61\x70\x69\x5f\x69\x64\0\x66\x61\
>>>> \x6d\x69\x6c\x79\0\x72\x65\x6d\x6f\x74\x65\x5f\x69\x70\x34\0\x6c\x6f\x63\x61\
>>>> \x6c\x5f\x69\x70\x34\0\x72\x65\x6d\x6f\x74\x65\x5f\x69\x70\x36\0\x6c\x6f\x63\
>>>> \x61\x6c\x5f\x69\x70\x36\0\x72\x65\x6d\x6f\x74\x65\x5f\x70\x6f\x72\x74\0\x6c\
>>>> \x6f\x63\x61\x6c\x5f\x70\x6f\x72\x74\0\x64\x61\x74\x61\x5f\x6d\x65\x74\x61\0\
>>>> \x74\x73\x74\x61\x6d\x70\0\x77\x69\x72\x65\x5f\x6c\x65\x6e\0\x67\x73\x6f\x5f\
>>>> \x73\x65\x67\x73\0\x67\x73\x6f\x5f\x73\x69\x7a\x65\0\x68\x77\x74\x73\x74\x61\
>>>> \x6d\x70\0\x66\x6c\x6f\x77\x5f\x6b\x65\x79\x73\0\x5f\x5f\x75\x36\x34\0\x75\x6e\
>>>> \x73\x69\x67\x6e\x65\x64\x20\x6c\x6f\x6e\x67\x20\x6c\x6f\x6e\x67\0\x73\x6b\0\
>>>> \x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\x74\x69\x66\x5f\x65\0\x73\x64\x5f\x72\
>>>> \x65\x73\x74\x72\x69\x63\x74\x69\x66\x5f\x69\0\x69\x73\x5f\x61\x6c\x6c\x6f\x77\
>>>> \x5f\x6c\x69\x73\x74\0\x63\x68\x61\x72\0\x5f\x6c\x69\x63\x65\x6e\x73\x65\0\x62\
>>>> \x70\x66\x5f\x66\x6c\x6f\x77\x5f\x6b\x65\x79\x73\0\x62\x70\x66\x5f\x73\x6f\x63\
>>>> \x6b\0\x2f\x68\x6f\x6d\x65\x2f\x62\x75\x69\x6c\x64\x72\x6f\x6f\x74\x2f\x62\x75\
>>>> \x69\x6c\x64\x72\x6f\x6f\x74\x2f\x6f\x75\x74\x70\x75\x74\x2f\x62\x75\x69\x6c\
>>>> \x64\x2f\x73\x79\x73\x74\x65\x6d\x64\x2d\x63\x75\x73\x74\x6f\x6d\x2f\x73\x72\
>>>> \x63\x2f\x63\x6f\x72\x65\x2f\x62\x70\x66\x2f\x72\x65\x73\x74\x72\x69\x63\x74\
>>>> \x5f\x69\x66\x61\x63\x65\x73\x2f\x72\x65\x73\x74\x72\x69\x63\x74\x2d\x69\x66\
>>>> \x61\x63\x65\x73\x2e\x62\x70\x66\x2e\x63\0\x20\x20\x20\x20\x20\x20\x20\x20\x69\
>>>> \x66\x69\x6e\x64\x65\x78\x20\x3d\x20\x73\x6b\x2d\x3e\x69\x66\x69\x6e\x64\x65\
>>>> \x78\x3b\0\x20\x20\x20\x20\x20\x20\x20\x20\x6c\x6f\x6f\x6b\x75\x70\x5f\x72\x65\
>>>> \x73\x75\x6c\x74\x20\x3d\x20\x62\x70\x66\x5f\x6d\x61\x70\x5f\x6c\x6f\x6f\x6b\
>>>> \x75\x70\x5f\x65\x6c\x65\x6d\x28\x26\x73\x64\x5f\x72\x65\x73\x74\x72\x69\x63\
>>>> \x74\x69\x66\x2c\x20\x26\x69\x66\x69\x6e\x64\x65\x78\x29\x3b\0\x20\x20\x20\x20\
>>>> \x20\x20\x20\x20\x69\x66\x20\x28\x69\x73\x5f\x61\x6c\x6c\x6f\x77\x5f\x6c\x69\
>>>> \x73\x74\x29\x20\x7b\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
>>>> \x20\x20\x69\x66\x20\x28\x6c\x6f\x6f\x6b\x75\x70\x5f\x72\x65\x73\x75\x6c\x74\
>>>> \x29\0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\
>>>> \x20\x28\x21\x6c\x6f\x6f\x6b\x75\x70\x5f\x72\x65\x73\x75\x6c\x74\x29\0\x20\x20\
>>>> \x20\x20\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x72\x65\x73\x74\x72\x69\
>>>> \x63\x74\x5f\x6e\x65\x74\x77\x6f\x72\x6b\x5f\x69\x6e\x74\x65\x72\x66\x61\x63\
>>>> \x65\x73\x5f\x69\x6d\x70\x6c\x28\x73\x6b\x29\x3b\0\x2e\x72\x6f\x64\x61\x74\x61\
>>>> \0\x6c\x69\x63\x65\x6e\x73\x65\0\x2e\x6d\x61\x70\x73\0\x63\x67\x72\x6f\x75\x70\
>>>> \x5f\x73\x6b\x62\x2f\x65\x67\x72\x65\x73\x73\0\x63\x67\x72\x6f\x75\x70\x5f\x73\
>>>> \x6b\x62\x2f\x69\x6e\x67\x72\x65\x73\x73\0\0\0\0\0\x9f\xeb\x01\0\x20\0\0\0\0\0\
>>>> \0\0\x24\0\0\0\x24\0\0\0\x34\x01\0\0\x58\x01\0\0\0\0\0\0\x08\0\0\0\x77\x03\0\0\
>>>> \x01\0\0\0\0\0\0\0\x19\0\0\0\x89\x03\0\0\x01\0\0\0\0\0\0\0\x1a\0\0\0\x10\0\0\0\
>>>> \x77\x03\0\0\x09\0\0\0\0\0\0\0\xf9\x01\0\0\x62\x02\0\0\x17\x6c\0\0\x08\0\0\0\
>>>> \xf9\x01\0\0\x62\x02\0\0\x11\x6c\0\0\x18\0\0\0\xf9\x01\0\0\0\0\0\0\0\0\0\0\x20\
>>>> \0\0\0\xf9\x01\0\0\x81\x02\0\0\x19\x70\0\0\x38\0\0\0\xf9\x01\0\0\xc8\x02\0\0\
>>>> \x0d\x74\0\0\x50\0\0\0\xf9\x01\0\0\xc8\x02\0\0\x0d\x74\0\0\x60\0\0\0\xf9\x01\0\
>>>> \0\xe5\x02\0\0\x15\x7c\0\0\x78\0\0\0\xf9\x01\0\0\x08\x03\0\0\x15\x8c\0\0\x88\0\
>>>> \0\0\xf9\x01\0\0\x2c\x03\0\0\x09\xb0\0\0\x89\x03\0\0\x09\0\0\0\0\0\0\0\xf9\x01\
>>>> \0\0\x62\x02\0\0\x17\x6c\0\0\x08\0\0\0\xf9\x01\0\0\x62\x02\0\0\x11\x6c\0\0\x18\
>>>> \0\0\0\xf9\x01\0\0\0\0\0\0\0\0\0\0\x20\0\0\0\xf9\x01\0\0\x81\x02\0\0\x19\x70\0\
>>>> \0\x38\0\0\0\xf9\x01\0\0\xc8\x02\0\0\x0d\x74\0\0\x50\0\0\0\xf9\x01\0\0\xc8\x02\
>>>> \0\0\x0d\x74\0\0\x60\0\0\0\xf9\x01\0\0\xe5\x02\0\0\x15\x7c\0\0\x78\0\0\0\xf9\
>>>> \x01\0\0\x08\x03\0\0\x15\x8c\0\0\x88\0\0\0\xf9\x01\0\0\x2c\x03\0\0\x09\xc4\0\0\
>>>> \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>>> \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\x03\0\0\0\x20\0\0\
>>>> \0\0\0\0\0\0\0\0\0\0\0\0\0\x40\0\0\0\0\0\0\0\x0c\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>>> \0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x09\0\0\0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>>> \0\0\0\0\0\x50\x01\0\0\0\0\0\0\x80\x01\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\x08\0\0\0\
>>>> \0\0\0\0\x18\0\0\0\0\0\0\0\x11\0\0\0\x01\0\0\0\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>>> \0\xd0\x02\0\0\0\0\0\0\x98\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0\0\
>>>> \0\0\0\0\0\0\x23\0\0\0\x01\0\0\0\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x68\x03\0\0\
>>>> \0\0\0\0\x98\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>>> \x36\0\0\0\x01\0\0\0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\x01\0\
>>>> \0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x3e\0\0\0\x01\0\
>>>> \0\0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x04\0\0\0\0\0\0\x12\0\0\0\0\0\0\0\0\
>>>> \0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x46\0\0\0\x01\0\0\0\x03\0\0\0\
>>>> \0\0\0\0\0\0\0\0\0\0\0\0\x18\x04\0\0\0\0\0\0\x18\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>>> \x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xd1\0\0\0\x09\0\0\0\x40\0\0\0\0\0\0\0\0\0\0\
>>>> \0\0\0\0\0\x30\x04\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\x02\0\0\0\x03\0\0\0\x08\0\0\0\
>>>> \0\0\0\0\x10\0\0\0\0\0\0\0\xe7\0\0\0\x09\0\0\0\x40\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>>> \0\x50\x04\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\x02\0\0\0\x04\0\0\0\x08\0\0\0\0\0\0\0\
>>>> \x10\0\0\0\0\0\0\0\xfe\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x70\x04\
>>>> \0\0\0\0\0\0\xc4\x07\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\
>>>> \0\0\x03\x01\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x38\x0c\0\0\0\0\0\0\
>>>> \x78\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
>>>> }
>>>>
>>>> #ifdef __cplusplus
>>>> struct restrict_ifaces_bpf *restrict_ifaces_bpf::open(const struct
>>>> bpf_object_open_opts *opts) { return
>>>> restrict_ifaces_bpf__open_opts(opts); }
>>>> struct restrict_ifaces_bpf *restrict_ifaces_bpf::open_and_load() {
>>>> return restrict_ifaces_bpf__open_and_load(); }
>>>> int restrict_ifaces_bpf::load(struct restrict_ifaces_bpf *skel) {
>>>> return restrict_ifaces_bpf__load(skel); }
>>>> int restrict_ifaces_bpf::attach(struct restrict_ifaces_bpf *skel) {
>>>> return restrict_ifaces_bpf__attach(skel); }
>>>> void restrict_ifaces_bpf::detach(struct restrict_ifaces_bpf *skel) {
>>>> restrict_ifaces_bpf__detach(skel); }
>>>> void restrict_ifaces_bpf::destroy(struct restrict_ifaces_bpf *skel) {
>>>> restrict_ifaces_bpf__destroy(skel); }
>>>> const void *restrict_ifaces_bpf::elf_bytes(size_t *sz) { return
>>>> restrict_ifaces_bpf__elf_bytes(sz); }
>>>> #endif /* __cplusplus */
>>>>
>>>> __attribute__((unused)) static void
>>>> restrict_ifaces_bpf__assert(struct restrict_ifaces_bpf *s
>>>> __attribute__((unused)))
>>>> {
>>>> #ifdef __cplusplus
>>>> #define _Static_assert static_assert
>>>> #endif
>>>>     _Static_assert(sizeof(s->rodata->is_allow_list) == 1, "unexpected
>>>> size of 'is_allow_list'");
>>>> #ifdef __cplusplus
>>>> #undef _Static_assert
>>>> #endif
>>>> }
>>>>
>>>> #endif /* __RESTRICT_IFACES_BPF_SKEL_H__ */
>>>>
>>>>>
>>>>>
>>>>> > Starting program:
>>>>> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>>>>> > --debug gen skeleton
>>>>> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>>>>> > [Thread debugging using libthread_db enabled]
>>>>> > Using host libthread_db library "/usr/lib/libthread_db.so.1".
>>>>> > libbpf: loading object 'restrict_ifaces_bpf' from buffer
>>>>> > libbpf: elf: section(2) .symtab, size 336, link 1, flags 0, type=2
>>>>> > libbpf: elf: section(3) .data, size 1, link 0, flags 3, type=1
>>>>> > libbpf: elf: section(4) .bss, size 0, link 0, flags 3, type=8
>>>>> > libbpf: elf: section(5) cgroup_skb/egress, size 184, link 0, flags 6, type=1
>>>>> > libbpf: sec 'cgroup_skb/egress': found program 'sd_restrictif_e' at
>>>>> > insn offset 0 (0 bytes), code size 23 insns (184 bytes)
>>>>> > libbpf: elf: section(6) cgroup_skb/ingress, size 184, link 0, flags 6, type=1
>>>>> > libbpf: sec 'cgroup_skb/ingress': found program 'sd_restrictif_i' at
>>>>> > insn offset 0 (0 bytes), code size 23 insns (184 bytes)
>>>>> > libbpf: elf: section(7) license, size 18, link 0, flags 2, type=1
>>>>> > libbpf: license of restrict_ifaces_bpf is LGPL-2.1-or-later
>>>>> > libbpf: elf: section(8) .maps, size 24, link 0, flags 3, type=1
>>>>> > libbpf: elf: section(9) .comment, size 49, link 0, flags 30, type=1
>>>>> > libbpf: elf: skipping unrecognized data section(9) .comment
>>>>> > libbpf: elf: section(10) .relcgroup_skb/egress, size 32, link 2, flags
>>>>> > 40, type=9
>>>>> > libbpf: elf: section(11) .relcgroup_skb/ingress, size 32, link 2,
>>>>> > flags 40, type=9
>>>>> > libbpf: elf: section(12) .BTF, size 3606, link 0, flags 0, type=1
>>>>> > libbpf: looking for externs among 14 symbols...
>>>>> > libbpf: collected 0 externs total
>>>>> > libbpf: map 'sd_restrictif': at sec_idx 8, offset 0.
>>>>> > libbpf: map 'sd_restrictif': found type = 1.
>>>>> > libbpf: map 'sd_restrictif': found key [12], sz = 4.
>>>>> > libbpf: map 'sd_restrictif': found value [3], sz = 1.
>>>>> >
>>>>> > Program received signal SIGSEGV, Segmentation fault.
>>>>> > 0x0000aaaaaab4fd2c in bpf_object.init_maps ()
>>>>> > (gdb) bt
>>>>> > #0  0x0000aaaaaab4fd2c in bpf_object.init_maps ()
>>>>> > #1  0x0000aaaaaab52178 in bpf_object_open.part ()
>>>>> > #2  0x0000aaaaaab544e8 in bpf_object.open_mem ()
>>>>> > #3  0x0000aaaaaab2a58c in do_skeleton ()
>>>>> > #4  0x0000aaaaaab1e204 in main ()
>>>>> >
>>>>> >>
>>>>> >> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
>>>>> >> index e89cc9c885b3..e3a6808f0bb6 100644
>>>>> >> --- a/tools/lib/bpf/libbpf.c
>>>>> >> +++ b/tools/lib/bpf/libbpf.c
>>>>> >> @@ -1591,6 +1591,10 @@ static int
>>> bpf_object__init_global_data_maps(struct bpf_object *obj)
>>>>> >>         for (sec_idx = 1; sec_idx < obj->efile.sec_cnt; sec_idx++) {
>>>>> >>                 sec_desc = &obj->efile.secs[sec_idx];
>>>>> >>
>>>>> >> +                /* Skip empty sections.  */
>>>>> >> +                if (sec_desc->data->d_size == 0)
>>>>> >> +                  continue;
>>>>> >> +
>>>>> >>                 switch (sec_desc->sec_type) {
>>>>> >>                 case SEC_DATA:
>>>>> >>                         sec_name = elf_sec_name(obj, elf_sec_by_idx(obj, sec_idx));
>>>>> >>
>>>>> >> > GCC:
>>>>> >> > $ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>>>>> >> > --debug gen skeleton
>>>>> >> > output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>>>>> >> > libbpf: loading object 'restrict_ifaces_bpf' from buffer
>>>>> >> > libbpf: elf: section(2) .symtab, size 336, link 1, flags 0, type=2
>>>>> >> > libbpf: elf: section(3) .data, size 1, link 0, flags 3, type=1
>>>>> >> > libbpf: elf: section(4) .bss, size 0, link 0, flags 3, type=8
>>>>> >> > libbpf: elf: section(5) cgroup_skb/egress, size 184, link 0, flags 6, type=1
>>>>> >> > libbpf: sec 'cgroup_skb/egress': found program 'sd_restrictif_e' at
>>>>> >> > insn offset 0 (0 bytes), code size 23 insns (184 bytes)
>>>>> >> > libbpf: elf: section(6) cgroup_skb/ingress, size 184, link 0, flags 6, type=1
>>>>> >> > libbpf: sec 'cgroup_skb/ingress': found program 'sd_restrictif_i' at
>>>>> >> > insn offset 0 (0 bytes), code size 23 insns (184 bytes)
>>>>> >> > libbpf: elf: section(7) license, size 18, link 0, flags 2, type=1
>>>>> >> > libbpf: license of restrict_ifaces_bpf is LGPL-2.1-or-later
>>>>> >> > libbpf: elf: section(8) .maps, size 24, link 0, flags 3, type=1
>>>>> >> > libbpf: elf: section(9) .comment, size 49, link 0, flags 30, type=1
>>>>> >> > libbpf: elf: skipping unrecognized data section(9) .comment
>>>>> >> > libbpf: elf: section(10) .relcgroup_skb/egress, size 32, link 2, flags
>>>>> >> > 40, type=9
>>>>> >> > libbpf: elf: section(11) .relcgroup_skb/ingress, size 32, link 2,
>>>>> >> > flags 40, type=9
>>>>> >> > libbpf: elf: section(12) .BTF, size 3606, link 0, flags 0, type=1
>>>>> >> > libbpf: looking for externs among 14 symbols...
>>>>> >> > libbpf: collected 0 externs total
>>>>> >> > libbpf: map 'sd_restrictif': at sec_idx 8, offset 0.
>>>>> >> > libbpf: map 'sd_restrictif': found type = 1.
>>>>> >> > libbpf: map 'sd_restrictif': found key [12], sz = 4.
>>>>> >> > libbpf: map 'sd_restrictif': found value [3], sz = 1.
>>>>> >> > libbpf: map 'restrict.data' (global data): at sec_idx 3, offset 0, flags 400.
>>>>> >> > libbpf: map 1 is "restrict.data"
>>>>> >> > libbpf: map 'restrict.bss' (global data): at sec_idx 4, offset 0, flags 400.
>>>>> >> > libbpf: failed to alloc map 'restrict.bss' content buffer: -22
>>>>> >> > Error: failed to open BPF object file: Invalid argument
>>>>> >> >
>>>>> >> > LLVM:
>>>>> >> > $ /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>>>>> >> > --debug gen skeleton restrict-ifaces.bpf.o
>>>>> >> > libbpf: loading object 'restrict_ifaces_bpf' from buffer
>>>>> >> > libbpf: elf: section(2) .symtab, size 384, link 1, flags 0, type=2
>>>>> >> > libbpf: elf: section(3) cgroup_skb/egress, size 152, link 0, flags 6, type=1
>>>>> >> > libbpf: sec 'cgroup_skb/egress': found program 'sd_restrictif_e' at
>>>>> >> > insn offset 0 (0 bytes), code size 19 insns (152 bytes)
>>>>> >> > libbpf: elf: section(4) cgroup_skb/ingress, size 152, link 0, flags 6, type=1
>>>>> >> > libbpf: sec 'cgroup_skb/ingress': found program 'sd_restrictif_i' at
>>>>> >> > insn offset 0 (0 bytes), code size 19 insns (152 bytes)
>>>>> >> > libbpf: elf: section(5) .rodata, size 1, link 0, flags 2, type=1
>>>>> >> > libbpf: elf: section(6) license, size 18, link 0, flags 2, type=1
>>>>> >> > libbpf: license of restrict_ifaces_bpf is LGPL-2.1-or-later
>>>>> >> > libbpf: elf: section(7) .maps, size 24, link 0, flags 3, type=1
>>>>> >> > libbpf: elf: section(8) .relcgroup_skb/egress, size 32, link 2, flags 40, type=9
>>>>> >> > libbpf: elf: section(9) .relcgroup_skb/ingress, size 32, link 2, flags
>>>>> >> > 40, type=9
>>>>> >> > libbpf: elf: section(10) .BTF, size 1988, link 0, flags 0, type=1
>>>>> >> > libbpf: elf: section(11) .BTF.ext, size 376, link 0, flags 0, type=1
>>>>> >> > libbpf: looking for externs among 16 symbols...
>>>>> >> > libbpf: collected 0 externs total
>>>>> >> > libbpf: map 'sd_restrictif': at sec_idx 7, offset 0.
>>>>> >> > libbpf: map 'sd_restrictif': found type = 1.
>>>>> >> > libbpf: map 'sd_restrictif': found key [6], sz = 4.
>>>>> >> > libbpf: map 'sd_restrictif': found value [9], sz = 1.
>>>>> >> > libbpf: map 'restrict.rodata' (global data): at sec_idx 5, offset 0, flags 480.
>>>>> >> > libbpf: map 1 is "restrict.rodata"
>>>>> >> > libbpf: sec '.relcgroup_skb/egress': collecting relocation for
>>>>> >> > section(3) 'cgroup_skb/egress'
>>>>> >> > libbpf: sec '.relcgroup_skb/egress': relo #0: insn #4 against 'sd_restrictif'
>>>>> >> > libbpf: prog 'sd_restrictif_e': found map 0 (sd_restrictif, sec 7, off
>>>>> >> > 0) for insn #4
>>>>> >> > libbpf: sec '.relcgroup_skb/egress': relo #1: insn #7 against 'is_allow_list'
>>>>> >> > libbpf: prog 'sd_restrictif_e': found data map 1 (restrict.rodata, sec
>>>>> >> > 5, off 0) for insn 7
>>>>> >> > libbpf: sec '.relcgroup_skb/ingress': collecting relocation for
>>>>> >> > section(4) 'cgroup_skb/ingress'
>>>>> >> > libbpf: sec '.relcgroup_skb/ingress': relo #0: insn #4 against 'sd_restrictif'
>>>>> >> > libbpf: prog 'sd_restrictif_i': found map 0 (sd_restrictif, sec 7, off
>>>>> >> > 0) for insn #4
>>>>> >> > libbpf: sec '.relcgroup_skb/ingress': relo #1: insn #7 against 'is_allow_list'
>>>>> >> > libbpf: prog 'sd_restrictif_i': found data map 1 (restrict.rodata, sec
>>>>> >> > 5, off 0) for insn 7
>>>>> >> >
>>>>> >> >> >
>>>>> >> >> > >>
>>>>> >> >> > >> Looking at libbpf.c, it seems to me that this may be due of trying to
>>>>> >> >> > >> mmap 0 bytes in `bpf_object__init_internal_map':
>>>>> >> >> > >>
>>>>> >> >> > >>         map->mmaped = mmap(NULL, bpf_map_mmap_sz(map), PROT_READ | PROT_WRITE,
>>>>> >> >> > >>                            MAP_SHARED | MAP_ANONYMOUS, -1, 0);
>>>>> >> >> > >>         if (map->mmaped == MAP_FAILED) {
>>>>> >> >> > >>                 err = -errno;
>>>>> >> >> > >>                 map->mmaped = NULL;
>>>>> >> >> > >>                 pr_warn("failed to alloc map '%s' content buffer: %d\n",
>>>>> >> >> > >>                         map->name, err);
>>>>> >> >> > >>                 zfree(&map->real_name);
>>>>> >> >> > >>                 zfree(&map->name);
>>>>> >> >> > >>                 return err;
>>>>> >> >> > >>         }
>>>>> >> >> > >>
>>>>> >> >> > >> I see no check for zero sized sections in
>>>>> >> >> > >> bpf_object__init_global_data_maps.
>>>>> >> >> > >>
>>>>> >> >> > >> Is maybe GCC failing to allocate stuff in BSS that is supposed to be
>>>>> >> >> > >> there?
>>>>> >> >> > >>
>>>>> >> >> > >> > Stripped file passed to gen skeleton:
>>>>> >> >> > >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>>>>> >> >> > >> > btf dump file
>>>>> >> >> > >> >
>>> output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>>>>> >> >> > >> > format raw
>>>>> >> >> > >> > [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>>>>> >> >> > >> > [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
>>>>> >> >> > >> > [3] TYPEDEF '__u8' type_id=2
>>>>> >> >> > >> > [4] CONST '(anon)' type_id=3
>>>>> >> >> > >> > [5] VOLATILE '(anon)' type_id=4
>>>>> >> >> > >> > [6] INT 'short int' size=2 bits_offset=0 nr_bits=16 encoding=SIGNED
>>>>> >> >> > >> > [7] INT 'short unsigned int' size=2 bits_offset=0 nr_bits=16 encoding=(none)
>>>>> >> >> > >> > [8] TYPEDEF '__u16' type_id=7
>>>>> >> >> > >> > [9] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
>>>>> >> >> > >> > [10] TYPEDEF '__s32' type_id=9
>>>>> >> >> > >> > [11] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
>>>>> >> >> > >> > [12] TYPEDEF '__u32' type_id=11
>>>>> >> >> > >> > [13] INT 'long long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
>>>>> >> >> > >> > [14] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64
>>>>> >> >> > >> > encoding=(none)
>>>>> >> >> > >> > [15] TYPEDEF '__u64' type_id=14
>>>>> >> >> > >> > [16] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
>>>>> >> >> > >> > [17] INT 'long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
>>>>> >> >> > >> > [18] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>>>>> >> >> > >> > [19] CONST '(anon)' type_id=18
>>>>> >> >> > >> > [20] TYPEDEF '__be16' type_id=8
>>>>> >> >> > >> > [21] TYPEDEF '__be32' type_id=12
>>>>> >> >> > >> > [22] ENUM 'bpf_map_type' encoding=UNSIGNED size=4 vlen=31
>>>>> >> >> > >> >     'BPF_MAP_TYPE_UNSPEC' val=0
>>>>> >> >> > >> >     'BPF_MAP_TYPE_HASH' val=1
>>>>> >> >> > >> >     'BPF_MAP_TYPE_ARRAY' val=2
>>>>> >> >> > >> >     'BPF_MAP_TYPE_PROG_ARRAY' val=3
>>>>> >> >> > >> >     'BPF_MAP_TYPE_PERF_EVENT_ARRAY' val=4
>>>>> >> >> > >> >     'BPF_MAP_TYPE_PERCPU_HASH' val=5
>>>>> >> >> > >> >     'BPF_MAP_TYPE_PERCPU_ARRAY' val=6
>>>>> >> >> > >> >     'BPF_MAP_TYPE_STACK_TRACE' val=7
>>>>> >> >> > >> >     'BPF_MAP_TYPE_CGROUP_ARRAY' val=8
>>>>> >> >> > >> >     'BPF_MAP_TYPE_LRU_HASH' val=9
>>>>> >> >> > >> >     'BPF_MAP_TYPE_LRU_PERCPU_HASH' val=10
>>>>> >> >> > >> >     'BPF_MAP_TYPE_LPM_TRIE' val=11
>>>>> >> >> > >> >     'BPF_MAP_TYPE_ARRAY_OF_MAPS' val=12
>>>>> >> >> > >> >     'BPF_MAP_TYPE_HASH_OF_MAPS' val=13
>>>>> >> >> > >> >     'BPF_MAP_TYPE_DEVMAP' val=14
>>>>> >> >> > >> >     'BPF_MAP_TYPE_SOCKMAP' val=15
>>>>> >> >> > >> >     'BPF_MAP_TYPE_CPUMAP' val=16
>>>>> >> >> > >> >     'BPF_MAP_TYPE_XSKMAP' val=17
>>>>> >> >> > >> >     'BPF_MAP_TYPE_SOCKHASH' val=18
>>>>> >> >> > >> >     'BPF_MAP_TYPE_CGROUP_STORAGE' val=19
>>>>> >> >> > >> >     'BPF_MAP_TYPE_REUSEPORT_SOCKARRAY' val=20
>>>>> >> >> > >> >     'BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE' val=21
>>>>> >> >> > >> >     'BPF_MAP_TYPE_QUEUE' val=22
>>>>> >> >> > >> >     'BPF_MAP_TYPE_STACK' val=23
>>>>> >> >> > >> >     'BPF_MAP_TYPE_SK_STORAGE' val=24
>>>>> >> >> > >> >     'BPF_MAP_TYPE_DEVMAP_HASH' val=25
>>>>> >> >> > >> >     'BPF_MAP_TYPE_STRUCT_OPS' val=26
>>>>> >> >> > >> >     'BPF_MAP_TYPE_RINGBUF' val=27
>>>>> >> >> > >> >     'BPF_MAP_TYPE_INODE_STORAGE' val=28
>>>>> >> >> > >> >     'BPF_MAP_TYPE_TASK_STORAGE' val=29
>>>>> >> >> > >> >     'BPF_MAP_TYPE_BLOOM_FILTER' val=30
>>>>> >> >> > >> > [23] UNION '(anon)' size=8 vlen=1
>>>>> >> >> > >> >     'flow_keys' type_id=29 bits_offset=0
>>>>> >> >> > >> > [24] STRUCT 'bpf_flow_keys' size=56 vlen=13
>>>>> >> >> > >> >     'nhoff' type_id=8 bits_offset=0
>>>>> >> >> > >> >     'thoff' type_id=8 bits_offset=16
>>>>> >> >> > >> >     'addr_proto' type_id=8 bits_offset=32
>>>>> >> >> > >> >     'is_frag' type_id=3 bits_offset=48
>>>>> >> >> > >> >     'is_first_frag' type_id=3 bits_offset=56
>>>>> >> >> > >> >     'is_encap' type_id=3 bits_offset=64
>>>>> >> >> > >> >     'ip_proto' type_id=3 bits_offset=72
>>>>> >> >> > >> >     'n_proto' type_id=20 bits_offset=80
>>>>> >> >> > >> >     'sport' type_id=20 bits_offset=96
>>>>> >> >> > >> >     'dport' type_id=20 bits_offset=112
>>>>> >> >> > >> >     '(anon)' type_id=25 bits_offset=128
>>>>> >> >> > >> >     'flags' type_id=12 bits_offset=384
>>>>> >> >> > >> >     'flow_label' type_id=21 bits_offset=416
>>>>> >> >> > >> > [25] UNION '(anon)' size=32 vlen=2
>>>>> >> >> > >> >     '(anon)' type_id=26 bits_offset=0
>>>>> >> >> > >> >     '(anon)' type_id=27 bits_offset=0
>>>>> >> >> > >> > [26] STRUCT '(anon)' size=8 vlen=2
>>>>> >> >> > >> >     'ipv4_src' type_id=21 bits_offset=0
>>>>> >> >> > >> >     'ipv4_dst' type_id=21 bits_offset=32
>>>>> >> >> > >> > [27] STRUCT '(anon)' size=32 vlen=2
>>>>> >> >> > >> >     'ipv6_src' type_id=28 bits_offset=0
>>>>> >> >> > >> >     'ipv6_dst' type_id=28 bits_offset=128
>>>>> >> >> > >> > [28] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=4
>>>>> >> >> > >> > [29] PTR '(anon)' type_id=24
>>>>> >> >> > >> > [30] UNION '(anon)' size=8 vlen=1
>>>>> >> >> > >> >     'sk' type_id=32 bits_offset=0
>>>>> >> >> > >> > [31] STRUCT 'bpf_sock' size=80 vlen=14
>>>>> >> >> > >> >     'bound_dev_if' type_id=12 bits_offset=0
>>>>> >> >> > >> >     'family' type_id=12 bits_offset=32
>>>>> >> >> > >> >     'type' type_id=12 bits_offset=64
>>>>> >> >> > >> >     'protocol' type_id=12 bits_offset=96
>>>>> >> >> > >> >     'mark' type_id=12 bits_offset=128
>>>>> >> >> > >> >     'priority' type_id=12 bits_offset=160
>>>>> >> >> > >> >     'src_ip4' type_id=12 bits_offset=192
>>>>> >> >> > >> >     'src_ip6' type_id=28 bits_offset=224
>>>>> >> >> > >> >     'src_port' type_id=12 bits_offset=352
>>>>> >> >> > >> >     'dst_port' type_id=20 bits_offset=384
>>>>> >> >> > >> >     'dst_ip4' type_id=12 bits_offset=416
>>>>> >> >> > >> >     'dst_ip6' type_id=28 bits_offset=448
>>>>> >> >> > >> >     'state' type_id=12 bits_offset=576
>>>>> >> >> > >> >     'rx_queue_mapping' type_id=10 bits_offset=608
>>>>> >> >> > >> > [32] PTR '(anon)' type_id=31
>>>>> >> >> > >> > [33] STRUCT '__sk_buff' size=192 vlen=33
>>>>> >> >> > >> >     'len' type_id=12 bits_offset=0
>>>>> >> >> > >> >     'pkt_type' type_id=12 bits_offset=32
>>>>> >> >> > >> >     'mark' type_id=12 bits_offset=64
>>>>> >> >> > >> >     'queue_mapping' type_id=12 bits_offset=96
>>>>> >> >> > >> >     'protocol' type_id=12 bits_offset=128
>>>>> >> >> > >> >     'vlan_present' type_id=12 bits_offset=160
>>>>> >> >> > >> >     'vlan_tci' type_id=12 bits_offset=192
>>>>> >> >> > >> >     'vlan_proto' type_id=12 bits_offset=224
>>>>> >> >> > >> >     'priority' type_id=12 bits_offset=256
>>>>> >> >> > >> >     'ingress_ifindex' type_id=12 bits_offset=288
>>>>> >> >> > >> >     'ifindex' type_id=12 bits_offset=320
>>>>> >> >> > >> >     'tc_index' type_id=12 bits_offset=352
>>>>> >> >> > >> >     'cb' type_id=34 bits_offset=384
>>>>> >> >> > >> >     'hash' type_id=12 bits_offset=544
>>>>> >> >> > >> >     'tc_classid' type_id=12 bits_offset=576
>>>>> >> >> > >> >     'data' type_id=12 bits_offset=608
>>>>> >> >> > >> >     'data_end' type_id=12 bits_offset=640
>>>>> >> >> > >> >     'napi_id' type_id=12 bits_offset=672
>>>>> >> >> > >> >     'family' type_id=12 bits_offset=704
>>>>> >> >> > >> >     'remote_ip4' type_id=12 bits_offset=736
>>>>> >> >> > >> >     'local_ip4' type_id=12 bits_offset=768
>>>>> >> >> > >> >     'remote_ip6' type_id=28 bits_offset=800
>>>>> >> >> > >> >     'local_ip6' type_id=28 bits_offset=928
>>>>> >> >> > >> >     'remote_port' type_id=12 bits_offset=1056
>>>>> >> >> > >> >     'local_port' type_id=12 bits_offset=1088
>>>>> >> >> > >> >     'data_meta' type_id=12 bits_offset=1120
>>>>> >> >> > >> >     '(anon)' type_id=23 bits_offset=1152
>>>>> >> >> > >> >     'tstamp' type_id=15 bits_offset=1216
>>>>> >> >> > >> >     'wire_len' type_id=12 bits_offset=1280
>>>>> >> >> > >> >     'gso_segs' type_id=12 bits_offset=1312
>>>>> >> >> > >> >     '(anon)' type_id=30 bits_offset=1344
>>>>> >> >> > >> >     'gso_size' type_id=12 bits_offset=1408
>>>>> >> >> > >> >     'hwtstamp' type_id=15 bits_offset=1472
>>>>> >> >> > >> > [34] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=5
>>>>> >> >> > >> > [35] CONST '(anon)' type_id=33
>>>>> >> >> > >> > [36] PTR '(anon)' type_id=0
>>>>> >> >> > >> > [37] STRUCT '(anon)' size=24 vlen=3
>>>>> >> >> > >> >     'type' type_id=39 bits_offset=0
>>>>> >> >> > >> >     'key' type_id=40 bits_offset=64
>>>>> >> >> > >> >     'value' type_id=41 bits_offset=128
>>>>> >> >> > >> > [38] ARRAY '(anon)' type_id=9 index_type_id=16 nr_elems=1
>>>>> >> >> > >> > [39] PTR '(anon)' type_id=38
>>>>> >> >> > >> > [40] PTR '(anon)' type_id=12
>>>>> >> >> > >> > [41] PTR '(anon)' type_id=3
>>>>> >> >> > >> > [42] ARRAY '(anon)' type_id=19 index_type_id=16 nr_elems=18
>>>>> >> >> > >> > [43] CONST '(anon)' type_id=42
>>>>> >> >> > >> > [44] FUNC_PROTO '(anon)' ret_type_id=36 vlen=2
>>>>> >> >> > >> >     '(anon)' type_id=36
>>>>> >> >> > >> >     '(anon)' type_id=46
>>>>> >> >> > >> > [45] CONST '(anon)' type_id=0
>>>>> >> >> > >> > [46] PTR '(anon)' type_id=45
>>>>> >> >> > >> > [47] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>>>>> >> >> > >> >     'sk' type_id=48
>>>>> >> >> > >> > [48] PTR '(anon)' type_id=35
>>>>> >> >> > >> > [49] VAR '_license' type_id=43, linkage=static
>>>>> >> >> > >> > [50] VAR 'is_allow_list' type_id=5, linkage=global
>>>>> >> >> > >> > [51] VAR 'sd_restrictif' type_id=37, linkage=global
>>>>> >> >> > >> > [52] FUNC 'sd_restrictif_i' type_id=47 linkage=global
>>>>> >> >> > >> > [53] FUNC 'sd_restrictif_e' type_id=47 linkage=global
>>>>> >> >> > >> > [54] FUNC 'restrict_network_interfaces_impl' type_id=47 linkage=static
>>>>> >> >> > >> > [55] DATASEC '.data' size=1 vlen=1
>>>>> >> >> > >> >     type_id=50 offset=0 size=1 (VAR 'is_allow_list')
>>>>> >> >> > >> > [56] DATASEC 'license' size=18 vlen=1
>>>>> >> >> > >> >     type_id=49 offset=0 size=18 (VAR '_license')
>>>>> >> >> > >> > [57] DATASEC '.maps' size=24 vlen=1
>>>>> >> >> > >> >     type_id=51 offset=0 size=24 (VAR 'sd_restrictif')
>>>>> >> >> > >> >
>>>>> >> >> > >> > File before being stripped using bpftool gen object:
>>>>> >> >> > >> > /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>>>>> >> >> > >> > btf dump file
>>>>> >> >> > >> >
>>>>> >> >
>>>>> >
>>>
>>
> output/build/systemd-custom/build/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
>>>>> >> >> > >> > format raw
>>>>> >> >> > >> > [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>>>>> >> >> > >> > [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
>>>>> >> >> > >> > [3] TYPEDEF '__u8' type_id=2
>>>>> >> >> > >> > [4] CONST '(anon)' type_id=3
>>>>> >> >> > >> > [5] VOLATILE '(anon)' type_id=4
>>>>> >> >> > >> > [6] INT 'short int' size=2 bits_offset=0 nr_bits=16 encoding=SIGNED
>>>>> >> >> > >> > [7] INT 'short unsigned int' size=2 bits_offset=0 nr_bits=16 encoding=(none)
>>>>> >> >> > >> > [8] TYPEDEF '__u16' type_id=7
>>>>> >> >> > >> > [9] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
>>>>> >> >> > >> > [10] TYPEDEF '__s32' type_id=9
>>>>> >> >> > >> > [11] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
>>>>> >> >> > >> > [12] TYPEDEF '__u32' type_id=11
>>>>> >> >> > >> > [13] INT 'long long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
>>>>> >> >> > >> > [14] INT 'long long unsigned int' size=8 bits_offset=0 nr_bits=64
>>>>> >> >> > >> > encoding=(none)
>>>>> >> >> > >> > [15] TYPEDEF '__u64' type_id=14
>>>>> >> >> > >> > [16] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
>>>>> >> >> > >> > [17] INT 'long int' size=8 bits_offset=0 nr_bits=64 encoding=SIGNED
>>>>> >> >> > >> > [18] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>>>>> >> >> > >> > [19] CONST '(anon)' type_id=18
>>>>> >> >> > >> > [20] TYPEDEF '__be16' type_id=8
>>>>> >> >> > >> > [21] TYPEDEF '__be32' type_id=12
>>>>> >> >> > >> > [22] ENUM 'bpf_map_type' encoding=UNSIGNED size=4 vlen=31
>>>>> >> >> > >> >     'BPF_MAP_TYPE_UNSPEC' val=0
>>>>> >> >> > >> >     'BPF_MAP_TYPE_HASH' val=1
>>>>> >> >> > >> >     'BPF_MAP_TYPE_ARRAY' val=2
>>>>> >> >> > >> >     'BPF_MAP_TYPE_PROG_ARRAY' val=3
>>>>> >> >> > >> >     'BPF_MAP_TYPE_PERF_EVENT_ARRAY' val=4
>>>>> >> >> > >> >     'BPF_MAP_TYPE_PERCPU_HASH' val=5
>>>>> >> >> > >> >     'BPF_MAP_TYPE_PERCPU_ARRAY' val=6
>>>>> >> >> > >> >     'BPF_MAP_TYPE_STACK_TRACE' val=7
>>>>> >> >> > >> >     'BPF_MAP_TYPE_CGROUP_ARRAY' val=8
>>>>> >> >> > >> >     'BPF_MAP_TYPE_LRU_HASH' val=9
>>>>> >> >> > >> >     'BPF_MAP_TYPE_LRU_PERCPU_HASH' val=10
>>>>> >> >> > >> >     'BPF_MAP_TYPE_LPM_TRIE' val=11
>>>>> >> >> > >> >     'BPF_MAP_TYPE_ARRAY_OF_MAPS' val=12
>>>>> >> >> > >> >     'BPF_MAP_TYPE_HASH_OF_MAPS' val=13
>>>>> >> >> > >> >     'BPF_MAP_TYPE_DEVMAP' val=14
>>>>> >> >> > >> >     'BPF_MAP_TYPE_SOCKMAP' val=15
>>>>> >> >> > >> >     'BPF_MAP_TYPE_CPUMAP' val=16
>>>>> >> >> > >> >     'BPF_MAP_TYPE_XSKMAP' val=17
>>>>> >> >> > >> >     'BPF_MAP_TYPE_SOCKHASH' val=18
>>>>> >> >> > >> >     'BPF_MAP_TYPE_CGROUP_STORAGE' val=19
>>>>> >> >> > >> >     'BPF_MAP_TYPE_REUSEPORT_SOCKARRAY' val=20
>>>>> >> >> > >> >     'BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE' val=21
>>>>> >> >> > >> >     'BPF_MAP_TYPE_QUEUE' val=22
>>>>> >> >> > >> >     'BPF_MAP_TYPE_STACK' val=23
>>>>> >> >> > >> >     'BPF_MAP_TYPE_SK_STORAGE' val=24
>>>>> >> >> > >> >     'BPF_MAP_TYPE_DEVMAP_HASH' val=25
>>>>> >> >> > >> >     'BPF_MAP_TYPE_STRUCT_OPS' val=26
>>>>> >> >> > >> >     'BPF_MAP_TYPE_RINGBUF' val=27
>>>>> >> >> > >> >     'BPF_MAP_TYPE_INODE_STORAGE' val=28
>>>>> >> >> > >> >     'BPF_MAP_TYPE_TASK_STORAGE' val=29
>>>>> >> >> > >> >     'BPF_MAP_TYPE_BLOOM_FILTER' val=30
>>>>> >> >> > >> > [23] UNION '(anon)' size=8 vlen=1
>>>>> >> >> > >> >     'flow_keys' type_id=29 bits_offset=0
>>>>> >> >> > >> > [24] STRUCT 'bpf_flow_keys' size=56 vlen=13
>>>>> >> >> > >> >     'nhoff' type_id=8 bits_offset=0
>>>>> >> >> > >> >     'thoff' type_id=8 bits_offset=16
>>>>> >> >> > >> >     'addr_proto' type_id=8 bits_offset=32
>>>>> >> >> > >> >     'is_frag' type_id=3 bits_offset=48
>>>>> >> >> > >> >     'is_first_frag' type_id=3 bits_offset=56
>>>>> >> >> > >> >     'is_encap' type_id=3 bits_offset=64
>>>>> >> >> > >> >     'ip_proto' type_id=3 bits_offset=72
>>>>> >> >> > >> >     'n_proto' type_id=20 bits_offset=80
>>>>> >> >> > >> >     'sport' type_id=20 bits_offset=96
>>>>> >> >> > >> >     'dport' type_id=20 bits_offset=112
>>>>> >> >> > >> >     '(anon)' type_id=25 bits_offset=128
>>>>> >> >> > >> >     'flags' type_id=12 bits_offset=384
>>>>> >> >> > >> >     'flow_label' type_id=21 bits_offset=416
>>>>> >> >> > >> > [25] UNION '(anon)' size=32 vlen=2
>>>>> >> >> > >> >     '(anon)' type_id=26 bits_offset=0
>>>>> >> >> > >> >     '(anon)' type_id=27 bits_offset=0
>>>>> >> >> > >> > [26] STRUCT '(anon)' size=8 vlen=2
>>>>> >> >> > >> >     'ipv4_src' type_id=21 bits_offset=0
>>>>> >> >> > >> >     'ipv4_dst' type_id=21 bits_offset=32
>>>>> >> >> > >> > [27] STRUCT '(anon)' size=32 vlen=2
>>>>> >> >> > >> >     'ipv6_src' type_id=28 bits_offset=0
>>>>> >> >> > >> >     'ipv6_dst' type_id=28 bits_offset=128
>>>>> >> >> > >> > [28] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=4
>>>>> >> >> > >> > [29] PTR '(anon)' type_id=24
>>>>> >> >> > >> > [30] UNION '(anon)' size=8 vlen=1
>>>>> >> >> > >> >     'sk' type_id=32 bits_offset=0
>>>>> >> >> > >> > [31] STRUCT 'bpf_sock' size=80 vlen=14
>>>>> >> >> > >> >     'bound_dev_if' type_id=12 bits_offset=0
>>>>> >> >> > >> >     'family' type_id=12 bits_offset=32
>>>>> >> >> > >> >     'type' type_id=12 bits_offset=64
>>>>> >> >> > >> >     'protocol' type_id=12 bits_offset=96
>>>>> >> >> > >> >     'mark' type_id=12 bits_offset=128
>>>>> >> >> > >> >     'priority' type_id=12 bits_offset=160
>>>>> >> >> > >> >     'src_ip4' type_id=12 bits_offset=192
>>>>> >> >> > >> >     'src_ip6' type_id=28 bits_offset=224
>>>>> >> >> > >> >     'src_port' type_id=12 bits_offset=352
>>>>> >> >> > >> >     'dst_port' type_id=20 bits_offset=384
>>>>> >> >> > >> >     'dst_ip4' type_id=12 bits_offset=416
>>>>> >> >> > >> >     'dst_ip6' type_id=28 bits_offset=448
>>>>> >> >> > >> >     'state' type_id=12 bits_offset=576
>>>>> >> >> > >> >     'rx_queue_mapping' type_id=10 bits_offset=608
>>>>> >> >> > >> > [32] PTR '(anon)' type_id=31
>>>>> >> >> > >> > [33] STRUCT '__sk_buff' size=192 vlen=33
>>>>> >> >> > >> >     'len' type_id=12 bits_offset=0
>>>>> >> >> > >> >     'pkt_type' type_id=12 bits_offset=32
>>>>> >> >> > >> >     'mark' type_id=12 bits_offset=64
>>>>> >> >> > >> >     'queue_mapping' type_id=12 bits_offset=96
>>>>> >> >> > >> >     'protocol' type_id=12 bits_offset=128
>>>>> >> >> > >> >     'vlan_present' type_id=12 bits_offset=160
>>>>> >> >> > >> >     'vlan_tci' type_id=12 bits_offset=192
>>>>> >> >> > >> >     'vlan_proto' type_id=12 bits_offset=224
>>>>> >> >> > >> >     'priority' type_id=12 bits_offset=256
>>>>> >> >> > >> >     'ingress_ifindex' type_id=12 bits_offset=288
>>>>> >> >> > >> >     'ifindex' type_id=12 bits_offset=320
>>>>> >> >> > >> >     'tc_index' type_id=12 bits_offset=352
>>>>> >> >> > >> >     'cb' type_id=34 bits_offset=384
>>>>> >> >> > >> >     'hash' type_id=12 bits_offset=544
>>>>> >> >> > >> >     'tc_classid' type_id=12 bits_offset=576
>>>>> >> >> > >> >     'data' type_id=12 bits_offset=608
>>>>> >> >> > >> >     'data_end' type_id=12 bits_offset=640
>>>>> >> >> > >> >     'napi_id' type_id=12 bits_offset=672
>>>>> >> >> > >> >     'family' type_id=12 bits_offset=704
>>>>> >> >> > >> >     'remote_ip4' type_id=12 bits_offset=736
>>>>> >> >> > >> >     'local_ip4' type_id=12 bits_offset=768
>>>>> >> >> > >> >     'remote_ip6' type_id=28 bits_offset=800
>>>>> >> >> > >> >     'local_ip6' type_id=28 bits_offset=928
>>>>> >> >> > >> >     'remote_port' type_id=12 bits_offset=1056
>>>>> >> >> > >> >     'local_port' type_id=12 bits_offset=1088
>>>>> >> >> > >> >     'data_meta' type_id=12 bits_offset=1120
>>>>> >> >> > >> >     '(anon)' type_id=23 bits_offset=1152
>>>>> >> >> > >> >     'tstamp' type_id=15 bits_offset=1216
>>>>> >> >> > >> >     'wire_len' type_id=12 bits_offset=1280
>>>>> >> >> > >> >     'gso_segs' type_id=12 bits_offset=1312
>>>>> >> >> > >> >     '(anon)' type_id=30 bits_offset=1344
>>>>> >> >> > >> >     'gso_size' type_id=12 bits_offset=1408
>>>>> >> >> > >> >     'hwtstamp' type_id=15 bits_offset=1472
>>>>> >> >> > >> > [34] ARRAY '(anon)' type_id=12 index_type_id=16 nr_elems=5
>>>>> >> >> > >> > [35] CONST '(anon)' type_id=33
>>>>> >> >> > >> > [36] PTR '(anon)' type_id=0
>>>>> >> >> > >> > [37] STRUCT '(anon)' size=24 vlen=3
>>>>> >> >> > >> >     'type' type_id=39 bits_offset=0
>>>>> >> >> > >> >     'key' type_id=40 bits_offset=64
>>>>> >> >> > >> >     'value' type_id=41 bits_offset=128
>>>>> >> >> > >> > [38] ARRAY '(anon)' type_id=9 index_type_id=16 nr_elems=1
>>>>> >> >> > >> > [39] PTR '(anon)' type_id=38
>>>>> >> >> > >> > [40] PTR '(anon)' type_id=12
>>>>> >> >> > >> > [41] PTR '(anon)' type_id=3
>>>>> >> >> > >> > [42] ARRAY '(anon)' type_id=19 index_type_id=16 nr_elems=18
>>>>> >> >> > >> > [43] CONST '(anon)' type_id=42
>>>>> >> >> > >> > [44] FUNC_PROTO '(anon)' ret_type_id=36 vlen=2
>>>>> >> >> > >> >     '(anon)' type_id=36
>>>>> >> >> > >> >     '(anon)' type_id=46
>>>>> >> >> > >> > [45] CONST '(anon)' type_id=0
>>>>> >> >> > >> > [46] PTR '(anon)' type_id=45
>>>>> >> >> > >> > [47] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>>>>> >> >> > >> >     'sk' type_id=48
>>>>> >> >> > >> > [48] PTR '(anon)' type_id=35
>>>>> >> >> > >> > [49] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>>>>> >> >> > >> >     'sk' type_id=48
>>>>> >> >> > >> > [50] FUNC_PROTO '(anon)' ret_type_id=9 vlen=1
>>>>> >> >> > >> >     'sk' type_id=48
>>>>> >> >> > >> > [51] VAR '_license' type_id=43, linkage=static
>>>>> >> >> > >> > [52] VAR 'is_allow_list' type_id=5, linkage=global
>>>>> >> >> > >> > [53] VAR 'sd_restrictif' type_id=37, linkage=global
>>>>> >> >> > >> > [54] FUNC 'bpf_map_lookup_elem' type_id=44 linkage=global
>>>>> >> >> > >> > [55] FUNC 'sd_restrictif_i' type_id=47 linkage=global
>>>>> >> >> > >> > [56] FUNC 'sd_restrictif_e' type_id=49 linkage=global
>>>>> >> >> > >> > [57] FUNC 'restrict_network_interfaces_impl' type_id=50 linkage=static
>>>>> >> >> > >> > [58] DATASEC 'license' size=0 vlen=1
>>>>> >> >> > >> >     type_id=51 offset=0 size=18 (VAR '_license')
>>>>> >> >> > >> > [59] DATASEC '.maps' size=0 vlen=1
>>>>> >> >> > >> >     type_id=53 offset=0 size=24 (VAR 'sd_restrictif')
>>>>> >> >> > >> > [60] DATASEC '.data' size=0 vlen=1
>>>>> >> >> > >> >     type_id=52 offset=0 size=1 (VAR 'is_allow_list')
>>>>> >> >> > >> >
>>>>> >> >> > >> >>
>>>>> >> >> > >> >> >> GCC is wrong, clearly. This function is global ([0]) and libbpf
>>>>> >> >> > >> >> >> expects it to be marked as such in BTF.
>>>>> >> >> > >> >> >>
>>>>> >> >> > >> >> >>
>>>>> >> >> > >> >
>>>>> >> >
>>>>> >
>>>
>>
> https://github.com/systemd/systemd/blob/main/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.c#L42-L50
>>>>> >> >> > >> >> >>
>>>>> >> >> > >> >> >>
>>>>> >> >> > >> >> >>> GCC:
>>>>> >> >> > >> >> >>>
>>>>> >> >> > >> >> >>> [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>>>>> >> >> > >> >> >>> [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
>>>>> >> >> > >> >> >>> [3] TYPEDEF '__u8' type_id=2
>>>>> >> >> > >> >> >>> [4] CONST '(anon)' type_id=3
>>>>> >> >> > >> >> >>
>>>>> >> >> > >> >> >> [...]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-07-06 17:20 ` Andrii Nakryiko
  2022-07-06 17:49   ` James Hilliard
  2022-07-08 14:51   ` Jose E. Marchesi
@ 2022-07-12  0:34   ` Indu Bhagat
  2022-07-13  4:28     ` Yonghong Song
  2 siblings, 1 reply; 38+ messages in thread
From: Indu Bhagat @ 2022-07-12  0:34 UTC (permalink / raw)
  To: Andrii Nakryiko, James Hilliard; +Cc: bpf

On 7/6/22 10:20 AM, Andrii Nakryiko wrote:
> On Wed, Jul 6, 2022 at 10:13 AM James Hilliard
> <james.hilliard1@gmail.com> wrote:
>>
>> Note I'm testing with the following patches:
>> https://lore.kernel.org/bpf/20220706111839.1247911-1-james.hilliard1@gmail.com/
>> https://lore.kernel.org/bpf/20220706140623.2917858-1-james.hilliard1@gmail.com/
>>
>> It would appear there's some compatibility issues with bpftool gen and
>> GCC, not sure what side though is wrong here:
>> /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>> gen object src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>> src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
>> libbpf: failed to find BTF info for global/extern symbol 'sd_restrictif_i'
>> Error: failed to link
>> 'src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o':
>> Unknown error -2 (-2)
>>
>> Relevant difference seems to be this:
>> GCC:
>> [55] FUNC 'sd_restrictif_i' type_id=47 linkage=static
>> Clang:
>> [27] FUNC 'sd_restrictif_i' type_id=26 linkage=global
>>
> 
> GCC is wrong, clearly. This function is global ([0]) and libbpf
> expects it to be marked as such in BTF.
> 
> https://github.com/systemd/systemd/blob/main/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.c#L42-L50
> 

How about updating the BTF format documentation in btf.rst to reflect 
the specification for BTF_KIND_FUNC ?

Thanks

diff --git a/Documentation/bpf/btf.rst b/Documentation/bpf/btf.rst
index f49aeef62d0c..b3a9d5ac882c 100644
--- a/Documentation/bpf/btf.rst
+++ b/Documentation/bpf/btf.rst
@@ -369,7 +369,7 @@ No additional type data follow ``btf_type``.
    * ``name_off``: offset to a valid C identifier
    * ``info.kind_flag``: 0
    * ``info.kind``: BTF_KIND_FUNC
-  * ``info.vlen``: 0
+  * ``info.vlen``: linkage information (static=0, global=1)
    * ``type``: a BTF_KIND_FUNC_PROTO type

  No additional type data follow ``btf_type``.

> 
>> GCC:
>>
>> [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>> [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
>> [3] TYPEDEF '__u8' type_id=2
>> [4] CONST '(anon)' type_id=3
> 
> [...]
> 


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-07-12  0:34   ` Indu Bhagat
@ 2022-07-13  4:28     ` Yonghong Song
  0 siblings, 0 replies; 38+ messages in thread
From: Yonghong Song @ 2022-07-13  4:28 UTC (permalink / raw)
  To: Indu Bhagat, Andrii Nakryiko, James Hilliard; +Cc: bpf



On 7/11/22 5:34 PM, Indu Bhagat wrote:
> On 7/6/22 10:20 AM, Andrii Nakryiko wrote:
>> On Wed, Jul 6, 2022 at 10:13 AM James Hilliard
>> <james.hilliard1@gmail.com> wrote:
>>>
>>> Note I'm testing with the following patches:
>>> https://lore.kernel.org/bpf/20220706111839.1247911-1-james.hilliard1@gmail.com/ 
>>>
>>> https://lore.kernel.org/bpf/20220706140623.2917858-1-james.hilliard1@gmail.com/ 
>>>
>>>
>>> It would appear there's some compatibility issues with bpftool gen and
>>> GCC, not sure what side though is wrong here:
>>> /home/buildroot/buildroot/output/per-package/systemd/host/sbin/bpftool
>>> gen object src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.o
>>> src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
>>> libbpf: failed to find BTF info for global/extern symbol 
>>> 'sd_restrictif_i'
>>> Error: failed to link
>>> 'src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o':
>>> Unknown error -2 (-2)
>>>
>>> Relevant difference seems to be this:
>>> GCC:
>>> [55] FUNC 'sd_restrictif_i' type_id=47 linkage=static
>>> Clang:
>>> [27] FUNC 'sd_restrictif_i' type_id=26 linkage=global
>>>
>>
>> GCC is wrong, clearly. This function is global ([0]) and libbpf
>> expects it to be marked as such in BTF.
>>
>> https://github.com/systemd/systemd/blob/main/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.c#L42-L50 
>>
>>
> 
> How about updating the BTF format documentation in btf.rst to reflect 
> the specification for BTF_KIND_FUNC ?

The below patch sounds good. Could you send a patch for this? Thanks!

> 
> Thanks
> 
> diff --git a/Documentation/bpf/btf.rst b/Documentation/bpf/btf.rst
> index f49aeef62d0c..b3a9d5ac882c 100644
> --- a/Documentation/bpf/btf.rst
> +++ b/Documentation/bpf/btf.rst
> @@ -369,7 +369,7 @@ No additional type data follow ``btf_type``.
>     * ``name_off``: offset to a valid C identifier
>     * ``info.kind_flag``: 0
>     * ``info.kind``: BTF_KIND_FUNC
> -  * ``info.vlen``: 0
> +  * ``info.vlen``: linkage information (static=0, global=1)
>     * ``type``: a BTF_KIND_FUNC_PROTO type
> 
>   No additional type data follow ``btf_type``.
> 
>>
>>> GCC:
>>>
>>> [1] INT 'signed char' size=1 bits_offset=0 nr_bits=8 encoding=UNKN
>>> [2] INT 'unsigned char' size=1 bits_offset=0 nr_bits=8 encoding=CHAR
>>> [3] TYPEDEF '__u8' type_id=2
>>> [4] CONST '(anon)' type_id=3
>>
>> [...]
>>
> 

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
       [not found]                                 ` <CADvTj4o-36iuru665BW0XnEauXBeszW438QTtpt4_VUEjf5nXg@mail.gmail.com>
@ 2022-08-01 22:51                                   ` Andrii Nakryiko
  2022-08-01 23:35                                     ` James Hilliard
  0 siblings, 1 reply; 38+ messages in thread
From: Andrii Nakryiko @ 2022-08-01 22:51 UTC (permalink / raw)
  To: James Hilliard; +Cc: Jose E. Marchesi, bpf, david.faust

On Sun, Jul 31, 2022 at 7:20 PM James Hilliard
<james.hilliard1@gmail.com> wrote:
>
> On Sun, Jul 10, 2022 at 2:22 PM Jose E. Marchesi
> <jose.marchesi@oracle.com> wrote:
> >
> >
> > >>> On Sun, Jul 10, 2022 at 3:38 AM Jose E. Marchesi
> > >>> <jose.marchesi@oracle.com> wrote:
> > >>>>
> > >>>>
> > >>>> > On Sat, Jul 9, 2022 at 4:41 PM Jose E. Marchesi
> > >>>> > <jose.marchesi@oracle.com> wrote:
> > >>>> >>
> > >>>> >>
> > >>>> >> > On Sat, Jul 9, 2022 at 2:32 PM James Hilliard <james.hilliard1@gmail.com> wrote:
> > >>>> >> >>
> > >>>> >> >> On Sat, Jul 9, 2022 at 2:21 PM Jose E. Marchesi
> > >>>> >> >> <jose.marchesi@oracle.com> wrote:
> > >>>> >> >> >
> > >>>> >> >> >

Please trim your replies (and I don't know what your email client did,
but it completely ruined nested quote formatting)

[...]

> > >>>>
> > >>>> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> > >>>> index e89cc9c885b3..887b78780099 100644
> > >>>> --- a/tools/lib/bpf/libbpf.c
> > >>>> +++ b/tools/lib/bpf/libbpf.c
> > >>>> @@ -1591,6 +1591,10 @@ static int bpf_object__init_global_data_maps(struct bpf_object *obj)
> > >>>>         for (sec_idx = 1; sec_idx < obj->efile.sec_cnt; sec_idx++) {
> > >>>>                 sec_desc = &obj->efile.secs[sec_idx];
> > >>>>
> > >>>> +                /* Skip recognized sections with size 0.  */
> > >>>> +                if (sec_desc->data && sec_desc->data->d_size == 0)
> > >>>> +                  continue;
> > >>>> +
> > >>>>                 switch (sec_desc->sec_type) {
> > >>>>                 case SEC_DATA:
> > >>>>                         sec_name = elf_sec_name(obj, elf_sec_by_idx(obj, sec_idx));
> > >>>
> > >>> Ok, skeleton is now getting generated successfully, however it differs from the
> > >>> clang version so there's a build error when we include/use the header:
> > >>> ../src/core/restrict-ifaces.c: In function ‘prepare_restrict_ifaces_bpf’:
> > >>> ../src/core/restrict-ifaces.c:45:14: error: ‘struct
> > >>> restrict_ifaces_bpf’ has no member named ‘rodata’; did you mean
> > >>> ‘data’?
> > >>>    45 |         obj->rodata->is_allow_list = is_allow_list;
> > >>>       |              ^~~~~~
> > >>>       |              data
> > >>>
> > >>> The issue appears to be that clang generates "rodata" members in
> > >>> restrict_ifaces_bpf while with gcc we get "data" members instead.
> > >>
> > >> This is because the BPF GCC port is putting the
> > >>
> > >>   const volatile unsigned char is_allow_list = 0;
> > >>
> > >> in a .data section instead of .rodata, due to the `volatile'.  The
> > >> x86_64 GCC seems to use .rodata.
> > >>
> > >> Looking at why the PBF port does this...
> > >
> > > So, turns out GCC puts zero-initialized `const volatile' variables in
> > > .data sections (and not .rodata) in all the targets I have tried, like
> > > x86_64 and aarch64.
> > >
> > > So this is a LLVM and GCC divergence :/
> >
> > See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25521.
> >
> > You may try, as a workaround:
> >
> > __attribute__((section(".rodata"))) const volatile unsigned char is_allow_list = 0;
> >
> > But that will use permissions "aw" for the .rodata section (and you will
> > get a warning from the assembler.)  It may be problematic for libbpf.
>
> So rather than try to force gcc to use the incorrect llvm .rodata
> section it looks
> like we can instead just force llvm to use the correct .data section like this:
> https://github.com/systemd/systemd/pull/24164
>

There is a huge difference between variables in .rodata and .data.
.rodata variable's value is known to the BPF verifier at verification
time and this knowledge will be used to decide which code paths are
always or never taken (as one example). It's a crucial property and
important guarantee.

If you don't care about that property, don't declare the variable as `const`.

So no, it's not llvm putting `const` variable into .rodata
incorrectly, but GCC is trying to be smart and just because variable
is declared volatile is putting *const* variable into read-write .data
section. It's declared as const, and yes it's volatile to make sure
that compiler isn't too smart about optimizing away read operations.
But it's still a const read-only variable from the perspective of that
BPF C code.

If you don't care about the read-only nature of that variable, drop
the const and make it into a non-read-only variable.

And please stop proposing hacks to be added to perfectly valid systemd
BPF source code (I replied on [0] as well).

  [0] https://github.com/systemd/systemd/pull/24164#issuecomment-1201806413


[...]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-08-01 22:51                                   ` Andrii Nakryiko
@ 2022-08-01 23:35                                     ` James Hilliard
  2022-08-02 21:28                                       ` Andrii Nakryiko
  0 siblings, 1 reply; 38+ messages in thread
From: James Hilliard @ 2022-08-01 23:35 UTC (permalink / raw)
  To: Andrii Nakryiko; +Cc: Jose E. Marchesi, bpf, david.faust

On Mon, Aug 1, 2022 at 4:52 PM Andrii Nakryiko
<andrii.nakryiko@gmail.com> wrote:
>
> On Sun, Jul 31, 2022 at 7:20 PM James Hilliard
> <james.hilliard1@gmail.com> wrote:
> >
> > On Sun, Jul 10, 2022 at 2:22 PM Jose E. Marchesi
> > <jose.marchesi@oracle.com> wrote:
> > >
> > >
> > > >>> On Sun, Jul 10, 2022 at 3:38 AM Jose E. Marchesi
> > > >>> <jose.marchesi@oracle.com> wrote:
> > > >>>>
> > > >>>>
> > > >>>> > On Sat, Jul 9, 2022 at 4:41 PM Jose E. Marchesi
> > > >>>> > <jose.marchesi@oracle.com> wrote:
> > > >>>> >>
> > > >>>> >>
> > > >>>> >> > On Sat, Jul 9, 2022 at 2:32 PM James Hilliard <james.hilliard1@gmail.com> wrote:
> > > >>>> >> >>
> > > >>>> >> >> On Sat, Jul 9, 2022 at 2:21 PM Jose E. Marchesi
> > > >>>> >> >> <jose.marchesi@oracle.com> wrote:
> > > >>>> >> >> >
> > > >>>> >> >> >
>
> Please trim your replies (and I don't know what your email client did,
> but it completely ruined nested quote formatting)

Yeah, not sure what happened there.

>
> [...]
>
> > > >>>>
> > > >>>> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> > > >>>> index e89cc9c885b3..887b78780099 100644
> > > >>>> --- a/tools/lib/bpf/libbpf.c
> > > >>>> +++ b/tools/lib/bpf/libbpf.c
> > > >>>> @@ -1591,6 +1591,10 @@ static int bpf_object__init_global_data_maps(struct bpf_object *obj)
> > > >>>>         for (sec_idx = 1; sec_idx < obj->efile.sec_cnt; sec_idx++) {
> > > >>>>                 sec_desc = &obj->efile.secs[sec_idx];
> > > >>>>
> > > >>>> +                /* Skip recognized sections with size 0.  */
> > > >>>> +                if (sec_desc->data && sec_desc->data->d_size == 0)
> > > >>>> +                  continue;
> > > >>>> +
> > > >>>>                 switch (sec_desc->sec_type) {
> > > >>>>                 case SEC_DATA:
> > > >>>>                         sec_name = elf_sec_name(obj, elf_sec_by_idx(obj, sec_idx));
> > > >>>
> > > >>> Ok, skeleton is now getting generated successfully, however it differs from the
> > > >>> clang version so there's a build error when we include/use the header:
> > > >>> ../src/core/restrict-ifaces.c: In function ‘prepare_restrict_ifaces_bpf’:
> > > >>> ../src/core/restrict-ifaces.c:45:14: error: ‘struct
> > > >>> restrict_ifaces_bpf’ has no member named ‘rodata’; did you mean
> > > >>> ‘data’?
> > > >>>    45 |         obj->rodata->is_allow_list = is_allow_list;
> > > >>>       |              ^~~~~~
> > > >>>       |              data
> > > >>>
> > > >>> The issue appears to be that clang generates "rodata" members in
> > > >>> restrict_ifaces_bpf while with gcc we get "data" members instead.
> > > >>
> > > >> This is because the BPF GCC port is putting the
> > > >>
> > > >>   const volatile unsigned char is_allow_list = 0;
> > > >>
> > > >> in a .data section instead of .rodata, due to the `volatile'.  The
> > > >> x86_64 GCC seems to use .rodata.
> > > >>
> > > >> Looking at why the PBF port does this...
> > > >
> > > > So, turns out GCC puts zero-initialized `const volatile' variables in
> > > > .data sections (and not .rodata) in all the targets I have tried, like
> > > > x86_64 and aarch64.
> > > >
> > > > So this is a LLVM and GCC divergence :/
> > >
> > > See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25521.
> > >
> > > You may try, as a workaround:
> > >
> > > __attribute__((section(".rodata"))) const volatile unsigned char is_allow_list = 0;
> > >
> > > But that will use permissions "aw" for the .rodata section (and you will
> > > get a warning from the assembler.)  It may be problematic for libbpf.
> >
> > So rather than try to force gcc to use the incorrect llvm .rodata
> > section it looks
> > like we can instead just force llvm to use the correct .data section like this:
> > https://github.com/systemd/systemd/pull/24164
> >
>
> There is a huge difference between variables in .rodata and .data.
> .rodata variable's value is known to the BPF verifier at verification
> time and this knowledge will be used to decide which code paths are
> always or never taken (as one example). It's a crucial property and
> important guarantee.
>
> If you don't care about that property, don't declare the variable as `const`.
>
> So no, it's not llvm putting `const` variable into .rodata
> incorrectly, but GCC is trying to be smart and just because variable
> is declared volatile is putting *const* variable into read-write .data
> section. It's declared as const, and yes it's volatile to make sure
> that compiler isn't too smart about optimizing away read operations.

Isn't const volatile generating a .rodata section(like llvm is doing) a spec
violation?
https://github.com/llvm/llvm-project/issues/56468

> But it's still a const read-only variable from the perspective of that
> BPF C code.
>
> If you don't care about the read-only nature of that variable, drop
> the const and make it into a non-read-only variable.
>
> And please stop proposing hacks to be added to perfectly valid systemd
> BPF source code (I replied on [0] as well).

From my understanding gcc is correctly putting a const volatile variable
in .data while llvm is incorrectly putting it in .rodata, is the gcc behavior
here invalid or is the llvm behavior invalid?

>
>   [0] https://github.com/systemd/systemd/pull/24164#issuecomment-1201806413
>
>
> [...]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-07-08 18:33     ` Jose E. Marchesi
  2022-07-08 20:59       ` James Hilliard
@ 2022-08-02 15:57       ` Jose E. Marchesi
  1 sibling, 0 replies; 38+ messages in thread
From: Jose E. Marchesi @ 2022-08-02 15:57 UTC (permalink / raw)
  To: Andrii Nakryiko; +Cc: James Hilliard, bpf, david.faust


>> For functions GCC generates a BTF_KIND_FUNC entry, which has no linkage
>> information, or so we thought: I just looked at bpftool/btf.c and I
>> found the linkage info for function types is expected to be encoded in
>> the vlen field of BTF_KIND_FUNC entries (why not adding a btf_func
>> instead???) which is surprising to say the least.
>>
>> We are changing GCC to encode the linkage info in vlen for these types.
>> Thanks for reporting this.
>
> Patch sent to GCC upstream:
> https://gcc.gnu.org/pipermail/gcc-patches/2022-July/598090.html

FYI this is now applied in GCC master.

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-08-01 23:35                                     ` James Hilliard
@ 2022-08-02 21:28                                       ` Andrii Nakryiko
  2022-08-02 22:05                                         ` James Hilliard
  0 siblings, 1 reply; 38+ messages in thread
From: Andrii Nakryiko @ 2022-08-02 21:28 UTC (permalink / raw)
  To: James Hilliard; +Cc: Jose E. Marchesi, bpf, david.faust

On Mon, Aug 1, 2022 at 4:35 PM James Hilliard <james.hilliard1@gmail.com> wrote:
>
> On Mon, Aug 1, 2022 at 4:52 PM Andrii Nakryiko
> <andrii.nakryiko@gmail.com> wrote:
> >
> > On Sun, Jul 31, 2022 at 7:20 PM James Hilliard
> > <james.hilliard1@gmail.com> wrote:
> > >
> > > On Sun, Jul 10, 2022 at 2:22 PM Jose E. Marchesi
> > > <jose.marchesi@oracle.com> wrote:
> > > >
> > > >
> > > > >>> On Sun, Jul 10, 2022 at 3:38 AM Jose E. Marchesi
> > > > >>> <jose.marchesi@oracle.com> wrote:
> > > > >>>>
> > > > >>>>
> > > > >>>> > On Sat, Jul 9, 2022 at 4:41 PM Jose E. Marchesi
> > > > >>>> > <jose.marchesi@oracle.com> wrote:
> > > > >>>> >>
> > > > >>>> >>
> > > > >>>> >> > On Sat, Jul 9, 2022 at 2:32 PM James Hilliard <james.hilliard1@gmail.com> wrote:
> > > > >>>> >> >>
> > > > >>>> >> >> On Sat, Jul 9, 2022 at 2:21 PM Jose E. Marchesi
> > > > >>>> >> >> <jose.marchesi@oracle.com> wrote:
> > > > >>>> >> >> >
> > > > >>>> >> >> >
> >
> > Please trim your replies (and I don't know what your email client did,
> > but it completely ruined nested quote formatting)
>
> Yeah, not sure what happened there.
>
> >
> > [...]
> >
> > > > >>>>
> > > > >>>> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> > > > >>>> index e89cc9c885b3..887b78780099 100644
> > > > >>>> --- a/tools/lib/bpf/libbpf.c
> > > > >>>> +++ b/tools/lib/bpf/libbpf.c
> > > > >>>> @@ -1591,6 +1591,10 @@ static int bpf_object__init_global_data_maps(struct bpf_object *obj)
> > > > >>>>         for (sec_idx = 1; sec_idx < obj->efile.sec_cnt; sec_idx++) {
> > > > >>>>                 sec_desc = &obj->efile.secs[sec_idx];
> > > > >>>>
> > > > >>>> +                /* Skip recognized sections with size 0.  */
> > > > >>>> +                if (sec_desc->data && sec_desc->data->d_size == 0)
> > > > >>>> +                  continue;
> > > > >>>> +
> > > > >>>>                 switch (sec_desc->sec_type) {
> > > > >>>>                 case SEC_DATA:
> > > > >>>>                         sec_name = elf_sec_name(obj, elf_sec_by_idx(obj, sec_idx));
> > > > >>>
> > > > >>> Ok, skeleton is now getting generated successfully, however it differs from the
> > > > >>> clang version so there's a build error when we include/use the header:
> > > > >>> ../src/core/restrict-ifaces.c: In function ‘prepare_restrict_ifaces_bpf’:
> > > > >>> ../src/core/restrict-ifaces.c:45:14: error: ‘struct
> > > > >>> restrict_ifaces_bpf’ has no member named ‘rodata’; did you mean
> > > > >>> ‘data’?
> > > > >>>    45 |         obj->rodata->is_allow_list = is_allow_list;
> > > > >>>       |              ^~~~~~
> > > > >>>       |              data
> > > > >>>
> > > > >>> The issue appears to be that clang generates "rodata" members in
> > > > >>> restrict_ifaces_bpf while with gcc we get "data" members instead.
> > > > >>
> > > > >> This is because the BPF GCC port is putting the
> > > > >>
> > > > >>   const volatile unsigned char is_allow_list = 0;
> > > > >>
> > > > >> in a .data section instead of .rodata, due to the `volatile'.  The
> > > > >> x86_64 GCC seems to use .rodata.
> > > > >>
> > > > >> Looking at why the PBF port does this...
> > > > >
> > > > > So, turns out GCC puts zero-initialized `const volatile' variables in
> > > > > .data sections (and not .rodata) in all the targets I have tried, like
> > > > > x86_64 and aarch64.
> > > > >
> > > > > So this is a LLVM and GCC divergence :/
> > > >
> > > > See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25521.
> > > >
> > > > You may try, as a workaround:
> > > >
> > > > __attribute__((section(".rodata"))) const volatile unsigned char is_allow_list = 0;
> > > >
> > > > But that will use permissions "aw" for the .rodata section (and you will
> > > > get a warning from the assembler.)  It may be problematic for libbpf.
> > >
> > > So rather than try to force gcc to use the incorrect llvm .rodata
> > > section it looks
> > > like we can instead just force llvm to use the correct .data section like this:
> > > https://github.com/systemd/systemd/pull/24164
> > >
> >
> > There is a huge difference between variables in .rodata and .data.
> > .rodata variable's value is known to the BPF verifier at verification
> > time and this knowledge will be used to decide which code paths are
> > always or never taken (as one example). It's a crucial property and
> > important guarantee.
> >
> > If you don't care about that property, don't declare the variable as `const`.
> >
> > So no, it's not llvm putting `const` variable into .rodata
> > incorrectly, but GCC is trying to be smart and just because variable
> > is declared volatile is putting *const* variable into read-write .data
> > section. It's declared as const, and yes it's volatile to make sure
> > that compiler isn't too smart about optimizing away read operations.
>
> Isn't const volatile generating a .rodata section(like llvm is doing) a spec
> violation?
> https://github.com/llvm/llvm-project/issues/56468
>
> > But it's still a const read-only variable from the perspective of that
> > BPF C code.
> >
> > If you don't care about the read-only nature of that variable, drop
> > the const and make it into a non-read-only variable.
> >
> > And please stop proposing hacks to be added to perfectly valid systemd
> > BPF source code (I replied on [0] as well).
>
> From my understanding gcc is correctly putting a const volatile variable
> in .data while llvm is incorrectly putting it in .rodata, is the gcc behavior
> here invalid or is the llvm behavior invalid?

From link you left to C standard, it does seem like that side-note
*implies* that const volatile should be put into .data, but it's a)
implied b) is quite arguable about assumptions that this data has to
be in modifiable section, and c) entire CO-RE feature detection and
guarding relies on having `const volatile` variables in .rodata and
mark them as read-only for BPF verifier to allow dead code
elimination. Changing c) would break entire CO-RE ecosystem.

Seems like this issue was raised by Ulrich Drepper back in 2005 ([0])
and he was also confused about GCC's behavior, btw.

So either way, at the very least for BPF target we can't change this
and I still think it's more logical to put const variables into
.rodata, regardless of side notes in C standard.


As for systemd's program and its is_allow_list ([1]), to unblock
yourself you can drop const because systemd doesn't rely on read-only
guarantees of that variable anyways. It's much more critical in
feature-detection use cases. But let's try to converge discussion in
one place (preferably here), it's quite inconvenient to either reply
the same thing twice here and on Github, or cross-reference lore and
Github.


  [0] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25521
  [1] https://github.com/systemd/systemd/pull/24164#issuecomment-1203207372

>
> >
> >   [0] https://github.com/systemd/systemd/pull/24164#issuecomment-1201806413
> >
> >
> > [...]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-08-02 21:28                                       ` Andrii Nakryiko
@ 2022-08-02 22:05                                         ` James Hilliard
  2022-08-03  0:29                                           ` Andrii Nakryiko
  0 siblings, 1 reply; 38+ messages in thread
From: James Hilliard @ 2022-08-02 22:05 UTC (permalink / raw)
  To: Andrii Nakryiko; +Cc: Jose E. Marchesi, bpf, david.faust

On Tue, Aug 2, 2022 at 3:29 PM Andrii Nakryiko
<andrii.nakryiko@gmail.com> wrote:
>
> On Mon, Aug 1, 2022 at 4:35 PM James Hilliard <james.hilliard1@gmail.com> wrote:
> >
> > On Mon, Aug 1, 2022 at 4:52 PM Andrii Nakryiko
> > <andrii.nakryiko@gmail.com> wrote:
> > >
> > > On Sun, Jul 31, 2022 at 7:20 PM James Hilliard
> > > <james.hilliard1@gmail.com> wrote:
> > > >
> > > > On Sun, Jul 10, 2022 at 2:22 PM Jose E. Marchesi
> > > > <jose.marchesi@oracle.com> wrote:
> > > > >
> > > > >
> > > > > >>> On Sun, Jul 10, 2022 at 3:38 AM Jose E. Marchesi
> > > > > >>> <jose.marchesi@oracle.com> wrote:
> > > > > >>>>
> > > > > >>>>
> > > > > >>>> > On Sat, Jul 9, 2022 at 4:41 PM Jose E. Marchesi
> > > > > >>>> > <jose.marchesi@oracle.com> wrote:
> > > > > >>>> >>
> > > > > >>>> >>
> > > > > >>>> >> > On Sat, Jul 9, 2022 at 2:32 PM James Hilliard <james.hilliard1@gmail.com> wrote:
> > > > > >>>> >> >>
> > > > > >>>> >> >> On Sat, Jul 9, 2022 at 2:21 PM Jose E. Marchesi
> > > > > >>>> >> >> <jose.marchesi@oracle.com> wrote:
> > > > > >>>> >> >> >
> > > > > >>>> >> >> >
> > >
> > > Please trim your replies (and I don't know what your email client did,
> > > but it completely ruined nested quote formatting)
> >
> > Yeah, not sure what happened there.
> >
> > >
> > > [...]
> > >
> > > > > >>>>
> > > > > >>>> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> > > > > >>>> index e89cc9c885b3..887b78780099 100644
> > > > > >>>> --- a/tools/lib/bpf/libbpf.c
> > > > > >>>> +++ b/tools/lib/bpf/libbpf.c
> > > > > >>>> @@ -1591,6 +1591,10 @@ static int bpf_object__init_global_data_maps(struct bpf_object *obj)
> > > > > >>>>         for (sec_idx = 1; sec_idx < obj->efile.sec_cnt; sec_idx++) {
> > > > > >>>>                 sec_desc = &obj->efile.secs[sec_idx];
> > > > > >>>>
> > > > > >>>> +                /* Skip recognized sections with size 0.  */
> > > > > >>>> +                if (sec_desc->data && sec_desc->data->d_size == 0)
> > > > > >>>> +                  continue;
> > > > > >>>> +
> > > > > >>>>                 switch (sec_desc->sec_type) {
> > > > > >>>>                 case SEC_DATA:
> > > > > >>>>                         sec_name = elf_sec_name(obj, elf_sec_by_idx(obj, sec_idx));
> > > > > >>>
> > > > > >>> Ok, skeleton is now getting generated successfully, however it differs from the
> > > > > >>> clang version so there's a build error when we include/use the header:
> > > > > >>> ../src/core/restrict-ifaces.c: In function ‘prepare_restrict_ifaces_bpf’:
> > > > > >>> ../src/core/restrict-ifaces.c:45:14: error: ‘struct
> > > > > >>> restrict_ifaces_bpf’ has no member named ‘rodata’; did you mean
> > > > > >>> ‘data’?
> > > > > >>>    45 |         obj->rodata->is_allow_list = is_allow_list;
> > > > > >>>       |              ^~~~~~
> > > > > >>>       |              data
> > > > > >>>
> > > > > >>> The issue appears to be that clang generates "rodata" members in
> > > > > >>> restrict_ifaces_bpf while with gcc we get "data" members instead.
> > > > > >>
> > > > > >> This is because the BPF GCC port is putting the
> > > > > >>
> > > > > >>   const volatile unsigned char is_allow_list = 0;
> > > > > >>
> > > > > >> in a .data section instead of .rodata, due to the `volatile'.  The
> > > > > >> x86_64 GCC seems to use .rodata.
> > > > > >>
> > > > > >> Looking at why the PBF port does this...
> > > > > >
> > > > > > So, turns out GCC puts zero-initialized `const volatile' variables in
> > > > > > .data sections (and not .rodata) in all the targets I have tried, like
> > > > > > x86_64 and aarch64.
> > > > > >
> > > > > > So this is a LLVM and GCC divergence :/
> > > > >
> > > > > See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25521.
> > > > >
> > > > > You may try, as a workaround:
> > > > >
> > > > > __attribute__((section(".rodata"))) const volatile unsigned char is_allow_list = 0;
> > > > >
> > > > > But that will use permissions "aw" for the .rodata section (and you will
> > > > > get a warning from the assembler.)  It may be problematic for libbpf.
> > > >
> > > > So rather than try to force gcc to use the incorrect llvm .rodata
> > > > section it looks
> > > > like we can instead just force llvm to use the correct .data section like this:
> > > > https://github.com/systemd/systemd/pull/24164
> > > >
> > >
> > > There is a huge difference between variables in .rodata and .data.
> > > .rodata variable's value is known to the BPF verifier at verification
> > > time and this knowledge will be used to decide which code paths are
> > > always or never taken (as one example). It's a crucial property and
> > > important guarantee.
> > >
> > > If you don't care about that property, don't declare the variable as `const`.
> > >
> > > So no, it's not llvm putting `const` variable into .rodata
> > > incorrectly, but GCC is trying to be smart and just because variable
> > > is declared volatile is putting *const* variable into read-write .data
> > > section. It's declared as const, and yes it's volatile to make sure
> > > that compiler isn't too smart about optimizing away read operations.
> >
> > Isn't const volatile generating a .rodata section(like llvm is doing) a spec
> > violation?
> > https://github.com/llvm/llvm-project/issues/56468
> >
> > > But it's still a const read-only variable from the perspective of that
> > > BPF C code.
> > >
> > > If you don't care about the read-only nature of that variable, drop
> > > the const and make it into a non-read-only variable.
> > >
> > > And please stop proposing hacks to be added to perfectly valid systemd
> > > BPF source code (I replied on [0] as well).
> >
> > From my understanding gcc is correctly putting a const volatile variable
> > in .data while llvm is incorrectly putting it in .rodata, is the gcc behavior
> > here invalid or is the llvm behavior invalid?
>
> From link you left to C standard, it does seem like that side-note
> *implies* that const volatile should be put into .data, but it's a)
> implied b) is quite arguable about assumptions that this data has to
> be in modifiable section, and c) entire CO-RE feature detection and
> guarding relies on having `const volatile` variables in .rodata and
> mark them as read-only for BPF verifier to allow dead code
> elimination. Changing c) would break entire CO-RE ecosystem.

Well it does appear that llvm is fixing the behavior to be in line with gcc:
https://reviews.llvm.org/D131012

>
> Seems like this issue was raised by Ulrich Drepper back in 2005 ([0])
> and he was also confused about GCC's behavior, btw.
>
> So either way, at the very least for BPF target we can't change this
> and I still think it's more logical to put const variables into
> .rodata, regardless of side notes in C standard.

GCC does put const variables in .rodata, just not const volatile variables.

>
>
> As for systemd's program and its is_allow_list ([1]), to unblock
> yourself you can drop const because systemd doesn't rely on read-only
> guarantees of that variable anyways. It's much more critical in
> feature-detection use cases. But let's try to converge discussion in
> one place (preferably here), it's quite inconvenient to either reply
> the same thing twice here and on Github, or cross-reference lore and
> Github.

Hmm, are you sure:
const __u8 is_allow_list SEC(".rodata") = 0;

doesn't provide equivalent behavior to:
const volatile __u8 is_allow_list = 0;

The used attribute in the SEC macro supposedly ensures that:
The compiler must emit the definition even if it appears to be unused, and
it must not apply optimizations which depend on fully understanding how
the entity is used.

Or maybe the retain attribute along with used would be sufficient to allow
us to drop volatile in these cases?:
https://clang.llvm.org/docs/AttributeReference.html#retain

>
>
>   [0] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25521
>   [1] https://github.com/systemd/systemd/pull/24164#issuecomment-1203207372
>
> >
> > >
> > >   [0] https://github.com/systemd/systemd/pull/24164#issuecomment-1201806413
> > >
> > >
> > > [...]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-08-02 22:05                                         ` James Hilliard
@ 2022-08-03  0:29                                           ` Andrii Nakryiko
  2022-08-03  1:49                                             ` James Hilliard
  0 siblings, 1 reply; 38+ messages in thread
From: Andrii Nakryiko @ 2022-08-03  0:29 UTC (permalink / raw)
  To: James Hilliard; +Cc: Jose E. Marchesi, bpf, david.faust

On Tue, Aug 2, 2022 at 3:06 PM James Hilliard <james.hilliard1@gmail.com> wrote:
>
> On Tue, Aug 2, 2022 at 3:29 PM Andrii Nakryiko
> <andrii.nakryiko@gmail.com> wrote:
> >
> > On Mon, Aug 1, 2022 at 4:35 PM James Hilliard <james.hilliard1@gmail.com> wrote:
> > >
> > > On Mon, Aug 1, 2022 at 4:52 PM Andrii Nakryiko
> > > <andrii.nakryiko@gmail.com> wrote:
> > > >
> > > > On Sun, Jul 31, 2022 at 7:20 PM James Hilliard
> > > > <james.hilliard1@gmail.com> wrote:
> > > > >
> > > > > On Sun, Jul 10, 2022 at 2:22 PM Jose E. Marchesi
> > > > > <jose.marchesi@oracle.com> wrote:
> > > > > >
> > > > > >
> > > > > > >>> On Sun, Jul 10, 2022 at 3:38 AM Jose E. Marchesi
> > > > > > >>> <jose.marchesi@oracle.com> wrote:
> > > > > > >>>>
> > > > > > >>>>
> > > > > > >>>> > On Sat, Jul 9, 2022 at 4:41 PM Jose E. Marchesi
> > > > > > >>>> > <jose.marchesi@oracle.com> wrote:
> > > > > > >>>> >>
> > > > > > >>>> >>
> > > > > > >>>> >> > On Sat, Jul 9, 2022 at 2:32 PM James Hilliard <james.hilliard1@gmail.com> wrote:
> > > > > > >>>> >> >>
> > > > > > >>>> >> >> On Sat, Jul 9, 2022 at 2:21 PM Jose E. Marchesi
> > > > > > >>>> >> >> <jose.marchesi@oracle.com> wrote:
> > > > > > >>>> >> >> >
> > > > > > >>>> >> >> >
> > > >
> > > > Please trim your replies (and I don't know what your email client did,
> > > > but it completely ruined nested quote formatting)
> > >
> > > Yeah, not sure what happened there.
> > >
> > > >
> > > > [...]
> > > >
> > > > > > >>>>
> > > > > > >>>> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> > > > > > >>>> index e89cc9c885b3..887b78780099 100644
> > > > > > >>>> --- a/tools/lib/bpf/libbpf.c
> > > > > > >>>> +++ b/tools/lib/bpf/libbpf.c
> > > > > > >>>> @@ -1591,6 +1591,10 @@ static int bpf_object__init_global_data_maps(struct bpf_object *obj)
> > > > > > >>>>         for (sec_idx = 1; sec_idx < obj->efile.sec_cnt; sec_idx++) {
> > > > > > >>>>                 sec_desc = &obj->efile.secs[sec_idx];
> > > > > > >>>>
> > > > > > >>>> +                /* Skip recognized sections with size 0.  */
> > > > > > >>>> +                if (sec_desc->data && sec_desc->data->d_size == 0)
> > > > > > >>>> +                  continue;
> > > > > > >>>> +
> > > > > > >>>>                 switch (sec_desc->sec_type) {
> > > > > > >>>>                 case SEC_DATA:
> > > > > > >>>>                         sec_name = elf_sec_name(obj, elf_sec_by_idx(obj, sec_idx));
> > > > > > >>>
> > > > > > >>> Ok, skeleton is now getting generated successfully, however it differs from the
> > > > > > >>> clang version so there's a build error when we include/use the header:
> > > > > > >>> ../src/core/restrict-ifaces.c: In function ‘prepare_restrict_ifaces_bpf’:
> > > > > > >>> ../src/core/restrict-ifaces.c:45:14: error: ‘struct
> > > > > > >>> restrict_ifaces_bpf’ has no member named ‘rodata’; did you mean
> > > > > > >>> ‘data’?
> > > > > > >>>    45 |         obj->rodata->is_allow_list = is_allow_list;
> > > > > > >>>       |              ^~~~~~
> > > > > > >>>       |              data
> > > > > > >>>
> > > > > > >>> The issue appears to be that clang generates "rodata" members in
> > > > > > >>> restrict_ifaces_bpf while with gcc we get "data" members instead.
> > > > > > >>
> > > > > > >> This is because the BPF GCC port is putting the
> > > > > > >>
> > > > > > >>   const volatile unsigned char is_allow_list = 0;
> > > > > > >>
> > > > > > >> in a .data section instead of .rodata, due to the `volatile'.  The
> > > > > > >> x86_64 GCC seems to use .rodata.
> > > > > > >>
> > > > > > >> Looking at why the PBF port does this...
> > > > > > >
> > > > > > > So, turns out GCC puts zero-initialized `const volatile' variables in
> > > > > > > .data sections (and not .rodata) in all the targets I have tried, like
> > > > > > > x86_64 and aarch64.
> > > > > > >
> > > > > > > So this is a LLVM and GCC divergence :/
> > > > > >
> > > > > > See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25521.
> > > > > >
> > > > > > You may try, as a workaround:
> > > > > >
> > > > > > __attribute__((section(".rodata"))) const volatile unsigned char is_allow_list = 0;
> > > > > >
> > > > > > But that will use permissions "aw" for the .rodata section (and you will
> > > > > > get a warning from the assembler.)  It may be problematic for libbpf.
> > > > >
> > > > > So rather than try to force gcc to use the incorrect llvm .rodata
> > > > > section it looks
> > > > > like we can instead just force llvm to use the correct .data section like this:
> > > > > https://github.com/systemd/systemd/pull/24164
> > > > >
> > > >
> > > > There is a huge difference between variables in .rodata and .data.
> > > > .rodata variable's value is known to the BPF verifier at verification
> > > > time and this knowledge will be used to decide which code paths are
> > > > always or never taken (as one example). It's a crucial property and
> > > > important guarantee.
> > > >
> > > > If you don't care about that property, don't declare the variable as `const`.
> > > >
> > > > So no, it's not llvm putting `const` variable into .rodata
> > > > incorrectly, but GCC is trying to be smart and just because variable
> > > > is declared volatile is putting *const* variable into read-write .data
> > > > section. It's declared as const, and yes it's volatile to make sure
> > > > that compiler isn't too smart about optimizing away read operations.
> > >
> > > Isn't const volatile generating a .rodata section(like llvm is doing) a spec
> > > violation?
> > > https://github.com/llvm/llvm-project/issues/56468
> > >
> > > > But it's still a const read-only variable from the perspective of that
> > > > BPF C code.
> > > >
> > > > If you don't care about the read-only nature of that variable, drop
> > > > the const and make it into a non-read-only variable.
> > > >
> > > > And please stop proposing hacks to be added to perfectly valid systemd
> > > > BPF source code (I replied on [0] as well).
> > >
> > > From my understanding gcc is correctly putting a const volatile variable
> > > in .data while llvm is incorrectly putting it in .rodata, is the gcc behavior
> > > here invalid or is the llvm behavior invalid?
> >
> > From link you left to C standard, it does seem like that side-note
> > *implies* that const volatile should be put into .data, but it's a)
> > implied b) is quite arguable about assumptions that this data has to
> > be in modifiable section, and c) entire CO-RE feature detection and
> > guarding relies on having `const volatile` variables in .rodata and
> > mark them as read-only for BPF verifier to allow dead code
> > elimination. Changing c) would break entire CO-RE ecosystem.
>
> Well it does appear that llvm is fixing the behavior to be in line with gcc:
> https://reviews.llvm.org/D131012
>
> >
> > Seems like this issue was raised by Ulrich Drepper back in 2005 ([0])
> > and he was also confused about GCC's behavior, btw.
> >
> > So either way, at the very least for BPF target we can't change this
> > and I still think it's more logical to put const variables into
> > .rodata, regardless of side notes in C standard.
>
> GCC does put const variables in .rodata, just not const volatile variables.
>

It's still const. Volatile doesn't change constness of a variable.
We've been discussing this over and over, it gets a bit tiring, tbh.

Aaron Ballman seems to agree, quoting him from [0]:

  The footnote cited isn't a normative requirement (I can't see any
  normative requirements that say we can't put a const volatile object
  into a read only section), so it's debatable just how much of a bug
  this is from a standards conformance perspective. I will have to
  inquire on the WG14 reflectors to see if there's something I've
  missed but I believe that C17 6.7.3p5 is meant to point out that
  only lvalue are qualified; rvalues are not because lvalue conversion
  strips the qualifiers. I think the footnote is mostly a nod towards
  the fact that volatile qualified objects may change their value in
  ways unknown to the compiler so storing it in a read-only section
  of memory is a bit questionable. But I'm curious if the committee
  tells me I've missed something there.


  [0] https://github.com/llvm/llvm-project/issues/56468#issuecomment-1203146308

> >
> >
> > As for systemd's program and its is_allow_list ([1]), to unblock
> > yourself you can drop const because systemd doesn't rely on read-only
> > guarantees of that variable anyways. It's much more critical in
> > feature-detection use cases. But let's try to converge discussion in
> > one place (preferably here), it's quite inconvenient to either reply
> > the same thing twice here and on Github, or cross-reference lore and
> > Github.
>
> Hmm, are you sure:
> const __u8 is_allow_list SEC(".rodata") = 0;
>
> doesn't provide equivalent behavior to:
> const volatile __u8 is_allow_list = 0;

Is there anything preventing you from experimenting with this yourself?..

Let's see:

$ git diff
diff --git a/tools/testing/selftests/bpf/prog_tests/skeleton.c
b/tools/testing/selftests/bpf/prog_tests/skeleton.c
index 99dac5292b41..386785a45af0 100644
--- a/tools/testing/selftests/bpf/prog_tests/skeleton.c
+++ b/tools/testing/selftests/bpf/prog_tests/skeleton.c
@@ -31,6 +31,8 @@ void test_skeleton(void)
        if (CHECK(skel->kconfig, "skel_kconfig", "kconfig is mmaped()!\n"))
                goto cleanup;

+       skel->rodata->should_trap = false;
+
        bss = skel->bss;
        data = skel->data;
        data_dyn = skel->data_dyn;
diff --git a/tools/testing/selftests/bpf/progs/test_skeleton.c
b/tools/testing/selftests/bpf/progs/test_skeleton.c
index 1a4e93f6d9df..eee26bc82525 100644
--- a/tools/testing/selftests/bpf/progs/test_skeleton.c
+++ b/tools/testing/selftests/bpf/progs/test_skeleton.c
@@ -26,6 +26,8 @@ const volatile struct {
        const int in6;
 } in = {};

+const bool should_trap SEC(".rodata") = true;
+
 /* .data section */
 int out1 = -1;
 long long out2 = -1;
@@ -58,6 +60,10 @@ int handler(const void *ctx)
 {
        int i;

+       while (should_trap)
+       {
+       }
+
        out1 = in1;
        out2 = in2;
        out3 = in3;


Result: selftests stop compiling. Why?

$ llvm-objdump -d test_skeleton.linked1.o

test_skeleton.linked1.o:        file format elf64-bpf

Disassembly of section raw_tp/sys_enter:

0000000000000000 <handler>:
       0:       05 00 ff ff 00 00 00 00 goto -1 <handler>

Because compiler optimized away everything with while (true) {}. There
is no global data at all anymore.

This is what I keep telling you, const volatile is the only thing
preventing the compiler from making wrong assumptions. And neither

const bool should_trap SEC(".rodata") = true;

nor

const bool should_trap = true;

work.

But

const volatile bool should_trap = true;

does work.

If you have some more speculative proposals, please investigate them
yourself and report back with the results. But either way there is a
lot of BPF code written with reliance on `const volatile`, both open
source and not, so please stop actively trying to break BPF ecosystem
with proposals like moving `const volatile` to .data, just because
it's more convenient for you in GCC. Thank you.

>
> The used attribute in the SEC macro supposedly ensures that:
> The compiler must emit the definition even if it appears to be unused, and
> it must not apply optimizations which depend on fully understanding how
> the entity is used.
>
> Or maybe the retain attribute along with used would be sufficient to allow
> us to drop volatile in these cases?:
> https://clang.llvm.org/docs/AttributeReference.html#retain
>
> >
> >
> >   [0] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25521
> >   [1] https://github.com/systemd/systemd/pull/24164#issuecomment-1203207372
> >
> > >
> > > >
> > > >   [0] https://github.com/systemd/systemd/pull/24164#issuecomment-1201806413
> > > >
> > > >
> > > > [...]

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-08-03  0:29                                           ` Andrii Nakryiko
@ 2022-08-03  1:49                                             ` James Hilliard
  2022-08-03 16:57                                               ` Andrii Nakryiko
  0 siblings, 1 reply; 38+ messages in thread
From: James Hilliard @ 2022-08-03  1:49 UTC (permalink / raw)
  To: Andrii Nakryiko; +Cc: Jose E. Marchesi, bpf, david.faust

On Tue, Aug 2, 2022 at 6:29 PM Andrii Nakryiko
<andrii.nakryiko@gmail.com> wrote:
>
> On Tue, Aug 2, 2022 at 3:06 PM James Hilliard <james.hilliard1@gmail.com> wrote:
> >
> > On Tue, Aug 2, 2022 at 3:29 PM Andrii Nakryiko
> > <andrii.nakryiko@gmail.com> wrote:
> > >
> > > On Mon, Aug 1, 2022 at 4:35 PM James Hilliard <james.hilliard1@gmail.com> wrote:
> > > >
> > > > On Mon, Aug 1, 2022 at 4:52 PM Andrii Nakryiko
> > > > <andrii.nakryiko@gmail.com> wrote:
> > > > >
> > > > > On Sun, Jul 31, 2022 at 7:20 PM James Hilliard
> > > > > <james.hilliard1@gmail.com> wrote:
> > > > > >
> > > > > > On Sun, Jul 10, 2022 at 2:22 PM Jose E. Marchesi
> > > > > > <jose.marchesi@oracle.com> wrote:
> > > > > > >
> > > > > > >
> > > > > > > >>> On Sun, Jul 10, 2022 at 3:38 AM Jose E. Marchesi
> > > > > > > >>> <jose.marchesi@oracle.com> wrote:
> > > > > > > >>>>
> > > > > > > >>>>
> > > > > > > >>>> > On Sat, Jul 9, 2022 at 4:41 PM Jose E. Marchesi
> > > > > > > >>>> > <jose.marchesi@oracle.com> wrote:
> > > > > > > >>>> >>
> > > > > > > >>>> >>
> > > > > > > >>>> >> > On Sat, Jul 9, 2022 at 2:32 PM James Hilliard <james.hilliard1@gmail.com> wrote:
> > > > > > > >>>> >> >>
> > > > > > > >>>> >> >> On Sat, Jul 9, 2022 at 2:21 PM Jose E. Marchesi
> > > > > > > >>>> >> >> <jose.marchesi@oracle.com> wrote:
> > > > > > > >>>> >> >> >
> > > > > > > >>>> >> >> >
> > > > >
> > > > > Please trim your replies (and I don't know what your email client did,
> > > > > but it completely ruined nested quote formatting)
> > > >
> > > > Yeah, not sure what happened there.
> > > >
> > > > >
> > > > > [...]
> > > > >
> > > > > > > >>>>
> > > > > > > >>>> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> > > > > > > >>>> index e89cc9c885b3..887b78780099 100644
> > > > > > > >>>> --- a/tools/lib/bpf/libbpf.c
> > > > > > > >>>> +++ b/tools/lib/bpf/libbpf.c
> > > > > > > >>>> @@ -1591,6 +1591,10 @@ static int bpf_object__init_global_data_maps(struct bpf_object *obj)
> > > > > > > >>>>         for (sec_idx = 1; sec_idx < obj->efile.sec_cnt; sec_idx++) {
> > > > > > > >>>>                 sec_desc = &obj->efile.secs[sec_idx];
> > > > > > > >>>>
> > > > > > > >>>> +                /* Skip recognized sections with size 0.  */
> > > > > > > >>>> +                if (sec_desc->data && sec_desc->data->d_size == 0)
> > > > > > > >>>> +                  continue;
> > > > > > > >>>> +
> > > > > > > >>>>                 switch (sec_desc->sec_type) {
> > > > > > > >>>>                 case SEC_DATA:
> > > > > > > >>>>                         sec_name = elf_sec_name(obj, elf_sec_by_idx(obj, sec_idx));
> > > > > > > >>>
> > > > > > > >>> Ok, skeleton is now getting generated successfully, however it differs from the
> > > > > > > >>> clang version so there's a build error when we include/use the header:
> > > > > > > >>> ../src/core/restrict-ifaces.c: In function ‘prepare_restrict_ifaces_bpf’:
> > > > > > > >>> ../src/core/restrict-ifaces.c:45:14: error: ‘struct
> > > > > > > >>> restrict_ifaces_bpf’ has no member named ‘rodata’; did you mean
> > > > > > > >>> ‘data’?
> > > > > > > >>>    45 |         obj->rodata->is_allow_list = is_allow_list;
> > > > > > > >>>       |              ^~~~~~
> > > > > > > >>>       |              data
> > > > > > > >>>
> > > > > > > >>> The issue appears to be that clang generates "rodata" members in
> > > > > > > >>> restrict_ifaces_bpf while with gcc we get "data" members instead.
> > > > > > > >>
> > > > > > > >> This is because the BPF GCC port is putting the
> > > > > > > >>
> > > > > > > >>   const volatile unsigned char is_allow_list = 0;
> > > > > > > >>
> > > > > > > >> in a .data section instead of .rodata, due to the `volatile'.  The
> > > > > > > >> x86_64 GCC seems to use .rodata.
> > > > > > > >>
> > > > > > > >> Looking at why the PBF port does this...
> > > > > > > >
> > > > > > > > So, turns out GCC puts zero-initialized `const volatile' variables in
> > > > > > > > .data sections (and not .rodata) in all the targets I have tried, like
> > > > > > > > x86_64 and aarch64.
> > > > > > > >
> > > > > > > > So this is a LLVM and GCC divergence :/
> > > > > > >
> > > > > > > See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25521.
> > > > > > >
> > > > > > > You may try, as a workaround:
> > > > > > >
> > > > > > > __attribute__((section(".rodata"))) const volatile unsigned char is_allow_list = 0;
> > > > > > >
> > > > > > > But that will use permissions "aw" for the .rodata section (and you will
> > > > > > > get a warning from the assembler.)  It may be problematic for libbpf.
> > > > > >
> > > > > > So rather than try to force gcc to use the incorrect llvm .rodata
> > > > > > section it looks
> > > > > > like we can instead just force llvm to use the correct .data section like this:
> > > > > > https://github.com/systemd/systemd/pull/24164
> > > > > >
> > > > >
> > > > > There is a huge difference between variables in .rodata and .data.
> > > > > .rodata variable's value is known to the BPF verifier at verification
> > > > > time and this knowledge will be used to decide which code paths are
> > > > > always or never taken (as one example). It's a crucial property and
> > > > > important guarantee.
> > > > >
> > > > > If you don't care about that property, don't declare the variable as `const`.
> > > > >
> > > > > So no, it's not llvm putting `const` variable into .rodata
> > > > > incorrectly, but GCC is trying to be smart and just because variable
> > > > > is declared volatile is putting *const* variable into read-write .data
> > > > > section. It's declared as const, and yes it's volatile to make sure
> > > > > that compiler isn't too smart about optimizing away read operations.
> > > >
> > > > Isn't const volatile generating a .rodata section(like llvm is doing) a spec
> > > > violation?
> > > > https://github.com/llvm/llvm-project/issues/56468
> > > >
> > > > > But it's still a const read-only variable from the perspective of that
> > > > > BPF C code.
> > > > >
> > > > > If you don't care about the read-only nature of that variable, drop
> > > > > the const and make it into a non-read-only variable.
> > > > >
> > > > > And please stop proposing hacks to be added to perfectly valid systemd
> > > > > BPF source code (I replied on [0] as well).
> > > >
> > > > From my understanding gcc is correctly putting a const volatile variable
> > > > in .data while llvm is incorrectly putting it in .rodata, is the gcc behavior
> > > > here invalid or is the llvm behavior invalid?
> > >
> > > From link you left to C standard, it does seem like that side-note
> > > *implies* that const volatile should be put into .data, but it's a)
> > > implied b) is quite arguable about assumptions that this data has to
> > > be in modifiable section, and c) entire CO-RE feature detection and
> > > guarding relies on having `const volatile` variables in .rodata and
> > > mark them as read-only for BPF verifier to allow dead code
> > > elimination. Changing c) would break entire CO-RE ecosystem.
> >
> > Well it does appear that llvm is fixing the behavior to be in line with gcc:
> > https://reviews.llvm.org/D131012
> >
> > >
> > > Seems like this issue was raised by Ulrich Drepper back in 2005 ([0])
> > > and he was also confused about GCC's behavior, btw.
> > >
> > > So either way, at the very least for BPF target we can't change this
> > > and I still think it's more logical to put const variables into
> > > .rodata, regardless of side notes in C standard.
> >
> > GCC does put const variables in .rodata, just not const volatile variables.
> >
>
> It's still const. Volatile doesn't change constness of a variable.
> We've been discussing this over and over, it gets a bit tiring, tbh.
>
> Aaron Ballman seems to agree, quoting him from [0]:
>
>   The footnote cited isn't a normative requirement (I can't see any
>   normative requirements that say we can't put a const volatile object
>   into a read only section), so it's debatable just how much of a bug
>   this is from a standards conformance perspective. I will have to
>   inquire on the WG14 reflectors to see if there's something I've
>   missed but I believe that C17 6.7.3p5 is meant to point out that
>   only lvalue are qualified; rvalues are not because lvalue conversion
>   strips the qualifiers. I think the footnote is mostly a nod towards
>   the fact that volatile qualified objects may change their value in
>   ways unknown to the compiler so storing it in a read-only section
>   of memory is a bit questionable. But I'm curious if the committee
>   tells me I've missed something there.
>
>
>   [0] https://github.com/llvm/llvm-project/issues/56468#issuecomment-1203146308
>
> > >
> > >
> > > As for systemd's program and its is_allow_list ([1]), to unblock
> > > yourself you can drop const because systemd doesn't rely on read-only
> > > guarantees of that variable anyways. It's much more critical in
> > > feature-detection use cases. But let's try to converge discussion in
> > > one place (preferably here), it's quite inconvenient to either reply
> > > the same thing twice here and on Github, or cross-reference lore and
> > > Github.
> >
> > Hmm, are you sure:
> > const __u8 is_allow_list SEC(".rodata") = 0;
> >
> > doesn't provide equivalent behavior to:
> > const volatile __u8 is_allow_list = 0;
>
> Is there anything preventing you from experimenting with this yourself?..

Wasn't sure how to reproduce the issue properly.

>
> Let's see:
>
> $ git diff
> diff --git a/tools/testing/selftests/bpf/prog_tests/skeleton.c
> b/tools/testing/selftests/bpf/prog_tests/skeleton.c
> index 99dac5292b41..386785a45af0 100644
> --- a/tools/testing/selftests/bpf/prog_tests/skeleton.c
> +++ b/tools/testing/selftests/bpf/prog_tests/skeleton.c
> @@ -31,6 +31,8 @@ void test_skeleton(void)
>         if (CHECK(skel->kconfig, "skel_kconfig", "kconfig is mmaped()!\n"))
>                 goto cleanup;
>
> +       skel->rodata->should_trap = false;
> +
>         bss = skel->bss;
>         data = skel->data;
>         data_dyn = skel->data_dyn;
> diff --git a/tools/testing/selftests/bpf/progs/test_skeleton.c
> b/tools/testing/selftests/bpf/progs/test_skeleton.c
> index 1a4e93f6d9df..eee26bc82525 100644
> --- a/tools/testing/selftests/bpf/progs/test_skeleton.c
> +++ b/tools/testing/selftests/bpf/progs/test_skeleton.c
> @@ -26,6 +26,8 @@ const volatile struct {
>         const int in6;
>  } in = {};
>
> +const bool should_trap SEC(".rodata") = true;
> +
>  /* .data section */
>  int out1 = -1;
>  long long out2 = -1;
> @@ -58,6 +60,10 @@ int handler(const void *ctx)
>  {
>         int i;
>
> +       while (should_trap)
> +       {
> +       }
> +
>         out1 = in1;
>         out2 = in2;
>         out3 = in3;
>
>
> Result: selftests stop compiling. Why?
>
> $ llvm-objdump -d test_skeleton.linked1.o
>
> test_skeleton.linked1.o:        file format elf64-bpf
>
> Disassembly of section raw_tp/sys_enter:
>
> 0000000000000000 <handler>:
>        0:       05 00 ff ff 00 00 00 00 goto -1 <handler>
>
> Because compiler optimized away everything with while (true) {}. There
> is no global data at all anymore.
>
> This is what I keep telling you, const volatile is the only thing
> preventing the compiler from making wrong assumptions. And neither
>
> const bool should_trap SEC(".rodata") = true;
>
> nor
>
> const bool should_trap = true;
>
> work.
>
> But
>
> const volatile bool should_trap = true;
>
> does work.
>
> If you have some more speculative proposals, please investigate them
> yourself and report back with the results. But either way there is a
> lot of BPF code written with reliance on `const volatile`, both open
> source and not, so please stop actively trying to break BPF ecosystem
> with proposals like moving `const volatile` to .data, just because
> it's more convenient for you in GCC. Thank you.

So it does at least seem I can force GCC to use .rodata like this for
systemd, maybe that's the best approach for now?:

const volatile __u8 is_allow_list SEC(".rodata") = 0;

It does emit an assembler warning but otherwise appears to work:
Generating src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
with a custom command
/tmp/ccM2b7jP.s: Assembler messages:
/tmp/ccM2b7jP.s:87: Warning: setting incorrect section attributes for .rodata

I updated my systemd PR with that.

>
> >
> > The used attribute in the SEC macro supposedly ensures that:
> > The compiler must emit the definition even if it appears to be unused, and
> > it must not apply optimizations which depend on fully understanding how
> > the entity is used.
> >
> > Or maybe the retain attribute along with used would be sufficient to allow
> > us to drop volatile in these cases?:
> > https://clang.llvm.org/docs/AttributeReference.html#retain
> >
> > >
> > >
> > >   [0] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25521
> > >   [1] https://github.com/systemd/systemd/pull/24164#issuecomment-1203207372
> > >
> > > >
> > > > >
> > > > >   [0] https://github.com/systemd/systemd/pull/24164#issuecomment-1201806413
> > > > >
> > > > >
> > > > > [...]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-08-03  1:49                                             ` James Hilliard
@ 2022-08-03 16:57                                               ` Andrii Nakryiko
  2022-08-03 19:24                                                 ` James Hilliard
  2022-08-04 17:29                                                 ` Alexei Starovoitov
  0 siblings, 2 replies; 38+ messages in thread
From: Andrii Nakryiko @ 2022-08-03 16:57 UTC (permalink / raw)
  To: James Hilliard; +Cc: Jose E. Marchesi, bpf, david.faust

On Tue, Aug 2, 2022 at 6:49 PM James Hilliard <james.hilliard1@gmail.com> wrote:
>
> On Tue, Aug 2, 2022 at 6:29 PM Andrii Nakryiko
> <andrii.nakryiko@gmail.com> wrote:
> >
> > On Tue, Aug 2, 2022 at 3:06 PM James Hilliard <james.hilliard1@gmail.com> wrote:
> > >
> > > On Tue, Aug 2, 2022 at 3:29 PM Andrii Nakryiko
> > > <andrii.nakryiko@gmail.com> wrote:
> > > >
> > > > On Mon, Aug 1, 2022 at 4:35 PM James Hilliard <james.hilliard1@gmail.com> wrote:
> > > > >
> > > > > On Mon, Aug 1, 2022 at 4:52 PM Andrii Nakryiko
> > > > > <andrii.nakryiko@gmail.com> wrote:
> > > > > >
> > > > > > On Sun, Jul 31, 2022 at 7:20 PM James Hilliard
> > > > > > <james.hilliard1@gmail.com> wrote:
> > > > > > >
> > > > > > > On Sun, Jul 10, 2022 at 2:22 PM Jose E. Marchesi
> > > > > > > <jose.marchesi@oracle.com> wrote:
> > > > > > > >
> > > > > > > >
> > > > > > > > >>> On Sun, Jul 10, 2022 at 3:38 AM Jose E. Marchesi
> > > > > > > > >>> <jose.marchesi@oracle.com> wrote:
> > > > > > > > >>>>
> > > > > > > > >>>>
> > > > > > > > >>>> > On Sat, Jul 9, 2022 at 4:41 PM Jose E. Marchesi
> > > > > > > > >>>> > <jose.marchesi@oracle.com> wrote:
> > > > > > > > >>>> >>
> > > > > > > > >>>> >>
> > > > > > > > >>>> >> > On Sat, Jul 9, 2022 at 2:32 PM James Hilliard <james.hilliard1@gmail.com> wrote:
> > > > > > > > >>>> >> >>
> > > > > > > > >>>> >> >> On Sat, Jul 9, 2022 at 2:21 PM Jose E. Marchesi
> > > > > > > > >>>> >> >> <jose.marchesi@oracle.com> wrote:
> > > > > > > > >>>> >> >> >
> > > > > > > > >>>> >> >> >
> > > > > >
> > > > > > Please trim your replies (and I don't know what your email client did,
> > > > > > but it completely ruined nested quote formatting)
> > > > >
> > > > > Yeah, not sure what happened there.
> > > > >
> > > > > >
> > > > > > [...]
> > > > > >
> > > > > > > > >>>>
> > > > > > > > >>>> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> > > > > > > > >>>> index e89cc9c885b3..887b78780099 100644
> > > > > > > > >>>> --- a/tools/lib/bpf/libbpf.c
> > > > > > > > >>>> +++ b/tools/lib/bpf/libbpf.c
> > > > > > > > >>>> @@ -1591,6 +1591,10 @@ static int bpf_object__init_global_data_maps(struct bpf_object *obj)
> > > > > > > > >>>>         for (sec_idx = 1; sec_idx < obj->efile.sec_cnt; sec_idx++) {
> > > > > > > > >>>>                 sec_desc = &obj->efile.secs[sec_idx];
> > > > > > > > >>>>
> > > > > > > > >>>> +                /* Skip recognized sections with size 0.  */
> > > > > > > > >>>> +                if (sec_desc->data && sec_desc->data->d_size == 0)
> > > > > > > > >>>> +                  continue;
> > > > > > > > >>>> +
> > > > > > > > >>>>                 switch (sec_desc->sec_type) {
> > > > > > > > >>>>                 case SEC_DATA:
> > > > > > > > >>>>                         sec_name = elf_sec_name(obj, elf_sec_by_idx(obj, sec_idx));
> > > > > > > > >>>
> > > > > > > > >>> Ok, skeleton is now getting generated successfully, however it differs from the
> > > > > > > > >>> clang version so there's a build error when we include/use the header:
> > > > > > > > >>> ../src/core/restrict-ifaces.c: In function ‘prepare_restrict_ifaces_bpf’:
> > > > > > > > >>> ../src/core/restrict-ifaces.c:45:14: error: ‘struct
> > > > > > > > >>> restrict_ifaces_bpf’ has no member named ‘rodata’; did you mean
> > > > > > > > >>> ‘data’?
> > > > > > > > >>>    45 |         obj->rodata->is_allow_list = is_allow_list;
> > > > > > > > >>>       |              ^~~~~~
> > > > > > > > >>>       |              data
> > > > > > > > >>>
> > > > > > > > >>> The issue appears to be that clang generates "rodata" members in
> > > > > > > > >>> restrict_ifaces_bpf while with gcc we get "data" members instead.
> > > > > > > > >>
> > > > > > > > >> This is because the BPF GCC port is putting the
> > > > > > > > >>
> > > > > > > > >>   const volatile unsigned char is_allow_list = 0;
> > > > > > > > >>
> > > > > > > > >> in a .data section instead of .rodata, due to the `volatile'.  The
> > > > > > > > >> x86_64 GCC seems to use .rodata.
> > > > > > > > >>
> > > > > > > > >> Looking at why the PBF port does this...
> > > > > > > > >
> > > > > > > > > So, turns out GCC puts zero-initialized `const volatile' variables in
> > > > > > > > > .data sections (and not .rodata) in all the targets I have tried, like
> > > > > > > > > x86_64 and aarch64.
> > > > > > > > >
> > > > > > > > > So this is a LLVM and GCC divergence :/
> > > > > > > >
> > > > > > > > See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25521.
> > > > > > > >
> > > > > > > > You may try, as a workaround:
> > > > > > > >
> > > > > > > > __attribute__((section(".rodata"))) const volatile unsigned char is_allow_list = 0;
> > > > > > > >
> > > > > > > > But that will use permissions "aw" for the .rodata section (and you will
> > > > > > > > get a warning from the assembler.)  It may be problematic for libbpf.
> > > > > > >
> > > > > > > So rather than try to force gcc to use the incorrect llvm .rodata
> > > > > > > section it looks
> > > > > > > like we can instead just force llvm to use the correct .data section like this:
> > > > > > > https://github.com/systemd/systemd/pull/24164
> > > > > > >
> > > > > >
> > > > > > There is a huge difference between variables in .rodata and .data.
> > > > > > .rodata variable's value is known to the BPF verifier at verification
> > > > > > time and this knowledge will be used to decide which code paths are
> > > > > > always or never taken (as one example). It's a crucial property and
> > > > > > important guarantee.
> > > > > >
> > > > > > If you don't care about that property, don't declare the variable as `const`.
> > > > > >
> > > > > > So no, it's not llvm putting `const` variable into .rodata
> > > > > > incorrectly, but GCC is trying to be smart and just because variable
> > > > > > is declared volatile is putting *const* variable into read-write .data
> > > > > > section. It's declared as const, and yes it's volatile to make sure
> > > > > > that compiler isn't too smart about optimizing away read operations.
> > > > >
> > > > > Isn't const volatile generating a .rodata section(like llvm is doing) a spec
> > > > > violation?
> > > > > https://github.com/llvm/llvm-project/issues/56468
> > > > >
> > > > > > But it's still a const read-only variable from the perspective of that
> > > > > > BPF C code.
> > > > > >
> > > > > > If you don't care about the read-only nature of that variable, drop
> > > > > > the const and make it into a non-read-only variable.
> > > > > >
> > > > > > And please stop proposing hacks to be added to perfectly valid systemd
> > > > > > BPF source code (I replied on [0] as well).
> > > > >
> > > > > From my understanding gcc is correctly putting a const volatile variable
> > > > > in .data while llvm is incorrectly putting it in .rodata, is the gcc behavior
> > > > > here invalid or is the llvm behavior invalid?
> > > >
> > > > From link you left to C standard, it does seem like that side-note
> > > > *implies* that const volatile should be put into .data, but it's a)
> > > > implied b) is quite arguable about assumptions that this data has to
> > > > be in modifiable section, and c) entire CO-RE feature detection and
> > > > guarding relies on having `const volatile` variables in .rodata and
> > > > mark them as read-only for BPF verifier to allow dead code
> > > > elimination. Changing c) would break entire CO-RE ecosystem.
> > >
> > > Well it does appear that llvm is fixing the behavior to be in line with gcc:
> > > https://reviews.llvm.org/D131012
> > >
> > > >
> > > > Seems like this issue was raised by Ulrich Drepper back in 2005 ([0])
> > > > and he was also confused about GCC's behavior, btw.
> > > >
> > > > So either way, at the very least for BPF target we can't change this
> > > > and I still think it's more logical to put const variables into
> > > > .rodata, regardless of side notes in C standard.
> > >
> > > GCC does put const variables in .rodata, just not const volatile variables.
> > >
> >
> > It's still const. Volatile doesn't change constness of a variable.
> > We've been discussing this over and over, it gets a bit tiring, tbh.
> >
> > Aaron Ballman seems to agree, quoting him from [0]:
> >
> >   The footnote cited isn't a normative requirement (I can't see any
> >   normative requirements that say we can't put a const volatile object
> >   into a read only section), so it's debatable just how much of a bug
> >   this is from a standards conformance perspective. I will have to
> >   inquire on the WG14 reflectors to see if there's something I've
> >   missed but I believe that C17 6.7.3p5 is meant to point out that
> >   only lvalue are qualified; rvalues are not because lvalue conversion
> >   strips the qualifiers. I think the footnote is mostly a nod towards
> >   the fact that volatile qualified objects may change their value in
> >   ways unknown to the compiler so storing it in a read-only section
> >   of memory is a bit questionable. But I'm curious if the committee
> >   tells me I've missed something there.
> >
> >
> >   [0] https://github.com/llvm/llvm-project/issues/56468#issuecomment-1203146308
> >
> > > >
> > > >
> > > > As for systemd's program and its is_allow_list ([1]), to unblock
> > > > yourself you can drop const because systemd doesn't rely on read-only
> > > > guarantees of that variable anyways. It's much more critical in
> > > > feature-detection use cases. But let's try to converge discussion in
> > > > one place (preferably here), it's quite inconvenient to either reply
> > > > the same thing twice here and on Github, or cross-reference lore and
> > > > Github.
> > >
> > > Hmm, are you sure:
> > > const __u8 is_allow_list SEC(".rodata") = 0;
> > >
> > > doesn't provide equivalent behavior to:
> > > const volatile __u8 is_allow_list = 0;
> >
> > Is there anything preventing you from experimenting with this yourself?..
>
> Wasn't sure how to reproduce the issue properly.
>

Then please start asking specific questions about how to repro issues
we are talking about, instead of randomly throwing various ideas
around and seeing what sticks.

> >
> > Let's see:
> >
> > $ git diff
> > diff --git a/tools/testing/selftests/bpf/prog_tests/skeleton.c
> > b/tools/testing/selftests/bpf/prog_tests/skeleton.c
> > index 99dac5292b41..386785a45af0 100644
> > --- a/tools/testing/selftests/bpf/prog_tests/skeleton.c
> > +++ b/tools/testing/selftests/bpf/prog_tests/skeleton.c
> > @@ -31,6 +31,8 @@ void test_skeleton(void)
> >         if (CHECK(skel->kconfig, "skel_kconfig", "kconfig is mmaped()!\n"))
> >                 goto cleanup;
> >
> > +       skel->rodata->should_trap = false;
> > +
> >         bss = skel->bss;
> >         data = skel->data;
> >         data_dyn = skel->data_dyn;
> > diff --git a/tools/testing/selftests/bpf/progs/test_skeleton.c
> > b/tools/testing/selftests/bpf/progs/test_skeleton.c
> > index 1a4e93f6d9df..eee26bc82525 100644
> > --- a/tools/testing/selftests/bpf/progs/test_skeleton.c
> > +++ b/tools/testing/selftests/bpf/progs/test_skeleton.c
> > @@ -26,6 +26,8 @@ const volatile struct {
> >         const int in6;
> >  } in = {};
> >
> > +const bool should_trap SEC(".rodata") = true;
> > +
> >  /* .data section */
> >  int out1 = -1;
> >  long long out2 = -1;
> > @@ -58,6 +60,10 @@ int handler(const void *ctx)
> >  {
> >         int i;
> >
> > +       while (should_trap)
> > +       {
> > +       }
> > +
> >         out1 = in1;
> >         out2 = in2;
> >         out3 = in3;
> >
> >
> > Result: selftests stop compiling. Why?
> >
> > $ llvm-objdump -d test_skeleton.linked1.o
> >
> > test_skeleton.linked1.o:        file format elf64-bpf
> >
> > Disassembly of section raw_tp/sys_enter:
> >
> > 0000000000000000 <handler>:
> >        0:       05 00 ff ff 00 00 00 00 goto -1 <handler>
> >
> > Because compiler optimized away everything with while (true) {}. There
> > is no global data at all anymore.
> >
> > This is what I keep telling you, const volatile is the only thing
> > preventing the compiler from making wrong assumptions. And neither
> >
> > const bool should_trap SEC(".rodata") = true;
> >
> > nor
> >
> > const bool should_trap = true;
> >
> > work.
> >
> > But
> >
> > const volatile bool should_trap = true;
> >
> > does work.
> >
> > If you have some more speculative proposals, please investigate them
> > yourself and report back with the results. But either way there is a
> > lot of BPF code written with reliance on `const volatile`, both open
> > source and not, so please stop actively trying to break BPF ecosystem
> > with proposals like moving `const volatile` to .data, just because
> > it's more convenient for you in GCC. Thank you.
>
> So it does at least seem I can force GCC to use .rodata like this for
> systemd, maybe that's the best approach for now?:
>
> const volatile __u8 is_allow_list SEC(".rodata") = 0;
>
> It does emit an assembler warning but otherwise appears to work:
> Generating src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
> with a custom command
> /tmp/ccM2b7jP.s: Assembler messages:
> /tmp/ccM2b7jP.s:87: Warning: setting incorrect section attributes for .rodata
>
> I updated my systemd PR with that.
>

For Nth time, don't do this. Drop the const for systemd. And please
start paying attention to feedback.

Please also start with learning how to build selftests/bpf with Clang
and looking at various examples so that you can at least look at all
the different features we rely on in the BPF world, instead of trying
to tune one small piece (systemd's BPF programs) to your liking. If
you are serious about making GCC BPF backend viable, you'll have to
understand BPF a bit better.

That would be a better use of everyone's time, instead of you going
behind our backs and requesting Clang to break the entire BPF
ecosystem just because GCC is doing something differently, like you
and Jose E. Marchesi did with [0] and [1].

  [0] https://github.com/llvm/llvm-project/issues/56468
  [1] https://reviews.llvm.org/D131012

> >
> > >
> > > The used attribute in the SEC macro supposedly ensures that:
> > > The compiler must emit the definition even if it appears to be unused, and
> > > it must not apply optimizations which depend on fully understanding how
> > > the entity is used.
> > >
> > > Or maybe the retain attribute along with used would be sufficient to allow
> > > us to drop volatile in these cases?:
> > > https://clang.llvm.org/docs/AttributeReference.html#retain
> > >
> > > >
> > > >
> > > >   [0] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25521
> > > >   [1] https://github.com/systemd/systemd/pull/24164#issuecomment-1203207372
> > > >
> > > > >
> > > > > >
> > > > > >   [0] https://github.com/systemd/systemd/pull/24164#issuecomment-1201806413
> > > > > >
> > > > > >
> > > > > > [...]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-08-03 16:57                                               ` Andrii Nakryiko
@ 2022-08-03 19:24                                                 ` James Hilliard
  2022-09-30 21:52                                                   ` James Hilliard
  2022-08-04 17:29                                                 ` Alexei Starovoitov
  1 sibling, 1 reply; 38+ messages in thread
From: James Hilliard @ 2022-08-03 19:24 UTC (permalink / raw)
  To: Andrii Nakryiko; +Cc: Jose E. Marchesi, bpf, david.faust

On Wed, Aug 3, 2022 at 10:57 AM Andrii Nakryiko
<andrii.nakryiko@gmail.com> wrote:
>
> On Tue, Aug 2, 2022 at 6:49 PM James Hilliard <james.hilliard1@gmail.com> wrote:
> >
> > On Tue, Aug 2, 2022 at 6:29 PM Andrii Nakryiko
> > <andrii.nakryiko@gmail.com> wrote:
> > >
> > > On Tue, Aug 2, 2022 at 3:06 PM James Hilliard <james.hilliard1@gmail.com> wrote:
> > > >
> > > > On Tue, Aug 2, 2022 at 3:29 PM Andrii Nakryiko
> > > > <andrii.nakryiko@gmail.com> wrote:
> > > > >
> > > > > On Mon, Aug 1, 2022 at 4:35 PM James Hilliard <james.hilliard1@gmail.com> wrote:
> > > > > >
> > > > > > On Mon, Aug 1, 2022 at 4:52 PM Andrii Nakryiko
> > > > > > <andrii.nakryiko@gmail.com> wrote:
> > > > > > >
> > > > > > > On Sun, Jul 31, 2022 at 7:20 PM James Hilliard
> > > > > > > <james.hilliard1@gmail.com> wrote:
> > > > > > > >
> > > > > > > > On Sun, Jul 10, 2022 at 2:22 PM Jose E. Marchesi
> > > > > > > > <jose.marchesi@oracle.com> wrote:
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > >>> On Sun, Jul 10, 2022 at 3:38 AM Jose E. Marchesi
> > > > > > > > > >>> <jose.marchesi@oracle.com> wrote:
> > > > > > > > > >>>>
> > > > > > > > > >>>>
> > > > > > > > > >>>> > On Sat, Jul 9, 2022 at 4:41 PM Jose E. Marchesi
> > > > > > > > > >>>> > <jose.marchesi@oracle.com> wrote:
> > > > > > > > > >>>> >>
> > > > > > > > > >>>> >>
> > > > > > > > > >>>> >> > On Sat, Jul 9, 2022 at 2:32 PM James Hilliard <james.hilliard1@gmail.com> wrote:
> > > > > > > > > >>>> >> >>
> > > > > > > > > >>>> >> >> On Sat, Jul 9, 2022 at 2:21 PM Jose E. Marchesi
> > > > > > > > > >>>> >> >> <jose.marchesi@oracle.com> wrote:
> > > > > > > > > >>>> >> >> >
> > > > > > > > > >>>> >> >> >
> > > > > > >
> > > > > > > Please trim your replies (and I don't know what your email client did,
> > > > > > > but it completely ruined nested quote formatting)
> > > > > >
> > > > > > Yeah, not sure what happened there.
> > > > > >
> > > > > > >
> > > > > > > [...]
> > > > > > >
> > > > > > > > > >>>>
> > > > > > > > > >>>> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> > > > > > > > > >>>> index e89cc9c885b3..887b78780099 100644
> > > > > > > > > >>>> --- a/tools/lib/bpf/libbpf.c
> > > > > > > > > >>>> +++ b/tools/lib/bpf/libbpf.c
> > > > > > > > > >>>> @@ -1591,6 +1591,10 @@ static int bpf_object__init_global_data_maps(struct bpf_object *obj)
> > > > > > > > > >>>>         for (sec_idx = 1; sec_idx < obj->efile.sec_cnt; sec_idx++) {
> > > > > > > > > >>>>                 sec_desc = &obj->efile.secs[sec_idx];
> > > > > > > > > >>>>
> > > > > > > > > >>>> +                /* Skip recognized sections with size 0.  */
> > > > > > > > > >>>> +                if (sec_desc->data && sec_desc->data->d_size == 0)
> > > > > > > > > >>>> +                  continue;
> > > > > > > > > >>>> +
> > > > > > > > > >>>>                 switch (sec_desc->sec_type) {
> > > > > > > > > >>>>                 case SEC_DATA:
> > > > > > > > > >>>>                         sec_name = elf_sec_name(obj, elf_sec_by_idx(obj, sec_idx));
> > > > > > > > > >>>
> > > > > > > > > >>> Ok, skeleton is now getting generated successfully, however it differs from the
> > > > > > > > > >>> clang version so there's a build error when we include/use the header:
> > > > > > > > > >>> ../src/core/restrict-ifaces.c: In function ‘prepare_restrict_ifaces_bpf’:
> > > > > > > > > >>> ../src/core/restrict-ifaces.c:45:14: error: ‘struct
> > > > > > > > > >>> restrict_ifaces_bpf’ has no member named ‘rodata’; did you mean
> > > > > > > > > >>> ‘data’?
> > > > > > > > > >>>    45 |         obj->rodata->is_allow_list = is_allow_list;
> > > > > > > > > >>>       |              ^~~~~~
> > > > > > > > > >>>       |              data
> > > > > > > > > >>>
> > > > > > > > > >>> The issue appears to be that clang generates "rodata" members in
> > > > > > > > > >>> restrict_ifaces_bpf while with gcc we get "data" members instead.
> > > > > > > > > >>
> > > > > > > > > >> This is because the BPF GCC port is putting the
> > > > > > > > > >>
> > > > > > > > > >>   const volatile unsigned char is_allow_list = 0;
> > > > > > > > > >>
> > > > > > > > > >> in a .data section instead of .rodata, due to the `volatile'.  The
> > > > > > > > > >> x86_64 GCC seems to use .rodata.
> > > > > > > > > >>
> > > > > > > > > >> Looking at why the PBF port does this...
> > > > > > > > > >
> > > > > > > > > > So, turns out GCC puts zero-initialized `const volatile' variables in
> > > > > > > > > > .data sections (and not .rodata) in all the targets I have tried, like
> > > > > > > > > > x86_64 and aarch64.
> > > > > > > > > >
> > > > > > > > > > So this is a LLVM and GCC divergence :/
> > > > > > > > >
> > > > > > > > > See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25521.
> > > > > > > > >
> > > > > > > > > You may try, as a workaround:
> > > > > > > > >
> > > > > > > > > __attribute__((section(".rodata"))) const volatile unsigned char is_allow_list = 0;
> > > > > > > > >
> > > > > > > > > But that will use permissions "aw" for the .rodata section (and you will
> > > > > > > > > get a warning from the assembler.)  It may be problematic for libbpf.
> > > > > > > >
> > > > > > > > So rather than try to force gcc to use the incorrect llvm .rodata
> > > > > > > > section it looks
> > > > > > > > like we can instead just force llvm to use the correct .data section like this:
> > > > > > > > https://github.com/systemd/systemd/pull/24164
> > > > > > > >
> > > > > > >
> > > > > > > There is a huge difference between variables in .rodata and .data.
> > > > > > > .rodata variable's value is known to the BPF verifier at verification
> > > > > > > time and this knowledge will be used to decide which code paths are
> > > > > > > always or never taken (as one example). It's a crucial property and
> > > > > > > important guarantee.
> > > > > > >
> > > > > > > If you don't care about that property, don't declare the variable as `const`.
> > > > > > >
> > > > > > > So no, it's not llvm putting `const` variable into .rodata
> > > > > > > incorrectly, but GCC is trying to be smart and just because variable
> > > > > > > is declared volatile is putting *const* variable into read-write .data
> > > > > > > section. It's declared as const, and yes it's volatile to make sure
> > > > > > > that compiler isn't too smart about optimizing away read operations.
> > > > > >
> > > > > > Isn't const volatile generating a .rodata section(like llvm is doing) a spec
> > > > > > violation?
> > > > > > https://github.com/llvm/llvm-project/issues/56468
> > > > > >
> > > > > > > But it's still a const read-only variable from the perspective of that
> > > > > > > BPF C code.
> > > > > > >
> > > > > > > If you don't care about the read-only nature of that variable, drop
> > > > > > > the const and make it into a non-read-only variable.
> > > > > > >
> > > > > > > And please stop proposing hacks to be added to perfectly valid systemd
> > > > > > > BPF source code (I replied on [0] as well).
> > > > > >
> > > > > > From my understanding gcc is correctly putting a const volatile variable
> > > > > > in .data while llvm is incorrectly putting it in .rodata, is the gcc behavior
> > > > > > here invalid or is the llvm behavior invalid?
> > > > >
> > > > > From link you left to C standard, it does seem like that side-note
> > > > > *implies* that const volatile should be put into .data, but it's a)
> > > > > implied b) is quite arguable about assumptions that this data has to
> > > > > be in modifiable section, and c) entire CO-RE feature detection and
> > > > > guarding relies on having `const volatile` variables in .rodata and
> > > > > mark them as read-only for BPF verifier to allow dead code
> > > > > elimination. Changing c) would break entire CO-RE ecosystem.
> > > >
> > > > Well it does appear that llvm is fixing the behavior to be in line with gcc:
> > > > https://reviews.llvm.org/D131012
> > > >
> > > > >
> > > > > Seems like this issue was raised by Ulrich Drepper back in 2005 ([0])
> > > > > and he was also confused about GCC's behavior, btw.
> > > > >
> > > > > So either way, at the very least for BPF target we can't change this
> > > > > and I still think it's more logical to put const variables into
> > > > > .rodata, regardless of side notes in C standard.
> > > >
> > > > GCC does put const variables in .rodata, just not const volatile variables.
> > > >
> > >
> > > It's still const. Volatile doesn't change constness of a variable.
> > > We've been discussing this over and over, it gets a bit tiring, tbh.
> > >
> > > Aaron Ballman seems to agree, quoting him from [0]:
> > >
> > >   The footnote cited isn't a normative requirement (I can't see any
> > >   normative requirements that say we can't put a const volatile object
> > >   into a read only section), so it's debatable just how much of a bug
> > >   this is from a standards conformance perspective. I will have to
> > >   inquire on the WG14 reflectors to see if there's something I've
> > >   missed but I believe that C17 6.7.3p5 is meant to point out that
> > >   only lvalue are qualified; rvalues are not because lvalue conversion
> > >   strips the qualifiers. I think the footnote is mostly a nod towards
> > >   the fact that volatile qualified objects may change their value in
> > >   ways unknown to the compiler so storing it in a read-only section
> > >   of memory is a bit questionable. But I'm curious if the committee
> > >   tells me I've missed something there.
> > >
> > >
> > >   [0] https://github.com/llvm/llvm-project/issues/56468#issuecomment-1203146308
> > >
> > > > >
> > > > >
> > > > > As for systemd's program and its is_allow_list ([1]), to unblock
> > > > > yourself you can drop const because systemd doesn't rely on read-only
> > > > > guarantees of that variable anyways. It's much more critical in
> > > > > feature-detection use cases. But let's try to converge discussion in
> > > > > one place (preferably here), it's quite inconvenient to either reply
> > > > > the same thing twice here and on Github, or cross-reference lore and
> > > > > Github.
> > > >
> > > > Hmm, are you sure:
> > > > const __u8 is_allow_list SEC(".rodata") = 0;
> > > >
> > > > doesn't provide equivalent behavior to:
> > > > const volatile __u8 is_allow_list = 0;
> > >
> > > Is there anything preventing you from experimenting with this yourself?..
> >
> > Wasn't sure how to reproduce the issue properly.
> >
>
> Then please start asking specific questions about how to repro issues
> we are talking about, instead of randomly throwing various ideas
> around and seeing what sticks.

I tested with the reproducer to see if any attribute based workarounds
might avoid the need for volatile, and I didn't find anything.

>
> > >
> > > Let's see:
> > >
> > > $ git diff
> > > diff --git a/tools/testing/selftests/bpf/prog_tests/skeleton.c
> > > b/tools/testing/selftests/bpf/prog_tests/skeleton.c
> > > index 99dac5292b41..386785a45af0 100644
> > > --- a/tools/testing/selftests/bpf/prog_tests/skeleton.c
> > > +++ b/tools/testing/selftests/bpf/prog_tests/skeleton.c
> > > @@ -31,6 +31,8 @@ void test_skeleton(void)
> > >         if (CHECK(skel->kconfig, "skel_kconfig", "kconfig is mmaped()!\n"))
> > >                 goto cleanup;
> > >
> > > +       skel->rodata->should_trap = false;
> > > +
> > >         bss = skel->bss;
> > >         data = skel->data;
> > >         data_dyn = skel->data_dyn;
> > > diff --git a/tools/testing/selftests/bpf/progs/test_skeleton.c
> > > b/tools/testing/selftests/bpf/progs/test_skeleton.c
> > > index 1a4e93f6d9df..eee26bc82525 100644
> > > --- a/tools/testing/selftests/bpf/progs/test_skeleton.c
> > > +++ b/tools/testing/selftests/bpf/progs/test_skeleton.c
> > > @@ -26,6 +26,8 @@ const volatile struct {
> > >         const int in6;
> > >  } in = {};
> > >
> > > +const bool should_trap SEC(".rodata") = true;
> > > +
> > >  /* .data section */
> > >  int out1 = -1;
> > >  long long out2 = -1;
> > > @@ -58,6 +60,10 @@ int handler(const void *ctx)
> > >  {
> > >         int i;
> > >
> > > +       while (should_trap)
> > > +       {
> > > +       }
> > > +
> > >         out1 = in1;
> > >         out2 = in2;
> > >         out3 = in3;
> > >
> > >
> > > Result: selftests stop compiling. Why?
> > >
> > > $ llvm-objdump -d test_skeleton.linked1.o
> > >
> > > test_skeleton.linked1.o:        file format elf64-bpf
> > >
> > > Disassembly of section raw_tp/sys_enter:
> > >
> > > 0000000000000000 <handler>:
> > >        0:       05 00 ff ff 00 00 00 00 goto -1 <handler>
> > >
> > > Because compiler optimized away everything with while (true) {}. There
> > > is no global data at all anymore.
> > >
> > > This is what I keep telling you, const volatile is the only thing
> > > preventing the compiler from making wrong assumptions. And neither
> > >
> > > const bool should_trap SEC(".rodata") = true;
> > >
> > > nor
> > >
> > > const bool should_trap = true;
> > >
> > > work.
> > >
> > > But
> > >
> > > const volatile bool should_trap = true;
> > >
> > > does work.
> > >
> > > If you have some more speculative proposals, please investigate them
> > > yourself and report back with the results. But either way there is a
> > > lot of BPF code written with reliance on `const volatile`, both open
> > > source and not, so please stop actively trying to break BPF ecosystem
> > > with proposals like moving `const volatile` to .data, just because
> > > it's more convenient for you in GCC. Thank you.
> >
> > So it does at least seem I can force GCC to use .rodata like this for
> > systemd, maybe that's the best approach for now?:
> >
> > const volatile __u8 is_allow_list SEC(".rodata") = 0;
> >
> > It does emit an assembler warning but otherwise appears to work:
> > Generating src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
> > with a custom command
> > /tmp/ccM2b7jP.s: Assembler messages:
> > /tmp/ccM2b7jP.s:87: Warning: setting incorrect section attributes for .rodata
> >
> > I updated my systemd PR with that.
> >
>
> For Nth time, don't do this. Drop the const for systemd. And please
> start paying attention to feedback.

Well I was looking for a more general solution for behavior convergence,
I posted here to see if that was a workable option to get both compilers
to behave the same for cases where we want the variable to be in
.rodata. I had also updated the pull request to make it easier to get
feedback on that approach.

I guess a developer at your company approved the PR already and
it got merged.

>
> Please also start with learning how to build selftests/bpf with Clang
> and looking at various examples so that you can at least look at all
> the different features we rely on in the BPF world, instead of trying
> to tune one small piece (systemd's BPF programs) to your liking. If
> you are serious about making GCC BPF backend viable, you'll have to
> understand BPF a bit better.

I did do that for both clang and gcc, I've been fixing issues I discovered
like this one for example when trying to build tests with gcc:
https://lore.kernel.org/bpf/20220803151403.793024-1-james.hilliard1@gmail.com/

>
> That would be a better use of everyone's time, instead of you going
> behind our backs and requesting Clang to break the entire BPF
> ecosystem just because GCC is doing something differently, like you
> and Jose E. Marchesi did with [0] and [1].

The behavior divergence here appears to predate BPF support in both
compilers from my understanding, the issue is being discussed in both
GCC and llvm issue trackers to try and figure out what the best way to
get behavior convergence would be, seems to make sense to me to
have this issue tracked by llvm and GCC.

Explicitly setting the section seemed like it might be a good approach so
that in the event llvm did change the default things would still work the
same way.

I don't think anyone is trying to go behind anyone's back here...I've tried
to cross reference issues in general so that everyone is aware of all the
discussions.

>
>   [0] https://github.com/llvm/llvm-project/issues/56468
>   [1] https://reviews.llvm.org/D131012
>
> > >
> > > >
> > > > The used attribute in the SEC macro supposedly ensures that:
> > > > The compiler must emit the definition even if it appears to be unused, and
> > > > it must not apply optimizations which depend on fully understanding how
> > > > the entity is used.
> > > >
> > > > Or maybe the retain attribute along with used would be sufficient to allow
> > > > us to drop volatile in these cases?:
> > > > https://clang.llvm.org/docs/AttributeReference.html#retain
> > > >
> > > > >
> > > > >
> > > > >   [0] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25521
> > > > >   [1] https://github.com/systemd/systemd/pull/24164#issuecomment-1203207372
> > > > >
> > > > > >
> > > > > > >
> > > > > > >   [0] https://github.com/systemd/systemd/pull/24164#issuecomment-1201806413
> > > > > > >
> > > > > > >
> > > > > > > [...]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-08-03 16:57                                               ` Andrii Nakryiko
  2022-08-03 19:24                                                 ` James Hilliard
@ 2022-08-04 17:29                                                 ` Alexei Starovoitov
  1 sibling, 0 replies; 38+ messages in thread
From: Alexei Starovoitov @ 2022-08-04 17:29 UTC (permalink / raw)
  To: Andrii Nakryiko
  Cc: James Hilliard, Jose E. Marchesi, bpf, david.faust, Jonathan Corbet

On Wed, Aug 3, 2022 at 9:59 AM Andrii Nakryiko
<andrii.nakryiko@gmail.com> wrote:
>
> Please also start with learning how to build selftests/bpf with Clang
> and looking at various examples so that you can at least look at all
> the different features we rely on in the BPF world, instead of trying
> to tune one small piece (systemd's BPF programs) to your liking. If
> you are serious about making GCC BPF backend viable, you'll have to
> understand BPF a bit better.
>
> That would be a better use of everyone's time, instead of you going
> behind our backs and requesting Clang to break the entire BPF
> ecosystem just because GCC is doing something differently, like you
> and Jose E. Marchesi did with [0] and [1].
>
>   [0] https://github.com/llvm/llvm-project/issues/56468
>   [1] https://reviews.llvm.org/D131012

+1

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-08-03 19:24                                                 ` James Hilliard
@ 2022-09-30 21:52                                                   ` James Hilliard
  2022-09-30 22:50                                                     ` Andrii Nakryiko
  0 siblings, 1 reply; 38+ messages in thread
From: James Hilliard @ 2022-09-30 21:52 UTC (permalink / raw)
  To: Andrii Nakryiko; +Cc: Jose E. Marchesi, bpf, david.faust

On Wed, Aug 3, 2022 at 3:24 PM James Hilliard <james.hilliard1@gmail.com> wrote:
>
> On Wed, Aug 3, 2022 at 10:57 AM Andrii Nakryiko
> <andrii.nakryiko@gmail.com> wrote:
> >
> > On Tue, Aug 2, 2022 at 6:49 PM James Hilliard <james.hilliard1@gmail.com> wrote:
> > >
> > > On Tue, Aug 2, 2022 at 6:29 PM Andrii Nakryiko
> > > <andrii.nakryiko@gmail.com> wrote:
> > > >
> > > > On Tue, Aug 2, 2022 at 3:06 PM James Hilliard <james.hilliard1@gmail.com> wrote:
> > > > >
> > > > > On Tue, Aug 2, 2022 at 3:29 PM Andrii Nakryiko
> > > > > <andrii.nakryiko@gmail.com> wrote:
> > > > > >
> > > > > > On Mon, Aug 1, 2022 at 4:35 PM James Hilliard <james.hilliard1@gmail.com> wrote:
> > > > > > >
> > > > > > > On Mon, Aug 1, 2022 at 4:52 PM Andrii Nakryiko
> > > > > > > <andrii.nakryiko@gmail.com> wrote:
> > > > > > > >
> > > > > > > > On Sun, Jul 31, 2022 at 7:20 PM James Hilliard
> > > > > > > > <james.hilliard1@gmail.com> wrote:
> > > > > > > > >
> > > > > > > > > On Sun, Jul 10, 2022 at 2:22 PM Jose E. Marchesi
> > > > > > > > > <jose.marchesi@oracle.com> wrote:
> > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > >>> On Sun, Jul 10, 2022 at 3:38 AM Jose E. Marchesi
> > > > > > > > > > >>> <jose.marchesi@oracle.com> wrote:
> > > > > > > > > > >>>>
> > > > > > > > > > >>>>
> > > > > > > > > > >>>> > On Sat, Jul 9, 2022 at 4:41 PM Jose E. Marchesi
> > > > > > > > > > >>>> > <jose.marchesi@oracle.com> wrote:
> > > > > > > > > > >>>> >>
> > > > > > > > > > >>>> >>
> > > > > > > > > > >>>> >> > On Sat, Jul 9, 2022 at 2:32 PM James Hilliard <james.hilliard1@gmail.com> wrote:
> > > > > > > > > > >>>> >> >>
> > > > > > > > > > >>>> >> >> On Sat, Jul 9, 2022 at 2:21 PM Jose E. Marchesi
> > > > > > > > > > >>>> >> >> <jose.marchesi@oracle.com> wrote:
> > > > > > > > > > >>>> >> >> >
> > > > > > > > > > >>>> >> >> >
> > > > > > > >
> > > > > > > > Please trim your replies (and I don't know what your email client did,
> > > > > > > > but it completely ruined nested quote formatting)
> > > > > > >
> > > > > > > Yeah, not sure what happened there.
> > > > > > >
> > > > > > > >
> > > > > > > > [...]
> > > > > > > >
> > > > > > > > > > >>>>
> > > > > > > > > > >>>> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> > > > > > > > > > >>>> index e89cc9c885b3..887b78780099 100644
> > > > > > > > > > >>>> --- a/tools/lib/bpf/libbpf.c
> > > > > > > > > > >>>> +++ b/tools/lib/bpf/libbpf.c
> > > > > > > > > > >>>> @@ -1591,6 +1591,10 @@ static int bpf_object__init_global_data_maps(struct bpf_object *obj)
> > > > > > > > > > >>>>         for (sec_idx = 1; sec_idx < obj->efile.sec_cnt; sec_idx++) {
> > > > > > > > > > >>>>                 sec_desc = &obj->efile.secs[sec_idx];
> > > > > > > > > > >>>>
> > > > > > > > > > >>>> +                /* Skip recognized sections with size 0.  */
> > > > > > > > > > >>>> +                if (sec_desc->data && sec_desc->data->d_size == 0)
> > > > > > > > > > >>>> +                  continue;
> > > > > > > > > > >>>> +
> > > > > > > > > > >>>>                 switch (sec_desc->sec_type) {
> > > > > > > > > > >>>>                 case SEC_DATA:
> > > > > > > > > > >>>>                         sec_name = elf_sec_name(obj, elf_sec_by_idx(obj, sec_idx));
> > > > > > > > > > >>>
> > > > > > > > > > >>> Ok, skeleton is now getting generated successfully, however it differs from the
> > > > > > > > > > >>> clang version so there's a build error when we include/use the header:
> > > > > > > > > > >>> ../src/core/restrict-ifaces.c: In function ‘prepare_restrict_ifaces_bpf’:
> > > > > > > > > > >>> ../src/core/restrict-ifaces.c:45:14: error: ‘struct
> > > > > > > > > > >>> restrict_ifaces_bpf’ has no member named ‘rodata’; did you mean
> > > > > > > > > > >>> ‘data’?
> > > > > > > > > > >>>    45 |         obj->rodata->is_allow_list = is_allow_list;
> > > > > > > > > > >>>       |              ^~~~~~
> > > > > > > > > > >>>       |              data
> > > > > > > > > > >>>
> > > > > > > > > > >>> The issue appears to be that clang generates "rodata" members in
> > > > > > > > > > >>> restrict_ifaces_bpf while with gcc we get "data" members instead.
> > > > > > > > > > >>
> > > > > > > > > > >> This is because the BPF GCC port is putting the
> > > > > > > > > > >>
> > > > > > > > > > >>   const volatile unsigned char is_allow_list = 0;
> > > > > > > > > > >>
> > > > > > > > > > >> in a .data section instead of .rodata, due to the `volatile'.  The
> > > > > > > > > > >> x86_64 GCC seems to use .rodata.
> > > > > > > > > > >>
> > > > > > > > > > >> Looking at why the PBF port does this...
> > > > > > > > > > >
> > > > > > > > > > > So, turns out GCC puts zero-initialized `const volatile' variables in
> > > > > > > > > > > .data sections (and not .rodata) in all the targets I have tried, like
> > > > > > > > > > > x86_64 and aarch64.
> > > > > > > > > > >
> > > > > > > > > > > So this is a LLVM and GCC divergence :/
> > > > > > > > > >
> > > > > > > > > > See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25521.
> > > > > > > > > >
> > > > > > > > > > You may try, as a workaround:
> > > > > > > > > >
> > > > > > > > > > __attribute__((section(".rodata"))) const volatile unsigned char is_allow_list = 0;
> > > > > > > > > >
> > > > > > > > > > But that will use permissions "aw" for the .rodata section (and you will
> > > > > > > > > > get a warning from the assembler.)  It may be problematic for libbpf.
> > > > > > > > >
> > > > > > > > > So rather than try to force gcc to use the incorrect llvm .rodata
> > > > > > > > > section it looks
> > > > > > > > > like we can instead just force llvm to use the correct .data section like this:
> > > > > > > > > https://github.com/systemd/systemd/pull/24164
> > > > > > > > >
> > > > > > > >
> > > > > > > > There is a huge difference between variables in .rodata and .data.
> > > > > > > > .rodata variable's value is known to the BPF verifier at verification
> > > > > > > > time and this knowledge will be used to decide which code paths are
> > > > > > > > always or never taken (as one example). It's a crucial property and
> > > > > > > > important guarantee.
> > > > > > > >
> > > > > > > > If you don't care about that property, don't declare the variable as `const`.
> > > > > > > >
> > > > > > > > So no, it's not llvm putting `const` variable into .rodata
> > > > > > > > incorrectly, but GCC is trying to be smart and just because variable
> > > > > > > > is declared volatile is putting *const* variable into read-write .data
> > > > > > > > section. It's declared as const, and yes it's volatile to make sure
> > > > > > > > that compiler isn't too smart about optimizing away read operations.
> > > > > > >
> > > > > > > Isn't const volatile generating a .rodata section(like llvm is doing) a spec
> > > > > > > violation?
> > > > > > > https://github.com/llvm/llvm-project/issues/56468
> > > > > > >
> > > > > > > > But it's still a const read-only variable from the perspective of that
> > > > > > > > BPF C code.
> > > > > > > >
> > > > > > > > If you don't care about the read-only nature of that variable, drop
> > > > > > > > the const and make it into a non-read-only variable.
> > > > > > > >
> > > > > > > > And please stop proposing hacks to be added to perfectly valid systemd
> > > > > > > > BPF source code (I replied on [0] as well).
> > > > > > >
> > > > > > > From my understanding gcc is correctly putting a const volatile variable
> > > > > > > in .data while llvm is incorrectly putting it in .rodata, is the gcc behavior
> > > > > > > here invalid or is the llvm behavior invalid?
> > > > > >
> > > > > > From link you left to C standard, it does seem like that side-note
> > > > > > *implies* that const volatile should be put into .data, but it's a)
> > > > > > implied b) is quite arguable about assumptions that this data has to
> > > > > > be in modifiable section, and c) entire CO-RE feature detection and
> > > > > > guarding relies on having `const volatile` variables in .rodata and
> > > > > > mark them as read-only for BPF verifier to allow dead code
> > > > > > elimination. Changing c) would break entire CO-RE ecosystem.
> > > > >
> > > > > Well it does appear that llvm is fixing the behavior to be in line with gcc:
> > > > > https://reviews.llvm.org/D131012
> > > > >
> > > > > >
> > > > > > Seems like this issue was raised by Ulrich Drepper back in 2005 ([0])
> > > > > > and he was also confused about GCC's behavior, btw.
> > > > > >
> > > > > > So either way, at the very least for BPF target we can't change this
> > > > > > and I still think it's more logical to put const variables into
> > > > > > .rodata, regardless of side notes in C standard.
> > > > >
> > > > > GCC does put const variables in .rodata, just not const volatile variables.
> > > > >
> > > >
> > > > It's still const. Volatile doesn't change constness of a variable.
> > > > We've been discussing this over and over, it gets a bit tiring, tbh.
> > > >
> > > > Aaron Ballman seems to agree, quoting him from [0]:
> > > >
> > > >   The footnote cited isn't a normative requirement (I can't see any
> > > >   normative requirements that say we can't put a const volatile object
> > > >   into a read only section), so it's debatable just how much of a bug
> > > >   this is from a standards conformance perspective. I will have to
> > > >   inquire on the WG14 reflectors to see if there's something I've
> > > >   missed but I believe that C17 6.7.3p5 is meant to point out that
> > > >   only lvalue are qualified; rvalues are not because lvalue conversion
> > > >   strips the qualifiers. I think the footnote is mostly a nod towards
> > > >   the fact that volatile qualified objects may change their value in
> > > >   ways unknown to the compiler so storing it in a read-only section
> > > >   of memory is a bit questionable. But I'm curious if the committee
> > > >   tells me I've missed something there.
> > > >
> > > >
> > > >   [0] https://github.com/llvm/llvm-project/issues/56468#issuecomment-1203146308
> > > >
> > > > > >
> > > > > >
> > > > > > As for systemd's program and its is_allow_list ([1]), to unblock
> > > > > > yourself you can drop const because systemd doesn't rely on read-only
> > > > > > guarantees of that variable anyways. It's much more critical in
> > > > > > feature-detection use cases. But let's try to converge discussion in
> > > > > > one place (preferably here), it's quite inconvenient to either reply
> > > > > > the same thing twice here and on Github, or cross-reference lore and
> > > > > > Github.
> > > > >
> > > > > Hmm, are you sure:
> > > > > const __u8 is_allow_list SEC(".rodata") = 0;
> > > > >
> > > > > doesn't provide equivalent behavior to:
> > > > > const volatile __u8 is_allow_list = 0;
> > > >
> > > > Is there anything preventing you from experimenting with this yourself?..
> > >
> > > Wasn't sure how to reproduce the issue properly.
> > >
> >
> > Then please start asking specific questions about how to repro issues
> > we are talking about, instead of randomly throwing various ideas
> > around and seeing what sticks.
>
> I tested with the reproducer to see if any attribute based workarounds
> might avoid the need for volatile, and I didn't find anything.
>
> >
> > > >
> > > > Let's see:
> > > >
> > > > $ git diff
> > > > diff --git a/tools/testing/selftests/bpf/prog_tests/skeleton.c
> > > > b/tools/testing/selftests/bpf/prog_tests/skeleton.c
> > > > index 99dac5292b41..386785a45af0 100644
> > > > --- a/tools/testing/selftests/bpf/prog_tests/skeleton.c
> > > > +++ b/tools/testing/selftests/bpf/prog_tests/skeleton.c
> > > > @@ -31,6 +31,8 @@ void test_skeleton(void)
> > > >         if (CHECK(skel->kconfig, "skel_kconfig", "kconfig is mmaped()!\n"))
> > > >                 goto cleanup;
> > > >
> > > > +       skel->rodata->should_trap = false;
> > > > +
> > > >         bss = skel->bss;
> > > >         data = skel->data;
> > > >         data_dyn = skel->data_dyn;
> > > > diff --git a/tools/testing/selftests/bpf/progs/test_skeleton.c
> > > > b/tools/testing/selftests/bpf/progs/test_skeleton.c
> > > > index 1a4e93f6d9df..eee26bc82525 100644
> > > > --- a/tools/testing/selftests/bpf/progs/test_skeleton.c
> > > > +++ b/tools/testing/selftests/bpf/progs/test_skeleton.c
> > > > @@ -26,6 +26,8 @@ const volatile struct {
> > > >         const int in6;
> > > >  } in = {};
> > > >
> > > > +const bool should_trap SEC(".rodata") = true;
> > > > +
> > > >  /* .data section */
> > > >  int out1 = -1;
> > > >  long long out2 = -1;
> > > > @@ -58,6 +60,10 @@ int handler(const void *ctx)
> > > >  {
> > > >         int i;
> > > >
> > > > +       while (should_trap)
> > > > +       {
> > > > +       }
> > > > +
> > > >         out1 = in1;
> > > >         out2 = in2;
> > > >         out3 = in3;
> > > >
> > > >
> > > > Result: selftests stop compiling. Why?
> > > >
> > > > $ llvm-objdump -d test_skeleton.linked1.o
> > > >
> > > > test_skeleton.linked1.o:        file format elf64-bpf
> > > >
> > > > Disassembly of section raw_tp/sys_enter:
> > > >
> > > > 0000000000000000 <handler>:
> > > >        0:       05 00 ff ff 00 00 00 00 goto -1 <handler>
> > > >
> > > > Because compiler optimized away everything with while (true) {}. There
> > > > is no global data at all anymore.
> > > >
> > > > This is what I keep telling you, const volatile is the only thing
> > > > preventing the compiler from making wrong assumptions. And neither
> > > >
> > > > const bool should_trap SEC(".rodata") = true;
> > > >
> > > > nor
> > > >
> > > > const bool should_trap = true;
> > > >
> > > > work.
> > > >
> > > > But
> > > >
> > > > const volatile bool should_trap = true;
> > > >
> > > > does work.
> > > >
> > > > If you have some more speculative proposals, please investigate them
> > > > yourself and report back with the results. But either way there is a
> > > > lot of BPF code written with reliance on `const volatile`, both open
> > > > source and not, so please stop actively trying to break BPF ecosystem
> > > > with proposals like moving `const volatile` to .data, just because
> > > > it's more convenient for you in GCC. Thank you.
> > >
> > > So it does at least seem I can force GCC to use .rodata like this for
> > > systemd, maybe that's the best approach for now?:
> > >
> > > const volatile __u8 is_allow_list SEC(".rodata") = 0;
> > >
> > > It does emit an assembler warning but otherwise appears to work:
> > > Generating src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
> > > with a custom command
> > > /tmp/ccM2b7jP.s: Assembler messages:
> > > /tmp/ccM2b7jP.s:87: Warning: setting incorrect section attributes for .rodata
> > >
> > > I updated my systemd PR with that.
> > >
> >
> > For Nth time, don't do this. Drop the const for systemd. And please
> > start paying attention to feedback.
>
> Well I was looking for a more general solution for behavior convergence,
> I posted here to see if that was a workable option to get both compilers
> to behave the same for cases where we want the variable to be in
> .rodata. I had also updated the pull request to make it easier to get
> feedback on that approach.

I've opened a pull request reverting this:
https://github.com/systemd/systemd/pull/24881

GCC const volatile .rodata section behavior should now match LLVM/clang.

Details:
https://github.com/gcc-mirror/gcc/commit/a0aafbc324aa90421f0ce99c6f5bbf64ed163da6

>
> I guess a developer at your company approved the PR already and
> it got merged.
>
> >
> > Please also start with learning how to build selftests/bpf with Clang
> > and looking at various examples so that you can at least look at all
> > the different features we rely on in the BPF world, instead of trying
> > to tune one small piece (systemd's BPF programs) to your liking. If
> > you are serious about making GCC BPF backend viable, you'll have to
> > understand BPF a bit better.
>
> I did do that for both clang and gcc, I've been fixing issues I discovered
> like this one for example when trying to build tests with gcc:
> https://lore.kernel.org/bpf/20220803151403.793024-1-james.hilliard1@gmail.com/
>
> >
> > That would be a better use of everyone's time, instead of you going
> > behind our backs and requesting Clang to break the entire BPF
> > ecosystem just because GCC is doing something differently, like you
> > and Jose E. Marchesi did with [0] and [1].
>
> The behavior divergence here appears to predate BPF support in both
> compilers from my understanding, the issue is being discussed in both
> GCC and llvm issue trackers to try and figure out what the best way to
> get behavior convergence would be, seems to make sense to me to
> have this issue tracked by llvm and GCC.
>
> Explicitly setting the section seemed like it might be a good approach so
> that in the event llvm did change the default things would still work the
> same way.
>
> I don't think anyone is trying to go behind anyone's back here...I've tried
> to cross reference issues in general so that everyone is aware of all the
> discussions.
>
> >
> >   [0] https://github.com/llvm/llvm-project/issues/56468
> >   [1] https://reviews.llvm.org/D131012
> >
> > > >
> > > > >
> > > > > The used attribute in the SEC macro supposedly ensures that:
> > > > > The compiler must emit the definition even if it appears to be unused, and
> > > > > it must not apply optimizations which depend on fully understanding how
> > > > > the entity is used.
> > > > >
> > > > > Or maybe the retain attribute along with used would be sufficient to allow
> > > > > us to drop volatile in these cases?:
> > > > > https://clang.llvm.org/docs/AttributeReference.html#retain
> > > > >
> > > > > >
> > > > > >
> > > > > >   [0] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25521
> > > > > >   [1] https://github.com/systemd/systemd/pull/24164#issuecomment-1203207372
> > > > > >
> > > > > > >
> > > > > > > >
> > > > > > > >   [0] https://github.com/systemd/systemd/pull/24164#issuecomment-1201806413
> > > > > > > >
> > > > > > > >
> > > > > > > > [...]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: bpftool gen object doesn't handle GCC built BPF ELF files
  2022-09-30 21:52                                                   ` James Hilliard
@ 2022-09-30 22:50                                                     ` Andrii Nakryiko
  0 siblings, 0 replies; 38+ messages in thread
From: Andrii Nakryiko @ 2022-09-30 22:50 UTC (permalink / raw)
  To: James Hilliard; +Cc: Jose E. Marchesi, bpf, david.faust

On Fri, Sep 30, 2022 at 2:52 PM James Hilliard
<james.hilliard1@gmail.com> wrote:
>
> On Wed, Aug 3, 2022 at 3:24 PM James Hilliard <james.hilliard1@gmail.com> wrote:
> >
> > On Wed, Aug 3, 2022 at 10:57 AM Andrii Nakryiko
> > <andrii.nakryiko@gmail.com> wrote:
> > >
> > > On Tue, Aug 2, 2022 at 6:49 PM James Hilliard <james.hilliard1@gmail.com> wrote:
> > > >
> > > > On Tue, Aug 2, 2022 at 6:29 PM Andrii Nakryiko
> > > > <andrii.nakryiko@gmail.com> wrote:
> > > > >
> > > > > On Tue, Aug 2, 2022 at 3:06 PM James Hilliard <james.hilliard1@gmail.com> wrote:
> > > > > >
> > > > > > On Tue, Aug 2, 2022 at 3:29 PM Andrii Nakryiko
> > > > > > <andrii.nakryiko@gmail.com> wrote:
> > > > > > >
> > > > > > > On Mon, Aug 1, 2022 at 4:35 PM James Hilliard <james.hilliard1@gmail.com> wrote:
> > > > > > > >
> > > > > > > > On Mon, Aug 1, 2022 at 4:52 PM Andrii Nakryiko
> > > > > > > > <andrii.nakryiko@gmail.com> wrote:
> > > > > > > > >
> > > > > > > > > On Sun, Jul 31, 2022 at 7:20 PM James Hilliard
> > > > > > > > > <james.hilliard1@gmail.com> wrote:
> > > > > > > > > >
> > > > > > > > > > On Sun, Jul 10, 2022 at 2:22 PM Jose E. Marchesi
> > > > > > > > > > <jose.marchesi@oracle.com> wrote:
> > > > > > > > > > >
> > > > > > > > > > >
> > > > > > > > > > > >>> On Sun, Jul 10, 2022 at 3:38 AM Jose E. Marchesi
> > > > > > > > > > > >>> <jose.marchesi@oracle.com> wrote:
> > > > > > > > > > > >>>>
> > > > > > > > > > > >>>>
> > > > > > > > > > > >>>> > On Sat, Jul 9, 2022 at 4:41 PM Jose E. Marchesi
> > > > > > > > > > > >>>> > <jose.marchesi@oracle.com> wrote:
> > > > > > > > > > > >>>> >>
> > > > > > > > > > > >>>> >>
> > > > > > > > > > > >>>> >> > On Sat, Jul 9, 2022 at 2:32 PM James Hilliard <james.hilliard1@gmail.com> wrote:
> > > > > > > > > > > >>>> >> >>
> > > > > > > > > > > >>>> >> >> On Sat, Jul 9, 2022 at 2:21 PM Jose E. Marchesi
> > > > > > > > > > > >>>> >> >> <jose.marchesi@oracle.com> wrote:
> > > > > > > > > > > >>>> >> >> >
> > > > > > > > > > > >>>> >> >> >
> > > > > > > > >
> > > > > > > > > Please trim your replies (and I don't know what your email client did,
> > > > > > > > > but it completely ruined nested quote formatting)
> > > > > > > >
> > > > > > > > Yeah, not sure what happened there.
> > > > > > > >
> > > > > > > > >
> > > > > > > > > [...]
> > > > > > > > >
> > > > > > > > > > > >>>>
> > > > > > > > > > > >>>> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> > > > > > > > > > > >>>> index e89cc9c885b3..887b78780099 100644
> > > > > > > > > > > >>>> --- a/tools/lib/bpf/libbpf.c
> > > > > > > > > > > >>>> +++ b/tools/lib/bpf/libbpf.c
> > > > > > > > > > > >>>> @@ -1591,6 +1591,10 @@ static int bpf_object__init_global_data_maps(struct bpf_object *obj)
> > > > > > > > > > > >>>>         for (sec_idx = 1; sec_idx < obj->efile.sec_cnt; sec_idx++) {
> > > > > > > > > > > >>>>                 sec_desc = &obj->efile.secs[sec_idx];
> > > > > > > > > > > >>>>
> > > > > > > > > > > >>>> +                /* Skip recognized sections with size 0.  */
> > > > > > > > > > > >>>> +                if (sec_desc->data && sec_desc->data->d_size == 0)
> > > > > > > > > > > >>>> +                  continue;
> > > > > > > > > > > >>>> +
> > > > > > > > > > > >>>>                 switch (sec_desc->sec_type) {
> > > > > > > > > > > >>>>                 case SEC_DATA:
> > > > > > > > > > > >>>>                         sec_name = elf_sec_name(obj, elf_sec_by_idx(obj, sec_idx));
> > > > > > > > > > > >>>
> > > > > > > > > > > >>> Ok, skeleton is now getting generated successfully, however it differs from the
> > > > > > > > > > > >>> clang version so there's a build error when we include/use the header:
> > > > > > > > > > > >>> ../src/core/restrict-ifaces.c: In function ‘prepare_restrict_ifaces_bpf’:
> > > > > > > > > > > >>> ../src/core/restrict-ifaces.c:45:14: error: ‘struct
> > > > > > > > > > > >>> restrict_ifaces_bpf’ has no member named ‘rodata’; did you mean
> > > > > > > > > > > >>> ‘data’?
> > > > > > > > > > > >>>    45 |         obj->rodata->is_allow_list = is_allow_list;
> > > > > > > > > > > >>>       |              ^~~~~~
> > > > > > > > > > > >>>       |              data
> > > > > > > > > > > >>>
> > > > > > > > > > > >>> The issue appears to be that clang generates "rodata" members in
> > > > > > > > > > > >>> restrict_ifaces_bpf while with gcc we get "data" members instead.
> > > > > > > > > > > >>
> > > > > > > > > > > >> This is because the BPF GCC port is putting the
> > > > > > > > > > > >>
> > > > > > > > > > > >>   const volatile unsigned char is_allow_list = 0;
> > > > > > > > > > > >>
> > > > > > > > > > > >> in a .data section instead of .rodata, due to the `volatile'.  The
> > > > > > > > > > > >> x86_64 GCC seems to use .rodata.
> > > > > > > > > > > >>
> > > > > > > > > > > >> Looking at why the PBF port does this...
> > > > > > > > > > > >
> > > > > > > > > > > > So, turns out GCC puts zero-initialized `const volatile' variables in
> > > > > > > > > > > > .data sections (and not .rodata) in all the targets I have tried, like
> > > > > > > > > > > > x86_64 and aarch64.
> > > > > > > > > > > >
> > > > > > > > > > > > So this is a LLVM and GCC divergence :/
> > > > > > > > > > >
> > > > > > > > > > > See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25521.
> > > > > > > > > > >
> > > > > > > > > > > You may try, as a workaround:
> > > > > > > > > > >
> > > > > > > > > > > __attribute__((section(".rodata"))) const volatile unsigned char is_allow_list = 0;
> > > > > > > > > > >
> > > > > > > > > > > But that will use permissions "aw" for the .rodata section (and you will
> > > > > > > > > > > get a warning from the assembler.)  It may be problematic for libbpf.
> > > > > > > > > >
> > > > > > > > > > So rather than try to force gcc to use the incorrect llvm .rodata
> > > > > > > > > > section it looks
> > > > > > > > > > like we can instead just force llvm to use the correct .data section like this:
> > > > > > > > > > https://github.com/systemd/systemd/pull/24164
> > > > > > > > > >
> > > > > > > > >
> > > > > > > > > There is a huge difference between variables in .rodata and .data.
> > > > > > > > > .rodata variable's value is known to the BPF verifier at verification
> > > > > > > > > time and this knowledge will be used to decide which code paths are
> > > > > > > > > always or never taken (as one example). It's a crucial property and
> > > > > > > > > important guarantee.
> > > > > > > > >
> > > > > > > > > If you don't care about that property, don't declare the variable as `const`.
> > > > > > > > >
> > > > > > > > > So no, it's not llvm putting `const` variable into .rodata
> > > > > > > > > incorrectly, but GCC is trying to be smart and just because variable
> > > > > > > > > is declared volatile is putting *const* variable into read-write .data
> > > > > > > > > section. It's declared as const, and yes it's volatile to make sure
> > > > > > > > > that compiler isn't too smart about optimizing away read operations.
> > > > > > > >
> > > > > > > > Isn't const volatile generating a .rodata section(like llvm is doing) a spec
> > > > > > > > violation?
> > > > > > > > https://github.com/llvm/llvm-project/issues/56468
> > > > > > > >
> > > > > > > > > But it's still a const read-only variable from the perspective of that
> > > > > > > > > BPF C code.
> > > > > > > > >
> > > > > > > > > If you don't care about the read-only nature of that variable, drop
> > > > > > > > > the const and make it into a non-read-only variable.
> > > > > > > > >
> > > > > > > > > And please stop proposing hacks to be added to perfectly valid systemd
> > > > > > > > > BPF source code (I replied on [0] as well).
> > > > > > > >
> > > > > > > > From my understanding gcc is correctly putting a const volatile variable
> > > > > > > > in .data while llvm is incorrectly putting it in .rodata, is the gcc behavior
> > > > > > > > here invalid or is the llvm behavior invalid?
> > > > > > >
> > > > > > > From link you left to C standard, it does seem like that side-note
> > > > > > > *implies* that const volatile should be put into .data, but it's a)
> > > > > > > implied b) is quite arguable about assumptions that this data has to
> > > > > > > be in modifiable section, and c) entire CO-RE feature detection and
> > > > > > > guarding relies on having `const volatile` variables in .rodata and
> > > > > > > mark them as read-only for BPF verifier to allow dead code
> > > > > > > elimination. Changing c) would break entire CO-RE ecosystem.
> > > > > >
> > > > > > Well it does appear that llvm is fixing the behavior to be in line with gcc:
> > > > > > https://reviews.llvm.org/D131012
> > > > > >
> > > > > > >
> > > > > > > Seems like this issue was raised by Ulrich Drepper back in 2005 ([0])
> > > > > > > and he was also confused about GCC's behavior, btw.
> > > > > > >
> > > > > > > So either way, at the very least for BPF target we can't change this
> > > > > > > and I still think it's more logical to put const variables into
> > > > > > > .rodata, regardless of side notes in C standard.
> > > > > >
> > > > > > GCC does put const variables in .rodata, just not const volatile variables.
> > > > > >
> > > > >
> > > > > It's still const. Volatile doesn't change constness of a variable.
> > > > > We've been discussing this over and over, it gets a bit tiring, tbh.
> > > > >
> > > > > Aaron Ballman seems to agree, quoting him from [0]:
> > > > >
> > > > >   The footnote cited isn't a normative requirement (I can't see any
> > > > >   normative requirements that say we can't put a const volatile object
> > > > >   into a read only section), so it's debatable just how much of a bug
> > > > >   this is from a standards conformance perspective. I will have to
> > > > >   inquire on the WG14 reflectors to see if there's something I've
> > > > >   missed but I believe that C17 6.7.3p5 is meant to point out that
> > > > >   only lvalue are qualified; rvalues are not because lvalue conversion
> > > > >   strips the qualifiers. I think the footnote is mostly a nod towards
> > > > >   the fact that volatile qualified objects may change their value in
> > > > >   ways unknown to the compiler so storing it in a read-only section
> > > > >   of memory is a bit questionable. But I'm curious if the committee
> > > > >   tells me I've missed something there.
> > > > >
> > > > >
> > > > >   [0] https://github.com/llvm/llvm-project/issues/56468#issuecomment-1203146308
> > > > >
> > > > > > >
> > > > > > >
> > > > > > > As for systemd's program and its is_allow_list ([1]), to unblock
> > > > > > > yourself you can drop const because systemd doesn't rely on read-only
> > > > > > > guarantees of that variable anyways. It's much more critical in
> > > > > > > feature-detection use cases. But let's try to converge discussion in
> > > > > > > one place (preferably here), it's quite inconvenient to either reply
> > > > > > > the same thing twice here and on Github, or cross-reference lore and
> > > > > > > Github.
> > > > > >
> > > > > > Hmm, are you sure:
> > > > > > const __u8 is_allow_list SEC(".rodata") = 0;
> > > > > >
> > > > > > doesn't provide equivalent behavior to:
> > > > > > const volatile __u8 is_allow_list = 0;
> > > > >
> > > > > Is there anything preventing you from experimenting with this yourself?..
> > > >
> > > > Wasn't sure how to reproduce the issue properly.
> > > >
> > >
> > > Then please start asking specific questions about how to repro issues
> > > we are talking about, instead of randomly throwing various ideas
> > > around and seeing what sticks.
> >
> > I tested with the reproducer to see if any attribute based workarounds
> > might avoid the need for volatile, and I didn't find anything.
> >
> > >
> > > > >
> > > > > Let's see:
> > > > >
> > > > > $ git diff
> > > > > diff --git a/tools/testing/selftests/bpf/prog_tests/skeleton.c
> > > > > b/tools/testing/selftests/bpf/prog_tests/skeleton.c
> > > > > index 99dac5292b41..386785a45af0 100644
> > > > > --- a/tools/testing/selftests/bpf/prog_tests/skeleton.c
> > > > > +++ b/tools/testing/selftests/bpf/prog_tests/skeleton.c
> > > > > @@ -31,6 +31,8 @@ void test_skeleton(void)
> > > > >         if (CHECK(skel->kconfig, "skel_kconfig", "kconfig is mmaped()!\n"))
> > > > >                 goto cleanup;
> > > > >
> > > > > +       skel->rodata->should_trap = false;
> > > > > +
> > > > >         bss = skel->bss;
> > > > >         data = skel->data;
> > > > >         data_dyn = skel->data_dyn;
> > > > > diff --git a/tools/testing/selftests/bpf/progs/test_skeleton.c
> > > > > b/tools/testing/selftests/bpf/progs/test_skeleton.c
> > > > > index 1a4e93f6d9df..eee26bc82525 100644
> > > > > --- a/tools/testing/selftests/bpf/progs/test_skeleton.c
> > > > > +++ b/tools/testing/selftests/bpf/progs/test_skeleton.c
> > > > > @@ -26,6 +26,8 @@ const volatile struct {
> > > > >         const int in6;
> > > > >  } in = {};
> > > > >
> > > > > +const bool should_trap SEC(".rodata") = true;
> > > > > +
> > > > >  /* .data section */
> > > > >  int out1 = -1;
> > > > >  long long out2 = -1;
> > > > > @@ -58,6 +60,10 @@ int handler(const void *ctx)
> > > > >  {
> > > > >         int i;
> > > > >
> > > > > +       while (should_trap)
> > > > > +       {
> > > > > +       }
> > > > > +
> > > > >         out1 = in1;
> > > > >         out2 = in2;
> > > > >         out3 = in3;
> > > > >
> > > > >
> > > > > Result: selftests stop compiling. Why?
> > > > >
> > > > > $ llvm-objdump -d test_skeleton.linked1.o
> > > > >
> > > > > test_skeleton.linked1.o:        file format elf64-bpf
> > > > >
> > > > > Disassembly of section raw_tp/sys_enter:
> > > > >
> > > > > 0000000000000000 <handler>:
> > > > >        0:       05 00 ff ff 00 00 00 00 goto -1 <handler>
> > > > >
> > > > > Because compiler optimized away everything with while (true) {}. There
> > > > > is no global data at all anymore.
> > > > >
> > > > > This is what I keep telling you, const volatile is the only thing
> > > > > preventing the compiler from making wrong assumptions. And neither
> > > > >
> > > > > const bool should_trap SEC(".rodata") = true;
> > > > >
> > > > > nor
> > > > >
> > > > > const bool should_trap = true;
> > > > >
> > > > > work.
> > > > >
> > > > > But
> > > > >
> > > > > const volatile bool should_trap = true;
> > > > >
> > > > > does work.
> > > > >
> > > > > If you have some more speculative proposals, please investigate them
> > > > > yourself and report back with the results. But either way there is a
> > > > > lot of BPF code written with reliance on `const volatile`, both open
> > > > > source and not, so please stop actively trying to break BPF ecosystem
> > > > > with proposals like moving `const volatile` to .data, just because
> > > > > it's more convenient for you in GCC. Thank you.
> > > >
> > > > So it does at least seem I can force GCC to use .rodata like this for
> > > > systemd, maybe that's the best approach for now?:
> > > >
> > > > const volatile __u8 is_allow_list SEC(".rodata") = 0;
> > > >
> > > > It does emit an assembler warning but otherwise appears to work:
> > > > Generating src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.unstripped.o
> > > > with a custom command
> > > > /tmp/ccM2b7jP.s: Assembler messages:
> > > > /tmp/ccM2b7jP.s:87: Warning: setting incorrect section attributes for .rodata
> > > >
> > > > I updated my systemd PR with that.
> > > >
> > >
> > > For Nth time, don't do this. Drop the const for systemd. And please
> > > start paying attention to feedback.
> >
> > Well I was looking for a more general solution for behavior convergence,
> > I posted here to see if that was a workable option to get both compilers
> > to behave the same for cases where we want the variable to be in
> > .rodata. I had also updated the pull request to make it easier to get
> > feedback on that approach.
>
> I've opened a pull request reverting this:
> https://github.com/systemd/systemd/pull/24881
>
> GCC const volatile .rodata section behavior should now match LLVM/clang.
>
> Details:
> https://github.com/gcc-mirror/gcc/commit/a0aafbc324aa90421f0ce99c6f5bbf64ed163da6
>

Great, thanks! Approved systemd PR (FWIW).

> >
> > I guess a developer at your company approved the PR already and
> > it got merged.
> >
> > >
> > > Please also start with learning how to build selftests/bpf with Clang
> > > and looking at various examples so that you can at least look at all
> > > the different features we rely on in the BPF world, instead of trying
> > > to tune one small piece (systemd's BPF programs) to your liking. If
> > > you are serious about making GCC BPF backend viable, you'll have to
> > > understand BPF a bit better.
> >
> > I did do that for both clang and gcc, I've been fixing issues I discovered
> > like this one for example when trying to build tests with gcc:
> > https://lore.kernel.org/bpf/20220803151403.793024-1-james.hilliard1@gmail.com/
> >
> > >
> > > That would be a better use of everyone's time, instead of you going
> > > behind our backs and requesting Clang to break the entire BPF
> > > ecosystem just because GCC is doing something differently, like you
> > > and Jose E. Marchesi did with [0] and [1].
> >
> > The behavior divergence here appears to predate BPF support in both
> > compilers from my understanding, the issue is being discussed in both
> > GCC and llvm issue trackers to try and figure out what the best way to
> > get behavior convergence would be, seems to make sense to me to
> > have this issue tracked by llvm and GCC.
> >
> > Explicitly setting the section seemed like it might be a good approach so
> > that in the event llvm did change the default things would still work the
> > same way.
> >
> > I don't think anyone is trying to go behind anyone's back here...I've tried
> > to cross reference issues in general so that everyone is aware of all the
> > discussions.
> >
> > >
> > >   [0] https://github.com/llvm/llvm-project/issues/56468
> > >   [1] https://reviews.llvm.org/D131012
> > >
> > > > >
> > > > > >
> > > > > > The used attribute in the SEC macro supposedly ensures that:
> > > > > > The compiler must emit the definition even if it appears to be unused, and
> > > > > > it must not apply optimizations which depend on fully understanding how
> > > > > > the entity is used.
> > > > > >
> > > > > > Or maybe the retain attribute along with used would be sufficient to allow
> > > > > > us to drop volatile in these cases?:
> > > > > > https://clang.llvm.org/docs/AttributeReference.html#retain
> > > > > >
> > > > > > >
> > > > > > >
> > > > > > >   [0] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25521
> > > > > > >   [1] https://github.com/systemd/systemd/pull/24164#issuecomment-1203207372
> > > > > > >
> > > > > > > >
> > > > > > > > >
> > > > > > > > >   [0] https://github.com/systemd/systemd/pull/24164#issuecomment-1201806413
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > [...]

^ permalink raw reply	[flat|nested] 38+ messages in thread

end of thread, other threads:[~2022-09-30 22:50 UTC | newest]

Thread overview: 38+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-06 17:11 bpftool gen object doesn't handle GCC built BPF ELF files James Hilliard
2022-07-06 17:20 ` Andrii Nakryiko
2022-07-06 17:49   ` James Hilliard
2022-07-08 11:55     ` Jose E. Marchesi
2022-07-08 12:23       ` James Hilliard
2022-07-08 13:46         ` Jose E. Marchesi
2022-07-08 13:53           ` James Hilliard
2022-07-08 14:39             ` Jose E. Marchesi
2022-07-08 14:51   ` Jose E. Marchesi
2022-07-08 18:33     ` Jose E. Marchesi
2022-07-08 20:59       ` James Hilliard
2022-07-09 17:24         ` Jose E. Marchesi
2022-07-09 17:28           ` James Hilliard
2022-07-09 20:20             ` Jose E. Marchesi
2022-07-09 20:32               ` James Hilliard
2022-07-09 20:39                 ` James Hilliard
2022-07-09 22:41                   ` Jose E. Marchesi
2022-07-09 22:54                     ` James Hilliard
2022-07-10  9:38                       ` Jose E. Marchesi
2022-07-10 12:16                         ` James Hilliard
2022-07-10 13:06                           ` Jose E. Marchesi
2022-07-10 19:49                             ` Jose E. Marchesi
2022-07-10 20:22                               ` Jose E. Marchesi
2022-07-11  1:55                                 ` Jose E. Marchesi
     [not found]                                 ` <CADvTj4o-36iuru665BW0XnEauXBeszW438QTtpt4_VUEjf5nXg@mail.gmail.com>
2022-08-01 22:51                                   ` Andrii Nakryiko
2022-08-01 23:35                                     ` James Hilliard
2022-08-02 21:28                                       ` Andrii Nakryiko
2022-08-02 22:05                                         ` James Hilliard
2022-08-03  0:29                                           ` Andrii Nakryiko
2022-08-03  1:49                                             ` James Hilliard
2022-08-03 16:57                                               ` Andrii Nakryiko
2022-08-03 19:24                                                 ` James Hilliard
2022-09-30 21:52                                                   ` James Hilliard
2022-09-30 22:50                                                     ` Andrii Nakryiko
2022-08-04 17:29                                                 ` Alexei Starovoitov
2022-08-02 15:57       ` Jose E. Marchesi
2022-07-12  0:34   ` Indu Bhagat
2022-07-13  4:28     ` Yonghong Song

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.