On 2/11/22 8:47 AM, Alexei Starovoitov wrote:
On Fri, Feb 11, 2022 at 7:21 AM Yonghong Song <yhs@xxxxxx> wrote:
struct bpf_spin_lock {
__u32 val;
};
struct bpf_timer {
__u64 :64;
__u64 :64;
} __attribute__((aligned(8)));
The initialization code:
*(struct bpf_spin_lock *)(dst + map->spin_lock_off) =
(struct bpf_spin_lock){};
*(struct bpf_timer *)(dst + map->timer_off) =
(struct bpf_timer){};
It appears the compiler has no obligation to initialize anonymous fields.
For example, let us use clang with bpf target as below:
$ cat t.c
struct bpf_timer {
unsigned long long :64;
};
struct bpf_timer2 {
unsigned long long a;
};
void test(struct bpf_timer *t) {
*t = (struct bpf_timer){};
}
void test2(struct bpf_timer2 *t) {
*t = (struct bpf_timer2){};
}
$ clang -target bpf -O2 -c -g t.c
$ llvm-objdump -d t.o
...
0000000000000000 <test>:
0: 95 00 00 00 00 00 00 00 exit
0000000000000008 <test2>:
1: b7 02 00 00 00 00 00 00 r2 = 0
2: 7b 21 00 00 00 00 00 00 *(u64 *)(r1 + 0) = r2
3: 95 00 00 00 00 00 00 00 exit
wow!
Is this a clang only behavior or gcc does the same "smart" optimization?
gcc seems okay for my above test.
$ /home/yhs/work/gcc2/gcc11-2/install/bin/gcc --version
gcc (GCC) 11.2.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ /home/yhs/work/gcc2/gcc11-2/install/bin/gcc -O2 -c t.c
$ llvm-objdump -d t.o
t.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <test>:
0: 48 c7 07 00 00 00 00 movq $0, (%rdi)
7: c3 retq
8: 0f 1f 84 00 00 00 00 00 nopl (%rax,%rax)
0000000000000010 <test2>:
10: 48 c7 07 00 00 00 00 movq $0, (%rdi)
17: c3 retq
[yhs@devbig309.ftw3 ~/tmp2]
We've seen this issue with padding, but I could have never guessed
that compiler will do so for explicit anon fields.
I wonder what standard says and what other kernel code is broken
by this "optimization".
Not familiar with the standard. Need to dig out.