问题
Why is there a compiler error when attempting to place two (RAM) variables, which only differ by their initialisation values, into the same section?
Problem
The C source:
int __attribute__((section(".in_my_data"))) _foo = 1;
int __attribute__((section(".in_my_data"))) _bar = 0;
The (relevant) GCC compiler output:
mcve/main.c:75:45: error: _bar causes a section type conflict
The linker script contains the following line in the SECTIONS
definition, but the (fatal) error is from the compiler, not the linker.
.my_data : { *(.in_my_data) } > data
Further Information
Changing the C source to permit the compiler to use two sections allows the compile to pass, but the linker then generates an error if the two input sections are mapped into the same output section.
The C source:
int __attribute__((section(".in_my_data_nonzero"))) _foo = 1;
int __attribute__((section(".in_my_data_zero"))) _bar = 0;
The linker script:
.my_data : { *(.in_my_data*) } > data
The (relevant) linker output:
Link Error: attributes for input section '.in_my_data_nonzero' conflict
with output section '.my_data'
Swapping the order of the lines in the C source only changes which section (the second to appear in the C source) is in error.
Question
What attribute(s) does the GCC compiler require of a section for a variable that is initialised with zero that it doesn't for one that is initialised with non-zero, or vice versa?
Is the compiler trying to place the variables that are initialised to zero in the .bss
section, rather than the .data
section for initialised data? Or is there another section for data that is initialised to zero?
Related questions
Similar questions appear cover issues with conflicts between memory types (ROM vs. RAM):
- "Section type conflict" in arm embedded, what is it?
- How do I resolve a "section type conflict" compile error and best practices for using section attribute with gcc
- Getting a "section type conflict" using M2tklib and glcd
... or putting initialised const
data in NOLOAD output sections:
- "Section type conflict" due to macro definition in GCC 4.8.2
... or remain a mystery as to the cause and may be related:
- Section type conflict for identically defined variables
None of the above appear to have an answer that I can apply to issue in this question, as far as I can tell.
回答1:
Caveat: This answer may only apply to the Microchip XC16 compiler.
Research
The compiler assigns attributes to C variables so that they are allocated to specific sections as follows (see Note 1 below for XC16 specific information).
int a = 1;
- is assigned to.data
.int b = 0;
- is assigned to.bss
.int c;
- is assigned to.bss
.
The first and last of these make sense: .data
is used for initialised data and .bss
is used for uninitialised data. However, .bss
data is also set to zero by the ANSI C start up (see Note 2).
Answer
It would appear that the compiler is including variables that are initialised, but with a value that equates to all bits 0 in the .bss
section as well as all those which are not initialised at all.
According to wikipedia:
An implementation may also assign statically-allocated variables and constants initialized with a value consisting solely of zero-valued bits to the BSS section.
Workaround
GCC has an option -fno-zero-initialized-in-bss
which can be used to force all variables that are initialised with zero into the .data
section, as stated in this answer. This can be applied on a per-source file basis, but not on individual variables.
Wishful Thinking
It would be nice if there were an __attribute__((**doload**))
that could be applied to force the compiler to place a zero-initialised variable in .data
instead of .bss
.
Notes
Note 1: The XC16 compiler may use .ndata
and .nbss
to indicate near data below address 0x8000.
Note 2: Marking a variable with __attribute__((noload))
will result in the variable being excluded from the .bss
section. XC16 generates a specific output section, with a (GUID?) unique name for each variable marked as such.
回答2:
By default, GCC places classes of objects in different sections, executable code goes to .text, initialized data to .data, static data to .bss, and some more obscure ones.
If you try to force two objects of different class to belong to the same section, GCC will raise this section error.
The solution is to place them in different sections, and finally, tell the linker to ultimately coalesce these objects in the same section, for example:
.boot : { // target ELF section will contain....
*(.boot) // executable code
*(.boot_rodata) // constant data
*(.boot_bss) // static data
} > BOOT // to finally be place in this area
来源:https://stackoverflow.com/questions/30076949/gcc-error-variable-causes-a-section-type-conflict