Bug 78903 - __attribute__((section(".ram"))) ignored with -Os or -flto
Summary: __attribute__((section(".ram"))) ignored with -Os or -flto
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 6.2.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
Depends on:
Reported: 2016-12-22 14:21 UTC by chrysn
Modified: 2021-09-17 09:43 UTC (History)
1 user (show)

See Also:
Known to work:
Known to fail:
Last reconfirmed:

example for amd64 linux where a function in should-be-crashing .data is inlined into regular text (121 bytes, text/x-csrc)
2016-12-22 14:21 UTC, chrysn

Note You need to log in before you can comment on or make changes to this bug.
Description chrysn 2016-12-22 14:21:30 UTC
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.
Comment 1 Jakub Jelinek 2016-12-22 14:48:28 UTC
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).
Comment 2 chrysn 2016-12-22 15:38:14 UTC
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."
Comment 3 Andrew Pinski 2021-09-17 09:43:23 UTC
As mentioned section does not block inlining.  So this is exacted.  You need to use noinline or noipa to get that effect.