Hi,
I'm using armclang compiler Product: Professional Component: ARM Compiler 6.16
There are unused functions which are linked in the final application. There functions are coming from a library which is linked to final application, but not called in application.
How to remove these unused functions from final image ?
ARM Linker does this automatically. You have to specify if you want to keep symbols/functions. Did you check the cross reference if there is no hidden usage?
The below are the options used for compilation,
armclang --target=arm-arm-none-eabi -mcpu=cortex-m7 -Wall -Wextra -Werror -Wno-error=unused-variable -Wno-error=unused-function -Wno-error=unused-parameter -fdiagnostics-absolute-paths -Wno-unused-command-line-argument -Wno-error=unused-private-field -mcpu=cortex-m7 --target=arm-arm-none-eabi -mno-unaligned-access -fno-builtin -c -O3 -fno-fine-grained-bitfield-accesses -o main.o -c main.c
armlink --scatter=test.sct --map --callgraph --datacompressor=off --no_remove --entry=Reset_Handler --symbols --no_scanlib main.o out/bin/main.axf --list=out/bin/main.map
Hello,
The linker has --no_remove specified, which disables this feature.
https://developer.arm.com/documentation/102284/6-16-2LTS/armlink-Reference/Linker-Optimization-Features/Elimination-of-unused-sections
I recommend also adding --info unused to the linker command line.
Tried removing --no_remove from linker options but no change in final image, still it conatins unused functions.
Tried lisiting --info unused in linker options, but no prints of removing unused code.
The smallest entity that can be removed is an ELF section. Are these unused functions in the same section as a used function?
The fromelf (with -c) utility can help you decipher this if you are unsure.
It shows there are 13 sections using fromelf -c. This includes code section, data rw, stack,
Is the "unused" code in the same section as "used" code? If so, then the linker cannot remove it.
By removing the option --no_remove from linker, the unused functions are removed, however it removed some used functios also.
How to prevent this from happening ? Is this a compiler bug ?
It would not be possible for the linker to remove used code, as that would cause the link step to fail.
Used code is any code that has a call chain growing from a defined ENTRY point. Try reviewing a callgraph.https://developer.arm.com/documentation/102284/6-16-2LTS/armlink-Reference/armlink-Command-line-Options/--callgraph----no-callgraph
I'm not clear on this statement,
"unused" code in the same section as "used" code? "
In scatter file only one section for .text for .RO and XO. Are you referring to different section creation in scatter file ?
I am referring to an ELF (the format of Arm objects and images) section.
By removing --no_remove from linker, the function
void __stack_chk_fail(void) got removed.
This function is called by compiler upon stack overflow check, so there is no call in the application explicitly.
How to prevent these functions getting removed, also exceptions, interrupt service routines won't have any callgrah.
Hi Benny
Use --keep <object containing this function> on the linker command line.
https://developer.arm.com/documentation/102284/6-16-2LTS/armlink-Reference/Image-Structure-and-Generation/The-structure-of-an-Arm-ELF-image/Image-entry-points
Ronan
Hi Ronan,
This seems to be tedious, for example if a file foo.o contains functions which are called and some are unused. Specifying each, of these to keep is cumbersome. Is there a better way to remove the unused functions while keeping the ones which are required like compiler calling functions like __stack_chck_fail().
Also after using --keep=foo_*.o it is showing so many 8 bytes removed, though they are being called from caller functions. .ARM.exidx.text.foo_test ), (8 bytes). What is this .exidx sections ?
Is it removing the functions or some data, it seems only 8 bytes.
Removing foo_test.o(.ARM.exidx.text.foo_test_init), (8 bytes).Removing foo_test.o(.ARM.exidx.text.foo_test_getHandle), (8 bytes).Removing foo_test.o(.ARM.exidx.text.foo_test_setType0), (8 bytes).Removing foo_test.o(.ARM.exidx.text.foo_test_SetupType0In), (8 bytes).Removing foo_test.o(.ARM.exidx.text.foo_test_cfgPort), (8 bytes).Removing foo_test.o(.ARM.exidx.text.foo_test_StatusCmd), (8 bytes).Removing foo_test.o(.ARM.exidx.text.foo_test_cfgTimerCtrl), (8 bytes).Removing foo_test.o(.ARM.exidx.text.foo_test_SetLm), (8 bytes).Removing foo_test.o(.ARM.exidx.text.foo_test_cfgP0Ctrl), (8 bytes).
I am not aware of another solution.