Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GCC error "<variable> causes a section type conflict"

Tags:

c

gcc

xc16

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.

like image 843
Evil Dog Pie Avatar asked May 06 '15 12:05

Evil Dog Pie


2 Answers

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
like image 163
Hendrik Beijeman Avatar answered Nov 04 '22 21:11

Hendrik Beijeman


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.

like image 32
Evil Dog Pie Avatar answered Nov 04 '22 19:11

Evil Dog Pie