Created attachment 40400 [details]
example for amd64 linux where a function in should-be-crashing .data is inlined into regular text
When function calls are inlined due to -Os or -flto, an __attribute__((section(".ram"))) gets ignored.
This bites for example when GCC somewhere before 5.4 started inlining flash writing sequences on ARM CortexM3 EFM32 chips in emlib where such an attribute should have made sure that the flash is not accessed for program code during the flash operation; there, it surfaced due to link time optimization.
I've created a minimal test case that seems equivalent to me, it is attached as test.c. Instead of moving code to RAM like in the original but harder-to-reproduce example on ARM, it is placing a test function `f()` in ".data", which on my system makes the program segfault when the f is invoked.
When compiled without optimizations ("gcc-7 test.c -o test"), the resulting program crashes as expected, probably trying to execute ".data" and running into protections. In the original microcontroller example, that crash would have been a successful execution from RAM.
With "gcc-7 -Os test.c -o test", the call to `f()` is inlined and the program exits successfully. In the original example, this would have a concurrent access to flash and would have caused some undefined state in the processor.
In both cases, the compiler outputs "Warning: ignoring changed section attributes for .data"; there is no equivalent output in the original ARM example as ".ram" is a valid section there in the linker script.
My build system is Debian sid on amd64 running linux 4.9.0-rc8. The behavior was obsered on arm-none-eabi-gcc 5.4, and on "regular" (amd64 debian built) gcc 6.2.1-7 and 7-20161217-1.
As a workaround, I'm currently marking the function __attribute__((noinline)). I might be having a "x-y problem" with the compiler here as my main intention is "keep your $pc off flash until this call returns" but I tell it "copy this to ram" and thus need to enhance the instructions to "and don't place copies anywhere else" and would appreciate suggestions on how to do it better, but __attribute__((section(".ram"))) seems to be the accepted way of doing it. A short inquery on freenode/#gcc indicated that this might be an optimizer bug.
noinline is not a workaround; if you don't want some function to be inlined, use noinline attribute, period. The section attribute itself is not a reason not to inline (and should not be).
I don't care about the function being inlined in general, I just don't want it inlined into different sections -- that's why I'd consider noinline a workaround.
Anyhow, if that is the definite answer, I'd like to suggest the following addition to the common-function-attributes documentation on section:
"[ of the linker instead.] The section applies when the function is placed as a whole; it can still be inlined into code in other sections."
As mentioned section does not block inlining. So this is exacted. You need to use noinline or noipa to get that effect.