Hi,

I'm a firmware/embedded engineer and frequently run into cases where
certain parts of the code need to be placed in a special memory area (for
example, because the area that contains the other code is not yet
initialized or currently inaccessible). My go-to method to solve this is to
mark all functions and globals used by this code with
__attribute__((section)), and using a linker script to map those special
sections to the desired area. This mostly works pretty well.

However, I just found an issue with this when the functions include local
variables like this:

  const int some_array[] = { 1, 2, 3, 4, 5, 6 };

In this case (and with -Os optimization), GCC seems to automatically
reserve some space in the .rodata section to place the array, and the
generated code accesses it there. Of course this breaks my use case if the
generic .rodata section is inaccessible while that function executes. I
have not found any way to work around this without either rewriting the
code to completely avoid those constructs, or manipulating sections
manually at the linker level (in particular, you can't just mark the array
itself with __attribute__((section)), since that attribute is not legal for
locals).

Is this intentional, and if so, does it make sense that it is? I can
understand that it may technically be compliant with the description of
__attribute__((section)) in the GCC manual -- but I think the use case I'm
trying to solve is one of the most common uses of that attribute, and it
seems to become completely impossible due to this. Wouldn't it make more
sense and be more useful if __attribute__((section)) meant "place
*everything* generated as part of this function source code into that
section"? Or at least offer some sort of other extension to be able to
control section placement for those special constants? (Note that GCC
usually seems to place constants for individual variables in the text
section, simply behind the epilogue of the function... so it's also quite
unclear to me why arrays get treated differently at all.)

Apart from this issue, this behavior also seems to "break"
-ffunction-sections/-fdata-sections. Even with both of those set, these
sorts of constants seem to get placed into the same big, common .rodata
section (as opposed to either .text.functionname or .rodata.functionname as
you'd expect). That means that they won't get collected when linking the
binary with --gc-sections and will bloat the code size for projects that
link a lot of code opportunistically and rely on --gc-sections to drop
everything that's not needed for the current configuration.

Is there some clever trick that I missed to work around this, or is this
really not possible with the current GCC? And if so, would you agree that
this is a valid problem that GCC should provide a solution for (in some
form or another)?

Thanks,
Julius

Reply via email to