Some time ago I wrote about using
--gc-sections to avoid unused functions to creep into final code. Today instead I’d like to show how that can be quite a problem if it was used indiscriminately.
I’m still using at least for some projects the diagnostic of
--gc-sections to identify stuff that is unused but still kept around. Today I noticed one bad thing with it and pulseaudio:
/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.2/../../../../x86_64-pc-linux-gnu/bin/ld: Removing unused section '.data.__padsp_disabled__' in file 'pulseaudio-main.o'
__padsp_disabled__ symbol is declared in
main.c to avoid pulseaudio’s access to OSS devices to be wrapped around by the
padsp script. When I first have seen this, I thought the problem was a missing
#ifdef directive: if I didn’t ask for the wrapper, it might still have declared the (unused) symbol. That was not the case.
Looking at the code, I found what the problem was: the symbol is (obviously) never used by pulseaudio itself; it is, rather, checked through
dlsym() by the DSP wrapper library. For this reason, for compiler and linker, the symbol looks pretty much unused, and when asking for it to be dropped explicitly, it is. Since the symbol is loaded via the runtime linker, neither building nor executing pulseaudio will have any problem. And indeed, the only problem would be when running pulseaudio as a children of
padsp, and using the OSS output module (so not on most Linux systems).
This shows how just using
-fdata-sections -ffunction-sections -Wl,--gc-sections is not safe at all and why you shouldn’t get excited about GCC and ld optimisations without understanding how they work in detail.
In particular, even I thought that it would be easier to work around than it actually seem to be: while GCC provides a
used attribute that allows to declare a variable (or a function) as used even though the compiler can’t tell that by itself (it’s often used together with inline hand-written ASM the compiler doesn’t check for), this does not propagate to the linker, so it won’t save the section from being emitted. The only solution I can think of is adding one instruction that sets the variable to itself, but that’s probably going to be optimised away. Or giving a way for gcc to explicit that the section is used.