Description of problem: gcc 10.2 generates code that segfaults due to placing global const pointers in read-only memory area rather than read-write as previous compilers Version-Release number of selected component (if applicable): gcc (GCC) 10.2.1 20200723 (Red Hat 10.2.1-1) How reproducible: Compile program with a global const pointer prototype to be initialized later. Additional info: Here is the simplest program I could come up with to demonstrate the problem. I call the program "maptest.c" because I'm looking at where things get mapped to memory by looking in /proc/<pid>/maps and seeing what permissions each chunk of memory has and where it is located. Using the debugger I can tell where in that memory space my variables are located. Here's the program: /* A program to try and find where a SIGSEV error occurs as * part of the program DOSEMU */ # include <stdio.h> # include <stdlib.h> char * const lowmem_base; int main(int argc, char **argv) { void *addr = malloc(114112); *(char **)(&lowmem_base) = addr; printf("Hello World!\n"); free(addr); } I could probably delete the Hello World! to make it even smaller but it's an experiment. When I compile this with gcc like this: $ gcc -g -Wall -o maptest maptest.c I get an ELF executable called "maptest" with debug information as expected. When I compile the program with gcc version 9.1.2 as found in Fedora 31, the programs runs and exits normally. Running in the debugger shows that the variable lowmem_base is located in a portion of the maptest space that is marked rw-p. Activating the disassembler in gdb shows that the value of addr is in a register and moves to the memory location of lowmem_base. When I compile the program with gcc version 10.2.1 as found in Fedora 32, the program runs and segfaults on the line: *(char **)(&lowmem_base) = addr; Running in the debugger shows that the variable lowmem_base is located in a region of maptest marked as read only. If I copy the binary from Feodra 31 to Fedora 32 it runs fine so I don't think it has anything to do with any of the shared libraries. The equivalent of this program has been working since before 2012, so I think that there is a problem with gcc. If I compile the program with clang, it functions as expected without a segfault.
The testcase is invalid. See e.g. ISO C99, 6.7.3/5: "If an attempt is made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type, the behavior is undefined." The only reason this "worked" before GCC 10 is that older GCC versions defaulted for C to -fcommon and as the variable has no initializer, it has been a common symbol which is always writable. If you compile this testcase with -fno-common, even GCC 9 or 8 will segfault on it. If you compile with C++, it will not even compile. You can use various workarounds, like -fcommon, or add __attribute__((common)) to the var, but the right fix is to drop the const qualifier if you want to modify the variable.