I have been running recently into an interesting case where the GNU ARM Linker failed to link an application with strange error messages:
The problem has been reported in a forum, and the error description triggered my interest as it was first around using sprintf(), and I knew that I had seen some issues in case the GNU compiler and linker is replacing some of the calls with more optimized ones.
The user of that forum post was so kind to send me that project, so I had a chance to look into it. The error message from the GNU linker ld was something like this:
`_sbrk' referenced in section `.text._sbrk_r' of arm-none-eabi/lib/armv7e-m/fpu\libg_s.a(lib_a-sbrkr.o): defined in discarded section `.text' of ./utilities/fsl_sbrk.o (symbol from plugin) `errno' referenced in section `.text._sbrk_r' of arm-none-eabi/lib/armv7e-m/fpu\libg_s.a(lib_a-sbrkr.o): defined in discarded section `.text' of ./middleware/lwip_2.0.0/port/sys_arch.o (symbol from plugin) collect2.exe: error: ld returned 1 exit status
Well, that error message is really weird, and seemed to happen only in some cases. But I did remember that I have seen something like this when I worked on a FreeRTOS application with the -flto (Link Time Optimization) turned on. And indeed, that application had that option turned on in the project settings:
Turning that option off proved that the problem is related to that option. So basically the error message is “I’m sorry, I have removed that symbol and marked it as discarded, but somehow the application code is still using it”. In essence, the linker has removed an object, but it was wrong as that object is still needed :-(.
It seems to me that the -flto linker optimization is more likely to fail in this area if a function or variable is marked as ‘weak’ (e.g. interrupt vectors or routines) or variables which are multiple times defined. This was the case here with _sbrk() overloaded and with the variable ‘error’ defined again in the lwip stack (well, that’s an issue of lwip).
Anyway, to work around the problem, I did the same what I did in other cases like this: adding the attribute ‘used’ to the functions or variables to prevent removal.
To prevent removing a function, add the following to the function definition:
__attribute__ ((noinline, used))
To prevent removing a variable by the -flto option in the linker, add the following:
I hope others facing that same problem might be able to find this article :-).
Happy discarding 🙂