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)