In math code we often have to make sure the compiler does not fold operations at compile time. In glibc we use variable declared as static const volatile double foo = 42.0; The problem is that gcc moves such variables into .data. But we could achieve that easily by leaving out the 'const'. What is needed is a method to achieve volatile behavior while having the variable in .rodata (and .rodata.cst8 etc). I therefore would like to ask for a change in the compiler which preserves the 'const' in the presence of 'volatile' and place the variable in read-only memory.
Subject: Re: New: change semantics of const volatile variables "drepper at redhat dot com" <gcc-bugzilla@gcc.gnu.org> writes: | In math code we often have to make sure the compiler does not fold operations | at compile time. In glibc we use variable declared as | | static const volatile double foo = 42.0; | | The problem is that gcc moves such variables into .data. But we could achieve | that easily by leaving out the 'const'. What is needed is a method to achieve | volatile behavior while having the variable in .rodata (and .rodata.cst8 etc). | | I therefore would like to ask for a change in the compiler which preserves the | 'const' in the presence of 'volatile' and place the variable in read-only | memory. that is tricky because of the general interpretation: [#10] EXAMPLE 1 An object declared extern const volatile int real_time_clock; may be modifiable by hardware, but cannot be assigned to, incremented, or decremented. If it may be modified by hardware or other external means, it can't go into .rodata section. -- Gaby
Using gcc's section attributes won't fully work either. Using __attribute((section(".rodata"))) is OK in the compiler, although the assembler (correctly) complaints. But what is really needed is __attribute((section(".rodata.cst8"))). This will cause gcc to fail with an ICE.
Subject: Re: change semantics of const volatile variables "drepper at redhat dot com" <gcc-bugzilla@gcc.gnu.org> writes: | __attribute((section(".rodata.cst8"))). This will cause gcc to fail with an | ICE. That is compiler bug. That is useful piece of data. I believe the PR should be retitled and reclassified based on that. -- Gaby
*** Bug 51085 has been marked as a duplicate of this bug. ***
Confirmed.
So I am being bitten by this in the BPF backend [1]. Long story short: LLVM places initialized `volatile const' variables in .rodata, whereas GCC puts them in .data. The kernel's libbpf scans the objects and generates a "skeleton" header that, among other things, reflects the sections in the compiled BPF object. This divergence in behavior between LLVM and GCC makes the skeleton to define different data structures, i.e. obj->rodata->foo vs. obj->data->foo. See [1] for details. I don't actually understand Gabriel's comment, "If it may be modified by hardware or other external means, it can't go into .rodata section.". Why not? The permissions of the .rodata section eventually determines the permissions used to map the corresponding pages in the particular process running the program, but I don't see how can prevent the same physical memory to be updated by hardware, or even other processes mapping the same physical page using write perms. Or what am I missing? Can we change the behavior of GCC to put such variables in .rodata? [1] https://lore.kernel.org/bpf/87fsj8vjcy.fsf@oracle.com/T/#me726127e166f97fd50f09b647a604f176f809c63
If, as a workaround, I try to use a `section' attribute, like in: __attribute__((section(".rodata"))) volatile const int lala = 0; I don't get an ICE, but a section with write permissions: .section .rodata,"aw" And the assembler then complains: foo-gcc.s:4: Warning: setting incorrect section attributes for .rodata
After a little discussion in IRC I filed this LLVM bug: https://github.com/llvm/llvm-project/issues/56468 Regarding the ICE described by Ulrich, I cannot reproduce it using: bpf-unknown-none-gcc (GCC) 13.0.0 20220708 (experimental) Maybe it is time to close this bug?
So I got feedback from the clang/llvm folks on this. As you can see in [1] they asked the WG14 reflectors about the footnote 135 in the C18 spec and their conclusion is that there is no normative objection to place `const volatile' variables in read-only sections, much like non-volatile consts. This matches my earlier impression (before I got pointed to that footnote) and since there is at least one target being impacted by this GCC/LLVM discrepancy (bpf-unknown-none) I intend to prepare a patch to change the place where GCC places the `const volatiles'. [1] https://github.com/llvm/llvm-project/issues/56468
The master branch has been updated by Jose E. Marchesi <jemarch@gcc.gnu.org>: https://gcc.gnu.org/g:a0aafbc324aa90421f0ce99c6f5bbf64ed163da6 commit r13-2952-ga0aafbc324aa90421f0ce99c6f5bbf64ed163da6 Author: Jose E. Marchesi <jose.marchesi@oracle.com> Date: Thu Aug 4 21:16:10 2022 +0200 place `const volatile' objects in read-only sections It is common for C BPF programs to use variables that are implicitly set by the BPF loader and run-time. It is also necessary for these variables to be stored in read-only storage so the BPF verifier recognizes them as such. This leads to declarations using both `const' and `volatile' qualifiers, like this: const volatile unsigned char is_allow_list = 0; Where `volatile' is used to avoid the compiler to optimize out the variable, or turn it into a constant, and `const' to make sure it is placed in .rodata. Now, it happens that: - GCC places `const volatile' objects in the .data section, under the assumption that `volatile' somehow voids the `const'. - LLVM places `const volatile' objects in .rodata, under the assumption that `volatile' is orthogonal to `const'. So there is a divergence, that has practical consequences: it makes BPF programs compiled with GCC to not work properly. When looking into this, I found this bugzilla: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25521 "change semantics of const volatile variables" which was filed back in 2005, long ago. This report was already asking to put `const volatile' objects in .rodata, questioning the current behavior. While discussing this in the #gcc IRC channel I was pointed out to the following excerpt from the C18 spec: 6.7.3 Type qualifiers / 5 The properties associated with qualified types are meaningful only for expressions that are lval-values [note 135] 135) The implementation may place a const object that is not volatile in a read-only region of storage. Moreover, the implementation need not allocate storage for such an object if its $ address is never used. This footnote may be interpreted as if const objects that are volatile shouldn't be put in read-only storage. Even if I personally was not very convinced of that interpretation (see my earlier comment in BZ 25521) I filed the following issue in the LLVM tracker in order to discuss the matter: https://github.com/llvm/llvm-project/issues/56468 As you can see, Aaron Ballman, one of the LLVM hackers, asked the WG14 reflectors about this. He reported that the reflectors don't think footnote 135 has any normative value. So, not having a normative mandate on either direction, there are two options: a) To change GCC to place `const volatile' objects in .rodata instead of .data. b) To change LLVM to place `const volatile' objects in .data instead of .rodata. Considering that: - One target (bpf-unknown-none) breaks with the current GCC behavior. - No target/platform relies on the GCC behavior, that we know. - Changing the LLVM behavior at this point would be very severely traumatic for the BPF people and their users. I think the right thing to do at this point is a). Therefore this patch. Regtested in x86_64-linux-gnu and bpf-unknown-none. No regressions observed. gcc/ChangeLog: PR middle-end/25521 * varasm.cc (categorize_decl_for_section): Place `const volatile' objects in read-only sections. (default_select_section): Likewise. gcc/testsuite/ChangeLog: PR middle-end/25521 * lib/target-supports.exp (check_effective_target_elf): Define. * gcc.dg/pr25521.c: New test.
Fixed in 13.
The master branch has been updated by Sam James <sjames@gcc.gnu.org>: https://gcc.gnu.org/g:0ac0e640a7f86ba45b7e13ed018826177197f3ce commit r15-2370-g0ac0e640a7f86ba45b7e13ed018826177197f3ce Author: Sam James <sam@gentoo.org> Date: Sat Jul 27 00:17:03 2024 +0100 testsuite: fix dg-do ordering wrt dg-require-* Per gccint, dg-do must precede dg-require-effective-target or dg-require-support. Fix a handful of deviant cases. gcc/testsuite/ChangeLog: PR middle-end/25521 PR debug/93122 * gcc.dg/pr25521.c: Fix dg-do directive order. * gcc.dg/vect/vect-simd-clone-19.c: Likewise. * gcc.target/arm/stack-protector-7.c: Likewise. * gcc.target/arm/stack-protector-8.c: Likewise. * gcc.target/powerpc/pr93122.c: Likewise. libstdc++-v3/ChangeLog: PR libstdc++/110572 * testsuite/18_support/type_info/110572.cc: Fix dg-do directive order.