I'm compiling a code for an embedded ARM microcontroller and I'm trying to optimize the binary size. I'm using arm-none-eabi-g++
with options -Os -ffunction-sections -fdata-sections -Wl,--gc-sections
in order to achieve this. It looks like this removes some (but not all) unused functions, especially some heavy one.
arm-none-eabi-nm --print-size --size-sort --radix=d
gives me :
[...]
00008412 00000084 T _raise_r
00004888 00000088 t restore_non_core_regs
00000172 00000092 t _ZN5USART5writeENS_4PortEc.constprop.22
00005276 00000094 T __gnu_Unwind_RaiseException
00001644 00000094 t _ZN4GPIO16enablePeripheralERKNS_3PinE
536871016 00000096 d impure_data
00004592 00000096 t search_EIT_table
00000624 00000100 t _ZN5Flash9writePageEiPh
00005648 00000112 T __gnu_Unwind_Backtrace
536874336 00000128 b _ZN3USB8_bankEP0E
00000264 00000128 t _ZN5USART9availableENS_4PortE.constprop.20
00002500 00000140 t _Z17usbControlHandlerRN3USB11SetupPacketEPhRi
00004728 00000160 t get_eit_entry
00000464 00000160 t _ZN3USB15ep0SETUPHandlerEv
00005060 00000212 t unwind_phase2_forced
536871424 00000256 b _ZN3USB17_epRAMDescriptorsE
536871688 00000384 b _ZN3USB10_endpointsE
536874496 00000384 b _ZN4Core9isrVectorE
00001972 00000528 t _ZN3USB12ep0INHandlerEv
00006504 00000590 T _Unwind_VRS_Pop
00007612 00000674 T __gnu_unwind_execute
00005760 00000732 t __gnu_unwind_pr_common
00000752 00000892 t _ZN3USB16interruptHandlerEv
00002640 00001848 T main
536872096 00002144 b _ZN5USART5portsE
As you can see, there are quite a lot of room taken by "unwind" functions. These seem to be related to C++ exceptions, but I'm not using them. I looked at the ELF with objdump -d
and it looks like no "unwind" function is called from any of my functions, so this would be effectively dead code.
Is there a way to remove it from the ELF? Or are they mandatory for some reason? I could save at least 1/4 of the total binary size.
So the linker is able to remove each individual function because it is in its own section. So enabling this for your library will allow the linker to remove unused functions from the library.
No: for unused globally available functions. The compiler doesn't know if some other compilation unit references it. Also, most object module types do not allow functions to be removed after compilation and also do not provide a way for the linker to tell if there exist internal references.
One approach is to use "Find All References" context menu item on class and function names. If a class/function is only referenced in itself, it is almost certainly dead code. Another approach, based on the same idea, is to remove(comment out) files/functions from project and see what error messages you will get.
--gc-sections decides which input sections are used by examining symbols and relocations. The section containing the entry symbol and all sections containing symbols undefined on the command-line will be kept, as will sections containing symbols referenced by dynamic objects.
Thanks to @DarkFalcon, @gudok and @jaggedSpire for the answer : the solution was to add -fno-exceptions
to remove all unwind-related functions. Now all the code still added in the binary is effectively used.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With