In a bootloader I have a version string that is not explicitly used, but must be present at a specific location in ROM for access by the application loaded by said bootloader. In a source file version.cpp I have:
// Place version string at end of bootrom less 16 bytes
#define VERSION_STRING "090600.01.00.00"
#define MAX_VERSION_STRING_LENGTH 0x10
const char bootmainVersionString[MAX_VERSION_STRING_LENGTH] __attribute__((used)) = VERSION_STRING ;
And the location is achieved via the scatter file:
LR_VERSION_IROM1 0x08001FF0 0x00000010
{
VERSION_IROM1 0x08001FF0 0x00000010
{
version.o (+RO)
}
}
This may seem rather convoluted but previous methods valid in armcc v5 are no longer supported in the LLVM/Clang based v6.
However, while the __attribute__((used))
prevents the unused object being removed normally, the linker removes it when LTO (Link-time Optimisation) is enabled. Since I am trying to keep the bootrom inside 8Kb in this case, LTO is otherwise useful.
I get a linker warning:
.\bootrom.sct(21): warning: L6314W: No section matches pattern version.o(RO).
so VERSION_IROM1
is empty, whereas without LTO enabled it is located as required, but not using adds ~560 bytes to the image size in this case.
Toolchain details:
Toolchain: MDK-ARM Plus Version: 5.36.0.0
C Compiler: ArmClang.exe V6.16
Linker/Locator: ArmLink.exe V6.16
Is there a means of preventing LTO from removing this object file?
I have tried using a volatile
qualifier, and including a dummy reference in the code, to no avail.
Further I have tried the linker option --keep=bootmainVersionString
, but that does not work either with LTO enabled, and has no effect otherwise that __attribute__((used))
does not achieve.
However I have noticed that the object is present in the link, but not located per the scatter file. In the map file I have:
Without LTO (located as intended):
bootmainVersionString 0x08001ff0 Data 16 version.o(.rodata.bootmainVersionString)
with LTO (located by the linker):
bootmainVersionString 0x0800130c Data 16 lto-llvm-dbc16f.o(.rodata)
I have been unable to solve this problem using linker directives - LTO defeating it at every turn. However I have devised a work-around that has the advantage or being tool-chain independent by not relying at all on tool-chain specific linker directives or linker specific script syntax.
My solution is:
srec_cat buildinfo -binary -fill 0x00 0x000 0x100 -o buildinfo.hex -Intel
srec_cat final.hex -Intel buildinfo.hex -Intel -offset %BUILD_INFO_ADDR% -o application.hex -Intel
The disadvantage of this perhaps, is that when the toolchain compiled/linked object code is loaded by the debugger, the located data is of course not included, and it is possible even to have data present from a previous build if the associated flash page did not need to be erased when the object code is loaded.