Hi all,
I am trying to use the weak attribute for global initialized variable. It works for a function I am also trying to re-implement, but fail to do so for variable. I am trying to do it for quite common scenario: I have layered structure to support applications and bootloader. Certain startup code and vector table I would like to re-implement (simplify) for bootloader. I am working only with object files (dropped using archives because of other linker limitations) so at the end the linker links together a lot of object files (the object files with strong symbols in bootloader case are listed first).
My implementation works without any issue with ARMClang v6.10.1 but has issues with both ARMCC and GCC (see versions below).
Code file1.c:
vect_table_ptr __attribute__((weak)) g_vect_table[] __attribute__((section("vect_table"))) = ...
file2.c:
vect_table_ptr g_vect_table[] __attribute__((section("vect_table"))) = ...
Note for ARMCC I tried also with __weak and putting both attributes to the same call (joined with section). To be sure the symbols are global I also added extern declaration into the header but it didn't help.
So what happens when I try to compile is I get two instances of this symbol:
- armlink complains it has multiple matches for this section and cannot all be FIRST/LAST (as vector table is) - it means it has two g_vect_table symbols
- GCC is even weirder: it links and just put both symbols in the section (so table from file1.c and after that table from file2.c).
If I check (GCC version) object files I get the following (I changed the object filenames for clarity):
[user@ws gcc_build ] arm-none-eabi-nm file1.c.o 00000002 T app_vect_table_size 00000000 T default_handler U drv_btmr_isr U drv_dma_isr U drv_spim_isr 00000000 V g_vect_table U __main U _stack_base [user@ws gcc_build ] arm-none-eabi-nm file2.c.o U default_handler U drv_dma_isr U drv_spim_isr 00000000 D g_vect_table U __main U _stack_base
It shows g_vect_table from file1.c.o is weak symbol (V) and the one from file2.c.o is initialized data section (D) - which to me it seems correct. But when linking it puts both symbols there.
Does anybody have any idea how to use these weak symbols in this specific case? Issue is that C standard is not well defined for this and it is up to compiler implementation how to handle it.
I have quite some experience with weak symbols and didn't have issues as such in the past but right now I am quite puzzled as there was no way I could make it work. I would like to keep the codebase compilable with all three compilers.
Compiler versions I am using are:
GCC version:
arm-none-eabi-gcc (GNU Tools for ARM Embedded Processors) 5.4.1 20160919 (release) [ARM/embedded-5-branch revision 240496]
ARMCC version:
Product: MDK Professional 5.25 (Flex)Component: ARM Compiler 5.06 update 6 for Certification (build 750)
Thanks for any comments or ideas and best regards,
Jure Menart
Adding +FIRST didn't give me an error with either compiler. I should also note that I'm using MDK 5.29, ARMCC 5.06 update 6 build 750 and ARMCLANG 6.13.1.
vect_table 0x20007800 0x00000800 { .ANY (vect_table,+FIRST) }
Can you post your original and latest scatter files? That could be useful to others who have a similar issue.
Hi Adam,
The start of my scatter is attached below.
I came to 'real answer' actually why I had issues - as you can see below I am using *.o for input file selection instead of .ANY (I came to this because I wanted to strictly describe which file has the content and then I changed architecture and allowed multiple files - but instead of .ANY I just changed to *.o. So if I add .ANY and use +First it is also working.
This now explains why multiple symbols were discovered - as the linker was indeed working on separate object files and not on the result of the linking!
Great finding, good school for me and hopefully also for others. It is also interesting to see different behavior between ARMCCv5 and ARMClangv6 in this respect.
Original scatter file (with +First removed in VECT_TABLE load region - if it was added I had the issue):
LR_BOOT 0x00000000 0x0E00 { VECT_TABLE 0x00000000 { *.o (vect_table) } FW_HEADER +0 { *.o (fw_header) } EXEC_BOOT +0 { .ANY (RESET +RO) } RAM 0x20000000 UNINIT { .ANY (+RW, +ZI) } ...