I'm trying to force a global variable to a specific address without modifying the source code. I'm well aware of solution such as:
// C source code
MyStruct globalVariable __attribute__((section(".myLinkerSection")));
// Linker script
. = 0x400000;
.myLinkerSection:
{
*(.myLinkerSection)
}
But in my case I would like to do the same thing without the __attribute__((section(".myLinkerSection")))
keyword.
Is it doable ?
EDIT: I cannot modify the source code at all. The variable is defined as follow:
file.h:
extern MyStruct globalVariable;
file.c:
MyStruct globalVariable;
CodePudding user response:
I assume from the mentions of __attribute__
that you are using gcc / clang or something compatible. You can use the -fdata-sections
option to make the compiler put every variable into its own section. With that option, your globalVariable
, assuming it would otherwise go in .bss
, will be placed in a section called .bss.globalVariable
(the exact name might be platform-dependent). Then you can use your linker script to place this section at the desired address.
Note that this option will inhibit certain compiler optimizations. There is a guarantee that objects defined in the same section within the same assembler module are assembled in strict order, and that their addresses do not change after that. In some cases the compiler can take advantage of this; e.g. if it defines int
variables foo
and bar
consecutively in the same section, then it knows their addresses are consecutive, and it can safely generate code that "hardcodes" their relative position. For instance, on some platforms such as ARM64, it takes multiple instructions to materialize the address of a global or static object. So if some function accesses both foo
and bar
, the compiler can materialize the address of foo
, then add the fixed constant 4 to get the address of bar
. But if foo
and bar
are in different sections, this can't be done, and you will pay the (small but nonzero) cost of materializing both addresses separately.
As such, you may want to use -fdata-sections
only on the particular source files that define the particular variables of concern.
This also illustrates why you have to get the variable in its own section in order to set its address; you can't move just one variable from a section, since the compiler may have been relying on its relative position to some other variable in that section.
CodePudding user response:
You can define this variable in a separate translation unit. Then list its object file in the appropriate section.