3

I'm writing some code that's going to be used on an embedded device so I want to keep the code size down by having the linker discard some of the third-party library functions I'm not using. I've tried using the -ffunction-sections and -fdata-sections options along with -Wl,--gc-sections but unused functions remain.

Here's an example I've built with MinGW:

#include <iostream>
using namespace std;

double unused_function(int a, int b)
{
    double r;

    r = (double)a + (1.0/ (double)b);

    return r;
}

double used_function(int a, int b)
{
    double r;

    r = (double)a + (1.0/ (double)b);
    cout << r << "is the value" << endl;

    return r;
}

int main() {
    cout << "!!!Hello World!!!" << endl;

    used_function(4,5);
    return 0;
}

Here's the command line output:

g++ -O1 -ffunction-sections -fdata-sections -g -Wall -c -fmessage-length=0 -o "src\\test.o" "..\\src\\test.cpp" 
g++ -Wl,--gc-sections,-Map=output.map,--print-gc-sections -o test.exe "src\\test.o" 
size --format=berkeley test.exe 
   text    data     bss     dec     hex filename
  36424    2476    2608   41508    a224 test.exe

Now if I comment out unused_function() entirely and rebuild, the size command reports this:

text    data     bss     dec     hex filename
36388    2476    2608   41472    a200 test.exe

I would have expected that the unused function would have been discarded and thus the text size would remain the same but that's obviously not the case. Is there a command line option I'm missing or is this part of my own ignorance about how GCC works internally?

This is just an example to demonstrate my problem. I'm using some third party libraries for various functions and my goal is to ensure that parts of the libraries I don't use are removed from the code.

CodingHero
  • 181
  • 13
  • 1
    They are not removed on the compilation stage as it is not known whether or not they are used. And on the linking stage you don't have any optimization defined. – Eugene Sh. Jan 05 '16 at 19:08
  • I understand why the compilation stage doesn't remove them. What other linker options should I be looking at? – CodingHero Jan 05 '16 at 19:10
  • 1
    I tested this on Linux - gcc correctly removes unused section. Did you try objdump to verify that the section was indeed there? Size is not very relevant. – SergeyA Jan 05 '16 at 19:11
  • 1
    @EugeneSh., OP's setting are correct as to remove unusing sections. – SergeyA Jan 05 '16 at 19:11
  • 1
    @YSC Thanks for the suggestion. I can see that `static` makes the problem go away but if I'm including third party libraries I don't want have to go in them and make everything static. Should I just be sure to shove any libraries I use into a namespace? – CodingHero Jan 05 '16 at 19:13
  • @CodingHero, static does a very different thing. It makes the function to be excluded at compilation step. It will not work with external libraries. – SergeyA Jan 05 '16 at 19:14
  • Looks like a common problem over google. People are blaming the specific linker.. – Eugene Sh. Jan 05 '16 at 19:16
  • 1
    @CodingHero See also http://stackoverflow.com/questions/12449387/bloated-exe-sizes-and-unwanted-dependencies-with-qt-mingw , it seems mingw currently doesn't support this (though there's a patch) – nos Jan 05 '16 at 19:17
  • I suspect this is just a limitation of binutils' poor Windows/PE support. If your final target is embedded and non-Windows, don't worry. Everything should work fine when you move to building for the actual target. – R.. GitHub STOP HELPING ICE Jan 05 '16 at 19:18
  • @SergeyA I missed the last sentence. But I think it was only irrelevant, not *very*. – YSC Jan 05 '16 at 19:18
  • @nos Thanks for the link. – CodingHero Jan 05 '16 at 19:19
  • @SergeyA I didn't know that the `size` utility didn't necessarily reflect what is/isn't in the binary. I'll have to do some more reading about it. – CodingHero Jan 05 '16 at 19:20
  • @CodingHero, it does display the size. But the size can vary based on multitude factors and as a rule is not something to verify when you want to know if particular symbol exists. However, looks the problem reported by you is due to the bug in MinGW toolchain, so my observation is not relevant. – SergeyA Jan 05 '16 at 19:22
  • @SergeyA While it may not be relevant to this particular question, it's still good information for future reference. – CodingHero Jan 05 '16 at 19:25
  • This is why good libraries tend to have a single function per source file. At least if linking statically, that makes the right thing happen (at least on any *nix I've tried).) Dynamic libraries are a whole other story. And if you link the library as a set of .o's (as above) rather than a library archive (.a), you defeat this. (But I know nothing about windows, or its library format; this may be irrelevant there.) – Arlie Stephens Jan 05 '16 at 19:48
  • 2
    Have you tried compiling/linking with -Os (optimize for size)? – Ken P Jan 05 '16 at 21:00

1 Answers1

0

The unused functions might be needed by a library that will be linked later. An example would be a memory allocation interface exposed by a lib that doesn't want to limit how the user manages memory.

We expect the linker to remove these during an optimization step (although I have run into related issues where the linker was not able to remove all remnants of such calls)

tletnes
  • 1,958
  • 10
  • 30
  • I understand why the _compiler_ would leave functions in, but not why the linker does. In the case of the example, there are no other libraries and the functions were still not removed. Based on above comments, in this particular case it is a bug in MinGW. – CodingHero Jan 06 '16 at 13:03
  • Well thats what I get for skimming questions when I'm almost asleep. – tletnes Jan 06 '16 at 14:53